diff --git a/.github/workflows/macos-check.yml b/.github/workflows/macos-check.yml new file mode 100644 index 000000000..465add45b --- /dev/null +++ b/.github/workflows/macos-check.yml @@ -0,0 +1,28 @@ +name: macOS Build Test + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: brew + run: brew install automake libtool + - name: autogen + run: ./autogen.sh + - name: configure + run: ./configure + - name: make + run: make + - name: make check + run: make check + - name: make distcheck + run: make distcheck + diff --git a/.github/workflows/ubuntu-check.yml b/.github/workflows/ubuntu-check.yml new file mode 100644 index 000000000..c851a5849 --- /dev/null +++ b/.github/workflows/ubuntu-check.yml @@ -0,0 +1,26 @@ +name: Ubuntu Build Test + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: autogen + run: ./autogen.sh + - name: configure + run: ./configure + - name: make + run: make + - name: make check + run: make check + - name: make distcheck + run: make distcheck + diff --git a/.github/workflows/windows-check.yml b/.github/workflows/windows-check.yml new file mode 100644 index 000000000..58d17fdeb --- /dev/null +++ b/.github/workflows/windows-check.yml @@ -0,0 +1,38 @@ +name: Windows Build Test + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: wolfssl64.sln + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + BUILD_CONFIGURATION: Release + BUILD_PLATFORM: x64 + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1 + + - name: Restore NuGet packages + working-directory: ${{env.GITHUB_WORKSPACE}} + run: nuget restore ${{env.SOLUTION_FILE_PATH}} + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} + diff --git a/.gitignore b/.gitignore index e4b39ed6e..53606474d 100644 --- a/.gitignore +++ b/.gitignore @@ -230,6 +230,7 @@ IDE/MDK-ARM/LPC43xx/LPC43xx/ *.gcno *.gcda *.gcov +*.dgcov !linuxkm/Makefile /Kbuild linuxkm/*.ko @@ -355,6 +356,12 @@ IDE/XCODE/Index /IDE/Renesas/e2studio/Projects/test/*.launch /IDE/Renesas/e2studio/Projects/test/*.scfg +# QNX CAAM +/IDE/QNX/example-server/server-tls +/IDE/QNX/example-client/client-tls +/IDE/QNX/example-cmac/cmac-test +/IDE/QNX/CAAM-DRIVER/wolfCrypt + # Emacs *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 65853b7cd..b9bfbc3c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") You must delete them, or cmake will refuse to work.") endif() -project(wolfssl VERSION 4.7.0 LANGUAGES C) +project(wolfssl VERSION 4.7.1 LANGUAGES C) # shared library versioning # increment if interfaces have been added, removed or changed @@ -180,9 +180,21 @@ find_package(Threads) # - 32-bit mode # - 16-bit mode +# For reproducible build, gate out from the build anything that might +# introduce semantically frivolous jitter, maximizing chance of +# identical object files. +set(WOLFSSL_REPRODUCIBLE_BUILD_HELP_STRING "Enable maximally reproducible build (default: disabled)") +add_option("WOLFSSL_REPRODUCIBLE_BUILD" ${WOLFSSL_REPRODUCIBLE_BUILD_HELP_STRING} "no" "yes;no") + +if(WOLFSSL_REPRODUCIBLE_BUILD) + set(CMAKE_C_ARCHIVE_CREATE " Dqc ") + set(CMAKE_C_ARCHIVE_APPEND " Dq ") + set(CMAKE_C_ARCHIVE_FINISH " -D ") +endif() + # Support for disabling all ASM set(WOLFSSL_ASM_HELP_STRING "Enables option for assembly (default: enabled)") -option(WOLFSSL_ASM ${WOLFSSL_ASM_HELP_STRING} "yes") +add_option("WOLFSSL_ASM" ${WOLFSSL_ASM_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_ASM) list(APPEND WOLFSSL_DEFINITIONS @@ -192,7 +204,7 @@ endif() # Single threaded set(WOLFSSL_SINGLE_THREADED_HELP_STRING "Enable wolfSSL single threaded (default: disabled)") -option(WOLFSSL_SINGLE_THREADED ${WOLFSSL_SINGLE_THREADED_HELP_STRING} "no") +add_option("WOLFSSL_SINGLE_THREADED" ${WOLFSSL_SINGLE_THREADED_HELP_STRING} "no" "yes;no") # TODO: Logic here isn't complete, yet (see AX_PTHREAD) if(NOT WOLFSSL_SINGLE_THREADED) @@ -209,7 +221,7 @@ endif() # TLS v1.3 set(WOLFSSL_TLS13_HELP_STRING "Enable wolfSSL TLS v1.3 (default: enabled)") -option(WOLFSSL_TLS13 ${WOLFSSL_TLS13_HELP_STRING} "yes") +add_option("WOLFSSL_TLS13" ${WOLFSSL_TLS13_HELP_STRING} "yes" "yes;no") if("${FIPS_VERSION}" STREQUAL "v1") override_cache(WOLFSSL_TLS13 "no") @@ -220,7 +232,7 @@ endif() # RNG set(WOLFSSL_RNG_HELP_STRING "Enable compiling and using RNG (default: enabled)") -option(WOLFSSL_RNG ${WOLFSSL_RNG_HELP_STRING} "yes") +add_option("WOLFSSL_RNG" ${WOLFSSL_RNG_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_RNG) list(APPEND WOLFSSL_DEFINITIONS "-DWC_NO_RNG") @@ -247,7 +259,7 @@ endif() # Harden, enable Timing Resistance and Blinding by default set(WOLFSSL_HARDEN_HELP_STRING "Enable Hardened build, Enables Timing Resistance and Blinding (default: enabled)") -option(WOLFSSL_HARDEN ${WOLFSSL_HARDEN_HELP_STRING} "yes") +add_option("WOLFSSL_HARDEN" ${WOLFSSL_HARDEN_HELP_STRING} "yes" "yes;no") if(WOLFSSL_HARDEN) list(APPEND WOLFSSL_DEFINITIONS "-DTFM_TIMING_RESISTANT" "-DECC_TIMING_RESISTANT") @@ -279,7 +291,7 @@ set(WOLFSSL_SLOW_MATH "yes") # AES-CBC set(WOLFSSL_AESCBC_HELP_STRING "Enable wolfSSL AES-CBC support (default: enabled)") -option(WOLFSSL_AESCBC ${WOLFSSL_AESCBC_HELP_STRING} "yes") +add_option("WOLFSSL_AESCBC" ${WOLFSSL_AESCBC_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_AESCBC) list(APPEND WOLFSSL_DEFINITIONS "-DNO_AES_CBC") @@ -287,8 +299,7 @@ endif() # AES-GCM set(WOLFSSL_AESGCM_HELP_STRING "Enable wolfSSL AES-GCM support (default: enabled)") -set(WOLFSSL_AESGCM "yes" CACHE STRING ${WOLFSSL_AESGCM_HELP_STRING}) -set_property(CACHE WOLFSSL_AESGCM PROPERTY STRINGS "yes" "no" "table" "small" "word32") +add_option("WOLFSSL_AESGCM" ${WOLFSSL_AESGCM_HELP_STRING} "yes" "yes;no;table;small;word32") # leanpsk and leantls don't need gcm if(WOLFSSL_LEAN_PSK OR (WOLFSSL_LEAN_TLS AND NOT WOLFSSL_TLS13)) @@ -331,9 +342,37 @@ endif() # - RIPEMD # - BLAKE2 + +# SHA224 +set(SHA224_DEFAULT "no") +if(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") OR + ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")) + if(NOT WOLFSSL_AFALG AND NOT WOLFSSL_DEVCRYPTO AND + (NOT WOLFSSL_FIPS OR ("${FIPS_VERSION}" STREQUAL "v2"))) + set(SHA224_DEFAULT "yes") + endif() +endif() +set(WOLFSSL_SHA224_HELP_STRING "Enable wolfSSL SHA-224 support (default: enabled on x86_64/aarch64)") +add_option("WOLFSSL_SHA224" ${WOLFSSL_SHA224_HELP_STRING} ${SHA224_DEFAULT} "yes;no") + +# SHA3 +set(SHA3_DEFAULT "no") +if(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") OR + ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")) + if(NOT WOLFSSL_FIPS OR ("${FIPS_VERSION}" STREQUAL "v2")) + set(SHA3_DEFAULT "yes") + endif() +endif() +set(WOLFSSL_SHA3_HELP_STRING "Enable wolfSSL SHA-3 support (default: enabled on x86_64/aarch64)") +add_option("WOLFSSL_SHA3" ${WOLFSSL_SHA3_HELP_STRING} ${SHA3_DEFAULT} "yes;no;small") + +# SHAKE256 +set(WOLFSSL_SHAKE256_HELP_STRING "Enable wolfSSL SHAKE256 support (default: enabled on x86_64/aarch64)") +add_option("WOLFSSL_SHAKE256" ${WOLFSSL_SHAKE256_HELP_STRING} "no" "yes;no;small") + # SHA512 set(WOLFSSL_SHA512_HELP_STRING "Enable wolfSSL SHA-512 support (default: enabled)") -option(WOLFSSL_SHA512 ${WOLFSSL_SHA512_HELP_STRING} "yes") +add_option("WOLFSSL_SHA512" ${WOLFSSL_SHA512_HELP_STRING} "yes" "yes;no") # options that don't require sha512 if(WOLFSSL_LEAN_PSK OR @@ -356,7 +395,7 @@ endif() # SHA384 set(WOLFSSL_SHA384_HELP_STRING "Enable wolfSSL SHA-384 support (default: enabled)") -option(WOLFSSL_SHA384 ${WOLFSSL_SHA384_HELP_STRING} "yes") +add_option("WOLFSSL_SHA384" ${WOLFSSL_SHA384_HELP_STRING} "yes" "yes;no") # options that don't require sha384 if(WOLFSSL_LEAN_PSK OR @@ -387,7 +426,7 @@ endif() # HKDF set(WOLFSSL_HKDF_HELP_STRING "Enable HKDF (HMAC-KDF) support (default: disabled)") -option(WOLFSSL_HKDF ${WOLFSSL_HKDF_HELP_STRING} "no") +add_option("WOLFSSL_HKDF" ${WOLFSSL_HKDF_HELP_STRING} "no" "yes;no") if(WOLFSSL_TLS13) override_cache(WOLFSSL_HKDF "yes") @@ -401,7 +440,7 @@ endif() # DSA set(WOLFSSL_DSA_HELP_STRING "Enable DSA (default: disabled)") -option(WOLFSSL_DSA ${WOLFSSL_DSA_HELP_STRING} "no") +add_option("WOLFSSL_DSA" ${WOLFSSL_DSA_HELP_STRING} "no" "yes;no") if(NOT WOLFSSL_DSA AND NOT WOLFSSL_OPENSSH) list(APPEND WOLFSSL_DEFINITIONS "-DNO_DSA") @@ -409,12 +448,11 @@ endif() # ECC Shamir set(WOLFSSL_ECCSHAMIR_HELP_STRING "Enable ECC Shamir (default: enabled)") -option(WOLFSSL_ECCSHAMIR ${WOLFSSL_ECCSHAMIR_HELP_STRING} "yes") +add_option("WOLFSSL_ECCSHAMIR" ${WOLFSSL_ECCSHAMIR_HELP_STRING} "yes" "yes;no") # ECC set(WOLFSSL_ECC_HELP_STRING "Enable ECC (default: enabled)") -set(WOLFSSL_ECC "yes" CACHE STRING ${WOLFSSL_ECC_HELP_STRING}) -set_property(CACHE WOLFSSL_ECC PROPERTY STRINGS "yes" "no" "nonblock") +add_option("WOLFSSL_ECC" ${WOLFSSL_ECC_HELP_STRING} "yes" "yes;no;nonblock") # lean psk doesn't need ecc if(WOLFSSL_LEAN_PSK) @@ -441,18 +479,105 @@ endif() # TODO: - ECC custom curves # - Compressed key -# - CURVE25519 -# - ED25519 -# - CURVE448 -# - ED448 # - FP ECC, fixed point cache ECC # - ECC encrypt # - PSK # - Single PSK identity +# CURVE25519 +set(WOLFSSL_CURVE25519_SMALL "no") +set(WOLFSSL_CURVE25519_HELP_STRING "Enable Curve25519 (default: disabled)") +add_option("WOLFSSL_CURVE25519" ${WOLFSSL_CURVE25519_HELP_STRING} "no" "yes;no;small;no128bit") + +if(WOLFSSL_OPENSSH) + override_cache(WOLFSSL_CURVE25519 "yes") +endif() + +if(WOLFSSL_CURVE25519) + if("${WOLFSSL_CURVE25519}" STREQUAL "small" OR WOLFSSL_LOW_RESOURCE) + list(APPEND WOLFSSL_DEFINITIONS "-DCURVE25519_SMALL") + set(WOLFSSL_CURVE25519_SMALL "yes") + endif() + + if("${WOLFSSL_CURVE25519}" STREQUAL "no128bit" OR WOLFSSL_32BIT) + list(APPEND WOLFSSL_DEFINITIONS "-DNO_CURVED25519_128BIT") + endif() + + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_CURVE25519") + set(WOLFSSL_FEMATH "yes") +endif() + +# ED25519 +set(WOLFSSL_ED25519_SMALL "no") +set(WOLFSSL_ED25519_HELP_STRING "Enable ED25519 (default: disabled)") +add_option("WOLFSSL_ED25519" ${WOLFSSL_ED25519_HELP_STRING} "no" "yes;no") + +if(WOLFSSL_OPENSSH) + override_cache(WOLFSSL_ED25519 "yes") +endif() + +if(WOLFSSL_ED25519 AND NOT WOLFSSL_32BIT) + if("${WOLFSSL_ED25519}" STREQUAL "small" OR WOLFSSL_LOW_RESOURCE) + list(APPEND WOLFSSL_DEFINITIONS "-DED25519_SMALL") + set(WOLFSSL_ED25519_SMALL "yes") + set(WOLFSSL_CURVE25519_SMALL "yes") + endif() + + if(NOT WOLFSSL_SHA512) + message(FATAL_ERROR "cannot enable ed25519 without enabling sha512.") + endif() + + set(WOLFSSL_FEMATH "yes") + set(WOLFSSL_GEMATH "yes") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ED25519") +endif() + +# CURVE448 +set(WOLFSSL_CURVE448_SMALL "no") +set(WOLFSSL_CURVE448_HELP_STRING "Enable Curve448 (default: disabled)") +add_option("WOLFSSL_CURVE448" ${WOLFSSL_CURVE448_HELP_STRING} "no" "yes;no;small") + +if(WOLFSSL_CURVE448) + if("${WOLFSSL_CURVE448}" STREQUAL "small" OR WOLFSSL_LOW_RESOURCE) + list(APPEND WOLFSSL_DEFINITIONS "-DCURVE448_SMALL") + set(WOLFSSL_CURVE448_SMALL "yes") + endif() + + if("${WOLFSSL_CURVE448}" STREQUAL "no128bit" OR WOLFSSL_32BIT) + list(APPEND WOLFSSL_DEFINITIONS "-DNO_CURVED448_128BIT") + endif() + + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_CURVE448") + set(WOLFSSL_FE448 "yes") +endif() + +# ED448 +set(WOLFSSL_ED448_SMALL "no") +set(WOLFSSL_ED448_HELP_STRING "Enable ED448 (default: disabled)") +add_option("WOLFSSL_ED448" ${WOLFSSL_ED448_HELP_STRING} "no" "yes;no;small") + +if(WOLFSSL_ED448 AND NOT WOLFSSL_32BIT) + if("${WOLFSSL_ED448}" STREQUAL "small" OR WOLFSSL_LOW_RESOURCE) + list(APPEND WOLFSSL_DEFINITIONS "-DED448_SMALL") + set(WOLFSSL_ED448_SMALL "yes") + set(WOLFSSL_CURVE448_SMALL "yes") + endif() + + if(NOT WOLFSSL_SHA512) + message(FATAL_ERROR "cannot enable ed448 without enabling sha512.") + endif() + + set(WOLFSSL_FE448 "yes") + set(WOLFSSL_GE448 "yes") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ED448") + + # EdDSA448 requires SHAKE256 which requires SHA-3 + override_cache(WOLFSSL_SHAKE256 "yes") +endif() + # Error strings set(WOLFSSL_ERROR_STRINGS_HELP_STRING "Enable error strings table (default: enabled)") -option(WOLFSSL_ERROR_STRINGS ${WOLFSSL_ERROR_STRINGS_HELP_STRING} "yes") +add_option("WOLFSSL_ERROR_STRINGS" ${WOLFSSL_ERROR_STRINGS_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_ERROR_STRINGS) list(APPEND WOLFSSL_DEFINITIONS "-DNO_ERROR_STRINGS") @@ -466,7 +591,7 @@ endif() # Error queue set(WOLFSSL_ERROR_QUEUE_HELP_STRING "Enables adding nodes to error queue when compiled with OPENSSL_EXTRA (default: enabled)") -option(WOLFSSL_ERROR_QUEUE ${WOLFSSL_DISABLE_ERROR_QUEUE_HELP_STRING} "yes") +add_option("WOLFSSL_ERROR_QUEUE" ${WOLFSSL_ERROR_QUEUE_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_ERROR_QUEUE) list(APPEND WOLFSSL_DEFINITIONS "-DNO_ERROR_QUEUE") @@ -474,7 +599,7 @@ endif() # Old TLS set(WOLFSSL_OLD_TLS_HELP_STRING "Enable old TLS versions < 1.2 (default: enabled)") -option(WOLFSSL_OLD_TLS ${WOLFSSL_OLD_TLS_HELP_STRING} "yes") +add_option("WOLFSSL_OLD_TLS" ${WOLFSSL_OLD_TLS_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_OLD_TLS) list(APPEND WOLFSSL_DEFINITIONS "-DNO_OLD_TLS") @@ -488,7 +613,7 @@ endif() # TLSv1.2 set(WOLFSSL_TLSV12_HELP_STRING "Enable TLS versions 1.2 (default: enabled)") -option(WOLFSSL_TLSV12 ${WOLFSSL_TLSV12_HELP_STRING} "yes") +add_option("WOLFSSL_TLSV12" ${WOLFSSL_TLSV12_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_TLSV12) list(APPEND WOLFSSL_DEFINITIONS @@ -503,7 +628,7 @@ endif() # Memory set(WOLFSSL_MEMORY_HELP_STRING "Enable memory callbacks (default: enabled)") -option(WOLFSSL_MEMORY ${WOLFSSL_MEMORY_HELP_STRING} "yes") +add_option("WOLFSSL_MEMORY" ${WOLFSSL_MEMORY_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_MEMORY) list(APPEND WOLFSSL_DEFINITIONS "-DNO_WOLFSSL_MEMORY") @@ -521,7 +646,7 @@ endif() # RSA set(WOLFSSL_RSA_HELP_STRING "Enable RSA (default: enabled)") -option(WOLFSSL_RSA ${WOLFSSL_RSA_HELP_STRING} "yes") +add_option("WOLFSSL_RSA" ${WOLFSSL_RSA_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_RSA) list(APPEND WOLFSSL_DEFINITIONS "-DNO_RSA") @@ -534,7 +659,7 @@ endif() # OAEP set(WOLFSSL_OAEP_HELP_STRING "Enable RSA OAEP (default: enabled)") -option(WOLFSSL_OAEP ${WOLFSSL_OAEP_HELP_STRING} "yes") +add_option("WOLFSSL_OAEP" ${WOLFSSL_OAEP_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_OAEP) list(APPEND WOLFSSL_DEFINITIONS "-DWC_NO_RSA_OAEP") @@ -545,7 +670,7 @@ endif() # RSA-PSS set(WOLFSSL_RSA_PSS_HELP_STRING "Enable RSA-PSS (default: disabled)") -option(WOLFSSL_RSA_PSS ${WOLFSSL_RSA_PSS_HELP_STRING} "no") +add_option("WOLFSSL_RSA_PSS" ${WOLFSSL_RSA_PSS_HELP_STRING} "no" "yes;no") if(NOT WOLFSSL_RSA) override_cache(WOLFSSL_RSA_PSS "no") @@ -560,7 +685,7 @@ endif() # DH set(WOLFSSL_DH_HELP_STRING "Enable DH (default: enabled)") -option(WOLFSSL_DH ${WOLFSSL_DH_HELP_STRING} "yes") +add_option("WOLFSSL_DH" ${WOLFSSL_DH_HELP_STRING} "yes" "yes;no") if(WOLFSSL_OPENSSH) override_cache(WOLFSSL_DH "yes") @@ -581,7 +706,7 @@ endif() # turn off asn, which means no certs, no rsa, no dsa, no ecc, # and no big int (unless dh is on) set(WOLFSSL_ASN_HELP_STRING "Enable ASN (default: enabled)") -option(WOLFSSL_ASN ${WOLFSSL_ASN_HELP_STRING} "yes") +add_option("WOLFSSL_ASN" ${WOLFSSL_ASN_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_ASN) list(APPEND WOLFSSL_DEFINITIONS "-DNO_ASN" "-DNO_CERTS") @@ -626,7 +751,7 @@ endif() # AES set(WOLFSSL_AES_HELP_STRING "Enable AES (default: enabled)") -option(WOLFSSL_AES ${WOLFSSL_AES_HELP_STRING} "yes") +add_option("WOLFSSL_AES" ${WOLFSSL_AES_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_AES) list(APPEND WOLFSSL_DEFINITIONS "-DNO_AES") @@ -655,7 +780,7 @@ endif() # Coding set(WOLFSSL_CODING_HELP_STRING "Enable coding base 16/64 (default: enabled)") -option(WOLFSSL_CODING ${WOLFSSL_CODING_HELP_STRING} "yes") +add_option("WOLFSSL_CODING" ${WOLFSSL_CODING_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_CODING) list(APPEND WOLFSSL_DEFINITIONS "-DNO_CODING") @@ -674,7 +799,7 @@ if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") endif() set(WOLFSSL_BASE64_ENCODE_HELP_STRING "Enable Base64 encoding (default: enabled on x86_64)") -option(WOLFSSL_BASE64_ENCODE ${WOLFSSL_BASE64_ENCODE_HELP_STRING} ${BASE64_ENCODE_DEFAULT}) +add_option("WOLFSSL_BASE64_ENCODE" ${WOLFSSL_BASE64_ENCODE_HELP_STRING} ${BASE64_ENCODE_DEFAULT} "yes;no") if(WOLFSSL_BASE64_ENCODE) list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_BASE64_ENCODE") @@ -684,7 +809,7 @@ endif() # DES3 set(WOLFSSL_DES3_HELP_STRING "Enable DES3 (default: disabled)") -option(WOLFSSL_DES3 ${WOLFSSL_DES3_HELP_STRING} "no") +add_option("WOLFSSL_DES3" ${WOLFSSL_DES3_HELP_STRING} "no" "yes;no") if(WOLFSSL_OPENSSH OR WOLFSSL_QT OR @@ -697,7 +822,7 @@ endif() # ARC4 set(WOLFSSL_ARC4_HELP_STRING "Enable ARC4 (default: disabled)") -option(WOLFSSL_ARC4 ${WOLFSSL_ARC4_HELP_STRING} "no") +add_option("WOLFSSL_ARC4" ${WOLFSSL_ARC4_HELP_STRING} "no" "yes;no") if(WOLFSSL_OPENSSH OR WOLFSSL_WPAS) override_cache(WOLFSSL_ARC4 "yes") @@ -715,7 +840,7 @@ endif() # MD5 set(WOLFSSL_MD5_HELP_STRING "Enable MD5 (default: enabled)") -option(WOLFSSL_MD5 ${WOLFSSL_MD5_HELP_STRING} "yes") +add_option("WOLFSSL_MD5" ${WOLFSSL_MD5_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_MD5) list(APPEND WOLFSSL_DEFINITIONS "-DNO_MD5" "-DNO_OLD_TLS") @@ -729,7 +854,7 @@ endif() # SHA set(WOLFSSL_SHA_HELP_STRING "Enable SHA (default: enabled)") -option(WOLFSSL_SHA ${WOLFSSL_SHA_HELP_STRING} "yes") +add_option("WOLFSSL_SHA" ${WOLFSSL_SHA_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_SHA) list(APPEND WOLFSSL_DEFINITIONS "-DNO_SHA" "-DNO_OLD_TLS") @@ -748,7 +873,7 @@ endif() # HC128 set(WOLFSSL_HC128_HELP_STRING "Enable HC-128 (default: disabled)") -option(WOLFSSL_HC128 ${WOLFSSL_HC128_HELP_STRING} "no") +add_option("WOLFSSL_HC128" ${WOLFSSL_HC128_HELP_STRING} "no" "yes;no") if(NOT WOLFSSL_HC128) list(APPEND WOLFSSL_DEFINITIONS "-DNO_HC128") @@ -768,35 +893,11 @@ endif() # - Selftest # SHA224 -set(SHA224_DEFAULT "no") -if(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") OR - ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")) - if(NOT WOLFSSL_AFALG AND NOT WOLFSSL_DEVCRYPTO AND - (NOT WOLFSSL_FIPS OR ("${FIPS_VERSION}" STREQUAL "v2"))) - set(SHA224_DEFAULT "yes") - endif() -endif() - -set(WOLFSSL_SHA224_HELP_STRING "Enable wolfSSL SHA-224 support (default: enabled on x86_64/aarch64)") -option(WOLFSSL_SHA224 ${WOLFSSL_SHA224_HELP_STRING} ${SHA224_DEFAULT}) - if(WOLFSSL_SHA224) list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHA224") endif() # SHA3 -set(SHA3_DEFAULT "no") -if(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") OR - ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")) - if(NOT WOLFSSL_FIPS OR ("${FIPS_VERSION}" STREQUAL "v2")) - set(SHA3_DEFAULT "yes") - endif() -endif() - -set(WOLFSSL_SHA3_HELP_STRING "Enable wolfSSL SHA-3 support (default: enabled on x86_64/aarch64)") -set(WOLFSSL_SHA3 ${SHA3_DEFAULT} CACHE STRING ${WOLFSSL_SHA3_HELP_STRING}) -set_property(CACHE WOLFSSL_SHA3 PROPERTY STRINGS "yes" "no" "small") - if("${WOLFSSL_SHA3}" STREQUAL "small") list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHA3_SMALL") override_cache(WOLFSSL_SHA3 "yes") @@ -807,10 +908,6 @@ if(WOLFSSL_SHA3 AND NOT WOLFSSL_32BIT) endif() # SHAKE256 -set(WOLFSSL_SHAKE256_HELP_STRING "Enable wolfSSL SHAKE256 support (default: enabled on x86_64/aarch64)") -set(WOLFSSL_SHAKE256 "no" CACHE STRING ${WOLFSSL_SHAKE256_HELP_STRING}) -set_property(CACHE WOLFSSL_SHAKE256 PROPERTY STRINGS "yes" "no" "small") - if(NOT WOLFSSL_SHAKE256) override_cache(WOLFSSL_SHAKE256 ${WOLFSSL_SHA3}) endif() @@ -832,7 +929,7 @@ if(WOLFSSL_FIPS) endif() set(WOLFSSL_POLY1305_HELP_STRING "Enable wolfSSL POLY1305 support (default: enabled)") -option(WOLFSSL_POLY1305 ${WOLFSSL_POLY1305_HELP_STRING} ${POLY1305_DEFAULT}) +add_option("WOLFSSL_POLY1305" ${WOLFSSL_POLY1305_HELP_STRING} ${POLY1305_DEFAULT} "yes;no") # leanpsk and leantls don't need poly1305 if(WOLFSSL_LEAN_PSK OR WOLFSSL_LEAN_TLS) @@ -852,8 +949,7 @@ if(WOLFSSL_FIPS) endif() set(WOLFSSL_CHACHA_HELP_STRING "Enable CHACHA (default: enabled). Use `=noasm` to disable ASM AVX/AVX2 speedups") -set(WOLFSSL_CHACHA ${CHACHA_DEFAULT} CACHE STRING ${WOLFSSL_CHACHA_HELP_STRING}) -set_property(CACHE WOLFSSL_CHACHA PROPERTY STRINGS "yes" "no" "noasm") +add_option("WOLFSSL_CHACHA" ${WOLFSSL_CHACHA_HELP_STRING} ${CHACHA_DEFAULT} "yes;no;noasm") # leanpsk and leantls don't need chacha if(WOLFSSL_LEAN_PSK OR WOLFSSL_LEAN_TLS) @@ -872,7 +968,7 @@ endif() # Hash DRBG set(WOLFSSL_HASH_DRBG_HELP_STRING "Enable Hash DRBG support (default: enabled)") -option(WOLFSSL_HASH_DRBG ${WOLFSSL_HASH_DRBG_HELP_STRING} "yes") +add_option("WOLFSSL_HASH_DRBG" ${WOLFSSL_HASH_DRBG_HELP_STRING} "yes" "yes;no") if(WOLFSSL_HASH_DRBG) list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_HASHDRBG") @@ -894,7 +990,7 @@ else() endif() set(WOLFSSL_FILESYSTEM_HELP_STRING "Enable Filesystem support (default: enabled)") -option(WOLFSSL_FILESYSTEM ${WOLFSSL_FILESYSTEM_HELP_STRING} ${FILESYSTEM_DEFAULT}) +add_option("WOLFSSL_FILESYSTEM" ${WOLFSSL_FILESYSTEM_HELP_STRING} ${FILESYSTEM_DEFAULT} "yes;no") if(NOT WOLFSSL_FILESYSTEM) list(APPEND WOLFSSL_DEFINITIONS "-DNO_FILESYSTEM") @@ -907,7 +1003,7 @@ endif() # Inline function support set(WOLFSSL_INLINE_HELP_STRING "Enable inline functions (default: enabled)") -option(WOLFSSL_INLINE ${WOLFSSL_INLINE_HELP_STRING} "yes") +add_option("WOLFSSL_INLINE" ${WOLFSSL_INLINE_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_INLINE) list(APPEND WOLFSSL_DEFINITIONS "-DNO_INLINE") @@ -933,7 +1029,7 @@ endif() # Supported elliptic curves extensions set(WOLFSSL_SUPPORTED_CURVES_HELP_STRING "Enable Supported Elliptic Curves (default: enabled)") -option(WOLFSSL_SUPPORTED_CURVES ${WOLFSSL_SUPPORTED_CURVES_HELP_STRING} "yes") +add_option("WOLFSSL_SUPPORTED_CURVES" ${WOLFSSL_SUPPORTED_CURVES_HELP_STRING} "yes" "yes;no") if(WOLFSSL_SUPPORTED_CURVES) if(NOT WOLFSSL_ECC AND NOT WOLFSSL_CURVE25519 AND NOT WOLFSSL_CURVE448) @@ -968,11 +1064,23 @@ if (WOLFSSL_TLS13) "-DHAVE_SUPPORTED_CURVES") endif() -# TODO: - Session ticket +# Session Ticket Extension +set(WOLFSSL_SESSION_TICKET_HELP_STRING "Enable Session Ticket (default: disabled)") +add_option("WOLFSSL_SESSION_TICKET" ${WOLFSSL_SESSION_TICKET_HELP_STRING} "no" "yes;no") + +if(WOLFSSL_NGINX OR WOLFSSL_WPAS OR WOLFSSL_HAPROXY OR WOLFSSL_LIGHTY) + override_cache(WOLFSSL_SESSION_TICKET "yes") +endif() + +if(WOLFSSL_SESSION_TICKET) + list(APPEND WOLFSSL_DEFINITIONS + "-DHAVE_TLS_EXTENSIONS" + "-DHAVE_SESSION_TICKET") +endif() # Extended master secret extension set(WOLFSSL_EXTENDED_MASTER_HELP_STRING "Enable Extended Master Secret (default: enabled)") -option(WOLFSSL_EXTENDED_MASTER ${WOLFSSL_EXTENDED_MASTER_HELP_STRING} "yes") +add_option("WOLFSSL_EXTENDED_MASTER" ${WOLFSSL_EXTENDED_MASTER_HELP_STRING} "yes" "yes;no") if(WOLFSSL_EXTENDED_MASTER) list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_EXTENDED_MASTER") @@ -998,7 +1106,7 @@ endif() # Encrypt-then-mac set(WOLFSSL_ENC_THEN_MAC_HELP_STRING "Enable Encryptr-Then-Mac extension (default: enabled)") -option(WOLFSSL_ENC_THEN_MAC ${WOLFSSL_ENC_THEN_MAC_HELP_STRING} "yes") +add_option("WOLFSSL_ENC_THEN_MAC" ${WOLFSSL_ENC_THEN_MAC_HELP_STRING} "yes" "yes;no") if(WOLFSSL_APACHE_HTTPD) override_cache(WOLFSSL_ENC_THEN_MAC "no") @@ -1015,7 +1123,7 @@ endif() # stunnel Support # TODO: rest of stunnel support set(WOLFSSL_STUNNEL_HELP_STRING "Enable stunnel (default: disabled)") -option(WOLFSSL_STUNNEL ${WOLFSSL_STUNNEL_HELP_STRING} "no") +add_option("WOLFSSL_STUNNEL" ${WOLFSSL_STUNNEL_HELP_STRING} "no" "yes;no") if(NOT WOLFSSL_PSK AND NOT WOLFSSL_LEAN_PSK AND @@ -1029,7 +1137,7 @@ endif() # MD4 set(WOLFSSL_MD4_HELP_STRING "Enable MD4 (default: disabled)") -option(WOLFSSL_MD4 ${WOLFSSL_MD4_HELP_STRING} "no") +add_option("WOLFSSL_MD4" ${WOLFSSL_MD4_HELP_STRING} "no" "yes;no") if(NOT WOLFSSL_MD4) # turn on MD4 if using stunnel @@ -1045,7 +1153,7 @@ endif() # PWDBASED has to come after certservice since we want it on w/o explicit on # PWDBASED set(WOLFSSL_PWDBASED_HELP_STRING "Enable PWDBASED (default: disabled)") -option(WOLFSSL_PWDBASED ${WOLFSSL_PWDBASED_HELP_STRING} "no") +add_option("WOLFSSL_PWDBASED" ${WOLFSSL_PWDBASED_HELP_STRING} "no" "yes;no") if(NOT WOLFSSL_PWDBASED) if(WOLFSSL_OPENSSLEXTRA OR @@ -1079,7 +1187,7 @@ if(WOLFSSL_SP_MATH) endif() set(WOLFSSL_FAST_MATH_HELP_STRING "Enable fast math ops (default: enabled on x86_64/aarch64)") -option(WOLFSSL_FAST_MATH ${WOLFSSL_FAST_MATH_HELP_STRING} ${FASTMATH_DEFAULT}) +add_option("WOLFSSL_FAST_MATH" ${WOLFSSL_FAST_MATH_HELP_STRING} ${FASTMATH_DEFAULT} "yes;no") if(WOLFSSL_FAST_MATH) # turn off fastmath if leanpsk on or asn off (w/o DH and ECC) @@ -1113,7 +1221,7 @@ else() endif() set(WOLFSSL_EXAMPLES_HELP_STRING "Enable examples (default: enabled)") -option(WOLFSSL_EXAMPLES ${WOLFSSL_EXAMPLES_HELP_STRING} ${EXAMPLES_DEFAULT}) +add_option("WOLFSSL_EXAMPLES" ${WOLFSSL_EXAMPLES_HELP_STRING} ${EXAMPLES_DEFAULT} "yes;no") if(NOT WOLFSSL_FILESYSTEM OR NOT WOLFSSL_INLINE OR @@ -1129,7 +1237,7 @@ else() endif() set(WOLFSSL_CRYPT_TESTS_HELP_STRING "Enable Crypt Bench/Test (default: enabled)") -option(WOLFSSL_CRYPT_TESTS ${WOLFSSL_CRYPT_TESTS_HELP_STRING} ${CRYPT_TESTS_DEFAULT}) +add_option("WOLFSSL_CRYPT_TESTS" ${WOLFSSL_CRYPT_TESTS_HELP_STRING} ${CRYPT_TESTS_DEFAULT} "yes;no") # TODO: - LIBZ # - PKCS#11 @@ -1146,7 +1254,7 @@ option(WOLFSSL_CRYPT_TESTS ${WOLFSSL_CRYPT_TESTS_HELP_STRING} ${CRYPT_TESTS_DEFA # Asynchronous threading set(WOLFSSL_ASYNC_THREADS_HELP_STRING "Enable Asynchronous Threading (default: enabled)") -option(WOLFSSL_ASYNC_THREADS ${WOLFSSL_ASYNC_THREADS_HELP_STRING} "yes") +add_option("WOLFSSL_ASYNC_THREADS" ${WOLFSSL_ASYNC_THREADS_HELP_STRING} "yes" "yes;no") if(WOLFSSL_ASYNC_CRYPT AND WOLFSSL_ASYNC_THREADS) if(CMAKE_USE_PTHREADS_INIT) @@ -1171,7 +1279,7 @@ endif() # - AES key wrap set(WOLFSSL_OLD_NAMES_HELP_STRING "Keep backwards compat with old names (default: enabled)") -option(WOLFSSL_OLD_NAMES ${WOLFSSL_OLD_NAMES_HELP_STRING} "yes") +add_option("WOLFSSL_OLD_NAMES" ${WOLFSSL_OLD_NAMES_HELP_STRING} "yes" "yes;no") if(NOT WOLFSSL_OLD_NAMES AND NOT WOLFSSL_OPENSSL_COEXIST) list(APPEND WOLFSSL_DEFINITIONS @@ -1186,7 +1294,7 @@ endif() # Support for enabling setting default DH parameters set(WOLFSSL_DH_DEFAULT_PARAMS_HELP_STRING "Enables option for default dh parameters (default: disabled)") -option(WOLFSSL_DH_DEFAULT_PARAMS ${WOLFSSL_DH_DEFAULT_PARAMS_HELP_STRING} "no") +add_option("WOLFSSL_DH_DEFAULT_PARAMS" ${WOLFSSL_DH_DEFAULT_PARAMS_HELP_STRING} "no" "yes;no") if(WOLFSSL_DH_DEFAULT_PARAMS OR NOT WOLFSSL_QT) override_cache(WOLFSSL_DH_DEFAULT_PARAMS "yes") @@ -1204,10 +1312,10 @@ else() endif() set(WOLFSSL_USER_SETTINGS_HELP_STRING "Use your own user_settings.h and do not add Makefile CFLAGS (default: disabled)") -option(WOLFSSL_USER_SETTINGS ${WOLFSSL_USER_SETTINGS_HELP_STRING} "no") +add_option("WOLFSSL_USER_SETTINGS" ${WOLFSSL_USER_SETTINGS_HELP_STRING} "no" "yes;no") set(WOLFSSL_OPTFLAGS_HELP_STRING "Enable default optimization CFLAGS for the compiler (default: enabled)") -option(WOLFSSL_OPTFLAGS ${WOLFSSL_OPTFLAGS_HELP_STRING} "yes") +add_option("WOLFSSL_OPTFLAGS" ${WOLFSSL_OPTFLAGS_HELP_STRING} "yes" "yes;no") # Generates the BUILD_* flags. These control what source files are included in # the library. A series of AM_CONDITIONALs handle this in configure.ac. @@ -1227,7 +1335,7 @@ endif() add_definitions(${WOLFSSL_DEFINITIONS}) set(WOLFSSL_CONFIG_H_HELP_STRING "Enable generation of config.h and define HAVE_CONFIG_H (default: enabled)") -option(WOLFSSL_CONFIG_H ${WOLFSSL_CONFIG_H_HELP_STRING} "yes") +add_option("WOLFSSL_CONFIG_H" ${WOLFSSL_CONFIG_H_HELP_STRING} "yes" "yes;no") if(WOLFSSL_CONFIG_H) add_definitions("-DHAVE_CONFIG_H") @@ -1261,6 +1369,8 @@ file(APPEND ${OPTION_FILE} "#ifdef __cplusplus\n") file(APPEND ${OPTION_FILE} "extern \"C\" {\n") file(APPEND ${OPTION_FILE} "#endif\n\n") +list(REMOVE_DUPLICATES WOLFSSL_DEFINITIONS) + foreach(DEF IN LISTS WOLFSSL_DEFINITIONS) if(DEF MATCHES "^-D") if(DEF MATCHES "^-D(N)?DEBUG(=.+)?") diff --git a/ChangeLog.md b/ChangeLog.md index 3ad61812e..3399d02be 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,6 +7,7 @@ Release 4.7.0 of wolfSSL embedded TLS has bug fixes and new features including: * Function wolfSSL_CTX_NoTicketTLSv12 added to enable turning off session tickets with TLS 1.2 while keeping TLS 1.3 session tickets available * Implement RFC 5705: Keying Material Exporters for TLS * Added --enable-reproducible-build flag for making more deterministic library outputs to assist debugging +* Added support for S/MIME (Secure/Multipurpose Internet Mail Extensions) bundles ### Fixes * Fix to free mutex when cert manager is free’d @@ -44,7 +45,7 @@ Release 4.7.0 of wolfSSL embedded TLS has bug fixes and new features including: * Out of directory builds resolved, wolfSSL can now be built in a separate directory than the root wolfssl directory ### Vulnerabilities -* [HIGH] CVE-2021-3336: In earlier versions of wolfSSL there exists a potential man in the middle attack on TLS 1.3 clients. Malicious attackers with a privileged network position can impersonate TLS 1.3 servers and bypass authentication. Users that have applications with client side code and have TLS 1.3 turned on, should update to the latest version of wolfSSL. Users that do not have TLS 1.3 turned on, or that are server side only, are NOT affected by this report. For the code change see https://github.com/wolfSSL/wolfssl/pull/3676. +* [HIGH] CVE-2021-3336: In earlier versions of wolfSSL there exists a potential man in the middle attack on TLS 1.3 clients. Malicious attackers with a privileged network position can impersonate TLS 1.3 servers and bypass authentication. Users that have applications with client side code and have TLS 1.3 turned on, should update to the latest version of wolfSSL. Users that do not have TLS 1.3 turned on, or that are server side only, are NOT affected by this report. For the code change see https://github.com/wolfSSL/wolfssl/pull/3676. Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis for the report. * [LOW] In the case of using custom ECC curves there is the potential for a crafted compressed ECC key that has a custom prime value to cause a hang when imported. This only affects applications that are loading in ECC keys with wolfSSL builds that have compressed ECC keys and custom ECC curves enabled. * [LOW] With TLS 1.3 authenticated-only ciphers a section of the server hello could contain 16 bytes of uninitialized data when sent to the connected peer. This affects only a specific build of wolfSSL with TLS 1.3 early data enabled and using authenticated-only ciphers with TLS 1.3. diff --git a/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino b/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino index a7f18a467..b5c83aa41 100644 --- a/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino +++ b/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino @@ -1,6 +1,6 @@ /* wolfssl_client.ino * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino b/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino index 26fac5767..6d5478d5a 100644 --- a/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino +++ b/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino @@ -1,6 +1,6 @@ /* wolfssl_server.ino * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/CRYPTOCELL/main.c b/IDE/CRYPTOCELL/main.c index 32ff58d71..ea889b8c8 100644 --- a/IDE/CRYPTOCELL/main.c +++ b/IDE/CRYPTOCELL/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include #include #include diff --git a/IDE/CRYPTOCELL/user_settings.h b/IDE/CRYPTOCELL/user_settings.h index bbc3bab28..380422d23 100644 --- a/IDE/CRYPTOCELL/user_settings.h +++ b/IDE/CRYPTOCELL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -41,6 +41,7 @@ extern "C" { #endif #if defined(WOLFSSL_CRYPTOCELL) + /* see SASI_AES_KEY_MAX_SIZE_IN_BYTES in the nRF5 SDK */ #define AES_MAX_KEY_SIZE 128 #endif /* WOLFSSL_CRYPTOCELL*/ @@ -137,6 +138,9 @@ extern "C" { #if 1 #define HAVE_ECC + #include + /* strings.h required for strncasecmp */ + /* Manually define enabled curves */ #undef ECC_USER_CURVES #define ECC_USER_CURVES diff --git a/IDE/ECLIPSE/DEOS/README.md b/IDE/ECLIPSE/DEOS/README.md index 5c67896d0..711846a38 100644 --- a/IDE/ECLIPSE/DEOS/README.md +++ b/IDE/ECLIPSE/DEOS/README.md @@ -1,71 +1,64 @@ - - # Deos Port + ## Overview -You can enable the wolfSSL support for Deos RTOS available [here](https://www.ddci.com/products_deos_do_178c_arinc_653/) using the `#define WOLFSSL_DEOS`. -Deos is a time & space partitioned, multi-core enabled, DO-178C DAL A certifiable RTOS. + +You can enable the wolfSSL support for Deos RTOS available +[here](https://www.ddci.com/products_deos_do_178c_arinc_653/) using +the `#define WOLFSSL_DEOS`. Deos is a time & space partitioned, +multi-core enabled, DO-178C DAL A certifiable RTOS. + ## Usage -You can start with your OpenArbor IDE-based example project for Deos with the network stack (lwip) to integrate wolfSSL source code. +You can start with your OpenArbor IDE-based example project for Deos +with the network stack (lwip) to integrate wolfSSL source code. -wolfSSL supports a compile-time user configurable options in the `IDE/ECLIPSE/DEOS/user_settings.h` file. +wolfSSL supports a compile-time user configurable options in the +`IDE/ECLIPSE/DEOS/user_settings.h` file. -The `tls_wolfssl.c` example application provides a simple function to run the selected examples at compile time through the following four #defines in user_settings.h. You can undefine any of these macro options to run a test. -``` - 1. #undef NO_CRYPT_TEST - 2. #undef NO_CRYPT_BENCHMARK - 3. #undef NO_WOLFSSL_CLIENT - 4. #undef NO_WOLFSSL_SERVER -``` -Do one of the following steps for building and running wolfSSL with the Deos kernel examples, which are included in the DDS release: -If you want to create a project from scratch, skip the Importing the project section and follow the steps in the other sections. +### Importing the project -If you want to use an pre-configured example project, go to the Importing the project section, skip the other sections and follow the Building and Running section. - -#### Importing the project In this section you will import a pre-configured example project. + +Note: To work wolfssl directory must not be under the workspace directory. + 1. Launch the OpenArbor IDE as an administrator -2. In the Workspace Launcher dialog, in the Workspace field, enter your -workspace +2. In the Workspace Launcher dialog, in the Workspace field, enter + your workspace 3. Right-click in the Project Explorer view and select Import -4. In the Import dialog, select General > Existing Projects into Workspace, then click Next. -5. In the Import Projects dialog, select Select archive file, then browse to `IDE/ECLIPSE/DEOS/` and double-click `deosWolfssl.zip` file +4. In the Import dialog, select General > Existing Projects into + Workspace, then click Next. +5. In the Import Projects dialog, select `Select root directory` and + browse to `IDE/ECLIPSE/DEOS/deos_wolfssl` and select the wolfssl + project 6. In the Import Projects dialog, click Finish +#### Dependencies + +* ansi +* gnu-language +* deos-time + +### Setting up a Deos project with wolfSSL + +The `tls_wolfssl.c` example application provides a simple function to +run the selected examples at compile time through the following four +`#defines` in `user_settings.h`. You can undefine any of these macro +options to run a test. -#### Setting up a Deos project with wolfSSL - 1. Download the wolfSSL source code or a zip file from GitHub. You can remove all of the files except for these folders and its contents. The top folder for this example is wolfsslPort. ``` -wolfsslPort - |-- IDE - | -- ECLIPSE - | -- DEOS - |-- src - |-- wolfcrypt - | -- benchmark - | -- src - | -- test - |-- wolfssl - |-- openssl - |-- wolfcrypt - |-- port +#undef NO_CRYPT_TEST +#undef NO_CRYPT_BENCHMARK +#undef NO_WOLFSSL_CLIENT +#undef NO_WOLFSSL_SERVER ``` - 2. Remove these two platform specific assembly source files: - - wolfsslPort/wolfcrypt/src/aes_asm.asm - - wolfsslPort/wolfcrypt/src/aes_asm.S - 3. Launch the OpenArbor IDE as an administrator - 4. Create a DDC-I Deos example project. In the main menu, go to File >DDC-I Deos example project > socket > udp-vs-tcp - 5. Import the `wolfSSLPort` source code into your project. - - Right-click the ` udp-vs-tcp` project and choose File -> Import. - - Expand the General folder and select File System, then click Next. You should now see the Import File system dialog. - - Browse to the location containing the wolfSSL code and choose OK. Select the `wolfsslPort` folder and check the `Create top-level folder` button, then select Finish. You should see the folder hierarchy the same as wolfSSL folder structures. -6. Review the configuration in $(PROJECT_DIR)/wolfsslPort/IDE/ECLIPSE/DEOS/user_setting.h +1. Launch the OpenArbor IDE -7. Review the custom malloc/realloc/free configuration $(PROJECT_DIR)/wolfsslPort/IDE/ECLIPSE/DEOS/deos_malloc.c . Memory allocated with malloc() is never freed. +2. Create a DDC-I Deos example project. In the main menu, go to File > + DDC-I Deos example project > socket > udp-vs-tcp + +3. Customize your config/udp-vs-tcp.pd.xml with the following changes: -#### Configuring the Deos Project - 1. Customize your config/udp-vs-tcp.pd.xml with the following changes: ``` ``` -Depending on your configuration, wolfSSL uses upto four mutexes. You also need to configure enough memory for the stack of each threads and the process logical memory pool. +Depending on your configuration, wolfSSL uses upto four mutexes. You +also need to configure enough memory for the stack of each threads and +the process logical memory pool. + +4. Right click on the `udp-vs-tcp` project, select properties and add + the following macros in the DDC-I Options > C Compile > + Preprocessor + + * WOLFSSL_USER_SETTINGS + +5. Add the following directory paths in the DDC-I Options > C Compile > + Directories and in the DDC-I Options > C++ Compile > Directories + + * $(PROJECT_DIR.wolfssl)/../../../.. + * $(PROJECT_DIR.wolfssl)/.. + * $(PROJECT_DIR.printx)/code + +6. Add the following library dependencies in the + DDC-I Options > Deos > Dependencies + + * math + * ansi + * deos-time + + For benchmark and test code: + + * printx - You must add printx into your workspace, File >DDC-I + Deos example project > training > printx + +7. Edit $(PROJECT_DIR)/wolfsslPort/IDE/ECLIPSE/DEOS/user_setting.h to + customize your configuration. For example, you can undef or define + these tests. + + * `#undef NO_CRYPT_TEST` + * `#undef NO_CRYPT_BENCHMARK` + * `#undef NO_WOLFSSL_CLIENT` + * `#undef NO_WOLFSSL_SERVER` + +8. Edit your application source file where main() thread is defined +and add the following: + + * #include "printx.h" + * #include "tls_wolfssl.h" + * and a call to `wolfsslRunTests()` - 2. Right click on the `udp-vs-tcp` project, select properties and add the following macros in the DDC-I Options > C Compile > Preprocessor - - DEOS_ALLOW_OBSOLETE_DEFINITIONS - - WOLFSSL_USER_SETTINGS - 3. Add the following directory paths in the DDC-I Options > C Compile > Directories and in the DDC-I Options > C++ Compile > Directories - - $(PROJECT_DIR)/wolfsslPort - - $(PROJECT_DIR)/wolfsslPort/wolfssl - - $(PROJECT_DIR)/wolfsslPort/IDE/ECLIPSE/DEOS - - $(PROJECT_DIR.printx)/code - 4. Change the optimization level in the DDC-I Options > C Compile > Code Generation > Optimization level:g - - g - 5. Add the following library dependencies in the DDC-I Options > Deos > Dependencies - - math - - dart - - ansi - - printx - - You must add printx into your workspace, File >DDC-I Deos example project > training > printx - 6. Edit $(PROJECT_DIR)/wolfsslPort/IDE/ECLIPSE/DEOS/user_setting.h to customize your configuration. For example, you can undef or define these tests. - - #undef NO_CRYPT_TEST - - #undef NO_CRYPT_BENCHMARK - - #undef NO_WOLFSSL_CLIENT - - #undef NO_WOLFSSL_SERVER - 7. Edit your application source file where main() thread is defined and add the following: - - #include "printx.h" - - #include "tls_wolfssl.h" - - and a call to `wolfsslRunTests()` Here's an example: + ``` #include #include @@ -137,7 +149,10 @@ int main(void) } ``` - 8. Review $(PROJECT_DIR)/udp-vs-tcp/mailbox-transport.config configuration. + +9. Review `$(PROJECT_DIR)/udp-vs-tcp/mailbox-transport.config` + configuration. + ``` transportConfigurationId 2 # Client thread quota - for client and server TCP @@ -166,45 +181,62 @@ userServiceThread # Server thread template name / ``` - #### Building and Running - 1. Build your project, then load and run your image on a target platform. Review the test results on the console output. +#### Building and Running + +1. Build your project, then load and run your image on a target + platform. Review the test results on the console output. ### `wolfcrypt_test()` -wolfcrypt_test() prints a message on the target console similar to the following output: + +`wolfcrypt_test()` prints a message on similar to the following: + ``` error test passed! base64 test passed! asn test passed! ... ``` + This example doesn't show the whole output. ### `benchmark_test()` -benchmark_test() prints a message on the target console similar to the following output. + +`benchmark_test()` prints a message on the similar to the following: ``` ------------------------------------------------------------------------------ - wolfSSL version 3.15.5 +wolfSSL version 4.6.0 ------------------------------------------------------------------------------ wolfCrypt Benchmark (block bytes 1024, min 1.0 sec each) -RNG 225 KB tooks 1.026 seconds, 219.313 KB/s -AES-128-CBC-enc 250 KB toks 1.105 seconds 226.210 KB/s -AES-128-CBC-dec 225 KB tooks 1.005 seconds, 223.922 KB/s +RNG 2 MB took 1.000 seconds, 2.124 MB/s +AES-128-CBC-enc 5 MB took 1.000 seconds, 5.127 MB/s +AES-128-CBC-dec 5 MB took 1.000 seconds, 4.907 MB/s +AES-192-CBC-enc 5 MB took 1.000 seconds, 4.736 MB/s +AES-192-CBC-dec 5 MB took 1.000 seconds, 4.761 MB/s ... ``` + This example doesn't show the whole output. ### `wolfssl_client_test()` -You can modify the `TCP_SERVER_IP_ADDR` and `TCP_SERVER_PORT` macros in the `tls_wolfssl.c` file to configure the host address and port. You will also need to define the server certificate. The example client uses the GET request to get a web resource from the server at https://google.com. +You can modify the `TCP_SERVER_IP_ADDR` and `TCP_SERVER_PORT` macros +in the `tls_wolfssl.c` file to configure the host address and +port. You will also need to define the server certificate. The example +client uses the GET request to get a web resource from the server at +https://google.com. ### `wolfssl_server_test()` -You can modify the `TLS_SERVER_PORT` in the `tls_wolfssl.c` file to configure the port number to listen on a local-host. -Once you start the TLS server and `Listening for client connection` displays on the serial console, the server is ready to accept client connections. +You can modify the `TLS_SERVER_PORT` in the `tls_wolfssl.c` file to +configure the port number to listen on a local-host. Once you start +the TLS server and `Listening for client connection` displays on the +serial console, the server is ready to accept client connections. + +You can connect to the server using the wolfssl TLS client example +from your Linux or Windows host as follows: -You can connect to the server using the wolfssl TLS client example from your Linux or Windows host as follows: ``` $ ./examples/client/client.exe -h TLS_SERVER_IP_ADDRESS @@ -218,8 +250,10 @@ I hear ya fa shizzle! ## References -The test results were collected from the qemu-x86 reference platform target with the following software and tool chains: -- OpenArbor, eclipse based IDE, toolVersion = "3.31.0" +The following software and tool chains were used for testing: + +- OpenArbor 7.0.0 - wolfssl [latest version](https://github.com/wolfSSL/wolfssl) -For more information or questions, please email [support@wolfssl.com](mailto:support@wolfssl.com) +For more information or questions, please email +[support@wolfssl.com](mailto:support@wolfssl.com) diff --git a/IDE/ECLIPSE/DEOS/deos_malloc.c b/IDE/ECLIPSE/DEOS/deos_malloc.c index e8b213001..f56dd5620 100644 --- a/IDE/ECLIPSE/DEOS/deos_malloc.c +++ b/IDE/ECLIPSE/DEOS/deos_malloc.c @@ -1,6 +1,6 @@ /* deos_malloc.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,27 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include -#include - -#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) -#define SIZEOF_HEADER sizeof(size_t) /* tracks size of allocated block */ - -#define HEAP_SIZE_MAX (1*1024*1024) - -static size_t allocatedMemory = 0; - -size_t getMemAllocatedSize_deos(size_t* size){ - - if (size) - *size = allocatedMemory; - - return allocatedMemory; -} - -/* Simply returns without freeing any memory. */ +#include +#include void free_deos(void *ptr) { - //printf("fake free_deos()\n"); + free(ptr); return; } @@ -51,10 +35,6 @@ void *realloc_deos(void *ptr, size_t size) { newptr = malloc_deos(size); if (ptr != NULL && newptr != NULL) { - - if ( *((char *)ptr - SIZEOF_HEADER) < *((char *)newptr - SIZEOF_HEADER)) - size = *((char *)ptr - SIZEOF_HEADER); - XMEMCPY((char *) newptr, (const char *) ptr, size); free_deos(ptr); } @@ -63,46 +43,5 @@ void *realloc_deos(void *ptr, size_t size) { } void *malloc_deos(size_t size) { - PDEOS_SYSTEM_INFO systemInfoPtr; - static VirtualAddressTYP heapAddr = NULL; - static VirtualAddressTYP freeAddr = NULL; - VirtualAddressTYP retAddr = NULL; - DWORD allocationSize = 0; - static int initialized = 0; - - if (size <= 0) - return NULL; - - if (!initialized) { - systemInfoPtr = (PDEOS_SYSTEM_INFO)getSystemInfoDEOS(); - freeAddr = (VirtualAddressTYP)getNextLibraryStartAddress(); - allocationSize = (((HEAP_SIZE_MAX - 1) / systemInfoPtr->dwPageSize) + 1) * - systemInfoPtr->dwPageSize; - - if (virtualAllocDEOS(freeAddr, allocationSize) != allocSuccess){ - printf("ERROR: virtualAllocDEOS failed\n"); - return NULL; - } - - setNextLibraryStartAddress(freeAddr + allocationSize); - heapAddr = freeAddr; - - initialized = 1; - } - - size = ROUND_UP(size, sizeof(size_t)); - - if ((size + SIZEOF_HEADER) > (HEAP_SIZE_MAX - (freeAddr - heapAddr))){ - printf("ERROR: malloc_deos cannot allocate from heap memory anymore\n"); - return NULL; - } - - *freeAddr = size; - freeAddr += SIZEOF_HEADER; - retAddr = freeAddr; - XMEMSET(retAddr, 0, size); - freeAddr += size; - allocatedMemory += size; - - return retAddr; + return malloc(size); } diff --git a/IDE/ECLIPSE/DEOS/deos_wolfssl/.cproject b/IDE/ECLIPSE/DEOS/deos_wolfssl/.cproject new file mode 100644 index 000000000..48ac73bc1 --- /dev/null +++ b/IDE/ECLIPSE/DEOS/deos_wolfssl/.cproject @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/ECLIPSE/DEOS/deos_wolfssl/.options b/IDE/ECLIPSE/DEOS/deos_wolfssl/.options new file mode 100644 index 000000000..eb9d4aeb7 --- /dev/null +++ b/IDE/ECLIPSE/DEOS/deos_wolfssl/.options @@ -0,0 +1,36 @@ + + + 26 + ppc + diagnostic + kernel + video + ansi + math + deos-time + sal + mtl + printx + gnu-language + lib$(PROJECT_NAME).so + $(BINARY) + $(BINARY).dbg + $(DESK_DIR)/arm/include + $(DESK_DIR)/ppc/include + $(DESK_DIR)/x86/include + $(DESK_DIR)/include + $(PROJECT_DIR)/../../../.. + $(PROJECT_DIR)/../../../../fips + $(PROJECT_DIR)/.. + $(PROJECT_DIR.printx)/code + WOLFSSL_USER_SETTINGS + $(DESK_DIR)/arm/appbin + $(DESK_DIR)/ppc/appbin + $(DESK_DIR)/x86/appbin + true + -L $(PROJECT_DIR.printx)/output/powerpc-motorola-elf/diagnostic + none + fips.c + fips_test.c + selftest.c + diff --git a/IDE/ECLIPSE/DEOS/deos_wolfssl/.project b/IDE/ECLIPSE/DEOS/deos_wolfssl/.project new file mode 100644 index 000000000..769c9630e --- /dev/null +++ b/IDE/ECLIPSE/DEOS/deos_wolfssl/.project @@ -0,0 +1,629 @@ + + + wolfssl + + + + + + com.ddci.common.ide.Builder + + + + + + com.ddci.common.ide.DdciNature + com.ddci.common.ide.ExecutableNature + com.ddci.deos.common.deosLoadListNature + com.ddci.common.ide.DEOS_SHARED_OBJECT + org.eclipse.cdt.core.cnature + + + + deos_malloc.c + 1 + WOLFSSL_ROOT/IDE/ECLIPSE/DEOS/deos_malloc.c + + + fips.c + 1 + WOLFSSL_ROOT/fips/fips.c + + + fips_test.c + 1 + WOLFSSL_ROOT/fips/fips_test.c + + + selftest.c + 1 + WOLFSSL_ROOT/fips/selftest.c + + + user_settings.h + 1 + WOLFSSL_ROOT/IDE/ECLIPSE/DEOS/user_settings.h + + + wolfssl + 2 + WOLFSSL_ROOT/wolfssl + + + src/crl.c + 1 + WOLFSSL_ROOT/src/crl.c + + + src/internal.c + 1 + WOLFSSL_ROOT/src/internal.c + + + src/keys.c + 1 + WOLFSSL_ROOT/src/keys.c + + + src/ocsp.c + 1 + WOLFSSL_ROOT/src/ocsp.c + + + src/sniffer.c + 1 + WOLFSSL_ROOT/src/sniffer.c + + + src/ssl.c + 1 + WOLFSSL_ROOT/src/ssl.c + + + src/tls.c + 1 + WOLFSSL_ROOT/src/tls.c + + + src/tls13.c + 1 + WOLFSSL_ROOT/src/tls13.c + + + src/wolfio.c + 1 + WOLFSSL_ROOT/src/wolfio.c + + + wolfcrypt/benchmark + 2 + WOLFSSL_ROOT/wolfcrypt/benchmark + + + wolfcrypt/test + 2 + WOLFSSL_ROOT/wolfcrypt/test + + + wolfcrypt/src/aes.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/aes.c + + + wolfcrypt/src/arc4.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/arc4.c + + + wolfcrypt/src/asm.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/asm.c + + + wolfcrypt/src/asn.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/asn.c + + + wolfcrypt/src/blake2b.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/blake2b.c + + + wolfcrypt/src/blake2s.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/blake2s.c + + + wolfcrypt/src/camellia.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/camellia.c + + + wolfcrypt/src/chacha.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/chacha.c + + + wolfcrypt/src/chacha20_poly1305.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/chacha20_poly1305.c + + + wolfcrypt/src/cmac.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/cmac.c + + + wolfcrypt/src/coding.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/coding.c + + + wolfcrypt/src/compress.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/compress.c + + + wolfcrypt/src/cpuid.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/cpuid.c + + + wolfcrypt/src/cryptocb.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/cryptocb.c + + + wolfcrypt/src/curve25519.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/curve25519.c + + + wolfcrypt/src/curve448.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/curve448.c + + + wolfcrypt/src/des3.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/des3.c + + + wolfcrypt/src/dh.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/dh.c + + + wolfcrypt/src/dsa.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/dsa.c + + + wolfcrypt/src/ecc.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ecc.c + + + wolfcrypt/src/ecc_fp.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ecc_fp.c + + + wolfcrypt/src/ed25519.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ed25519.c + + + wolfcrypt/src/ed448.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ed448.c + + + wolfcrypt/src/error.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/error.c + + + wolfcrypt/src/fe_448.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/fe_448.c + + + wolfcrypt/src/fe_low_mem.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/fe_low_mem.c + + + wolfcrypt/src/fe_operations.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/fe_operations.c + + + wolfcrypt/src/fe_x25519_128.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fe_x25519_128.i + + + wolfcrypt/src/fp_mont_small.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mont_small.i + + + wolfcrypt/src/fp_mul_comba_12.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_12.i + + + wolfcrypt/src/fp_mul_comba_17.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_17.i + + + wolfcrypt/src/fp_mul_comba_20.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_20.i + + + wolfcrypt/src/fp_mul_comba_24.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_24.i + + + wolfcrypt/src/fp_mul_comba_28.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_28.i + + + wolfcrypt/src/fp_mul_comba_3.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_3.i + + + wolfcrypt/src/fp_mul_comba_32.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_32.i + + + wolfcrypt/src/fp_mul_comba_4.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_4.i + + + wolfcrypt/src/fp_mul_comba_48.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_48.i + + + wolfcrypt/src/fp_mul_comba_6.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_6.i + + + wolfcrypt/src/fp_mul_comba_64.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_64.i + + + wolfcrypt/src/fp_mul_comba_7.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_7.i + + + wolfcrypt/src/fp_mul_comba_8.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_8.i + + + wolfcrypt/src/fp_mul_comba_9.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_9.i + + + wolfcrypt/src/fp_mul_comba_small_set.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_mul_comba_small_set.i + + + wolfcrypt/src/fp_sqr_comba_12.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_12.i + + + wolfcrypt/src/fp_sqr_comba_17.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_17.i + + + wolfcrypt/src/fp_sqr_comba_20.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_20.i + + + wolfcrypt/src/fp_sqr_comba_24.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_24.i + + + wolfcrypt/src/fp_sqr_comba_28.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_28.i + + + wolfcrypt/src/fp_sqr_comba_3.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_3.i + + + wolfcrypt/src/fp_sqr_comba_32.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_32.i + + + wolfcrypt/src/fp_sqr_comba_4.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_4.i + + + wolfcrypt/src/fp_sqr_comba_48.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_48.i + + + wolfcrypt/src/fp_sqr_comba_6.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_6.i + + + wolfcrypt/src/fp_sqr_comba_64.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_64.i + + + wolfcrypt/src/fp_sqr_comba_7.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_7.i + + + wolfcrypt/src/fp_sqr_comba_8.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_8.i + + + wolfcrypt/src/fp_sqr_comba_9.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_9.i + + + wolfcrypt/src/fp_sqr_comba_small_set.i + 1 + WOLFSSL_ROOT/wolfcrypt/src/fp_sqr_comba_small_set.i + + + wolfcrypt/src/ge_448.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ge_448.c + + + wolfcrypt/src/ge_low_mem.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ge_low_mem.c + + + wolfcrypt/src/ge_operations.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ge_operations.c + + + wolfcrypt/src/hash.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/hash.c + + + wolfcrypt/src/hc128.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/hc128.c + + + wolfcrypt/src/hmac.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/hmac.c + + + wolfcrypt/src/idea.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/idea.c + + + wolfcrypt/src/integer.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/integer.c + + + wolfcrypt/src/logging.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/logging.c + + + wolfcrypt/src/md2.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/md2.c + + + wolfcrypt/src/md4.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/md4.c + + + wolfcrypt/src/md5.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/md5.c + + + wolfcrypt/src/memory.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/memory.c + + + wolfcrypt/src/pkcs12.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/pkcs12.c + + + wolfcrypt/src/pkcs7.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/pkcs7.c + + + wolfcrypt/src/poly1305.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/poly1305.c + + + wolfcrypt/src/pwdbased.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/pwdbased.c + + + wolfcrypt/src/rabbit.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/rabbit.c + + + wolfcrypt/src/random.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/random.c + + + wolfcrypt/src/rc2.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/rc2.c + + + wolfcrypt/src/ripemd.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/ripemd.c + + + wolfcrypt/src/rsa.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/rsa.c + + + wolfcrypt/src/sha.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sha.c + + + wolfcrypt/src/sha256.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sha256.c + + + wolfcrypt/src/sha3.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sha3.c + + + wolfcrypt/src/sha512.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sha512.c + + + wolfcrypt/src/signature.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/signature.c + + + wolfcrypt/src/sp_arm32.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_arm32.c + + + wolfcrypt/src/sp_arm64.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_arm64.c + + + wolfcrypt/src/sp_armthumb.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_armthumb.c + + + wolfcrypt/src/sp_c32.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_c32.c + + + wolfcrypt/src/sp_c64.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_c64.c + + + wolfcrypt/src/sp_cortexm.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_cortexm.c + + + wolfcrypt/src/sp_dsp32.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_dsp32.c + + + wolfcrypt/src/sp_int.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_int.c + + + wolfcrypt/src/sp_x86_64.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/sp_x86_64.c + + + wolfcrypt/src/srp.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/srp.c + + + wolfcrypt/src/tfm.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/tfm.c + + + wolfcrypt/src/wc_dsp.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/wc_dsp.c + + + wolfcrypt/src/wc_encrypt.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/wc_encrypt.c + + + wolfcrypt/src/wc_pkcs11.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/wc_pkcs11.c + + + wolfcrypt/src/wc_port.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/wc_port.c + + + wolfcrypt/src/wolfevent.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/wolfevent.c + + + wolfcrypt/src/wolfmath.c + 1 + WOLFSSL_ROOT/wolfcrypt/src/wolfmath.c + + + + + WOLFSSL_ROOT + $%7BPARENT-4-PROJECT_LOC%7D + + + diff --git a/IDE/ECLIPSE/DEOS/include.am b/IDE/ECLIPSE/DEOS/include.am index 14a71c89b..88dc9a3ff 100644 --- a/IDE/ECLIPSE/DEOS/include.am +++ b/IDE/ECLIPSE/DEOS/include.am @@ -7,4 +7,7 @@ EXTRA_DIST += \ IDE/ECLIPSE/DEOS/user_settings.h \ IDE/ECLIPSE/DEOS/tls_wolfssl.h \ IDE/ECLIPSE/DEOS/tls_wolfssl.c \ - IDE/ECLIPSE/DEOS/deos_malloc.c \ No newline at end of file + IDE/ECLIPSE/DEOS/deos_malloc.c \ + IDE/ECLIPSE/DEOS/deos_wolfssl/.cproject \ + IDE/ECLIPSE/DEOS/deos_wolfssl/.options \ + IDE/ECLIPSE/DEOS/deos_wolfssl/.project diff --git a/IDE/ECLIPSE/DEOS/tls_wolfssl.c b/IDE/ECLIPSE/DEOS/tls_wolfssl.c index 1abf5526d..18a0cf005 100644 --- a/IDE/ECLIPSE/DEOS/tls_wolfssl.c +++ b/IDE/ECLIPSE/DEOS/tls_wolfssl.c @@ -1,6 +1,6 @@ /* tls_wolfssl.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/DEOS/tls_wolfssl.h b/IDE/ECLIPSE/DEOS/tls_wolfssl.h index 062826fba..d54205b42 100644 --- a/IDE/ECLIPSE/DEOS/tls_wolfssl.h +++ b/IDE/ECLIPSE/DEOS/tls_wolfssl.h @@ -1,6 +1,6 @@ /* tls_wolfssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/DEOS/user_settings.h b/IDE/ECLIPSE/DEOS/user_settings.h index 5283e3d8a..5f74bc563 100644 --- a/IDE/ECLIPSE/DEOS/user_settings.h +++ b/IDE/ECLIPSE/DEOS/user_settings.h @@ -1,6 +1,6 @@ /* user_setting.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -65,6 +65,8 @@ You can get the current time from https://www.unixtimestamp.com/ #define HAVE_ED25519 #define ED25519_SMALL +#define WOLFSSL_DTLS + /* TLS 1.3 */ #if 0 #define WOLFSSL_TLS13 @@ -103,8 +105,6 @@ You can get the current time from https://www.unixtimestamp.com/ #endif -#define printf printx - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/IDE/ECLIPSE/MICRIUM/client_wolfssl.c b/IDE/ECLIPSE/MICRIUM/client_wolfssl.c index 241eb1df9..4e28a92eb 100644 --- a/IDE/ECLIPSE/MICRIUM/client_wolfssl.c +++ b/IDE/ECLIPSE/MICRIUM/client_wolfssl.c @@ -1,6 +1,6 @@ /* client_wolfssl.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/MICRIUM/client_wolfssl.h b/IDE/ECLIPSE/MICRIUM/client_wolfssl.h index e95f818ec..e1600674f 100644 --- a/IDE/ECLIPSE/MICRIUM/client_wolfssl.h +++ b/IDE/ECLIPSE/MICRIUM/client_wolfssl.h @@ -1,6 +1,6 @@ /* client_wolfssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/MICRIUM/server_wolfssl.c b/IDE/ECLIPSE/MICRIUM/server_wolfssl.c index a8d0a8232..20fe49073 100644 --- a/IDE/ECLIPSE/MICRIUM/server_wolfssl.c +++ b/IDE/ECLIPSE/MICRIUM/server_wolfssl.c @@ -1,6 +1,6 @@ /* server_wolfssl.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/MICRIUM/server_wolfssl.h b/IDE/ECLIPSE/MICRIUM/server_wolfssl.h index c75e1b927..f338db11f 100644 --- a/IDE/ECLIPSE/MICRIUM/server_wolfssl.h +++ b/IDE/ECLIPSE/MICRIUM/server_wolfssl.h @@ -1,6 +1,6 @@ /* server_wolfssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/MICRIUM/user_settings.h b/IDE/ECLIPSE/MICRIUM/user_settings.h index affd9d9ca..154a67714 100644 --- a/IDE/ECLIPSE/MICRIUM/user_settings.h +++ b/IDE/ECLIPSE/MICRIUM/user_settings.h @@ -1,6 +1,6 @@ /* user_setting.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/MICRIUM/wolfsslRunTests.c b/IDE/ECLIPSE/MICRIUM/wolfsslRunTests.c index 84f02b254..538484d49 100644 --- a/IDE/ECLIPSE/MICRIUM/wolfsslRunTests.c +++ b/IDE/ECLIPSE/MICRIUM/wolfsslRunTests.c @@ -1,6 +1,6 @@ /* wolfsslRunTests.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/RTTHREAD/user_settings.h b/IDE/ECLIPSE/RTTHREAD/user_settings.h index f28c968c6..9ea3951ab 100644 --- a/IDE/ECLIPSE/RTTHREAD/user_settings.h +++ b/IDE/ECLIPSE/RTTHREAD/user_settings.h @@ -1,6 +1,6 @@ /* user_setting.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ECLIPSE/RTTHREAD/wolfssl_test.c b/IDE/ECLIPSE/RTTHREAD/wolfssl_test.c index 0dce7d0d0..7268303fd 100644 --- a/IDE/ECLIPSE/RTTHREAD/wolfssl_test.c +++ b/IDE/ECLIPSE/RTTHREAD/wolfssl_test.c @@ -1,6 +1,6 @@ /* wolfsslRunTests.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Espressif/ESP-IDF/dummy_config_h b/IDE/Espressif/ESP-IDF/dummy_config_h index 8d42a0cbf..74a682e85 100644 --- a/IDE/Espressif/ESP-IDF/dummy_config_h +++ b/IDE/Espressif/ESP-IDF/dummy_config_h @@ -1,6 +1,6 @@ /* config.h - dummy * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/main/helper.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/main/helper.c index f2084a87d..0aa8631b5 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/main/helper.c +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/main/helper.c @@ -1,6 +1,6 @@ /* helper.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -118,7 +118,7 @@ int construct_argv() __argv[cnt] = malloc(10); sprintf(__argv[cnt], "benchmark"); - __argv[9] = '\0'; + __argv[cnt][9] = '\0'; cnt = 1; while (*ch != '\0') diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/client-tls.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/client-tls.c index 64730aa77..1a4d20a6c 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/client-tls.c +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/client-tls.c @@ -1,6 +1,6 @@ /* client-tls-callback.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/include/wifi_connect.h b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/include/wifi_connect.h index 8212b30e3..ab7de663b 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/include/wifi_connect.h +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/include/wifi_connect.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/wifi_connect.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/wifi_connect.c index f4758c6ec..a79ab29e2 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/wifi_connect.c +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/main/wifi_connect.c @@ -1,6 +1,6 @@ /* wifi_connect.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -51,10 +51,10 @@ static void set_time() time_t now; struct tm timeinfo; char strftime_buf[64]; - /* please update the time if seeing unknown failure. */ - /* this could cause TLS communication failure due to time expiration */ - /* incleasing 31536000 seconds is close to spend 356 days. */ - utctime.tv_sec = 1598661910; /* dummy time: Fri Aug 29 09:45:00 2020 */ + /* please update the time if seeing unknown failure when loading cert. */ + /* this could cause TLS communication failure due to time expiration */ + /* incleasing 31536000 seconds is close to spend 356 days. */ + utctime.tv_sec = 1619650800; /* dummy time: Wed April 28 23:00:00 2021 */ utctime.tv_usec = 0; tz.tz_minuteswest = 0; tz.tz_dsttime = 0; diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/include/wifi_connect.h b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/include/wifi_connect.h index 948173572..5dd9625ee 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/include/wifi_connect.h +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/include/wifi_connect.h @@ -1,6 +1,6 @@ /* wifi_connect.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/server-tls.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/server-tls.c index a3beca538..c31e21855 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/server-tls.c +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/server-tls.c @@ -1,6 +1,6 @@ /* server-tls-callback.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/wifi_connect.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/wifi_connect.c index 3848fbfe9..5048e9f6e 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/wifi_connect.c +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/main/wifi_connect.c @@ -1,6 +1,6 @@ /* wifi_connect.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -48,10 +48,10 @@ static void set_time() time_t now; struct tm timeinfo; char strftime_buf[64]; - /* please update the time if seeing unknown failure. */ - /* this could cause TLS communication failure due to time expiration */ - /* incleasing 31536000 seconds is close to spend 356 days. */ - utctime.tv_sec = 1598661910; /* dummy time: Fri Aug 29 09:45:00 2020 */ + /* please update the time if seeing unknown failure when loading cert. */ + /* this could cause TLS communication failure due to time expiration */ + /* incleasing 31536000 seconds is close to spend 356 days. */ + utctime.tv_sec = 1619650800; /* dummy time: Wed April 28 23:00:00 2021 */ utctime.tv_usec = 0; tz.tz_minuteswest = 0; tz.tz_dsttime = 0; diff --git a/IDE/Espressif/ESP-IDF/setup_win.bat b/IDE/Espressif/ESP-IDF/setup_win.bat index adbf55b86..6aebad485 100644 --- a/IDE/Espressif/ESP-IDF/setup_win.bat +++ b/IDE/Espressif/ESP-IDF/setup_win.bat @@ -32,10 +32,10 @@ xcopy /Y/Q %BASEDIR%\src\*.c %WOLFSSLLIB_TRG_DIR%\src\ xcopy /Y/Q %BASEDIR%\wolfcrypt\src\*.c %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src xcopy /Y/Q %BASEDIR%\wolfcrypt\src\*.i %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src xcopy /E/Y/Q %BASEDIR%\wolfcrypt\src\port %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\port\ -xcopy /E/Y/Q %BASEDIR%\wolfcrypt\test\ %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\ -xcopy /E/Y/Q %BASEDIR%\wolfcrypt\benchmark\ %WOLFSSLLIB_TRG_DIR%\wolfcrypt\benchmark\ +xcopy /E/Y/Q %BASEDIR%\wolfcrypt\test %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\ +xcopy /E/Y/Q %BASEDIR%\wolfcrypt\benchmark %WOLFSSLLIB_TRG_DIR%\wolfcrypt\benchmark\ xcopy /Y/Q %BASEDIR%\wolfssl\*.h %WOLFSSLLIB_TRG_DIR%\wolfssl\ -xcopy /E/Y/Q %BASEDIR%\wolfssl\wolfcrypt\ %WOLFSSLLIB_TRG_DIR%\wolfssl\wolfcrypt\ +xcopy /E/Y/Q %BASEDIR%\wolfssl\wolfcrypt %WOLFSSLLIB_TRG_DIR%\wolfssl\wolfcrypt\ rem user_settings.h xcopy /F/Q %WOLFSSL_ESPIDFDIR%\user_settings.h %WOLFSSLLIB_TRG_DIR%\include\ diff --git a/IDE/Espressif/ESP-IDF/test/test_wolfssl.c b/IDE/Espressif/ESP-IDF/test/test_wolfssl.c index b1cb8bd4c..f7db98dc7 100644 --- a/IDE/Espressif/ESP-IDF/test/test_wolfssl.c +++ b/IDE/Espressif/ESP-IDF/test/test_wolfssl.c @@ -666,7 +666,7 @@ TEST_CASE("wolfssl sha crypt-test", "[wolfssl]") ESP_LOGI(TAG, "sha256_test()"); TEST_ASSERT_EQUAL(0, sha256_test()); #endif -#ifdef WOLSSL_SHA384 +#ifdef WOLFSSL_SHA384 ESP_LOGI(TAG, "sha384_test()"); TEST_ASSERT_EQUAL(0, sha384_test()); #endif diff --git a/IDE/Espressif/ESP-IDF/user_settings.h b/IDE/Espressif/ESP-IDF/user_settings.h index 67b2d4391..2e6252322 100644 --- a/IDE/Espressif/ESP-IDF/user_settings.h +++ b/IDE/Espressif/ESP-IDF/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/GCC-ARM/Header/user_settings.h b/IDE/GCC-ARM/Header/user_settings.h index dff00b0d9..c3b61925f 100644 --- a/IDE/GCC-ARM/Header/user_settings.h +++ b/IDE/GCC-ARM/Header/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/GCC-ARM/Source/armtarget.c b/IDE/GCC-ARM/Source/armtarget.c index 8b276463f..c718c6ba5 100644 --- a/IDE/GCC-ARM/Source/armtarget.c +++ b/IDE/GCC-ARM/Source/armtarget.c @@ -1,6 +1,6 @@ /* armtarget.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/GCC-ARM/Source/benchmark_main.c b/IDE/GCC-ARM/Source/benchmark_main.c index 7f91e7ccb..d6d610fd0 100644 --- a/IDE/GCC-ARM/Source/benchmark_main.c +++ b/IDE/GCC-ARM/Source/benchmark_main.c @@ -1,6 +1,6 @@ /* benchmark_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/GCC-ARM/Source/test_main.c b/IDE/GCC-ARM/Source/test_main.c index d3d525a76..9320c57c5 100644 --- a/IDE/GCC-ARM/Source/test_main.c +++ b/IDE/GCC-ARM/Source/test_main.c @@ -1,6 +1,6 @@ /* test_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/GCC-ARM/Source/tls_client.c b/IDE/GCC-ARM/Source/tls_client.c index 43c0b73f9..66ea21626 100644 --- a/IDE/GCC-ARM/Source/tls_client.c +++ b/IDE/GCC-ARM/Source/tls_client.c @@ -1,6 +1,6 @@ /* tls_client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/GCC-ARM/Source/wolf_main.c b/IDE/GCC-ARM/Source/wolf_main.c index de1ec7adf..c47b0cec6 100644 --- a/IDE/GCC-ARM/Source/wolf_main.c +++ b/IDE/GCC-ARM/Source/wolf_main.c @@ -1,6 +1,6 @@ /* wolf_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/HEXAGON/DSP/Makefile b/IDE/HEXAGON/DSP/Makefile index 1cf0ccb0d..42022dda3 100644 --- a/IDE/HEXAGON/DSP/Makefile +++ b/IDE/HEXAGON/DSP/Makefile @@ -1,6 +1,6 @@ # Makefile # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +#/ ENVI=hexagon diff --git a/IDE/HEXAGON/Makefile b/IDE/HEXAGON/Makefile index 87ed33cd4..11dea412b 100644 --- a/IDE/HEXAGON/Makefile +++ b/IDE/HEXAGON/Makefile @@ -1,6 +1,6 @@ # Makefile # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +#/ ENVI=UbuntuARM diff --git a/IDE/HEXAGON/ecc-verify-benchmark.c b/IDE/HEXAGON/ecc-verify-benchmark.c index a9e7ad8d6..6bc183fed 100644 --- a/IDE/HEXAGON/ecc-verify-benchmark.c +++ b/IDE/HEXAGON/ecc-verify-benchmark.c @@ -1,6 +1,6 @@ /* ecc-verify-benchmark.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/HEXAGON/ecc-verify.c b/IDE/HEXAGON/ecc-verify.c index 835301c75..0ffed79ad 100644 --- a/IDE/HEXAGON/ecc-verify.c +++ b/IDE/HEXAGON/ecc-verify.c @@ -1,6 +1,6 @@ /* ecc-verify.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c b/IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c index 49acf8060..44016be28 100644 --- a/IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c +++ b/IDE/IAR-EWARM/Projects/benchmark/benchmark-main.c @@ -1,6 +1,6 @@ /* benchmark-main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/IAR-EWARM/Projects/benchmark/current_time.c b/IDE/IAR-EWARM/Projects/benchmark/current_time.c index 1e96a0bca..1fbc1d17f 100644 --- a/IDE/IAR-EWARM/Projects/benchmark/current_time.c +++ b/IDE/IAR-EWARM/Projects/benchmark/current_time.c @@ -1,6 +1,6 @@ /* current-time.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/IAR-EWARM/Projects/common/minimum-startup.c b/IDE/IAR-EWARM/Projects/common/minimum-startup.c index 3fbff1166..01ceaa51c 100644 --- a/IDE/IAR-EWARM/Projects/common/minimum-startup.c +++ b/IDE/IAR-EWARM/Projects/common/minimum-startup.c @@ -1,6 +1,6 @@ /* minimum-startup.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/IAR-EWARM/Projects/test/test-main.c b/IDE/IAR-EWARM/Projects/test/test-main.c index 28c1a01e2..4b1b61430 100644 --- a/IDE/IAR-EWARM/Projects/test/test-main.c +++ b/IDE/IAR-EWARM/Projects/test/test-main.c @@ -1,6 +1,6 @@ /* test-main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/INTIME-RTOS/user_settings.h b/IDE/INTIME-RTOS/user_settings.h index 8458f3814..529dad4d1 100644 --- a/IDE/INTIME-RTOS/user_settings.h +++ b/IDE/INTIME-RTOS/user_settings.h @@ -14,7 +14,7 @@ extern "C" { #define INTIME_RTOS #undef WOLF_EXAMPLES_STACK -#define WOLF_EXAMPLES_STACK 65536 +#define WOLF_EXAMPLES_STACK (1<<17) #undef WOLFSSL_GENERAL_ALIGNMENT #define WOLFSSL_GENERAL_ALIGNMENT 4 @@ -27,7 +27,7 @@ extern "C" { /* disable directory support */ #undef NO_WOLFSSL_DIR -#define NO_WOLFSSL_DIR +//#define NO_WOLFSSL_DIR /* disable writev */ #undef NO_WRITEV diff --git a/IDE/INTIME-RTOS/wolfExamples.vcxproj b/IDE/INTIME-RTOS/wolfExamples.vcxproj index 81b1e6d4f..f650244c0 100755 --- a/IDE/INTIME-RTOS/wolfExamples.vcxproj +++ b/IDE/INTIME-RTOS/wolfExamples.vcxproj @@ -66,7 +66,7 @@ Async - WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + WOLFSSL_USER_SETTINGS;_USE_64BIT_TIME_T;%(PreprocessorDefinitions) $(ProjectDir);$(ProjectDir)..\..\;%(AdditionalIncludeDirectories) diff --git a/IDE/LPCXPRESSO/lib_wolfssl/lpc_18xx_port.c b/IDE/LPCXPRESSO/lib_wolfssl/lpc_18xx_port.c index c02496838..810e5cf83 100644 --- a/IDE/LPCXPRESSO/lib_wolfssl/lpc_18xx_port.c +++ b/IDE/LPCXPRESSO/lib_wolfssl/lpc_18xx_port.c @@ -1,6 +1,6 @@ /* lpc_18xx_port.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/LPCXPRESSO/wolf_example/src/lpc_18xx_startup.c b/IDE/LPCXPRESSO/wolf_example/src/lpc_18xx_startup.c index ef7432167..e5b722c4f 100644 --- a/IDE/LPCXPRESSO/wolf_example/src/lpc_18xx_startup.c +++ b/IDE/LPCXPRESSO/wolf_example/src/lpc_18xx_startup.c @@ -1,6 +1,6 @@ /* lpc_18xx_startup.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/M68K/benchmark/main.cpp b/IDE/M68K/benchmark/main.cpp index 7a42ae48f..b66b805f6 100644 --- a/IDE/M68K/benchmark/main.cpp +++ b/IDE/M68K/benchmark/main.cpp @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/M68K/testwolfcrypt/main.cpp b/IDE/M68K/testwolfcrypt/main.cpp index 90f894a32..6380bd782 100644 --- a/IDE/M68K/testwolfcrypt/main.cpp +++ b/IDE/M68K/testwolfcrypt/main.cpp @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/LPC43xx/time-LCP43xx.c b/IDE/MDK-ARM/LPC43xx/time-LCP43xx.c index 3cdf214d7..150415861 100644 --- a/IDE/MDK-ARM/LPC43xx/time-LCP43xx.c +++ b/IDE/MDK-ARM/LPC43xx/time-LCP43xx.c @@ -1,6 +1,6 @@ /* time.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/cert_data.c b/IDE/MDK-ARM/MDK-ARM/wolfSSL/cert_data.c index a094bb1dd..5b7402f57 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/cert_data.c +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/cert_data.c @@ -1,6 +1,6 @@ /* certs_test.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-BARE-METAL.h b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-BARE-METAL.h index 21974401e..4a1e452fc 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-BARE-METAL.h +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-BARE-METAL.h @@ -1,6 +1,6 @@ /* config-BEREFOOT.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-FS.h b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-FS.h index daeb75b88..b77821155 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-FS.h +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-FS.h @@ -1,6 +1,6 @@ /* config-FS.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-RTX-TCP-FS.h b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-RTX-TCP-FS.h index 193eb2531..626a1c348 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-RTX-TCP-FS.h +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config-RTX-TCP-FS.h @@ -1,6 +1,6 @@ /* config-RTX-TCP-FS.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config.h b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config.h index de37fa143..fba3347eb 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/config.h +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/config.h @@ -1,6 +1,6 @@ /* config.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/main.c b/IDE/MDK-ARM/MDK-ARM/wolfSSL/main.c index fab05b7e8..fd43e40cf 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/main.c +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/shell.c b/IDE/MDK-ARM/MDK-ARM/wolfSSL/shell.c index fad4ec34b..0b8bf4063 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/shell.c +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/shell.c @@ -1,6 +1,6 @@ /*shell.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-CortexM3-4.c b/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-CortexM3-4.c index ed6b53d97..a057f6d63 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-CortexM3-4.c +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-CortexM3-4.c @@ -1,6 +1,6 @@ /* time-STM32F2.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-dummy.c b/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-dummy.c index b934398f1..07c8bb682 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-dummy.c +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/time-dummy.c @@ -1,6 +1,6 @@ /* time-dummy.c.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.c b/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.c index 7158af50d..6a9a345d3 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.c +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.c @@ -1,6 +1,6 @@ /* wolfssl_KEIL_RL.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -197,6 +197,7 @@ FILE * wolfSSL_fopen(const char *name, const char *openmode) #define PATHSIZE 100 char path[PATHSIZE] ; char *p ; + if (name == NULL) return NULL; if(strlen(name) > PATHSIZE)return(NULL) ; for(i = 0; i<= strlen(name); i++) { diff --git a/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.h b/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.h index b334a45e0..6a2165fab 100644 --- a/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.h +++ b/IDE/MDK-ARM/MDK-ARM/wolfSSL/wolfssl_MDK_ARM.h @@ -1,6 +1,6 @@ /* wolfssl_KEIL_RL.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/time-STM32F2xx.c b/IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/time-STM32F2xx.c index 6480e10cc..8a2ce67b8 100644 --- a/IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/time-STM32F2xx.c +++ b/IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/time-STM32F2xx.c @@ -1,6 +1,6 @@ /* time-STM32F2xx.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Conf/user_settings.h b/IDE/MDK5-ARM/Conf/user_settings.h index 5251f1470..98f168809 100644 --- a/IDE/MDK5-ARM/Conf/user_settings.h +++ b/IDE/MDK5-ARM/Conf/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Inc/wolfssl_MDK_ARM.h b/IDE/MDK5-ARM/Inc/wolfssl_MDK_ARM.h index 4645d7c39..00bce98bf 100644 --- a/IDE/MDK5-ARM/Inc/wolfssl_MDK_ARM.h +++ b/IDE/MDK5-ARM/Inc/wolfssl_MDK_ARM.h @@ -1,6 +1,6 @@ /* wolfssl_KEIL_ARM.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/CryptBenchmark/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/CryptBenchmark/RTE/wolfSSL/user_settings.h index 9ce8e4d0b..639e0fc50 100644 --- a/IDE/MDK5-ARM/Projects/CryptBenchmark/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/CryptBenchmark/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/CryptBenchmark/main.c b/IDE/MDK5-ARM/Projects/CryptBenchmark/main.c index 1b32a4710..38c167ac0 100644 --- a/IDE/MDK5-ARM/Projects/CryptBenchmark/main.c +++ b/IDE/MDK5-ARM/Projects/CryptBenchmark/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/CryptTest/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/CryptTest/RTE/wolfSSL/user_settings.h index 1645d956c..96106ffc1 100644 --- a/IDE/MDK5-ARM/Projects/CryptTest/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/CryptTest/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/CryptTest/main.c b/IDE/MDK5-ARM/Projects/CryptTest/main.c index ea6ad3851..7ff887cd8 100644 --- a/IDE/MDK5-ARM/Projects/CryptTest/main.c +++ b/IDE/MDK5-ARM/Projects/CryptTest/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/EchoClient/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/EchoClient/RTE/wolfSSL/user_settings.h index a62071372..4ddba7092 100644 --- a/IDE/MDK5-ARM/Projects/EchoClient/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/EchoClient/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/EchoClient/main.c b/IDE/MDK5-ARM/Projects/EchoClient/main.c index 2c74bd3bb..62832e60a 100644 --- a/IDE/MDK5-ARM/Projects/EchoClient/main.c +++ b/IDE/MDK5-ARM/Projects/EchoClient/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/EchoServer/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/EchoServer/RTE/wolfSSL/user_settings.h index 4caaed5d0..36806c07e 100644 --- a/IDE/MDK5-ARM/Projects/EchoServer/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/EchoServer/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/EchoServer/main.c b/IDE/MDK5-ARM/Projects/EchoServer/main.c index f3c252a58..2be031964 100644 --- a/IDE/MDK5-ARM/Projects/EchoServer/main.c +++ b/IDE/MDK5-ARM/Projects/EchoServer/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/SimpleClient/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/SimpleClient/RTE/wolfSSL/user_settings.h index 74630fa88..5f47c6c93 100644 --- a/IDE/MDK5-ARM/Projects/SimpleClient/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/SimpleClient/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/SimpleClient/main.c b/IDE/MDK5-ARM/Projects/SimpleClient/main.c index 21f058eba..09447b745 100644 --- a/IDE/MDK5-ARM/Projects/SimpleClient/main.c +++ b/IDE/MDK5-ARM/Projects/SimpleClient/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/SimpleServer/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/SimpleServer/RTE/wolfSSL/user_settings.h index 74630fa88..5f47c6c93 100644 --- a/IDE/MDK5-ARM/Projects/SimpleServer/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/SimpleServer/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/SimpleServer/main.c b/IDE/MDK5-ARM/Projects/SimpleServer/main.c index 823d17548..9f28ab1e2 100644 --- a/IDE/MDK5-ARM/Projects/SimpleServer/main.c +++ b/IDE/MDK5-ARM/Projects/SimpleServer/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/wolfSSL-Full/main.c b/IDE/MDK5-ARM/Projects/wolfSSL-Full/main.c index 3320923cc..57562cc60 100644 --- a/IDE/MDK5-ARM/Projects/wolfSSL-Full/main.c +++ b/IDE/MDK5-ARM/Projects/wolfSSL-Full/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/wolfSSL-Full/shell.c b/IDE/MDK5-ARM/Projects/wolfSSL-Full/shell.c index 37a8e52e4..489665e9a 100644 --- a/IDE/MDK5-ARM/Projects/wolfSSL-Full/shell.c +++ b/IDE/MDK5-ARM/Projects/wolfSSL-Full/shell.c @@ -1,6 +1,6 @@ /*shell.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/wolfSSL-Full/time-CortexM3-4.c b/IDE/MDK5-ARM/Projects/wolfSSL-Full/time-CortexM3-4.c index ee71c2a02..b64340f75 100644 --- a/IDE/MDK5-ARM/Projects/wolfSSL-Full/time-CortexM3-4.c +++ b/IDE/MDK5-ARM/Projects/wolfSSL-Full/time-CortexM3-4.c @@ -1,6 +1,6 @@ /* time-STM32F2.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Projects/wolfSSL-Lib/RTE/wolfSSL/user_settings.h b/IDE/MDK5-ARM/Projects/wolfSSL-Lib/RTE/wolfSSL/user_settings.h index 74630fa88..5f47c6c93 100644 --- a/IDE/MDK5-ARM/Projects/wolfSSL-Lib/RTE/wolfSSL/user_settings.h +++ b/IDE/MDK5-ARM/Projects/wolfSSL-Lib/RTE/wolfSSL/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MDK5-ARM/Src/ssl-dummy.c b/IDE/MDK5-ARM/Src/ssl-dummy.c index 7a6e6961f..1aec62898 100644 --- a/IDE/MDK5-ARM/Src/ssl-dummy.c +++ b/IDE/MDK5-ARM/Src/ssl-dummy.c @@ -1,6 +1,6 @@ /* ssl-dummy.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/MQX/client-tls.c b/IDE/MQX/client-tls.c index b16987624..ced96d33c 100644 --- a/IDE/MQX/client-tls.c +++ b/IDE/MQX/client-tls.c @@ -1,8 +1,8 @@ /* client-tls.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,8 +16,9 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* wolfSSL */ diff --git a/IDE/MQX/server-tls.c b/IDE/MQX/server-tls.c index 47f1a05c3..211f65513 100644 --- a/IDE/MQX/server-tls.c +++ b/IDE/MQX/server-tls.c @@ -1,8 +1,8 @@ /* server-tls.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,8 +16,9 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* wolfSSL */ #include diff --git a/IDE/MYSQL/CMakeLists_wolfCrypt.txt b/IDE/MYSQL/CMakeLists_wolfCrypt.txt index db977dd05..c7c13196e 100644 --- a/IDE/MYSQL/CMakeLists_wolfCrypt.txt +++ b/IDE/MYSQL/CMakeLists_wolfCrypt.txt @@ -1,6 +1,6 @@ # CMakeLists.txt # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include diff --git a/IDE/MYSQL/CMakeLists_wolfSSL.txt b/IDE/MYSQL/CMakeLists_wolfSSL.txt index 28bda396b..aab778220 100644 --- a/IDE/MYSQL/CMakeLists_wolfSSL.txt +++ b/IDE/MYSQL/CMakeLists_wolfSSL.txt @@ -1,6 +1,6 @@ # CMakeLists.txt # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include diff --git a/IDE/QNX/CAAM-DRIVER/Makefile b/IDE/QNX/CAAM-DRIVER/Makefile new file mode 100644 index 000000000..5e08b4724 --- /dev/null +++ b/IDE/QNX/CAAM-DRIVER/Makefile @@ -0,0 +1,34 @@ +ARTIFACT = wolfCrypt + +#Build architecture/variant string, possible values: x86, armv7le, etc... +PLATFORM = armv7le +OUTPUT_DIR = build +TARGET = $(ARTIFACT) + +CC = qcc -Vgcc_nto$(PLATFORM) +CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM) +LD = $(CC) + +INCLUDES += -I../../../wolfssl/wolfcrypt/port/caam/ +CCFLAGS += -O2 -Wall + +SRCS = \ + ../../../wolfcrypt/src/port/caam/caam_driver.c \ + ../../../wolfcrypt/src/port/caam/caam_error.c \ + ../../../wolfcrypt/src/port/caam/caam_qnx.c \ + +OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS)))) + +$(OUTPUT_DIR)/%.o: %.c + @mkdir -p $(dir $@) + $(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $< + +$(TARGET):$(OBJS) + $(LD) -o $(TARGET) $(LDFLAGS) $(OBJS) $(LIBS) + +all: $(TARGET) + +clean: + rm -rf $(OUTPUT_DIR) $(ARTIFACT) + +rebuild: clean all diff --git a/IDE/QNX/README.md b/IDE/QNX/README.md new file mode 100644 index 000000000..800f54cdc --- /dev/null +++ b/IDE/QNX/README.md @@ -0,0 +1,28 @@ +# QNX CAAM Driver And Examples + +This directory contains; +- A Makefile for creating the QNX CAAM driver located at IDE/QNX/CAAM-DRIVER/Makefile +- An example TLS server located at IDE/QNX/example-server/ +- An example client located at IDE/QNX/example-client +- An example CMAC use located at IDE/QNX/example-cmac + +To build either of these, first build wolfSSL with support for use with QNX CAAM. To do this use the configure option --enable-caam=qnx + +``` +bash +source ~/qnx700/qnxsdp-env.sh +./configure --host=arm-unknown-nto-qnx7.0.0eabi --enable-caam=qnx +make +``` + +Once the wolfSSL library has been built cd to IDE/QNX/CAAM-DRIVER and run "make". This will produce the wolfCrypt resource manager. It should be started on the device with root permisions. Once wolfCrypt is running on the device with root permisions then any user with access to open a connection to wolfCrypt can make use of the driver. + + +### Supported Operations By CAAM Driver +- ECC black key creation +- ECC black key sign / verify / ecdh +- Black blob creation and open +- Red blob creation and open +- Cover keys (turn to black key) +- CMAC with and without black keys +- TRNG used by default to seed Hash DRBG diff --git a/IDE/QNX/example-client/Makefile b/IDE/QNX/example-client/Makefile new file mode 100644 index 000000000..5e76d4bd1 --- /dev/null +++ b/IDE/QNX/example-client/Makefile @@ -0,0 +1,33 @@ +ARTIFACT = client-tls + +#Build architecture/variant string, possible values: x86, armv7le, etc... +PLATFORM = armv7le +OUTPUT_DIR = build +TARGET = $(ARTIFACT) + +CC = qcc -Vgcc_nto$(PLATFORM) +CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM) +LD = $(CC) + +INCLUDES += -I../../../ +LIBS += -L../../../src/.libs/ -lwolfssl +LIBS += -lsocket -lm +CCFLAGS += -O2 -Wall + +SRCS = client-tls.c + +OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS)))) + +$(OUTPUT_DIR)/%.o: %.c + @mkdir -p $(dir $@) + $(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $< + +$(TARGET):$(OBJS) + $(LD) -o $(TARGET) $(OBJS) $(LIBS) + +all: $(TARGET) + +clean: + rm -rf $(OUTPUT_DIR) $(ARTIFACT) + +rebuild: clean all diff --git a/IDE/QNX/example-client/client-tls.c b/IDE/QNX/example-client/client-tls.c new file mode 100644 index 000000000..d6e890d4a --- /dev/null +++ b/IDE/QNX/example-client/client-tls.c @@ -0,0 +1,266 @@ +/* client-tls.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include + +/* socket includes */ +#include +#include +#include +#include + +/* wolfSSL */ +#include +#include + +/* malloc out buffer and fill it with converted DER to PEM + * returns pem size on success + */ +static int convertDerToPem(int type, char* file, unsigned char **out) +{ + int derSz, pemSz; + unsigned char der[4096]; + unsigned char *pem; + FILE* f; + + f = fopen(file, "rb"); + if (f == NULL) { + fprintf(stderr, "unable to open cert file %s\n", file); + return -1; + } + derSz = fread(der, 1, sizeof(der), f); + fclose(f); + + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, type); + if (pemSz <= 0) { + fprintf(stderr, "issue getting pem size needed\n"); + return -1; + } + + pem = (unsigned char*)malloc(pemSz); + if (pem == NULL) { + fprintf(stderr, "issue malloc'ing pem size needed\n"); + return -1; + } + + pemSz = wc_DerToPemEx(der, derSz, pem, pemSz, NULL, type); + if (pemSz <= 0) { + fprintf(stderr, "issue %d converting der to pem\n", pemSz); + free(pem); + return -1; + } + *out = pem; + return pemSz; +} + + +int main(int argc, char** argv) +{ + int sockfd; + struct sockaddr_in servAddr; + char buff[256]; + size_t len; + int ret; + int port; + + int pemSz; + unsigned char *pem; + FILE* f; + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + + /* Check for proper calling convention */ + if (argc != 6) { + printf("usage: %s \n", + argv[0]); + return 0; + } + port = atoi(argv[1]); + + /* Create a socket that uses an internet IPv4 address, + * Sets the socket to be stream based (TCP), + * 0 means choose the default protocol. */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + fprintf(stderr, "ERROR: failed to create the socket\n"); + ret = -1; + goto end; + } + + /* Initialize the server address struct with zeros */ + memset(&servAddr, 0, sizeof(servAddr)); + + /* Fill in the server address */ + servAddr.sin_family = AF_INET; /* using IPv4 */ + servAddr.sin_port = htons(port); /* on DEFAULT_PORT */ + + /* Get the server IPv4 address from the command line call */ + if (inet_pton(AF_INET, argv[2], &servAddr.sin_addr) != 1) { + fprintf(stderr, "ERROR: invalid address\n"); + ret = -1; + goto end; + } + + /* Connect to the server */ + if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) + == -1) { + fprintf(stderr, "ERROR: failed to connect\n"); + goto end; + } + + /*---------------------------------*/ + /* Start of security */ + /*---------------------------------*/ + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: Failed to initialize the library\n"); + goto socket_cleanup; + } + + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + goto socket_cleanup; + } + + /* load cert and convert DER to PEM using dynamic length */ + pemSz = convertDerToPem(CERT_TYPE, argv[4], &pem); + if (pemSz <= 0) { + fprintf(stderr, "ERROR: converting DER cert to PEM\n"); + ret = -1; + goto socket_cleanup; + } + + if (wolfSSL_CTX_use_certificate_buffer(ctx, pem, pemSz, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + fprintf(stderr, "issue loading in pem cert\n"); + ret = -1; + free(pem); + goto socket_cleanup; + } + free(pem); + + /* load key and convert DER to PEM using dynamic length */ + pemSz = convertDerToPem(PRIVATEKEY_TYPE, argv[5], &pem); + if (pemSz <= 0) { + fprintf(stderr, "ERROR: converting DER key to PEM\n"); + ret = -1; + goto socket_cleanup; + } + + if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, pem, pemSz, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + fprintf(stderr, "issue loading in pem key\n"); + ret = -1; + free(pem); + goto socket_cleanup; + } + free(pem); + + /* Load client certificates into WOLFSSL_CTX */ + f = fopen(argv[3], "rb"); + if (f == NULL) { + fprintf(stderr, "unable to open %s\n", argv[3]); + ret = -1; + goto socket_cleanup; + } + fseek(f, 0, SEEK_END); + pemSz = ftell(f); + rewind(f); + pem = malloc(pemSz); + if (pem == NULL) { + fclose(f); + ret = -1; + goto socket_cleanup; + } + pemSz = fread(pem, 1, pemSz, f); + fclose(f); + + ret = wolfSSL_CTX_load_verify_buffer(ctx, pem, pemSz, WOLFSSL_FILETYPE_PEM); + if (ret != SSL_SUCCESS) { + fprintf(stderr, "ERROR %d: failed to load %s, please check the file.\n", + ret, argv[3]); + free(pem); + goto ctx_cleanup; + } + free(pem); + + /* Create a WOLFSSL object */ + if ((ssl = wolfSSL_new(ctx)) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); + ret = -1; + goto ctx_cleanup; + } + + /* Attach wolfSSL to the socket */ + if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: Failed to set the file descriptor\n"); + goto cleanup; + } + + /* Connect to wolfSSL on the server side */ + if ((ret = wolfSSL_connect(ssl)) != SSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to connect to wolfSSL\n"); + goto cleanup; + } + + /* Get a message for the server from stdin */ + printf("Message for server: "); + memset(buff, 0, sizeof(buff)); + if (fgets(buff, sizeof(buff), stdin) == NULL) { + fprintf(stderr, "ERROR: failed to get message for server\n"); + ret = -1; + goto cleanup; + } + len = strnlen(buff, sizeof(buff)); + + /* Send the message to the server */ + if ((ret = wolfSSL_write(ssl, buff, len)) != len) { + fprintf(stderr, "ERROR: failed to write entire message\n"); + fprintf(stderr, "%d bytes of %d bytes were sent", ret, (int) len); + goto cleanup; + } + + /* Read the server data into our buff array */ + memset(buff, 0, sizeof(buff)); + if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) { + fprintf(stderr, "ERROR: failed to read\n"); + goto cleanup; + } + + /* Print to stdout any data the server sends */ + printf("Server: %s\n", buff); + + /* Cleanup and return */ +cleanup: + wolfSSL_free(ssl); /* Free the wolfSSL object */ +ctx_cleanup: + wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ +socket_cleanup: + close(sockfd); /* Close the connection to the server */ +end: + return ret; /* Return reporting a success */ +} diff --git a/IDE/QNX/example-cmac/Makefile b/IDE/QNX/example-cmac/Makefile new file mode 100644 index 000000000..13b9afc5e --- /dev/null +++ b/IDE/QNX/example-cmac/Makefile @@ -0,0 +1,33 @@ +ARTIFACT = cmac-test + +#Build architecture/variant string, possible values: x86, armv7le, etc... +PLATFORM = armv7le +OUTPUT_DIR = build +TARGET = $(ARTIFACT) + +CC = qcc -Vgcc_nto$(PLATFORM) +CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM) +LD = $(CC) + +INCLUDES += -I../../../ +LIBS += -L../../../src/.libs/ -lwolfssl +LIBS += -lsocket -lm +CCFLAGS += -O2 -Wall + +SRCS = cmac-test.c + +OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS)))) + +$(OUTPUT_DIR)/%.o: %.c + @mkdir -p $(dir $@) + $(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $< + +$(TARGET):$(OBJS) + $(LD) -o $(TARGET) $(OBJS) $(LIBS) + +all: $(TARGET) + +clean: + rm -rf $(OUTPUT_DIR) $(ARTIFACT) + +rebuild: clean all diff --git a/IDE/QNX/example-cmac/cmac-test.c b/IDE/QNX/example-cmac/cmac-test.c new file mode 100644 index 000000000..f82155652 --- /dev/null +++ b/IDE/QNX/example-cmac/cmac-test.c @@ -0,0 +1,113 @@ +/* cmac-test.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +static const byte k256[] = +{ + 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 +}; + + +static int createTag(const byte* key, int keySz, byte* msg, int msgSz, + byte* msg2, int msg2Sz) +{ + Cmac cmac; + byte tag[AES_BLOCK_SIZE]; + word32 i, tagSz; + byte out[48]; + word32 outSz; + + XMEMSET(tag, 0, sizeof(tag)); + tagSz = AES_BLOCK_SIZE; + + outSz = 48; + wc_caamCoverKey((byte*)key, keySz, out, &outSz, 0); + + if (wc_InitCmac(&cmac, NULL, keySz, WC_CMAC_AES, out) != 0) { + printf("Cmac init error\n"); + return -1; + } + + if (wc_CmacUpdate(&cmac, msg, msgSz) != 0) { + printf("message update error\n"); + return -1; + } + + if (msg2Sz > 0) { + if (wc_CmacUpdate(&cmac, msg2, msg2Sz) != 0) { + printf("message2 update error\n"); + return -1; + } + } + + if (wc_CmacFinal(&cmac, tag, &tagSz) != 0) { + printf("create tag error\n"); + return -1; + } + + printf("TAG :"); + for (i = 0; i < tagSz; i++) + printf("%02X", tag[i]); + printf("\n"); + + return 0; +} + +int main(int argc, char* argv[]) +{ + uintptr_t virtual_base; + byte msg[256]; + byte msg2[256]; + int i; + + printf("checking out permissions, can we call mmap_device_io?\n"); + virtual_base = mmap_device_io(0x00010000, 0x02140000); + if (virtual_base == (uintptr_t)MAP_FAILED) { + perror("mmap_device_io failed for base address "); + } + else { + munmap_device_io(virtual_base, 0x00010000); + } + + wolfCrypt_Init(); + + XMEMSET(msg, 1, sizeof(msg)); + XMEMSET(msg2, 9, sizeof(msg2)); + + for (i = 0; i < 256; i+=8) { + if (createTag(k256, sizeof(k256), msg, i, NULL, 0) != 0) + return -1; + } + + wolfCrypt_Cleanup(); + return 0; +} diff --git a/IDE/QNX/example-server/Makefile b/IDE/QNX/example-server/Makefile new file mode 100644 index 000000000..f8fa25d94 --- /dev/null +++ b/IDE/QNX/example-server/Makefile @@ -0,0 +1,33 @@ +ARTIFACT = server-tls + +#Build architecture/variant string, possible values: x86, armv7le, etc... +PLATFORM = armv7le +OUTPUT_DIR = build +TARGET = $(ARTIFACT) + +CC = qcc -Vgcc_nto$(PLATFORM) +CXX = qcc -lang-c++ -Vgcc_nto$(PLATFORM) +LD = $(CC) + +INCLUDES += -I../../../ +LIBS += -L../../../src/.libs/ -lwolfssl +LIBS += -lsocket -lm +CCFLAGS += -O2 -Wall + +SRCS = server-tls.c + +OBJS = $(addprefix $(OUTPUT_DIR)/,$(addsuffix .o, $(basename $(SRCS)))) + +$(OUTPUT_DIR)/%.o: %.c + @mkdir -p $(dir $@) + $(CC) -c -o $@ $(INCLUDES) $(CCFLAGS) $< + +$(TARGET):$(OBJS) + $(LD) -o $(TARGET) $(OBJS) $(LIBS) + +all: $(TARGET) + +clean: + rm -rf $(OUTPUT_DIR) $(ARTIFACT) + +rebuild: clean all diff --git a/IDE/QNX/example-server/server-tls.c b/IDE/QNX/example-server/server-tls.c new file mode 100644 index 000000000..ebd68ece8 --- /dev/null +++ b/IDE/QNX/example-server/server-tls.c @@ -0,0 +1,392 @@ +/* server-tls.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include + +/* socket includes */ +#include +#include +#include +#include + +/* wolfSSL */ +#include +#include +#include +#include /* functions for blob/cover*/ + +#define DEFAULT_PORT 11111 +#define ECC_KEY_SIZE 32 + +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 +#include + +/* creates a blob then opens it, returns 0 on success */ +static int test_blob(byte* key, int keySz) +{ + int ret, i; + byte out[keySz + WC_CAAM_BLOB_SZ]; + int outSz; + int keyOutSz; + + byte keymod[WC_CAAM_BLACK_KEYMOD_SZ]; + int keymodSz = WC_CAAM_BLACK_KEYMOD_SZ; + + /* using a key mod of all 1's */ + XMEMSET(keymod, 1, keymodSz); + + /* example of creating black blog with key for later */ + outSz = keySz + WC_CAAM_BLOB_SZ; + ret = wc_caamCreateBlob_ex(key, keySz, out, (word32*)&outSz, + WC_CAAM_BLOB_BLACK, keymod, keymodSz); + if (ret != 0) { + printf("Error creating black blob\n"); + return -1; + } + + printf("created black blob :"); + for (i = 0; i < outSz; i++) + printf("%02X,", out[i]); + printf("\n"); + + + /* open black blob and overwrite key, this is to show that the opened blob + * can be used for the upcoming TLS connection */ + memset(key, 0, keySz); + keyOutSz = keySz; + ret = wc_caamOpenBlob_ex(out, outSz, key, (word32*)&keyOutSz, + WC_CAAM_BLOB_BLACK, keymod, keymodSz); + if (ret != 0) { + printf("Error opening black blob\n"); + } + + return ret; +} + + +/* example of covering an existing key and then making a black blob with it + * note that generating an ECC completely in secure memory already covered can + * be done by call wc_ecc_make_key */ +int cover(ecc_key* keyOut, const byte* der, word32 derSz) +{ + int ret; + ecc_key notSecure; + word32 idx = 0; + + /* format bit plus public key x and y parameter */ + byte x963[(ECC_KEY_SIZE*2) + 1]; + word32 x963Sz = (ECC_KEY_SIZE*2) + 1; + + /* uncovered private key */ + byte d[ECC_KEY_SIZE]; + word32 dSz = ECC_KEY_SIZE; + + byte blackKey[ECC_KEY_SIZE + WC_CAAM_MAC_SZ]; + word32 blackKeySz = ECC_KEY_SIZE + WC_CAAM_MAC_SZ; + + + /* The DER buffer for test case does not contain a black key, here we will + * extract the key information, cover it (make it a black key), and then + * import that into 'keyOut' which will create a secure partition on import. + * + * These steps of covering and importing can be avoided with a call to + * wc_ecc_make_key which creates a new black key that never leaves the CAAM. + * The cover process is only being used to make use of an existing key that + * matches the test certificate. + */ + wc_ecc_init(¬Secure); + if (wc_EccPrivateKeyDecode(der, &idx, ¬Secure, derSz) != 0) { + printf("Error extracting ECC der buffer\n"); + ret = -1; + goto done; + } + + /* Get the uncovered key values */ + if (wc_ecc_export_private_raw(¬Secure, NULL, NULL, NULL, NULL, d, &dSz) + != 0) { + printf("Error getting ecc key values\n"); + ret = -1; + goto done; + } + + if (wc_ecc_export_x963(¬Secure, x963, &x963Sz) != 0) { + printf("Error getting ecc public key\n"); + ret = -1; + goto done; + } + + /* Cover up the private key (make it a black key, encrypting with AES-CCM)*/ + XMEMSET(blackKey, 0, blackKeySz); + if (wc_caamCoverKey(d, dSz, blackKey, &blackKeySz, 0) != 0) { + printf("Error covering up the private key\n"); + ret = -1; + goto done; + } + + /* Sanity check to compare covered key versus plain text */ + if (XMEMCMP(d, blackKey, dSz) == 0) { + printf("Something went wrong with key cover!!\n"); + ret = -1; + goto done; + } + + if (test_blob(blackKey, blackKeySz - WC_CAAM_MAC_SZ) != 0) { + printf("test blob failed\n"); + ret = -1; + goto done; + } + + /* zero out the plain text buffer and free key */ + XMEMSET(d, 0, dSz); + + /* Import the black key into a ecc_key structure (this step tries to create + * a partition of secure memory marked CPS) + */ + ret = wc_ecc_import_private_key(blackKey, blackKeySz, x963, x963Sz, keyOut); + if (ret != 0) { + printf("Error importing black key into secure memory %d\n", ret); + wc_ecc_free(keyOut); + goto done; + } + printf("blackKeySz = %d, virtual secure address ecc_key.blackKey = 0x%08X\n", + blackKeySz, keyOut->blackKey); + + ret = 0; +done: + + wc_ecc_free(¬Secure); + return ret; +} + + +/* callback function for creating ECC signatures */ +static int TLS_ECC_Sign_callback(WOLFSSL* ssl, const unsigned char* in, + unsigned int inSz, unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + ecc_key* blackKey; + + printf("Using ECC sign callback\n"); + + if (ctx == NULL) { + printf("Was expecting a black key passed along with WOLFSSL\n"); + return -1; + } + blackKey = (ecc_key*)ctx; + + return wc_ecc_sign_hash(in, inSz, out, outSz, NULL, blackKey); +} + + +/* callback function to do ECDH operation in TLS handshake */ +static int TLS_ECDH_callback(WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* outlen, + int side, void* ctx) +{ + int ret= -1; + + printf("Using ECDH callback\n"); + + if (ctx == NULL) { + printf("Was expecting a black key passed along with WOLFSSH\n"); + return -1; + } + + /* this is being called from client end */ + if (side == WOLFSSL_CLIENT_END) { + } + + /* this is being called from server end */ + if (side == WOLFSSL_SERVER_END) { + ecc_key pub; + + wc_ecc_init(&pub); + if (wc_ecc_import_x963(pubKeyDer, *pubKeySz, &pub) != 0) { + printf("Issue decoding the public key to generate shared secret\n"); + wc_ecc_free(&pub); + return -1; + } + + /* otherKey is the ephemeral private key created with ECDHE cipher + * suites. As long as EccKeyGenCb has not been set this key was created + * with wc_ecc_make_key_ex, which when used with NIST P256 it will + * automatically try to create a secure black key + */ + ret = wc_ecc_shared_secret(otherKey, &pub, out, outlen); + wc_ecc_free(&pub); + } + + return ret; +} + + +int main() +{ + int sockfd; + int connd = 0; + struct sockaddr_in servAddr; + struct sockaddr_in clientAddr; + socklen_t size = sizeof(clientAddr); + char buff[256]; + size_t len; + int ret; + const char* reply = "I hear ya fa shizzle!\n"; + + ecc_key blackKey; + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + + /* Initialize wolfSSL */ + if (wolfSSL_Init() != WOLFSSL_SUCCESS) { + fprintf(stderr, "issue with wolfSSL_Init()\n"); + return -1; + } + wolfSSL_Debugging_ON(); + wc_ecc_init(&blackKey); + + /* Create a socket that uses an internet IPv4 address, + * Sets the socket to be stream based (TCP), + * 0 means choose the default protocol. */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + fprintf(stderr, "ERROR: failed to create the socket\n"); + goto end; + } + + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); + goto end; + } + + /* Load server certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(ctx, serv_ecc_der_256, + sizeof_serv_ecc_der_256, SSL_FILETYPE_ASN1) != SSL_SUCCESS) { + printf("error loading in certificate buffer\n"); + goto end; + } + +// wolfSSL_CTX_use_PrivateKey_buffer(ctx, ecc_key_der_256, sizeof_ecc_key_der_256, SSL_FILETYPE_ASN1); + + if (cover(&blackKey, ecc_key_der_256, sizeof_ecc_key_der_256) != 0) { + printf("error covering up key\n"); + goto end; + } + + /* set signing callback to use during TLS connection */ + wolfSSL_CTX_SetEccSignCb(ctx, TLS_ECC_Sign_callback); + + /* set ECDH shared secret callback to use during TLS connection */ + wolfSSL_CTX_SetEccSharedSecretCb(ctx, TLS_ECDH_callback); + + /* Initialize the server address struct with zeros */ + memset(&servAddr, 0, sizeof(servAddr)); + + /* Fill in the server address */ + servAddr.sin_family = AF_INET; /* using IPv4 */ + servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */ + servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */ + + /* Bind the server socket to our port */ + if (bind(sockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) { + fprintf(stderr, "ERROR: failed to bind\n"); + goto end; + } + + /* Listen for a new connection, allow 5 pending connections */ + if (listen(sockfd, 5) == -1) { + fprintf(stderr, "ERROR: failed to listen\n"); + goto end; + } + + /* Continue to accept clients until shutdown is issued */ + printf("Waiting for a connection...\n"); + + /* Accept client connections */ + if ((connd = accept(sockfd, (struct sockaddr*)&clientAddr, &size)) == -1) { + fprintf(stderr, "ERROR: failed to accept the connection\n\n"); + goto end; + } + + /* Create a WOLFSSL object */ + if ((ssl = wolfSSL_new(ctx)) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); + goto end; + } + + /* Attach wolfSSL to the socket */ + wolfSSL_set_fd(ssl, connd); + + /* associate the covered up black key with the WOLFSSH structure, + * this will then get passed as the last argument to the callbacks */ + wolfSSL_SetEccSignCtx(ssl, (void*)&blackKey); + wolfSSL_SetEccSharedSecretCtx(ssl, (void*)&blackKey); + + /* Establish TLS connection */ + ret = wolfSSL_accept(ssl); + if (ret != SSL_SUCCESS) { + fprintf(stderr, "wolfSSL_accept error = %d\n", + wolfSSL_get_error(ssl, ret)); + goto end; + } + printf("Client connected successfully\n"); + + /* Read the client data into our buff array */ + memset(buff, 0, sizeof(buff)); + if (wolfSSL_read(ssl, buff, sizeof(buff)-1) == -1) { + fprintf(stderr, "ERROR: failed to read\n"); + goto end; + } + + /* Print to stdout any data the client sends */ + printf("Client: %s\n", buff); + + /* Write our reply into buff */ + memset(buff, 0, sizeof(buff)); + memcpy(buff, reply, strlen(reply)); + len = strnlen(buff, sizeof(buff)); + + /* Reply back to the client */ + if (wolfSSL_write(ssl, buff, len) != len) { + fprintf(stderr, "ERROR: failed to write\n"); + goto end; + } + +end: + /* Cleanup after this connection */ + wolfSSL_free(ssl); /* Free the wolfSSL object */ + close(connd); /* Close the connection to the client */ + wc_ecc_free(&blackKey); + + printf("Shutdown complete\n"); + + /* Cleanup and return */ + wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ + close(sockfd); /* Close the socket listening for clients */ + return 0; /* Return reporting a success */ +} diff --git a/IDE/QNX/include.am b/IDE/QNX/include.am new file mode 100644 index 000000000..3236ecd5e --- /dev/null +++ b/IDE/QNX/include.am @@ -0,0 +1,12 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= IDE/QNX/README.md +EXTRA_DIST+= IDE/QNX/CAAM-DRIVER/Makefile +EXTRA_DIST+= IDE/QNX/example-server/Makefile +EXTRA_DIST+= IDE/QNX/example-server/server-tls.c +EXTRA_DIST+= IDE/QNX/example-client/Makefile +EXTRA_DIST+= IDE/QNX/example-client/client-tls.c +EXTRA_DIST+= IDE/QNX/example-cmac/Makefile +EXTRA_DIST+= IDE/QNX/example-cmac/cmac-test.c diff --git a/IDE/RISCV/SIFIVE-HIFIVE1/main.c b/IDE/RISCV/SIFIVE-HIFIVE1/main.c index a3e4a19c0..84611784b 100644 --- a/IDE/RISCV/SIFIVE-HIFIVE1/main.c +++ b/IDE/RISCV/SIFIVE-HIFIVE1/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/RISCV/SIFIVE-HIFIVE1/user_settings.h b/IDE/RISCV/SIFIVE-HIFIVE1/user_settings.h index 19a5686b2..b70cb2624 100644 --- a/IDE/RISCV/SIFIVE-HIFIVE1/user_settings.h +++ b/IDE/RISCV/SIFIVE-HIFIVE1/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/arm_startup.c b/IDE/ROWLEY-CROSSWORKS-ARM/arm_startup.c index 8d7d07488..d838357b1 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/arm_startup.c +++ b/IDE/ROWLEY-CROSSWORKS-ARM/arm_startup.c @@ -1,6 +1,6 @@ /* arm_startup.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/benchmark_main.c b/IDE/ROWLEY-CROSSWORKS-ARM/benchmark_main.c index 4d3b63983..8fc13dc6c 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/benchmark_main.c +++ b/IDE/ROWLEY-CROSSWORKS-ARM/benchmark_main.c @@ -1,6 +1,6 @@ /* benchmark_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/kinetis_hw.c b/IDE/ROWLEY-CROSSWORKS-ARM/kinetis_hw.c index 8476b0f58..bdbce0bda 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/kinetis_hw.c +++ b/IDE/ROWLEY-CROSSWORKS-ARM/kinetis_hw.c @@ -1,6 +1,6 @@ /* kinetis_hw.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -64,10 +64,10 @@ // UART TX Port, Pin, Mux and Baud #ifdef FREESCALE_KSDK_BM - #define UART_PORT LPUART0 /* UART Port */ - #define UART_TX_PORT PORTA /* UART TX Port */ - #define UART_TX_PIN 2U /* UART TX Pin */ - #define UART_TX_MUX kPORT_MuxAlt2 /* Kinetis UART pin mux */ + #define UART_PORT LPUART4 /* UART Port */ + #define UART_TX_PORT PORTC /* UART TX Port */ + #define UART_TX_PIN 15U /* UART TX Pin */ + #define UART_TX_MUX kPORT_MuxAlt3 /* Kinetis UART pin mux */ #elif defined (WOLFSSL_FRDM_K64) #define UART_PORT UART0 /* UART Port */ #define UART_TX_PORT PORTB /* UART TX Port */ @@ -91,7 +91,7 @@ /* Note: TWR-K60 is UART3, PTC17 */ /* Note: FRDM-K64 is UART4, PTE24 or UART0 PTB17 for OpenOCD (SIM_SCGC4_UART0_MASK)*/ /* Note: TWR-K64 is UART5, PTE8 */ -/* Note: FRDM-K82F is LPUART0 A2, LPUART4 PTC15 */ +/* Note: FRDM-K82F is LPUART4 PTC15 Alt3 (OpenOCD UART) */ /***********************************************/ diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/retarget.c b/IDE/ROWLEY-CROSSWORKS-ARM/retarget.c index c0b6602af..b3841f671 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/retarget.c +++ b/IDE/ROWLEY-CROSSWORKS-ARM/retarget.c @@ -1,6 +1,6 @@ /* retarget.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/test_main.c b/IDE/ROWLEY-CROSSWORKS-ARM/test_main.c index b26835b87..3b2b3e644 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/test_main.c +++ b/IDE/ROWLEY-CROSSWORKS-ARM/test_main.c @@ -1,6 +1,6 @@ /* test_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp index 5a474b301..2cd93b21f 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp +++ b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp @@ -159,7 +159,6 @@ - @@ -223,8 +222,6 @@ - - diff --git a/IDE/Renesas/cs+/Projects/common/strings.h b/IDE/Renesas/cs+/Projects/common/strings.h index fd2cf86e6..e3752588e 100644 --- a/IDE/Renesas/cs+/Projects/common/strings.h +++ b/IDE/Renesas/cs+/Projects/common/strings.h @@ -1,6 +1,6 @@ /* strings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/common/unistd.h b/IDE/Renesas/cs+/Projects/common/unistd.h index d91dd4790..962ad47ee 100644 --- a/IDE/Renesas/cs+/Projects/common/unistd.h +++ b/IDE/Renesas/cs+/Projects/common/unistd.h @@ -1,6 +1,6 @@ /* unistd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/common/user_settings.h b/IDE/Renesas/cs+/Projects/common/user_settings.h index 241316fc3..eef1d3331 100644 --- a/IDE/Renesas/cs+/Projects/common/user_settings.h +++ b/IDE/Renesas/cs+/Projects/common/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/common/wolfssl_dummy.c b/IDE/Renesas/cs+/Projects/common/wolfssl_dummy.c index 7541fccc6..cfba7259e 100644 --- a/IDE/Renesas/cs+/Projects/common/wolfssl_dummy.c +++ b/IDE/Renesas/cs+/Projects/common/wolfssl_dummy.c @@ -1,6 +1,6 @@ /* wolfssl_dummy.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/t4_demo/wolf_client.c b/IDE/Renesas/cs+/Projects/t4_demo/wolf_client.c index ac7ff1e43..49628d8ba 100644 --- a/IDE/Renesas/cs+/Projects/t4_demo/wolf_client.c +++ b/IDE/Renesas/cs+/Projects/t4_demo/wolf_client.c @@ -1,6 +1,6 @@ /* wolf_client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/t4_demo/wolf_main.c b/IDE/Renesas/cs+/Projects/t4_demo/wolf_main.c index 8e3f4c54b..c50c858c2 100644 --- a/IDE/Renesas/cs+/Projects/t4_demo/wolf_main.c +++ b/IDE/Renesas/cs+/Projects/t4_demo/wolf_main.c @@ -1,6 +1,6 @@ /* wolf_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/t4_demo/wolf_server.c b/IDE/Renesas/cs+/Projects/t4_demo/wolf_server.c index bcb3e3390..97ca42816 100644 --- a/IDE/Renesas/cs+/Projects/t4_demo/wolf_server.c +++ b/IDE/Renesas/cs+/Projects/t4_demo/wolf_server.c @@ -1,6 +1,6 @@ /* wolf_server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/cs+/Projects/test/test_main.c b/IDE/Renesas/cs+/Projects/test/test_main.c index 8defb1d14..9493273cb 100644 --- a/IDE/Renesas/cs+/Projects/test/test_main.c +++ b/IDE/Renesas/cs+/Projects/test/test_main.c @@ -1,6 +1,6 @@ /* test_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/DK-S7G2/benchmark-template/src/app_entry.c b/IDE/Renesas/e2studio/DK-S7G2/benchmark-template/src/app_entry.c index be610ccdb..f78c41ca5 100644 --- a/IDE/Renesas/e2studio/DK-S7G2/benchmark-template/src/app_entry.c +++ b/IDE/Renesas/e2studio/DK-S7G2/benchmark-template/src/app_entry.c @@ -1,6 +1,6 @@ /* app_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include "app.h" #include "stdio.h" diff --git a/IDE/Renesas/e2studio/DK-S7G2/example_server-template/src/app_entry.c b/IDE/Renesas/e2studio/DK-S7G2/example_server-template/src/app_entry.c index a83322322..d7df11ce9 100644 --- a/IDE/Renesas/e2studio/DK-S7G2/example_server-template/src/app_entry.c +++ b/IDE/Renesas/e2studio/DK-S7G2/example_server-template/src/app_entry.c @@ -1,6 +1,6 @@ /* app_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include "app.h" diff --git a/IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/src/app_entry.c b/IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/src/app_entry.c index c9eee735e..a0821fa04 100644 --- a/IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/src/app_entry.c +++ b/IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/src/app_entry.c @@ -1,6 +1,6 @@ /* app_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/IDE/Renesas/e2studio/GR-ROSE/common/strings.h b/IDE/Renesas/e2studio/GR-ROSE/common/strings.h index fd2cf86e6..e3752588e 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/common/strings.h +++ b/IDE/Renesas/e2studio/GR-ROSE/common/strings.h @@ -1,6 +1,6 @@ /* strings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/common/unistd.h b/IDE/Renesas/e2studio/GR-ROSE/common/unistd.h index d91dd4790..962ad47ee 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/common/unistd.h +++ b/IDE/Renesas/e2studio/GR-ROSE/common/unistd.h @@ -1,6 +1,6 @@ /* unistd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/common/user_settings.h b/IDE/Renesas/e2studio/GR-ROSE/common/user_settings.h index f47e578dc..52d87c9c6 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/common/user_settings.h +++ b/IDE/Renesas/e2studio/GR-ROSE/common/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/common/wolfssl_dummy.c b/IDE/Renesas/e2studio/GR-ROSE/common/wolfssl_dummy.c index 8fa6340b4..a31c43cdc 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/common/wolfssl_dummy.c +++ b/IDE/Renesas/e2studio/GR-ROSE/common/wolfssl_dummy.c @@ -1,6 +1,6 @@ /* wolfssl_dummy.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.c b/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.c index 01aa6015b..4a4fd08a3 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.c +++ b/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.c @@ -1,6 +1,6 @@ /* key_data.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include "key_data.h" diff --git a/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.h b/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.h index 958977c06..efc8c4576 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.h +++ b/IDE/Renesas/e2studio/GR-ROSE/test/src/key_data.h @@ -1,6 +1,6 @@ /* key_data.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef KEY_DATA_H_ #define KEY_DATA_H_ diff --git a/IDE/Renesas/e2studio/GR-ROSE/test/src/test_main.c b/IDE/Renesas/e2studio/GR-ROSE/test/src/test_main.c index 7d336826a..5979896f8 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/test/src/test_main.c +++ b/IDE/Renesas/e2studio/GR-ROSE/test/src/test_main.c @@ -1,6 +1,6 @@ /* test_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_client.c b/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_client.c index ff09b1a80..cc1eeac79 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_client.c +++ b/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_client.c @@ -1,6 +1,6 @@ /* wolf_client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_server.c b/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_server.c index 5d38b0358..b193fbe71 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_server.c +++ b/IDE/Renesas/e2studio/GR-ROSE/test/src/wolf_server.c @@ -1,6 +1,6 @@ /* wolf_server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/GR-ROSE/test/src/wolfssl_demo.h b/IDE/Renesas/e2studio/GR-ROSE/test/src/wolfssl_demo.h index ca5482007..96e0eab3f 100644 --- a/IDE/Renesas/e2studio/GR-ROSE/test/src/wolfssl_demo.h +++ b/IDE/Renesas/e2studio/GR-ROSE/test/src/wolfssl_demo.h @@ -1,6 +1,6 @@ /* wolfssl_demo.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/common/strings.h b/IDE/Renesas/e2studio/Projects/common/strings.h index fd2cf86e6..e3752588e 100644 --- a/IDE/Renesas/e2studio/Projects/common/strings.h +++ b/IDE/Renesas/e2studio/Projects/common/strings.h @@ -1,6 +1,6 @@ /* strings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/common/unistd.h b/IDE/Renesas/e2studio/Projects/common/unistd.h index d91dd4790..962ad47ee 100644 --- a/IDE/Renesas/e2studio/Projects/common/unistd.h +++ b/IDE/Renesas/e2studio/Projects/common/unistd.h @@ -1,6 +1,6 @@ /* unistd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/common/user_settings.h b/IDE/Renesas/e2studio/Projects/common/user_settings.h index 3f110ef20..62648c9cc 100644 --- a/IDE/Renesas/e2studio/Projects/common/user_settings.h +++ b/IDE/Renesas/e2studio/Projects/common/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/common/wolfssl_dummy.c b/IDE/Renesas/e2studio/Projects/common/wolfssl_dummy.c index 61cd51f74..9aa14dbf1 100644 --- a/IDE/Renesas/e2studio/Projects/common/wolfssl_dummy.c +++ b/IDE/Renesas/e2studio/Projects/common/wolfssl_dummy.c @@ -1,6 +1,6 @@ /* wolfssl_dummy.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/test/src/key_data.c b/IDE/Renesas/e2studio/Projects/test/src/key_data.c index c924f8f81..cef0a9c99 100644 --- a/IDE/Renesas/e2studio/Projects/test/src/key_data.c +++ b/IDE/Renesas/e2studio/Projects/test/src/key_data.c @@ -1,6 +1,6 @@ /* key_data.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include "key_data.h" #ifdef WOLFSSL_RENESAS_TSIP diff --git a/IDE/Renesas/e2studio/Projects/test/src/key_data.h b/IDE/Renesas/e2studio/Projects/test/src/key_data.h index 8152b2946..e2e53e72a 100644 --- a/IDE/Renesas/e2studio/Projects/test/src/key_data.h +++ b/IDE/Renesas/e2studio/Projects/test/src/key_data.h @@ -1,6 +1,6 @@ /* key_data.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef KEY_DATA_H_ #define KEY_DATA_H_ #include diff --git a/IDE/Renesas/e2studio/Projects/test/src/test_main.c b/IDE/Renesas/e2studio/Projects/test/src/test_main.c index 252d08bfc..063d41a73 100644 --- a/IDE/Renesas/e2studio/Projects/test/src/test_main.c +++ b/IDE/Renesas/e2studio/Projects/test/src/test_main.c @@ -1,6 +1,6 @@ /* test_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/test/src/wolf_client.c b/IDE/Renesas/e2studio/Projects/test/src/wolf_client.c index 7122bd811..5f0e96ac1 100644 --- a/IDE/Renesas/e2studio/Projects/test/src/wolf_client.c +++ b/IDE/Renesas/e2studio/Projects/test/src/wolf_client.c @@ -1,6 +1,6 @@ /* wolf_client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/test/src/wolf_server.c b/IDE/Renesas/e2studio/Projects/test/src/wolf_server.c index 5d38b0358..b193fbe71 100644 --- a/IDE/Renesas/e2studio/Projects/test/src/wolf_server.c +++ b/IDE/Renesas/e2studio/Projects/test/src/wolf_server.c @@ -1,6 +1,6 @@ /* wolf_server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h b/IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h index 3127a9f7c..0241f9196 100644 --- a/IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h +++ b/IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h @@ -1,6 +1,6 @@ /* wolfssl_demo.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/benchmark-wolfcrypt/src/wolfssl_thread_entry.c b/IDE/Renesas/e2studio/RA6M3/benchmark-wolfcrypt/src/wolfssl_thread_entry.c index 67629b1c4..d56ee00db 100644 --- a/IDE/Renesas/e2studio/RA6M3/benchmark-wolfcrypt/src/wolfssl_thread_entry.c +++ b/IDE/Renesas/e2studio/RA6M3/benchmark-wolfcrypt/src/wolfssl_thread_entry.c @@ -1,6 +1,6 @@ /* wolfssl_thread_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/client-wolfssl/src/wolfssl_thread_entry.c b/IDE/Renesas/e2studio/RA6M3/client-wolfssl/src/wolfssl_thread_entry.c index a7a6d3f72..c21a2cc17 100644 --- a/IDE/Renesas/e2studio/RA6M3/client-wolfssl/src/wolfssl_thread_entry.c +++ b/IDE/Renesas/e2studio/RA6M3/client-wolfssl/src/wolfssl_thread_entry.c @@ -1,6 +1,6 @@ /* wolfssl_thread_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/client-wolfssl/wolfssl_thread_entry.h b/IDE/Renesas/e2studio/RA6M3/client-wolfssl/wolfssl_thread_entry.h index 8184edbb2..cd1ca54b7 100644 --- a/IDE/Renesas/e2studio/RA6M3/client-wolfssl/wolfssl_thread_entry.h +++ b/IDE/Renesas/e2studio/RA6M3/client-wolfssl/wolfssl_thread_entry.h @@ -1,6 +1,6 @@ /* wolfssl_thread_entry.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/common/src/freertos_tcp_port.c b/IDE/Renesas/e2studio/RA6M3/common/src/freertos_tcp_port.c index 9e5715316..a10162026 100644 --- a/IDE/Renesas/e2studio/RA6M3/common/src/freertos_tcp_port.c +++ b/IDE/Renesas/e2studio/RA6M3/common/src/freertos_tcp_port.c @@ -1,6 +1,6 @@ /* freertos_tcp_port.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/common/user_settings.h b/IDE/Renesas/e2studio/RA6M3/common/user_settings.h index 4a496e751..41550dd47 100644 --- a/IDE/Renesas/e2studio/RA6M3/common/user_settings.h +++ b/IDE/Renesas/e2studio/RA6M3/common/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/common/util.h b/IDE/Renesas/e2studio/RA6M3/common/util.h index 805415b04..f1445ff45 100644 --- a/IDE/Renesas/e2studio/RA6M3/common/util.h +++ b/IDE/Renesas/e2studio/RA6M3/common/util.h @@ -1,6 +1,6 @@ /* util.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/server-wolfssl/src/wolfssl_thread_entry.c b/IDE/Renesas/e2studio/RA6M3/server-wolfssl/src/wolfssl_thread_entry.c index 04518edb8..d09dd5ccb 100644 --- a/IDE/Renesas/e2studio/RA6M3/server-wolfssl/src/wolfssl_thread_entry.c +++ b/IDE/Renesas/e2studio/RA6M3/server-wolfssl/src/wolfssl_thread_entry.c @@ -1,6 +1,6 @@ /* wolfssl_thread_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/server-wolfssl/wolfssl_thread_entry.h b/IDE/Renesas/e2studio/RA6M3/server-wolfssl/wolfssl_thread_entry.h index 66ffb506f..003164f60 100644 --- a/IDE/Renesas/e2studio/RA6M3/server-wolfssl/wolfssl_thread_entry.h +++ b/IDE/Renesas/e2studio/RA6M3/server-wolfssl/wolfssl_thread_entry.h @@ -1,6 +1,6 @@ /* wolfssl_thread_entry.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RA6M3/test-wolfcrypt/src/wolfssl_thread_entry.c b/IDE/Renesas/e2studio/RA6M3/test-wolfcrypt/src/wolfssl_thread_entry.c index 96629a8ba..665e8f11f 100644 --- a/IDE/Renesas/e2studio/RA6M3/test-wolfcrypt/src/wolfssl_thread_entry.c +++ b/IDE/Renesas/e2studio/RA6M3/test-wolfcrypt/src/wolfssl_thread_entry.c @@ -1,6 +1,6 @@ /* wolfssl_thread_entry.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h index fd2cf86e6..e3752588e 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/strings.h @@ -1,6 +1,6 @@ /* strings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h index d91dd4790..962ad47ee 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/unistd.h @@ -1,6 +1,6 @@ /* unistd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h index bcc83bdb7..153ee8554 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c index 8fa6340b4..a31c43cdc 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/common/wolfssl_dummy.c @@ -1,6 +1,6 @@ /* wolfssl_dummy.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c index 6dfac9811..745c6fe29 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.c @@ -1,6 +1,6 @@ /* key_data.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include "key_data.h" /*------------------------------------------------------------------------- diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h index 74e9ed242..b04ea27ea 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/key_data.h @@ -1,6 +1,6 @@ /* key_data.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c index 7d336826a..5979896f8 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/test_main.c @@ -1,6 +1,6 @@ /* test_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c index ff09b1a80..cc1eeac79 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_client.c @@ -1,6 +1,6 @@ /* wolf_client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c index 5d38b0358..b193fbe71 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolf_server.c @@ -1,6 +1,6 @@ /* wolf_server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h index b2a272245..d82743a7e 100644 --- a/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h +++ b/IDE/Renesas/e2studio/RX72NEnvisionKit/test/src/wolfssl_demo.h @@ -1,6 +1,6 @@ /* wolfssl_demo.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/STM32Cube/default_conf.ftl b/IDE/STM32Cube/default_conf.ftl index 3f67578e5..f7f21e6be 100644 --- a/IDE/STM32Cube/default_conf.ftl +++ b/IDE/STM32Cube/default_conf.ftl @@ -122,6 +122,11 @@ extern ${variable.value} ${variable.name}; #define HAL_CONSOLE_UART huart2 #define NO_STM32_RNG #define WOLFSSL_GENSEED_FORTEST +#elif defined(STM32G071xx) + #define WOLFSSL_STM32G0 + #define HAL_CONSOLE_UART huart2 + #define NO_STM32_RNG + #define WOLFSSL_GENSEED_FORTEST #else #warning Please define a hardware platform! /* This means there is not a pre-defined platform for your board/CPU */ diff --git a/IDE/STM32Cube/main.c b/IDE/STM32Cube/main.c index a2d8e0eb2..149f04397 100644 --- a/IDE/STM32Cube/main.c +++ b/IDE/STM32Cube/main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/STM32Cube/wolfSSL_conf.h b/IDE/STM32Cube/wolfSSL_conf.h index 1f74bb4bc..0cc1c1261 100644 --- a/IDE/STM32Cube/wolfSSL_conf.h +++ b/IDE/STM32Cube/wolfSSL_conf.h @@ -1,6 +1,6 @@ /* wolfSSL_conf.h (example of generated wolfSSL.I-CUBE-wolfSSL_conf.h) * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -177,6 +177,11 @@ #define HAL_CONSOLE_UART huart2 #define NO_STM32_RNG #define WOLFSSL_GENSEED_FORTEST +#elif defined(STM32G071xx) + #define WOLFSSL_STM32G0 + #define HAL_CONSOLE_UART huart2 + #define NO_STM32_RNG + #define WOLFSSL_GENSEED_FORTEST #else #warning Please define a hardware platform! /* This means there is not a pre-defined platform for your board/CPU */ diff --git a/IDE/STM32Cube/wolfssl_example.c b/IDE/STM32Cube/wolfssl_example.c index f604c1788..8347ed4dc 100644 --- a/IDE/STM32Cube/wolfssl_example.c +++ b/IDE/STM32Cube/wolfssl_example.c @@ -1,6 +1,6 @@ /* wolfssl_example.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/STM32Cube/wolfssl_example.h b/IDE/STM32Cube/wolfssl_example.h index f43884d87..341667fd8 100644 --- a/IDE/STM32Cube/wolfssl_example.h +++ b/IDE/STM32Cube/wolfssl_example.h @@ -1,6 +1,6 @@ /* wolfssl_example.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/VS-AZURE-SPHERE/client/client.c b/IDE/VS-AZURE-SPHERE/client/client.c index 82a236687..8b8c43812 100644 --- a/IDE/VS-AZURE-SPHERE/client/client.c +++ b/IDE/VS-AZURE-SPHERE/client/client.c @@ -1,6 +1,6 @@ /* client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include "client.h" diff --git a/IDE/VS-AZURE-SPHERE/client/client.h b/IDE/VS-AZURE-SPHERE/client/client.h index e24aa3ac1..8443a084a 100644 --- a/IDE/VS-AZURE-SPHERE/client/client.h +++ b/IDE/VS-AZURE-SPHERE/client/client.h @@ -1,6 +1,6 @@ /* client.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_CLIENT_H #define WOLFSSL_CLIENT_H diff --git a/IDE/VS-AZURE-SPHERE/server/server.c b/IDE/VS-AZURE-SPHERE/server/server.c index 48a7922bf..a262dc417 100644 --- a/IDE/VS-AZURE-SPHERE/server/server.c +++ b/IDE/VS-AZURE-SPHERE/server/server.c @@ -1,8 +1,8 @@ /* server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include "server.h" diff --git a/IDE/VS-AZURE-SPHERE/server/server.h b/IDE/VS-AZURE-SPHERE/server/server.h index 29ea245be..d623782dc 100644 --- a/IDE/VS-AZURE-SPHERE/server/server.h +++ b/IDE/VS-AZURE-SPHERE/server/server.h @@ -1,6 +1,6 @@ /* server.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_SERVER_H diff --git a/IDE/VisualDSP/user_settings.h b/IDE/VisualDSP/user_settings.h index f0fa67553..d4fbdbfd1 100644 --- a/IDE/VisualDSP/user_settings.h +++ b/IDE/VisualDSP/user_settings.h @@ -350,9 +350,6 @@ extern "C" { #undef WOLFSSL_SHA3 #if 1 #define WOLFSSL_SHA3 - #ifdef HAVE_FIPS - #define WOLFSSL_NO_SHAKE256 - #endif #endif /* MD5 */ diff --git a/IDE/WIN/user_settings.h b/IDE/WIN/user_settings.h index 43c7f3ab3..8152b1def 100644 --- a/IDE/WIN/user_settings.h +++ b/IDE/WIN/user_settings.h @@ -57,11 +57,23 @@ #define WOLFSSL_AESNI #endif - /* Single Precision Support for RSA/DH 1024/2048/3072 and ECC P-256 */ + /* Single Precision Support for RSA/DH 1024/2048/3072 and + * ECC P-256/P-384 */ #define WOLFSSL_SP #define WOLFSSL_HAVE_SP_ECC #define WOLFSSL_HAVE_SP_DH #define WOLFSSL_HAVE_SP_RSA + + #ifdef _WIN64 + /* Old versions of MASM compiler do not recognize newer + * instructions. */ + #if 0 + #define NO_AVX2_SUPPORT + #define NO_MOVBE_SUPPORT + #endif + #define WOLFSSL_SP_ASM + #define WOLFSSL_SP_X86_64_ASM + #endif #endif #else diff --git a/IDE/WINCE/include.am b/IDE/WINCE/include.am new file mode 100644 index 000000000..052fdce8a --- /dev/null +++ b/IDE/WINCE/include.am @@ -0,0 +1,5 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= IDE/WINCE/user_settings.h diff --git a/IDE/WINCE/user_settings.h b/IDE/WINCE/user_settings.h new file mode 100644 index 000000000..4a29cc87d --- /dev/null +++ b/IDE/WINCE/user_settings.h @@ -0,0 +1,341 @@ +#ifndef _WIN_USER_SETTINGS_H_ +#define _WIN_USER_SETTINGS_H_ + +/* For FIPS Ready, uncomment the following: */ +/* #define WOLFSSL_FIPS_READY */ +#ifdef WOLFSSL_FIPS_READY + #undef HAVE_FIPS_VERSION + #define HAVE_FIPS_VERSION 3 +#endif + + +/* Verify this is Windows */ +#ifndef _WIN32 +#error This user_settings.h header is only designed for Windows +#endif + +/* Configurations */ +#define WOLFCRYPT_ONLY + +#undef USE_FAST_MATH +#if 1 + #define USE_FAST_MATH + + #undef TFM_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + + /* Optimizations */ + //#define TFM_ARM +#endif + +/* Wolf Single Precision Math */ +#undef WOLFSSL_SP +#if 0 + #define WOLFSSL_SP + //#define WOLFSSL_SP_SMALL /* use smaller version of code */ + #define WOLFSSL_HAVE_SP_RSA + #define WOLFSSL_HAVE_SP_DH + #define WOLFSSL_HAVE_SP_ECC + //#define WOLFSSL_SP_CACHE_RESISTANT + //#define WOLFSSL_SP_MATH /* only SP math - eliminates fast math code */ + + /* SP Assembly Speedups */ + //#define WOLFSSL_SP_ASM /* required if using the ASM versions */ + //#define WOLFSSL_SP_ARM32_ASM + //#define WOLFSSL_SP_ARM64_ASM + //#define WOLFSSL_SP_ARM_THUMB_ASM + //#define WOLFSSL_SP_ARM_CORTEX_M_ASM +#endif + +/* ------------------------------------------------------------------------- */ +/* FIPS - Requires eval or license from wolfSSL */ +/* ------------------------------------------------------------------------- */ +#undef HAVE_FIPS +#if 1 + #define HAVE_FIPS + + #undef HAVE_FIPS_VERSION + #define HAVE_FIPS_VERSION 2 + + #ifdef SINGLE_THREADED + #undef NO_THREAD_LS + #define NO_THREAD_LS + #else + #ifndef USE_WINDOWS_API + #define USE_WINDOWS_API + #endif + #endif + + #undef NO_ATTRIBUTE_CONSTRUCTOR + //#define NO_ATTRIBUTE_CONSTRUCTOR + +#endif + + +/* FIPS */ +//#define OPENSSL_EXTRA +//#define HAVE_THREAD_LS +#define WOLFSSL_KEY_GEN +#define HAVE_AESGCM +#define HAVE_HASHDRBG +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 +#define NO_PSK +#define NO_HC128 +#define NO_RC4 +#define NO_RABBIT +//#define NO_DSA +#define NO_MD4 + +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* ------------------------------------------------------------------------- */ + /* Crypto */ + /* ------------------------------------------------------------------------- */ + #define USE_CERT_BUFFERS_2048 + #define USE_CERT_BUFFERS_256 + /* RSA */ + #undef NO_RSA + #if 1 + #ifdef USE_FAST_MATH + /* Maximum math bits (Max RSA key bits * 2) */ + #undef FP_MAX_BITS + #define FP_MAX_BITS 8192 + #endif + + /* half as much memory but twice as slow */ + #undef RSA_LOW_MEM + //#define RSA_LOW_MEM + + /* Enables blinding mode, to prevent timing attacks */ + #if 0 + #undef WC_RSA_BLINDING + #define WC_RSA_BLINDING + #else + #undef WC_NO_HARDEN + #define WC_NO_HARDEN + #endif + + /* RSA PSS Support */ + #if 1 + #define WC_RSA_PSS + #endif + + #if 1 + #define WC_RSA_NO_PADDING + #endif + #else + #define NO_RSA + #endif + /* ECC */ + #undef HAVE_ECC + #if 1 + #define HAVE_ECC + + /* Manually define enabled curves */ + #undef ECC_USER_CURVES + //#define ECC_USER_CURVES + + #ifdef ECC_USER_CURVES + /* Manual Curve Selection */ + //#define HAVE_ECC192 + //#define HAVE_ECC224 + #undef NO_ECC256 + //#define HAVE_ECC384 + //#define HAVE_ECC521 + #endif + + /* Fixed point cache (speeds repeated operations against same private key) */ + #undef FP_ECC + //#define FP_ECC + #ifdef FP_ECC + /* Bits / Entries */ + #undef FP_ENTRIES + #define FP_ENTRIES 2 + #undef FP_LUT + #define FP_LUT 4 + #endif + + /* Optional ECC calculation method */ + /* Note: doubles heap usage, but slightly faster */ + #undef ECC_SHAMIR + #define ECC_SHAMIR + + /* Reduces heap usage, but slower */ + #undef ECC_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + + #ifdef HAVE_FIPS + #undef HAVE_ECC_CDH + #define HAVE_ECC_CDH /* Enable cofactor support */ + + #undef NO_STRICT_ECDSA_LEN + #define NO_STRICT_ECDSA_LEN /* Do not force fixed len w/ FIPS */ + + #undef WOLFSSL_VALIDATE_ECC_IMPORT + #define WOLFSSL_VALIDATE_ECC_IMPORT /* Validate import */ + #endif + + /* Compressed Key Support */ + #undef HAVE_COMP_KEY + //#define HAVE_COMP_KEY + + /* Use alternate ECC size for ECC math */ + #ifdef USE_FAST_MATH + /* MAX ECC BITS = ROUND8(MAX ECC) * 2 */ + #ifdef NO_RSA + /* Custom fastmath size if not using RSA */ + #undef FP_MAX_BITS + #define FP_MAX_BITS (256 * 2) + #else + #undef ALT_ECC_SIZE + #define ALT_ECC_SIZE + /* wolfSSL will compute the FP_MAX_BITS_ECC, but it can be overriden */ + //#undef FP_MAX_BITS_ECC + //#define FP_MAX_BITS_ECC (256 * 2) + #endif + + /* Speedups specific to curve */ + #ifndef NO_ECC256 + #undef TFM_ECC256 + #define TFM_ECC256 + #endif + #endif + #endif + + /* AES */ + #undef NO_AES + #if 1 + #undef HAVE_AES_CBC + #define HAVE_AES_CBC + + #undef HAVE_AESGCM + #define HAVE_AESGCM + + /* GCM Method: GCM_SMALL, GCM_WORD32 or GCM_TABLE */ + //#define GCM_SMALL + //#define GCM_WORD32 + #define GCM_TABLE + + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + + #undef HAVE_AES_ECB + #define HAVE_AES_ECB + + #undef WOLFSSL_AES_COUNTER + #define WOLFSSL_AES_COUNTER + + #undef HAVE_AESCCM + #define HAVE_AESCCM + + #else + #define NO_AES + #endif + + + /* DES3 */ + #undef NO_DES3 + #if 1 + #else + #define NO_DES3 + #endif + + /* ------------------------------------------------------------------------- */ + /* Hashing */ + /* ------------------------------------------------------------------------- */ + /* Sha */ + #undef NO_SHA + #if 1 + /* 1k smaller, but 25% slower */ + //#define USE_SLOW_SHA + #else + #define NO_SHA + #endif + + /* Sha256 */ + #undef NO_SHA256 + #if 1 + /* not unrolled - ~2k smaller and ~25% slower */ + //#define USE_SLOW_SHA256 + + /* Sha224 */ + #if 1 + #define WOLFSSL_SHA224 + #endif + #else + #define NO_SHA256 + #endif + + /* Sha512 */ + #undef WOLFSSL_SHA512 + #if 1 + #define WOLFSSL_SHA512 + + /* Sha384 */ + #undef WOLFSSL_SHA384 + #if 1 + #define WOLFSSL_SHA384 + #endif + + /* over twice as small, but 50% slower */ + //#define USE_SLOW_SHA512 + #endif + + /* Sha3 */ + #undef WOLFSSL_SHA3 + #if 1 + #define WOLFSSL_SHA3 + #endif + + /* MD5 */ + #undef NO_MD5 + #if 0 + + #else + #define NO_MD5 + #endif + + /* HKDF */ + #undef HAVE_HKDF + #if 1 + #define HAVE_HKDF + #endif + + /* CMAC */ + #undef WOLFSSL_CMAC + #if 1 + #define WOLFSSL_CMAC + #endif + + /* DH */ + #undef NO_DH + #if 1 + /* Use table for DH instead of -lm (math) lib dependency */ + #if 0 + #define WOLFSSL_DH_CONST + #define HAVE_FFDHE_2048 + #define HAVE_FFDHE_4096 + //#define HAVE_FFDHE_6144 + //#define HAVE_FFDHE_8192 + #endif + + #ifdef HAVE_FIPS + #define WOLFSSL_VALIDATE_FFC_IMPORT + #define HAVE_FFDHE_Q + #endif + #else + #define NO_DH + #endif +#endif /* FIPS v2 */ + +//#define DEBUG_WOLFSSL +#define NO_MAIN_DRIVER + +/* wolfEngine settings */ +#define WOLFSSL_PUBLIC_MP +#define NO_WOLFSSL_DIR + +//#define WOLFENGINE_DEBUG +/* TODO: Add WE_HAVE_* settings here */ + +#endif /* _WIN_USER_SETTINGS_H_ */ diff --git a/IDE/XCODE/Benchmark/wolfBench/AppDelegate.h b/IDE/XCODE/Benchmark/wolfBench/AppDelegate.h index ea0887488..dc7165087 100644 --- a/IDE/XCODE/Benchmark/wolfBench/AppDelegate.h +++ b/IDE/XCODE/Benchmark/wolfBench/AppDelegate.h @@ -1,6 +1,6 @@ /* AppDelegate.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/XCODE/Benchmark/wolfBench/AppDelegate.m b/IDE/XCODE/Benchmark/wolfBench/AppDelegate.m index 1dc369087..1da758448 100644 --- a/IDE/XCODE/Benchmark/wolfBench/AppDelegate.m +++ b/IDE/XCODE/Benchmark/wolfBench/AppDelegate.m @@ -1,6 +1,6 @@ /* AppDelegate.m * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/XCODE/Benchmark/wolfBench/ViewController.h b/IDE/XCODE/Benchmark/wolfBench/ViewController.h index 4990aabfd..4e9cfb8f3 100644 --- a/IDE/XCODE/Benchmark/wolfBench/ViewController.h +++ b/IDE/XCODE/Benchmark/wolfBench/ViewController.h @@ -1,6 +1,6 @@ /* ViewController.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/XCODE/Benchmark/wolfBench/ViewController.m b/IDE/XCODE/Benchmark/wolfBench/ViewController.m index fefbc87bd..ff0465b00 100644 --- a/IDE/XCODE/Benchmark/wolfBench/ViewController.m +++ b/IDE/XCODE/Benchmark/wolfBench/ViewController.m @@ -1,6 +1,6 @@ /* ViewController.m * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/XCODE/Benchmark/wolfBench/main.m b/IDE/XCODE/Benchmark/wolfBench/main.m index eddb4bef3..4ee19f302 100644 --- a/IDE/XCODE/Benchmark/wolfBench/main.m +++ b/IDE/XCODE/Benchmark/wolfBench/main.m @@ -1,6 +1,6 @@ /* main.m * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/XilinxSDK/user_settings.h b/IDE/XilinxSDK/user_settings.h index 670cc9cc7..01049b72b 100644 --- a/IDE/XilinxSDK/user_settings.h +++ b/IDE/XilinxSDK/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/XilinxSDK/wolfssl_example.c b/IDE/XilinxSDK/wolfssl_example.c index c67a12f69..eea82bd75 100644 --- a/IDE/XilinxSDK/wolfssl_example.c +++ b/IDE/XilinxSDK/wolfssl_example.c @@ -1,6 +1,6 @@ /* wolfssl_example.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/IDE/include.am b/IDE/include.am index 17b5e8ab8..c11e6e3a8 100644 --- a/IDE/include.am +++ b/IDE/include.am @@ -36,6 +36,8 @@ include IDE/HEXAGON/include.am include IDE/RISCV/include.am include IDE/XilinxSDK/include.am include IDE/VisualDSP/include.am +include IDE/QNX/include.am +include IDE/WINCE/include.am EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL IDE/LPCXPRESSO IDE/HEXIWEAR IDE/Espressif IDE/zephyr EXTRA_DIST+= IDE/OPENSTM32/README.md diff --git a/IDE/mynewt/apps.wolfcrypttest.pkg.yml b/IDE/mynewt/apps.wolfcrypttest.pkg.yml index 2ce68544e..bac9422c6 100644 --- a/IDE/mynewt/apps.wolfcrypttest.pkg.yml +++ b/IDE/mynewt/apps.wolfcrypttest.pkg.yml @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -16,6 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pkg.name: "apps/wolfcrypttest" diff --git a/IDE/mynewt/crypto.wolfssl.pkg.yml b/IDE/mynewt/crypto.wolfssl.pkg.yml index 0c516896a..f8951fef8 100644 --- a/IDE/mynewt/crypto.wolfssl.pkg.yml +++ b/IDE/mynewt/crypto.wolfssl.pkg.yml @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -16,6 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pkg.name: "crypto/wolfssl" diff --git a/IDE/zephyr/lib/settings/user_settings-tls-generic.h b/IDE/zephyr/lib/settings/user_settings-tls-generic.h index b59b88355..912ac0782 100644 --- a/IDE/zephyr/lib/settings/user_settings-tls-generic.h +++ b/IDE/zephyr/lib/settings/user_settings-tls-generic.h @@ -1,10 +1,23 @@ /* wolfssl options.h * generated from configure options * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifndef WOLFSSL_OPTIONS_H diff --git a/IDE/zephyr/wolfssl_tls_sock/src/tls_sock.c b/IDE/zephyr/wolfssl_tls_sock/src/tls_sock.c index f644c70da..0c0e9cb24 100644 --- a/IDE/zephyr/wolfssl_tls_sock/src/tls_sock.c +++ b/IDE/zephyr/wolfssl_tls_sock/src/tls_sock.c @@ -1,6 +1,6 @@ /* tls_sock.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -323,9 +323,7 @@ int wolfssl_server_accept_tcp(WOLFSSL* ssl, SOCKET_T* fd, SOCKET_T* acceptfd) if (ret == 0) { *acceptfd = clientfd; tcp_set_nonblocking(&clientfd); - } - if (ret == 0) { printf("Server has client\n"); if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) ret = -1; diff --git a/IDE/zephyr/wolfssl_tls_thread/src/tls_threaded.c b/IDE/zephyr/wolfssl_tls_thread/src/tls_threaded.c index c57d8df6a..6d8059b6e 100644 --- a/IDE/zephyr/wolfssl_tls_thread/src/tls_threaded.c +++ b/IDE/zephyr/wolfssl_tls_thread/src/tls_threaded.c @@ -1,6 +1,6 @@ /* tls_threaded.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/README b/README index bcb072d64..f3bfd5a40 100644 --- a/README +++ b/README @@ -82,6 +82,7 @@ Release 4.7.0 of wolfSSL embedded TLS has bug fixes and new features including: * Function wolfSSL_CTX_NoTicketTLSv12 added to enable turning off session tickets with TLS 1.2 while keeping TLS 1.3 session tickets available * Implement RFC 5705: Keying Material Exporters for TLS * Added --enable-reproducible-build flag for making more deterministic library outputs to assist debugging +* Added support for S/MIME (Secure/Multipurpose Internet Mail Extensions) bundles ### Fixes * Fix to free mutex when cert manager is free’d @@ -119,7 +120,7 @@ Release 4.7.0 of wolfSSL embedded TLS has bug fixes and new features including: * Out of directory builds resolved, wolfSSL can now be built in a separate directory than the root wolfssl directory ### Vulnerabilities -* [HIGH] CVE-2021-3336: In earlier versions of wolfSSL there exists a potential man in the middle attack on TLS 1.3 clients. Malicious attackers with a privileged network position can impersonate TLS 1.3 servers and bypass authentication. Users that have applications with client side code and have TLS 1.3 turned on, should update to the latest version of wolfSSL. Users that do not have TLS 1.3 turned on, or that are server side only, are NOT affected by this report. For the code change see https://github.com/wolfSSL/wolfssl/pull/3676. +* [HIGH] CVE-2021-3336: In earlier versions of wolfSSL there exists a potential man in the middle attack on TLS 1.3 clients. Malicious attackers with a privileged network position can impersonate TLS 1.3 servers and bypass authentication. Users that have applications with client side code and have TLS 1.3 turned on, should update to the latest version of wolfSSL. Users that do not have TLS 1.3 turned on, or that are server side only, are NOT affected by this report. For the code change see https://github.com/wolfSSL/wolfssl/pull/3676. Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis for the report. * [LOW] In the case of using custom ECC curves there is the potential for a crafted compressed ECC key that has a custom prime value to cause a hang when imported. This only affects applications that are loading in ECC keys with wolfSSL builds that have compressed ECC keys and custom ECC curves enabled. * [LOW] With TLS 1.3 authenticated-only ciphers a section of the server hello could contain 16 bytes of uninitialized data when sent to the connected peer. This affects only a specific build of wolfSSL with TLS 1.3 early data enabled and using authenticated-only ciphers with TLS 1.3. diff --git a/README.md b/README.md index 94bbdf5e5..075543457 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Release 4.7.0 of wolfSSL embedded TLS has bug fixes and new features including: * Function wolfSSL_CTX_NoTicketTLSv12 added to enable turning off session tickets with TLS 1.2 while keeping TLS 1.3 session tickets available * Implement RFC 5705: Keying Material Exporters for TLS * Added --enable-reproducible-build flag for making more deterministic library outputs to assist debugging +* Added support for S/MIME (Secure/Multipurpose Internet Mail Extensions) bundles ### Fixes * Fix to free mutex when cert manager is free’d @@ -122,7 +123,7 @@ Release 4.7.0 of wolfSSL embedded TLS has bug fixes and new features including: * Out of directory builds resolved, wolfSSL can now be built in a separate directory than the root wolfssl directory ### Vulnerabilities -* [HIGH] CVE-2021-3336: In earlier versions of wolfSSL there exists a potential man in the middle attack on TLS 1.3 clients. Malicious attackers with a privileged network position can impersonate TLS 1.3 servers and bypass authentication. Users that have applications with client side code and have TLS 1.3 turned on, should update to the latest version of wolfSSL. Users that do not have TLS 1.3 turned on, or that are server side only, are NOT affected by this report. For the code change see https://github.com/wolfSSL/wolfssl/pull/3676. +* [HIGH] CVE-2021-3336: In earlier versions of wolfSSL there exists a potential man in the middle attack on TLS 1.3 clients. Malicious attackers with a privileged network position can impersonate TLS 1.3 servers and bypass authentication. Users that have applications with client side code and have TLS 1.3 turned on, should update to the latest version of wolfSSL. Users that do not have TLS 1.3 turned on, or that are server side only, are NOT affected by this report. For the code change see https://github.com/wolfSSL/wolfssl/pull/3676. Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis for the report. * [LOW] In the case of using custom ECC curves there is the potential for a crafted compressed ECC key that has a custom prime value to cause a hang when imported. This only affects applications that are loading in ECC keys with wolfSSL builds that have compressed ECC keys and custom ECC curves enabled. * [LOW] With TLS 1.3 authenticated-only ciphers a section of the server hello could contain 16 bytes of uninitialized data when sent to the connected peer. This affects only a specific build of wolfSSL with TLS 1.3 early data enabled and using authenticated-only ciphers with TLS 1.3. @@ -154,3 +155,5 @@ More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html [TLS 1.3](https://www.wolfssl.com/docs/tls13/) [wolfSSL Vulnerabilities](https://www.wolfssl.com/docs/security-vulnerabilities/) + +[Additional wolfSSL Examples](https://github.com/wolfssl/wolfssl-examples) diff --git a/certs/crl/crl.der b/certs/crl/crl.der new file mode 100644 index 000000000..f8726dd52 Binary files /dev/null and b/certs/crl/crl.der differ diff --git a/certs/crl/crl2.der b/certs/crl/crl2.der new file mode 100644 index 000000000..f8726dd52 Binary files /dev/null and b/certs/crl/crl2.der differ diff --git a/certs/crl/gencrls.sh b/certs/crl/gencrls.sh index 7cf4bf6e4..4f2e22ad0 100755 --- a/certs/crl/gencrls.sh +++ b/certs/crl/gencrls.sh @@ -177,4 +177,9 @@ echo "Step 22" openssl ca -config ./wolfssl.cnf -gencrl -crldays 1000 -out caEcc384Crl.pem -keyfile ../ca-ecc384-key.pem -cert ../ca-ecc384-cert.pem check_result $? +# create crl and crl2 der files for unit test +echo "Step 23" +openssl crl -in crl.pem -inform PEM -out crl.der -outform DER +openssl crl -in crl2.pem -inform PEM -out crl2.der -outform DER + exit 0 diff --git a/certs/crl/include.am b/certs/crl/include.am index c5da8de99..6d6d9b2c6 100644 --- a/certs/crl/include.am +++ b/certs/crl/include.am @@ -10,7 +10,9 @@ EXTRA_DIST += \ certs/crl/crl2.pem \ certs/crl/caEccCrl.pem \ certs/crl/caEcc384Crl.pem \ - certs/crl/wolfssl.cnf + certs/crl/wolfssl.cnf \ + certs/crl/crl.der \ + certs/crl/crl2.der EXTRA_DIST += \ certs/crl/crl.revoked diff --git a/certs/crl/server-goodaltCrl.pem b/certs/crl/server-goodaltCrl.pem old mode 100644 new mode 100755 index 3abb81f3c..8550d9693 --- a/certs/crl/server-goodaltCrl.pem +++ b/certs/crl/server-goodaltCrl.pem @@ -1,38 +1,38 @@ Certificate Revocation List (CRL): Version 2 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: /C=US/ST=Montana/L=Bozeman/OU=Engineering/CN=www.nomatch.com/emailAddress=info@wolfssl.com - Last Update: Sep 19 21:21:24 2018 GMT - Next Update: Jun 15 21:21:24 2021 GMT + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com + Last Update: Jun 15 22:02:33 2021 GMT + Next Update: Mar 11 22:02:33 2024 GMT CRL extensions: X509v3 CRL Number: 1 No Revoked Certificates. Signature Algorithm: sha256WithRSAEncryption - 01:b3:58:8d:bf:27:46:70:f1:cc:29:71:24:0b:ba:e3:fc:d4: - c8:30:09:3a:5e:e5:61:c7:d2:02:61:63:ba:e1:06:25:eb:4e: - 04:77:dc:31:4d:59:84:63:ee:09:5d:41:dd:07:8f:07:15:71: - 79:cb:6c:67:a9:e5:53:01:7d:98:b0:d0:a2:36:7a:8c:bf:51: - 84:78:0e:b3:d8:ef:7c:b7:9e:de:c0:09:46:3d:43:e0:9d:a1: - d7:77:d2:a6:28:f7:9e:92:82:ba:a9:cc:a8:d0:2b:f8:09:9b: - fd:e4:2d:e6:d4:d5:60:2e:31:48:e8:55:3f:54:e9:f4:c4:78: - 4d:0a:43:9d:3a:2e:44:9a:e7:63:25:73:e7:c4:fb:71:2b:0d: - 3e:ad:e6:95:7d:60:95:4f:f6:cf:a7:52:59:e0:4b:f2:51:46: - 0a:0c:9c:2e:2d:55:ae:57:76:a7:4b:8e:48:53:87:f7:e3:3c: - 44:9b:70:17:96:c4:dc:f0:d1:43:a8:5e:59:5c:2d:4d:88:e6: - 07:20:e4:75:09:dd:c4:9a:46:5c:c5:1f:20:f8:8a:dc:07:3d: - f2:31:11:cd:43:d8:72:c7:8b:83:78:c1:e3:a5:bc:8e:87:2b: - be:fd:66:0f:ab:4b:82:df:9e:71:e8:de:69:4c:c0:93:e6:9f: - 9c:78:b0:05 + 8a:53:b8:29:0e:37:13:d7:8a:f8:3e:d3:c9:20:3b:fa:6c:8a: + 1c:59:3a:54:4d:93:ca:68:e2:b0:08:b3:23:d1:98:a5:0e:44: + 4c:19:e7:de:a1:e4:56:6e:c5:d2:9a:05:d4:d5:c7:07:8d:65: + ca:df:cf:5e:89:74:d3:9d:3f:1f:c4:1e:f2:cf:5c:e0:c7:a8: + 23:cc:c3:db:cb:f6:9d:55:3a:9d:7a:7a:4b:c7:b8:7e:d1:6f: + 17:d2:a3:03:2d:9f:97:12:12:e8:75:a0:2e:64:3e:f5:ae:72: + a6:52:4a:9d:fe:39:f5:82:fc:d7:cf:34:4d:c2:23:eb:64:95: + 44:e6:1d:4b:2b:26:87:6e:3a:d0:e9:93:26:f7:a5:fd:45:66: + 79:1f:14:93:1e:5d:92:07:f0:a1:53:ae:c3:32:b7:17:be:85: + 57:cb:4d:a3:1f:26:71:be:ae:21:10:4f:df:6d:3e:ca:0a:84: + 4c:b7:d2:29:b2:34:3e:5d:aa:0b:16:e1:c4:92:cc:aa:2d:13: + f0:7d:1d:cf:52:ff:15:4e:12:b3:ff:d9:b6:72:06:be:26:f7: + 78:85:2d:ba:65:4a:55:85:85:71:47:8d:fd:23:68:c8:cd:8b: + de:d3:8b:33:56:77:03:72:41:d6:29:81:d9:bf:ae:bb:55:3b: + da:b0:bc:b8 -----BEGIN X509 CRL----- MIIB3DCBxQIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCVVMxEDAOBgNV BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVy aW5nMRgwFgYDVQQDDA93d3cubm9tYXRjaC5jb20xHzAdBgkqhkiG9w0BCQEWEGlu -Zm9Ad29sZnNzbC5jb20XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIxMjEyNFqgDjAM -MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQABs1iNvydGcPHMKXEkC7rj -/NTIMAk6XuVhx9ICYWO64QYl604Ed9wxTVmEY+4JXUHdB48HFXF5y2xnqeVTAX2Y -sNCiNnqMv1GEeA6z2O98t57ewAlGPUPgnaHXd9KmKPeekoK6qcyo0Cv4CZv95C3m -1NVgLjFI6FU/VOn0xHhNCkOdOi5EmudjJXPnxPtxKw0+reaVfWCVT/bPp1JZ4Evy -UUYKDJwuLVWuV3anS45IU4f34zxEm3AXlsTc8NFDqF5ZXC1NiOYHIOR1Cd3EmkZc -xR8g+IrcBz3yMRHNQ9hyx4uDeMHjpbyOhyu+/WYPq0uC355x6N5pTMCT5p+ceLAF +Zm9Ad29sZnNzbC5jb20XDTIxMDYxNTIyMDIzM1oXDTI0MDMxMTIyMDIzM1qgDjAM +MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQCKU7gpDjcT14r4PtPJIDv6 +bIocWTpUTZPKaOKwCLMj0ZilDkRMGefeoeRWbsXSmgXU1ccHjWXK389eiXTTnT8f +xB7yz1zgx6gjzMPby/adVTqdenpLx7h+0W8X0qMDLZ+XEhLodaAuZD71rnKmUkqd +/jn1gvzXzzRNwiPrZJVE5h1LKyaHbjrQ6ZMm96X9RWZ5HxSTHl2SB/ChU67DMrcX +voVXy02jHyZxvq4hEE/fbT7KCoRMt9IpsjQ+XaoLFuHEksyqLRPwfR3PUv8VThKz +/9m2cga+Jvd4hS26ZUpVhYVxR439I2jIzYve04szVncDckHWKYHZv667VTvasLy4 -----END X509 CRL----- diff --git a/certs/crl/server-goodaltwildCrl.pem b/certs/crl/server-goodaltwildCrl.pem old mode 100644 new mode 100755 index 3abb81f3c..8550d9693 --- a/certs/crl/server-goodaltwildCrl.pem +++ b/certs/crl/server-goodaltwildCrl.pem @@ -1,38 +1,38 @@ Certificate Revocation List (CRL): Version 2 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: /C=US/ST=Montana/L=Bozeman/OU=Engineering/CN=www.nomatch.com/emailAddress=info@wolfssl.com - Last Update: Sep 19 21:21:24 2018 GMT - Next Update: Jun 15 21:21:24 2021 GMT + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com + Last Update: Jun 15 22:02:33 2021 GMT + Next Update: Mar 11 22:02:33 2024 GMT CRL extensions: X509v3 CRL Number: 1 No Revoked Certificates. Signature Algorithm: sha256WithRSAEncryption - 01:b3:58:8d:bf:27:46:70:f1:cc:29:71:24:0b:ba:e3:fc:d4: - c8:30:09:3a:5e:e5:61:c7:d2:02:61:63:ba:e1:06:25:eb:4e: - 04:77:dc:31:4d:59:84:63:ee:09:5d:41:dd:07:8f:07:15:71: - 79:cb:6c:67:a9:e5:53:01:7d:98:b0:d0:a2:36:7a:8c:bf:51: - 84:78:0e:b3:d8:ef:7c:b7:9e:de:c0:09:46:3d:43:e0:9d:a1: - d7:77:d2:a6:28:f7:9e:92:82:ba:a9:cc:a8:d0:2b:f8:09:9b: - fd:e4:2d:e6:d4:d5:60:2e:31:48:e8:55:3f:54:e9:f4:c4:78: - 4d:0a:43:9d:3a:2e:44:9a:e7:63:25:73:e7:c4:fb:71:2b:0d: - 3e:ad:e6:95:7d:60:95:4f:f6:cf:a7:52:59:e0:4b:f2:51:46: - 0a:0c:9c:2e:2d:55:ae:57:76:a7:4b:8e:48:53:87:f7:e3:3c: - 44:9b:70:17:96:c4:dc:f0:d1:43:a8:5e:59:5c:2d:4d:88:e6: - 07:20:e4:75:09:dd:c4:9a:46:5c:c5:1f:20:f8:8a:dc:07:3d: - f2:31:11:cd:43:d8:72:c7:8b:83:78:c1:e3:a5:bc:8e:87:2b: - be:fd:66:0f:ab:4b:82:df:9e:71:e8:de:69:4c:c0:93:e6:9f: - 9c:78:b0:05 + 8a:53:b8:29:0e:37:13:d7:8a:f8:3e:d3:c9:20:3b:fa:6c:8a: + 1c:59:3a:54:4d:93:ca:68:e2:b0:08:b3:23:d1:98:a5:0e:44: + 4c:19:e7:de:a1:e4:56:6e:c5:d2:9a:05:d4:d5:c7:07:8d:65: + ca:df:cf:5e:89:74:d3:9d:3f:1f:c4:1e:f2:cf:5c:e0:c7:a8: + 23:cc:c3:db:cb:f6:9d:55:3a:9d:7a:7a:4b:c7:b8:7e:d1:6f: + 17:d2:a3:03:2d:9f:97:12:12:e8:75:a0:2e:64:3e:f5:ae:72: + a6:52:4a:9d:fe:39:f5:82:fc:d7:cf:34:4d:c2:23:eb:64:95: + 44:e6:1d:4b:2b:26:87:6e:3a:d0:e9:93:26:f7:a5:fd:45:66: + 79:1f:14:93:1e:5d:92:07:f0:a1:53:ae:c3:32:b7:17:be:85: + 57:cb:4d:a3:1f:26:71:be:ae:21:10:4f:df:6d:3e:ca:0a:84: + 4c:b7:d2:29:b2:34:3e:5d:aa:0b:16:e1:c4:92:cc:aa:2d:13: + f0:7d:1d:cf:52:ff:15:4e:12:b3:ff:d9:b6:72:06:be:26:f7: + 78:85:2d:ba:65:4a:55:85:85:71:47:8d:fd:23:68:c8:cd:8b: + de:d3:8b:33:56:77:03:72:41:d6:29:81:d9:bf:ae:bb:55:3b: + da:b0:bc:b8 -----BEGIN X509 CRL----- MIIB3DCBxQIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCVVMxEDAOBgNV BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVy aW5nMRgwFgYDVQQDDA93d3cubm9tYXRjaC5jb20xHzAdBgkqhkiG9w0BCQEWEGlu -Zm9Ad29sZnNzbC5jb20XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIxMjEyNFqgDjAM -MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQABs1iNvydGcPHMKXEkC7rj -/NTIMAk6XuVhx9ICYWO64QYl604Ed9wxTVmEY+4JXUHdB48HFXF5y2xnqeVTAX2Y -sNCiNnqMv1GEeA6z2O98t57ewAlGPUPgnaHXd9KmKPeekoK6qcyo0Cv4CZv95C3m -1NVgLjFI6FU/VOn0xHhNCkOdOi5EmudjJXPnxPtxKw0+reaVfWCVT/bPp1JZ4Evy -UUYKDJwuLVWuV3anS45IU4f34zxEm3AXlsTc8NFDqF5ZXC1NiOYHIOR1Cd3EmkZc -xR8g+IrcBz3yMRHNQ9hyx4uDeMHjpbyOhyu+/WYPq0uC355x6N5pTMCT5p+ceLAF +Zm9Ad29sZnNzbC5jb20XDTIxMDYxNTIyMDIzM1oXDTI0MDMxMTIyMDIzM1qgDjAM +MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQCKU7gpDjcT14r4PtPJIDv6 +bIocWTpUTZPKaOKwCLMj0ZilDkRMGefeoeRWbsXSmgXU1ccHjWXK389eiXTTnT8f +xB7yz1zgx6gjzMPby/adVTqdenpLx7h+0W8X0qMDLZ+XEhLodaAuZD71rnKmUkqd +/jn1gvzXzzRNwiPrZJVE5h1LKyaHbjrQ6ZMm96X9RWZ5HxSTHl2SB/ChU67DMrcX +voVXy02jHyZxvq4hEE/fbT7KCoRMt9IpsjQ+XaoLFuHEksyqLRPwfR3PUv8VThKz +/9m2cga+Jvd4hS26ZUpVhYVxR439I2jIzYve04szVncDckHWKYHZv667VTvasLy4 -----END X509 CRL----- diff --git a/certs/crl/server-goodcnCrl.pem b/certs/crl/server-goodcnCrl.pem old mode 100644 new mode 100755 index 79e56efc1..a68d97881 --- a/certs/crl/server-goodcnCrl.pem +++ b/certs/crl/server-goodcnCrl.pem @@ -1,38 +1,38 @@ Certificate Revocation List (CRL): Version 2 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: /C=US/ST=Montana/L=Bozeman/OU=Engineering/CN=localhost/emailAddress=info@wolfssl.com - Last Update: Sep 19 21:21:24 2018 GMT - Next Update: Jun 15 21:21:24 2021 GMT + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com + Last Update: Jun 15 22:02:33 2021 GMT + Next Update: Mar 11 22:02:33 2024 GMT CRL extensions: X509v3 CRL Number: 1 No Revoked Certificates. Signature Algorithm: sha256WithRSAEncryption - 2c:f5:7a:4f:67:06:9b:f2:56:8c:e1:00:05:70:60:5b:60:51: - ad:65:7e:10:69:c9:84:98:b6:66:33:18:ba:f8:86:f9:23:e3: - ac:42:53:1d:27:5d:28:6a:d7:1c:a2:28:4d:02:01:c4:23:c1: - b8:ac:d3:ba:e1:75:d0:2e:ad:98:78:39:f2:c1:6b:7b:4b:78: - f2:f6:49:6f:92:2e:59:91:e9:de:7f:ef:62:5e:77:df:1c:a9: - 1a:d5:b8:63:1f:53:0e:b7:28:f8:5e:61:11:1b:b4:dd:9c:85: - 77:45:7d:31:fc:61:ab:55:f9:8d:50:ce:56:a0:ff:c0:a8:60: - b5:7a:ec:f1:6a:c8:94:be:89:41:47:a2:22:d9:9d:8e:f7:36: - d2:6f:bc:ce:04:3d:b7:9d:5c:82:37:59:9f:67:15:78:a0:a7: - c1:2f:01:d5:f0:ac:0f:34:21:d7:16:c8:dc:b1:af:60:e0:b1: - de:88:6f:d9:e5:32:c2:63:01:79:e6:10:ef:30:ef:c2:c6:08: - 89:cc:21:76:b8:ee:18:bc:88:66:7a:88:89:b4:ba:d9:02:00: - 92:73:6a:b5:84:ec:0c:9c:fc:d1:c1:0f:f2:e2:18:30:a6:be: - 1d:99:8b:16:26:65:fd:fe:15:48:16:1d:68:0b:1e:b4:a0:0d: - ec:93:cb:a2 + 00:64:45:a0:7a:db:6a:39:fb:5b:ac:38:18:9c:dd:62:a9:8d: + 8f:76:64:1f:42:07:81:81:57:e3:58:14:cd:5c:49:53:cb:30: + fc:4e:28:0d:29:8e:12:96:f7:d3:59:87:27:cf:b9:70:95:79: + dc:2a:08:ce:0c:e8:96:fc:95:b3:d0:89:18:8d:7a:80:45:dc: + 66:32:3b:e7:65:93:ed:87:59:f5:4b:4d:c9:88:f2:54:e3:b0: + d5:3d:29:1f:ff:01:7f:13:88:5b:1a:0c:bd:84:c0:ab:ea:7a: + cb:ea:bb:80:35:fa:e5:5d:72:8c:2b:5a:48:2d:b6:c7:90:fa: + 32:71:e4:f5:ec:59:a0:b5:38:7e:0a:68:d7:f3:ab:c8:a1:33: + b6:1f:54:11:d1:a4:87:d7:a6:99:2f:c1:08:0a:a6:e8:91:12: + a9:e7:fe:46:84:a2:a8:6a:40:c8:b5:6c:28:f5:ad:80:34:98: + 69:ae:a5:16:ca:e9:85:07:21:39:11:be:82:f0:9d:dc:6c:af: + 24:8a:05:e9:26:14:c2:d5:f0:12:ba:73:dc:73:b9:31:24:5f: + a1:d5:cc:a5:f2:f3:85:33:b2:2b:50:8f:33:c9:85:b1:b9:20: + 37:a8:92:55:66:45:06:da:3c:7b:85:c0:70:6d:fd:ae:e6:17: + 5b:78:40:ae -----BEGIN X509 CRL----- MIIB1TCBvgIBATANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzEQMA4GA1UE CAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJp bmcxEjAQBgNVBAMMCWxvY2FsaG9zdDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm -c3NsLmNvbRcNMTgwOTE5MjEyMTI0WhcNMjEwNjE1MjEyMTI0WqAOMAwwCgYDVR0U -BAMCAQEwDQYJKoZIhvcNAQELBQADggEBACz1ek9nBpvyVozhAAVwYFtgUa1lfhBp -yYSYtmYzGLr4hvkj46xCUx0nXShq1xyiKE0CAcQjwbis07rhddAurZh4OfLBa3tL -ePL2SW+SLlmR6d5/72Jed98cqRrVuGMfUw63KPheYREbtN2chXdFfTH8YatV+Y1Q -zlag/8CoYLV67PFqyJS+iUFHoiLZnY73NtJvvM4EPbedXII3WZ9nFXigp8EvAdXw -rA80IdcWyNyxr2Dgsd6Ib9nlMsJjAXnmEO8w78LGCInMIXa47hi8iGZ6iIm0utkC -AJJzarWE7Ayc/NHBD/LiGDCmvh2ZixYmZf3+FUgWHWgLHrSgDeyTy6I= +c3NsLmNvbRcNMjEwNjE1MjIwMjMzWhcNMjQwMzExMjIwMjMzWqAOMAwwCgYDVR0U +BAMCAQEwDQYJKoZIhvcNAQELBQADggEBAABkRaB622o5+1usOBic3WKpjY92ZB9C +B4GBV+NYFM1cSVPLMPxOKA0pjhKW99NZhyfPuXCVedwqCM4M6Jb8lbPQiRiNeoBF +3GYyO+dlk+2HWfVLTcmI8lTjsNU9KR//AX8TiFsaDL2EwKvqesvqu4A1+uVdcowr +WkgttseQ+jJx5PXsWaC1OH4KaNfzq8ihM7YfVBHRpIfXppkvwQgKpuiREqnn/kaE +oqhqQMi1bCj1rYA0mGmupRbK6YUHITkRvoLwndxsrySKBekmFMLV8BK6c9xzuTEk +X6HVzKXy84UzsitQjzPJhbG5IDeoklVmRQbaPHuFwHBt/a7mF1t4QK4= -----END X509 CRL----- diff --git a/certs/crl/server-goodcnwildCrl.pem b/certs/crl/server-goodcnwildCrl.pem old mode 100644 new mode 100755 index 464c86214..cb82df6ff --- a/certs/crl/server-goodcnwildCrl.pem +++ b/certs/crl/server-goodcnwildCrl.pem @@ -1,38 +1,38 @@ Certificate Revocation List (CRL): Version 2 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: /C=US/ST=Montana/L=Bozeman/OU=Engineering/CN=*localhost/emailAddress=info@wolfssl.com - Last Update: Sep 19 21:21:24 2018 GMT - Next Update: Jun 15 21:21:24 2021 GMT + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = *localhost, emailAddress = info@wolfssl.com + Last Update: Jun 15 22:02:33 2021 GMT + Next Update: Mar 11 22:02:33 2024 GMT CRL extensions: X509v3 CRL Number: 1 No Revoked Certificates. Signature Algorithm: sha256WithRSAEncryption - 0f:0e:30:ee:50:7a:50:b0:8d:06:74:9a:67:0b:3f:44:c1:13: - 58:4e:87:0c:0c:8d:89:44:6e:29:f2:14:0c:5e:57:65:88:fb: - b9:56:a7:99:71:3d:12:16:25:d1:38:19:9d:76:41:e6:e0:37: - 0e:0a:52:93:26:19:c3:9d:27:10:29:d4:30:5f:1a:9f:9f:0a: - 2e:c0:3a:7c:07:f0:fe:c4:ad:7b:84:a8:2e:e5:06:a9:8d:dd: - b2:2b:bf:e8:ac:e8:d8:30:2b:eb:5f:67:ca:4a:b8:d5:be:7b: - 37:0d:04:ef:ad:9d:5d:9c:a3:02:5c:cd:97:4a:78:7c:16:2b: - 7d:90:b5:8a:ef:3d:68:53:72:5b:21:92:8b:a3:48:72:f8:f3: - 6a:c0:10:93:0f:de:43:d0:7a:b0:f6:13:e9:96:64:5d:d9:a7: - 11:e5:ea:72:09:5e:be:a0:6b:54:e8:fb:23:b7:58:a4:a0:88: - d9:cc:22:25:9a:1a:1a:83:40:99:97:05:0f:7f:e6:a9:ee:1a: - a2:6a:4d:f2:60:f3:46:5d:95:3a:03:a6:8a:a0:79:16:f7:3c: - 1f:16:29:02:7b:c8:bb:98:d9:ed:b0:a3:fb:4a:2a:9e:00:0a: - cf:42:94:fa:14:73:4f:26:ed:a2:97:8d:a5:86:0f:72:e9:7b: - 06:da:35:08 + 70:25:b0:87:e0:58:78:55:a7:8f:4a:53:b8:46:39:2f:5f:fe: + 7a:29:a9:e6:78:f4:3f:e4:ce:95:3f:fe:08:d2:7e:30:2e:7c: + 2f:a2:9d:1d:30:36:35:6e:e6:20:89:58:d4:d8:23:42:dd:ae: + 8a:63:3f:4c:20:14:40:24:0f:cd:a4:5e:da:1e:32:c1:08:fe: + b9:48:87:d4:07:dc:1e:0f:a5:5c:a7:5c:fe:20:96:54:60:69: + 6c:dd:e2:55:77:e5:d1:b0:6e:b1:fb:a1:2b:89:59:55:ba:f1: + fd:23:bc:05:33:29:7c:5f:63:f3:ed:47:8a:db:46:f2:df:cd: + b4:57:55:28:25:0f:be:41:97:c7:69:cf:b7:36:e2:d4:13:8d: + 53:dc:a6:3e:fb:e0:0a:98:bc:6d:3a:86:4b:13:3f:a2:a0:06: + 97:d0:c9:2b:48:9f:a2:66:39:cb:64:07:cc:32:64:51:11:fb: + 76:1d:28:af:89:8f:ba:f3:7f:1a:6b:b6:b7:1e:0d:6e:70:55: + ae:12:0b:af:8d:1c:46:f7:33:b3:36:8b:28:cb:9d:da:95:9e: + 93:c6:8d:d3:c6:81:bf:93:01:99:dd:90:8e:20:89:6d:1f:cd: + e8:f2:0e:e3:26:a6:e8:ec:04:4c:4d:43:3f:d2:28:bd:e2:03: + c5:dc:e6:96 -----BEGIN X509 CRL----- MIIB1jCBvwIBATANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJVUzEQMA4GA1UE CAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJp bmcxEzARBgNVBAMMCipsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s -ZnNzbC5jb20XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIxMjEyNFqgDjAMMAoGA1Ud -FAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAPDjDuUHpQsI0GdJpnCz9EwRNYTocM -DI2JRG4p8hQMXldliPu5VqeZcT0SFiXROBmddkHm4DcOClKTJhnDnScQKdQwXxqf -nwouwDp8B/D+xK17hKgu5Qapjd2yK7/orOjYMCvrX2fKSrjVvns3DQTvrZ1dnKMC -XM2XSnh8Fit9kLWK7z1oU3JbIZKLo0hy+PNqwBCTD95D0Hqw9hPplmRd2acR5epy -CV6+oGtU6Psjt1ikoIjZzCIlmhoag0CZlwUPf+ap7hqiak3yYPNGXZU6A6aKoHkW -9zwfFikCe8i7mNntsKP7SiqeAArPQpT6FHNPJu2il42lhg9y6XsG2jUI +ZnNzbC5jb20XDTIxMDYxNTIyMDIzM1oXDTI0MDMxMTIyMDIzM1qgDjAMMAoGA1Ud +FAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBwJbCH4Fh4VaePSlO4RjkvX/56Kanm +ePQ/5M6VP/4I0n4wLnwvop0dMDY1buYgiVjU2CNC3a6KYz9MIBRAJA/NpF7aHjLB +CP65SIfUB9weD6Vcp1z+IJZUYGls3eJVd+XRsG6x+6EriVlVuvH9I7wFMyl8X2Pz +7UeK20by3820V1UoJQ++QZfHac+3NuLUE41T3KY+++AKmLxtOoZLEz+ioAaX0Mkr +SJ+iZjnLZAfMMmRREft2HSiviY+6838aa7a3Hg1ucFWuEguvjRxG9zOzNosoy53a +lZ6Txo3TxoG/kwGZ3ZCOIIltH83o8g7jJqbo7ARMTUM/0ii94gPF3OaW -----END X509 CRL----- diff --git a/certs/dh-pubkey-2048.der b/certs/dh-pubkey-2048.der new file mode 100644 index 000000000..d364fce37 Binary files /dev/null and b/certs/dh-pubkey-2048.der differ diff --git a/certs/dsa-pubkey-2048.der b/certs/dsa-pubkey-2048.der new file mode 100644 index 000000000..222251fda Binary files /dev/null and b/certs/dsa-pubkey-2048.der differ diff --git a/certs/ed25519/ca-ed25519-key.der b/certs/ed25519/ca-ed25519-key.der index 819013780..f1dfb912e 100644 Binary files a/certs/ed25519/ca-ed25519-key.der and b/certs/ed25519/ca-ed25519-key.der differ diff --git a/certs/ed25519/ca-ed25519-key.pem b/certs/ed25519/ca-ed25519-key.pem index f964dca0f..0eb5c3ca4 100644 --- a/certs/ed25519/ca-ed25519-key.pem +++ b/certs/ed25519/ca-ed25519-key.pem @@ -1,4 +1,3 @@ ------BEGIN EDDSA PRIVATE KEY----- -MFICAQAwBQYDK2VwBCIEIAw37caag1d0w0pY63b7oe9Frg8SA0rLDtnWWDl7MafZ -oSIEIKqWfWdx1/6tqF8UGL4C0BV+gGS5IXuyP3x0bv/1hOKB ------END EDDSA PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAQjt6+YLP+d8Z3fPwMilt+v12T2jCwuBsR67CVWisDU0= +-----END PUBLIC KEY----- diff --git a/certs/ed25519/ca-ed25519-priv.der b/certs/ed25519/ca-ed25519-priv.der index 47edd8f90..4d7e9b5bf 100644 Binary files a/certs/ed25519/ca-ed25519-priv.der and b/certs/ed25519/ca-ed25519-priv.der differ diff --git a/certs/ed25519/ca-ed25519-priv.pem b/certs/ed25519/ca-ed25519-priv.pem index a1c81d93c..da2e90598 100644 --- a/certs/ed25519/ca-ed25519-priv.pem +++ b/certs/ed25519/ca-ed25519-priv.pem @@ -1,3 +1,3 @@ -----BEGIN PRIVATE KEY----- -MC4CAQAwBQYDK2VwBCIEIAw37caag1d0w0pY63b7oe9Frg8SA0rLDtnWWDl7MafZ +MC4CAQAwBQYDK2VwBCIEIPhVt7ZJP5mciOPFQmqkR0rkldrbv/inQp0O59BXjxZp -----END PRIVATE KEY----- diff --git a/certs/ed25519/ca-ed25519.der b/certs/ed25519/ca-ed25519.der index 8b7788d0d..d46aa7926 100644 Binary files a/certs/ed25519/ca-ed25519.der and b/certs/ed25519/ca-ed25519.der differ diff --git a/certs/ed25519/ca-ed25519.pem b/certs/ed25519/ca-ed25519.pem index c8abf6880..7b645aaf3 100644 --- a/certs/ed25519/ca-ed25519.pem +++ b/certs/ed25519/ca-ed25519.pem @@ -1,15 +1,47 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED25519 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed25519, OU = Root-Ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Mar 10 06:49:03 2021 GMT + Not After : Dec 5 06:49:03 2023 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = CA-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 42:3b:7a:f9:82:cf:f9:df:19:dd:f3:f0:32:29:6d: + fa:fd:76:4f:68:c2:c2:e0:6c:47:ae:c2:55:68:ac: + 0d:4d + X509v3 extensions: + X509v3 Subject Key Identifier: + 74:D5:38:19:5E:83:B9:03:F8:01:8A:35:35:BB:89:4C:49:B4:23:E9 + X509v3 Authority Key Identifier: + keyid:FA:BA:5B:76:1D:F1:1D:1D:4D:74:48:D8:98:3B:56:EF:B3:14:F3:DE + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ED25519 + da:fe:58:53:89:43:85:98:35:dc:13:1c:a3:f1:1f:8d:26:be: + b6:a2:fc:b7:fe:9c:b9:35:69:31:7e:d4:b9:11:45:16:a2:29: + 35:a9:74:a7:97:da:7e:71:4f:b1:72:5d:75:17:ac:e3:f6:b8: + ce:1e:e4:8a:95:ba:cd:1d:ce:0d -----BEGIN CERTIFICATE----- -MIICVDCCAgagAwIBAgIQQAiKTYWESER1OSfza785ITAFBgMrZXAwgZkxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ0wCwYD -VQQEDARSb290MRAwDgYDVQQKDAd3b2xmU1NMMRAwDgYDVQQLDAdFRDI1NTE5MRgw -FgYDVQQDDA93d3cud29sZnNzbC5jb20xGTAXBgNVBAUAEGluZm9Ad29sZnNzbC5j -b20wIhgPMjAyMTAyMDkxOTUwMDRaGA8yMDIzMDIxMDE5NTAwNFowgZcxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQswCQYD -VQQEDAJDQTEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCowBQYDK2VwAyEAqpZ9Z3HX/q2oXxQYvgLQFX6AZLkhe7I/fHRu//WE4oGjYDBe -MAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFG6LDcksWUNgr6UyhWz1dPO6VJvMMB8G -A1UdIwQYMBaAFBl6CabmJl9fBlLOYyRaj1xxPbt3MA4GA1UdDwEB/wQEAwIBxjAF -BgMrZXADQQC7w3pxbsKWWTZl1BQDkNAauSRVUoKYgLK67OcsHMYTpbjNLan5jeT+ -3z62i4fbzNBLDJD89XUSjtqQt1LRoE0F +MIICTDCCAf6gAwIBAgIBATAFBgMrZXAwgZ0xCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX0Vk +MjU1MTkxFTATBgNVBAsMDFJvb3QtRWQyNTUxOTEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDMx +MDA2NDkwM1oXDTIzMTIwNTA2NDkwM1owgZsxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX2Vk +MjU1MTkxEzARBgNVBAsMCkNBLWVkMjU1MTkxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAqMAUGAytlcAMh +AEI7evmCz/nfGd3z8DIpbfr9dk9owsLgbEeuwlVorA1No2MwYTAdBgNVHQ4EFgQU +dNU4GV6DuQP4AYo1NbuJTEm0I+kwHwYDVR0jBBgwFoAU+rpbdh3xHR1NdEjYmDtW +77MU894wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwBQYDK2VwA0EA +2v5YU4lDhZg13BMco/EfjSa+tqL8t/6cuTVpMX7UuRFFFqIpNal0p5fafnFPsXJd +dRes4/a4zh7kipW6zR3ODQ== -----END CERTIFICATE----- diff --git a/certs/ed25519/client-ed25519-key.der b/certs/ed25519/client-ed25519-key.der index 0672c15f1..70cd43c5f 100644 Binary files a/certs/ed25519/client-ed25519-key.der and b/certs/ed25519/client-ed25519-key.der differ diff --git a/certs/ed25519/client-ed25519-key.pem b/certs/ed25519/client-ed25519-key.pem index f9742bdbd..134666eaa 100644 --- a/certs/ed25519/client-ed25519-key.pem +++ b/certs/ed25519/client-ed25519-key.pem @@ -1,4 +1,3 @@ ------BEGIN EDDSA PRIVATE KEY----- -MFICAQAwBQYDK2VwBCIEICkn2+pW4KyBhuv1IuoymGLEqp9hTFcALhcvKrmHgkhs -oSIEIE6fglljSpes+m6VbFo7Uuuj2ef2J7uJ+3e046zCCGrA ------END EDDSA PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA5ldbExvHURRr7Tv10fqrnmy26wIJo5n1br+dPP5UOeY= +-----END PUBLIC KEY----- diff --git a/certs/ed25519/client-ed25519-priv.der b/certs/ed25519/client-ed25519-priv.der index 0ee0ad288..eaf16472f 100644 Binary files a/certs/ed25519/client-ed25519-priv.der and b/certs/ed25519/client-ed25519-priv.der differ diff --git a/certs/ed25519/client-ed25519-priv.pem b/certs/ed25519/client-ed25519-priv.pem index 214c1eaaa..d7c8a771a 100644 --- a/certs/ed25519/client-ed25519-priv.pem +++ b/certs/ed25519/client-ed25519-priv.pem @@ -1,3 +1,3 @@ -----BEGIN PRIVATE KEY----- -MC4CAQAwBQYDK2VwBCIEICkn2+pW4KyBhuv1IuoymGLEqp9hTFcALhcvKrmHgkhs +MC4CAQAwBQYDK2VwBCIEIJK1TOyvgca7AdbV3r03l1rSxvbDhbU75uTsMunHylLr -----END PRIVATE KEY----- diff --git a/certs/ed25519/client-ed25519.der b/certs/ed25519/client-ed25519.der index f9d6fe85d..adfdaa58e 100644 Binary files a/certs/ed25519/client-ed25519.der and b/certs/ed25519/client-ed25519.der differ diff --git a/certs/ed25519/client-ed25519.pem b/certs/ed25519/client-ed25519.pem index b340a1265..809742d6b 100644 --- a/certs/ed25519/client-ed25519.pem +++ b/certs/ed25519/client-ed25519.pem @@ -1,15 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 40:66:c6:11:bc:00:f8:51:f9:e4:4b:bb:0b:ad:c1:09:38:b0:4a:e4 + Signature Algorithm: ED25519 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = Client-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Mar 10 06:49:03 2021 GMT + Not After : Dec 5 06:49:03 2023 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = Client-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + e6:57:5b:13:1b:c7:51:14:6b:ed:3b:f5:d1:fa:ab: + 9e:6c:b6:eb:02:09:a3:99:f5:6e:bf:9d:3c:fe:54: + 39:e6 + X509v3 extensions: + X509v3 Subject Key Identifier: + FE:41:5E:3E:81:E2:2E:46:B3:3E:47:89:90:D4:C2:B4:8E:11:D6:8A + X509v3 Authority Key Identifier: + keyid:FE:41:5E:3E:81:E2:2E:46:B3:3E:47:89:90:D4:C2:B4:8E:11:D6:8A + DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_ed25519/OU=Client-ed25519/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:40:66:C6:11:BC:00:F8:51:F9:E4:4B:BB:0B:AD:C1:09:38:B0:4A:E4 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Alternative Name: + DNS:example.com, IP Address:127.0.0.1 + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: ED25519 + e0:87:e2:ce:d3:87:77:9d:f7:44:c0:73:00:ff:07:6d:2e:90: + 90:5c:bf:30:46:9c:75:a9:48:50:8a:da:09:0f:a8:a8:04:b4: + 33:c8:f4:28:61:9e:c2:a5:19:b7:70:1e:69:cd:49:5c:9a:f3: + 81:e0:de:38:b3:37:ff:33:bb:07 -----BEGIN CERTIFICATE----- -MIICTDCCAf6gAwIBAgIQFcHfya6OWie0wxPOBaz6TDAFBgMrZXAwgZsxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ8wDQYD -VQQEDAZjbGllbnQxEDAOBgNVBAoMB3dvbGZTU0wxEDAOBgNVBAsMB0VEMjU1MTkx -GDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEZMBcGA1UEBQAQaW5mb0B3b2xmc3Ns -LmNvbTAiGA8yMDIxMDIwOTE5NTAwNFoYDzIwMjMwMjEwMTk1MDA0WjCBmzELMAkG -A1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xDzAN -BgNVBAQMBmNsaWVudDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUx -OTEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZz -c2wuY29tMCowBQYDK2VwAyEATp+CWWNKl6z6bpVsWjtS66PZ5/Ynu4n7d7TjrMII -asCjUjBQMB0GA1UdDgQWBBQxmyle67rNf5gcL3e47pgvKH2Z+DAfBgNVHSMEGDAW -gBQxmyle67rNf5gcL3e47pgvKH2Z+DAOBgNVHQ8BAf8EBAMCBsAwBQYDK2VwA0EA -2DDJOFXo02UBBQyoCvcK5n21/GJmFQiwlQQICFMzq//6xYm8eYtNN/RkCnBDysvj -p6jnAwZw6/MMujoxC3PtCg== +MIIDVDCCAwagAwIBAgIUQGbGEbwA+FH55Eu7C63BCTiwSuQwBQYDK2VwMIGfMQsw +CQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEY +MBYGA1UECgwPd29sZlNTTF9lZDI1NTE5MRcwFQYDVQQLDA5DbGllbnQtZWQyNTUx +OTEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tMB4XDTIxMDMxMDA2NDkwM1oXDTIzMTIwNTA2NDkwM1owgZ8x +CzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFu +MRgwFgYDVQQKDA93b2xmU1NMX2VkMjU1MTkxFzAVBgNVBAsMDkNsaWVudC1lZDI1 +NTE5MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGlu +Zm9Ad29sZnNzbC5jb20wKjAFBgMrZXADIQDmV1sTG8dRFGvtO/XR+quebLbrAgmj +mfVuv508/lQ55qOCAVAwggFMMB0GA1UdDgQWBBT+QV4+geIuRrM+R4mQ1MK0jhHW +ijCB3wYDVR0jBIHXMIHUgBT+QV4+geIuRrM+R4mQ1MK0jhHWiqGBpaSBojCBnzEL +MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x +GDAWBgNVBAoMD3dvbGZTU0xfZWQyNTUxOTEXMBUGA1UECwwOQ2xpZW50LWVkMjU1 +MTkxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5m +b0B3b2xmc3NsLmNvbYIUQGbGEbwA+FH55Eu7C63BCTiwSuQwDAYDVR0TBAUwAwEB +/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwBQYDK2VwA0EA4IfiztOHd533RMBzAP8HbS6QkFy/MEac +dalIUIraCQ+oqAS0M8j0KGGewqUZt3Aeac1JXJrzgeDeOLM3/zO7Bw== -----END CERTIFICATE----- diff --git a/certs/ed25519/gen-ed25519-certs.sh b/certs/ed25519/gen-ed25519-certs.sh new file mode 100755 index 000000000..1e25707ee --- /dev/null +++ b/certs/ed25519/gen-ed25519-certs.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +check_result(){ + if [ $1 -ne 0 ]; then + echo "Failed at \"$2\", Abort" + exit 1 + else + echo "Step Succeeded!" + fi +} + +openssl pkey -in root-ed25519-priv.pem -noout >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "OpenSSL does not support Ed25519" + echo "Skipping Ed25519 certificate renewal" + exit 0 +fi + +############################################################ +###### update the self-signed root-ed25519.pem ############# +############################################################ +echo "Updating root-ed25519.pem" +echo "" +#pipe the following arguments to openssl req... +echo -e "US\\nMontana\\nBozeman\\nwolfSSL_Ed25519\\nRoot-Ed25519\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n.\\n.\\n" | \ +openssl req -new -key root-ed25519-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out root-ed25519.csr +check_result $? "Generate request" + +openssl x509 -req -in root-ed25519.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions ca_ecc_cert -signkey root-ed25519-priv.pem -out root-ed25519.pem +check_result $? "Generate certificate" +rm root-ed25519.csr + +openssl x509 -in root-ed25519.pem -outform DER > root-ed25519.der +check_result $? "Convert to DER" +openssl x509 -in root-ed25519.pem -text > tmp.pem +check_result $? "Add text" +mv tmp.pem root-ed25519.pem +echo "End of section" +echo "---------------------------------------------------------------------" + +############################################################ +###### update ca-ed25519.pem signed by root ################ +############################################################ +echo "Updating ca-ed25519.pem" +echo "" +#pipe the following arguments to openssl req... +echo -e "US\\nMontana\\nBozeman\\nwolfSSL_ed25519\\nCA-ed25519\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n\\n\\n\\n" | openssl req -new -key ca-ed25519-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out ca-ed25519.csr +check_result $? "Generate request" + +openssl x509 -req -in ca-ed25519.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions ca_ecc_cert -CA root-ed25519.pem -CAkey root-ed25519-priv.pem -set_serial 01 -out ca-ed25519.pem +check_result $? "Generate certificate" +rm ca-ed25519.csr + +openssl x509 -in ca-ed25519.pem -outform DER > ca-ed25519.der +check_result $? "Convert to DER" +openssl x509 -in ca-ed25519.pem -text > tmp.pem +check_result $? "Add text" +mv tmp.pem ca-ed25519.pem +echo "End of section" +echo "---------------------------------------------------------------------" + +############################################################ +###### update server-ed25519.pem signed by ca ############## +############################################################ +echo "Updating server-ed25519.pem" +echo "" +#pipe the following arguments to openssl req... +echo -e "US\\nMontana\\nBozeman\\nwolfSSL_ed25519\\nServer-ed25519\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n\\n\\n\\n" | openssl req -new -key server-ed25519-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out server-ed25519.csr +check_result $? "Generate request" + +openssl x509 -req -in server-ed25519.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions server_ecc -CA ca-ed25519.pem -CAkey ca-ed25519-priv.pem -set_serial 01 -out server-ed25519-cert.pem +check_result $? "Generate certificate" +rm server-ed25519.csr + +openssl x509 -in server-ed25519-cert.pem -outform DER > server-ed25519.der +check_result $? "Convert to DER" +openssl x509 -in server-ed25519-cert.pem -text > tmp.pem +check_result $? "Add text" +mv tmp.pem server-ed25519-cert.pem +cat server-ed25519-cert.pem ca-ed25519.pem > server-ed25519.pem +check_result $? "Add CA into server cert" +echo "End of section" +echo "---------------------------------------------------------------------" + +############################################################ +###### update the self-signed client-ed25519.pem ########### +############################################################ +echo "Updating client-ed25519.pem" +echo "" +#pipe the following arguments to openssl req... +echo -e "US\\nMontana\\nBozeman\\nwolfSSL_ed25519\\nClient-ed25519\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n\\n\\n\\n" | openssl req -new -key client-ed25519-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out client-ed25519.csr +check_result $? "Generate request" + +openssl x509 -req -in client-ed25519.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions client_ecc -signkey client-ed25519-priv.pem -out client-ed25519.pem +check_result $? "Generate certificate" +rm client-ed25519.csr + +openssl x509 -in client-ed25519.pem -outform DER > client-ed25519.der +check_result $? "Convert to DER" +openssl x509 -in client-ed25519.pem -text > tmp.pem +check_result $? "Add text" +mv tmp.pem client-ed25519.pem +echo "End of section" +echo "---------------------------------------------------------------------" + diff --git a/certs/ed25519/gen-ed25519-keys.sh b/certs/ed25519/gen-ed25519-keys.sh new file mode 100755 index 000000000..5f9bc666a --- /dev/null +++ b/certs/ed25519/gen-ed25519-keys.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +for key in root ca server client +do + + openssl genpkey -algorithm ED25519 > ${key}-ed25519-priv.pem + + openssl pkey -in ${key}-ed25519-priv.pem -outform DER -out ${key}-ed25519-priv.der + + openssl pkey -in ${key}-ed25519-priv.pem -outform PEM -pubout -out ${key}-ed25519-key.pem + + openssl pkey -in ${key}-ed25519-priv.pem -outform DER -pubout -out ${key}-ed25519-key.der + +done + + diff --git a/certs/ed25519/include.am b/certs/ed25519/include.am index ad2897684..5739596c1 100644 --- a/certs/ed25519/include.am +++ b/certs/ed25519/include.am @@ -28,3 +28,8 @@ EXTRA_DIST += \ certs/ed25519/server-ed25519-key.pem \ certs/ed25519/server-ed25519-priv.der \ certs/ed25519/server-ed25519-priv.pem + +EXTRA_DIST += \ + certs/ed25519/gen-ed25519.sh \ + certs/ed25519/gen-ed25519-certs.sh \ + certs/ed25519/gen-ed25519-keys.sh diff --git a/certs/ed25519/root-ed25519-key.der b/certs/ed25519/root-ed25519-key.der index 230709878..cc03be2a1 100644 Binary files a/certs/ed25519/root-ed25519-key.der and b/certs/ed25519/root-ed25519-key.der differ diff --git a/certs/ed25519/root-ed25519-key.pem b/certs/ed25519/root-ed25519-key.pem index 6d6b2d8ec..eb8a72ce1 100644 --- a/certs/ed25519/root-ed25519-key.pem +++ b/certs/ed25519/root-ed25519-key.pem @@ -1,4 +1,3 @@ ------BEGIN EDDSA PRIVATE KEY----- -MFICAQAwBQYDK2VwBCIEIPUBUd1CTNITOelSbDQlzuGA30xv42CVcvpe92sq7N+o -oSIEIIgura+qJ+c7nKcbmd2OK5+dL++bfwkNtP5Cs9JL+nwO ------END EDDSA PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA6bNvfHCKq8pUIE5kdjwaT/f6Xkr/89u5ZC0QpQxaP9o= +-----END PUBLIC KEY----- diff --git a/certs/ed25519/root-ed25519-priv.der b/certs/ed25519/root-ed25519-priv.der index 2c51356eb..3cab31329 100644 Binary files a/certs/ed25519/root-ed25519-priv.der and b/certs/ed25519/root-ed25519-priv.der differ diff --git a/certs/ed25519/root-ed25519-priv.pem b/certs/ed25519/root-ed25519-priv.pem index 18efe8f48..6f725f119 100644 --- a/certs/ed25519/root-ed25519-priv.pem +++ b/certs/ed25519/root-ed25519-priv.pem @@ -1,3 +1,3 @@ -----BEGIN PRIVATE KEY----- -MC4CAQAwBQYDK2VwBCIEIPUBUd1CTNITOelSbDQlzuGA30xv42CVcvpe92sq7N+o +MC4CAQAwBQYDK2VwBCIEIFcyr6XNVwsNpxIoY6ENIWmuvF/LJs2xkuvuxmoPrf1w -----END PRIVATE KEY----- diff --git a/certs/ed25519/root-ed25519.der b/certs/ed25519/root-ed25519.der index 3e481a16b..76117a27e 100644 Binary files a/certs/ed25519/root-ed25519.der and b/certs/ed25519/root-ed25519.der differ diff --git a/certs/ed25519/root-ed25519.pem b/certs/ed25519/root-ed25519.pem index cdb9bb22e..05720a367 100644 --- a/certs/ed25519/root-ed25519.pem +++ b/certs/ed25519/root-ed25519.pem @@ -1,15 +1,48 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 3c:8f:b8:f9:5c:f1:81:97:76:e0:cc:04:c6:f6:77:7b:4f:92:4c:c6 + Signature Algorithm: ED25519 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed25519, OU = Root-Ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Mar 10 06:49:03 2021 GMT + Not After : Dec 5 06:49:03 2023 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed25519, OU = Root-Ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + e9:b3:6f:7c:70:8a:ab:ca:54:20:4e:64:76:3c:1a: + 4f:f7:fa:5e:4a:ff:f3:db:b9:64:2d:10:a5:0c:5a: + 3f:da + X509v3 extensions: + X509v3 Subject Key Identifier: + FA:BA:5B:76:1D:F1:1D:1D:4D:74:48:D8:98:3B:56:EF:B3:14:F3:DE + X509v3 Authority Key Identifier: + keyid:FA:BA:5B:76:1D:F1:1D:1D:4D:74:48:D8:98:3B:56:EF:B3:14:F3:DE + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ED25519 + 44:f7:5d:ad:c0:68:5e:0c:af:c5:dd:da:a4:f9:34:4f:33:4f: + b3:db:bb:b6:36:67:f4:4d:63:a5:61:e8:b8:98:b7:e7:d3:52: + 8b:fb:ca:61:97:db:34:55:63:a8:27:e8:22:16:b6:a9:f1:8d: + 0e:f8:d1:56:08:45:b6:40:d9:09 -----BEGIN CERTIFICATE----- -MIICVjCCAgigAwIBAgIQYlI7cNFaPvFoHcYXLFMPzTAFBgMrZXAwgZkxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ0wCwYD -VQQEDARSb290MRAwDgYDVQQKDAd3b2xmU1NMMRAwDgYDVQQLDAdFRDI1NTE5MRgw -FgYDVQQDDA93d3cud29sZnNzbC5jb20xGTAXBgNVBAUAEGluZm9Ad29sZnNzbC5j -b20wIhgPMjAyMTAyMDkxOTUwMDRaGA8yMDIzMDIxMDE5NTAwNFowgZkxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ0wCwYD -VQQEDARSb290MRAwDgYDVQQKDAd3b2xmU1NMMRAwDgYDVQQLDAdFRDI1NTE5MRgw -FgYDVQQDDA93d3cud29sZnNzbC5jb20xGTAXBgNVBAUAEGluZm9Ad29sZnNzbC5j -b20wKjAFBgMrZXADIQCILq2vqifnO5ynG5ndjiufnS/vm38JDbT+QrPSS/p8DqNg -MF4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUGXoJpuYmX18GUs5jJFqPXHE9u3cw -HwYDVR0jBBgwFoAUGXoJpuYmX18GUs5jJFqPXHE9u3cwDgYDVR0PAQH/BAQDAgHG -MAUGAytlcANBAOzVbL+V/Ik567gy9xUG5NwC1PE/SXEl6pNWTewxHAj8wU1IkDLT -FLYfC9ezVkWy9aOYaLH79T63Hl/tIahybgc= +MIICYTCCAhOgAwIBAgIUPI+4+VzxgZd24MwExvZ3e0+STMYwBQYDK2VwMIGdMQsw +CQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEY +MBYGA1UECgwPd29sZlNTTF9FZDI1NTE5MRUwEwYDVQQLDAxSb290LUVkMjU1MTkx +GDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbTAeFw0yMTAzMTAwNjQ5MDNaFw0yMzEyMDUwNjQ5MDNaMIGdMQsw +CQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEY +MBYGA1UECgwPd29sZlNTTF9FZDI1NTE5MRUwEwYDVQQLDAxSb290LUVkMjU1MTkx +GDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbTAqMAUGAytlcAMhAOmzb3xwiqvKVCBOZHY8Gk/3+l5K//PbuWQt +EKUMWj/ao2MwYTAdBgNVHQ4EFgQU+rpbdh3xHR1NdEjYmDtW77MU894wHwYDVR0j +BBgwFoAU+rpbdh3xHR1NdEjYmDtW77MU894wDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwBQYDK2VwA0EARPddrcBoXgyvxd3apPk0TzNPs9u7tjZn9E1j +pWHouJi359NSi/vKYZfbNFVjqCfoIha2qfGNDvjRVghFtkDZCQ== -----END CERTIFICATE----- diff --git a/certs/ed25519/server-ed25519-cert.pem b/certs/ed25519/server-ed25519-cert.pem index d9d035a52..2006b538d 100644 --- a/certs/ed25519/server-ed25519-cert.pem +++ b/certs/ed25519/server-ed25519-cert.pem @@ -1,30 +1,52 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED25519 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = CA-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Mar 10 06:49:03 2021 GMT + Not After : Dec 5 06:49:03 2023 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = Server-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 23:aa:4d:60:50:e0:13:d3:3a:ed:ab:f6:a9:cc:4a: + fe:d7:4d:2f:d2:5b:1a:10:05:ef:5a:41:25:ce:1b: + 53:78 + X509v3 extensions: + X509v3 Subject Key Identifier: + A3:29:81:E7:90:6F:B9:60:F8:AF:CC:15:7A:AE:D7:A1:F4:B4:86:BA + X509v3 Authority Key Identifier: + keyid:74:D5:38:19:5E:83:B9:03:F8:01:8A:35:35:BB:89:4C:49:B4:23:E9 + + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + Netscape Cert Type: + SSL Server + Signature Algorithm: ED25519 + f3:c2:ef:8b:55:65:4f:bc:e3:df:fc:d8:a1:ad:8e:43:07:73: + c8:58:c3:46:0a:c1:f1:4d:3f:fb:3d:78:e6:76:58:26:ce:d7: + 59:55:ec:c5:b5:b4:05:ed:f9:d4:97:69:66:d6:2c:1b:43:5a: + 51:5c:be:10:28:95:c4:96:af:00 -----BEGIN CERTIFICATE----- -MIICRjCCAfigAwIBAgIQQyBFY/XbM3h5GPnWdnTeajAFBgMrZXAwgZcxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQswCQYD -VQQEDAJDQTEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCIYDzIwMjEwMjA5MTk1MDA0WhgPMjAyMzAyMTAxOTUwMDRaMIGZMQswCQYDVQQG -EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UE -BAwETGVhZjEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCowBQYDK2VwAyEAi/OP+P/p9GU5NF71Iny3X/19LSd1vDHlmtPu8us3ryijUjBQ -MB0GA1UdDgQWBBQp8hOvwv+m0cj7fJgvDhEuOGSijjAfBgNVHSMEGDAWgBRuiw3J -LFlDYK+lMoVs9XTzulSbzDAOBgNVHQ8BAf8EBAMCBsAwBQYDK2VwA0EAo/sGXBKn -xIvogGi7VbdCmq1KbS04WEC2Kiu6DI22jOpQecqeUQ+iJ+Ua7tIlSsv0NPqqraq8 -KKxhcSh1nWQbDQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICVDCCAgagAwIBAgIQQAiKTYWESER1OSfza785ITAFBgMrZXAwgZkxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ0wCwYD -VQQEDARSb290MRAwDgYDVQQKDAd3b2xmU1NMMRAwDgYDVQQLDAdFRDI1NTE5MRgw -FgYDVQQDDA93d3cud29sZnNzbC5jb20xGTAXBgNVBAUAEGluZm9Ad29sZnNzbC5j -b20wIhgPMjAyMTAyMDkxOTUwMDRaGA8yMDIzMDIxMDE5NTAwNFowgZcxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQswCQYD -VQQEDAJDQTEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCowBQYDK2VwAyEAqpZ9Z3HX/q2oXxQYvgLQFX6AZLkhe7I/fHRu//WE4oGjYDBe -MAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFG6LDcksWUNgr6UyhWz1dPO6VJvMMB8G -A1UdIwQYMBaAFBl6CabmJl9fBlLOYyRaj1xxPbt3MA4GA1UdDwEB/wQEAwIBxjAF -BgMrZXADQQC7w3pxbsKWWTZl1BQDkNAauSRVUoKYgLK67OcsHMYTpbjNLan5jeT+ -3z62i4fbzNBLDJD89XUSjtqQt1LRoE0F +MIICdTCCAiegAwIBAgIBATAFBgMrZXAwgZsxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX2Vk +MjU1MTkxEzARBgNVBAsMCkNBLWVkMjU1MTkxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMTAzMTAw +NjQ5MDNaFw0yMzEyMDUwNjQ5MDNaMIGfMQswCQYDVQQGEwJVUzEQMA4GA1UECAwH +TW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEYMBYGA1UECgwPd29sZlNTTF9lZDI1 +NTE5MRcwFQYDVQQLDA5TZXJ2ZXItZWQyNTUxOTEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMCowBQYDK2Vw +AyEAI6pNYFDgE9M67av2qcxK/tdNL9JbGhAF71pBJc4bU3ijgYkwgYYwHQYDVR0O +BBYEFKMpgeeQb7lg+K/MFXqu16H0tIa6MB8GA1UdIwQYMBaAFHTVOBleg7kD+AGK +NTW7iUxJtCPpMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgOoMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMBEGCWCGSAGG+EIBAQQEAwIGQDAFBgMrZXADQQDzwu+LVWVP +vOPf/NihrY5DB3PIWMNGCsHxTT/7PXjmdlgmztdZVezFtbQF7fnUl2lm1iwbQ1pR +XL4QKJXElq8A -----END CERTIFICATE----- diff --git a/certs/ed25519/server-ed25519-key.der b/certs/ed25519/server-ed25519-key.der index e522ba1c2..0bdd0dd69 100644 Binary files a/certs/ed25519/server-ed25519-key.der and b/certs/ed25519/server-ed25519-key.der differ diff --git a/certs/ed25519/server-ed25519-key.pem b/certs/ed25519/server-ed25519-key.pem index b64ae01fe..f99c16453 100644 --- a/certs/ed25519/server-ed25519-key.pem +++ b/certs/ed25519/server-ed25519-key.pem @@ -1,4 +1,3 @@ ------BEGIN EDDSA PRIVATE KEY----- -MFICAQAwBQYDK2VwBCIEIHyd6hRAi4voY3m+UTepnRnoKo50DlIF3i9js6EkbTEG -oSIEIIvzj/j/6fRlOTRe9SJ8t1/9fS0ndbwx5ZrT7vLrN68o ------END EDDSA PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAI6pNYFDgE9M67av2qcxK/tdNL9JbGhAF71pBJc4bU3g= +-----END PUBLIC KEY----- diff --git a/certs/ed25519/server-ed25519-priv.der b/certs/ed25519/server-ed25519-priv.der index b25e2969d..23acaaf1b 100644 Binary files a/certs/ed25519/server-ed25519-priv.der and b/certs/ed25519/server-ed25519-priv.der differ diff --git a/certs/ed25519/server-ed25519-priv.pem b/certs/ed25519/server-ed25519-priv.pem index 20f443f28..9fdbd2ede 100644 --- a/certs/ed25519/server-ed25519-priv.pem +++ b/certs/ed25519/server-ed25519-priv.pem @@ -1,3 +1,3 @@ -----BEGIN PRIVATE KEY----- -MC4CAQAwBQYDK2VwBCIEIHyd6hRAi4voY3m+UTepnRnoKo50DlIF3i9js6EkbTEG +MC4CAQAwBQYDK2VwBCIEII6YRLBUgcY6R9j7wza/GXBhCSN24xxvgziuSVXFnoci -----END PRIVATE KEY----- diff --git a/certs/ed25519/server-ed25519.der b/certs/ed25519/server-ed25519.der index ce580d991..dbc551d44 100644 Binary files a/certs/ed25519/server-ed25519.der and b/certs/ed25519/server-ed25519.der differ diff --git a/certs/ed25519/server-ed25519.pem b/certs/ed25519/server-ed25519.pem index d9d035a52..d8d2277e7 100644 --- a/certs/ed25519/server-ed25519.pem +++ b/certs/ed25519/server-ed25519.pem @@ -1,30 +1,99 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED25519 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = CA-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Mar 10 06:49:03 2021 GMT + Not After : Dec 5 06:49:03 2023 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = Server-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 23:aa:4d:60:50:e0:13:d3:3a:ed:ab:f6:a9:cc:4a: + fe:d7:4d:2f:d2:5b:1a:10:05:ef:5a:41:25:ce:1b: + 53:78 + X509v3 extensions: + X509v3 Subject Key Identifier: + A3:29:81:E7:90:6F:B9:60:F8:AF:CC:15:7A:AE:D7:A1:F4:B4:86:BA + X509v3 Authority Key Identifier: + keyid:74:D5:38:19:5E:83:B9:03:F8:01:8A:35:35:BB:89:4C:49:B4:23:E9 + + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + Netscape Cert Type: + SSL Server + Signature Algorithm: ED25519 + f3:c2:ef:8b:55:65:4f:bc:e3:df:fc:d8:a1:ad:8e:43:07:73: + c8:58:c3:46:0a:c1:f1:4d:3f:fb:3d:78:e6:76:58:26:ce:d7: + 59:55:ec:c5:b5:b4:05:ed:f9:d4:97:69:66:d6:2c:1b:43:5a: + 51:5c:be:10:28:95:c4:96:af:00 -----BEGIN CERTIFICATE----- -MIICRjCCAfigAwIBAgIQQyBFY/XbM3h5GPnWdnTeajAFBgMrZXAwgZcxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQswCQYD -VQQEDAJDQTEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCIYDzIwMjEwMjA5MTk1MDA0WhgPMjAyMzAyMTAxOTUwMDRaMIGZMQswCQYDVQQG -EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UE -BAwETGVhZjEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCowBQYDK2VwAyEAi/OP+P/p9GU5NF71Iny3X/19LSd1vDHlmtPu8us3ryijUjBQ -MB0GA1UdDgQWBBQp8hOvwv+m0cj7fJgvDhEuOGSijjAfBgNVHSMEGDAWgBRuiw3J -LFlDYK+lMoVs9XTzulSbzDAOBgNVHQ8BAf8EBAMCBsAwBQYDK2VwA0EAo/sGXBKn -xIvogGi7VbdCmq1KbS04WEC2Kiu6DI22jOpQecqeUQ+iJ+Ua7tIlSsv0NPqqraq8 -KKxhcSh1nWQbDQ== +MIICdTCCAiegAwIBAgIBATAFBgMrZXAwgZsxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX2Vk +MjU1MTkxEzARBgNVBAsMCkNBLWVkMjU1MTkxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMTAzMTAw +NjQ5MDNaFw0yMzEyMDUwNjQ5MDNaMIGfMQswCQYDVQQGEwJVUzEQMA4GA1UECAwH +TW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEYMBYGA1UECgwPd29sZlNTTF9lZDI1 +NTE5MRcwFQYDVQQLDA5TZXJ2ZXItZWQyNTUxOTEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMCowBQYDK2Vw +AyEAI6pNYFDgE9M67av2qcxK/tdNL9JbGhAF71pBJc4bU3ijgYkwgYYwHQYDVR0O +BBYEFKMpgeeQb7lg+K/MFXqu16H0tIa6MB8GA1UdIwQYMBaAFHTVOBleg7kD+AGK +NTW7iUxJtCPpMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgOoMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMBEGCWCGSAGG+EIBAQQEAwIGQDAFBgMrZXADQQDzwu+LVWVP +vOPf/NihrY5DB3PIWMNGCsHxTT/7PXjmdlgmztdZVezFtbQF7fnUl2lm1iwbQ1pR +XL4QKJXElq8A -----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED25519 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed25519, OU = Root-Ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Mar 10 06:49:03 2021 GMT + Not After : Dec 5 06:49:03 2023 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed25519, OU = CA-ed25519, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 42:3b:7a:f9:82:cf:f9:df:19:dd:f3:f0:32:29:6d: + fa:fd:76:4f:68:c2:c2:e0:6c:47:ae:c2:55:68:ac: + 0d:4d + X509v3 extensions: + X509v3 Subject Key Identifier: + 74:D5:38:19:5E:83:B9:03:F8:01:8A:35:35:BB:89:4C:49:B4:23:E9 + X509v3 Authority Key Identifier: + keyid:FA:BA:5B:76:1D:F1:1D:1D:4D:74:48:D8:98:3B:56:EF:B3:14:F3:DE + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ED25519 + da:fe:58:53:89:43:85:98:35:dc:13:1c:a3:f1:1f:8d:26:be: + b6:a2:fc:b7:fe:9c:b9:35:69:31:7e:d4:b9:11:45:16:a2:29: + 35:a9:74:a7:97:da:7e:71:4f:b1:72:5d:75:17:ac:e3:f6:b8: + ce:1e:e4:8a:95:ba:cd:1d:ce:0d -----BEGIN CERTIFICATE----- -MIICVDCCAgagAwIBAgIQQAiKTYWESER1OSfza785ITAFBgMrZXAwgZkxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ0wCwYD -VQQEDARSb290MRAwDgYDVQQKDAd3b2xmU1NMMRAwDgYDVQQLDAdFRDI1NTE5MRgw -FgYDVQQDDA93d3cud29sZnNzbC5jb20xGTAXBgNVBAUAEGluZm9Ad29sZnNzbC5j -b20wIhgPMjAyMTAyMDkxOTUwMDRaGA8yMDIzMDIxMDE5NTAwNFowgZcxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQswCQYD -VQQEDAJDQTEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG -A1UEAwwPd3d3LndvbGZzc2wuY29tMRkwFwYDVQQFABBpbmZvQHdvbGZzc2wuY29t -MCowBQYDK2VwAyEAqpZ9Z3HX/q2oXxQYvgLQFX6AZLkhe7I/fHRu//WE4oGjYDBe -MAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFG6LDcksWUNgr6UyhWz1dPO6VJvMMB8G -A1UdIwQYMBaAFBl6CabmJl9fBlLOYyRaj1xxPbt3MA4GA1UdDwEB/wQEAwIBxjAF -BgMrZXADQQC7w3pxbsKWWTZl1BQDkNAauSRVUoKYgLK67OcsHMYTpbjNLan5jeT+ -3z62i4fbzNBLDJD89XUSjtqQt1LRoE0F +MIICTDCCAf6gAwIBAgIBATAFBgMrZXAwgZ0xCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX0Vk +MjU1MTkxFTATBgNVBAsMDFJvb3QtRWQyNTUxOTEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDMx +MDA2NDkwM1oXDTIzMTIwNTA2NDkwM1owgZsxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRgwFgYDVQQKDA93b2xmU1NMX2Vk +MjU1MTkxEzARBgNVBAsMCkNBLWVkMjU1MTkxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAqMAUGAytlcAMh +AEI7evmCz/nfGd3z8DIpbfr9dk9owsLgbEeuwlVorA1No2MwYTAdBgNVHQ4EFgQU +dNU4GV6DuQP4AYo1NbuJTEm0I+kwHwYDVR0jBBgwFoAU+rpbdh3xHR1NdEjYmDtW +77MU894wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwBQYDK2VwA0EA +2v5YU4lDhZg13BMco/EfjSa+tqL8t/6cuTVpMX7UuRFFFqIpNal0p5fafnFPsXJd +dRes4/a4zh7kipW6zR3ODQ== -----END CERTIFICATE----- diff --git a/certs/include.am b/certs/include.am index c7e70ad1a..eb930e1dc 100644 --- a/certs/include.am +++ b/certs/include.am @@ -68,11 +68,13 @@ EXTRA_DIST += \ certs/dh2048.der \ certs/dh3072.der \ certs/dh4096.der \ + certs/dh-pubkey-2048.der \ certs/rsa2048.der \ certs/rsa-pub-2048.pem \ certs/rsa3072.der \ certs/dsa2048.der \ certs/dsa3072.der \ + certs/dsa-pubkey-2048.der \ certs/ecc-client-key.der \ certs/ecc-client-keyPub.der \ certs/ecc-key.der \ diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf index 7cfb731af..92e703a05 100644 --- a/certs/renewcerts/wolfssl.cnf +++ b/certs/renewcerts/wolfssl.cnf @@ -271,6 +271,14 @@ keyUsage=critical, digitalSignature, keyEncipherment, keyAgreement extendedKeyUsage=serverAuth nsCertType=server +# server-ecc extensions +[ client_ecc ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always +basicConstraints=critical, CA:FALSE +keyUsage=critical, digitalSignature, keyEncipherment, keyAgreement +extendedKeyUsage=clientAuth + # test parsing URI [ uri ] subjectKeyIdentifier=hash diff --git a/certs/statickeys/dh-ffdhe2048-pub.der b/certs/statickeys/dh-ffdhe2048-pub.der new file mode 100644 index 000000000..6a817a526 Binary files /dev/null and b/certs/statickeys/dh-ffdhe2048-pub.der differ diff --git a/certs/statickeys/dh-ffdhe2048-pub.pem b/certs/statickeys/dh-ffdhe2048-pub.pem new file mode 100644 index 000000000..eea809986 --- /dev/null +++ b/certs/statickeys/dh-ffdhe2048-pub.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICJDCCARcGCSqGSIb3DQEDATCCAQgCggEBAP//////////rfhUWKK7Spqv3FYg +Jz088di5xYPOLTaVqeE2QRRkM/vMk53OJJs++X0v42NjDHXY9oGyAq7EYXrT3x7V +1f1lYSQz9R9fBm7QhWNlVT3tGvO1VxNef1fJNZhPDHDg5ot34qaJ2vPv6HId8Vih +Nq3nNTCsyk9IOnl6vAqxgrMk+2HRCKlLssjj+7lq2rdg1/RoHU9Co945TfSuVu3n +Y3K7GQsHp8juCm1wngL84c334uzANATNKDQvYZFy/pzphYP/jk8SMu7ygYPD/jsb +TG+tczu1/LwuwiAFxY7xg30Wg7LG80omwbLv+ohrQjhhKFyX//////////8CAQID +ggEFAAKCAQBNP0zkbEZx/2ECcwtlT0bnLg+eQQRVQVGJqV6EvHoKNTQVvrHDHs3H +WheYX/+WPRub+swfHqcii5XuK9R04mPi/ZyqT75kaYMxXpBchV2ymeAFtfK2Gc0G +zaizWY2HhH+PCe69YW/FzbicpxWX0EQuLS4yIMU731BvjRe4hKNnJH6j7IwIeGwl +iALToGjOGiVGLptMgvTrs8kdFwySlFQPtd8/cUUzl02HGktACnG0Gb4zvc/zFWMG +N1yhncDnp4vToms/8ULINmsKQ4vp0IzNDzHNIuc5yI3rXZGLBm4fB9urK0+F+LtV +471wUVxzZl3RtvhEEODyCRxtAl38egiC +-----END PUBLIC KEY----- diff --git a/certs/statickeys/gen-static.sh b/certs/statickeys/gen-static.sh index 58289eecb..dc92757db 100644 --- a/certs/statickeys/gen-static.sh +++ b/certs/statickeys/gen-static.sh @@ -10,3 +10,6 @@ openssl ec -inform pem -in certs/statickeys/ecc-secp256r1.pem -outform der -out # Using one generated and capture with wolfSSL using wc_DhGenerateKeyPair (openssl generates DH keys with 2048-bits... based on the DH "p" prime size) #openssl genpkey -paramfile certs/statickeys/dh-ffdhe2048-params.pem -out certs/statickeys/dh-ffdhe2048.der openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform pem -out certs/statickeys/dh-ffdhe2048.pem +# Export DH public key as DER and convert to PEM +openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform der -out certs/statickeys/dh-ffdhe2048-pub.der -pubout +openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform pem -out certs/statickeys/dh-ffdhe2048-pub.pem -pubout diff --git a/certs/statickeys/include.am b/certs/statickeys/include.am index 988b03dcc..123764dd5 100644 --- a/certs/statickeys/include.am +++ b/certs/statickeys/include.am @@ -14,4 +14,6 @@ EXTRA_DIST += \ EXTRA_DIST += \ certs/statickeys/dh-ffdhe2048-params.pem \ certs/statickeys/dh-ffdhe2048.der \ - certs/statickeys/dh-ffdhe2048.pem + certs/statickeys/dh-ffdhe2048.pem \ + certs/statickeys/dh-ffdhe2048-pub.der \ + certs/statickeys/dh-ffdhe2048-pub.pem diff --git a/certs/test/expired/expired-ca.der b/certs/test/expired/expired-ca.der old mode 100644 new mode 100755 index df9dd7508..109efb951 Binary files a/certs/test/expired/expired-ca.der and b/certs/test/expired/expired-ca.der differ diff --git a/certs/test/expired/expired-ca.pem b/certs/test/expired/expired-ca.pem old mode 100644 new mode 100755 index d4f6716c7..08f316b20 --- a/certs/test/expired/expired-ca.pem +++ b/certs/test/expired/expired-ca.pem @@ -2,7 +2,7 @@ Certificate: Data: Version: 1 (0x0) Serial Number: 4096 (0x1000) - Signature Algorithm: sha256WithRSAEncryption + Signature Algorithm: sha256WithRSAEncryption Issuer: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering Validity Not Before: Jul 31 00:00:00 2018 GMT @@ -10,7 +10,7 @@ Certificate: Subject: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:bf:0c:ca:2d:14:b2:1e:84:42:5b:cd:38:1f:4a: f2:4d:75:10:f1:b6:35:9f:df:ca:7d:03:98:d3:ac: @@ -32,26 +32,26 @@ Certificate: 36:79 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption - 52:af:84:10:08:83:9a:39:c2:05:5c:33:fc:a6:a0:7c:ce:68: - 34:fa:cc:05:9f:8a:33:79:64:07:da:6c:17:85:91:ab:1d:be: - 32:45:c6:7f:54:b6:10:cf:ea:17:74:d4:d9:06:6e:71:5d:0d: - 40:72:21:07:79:20:63:b3:15:d5:b7:e6:1a:d6:d0:11:1a:60: - 7f:81:e9:9b:69:b4:67:4e:e2:22:1a:2f:9d:6a:3c:da:95:34: - a9:bf:2b:14:fa:fe:21:73:e7:c9:19:7d:2c:14:9f:9f:33:c1: - 83:35:9c:94:95:0e:e4:3e:29:17:95:a2:85:e3:ad:70:5f:6a: - ff:2d:8a:92:fb:58:f6:fe:46:2b:d0:e4:9d:9b:0d:d9:e4:39: - 0a:c5:e2:3d:17:de:95:cc:a4:1c:33:a1:75:02:ec:98:66:47: - b9:ce:e4:8f:7e:32:cd:38:ff:6f:3d:be:7a:44:bf:47:61:7a: - b7:5a:09:fa:1e:bf:3d:63:68:b3:15:00:87:fd:8d:b8:f6:b8: - 83:13:ff:f8:56:ed:14:05:4f:49:07:f9:33:6b:3f:fd:c6:7d: - ff:6b:04:d5:46:80:c1:6b:74:fd:e6:18:14:1d:3b:c6:12:67: - 0e:1e:8d:81:c4:a9:9c:59:ee:29:cd:cf:55:a6:bc:53:13:f4: - 51:bc:b7:b3 + ab:8a:ab:ae:77:a2:61:62:01:54:51:95:7c:d5:6c:76:cb:fe: + ac:b8:cd:bc:ec:c4:75:71:16:62:59:67:02:ab:e2:fb:9c:74: + 46:be:d9:08:8c:30:d1:0d:5c:c8:48:ff:6d:77:29:6d:c1:4c: + bc:90:44:e6:d9:aa:e8:c1:ae:b1:81:b2:58:50:b3:23:59:35: + c0:c3:e1:34:98:ef:68:86:fb:e9:9a:a1:63:41:54:cb:ab:73: + 03:c3:1a:e9:5f:50:81:b8:a8:b8:05:14:7d:1e:fa:a2:2b:b8: + 68:eb:c8:b0:b6:50:df:2b:96:c7:26:b9:ca:c9:41:e1:83:c5: + 3e:06:11:56:a3:54:f5:e2:26:65:b9:7f:e4:5f:fb:49:ef:82: + 7d:15:24:72:02:5b:2b:d7:c9:d4:dc:26:08:78:f2:c3:73:c6: + 25:56:d1:30:99:39:09:43:5d:e6:e3:ca:f2:3f:68:13:13:d6: + d2:df:5f:05:5b:09:48:27:87:5a:60:eb:c2:ff:93:7d:5c:e0: + 45:c4:85:21:d3:43:1d:c2:78:0d:e5:ff:2b:27:f0:e9:d4:a4: + 40:02:5f:27:19:94:4b:ea:64:cc:e2:d6:04:e5:70:7a:01:a5: + 6f:3f:3c:ce:3d:84:cf:fb:d9:80:c3:df:fb:44:2f:1e:2f:32: + e9:56:6b:5b -----BEGIN CERTIFICATE----- MIIDVTCCAj0CAhAAMA0GCSqGSIb3DQEBCwUAMHAxGDAWBgNVBAMMD3d3dy53b2xm c3NsLmNvbTEQMA4GA1UECAwHTW9udGFuYTELMAkGA1UEBhMCVVMxHzAdBgkqhkiG -9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFDASBgNVBAsMC0VuZ2luZWVyaW5nMB4Y -DTIwMTgwNzMxMDAwMFoYDTIwMTgwODMwMDAwMFowcDEYMBYGA1UEAwwPd3d3Lndv +9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFDASBgNVBAsMC0VuZ2luZWVyaW5nMB4X +DTE4MDczMTAwMDAwMFoXDTE4MDgzMDAwMDAwMFowcDEYMBYGA1UEAwwPd3d3Lndv bGZzc2wuY29tMRAwDgYDVQQIDAdNb250YW5hMQswCQYDVQQGEwJVUzEfMB0GCSqG SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEUMBIGA1UECwwLRW5naW5lZXJpbmcw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/DMotFLIehEJbzTgfSvJN @@ -60,10 +60,10 @@ aVIQAy+o85XF8YtiVhvvZ2+kEEGVrQqb46XAsNJwdlAwW6joCCx87aeieo04KRys x+3yfJWwlYJ9SVw4zXcl772AdVOUPD3KY1ufFbXTHRMvGdE823Y6zLh9yeXC19pA b9gh3HMbQi1TnP4a/H2rejY/mN6EfAVnzmoUOIep8Yy1aMtof3EgK/WgY/VWL6Mm 0rdvsVoX1ziZCP6TWG/+wxNJCBYLp01nAFIxZyNOmO1RRR25BNkL7Ngos0u97TZ5 -AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFKvhBAIg5o5wgVcM/ymoHzOaDT6zAWf -ijN5ZAfabBeFkasdvjJFxn9UthDP6hd01NkGbnFdDUByIQd5IGOzFdW35hrW0BEa -YH+B6ZtptGdO4iIaL51qPNqVNKm/KxT6/iFz58kZfSwUn58zwYM1nJSVDuQ+KReV -ooXjrXBfav8tipL7WPb+RivQ5J2bDdnkOQrF4j0X3pXMpBwzoXUC7JhmR7nO5I9+ -Ms04/289vnpEv0dherdaCfoevz1jaLMVAIf9jbj2uIMT//hW7RQFT0kH+TNrP/3G -ff9rBNVGgMFrdP3mGBQdO8YSZw4ejYHEqZxZ7inNz1WmvFMT9FG8t7M= +AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAKuKq653omFiAVRRlXzVbHbL/qy4zbzs +xHVxFmJZZwKr4vucdEa+2QiMMNENXMhI/213KW3BTLyQRObZqujBrrGBslhQsyNZ +NcDD4TSY72iG++maoWNBVMurcwPDGulfUIG4qLgFFH0e+qIruGjryLC2UN8rlscm +ucrJQeGDxT4GEVajVPXiJmW5f+Rf+0nvgn0VJHICWyvXydTcJgh48sNzxiVW0TCZ +OQlDXebjyvI/aBMT1tLfXwVbCUgnh1pg68L/k31c4EXEhSHTQx3CeA3l/ysn8OnU +pEACXycZlEvqZMzi1gTlcHoBpW8/PM49hM/72YDD3/tELx4vMulWa1s= -----END CERTIFICATE----- diff --git a/certs/test/expired/expired-cert.der b/certs/test/expired/expired-cert.der old mode 100644 new mode 100755 index 32a1c4a43..d7d9f5e3a Binary files a/certs/test/expired/expired-cert.der and b/certs/test/expired/expired-cert.der differ diff --git a/certs/test/expired/expired-cert.pem b/certs/test/expired/expired-cert.pem old mode 100644 new mode 100755 index cc21c2b53..9fc58c764 --- a/certs/test/expired/expired-cert.pem +++ b/certs/test/expired/expired-cert.pem @@ -2,7 +2,7 @@ Certificate: Data: Version: 1 (0x0) Serial Number: 4096 (0x1000) - Signature Algorithm: sha256WithRSAEncryption + Signature Algorithm: sha256WithRSAEncryption Issuer: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering Validity Not Before: Jul 31 00:00:00 2018 GMT @@ -10,7 +10,7 @@ Certificate: Subject: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -32,26 +32,26 @@ Certificate: ad:d7 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption - 3d:b8:e9:dc:03:4f:0c:79:ed:5d:b5:e8:45:99:b4:9e:fe:9b: - d9:88:aa:6c:de:1e:34:59:8a:4b:1c:39:0c:7a:a0:7d:24:c1: - 8d:54:d2:65:92:d4:5b:35:cb:de:fc:37:fe:b1:67:20:64:04: - 0a:8f:09:71:cf:d3:16:2e:dc:23:c8:7c:2e:72:35:54:ec:d3: - 63:5a:9d:63:93:42:b6:72:67:8f:80:83:6a:e3:d3:ad:28:87: - 46:4c:6e:56:d2:02:af:58:2e:a9:0e:e0:07:a6:f1:58:dd:17: - 82:27:f1:49:3b:8c:77:6f:08:96:d9:04:c8:ec:34:22:a5:b1: - e9:48:07:41:3c:aa:1e:e4:d9:75:1b:71:bd:4f:ec:5e:fd:2b: - 44:2e:81:cd:8c:b1:08:e6:de:9b:e2:61:c9:ee:43:f7:af:99: - 29:fa:50:69:2a:98:47:b9:58:46:57:1e:2d:29:77:51:89:64: - ee:f2:ba:14:fb:f7:ba:dc:68:d6:34:bc:28:eb:17:f4:37:6a: - 91:a9:cf:d5:46:e8:6e:8f:2f:e7:f2:e0:b1:ca:8a:0f:a4:55: - 8b:b9:c2:89:d0:29:82:b7:11:47:af:8b:96:92:e5:a3:da:11: - 0f:76:db:15:61:a5:5a:ab:60:83:06:de:7e:bf:b6:c8:10:ab: - 38:1a:d3:c2 + 71:a7:78:76:da:ba:98:0f:3d:21:cd:42:76:fe:b9:e3:b9:2e: + 49:a6:8c:31:de:6e:4b:b4:b4:e2:d8:a7:d3:ee:1c:fe:c9:92: + e2:e1:e2:ef:b2:a7:7f:a8:ba:4b:e2:aa:16:e5:ab:5d:e6:28: + 35:cc:1b:8b:8d:b0:86:07:c8:21:8e:90:a6:86:2c:05:23:d9: + a0:4b:bf:8a:81:f0:0f:33:73:af:40:e8:84:dc:bb:dd:af:e4: + 6e:c0:30:d1:60:5c:c2:1e:af:7d:82:16:b7:e5:ad:74:6c:9e: + ff:71:23:2c:70:ac:51:5f:7d:dc:39:90:44:f2:69:b7:84:0b: + 65:4e:4f:0c:8a:ff:0a:6e:9c:56:cd:87:0b:5e:49:7b:eb:25: + e1:e9:1c:ac:73:e4:bd:d0:6f:e0:d8:77:dd:54:df:a5:16:64: + ab:82:0e:c7:ae:fd:1c:cb:22:f2:e3:f3:81:54:7a:26:0e:98: + f4:dc:bb:9c:a1:b8:47:e9:fc:d4:6e:84:51:9d:0e:fa:b2:d5: + 9a:76:6f:f0:30:39:4e:39:cd:84:78:29:4f:d5:7b:eb:06:f2: + 37:ee:3c:c1:8b:3c:b5:21:12:e8:ed:67:a0:98:d6:13:3f:14: + 70:5e:09:67:de:d1:82:8b:88:50:57:d0:fb:fc:d7:64:14:99: + 12:71:61:2f -----BEGIN CERTIFICATE----- MIIDVTCCAj0CAhAAMA0GCSqGSIb3DQEBCwUAMHAxGDAWBgNVBAMMD3d3dy53b2xm c3NsLmNvbTEQMA4GA1UECAwHTW9udGFuYTELMAkGA1UEBhMCVVMxHzAdBgkqhkiG -9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFDASBgNVBAsMC0VuZ2luZWVyaW5nMB4Y -DTIwMTgwNzMxMDAwMFoYDTIwMTgwODMwMDAwMFowcDEYMBYGA1UEAwwPd3d3Lndv +9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFDASBgNVBAsMC0VuZ2luZWVyaW5nMB4X +DTE4MDczMTAwMDAwMFoXDTE4MDgzMDAwMDAwMFowcDEYMBYGA1UEAwwPd3d3Lndv bGZzc2wuY29tMRAwDgYDVQQIDAdNb250YW5hMQswCQYDVQQGEwJVUzEfMB0GCSqG SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEUMBIGA1UECwwLRW5naW5lZXJpbmcw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFl @@ -60,10 +60,10 @@ XXu64CHlci5vLobYlXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2 fwtZaHhzpowYqQJtr8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZR DL1Us+FtXxy8I3PRCQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Wh d7oT0pdz4l0lyWoNwzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63X -AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD246dwDTwx57V216EWZtJ7+m9mIqmze -HjRZikscOQx6oH0kwY1U0mWS1Fs1y978N/6xZyBkBAqPCXHP0xYu3CPIfC5yNVTs -02NanWOTQrZyZ4+Ag2rj060oh0ZMblbSAq9YLqkO4Aem8VjdF4In8Uk7jHdvCJbZ -BMjsNCKlselIB0E8qh7k2XUbcb1P7F79K0Qugc2MsQjm3pviYcnuQ/evmSn6UGkq -mEe5WEZXHi0pd1GJZO7yuhT797rcaNY0vCjrF/Q3apGpz9VG6G6PL+fy4LHKig+k -VYu5wonQKYK3EUevi5aS5aPaEQ922xVhpVqrYIMG3n6/tsgQqzga08I= +AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHGneHbaupgPPSHNQnb+ueO5LkmmjDHe +bku0tOLYp9PuHP7JkuLh4u+yp3+oukviqhblq13mKDXMG4uNsIYHyCGOkKaGLAUj +2aBLv4qB8A8zc69A6ITcu92v5G7AMNFgXMIer32CFrflrXRsnv9xIyxwrFFffdw5 +kETyabeEC2VOTwyK/wpunFbNhwteSXvrJeHpHKxz5L3Qb+DYd91U36UWZKuCDseu +/RzLIvLj84FUeiYOmPTcu5yhuEfp/NRuhFGdDvqy1Zp2b/AwOU45zYR4KU/Ve+sG +8jfuPMGLPLUhEujtZ6CY1hM/FHBeCWfe0YKLiFBX0Pv812QUmRJxYS8= -----END CERTIFICATE----- diff --git a/certs/test/include.am b/certs/test/include.am index fef473888..d7c7e4cef 100644 --- a/certs/test/include.am +++ b/certs/test/include.am @@ -48,6 +48,7 @@ EXTRA_DIST += \ certs/test/server-localhost.der \ certs/test/server-localhost.pem \ certs/test/smime-test.p7s \ + certs/test/smime-test-canon.p7s \ certs/test/smime-test-multipart.p7s \ certs/test/smime-test-multipart-badsig.p7s \ certs/crl/server-goodaltCrl.pem \ diff --git a/certs/test/server-badaltname.der b/certs/test/server-badaltname.der old mode 100644 new mode 100755 index 998b44a60..4a1fef0a6 Binary files a/certs/test/server-badaltname.der and b/certs/test/server-badaltname.der differ diff --git a/certs/test/server-badaltname.pem b/certs/test/server-badaltname.pem old mode 100644 new mode 100755 index 849e6600b..9122ccb17 --- a/certs/test/server-badaltname.pem +++ b/certs/test/server-badaltname.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - b2:b1:5d:67:1e:bd:3f:cb - Signature Algorithm: sha256WithRSAEncryption + 6d:8b:3a:c3:b7:18:15:6d:43:02:95:5f:94:12:5d:7d:d1:35:ac:74 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -36,40 +36,40 @@ Certificate: X509v3 Subject Alternative Name: DNS:www.nomatch.com Signature Algorithm: sha256WithRSAEncryption - b3:a6:46:25:12:aa:40:b8:db:4e:7f:c5:06:ae:76:51:67:cc: - a1:58:bf:47:37:1f:59:99:e8:3e:2d:c8:38:84:19:18:f5:c1: - d3:2d:c5:82:11:e7:94:c4:0f:f1:d1:e6:30:d2:9a:20:07:33: - 3c:e9:8d:a3:7c:e3:40:d5:e1:ec:8c:94:60:f1:93:8a:10:bb: - a8:dd:0c:6c:89:68:8c:f2:e3:53:a3:58:21:5b:7d:ab:b2:f2: - 7c:1a:06:8f:2d:fd:89:75:1f:9f:92:24:9b:f9:1e:a0:dd:01: - 08:a4:2c:58:40:29:c6:b9:46:42:66:4f:d6:21:db:42:24:47: - 1b:74:94:99:d2:14:84:5b:75:49:03:92:f3:51:7b:c5:53:68: - 04:98:a6:0c:08:86:91:28:c8:d4:86:5f:3d:0e:05:54:bd:05: - a6:99:2e:94:c9:db:e0:5e:19:94:6d:4a:a2:81:73:e7:d3:8f: - e4:ec:f3:fe:22:26:ae:8a:86:01:e2:c6:7c:38:dc:88:54:25: - 69:aa:d4:1c:33:d8:9a:ae:83:95:59:1a:6f:d6:27:e4:03:7a: - 25:66:16:02:7d:2b:fb:ff:8e:82:1b:4f:2c:d6:ca:61:16:08: - aa:44:0f:aa:76:3b:72:87:21:dd:a8:5d:38:fc:c7:03:3c:4a: - 0a:80:7a:4e + 4f:8b:ef:6c:a6:c6:2c:af:b4:a7:c9:ed:4c:e1:8c:d0:83:40: + b1:ee:72:ba:f7:92:bb:4f:b6:e6:a3:3e:99:8c:af:8c:12:15: + c0:51:4c:46:a8:96:2a:72:a1:35:60:4f:e2:e2:e1:69:e2:f3: + c7:c7:b1:bb:01:54:3c:a8:5d:ac:76:1a:40:4e:8d:2a:68:6d: + 58:70:ce:61:87:f5:3d:e6:21:03:85:8b:82:e5:6a:a1:c3:75: + 06:7d:16:b0:38:71:de:5c:1e:b9:23:0b:09:8e:7a:d7:43:bf: + 76:57:05:01:54:e2:b0:87:82:05:16:9b:ac:4c:98:ef:4f:76: + 3a:e2:9d:b6:54:a4:f3:e8:f9:1f:11:65:2a:9d:65:a3:f6:80: + 48:d0:f1:11:f3:86:a9:ce:8c:f9:33:19:ba:12:d7:7f:2d:48: + 97:c5:12:c7:7f:fb:9a:41:41:05:84:7a:ec:4b:ca:fb:da:0e: + 2d:7f:6b:3b:4b:22:0c:4d:92:7b:8a:3e:2b:99:7b:81:6c:2d: + 2b:b2:68:36:99:1d:96:54:4d:86:79:80:df:3f:1e:c1:18:e2: + fd:ed:ab:b3:e9:27:32:f6:d1:64:b5:a6:34:ab:20:99:d0:10: + 2b:4b:54:e5:c0:dd:ad:ac:5c:31:44:c5:e9:d2:c9:b8:4d:aa: + f0:7f:c3:e2 -----BEGIN CERTIFICATE----- -MIIDpzCCAo+gAwIBAgIJALKxXWcevT/LMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG -A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y -MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ -MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM -D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv -bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn -AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX -/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj -xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 -ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj -laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP -rdcCAwEAAaMeMBwwGgYDVR0RBBMwEYIPd3d3Lm5vbWF0Y2guY29tMA0GCSqGSIb3 -DQEBCwUAA4IBAQCzpkYlEqpAuNtOf8UGrnZRZ8yhWL9HNx9Zmeg+Lcg4hBkY9cHT -LcWCEeeUxA/x0eYw0pogBzM86Y2jfONA1eHsjJRg8ZOKELuo3QxsiWiM8uNTo1gh -W32rsvJ8GgaPLf2JdR+fkiSb+R6g3QEIpCxYQCnGuUZCZk/WIdtCJEcbdJSZ0hSE -W3VJA5LzUXvFU2gEmKYMCIaRKMjUhl89DgVUvQWmmS6UydvgXhmUbUqigXPn04/k -7PP+IiauioYB4sZ8ONyIVCVpqtQcM9iaroOVWRpv1ifkA3olZhYCfSv7/46CG08s -1sphFgiqRA+qdjtyhyHdqF04/McDPEoKgHpO +MIIDsjCCApqgAwIBAgIUbYs6w7cYFW1DApVflBJdfdE1rHQwDQYJKoZIhvcNAQEL +BQAwgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEYMBYGA1UEAwwPd3d3Lm5vbWF0 +Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYx +NTIyMDIzM1oXDTI0MDMxMTIyMDIzM1owgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd3d3Lm5vbWF0Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI +4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUv +j+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+t +Q7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem +8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDB +Y3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE +4eZhg8XSlt/Z0E+t1wIDAQABox4wHDAaBgNVHREEEzARgg93d3cubm9tYXRjaC5j +b20wDQYJKoZIhvcNAQELBQADggEBAE+L72ymxiyvtKfJ7UzhjNCDQLHucrr3krtP +tuajPpmMr4wSFcBRTEaolipyoTVgT+Li4Wni88fHsbsBVDyoXax2GkBOjSpobVhw +zmGH9T3mIQOFi4LlaqHDdQZ9FrA4cd5cHrkjCwmOetdDv3ZXBQFU4rCHggUWm6xM +mO9PdjrinbZUpPPo+R8RZSqdZaP2gEjQ8RHzhqnOjPkzGboS138tSJfFEsd/+5pB +QQWEeuxLyvvaDi1/aztLIgxNknuKPiuZe4FsLSuyaDaZHZZUTYZ5gN8/HsEY4v3t +q7PpJzL20WS1pjSrIJnQECtLVOXA3a2sXDFExenSybhNqvB/w+I= -----END CERTIFICATE----- diff --git a/certs/test/server-badaltnull.der b/certs/test/server-badaltnull.der old mode 100644 new mode 100755 index 551c1dbe2..10e6385bf Binary files a/certs/test/server-badaltnull.der and b/certs/test/server-badaltnull.der differ diff --git a/certs/test/server-badaltnull.pem b/certs/test/server-badaltnull.pem old mode 100644 new mode 100755 index 88613b353..4ef1fd994 --- a/certs/test/server-badaltnull.pem +++ b/certs/test/server-badaltnull.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 90:02:1e:3e:94:03:86:27 - Signature Algorithm: sha256WithRSAEncryption + 63:8b:eb:7c:a5:8c:1a:1f:c0:4d:d2:f3:36:90:e1:89:6b:d8:95:a0 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -36,41 +36,41 @@ Certificate: X509v3 Subject Alternative Name: DNS:DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68 Signature Algorithm: sha256WithRSAEncryption - 7f:43:90:8a:bb:e2:2e:d9:f1:df:83:6d:89:53:65:b0:69:6c: - 00:30:35:b3:24:3c:3e:40:60:7c:b2:a1:86:5c:99:bc:30:e3: - f6:f0:2f:71:e0:1f:17:a2:71:a8:ad:33:62:98:13:61:04:0d: - f2:fc:aa:df:af:62:6d:ac:ba:55:95:da:5e:5b:14:c1:a5:8e: - 73:62:a7:e1:3f:fb:66:6a:c9:f7:41:3b:17:9c:f8:20:0a:11: - 54:e9:8e:bd:42:3e:61:6f:b7:21:c2:aa:8f:1b:73:9e:af:eb: - 4d:7b:94:4a:17:d5:4a:15:a5:62:bb:4b:5f:06:3f:a2:e2:28: - b7:c9:67:4b:d9:0d:b7:8f:bf:46:02:ad:a6:aa:31:cb:ff:76: - 9d:e5:d7:b8:fd:7b:df:e1:42:75:78:76:7d:35:90:6c:94:16: - 47:0f:65:e6:86:ee:65:16:19:65:a3:96:20:44:28:f5:de:8d: - f3:f7:8e:2b:95:f8:4f:4d:76:74:43:5d:e1:84:7c:94:f0:8c: - c7:19:6c:a3:77:06:37:7e:c2:f4:f7:6a:c6:19:8a:54:75:cc: - b6:a7:7c:db:f3:91:79:76:d1:e4:b8:fa:cd:07:94:ef:33:11: - fa:43:ca:1f:6e:08:70:9c:3c:19:dd:89:65:78:aa:6a:da:ec: - d5:d9:f8:3f + 80:b1:67:53:d5:5d:8d:f0:a1:2a:31:ce:ff:9c:16:01:93:f9: + 10:37:8c:bf:e1:26:b7:13:20:d4:19:df:c5:b8:cd:2d:e3:36: + 37:d3:9e:14:f8:16:35:eb:f3:85:ba:5a:65:3b:ec:19:c8:50: + 51:3a:ff:d8:52:ab:6f:49:6d:12:af:81:45:c1:39:1a:24:67: + 84:04:d4:6e:02:21:6b:10:28:e4:40:85:5b:dd:58:99:4e:d1: + e9:11:c9:d2:18:c2:4e:7c:e2:14:f8:cf:b4:7a:e0:7f:f6:e3: + af:d0:8a:de:e0:d4:da:65:35:92:72:17:e4:cc:18:61:8d:fd: + ef:9c:58:fc:1a:44:10:1b:29:50:82:f8:26:c4:ee:ab:8a:d8: + a8:bc:67:9e:99:83:37:cb:f0:dc:25:b0:ba:0d:c8:b4:32:d8: + 95:dd:92:76:31:e2:20:0b:65:c0:a7:f2:17:11:3d:db:78:f3: + 21:ea:68:8c:4e:97:2f:5b:b0:d4:e9:48:4a:5d:49:25:bc:20: + ee:a5:29:f4:29:97:8d:de:56:74:78:28:b5:e3:e3:66:95:aa: + 41:b8:c0:44:88:e3:33:df:32:92:fd:04:a5:da:60:4f:c0:2f: + 44:e8:bd:35:ce:72:d0:77:28:7b:1c:03:5c:03:ad:d8:52:6b: + d5:a0:ea:34 -----BEGIN CERTIFICATE----- -MIIDyDCCArCgAwIBAgIJAJACHj6UA4YnMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG -A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y -MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ -MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM -D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv -bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn -AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX -/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj -xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 -ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj -laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP -rdcCAwEAAaM/MD0wOwYDVR0RBDQwMoIwREVSOjMwOjBkOjgyOjBiOjZjOjZmOjYz -OjYxOjZjOjY4OjZmOjczOjc0OjAwOjY4MA0GCSqGSIb3DQEBCwUAA4IBAQB/Q5CK -u+Iu2fHfg22JU2WwaWwAMDWzJDw+QGB8sqGGXJm8MOP28C9x4B8XonGorTNimBNh -BA3y/Krfr2JtrLpVldpeWxTBpY5zYqfhP/tmasn3QTsXnPggChFU6Y69Qj5hb7ch -wqqPG3Oer+tNe5RKF9VKFaViu0tfBj+i4ii3yWdL2Q23j79GAq2mqjHL/3ad5de4 -/Xvf4UJ1eHZ9NZBslBZHD2Xmhu5lFhllo5YgRCj13o3z944rlfhPTXZ0Q13hhHyU -8IzHGWyjdwY3fsL092rGGYpUdcy2p3zb85F5dtHkuPrNB5TvMxH6Q8ofbghwnDwZ -3YlleKpq2uzV2fg/ +MIID0zCCArugAwIBAgIUY4vrfKWMGh/ATdLzNpDhiWvYlaAwDQYJKoZIhvcNAQEL +BQAwgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEYMBYGA1UEAwwPd3d3Lm5vbWF0 +Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYx +NTIyMDIzM1oXDTI0MDMxMTIyMDIzM1owgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd3d3Lm5vbWF0Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI +4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUv +j+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+t +Q7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem +8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDB +Y3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE +4eZhg8XSlt/Z0E+t1wIDAQABoz8wPTA7BgNVHREENDAygjBERVI6MzA6MGQ6ODI6 +MGI6NmM6NmY6NjM6NjE6NmM6Njg6NmY6NzM6NzQ6MDA6NjgwDQYJKoZIhvcNAQEL +BQADggEBAICxZ1PVXY3woSoxzv+cFgGT+RA3jL/hJrcTINQZ38W4zS3jNjfTnhT4 +FjXr84W6WmU77BnIUFE6/9hSq29JbRKvgUXBORokZ4QE1G4CIWsQKORAhVvdWJlO +0ekRydIYwk584hT4z7R64H/246/Qit7g1NplNZJyF+TMGGGN/e+cWPwaRBAbKVCC ++CbE7quK2Ki8Z56ZgzfL8NwlsLoNyLQy2JXdknYx4iALZcCn8hcRPdt48yHqaIxO +ly9bsNTpSEpdSSW8IO6lKfQpl43eVnR4KLXj42aVqkG4wESI4zPfMpL9BKXaYE/A +L0TovTXOctB3KHscA1wDrdhSa9Wg6jQ= -----END CERTIFICATE----- diff --git a/certs/test/server-badcn.der b/certs/test/server-badcn.der old mode 100644 new mode 100755 index 5161e6a1c..8cab7cefb Binary files a/certs/test/server-badcn.der and b/certs/test/server-badcn.der differ diff --git a/certs/test/server-badcn.pem b/certs/test/server-badcn.pem old mode 100644 new mode 100755 index eff21cd58..9aeb3846e --- a/certs/test/server-badcn.pem +++ b/certs/test/server-badcn.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:e7:91:d6:1a:3a:ce:8a - Signature Algorithm: sha256WithRSAEncryption + 0b:8f:fc:fa:c7:70:2a:92:f9:ba:32:4e:79:14:00:72:d9:ec:7d:b6 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -33,39 +33,40 @@ Certificate: ad:d7 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption - 4b:d3:ae:c0:12:36:af:f3:53:ca:55:b0:8e:d4:e3:9d:ec:fd: - df:92:9a:cc:3f:b3:d9:4f:4f:8e:1d:20:b2:94:85:88:07:d4: - 7c:b3:8f:30:84:9b:9a:bf:46:3f:50:3f:3f:5f:59:f7:68:1e: - b9:f6:9b:89:d7:e6:d5:b3:fd:01:22:df:e0:a2:50:9c:b4:e1: - 20:e7:27:e8:5a:ee:d1:1c:01:24:05:e5:8d:f9:ad:62:4c:1b: - c7:28:b4:ce:11:69:c4:65:f1:c8:9c:cb:a4:84:a0:db:74:2d: - fc:f6:da:a8:f6:e2:c8:9e:58:6e:3e:da:f9:7f:06:8c:3f:da: - 56:f3:c5:9e:11:b8:7d:4d:7d:f5:77:a8:0e:c7:9c:92:e7:a9: - 72:b7:18:06:6c:a1:5c:0d:bf:b4:0e:32:05:de:b7:94:cc:aa: - a8:f5:b5:22:66:79:6a:58:23:87:18:67:60:a9:3d:56:89:16: - 73:41:6b:56:d2:46:b0:3c:36:26:ec:6c:bd:53:02:24:a7:c1: - 76:f8:2d:3b:7f:22:e0:46:2c:f0:bf:5d:09:cd:bc:d3:40:3a: - 42:e0:c8:d4:c0:18:f1:21:b4:22:62:3d:57:f9:2e:64:00:62: - 8d:78:4d:03:af:8b:c6:4e:0e:c1:d5:31:59:56:64:8a:75:c6: - 46:0e:42:80 + 86:ba:df:88:f4:26:fc:ac:e6:a3:98:c6:4b:11:c6:f0:de:e8: + 79:6b:84:09:bc:38:83:a1:23:bd:c7:50:9a:8e:a9:8f:e8:84: + 77:68:94:a1:58:5a:5b:71:49:2d:d5:23:7c:67:1a:fe:8a:a6: + f6:9e:6a:e6:5a:65:73:e7:42:78:a9:10:8d:c4:69:bb:1d:7c: + 1e:c0:b0:cf:d5:e4:3c:44:8d:85:a9:76:94:a2:b3:1b:b1:94: + 42:7e:cd:ef:da:88:f1:62:a9:ed:d6:70:85:26:2b:2d:b2:e7: + e6:af:0d:76:0c:73:48:c6:ab:18:d4:97:cb:d8:bd:24:8f:bd: + c1:9a:79:aa:f4:1c:10:8c:6d:71:71:b9:1c:2e:49:21:2a:dc: + 33:83:5b:2c:8a:d2:6b:06:9e:23:47:6b:72:12:b8:43:6a:94: + d6:c5:25:df:ae:77:7f:b4:4a:6c:39:b9:47:04:68:58:23:e1: + c1:24:f3:f2:e1:b8:72:27:fb:4a:3e:7f:bf:8b:bc:69:79:74: + 28:8c:33:b0:9d:7a:cb:c4:5b:6b:82:43:60:53:85:87:db:0b: + 1a:e4:83:bb:6c:a3:87:b9:87:42:a0:7f:ff:ec:db:ec:8e:89: + 83:d6:af:f3:80:d0:5d:fe:e5:15:c1:7a:bc:d6:cf:14:b8:d5: + 25:92:ef:b1 -----BEGIN CERTIFICATE----- -MIIDhzCCAm+gAwIBAgIJANjnkdYaOs6KMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG -A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y -MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ -MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM -D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv -bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn -AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX -/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj -xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 -ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj -laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP -rdcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAS9OuwBI2r/NTylWwjtTjnez935Ka -zD+z2U9Pjh0gspSFiAfUfLOPMISbmr9GP1A/P19Z92geufabidfm1bP9ASLf4KJQ -nLThIOcn6Fru0RwBJAXljfmtYkwbxyi0zhFpxGXxyJzLpISg23Qt/PbaqPbiyJ5Y -bj7a+X8GjD/aVvPFnhG4fU199XeoDseckuepcrcYBmyhXA2/tA4yBd63lMyqqPW1 -ImZ5algjhxhnYKk9VokWc0FrVtJGsDw2JuxsvVMCJKfBdvgtO38i4EYs8L9dCc28 -00A6QuDI1MAY8SG0ImI9V/kuZABijXhNA6+Lxk4OwdUxWVZkinXGRg5CgA== +MIIDkjCCAnqgAwIBAgIUC4/8+sdwKpL5ujJOeRQActnsfbYwDQYJKoZIhvcNAQEL +BQAwgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEYMBYGA1UEAwwPd3d3Lm5vbWF0 +Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYx +NTIyMDIzM1oXDTI0MDMxMTIyMDIzM1owgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd3d3Lm5vbWF0Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI +4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUv +j+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+t +Q7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem +8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDB +Y3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE +4eZhg8XSlt/Z0E+t1wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCGut+I9Cb8rOaj +mMZLEcbw3uh5a4QJvDiDoSO9x1CajqmP6IR3aJShWFpbcUkt1SN8Zxr+iqb2nmrm +WmVz50J4qRCNxGm7HXwewLDP1eQ8RI2FqXaUorMbsZRCfs3v2ojxYqnt1nCFJist +sufmrw12DHNIxqsY1JfL2L0kj73Bmnmq9BwQjG1xcbkcLkkhKtwzg1ssitJrBp4j +R2tyErhDapTWxSXfrnd/tEpsOblHBGhYI+HBJPPy4bhyJ/tKPn+/i7xpeXQojDOw +nXrLxFtrgkNgU4WH2wsa5IO7bKOHuYdCoH//7NvsjomD1q/zgNBd/uUVwXq81s8U +uNUlku+x -----END CERTIFICATE----- diff --git a/certs/test/server-badcnnull.der b/certs/test/server-badcnnull.der old mode 100644 new mode 100755 index 9c4ff9cc5..e84fcc012 Binary files a/certs/test/server-badcnnull.der and b/certs/test/server-badcnnull.der differ diff --git a/certs/test/server-badcnnull.pem b/certs/test/server-badcnnull.pem old mode 100644 new mode 100755 index 41f31480a..52d18641b --- a/certs/test/server-badcnnull.pem +++ b/certs/test/server-badcnnull.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - c8:aa:6e:e3:4e:bf:ed:34 - Signature Algorithm: sha256WithRSAEncryption + 2f:dc:cf:8a:1c:ed:ad:f7:a4:ac:5f:24:68:1c:f5:dd:82:c5:59:1e + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -33,41 +33,41 @@ Certificate: ad:d7 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption - 59:58:d4:6f:58:56:b5:a8:93:1c:32:3c:be:f1:e2:e8:93:c9: - 64:69:b3:8e:87:66:20:62:27:23:ff:3a:99:73:4b:56:27:27: - 9f:2a:17:56:d9:6d:01:a1:f5:e7:50:aa:ff:23:fb:4e:3d:35: - fe:60:d4:ba:fd:01:1a:5b:99:c8:72:e8:19:bc:82:92:26:c8: - 02:09:6a:5b:50:b1:69:ab:49:9b:f5:07:f5:bd:f1:70:13:0e: - c7:69:7d:ca:78:9b:84:6f:b0:c7:c9:48:da:2e:c7:2e:44:18: - 15:17:ce:23:63:fa:ae:bb:da:0d:72:fa:e6:99:d5:00:bb:55: - 1f:7b:73:da:ad:36:e7:43:db:20:82:e5:83:a9:7f:49:f2:e3: - 26:8d:23:ea:da:a0:9a:1d:fa:6a:12:a8:c9:e8:01:87:8b:39: - 90:3e:f9:b5:f2:36:ed:87:5c:55:6d:b7:40:34:59:cb:04:6e: - 06:c6:f0:4b:31:51:25:50:c7:a2:5f:a0:ba:0a:6f:fb:13:01: - ef:21:18:af:64:9d:39:b8:b1:9b:0f:8d:34:12:26:43:a0:51: - 4d:82:27:f8:19:dc:fc:29:d6:29:5e:22:b9:f4:da:e7:c0:2a: - 1c:0c:7a:d9:0f:cb:08:a0:41:40:03:4f:cb:04:20:2a:f4:e0: - bd:9b:fa:53 + ae:86:0e:c4:71:4f:75:f5:12:19:d8:60:b4:80:f8:e2:23:43: + cb:7f:38:16:97:b6:1e:57:58:d1:41:6b:7e:8b:4e:9a:10:3f: + 24:fa:89:23:ba:76:28:ae:4a:d6:d9:35:52:c9:60:0b:70:5b: + fa:79:6d:0c:36:fb:cd:7e:16:8c:e4:7a:5b:6d:d2:c2:28:86: + d7:ea:b2:e1:d9:08:5c:a6:49:12:8c:8d:0c:1a:f5:a9:ce:35: + b4:05:d2:16:90:f1:42:0b:7f:35:40:ad:0e:77:f0:5e:aa:9c: + 14:c9:2d:55:26:94:44:4a:23:d7:92:6f:f3:75:e4:96:5c:ee: + 0b:25:39:a4:67:3c:58:f3:32:d9:12:c7:0f:18:89:4f:e6:42: + ba:22:1e:3d:c8:6a:2d:dc:cc:94:c8:bf:5f:6e:1d:35:cc:2d: + 60:78:d5:a9:2a:52:28:65:c5:17:0f:bb:47:f7:0a:17:a1:dc: + 4b:fa:a6:d9:b7:17:37:b6:d9:94:fd:3c:f0:a6:3d:c1:51:67: + 11:c6:53:ce:db:e3:d7:fe:d3:d6:73:63:15:48:02:35:d1:df: + e8:e0:14:c2:f8:52:2c:a7:ff:15:8c:86:f2:4a:de:a3:61:b4: + ce:46:29:1e:3d:74:92:a3:f8:39:fc:d5:5c:12:01:d0:b9:46: + 9f:b6:18:0d -----BEGIN CERTIFICATE----- -MIIDyTCCArGgAwIBAgIJAMiqbuNOv+00MA0GCSqGSIb3DQEBCwUAMIGjMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG -A1UECwwLRW5naW5lZXJpbmcxOTA3BgNVBAMMMERFUjozMDowZDo4MjowYjo2Yzo2 -Zjo2Mzo2MTo2Yzo2ODo2Zjo3Mzo3NDowMDo2ODEfMB0GCSqGSIb3DQEJARYQaW5m -b0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0yMTA2MTUyMTIxMjRaMIGj -MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1h -bjEUMBIGA1UECwwLRW5naW5lZXJpbmcxOTA3BgNVBAMMMERFUjozMDowZDo4Mjow -Yjo2Yzo2Zjo2Mzo2MTo2Yzo2ODo2Zjo3Mzo3NDowMDo2ODEfMB0GCSqGSIb3DQEJ -ARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF1 -94rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+Fj -Y1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0Yz -aYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh -1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMg -s1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAWVjU -b1hWtaiTHDI8vvHi6JPJZGmzjodmIGInI/86mXNLVicnnyoXVtltAaH151Cq/yP7 -Tj01/mDUuv0BGluZyHLoGbyCkibIAglqW1CxaatJm/UH9b3xcBMOx2l9ynibhG+w -x8lI2i7HLkQYFRfOI2P6rrvaDXL65pnVALtVH3tz2q0250PbIILlg6l/SfLjJo0j -6tqgmh36ahKoyegBh4s5kD75tfI27YdcVW23QDRZywRuBsbwSzFRJVDHol+gugpv -+xMB7yEYr2SdObixmw+NNBImQ6BRTYIn+Bnc/CnWKV4iufTa58AqHAx62Q/LCKBB -QANPywQgKvTgvZv6Uw== +MIID1DCCArygAwIBAgIUL9zPihztrfekrF8kaBz13YLFWR4wDQYJKoZIhvcNAQEL +BQAwgaMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzE5MDcGA1UEAwwwREVSOjMwOjBk +OjgyOjBiOjZjOjZmOjYzOjYxOjZjOjY4OjZmOjczOjc0OjAwOjY4MR8wHQYJKoZI +hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYxNTIyMDIzM1oXDTI0MDMx +MTIyMDIzM1owgaMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYD +VQQHDAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzE5MDcGA1UEAwwwREVS +OjMwOjBkOjgyOjBiOjZjOjZmOjYzOjYxOjZjOjY4OjZmOjczOjc0OjAwOjY4MR8w +HQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8 +fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwb +U7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEu +uBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTS +ELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0 +sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQABMA0GCSqGSIb3DQEB +CwUAA4IBAQCuhg7EcU919RIZ2GC0gPjiI0PLfzgWl7YeV1jRQWt+i06aED8k+okj +unYorkrW2TVSyWALcFv6eW0MNvvNfhaM5HpbbdLCKIbX6rLh2QhcpkkSjI0MGvWp +zjW0BdIWkPFCC381QK0Od/BeqpwUyS1VJpRESiPXkm/zdeSWXO4LJTmkZzxY8zLZ +EscPGIlP5kK6Ih49yGot3MyUyL9fbh01zC1geNWpKlIoZcUXD7tH9woXodxL+qbZ +txc3ttmU/Tzwpj3BUWcRxlPO2+PX/tPWc2MVSAI10d/o4BTC+FIsp/8VjIbySt6j +YbTORikePXSSo/g5/NVcEgHQuUafthgN -----END CERTIFICATE----- diff --git a/certs/test/server-garbage.der b/certs/test/server-garbage.der old mode 100644 new mode 100755 index 1877226d3..c8e7d7cec Binary files a/certs/test/server-garbage.der and b/certs/test/server-garbage.der differ diff --git a/certs/test/server-garbage.pem b/certs/test/server-garbage.pem old mode 100644 new mode 100755 index 1eec5170c..32e1ed08d --- a/certs/test/server-garbage.pem +++ b/certs/test/server-garbage.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - c7:45:d4:e8:37:93:0d:ad - Signature Algorithm: sha256WithRSAEncryption + 5b:d1:6a:7d:d9:c4:9a:1a:c6:11:44:12:fc:ca:a1:f4:79:6b:1b:a2 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:34 2021 GMT + Not After : Mar 11 22:02:34 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -36,40 +36,40 @@ Certificate: X509v3 Subject Alternative Name: DNS:garbage Signature Algorithm: sha256WithRSAEncryption - 3f:9b:00:89:dc:8e:20:7a:8e:a3:1c:e5:4a:4f:7a:76:eb:d0: - cb:33:6d:30:f8:b0:7f:40:2c:da:90:46:00:4c:28:8d:6e:6f: - fc:25:43:80:d3:59:40:a6:e8:1b:0f:a8:25:13:ec:b9:c0:93: - bd:ef:09:49:b5:fc:95:1d:76:0e:b6:7e:94:4d:d6:04:c9:36: - 72:e9:1d:ea:92:48:51:b0:61:d4:90:d3:99:44:f0:95:be:c8: - 46:a3:22:24:34:d8:52:55:37:95:af:10:ec:ed:f3:a3:26:a6: - 1b:10:20:3c:a2:5c:63:18:41:91:f7:cb:c0:a0:ec:8b:5b:25: - 55:cd:a2:d1:2c:c8:0b:c8:bf:4c:fc:0b:85:b4:c1:2e:be:d1: - 39:01:eb:fa:5c:ce:63:6f:20:ba:87:83:c7:45:14:9f:b2:81: - 5d:d8:48:4e:bc:cc:f5:72:be:95:07:6d:2c:78:e1:87:47:a1: - 02:a5:3c:65:33:2b:5e:8f:cf:53:06:f9:73:8c:0f:91:5d:f7: - 60:df:0c:21:c7:39:08:bd:d3:cd:99:80:29:fd:38:02:8a:65: - 83:e9:11:b0:a9:d5:2e:fa:7e:20:74:bb:3e:55:6d:05:90:55: - b8:ec:c9:84:de:41:cc:83:56:07:5c:3f:25:29:31:f2:3a:47: - ed:0b:be:fc + b1:e4:67:79:4d:83:e3:5a:49:d3:8e:33:18:a2:ee:bd:c4:66: + 40:d2:81:19:c8:fa:95:0a:e9:8f:dd:58:cd:10:8a:c3:43:fd: + 62:2f:ca:2b:0d:e9:7d:28:4f:5f:45:3b:27:3b:7d:06:39:12: + 75:c3:e7:2e:8e:82:f7:b1:28:7f:7f:76:83:db:f5:ea:d2:87: + 5b:90:a4:b1:3e:4b:64:a3:3d:0a:d7:41:31:71:28:3b:54:89: + 20:b5:17:65:20:c9:f8:1b:25:11:44:a3:0b:b5:60:37:f0:92: + fc:3b:1d:4a:03:ef:e1:b4:61:23:33:8c:48:2f:e8:dd:4b:f8: + 3d:97:00:55:c7:49:be:35:6a:3f:e1:db:32:ef:7f:b3:6a:ab: + 5d:8b:f1:fb:45:1e:75:1f:d1:e6:93:24:7f:b2:57:97:57:08: + 27:3d:94:3b:b3:97:b4:07:c0:e7:ed:77:9a:e1:f7:90:2d:af: + 1e:2f:15:7c:da:2c:d7:db:a2:b1:e5:4e:27:4c:0c:52:0c:54: + a1:d3:b9:31:aa:d1:1f:20:91:b6:c1:7f:72:43:02:63:f4:13: + 1d:66:7b:80:7c:1e:b5:17:03:2b:95:53:47:eb:10:63:e6:8e: + 23:ca:c7:2d:05:eb:ad:db:24:a4:e6:f0:2b:a2:7a:37:d7:20: + 5c:ed:82:ce -----BEGIN CERTIFICATE----- -MIIDkTCCAnmgAwIBAgIJAMdF1Og3kw2tMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD -VQQLDAtFbmdpbmVlcmluZzESMBAGA1UEAwwJbG9jYWxob3N0MR8wHQYJKoZIhvcN -AQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIx -MjEyNFowfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcM -B0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhv -c3QxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFlxkWu8rwkMLiVzi9O -1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2SoF/zKXXu64CHlci5vLobY -lXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2fwtZaHhzpowYqQJt -r8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZRDL1Us+FtXxy8I3PR -CQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Whd7oT0pdz4l0lyWoN -wzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63XAgMBAAGjFjAUMBIG -A1UdEQQLMAmCB2dhcmJhZ2UwDQYJKoZIhvcNAQELBQADggEBAD+bAIncjiB6jqMc -5UpPenbr0MszbTD4sH9ALNqQRgBMKI1ub/wlQ4DTWUCm6BsPqCUT7LnAk73vCUm1 -/JUddg62fpRN1gTJNnLpHeqSSFGwYdSQ05lE8JW+yEajIiQ02FJVN5WvEOzt86Mm -phsQIDyiXGMYQZH3y8Cg7ItbJVXNotEsyAvIv0z8C4W0wS6+0TkB6/pczmNvILqH -g8dFFJ+ygV3YSE68zPVyvpUHbSx44YdHoQKlPGUzK16Pz1MG+XOMD5Fd92DfDCHH -OQi9082ZgCn9OAKKZYPpEbCp1S76fiB0uz5VbQWQVbjsyYTeQcyDVgdcPyUpMfI6 -R+0Lvvw= +MIIDnDCCAoSgAwIBAgIUW9FqfdnEmhrGEUQS/Mqh9HlrG6IwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhvc3Qx +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjEwNjE1MjIwMjM0 +WhcNMjQwMzExMjIwMjM0WjB8MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFu +YTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxEjAQBgNV +BAMMCWxvY2FsaG9zdDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXG +Ra7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpd +e7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/ +C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEM +vVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3 +uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcC +AwEAAaMWMBQwEgYDVR0RBAswCYIHZ2FyYmFnZTANBgkqhkiG9w0BAQsFAAOCAQEA +seRneU2D41pJ044zGKLuvcRmQNKBGcj6lQrpj91YzRCKw0P9Yi/KKw3pfShPX0U7 +Jzt9BjkSdcPnLo6C97Eof392g9v16tKHW5CksT5LZKM9CtdBMXEoO1SJILUXZSDJ ++BslEUSjC7VgN/CS/DsdSgPv4bRhIzOMSC/o3Uv4PZcAVcdJvjVqP+HbMu9/s2qr +XYvx+0UedR/R5pMkf7JXl1cIJz2UO7OXtAfA5+13muH3kC2vHi8VfNos19uiseVO +J0wMUgxUodO5MarRHyCRtsF/ckMCY/QTHWZ7gHwetRcDK5VTR+sQY+aOI8rHLQXr +rdskpObwK6J6N9cgXO2Czg== -----END CERTIFICATE----- diff --git a/certs/test/server-goodalt.der b/certs/test/server-goodalt.der old mode 100644 new mode 100755 index 66fc73555..fa2afb567 Binary files a/certs/test/server-goodalt.der and b/certs/test/server-goodalt.der differ diff --git a/certs/test/server-goodalt.pem b/certs/test/server-goodalt.pem old mode 100644 new mode 100755 index 3902608e4..7a393bee3 --- a/certs/test/server-goodalt.pem +++ b/certs/test/server-goodalt.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - cd:00:d2:2e:bb:c5:a6:5d - Signature Algorithm: sha256WithRSAEncryption + 22:0f:95:6c:4d:29:a8:eb:a8:48:f9:16:e0:f7:9f:52:2c:3d:8c:74 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -36,40 +36,40 @@ Certificate: X509v3 Subject Alternative Name: DNS:localhost Signature Algorithm: sha256WithRSAEncryption - 5e:9a:6d:ea:58:6d:a9:6e:fa:c7:bb:16:7d:5d:cb:97:54:cb: - 4f:e8:38:95:e2:1b:6c:ea:ad:4b:cb:ea:58:57:f7:2e:05:c9: - 57:9b:f1:cc:03:c1:29:7c:13:16:8f:78:d2:c0:ea:18:af:f8: - 1d:cf:f4:25:6c:33:cd:d8:9b:28:21:c4:dd:f0:df:10:73:10: - ed:2e:30:c1:53:15:50:1f:f9:f8:d6:db:14:66:ad:a6:a7:78: - 7e:a1:46:50:f5:cf:07:21:e7:33:e4:25:d8:18:d2:1f:ca:7c: - d6:45:d1:db:2f:34:ae:61:b1:1a:05:4e:ce:ba:b7:48:5f:b7: - 0d:9e:01:f0:5e:fd:f1:30:60:0d:59:6e:1b:d9:b7:29:15:31: - d8:be:dc:2f:23:f5:13:4e:44:eb:2d:0e:52:9e:7e:3d:7d:a9: - a0:af:88:0a:15:8c:cb:11:dc:24:b4:6b:af:3b:a5:e4:82:57: - 13:d1:ca:24:75:b0:53:bf:b8:ec:71:81:a3:84:a9:b7:fe:bb: - 31:1b:89:94:be:91:16:dd:67:1b:66:1b:79:81:19:3c:1d:29: - 1e:e0:dc:3f:0b:6e:0d:e5:0b:0a:43:28:f9:69:d7:7a:55:2c: - e3:7b:2f:b7:66:34:ed:29:f5:c5:6d:09:51:d8:00:69:57:34: - 34:26:f3:b7 + b3:56:1e:6c:00:74:10:74:01:e6:44:8f:61:f3:db:cb:57:3a: + e9:20:d7:09:ad:85:29:1f:dd:6e:2c:98:21:7b:46:51:10:56: + 38:10:9b:7b:ad:f4:8c:6c:29:78:13:33:33:c3:17:7d:a6:d3: + 45:1c:25:cf:dd:4b:4e:9e:19:62:86:6b:f8:6b:40:ec:96:09: + 0f:6a:a5:2c:79:3b:1d:b5:87:78:f2:6c:31:1d:01:1e:1e:c1: + 29:14:fe:85:e2:0f:bc:4c:bb:2d:93:be:41:b3:46:4f:ea:a4: + 9d:35:bb:f4:fc:0c:9b:c4:ae:1d:94:76:7c:cc:7c:22:13:2c: + 87:cf:ea:89:3f:de:c1:26:02:6f:68:58:47:df:94:e7:7e:56: + a8:9c:5e:99:15:d4:c2:d3:2e:a8:9f:d5:61:1c:7d:46:a7:57: + 70:58:31:b7:aa:60:ae:5c:1d:4a:07:54:02:77:a7:f9:a8:b2: + 8a:ca:6a:14:bf:83:e1:2f:e5:28:bf:d7:de:e7:fb:47:bc:f2: + 84:78:11:f9:41:bf:33:d6:c8:17:1a:da:ff:eb:fd:32:75:cd: + 08:47:78:0c:26:16:2e:dc:75:db:e8:44:f8:10:87:b1:94:16: + eb:c3:29:3d:fb:ae:46:5e:9a:42:4d:40:03:c1:58:50:67:ff: + e6:77:9c:9a -----BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgIJAM0A0i67xaZdMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG -A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y -MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ -MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM -D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv -bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn -AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX -/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj -xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 -ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj -laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP -rdcCAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUA -A4IBAQBemm3qWG2pbvrHuxZ9XcuXVMtP6DiV4hts6q1Ly+pYV/cuBclXm/HMA8Ep -fBMWj3jSwOoYr/gdz/QlbDPN2JsoIcTd8N8QcxDtLjDBUxVQH/n41tsUZq2mp3h+ -oUZQ9c8HIecz5CXYGNIfynzWRdHbLzSuYbEaBU7OurdIX7cNngHwXv3xMGANWW4b -2bcpFTHYvtwvI/UTTkTrLQ5Snn49famgr4gKFYzLEdwktGuvO6XkglcT0cokdbBT -v7jscYGjhKm3/rsxG4mUvpEW3WcbZht5gRk8HSke4Nw/C24N5QsKQyj5add6VSzj -ey+3ZjTtKfXFbQlR2ABpVzQ0JvO3 +MIIDrDCCApSgAwIBAgIUIg+VbE0pqOuoSPkW4PefUiw9jHQwDQYJKoZIhvcNAQEL +BQAwgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEYMBYGA1UEAwwPd3d3Lm5vbWF0 +Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYx +NTIyMDIzM1oXDTI0MDMxMTIyMDIzM1owgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd3d3Lm5vbWF0Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI +4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUv +j+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+t +Q7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem +8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDB +Y3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE +4eZhg8XSlt/Z0E+t1wIDAQABoxgwFjAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJ +KoZIhvcNAQELBQADggEBALNWHmwAdBB0AeZEj2Hz28tXOukg1wmthSkf3W4smCF7 +RlEQVjgQm3ut9IxsKXgTMzPDF32m00UcJc/dS06eGWKGa/hrQOyWCQ9qpSx5Ox21 +h3jybDEdAR4ewSkU/oXiD7xMuy2TvkGzRk/qpJ01u/T8DJvErh2UdnzMfCITLIfP +6ok/3sEmAm9oWEfflOd+VqicXpkV1MLTLqif1WEcfUanV3BYMbeqYK5cHUoHVAJ3 +p/mosorKahS/g+Ev5Si/197n+0e88oR4EflBvzPWyBca2v/r/TJ1zQhHeAwmFi7c +ddvoRPgQh7GUFuvDKT37rkZemkJNQAPBWFBn/+Z3nJo= -----END CERTIFICATE----- diff --git a/certs/test/server-goodaltwild.der b/certs/test/server-goodaltwild.der old mode 100644 new mode 100755 index 6ec2b54d7..67fa3a9c8 Binary files a/certs/test/server-goodaltwild.der and b/certs/test/server-goodaltwild.der differ diff --git a/certs/test/server-goodaltwild.pem b/certs/test/server-goodaltwild.pem old mode 100644 new mode 100755 index a16fbf280..dd2620d0e --- a/certs/test/server-goodaltwild.pem +++ b/certs/test/server-goodaltwild.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 81:aa:d6:88:40:5c:21:41 - Signature Algorithm: sha256WithRSAEncryption + 51:c8:76:f6:e4:03:7b:88:d2:98:fb:66:35:aa:83:d3:f3:c7:c4:01 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -36,40 +36,40 @@ Certificate: X509v3 Subject Alternative Name: DNS:*localhost Signature Algorithm: sha256WithRSAEncryption - 79:9c:b3:8c:52:fe:d2:38:36:4c:70:80:ee:36:db:cc:68:5f: - a3:fb:c5:3e:a3:77:18:80:e9:88:69:da:39:69:bc:40:8b:2c: - 5c:c3:d0:4c:8b:17:05:12:a9:f1:d5:b7:9a:6a:6d:f7:19:09: - 20:22:dc:7f:11:b2:4e:df:7d:a2:1a:4d:fd:86:b9:bc:ee:e0: - a0:94:47:fd:4d:5c:45:4c:47:a7:d8:95:22:1b:2c:be:88:b0: - a1:94:15:31:34:bd:3a:01:3f:eb:67:ce:80:c0:1f:d5:9d:0e: - be:9f:90:a1:15:45:ed:0f:27:50:6e:52:6c:2b:81:22:00:99: - 2c:71:2d:86:e2:58:87:73:4c:3d:6b:50:14:7b:96:54:6f:e5: - 19:69:01:3d:d8:dd:2e:30:e3:e1:15:35:a6:8d:5b:50:32:98: - 32:76:fe:19:28:ff:50:e2:c4:5e:e7:b7:60:ad:7a:f2:9f:62: - 4b:c8:22:d3:0f:e0:4a:48:5e:d5:c9:75:41:d5:ce:c2:4a:a2: - 5f:d2:75:a3:d3:d6:95:f2:be:e0:5e:da:87:2c:02:70:99:49: - 87:bc:0e:8b:92:73:fc:05:7d:18:b8:ed:96:b2:11:5c:83:8f: - da:92:45:10:60:e3:db:c1:5f:94:b1:4c:82:d6:db:7a:05:b1: - 8f:78:74:35 + bd:57:16:44:c4:39:a1:e6:12:50:8b:f9:2f:53:74:92:b6:42: + 6c:34:2d:9e:82:7b:f3:e5:c5:9b:93:a7:26:a2:3b:2c:eb:99: + cf:f0:2e:af:de:ac:8a:a7:0c:a5:d6:fb:0c:65:be:4c:ea:39: + 7d:60:4a:d3:1e:fb:48:0d:4c:90:12:1d:41:96:f5:80:be:52: + e3:57:23:5a:4d:4d:03:6c:82:7c:75:0e:8a:ec:2c:ee:f3:05: + 80:84:7a:58:a2:d6:58:05:31:27:ae:8f:6b:52:c3:93:eb:66: + 23:0b:15:d0:5f:cc:fd:ca:af:f9:94:6b:4d:0d:05:6b:65:22: + 35:d2:0c:ed:bf:82:02:52:bf:28:08:b4:6e:7e:7f:9e:eb:37: + 93:89:b8:1d:4a:17:eb:f7:e3:8c:1f:6f:8a:00:6c:85:57:c3: + 17:86:94:d4:50:fd:a1:74:01:41:92:cc:16:52:5a:8e:fc:30: + 2e:fd:13:3f:0a:a6:fc:89:e1:4c:83:30:b7:82:76:7a:ee:c4: + 57:77:e6:2f:75:27:b8:28:76:f4:9f:db:13:4b:de:9c:6c:ce: + b7:d9:39:7c:2a:f9:52:59:e2:ba:10:33:86:73:f6:a8:52:f2: + 58:0c:bd:11:e5:fd:b1:3d:ab:10:33:a1:56:84:5e:af:ad:23: + 44:99:30:19 -----BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIJAIGq1ohAXCFBMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG -A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y -MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ -MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM -D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv -bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn -AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX -/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj -xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 -ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj -laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP -rdcCAwEAAaMZMBcwFQYDVR0RBA4wDIIKKmxvY2FsaG9zdDANBgkqhkiG9w0BAQsF -AAOCAQEAeZyzjFL+0jg2THCA7jbbzGhfo/vFPqN3GIDpiGnaOWm8QIssXMPQTIsX -BRKp8dW3mmpt9xkJICLcfxGyTt99ohpN/Ya5vO7goJRH/U1cRUxHp9iVIhssvoiw -oZQVMTS9OgE/62fOgMAf1Z0Ovp+QoRVF7Q8nUG5SbCuBIgCZLHEthuJYh3NMPWtQ -FHuWVG/lGWkBPdjdLjDj4RU1po1bUDKYMnb+GSj/UOLEXue3YK168p9iS8gi0w/g -Skhe1cl1QdXOwkqiX9J1o9PWlfK+4F7ahywCcJlJh7wOi5Jz/AV9GLjtlrIRXIOP -2pJFEGDj28FflLFMgtbbegWxj3h0NQ== +MIIDrTCCApWgAwIBAgIUUch29uQDe4jSmPtmNaqD0/PHxAEwDQYJKoZIhvcNAQEL +BQAwgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEYMBYGA1UEAwwPd3d3Lm5vbWF0 +Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYx +NTIyMDIzM1oXDTI0MDMxMTIyMDIzM1owgYIxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd3d3Lm5vbWF0Y2guY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI +4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUv +j+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+t +Q7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem +8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDB +Y3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE +4eZhg8XSlt/Z0E+t1wIDAQABoxkwFzAVBgNVHREEDjAMggoqbG9jYWxob3N0MA0G +CSqGSIb3DQEBCwUAA4IBAQC9VxZExDmh5hJQi/kvU3SStkJsNC2egnvz5cWbk6cm +ojss65nP8C6v3qyKpwyl1vsMZb5M6jl9YErTHvtIDUyQEh1BlvWAvlLjVyNaTU0D +bIJ8dQ6K7Czu8wWAhHpYotZYBTEnro9rUsOT62YjCxXQX8z9yq/5lGtNDQVrZSI1 +0gztv4ICUr8oCLRufn+e6zeTibgdShfr9+OMH2+KAGyFV8MXhpTUUP2hdAFBkswW +UlqO/DAu/RM/Cqb8ieFMgzC3gnZ67sRXd+YvdSe4KHb0n9sTS96cbM632Tl8KvlS +WeK6EDOGc/aoUvJYDL0R5f2xPasQM6FWhF6vrSNEmTAZ -----END CERTIFICATE----- diff --git a/certs/test/server-goodcn.der b/certs/test/server-goodcn.der old mode 100644 new mode 100755 index d8dffb33a..87bb4e792 Binary files a/certs/test/server-goodcn.der and b/certs/test/server-goodcn.der differ diff --git a/certs/test/server-goodcn.pem b/certs/test/server-goodcn.pem old mode 100644 new mode 100755 index ec7a6a4f1..e7beeae77 --- a/certs/test/server-goodcn.pem +++ b/certs/test/server-goodcn.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - c2:e8:97:dd:c7:fe:a9:d4 - Signature Algorithm: sha256WithRSAEncryption + 71:8f:a1:ae:aa:b4:f3:7c:c3:2c:f9:3a:31:06:28:a3:78:f4:fe:1c + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -33,39 +33,39 @@ Certificate: ad:d7 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption - 26:28:b4:09:65:22:8f:32:5d:58:8c:40:ff:6f:7e:66:bf:6f: - b5:69:4e:ee:ad:4e:f2:63:69:b1:79:21:4e:b4:76:84:06:90: - e6:6e:a7:56:45:96:03:90:8c:88:32:92:ff:90:d9:b3:d0:28: - d2:7c:34:f6:76:3a:cc:71:fa:fb:28:d1:29:8d:8b:73:ae:d7: - 7c:eb:63:34:01:80:58:3e:f0:d7:5b:17:4b:da:ae:5f:75:d1: - 92:41:05:d3:c0:1a:a2:c7:b8:ac:d8:70:08:fa:d5:d5:4e:17: - 18:ef:06:04:aa:9e:15:b8:e8:05:db:51:63:2d:95:c3:af:6a: - 54:65:84:cf:a0:7e:34:44:37:fc:5b:34:5e:2a:c9:a7:9c:a0: - f1:c5:89:32:f1:71:df:91:b1:28:e8:e8:15:42:3b:0b:44:8e: - dd:2d:83:6b:77:46:18:80:6e:a2:2b:2f:c7:e4:e7:fe:b1:3c: - b4:3d:71:ba:9b:dc:85:4a:ba:87:c3:ad:15:10:e2:0a:ad:c3: - db:e8:49:21:87:b8:05:f0:a2:29:5d:91:45:dd:73:53:10:94: - 8a:4f:1a:e2:c3:87:7b:26:4b:bc:b0:e2:5d:7c:af:06:8f:54: - 94:3a:5d:ef:8d:34:d4:09:50:ab:5e:9b:3b:12:51:b3:18:1f: - 35:b7:8d:49 + 94:fb:ed:5e:58:16:79:bd:08:1c:6c:04:eb:00:59:b2:f8:2f: + cf:8f:d3:22:80:4c:df:ad:6d:ef:42:0a:f7:70:ce:4a:2f:9a: + 69:33:05:de:1f:0e:f5:55:a5:55:de:e0:da:82:28:da:bc:b5: + 8f:22:d9:fe:bf:5d:37:6c:a0:13:1b:f0:94:ff:ee:90:2a:6c: + 9c:bc:ff:7b:cd:85:65:59:f1:08:8e:fc:10:f3:38:8b:7e:37: + b0:82:71:24:0f:b9:02:94:61:21:d1:cd:7e:a3:ba:e9:59:80: + 32:ac:42:f3:81:92:22:ac:bf:6c:3f:be:5b:c3:72:30:cc:89: + f8:34:0c:fb:cd:28:94:3d:8c:c5:2b:64:77:73:94:6f:4e:bb: + ce:ab:68:77:70:b0:6d:88:5f:3c:9f:dd:8e:94:44:02:87:8c: + 33:64:44:a6:a5:b2:d0:5e:d6:cf:1b:92:7b:de:7d:97:6f:4a: + cd:d1:d2:75:86:1d:85:d1:24:7d:33:e0:58:8f:d8:0f:cf:b3: + 2b:22:00:25:d8:7d:e5:94:19:b6:33:c5:c0:89:a5:d2:b9:3b: + 27:3f:57:f9:1b:9e:40:16:2a:d1:9e:3b:ed:61:53:9a:38:58: + bf:0c:68:ce:e5:f8:4d:a3:fa:98:1b:81:74:7d:ae:5d:c3:11: + f8:55:2d:11 -----BEGIN CERTIFICATE----- -MIIDeTCCAmGgAwIBAgIJAMLol93H/qnUMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD -VQQLDAtFbmdpbmVlcmluZzESMBAGA1UEAwwJbG9jYWxob3N0MR8wHQYJKoZIhvcN -AQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIx -MjEyNFowfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcM -B0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhv -c3QxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFlxkWu8rwkMLiVzi9O -1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2SoF/zKXXu64CHlci5vLobY -lXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2fwtZaHhzpowYqQJt -r8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZRDL1Us+FtXxy8I3PR -CQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Whd7oT0pdz4l0lyWoN -wzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63XAgMBAAEwDQYJKoZI -hvcNAQELBQADggEBACYotAllIo8yXViMQP9vfma/b7VpTu6tTvJjabF5IU60doQG -kOZup1ZFlgOQjIgykv+Q2bPQKNJ8NPZ2Osxx+vso0SmNi3Ou13zrYzQBgFg+8Ndb -F0varl910ZJBBdPAGqLHuKzYcAj61dVOFxjvBgSqnhW46AXbUWMtlcOvalRlhM+g -fjREN/xbNF4qyaecoPHFiTLxcd+RsSjo6BVCOwtEjt0tg2t3RhiAbqIrL8fk5/6x -PLQ9cbqb3IVKuofDrRUQ4gqtw9voSSGHuAXwoildkUXdc1MQlIpPGuLDh3smS7yw -4l18rwaPVJQ6Xe+NNNQJUKtemzsSUbMYHzW3jUk= +MIIDhDCCAmygAwIBAgIUcY+hrqq083zDLPk6MQYoo3j0/hwwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhvc3Qx +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjEwNjE1MjIwMjMz +WhcNMjQwMzExMjIwMjMzWjB8MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFu +YTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxEjAQBgNV +BAMMCWxvY2FsaG9zdDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXG +Ra7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpd +e7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/ +C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEM +vVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3 +uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcC +AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAlPvtXlgWeb0IHGwE6wBZsvgvz4/TIoBM +361t70IK93DOSi+aaTMF3h8O9VWlVd7g2oIo2ry1jyLZ/r9dN2ygExvwlP/ukCps +nLz/e82FZVnxCI78EPM4i343sIJxJA+5ApRhIdHNfqO66VmAMqxC84GSIqy/bD++ +W8NyMMyJ+DQM+80olD2MxStkd3OUb067zqtod3CwbYhfPJ/djpREAoeMM2REpqWy +0F7WzxuSe959l29KzdHSdYYdhdEkfTPgWI/YD8+zKyIAJdh95ZQZtjPFwIml0rk7 +Jz9X+RueQBYq0Z477WFTmjhYvwxozuX4TaP6mBuBdH2uXcMR+FUtEQ== -----END CERTIFICATE----- diff --git a/certs/test/server-goodcnwild.der b/certs/test/server-goodcnwild.der old mode 100644 new mode 100755 index 3ab2636d5..70248b786 Binary files a/certs/test/server-goodcnwild.der and b/certs/test/server-goodcnwild.der differ diff --git a/certs/test/server-goodcnwild.pem b/certs/test/server-goodcnwild.pem old mode 100644 new mode 100755 index 3971fc78b..8f5821d6d --- a/certs/test/server-goodcnwild.pem +++ b/certs/test/server-goodcnwild.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - e7:ad:a9:3a:44:c1:7e:48 - Signature Algorithm: sha256WithRSAEncryption + 54:28:61:98:f6:94:1e:cd:01:47:65:7a:64:cd:f6:1e:37:0a:e4:f3 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = *localhost, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:33 2021 GMT + Not After : Mar 11 22:02:33 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = *localhost, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -33,39 +33,39 @@ Certificate: ad:d7 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption - a5:03:1d:6f:49:00:29:c5:92:14:8f:3b:8f:aa:e9:1f:b6:fd: - f1:32:5a:1a:dd:4b:36:f5:83:1f:45:e0:aa:95:6c:6f:b9:fd: - f9:04:10:df:73:fc:e2:e5:15:4c:04:51:95:74:77:d0:d5:d3: - 13:b9:16:1a:db:02:9f:61:c5:71:d0:41:80:f3:1d:bd:f6:0f: - 30:5a:cc:bf:e0:b7:22:7a:2f:51:46:20:d9:f3:c6:ea:0a:0b: - 23:69:a1:b9:96:3b:7d:af:bd:f0:1a:b2:b3:05:4a:fd:b2:71: - 3e:e7:24:8a:57:69:17:0c:18:3a:3a:84:a1:28:37:45:7b:8f: - c7:c6:28:5f:3f:c2:8d:51:2c:0b:77:61:c3:78:a2:c0:1f:0b: - 0f:23:5a:a9:1d:e6:2b:67:9a:0e:fa:f9:d7:de:73:53:e9:96: - b0:e6:5a:ef:3f:21:58:86:a4:df:9a:17:db:39:04:9f:04:42: - ec:b4:de:24:59:99:fc:cd:df:f0:be:44:f4:76:fe:c4:5a:05: - ae:a5:f5:51:7f:50:2c:57:c7:95:b8:e1:ad:8a:27:39:ce:fa: - 68:17:d0:bf:73:66:5b:06:2d:fb:c0:7e:35:bc:a5:70:ec:8d: - aa:45:f5:fe:30:2f:e3:a1:9f:75:f6:d1:46:14:c5:36:52:59: - 49:68:2f:3e + 56:75:ba:9c:6f:c1:b8:3a:4b:a9:11:53:19:78:a8:92:8d:69: + b1:30:d8:54:70:dc:db:c8:e2:87:66:f0:a3:82:8c:c7:8a:1a: + 7b:7b:c7:07:25:ad:ed:7b:7d:21:9b:32:64:54:6b:37:70:ce: + fa:f9:86:dc:44:a9:3b:47:4b:90:e6:91:67:29:a1:80:85:74: + 5c:80:8b:27:87:84:7d:eb:af:96:0a:a5:3d:88:aa:db:0a:8c: + ec:6f:4f:bc:ab:f3:8e:bf:13:03:b0:25:87:e4:da:81:ef:06: + 4c:dd:bf:d4:8b:96:a4:a4:cd:ce:1e:17:98:ac:ed:44:92:82: + 48:0e:67:c2:8f:2f:cb:3e:e8:cd:9b:80:1c:5a:ed:83:51:be: + 78:ec:ab:e7:e8:f1:4c:af:50:aa:5b:47:68:31:21:de:88:32: + af:cb:74:d4:ba:86:bb:db:5a:78:1e:27:4b:b8:16:53:83:20: + 84:a4:df:67:68:c0:a1:ab:59:3c:14:8b:3c:f5:37:41:60:d8: + 7c:bf:bf:fe:d1:72:d2:a5:0b:f5:fc:97:ce:c4:c4:d9:ce:6f: + cb:ee:27:7c:a0:9a:d0:ae:0d:a6:85:3e:ed:a6:3e:90:09:c7: + 5e:df:e9:89:fb:44:dc:64:a9:c1:1b:ef:d7:1f:98:c1:28:0b: + f5:33:d3:25 -----BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIJAOetqTpEwX5IMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD -VQQLDAtFbmdpbmVlcmluZzETMBEGA1UEAwwKKmxvY2FsaG9zdDEfMB0GCSqGSIb3 -DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0yMTA2MTUy -MTIxMjRaMH0xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQH -DAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzETMBEGA1UEAwwKKmxvY2Fs -aG9zdDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXO -L07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8u -htiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBip -Am2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwj -c9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJ -ag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAATANBgkq -hkiG9w0BAQsFAAOCAQEApQMdb0kAKcWSFI87j6rpH7b98TJaGt1LNvWDH0XgqpVs -b7n9+QQQ33P84uUVTARRlXR30NXTE7kWGtsCn2HFcdBBgPMdvfYPMFrMv+C3Inov -UUYg2fPG6goLI2mhuZY7fa+98BqyswVK/bJxPuckildpFwwYOjqEoSg3RXuPx8Yo -Xz/CjVEsC3dhw3iiwB8LDyNaqR3mK2eaDvr5195zU+mWsOZa7z8hWIak35oX2zkE -nwRC7LTeJFmZ/M3f8L5E9Hb+xFoFrqX1UX9QLFfHlbjhrYonOc76aBfQv3NmWwYt -+8B+NbylcOyNqkX1/jAv46GfdfbRRhTFNlJZSWgvPg== +MIIDhjCCAm6gAwIBAgIUVChhmPaUHs0BR2V6ZM32HjcK5PMwDQYJKoZIhvcNAQEL +BQAwfTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRMwEQYDVQQDDAoqbG9jYWxob3N0 +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIxMDYxNTIyMDIz +M1oXDTI0MDMxMTIyMDIzM1owfTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh +bmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRMwEQYD +VQQDDAoqbG9jYWxob3N0MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScB +ZcZFrvK8JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8 +yl17uuAh5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF +9n8LWWh4c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1m +UQy9VLPhbV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOV +oXe6E9KXc+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t +1wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBWdbqcb8G4OkupEVMZeKiSjWmxMNhU +cNzbyOKHZvCjgozHihp7e8cHJa3te30hmzJkVGs3cM76+YbcRKk7R0uQ5pFnKaGA +hXRcgIsnh4R966+WCqU9iKrbCozsb0+8q/OOvxMDsCWH5NqB7wZM3b/Ui5akpM3O +HheYrO1EkoJIDmfCjy/LPujNm4AcWu2DUb547Kvn6PFMr1CqW0doMSHeiDKvy3TU +uoa721p4HidLuBZTgyCEpN9naMChq1k8FIs89TdBYNh8v7/+0XLSpQv1/JfOxMTZ +zm/L7id8oJrQrg2mhT7tpj6QCcde3+mJ+0TcZKnBG+/XH5jBKAv1M9Ml -----END CERTIFICATE----- diff --git a/certs/test/server-localhost.der b/certs/test/server-localhost.der old mode 100644 new mode 100755 index 77eb5ac8b..e7e28d6de Binary files a/certs/test/server-localhost.der and b/certs/test/server-localhost.der differ diff --git a/certs/test/server-localhost.pem b/certs/test/server-localhost.pem old mode 100644 new mode 100755 index c34c9e0fd..ae0f7da90 --- a/certs/test/server-localhost.pem +++ b/certs/test/server-localhost.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d9:6c:d7:cc:f4:9f:c5:18 - Signature Algorithm: sha256WithRSAEncryption + 5f:cb:7b:57:73:63:6d:62:69:9f:72:e0:66:15:00:27:fa:b6:b6:b6 + Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com Validity - Not Before: Sep 19 21:21:24 2018 GMT - Not After : Jun 15 21:21:24 2021 GMT + Not Before: Jun 15 22:02:34 2021 GMT + Not After : Mar 11 22:02:34 2024 GMT Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: @@ -36,40 +36,40 @@ Certificate: X509v3 Subject Alternative Name: DNS:localhost Signature Algorithm: sha256WithRSAEncryption - 3a:16:c1:b1:05:65:32:fc:65:4b:09:5a:05:4a:c0:9c:ec:07: - f5:f0:01:41:7c:cf:20:c7:55:80:81:6a:df:65:f2:44:37:02: - b0:8f:7b:7b:0a:3d:a3:44:0f:e4:73:55:ee:cc:3a:d5:b0:8f: - 62:a5:65:73:dd:6c:b2:11:2a:76:3c:94:3a:8b:ea:32:a0:ea: - 41:05:a5:78:af:27:d2:9e:e9:b9:c3:9d:11:2a:3e:d3:d5:bf: - 72:46:b6:7b:8d:5f:6a:b9:25:78:c7:60:1a:60:5d:26:d6:45: - 06:b7:4d:b0:a1:20:bb:62:94:64:92:98:f6:a7:62:3d:06:70: - d5:7e:51:72:92:3e:97:81:20:d3:8a:fe:43:7b:a2:c6:4f:89: - a0:c5:e6:c5:a8:a4:e3:4c:a2:dc:52:de:61:fe:99:7e:c4:f3: - 2e:f0:81:c3:34:07:d6:2b:b5:cf:21:a3:8a:71:82:de:28:57: - 20:a0:1c:08:d8:c0:1f:d5:ec:48:d6:04:dd:72:df:9d:90:73: - c7:90:56:ec:71:cb:fa:ff:57:5c:74:6f:97:2e:f8:86:6c:28: - 9a:0e:69:b9:ec:f4:6f:8f:d5:c2:4b:94:57:ec:74:ed:f0:bf: - 9b:c2:ae:0e:0f:10:10:5f:9e:a3:c1:39:03:d2:a6:90:50:a3: - df:3e:56:dd + 40:4f:9f:fa:37:67:e7:64:8a:6a:0b:fd:68:ab:39:09:96:ae: + 98:b8:9a:16:ab:30:84:ba:6a:89:0f:e5:fd:d1:a0:3f:f5:8f: + b8:13:2f:4c:1c:a1:a6:8d:59:f0:ab:61:f2:c8:af:0b:e2:fc: + b5:14:17:f9:a5:b6:ba:ad:d8:70:01:0b:9a:d4:3e:c2:04:06: + 65:f1:25:4f:de:36:ef:52:3e:a9:27:77:5d:89:5d:7a:7b:ef: + 3d:28:ad:0f:2e:6e:74:4f:67:41:7c:37:17:c9:8a:71:05:10: + 66:11:b0:f6:15:b5:59:0f:29:dc:0c:93:cc:bd:3c:6d:93:40: + 28:a4:59:de:7b:f4:f5:31:1c:0b:b1:db:c8:39:00:70:39:3a: + 3b:31:fc:de:02:e2:00:1e:e1:35:cf:8a:ca:0b:15:ae:ac:63: + 92:d2:33:77:54:0e:56:6f:b7:1b:84:f9:e5:fc:4e:2e:db:26: + 5f:bd:51:a0:bb:d7:23:0b:8f:d7:24:4d:ab:df:74:46:fe:9f: + 17:55:23:0d:a7:9a:ea:56:d7:a7:a9:cd:3e:18:60:14:d2:fd: + 9a:b7:61:4c:0b:6f:60:ac:9c:e9:81:db:e1:13:4f:4b:80:43: + 57:c1:05:86:a6:23:6e:b7:61:ed:76:58:d3:65:dc:6b:eb:92: + ac:35:fa:0a -----BEGIN CERTIFICATE----- -MIIDkzCCAnugAwIBAgIJANls18z0n8UYMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD -VQQLDAtFbmdpbmVlcmluZzESMBAGA1UEAwwJbG9jYWxob3N0MR8wHQYJKoZIhvcN -AQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIx -MjEyNFowfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcM -B0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhv -c3QxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFlxkWu8rwkMLiVzi9O -1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2SoF/zKXXu64CHlci5vLobY -lXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2fwtZaHhzpowYqQJt -r8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZRDL1Us+FtXxy8I3PR -CQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Whd7oT0pdz4l0lyWoN -wzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63XAgMBAAGjGDAWMBQG -A1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAOhbBsQVlMvxl -SwlaBUrAnOwH9fABQXzPIMdVgIFq32XyRDcCsI97ewo9o0QP5HNV7sw61bCPYqVl -c91sshEqdjyUOovqMqDqQQWleK8n0p7pucOdESo+09W/cka2e41farkleMdgGmBd -JtZFBrdNsKEgu2KUZJKY9qdiPQZw1X5RcpI+l4Eg04r+Q3uixk+JoMXmxaik40yi -3FLeYf6ZfsTzLvCBwzQH1iu1zyGjinGC3ihXIKAcCNjAH9XsSNYE3XLfnZBzx5BW -7HHL+v9XXHRvly74hmwomg5puez0b4/VwkuUV+x07fC/m8KuDg8QEF+eo8E5A9Km -kFCj3z5W3Q== +MIIDnjCCAoagAwIBAgIUX8t7V3NjbWJpn3LgZhUAJ/q2trYwDQYJKoZIhvcNAQEL +BQAwfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhvc3Qx +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjEwNjE1MjIwMjM0 +WhcNMjQwMzExMjIwMjM0WjB8MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFu +YTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxEjAQBgNV +BAMMCWxvY2FsaG9zdDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXG +Ra7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpd +e7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/ +C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEM +vVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3 +uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcC +AwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IB +AQBAT5/6N2fnZIpqC/1oqzkJlq6YuJoWqzCEumqJD+X90aA/9Y+4Ey9MHKGmjVnw +q2HyyK8L4vy1FBf5pba6rdhwAQua1D7CBAZl8SVP3jbvUj6pJ3ddiV16e+89KK0P +Lm50T2dBfDcXyYpxBRBmEbD2FbVZDyncDJPMvTxtk0AopFnee/T1MRwLsdvIOQBw +OTo7MfzeAuIAHuE1z4rKCxWurGOS0jN3VA5Wb7cbhPnl/E4u2yZfvVGgu9cjC4/X +JE2r33RG/p8XVSMNp5rqVtenqc0+GGAU0v2at2FMC29grJzpgdvhE09LgENXwQWG +piNut2HtdljTZdxr65KsNfoK -----END CERTIFICATE----- diff --git a/certs/test/smime-test-canon.p7s b/certs/test/smime-test-canon.p7s new file mode 100644 index 000000000..d95207fb2 --- /dev/null +++ b/certs/test/smime-test-canon.p7s @@ -0,0 +1,63 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----7DB22CE8F405BFCE81603E2CD3794291" + +This is an S/MIME signed message + +------7DB22CE8F405BFCE81603E2CD3794291 +Content-Type: text/plain + +This text/plain content has been signed with canonicalized CRLF line endings, +but it is added to the multipart message with non canonicalized line endings. + +In order to match the hash, it will need to be canonicalized first. +------7DB22CE8F405BFCE81603E2CD3794291 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIH3gYJKoZIhvcNAQcCoIIHzzCCB8sCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggTtMIIE6TCCA9GgAwIBAgIJAKrTP6wYCjdNMA0GCSqGSIb3DQEB +CwUAMIGUMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH +Qm96ZW1hbjERMA8GA1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcx +GDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbTAeFw0yMTAyMTAxOTQ5NTJaFw0yMzExMDcxOTQ5NTJaMIGUMQsw +CQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjER +MA8GA1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMM +D3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL8Myi0Ush6EQlvNOB9K +8k11EPG2NZ/fyn0DmNOs3gNm7irx2LB9bgdUCxCYIU2AyxIg58xP3kV9yXJ3MurK +kLtpUhADL6jzlcXxi2JWG+9nb6QQQZWtCpvjpcCw0nB2UDBbqOgILHztp6J6jTgp +HKzH7fJ8lbCVgn1JXDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX +2kBv2CHccxtCLVOc/hr8fat6Nj+Y3oR8BWfOahQ4h6nxjLVoy2h/cSAr9aBj9VYv +oybSt2+xWhfXOJkI/pNYb/7DE0kIFgunTWcAUjFnI06Y7VFFHbkE2Qvs2CizS73t +NnkCAwEAAaOCATowggE2MB0GA1UdDgQWBBQnjmcRdMMmHT/tM2OzpNgdMOXo1TCB +yQYDVR0jBIHBMIG+gBQnjmcRdMMmHT/tM2OzpNgdMOXo1aGBmqSBlzCBlDELMAkG +A1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAP +BgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93 +d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22C +CQCq0z+sGAo3TTAMBgNVHRMEBTADAQH/MBwGA1UdEQQVMBOCC2V4YW1wbGUuY29t +hwR/AAABMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B +AQsFAAOCAQEAYpjIWM9WA4ZbG3FJfQUDXeAIhq3bSt6rIpaow1lowTeQQN+9idC8 +2o7vh7LCYlLhGikXapaZyE7YMv640Vw7CsI8X6EemH/OiSYhH2ScFXqc7/sdhWr6 +mM6oqavDosDrh+28Id/zB1uu/UDUriDQdooxCqJifGENzl2aHuQgiFFJ+3epzU3G +v1SZM+9LoHNwbS7ZPQj2EjkxaMZhXEG1G/Q4ffy+c2Yt98pbLFsxqs/2fzDkEiyO +1jhR5kXu1drDg9btXuzWthSzk1nhVUp/BN/OZdTfGE/dtEV/plYwxAVEmJ1PJm2E +gKBe7SPRSIcOBQaRO7A8u4yPPHtMT6HKmDGCArUwggKxAgEBMIGiMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbQIJ +AKrTP6wYCjdNMA0GCWCGSAFlAwQCAQUAoIHkMBgGCSqGSIb3DQEJAzELBgkqhkiG +9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIxMDQzMDIyMDIxNVowLwYJKoZIhvcNAQkE +MSIEIK/ck17trnj+dm7BHjYDU6Vr84PBHws8jt5J5kmOBzeFMHkGCSqGSIb3DQEJ +DzFsMGowCwYJYIZIAWUDBAEqMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAIpnnr7ts2RcUhyYH0g8 +H55w+mgaX+BEZ6dPbR0Db3VIwueDXhsyyp+JQtfRo4DUPgHQtGKFFk5PsAnv122l +dMEdEx90hwtzdM1GAg/8PIMJnsKFlz+Yc2F6WsTGdCKasCpr4Tz/UiiztdCi3eJn +UGGlChnuZgUS0LRRNfSmZGdnAjVdk8yammEUFclS09z+t9NT+2UIMHeZWfsMRSit +fHjnvzbMtxF32uRbZdALMV2b8nW56y6al+/lMvj0074l4VKmKuH3Vj/EnC2PQ9xl +EG9H2hS68U8ZxPtUELh4fEUy52nubfohCpBd0CFSe7BM3CKYid+fFLQmNc5POCla +7RM= + +------7DB22CE8F405BFCE81603E2CD3794291-- + diff --git a/cmake/functions.cmake b/cmake/functions.cmake index abb0e5a2b..1869c50c1 100644 --- a/cmake/functions.cmake +++ b/cmake/functions.cmake @@ -1,3 +1,22 @@ +function(add_option NAME HELP_STRING DEFAULT VALUES) + list(FIND VALUES ${DEFAULT} IDX) + if (${IDX} EQUAL -1) + message(FATAL_ERROR "Failed to add option ${NAME}. Default value " + "${DEFAULT} is not in list of possible values: ${VALUES}.") + endif() + + if(DEFINED ${NAME}) + list(FIND VALUES ${${NAME}} IDX) + if (${IDX} EQUAL -1) + message(FATAL_ERROR "Failed to set option ${NAME}. Value " + "${${NAME}} is not in list of possible values: ${VALUES}.") + endif() + endif() + + set(${NAME} ${DEFAULT} CACHE STRING ${HELP_STRING}) + set_property(CACHE ${NAME} PROPERTY STRINGS ${VALUES}) +endfunction() + function(override_cache VAR VAL) get_property(VAR_TYPE CACHE ${VAR} PROPERTY TYPE) set(${VAR} ${VAL} CACHE ${VAR_TYPE} ${${VAR}_HELP_STRING} FORCE) diff --git a/configure.ac b/configure.ac index dd8a6ac74..1509bf658 100644 --- a/configure.ac +++ b/configure.ac @@ -1,26 +1,94 @@ # configure.ac # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # # AC_COPYRIGHT([Copyright (C) 2006-2020 wolfSSL Inc.]) -AC_PREREQ([2.63]) -AC_INIT([wolfssl],[4.7.0],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[https://www.wolfssl.com]) +AC_PREREQ([2.69]) +AC_INIT([wolfssl],[4.7.1],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[https://www.wolfssl.com]) AC_CONFIG_AUX_DIR([build-aux]) # The following sets CFLAGS to empty if unset on command line. We do not # want the default "-g -O2" that AC_PROG_CC sets automatically. : ${CFLAGS=""} -# For reproducible builds, gate out from the build anything that might +# Capture user C_EXTRA_FLAGS from configure line. +# Use of C_EXTRA_FLAGS is deprecated because CFLAGS was fixed but someone +# might still be using it. +CFLAGS="$CFLAGS $C_EXTRA_FLAGS $C_FLAGS" + +AC_PROG_CC +AM_PROG_CC_C_O +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([1.14.1 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +AC_ARG_PROGRAM + +AC_CONFIG_HEADERS([config.h:config.in]) + +LT_PREREQ([2.4.2]) +LT_INIT([disable-static win32-dll]) + +#shared library versioning +WOLFSSL_LIBRARY_VERSION=28:1:4 +# | | | +# +------+ | +---+ +# | | | +# current:revision:age +# | | | +# | | +- increment if interfaces have been added +# | | set to zero if interfaces have been removed +# | | or changed +# | +- increment if source code has changed +# | set to zero if current is incremented +# +- increment if interfaces have been added, removed or changed +AC_SUBST([WOLFSSL_LIBRARY_VERSION]) + +gl_VISIBILITY +AS_IF([ test -n "$CFLAG_VISIBILITY" ], [ + AM_CFLAGS="$AM_CPPFLAGS $CFLAG_VISIBILITY" + ]) + + +# Moved these size of and type checks before the library checks. +# The library checks add the library to subsequent test compiles +# and in some rare cases, the networking check causes these sizeof +# checks to fail. +AC_CHECK_SIZEOF([long long]) +AC_CHECK_SIZEOF([long]) +AC_CHECK_SIZEOF([time_t]) +AC_CHECK_TYPES([__uint128_t]) + + +# Distro build feature subset (Debian, Ubuntu, etc.) +AC_ARG_ENABLE([distro], + [AS_HELP_STRING([--enable-distro],[Enable wolfSSL distro build (default: disabled)])], + [ ENABLED_DISTRO=$enableval ], + [ ENABLED_DISTRO=no ] + ) +if test "$ENABLED_DISTRO" = "yes" +then + enable_shared=yes + enable_static=yes + enable_all=yes + REPRODUCIBLE_BUILD_DEFAULT=yes +else + REPRODUCIBLE_BUILD_DEFAULT=no +fi + +# For reproducible build, gate out from the build anything that might # introduce semantically frivolous jitter, maximizing chance of # identical object files. AC_ARG_ENABLE([reproducible-build], - [AS_HELP_STRING([--enable-reproducible-builds],[Enable maximally reproducible build (default: disabled)])], + [AS_HELP_STRING([--enable-reproducible-build],[Enable maximally reproducible build (default: disabled)])], [ ENABLED_REPRODUCIBLE_BUILD=$enableval ], - [ ENABLED_REPRODUCIBLE_BUILD=no ] + [ ENABLED_REPRODUCIBLE_BUILD=$REPRODUCIBLE_BUILD_DEFAULT ] ) # Test ar for the "U" or "D" options. Should be checked before the libtool macros. @@ -39,55 +107,6 @@ else AS_CASE([$xxx_ranlib_flags],[*'Use actual symbol map timestamp'*],[: ${RANLIB="ranlib -U"}]) fi -AC_PROG_CC -AM_PROG_CC_C_O -AC_CANONICAL_HOST -AC_CONFIG_MACRO_DIR([m4]) - -AM_INIT_AUTOMAKE([1.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) -m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) - -AC_ARG_PROGRAM - -AC_CONFIG_HEADERS([config.h:config.in]) - -LT_PREREQ([2.2]) -LT_INIT([disable-static win32-dll]) - -#shared library versioning -WOLFSSL_LIBRARY_VERSION=28:0:4 -# | | | -# +------+ | +---+ -# | | | -# current:revision:age -# | | | -# | | +- increment if interfaces have been added -# | | set to zero if interfaces have been removed -# | | or changed -# | +- increment if source code has changed -# | set to zero if current is incremented -# +- increment if interfaces have been added, removed or changed -AC_SUBST([WOLFSSL_LIBRARY_VERSION]) - -# Capture user C_EXTRA_FLAGS from configure line. -# Use of C_EXTRA_FLAGS is deprecated because CFLAGS was fixed but someone -# might still be using it. -CFLAGS="$CFLAGS $C_EXTRA_FLAGS $C_FLAGS" - -gl_VISIBILITY -AS_IF([ test -n "$CFLAG_VISIBILITY" ], [ - AM_CFLAGS="$AM_CPPFLAGS $CFLAG_VISIBILITY" - ]) - - -# Moved these size of and type checks before the library checks. -# The library checks add the library to subsequent test compiles -# and in some rare cases, the networking check causes these sizeof -# checks to fail. -AC_CHECK_SIZEOF([long long]) -AC_CHECK_SIZEOF([long]) -AC_CHECK_SIZEOF([time_t]) -AC_CHECK_TYPES([__uint128_t]) AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stddef.h time.h sys/ioctl.h sys/socket.h sys/time.h errno.h]) AC_CHECK_LIB([network],[socket]) @@ -150,6 +169,9 @@ AX_DEBUG AS_IF([test "$ax_enable_debug" = "yes"], [AM_CFLAGS="$DEBUG_CFLAGS $AM_CFLAGS"], [AM_CFLAGS="$AM_CFLAGS -DNDEBUG"]) +AS_IF([test "$ax_enable_debug" = "yes"], + [AM_CCASFLAGS="$DEBUG_CFLAGS $AM_CCASFLAGS"], + [AM_CCASFLAGS="$AM_CCASFLAGS -DNDEBUG"]) # Start without certificates enabled and enable if a certificate algorithm is @@ -165,57 +187,45 @@ AC_ARG_ENABLE([fips], [ENABLED_FIPS="no"]) AS_CASE([$ENABLED_FIPS], - ["ready"],[ + [ready],[ ENABLED_FIPS="yes" FIPS_VERSION="v2" FIPS_READY="yes" ], - ["v2"],[ - # FIPS v2 - ENABLED_FIPS="yes" - FIPS_VERSION="v2" + [no],[ + FIPS_VERSION="none" + ENABLED_FIPS="no" ], - ["rand"],[ - # FIPS Rand + [rand|v1|v2],[ + FIPS_VERSION="$ENABLED_FIPS" ENABLED_FIPS="yes" - FIPS_VERSION="rand" ], - ["no"],[FIPS_VERSION="none"], + [yes], [ # FIPS v1 ENABLED_FIPS="yes" FIPS_VERSION="v1" + ], + [ + AC_MSG_ERROR([Invalid value for --enable-fips "$ENABLED_FIPS" (allowed: ready, rand, v1, v2)]) ]) -case "$FIPS_VERSION" in -none) if test -s wolfcrypt/src/fips.c || test -s ctaocrypt/src/fips.c; then - AC_MSG_ERROR([FIPS source tree is incompatible with non-FIPS build (requires --enable-fips)]) - fi - ;; -v1) if ! test -s ctaocrypt/src/fips.c; then - AC_MSG_ERROR([non-FIPS-v1 source tree is incompatible with --enable-fips=$enableval]) - fi - ;; -*) if ! test -s wolfcrypt/src/fips.c; then - AC_MSG_ERROR([non-FIPS source tree is incompatible with --enable-fips=$enableval]) - fi - ;; -esac - - -# Distro build feature subset (Debian, Ubuntu, etc.) -AC_ARG_ENABLE([distro], - [AS_HELP_STRING([--enable-distro],[Enable wolfSSL distro build (default: disabled)])], - [ ENABLED_DISTRO=$enableval ], - [ ENABLED_DISTRO=no ] - ) -if test "$ENABLED_DISTRO" = "yes" -then - enable_shared=yes - enable_static=yes - enable_all=yes -fi - +AS_CASE([$FIPS_VERSION], + [none], + [ + AS_IF([ test -s $srcdir/wolfcrypt/src/fips.c -o -s $srcdir/ctaocrypt/src/fips.c ], + [AC_MSG_ERROR([FIPS source tree is incompatible with non-FIPS build (requires --enable-fips)])]) + ], + [v1], + [ + AS_IF([ ! test -s $srcdir/ctaocrypt/src/fips.c], + [AC_MSG_ERROR([non-FIPS-v1 source tree is incompatible with --enable-fips=$enableval])]) + ], + [ + AS_IF([ ! test -s $srcdir/wolfcrypt/src/fips.c], + [AC_MSG_ERROR([non-FIPS source tree is incompatible with --enable-fips=$enableval])]) + ] +) # Linux Kernel Module AC_ARG_ENABLE([linuxkm], @@ -314,6 +324,11 @@ then AC_MSG_ERROR([cannot enable sp-math and sp-math-all simultaneously.]) fi +AC_ARG_ENABLE([sp-asm], + [AS_HELP_STRING([--enable-sp-asm],[Enable Single Precision assembly implementation (default: disabled)])], + [ ENABLED_SP_ASM=$enableval ], + [ ENABLED_SP_ASM=no ], + ) # ALL FEATURES AC_ARG_ENABLE([all], @@ -338,6 +353,7 @@ then test "$enable_aesctr" = "" && enable_aesctr=yes test "$enable_aesofb" = "" && enable_aesofb=yes test "$enable_aescfb" = "" && enable_aescfb=yes + test "$enable_aescbc_length_checks" = "" && enable_aescbc_length_checks=yes test "$enable_camellia" = "" && enable_camellia=yes test "$enable_ripemd" = "" && enable_ripemd=yes test "$enable_sha512" = "" && enable_sha512=yes @@ -383,6 +399,7 @@ then test "$enable_enckeys" = "" && enable_enckeys=yes test "$enable_hashflags" = "" && enable_hashflags=yes test "$enable_defaultdhparams" = "" && enable_defaultdhparams=yes + test "$enable_base64encode" = "" && enable_base64encode=yes test "$enable_arc4" = "" && enable_arc4=yes test "$enable_des3" = "" && enable_des3=yes test "$enable_nullcipher" = "" && enable_nullcipher=yes @@ -442,6 +459,12 @@ then test "$enable_pkcs7" = "" && enable_pkcs7=yes test "$enable_ed25519" = "" && enable_ed25519=yes test "$enable_ed448" = "" && enable_ed448=yes + + if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" + then + test "$enable_eccsi" = "" && enable_eccsi=yes + test "$enable_sakke" = "" && enable_sakke=yes + fi fi # Enable DH const table speedups (eliminates `-lm` math lib dependency) @@ -533,12 +556,18 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT" fi - if test "$ENABLED_FIPS" != "yes" + if test "$ENABLED_FIPS" == "no" then test "$enable_xchacha" = "" && enable_xchacha=yes test "$enable_ed25519" = "" && enable_ed25519=yes test "$enable_ed448" = "" && enable_ed448=yes test "$enable_pkcs7" = "" && enable_pkcs7=yes + + if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" + then + test "$enable_eccsi" = "" && enable_eccsi=yes + test "$enable_sakke" = "" && enable_sakke=yes + fi fi # Enable AES Decrypt, AES ECB, Alt Names, DER Load @@ -926,16 +955,24 @@ then AM_CFLAGS="-DHAVE_EXT_CACHE $AM_CFLAGS" fi -if test "$ENABLED_OPENSSLEXTRA" = "yes" && test "$ENABLED_SMALL" = "yes" -then - AC_MSG_ERROR([cannot enable small and opensslextra, only one or the other.]) -fi - if test "$ENABLED_OPENSSLEXTRA" = "x509small" then AC_MSG_NOTICE([Enabling only a subset of X509 opensslextra]) AM_CFLAGS="-DOPENSSL_EXTRA_X509_SMALL $AM_CFLAGS" AM_CFLAGS="-DWOLFSSL_EKU_OID -DWOLFSSL_MULTI_ATTRIB $AM_CFLAGS" + AM_CFLAGS="-DWOLFSSL_NO_OPENSSL_RAND_CB $AM_CFLAGS" +fi + +# One Error Queue per Thread +AC_ARG_ENABLE([error-queue-per-thread], +[AS_HELP_STRING([--enable-error-queue-per-thread],[Enable one error queue per thread. Requires thread local storage. (default: disabled)])], +[ ENABLED_ERRORQUEUEPERTHREAD=$enableval ], +[ ENABLED_ERRORQUEUEPERTHREAD=no ] +) + +if test "$ENABLED_ERRORQUEUEPERTHREAD" = "yes" +then + AM_CFLAGS="-DERROR_QUEUE_PER_THREAD $AM_CFLAGS" fi # High Strength Build @@ -1252,6 +1289,18 @@ then AM_CFLAGS="$AM_CFLAGS -DNO_AES_CBC" fi +# AES-CBC length checks (checks that input lengths are multiples of block size) +AC_ARG_ENABLE([aescbc_length_checks], + [AS_HELP_STRING([--enable-aescbc-length-checks],[Enable AES-CBC length validity checks (default: disabled)])], + [ ENABLED_AESCBC_LENGTH_CHECKS=$enableval ], + [ ENABLED_AESCBC_LENGTH_CHECKS=no ] + ) + +if test "$ENABLED_AESCBC_LENGTH_CHECKS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_CBC_LENGTH_CHECKS" +fi + # leanpsk and leantls don't need gcm # AES-GCM @@ -1260,6 +1309,11 @@ AC_ARG_ENABLE([aesgcm], [ ENABLED_AESGCM=$enableval ], [ ENABLED_AESGCM=yes ] ) +AC_ARG_ENABLE([aesgcm-stream], + [AS_HELP_STRING([--enable-aesgcm-stream],[Enable wolfSSL AES-GCM support with streaming APIs (default: enabled)])], + [ ENABLED_AESGCM_STREAM=$enableval ], + [ ENABLED_AESGCM_STREAM=no ] + ) # leanpsk and leantls don't need gcm if test "$ENABLED_LEANPSK" = "yes" || ( test "$ENABLED_LEANTLS" = "yes" && @@ -1400,6 +1454,23 @@ then fi +# CAAM build +AC_ARG_ENABLE([caam], + [AS_HELP_STRING([--enable-caam],[Enable wolfSSL support for CAAM (default: disabled)])], + [ ENABLED_CAAM=$enableval ], + [ ENABLED_CAAM=no ] + ) +if test "$ENABLED_CAAM" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IMX6_CAAM" +fi + +if test "$ENABLED_CAAM" = "qnx" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IMX6_CAAM -DWOLFSSL_QNX_CAAM" +fi + + # INTEL AES-NI AC_ARG_ENABLE([aesni], [AS_HELP_STRING([--enable-aesni],[Enable wolfSSL AES-NI support (default: disabled)])], @@ -1485,7 +1556,7 @@ if test "$ENABLED_AFALG" = "xilinx" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX -DWOLFSSL_AFALG_XILINX_AES" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_SHA3 -DWOLFSSL_AFALG_XILINX_RSA" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512 -DWOLFSSL_NO_SHAKE256" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512" ENABLED_AFALG="yes" ENABLED_XILINX="yes" fi @@ -1501,7 +1572,7 @@ if test "$ENABLED_AFALG" = "xilinx-sha3" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_SHA3" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512 -DWOLFSSL_NO_SHAKE256" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512" ENABLED_AFALG="yes" ENABLED_XILINX="yes" fi @@ -1657,6 +1728,59 @@ then fi +# set sha224 default +SHA224_DEFAULT=no +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + if test "x$ENABLED_AFALG" = "xno" && test "x$ENABLED_DEVCRYPTO" = "xno" && ( test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" ) + then + SHA224_DEFAULT=yes + fi +fi + +# SHA224 +AC_ARG_ENABLE([sha224], + [AS_HELP_STRING([--enable-sha224],[Enable wolfSSL SHA-224 support (default: enabled on x86_64/aarch64)])], + [ ENABLED_SHA224=$enableval ], + [ ENABLED_SHA224=$SHA224_DEFAULT ] + ) + +if test "$ENABLED_SHA224" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224" +fi + + +# set sha3 default +SHA3_DEFAULT=no +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + if test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" + then + SHA3_DEFAULT=yes + fi +fi + +# SHA3 +AC_ARG_ENABLE([sha3], + [AS_HELP_STRING([--enable-sha3],[Enable wolfSSL SHA-3 support (default: enabled on x86_64/aarch64)])], + [ ENABLED_SHA3=$enableval ], + [ ENABLED_SHA3=$SHA3_DEFAULT ] + ) + +if test "$ENABLED_SHA3" = "small" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3_SMALL" + ENABLED_SHA3="yes" +fi + +# SHAKE256 +AC_ARG_ENABLE([shake256], + [AS_HELP_STRING([--enable-shake256],[Enable wolfSSL SHAKE256 support (default: disabled)])], + [ ENABLED_SHAKE256=$enableval ] + [ ENABLED_SHAKE256=no ] + ) + # SHA512 AC_ARG_ENABLE([sha512], [AS_HELP_STRING([--enable-sha512],[Enable wolfSSL SHA-512 support (default: enabled)])], @@ -2085,12 +2209,16 @@ then then AC_MSG_ERROR([cannot enable ed448 without enabling sha512.]) fi + if test "$FIPS_VERSION" = "v2" + then + AC_MSG_ERROR([cannot enable ed448 w/ dependency shake256 in FIPSv2 mode]) + fi ENABLED_FE448=yes ENABLED_GE448=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448" # EdDSA448 requires SHAKE256 which requires SHA-3 - ENABLED_SHAKE3=yes + ENABLED_SHA3=yes ENABLED_SHAKE256=yes ENABLED_CERTS=yes @@ -2135,6 +2263,36 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT" fi +# Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption (ECCSI) +AC_ARG_ENABLE([eccsi], + [AS_HELP_STRING([--enable-eccsi],[Enable ECCSI (default: disabled)])], + [ ENABLED_ECCSI=$enableval ], + [ ENABLED_ECCSI=no ] + ) + +if test "x$ENABLED_ECCSI" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_ECCSI -DWOLFSSL_PUBLIC_MP" +fi + +# Sakai-Kasahara Key Encryption (SAKKE) - pairing based crypto +AC_ARG_ENABLE([sakke], + [AS_HELP_STRING([--enable-sakke],[Enable SAKKE - paring based crypto (default: disabled)])], + [ ENABLED_SAKKE=$enableval ], + [ ENABLED_SAKKE=no ] + ) + +if test "x$ENABLED_SAKKE" = "xsmall" +then + ENABLED_SAKKE="yes" + ENABLED_SAKKE_SMALL="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_SAKKE_SMALL" +fi +if test "x$ENABLED_SAKKE" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_SAKKE" +fi + # PSK AC_ARG_ENABLE([psk], @@ -2347,6 +2505,77 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STACK_LOG -finstrument-functions" fi + +ENABLED_WOLFSENTRY=no + +AC_ARG_WITH([wolfsentry], + [AS_HELP_STRING([--with-wolfsentry=PATH],[PATH to directory with wolfSentry installation])], + [WOLFSENTRY_INSTALLDIR=$withval], + [WOLFSENTRY_INSTALLDIR=""]) + +AC_ARG_WITH([wolfsentry-lib], + [AS_HELP_STRING([--with-wolfsentry-lib=PATH],[PATH to directory with wolfSentry library])], + [WOLFSENTRY_LIB=$withval], + [WOLFSENTRY_LIB=""]) + +AC_ARG_WITH([wolfsentry-include], + [AS_HELP_STRING([--with-wolfsentry-include=PATH],[PATH to directory with wolfSentry header files])], + [WOLFSENTRY_INCLUDE=$withval], + [WOLFSENTRY_INCLUDE=""]) + +if test -n "$WOLFSENTRY_INSTALLDIR" || test -n "$WOLFSENTRY_LIB" || test -n "$WOLFSENTRY_INCLUDE" +then + ENABLED_WOLFSENTRY=yes +fi + +AC_ARG_ENABLE([wolfsentry], + [AS_HELP_STRING([--enable-wolfsentry],[Enable wolfSentry hooks and plugins (default: disabled)])], + [ ENABLED_WOLFSENTRY=$enableval ], + [ ] + ) + +if test "$WOLFSENTRY_LIB" = "" && test -n "$WOLFSENTRY_INSTALLDIR" +then + WOLFSENTRY_LIB="${WOLFSENTRY_INSTALLDIR}/lib" +fi + +if test "$WOLFSENTRY_INCLUDE" = "" && test -n "$WOLFSENTRY_INSTALLDIR" +then + WOLFSENTRY_INCLUDE="${WOLFSENTRY_INSTALLDIR}/include" +fi + +if test -n "$WOLFSENTRY_LIB" +then + AC_MSG_CHECKING([for $WOLFSENTRY_LIB]) + if ! test -d "$WOLFSENTRY_LIB" + then + AC_MSG_ERROR([wolfSentry lib dir $WOLFSENTRY_LIB not found.]) + fi + AC_MSG_RESULT([yes]) + WOLFSENTRY_LIB="-L$WOLFSENTRY_LIB" +fi + +if test -n "$WOLFSENTRY_INCLUDE" +then + AC_MSG_CHECKING([for $WOLFSENTRY_INCLUDE]) + if ! test -d "$WOLFSENTRY_INCLUDE" + then + AC_MSG_ERROR([wolfSentry include dir $WOLFSENTRY_INCLUDE not found.]) + fi + AC_MSG_RESULT([yes]) + WOLFSENTRY_INCLUDE="-I$WOLFSENTRY_INCLUDE" +fi + +if test "$ENABLED_WOLFSENTRY" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WOLFSENTRY_HOOKS -DHAVE_EX_DATA -DHAVE_EX_DATA_CLEANUP_HOOKS" + WOLFSENTRY_LIB="$WOLFSENTRY_LIB -lwolfsentry" +fi + +AC_SUBST([WOLFSENTRY_LIB]) +AC_SUBST([WOLFSENTRY_INCLUDE]) + + if test "$ENABLED_QT" = "yes" then # Requires opensslextra and opensslall @@ -2530,7 +2759,7 @@ AC_ARG_ENABLE([anon], [ ENABLED_ANON=no ] ) -if test "x$ENABLED_WPAS" = "xyes" +if test "x$ENABLED_WPAS" = "xyes" || test "$ENABLED_NGINX" = "yes" then ENABLED_ANON=yes fi @@ -2677,6 +2906,12 @@ AC_ARG_ENABLE([base16], [ ENABLED_BASE16=$enableval ], [ ENABLED_BASE16=no ] ) + +if test "$ENABLED_CAAM" = "qnx" +then + ENABLED_BASE16=yes +fi + if test "$ENABLED_BASE16" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BASE16" @@ -2875,8 +3110,6 @@ AS_CASE([$FIPS_VERSION], AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS -DWOLFSSL_KEY_GEN -DWOLFSSL_SHA224 -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB -DHAVE_ECC_CDH -DWC_RSA_NO_PADDING -DWOLFSSL_VALIDATE_FFC_IMPORT -DHAVE_FFDHE_Q" ENABLED_KEYGEN="yes" ENABLED_SHA224="yes" - # Shake256 is a SHA-3 algorithm not in our FIPS algorithm list - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE256" AS_IF([test "x$ENABLED_AESCCM" != "xyes"], [ENABLED_AESCCM="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM"]) @@ -2954,63 +3187,22 @@ AS_CASE([$SELFTEST_VERSION], ]) -# set sha224 default -SHA224_DEFAULT=no -if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" + +# set POLY1305 default +POLY1305_DEFAULT=yes + +if test "x$ENABLED_FIPS" = "xyes" then - if test "x$ENABLED_AFALG" = "xno" && test "x$ENABLED_DEVCRYPTO" = "xno" && ( test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" ) - then - SHA224_DEFAULT=yes - fi +POLY1305_DEFAULT=no fi -# SHA224 -AC_ARG_ENABLE([sha224], - [AS_HELP_STRING([--enable-sha224],[Enable wolfSSL SHA-224 support (default: enabled on x86_64/aarch64)])], - [ ENABLED_SHA224=$enableval ], - [ ENABLED_SHA224=$SHA224_DEFAULT ] - ) - -if test "$ENABLED_SHA224" = "yes" -then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224" -fi - - -# set sha3 default -SHA3_DEFAULT=no -if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" -then - if test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" - then - SHA3_DEFAULT=yes - fi -fi - -# SHA3 -AC_ARG_ENABLE([sha3], - [AS_HELP_STRING([--enable-sha3],[Enable wolfSSL SHA-3 support (default: enabled on x86_64/aarch64)])], - [ ENABLED_SHA3=$enableval ], - [ ENABLED_SHA3=$SHA3_DEFAULT ] - ) - -if test "$ENABLED_SHA3" = "small" -then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3_SMALL" - ENABLED_SHA3="yes" -fi +# Set SHA-3 and SHAKE256 flags if test "$ENABLED_SHA3" = "yes" && test "$ENABLED_32BIT" = "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3" fi -# SHAKE256 -AC_ARG_ENABLE([shake256], - [AS_HELP_STRING([--enable-shake256],[Enable wolfSSL SHAKE256 support (default: enabled on x86_64/aarch64)])], - [ ENABLED_SHAKE256=$enableval ], - [ ENABLED_SHAKE256=$ENABLED_SHA3 ] - ) if test "$ENABLED_SHAKE256" = "yes" || test "$ENABLED_SHAKE256" = "small" then @@ -3024,13 +3216,6 @@ then fi fi -# set POLY1305 default -POLY1305_DEFAULT=yes - -if test "x$ENABLED_FIPS" = "xyes" -then -POLY1305_DEFAULT=no -fi # POLY1305 AC_ARG_ENABLE([poly1305], @@ -3074,7 +3259,7 @@ fi if test "$ENABLED_CHACHA" = "noasm" || test "$ENABLED_ASM" = "no" then - AM_CFLAGS="$AM_CFLAGS -DNO_CHACHA_ASM" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CHACHA -DNO_CHACHA_ASM" fi if test "$ENABLED_CHACHA" = "yes" @@ -4176,6 +4361,7 @@ then AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 -DOPENSSL_NO_COMP" AM_CFLAGS="$AM_CFLAGS -DHAVE_EX_DATA -DWOLFSSL_SIGNER_DER_CERT" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT -DWOLFSSL_CERT_GEN" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI" # Requires OCSP make sure on if test "x$ENABLED_OCSP" = "xno" @@ -4264,49 +4450,49 @@ if test "$ENABLED_WPAS" = "yes" then ENABLED_STUNNEL="yes" fi +# stunnel support requires all the features enabled within this conditional. if test "$ENABLED_STUNNEL" = "yes" then - # Requires opensslextra make sure on if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" then ENABLED_OPENSSLEXTRA="yes" AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" fi - # Requires OCSP make sure on + if test "x$ENABLED_SESSION_TICKET" = "xno" + then + ENABLED_SESSION_TICKET="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_SESSION_TICKET" + fi + if test "x$ENABLED_OCSP" = "xno" then ENABLED_OCSP="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" fi - # Requires coding make sure on if test "x$ENABLED_CODING" = "xno" then ENABLED_CODING="yes" fi - # Requires sessioncerts make sure on if test "x$ENABLED_SESSIONCERTS" = "xno" then ENABLED_SESSIONCERTS="yes" AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" fi - # Requires crls, make sure on if test "x$ENABLED_CRL" = "xno" then ENABLED_CRL="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" fi - # Requires DES3, make sure on if test "x$ENABLED_DES3" = "xno" then ENABLED_DES3="yes" fi - # Requires tlsx, make sure on if test "x$ENABLED_TLSX" = "xno" then ENABLED_TLSX="yes" @@ -4318,7 +4504,6 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi - # Requires ecc make sure on if test "x$ENABLED_ECC" = "xno" then ENABLED_OPENSSLEXTRA="yes" @@ -4331,14 +4516,12 @@ then fi fi - # Requires wolfSSL_OBJ_txt2nid if test "x$ENABLED_CERTEXT" = "xno" then ENABLED_CERTEXT="yes" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" fi - # Requires certgen if test "x$ENABLED_CERTGEN" = "xno" then ENABLED_CERTGEN="yes" @@ -4347,7 +4530,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DWOLFSSL_SIGNER_DER_CERT" fi if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" \ @@ -4604,6 +4787,11 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_X86_64_BUILD" fi AS_IF([test "x$host_cpu" = "xaarch64"],[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AARCH64_BUILD"]) + + if test "$ENABLED_SAKKE" = "yes" && test "$ENABLED_SAKKE_SMALL" != "yes" + then + AM_CFLAGS="$AM_CFLAGS -funroll-loops -DTFM_SMALL_SET" + fi fi @@ -4897,6 +5085,7 @@ ENABLED_SP_FF_4096=no ENABLED_SP_ECC=no ENABLED_SP_EC_256=no ENABLED_SP_EC_384=no +ENABLED_SP_SAKKE_1024=$ENABLED_SAKKE ENABLED_SP_NO_MALLOC=no ENABLED_SP_NONBLOCK=no ENABLED_SP_SMALL=no @@ -4951,6 +5140,15 @@ do ENABLED_SP_ECC=yes ENABLED_SP_EC_384=yes ;; + smallec1024 | smallp1024 | small1024) + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_SAKKE_1024=yes + ;; + ec1024 | p1024 | 1024) + ENABLED_SP_ECC=yes + ENABLED_SP_SAKKE_1024=yes + ;; small2048) ENABLED_SP_SMALL=yes @@ -5026,6 +5224,10 @@ do ENABLED_SP_SMALL=yes ;; + asm) + ENABLED_SP_ASM=yes + ;; + *) AC_MSG_ERROR([Invalid choice of Single Precision length in bits [256, 2048, 3072]: $ENABLED_SP.]) break;; @@ -5069,6 +5271,10 @@ if test "$ENABLED_ECC" != "no" && test "$ENABLED_SP_ECC" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC384 -DWOLFSSL_SP_384" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_384" fi + if test "$ENABLED_SP_SAKKE_1024" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_1024" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_1024" + fi fi if test "$ENABLED_SP_SMALL" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" @@ -5082,11 +5288,6 @@ if test "$ENABLED_SP_NONBLOCK" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NONBLOCK" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NONBLOCK" fi -if test "$ENABLED_SMALL" = "yes"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" - AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_SMALL" -fi - if test "$ENABLED_SP_MATH" = "yes"; then if test "$ENABLED_SP" = "no"; then @@ -5201,11 +5402,6 @@ if test "$ENABLED_SP_MATH_ALL" = "yes"; then fi -AC_ARG_ENABLE([sp-asm], - [AS_HELP_STRING([--enable-sp-asm],[Enable Single Precision assembly implementation (default: disabled)])], - [ ENABLED_SP_ASM=$enableval ], - [ ENABLED_SP_ASM=no ], - ) if test "$ENABLED_SP_ASM" = "yes"; then if test "$ENABLED_SP" = "no"; then AC_MSG_ERROR([Must have SP enabled: --enable-sp]) @@ -5242,7 +5438,7 @@ if test "$ENABLED_SP_ASM" = "yes"; then fi fi ;; - *x86_64*) + *x86_64*|*amd64*) AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_X86_64_ASM" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_X86_64_ASM" ENABLED_SP_X86_64_ASM=yes @@ -5540,7 +5736,7 @@ AC_ARG_ENABLE([cryptocb], [ ENABLED_CRYPTOCB=no ] ) -if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" +if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" || test "$ENABLED_CAAM" = "qnx" then ENABLED_CRYPTOCB=yes fi @@ -5601,7 +5797,7 @@ AC_ARG_ENABLE([oldnames], if test "x$ENABLED_OLDNAMES" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" then AM_CFLAGS="$AM_CFLAGS -DNO_OLD_RNGNAME -DNO_OLD_WC_NAMES -DNO_OLD_SSL_NAMES" - AM_CFLAGS="$AM_CFLAGS -DNO_OLD_SHA_NAMES" + AM_CFLAGS="$AM_CFLAGS -DNO_OLD_SHA_NAMES -DNO_OLD_MD5_NAME" fi @@ -5863,6 +6059,16 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" fi +if test "$ENABLED_AESGCM_STREAM" != "no" +then + if test "$ENABLED_AESGCM" = "no" + then + AC_MSG_ERROR([AES-GCM streaming enabled but AES-GCM is disabled]) + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESGCM_STREAM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AESGCM_STREAM" + fi +fi AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes"], @@ -6110,6 +6316,8 @@ AM_CONDITIONAL([BUILD_FE448], [test "x$ENABLED_FE448" = "xyes" || test "x$ENABLE AM_CONDITIONAL([BUILD_GE448], [test "x$ENABLED_GE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_CURVE448],[test "x$ENABLED_CURVE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_CURVE448_SMALL],[test "x$ENABLED_CURVE448_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ECCSI],[test "x$ENABLED_ECCSI" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SAKKE],[test "x$ENABLED_SAKKE" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_MEMORY],[test "x$ENABLED_MEMORY" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_RSA],[test "x$ENABLED_RSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_DH],[test "x$ENABLED_DH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) @@ -6132,7 +6340,7 @@ AM_CONDITIONAL([BUILD_SELFTEST],[test "x$ENABLED_SELFTEST" = "xyes"]) AM_CONDITIONAL([BUILD_SHA224],[test "x$ENABLED_SHA224" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SHA3],[test "x$ENABLED_SHA3" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_POLY1305],[test "x$ENABLED_POLY1305" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) -AM_CONDITIONAL([BUILD_CHACHA],[test "x$ENABLED_CHACHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CHACHA],[test "x$ENABLED_CHACHA" = "xyes" || test "x$ENABLED_CHACHA" = "xnoasm" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_XCHACHA],[test "x$ENABLED_XCHACHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_INLINE],[test "x$ENABLED_INLINE" = "xyes"]) AM_CONDITIONAL([BUILD_OCSP],[test "x$ENABLED_OCSP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) @@ -6185,9 +6393,11 @@ AM_CONDITIONAL([BUILD_DES3],[test "x$ENABLED_DES3" = "xyes" || test "x$ENABLED_U AM_CONDITIONAL([BUILD_PKCS7],[test "x$ENABLED_PKCS7" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SMIME],[test "x$ENABLED_SMIME" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_HASHFLAGS],[test "x$ENABLED_HASHFLAGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CAAM],[test "x$ENABLED_CAAM" = "xyes" || test "x$ENABLED_CAAM" = "xqnx"]) AM_CONDITIONAL([BUILD_LINUXKM],[test "$ENABLED_LINUXKM" = "yes"]) AM_CONDITIONAL([BUILD_NO_LIBRARY],[test "$ENABLED_NO_LIBRARY" = "yes"]) AM_CONDITIONAL([BUILD_RC2],[test "x$ENABLED_RC2" = "xyes"]) +AM_CONDITIONAL([BUILD_QNXCAAM],[test "x$ENABLED_CAAM" = "xqnx"]) if test "$ax_enable_debug" = "yes" || test "$ENABLED_STACKSIZE" != "no" || @@ -6379,6 +6589,7 @@ echo " * ARC4: $ENABLED_ARC4" echo " * AES: $ENABLED_AES" echo " * AES-NI: $ENABLED_AESNI" echo " * AES-CBC: $ENABLED_AESCBC" +echo " * AES-CBC length checks: $ENABLED_AESCBC_LENGTH_CHECKS" echo " * AES-GCM: $ENABLED_AESGCM" echo " * AES-CCM: $ENABLED_AESCCM" echo " * AES-CTR: $ENABLED_AESCTR" @@ -6427,19 +6638,22 @@ echo " * DSA: $ENABLED_DSA" echo " * DH: $ENABLED_DH" echo " * DH Default Parameters: $ENABLED_DHDEFAULTPARAMS" echo " * ECC: $ENABLED_ECC" -echo " * ECC Custom Curves $ENABLED_ECCCUSTCURVES" -echo " * ECC Minimum Bits $ENABLED_ECCMINSZ" +echo " * ECC Custom Curves: $ENABLED_ECCCUSTCURVES" +echo " * ECC Minimum Bits: $ENABLED_ECCMINSZ" echo " * CURVE25519: $ENABLED_CURVE25519" echo " * ED25519: $ENABLED_ED25519" echo " * CURVE448: $ENABLED_CURVE448" echo " * ED448: $ENABLED_ED448" echo " * FPECC: $ENABLED_FPECC" echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" +echo " * ECCSI $ENABLED_ECCSI" +echo " * SAKKE $ENABLED_SAKKE" echo " * ASN: $ENABLED_ASN" echo " * Anonymous cipher: $ENABLED_ANON" echo " * CODING: $ENABLED_CODING" echo " * MEMORY: $ENABLED_MEMORY" echo " * I/O POOL: $ENABLED_IOPOOL" +echo " * wolfSentry: $ENABLED_WOLFSENTRY" echo " * LIGHTY: $ENABLED_LIGHTY" echo " * HAPROXY: $ENABLED_HAPROXY" echo " * STUNNEL: $ENABLED_STUNNEL" @@ -6447,8 +6661,8 @@ echo " * Apache httpd: $ENABLED_APACHE_HTTPD" echo " * NGINX: $ENABLED_NGINX" echo " * ASIO: $ENABLED_ASIO" echo " * LIBWEBSOCKETS: $ENABLED_LIBWEBSOCKETS" -echo " * Qt $ENABLED_QT" -echo " * Qt Unit Testing $ENABLED_QT_TEST" +echo " * Qt: $ENABLED_QT" +echo " * Qt Unit Testing: $ENABLED_QT_TEST" echo " * SIGNAL: $ENABLED_SIGNAL" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" @@ -6489,12 +6703,12 @@ echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" echo " * Fallback SCSV: $ENABLED_FALLBACK_SCSV" echo " * Keying Material Exporter: $ENABLED_KEYING_MATERIAL" echo " * All TLS Extensions: $ENABLED_TLSX" -echo " * PKCS#7 $ENABLED_PKCS7" -echo " * S/MIME $ENABLED_SMIME" -echo " * wolfSSH $ENABLED_WOLFSSH" -echo " * wolfTPM $ENABLED_WOLFTPM" -echo " * wolfSCEP $ENABLED_WOLFSCEP" -echo " * Secure Remote Password $ENABLED_SRP" +echo " * PKCS#7: $ENABLED_PKCS7" +echo " * S/MIME: $ENABLED_SMIME" +echo " * wolfSSH: $ENABLED_WOLFSSH" +echo " * wolfTPM: $ENABLED_WOLFTPM" +echo " * wolfSCEP: $ENABLED_WOLFSCEP" +echo " * Secure Remote Password: $ENABLED_SRP" echo " * Small Stack: $ENABLED_SMALL_STACK" echo " * Linux Kernel Module: $ENABLED_LINUXKM" echo " * valgrind unit tests: $ENABLED_VALGRIND" @@ -6508,13 +6722,16 @@ echo " * Fast RSA: $ENABLED_FAST_RSA" echo " * Single Precision: $ENABLED_SP" if test "$ENABLED_SP_MATH_ALL" != "no" then - echo " * SP math implementation: all" -elif test "$ENABLED_SP_MATH" != "no" -then - echo " * SP math implementation: restricted" + ENABLED_SP_MATH_DESC="all" else - echo " * SP math implementation: no" + if test "$ENABLED_SP_MATH" != "no" + then + ENABLED_SP_MATH_DESC="restricted" + else + ENABLED_SP_MATH_DESC="no" + fi fi +echo " * SP math implementation: $ENABLED_SP_MATH_DESC" echo " * Async Crypto: $ENABLED_ASYNCCRYPT" echo " * PKCS#11: $ENABLED_PKCS11" echo " * PKCS#12: $ENABLED_PKCS12" @@ -6529,6 +6746,7 @@ echo " * Inline Code: $ENABLED_INLINE" echo " * Linux AF_ALG: $ENABLED_AFALG" echo " * Linux devcrypto: $ENABLED_DEVCRYPTO" echo " * Crypto callbacks: $ENABLED_CRYPTOCB" +echo " * i.MX6 CAAM: $ENABLED_CAAM" echo "" echo "---" diff --git a/ctaocrypt/src/misc.c b/ctaocrypt/src/misc.c index bd127625d..5d185c485 100644 --- a/ctaocrypt/src/misc.c +++ b/ctaocrypt/src/misc.c @@ -1,6 +1,6 @@ /* misc.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/ctaocrypt/src/wolfcrypt_first.c b/ctaocrypt/src/wolfcrypt_first.c index 74e759a7a..93d0a2597 100644 --- a/ctaocrypt/src/wolfcrypt_first.c +++ b/ctaocrypt/src/wolfcrypt_first.c @@ -1,6 +1,6 @@ /* wolfcrypt_first.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/ctaocrypt/src/wolfcrypt_last.c b/ctaocrypt/src/wolfcrypt_last.c index 60cb33a4e..b6d69d01a 100644 --- a/ctaocrypt/src/wolfcrypt_last.c +++ b/ctaocrypt/src/wolfcrypt_last.c @@ -1,6 +1,6 @@ /* wolfcrypt_last.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/callbacks.h b/cyassl/callbacks.h index 69dd3476b..7a1c1d43d 100644 --- a/cyassl/callbacks.h +++ b/cyassl/callbacks.h @@ -1,6 +1,6 @@ /* callbacks.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/crl.h b/cyassl/crl.h index 7f285a33e..a883879b9 100644 --- a/cyassl/crl.h +++ b/cyassl/crl.h @@ -1,6 +1,6 @@ /* crl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/aes.h b/cyassl/ctaocrypt/aes.h index dae7812e8..3973c8f30 100644 --- a/cyassl/ctaocrypt/aes.h +++ b/cyassl/ctaocrypt/aes.h @@ -1,6 +1,6 @@ /* aes.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/arc4.h b/cyassl/ctaocrypt/arc4.h index 627d79735..ff7440c30 100644 --- a/cyassl/ctaocrypt/arc4.h +++ b/cyassl/ctaocrypt/arc4.h @@ -1,6 +1,6 @@ /* arc4.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 673cce748..5ee090fa8 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -1,6 +1,6 @@ /* asn.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/asn_public.h b/cyassl/ctaocrypt/asn_public.h index 5e75943f0..b4dc6da66 100644 --- a/cyassl/ctaocrypt/asn_public.h +++ b/cyassl/ctaocrypt/asn_public.h @@ -1,6 +1,6 @@ /* asn_public.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/blake2-impl.h b/cyassl/ctaocrypt/blake2-impl.h index e815f0769..aa34a81cb 100644 --- a/cyassl/ctaocrypt/blake2-impl.h +++ b/cyassl/ctaocrypt/blake2-impl.h @@ -12,7 +12,7 @@ */ /* blake2-impl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/blake2-int.h b/cyassl/ctaocrypt/blake2-int.h index 77244a232..062de2ff6 100644 --- a/cyassl/ctaocrypt/blake2-int.h +++ b/cyassl/ctaocrypt/blake2-int.h @@ -12,7 +12,7 @@ */ /* blake2-int.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/blake2.h b/cyassl/ctaocrypt/blake2.h index c1378d9cd..377a51577 100644 --- a/cyassl/ctaocrypt/blake2.h +++ b/cyassl/ctaocrypt/blake2.h @@ -1,6 +1,6 @@ /* blake2.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/camellia.h b/cyassl/ctaocrypt/camellia.h index 8c0ce8d4c..8db4a45e2 100644 --- a/cyassl/ctaocrypt/camellia.h +++ b/cyassl/ctaocrypt/camellia.h @@ -1,6 +1,6 @@ /* camellia.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/chacha.h b/cyassl/ctaocrypt/chacha.h index bfe099851..0ad52ba35 100644 --- a/cyassl/ctaocrypt/chacha.h +++ b/cyassl/ctaocrypt/chacha.h @@ -1,6 +1,6 @@ /* chacha.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/coding.h b/cyassl/ctaocrypt/coding.h index 9902a5aba..7b433c768 100644 --- a/cyassl/ctaocrypt/coding.h +++ b/cyassl/ctaocrypt/coding.h @@ -1,6 +1,6 @@ /* coding.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/compress.h b/cyassl/ctaocrypt/compress.h index 6bb26c6b0..f1f8cb39b 100644 --- a/cyassl/ctaocrypt/compress.h +++ b/cyassl/ctaocrypt/compress.h @@ -1,6 +1,6 @@ /* compress.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/des3.h b/cyassl/ctaocrypt/des3.h index 8e355196d..94fd5ea35 100644 --- a/cyassl/ctaocrypt/des3.h +++ b/cyassl/ctaocrypt/des3.h @@ -1,6 +1,6 @@ /* des3.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/dh.h b/cyassl/ctaocrypt/dh.h index 80d4e51d3..5cf584930 100644 --- a/cyassl/ctaocrypt/dh.h +++ b/cyassl/ctaocrypt/dh.h @@ -1,6 +1,6 @@ /* dh.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/dsa.h b/cyassl/ctaocrypt/dsa.h index d99429081..60c815987 100644 --- a/cyassl/ctaocrypt/dsa.h +++ b/cyassl/ctaocrypt/dsa.h @@ -1,6 +1,6 @@ /* dsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/ecc.h b/cyassl/ctaocrypt/ecc.h index b4b2f96c4..6e1e1dcb2 100644 --- a/cyassl/ctaocrypt/ecc.h +++ b/cyassl/ctaocrypt/ecc.h @@ -1,6 +1,6 @@ /* ecc.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/error-crypt.h b/cyassl/ctaocrypt/error-crypt.h index 55a973947..061de0292 100644 --- a/cyassl/ctaocrypt/error-crypt.h +++ b/cyassl/ctaocrypt/error-crypt.h @@ -1,6 +1,6 @@ /* error-crypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/fips_test.h b/cyassl/ctaocrypt/fips_test.h index cdfad6cae..561da88cb 100644 --- a/cyassl/ctaocrypt/fips_test.h +++ b/cyassl/ctaocrypt/fips_test.h @@ -1,6 +1,6 @@ /* fips_test.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/hc128.h b/cyassl/ctaocrypt/hc128.h index af1186bde..378389343 100644 --- a/cyassl/ctaocrypt/hc128.h +++ b/cyassl/ctaocrypt/hc128.h @@ -1,6 +1,6 @@ /* hc128.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index 4c0dd153a..04fb6fb11 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/integer.h b/cyassl/ctaocrypt/integer.h index 2aed0cd0f..2ee59a394 100644 --- a/cyassl/ctaocrypt/integer.h +++ b/cyassl/ctaocrypt/integer.h @@ -1,6 +1,6 @@ /* integer.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/logging.h b/cyassl/ctaocrypt/logging.h index 12fa22c61..37dc5763a 100644 --- a/cyassl/ctaocrypt/logging.h +++ b/cyassl/ctaocrypt/logging.h @@ -1,6 +1,6 @@ /* logging.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/md2.h b/cyassl/ctaocrypt/md2.h index e3e7816e6..b01cc6efe 100644 --- a/cyassl/ctaocrypt/md2.h +++ b/cyassl/ctaocrypt/md2.h @@ -1,6 +1,6 @@ /* md2.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/md4.h b/cyassl/ctaocrypt/md4.h index f550a71ad..463a68da1 100644 --- a/cyassl/ctaocrypt/md4.h +++ b/cyassl/ctaocrypt/md4.h @@ -1,6 +1,6 @@ /* md4.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/md5.h b/cyassl/ctaocrypt/md5.h index 4f5dc4727..77d99ae40 100644 --- a/cyassl/ctaocrypt/md5.h +++ b/cyassl/ctaocrypt/md5.h @@ -1,6 +1,6 @@ /* md5.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/memory.h b/cyassl/ctaocrypt/memory.h index a7f2a8b3a..0084be7d6 100644 --- a/cyassl/ctaocrypt/memory.h +++ b/cyassl/ctaocrypt/memory.h @@ -1,6 +1,6 @@ /* memory.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/misc.h b/cyassl/ctaocrypt/misc.h index 02c544101..f311fc916 100644 --- a/cyassl/ctaocrypt/misc.h +++ b/cyassl/ctaocrypt/misc.h @@ -1,6 +1,6 @@ /* misc.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/mpi_class.h b/cyassl/ctaocrypt/mpi_class.h index 01141a98b..134b71407 100644 --- a/cyassl/ctaocrypt/mpi_class.h +++ b/cyassl/ctaocrypt/mpi_class.h @@ -1,6 +1,6 @@ /* mpi_class.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/mpi_superclass.h b/cyassl/ctaocrypt/mpi_superclass.h index ca7531c21..3a5d80e58 100644 --- a/cyassl/ctaocrypt/mpi_superclass.h +++ b/cyassl/ctaocrypt/mpi_superclass.h @@ -1,6 +1,6 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/pkcs7.h b/cyassl/ctaocrypt/pkcs7.h index 4b0488f25..3760567af 100644 --- a/cyassl/ctaocrypt/pkcs7.h +++ b/cyassl/ctaocrypt/pkcs7.h @@ -1,6 +1,6 @@ /* pkcs7.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/poly1305.h b/cyassl/ctaocrypt/poly1305.h index 72021ab27..e44be6cde 100644 --- a/cyassl/ctaocrypt/poly1305.h +++ b/cyassl/ctaocrypt/poly1305.h @@ -1,6 +1,6 @@ /* poly1305.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h b/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h index e56e236c9..b6f603280 100644 --- a/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h +++ b/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h @@ -1,6 +1,6 @@ /* pic32mz-crypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/pwdbased.h b/cyassl/ctaocrypt/pwdbased.h index 9f1d1de36..75df424e0 100644 --- a/cyassl/ctaocrypt/pwdbased.h +++ b/cyassl/ctaocrypt/pwdbased.h @@ -1,6 +1,6 @@ /* pwdbased.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/rabbit.h b/cyassl/ctaocrypt/rabbit.h index 109e97331..365e4ba5d 100644 --- a/cyassl/ctaocrypt/rabbit.h +++ b/cyassl/ctaocrypt/rabbit.h @@ -1,6 +1,6 @@ /* rabbit.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/random.h b/cyassl/ctaocrypt/random.h index 9581ff92c..44ca532c5 100644 --- a/cyassl/ctaocrypt/random.h +++ b/cyassl/ctaocrypt/random.h @@ -1,6 +1,6 @@ /* random.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/ripemd.h b/cyassl/ctaocrypt/ripemd.h index 25bcf990e..b9c2feea7 100644 --- a/cyassl/ctaocrypt/ripemd.h +++ b/cyassl/ctaocrypt/ripemd.h @@ -1,6 +1,6 @@ /* ripemd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/rsa.h b/cyassl/ctaocrypt/rsa.h index 18949e393..6a8b643e8 100644 --- a/cyassl/ctaocrypt/rsa.h +++ b/cyassl/ctaocrypt/rsa.h @@ -1,6 +1,6 @@ /* rsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/settings.h b/cyassl/ctaocrypt/settings.h index 83e8bdd22..adac2b4e4 100644 --- a/cyassl/ctaocrypt/settings.h +++ b/cyassl/ctaocrypt/settings.h @@ -1,6 +1,6 @@ /* settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/settings_comp.h b/cyassl/ctaocrypt/settings_comp.h index c886d8e62..8565e1aa2 100644 --- a/cyassl/ctaocrypt/settings_comp.h +++ b/cyassl/ctaocrypt/settings_comp.h @@ -1,6 +1,6 @@ /* settings_comp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/sha.h b/cyassl/ctaocrypt/sha.h index 92c8e33ad..78b9342c6 100644 --- a/cyassl/ctaocrypt/sha.h +++ b/cyassl/ctaocrypt/sha.h @@ -1,6 +1,6 @@ /* sha.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/sha256.h b/cyassl/ctaocrypt/sha256.h index 000e834bb..a2fb7c0e6 100644 --- a/cyassl/ctaocrypt/sha256.h +++ b/cyassl/ctaocrypt/sha256.h @@ -1,6 +1,6 @@ /* sha256.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/sha512.h b/cyassl/ctaocrypt/sha512.h index 39c634235..cc679a592 100644 --- a/cyassl/ctaocrypt/sha512.h +++ b/cyassl/ctaocrypt/sha512.h @@ -1,6 +1,6 @@ /* sha512.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/tfm.h b/cyassl/ctaocrypt/tfm.h index 77990ef27..303793403 100644 --- a/cyassl/ctaocrypt/tfm.h +++ b/cyassl/ctaocrypt/tfm.h @@ -1,6 +1,6 @@ /* tfm.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index b6d97b51f..e86506286 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -1,6 +1,6 @@ /* types.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/visibility.h b/cyassl/ctaocrypt/visibility.h index f22c08481..51e2ca94f 100644 --- a/cyassl/ctaocrypt/visibility.h +++ b/cyassl/ctaocrypt/visibility.h @@ -1,6 +1,6 @@ /* visibility.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/wc_port.h b/cyassl/ctaocrypt/wc_port.h index 50fb90ad9..b330803f0 100644 --- a/cyassl/ctaocrypt/wc_port.h +++ b/cyassl/ctaocrypt/wc_port.h @@ -1,6 +1,6 @@ /* port.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index e5189fac4..13fd5d600 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -1,6 +1,6 @@ /* error-ssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/internal.h b/cyassl/internal.h index 80d451e98..f7239e3f1 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1,6 +1,6 @@ /* internal.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ocsp.h b/cyassl/ocsp.h index e06a1b53c..bb11e5624 100644 --- a/cyassl/ocsp.h +++ b/cyassl/ocsp.h @@ -1,6 +1,6 @@ /* ocsp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/openssl/des.h b/cyassl/openssl/des.h index de4676402..79a06b741 100644 --- a/cyassl/openssl/des.h +++ b/cyassl/openssl/des.h @@ -1,6 +1,6 @@ /* des.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/openssl/evp.h b/cyassl/openssl/evp.h index b7ad1f50c..af81c100b 100644 --- a/cyassl/openssl/evp.h +++ b/cyassl/openssl/evp.h @@ -1,6 +1,6 @@ /* evp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/openssl/hmac.h b/cyassl/openssl/hmac.h index 6dd377994..c93ef8d92 100644 --- a/cyassl/openssl/hmac.h +++ b/cyassl/openssl/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/openssl/ssl.h b/cyassl/openssl/ssl.h index 3896292c1..3f2f3e351 100644 --- a/cyassl/openssl/ssl.h +++ b/cyassl/openssl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/options.h.in b/cyassl/options.h.in index ff991bdb5..fc90ce70b 100644 --- a/cyassl/options.h.in +++ b/cyassl/options.h.in @@ -1,6 +1,6 @@ /* options.h.in * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/sniffer.h b/cyassl/sniffer.h index 629785591..f92eeec08 100644 --- a/cyassl/sniffer.h +++ b/cyassl/sniffer.h @@ -1,6 +1,6 @@ /* sniffer.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/sniffer_error.h b/cyassl/sniffer_error.h index 8d7e8e159..d609f662d 100644 --- a/cyassl/sniffer_error.h +++ b/cyassl/sniffer_error.h @@ -1,6 +1,6 @@ /* sniffer_error.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 5d36b366e..8599de128 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/version.h b/cyassl/version.h index 0f59b121b..cc5da906f 100644 --- a/cyassl/version.h +++ b/cyassl/version.h @@ -1,6 +1,6 @@ /* cyassl/version.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/version.h.in b/cyassl/version.h.in index 25ce7d417..5fccf9ecb 100644 --- a/cyassl/version.h.in +++ b/cyassl/version.h.in @@ -1,6 +1,6 @@ /* cyassl_version.h.in * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/doc/dox_comments/header_files/aes.h b/doc/dox_comments/header_files/aes.h index 862f7a778..72df22e65 100644 --- a/doc/dox_comments/header_files/aes.h +++ b/doc/dox_comments/header_files/aes.h @@ -66,16 +66,22 @@ WOLFSSL_API int wc_AesSetIV(Aes* aes, const byte* iv); the resulting cipher text in the output buffer out using cipher block chaining with AES. This function requires that the AES object has been initialized by calling AesSetKey before a message is able to be encrypted. - This function assumes that the input message is AES block length aligned. - PKCS#7 style padding should be added beforehand. This differs from the - OpenSSL AES-CBC methods which add the padding for you. To make the wolfSSL - function and equivalent OpenSSL functions interoperate, one should specify + This function assumes that the input message is AES block length aligned, + and expects the input length to be a multiple of the block length, which + will optionally be checked and enforced if WOLFSSL_AES_CBC_LENGTH_CHECKS + is defined in the build configuration. In order to assure block-multiple + input, PKCS#7 style padding should be added beforehand. This differs from + the OpenSSL AES-CBC methods which add the padding for you. To make the + wolfSSL and corresponding OpenSSL functions interoperate, one should specify the -nopad option in the OpenSSL command line function so that it behaves like the wolfSSL AesCbcEncrypt method and does not add extra padding during encryption. \return 0 On successfully encrypting message. - \return BAD_ALIGN_E: Returned on block align error + \return BAD_ALIGN_E: may be returned on block align error + \return BAD_LENGTH_E will be returned if the input length isn't a + multiple of the AES block length, when the library is built with + WOLFSSL_AES_CBC_LENGTH_CHECKS. \param aes pointer to the AES object used to encrypt data \param out pointer to the output buffer in which to store the ciphertext @@ -110,15 +116,21 @@ WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, with AES. This function requires that the AES structure has been initialized by calling AesSetKey before a message is able to be decrypted. This function assumes that the original message was AES block length - aligned. This differs from the OpenSSL AES-CBC methods which do not - require alignment as it adds PKCS#7 padding automatically. To make the + aligned, and expects the input length to be a multiple of the block length, + which will optionally be checked and enforced if + WOLFSSL_AES_CBC_LENGTH_CHECKS is defined in the build configuration. + This differs from the OpenSSL AES-CBC methods, which add PKCS#7 padding + automatically, and so do not require block-multiple input. To make the wolfSSL function and equivalent OpenSSL functions interoperate, one should specify the -nopad option in the OpenSSL command line function so that it behaves like the wolfSSL AesCbcEncrypt method and does not create errors during decryption. \return 0 On successfully decrypting message. - \return BAD_ALIGN_E Returned on block align error. + \return BAD_ALIGN_E may be returned on block align error. + \return BAD_LENGTH_E will be returned if the input length isn't a + multiple of the AES block length, when the library is built with + WOLFSSL_AES_CBC_LENGTH_CHECKS. \param aes pointer to the AES object used to decrypt data. \param out pointer to the output buffer in which to store the plain text diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index e4f2cf69d..2d24e804e 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -1210,7 +1210,7 @@ int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz); and storing it as a pem file \return MEMORY_E Returned if there is an error allocating memory with XMALLOC - \return ASN_INPUT_E Returned in the case of a base 64 encoding error + \return ASN_INPUT_E Returned in the case of a base64 encoding error \return BUFFER_E May be returned if the output buffer is too small to store the pem formatted certificate @@ -1253,7 +1253,7 @@ WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, and storing it as a pem file \return MEMORY_E Returned if there is an error allocating memory with XMALLOC - \return ASN_INPUT_E Returned in the case of a base 64 encoding error + \return ASN_INPUT_E Returned in the case of a base64 encoding error \return BUFFER_E May be returned if the output buffer is too small to store the pem formatted certificate diff --git a/doc/dox_comments/header_files/doxygen_groups.h b/doc/dox_comments/header_files/doxygen_groups.h index cdb5a2a11..f8ac68330 100644 --- a/doc/dox_comments/header_files/doxygen_groups.h +++ b/doc/dox_comments/header_files/doxygen_groups.h @@ -13,6 +13,185 @@ \defgroup ECC Algorithms - ECC \defgroup ED25519 Algorithms - ED25519 \defgroup ED448 Algorithms - ED448 + \defgroup ECCSI_Overview Overview of ECCSI + ECCSI (Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption) is specified in RFC 6507 (https://tools.ietf.org/html/rfc6507). + + In Identity-Based cryptography, there is a Key Management Service that generates keys based on an identity for a client. + The private key (SSK) and public key (PVT) are delivered to the signer and the public key (PVT) only delivered to the verifier on request.\n\n + wolfCrypt offers the ability to: + -# Create KMS keys, + -# Generate signing key pairs, + -# Validate signing key pairs, + -# Sign messages and + -# Verify messages. + + KMS: + -# Initialize ECCSI Key: wc_InitEccsiKey() + -# Make and save or load ECCSI Key: + -# wc_MakeEccsiKey(), wc_ExportEccsiKey(), wc_ExportEccsiPublicKey() or + -# wc_ImportEccsiKey() + -# Wait for request: + -# Receive signing ID from client. + -# Generate signing key pair from ID: wc_MakeEccsiPair() + -# Encode result: + -# For signer, signing key pair: wc_EncodeEccsiPair() + -# Send KPAK and result + -# Free ECCSI Key: wc_FreeEccsiKey() + + Client, signer: + -# Initialize ECCSI Key: wc_InitEccsiKey() + -# (When signing pair not cached) Request KPAK and signing pair from KMS + -# Send signing ID to KMS. + -# Receive signing key pair from KMS. + -# Load KMS Public Key: wc_ImportEccsiPublicKey() + -# Decode signing key pair: wc_DecodeEccsiPair() + -# Validate the key pair: wc_ValidateEccsiPair() + -# (If not done above) Load KMS Public Key: wc_ImportEccsiPublicKey() + -# (If not cached) Calculate hash of the ID and PVT: wc_HashEccsiId() + -# For each message: + -# Set Hash of Identity: wc_SetEccsiHash() + -# Sign message: wc_SignEccsiHash() + -# Send hash ID, message and signature to peer. + -# Free ECCSI Key: wc_FreeEccsiKey() + + Client, verifier: + -# Receive hash ID, message and signature from signer. + -# Request KPAK (if not cached) and PVT (if not cached) for hash ID from KMS. + -# Receive KPAK (if not cached) and PVT (if not cached) for hash ID from KMS. + -# Initialize ECCSI Key: wc_InitEccsiKey() + -# Load KMS Public Key: wc_ImportEccsiPublicKey() + -# Decode PVT: wc_DecodeEccsiPvtFromSig() + -# Calculate hash of the ID and PVT: wc_HashEccsiId() + -# Set ECCSI key pair: wc_SetEccsiPair() + -# Verify signature of message: wc_VerifyEccsiHash() + -# Free ECCSI Key: wc_FreeEccsiKey() + + \defgroup ECCSI_Setup Setup ECCSI Key + Operations for establinshing an ECCSI key. + + Initialize ECCSI Key before use (wc_InitEccsiKey()).\n + Initialize ECCSI Key before use (wc_InitEccsiKey_ex()) for use with a curve other than P256.\n + Either make a new key (wc_MakeEccsiKey()), import an existing key (wc_ImportEccsiKey()) or import existing private key (wc_ImportEccsiPrivateKey()) and public key (wc_ImportEccsiPublicKey()).\n + Export the key (wc_ExportEccsiKey()) after making a new key for future use.\n + Export the private key (wc_ExportEccsiPrivateKey()) after making a new key for future use.\n + Export the public key (wc_ExportEccsiPublicKey()) from KMS to pass to client.\n + Import the public key (wc_ImportEccsiPublicKey()) into client.\n + Free the ECCSI Key (wc_FreeEccsiKey()) when finished. + + \defgroup ECCSI_Operations Operations for Signing and Verifying with ECCSI Key + These operations are for signing and verifying with ECCSI keys. + + Make an ECCSI key pair (wc_MakeEccsiPair()) with the signer's ID for use when signing.\n + Validate the ECCSI key pair (wc_ValidateEccsiPair()) with the signer's ID.\n + Validate the ECCSI Public Validation Token (PVT) (wc_ValidateEccsiPvt()).\n + Encode the ECCSI key pair (wc_EncodeEccsiPair()) for transfer to client.\n + Encode the ECCSI SSK (wc_EncodeEccsiSsk()) for transfer to client.\n + Encode the ECCSI PVT (wc_EncodeEccsiPvt()) for transfer to verifier.\n + Decode the ECCSI key pair (wc_DecodeEccsiPair()) on client for signing.\n + Decode the ECCSI SSK (wc_DecodeEccsiSsk()) on client for signing.\n + Decode the ECCSI PVT (wc_DecodeEccsiPvt()) on client for signing.\n + Decode the ECCSI PVT from the signature (wc_DecodeEccsiPvtFromSig()) on client for verifying.\n + Calculate hash of the ID (wc_HashEccsiId()) for signing/verifying using ID and Public Validation Token (PVT).\n + Sign (wc_SignEccsiHash()) a message with the hash of the ID and the Secret Signing Key (SSK) and Public Validation Token (PVT).\n + Verify (wc_VerifyEccsiHash()) a message with the hash of the signer's ID. + + \defgroup SAKKE_Overview Overview of SAKKE Key + SAKKE (Sakai-Kasahara Key Encryption) is specified in RFC 6508 (https://tools.ietf.org/html/rfc6508). + + SAKKE is used to transfer a secret to a peer using Identity Based cryptography.\n + The Key Management Service (KMS) is responsible for issuing Receiver Secret %Keys (RSKs). + Data up to (2^hashlen)^hashlen bytes of data can be transferred.\n + The sender must know the identity of the receiver and the KMS Public Key.\n + The receiver must have obtained a Receiver Secret Key (RSK) for the identity from a KMS in order to derive the secret. + + KMS: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Make and save or load SAKKE Key: + -# wc_MakeSakkeKey(), wc_ExportSakkeKey(), wc_ExportSakkePublicKey() or + -# wc_ImportSakkeKey() + -# Wait for request: + -# Make an RSK base on ID for the client: wc_MakeSakkeRsk() + -# Encode RSK for transfer to client: wc_EncodeSakkeRsk() + -# Free SAKKE Key: wc_FreeSakkeKey() + + Key Exchange, Peer A: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Generate a random SSV: wc_GenerateSakkeSSV() + -# Set the identity of Peer B: wc_SetSakkeIdentity() + -# Make an encapsulated SSV and auth data: wc_MakeSakkeEncapsulatedSSV() + -# Send encapsulated data to Peer B + -# Free SAKKE Key: wc_FreeSakkeKey() + + Key Exchange, Peer B: + -# Receive encapsulated data. + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Decode RSK transferred from KMS or stored locally: wc_DecodeSakkeRsk() + -# [Optional] Validate RSK before first use: wc_ValidateSakkeRsk() + -# Set the identity: wc_SetSakkeIdentity() + -# Set the RSK and, optionally precomputation table: wc_SetSakkeRsk() + -# Derive SSV with auth data: wc_DeriveSakkeSSV() + -# Free SAKKE Key: wc_FreeSakkeKey() + + Transfer secret, Peer A: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Set the identity of Peer B: wc_SetSakkeIdentity() + -# Make an encapsulation of the SSV and auth data: wc_MakeSakkeEncapsulatedSSV() + -# Send encapsulated data to Peer B + -# Free SAKKE Key: wc_FreeSakkeKey() + + Transfer secret, Peer B: + -# Initialize SAKKE Key: wc_InitSakkeKey() + -# Load KMS Public Key: wc_ImportSakkePublicKey() + -# Decode RSK transferred from KMS or stored locally: wc_DecodeSakkeRsk() + -# [Optional] Validate RSK before first use: wc_ValidateSakkeRsk() + -# Receive encapsulated data. + -# Set the identity: wc_SetSakkeIdentity() + -# Set the RSK and, optionally precomputation table: wc_SetSakkeRsk() + -# Derive SSV and auth data: wc_DeriveSakkeSSV() + -# Free SAKKE Key: wc_FreeSakkeKey() + + \defgroup SAKKE_Setup Setup SAKKE Key + Operations for establishing a SAKKE key. + + Initialization SAKKE Key before use (wc_InitSakkeKey() or wc_InitSakkeKey_ex()).\n + Either make a new key (wc_MakeSakkeKey()) or import an existing key (wc_ImportSakkeKey()).\n + Export the key (wc_ExportSakkeKey()) after making a new key for future use.\n + If only the private part of the KMS SAKKE Key is available, make the public key (wc_MakeSakkePublicKey()).\n + Export the private key (wc_ExportSakkePrivateKey()) from KMS from storage.\n + Import the private key (wc_ImportSakkePrivateKey()) into KMS from storage.\n + Export the public key (wc_ExportSakkePublicKey()) from KMS to pass to client.\n + Import the public key (wc_ImportSakkePublicKey()) into client.\n + Set the identity to use (wc_SetSakkeIdentity()) into client.\n + Free the SAKKE Key (wc_FreeSakkeKey()) when finished. + + \defgroup SAKKE_RSK Operations on/with SAKKE RSK + These operations make, validate, encode and decode a Receiver Secret Key (RSK). + + An RSK is required to derive an SSV (see wc_DeriveSakkeSSV()).\n + On the KMS, make an RSK (wc_MakeSakkeRsk()) from the client's ID.\n + On the client, validate the RSK (wc_ValidateSakkeRsk()) with the ID.\n + Encode the RSK (wc_EncodeSakkeRsk()) to pass to client or for storage.\n + Decode the RSK (wc_DecodeSakkeRsk()) on the client when needed.\n + Import the RSK (wc_ImportSakkeRsk()) on the client when needed.\n + Set the RSK and, optionally, a pre-computation table (wc_SetSakkeRsk()) on the client when needed. + + \defgroup SAKKE_Operations Operations using SAKKE Key + These operations transfer a Shared Secret Value (SSV) from one client to another. The SSV may be randomly generated. + + Calculate the size of the authentication data (wc_GetSakkeAuthSize()) to determine where the SSV starts in a buffer.\n + Make the intermediate point I (wc_MakeSakkePointI()) to speed making an encapsulated and deriving SSV.\n + Get intermediate point I (wc_GetSakkePointI()) for storage.\n + Set intermediate point I (wc_SetSakkePointI()) from storage.\n + Generate a pre-computation table for intermediate point I (wc_GenerateSakkePointITable()) to further enhance performance. Store as necessary.\n + Set the pre-computation table for intermediate point I (wc_SetSakkePointITable()) to further enhance performance.\n + Clear the pre-computation table for intermediate point I (wc_ClearSakkePointITable()) to remove reference to external table pointer.\n + Make an encapsulated SSV (wc_MakeSakkeEncapsulatedSSV()) to share with another client. Data in SSV is modified.\n + Generate a random SSV (wc_GenerateSakkeSSV()) for key exchange.\n + Derive the SSV, (wc_DeriveSakkeSSV()) on the recipient from the encapsulated SSV. + \defgroup HC128 Algorithms - HC-128 \defgroup HMAC Algorithms - HMAC \defgroup IDEA Algorithms - IDEA diff --git a/doc/dox_comments/header_files/doxygen_pages.h b/doc/dox_comments/header_files/doxygen_pages.h index 015c73a3f..262236297 100644 --- a/doc/dox_comments/header_files/doxygen_pages.h +++ b/doc/dox_comments/header_files/doxygen_pages.h @@ -39,6 +39,8 @@
  • \ref ECC
  • \ref ED25519
  • \ref ED448
  • +
  • \ref ECCSI
  • +
  • \ref SAKKE
  • \ref HC128
  • \ref HMAC
  • \ref IDEA
  • @@ -56,3 +58,17 @@
  • \ref SRP
  • */ +/*! + \page ECCSI ECCSI API Reference + - \ref ECCSI_Overview + - \ref ECCSI_Setup + - \ref ECCSI_Operations +*/ +/*! + \page SAKKE SAKKE API Reference + - \ref SAKKE_Overview + - \ref SAKKE_Setup + - \ref SAKKE_RSK + - \ref SAKKE_Operations +*/ + diff --git a/doc/dox_comments/header_files/eccsi.h b/doc/dox_comments/header_files/eccsi.h new file mode 100644 index 000000000..b4f40aaf5 --- /dev/null +++ b/doc/dox_comments/header_files/eccsi.h @@ -0,0 +1,131 @@ + +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_InitEccsiKey(EccsiKey* key, void* heap, int devId); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, + void* heap, int devId); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API void wc_FreeEccsiKey(EccsiKey* key); + +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_MakeEccsiKey(EccsiKey* key, WC_RNG* rng); + +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_MakeEccsiPair(EccsiKey* key, WC_RNG* rng, + enum wc_HashType hashType, const byte* id, word32 idSz, mp_int* ssk, + ecc_point* pvt); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_ValidateEccsiPair(EccsiKey* key, enum wc_HashType hashType, + const byte* id, word32 idSz, const mp_int* ssk, ecc_point* pvt, + int* valid); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_ValidateEccsiPvt(EccsiKey* key, const ecc_point* pvt, + int* valid); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_EncodeEccsiPair(const EccsiKey* key, mp_int* ssk, + ecc_point* pvt, byte* data, word32* sz); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_EncodeEccsiSsk(const EccsiKey* key, mp_int* ssk, byte* data, + word32* sz); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_EncodeEccsiPvt(const EccsiKey* key, ecc_point* pvt, + byte* data, word32* sz, int raw); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_DecodeEccsiPair(const EccsiKey* key, const byte* data, + word32 sz, mp_int* ssk, ecc_point* pvt); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_DecodeEccsiSsk(const EccsiKey* key, const byte* data, + word32 sz, mp_int* ssk); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_DecodeEccsiPvt(const EccsiKey* key, const byte* data, + word32 sz, ecc_point* pvt); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_DecodeEccsiPvtFromSig(const EccsiKey* key, const byte* sig, + word32 sz, ecc_point* pvt); + +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_ExportEccsiKey(EccsiKey* key, byte* data, word32* sz); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_ImportEccsiKey(EccsiKey* key, const byte* data, word32 sz); + +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_ExportEccsiPrivateKey(EccsiKey* key, byte* data, word32* sz); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_ImportEccsiPrivateKey(EccsiKey* key, const byte* data, + word32 sz); + +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_ExportEccsiPublicKey(EccsiKey* key, byte* data, word32* sz, + int raw); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_ImportEccsiPublicKey(EccsiKey* key, const byte* data, + word32 sz, int trusted); + +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_HashEccsiId(EccsiKey* key, enum wc_HashType hashType, + const byte* id, word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_SetEccsiHash(EccsiKey* key, const byte* hash, byte hashSz); +/*! + \ingroup ECCSI_Setup +*/ +WOLFSSL_API int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, + const ecc_point* pvt); + +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_SignEccsiHash(EccsiKey* key, WC_RNG* rng, + enum wc_HashType hashType, const byte* msg, word32 msgSz, byte* sig, + word32* sigSz); +/*! + \ingroup ECCSI_Operations +*/ +WOLFSSL_API int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType, + const byte* msg, word32 msgSz, const byte* sig, word32 sigSz, + int* verified); + diff --git a/doc/dox_comments/header_files/sakke.h b/doc/dox_comments/header_files/sakke.h new file mode 100644 index 000000000..021334c87 --- /dev/null +++ b/doc/dox_comments/header_files/sakke.h @@ -0,0 +1,143 @@ + +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_InitSakkeKey(SakkeKey* key, void* heap, int devId); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_InitSakkeKey_ex(SakkeKey* key, int keySize, int curveId, + void* heap, int devId); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API void wc_FreeSakkeKey(SakkeKey* key); + +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_MakeSakkeKey(SakkeKey* key, WC_RNG* rng); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_MakeSakkePublicKey(SakkeKey* key, ecc_point* pub); + +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_MakeSakkeRsk(SakkeKey* key, const byte* id, word16 idSz, + ecc_point* rsk); +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_ValidateSakkeRsk(SakkeKey* key, const byte* id, word16 idSz, + ecc_point* rsk, int* valid); +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_GenerateSakkeRskTable(const SakkeKey* key, + const ecc_point* rsk, byte* table, word32* len); + + +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_ExportSakkeKey(SakkeKey* key, byte* data, word32* sz); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_ImportSakkeKey(SakkeKey* key, const byte* data, word32 sz); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_ExportSakkePrivateKey(SakkeKey* key, byte* data, word32* sz); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_ImportSakkePrivateKey(SakkeKey* key, const byte* data, + word32 sz); + +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_EncodeSakkeRsk(const SakkeKey* key, ecc_point* rsk, + byte* out, word32* sz, int raw); +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_DecodeSakkeRsk(const SakkeKey* key, const byte* data, + word32 sz, ecc_point* rsk); + +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_ImportSakkeRsk(SakkeKey* key, const byte* data, word32 sz); + +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_ExportSakkePublicKey(SakkeKey* key, byte* data, + word32* sz, int raw); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_ImportSakkePublicKey(SakkeKey* key, const byte* data, + word32 sz, int trusted); + +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_GetSakkeAuthSize(SakkeKey* key, word16* authSz); +/*! + \ingroup SAKKE_Setup +*/ +WOLFSSL_API int wc_SetSakkeIdentity(SakkeKey* key, const byte* id, word16 idSz); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_MakeSakkePointI(SakkeKey* key, const byte* id, word16 idSz); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_GetSakkePointI(SakkeKey* key, byte* data, word32* sz); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_SetSakkePointI(SakkeKey* key, const byte* id, word16 idSz, + const byte* data, word32 sz); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_GenerateSakkePointITable(SakkeKey* key, byte* table, + word32* len); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_SetSakkePointITable(SakkeKey* key, byte* table, word32 len); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_ClearSakkePointITable(SakkeKey* key); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_MakeSakkeEncapsulatedSSV(SakkeKey* key, + enum wc_HashType hashType, byte* ssv, word16 ssvSz, byte* auth, + word16* authSz); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_GenerateSakkeSSV(SakkeKey* key, WC_RNG* rng, byte* ssv, + word16* ssvSz); +/*! + \ingroup SAKKE_RSK +*/ +WOLFSSL_API int wc_SetSakkeRsk(SakkeKey* key, const ecc_point* rsk, byte* table, + word32 len); +/*! + \ingroup SAKKE_Operations +*/ +WOLFSSL_API int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, + byte* ssv, word16 ssvSz, const byte* auth, + word16 authSz); + diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index c91db1441..66bfa797a 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -5036,7 +5036,17 @@ WOLFSSL_API void wolfSSL_ERR_print_errors_cb ( \param ctx a pointer to a WOLFSSL_CTX structure, created using wolfSSL_CTX_new(). \param cb wc_psk_client_callback is a function pointer that will be - stored in the WOLFSSL_CTX structure. + stored in the WOLFSSL_CTX structure. Return value is the key length on + success or zero on error. + unsigned int (*wc_psk_client_callback) + PSK client callback parameters: + WOLFSSL* ssl - Pointer to the wolfSSL structure + const char* hint - A stored string that could be displayed to provide a + hint to the user. + char* identity - The ID will be stored here. + unsigned int id_max_len - Size of the ID buffer. + unsigned char* key - The key will be stored here. + unsigned int key_max_len - The max size of the key. _Example_ \code @@ -5063,19 +5073,27 @@ WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*, \return none No returns. \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). - \param cb a function pointer to type wc_psk_client_callback. + \param cb a function pointer to type wc_psk_client_callback. Return value + is the key length on success or zero on error. + unsigned int (*wc_psk_client_callback) + PSK client callback parameters: + WOLFSSL* ssl - Pointer to the wolfSSL structure + const char* hint - A stored string that could be displayed to provide a + hint to the user. + char* identity - The ID will be stored here. + unsigned int id_max_len - Size of the ID buffer. + unsigned char* key - The key will be stored here. + unsigned int key_max_len - The max size of the key. _Example_ \code WOLFSSL* ssl; - unsigned int cb(WOLFSSL*, const char*, char*) // Header of function* - { - // Function body - } + static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + Unsigned int key_max_len){ … - cb = wc_psk_client_callback; if(ssl){ - wolfSSL_set_psk_client_callback(ssl, cb); + wolfSSL_set_psk_client_callback(ssl, my_psk_client_cb); } else { // could not set callback } @@ -5216,21 +5234,28 @@ WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*); \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). \param cb a function pointer for the callback and will be stored in - the WOLFSSL_CTX structure. + the WOLFSSL_CTX structure. Return value is the key length on success or + zero on error. + unsigned int (*wc_psk_server_callback) + PSK server callback parameters + WOLFSSL* ssl - Pointer to the wolfSSL structure + char* identity - The ID will be stored here. + unsigned char* key - The key will be stored here. + unsigned int key_max_len - The max size of the key. _Example_ \code WOLFSSL_CTX* ctx = wolfSSL_CTX_new( protocol method ); WOLFSSL* ssl = wolfSSL_new(ctx); … - unsigned int cb(WOLFSSL*, const char*, unsigned char*, unsigned int) - // signature requirement + static unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, + unsigned char* key, unsigned int key_max_len) { - // Function body. + // Function body. } … if(ctx != NULL){ - wolfSSL_CTX_set_psk_server_callback(ctx, cb); + wolfSSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); } else { // The CTX object was not properly initialized. } @@ -5252,20 +5277,29 @@ WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*, \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). \param cb a function pointer for the callback and will be stored in - the WOLFSSL structure. + the WOLFSSL structure. Return value is the key length on success or zero + on error. + unsigned int (*wc_psk_server_callback) + PSK server callback parameters + WOLFSSL* ssl - Pointer to the wolfSSL structure + char* identity - The ID will be stored here. + unsigned char* key - The key will be stored here. + unsigned int key_max_len - The max size of the key. + _Example_ \code WOLFSSL_CTX* ctx; WOLFSSL* ssl; … - int cb(WOLFSSL*, const char*, unsigned char*, unsigned int) // Required sig. + static unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, + unsigned char* key, unsigned int key_max_len) { - // Function body. + // Function body. } … if(ssl != NULL && cb != NULL){ - wolfSSL_set_psk_server_callback(ssl, cb); + wolfSSL_set_psk_server_callback(ssl, my_psk_server_cb); } \endcode @@ -6719,22 +6753,22 @@ WOLFSSL_API int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f, /*! \ingroup CertsKeys - \brief This function sets the minimum size of the Diffie Hellman key size - by accessing the minDhKeySz member in the WOLFSSL_CTX structure. + \brief This function sets the minimum size (in bits) of the Diffie Hellman + key size by accessing the minDhKeySz member in the WOLFSSL_CTX structure. \return SSL_SUCCESS returned if the function completes successfully. \return BAD_FUNC_ARG returned if the WOLFSSL_CTX struct is NULL or if - the keySz is greater than 16,000 or not divisible by 8. + the keySz_bits is greater than 16,000 or not divisible by 8. \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). - \param keySz a word16 type used to set the minimum DH key size. The - WOLFSSL_CTX struct holds this information in the minDhKeySz member. + \param keySz_bits a word16 type used to set the minimum DH key size in bits. + The WOLFSSL_CTX struct holds this information in the minDhKeySz member. _Example_ \code public static int CTX_SetMinDhKey_Sz(IntPtr ctx, short minDhKey){ … - return wolfSSL_CTX_SetMinDhKey_Sz(local_ctx, minDhKey); + return wolfSSL_CTX_SetMinDhKey_Sz(local_ctx, minDhKeyBits); \endcode \sa wolfSSL_SetMinDhKey_Sz @@ -6743,27 +6777,28 @@ WOLFSSL_API int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f, \sa wolfSSL_GetDhKey_Sz \sa wolfSSL_CTX_SetTMpDH_file */ -WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, word16); +WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16); /*! \ingroup CertsKeys - \brief Sets the minimum size for a Diffie-Hellman key in the WOLFSSL - structure in bytes. + \brief Sets the minimum size (in bits) for a Diffie-Hellman key in the + WOLFSSL structure. \return SSL_SUCCESS the minimum size was successfully set. - \return BAD_FUNC_ARG the WOLFSSL structure was NULL or the keySz parameter - was greater than the allowable size or not divisible by 8. + \return BAD_FUNC_ARG the WOLFSSL structure was NULL or if the keySz_bits is + greater than 16,000 or not divisible by 8. \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). - \param keySz a word16 type representing the bit size of the minimum DH key. + \param keySz_bits a word16 type used to set the minimum DH key size in bits. + The WOLFSSL_CTX struct holds this information in the minDhKeySz member. _Example_ \code WOLFSSL* ssl = wolfSSL_new(ctx); - word16 keySz; + word16 keySz_bits; ... - if(wolfSSL_SetMinDhKey(ssl, keySz) != SSL_SUCCESS){ + if(wolfSSL_SetMinDhKey_Sz(ssl, keySz_bits) != SSL_SUCCESS){ // Failed to set. } \endcode @@ -6776,22 +6811,22 @@ WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, word16); /*! \ingroup CertsKeys - \brief This function sets the maximum size of the Diffie Hellman key size - by accessing the maxDhKeySz member in the WOLFSSL_CTX structure. + \brief This function sets the maximum size (in bits) of the Diffie Hellman + key size by accessing the maxDhKeySz member in the WOLFSSL_CTX structure. \return SSL_SUCCESS returned if the function completes successfully. \return BAD_FUNC_ARG returned if the WOLFSSL_CTX struct is NULL or if - the keySz is greater than 16,000 or not divisible by 8. + the keySz_bits is greater than 16,000 or not divisible by 8. \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). - \param keySz a word16 type used to set the maximum DH key size. The - WOLFSSL_CTX struct holds this information in the maxDhKeySz member. + \param keySz_bits a word16 type used to set the maximum DH key size in bits. + The WOLFSSL_CTX struct holds this information in the maxDhKeySz member. _Example_ \code public static int CTX_SetMaxDhKey_Sz(IntPtr ctx, short maxDhKey){ … - return wolfSSL_CTX_SetMaxDhKey_Sz(local_ctx, maxDhKey); + return wolfSSL_CTX_SetMaxDhKey_Sz(local_ctx, keySz_bits); \endcode \sa wolfSSL_SetMinDhKey_Sz @@ -6805,8 +6840,8 @@ WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, word16); /*! \ingroup CertsKeys - \brief Sets the maximum size for a Diffie-Hellman key in the WOLFSSL - structure in bytes. + \brief Sets the maximum size (in bits) for a Diffie-Hellman key in the + WOLFSSL structure. \return SSL_SUCCESS the maximum size was successfully set. \return BAD_FUNC_ARG the WOLFSSL structure was NULL or the keySz parameter @@ -6833,11 +6868,12 @@ WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, word16); /*! \ingroup CertsKeys - \brief Returns the value of dhKeySz that is a member of the options - structure. This value represents the Diffie-Hellman key size in bytes. + \brief Returns the value of dhKeySz (in bits) that is a member of the + options structure. This value represents the Diffie-Hellman key size in + bytes. \return dhKeySz returns the value held in ssl->options.dhKeySz which is an - integer value. + integer value representing a size in bits. \return BAD_FUNC_ARG returns if the WOLFSSL struct is NULL. \param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). @@ -6899,7 +6935,7 @@ WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short); /*! \ingroup CertsKeys - \brief Sets the minimum allowable key size in bytes for RSA located in the + \brief Sets the minimum allowable key size in bits for RSA located in the WOLFSSL structure. \return SSL_SUCCESS the minimum was set successfully. @@ -6928,7 +6964,7 @@ WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short); /*! \ingroup CertsKeys - \brief Sets the minimum size in bytes for the ECC key in the WOLF_CTX + \brief Sets the minimum size in bits for the ECC key in the WOLF_CTX structure and the WOLFSSL_CERT_MANAGER structure. \return SSL_SUCCESS returned for a successful execution and the minEccKeySz @@ -12743,6 +12779,40 @@ WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); */ WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); +/*! + \ingroup IO + + \brief This function is called on a TLS v1.3 client or server wolfSSL to + determine whether a rollover of keys is in progress. When + wolfSSL_update_keys() is called, a KeyUpdate message is sent and the + encryption key is updated. The decryption key is updated when the response + is received. + + \param [in] ssl a pointer to a WOLFSSL structure, created using wolfSSL_new(). + \param [out] required 0 when no key update response required. 1 when no key update response required. + + \return 0 on successful. + \return BAD_FUNC_ARG if ssl is NULL or not using TLS v1.3. + + _Example_ + \code + int ret; + WOLFSSL* ssl; + int required; + ... + ret = wolfSSL_key_update_response(ssl, &required); + if (ret != 0) { + // bad parameters + } + if (required) { + // encrypt Key updated, awaiting response to change decrypt key + } + \endcode + + \sa wolfSSL_update_keys +*/ +WOLFSSL_API int wolfSSL_key_update_response(WOLFSSL* ssl, int* required); + /*! \ingroup Setup @@ -13735,6 +13805,7 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method(void); \param key key file path (if keySz == 0) or actual key buffer (PEM or ASN.1) \param keySz key size (should be 0 for "key" arg is file path) \param format WOLFSSL_FILETYPE_ASN1 or WOLFSSL_FILETYPE_PEM + \sa wolfSSL_CTX_get_ephemeral_key */ WOLFSSL_API int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, const char* key, unsigned int keySz, int format); @@ -13747,9 +13818,36 @@ WOLFSSL_API int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, con \param key key file path (if keySz == 0) or actual key buffer (PEM or ASN.1) \param keySz key size (should be 0 for "key" arg is file path) \param format WOLFSSL_FILETYPE_ASN1 or WOLFSSL_FILETYPE_PEM + \sa wolfSSL_get_ephemeral_key */ WOLFSSL_API int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, const char* key, unsigned int keySz, int format); +/*! + \ingroup SSL + \brief This function returns pointer to loaded key as ASN.1/DER + \return 0 Key returned successfully + \param ctx A WOLFSSL_CTX context pointer + \param keyAlgo enum wc_PkType like WC_PK_TYPE_DH and WC_PK_TYPE_ECDH + \param key key buffer pointer + \param keySz key size pointer + \sa wolfSSL_CTX_set_ephemeral_key + */ +WOLFSSL_API int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const unsigned char** key, unsigned int* keySz); + +/*! + \ingroup SSL + \brief This function returns pointer to loaded key as ASN.1/DER + \return 0 Key returned successfully + \param ssl A WOLFSSL object pointer + \param keyAlgo enum wc_PkType like WC_PK_TYPE_DH and WC_PK_TYPE_ECDH + \param key key buffer pointer + \param keySz key size pointer + \sa wolfSSL_set_ephemeral_key + */ +WOLFSSL_API int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const unsigned char** key, unsigned int* keySz); + /*! \ingroup SSL \brief Sign a message with the chosen message digest, padding, and RSA key diff --git a/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index f130f28d1..fcbdd6659 100644 --- a/examples/benchmark/tls_bench.c +++ b/examples/benchmark/tls_bench.c @@ -1,6 +1,6 @@ /* tls_bench.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -42,7 +42,7 @@ bench_tls(args); #include #include /* WC_MAX_DIGEST_SIZE */ #include - +#include #include /* force certificate test buffers to be included via headers */ @@ -121,13 +121,13 @@ bench_tls(args); #define SHOW_VERBOSE 0 /* Default output is tab delimited format */ #if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ - !defined(WOLFCRYPT_ONLY) + !defined(WOLFCRYPT_ONLY) && defined(USE_WOLFSSL_IO) /* shutdown message - nice signal to server, we are done */ static const char* kShutdown = "shutdown"; #ifndef NO_WOLFSSL_CLIENT -static const char* kTestStr = +PEDANTIC_EXTENSION static const char* kTestStr = "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n" "polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n" "marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n" @@ -1930,7 +1930,7 @@ exit: return ret; } -#endif /* (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) && !WOLFCRYPT_ONLY */ +#endif /* (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) && !WOLFCRYPT_ONLY && USE_WOLFSSL_IO */ #ifndef NO_MAIN_DRIVER @@ -1942,7 +1942,8 @@ int main(int argc, char** argv) args.argv = argv; args.return_code = 0; -#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && !defined(WOLFCRYPT_ONLY) +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ + !defined(WOLFCRYPT_ONLY) && defined(USE_WOLFSSL_IO) bench_tls(&args); #endif diff --git a/examples/benchmark/tls_bench.h b/examples/benchmark/tls_bench.h index 483a3ae4f..62e0ba1b5 100644 --- a/examples/benchmark/tls_bench.h +++ b/examples/benchmark/tls_bench.h @@ -1,6 +1,6 @@ /* tls_bench.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/client/client.c b/examples/client/client.c index 79aece83e..f9376c278 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1,6 +1,6 @@ /* client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - #ifdef HAVE_CONFIG_H #include #endif @@ -274,8 +273,9 @@ static void ShowVersions(void) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #define MAX_GROUP_NUMBER 4 static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, - int useX448) + int useX448, int setGroups) { + int ret; int groups[MAX_GROUP_NUMBER] = {0}; int count = 0; @@ -284,49 +284,78 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); if (onlyKeyShare == 0 || onlyKeyShare == 2) { - #ifdef HAVE_CURVE25519 if (useX25519) { - groups[count++] = WOLFSSL_ECC_X25519; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) - err_sys("unable to use curve x25519"); - } - else + #ifdef HAVE_CURVE25519 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X25519; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x25519"); + } while (ret == WC_PENDING_E); #endif + } + else if (useX448) { #ifdef HAVE_CURVE448 - if (useX448) { - groups[count++] = WOLFSSL_ECC_X448; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) != WOLFSSL_SUCCESS) - err_sys("unable to use curve x448"); - } - else + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X448; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x448"); + } while (ret == WC_PENDING_E); #endif - { + } + else { #ifdef HAVE_ECC #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - groups[count++] = WOLFSSL_ECC_SECP256R1; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_SECP256R1; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve secp256r1"); + } while (ret == WC_PENDING_E); #endif #endif } } if (onlyKeyShare == 0 || onlyKeyShare == 1) { #ifdef HAVE_FFDHE_2048 - groups[count++] = WOLFSSL_FFDHE_2048; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) - err_sys("unable to use DH 2048-bit parameters"); + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_FFDHE_2048; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use DH 2048-bit parameters"); + } while (ret == WC_PENDING_E); #endif } - if (count >= MAX_GROUP_NUMBER) err_sys("example group array size error"); - if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) - err_sys("unable to set groups"); + if (setGroups && count > 0) { + if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) + err_sys("unable to set groups"); + } WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); } -#endif +#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */ #ifdef WOLFSSL_EARLY_DATA static void EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg, @@ -444,7 +473,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) else if (version >= 4) { if (!helloRetry) - SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); else wolfSSL_NoKeyShares(ssl); } @@ -466,6 +495,9 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, do { err = 0; /* reset error */ ret = wolfSSL_connect(ssl); +#ifdef WOLFSSL_EARLY_DATA + EarlyDataStatus(ssl); +#endif if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); #ifdef WOLFSSL_ASYNC_CRYPT @@ -525,7 +557,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in mbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519, - int useX448, int exitWithRet) + int useX448, int exitWithRet, int version, int onlyKeyShare) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -544,24 +576,13 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, (void)useX25519; (void)useX448; - #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) - #ifdef HAVE_CURVE25519 - if (useX25519) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - } - #endif - #ifdef HAVE_CURVE448 - if (useX448) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x448"); - } - } - #endif - #endif + (void)version; + (void)onlyKeyShare; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) + if (version >= 4) { + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); + } +#endif do { err = 0; /* reset error */ @@ -946,7 +967,7 @@ static int ClientRead(WOLFSSL* ssl, char* reply, int replyLen, int mustRead, /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* client_usage_msg[][66] = { +static const char* client_usage_msg[][67] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -1117,8 +1138,15 @@ static const char* client_usage_msg[][66] = { #ifdef HAVE_CURVE448 "-8 Use X448 for key exchange\n", /* 66 */ #endif -#ifdef HAVE_CRL - "-C Disable CRL\n", +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 Use hash dir look up for certificate loading\n" + " loading from /certs folder\n" + " files in the folder would have the form \"hash.N\" file name\n" + " e.g symbolic link to the file at certs folder\n" + " ln -s ca-cert.pem `openssl x509 -in ca-cert.pem -hash -noout`.0\n", + /* 67 */ #endif NULL, }, @@ -1291,8 +1319,19 @@ static const char* client_usage_msg[][66] = { #ifdef HAVE_TRUSTED_CA "-5 信頼できる認証局の鍵表示を使用する\n", /* 63 */ #endif + "-6 WANT_WRITE エラーを全てのIO 送信でシュミレートします\n", #ifdef HAVE_CURVE448 "-8 Use X448 for key exchange\n", /* 66 */ +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 証明書の読み込みに hash dir 機能を使用する\n" + " /certs フォルダーからロードします\n" + " フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n" + " 以下の例ではca-cert.pemにシンボリックリンクを設定します\n" + " ln -s ca-cert.pem `openssl x509 -in ca-cert.pem -hash -noout`.0\n", + /* 67 */ #endif NULL, }, @@ -1462,9 +1501,15 @@ static void Usage(void) #ifdef HAVE_TRUSTED_CA printf("%s", msg[++msgid]); /* -5 */ #endif + printf("%s", msg[++msgid]); /* -6 */ #ifdef HAVE_CURVE448 printf("%s", msg[++msgid]); /* -8 */ #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + printf("%s", msg[++msgid]); /* -9 */ +#endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -1494,6 +1539,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int ch; #endif int version = CLIENT_INVALID_VERSION; + int minVersion = CLIENT_INVALID_VERSION; + int setMinVersion = 0; int usePsk = 0; int useAnon = 0; int sendGET = 0; @@ -1502,6 +1549,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) size_t throughput = 0; int doDTLS = 0; int dtlsUDP = 0; +#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + int dtlsMTU = 0; +#endif int dtlsSCTP = 0; int doMcast = 0; int matchName = 0; @@ -1598,6 +1649,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + int useCertFolder = 0; #endif char buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -1681,9 +1737,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS /* Not used: All used */ while ((ch = mygetopt(argc, argv, "?:" - "ab:c:defgh:i;jk:l:mnop:q:rstuv:wxyz" + "ab:c:defgh:i;jk:l:mnop:q:rstu;v:wxyz" "A:B:CDE:F:GH:IJKL:M:NO:PQRS:TUVW:XYZ:" - "01:23:4568" + "01:23:4567:89" "@#")) != -1) { switch (ch) { case '?' : @@ -1721,6 +1777,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case 'u' : doDTLS = 1; dtlsUDP = 1; + #if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + dtlsMTU = atoi(myoptarg); + #endif break; case 'G' : @@ -2146,7 +2206,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) nonBlocking = 1; simulateWantWrite = 1; break; - + case '7' : + setMinVersion = 1; + minVersion = atoi(myoptarg); + if (minVersion < 0 || minVersion > 4) { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + break; case '8' : #ifdef HAVE_CURVE448 useX448 = 1; @@ -2159,7 +2226,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #endif break; - + case '9' : +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + useCertFolder = 1; + break; +#endif case '@' : { #ifdef HAVE_WC_INTROSPECTION @@ -2420,10 +2493,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("unable to get ctx"); } #endif - - if (simulateWantWrite) - { + if (setMinVersion) { + wolfSSL_CTX_SetMinVersion(ctx, minVersion); + } + if (simulateWantWrite) { + #ifdef USE_WOLFSSL_IO wolfSSL_CTX_SetIOSend(ctx, SimulateWantWriteIOSendCb); + #endif } #ifdef SINGLE_THREADED @@ -2455,6 +2531,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (fewerPackets) wolfSSL_CTX_set_group_messages(ctx); +#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + if (dtlsMTU) + wolfSSL_CTX_dtls_set_mtu(ctx, dtlsMTU); +#endif #ifndef NO_DH if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits) @@ -2468,9 +2549,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) const char *defaultCipherList = cipherList; wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); - #ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_TLS13 + #if !defined(WOLFSSL_PSK_TLS13_CB) && !defined(WOLFSSL_PSK_ONE_ID) + wolfSSL_CTX_set_psk_client_cs_callback(ctx, my_psk_client_cs_cb); + #else wolfSSL_CTX_set_psk_client_tls13_callback(ctx, my_psk_client_tls13_cb); #endif +#endif if (defaultCipherList == NULL) { #if defined(HAVE_AESGCM) && !defined(NO_DH) #ifdef WOLFSSL_TLS13 @@ -2547,7 +2632,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_OCSP if (useOcsp) { - #ifdef HAVE_IO_TIMEOUT + #if defined(HAVE_IO_TIMEOUT) && defined(HAVE_HTTP_CLIENT) wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC); #endif @@ -2581,7 +2666,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef NO_FILESYSTEM if (wolfSSL_CTX_use_certificate_chain_buffer(ctx, client_cert_der_2048, sizeof_client_cert_der_2048) != WOLFSSL_SUCCESS) - err_sys("can't load server cert buffer"); + err_sys("can't load client cert buffer"); #elif !defined(TEST_LOAD_BUFFER) if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != WOLFSSL_SUCCESS) { @@ -2605,7 +2690,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef NO_FILESYSTEM if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, client_key_der_2048, sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) - err_sys("can't load server private key buffer"); + err_sys("can't load client private key buffer"); #elif !defined(TEST_LOAD_BUFFER) if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { @@ -2619,6 +2704,29 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } if (!usePsk && !useAnon && !useVerifyCb && myVerifyAction != VERIFY_FORCE_FAIL) { + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (useCertFolder) { + WOLFSSL_X509_STORE *store; + WOLFSSL_X509_LOOKUP *lookup; + + store = wolfSSL_CTX_get_cert_store(ctx); + if (store == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't get WOLFSSL_X509_STORE"); + } + lookup = wolfSSL_X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't add lookup"); + } + if (wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, caCertFolder, + X509_FILETYPE_PEM, NULL) != WOLFSSL_SUCCESS) { + err_sys("X509_LOOKUP_ctrl w/ L_ADD_DIR failed"); + } + } else { + #endif #ifdef NO_FILESYSTEM if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048, sizeof_ca_cert_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { @@ -2666,6 +2774,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } } #endif /* WOLFSSL_TRUST_PEER_CERT && !NO_FILESYSTEM */ + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + } + #endif } if (useVerifyCb || myVerifyAction == VERIFY_FORCE_FAIL || myVerifyAction == VERIFY_USE_PREVERFIY) { @@ -2684,12 +2797,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_SNI if (sniHostName) { - if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, + if (wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, sniHostName, (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("UseSNI failed"); @@ -2791,7 +2904,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, block, throughput, useX25519, useX448, - exitWithRet); + exitWithRet, version, onlyKeyShare); wolfSSL_CTX_free(ctx); ctx = NULL; if (!exitWithRet) XEXIT_T(EXIT_SUCCESS); @@ -2844,6 +2957,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("unable to get SSL object"); } +#ifndef NO_PSK + if (usePsk) { + #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && defined(TEST_PSK_USE_SESSION) + SSL_set_psk_use_session_callback(ssl, my_psk_use_session_cb); + #endif + } +#endif #ifndef NO_CERTS if (useClientCert && loadCertKeyIntoSSLObj){ @@ -2901,43 +3021,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (!helloRetry && version >= 4) { - #if defined(WOLFSSL_TLS13) && (!defined(NO_DH) || defined(HAVE_ECC) || \ - defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) - if (onlyKeyShare == 0 || onlyKeyShare == 2) { - #ifdef HAVE_CURVE25519 - if (useX25519) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - } - #endif - #ifdef HAVE_CURVE448 - if (useX448) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x448"); - } - } - #endif - #ifdef HAVE_ECC - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } - #endif - #endif - } - if (onlyKeyShare == 0 || onlyKeyShare == 1) { - #ifdef HAVE_FFDHE_2048 - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) - != WOLFSSL_SUCCESS) { - err_sys("unable to use DH 2048-bit parameters"); - } - #endif - } - #endif + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 0); } else { wolfSSL_NoKeyShares(ssl); @@ -3070,7 +3154,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_CRL if (disableCRL == 0 && !useVerifyCb) { - #ifdef HAVE_IO_TIMEOUT + #if defined(HAVE_IO_TIMEOUT) && defined(HAVE_HTTP_CLIENT) wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC); #endif @@ -3171,7 +3255,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) * cipher name, or the requested cipher name is marked as an alias * that matches the established cipher. */ - if (cipherList && (! XSTRSTR(cipherList, ":"))) { + if (cipherList && !useDefCipherList && (! XSTRSTR(cipherList, ":"))) { WOLFSSL_CIPHER* established_cipher = wolfSSL_get_current_cipher(ssl); byte requested_cipherSuite0, requested_cipherSuite; int requested_cipherFlags; @@ -3227,7 +3311,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #endif -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(HAVE_SECRET_CALLBACK) printf("Session timeout set to %ld seconds\n", wolfSSL_get_timeout(ssl)); { byte* rnd; @@ -3263,9 +3347,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); } +#endif - #if defined(OPENSSL_ALL) && !defined(NO_SESSION_CACHE) - +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) +#if !defined(NO_SESSION_CACHE) && \ + (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \ + !defined(NO_FILESYSTEM) #ifndef NO_BIO /* print out session to stdout */ { @@ -3273,13 +3362,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (bio != NULL) { if (wolfSSL_SESSION_print(bio, wolfSSL_get_session(ssl)) != WOLFSSL_SUCCESS) { - wolfSSL_BIO_printf(bio, "ERROR: Unable to print out session\n"); + wolfSSL_BIO_printf(bio, "BIO error printing session\n"); } } wolfSSL_BIO_free(bio); } - #endif - #endif + #endif /* !NO_BIO */ +#endif #endif if (doSTARTTLS && starttlsProt != NULL) { diff --git a/examples/client/client.h b/examples/client/client.h index 72402e99f..bfdfe4144 100644 --- a/examples/client/client.h +++ b/examples/client/client.h @@ -1,6 +1,6 @@ /* client.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/configs/user_settings_all.h b/examples/configs/user_settings_all.h index 905989d85..589a28eca 100644 --- a/examples/configs/user_settings_all.h +++ b/examples/configs/user_settings_all.h @@ -1,6 +1,6 @@ /* user_settings_all.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/configs/user_settings_min_ecc.h b/examples/configs/user_settings_min_ecc.h index 2dcdce2b4..c23e34f1b 100644 --- a/examples/configs/user_settings_min_ecc.h +++ b/examples/configs/user_settings_min_ecc.h @@ -1,6 +1,6 @@ /* user_settings_min_ecc.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -100,8 +100,8 @@ extern "C" { #define WOLFSSL_NO_PEM //#define NO_CODING #define NO_PSK -#ifndef DEBUG - #define DEBGUG_WOLFSSL +#ifndef DEBUG_WOLFSSL + #define DEBUG_WOLFSSL #define NO_ERROR_STRINGS #endif diff --git a/examples/configs/user_settings_wolfboot_keytools.h b/examples/configs/user_settings_wolfboot_keytools.h index 4634c9d2c..230c73245 100644 --- a/examples/configs/user_settings_wolfboot_keytools.h +++ b/examples/configs/user_settings_wolfboot_keytools.h @@ -4,16 +4,16 @@ * Enabled via WOLFSSL_USER_SETTINGS. * * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfBoot. + * This file is part of wolfSSL. * - * wolfBoot is free software; you can redistribute it and/or modify + * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * wolfBoot is distributed in the hope that it will be useful, + * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index c9cdd13ea..105b024e0 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -1,6 +1,6 @@ /* echoclient.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -89,7 +89,7 @@ void echoclient_test(void* args) int argc = 0; char** argv = 0; #endif - word16 port = yasslPort; + word16 port; char buffer[CYASSL_MAX_ERROR_SZ]; ((func_args*)args)->return_code = -1; /* error state */ @@ -126,6 +126,8 @@ void echoclient_test(void* args) #if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_SHELL) port = ((func_args*)args)->signal->port; +#else + port = yasslPort; #endif #if defined(CYASSL_DTLS) @@ -217,7 +219,7 @@ void echoclient_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); diff --git a/examples/echoclient/echoclient.h b/examples/echoclient/echoclient.h index 0aebffbc2..b2b530956 100644 --- a/examples/echoclient/echoclient.h +++ b/examples/echoclient/echoclient.h @@ -1,6 +1,6 @@ /* echoclient.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 1ef3007f8..fc36a26be 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1,6 +1,6 @@ /* echoserver.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -293,7 +293,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ SignalReady(args, port); diff --git a/examples/echoserver/echoserver.h b/examples/echoserver/echoserver.h index 622193f61..40bbfe684 100644 --- a/examples/echoserver/echoserver.h +++ b/examples/echoserver/echoserver.h @@ -1,6 +1,6 @@ /* echoserver.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/sctp/sctp-client-dtls.c b/examples/sctp/sctp-client-dtls.c index c0a222463..8022e50ed 100644 --- a/examples/sctp/sctp-client-dtls.c +++ b/examples/sctp/sctp-client-dtls.c @@ -1,6 +1,6 @@ /* sctp-client-dtls.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/sctp/sctp-client.c b/examples/sctp/sctp-client.c index cb01354d8..9a55cd210 100644 --- a/examples/sctp/sctp-client.c +++ b/examples/sctp/sctp-client.c @@ -1,6 +1,6 @@ /* sctp-client.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/sctp/sctp-server-dtls.c b/examples/sctp/sctp-server-dtls.c index 50a20f241..5d14ca872 100644 --- a/examples/sctp/sctp-server-dtls.c +++ b/examples/sctp/sctp-server-dtls.c @@ -1,6 +1,6 @@ /* sctp-server-dtls.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/sctp/sctp-server.c b/examples/sctp/sctp-server.c index 34b02c9ce..75034caaf 100644 --- a/examples/sctp/sctp-server.c +++ b/examples/sctp/sctp-server.c @@ -1,6 +1,6 @@ /* sctp-server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/server/include.am b/examples/server/include.am index 8a3d75119..9f6fdd8d9 100644 --- a/examples/server/include.am +++ b/examples/server/include.am @@ -7,8 +7,9 @@ if BUILD_EXAMPLE_SERVERS noinst_PROGRAMS += examples/server/server noinst_HEADERS += examples/server/server.h examples_server_server_SOURCES = examples/server/server.c -examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) examples_server_server_DEPENDENCIES = src/libwolfssl.la +examples_server_server_CFLAGS = $(WOLFSENTRY_INCLUDE) $(AM_CFLAGS) endif EXTRA_DIST += examples/server/server.sln EXTRA_DIST += examples/server/server-ntru.vcproj diff --git a/examples/server/server.c b/examples/server/server.c index 05b6f2f54..c6fa74f61 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1,6 +1,6 @@ /* server.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -35,6 +35,10 @@ #include /* wc_ecc_fp_free */ #endif +#ifdef WOLFSSL_WOLFSENTRY_HOOKS +# include +#endif + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include @@ -148,7 +152,7 @@ static void err_sys_ex(int out, const char* msg) } -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO) /* Translates return codes returned from * send() and recv() if need be. @@ -273,9 +277,138 @@ static int TestEmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) return sent; } +#endif /* WOLFSSL_DTLS && USE_WOLFSSL_IO */ -#endif /* WOLFSSL_DTLS */ +#ifdef WOLFSSL_WOLFSENTRY_HOOKS +struct wolfsentry_data { + struct wolfsentry_sockaddr remote; + byte remote_addrbuf[16]; + struct wolfsentry_sockaddr local; + byte local_addrbuf[16]; + wolfsentry_route_flags_t flags; + void *heap; + int alloctype; +}; + +static void free_wolfsentry_data(struct wolfsentry_data *data) { + XFREE(data, data->heap, data->alloctype); +} + +static int wolfsentry_data_index = -1; + +static int wolfsentry_store_endpoints( + WOLFSSL *ssl, + SOCKADDR_IN_T *remote, + SOCKADDR_IN_T *local, + int proto, + wolfsentry_route_flags_t flags) +{ + struct wolfsentry_data *data = (struct wolfsentry_data *)XMALLOC( + sizeof *data, NULL, DYNAMIC_TYPE_SOCKADDR); + if (data == NULL) + return WOLFSSL_FAILURE; + + data->heap = NULL; + data->alloctype = DYNAMIC_TYPE_SOCKADDR; + +#ifdef TEST_IPV6 + if ((sizeof data->remote_addrbuf < sizeof remote->sin6_addr) || + (sizeof data->local_addrbuf < sizeof local->sin6_addr)) + return WOLFSSL_FAILURE; + data->remote.sa_family = data->local.sa_family = remote->sin6_family; + data->remote.sa_port = ntohs(remote->sin6_port); + data->local.sa_port = ntohs(local->sin6_port); + data->remote.addr_len = sizeof remote->sin6_addr * BITS_PER_BYTE; + XMEMCPY(data->remote.addr, &remote->sin6_addr, sizeof remote->sin6_addr); + data->local.addr_len = sizeof local->sin6_addr * BITS_PER_BYTE; + XMEMCPY(data->local.addr, &local->sin6_addr, sizeof local->sin6_addr); +#else + if ((sizeof data->remote_addrbuf < sizeof remote->sin_addr) || + (sizeof data->local_addrbuf < sizeof local->sin_addr)) + return WOLFSSL_FAILURE; + data->remote.sa_family = data->local.sa_family = remote->sin_family; + data->remote.sa_port = ntohs(remote->sin_port); + data->local.sa_port = ntohs(local->sin_port); + data->remote.addr_len = sizeof remote->sin_addr * BITS_PER_BYTE; + XMEMCPY(data->remote.addr, &remote->sin_addr, sizeof remote->sin_addr); + data->local.addr_len = sizeof local->sin_addr * BITS_PER_BYTE; + XMEMCPY(data->local.addr, &local->sin_addr, sizeof local->sin_addr); +#endif + data->remote.sa_proto = data->local.sa_proto = proto; + data->remote.interface = data->local.interface = 0; + data->flags = flags; + + if (wolfSSL_set_ex_data_with_cleanup( + ssl, wolfsentry_data_index, data, + (wolfSSL_ex_data_cleanup_routine_t)free_wolfsentry_data) != + WOLFSSL_SUCCESS) { + free_wolfsentry_data(data); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +static int wolfSentry_NetworkFilterCallback( + WOLFSSL *ssl, + struct wolfsentry_context *wolfsentry, + wolfSSL_netfilter_decision_t *decision) +{ + struct wolfsentry_data *data; + char inet_ntop_buf[INET6_ADDRSTRLEN], inet_ntop_buf2[INET6_ADDRSTRLEN]; + wolfsentry_errcode_t ret; + wolfsentry_action_res_t action_results; + + if ((data = wolfSSL_get_ex_data(ssl, wolfsentry_data_index)) == NULL) + return WOLFSSL_FAILURE; + + ret = wolfsentry_route_event_dispatch( + wolfsentry, + &data->remote, + &data->local, + data->flags, + NULL /* event_label */, + 0 /* event_label_len */, + NULL /* caller_context */, + NULL /* id */, + NULL /* inexact_matches */, + &action_results); + + if (ret >= 0) { + if (WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_REJECT)) + *decision = WOLFSSL_NETFILTER_REJECT; + else if (WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_ACCEPT)) + *decision = WOLFSSL_NETFILTER_ACCEPT; + else + *decision = WOLFSSL_NETFILTER_PASS; + } else { + printf("wolfsentry_route_event_dispatch error " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + *decision = WOLFSSL_NETFILTER_PASS; + } + + printf("wolfSentry got network filter callback: family=%d proto=%d rport=%d" + "lport=%d raddr=%s laddr=%s interface=%d; decision=%d (%s)\n", + data->remote.sa_family, + data->remote.sa_proto, + data->remote.sa_port, + data->local.sa_port, + inet_ntop(data->remote.sa_family, data->remote.addr, inet_ntop_buf, + sizeof inet_ntop_buf), + inet_ntop(data->local.sa_family, data->local.addr, inet_ntop_buf2, + sizeof inet_ntop_buf2), + data->remote.interface, + *decision, + *decision == WOLFSSL_NETFILTER_REJECT ? "REJECT" : + *decision == WOLFSSL_NETFILTER_ACCEPT ? "ACCEPT" : + *decision == WOLFSSL_NETFILTER_PASS ? "PASS" : + "???"); + + return WOLFSSL_SUCCESS; +} + +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ static int NonBlockingSSL_Accept(SSL* ssl) { @@ -575,6 +708,95 @@ static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen) err_sys_ex(runWithErrors, "SSL_write failed"); } } + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) +#define MAX_GROUP_NUMBER 4 +static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, + int useX448) +{ + int ret; + int groups[MAX_GROUP_NUMBER] = {0}; + int count = 0; + + (void)useX25519; + (void)useX448; + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + if (onlyKeyShare == 2) { + if (useX25519) { + #ifdef HAVE_CURVE25519 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X25519; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x25519"); + } while (ret == WC_PENDING_E); + #endif + } + else if (useX448) { + #ifdef HAVE_CURVE448 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X448; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x448"); + } while (ret == WC_PENDING_E); + #endif + } + else { + #ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_SECP256R1; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve secp256r1"); + } while (ret == WC_PENDING_E); + #endif + #endif + } + } + if (onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_FFDHE_2048; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use DH 2048-bit parameters"); + } while (ret == WC_PENDING_E); + #endif + } + if (count >= MAX_GROUP_NUMBER) + err_sys("example group array size error"); + if (count > 0) { + if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) + err_sys("unable to set groups"); + } + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); +} +#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */ + + /* when adding new option, please follow the steps below: */ /* 1. add new option message in English section */ /* 2. increase the number of the second column */ @@ -582,7 +804,7 @@ static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen) /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* server_usage_msg[][56] = { +static const char* server_usage_msg[][57] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -705,6 +927,16 @@ static const char* server_usage_msg[][56] = { /* 55 */ #ifdef HAVE_CURVE448 "-8 Pre-generate Key share using Curve448 only\n", /* 56 */ +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 Use hash dir look up for certificate loading\n" + " loading from /certs folder\n" + " files in the folder would have the form \"hash.N\" file name\n" + " e.g symbolic link to the file at certs folder\n" + " ln -s client-ca.pem `openssl x509 -in client-ca.pem -hash -noout`.0\n", + /* 57 */ #endif NULL, }, @@ -838,6 +1070,16 @@ static const char* server_usage_msg[][56] = { /* 55 */ #ifdef HAVE_CURVE448 "-8 Pre-generate Key share using Curve448 only\n", /* 56 */ +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 証明書の読み込みに hash dir 機能を使用する\n" + " /certs フォルダーからロードします\n" + " フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n" + " 以下の例ではca-cert.pemにシンボリックリンクを設定します\n" + " ln -s client-ca.pem `openssl x509 -in client-ca.pem -hash -noout`.0\n", + /* 57 */ #endif NULL, }, @@ -966,19 +1208,31 @@ static void Usage(void) #ifdef HAVE_TRUSTED_CA printf("%s", msg[++msgId]); /* -5 */ #endif /* HAVE_TRUSTED_CA */ + printf("%s", msg[++msgId]); /* -6 */ #ifdef HAVE_CURVE448 printf("%s", msg[++msgId]); /* -8 */ #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + printf("%s", msg[++msgId]); /* -9 */ +#endif } THREAD_RETURN WOLFSSL_THREAD server_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + SOCKADDR_IN_T client_addr; + socklen_t client_len; wolfSSL_method_func method = NULL; SSL_CTX* ctx = 0; SSL* ssl = 0; +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + struct wolfsentry_context *wolfsentry = NULL; + wolfsentry_errcode_t wolfsentry_ret; +#endif int useWebServerMsg = 0; char input[SRV_READ_SZ]; @@ -1001,9 +1255,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) int useAnon = 0; int doDTLS = 0; int dtlsUDP = 0; +#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + int dtlsMTU = 0; +#endif int dtlsSCTP = 0; int doMcast = 0; -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO) int doBlockSeq = 0; WOLFSSL_TEST_DTLS_CTX dtlsCtx; #endif @@ -1126,6 +1384,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef HAVE_ENCRYPT_THEN_MAC int disallowETM = 0; #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + int useCertFolder = 0; +#endif ((func_args*)args)->return_code = -1; /* error state */ @@ -1189,10 +1452,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) /* Not Used: h, z, W, X, 7, 9 */ while ((ch = mygetopt(argc, argv, "?:" - "abc:defgijk:l:mnop:q:rstuv:wxy" + "abc:defgijk:l:mnop:q:rstu;v:wxy" "A:B:C:D:E:FGH:IJKL:MNO:PQR:S:T;UVYZ:" - "01:23:4:568" - "@#")) != -1) { + "01:23:4:5689" + "@#")) != -1) { switch (ch) { case '?' : if(myoptarg!=NULL) { @@ -1237,6 +1500,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) case 'u' : doDTLS = 1; dtlsUDP = 1; + #if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + dtlsMTU = atoi(myoptarg); + #endif break; case 'G' : @@ -1594,7 +1861,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) break; case '4' : - #ifdef WOLFSSL_DTLS + #if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO) XMEMSET(&dtlsCtx, 0, sizeof(dtlsCtx)); doBlockSeq = 1; dtlsCtx.blockSeq = atoi(myoptarg); @@ -1620,7 +1887,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif #endif break; - + case '9' : +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + useCertFolder = 1; + break; +#endif case '@' : { #ifdef HAVE_WC_INTROSPECTION @@ -1795,9 +2068,94 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (ctx == NULL) err_sys_ex(catastrophic, "unable to get ctx"); +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + wolfsentry_ret = wolfsentry_init(NULL /* hpi */, NULL /* default config */, + &wolfsentry); + if (wolfsentry_ret < 0) { + fprintf(stderr, "wolfsentry_init() returned " WOLFSENTRY_ERROR_FMT "\n", + WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret)); + err_sys_ex(catastrophic, "unable to initialize wolfSentry"); + } + + if (wolfsentry_data_index < 0) + wolfsentry_data_index = wolfSSL_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + + { + struct wolfsentry_route_table *table; + + if ((wolfsentry_ret = wolfsentry_route_get_table_static(wolfsentry, + &table)) < 0) + fprintf(stderr, "wolfsentry_route_get_table_static() returned " + WOLFSENTRY_ERROR_FMT "\n", + WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret)); + if (wolfsentry_ret >= 0) { + if ((wolfsentry_ret = wolfsentry_route_table_default_policy_set( + wolfsentry, table, + WOLFSENTRY_ACTION_RES_REJECT|WOLFSENTRY_ACTION_RES_STOP)) + < 0) + fprintf(stderr, + "wolfsentry_route_table_default_policy_set() returned " + WOLFSENTRY_ERROR_FMT "\n", + WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret)); + } + + if (wolfsentry_ret >= 0) { + struct { + struct wolfsentry_sockaddr sa; + byte buf[16]; + } remote, local; + wolfsentry_ent_id_t id; + wolfsentry_action_res_t action_results; + + memset(&remote, 0, sizeof remote); + memset(&local, 0, sizeof local); +#ifdef TEST_IPV6 + remote.sa.sa_family = local.sa.sa_family = AF_INET6; + remote.sa.addr_len = 128; + memcpy(remote.sa.addr, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", 16); +#else + remote.sa.sa_family = local.sa.sa_family = AF_INET; + remote.sa.addr_len = 32; + memcpy(remote.sa.addr, "\177\000\000\001", 4); +#endif + + if ((wolfsentry_ret = wolfsentry_route_insert_static + (wolfsentry, NULL /* caller_context */, &remote.sa, &local.sa, + WOLFSENTRY_ROUTE_FLAG_GREENLISTED | + WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_TRIGGER_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_REMOTE_INTERFACE_WILDCARD| + WOLFSENTRY_ROUTE_FLAG_LOCAL_INTERFACE_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_LOCAL_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_PROTO_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_LOCAL_PORT_WILDCARD, + 0 /* event_label_len */, 0 /* event_label */, &id, + &action_results)) < 0) + fprintf(stderr, "wolfsentry_route_insert_static() returned " + WOLFSENTRY_ERROR_FMT "\n", + WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret)); + } + + if (wolfsentry_ret < 0) + err_sys_ex(catastrophic, "unable to configure route table"); + } + + + if (wolfSSL_CTX_set_AcceptFilter( + ctx, + (NetworkFilterCallback_t)wolfSentry_NetworkFilterCallback, + wolfsentry) < 0) + err_sys_ex(catastrophic, + "unable to install wolfSentry_NetworkFilterCallback"); +#endif + if (simulateWantWrite) { + #ifdef USE_WOLFSSL_IO wolfSSL_CTX_SetIOSend(ctx, SimulateWantWriteIOSendCb); + #endif } #if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ @@ -1817,6 +2175,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (ret != 0) { err_sys_ex(runWithErrors, "error loading static ECDH key"); } + { + const byte* key = NULL; + word32 keySz = 0; + /* example for getting pointer to loaded static ephemeral key */ + wolfSSL_CTX_get_ephemeral_key(ctx, WC_PK_TYPE_ECDH, &key, &keySz); + (void)key; + (void)keySz; + } #endif #ifndef NO_DH ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_DH, @@ -1847,6 +2213,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (fewerPackets) wolfSSL_CTX_set_group_messages(ctx); +#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + if (dtlsMTU) + wolfSSL_CTX_dtls_set_mtu(ctx, dtlsMTU); +#endif #ifdef WOLFSSL_SCTP if (dtlsSCTP) @@ -2011,7 +2382,29 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef TEST_BEFORE_DATE verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; #endif - + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (useCertFolder) { + WOLFSSL_X509_STORE *store; + WOLFSSL_X509_LOOKUP *lookup; + + store = wolfSSL_CTX_get_cert_store(ctx); + if (store == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't get WOLFSSL_X509_STORE"); + } + lookup = wolfSSL_X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't add lookup"); + } + if (wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, caCertFolder, + X509_FILETYPE_PEM, NULL) != WOLFSSL_SUCCESS) { + err_sys("X509_LOOKUP_ctrl w/ L_ADD_DIR failed"); + } + } else { + #endif if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags) != WOLFSSL_SUCCESS) { err_sys_ex(catastrophic, @@ -2026,6 +2419,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } } #endif /* WOLFSSL_TRUST_PEER_CERT */ + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + } + #endif } #endif @@ -2058,7 +2456,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_TLS13 @@ -2080,9 +2478,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) /* allow resume option */ if (resumeCount > 1) { if (dtlsUDP == 0) { - SOCKADDR_IN_T client; - socklen_t client_len = sizeof(client); - clientfd = accept(sockfd, (struct sockaddr*)&client, + client_len = sizeof client_addr; + clientfd = accept(sockfd, (struct sockaddr*)&client_addr, (ACCEPT_THIRD_T)&client_len); } else { @@ -2111,7 +2508,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } if (doDTLS && dtlsUDP) { -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO) if (doBlockSeq) { wolfSSL_CTX_SetIOSend(ctx, TestEmbedSendTo); } @@ -2319,64 +2716,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_TLS13 if (version >= 4) { - WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); - if (onlyKeyShare == 2) { - if (useX25519 == 1) { - #ifdef HAVE_CURVE25519 - int groups[1] = { WOLFSSL_ECC_X25519 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: x25519"); - } - #endif - } - else if (useX448 == 1) { - #ifdef HAVE_CURVE448 - int groups[1] = { WOLFSSL_ECC_X448 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x448"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: x448"); - } - #endif - } - else { - #ifdef HAVE_ECC - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - int groups[1] = { WOLFSSL_ECC_SECP256R1 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: secp256r1"); - } - #endif - #endif - } - } - else if (onlyKeyShare == 1) { - #ifdef HAVE_FFDHE_2048 - int groups[1] = { WOLFSSL_FFDHE_2048 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) - != WOLFSSL_SUCCESS) { - err_sys("unable to use DH 2048-bit parameters"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: DH 2048-bit"); - } - #endif - } - WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); } #endif @@ -2391,8 +2731,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (readySignal) { readySignal->srfName = serverReadyFile; } + + client_len = sizeof client_addr; tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, - dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen); + dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen, + &client_addr, &client_len); + doListen = 0; /* Don't listen next time */ if (port == 0) { @@ -2419,34 +2763,56 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } #endif -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO) if (doDTLS && dtlsUDP) { - SOCKADDR_IN_T cliaddr; byte b[1500]; int n; - socklen_t len = sizeof(cliaddr); + + client_len = sizeof client_addr; /* For DTLS, peek at the next datagram so we can get the client's * address and set it into the ssl object later to generate the * cookie. */ n = (int)recvfrom(clientfd, (char*)b, sizeof(b), MSG_PEEK, - (struct sockaddr*)&cliaddr, &len); + (struct sockaddr*)&client_addr, &client_len); if (n <= 0) err_sys_ex(runWithErrors, "recvfrom failed"); if (doBlockSeq) { - XMEMCPY(&dtlsCtx.peer.sa, &cliaddr, len); - dtlsCtx.peer.sz = len; + XMEMCPY(&dtlsCtx.peer.sa, &client_addr, client_len); + dtlsCtx.peer.sz = client_len; dtlsCtx.wfd = clientfd; dtlsCtx.failOnce = 1; wolfSSL_SetIOWriteCtx(ssl, &dtlsCtx); } else { - wolfSSL_dtls_set_peer(ssl, &cliaddr, len); + wolfSSL_dtls_set_peer(ssl, &client_addr, client_len); } } #endif + +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + { + SOCKADDR_IN_T local_addr; + socklen_t local_len = sizeof(local_addr); + getsockname(clientfd, (struct sockaddr *)&local_addr, + (socklen_t *)&local_len); + + if (((struct sockaddr *)&client_addr)->sa_family != + ((struct sockaddr *)&local_addr)->sa_family) + err_sys_ex(catastrophic, + "client_addr.sa_family != local_addr.sa_family"); + + if (wolfsentry_store_endpoints( + ssl, &client_addr, &local_addr, + dtlsUDP ? IPPROTO_UDP : IPPROTO_TCP, + WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN) != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, + "error in wolfsentry_store_endpoints()"); + } +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL || needDH == 1) { #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) @@ -2501,6 +2867,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) do { err = 0; /* reset error */ ret = SSL_accept(ssl); +#ifdef WOLFSSL_EARLY_DATA + EarlyDataStatus(ssl); +#endif if (ret != WOLFSSL_SUCCESS) { err = SSL_get_error(ssl, 0); #ifdef WOLFSSL_ASYNC_CRYPT @@ -2542,7 +2911,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) * cipher name, or the requested cipher name is marked as an alias * that matches the established cipher. */ - if (cipherList && (! XSTRSTR(cipherList, ":"))) { + if (cipherList && !useDefCipherList && (! XSTRSTR(cipherList, ":"))) { WOLFSSL_CIPHER* established_cipher = wolfSSL_get_current_cipher(ssl); byte requested_cipherSuite0, requested_cipherSuite; int requested_cipherFlags; @@ -2581,7 +2950,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } } -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(HAVE_SECRET_CALLBACK) { byte* rnd = NULL; byte* pt; @@ -2825,6 +3194,15 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) exit: +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + wolfsentry_ret = wolfsentry_shutdown(&wolfsentry); + if (wolfsentry_ret < 0) { + fprintf(stderr, + "wolfsentry_shutdown() returned " WOLFSENTRY_ERROR_FMT "\n", + WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret)); + } +#endif + #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) wc_ecc_fp_free(); /* free per thread cache */ diff --git a/examples/server/server.h b/examples/server/server.h index 91927c7ea..45b5d5c1f 100644 --- a/examples/server/server.h +++ b/examples/server/server.h @@ -1,6 +1,6 @@ /* server.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/gencertbuf.pl b/gencertbuf.pl index 6b71fffad..d709bb7c8 100755 --- a/gencertbuf.pl +++ b/gencertbuf.pl @@ -67,6 +67,8 @@ my @fileList_2048 = ( [ "./certs/client-keyPub.der", "client_keypub_der_2048" ], [ "./certs/client-cert.der", "client_cert_der_2048" ], [ "./certs/dh2048.der", "dh_key_der_2048" ], + [ "./certs/dh-pubkey-2048.der", "dh_pub_key_der_2048" ], + [ "./certs/dsa-pubkey-2048.der", "dsa_pub_key_der_2048" ], [ "./certs/dsa2048.der", "dsa_key_der_2048" ], [ "./certs/rsa2048.der", "rsa_key_der_2048" ], [ "./certs/ca-key.der", "ca_key_der_2048" ], diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index 5909a1e2a..0fd689119 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -1,6 +1,6 @@ # Linux kernel-native Makefile ("Kbuild") for libwolfssl.ko # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +#/ SHELL=/bin/bash diff --git a/linuxkm/Makefile b/linuxkm/Makefile index 6293cfcf2..c0b5aaf09 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -1,6 +1,6 @@ # libwolfssl Linux kernel module Makefile (wraps Kbuild-native makefile) # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +#/ SHELL=/bin/bash diff --git a/linuxkm/get_thread_size.c b/linuxkm/get_thread_size.c index a3d4caac6..d475c8857 100644 --- a/linuxkm/get_thread_size.c +++ b/linuxkm/get_thread_size.c @@ -1,7 +1,7 @@ /* get_thread_size.c -- trivial program to determine stack frame size * for a Linux kernel thread, given a configured source tree. * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/linuxkm/module_exports.c.template b/linuxkm/module_exports.c.template index a78b7e281..aaa2f536a 100644 --- a/linuxkm/module_exports.c.template +++ b/linuxkm/module_exports.c.template @@ -1,7 +1,7 @@ /* module_exports.c.template -- static preamble for dynamically generated * module_exports.c (see Kbuild) * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 9bc8cb80a..bf31f8b11 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -1,6 +1,6 @@ /* module_hooks.c -- module load/unload hooks for libwolfssl.ko * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/m4/ax_linuxkm.m4 b/m4/ax_linuxkm.m4 index 6bba14254..f89ed5dab 100644 --- a/m4/ax_linuxkm.m4 +++ b/m4/ax_linuxkm.m4 @@ -1,6 +1,6 @@ # ax_linuxkm.m4 -- macros for getting attributes of default configured kernel # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +#/ AC_DEFUN([AC_PATH_DEFAULT_KERNEL_SOURCE], [ @@ -140,7 +141,7 @@ AC_DEFUN([AX_SIMD_CC_COMPILER_FLAGS], [ ;; *) - AC_MSG_ERROR(["Don\'t know how to construct assembler flags for target \"${host_cpu}\"."]) + AC_MSG_ERROR([Don't know how to construct assembler flags for target "${host_cpu}".]) ;; esac diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 index ada7071f2..e5858e50c 100644 --- a/m4/ax_pthread.m4 +++ b/m4/ax_pthread.m4 @@ -14,20 +14,24 @@ # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # -# Also sets PTHREAD_CC to any special C compiler that is needed for -# multi-threaded programs (defaults to the value of CC otherwise). (This -# is necessary on AIX to use the special cc_r compiler alias.) +# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is +# needed for multi-threaded programs (defaults to the value of CC +# respectively CXX otherwise). (This is necessary on e.g. AIX to use the +# special cc_r/CC_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" +# CXX="$PTHREAD_CXX" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to @@ -55,6 +59,7 @@ # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. +# Copyright (c) 2019 Marc Stevens # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -82,11 +87,11 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 24 +#serial 30 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_CANONICAL_TARGET]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) @@ -104,6 +109,7 @@ if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) @@ -123,10 +129,12 @@ fi # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. +# Create a list of thread flags to try. Items with a "," contain both +# C compiler flags (before ",") and linker flags (after ","). Other items +# starting with a "-" are C compiler flags, and remaining items are +# library names, except for "none" which indicates that we try without +# any flags at all, and "pthread-config" which is a program returning +# the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" @@ -150,7 +158,7 @@ ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread -- # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case $host_os in +case $target_os in freebsd*) @@ -194,36 +202,10 @@ case $host_os in # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). - ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" ;; esac -# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) - -AS_IF([test "x$GCC" = "xyes"], - [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) - -# The presence of a feature test macro requesting re-entrant function -# definitions is, on some systems, a strong hint that pthreads support is -# correctly enabled - -case $host_os in - darwin* | hpux* | linux* | osf* | solaris*) - ax_pthread_check_macro="_REENTRANT" - ;; - - aix*) - ax_pthread_check_macro="_THREAD_SAFE" - ;; - - *) - ax_pthread_check_macro="--" - ;; -esac -AS_IF([test "x$ax_pthread_check_macro" = "x--"], - [ax_pthread_check_cond=0], - [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) - # Are we compiling with Clang? AC_CACHE_CHECK([whether $CC is Clang], @@ -242,83 +224,47 @@ AC_CACHE_CHECK([whether $CC is Clang], ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" -ax_pthread_clang_warning=no -# Clang needs special handling, because older versions handle the -pthread -# option in a rather... idiosyncratic way +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) -if test "x$ax_pthread_clang" = "xyes"; then +# Note that for GCC and Clang -pthread generally implies -lpthread, +# except when -nostdlib is passed. +# This is problematic using libtool to build C++ shared libraries with pthread: +# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 +# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 +# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 +# To solve this, first try -pthread together with -lpthread for GCC - # Clang takes -pthread; it has never supported any other flag +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) - # (Note 1: This will need to be revisited if a system that Clang - # supports has POSIX threads in a separate library. This tends not - # to be the way of modern systems, but it's conceivable.) +# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first - # (Note 2: On some systems, notably Darwin, -pthread is not needed - # to get POSIX threads support; the API is always present and - # active. We could reasonably leave PTHREAD_CFLAGS empty. But - # -pthread does define _REENTRANT, and while the Darwin headers - # ignore this macro, third-party headers might not.) +AS_IF([test "x$ax_pthread_clang" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread"]) - PTHREAD_CFLAGS="-pthread" - PTHREAD_LIBS= - ax_pthread_ok=yes +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled - # However, older versions of Clang make a point of warning the user - # that, in an invocation where only linking and no compilation is - # taking place, the -pthread option has no effect ("argument unused - # during compilation"). They expect -pthread to be passed in only - # when source code is being compiled. - # - # Problem is, this is at odds with the way Automake and most other - # C build frameworks function, which is that the same flags used in - # compilation (CFLAGS) are also used in linking. Many systems - # supported by AX_PTHREAD require exactly this for POSIX threads - # support, and in fact it is often not straightforward to specify a - # flag that is used only in the compilation phase and not in - # linking. Such a scenario is extremely rare in practice. - # - # Even though use of the -pthread flag in linking would only print - # a warning, this can be a nuisance for well-run software projects - # that build with -Werror. So if the active version of Clang has - # this misfeature, we search for an option to squash it. +case $target_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; - AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown - # Create an alternate version of $ac_link that compiles and - # links in two steps (.c -> .o, .o -> exe) instead of one - # (.c -> exe), because the warning occurs only in the second - # step - ax_pthread_save_ac_link="$ac_link" - ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' - ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` - ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" - ax_pthread_save_CFLAGS="$CFLAGS" - for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do - AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) - CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" - ac_link="$ax_pthread_save_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [ac_link="$ax_pthread_2step_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [break]) - ]) - done - ac_link="$ax_pthread_save_ac_link" - CFLAGS="$ax_pthread_save_CFLAGS" - AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) - ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" - ]) + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; - case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in - no | unknown) ;; - *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; - esac + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) -fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do @@ -328,10 +274,10 @@ for ax_pthread_try_flag in $ax_pthread_flags; do AC_MSG_CHECKING([whether pthreads work without any flags]) ;; - -mt,pthread) - AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) - PTHREAD_CFLAGS="-mt" - PTHREAD_LIBS="-lpthread" + *,*) + PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` + PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` + AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) ;; -*) @@ -368,10 +314,16 @@ for ax_pthread_try_flag in $ax_pthread_flags; do # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include -dnl# if $ax_pthread_check_cond -dnl# error "$ax_pthread_check_macro must be defined" -dnl# endif - static void routine(void *a) { a = 0; } +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); @@ -393,6 +345,80 @@ dnl# endif done fi + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + + + # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" @@ -424,7 +450,7 @@ if test "x$ax_pthread_ok" = "xyes"; then AC_CACHE_CHECK([whether more special flags are required for pthreads], [ax_cv_PTHREAD_SPECIAL_FLAGS], [ax_cv_PTHREAD_SPECIAL_FLAGS=no - case $host_os in + case $target_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; @@ -438,7 +464,8 @@ if test "x$ax_pthread_ok" = "xyes"; then AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], + [[int i = PTHREAD_PRIO_INHERIT; + return i;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) @@ -453,25 +480,35 @@ if test "x$ax_pthread_ok" = "xyes"; then # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then - case $host_os in + case $target_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + [ + AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) + AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) + ], + [ + AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) + AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) + ] + ) + ]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" +test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) +AC_SUBST([PTHREAD_CXX]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then diff --git a/m4/ax_tls.m4 b/m4/ax_tls.m4 index 3f6b5e10b..deba1feb6 100644 --- a/m4/ax_tls.m4 +++ b/m4/ax_tls.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_tls.html +# https://www.gnu.org/software/autoconf-archive/ax_tls.html # =========================================================================== # # SYNOPSIS @@ -9,9 +9,9 @@ # DESCRIPTION # # Provides a test for the compiler support of thread local storage (TLS) -# extensions. Defines TLS if it is found. Currently knows about GCC/ICC -# and MSVC. I think SunPro uses the same as GCC, and Borland apparently -# supports either. +# extensions. Defines TLS if it is found. Currently knows about C++11, +# GCC/ICC, and MSVC. I think SunPro uses the same as GCC, and Borland +# apparently supports either. # # LICENSE # @@ -29,7 +29,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -44,7 +44,7 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 11 +#serial 15 # Define m4_ifblank and m4_ifnblank macros from introduced in # autotools 2.64 m4sugar.m4 if using an earlier autotools. @@ -55,7 +55,6 @@ ifdef([m4_ifblank], [], [ ]), [], [$2], [$3])]) ]) - ifdef([m4_ifnblank], [], [ m4_define([m4_ifnblank], [m4_if(m4_translit([[$1]], [ ][ ][ @@ -63,30 +62,25 @@ ifdef([m4_ifnblank], [], [ ]) AC_DEFUN([AX_TLS], [ - AC_MSG_CHECKING(for thread local storage (TLS) class) - AC_CACHE_VAL(ac_cv_tls, [ - ax_tls_keywords="__thread __declspec(thread) none" - for ax_tls_keyword in $ax_tls_keywords; do + AC_MSG_CHECKING([for thread local storage (TLS) class]) + AC_CACHE_VAL([ac_cv_tls], + [for ax_tls_keyword in thread_local _Thread_local __thread '__declspec(thread)' none; do AS_CASE([$ax_tls_keyword], [none], [ac_cv_tls=none ; break], - [AC_TRY_COMPILE( - [#include - static void - foo(void) { - static ] $ax_tls_keyword [ int bar; - exit(1); - }], - [], - [ac_cv_tls=$ax_tls_keyword ; break], - ac_cv_tls=none - )]) - done - ]) - AC_MSG_RESULT($ac_cv_tls) + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [#include ], + [static $ax_tls_keyword int bar;] + )], + [ac_cv_tls=$ax_tls_keyword ; break], + [ac_cv_tls=none] + )] + ) + done ] + ) + AC_MSG_RESULT([$ac_cv_tls]) AS_IF([test "$ac_cv_tls" != "none"], - AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) - m4_ifnblank([$1], [$1]), - m4_ifnblank([$2], [$2]) - ) + [AC_DEFINE_UNQUOTED([TLS],[$ac_cv_tls],[If the compiler supports a TLS storage class, define it to that here]) + m4_ifnblank([$1],[$1],[[:]])], + [m4_ifnblank([$2],[$2],[[:]])]) ]) diff --git a/mcapi/crypto.c b/mcapi/crypto.c index 18ec920c3..568cd8849 100644 --- a/mcapi/crypto.c +++ b/mcapi/crypto.c @@ -1,6 +1,6 @@ /* crypto.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/mcapi/crypto.h b/mcapi/crypto.h index ddb450b63..8698fd1e2 100644 --- a/mcapi/crypto.h +++ b/mcapi/crypto.h @@ -1,6 +1,6 @@ /* crypto.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/mcapi/mcapi_test.c b/mcapi/mcapi_test.c index cf0c31075..63075cfd3 100644 --- a/mcapi/mcapi_test.c +++ b/mcapi/mcapi_test.c @@ -1,6 +1,6 @@ /* mcapi_test.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -238,7 +238,7 @@ static int check_md5(void) return -1; } - if (ret == 0 && memcmp(mcDigest, defDigest, CRYPT_MD5_DIGEST_SIZE) != 0) { + if (memcmp(mcDigest, defDigest, CRYPT_MD5_DIGEST_SIZE) != 0) { printf("md5 final memcmp failed\n"); return -1; } diff --git a/mplabx/benchmark_main.c b/mplabx/benchmark_main.c index 461e53bea..5a7da70c0 100644 --- a/mplabx/benchmark_main.c +++ b/mplabx/benchmark_main.c @@ -1,6 +1,6 @@ /* benchmark_main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/mplabx/test_main.c b/mplabx/test_main.c index 8d1881cc4..101937678 100644 --- a/mplabx/test_main.c +++ b/mplabx/test_main.c @@ -1,6 +1,6 @@ /* main.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/scripts/crl-revoked.test b/scripts/crl-revoked.test index 9d7f7eba0..483c62223 100755 --- a/scripts/crl-revoked.test +++ b/scripts/crl-revoked.test @@ -29,9 +29,9 @@ server_pid=$no_pid ready_file=`pwd`/wolfssl_crl_ready$$ remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "removing existing ready file" - rm $ready_file + rm "$ready_file" fi } @@ -70,12 +70,12 @@ run_test() { # starts the server on crl_port, -R generates ready file to be used as a # mutex lock, -c loads the revoked certificate. We capture the processid # into the variable server_pid - ./examples/server/server -R $ready_file -p $crl_port \ + ./examples/server/server -R "$ready_file" -p $crl_port \ -c ${CERT_DIR}/server-revoked-cert.pem \ -k ${CERT_DIR}/server-revoked-key.pem & server_pid=$! - while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) @@ -84,7 +84,7 @@ run_test() { # sleep for an additional 0.1 to mitigate race on write/read of $ready_file: sleep 0.1 - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "found ready file, starting client..." else echo -e "NO ready file ending test..." @@ -92,7 +92,7 @@ run_test() { fi # get created port 0 ephemeral port - crl_port="$(cat $ready_file)" + crl_port="$(cat "$ready_file")" # starts client on crl_port and captures the output from client capture_out=$(./examples/client/client -p $crl_port 2>&1) @@ -107,9 +107,13 @@ run_test() { echo "" echo "Successful Revocation!!!!" echo "" - exit_code=0 - echo "exiting with $exit_code" - exit $exit_code + if [ $exit_hash_dir_code -ne 0 ]; then + exit_code=1 + else + exit_code=0 + echo "exiting with $exit_code" + exit $exit_code + fi ;; *) echo "" @@ -120,9 +124,88 @@ run_test() { esac } +run_hashdir_test() { + echo -e "\n\nHash dir with CRL and Certificate loading" + remove_ready_file + # create hashed cert and crl + pushd ${CERT_DIR} + # ca file + ca_hash_name=`openssl x509 -in ca-cert.pem -hash -noout` + if [ -f "$ca_hash_name".0 ]; then + rm "$ca_hash_name".0 + fi + ln -s ca-cert.pem "$ca_hash_name".0 + # crl file + crl_hash_name=`openssl crl -in ./crl/crl.pem -hash -noout` + if [ -f "$crl_hash_name".r0 ]; then + rm "$crl_hash_name".r0 + fi + ln -s ./crl/crl.pem "$crl_hash_name".r0 + popd + + # starts the server on crl_port, -R generates ready file to be used as a + # mutex lock, -c loads the revoked certificate. We capture the processid + # into the variable server_pid + ./examples/server/server -R "$ready_file" -p $crl_port \ + -c ${CERT_DIR}/server-revoked-cert.pem \ + -k ${CERT_DIR}/server-revoked-key.pem & + server_pid=$! + while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + # get created port 0 ephemeral port + crl_port="$(cat "$ready_file")" + + # starts client on crl_port and captures the output from client + capture_out=$(./examples/client/client -p $crl_port -9 2>&1) + client_result=$? + + wait $server_pid + server_result=$? + + case "$capture_out" in + *$revocation_code*) + # only exit with zero on detection of the expected error code + echo "" + echo "Successful Revocation!!!! with hash dir" + echo "" + exit_hash_dir_code=0 + ;; + *) + echo "" + echo "Certificate was not revoked saw this instead: $capture_out" + echo "" + echo "configure with --enable-crl and run this script again" + echo "" + exit_hash_dir_code=1 + esac + + # clean up hashed cert and crl + pushd ${CERT_DIR} + rm "$ca_hash_name".0 + rm "$crl_hash_name".r0 + popd + +} ######### begin program ######### +# Check for enabling hash dir feature +./examples/client/client -? 2>&1 | grep -- 'hash dir' +if [ $? -eq 0 ]; then + hash_dir=yes + exit_hash_dir_code=1 +fi + +if [ "$hash_dir" = "yes" ]; then + run_hashdir_test +else + exit_hash_dir_code=0 +fi + # run the test run_test diff --git a/scripts/external.test b/scripts/external.test index e8826b245..b794c73c2 100755 --- a/scripts/external.test +++ b/scripts/external.test @@ -34,7 +34,7 @@ if [ $? -ne 0 ]; then fi # is our desired server there? - ${SCRIPT_DIR}/ping.test $server 2 + "${SCRIPT_DIR}"/ping.test $server 2 RESULT=$? [ $RESULT -ne 0 ] && exit 0 diff --git a/scripts/ocsp-stapling-with-ca-as-responder.test b/scripts/ocsp-stapling-with-ca-as-responder.test index 0991b4569..8e6309469 100755 --- a/scripts/ocsp-stapling-with-ca-as-responder.test +++ b/scripts/ocsp-stapling-with-ca-as-responder.test @@ -43,7 +43,7 @@ CERT_DIR="certs/ocsp" ready_file="${WORKSPACE}"/wolf_ocsp_s1_readyF$$ ready_file2="${WORKSPACE}"/wolf_ocsp_s1_readyF2$$ -printf '%s\n' "ready files: $ready_file $ready_file2" +printf '%s\n' "ready files: \"$ready_file\" \"$ready_file2\"" test_cnf="ocsp_s_w_ca_a_r.cnf" @@ -51,7 +51,7 @@ wait_for_readyFile(){ counter=0 - while [ ! -s $1 -a "$counter" -lt 20 ]; do + while [ ! -s "$1" -a "$counter" -lt 20 ]; do if [[ -n "${2-}" ]]; then if ! kill -0 $2 2>&-; then echo "pid $2 for port ${3-} exited before creating ready file. bailing..." @@ -63,19 +63,19 @@ wait_for_readyFile(){ counter=$((counter+ 1)) done - if test -e $1; then + if test -e "$1"; then echo -e "found ready file, starting client..." else - echo -e "NO ready file at $1 -- ending test..." + echo -e "NO ready file at \"$1\" -- ending test..." exit 1 fi } remove_single_rF(){ - if test -e $1; then - printf '%s\n' "removing ready file: $1" - rm $1 + if test -e "$1"; then + printf '%s\n' "removing ready file: \"$1\"" + rm "$1" fi } @@ -135,13 +135,13 @@ create_new_cnf() { } remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then printf '%s\n' "removing ready file" - rm $ready_file + rm "$ready_file" fi - if test -e $ready_file2; then - printf '%s\n' "removing ready file: $ready_file2" - rm $ready_file2 + if test -e "$ready_file2"; then + printf '%s\n' "removing ready file: \"$ready_file2\"" + rm "$ready_file2" fi } @@ -197,10 +197,10 @@ port2=$(get_first_free_port $((port1 + 1))) # create a port to use with openssl ocsp responder -./examples/server/server -R $ready_file -p $port1 & +./examples/server/server -R "$ready_file" -p $port1 & wolf_pid=$! -wait_for_readyFile $ready_file $wolf_pid $port1 -if [ ! -f $ready_file ]; then +wait_for_readyFile "$ready_file" $wolf_pid $port1 +if [ ! -f "$ready_file" ]; then printf '%s\n' "Failed to create ready file: \"$ready_file\"" exit 1 else @@ -240,10 +240,10 @@ sleep 0.1 printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" # client test against our own server - GOOD CERT ./examples/server/server -c certs/ocsp/server1-cert.pem \ - -k certs/ocsp/server1-key.pem -R $ready_file2 \ + -k certs/ocsp/server1-key.pem -R "$ready_file2" \ -p $port2 & wolf_pid2=$! -wait_for_readyFile $ready_file2 $wolf_pid2 $port2 +wait_for_readyFile "$ready_file2" $wolf_pid2 $port2 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 \ -p $port2 RESULT=$? @@ -252,12 +252,12 @@ printf '%s\n\n' "Test PASSED!" printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------" # client test against our own server - REVOKED CERT -remove_single_rF $ready_file2 +remove_single_rF "$ready_file2" ./examples/server/server -c certs/ocsp/server2-cert.pem \ - -k certs/ocsp/server2-key.pem -R $ready_file2 \ + -k certs/ocsp/server2-key.pem -R "$ready_file2" \ -p $port2 & wolf_pid2=$! -wait_for_readyFile $ready_file2 $wolf_pid2 $port2 +wait_for_readyFile "$ready_file2" $wolf_pid2 $port2 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 \ -p $port2 RESULT=$? diff --git a/scripts/ocsp-stapling.test b/scripts/ocsp-stapling.test index 7a1583138..bf7cc2233 100755 --- a/scripts/ocsp-stapling.test +++ b/scripts/ocsp-stapling.test @@ -60,7 +60,7 @@ ln -s ../examples CERT_DIR="./certs/ocsp" ready_file="$WORKSPACE"/wolf_ocsp_s1_readyF$$ ready_file2="$WORKSPACE"/wolf_ocsp_s1_readyF2$$ -printf '%s\n' "ready file: $ready_file" +printf '%s\n' "ready file: \"$ready_file\"" test_cnf="ocsp_s1.cnf" @@ -68,7 +68,7 @@ wait_for_readyFile(){ counter=0 - while [ ! -s $1 -a "$counter" -lt 20 ]; do + while [ ! -s "$1" -a "$counter" -lt 20 ]; do if [[ -n "${2-}" ]]; then if ! kill -0 $2 2>&-; then echo "pid $2 for port ${3-} exited before creating ready file. bailing..." @@ -80,19 +80,19 @@ wait_for_readyFile(){ counter=$((counter+ 1)) done - if test -e $1; then + if test -e "$1"; then echo -e "found ready file, starting client..." else - echo -e "NO ready file at $1 -- ending test..." + echo -e "NO ready file at \"$1\" -- ending test..." exit 1 fi } remove_single_rF(){ - if test -e $1; then - printf '%s\n' "removing ready file: $1" - rm $1 + if test -e "$1"; then + printf '%s\n' "removing ready file: \"$1\"" + rm "$1" fi } @@ -148,17 +148,17 @@ create_new_cnf() { CURR_LOC="$PWD" printf '%s\n' "echo now in $CURR_LOC" ./renewcerts-for-test.sh $test_cnf - cd $WORKSPACE + cd "$WORKSPACE" } remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then printf '%s\n' "removing ready file" - rm $ready_file + rm "$ready_file" fi - if test -e $ready_file2; then - printf '%s\n' "removing ready file: $ready_file2" - rm $ready_file2 + if test -e "$ready_file2"; then + printf '%s\n' "removing ready file: \"$ready_file2\"" + rm "$ready_file2" fi } @@ -227,11 +227,11 @@ port3=$(get_first_free_port $((port2 + 1))) # test interop fail case ready_file=$PWD/wolf_ocsp_readyF$$ -printf '%s\n' "ready file: $ready_file" -./examples/server/server -b -p $port1 -o -R $ready_file & +printf '%s\n' "ready file: \"$ready_file\"" +./examples/server/server -b -p $port1 -o -R "$ready_file" & wolf_pid=$! -wait_for_readyFile $ready_file $wolf_pid $port1 -if [ ! -f $ready_file ]; then +wait_for_readyFile "$ready_file" $wolf_pid $port1 +if [ ! -f "$ready_file" ]; then printf '%s\n' "Failed to create ready file: \"$ready_file\"" exit 1 else @@ -239,10 +239,10 @@ else echo "hi" | openssl s_client -status $V4V6_FLAG -connect ${LOCALHOST}:$port1 -cert ./certs/client-cert.pem -key ./certs/client-key.pem -CAfile ./certs/ocsp/root-ca-cert.pem 2>&1 | tee /dev/stderr | fgrep -q 'self signed certificate in certificate chain' if [ $? -neq 0 ]; then printf '%s\n' "Expected verification error from s_client is missing." - remove_single_rF $ready_file + remove_single_rF "$ready_file" exit 1 fi - remove_single_rF $ready_file + remove_single_rF "$ready_file" wait $wolf_pid if [ $? -ne 1 ]; then printf '%s\n' "wolfSSL server unexpected fail value" @@ -252,10 +252,10 @@ fi # create a port to use with openssl ocsp responder -./examples/server/server -b -p $port2 -R $ready_file & +./examples/server/server -b -p $port2 -R "$ready_file" & wolf_pid2=$! -wait_for_readyFile $ready_file $wolf_pid2 $port2 -if [ ! -f $ready_file ]; then +wait_for_readyFile "$ready_file" $wolf_pid2 $port2 +if [ ! -f "$ready_file" ]; then printf '%s\n' "Failed to create ready file: \"$ready_file\"" exit 1 else @@ -307,10 +307,10 @@ sleep 0.1 printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" # client test against our own server - GOOD CERT -./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ +./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \ -k certs/ocsp/server1-key.pem -p $port3 & wolf_pid3=$! -wait_for_readyFile $ready_file2 $wolf_pid3 $port3 +wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $port3 RESULT=$? [ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1 @@ -318,11 +318,11 @@ printf '%s\n\n' "Test PASSED!" printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------" # client test against our own server - REVOKED CERT -remove_single_rF $ready_file2 -./examples/server/server -c certs/ocsp/server2-cert.pem -R $ready_file2 \ +remove_single_rF "$ready_file2" +./examples/server/server -c certs/ocsp/server2-cert.pem -R "$ready_file2" \ -k certs/ocsp/server2-key.pem -p $port3 & wolf_pid3=$! -wait_for_readyFile $ready_file2 $wolf_pid3 $port3 +wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 sleep 0.1 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $port3 RESULT=$? @@ -335,12 +335,12 @@ printf '%s\n\n' "Test successfully REVOKED!" if [ $? -ne 0 ]; then printf '%s\n\n' "------------- TEST CASE 3 SHOULD PASS --------------------" # client test against our own server - GOOD CERT - remove_single_rF $ready_file2 - ./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ + remove_single_rF "$ready_file2" + ./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \ -k certs/ocsp/server1-key.pem -v 4 \ -p $port3 & wolf_pid3=$! - wait_for_readyFile $ready_file2 $wolf_pid3 $port3 + wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 \ -p $port3 RESULT=$? @@ -349,12 +349,12 @@ if [ $? -ne 0 ]; then printf '%s\n\n' "------------- TEST CASE 4 SHOULD PASS --------------------" # client test against our own server, must staple - GOOD CERT - remove_single_rF $ready_file2 - ./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ + remove_single_rF "$ready_file2" + ./examples/server/server -c certs/ocsp/server1-cert.pem -R "$ready_file2" \ -k certs/ocsp/server1-key.pem -v 4 \ -p $port3 & wolf_pid3=$! - wait_for_readyFile $ready_file2 $wolf_pid3 $port3 + wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1m -v 4 -F 1 \ -p $port3 RESULT=$? @@ -363,12 +363,12 @@ if [ $? -ne 0 ]; then printf '%s\n\n' "------------- TEST CASE 5 SHOULD REVOKE ------------------" # client test against our own server - REVOKED CERT - remove_single_rF $ready_file2 - ./examples/server/server -c certs/ocsp/server2-cert.pem -R $ready_file2 \ + remove_single_rF "$ready_file2" + ./examples/server/server -c certs/ocsp/server2-cert.pem -R "$ready_file2" \ -k certs/ocsp/server2-key.pem -v 4 \ -p $port3 & wolf_pid3=$! - wait_for_readyFile $ready_file2 $wolf_pid3 $port3 + wait_for_readyFile "$ready_file2" $wolf_pid3 $port3 ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 \ -p $port3 RESULT=$? diff --git a/scripts/ocsp.test b/scripts/ocsp.test index 74231b404..e89ecbe77 100755 --- a/scripts/ocsp.test +++ b/scripts/ocsp.test @@ -27,7 +27,7 @@ if [ "$OUTPUT" = "SNI is: ON" ]; then printf '\n\n%s\n\n' "SNI is on, proceed with globalsign test" # is our desired server there? - ${SCRIPT_DIR}/ping.test $server 2 + "${SCRIPT_DIR}/ping.test" $server 2 RESULT=$? if [ $RESULT -ne 0 ]; then GL_UNREACHABLE=1 @@ -35,7 +35,7 @@ if [ "$OUTPUT" = "SNI is: ON" ]; then if [ $RESULT -eq 0 ]; then # client test against the server - ./examples/client/client -X -C -h $server -p 443 -A $ca -g -o -N -v d -S $server + ./examples/client/client -X -C -h $server -p 443 -A "$ca" -g -o -N -v d -S $server GL_RESULT=$? [ $GL_RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed" else @@ -54,7 +54,7 @@ ${SCRIPT_DIR}/ping.test $server 2 RESULT=$? if [ $RESULT -eq 0 ]; then # client test against the server - ./examples/client/client -X -C -h $server -p 443 -A $ca -g -o -N + ./examples/client/client -X -C -h $server -p 443 -A "$ca" -g -o -N GR_RESULT=$? [ $GR_RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed" else diff --git a/scripts/openssl.test b/scripts/openssl.test index 605946b46..b6d109042 100755 --- a/scripts/openssl.test +++ b/scripts/openssl.test @@ -2,6 +2,10 @@ #openssl.test +# Enviornment variables used: +# OPENSSL (openssl app to use) +# OPENSSL_ENGINE_ID (engine id if any i.e. "wolfengine") + CERT_DIR="$PWD/$(dirname "$0")/../certs" if ! test -n "$WOLFSSL_OPENSSL_TEST"; then @@ -129,17 +133,39 @@ start_openssl_server() { server_port=$port found_free_port=0 counter=0 + + # If OPENSSL_ENGINE_ID has been set then check that the desired engine can + # be loaded successfully and error out if not. Otherwise the OpenSSL app + # will fall back to default engine. + if [ ! -z "${OPENSSL_ENGINE_ID}" ]; then + OUTPUT=`$OPENSSL engine -tt $OPENSSL_ENGINE_ID` + if [ $? != 0 ]; then + printf "not able to load engine\n" + printf "$OPENSSL engine -tt $OPENSSL_ENGINE_ID\n" + do_cleanup + exit 1 + else + echo $OUTPUT | grep "available" + if [ $? != 0 ]; then + printf "engine not available\n" + do_cleanup + exit 1 + fi + fi + OPENSSL_ENGINE_ID="-engine ${OPENSSL_ENGINE_ID}" + fi + while [ "$counter" -lt 20 ]; do echo -e "\n# Trying to start $openssl_suite OpenSSL server on port $server_port..." echo "#" if [ "$cert_file" != "" ] then - echo "# " $OPENSSL s_server -accept $server_port -cert $cert_file -key $key_file -quiet -CAfile $ca_file -www -dhparam ${CERT_DIR}/dh2048.pem -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe - $OPENSSL s_server -accept $server_port -cert $cert_file -key $key_file -quiet -CAfile $ca_file -www -dhparam ${CERT_DIR}/dh2048.pem -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe & + echo "# " $OPENSSL s_server -accept $server_port $OPENSSL_ENGINE_ID -cert \"$cert_file\" -key \"$key_file\" -quiet -CAfile \"$ca_file\" -www -dhparam \"${CERT_DIR}/dh2048.pem\" -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe + $OPENSSL s_server -accept $server_port $OPENSSL_ENGINE_ID -cert "$cert_file" -key "$key_file" -quiet -CAfile "$ca_file" -www -dhparam "${CERT_DIR}/dh2048.pem" -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe & else - echo "# " $OPENSSL s_server -accept $server_port -quiet -nocert -www -dhparam ${CERT_DIR}/dh2048.pem -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe - $OPENSSL s_server -accept $server_port -quiet -nocert -www -dhparam ${CERT_DIR}/dh2048.pem -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe & + echo "# " $OPENSSL s_server -accept $server_port $OPENSSL_ENGINE_ID -quiet -nocert -www -dhparam \"${CERT_DIR}/dh2048.pem\" -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe + $OPENSSL s_server -accept $server_port $OPENSSL_ENGINE_ID -quiet -nocert -www -dhparam "${CERT_DIR}/dh2048.pem" -verify 10 -verify_return_error -psk $psk_hex -cipher "ALL:eNULL" $openssl_nodhe & fi server_pid=$! # wait to see if s_server successfully starts before continuing @@ -203,8 +229,8 @@ start_wolfssl_server() { echo -e "\n# Trying to start $wolfssl_suite wolfSSL server on port $server_port..." echo "#" - echo "# $WOLFSSL_SERVER -p $server_port $wolfssl_cert $wolfssl_key $wolfssl_caCert -g -v d -x -i $psk $crl -l ALL" - $WOLFSSL_SERVER -p $server_port $wolfssl_cert $wolfssl_key $wolfssl_caCert -g -v d -x -i $psk $crl -l ALL & + echo "# $WOLFSSL_SERVER -p $server_port -g -v d -x -i $psk $crl -l ALL \"$wolfssl_cert\" \"$wolfssl_key\" \"$wolfssl_caCert\"" + $WOLFSSL_SERVER -p $server_port -g -v d -x -i $psk $crl -l ALL "$wolfssl_cert" "$wolfssl_key" "$wolfssl_caCert" & server_pid=$! # wait to see if server successfully starts before continuing sleep 0.1 @@ -290,13 +316,13 @@ do_wolfssl_client() { if [ "$version" != "5" -a "$version" != "" ] then echo "#" - echo "# $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite -v $version $psk $adh $wolfssl_cert $wolfssl_key $wolfssl_caCert $crl" - $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite -v $version $psk $adh $wolfssl_cert $wolfssl_key $wolfssl_caCert $crl + echo "# $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite -v $version $psk $adh "$wolfssl_cert" "$wolfssl_key" "$wolfssl_caCert" $crl" + $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite -v $version $psk $adh "$wolfssl_cert" "$wolfssl_key" "$wolfssl_caCert" $crl else echo "#" - echo "# $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite $psk $adh $wolfssl_cert $wolfssl_key $wolfssl_caCert $crl" + echo "# $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite $psk $adh "$wolfssl_cert" "$wolfssl_key" "$wolfssl_caCert" $crl" # do all versions - $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite $psk $adh $wolfssl_cert $wolfssl_key $wolfssl_caCert $crl + $WOLFSSL_CLIENT -p $port -g $wolfssl_resume -l $wolfSuite $psk $adh "$wolfssl_cert" "$wolfssl_key" "$wolfssl_caCert" $crl fi client_result=$? @@ -344,12 +370,12 @@ do_openssl_client() { if [ "$tls13_cipher" = "" ] then echo "#" - echo "# $OPENSSL s_client -connect localhost:$port -reconnect -cipher $cmpSuite $openssl_version $openssl_psk $openssl_cert1 $openssl_cert2 $openssl_key1 $openssl_key2 $openssl_caCert1 $openssl_caCert2" - echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -cipher $cmpSuite $openssl_version $openssl_psk $openssl_cert1 $openssl_cert2 $openssl_key1 $openssl_key2 $openssl_caCert1 $openssl_caCert2" + echo "# $OPENSSL s_client -connect localhost:$port -reconnect -cipher $cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\"" + echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -cipher $cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\"" else echo "#" - echo "# $OPENSSL s_client -connect localhost:$port -reconnect -ciphersuites=$cmpSuite $openssl_version $openssl_psk $openssl_cert1 $openssl_cert2 $openssl_key1 $openssl_key2 $openssl_caCert1 $openssl_caCert2" - echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -ciphersuites=$cmpSuite $openssl_version $openssl_psk $openssl_cert1 $openssl_cert2 $openssl_key1 $openssl_key2 $openssl_caCert1 $openssl_caCert2" + echo "# $OPENSSL s_client -connect localhost:$port -reconnect -ciphersuites=$cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\"" + echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -ciphersuites=$cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\"" fi client_result=$? @@ -381,7 +407,7 @@ command -v $OPENSSL >/dev/null 2>&1 || { echo >&2 "Requires openssl command, but echo -e "\nTesting for _build directory as part of distcheck, different paths" currentDir=`pwd` -if [ $currentDir = *"_build" ] +if [ "$currentDir" = *"_build" ] then echo -e "_build directory detected, moving a directory back" cd .. @@ -441,7 +467,7 @@ IFS=$OIFS #restore separator # # Check for cerificate support in wolfSSL -wolf_certs=`$WOLFSSL_CLIENT -help 2>&1` +wolf_certs=`$WOLFSSL_CLIENT -? 2>&1` case $wolf_certs in *"cert"*) ;; @@ -453,7 +479,7 @@ esac if [ "$wolf_certs" != "" ] then # Check if ECC certificates supported in wolfSSL - wolf_ecc=`$WOLFSSL_CLIENT -A ${CERT_DIR}/ed25519/ca-ecc-cert.pem 2>&1` + wolf_ecc=`$WOLFSSL_CLIENT -A "${CERT_DIR}/ed25519/ca-ecc-cert.pem" 2>&1` case $wolf_ecc in *"ca file"*) wolf_ecc="" @@ -462,7 +488,7 @@ then ;; esac # Check if Ed25519 certificates supported in wolfSSL - wolf_ed25519=`$WOLFSSL_CLIENT -A ${CERT_DIR}/ed25519/root-ed25519.pem 2>&1` + wolf_ed25519=`$WOLFSSL_CLIENT -A "${CERT_DIR}/ed25519/root-ed25519.pem" 2>&1` case $wolf_ed25519 in *"ca file"*) wolf_ed25519="" @@ -471,7 +497,7 @@ then ;; esac # Check if Ed25519 certificates supported in OpenSSL - openssl_ed25519=`$OPENSSL s_client -cert ${CERT_DIR}/ed25519/client-ed25519.pem -key ${CERT_DIR}/ed25519/client-ed25519-priv.pem 2>&1` + openssl_ed25519=`$OPENSSL s_client -cert "${CERT_DIR}/ed25519/client-ed25519.pem" -key "${CERT_DIR}/ed25519/client-ed25519-priv.pem" 2>&1` case $openssl_ed25519 in *"unable to load"*) wolf_ed25519="" @@ -480,7 +506,7 @@ then ;; esac # Check if Ed448 certificates supported in wolfSSL - wolf_ed448=`$WOLFSSL_CLIENT -A ${CERT_DIR}/ed448/root-ed448.pem 2>&1` + wolf_ed448=`$WOLFSSL_CLIENT -A "${CERT_DIR}/ed448/root-ed448.pem" 2>&1` case $wolf_ed448 in *"ca file"*) wolf_ed448="" @@ -489,7 +515,7 @@ then ;; esac # Check if Ed448 certificates supported in OpenSSL - openssl_ed448=`$OPENSSL s_client -cert ${CERT_DIR}/ed448/client-ed448.pem -key ${CERT_DIR}/ed448/client-ed448-priv.pem 2>&1` + openssl_ed448=`$OPENSSL s_client -cert "${CERT_DIR}/ed448/client-ed448.pem" -key "${CERT_DIR}/ed448/client-ed448-priv.pem" 2>&1` case $openssl_ed448 in *"unable to load"*) wolf_ed448="" @@ -640,7 +666,7 @@ if [ "$wolf_ed25519" != "" ]; then cert_file="${CERT_DIR}/ed25519/server-ed25519.pem" key_file="${CERT_DIR}/ed25519/server-ed25519-priv.pem" - ca_file="${CERT_DIR}/ed25519/root-ed25519.pem" + ca_file="${CERT_DIR}/ed25519/client-ed25519.pem" openssl_suite="Ed25519" start_openssl_server @@ -731,7 +757,7 @@ do # double check that can actually do a sslv3 connection using # client-cert.pem to send but any file with EOF works - $OPENSSL s_client -ssl3 -no_ign_eof -host localhost -port $openssl_port < ${CERT_DIR}/client-cert.pem + $OPENSSL s_client -ssl3 -no_ign_eof -host localhost -port $openssl_port < "${CERT_DIR}/client-cert.pem" sslv3_sup=$? if [ $sslv3_sup != 0 ] then @@ -948,8 +974,8 @@ do fi if [ $ed25519_openssl_pid != $no_pid -a "$version" != "0" -a "$version" != "1" -a "$version" != "2" ] then - cert="${CERT_DIR}/ed25519/server-ed25519.pem" - key="${CERT_DIR}/ed25519/server-ed25519-priv.pem" + cert="${CERT_DIR}/ed25519/client-ed25519.pem" + key="${CERT_DIR}/ed25519/client-ed25519-priv.pem" caCert="${CERT_DIR}/ed25519/server-ed25519.pem" wolf_temp_cases_total=$((wolf_temp_cases_total + 1)) @@ -1086,8 +1112,8 @@ do # Ed25519 if [ $ed25519_openssl_pid != $no_pid ] then - cert="${CERT_DIR}/ed25519/server-ed25519.pem" - key="${CERT_DIR}/ed25519/server-ed25519-priv.pem" + cert="${CERT_DIR}/ed25519/client-ed25519.pem" + key="${CERT_DIR}/ed25519/client-ed25519-priv.pem" caCert="${CERT_DIR}/ed25519/server-ed25519.pem" wolf_temp_cases_total=$((wolf_temp_cases_total + 1)) diff --git a/scripts/pkcallbacks.test b/scripts/pkcallbacks.test index a614741e6..49095e179 100755 --- a/scripts/pkcallbacks.test +++ b/scripts/pkcallbacks.test @@ -27,9 +27,9 @@ server_pid=$no_pid ready_file=`pwd`/wolfssl_pk_ready$$ remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "removing existing ready file" - rm $ready_file + rm "$ready_file" fi } @@ -79,16 +79,16 @@ run_test() { # starts the server on pk_port, -R generates ready file to be used as a # mutex lock, -P does pkcallbacks. We capture the processid # into the variable server_pid - ./examples/server/server -P -R $ready_file -p $pk_port & + ./examples/server/server -P -R "$ready_file" -p $pk_port & server_pid=$! - while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) done - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "found ready file, starting client..." else echo -e "NO ready file ending test..." @@ -99,7 +99,7 @@ run_test() { sleep 0.1 # get created port 0 ephemeral port - pk_port=`cat $ready_file` + pk_port=`cat "$ready_file"` # starts client on pk_port with pkcallbacks, captures the output from client capture_out=$(./examples/client/client -P -p $pk_port 2>&1) diff --git a/scripts/psk.test b/scripts/psk.test index e0dc81708..d264b0a75 100755 --- a/scripts/psk.test +++ b/scripts/psk.test @@ -25,23 +25,23 @@ counter=0 # per source tree ready_file=`pwd`/wolfssl_psk_ready$$ -echo "ready file $ready_file" +echo "ready file \"$ready_file\"" create_port() { - while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) done - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "found ready file, starting client..." # sleep for an additional 0.1 to mitigate race on write/read of $ready_file: sleep 0.1 # get created port 0 ephemeral port - port=`cat $ready_file` + port=`cat "$ready_file"` else echo -e "NO ready file ending test..." do_cleanup @@ -49,9 +49,9 @@ create_port() { } remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "removing existing ready file" - rm $ready_file + rm "$ready_file" fi } @@ -87,7 +87,7 @@ fi # Usual psk server / psk client. This use case is tested in # tests/unit.test and is used here for just checking if PSK is enabled port=0 -./examples/server/server -s -R $ready_file -p $port & +./examples/server/server -s -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -s -p $port @@ -110,7 +110,7 @@ if [ $? -ne 0 ]; then # tests/unit.test and is used here for just checking if cipher suite # is available (one case for example is with disable-asn) port=0 - ./examples/server/server -R $ready_file -p $port -l DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-DES-CBC3-SHA & + ./examples/server/server -R "$ready_file" -p $port -l DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-DES-CBC3-SHA & server_pid=$! create_port ./examples/client/client -p $port @@ -126,7 +126,7 @@ if [ $? -ne 0 ]; then # psk server with non psk client port=0 - ./examples/server/server -j -R $ready_file -p $port & + ./examples/server/server -j -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -p $port @@ -142,7 +142,7 @@ if [ $? -ne 0 ]; then # check fail if no auth, psk server with non psk client echo "Checking fail when not sending peer cert" port=0 - ./examples/server/server -j -R $ready_file -p $port & + ./examples/server/server -j -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -x -p $port diff --git a/scripts/resume.test b/scripts/resume.test index a523c5168..f811e34b2 100755 --- a/scripts/resume.test +++ b/scripts/resume.test @@ -29,9 +29,9 @@ ready_file=`pwd`/wolfssl_resume_ready$$ echo "ready file $ready_file" remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "removing existing ready file" - rm $ready_file + rm "$ready_file" fi } @@ -69,16 +69,16 @@ do_test() { esac remove_ready_file - ./examples/server/server -r -R $ready_file -p $resume_port & + ./examples/server/server -r -R "$ready_file" -p $resume_port & server_pid=$! - while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) done - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "found ready file, starting client..." else echo -e "NO ready file ending test..." @@ -90,7 +90,7 @@ do_test() { sleep 0.1 # get created port 0 ephemeral port - resume_port=`cat $ready_file` + resume_port=`cat "$ready_file"` capture_out=$(./examples/client/client $1 -r -p $resume_port 2>&1) client_result=$? diff --git a/scripts/tls13.test b/scripts/tls13.test index 7f4c927d3..3c09db2ae 100755 --- a/scripts/tls13.test +++ b/scripts/tls13.test @@ -1,7 +1,7 @@ #!/bin/sh # tls13.test -# copyright wolfSSL 2016 +# Copyright wolfSSL 2016-2021 # if we can, isolate the network namespace to eliminate port collisions. if [ "${AM_BWRAPPED-}" != "yes" ]; then @@ -30,10 +30,10 @@ server_out_file=`pwd`/wolfssl_tls13_server_out$$ # Client output client_out_file=`pwd`/wolfssl_tls13_client_out$$ -echo "ready file $ready_file" +echo "ready file "$ready_file"" create_port() { - while [ ! -s $ready_file ]; do + while [ ! -s "$ready_file" ]; do if [ "$counter" -gt 50 ]; then break fi @@ -42,14 +42,14 @@ create_port() { counter=$((counter+ 1)) done - if [ -e $ready_file ]; then + if [ -e "$ready_file" ]; then echo -e "found ready file, starting client..." # sleep for an additional 0.1 to mitigate race on write/read of $ready_file: sleep 0.1 # get created port 0 ephemeral port - port=`cat $ready_file` + port=`cat "$ready_file"` else echo -e "NO ready file ending test..." do_cleanup @@ -57,9 +57,9 @@ create_port() { } remove_ready_file() { - if [ -e $ready_file ]; then + if [ -e "$ready_file" ]; then echo -e "removing existing ready file" - rm $ready_file + rm "$ready_file" fi } @@ -73,17 +73,17 @@ do_cleanup() { server_pid=$no_pid fi remove_ready_file - if [ -e $client_file ]; then + if [ -e "$client_file" ]; then echo -e "removing existing client file" - rm $client_file + rm "$client_file" fi - if [ -e $server_out_file ]; then + if [ -e "$server_out_file" ]; then echo -e "removing existing server output file" - rm $server_out_file + rm "$server_out_file" fi - if [ -e $client_out_file ]; then + if [ -e "$client_out_file" ]; then echo -e "removing existing client output file" - rm $client_out_file + rm "$client_out_file" fi } @@ -108,10 +108,10 @@ fi # Usual TLS v1.3 server / TLS v1.3 client. echo -e "\n\nTLS v1.3 server with TLS v1.3 client" port=0 -./examples/server/server -v 4 -R $ready_file -p $port & +./examples/server/server -v 4 -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -v 4 -p $port | tee $client_file +./examples/client/client -v 4 -p $port | tee "$client_file" RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -124,7 +124,7 @@ echo "" # TLS 1.3 cipher suites server / client. echo -e "\n\nTLS v1.3 cipher suite mismatch" port=0 -./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-CHACHA20-POLY1305-SHA256 & +./examples/server/server -v 4 -R "$ready_file" -p $port -l TLS13-CHACHA20-POLY1305-SHA256 & server_pid=$! create_port ./examples/client/client -v 4 -p $port -l TLS13-AES256-GCM-SHA384 @@ -146,7 +146,7 @@ if [ $NO_CERTS -ne 0 -a $NO_CLIENT_AUTH -ne 0 ]; then # TLS 1.3 mutual auth required but client doesn't send certificates. echo -e "\n\nTLS v1.3 mutual auth fail" port=0 - ./examples/server/server -v 4 -F -R $ready_file -p $port & + ./examples/server/server -v 4 -F -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -v 4 -x -p $port @@ -167,7 +167,7 @@ if [ $? -ne 0 ]; then # TLS 1.3 server / TLS 1.2 client. echo -e "\n\nTLS v1.3 server downgrading to TLS v1.2" port=0 - ./examples/server/server -v 4 -R $ready_file -p $port & + ./examples/server/server -v 4 -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -v 3 -p $port @@ -184,7 +184,7 @@ if [ $? -ne 0 ]; then # TLS 1.2 server / TLS 1.3 client. echo -e "\n\nTLS v1.3 client upgrading server to TLS v1.3" port=0 - ./examples/server/server -v 3 -R $ready_file -p $port & + ./examples/server/server -v 3 -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -v 4 -p $port @@ -215,7 +215,7 @@ if [ $? -ne 0 ]; then port=0 SERVER_CS="TLS13-AES256-GCM-SHA384:$TLS12_CS" CLIENT_CS="TLS13-AES128-GCM-SHA256:$TLS12_CS" - ./examples/server/server -v d -l $SERVER_CS -R $ready_file -p $port & + ./examples/server/server -v d -l $SERVER_CS -R "$ready_file" -p $port & server_pid=$! create_port ./examples/client/client -v d -l $CLIENT_CS -p $port @@ -246,18 +246,18 @@ fi if [ "$early_data" = "yes" ]; then echo -e "\n\nTLS v1.3 Early Data - session ticket" port=0 - (./examples/server/server -v 4 -r -0 -R $ready_file -p $port 2>&1 | \ - tee $server_out_file) & + (./examples/server/server -v 4 -r -0 -R "$ready_file" -p $port 2>&1 | \ + tee "$server_out_file") & server_pid=$! create_port - ./examples/client/client -v 4 -r -0 -p $port 2>&1 >$client_out_file + ./examples/client/client -v 4 -r -0 -p $port 2>&1 >"$client_out_file" RESULT=$? - cat $client_out_file + cat "$client_out_file" remove_ready_file - grep 'Session Ticket' $client_out_file + grep 'Session Ticket' "$client_out_file" session_ticket=$? - early_data_cnt=`grep 'Early Data' $server_out_file | wc -l` - if [ $session_ticket -eq 0 -a $early_data_cnt -ne 2 ]; then + early_data_cnt=`grep 'Early Data' "$server_out_file" | wc -l` + if [ $session_ticket -eq 0 -a $early_data_cnt -ne 4 ]; then RESULT=1 fi if [ $RESULT -ne 0 ]; then @@ -272,19 +272,30 @@ fi if [ "$early_data" = "yes" -a "$psk" = "yes" ]; then echo -e "\n\nTLS v1.3 Early Data - PSK" port=0 - (./examples/server/server -v 4 -s -0 -R $ready_file -p $port 2>&1 | \ - tee $server_out_file) & + (./examples/server/server -v 4 -s -0 -R "$ready_file" -p $port 2>&1 | \ + tee "$server_out_file") & server_pid=$! create_port ./examples/client/client -v 4 -s -0 -p $port RESULT=$? remove_ready_file - early_data_cnt=`grep 'Early Data' $server_out_file | wc -l` - if [ $early_data_cnt -ne 2 -a $early_data_cnt -ne 4 ]; then + + # wait for the server to quit and write output + wait $server_pid + + early_data_cnt=`grep 'Early Data' "$server_out_file" | wc -l` + if [ $early_data_cnt -ne 3 -a $early_data_cnt -ne 5 ]; then + echo + echo "Server out file" + cat "$server_out_file" + echo + echo "Found lines" + grep 'Early Data' "$server_out_file" + echo -e "\n\nToo few 'Early Data' lines - $early_data_cnt" RESULT=1 fi if [ $RESULT -ne 0 ]; then - echo -e "\n\nIssue with TLS v1.3 Early Data - session ticket" + echo -e "\n\nIssue with TLS v1.3 Early Data - PSK" do_cleanup exit 1 fi diff --git a/scripts/trusted_peer.test b/scripts/trusted_peer.test index 82e61ef8c..d38c3d771 100755 --- a/scripts/trusted_peer.test +++ b/scripts/trusted_peer.test @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # trusted_peer.test # copyright wolfSSL 2016 @@ -36,23 +36,23 @@ combined_cert=`pwd`/certs/client_combined.pem wrong_ca=`pwd`/certs/wolfssl-website-ca.pem wrong_cert=`pwd`/certs/server-revoked-cert.pem -echo "ready file $ready_file" +echo "ready file \"$ready_file\"" create_port() { - while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + while [ ! -s "$ready_file" -a "$counter" -lt 20 ]; do echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) done - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "found ready file, starting client..." # sleep for an additional 0.1 to mitigate race on write/read of $ready_file: sleep 0.1 # get created port 0 ephemeral port - port=`cat $ready_file` + port=`cat "$ready_file"` else echo -e "NO ready file ending test..." do_cleanup @@ -60,9 +60,9 @@ create_port() { } remove_ready_file() { - if test -e $ready_file; then + if test -e "$ready_file"; then echo -e "removing existing ready file" - rm $ready_file + rm "$ready_file" fi } @@ -89,7 +89,7 @@ trap do_trap INT TERM # Look for if RSA and/or ECC is enabled and adjust certs/keys ciphers=`./examples/client/client -e` -if [[ $ciphers != *"RSA"* ]]; then +if [[ "$ciphers" != *"RSA"* ]]; then if [[ $ciphers == *"ECDSA"* ]]; then client_cert=`pwd`/certs/client-ecc-cert.pem client_ca=`pwd`/certs/server-ecc.pem @@ -107,7 +107,7 @@ fi # CRL list not set up for tests crl_test=`./examples/client/client -h` -if [[ $crl_test == *"-C "* ]]; then +if [[ "$crl_test" == *"-C "* ]]; then echo "test not set up to run with CRL" exit 0 fi @@ -118,10 +118,10 @@ echo "Checking built with trusted peer certs " echo "-----------------------------------------------------" port=0 remove_ready_file -./examples/server/server -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -E "$client_cert" -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $client_ca -p $port +./examples/client/client -A "$client_ca" -p $port RESULT=$? remove_ready_file # if fail here then is a settings issue so return 0 @@ -136,10 +136,10 @@ echo "" echo "Server and Client relying on trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -A $wrong_ca -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -A "$wrong_ca" -E "$client_cert" -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $wrong_ca -E $server_cert -c $client_cert -p $port +./examples/client/client -A "$wrong_ca" -E "$server_cert" -c "$client_cert" -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -153,10 +153,10 @@ echo "" echo "Server relying on trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -A $wrong_ca -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -A "$wrong_ca" -E "$client_cert" -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $client_ca -c $client_cert -p $port +./examples/client/client -A "$client_ca" -c "$client_cert" -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -170,10 +170,10 @@ echo "" echo "Client relying on trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $wrong_ca -E $server_cert -p $port +./examples/client/client -A "$wrong_ca" -E "$server_cert" -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -187,10 +187,10 @@ echo "" echo "Client fall through to loaded CAs" echo "-----------------------------------------------------" port=0 -./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $client_ca -E $wrong_cert -p $port +./examples/client/client -A "$client_ca" -E "$wrong_cert" -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -206,10 +206,10 @@ if [[ $wrong_ca != *"ecc"* ]]; then echo "Client wrong CA and wrong trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $wrong_ca -E $wrong_cert -p $port +./examples/client/client -A "$wrong_ca" -E "$wrong_cert" -p $port RESULT=$? remove_ready_file if [ $RESULT -eq 0 ]; then @@ -224,10 +224,10 @@ fi echo "Server wrong CA and wrong trusted peer cert loaded" echo "-----------------------------------------------------" port=0 -./examples/server/server -A $wrong_ca -E $wrong_cert -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -A "$wrong_ca" -E "$wrong_cert" -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $client_ca -p $port +./examples/client/client -A "$client_ca" -p $port RESULT=$? remove_ready_file if [ $RESULT -eq 0 ]; then @@ -241,10 +241,10 @@ echo "" echo "Server fall through to loaded CAs" echo "-----------------------------------------------------" port=0 -./examples/server/server -E $wrong_cert -c $server_cert -k $server_key -R $ready_file -p $port & +./examples/server/server -E "$wrong_cert" -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $client_ca -p $port +./examples/client/client -A "$client_ca" -p $port RESULT=$? remove_ready_file if [ $RESULT -ne 0 ]; then @@ -259,25 +259,25 @@ echo "Server loading multiple trusted peer certs" echo "Test two success cases and one fail case" echo "-----------------------------------------------------" port=0 -cat $client_cert $client_ca > $combined_cert -./examples/server/server -i -A $wrong_ca -E $combined_cert -c $server_cert -k $server_key -R $ready_file -p $port & +cat "$client_cert" "$client_ca" > "$combined_cert" +./examples/server/server -i -A "$wrong_ca" -E "$combined_cert" -c "$server_cert" -k "$server_key" -R "$ready_file" -p $port & server_pid=$! create_port -./examples/client/client -A $client_ca -c $client_cert -k $client_key -p $port +./examples/client/client -A "$client_ca" -c "$client_cert" -k "$client_key" -p $port RESULT=$? if [ $RESULT -ne 0 ]; then echo -e "\nServer load multiple trusted peer certs failed!" do_cleanup exit 1 fi -./examples/client/client -A $client_ca -c $client_ca -k $ca_key -p $port +./examples/client/client -A "$client_ca" -c "$client_ca" -k "$ca_key" -p $port RESULT=$? if [ $RESULT -ne 0 ]; then echo -e "\nServer load multiple trusted peer certs failed!" do_cleanup exit 1 fi -./examples/client/client -A $client_ca -c $wrong_cert -k $client_key -p $port +./examples/client/client -A "$client_ca" -c "$wrong_cert" -k "$client_key" -p $port RESULT=$? if [ $RESULT -eq 0 ]; then echo -e "\nServer load multiple trusted peer certs failed!" @@ -286,7 +286,7 @@ if [ $RESULT -eq 0 ]; then fi do_cleanup # kill PID of server running in infinite loop -rm $combined_cert +rm "$combined_cert" remove_ready_file echo "" diff --git a/src/bio.c b/src/bio.c index d80b7c096..fae495fc1 100644 --- a/src/bio.c +++ b/src/bio.c @@ -1,6 +1,6 @@ /* bio.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -40,7 +40,7 @@ static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) if (Base64_Decode((const byte*)buf, (word32)len, (byte*)buf, &frmtSz) !=0) { WOLFSSL_MSG("Err doing base64 decode"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } (void)bio; @@ -146,7 +146,7 @@ static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf, front->eof = 1; else if (ret < 0) { int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) { + if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) { front->eof = 1; } else { @@ -187,9 +187,9 @@ static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) */ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) { - int ret = 0; + int ret = 0; WOLFSSL_BIO* front = bio; - int sz = 0; + int sz = 0; WOLFSSL_ENTER("wolfSSL_BIO_read"); @@ -202,8 +202,9 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } } - /* start at end of list and work backwards */ - while ((bio != NULL) && (bio->next != NULL)) { + /* start at end of list (or a WOLFSSL_BIO_SSL object since it takes care of + * the rest of the chain) and work backwards */ + while (bio != NULL && bio->next != NULL && bio->type != WOLFSSL_BIO_SSL) { bio = bio->next; } @@ -212,44 +213,65 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (bio->method && bio->method->readCb) { ret = bio->method->readCb(bio, (char*)buf, len); } - - /* formatting data */ - if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) { - ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); + else { + switch (bio->type) { + case WOLFSSL_BIO_BASE64: /* formatting data */ + if (sz > 0) + ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); + break; + case WOLFSSL_BIO_BIO: /* read BIOs */ + ret = wolfSSL_BIO_BIO_read(bio, buf, len); + break; + case WOLFSSL_BIO_MEMORY: + ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); + break; + case WOLFSSL_BIO_FILE: + #ifndef NO_FILESYSTEM + if (bio->ptr) { + ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); + } + else { + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + ret = (int)XREAD(bio->num, buf, len); + #else + WOLFSSL_MSG("No file pointer and XREAD not enabled"); + ret = NOT_COMPILED_IN; + #endif + } + #else + WOLFSSL_MSG("WOLFSSL_BIO_FILE used with NO_FILESYSTEM"); + ret = NOT_COMPILED_IN; + #endif /* !NO_FILESYSTEM */ + break; + case WOLFSSL_BIO_SSL: + #ifndef WOLFCRYPT_ONLY + ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); + #else + WOLFSSL_MSG("WOLFSSL_BIO_SSL used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; + #endif + break; + case WOLFSSL_BIO_MD: /* data passing through BIO MD wrapper */ + #ifndef WOLFCRYPT_ONLY + ret = wolfSSL_BIO_MD_read(bio, buf, ret); + #else + WOLFSSL_MSG("WOLFSSL_BIO_MD used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; + #endif + break; + case WOLFSSL_BIO_SOCKET: + #ifdef USE_WOLFSSL_IO + /* BIO requires built-in socket support + * (cannot be used with WOLFSSL_USER_IO) */ + ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); + #else + ret = NOT_COMPILED_IN; + #endif + break; + } /* switch */ } - /* write BIOs */ - if (bio && bio->type == WOLFSSL_BIO_BIO) { - ret = wolfSSL_BIO_BIO_read(bio, buf, len); - } - - if (bio && bio->type == WOLFSSL_BIO_MEMORY) { - ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); - } - - #ifndef NO_FILESYSTEM - if (bio && bio->type == WOLFSSL_BIO_FILE) { - if (bio->ptr) - ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ - && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - else - ret = (int)XREAD(bio->num, buf, len); - #endif - } - #endif - - #ifndef WOLFCRYPT_ONLY - if (bio && bio->type == WOLFSSL_BIO_SSL) { - ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); - } - - /* data passing through BIO MD wrapper */ - if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) { - ret = wolfSSL_BIO_MD_read(bio, buf, ret); - } - #endif - /* case where front of list is done */ if (bio == front) { break; /* at front of list so be done */ @@ -274,15 +296,22 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } +#ifdef WOLFSSL_BASE64_ENCODE /* Converts data into base64 output * * returns the resulting buffer size on success. */ +/** + * `out` buffer is allocated here and the caller is responsible + * for free'ing it + * `data` and `out` can be the same in which case `data` should + * always be set to `out` after this function call succeeds + */ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, - word32 inLen, byte* out, word32* outLen) + word32 inLen, byte** out, word32* outLen, void* heap) { byte* tmp = NULL; - int ret = 0; + word32 sz = 0; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write"); @@ -290,44 +319,61 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, return BAD_FUNC_ARG; } -#if defined(WOLFSSL_BASE64_ENCODE) - tmp = (byte*)XMALLOC(*outLen, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { - return WOLFSSL_FATAL_ERROR; + /* get the encoded length */ + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, + &sz) != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base64 get length"); + return WOLFSSL_FATAL_ERROR; + } + } + else { + if (Base64_Encode((const byte*)data, inLen, NULL, &sz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base64 get length"); + return WOLFSSL_FATAL_ERROR; + } } - if ((bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) == - WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (sz == 0) { + *outLen = 0; + return 0; /* nothing to do */ + } + + /* allocate temp buffer, since base64 encode does not allow inline */ + tmp = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FATAL_ERROR; + } + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, - tmp, outLen) < 0) { - ret = WOLFSSL_FATAL_ERROR; + tmp, &sz) < 0) { + WOLFSSL_MSG("Base64_Encode_NoNl error"); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } else { if (Base64_Encode((const byte*)data, inLen, - tmp, outLen) < 0) { - ret = WOLFSSL_FATAL_ERROR; + tmp, &sz) < 0) { + WOLFSSL_MSG("Base64_Encode error"); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FATAL_ERROR; } } - if (ret != WOLFSSL_FATAL_ERROR) { - ret = (int) inLen; - XMEMCPY(out, tmp, *outLen); + if (*out != NULL) + XFREE(*out, heap, DYNAMIC_TYPE_TMP_BUFFER); + *out = tmp; + *outLen = sz; + /* out is free'd by caller */ - } - XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); -#else - (void)bio; - (void)data; - (void)inLen; - (void)out; - (void)outLen; - (void)tmp; - WOLFSSL_MSG("BASE64 encoding not compiled in"); -#endif - return ret; + (void)heap; + + return inLen; } - +#endif /* WOLFSSL_BASE64_ENCODE */ #ifndef WOLFCRYPT_ONLY /* Helper function for writing to a WOLFSSL_BIO_SSL type @@ -351,7 +397,7 @@ static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data, front->eof = 1; else if (ret < 0) { int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) { + if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) { front->eof = 1; } else { @@ -500,10 +546,14 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) */ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) { - int ret = 0; - int retB64 = 0; + int ret = 0; +#ifdef WOLFSSL_BASE64_ENCODE + /* Use extra return var as we want to return how much of input we have + * written, not how big the base64 encoding ended up being */ + int retB64 = 0; +#endif WOLFSSL_BIO* front = bio; - void* frmt = NULL; + void* frmt = NULL; word32 frmtSz = 0; WOLFSSL_ENTER("wolfSSL_BIO_write"); @@ -522,103 +572,96 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) if (bio->method && bio->method->writeCb) { ret = bio->method->writeCb(bio, (const char*)data, len); } - - /* check for formatting */ - if (bio->type == WOLFSSL_BIO_BASE64) { -#if defined(WOLFSSL_BASE64_ENCODE) - word32 sz = 0; - - if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { - if (Base64_Encode_NoNl((const byte*)data, len, NULL, - &sz) != LENGTH_ONLY_E) { - WOLFSSL_MSG("Error with base 64 get length"); - ret = SSL_FATAL_ERROR; + else { + switch (bio->type) { + case WOLFSSL_BIO_BASE64: + { + #ifdef WOLFSSL_BASE64_ENCODE + ret = retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, + (byte**)&frmt, &frmtSz, front->heap); + if (ret > 0) { + /* change so that data is formatted buffer */ + data = frmt; + len = frmtSz; } + #else + WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without " + "WOLFSSL_BASE64_ENCODE"); + ret = NOT_COMPILED_IN; + #endif /* WOLFSSL_BASE64_ENCODE */ + break; } - else { - if (Base64_Encode((const byte*)data, len, NULL, &sz) != - LENGTH_ONLY_E) { - WOLFSSL_MSG("Error with base 64 get length"); - ret = SSL_FATAL_ERROR; + case WOLFSSL_BIO_BIO: /* write bios */ + ret = wolfSSL_BIO_BIO_write(bio, data, len); + break; + case WOLFSSL_BIO_MEMORY: + ret = wolfSSL_BIO_MEMORY_write(bio, data, len); + break; + case WOLFSSL_BIO_FILE: + #ifndef NO_FILESYSTEM + if (bio->ptr) { + ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); } - } - - if (frmt == NULL && sz > 0 && ret != SSL_FATAL_ERROR) { - frmt = (void*)XMALLOC(sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (frmt == NULL) { - WOLFSSL_MSG("Memory error"); - ret = SSL_FATAL_ERROR; + else { + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + ret = (int)XWRITE(bio->num, data, len); + #else + WOLFSSL_MSG("No file pointer and XWRITE not enabled"); + ret = NOT_COMPILED_IN; + #endif } - frmtSz = sz; - } - else if (sz > frmtSz) { - frmt = (void*)XREALLOC(frmt, sz, front->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (frmt == NULL) { - WOLFSSL_MSG("Memory error"); - ret = SSL_FATAL_ERROR; + #else + WOLFSSL_MSG("WOLFSSL_BIO_FILE used with NO_FILESYSTEM"); + ret = NOT_COMPILED_IN; + #endif /* !NO_FILESYSTEM */ + break; + case WOLFSSL_BIO_SSL: + #ifndef WOLFCRYPT_ONLY + /* already got eof, again is error */ + if (front->eof) { + ret = WOLFSSL_FATAL_ERROR; } - /* since frmt already existed then data should point to knew - formatted buffer */ - data = frmt; - len = frmtSz; - frmtSz = sz; - } -#endif /* defined(WOLFSSL_BASE64_ENCODE) */ - - if (ret >= 0) { - /* change so that data is formatted buffer */ - retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, - (byte*)frmt, &frmtSz); - data = frmt; - len = frmtSz; - } + else { + ret = wolfSSL_BIO_SSL_write(bio, data, len, front); + } + /* Rest of chain is taken care of inside call */ + goto exit_chain; + #else + WOLFSSL_MSG("WOLFSSL_BIO_SSL used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; + #endif + break; + case WOLFSSL_BIO_MD: + #ifndef WOLFCRYPT_ONLY + if (bio->next != NULL) { /* data passing through MD BIO */ + ret = wolfSSL_BIO_MD_write(bio, data, len); + } + #else + WOLFSSL_MSG("WOLFSSL_BIO_MD used with WOLFCRYPT_ONLY"); + ret = NOT_COMPILED_IN; + #endif + break; + case WOLFSSL_BIO_SOCKET: + #ifdef USE_WOLFSSL_IO + /* BIO requires built-in socket support + * (cannot be used with WOLFSSL_USER_IO) */ + ret = wolfIO_Send(bio->num, (char*)data, len, 0); + #else + ret = NOT_COMPILED_IN; + #endif + break; + } /* switch */ } - /* write bios */ - if (bio->type == WOLFSSL_BIO_BIO) { - ret = wolfSSL_BIO_BIO_write(bio, data, len); - } - - if (bio->type == WOLFSSL_BIO_MEMORY) { - ret = wolfSSL_BIO_MEMORY_write(bio, data, len); - } - - #ifndef NO_FILESYSTEM - if (bio && bio->type == WOLFSSL_BIO_FILE) { - if (bio->ptr) - ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ - && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - else - ret = (int)XWRITE(bio->num, data, len); - #endif - } - #endif - - #ifndef WOLFCRYPT_ONLY - if (bio->type == WOLFSSL_BIO_SSL) { - /* already got eof, again is error */ - if (front->eof) { - ret = SSL_FATAL_ERROR; - } - else { - ret = wolfSSL_BIO_SSL_write(bio, data, len, front); - } - } - - if (bio->type == WOLFSSL_BIO_MD) { - if (bio->next != NULL) { /* data passing through MD BIO */ - ret = wolfSSL_BIO_MD_write(bio, data, len); - } - } - #endif /* WOLFCRYPT_ONLY */ - /* advance to the next bio in list */ bio = bio->next; } +#ifndef WOLFCRYPT_ONLY +exit_chain: +#endif + /* info cb, user can override return value */ if (front != NULL && front->infoCb != NULL) { ret = (int)front->infoCb(front, @@ -630,9 +673,11 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER); } - if (retB64 != 0) +#ifdef WOLFSSL_BASE64_ENCODE + if (retB64 > 0 && ret > 0) return retB64; else +#endif return ret; } @@ -944,6 +989,21 @@ size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio) return 0; } +/* Custom wolfSSL API to check if current bio object supports checking + * pending state. + */ +int wolfSSL_BIO_supports_pending(const WOLFSSL_BIO *bio) +{ + while (bio) { + if (bio->type == WOLFSSL_BIO_SSL || + bio->type == WOLFSSL_BIO_MEMORY || + bio->type == WOLFSSL_BIO_BIO) + return 1; + bio = bio->next; + } + return 0; +} + /* Return the number of pending bytes in read and write buffers */ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) { @@ -1118,7 +1178,7 @@ int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } b->readRq = 0; @@ -1168,7 +1228,7 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) } if (bio->type == WOLFSSL_BIO_MEMORY) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->pair != NULL) { @@ -1220,7 +1280,7 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) } if (bio->type != WOLFSSL_BIO_BIO) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->pair != NULL) { @@ -1388,7 +1448,7 @@ long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) } if (bio->type != WOLFSSL_BIO_FILE) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } *fp = (XFILE)bio->ptr; @@ -1439,6 +1499,31 @@ int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) return 0; } +/* wolfSSL_BIO_tell is provided as compatible API with + * BIO_tell which returns the current file position of a file related BIO. + * Returns the current file position on success and -1 for failure. + * Returns 0 for a BIOs except file related BIO. + */ +int wolfSSL_BIO_tell(WOLFSSL_BIO* bio) +{ + int pos; + + WOLFSSL_ENTER("wolfSSL_BIO_tell"); + + if (bio == NULL) { + return -1; + } + + if (bio->type != WOLFSSL_BIO_FILE) { + return 0; + } + + pos = (int)XFTELL((XFILE)bio->ptr); + if (pos < 0) + return -1; + else + return pos; +} #endif /* NO_FILESYSTEM */ diff --git a/src/crl.c b/src/crl.c index 1663b347a..41dad91c8 100644 --- a/src/crl.c +++ b/src/crl.c @@ -1,6 +1,6 @@ /* crl.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -364,6 +364,25 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) } #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + /* if not find entry in the CRL list, it looks at the folder that sets */ + /* by LOOKUP_ctrl because user would want to use hash_dir. */ + /* Loading .rN form CRL file if find at the folder, */ + /* and try again checking Cert in the CRL list. */ + /* When not set the folder or not use hash_dir, do nothing. */ + if (foundEntry == 0) { + if (crl->cm->x509_store_p != NULL) { + ret = LoadCertByIssuer(crl->cm->x509_store_p, + (WOLFSSL_X509_NAME*)cert->issuerName, X509_LU_CRL); + if (ret == WOLFSSL_SUCCESS) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); ret = CRL_MISSING; @@ -633,6 +652,7 @@ static CRL_Entry* DupCRL_list(CRL_Entry* crl, void* heap) current = head; head = head->next; FreeCRL_Entry(current, heap); + XFREE(current, heap, DYNAMIC_TYPE_CRL_ENTRY); } return NULL; @@ -701,7 +721,8 @@ int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newc if (store->cm->crl == NULL) { crl = wolfSSL_X509_crl_new(store->cm); if (DupX509_CRL(crl, newcrl) != 0) { - FreeCRL(crl, 1); + if (crl != NULL) + FreeCRL(crl, 1); return WOLFSSL_FAILURE; } store->crl = store->cm->crl = crl; @@ -911,7 +932,7 @@ static void* DoMonitor(void* arg) if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) { WOLFSSL_MSG("kevent monitor customer event failed"); SignalSetup(crl, MONITOR_SETUP_E); - close(crl->mfd); + (void)close(crl->mfd); return NULL; } @@ -923,7 +944,7 @@ static void* DoMonitor(void* arg) if (fPEM == -1) { WOLFSSL_MSG("PEM event dir open failed"); SignalSetup(crl, MONITOR_SETUP_E); - close(crl->mfd); + (void)close(crl->mfd); return NULL; } } @@ -933,8 +954,8 @@ static void* DoMonitor(void* arg) if (fDER == -1) { WOLFSSL_MSG("DER event dir open failed"); if (fPEM != -1) - close(fPEM); - close(crl->mfd); + (void)close(fPEM); + (void)close(crl->mfd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -951,10 +972,10 @@ static void* DoMonitor(void* arg) /* signal to calling thread we're setup */ if (SignalSetup(crl, 1) != 0) { if (fPEM != -1) - close(fPEM); + (void)close(fPEM); if (fDER != -1) - close(fDER); - close(crl->mfd); + (void)close(fDER); + (void)close(crl->mfd); return NULL; } @@ -980,11 +1001,11 @@ static void* DoMonitor(void* arg) } if (fPEM != -1) - close(fPEM); + (void)close(fPEM); if (fDER != -1) - close(fDER); + (void)close(fDER); - close(crl->mfd); + (void)close(crl->mfd); return NULL; } @@ -1045,7 +1066,7 @@ static void* DoMonitor(void* arg) notifyFd = inotify_init(); if (notifyFd < 0) { WOLFSSL_MSG("inotify failed"); - close(crl->mfd); + (void)close(crl->mfd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -1055,8 +1076,8 @@ static void* DoMonitor(void* arg) IN_DELETE); if (wd < 0) { WOLFSSL_MSG("PEM notify add watch failed"); - close(crl->mfd); - close(notifyFd); + (void)close(crl->mfd); + (void)close(notifyFd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -1067,8 +1088,8 @@ static void* DoMonitor(void* arg) IN_DELETE); if (wd < 0) { WOLFSSL_MSG("DER notify add watch failed"); - close(crl->mfd); - close(notifyFd); + (void)close(crl->mfd); + (void)close(notifyFd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -1088,8 +1109,8 @@ static void* DoMonitor(void* arg) if (wd > 0) inotify_rm_watch(notifyFd, wd); - close(crl->mfd); - close(notifyFd); + (void)close(crl->mfd); + (void)close(notifyFd); return NULL; } @@ -1143,8 +1164,8 @@ static void* DoMonitor(void* arg) if (wd > 0) inotify_rm_watch(notifyFd, wd); - close(crl->mfd); - close(notifyFd); + (void)close(crl->mfd); + (void)close(notifyFd); return NULL; } diff --git a/src/include.am b/src/include.am index ee6be660e..e1c6b461d 100644 --- a/src/include.am +++ b/src/include.am @@ -444,6 +444,12 @@ if !BUILD_FIPS_V2 if BUILD_ECC src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c endif +if BUILD_ECCSI +src_libwolfssl_la_SOURCES += wolfcrypt/src/eccsi.c +endif +if BUILD_SAKKE +src_libwolfssl_la_SOURCES += wolfcrypt/src/sakke.c +endif endif if BUILD_CURVE25519 diff --git a/src/internal.c b/src/internal.c index 5f5220a8c..18732349d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1,6 +1,6 @@ /* internal.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -91,6 +91,10 @@ #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #endif +#ifdef WOLFSSL_QNX_CAAM + /* included to get CAAM devId value */ + #include +#endif #if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \ defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) @@ -170,6 +174,8 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #endif #endif + static int cipherExtraData(WOLFSSL* ssl); + #ifdef WOLFSSL_DTLS static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl); static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl); @@ -951,6 +957,7 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) } #endif #else + exp[idx++] = 0; exp[idx++] = 0; exp[idx++] = 0; if (ver > DTLS_EXPORT_VERSION_3) { @@ -1113,10 +1120,11 @@ static int dtls_export_load(WOLFSSL* ssl, const byte* exp, word32 len, byte ver) } #else if (ver > DTLS_EXPORT_VERSION_3) { - exp[idx++] = 0; + idx++; } #endif #else + idx++; idx++; idx++; if (ver > DTLS_EXPORT_VERSION_3) { @@ -1616,7 +1624,8 @@ void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) method->downgrade = 0; } -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) || \ + defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) int InitSSL_Side(WOLFSSL* ssl, word16 side) { if (ssl == NULL) @@ -1707,9 +1716,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->minEccKeySz = MIN_ECCKEY_SZ; ctx->eccTempKeySz = ECDHE_SIZE; #endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) ctx->verifyDepth = MAX_CHAIN_DEPTH; -#endif #ifdef OPENSSL_EXTRA ctx->cbioFlag = WOLFSSL_CBIO_NONE; #endif @@ -1781,7 +1788,12 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) } #endif +#ifdef WOLFSSL_QNX_CAAM + /* default to try using CAAM when built */ + ctx->devId = WOLFSSL_CAAM_DEVID; +#else ctx->devId = INVALID_DEVID; +#endif #if defined(WOLFSSL_DTLS) #ifdef WOLFSSL_SCTP @@ -1800,6 +1812,32 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #ifdef OPENSSL_EXTRA /* setup WOLFSSL_X509_STORE */ ctx->x509_store.cm = ctx->cm; + /* set pointer back to x509 store */ + ctx->cm->x509_store_p = &ctx->x509_store; + + /* WOLFSSL_X509_VERIFY_PARAM */ + if ((ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("ctx->param memory error"); + return MEMORY_E; + } + XMEMSET(ctx->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + /* WOLFSSL_X509_LOOKUP */ + if ((ctx->x509_store.lookup.dirs = + (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR), + heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("ctx-x509_store.lookup.dir memory allocation error"); + XFREE(ctx->param, heap, DYNAMIC_TYPE_OPENSSL); + return MEMORY_E; + } + XMEMSET(ctx->x509_store.lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR)); + if (wc_InitMutex(&ctx->x509_store.lookup.dirs->lock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + XFREE(ctx->param, heap, DYNAMIC_TYPE_OPENSSL); + XFREE(ctx->x509_store.lookup.dirs, heap, DYNAMIC_TYPE_OPENSSL); + return BAD_MUTEX_E; + } #endif #endif @@ -1827,10 +1865,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT; #endif -#ifdef HAVE_WOLF_EVENT - ret = wolfEventQueue_Init(&ctx->event_queue); -#endif /* HAVE_WOLF_EVENT */ - #ifdef WOLFSSL_EARLY_DATA ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ; #endif @@ -1840,11 +1874,25 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #endif ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */ - ctx->verifyDepth = MAX_CHAIN_DEPTH; + +#ifdef HAVE_WOLF_EVENT + ret = wolfEventQueue_Init(&ctx->event_queue); +#endif /* HAVE_WOLF_EVENT */ return ret; } +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data) +{ + int n_ex_data = (int)(sizeof ex_data->ex_data / sizeof ex_data->ex_data[0]); + for (--n_ex_data; n_ex_data >= 0; --n_ex_data) { + if (ex_data->ex_data[n_ex_data] != NULL) + (void)wolfSSL_CRYPTO_set_ex_data_with_cleanup(ex_data, n_ex_data, + NULL, NULL); + } +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ /* In case contexts are held in array and don't want to free actual ctx */ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) @@ -1854,6 +1902,10 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) int i; #endif +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&ctx->ex_data); +#endif + #ifdef HAVE_WOLF_EVENT wolfEventQueue_Free(&ctx->event_queue); #endif /* HAVE_WOLF_EVENT */ @@ -1947,6 +1999,20 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL); ctx->alpn_cli_protos = NULL; } + if (ctx->param) { + XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); + } + + if (ctx->x509_store.lookup.dirs) { +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (ctx->x509_store.lookup.dirs->dir_entry) { + wolfSSL_sk_BY_DIR_entry_free(ctx->x509_store.lookup.dirs->dir_entry); + } + +#endif + wc_FreeMutex(&ctx->x509_store.lookup.dirs->lock); + XFREE(ctx->x509_store.lookup.dirs, ctx->heap, DYNAMIC_TYPE_OPENSSL); + } #endif #ifdef WOLFSSL_STATIC_EPHEMERAL #ifndef NO_DH @@ -2291,7 +2357,7 @@ void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveNTRU, word16 haveECDSAsig, word16 haveECC, - word16 haveStaticECC, int side) + word16 haveStaticECC, word16 haveAnon, int side) { word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; @@ -2313,6 +2379,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, (void)side; (void)haveRSA; /* some builds won't read */ (void)haveRSAsig; /* non ecc builds won't read */ + (void)haveAnon; /* anon ciphers optional */ if (suites == NULL) { WOLFSSL_MSG("InitSuites pointer error"); @@ -2532,14 +2599,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, #endif #ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA - if (tls1_2 && haveDH) { + if (tls1_2 && haveDH && haveAnon) { suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; } #endif #ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveDH) { + if (tls1_2 && haveDH && haveAnon) { suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384; } @@ -3393,15 +3460,9 @@ void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag, void* heap) (void)heap; if (name != NULL) { + XMEMSET(name, 0, sizeof(WOLFSSL_X509_NAME)); name->name = name->staticName; - name->dynamicName = 0; - name->sz = 0; name->heap = heap; -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - XMEMSET(name->entry, 0, sizeof(name->entry)); - name->x509 = NULL; - name->entrySz = 0; -#endif /* OPENSSL_EXTRA */ } } @@ -3569,6 +3630,8 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif + default: + break; } (void)hashAlgo; (void)output; @@ -3603,6 +3666,8 @@ static void SetDigest(WOLFSSL* ssl, int hashAlgo) ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE; break; #endif /* WOLFSSL_SHA512 */ + default: + break; } /* switch */ } #endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */ @@ -3624,7 +3689,8 @@ static word32 MacSize(WOLFSSL* ssl) #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ #ifndef NO_RSA -#ifndef WOLFSSL_NO_TLS12 +#if !defined(WOLFSSL_NO_TLS12) || \ + (defined(WC_RSA_PSS) && defined(HAVE_PK_CALLBACKS)) #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) static int TypeHash(int hashAlgo) { @@ -3649,6 +3715,8 @@ static int TypeHash(int hashAlgo) case sha_mac: return SHAh; #endif + default: + break; } return 0; @@ -4349,17 +4417,16 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) /* get key size */ if (peer == NULL || peer->dp == NULL) { keySz = ssl->eccTempKeySz; + /* get curve type */ + if (ssl->ecdhCurveOID > 0) { + ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL); + } } else { keySz = peer->dp->size; ecc_curve = peer->dp->id; } - /* get curve type */ - if (ssl->ecdhCurveOID > 0) { - ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL); - } - #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccKeyGenCb) { void* ctx = wolfSSL_GetEccKeyGenCtx(ssl); @@ -4697,6 +4764,8 @@ static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key, } #endif /* HAVE_CURVE25519 */ +#endif /* !WOLFSSL_NO_TLS12 */ + #ifdef HAVE_ED448 /* Check whether the key contains a public key. * If not then pull it out of the leaf certificate. @@ -4865,6 +4934,8 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, } #endif /* HAVE_ED448 */ +#ifndef WOLFSSL_NO_TLS12 + #ifdef HAVE_CURVE448 #ifdef HAVE_PK_CALLBACKS /* Gets X448 key for shared secret callback testing @@ -4999,6 +5070,8 @@ static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer) } #endif /* HAVE_CURVE448 */ +#endif /* !WOLFSSL_NO_TLS12 */ + #if !defined(NO_CERTS) || !defined(NO_PSK) #if !defined(NO_DH) @@ -5034,7 +5107,8 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, int DhAgree(WOLFSSL* ssl, DhKey* dhKey, const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, - byte* agree, word32* agreeSz) + byte* agree, word32* agreeSz, + const byte* prime, word32 primeSz) { int ret; @@ -5061,9 +5135,18 @@ int DhAgree(WOLFSSL* ssl, DhKey* dhKey, #endif { #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) - ret = wc_DhCheckPubValue(ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, otherPub, otherPubSz); + /* check the public key has valid number */ + if (dhKey != NULL && (prime == NULL || primeSz == 0)) { + /* wc_DhCheckPubKey does not do exponentiation */ + ret = wc_DhCheckPubKey(dhKey, otherPub, otherPubSz); + } + else { + ret = wc_DhCheckPubValue(prime, primeSz, otherPub, otherPubSz); + } if (ret != 0) { + /* translate to valid error (wc_DhCheckPubValue returns MP_VAL -1) */ + ret = PEER_KEY_ERROR; + #ifdef OPENSSL_EXTRA SendAlert(ssl, alert_fatal, illegal_parameter); #endif @@ -5085,13 +5168,14 @@ int DhAgree(WOLFSSL* ssl, DhKey* dhKey, WOLFSSL_LEAVE("DhAgree", ret); + (void)prime; + (void)primeSz; + return ret; } #endif /* !NO_DH */ #endif /* !NO_CERTS || !NO_PSK */ -#endif /* !WOLFSSL_NO_TLS12 */ - #ifdef HAVE_PK_CALLBACKS int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl) @@ -5209,13 +5293,15 @@ int InitSSL_Suites(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } else { InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, TRUE, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) @@ -5409,6 +5495,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.server_psk_cb = ctx->server_psk_cb; ssl->options.psk_ctx = ctx->psk_ctx; #ifdef WOLFSSL_TLS13 + ssl->options.client_psk_cs_cb = ctx->client_psk_cs_cb; ssl->options.client_psk_tls13_cb = ctx->client_psk_tls13_cb; ssl->options.server_psk_tls13_cb = ctx->server_psk_tls13_cb; #endif @@ -5526,6 +5613,11 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #endif #endif +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + ssl->AcceptFilter = ctx->AcceptFilter; + ssl->AcceptFilter_arg = ctx->AcceptFilter_arg; +#endif + ssl->CBIORecv = ctx->CBIORecv; ssl->CBIOSend = ctx->CBIOSend; #ifdef OPENSSL_EXTRA @@ -5755,9 +5847,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->wfd = -1; ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */ - ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ - ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ - #ifdef HAVE_NETX ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */ ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ @@ -5771,7 +5860,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #elif defined (WOLFSSL_GNRC) ssl->IOCB_ReadCtx = ssl->gnrcCtx; ssl->IOCB_WriteCtx = ssl->gnrcCtx; +#else + ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ + ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ #endif + /* initialize states */ ssl->options.serverState = NULL_STATE; ssl->options.clientState = NULL_STATE; @@ -5796,7 +5889,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #endif #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) ssl->dtlsMtuSz = ctx->dtlsMtuSz; - ssl->dtls_expected_rx = ssl->dtlsMtuSz; + /* Add some bytes so that we can operate with slight difference + * in set MTU size on each peer */ + ssl->dtls_expected_rx = ssl->dtlsMtuSz + + DTLS_MTU_ADDITIONAL_READ_BUFFER; #else ssl->dtls_expected_rx = MAX_MTU; #endif @@ -6177,10 +6273,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) return BAD_FUNC_ARG; } - if (sz == 0) { - return NOT_COMPILED_IN; - } - /* Allocate memory for key */ *pKey = (void *)XMALLOC(sz, ssl->heap, type); if (*pKey == NULL) { @@ -6342,7 +6434,9 @@ void FreeSuites(WOLFSSL* ssl) #endif { #ifdef OPENSSL_ALL - wolfSSL_sk_SSL_CIPHER_free(ssl->suites->stack); + if (ssl->suites != NULL) { + wolfSSL_sk_SSL_CIPHER_free(ssl->suites->stack); + } #endif XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); } @@ -6359,6 +6453,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) * example with the RNG, it isn't used beyond the handshake except when * using stream ciphers where it is retained. */ +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&ssl->ex_data); +#endif + FreeCiphers(ssl); FreeArrays(ssl, 0); FreeKeyExchange(ssl); @@ -6428,9 +6526,14 @@ void SSL_ResourceFree(WOLFSSL* ssl) #endif /* WOLFSSL_DTLS */ #ifdef OPENSSL_EXTRA #ifndef NO_BIO + /* Don't free if there was/is a previous element in the chain. + * This means that this BIO was part of a chain that will be + * free'd separately. */ if (ssl->biord != ssl->biowr) /* only free write if different */ - wolfSSL_BIO_free(ssl->biowr); - wolfSSL_BIO_free(ssl->biord); /* always free read bio */ + if (ssl->biowr != NULL && ssl->biowr->prev == NULL) + wolfSSL_BIO_free(ssl->biowr); + if (ssl->biord != NULL && ssl->biord->prev == NULL) + wolfSSL_BIO_free(ssl->biord); ssl->biowr = NULL; ssl->biord = NULL; #endif @@ -7100,7 +7203,8 @@ int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte ty { WOLFSSL_ENTER("DtlsMsgSet()"); if (msg != NULL && data != NULL && msg->fragSz <= msg->sz && - (fragOffset + fragSz) <= msg->sz) { + fragSz <= msg->sz && fragOffset <= msg->sz && + (fragOffset + fragSz) <= msg->sz) { DtlsFrag* cur = msg->fragList; DtlsFrag* prev = cur; DtlsFrag* newFrag; @@ -7493,7 +7597,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) input = pool->buf; inputSz = pool->sz; - sendSz = inputSz + MAX_MSG_EXTRA; + sendSz = inputSz + cipherExtraData(ssl); #ifdef HAVE_SECURE_RENEGOTIATION /* @@ -7668,7 +7772,7 @@ ProtocolVersion MakeDTLSv1_2(void) word32 LowResTimer(void) { const word32 systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); - word32 *systemTickPtr = systemTickPointer(); + const volatile word32 *systemTickPtr = systemTickPointer(); return (word32) *systemTickPtr/systemTickTimeInHz; } @@ -7833,7 +7937,12 @@ ProtocolVersion MakeDTLSv1_2(void) return (word32)XTIME(0); } #endif +#else + /* user must supply timer function to return elapsed seconds: + * word32 LowResTimer(void); + */ #endif /* !NO_ASN_TIME */ + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) @@ -8064,7 +8173,8 @@ static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl) #ifndef WOLFSSL_NO_TLS12 #if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_SERVER) || \ - !defined(WOLFSSL_NO_CLIENT_AUTH)) + !defined(WOLFSSL_NO_CLIENT_AUTH)) || \ + defined(WOLFSSL_DTLS) static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, word32 length, byte type, WOLFSSL* ssl) { @@ -8083,6 +8193,162 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl); } #endif /* NO_CERTS */ + +/** + * Send the handshake message. This function handles fragmenting the message + * so that it will fit into the desired MTU or the max fragment size. + * @param ssl Connection object + * @param input Input starting at the record layer header. This function + * assumes that the appropriate record and handshake headers + * are present. These headers must assume no fragmentation. + * That is handled here. + * @param inputSz Length of message excluding headers (this is the total + * length of all fragments) + * @param type Type of message being sent + * @return 0 on success and negative otherwise + */ +static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz, + enum HandShakeType type, const char* packetName) +{ + int maxFrag; + int ret = 0; + int headerSz; + + WOLFSSL_ENTER("SendHandshakeMsg"); + (void)type; + (void)packetName; + + if (ssl == NULL || input == NULL) + return BAD_FUNC_ARG; +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + headerSz = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ; + else +#endif + { + /* In TLS we send one handshake header in total, not one + * per fragment like in DTLS. The handshake header should + * already be in the input buffer. */ + inputSz += HANDSHAKE_HEADER_SZ; + headerSz = RECORD_HEADER_SZ; + } + maxFrag = wolfSSL_GetMaxRecordSize(ssl, (int)inputSz); + + /* Make sure input is not the ssl output buffer as this + * function doesn't handle that */ + if (input >= ssl->buffers.outputBuffer.buffer && + input <= ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.bufferSize) { + WOLFSSL_MSG("Can't use output buffer for input in SendHandshakeMsg"); + return BAD_FUNC_ARG; + } + if (ssl->fragOffset == 0) { + /* Hash it before the loop as we modify the input with + * encryption on */ + ret = HashOutput(ssl, input, headerSz + (int)inputSz, 0); + if (ret != 0) + return ret; +#ifdef WOLFSSL_DTLS + /* Decrement msg number so that we continue to use the + * same msg number for this msg */ + if (ssl->options.dtls) + ssl->keys.dtls_handshake_number--; +#endif + } + while (ssl->fragOffset < inputSz) { + byte* output; + int outputSz; + byte* data = input + ssl->fragOffset + headerSz; + word32 fragSz = (word32)maxFrag; + if (inputSz - ssl->fragOffset < fragSz) + fragSz = inputSz - ssl->fragOffset; + + /* check for available size */ + outputSz = headerSz + fragSz; + if (IsEncryptionOn(ssl, 1)) + outputSz += cipherExtraData(ssl); + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + /* scan-build complains that this may be null */ + if (output == NULL) + return MEMORY_E; + + if (IsEncryptionOn(ssl, 1)) { + /* First we need to add the fragment header ourselves. + * We do this in the input to minimize allocations */ + int dataSz = (int)fragSz; +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + data -= DTLS_HANDSHAKE_HEADER_SZ; + dataSz += DTLS_HANDSHAKE_HEADER_SZ; + AddHandShakeHeader(data, + inputSz, ssl->fragOffset, fragSz, type, ssl); + } + if (ssl->options.dtls) + ssl->keys.dtls_handshake_number--; + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, data, + fragSz + DTLS_HANDSHAKE_HEADER_SZ, type)) + != 0) + return ret; +#endif + ret = BuildMessage(ssl, output, outputSz, + data, dataSz, handshake, 0, 0, 0, CUR_ORDER); + if (ret >= 0) + outputSz = ret; + else + return ret; + ret = 0; + } + else { +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + AddFragHeaders(output, fragSz, ssl->fragOffset, + inputSz, type, ssl); + else +#endif + AddRecordHeader(output, fragSz, handshake, ssl, CUR_ORDER); + + XMEMCPY(output + headerSz, data, fragSz); +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->keys.dtls_handshake_number--; + DtlsSEQIncrement(ssl, CUR_ORDER); + } + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, headerSz + fragSz, + type)) != 0) { + return ret; + } + } +#endif + } + ssl->buffers.outputBuffer.length += outputSz; +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) { + AddPacketName(ssl, packetName); + } + if (ssl->toInfoOn) { + AddPacketInfo(ssl, packetName, handshake, + output, outputSz, WRITE_PROTO, ssl->heap); + } +#endif + ssl->fragOffset += fragSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + if (ret != 0) + return ret; + } +#ifdef WOLFSSL_DTLS + /* Increment msg number once we sent all fragments */ + if (ssl->options.dtls) + ssl->keys.dtls_handshake_number++; +#endif + ssl->fragOffset = 0; + return ret; +} #endif /* !WOLFSSL_NO_TLS12 */ @@ -8309,10 +8575,8 @@ static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) the header, if the user wants encrypted alignment they need to define their alignment requirement */ - if (align) { - while (align < hdrSz) - align *= 2; - } + while (align < hdrSz) + align *= 2; #endif tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align, @@ -8448,14 +8712,31 @@ int CheckAvailableSize(WOLFSSL *ssl, int size) } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls && - size + ssl->buffers.outputBuffer.length - - ssl->buffers.outputBuffer.idx > ssl->dtls_expected_rx) { - int ret; - WOLFSSL_MSG("CheckAvailableSize() flushing buffer " - "to make room for new message"); - if ((ret = SendBuffered(ssl)) != 0) { - return ret; + if (ssl->options.dtls) { + if (size + ssl->buffers.outputBuffer.length - + ssl->buffers.outputBuffer.idx > +#if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) + ssl->dtlsMtuSz +#else + ssl->dtls_expected_rx +#endif + ) { + int ret; + WOLFSSL_MSG("CheckAvailableSize() flushing buffer " + "to make room for new message"); + if ((ret = SendBuffered(ssl)) != 0) { + return ret; + } + } + if (size > (int) +#if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) + ssl->dtlsMtuSz +#else + ssl->dtls_expected_rx +#endif + ) { + WOLFSSL_MSG("CheckAvailableSize() called with size greater than MTU."); + return DTLS_SIZE_ERROR; } } #endif @@ -8570,6 +8851,11 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return LENGTH_ERROR; #endif + if (*size == 0 && rh->type != application_data) { + WOLFSSL_MSG("0 length, non-app data record."); + return LENGTH_ERROR; + } + /* verify record type here as well */ switch (rh->type) { case handshake: @@ -8826,62 +9112,61 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (first == CHACHA_BYTE) { switch (second) { - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_RSA) - return 1; - break; + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_ECC) - return 1; - break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; - case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_RSA) - return 1; - if (requirement == REQUIRES_DHE) - return 1; - break; + case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; - case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - if (requirement == REQUIRES_RSA) - return 1; - break; + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; - case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - if (requirement == REQUIRES_ECC) - return 1; - break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; - case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - if (requirement == REQUIRES_RSA) - return 1; - if (requirement == REQUIRES_DHE) - return 1; - break; + case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; - case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_PSK) - return 1; - break; + case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; - case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_PSK) - return 1; - break; + case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; - case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_PSK) - return 1; - if (requirement == REQUIRES_DHE) - return 1; - break; - } + case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + } if (requirement == REQUIRES_AEAD) return 1; - } #endif /* HAVE_CHACHA */ @@ -9800,9 +10085,13 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } else { wolfSSL_ASN1_OBJECT_free(x509->key.algor->algorithm); } - if (!(x509->key.algor->algorithm = - wolfSSL_OBJ_nid2obj(dCert->keyOID))) { - ret = PUBLIC_KEY_E; + if (!x509->key.algor) { + ret = MEMORY_E; + } else { + if (!(x509->key.algor->algorithm = + wolfSSL_OBJ_nid2obj(dCert->keyOID))) { + ret = PUBLIC_KEY_E; + } } wolfSSL_EVP_PKEY_free(x509->key.pkey); @@ -10524,6 +10813,198 @@ static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) args->dCert = NULL; } } +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +/* load certificate file which has the form .(r)N[0..N] */ +/* in the folder. */ +/* (r), in the case of CRL file */ +/* @param store a pointer to X509_STORE structure */ +/* @param issuer a pointer to X509_NAME that presents an issuer */ +/* @param type X509_LU_X509 or X509_LU_CRL */ +/* @return WOLFSSL_SUCCESS on successful, otherwise WOLFSSL_FAILURE */ +int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type) +{ + const int MAX_SUFFIX = 10;/* The number comes from CA_TABLE_SIZE=10 */ + int ret = WOLFSSL_SUCCESS; + WOLFSSL_X509_LOOKUP* lookup; + WOLFSSL_BY_DIR_entry* entry; + WOLFSSL_BY_DIR_HASH hash_tmp; + WOLFSSL_BY_DIR_HASH* ph = NULL; + WOLFSSL_X509* x509; + unsigned long hash = 0; + char* filename = NULL; + const char* post = ""; + byte* pbuf = NULL; + int len, num, i, index; + byte suffix = 0; + int retHash = NOT_COMPILED_IN; + byte dgt[WC_MAX_DIGEST_SIZE]; + + WOLFSSL_ENTER("LoadCertByIssuer"); + + /* sanity check */ + if (store == NULL || issuer == NULL || (type != X509_LU_X509 && type != X509_LU_CRL)) { + return WOLFSSL_FAILURE; + } + lookup = &store->lookup; + if (lookup->dirs == NULL || lookup->type != 1) { + return WOLFSSL_FAILURE; + } + + len = wolfSSL_i2d_X509_NAME_canon(issuer, &pbuf); + if (len > 0) { + #ifndef NO_SHA + retHash = wc_ShaHash((const byte*)pbuf, len, dgt); + #endif + if (retHash == 0) { + /* 4 bytes in little endian as unsigned long */ + hash = (((unsigned long)dgt[3] << 24) | + ((unsigned long)dgt[2] << 16) | + ((unsigned long)dgt[1] << 8) | + ((unsigned long)dgt[0])); + } else { + WOLFSSL_MSG("failed hash operation"); + return WOLFSSL_FAILURE; + } + wolfSSL_OPENSSL_free(pbuf); + } + + /* try to load each hashed name file in path */ +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + + if (type == X509_LU_CRL) { + post = "r"; + } + + num = wolfSSL_sk_BY_DIR_entry_num(lookup->dirs->dir_entry); + + for (i=0; idirs->dir_entry, i); + + if (type == X509_LU_CRL && entry->hashes != NULL && + wolfSSL_sk_BY_DIR_HASH_num(entry->hashes) > 0) { + /* lock the list */ + if (wc_LockMutex(&lookup->dirs->lock) != 0) { + WOLFSSL_MSG("wc_LockMutex cdir Lock error"); + return BAD_MUTEX_E; + } + + hash_tmp.hash_value = hash; + index = wolfSSL_sk_BY_DIR_HASH_find(entry->hashes, &hash_tmp); + if (index >= 0) { + WOLFSSL_MSG("find hashed CRL in list"); + ph = wolfSSL_sk_BY_DIR_HASH_value(entry->hashes, index); + suffix = ph->last_suffix; + } else { + ph = NULL; + suffix = 0; + } + + wc_UnLockMutex(&lookup->dirs->lock); + } + + /* Additional buffer length for file name memory allocation : */ + /* / .(r)N\0 */ + /*|1| 8 |1|1|1|1| => 13 */ + len = (int)XSTRLEN(entry->dir_name) + 13; + if (filename != NULL) { + XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL); + } + + filename = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (filename == NULL) { + WOLFSSL_MSG("memory allocation error"); + return MEMORY_E; + } + + /* set as FAILURE, if successfuly loading cert of CRL, this becomes */ + /* WOLFSSL_SUCCESS */ + ret = WOLFSSL_FAILURE; + + for (; suffix < MAX_SUFFIX; suffix++) { + /* /folder-path/.(r)N[0..9] */ + XSNPRINTF(filename, len, "%s/%08lx.%s%d", entry->dir_name, + hash, post, suffix); + if(wc_FileExists(filename) == 0/*0 file exists */) { + + if (type == X509_LU_X509) { + x509 = wolfSSL_X509_load_certificate_file(filename, + WOLFSSL_FILETYPE_PEM); + if (x509 != NULL) { + ret = wolfSSL_X509_STORE_add_cert(store, x509); + wolfSSL_X509_free(x509); + } else { + WOLFSSL_MSG("failed to load certificate\n"); + ret = WOLFSSL_FAILURE; + break; + } + } +#ifdef HAVE_CRL + else if (type == X509_LU_CRL) { + ret = wolfSSL_X509_load_crl_file(&store->lookup, filename, + WOLFSSL_FILETYPE_PEM); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("failed to load CRL\n"); + break; + } + } +#else + else if (type == X509_LU_CRL) { + WOLFSSL_MSG("CRL is not supported"); + ret = WOLFSSL_FAILURE; + break; + } +#endif + } else + break; + } + + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("not found file"); + ret = WOLFSSL_FAILURE; + } else { + if (type == X509_LU_CRL) { + if (wc_LockMutex(&lookup->dirs->lock) != 0) { + WOLFSSL_MSG("wc_LockMutex cdir Lock error"); + XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL); + return BAD_MUTEX_E; + } + if (ph == NULL) { + ph = wolfSSL_BY_DIR_HASH_new(); + if (ph == NULL) { + WOLFSSL_MSG("failed to allocate hash stack"); + ret = WOLFSSL_FAILURE; + } else { + ph->hash_value = hash; + ph->last_suffix = suffix; + + ret = wolfSSL_sk_BY_DIR_HASH_push(entry->hashes, ph); + } + } + wc_UnLockMutex(&lookup->dirs->lock); + } + } + + XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else + (void) type; + (void) ret; + (void) x509; + (void) filename; + (void) suffix; + (void) num; + (void) i; + ret = WOLFSSL_NOT_IMPLEMENTED; +#endif + WOLFSSL_LEAVE("LoadCertByIssuer", ret); + + return ret; +} +#endif + static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, int certType, int verify, byte** pSubjectHash, int* pAlreadySigner) @@ -10840,21 +11321,12 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif args->idx += ctxSz; - #ifdef OPENSSL_EXTRA /* allocate buffer for cert extensions */ args->exts = (buffer*)XMALLOC(sizeof(buffer) * - (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_CERT_EXT); + MAX_CHAIN_DEPTH, ssl->heap, DYNAMIC_TYPE_CERT_EXT); if (args->exts == NULL) { ERROR_OUT(MEMORY_E, exit_ppc); } - #else - /* allocate buffer for cert extensions */ - args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, - ssl->heap, DYNAMIC_TYPE_CERT_EXT); - if (args->exts == NULL) { - ERROR_OUT(MEMORY_E, exit_ppc); - } - #endif } #endif @@ -10945,7 +11417,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->idx += extSz; listSz -= extSz + OPAQUE16_LEN; ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer, - args->exts[args->totalCerts].length, certificate, NULL); + (word16)args->exts[args->totalCerts].length, + certificate, NULL); if (ret < 0) { ERROR_OUT(ret, exit_ppc); } @@ -11050,6 +11523,31 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, !ssl->options.verifyNone ? VERIFY : NO_VERIFY, &subjectHash, &alreadySigner); +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (ret == ASN_NO_SIGNER_E) { + WOLFSSL_MSG("try to load certificate if hash dir is set"); + if (ssl->ctx->x509_store_pt != NULL) { + ret = LoadCertByIssuer(ssl->ctx->x509_store_pt, + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); + } else { + ret = LoadCertByIssuer(&ssl->ctx->x509_store, + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); + } + if (ret == WOLFSSL_SUCCESS) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + /* once again */ + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, + !ssl->options.verifyNone ? VERIFY : NO_VERIFY, + &subjectHash, &alreadySigner); + } else + ret = ASN_NO_SIGNER_E; + } +#endif #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) goto exit_ppc; @@ -11243,6 +11741,31 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, !ssl->options.verifyNone ? VERIFY : NO_VERIFY, &subjectHash, &alreadySigner); +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (ret == ASN_NO_SIGNER_E) { + WOLFSSL_MSG("try to load certificate if hash dir is set"); + if (ssl->ctx->x509_store_pt != NULL) { + ret = LoadCertByIssuer(ssl->ctx->x509_store_pt, + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); + } else { + ret = LoadCertByIssuer(&ssl->ctx->x509_store, + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); + } + if (ret == WOLFSSL_SUCCESS) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + /* once again */ + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, + !ssl->options.verifyNone ? VERIFY : NO_VERIFY, + &subjectHash, &alreadySigner); + } else + ret = ASN_NO_SIGNER_E; + } +#endif #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) goto exit_ppc; @@ -11264,8 +11787,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* Check peer's certificate version number. TLS 1.2 / 1.3 * requires the clients certificate be version 3 unless a * different version has been negotiated using RFC 7250 */ - if ((ret == 0) && - (ssl->options.side == WOLFSSL_SERVER_END)) { + if (ssl->options.side == WOLFSSL_SERVER_END) { if (args->dCert->version != WOLFSSL_X509_V3) { WOLFSSL_MSG("Peers certificate was not version 3!"); args->lastErr = ASN_VERSION_E; @@ -11371,8 +11893,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ssl->options.side == WOLFSSL_CLIENT_END) { #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->status_request) { - args->fatal = TLSX_CSR_InitRequest(ssl->extensions, - args->dCert, ssl->heap); + args->fatal = (TLSX_CSR_InitRequest(ssl->extensions, + args->dCert, ssl->heap) != 0); doLookup = 0; #if defined(WOLFSSL_TLS13) if (ssl->options.tls1_3) { @@ -11399,8 +11921,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 if (ssl->status_request_v2) { - args->fatal = TLSX_CSR2_InitRequests(ssl->extensions, - args->dCert, 1, ssl->heap); + args->fatal = (TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 1, ssl->heap) != 0); doLookup = 0; } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ @@ -13234,7 +13756,7 @@ static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl) WOLFSSL_MSG("Current record sequence number from the past."); return 0; } -#ifndef WOLFSSL_DTLS_ALLOW_FUTURE +#ifdef WOLFSSL_DTLS_DISALLOW_FUTURE else if (!curLT && (diff > DTLS_SEQ_BITS)) { WOLFSSL_MSG("Rejecting message too far into the future."); return 0; @@ -13754,14 +14276,34 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, #ifdef CHACHA_AEAD_TEST int i; #endif + Keys* keys = &ssl->keys; XMEMSET(tag, 0, sizeof(tag)); XMEMSET(nonce, 0, sizeof(nonce)); XMEMSET(poly, 0, sizeof(poly)); XMEMSET(add, 0, sizeof(add)); +#if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) + /* + * For epochs 2+: + * * use ssl->secure_renegotiation when encrypting the current epoch as it + * has the current epoch cipher material + * * use PREV_ORDER if encrypting the epoch not in + * ssl->secure_renegotiation + */ /* opaque SEQ number stored for AD */ - WriteSEQ(ssl, CUR_ORDER, add); + if (ssl->options.dtls && DtlsSCRKeysSet(ssl)) { + if (ssl->keys.dtls_epoch == + ssl->secure_renegotiation->tmp_keys.dtls_epoch) { + keys = &ssl->secure_renegotiation->tmp_keys; + WriteSEQ(ssl, CUR_ORDER, add); + } + else + WriteSEQ(ssl, PREV_ORDER, add); + } + else +#endif + WriteSEQ(ssl, CUR_ORDER, add); if (ssl->options.oldPoly != 0) { /* get nonce. SEQ should not be incremented again here */ @@ -13800,7 +14342,7 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, if (ssl->options.oldPoly == 0) { /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte * record sequence number XORed with client_write_IV/server_write_IV */ - XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ); + XMEMCPY(nonce, keys->aead_enc_imp_IV, CHACHA20_IMP_IV_SZ); nonce[4] ^= add[0]; nonce[5] ^= add[1]; nonce[6] ^= add[2]; @@ -13908,6 +14450,7 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ int ret = 0; int msgLen = (sz - ssl->specs.aead_mac_size); + Keys* keys = &ssl->keys; #ifdef CHACHA_AEAD_TEST int i; @@ -13925,6 +14468,17 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, XMEMSET(nonce, 0, sizeof(nonce)); XMEMSET(add, 0, sizeof(add)); +#if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) + /* + * For epochs 2+: + * * use ssl->secure_renegotiation when decrypting the latest epoch as it + * has the latest epoch cipher material + */ + if (ssl->options.dtls && DtlsSCRKeysSet(ssl) && + ssl->keys.curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) + keys = &ssl->secure_renegotiation->tmp_keys; +#endif + /* sequence number field is 64-bits */ WriteSEQ(ssl, PEER_ORDER, add); @@ -13954,7 +14508,7 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, if (ssl->options.oldPoly == 0) { /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte * record sequence number XORed with client_write_IV/server_write_IV */ - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ); + XMEMCPY(nonce, keys->aead_dec_imp_IV, CHACHA20_IMP_IV_SZ); nonce[4] ^= add[0]; nonce[5] ^= add[1]; nonce[6] ^= add[2]; @@ -13999,7 +14553,7 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, return ret; } if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, - sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) { + sizeof(add), input, msgLen, tag, sizeof(tag))) != 0) { ForceZero(poly, sizeof(poly)); return ret; } @@ -14332,6 +14886,9 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 #endif /* BUILD_AESGCM || HAVE_AESCCM */ break; } + + default: + break; } /* Reset state */ @@ -14621,6 +15178,9 @@ static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* BUILD_AESGCM || HAVE_AESCCM */ break; } + + default: + break; } /* Reset state */ @@ -15351,7 +15911,7 @@ int ProcessReply(WOLFSSL* ssl) used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; if (used < ssl->curSize) - if ((ret = GetInputData(ssl, ssl->curSize)) < 0) + if ((ret = GetInputData(ssl, ssl->curSize - used)) < 0) return ret; #endif /* WOLFSSL_DTLS */ } @@ -15379,6 +15939,7 @@ int ProcessReply(WOLFSSL* ssl) ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, &ssl->curRL, &ssl->curSize); + #ifdef WOLFSSL_DTLS if (ssl->options.dtls && ret == SEQUENCE_ERROR) { WOLFSSL_MSG("Silently dropping out of order DTLS message"); @@ -15547,7 +16108,7 @@ int ProcessReply(WOLFSSL* ssl) ret = Decrypt(ssl, in->buffer + in->idx, in->buffer + in->idx, - ssl->curSize - digestSz); + ssl->curSize - (word16)digestSz); if (ret == 0) { ssl->keys.padSz = in->buffer[in->idx + ssl->curSize - @@ -15866,6 +16427,12 @@ int ProcessReply(WOLFSSL* ssl) #endif #ifndef WOLFSSL_NO_TLS12 + if (ssl->buffers.inputBuffer.idx >= + ssl->buffers.inputBuffer.length || + ssl->curSize < 1) { + WOLFSSL_MSG("ChangeCipher msg too short"); + return LENGTH_ERROR; + } if (ssl->buffers.inputBuffer.buffer[ ssl->buffers.inputBuffer.idx] != 1) { WOLFSSL_MSG("ChangeCipher msg wrong value"); @@ -15892,7 +16459,7 @@ int ProcessReply(WOLFSSL* ssl) if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); ssl->buffers.inputBuffer.idx += digestSz; - ssl->curSize -= digestSz; + ssl->curSize -= (word16)digestSz; } #endif } @@ -16496,7 +17063,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int epochOrder) { #ifndef WOLFSSL_NO_TLS12 - int ret = 0; + int ret; BuildMsgArgs* args; BuildMsgArgs lcl_args; #ifdef WOLFSSL_ASYNC_CRYPT @@ -16523,8 +17090,8 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } #endif - ret = WC_NOT_PENDING_E; #ifdef WOLFSSL_ASYNC_CRYPT + ret = WC_NOT_PENDING_E; if (asyncOkay) { ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); if (ret != WC_NOT_PENDING_E) { @@ -16540,7 +17107,10 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } /* Reset state */ - if (ret == WC_NOT_PENDING_E) { +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_NOT_PENDING_E) +#endif + { ret = 0; ssl->options.buildMsgState = BUILD_MSG_BEGIN; XMEMSET(args, 0, sizeof(BuildMsgArgs)); @@ -16830,8 +17400,9 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMWrite) { ret = Encrypt(ssl, output + args->headerSz, - output + args->headerSz, - args->size - args->digestSz, asyncOkay); + output + args->headerSz, + (word16)(args->size - args->digestSz), + asyncOkay); } else #endif @@ -16895,6 +17466,9 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ } + FALL_THROUGH; + default: + break; } exit_buildmsg: @@ -17197,8 +17771,6 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, #endif #endif /* !NO_WOLFSSL_SERVER */ -#if (!defined(WOLFSSL_NO_TLS12) && !defined(NO_CERTS)) \ - || (defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)) static int cipherExtraData(WOLFSSL* ssl) { /* Cipher data that may be added by BuildMessage */ @@ -17206,7 +17778,6 @@ static int cipherExtraData(WOLFSSL* ssl) ssl->specs.aead_mac_size + ssl->specs.iv_size + ssl->specs.pad_size; } -#endif #ifndef WOLFSSL_NO_TLS12 @@ -17270,16 +17841,6 @@ int SendCertificate(WOLFSSL* ssl) maxFragment = MAX_RECORD_SIZE; - if (ssl->options.dtls) { - #ifdef WOLFSSL_DTLS - /* The 100 bytes is used to account for the UDP and IP headers. - It can also include the record padding and MAC if the - SendCertificate is called for a secure renegotiation. */ - maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ - - DTLS_HANDSHAKE_HEADER_SZ - 100; - #endif /* WOLFSSL_DTLS */ - } - maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment); while (length > 0 && ret == 0) { @@ -18040,9 +18601,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) { int sent = 0, /* plainText size */ sendSz, - ret, - dtlsExtra = 0; + ret; +#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP) int groupMsgs = 0; +#endif if (ssl->error == WANT_WRITE #ifdef WOLFSSL_ASYNC_CRYPT @@ -18093,7 +18655,11 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } /* last time system socket output buffer was full, try again to send */ - if (!groupMsgs && ssl->buffers.outputBuffer.length > 0) { + if (ssl->buffers.outputBuffer.length > 0 + #if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP) + && !groupMsgs + #endif + ) { WOLFSSL_MSG("output buffer was full, trying to send again"); if ( (ssl->error = SendBuffered(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); @@ -18117,14 +18683,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } } -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - dtlsExtra = DTLS_RECORD_EXTRA; - } -#endif - for (;;) { - int len; byte* out; byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ int buffSz; /* may switch on comp */ @@ -18135,19 +18694,21 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (sent == sz) break; - len = wolfSSL_GetMaxRecordSize(ssl, sz - sent); + buffSz = wolfSSL_GetMaxRecordSize(ssl, sz - sent); #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_DTLS_SIZE_CHECK) - if (ssl->options.dtls && (len < sz - sent)) { + if (ssl->options.dtls && (buffSz < sz - sent)) { ssl->error = DTLS_SIZE_ERROR; WOLFSSL_ERROR(ssl->error); return ssl->error; } #endif - buffSz = len; + outputSz = buffSz + COMP_EXTRA + DTLS_RECORD_HEADER_SZ + + DTLS_HANDSHAKE_HEADER_SZ; + if (IsEncryptionOn(ssl, 1)) + outputSz += cipherExtraData(ssl); /* check for available size */ - outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA; if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) return ssl->error = ret; @@ -18190,7 +18751,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) WOLFSSL_ERROR(ssl->error); /* store for next call if WANT_WRITE or user embedSend() that doesn't present like WANT_WRITE */ - ssl->buffers.plainSz = len; + ssl->buffers.plainSz = buffSz; ssl->buffers.prevSent = sent; if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || ssl->options.isClosed)) { @@ -18201,7 +18762,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) return ssl->error; } - sent += len; + sent += buffSz; /* only one message per attempt */ if (ssl->options.partialWrite == 1) { @@ -18917,6 +19478,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case NO_CERT_ERROR: return "TLS1.3 No Certificate Set Error"; + case TOO_MUCH_EARLY_DATA: + return "Too much early data"; + + case SOCKET_FILTERED_E: + return "Session stopped by network filter"; + default : return "unknown error number"; } @@ -19936,7 +20503,7 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo) defined(USE_ECDSA_KEYSZ_HASH_ALGO) static int CmpEccStrength(int hashAlgo, int curveSz) { - int dgstSz = GetMacDigestSize(hashAlgo); + int dgstSz = GetMacDigestSize((byte)hashAlgo); if (dgstSz <= 0) return -1; return dgstSz - (curveSz & (~0x3)); @@ -19955,6 +20522,7 @@ static byte MinHashAlgo(WOLFSSL* ssl) return sha256_mac; } #endif /* WOLFSSL_NO_TLS12 */ + (void)ssl; return sha_mac; } @@ -21428,19 +21996,20 @@ exit_dpk: /* Make sure client setup is valid for this suite, true on success */ int VerifyClientSuite(WOLFSSL* ssl) { - int havePSK = 0; + #ifndef NO_PSK + int havePSK = ssl->options.havePSK; + #endif byte first = ssl->options.cipherSuite0; byte second = ssl->options.cipherSuite; WOLFSSL_ENTER("VerifyClientSuite"); - #ifndef NO_PSK - havePSK = ssl->options.havePSK; - #endif - if (CipherRequires(first, second, REQUIRES_PSK)) { WOLFSSL_MSG("Requires PSK"); - if (havePSK == 0) { + #ifndef NO_PSK + if (havePSK == 0) + #endif + { WOLFSSL_MSG("Don't have PSK"); return 0; } @@ -21493,7 +22062,7 @@ exit_dpk: ato16(input + *inOutIdx, &len); *inOutIdx += OPAQUE16_LEN; - if ((*inOutIdx - begin) + len > size) + if ((len > size) || ((*inOutIdx - begin) + len > size)) return BUFFER_ERROR; if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && @@ -21670,6 +22239,7 @@ exit_dpk: case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID; #endif /* !NO_ECC_SECP */ #endif + default: break; } return ret; @@ -21722,7 +22292,7 @@ static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size, word16 length; #ifdef HAVE_FFDHE const DhParams* params = NULL; - int group = 0; + word16 group = 0; #endif if (ssl->buffers.weOwnDH) { @@ -23556,9 +24126,14 @@ int SendClientKeyExchange(WOLFSSL* ssl) } else #endif + #ifdef HAVE_ECC if (ssl->ctx->EccSharedSecretCb != NULL) { break; } + else + #endif + { + } #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_CURVE25519 @@ -23646,7 +24221,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) case TLS_ASYNC_BUILD: { args->encSz = MAX_ENCRYPT_SZ; - args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap, + args->encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, ssl->heap, DYNAMIC_TYPE_SECRET); if (args->encSecret == NULL) { ERROR_OUT(MEMORY_E, exit_scke); @@ -24084,7 +24659,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH */ @@ -24102,7 +24679,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH && !NO_PSK */ @@ -24684,14 +25263,12 @@ int SendCertificateVerify(WOLFSSL* ssl) args->sendSz += MAX_MSG_EXTRA; } - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { - goto exit_scv; - } - - /* get output buffer */ - args->output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* Use tmp buffer */ + args->input = (byte*)XMALLOC(args->sendSz, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) + ERROR_OUT(MEMORY_E, exit_scv); + args->output = args->input; /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_BUILD; @@ -24732,7 +25309,7 @@ int SendCertificateVerify(WOLFSSL* ssl) /* build encoded signature buffer */ ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, + ssl->buffers.sig.buffer = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap, DYNAMIC_TYPE_SIGNATURE); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scv); @@ -24782,9 +25359,10 @@ int SendCertificateVerify(WOLFSSL* ssl) } #ifndef NO_OLD_TLS else { - /* if old TLS load MD5 and SHA hash as value to sign */ + /* if old TLS load MD5 and SHA hash as value to sign + * MD5 and SHA must be first two buffers in stucture */ XMEMCPY(ssl->buffers.sig.buffer, - (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ); + (byte*)&ssl->hsHashes->certHashes, FINISHED_SZ); } #endif @@ -24981,32 +25559,6 @@ int SendCertificateVerify(WOLFSSL* ssl) AddHeaders(args->output, (word32)args->length + args->extraSz + VERIFY_HEADER, certificate_verify, ssl); - args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + - (word32)args->length + args->extraSz + VERIFY_HEADER; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif - - if (IsEncryptionOn(ssl, 1)) { - int recordHeaderSz = RECORD_HEADER_SZ; - - if (ssl->options.dtls) - recordHeaderSz += DTLS_RECORD_EXTRA; - args->inputSz = args->sendSz - recordHeaderSz; - /* build msg adds rec hdr */ - args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, - DYNAMIC_TYPE_IN_BUFFER); - if (args->input == NULL) { - ERROR_OUT(MEMORY_E, exit_scv); - } - - XMEMCPY(args->input, args->output + recordHeaderSz, - args->inputSz); - } - /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; } /* case TLS_ASYNC_FINALIZE */ @@ -25014,59 +25566,11 @@ int SendCertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_END: { - if (IsEncryptionOn(ssl, 1)) { - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, args->input, args->inputSz, certificate_verify)) != 0) { - goto exit_scv; - } - #endif - ret = BuildMessage(ssl, args->output, - MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, - args->input, args->inputSz, handshake, - 1, 0, 1, CUR_ORDER); - #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) - goto exit_scv; - #endif - - XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); - args->input = NULL; /* make sure its not double free'd on cleanup */ - - if (ret >= 0) { - args->sendSz = ret; - ret = 0; - } - } - else { - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz, certificate_verify); - } - if (ret == 0 && ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - if (ret == 0) - ret = HashOutput(ssl, args->output, args->sendSz, 0); - } - - if (ret != 0) { + ret = SendHandshakeMsg(ssl, args->output, (word32)args->length + args->extraSz + + VERIFY_HEADER, certificate_verify, "CertificateVerify"); + if (ret != 0) goto exit_scv; - } - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) - if (ssl->hsInfoOn) - AddPacketName(ssl, "CertificateVerify"); - if (ssl->toInfoOn) - AddPacketInfo(ssl, "CertificateVerify", handshake, - args->output, args->sendSz, WRITE_PROTO, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += args->sendSz; - - if (!ssl->options.groupMessages) { - ret = SendBuffered(ssl); - } break; } default: @@ -25348,7 +25852,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; int sendSz; byte sessIdSz = ID_LEN; + #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SESSION_TICKET) byte echoId = 0; /* ticket echo id flag */ + #endif byte cacheOff = 0; /* session cache off flag */ WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND); @@ -25393,7 +25899,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* if no session cache don't send a session ID unless we're echoing * an ID as part of session tickets */ - if (echoId == 0 && cacheOff == 1) { + if (cacheOff == 1 + #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SESSION_TICKET) + && echoId == 0 + #endif + ) { length -= ID_LEN; /* adjust ID_LEN assumption */ sessIdSz = 0; } @@ -25959,14 +26469,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += MAX_MSG_EXTRA; } - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { - goto exit_sske; - } - - /* get output buffer */ - args->output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* Use tmp buffer */ + args->input = (byte*)XMALLOC(args->sendSz, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) + ERROR_OUT(MEMORY_E, exit_sske); + args->output = args->input; AddHeaders(args->output, args->length, server_key_exchange, ssl); @@ -26022,14 +26530,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += MAX_MSG_EXTRA; } - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { - goto exit_sske; - } - - /* get output buffer */ - args->output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* Use tmp buffer */ + args->input = (byte*)XMALLOC(args->sendSz, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) + ERROR_OUT(MEMORY_E, exit_sske); + args->output = args->input; AddHeaders(args->output, args->length, server_key_exchange, ssl); @@ -26082,7 +26588,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; args->exportSz = MAX_EXPORT_ECC_SZ; - args->exportBuf = (byte*)XMALLOC(args->exportSz, + args->exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, ssl->heap, DYNAMIC_TYPE_DER); if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); @@ -26140,14 +26646,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += MAX_MSG_EXTRA; } - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { - goto exit_sske; - } - - /* get output buffer */ - args->output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* Use tmp buffer */ + args->input = (byte*)XMALLOC(args->sendSz, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) + ERROR_OUT(MEMORY_E, exit_sske); + args->output = args->input; /* key data */ c16toa((word16)hintLen, args->output + args->idx); @@ -26193,7 +26697,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Export temp ECC key and add to length */ args->exportSz = MAX_EXPORT_ECC_SZ; - args->exportBuf = (byte*)XMALLOC(args->exportSz, + args->exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, ssl->heap, DYNAMIC_TYPE_DER); if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); @@ -26342,14 +26846,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += MAX_MSG_EXTRA; } - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { - goto exit_sske; - } - - /* get output buffer */ - args->output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* Use tmp buffer */ + args->input = (byte*)XMALLOC(args->sendSz, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) + ERROR_OUT(MEMORY_E, exit_sske); + args->output = args->input; /* record and message headers will be added below, when we're sure of the sig length */ @@ -26510,6 +27012,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_sske; break; #endif /* HAVE_ED448 */ + default: + break; } /* switch(ssl->specs.sig_algo) */ break; } @@ -26529,7 +27033,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, preSigSz = args->length; if (!ssl->options.usingAnon_cipher) { - word16 keySz; + word16 keySz = 0; /* sig length */ args->length += LENGTH_SZ; @@ -26552,7 +27056,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } - if (keySz == 0) { /* test if keySz has error */ + /* test if keySz has error */ + if (keySz == 0) { ERROR_OUT(keySz, exit_sske); } @@ -26583,14 +27088,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += MAX_MSG_EXTRA; } - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { - goto exit_sske; - } - - /* get output buffer */ - args->output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* Use tmp buffer */ + args->input = (byte*)XMALLOC(args->sendSz, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) + ERROR_OUT(MEMORY_E, exit_sske); + args->output = args->input; AddHeaders(args->output, args->length, server_key_exchange, ssl); @@ -26726,10 +27229,14 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } #endif /* NO_RSA */ + default: + break; } /* switch (ssl->suites->sigAlgo) */ break; } #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + default: + break; } /* switch(ssl->specs.kea) */ /* Check for error */ @@ -26850,6 +27357,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } #endif + default: + ERROR_OUT(ALGO_ID_E, exit_sske); } /* switch(ssl->specs.sig_algo) */ break; } @@ -26884,11 +27393,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } #endif /* NO_RSA */ + default: + break; } /* switch (ssl->suites->sigAlgo) */ break; } #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + default: + break; } /* switch(ssl->specs.kea) */ /* Check for error */ @@ -27035,6 +27548,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + default: + break; } /* switch(ssl->specs.kea) */ /* Check for error */ @@ -27087,73 +27602,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ - if (IsEncryptionOn(ssl, 1)) { - args->inputSz = args->length + HANDSHAKE_HEADER_SZ; - if (ssl->options.dtls) - args->inputSz += DTLS_HANDSHAKE_EXTRA; - args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, - DYNAMIC_TYPE_IN_BUFFER); - if (args->input == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - - if (args->output == NULL) { - ERROR_OUT(BUFFER_ERROR, exit_sske); - } - - if (!ssl->options.dtls) - XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, - args->inputSz); - else - XMEMCPY(args->input, args->output + DTLS_RECORD_HEADER_SZ, - args->inputSz); - - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, args->input, args->inputSz, server_key_exchange)) - != 0) { - goto exit_sske; - } - #endif - ret = BuildMessage(ssl, args->output, args->sendSz, - args->input, args->inputSz, handshake, 1, 0, 0, CUR_ORDER); - XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); - args->input = NULL; - /* make sure its not double free'd on cleanup */ - - if (ret >= 0) { - args->sendSz = ret; - ret = 0; - } - } - else { - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, - args->output, args->sendSz, server_key_exchange)) != 0) { - goto exit_sske; - } - } - - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - - ret = HashOutput(ssl, args->output, args->sendSz, 0); - if (ret != 0) { - goto exit_sske; - } - } - - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) - if (ssl->hsInfoOn) { - AddPacketName(ssl, "ServerKeyExchange"); - } - if (ssl->toInfoOn) { - AddPacketInfo(ssl, "ServerKeyExchange", handshake, - args->output, args->sendSz, WRITE_PROTO, ssl->heap); - } - #endif + ret = SendHandshakeMsg(ssl, args->output, args->length, + server_key_exchange, "ServerKeyExchange"); + if (ret != 0) + goto exit_sske; /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; @@ -27162,11 +27614,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case TLS_ASYNC_END: { - ssl->buffers.outputBuffer.length += args->sendSz; - if (!ssl->options.groupMessages) { - ret = SendBuffered(ssl); - } - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; break; } @@ -27200,10 +27647,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, defined(OPENSSL_ALL) /* search suites for specific one, idx on success, negative on error */ -#ifndef WOLFSSL_TLS13 - static -#endif - int FindSuite(Suites* suites, byte first, byte second) + static int FindSuite(Suites* suites, byte first, byte second) { int i; @@ -27225,11 +27669,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !WOLFSSL_NO_TLS12 */ - /* Make sure server cert/key are valid for this suite, true on success */ + /* Make sure server cert/key are valid for this suite, true on success + * Returns 1 for valid server suite or 0 if not found + * For asynchronous this can return WC_PENDING_E + */ static int VerifyServerSuite(WOLFSSL* ssl, word16 idx) { int haveRSA = !ssl->options.haveStaticECC; - int havePSK = 0; + #ifndef NO_PSK + int havePSK = ssl->options.havePSK; + #endif byte first; byte second; @@ -27243,10 +27692,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, first = ssl->suites->suites[idx]; second = ssl->suites->suites[idx+1]; - #ifndef NO_PSK - havePSK = ssl->options.havePSK; - #endif - if (ssl->options.haveNTRU) haveRSA = 0; @@ -27284,7 +27729,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (CipherRequires(first, second, REQUIRES_PSK)) { WOLFSSL_MSG("Requires PSK"); - if (havePSK == 0) { + #ifndef NO_PSK + if (havePSK == 0) + #endif + { WOLFSSL_MSG("Don't have PSK"); return 0; } @@ -27347,13 +27795,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.side == WOLFSSL_SERVER_END) { #ifdef HAVE_SUPPORTED_CURVES + int doHelloRetry = 0; /* Try to establish a key share. */ - int ret = TLSX_KeyShare_Establish(ssl); - if (ret == KEY_SHARE_ERROR) + int ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry); + if (doHelloRetry) { ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; - else if (ret != 0) - return 0; - #endif + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (!doHelloRetry && ret != 0) { + return 0; /* not found */ + } + #endif /* HAVE_SUPPORTED_CURVES */ } else if (first == TLS13_BYTE || (first == ECC_BYTE && (second == TLS_SHA256_SHA256 || second == TLS_SHA384_SHA384))) { @@ -27361,7 +27816,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * version. */ return 0; } -#endif +#endif /* WOLFSSL_TLS13 */ return 1; } @@ -27373,17 +27828,21 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->suites->suites[i] == peerSuites->suites[j] && ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { - if (VerifyServerSuite(ssl, i)) { - int result; + int ret = VerifyServerSuite(ssl, i); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret) { WOLFSSL_MSG("Verified suite validity"); ssl->options.cipherSuite0 = ssl->suites->suites[i]; ssl->options.cipherSuite = ssl->suites->suites[i+1]; - result = SetCipherSpecs(ssl); - if (result == 0) { - result = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + ret = SetCipherSpecs(ssl); + if (ret == 0) { + ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, peerSuites->hashSigAlgoSz); } - return result; + return ret; } else { WOLFSSL_MSG("Could not verify suite validity, continue"); @@ -27528,7 +27987,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } /* suite size */ @@ -27642,11 +28102,18 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef WOLFSSL_NO_TLS12 + /** + * Handles session resumption. + * Session tickets are checked for validity based on the time each ticket + * was created, timeout value and the current time. If the tickets are + * judged expired, falls back to full-handshake. If you want disable this + * sessin ticket validation check in TLS1.2 and below, define + * WOLFSSL_NO_TICKET_EXPRE. + */ int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites) { int ret = 0; WOLFSSL_SESSION* session; - (void)bogusID; session = GetSession(ssl, ssl->arrays->masterSecret, 1); @@ -27662,7 +28129,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (!session) { WOLFSSL_MSG("Session lookup for resume failed"); ssl->options.resuming = 0; + return ret; } +#if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TICKET_EXPIRE) && \ + !defined(NO_ASN_TIME) + /* check if the ticket is valid */ + if (LowResTimer() > session->bornOn + ssl->timeout) { + WOLFSSL_MSG("Expired session ticket, fall back to full handshake."); + ssl->options.resuming = 0; + } +#endif /* HAVE_SESSION_TICKET && !WOLFSSL_NO_TICKET_EXPIRE && !NO_ASN_TIME */ + else if (session->haveEMS != ssl->options.haveEMS) { /* RFC 7627, 5.3, server-side */ /* if old sess didn't have EMS, but new does, full handshake */ @@ -27858,7 +28335,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } #ifdef OPENSSL_EXTRA @@ -27920,7 +28398,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } } #endif @@ -28208,8 +28687,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_TLS_EXTENSIONS /* tls extensions */ - if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, - client_hello, &clSuites))) + if ((ret = TLSX_Parse(ssl, input + i, totalExtSz, client_hello, + &clSuites))) goto out; #ifdef WOLFSSL_TLS13 if (TLSX_Find(ssl->extensions, @@ -28711,6 +29190,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; case TLS_ASYNC_END: { @@ -28904,7 +29384,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (!ssl->options.tls1_3) { XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); +#ifndef NO_ASN_TIME c32toa(LowResTimer(), (byte*)&it.timestamp); +#endif it.haveEMS = ssl->options.haveEMS; } else { @@ -29074,6 +29556,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Copy the haveExtendedMasterSecret property from the ticket to * the saved session, so the property may be checked later. */ ssl->session.haveEMS = it.haveEMS; + ato32((const byte*)&it.timestamp, &ssl->session.bornOn); #ifndef NO_RESUME_SUITE_CHECK ssl->session.cipherSuite0 = it.suite[0]; ssl->session.cipherSuite = it.suite[1]; @@ -29737,10 +30220,16 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - /* Hello Verify Request should use the same sequence number as the - * Client Hello. */ - ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; - ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + /* Hello Verify Request should use the same sequence number + * as the Client Hello unless we are in renegotiation then + * don't change numbers */ +#ifdef HAVE_SECURE_RENEGOTIATION + if (!IsSCR(ssl)) +#endif + { + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + } AddHeaders(output, length, hello_verify_request, ssl); #ifdef OPENSSL_EXTRA @@ -29768,13 +30257,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], /* are we in scr */ if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = HANDSHAKE_HEADER_SZ + length; /* build msg adds rec hdr */ - int recordHeaderSz = RECORD_HEADER_SZ; - - if (ssl->options.dtls) { - recordHeaderSz += DTLS_RECORD_EXTRA; - inputSz += DTLS_HANDSHAKE_EXTRA; - } + int inputSz = DTLS_HANDSHAKE_HEADER_SZ + length; /* build msg adds rec hdr */ + int recordHeaderSz = DTLS_RECORD_HEADER_SZ; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) @@ -29790,6 +30274,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], } ssl->buffers.outputBuffer.length += sendSz; + DtlsSEQIncrement(ssl, CUR_ORDER); return SendBuffered(ssl); } @@ -30758,7 +31243,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, (word16)args->sigSz, ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH */ @@ -30771,7 +31258,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, (word16)args->sigSz, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH && !NO_PSK */ @@ -31121,16 +31610,22 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], #ifdef HAVE_SNI int SNI_Callback(WOLFSSL* ssl) { + int ad = 0; + int sniRet = 0; /* Stunnel supports a custom sni callback to switch an SSL's ctx * when SNI is received. Call it now if exists */ if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) { WOLFSSL_MSG("Calling custom sni callback"); - if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg) - == alert_fatal) { + sniRet = ssl->ctx->sniRecvCb(ssl, &ad, ssl->ctx->sniRecvCbArg); + if (sniRet == alert_fatal) { WOLFSSL_MSG("Error in custom sni callback. Fatal alert"); - SendAlert(ssl, alert_fatal, unrecognized_name); + SendAlert(ssl, alert_fatal, ad); return FATAL_ERROR; } + else if (sniRet == alert_warning) { + WOLFSSL_MSG("Error in custom sni callback. Warning alert"); + SendAlert(ssl, alert_warning, ad); + } } return 0; } @@ -31247,13 +31742,22 @@ int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment) #endif /* HAVE_MAX_FRAGMENT */ #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { + int cipherExtra = IsEncryptionOn(ssl, 1) ? cipherExtraData(ssl) : 0; if (maxFragment > MAX_UDP_SIZE) { maxFragment = MAX_UDP_SIZE; } + if (maxFragment > MAX_MTU - COMP_EXTRA - DTLS_RECORD_HEADER_SZ - + DTLS_HANDSHAKE_HEADER_SZ - cipherExtra) { + maxFragment = MAX_MTU - COMP_EXTRA - DTLS_RECORD_HEADER_SZ - + DTLS_HANDSHAKE_HEADER_SZ - cipherExtra; + } #if defined(WOLFSSL_DTLS_MTU) - if (maxFragment > - ssl->dtlsMtuSz - RECORD_HEADER_SZ - DTLS_RECORD_EXTRA) { - maxFragment = ssl->dtlsMtuSz - RECORD_HEADER_SZ - DTLS_RECORD_EXTRA; + { + int overheadSz = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ + + COMP_EXTRA + cipherExtra; + if (maxFragment > ssl->dtlsMtuSz - overheadSz) { + maxFragment = ssl->dtlsMtuSz - overheadSz; + } } #endif } @@ -31261,6 +31765,393 @@ int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment) return maxFragment; } +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +/* create an instance of WOLFSSL_BY_DIR_HASH structure */ +WOLFSSL_BY_DIR_HASH* wolfSSL_BY_DIR_HASH_new(void) +{ + WOLFSSL_BY_DIR_HASH* dir_hash; + + WOLFSSL_ENTER("wolfSSL_BY_DIR_HASH_new"); + + dir_hash = (WOLFSSL_BY_DIR_HASH*)XMALLOC(sizeof(WOLFSSL_BY_DIR_HASH), NULL, + DYNAMIC_TYPE_OPENSSL); + if (dir_hash) { + XMEMSET(dir_hash, 0, sizeof(WOLFSSL_BY_DIR_HASH)); + } + return dir_hash; +} +/* release a WOLFSSL_BY_DIR_HASH resource */ +void wolfSSL_BY_DIR_HASH_free(WOLFSSL_BY_DIR_HASH* dir_hash) +{ + if (dir_hash == NULL) + return; + + XFREE(dir_hash, NULL, DYNAMIC_TYPE_OPENSSL); +} +/* create an instance of WOLFSSL_STACK for STACK_TYPE_BY_DIR_hash */ +WOLFSSL_STACK* wolfSSL_sk_BY_DIR_HASH_new_null(void) +{ + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_new_null"); + + if (sk) { + sk->type = STACK_TYPE_BY_DIR_hash; + } + return sk; +} + +/* returns value less than 0 on fail to match + * On a successful match the priority level found is returned + */ +int wolfSSL_sk_BY_DIR_HASH_find( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, const WOLFSSL_BY_DIR_HASH* toFind) +{ + WOLFSSL_STACK* next; + int i, sz; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_find"); + + if (sk == NULL || toFind == NULL) { + return WOLFSSL_FAILURE; + } + + sz = wolfSSL_sk_BY_DIR_HASH_num(sk); + next = sk; + for (i = 0; i < sz && next != NULL; i++) { + if (next->data.dir_hash->hash_value == toFind->hash_value) { + return sz - i; /* reverse because stack pushed highest on first */ + } + next = next->next; + } + return -1; +} +/* return a number of WOLFSSL_BY_DIR_HASH in stack */ +int wolfSSL_sk_BY_DIR_HASH_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_num"); + + if (sk == NULL) + return -1; + return (int)sk->num; +} +/* return WOLFSSL_BY_DIR_HASH instance at i */ +WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.dir_hash; +} +/* pop WOLFSSL_BY_DIR_HASH instance, and remove its node from stack */ +WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_BY_DIR_HASH* hash; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_pop"); + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + hash = sk->data.dir_hash; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.dir_hash = node->data.dir_hash; + sk->next = node->next; + wolfSSL_sk_free_node(node); + } + else { /* last x509 in stack */ + sk->data.dir_hash = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return hash; +} +/* release all contents in stack, and then release stack itself. */ +/* Second argument is a function pointer to release resouces. */ +/* It calls the function to release resouces when t is passed */ +/* instead of wolfSSL_BY_DIR_HASH_free(). */ +void wolfSSL_sk_BY_DIR_HASH_pop_free(WOLF_STACK_OF(BY_DIR_HASH)* sk, + void (*f) (WOLFSSL_BY_DIR_HASH*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.dir_hash); + else + wolfSSL_BY_DIR_HASH_free(tmp->data.dir_hash); + tmp->data.dir_hash = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.dir_hash); + else + wolfSSL_BY_DIR_HASH_free(sk->data.dir_hash); + sk->data.dir_hash = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); +} +/* release all contents in stack, and then release stack itself */ +void wolfSSL_sk_BY_DIR_HASH_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk) +{ + wolfSSL_sk_BY_DIR_HASH_pop_free(sk, NULL); +} +/* Adds the WOLFSSL_BY_DIR_HASH to the stack "sk". "sk" takes control of "in" and + * tries to free it when the stack is free'd. + * + * return 1 on success 0 on fail + */ +int wolfSSL_sk_BY_DIR_HASH_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, + WOLFSSL_BY_DIR_HASH* in) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_push"); + + if (sk == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.dir_hash == NULL) { + sk->data.dir_hash = in; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.dir_hash = sk->data.dir_hash; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.dir_hash = in; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} +/* create an instance of WOLFSSL_BY_DIR_entry structure */ +WOLFSSL_BY_DIR_entry* wolfSSL_BY_DIR_entry_new(void) +{ + WOLFSSL_BY_DIR_entry* entry; + + WOLFSSL_ENTER("wolfSSL_BY_DIR_entry_new"); + + entry = (WOLFSSL_BY_DIR_entry*)XMALLOC(sizeof(WOLFSSL_BY_DIR_entry), NULL, + DYNAMIC_TYPE_OPENSSL); + + if (entry) { + XMEMSET(entry, 0, sizeof(WOLFSSL_BY_DIR_entry)); + } + return entry; +} +/* release a WOLFSSL_BY_DIR_entry resource */ +void wolfSSL_BY_DIR_entry_free(WOLFSSL_BY_DIR_entry* entry) +{ + WOLFSSL_ENTER("wolfSSL_BY_DIR_entry_free"); + + if (entry == NULL) + return; + + if (entry->hashes) { + wolfSSL_sk_BY_DIR_HASH_free(entry->hashes); + } + + if (entry->dir_name != NULL) { + XFREE(entry->dir_name, NULL, DYNAMIC_TYPE_OPENSSL); + } + + XFREE(entry, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_STACK* wolfSSL_sk_BY_DIR_entry_new_null(void) +{ + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_new_null"); + + if (sk) { + sk->type = STACK_TYPE_BY_DIR_entry; + } + return sk; +} +/* return a number of WOLFSSL_BY_DIR_entry in stack */ +int wolfSSL_sk_BY_DIR_entry_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_num"); + + if (sk == NULL) + return -1; + return (int)sk->num; +} +/* return WOLFSSL_BY_DIR_entry instance at i */ +WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.dir_entry; +} +/* pop WOLFSSL_BY_DIR_entry instance first, and remove its node from stack */ +WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_BY_DIR_entry* entry; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_pop"); + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + entry = sk->data.dir_entry; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.dir_entry = node->data.dir_entry; + sk->next = node->next; + wolfSSL_sk_free_node(node); + } + else { /* last x509 in stack */ + sk->data.dir_entry = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return entry; +} +/* release all contents in stack, and then release stack itself. */ +/* Second argument is a function pointer to release resouces. */ +/* It calls the function to release resouces when t is passed */ +/* instead of wolfSSL_BY_DIR_entry_free(). */ +void wolfSSL_sk_BY_DIR_entry_pop_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk, + void (*f) (WOLFSSL_BY_DIR_entry*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.dir_entry); + else + wolfSSL_BY_DIR_entry_free(tmp->data.dir_entry); + tmp->data.dir_entry = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.dir_entry); + else + wolfSSL_BY_DIR_entry_free(sk->data.dir_entry); + sk->data.dir_entry = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); +} +/* release all contents in stack, and then release stack itself */ +void wolfSSL_sk_BY_DIR_entry_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry) *sk) +{ + wolfSSL_sk_BY_DIR_entry_pop_free(sk, NULL); +} + +/* Adds the wolfSSL_BY_DIR_entry to the stack "sk". "sk" takes control of "in" and + * tries to free it when the stack is free'd. + * + * return 1 on success 0 on fail + */ +int wolfSSL_sk_BY_DIR_entry_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk, + WOLFSSL_BY_DIR_entry* in) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.dir_entry == NULL) { + sk->data.dir_entry = in; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.dir_entry = sk->data.dir_entry; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.dir_entry = in; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +#endif /* OPENSSL_ALL */ #undef ERROR_OUT diff --git a/src/keys.c b/src/keys.c index deb62ed43..67e65feea 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1,6 +1,6 @@ /* keys.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -1203,6 +1203,8 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif #endif /* WOLFSSL_TLS13 */ + default: + break; } } @@ -3084,10 +3086,10 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Provisioning ENCRYPT key"); if (ssl->options.side == WOLFSSL_CLIENT_END) { - WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->client_write_key, ssl->specs.key_size); } else { - WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->server_write_key, ssl->specs.key_size); } #endif wc_encrypt = &ssl->encrypt; @@ -3097,10 +3099,10 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Provisioning DECRYPT key"); if (ssl->options.side == WOLFSSL_CLIENT_END) { - WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->server_write_key, ssl->specs.key_size); } else { - WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->client_write_key, ssl->specs.key_size); } #endif wc_decrypt = &ssl->decrypt; @@ -3110,17 +3112,17 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Provisioning ENCRYPT key"); if (ssl->options.side == WOLFSSL_CLIENT_END) { - WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->client_write_key, ssl->specs.key_size); } else { - WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->server_write_key, ssl->specs.key_size); } WOLFSSL_MSG("Provisioning DECRYPT key"); if (ssl->options.side == WOLFSSL_CLIENT_END) { - WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->server_write_key, ssl->specs.key_size); } else { - WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size); + WOLFSSL_BUFFER(keys->client_write_key, ssl->specs.key_size); } #endif wc_encrypt = &ssl->encrypt; diff --git a/src/ocsp.c b/src/ocsp.c index 4862cf939..f4b264bd3 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -1,6 +1,6 @@ /* ocsp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -75,7 +75,7 @@ static void FreeOcspEntry(OcspEntry* entry, void* heap) { CertStatus *status, *next; - if (entry == NULL) + if (entry == NULL || !entry->ownStatus) return; WOLFSSL_ENTER("FreeOcspEntry"); @@ -371,6 +371,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp XMEMCPY(status, newSingle->status, sizeof(CertStatus)); status->next = entry->status; entry->status = status; + entry->ownStatus = 1; entry->totalStatus++; } } @@ -598,7 +599,9 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( (void)dgst; cm = wolfSSL_CertManagerNew(); - if (cm == NULL) + if (cm == NULL + || subject == NULL || subject->derCert == NULL + || issuer == NULL || issuer->derCert == NULL) return NULL; ret = AllocDer(&derCert, issuer->derCert->length, @@ -607,7 +610,11 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( /* AddCA() frees the buffer. */ XMEMCPY(derCert->buffer, issuer->derCert->buffer, issuer->derCert->length); - AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + ret = AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + if (ret != WOLFSSL_SUCCESS) { + wolfSSL_CertManagerFree(cm); + return NULL; + } } certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, @@ -621,27 +628,30 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( if (certStatus) XFREE(certStatus, NULL, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - - XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); - XMEMSET(certStatus, 0, sizeof(CertStatus)); - - certId->status = certStatus; - - InitDecodedCert(&cert, subject->derCert->buffer, - subject->derCert->length, NULL); - if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { - XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); certId = NULL; } - else { - XMEMCPY(certId->issuerHash, cert.issuerHash, OCSP_DIGEST_SIZE); - XMEMCPY(certId->issuerKeyHash, cert.issuerKeyHash, OCSP_DIGEST_SIZE); - XMEMCPY(certId->status->serial, cert.serial, cert.serialSz); - certId->status->serialSz = cert.serialSz; + + if (certId != NULL) { + XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); + XMEMSET(certStatus, 0, sizeof(CertStatus)); + + certId->status = certStatus; + certId->ownStatus = 1; + + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else { + XMEMCPY(certId->issuerHash, cert.issuerHash, OCSP_DIGEST_SIZE); + XMEMCPY(certId->issuerKeyHash, cert.issuerKeyHash, OCSP_DIGEST_SIZE); + XMEMCPY(certId->status->serial, cert.serial, cert.serialSz); + certId->status->serialSz = cert.serialSz; + } + FreeDecodedCert(&cert); } - FreeDecodedCert(&cert); wolfSSL_CertManagerFree(cm); @@ -797,10 +807,11 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, XMEMSET(resp->single, 0, sizeof(OcspEntry)); resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_OCSP_STATUS); + resp->single->ownStatus = 1; if (resp->single->status == NULL) { XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); + XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); return NULL; } XMEMSET(resp->single->status, 0, sizeof(CertStatus)); @@ -876,6 +887,7 @@ WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) else { XMEMCPY(bs->single, response->single, sizeof(OcspEntry)); XMEMCPY(bs->source, response->source, response->maxIdx); + bs->single->ownStatus = 0; } return bs; } @@ -912,11 +924,19 @@ int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, WOLFSSL_OCSP_CERTID *cid) { - if (req == NULL || cid == NULL) + if (req == NULL || cid == NULL || cid->status == NULL) return NULL; XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE); XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE); + if (cid->status->serialSz > req->serialSz) { + if (req->serial != NULL) + XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); + req->serial = (byte*)XMALLOC(cid->status->serialSz, + req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL) + return NULL; + } XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz); req->serialSz = cid->status->serialSz; diff --git a/src/sniffer.c b/src/sniffer.c index 3411bc7c5..1b77ae962 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1,6 +1,6 @@ /* sniffer.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -2280,7 +2280,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, /* Derive secret from private key and peer's public key */ do { #ifdef WOLFSSL_ASYNC_CRYPT - ret = wc_AsyncWait(ret, &dhPriv.asyncDev, + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { @@ -4828,7 +4828,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, word32 length; WOLFSSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? (*session)->sslServer : (*session)->sslClient; - byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? + byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? (*session)->flags.srvSkipPartial : (*session)->flags.cliSkipPartial; /* remove SnifferSession on 2nd FIN or RST */ @@ -4865,7 +4865,8 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, /* if current partial data, add to end of partial */ /* if skipping, the data is already at the end of partial */ - if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) { + length = ssl->buffers.inputBuffer.length; + if ( !skipPartial && length ) { Trace(PARTIAL_ADD_STR); if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { @@ -4882,46 +4883,46 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, *sslFrame = ssl->buffers.inputBuffer.buffer; *end = *sslFrame + *sslBytes; } - } - if (vChain != NULL) { -#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT - struct iovec* chain = (struct iovec*)vChain; - word32 i, offset, headerSz, qty, remainder; + if (vChain != NULL) { + #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + struct iovec* chain = (struct iovec*)vChain; + word32 i, offset, headerSz, qty, remainder; - Trace(CHAIN_INPUT_STR); - headerSz = (word32)((const byte*)*sslFrame - (const byte*)chain[0].iov_base); - remainder = *sslBytes; + Trace(CHAIN_INPUT_STR); + headerSz = (word32)((const byte*)*sslFrame - (const byte*)chain[0].iov_base); + remainder = *sslBytes; - if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { - if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { - SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); - return -1; + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { + SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); + return -1; + } } + + qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz); + XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], + (byte*)chain[0].iov_base + headerSz, qty); + offset = length; + for (i = 1; i < chainSz; i++) { + offset += qty; + remainder -= qty; + + if (chain[i].iov_len > remainder) + qty = remainder; + else + qty = (word32)chain[i].iov_len; + XMEMCPY(ssl->buffers.inputBuffer.buffer + offset, + chain[i].iov_base, qty); + } + + *sslBytes += length; + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + #endif + (void)chainSz; } - - qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz); - XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], - (byte*)chain[0].iov_base + headerSz, qty); - offset = length; - for (i = 1; i < chainSz; i++) { - offset += qty; - remainder -= qty; - - if (chain[i].iov_len > remainder) - qty = remainder; - else - qty = (word32)chain[i].iov_len; - XMEMCPY(ssl->buffers.inputBuffer.buffer + offset, - chain[i].iov_base, qty); - } - - *sslBytes += length; - ssl->buffers.inputBuffer.length = *sslBytes; - *sslFrame = ssl->buffers.inputBuffer.buffer; - *end = *sslFrame + *sslBytes; -#endif - (void)chainSz; } if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { @@ -5334,7 +5335,10 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ -/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +/* returns Number of bytes on success, 0 for no data yet, and + * WOLFSSL_SNIFFER_ERROR on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state + * error + */ static int ssl_DecodePacketInternal(const byte* packet, int length, void* vChain, word32 chainSz, byte** data, SSLInfo* sslInfo, @@ -5362,13 +5366,14 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, error) != 0) - return -1; + return WOLFSSL_SNIFFER_ERROR; end = sslFrame + sslBytes; ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); - if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; - else if (ret == -1) return -1; + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) + return WOLFSSL_SNIFFER_FATAL_ERROR; + else if (ret == -1) return WOLFSSL_SNIFFER_ERROR; else if (ret == 1) { #ifdef WOLFSSL_SNIFFER_STATS if (sslBytes > 0) { @@ -5384,8 +5389,9 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, } ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error); - if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; - else if (ret == -1) return -1; + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) + return WOLFSSL_SNIFFER_FATAL_ERROR; + else if (ret == -1) return WOLFSSL_SNIFFER_ERROR; else if (ret == 1) { #ifdef WOLFSSL_SNIFFER_STATS INC_STAT(SnifferStats.sslDecryptedPackets); @@ -5395,8 +5401,9 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, &end, vChain, chainSz, error); - if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; - else if (ret == -1) return -1; + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) + return WOLFSSL_SNIFFER_FATAL_ERROR; + else if (ret == -1) return WOLFSSL_SNIFFER_ERROR; else if (ret == 1) { #ifdef WOLFSSL_SNIFFER_STATS INC_STAT(SnifferStats.sslDecryptedPackets); @@ -5416,7 +5423,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, #endif ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error); - if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) + return WOLFSSL_SNIFFER_FATAL_ERROR; if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) { CopySessionInfo(session, sslInfo); } @@ -5426,7 +5434,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ -/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR. + * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */ /* Also returns Session Info if available */ int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, unsigned char** data, SSLInfo* sslInfo, char* error) @@ -5437,7 +5446,8 @@ int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ -/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR. + * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) { return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL, @@ -5447,6 +5457,8 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB +/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR. + * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */ int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet, int length, void* ctx, SSLInfo* sslInfo, char* error) { @@ -5459,6 +5471,8 @@ int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet, #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT +/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR. + * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */ int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data, char* error) { @@ -5472,6 +5486,10 @@ int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data, #if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \ defined(WOLFSSL_SNIFFER_STORE_DATA_CB) +/* + * returns WOLFSSL_SNIFFER_ERROR on error and WOLFSSL_SNIFFER_FATAL_ERROR on + * fatal state error + */ int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz, void* ctx, SSLInfo* sslInfo, char* error) { @@ -5517,7 +5535,7 @@ int ssl_Trace(const char* traceFile, char* error) if (traceFile) { /* Don't try to reopen the file */ if (TraceFile == NULL) { - TraceFile = fopen(traceFile, "a"); + TraceFile = XFOPEN(traceFile, "a"); if (!TraceFile) { SetError(BAD_TRACE_FILE_STR, error, NULL, 0); return -1; diff --git a/src/ssl.c b/src/ssl.c index 57348a9ea..4da12f4b1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1,6 +1,6 @@ /* ssl.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -151,9 +151,17 @@ #ifndef WOLFCRYPT_ONLY #ifdef OPENSSL_EXTRA -/* Global pointer to constant BN on */ -static WOLFSSL_BIGNUM* bn_one = NULL; -#endif + /* Global pointer to constant BN on */ + static WOLFSSL_BIGNUM* bn_one = NULL; + + /* WOLFSSL_NO_OPENSSL_RAND_CB: Allows way to reduce code size for + * OPENSSL_EXTRA where RAND callbacks are not used */ + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + static const WOLFSSL_RAND_METHOD* gRandMethods = NULL; + static int gRandMethodsInit = 0; + static wolfSSL_Mutex gRandMethodMutex; + #endif /* !WOLFSSL_NO_OPENSSL_RAND_CB */ +#endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) const WOLF_EC_NIST_NAME kNistCurves[] = { @@ -540,7 +548,6 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) WOLFSSL* ssl = NULL; int ret = 0; - (void)ret; WOLFSSL_ENTER("SSL_new"); if (ctx == NULL) @@ -554,6 +561,8 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) } WOLFSSL_LEAVE("SSL_new", ret); + (void)ret; + return ssl; } @@ -1005,6 +1014,34 @@ int wolfSSL_mutual_auth(WOLFSSL* ssl, int req) } #endif /* NO_CERTS */ +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + +int wolfSSL_CTX_set_AcceptFilter( + WOLFSSL_CTX *ctx, + NetworkFilterCallback_t AcceptFilter, + void *AcceptFilter_arg) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + ctx->AcceptFilter = AcceptFilter; + ctx->AcceptFilter_arg = AcceptFilter_arg; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_set_AcceptFilter( + WOLFSSL *ssl, + NetworkFilterCallback_t AcceptFilter, + void *AcceptFilter_arg) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + ssl->AcceptFilter = AcceptFilter; + ssl->AcceptFilter_arg = AcceptFilter_arg; + return WOLFSSL_SUCCESS; +} + +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + #ifndef WOLFSSL_LEANPSK int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz) { @@ -1792,7 +1829,8 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0); @@ -1888,42 +1926,42 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, } -int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) +int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz_bits) { - if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) + if (ctx == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0) return BAD_FUNC_ARG; - ctx->minDhKeySz = keySz / 8; + ctx->minDhKeySz = keySz_bits / 8; return WOLFSSL_SUCCESS; } -int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz) +int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz_bits) { - if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) + if (ssl == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0) return BAD_FUNC_ARG; - ssl->options.minDhKeySz = keySz / 8; + ssl->options.minDhKeySz = keySz_bits / 8; return WOLFSSL_SUCCESS; } -int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) +int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz_bits) { - if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) + if (ctx == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0) return BAD_FUNC_ARG; - ctx->maxDhKeySz = keySz / 8; + ctx->maxDhKeySz = keySz_bits / 8; return WOLFSSL_SUCCESS; } -int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz) +int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz_bits) { - if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) + if (ssl == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0) return BAD_FUNC_ARG; - ssl->options.maxDhKeySz = keySz / 8; + ssl->options.maxDhKeySz = keySz_bits / 8; return WOLFSSL_SUCCESS; } @@ -2016,6 +2054,30 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) && defined(OPENSSL_EXTRA) + /* This additional logic is meant to simulate following openSSL behavior: + * After bidirectional SSL_shutdown complete, SSL_read returns 0 and + * SSL_get_error_code returns SSL_ERROR_ZERO_RETURN. + * This behavior is used to know the disconnect of the underlying + * transport layer. + * + * In this logic, CBIORecv is called with a read size of 0 to check the + * transport layer status. It also returns WOLFSSL_FAILURE so that + * SSL_read does not return a positive number on failure. + */ + + /* make sure bidirectional TLS shutdown completes */ + if (ssl->error == WOLFSSL_ERROR_SYSCALL) { + /* ask the underlying transport the connection is closed */ + if (ssl->CBIORecv(ssl, (char*)data, 0, ssl->IOCB_ReadCtx) == + WOLFSSL_CBIO_ERR_CONN_CLOSE) { + ssl->options.isClosed = 1; + ssl->error = WOLFSSL_ERROR_ZERO_RETURN; + } + return WOLFSSL_FAILURE; + } +#endif + #ifdef HAVE_WRITE_DUP if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) { WOLFSSL_MSG("Write dup side cannot read"); @@ -2029,12 +2091,16 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); + ssl->dtls_expected_rx = max(sz + DTLS_MTU_ADDITIONAL_READ_BUFFER, + MAX_MTU); #ifdef WOLFSSL_SCTP if (ssl->options.dtlsSctp) #endif #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) - ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz); + /* Add some bytes so that we can operate with slight difference + * in set MTU size on each peer */ + ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, + ssl->dtlsMtuSz + DTLS_MTU_ADDITIONAL_READ_BUFFER); #endif } #endif @@ -2084,6 +2150,9 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) WOLFSSL_ENTER("wolfSSL_read()"); #ifdef OPENSSL_EXTRA + if (ssl == NULL) { + return BAD_FUNC_ARG; + } if (ssl->CBIS != NULL) { ssl->CBIS(ssl, SSL_CB_READ, WOLFSSL_SUCCESS); ssl->cbmode = SSL_CB_READ; @@ -2271,7 +2340,7 @@ int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl) #ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST /* The following is a non-standard way to reconfigure the max packet size - post-handshake for wolfSSL_write/woflSSL_read */ + post-handshake for wolfSSL_write/wolfSSL_read */ if (ssl->options.handShakeState == HANDSHAKE_DONE) { switch (mfl) { case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break; @@ -2798,7 +2867,9 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) #endif } +#ifdef HAVE_SESSION_TICKET if (ret == WOLFSSL_SUCCESS) +#endif ret = _Rehandshake(ssl); return ret; @@ -3791,99 +3862,182 @@ int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm) WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_STACK* sk = NULL; + int numCerts = 0; + DerBuffer** certBuffers = NULL; + const byte* derBuffer = NULL; Signer* signers = NULL; word32 row = 0; - DecodedCert* dCert = NULL; WOLFSSL_X509* x509 = NULL; - int found = 0; + int i = 0; + int ret = 0; if (cm == NULL) return NULL; sk = wolfSSL_sk_X509_new(); + if (sk == NULL) + goto error; - if (sk == NULL) { - return NULL; - } - - if (wc_LockMutex(&cm->caLock) != 0) { - goto error_init; - } + if (wc_LockMutex(&cm->caLock) != 0) + goto error; + /* Iterate once to get the number of certs, for memory allocation + purposes. */ for (row = 0; row < CA_TABLE_SIZE; row++) { signers = cm->caTable[row]; while (signers && signers->derCert && signers->derCert->buffer) { - - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, - DYNAMIC_TYPE_DCERT); - if (dCert == NULL) { - goto error; - } - - XMEMSET(dCert, 0, sizeof(DecodedCert)); - - InitDecodedCert(dCert, signers->derCert->buffer, - signers->derCert->length, cm->heap); - - /* Parse Certificate */ - if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, cm)) { - goto error; - } - - x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), cm->heap, - DYNAMIC_TYPE_X509); - - if (x509 == NULL) { - goto error; - } - - InitX509(x509, 1, NULL); - - if (CopyDecodedToX509(x509, dCert) == 0) { - - if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Unable to load x509 into stack"); - FreeX509(x509); - XFREE(x509, cm->heap, DYNAMIC_TYPE_X509); - goto error; - } - } - else { - goto error; - } - - found = 1; - + ++numCerts; signers = signers->next; - - FreeDecodedCert(dCert); - XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT); - dCert = NULL; } } + + if (numCerts == 0) { + wc_UnLockMutex(&cm->caLock); + goto error; + } + + certBuffers = (DerBuffer**)XMALLOC(sizeof(DerBuffer*) * numCerts, cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certBuffers == NULL) { + wc_UnLockMutex(&cm->caLock); + goto error; + } + XMEMSET(certBuffers, 0, sizeof(DerBuffer*) * numCerts); + + /* Copy the certs locally so that we can release the caLock. If the lock is + held when wolfSSL_d2i_X509 is called, GetCA will also try to get the + lock, leading to deadlock. */ + for (row = 0; row < CA_TABLE_SIZE; row++) { + signers = cm->caTable[row]; + while (signers && signers->derCert && signers->derCert->buffer) { + ret = AllocDer(&certBuffers[i], signers->derCert->length, CA_TYPE, + cm->heap); + if (ret < 0) { + wc_UnLockMutex(&cm->caLock); + goto error; + } + + XMEMCPY(certBuffers[i]->buffer, signers->derCert->buffer, + signers->derCert->length); + certBuffers[i]->length = signers->derCert->length; + + ++i; + signers = signers->next; + } + } + wc_UnLockMutex(&cm->caLock); - if (!found) { - goto error_init; + for (i = 0; i < numCerts; ++i) { + derBuffer = certBuffers[i]->buffer; + wolfSSL_d2i_X509(&x509, &derBuffer, certBuffers[i]->length); + if (x509 == NULL) + goto error; + + if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) + goto error; } + for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) { + FreeDer(&certBuffers[i]); + } + + XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + return sk; error: - wc_UnLockMutex(&cm->caLock); - -error_init: - - if (dCert) { - FreeDecodedCert(dCert); - XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT); - } - if (sk) wolfSSL_sk_X509_free(sk); + if (certBuffers != NULL) { + for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) { + FreeDer(&certBuffers[i]); + } + } + + if (certBuffers) + XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; } + +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name) +{ + WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL; + int err = 0; + WOLFSSL_X509_STORE* store = NULL; + WOLFSSL_STACK* sk = NULL; + WOLFSSL_STACK* certToFilter = NULL; + WOLFSSL_X509_NAME* certToFilterName = NULL; + WOLF_STACK_OF(WOLFSSL_X509)* filteredCerts = NULL; + WOLFSSL_X509* filteredCert = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); + + if (name == NULL) { + err = 1; + } + + if (err == 0) { + store = wolfSSL_X509_STORE_CTX_get0_store(ctx); + if (store == NULL) { + err = 1; + } + } + + if (err == 0) { + filteredCerts = wolfSSL_sk_X509_new(); + if (filteredCerts == NULL) { + err = 1; + } + } + + if (err == 0) { + sk = wolfSSL_CertManagerGetCerts(store->cm); + if (sk == NULL) { + err = 1; + } + } + + if (err == 0) { + certToFilter = sk; + while (certToFilter != NULL) { + certToFilterName = wolfSSL_X509_get_subject_name( + certToFilter->data.x509); + if (certToFilterName != NULL) { + if (wolfSSL_X509_NAME_cmp(certToFilterName, name) == 0) { + filteredCert = wolfSSL_X509_dup(certToFilter->data.x509); + if (filteredCert == NULL) { + err = 1; + break; + } + else { + wolfSSL_sk_X509_push(filteredCerts, filteredCert); + } + } + } + certToFilter = certToFilter->next; + } + } + + if (err == 1) { + if (filteredCerts != NULL) { + wolfSSL_sk_X509_free(filteredCerts); + } + ret = NULL; + } + else { + ret = filteredCerts; + } + + if (sk != NULL) { + wolfSSL_sk_X509_free(sk); + } + + return ret; +} #endif /* WOLFSSL_SIGNER_DER_CERT */ /****************************************************************************** @@ -4260,7 +4414,8 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); return WOLFSSL_SUCCESS; } @@ -4514,13 +4669,16 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, DYNAMIC_TYPE_DCERT); - if (cert == NULL) + if (cert == NULL) { + FreeDer(&der); return MEMORY_E; + } InitDecodedCert(cert, der->buffer, der->length, cm->heap); if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) { FreeDecodedCert(cert); XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + FreeDer(&der); return ret; } WOLFSSL_MSG("\tParsed new trusted peer cert"); @@ -4530,6 +4688,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) if (peerCert == NULL) { FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + FreeDer(&der); return MEMORY_E; } XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); @@ -4566,6 +4725,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); FreeTrustedPeer(peerCert, cm->heap); + FreeDer(&der); return MEMORY_E; } XMEMCPY(peerCert->sig, cert->signature, cert->sigLength); @@ -4613,6 +4773,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); FreeTrustedPeer(peerCert, cm->heap); + FreeDer(&der); return BAD_MUTEX_E; } } @@ -4921,9 +5082,25 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #if defined(OPENSSL_EXTRA) || \ (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)) -static WC_RNG globalRNG; -static int initGlobalRNG = 0; -static wolfSSL_Mutex globalRNGMutex; + + #define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */ + static WC_RNG globalRNG; + static int initGlobalRNG = 0; + static wolfSSL_Mutex globalRNGMutex; +#endif + +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) +static int wolfSSL_RAND_InitMutex(void) +{ + if (gRandMethodsInit == 0) { + if (wc_InitMutex(&gRandMethodMutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex rand methods"); + return BAD_MUTEX_E; + } + gRandMethodsInit = 1; + } + return 0; +} #endif WOLFSSL_ABI @@ -4938,8 +5115,7 @@ int wolfSSL_Init(void) return WC_INIT_E; } -#if defined(OPENSSL_EXTRA) || \ - (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)) +#ifdef HAVE_GLOBAL_RNG if (wc_InitMutex(&globalRNGMutex) != 0) { WOLFSSL_MSG("Bad Init Mutex rng"); return BAD_MUTEX_E; @@ -4947,6 +5123,11 @@ int wolfSSL_Init(void) #endif #ifdef OPENSSL_EXTRA + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() != 0) { + return BAD_MUTEX_E; + } + #endif if (wolfSSL_RAND_seed(NULL, 0) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_RAND_Seed failed"); return WC_INIT_E; @@ -5531,8 +5712,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, FreeDer(&der); return BAD_FUNC_ARG; } - /* add trusted peer cert */ + /* add trusted peer cert. der is freed within */ ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error adding trusted peer"); + } done = 1; } #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -5698,21 +5882,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, case CTC_SHA256wECDSA: case CTC_SHA384wECDSA: case CTC_SHA512wECDSA: - WOLFSSL_MSG("ECDSA cert signature"); - if (ssl) - ssl->options.haveECDSAsig = 1; - else if (ctx) - ctx->haveECDSAsig = 1; - break; case CTC_ED25519: - WOLFSSL_MSG("ED25519 cert signature"); - if (ssl) - ssl->options.haveECDSAsig = 1; - else if (ctx) - ctx->haveECDSAsig = 1; - break; case CTC_ED448: - WOLFSSL_MSG("ED448 cert signature"); + WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature"); if (ssl) ssl->options.haveECDSAsig = 1; else if (ctx) @@ -5939,7 +6111,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } return WOLFSSL_SUCCESS; @@ -6155,7 +6328,7 @@ int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) return WOLFSSL_FAILURE; } - #ifdef HAVE_CRL_IO + #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO) cm->crl->crlIOCb = EmbedCrlLookup; #endif } @@ -6231,7 +6404,7 @@ int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff, #endif } else { - InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap); + InitDecodedCert(cert, buff, (word32)sz, cm->heap); } if (ret == 0) @@ -6511,7 +6684,7 @@ WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm, { int ret; - WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP_Staple"); + WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse"); if (cm == NULL || response == NULL) return BAD_FUNC_ARG; if (cm->ocspEnabled == 0) @@ -6913,8 +7086,10 @@ WOLFSSL_ABI int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, const char* path) { - return wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, + int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); + + return WS_RETURN_CODE(ret,WOLFSSL_FAILURE); } @@ -7456,7 +7631,7 @@ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) #endif word32 size; byte* buff; - int ret; + int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_CTX_check_private_key"); @@ -7489,36 +7664,51 @@ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) int type = 0; void *pkey = NULL; + #ifndef NO_RSA if (der->keyOID == RSAk) { type = DYNAMIC_TYPE_RSA; } - else if (der->keyOID == ECDSAk) { + #endif + #ifdef HAVE_ECC + if (der->keyOID == ECDSAk) { type = DYNAMIC_TYPE_ECC; } + #endif ret = CreateDevPrivateKey(&pkey, buff, size, type, ctx->privateKeyLabel, ctx->privateKeyId, ctx->heap, ctx->privateKeyDevId); + #ifndef NO_RSA if (ret == 0 && der->keyOID == RSAk) { ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, der->publicKey, der->pubKeySize); wc_FreeRsaKey((RsaKey*)pkey); } - else if (ret == 0 && der->keyOID == ECDSAk) { + #endif + #ifdef HAVE_ECC + if (ret == 0 && der->keyOID == ECDSAk) { ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, der->publicKey, der->pubKeySize); wc_ecc_free((ecc_key*)pkey); } + #endif if (pkey != NULL) { XFREE(pkey, ctx->heap, type); } - if (ret == 0) { - ret = WOLFSSL_SUCCESS; - } - else { - ret = WOLFSSL_FAILURE; + if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret == 0) { + ret = WOLFSSL_SUCCESS; + } + else { + ret = WOLFSSL_FAILURE; + } } } - else + else { + /* fall through if unavailable */ + ret = CRYPTOCB_UNAVAILABLE; + } + + if (ret == CRYPTOCB_UNAVAILABLE) #endif { ret = wc_CheckPrivateKeyCert(buff, size, der); @@ -7877,6 +8067,76 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ + #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) + #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) + { + DhKey dh; + word32 keyIdx = 0; + DhKey* key = NULL; + int ret; + Element_Set elements; + /* test if DH-public key */ + if (wc_InitDhKey(&dh) != 0) + return NULL; + + ret = wc_DhPublicKeyDecode(mem, &keyIdx, &dh, (word32)memSz); + wc_FreeDhKey(&dh); + + if (ret == 0) { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey != NULL) { + pkey->type = EVP_PKEY_DH; + pkey->pkey_sz = (int)memSz; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, memSz); + if (out != NULL) { + *out = pkey; + } + pkey->ownDh = 1; + pkey->dh = wolfSSL_DH_new(); + if (pkey->dh == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + key = (DhKey*)pkey->dh->internal; + + keyIdx = 0; + if (wc_DhPublicKeyDecode(mem, &keyIdx, key, (word32)memSz) == 0) + { + elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; + if( SetDhExternal_ex(pkey->dh, elements) + == WOLFSSL_SUCCESS ){ + return pkey; + } + /* + if (SetIndividualExternal(&(pkey->dh->p), &key->p) + == WOLFSSL_SUCCESS && + SetIndividualExternal(&(pkey->dh->g), &key->g) + == WOLFSSL_SUCCESS && + SetIndividualExternal(&(pkey->dh->q), &key->q) + == WOLFSSL_SUCCESS && + SetIndividualExternal(&(pkey->dh->pub_key), &key->pub) + == WOLFSSL_SUCCESS) { + return pkey; + } */ + } + else { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + } + } + } + #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ + #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ + if (pkey == NULL) { WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type"); } @@ -8111,35 +8371,48 @@ int wolfSSL_check_private_key(const WOLFSSL* ssl) int type = 0; void *pkey = NULL; + #ifndef NO_RSA if (der.keyOID == RSAk) { type = DYNAMIC_TYPE_RSA; } - else if (der.keyOID == ECDSAk) { + #endif + #ifdef HAVE_ECC + if (der.keyOID == ECDSAk) { type = DYNAMIC_TYPE_ECC; } + #endif ret = CreateDevPrivateKey(&pkey, buff, size, type, ssl->buffers.keyLabel, ssl->buffers.keyId, ssl->heap, ssl->buffers.keyDevId); + #ifndef NO_RSA if (ret == 0 && der.keyOID == RSAk) { ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, der.publicKey, der.pubKeySize); if (ret == 0) - ret = 1; + ret = WOLFSSL_SUCCESS; wc_FreeRsaKey((RsaKey*)pkey); } - else if (ret == 0 && der.keyOID == ECDSAk) { + #endif + #ifdef HAVE_ECC + if (ret == 0 && der.keyOID == ECDSAk) { ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, der.publicKey, der.pubKeySize); if (ret == 0) - ret = 1; + ret = WOLFSSL_SUCCESS; wc_ecc_free((ecc_key*)pkey); } + #endif if (pkey != NULL) { XFREE(pkey, ssl->heap, type); } } - else + else { + /* fall through if unavailable */ + ret = CRYPTOCB_UNAVAILABLE; + } + + if (ret == CRYPTOCB_UNAVAILABLE) #endif ret = wc_CheckPrivateKeyCert(buff, size, &der); FreeDecodedCert(&der); @@ -8179,6 +8452,7 @@ int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert) CA_TYPE, NO_VERIFY, NULL) < 0) { WOLFSSL_MSG("\tCertificate parsing failed"); + FreeDecodedCert(&cert); return WOLFSSL_FAILURE; } @@ -8538,6 +8812,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) NO_VERIFY, NULL) < 0) { WOLFSSL_MSG("\tCertificate parsing failed"); wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); return NULL; } @@ -9046,7 +9321,7 @@ int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, int nid; const int sz = CTC_NAME_SIZE*2; int rc = WOLFSSL_FAILURE; - char tmp[CTC_NAME_SIZE*2] = {0}; + char tmp[CTC_NAME_SIZE*2 + 1] = {0}; WOLFSSL_ENTER("wolfSSL_X509V3_EXT_print"); if ((out == NULL) || (ext == NULL)) { @@ -9102,7 +9377,7 @@ int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, return rc; } if (sk->next) - XSNPRINTF(val, len, "%*s%s, ", indent, "", str->strData); + XSNPRINTF(val, len, "%*s%s,", indent, "", str->strData); else XSNPRINTF(val, len, "%*s%s", indent, "", str->strData); @@ -9337,6 +9612,8 @@ void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext) WOLFSSL_MSG("Failed to malloc authority key id"); return NULL; } + + XMEMSET(akey, 0, sizeof(WOLFSSL_AUTHORITY_KEYID)); akey->keyid = wolfSSL_ASN1_STRING_new(); if (akey->keyid == NULL) { @@ -9483,6 +9760,7 @@ void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext) WOLFSSL_MSG("ASN1_STRING_set() failed"); wolfSSL_ASN1_OBJECT_free(ad->method); XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad->location, NULL, DYNAMIC_TYPE_OPENSSL); XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); return NULL; } @@ -9555,6 +9833,7 @@ int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) CA_TYPE, NO_VERIFY, NULL) < 0) { WOLFSSL_MSG("\tCertificate parsing failed"); + FreeDecodedCert(&cert); return WOLFSSL_FATAL_ERROR; } @@ -9765,8 +10044,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, gn = wolfSSL_GENERAL_NAME_new(); if (gn == NULL) { WOLFSSL_MSG("Error creating GENERAL_NAME"); - wolfSSL_sk_free(sk); - return NULL; + goto err; } gn->type = dns->type; @@ -9774,18 +10052,14 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name, gn->d.ia5->length) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ASN1_STRING_set failed"); - wolfSSL_GENERAL_NAME_free(gn); - wolfSSL_sk_free(sk); - return NULL; + goto err; } dns = dns->next; if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error pushing ASN1 object onto stack"); - wolfSSL_GENERAL_NAME_free(gn); - wolfSSL_sk_free(sk); - sk = NULL; + goto err; } /* null so that it doesn't get pushed again after switch */ gn = NULL; @@ -10065,13 +10339,6 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, goto err; } } - else if (gn) { - if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error pushing GENERAL_NAME object onto " - "stack."); - goto err; - } - } ret = sk; @@ -10408,6 +10675,29 @@ int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, WOLFSSL_LEAVE("wolfSSL_X509_digest", ret); return ret; } + +int wolfSSL_X509_pubkey_digest(const WOLFSSL_X509 *x509, + const WOLFSSL_EVP_MD *digest, unsigned char* buf, unsigned int* len) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_X509_pubkey_digest"); + + if (x509 == NULL || digest == NULL) { + WOLFSSL_MSG("Null argument found"); + return WOLFSSL_FAILURE; + } + + if (x509->pubKey.buffer == NULL || x509->pubKey.length == 0) { + WOLFSSL_MSG("No DER public key stored in X509"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_EVP_Digest(x509->pubKey.buffer, x509->pubKey.length, buf, + len, digest, NULL); + WOLFSSL_LEAVE("wolfSSL_X509_pubkey_digest", ret); + return ret; +} #endif int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) @@ -11264,8 +11554,10 @@ int wolfSSL_restore_session_cache(const char *fname) #endif /* NO_SESSION_CACHE */ -void wolfSSL_load_error_strings(void) /* compatibility only */ -{} +void wolfSSL_load_error_strings(void) +{ + /* compatibility only */ +} int wolfSSL_library_init(void) @@ -12175,10 +12467,21 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) if (ssl == NULL) return WOLFSSL_FATAL_ERROR; - if ((IsSCR(ssl) || !ssl->options.handShakeDone) && - (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) { - - result = WOLFSSL_FATAL_ERROR; + if ((IsSCR(ssl) || !ssl->options.handShakeDone)) { + if (DtlsMsgPoolTimeout(ssl) < 0){ + ssl->error = SOCKET_ERROR_E; + WOLFSSL_ERROR(ssl->error); + result = WOLFSSL_FATAL_ERROR; + } + else if ((result = DtlsMsgPoolSend(ssl, 0)) < 0) { + ssl->error = result; + WOLFSSL_ERROR(result); + result = WOLFSSL_FATAL_ERROR; + } + else { + /* Reset return value to success */ + result = WOLFSSL_SUCCESS; + } } WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout()", result); @@ -12802,6 +13105,18 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + if (ssl->AcceptFilter) { + wolfSSL_netfilter_decision_t res; + if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) == + WOLFSSL_SUCCESS) && + (res == WOLFSSL_NETFILTER_REJECT)) { + WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) return wolfSSL_accept_TLSv13(ssl); #else @@ -13176,6 +13491,11 @@ int wolfSSL_Cleanup(void) ret = WC_CLEANUP_E; } +#ifdef HAVE_GLOBAL_RNG + if (wc_FreeMutex(&globalRNGMutex) != 0) { + ret = BAD_MUTEX_E; + } +#endif return ret; } @@ -13291,7 +13611,7 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) if (idx < 0) idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ - for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) { + for (; count > 0; --count) { WOLFSSL_SESSION* current; ClientSession clSess; @@ -13315,6 +13635,8 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } else { WOLFSSL_MSG("ServerID not a match from client table"); } + + idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1; } wc_UnLockMutex(&session_mutex); @@ -13416,7 +13738,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, if (idx < 0) idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ - for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) { + for (; count > 0; --count) { WOLFSSL_SESSION* current; if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */ @@ -13439,6 +13761,8 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, } else { WOLFSSL_MSG("SessionID not a match at this idx"); } + + idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1; } wc_UnLockMutex(&session_mutex); @@ -13575,7 +13899,7 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) { - if (ssl->options.sessionCacheOff) + if (ssl == NULL || ssl->options.sessionCacheOff) return WOLFSSL_FAILURE; #ifdef OPENSSL_EXTRA @@ -14240,7 +14564,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) idx += (int)iov[i].iov_len; } + /* myBuffer may not initialized fully, but the sending length will be */ + PRAGMA_GCC_IGNORE("GCC diagnostic ignored \"-Wmaybe-uninitialized\""); ret = wolfSSL_write(ssl, myBuffer, sending); + PRAGMA_GCC_POP; if (dynamic) XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); @@ -14467,9 +14794,28 @@ int wolfSSL_set_compression(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } - + #ifdef OPENSSL_EXTRA + /** + * set call back function for psk session use + * @param ssl a pointer to WOLFSSL structure + * @param cb a function pointer to wc_psk_use_session_cb + * @return none + */ + void wolfSSL_set_psk_use_session_callback(WOLFSSL* ssl, + wc_psk_use_session_cb_func cb) + { + WOLFSSL_ENTER("wolfSSL_set_psk_use_session_callback"); + + ssl->options.havePSK = 1; + ssl->options.session_psk_cb = cb; + + WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS); + } + #endif + void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx, wc_psk_server_callback cb) { @@ -14501,7 +14847,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) @@ -15108,37 +15455,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return; } - /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */ - if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) { - wolfSSL_set_rfd(ssl, rd->num); - } - if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) { - wolfSSL_set_wfd(ssl, wr->num); - } - - /* free any existing WOLFSSL_BIOs in use */ + /* free any existing WOLFSSL_BIOs in use but don't free those in + * a chain */ if (ssl->biord != NULL) { if (ssl->biord != ssl->biowr) { - if (ssl->biowr != NULL) { + if (ssl->biowr != NULL && ssl->biowr->prev != NULL) wolfSSL_BIO_free(ssl->biowr); - ssl->biowr = NULL; - } + ssl->biowr = NULL; } - wolfSSL_BIO_free(ssl->biord); + if (ssl->biord->prev != NULL) + wolfSSL_BIO_free(ssl->biord); ssl->biord = NULL; } - ssl->biord = rd; ssl->biowr = wr; /* set SSL to use BIO callbacks instead */ - if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) && - (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) { + if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)) { ssl->CBIORecv = BioReceive; } - if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) && - (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) { + if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)) { ssl->CBIOSend = BioSend; } @@ -15689,6 +16026,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->mask = wolf_set_options(ctx->mask, opt); +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \ + defined(OPENSSL_EXTRA) + if (ctx->mask & SSL_OP_NO_TICKET) { + ctx->ticketEncCb = NULL; + ctx->ticketEncCtx = NULL; + WOLFSSL_MSG("\tSSL_OP_NO_TICKET"); + } +#endif + return ctx->mask; } @@ -15757,6 +16103,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->x509_store.cache = str->cache; ctx->x509_store_pt = str; /* take ownership of store and free it with CTX free */ + ctx->cm->x509_store_p = ctx->x509_store_pt;/* CTX has onwership + and free it with CTX free*/ } @@ -16012,6 +16360,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return 0; } + long wolfSSL_BIO_do_handshake(WOLFSSL_BIO *b) + { + WOLFSSL_ENTER("wolfSSL_BIO_do_handshake"); + if (b == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + if (b->type == WOLFSSL_BIO_SSL && b->ptr != NULL) { + return wolfSSL_negotiate((WOLFSSL*)b->ptr); + } + else { + WOLFSSL_MSG("Not SSL BIO or no SSL object set"); + return WOLFSSL_FAILURE; + } + } long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF) { @@ -16022,6 +16385,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (b != NULL) { b->ptr = ssl; b->shutdown = (byte)closeF; + if (b->next != NULL) + wolfSSL_set_bio(ssl, b->next, b->next); /* add to ssl for bio free if SSL_free called before/instead of free_all? */ ret = WOLFSSL_SUCCESS; } @@ -16054,8 +16419,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return WOLFSSL_SUCCESS; } - +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + WOLFSSL_BIO* wolfSSL_BIO_new(const WOLFSSL_BIO_METHOD* method) +#else WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) +#endif { WOLFSSL_BIO* bio; @@ -16070,7 +16438,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (bio) { XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = (byte)method->type; +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + bio->method = (WOLFSSL_BIO_METHOD*)method; +#else bio->method = method; +#endif bio->shutdown = BIO_CLOSE; /* default to close things */ bio->num = -1; /* Default to invalid socket */ bio->init = 1; @@ -16118,7 +16490,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } if (len < 0) { - len = (int)XSTRLEN((const char*)buf); + /* The length of the string including terminating null. */ + len = (int)XSTRLEN((const char*)buf) + 1; } bio->num = bio->wrSz = len; bio->ptr = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); @@ -16148,7 +16521,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) /* unchain?, doesn't matter in goahead since from free all */ WOLFSSL_ENTER("wolfSSL_BIO_free"); if (bio) { - +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&bio->ex_data); +#endif if (bio->infoCb) { /* info callback is called before free */ ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_FREE, NULL, 0, 0, 1); @@ -16214,8 +16589,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_SUCCESS; } - return 1; + return WOLFSSL_FAILURE; } /* like BIO_free, but no return value */ @@ -16243,6 +16619,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) top->next = append; append->prev = top; + /* SSL BIO's should use the next object in the chain for IO */ + if (top->type == WOLFSSL_BIO_SSL && top->ptr) + wolfSSL_set_bio((WOLFSSL*)top->ptr, append, append); + return top; } #endif /* !NO_BIO */ @@ -16383,14 +16763,17 @@ int wolfSSL_set_compression(WOLFSSL* ssl) wc_RemoveErrorNode(0); } } while (ret >= 0); - wolfSSL_BIO_write(bio, "", 1); + if (wolfSSL_BIO_write(bio, "", 1) != 1) { + WOLFSSL_MSG("Issue writing final string terminator"); + } } #endif /* !NO_BIO */ #endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */ #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_SECRET_CALLBACK) #if !defined(NO_WOLFSSL_SERVER) size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, size_t outSz) @@ -16422,7 +16805,7 @@ size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, return size; } #endif /* !NO_WOLFSSL_SERVER */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ #ifdef OPENSSL_EXTRA #if !defined(NO_WOLFSSL_SERVER) @@ -16473,27 +16856,88 @@ int wolfSSL_get_server_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey) #endif *pkey = ret; - if (ret == NULL) - return WOLFSSL_FAILURE; - else +#ifdef HAVE_ECC + if (ret != NULL) return WOLFSSL_SUCCESS; + else +#endif + return WOLFSSL_FAILURE; } #endif /* !NO_WOLFSSL_SERVER */ -static int sanityCheckProtoVersion(WOLFSSL_CTX* ctx) +/** + * This function checks if any compiled in protocol versions are + * left enabled after calls to set_min or set_max API. + * @param ctx The WOLFSSL_CTX to check + * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no + * protocol versions are left enabled. + */ +static int CheckSslMethodVersion(byte major, unsigned long options) { - if ((ctx->mask & WOLFSSL_OP_NO_SSLv3) && - (ctx->mask & WOLFSSL_OP_NO_TLSv1) && - (ctx->mask & WOLFSSL_OP_NO_TLSv1_1) && - (ctx->mask & WOLFSSL_OP_NO_TLSv1_2) && - (ctx->mask & WOLFSSL_OP_NO_TLSv1_3)) { - WOLFSSL_MSG("All TLS versions disabled"); + int sanityConfirmed = 0; + + (void)options; + + switch (major) { + #ifndef NO_TLS + case SSLv3_MAJOR: + #ifdef WOLFSSL_ALLOW_SSLV3 + if (!(options & WOLFSSL_OP_NO_SSLv3)) { + sanityConfirmed = 1; + } + #endif + #ifndef NO_OLD_TLS + if (!(options & WOLFSSL_OP_NO_TLSv1)) + sanityConfirmed = 1; + if (!(options & WOLFSSL_OP_NO_TLSv1_1)) + sanityConfirmed = 1; + #endif + #ifndef WOLFSSL_NO_TLS12 + if (!(options & WOLFSSL_OP_NO_TLSv1_2)) + sanityConfirmed = 1; + #endif + #ifdef WOLFSSL_TLS13 + if (!(options & WOLFSSL_OP_NO_TLSv1_3)) + sanityConfirmed = 1; + #endif + break; + #endif + #ifdef WOLFSSL_DTLS + case DTLS_MAJOR: + sanityConfirmed = 1; + break; + #endif + default: + WOLFSSL_MSG("Invalid major version"); + return WOLFSSL_FAILURE; + } + if (!sanityConfirmed) { + WOLFSSL_MSG("All compiled in TLS versions disabled"); return WOLFSSL_FAILURE; } return WOLFSSL_SUCCESS; } +/** + * This function attempts to set the minimum protocol version to use by SSL + * objects created from this WOLFSSL_CTX. This API guarantees that a version + * of SSL/TLS lower than specified here will not be allowed. If the version + * specified is not compiled in then this API sets the lowest compiled in + * protocol version. CheckSslMethodVersion() is called to check if any + * remaining protocol versions are enabled. + * @param ctx + * @param version Any of the following + * * SSL3_VERSION + * * TLS1_VERSION + * * TLS1_1_VERSION + * * TLS1_2_VERSION + * * TLS1_3_VERSION + * * DTLS1_VERSION + * * DTLS1_2_VERSION + * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no + * protocol versions are left enabled. + */ int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) { WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version"); @@ -16503,36 +16947,36 @@ int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) } switch (version) { -#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) +#ifndef NO_TLS case SSL3_VERSION: +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) ctx->minDowngrade = SSLv3_MINOR; break; #endif -#ifndef NO_TLS - #ifndef NO_OLD_TLS - #ifdef WOLFSSL_ALLOW_TLSV10 case TLS1_VERSION: + #ifdef WOLFSSL_ALLOW_TLSV10 ctx->minDowngrade = TLSv1_MINOR; break; #endif case TLS1_1_VERSION: + #ifndef NO_OLD_TLS ctx->minDowngrade = TLSv1_1_MINOR; break; - #endif - #ifndef WOLFSSL_NO_TLS12 + #endif case TLS1_2_VERSION: + #ifndef WOLFSSL_NO_TLS12 ctx->minDowngrade = TLSv1_2_MINOR; break; - #endif - #ifdef WOLFSSL_TLS13 + #endif case TLS1_3_VERSION: + #ifdef WOLFSSL_TLS13 ctx->minDowngrade = TLSv1_3_MINOR; break; - #endif + #endif #endif #ifdef WOLFSSL_DTLS - #ifndef NO_OLD_TLS case DTLS1_VERSION: + #ifndef NO_OLD_TLS ctx->minDowngrade = DTLS_MINOR; break; #endif @@ -16559,17 +17003,13 @@ int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) case TLS1_VERSION: wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_SSLv3); break; -#endif -#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) case SSL3_VERSION: case SSL2_VERSION: /* Nothing to do here */ -#endif break; -#ifdef WOLFSSL_DTLS -#ifndef NO_OLD_TLS - case DTLS1_VERSION: #endif +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: case DTLS1_2_VERSION: break; #endif @@ -16578,9 +17018,28 @@ int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) return WOLFSSL_FAILURE; } - return sanityCheckProtoVersion(ctx); + return CheckSslMethodVersion(ctx->method->version.major, ctx->mask); } +/** + * This function attempts to set the maximum protocol version to use by SSL + * objects created from this WOLFSSL_CTX. This API guarantees that a version + * of SSL/TLS higher than specified here will not be allowed. If the version + * specified is not compiled in then this API sets the highest compiled in + * protocol version. CheckSslMethodVersion() is called to check if any + * remaining protocol versions are enabled. + * @param ctx + * @param version Any of the following + * * SSL3_VERSION + * * TLS1_VERSION + * * TLS1_1_VERSION + * * TLS1_2_VERSION + * * TLS1_3_VERSION + * * DTLS1_VERSION + * * DTLS1_2_VERSION + * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no + * protocol versions are left enabled. + */ int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver) { WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version"); @@ -16594,7 +17053,7 @@ int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver) case SSL2_VERSION: WOLFSSL_MSG("wolfSSL does not support SSLv2"); return WOLFSSL_FAILURE; -#if (defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)) || !defined(NO_TLS) +#ifndef NO_TLS case SSL3_VERSION: wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1); FALL_THROUGH; @@ -16612,9 +17071,7 @@ int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver) break; #endif #ifdef WOLFSSL_DTLS -#ifndef NO_OLD_TLS case DTLS1_VERSION: -#endif case DTLS1_2_VERSION: break; #endif @@ -16623,12 +17080,69 @@ int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver) return WOLFSSL_FAILURE; } - return sanityCheckProtoVersion(ctx); + return CheckSslMethodVersion(ctx->method->version.major, ctx->mask); +} + +static int GetMinProtoVersion(int minDowngrade) +{ + int ret; + + switch (minDowngrade) { +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + case SSLv3_MINOR: + ret = SSL3_VERSION; + break; + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + case TLSv1_MINOR: + ret = TLS1_VERSION; + break; + #endif + case TLSv1_1_MINOR: + ret = TLS1_1_VERSION; + break; +#endif +#ifndef WOLFSSL_NO_TLS12 + case TLSv1_2_MINOR: + ret = TLS1_2_VERSION; + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSv1_3_MINOR: + ret = TLS1_3_VERSION; + break; +#endif + default: + ret = 0; + break; + } + + return ret; +} + +WOLFSSL_API int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version"); + + if (ctx != NULL) { + ret = GetMinProtoVersion(ctx->minDowngrade); + } + if (ret == 0) { + ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE); + } + + WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret); + + return ret; } #endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_SECRET_CALLBACK) #if !defined(NO_WOLFSSL_CLIENT) /* Return the amount of random bytes copied over or error case. * ssl : ssl struct after handshake @@ -16667,7 +17181,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, return size; } #endif /* !NO_WOLFSSL_CLIENT */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ #ifdef OPENSSL_EXTRA unsigned long wolfSSLeay(void) @@ -16735,6 +17249,31 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, return 0; } + /* Apply MD5 transformation to the data */ + int wolfSSL_MD5_Transform(WOLFSSL_MD5_CTX* md5, const unsigned char* data) + { + int ret; + + WOLFSSL_ENTER("MD5_Transform"); + + /* sanity check */ + if (md5 == NULL || data == NULL) { + return 0; + } + #if defined(BIG_ENDIAN_ORDER) + { + ByteReverseWords((word32*)data, (word32*)data, WC_MD5_BLOCK_SIZE); + } + #endif + + ret = wc_Md5Transform((wc_Md5*)md5, data); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + else + return 0; + } #endif /* !NO_MD5 */ @@ -16787,7 +17326,36 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, return 0; } + #if defined(OPENSSL_EXTRA) + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + /* Apply SHA1 transformation to the data */ + int wolfSSL_SHA_Transform(WOLFSSL_SHA_CTX* sha, + const unsigned char* data) + { + int ret; + + WOLFSSL_ENTER("SHA_Transform"); + /* sanity check */ + if (sha == NULL || data == NULL) { + return 0; + } + #if defined(LITTLE_ENDIAN_ORDER) + { + ByteReverseWords((word32*)data, (word32*)data, WC_SHA_BLOCK_SIZE); + } + #endif + ret = wc_ShaTransform((wc_Sha*)sha, data); + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + else + return 0; + } + #endif + #endif + int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha) { WOLFSSL_ENTER("SHA1_Init"); @@ -16808,6 +17376,18 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, WOLFSSL_ENTER("SHA1_Final"); return SHA_Final(input, sha); } + #if defined(OPENSSL_EXTRA) + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + /* Apply SHA1 transformation to the data */ + int wolfSSL_SHA1_Transform(WOLFSSL_SHA_CTX* sha, + const unsigned char* data) + { + WOLFSSL_ENTER("SHA1_Transform"); + return (wolfSSL_SHA_Transform(sha, data)); + } + #endif + #endif #endif /* !NO_SHA */ #ifdef WOLFSSL_SHA224 @@ -16910,8 +17490,37 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, return 0; } + + #if defined(OPENSSL_EXTRA) + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + /* Apply SHA256 transformation to the data */ + int wolfSSL_SHA256_Transform(WOLFSSL_SHA256_CTX* sha256, + const unsigned char* data) + { + int ret; + + WOLFSSL_ENTER("SHA256_Transform"); + /* sanity check */ + if (sha256 == NULL || data == NULL) { + return 0; + } + #if defined(LITTLE_ENDIAN_ORDER) + { + ByteReverseWords((word32*)data, (word32*)data, WC_SHA256_BLOCK_SIZE); + } + #endif + ret = wc_Sha256Transform((wc_Sha256*)sha256, data); - + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + else + return 0; + } + #endif + #endif + #ifdef WOLFSSL_SHA384 int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha) @@ -17015,6 +17624,30 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, return 0; } + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + /* Apply SHA512 transformation to the data */ + int wolfSSL_SHA512_Transform(WOLFSSL_SHA512_CTX* sha512, + const unsigned char* data) + { + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("SHA512_Transform"); + /* sanity check */ + if (sha512 == NULL || data == NULL) { + return 0; + } + + ret = wc_Sha512Transform((wc_Sha512*)sha512, data); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + else + return 0; + } + #endif /* !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) */ #endif /* WOLFSSL_SHA512 */ #ifdef WOLFSSL_SHA3 @@ -17556,24 +18189,62 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #endif } + /* If a valid struct is provided with function pointers, will override + RAND_seed, bytes, cleanup, add, pseudo_bytes and status. If a NULL + pointer is passed in, it will cancel any previous function overrides. - int wolfSSL_RAND_status(void) + Returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure. */ + int wolfSSL_RAND_set_rand_method(const WOLFSSL_RAND_METHOD *methods) { - return WOLFSSL_SUCCESS; /* wolfCrypt provides enough seed internally */ + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + gRandMethods = methods; + wc_UnLockMutex(&gRandMethodMutex); + return WOLFSSL_SUCCESS; + } + #else + (void)methods; + #endif + return WOLFSSL_FAILURE; } + /* Returns WOLFSSL_SUCCESS if the RNG has been seeded with enough data */ + int wolfSSL_RAND_status(void) + { + int ret = WOLFSSL_SUCCESS; + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->status) + ret = gRandMethods->status(); + wc_UnLockMutex(&gRandMethodMutex); + } + else { + ret = WOLFSSL_FAILURE; + } + #else + /* wolfCrypt provides enough seed internally, so return success */ + #endif + return ret; + } - #ifndef NO_WOLFSSL_STUB void wolfSSL_RAND_add(const void* add, int len, double entropy) { + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->add) { + /* callback has return code, but RAND_add does not */ + (void)gRandMethods->add(add, len, entropy); + } + wc_UnLockMutex(&gRandMethodMutex); + } + #else + /* wolfSSL seeds/adds internally, use explicit RNG if you want + to take control */ (void)add; (void)len; (void)entropy; - WOLFSSL_STUB("RAND_add"); - /* wolfSSL seeds/adds internally, use explicit RNG if you want - to take control */ - } #endif + } #ifndef NO_DES3 /* 0 on ok */ @@ -18248,39 +18919,68 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #endif /* KEEP_PEER_CERT */ -#if defined(SESSION_CERTS) -/* Return stack of peer certs. - * If Qt or OPENSSL_ALL is defined then return ssl->peerCertChain. - * All other cases return &ssl->session.chain - * ssl->peerCertChain is type WOLFSSL_STACK* - * ssl->session.chain is type WOLFSSL_X509_CHAIN +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) +/* Return stack of peer certs. * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl is. */ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) { - WOLFSSL_STACK* sk; WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); if (ssl == NULL) return NULL; - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - if (ssl->peerCertChain == NULL) - wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); - sk = ssl->peerCertChain; - #else - sk = (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain; - #endif - - if (sk == NULL) { - WOLFSSL_MSG("Error: Null Peer Cert Chain"); - } - return sk; + if (ssl->peerCertChain == NULL) + wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); + return ssl->peerCertChain; +} + +static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, + WOLFSSL_X509 *x); +/** + * Recursively push the issuer CA chain onto the stack + * @param cm The cert manager that is queried for the issuer + * @param x This cert's issuer will be queried in cm + * @param sk The issuer is pushed onto this stack + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on no issuer found + * WOLFSSL_FATAL_ERROR on a fatal error + */ +static int pushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, + WOLFSSL_X509 *x, WOLFSSL_STACK* sk) +{ + WOLFSSL_X509* issuer[MAX_CHAIN_DEPTH]; + int i; + int push = 1; + int ret = WOLFSSL_SUCCESS; + + for (i = 0; i < MAX_CHAIN_DEPTH; i++) { + if (x509GetIssuerFromCM(&issuer[i], cm, x) + != WOLFSSL_SUCCESS) + break; + x = issuer[i]; + } + if (i == 0) /* No further chain found */ + return WOLFSSL_FAILURE; + i--; + for (; i >= 0; i--) { + if (push) { + if (wolfSSL_sk_X509_push(sk, issuer[i]) != WOLFSSL_SUCCESS) { + wolfSSL_X509_free(issuer[i]); + ret = WOLFSSL_FATAL_ERROR; + push = 0; /* Free the rest of the unpushed certs */ + } + } + else { + wolfSSL_X509_free(issuer[i]); + } + } + return ret; } -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) /* Builds up and creates a stack of peer certificates for ssl->peerCertChain - based off of the ssl session chain. Returns stack of WOLFSSL_X509 certs or + based off of the ssl session chain. Attempts to place CA certificates + at the bottom of the stack. Returns stack of WOLFSSL_X509 certs or NULL on failure */ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) { @@ -18296,17 +18996,22 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) sk = wolfSSL_sk_X509_new(); i = ssl->session.chain.count-1; for (; i >= 0; i--) { - /* For servers, the peer certificate chain does not include the peer - certificate, so do not add it to the stack */ - if (ssl->options.side == WOLFSSL_SERVER_END && i == 0) - continue; x509 = wolfSSL_X509_new(); if (x509 == NULL) { WOLFSSL_MSG("Error Creating X509"); + wolfSSL_sk_X509_free(sk); return NULL; } ret = DecodeToX509(x509, ssl->session.chain.certs[i].buffer, ssl->session.chain.certs[i].length); + if (ret == 0 && i == ssl->session.chain.count-1) { + /* On the last element in the chain try to add the CA chain + * first if we have one for this cert */ + if (pushCAx509Chain(ssl->ctx->cm, x509, sk) + == WOLFSSL_FATAL_ERROR) { + ret = WOLFSSL_FATAL_ERROR; + } + } if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error decoding cert"); @@ -18323,8 +19028,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) ssl->peerCertChain = sk; return sk; } -#endif /* OPENSSL_ALL || WOLFSSL_QT */ -#endif /* SESSION_CERTS */ +#endif /* SESSION_CERTS && OPENSSL_EXTRA */ #ifndef NO_CERTS #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ @@ -18334,10 +19038,15 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) * don't */ static void ExternalFreeX509(WOLFSSL_X509* x509) { +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) int doFree = 0; +#endif WOLFSSL_ENTER("ExternalFreeX509"); if (x509) { +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&x509->ex_data); +#endif if (x509->dynamicMemory) { #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) if (wc_LockMutex(&x509->refMutex) != 0) { @@ -18348,11 +19057,12 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) if (x509->refCount == 0) doFree = 1; wc_UnLockMutex(&x509->refMutex); - #else - doFree = 1; - #endif /* OPENSSL_EXTRA */ + #endif /* OPENSSL_EXTRA || OPENSSL_ALL */ - if (doFree) { + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + if (doFree) + #endif /* OPENSSL_EXTRA || OPENSSL_ALL */ + { FreeX509(x509); XFREE(x509, x509->heap, DYNAMIC_TYPE_X509); } @@ -20279,8 +20989,11 @@ int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline) } sectionName[sectionNameLen] = '\0'; - if (!(section = wolfSSL_CONF_get_section(conf, sectionName))) + if (!(section = wolfSSL_CONF_get_section(conf, sectionName))) { section = wolfSSL_CONF_new_section(conf, sectionName); + if (!section) + goto cleanup; + } } else { char* name; @@ -21463,7 +22176,7 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new(void) } /* add one to session reference count - * return WOFLSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) { if (session == NULL) @@ -21535,6 +22248,10 @@ void FreeSession(WOLFSSL_SESSION* session, int isAlloced) if (session == NULL) return; +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); +#endif + #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) if (session->peer) { wolfSSL_X509_free(session->peer); @@ -21583,6 +22300,28 @@ void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) FreeSession(session, 0); #endif } +/** +* set cipher to WOLFSSL_SESSION from WOLFSSL_CIPHER +* @param session a pointer to WOLFSSL_SESSION structure +* @param cipher a function pointer to WOLFSSL_CIPHER +* @return WOLFSSL_SUCCESS on success, otherwise WOLFSSL_FAILURE +*/ +int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, + const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); + + /* sanity check */ + if (session == NULL || cipher == NULL) { + WOLFSSL_MSG("bad argument"); + return WOLFSSL_FAILURE; + } + session->cipherSuite0 = cipher->cipherSuite0; + session->cipherSuite = cipher->cipherSuite; + + WOLFSSL_LEAVE("wolfSSL_SESSION_set_cipher", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} #endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ @@ -21645,10 +22384,18 @@ const char* wolfSSL_lib_version(void) } #ifdef OPENSSL_EXTRA +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +const char* wolfSSL_OpenSSL_version(int a) +{ + (void)a; + return "wolfSSL " LIBWOLFSSL_VERSION_STRING; +} +#else const char* wolfSSL_OpenSSL_version(void) { return "wolfSSL " LIBWOLFSSL_VERSION_STRING; } +#endif /* WOLFSSL_QT */ #endif @@ -22136,6 +22883,8 @@ static const char* wolfssl_ffdhe_name(word16 group) case WOLFSSL_FFDHE_8192: str = "FFDHE_8192"; break; + default: + break; } return str; } @@ -22381,7 +23130,8 @@ int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, return textSz; } - if (buf != NULL && text != NULL) { + /* buf is not NULL from above */ + if (text != NULL) { textSz = min(textSz + 1, len); /* + 1 to account for null char */ if (textSz > 0) { XMEMCPY(buf, text, textSz - 1); @@ -22838,6 +23588,21 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ defined(OPENSSL_EXTRA_X509_SMALL)) + int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dest, + const WOLFSSL_ASN1_STRING* src) + { + if (src == NULL || dest == NULL) { + return WOLFSSL_FAILURE; + } + dest->type = src->type; + if(wolfSSL_ASN1_STRING_set(dest, src->data, src->length) + != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + dest->flags = src->flags; + + return WOLFSSL_SUCCESS; + } /* Creates a new WOLFSSL_ASN1_STRING structure given the input type. * * type is the type of set when WOLFSSL_ASN1_STRING is created @@ -22938,6 +23703,17 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) #ifndef NO_CERTS #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + const unsigned char* wolfSSL_ASN1_STRING_get0_data( + const WOLFSSL_ASN1_STRING* asn) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_get0_data"); + + if (asn) { + return (const unsigned char*)asn->data; + } else { + return NULL; + } + } unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn) { @@ -23685,6 +24461,7 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_BIO_set_fp error"); + wolfSSL_BIO_free(bio); return WOLFSSL_FAILURE; } @@ -23697,7 +24474,6 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) #endif /* NO_FILESYSTEM */ #endif /* XSNPRINTF */ -#endif /* !NO_BIO */ int wolfSSL_X509_signature_print(WOLFSSL_BIO *bp, const WOLFSSL_X509_ALGOR *sigalg, const WOLFSSL_ASN1_STRING *sig) @@ -23723,6 +24499,7 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) return WOLFSSL_SUCCESS; } +#endif /* !NO_BIO */ #ifndef NO_WOLFSSL_STUB void wolfSSL_X509_get0_signature(const WOLFSSL_ASN1_BIT_STRING **psig, @@ -23794,7 +24571,7 @@ int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher) strLen = (int)XSTRLEN(name); for (i = 0, j = 0, k = 0; i <= strLen; i++) { - if (k > MAX_SEGMENTS || j > MAX_SEGMENT_SZ) + if (k >= MAX_SEGMENTS || j >= MAX_SEGMENT_SZ) break; if (name[i] != '-' && name[i] != '\0') { @@ -24275,6 +25052,31 @@ int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data) return WOLFSSL_FAILURE; } +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +/* Set ex_data for WOLFSSL_BIO + * + * bio : BIO structure to set ex_data in + * idx : Index of ex_data to set + * data : Data to set in ex_data + * cleanup_routine : Function pointer to clean up data + * + * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure + */ +int wolfSSL_BIO_set_ex_data_with_cleanup( + WOLFSSL_BIO *bio, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_ex_data_with_cleanup"); + if (bio != NULL && idx < MAX_EX_DATA) { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&bio->ex_data, idx, data, + cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + /* Get ex_data in WOLFSSL_BIO at given index * * bio : BIO structure to get ex_data from @@ -24344,32 +25146,40 @@ int wolfSSL_COMP_add_compression_method(int method, void* data) } #endif -#ifndef NO_WOLFSSL_STUB +/* wolfSSL_set_dynlock_create_callback + * CRYPTO_set_dynlock_create_callback has been deprecated since openSSL 1.0.1. + * This function exists for compatibility purposes because wolfSSL satisfies + * thread safety without relying on the callback. + */ void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)( const char*, int)) { WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback"); (void)f; } -#endif - -#ifndef NO_WOLFSSL_STUB +/* wolfSSL_set_dynlock_lock_callback + * CRYPTO_set_dynlock_lock_callback has been deprecated since openSSL 1.0.1. + * This function exists for compatibility purposes because wolfSSL satisfies + * thread safety without relying on the callback. + */ void wolfSSL_set_dynlock_lock_callback( void (*f)(int, WOLFSSL_dynlock_value*, const char*, int)) { WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback"); (void)f; } -#endif - -#ifndef NO_WOLFSSL_STUB +/* wolfSSL_set_dynlock_destroy_callback + * CRYPTO_set_dynlock_destroy_callback has been deprecated since openSSL 1.0.1. + * This function exists for compatibility purposes because wolfSSL satisfies + * thread safety without relying on the callback. + */ void wolfSSL_set_dynlock_destroy_callback( void (*f)(WOLFSSL_dynlock_value*, const char*, int)) { WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback"); (void)f; } -#endif + #endif /* OPENSSL_EXTRA */ @@ -24410,15 +25220,15 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, const char* footer = NULL; if (type != X509_FILETYPE_PEM) - return BAD_FUNC_ARG; + return WS_RETURN_CODE(BAD_FUNC_ARG,WOLFSSL_FAILURE); fp = XFOPEN(file, "rb"); if (fp == XBADFILE) - return BAD_FUNC_ARG; + return WS_RETURN_CODE(BAD_FUNC_ARG,WOLFSSL_FAILURE); if(XFSEEK(fp, 0, XSEEK_END) != 0) { XFCLOSE(fp); - return WOLFSSL_BAD_FILE; + return WS_RETURN_CODE(WOLFSSL_BAD_FILE,WOLFSSL_FAILURE); } sz = XFTELL(fp); XREWIND(fp); @@ -24488,12 +25298,12 @@ end: if (pem != NULL) XFREE(pem, 0, DYNAMIC_TYPE_PEM); XFCLOSE(fp); - return ret; + return WS_RETURN_CODE(ret,WOLFSSL_FAILURE); #else (void)lookup; (void)file; (void)type; - return WOLFSSL_FAILURE; + return WS_RETURN_CODE(WOLFSSL_FAILURE,WOLFSSL_FAILURE); #endif } @@ -24511,35 +25321,185 @@ WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) return &meth; } +/* set directory path to load certificate or CRL which have the hash.N form */ +/* for late use */ +/* @param ctx a pointer to WOLFSSL_BY_DIR structure */ +/* @param argc directory path */ +/* @param argl file type, either WOLFSSL_FILETYPE_PEM or */ +/* WOLFSSL_FILETYPE_ASN1 */ +/* @return WOLFSSL_SUCCESS on successful, othewise negative or zero */ +static int x509AddCertDir(WOLFSSL_BY_DIR *ctx, const char *argc, long argl) +{ + WOLFSSL_ENTER("x509AddCertDir"); + (void)argl; +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + WOLFSSL_BY_DIR_entry *entry; + size_t pathLen; + int i, num; + const char* c; +#ifdef WOLFSSL_SMALL_STACK + char *buf; +#else + char buf[MAX_FILENAME_SZ]; +#endif + + pathLen = 0; + c = argc; + /* sanity check, zero length */ + if (ctx == NULL || c == NULL || *c == '\0') + return WOLFSSL_FAILURE; + +#ifdef WOLFSSL_SMALL_STACK + buf = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_OPENSSL); + if (buf == NULL) { + WOLFSSL_LEAVE("x509AddCertDir", MEMORY_E); + return MEMORY_E; + } +#endif + + XMEMSET(buf, 0, MAX_FILENAME_SZ); + + do { + if (*c == SEPARATOR_CHAR || *c == '\0') { + + num = wolfSSL_sk_BY_DIR_entry_num(ctx->dir_entry); + + for (i=0; idir_entry, i); + + if (XSTRLEN(entry->dir_name) == pathLen && + XSTRNCMP(entry->dir_name, buf, pathLen) == 0) { + WOLFSSL_MSG("dir entry found"); + break; + } + } + + if (num == -1 || i == num) { + WOLFSSL_MSG("no entry found"); + + if (ctx->dir_entry == NULL) { + ctx->dir_entry = wolfSSL_sk_BY_DIR_entry_new_null(); + + if (ctx->dir_entry == NULL) { + WOLFSSL_MSG("failed to allocate dir_entry"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL); + #endif + return 0; + } + } + + entry = wolfSSL_BY_DIR_entry_new(); + if (entry == NULL) { + WOLFSSL_MSG("failed to allocate dir entry"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL); + #endif + return 0; + } + entry->dir_type = (int)argl; + entry->dir_name = (char*)XMALLOC(pathLen + 1/* \0 termination*/ + , NULL, DYNAMIC_TYPE_OPENSSL); + entry->hashes = wolfSSL_sk_BY_DIR_HASH_new_null(); + if (entry->dir_name == NULL || entry->hashes == NULL) { + WOLFSSL_MSG("failed to allocate dir name"); + wolfSSL_BY_DIR_entry_free(entry); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL); + #endif + return 0; + } + + XSTRNCPY(entry->dir_name, buf, pathLen); + entry->dir_name[pathLen] = '\0'; + + if (wolfSSL_sk_BY_DIR_entry_push(ctx->dir_entry, entry) + != WOLFSSL_SUCCESS) { + wolfSSL_BY_DIR_entry_free(entry); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL); + #endif + return 0; + } + } + /* skip separator */ + if (*c == SEPARATOR_CHAR) c++; + + pathLen = 0; + XMEMSET(buf, 0, MAX_FILENAME_SZ); + } + buf[pathLen++] = *c; + + } while(*c++ != '\0'); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL); +#endif + + return WOLFSSL_SUCCESS; +#else + (void)ctx; + (void)argc; + return WOLFSSL_NOT_IMPLEMENTED; +#endif +} + +/* set additional data to X509_LOOKUP */ +/* @param ctx a pointer to X509_LOOKUP structure */ +/* @param cmd control command : */ +/* X509_L_FILE_LOAD, X509_L_ADD_DIR X509_L_ADD_STORE or */ +/* X509_L_LOAD_STORE */ +/* @param argc arguments for the control command */ +/* @param argl arguments for the control command */ +/* @param **ret return value of the control command */ +/* @return WOLFSSL_SUCCESS on successful, othewise WOLFSSL_FAILURE */ +/* note: WOLFSSL_X509_L_ADD_STORE and WOLFSSL_X509_L_LOAD_STORE have not*/ +/* yet implemented. It retutns WOLFSSL_NOT_IMPLEMENTED */ +/* when those control commands are passed. */ int wolfSSL_X509_LOOKUP_ctrl(WOLFSSL_X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) { - /* control commands: - * X509_L_FILE_LOAD, X509_L_ADD_DIR, X509_L_ADD_STORE, X509_L_LOAD_STORE - */ - - /* returns -1 if the X509_LOOKUP doesn't have an associated X509_LOOKUP_METHOD */ - - + int lret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_X509_LOOKUP_ctrl"); +#if !defined(NO_FILESYSTEM) if (ctx != NULL) { switch (cmd) { case WOLFSSL_X509_L_FILE_LOAD: + /* expects to return a number of processed cert or crl file */ + lret = wolfSSL_X509_load_cert_crl_file(ctx, argc, (int)argl) > 0 ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + break; case WOLFSSL_X509_L_ADD_DIR: + /* store directory loaction to use it later */ +#if !defined(NO_WOLFSSL_DIR) + lret = x509AddCertDir(ctx->dirs, argc, argl); +#else + (void)x509AddCertDir; + lret = WOLFSSL_NOT_IMPLEMENTED; +#endif + break; case WOLFSSL_X509_L_ADD_STORE: case WOLFSSL_X509_L_LOAD_STORE: - return WOLFSSL_SUCCESS; + return WOLFSSL_NOT_IMPLEMENTED; default: break; } - } - - (void)argc; (void)argl; (void)ret; - - return WOLFSSL_FAILURE; + (void)ret; +#else + (void)ctx; + (void)argc; + (void)argl; + (void)ret; + (void)cmd; + (void)x509AddCertDir; + lret = WOLFSSL_NOT_IMPLEMENTED; +#endif + return lret; } @@ -24547,13 +25507,13 @@ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509_LOOKUP_METHOD* m) { WOLFSSL_ENTER("SSL_X509_STORE_add_lookup"); - if (store == NULL) + if (store == NULL || m == NULL) return NULL; - /* Method is a dummy value and is not needed. */ - (void)m; /* Make sure the lookup has a back reference to the store. */ store->lookup.store = store; + /* store a type to know which method wants to be used for */ + store->lookup.type = m->type; return &store->lookup; } @@ -24613,7 +25573,6 @@ cleanup: return ret; } -#endif /* !NO_BIO */ /* Converts the X509 to DER format and outputs it into bio. * @@ -24633,6 +25592,7 @@ int wolfSSL_i2d_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) return loadX509orX509REQFromBio(bio, x509, 1); } #endif /* WOLFSSL_CERT_REQ */ +#endif /* !NO_BIO */ #endif /* WOLFSSL_CERT_GEN */ /* Converts an internal structure to a DER buffer @@ -24699,7 +25659,7 @@ static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio, } size = wolfSSL_BIO_get_len(bio); - if (size == 0) { + if (size <= 0) { WOLFSSL_MSG("wolfSSL_BIO_get_len error. Possibly no pending data."); return NULL; } @@ -24738,7 +25698,6 @@ static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio, XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL); return localX509; } -#endif /* !NO_BIO */ WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) { @@ -24751,9 +25710,10 @@ WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) return d2i_X509orX509REQ_bio(bio, x509, 1); } #endif +#endif /* !NO_BIO */ #if !defined(NO_ASN) && !defined(NO_PWDBASED) -#ifndef NO_BIO +#if !defined(NO_BIO) && defined(HAVE_PKCS12) WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) { WC_PKCS12* localPkcs12 = NULL; @@ -24833,7 +25793,7 @@ int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12) return ret; } -#endif /* !NO_BIO */ +#endif /* !NO_BIO && HAVE_PKCS12 */ /* Copies unencrypted DER key buffer into "der". If "der" is null then the size * of buffer needed is returned. If *der == NULL then it allocates a buffer. @@ -24846,6 +25806,7 @@ int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der) return wolfSSL_EVP_PKEY_get_der(key, der); } +#ifdef HAVE_PKCS12 /* Creates a new WC_PKCS12 structure * * pass password to use @@ -25233,6 +26194,7 @@ int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw, return wc_PKCS12_verify_ex(pkcs12, (const byte*)psw, pswLen) == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } +#endif /* HAVE_PKCS12 */ #endif /* !NO_ASN && !NO_PWDBASED */ @@ -25408,7 +26370,17 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) { goto err_exit; } - + XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + if ((store->lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR), + NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("store->lookup.dir memory allocation error"); + goto err_exit; + } + XMEMSET(store->lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR)); + if (wc_InitMutex(&store->lookup.dirs->lock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + goto err_exit; + } #endif return store; @@ -25424,7 +26396,14 @@ err_exit: void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { - if (store != NULL && store->isDynamic) { + if (store == NULL) + return; + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&store->ex_data); +#endif + + if (store->isDynamic) { if (store->cm != NULL) { wolfSSL_CertManagerFree(store->cm); store->cm = NULL; @@ -25434,11 +26413,89 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL); store->param = NULL; } + + if (store->lookup.dirs != NULL) { +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (store->lookup.dirs->dir_entry) { + wolfSSL_sk_BY_DIR_entry_free(store->lookup.dirs->dir_entry); + } +#endif + wc_FreeMutex(&store->lookup.dirs->lock); + XFREE(store->lookup.dirs, NULL, DYNAMIC_TYPE_OPENSSL); + store->lookup.dirs = NULL; + } #endif XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); } } +/** + * Get ex_data in WOLFSSL_STORE at given index + * @param store a pointer to WOLFSSL_X509_STORE structure + * @param idx Index of ex_data to get data from + * @return void pointer to ex_data on success or NULL on failure + */ +void* wolfSSL_X509_STORE_get_ex_data(WOLFSSL_X509_STORE* store, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_get_ex_data"); +#ifdef HAVE_EX_DATA + if (store != NULL && idx < MAX_EX_DATA && idx >= 0) { + return wolfSSL_CRYPTO_get_ex_data(&store->ex_data, idx); + } +#else + (void)store; + (void)idx; +#endif + return NULL; +} + +/** + * Set ex_data for WOLFSSL_STORE + * @param store a pointer to WOLFSSL_X509_STORE structure + * @param idx Index of ex data to set + * @param data Data to set in ex data + * @return WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure + */ +int wolfSSL_X509_STORE_set_ex_data(WOLFSSL_X509_STORE* store, int idx, + void *data) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_ex_data"); +#ifdef HAVE_EX_DATA + if (store != NULL && idx < MAX_EX_DATA) { + return wolfSSL_CRYPTO_set_ex_data(&store->ex_data, idx, data); + } +#else + (void)store; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +/** + * Set ex_data for WOLFSSL_STORE + * @param store a pointer to WOLFSSL_X509_STORE structure + * @param idx Index of ex data to set + * @param data Data to set in ex data + * @return WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure + */ +int wolfSSL_X509_STORE_set_ex_data_with_cleanup( + WOLFSSL_X509_STORE* store, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_ex_data_with_cleanup"); + if (store != NULL && idx < MAX_EX_DATA) { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&store->ex_data, idx, + data, cleanup_routine); + } + return WOLFSSL_FAILURE; +} + +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #ifdef OPENSSL_EXTRA @@ -25560,6 +26617,9 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) { WOLFSSL_ENTER("X509_STORE_CTX_free"); if (ctx != NULL) { +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&ctx->ex_data); +#endif #ifdef OPENSSL_EXTRA if (ctx->param != NULL){ XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL); @@ -25627,7 +26687,9 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) int ret = 0; int depth = 0; int error; +#ifndef NO_ASN_TIME byte *afterDate, *beforeDate; +#endif WOLFSSL_ENTER("wolfSSL_X509_verify_cert"); @@ -25654,6 +26716,7 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) #endif } + #ifndef NO_ASN_TIME error = 0; /* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or ASN_BEFORE_DATE_E if there are no additional errors found in the @@ -25679,6 +26742,7 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) ctx->store->verify_cb(0, ctx); #endif } + #endif /* OpenSSL returns 0 when a chain can't be built */ if (ret == ASN_NO_SIGNER_E) @@ -25798,7 +26862,7 @@ static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz); } #endif - #if !defined(NO_ASN) && !defined(NO_PWDBASED) + #if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) else if (type == PKCS12_TYPE) { if ((newx509 = wc_PKCS12_new()) == NULL) { goto err_exit; @@ -25823,7 +26887,7 @@ static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) goto _exit; err_exit: -#if !defined(NO_ASN) && !defined(NO_PWDBASED) +#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) if ((newx509 != NULL) && (type == PKCS12_TYPE)) { wc_PKCS12_free((WC_PKCS12*)newx509); newx509 = NULL; @@ -25847,16 +26911,213 @@ WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509) WOLFSSL_ENTER("wolfSSL_d2i_X509_fp"); return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE); } +/* load certificate or CRL file, and add it to the STORE */ +/* @param ctx a pointer to X509_LOOKUP structure */ +/* @param file file name to load */ +/* @param type WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1 */ +/* @return a number of loading CRL or certificate, otherwise zero */ +WOLFSSL_API int wolfSSL_X509_load_cert_crl_file(WOLFSSL_X509_LOOKUP *ctx, + const char *file, int type) +{ + STACK_OF(WOLFSSL_X509_INFO) *info; + WOLFSSL_X509_INFO *info_tmp; + WOLFSSL_BIO *bio; + WOLFSSL_X509 *x509 = NULL; + + int i; + int cnt = 0; + int num = 0; + + WOLFSSL_ENTER("wolfSSL_X509_load_cert_crl_file"); + + /* stanity check */ + if (ctx == NULL || file == NULL) { + WOLFSSL_MSG("bad arguments"); + return 0; + } + + if (type != WOLFSSL_FILETYPE_PEM) { + x509 = wolfSSL_X509_load_certificate_file(file, type); + if (x509 != NULL) { + if (wolfSSL_X509_STORE_add_cert(ctx->store, x509) + == WOLFSSL_SUCCESS) { + cnt++; + } else { + WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert error"); + } + wolfSSL_X509_free(x509); + x509 = NULL; + } else { + WOLFSSL_MSG("wolfSSL_X509_load_certificate_file error"); + } + + } else { +#ifdef OPENSSL_ALL + bio = wolfSSL_BIO_new_file(file, "rb"); + if(!bio) { + WOLFSSL_MSG("wolfSSL_BIO_new error"); + return cnt; + } + + info = wolfSSL_PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + + wolfSSL_BIO_free(bio); + + if (!info) { + WOLFSSL_MSG("wolfSSL_PEM_X509_INFO_read_bio error"); + return cnt; + } + num = wolfSSL_sk_X509_INFO_num(info); + for (i=0; i < num; i++) { + info_tmp = wolfSSL_sk_X509_INFO_value(info, i); + + if (info_tmp->x509) { + if(wolfSSL_X509_STORE_add_cert(ctx->store, info_tmp->x509) == + WOLFSSL_SUCCESS) { + cnt ++; + } else { + WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert failed"); + } + } +#ifdef HAVE_CRL + if (info_tmp->crl) { + if(wolfSSL_X509_STORE_add_crl(ctx->store, info_tmp->crl) == + WOLFSSL_SUCCESS) { + cnt ++; + } else { + WOLFSSL_MSG("wolfSSL_X509_STORE_add_crl failed"); + } + } +#endif + } + wolfSSL_sk_X509_INFO_pop_free(info, X509_INFO_free); +#else + (void)i; + (void)cnt; + (void)num; + (void)info_tmp; + (void)info; + (void)bio; +#endif + } + + WOLFSSL_LEAVE("wolfSSL_X509_load_ceretificate_crl_file", cnt); + return cnt; +} #endif /* !NO_FILESYSTEM */ #ifdef HAVE_CRL + +#ifndef NO_BIO +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_bio(WOLFSSL_BIO *bp, + WOLFSSL_X509_CRL **x) +{ + int derSz; + byte* der = NULL; + WOLFSSL_X509_CRL* crl = NULL; + + if (bp == NULL) + return NULL; + + if ((derSz = wolfSSL_BIO_get_len(bp)) > 0) { + der = (byte*)XMALLOC(derSz, 0, DYNAMIC_TYPE_DER); + if (der != NULL) { + if (wolfSSL_BIO_read(bp, der, derSz) == derSz) { + crl = wolfSSL_d2i_X509_CRL(x, der, derSz); + } + } + } + + if (der != NULL) { + XFREE(der, 0, DYNAMIC_TYPE_DER); + } + + return crl; +} +#endif + #ifndef NO_FILESYSTEM WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl) { WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp"); return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE); } + +/* Read CRL file, and add it to store and corresponding cert manager */ +/* @param ctx a pointer of X509_LOOKUP back to the X509_STORE */ +/* @param file a file to read */ +/* @param type WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1 */ +/* @return WOLFSSL_SUCCESS(1) on successful, othewise WOLFSSL_FAILURE(0)*/ +WOLFSSL_API int wolfSSL_X509_load_crl_file(WOLFSSL_X509_LOOKUP *ctx, + const char *file, int type) +{ + int ret = WOLFSSL_FAILURE; + int count = 0; + WOLFSSL_BIO *bio = NULL; + WOLFSSL_X509_CRL *crl = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_load_crl_file"); + + if (ctx == NULL || file == NULL) + return ret; + + if ((bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file())) == NULL) + return ret; + + if (wolfSSL_BIO_read_filename(bio, file) <= 0) { + wolfSSL_BIO_free(bio); + return ret; + } + + if (wolfSSL_BIO_read_filename(bio, file) <= 0) { + wolfSSL_BIO_free(bio); + return ret; + } + + if (type == WOLFSSL_FILETYPE_PEM) { + do { + crl = wolfSSL_PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL); + if (crl == NULL) { + if (count <= 0) { + WOLFSSL_MSG("Load crl failed"); + } + break; + } + + ret = wolfSSL_X509_STORE_add_crl(ctx->store, crl); + if (ret == WOLFSSL_FAILURE) { + WOLFSSL_MSG("Adding crl failed"); + break; + } + count++; + wolfSSL_X509_CRL_free(crl); + crl = NULL; + } while(crl == NULL); + + ret = count; + } else if (type == WOLFSSL_FILETYPE_ASN1) { + crl = wolfSSL_d2i_X509_CRL_bio(bio, NULL); + if (crl == NULL) { + WOLFSSL_MSG("Load crl failed"); + } else { + ret = wolfSSL_X509_STORE_add_crl(ctx->store, crl); + if (ret == WOLFSSL_FAILURE) { + WOLFSSL_MSG("Adding crl failed"); + } else { + ret = 1;/* handled a file */ + } + } + } else { + WOLFSSL_MSG("Invalid file type"); + } + + wolfSSL_X509_CRL_free(crl); + wolfSSL_BIO_free(bio); + + WOLFSSL_LEAVE("wolfSSL_X509_load_crl_file", ret); + return ret; +} #endif /* !NO_FILESYSTEM */ @@ -26066,6 +27327,69 @@ int wolfSSL_X509_VERIFY_PARAM_clear_flags(WOLFSSL_X509_VERIFY_PARAM *param, } +/* inherits properties of param "to" to param "from" +* +* WOLFSSL_VPARAM_DEFAULT any values in "src" is copied +* if "src" value is new for "to". +* WOLFSSL_VPARAM_OVERWRITE all values of "form" are copied to "to" +* WOLFSSL_VPARAM_RESET_FLAGS the flag values are copied, not Ored +* WOLFSSL_VPARAM_LOCKED don't copy any values +* WOLFSSL_VPARAM_ONCE the current inherit_flags is zerroed +*/ +static int wolfSSL_X509_VERIFY_PARAM_inherit(WOLFSSL_X509_VERIFY_PARAM *to, + const WOLFSSL_X509_VERIFY_PARAM *from) +{ + int ret = WOLFSSL_FAILURE; + int isOverWrite = 0; + int isDefault = 0; + unsigned int flags; + + /* sanity check */ + if (!to || !from) { + /* be compatible to openssl return value */ + return WOLFSSL_SUCCESS; + } + flags = to->inherit_flags | from->inherit_flags; + + if (flags & WOLFSSL_VPARAM_LOCKED) { + return WOLFSSL_SUCCESS; + } + + if (flags & WOLFSSL_VPARAM_ONCE) { + to->inherit_flags = 0; + } + + isOverWrite = (flags & WOLFSSL_VPARAM_OVERWRITE); + isDefault = (flags & WOLFSSL_VPARAM_DEFAULT); + + /* copy check_time if check time is not set */ + if ((to->flags & WOLFSSL_USE_CHECK_TIME) == 0 || isOverWrite) { + to->check_time = from->check_time; + to->flags &= ~WOLFSSL_USE_CHECK_TIME; + } + /* host name */ + if (isOverWrite || + (from->hostName[0] != 0 && (to->hostName[0] == 0 || isDefault))) { + if (!(ret = wolfSSL_X509_VERIFY_PARAM_set1_host(to, from->hostName, + (int)XSTRLEN(from->hostName)))) + return ret; + to->hostFlags = from->hostFlags; + } + /* ip ascii */ + if (isOverWrite || + (from->ipasc[0] != 0 && (to->ipasc[0] == 0 || isDefault))) { + + if (!(ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(to, from->ipasc))) + return ret; + } + + if (flags & WOLFSSL_VPARAM_RESET_FLAGS) + to->flags = 0; + + to->flags |= from->flags; + + return ret; +} /****************************************************************************** * wolfSSL_X509_VERIFY_PARAM_set1_host - sets the DNS hostname to name * hostnames is cleared if name is NULL or empty. @@ -26102,17 +27426,42 @@ int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam, if (nameSz > 0) XMEMCPY(pParam->hostName, name, nameSz); - pParam->hostName[nameSz] = '\0'; + pParam->hostName[nameSz] = '\0'; return WOLFSSL_SUCCESS; } /****************************************************************************** -* wolfSSL_get0_param - return a pointer to the SSL verification parameters +* wolfSSL_CTX_set1_param - set a pointer to the SSL verification parameters +* +* RETURNS: +* WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +* Note: Returns WOLFSSL_SUCCESS, in case either parameter is NULL, +* same as openssl. +*/ +int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm) +{ + if (ctx == NULL || vpm == NULL) + return WOLFSSL_SUCCESS; + + return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm); +} + +/****************************************************************************** +* wolfSSL_CTX/_get0_param - return a pointer to the SSL verification parameters * * RETURNS: * returns pointer to the SSL verification parameters on success, * otherwise returns NULL */ +WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return NULL; + } + + return ctx->param; +} + WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) { if (ssl == NULL) { @@ -26121,6 +27470,32 @@ WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) return ssl->param; } +/* Set VERIFY PARAM from "from" pointer to "to" pointer */ +int wolfSSL_X509_VERIFY_PARAM_set1(WOLFSSL_X509_VERIFY_PARAM *to, + const WOLFSSL_X509_VERIFY_PARAM *from) +{ + int ret = WOLFSSL_FAILURE; + unsigned int _inherit_flags; + + if (!to) { + return ret; + } + /* keeps the inherit flags for save */ + _inherit_flags = to->inherit_flags; + + /* Ored DEFAULT inherit flag proerty to copy "from" contents to "to" + * contents + */ + to->inherit_flags |= WOLFSSL_VPARAM_DEFAULT; + + ret = wolfSSL_X509_VERIFY_PARAM_inherit(to, from); + + /* restore inherit flag */ + to->inherit_flags = _inherit_flags; + + return ret; +} + /* Set the host flag in the X509_VERIFY_PARAM structure */ void wolfSSL_X509_VERIFY_PARAM_set_hostflags(WOLFSSL_X509_VERIFY_PARAM* param, unsigned int flags) @@ -26607,6 +27982,25 @@ int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx, return WOLFSSL_FAILURE; } +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +/* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS + * on success, WOLFSSL_FAILURE on error. */ +int wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup( + WOLFSSL_X509_STORE_CTX* ctx, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup"); + if (ctx != NULL) + { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, data, + cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + #if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth) { @@ -27542,9 +28936,10 @@ long wolfSSL_set_options(WOLFSSL* ssl, long op) if (ssl->suites != NULL && ssl->options.side != WOLFSSL_NEITHER_END) InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveNTRU, - ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); return ssl->options.mask; } @@ -27701,8 +29096,7 @@ long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) } if (type == TLSEXT_STATUSTYPE_ocsp){ - int r = 0; - r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s, + int r = TLSX_UseCertificateStatusRequest(&s->extensions, (byte)type, 0, s, s->heap, s->devId); return (long)r; } else { @@ -27930,10 +29324,14 @@ void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at) wolfSSL_ASN1_OBJECT_free(at->value.object); break; case V_ASN1_UTCTIME: + #ifndef NO_ASN_TIME wolfSSL_ASN1_TIME_free(at->value.utctime); + #endif break; case V_ASN1_GENERALIZEDTIME: + #ifndef NO_ASN_TIME wolfSSL_ASN1_TIME_free(at->value.generalizedtime); + #endif break; case V_ASN1_UTF8STRING: case V_ASN1_PRINTABLESTRING: @@ -29396,6 +30794,45 @@ void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out, *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0; #endif /* WOLFSSL_AES_CFB */ } + +/* wc_AesKey*Wrap_ex API not available in FIPS and SELFTEST */ +#if defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) +int wolfSSL_AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_AES_wrap_key"); + + if (out == NULL || in == NULL) { + WOLFSSL_MSG("Error, Null argument passed in"); + return WOLFSSL_FAILURE; + } + + ret = wc_AesKeyWrap_ex((Aes*)key, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv); + + return ret < 0 ? WOLFSSL_FAILURE : ret; +} + +int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_AES_wrap_key"); + + if (out == NULL || in == NULL) { + WOLFSSL_MSG("Error, Null argument passed in"); + return WOLFSSL_FAILURE; + } + + ret = wc_AesKeyUnWrap_ex((Aes*)key, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv); + + return ret < 0 ? WOLFSSL_FAILURE : ret; +} +#endif /* HAVE_AES_KEYWRAP && !HAVE_FIPS && !HAVE_SELFTEST */ #endif /* NO_AES */ #ifndef NO_FILESYSTEM @@ -29556,16 +30993,23 @@ int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) * returns WOLFSSL_SUCCESS (1) if correct otherwise WOLFSSL_FAILURE (0) */ int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a) { +#ifndef NO_ASN_TIME char buf[MAX_TIME_STRING_SZ]; +#endif WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check"); +#ifndef NO_ASN_TIME /* if can parse the WOLFSSL_ASN1_TIME passed in then consider syntax good */ if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf, MAX_TIME_STRING_SZ) == NULL) { return WOLFSSL_FAILURE; } return WOLFSSL_SUCCESS; +#else + (void)a; + return WOLFSSL_FAILURE; +#endif } #endif /* !NO_ASN_TIME */ @@ -29588,6 +31032,7 @@ WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t) (void)t; return s; } +#endif /* !NO_WOLFSSL_STUB */ int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *s, const char *str) { @@ -29605,12 +31050,12 @@ int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *s, const char *str) } if (s) { XMEMCPY(s->data, str, slen); - s->length = slen; - s->type = slen == ASN_UTC_TIME_SIZE ? ASN_UTC_TIME : ASN_GENERALIZED_TIME; + s->length = slen - 1; /* do not include null terminator in length */ + s->type = slen == ASN_UTC_TIME_SIZE ? V_ASN1_UTCTIME : + V_ASN1_GENERALIZEDTIME; } return WOLFSSL_SUCCESS; } -#endif /* !NO_WOLFSSL_STUB */ #ifndef NO_BIO @@ -29642,21 +31087,36 @@ int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, } p = (const char *)(asnTime->data); /* GetTimeString not always available. */ - wolfSSL_BIO_write(bio, MonthStr(p + 4), 3); - wolfSSL_BIO_write(bio, " ", 1); + if (wolfSSL_BIO_write(bio, MonthStr(p + 4), 3) <= 0) + return WOLFSSL_FAILURE; + if (wolfSSL_BIO_write(bio, " ", 1) <= 0) + return WOLFSSL_FAILURE; + /* Day */ - wolfSSL_BIO_write(bio, p + 6, 2); - wolfSSL_BIO_write(bio, " ", 1); + if (wolfSSL_BIO_write(bio, p + 6, 2) <= 0) + return WOLFSSL_FAILURE; + if (wolfSSL_BIO_write(bio, " ", 1) <= 0) + return WOLFSSL_FAILURE; + /* Hour */ - wolfSSL_BIO_write(bio, p + 8, 2); - wolfSSL_BIO_write(bio, ":", 1); + if (wolfSSL_BIO_write(bio, p + 8, 2) <= 0) + return WOLFSSL_FAILURE; + if (wolfSSL_BIO_write(bio, ":", 1) <= 0) + return WOLFSSL_FAILURE; + /* Min */ - wolfSSL_BIO_write(bio, p + 10, 2); - wolfSSL_BIO_write(bio, ":", 1); + if (wolfSSL_BIO_write(bio, p + 10, 2) <= 0) + return WOLFSSL_FAILURE; + if (wolfSSL_BIO_write(bio, ":", 1) <= 0) + return WOLFSSL_FAILURE; + /* Secs */ - wolfSSL_BIO_write(bio, p + 12, 2); - wolfSSL_BIO_write(bio, " ", 1); - wolfSSL_BIO_write(bio, p, 4); + if (wolfSSL_BIO_write(bio, p + 12, 2) <= 0) + return WOLFSSL_FAILURE; + if (wolfSSL_BIO_write(bio, " ", 1) <= 0) + return WOLFSSL_FAILURE; + if (wolfSSL_BIO_write(bio, p, 4) <= 0) + return WOLFSSL_FAILURE; return 0; } @@ -29755,6 +31215,8 @@ WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) switch (sk->type) { case STACK_TYPE_X509: + if (!sk->data.x509) + break; cur->data.x509 = wolfSSL_X509_dup(sk->data.x509); if (!cur->data.x509) { WOLFSSL_MSG("wolfSSL_X509_dup error"); @@ -29765,6 +31227,8 @@ WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) wolfSSL_CIPHER_copy(&sk->data.cipher, &cur->data.cipher); break; case STACK_TYPE_GEN_NAME: + if (!sk->data.gn) + break; cur->data.gn = wolfSSL_GENERAL_NAME_dup(sk->data.gn); if (!cur->data.gn) { WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error"); @@ -29772,6 +31236,8 @@ WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) } break; case STACK_TYPE_OBJ: + if (!sk->data.obj) + break; cur->data.obj = wolfSSL_ASN1_OBJECT_dup(sk->data.obj); if (!cur->data.obj) { WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error"); @@ -30601,8 +32067,8 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = { "certificatePolicies", "X509v3 Certificate Policies"}, /* oidCertAuthInfoType */ - { AIA_OCSP_OID, AIA_OCSP_OID, oidCertAuthInfoType, "authorityInfoAccess", - "Authority Information Access"}, + { AIA_OCSP_OID, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP", + "OCSP"}, { AIA_CA_ISSUER_OID, AIA_CA_ISSUER_OID, oidCertAuthInfoType, "caIssuers", "CA Issuers"}, @@ -30640,6 +32106,8 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = { "emailAddress"}, { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC", "domainComponent"}, + { NID_favouriteDrink, NID_favouriteDrink, oidCertNameType, "favouriteDrink", + "favouriteDrink"}, { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory", "businessCategory"}, { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC", @@ -30908,8 +32376,13 @@ WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, int *initTmpRng) !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) rng = ((RsaKey*)rsa->internal)->rng; #endif - if (rng == NULL && tmpRNG) { - if (!*tmpRNG) { + if (tmpRNG != NULL + #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + && rng == NULL + #endif + ) { + if (*tmpRNG == NULL) { #ifdef WOLFSSL_SMALL_STACK *tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*tmpRNG == NULL) @@ -30949,33 +32422,41 @@ WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, int *initTmpRng) */ static int wolfSSL_RAND_Init(void) { - if (wc_LockMutex(&globalRNGMutex) != 0) { - WOLFSSL_MSG("Bad Lock Mutex rng"); - return 0; - } - if (initGlobalRNG == 0) { - if (wc_InitRng(&globalRNG) < 0) { - WOLFSSL_MSG("wolfSSL Init Global RNG failed"); - wc_UnLockMutex(&globalRNGMutex); - return 0; + int ret = WOLFSSL_FAILURE; +#ifdef HAVE_GLOBAL_RNG + if (wc_LockMutex(&globalRNGMutex) == 0) { + if (initGlobalRNG == 0) { + ret = wc_InitRng(&globalRNG); + if (ret == 0) { + initGlobalRNG = 1; + ret = WOLFSSL_SUCCESS; + } } - initGlobalRNG = 1; + wc_UnLockMutex(&globalRNGMutex); } - - wc_UnLockMutex(&globalRNGMutex); - return WOLFSSL_SUCCESS; +#endif + return ret; } /* WOLFSSL_SUCCESS on ok */ int wolfSSL_RAND_seed(const void* seed, int len) { - - WOLFSSL_MSG("wolfSSL_RAND_seed"); - +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->seed) { + int ret = gRandMethods->seed(seed, len); + wc_UnLockMutex(&gRandMethodMutex); + return ret; + } + wc_UnLockMutex(&gRandMethodMutex); + } +#else (void)seed; (void)len; +#endif + /* Make sure global shared RNG (globalRNG) is initialized */ return wolfSSL_RAND_Init(); } @@ -31145,6 +32626,7 @@ int wolfSSL_RAND_egd(const char* nm) } #endif + XMEMSET(&rem, 0, sizeof(struct sockaddr_un)); if (nm == NULL) { #ifdef WOLFSSL_SMALL_STACK XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -31160,35 +32642,28 @@ int wolfSSL_RAND_egd(const char* nm) #endif return WOLFSSL_FATAL_ERROR; } - if (ret == WOLFSSL_SUCCESS) { - rem.sun_family = AF_UNIX; - XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1); - rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; - } + rem.sun_family = AF_UNIX; + XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1); + rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; /* connect to egd server */ - if (ret == WOLFSSL_SUCCESS) { - if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) - == -1) { - WOLFSSL_MSG("error connecting to egd server"); - ret = WOLFSSL_FATAL_ERROR; - } + if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) == -1) { + WOLFSSL_MSG("error connecting to egd server"); + ret = WOLFSSL_FATAL_ERROR; } while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) { - if (ret == WOLFSSL_SUCCESS) { - buf[idx] = WOLFSSL_EGD_NBLOCK; - buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */ - ret = (int)write(fd, buf + idx, 2); - if (ret <= 0 || ret != 2) { - if (errno == EAGAIN) { - ret = WOLFSSL_SUCCESS; - continue; - } - WOLFSSL_MSG("error requesting entropy from egd server"); - ret = WOLFSSL_FATAL_ERROR; - break; + buf[idx] = WOLFSSL_EGD_NBLOCK; + buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */ + ret = (int)write(fd, buf + idx, 2); + if (ret != 2) { + if (errno == EAGAIN) { + ret = WOLFSSL_SUCCESS; + continue; } + WOLFSSL_MSG("error requesting entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; } /* attempting to read */ @@ -31279,48 +32754,79 @@ int wolfSSL_RAND_egd(const char* nm) void wolfSSL_RAND_Cleanup(void) { - WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()"); +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->cleanup) + gRandMethods->cleanup(); + wc_UnLockMutex(&gRandMethodMutex); + } - if (wc_LockMutex(&globalRNGMutex) != 0) { - WOLFSSL_MSG("Bad Lock Mutex rng"); - return; + if (wc_FreeMutex(&gRandMethodMutex) == 0) + gRandMethodsInit = 0; +#endif +#ifdef HAVE_GLOBAL_RNG + if (wc_LockMutex(&globalRNGMutex) == 0) { + if (initGlobalRNG) { + wc_FreeRng(&globalRNG); + initGlobalRNG = 0; + } + wc_UnLockMutex(&globalRNGMutex); } - if (initGlobalRNG != 0) { - wc_FreeRng(&globalRNG); - initGlobalRNG = 0; - } - wc_UnLockMutex(&globalRNGMutex); +#endif } - +/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */ int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) { +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->pseudorand) { + int ret = gRandMethods->pseudorand(buf, num); + wc_UnLockMutex(&gRandMethodMutex); + return ret; + } + wc_UnLockMutex(&gRandMethodMutex); + } +#endif + + /* fallback to using the global shared RNG */ return wolfSSL_RAND_bytes(buf, num); } - -/* WOLFSSL_SUCCESS on ok */ +/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */ int wolfSSL_RAND_bytes(unsigned char* buf, int num) { int ret = 0; - int initTmpRng = 0; WC_RNG* rng = NULL; #ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG; + WC_RNG* tmpRNG = NULL; #else WC_RNG tmpRNG[1]; #endif - int used_global = 0; + int initTmpRng = 0; int blockCount = 0; - - WOLFSSL_ENTER("wolfSSL_RAND_bytes"); - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return ret; +#ifdef HAVE_GLOBAL_RNG + int used_global = 0; #endif + WOLFSSL_ENTER("wolfSSL_RAND_bytes"); + /* sanity check */ + if (buf == NULL || num < 0) + /* return code compliant with OpenSSL */ + return 0; + + /* if a RAND callback has been set try and use it */ +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->bytes) { + ret = gRandMethods->bytes(buf, num); + wc_UnLockMutex(&gRandMethodMutex); + return ret; + } + wc_UnLockMutex(&gRandMethodMutex); + } +#endif +#ifdef HAVE_GLOBAL_RNG if (initGlobalRNG) { if (wc_LockMutex(&globalRNGMutex) != 0) { WOLFSSL_MSG("Bad Lock Mutex rng"); @@ -31330,41 +32836,51 @@ int wolfSSL_RAND_bytes(unsigned char* buf, int num) rng = &globalRNG; used_global = 1; } - else if(wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; + else +#endif + { + #ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return ret; + #endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } } if (rng) { - /* handles size grater than RNG_MAX_BLOCK_LEN */ + /* handles size greater than RNG_MAX_BLOCK_LEN */ blockCount = num / RNG_MAX_BLOCK_LEN; - - while(blockCount--) { - if((ret = wc_RNG_GenerateBlock(rng, buf, RNG_MAX_BLOCK_LEN) != 0)){ + + while (blockCount--) { + ret = wc_RNG_GenerateBlock(rng, buf, RNG_MAX_BLOCK_LEN); + if (ret != 0) { WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); break; } num -= RNG_MAX_BLOCK_LEN; buf += RNG_MAX_BLOCK_LEN; } - + if (ret == 0 && num) ret = wc_RNG_GenerateBlock(rng, buf, num); - + if (ret != 0) WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); else ret = WOLFSSL_SUCCESS; } - if (used_global == 1) { +#ifdef HAVE_GLOBAL_RNG + if (used_global == 1) wc_UnLockMutex(&globalRNGMutex); - } - +#endif if (initTmpRng) wc_FreeRng(tmpRNG); - #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG) + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return ret; @@ -31450,6 +32966,10 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFS } else { len = wolfSSL_BN_bn2bin(bn, a->data); + if (len < 0) { + wolfSSL_ASN1_INTEGER_free(a); + return NULL; + } } a->length = len; @@ -31841,7 +33361,7 @@ int SetDhInternal(WOLFSSL_DH* dh) } #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) \ - || defined(WOLFSSL_OPENSSH)) + || defined(WOLFSSL_OPENSSH)) || defined(OPENSSL_EXTRA) #ifdef WOLFSSL_DH_EXTRA WOLFSSL_DH* wolfSSL_DH_dup(WOLFSSL_DH* dh) @@ -31883,38 +33403,51 @@ WOLFSSL_DH* wolfSSL_DH_dup(WOLFSSL_DH* dh) #endif /* WOLFSSL_DH_EXTRA */ /* Set the members of DhKey into WOLFSSL_DH - * DhKey was populated from wc_DhKeyDecode + * Specify elements to set via the 2nd parmeter */ -int SetDhExternal(WOLFSSL_DH *dh) +int SetDhExternal_ex(WOLFSSL_DH *dh, int elm) { DhKey *key; - WOLFSSL_MSG("Entering SetDhExternal"); + WOLFSSL_MSG("Entering SetDhExternal_ex"); if (dh == NULL || dh->internal == NULL) { WOLFSSL_MSG("dh key NULL error"); + return WOLFSSL_FATAL_ERROR; } key = (DhKey*)dh->internal; - if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("dh param p error"); - return WOLFSSL_FATAL_ERROR; + if (elm & ELEMENT_P) { + if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dh param p error"); + return WOLFSSL_FATAL_ERROR; + } } - - if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("dh param g error"); - return WOLFSSL_FATAL_ERROR; + if (elm & ELEMENT_Q) { + if (SetIndividualExternal(&dh->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dh param q error"); + return WOLFSSL_FATAL_ERROR; + } + } + if (elm & ELEMENT_G) { + if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dh param g error"); + return WOLFSSL_FATAL_ERROR; + } } - #ifdef WOLFSSL_DH_EXTRA - if (SetIndividualExternal(&dh->priv_key, &key->priv) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("No DH Private Key"); - return WOLFSSL_FATAL_ERROR; + if (elm & ELEMENT_PRV) { + if (SetIndividualExternal(&dh->priv_key, &key->priv) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No DH Private Key"); + return WOLFSSL_FATAL_ERROR; + } } - - if (SetIndividualExternal(&dh->pub_key, &key->pub) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("No DH Public Key"); - return WOLFSSL_FATAL_ERROR; + if (elm & ELEMENT_PUB) { + if (SetIndividualExternal(&dh->pub_key, &key->pub) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No DH Public Key"); + return WOLFSSL_FATAL_ERROR; + } } #endif /* WOLFSSL_DH_EXTRA */ @@ -31922,6 +33455,16 @@ int SetDhExternal(WOLFSSL_DH *dh) return WOLFSSL_SUCCESS; } +/* Set the members of DhKey into WOLFSSL_DH + * DhKey was populated from wc_DhKeyDecode + * p, g, pub_key and pri_key are set. + */ +int SetDhExternal(WOLFSSL_DH *dh) +{ + int elements = ELEMENT_P | ELEMENT_G | ELEMENT_PUB | ELEMENT_PRV; + WOLFSSL_MSG("Entering SetDhExternal"); + return SetDhExternal_ex(dh, elements); +} #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ /* return code compliant with OpenSSL : @@ -32544,6 +34087,7 @@ int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p, return WOLFSSL_SUCCESS; } + #endif /* v1.1.0 or later */ #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ @@ -34298,6 +35842,61 @@ void *wolfSSL_OPENSSL_malloc(size_t a) return (void *)XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL); } +int wolfSSL_OPENSSL_hexchar2int(unsigned char c) +{ + int ret = -1; + + if ('0' <= c && c <= '9') { + ret = c - '0'; + } + else if ('a' <= c && c <= 'f') { + ret = c - 'a' + 0x0a; + } + else if ('A' <= c && c <= 'F') { + ret = c - 'A' + 0x0a; + } + + return ret; +} + +unsigned char *wolfSSL_OPENSSL_hexstr2buf(const char *str, long *len) +{ + unsigned char* targetBuf; + int srcDigitHigh = 0; + int srcDigitLow = 0; + size_t srcLen; + size_t srcIdx = 0; + long targetIdx = 0; + + srcLen = XSTRLEN(str); + targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL); + if (targetBuf == NULL) { + return NULL; + } + + while (srcIdx < srcLen) { + if (str[srcIdx] == ':') { + srcIdx++; + continue; + } + + srcDigitHigh = wolfSSL_OPENSSL_hexchar2int(str[srcIdx++]); + srcDigitLow = wolfSSL_OPENSSL_hexchar2int(str[srcIdx++]); + if (srcDigitHigh < 0 || srcDigitLow < 0) { + WOLFSSL_MSG("Invalid hex character."); + XFREE(targetBuf, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) | srcDigitLow); + } + + if (len != NULL) + *len = targetIdx; + + return targetBuf; +} + int wolfSSL_OPENSSL_init_ssl(word64 opts, const OPENSSL_INIT_SETTINGS *settings) { (void)opts; @@ -35271,12 +36870,28 @@ const char* wolfSSL_EC_curve_nid2nist(int nid) const WOLF_EC_NIST_NAME* nist_name; for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { if (nist_name->nid == nid) { - return kNistCurves->name; + return nist_name->name; } } return NULL; } +/** + * return nist curve id + * @param name nist curve name + * @return nist curve id when found, 0 when not found + */ +int wolfSSL_EC_curve_nist2nid(const char* name) +{ + const WOLF_EC_NIST_NAME* nist_name; + for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { + if (XSTRCMP(nist_name->name, name) == 0) { + return nist_name->nid; + } + } + return 0; +} + #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) static int populate_groups(int* groups, int max_count, char *list) { @@ -35394,8 +37009,8 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) goto error; } - /* curve group */ - external->group = wolfSSL_EC_GROUP_new_by_curve_name(ECC_CURVE_DEF); + /* Group unknown at creation */ + external->group = wolfSSL_EC_GROUP_new_by_curve_name(NID_undef); if (external->group == NULL) { WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); goto error; @@ -35440,18 +37055,28 @@ void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) } } -#ifndef NO_WOLFSSL_STUB + +/* set the group in WOLFSSL_EC_KEY and return WOLFSSL_SUCCESS on success */ int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) { - (void)key; - (void)group; + if (key == NULL || group == NULL) + return WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); - WOLFSSL_STUB("EC_KEY_set_group"); - return -1; + if (key->group != NULL) { + /* free the current group */ + wolfSSL_EC_GROUP_free(key->group); + } + + key->group = wolfSSL_EC_GROUP_dup(group); + if (key->group == NULL) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; } -#endif + int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) { @@ -36548,11 +38173,12 @@ int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, mp_clear(&modulus); return WOLFSSL_FAILURE; } + + mp_clear(&modulus); } BN_copy(x, point->X); BN_copy(y, point->Y); - mp_clear(&modulus); return WOLFSSL_SUCCESS; } @@ -38536,7 +40162,10 @@ int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset) return WOLFSSL_FAILURE; } XMEMSET(rawKey, 0, rawLen); - mp_to_unsigned_bin(rsaElem, rawKey); + if (mp_to_unsigned_bin(rsaElem, rawKey) < 0) { + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } if ((word32)rawLen <= sizeof(word32)) { idx = *(word32*)rawKey; #ifdef BIG_ENDIAN_ORDER @@ -38564,7 +40193,10 @@ int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset) WOLFSSL_MSG("Memory error"); return WOLFSSL_FAILURE; } - mp_to_unsigned_bin(rsaElem, rawKey); + if (mp_to_unsigned_bin(rsaElem, rawKey) < 0) { + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } for (idx = 0; idx < (word32)rawLen; idx++) { char val[5]; int valSz = 5; @@ -39180,6 +40812,22 @@ int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data) return WOLFSSL_FAILURE; } +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_RSA_set_ex_data_with_cleanup( + WOLFSSL_RSA *rsa, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data_with_cleanup"); + if (rsa) { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&rsa->ex_data, idx, data, + cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e, WOLFSSL_BIGNUM *d) { @@ -40272,6 +41920,12 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) WOLFSSL_MSG("Serial size error"); return WOLFSSL_FAILURE; } + + if (serialSz > EXTERNAL_SERIAL_SIZE || + serialSz > CTC_SERIAL_SIZE) { + WOLFSSL_MSG("Serial size too large error"); + return WOLFSSL_FAILURE; + } XMEMCPY(cert->serial, serial, serialSz); cert->serialSz = serialSz; #else @@ -40728,7 +42382,364 @@ cleanup: return wolfSSL_X509_sign(x509, ctx->pctx->pkey, wolfSSL_EVP_MD_CTX_md(ctx)); } #endif /* OPENSSL_EXTRA */ + +/* Guarded by either + * A) WOLFSSL_WPAS_SMALL is on or + * B) (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_CERT_GEN + + * (WOLFSSL_CERT_REQ or WOLFSSL_CERT_EXT or OPENSSL_EXTRA) has been + * defined + */ +#if defined(WOLFSSL_WPAS_SMALL) || \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \ + defined(OPENSSL_EXTRA)) +/* Converts from NID_* value to wolfSSL value if needed */ +static int ConvertNIDToWolfSSL(int nid) +{ + switch (nid) { + case NID_commonName : return ASN_COMMON_NAME; + case NID_surname : return ASN_SUR_NAME; + case NID_countryName: return ASN_COUNTRY_NAME; + case NID_localityName: return ASN_LOCALITY_NAME; + case NID_stateOrProvinceName: return ASN_STATE_NAME; + case NID_organizationName: return ASN_ORG_NAME; + case NID_organizationalUnitName: return ASN_ORGUNIT_NAME; + case NID_emailAddress: return ASN_EMAIL_NAME; + case NID_serialNumber: return ASN_SERIAL_NUMBER; + case NID_businessCategory: return ASN_BUS_CAT; + case NID_domainComponent: return ASN_DOMAIN_COMPONENT; + default: + WOLFSSL_MSG("Attribute NID not found"); + return -1; + } +} + +#if defined(OPENSSL_ALL) +/* Convert ASN1 input string into canonical ASN1 string */ +/* , which has the following rules: */ +/* convert to UTF8 */ +/* convert to lower case */ +/* multi-spaces collapsed */ +/* @param asn_out a pointer to ASN1_STRING to be converted */ +/* @param asn_in a pointer to input ASN1_STRING */ +/* @return WOLFSSL_SUCCESS on successful converted, otherwise <=0 error code*/ +static int wolfSSL_ASN1_STRING_canon(WOLFSSL_ASN1_STRING* asn_out, + const WOLFSSL_ASN1_STRING* asn_in) +{ + char* dst; + char* src; + int i, len; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_canon"); + + /* sanity check */ + if (asn_out == NULL || asn_in == NULL) { + WOLFSSL_MSG("invalid function arguments"); + return BAD_FUNC_ARG; + } + + switch (asn_in->type) { + case MBSTRING_UTF8: + case V_ASN1_PRINTABLESTRING: + break; + default: + WOLFSSL_MSG("just copy string"); + return wolfSSL_ASN1_STRING_copy(asn_out, asn_in); + } + /* type is set as UTF8 */ + asn_out->type = MBSTRING_UTF8; + asn_out->length = wolfSSL_ASN1_STRING_to_UTF8( + (unsigned char**)&asn_out->data + , (WOLFSSL_ASN1_STRING*)asn_in); + + if (asn_out->length < 0) { + return WOLFSSL_FAILURE; + } + /* point to the last */ + dst = asn_out->data + asn_out->length; + /* point to the start */ + src = asn_out->data; + + len = asn_out->length; + + /* trimming spaces at the head and tail */ + dst--; + for (; (len > 0 && XISSPACE(*dst)); len--) { + dst--; + } + for (; (len > 0 && XISSPACE(*src)); len--) { + src++; + } + + /* point to the start */ + dst = asn_out->data; + + for (i = 0; i < len; dst++, i++) { + if (!XISASCII(*src)) { + /* keep non-ascii code */ + *dst = *src++; + } else if (XISSPACE(*src)) { + *dst = 0x20; /* space */ + /* remove the rest of spaces */ + while (XISSPACE(*++src) && i++ < len); + } else { + *dst = XTOLOWER(*src++); + } + } + /* put actual length */ + asn_out->length = (int)(dst - asn_out->data); + return WOLFSSL_SUCCESS; +} + +/* This is to convert the x509 name structure into canonical DER format */ +/* , which has the following rules: */ +/* convert to UTF8 */ +/* convert to lower case */ +/* multi-spaces collapsed */ +/* leading SEQUENCE hader is skipped */ +/* @param name a pointer to X509_NAME that is to be converted */ +/* @param out a pointer to conveted data */ +/* @return a number of converted bytes, otherwise <=0 error code */ +int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, unsigned char** out) +{ + int totalBytes = 0, i, idx; + byte *output, *local = NULL; +#ifdef WOLFSSL_SMALL_STACK + EncodedName* names = NULL; +#else + EncodedName names[MAX_NAME_ENTRIES]; +#endif + + if (out == NULL || name == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (names == NULL) + return MEMORY_E; +#endif + + XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES); + + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + WOLFSSL_X509_NAME_ENTRY* entry; + int ret; + + entry = wolfSSL_X509_NAME_get_entry(name, i); + if (entry != NULL && entry->set == 1) { + const char* nameStr; + WOLFSSL_ASN1_STRING* data; + WOLFSSL_ASN1_STRING* cano_data; + + cano_data = wolfSSL_ASN1_STRING_new(); + if (cano_data == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + data = wolfSSL_X509_NAME_ENTRY_get_data(entry); + if (data == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + wolfSSL_ASN1_STRING_free(cano_data); + WOLFSSL_MSG("Error getting entry data"); + return WOLFSSL_FATAL_ERROR; + } + if (wolfSSL_ASN1_STRING_canon(cano_data, data) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + nameStr = (const char*)wolfSSL_ASN1_STRING_data(cano_data); + + ret = wc_EncodeNameCanonical(&names[i], nameStr, CTC_UTF8, + ConvertNIDToWolfSSL(entry->nid)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + wolfSSL_ASN1_STRING_free(cano_data); + WOLFSSL_MSG("EncodeName failed"); + return WOLFSSL_FATAL_ERROR; + } + totalBytes += ret; + wolfSSL_OPENSSL_free(cano_data->data); + wolfSSL_ASN1_STRING_free(cano_data); + } + } + + /* skip header */ + /* check if using buffer passed in */ + if (*out == NULL) { + *out = local = (unsigned char*)XMALLOC(totalBytes, NULL, + DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + output = *out; + idx = 0; + + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + if (names[i].used) { + XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); + idx += names[i].totalLen; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* used existing buffer passed in, so increment pointer */ + if (local == NULL) { + *out += totalBytes; + } + return totalBytes; +} +#endif + +/* Converts the x509 name structure into DER format. + * + * out pointer to either a pre setup buffer or a pointer to null for + * creating a dynamic buffer. In the case that a pre-existing buffer is + * used out will be incremented the size of the DER buffer on success. + * + * returns the size of the buffer on success, or negative value with failure + */ +int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) +{ + int totalBytes = 0, i, idx; + byte temp[MAX_SEQ_SZ]; + byte *output, *local = NULL; +#ifdef WOLFSSL_SMALL_STACK + EncodedName* names = NULL; +#else + EncodedName names[MAX_NAME_ENTRIES]; +#endif + + if (out == NULL || name == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (names == NULL) + return MEMORY_E; +#endif + + XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES); + + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + WOLFSSL_X509_NAME_ENTRY* entry; + int ret; + + entry = wolfSSL_X509_NAME_get_entry(name, i); + if (entry != NULL && entry->set == 1) { + const char* nameStr; + int type; + WOLFSSL_ASN1_STRING* data; + + data = wolfSSL_X509_NAME_ENTRY_get_data(entry); + if (data == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + WOLFSSL_MSG("Error getting entry data"); + return WOLFSSL_FATAL_ERROR; + } + + nameStr = (const char*)wolfSSL_ASN1_STRING_data(data); + type = wolfSSL_ASN1_STRING_type(data); + + switch (type) { + case MBSTRING_UTF8: + type = CTC_UTF8; + break; + case V_ASN1_PRINTABLESTRING: + type = CTC_PRINTABLE; + break; + default: + WOLFSSL_MSG("Unknown encoding type conversion UTF8 by default"); + type = CTC_UTF8; + } + ret = wc_EncodeName(&names[i], nameStr, type, + ConvertNIDToWolfSSL(entry->nid)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + WOLFSSL_MSG("EncodeName failed"); + return WOLFSSL_FATAL_ERROR; + } + totalBytes += ret; + } + } + + /* header */ + idx = SetSequence(totalBytes, temp); + if (totalBytes + idx > ASN_NAME_MAX) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX"); + return BUFFER_E; + } + + /* check if using buffer passed in */ + if (*out == NULL) { + *out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL, + DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + + /* header */ + idx = SetSequence(totalBytes, temp); + if (totalBytes + idx > ASN_NAME_MAX) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX"); + return BUFFER_E; + } + + /* check if using buffer passed in */ + if (*out == NULL) { + *out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL, + DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + output = *out; + + idx = SetSequence(totalBytes, output); + totalBytes += idx; + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + if (names[i].used) { + XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); + idx += names[i].totalLen; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* used existing buffer passed in, so increment pointer */ + if (local == NULL) { + *out += totalBytes; + } + return totalBytes; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_X509_NAME *wolfSSL_d2i_X509_NAME(WOLFSSL_X509_NAME **name, @@ -40842,6 +42853,7 @@ cleanup: pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM); if (pem == NULL) return NULL; + XMEMSET(pem, 0, l); i = 0; if (wc_PemGetHeaderFooter(type, NULL, &footer) != 0) { @@ -41401,7 +43413,8 @@ err: #endif #endif /* !NO_BIO */ - int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, EncryptedInfo* cipher) + int wolfSSL_PEM_get_EVP_CIPHER_INFO(const char* header, + EncryptedInfo* cipher) { if (header == NULL || cipher == NULL) return WOLFSSL_FAILURE; @@ -41518,15 +43531,19 @@ err: * * returns WOLFSSL_SUCCESS on success */ - static int wolfSSL_X509_INFO_set(WOLFSSL_X509_INFO* info, + static int wolfSSL_X509_INFO_set(WOLFSSL_X509_INFO** info, WOLFSSL_X509* x509) { if (info == NULL || x509 == NULL) { return BAD_FUNC_ARG; } + if (*info == NULL) { + return BAD_FUNC_ARG; + } + /* check is fresh "info" passed in, if not free it */ - if (info->x509 != NULL || info->x_pkey != NULL) { + if ((*info)->x509 != NULL || (*info)->x_pkey != NULL) { WOLFSSL_X509_INFO* tmp; tmp = wolfSSL_X509_INFO_new(); @@ -41534,11 +43551,11 @@ err: WOLFSSL_MSG("Unable to create new structure"); return MEMORY_E; } - wolfSSL_X509_INFO_free(info); - info = tmp; + wolfSSL_X509_INFO_free(*info); + (*info) = tmp; } - info->x509 = x509; + (*info)->x509 = x509; //@TODO info->num //@TODO info->enc_cipher @@ -41546,8 +43563,8 @@ err: //@TODO info->enc_data //@TODO info->crl - info->x_pkey = wolfSSL_X509_PKEY_new(x509->heap); - return wolfSSL_X509_PKEY_set(info->x_pkey, x509); + (*info)->x_pkey = wolfSSL_X509_PKEY_new(x509->heap); + return wolfSSL_X509_PKEY_set((*info)->x_pkey, x509); } /** @@ -41573,7 +43590,9 @@ err: const char* headerEnd = NULL; const char* footer = NULL; const char* footerEnd = NULL; + #ifdef HAVE_CRL DerBuffer* der = NULL; + #endif (void)cb; @@ -41603,9 +43622,10 @@ err: /* Read the header and footer */ while (wolfSSL_BIO_read(bio, &pem[i], 1) == 1) { i++; - if (!header) + if (!header) { header = XSTRNSTR(pem, "-----BEGIN ", (unsigned int)i); - else if (header) { + } + else { if (!headerEnd) { headerEnd = XSTRNSTR(header + XSTR_SIZEOF("-----BEGIN "), "-----", @@ -41669,7 +43689,7 @@ err: goto err; } } -#ifdef HAVE_CRL + #ifdef HAVE_CRL else if (headerEnd - header == XSTR_SIZEOF("-----BEGIN X509 CRL-----") && XMEMCMP(header, "-----BEGIN X509 CRL-----", @@ -41687,7 +43707,7 @@ err: goto err; } } -#endif + #endif else { /* TODO support WOLFSSL_X509_PKEY as well */ WOLFSSL_MSG("Unsupported PEM structure"); @@ -41696,12 +43716,18 @@ err: } XFREE(pem, 0, DYNAMIC_TYPE_PEM); + #ifdef HAVE_CRL + if (der) + FreeDer(&der); + #endif return WOLFSSL_SUCCESS; err: if (pem) XFREE(pem, 0, DYNAMIC_TYPE_PEM); + #ifdef HAVE_CRL if (der) FreeDer(&der); + #endif return WOLFSSL_FAILURE; #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ } @@ -41742,7 +43768,7 @@ err: return NULL; } if (x509) { - ret = wolfSSL_X509_INFO_set(current, x509); + ret = wolfSSL_X509_INFO_set(¤t, x509); } else if (crl) { current->crl = crl; @@ -41857,8 +43883,10 @@ err: ne->object = wolfSSL_OBJ_nid2obj_ex(nid, ne->object); ne->value = wolfSSL_ASN1_STRING_type_new(type); if (ne->value != NULL) { - wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz); - ne->set = 1; + if (wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, + dataSz) == WOLFSSL_SUCCESS) { + ne->set = 1; + } } } @@ -41902,8 +43930,10 @@ err: ne->object = wolfSSL_OBJ_nid2obj_ex(nid, ne->object); ne->value = wolfSSL_ASN1_STRING_type_new(type); if (ne->value != NULL) { - wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz); - ne->set = 1; + if (wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz) + == WOLFSSL_SUCCESS) { + ne->set = 1; + } } return ne; @@ -42318,6 +44348,10 @@ err: const char* name = wolfSSL_OBJ_nid2ln(wolfSSL_OBJ_obj2nid(a)); #endif + if (name == NULL) { + WOLFSSL_MSG("Name not found"); + return WOLFSSL_FAILURE; + } if (XSTRLEN(name) + 1 < (word32)bufLen - 1) { bufSz = (int)XSTRLEN(name); } @@ -42432,6 +44466,53 @@ err: } #endif /* ! NO_SHA */ +#ifdef WOLFSSL_SHA224 + /* One shot SHA224 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA224_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA224(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA224_DIGEST_SIZE]; + byte* ret = md; + wc_Sha256 sha; + + WOLFSSL_ENTER("wolfSSL_SHA224"); + + if (wc_InitSha224_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA224 Init failed"); + return NULL; + } + + if (wc_Sha224Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA224 Update failed"); + return NULL; + } + + if (md == NULL) { + WOLFSSL_MSG("STATIC BUFFER BEING USED. wolfSSL_SHA224 IS NOT " + "THREAD SAFE WHEN md == NULL"); + ret = dig; + } + if (wc_Sha224Final(&sha, ret) != 0) { + WOLFSSL_MSG("SHA224 Final failed"); + wc_Sha224Free(&sha); + return NULL; + } + wc_Sha224Free(&sha); + + return ret; + } +#endif + #ifndef NO_SHA256 /* One shot SHA256 hash of message. * @@ -43137,9 +45218,62 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) #endif /* OPENSSL_EXTRA */ -#if ((defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && defined(HAVE_EX_DATA)) || \ - defined(FORTRESS) || \ - defined(WOLFSSL_WPAS_SMALL) +#if ((defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && defined(HAVE_EX_DATA) || \ + defined(FORTRESS) || defined(WOLFSSL_WPAS_SMALL) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) +/** + * get_ex_new_index is a helper function for the following + * xx_get_ex_new_index functions: + * - wolfSSL_CRYPTO_get_ex_new_index + * - wolfSSL_CTX_get_ex_new_index + * - wolfSSL_get_ex_new_index + * Issues a unique index number for the specified class-index. + * Returns an index number greater or equal to zero on success, + * -1 on failure. + */ +static int get_ex_new_index(int class_index) +{ + /* index counter for each class index*/ + static int ctx_idx = 0; + static int ssl_idx = 0; + static int x509_idx = 0; + + int index = -1; + + switch(class_index) { + case CRYPTO_EX_INDEX_SSL: + index = ssl_idx++; + break; + case CRYPTO_EX_INDEX_SSL_CTX: + index = ctx_idx++; + break; + case CRYPTO_EX_INDEX_X509: + index = x509_idx++; + break; + + /* following class indexes are not supoprted */ + case CRYPTO_EX_INDEX_SSL_SESSION: + case CRYPTO_EX_INDEX_X509_STORE: + case CRYPTO_EX_INDEX_X509_STORE_CTX: + case CRYPTO_EX_INDEX_DH: + case CRYPTO_EX_INDEX_DSA: + case CRYPTO_EX_INDEX_EC_KEY: + case CRYPTO_EX_INDEX_RSA: + case CRYPTO_EX_INDEX_ENGINE: + case CRYPTO_EX_INDEX_UI: + case CRYPTO_EX_INDEX_BIO: + case CRYPTO_EX_INDEX_APP: + case CRYPTO_EX_INDEX_UI_METHOD: + case CRYPTO_EX_INDEX_DRBG: + default: + break; + } + return index; +} +#endif /* HAVE_EX_DATA || FORTRESS */ + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) || defined(WOLFSSL_WPAS_SMALL) void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); @@ -43157,7 +45291,6 @@ void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, void* c) { - static int ctx_idx = 0; WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); (void)idx; @@ -43166,7 +45299,7 @@ int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, (void)b; (void)c; - return ctx_idx++; + return get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX); } /* Return the index that can be used for the WOLFSSL structure to store @@ -43177,7 +45310,6 @@ int wolfSSL_get_ex_new_index(long argValue, void* arg, WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2, WOLFSSL_CRYPTO_EX_free* cb3) { - static int ssl_idx = 0; WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); @@ -43187,7 +45319,7 @@ int wolfSSL_get_ex_new_index(long argValue, void* arg, (void)cb2; (void)cb3; - return ssl_idx++; + return get_ex_new_index(CRYPTO_EX_INDEX_SSL); } @@ -43207,7 +45339,24 @@ int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) return WOLFSSL_FAILURE; } -#endif /* ((OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) && HAVE_EX_DATA) || FORTRESS || WOLFSSL_WPAS_SMALL */ +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_CTX_set_ex_data_with_cleanup( + WOLFSSL_CTX* ctx, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data_with_cleanup"); + if (ctx != NULL) + { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, data, + cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + +#endif /* defined(HAVE_EX_DATA) || defined(FORTRESS) || defined(WOLFSSL_WPAS_SMALL) */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -43239,8 +45388,8 @@ int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) { #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(WOLFSSL_WPAS_SMALL) +#if defined(HAVE_EX_DATA) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL) int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) { @@ -43259,6 +45408,23 @@ int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) return WOLFSSL_FAILURE; } +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_set_ex_data_with_cleanup( + WOLFSSL* ssl, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_set_ex_data_with_cleanup"); + if (ssl != NULL) + { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ssl->ex_data, idx, data, + cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) { WOLFSSL_ENTER("wolfSSL_get_ex_data"); @@ -43677,274 +45843,7 @@ end: } #endif /* !NO_BIO */ -#ifndef NO_FILESYSTEM -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) -/* Convert DH key parameters to DER format, write to output (outSz) - * If output is NULL then max expected size is set to outSz and LENGTH_ONLY_E is - * returned. - * - * Note : static function due to redefinition complications with DhKey and FIPS - * version 2 build. - * - * return bytes written on success */ -int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz) -{ - word32 sz = 0, idx = 0; - int pSz = 0, gSz = 0, ret; - byte scratch[MAX_LENGTH_SZ]; - - if (key == NULL || outSz == NULL) { - return BAD_FUNC_ARG; - } - - pSz = mp_unsigned_bin_size(&key->p); - if (pSz < 0) { - return pSz; - } - if (mp_leading_bit(&key->p)) { - pSz++; - } - - gSz = mp_unsigned_bin_size(&key->g); - if (gSz < 0) { - return gSz; - } - if (mp_leading_bit(&key->g)) { - gSz++; - } - - sz = ASN_TAG_SZ; /* Integer */ - sz += SetLength(pSz, scratch); - sz += ASN_TAG_SZ; /* Integer */ - sz += SetLength(gSz, scratch); - sz += gSz + pSz; - - if (out == NULL) { - byte seqScratch[MAX_SEQ_SZ]; - - *outSz = sz + SetSequence(sz, seqScratch); - return LENGTH_ONLY_E; - } - - if (*outSz < MAX_SEQ_SZ || *outSz < sz) { - return BUFFER_E; - } - - idx += SetSequence(sz, out); - if (*outSz < idx + sz) { - return BUFFER_E; - } - - out[idx++] = ASN_INTEGER; - idx += SetLength(pSz, out + idx); - if (mp_leading_bit(&key->p)) { - out[idx++] = 0x00; - pSz -= 1; /* subtract 1 from size to account for leading 0 */ - } - ret = mp_to_unsigned_bin(&key->p, out + idx); - if (ret != MP_OKAY) { - return BUFFER_E; - } - idx += pSz; - - out[idx++] = ASN_INTEGER; - idx += SetLength(gSz, out + idx); - if (mp_leading_bit(&key->g)) { - out[idx++] = 0x00; - gSz -= 1; /* subtract 1 from size to account for leading 0 */ - } - ret = mp_to_unsigned_bin(&key->g, out + idx); - if (ret != MP_OKAY) { - return BUFFER_E; - } - idx += gSz; - return idx; -} - -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) -int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz) -{ - word32 sz = 0; - word32 paramSz = 0; - int ret; - int pubSz = 0; - int idx = 0; - byte scratch[MAX_ALGO_SZ]; - - /* Get size of entire key */ - - /* SEQUENCE <--| SetAlgoId - * OBJECT IDENTIFIER <--| - * SEQUENCE <-- - * INTEGER | wc_DhParamsToDer - * INTEGER <-- - */ - ret = wc_DhParamsToDer(key, NULL, ¶mSz); - if (ret != LENGTH_ONLY_E) - return ASN_PARSE_E; - sz += paramSz; - sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz); - - /* BIT STRING - * INTEGER - */ - pubSz = mp_unsigned_bin_size(&key->pub); - if (pubSz < 0) - return pubSz; - - if (mp_leading_bit(&key->pub)) - pubSz++; - - sz += ASN_TAG_SZ; /* Integer */ - sz += SetLength(pubSz, scratch); - sz += pubSz; - - sz += SetBitString(pubSz, 0, scratch); - - if (out == NULL) { - /* Uppermost SEQUENCE */ - *outSz = sz + SetSequence(sz, scratch); - return LENGTH_ONLY_E; - } - /* end get size of entire key */ - - /* Check for indexing errors */ - if (*outSz < MAX_SEQ_SZ || *outSz < sz) { - return BUFFER_E; - } - - /* Build Up Entire Key */ - - idx += SetSequence(sz, out); - - idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz); - ret = wc_DhParamsToDer(key, out+idx, ¶mSz); - if (ret < 0) - return ret; - idx += ret; - - /* BIT STRING - * INTEGER - */ - idx += SetBitString(pubSz, 0, out+idx); - - out[idx++] = ASN_INTEGER; - idx += SetLength(pubSz, out + idx); - if (mp_leading_bit(&key->pub)) { - out[idx++] = 0x00; - pubSz -= 1; /* subtract 1 from size to account for leading 0 */ - } - ret = mp_to_unsigned_bin(&key->pub, out + idx); - if (ret != MP_OKAY) { - return BUFFER_E; - } - idx += pubSz; - - return idx; -} - -int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz) -{ - word32 sz = 0; - word32 paramSz = 0; - int ret; - int privSz = 0; - int idx = 0; - byte scratch[MAX_ALGO_SZ]; - - /* Get size of entire key */ - - /* INTEGER 0 */ - sz += ASN_TAG_SZ; /* Integer */ - sz += SetLength(1, scratch); - sz += 1; - - /* SEQUENCE <--| SetAlgoId - * OBJECT IDENTIFIER <--| - * SEQUENCE <-- - * INTEGER | wc_DhParamsToDer - * INTEGER <-- - */ - ret = wc_DhParamsToDer(key, NULL, ¶mSz); - if (ret != LENGTH_ONLY_E) - return ASN_PARSE_E; - sz += paramSz; - sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz); - - /* OCTET STRING - * INTEGER - */ - privSz = mp_unsigned_bin_size(&key->priv); - if (privSz < 0) - return privSz; - else if (privSz > 256) /* Key is larger than 2048 */ - return ASN_VERSION_E; - - if (mp_leading_bit(&key->priv)) - privSz++; - - sz += ASN_TAG_SZ; /* Integer */ - sz += SetLength(privSz, scratch); - sz += privSz; - - sz += SetOctetString(privSz + ASN_OCTET_STRING, scratch); - - if (out == NULL) { - /* Uppermost SEQUENCE */ - *outSz = sz + SetSequence(sz, scratch); - return LENGTH_ONLY_E; - } - /* end get size of entire key */ - - /* Check for indexing errors */ - if (*outSz < MAX_SEQ_SZ || *outSz < sz) { - return BUFFER_E; - } - - /* Build Up Entire Key */ - - idx += SetSequence(sz, out); - - /* INTEGER 0 */ - out[idx++] = ASN_INTEGER; - idx += SetLength(1, out+idx); - out[idx++] = 0; - - idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz); - ret = wc_DhParamsToDer(key, out+idx, ¶mSz); - if (ret < 0) - return ret; - idx += ret; - - /* OCTET STRING - * INTEGER - */ - if (privSz == 256) { - idx += SetOctetString(privSz + ASN_OCTET_STRING, out+idx); - } else if (privSz == 128) { - idx += SetOctetString(privSz + ASN_OCTET_STRING-1, out+idx); - } else if (privSz == 64) { - idx += SetOctetString(privSz + ASN_OCTET_STRING-2, out+idx); - } else { - WOLFSSL_MSG("Unsupported key size"); - return ASN_VERSION_E; - } - - out[idx++] = ASN_INTEGER; - idx += SetLength(privSz, out + idx); - if (mp_leading_bit(&key->priv)) { - out[idx++] = 0x00; - privSz -= 1; /* subtract 1 from size to account for leading 0 */ - } - ret = mp_to_unsigned_bin(&key->priv, out + idx); - if (ret != MP_OKAY) { - return BUFFER_E; - } - idx += privSz; - - return idx; -} - +#if defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) /* Writes the DH parameters in PEM format from "dh" out to the file pointer * passed in. * @@ -44027,9 +45926,7 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh) WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", WOLFSSL_SUCCESS); return WOLFSSL_SUCCESS; } -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* WOLFSSL_QT || OPENSSL_ALL */ -#endif /* !NO_FILESYSTEM */ +#endif /* WOLFSSL_DH_EXTRA && !NO_FILESYSTEM */ #endif /* !NO_DH */ #ifndef NO_BIO @@ -44407,7 +46304,20 @@ long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) case SSL_CTRL_MODE: wolfSSL_CTX_set_mode(ctx,opt); break; - + case SSL_CTRL_SET_MIN_PROTO_VERSION: + WOLFSSL_MSG("set min proto version"); + if (opt == 0) { + /* do nothing */ + return WOLFSSL_SUCCESS; + } + return wolfSSL_CTX_set_min_proto_version(ctx, (int)opt); + case SSL_CTRL_SET_MAX_PROTO_VERSION: + WOLFSSL_MSG("set max proto version"); + if (opt == 0) { + /* do nothing */ + return WOLFSSL_SUCCESS; + } + return wolfSSL_CTX_set_max_proto_version(ctx, (int)opt); default: WOLFSSL_MSG("CTX_ctrl cmd not implemented"); ret = WOLFSSL_FAILURE; @@ -44554,6 +46464,7 @@ WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out) const byte* bioMemPt = bioMem; /* leave bioMem pointer unaltered */ if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMemPt, bioMemSz)) == NULL) { XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE((unsigned char*)maxKeyBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); return NULL; } @@ -44884,6 +46795,22 @@ int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) return WOLFSSL_FAILURE; } +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_SESSION_set_ex_data_with_cleanup( + WOLFSSL_SESSION* session, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data_with_cleanup"); + if(session != NULL) { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&session->ex_data, idx, + data, cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); @@ -44899,6 +46826,7 @@ void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) } #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || FORTRESS */ +/* Note: This is a huge section of API's - through wolfSSL_SESSION_print */ #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) @@ -45000,19 +46928,6 @@ int wolfSSL_FIPS_mode_set(int r) } #endif -#ifndef NO_WOLFSSL_STUB -int wolfSSL_RAND_set_rand_method(const void *meth) -{ - (void) meth; - WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); - WOLFSSL_STUB("RAND_set_rand_method"); - - /* if implemented RAND_bytes and RAND_pseudo_bytes need updated - * those two functions will call the respective functions from meth */ - return SSL_FAILURE; -} -#endif - int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) { int ret = WOLFSSL_FAILURE; @@ -45123,7 +47038,6 @@ void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) } } - int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk) { WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_num"); @@ -45562,7 +47476,7 @@ int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, #if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) int count = 0, len = 0, totalSz = 0, tmpSz = 0; char tmp[ASN_NAME_MAX+1]; - char fullName[ASN_NAME_MAX]; + char fullName[ASN_NAME_MAX+2]; const char *buf = NULL; WOLFSSL_X509_NAME_ENTRY* ne; WOLFSSL_ASN1_STRING* str; @@ -45656,7 +47570,7 @@ int wolfSSL_X509_NAME_print_ex_fp(XFILE file, WOLFSSL_X509_NAME* name, return ret; } -#endif +#endif /* NO_FILESYSTEM */ #ifndef NO_WOLFSSL_STUB WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) @@ -45825,18 +47739,7 @@ void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) } #endif - #ifndef NO_WOLFSSL_STUB -WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( - WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name) -{ - WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); - WOLFSSL_STUB("X509_STORE_get1_certs"); - (void)ctx; - (void)name; - return NULL; -} - WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( WOLFSSL_X509_STORE* store) { @@ -47093,7 +48996,10 @@ WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) } return suites->stack; } +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(HAVE_STUNNEL) #ifndef NO_WOLFSSL_STUB void wolfSSL_OPENSSL_config(char *config_name) { @@ -47101,14 +49007,13 @@ void wolfSSL_OPENSSL_config(char *config_name) WOLFSSL_STUB("OPENSSL_config"); } #endif /* !NO_WOLFSSL_STUB */ -#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_STUNNEL*/ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) { - static int x509_idx = 0; WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index"); (void)idx; @@ -47117,12 +49022,10 @@ int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) (void)b; (void)c; - return x509_idx++; + return get_ex_new_index(CRYPTO_EX_INDEX_X509); } #endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(WOLFSSL_WPAS_SMALL) #if defined(HAVE_EX_DATA) || defined(FORTRESS) void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx) { @@ -47143,6 +49046,13 @@ int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *d WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data"); #ifdef MAX_EX_DATA if (ex_data && idx < MAX_EX_DATA && idx >= 0) { +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + if (ex_data->ex_data_cleanup_routines[idx]) { + if (ex_data->ex_data[idx]) + ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]); + ex_data->ex_data_cleanup_routines[idx] = NULL; + } +#endif ex_data->ex_data[idx] = data; return WOLFSSL_SUCCESS; } @@ -47153,8 +49063,30 @@ int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *d #endif return WOLFSSL_FAILURE; } + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_CRYPTO_set_ex_data_with_cleanup( + WOLFSSL_CRYPTO_EX_DATA* ex_data, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data_with_cleanup"); + if (ex_data && idx < MAX_EX_DATA && idx >= 0) { + if (ex_data->ex_data_cleanup_routines[idx] && ex_data->ex_data[idx]) + ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]); + ex_data->ex_data[idx] = data; + ex_data->ex_data_cleanup_routines[idx] = cleanup_routine; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + #endif /* HAVE_EX_DATA || FORTRESS */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(WOLFSSL_WPAS_SMALL) void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) { WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); @@ -47184,6 +49116,24 @@ int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data) #endif return WOLFSSL_FAILURE; } + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_X509_set_ex_data_with_cleanup( + X509 *x509, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_ex_data_with_cleanup"); + if (x509 != NULL) + { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&x509->ex_data, idx, + data, cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */ @@ -47265,6 +49215,60 @@ int wolfSSL_X509_check_ip_asc(WOLFSSL_X509 *x, const char *ipasc, } #endif +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_GEN) +int wolfSSL_X509_check_email(WOLFSSL_X509 *x, const char *chk, size_t chkLen, + unsigned int flags) +{ + WOLFSSL_X509_NAME *subjName; + int emailLen; + char *emailBuf; + + (void)flags; + + WOLFSSL_ENTER("wolfSSL_X509_check_email"); + + if ((x == NULL) || (chk == NULL)) { + WOLFSSL_MSG("Invalid parameter"); + return WOLFSSL_FAILURE; + } + + subjName = wolfSSL_X509_get_subject_name(x); + if (subjName == NULL) + return WOLFSSL_FAILURE; + + /* Call with NULL buffer to get required length. */ + emailLen = wolfSSL_X509_NAME_get_text_by_NID(subjName, NID_emailAddress, + NULL, 0); + if (emailLen < 0) + return WOLFSSL_FAILURE; + + ++emailLen; /* Add 1 for the NUL. */ + + emailBuf = (char*)XMALLOC(emailLen, x->heap, DYNAMIC_TYPE_OPENSSL); + if (emailBuf == NULL) + return WOLFSSL_FAILURE; + + emailLen = wolfSSL_X509_NAME_get_text_by_NID(subjName, NID_emailAddress, + emailBuf, emailLen); + if (emailLen < 0) { + XFREE(emailBuf, x->heap, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_FAILURE; + } + + if (chkLen == 0) + chkLen = XSTRLEN(chk); + + if (chkLen != (size_t)emailLen + || XSTRNCMP(chk, emailBuf, chkLen)) { + XFREE(emailBuf, x->heap, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_FAILURE; + } + + XFREE(emailBuf, x->heap, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_SUCCESS; +} +#endif /* OPENSSL_EXTRA && WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) @@ -47394,7 +49398,11 @@ int wolfSSL_SSL_do_handshake(WOLFSSL *s) #endif } +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +int wolfSSL_SSL_in_init(const WOLFSSL *ssl) +#else int wolfSSL_SSL_in_init(WOLFSSL *ssl) +#endif { WOLFSSL_ENTER("SSL_in_init"); @@ -47470,7 +49478,7 @@ int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); asn1->isDynamic = 0; } - XMEMSET(asn1->intData, 0, sizeof(WOLFSSL_ASN1_INTEGER)); + XMEMSET(asn1->intData, 0, WOLFSSL_ASN1_INTEGER_MAX); asn1->data = asn1->intData; asn1->length = 0; asn1->negative = 0; @@ -47499,7 +49507,7 @@ int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, len = asn1->length + (lineLen/2); /* Check if it will fit in static memory and * save space for the ASN tag in front */ - if (len > (int)(sizeof(asn1->intData) - extraTagSz)) { + if (len > (int)(WOLFSSL_ASN1_INTEGER_MAX - extraTagSz)) { /* Allocate mem for data */ if (asn1->isDynamic) { byte* tmp = (byte*)XREALLOC(asn1->data, len + extraTagSz, NULL, @@ -47511,12 +49519,17 @@ int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, asn1->data = tmp; } else { + /* Up to this point asn1->data pointed to asn1->intData. + * Now that the size has grown larger than intData can handle + * the asn1 structure moves to a dynamic type with isDynamic + * flag being set and asn1->data being malloc'd. */ asn1->data = (byte*)XMALLOC(len + extraTagSz, NULL, DYNAMIC_TYPE_OPENSSL); if (!asn1->data) { WOLFSSL_MSG("malloc error"); return WOLFSSL_FAILURE; } + asn1->isDynamic = 1; XMEMCPY(asn1->data, asn1->intData, asn1->length); } } @@ -47558,8 +49571,7 @@ int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) /* Zero length integer is the value zero. */ if (len == 0) { - wolfSSL_BIO_write(bp, "00", 2); - return 2; + return wolfSSL_BIO_write(bp, "00", 2); } if (Base16_Encode(a->data + idx, len, buf, &bufLen) != 0 || @@ -47580,10 +49592,6 @@ int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) #define TICKET_KEY_CB_RET_OK 1 #define TICKET_KEY_CB_RET_RENEW 2 -/* The ticket key callback as used in OpenSSL is stored here. */ -static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, - WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL; - /* Implementation of session ticket encryption/decryption using OpenSSL * callback to initialize the cipher and HMAC. * @@ -47601,11 +49609,11 @@ static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, * WOLFSSL_TICKET_RET_FATAL on error. */ static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, - unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], - unsigned char iv[WOLFSSL_TICKET_IV_SZ], - unsigned char mac[WOLFSSL_TICKET_MAC_SZ], - int enc, unsigned char* encTicket, - int encTicketLen, int* encLen, void* ctx) + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) { byte digest[WC_MAX_DIGEST_SIZE]; WOLFSSL_EVP_CIPHER_CTX evpCtx; @@ -47617,14 +49625,25 @@ static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, (void)ctx; - if (ticketKeyCb == NULL) - return WOLFSSL_TICKET_RET_FATAL; + WOLFSSL_ENTER("wolfSSL_TicketKeyCb"); - wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); - /* Initialize the cipher and HMAC. */ - res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc); - if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) + if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketEncWrapCb == NULL) { + WOLFSSL_MSG("Bad parameter"); return WOLFSSL_TICKET_RET_FATAL; + } + + /* Initialize the cipher and HMAC. */ + wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); + if (wolfSSL_HMAC_CTX_Init(&hmacCtx) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init error"); + return WOLFSSL_TICKET_RET_FATAL; + } + res = ssl->ctx->ticketEncWrapCb(ssl, keyName, + iv, &evpCtx, &hmacCtx, enc); + if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) { + WOLFSSL_MSG("Ticket callback error"); + return WOLFSSL_TICKET_RET_FATAL; + } if (enc) { @@ -47683,16 +49702,14 @@ end: * cb The OpenSSL session ticket callback. * returns WOLFSSL_SUCCESS to indicate success. */ -int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( - WOLFSSL *ssl, unsigned char *name, unsigned char *iv, - WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, ticketCompatCb cb) { - /* Store callback in a global. */ - ticketKeyCb = cb; + /* Set the ticket encryption callback to be a wrapper around OpenSSL * callback. */ ctx->ticketEncCb = wolfSSL_TicketKeyCb; + ctx->ticketEncWrapCb = cb; return WOLFSSL_SUCCESS; } @@ -47829,7 +49846,8 @@ int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) { if (produced_tm == NULL) return BAD_FUNC_ARG; - if (ExtractDate(ssl->ocspProducedDate, ssl->ocspProducedDateFormat, produced_tm, &idx)) + if (ExtractDate(ssl->ocspProducedDate, + (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx)) return 0; else return ASN_PARSE_E; @@ -47924,16 +49942,77 @@ int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, return WOLFSSL_SUCCESS; } -int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, - WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) +/** + * Find the issuing cert of the input cert. On a self-signed cert this + * function will return an error. + * @param issuer The issuer x509 struct is returned here + * @param cm The cert manager that is queried for the issuer + * @param x This cert's issuer will be queried in cm + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on error + */ +static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, + WOLFSSL_X509 *x) { - WOLFSSL_STACK* node; Signer* ca = NULL; #ifdef WOLFSSL_SMALL_STACK DecodedCert* cert = NULL; #else DecodedCert cert[1]; #endif + /* sanity check */ + if (cm == NULL || x == NULL || x->derCert == NULL) + return WOLFSSL_FAILURE; + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return WOLFSSL_FAILURE; +#endif + + /* Use existing CA retrieval APIs that use DecodedCert. */ + InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0 + && !cert->selfSigned) { + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(cm, cert->issuerHash); + #endif /* NO SKID */ + } + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); +#endif + + if (ca == NULL) + return WOLFSSL_FAILURE; + +#ifdef WOLFSSL_SIGNER_DER_CERT + /* populate issuer with Signer DER */ + if (wolfSSL_X509_d2i(issuer, ca->derCert->buffer, + ca->derCert->length) == NULL) + return WOLFSSL_FAILURE; +#else + /* Create an empty certificate as CA doesn't have a certificate. */ + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return WOLFSSL_FAILURE; + + InitX509((*issuer), 1, NULL); +#endif + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) +{ + WOLFSSL_STACK* node; if (issuer == NULL || ctx == NULL || x == NULL) return WOLFSSL_FATAL_ERROR; @@ -47947,52 +50026,9 @@ int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, } } - -#ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return WOLFSSL_FAILURE; -#endif - - /* Use existing CA retrieval APIs that use DecodedCert. */ - InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); - if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { - #ifndef NO_SKID - if (cert->extAuthKeyIdSet) - ca = GetCA(ctx->store->cm, cert->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(ctx->store->cm, cert->issuerHash); - #else /* NO_SKID */ - ca = GetCA(ctx->store->cm, cert->issuerHash); - #endif /* NO SKID */ - } - FreeDecodedCert(cert); -#ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); -#endif - - if (ca == NULL) - return WOLFSSL_FAILURE; - -#ifdef WOLFSSL_SIGNER_DER_CERT - /* populate issuer with Signer DER */ - *issuer = wolfSSL_X509_d2i(issuer, ca->derCert->buffer, - ca->derCert->length); - if (*issuer == NULL) - return WOLFSSL_FAILURE; -#else - /* Create an empty certificate as CA doesn't have a certificate. */ - *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, - DYNAMIC_TYPE_OPENSSL); - if (*issuer == NULL) - return WOLFSSL_FAILURE; - - InitX509((*issuer), 1, NULL); -#endif - /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ - return WOLFSSL_SUCCESS; + return x509GetIssuerFromCM(issuer, ctx->store->cm, x); } void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk) @@ -48012,7 +50048,7 @@ WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) WOLFSSL_STACK* list = NULL; char* url; - if (x->authInfoSz == 0) + if (x == NULL || x->authInfoSz == 0) return NULL; list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1, @@ -48107,7 +50143,7 @@ WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) { WOLFSSL_ENTER("wolfSSL_X509_dup"); - if (x == NULL) { + if (x == NULL || x->derCert == NULL) { WOLFSSL_MSG("Error: NULL certificate passed in"); return NULL; } @@ -48278,7 +50314,7 @@ int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names) #endif } - if (curve > (sizeof(word32) * WOLFSSL_BIT_SIZE)) { + if (curve >= (sizeof(word32) * WOLFSSL_BIT_SIZE)) { /* shift left more than size of ctx->disabledCurves causes static * analysis report */ WOLFSSL_MSG("curve value is too large for upcoming shift"); @@ -49609,7 +51645,7 @@ int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, * rsa Key to use for encryption * padding Type of RSA padding to use. */ -int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, +int wolfSSL_RSA_private_encrypt(int len, const unsigned char* in, unsigned char* out, WOLFSSL_RSA* rsa, int padding) { int sz = 0; @@ -49626,7 +51662,14 @@ int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, return 0; } - if (padding != RSA_PKCS1_PADDING && padding != RSA_PKCS1_PSS_PADDING) { + if ( + #ifdef WC_RSA_PSS + padding != RSA_PKCS1_PSS_PADDING && + #endif + #ifdef WC_RSA_NO_PADDING + padding != RSA_NO_PADDING && + #endif + padding != RSA_PKCS1_PADDING) { WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding"); return 0; } @@ -49658,7 +51701,33 @@ int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, #endif /* size of output buffer must be size of RSA key */ - sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng); + switch (padding) { + case RSA_PKCS1_PADDING: + sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), + key, rng); + break; + #ifdef WC_RSA_PSS + case RSA_PKCS1_PSS_PADDING: + sz = wc_RsaPSS_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), + WC_HASH_TYPE_NONE, WC_MGF1NONE, key, rng); + break; + #endif + #ifdef WC_RSA_NO_PADDING + case RSA_NO_PADDING: + { + word32 outLen = (word32)len; + sz = wc_RsaFunction(in, (word32)len, out, &outLen, + RSA_PRIVATE_ENCRYPT, key, rng); + if (sz == 0) + sz = (int)outLen; + break; + } + #endif + default: + sz = BAD_FUNC_ARG; + break; + } + #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA) if (wc_FreeRng(rng) != 0) { WOLFSSL_MSG("Error freeing random number generator"); @@ -49990,6 +52059,9 @@ WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, return NULL; } } else { + /* This may be overly defensive */ + if (weOwn) + wolfSSL_BN_free(ret); return NULL; } @@ -50014,7 +52086,7 @@ int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) { int ret = 0; - int len = bits / 8; + int len; int initTmpRng = 0; WC_RNG* rng = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -50029,9 +52101,19 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) (void)bottom; WOLFSSL_MSG("wolfSSL_BN_rand"); + if (bits <= 0) { + return WOLFSSL_FAILURE; + } + + len = bits / 8; if (bits % 8) len++; + /* has to be a length of at least 1 since we set buf[0] and buf[len-1] */ + if (len < 1) { + return WOLFSSL_FAILURE; + } + #ifdef WOLFSSL_SMALL_STACK buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); @@ -50087,7 +52169,7 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) { int ret = 0; - int len = bits / 8; + int len; int initTmpRng = 0; WC_RNG* rng = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -50098,11 +52180,23 @@ int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) byte buff[1024]; #endif - WOLFSSL_MSG("wolfSSL_BN_rand"); + WOLFSSL_ENTER("wolfSSL_BN_pseudo_rand"); + if (bits <= 0) { + return WOLFSSL_FAILURE; + } + + len = bits / 8; if (bits % 8) len++; + /* has to be a length of at least 1 since we set buf[0] and buf[len-1] */ + if (top == 1 || top == 0 || bottom == 1) { + if (len < 1) { + return WOLFSSL_FAILURE; + } + } + #ifdef WOLFSSL_SMALL_STACK buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -50204,17 +52298,17 @@ int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n) if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - goto cleanup; + goto end; } if (mp_is_bit_set((mp_int*)bn->internal, n)) { #ifdef WOLFSSL_SMALL_STACK tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); if (tmp == NULL) { - goto cleanup; + goto end; } #endif if (mp_init(tmp) != MP_OKAY) { - goto cleanup; + goto end; } if (mp_set_bit(tmp, n) != MP_OKAY) { goto cleanup; @@ -50222,11 +52316,15 @@ int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n) if (mp_sub((mp_int*)bn->internal, tmp, (mp_int*)bn->internal) != MP_OKAY) { goto cleanup; } + } else { + goto end; } ret = WOLFSSL_SUCCESS; cleanup: mp_clear(tmp); + +end: #ifdef WOLFSSL_SMALL_STACK if (tmp) XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); @@ -50967,10 +53065,10 @@ int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, } str_len++; if (flags & ASN1_STRFLGS_DUMP_DER){ - hex_tmp[0] = hex_char[str->type >> 4]; - hex_tmp[1] = hex_char[str->type & 0xf]; - hex_tmp[2] = hex_char[str->length >> 4]; - hex_tmp[3] = hex_char[str->length & 0xf]; + hex_tmp[0] = hex_char[(str->type & 0xf0) >> 4]; + hex_tmp[1] = hex_char[(str->type & 0x0f)]; + hex_tmp[2] = hex_char[(str->length & 0xf0) >> 4]; + hex_tmp[3] = hex_char[(str->length & 0x0f)]; if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){ goto err_exit; } @@ -51075,7 +53173,7 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, ts = (struct tm *)XGMTIME(&t_adj, tmpTime); if (ts == NULL){ WOLFSSL_MSG("failed to get time data."); - XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); + wolfSSL_ASN1_TIME_free(s); return NULL; } @@ -51085,9 +53183,6 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, char utc_str[ASN_UTC_TIME_SIZE]; int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec; - s->type = V_ASN1_UTCTIME; - s->length = ASN_UTC_TIME_SIZE; - if (ts->tm_year >= 50 && ts->tm_year < 100){ utc_year = ts->tm_year; } else if (ts->tm_year >= 100 && ts->tm_year < 150){ @@ -51101,15 +53196,15 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, XSNPRINTF((char *)utc_str, sizeof(utc_str), "%02d%02d%02d%02d%02d%02dZ", utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec); - XMEMCPY(s->data, (byte *)utc_str, s->length); + if (wolfSSL_ASN1_TIME_set_string(s, utc_str) != WOLFSSL_SUCCESS) { + wolfSSL_ASN1_TIME_free(s); + return NULL; + } /* GeneralizedTime */ } else { char gt_str[ASN_GENERALIZED_TIME_MAX]; int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec; - s->type = V_ASN1_GENERALIZEDTIME; - s->length = ASN_GENERALIZED_TIME_SIZE; - gt_year = ts->tm_year + 1900; gt_mon = ts->tm_mon + 1; gt_day = ts->tm_mday; @@ -51119,7 +53214,10 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, XSNPRINTF((char *)gt_str, sizeof(gt_str), "%4d%02d%02d%02d%02d%02dZ", gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec); - XMEMCPY(s->data, (byte *)gt_str, s->length); + if (wolfSSL_ASN1_TIME_set_string(s, gt_str) != WOLFSSL_SUCCESS) { + wolfSSL_ASN1_TIME_free(s); + return NULL; + } } return s; @@ -51372,6 +53470,18 @@ int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) } return wc_RsaEncryptSize((RsaKey*)rsa->internal); } +/* return RSA modulus in bits */ +/* @param rsa a pointer to WOLFSSL_RSA structur */ +/* @return RSA modulus size in bits, 0 if error */ +int wolfSSL_RSA_bits(const WOLFSSL_RSA* rsa) +{ + WOLFSSL_ENTER("wolfSSL_RSA_bits"); + + if (rsa == NULL) + return WOLFSSL_FAILURE; + + return wolfSSL_BN_num_bits(rsa->n); +} #endif #if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \ @@ -51589,6 +53699,9 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) WOLFSSL_ENTER("wolfSSL_RSA_free"); if (rsa) { +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&rsa->ex_data); +#endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) int doFree = 0; if (wc_LockMutex(&rsa->refMutex) != 0) { @@ -51877,6 +53990,7 @@ PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7) pkcs7->len = ret; if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len) != 0) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); return NULL; } @@ -52297,14 +54411,18 @@ WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, int sectionLen = 0; int ret = -1; char* section = NULL; + char* canonLine = NULL; + char* canonSection = NULL; PKCS7* pkcs7 = NULL; word32 outLen = 0; byte* out = NULL; byte* outHead = NULL; + int canonPos = 0; int lineLen = 0; int remainLen = 0; byte isEnd = 0; + size_t canonSize = 0; size_t boundLen = 0; char* boundary = NULL; @@ -52329,8 +54447,7 @@ WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, goto error; } - section = (char*)XMALLOC((remainLen+1)*sizeof(char), NULL, - DYNAMIC_TYPE_PKCS7); + section = (char*)XMALLOC(remainLen+1, NULL, DYNAMIC_TYPE_PKCS7); if (section == NULL) { goto error; } @@ -52377,12 +54494,11 @@ WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, } boundLen = XSTRLEN(curParam->value) + 2; - boundary = (char*)XMALLOC((boundLen+1)*sizeof(char), NULL, - DYNAMIC_TYPE_PKCS7); + boundary = (char*)XMALLOC(boundLen+1, NULL, DYNAMIC_TYPE_PKCS7); if (boundary == NULL) { goto error; } - XMEMSET(boundary, 0, (word32)((boundLen+1)*sizeof(char))); + XMEMSET(boundary, 0, (word32)(boundLen+1)); boundary[0] = boundary[1] = '-'; XSTRNCPY(&boundary[2], curParam->value, boundLen-2); @@ -52404,41 +54520,80 @@ WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, section[0] = '\0'; sectionLen = 0; + canonSize = remainLen + 1; + canonSection = (char*)XMALLOC(canonSize, NULL, + DYNAMIC_TYPE_PKCS7); + if (canonSection == NULL) { + goto error; + } + lineLen = wolfSSL_BIO_gets(in, section, remainLen); while(XSTRNCMP(§ion[sectionLen], boundary, boundLen) && remainLen > 0) { + canonLine = wc_MIME_canonicalize(§ion[sectionLen]); + if (canonLine == NULL) { + goto error; + } + /* If line endings were added, the initial length may be + * exceeded. */ + if ((canonPos + XSTRLEN(canonLine) + 1) >= canonSize) { + canonSize = canonPos + XSTRLEN(canonLine) + 1; + canonSection = (char*)XREALLOC(canonSection, canonSize, + NULL, DYNAMIC_TYPE_PKCS7); + if (canonSection == NULL) { + goto error; + } + } + XMEMCPY(&canonSection[canonPos], canonLine, + (int)XSTRLEN(canonLine)); + canonPos += XSTRLEN(canonLine); + XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); + canonLine = NULL; + sectionLen += lineLen; remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], remainLen); if (lineLen <= 0) { goto error; } } - sectionLen--; + + if (canonPos > 0) { + canonPos--; + } + /* Strip the final trailing newline. Support \r, \n or \r\n. */ - if (section[sectionLen] == '\n') { - sectionLen--; - if (section[sectionLen] == '\r') { - sectionLen--; + if (canonSection[canonPos] == '\n') { + if (canonPos > 0) { + canonPos--; } } - else if (section[sectionLen] == '\r') { - sectionLen--; + + if (canonSection[canonPos] == '\r') { + if (canonPos > 0) { + canonPos--; + } } - section[sectionLen+1] = '\0'; + + canonSection[canonPos+1] = '\0'; *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); - ret = wolfSSL_BIO_write(*bcont, section, (int)XSTRLEN(section)); - if (ret != (int)XSTRLEN(section)) { + ret = wolfSSL_BIO_write(*bcont, canonSection, + (int)XSTRLEN(canonSection)); + if (ret != (int)XSTRLEN(canonSection)) { goto error; } if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem)) < 0) { goto error; } + XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); + canonSection = NULL; wc_MIME_free_hdrs(allHdrs); + allHdrs = NULL; section[0] = '\0'; sectionLen = 0; lineLen = wolfSSL_BIO_gets(in, section, remainLen); @@ -52492,6 +54647,7 @@ WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, } XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); + boundary = NULL; } } else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime, @@ -52534,8 +54690,8 @@ WOLFSSL_API PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, goto error; } /* Strip trailing newlines. */ - while ((section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n') && - sectionLen > 0) { + while ((sectionLen > 0) && + (section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n')) { sectionLen--; } section[sectionLen] = '\0'; @@ -52560,7 +54716,12 @@ error: XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); - wolfSSL_BIO_free(*bcont); + if (canonSection != NULL) + XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); + if (bcont) { + wolfSSL_BIO_free(*bcont); + *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */ + } return NULL; } @@ -52666,7 +54827,10 @@ int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, oidSz = 0; } - if (ret >= 0) { + #ifdef HAVE_ECC + if (ret >= 0) + #endif + { ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr, pkey->pkey_sz, algId, curveOid, oidSz); keySz = ret; @@ -52921,6 +55085,17 @@ int wolfSSL_X509_NAME_copy(WOLFSSL_X509_NAME* from, WOLFSSL_X509_NAME* to) return BAD_FUNC_ARG; } +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) + if (from->rawLen > 0) { + if (from->rawLen > ASN_NAME_MAX) { + WOLFSSL_MSG("Bad raw size"); + return BAD_FUNC_ARG; + } + XMEMCPY(to->raw, from->raw, from->rawLen); + to->rawLen = from->rawLen; + } +#endif + if (from->dynamicName) { to->name = (char*)XMALLOC(from->sz, to->heap, DYNAMIC_TYPE_SUBJECT_CN); if (to->name == NULL) @@ -53033,61 +55208,93 @@ int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s) int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) { byte* p = NULL; + int derSz = 0; WOLFSSL_ENTER("wolfSSL_X509_set_pubkey"); if (cert == NULL || pkey == NULL) return WOLFSSL_FAILURE; - if (pkey->type == EVP_PKEY_RSA -#ifndef NO_DSA - || pkey->type == EVP_PKEY_DSA -#endif /* !NO_DSA */ - ) { - p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (p == NULL) - return WOLFSSL_FAILURE; + /* Regenerate since pkey->pkey.ptr may contain private key */ + switch (pkey->type) { +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) + case EVP_PKEY_RSA: + { + RsaKey* rsa; - if (cert->pubKey.buffer != NULL) - XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); - cert->pubKey.buffer = p; - XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz); - cert->pubKey.length = pkey->pkey_sz; -#ifndef NO_DSA - if (pkey->type == EVP_PKEY_DSA) - cert->pubKeyOID = DSAk; - else -#endif /* !NO_DSA */ + if (pkey->rsa == NULL || pkey->rsa->internal == NULL) + return WOLFSSL_FAILURE; + + rsa = (RsaKey*)pkey->rsa->internal; + derSz = wc_RsaPublicKeyDerSize(rsa, 1); + if (derSz <= 0) + return WOLFSSL_FAILURE; + + p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL) + return WOLFSSL_FAILURE; + + if ((derSz = wc_RsaKeyToPublicDer(rsa, p, derSz)) <= 0) { + XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FAILURE; + } cert->pubKeyOID = RSAk; - } -#ifdef HAVE_ECC - else if (pkey->type == EVP_PKEY_EC) { - /* Generate since pkey->pkey.ptr may contain private key */ - ecc_key* ecc; - int derSz; - - if (pkey->ecc == NULL || pkey->ecc->internal == NULL) - return WOLFSSL_FAILURE; - - ecc = (ecc_key*)pkey->ecc->internal; - derSz = wc_EccPublicKeyDerSize(ecc, 1); - if (derSz <= 0) - return WOLFSSL_FAILURE; - - p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (p == NULL) - return WOLFSSL_FAILURE; - - if ((derSz = wc_EccPublicKeyToDer(ecc, p, derSz, 1)) <= 0) { - XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); - return WOLFSSL_FAILURE; } - cert->pubKey.buffer = p; - cert->pubKey.length = derSz; - cert->pubKeyOID = ECDSAk; - } -#endif /* HAVE_ECC */ - else + break; +#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA */ +#if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \ + defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA) + case EVP_PKEY_DSA: + { + DsaKey* dsa; + + if (pkey->dsa == NULL || pkey->dsa->internal == NULL) + return WOLFSSL_FAILURE; + + dsa = (DsaKey*)pkey->dsa->internal; + /* size of pub, priv, p, q, g + ASN.1 additional information */ + derSz = 5 * mp_unsigned_bin_size(&dsa->g) + MAX_ALGO_SZ; + p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL) + return WOLFSSL_FAILURE; + + if ((derSz = wc_DsaKeyToPublicDer(dsa, p, derSz)) <= 0) { + XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FAILURE; + } + cert->pubKeyOID = RSAk; + } + break; +#endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) && !NO_DSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + { + ecc_key* ecc; + + if (pkey->ecc == NULL || pkey->ecc->internal == NULL) + return WOLFSSL_FAILURE; + + ecc = (ecc_key*)pkey->ecc->internal; + derSz = wc_EccPublicKeyDerSize(ecc, 1); + if (derSz <= 0) + return WOLFSSL_FAILURE; + + p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL) + return WOLFSSL_FAILURE; + + if ((derSz = wc_EccPublicKeyToDer(ecc, p, derSz, 1)) <= 0) { + XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FAILURE; + } + cert->pubKeyOID = ECDSAk; + } + break; +#endif + default: return WOLFSSL_FAILURE; + } + cert->pubKey.buffer = p; + cert->pubKey.length = derSz; return WOLFSSL_SUCCESS; } @@ -53629,7 +55836,6 @@ int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, return SetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz, format, ctx->heap, NULL); } - int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, const char* key, unsigned int keySz, int format) { @@ -53641,6 +55847,726 @@ int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, ssl->heap, ssl->ctx); } +static int GetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo, + const unsigned char** key, unsigned int* keySz) +{ + int ret = 0; + DerBuffer* der = NULL; + + if (staticKE == NULL || key == NULL || keySz == NULL) { + return BAD_FUNC_ARG; + } + + *key = NULL; + *keySz = 0; + + switch (keyAlgo) { + #ifndef NO_DH + case WC_PK_TYPE_DH: + der = staticKE->dhKey; + break; + #endif + #ifdef HAVE_ECC + case WC_PK_TYPE_ECDH: + der = staticKE->ecKey; + break; + #endif + default: + /* not supported */ + ret = NOT_COMPILED_IN; + break; + } + + if (der) { + *key = der->buffer; + *keySz = der->length; + } + + return ret; +} + +/* returns pointer to currently loaded static ephemeral as ASN.1 */ +/* this can be converted to PEM using wc_DerToPem */ +int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const unsigned char** key, unsigned int* keySz) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + return GetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz); +} +int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const unsigned char** key, unsigned int* keySz) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + return GetStaticEphemeralKey(&ssl->staticKE, keyAlgo, key, keySz); +} + #endif /* WOLFSSL_STATIC_EPHEMERAL */ +#if defined(OPENSSL_EXTRA) +/* wolfSSL_THREADID_current is provided as a compat API with + * CRYPTO_THREADID_current to register current thread id into given id object. + * However, CRYPTO_THREADID_current API has been deprecated and no longer + * exists in the OpenSSL 1.0.0 or later.This API only works as a stub + * like as existing wolfSSL_THREADID_set_numeric. + */ +void wolfSSL_THREADID_current(WOLFSSL_CRYPTO_THREADID* id) +{ + (void)id; + return; +} +/* wolfSSL_THREADID_hash is provided as a compatible API with + * CRYPTO_THREADID_hash which returns a hash value calcurated from the + * specified thread id. However, CRYPTO_THREADID_hash API has been + * deprecated and no longer exists in the OpenSSL 1.0.0 or later. + * This API only works as a stub to returns 0. This behavior is + * equivalent to the latest OpenSSL CRYPTO_THREADID_hash. + */ +unsigned long wolfSSL_THREADID_hash(const WOLFSSL_CRYPTO_THREADID* id) +{ + (void)id; + return 0UL; +} +/* wolfSSL_CTX_set_ecdh_auto is provided as compatible API with + * SSL_CTX_set_ecdh_auto to enable auto ecdh curve selection functionality. + * Since this functionality is enabled by default in wolfSSL, + * this API exists as a stub. + */ +int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff) +{ + (void)ctx; + (void)onoff; + return WOLFSSL_SUCCESS; +} + +/** + * set security level (wolfSSL doesn't support security level) + * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @param level security level + */ +void wolfSSL_CTX_set_security_level(WOLFSSL_CTX* ctx, int level) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_security_level"); + (void)ctx; + (void)level; +} +/** + * get security level (wolfSSL doesn't support security level) + * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @return always 0(level 0) + */ +int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_security_level"); + (void)ctx; + return 0; +} + + +/** + * Determine whether a WOLFSSL_SESSION object can be used for resumption + * @param s a pointer to WOLFSSL_SESSION structure + * @return return 1 if session is resumable, otherwise 0. + */ +int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) +{ + if (s == NULL) + return 0; + + #ifdef HAVE_SESSION_TICKET + if (s->ticketLen > 0) + return 1; + #endif + + if (s->sessionIDSz > 0) + return 1; + + return 0; +} + + + +/** + * free allocated memory resouce + * @param str a pointer to resource to be freed + * @param file dummy argument + * @param line dummy argument + */ +void wolfSSL_CRYPTO_free(void *str, const char *file, int line) +{ + (void)file; + (void)line; + XFREE(str, 0, DYNAMIC_TYPE_TMP_BUFFER); +} +/** + * allocate memory with size of num + * @param num size of memory allocation to be malloced + * @param file dummy argument + * @param line dummy argument + * @return a pointer to allocated memory on succssesful, otherwise NULL + */ +void *wolfSSL_CRYPTO_malloc(size_t num, const char *file, int line) +{ + (void)file; + (void)line; + return XMALLOC(num, 0, DYNAMIC_TYPE_TMP_BUFFER); +} +/** + * Allocate WOLFSSL_CONF_CTX instance + * @return pointer to WOLFSSL_CONF_CTX structure on success and NULL on fail + */ +WOLFSSL_CONF_CTX* wolfSSL_CONF_CTX_new(void) +{ + WOLFSSL_CONF_CTX* cctx; + + WOLFSSL_ENTER("wolfSSL_CONF_CTX_new"); + + cctx = (WOLFSSL_CONF_CTX*)XMALLOC(sizeof(WOLFSSL_CONF_CTX), NULL, + DYNAMIC_TYPE_OPENSSL); + if (!cctx) { + WOLFSSL_MSG("malloc error"); + return NULL; + } + XMEMSET(cctx, 0, sizeof(WOLFSSL_CONF_CTX)); + + return cctx; +} +/** + * Release WOLFSSL_CONF_CTX instance + * @param cctx a pointer to WOLFSSL_CONF_CTX structure to be freed + * @return none + */ +void wolfSSL_CONF_CTX_free(WOLFSSL_CONF_CTX* cctx) +{ + WOLFSSL_ENTER("wolfSSL_CONF_CTX_free"); + + if (cctx) { + XFREE(cctx, NULL, DYNAMIC_TYPE_OPENSSL); + } + WOLFSSL_LEAVE("wolfSSL_CONF_CTX_free", 1); +} +/** + * Set WOLFSSL_CTX instance to WOLFSSL_CONF_CTX + * @param cctx a pointer to WOLFSSL_CONF_CTX structure to set a WOLFSSL_CTX + * pointer to its ctx + * @param ctx a pointer to WOLFSSL_CTX structure to be set + * @return none + */ +void wolfSSL_CONF_CTX_set_ssl_ctx(WOLFSSL_CONF_CTX* cctx, WOLFSSL_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_CONF_CTX_set_ssl_ctx"); + + /* sanity check */ + if (cctx == NULL) { + WOLFSSL_MSG("cctx is null"); + return; + } + + cctx->ctx = ctx; + WOLFSSL_LEAVE("wolfSSL_CONF_CTX_set_ssl_ctx", 1); +} +/** + * set flag value into WOLFSSL_CONF_CTX + * @param cctx a pointer to WOLFSSL_CONF_CTX structure to be set + * @param flags falg value to be OR'd + * @return OR'd flag value, otherwise 0 + */ +unsigned int wolfSSL_CONF_CTX_set_flags(WOLFSSL_CONF_CTX* cctx, + unsigned int flags) +{ + /* sanity check */ + if (cctx == NULL) + return 0; + + cctx->flags |= flags; + return cctx->flags; +} + +/** + * finish configuration command operation + * @param cctx a pointer to WOLFSSL_CONF_CTX structure to be set + * @return WOLFSSL_SUCCESS on success + */ +int wolfSSL_CONF_CTX_finish(WOLFSSL_CONF_CTX* cctx) +{ + (void)cctx; + return WOLFSSL_SUCCESS; +} +/* + * The following definitions and static functions are used for + * wolfSSL_CONF_cmd() to handle command. + * + * Definitions below are a part of conf_cmds_tbl[] contents. + * WOLFSSL_CONF_FILE_CMDx represents command name in configuration file + * WOLFSSL_CONF_CMDL_CMDx represents command name on command line + * + * The static functions after the definition section process + * those FILE or CMDL which are defined in the conf_cmds_tbl. + * + * To add a new command handling: + * 1. Add new #define to a section of WOLFSSL_CONF_FILE_CMD* and + * WOLFSSL_CONF_CMDL_CMD* + * 2. Add new static function after #define section, before + * "typedef struct conf_cmd_tbl {" line + * 3. Add new entry to conf_cmds_tbl[] by following other command entries + */ +#define WOLFSSL_CONF_FILE_CMD1 "Curves" +#define WOLFSSL_CONF_FILE_CMD2 "Certificate" +#define WOLFSSL_CONF_FILE_CMD3 "PrivateKey" +#define WOLFSSL_CONF_FILE_CMD4 "Protocol" +#define WOLFSSL_CONF_FILE_CMD5 "Options" +#define WOLFSSL_CONF_FILE_CMD6 "ServerInfoFile" +#define WOLFSSL_CONF_FILE_CMD7 "SignatureAlgorithms" +#define WOLFSSL_CONF_FILE_CMD8 "ClientSignatureAlgorithms" +#define WOLFSSL_CONF_FILE_CMD9 "CipherString" + +#define WOLFSSL_CONF_CMDL_CMD1 "curves" +#define WOLFSSL_CONF_CMDL_CMD2 "cert" +#define WOLFSSL_CONF_CMDL_CMD3 "key" +#define WOLFSSL_CONF_CMDL_CMD4 NULL +#define WOLFSSL_CONF_CMDL_CMD5 NULL +#define WOLFSSL_CONF_CMDL_CMD6 NULL +#define WOLFSSL_CONF_CMDL_CMD7 "sigalgs" +#define WOLFSSL_CONF_CMDL_CMD8 "client_sigalgs" +#define WOLFSSL_CONF_CMDL_CMD9 "cipher" + +#if !defined(NO_DH) && !defined(NO_BIO) +#define WOLFSSL_CONF_FILE_CMD10 "DHParameters" +#define WOLFSSL_CONF_CMDL_CMD10 "dhparam" +#endif + +#ifdef HAVE_ECC +#define WOLFSSL_CONF_FILE_CMD11 "ECDHParameters" +#define WOLFSSL_CONF_CMDL_CMD11 "named_curves" +#endif + +/** + * process Cipher String command + * @param cctx a pointer to WOLFSSL_CONF_CTX structure + * @param value arguments for cmd + * @return WOLFSSL_SUCCESS on success, + * otherwise WOLFSSL_FAILURE or + * -3 if value is null or + * negative value on other failure + */ +static int cmdfunc_cipherstring(WOLFSSL_CONF_CTX* cctx, const char* value) +{ + int ret = -3; + + WOLFSSL_ENTER("cmdfunc_cipherstring"); + + /* sanity check */ + if (cctx == NULL) + return WOLFSSL_FAILURE; + + if (value == NULL) { + WOLFSSL_MSG("bad arguments"); + return ret; + } + + if (cctx->ctx) { + ret = wolfSSL_CTX_set_cipher_list(cctx->ctx, value); + } + + if (((cctx->ctx && ret == WOLFSSL_SUCCESS) || + (!cctx->ctx && ret == -3)) && + cctx->ssl) { + ret = wolfSSL_set_cipher_list(cctx->ssl, value); + } + + WOLFSSL_LEAVE("cmdfunc_cipherstring", ret); + return ret; +} + +/** + * process curves command + * @param cctx a pointer to WOLFSSL_CONF_CTX structure + * @param value arguments for cmd + * @return WOLFSSL_SUCCESS on success, + * otherwise WOLFSSL_FAILURE or + * -3 if value is null or + * negative value on other failure + */ +#if defined(HAVE_ECC) +static int cmdfunc_curves(WOLFSSL_CONF_CTX* cctx, const char* value) +{ + int ret = -3; + + WOLFSSL_ENTER("cmdfunc_curves"); + + /* sanity check */ + if (cctx == NULL) + return WOLFSSL_FAILURE; + + if (value == NULL) { + WOLFSSL_MSG("bad arguments"); + return ret; + } + + if (cctx->ctx) { + ret = wolfSSL_CTX_set1_curves_list(cctx->ctx, value); + } + + if (((cctx->ctx && ret == WOLFSSL_SUCCESS) || + (!cctx->ctx && ret == -3)) && + cctx->ssl) { + ret = wolfSSL_set1_curves_list(cctx->ssl, value); + } + + WOLFSSL_LEAVE("cmdfunc_curves", ret); + return ret; +} +#endif + +#ifndef NO_FILESYSTEM +/** + * process cert command + * @param cctx a pointer to WOLFSSL_CONF_CTX structure + * @param value arguments for cmd + * @return WOLFSSL_SUCCESS on success, + * otherwise WOLFSSL_FAILURE or + * -3 if value is null or + * negative value on other failure + */ +static int cmdfunc_cert(WOLFSSL_CONF_CTX* cctx, const char* value) +{ + int ret = -3; + + WOLFSSL_ENTER("cmdfunc_cert"); + + /* sanity check */ + if (cctx == NULL) + return WOLFSSL_FAILURE; + + if (value == NULL) { + WOLFSSL_MSG("bad arguments"); + return ret; + } + + if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) { + WOLFSSL_MSG("certificate flag is not set"); + return -2; + } + + if (cctx->ctx) { + ret = wolfSSL_CTX_use_certificate_chain_file(cctx->ctx, value); + } + + if (((cctx->ctx && ret == WOLFSSL_SUCCESS) || + (!cctx->ctx && ret == -3)) && + cctx->ssl) { + ret = wolfSSL_use_certificate_file(cctx->ssl, value, + WOLFSSL_FILETYPE_PEM); + } + + WOLFSSL_LEAVE("cmdfunc_cert", ret); + return ret; +} +/** + * process key command + * @param cctx a pointer to WOLFSSL_CONF_CTX structure + * @param value arguments for cmd + * @return WOLFSSL_SUCCESS on success, + * otherwise WOLFSSL_FAILURE or + * -3 if value is null or + * negative value on other failure + */ +static int cmdfunc_key(WOLFSSL_CONF_CTX* cctx, const char* value) +{ + int ret = -3; + + WOLFSSL_ENTER("cmdfunc_key"); + + /* sanity check */ + if (cctx == NULL) + return WOLFSSL_FAILURE; + + if (value == NULL) { + WOLFSSL_MSG("bad arguments"); + return ret; + } + + if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) { + WOLFSSL_MSG("certificate flag is not set"); + return -2; + } + + if (cctx->ctx) { + ret = wolfSSL_CTX_use_PrivateKey_file(cctx->ctx, value, + WOLFSSL_FILETYPE_PEM); + } + + if (((cctx->ctx && ret == WOLFSSL_SUCCESS) || + (!cctx->ctx && ret == -3)) && + cctx->ssl) { + ret = wolfSSL_use_PrivateKey_file(cctx->ssl, value, + WOLFSSL_FILETYPE_PEM); + } + + WOLFSSL_LEAVE("cmdfunc_key", ret); + return ret; +} +#endif /* NO_FILESYSTEM */ +/** + * process DH parameter command + * @param cctx a pointer to WOLFSSL_CONF_CTX structure + * @param value arguments for cmd + * @return WOLFSSL_SUCCESS on success, + * otherwise WOLFSSL_FAILURE or + * -3 if value is null or + * negative value on other failure + */ +#if !defined(NO_DH) && !defined(NO_BIO) +static int cmdfunc_dhparam(WOLFSSL_CONF_CTX* cctx, const char* value) +{ + int ret = -3; + WOLFSSL_DH* dh = NULL; + WOLFSSL_BIO* bio = NULL; + + WOLFSSL_MSG("cmdfunc_dhparam"); + + /* sanity check */ + if (cctx == NULL) + return WOLFSSL_FAILURE; + + if (value == NULL) { + WOLFSSL_MSG("bad arguments"); + return ret; + } + + if (cctx->ctx || cctx->ssl) { + bio = wolfSSL_BIO_new_file(value, "rb"); + if (!bio) { + WOLFSSL_MSG("bio new file failed"); + return WOLFSSL_FAILURE; + } + dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + if (!dh) { + wolfSSL_BIO_free(bio); + WOLFSSL_MSG("PEM read bio failed"); + return WOLFSSL_FAILURE; + } + } else { + return 1; + } + + if (cctx->ctx) { + ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ctx, dh); + } + + if (((cctx->ctx && ret == WOLFSSL_SUCCESS) || + (!cctx->ctx && ret == -3)) && + cctx->ssl) { + ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ssl->ctx, dh); + } + + if (dh) + wolfSSL_DH_free(dh); + if (bio) + wolfSSL_BIO_free(bio); + + WOLFSSL_LEAVE("cmdfunc_dhparam", ret); + return ret; +} +#endif /* !NO_DH && !NO_BIO */ +/** + * command table + */ +typedef struct conf_cmd_tbl { + const char* file_cmd; + const char* cmdline_cmd; + word32 data_type; + int (*cmdfunc)(WOLFSSL_CONF_CTX* cctx, const char* value); +}conf_cmd_tbl; + +static const conf_cmd_tbl conf_cmds_tbl[] = { +#if defined(HAVE_ECC) + /* cmd Curves */ + {WOLFSSL_CONF_FILE_CMD1, WOLFSSL_CONF_CMDL_CMD1, + WOLFSSL_CONF_TYPE_STRING, cmdfunc_curves}, +#endif +#if !defined(NO_FILESYSTEM) + /* cmd Certificate */ + {WOLFSSL_CONF_FILE_CMD2, WOLFSSL_CONF_CMDL_CMD2, + WOLFSSL_CONF_TYPE_FILE, cmdfunc_cert}, + /* cmd PrivateKey */ + {WOLFSSL_CONF_FILE_CMD3, WOLFSSL_CONF_CMDL_CMD3, + WOLFSSL_CONF_TYPE_FILE, cmdfunc_key}, +#endif + /* cmd Protocol */ + {WOLFSSL_CONF_FILE_CMD4, WOLFSSL_CONF_CMDL_CMD4, + WOLFSSL_CONF_TYPE_STRING, NULL}, + /* cmd Options */ + {WOLFSSL_CONF_FILE_CMD5, WOLFSSL_CONF_CMDL_CMD5, + WOLFSSL_CONF_TYPE_STRING, NULL}, + /* cmd ServerInfoFile */ + {WOLFSSL_CONF_FILE_CMD6, WOLFSSL_CONF_CMDL_CMD6, + WOLFSSL_CONF_TYPE_FILE, NULL}, + /* cmd SignatureAlgorithms */ + {WOLFSSL_CONF_FILE_CMD7, WOLFSSL_CONF_CMDL_CMD7, + WOLFSSL_CONF_TYPE_STRING, NULL}, + /* cmd ClientSignatureAlgorithms */ + {WOLFSSL_CONF_FILE_CMD8, WOLFSSL_CONF_CMDL_CMD8, + WOLFSSL_CONF_TYPE_STRING, NULL}, + /* cmd CipherString */ + {WOLFSSL_CONF_FILE_CMD9, WOLFSSL_CONF_CMDL_CMD9, + WOLFSSL_CONF_TYPE_STRING, cmdfunc_cipherstring}, +#if !defined(NO_DH) && !defined(NO_BIO) + /* cmd DHParameters */ + {WOLFSSL_CONF_FILE_CMD10, WOLFSSL_CONF_CMDL_CMD10, + WOLFSSL_CONF_TYPE_FILE, cmdfunc_dhparam}, +#endif +#ifdef HAVE_ECC + /* cmd ECHDParameters */ + {WOLFSSL_CONF_FILE_CMD11, WOLFSSL_CONF_CMDL_CMD11, + WOLFSSL_CONF_TYPE_STRING, NULL}, +#endif +}; +/* size of command table */ +static const size_t size_of_cmd_tbls = sizeof(conf_cmds_tbl) + / sizeof(conf_cmd_tbl); + +/** + * send configuration command + * @param cctx a pointer to WOLFSSL_CONF_CTX structure + * @param cmd configuration command + * @param value arguments for cmd + * @return 1 when cmd is recognised, but value is not used + * 2 both cmd and value are used + * otherwise WOLFSSL_FAILURE + * -2 if cmd is not recognised + * -3 if value is NULL, but cmd is recognized + */ +int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value) +{ + int ret = WOLFSSL_FAILURE; + size_t i = 0; + size_t cmdlen = 0; + const char* c = NULL; + WOLFSSL_ENTER("wolfSSL_CONF_cmd"); + + (void)cctx; + (void)cmd; + (void)value; + + /* sanity check */ + if (cctx == NULL || cmd == NULL) { + WOLFSSL_MSG("bad arguments"); + return ret; + } + + if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) { + cmdlen = XSTRLEN(cmd); + + if (cmdlen < 2) { + WOLFSSL_MSG("bad cmdline command"); + return -2; + } + /* skip "-" prefix */ + c = ++cmd; + } + + for (i = 0; i < size_of_cmd_tbls; i++) { + /* check if the cmd is valid */ + if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) { + if (c != NULL && conf_cmds_tbl[i].cmdline_cmd != NULL && + XSTRCMP(c, conf_cmds_tbl[i].cmdline_cmd) == 0) { + if (conf_cmds_tbl[i].cmdfunc != NULL) { + ret = conf_cmds_tbl[i].cmdfunc(cctx, value); + break; + } else { + WOLFSSL_MSG("cmd not yet implemented"); + return -2; + } + } + } + + if (cctx->flags & WOLFSSL_CONF_FLAG_FILE) { + if (conf_cmds_tbl[i].file_cmd != NULL && + XSTRCMP(cmd, conf_cmds_tbl[i].file_cmd) == 0) { + if (conf_cmds_tbl[i].cmdfunc != NULL) { + ret = conf_cmds_tbl[i].cmdfunc(cctx, value); + break; + } else { + WOLFSSL_MSG("cmd not yet implemented"); + return -2; + } + } + } + } + + if (i == size_of_cmd_tbls) { + WOLFSSL_MSG("invalid command"); + ret = -2; + } + + /* return code compliant with OpenSSL */ + if (ret < -3) + ret = 0; + + WOLFSSL_LEAVE("wolfSSL_CONF_cmd", ret); + return ret; +} + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) +/** + * Issues unique index for the class specified by class_index. + * Other parameter except class_index are ignored. + * Currently, following class_index are accepted: + * - CRYPTO_EX_INDEX_SSL + * - CRYPTO_EX_INDEX_SSL_CTX + * - CRYPTO_EX_INDEX_X509 + * @param class index one of CRYPTO_EX_INDEX_xxx + * @param argp parameters to be saved + * @param argl parameters to be saved + * @param new_func a pointer to WOLFSSL_CRYPTO_EX_new + * @param dup_func a pointer to WOLFSSL_CRYPTO_EX_dup + * @param free_func a pointer to WOLFSSL_CRYPTO_EX_free + * @return index value grater or equal to zero on success, -1 on failure. + */ +int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + WOLFSSL_CRYPTO_EX_new* new_func, + WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func) +{ + WOLFSSL_ENTER("wolfSSL_CRYPTO_get_ex_new_index"); + (void)argl; + (void)argp; + (void)new_func; + (void)dup_func; + (void)free_func; + + return get_ex_new_index(class_index); +} +#endif /* HAVE_EX_DATA || FORTRESS */ + +/** + * Return DH p, q and g parameters + * @param dh a pointer to WOLFSSL_DH + * @param p a pointer to WOLFSSL_BIGNUM to be obtained from dh + * @param q a pointer to WOLFSSL_BIGNUM to be obtained from dh + * @param q a pointer to WOLFSSL_BIGNUM to be obtained from dh + */ +void wolfSSL_DH_get0_pqg(const WOLFSSL_DH *dh, const WOLFSSL_BIGNUM **p, + const WOLFSSL_BIGNUM **q, const WOLFSSL_BIGNUM **g) +{ + WOLFSSL_ENTER("wolfSSL_DH_get0_pqg"); + if (dh == NULL) + return; + + if (p != NULL) + *p = dh->p; + if (q != NULL) + *q = dh->q; + if (g != NULL) + *g = dh->g; +} + +#endif /* OPENSSL_EXTRA */ + #endif /* !WOLFCRYPT_ONLY */ diff --git a/src/tls.c b/src/tls.c index 0df44fc9b..15c762b9e 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1,6 +1,6 @@ /* tls.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -778,6 +778,9 @@ static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz) ret = wc_Sha512Update(&hmac->hash.sha512, data, sz); break; #endif /* WOLFSSL_SHA512 */ + + default: + break; } return ret; @@ -817,6 +820,9 @@ static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash) ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash); break; #endif /* WOLFSSL_SHA512 */ + + default: + break; } return ret; @@ -866,16 +872,17 @@ static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, word32 sz, byte* header) { - byte lenBytes[8]; - int i, j, k; - int blockBits, blockMask; - int lastBlockLen, macLen, extraLen, eocIndex; - int blocks, safeBlocks, lenBlock, eocBlock; - int maxLen; - int blockSz, padSz; - int ret; - word32 realLen; - byte extraBlock; + byte lenBytes[8]; + int i, j; + unsigned int k; + int blockBits, blockMask; + int lastBlockLen, macLen, extraLen, eocIndex; + int blocks, safeBlocks, lenBlock, eocBlock; + unsigned int maxLen; + int blockSz, padSz; + int ret; + word32 realLen; + byte extraBlock; switch (hmac->macType) { #ifndef NO_SHA @@ -972,7 +979,7 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, unsigned char isEocBlock = ctMaskEq(i, eocBlock); unsigned char isOutBlock = ctMaskEq(i, lenBlock); - for (j = 0; j < blockSz; j++, k++) { + for (j = 0; j < blockSz; j++) { unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock; unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock; unsigned char b = 0; @@ -981,6 +988,7 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, b = header[k]; else if (k < maxLen) b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ]; + k++; b = ctMaskSel(atEoc, 0x80, b); b &= (unsigned char)~(word32)pastEoc; @@ -1095,7 +1103,7 @@ static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in, blocks += ((maxSz + padSz) % blockSz) < padSz; msgBlocks = realSz >> blockBits; /* #Extra blocks to process. */ - blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz); + blocks -= (msgBlocks + (((realSz + padSz) % blockSz) < padSz)) ? 1 : 0; /* Calculate whole blocks. */ msgBlocks--; @@ -1306,7 +1314,7 @@ static WC_INLINE word16 TLSX_ToSemaphore(word16 type) ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8))) /** Creates a new extension. */ -static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) +static TLSX* TLSX_New(TLSX_Type type, const void* data, void* heap) { TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX); @@ -1314,7 +1322,7 @@ static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) if (extension) { extension->type = type; - extension->data = data; + extension->data = (void*)data; extension->resp = 0; extension->next = NULL; } @@ -1326,7 +1334,7 @@ static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) * Creates a new extension and pushes it to the provided list. * Checks for duplicate extensions, keeps the newest. */ -static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) +static int TLSX_Push(TLSX** list, TLSX_Type type, const void* data, void* heap) { TLSX* extension = TLSX_New(type, data, heap); @@ -1592,7 +1600,7 @@ static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size, /** Parses a buffer of ALPN extensions and set the first one matching * client and server requirements */ -static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, +static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length, byte isRequest) { word16 size = 0, offset = 0, idx = 0; @@ -1973,8 +1981,8 @@ byte TLSX_SNI_Status(TLSX* extensions, byte type) } /** Parses a buffer of SNI extensions. */ -static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) { #ifndef NO_WOLFSSL_SERVER word16 size = 0; @@ -2016,18 +2024,24 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, #ifndef NO_WOLFSSL_SERVER if (!extension || !extension->data) { - #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) - /* This will keep SNI even though TLSX_UseSNI has not been called. - * Enable it so that the received sni is available to functions - * that use a custom callback when SNI is received. - */ - + /* This will keep SNI even though TLSX_UseSNI has not been called. + * Enable it so that the received sni is available to functions + * that use a custom callback when SNI is received. + */ + #ifdef WOLFSSL_ALWAYS_KEEP_SNI + cacheOnly = 1; + #endif + if (ssl->ctx->sniRecvCb) { cacheOnly = 1; + } + + if (cacheOnly) { WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); - #else + } + else { /* Skipping, SNI not enabled at server side. */ return 0; - #endif + } } if (OPAQUE16_LEN > length) @@ -2088,7 +2102,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat); - if(!cacheOnly) + if (!cacheOnly) TLSX_SetResponse(ssl, TLSX_SERVER_NAME); } else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { @@ -2744,8 +2758,8 @@ static word16 TLSX_MFL_Write(byte* data, byte* output) return ENUM_LEN; } -static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_MFL_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) { if (length != ENUM_LEN) return BUFFER_ERROR; @@ -2830,8 +2844,8 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap) #ifdef HAVE_TRUNCATED_HMAC -static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_THM_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) { if (length != 0 || input == NULL) return BUFFER_ERROR; @@ -2976,8 +2990,8 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, return 0; } -static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) { int ret; #if !defined(NO_WOLFSSL_SERVER) @@ -3066,7 +3080,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, ret = BUFFER_ERROR; } if (ret == 0) { - csr->response.buffer = input + offset; + csr->response.buffer = (byte*)(input + offset); csr->response.length = resp_length; } @@ -3423,8 +3437,8 @@ static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, return 0; } -static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) { int ret; @@ -3868,51 +3882,68 @@ static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap) #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) +#if defined(HAVE_FFDHE) && (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) +static void TLSX_SupportedCurve_ValidateRequest(const WOLFSSL* ssl, + const byte* semaphore) +{ + /* If all pre-defined parameter types for key exchange are supported then + * always send SupportedGroups extension. + */ + (void)ssl; + (void)semaphore; +} +#else static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { word16 i; - for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { if (ssl->suites->suites[i] == TLS13_BYTE) return; - if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE) { + if ((ssl->suites->suites[i] == ECC_BYTE) || + (ssl->suites->suites[i] == CHACHA_BYTE)) { #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448) return; #endif } - else { #ifdef HAVE_FFDHE + else { return; - #endif } + #endif } /* turns semaphore on to avoid sending this extension. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); } +#endif +/* Only send PointFormats if TLSv13, ECC or CHACHA cipher suite present. + */ static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { word16 i; - for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { if (ssl->suites->suites[i] == TLS13_BYTE) return; - if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE) { + if ((ssl->suites->suites[i] == ECC_BYTE) || + (ssl->suites->suites[i] == CHACHA_BYTE)) { #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448) return; #endif } } - #ifdef HAVE_FFDHE - return; - #endif - /* turns semaphore on to avoid sending this extension. */ - TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +#ifdef HAVE_FFDHE + (void)semaphore; + return; +#else + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +#endif } #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ @@ -3928,23 +3959,15 @@ static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore) if (ssl->options.cipherSuite0 == TLS13_BYTE) return; +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) if (ssl->options.cipherSuite0 == ECC_BYTE || ssl->options.cipherSuite0 == CHACHA_BYTE) { -#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) return; -#endif } - else { -#ifdef HAVE_FFDHE - return; #endif - } -#if !defined(HAVE_FFDHE) || (!defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ - && !defined(HAVE_CURVE448)) /* turns semaphore on to avoid sending this extension. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); -#endif } #endif /* !NO_WOLFSSL_SERVER */ @@ -4015,8 +4038,8 @@ static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output) #if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) -static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte isRequest) { word16 offset; word16 name; @@ -4229,6 +4252,8 @@ int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) params = wc_Dh_ffdhe8192_Get(); break; #endif + default: + break; } if (params == NULL) return BAD_FUNC_ARG; @@ -4293,8 +4318,8 @@ int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported) #ifndef NO_WOLFSSL_SERVER -static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_PointFormat_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte isRequest) { int ret; @@ -4845,8 +4870,8 @@ static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, return offset; } -static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, - word16 length, byte isRequest) +static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte isRequest) { int ret = SECURE_RENEGOTIATION_E; @@ -4860,6 +4885,8 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, } if (ret != 0 && ret != SECURE_RENEGOTIATION_E) { } + else if (ssl->secure_renegotiation == NULL) { + } else if (!ssl->secure_renegotiation->enabled) { if (*input == 0) { input++; /* get past size */ @@ -5013,7 +5040,7 @@ static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) } } } -#endif /* WLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) @@ -5023,7 +5050,7 @@ static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) } static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output, - int isRequest) + int isRequest) { word16 offset = 0; /* empty ticket */ @@ -5036,8 +5063,8 @@ static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output, } -static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte isRequest) { int ret = 0; @@ -5108,8 +5135,10 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, WOLFSSL_MSG("Process client ticket rejected, bad TLS version"); ssl->options.rejectTicket = 1; ret = 0; /* not fatal */ - } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) { + } else if (ret == WOLFSSL_TICKET_RET_FATAL) { WOLFSSL_MSG("Process client ticket fatal error, not using"); + } else if (ret < 0) { + WOLFSSL_MSG("Process client ticket unknown error, not using"); } } } @@ -5247,7 +5276,7 @@ static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { int i; - for (i = 0; i < ssl->suites->suiteSz; i+= 2) + for (i = 0; i < ssl->suites->suiteSz; i += 2) if (ssl->suites->suites[i] == QSH_BYTE) return; @@ -5398,8 +5427,8 @@ static void TLSX_QSHAgreement(TLSX** extensions, void* heap) length length of total extension found isRequest set to 1 if being sent to the server */ -static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest) +static int TLSX_QSH_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) { byte numKeys = 0; word16 offset = 0; @@ -5564,7 +5593,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, /* Used for parsing in QSHCipher structs on Key Exchange */ int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, - byte isServer) + byte isServer) { QSHKey* key; word16 Max_Secret_Len = 48; @@ -5578,6 +5607,9 @@ int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte buff[145]; /* size enough for 3 secrets */ buffer* buf; + if (offset_len + OPAQUE24_LEN > length) + return BUFFER_ERROR; + /* pointer to location where secret should be stored */ if (isServer) { buf = ssl->QSH_secret->CliSi; @@ -5846,8 +5878,8 @@ static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType, * MEMORY_E when unable to allocate memory and * 0 otherwise. */ -static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte msgType) +static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte msgType) { int ret; @@ -6068,7 +6100,7 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, * msgType The type of the message this extension is being parsed from. * returns 0 on success, otherwise failure. */ -static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input, +static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType) { ProtocolVersion pv = ssl->ctx->method->version; @@ -6212,7 +6244,7 @@ static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, if (extensions == NULL || data == NULL) return BAD_FUNC_ARG; - return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap); + return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, data, heap); } #define SV_GET_SIZE TLSX_SupportedVersions_GetSize @@ -6294,8 +6326,8 @@ static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType, * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte msgType) +static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte msgType) { word16 len; word16 idx = 0; @@ -6343,7 +6375,7 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length, * resp Indicates the extension will go into a response (HelloRetryRequest). * returns 0 on success and other values indicate failure. */ -int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac, +int TLSX_Cookie_Use(WOLFSSL* ssl, const byte* data, word16 len, byte* mac, byte macSz, int resp) { int ret = 0; @@ -6424,8 +6456,8 @@ static word16 TLSX_SignatureAlgorithms_GetSize(void* data) * length The length of the list in bytes. * returns 0 on success, BUFFER_ERROR when the length is not even. */ -static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input, - word16 length) +static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, const byte* input, + word16 length) { word16 i; @@ -6474,7 +6506,7 @@ static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output) * length The length of the extension data. * returns 0 on success, otherwise failure. */ -static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, +static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, const byte* input, word16 length, byte isRequest, Suites* suites) { word16 len; @@ -6521,7 +6553,7 @@ static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, if (extensions == NULL) return BAD_FUNC_ARG; - return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap); + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, data, heap); } #define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize @@ -6569,7 +6601,7 @@ static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output) * length The length of the extension data. * returns 0 on success, otherwise failure. */ -static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input, +static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, const byte* input, word16 length, byte isRequest) { word16 len; @@ -6607,13 +6639,12 @@ static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input, * returns 0 on success, otherwise failure. */ static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data, - void* heap) + void* heap) { if (extensions == NULL) return BAD_FUNC_ARG; - return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data, - heap); + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, data, heap); } #define SAC_GET_SIZE TLSX_SignatureAlgorithmsCert_GetSize @@ -6636,18 +6667,11 @@ static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data, */ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; -#ifndef NO_DH - byte* keyData; - void* key = NULL; - word32 keySz; - word32 dataSz; - const DhParams* params; -#ifdef WOLFSSL_SMALL_STACK - DhKey* dhKey = NULL; -#else - DhKey dhKey[1]; -#endif + int ret = 0; +#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) + word32 keySz; + const DhParams* params = NULL; + DhKey* dhKey = (DhKey*)kse->key; /* TODO: [TLS13] The key size should come from wolfcrypt. */ /* Pick the parameters from the named group. */ @@ -6683,99 +6707,116 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) break; #endif default: - return BAD_FUNC_ARG; + break; } -#ifdef WOLFSSL_SMALL_STACK - dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); - if (dhKey == NULL) - return MEMORY_E; -#endif + if (params == NULL) + return BAD_FUNC_ARG; - ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif - return ret; - } - - /* Allocate space for the public key */ - dataSz = params->p_len; - keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - ret = MEMORY_E; - goto end; - } - /* Allocate space for the private key */ - key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (key == NULL) { - ret = MEMORY_E; - goto end; - } - - /* Set key */ - ret = wc_DhSetKey(dhKey, - (byte*)params->p, params->p_len, - (byte*)params->g, params->g_len); - if (ret != 0) - goto end; - -#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA) - if (ssl->staticKE.dhKey) { - DerBuffer* keyDer = ssl->staticKE.dhKey; - word32 idx = 0; - WOLFSSL_MSG("Using static DH key"); - ret = wc_DhKeyDecode(keyDer->buffer, &idx, dhKey, keyDer->length); - if (ret == 0) { - ret = wc_DhExportKeyPair(dhKey, (byte*)key, &keySz, keyData, &dataSz); - } - } - else -#endif - { - /* Generate a new key pair */ - ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData, - &dataSz); - #ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); - } - #endif - } - if (ret != 0) - goto end; - - if (params->p_len != dataSz) { - /* Zero pad the front of the public key to match prime "p" size */ - XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); - XMEMSET(keyData, 0, params->p_len - dataSz); - } - - kse->pubKey = keyData; kse->pubKeyLen = params->p_len; - kse->key = key; kse->keyLen = keySz; -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public DH Key"); - WOLFSSL_BUFFER(keyData, params->p_len); -#endif + /* Trigger Key Generation */ + if (kse->pubKey == NULL || kse->privKey == NULL) { + if (kse->key == NULL) { + kse->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, + DYNAMIC_TYPE_DH); + if (kse->key == NULL) + return MEMORY_E; -end: + /* Setup Key */ + ret = wc_InitDhKey_ex((DhKey*)kse->key, ssl->heap, ssl->devId); + if (ret == 0) { + dhKey = (DhKey*)kse->key; + ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, + params->g_len); + } + } - wc_FreeDhKey(dhKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); -#endif + /* Allocate space for the private and public key */ + if (ret == 0 && kse->pubKey == NULL) { + kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (kse->pubKey == NULL) + ret = MEMORY_E; + } + + if (ret == 0 && kse->privKey == NULL) { + kse->privKey = (byte*)XMALLOC(kse->keyLen, ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (kse->privKey == NULL) + ret = MEMORY_E; + } + + if (ret == 0) { + #if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA) + if (ssl->staticKE.dhKey) { + DerBuffer* keyDer = ssl->staticKE.dhKey; + word32 idx = 0; + WOLFSSL_MSG("Using static DH key"); + ret = wc_DhKeyDecode(keyDer->buffer, &idx, dhKey, keyDer->length); + if (ret == 0) { + ret = wc_DhExportKeyPair(dhKey, + (byte*)kse->privKey, &kse->keyLen, /* private */ + kse->pubKey, &kse->pubKeyLen /* public */ + ); + } + } + else + #endif + { + /* Generate a new key pair */ + /* For async this is called once and when event is done, the + * provided buffers will be populated. + * Final processing is zero pad below. */ + ret = DhGenKeyPair(ssl, dhKey, + (byte*)kse->privKey, &kse->keyLen, /* private */ + kse->pubKey, &kse->pubKeyLen /* public */ + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + } + } + + if (ret == 0) { + if (params->p_len != kse->pubKeyLen) { + /* Zero pad the front of the public key to match prime "p" size */ + XMEMMOVE(kse->pubKey + params->p_len - kse->pubKeyLen, kse->pubKey, + kse->pubKeyLen); + XMEMSET(kse->pubKey, 0, params->p_len - kse->pubKeyLen); + } + + kse->pubKeyLen = params->p_len; + + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public DH Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + #endif + } + + /* Always release the DH key to free up memory. + * The DhKey will be setup again in TLSX_KeyShare_ProcessDh */ + if (dhKey != NULL) + wc_FreeDhKey(dhKey); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_DH); + kse->key = NULL; + } if (ret != 0) { - /* Data owned by key share entry otherwise. */ - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (key != NULL) - XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + /* Cleanup on error, otherwise data owned by key share entry */ + if (kse->privKey != NULL) { + XFREE(kse->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->privKey = NULL; + } + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } } #else (void)ssl; @@ -6796,60 +6837,66 @@ end: */ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; + int ret = 0; #ifdef HAVE_CURVE25519 - byte* keyData = NULL; - word32 dataSize = CURVE25519_KEYSIZE; - curve25519_key* key; + curve25519_key* key = (curve25519_key*)kse->key; - /* Allocate an ECC key to hold private key. */ - key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, + if (kse->key == NULL) { + /* Allocate a Curve25519 key to hold private key. */ + kse->key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (key == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; + if (kse->key == NULL) { + WOLFSSL_MSG("GenX25519Key memory error"); + return MEMORY_E; + } + + /* Make an Curve25519 key. */ + ret = wc_curve25519_init((curve25519_key*)kse->key); + if (ret == 0) { + key = (curve25519_key*)kse->key; + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + } } - /* Make an ECC key. */ - ret = wc_curve25519_init(key); - if (ret != 0) - goto end; - ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); - if (ret != 0) - goto end; - - /* Allocate space for the public key. */ - keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap, + if (ret == 0 && kse->pubKey == NULL) { + /* Allocate space for the public key. */ + kse->pubKey = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - WOLFSSL_MSG("Key data Memory error"); - ret = MEMORY_E; - goto end; + if (kse->pubKey == NULL) { + WOLFSSL_MSG("GenX25519Key pub memory error"); + ret = MEMORY_E; + } } - /* Export public key. */ - if (wc_curve25519_export_public_ex(key, keyData, &dataSize, + if (ret == 0) { + /* Export Curve25519 public key. */ + kse->pubKeyLen = CURVE25519_KEYSIZE; + if (wc_curve25519_export_public_ex(key, kse->pubKey, &kse->pubKeyLen, EC25519_LITTLE_ENDIAN) != 0) { - ret = ECC_EXPORT_ERROR; - goto end; + ret = ECC_EXPORT_ERROR; + } + kse->pubKeyLen = CURVE25519_KEYSIZE; /* always CURVE25519_KEYSIZE */ } - kse->pubKey = keyData; - kse->pubKeyLen = CURVE25519_KEYSIZE; - kse->key = key; - #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public Curve25519 Key"); - WOLFSSL_BUFFER(keyData, dataSize); + if (ret == 0) { + WOLFSSL_MSG("Public Curve25519 Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + } #endif -end: if (ret != 0) { /* Data owned by key share entry otherwise. */ - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - wc_curve25519_free(key); - XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } + if (key != NULL) + wc_curve25519_free(key); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->key = NULL; + } } #else (void)ssl; @@ -6870,60 +6917,66 @@ end: */ static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; + int ret = 0; #ifdef HAVE_CURVE448 - byte* keyData = NULL; - word32 dataSize = CURVE448_KEY_SIZE; - curve448_key* key; + curve448_key* key = (curve448_key*)kse->key; - /* Allocate an ECC key to hold private key. */ - key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, + if (kse->key == NULL) { + /* Allocate a Curve448 key to hold private key. */ + kse->key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (key == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; + if (kse->key == NULL) { + WOLFSSL_MSG("GenX448Key memory error"); + return MEMORY_E; + } + + /* Make an Curve448 key. */ + ret = wc_curve448_init((curve448_key*)kse->key); + if (ret == 0) { + key = (curve448_key*)kse->key; + ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key); + } } - /* Make an ECC key. */ - ret = wc_curve448_init(key); - if (ret != 0) - goto end; - ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key); - if (ret != 0) - goto end; - - /* Allocate space for the public key. */ - keyData = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap, + if (ret == 0 && kse->pubKey == NULL) { + /* Allocate space for the public key. */ + kse->pubKey = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - WOLFSSL_MSG("Key data Memory error"); - ret = MEMORY_E; - goto end; + if (kse->pubKey == NULL) { + WOLFSSL_MSG("GenX448Key pub memory error"); + ret = MEMORY_E; + } } - /* Export public key. */ - if (wc_curve448_export_public_ex(key, keyData, &dataSize, + if (ret == 0) { + /* Export Curve448 public key. */ + kse->pubKeyLen = CURVE448_KEY_SIZE; + if (wc_curve448_export_public_ex(key, kse->pubKey, &kse->pubKeyLen, EC448_LITTLE_ENDIAN) != 0) { - ret = ECC_EXPORT_ERROR; - goto end; + ret = ECC_EXPORT_ERROR; + } + kse->pubKeyLen = CURVE448_KEY_SIZE; /* always CURVE448_KEY_SIZE */ } - - kse->pubKey = keyData; - kse->pubKeyLen = CURVE448_KEY_SIZE; - kse->key = key; - + #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public Curve448 Key"); - WOLFSSL_BUFFER(keyData, dataSize); + if (ret == 0) { + WOLFSSL_MSG("Public Curve448 Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + } #endif -end: if (ret != 0) { /* Data owned by key share entry otherwise. */ - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - wc_curve448_free(key); - XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } + if (key != NULL) + wc_curve448_free(key); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->key = NULL; + } } #else (void)ssl; @@ -6944,14 +6997,11 @@ end: */ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; + int ret = 0; #ifdef HAVE_ECC - byte* keyData = NULL; - word32 dataSize; - byte* keyPtr = NULL; - word32 keySize; - ecc_key* eccKey; - word16 curveId; + word32 keySize = 0; + word16 curveId = ECC_CURVE_INVALID; + ecc_key* eccKey = (ecc_key*)kse->key; /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ /* Translate named group to a curve id. */ @@ -6961,7 +7011,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) case WOLFSSL_ECC_SECP256R1: curveId = ECC_SECP256R1; keySize = 32; - dataSize = keySize * 2 + 1; break; #endif /* !NO_ECC_SECP */ #endif @@ -6970,7 +7019,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) case WOLFSSL_ECC_SECP384R1: curveId = ECC_SECP384R1; keySize = 48; - dataSize = keySize * 2 + 1; break; #endif /* !NO_ECC_SECP */ #endif @@ -6979,86 +7027,95 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) case WOLFSSL_ECC_SECP521R1: curveId = ECC_SECP521R1; keySize = 66; - dataSize = keySize * 2 + 1; break; #endif /* !NO_ECC_SECP */ - #endif - #if defined(HAVE_X448) && ECC_MIN_KEY_SZ <= 448 - case WOLFSSL_ECC_X448: - curveId = ECC_X448; - dataSize = keySize = 56; - break; #endif default: return BAD_FUNC_ARG; } - /* Allocate an ECC key to hold private key. */ - keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, + if (kse->key == NULL) { + kse->keyLen = keySize; + kse->pubKeyLen = keySize * 2 + 1; + + /* Allocate an ECC key to hold private key. */ + kse->key = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (keyPtr == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; - } - eccKey = (ecc_key*)keyPtr; - - /* Make an ECC key. */ - ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); - if (ret != 0) - goto end; - -#ifdef WOLFSSL_STATIC_EPHEMERAL - if (ssl->staticKE.ecKey) { - DerBuffer* keyDer = ssl->staticKE.ecKey; - word32 idx = 0; - WOLFSSL_MSG("Using static ECDH key"); - ret = wc_EccPrivateKeyDecode(keyDer->buffer, &idx, eccKey, keyDer->length); - } - else -#endif - { - /* Generate ephemeral ECC key */ - ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); - #ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (kse->key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; } - #endif - } - if (ret != 0) - goto end; - /* Allocate space for the public key. */ - keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - WOLFSSL_MSG("Key data Memory error"); - ret = MEMORY_E; - goto end; + /* Make an ECC key */ + ret = wc_ecc_init_ex((ecc_key*)kse->key, ssl->heap, ssl->devId); + if (ret == 0) { + eccKey = (ecc_key*)kse->key; + + #ifdef WOLFSSL_STATIC_EPHEMERAL + if (ssl->staticKE.ecKey) { + DerBuffer* keyDer = ssl->staticKE.ecKey; + word32 idx = 0; + WOLFSSL_MSG("Using static ECDH key"); + ret = wc_EccPrivateKeyDecode(keyDer->buffer, &idx, eccKey, + keyDer->length); + } + else + #endif + { + /* set curve info for EccMakeKey "peer" info */ + ret = wc_ecc_set_curve(eccKey, kse->keyLen, curveId); + if (ret == 0) { + /* Generate ephemeral ECC key */ + /* For async this is called once and when event is done, the + * provided buffers in key be populated. + * Final processing is x963 key export below. */ + ret = EccMakeKey(ssl, eccKey, eccKey); + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + } + } } - /* Export public key. */ - if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) { - ret = ECC_EXPORT_ERROR; - goto end; + if (ret == 0 && kse->pubKey == NULL) { + /* Allocate space for the public key */ + kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (kse->pubKey == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + } } - kse->pubKey = keyData; - kse->pubKeyLen = dataSize; - kse->key = keyPtr; + if (ret == 0) { + XMEMSET(kse->pubKey, 0, kse->pubKeyLen); + /* Export public key. */ + if (wc_ecc_export_x963(eccKey, kse->pubKey, &kse->pubKeyLen) != 0) { + ret = ECC_EXPORT_ERROR; + } + } #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public ECC Key"); - WOLFSSL_BUFFER(keyData, dataSize); + if (ret == 0) { + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + } #endif -end: if (ret != 0) { - /* Data owned by key share entry otherwise. */ - if (keyPtr != NULL) - XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + /* Cleanup on error, otherwise data owned by key share entry */ + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } + if (eccKey != NULL) + wc_ecc_free(eccKey); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->key = NULL; + } } #else (void)ssl; @@ -7077,14 +7134,20 @@ end: */ static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) { + int ret; /* Named FFHE groups have a bit set to identify them. */ if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK) - return TLSX_KeyShare_GenDhKey(ssl, kse); - if (kse->group == WOLFSSL_ECC_X25519) - return TLSX_KeyShare_GenX25519Key(ssl, kse); - if (kse->group == WOLFSSL_ECC_X448) - return TLSX_KeyShare_GenX448Key(ssl, kse); - return TLSX_KeyShare_GenEccKey(ssl, kse); + ret = TLSX_KeyShare_GenDhKey(ssl, kse); + else if (kse->group == WOLFSSL_ECC_X25519) + ret = TLSX_KeyShare_GenX25519Key(ssl, kse); + else if (kse->group == WOLFSSL_ECC_X448) + ret = TLSX_KeyShare_GenX448Key(ssl, kse); + else + ret = TLSX_KeyShare_GenEccKey(ssl, kse); +#ifdef WOLFSSL_ASYNC_CRYPT + kse->lastRet = ret; +#endif + return ret; } /* Free the key share dynamic data. @@ -7098,25 +7161,30 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) while ((current = list) != NULL) { list = current->next; - if ((current->group & NAMED_DH_MASK) == 0) { - if (current->group == WOLFSSL_ECC_X25519) { -#ifdef HAVE_CURVE25519 - wc_curve25519_free((curve25519_key*)current->key); + if ((current->group & NAMED_DH_MASK) == NAMED_DH_MASK) { +#ifndef NO_DH + wc_FreeDhKey((DhKey*)current->key); #endif - } - else if (current->group == WOLFSSL_ECC_X448) { -#ifdef HAVE_CURVE448 - wc_curve448_free((curve448_key*)current->key); -#endif - } - else { -#ifdef HAVE_ECC - wc_ecc_free((ecc_key*)(current->key)); -#endif - } } - if (current->key != NULL) - XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + else if (current->group == WOLFSSL_ECC_X25519) { +#ifdef HAVE_CURVE25519 + wc_curve25519_free((curve25519_key*)current->key); +#endif + } + else if (current->group == WOLFSSL_ECC_X448) { +#ifdef HAVE_CURVE448 + wc_curve448_free((curve448_key*)current->key); +#endif + } + else { +#ifdef HAVE_ECC + wc_ecc_free((ecc_key*)current->key); +#endif + } + XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + #if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) + XFREE(current->privKey, heap, DYNAMIC_TYPE_PRIVATE_KEY); + #endif XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(current, heap, DYNAMIC_TYPE_TLSX); @@ -7147,10 +7215,10 @@ static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) while ((current = list) != NULL) { list = current->next; - if (!isRequest && current->key == NULL) + if (!isRequest && current->pubKey == NULL) continue; - len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen; + len += (word16)(KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen); } return len; @@ -7184,7 +7252,7 @@ static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, while ((current = list) != NULL) { list = current->next; - if (!isRequest && current->key == NULL) + if (!isRequest && current->pubKey == NULL) continue; c16toa(current->group, &output[i]); @@ -7209,14 +7277,10 @@ static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, */ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) { -#ifndef NO_DH - int ret; - const DhParams* params; -#ifdef WOLFSSL_SMALL_STACK - DhKey* dhKey = NULL; -#else - DhKey dhKey[1]; -#endif + int ret = 0; +#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) + const DhParams* params = NULL; + DhKey* dhKey = (DhKey*)keyShareEntry->key; switch (keyShareEntry->group) { #ifdef HAVE_FFDHE_2048 @@ -7245,91 +7309,88 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) break; #endif default: - return PEER_KEY_ERROR; + break; } -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Peer DH Key"); - WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); -#endif - -#ifdef WOLFSSL_SMALL_STACK - dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); - if (dhKey == NULL) - return MEMORY_E; -#endif - - ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif - return ret; - } - - /* Set key */ - ret = wc_DhSetKey(dhKey, (byte*)params->p, params->p_len, (byte*)params->g, - params->g_len); - if (ret != 0) { - wc_FreeDhKey(dhKey); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif - return ret; - } - - ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen); - if (ret != 0) { - wc_FreeDhKey(dhKey); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif + if (params == NULL) return PEER_KEY_ERROR; + + /* if DhKey is not setup, do it now */ + if (keyShareEntry->key == NULL) { + keyShareEntry->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, + DYNAMIC_TYPE_DH); + if (keyShareEntry->key == NULL) + return MEMORY_E; + + /* Setup Key */ + ret = wc_InitDhKey_ex((DhKey*)keyShareEntry->key, ssl->heap, ssl->devId); + if (ret == 0) { + dhKey = (DhKey*)keyShareEntry->key; + ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, + params->g_len); + } } - /* Derive secret from private key and peer's public key. */ - ret = wc_DhAgree(dhKey, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, - (const byte*)keyShareEntry->key, keyShareEntry->keyLen, - keyShareEntry->ke, keyShareEntry->keLen); -#ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret == 0 + #ifdef WOLFSSL_ASYNC_CRYPT + && keyShareEntry->lastRet == 0 /* don't enter here if WC_PENDING_E */ + #endif + ) { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer DH Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); + #endif + + ssl->options.dhKeySz = (word16)params->p_len; + + /* Derive secret from private key and peer's public key. */ + ret = DhAgree(ssl, dhKey, + (const byte*)keyShareEntry->privKey, keyShareEntry->keyLen, /* our private */ + keyShareEntry->ke, keyShareEntry->keLen, /* peer's public key */ + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, /* secret */ + NULL, 0 + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } + #endif } -#endif + /* RFC 8446 Section 7.4.1: * ... left-padded with zeros up to the size of the prime. ... */ - if (params->p_len > ssl->arrays->preMasterSz) { - word32 diff = params->p_len - ssl->arrays->preMasterSz; + if (ret == 0 && (word32)ssl->options.dhKeySz > ssl->arrays->preMasterSz) { + word32 diff = (word32)ssl->options.dhKeySz - ssl->arrays->preMasterSz; XMEMMOVE(ssl->arrays->preMasterSecret + diff, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); XMEMSET(ssl->arrays->preMasterSecret, 0, diff); - ssl->arrays->preMasterSz = params->p_len; + ssl->arrays->preMasterSz = ssl->options.dhKeySz; } - ssl->options.dhKeySz = params->p_len; - - wc_FreeDhKey(dhKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); -#endif - if (keyShareEntry->key != NULL) { - XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + /* done with key share, release resources */ + if (dhKey) + wc_FreeDhKey(dhKey); + if (keyShareEntry->key) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_DH); keyShareEntry->key = NULL; } - XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - keyShareEntry->pubKey = NULL; + if (keyShareEntry->privKey != NULL) { + XFREE(keyShareEntry->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->privKey = NULL; + } + if (keyShareEntry->pubKey != NULL) { + XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->pubKey = NULL; + } XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); keyShareEntry->ke = NULL; - - return ret; #else (void)ssl; (void)keyShareEntry; - return PEER_KEY_ERROR; + ret = PEER_KEY_ERROR; #endif + return ret; } /* Process the X25519 key share extension on the client side. @@ -7493,24 +7554,10 @@ static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) */ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) { - int ret; - + int ret = 0; #ifdef HAVE_ECC - int curveId; - ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key; - - if (ssl->peerEccKey != NULL) - wc_ecc_free(ssl->peerEccKey); - - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - return MEMORY_ERROR; - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); - if (ret != 0) - return ret; + int curveId = ECC_CURVE_INVALID; + ecc_key* eccKey = (ecc_key*)keyShareEntry->key; /* find supported curve */ switch (keyShareEntry->group) { @@ -7544,55 +7591,73 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) /* unsupported curve */ return ECC_PEERKEY_ERROR; } - -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Peer ECC Key"); - WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (keyShareEntry->lastRet == 0) /* don't enter here if WC_PENDING_E */ #endif - - /* Point is validated by import function. */ - if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, - ssl->peerEccKey, curveId) != 0) { - return ECC_PEERKEY_ERROR; - } - ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; - -#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ - (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ - !defined(HAVE_SELFTEST) - ret = wc_ecc_set_rng(keyShareKey, ssl->rng); - if (ret != 0) { - return ret; - } -#endif - - do { - #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); #endif - if (ret >= 0) - ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); - } while (ret == WC_PENDING_E); -#if 0 - /* TODO: Switch to support async here and use: */ - ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey, - keyShareEntry->ke, &keyShareEntry->keLen, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, - ssl->options.side - ); -#endif + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + } - wc_ecc_free(ssl->peerEccKey); - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccKey = NULL; - wc_ecc_free((ecc_key*)(keyShareEntry->key)); - if (keyShareEntry->key != NULL) { - XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + ret = MEMORY_ERROR; + } + + if (ret == 0) { + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + } + + /* Point is validated by import function. */ + if (ret == 0) { + ret = wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, + ssl->peerEccKey, curveId); + if (ret != 0) { + ret = ECC_PEERKEY_ERROR; + } + } + + if (ret == 0) { + ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; + } + } + + if (ret == 0 && eccKey == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0) { + ret = EccSharedSecret(ssl, eccKey, ssl->peerEccKey, + keyShareEntry->ke, &keyShareEntry->keLen, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + ssl->options.side + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + } + + /* done with key share, release resources */ + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = NULL; + } + if (keyShareEntry->key) { + wc_ecc_free((ecc_key*)keyShareEntry->key); + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_ECC); keyShareEntry->key = NULL; } - + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; #else (void)ssl; (void)keyShareEntry; @@ -7627,8 +7692,13 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("KE Secret"); - WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + if (ret == 0) { + WOLFSSL_MSG("KE Secret"); + WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + } +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + keyShareEntry->lastRet = ret; #endif return ret; @@ -7643,8 +7713,8 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) * returns a positive number to indicate amount of data parsed and a negative * number on error. */ -static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length, - KeyShareEntry **kse) +static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, const byte* input, + word16 length, KeyShareEntry **kse) { int ret; word16 group; @@ -7753,7 +7823,7 @@ static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, +static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType) { int ret; @@ -7784,8 +7854,9 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, offset += OPAQUE16_LEN; while (offset < (int)length) { - ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset, - &keyShareEntry); + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], + length - (word16)offset, + &keyShareEntry); if (ret < 0) return ret; @@ -7817,8 +7888,13 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, return BUFFER_ERROR; /* Not in list sent if there isn't a private key. */ - if (keyShareEntry == NULL || keyShareEntry->key == NULL) + if (keyShareEntry == NULL || (keyShareEntry->key == NULL + #ifndef NO_DH + && keyShareEntry->privKey == NULL + #endif + )) { return BAD_KEY_SHARE_DATA; + } /* Process the entry to calculate the secret. */ ret = TLSX_KeyShare_Process(ssl, keyShareEntry); @@ -7832,18 +7908,24 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, /* The data is the named group the server wants to use. */ ato16(input, &group); - /* Check the selected group was supported by ClientHello extensions. */ - if (!TLSX_SupportedGroups_Find(ssl, group)) - return BAD_KEY_SHARE_DATA; + #ifdef WOLFSSL_ASYNC_CRYPT + /* only perform find and clear TLSX if not returning from async */ + if (ssl->error != WC_PENDING_E) + #endif + { + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; - /* Check if the group was sent. */ - if (TLSX_KeyShare_Find(ssl, group)) - return BAD_KEY_SHARE_DATA; + /* Check if the group was sent. */ + if (TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; - /* Clear out unusable key shares. */ - ret = TLSX_KeyShare_Empty(ssl); - if (ret != 0) - return ret; + /* Clear out unusable key shares. */ + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + } /* Try to use the server's group. */ ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); @@ -8150,13 +8232,20 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) /* Delete the old key share data list. */ extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension != NULL) { - TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); - extension->data = NULL; + KeyShareEntry* kse = (KeyShareEntry*)extension->data; + #ifdef WOLFSSL_ASYNC_CRYPT + /* for async don't free, call `TLSX_KeyShare_Use` again */ + if (kse && kse->lastRet != WC_PENDING_E) + #endif + { + TLSX_KeyShare_FreeAll(kse, ssl->heap); + extension->data = NULL; + } } /* Add in the chosen group. */ ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); - if (ret != 0) + if (ret != 0 && ret != WC_PENDING_E) return ret; /* Set extension to be in response. */ @@ -8174,9 +8263,10 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) /* Ensure there is a key pair that can be used for key exchange. * * ssl The SSL/TLS object. + * doHelloRetry If set to non-zero will do hello_retry * returns 0 on success and other values indicate failure. */ -int TLSX_KeyShare_Establish(WOLFSSL *ssl) +int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) { int ret; TLSX* extension; @@ -8192,8 +8282,19 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) if (extension != NULL) list = (KeyShareEntry*)extension->data; - if (extension && extension->resp == 1) - return 0; + if (extension && extension->resp == 1) { + ret = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + /* in async case make sure key generation is finalized */ + serverKSE = (KeyShareEntry*)extension->data; + if (serverKSE->lastRet == WC_PENDING_E) { + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) + *doHelloRetry = 1; + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + } + #endif + return ret; + } /* Use server's preference order. */ for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { @@ -8230,11 +8331,9 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) /* No supported group found - send HelloRetryRequest. */ if (clientKSE == NULL) { - ret = TLSX_KeyShare_SetSupported(ssl); - /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ - if (ret == 0) - return KEY_SHARE_ERROR; - return ret; + /* Set KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + *doHelloRetry = 1; + return TLSX_KeyShare_SetSupported(ssl); } list = NULL; @@ -8245,16 +8344,27 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) if (clientKSE->key == NULL) { ret = TLSX_KeyShare_GenKey(ssl, serverKSE); - if (ret != 0) + /* for async do setup of serverKSE below, but return WC_PENDING_E */ + if (ret != 0 + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { return ret; + } } else { + /* transfer buffers to serverKSE */ serverKSE->key = clientKSE->key; + clientKSE->key = NULL; serverKSE->keyLen = clientKSE->keyLen; serverKSE->pubKey = clientKSE->pubKey; - serverKSE->pubKeyLen = clientKSE->pubKeyLen; - clientKSE->key = NULL; clientKSE->pubKey = NULL; + serverKSE->pubKeyLen = clientKSE->pubKeyLen; + #ifndef NO_DH + serverKSE->privKey = clientKSE->privKey; + clientKSE->privKey = NULL; + #endif } serverKSE->ke = clientKSE->ke; serverKSE->keLen = clientKSE->keLen; @@ -8266,7 +8376,7 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) extension->resp = 1; - return 0; + return ret; } /* Derive the shared secret of the key exchange. @@ -8280,6 +8390,14 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) TLSX* extension; KeyShareEntry* list = NULL; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, NULL); + /* Check for error */ + if (ret != WC_NOT_PENDING_E && ret < 0) { + return ret; + } +#endif + /* Find the KeyShare extension if it exists. */ extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension != NULL) @@ -8290,8 +8408,6 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) /* Calculate secret. */ ret = TLSX_KeyShare_Process(ssl, list); - if (ret != 0) - return ret; return ret; } @@ -8349,7 +8465,7 @@ static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType, while (list != NULL) { /* Each entry has: identity, ticket age and binder. */ len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN + - OPAQUE8_LEN + list->binderLen; + OPAQUE8_LEN + (word16)list->binderLen; list = list->next; } *pSz += len; @@ -8382,7 +8498,7 @@ int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType, /* Length of all binders. */ len = OPAQUE16_LEN; while (list != NULL) { - len += OPAQUE8_LEN + list->binderLen; + len += OPAQUE8_LEN + (word16)list->binderLen; list = list->next; } @@ -8414,10 +8530,10 @@ int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, idx += OPAQUE16_LEN; while (current != NULL) { /* Binder data length. */ - output[idx++] = current->binderLen; + output[idx++] = (byte)current->binderLen; /* Binder data. */ XMEMCPY(output + idx, current->binder, current->binderLen); - idx += current->binderLen; + idx += (word16)current->binderLen; current = current->next; } @@ -8508,8 +8624,8 @@ static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte msgType) +static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte msgType) { TLSX* extension; PreSharedKey* list; @@ -8533,9 +8649,9 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, /* Create a pre-shared key object for each identity. */ while (len > 0) { - byte* identity; - word16 identityLen; - word32 age; + const byte* identity; + word16 identityLen; + word32 age; if (len < OPAQUE16_LEN) return BUFFER_E; @@ -8588,10 +8704,10 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, /* Copy binder into static buffer. */ XMEMCPY(list->binder, input + idx, list->binderLen); - idx += list->binderLen; + idx += (word16)list->binderLen; /* Done with binder entry. */ - len -= OPAQUE8_LEN + list->binderLen; + len -= OPAQUE8_LEN + (word16)list->binderLen; /* Next identity. */ list = list->next; @@ -8654,7 +8770,7 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, * preSharedKey The new pre-shared key object. * returns 0 on success and other values indicate failure. */ -static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity, +static int TLSX_PreSharedKey_New(PreSharedKey** list, const byte* identity, word16 len, void *heap, PreSharedKey** preSharedKey) { @@ -8721,8 +8837,8 @@ static WC_INLINE byte GetHmacLength(int hmac) * preSharedKey The new pre-shared key object. * returns 0 on success and other values indicate failure. */ -int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age, - byte hmac, byte cipherSuite0, +int TLSX_PreSharedKey_Use(WOLFSSL* ssl, const byte* identity, word16 len, + word32 age, byte hmac, byte cipherSuite0, byte cipherSuite, byte resumption, PreSharedKey **preSharedKey) { @@ -8832,7 +8948,7 @@ static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, { if (msgType == client_hello) { /* Format: Len | Modes* */ - int idx = OPAQUE8_LEN; + word16 idx = OPAQUE8_LEN; /* Write out each possible mode. */ if (modes & (1 << PSK_KE)) @@ -8840,7 +8956,7 @@ static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, if (modes & (1 << PSK_DHE_KE)) output[idx++] = PSK_DHE_KE; /* Write out length of mode list. */ - output[0] = idx - OPAQUE8_LEN; + output[0] = (byte)(idx - OPAQUE8_LEN); *pSz += idx; return 0; @@ -8858,7 +8974,7 @@ static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length, +static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType) { int ret; @@ -8991,8 +9107,8 @@ static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz) * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte msgType) +static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte msgType) { (void)input; @@ -9100,16 +9216,24 @@ static int TLSX_EarlyData_Write(word32 maxSz, byte* output, byte msgType, * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length, +static int TLSX_EarlyData_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType) { if (msgType == client_hello) { if (length != 0) return BUFFER_E; - if (ssl->earlyData == expecting_early_data) + if (ssl->earlyData == expecting_early_data) { + + if (ssl->options.maxEarlyDataSz != 0) + ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_ACCEPTED; + else + ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_REJECTED; + return TLSX_EarlyData_Use(ssl, 0); + } ssl->earlyData = early_data_ext; + return 0; } if (msgType == encrypted_extensions) { @@ -9122,6 +9246,11 @@ static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length, if (ssl->options.pskIdIndex != 1) return PSK_KEY_ERROR; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* the extension from server comes in */ + ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_ACCEPTED; + } + return TLSX_EarlyData_Use(ssl, 1); } if (msgType == session_ticket) { @@ -9320,6 +9449,9 @@ void TLSX_FreeAll(TLSX* list, void* heap) KS_FREE_ALL((KeyShareEntry*)extension->data, heap); break; #endif + + default: + break; } XFREE(extension, heap, DYNAMIC_TYPE_TLSX); @@ -9446,7 +9578,7 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, break; case TLSX_PSK_KEY_EXCHANGE_MODES: - ret = PKM_GET_SIZE(extension->val, msgType, &length); + ret = PKM_GET_SIZE((byte)extension->val, msgType, &length); break; #endif @@ -9472,6 +9604,8 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); break; #endif + default: + break; } /* marks the extension as processed so ctx level */ @@ -9629,7 +9763,7 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, case TLSX_PSK_KEY_EXCHANGE_MODES: WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); - ret = PKM_WRITE(extension->val, output + offset, msgType, + ret = PKM_WRITE((byte)extension->val, output + offset, msgType, &offset); break; #endif @@ -9662,6 +9796,8 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, output + offset, msgType); break; #endif + default: + break; } /* writes extension data length. */ @@ -10006,6 +10142,7 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) #endif /* HAVE_FIPS */ #endif /* HAVE_ECC */ +#ifndef NO_DH /* Add FFDHE supported groups. */ #ifdef HAVE_FFDHE_8192 if (8192/8 >= ssl->options.minDhKeySz && @@ -10052,6 +10189,7 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) return ret; } #endif +#endif (void)ssl; (void)extensions; @@ -10110,8 +10248,13 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) int usingPSK = 0; #endif +#if defined(HAVE_SUPPORTED_CURVES) || defined(HAVE_QSH) + TLSX* extension = NULL; +#endif +#if defined(HAVE_SUPPORTED_CURVES) + word16 namedGroup = 0; +#endif #ifdef HAVE_QSH - TLSX* extension; QSHScheme* qsh; QSHScheme* next; @@ -10191,6 +10334,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) } } } + if (ret != 0) { + return ret; + } #endif #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) @@ -10262,9 +10408,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif #if defined(HAVE_SUPPORTED_CURVES) - if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { - word16 namedGroup; - + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (ssl->options.resuming && ssl->session.namedGroup != 0) namedGroup = ssl->session.namedGroup; @@ -10278,14 +10423,14 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) int set = 0; int i, j; - /* Default to first group in supported list. */ - namedGroup = ssl->group[0]; - /* Try to find preferred in supported list. */ - for (i = 0; i < (int)PREFERRED_GROUP_SZ && !set; i++) { - for (j = 0; j < ssl->numGroups; j++) { - if (preferredGroup[i] == ssl->group[j]) { - /* Most preferred that is supported. */ - namedGroup = ssl->group[j]; + /* try to find the highest element in ssl->group[] + * that is contained in preferredGroup[]. + */ + namedGroup = preferredGroup[0]; + for (i = 0; i < ssl->numGroups && !set; i++) { + for (j = 0; j < (int)PREFERRED_GROUP_SZ; j++) { + if (preferredGroup[j] == ssl->group[i]) { + namedGroup = ssl->group[i]; set = 1; break; } @@ -10296,11 +10441,18 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) /* Choose the most preferred group. */ namedGroup = preferredGroup[0]; } + } + else { + KeyShareEntry* kse = (KeyShareEntry*)extension->data; + if (kse) + namedGroup = kse->group; + } + if (namedGroup > 0) { ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); if (ret != 0) return ret; } - #endif + #endif /* HAVE_SUPPORTED_CURVES */ #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); @@ -10308,7 +10460,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #if defined(HAVE_SESSION_TICKET) if (ssl->options.resuming && ssl->session.ticketLen > 0) { WOLFSSL_SESSION* sess = &ssl->session; - word32 milli; + word32 now, milli; if (sess->ticketLen > MAX_PSK_ID_LEN) { WOLFSSL_MSG("Session ticket length for PSK ext is too large"); @@ -10321,8 +10473,13 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ret = SetCipherSpecs(ssl); if (ret != 0) return ret; - milli = TimeNowInMilliseconds() - sess->ticketSeen + - sess->ticketAdd; + now = TimeNowInMilliseconds(); + if (now < sess->ticketSeen) + milli = (0xFFFFFFFFU - sess->ticketSeen) + 1 + now; + else + milli = now - sess->ticketSeen; + milli += sess->ticketAdd; + /* Pre-shared key is mandatory extension for resumption. */ ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, milli, ssl->specs.mac_algorithm, @@ -10335,7 +10492,49 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) usingPSK = 1; } #endif - #ifndef NO_PSK + #ifndef NO_PSK + #ifndef WOLFSSL_PSK_ONE_ID + if (ssl->options.client_psk_cs_cb != NULL) { + int i; + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + byte cipherSuite0 = ssl->suites->suites[i + 0]; + byte cipherSuite = ssl->suites->suites[i + 1]; + unsigned int keySz; + + #ifdef HAVE_NULL_CIPHER + if (cipherSuite0 == ECC_BYTE) { + if (cipherSuite != TLS_SHA256_SHA256 && + cipherSuite != TLS_SHA384_SHA384) { + continue; + } + } + else + #endif + if (cipherSuite0 != TLS13_BYTE) + continue; + + keySz = ssl->options.client_psk_cs_cb( + ssl, ssl->arrays->server_hint, + ssl->arrays->client_identity, MAX_PSK_ID_LEN, + ssl->arrays->psk_key, MAX_PSK_KEY_LEN, + GetCipherNameInternal(cipherSuite0, cipherSuite)); + if (keySz > 0) { + ssl->arrays->psk_keySz = keySz; + ret = TLSX_PreSharedKey_Use(ssl, + (byte*)ssl->arrays->client_identity, + (word16)XSTRLEN(ssl->arrays->client_identity), 0, + SuiteMac(ssl->suites->suites + i), + cipherSuite0, cipherSuite, 0, NULL); + if (ret != 0) + return ret; + } + } + + usingPSK = 1; + } + else + #endif if (ssl->options.client_psk_cb != NULL || ssl->options.client_psk_tls13_cb != NULL) { /* Default ciphersuite. */ @@ -10350,7 +10549,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName); if (GetCipherSuiteFromName(cipherName, &cipherSuite0, - &cipherSuite, &cipherSuiteFlags) != 0) { + &cipherSuite, &cipherSuiteFlags) != 0) { return PSK_KEY_ERROR; } } @@ -10359,11 +10558,22 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ssl->arrays->server_hint, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); } + #if defined(OPENSSL_EXTRA) + /* OpenSSL treats 0 as a PSK key length of 0 + * and meaning no PSK available. + */ + if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + return PSK_KEY_ERROR; + } + if (ssl->arrays->psk_keySz > 0) { + #else if (ssl->arrays->psk_keySz == 0 || ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { return PSK_KEY_ERROR; } + #endif ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; + ssl->options.cipherSuite0 = cipherSuite0; ssl->options.cipherSuite = cipherSuite; (void)cipherSuiteFlags; @@ -10381,8 +10591,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) return ret; usingPSK = 1; - } + #if defined(OPENSSL_EXTRA) + } #endif + } + #endif /* !NO_PSK */ #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (usingPSK) { byte modes; @@ -10414,6 +10627,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) (void)public_key; (void)public_key_len; (void)ssl; + (void)extension; + (void)namedGroup; return ret; } @@ -10871,6 +11086,9 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset break; #endif #endif + + default: + break; } offset += OPAQUE16_LEN; /* extensions length */ @@ -10915,8 +11133,8 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */ #ifdef WOLFSSL_TLS13 -int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType, - int* found) +int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input, word16 length, + byte msgType, int* found) { int ret = 0; int offset = 0; @@ -10959,7 +11177,7 @@ int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType, #endif /** Parses a buffer of TLS extensions. */ -int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, +int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, Suites *suites) { int ret = 0; @@ -10995,7 +11213,7 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, ato16(input + offset, &size); offset += OPAQUE16_LEN; - if (offset + size > length) + if (length - offset < size) return BUFFER_ERROR; switch (type) { diff --git a/src/tls13.c b/src/tls13.c index ac79d0b49..357f2ed0e 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1,6 +1,6 @@ /* tls13.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -65,6 +65,10 @@ * Allow a NewSessionTicket message to be sent by server before Client's * Finished message. * See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note). + * WOLFSSL_PSK_ONE_ID + * When only one PSK ID is used and only one call to the PSK callback can + * be made per connect. + * You cannot use wc_psk_client_cs_callback type callback on client. */ #ifdef HAVE_CONFIG_H @@ -84,6 +88,11 @@ #include #endif +#if defined(__MACH__) || defined(__FreeBSD__) +#include +#endif /* __MACH__ || __FreeBSD__ */ + + #include #include #include @@ -174,6 +183,9 @@ static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen, len = WC_SHA512_DIGEST_SIZE; break; #endif + + default: + break; } /* When length is 0 then use zeroed data of digest length. */ @@ -385,32 +397,36 @@ static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, int digestAlg = 0; switch (hashAlgo) { - #ifndef NO_SHA256 - case sha256_mac: - hashSz = WC_SHA256_DIGEST_SIZE; - digestAlg = WC_SHA256; - if (includeMsgs) - ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + #ifndef NO_SHA256 + case sha256_mac: + hashSz = WC_SHA256_DIGEST_SIZE; + digestAlg = WC_SHA256; + if (includeMsgs) + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); break; - #endif + #endif - #ifdef WOLFSSL_SHA384 - case sha384_mac: - hashSz = WC_SHA384_DIGEST_SIZE; - digestAlg = WC_SHA384; - if (includeMsgs) - ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashSz = WC_SHA384_DIGEST_SIZE; + digestAlg = WC_SHA384; + if (includeMsgs) + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); break; - #endif + #endif - #ifdef WOLFSSL_TLS13_SHA512 - case sha512_mac: - hashSz = WC_SHA512_DIGEST_SIZE; - digestAlg = WC_SHA512; - if (includeMsgs) - ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hashSz = WC_SHA512_DIGEST_SIZE; + digestAlg = WC_SHA512; + if (includeMsgs) + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif + + default: + ret = HASH_TYPE_E; break; - #endif } if (ret != 0) return ret; @@ -424,9 +440,12 @@ static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, if (includeMsgs) hashOutSz = hashSz; + /* myBuffer may not initialized fully, but the sending length will be */ + PRAGMA_GCC_IGNORE("GCC diagnostic ignored \"-Wmaybe-uninitialized\""); return HKDF_Expand_Label(output, outputLen, secret, hashSz, protocol, protocolLen, label, labelLen, hash, hashOutSz, digestAlg); + PRAGMA_GCC_POP; } #ifndef NO_PSK @@ -1071,10 +1090,19 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); break; #endif /* WOLFSSL_TLS13_SHA512 */ + default: + break; } if (ret != 0) return ret; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" Key"); + WOLFSSL_BUFFER(key, ssl->specs.hash_size); + WOLFSSL_MSG(" Msg Hash"); + WOLFSSL_BUFFER(hash, hashSz); +#endif + /* Calculate the verify data. */ ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId); if (ret == 0) { @@ -1086,6 +1114,11 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, wc_HmacFree(&verifyHmac); } +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" Hash"); + WOLFSSL_BUFFER(hash, hashSz); +#endif + if (pHashSz) *pHashSz = hashSz; @@ -1195,6 +1228,9 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) goto end; } break; + + default: + break; } if (!store) @@ -1256,7 +1292,8 @@ end: return ret; } -#ifdef HAVE_SESSION_TICKET +#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +#ifndef NO_ASN_TIME #if defined(USER_TICKS) #if 0 word32 TimeNowInMilliseconds(void) @@ -1470,6 +1507,13 @@ end: return (word32)(ktime_get_real_ns() / (ktime_t)1000000); #endif } +#elif defined(WOLFSSL_QNX_CAAM) + word32 TimeNowInMilliseconds(void) + { + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + return (word32)(now.tv_sec * 1000 + now.tv_nsec / 1000000); + } #elif defined(FUSION_RTOS) /* The time in milliseconds. * Used for tickets to represent difference between when first seen and when @@ -1505,6 +1549,12 @@ end: return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); } #endif +#else + /* user must supply time in milliseconds function: + * word32 TimeNowInMilliseconds(void); + * The response is milliseconds elapsed + */ +#endif /* !NO_ASN_TIME */ #endif /* HAVE_SESSION_TICKET || !NO_PSK */ @@ -1719,8 +1769,8 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, if (ret != 0) return ret; /* Add authentication code of encrypted data to end. */ - ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz, - tag, POLY1305_AUTH_SZ); + ret = wc_Poly1305_MAC(ssl->auth.poly1305, aad, aadSz, output, sz, tag, + POLY1305_AUTH_SZ); return ret; } @@ -1944,6 +1994,9 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, break; } + + default: + break; } /* Reset state */ @@ -1996,8 +2049,8 @@ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, if (ret != 0) return ret; /* Generate authentication tag for encrypted data. */ - if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, - (byte*)input, sz, tag, sizeof(tag))) != 0) { + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, aad, aadSz, input, sz, tag, + sizeof(tag))) != 0) { return ret; } @@ -2139,7 +2192,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, - WC_ASYNC_FLAG_CALL_AGAIN); + WC_ASYNC_FLAG_NONE); if (ret != 0) break; #endif @@ -2162,7 +2215,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, - WC_ASYNC_FLAG_CALL_AGAIN); + WC_ASYNC_FLAG_NONE); if (ret != 0) break; #endif @@ -2227,6 +2280,9 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, break; } + + default: + break; } #ifndef WOLFSSL_EARLY_DATA @@ -2274,7 +2330,7 @@ static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs) int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { - int ret = 0; + int ret; BuildMsg13Args* args; BuildMsg13Args lcl_args; #ifdef WOLFSSL_ASYNC_CRYPT @@ -2285,8 +2341,8 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, WOLFSSL_ENTER("BuildTls13Message"); - ret = WC_NOT_PENDING_E; #ifdef WOLFSSL_ASYNC_CRYPT + ret = WC_NOT_PENDING_E; if (asyncOkay) { ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); if (ret != WC_NOT_PENDING_E) { @@ -2302,7 +2358,10 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } /* Reset state */ - if (ret == WC_NOT_PENDING_E) { +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_NOT_PENDING_E) +#endif + { ret = 0; ssl->options.buildMsgState = BUILD_MSG_BEGIN; XMEMSET(args, 0, sizeof(BuildMsg13Args)); @@ -2396,6 +2455,9 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } break; } + + default: + break; } exit_buildmsg: @@ -2424,7 +2486,8 @@ exit_buildmsg: return ret; } -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) || \ + !defined(NO_WOLFSSL_CLIENT) /* Find the cipher suite in the suites set in the SSL. * * ssl SSL/TLS object. @@ -2446,6 +2509,70 @@ static int FindSuiteSSL(WOLFSSL* ssl, byte* suite) } #endif +#ifndef NO_PSK +/* Get the MAC algorithm for the TLS 1.3 cipher suite. + * + * @param [in] suite. + * @return A value from wc_MACAlgorithm enumeration. + */ +byte SuiteMac(byte* suite) +{ + byte mac = no_mac; + + if (suite[0] == TLS13_BYTE) { + switch (suite[1]) { + #ifdef BUILD_TLS_AES_128_GCM_SHA256 + case TLS_AES_128_GCM_SHA256: + mac = sha256_mac; + break; + #endif + #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + case TLS_CHACHA20_POLY1305_SHA256: + mac = sha256_mac; + break; + #endif + #ifdef BUILD_TLS_AES_128_CCM_SHA256 + case TLS_AES_128_CCM_SHA256: + mac = sha256_mac; + break; + #endif + #ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + case TLS_AES_128_CCM_8_SHA256: + mac = sha256_mac; + break; + #endif + #ifdef BUILD_TLS_AES_256_GCM_SHA384 + case TLS_AES_256_GCM_SHA384: + mac = sha384_mac; + break; + #endif + default: + break; + } + } +#ifdef HAVE_NULL_CIPHER + else if (suite[0] == ECC_BYTE) { + switch (suite[1]) { + #ifdef BUILD_TLS_SHA256_SHA256 + case TLS_SHA256_SHA256: + mac = sha256_mac; + break; + #endif + #ifdef BUILD_TLS_SHA384_SHA384 + case TLS_SHA384_SHA384: + mac = sha384_mac; + break; + #endif + default: + break; + } + } +#endif + + return mac; +} +#endif + #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) /* Create Cookie extension using the hash of the first ClientHello. * @@ -2528,8 +2655,10 @@ int RestartHandshakeHash(WOLFSSL* ssl) AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); +#ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Restart Hash"); WOLFSSL_BUFFER(hash, hashSz); +#endif #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.sendCookie) { @@ -2575,33 +2704,84 @@ static byte helloRetryRequestRandom[] = { #ifndef NO_WOLFSSL_CLIENT #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_PSK_ONE_ID) && \ + !defined(NO_PSK) +/** +* convert mac algorithm to WOLFSSL_EVP_MD +* @param mac_alg mac algorithm +* @return const WOLFSSL_EVP_MD on sucessful, otherwise NULL +*/ +static const WOLFSSL_EVP_MD* ssl_handshake_md(const byte mac_alg) +{ + switch(mac_alg) { + case no_mac: + #ifndef NO_MD5 + case md5_mac: + return wolfSSL_EVP_md5(); + #endif + #ifndef NO_SHA + case sha_mac: + return wolfSSL_EVP_sha1(); + #endif + #ifdef WOLFSSL_SHA224 + case sha224_mac: + return wolfSSL_EVP_sha224(); + #endif + case sha256_mac: + return wolfSSL_EVP_sha256(); + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return wolfSSL_EVP_sha384(); + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return wolfSSL_EVP_sha512(); + #endif + case rmd_mac: + case blake2b_mac: + WOLFSSL_MSG("no suitable EVP_MD"); + return NULL; + default: + WOLFSSL_MSG("Unknown mac algorithm"); + return NULL; + } +} +#endif /* Setup pre-shared key based on the details in the extension data. * - * ssl SSL/TLS object. - * psk Pre-shared key extension data. + * ssl SSL/TLS object. + * psk Pre-shared key extension data. + * clientHello Whether called from client_hello construction. * returns 0 on success, PSK_KEY_ERROR when the client PSK callback fails and * other negative value on failure. */ -static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) +static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) { +#if defined(HAVE_SESSION_TICKET) || !defined(WOLFSSL_PSK_ONE_ID) int ret; +#endif byte suite[2]; if (psk == NULL) return BAD_FUNC_ARG; - suite[0] = psk->cipherSuite0; - suite[1] = psk->cipherSuite; - if (!FindSuiteSSL(ssl, suite)) - return PSK_KEY_ERROR; - - ssl->options.cipherSuite0 = psk->cipherSuite0; - ssl->options.cipherSuite = psk->cipherSuite; - if ((ret = SetCipherSpecs(ssl)) != 0) - return ret; + suite[0] = ssl->options.cipherSuite0; + suite[1] = ssl->options.cipherSuite; #ifdef HAVE_SESSION_TICKET if (psk->resumption) { + if (clientHello) { + /* Ensure cipher suite is supported or changed suite to one with + * the same MAC algorithm. */ + if (!FindSuiteSSL(ssl, suite)) + return PSK_KEY_ERROR; + + /* Setting mac for binder and keys for deriving EarlyData. */ + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + } + #ifdef WOLFSSL_EARLY_DATA if (ssl->session.maxEarlyDataSz == 0) ssl->earlyData = no_early_data; @@ -2616,40 +2796,124 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) #endif #ifndef NO_PSK if (!psk->resumption) { - #ifndef WOLFSSL_PSK_ONE_ID + /* Get the pre-shared key. */ +#ifndef WOLFSSL_PSK_ONE_ID const char* cipherName = NULL; - byte cipherSuite0 = TLS13_BYTE, cipherSuite = WOLFSSL_DEF_PSK_CIPHER; - int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE; + #ifdef OPENSSL_EXTRA + WOLFSSL_SESSION* psksession = NULL; + #endif + + /* Set the client identity to use. */ + XMEMSET(ssl->arrays->client_identity, 0, + sizeof(ssl->arrays->client_identity)); + XMEMCPY(ssl->arrays->client_identity, psk->identity, psk->identityLen); + + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("PSK cipher suite:"); + WOLFSSL_MSG(GetCipherNameInternal(psk->cipherSuite0, psk->cipherSuite)); + #endif /* Get the pre-shared key. */ - if (ssl->options.client_psk_tls13_cb != NULL) { + #ifdef OPENSSL_EXTRA + if (ssl->options.session_psk_cb != NULL) { + const unsigned char* id = NULL; + size_t idlen = 0; + const WOLFSSL_EVP_MD* handshake_md = NULL; + + if (ssl->msgsReceived.got_hello_retry_request >= 1) { + handshake_md = ssl_handshake_md(ssl->specs.mac_algorithm); + } + /* OpenSSL compatible callback that gets cached session. */ + if (ssl->options.session_psk_cb(ssl, handshake_md, &id, &idlen, + &psksession) == 0) { + wolfSSL_SESSION_free(psksession); + WOLFSSL_MSG("psk session callback failed"); + return PSK_KEY_ERROR; + } + if (psksession != NULL) { + if (idlen > MAX_PSK_KEY_LEN) { + wolfSSL_SESSION_free(psksession); + WOLFSSL_MSG("psk key length is too long"); + return PSK_KEY_ERROR; + } + + ssl->arrays->psk_keySz = (word32)idlen; + XMEMCPY(ssl->arrays->psk_key, id, idlen); + suite[0] = psksession->cipherSuite0; + suite[1] = psksession->cipherSuite; + /* Not needed anymore. */ + wolfSSL_SESSION_free(psksession); + /* Leave pointer not NULL to indicate success with callback. */ + } + } + if (psksession != NULL) { + /* Don't try other callbacks - we have an answer. */ + } + else + #endif /* OPENSSL_EXTRA */ + if (ssl->options.client_psk_cs_cb != NULL) { + /* Lookup key again for next identity. */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cs_cb( + ssl, ssl->arrays->server_hint, + ssl->arrays->client_identity, MAX_PSK_ID_LEN, + ssl->arrays->psk_key, MAX_PSK_KEY_LEN, + GetCipherNameInternal(psk->cipherSuite0, psk->cipherSuite)); + if (clientHello) { + /* Use PSK cipher suite. */ + ssl->options.cipherSuite0 = psk->cipherSuite0; + ssl->options.cipherSuite = psk->cipherSuite; + } + else { + byte pskCS[2] = { psk->cipherSuite0, psk->cipherSuite }; + /* Ensure PSK and negotiated cipher suites have same hash. */ + if (SuiteMac(pskCS) != SuiteMac(suite)) { + return PSK_KEY_ERROR; + } + /* Negotiated cipher suite is to be used - update PSK. */ + psk->cipherSuite0 = suite[0]; + psk->cipherSuite = suite[1]; + } + } + else if (ssl->options.client_psk_tls13_cb != NULL) { + byte cipherSuite0; + byte cipherSuite; + int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE; + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(ssl, - (char *)psk->identity, ssl->arrays->client_identity, + ssl->arrays->server_hint, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName); if (GetCipherSuiteFromName(cipherName, &cipherSuite0, &cipherSuite, &cipherSuiteFlags) != 0) { return PSK_KEY_ERROR; } + ssl->options.cipherSuite0 = cipherSuite0; + ssl->options.cipherSuite = cipherSuite; + (void)cipherSuiteFlags; } else { ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, - (char *)psk->identity, ssl->arrays->client_identity, + ssl->arrays->server_hint, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + ssl->options.cipherSuite0 = TLS13_BYTE; + ssl->options.cipherSuite = WOLFSSL_DEF_PSK_CIPHER; } if (ssl->arrays->psk_keySz == 0 || ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { return PSK_KEY_ERROR; } - if (psk->cipherSuite0 != cipherSuite0 || - psk->cipherSuite != cipherSuite) { + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; +#else + /* PSK information loaded during setting of default TLS extensions. */ +#endif /* !WOLFSSL_PSK_ONE_ID */ + + if (!clientHello && (psk->cipherSuite0 != suite[0] || + psk->cipherSuite != suite[1])) { return PSK_KEY_ERROR; } - (void)cipherSuiteFlags; - #else - /* PSK information loaded during setting of default TLS extensions. */ - #endif } #endif @@ -2699,7 +2963,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) /* Calculate the binder for each identity based on previous handshake data. */ while (current != NULL) { - if ((ret = SetupPskKey(ssl, current)) != 0) + if ((ret = SetupPskKey(ssl, current, 1)) != 0) return ret; #ifdef HAVE_SESSION_TICKET @@ -2741,7 +3005,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) #ifdef WOLFSSL_EARLY_DATA if (ssl->earlyData != no_early_data) { - if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0) + if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data, 1)) != 0) return ret; /* Derive early data encryption key. */ @@ -2768,13 +3032,24 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) * ssl The SSL/TLS object. * returns 0 on success and otherwise failure. */ + +typedef struct Sch13Args { + byte* output; + word32 idx; + int sendSz; + word16 length; +} Sch13Args; + int SendTls13ClientHello(WOLFSSL* ssl) { - byte* output; - word16 length; - word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int sendSz; - int ret; + int ret; +#ifdef WOLFSSL_ASYNC_CRYPT + Sch13Args* args = (Sch13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Sch13Args args[1]; +#endif WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); WOLFSSL_ENTER("SendTls13ClientHello"); @@ -2803,19 +3078,55 @@ int SendTls13ClientHello(WOLFSSL* ssl) return SUITES_ERROR; } - /* Version | Random | Session Id | Cipher Suites | Compression */ - length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + - SUITE_LEN + COMP_LEN + ENUM_LEN; - #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) - length += ID_LEN; - #else - if (ssl->session.sessionIDSz > 0) - length += ssl->session.sessionIDSz; - #endif +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } + else +#endif + { + /* Reset state */ + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Sch13Args)); + } + switch (ssl->options.asyncState) { + case TLS_ASYNC_BEGIN: + { + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + /* Version | Random | Session Id | Cipher Suites | Compression */ + args->length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; +#if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + args->length += ID_LEN; +#else + if (ssl->session.sessionIDSz > 0) + args->length += ssl->session.sessionIDSz; +#endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + case TLS_ASYNC_DO: + { /* Auto populate extensions supported unless user defined. */ if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) return ret; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { #ifdef WOLFSSL_EARLY_DATA #ifndef NO_PSK if (!ssl->options.resuming && @@ -2835,86 +3146,99 @@ int SendTls13ClientHello(WOLFSSL* ssl) } #endif /* Include length of TLS extensions. */ - ret = TLSX_GetRequestSize(ssl, client_hello, &length); + ret = TLSX_GetRequestSize(ssl, client_hello, &args->length); if (ret != 0) return ret; /* Total message size. */ - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; /* Check buffers are big enough and grow if needed. */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) return ret; /* Get position in output buffer to write new message to. */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* Put the record and handshake headers on. */ - AddTls13Headers(output, length, client_hello, ssl); + AddTls13Headers(args->output, args->length, client_hello, ssl); /* Protocol version - negotiation now in extension: supported_versions. */ - output[idx++] = SSLv3_MAJOR; - output[idx++] = TLSv1_2_MINOR; + args->output[args->idx++] = SSLv3_MAJOR; + args->output[args->idx++] = TLSv1_2_MINOR; /* Keep for downgrade. */ ssl->chVersion = ssl->version; /* Client Random */ if (ssl->options.connectState == CONNECT_BEGIN) { - ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + ret = wc_RNG_GenerateBlock(ssl->rng, args->output + args->idx, RAN_LEN); if (ret != 0) return ret; /* Store random for possible second ClientHello. */ - XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + XMEMCPY(ssl->arrays->clientRandom, args->output + args->idx, RAN_LEN); } else - XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); - idx += RAN_LEN; + XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN); + args->idx += RAN_LEN; if (ssl->session.sessionIDSz > 0) { /* Session resumption for old versions of protocol. */ - output[idx++] = ID_LEN; - XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); - idx += ID_LEN; + args->output[args->idx++] = ID_LEN; + XMEMCPY(args->output + args->idx, ssl->session.sessionID, + ssl->session.sessionIDSz); + args->idx += ID_LEN; } else { #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT - output[idx++] = ID_LEN; - XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN); - idx += ID_LEN; + args->output[args->idx++] = ID_LEN; + XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, ID_LEN); + args->idx += ID_LEN; #else /* TLS v1.3 does not use session id - 0 length. */ - output[idx++] = 0; + args->output[args->idx++] = 0; #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ } /* Cipher suites */ - c16toa(ssl->suites->suiteSz, output + idx); - idx += OPAQUE16_LEN; - XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); - idx += ssl->suites->suiteSz; + c16toa(ssl->suites->suiteSz, args->output + args->idx); + args->idx += OPAQUE16_LEN; + XMEMCPY(args->output + args->idx, &ssl->suites->suites, + ssl->suites->suiteSz); + args->idx += ssl->suites->suiteSz; +#ifdef WOLFSSL_DEBUG_TLS + { + int ii; + WOLFSSL_MSG("Ciphers:"); + for (ii = 0 ; ii < ssl->suites->suiteSz; ii += 2) { + WOLFSSL_MSG(GetCipherNameInternal(ssl->suites->suites[ii+0], + ssl->suites->suites[ii+1])); + } + } +#endif /* Compression not supported in TLS v1.3. */ - output[idx++] = COMP_LEN; - output[idx++] = NO_COMPRESSION; + args->output[args->idx++] = COMP_LEN; + args->output[args->idx++] = NO_COMPRESSION; /* Write out extensions for a request. */ - length = 0; - ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length); + args->length = 0; + ret = TLSX_WriteRequest(ssl, args->output + args->idx, client_hello, + &args->length); if (ret != 0) return ret; - idx += length; + args->idx += args->length; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Resumption has a specific set of extensions and binder is calculated * for each identity. */ if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY)) - ret = WritePSKBinders(ssl, output, idx); + ret = WritePSKBinders(ssl, args->output, args->idx); else #endif - ret = HashOutput(ssl, output, idx, 0); + ret = HashOutput(ssl, args->output, args->idx, 0); if (ret != 0) return ret; @@ -2923,18 +3247,23 @@ int SendTls13ClientHello(WOLFSSL* ssl) #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); if (ssl->toInfoOn) { - AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz, + AddPacketInfo(ssl, "ClientHello", handshake, args->output, args->sendSz, WRITE_PROTO, ssl->heap); } #endif - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; #ifdef WOLFSSL_EARLY_DATA_GROUP if (ssl->earlyData == no_early_data) #endif ret = SendBuffered(ssl); + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch (ssl->options.asyncState) */ WOLFSSL_LEAVE("SendTls13ClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); @@ -2953,63 +3282,95 @@ int SendTls13ClientHello(WOLFSSL* ssl) * helloSz The length of the current handshake message. * returns 0 on success and otherwise failure. */ + +typedef struct Dsh13Args { + ProtocolVersion pv; + word32 idx; + word32 begin; + const byte* sessId; + word16 totalExtSz; + byte sessIdSz; + byte extMsgType; +} Dsh13Args; + int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz, byte* extMsgType) { - ProtocolVersion pv; - word32 i = *inOutIdx; - word32 begin = i; - int ret; - byte sessIdSz; - const byte* sessId; - byte b; - int foundVersion; - word16 totalExtSz; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - TLSX* ext; - PreSharedKey* psk = NULL; + int ret; + byte suite[2]; +#ifdef WOLFSSL_ASYNC_CRYPT + Dsh13Args* args = (Dsh13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dsh13Args args[1]; #endif WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); WOLFSSL_ENTER("DoTls13ServerHello"); - if (ssl->arrays == NULL) + if (ssl == NULL || ssl->arrays == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } + else +#endif + { + /* Reset state */ + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dsh13Args)); + } + + switch (ssl->options.asyncState) { + case TLS_ASYNC_BEGIN: + { + byte b; #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello"); if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); #endif - if (ssl == NULL || ssl->arrays == NULL) - return BAD_FUNC_ARG; - /* Protocol version length check. */ - if (OPAQUE16_LEN > helloSz) + if (helloSz < OPAQUE16_LEN) return BUFFER_ERROR; + args->idx = *inOutIdx; + args->begin = args->idx; + /* Protocol version */ - XMEMCPY(&pv, input + i, OPAQUE16_LEN); - i += OPAQUE16_LEN; + XMEMCPY(&args->pv, input + args->idx, OPAQUE16_LEN); + args->idx += OPAQUE16_LEN; #ifndef WOLFSSL_NO_TLS12 - if (pv.major == ssl->version.major && pv.minor < TLSv1_2_MINOR && - ssl->options.downgrade) { + if (args->pv.major == ssl->version.major && + args->pv.minor < TLSv1_2_MINOR && + ssl->options.downgrade) + { /* Force client hello version 1.2 to work for static RSA. */ ssl->chVersion.minor = TLSv1_2_MINOR; ssl->version.minor = TLSv1_2_MINOR; return DoServerHello(ssl, input, inOutIdx, helloSz); } #endif - if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR) + if (args->pv.major != ssl->version.major || + args->pv.minor != TLSv1_2_MINOR) { return VERSION_ERROR; + } /* Random and session id length check */ - if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz) + if ((args->idx - args->begin) + RAN_LEN + ENUM_LEN > helloSz) return BUFFER_ERROR; - if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0) { + /* Check if hello retry request */ + if (XMEMCMP(input + args->idx, helloRetryRequestRandom, RAN_LEN) == 0) { *extMsgType = hello_retry_request; + /* A HelloRetryRequest comes in as an ServerHello for MiddleBox compat. * Found message to be a HelloRetryRequest. * Don't allow more than one HelloRetryRequest or ServerHello. @@ -3017,40 +3378,43 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->msgsReceived.got_hello_retry_request == 1) { return DUPLICATE_MSG_E; } - /* Update counts to reflect change of message type. */ - ssl->msgsReceived.got_hello_retry_request++; - ssl->msgsReceived.got_server_hello--; } + args->extMsgType = *extMsgType; /* Server random - keep for debugging. */ - XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); - i += RAN_LEN; + XMEMCPY(ssl->arrays->serverRandom, input + args->idx, RAN_LEN); + args->idx += RAN_LEN; /* Session id */ - sessIdSz = input[i++]; - if ((i - begin) + sessIdSz > helloSz) + args->sessIdSz = input[args->idx++]; + if ((args->idx - args->begin) + args->sessIdSz > helloSz) return BUFFER_ERROR; - sessId = input + i; - i += sessIdSz; + args->sessId = input + args->idx; + args->idx += args->sessIdSz; ssl->options.haveSessionId = 1; /* Ciphersuite and compression check */ - if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) + if ((args->idx - args->begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; /* Set the cipher suite from the message. */ - ssl->options.cipherSuite0 = input[i++]; - ssl->options.cipherSuite = input[i++]; + ssl->options.cipherSuite0 = input[args->idx++]; + ssl->options.cipherSuite = input[args->idx++]; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Chosen cipher suite:"); + WOLFSSL_MSG(GetCipherNameInternal(ssl->options.cipherSuite0, + ssl->options.cipherSuite)); +#endif /* Compression */ - b = input[i++]; + b = input[args->idx++]; if (b != 0) { WOLFSSL_MSG("Must be no compression types in list"); return INVALID_PARAMETER; } - if ((i - begin) + OPAQUE16_LEN > helloSz) { + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) { if (!ssl->options.downgrade) return BUFFER_ERROR; #ifndef WOLFSSL_NO_TLS12 @@ -3058,18 +3422,21 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ssl->options.haveEMS = 0; } - if ((i - begin) < helloSz) { + + if ((args->idx - args->begin) < helloSz) { + int foundVersion; + /* Get extension length and length check. */ - if ((i - begin) + OPAQUE16_LEN > helloSz) + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) return BUFFER_ERROR; - ato16(&input[i], &totalExtSz); - i += OPAQUE16_LEN; - if ((i - begin) + totalExtSz > helloSz) + ato16(&input[args->idx], &args->totalExtSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + args->totalExtSz > helloSz) return BUFFER_ERROR; /* Need to negotiate version first. */ - if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz, - *extMsgType, &foundVersion))) { + if ((ret = TLSX_ParseVersion(ssl, input + args->idx, + args->totalExtSz, *extMsgType, &foundVersion))) { return ret; } if (!foundVersion) { @@ -3079,20 +3446,50 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; } - if (pv.minor < ssl->options.minDowngrade) + if (args->pv.minor < ssl->options.minDowngrade) return VERSION_ERROR; - ssl->version.minor = pv.minor; + ssl->version.minor = args->pv.minor; + } + if (foundVersion && ssl->options.downgrade && + (args->pv.minor < ssl->options.minDowngrade)) { + return VERSION_ERROR; } - - /* Parse and handle extensions. */ - ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType, - NULL); - if (ret != 0) - return ret; - - i += totalExtSz; } - *inOutIdx = i; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + case TLS_ASYNC_DO: + { + /* restore message type */ + *extMsgType = args->extMsgType; + + if (args->totalExtSz > 0) { + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, input + args->idx, args->totalExtSz, + *extMsgType, NULL); + if (ret != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_server_hello--; + } + #endif + return ret; + } + args->idx += args->totalExtSz; + } + + if (*extMsgType == hello_retry_request) { + /* Update counts to reflect change of message type. */ + ssl->msgsReceived.got_hello_retry_request = 1; + ssl->msgsReceived.got_server_hello--; + } + *inOutIdx = args->idx; ssl->options.serverState = SERVER_HELLO_COMPLETE; @@ -3112,7 +3509,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, */ if (!IsAtLeastTLSv1_3(ssl->version)) { #ifndef WOLFSSL_NO_TLS12 - ssl->arrays->sessionIDSz = sessIdSz; + ssl->arrays->sessionIDSz = args->sessIdSz; if (ssl->arrays->sessionIDSz > ID_LEN) { WOLFSSL_MSG("Invalid session ID size"); @@ -3120,7 +3517,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BUFFER_ERROR; } else if (ssl->arrays->sessionIDSz) { - XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz); + XMEMCPY(ssl->arrays->sessionID, args->sessId, + ssl->arrays->sessionIDSz); ssl->options.haveSessionId = 1; } @@ -3138,20 +3536,31 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return ret; } + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT - if (sessIdSz == 0) + if (args->sessIdSz == 0) return INVALID_PARAMETER; if (ssl->session.sessionIDSz != 0) { - if (ssl->session.sessionIDSz != sessIdSz || - XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) { + if (ssl->session.sessionIDSz != args->sessIdSz || + XMEMCMP(ssl->session.sessionID, args->sessId, + args->sessIdSz) != 0) { return INVALID_PARAMETER; } } - else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0) + else if (XMEMCMP(ssl->arrays->clientRandom, args->sessId, + args->sessIdSz) != 0) { return INVALID_PARAMETER; + } #else - if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 && - XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) { + if (args->sessIdSz != ssl->session.sessionIDSz || (args->sessIdSz > 0 && + XMEMCMP(ssl->session.sessionID, args->sessId, args->sessIdSz) != 0)) + { WOLFSSL_MSG("Server sent different session id"); return INVALID_PARAMETER; } @@ -3174,9 +3583,17 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return INVALID_PARAMETER; } -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + suite[0] = ssl->options.cipherSuite0; + suite[1] = ssl->options.cipherSuite; + if (!FindSuiteSSL(ssl, suite)) { + WOLFSSL_MSG("Cipher suite not supported on client"); + return PSK_KEY_ERROR; + } + if (*extMsgType == server_hello) { - ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + PreSharedKey* psk = NULL; + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); if (ext != NULL) psk = (PreSharedKey*)ext->data; while (psk != NULL && !psk->chosen) @@ -3186,12 +3603,10 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->arrays->psk_keySz = 0; XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN); } - else if ((ret = SetupPskKey(ssl, psk)) != 0) + else if ((ret = SetupPskKey(ssl, psk, 0)) != 0) return ret; - } #endif - if (*extMsgType == server_hello) { ssl->keys.encryptionOn = 1; ssl->options.serverState = SERVER_HELLO_COMPLETE; } @@ -3202,6 +3617,12 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = RestartHandshakeHash(ssl); } + break; + } /* case TLS_ASYNC_FINALIZE */ + default: + ret = INPUT_CASE_ERROR; + } /* switch (ssl->options.asyncState) */ + WOLFSSL_LEAVE("DoTls13ServerHello", ret); WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); @@ -3238,7 +3659,7 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, #endif /* Length field of extension data. */ - if (totalSz < i - begin + OPAQUE16_LEN) + if (totalSz < OPAQUE16_LEN) return BUFFER_ERROR; ato16(&input[i], &totalExtSz); i += OPAQUE16_LEN; @@ -3246,9 +3667,10 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, /* Extension data. */ if (i - begin + totalExtSz > totalSz) return BUFFER_ERROR; - if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, - encrypted_extensions, NULL))) + if ((ret = TLSX_Parse(ssl, input + i, totalExtSz, encrypted_extensions, + NULL))) { return ret; + } /* Move index to byte after message. */ *inOutIdx = i + totalExtSz; @@ -3314,7 +3736,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); #endif - if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + if (OPAQUE8_LEN > size) return BUFFER_ERROR; /* Length of the request context. */ @@ -3352,8 +3774,8 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, return BUFFER_ERROR; if (len == 0) return INVALID_PARAMETER; - if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len, - certificate_request, &peerSuites))) { + if ((ret = TLSX_Parse(ssl, input + *inOutIdx, len, certificate_request, + &peerSuites))) { return ret; } *inOutIdx += len; @@ -3400,8 +3822,8 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, */ static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) { - byte suites[WOLFSSL_MAX_SUITE_SZ]; - int suiteSz = 0; + byte suites[WOLFSSL_MAX_SUITE_SZ]; + word16 suiteSz = 0; word16 i, j; XMEMSET(suites, 0, WOLFSSL_MAX_SUITE_SZ); @@ -3418,77 +3840,125 @@ static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) ssl->suites->suiteSz = suiteSz; XMEMCPY(ssl->suites->suites, &suites, sizeof(suites)); +#ifdef WOLFSSL_DEBUG_TLS + { + int ii; + WOLFSSL_MSG("Refined Ciphers:"); + for (ii = 0 ; ii < ssl->suites->suiteSz; ii += 2) { + WOLFSSL_MSG(GetCipherNameInternal(ssl->suites->suites[ii+0], + ssl->suites->suites[ii+1])); + } + } +#endif } -/* Handle any Pre-Shared Key (PSK) extension. - * Must do this in ClientHello as it requires a hash of the truncated message. - * Don't know size of binders until Pre-Shared Key extension has been parsed. +#ifndef NO_PSK +/* Attempt to find the PSK (not session ticket) that matches. * - * ssl The SSL/TLS object. - * input The ClientHello message. - * helloSz The size of the ClientHello message (including binders if present). - * usingPSK Indicates handshake is using Pre-Shared Keys. + * @param [in, out] ssl The SSL/TLS object. + * @param [in] psk A pre-shared key from the extension. + * @param [out] suite Cipher suite to use with PSK. + * @param [out] err Error code. + * PSK_KEY_ERROR when key is too big or ticket age is + * invalid, + * UNSUPPORTED_SUITE on invalid suite. + * Other error when attempting to derive early secret. + * @return 1 when a match found - but check error code. + * @return 0 when no match found. + */ +static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) +{ + int ret = 0; + int found = 0; + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + Arrays* sa = ssl->arrays; + + if (ssl->options.server_psk_tls13_cb != NULL) { + sa->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, + sa->client_identity, sa->psk_key, MAX_PSK_KEY_LEN, &cipherName); + if (sa->psk_keySz != 0) { + int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE; + found = (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite, &cipherSuiteFlags) == 0); + (void)cipherSuiteFlags; + } + } + if (!found && (ssl->options.server_psk_cb != NULL)) { + sa->psk_keySz = ssl->options.server_psk_cb(ssl, + sa->client_identity, sa->psk_key, + MAX_PSK_KEY_LEN); + found = (sa->psk_keySz != 0); + } + if (found) { + if (sa->psk_keySz > MAX_PSK_KEY_LEN) { + ret = PSK_KEY_ERROR; + } + if (ret == 0) { + #ifndef WOLFSSL_PSK_ONE_ID + /* Check whether PSK ciphersuite is in SSL. */ + found = (suite[0] == cipherSuite0) && (suite[1] == cipherSuite); + #else + /* Check whether PSK ciphersuite is in SSL. */ + suite[0] = cipherSuite0; + suite[1] = cipherSuite; + found = FindSuiteSSL(ssl, suite); + #endif + } + if ((ret == 0) && found) { + /* Default to ciphersuite if cb doesn't specify. */ + ssl->options.resuming = 0; + /* Don't send certificate request when using PSK. */ + ssl->options.verifyPeer = 0; + + /* PSK age is always zero. */ + if (psk->ticketAge != ssl->session.ticketAdd) { + ret = PSK_KEY_ERROR; + } + } + if ((ret == 0) && found) { + /* Set PSK ciphersuite into SSL. */ + ssl->options.cipherSuite0 = suite[0]; + ssl->options.cipherSuite = suite[1]; + ret = SetCipherSpecs(ssl); + } + if ((ret == 0) && found) { + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + } + } + + *err = ret; + return found; +} +#endif + +/* Handle any Pre-Shared Key (PSK) extension. + * Find a PSK that supports the cipher suite passed in. + * + * ssl SSL/TLS object. + * suite Cipher suite to find PSK for. + * usingPSK 1=Indicates handshake is using Pre-Shared Keys (2=Ephemeral) + * first Set to 1 if first in extension * returns 0 on success and otherwise failure. */ -static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, - int* usingPSK) +static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) { int ret; TLSX* ext; - word16 bindersLen; PreSharedKey* current; byte binderKey[WC_MAX_DIGEST_SIZE]; byte binder[WC_MAX_DIGEST_SIZE]; word32 binderLen; - word16 modes; - byte suite[2]; -#ifdef WOLFSSL_EARLY_DATA - int pskCnt = 0; - TLSX* extEarlyData; -#endif -#ifndef NO_PSK - const char* cipherName = NULL; - byte cipherSuite0 = TLS13_BYTE; - byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; - int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE; -#endif WOLFSSL_ENTER("DoPreSharedKeys"); ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); - if (ext == NULL) { - /* Hash data up to binders for deriving binders in PSK extension. */ - ret = HashInput(ssl, input, helloSz); - return ret; - } - - /* Extensions pushed on stack/list and PSK must be last. */ - if (ssl->extensions != ext) - return PSK_KEY_ERROR; - - /* Assume we are going to resume with a pre-shared key. */ - ssl->options.resuming = 1; - - /* Find the pre-shared key extension and calculate hash of truncated - * ClientHello for binders. - */ - ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, - client_hello, &bindersLen); - if (ret < 0) - return ret; - - /* Hash data up to binders for deriving binders in PSK extension. */ - ret = HashInput(ssl, input, helloSz - bindersLen); - if (ret != 0) - return ret; /* Look through all client's pre-shared keys for a match. */ current = (PreSharedKey*)ext->data; while (current != NULL) { - #ifdef WOLFSSL_EARLY_DATA - pskCnt++; - #endif - #ifndef NO_PSK if (current->identityLen > MAX_PSK_ID_LEN) { return BUFFER_ERROR; @@ -3508,7 +3978,10 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, now = TimeNowInMilliseconds(); if (now == (word32)GETTIME_ERROR) return now; - diff = now - ssl->session.ticketSeen; + if (now < ssl->session.ticketSeen) + diff = (0xFFFFFFFFU - ssl->session.ticketSeen) + 1 + now; + else + diff = now - ssl->session.ticketSeen; diff -= current->ticketAge - ssl->session.ticketAdd; /* Check session and ticket age timeout. * Allow +/- 1000 milliseconds on ticket age. @@ -3517,19 +3990,25 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, diff - MAX_TICKET_AGE_SECS * 1000 > 1000) { /* Invalid difference, fallback to full handshake. */ ssl->options.resuming = 0; - /* Hash the rest of the ClientHello. */ - return HashRaw(ssl, input + helloSz - bindersLen, bindersLen); } + #ifndef WOLFSSL_PSK_ONE_ID /* Check whether resumption is possible based on suites in SSL and * ciphersuite in ticket. */ + if ((suite[0] != ssl->session.cipherSuite0) || + (suite[1] != ssl->session.cipherSuite)) { + current = current->next; + continue; + } + #else suite[0] = ssl->session.cipherSuite0; suite[1] = ssl->session.cipherSuite; if (!FindSuiteSSL(ssl, suite)) { current = current->next; continue; } + #endif #ifdef WOLFSSL_EARLY_DATA ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz; @@ -3552,7 +4031,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, ret = DeriveEarlySecret(ssl); if (ret != 0) return ret; - /* Derive the binder key to use to with HMAC. */ + /* Derive the binder key to use with HMAC. */ ret = DeriveBinderKeyResume(ssl, binderKey); if (ret != 0) return ret; @@ -3560,49 +4039,11 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, else #endif #ifndef NO_PSK - if ((ssl->options.server_psk_tls13_cb != NULL && - (ssl->arrays->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, - ssl->arrays->client_identity, ssl->arrays->psk_key, - MAX_PSK_KEY_LEN, &cipherName)) != 0 && - GetCipherSuiteFromName(cipherName, &cipherSuite0, - &cipherSuite, &cipherSuiteFlags) == 0) || - (ssl->options.server_psk_cb != NULL && - (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, - ssl->arrays->client_identity, ssl->arrays->psk_key, - MAX_PSK_KEY_LEN)) != 0)) { - if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) - return PSK_KEY_ERROR; - - /* Check whether PSK ciphersuite is in SSL. */ - suite[0] = cipherSuite0; - suite[1] = cipherSuite; - (void)cipherSuiteFlags; - if (!FindSuiteSSL(ssl, suite)) { - current = current->next; - continue; - } - - /* Default to ciphersuite if cb doesn't specify. */ - ssl->options.resuming = 0; - /* Don't send certificate request when using PSK. */ - ssl->options.verifyPeer = 0; - - /* PSK age is always zero. */ - if (current->ticketAge != ssl->session.ticketAdd) - return PSK_KEY_ERROR; - - /* Set PSK ciphersuite into SSL. */ - ssl->options.cipherSuite0 = cipherSuite0; - ssl->options.cipherSuite = cipherSuite; - ret = SetCipherSpecs(ssl); + if (FindPsk(ssl, current, suite, &ret)) { if (ret != 0) return ret; - /* Derive the early secret using the PSK. */ - ret = DeriveEarlySecret(ssl); - if (ret != 0) - return ret; - /* Derive the binder key to use to with HMAC. */ + /* Derive the binder key to use with HMAC. */ ret = DeriveBinderKey(ssl, binderKey); if (ret != 0) return ret; @@ -3614,6 +4055,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, continue; } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ssl->options.sendVerify = 0; /* Derive the Finished message secret. */ @@ -3636,14 +4078,13 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, current->chosen = 1; ext->resp = 1; break; + #endif } - /* Hash the rest of the ClientHello. */ - ret = HashRaw(ssl, input + helloSz - bindersLen, bindersLen); - if (ret != 0) - return ret; - - if (current == NULL) { +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (current == NULL) +#endif + { #ifdef WOLFSSL_PSK_ID_PROTECTION #ifndef NO_CERTS if (ssl->buffers.certChainCnt != 0) @@ -3655,67 +4096,173 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, #endif } -#ifdef WOLFSSL_EARLY_DATA - extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); - if (extEarlyData != NULL) { - if (ssl->earlyData != no_early_data && current == ext->data) { - extEarlyData->resp = 1; - - /* Derive early data decryption key. */ - ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, 1); - if (ret != 0) - return ret; - if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) - return ret; - - ssl->earlyData = process_early_data; - } - else - extEarlyData->resp = 0; - } -#endif - - /* Get the PSK key exchange modes the client wants to negotiate. */ - ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); - if (ext == NULL) - return MISSING_HANDSHAKE_DATA; - modes = ext->val; - -#ifdef HAVE_SUPPORTED_CURVES - ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); - /* Use (EC)DHE for forward-security if possible. */ - if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe && - ext != NULL) { - /* Only use named group used in last session. */ - ssl->namedGroup = ssl->session.namedGroup; - - /* Pick key share and Generate a new key if not present. */ - ret = TLSX_KeyShare_Establish(ssl); - if (ret == KEY_SHARE_ERROR) { - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; - ret = 0; - } - else if (ret < 0) - return ret; - - /* Send new public key to client. */ - ext->resp = 1; - } - else -#endif - { - if ((modes & (1 << PSK_KE)) == 0) - return PSK_KEY_ERROR; - ssl->options.noPskDheKe = 1; - ssl->arrays->preMasterSz = 0; - } - + *first = (current == ext->data); *usingPSK = 1; WOLFSSL_LEAVE("DoPreSharedKeys", ret); return ret; } + +/* Handle any Pre-Shared Key (PSK) extension. + * Must do this in ClientHello as it requires a hash of the truncated message. + * Don't know size of binders until Pre-Shared Key extension has been parsed. + * + * ssl SSL/TLS object. + * input ClientHello message. + * helloSz Size of the ClientHello message (including binders if present). + * clSuites Client's cipher suite list. + * usingPSK Indicates handshake is using Pre-Shared Keys. + */ +static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, + Suites* clSuites, int* usingPSK) +{ + int ret; + TLSX* ext; + word16 bindersLen; + int first = 0; +#ifndef WOLFSSL_PSK_ONE_ID + int i; + int j; +#else + byte suite[2]; +#endif + + WOLFSSL_ENTER("CheckPreSharedKeys"); + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) { +#ifdef WOLFSSL_EARLY_DATA + ssl->earlyData = no_early_data; +#endif + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz); + return ret; + } + + /* Extensions pushed on stack/list and PSK must be last. */ + if (ssl->extensions != ext) + return PSK_KEY_ERROR; + + /* Assume we are going to resume with a pre-shared key. */ + ssl->options.resuming = 1; + + /* Find the pre-shared key extension and calculate hash of truncated + * ClientHello for binders. + */ + ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello, &bindersLen); + if (ret < 0) + return ret; + + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz - bindersLen); + if (ret < 0) + return ret; + + /* Refine list for PSK processing. */ + RefineSuites(ssl, clSuites); + +#ifndef WOLFSSL_PSK_ONE_ID + if (!ssl->options.useClientOrder) { + /* Server order - server list has only common suites from refining. */ + for (i = 0; !*usingPSK && i < ssl->suites->suiteSz; i += 2) { + ret = DoPreSharedKeys(ssl, ssl->suites->suites + i, usingPSK, + &first); + if (ret != 0) { + return ret; + } + } + } + else { + /* Client order */ + for (j = 0; !*usingPSK && j < clSuites->suiteSz; j += 2) { + for (i = 0; !*usingPSK && i < ssl->suites->suiteSz; i += 2) { + ret = DoPreSharedKeys(ssl, ssl->suites->suites + i, usingPSK, + &first); + if (ret != 0) + return ret; + } + } + } +#else + ret = DoPreSharedKeys(ssl, suite, usingPSK, &first); + if (ret != 0) + return ret; +#endif + + /* Hash the rest of the ClientHello. */ + ret = HashRaw(ssl, input + helloSz - bindersLen, bindersLen); + if (ret != 0) + return ret; + + if (usingPSK) { + word16 modes; + #ifdef WOLFSSL_EARLY_DATA + TLSX* extEarlyData; + + extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extEarlyData != NULL) { + /* Check if accepting early data and first PSK. */ + if (ssl->earlyData != no_early_data && first) { + extEarlyData->resp = 1; + + /* Derive early data decryption key. */ + ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, + 1); + if (ret != 0) + return ret; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + ssl->earlyData = process_early_data; + } + else + extEarlyData->resp = 0; + } + #endif + + /* Get the PSK key exchange modes the client wants to negotiate. */ + ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (ext == NULL) + return MISSING_HANDSHAKE_DATA; + modes = ext->val; + + #ifdef HAVE_SUPPORTED_CURVES + ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + /* Use (EC)DHE for forward-security if possible. */ + if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe && + ext != NULL) { + /* Only use named group used in last session. */ + ssl->namedGroup = ssl->session.namedGroup; + + *usingPSK = 2; /* generate new ephemeral key */ + } + else + #endif + { + if ((modes & (1 << PSK_KE)) == 0) + return PSK_KEY_ERROR; + ssl->options.noPskDheKe = 1; + ssl->arrays->preMasterSz = 0; + + *usingPSK = 1; + } + } +#ifdef WOLFSSL_PSK_ID_PROTECTION + else { + #ifndef NO_CERTS + if (ssl->buffers.certChainCnt != 0) + return 0; + #endif + return BAD_BINDER; + } +#endif + + WOLFSSL_LEAVE("CheckPreSharedKeys", ret); + + return 0; +} #endif #if defined(WOLFSSL_SEND_HRR_COOKIE) @@ -3885,7 +4432,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) hrrIdx += 2; #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Reconstucted HelloRetryRequest"); + WOLFSSL_MSG("Reconstructed HelloRetryRequest"); WOLFSSL_BUFFER(hrr, hrrIdx); WOLFSSL_MSG("Cookie"); WOLFSSL_BUFFER(cookieData, cookie->len); @@ -3946,8 +4493,8 @@ static int DoTls13SupportedVersions(WOLFSSL* ssl, const byte* input, word32 i, return BUFFER_ERROR; /* Need to negotiate version first. */ - if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz, - client_hello, &foundVersion))) { + if ((ret = TLSX_ParseVersion(ssl, input + i, totalExtSz, client_hello, + &foundVersion))) { return ret; } } @@ -3969,160 +4516,216 @@ static int DoTls13SupportedVersions(WOLFSSL* ssl, const byte* input, word32 i, * helloSz The length of the current handshake message. * returns 0 on success and otherwise failure. */ + +typedef struct Dch13Args { + ProtocolVersion pv; + Suites* clSuites; + word32 idx; + word32 begin; + int usingPSK; +} Dch13Args; + +static void FreeDch13Args(WOLFSSL* ssl, void* pArgs) +{ + Dch13Args* args = (Dch13Args*)pArgs; + + (void)ssl; + + if (args->clSuites) { + XFREE(args->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES); + args->clSuites = NULL; + } +} + int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { - int ret = VERSION_ERROR; - byte b = 0; - ProtocolVersion pv; - Suites clSuites; - word32 i = *inOutIdx; - word32 begin = i; - word16 totalExtSz = 0; - int usingPSK = 0; - byte sessIdSz = 0; - int wantDowngrade = 0; + int ret; +#ifdef WOLFSSL_ASYNC_CRYPT + Dch13Args* args = (Dch13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dch13Args args[1]; +#endif WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); WOLFSSL_ENTER("DoTls13ClientHello"); - XMEMSET(&pv, 0, sizeof(ProtocolVersion)); - XMEMSET(&clSuites, 0, sizeof(Suites)); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } + else +#endif + { + /* Reset state */ + ret = VERSION_ERROR; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dch13Args)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDch13Args; + #endif + } + + switch (ssl->options.asyncState) { + case TLS_ASYNC_BEGIN: + { + byte b; + byte sessIdSz; + int wantDowngrade = 0; + word16 totalExtSz = 0; #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); #endif + args->idx = *inOutIdx; + args->begin = args->idx; + /* protocol version, random and session id length check */ - if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) - return BUFFER_ERROR; + if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) { + ERROR_OUT(BUFFER_ERROR, exit_dch); + } /* Protocol version */ - XMEMCPY(&pv, input + i, OPAQUE16_LEN); - ssl->chVersion = pv; /* store */ - i += OPAQUE16_LEN; - if (pv.major < SSLv3_MAJOR) { + XMEMCPY(&args->pv, input + args->idx, OPAQUE16_LEN); + ssl->chVersion = args->pv; /* store */ + args->idx += OPAQUE16_LEN; + if (args->pv.major < SSLv3_MAJOR) { WOLFSSL_MSG("Legacy version field contains unsupported value"); #ifdef WOLFSSL_MYSQL_COMPATIBLE SendAlert(ssl, alert_fatal, wc_protocol_version); #else SendAlert(ssl, alert_fatal, protocol_version); #endif - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); } + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ - if (pv.major > SSLv3_MAJOR || (pv.major == SSLv3_MAJOR && - pv.minor >= TLSv1_3_MINOR)) { - pv.major = SSLv3_MAJOR; - pv.minor = TLSv1_2_MINOR; + if (args->pv.major > SSLv3_MAJOR || (args->pv.major == SSLv3_MAJOR && + args->pv.minor >= TLSv1_3_MINOR)) { + args->pv.major = SSLv3_MAJOR; + args->pv.minor = TLSv1_2_MINOR; wantDowngrade = 1; - ssl->version.minor = pv.minor; + ssl->version.minor = args->pv.minor; } /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */ - else if (pv.major == SSLv3_MAJOR && pv.minor < TLSv1_2_MINOR) { + else if (args->pv.major == SSLv3_MAJOR && args->pv.minor < TLSv1_2_MINOR) { wantDowngrade = 1; - ssl->version.minor = pv.minor; + ssl->version.minor = args->pv.minor; } else { - ret = DoTls13SupportedVersions(ssl, input + begin, i - begin, helloSz, - &wantDowngrade); + ret = DoTls13SupportedVersions(ssl, input + args->begin, + args->idx - args->begin, helloSz, &wantDowngrade); if (ret < 0) - return ret; + goto exit_dch; } if (wantDowngrade) { #ifndef WOLFSSL_NO_TLS12 if (!ssl->options.downgrade) { WOLFSSL_MSG("Client trying to connect with lesser version than " "TLS v1.3"); - return VERSION_ERROR; + ERROR_OUT(VERSION_ERROR, exit_dch); } - if (pv.minor < ssl->options.minDowngrade) - return VERSION_ERROR; + if (args->pv.minor < ssl->options.minDowngrade) + ERROR_OUT(VERSION_ERROR, exit_dch); - if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) - return ret; - return DoClientHello(ssl, input, inOutIdx, helloSz); + ret = HashInput(ssl, input + args->begin, helloSz); + if (ret == 0) { + ret = DoClientHello(ssl, input, inOutIdx, helloSz); + } + goto exit_dch; #else WOLFSSL_MSG("Client trying to connect with lesser version than " "TLS v1.3"); - return VERSION_ERROR; + ERROR_OUT(VERSION_ERROR, exit_dch); #endif } /* From here on we are a TLS 1.3 ClientHello. */ /* Client random */ - XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); - i += RAN_LEN; + XMEMCPY(ssl->arrays->clientRandom, input + args->idx, RAN_LEN); + args->idx += RAN_LEN; #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("client random"); WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); #endif - sessIdSz = input[i++]; + sessIdSz = input[args->idx++]; if (sessIdSz != ID_LEN && sessIdSz != 0) - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); - if (sessIdSz + i > helloSz) { - return BUFFER_ERROR; + if (sessIdSz + args->idx > helloSz) { + ERROR_OUT(BUFFER_ERROR, exit_dch); } ssl->session.sessionIDSz = sessIdSz; if (sessIdSz == ID_LEN) { - XMEMCPY(ssl->session.sessionID, input + i, sessIdSz); - i += ID_LEN; + XMEMCPY(ssl->session.sessionID, input + args->idx, sessIdSz); + args->idx += ID_LEN; + } + + args->clSuites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (args->clSuites == NULL) { + ERROR_OUT(MEMORY_E, exit_dch); } /* Cipher suites */ - if ((i - begin) + OPAQUE16_LEN > helloSz) - return BUFFER_ERROR; - ato16(&input[i], &clSuites.suiteSz); - i += OPAQUE16_LEN; + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + ato16(&input[args->idx], &args->clSuites->suiteSz); + args->idx += OPAQUE16_LEN; /* suites and compression length check */ - if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) - return BUFFER_ERROR; - if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) - return BUFFER_ERROR; - XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); - i += clSuites.suiteSz; - clSuites.hashSigAlgoSz = 0; + if ((args->idx - args->begin) + args->clSuites->suiteSz + OPAQUE8_LEN > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + if (args->clSuites->suiteSz > WOLFSSL_MAX_SUITE_SZ) + ERROR_OUT(BUFFER_ERROR, exit_dch); + XMEMCPY(args->clSuites->suites, input + args->idx, args->clSuites->suiteSz); + args->idx += args->clSuites->suiteSz; + args->clSuites->hashSigAlgoSz = 0; /* Compression */ - b = input[i++]; - if ((i - begin) + b > helloSz) - return BUFFER_ERROR; + b = input[args->idx++]; + if ((args->idx - args->begin) + b > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); if (b != COMP_LEN) { WOLFSSL_MSG("Must be one compression type in list"); - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); } - b = input[i++]; + b = input[args->idx++]; if (b != NO_COMPRESSION) { WOLFSSL_MSG("Must be no compression type in list"); - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); } /* Extensions */ - if ((i - begin) == helloSz) - return BUFFER_ERROR; - if ((i - begin) + OPAQUE16_LEN > helloSz) - return BUFFER_ERROR; + if ((args->idx - args->begin) == helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); - ato16(&input[i], &totalExtSz); - i += OPAQUE16_LEN; - if ((i - begin) + totalExtSz > helloSz) - return BUFFER_ERROR; + ato16(&input[args->idx], &totalExtSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + totalExtSz > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); /* Auto populate extensions supported unless user defined. */ if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) - return ret; + goto exit_dch; /* Parse extensions */ - if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, - &clSuites))) { - return ret; + if ((ret = TLSX_Parse(ssl, input + args->idx, totalExtSz, client_hello, + args->clSuites))) { + goto exit_dch; } #ifdef HAVE_SNI @@ -4131,13 +4734,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.side = WOLFSSL_SERVER_END; #endif - i += totalExtSz; - *inOutIdx = i; - - ssl->options.sendVerify = SEND_CERT; - - ssl->options.clientState = CLIENT_HELLO_COMPLETE; + args->idx += totalExtSz; ssl->options.haveSessionId = 1; + ssl->options.sendVerify = SEND_CERT; #if defined(WOLFSSL_SEND_HRR_COOKIE) if (ssl->options.sendCookie && @@ -4145,59 +4744,103 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, TLSX* ext; if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) - return HRR_COOKIE_ERROR; + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); + /* Ensure the cookie came from client and isn't the one in the - * response - HelloRetryRequest. - */ + * response - HelloRetryRequest. + */ if (ext->resp == 1) - return HRR_COOKIE_ERROR; + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); if (ret != 0) - return ret; + goto exit_dch; } #endif #if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ defined(HAVE_TLS_EXTENSIONS) - if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY) != NULL) { - /* Refine list for PSK processing. */ - RefineSuites(ssl, &clSuites); + ret = CheckPreSharedKeys(ssl, input + args->begin, helloSz, args->clSuites, + &args->usingPSK); + if (ret != 0) + goto exit_dch; +#else + if ((ret = HashInput(ssl, input + args->begin, helloSz)) != 0) + goto exit_dch; +#endif - /* Process the Pre-Shared Key extension if present. */ - ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); - if (ret != 0) - return ret; - } - else +#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ + defined(HAVE_TLS_EXTENSIONS) + if (!args->usingPSK) #endif { -#ifdef WOLFSSL_EARLY_DATA - ssl->earlyData = no_early_data; -#endif - if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) - return ret; + /* Not using PSK so don't require no KE. */ + ssl->options.noPskDheKe = 0; - } - - if (!usingPSK) { #ifndef NO_CERTS if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { WOLFSSL_MSG("Client did not send a KeyShare extension"); SendAlert(ssl, alert_fatal, missing_extension); - return INCOMPLETE_DATA; + ERROR_OUT(INCOMPLETE_DATA, exit_dch); } if (TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS) == NULL) { WOLFSSL_MSG("Client did not send a SignatureAlgorithms extension"); SendAlert(ssl, alert_fatal, missing_extension); - return INCOMPLETE_DATA; + ERROR_OUT(INCOMPLETE_DATA, exit_dch); } +#else + ERROR_OUT(INVALID_PARAMETER, exit_dch); +#endif + } - if ((ret = MatchSuite(ssl, &clSuites)) < 0) { + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + case TLS_ASYNC_DO: + { +#ifndef NO_CERTS + if (!args->usingPSK) { + if ((ret = MatchSuite(ssl, args->clSuites)) < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_dch; + #endif WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); SendAlert(ssl, alert_fatal, handshake_failure); - return ret; + goto exit_dch; } + } + else +#endif +#ifdef HAVE_SUPPORTED_CURVES + if (args->usingPSK == 2) { + /* Pick key share and Generate a new key if not present. */ + int doHelloRetry = 0; + ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry); + if (doHelloRetry) { + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + if (ret != WC_PENDING_E) + ret = 0; /* for hello_retry return 0 */ + } + if (ret != 0) + goto exit_dch; + } +#endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + *inOutIdx = args->idx; + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + + if (!args->usingPSK) { +#ifndef NO_CERTS #ifdef HAVE_NULL_CIPHER if (ssl->options.cipherSuite0 == ECC_BYTE && (ssl->options.cipherSuite == TLS_SHA256_SHA256 || @@ -4211,7 +4854,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Negotiated ciphersuite from lesser version than " "TLS v1.3"); SendAlert(ssl, alert_fatal, handshake_failure); - return VERSION_ERROR; + ERROR_OUT(VERSION_ERROR, exit_dch); } #ifdef HAVE_SESSION_TICKET @@ -4223,13 +4866,27 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Derive early secret for handshake secret. */ if ((ret = DeriveEarlySecret(ssl)) != 0) - return ret; -#else - ret = INVALID_PARAMETER; -#endif + goto exit_dch; +#endif /* !NO_CERTS */ } + break; + } /* case TLS_ASYNC_FINALIZE */ + default: + ret = INPUT_CASE_ERROR; + } /* switch (ssl->options.asyncState) */ + +exit_dch: WOLFSSL_LEAVE("DoTls13ClientHello", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ssl->msgsReceived.got_client_hello = 0; + return ret; + } +#endif + + FreeDch13Args(ssl, args); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); return ret; @@ -4312,6 +4969,11 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) /* Chosen cipher suite */ output[idx++] = ssl->options.cipherSuite0; output[idx++] = ssl->options.cipherSuite; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Chosen cipher suite:"); + WOLFSSL_MSG(GetCipherNameInternal(ssl->options.cipherSuite0, + ssl->options.cipherSuite)); +#endif /* Compression not supported in TLS v1.3. */ output[idx++] = 0; @@ -4584,6 +5246,8 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[1] = hashAlgo; break; #endif + default: + break; } } @@ -4665,6 +5329,8 @@ static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash) ret = WC_SHA512_DIGEST_SIZE; break; #endif /* WOLFSSL_TLS13_SHA512 */ + default: + break; } return ret; } @@ -4845,6 +5511,8 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) hashSz = WC_SHA512_DIGEST_SIZE; break; #endif + default: + break; } if (ret != 0) @@ -4991,7 +5659,14 @@ static int SendTls13Certificate(WOLFSSL* ssl) word32 offset = OPAQUE16_LEN; byte* p = NULL; byte certReqCtxLen = 0; +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH byte* certReqCtx = NULL; +#endif + +#ifdef OPENSSL_EXTRA + WOLFSSL_X509* x509 = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; +#endif WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); WOLFSSL_ENTER("SendTls13Certificate"); @@ -5003,6 +5678,22 @@ static int SendTls13Certificate(WOLFSSL* ssl) } #endif +#ifdef OPENSSL_EXTRA + /* call client cert callback if no cert has been loaded */ + if ((ssl->ctx->CBClientCert != NULL) && + (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer)) { + ret = ssl->ctx->CBClientCert(ssl, &x509, &pkey); + if (ret == 1) { + if ((wolfSSL_CTX_use_certificate(ssl->ctx, x509) == WOLFSSL_SUCCESS) && + (wolfSSL_CTX_use_PrivateKey(ssl->ctx, pkey) == WOLFSSL_SUCCESS)) { + ssl->options.sendVerify = SEND_CERT; + } + wolfSSL_X509_free(x509); + wolfSSL_EVP_PKEY_free(pkey); + } + } +#endif + if (ssl->options.sendVerify == SEND_BLANK_CERT) { certSz = 0; certChainSz = 0; @@ -5100,10 +5791,12 @@ static int SendTls13Certificate(WOLFSSL* ssl) /* Request context. */ output[i++] = certReqCtxLen; + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH if (certReqCtxLen > 0) { XMEMCPY(output + i, certReqCtx, certReqCtxLen); i += certReqCtxLen; } + #endif length -= OPAQUE8_LEN + certReqCtxLen; fragSz -= OPAQUE8_LEN + certReqCtxLen; /* Certificate list length. */ @@ -5989,11 +6682,13 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ssl->options.serverState = SERVER_CERT_VERIFY_COMPLETE; #endif } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; case TLS_ASYNC_END: { break; } + default: ret = INPUT_CASE_ERROR; } /* switch(ssl->options.asyncState) */ @@ -7841,6 +8536,7 @@ int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret, * ssl The SSL/TLS object. * group The named group. * returns 0 on success, otherwise failure. + * for async can return WC_PENDING_E and should be called again */ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) { @@ -7849,6 +8545,15 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) if (ssl == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, NULL); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } +#endif + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); if (ret != 0) return ret; @@ -7972,6 +8677,24 @@ int wolfSSL_update_keys(WOLFSSL* ssl) return ret; } +/* Whether a response is waiting for key update request. + * + * ssl The SSL/TLS object. + * required 0 when no key update response required. + * 1 when no key update response required. + * return 0 on success. + * return BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3 + */ +int wolfSSL_key_update_response(WOLFSSL* ssl, int* required) +{ + if (required == NULL || ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + *required = ssl->keys.updateResponseReq; + + return 0; +} + #if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) /* Allow post-handshake authentication in TLS v1.3 connections. * @@ -8114,12 +8837,12 @@ int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) for (i = 0; i < count; i++) { /* Call to wolfSSL_CTX_UseSupportedCurve also checks if input groups * are valid */ - if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, groups[i])) + if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, (word16)groups[i])) != WOLFSSL_SUCCESS) { TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); return ret; } - ctx->group[i] = groups[i]; + ctx->group[i] = (word16)groups[i]; } ctx->numGroups = (byte)count; @@ -8149,12 +8872,12 @@ int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) for (i = 0; i < count; i++) { /* Call to wolfSSL_UseSupportedCurve also checks if input groups * are valid */ - if ((ret = wolfSSL_UseSupportedCurve(ssl, groups[i])) + if ((ret = wolfSSL_UseSupportedCurve(ssl, (word16)groups[i])) != WOLFSSL_SUCCESS) { TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); return ret; } - ssl->group[i] = groups[i]; + ssl->group[i] = (word16)groups[i]; } ssl->numGroups = (byte)count; @@ -8163,6 +8886,63 @@ int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) #endif /* HAVE_SUPPORTED_CURVES */ #ifndef NO_PSK +/* Set the PSK callback, that is passed the cipher suite, for a client to use + * against context object. + * + * @param [in, out] ctx SSL/TLS context object. + * @param [in] cb Client PSK callback passed a cipher suite. + */ +void wolfSSL_CTX_set_psk_client_cs_callback(WOLFSSL_CTX* ctx, + wc_psk_client_cs_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_client_cs_callback"); + + if (ctx == NULL) + return; + + ctx->havePSK = 1; + ctx->client_psk_cs_cb = cb; +} + +/* Set the PSK callback, that is passed the cipher suite, for a client to use + * against SSL object. + * + * @param [in, out] ssl SSL/TLS object. + * @param [in] cb Client PSK callback passed a cipher suite. + */ +void wolfSSL_set_psk_client_cs_callback(WOLFSSL* ssl, + wc_psk_client_cs_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_client_cs_callback"); + + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.client_psk_cs_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); +} + +/* Set the PSK callback that returns the cipher suite for a client to use + * against context object. + * + * @param [in, out] ctx SSL/TLS context object. + * @param [in] cb Client PSK callback returning cipher suite. + */ void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx, wc_psk_client_tls13_callback cb) { @@ -8175,7 +8955,12 @@ void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx, ctx->client_psk_tls13_cb = cb; } - +/* Set the PSK callback that returns the cipher suite for a client to use + * against SSL object. + * + * @param [in, out] ssl SSL/TLS object. + * @param [in] cb Client PSK callback returning cipher suite. + */ void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, wc_psk_client_tls13_callback cb) { @@ -8199,10 +8984,16 @@ void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } - +/* Set the PSK callback that returns the cipher suite for a server to use + * against context object. + * + * @param [in, out] ctx SSL/TLS context object. + * @param [in] cb Server PSK callback returning cipher suite. + */ void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx, wc_psk_server_tls13_callback cb) { @@ -8213,7 +9004,12 @@ void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx, ctx->server_psk_tls13_cb = cb; } - +/* Set the PSK callback that returns the cipher suite for a server to use + * against SSL object. + * + * @param [in, out] ssl SSL/TLS object. + * @param [in] cb Server PSK callback returning cipher suite. + */ void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, wc_psk_server_tls13_callback cb) { @@ -8236,9 +9032,41 @@ void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); + ssl->options.haveStaticECC, ssl->options.haveAnon, + ssl->options.side); } -#endif + +/* Get name of first supported cipher suite that uses the hash indicated. + * + * @param [in] ssl SSL/TLS object. + * @param [in] hash Name of hash algorithm. e.g. "SHA256", "SHA384" + * @return Name of cipher suite. + * @return NULL on failure. + */ +const char* wolfSSL_get_cipher_name_by_hash(WOLFSSL* ssl, const char* hash) +{ + const char* name = NULL; + byte mac = no_mac; + int i; + + if (XSTRNCMP(hash, "SHA256", 6) == 0) { + mac = sha256_mac; + } + else if (XSTRNCMP(hash, "SHA384", 6) == 0) { + mac = sha384_mac; + } + if (mac != no_mac) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + if (SuiteMac(ssl->suites->suites + i) == mac) { + name = GetCipherNameInternal(ssl->suites->suites[i + 0], + ssl->suites->suites[i + 1]); + break; + } + } + } + return name; +} +#endif /* !NO_PSK */ #ifndef NO_WOLFSSL_SERVER @@ -8255,26 +9083,42 @@ void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, */ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) { +#if !defined(NO_CERTS) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) word16 havePSK = 0; +#endif WOLFSSL_ENTER("SSL_accept_TLSv13()"); #ifdef HAVE_ERRNO_H errno = 0; #endif -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#if !defined(NO_CERTS) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) havePSK = ssl->options.havePSK; #endif - (void)havePSK; if (ssl->options.side != WOLFSSL_SERVER_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); return WOLFSSL_FATAL_ERROR; } +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + if (ssl->AcceptFilter) { + wolfSSL_netfilter_decision_t res; + if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) == + WOLFSSL_SUCCESS) && + (res == WOLFSSL_NETFILTER_REJECT)) { + WOLFSSL_ERROR(ssl->error = SOCKET_FILTERED_E); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + #ifndef NO_CERTS /* allow no private key if using PK callbacks and CB is set */ - if (!havePSK) { +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (!havePSK) +#endif + { if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) { @@ -8295,7 +9139,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) return WOLFSSL_FATAL_ERROR; } } -#endif +#endif /* NO_CERTS */ if (ssl->buffers.outputBuffer.length > 0 #ifdef WOLFSSL_ASYNC_CRYPT @@ -8636,11 +9480,25 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) ret = wolfSSL_connect_TLSv13(ssl); if (ret != WOLFSSL_SUCCESS) return WOLFSSL_FATAL_ERROR; + /* on client side, status is set to rejected */ + /* until sever accepts the early data extension. */ + ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_REJECTED; } if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) { +#ifdef OPENSSL_EXTRA + /* when processed early data exceeds max size */ + if (ssl->session.maxEarlyDataSz > 0 && + (ssl->earlyDataSz + sz > ssl->session.maxEarlyDataSz)) { + ssl->error = TOO_MUCH_EARLY_DATA; + return WOLFSSL_FATAL_ERROR; + } +#endif ret = SendData(ssl, data, sz); - if (ret > 0) + if (ret > 0) { *outSz = ret; + /* store amount of processed early data from client */ + ssl->earlyDataSz += ret; + } } #else return SIDE_ERROR; @@ -8704,6 +9562,21 @@ int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) ret = WOLFSSL_FATAL_ERROR; return ret; } + +/* Returns early data status + * + * ssl The SSL/TLS object. + * returns WOLFSSL_EARLY_DATA_ACCEPTED if the data was accepted + * WOLFSSL_EARLY_DATA_REJECTED if the data was rejected + * WOLFSSL_EARLY_DATA_NOT_SENT if no early data was sent + */ +int wolfSSL_get_early_data_status(const WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + return ssl->earlyDataStatus; +} #endif #ifdef HAVE_SECRET_CALLBACK diff --git a/src/wolfio.c b/src/wolfio.c index 27b335c66..4345d7064 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -1,6 +1,6 @@ /* wolfio.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -47,7 +47,7 @@ Possible IO enable options: * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off allows user to define their own using wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend - * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: off + * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: on * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off (unless HAVE_OCSP or HAVE_CRL_IO defined) * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off @@ -106,8 +106,38 @@ static WC_INLINE int wolfSSL_LastError(int err) #endif } -#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ +static int TranslateIoError(int err) +{ + if (err > 0) + return err; + err = wolfSSL_LastError(err); +#if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN + if ((err == SOCKET_EWOULDBLOCK) || (err == SOCKET_EAGAIN)) +#else + if (err == SOCKET_EWOULDBLOCK) +#endif + { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNABORTED) { + WOLFSSL_MSG("\tConnection aborted"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; +} +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ #ifdef OPENSSL_EXTRA #ifndef NO_BIO @@ -133,31 +163,25 @@ int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx) return WOLFSSL_CBIO_ERR_GENERAL; } - if (ssl->biord->method && ssl->biord->method->readCb) { - WOLFSSL_MSG("Calling custom biord"); - recvd = ssl->biord->method->readCb(ssl->biord, buf, sz); - if (recvd < 0 && recvd != WOLFSSL_CBIO_ERR_WANT_READ) - return WOLFSSL_CBIO_ERR_GENERAL; - return recvd; - } - - switch (ssl->biord->type) { - case WOLFSSL_BIO_MEMORY: - case WOLFSSL_BIO_BIO: - if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) { - WOLFSSL_MSG("BIO want read"); - return WOLFSSL_CBIO_ERR_WANT_READ; + recvd = wolfSSL_BIO_read(ssl->biord, buf, sz); + if (recvd <= 0) { + if (wolfSSL_BIO_supports_pending(ssl->biord) && + wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else if (ssl->biord->type == WOLFSSL_BIO_SOCKET) { + if (recvd == 0) { + WOLFSSL_MSG("BioReceive connection closed"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; } - recvd = wolfSSL_BIO_read(ssl->biord, buf, sz); - if (recvd <= 0) { - WOLFSSL_MSG("BIO general error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - break; + #ifdef USE_WOLFSSL_IO + recvd = TranslateIoError(recvd); + #endif + return recvd; + } - default: - WOLFSSL_MSG("This BIO type is unknown / unsupported"); - return WOLFSSL_CBIO_ERR_GENERAL; + WOLFSSL_MSG("BIO general error"); + return WOLFSSL_CBIO_ERR_GENERAL; } (void)ctx; @@ -186,27 +210,15 @@ int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) return WOLFSSL_CBIO_ERR_GENERAL; } - if (ssl->biowr->method && ssl->biowr->method->writeCb) { - WOLFSSL_MSG("Calling custom biowr"); - sent = ssl->biowr->method->writeCb(ssl->biowr, buf, sz); - if ((sent < 0) && (sent != WOLFSSL_CBIO_ERR_WANT_WRITE)) { - return WOLFSSL_CBIO_ERR_GENERAL; + sent = wolfSSL_BIO_write(ssl->biowr, buf, sz); + if (sent < 0) { + if (ssl->biowr->type == WOLFSSL_BIO_SOCKET) { + #ifdef USE_WOLFSSL_IO + sent = TranslateIoError(sent); + #endif + return sent; } - return sent; - } - - switch (ssl->biowr->type) { - case WOLFSSL_BIO_MEMORY: - case WOLFSSL_BIO_BIO: - sent = wolfSSL_BIO_write(ssl->biowr, buf, sz); - if (sent < 0) { - return WOLFSSL_CBIO_ERR_GENERAL; - } - break; - - default: - WOLFSSL_MSG("This BIO type is unknown / unsupported"); - return WOLFSSL_CBIO_ERR_GENERAL; + return WOLFSSL_CBIO_ERR_GENERAL; } (void)ctx; @@ -232,29 +244,8 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); if (recvd < 0) { - int err = wolfSSL_LastError(recvd); WOLFSSL_MSG("Embed Receive error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG("\tWould block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNABORTED) { - WOLFSSL_MSG("\tConnection aborted"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } + return TranslateIoError(recvd); } else if (recvd == 0) { WOLFSSL_MSG("Embed receive connection closed"); @@ -283,29 +274,8 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) sent = wolfIO_Send(sd, buf, sz, ssl->wflags); if (sent < 0) { - int err = wolfSSL_LastError(sent); WOLFSSL_MSG("Embed Send error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG("\tWould Block"); - return WOLFSSL_CBIO_ERR_WANT_WRITE; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG("\tSocket EPIPE"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } + return TranslateIoError(sent); } return sent; @@ -327,7 +297,6 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) { WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; int recvd; - int err; int sd = dtlsCtx->rfd; int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); SOCKADDR_S peer; @@ -372,35 +341,13 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = TranslateReturnCode(recvd, sd); if (recvd < 0) { - err = wolfSSL_LastError(recvd); WOLFSSL_MSG("Embed Receive From error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - if (wolfSSL_dtls_get_using_nonblock(ssl)) { - WOLFSSL_MSG("\tWould block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tSocket timeout"); - return WOLFSSL_CBIO_ERR_TIMEOUT; - } - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG("\tConnection refused"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; + recvd = TranslateIoError(recvd); + if (recvd == WOLFSSL_CBIO_ERR_WANT_READ && + !wolfSSL_dtls_get_using_nonblock(ssl)) { + recvd = WOLFSSL_CBIO_ERR_TIMEOUT; } + return recvd; } else { if (dtlsCtx->peer.sz > 0 @@ -426,7 +373,6 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; int sd = dtlsCtx->wfd; int sent; - int err; WOLFSSL_ENTER("EmbedSendTo()"); @@ -437,29 +383,8 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) sent = TranslateReturnCode(sent, sd); if (sent < 0) { - err = wolfSSL_LastError(sent); WOLFSSL_MSG("Embed Send To error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG("\tWould Block"); - return WOLFSSL_CBIO_ERR_WANT_WRITE; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG("\tSocket EPIPE"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } + return TranslateIoError(sent); } return sent; @@ -475,7 +400,6 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) { WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; int recvd; - int err; int sd = dtlsCtx->rfd; WOLFSSL_ENTER("EmbedReceiveFromMcast()"); @@ -485,35 +409,13 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = TranslateReturnCode(recvd, sd); if (recvd < 0) { - err = wolfSSL_LastError(recvd); WOLFSSL_MSG("Embed Receive From error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - if (wolfSSL_dtls_get_using_nonblock(ssl)) { - WOLFSSL_MSG("\tWould block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tSocket timeout"); - return WOLFSSL_CBIO_ERR_TIMEOUT; - } - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG("\tConnection refused"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; + recvd = TranslateIoError(recvd); + if (recvd == WOLFSSL_CBIO_ERR_WANT_READ && + !wolfSSL_dtls_get_using_nonblock(ssl)) { + recvd = WOLFSSL_CBIO_ERR_TIMEOUT; } + return recvd; } return recvd; @@ -770,6 +672,11 @@ int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) nfds = (int)sockfd + 1; #endif + if ((sockfd < 0) || (sockfd >= FD_SETSIZE)) { + WOLFSSL_MSG("socket fd out of FDSET range"); + return -1; + } + FD_ZERO(&rfds); FD_SET(sockfd, &rfds); wfds = rfds; @@ -2253,7 +2160,7 @@ void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_so if (ssl && ssl->mnCtx) { Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx; mynewt_ctx->mnSocket = mnSocket; - memcpy(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in)); + XMEMCPY(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in)); mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs); } } diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index af6bbe56d..2816b179f 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -1,6 +1,6 @@ /* snifftest.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/swig/wolfssl.i b/swig/wolfssl.i index 2571cda3f..57c4ee7c6 100644 --- a/swig/wolfssl.i +++ b/swig/wolfssl.i @@ -1,6 +1,6 @@ /* wolfssl.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/swig/wolfssl_adds.c b/swig/wolfssl_adds.c index fd055ff80..74356eda7 100644 --- a/swig/wolfssl_adds.c +++ b/swig/wolfssl_adds.c @@ -1,6 +1,6 @@ /* wolfssl_adds.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/tests/api.c b/tests/api.c index 424d82938..c03837ed8 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1,6 +1,6 @@ /* api.c API unit tests * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,6 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/* For AES-CBC, input lengths can optionally be validated to be a + * multiple of the block size, by defining WOLFSSL_AES_CBC_LENGTH_CHECKS, + * also available via the configure option --enable-aescbc-length-checks. + */ + /*----------------------------------------------------------------------------* | Includes @@ -307,6 +312,7 @@ #include #include #include + #include #ifdef OPENSSL_ALL #include #include @@ -422,7 +428,12 @@ enum { TESTING_ECC = 2 }; +#ifdef WOLFSSL_QNX_CAAM +#include +static int devId = WOLFSSL_CAAM_DEVID; +#else static int devId = INVALID_DEVID; +#endif /*----------------------------------------------------------------------------* @@ -471,7 +482,7 @@ static int test_wolfCrypt_Init(void) /*----------------------------------------------------------------------------* | Platform dependent function test *----------------------------------------------------------------------------*/ - static int test_fileAccess() + static int test_fileAccess(void) { #if defined(WOLFSSL_TEST_PLATFORMDEPEND) && !defined(NO_FILESYSTEM) const char *fname[] = { @@ -953,17 +964,20 @@ static void test_wolfSSL_CTX_load_verify_locations(void) AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, NULL), WOLFSSL_FAILURE); /* invalid ca file */ - AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, NULL), WOLFSSL_BAD_FILE); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, NULL), + WS_RETURN_CODE(WOLFSSL_BAD_FILE,WOLFSSL_FAILURE)); #if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) /* invalid path */ - AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, bogusFile), BAD_PATH_ERROR); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, bogusFile), + WS_RETURN_CODE(BAD_PATH_ERROR,WOLFSSL_FAILURE)); #endif /* load ca cert */ #ifdef NO_RSA - AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), ASN_UNKNOWN_OID_E); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), + WS_RETURN_CODE(ASN_UNKNOWN_OID_E,WOLFSSL_FAILURE)); #else /* Skip the following test without RSA certs. */ AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), WOLFSSL_SUCCESS); @@ -1091,6 +1105,195 @@ static int test_cm_load_ca_file(const char* ca_cert_file) } #endif /* !NO_FILESYSTEM && !NO_CERTS */ +static void test_wolfSSL_CertManagerCheckOCSPResponse(void) +{ +#ifdef HAVE_OCSP +/* Need one of these for wolfSSL_OCSP_REQUEST_new. */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_APACHE_HTTPD) || \ + defined(HAVE_LIGHTY) + WOLFSSL_CERT_MANAGER* cm = NULL; + /* Raw OCSP response bytes captured using the following setup: + * - Run responder with + * openssl ocsp -port 9999 -ndays 9999 + * -index certs/ocsp/index-intermediate1-ca-issued-certs.txt + * -rsigner certs/ocsp/ocsp-responder-cert.pem + * -rkey certs/ocsp/ocsp-responder-key.pem + * -CA certs/ocsp/intermediate1-ca-cert.pem + * - Run client with + * openssl ocsp -host 127.0.0.1:9999 -respout resp.out + * -issuer certs/ocsp/intermediate1-ca-cert.pem + * -cert certs/ocsp/server1-cert.pem + * -CAfile certs/ocsp/root-ca-cert.pem -noverify + * - Copy raw response from Wireshark. + */ + byte response[] = { + 0x30, 0x82, 0x07, 0x40, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x07, 0x39, 0x30, 0x82, 0x07, 0x35, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x07, 0x26, 0x30, 0x82, + 0x07, 0x22, 0x30, 0x82, 0x01, 0x40, 0xa1, 0x81, 0xa1, 0x30, 0x81, 0x9e, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, + 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x77, + 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, + 0x30, 0x35, 0x30, 0x33, 0x32, 0x31, 0x34, 0x37, 0x31, 0x30, 0x5a, 0x30, 0x64, 0x30, 0x62, 0x30, + 0x3a, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x71, 0x4d, + 0x82, 0x23, 0x40, 0x59, 0xc0, 0x96, 0xa1, 0x37, 0x43, 0xfa, 0x31, 0xdb, 0xba, 0xb1, 0x43, 0x18, + 0xda, 0x04, 0x04, 0x14, 0x83, 0xc6, 0x3a, 0x89, 0x2c, 0x81, 0xf4, 0x02, 0xd7, 0x9d, 0x4c, 0xe2, + 0x2a, 0xc0, 0x71, 0x82, 0x64, 0x44, 0xda, 0x0e, 0x02, 0x01, 0x05, 0x80, 0x00, 0x18, 0x0f, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x35, 0x30, 0x33, 0x32, 0x31, 0x34, 0x37, 0x31, 0x30, 0x5a, 0xa0, 0x11, + 0x18, 0x0f, 0x32, 0x30, 0x34, 0x38, 0x30, 0x39, 0x31, 0x37, 0x32, 0x31, 0x34, 0x37, 0x31, 0x30, + 0x5a, 0xa1, 0x23, 0x30, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, + 0x01, 0x02, 0x04, 0x12, 0x04, 0x10, 0x38, 0x31, 0x60, 0x99, 0xc8, 0x05, 0x09, 0x68, 0x1c, 0x33, + 0x49, 0xea, 0x45, 0x26, 0x2f, 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4d, 0x58, 0xcc, 0x69, 0x42, 0xe2, + 0x9e, 0x64, 0xf6, 0x57, 0xce, 0xcb, 0x5f, 0x14, 0xaf, 0x08, 0x6c, 0xc1, 0x52, 0x7a, 0x40, 0x0a, + 0xfd, 0xb6, 0xce, 0xbb, 0x40, 0xf4, 0xb9, 0xa5, 0x88, 0xc7, 0xf3, 0x42, 0x9f, 0xa9, 0x94, 0xbe, + 0x6e, 0x7e, 0x09, 0x30, 0x9d, 0x0e, 0x10, 0x6f, 0x9c, 0xd9, 0x4c, 0x71, 0x81, 0x41, 0x64, 0x95, + 0xf5, 0x85, 0x77, 0x94, 0x81, 0x61, 0x88, 0xc8, 0x0b, 0x50, 0xbb, 0x37, 0xc8, 0x86, 0x76, 0xd8, + 0xa2, 0xed, 0x66, 0x34, 0xfb, 0xe4, 0xe7, 0x09, 0x8c, 0xf5, 0xb5, 0x85, 0xd0, 0x4b, 0xb5, 0xe6, + 0x23, 0x62, 0xc3, 0xd0, 0xef, 0xf7, 0x42, 0x89, 0x02, 0x80, 0x64, 0xc9, 0xed, 0xdd, 0x7c, 0x8f, + 0x0d, 0xe7, 0x43, 0x9b, 0x88, 0x1f, 0xb0, 0xfd, 0x24, 0x01, 0xc7, 0x55, 0xc3, 0x73, 0x12, 0x84, + 0x09, 0x7c, 0x57, 0xa8, 0x5d, 0xab, 0x75, 0x29, 0x5c, 0x36, 0x97, 0x64, 0x40, 0x0b, 0x55, 0x34, + 0x0a, 0x5d, 0xb1, 0x1b, 0x61, 0x1b, 0xdc, 0xe5, 0x89, 0xdd, 0x92, 0x62, 0x57, 0xa7, 0x52, 0xb4, + 0x38, 0x9a, 0x48, 0xc8, 0x3a, 0x14, 0xde, 0x69, 0x42, 0xe9, 0x37, 0xa4, 0xe7, 0x2d, 0x00, 0xa7, + 0x0b, 0x29, 0x18, 0xd5, 0xce, 0xd9, 0x0d, 0xdd, 0xfe, 0xae, 0x86, 0xb3, 0x32, 0x1c, 0xc9, 0x33, + 0xb0, 0x2b, 0xb7, 0x3c, 0x0d, 0x43, 0xd8, 0x6c, 0xf2, 0xb7, 0xcd, 0x7b, 0xd5, 0x7d, 0xf0, 0xde, + 0x34, 0x9f, 0x6d, 0x83, 0xb9, 0xd5, 0xed, 0xe3, 0xda, 0x96, 0x40, 0x9e, 0xd6, 0xa6, 0xfd, 0x70, + 0x80, 0x70, 0x87, 0x61, 0x0f, 0xc5, 0x9f, 0x75, 0xfe, 0x11, 0x78, 0x34, 0xc9, 0x42, 0x16, 0x73, + 0x46, 0x7b, 0x05, 0x53, 0x28, 0x43, 0xbe, 0xee, 0x88, 0x67, 0x1d, 0xcc, 0x74, 0xa7, 0xb6, 0x58, + 0x7b, 0x29, 0x68, 0x40, 0xcf, 0xce, 0x7b, 0x19, 0x33, 0x68, 0xa0, 0x82, 0x04, 0xc6, 0x30, 0x82, + 0x04, 0xc2, 0x30, 0x82, 0x04, 0xbe, 0x30, 0x82, 0x03, 0xa6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, + 0x53, 0x4c, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, + 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, + 0x31, 0x30, 0x32, 0x31, 0x30, 0x31, 0x39, 0x34, 0x39, 0x35, 0x34, 0x5a, 0x17, 0x0d, 0x32, 0x33, + 0x31, 0x31, 0x30, 0x37, 0x31, 0x39, 0x34, 0x39, 0x35, 0x34, 0x5a, 0x30, 0x81, 0x9e, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, + 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x16, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x4f, 0x43, 0x53, + 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, + 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb8, 0xba, 0x23, + 0xb4, 0xf6, 0xc3, 0x7b, 0x14, 0xc3, 0xa4, 0xf5, 0x1d, 0x61, 0xa1, 0xf5, 0x1e, 0x63, 0xb9, 0x85, + 0x23, 0x34, 0x50, 0x6d, 0xf8, 0x7c, 0xa2, 0x8a, 0x04, 0x8b, 0xd5, 0x75, 0x5c, 0x2d, 0xf7, 0x63, + 0x88, 0xd1, 0x07, 0x7a, 0xea, 0x0b, 0x45, 0x35, 0x2b, 0xeb, 0x1f, 0xb1, 0x22, 0xb4, 0x94, 0x41, + 0x38, 0xe2, 0x9d, 0x74, 0xd6, 0x8b, 0x30, 0x22, 0x10, 0x51, 0xc5, 0xdb, 0xca, 0x3f, 0x46, 0x2b, + 0xfe, 0xe5, 0x5a, 0x3f, 0x41, 0x74, 0x67, 0x75, 0x95, 0xa9, 0x94, 0xd5, 0xc3, 0xee, 0x42, 0xf8, + 0x8d, 0xeb, 0x92, 0x95, 0xe1, 0xd9, 0x65, 0xb7, 0x43, 0xc4, 0x18, 0xde, 0x16, 0x80, 0x90, 0xce, + 0x24, 0x35, 0x21, 0xc4, 0x55, 0xac, 0x5a, 0x51, 0xe0, 0x2e, 0x2d, 0xb3, 0x0a, 0x5a, 0x4f, 0x4a, + 0x73, 0x31, 0x50, 0xee, 0x4a, 0x16, 0xbd, 0x39, 0x8b, 0xad, 0x05, 0x48, 0x87, 0xb1, 0x99, 0xe2, + 0x10, 0xa7, 0x06, 0x72, 0x67, 0xca, 0x5c, 0xd1, 0x97, 0xbd, 0xc8, 0xf1, 0x76, 0xf8, 0xe0, 0x4a, + 0xec, 0xbc, 0x93, 0xf4, 0x66, 0x4c, 0x28, 0x71, 0xd1, 0xd8, 0x66, 0x03, 0xb4, 0x90, 0x30, 0xbb, + 0x17, 0xb0, 0xfe, 0x97, 0xf5, 0x1e, 0xe8, 0xc7, 0x5d, 0x9b, 0x8b, 0x11, 0x19, 0x12, 0x3c, 0xab, + 0x82, 0x71, 0x78, 0xff, 0xae, 0x3f, 0x32, 0xb2, 0x08, 0x71, 0xb2, 0x1b, 0x8c, 0x27, 0xac, 0x11, + 0xb8, 0xd8, 0x43, 0x49, 0xcf, 0xb0, 0x70, 0xb1, 0xf0, 0x8c, 0xae, 0xda, 0x24, 0x87, 0x17, 0x3b, + 0xd8, 0x04, 0x65, 0x6c, 0x00, 0x76, 0x50, 0xef, 0x15, 0x08, 0xd7, 0xb4, 0x73, 0x68, 0x26, 0x14, + 0x87, 0x95, 0xc3, 0x5f, 0x6e, 0x61, 0xb8, 0x87, 0x84, 0xfa, 0x80, 0x1a, 0x0a, 0x8b, 0x98, 0xf3, + 0xe3, 0xff, 0x4e, 0x44, 0x1c, 0x65, 0x74, 0x7c, 0x71, 0x54, 0x65, 0xe5, 0x39, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x82, 0x01, 0x0a, 0x30, 0x82, 0x01, 0x06, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x32, 0x67, 0xe1, 0xb1, 0x79, 0xd2, 0x81, 0xfc, 0x9f, 0x23, 0x0c, 0x70, 0x40, 0x50, 0xb5, 0x46, + 0x56, 0xb8, 0x30, 0x36, 0x30, 0x81, 0xc4, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xbc, 0x30, + 0x81, 0xb9, 0x80, 0x14, 0x73, 0xb0, 0x1c, 0xa4, 0x2f, 0x82, 0xcb, 0xcf, 0x47, 0xa5, 0x38, 0xd7, + 0xb0, 0x04, 0x82, 0x3a, 0x7e, 0x72, 0x15, 0x21, 0xa1, 0x81, 0x9d, 0xa4, 0x81, 0x9a, 0x30, 0x81, + 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, + 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, + 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, + 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x77, 0x6f, 0x6c, + 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x01, 0x63, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x07, 0xca, 0xa6, 0xa1, 0x9f, 0xbf, 0xaf, 0x92, 0x41, 0x35, 0x66, 0x51, + 0xac, 0xbc, 0x2c, 0xec, 0xe7, 0x8d, 0x65, 0x7e, 0xe9, 0x40, 0xfe, 0x5a, 0xab, 0x8a, 0x1d, 0x3d, + 0x13, 0xdb, 0xb4, 0x43, 0x2c, 0x9a, 0x36, 0x98, 0x21, 0xa5, 0xe8, 0xca, 0xa9, 0x4d, 0xfc, 0xe3, + 0xf7, 0x45, 0x88, 0xcd, 0x33, 0xbf, 0x8a, 0x62, 0x10, 0x2f, 0xb2, 0xb7, 0x04, 0xef, 0x26, 0x43, + 0x51, 0x1d, 0x43, 0x62, 0x7d, 0x1e, 0x50, 0xc8, 0xd5, 0x98, 0x94, 0x71, 0x8f, 0x3b, 0x23, 0x26, + 0xf1, 0x71, 0x8e, 0x1e, 0x3d, 0x3f, 0x21, 0xfd, 0xb7, 0x2d, 0x65, 0xe4, 0x07, 0x65, 0xac, 0x3c, + 0xfc, 0xc0, 0x47, 0xa9, 0x32, 0xf6, 0xda, 0x26, 0x93, 0x10, 0xb2, 0xd1, 0x6d, 0xc8, 0x81, 0x31, + 0x7c, 0xb0, 0x6b, 0xc5, 0x22, 0x8d, 0xb3, 0xfa, 0xbe, 0x82, 0xea, 0x41, 0x42, 0xc4, 0xc0, 0xef, + 0xe3, 0x84, 0x0f, 0x6f, 0x9a, 0x03, 0x63, 0xb3, 0x30, 0xe0, 0x31, 0x81, 0x2a, 0x16, 0xb3, 0x47, + 0xd9, 0x5b, 0x38, 0x93, 0x07, 0xd0, 0x6e, 0x79, 0x52, 0x2c, 0xe5, 0x50, 0x84, 0x79, 0x10, 0xe7, + 0xf6, 0x31, 0x7a, 0x3e, 0x48, 0xa2, 0x38, 0x21, 0x90, 0x7a, 0xf2, 0x5f, 0x48, 0xa4, 0x46, 0x93, + 0x87, 0xdd, 0x5c, 0x83, 0x64, 0xea, 0xb5, 0x99, 0xa2, 0xe9, 0x01, 0x40, 0xfe, 0xf0, 0x48, 0x66, + 0x4f, 0x96, 0xf7, 0x83, 0x52, 0xf8, 0x6d, 0xf8, 0x5f, 0xed, 0x0c, 0xbb, 0xbe, 0xd0, 0x69, 0x10, + 0x4b, 0x99, 0x8f, 0xf8, 0x61, 0x53, 0x9d, 0x12, 0xca, 0x86, 0xaa, 0xb1, 0x80, 0xb4, 0xa6, 0xc1, + 0xcb, 0xb7, 0x48, 0xf7, 0x9f, 0x55, 0xb4, 0x6e, 0xab, 0xd3, 0xa1, 0xaa, 0x4b, 0xa7, 0x21, 0x6e, + 0x16, 0x7f, 0xad, 0xbb, 0xea, 0x0f, 0x41, 0x80, 0x9b, 0x7f, 0xd6, 0x46, 0xa2, 0xc0, 0x61, 0x72, + 0x59, 0x59, 0xa0, 0x07 + }; + OcspEntry entry[1]; + CertStatus status[1]; + OcspRequest* request; + + byte serial[] = {0x05}; + byte issuerHash[] = {0x71, 0x4d, 0x82, 0x23, 0x40, 0x59, 0xc0, 0x96, 0xa1, 0x37, 0x43, 0xfa, 0x31, 0xdb, 0xba, 0xb1, 0x43, 0x18, 0xda, 0x04}; + byte issuerKeyHash[] = {0x83, 0xc6, 0x3a, 0x89, 0x2c, 0x81, 0xf4, 0x02, 0xd7, 0x9d, 0x4c, 0xe2, 0x2a, 0xc0, 0x71, 0x82, 0x64, 0x44, 0xda, 0x0e}; + + printf(testingFmt, "wolfSSL_CertManagerCheckOCSPResponse()"); + + XMEMSET(entry, 0, sizeof(OcspEntry)); + XMEMSET(status, 0, sizeof(CertStatus)); + + AssertNotNull(request = wolfSSL_OCSP_REQUEST_new()); + request->serial = (byte*)XMALLOC(sizeof(serial), NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + AssertNotNull(request->serial); + + request->serialSz = sizeof(serial); + XMEMCPY(request->serial, serial, sizeof(serial)); + XMEMCPY(request->issuerHash, issuerHash, sizeof(issuerHash)); + XMEMCPY(request->issuerKeyHash, issuerKeyHash, sizeof(issuerKeyHash)); + + AssertNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); + AssertIntEQ(wolfSSL_CertManagerEnableOCSP(cm, 0), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CertManagerLoadCA(cm, + "./certs/ocsp/intermediate1-ca-cert.pem", NULL), WOLFSSL_SUCCESS); + + /* Response should be valid. */ + AssertIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, response, + sizeof(response), NULL, status, entry, request), WOLFSSL_SUCCESS); + + /* Flip a byte in the request serial number, response should be invalid + * now. */ + request->serial[0] ^= request->serial[0]; + AssertIntNE(wolfSSL_CertManagerCheckOCSPResponse(cm, response, + sizeof(response), NULL, status, entry, request), WOLFSSL_SUCCESS); + + + wolfSSL_OCSP_REQUEST_free(request); + wolfSSL_CertManagerFree(cm); + + printf(resultFmt, passed); +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + * WOLFSSL_APACHE_HTTPD || HAVE_LIGHTY */ +#endif /* HAVE_OCSP */ +} + static int test_wolfSSL_CertManagerLoadCABuffer(void) { int ret = 0; @@ -2895,6 +3098,276 @@ static void test_wolfSSL_EVP_DecodeFinal(void) printf(resultFmt, passed); #endif /* OPENSSL && WOLFSSL_BASE_DECODE */ } +static void test_wolfSSL_EVP_PKEY_print_public(void) +{ +#if defined(OPENSSL_EXTRA) + + WOLFSSL_BIO* rbio = NULL; + WOLFSSL_BIO* wbio = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + char line[256] = { 0 }; + char line1[256] = { 0 }; + int i; + + printf(testingFmt, "EVP_PKEY_print_public()"); + /* test error cases */ + AssertIntEQ( EVP_PKEY_print_public(NULL,NULL,0,NULL),0L); + + /* + * test RSA public key print + * in this test, pass '3' for indent + */ +#if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_1024) + + rbio = BIO_new_mem_buf( client_keypub_der_1024, + sizeof_client_keypub_der_1024); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,3,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " RSA Public-Key: (1024 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " Modulus:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " 00:BC:73:0E:A8:49:F3:74:A2:A9:EF:18:A5:DA:55:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + + /* skip to the end of modulus element*/ + for( i = 0; i < 8 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " Exponent: 65537 (0x010001)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* !NO_RSA && USE_CERT_BUFFERS_1024*/ + + /* + * test DSA public key print + */ +#if !defined(NO_DSA) && defined(USE_CERT_BUFFERS_2048) + rbio = BIO_new_mem_buf( dsa_pub_key_der_2048, + sizeof_dsa_pub_key_der_2048); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "DSA Public-Key: (2048 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "pub:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 00:C2:35:2D:EC:83:83:6C:73:13:9E:52:7C:74:C8:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of pub element*/ + for( i = 0; i < 17 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "P:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of P element*/ + for( i = 0; i < 18 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "Q:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of Q element*/ + for( i = 0; i < 3 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "G:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of G element*/ + for( i = 0; i < 18 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* !NO_DSA && USE_CERT_BUFFERS_2048 */ + + /* + * test ECC public key print + */ +#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + + rbio = BIO_new_mem_buf( ecc_clikeypub_der_256, + sizeof_ecc_clikeypub_der_256); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "Public-Key: (256 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "pub:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 04:55:BF:F4:0F:44:50:9A:3D:CE:9B:B7:F0:C5:4D:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of pub element*/ + for( i = 0; i < 4 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "ASN1 OID: prime256v1\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "NIST CURVE: P-256\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* HAVE_ECC && USE_CERT_BUFFERS_256 */ + + /* + * test DH public key print + */ +#if defined(WOLFSSL_DH_EXTRA) && defined(USE_CERT_BUFFERS_2048) + + rbio = BIO_new_mem_buf( dh_pub_key_der_2048, + sizeof_dh_pub_key_der_2048); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "DH Public-Key: (2048 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "public-key:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 34:41:BF:E9:F2:11:BF:05:DB:B2:72:A8:29:CC:BD:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of public-key element*/ + for( i = 0; i < 17 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "prime:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 00:D3:B2:99:84:5C:0A:4C:E7:37:CC:FC:18:37:01:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of prime element*/ + for( i = 0; i < 17 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "generator: 2 (0x02)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* WOLFSSL_DH_EXTRA && USE_CERT_BUFFERS_2048 */ + + /* to prevent "unused variable" warning */ + (void)pkey; + (void)wbio; + (void)rbio; + (void)line; + (void)line1; + (void)i; + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} /* Test function for wolfSSL_EVP_get_cipherbynid. */ @@ -2998,7 +3471,7 @@ static void test_wolfSSL_EVP_get_cipherbynid(void) } -static void test_wolfSSL_EVP_CIPHER_CTX() +static void test_wolfSSL_EVP_CIPHER_CTX(void) { #if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); @@ -3018,6 +3491,8 @@ static void test_wolfSSL_EVP_CIPHER_CTX() AssertIntEQ(EVP_CIPHER_CTX_reset(NULL), WOLFSSL_FAILURE); EVP_CIPHER_CTX_free(ctx); + /* test EVP_CIPHER_CTX_cleanup with NULL */ + AssertIntEQ(EVP_CIPHER_CTX_cleanup(NULL), WOLFSSL_SUCCESS); #endif /* !NO_AES && HAVE_AES_CBC && WOLFSSL_AES_128 */ } #endif /* OPENSSL_EXTRA */ @@ -3128,6 +3603,75 @@ static int nonblocking_accept_read(void* args, WOLFSSL* ssl, SOCKET_T* sockfd) } #endif /* WOLFSSL_SESSION_EXPORT */ +/* TODO: Expand and enable this when EVP_chacha20_poly1305 is supported */ +#if defined(HAVE_SESSION_TICKET) && \ + defined(HAVE_AESGCM) && \ + defined(OPENSSL_EXTRA) + + typedef struct openssl_key_ctx { + byte name[WOLFSSL_TICKET_NAME_SZ]; /* server name */ + byte key[WOLFSSL_TICKET_KEY_SZ]; /* cipher key */ + byte hmacKey[WOLFSSL_TICKET_NAME_SZ]; /* hmac key */ + byte iv[WOLFSSL_TICKET_IV_SZ]; /* cipher iv */ + } openssl_key_ctx; + + static THREAD_LS_T openssl_key_ctx myOpenSSLKey_ctx; + static THREAD_LS_T WC_RNG myOpenSSLKey_rng; + + static WC_INLINE int OpenSSLTicketInit(void) + { + int ret = wc_InitRng(&myOpenSSLKey_rng); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.name, + sizeof(myOpenSSLKey_ctx.name)); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.key, + sizeof(myOpenSSLKey_ctx.key)); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.hmacKey, + sizeof(myOpenSSLKey_ctx.hmacKey)); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.iv, + sizeof(myOpenSSLKey_ctx.iv)); + if (ret != 0) return ret; + + return 0; + } + + static WC_INLINE int myTicketEncCbOpenSSL(WOLFSSL* ssl, + byte name[WOLFSSL_TICKET_NAME_SZ], + byte iv[WOLFSSL_TICKET_IV_SZ], + WOLFSSL_EVP_CIPHER_CTX *ectx, + WOLFSSL_HMAC_CTX *hctx, int enc) { + (void)ssl; + if (enc) { + XMEMCPY(name, myOpenSSLKey_ctx.name, sizeof(myOpenSSLKey_ctx.name)); + XMEMCPY(iv, myOpenSSLKey_ctx.iv, sizeof(myOpenSSLKey_ctx.iv)); + } + else if (XMEMCMP(name, myOpenSSLKey_ctx.name, + sizeof(myOpenSSLKey_ctx.name)) != 0 || + XMEMCMP(iv, myOpenSSLKey_ctx.iv, + sizeof(myOpenSSLKey_ctx.iv)) != 0) { + return 0; + } + HMAC_Init_ex(hctx, myOpenSSLKey_ctx.hmacKey, WOLFSSL_TICKET_NAME_SZ, EVP_sha256(), NULL); + if (enc) + EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, myOpenSSLKey_ctx.key, iv); + else + EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, myOpenSSLKey_ctx.key, iv); + return 1; + } + + static WC_INLINE void OpenSSLTicketCleanup(void) + { + wc_FreeRng(&myOpenSSLKey_rng); + } +#endif + static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) { SOCKET_T sockfd = 0; @@ -3168,12 +3712,20 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) } ctx = wolfSSL_CTX_new(method); } + if (ctx == NULL) { + goto done; + } -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ +#if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) +#if defined(OPENSSL_EXTRA) && defined(HAVE_AESGCM) + OpenSSLTicketInit(); + wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL); +#elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketInit(); wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif +#endif #if defined(USE_WINDOWS_API) port = ((func_args*)args)->signal->port; @@ -3187,7 +3739,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #endif /* do it here to detect failure */ - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sockfd); wolfSSL_CTX_set_verify(ctx, @@ -3356,10 +3908,14 @@ done: wc_ecc_fp_free(); /* free per thread cache */ #endif -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ +#if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) +#if defined(OPENSSL_EXTRA) && defined(HAVE_AESGCM) + OpenSSLTicketCleanup(); +#elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketCleanup(); #endif +#endif #ifndef WOLFSSL_TIRTOS return 0; @@ -3478,7 +4034,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) cbf->ssl_ready(ssl); } /* do it here to detect failure */ - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sockfd); if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ @@ -3560,7 +4116,7 @@ done: typedef int (*cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl); -static void test_client_nofail(void* args, void *cb) +static void test_client_nofail(void* args, cbType cb) { SOCKET_T sockfd = 0; callback_functions* cbf; @@ -3727,7 +4283,7 @@ static void test_client_nofail(void* args, void *cb) #endif if (cb != NULL) - ((cbType)cb)(ctx, ssl); + (cb)(ctx, ssl); if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { /*err_sys("SSL_write failed");*/ @@ -3982,6 +4538,127 @@ done: } #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ + +static void test_client_verifyDepth(void* args) +{ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TIRTOS) && !defined(NO_WOLFSSL_CLIENT) + SOCKET_T sockfd = 0; + callback_functions* cbf; + + WOLFSSL_CTX* ctx = 0; + WOLFSSL* ssl = 0; + + char msg[64] = "hello wolfssl!"; + char reply[1024]; + int input; + int msgSz = (int)XSTRLEN(msg); + int ret, err = 0; + int verify_depth = ((func_args*)args)->argc; + + ((func_args*)args)->return_code = TEST_FAIL; + cbf = ((func_args*)args)->callbacks; + + { + WOLFSSL_METHOD* method = NULL; + if (cbf != NULL && cbf->method != NULL) { + method = cbf->method(); + } + else { + method = wolfSSLv23_client_method(); + } + ctx = wolfSSL_CTX_new(method); + } + + /* Do connect here so server detects failures */ + tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, NULL); + + if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) + != WOLFSSL_SUCCESS) + { + /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ + goto done; + } + if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load client cert file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load client key file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); + + /* set verify depth */ + if (verify_depth == 0) { + myVerifyAction = VERIFY_OVERRIDE_ERROR; + SSL_CTX_set_verify_depth(ctx, verify_depth); + } else if (verify_depth == -1) { + myVerifyAction = VERIFY_USE_PREVERFIY; + SSL_CTX_set_verify_depth(ctx, 0); + } else if (verify_depth > 0) { + myVerifyAction = VERIFY_USE_PREVERFIY; + SSL_CTX_set_verify_depth(ctx, verify_depth); + } + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + goto done; + } + + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { + /*err_sys("SSL_set_fd failed");*/ + goto done; + } + + do { +#ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) { break; } else if (ret == 0) { continue; } + } +#endif + + err = 0; /* Reset error */ + ret = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + goto done; + } + + if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { + goto done; + } + + input = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (input > 0) { + reply[input] = '\0'; + printf("Server response: %s\n", reply); + } + + ((func_args*)args)->return_code = TEST_SUCCESS; + +done: + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + CloseSocket(sockfd); +#else + (void)args; +#endif /* defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TIRTOS) && !defined(NO_WOLFSSL_CLIENT) */ +} + + /* SNI / ALPN / session export helper functions */ #if defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLFSSL_SESSION_EXPORT) @@ -4047,14 +4724,14 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) socklen_t cliLen; cliLen = sizeof(cliAddr); - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0, 0, 0); idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK, (struct sockaddr*)&cliAddr, &cliLen); AssertIntGT(idx, 0); wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen); } else { - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sfd); } @@ -4340,29 +5017,121 @@ static void test_wolfSSL_reuse_WOLFSSLobj(void) } #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ +static void test_wolfSSL_CTX_verifyDepth_ServerClient(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TIRTOS) && !defined(NO_WOLFSSL_CLIENT) + + /* This unit test is to check set verify Depth */ + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + callback_functions client_cbf; + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&client_cbf, 0, sizeof(callback_functions)); + + printf(testingFmt, "test_wolfSSL_CTX_verifyDepth_ServerClient()\n"); + +#ifdef WOLFSSL_TLS13 + client_cbf.method = wolfTLSv1_3_client_method; +#endif /* WOLFSSL_TLS13 */ + + client_args.callbacks = &client_cbf; + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + client_args.signal = &ready; + /* the var is used for loop number */ + server_args.argc = 1; + + /* test case 1 verify depth is equal to peer chain */ + { + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + /* the var is used for verify depth */ + client_args.argc = 2; + + test_client_verifyDepth(&client_args); + join_thread(serverThread); + AssertIntEQ(client_args.return_code, TEST_SUCCESS); + AssertIntEQ(server_args.return_code, TEST_SUCCESS); + } + + /* test case 2 + * verify depth is zero, number of peer's chain is 2. + * verify result becomes MAX_CHAIN_ERROR, but it is overridden in + * callback. + */ + + /* the var is used for verify depth 0 and VERIFY_OVERRIDE_ERROR */ + { + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + client_args.argc = 0; + test_client_verifyDepth(&client_args); + join_thread(serverThread); + AssertIntEQ(client_args.return_code, TEST_SUCCESS); + AssertIntEQ(server_args.return_code, TEST_SUCCESS); + } + /* test case 3 + * verify depth is zero, number of peer's chain is 2 + * verify result becomes MAX_CHAIN_ERRO. call-back returns failure. + * therefore, handshake becomes failure. + */ + /* the var is used for verify depth 0 and VERIFY_USE_PREVERFIY */ + { + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + client_args.argc = -1; + test_client_verifyDepth(&client_args); + join_thread(serverThread); + AssertIntEQ(client_args.return_code, TEST_FAIL); + AssertIntEQ(server_args.return_code, TEST_FAIL); + } + + FreeTcpReady(&ready); + printf(resultFmt, passed); +#else + (void)test_client_verifyDepth; +#endif /* (OPENSSL_EXTRA) && !(WOLFSSL_TIRTOS) && (NO_WOLFSSL_CLIENT) */ +} + + #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) /* canned export of a session using older version 3 */ static unsigned char version_3[] = { - 0xA5, 0xA3, 0x01, 0x87, 0x00, 0x3b, 0x00, 0x01, + 0xA5, 0xA3, 0x01, 0x88, 0x00, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x30, 0x05, - 0x09, 0x0A, 0x01, 0x01, 0x00, 0x0D, 0x05, 0xFE, - 0xFD, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x30, + 0x05, 0x09, 0x0A, 0x01, 0x01, 0x00, 0x0D, 0x05, + 0xFE, 0xFD, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -4374,25 +5143,25 @@ static unsigned char version_3[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x05, 0x12, - 0xCF, 0x22, 0xA1, 0x9F, 0x1C, 0x39, 0x1D, 0x31, - 0x11, 0x12, 0x1D, 0x11, 0x18, 0x0D, 0x0B, 0xF3, - 0xE1, 0x4D, 0xDC, 0xB1, 0xF1, 0x39, 0x98, 0x91, - 0x6C, 0x48, 0xE5, 0xED, 0x11, 0x12, 0xA0, 0x00, - 0xF2, 0x25, 0x4C, 0x09, 0x26, 0xD1, 0x74, 0xDF, - 0x23, 0x40, 0x15, 0x6A, 0x42, 0x2A, 0x26, 0xA5, - 0xAC, 0x56, 0xD5, 0x4A, 0x20, 0xB7, 0xE9, 0xEF, - 0xEB, 0xAF, 0xA8, 0x1E, 0x23, 0x7C, 0x04, 0xAA, - 0xA1, 0x6D, 0x92, 0x79, 0x7B, 0xFA, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, - 0x79, 0x7B, 0xFA, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xAA, 0xA1, 0x6D, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, - 0x00, 0x10, 0x08, 0x02, 0x05, 0x08, 0x01, 0x30, - 0x28, 0x00, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x09, - 0x31, 0x32, 0x37, 0x2E, 0x30, 0x2E, 0x30, 0x2E, - 0x31, 0xED, 0x4F + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x05, + 0x12, 0xCF, 0x22, 0xA1, 0x9F, 0x1C, 0x39, 0x1D, + 0x31, 0x11, 0x12, 0x1D, 0x11, 0x18, 0x0D, 0x0B, + 0xF3, 0xE1, 0x4D, 0xDC, 0xB1, 0xF1, 0x39, 0x98, + 0x91, 0x6C, 0x48, 0xE5, 0xED, 0x11, 0x12, 0xA0, + 0x00, 0xF2, 0x25, 0x4C, 0x09, 0x26, 0xD1, 0x74, + 0xDF, 0x23, 0x40, 0x15, 0x6A, 0x42, 0x2A, 0x26, + 0xA5, 0xAC, 0x56, 0xD5, 0x4A, 0x20, 0xB7, 0xE9, + 0xEF, 0xEB, 0xAF, 0xA8, 0x1E, 0x23, 0x7C, 0x04, + 0xAA, 0xA1, 0x6D, 0x92, 0x79, 0x7B, 0xFA, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x0C, 0x79, 0x7B, 0xFA, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xA1, 0x6D, + 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x10, 0x08, 0x02, 0x05, 0x08, 0x01, + 0x30, 0x28, 0x00, 0x00, 0x0F, 0x00, 0x02, 0x00, + 0x09, 0x31, 0x32, 0x37, 0x2E, 0x30, 0x2E, 0x30, + 0x2E, 0x31, 0xED, 0x4F }; #endif /* defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) */ @@ -4790,7 +5559,7 @@ static void test_wolfSSL_UseSNI_connection(void) static void test_wolfSSL_SNI_GetFromBuffer(void) { - byte buffer[] = { /* www.paypal.com */ + byte buff[] = { /* www.paypal.com */ 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x60, 0x03, 0x03, 0x5c, 0xc4, 0xb3, 0x8c, 0x87, 0xef, 0xa4, 0x09, 0xe0, 0x02, 0xab, 0x86, 0xca, 0x76, 0xf0, 0x9e, 0x01, 0x65, 0xf6, 0xa6, 0x06, 0x13, 0x1d, 0x0f, 0xa5, @@ -4802,7 +5571,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x02, 0x01 }; - byte buffer2[] = { /* api.textmate.org */ + byte buff2[] = { /* api.textmate.org */ 0x16, 0x03, 0x01, 0x00, 0xc6, 0x01, 0x00, 0x00, 0xc2, 0x03, 0x03, 0x52, 0x8b, 0x7b, 0xca, 0x69, 0xec, 0x97, 0xd5, 0x08, 0x03, 0x50, 0xfe, 0x3b, 0x99, 0xc3, 0x20, 0xce, 0xa5, 0xf6, 0x99, 0xa5, 0x71, 0xf9, 0x57, 0x7f, @@ -4822,7 +5591,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) 0x0a, 0x05, 0x01, 0x04, 0x01, 0x02, 0x01, 0x04, 0x03, 0x02, 0x03 }; - byte buffer3[] = { /* no sni extension */ + byte buff3[] = { /* no sni extension */ 0x16, 0x03, 0x03, 0x00, 0x4d, 0x01, 0x00, 0x00, 0x49, 0x03, 0x03, 0xea, 0xa1, 0x9f, 0x60, 0xdd, 0x52, 0x12, 0x13, 0xbd, 0x84, 0x34, 0xd5, 0x1c, 0x38, 0x25, 0xa8, 0x97, 0xd2, 0xd5, 0xc6, 0x45, 0xaf, 0x1b, 0x08, 0xe4, @@ -4832,7 +5601,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) 0x00, 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x02, 0x01 }; - byte buffer4[] = { /* last extension has zero size */ + byte buff4[] = { /* last extension has zero size */ 0x16, 0x03, 0x01, 0x00, 0xba, 0x01, 0x00, 0x00, 0xb6, 0x03, 0x03, 0x83, 0xa3, 0xe6, 0xdc, 0x16, 0xa1, 0x43, 0xe9, 0x45, 0x15, 0xbd, 0x64, 0xa9, 0xb6, 0x07, 0xb4, 0x50, 0xc6, 0xdd, 0xff, 0xc2, @@ -4852,7 +5621,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) 0x12, 0x00, 0x00 }; - byte buffer5[] = { /* SSL v2.0 client hello */ + byte buff5[] = { /* SSL v2.0 client hello */ 0x00, 0x2b, 0x01, 0x03, 0x01, 0x00, 0x09, 0x00, 0x00, /* dummy bytes bellow, just to pass size check */ 0xb6, 0x03, 0x03, 0x83, 0xa3, 0xe6, 0xdc, 0x16, 0xa1, 0x43, 0xe9, 0x45, @@ -4863,58 +5632,58 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) byte result[32] = {0}; word32 length = 32; - AssertIntEQ(0, wolfSSL_SNI_GetFromBuffer(buffer4, sizeof(buffer4), + AssertIntEQ(0, wolfSSL_SNI_GetFromBuffer(buff4, sizeof(buff4), 0, result, &length)); - AssertIntEQ(0, wolfSSL_SNI_GetFromBuffer(buffer3, sizeof(buffer3), + AssertIntEQ(0, wolfSSL_SNI_GetFromBuffer(buff3, sizeof(buff3), 0, result, &length)); - AssertIntEQ(0, wolfSSL_SNI_GetFromBuffer(buffer2, sizeof(buffer2), + AssertIntEQ(0, wolfSSL_SNI_GetFromBuffer(buff2, sizeof(buff2), 1, result, &length)); - AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); - buffer[0] = 0x16; + buff[0] = 0x16; - AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); - buffer[1] = 0x03; + buff[1] = 0x03; - AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer, - sizeof(buffer), 0, result, &length)); - buffer[2] = 0x03; + AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buff, + sizeof(buff), 0, result, &length)); + buff[2] = 0x03; - AssertIntEQ(INCOMPLETE_DATA, wolfSSL_SNI_GetFromBuffer(buffer, - sizeof(buffer), 0, result, &length)); - buffer[4] = 0x64; + AssertIntEQ(INCOMPLETE_DATA, wolfSSL_SNI_GetFromBuffer(buff, + sizeof(buff), 0, result, &length)); + buff[4] = 0x64; - AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); result[length] = 0; AssertStrEQ("www.paypal.com", (const char*) result); length = 32; - AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buffer2, sizeof(buffer2), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buff2, sizeof(buff2), 0, result, &length)); result[length] = 0; AssertStrEQ("api.textmate.org", (const char*) result); /* SSL v2.0 tests */ - AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer5, - sizeof(buffer5), 0, result, &length)); + AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buff5, + sizeof(buff5), 0, result, &length)); - buffer5[2] = 0x02; - AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5, - sizeof(buffer5), 0, result, &length)); + buff5[2] = 0x02; + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buff5, + sizeof(buff5), 0, result, &length)); - buffer5[2] = 0x01; buffer5[6] = 0x08; - AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5, - sizeof(buffer5), 0, result, &length)); + buff5[2] = 0x01; buff5[6] = 0x08; + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buff5, + sizeof(buff5), 0, result, &length)); - buffer5[6] = 0x09; buffer5[8] = 0x01; - AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5, - sizeof(buffer5), 0, result, &length)); + buff5[6] = 0x09; buff5[8] = 0x01; + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buff5, + sizeof(buff5), 0, result, &length)); } #endif /* HAVE_SNI */ @@ -5467,7 +6236,7 @@ static void test_wolfSSL_PKCS12(void) */ #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \ !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_RSA) && \ - !defined(NO_SHA) + !defined(NO_SHA) && defined(HAVE_PKCS12) byte buffer[6000]; char file[] = "./certs/test-servercert.p12"; char order[] = "./certs/ecc-rsa-server.p12"; @@ -5475,12 +6244,14 @@ static void test_wolfSSL_PKCS12(void) char rc2p12[] = "./certs/test-servercert-rc2.p12"; #endif char pass[] = "a password"; + const char goodPsw[] = "wolfSSL test"; + const char badPsw[] = "bad"; #ifdef HAVE_ECC WOLFSSL_X509_NAME* subject; WOLFSSL_X509 *x509; #endif XFILE f; - int bytes, ret; + int bytes, ret, goodPswLen, badPswLen; WOLFSSL_BIO *bio; WOLFSSL_EVP_PKEY *pkey; WC_PKCS12 *pkcs12; @@ -5502,6 +6273,9 @@ static void test_wolfSSL_PKCS12(void) bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); XFCLOSE(f); + goodPswLen = (int)XSTRLEN(goodPsw); + badPswLen = (int)XSTRLEN(badPsw); + bio = BIO_new_mem_buf((void*)buffer, bytes); AssertNotNull(bio); @@ -5513,12 +6287,20 @@ static void test_wolfSSL_PKCS12(void) AssertNotNull(pkcs12); BIO_free(bio); + /* check verify MAC directly */ + ret = PKCS12_verify_mac(pkcs12, goodPsw, goodPswLen); + AssertIntEQ(ret, 1); + + /* check verify MAC fail case directly */ + ret = PKCS12_verify_mac(pkcs12, badPsw, badPswLen); + AssertIntEQ(ret, 0); + /* check verify MAC fail case */ ret = PKCS12_parse(pkcs12, "bad", &pkey, &cert, NULL); AssertIntEQ(ret, 0); AssertNull(pkey); AssertNull(cert); - + /* check parse with no extra certs kept */ ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, NULL); AssertIntEQ(ret, 1); @@ -5815,7 +6597,7 @@ static void test_wolfSSL_no_password_cb(void) #if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) \ && defined(HAVE_ECC) && defined(WOLFSSL_ENCRYPTED_KEYS) WOLFSSL_CTX* ctx; - byte buffer[FOURK_BUF]; + byte buff[FOURK_BUF]; const char eccPkcs8PrivKeyDerFile[] = "./certs/ecc-privkeyPkcs8.der"; const char eccPkcs8PrivKeyPemFile[] = "./certs/ecc-privkeyPkcs8.pem"; XFILE f; @@ -5831,17 +6613,17 @@ static void test_wolfSSL_no_password_cb(void) wolfSSL_CTX_set_default_passwd_cb(ctx, FailTestCallBack); AssertTrue((f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb")) != XBADFILE); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); - AssertIntLE(bytes, sizeof(buffer)); - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntLE(bytes, sizeof(buff)); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); AssertTrue((f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb")) != XBADFILE); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); - AssertIntLE(bytes, sizeof(buffer)); - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntLE(bytes, sizeof(buff)); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); @@ -5884,7 +6666,7 @@ static int PKCS8TestCallBack(char* passwd, int sz, int rw, void* userdata) static void test_wolfSSL_PKCS8(void) { #if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) - byte buffer[FOURK_BUF]; + byte buff[FOURK_BUF]; byte der[FOURK_BUF]; #ifndef NO_RSA const char serverKeyPkcs8PemFile[] = "./certs/server-keyPkcs8.pem"; @@ -5939,36 +6721,36 @@ static void test_wolfSSL_PKCS8(void) /* test loading PEM PKCS8 encrypted file */ f = XFOPEN(serverKeyPkcs8EncPemFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ - AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ - AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + AssertIntGT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "yassl123"), 0); /* test that error value is returned with a bad password */ - AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + AssertIntLT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "bad"), 0); /* test loading PEM PKCS8 encrypted file */ f = XFOPEN(serverKeyPkcs8EncDerFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); flag = 1; /* used by password callback as return code */ - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ - AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif /* !NO_RSA && !NO_SHA */ @@ -5976,37 +6758,37 @@ static void test_wolfSSL_PKCS8(void) /* test loading PEM PKCS8 encrypted ECC Key file */ f = XFOPEN(eccPkcs8EncPrivKeyPemFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); flag = 1; /* used by password callback as return code */ - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ - AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ - AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + AssertIntGT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "yassl123"), 0); /* test that error value is returned with a bad password */ - AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + AssertIntLT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "bad"), 0); /* test loading DER PKCS8 encrypted ECC Key file */ f = XFOPEN(eccPkcs8EncPrivKeyDerFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); flag = 1; /* used by password callback as return code */ - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ - AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* leave flag as "okay" */ @@ -6019,32 +6801,32 @@ static void test_wolfSSL_PKCS8(void) /* test loading ASN.1 (DER) PKCS8 private key file (not encrypted) */ f = XFOPEN(serverKeyPkcs8DerFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* test loading PEM PKCS8 private key file (not encrypted) */ f = XFOPEN(serverKeyPkcs8PemFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #endif /* !NO_RSA */ /* Test PKCS8 PEM ECC key no crypt */ f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); #ifdef HAVE_ECC /* Test PKCS8 PEM ECC key no crypt */ - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format */ - AssertIntGT((bytes = wc_KeyPemToDer(buffer, bytes, der, + AssertIntGT((bytes = wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), NULL)), 0); ret = wc_ecc_init(&key); if (ret == 0) { @@ -6056,15 +6838,15 @@ static void test_wolfSSL_PKCS8(void) /* Test PKCS8 DER ECC key no crypt */ f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); /* Test using a PKCS8 ECC PEM */ - AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #else /* if HAVE_ECC is not defined then BEGIN EC PRIVATE KEY is not found */ - AssertIntEQ((bytes = wc_KeyPemToDer(buffer, bytes, der, + AssertIntEQ((bytes = wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), NULL)), ASN_NO_PEM_HEADER); #endif /* HAVE_ECC */ @@ -6225,7 +7007,7 @@ static void test_wolfSSL_X509_verify(void) #if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) \ && defined(OPENSSL_EXTRA) WOLFSSL_X509* ca; - WOLFSSL_X509* server; + WOLFSSL_X509* serv; WOLFSSL_EVP_PKEY* pkey; unsigned char buf[2048]; const unsigned char* pt = NULL; @@ -6249,7 +7031,7 @@ static void test_wolfSSL_X509_verify(void) AssertIntEQ(wolfSSL_X509_get_pubkey_type(ca), RSAk); - AssertNotNull(server = + AssertNotNull(serv = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM)); /* success case */ @@ -6258,23 +7040,23 @@ static void test_wolfSSL_X509_verify(void) AssertIntEQ(i2d_PUBKEY(pkey, NULL), bufSz); - AssertIntEQ(wolfSSL_X509_verify(server, pkey), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_verify(serv, pkey), WOLFSSL_SUCCESS); wolfSSL_EVP_PKEY_free(pkey); /* fail case */ bufSz = 2048; - AssertIntEQ(wolfSSL_X509_get_pubkey_buffer(server, buf, &bufSz), + AssertIntEQ(wolfSSL_X509_get_pubkey_buffer(serv, buf, &bufSz), WOLFSSL_SUCCESS); pt = buf; AssertNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &pt, bufSz)); - AssertIntEQ(wolfSSL_X509_verify(server, pkey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_X509_verify(serv, pkey), WOLFSSL_FAILURE); AssertIntEQ(wolfSSL_X509_verify(NULL, pkey), WOLFSSL_FATAL_ERROR); - AssertIntEQ(wolfSSL_X509_verify(server, NULL), WOLFSSL_FATAL_ERROR); + AssertIntEQ(wolfSSL_X509_verify(serv, NULL), WOLFSSL_FATAL_ERROR); wolfSSL_EVP_PKEY_free(pkey); wolfSSL_FreeX509(ca); - wolfSSL_FreeX509(server); + wolfSSL_FreeX509(serv); printf(resultFmt, passed); #endif @@ -7098,6 +7880,16 @@ static int test_wc_ShaUpdate (void) a.input = "a"; a.inLen = XSTRLEN(a.input); + ret = wc_ShaUpdate(&sha, NULL, 0); + if (ret != 0) { + flag = ret; + } + + ret = wc_ShaUpdate(&sha, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); if (ret != 0) { flag = ret; @@ -7306,6 +8098,16 @@ static int test_wc_Sha256Update (void) a.input = "a"; a.inLen = XSTRLEN(a.input); + ret = wc_Sha256Update(&sha256, NULL, 0); + if (ret != 0) { + flag = ret; + } + + ret = wc_Sha256Update(&sha256, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); if (ret != 0) { flag = ret; @@ -7726,6 +8528,16 @@ static int test_wc_Sha512Update (void) a.input = "a"; a.inLen = XSTRLEN(a.input); + ret = wc_Sha512Update(&sha512, NULL, 0); + if (ret != 0) { + flag = ret; + } + + ret = wc_Sha512Update(&sha512,(byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + ret = wc_Sha512Update(&sha512, (byte*)a.input, (word32)a.inLen); if (ret != 0) { flag = ret; @@ -8143,6 +8955,16 @@ static int test_wc_Sha384Update (void) a.input = "a"; a.inLen = XSTRLEN(a.input); + ret = wc_Sha384Update(&sha384, NULL, 0); + if (ret != 0) { + flag = ret; + } + + ret = wc_Sha384Update(&sha384, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); if (ret != 0) { flag = ret; @@ -8562,6 +9384,16 @@ static int test_wc_Sha224Update (void) a.input = "a"; a.inLen = XSTRLEN(a.input); + ret = wc_Sha224Update(&sha224, NULL, 0); + if (ret != 0) { + flag = ret; + } + + ret = wc_Sha224Update(&sha224, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); if (ret != 0) { flag = ret; @@ -10053,7 +10885,7 @@ static int test_wc_Sha3_GetFlags (void) static int test_wc_InitShake256 (void) { int ret = 0; -#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) +#ifdef WOLFSSL_SHAKE256 wc_Shake shake; printf(testingFmt, "wc_InitShake256()"); @@ -10080,7 +10912,7 @@ static int testing_wc_Shake256_Update (void) { int ret = 0; -#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) +#ifdef WOLFSSL_SHAKE256 wc_Shake shake; byte msg[] = "Everybody's working for the weekend."; byte msg2[] = "Everybody gets Friday off."; @@ -10132,7 +10964,7 @@ static int testing_wc_Shake256_Update (void) wc_Shake256_Free(&shake); printf(resultFmt, ret == 0 ? passed : failed); -#endif /* WOLFSSL_SHAKE256 && !WOLFSSL_NO_SHAKE256 */ +#endif /* WOLFSSL_SHAKE256 */ return ret; @@ -10142,7 +10974,7 @@ static int test_wc_Shake256_Final (void) { int ret = 0; -#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) +#ifdef WOLFSSL_SHAKE256 wc_Shake shake; const char* msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnom" "nopnopq"; @@ -10197,7 +11029,7 @@ static int test_wc_Shake256_Final (void) static int test_wc_Shake256_Copy (void) { int ret = 0; -#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) +#ifdef WOLFSSL_SHAKE256 wc_Shake shake, shakeCpy; const char* msg = TEST_STRING; word32 msglen = (word32)TEST_STRING_SZ; @@ -10260,7 +11092,7 @@ static int test_wc_Shake256_Copy (void) static int test_wc_Shake256Hash(void) { int ret = 0; -#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) +#ifdef WOLFSSL_SHAKE256 const byte data[] = { /* Hello World */ 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, @@ -12031,6 +12863,212 @@ static int test_wc_AesCmacGenerate (void) } /* END test_wc_AesCmacGenerate */ +/* + * Testing streaming AES-GCM API. + */ +static int test_wc_AesGcmStream (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(WOLFSSL_AES_128) && defined(HAVE_AESGCM) && \ + defined(WOLFSSL_AESGCM_STREAM) + + int i; + WC_RNG rng[1]; + Aes aesEnc[1]; + Aes aesDec[1]; + byte tag[AES_BLOCK_SIZE]; + byte in[AES_BLOCK_SIZE * 3 + 2] = { 0, }; + byte out[AES_BLOCK_SIZE * 3 + 2]; + byte plain[AES_BLOCK_SIZE * 3 + 2]; + byte aad[AES_BLOCK_SIZE * 3 + 2] = { 0, }; + byte key[AES_128_KEY_SIZE] = { 0, }; + byte iv[AES_IV_SIZE] = { 1, }; + byte ivOut[AES_IV_SIZE]; + static const byte expTagAAD1[AES_BLOCK_SIZE] = { + 0x6c, 0x35, 0xe6, 0x7f, 0x59, 0x9e, 0xa9, 0x2f, + 0x27, 0x2d, 0x5f, 0x8e, 0x7e, 0x42, 0xd3, 0x05 + }; + static const byte expTagPlain1[AES_BLOCK_SIZE] = { + 0x24, 0xba, 0x57, 0x95, 0xd0, 0x27, 0x9e, 0x78, + 0x3a, 0x88, 0x4c, 0x0a, 0x5d, 0x50, 0x23, 0xd1 + }; + static const byte expTag[AES_BLOCK_SIZE] = { + 0x22, 0x91, 0x70, 0xad, 0x42, 0xc3, 0xad, 0x96, + 0xe0, 0x31, 0x57, 0x60, 0xb7, 0x92, 0xa3, 0x6d + }; + + /* Create a random for generating IV/nonce. */ + AssertIntEQ(wc_InitRng(rng), 0); + + /* Initialize data structures. */ + AssertIntEQ(wc_AesInit(aesEnc, NULL, INVALID_DEVID), 0); + AssertIntEQ(wc_AesInit(aesDec, NULL, INVALID_DEVID), 0); + + /* BadParameters to streaming init. */ + AssertIntEQ(wc_AesGcmEncryptInit(NULL, NULL, 0, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptInit(NULL, NULL, 0, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptInit(aesEnc, NULL, AES_128_KEY_SIZE, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptInit(aesEnc, NULL, 0, NULL, GCM_NONCE_MID_SZ), + BAD_FUNC_ARG); + + /* Bad parameters to encrypt update. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(NULL, NULL, NULL, 0, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 1, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, in, 1, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, NULL, 1, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, NULL, 1), + BAD_FUNC_ARG); + /* Bad parameters to decrypt update. */ + AssertIntEQ(wc_AesGcmDecryptUpdate(NULL, NULL, NULL, 0, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 1, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, in, 1, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, out, NULL, 1, NULL, 0), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, NULL, 1), + BAD_FUNC_ARG); + + /* Bad parameters to encrypt final. */ + AssertIntEQ(wc_AesGcmEncryptFinal(NULL, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptFinal(NULL, tag, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptFinal(NULL, NULL, AES_BLOCK_SIZE), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, NULL, AES_BLOCK_SIZE), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE + 1), + BAD_FUNC_ARG); + /* Bad parameters to decrypt final. */ + AssertIntEQ(wc_AesGcmDecryptFinal(NULL, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptFinal(NULL, tag, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptFinal(NULL, NULL, AES_BLOCK_SIZE), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, NULL, AES_BLOCK_SIZE), + BAD_FUNC_ARG); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE + 1), + BAD_FUNC_ARG); + + /* Check calling final before setting key fails. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, sizeof(tag)), MISSING_KEY); + AssertIntEQ(wc_AesGcmEncryptFinal(aesDec, tag, sizeof(tag)), MISSING_KEY); + /* Check calling update before setting key else fails. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad, 1), + MISSING_KEY); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad, 1), + MISSING_KEY); + + /* Set key but not IV. */ + AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), NULL, 0), 0); + AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), NULL, 0), 0); + /* Check calling final before setting IV fails. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, sizeof(tag)), MISSING_IV); + AssertIntEQ(wc_AesGcmEncryptFinal(aesDec, tag, sizeof(tag)), MISSING_IV); + /* Check calling update before setting IV else fails. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad, 1), + MISSING_IV); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad, 1), + MISSING_IV); + + /* Set IV using fixed part IV and external IV APIs. */ + AssertIntEQ(wc_AesGcmSetIV(aesEnc, GCM_NONCE_MID_SZ, iv, AES_IV_FIXED_SZ, + rng), 0); + AssertIntEQ(wc_AesGcmEncryptInit_ex(aesEnc, NULL, 0, ivOut, + GCM_NONCE_MID_SZ), 0); + AssertIntEQ(wc_AesGcmSetExtIV(aesDec, ivOut, GCM_NONCE_MID_SZ), 0); + AssertIntEQ(wc_AesGcmInit(aesDec, NULL, 0, NULL, 0), 0); + /* Encrypt and decrypt data. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, in, 1, aad, 1), 0); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain, out, 1, aad, 1), 0); + AssertIntEQ(XMEMCMP(plain, in, 1), 0); + /* Finalize and check tag matches. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0); + + /* Set key and IV through streaming init API. */ + AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0); + AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0); + /* Encrypt/decrypt one block and AAD of one block. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, in, AES_BLOCK_SIZE, aad, + AES_BLOCK_SIZE), 0); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain, out, AES_BLOCK_SIZE, aad, + AES_BLOCK_SIZE), 0); + AssertIntEQ(XMEMCMP(plain, in, AES_BLOCK_SIZE), 0); + /* Finalize and check tag matches. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0); + + /* Set key and IV through streaming init API. */ + AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0); + AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0); + /* No data to encrypt/decrypt one byte of AAD. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad, 1), 0); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad, 1), 0); + /* Finalize and check tag matches. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0); + AssertIntEQ(XMEMCMP(tag, expTagAAD1, AES_BLOCK_SIZE), 0); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0); + + /* Set key and IV through streaming init API. */ + AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0); + AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0); + /* Encrypt/decrypt one byte and no AAD. */ + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, in, 1, NULL, 0), 0); + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain, out, 1, NULL, 0), 0); + AssertIntEQ(XMEMCMP(plain, in, 1), 0); + /* Finalize and check tag matches. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0); + AssertIntEQ(XMEMCMP(tag, expTagPlain1, AES_BLOCK_SIZE), 0); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0); + + /* Set key and IV through streaming init API. */ + AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0); + AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0); + /* Encryption AES is one byte at a time */ + for (i = 0; i < (int)sizeof(aad); i++) { + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad + i, 1), + 0); + } + for (i = 0; i < (int)sizeof(in); i++) { + AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out + i, in + i, 1, NULL, 0), + 0); + } + /* Decryption AES is two bytes at a time */ + for (i = 0; i < (int)sizeof(aad); i += 2) { + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad + i, 2), + 0); + } + for (i = 0; i < (int)sizeof(aad); i += 2) { + AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain + i, out + i, 2, NULL, + 0), 0); + } + AssertIntEQ(XMEMCMP(plain, in, sizeof(in)), 0); + /* Finalize and check tag matches. */ + AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0); + AssertIntEQ(XMEMCMP(tag, expTag, AES_BLOCK_SIZE), 0); + AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0); + + /* Check streaming encryption can be decrypted with one shot. */ + AssertIntEQ(wc_AesGcmSetKey(aesDec, key, sizeof(key)), 0); + AssertIntEQ(wc_AesGcmDecrypt(aesDec, plain, out, sizeof(in), iv, + AES_IV_SIZE, tag, AES_BLOCK_SIZE, aad, sizeof(aad)), 0); + AssertIntEQ(XMEMCMP(plain, in, sizeof(in)), 0); + + wc_AesFree(aesEnc); + wc_AesFree(aesDec); + wc_FreeRng(rng); + +#endif + return ret; + +} /* END test_wc_AesGcmStream */ /* @@ -13297,11 +14335,12 @@ static int test_wc_AesCbcEncryptDecrypt (void) 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; - byte vector[] = /* Now is the time for all w/o trailing 0 */ + byte vector[] = /* Now is the time for all good men w/o trailing 0 */ { 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, - 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20, + 0x67,0x6f,0x6f,0x64,0x20,0x6d,0x65,0x6e }; byte iv[] = "1234567890abcdef"; byte enc[sizeof(vector)]; @@ -13331,8 +14370,8 @@ static int test_wc_AesCbcEncryptDecrypt (void) iv, AES_DECRYPTION); } if (ret == 0) { - ret = wc_AesCbcDecrypt(&aes, dec, enc, AES_BLOCK_SIZE); - if (ret != 0 || XMEMCMP(vector, dec, AES_BLOCK_SIZE) != 0) { + ret = wc_AesCbcDecrypt(&aes, dec, enc, sizeof(vector)); + if (ret != 0 || XMEMCMP(vector, dec, sizeof(vector)) != 0) { ret = WOLFSSL_FATAL_ERROR; } else { /* Set flag. */ @@ -13364,6 +14403,16 @@ static int test_wc_AesCbcEncryptDecrypt (void) } else { cbcE = WOLFSSL_FATAL_ERROR; } +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (cbcE == 0) { + cbcE = wc_AesCbcEncrypt(&aes, enc, vector, sizeof(vector) - 1); + } + if (cbcE == BAD_LENGTH_E) { + cbcE = 0; + } else { + cbcE = WOLFSSL_FATAL_ERROR; + } +#endif } if (cbcE == 0) { /* Test passing in size of 0 */ @@ -13371,7 +14420,9 @@ static int test_wc_AesCbcEncryptDecrypt (void) cbcE = wc_AesCbcEncrypt(&aes, enc, vector, 0); if (cbcE == 0) { /* Check enc was not modified */ - cbcE |= enc[0]; + int i; + for (i = 0; i < (int)sizeof(enc); i++) + cbcE |= enc[i]; } } printf(resultFmt, cbcE == 0 ? passed : failed); @@ -13392,11 +14443,19 @@ static int test_wc_AesCbcEncryptDecrypt (void) if (cbcD == BAD_FUNC_ARG) { cbcD = wc_AesCbcDecrypt(&aes, dec, enc, AES_BLOCK_SIZE * 2 - 1); } +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (cbcD == BAD_LENGTH_E) { + cbcD = 0; + } else { + cbcD = WOLFSSL_FATAL_ERROR; + } +#else if (cbcD == BAD_FUNC_ARG) { cbcD = 0; } else { cbcD = WOLFSSL_FATAL_ERROR; } +#endif } if (cbcD == 0) { /* Test passing in size of 0 */ @@ -13404,7 +14463,9 @@ static int test_wc_AesCbcEncryptDecrypt (void) cbcD = wc_AesCbcDecrypt(&aes, dec, enc, 0); if (cbcD == 0) { /* Check dec was not modified */ - cbcD |= dec[0]; + int i; + for (i = 0; i < (int)sizeof(dec); i++) + cbcD |= dec[i]; } } printf(resultFmt, cbcD == 0 ? passed : failed); @@ -15194,7 +16255,7 @@ static int test_wc_CheckProbablePrime (void) ret = 0; } } - + /* Good case */ if (ret == 0) { ret = wc_CheckProbablePrime(p, pSz, q, qSz, e, eSz, @@ -15218,7 +16279,7 @@ static int test_wc_RsaPSS_Verify (void) { int ret = 0; #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && !defined(HAVE_SELFTEST) && \ - !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING) + !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING) && defined(WC_RSA_PSS) RsaKey key; WC_RNG rng; int sz = 256; @@ -15303,7 +16364,7 @@ static int test_wc_RsaPSS_VerifyCheck (void) { int ret = 0; #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && !defined(HAVE_SELFTEST) && \ - !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING) + !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING) && defined(WC_RSA_PSS) RsaKey key; WC_RNG rng; int sz = 256; /* 2048/8 */ @@ -15337,7 +16398,7 @@ static int test_wc_RsaPSS_VerifyCheck (void) ret = wc_Hash(WC_HASH_TYPE_SHA256, pSignature, sz, digest, digestSz); } - + if (ret == 0) { ret = wc_RsaPSS_Sign(digest, digestSz, pSignature, pSignatureSz, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, &key, &rng); @@ -15374,8 +16435,8 @@ static int test_wc_RsaPSS_VerifyCheck (void) if (ret == BAD_FUNC_ARG) { ret = 0; } - } - + } + /* Good case */ if (ret == 0) { ret = wc_RsaPSS_VerifyCheck(pSignature, sz, pt, outLen, @@ -15398,7 +16459,7 @@ static int test_wc_RsaPSS_VerifyCheckInline (void) { int ret = 0; #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && !defined(HAVE_SELFTEST) && \ - !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING) + !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING) && defined(WC_RSA_PSS) RsaKey key; WC_RNG rng; int sz = 256; @@ -15407,8 +16468,8 @@ static int test_wc_RsaPSS_VerifyCheckInline (void) word32 digestSz; unsigned char pSignature[2048/8]; /* 2048 is RSA_KEY_SIZE */ unsigned char pDecrypted[2048/8]; - pt = pDecrypted; - + pt = pDecrypted; + printf(testingFmt, "wc_RsaPSS_VerifyCheckInline()"); @@ -15431,7 +16492,7 @@ static int test_wc_RsaPSS_VerifyCheckInline (void) ret = wc_Hash(WC_HASH_TYPE_SHA256, pSignature, sz, digest, digestSz); } - + if (ret == 0) { ret = wc_RsaPSS_Sign(digest, digestSz, pSignature, sizeof(pSignature), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, &key, &rng); @@ -18839,7 +19900,7 @@ static int test_wc_curve25519_make_key (void) /* * Testing wc_curve25519_shared_secret_ex */ -static int test_wc_curve25519_shared_secret_ex (void) +static int test_wc_curve25519_shared_secret_ex(void) { int ret = 0; #if defined(HAVE_CURVE25519) @@ -18855,9 +19916,9 @@ static int test_wc_curve25519_shared_secret_ex (void) ret = wc_curve25519_init(&private_key); if (ret == 0) { ret = wc_InitRng(&rng); - if (ret == 0) { - ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &private_key); - } + } + if (ret == 0) { + ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &private_key); } if (ret == 0) { ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &public_key); @@ -18871,6 +19932,9 @@ static int test_wc_curve25519_shared_secret_ex (void) if (ret == 0) { ret = wc_curve25519_shared_secret_ex(NULL, NULL, NULL, 0, endian); + if (ret == 0) { + ret = -1; + } if (ret == BAD_FUNC_ARG) { ret = 0; } @@ -18878,28 +19942,40 @@ static int test_wc_curve25519_shared_secret_ex (void) if (ret == 0) { ret = wc_curve25519_shared_secret_ex(NULL, &public_key, out, &outLen, endian); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; } } if (ret == 0) { ret = wc_curve25519_shared_secret_ex(&private_key, NULL, out, &outLen, endian); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; } } if (ret == 0) { ret = wc_curve25519_shared_secret_ex(&private_key, &public_key, NULL, &outLen, endian); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; } } if (ret == 0) { ret = wc_curve25519_shared_secret_ex(&private_key, &public_key, out, NULL, endian); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; } } @@ -18910,7 +19986,10 @@ static int test_wc_curve25519_shared_secret_ex (void) public_key.p.point[CURVE25519_KEYSIZE-1] = 0x8F; ret = wc_curve25519_shared_secret_ex(&private_key, &public_key, out, &outLen, endian); - if (ret == ECC_BAD_ARG_E) { + if (ret == 0) { + ret = -1; + } + else if (ret == ECC_BAD_ARG_E) { ret = 0; } } @@ -18919,7 +19998,10 @@ static int test_wc_curve25519_shared_secret_ex (void) if (ret == 0) { ret = wc_curve25519_shared_secret_ex(&private_key, &public_key, out, &outLen, endian); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; } } @@ -20750,12 +21832,14 @@ static int test_wc_ecc_signVerify_hash (void) #endif word32 siglen = ECC_BUFSIZE; byte sig[ECC_BUFSIZE]; + byte adjustedSig[ECC_BUFSIZE+1]; byte digest[] = TEST_STRING; word32 digestlen = (word32)TEST_STRING_SZ; /* Init stack var */ XMEMSET(sig, 0, siglen); XMEMSET(&key, 0, sizeof(key)); + XMEMSET(adjustedSig, 0, ECC_BUFSIZE+1); /* Init structs. */ ret = wc_InitRng(&rng); @@ -20807,6 +21891,20 @@ static int test_wc_ecc_signVerify_hash (void) if (verify != 1 && ret == 0) { ret = WOLFSSL_FATAL_ERROR; } + + /* test check on length of signature passed in */ + XMEMCPY(adjustedSig, sig, siglen); + adjustedSig[1] = adjustedSig[1] + 1; /* add 1 to length for extra byte*/ +#ifndef NO_STRICT_ECDSA_LEN + AssertIntNE(wc_ecc_verify_hash(adjustedSig, siglen+1, digest, digestlen, + &verify, &key), 0); +#else + /* if NO_STRICT_ECDSA_LEN is set then extra bytes after the signature + * is allowed */ + AssertIntEQ(wc_ecc_verify_hash(adjustedSig, siglen+1, digest, digestlen, + &verify, &key), 0); +#endif + /* Test bad args. */ if (ret == 0) { verifyH = wc_ecc_verify_hash(NULL, siglen, digest, digestlen, @@ -20863,6 +21961,23 @@ static int test_wc_ecc_shared_secret (void) byte out[KEY16]; word32 outlen = (word32)sizeof(out); +#if defined(HAVE_ECC) && !defined(NO_ECC256) + const char* qx = + "bb33ac4c27504ac64aa504c33cde9f36db722dce94ea2bfacb2009392c16e861"; + const char* qy = + "02e9af4dd302939a315b9792217ff0cf18da9111023486e82058330b803489d8"; + const char* d = + "45b66902739c6c85a1385b72e8e8c7acc4038d533504fa6c28dc348de1a8098c"; + const char* curveName = "SECP256R1"; + const byte expected_shared_secret[] = + { + 0x65, 0xc0, 0xd4, 0x61, 0x17, 0xe6, 0x09, 0x75, + 0xf0, 0x12, 0xa0, 0x4d, 0x0b, 0x41, 0x30, 0x7a, + 0x51, 0xf0, 0xb3, 0xaf, 0x23, 0x8f, 0x0f, 0xdf, + 0xf1, 0xff, 0x23, 0x64, 0x28, 0xca, 0xf8, 0x06 + }; +#endif + /* Initialize variables. */ XMEMSET(out, 0, keySz); XMEMSET(&rng, 0, sizeof(rng)); @@ -20876,12 +21991,22 @@ static int test_wc_ecc_shared_secret (void) ret = wc_ecc_init(&pubKey); } } + +#if defined(HAVE_ECC) && !defined(NO_ECC256) + if (ret == 0) { + ret = wc_ecc_import_raw(&key, qx, qy, d, curveName); + } + if (ret == 0) { + ret = wc_ecc_import_raw(&pubKey, qx, qy, NULL, curveName); + } +#else if (ret == 0) { ret = wc_ecc_make_key(&rng, keySz, &key); } if (ret == 0) { ret = wc_ecc_make_key(&rng, keySz, &pubKey); } +#endif #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ @@ -20894,6 +22019,15 @@ static int test_wc_ecc_shared_secret (void) printf(testingFmt, "wc_ecc_shared_secret()"); if (ret == 0) { ret = wc_ecc_shared_secret(&key, &pubKey, out, &outlen); + +#if defined(HAVE_ECC) && !defined(NO_ECC256) + if (ret == 0) { + if (0 != XMEMCMP(out, expected_shared_secret, outlen)) { + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif + /* Test bad args. */ if (ret == 0) { ret = wc_ecc_shared_secret(NULL, &pubKey, out, &outlen); @@ -20907,6 +22041,12 @@ static int test_wc_ecc_shared_secret (void) ret = wc_ecc_shared_secret(&key, &pubKey, out, NULL); } if (ret == BAD_FUNC_ARG) { + /* Invalid length */ + outlen = 1; + ret = wc_ecc_shared_secret(&key, &pubKey, out, &outlen); + } + + if (ret == BUFFER_E) { ret = 0; } else if (ret == 0) { ret = WOLFSSL_FATAL_ERROR; @@ -22710,7 +23850,7 @@ static int test_wc_EccPrivateKeyToDer (void) } if (ret == 0) { ret = wc_EccPrivateKeyToDer(&eccKey, NULL, inLen); - if (ret == BAD_FUNC_ARG) { + if (ret == LENGTH_ONLY_E) { ret = 0; } } @@ -22736,6 +23876,45 @@ static int test_wc_EccPrivateKeyToDer (void) return ret; }/* End test_wc_EccPrivateKeyToDer*/ +/* + * Testing wc_DhPublicKeyDecode + */ +static int test_wc_DhPublicKeyDecode(void) +{ + int ret = 0; + word32 inOutIdx; + +#if defined(WOLFSSL_DH_EXTRA) && defined(USE_CERT_BUFFERS_2048) + DhKey key; + AssertIntEQ(wc_InitDhKey(&key), 0); + printf(testingFmt, "wc_DhPublicKeyDecode()"); + + AssertIntEQ(wc_DhPublicKeyDecode(NULL,NULL,NULL,0), + BAD_FUNC_ARG); + AssertIntEQ(wc_DhPublicKeyDecode(dh_pub_key_der_2048,NULL,NULL,0), + BAD_FUNC_ARG); + AssertIntEQ(wc_DhPublicKeyDecode(dh_pub_key_der_2048,NULL,NULL,0), + BAD_FUNC_ARG); + inOutIdx = 0; + AssertIntEQ(wc_DhPublicKeyDecode(dh_pub_key_der_2048,&inOutIdx,NULL, 0), + BAD_FUNC_ARG); + inOutIdx = 0; + AssertIntEQ(wc_DhPublicKeyDecode(dh_pub_key_der_2048,&inOutIdx,&key, 0), + BAD_FUNC_ARG); + inOutIdx = 0; + AssertIntEQ(wc_DhPublicKeyDecode(dh_pub_key_der_2048,&inOutIdx,&key, + sizeof_dh_pub_key_der_2048), 0); + AssertTrue(key.p.used != 0 && key.g.used != 0 && key.q.used == 0 && + key.pub.used != 0 && key.priv.used == 0); + + wc_FreeDhKey(&key); + printf(resultFmt, passed); + +#endif + (void)inOutIdx; + return ret; +} + /* * Testing wc_Ed25519KeyToDer */ @@ -23022,6 +24201,9 @@ static int test_wc_SetSubjectBuffer (void) derSz = (word32)XFREAD(der, 1, FOURK_BUF, file); XFCLOSE(file); } + else { + ret = -1; + } } if (ret == 0) { ret = wc_InitCert(&cert); @@ -23079,7 +24261,7 @@ static int test_wc_SetSubjectKeyIdFromPublicKey_ex (void) if (ret == 0) { /*ED25519*/ ret = wc_ed25519_init(&ed25519Key); if (ret == 0) { - wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &ed25519Key); + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &ed25519Key); } if (ret == 0) { ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, @@ -23104,7 +24286,7 @@ static int test_wc_SetSubjectKeyIdFromPublicKey_ex (void) if (ret == 0) { /*ECC*/ ret = wc_ecc_init(&eccKey); if (ret == 0) { - wc_ecc_make_key(&rng, KEY14, &eccKey); + ret = wc_ecc_make_key(&rng, KEY14, &eccKey); } if (ret == 0) { ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &eccKey); @@ -23118,7 +24300,7 @@ static int test_wc_SetSubjectKeyIdFromPublicKey_ex (void) if (ret == 0) { /*ED448*/ ret = wc_ed448_init(&ed448Key); if (ret == 0) { - wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key); + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key); } if (ret == 0) { ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED448_TYPE, @@ -23170,7 +24352,7 @@ static int test_wc_SetAuthKeyIdFromPublicKey_ex (void) if (ret == 0) { /*ED25519*/ ret = wc_ed25519_init(&ed25519Key); if (ret == 0) { - wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &ed25519Key); + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &ed25519Key); } if (ret == 0) { ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, @@ -23195,7 +24377,7 @@ static int test_wc_SetAuthKeyIdFromPublicKey_ex (void) if (ret == 0) { /*ECC*/ ret = wc_ecc_init(&eccKey); if (ret == 0) { - wc_ecc_make_key(&rng, KEY14, &eccKey); + ret = wc_ecc_make_key(&rng, KEY14, &eccKey); } if (ret == 0) { ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &eccKey); @@ -23209,7 +24391,7 @@ static int test_wc_SetAuthKeyIdFromPublicKey_ex (void) if (ret == 0) { /*ED448*/ ret = wc_ed448_init(&ed448Key); if (ret == 0) { - wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key); + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key); } if (ret == 0) { ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED448_TYPE, @@ -23604,9 +24786,9 @@ static void test_wc_PKCS7_EncodeSignedData(void) PKCS7* pkcs7; WC_RNG rng; byte output[FOURK_BUF]; - byte badOut[0]; + byte badOut[1]; word32 outputSz = (word32)sizeof(output); - word32 badOutSz = (word32)sizeof(badOut); + word32 badOutSz = 0; byte data[] = "Test data to encode."; #ifndef NO_RSA @@ -24085,8 +25267,8 @@ static void test_wc_PKCS7_VerifySignedData(void) byte output[FOURK_BUF]; word32 outputSz = sizeof(output); byte data[] = "Test data to encode."; - byte badOut[0]; - word32 badOutSz = (word32)sizeof(badOut); + byte badOut[1]; + word32 badOutSz = 0; byte badContent[] = "This is different content than was signed"; AssertIntGT((outputSz = CreatePKCS7SignedData(output, outputSz, data, @@ -25700,22 +26882,26 @@ static int test_wc_HashSetFlags(void) } /* For loop to test not supported cases */ int notSupportedLen = (sizeof(notSupported)/sizeof(enum wc_HashType)); - for (j = 0; j < notSupportedLen; j++){ + for (j = 0; ret == 0 && j < notSupportedLen; j++){ + ret = wc_HashInit(&hash, notSupported[j]); if (ret == 0) { - ret = wc_HashInit(&hash, notSupported[j]); - if (ret == BAD_FUNC_ARG){ + ret = -1; + } + else if (ret == BAD_FUNC_ARG){ + ret = wc_HashSetFlags(&hash, notSupported[j], flags); + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; - if (ret == 0){ - ret = wc_HashSetFlags(&hash, notSupported[j], flags); - if (ret == BAD_FUNC_ARG) { - ret = 0; - } - } } } if (ret == 0) { ret = wc_HashFree(&hash, notSupported[j]); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; } } @@ -25797,22 +26983,26 @@ static int test_wc_HashGetFlags(void) } /* For loop to test not supported cases */ int notSupportedLen = (sizeof(notSupported)/sizeof(enum wc_HashType)); - for (j = 0; j < notSupportedLen; j++){ + for (j = 0; ret == 0 && j < notSupportedLen; j++){ + ret = wc_HashInit(&hash, notSupported[j]); if (ret == 0) { - ret = wc_HashInit(&hash, notSupported[j]); - if (ret == BAD_FUNC_ARG){ + ret = -1; + } + else if (ret == BAD_FUNC_ARG){ + ret = wc_HashGetFlags(&hash, notSupported[j], &flags); + if (ret == 0) { + ret = -1; + } + else if (ret == BAD_FUNC_ARG) { ret = 0; - if (ret == 0){ - ret = wc_HashGetFlags(&hash, notSupported[j], &flags); - if (ret == BAD_FUNC_ARG) { - ret = 0; - } - } } } if (ret == 0) { ret = wc_HashFree(&hash, notSupported[j]); - if (ret == BAD_FUNC_ARG) { + if (ret == 0) { + ret = -1; + } + if (ret == BAD_FUNC_ARG) { ret = 0; } } @@ -26055,6 +27245,41 @@ static void test_wolfSSL_X509_check_host(void) #endif } +static void test_wolfSSL_X509_check_email(void) +{ +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_GEN) + X509* x509; + const char goodEmail[] = "info@wolfssl.com"; + const char badEmail[] = "disinfo@wolfssl.com"; + + printf(testingFmt, "wolfSSL_X509_check_email()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + + /* Should fail on non-matching email address */ + AssertIntEQ(wolfSSL_X509_check_email(x509, badEmail, XSTRLEN(badEmail), 0), + WOLFSSL_FAILURE); + /* Should succeed on matching email address */ + AssertIntEQ(wolfSSL_X509_check_email(x509, goodEmail, XSTRLEN(goodEmail), 0), + WOLFSSL_SUCCESS); + /* Should compute length internally when not provided */ + AssertIntEQ(wolfSSL_X509_check_email(x509, goodEmail, 0, 0), + WOLFSSL_SUCCESS); + /* Should fail when email address is NULL */ + AssertIntEQ(wolfSSL_X509_check_email(x509, NULL, 0, 0), + WOLFSSL_FAILURE); + + X509_free(x509); + + /* Should fail when x509 is NULL */ + AssertIntEQ(wolfSSL_X509_check_email(NULL, goodEmail, 0, 0), + WOLFSSL_FAILURE); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && WOLFSSL_CERT_GEN */ +} + static void test_wolfSSL_DES(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) @@ -26516,9 +27741,13 @@ static void test_wolfSSL_X509_check_private_key(void) AssertNotNull(d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &key, (long)sizeof_server_key_der_2048)); AssertIntEQ(X509_check_private_key(x509, pkey), 0); + + /* test for incorrect parameter */ + AssertIntEQ(X509_check_private_key(NULL, pkey), 0); + AssertIntEQ(X509_check_private_key(x509, NULL), 0); + AssertIntEQ(X509_check_private_key(NULL, NULL), 0); + EVP_PKEY_free(pkey); - - X509_free(x509); printf(resultFmt, passed); #endif @@ -27368,13 +28597,14 @@ static void test_wolfSSL_tmp_dh(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ !defined(NO_DSA) && !defined(NO_RSA) && !defined(NO_DH) && !defined(NO_BIO) - byte buffer[6000]; + byte buff[6000]; char file[] = "./certs/dsaparams.pem"; XFILE f; int bytes; DSA* dsa; DH* dh; -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) +#if defined(WOLFSSL_DH_EXTRA) && \ + (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) DH* dh2; #endif BIO* bio; @@ -27394,10 +28624,10 @@ static void test_wolfSSL_tmp_dh(void) f = XFOPEN(file, "rb"); AssertTrue((f != XBADFILE)); - bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); XFCLOSE(f); - bio = BIO_new_mem_buf((void*)buffer, bytes); + bio = BIO_new_mem_buf((void*)buff, bytes); AssertNotNull(bio); dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); @@ -27405,7 +28635,8 @@ static void test_wolfSSL_tmp_dh(void) dh = wolfSSL_DSA_dup_DH(dsa); AssertNotNull(dh); -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) +#if defined(WOLFSSL_DH_EXTRA) && \ + (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) AssertNotNull(dh2 = wolfSSL_DH_dup(dh)); #endif @@ -27419,7 +28650,8 @@ static void test_wolfSSL_tmp_dh(void) BIO_free(bio); DSA_free(dsa); DH_free(dh); -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) +#if defined(WOLFSSL_DH_EXTRA) && \ + (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) DH_free(dh2); #endif SSL_free(ssl); @@ -28182,7 +29414,284 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) } #endif +static void test_wolfSSL_X509_Name_canon(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_SHA) && \ + defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) + + const long ex_hash1 = 0x0fdb2da4; + const long ex_hash2 = 0x9f3e8c9e; + X509_NAME *name = NULL; + X509 *x509 = NULL; + FILE* file = NULL; + unsigned long hash = 0; + byte digest[WC_MAX_DIGEST_SIZE] = {0}; + byte *pbuf = NULL; + word32 len = 0; + (void) ex_hash2; + printf(testingFmt, "test_wolfSSL_X509_Name_canon()"); + file = XFOPEN(caCertFile, "rb"); + AssertNotNull(file); + AssertNotNull(x509 = PEM_read_X509(file, NULL, NULL, NULL)); + AssertNotNull(name = X509_get_issuer_name(x509)); + + AssertIntGT((len = wolfSSL_i2d_X509_NAME_canon(name, &pbuf)), 0); + AssertIntEQ(wc_ShaHash((const byte*)pbuf, (word32)len, digest), 0); + + hash = (((unsigned long)digest[3] << 24) | + ((unsigned long)digest[2] << 16) | + ((unsigned long)digest[1] << 8) | + ((unsigned long)digest[0])); + AssertIntEQ(hash, ex_hash1); + + XFCLOSE(file); + X509_free(x509); + XFREE(pbuf, NULL, DYNAMIC_TYPE_OPENSSL); + pbuf = NULL; + + file = XFOPEN(cliCertFile, "rb"); + AssertNotNull(file); + AssertNotNull(x509 = PEM_read_X509(file, NULL, NULL, NULL)); + AssertNotNull(name = X509_get_issuer_name(x509)); + + AssertIntGT((len = wolfSSL_i2d_X509_NAME_canon(name, &pbuf)), 0); + AssertIntEQ(wc_ShaHash((const byte*)pbuf, (word32)len, digest), 0); + + hash = (((unsigned long)digest[3] << 24) | + ((unsigned long)digest[2] << 16) | + ((unsigned long)digest[1] << 8) | + ((unsigned long)digest[0])); + + AssertIntEQ(hash, ex_hash2); + + XFCLOSE(file); + X509_free(x509); + XFREE(pbuf, NULL, DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); + +#endif + +} + +static void test_wolfSSL_X509_LOOKUP_ctrl_hash_dir(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + const int MAX_DIR = 4; + const char paths[][32] = { + "./certs/ed25519", + "./certs/ecc", + "./certs/crl", + "./certs/", + }; + + char CertCrl_path[MAX_FILENAME_SZ]; + char *p; + X509_STORE* str; + X509_LOOKUP* lookup; + WOLFSSL_STACK* sk = NULL; + int len, total_len, i; + + (void) sk; + + printf(testingFmt, "test_wolfSSL_X509_LOOKUP_ctrl_hash_dir()"); + + XMEMSET(CertCrl_path, 0, MAX_FILENAME_SZ); + + /* illegal string */ + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, "", + SSL_FILETYPE_PEM,NULL), 0); + + /* free store */ + X509_STORE_free(str); + + /* short folder string */ + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, "./", + SSL_FILETYPE_PEM,NULL), 1); + #if defined(WOLFSSL_INT_H) + /* only available when including internal.h */ + AssertNotNull(sk = lookup->dirs->dir_entry); + #endif + /* free store */ + X509_STORE_free(str); + + /* typical function check */ + p = &CertCrl_path[0]; + total_len = 0; + + for(i = MAX_DIR - 1; i>=0 && total_len < MAX_FILENAME_SZ; i--) { + len = (int)XSTRLEN((const char*)&paths[i]); + total_len += len; + XSTRNCPY(p, paths[i], MAX_FILENAME_SZ - total_len); + p += len; + if (i != 0) *(p++) = SEPARATOR_CHAR; + } + + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, CertCrl_path, + SSL_FILETYPE_PEM,NULL), 1); + #if defined(WOLFSSL_INT_H) + /* only available when including internal.h */ + AssertNotNull(sk = lookup->dirs->dir_entry); + #endif + + X509_STORE_free(str); + + printf(resultFmt, passed); +#endif + +} + +static void test_wolfSSL_X509_LOOKUP_ctrl_file(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + + X509_STORE_CTX* ctx; + X509_STORE* str; + X509_LOOKUP* lookup; + + X509* cert1; + X509* x509Ca; + X509* x509Svr; + X509* issuer; + + WOLFSSL_STACK* sk = NULL; + X509_NAME* caName; + X509_NAME* issuerName; + + FILE* file1 = NULL; + int i, cert_count, cmp; + + char der[] = "certs/ca-cert.der"; + +#ifdef HAVE_CRL + char pem[][100] = { + "./certs/crl/crl.pem", + "./certs/crl/crl2.pem", + "./certs/crl/caEccCrl.pem", + "./certs/crl/eccCliCRL.pem", + "./certs/crl/eccSrvCRL.pem", + "" + }; +#endif + printf(testingFmt, "test_wolfSSL_X509_LOOKUP_ctrl_file()"); + AssertNotNull(file1=fopen("./certs/ca-cert.pem", "rb")); + + AssertNotNull(cert1 = wolfSSL_PEM_read_X509(file1, NULL, NULL, NULL)); + fclose(file1); + + AssertNotNull(ctx = X509_STORE_CTX_new()); + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, caCertFile, + SSL_FILETYPE_PEM,NULL), 1); + AssertNotNull(sk = wolfSSL_CertManagerGetCerts(str->cm)); + AssertIntEQ((cert_count = sk_X509_num(sk)), 1); + + /* check if CA cert is loaded into the store */ + for (i = 0; i < cert_count; i++) { + x509Ca = sk_X509_value(sk, i); + AssertIntEQ(0, wolfSSL_X509_cmp(x509Ca, cert1)); + } + + AssertNotNull((x509Svr = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + + AssertIntEQ(X509_STORE_CTX_init(ctx, str, x509Svr, NULL), SSL_SUCCESS); + + AssertNull(X509_STORE_CTX_get0_current_issuer(NULL)); + issuer = X509_STORE_CTX_get0_current_issuer(ctx); + AssertNotNull(issuer); + + caName = X509_get_subject_name(x509Ca); + AssertNotNull(caName); + issuerName = X509_get_subject_name(issuer); + AssertNotNull(issuerName); + cmp = X509_NAME_cmp(caName, issuerName); + AssertIntEQ(cmp, 0); + + /* load der format */ + X509_free(issuer); + X509_STORE_CTX_free(ctx); + X509_STORE_free(str); + sk_X509_free(sk); + X509_free(x509Svr); + + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, der, + SSL_FILETYPE_ASN1,NULL), 1); + AssertNotNull(sk = wolfSSL_CertManagerGetCerts(str->cm)); + AssertIntEQ((cert_count = sk_X509_num(sk)), 1); + /* check if CA cert is loaded into the store */ + for (i = 0; i < cert_count; i++) { + x509Ca = sk_X509_value(sk, i); + AssertIntEQ(0, wolfSSL_X509_cmp(x509Ca, cert1)); + } + + X509_STORE_free(str); + sk_X509_free(sk); + X509_free(cert1); + +#ifdef HAVE_CRL + AssertNotNull(str = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, caCertFile, + SSL_FILETYPE_PEM,NULL), 1); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, + "certs/server-revoked-cert.pem", + SSL_FILETYPE_PEM,NULL), 1); + if (str) { + AssertIntEQ(wolfSSL_CertManagerVerify(str->cm, svrCertFile, + WOLFSSL_FILETYPE_PEM), 1); + /* since store hasn't yet known the revoked cert*/ + AssertIntEQ(wolfSSL_CertManagerVerify(str->cm, + "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM), 1); + } + for (i = 0; pem[i][0] != '\0'; i++) + { + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, pem[i], + SSL_FILETYPE_PEM, NULL), 1); + } + + if (str) { + /* since store knows crl list */ + AssertIntEQ(wolfSSL_CertManagerVerify(str->cm, + "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM ), CRL_CERT_REVOKED); + } + + AssertIntEQ(X509_LOOKUP_ctrl(NULL, 0, NULL, 0, NULL), 0); + X509_STORE_free(str); + +#endif + + + printf(resultFmt, passed); +#endif +} +static void test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup(void) +{ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup()"); + + X509_STORE_CTX_cleanup(NULL); + X509_STORE_CTX_trusted_stack(NULL, NULL); + AssertTrue(1); /* to confirm previous call gives no harm */ + printf(resultFmt, passed); +#endif +} static void test_wolfSSL_X509_STORE_CTX_get0_current_issuer(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) @@ -28380,6 +29889,28 @@ static void test_wolfSSL_X509_STORE_CTX(void) X509_STORE_CTX_free(ctx); } + /* test X509_STORE_get/set_ex_data */ + { + int i = 0, tmpData = 99; + void* tmpDataRet; + AssertNotNull(str = X509_STORE_new()); + #if defined(HAVE_EX_DATA) + for (i = 0; i < MAX_EX_DATA; i++) { + AssertIntEQ(X509_STORE_set_ex_data(str, i, &tmpData), + WOLFSSL_SUCCESS); + tmpDataRet = (int*)X509_STORE_get_ex_data(str, i); + AssertNotNull(tmpDataRet); + AssertIntEQ(tmpData, *(int*)tmpDataRet); + } + #else + AssertIntEQ(X509_STORE_set_ex_data(str, i, &tmpData), + WOLFSSL_FAILURE); + tmpDataRet = (int*)X509_STORE_get_ex_data(str, i); + AssertNull(tmpDataRet); + #endif + X509_STORE_free(str); + } + printf(resultFmt, passed); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ @@ -28470,6 +30001,57 @@ static void test_wolfSSL_X509_STORE_CTX_set_time(void) #endif /* OPENSSL_EXTRA */ } +static void test_wolfSSL_CTX_get0_set1_param(void) +{ +#if defined(OPENSSL_EXTRA) + int ret; + SSL_CTX* ctx; + WOLFSSL_X509_VERIFY_PARAM* pParam; + WOLFSSL_X509_VERIFY_PARAM* pvpm; + char testIPv4[] = "127.0.0.1"; + char testhostName[] = "foo.hoge.com"; + + printf(testingFmt, "wolfSSL_CTX_get0_set1_param()"); + + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + + AssertNull(SSL_CTX_get0_param(NULL)); + AssertNotNull(pParam = SSL_CTX_get0_param(ctx)); + + pvpm = (WOLFSSL_X509_VERIFY_PARAM *)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), NULL, DYNAMIC_TYPE_OPENSSL); + AssertNotNull(pvpm); + XMEMSET(pvpm, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + + wolfSSL_X509_VERIFY_PARAM_set1_host(pvpm, testhostName, + (int)XSTRLEN(testhostName)); + wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(pvpm, testIPv4); + wolfSSL_X509_VERIFY_PARAM_set_hostflags(pvpm, 0x01); + + ret = SSL_CTX_set1_param(ctx, pvpm); + AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(pParam->hostName, testhostName, + (int)XSTRLEN(testhostName))); + AssertIntEQ(0x01, pParam->hostFlags); + AssertIntEQ(0, XSTRNCMP(pParam->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + + /* test for incorrect patameter */ + AssertIntEQ(1,SSL_CTX_set1_param(ctx, NULL)); + AssertIntEQ(1,SSL_CTX_set1_param(NULL, pvpm)); + AssertIntEQ(1,SSL_CTX_set1_param(NULL, NULL)); + + SSL_CTX_free(ctx); + + XFREE(pvpm, NULL, DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !defined(NO_RSA)*/ +} + static void test_wolfSSL_get0_param(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) @@ -28603,6 +30185,11 @@ static void test_wolfSSL_CTX_add_client_CA(void) SSL_FILETYPE_PEM)); AssertIntEQ(SSL_CTX_add_client_CA(ctx, x509_a), SSL_SUCCESS); + /* test for incorrect parameter */ + AssertIntEQ(SSL_CTX_add_client_CA(NULL, x509), 0); + AssertIntEQ(SSL_CTX_add_client_CA(ctx, NULL), 0); + AssertIntEQ(SSL_CTX_add_client_CA(NULL, NULL), 0); + X509_free(x509); X509_free(x509_a); SSL_CTX_free(ctx); @@ -28830,7 +30417,8 @@ static void test_wolfSSL_X509_STORE(void) static void test_wolfSSL_X509_STORE_load_locations(void) { -#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && !defined(NO_FILESYSTEM) +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && !defined(NO_FILESYSTEM)\ + && !defined(NO_WOLFSSL_DIR) SSL_CTX *ctx; X509_STORE *store; @@ -29070,7 +30658,7 @@ static int msgCb(SSL_CTX *ctx, SSL *ssl) { (void) ctx; (void) ssl; - #ifdef WOLFSSL_QT + #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) STACK_OF(X509)* sk; X509* x509; int i, num; @@ -29079,10 +30667,10 @@ static int msgCb(SSL_CTX *ctx, SSL *ssl) printf("\n===== msgcb called ====\n"); #if defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN) AssertTrue(SSL_get_peer_cert_chain(ssl) != NULL); - AssertIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 1); + AssertIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 2); #endif - #ifdef WOLFSSL_QT + #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) bio = BIO_new(BIO_s_file()); BIO_set_fp(bio, stdout, BIO_NOCLOSE); sk = SSL_get_peer_cert_chain(ssl); @@ -29156,7 +30744,7 @@ static void test_wolfSSL_msgCb(void) #ifndef SINGLE_THREADED start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); - test_client_nofail(&client_args, (void *)msgCb); + test_client_nofail(&client_args, msgCb); join_thread(serverThread); #endif @@ -29316,7 +30904,7 @@ static void test_wolfSSL_DTLS_either_side(void) static void test_generate_cookie(void) { -#if defined(WOLFSSL_DTLS) && defined(OPENSSL_EXTRA) +#if defined(WOLFSSL_DTLS) && defined(OPENSSL_EXTRA) && defined(USE_WOLFSSL_IO) SSL_CTX* ctx; SSL* ssl; byte buf[FOURK_BUF] = {0}; @@ -29562,6 +31150,8 @@ static void test_wolfSSL_BIO(void) for (i = 0; i < 20; i++) { buff[i] = i; } + /* test BIO_free with NULL */ + AssertIntEQ(BIO_free(NULL), WOLFSSL_FAILURE); /* Creating and testing type BIO_s_bio */ AssertNotNull(bio1 = BIO_new(BIO_s_bio())); @@ -29725,12 +31315,18 @@ static void test_wolfSSL_BIO(void) WOLFSSL_SUCCESS); AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); + AssertIntEQ(BIO_tell(f_bio1),sizeof(cert)); AssertIntEQ(BIO_write(f_bio2, msg, sizeof(msg)), sizeof(msg)); + AssertIntEQ(BIO_tell(f_bio2),sizeof(msg)); AssertIntEQ(BIO_write(f_bio2, cert, sizeof(cert)), sizeof(cert)); + AssertIntEQ(BIO_tell(f_bio2),sizeof(cert) + sizeof(msg)); AssertIntEQ((int)BIO_get_fp(f_bio2, &f2), WOLFSSL_SUCCESS); AssertIntEQ(BIO_reset(f_bio2), 0); + AssertIntEQ(BIO_tell(NULL),-1); + AssertIntEQ(BIO_tell(f_bio2),0); AssertIntEQ(BIO_seek(f_bio2, 4), 0); + AssertIntEQ(BIO_tell(f_bio2),4); BIO_free(f_bio1); BIO_free(f_bio2); @@ -29813,6 +31409,51 @@ static void test_wolfSSL_ASN1_BIT_STRING(void) #endif } +static void test_wolfSSL_a2i_ASN1_INTEGER(void) +{ +#ifdef OPENSSL_EXTRA + BIO *bio, *out; + ASN1_INTEGER* ai; + char buf[] = "123456\n12345\n112345678912345678901234567890\n"; + char tmp[1024]; + int tmpSz; + + const char expected1[] = "123456"; + const char expected2[] = "112345678912345678901234567890"; + + printf(testingFmt, "test_wolfSSL_a2i_ASN1_INTEGER()"); + + AssertNotNull(bio = BIO_new_mem_buf(buf, -1)); + AssertNotNull(out = BIO_new(BIO_s_mem())); + AssertNotNull(ai = ASN1_INTEGER_new()); + + /* read first line */ + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS); + AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 6); + XMEMSET(tmp, 0, 1024); + tmpSz = BIO_read(out, tmp, 1024); + AssertIntEQ(tmpSz, 6); + AssertIntEQ(XMEMCMP(tmp, expected1, tmpSz), 0); + + /* fail on second line (not % 2) */ + AssertIntNE(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS); + + /* read 3rd long line */ + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS); + AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 30); + XMEMSET(tmp, 0, 1024); + tmpSz = BIO_read(out, tmp, 1024); + AssertIntEQ(tmpSz, 30); + AssertIntEQ(XMEMCMP(tmp, expected2, tmpSz), 0); + + BIO_free(out); + BIO_free(bio); + ASN1_INTEGER_free(ai); + + printf(resultFmt, passed); + +#endif +} static void test_wolfSSL_DES_ecb_encrypt(void) { @@ -30098,6 +31739,202 @@ static void test_wolfSSL_X509_get_ext_count(void) #endif } +static void test_wolfSSL_X509_sign2(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES) && \ + defined(WOLFSSL_CERT_EXT) && \ + (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)) + + WOLFSSL_X509 *x509, *ca; + const unsigned char *der; + const unsigned char *pt; + WOLFSSL_EVP_PKEY *priv; + WOLFSSL_X509_NAME *name; + WOLFSSL_ASN1_TIME *notBefore, *notAfter; + int derSz; + + const int year = 365*24*60*60; + const int day = 24*60*60; + const int hour = 60*60; + const int mini = 60; + time_t t; + + const unsigned char expected[] = { + 0x30, 0x82, 0x04, 0x25, 0x30, 0x82, 0x03, 0x0D, + 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xF1, 0x5C, 0x99, 0x43, 0x66, 0x3D, 0x96, 0x04, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, + 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, + 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E, + 0x17, 0x0D, 0x30, 0x30, 0x30, 0x32, 0x31, 0x35, + 0x32, 0x30, 0x33, 0x30, 0x30, 0x30, 0x5A, 0x17, + 0x0D, 0x30, 0x31, 0x30, 0x32, 0x31, 0x34, 0x32, + 0x30, 0x33, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x81, + 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, + 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x32, 0x30, 0x34, + 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, + 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x32, 0x30, 0x34, 0x38, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, + 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, + 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, 0x32, + 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, + 0x74, 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, + 0xD6, 0xA6, 0x36, 0xB2, 0x07, 0x32, 0x8E, 0xD0, + 0xBA, 0x69, 0x7B, 0xC6, 0xC3, 0x44, 0x9E, 0xD4, + 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, 0x67, + 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, + 0x1B, 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, + 0xEC, 0xF1, 0x81, 0x1E, 0x7B, 0x9B, 0x03, 0x47, + 0x9A, 0xBF, 0x65, 0xCC, 0x7F, 0x65, 0x24, 0x69, + 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, 0xF7, + 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, + 0x7A, 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, + 0x13, 0x42, 0x8D, 0xD2, 0x3C, 0x40, 0x9C, 0x4C, + 0xEF, 0xD1, 0x86, 0xDF, 0x37, 0x51, 0x1B, 0x0C, + 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, 0xE4, + 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, + 0x97, 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, + 0xAF, 0x20, 0x0B, 0x43, 0x14, 0xC5, 0x74, 0x67, + 0xB4, 0x32, 0x82, 0x6F, 0x8D, 0x86, 0xC2, 0x88, + 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, 0x72, + 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, + 0xCE, 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, + 0x7B, 0xC0, 0x12, 0x03, 0xD4, 0x4E, 0x72, 0x0D, + 0x50, 0x6D, 0x3B, 0xA3, 0x3B, 0xA3, 0x99, 0x5E, + 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, 0x8A, + 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, + 0xFF, 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, + 0xD3, 0x86, 0x40, 0x18, 0x13, 0xB0, 0x63, 0xB5, + 0x72, 0x4E, 0x30, 0xC4, 0x97, 0x84, 0x86, 0x2D, + 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, 0xAE, + 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x6E, 0x30, + 0x6C, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, + 0x1C, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x15, + 0x30, 0x13, 0x87, 0x04, 0x7F, 0x00, 0x00, 0x01, + 0x82, 0x0B, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, + 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1D, 0x06, + 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, + 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18, + 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26, + 0xD7, 0x85, 0x65, 0xC0, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, + 0x18, 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, + 0x26, 0xD7, 0x85, 0x65, 0xC0, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, + 0x00, 0x19, 0xE7, 0xD0, 0x9A, 0xF9, 0x90, 0xAA, + 0xAD, 0x63, 0x58, 0x21, 0x38, 0xA2, 0x4D, 0x30, + 0x9A, 0x6F, 0x88, 0x9E, 0x9B, 0xFB, 0xDE, 0x73, + 0xF2, 0x38, 0xFC, 0x7E, 0x60, 0xC5, 0xFA, 0xBB, + 0x64, 0xA0, 0xD2, 0xC0, 0xBD, 0xB6, 0x4A, 0xAC, + 0x38, 0x90, 0xF5, 0xEE, 0xEC, 0x43, 0x90, 0x7D, + 0x5B, 0xF0, 0x22, 0xA0, 0xAC, 0x59, 0x10, 0xE2, + 0x8D, 0x16, 0xDA, 0x3A, 0xAB, 0x0F, 0x94, 0x11, + 0x6C, 0x0C, 0x61, 0xC1, 0xFD, 0xB5, 0xA3, 0xFC, + 0xE7, 0xFD, 0x0C, 0x63, 0x20, 0xE5, 0x00, 0xCE, + 0xFD, 0xEE, 0x21, 0xE1, 0xE1, 0x9D, 0x48, 0x9B, + 0x71, 0x9C, 0x80, 0x39, 0x5E, 0x5A, 0xD3, 0x32, + 0xA6, 0xAC, 0x3F, 0x84, 0x8C, 0xB6, 0xBC, 0x70, + 0x90, 0xE9, 0xC1, 0x0F, 0xAB, 0xA5, 0x97, 0xD4, + 0xE0, 0x8E, 0x3B, 0xBB, 0x02, 0xE0, 0xED, 0xB0, + 0x10, 0xE8, 0x3F, 0x49, 0xD2, 0x46, 0x4E, 0xE7, + 0x72, 0x0F, 0x1A, 0xFD, 0xE4, 0x59, 0x84, 0x24, + 0xA9, 0x7B, 0x9D, 0x8E, 0x8C, 0xBC, 0xEA, 0xD1, + 0x04, 0x1F, 0xC6, 0x30, 0x47, 0xBD, 0xCC, 0xD1, + 0xBC, 0x87, 0x00, 0xB5, 0x23, 0x3C, 0x60, 0x8F, + 0xB2, 0xDB, 0x71, 0xD2, 0xF5, 0xBA, 0xEB, 0xB1, + 0xD0, 0x53, 0xAC, 0x2E, 0x2C, 0xA5, 0x5D, 0x41, + 0xCD, 0x9B, 0x4F, 0x8B, 0x41, 0xA1, 0x5D, 0x8E, + 0xD9, 0x89, 0x5B, 0x5C, 0x58, 0x1C, 0x4A, 0xE6, + 0x22, 0xC8, 0x15, 0x2D, 0x8E, 0x24, 0x48, 0xF8, + 0xB2, 0x3C, 0x7A, 0x72, 0x62, 0xEC, 0xB2, 0x76, + 0xAD, 0x3D, 0x42, 0x29, 0xE9, 0x3B, 0x4E, 0x7F, + 0x06, 0xA4, 0xA4, 0x72, 0x55, 0xDD, 0x1C, 0x69, + 0x5E, 0x2B, 0x7E, 0xB7, 0x7C, 0xBD, 0xF6, 0x2F, + 0xC9, 0x9A, 0x33, 0x31, 0xD9, 0x92, 0x32, 0xB6, + 0x60, 0x4D, 0x8F, 0x5B, 0xF2, 0xAE, 0xD5, 0x72, + 0x88, 0x92, 0x75, 0xC4, 0xDC, 0xBD, 0x0B, 0xB8, 0x9D + }; + + printf(testingFmt, "wolfSSL_X509_sign2"); + + pt = ca_key_der_2048; + AssertNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, &pt, + sizeof_ca_key_der_2048)); + + pt = client_cert_der_2048; + AssertNotNull(x509 = wolfSSL_d2i_X509(NULL, &pt, + sizeof_client_cert_der_2048)); + + pt = ca_cert_der_2048; + AssertNotNull(ca = wolfSSL_d2i_X509(NULL, &pt, sizeof_ca_cert_der_2048)); + AssertNotNull(name = wolfSSL_X509_get_subject_name(ca)); + AssertIntEQ(wolfSSL_X509_set_issuer_name(x509, name), WOLFSSL_SUCCESS); + + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 7 * day; + AssertNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); + AssertNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); + AssertIntEQ(notAfter->length, 13); + + AssertTrue(wolfSSL_X509_set_notBefore(x509, notBefore)); + AssertTrue(wolfSSL_X509_set_notAfter(x509, notAfter)); + + wolfSSL_X509_sign(x509, priv, EVP_sha256()); + AssertNotNull((der = wolfSSL_X509_get_der(x509, &derSz))); + + AssertIntEQ(derSz, sizeof(expected)); + AssertIntEQ(XMEMCMP(der, expected, derSz), 0); + + wolfSSL_X509_free(ca); + wolfSSL_X509_free(x509); + wolfSSL_EVP_PKEY_free(priv); + wolfSSL_ASN1_TIME_free(notBefore); + wolfSSL_ASN1_TIME_free(notAfter); + printf(resultFmt, passed); +#endif +} + + static void test_wolfSSL_X509_sign(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -30328,51 +32165,136 @@ static void test_wolfSSL_X509_ALGOR_get0(void) static void test_wolfSSL_X509_VERIFY_PARAM(void) { #if defined(OPENSSL_EXTRA) - WOLFSSL_X509_VERIFY_PARAM *param; + X509_VERIFY_PARAM *paramTo; + X509_VERIFY_PARAM *paramFrom; int ret; char testIPv4[] = "127.0.0.1"; char testIPv6[] = "0001:0000:0000:0000:0000:0000:0000:0000/32"; + char testhostName1[] = "foo.hoge.com"; + char testhostName2[] = "foobar.hoge.com"; printf(testingFmt, "wolfSSL_X509()"); - param = wolfSSL_X509_VERIFY_PARAM_new(); - AssertNotNull(param); + paramTo = X509_VERIFY_PARAM_new(); + AssertNotNull(paramTo); + XMEMSET(paramTo, 0, sizeof(X509_VERIFY_PARAM )); - XMEMSET(param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM )); + paramFrom = X509_VERIFY_PARAM_new(); + AssertNotNull(paramFrom); + XMEMSET(paramFrom, 0, sizeof(X509_VERIFY_PARAM )); - wolfSSL_X509_VERIFY_PARAM_set_hostflags(NULL, 0x00); + ret = X509_VERIFY_PARAM_set1_host(paramFrom, testhostName1, + (int)XSTRLEN(testhostName1)); + AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(paramFrom->hostName, testhostName1, + (int)XSTRLEN(testhostName1))); - wolfSSL_X509_VERIFY_PARAM_set_hostflags(param, 0x01); - AssertIntEQ(0x01, param->hostFlags); + X509_VERIFY_PARAM_set_hostflags(NULL, 0x00); - ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(NULL, testIPv4); + X509_VERIFY_PARAM_set_hostflags(paramFrom, 0x01); + AssertIntEQ(0x01, paramFrom->hostFlags); + + ret = X509_VERIFY_PARAM_set1_ip_asc(NULL, testIPv4); AssertIntEQ(0, ret); - ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, testIPv4); + ret = X509_VERIFY_PARAM_set1_ip_asc(paramFrom, testIPv4); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(param->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + AssertIntEQ(0, XSTRNCMP(paramFrom->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); - ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, NULL); + ret = X509_VERIFY_PARAM_set1_ip_asc(paramFrom, NULL); AssertIntEQ(1, ret); - ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, testIPv6); + ret = X509_VERIFY_PARAM_set1_ip_asc(paramFrom, testIPv6); AssertIntEQ(1, ret); - AssertIntEQ(0, XSTRNCMP(param->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); + AssertIntEQ(0, XSTRNCMP(paramFrom->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); - ret = wolfSSL_X509_VERIFY_PARAM_set_flags(param, WOLFSSL_CRL_CHECKALL); + /* null pointer */ + ret = X509_VERIFY_PARAM_set1(NULL, paramFrom); + AssertIntEQ(WOLFSSL_FAILURE, ret); + /* in the case of "from" null, returns success */ + ret = X509_VERIFY_PARAM_set1(paramTo, NULL); + AssertIntEQ(WOLFSSL_SUCCESS, ret); + + ret = X509_VERIFY_PARAM_set1(NULL, NULL); + AssertIntEQ(WOLFSSL_FAILURE, ret); + + /* inherit flags test : VPARAM_DEFAULT */ + ret = X509_VERIFY_PARAM_set1(paramTo, paramFrom); AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, + (int)XSTRLEN(testhostName1))); + AssertIntEQ(0x01, paramTo->hostFlags); + AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); - ret = wolfSSL_X509_VERIFY_PARAM_get_flags(param); - AssertIntEQ(WOLFSSL_CRL_CHECKALL, ret); + /* inherit flags test : VPARAM OVERWRITE */ + X509_VERIFY_PARAM_set1_host(paramTo, testhostName2, + (int)XSTRLEN(testhostName2)); + X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4); + X509_VERIFY_PARAM_set_hostflags(paramTo, 0x00); - ret = wolfSSL_X509_VERIFY_PARAM_clear_flags(param, WOLFSSL_CRL_CHECKALL); + paramTo->inherit_flags = X509_VP_FLAG_OVERWRITE; + + ret = X509_VERIFY_PARAM_set1(paramTo, paramFrom); AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, + (int)XSTRLEN(testhostName1))); + AssertIntEQ(0x01, paramTo->hostFlags); + AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); - ret = wolfSSL_X509_VERIFY_PARAM_get_flags(param); + /* inherit flags test : VPARAM_RESET_FLAGS */ + X509_VERIFY_PARAM_set1_host(paramTo, testhostName2, + (int)XSTRLEN(testhostName2)); + X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4); + X509_VERIFY_PARAM_set_hostflags(paramTo, 0x10); + + paramTo->inherit_flags = X509_VP_FLAG_RESET_FLAGS; + + ret = X509_VERIFY_PARAM_set1(paramTo, paramFrom); + AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName1, + (int)XSTRLEN(testhostName1))); + AssertIntEQ(0x01, paramTo->hostFlags); + AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); + + /* inherit flags test : VPARAM_LOCKED */ + X509_VERIFY_PARAM_set1_host(paramTo, testhostName2, + (int)XSTRLEN(testhostName2)); + X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4); + X509_VERIFY_PARAM_set_hostflags(paramTo, 0x00); + + paramTo->inherit_flags = X509_VP_FLAG_LOCKED; + + ret = X509_VERIFY_PARAM_set1(paramTo, paramFrom); + AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName2, + (int)XSTRLEN(testhostName2))); + AssertIntEQ(0x00, paramTo->hostFlags); + AssertIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + + /* test for incorrect parameters */ + ret = X509_VERIFY_PARAM_set_flags(NULL, X509_V_FLAG_CRL_CHECK_ALL ); AssertIntEQ(0, ret); - wolfSSL_X509_VERIFY_PARAM_free(param); + ret = X509_VERIFY_PARAM_set_flags(NULL, 0 ); + AssertIntEQ(0, ret); + /* inherit flags test : VPARAM_ONCE, not testable yet */ + + ret = X509_VERIFY_PARAM_set_flags(paramTo, X509_V_FLAG_CRL_CHECK_ALL); + AssertIntEQ(1, ret); + + ret = X509_VERIFY_PARAM_get_flags(paramTo); + AssertIntEQ(X509_V_FLAG_CRL_CHECK_ALL, ret); + + ret = X509_VERIFY_PARAM_clear_flags(paramTo, X509_V_FLAG_CRL_CHECK_ALL); + AssertIntEQ(1, ret); + + ret = X509_VERIFY_PARAM_get_flags(paramTo); + AssertIntEQ(0, ret); + + X509_VERIFY_PARAM_free(paramTo); + X509_VERIFY_PARAM_free(paramFrom); + X509_VERIFY_PARAM_free(NULL); /* to confirm NULL parameter gives no harm */ printf(resultFmt, passed); #endif @@ -30472,29 +32394,160 @@ static void test_wolfSSL_BUF(void) #endif /* OPENSSL_EXTRA */ } +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) +static int stub_rand_seed(const void *buf, int num) +{ + (void)buf; + (void)num; + + return 123; +} + +static int stub_rand_bytes(unsigned char *buf, int num) +{ + (void)buf; + (void)num; + + return 456; +} + +static byte* was_stub_rand_cleanup_called(void) +{ + static byte was_called = 0; + + return &was_called; +} + +static void stub_rand_cleanup(void) +{ + byte* was_called = was_stub_rand_cleanup_called(); + + *was_called = 1; + + return; +} + +static byte* was_stub_rand_add_called(void) +{ + static byte was_called = 0; + + return &was_called; +} + +static int stub_rand_add(const void *buf, int num, double entropy) +{ + byte* was_called = was_stub_rand_add_called(); + + (void)buf; + (void)num; + (void)entropy; + + *was_called = 1; + + return 0; +} + +static int stub_rand_pseudo_bytes(unsigned char *buf, int num) +{ + (void)buf; + (void)num; + + return 9876; +} + +static int stub_rand_status(void) +{ + return 5432; +} +#endif /* OPENSSL_EXTRA && !WOLFSSL_NO_OPENSSL_RAND_CB */ + +static void test_wolfSSL_RAND_set_rand_method(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) + RAND_METHOD rand_methods = {NULL, NULL, NULL, NULL, NULL, NULL}; + unsigned char* buf = NULL; + int num = 0; + double entropy = 0; + byte* was_cleanup_called = was_stub_rand_cleanup_called(); + byte* was_add_called = was_stub_rand_add_called(); + + printf(testingFmt, "wolfSSL_RAND_set_rand_method()"); + + buf = (byte*)XMALLOC(32 * sizeof(byte), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + AssertIntNE(wolfSSL_RAND_status(), 5432); + AssertIntEQ(*was_cleanup_called, 0); + RAND_cleanup(); + AssertIntEQ(*was_cleanup_called, 0); + + + rand_methods.seed = &stub_rand_seed; + rand_methods.bytes = &stub_rand_bytes; + rand_methods.cleanup = &stub_rand_cleanup; + rand_methods.add = &stub_rand_add; + rand_methods.pseudorand = &stub_rand_pseudo_bytes; + rand_methods.status = &stub_rand_status; + + AssertIntEQ(RAND_set_rand_method(&rand_methods), WOLFSSL_SUCCESS); + AssertIntEQ(RAND_seed(buf, num), 123); + AssertIntEQ(RAND_bytes(buf, num), 456); + AssertIntEQ(RAND_pseudo_bytes(buf, num), 9876); + AssertIntEQ(RAND_status(), 5432); + + AssertIntEQ(*was_add_called, 0); + /* The function pointer for RAND_add returns int, but RAND_add itself returns void. */ + RAND_add(buf, num, entropy); + AssertIntEQ(*was_add_called, 1); + was_add_called = 0; + AssertIntEQ(*was_cleanup_called, 0); + RAND_cleanup(); + AssertIntEQ(*was_cleanup_called, 1); + *was_cleanup_called = 0; + + + AssertIntEQ(RAND_set_rand_method(NULL), WOLFSSL_SUCCESS); + AssertIntNE(RAND_status(), 5432); + AssertIntEQ(*was_cleanup_called, 0); + RAND_cleanup(); + AssertIntEQ(*was_cleanup_called, 0); + + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !WOLFSSL_NO_OPENSSL_RAND_CB */ +} + static void test_wolfSSL_RAND_bytes(void) { #if defined(OPENSSL_EXTRA) const int size1 = RNG_MAX_BLOCK_LEN; /* in bytes */ - const int size2 = RNG_MAX_BLOCK_LEN + 1; /* in bytes */ + const int size2 = RNG_MAX_BLOCK_LEN + 1; /* in bytes */ const int size3 = RNG_MAX_BLOCK_LEN * 2; /* in bytes */ const int size4 = RNG_MAX_BLOCK_LEN * 4; /* in bytes */ int max_bufsize; byte *my_buf; - - printf(testingFmt, "test_wolfSSL_RAND_bytes()"); - max_bufsize = size4; + printf(testingFmt, "test_wolfSSL_RAND_bytes()"); + /* sanity check */ + AssertIntEQ(RAND_bytes(NULL, 16), 0); + AssertIntEQ(RAND_bytes(NULL, 0), 0); + max_bufsize = size4; + my_buf = (byte*)XMALLOC(max_bufsize * sizeof(byte), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + AssertIntEQ(RAND_bytes(my_buf, 0), 1); + AssertIntEQ(RAND_bytes(my_buf, -1), 0); + AssertNotNull(my_buf); XMEMSET(my_buf, 0, max_bufsize); - AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size1), 1); - AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size2), 1); - AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size3), 1); - AssertIntEQ(wolfSSL_RAND_bytes(my_buf, size4), 1); - + AssertIntEQ(RAND_bytes(my_buf, size1), 1); + AssertIntEQ(RAND_bytes(my_buf, size2), 1); + AssertIntEQ(RAND_bytes(my_buf, size3), 1); + AssertIntEQ(RAND_bytes(my_buf, size4), 1); + XFREE(my_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf(resultFmt, passed); @@ -30502,6 +32555,29 @@ static void test_wolfSSL_RAND_bytes(void) #endif } +static void test_wolfSSL_BN_rand(void) +{ + #if defined(OPENSSL_EXTRA) + BIGNUM* bn; + + printf(testingFmt, "wolfSSL_BN_rand()"); + + AssertNotNull(bn = BN_new()); + AssertIntNE(BN_rand(bn, 0, 0, 0), SSL_SUCCESS); + BN_free(bn); + + AssertNotNull(bn = BN_new()); + AssertIntEQ(BN_rand(bn, 8, 0, 0), SSL_SUCCESS); + BN_free(bn); + + AssertNotNull(bn = BN_new()); + AssertIntEQ(BN_rand(bn, 64, 0, 0), SSL_SUCCESS); + BN_free(bn); + + printf(resultFmt, passed); + #endif +} + static void test_wolfSSL_pseudo_rand(void) { #if defined(OPENSSL_EXTRA) @@ -30744,6 +32820,57 @@ static void test_wolfSSL_PKCS8_d2i(void) #endif /* HAVE_FIPS */ } +#if defined(ERROR_QUEUE_PER_THREAD) && !defined(NO_ERROR_QUEUE) && \ + defined(OPENSSL_EXTRA) && defined(DEBUG_WOLFSSL) +#define LOGGING_THREADS 5 +#define ERROR_COUNT 10 +static volatile int loggingThreadsReady; +static THREAD_RETURN WOLFSSL_THREAD test_logging(void* args) +{ + const char* file; + int line; + int err; + int errorCount = 0; + int i; + + (void)args; + + while (!loggingThreadsReady); + for (i = 0; i < ERROR_COUNT; i++) + ERR_put_error(ERR_LIB_PEM, SYS_F_ACCEPT, -990 - i, __FILE__, __LINE__); + + while ((err = ERR_get_error_line(&file, &line))) { + AssertIntEQ(err, 990 + errorCount); + errorCount++; + } + AssertIntEQ(errorCount, ERROR_COUNT); + + return 0; +} +#endif + +static void test_error_queue_per_thread(void) +{ +#if defined(ERROR_QUEUE_PER_THREAD) && !defined(NO_ERROR_QUEUE) && \ + defined(OPENSSL_EXTRA) && defined(DEBUG_WOLFSSL) + THREAD_TYPE loggingThreads[LOGGING_THREADS]; + int i; + + printf(testingFmt, "error_queue_per_thread()"); + + ERR_clear_error(); /* clear out any error nodes */ + + loggingThreadsReady = 0; + for (i = 0; i < LOGGING_THREADS; i++) + start_thread(test_logging, NULL, &loggingThreads[i]); + loggingThreadsReady = 1; + for (i = 0; i < LOGGING_THREADS; i++) + join_thread(loggingThreads[i]); + + printf(resultFmt, passed); +#endif +} + static void test_wolfSSL_ERR_put_error(void) { #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ @@ -30824,15 +32951,15 @@ static void test_wolfSSL_ERR_print_errors(void) AssertNotNull(bio = BIO_new(BIO_s_mem())); ERR_clear_error(); /* clear out any error nodes */ ERR_put_error(0,SYS_F_ACCEPT, -173, "ssl.c", 0); - /* Choosing -295 as an unused errno between MIN_CODE_E < x < WC_LAST_E. */ - ERR_put_error(0,SYS_F_BIND, -295, "asn.c", 100); + /* Choosing -299 as an unused errno between MIN_CODE_E < x < WC_LAST_E. */ + ERR_put_error(0,SYS_F_BIND, -299, "asn.c", 100); ERR_print_errors(bio); AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 56); AssertIntEQ(XSTRNCMP("error:173:wolfSSL library:Bad function argument:ssl.c:0", buf, 55), 0); AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 57); - AssertIntEQ(XSTRNCMP("error:295:wolfSSL library:unknown error number:asn.c:100", + AssertIntEQ(XSTRNCMP("error:299:wolfSSL library:unknown error number:asn.c:100", buf, 56), 0); AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 1); AssertIntEQ(buf[0], '\0'); @@ -31104,15 +33231,6 @@ static void test_wolfSSL_OBJ(void) ASN1_STRING *asn1 = NULL; unsigned char *buf_dyn = NULL; - PKCS12 *p12; - int boolRet; - EVP_PKEY *pkey = NULL; - const char *p12_f[] = { - #if !defined(NO_DES3) && !defined(NO_RSA) - "./certs/test-servercert.p12", - #endif - NULL}; - printf(testingFmt, "wolfSSL_OBJ()"); AssertIntEQ(OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1), SSL_FAILURE); @@ -31170,27 +33288,42 @@ static void test_wolfSSL_OBJ(void) } - for (i = 0; p12_f[i] != NULL; i++) +#ifdef HAVE_PKCS12 { - AssertTrue((fp = XFOPEN(p12_f[i], "rb")) != XBADFILE); - AssertNotNull(p12 = d2i_PKCS12_fp(fp, NULL)); - XFCLOSE(fp); - AssertTrue((boolRet = PKCS12_parse(p12, "wolfSSL test", &pkey, &x509, NULL)) > 0); - wc_PKCS12_free(p12); - EVP_PKEY_free(pkey); - x509Name = X509_get_issuer_name(x509); - AssertNotNull(x509Name); - AssertIntNE((numNames = X509_NAME_entry_count(x509Name)), 0); - AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); - for (j = 0; j < numNames; j++) + PKCS12 *p12; + int boolRet; + EVP_PKEY *pkey = NULL; + const char *p12_f[] = { + #if !defined(NO_DES3) && !defined(NO_RSA) + "./certs/test-servercert.p12", + #endif + NULL}; + + for (i = 0; p12_f[i] != NULL; i++) { - AssertNotNull(x509NameEntry = X509_NAME_get_entry(x509Name, j)); - AssertNotNull(asn1Name = X509_NAME_ENTRY_get_object(x509NameEntry)); - AssertTrue((nid = OBJ_obj2nid(asn1Name)) > 0); + AssertTrue((fp = XFOPEN(p12_f[i], "rb")) != XBADFILE); + AssertNotNull(p12 = d2i_PKCS12_fp(fp, NULL)); + XFCLOSE(fp); + AssertTrue((boolRet = PKCS12_parse(p12, "wolfSSL test", + &pkey, &x509, NULL)) > 0); + wc_PKCS12_free(p12); + EVP_PKEY_free(pkey); + x509Name = X509_get_issuer_name(x509); + AssertNotNull(x509Name); + AssertIntNE((numNames = X509_NAME_entry_count(x509Name)), 0); + AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); + for (j = 0; j < numNames; j++) + { + AssertNotNull(x509NameEntry = X509_NAME_get_entry(x509Name, j)); + AssertNotNull(asn1Name = + X509_NAME_ENTRY_get_object(x509NameEntry)); + AssertTrue((nid = OBJ_obj2nid(asn1Name)) > 0); + } + BIO_free(bio); + X509_free(x509); } - BIO_free(bio); - X509_free(x509); } +#endif /* HAVE_PKCS12 */ printf(resultFmt, passed); #endif @@ -31736,7 +33869,7 @@ static void test_wolfSSL_BIO_puts(void) #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \ - defined(HAVE_IO_TESTS_DEPENDENCIES) + defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(USE_WOLFSSL_IO) static int forceWantRead(WOLFSSL *ssl, char *buf, int sz, void *ctx) { (void)ssl; @@ -31751,7 +33884,7 @@ static void test_wolfSSL_BIO_should_retry(void) { #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \ - defined(HAVE_IO_TESTS_DEPENDENCIES) + defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(USE_WOLFSSL_IO) tcp_ready ready; func_args server_args; THREAD_TYPE serverThread; @@ -31833,6 +33966,75 @@ static void test_wolfSSL_BIO_should_retry(void) #endif } +static void test_wolfSSL_BIO_connect(void) +{ +#if defined(OPENSSL_ALL) && defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_HTTP_CLIENT) + tcp_ready ready; + func_args server_args; + THREAD_TYPE serverThread; + BIO *tcp_bio; + BIO *ssl_bio; + SSL_CTX* ctx; + SSL *ssl; + char msg[] = "hello wolfssl!"; + char reply[30]; + char buff[10] = {0}; + + printf(testingFmt, "wolfSSL_BIO_new_connect()"); + + /* Setup server */ + XMEMSET(&server_args, 0, sizeof(func_args)); + StartTCP(); + InitTcpReady(&ready); +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + server_args.signal = &ready; + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + AssertIntGT(XSPRINTF(buff, "%d", ready.port), 0); + + /* Start the test proper */ + /* Setup the TCP BIO */ + AssertNotNull(tcp_bio = BIO_new_connect(wolfSSLIP)); + AssertIntEQ(BIO_set_conn_port(tcp_bio, buff), 1); + /* Setup the SSL object */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + SSL_set_connect_state(ssl); + /* Setup the SSL BIO */ + AssertNotNull(ssl_bio = BIO_new(BIO_f_ssl())); + AssertIntEQ(BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE), 1); + /* Link BIO's so that ssl_bio uses tcp_bio for IO */ + AssertPtrEq(BIO_push(ssl_bio, tcp_bio), ssl_bio); + /* Do TCP connect */ + AssertIntEQ(BIO_do_connect(ssl_bio), 1); + /* Do TLS handshake */ + AssertIntEQ(BIO_do_handshake(ssl_bio), 1); + /* Test writing */ + AssertIntEQ(BIO_write(ssl_bio, msg, sizeof(msg)), sizeof(msg)); + /* Expect length of default wolfSSL reply */ + AssertIntEQ(BIO_read(ssl_bio, reply, sizeof(reply)), 23); + + /* Clean it all up */ + BIO_free_all(ssl_bio); + SSL_CTX_free(ctx); + + /* Server clean up */ + join_thread(serverThread); + FreeTcpReady(&ready); + + printf(resultFmt, passed); +#endif +} + static void test_wolfSSL_BIO_write(void) { #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE) @@ -32121,6 +34323,16 @@ static void test_wolfSSL_SESSION(void) AssertIntEQ(wolfSSL_read(ssl, msg, sizeof(msg)), 23); sess = wolfSSL_get_session(ssl); + + + #if defined(OPENSSL_EXTRA) + AssertIntEQ(SSL_SESSION_is_resumable(NULL), 0); + AssertIntEQ(SSL_SESSION_is_resumable(sess), 1); + #else + AssertIntEQ(wolfSSL_SESSION_is_resumable(NULL), 0); + AssertIntEQ(wolfSSL_SESSION_is_resumable(sess), 1); + #endif + wolfSSL_shutdown(ssl); wolfSSL_free(ssl); @@ -32284,6 +34496,26 @@ static void test_wolfSSL_d2i_PUBKEY(void) EVP_PKEY_free(pkey); #endif +#if defined(USE_CERT_BUFFERS_2048) && !defined(NO_DSA) + /* DSA PUBKEY test */ + AssertIntGT(BIO_write(bio, dsa_pub_key_der_2048, + sizeof_dsa_pub_key_der_2048), 0); + AssertNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); + EVP_PKEY_free(pkey); +#endif + +#if defined(USE_CERT_BUFFERS_2048) && !defined(NO_DH) && \ +defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) + /* DH PUBKEY test */ + AssertIntGT(BIO_write(bio, dh_pub_key_der_2048, + sizeof_dh_pub_key_der_2048), 0); + AssertNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); + EVP_PKEY_free(pkey); +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* USE_CERT_BUFFERS_2048 && !NO_DH && && OPENSSL_EXTRA */ + BIO_free(bio); (void)pkey; @@ -32501,6 +34733,11 @@ static void test_wolfSSL_RSA(void) AssertNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); AssertIntEQ(RSA_size(rsa), 256); + + /* sanity check */ + AssertIntEQ(RSA_bits(NULL), 0); + + AssertIntEQ(RSA_bits(rsa), 2048); RSA_get0_key(rsa, &n, &e, &d); AssertPtrEq(rsa->n, n); AssertPtrEq(rsa->e, e); @@ -32512,11 +34749,15 @@ static void test_wolfSSL_RSA(void) AssertPtrEq(rsa->n, n); AssertPtrEq(rsa->e, e); AssertPtrEq(rsa->d, d); + + AssertIntEQ(BN_hex2bn(&rsa->n, "1FFFFF"), 1); + AssertIntEQ(RSA_bits(rsa), 21); RSA_free(rsa); - + #if !defined(USE_FAST_MATH) || (FP_MAX_BITS >= (3072*2)) AssertNotNull(rsa = RSA_generate_key(3072, 17, NULL, NULL)); AssertIntEQ(RSA_size(rsa), 384); + AssertIntEQ(RSA_bits(rsa), 3072); RSA_free(rsa); #endif @@ -33036,7 +35277,7 @@ static void test_wolfSSL_SHA(void) #if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) printf(testingFmt, "wolfSSL_SHA()"); - #if !defined(NO_SHA) + #if !defined(NO_SHA) && defined(NO_OLD_SHA_NAMES) { const unsigned char in[] = "abc"; unsigned char expected[] = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" @@ -33046,6 +35287,18 @@ static void test_wolfSSL_SHA(void) XMEMSET(out, 0, WC_SHA_DIGEST_SIZE); AssertNotNull(SHA1(in, XSTRLEN((char*)in), out)); AssertIntEQ(XMEMCMP(out, expected, WC_SHA_DIGEST_SIZE), 0); + + /* SHA interface test */ + XMEMSET(out, 0, WC_SHA_DIGEST_SIZE); + + AssertNull(SHA(NULL, XSTRLEN((char*)in), out)); + AssertNotNull(SHA(in, 0, out)); + AssertNotNull(SHA(in, XSTRLEN((char*)in), NULL)); + AssertNotNull(SHA(NULL, 0, out)); + AssertNotNull(SHA(NULL, 0, NULL)); + + AssertNotNull(SHA(in, XSTRLEN((char*)in), out)); + AssertIntEQ(XMEMCMP(out, expected, WC_SHA_DIGEST_SIZE), 0); } #endif @@ -33156,10 +35409,8 @@ static void test_wolfSSL_DH_1536_prime(void) static void test_wolfSSL_PEM_write_DHparams(void) { -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) -#if defined(OPENSSL_EXTRA) && !defined(NO_DH) && !defined(NO_FILESYSTEM) -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) -#ifndef NO_BIO +#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) && \ + !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) DH* dh; BIO* bio; XFILE fp; @@ -33199,9 +35450,6 @@ tgZl96bcAGdru8OpQYP7x/rI4h5+rwA/kwIBAg==\n\ XFCLOSE(fp); printf(resultFmt, passed); -#endif /* !NO_BIO */ -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* OPENSSL_ALL || OPENSSL_QT */ #endif } @@ -33255,6 +35503,272 @@ static void test_wolfSSL_AES_ecb_encrypt(void) #endif } +static void test_wolfSSL_MD5(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_MD5) + byte input1[] = ""; + byte input2[] = "message digest"; + byte hash[WC_MD5_DIGEST_SIZE]; + unsigned char output1[] = + "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e"; + unsigned char output2[] = + "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0"; + WOLFSSL_MD5_CTX md5; + + printf(testingFmt, "wolfSSL_MD5()"); + + XMEMSET(&md5, 0, sizeof(md5)); + + /* Test cases for illegal parameters */ + AssertIntEQ(MD5_Init(NULL), 0); + AssertIntEQ(MD5_Init(&md5), 1); + AssertIntEQ(MD5_Update(NULL, input1, 0), 0); + AssertIntEQ(MD5_Update(NULL, NULL, 0), 0); + AssertIntEQ(MD5_Update(&md5, NULL, 1), 0); + AssertIntEQ(MD5_Final(NULL, &md5), 0); + AssertIntEQ(MD5_Final(hash, NULL), 0); + AssertIntEQ(MD5_Final(NULL, NULL), 0); + + /* Init MD5 CTX */ + AssertIntEQ(wolfSSL_MD5_Init(&md5), 1); + AssertIntEQ(wolfSSL_MD5_Update(&md5, input1, + XSTRLEN((const char*)&input1)), 1); + AssertIntEQ(wolfSSL_MD5_Final(hash, &md5), 1); + AssertIntEQ(XMEMCMP(&hash, output1, WC_MD5_DIGEST_SIZE), 0); + + /* Init MD5 CTX */ + AssertIntEQ(wolfSSL_MD5_Init(&md5), 1); + AssertIntEQ(wolfSSL_MD5_Update(&md5, input2, + (int)XSTRLEN((const char*)input2)), 1); + AssertIntEQ(wolfSSL_MD5_Final(hash, &md5), 1); + AssertIntEQ(XMEMCMP(&hash, output2, WC_MD5_DIGEST_SIZE), 0); +#if !defined(NO_OLD_NAMES) && \ + (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))) + AssertIntNE(MD5(NULL, 1, (byte*)&hash), 0); + AssertIntEQ(MD5(input1, 0, (byte*)&hash), 0); + AssertIntNE(MD5(input1, 1, NULL), 0); + AssertIntNE(MD5(NULL, 0, NULL), 0); + + AssertIntEQ(MD5(input1, (int)XSTRLEN((const char*)&input1), (byte*)&hash), 0); + AssertIntEQ(XMEMCMP(&hash, output1, WC_MD5_DIGEST_SIZE), 0); + + AssertIntEQ(MD5(input2, (int)XSTRLEN((const char*)&input2), (byte*)&hash), 0); + AssertIntEQ(XMEMCMP(&hash, output2, WC_MD5_DIGEST_SIZE), 0); +#endif + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_MD5_Transform(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_MD5) + byte input1[] = ""; + byte input2[] = "abc"; + byte local[WC_MD5_BLOCK_SIZE]; + word32 sLen = 0; + unsigned char output1[] = + "\xac\x1d\x1f\x03\xd0\x8e\xa5\x6e\xb7\x67\xab\x1f\x91\x77\x31\x74"; + unsigned char output2[] = + "\x8d\x79\xd3\xef\x90\x25\x17\x67\xc7\x79\x13\xa4\xbc\x7b\xa7\xe3"; + + MD5_CTX md5; + + printf(testingFmt, "wolfSSL_MD5_Transform()"); + + XMEMSET(&md5, 0, sizeof(md5)); + XMEMSET(&local, 0, sizeof(local)); + + /* sanity check */ + AssertIntEQ(MD5_Transform(NULL, NULL), 0); + AssertIntEQ(MD5_Transform(NULL, (const byte*)&input1), 0); + AssertIntEQ(MD5_Transform(&md5, NULL), 0); + AssertIntEQ(wc_Md5Transform(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wc_Md5Transform(NULL, (const byte*)&input1), BAD_FUNC_ARG); + AssertIntEQ(wc_Md5Transform((wc_Md5*)&md5, NULL), BAD_FUNC_ARG); + + /* Init MD5 CTX */ + AssertIntEQ(wolfSSL_MD5_Init(&md5), 1); + /* Do Transform*/ + sLen = (word32)XSTRLEN((char*)input1); + XMEMCPY(local, input1, sLen); + AssertIntEQ(MD5_Transform(&md5, (const byte*)&local[0]), 1); + + AssertIntEQ(XMEMCMP(&((wc_Md5*)&md5)->digest[0], output1, + WC_MD5_DIGEST_SIZE), 0); + + /* Init MD5 CTX */ + AssertIntEQ(MD5_Init(&md5), 1); + sLen = (word32)XSTRLEN((char*)input2); + XMEMSET(local, 0, WC_MD5_BLOCK_SIZE); + XMEMCPY(local, input2, sLen); + AssertIntEQ(MD5_Transform(&md5, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Md5*)&md5)->digest[0], output2, + WC_MD5_DIGEST_SIZE), 0); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_SHA224(void) +{ +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SHA224) && \ + !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) + unsigned char input[] = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + unsigned char output[] = + "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01" + "\x50\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25"; + size_t inLen; + byte hash[WC_SHA224_DIGEST_SIZE]; + + printf(testingFmt, "wolfSSL_SHA224()"); + inLen = XSTRLEN((char*)input); + + XMEMSET(hash, 0, WC_SHA224_DIGEST_SIZE); + + AssertNull(SHA224(NULL, inLen, hash)); + AssertNotNull(SHA224(input, 0, hash)); + AssertNotNull(SHA224(input, inLen, NULL)); + AssertNotNull(SHA224(NULL, 0, hash)); + AssertNotNull(SHA224(NULL, 0, NULL)); + + AssertNotNull(SHA224(input, inLen, hash)); + AssertIntEQ(XMEMCMP(hash, output, WC_SHA224_DIGEST_SIZE), 0); + + printf(resultFmt, passed); +#endif +} +static void test_wolfSSL_SHA_Transform(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA) +#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + byte input1[] = ""; + byte input2[] = "abc"; + byte local[WC_SHA_BLOCK_SIZE]; + word32 sLen = 0; + unsigned char output1[] = + "\xe5\x04\xb4\x92\xed\x8c\x58\x56\x4e\xcd\x1a\x6c\x68\x3f\x05\xbf" + "\x93\x3a\xf7\x09"; + unsigned char output2[] = + "\x8b\x74\xb2\x97\xca\xbc\x5b\x4f\xea\xe6\xc0\x5b\xa0\xb4\x40\x2d" + "\xb8\x08\x6e\x7c"; + + SHA_CTX sha; + SHA_CTX sha1; + + printf(testingFmt, "wolfSSL_SHA_Transform()"); + + XMEMSET(&sha, 0, sizeof(sha)); + XMEMSET(&local, 0, sizeof(local)); + + /* sanity check */ + AssertIntEQ(SHA_Transform(NULL, NULL), 0); + AssertIntEQ(SHA_Transform(NULL, (const byte*)&input1), 0); + AssertIntEQ(SHA_Transform(&sha, NULL), 0); + AssertIntEQ(SHA1_Transform(NULL, NULL), 0); + AssertIntEQ(SHA1_Transform(NULL, (const byte*)&input1), 0); + AssertIntEQ(SHA1_Transform(&sha, NULL), 0); + AssertIntEQ(wc_ShaTransform(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wc_ShaTransform(NULL, (const byte*)&input1), BAD_FUNC_ARG); + AssertIntEQ(wc_ShaTransform((wc_Sha*)&sha, NULL), BAD_FUNC_ARG); + + /* Init SHA CTX */ + AssertIntEQ(SHA_Init(&sha), 1); + /* Do Transform*/ + sLen = (word32)XSTRLEN((char*)input1); + XMEMCPY(local, input1, sLen); + AssertIntEQ(SHA_Transform(&sha, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha)->digest[0], output1, + WC_SHA_DIGEST_SIZE), 0); + /* Init SHA CTX */ + AssertIntEQ(SHA_Init(&sha), 1); + sLen = (word32)XSTRLEN((char*)input2); + XMEMSET(local, 0, WC_SHA_BLOCK_SIZE); + XMEMCPY(local, input2, sLen); + AssertIntEQ(SHA_Transform(&sha, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha)->digest[0], output2, + WC_SHA_DIGEST_SIZE), 0); + /* SHA1 */ + XMEMSET(local, 0, WC_SHA_BLOCK_SIZE); + /* Init SHA CTX */ + AssertIntEQ(SHA1_Init(&sha1), 1); + /* Do Transform*/ + sLen = (word32)XSTRLEN((char*)input1); + XMEMCPY(local, input1, sLen); + AssertIntEQ(SHA1_Transform(&sha1, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha1)->digest[0], output1, + WC_SHA_DIGEST_SIZE), 0); + /* Init SHA CTX */ + AssertIntEQ(SHA1_Init(&sha1), 1); + sLen = (word32)XSTRLEN((char*)input2); + XMEMSET(local, 0, WC_SHA_BLOCK_SIZE); + XMEMCPY(local, input2, sLen); + AssertIntEQ(SHA1_Transform(&sha1, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha*)&sha1)->digest[0], output2, + WC_SHA_DIGEST_SIZE), 0); + + printf(resultFmt, passed); +#endif +#endif +} + +static void test_wolfSSL_SHA256_Transform(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) +#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + byte input1[] = ""; + byte input2[] = "abc"; + byte local[WC_SHA256_BLOCK_SIZE]; + word32 sLen = 0; + unsigned char output1[] = + "\xbe\x98\x56\xda\x69\xb4\xb9\x17\x99\x57\x33\x62\xca\xbe\x9f\x77" + "\x91\xd4\xe5\x8c\x43\x62\xd2\xc0\xea\xf9\xfe\xba\xd8\xa9\x37\x18"; + unsigned char output2[] = + "\x67\xd4\x4e\x1d\x67\x61\x7c\x67\x26\x76\x10\x44\xb8\xff\x10\x78" + "\x39\x9a\xc8\x40\x8c\x60\x16\x73\x05\xd6\x61\xa6\x35\x8c\xf2\x91"; + + SHA256_CTX sha256; + + printf(testingFmt, "wolfSSL_SHA256_Transform()"); + + XMEMSET(&sha256, 0, sizeof(sha256)); + XMEMSET(&local, 0, sizeof(local)); + + /* sanity check */ + AssertIntEQ(SHA256_Transform(NULL, NULL), 0); + AssertIntEQ(SHA256_Transform(NULL, (const byte*)&input1), 0); + AssertIntEQ(SHA256_Transform(&sha256, NULL), 0); + AssertIntEQ(wc_Sha256Transform(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wc_Sha256Transform(NULL, (const byte*)&input1), BAD_FUNC_ARG); + AssertIntEQ(wc_Sha256Transform((wc_Sha256*)&sha256, NULL), BAD_FUNC_ARG); + + /* Init SHA256 CTX */ + AssertIntEQ(SHA256_Init(&sha256), 1); + /* Do Transform*/ + sLen = (word32)XSTRLEN((char*)input1); + XMEMCPY(local, input1, sLen); + AssertIntEQ(SHA256_Transform(&sha256, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha256*)&sha256)->digest[0], output1, + WC_SHA256_DIGEST_SIZE), 0); + + /* Init SHA256 CTX */ + AssertIntEQ(SHA256_Init(&sha256), 1); + sLen = (word32)XSTRLEN((char*)input2); + XMEMSET(local, 0, WC_SHA256_BLOCK_SIZE); + XMEMCPY(local, input2, sLen); + AssertIntEQ(SHA256_Transform(&sha256, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha256*)&sha256)->digest[0], output2, + WC_SHA256_DIGEST_SIZE), 0); + + printf(resultFmt, passed); +#endif +#endif +} + static void test_wolfSSL_SHA256(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) && \ @@ -33279,6 +35793,65 @@ static void test_wolfSSL_SHA256(void) #endif } +static void test_wolfSSL_SHA512_Transform(void) +{ +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SHA512) +#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + byte input1[] = ""; + byte input2[] = "abc"; + byte local[WC_SHA512_BLOCK_SIZE]; + word32 sLen = 0; + unsigned char output1[] = + "\xe8\xcb\x4a\x77\xd5\x81\x78\xcf\x70\x80\xc7\xfb\xe0\x62\x33\x53" + "\xda\x0e\x46\x87\x9d\x63\x67\x02\xb0\x31\x59\xe8\x40\xcb\x86\x30" + "\xa3\x23\xa0\x88\x52\xc9\x7d\x71\xe0\xb5\xe0\x4c\xc1\xb2\xba\x96" + "\x0b\x3e\xe3\xea\x04\xfe\xc4\x6f\xee\x8b\x66\xbd\x0c\xd8\xf4\x91"; + unsigned char output2[] = + "\x0d\xcc\xa0\xeb\x4e\x93\x10\x11\x21\xc8\x04\xfb\x9c\x43\x33\xfd" + "\x41\x31\xab\xca\x3d\x26\xb4\xa9\xab\xd7\x67\xe1\xaf\xaa\xc6\xe2" + "\x83\x4e\xba\x2c\x54\x2e\x8f\x31\x98\x38\x2b\x8f\x9d\xec\x88\xbe" + "\x4d\x5e\x8b\x53\x9d\x4e\xd2\x14\xf0\x96\x20\xaf\x69\x6c\x68\xde"; + + SHA512_CTX sha512; + + printf(testingFmt, "wolfSSL_SHA512_Transform()"); + + XMEMSET(&sha512, 0, sizeof(sha512)); + XMEMSET(&local, 0, sizeof(local)); + + /* sanity check */ + AssertIntEQ(SHA512_Transform(NULL, NULL), 0); + AssertIntEQ(SHA512_Transform(NULL, (const byte*)&input1), 0); + AssertIntEQ(SHA512_Transform(&sha512, NULL), 0); + AssertIntEQ(wc_Sha512Transform(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wc_Sha512Transform(NULL, (const byte*)&input1), BAD_FUNC_ARG); + AssertIntEQ(wc_Sha512Transform((wc_Sha512*)&sha512, NULL), BAD_FUNC_ARG); + + /* Init SHA512 CTX */ + AssertIntEQ(wolfSSL_SHA512_Init(&sha512), 1); + + /* Do Transform*/ + sLen = (word32)XSTRLEN((char*)input1); + XMEMCPY(local, input1, sLen); + AssertIntEQ(SHA512_Transform(&sha512, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha512*)&sha512)->digest[0], output1, + WC_SHA512_DIGEST_SIZE), 0); + + /* Init SHA512 CTX */ + AssertIntEQ(SHA512_Init(&sha512), 1); + sLen = (word32)XSTRLEN((char*)input2); + XMEMSET(local, 0, WC_SHA512_BLOCK_SIZE); + XMEMCPY(local, input2, sLen); + AssertIntEQ(SHA512_Transform(&sha512, (const byte*)&local[0]), 1); + AssertIntEQ(XMEMCMP(&((wc_Sha512*)&sha512)->digest[0], output2, + WC_SHA512_DIGEST_SIZE), 0); + (void)input1; + printf(resultFmt, passed); +#endif +#endif +} + static void test_wolfSSL_X509_get_serialNumber(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) @@ -33377,6 +35950,57 @@ static void test_wolfSSL_OpenSSL_add_all_algorithms(void){ #endif } +static void test_wolfSSL_OPENSSL_hexstr2buf(void) +{ +#if defined(OPENSSL_EXTRA) + struct Output { + const unsigned char* buffer; + long ret; + }; + enum { NUM_CASES = 5 }; + int i; + int j; + + const char* inputs[NUM_CASES] = { + "aabcd1357e", + "01:12:23:34:a5:b6:c7:d8:e9", + ":01:02", + "012", + ":ab:ac:d" + }; + struct Output expectedOutputs[NUM_CASES] = { + {(const unsigned char []){0xaa, 0xbc, 0xd1, 0x35, 0x7e}, 5}, + {(const unsigned char []){0x01, 0x12, 0x23, 0x34, 0xa5, 0xb6, 0xc7, + 0xd8, 0xe9}, 9}, + {(const unsigned char []){0x01, 0x02}, 2}, + {NULL, 0}, + {NULL, 0} + }; + long len = 0; + unsigned char* returnedBuf = NULL; + + printf(testingFmt, "test_wolfSSL_OPENSSL_hexstr2buf()"); + + for (i = 0; i < NUM_CASES; ++i) { + returnedBuf = wolfSSL_OPENSSL_hexstr2buf(inputs[i], &len); + + if (returnedBuf == NULL) { + AssertNull(expectedOutputs[i].buffer); + continue; + } + + AssertIntEQ(expectedOutputs[i].ret, len); + + for (j = 0; j < len; ++j) { + AssertIntEQ(expectedOutputs[i].buffer[j], returnedBuf[j]); + } + OPENSSL_free(returnedBuf); + } + + printf(resultFmt, passed); +#endif +} + static void test_wolfSSL_ASN1_STRING_print_ex(void){ #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) #ifndef NO_BIO @@ -33794,7 +36418,7 @@ static void test_wolfSSL_DES_ncbc(void){ #endif } -static void test_wolfSSL_AES_cbc_encrypt() +static void test_wolfSSL_AES_cbc_encrypt(void) { #if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(OPENSSL_EXTRA) AES_KEY aes; @@ -33981,6 +36605,36 @@ static void test_wolfSSL_AES_cbc_encrypt() printf(resultFmt, "passed"); #endif + + #if defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + byte wrapCipher[sizeof(key256) + KEYWRAP_BLOCK_SIZE] = { 0 }; + byte wrapPlain[sizeof(key256)] = { 0 }; + byte wrapIV[KEYWRAP_BLOCK_SIZE] = { 0 }; + printf(testingFmt, "wolfSSL_AES_wrap_key() 256-bit NULL iv"); + AssertIntEQ(wolfSSL_AES_set_encrypt_key(key256, sizeof(key256)*8, &aes), 0); + AssertIntEQ(wolfSSL_AES_wrap_key(&aes, NULL, wrapCipher, key256, + sizeof(key256)), sizeof(wrapCipher)); + printf(resultFmt, "passed"); + printf(testingFmt, "wolfSSL_AES_unwrap_key() 256-bit NULL iv"); + AssertIntEQ(wolfSSL_AES_set_decrypt_key(key256, sizeof(key256)*8, &aes), 0); + AssertIntEQ(wolfSSL_AES_unwrap_key(&aes, NULL, wrapPlain, wrapCipher, + sizeof(wrapCipher)), sizeof(wrapPlain)); + AssertIntEQ(XMEMCMP(wrapPlain, key256, sizeof(key256)), 0); + printf(resultFmt, "passed"); + XMEMSET(wrapCipher, 0, sizeof(wrapCipher)); + XMEMSET(wrapPlain, 0, sizeof(wrapPlain)); + printf(testingFmt, "wolfSSL_AES_wrap_key() 256-bit custom iv"); + AssertIntEQ(wolfSSL_AES_set_encrypt_key(key256, sizeof(key256)*8, &aes), 0); + AssertIntEQ(wolfSSL_AES_wrap_key(&aes, wrapIV, wrapCipher, key256, + sizeof(key256)), sizeof(wrapCipher)); + printf(resultFmt, "passed"); + printf(testingFmt, "wolfSSL_AES_unwrap_key() 256-bit custom iv"); + AssertIntEQ(wolfSSL_AES_set_decrypt_key(key256, sizeof(key256)*8, &aes), 0); + AssertIntEQ(wolfSSL_AES_unwrap_key(&aes, wrapIV, wrapPlain, wrapCipher, + sizeof(wrapCipher)), sizeof(wrapPlain)); + AssertIntEQ(XMEMCMP(wrapPlain, key256, sizeof(key256)), 0); + printf(resultFmt, "passed"); + #endif /* HAVE_AES_KEYWRAP */ #endif /* WOLFSSL_AES_256 */ #endif } @@ -34195,7 +36849,7 @@ static void test_wolfSSL_X509_PUBKEY_get(void) printf(resultFmt,retEvpPkey == NULL ? passed : failed); } -static void test_wolfSSL_d2i_DHparams() +static void test_wolfSSL_d2i_DHparams(void) { #if !defined(NO_DH) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) @@ -34257,7 +36911,7 @@ static void test_wolfSSL_d2i_DHparams() #endif /* !NO_DH */ } -static void test_wolfSSL_i2d_DHparams() +static void test_wolfSSL_i2d_DHparams(void) { #if !defined(NO_DH) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) @@ -34402,7 +37056,7 @@ static void test_wolfSSL_EC_KEY_dup(void) static void test_wolfSSL_EVP_PKEY_set1_get1_DSA(void) { -#if !defined(NO_DSA) +#if !defined (NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN) DSA *dsa = NULL; DSA *setDsa = NULL; EVP_PKEY *pkey = NULL; @@ -34488,7 +37142,7 @@ static void test_wolfSSL_EVP_PKEY_set1_get1_DSA(void) DSA_free(setDsa); EVP_PKEY_free(pkey); EVP_PKEY_free(set1Pkey); -#endif /* NO_DSA */ +#endif /* !NO_DSA && !HAVE_SELFTEST && WOLFSSL_KEY_GEN */ } /* END test_EVP_PKEY_set1_get1_DSA */ static void test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY (void) @@ -34526,8 +37180,9 @@ static void test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY (void) static void test_wolfSSL_EVP_PKEY_set1_get1_DH (void) { -#if !defined(NO_DH) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENSSH) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) +#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) DH *dh = NULL; DH *setDh = NULL; EVP_PKEY *pkey = NULL; @@ -34570,8 +37225,9 @@ static void test_wolfSSL_EVP_PKEY_set1_get1_DH (void) DH_free(setDh); DH_free(dh); printf(resultFmt, passed); +#endif /* !NO_DH && WOLFSSL_DH_EXTRA && !NO_FILESYSTEM */ #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* NO_DH */ +#endif /* OPENSSL_ALL || WOLFSSL_QT || WOLFSSL_OPENSSH */ } /* END test_EVP_PKEY_set1_get1_DH */ static void test_wolfSSL_CTX_ctrl(void) @@ -34707,7 +37363,23 @@ static void test_wolfSSL_CTX_ctrl(void) AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); #endif + + /* Test for min/max proto */ + #ifndef WOLFSSL_NO_TLS12 + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, + 0, NULL), SSL_SUCCESS); + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, + TLS1_2_VERSION, NULL), SSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_2_VERSION); + #endif + #ifdef WOLFSSL_TLS13 + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, + 0, NULL), SSL_SUCCESS); + + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, + TLS1_3_VERSION, NULL), SSL_SUCCESS); + #endif /* Cleanup and Pass */ #if !defined(NO_DH) && !defined(NO_DSA) #ifndef NO_BIO @@ -34846,6 +37518,9 @@ static void test_wolfSSL_EVP_PKEY_assign(void) AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,ecKey), WOLFSSL_SUCCESS); wolfSSL_EVP_PKEY_free(pkey); #endif /* HAVE_ECC */ + + (void)type; + printf(resultFmt, passed); #endif /* OPENSSL_ALL */ } @@ -34933,7 +37608,7 @@ static void test_wolfSSL_EVP_PKEY_keygen_init(void) } static void test_wolfSSL_EVP_PKEY_missing_parameters(void) { -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_STUB) WOLFSSL_EVP_PKEY* pkey; printf(testingFmt, "wolfSSL_EVP_PKEY_missing_parameters"); @@ -35218,7 +37893,7 @@ static void test_wolfSSL_EVP_aes_192_gcm(void) } static void test_wolfSSL_EVP_ripemd160(void) { -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_STUB) printf(testingFmt, "wolfSSL_EVP_ripemd160"); @@ -35370,7 +38045,7 @@ static void test_wolfSSL_EVP_CIPHER_block_size(void) #endif #endif -#ifdef WOLFSSL_AES_ECB +#ifdef HAVE_AES_ECB #ifdef WOLFSSL_AES_128 AssertIntEQ(EVP_CIPHER_block_size(EVP_aes_128_ecb()), AES_BLOCK_SIZE); #endif @@ -35448,7 +38123,7 @@ static void test_wolfSSL_EVP_CIPHER_iv_length(void) NID_des_ede3_cbc, #endif #ifdef HAVE_IDEA - NID_idea_cbc, + NID_idea_cbc, #endif }; int iv_lengths[] = { @@ -35601,6 +38276,83 @@ static void test_wolfSSL_EVP_PKEY_assign_DH(void) printf(resultFmt, passed); #endif } + +static void test_wolfSSL_QT_EVP_PKEY_CTX_free(void) +{ +#if defined(OPENSSL_EXTRA) + EVP_PKEY* pkey; + EVP_PKEY_CTX* ctx; + + printf(testingFmt, "test_wolfSSL_QT_EVP_PKEY_CTX_free"); + + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + + #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + /* void */ + EVP_PKEY_CTX_free(ctx); + AssertTrue(1); + #else + /* int */ + AssertIntEQ(EVP_PKEY_CTX_free(ctx), WOLFSSL_SUCCESS); + #endif + + EVP_PKEY_free(pkey); + printf(resultFmt, passed); +#endif +} +static void test_wolfSSL_EVP_PKEY_param_check(void) +{ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) + + DH *dh = NULL; + DH *setDh = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX* ctx = NULL; + + FILE* f = NULL; + unsigned char buf[512]; + const unsigned char* pt = buf; + const char* dh2048 = "./certs/dh2048.der"; + long len = 0; + int code = -1; + + printf(testingFmt, "test_wolfSSL_EVP_PKEY_param_check"); + + XMEMSET(buf, 0, sizeof(buf)); + + f = XFOPEN(dh2048, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Load dh2048.der into DH with internal format */ + AssertNotNull(setDh = d2i_DHparams(NULL, &pt, len)); + AssertIntEQ(DH_check(setDh, &code), WOLFSSL_SUCCESS); + AssertIntEQ(code, 0); + code = -1; + + pkey = wolfSSL_EVP_PKEY_new(); + /* Set DH into PKEY */ + AssertIntEQ(EVP_PKEY_set1_DH(pkey, setDh), WOLFSSL_SUCCESS); + /* create ctx from pkey */ + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + AssertIntEQ(EVP_PKEY_param_check(ctx), 1/* valid */); + + /* */ + /* TO DO invlaid case */ + /* */ + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + DH_free(setDh); + DH_free(dh); + + printf(resultFmt, passed); +#endif +#endif +} static void test_wolfSSL_EVP_BytesToKey(void) { #if defined(OPENSSL_ALL) && !defined(NO_DES3) @@ -35660,7 +38412,7 @@ static void test_IncCtr(void) ctx->cipher.aes.keylen = 128; - AssertIntEQ(wolfSSL_EVP_CIPHER_CTX_ctrl(ctx, type, arg, ptr), 0); + AssertIntEQ(wolfSSL_EVP_CIPHER_CTX_ctrl(ctx, type, arg, ptr), 0); EVP_CIPHER_CTX_free(ctx); @@ -35843,6 +38595,28 @@ static void test_wolfSSL_NCONF(void) } #endif /* OPENSSL_ALL */ +static void test_wolfSSL_EC_KEY_set_group(void) +{ +#if defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) && \ + defined(OPENSSL_EXTRA) + EC_KEY *key = NULL; + EC_GROUP *group = NULL; + const EC_GROUP *group2 = NULL; + + printf(testingFmt, "wolfSSL_EC_KEY_dup()"); + + AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + AssertNotNull(key = EC_KEY_new()); + AssertIntEQ(EC_KEY_set_group(key, group), WOLFSSL_SUCCESS); + AssertNotNull(group2 = EC_KEY_get0_group(key)); + AssertIntEQ(EC_GROUP_cmp(group2, group, NULL), 0); + + EC_GROUP_free(group); + EC_KEY_free(key); + + printf(resultFmt, passed); +#endif +} static void test_wolfSSL_X509V3_EXT_get(void) { #if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) @@ -35960,7 +38734,11 @@ static void test_wolfSSL_X509V3_EXT(void) { AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_key_usage); AssertNotNull(asn1str = (WOLFSSL_ASN1_STRING*)wolfSSL_X509V3_EXT_d2i(ext)); + #if defined(WOLFSSL_QT) + AssertNotNull(data = (unsigned char*)ASN1_STRING_get0_data(asn1str)); + #else AssertNotNull(data = wolfSSL_ASN1_STRING_data(asn1str)); + #endif expected = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; #ifdef BIG_ENDIAN_ORDER actual = data[1]; @@ -35978,10 +38756,17 @@ static void test_wolfSSL_X509V3_EXT(void) { AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_info_access); AssertNotNull(aia = (WOLFSSL_AUTHORITY_INFO_ACCESS*)wolfSSL_X509V3_EXT_d2i(ext)); +#if defined(WOLFSSL_QT) + AssertIntEQ(OPENSSL_sk_num(aia), 1); /* Only one URI entry for this cert */ +#else AssertIntEQ(wolfSSL_sk_num(aia), 1); /* Only one URI entry for this cert */ - +#endif /* URI entry is an ACCESS_DESCRIPTION type */ +#if defined(WOLFSSL_QT) AssertNotNull(ad = (WOLFSSL_ACCESS_DESCRIPTION*)wolfSSL_sk_value(aia, 0)); +#else + AssertNotNull(ad = (WOLFSSL_ACCESS_DESCRIPTION*)OPENSSL_sk_value(aia, 0)); +#endif AssertNotNull(adObj = ad->method); /* Make sure nid is OCSP */ AssertIntEQ(wolfSSL_OBJ_obj2nid(adObj), AIA_OCSP_OID); @@ -35991,7 +38776,11 @@ static void test_wolfSSL_X509V3_EXT(void) { AssertIntEQ(gn->type, GEN_URI); /* Type should always be GEN_URI */ AssertNotNull(asn1str = gn->d.uniformResourceIdentifier); AssertIntEQ(wolfSSL_ASN1_STRING_length(asn1str), 22); + #if defined(WOLFSSL_QT) + str = (char*)ASN1_STRING_get0_data(asn1str); + #else str = (char*)wolfSSL_ASN1_STRING_data(asn1str); + #endif actual = strcmp(str, "http://127.0.0.1:22220"); AssertIntEQ(actual, 0); @@ -36280,7 +39069,7 @@ static void test_wolfSSL_X509_cmp(void) #endif } -static void test_wolfSSL_PKEY_up_ref() +static void test_wolfSSL_PKEY_up_ref(void) { #if defined(OPENSSL_ALL) EVP_PKEY* pkey; @@ -36298,7 +39087,7 @@ static void test_wolfSSL_PKEY_up_ref() #endif } -static void test_wolfSSL_i2d_PrivateKey() +static void test_wolfSSL_i2d_PrivateKey(void) { #if (!defined(NO_RSA) || defined(HAVE_ECC)) && defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(NO_PWDBASED) @@ -36345,7 +39134,7 @@ static void test_wolfSSL_i2d_PrivateKey() #endif } -static void test_wolfSSL_OCSP_id_get0_info() +static void test_wolfSSL_OCSP_id_get0_info(void) { #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) X509* cert; @@ -36393,7 +39182,7 @@ static void test_wolfSSL_OCSP_id_get0_info() #endif } -static void test_wolfSSL_i2d_OCSP_CERTID() +static void test_wolfSSL_i2d_OCSP_CERTID(void) { #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) WOLFSSL_OCSP_CERTID certId; @@ -36412,7 +39201,7 @@ static void test_wolfSSL_i2d_OCSP_CERTID() int ret, i; printf(testingFmt, "wolfSSL_i2d_OCSP_CERTID()"); - + XMEMSET(&certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); certId.rawCertId = rawCertId; certId.rawCertIdSize = sizeof(rawCertId); @@ -36448,7 +39237,7 @@ static void test_wolfSSL_i2d_OCSP_CERTID() #endif } -static void test_wolfSSL_OCSP_SINGLERESP_get0_id() +static void test_wolfSSL_OCSP_SINGLERESP_get0_id(void) { #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) WOLFSSL_OCSP_SINGLERESP single; @@ -36456,7 +39245,7 @@ static void test_wolfSSL_OCSP_SINGLERESP_get0_id() XMEMSET(&single, 0, sizeof(single)); certId = wolfSSL_OCSP_SINGLERESP_get0_id(&single); - + printf(testingFmt, "wolfSSL_OCSP_SINGLERESP_get0_id()"); AssertPtrEq(&single, certId); @@ -36465,9 +39254,9 @@ static void test_wolfSSL_OCSP_SINGLERESP_get0_id() #endif } -static void test_wolfSSL_OCSP_single_get0_status() +static void test_wolfSSL_OCSP_single_get0_status(void) { -#if defined(OPENSSL_ALL) && defined(HAVE_OCSP) +#if defined(OPENSSL_ALL) && defined(HAVE_OCSP) WOLFSSL_OCSP_SINGLERESP single; CertStatus certStatus; WOLFSSL_ASN1_TIME* thisDate; @@ -36497,7 +39286,7 @@ static void test_wolfSSL_OCSP_single_get0_status() #endif } -static void test_wolfSSL_OCSP_resp_count() +static void test_wolfSSL_OCSP_resp_count(void) { #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) WOLFSSL_OCSP_BASICRESP basicResp; @@ -36526,7 +39315,7 @@ static void test_wolfSSL_OCSP_resp_count() #endif } -static void test_wolfSSL_OCSP_resp_get0() +static void test_wolfSSL_OCSP_resp_get0(void) { #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) WOLFSSL_OCSP_BASICRESP basicResp; @@ -36555,16 +39344,18 @@ static void test_wolfSSL_OCSP_resp_get0() static void test_wolfSSL_EVP_PKEY_derive(void) { -#if defined(OPENSSL_ALL) && !defined(NO_DH) - printf(testingFmt, "wolfSSL_EVP_PKEY_derive()"); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENSSH) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) +#if (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || defined(HAVE_ECC) + + printf(testingFmt, "wolfSSL_EVP_PKEY_derive()"); EVP_PKEY_CTX *ctx; unsigned char *skey; size_t skeylen; EVP_PKEY *pkey, *peerkey; const unsigned char* key; -#ifndef NO_DH +#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) /* DH */ key = dh_key_der_2048; AssertNotNull((pkey = d2i_PrivateKey(EVP_PKEY_DH, NULL, &key, @@ -36607,9 +39398,11 @@ static void test_wolfSSL_EVP_PKEY_derive(void) EVP_PKEY_free(pkey); XFREE(skey, NULL, DYNAMIC_TYPE_OPENSSL); #endif /* HAVE_ECC */ -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ + printf(resultFmt, "passed"); -#endif /* OPENSSL_ALL */ +#endif /* (!NO_DH && WOLFSSL_DH_EXTRA) || HAVE_ECC */ +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* OPENSSL_ALL || WOLFSSL_QT || WOLFSSL_OPENSSH */ } #ifndef NO_RSA @@ -36635,7 +39428,7 @@ static void test_wolfSSL_RSA_padding_add_PKCS1_PSS(void) #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ #endif /* OPENSSL_ALL && WC_RSA_PSS && !WC_NO_RNG*/ } -#endif +#endif static void test_wolfSSL_EC_get_builtin_curves(void) { @@ -37345,6 +40138,7 @@ static void test_EVP_PKEY_cmp(void) EVP_PKEY *a, *b; const unsigned char *in; + printf(testingFmt, "wolfSSL_EVP_PKEY_cmp()"); #if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_2048) in = client_key_der_2048; AssertNotNull(a = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, @@ -37354,7 +40148,11 @@ static void test_EVP_PKEY_cmp(void) &in, (long)sizeof_client_key_der_2048)); /* Test success case RSA */ +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + AssertIntEQ(EVP_PKEY_cmp(a, b), 1); +#else AssertIntEQ(EVP_PKEY_cmp(a, b), 0); +#endif /* WOLFSSL_ERROR_CODE_OPENSSL */ EVP_PKEY_free(b); EVP_PKEY_free(a); @@ -37369,7 +40167,11 @@ static void test_EVP_PKEY_cmp(void) &in, (long)sizeof_ecc_clikey_der_256)); /* Test success case ECC */ +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + AssertIntEQ(EVP_PKEY_cmp(a, b), 1); +#else AssertIntEQ(EVP_PKEY_cmp(a, b), 0); +#endif /* WOLFSSL_ERROR_CODE_OPENSSL */ EVP_PKEY_free(b); EVP_PKEY_free(a); @@ -37386,8 +40188,11 @@ static void test_EVP_PKEY_cmp(void) AssertNotNull(b = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, &in, (long)sizeof_ecc_clikey_der_256)); +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + AssertIntEQ(EVP_PKEY_cmp(a, b), -1); +#else AssertIntNE(EVP_PKEY_cmp(a, b), 0); - +#endif /* WOLFSSL_ERROR_CODE_OPENSSL */ EVP_PKEY_free(b); EVP_PKEY_free(a); #endif @@ -37395,10 +40200,17 @@ static void test_EVP_PKEY_cmp(void) /* invalid or empty failure cases */ a = EVP_PKEY_new(); b = EVP_PKEY_new(); +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + AssertIntEQ(EVP_PKEY_cmp(NULL, NULL), 0); + AssertIntEQ(EVP_PKEY_cmp(a, NULL), 0); + AssertIntEQ(EVP_PKEY_cmp(NULL, b), 0); + AssertIntEQ(EVP_PKEY_cmp(a, b), 0); +#else AssertIntNE(EVP_PKEY_cmp(NULL, NULL), 0); AssertIntNE(EVP_PKEY_cmp(a, NULL), 0); AssertIntNE(EVP_PKEY_cmp(NULL, b), 0); AssertIntNE(EVP_PKEY_cmp(a, b), 0); +#endif EVP_PKEY_free(b); EVP_PKEY_free(a); @@ -37786,6 +40598,15 @@ static void test_wolfSSL_SMIME_read_PKCS7(void) pkcs7 = wolfSSL_SMIME_read_PKCS7(bio, &bcont); AssertNull(pkcs7); AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, bcont, NULL, PKCS7_NOVERIFY), SSL_FAILURE); + XFCLOSE(smimeTestFile); + if (bcont) BIO_free(bcont); + wolfSSL_PKCS7_free(pkcs7); + + smimeTestFile = XFOPEN("./certs/test/smime-test-canon.p7s", "r"); + AssertIntEQ(wolfSSL_BIO_set_fp(bio, smimeTestFile, BIO_CLOSE), SSL_SUCCESS); + pkcs7 = wolfSSL_SMIME_read_PKCS7(bio, &bcont); + AssertNotNull(pkcs7); + AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, bcont, NULL, PKCS7_NOVERIFY), SSL_SUCCESS); BIO_free(bio); if (bcont) BIO_free(bcont); wolfSSL_PKCS7_free(pkcs7); @@ -37942,6 +40763,7 @@ static int test_tls13_apis(void) const char* ourKey = svrKeyFile; #endif #endif + int required; #ifdef WOLFSSL_EARLY_DATA int outSz; #endif @@ -38131,6 +40953,19 @@ static int test_tls13_apis(void) AssertIntEQ(wolfSSL_update_keys(serverSsl), BUILD_MSG_ERROR); #endif + AssertIntEQ(wolfSSL_key_update_response(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_key_update_response(NULL, &required), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_key_update_response(clientTls12Ssl, &required), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_key_update_response(clientSsl, NULL), BAD_FUNC_ARG); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_key_update_response(serverSsl, NULL), BAD_FUNC_ARG); +#endif + #if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(NULL), BAD_FUNC_ARG); #ifndef NO_WOLFSSL_SERVER @@ -38346,6 +41181,11 @@ static int test_tls13_apis(void) #endif #endif +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_EARLY_DATA) + AssertIntLT(SSL_get_early_data_status(NULL), 0); +#endif + + #ifndef NO_WOLFSSL_SERVER wolfSSL_free(serverSsl); wolfSSL_CTX_free(serverCtx); @@ -38371,7 +41211,8 @@ static int test_tls13_apis(void) #endif -#ifdef HAVE_PK_CALLBACKS +#if defined(HAVE_PK_CALLBACKS) && (!defined(WOLFSSL_NO_TLS12) || \ + !defined(NO_OLD_TLS)) #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_DH) && !defined(NO_AES) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) @@ -38389,7 +41230,7 @@ static int my_DhCallback(WOLFSSL* ssl, struct DhKey* key, (void)ssl; /* return 0 on success */ return wc_DhAgree(key, out, outlen, priv, privSz, pubKeyDer, pubKeySz); -}; +} static void test_dh_ctx_setup(WOLFSSL_CTX* ctx) { wolfSSL_CTX_SetDhAgreeCb(ctx, my_DhCallback); @@ -39027,6 +41868,95 @@ static void test_wolfSSL_X509_CRL(void) return; } +static void test_wolfSSL_X509_load_crl_file(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_FILESYSTEM) + int i; + char pem[][100] = { + "./certs/crl/crl.pem", + "./certs/crl/crl2.pem", + "./certs/crl/caEccCrl.pem", + "./certs/crl/eccCliCRL.pem", + "./certs/crl/eccSrvCRL.pem", + "" + }; + char der[][100] = { + "./certs/crl/crl.der", + "./certs/crl/crl2.der", + "" + }; + WOLFSSL_X509_STORE* store; + WOLFSSL_X509_LOOKUP* lookup; + + printf(testingFmt, "wolfSSL_X509_load_crl_file"); + + AssertNotNull(store = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); + + AssertIntEQ(X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(X509_LOOKUP_load_file(lookup, "certs/server-revoked-cert.pem", + X509_FILETYPE_PEM), 1); + if (store) { + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + WOLFSSL_FILETYPE_PEM), 1); + /* since store hasn't yet known the revoked cert*/ + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM), 1); + } + + for (i = 0; pem[i][0] != '\0'; i++) + { + AssertIntEQ(X509_load_crl_file(lookup, pem[i], WOLFSSL_FILETYPE_PEM), 1); + } + + if (store) { + /* since store knows crl list */ + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM ), CRL_CERT_REVOKED); + } + /* once feeing store */ + X509_STORE_free(store); + store = NULL; + + AssertNotNull(store = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); + + AssertIntEQ(X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(X509_LOOKUP_load_file(lookup, "certs/server-revoked-cert.pem", + X509_FILETYPE_PEM), 1); + if (store) { + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + WOLFSSL_FILETYPE_PEM), 1); + /* since store hasn't yet known the revoked cert*/ + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM), 1); + } + + for (i = 0; der[i][0] != '\0'; i++) + { + AssertIntEQ(X509_load_crl_file(lookup, der[i], WOLFSSL_FILETYPE_ASN1), 1); + } + + if (store) { + /* since store knows crl list */ + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM ), CRL_CERT_REVOKED); + } + + /* test for incorrect parameter */ + AssertIntEQ(X509_load_crl_file(NULL, pem[0], 0), 0); + AssertIntEQ(X509_load_crl_file(lookup, NULL, 0), 0); + AssertIntEQ(X509_load_crl_file(NULL, NULL, 0), 0); + + X509_STORE_free(store); + store = NULL; + + printf(resultFmt, passed); +#endif +} + static void test_wolfSSL_d2i_X509_REQ(void) { #if defined(WOLFSSL_CERT_REQ) && (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) @@ -39305,15 +42235,19 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void) const byte iv[12] = { 0 }; const byte key[16] = { 0 }; const byte cleartext[16] = { 0 }; - const byte aad[] = {0x01, 0x10, 0x00, 0x2a, 0x08, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xdc, 0x4d, - 0xad, 0x6b, 0x06, 0x93, 0x4f}; + const byte aad[] = { + 0x01, 0x10, 0x00, 0x2a, 0x08, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0xdc, 0x4d, 0xad, 0x6b, 0x06, 0x93, + 0x4f + }; byte out1Part[16]; byte outTag1Part[16]; byte out2Part[16]; byte outTag2Part[16]; byte decryptBuf[16]; int len; + int tlen; EVP_CIPHER_CTX* ctx = NULL; printf(testingFmt, "wolfssl_EVP_aes_gcm_AAD_2_parts"); @@ -39321,25 +42255,37 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void) /* ENCRYPT */ /* Send AAD and data in 1 part */ AssertNotNull(ctx = EVP_CIPHER_CTX_new()); - AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); + tlen = 0; + AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), + 1); AssertIntEQ(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1); - AssertIntEQ(EVP_EncryptUpdate(ctx, out1Part, &len, cleartext, sizeof(cleartext)), 1); + AssertIntEQ(EVP_EncryptUpdate(ctx, out1Part, &len, cleartext, + sizeof(cleartext)), 1); + tlen += len; AssertIntEQ(EVP_EncryptFinal_ex(ctx, out1Part, &len), 1); - AssertIntEQ(len, sizeof(cleartext)); - AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag1Part), 1); + tlen += len; + AssertIntEQ(tlen, sizeof(cleartext)); + AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, + outTag1Part), 1); EVP_CIPHER_CTX_free(ctx); /* DECRYPT */ /* Send AAD and data in 1 part */ AssertNotNull(ctx = EVP_CIPHER_CTX_new()); - AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); + tlen = 0; + AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), + 1); AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1); - AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, sizeof(cleartext)), 1); - AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, outTag1Part), 1); + AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, + sizeof(cleartext)), 1); + tlen += len; + AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, + outTag1Part), 1); AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf, &len), 1); - AssertIntEQ(len, sizeof(cleartext)); + tlen += len; + AssertIntEQ(tlen, sizeof(cleartext)); EVP_CIPHER_CTX_free(ctx); AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0); @@ -39347,16 +42293,23 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void) /* ENCRYPT */ /* Send AAD and data in 2 parts */ AssertNotNull(ctx = EVP_CIPHER_CTX_new()); - AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); + tlen = 0; + AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), + 1); AssertIntEQ(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad, 1), 1); - AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), 1); + AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), + 1); AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext, 1), 1); - AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext + 1, + tlen += len; + AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part + tlen, &len, cleartext + 1, sizeof(cleartext) - 1), 1); - AssertIntEQ(EVP_EncryptFinal_ex(ctx, out2Part, &len), 1); - AssertIntEQ(len, sizeof(cleartext)); - AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag2Part), 1); + tlen += len; + AssertIntEQ(EVP_EncryptFinal_ex(ctx, out2Part + tlen, &len), 1); + tlen += len; + AssertIntEQ(tlen, sizeof(cleartext)); + AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, + outTag2Part), 1); AssertIntEQ(XMEMCMP(out1Part, out2Part, sizeof(out1Part)), 0); AssertIntEQ(XMEMCMP(outTag1Part, outTag2Part, sizeof(outTag1Part)), 0); @@ -39365,16 +42318,23 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void) /* DECRYPT */ /* Send AAD and data in 2 parts */ AssertNotNull(ctx = EVP_CIPHER_CTX_new()); - AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); + tlen = 0; + AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), + 1); AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad, 1), 1); - AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), 1); + AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), + 1); AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, 1), 1); - AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part + 1, + tlen += len; + AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf + tlen, &len, out1Part + 1, sizeof(cleartext) - 1), 1); - AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, outTag1Part), 1); - AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf, &len), 1); - AssertIntEQ(len, sizeof(cleartext)); + tlen += len; + AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, + outTag1Part), 1); + AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf + tlen, &len), 1); + tlen += len; + AssertIntEQ(tlen, sizeof(cleartext)); AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0); @@ -39387,23 +42347,24 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void) #if defined(OPENSSL_EXTRA) && !defined(NO_AES) && defined(HAVE_AESGCM) && \ !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) -static void test_wolfssl_EVP_aes_gcm_zeroLen() -{ +static void test_wolfssl_EVP_aes_gcm_zeroLen(void) +{ /* Zero length plain text */ - byte key[] = - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + byte key[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; /* align */ - byte iv[] = - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - /* align */ - byte plaintxt[0]; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; /* align */ + byte iv[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; /* align */ + byte plaintxt[1]; int ivSz = 12; int plaintxtSz = 0; unsigned char tag[16]; - unsigned char tag_kat[] = + unsigned char tag_kat[] = {0x53,0x0f,0x8a,0xfb,0xc7,0x45,0x36,0xb9, 0xa9,0x63,0xb4,0xf1,0xc4,0xcb,0x73,0x8b}; @@ -39418,7 +42379,8 @@ static void test_wolfssl_EVP_aes_gcm_zeroLen() AssertIntEQ(1, EVP_EncryptInit_ex(en, EVP_aes_256_gcm(), NULL, key, iv)); AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_GCM_SET_IVLEN, ivSz, NULL)); - AssertIntEQ(1, EVP_EncryptUpdate(en, ciphertxt, &ciphertxtSz , plaintxt, plaintxtSz)); + AssertIntEQ(1, EVP_EncryptUpdate(en, ciphertxt, &ciphertxtSz , plaintxt, + plaintxtSz)); AssertIntEQ(1, EVP_EncryptFinal_ex(en, ciphertxt, &len)); ciphertxtSz += len; AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_GCM_GET_TAG, 16, tag)); @@ -39426,7 +42388,7 @@ static void test_wolfssl_EVP_aes_gcm_zeroLen() AssertIntEQ(0, ciphertxtSz); AssertIntEQ(0, XMEMCMP(tag, tag_kat, sizeof(tag))); - + EVP_CIPHER_CTX_init(de); AssertIntEQ(1, EVP_DecryptInit_ex(de, EVP_aes_256_gcm(), NULL, key, iv)); AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(de, EVP_CTRL_GCM_SET_IVLEN, ivSz, NULL)); @@ -39436,7 +42398,7 @@ static void test_wolfssl_EVP_aes_gcm_zeroLen() AssertIntEQ(1, EVP_DecryptFinal_ex(de, decryptedtxt, &len)); decryptedtxtSz += len; AssertIntEQ(0, decryptedtxtSz); - + EVP_CIPHER_CTX_free(en); EVP_CIPHER_CTX_free(de); } @@ -39548,7 +42510,7 @@ static void test_wolfssl_EVP_aes_gcm(void) AssertIntEQ(0, len); AssertIntEQ(wolfSSL_EVP_CIPHER_CTX_cleanup(&de[i]), 1); } - + test_wolfssl_EVP_aes_gcm_zeroLen(); printf(resultFmt, passed); @@ -39601,7 +42563,7 @@ static void test_wolfSSL_PEM_X509_INFO_read_bio(void) } #endif /* !NO_BIO */ -static void test_wolfSSL_X509_NAME_ENTRY_get_object() +static void test_wolfSSL_X509_NAME_ENTRY_get_object(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509 *x509; @@ -39627,7 +42589,7 @@ static void test_wolfSSL_X509_NAME_ENTRY_get_object() #endif } -static void test_wolfSSL_ASN1_INTEGER_set() +static void test_wolfSSL_ASN1_INTEGER_set(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) ASN1_INTEGER *a; @@ -39707,6 +42669,57 @@ static void test_wolfSSL_ASN1_INTEGER_set() #endif } +static void test_wolfSSL_X509_STORE_get1_certs(void) +{ +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && \ + !defined(NO_FILESYSTEM) + X509_STORE_CTX *storeCtx; + X509_STORE *store; + X509 *caX509; + X509 *svrX509; + X509_NAME *subject; + WOLF_STACK_OF(WOLFSSL_X509) *certs; + + printf(testingFmt, "wolfSSL_X509_STORE_get1_certs()"); + + AssertNotNull(caX509 = + X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); + AssertNotNull((svrX509 = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + AssertNotNull(storeCtx = X509_STORE_CTX_new()); + AssertNotNull(store = X509_STORE_new()); + AssertNotNull(subject = X509_get_subject_name(caX509)); + + /* Errors */ + AssertNull(X509_STORE_get1_certs(storeCtx, subject)); + AssertNull(X509_STORE_get1_certs(NULL, subject)); + AssertNull(X509_STORE_get1_certs(storeCtx, NULL)); + + AssertIntEQ(X509_STORE_add_cert(store, caX509), SSL_SUCCESS); + AssertIntEQ(X509_STORE_CTX_init(storeCtx, store, caX509, NULL), SSL_SUCCESS); + + /* Should find the cert */ + AssertNotNull(certs = X509_STORE_get1_certs(storeCtx, subject)); + AssertIntEQ(1, wolfSSL_sk_X509_num(certs)); + + sk_X509_free(certs); + + /* Should not find the cert */ + AssertNotNull(subject = X509_get_subject_name(svrX509)); + AssertNotNull(certs = X509_STORE_get1_certs(storeCtx, subject)); + AssertIntEQ(0, wolfSSL_sk_X509_num(certs)); + + sk_X509_free(certs); + + X509_STORE_free(store); + X509_STORE_CTX_free(storeCtx); + X509_free(svrX509); + X509_free(caX509); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && WOLFSSL_SIGNER_DER_CERT && !NO_FILESYSTEM */ +} + /* Testing code used in dpp.c in hostap */ #if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) typedef struct { @@ -39720,12 +42733,12 @@ typedef struct { ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) -} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); +} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY) -IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); +IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY) #endif -static void test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS() +static void test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS(void) { /* Testing code used in dpp.c in hostap */ #if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) @@ -39783,7 +42796,7 @@ static void test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS() #endif /* WOLFSSL_WPAS && HAVE_ECC && USE_CERT_BUFFERS_256 */ } -static void test_wolfSSL_i2c_ASN1_INTEGER() +static void test_wolfSSL_i2c_ASN1_INTEGER(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) ASN1_INTEGER *a; @@ -39919,13 +42932,13 @@ static int test_ForceZero(void) #ifndef NO_BIO -static void test_wolfSSL_X509_print() +static void test_wolfSSL_X509_print(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && defined(XSNPRINTF) X509 *x509; BIO *bio; -#ifdef OPENSSL_ALL +#if defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_DIR) const X509_ALGOR *cert_sig_alg; #endif @@ -39946,14 +42959,16 @@ static void test_wolfSSL_X509_print() AssertNotNull(bio = BIO_new_fd(STDOUT_FILENO, BIO_NOCLOSE)); -#ifdef OPENSSL_ALL +#if defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_DIR) /* Print signature */ AssertNotNull(cert_sig_alg = X509_get0_tbs_sigalg(x509)); AssertIntEQ(X509_signature_print(bio, cert_sig_alg, NULL), SSL_SUCCESS); #endif /* print to stdout */ +#if !defined(NO_WOLFSSL_DIR) AssertIntEQ(X509_print(bio, x509), SSL_SUCCESS); +#endif /* print again */ AssertIntEQ(X509_print_fp(stdout, x509), SSL_SUCCESS); @@ -39963,7 +42978,7 @@ static void test_wolfSSL_X509_print() #endif } -static void test_wolfSSL_RSA_print() +static void test_wolfSSL_RSA_print(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ @@ -39982,7 +42997,7 @@ static void test_wolfSSL_RSA_print() #endif } -static void test_wolfSSL_BIO_get_len() +static void test_wolfSSL_BIO_get_len(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_BIO) BIO *bio; @@ -40115,7 +43130,7 @@ static void test_wolfSSL_ASN1_get_object(void) #endif /* OPENSSL_EXTRA && HAVE_ECC && USE_CERT_BUFFERS_256 */ } -static void test_wolfSSL_RSA_verify() +static void test_wolfSSL_RSA_verify(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && \ !defined(NO_FILESYSTEM) && defined(HAVE_CRL) @@ -40185,7 +43200,7 @@ static void test_wolfSSL_RSA_verify() #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) static void test_openssl_make_self_signed_certificate(EVP_PKEY* pkey) { X509* x509 = NULL; @@ -40266,7 +43281,8 @@ static void test_openssl_generate_key_and_cert(void) BN_free(exponent); - #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) test_openssl_make_self_signed_certificate(pkey); #endif } @@ -40290,7 +43306,8 @@ static void test_openssl_generate_key_and_cert(void) AssertIntNE(EC_KEY_generate_key(ec_key), 0); AssertIntNE(EVP_PKEY_assign_EC_KEY(pkey, ec_key), 0); - #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) test_openssl_make_self_signed_certificate(pkey); #endif @@ -40300,7 +43317,7 @@ static void test_openssl_generate_key_and_cert(void) #endif /* OPENSSL_EXTRA */ } -static void test_stubs_are_stubs() +static void test_stubs_are_stubs(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB) WOLFSSL_CTX* ctx = NULL; @@ -40339,7 +43356,73 @@ static void test_stubs_are_stubs() #endif /* OPENSSL_EXTRA && !NO_WOLFSSL_STUB */ } -static void test_wolfSSL_CTX_LoadCRL() + +static void test_CONF_modules_xxx(void) +{ +#if defined(OPENSSL_EXTRA) + CONF_modules_free(); + AssertTrue(1); /* to confirm previous call gives no harm */ + + CONF_modules_unload(0); + AssertTrue(1); + + CONF_modules_unload(1); + AssertTrue(1); + + CONF_modules_unload(-1); + AssertTrue(1); + +#endif /* OPENSSL_EXTRA */ +} +static void test_CRYPTO_set_dynlock_xxx(void) +{ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "CRYPTO_set_dynlock_xxx()"); + + CRYPTO_set_dynlock_create_callback( + (struct CRYPTO_dynlock_value *(*)(const char*, int))NULL); + + CRYPTO_set_dynlock_create_callback( + (struct CRYPTO_dynlock_value *(*)(const char*, int))1); + + CRYPTO_set_dynlock_destroy_callback( + (void (*)(struct CRYPTO_dynlock_value*, const char*, int))NULL); + + CRYPTO_set_dynlock_destroy_callback( + (void (*)(struct CRYPTO_dynlock_value*, const char*, int))1); + + CRYPTO_set_dynlock_lock_callback( + (void (*)(int, struct CRYPTO_dynlock_value *, const char*, int))NULL); + + CRYPTO_set_dynlock_lock_callback( + (void (*)(int, struct CRYPTO_dynlock_value *, const char*, int))1); + + AssertTrue(1); /* to confirm previous call gives no harm */ + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} +static void test_CRYPTO_THREADID_xxx(void) +{ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "CRYPTO_THREADID_xxx()"); + + CRYPTO_THREADID_current((CRYPTO_THREADID*)NULL); + CRYPTO_THREADID_current((CRYPTO_THREADID*)1); + AssertIntEQ(CRYPTO_THREADID_hash((const CRYPTO_THREADID*)NULL), 0); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} +static void test_ENGINE_cleanup(void) +{ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "ENGINE_cleanup()"); + ENGINE_cleanup(); + AssertTrue(1); /* to confirm previous call gives no harm */ + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + +static void test_wolfSSL_CTX_LoadCRL(void) { #ifdef HAVE_CRL WOLFSSL_CTX* ctx = NULL; @@ -40757,7 +43840,7 @@ static void test_export_keying_material(void) start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); - test_client_nofail(&client_args, (void*)test_export_keying_material_cb); + test_client_nofail(&client_args, test_export_keying_material_cb); join_thread(serverThread); AssertTrue(client_args.return_code); @@ -40772,6 +43855,817 @@ static void test_export_keying_material(void) } #endif /* HAVE_KEYING_MATERIAL */ +static int test_wolfSSL_THREADID_hash(void) +{ + int ret = 0; + CRYPTO_THREADID id; + unsigned long res; +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "wolfSSL_THREADID_hash"); + CRYPTO_THREADID_current(NULL); + AssertTrue(1); + res = CRYPTO_THREADID_hash(NULL); + AssertTrue( res == 0UL); + XMEMSET(&id, 0, sizeof(id)); + res = CRYPTO_THREADID_hash(&id); + AssertTrue( res == 0UL); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ + (void)id; + (void)res; + return ret; +} +static int test_wolfSSL_CTX_set_ecdh_auto(void) +{ + int ret = 0; + WOLFSSL_CTX* ctx = NULL; +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "SSL_CTX_set_ecdh_auto"); + AssertIntEQ( SSL_CTX_set_ecdh_auto(NULL,0),1); + AssertIntEQ( SSL_CTX_set_ecdh_auto(NULL,1),1); + AssertIntEQ( SSL_CTX_set_ecdh_auto(ctx,0),1); + AssertIntEQ( SSL_CTX_set_ecdh_auto(ctx,1),1); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ + (void)ctx; + return ret; +} + +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) +static THREAD_RETURN WOLFSSL_THREAD SSL_read_test_server_thread(void* args) +{ + callback_functions* callbacks = NULL; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + SOCKET_T sfd = 0; + SOCKET_T cfd = 0; + word16 port; + char msg[] = "I hear you fa shizzle!"; + int len = (int) XSTRLEN(msg); + char input[1024]; + int ret, err; + + if (!args) + return 0; + + ((func_args*)args)->return_code = TEST_FAIL; + + callbacks = ((func_args*)args)->callbacks; + ctx = wolfSSL_CTX_new(callbacks->method()); + +#if defined(USE_WINDOWS_API) + port = ((func_args*)args)->signal->port; +#else + /* Let tcp_listen assign port */ + port = 0; +#endif + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, + WOLFSSL_FILETYPE_PEM)); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, + WOLFSSL_FILETYPE_PEM)); + + if (callbacks->ctx_ready) + callbacks->ctx_ready(ctx); + + ssl = wolfSSL_new(ctx); + AssertNotNull(ssl); + + /* listen and accept */ + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); + CloseSocket(sfd); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd)); + + if (callbacks->ssl_ready) + callbacks->ssl_ready(ssl); + + do { + err = 0; /* Reset error */ + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + CloseSocket(cfd); + ((func_args*)args)->return_code = TEST_FAIL; + return 0; + } + + /* read and write data */ + XMEMSET( input, 0, sizeof(input)); + + while (1) { + ret = wolfSSL_read(ssl, input, sizeof(input)); + if (ret > 0) { + break; + } + else { + err = wolfSSL_get_error(ssl,ret); + if (err == WOLFSSL_ERROR_WANT_READ) { + continue; + } + break; + } + } + + if (err == WOLFSSL_ERROR_ZERO_RETURN) { + do { + ret = wolfSSL_write(ssl, msg, len); + if (ret > 0) { + break; + } + } while (ret < 0); + } + + /* bidirectional shutdown */ + while ((ret = wolfSSL_shutdown(ssl)) != WOLFSSL_SUCCESS) { + continue; + } + + /* wait for the peer to disconnect the tcp connection */ + do { + ret = wolfSSL_read(ssl, input, sizeof(input)); + err = wolfSSL_get_error(ssl, ret); + } while (ret > 0 || err != WOLFSSL_ERROR_ZERO_RETURN); + + /* detect TCP disconnect */ + AssertIntLE(ret,WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_get_error(ssl, ret), WOLFSSL_ERROR_ZERO_RETURN); + + ((func_args*)args)->return_code = TEST_SUCCESS; + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + CloseSocket(cfd); + + return 0; +} +static THREAD_RETURN WOLFSSL_THREAD SSL_read_test_client_thread(void* args) +{ + callback_functions* callbacks = NULL; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + SOCKET_T sfd = 0; + char msg[] = "hello wolfssl server!"; + int len = (int) XSTRLEN(msg); + char input[1024]; + int idx; + int ret, err; + + if (!args) + return 0; + + ((func_args*)args)->return_code = TEST_FAIL; + callbacks = ((func_args*)args)->callbacks; + ctx = wolfSSL_CTX_new(callbacks->method()); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, + WOLFSSL_FILETYPE_PEM)); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, + WOLFSSL_FILETYPE_PEM)); + + AssertNotNull((ssl = wolfSSL_new(ctx))); + + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, ssl); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); + + do { + err = 0; /* Reset error */ + ret = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + ret = wolfSSL_write(ssl, msg, len); + + if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { + input[idx] = 0; + } + + ret = wolfSSL_shutdown(ssl); + if ( ret == WOLFSSL_SHUTDOWN_NOT_DONE) { + ret = wolfSSL_shutdown(ssl); + } + AssertIntEQ(ret, WOLFSSL_SUCCESS); + + ((func_args*)args)->return_code = TEST_SUCCESS; + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + CloseSocket(sfd); + return 0; +} +#endif /* OPENSSL_EXTRA && WOLFSSL_ERROR_CODE_OPENSSL */ + +/* This test is to check wolfSSL_read behaves as same as + * openSSL when it is called after SSL_shutdown completes. + */ +static int test_wolfSSL_read_detect_TCP_disconnect(void) +{ + int ret = 0; +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + THREAD_TYPE clientThread; + callback_functions server_cbf; + callback_functions client_cbf; + + + printf(testingFmt, "wolfSSL_read_detect_TCP_disconnect()"); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + XMEMSET(&server_cbf, 0, sizeof(callback_functions)); + XMEMSET(&client_cbf, 0, sizeof(callback_functions)); + + server_cbf.method = wolfTLSv1_2_server_method; + client_cbf.method = wolfTLSv1_2_client_method; + + server_args.callbacks = &server_cbf; + client_args.callbacks = &client_cbf; + + server_args.signal = &ready; + client_args.signal = &ready; + + start_thread(SSL_read_test_server_thread, &server_args, &serverThread); + + wait_tcp_ready(&server_args); + + start_thread(SSL_read_test_client_thread, &client_args, &clientThread); + + join_thread(clientThread); + join_thread(serverThread); + + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + + FreeTcpReady(&ready); + + printf(resultFmt, passed); +#endif + return ret; +} +static void test_wolfSSL_CTX_get_min_proto_version(void) +{ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + WOLFSSL_CTX *ctx; + + (void)ctx; + + printf(testingFmt, "wolfSSL_CTX_get_min_proto_version()"); + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); + AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, SSL3_VERSION), WOLFSSL_SUCCESS); + #ifdef WOLFSSL_ALLOW_SSLV3 + AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), SSL3_VERSION); + #else + AssertIntGT(wolfSSL_CTX_get_min_proto_version(ctx), SSL3_VERSION); + #endif + wolfSSL_CTX_free(ctx); + + #ifdef WOLFSSL_ALLOW_TLSV10 + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); + #endif + AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_VERSION), WOLFSSL_SUCCESS); + #ifdef WOLFSSL_ALLOW_TLSV10 + AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_VERSION); + #else + AssertIntGT(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_VERSION); + #endif + wolfSSL_CTX_free(ctx); + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); + AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION), WOLFSSL_SUCCESS); + #ifndef NO_OLD_TLS + AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_1_VERSION); + #else + AssertIntGT(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_1_VERSION); + #endif + wolfSSL_CTX_free(ctx); + + #ifndef WOLFSSL_NO_TLS12 + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_method())); + AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_2_VERSION); + wolfSSL_CTX_free(ctx); + #endif + + #ifdef WOLFSSL_TLS13 + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_method())); + AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_3_VERSION); + wolfSSL_CTX_free(ctx); + #endif + + printf(resultFmt, passed); +#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) */ +} + +static void test_wolfSSL_security_level(void) +{ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "test_wolfSSL_security_level()"); + + SSL_CTX *ctx; + + #ifdef WOLFSSL_TLS13 + #ifdef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); + #endif + SSL_CTX_set_security_level(ctx, 1); + AssertTrue(1); + + AssertIntEQ(SSL_CTX_get_security_level(ctx), 0); + + SSL_CTX_free(ctx); + #else + (void)ctx; + #endif + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_SSL_in_init(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_BIO) + printf(testingFmt, "test_wolfSSL_SSL_in_init()"); + + SSL_CTX* ctx; + SSL* ssl; + const char* testCertFile; + const char* testKeyFile; + + #ifdef WOLFSSL_TLS13 + #ifdef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); + #endif +#ifndef NO_RSA + testCertFile = svrCertFile; + testKeyFile = svrKeyFile; +#elif defined(HAVE_ECC) + testCertFile = eccCertFile; + testKeyFile = eccKeyFile; +#else + testCertFile = NULL; + testKeyFile = NULL; +#endif + if (testCertFile != NULL && testKeyFile != NULL) { + AssertTrue(SSL_CTX_use_certificate_file(ctx, testCertFile, + SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, testKeyFile, + SSL_FILETYPE_PEM)); + } + + ssl = SSL_new(ctx); + AssertNotNull(ssl); + AssertIntEQ(SSL_in_init(ssl), 1); + + SSL_CTX_free(ctx); + SSL_free(ssl); + #else + (void)ctx; + (void)ssl; + (void)testCertFile; + (void)testKeyFile; + #endif + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_EC_curve(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + printf(testingFmt, "test_wolfSSL_EC_curve()"); + int nid = NID_secp160k1; + const char* nid_name; + + AssertNotNull(nid_name = EC_curve_nid2nist(nid)); + AssertIntEQ(XMEMCMP(nid_name, "K-160", XSTRLEN("K-160")), 0); + + AssertIntEQ(EC_curve_nist2nid(nid_name), nid); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_OpenSSL_version(void) +{ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "test_wolfSSL_OpenSSL_version()"); + const char* ver; + + #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + AssertNotNull(ver = OpenSSL_version(0)); + #else + AssertNotNull(ver = OpenSSL_version()); + #endif + AssertIntEQ(XMEMCMP(ver, "wolfSSL " LIBWOLFSSL_VERSION_STRING, + XSTRLEN("wolfSSL " LIBWOLFSSL_VERSION_STRING)), 0); + printf(resultFmt, passed); +#endif +} + +static void test_CONF_CTX_CMDLINE(void) +{ +#if defined(OPENSSL_ALL) + printf(testingFmt, "test_CONF_CTX_CMDLINE"); + + SSL_CTX* ctx = NULL; + SSL_CONF_CTX* cctx = NULL; + + AssertNotNull(cctx = SSL_CONF_CTX_new()); + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + AssertTrue(1); + + /* set flags */ + AssertIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CMDLINE), + WOLFSSL_CONF_FLAG_CMDLINE); + AssertIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CERTIFICATE), + WOLFSSL_CONF_FLAG_CMDLINE | WOLFSSL_CONF_FLAG_CERTIFICATE); + /* cmd invalid command */ + AssertIntEQ(SSL_CONF_cmd(cctx, "foo", "foobar"), -2); + AssertIntEQ(SSL_CONF_cmd(cctx, "foo", NULL), -2); + AssertIntEQ(SSL_CONF_cmd(cctx, NULL, NULL), WOLFSSL_FAILURE); + AssertIntEQ(SSL_CONF_cmd(cctx, NULL, "foobar"), WOLFSSL_FAILURE); + AssertIntEQ(SSL_CONF_cmd(NULL, "-curves", "foobar"), WOLFSSL_FAILURE); + + /* cmd Certificate and Private Key*/ + { + #ifndef NO_CERTS + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; + + AssertIntEQ(SSL_CONF_cmd(cctx, "-cert", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "-cert", ourCert), + WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_cmd(cctx, "-key", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "-key", ourKey), WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + #endif + } + + /* cmd curves */ + { + #if defined(HAVE_ECC) + const char* curve = "secp256r1"; + + AssertIntEQ(SSL_CONF_cmd(cctx, "-curves", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "-curves", curve), WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + #endif + } + + /* cmd CipherString */ + { + char* cipher = wolfSSL_get_cipher_list(0/*top priority*/); + + AssertIntEQ(SSL_CONF_cmd(cctx, "-cipher", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "-cipher", cipher), WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + } + + /* cmd DH parameter */ + { + #if !defined(NO_DH) && !defined(NO_BIO) + const char* ourdhcert = "./certs/dh4096.pem"; + + AssertIntEQ(SSL_CONF_cmd(cctx, "-dhparam", NULL), + -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "-dhparam", ourdhcert), + WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + + #endif + } + SSL_CTX_free(ctx); + SSL_CONF_CTX_free(cctx); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + +static void test_CONF_CTX_FILE(void) +{ +#if defined(OPENSSL_ALL) + printf(testingFmt, "test_CONF_CTX_FILE"); + + SSL_CTX* ctx = NULL; + SSL_CONF_CTX* cctx = NULL; + + AssertNotNull(cctx = SSL_CONF_CTX_new()); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + AssertTrue(1); + + /* set flags */ + AssertIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_FILE), + WOLFSSL_CONF_FLAG_FILE); + AssertIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CERTIFICATE), + WOLFSSL_CONF_FLAG_FILE | WOLFSSL_CONF_FLAG_CERTIFICATE); + /* sanity check */ + AssertIntEQ(SSL_CONF_cmd(cctx, "foo", "foobar"), -2); + AssertIntEQ(SSL_CONF_cmd(cctx, "foo", NULL), -2); + AssertIntEQ(SSL_CONF_cmd(cctx, NULL, NULL), WOLFSSL_FAILURE); + AssertIntEQ(SSL_CONF_cmd(cctx, NULL, "foobar"), WOLFSSL_FAILURE); + AssertIntEQ(SSL_CONF_cmd(NULL, "-curves", "foobar"), WOLFSSL_FAILURE); + + /* cmd Certificate and Private Key*/ + { + #ifndef NO_CERTS + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; + + AssertIntEQ(SSL_CONF_cmd(cctx, "Certificate", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "PrivateKey", NULL), -3); + + AssertIntEQ(SSL_CONF_cmd(cctx, "Certificate", ourCert), + WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_cmd(cctx, "PrivateKey", ourKey), WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + #endif + } + + /* cmd curves */ + { + #if defined(HAVE_ECC) + const char* curve = "secp256r1"; + + AssertIntEQ(SSL_CONF_cmd(cctx, "Curves", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "Curves", curve), WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + #endif + } + + /* cmd CipherString */ + { + char* cipher = wolfSSL_get_cipher_list(0/*top priority*/); + + AssertIntEQ(SSL_CONF_cmd(cctx, "CipherString", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "CipherString", cipher), WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + } + + /* cmd DH parameter */ + { + #if !defined(NO_DH) && !defined(NO_BIO) + const char* ourdhcert = "./certs/dh3072.pem"; + + AssertIntEQ(SSL_CONF_cmd(cctx, "DHParameters", NULL), -3); + AssertIntEQ(SSL_CONF_cmd(cctx, "DHParameters", ourdhcert), + WOLFSSL_SUCCESS); + AssertIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); + + #endif + } + SSL_CTX_free(ctx); + SSL_CONF_CTX_free(cctx); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + +static void test_wolfSSL_CRYPTO_get_ex_new_index(void) +{ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + int idx1,idx2; + + printf(testingFmt, "test_wolfSSL_CRYPTO_get_ex_new_index()"); + + /* test for unsupported flass index */ + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_APP, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI_METHOD, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DRBG, + 0,NULL, NULL, NULL, NULL ), -1); + AssertIntEQ(CRYPTO_get_ex_new_index(20, 0,NULL, NULL, NULL, NULL ), -1); + + /* test for supported class index */ + idx1 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, + 0,NULL, NULL, NULL, NULL ); + idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, + 0,NULL, NULL, NULL, NULL ); + AssertIntNE(idx1, -1); + AssertIntNE(idx2, -1); + AssertIntNE(idx1, idx2); + + idx1 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, + 0,NULL, NULL, NULL, NULL ); + idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, + 0,NULL, NULL, NULL, NULL ); + AssertIntNE(idx1, -1); + AssertIntNE(idx2, -1); + AssertIntNE(idx1, idx2); + + idx1 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, + 0,NULL, NULL, NULL, NULL ); + idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, + 0,NULL, NULL, NULL, NULL ); + AssertIntNE(idx1, -1); + AssertIntNE(idx2, -1); + AssertIntNE(idx1, idx2); + + printf(resultFmt, "passed"); +#endif /* HAVE_EX_DATA || FORTRESS */ +} + +static void test_wolfSSL_set_psk_use_session_callback(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_PSK) + printf(testingFmt, "test_wolfSSL_set_psk_use_session_callback()"); + SSL_CTX* ctx; + SSL* ssl; + const char* testCertFile; + const char* testKeyFile; + + #ifdef WOLFSSL_TLS13 + #ifdef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); + #endif +#ifndef NO_RSA + testCertFile = svrCertFile; + testKeyFile = svrKeyFile; +#elif defined(HAVE_ECC) + testCertFile = eccCertFile; + testKeyFile = eccKeyFile; +#else + testCertFile = NULL; + testKeyFile = NULL; +#endif + if (testCertFile != NULL && testKeyFile != NULL) { + AssertTrue(SSL_CTX_use_certificate_file(ctx, testCertFile, + SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, testKeyFile, + SSL_FILETYPE_PEM)); + } + + ssl = SSL_new(ctx); + AssertNotNull(ssl); + + SSL_set_psk_use_session_callback(ssl, + my_psk_use_session_cb); + AssertTrue(1); + + SSL_CTX_free(ctx); + SSL_free(ssl); + #else + (void)ctx; + (void)ssl; + (void)testCertFile; + (void)testKeyFile; + #endif + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_DH_get0_pqg(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) + DH *dh = NULL; + BIGNUM* p; + BIGNUM* q; + BIGNUM* g; + (void)dh; + (void)p; + (void)q; + (void)g; + +#if defined(OPENSSL_ALL) +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) + FILE* f = NULL; + unsigned char buf[268]; + const unsigned char* pt = buf; + long len = 0; + + dh = NULL; + XMEMSET(buf, 0, sizeof(buf)); + /* Test 2048 bit parameters */ + f = XFOPEN("./certs/dh2048.der", "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + AssertNotNull(dh = d2i_DHparams(NULL, &pt, len)); + AssertNotNull(dh->p); + AssertNotNull(dh->p); + AssertTrue(pt != buf); + AssertIntEQ(DH_generate_key(dh), WOLFSSL_SUCCESS); + + DH_get0_pqg(dh, (const BIGNUM**)&p, + (const BIGNUM**)&q, + (const BIGNUM**) &g); + + AssertPtrEq(p, dh->p); + AssertPtrEq(q, dh->q); + AssertPtrEq(g, dh->g); + DH_free(dh); +#endif +#endif + printf(testingFmt, "test_wolfSSL_DH_get0_pqg"); + + dh = wolfSSL_DH_new(); + AssertNotNull(dh); + + /* invalid parameters test */ + DH_get0_pqg(NULL, (const BIGNUM**)&p, + (const BIGNUM**)&q, + (const BIGNUM**)&g); + + DH_get0_pqg(dh, NULL, + (const BIGNUM**)&q, + (const BIGNUM**)&g); + + DH_get0_pqg(dh, NULL, NULL, (const BIGNUM**)&g); + + DH_get0_pqg(dh, NULL, NULL, NULL); + AssertTrue(1); + + DH_get0_pqg(dh, (const BIGNUM**)&p, + (const BIGNUM**)&q, + (const BIGNUM**)&g); + + AssertPtrEq(p, NULL); + AssertPtrEq(q, NULL); + AssertPtrEq(g, NULL); + DH_free(dh); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_DH */ +} + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -40796,6 +44690,7 @@ void ApiTest(void) AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), WOLFSSL_SUCCESS); test_wolfSSL_CTX_use_PrivateKey_file(); test_wolfSSL_CTX_load_verify_locations(); + test_wolfSSL_CertManagerCheckOCSPResponse(); test_wolfSSL_CertManagerLoadCABuffer(); test_wolfSSL_CertManagerGetCerts(); test_wolfSSL_CertManagerSetVerify(); @@ -40820,12 +44715,14 @@ void ApiTest(void) test_wolfSSL_SetMinMaxDhKey_Sz(); test_SetTmpEC_DHE_Sz(); test_wolfSSL_dtls_set_mtu(); + test_wolfSSL_DH_get0_pqg(); #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) test_wolfSSL_read_write(); #if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) test_wolfSSL_reuse_WOLFSSLobj(); #endif + test_wolfSSL_CTX_verifyDepth_ServerClient(); test_wolfSSL_dtls_export(); #endif AssertIntEQ(test_wolfSSL_SetMinVersion(), WOLFSSL_SUCCESS); @@ -40878,6 +44775,7 @@ void ApiTest(void) test_wolfSSL_X509_subject_name_hash(); test_wolfSSL_X509_issuer_name_hash(); test_wolfSSL_X509_check_host(); + test_wolfSSL_X509_check_email(); test_wolfSSL_DES(); test_wolfSSL_certs(); test_wolfSSL_X509_check_private_key(); @@ -40910,6 +44808,7 @@ void ApiTest(void) test_wolfSSL_EVP_DecodeInit(); test_wolfSSL_EVP_DecodeUpdate(); test_wolfSSL_EVP_DecodeFinal(); + test_wolfSSL_EVP_PKEY_print_public(); test_wolfSSL_CTX_add_extra_chain_cert(); #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) test_wolfSSL_ERR_peek_last_error_line(); @@ -40925,6 +44824,7 @@ void ApiTest(void) test_wolfSSL_sk_SSL_CIPHER(); test_wolfSSL_PKCS7_certs(); test_wolfSSL_X509_STORE_CTX(); + test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup(); test_wolfSSL_X509_STORE_CTX_get0_current_issuer(); test_wolfSSL_msgCb(); test_wolfSSL_either_side(); @@ -40932,6 +44832,9 @@ void ApiTest(void) test_generate_cookie(); test_wolfSSL_X509_STORE_set_flags(); test_wolfSSL_X509_LOOKUP_load_file(); + test_wolfSSL_X509_Name_canon(); + test_wolfSSL_X509_LOOKUP_ctrl_file(); + test_wolfSSL_X509_LOOKUP_ctrl_hash_dir(); test_wolfSSL_X509_NID(); test_wolfSSL_X509_STORE_CTX_set_time(); test_wolfSSL_get0_param(); @@ -40939,16 +44842,20 @@ void ApiTest(void) test_wolfSSL_X509_STORE_CTX_get0_store(); test_wolfSSL_X509_STORE(); test_wolfSSL_X509_STORE_load_locations(); + test_wolfSSL_X509_load_crl_file(); test_wolfSSL_BN(); + test_wolfSSL_CTX_get0_set1_param(); #ifndef NO_BIO test_wolfSSL_PEM_read_bio(); test_wolfSSL_BIO(); #endif test_wolfSSL_ASN1_STRING(); test_wolfSSL_ASN1_BIT_STRING(); + test_wolfSSL_a2i_ASN1_INTEGER(); test_wolfSSL_X509(); test_wolfSSL_X509_VERIFY_PARAM(); test_wolfSSL_X509_sign(); + test_wolfSSL_X509_sign2(); test_wolfSSL_X509_get0_tbs_sigalg(); test_wolfSSL_X509_ALGOR_get0(); test_wolfSSL_X509_get_X509_PUBKEY(); @@ -40963,10 +44870,15 @@ void ApiTest(void) test_wolfSSL_CTX_add_client_CA(); test_wolfSSL_CTX_set_srp_username(); test_wolfSSL_CTX_set_srp_password(); + test_wolfSSL_CTX_set_ecdh_auto(); + test_wolfSSL_THREADID_hash(); + test_wolfSSL_RAND_set_rand_method(); test_wolfSSL_RAND_bytes(); + test_wolfSSL_BN_rand(); test_wolfSSL_pseudo_rand(); test_wolfSSL_PKCS8_Compat(); test_wolfSSL_PKCS8_d2i(); + test_error_queue_per_thread(); test_wolfSSL_ERR_put_error(); #ifndef NO_BIO test_wolfSSL_ERR_print_errors(); @@ -40988,6 +44900,7 @@ void ApiTest(void) test_wolfSSL_BIO_should_retry(); test_wolfSSL_d2i_PUBKEY(); test_wolfSSL_BIO_write(); + test_wolfSSL_BIO_connect(); test_wolfSSL_BIO_printf(); test_wolfSSL_BIO_f_md(); #endif @@ -41008,7 +44921,13 @@ void ApiTest(void) test_wolfSSL_DH_1536_prime(); test_wolfSSL_PEM_write_DHparams(); test_wolfSSL_AES_ecb_encrypt(); + test_wolfSSL_MD5(); + test_wolfSSL_MD5_Transform(); + test_wolfSSL_SHA_Transform(); test_wolfSSL_SHA256(); + test_wolfSSL_SHA256_Transform(); + test_wolfSSL_SHA224(); + test_wolfSSL_SHA512_Transform(); test_wolfSSL_X509_get_serialNumber(); test_wolfSSL_X509_CRL(); test_wolfSSL_d2i_X509_REQ(); @@ -41018,8 +44937,10 @@ void ApiTest(void) test_wolfSSL_PEM_X509_INFO_read_bio(); test_wolfSSL_PEM_read_bio_ECPKParameters(); #endif + test_wolfSSL_X509_STORE_get1_certs(); test_wolfSSL_X509_NAME_ENTRY_get_object(); test_wolfSSL_OpenSSL_add_all_algorithms(); + test_wolfSSL_OPENSSL_hexstr2buf(); test_wolfSSL_ASN1_STRING_print_ex(); test_wolfSSL_ASN1_TIME_to_generalizedtime(); test_wolfSSL_ASN1_INTEGER_set(); @@ -41041,10 +44962,15 @@ void ApiTest(void) test_wolfSSL_OCSP_resp_count(); test_wolfSSL_OCSP_resp_get0(); test_wolfSSL_EVP_PKEY_derive(); -#ifndef NO_RSA +#ifndef NO_RSA test_wolfSSL_RSA_padding_add_PKCS1_PSS(); -#endif +#endif + test_CONF_modules_xxx(); + test_CRYPTO_set_dynlock_xxx(); + test_CRYPTO_THREADID_xxx(); + test_ENGINE_cleanup(); + test_wolfSSL_EC_KEY_set_group(); #if defined(OPENSSL_ALL) test_wolfSSL_X509_PUBKEY_get(); test_wolfSSL_sk_CIPHER_description(); @@ -41089,6 +45015,8 @@ void ApiTest(void) test_wolfSSL_EVP_DigestFinal_ex(); test_wolfSSL_EVP_PKEY_assign_DH(); test_wolfSSL_EVP_BytesToKey(); + test_wolfSSL_EVP_PKEY_param_check(); + test_wolfSSL_QT_EVP_PKEY_CTX_free(); test_IncCtr(); test_wolfSSL_OBJ_ln(); test_wolfSSL_OBJ_sn(); @@ -41132,7 +45060,7 @@ void ApiTest(void) test_wolfSSL_EC_get_builtin_curves(); test_wolfSSL_CRYPTO_memcmp(); - + test_wolfSSL_read_detect_TCP_disconnect(); /* test the no op functions for compatibility */ test_no_op_functions(); @@ -41187,7 +45115,8 @@ void ApiTest(void) AssertIntEQ(test_RsaSigFailure_cm(), ASN_SIG_CONFIRM_E); #endif /* NO_CERTS */ -#ifdef HAVE_PK_CALLBACKS +#if defined(HAVE_PK_CALLBACKS) && (!defined(WOLFSSL_NO_TLS12) || \ + !defined(NO_OLD_TLS)) /* public key callback tests */ test_DhCallbacks(); #endif @@ -41197,6 +45126,19 @@ void ApiTest(void) test_export_keying_material(); #endif /* HAVE_KEYING_MATERIAL */ + test_wolfSSL_CTX_get_min_proto_version(); + + test_wolfSSL_security_level(); + test_wolfSSL_SSL_in_init(); + test_wolfSSL_EC_curve(); + test_wolfSSL_OpenSSL_version(); + test_wolfSSL_set_psk_use_session_callback(); + + test_CONF_CTX_FILE(); + test_CONF_CTX_CMDLINE(); + test_wolfSSL_CRYPTO_get_ex_new_index(); + test_wolfSSL_DH_get0_pqg(); + /*wolfcrypt */ printf("\n-----------------wolfcrypt unit tests------------------\n"); AssertFalse(test_wolfCrypt_Init()); @@ -41286,6 +45228,7 @@ void ApiTest(void) AssertIntEQ(test_wc_CmacUpdate(), 0); AssertIntEQ(test_wc_CmacFinal(), 0); AssertIntEQ(test_wc_AesCmacGenerate(), 0); + AssertIntEQ(test_wc_AesGcmStream(), 0); AssertIntEQ(test_wc_Des3_SetIV(), 0); AssertIntEQ(test_wc_Des3_SetKey(), 0); @@ -41474,6 +45417,7 @@ void ApiTest(void) AssertIntEQ(test_ToTraditional(), 0); AssertIntEQ(test_wc_EccPrivateKeyToDer(), 0); + AssertIntEQ(test_wc_DhPublicKeyDecode(), 0); AssertIntEQ(test_wc_Ed25519KeyToDer(), 0); AssertIntEQ(test_wc_Ed25519PrivateKeyToDer(), 0); AssertIntEQ(test_wc_Ed448KeyToDer(), 0); diff --git a/tests/hash.c b/tests/hash.c index ef0ee0c93..fd5e79c64 100644 --- a/tests/hash.c +++ b/tests/hash.c @@ -1,6 +1,6 @@ /* hash.c has unit tests * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/tests/include.am b/tests/include.am index 17443dcf1..aade835f0 100644 --- a/tests/include.am +++ b/tests/include.am @@ -13,8 +13,8 @@ tests_unit_test_SOURCES = \ tests/srp.c \ examples/client/client.c \ examples/server/server.c -tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE) +tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h @@ -31,7 +31,9 @@ EXTRA_DIST += tests/test.conf \ tests/test-psk-no-id-sha2.conf \ tests/test-dtls.conf \ tests/test-dtls-fails.conf \ + tests/test-dtls-fails-cipher.conf \ tests/test-dtls-group.conf \ + tests/test-dtls-mtu.conf \ tests/test-dtls-reneg-client.conf \ tests/test-dtls-reneg-server.conf \ tests/test-dtls-resume.conf \ @@ -52,5 +54,6 @@ EXTRA_DIST += tests/test.conf \ tests/test-p521.conf \ tests/test-ecc-cust-curves.conf \ tests/NCONF_test.cnf \ + tests/test-tls-downgrade.conf \ tests/TXT_DB.txt DISTCLEANFILES+= tests/.libs/unit.test diff --git a/tests/srp.c b/tests/srp.c index 1132f35b0..7cd13326d 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -1,6 +1,6 @@ /* srp.c SRP unit tests * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/tests/suites.c b/tests/suites.c index 7d02f4223..cd554f96e 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -1,6 +1,6 @@ /* suites.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -82,6 +82,8 @@ static int GetTlsVersion(const char* line) if (begin) { begin += 3; + if (*begin == 'd' || *begin == 'e') + begin += 2; version = atoi(begin); } @@ -807,7 +809,7 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } - wolfSSL_CTX_UseAsync(cipherSuiteCtx, devId); + wolfSSL_CTX_SetDevId(cipherSuiteCtx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ /* support for custom command line tests */ @@ -978,6 +980,19 @@ int SuiteTest(int argc, char** argv) goto exit; } #endif +#ifdef WOLFSSL_DTLS_MTU + /* Add dtls different MTU size tests. + * These also use grouping to force wolfSSL to + * bounce off the MTU limit more */ + strcpy(argv0[1], "tests/test-dtls-mtu.conf"); + printf("starting dtls MTU tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif #ifdef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls-sha2.conf"); @@ -1003,6 +1018,20 @@ int SuiteTest(int argc, char** argv) } strcpy(argv0[2], ""); #endif +#ifdef WOLFSSL_EXTRA_ALERTS + /* failure tests */ + args.argc = 3; + strcpy(argv0[1], "tests/test-dtls-fails-cipher.conf"); + strcpy(argv0[2], "expFail"); /* tests are expected to fail */ + printf("starting dtls cipher mismatch tests that expect failure\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + strcpy(argv0[2], ""); +#endif #endif #ifdef WOLFSSL_SCTP /* add dtls-sctp extra suites */ diff --git a/tests/test-dtls-fails-cipher.conf b/tests/test-dtls-fails-cipher.conf new file mode 100644 index 000000000..70a587612 --- /dev/null +++ b/tests/test-dtls-fails-cipher.conf @@ -0,0 +1,9 @@ +# server DTLSv1.2 cipher mismatch +-v 3 +-u +-l DHE-RSA-AES128-SHA256 + +# client DTLSv1.2 cipher mismatch +-v 3 +-u +-l DHE-RSA-AES256-SHA256 diff --git a/tests/test-dtls-mtu.conf b/tests/test-dtls-mtu.conf new file mode 100644 index 000000000..cb08e2e06 --- /dev/null +++ b/tests/test-dtls-mtu.conf @@ -0,0 +1,2151 @@ +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-u 1024 +-f +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-u 1024 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-u 1024 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-u 1024 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-u 1024 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1 IDEA-CBC-SHA +-u 1024 +-f +-v 2 +-l IDEA-CBC-SHA + +# client DTLSv1 IDEA-CBC-SHA +-u 1024 +-f +-v 2 +-l IDEA-CBC-SHA + +# server DTLSv1 DES-CBC3-SHA +-u 1024 +-f +-v 2 +-l DES-CBC3-SHA + +# client DTLSv1 DES-CBC3-SHA +-u 1024 +-f +-v 2 +-l DES-CBC3-SHA + +# server DTLSv1.2 DES-CBC3-SHA +-u 1024 +-f +-v 3 +-l DES-CBC3-SHA + +# client DTLSv1.2 DES-CBC3-SHA +-u 1024 +-f +-v 3 +-l DES-CBC3-SHA + +# server DTLSv1 AES128-SHA +-u 1024 +-f +-v 2 +-l AES128-SHA + +# client DTLSv1 AES128-SHA +-u 1024 +-f +-v 2 +-l AES128-SHA + +# server DTLSv1.2 AES128-SHA +-u 1024 +-f +-v 3 +-l AES128-SHA + +# client DTLSv1.2 AES128-SHA +-u 1024 +-f +-v 3 +-l AES128-SHA + +# server DTLSv1 AES256-SHA +-u 1024 +-f +-v 2 +-l AES256-SHA + +# client DTLSv1 AES256-SHA +-u 1024 +-f +-v 2 +-l AES256-SHA + +# server DTLSv1.2 AES256-SHA +-u 1024 +-f +-v 3 +-l AES256-SHA + +# client DTLSv1.2 AES256-SHA +-u 1024 +-f +-v 3 +-l AES256-SHA + +# server DTLSv1.2 AES128-SHA256 +-u 1024 +-f +-v 3 +-l AES128-SHA256 + +# client DTLSv1.2 AES128-SHA256 +-u 1024 +-f +-v 3 +-l AES128-SHA256 + +# server DTLSv1.2 AES256-SHA256 +-u 1024 +-f +-v 3 +-l AES256-SHA256 + +# client DTLSv1.2 AES256-SHA256 +-u 1024 +-f +-v 3 +-l AES256-SHA256 + +# server DTLSv1.1 ECDHE-RSA-DES3 +-u 1024 +-f +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.1 ECDHE-RSA-DES3 +-u 1024 +-f +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDHE-RSA-AES128 +-u 1024 +-f +-v 2 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.1 ECDHE-RSA-AES128 +-u 1024 +-f +-v 2 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.1 ECDHE-RSA-AES256 +-u 1024 +-f +-v 2 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.1 ECDHE-RSA-AES256 +-u 1024 +-f +-v 2 +-l ECDHE-RSA-AES256-SHA + +# server DTLSv1.2 ECDHE-RSA-DES3 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.2 ECDHE-RSA-DES3 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.2 ECDHE-RSA-AES128 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.2 ECDHE-RSA-AES256 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA + +# server TLSv1 ECDHE-ECDSA-NULL-SHA +-u 1024 +-f +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-u 1024 +-f +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-DES3 +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-DES3 +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES128 +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES128 +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES256 +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES256 +-u 1024 +-f +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-DES3 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-DES3 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-RSA-DES3 +-u 1024 +-f +-v 2 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-DES3 +-u 1024 +-f +-v 2 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDH-RSA-AES128 +-u 1024 +-f +-v 2 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES128 +-u 1024 +-f +-v 2 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.1 ECDH-RSA-AES256 +-u 1024 +-f +-v 2 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES256 +-u 1024 +-f +-v 2 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.2 ECDH-RSA-DES3 +-u 1024 +-f +-v 3 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-DES3 +-u 1024 +-f +-v 3 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDH-RSA-AES128 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES128-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.1 ECDH-ECDSA-DES3 +-u 1024 +-f +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-DES3 +-u 1024 +-f +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-AES128 +-u 1024 +-f +-v 2 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES128 +-u 1024 +-f +-v 2 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-AES256 +-u 1024 +-f +-v 2 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES256 +-u 1024 +-f +-v 2 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-DES3 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-DES3 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES256-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-u 1024 +-f +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-u 1024 +-f +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-u 1024 +-f +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-u 1024 +-f +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# server DTLSv1 PSK-AES128 +-s +-u 1024 +-f +-v 2 +-l PSK-AES128-CBC-SHA + +# client DTLSv1 PSK-AES128 +-s +-u 1024 +-f +-v 2 +-l PSK-AES128-CBC-SHA + +# server DTLSv1 PSK-AES256 +-s +-u 1024 +-f +-v 2 +-l PSK-AES256-CBC-SHA + +# client DTLSv1 PSK-AES256 +-s +-u 1024 +-f +-v 2 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128 +-s +-u 1024 +-f +-v 3 +-l PSK-AES128-CBC-SHA + +# client DTLSv1.2 PSK-AES128 +-s +-u 1024 +-f +-v 3 +-l PSK-AES128-CBC-SHA + +# server DTLSv1.2 PSK-AES256 +-s +-u 1024 +-f +-v 3 +-l PSK-AES256-CBC-SHA + +# client DTLSv1.2 PSK-AES256 +-s +-u 1024 +-f +-v 3 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128-SHA256 +-s +-u 1024 +-f +-v 3 +-l PSK-AES128-CBC-SHA256 + +# client DTLSv1.2 PSK-AES128-SHA256 +-s +-u 1024 +-f +-v 3 +-l PSK-AES128-CBC-SHA256 + +# server DTLSv1.2 PSK-AES256-SHA384 +-s +-u 1024 +-f +-v 3 +-l PSK-AES256-CBC-SHA384 + +# client DTLSv1.2 PSK-AES256-SHA384 +-s +-u 1024 +-f +-v 3 +-l PSK-AES256-CBC-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-u 1024 +-f +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 PSK-AES128-GCM-SHA256 +-u 1024 +-f +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# client DTLSv1.2 PSK-AES128-GCM-SHA256 +-u 1024 +-f +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# server DTLSv1.2 PSK-AES256-GCM-SHA384 +-u 1024 +-f +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# client DTLSv1.2 PSK-AES256-GCM-SHA384 +-u 1024 +-f +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM8 (OpenSSL-compat alias) +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM8 (OpenSSL-compat alias) +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-CCM8 (OpenSSL-compat alias) +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-CCM8 (OpenSSL-compat alias) +-u 1024 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ADH-AES128-SHA +-u 1024 +-f +-a +-v 3 +-l ADH-AES128-SHA + +# client DTLSv1.2 ADH-AES128-SHA +-u 1024 +-f +-a +-v 3 +-l ADH-AES128-SHA + +# server DTLSv1.0 ADH-AES128-SHA +-u 1024 +-f +-a +-v 2 +-l ADH-AES128-SHA + +# client DTLSv1.0 ADH-AES128-SHA +-u 1024 +-f +-a +-v 2 +-l ADH-AES128-SHA + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-u 512 +-f +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-u 512 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-u 512 +-f +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-u 512 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-u 512 +-f +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1 IDEA-CBC-SHA +-u 512 +-f +-v 2 +-l IDEA-CBC-SHA + +# client DTLSv1 IDEA-CBC-SHA +-u 512 +-f +-v 2 +-l IDEA-CBC-SHA + +# server DTLSv1 DES-CBC3-SHA +-u 512 +-f +-v 2 +-l DES-CBC3-SHA + +# client DTLSv1 DES-CBC3-SHA +-u 512 +-f +-v 2 +-l DES-CBC3-SHA + +# server DTLSv1.2 DES-CBC3-SHA +-u 512 +-f +-v 3 +-l DES-CBC3-SHA + +# client DTLSv1.2 DES-CBC3-SHA +-u 512 +-f +-v 3 +-l DES-CBC3-SHA + +# server DTLSv1 AES128-SHA +-u 512 +-f +-v 2 +-l AES128-SHA + +# client DTLSv1 AES128-SHA +-u 512 +-f +-v 2 +-l AES128-SHA + +# server DTLSv1.2 AES128-SHA +-u 512 +-f +-v 3 +-l AES128-SHA + +# client DTLSv1.2 AES128-SHA +-u 512 +-f +-v 3 +-l AES128-SHA + +# server DTLSv1 AES256-SHA +-u 512 +-f +-v 2 +-l AES256-SHA + +# client DTLSv1 AES256-SHA +-u 512 +-f +-v 2 +-l AES256-SHA + +# server DTLSv1.2 AES256-SHA +-u 512 +-f +-v 3 +-l AES256-SHA + +# client DTLSv1.2 AES256-SHA +-u 512 +-f +-v 3 +-l AES256-SHA + +# server DTLSv1.2 AES128-SHA256 +-u 512 +-f +-v 3 +-l AES128-SHA256 + +# client DTLSv1.2 AES128-SHA256 +-u 512 +-f +-v 3 +-l AES128-SHA256 + +# server DTLSv1.2 AES256-SHA256 +-u 512 +-f +-v 3 +-l AES256-SHA256 + +# client DTLSv1.2 AES256-SHA256 +-u 512 +-f +-v 3 +-l AES256-SHA256 + +# server DTLSv1.1 ECDHE-RSA-DES3 +-u 512 +-f +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.1 ECDHE-RSA-DES3 +-u 512 +-f +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDHE-RSA-AES128 +-u 512 +-f +-v 2 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.1 ECDHE-RSA-AES128 +-u 512 +-f +-v 2 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.1 ECDHE-RSA-AES256 +-u 512 +-f +-v 2 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.1 ECDHE-RSA-AES256 +-u 512 +-f +-v 2 +-l ECDHE-RSA-AES256-SHA + +# server DTLSv1.2 ECDHE-RSA-DES3 +-u 512 +-f +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.2 ECDHE-RSA-DES3 +-u 512 +-f +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.2 ECDHE-RSA-AES128 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.2 ECDHE-RSA-AES256 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA + +# server TLSv1 ECDHE-ECDSA-NULL-SHA +-u 512 +-f +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-u 512 +-f +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-DES3 +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-DES3 +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES128 +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES128 +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES256 +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES256 +-u 512 +-f +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-DES3 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-DES3 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-RSA-DES3 +-u 512 +-f +-v 2 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-DES3 +-u 512 +-f +-v 2 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDH-RSA-AES128 +-u 512 +-f +-v 2 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES128 +-u 512 +-f +-v 2 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.1 ECDH-RSA-AES256 +-u 512 +-f +-v 2 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES256 +-u 512 +-f +-v 2 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.2 ECDH-RSA-DES3 +-u 512 +-f +-v 3 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-DES3 +-u 512 +-f +-v 3 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDH-RSA-AES128 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES128-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.1 ECDH-ECDSA-DES3 +-u 512 +-f +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-DES3 +-u 512 +-f +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-AES128 +-u 512 +-f +-v 2 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES128 +-u 512 +-f +-v 2 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-AES256 +-u 512 +-f +-v 2 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES256 +-u 512 +-f +-v 2 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-DES3 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-DES3 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES256-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-u 512 +-f +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-u 512 +-f +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-u 512 +-f +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-u 512 +-f +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# server DTLSv1 PSK-AES128 +-s +-u 512 +-f +-v 2 +-l PSK-AES128-CBC-SHA + +# client DTLSv1 PSK-AES128 +-s +-u 512 +-f +-v 2 +-l PSK-AES128-CBC-SHA + +# server DTLSv1 PSK-AES256 +-s +-u 512 +-f +-v 2 +-l PSK-AES256-CBC-SHA + +# client DTLSv1 PSK-AES256 +-s +-u 512 +-f +-v 2 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128 +-s +-u 512 +-f +-v 3 +-l PSK-AES128-CBC-SHA + +# client DTLSv1.2 PSK-AES128 +-s +-u 512 +-f +-v 3 +-l PSK-AES128-CBC-SHA + +# server DTLSv1.2 PSK-AES256 +-s +-u 512 +-f +-v 3 +-l PSK-AES256-CBC-SHA + +# client DTLSv1.2 PSK-AES256 +-s +-u 512 +-f +-v 3 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128-SHA256 +-s +-u 512 +-f +-v 3 +-l PSK-AES128-CBC-SHA256 + +# client DTLSv1.2 PSK-AES128-SHA256 +-s +-u 512 +-f +-v 3 +-l PSK-AES128-CBC-SHA256 + +# server DTLSv1.2 PSK-AES256-SHA384 +-s +-u 512 +-f +-v 3 +-l PSK-AES256-CBC-SHA384 + +# client DTLSv1.2 PSK-AES256-SHA384 +-s +-u 512 +-f +-v 3 +-l PSK-AES256-CBC-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-u 512 +-f +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 PSK-AES128-GCM-SHA256 +-u 512 +-f +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# client DTLSv1.2 PSK-AES128-GCM-SHA256 +-u 512 +-f +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# server DTLSv1.2 PSK-AES256-GCM-SHA384 +-u 512 +-f +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# client DTLSv1.2 PSK-AES256-GCM-SHA384 +-u 512 +-f +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM8 (OpenSSL-compat alias) +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM8 (OpenSSL-compat alias) +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES128-CCM8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-CCM8 (OpenSSL-compat alias) +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-CCM8 (OpenSSL-compat alias) +-u 512 +-f +-v 3 +-l ECDHE-ECDSA-AES256-CCM8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ADH-AES128-SHA +-u 512 +-f +-a +-v 3 +-l ADH-AES128-SHA + +# client DTLSv1.2 ADH-AES128-SHA +-u 512 +-f +-a +-v 3 +-l ADH-AES128-SHA + +# server DTLSv1.0 ADH-AES128-SHA +-u 512 +-f +-a +-v 2 +-l ADH-AES128-SHA + +# client DTLSv1.0 ADH-AES128-SHA +-u 512 +-f +-a +-v 2 +-l ADH-AES128-SHA diff --git a/tests/test-ed25519.conf b/tests/test-ed25519.conf index 342a476b6..d6cc898e7 100644 --- a/tests/test-ed25519.conf +++ b/tests/test-ed25519.conf @@ -2,7 +2,7 @@ -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/ed25519/server-ed25519.pem --k ./certs/ed25519/server-ed25519-key.pem +-k ./certs/ed25519/server-ed25519-priv.pem -d # client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 @@ -28,7 +28,7 @@ -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/ed25519/server-ed25519.pem --k ./certs/ed25519/server-ed25519-key.pem +-k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem -V # Remove -V when CRL for ED25519 certificates available. @@ -37,7 +37,7 @@ -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/ed25519/client-ed25519.pem --k ./certs/ed25519/client-ed25519-key.pem +-k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem -C @@ -45,7 +45,7 @@ -v 4 -l TLS13-AES128-GCM-SHA256 -c ./certs/ed25519/server-ed25519.pem --k ./certs/ed25519/server-ed25519-key.pem +-k ./certs/ed25519/server-ed25519-priv.pem -d # client TLSv1.3 TLS13-AES128-GCM-SHA256 @@ -59,7 +59,7 @@ -v 4 -l TLS13-AES128-GCM-SHA256 -c ./certs/ed25519/server-ed25519.pem --k ./certs/ed25519/server-ed25519-key.pem +-k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem -V # Remove -V when CRL for ED25519 certificates available. @@ -68,7 +68,7 @@ -v 4 -l TLS13-AES128-GCM-SHA256 -c ./certs/ed25519/client-ed25519.pem --k ./certs/ed25519/client-ed25519-key.pem +-k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem -C diff --git a/tests/test-tls-downgrade.conf b/tests/test-tls-downgrade.conf new file mode 100644 index 000000000..509ecda9b --- /dev/null +++ b/tests/test-tls-downgrade.conf @@ -0,0 +1,30 @@ +# server TLSv1.3 +-v 4 +-l ECDHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.2, should fail +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# server TLSv1.2 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.3, should fail +-v 4 +-l ECDHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# server TLSv1.2 +-v d 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.3 with downgrade option, set downgrade to TLSv1.3, should fail +-7 4 +-v d 4 +-l ECDHE-RSA-AES256-GCM-SHA384 +-H exitWithRet diff --git a/tests/test-tls13-psk.conf b/tests/test-tls13-psk.conf index b8b7e2607..31ca902bc 100644 --- a/tests/test-tls13-psk.conf +++ b/tests/test-tls13-psk.conf @@ -1,15 +1,17 @@ # server TLSv1.3 PSK +# Use AES128-GCM and SHA256 -v 4 -s -l TLS13-AES128-GCM-SHA256 -d # client TLSv1.3 PSK +# Use AES128-GCM and SHA256 -v 4 -s -l TLS13-AES128-GCM-SHA256 -# server TLSv1.3 PSK +# server TLSv1.3 PSK plus -v 4 -j -l TLS13-AES128-GCM-SHA256 @@ -29,3 +31,53 @@ # client TLSv1.3 not-PSK -v 4 -l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 PSK +# AES256-GCM and SHA384 +-v 4 +-s +-l TLS13-AES256-GCM-SHA384 +-d + +# client TLSv1.3 PSK +# AES256-GCM and SHA384 +-v 4 +-s +-l TLS13-AES256-GCM-SHA384 + +# Disabling ChaCha20 results in failures. +# server TLSv1.3 PSK +# CHACHA20 only supported +#-v 4 +#-s +#-l TLS13-CHACHA20-POLY1305-SHA256 + +# client TLSv1.3 PSK +# AESGCM-SHA256 is first but CHACHA20 is negotiated as it is also SHA-256 +#-v 4 +#-s +#-l TLS13-AES128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256 + +# server TLSv1.3 PSK +# AESGCM-SHA256 is first but CHACHA20 is negotiated as it is also SHA-256 +#-v 4 +#-s +#-l TLS13-AES128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256 + +# client TLSv1.3 PSK +# CHACHA20 only supported +#-v 4 +#-s +#-l TLS13-CHACHA20-POLY1305-SHA256 + +# server TLSv1.3 PSK +# AESGCM-SHA256 is first but CHACHA20 is negotiated as it is also SHA-256 +#-v 4 +#-s +#-l TLS13-AES128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256 + +# client TLSv1.3 PSK +# CHACHA20 only supported +#-v 4 +#-s +#-l TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-GCM-SHA256 diff --git a/tests/unit.c b/tests/unit.c index 670e1d198..5d7325983 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -1,6 +1,6 @@ /* unit.c API unit tests driver * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/tests/unit.h b/tests/unit.h index 67f49f5f9..33e78b4a9 100644 --- a/tests/unit.h +++ b/tests/unit.h @@ -1,6 +1,6 @@ /* unit.c API unit tests driver * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -53,10 +53,10 @@ #define AssertFalse(x) Assert(!(x), ("%s is false", #x), (#x " => TRUE")) #define AssertNotNull(x) Assert( (x), ("%s is not null", #x), (#x " => NULL")) -#define AssertNull(x) do { \ - void* _x = (void *) (x); \ - \ - Assert(!_x, ("%s is null", #x), (#x " => %p", _x)); \ +#define AssertNull(x) do { \ + PEDANTIC_EXTENSION void* _x = (void *) (x); \ + \ + Assert(!_x, ("%s is null", #x), (#x " => %p", _x)); \ } while(0) #define AssertInt(x, y, op, er) do { \ diff --git a/testsuite/include.am b/testsuite/include.am index ed2604427..a3eea3978 100644 --- a/testsuite/include.am +++ b/testsuite/include.am @@ -13,8 +13,8 @@ testsuite_testsuite_test_SOURCES = \ examples/echoserver/echoserver.c \ examples/server/server.c \ testsuite/testsuite.c -testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE) +testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += testsuite/testsuite.sln diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index d390b5483..f68eaa4f8 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -1,6 +1,6 @@ /* testsuite.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -56,6 +56,10 @@ static THREAD_RETURN simple_test(func_args*); #else static void simple_test(func_args*); #endif +static int test_tls(func_args* server_args); +static void show_ciphers(void); +static void cleanup_output(void); +static int validate_cleanup_output(void); enum { NUMARGS = 3 @@ -79,6 +83,7 @@ char* myoptarg = NULL; #endif /* NO_TESTSUITE_MAIN_DRIVER */ #ifdef HAVE_STACK_SIZE +/* Wrap TLS echo client to free thread locals. */ static void *echoclient_test_wrapper(void* args) { echoclient_test(args); @@ -108,8 +113,9 @@ int testsuite_test(int argc, char** argv) int num = 6; #endif #ifdef HAVE_STACK_SIZE - void *serverThreadStackContext = 0; + void *serverThreadStackContext = NULL; #endif + int ret; #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { @@ -158,94 +164,42 @@ int testsuite_test(int argc, char** argv) if (server_args.return_code != 0) return server_args.return_code; /* Echo input wolfSSL client server test */ #ifdef HAVE_STACK_SIZE - StackSizeCheck_launch(&server_args, echoserver_test, &serverThread, &serverThreadStackContext); + StackSizeCheck_launch(&server_args, echoserver_test, &serverThread, + &serverThreadStackContext); #else start_thread(echoserver_test, &server_args, &serverThread); #endif - wait_tcp_ready(&server_args); - { - func_args echo_args; - char* myArgv[NUMARGS]; - char arg[3][32]; + /* Create unique file name */ + outputName = mymktemp(tempName, len, num); + if (outputName == NULL) { + printf("Could not create unique file name"); + return EXIT_FAILURE; + } - myArgv[0] = arg[0]; - myArgv[1] = arg[1]; - myArgv[2] = arg[2]; + ret = test_tls(&server_args); + if (ret != 0) { + cleanup_output(); + return ret; + } - echo_args.argc = 3; - echo_args.argv = myArgv; - - /* Create unique file name */ - outputName = mymktemp(tempName, len, num); - if (outputName == NULL) { - printf("Could not create unique file name"); - return EXIT_FAILURE; - } - - strcpy(arg[0], "testsuite"); - strcpy(arg[1], "input"); - strcpy(arg[2], outputName); - - /* Share the signal, it has the new port number in it. */ - echo_args.signal = server_args.signal; - - /* make sure OK */ - - #ifdef HAVE_STACK_SIZE - fputs("echoclient_test #1: ", stdout); - StackSizeCheck(&echo_args, echoclient_test_wrapper); - #else - echoclient_test(&echo_args); - #endif - if (echo_args.return_code != 0) return echo_args.return_code; - -#ifdef WOLFSSL_DTLS - wait_tcp_ready(&server_args); + /* Server won't quit unless TLS test has worked. */ +#ifdef HAVE_STACK_SIZE + fputs("reaping echoserver_test: ", stdout); + StackSizeCheck_reap(serverThread, serverThreadStackContext); +#else + join_thread(serverThread); #endif - /* send quit to echoserver */ - echo_args.argc = 2; - strcpy(echo_args.argv[1], "quit"); - - #ifdef HAVE_STACK_SIZE - fputs("echoclient_test #2: ", stdout); - StackSizeCheck(&echo_args, echoclient_test_wrapper); - #else - echoclient_test(&echo_args); - #endif - if (echo_args.return_code != 0) return echo_args.return_code; - #ifdef HAVE_STACK_SIZE - fputs("reaping echoserver_test: ", stdout); - StackSizeCheck_reap(serverThread, serverThreadStackContext); - #else - join_thread(serverThread); - #endif - if (server_args.return_code != 0) return server_args.return_code; + if (server_args.return_code != 0) { + cleanup_output(); + return server_args.return_code; } - /* show ciphers */ - { - char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE]; - XMEMSET(ciphers, 0, sizeof(ciphers)); - wolfSSL_get_ciphers(ciphers, sizeof(ciphers)-1); - printf("ciphers = %s\n", ciphers); - } + show_ciphers(); - /* validate output equals input */ - { - #ifndef NO_SHA256 - byte input[WC_SHA256_DIGEST_SIZE]; - byte output[WC_SHA256_DIGEST_SIZE]; - - file_test("input", input); - file_test(outputName, output); - #endif - remove(outputName); - #ifndef NO_SHA256 - if (memcmp(input, output, sizeof(input)) != 0) - return EXIT_FAILURE; - #endif - } + ret = validate_cleanup_output(); + if (ret != 0) + return EXIT_FAILURE; wolfSSL_Cleanup(); FreeTcpReady(&ready); @@ -270,6 +224,114 @@ int testsuite_test(int argc, char** argv) } #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) +/* Perform a basic TLS handshake. + * + * First connection to echo a file. + * Second to tell TLS server to quit. + * + * @param [in,out] server_args Object sent to server thread. + * @return 0 on success. + * @return echoclient error return code on failure. + */ +static int test_tls(func_args* server_args) +{ + func_args echo_args; + char* myArgv[NUMARGS]; + char arg[3][32]; + + /* Set up command line arguments for echoclient to send input file + * and write echoed data to temporary output file. */ + myArgv[0] = arg[0]; + myArgv[1] = arg[1]; + myArgv[2] = arg[2]; + + echo_args.argc = 3; + echo_args.argv = myArgv; + + strcpy(arg[0], "testsuite"); + strcpy(arg[1], "input"); + strcpy(arg[2], outputName); + + /* Share the signal, it has the new port number in it. */ + echo_args.signal = server_args->signal; + + /* Ready to execute client - wait for server to be ready. */ + wait_tcp_ready(server_args); + + /* Do a client TLS connection. */ +#ifdef HAVE_STACK_SIZE + fputs("echoclient_test #1: ", stdout); + StackSizeCheck(&echo_args, echoclient_test_wrapper); +#else + echoclient_test(&echo_args); +#endif + if (echo_args.return_code != 0) + return echo_args.return_code; + +#ifdef WOLFSSL_DTLS + /* Ensure server is ready for UDP data. */ + wait_tcp_ready(server_args); +#endif + + /* Next client connection - send quit to shutdown server. */ + echo_args.argc = 2; + strcpy(echo_args.argv[1], "quit"); + + /* Do a client TLS connection. */ +#ifdef HAVE_STACK_SIZE + fputs("echoclient_test #2: ", stdout); + StackSizeCheck(&echo_args, echoclient_test_wrapper); +#else + echoclient_test(&echo_args); +#endif + if (echo_args.return_code != 0) + return echo_args.return_code; + + return 0; +} + +/* Show cipher suites available. */ +static void show_ciphers() +{ + char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE]; + XMEMSET(ciphers, 0, sizeof(ciphers)); + wolfSSL_get_ciphers(ciphers, sizeof(ciphers)-1); + printf("ciphers = %s\n", ciphers); +} + +/* Cleanup temporary output file. */ +static void cleanup_output() +{ + remove(outputName); +} + +/* Validate output equals input using a hash. Remove temporary output file. + * + * @return 0 on success. + * @return 1 on failure. + */ +static int validate_cleanup_output() +{ +#ifndef NO_SHA256 + byte input[WC_SHA256_DIGEST_SIZE]; + byte output[WC_SHA256_DIGEST_SIZE]; + + file_test("input", input); + file_test(outputName, output); +#endif + cleanup_output(); +#ifndef NO_SHA256 + if (memcmp(input, output, sizeof(input)) != 0) + return 1; +#endif + return 0; +} + +/* Simple server. + * + * @param [in] args Object for server data in thread. + * @return Return code. + */ #ifdef HAVE_STACK_SIZE static THREAD_RETURN simple_test(func_args* args) #else @@ -313,13 +375,13 @@ static void simple_test(func_args* args) strcpy(argvc[0], "SimpleClient"); cliArgs.argv = cliArgv; cliArgs.return_code = 0; - #ifndef USE_WINDOWS_API - cliArgs.argc = NUMARGS; - strcpy(argvc[1], "-p"); - snprintf(argvc[2], sizeof(argvc[2]), "%d", svrArgs.signal->port); - #else - cliArgs.argc = 1; - #endif +#ifndef USE_WINDOWS_API + cliArgs.argc = NUMARGS; + strcpy(argvc[1], "-p"); + snprintf(argvc[2], sizeof(argvc[2]), "%d", svrArgs.signal->port); +#else + cliArgs.argc = 1; +#endif client_test(&cliArgs); if (cliArgs.return_code != 0) { @@ -339,6 +401,10 @@ static void simple_test(func_args* args) #endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ +/* Wait for the server to be ready for a connection. + * + * @param [in] args Object to send to thread. + */ void wait_tcp_ready(func_args* args) { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) @@ -355,6 +421,12 @@ void wait_tcp_ready(func_args* args) } +/* Start a thread. + * + * @param [in] fun Function to executre in thread. + * @param [in] args Object to send to function in thread. + * @param [out] thread Handle to thread. + */ void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread) { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) @@ -377,6 +449,10 @@ void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread) } +/* Join thread to wait for completion. + * + * @param [in] thread Handle to thread. + */ void join_thread(THREAD_TYPE thread) { #if defined(_POSIX_THREADS) && !defined(__MINGW32__) @@ -400,6 +476,11 @@ void join_thread(THREAD_TYPE thread) #ifndef NO_SHA256 +/* Create SHA-256 hash of the file based on filename. + * + * @param [in] file Name of file. + * @parma [out] check Buffer to hold SHA-256 hash. + */ void file_test(const char* file, byte* check) { FILE* f; @@ -455,16 +536,18 @@ char* myoptarg = NULL; int main(int argc, char** argv) { - func_args server_args; + func_args wolfcrypt_test_args; - server_args.argc = argc; - server_args.argv = argv; + wolfcrypt_test_args.argc = argc; + wolfcrypt_test_args.argv = argv; wolfSSL_Init(); ChangeToWolfRoot(); - wolfcrypt_test(&server_args); - if (server_args.return_code != 0) return server_args.return_code; + /* No TLS - only doing cryptographic algorithm testing. */ + wolfcrypt_test(&wolfcrypt_test_args); + if (wolfcrypt_test_args.return_code != 0) + return wolfcrypt_test_args.return_code; wolfSSL_Cleanup(); printf("\nAll tests passed!\n"); diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index b480f5d94..c93836e92 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1,6 +1,6 @@ /* benchmark.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -33,6 +33,7 @@ #include #include #include +#include /* Macro to disable benchmark */ #ifndef NO_CRYPT_BENCHMARK @@ -61,6 +62,7 @@ #define printf PRINTF #elif defined(WOLFSSL_DEOS) #include + #include #undef printf #define printf printx #elif defined(MICRIUM) @@ -108,6 +110,20 @@ #undef NO_FILESYSTEM #define NO_FILESYSTEM +#elif defined(ANDROID) + #ifdef XMALLOC_USER + #include /* we're using malloc / free direct here */ + #endif + #ifndef STRING_USER + #include + #endif + #include + + #define printf(...) \ + __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__) + #define fprintf(fp, ...) \ + __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__) + #else #if defined(XMALLOC_USER) || defined(FREESCALE_MQX) /* MQX classic needs for EXIT_FAILURE */ @@ -170,6 +186,12 @@ #ifdef HAVE_ED448 #include #endif +#ifdef WOLFCRYPT_HAVE_ECCSI + #include +#endif +#ifdef WOLFCRYPT_HAVE_SAKKE + #include +#endif #include #ifdef HAVE_NTRU @@ -289,6 +311,14 @@ #define BENCH_ED448_SIGN 0x00800000 #define BENCH_ECC_P256 0x01000000 #define BENCH_ECC_P384 0x02000000 +#define BENCH_ECCSI_KEYGEN 0x00000020 +#define BENCH_ECCSI_PAIRGEN 0x00000040 +#define BENCH_ECCSI_VALIDATE 0x00000080 +#define BENCH_ECCSI 0x00000400 +#define BENCH_SAKKE_KEYGEN 0x10000000 +#define BENCH_SAKKE_RSKGEN 0x20000000 +#define BENCH_SAKKE_VALIDATE 0x40000000 +#define BENCH_SAKKE 0x80000000 /* Other */ #define BENCH_RNG 0x00000001 @@ -318,13 +348,13 @@ typedef struct bench_alg { /* Command line option string. */ const char* str; /* Bit values to set. */ - int val; + word32 val; } bench_alg; #ifndef MAIN_NO_ARGS /* All recognized cipher algorithm choosing command line options. */ static const bench_alg bench_cipher_opt[] = { - { "-cipher", -1 }, + { "-cipher", 0xffffffff }, #ifdef HAVE_AES_CBC { "-aes-cbc", BENCH_AES_CBC }, #endif @@ -373,12 +403,12 @@ static const bench_alg bench_cipher_opt[] = { #ifdef HAVE_IDEA { "-idea", BENCH_IDEA }, #endif - { NULL, 0} + { NULL, 0 } }; /* All recognized digest algorithm choosing command line options. */ static const bench_alg bench_digest_opt[] = { - { "-digest", -1 }, + { "-digest", 0xffffffff }, #ifndef NO_MD5 { "-md5", BENCH_MD5 }, #endif @@ -428,12 +458,12 @@ static const bench_alg bench_digest_opt[] = { #ifdef HAVE_BLAKE2S { "-blake2s", BENCH_BLAKE2S }, #endif - { NULL, 0} + { NULL, 0 } }; /* All recognized MAC algorithm choosing command line options. */ static const bench_alg bench_mac_opt[] = { - { "-mac", -1 }, + { "-mac", 0xffffffff }, #ifdef WOLFSSL_CMAC { "-cmac", BENCH_CMAC }, #endif @@ -461,12 +491,12 @@ static const bench_alg bench_mac_opt[] = { { "-pbkdf2", BENCH_PBKDF2 }, #endif #endif - { NULL, 0} + { NULL, 0 } }; /* All recognized asymmetric algorithm choosing command line options. */ static const bench_alg bench_asym_opt[] = { - { "-asym", -1 }, + { "-asym", 0xffffffff }, #ifndef NO_RSA #ifdef WOLFSSL_KEY_GEN { "-rsa-kg", BENCH_RSA_KEYGEN }, @@ -509,13 +539,25 @@ static const bench_alg bench_asym_opt[] = { { "-ed448-kg", BENCH_ED448_KEYGEN }, { "-ed448", BENCH_ED448_SIGN }, #endif - { NULL, 0} +#ifdef WOLFCRYPT_HAVE_ECCSI + { "-eccsi-kg", BENCH_ECCSI_KEYGEN }, + { "-eccsi-pair", BENCH_ECCSI_PAIRGEN }, + { "-eccsi-val", BENCH_ECCSI_VALIDATE }, + { "-eccsi", BENCH_ECCSI }, +#endif +#ifdef WOLFCRYPT_HAVE_SAKKE + { "-sakke-kg", BENCH_SAKKE_KEYGEN }, + { "-sakke-rsk", BENCH_SAKKE_RSKGEN }, + { "-sakke-val", BENCH_SAKKE_VALIDATE }, + { "-sakke", BENCH_SAKKE }, +#endif + { NULL, 0 } }; /* All recognized other cryptographic algorithm choosing command line options. */ static const bench_alg bench_other_opt[] = { - { "-other", -1 }, + { "-other", 0xffffffff }, #ifndef WC_NO_RNG { "-rng", BENCH_RNG }, #endif @@ -600,11 +642,11 @@ static const char* bench_result_words1[][4] = { defined(HAVE_ED25519) || defined(HAVE_CURVE448) || \ defined(HAVE_CURVE448_SHARED_SECRET) || defined(HAVE_ED448) -static const char* bench_desc_words[][9] = { - /* 0 1 2 3 4 5 6 7 8 */ - {"public", "private", "key gen", "agree" , "sign", "verify", "encryption", "decryption", NULL}, /* 0 English */ +static const char* bench_desc_words[][14] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 */ + {"public", "private", "key gen", "agree" , "sign", "verify", "encryption", "decryption", "rsk gen", "encap", "derive", "valid", "pair gen", NULL}, /* 0 English */ #ifndef NO_MULTIBYTE_PRINT - {"公開鍵", "秘密鍵" ,"鍵生成" , "鍵共有" , "署名", "検証" , "暗号化" , "復号化" , NULL}, /* 1 Japanese */ + {"公開鍵", "秘密鍵" ,"鍵生成" , "鍵共有" , "署名", "検証" , "暗号化" , "復号化" , "rsk gen", "encap", "derive", "valid", "pair gen", NULL}, /* 1 Japanese */ #endif }; @@ -752,7 +794,12 @@ static const char* bench_result_words2[][5] = { #endif /* Asynchronous helper macros */ +#ifdef WOLFSSL_QNX_CAAM +#include +static THREAD_LS_T int devId = WOLFSSL_CAAM_DEVID; +#else static THREAD_LS_T int devId = INVALID_DEVID; +#endif #ifdef WOLFSSL_ASYNC_CRYPT static WOLF_EVENT_QUEUE eventQueue; @@ -1909,6 +1956,44 @@ static void* benchmarks_do(void* args) bench_ed448KeySign(); #endif +#ifdef WOLFCRYPT_HAVE_ECCSI + #ifdef WOLFCRYPT_ECCSI_KMS + if (bench_all || (bench_asym_algs & BENCH_ECCSI_KEYGEN)) { + bench_eccsiKeyGen(); + } + if (bench_all || (bench_asym_algs & BENCH_ECCSI_PAIRGEN)) { + bench_eccsiPairGen(); + } + #endif + #ifdef WOLFCRYPT_ECCSI_CLIENT + if (bench_all || (bench_asym_algs & BENCH_ECCSI_VALIDATE)) { + bench_eccsiValidate(); + } + if (bench_all || (bench_asym_algs & BENCH_ECCSI)) { + bench_eccsi(); + } + #endif +#endif + +#ifdef WOLFCRYPT_HAVE_SAKKE + #ifdef WOLFCRYPT_SAKKE_KMS + if (bench_all || (bench_asym_algs & BENCH_SAKKE_KEYGEN)) { + bench_sakkeKeyGen(); + } + if (bench_all || (bench_asym_algs & BENCH_SAKKE_RSKGEN)) { + bench_sakkeRskGen(); + } + #endif + #ifdef WOLFCRYPT_SAKKE_CLIENT + if (bench_all || (bench_asym_algs & BENCH_SAKKE_VALIDATE)) { + bench_sakkeValidate(); + } + if (bench_all || (bench_asym_algs & BENCH_SAKKE)) { + bench_sakke(); + } + #endif +#endif + exit: /* free benchmark buffers */ XFREE(bench_plain, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); @@ -2311,10 +2396,23 @@ static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz, /* while free pending slots in queue, submit ops */ for (i = 0; i < BENCH_MAX_PENDING; i++) { if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { +#ifndef BENCHMARK_AESGCM_STREAM ret = wc_AesGcmEncrypt(&enc[i], bench_cipher, bench_plain, BENCH_SIZE, iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, bench_additional, aesAuthAddSz); +#else + ret = wc_AesGcmEncryptInit(&enc[i], NULL, 0, iv, ivSz); + if (ret == 0) { + ret = wc_AesGcmEncryptUpdate(&enc[i], bench_cipher, + bench_plain, BENCH_SIZE, bench_additional, + aesAuthAddSz); + } + if (ret == 0) { + ret = wc_AesGcmEncryptFinal(&enc[i], bench_tag, + AES_AUTH_TAG_SZ); + } +#endif if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { goto exit_aes_gcm; } @@ -2350,10 +2448,23 @@ exit_aes_gcm: /* while free pending slots in queue, submit ops */ for (i = 0; i < BENCH_MAX_PENDING; i++) { if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, ×, numBlocks, &pending)) { +#ifndef BENCHMARK_AESGCM_STREAM ret = wc_AesGcmDecrypt(&dec[i], bench_plain, bench_cipher, BENCH_SIZE, iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, bench_additional, aesAuthAddSz); +#else + ret = wc_AesGcmDecryptInit(&enc[i], NULL, 0, iv, ivSz); + if (ret == 0) { + ret = wc_AesGcmDecryptUpdate(&enc[i], bench_plain, + bench_cipher, BENCH_SIZE, bench_additional, + aesAuthAddSz); + } + if (ret == 0) { + ret = wc_AesGcmDecryptFinal(&enc[i], bench_tag, + AES_AUTH_TAG_SZ); + } +#endif if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, ×, &pending)) { goto exit_aes_gcm_dec; } @@ -4568,18 +4679,17 @@ static void bench_rsa_helper(int doAsync, RsaKey rsaKey[BENCH_MAX_PENDING], #ifndef WOLFSSL_RSA_VERIFY_ONLY DECLARE_VAR(message, byte, TEST_STRING_SZ, HEAP_HINT); #endif - #if !defined(WOLFSSL_MDK5_COMPLv5) + #if !defined(WOLFSSL_MDK5_COMPLv5) && !defined(_WIN32_WCE) /* MDK5 compiler regard this as a executable statement, and does not allow declarations after the line. */ DECLARE_ARRAY_DYNAMIC_DEC(enc, byte, BENCH_MAX_PENDING, rsaKeySz, HEAP_HINT); #else byte* enc[BENCH_MAX_PENDING]; #endif #if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) - #if !defined(WOLFSSL_MDK5_COMPLv5) + #if !defined(WOLFSSL_MDK5_COMPLv5) && !defined(_WIN32_WCE) /* MDK5 compiler regard this as a executable statement, and does not allow declarations after the line. */ DECLARE_ARRAY_DYNAMIC_DEC(out, byte, BENCH_MAX_PENDING, rsaKeySz, HEAP_HINT); #else - int idxout; byte* out[BENCH_MAX_PENDING]; #endif #else @@ -5354,12 +5464,20 @@ void bench_ecc_curve(int curveId) void bench_eccMakeKey(int doAsync, int curveId) { int ret = 0, i, times, count, pending = 0; + int deviceID; int keySize; ecc_key genKey[BENCH_MAX_PENDING]; char name[BENCH_ECC_NAME_SZ]; double start; const char**desc = bench_desc_words[lng_index]; + +#ifdef WOLFSSL_ASYNC_CRYPT + deviceID = doAsync ? devId : INVALID_DEVID; +#else + deviceID = devId; +#endif + keySize = wc_ecc_get_curve_size_from_id(curveId); /* clear for done cleanup */ @@ -5377,8 +5495,7 @@ void bench_eccMakeKey(int doAsync, int curveId) ×, genTimes, &pending)) { wc_ecc_free(&genKey[i]); - ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, doAsync ? - devId : INVALID_DEVID); + ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, deviceID); if (ret < 0) { goto exit; } @@ -5411,6 +5528,7 @@ exit: void bench_ecc(int doAsync, int curveId) { int ret = 0, i, times, count, pending = 0; + int deviceID; int keySize; char name[BENCH_ECC_NAME_SZ]; ecc_key genKey[BENCH_MAX_PENDING]; @@ -5434,6 +5552,12 @@ void bench_ecc(int doAsync, int curveId) DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, MAX_ECC_BYTES, HEAP_HINT); #endif +#ifdef WOLFSSL_ASYNC_CRYPT + deviceID = doAsync ? devId : INVALID_DEVID; +#else + deviceID = devId; +#endif + /* clear for done cleanup */ XMEMSET(&genKey, 0, sizeof(genKey)); #ifdef HAVE_ECC_DHE @@ -5444,8 +5568,7 @@ void bench_ecc(int doAsync, int curveId) /* init keys */ for (i = 0; i < BENCH_MAX_PENDING; i++) { /* setup an context for each key */ - if ((ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, - doAsync ? devId : INVALID_DEVID)) < 0) { + if ((ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, deviceID)) < 0) { goto exit; } ret = wc_ecc_make_key_ex(&gRng, keySize, &genKey[i], curveId); @@ -5457,7 +5580,7 @@ void bench_ecc(int doAsync, int curveId) } #ifdef HAVE_ECC_DHE - if ((ret = wc_ecc_init_ex(&genKey2[i], HEAP_HINT, INVALID_DEVID)) < 0) { + if ((ret = wc_ecc_init_ex(&genKey2[i], HEAP_HINT, deviceID)) < 0) { goto exit; } if ((ret = wc_ecc_make_key_ex(&gRng, keySize, &genKey2[i], @@ -5611,6 +5734,7 @@ exit: (void)times; (void)desc; (void)start; + (void)name; } @@ -6028,6 +6152,422 @@ exit_ed_verify: } #endif /* HAVE_ED448 */ +#ifdef WOLFCRYPT_HAVE_ECCSI +#ifdef WOLFCRYPT_ECCSI_KMS +void bench_eccsiKeyGen(void) +{ + EccsiKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + int ret; + + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + wc_InitEccsiKey(&genKey, NULL, INVALID_DEVID); + ret = wc_MakeEccsiKey(&genKey, &gRng); + if (ret != 0) { + printf("wc_MakeEccsiKey failed: %d\n", ret); + break; + } + wc_FreeEccsiKey(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ECCSI", 256, desc[2], 0, count, start, 0); +} + +void bench_eccsiPairGen(void) +{ + EccsiKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + mp_int ssk; + ecc_point* pvt; + byte id[] = { 0x01, 0x23, 0x34, 0x45 }; + int ret; + + (void)mp_init(&ssk); + pvt = wc_ecc_new_point(); + wc_InitEccsiKey(&genKey, NULL, INVALID_DEVID); + (void)wc_MakeEccsiKey(&genKey, &gRng); + + /* RSK Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_MakeEccsiPair(&genKey, &gRng, WC_HASH_TYPE_SHA256, id, + sizeof(id), &ssk, pvt); + if (ret != 0) { + printf("wc_MakeEccsiPair failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ECCSI", 256, desc[12], 0, count, start, 0); + + wc_FreeEccsiKey(&genKey); + wc_ecc_del_point(pvt); + mp_free(&ssk); +} +#endif + +#ifdef WOLFCRYPT_ECCSI_CLIENT +void bench_eccsiValidate(void) +{ + EccsiKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + mp_int ssk; + ecc_point* pvt; + byte id[] = { 0x01, 0x23, 0x34, 0x45 }; + int valid; + int ret; + + (void)mp_init(&ssk); + pvt = wc_ecc_new_point(); + wc_InitEccsiKey(&genKey, NULL, INVALID_DEVID); + (void)wc_MakeEccsiKey(&genKey, &gRng); + (void)wc_MakeEccsiPair(&genKey, &gRng, WC_HASH_TYPE_SHA256, id, sizeof(id), + &ssk, pvt); + + /* Validation of RSK */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_ValidateEccsiPair(&genKey, WC_HASH_TYPE_SHA256, id, + sizeof(id), &ssk, pvt, &valid); + if (ret != 0 || !valid) { + printf("wc_ValidateEccsiPair failed: %d (valid=%d))\n", ret, + valid); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ECCSI", 256, desc[11], 0, count, start, 0); + + wc_FreeEccsiKey(&genKey); + wc_ecc_del_point(pvt); + mp_free(&ssk); +} + +void bench_eccsi(void) +{ + EccsiKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + mp_int ssk; + ecc_point* pvt; + byte id[] = { 0x01, 0x23, 0x34, 0x45 }; + byte msg[] = { 0x01, 0x23, 0x34, 0x45 }; + byte hash[WC_SHA256_DIGEST_SIZE]; + byte hashSz = (byte)sizeof(hash); + byte sig[257]; + word32 sigSz = sizeof(sig); + int ret; + int verified; + + (void)mp_init(&ssk); + pvt = wc_ecc_new_point(); + (void)wc_InitEccsiKey(&genKey, NULL, INVALID_DEVID); + (void)wc_MakeEccsiKey(&genKey, &gRng); + (void)wc_MakeEccsiPair(&genKey, &gRng, WC_HASH_TYPE_SHA256, id, sizeof(id), + &ssk, pvt); + (void)wc_HashEccsiId(&genKey, WC_HASH_TYPE_SHA256, id, sizeof(id), pvt, + hash, &hashSz); + (void)wc_SetEccsiHash(&genKey, hash, hashSz); + (void)wc_SetEccsiPair(&genKey, &ssk, pvt); + + /* Encapsulate */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_SignEccsiHash(&genKey, &gRng, WC_HASH_TYPE_SHA256, msg, + sizeof(msg), sig, &sigSz); + if (ret != 0) { + printf("wc_SignEccsiHash failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ECCSI", 256, desc[4], 0, count, start, 0); + + /* Derive */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_VerifyEccsiHash(&genKey, WC_HASH_TYPE_SHA256, msg, + sizeof(msg), sig, sigSz, &verified); + if (ret != 0 || !verified) { + printf("wc_VerifyEccsiHash failed: %d (verified: %d)\n", ret, + verified); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ECCSI", 256, desc[5], 0, count, start, 0); + + wc_FreeEccsiKey(&genKey); + wc_ecc_del_point(pvt); +} +#endif /* WOLFCRYPT_ECCSI_CLIENT */ +#endif /* WOLFCRYPT_HAVE_ECCSI */ + +#ifdef WOLFCRYPT_HAVE_SAKKE +#ifdef WOLFCRYPT_SAKKE_KMS +void bench_sakkeKeyGen(void) +{ + SakkeKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + int ret; + + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + wc_InitSakkeKey_ex(&genKey, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + ret = wc_MakeSakkeKey(&genKey, &gRng); + if (ret != 0) { + printf("wc_MakeSakkeKey failed: %d\n", ret); + break; + } + wc_FreeSakkeKey(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[2], 0, count, start, 0); +} + +void bench_sakkeRskGen(void) +{ + SakkeKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + ecc_point* rsk; + byte id[] = { 0x01, 0x23, 0x34, 0x45 }; + int ret; + + rsk = wc_ecc_new_point(); + wc_InitSakkeKey_ex(&genKey, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + (void)wc_MakeSakkeKey(&genKey, &gRng); + + /* RSK Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_MakeSakkeRsk(&genKey, id, sizeof(id), rsk); + if (ret != 0) { + printf("wc_MakeSakkeRsk failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[8], 0, count, start, 0); + + wc_FreeSakkeKey(&genKey); + wc_ecc_del_point(rsk); +} +#endif + +#ifdef WOLFCRYPT_SAKKE_CLIENT +void bench_sakkeValidate(void) +{ + SakkeKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + ecc_point* rsk; + byte id[] = { 0x01, 0x23, 0x34, 0x45 }; + int valid; + int ret; + + rsk = wc_ecc_new_point(); + (void)wc_InitSakkeKey_ex(&genKey, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + (void)wc_MakeSakkeKey(&genKey, &gRng); + (void)wc_MakeSakkeRsk(&genKey, id, sizeof(id), rsk); + (void)wc_ValidateSakkeRsk(&genKey, id, sizeof(id), rsk, &valid); + + /* Validation of RSK */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_ValidateSakkeRsk(&genKey, id, sizeof(id), rsk, &valid); + if (ret != 0 || !valid) { + printf("wc_ValidateSakkeRsk failed: %d (valid=%d))\n", ret, + valid); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[11], 0, count, start, 0); + + wc_FreeSakkeKey(&genKey); + wc_ecc_del_point(rsk); +} + +void bench_sakke(void) +{ + SakkeKey genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + ecc_point* rsk; + byte id[] = { 0x01, 0x23, 0x34, 0x45 }; + byte ssv[] = { 0x01, 0x23, 0x34, 0x45 }; + byte derSSV[sizeof(ssv)]; + byte auth[257]; + word16 authSz = sizeof(auth); + int ret = 0; + byte* table = NULL; + word32 len = 0; + byte* iTable = NULL; + word32 iTableLen = 0; + + rsk = wc_ecc_new_point(); + (void)wc_InitSakkeKey_ex(&genKey, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + (void)wc_MakeSakkeKey(&genKey, &gRng); + (void)wc_MakeSakkeRsk(&genKey, id, sizeof(id), rsk); + (void)wc_SetSakkeRsk(&genKey, rsk, NULL, 0); + (void)wc_SetSakkeIdentity(&genKey, id, sizeof(id)); + + /* Encapsulate */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_MakeSakkeEncapsulatedSSV(&genKey, WC_HASH_TYPE_SHA256, ssv, + sizeof(ssv), auth, &authSz); + if (ret != 0) { + printf("wc_MakeSakkeEncapsulatedSSV failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[9], 0, count, start, 0); + + /* Derive */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + XMEMCPY(derSSV, ssv, sizeof(ssv)); + ret = wc_DeriveSakkeSSV(&genKey, WC_HASH_TYPE_SHA256, derSSV, + sizeof(derSSV), auth, authSz); + if (ret != 0) { + printf("wc_DeriveSakkeSSV failed: %d\n", ret); + break; + } + } + if (ret != 0) break; + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[10], 0, count, start, 0); + + /* Calculate Point I and generate table. */ + (void)wc_MakeSakkePointI(&genKey, id, sizeof(id)); + iTableLen = 0; + (void)wc_GenerateSakkePointITable(&genKey, NULL, &iTableLen); + if (iTableLen != 0) { + iTable = (byte*)XMALLOC(iTableLen, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + (void)wc_GenerateSakkePointITable(&genKey, iTable, &iTableLen); + } + + /* Encapsulate with Point I table */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_MakeSakkeEncapsulatedSSV(&genKey, WC_HASH_TYPE_SHA256, ssv, + sizeof(ssv), auth, &authSz); + if (ret != 0) { + printf("wc_MakeSakkeEncapsulatedSSV failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[9], 0, count, start, 0); + + (void)wc_SetSakkeRsk(&genKey, rsk, table, len); + + /* Derive with Point I table */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + XMEMCPY(derSSV, ssv, sizeof(ssv)); + ret = wc_DeriveSakkeSSV(&genKey, WC_HASH_TYPE_SHA256, derSSV, + sizeof(derSSV), auth, authSz); + if (ret != 0) { + printf("wc_DeriveSakkeSSV failed: %d\n", ret); + break; + } + } + if (ret != 0) break; + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[10], 0, count, start, 0); + + len = 0; + (void)wc_GenerateSakkeRskTable(&genKey, rsk, NULL, &len); + if (len > 0) { + table = (byte*)XMALLOC(len, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + (void)wc_GenerateSakkeRskTable(&genKey, rsk, table, &len); + } + (void)wc_SetSakkeRsk(&genKey, rsk, table, len); + + /* Derive with Point I table and RSK table */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + XMEMCPY(derSSV, ssv, sizeof(ssv)); + ret = wc_DeriveSakkeSSV(&genKey, WC_HASH_TYPE_SHA256, derSSV, + sizeof(derSSV), auth, authSz); + if (ret != 0) { + printf("wc_DeriveSakkeSSV failed: %d\n", ret); + break; + } + } + if (ret != 0) break; + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[10], 0, count, start, 0); + + wc_ClearSakkePointITable(&genKey); + /* Derive with RSK table */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + XMEMCPY(derSSV, ssv, sizeof(ssv)); + ret = wc_DeriveSakkeSSV(&genKey, WC_HASH_TYPE_SHA256, derSSV, + sizeof(derSSV), auth, authSz); + if (ret != 0) { + printf("wc_DeriveSakkeSSV failed: %d\n", ret); + break; + } + } + if (ret != 0) break; + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("SAKKE", 1024, desc[10], 0, count, start, 0); + + wc_FreeSakkeKey(&genKey); + wc_ecc_del_point(rsk); +} +#endif /* WOLFCRYPT_SAKKE_CLIENT */ +#endif /* WOLFCRYPT_HAVE_SAKKE */ + #ifndef HAVE_STACK_SIZE #if defined(_WIN32) && !defined(INTIME_RTOS) @@ -6143,7 +6683,7 @@ exit_ed_verify: double current_time(int reset) { const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); - uint32_t *systemTickPtr = systemTickPointer(); + const volatile uint32_t *systemTickPtr = systemTickPointer(); (void)reset; @@ -6377,7 +6917,7 @@ static int string_matches(const char* arg, const char* str) } #endif /* MAIN_NO_ARGS */ -#ifdef WOLFSSL_ESPIDF +#if defined(WOLFSSL_ESPIDF) || defined(_WIN32_WCE) int wolf_benchmark_task( ) #elif defined(MAIN_NO_ARGS) int main() diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 23330cbc9..e9b13a410 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -1,6 +1,6 @@ /* wolfcrypt/benchmark/benchmark.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -94,6 +94,14 @@ void bench_curve448KeyGen(void); void bench_curve448KeyAgree(void); void bench_ed448KeyGen(void); void bench_ed448KeySign(void); +void bench_eccsiKeyGen(void); +void bench_eccsiPairGen(void); +void bench_eccsiValidate(void); +void bench_eccsi(void); +void bench_sakkeKeyGen(void); +void bench_sakkeRskGen(void); +void bench_sakkeValidate(void); +void bench_sakke(void); void bench_ntru(void); void bench_ntruKeyGen(void); void bench_rng(void); diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index dcc1187af..08c13faa7 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -1,6 +1,6 @@ /* aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -840,7 +840,8 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits } #endif /* HAVE_AES_DECRYPT */ -#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)) || \ +#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) \ + && !defined(WOLFSSL_QNX_CAAM)) || \ ((defined(WOLFSSL_AFALG) || defined(WOLFSSL_DEVCRYPTO_AES)) && \ defined(HAVE_AESCCM)) static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) @@ -2700,7 +2701,8 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) } #endif -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) \ + && !defined(WOLFSSL_QNX_CAAM) /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ #elif defined(WOLFSSL_AFALG) @@ -3048,7 +3050,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #if defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't yet support AES direct" - #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \ + !defined(WOLFSSL_QNX_CAAM) /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ #elif defined(WOLFSSL_AFALG) @@ -3082,8 +3085,16 @@ int wc_AesSetIV(Aes* aes, const byte* iv) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int ret = 0; - word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_HandleTypeDef hcryp; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; ret = wc_Stm32_Aes_Init(aes, &hcryp); if (ret != 0) @@ -3132,8 +3143,16 @@ int wc_AesSetIV(Aes* aes, const byte* iv) int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int ret = 0; - word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_HandleTypeDef hcryp; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; ret = wc_Stm32_Aes_Init(aes, &hcryp); if (ret != 0) @@ -3188,10 +3207,18 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { int ret; word32 *iv; - word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_InitTypeDef cryptInit; CRYP_KeyInitTypeDef keyInit; CRYP_IVInitTypeDef ivInit; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); if (ret != 0) @@ -3263,10 +3290,18 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { int ret; word32 *iv; - word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_InitTypeDef cryptInit; CRYP_KeyInitTypeDef keyInit; CRYP_IVInitTypeDef ivInit; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); if (ret != 0) @@ -3360,6 +3395,12 @@ int wc_AesSetIV(Aes* aes, const byte* iv) if ((pi == NULL) || (po == NULL)) return BAD_FUNC_ARG; /*wrong pointer*/ +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + wc_LockMutex(&Mutex_AesSEC); /* Set descriptor for SEC */ @@ -3385,16 +3426,24 @@ int wc_AesSetIV(Aes* aes, const byte* iv) secDesc->pointer7 = NULL; secDesc->nextDescriptorPtr = NULL; +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + size = AES_BUFFER_SIZE; +#endif while (sz) { secDesc->header = descHeader; XMEMCPY(secReg, aes->reg, AES_BLOCK_SIZE); - if ((sz % AES_BUFFER_SIZE) == sz) { +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + sz -= AES_BUFFER_SIZE; +#else + if (sz < AES_BUFFER_SIZE) { size = sz; sz = 0; } else { size = AES_BUFFER_SIZE; sz -= AES_BUFFER_SIZE; } +#endif + secDesc->length4 = size; secDesc->length5 = size; @@ -3460,6 +3509,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv) byte *iv, *enc_key; word32 blocks = (sz / AES_BLOCK_SIZE); +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; + iv = (byte*)aes->reg; enc_key = (byte*)aes->key; @@ -3489,8 +3546,16 @@ int wc_AesSetIV(Aes* aes, const byte* iv) word32 keySize; status_t status; byte* iv, *dec_key; - word32 blocks = (sz / AES_BLOCK_SIZE); byte temp_block[AES_BLOCK_SIZE]; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; iv = (byte*)aes->reg; dec_key = (byte*)aes->key; @@ -3524,9 +3589,17 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { int i; int offset = 0; - word32 blocks = (sz / AES_BLOCK_SIZE); byte *iv; byte temp_block[AES_BLOCK_SIZE]; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; iv = (byte*)aes->reg; @@ -3552,9 +3625,17 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { int i; int offset = 0; - word32 blocks = (sz / AES_BLOCK_SIZE); byte* iv; byte temp_block[AES_BLOCK_SIZE]; + word32 blocks = (sz / AES_BLOCK_SIZE); + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + if (blocks == 0) + return 0; iv = (byte*)aes->reg; @@ -3583,9 +3664,16 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { int ret; + if (sz == 0) + return 0; + /* hardware fails on input that is not a multiple of AES block size */ if (sz % AES_BLOCK_SIZE != 0) { +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + return BAD_LENGTH_E; +#else return BAD_FUNC_ARG; +#endif } ret = wc_Pic32AesCrypt( @@ -3606,9 +3694,16 @@ int wc_AesSetIV(Aes* aes, const byte* iv) int ret; byte scratch[AES_BLOCK_SIZE]; + if (sz == 0) + return 0; + /* hardware fails on input that is not a multiple of AES block size */ if (sz % AES_BLOCK_SIZE != 0) { +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + return BAD_LENGTH_E; +#else return BAD_FUNC_ARG; +#endif } XMEMCPY(scratch, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); @@ -3645,7 +3740,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t*)in, sz, out); } -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \ + !defined(WOLFSSL_QNX_CAAM) /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ #elif defined(WOLFSSL_AFALG) @@ -3662,7 +3758,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* Software AES - CBC Encrypt */ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = (sz / AES_BLOCK_SIZE); + word32 blocks; if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; @@ -3671,6 +3767,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv) if (sz == 0) { return 0; } + + blocks = sz / AES_BLOCK_SIZE; +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + #ifdef WOLFSSL_IMXRT_DCP /* Implemented in wolfcrypt/src/port/nxp/dcp_port.c */ if (aes->keylen == 16) @@ -3775,14 +3879,23 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { word32 blocks; - if (aes == NULL || out == NULL || in == NULL - || sz % AES_BLOCK_SIZE != 0) { + if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; } if (sz == 0) { return 0; } + + blocks = sz / AES_BLOCK_SIZE; + if (sz % AES_BLOCK_SIZE) { +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + return BAD_LENGTH_E; +#else + return BAD_FUNC_ARG; +#endif + } + #ifdef WOLFSSL_IMXRT_DCP /* Implemented in wolfcrypt/src/port/nxp/dcp_port.c */ if (aes->keylen == 16) @@ -3852,7 +3965,6 @@ int wc_AesSetIV(Aes* aes, const byte* iv) } #endif - blocks = sz / AES_BLOCK_SIZE; while (blocks--) { XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); wc_AesDecrypt(aes, (byte*)aes->tmp, out); @@ -4048,7 +4160,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv) return ret; } - #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \ + !defined(WOLFSSL_QNX_CAAM) /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ #elif defined(WOLFSSL_AFALG) @@ -4166,6 +4279,19 @@ static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) #ifdef HAVE_AESGCM +#ifdef WOLFSSL_AESGCM_STREAM + /* Access initialization counter data. */ + #define AES_INITCTR(aes) ((aes)->streamData + 0 * AES_BLOCK_SIZE) + /* Access counter data. */ + #define AES_COUNTER(aes) ((aes)->streamData + 1 * AES_BLOCK_SIZE) + /* Access tag data. */ + #define AES_TAG(aes) ((aes)->streamData + 2 * AES_BLOCK_SIZE) + /* Access last GHASH block. */ + #define AES_LASTGBLOCK(aes) ((aes)->streamData + 3 * AES_BLOCK_SIZE) + /* Access last encrypted block. */ + #define AES_LASTBLOCK(aes) ((aes)->streamData + 4 * AES_BLOCK_SIZE) +#endif + #if defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-GCM mode" @@ -4350,15 +4476,18 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) if (!((len == 16) || (len == 24) || (len == 32))) return BAD_FUNC_ARG; + if (aes == NULL) + return BAD_FUNC_ARG; #ifdef OPENSSL_EXTRA - if (aes != NULL) { - XMEMSET(aes->aadH, 0, sizeof(aes->aadH)); - aes->aadLen = 0; - } + XMEMSET(aes->aadH, 0, sizeof(aes->aadH)); + aes->aadLen = 0; #endif XMEMSET(iv, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION); +#ifdef WOLFSSL_AESGCM_STREAM + aes->gcmKeySet = 1; +#endif #ifdef WOLFSSL_AESNI /* AES-NI code generates its own H value. */ @@ -4798,7 +4927,7 @@ static void AES_GCM_encrypt(const unsigned char *in, unsigned char *out, const unsigned char* addt, const unsigned char* ivec, unsigned char *tag, word32 nbytes, word32 abytes, word32 ibytes, - wrd32 tbytes, const unsigned char* key, int nr) + word32 tbytes, const unsigned char* key, int nr) { int i, j ,k; __m128i ctr1; @@ -5257,7 +5386,7 @@ static void AES_GCM_decrypt(const unsigned char *in, unsigned char *out, else aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T); - for (i=0; iH); \ + } \ + while (0) +#endif /* WOLFSSL_AESGCM_STREAM */ /* end GCM_SMALL */ #elif defined(GCM_TABLE) @@ -5821,6 +5970,27 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, XMEMCPY(s, x, sSz); } +#ifdef WOLFSSL_AESGCM_STREAM +/* No extra initialization for table implementation. + * + * @param [in] aes AES GCM object. + */ +#define GHASH_INIT_EXTRA(aes) + +/* GHASH one block of data.. + * + * XOR block into tag and GMULT with H using pre-computed table. + * + * @param [in, out] aes AES GCM object. + * @param [in] block Block of AAD or cipher text. + */ +#define GHASH_ONE_BLOCK(aes, block) \ + do { \ + xorbuf(AES_TAG(aes), block, AES_BLOCK_SIZE); \ + GMULT(AES_TAG(aes), aes->M0); \ + } \ + while (0) +#endif /* WOLFSSL_AESGCM_STREAM */ /* end GCM_TABLE */ #elif defined(GCM_TABLE_4BIT) @@ -6096,6 +6266,27 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, XMEMCPY(s, x, sSz); } +#ifdef WOLFSSL_AESGCM_STREAM +/* No extra initialization for 4-bit table implementation. + * + * @param [in] aes AES GCM object. + */ +#define GHASH_INIT_EXTRA(aes) + +/* GHASH one block of data.. + * + * XOR block into tag and GMULT with H using pre-computed table. + * + * @param [in, out] aes AES GCM object. + * @param [in] block Block of AAD or cipher text. + */ +#define GHASH_ONE_BLOCK(aes, block) \ + do { \ + xorbuf(AES_TAG(aes), block, AES_BLOCK_SIZE); \ + GMULT(AES_TAG(aes), aes->M0); \ + } \ + while (0) +#endif /* WOLFSSL_AESGCM_STREAM */ #elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) #if !defined(FREESCALE_LTC_AES_GCM) @@ -6404,10 +6595,282 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, XMEMCPY(s, x, sSz); } +#ifdef WOLFSSL_AESGCM_STREAM +#ifdef LITTLE_ENDIAN_ORDER +/* Little-endian 32-bit word implementation requires byte reversal of H. + * + * H is all-zeros block encrypted with key. + * + * @param [in, out] aes AES GCM object. + */ +#define GHASH_INIT_EXTRA(aes) \ + ByteReverseWords((word32*)aes->H, (word32*)aes->H, AES_BLOCK_SIZE) + +/* GHASH one block of data.. + * + * XOR block, in big-endian form, into tag and GMULT with H. + * + * @param [in, out] aes AES GCM object. + * @param [in] block Block of AAD or cipher text. + */ +#define GHASH_ONE_BLOCK(aes, block) \ + do { \ + word32* x = (word32*)AES_TAG(aes); \ + word32* h = (word32*)aes->H; \ + word32 bigEnd[4]; \ + XMEMCPY(bigEnd, block, AES_BLOCK_SIZE); \ + ByteReverseWords(bigEnd, bigEnd, AES_BLOCK_SIZE); \ + x[0] ^= bigEnd[0]; \ + x[1] ^= bigEnd[1]; \ + x[2] ^= bigEnd[2]; \ + x[3] ^= bigEnd[3]; \ + GMULT(x, h); \ + } \ + while (0) + +/* GHASH in AAD and cipher text lengths in bits. + * + * Convert tag back to little-endian. + * + * @param [in, out] aes AES GCM object. + */ +#define GHASH_LEN_BLOCK(aes) \ + do { \ + word32 len[4]; \ + word32* x = (word32*)AES_TAG(aes); \ + word32* h = (word32*)aes->H; \ + len[0] = (aes->aSz >> (8*sizeof(aes->aSz) - 3)); \ + len[1] = aes->aSz << 3; \ + len[2] = (aes->cSz >> (8*sizeof(aes->cSz) - 3)); \ + len[3] = aes->cSz << 3; \ + x[0] ^= len[0]; \ + x[1] ^= len[1]; \ + x[2] ^= len[2]; \ + x[3] ^= len[3]; \ + GMULT(x, h); \ + ByteReverseWords(x, x, AES_BLOCK_SIZE); \ + } \ + while (0) +#else +/* No extra initialization for 32-bit word implementation. + * + * @param [in] aes AES GCM object. + */ +#define GHASH_INIT_EXTRA(aes) + +/* GHASH one block of data.. + * + * XOR block into tag and GMULT with H. + * + * @param [in, out] aes AES GCM object. + * @param [in] block Block of AAD or cipher text. + */ +#define GHASH_ONE_BLOCK(aes, block) \ + do { \ + word32* x = (word32*)AES_TAG(aes); \ + word32* h = (word32*)aes->H; \ + word32 block32[4]; \ + XMEMCPY(block32, block, AES_BLOCK_SIZE); \ + x[0] ^= block32[0]; \ + x[1] ^= block32[1]; \ + x[2] ^= block32[2]; \ + x[3] ^= block32[3]; \ + GMULT(x, h); \ + } \ + while (0) + +/* GHASH in AAD and cipher text lengths in bits. + * + * @param [in, out] aes AES GCM object. + */ +#define GHASH_LEN_BLOCK(aes) \ + do { \ + word32 len[4]; \ + word32* x = (word32*)AES_TAG(aes); \ + word32* h = (word32*)aes->H; \ + len[0] = (aes->aSz >> (8*sizeof(aes->aSz) - 3)); \ + len[1] = aes->aSz << 3; \ + len[2] = (aes->cSz >> (8*sizeof(aes->cSz) - 3)); \ + len[3] = aes->cSz << 3; \ + x[0] ^= len[0]; \ + x[1] ^= len[1]; \ + x[2] ^= len[2]; \ + x[3] ^= len[3]; \ + GMULT(x, h); \ + } \ + while (0) +#endif /* LITTLE_ENDIAN_ORDER */ +#endif /* WOLFSSL_AESGCM_STREAM */ #endif /* end GCM_WORD32 */ - #if !defined(WOLFSSL_XILINX_CRYPT) && !defined(WOLFSSL_AFALG_XILINX_AES) +#ifdef WOLFSSL_AESGCM_STREAM +#ifndef GHASH_LEN_BLOCK +/* Hash in the lengths of the AAD and cipher text in bits. + * + * Default implementation. + * + * @param [in, out] aes AES GCM object. + */ +#define GHASH_LEN_BLOCK(aes) \ + do { \ + byte scratch[AES_BLOCK_SIZE]; \ + FlattenSzInBits(&scratch[0], aes->aSz); \ + FlattenSzInBits(&scratch[8], aes->cSz); \ + GHASH_ONE_BLOCK(aes, scratch); \ + } \ + while (0) +#endif + +/* Initialize a GHASH for streaming operations. + * + * @param [in, out] aes AES GCM object. + */ +static void GHASH_INIT(Aes* aes) { + /* Set tag to all zeros as initial value. */ + XMEMSET(AES_TAG(aes), 0, AES_BLOCK_SIZE); + /* Reset counts of AAD and cipher text. */ + aes->aOver = 0; + aes->cOver = 0; + /* Extra initialization baed on implementation. */ + GHASH_INIT_EXTRA(aes); +} + +/* Update the GHASH with AAD and/or cipher text. + * + * @param [in,out] aes AES GCM object. + * @param [in] a Additional authentication data buffer. + * @param [in] aSz Size of data in AAD buffer. + * @param [in] c Cipher text buffer. + * @param [in] cSz Size of data in cipher text buffer. + */ +static void GHASH_UPDATE(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz) +{ + word32 blocks; + word32 partial; + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + /* Update count of AAD we have hashed. */ + aes->aSz += aSz; + /* Check if we have unprocessed data. */ + if (aes->aOver > 0) { + /* Calculate amount we can use - fill up the block. */ + byte sz = AES_BLOCK_SIZE - aes->aOver; + if (sz > aSz) { + sz = aSz; + } + /* Copy extra into last GHASH block array and update count. */ + XMEMCPY(AES_LASTGBLOCK(aes) + aes->aOver, a, sz); + aes->aOver += sz; + if (aes->aOver == AES_BLOCK_SIZE) { + /* We have filled up the block and can process. */ + GHASH_ONE_BLOCK(aes, AES_LASTGBLOCK(aes)); + /* Reset count. */ + aes->aOver = 0; + } + /* Used up some data. */ + aSz -= sz; + a += sz; + } + + /* Calculate number of blocks of AAD and the leftover. */ + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + /* GHASH full blocks now. */ + while (blocks--) { + GHASH_ONE_BLOCK(aes, a); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + /* Cache the partial block. */ + XMEMCPY(AES_LASTGBLOCK(aes), a, partial); + aes->aOver = (byte)partial; + } + } + if (aes->aOver > 0 && cSz > 0 && c != NULL) { + /* No more AAD coming and we have a partial block. */ + /* Fill the rest of the block with zeros. */ + byte sz = AES_BLOCK_SIZE - aes->aOver; + XMEMSET(AES_LASTGBLOCK(aes) + aes->aOver, 0, sz); + /* GHASH last AAD block. */ + GHASH_ONE_BLOCK(aes, AES_LASTGBLOCK(aes)); + /* Clear partial count for next time through. */ + aes->aOver = 0; + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + /* Update count of cipher text we have hashed. */ + aes->cSz += cSz; + if (aes->cOver > 0) { + /* Calculate amount we can use - fill up the block. */ + byte sz = AES_BLOCK_SIZE - aes->cOver; + if (sz > cSz) { + sz = cSz; + } + XMEMCPY(AES_LASTGBLOCK(aes) + aes->cOver, c, sz); + /* Update count of unsed encrypted counter. */ + aes->cOver += sz; + if (aes->cOver == AES_BLOCK_SIZE) { + /* We have filled up the block and can process. */ + GHASH_ONE_BLOCK(aes, AES_LASTGBLOCK(aes)); + /* Reset count. */ + aes->cOver = 0; + } + /* Used up some data. */ + cSz -= sz; + c += sz; + } + + /* Calculate number of blocks of cipher text and the leftover. */ + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + /* GHASH full blocks now. */ + while (blocks--) { + GHASH_ONE_BLOCK(aes, c); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + /* Cache the partial block. */ + XMEMCPY(AES_LASTGBLOCK(aes), c, partial); + aes->cOver = (byte)partial; + } + } +} + +/* Finalize the GHASH calculation. + * + * Complete hashing cipher text and hash the AAD and cipher text lengths. + * + * @param [in, out] aes AES GCM object. + * @param [out] s Authentication tag. + * @param [in] sSz Size of authentication tag required. + */ +static void GHASH_FINAL(Aes* aes, byte* s, word32 sSz) +{ + /* AAD block incomplete when > 0 */ + byte over = aes->aOver; + + if (aes->cOver > 0) { + /* Cipher text block incomplete. */ + over = aes->cOver; + } + if (over > 0) { + /* Zeroize the unused part of the block. */ + XMEMSET(AES_LASTGBLOCK(aes) + over, 0, AES_BLOCK_SIZE - over); + /* Hash the last block of cipher text. */ + GHASH_ONE_BLOCK(aes, AES_LASTGBLOCK(aes)); + } + /* Hash in the lengths of AAD and cipher text in bits */ + GHASH_LEN_BLOCK(aes); + /* Copy the result into s. */ + XMEMCPY(s, AES_TAG(aes), sSz); +} +#endif /* WOLFSSL_AESGCM_STREAM */ + + #ifdef FREESCALE_LTC_AES_GCM int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, @@ -6447,8 +6910,8 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, #ifdef STM32_CRYPTO_AES_GCM /* this function supports inline encrypt */ -/* define STM32_AESGCM_PARTIAL for newer STM Cube HAL's with workaround - for handling partial packets to improve auth tag calculation performance by +/* define STM32_AESGCM_PARTIAL for newer STM Cube HAL's with workaround + for handling partial packets to improve auth tag calculation performance by using hardware */ static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, @@ -6524,10 +6987,14 @@ static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz /* for cases where hardware cannot be used for authTag calculate it */ /* if IV is not 12 calculate GHASH using software */ if (ivSz != GCM_NONCE_MID_SZ -#ifndef STM32_AESGCM_PARTIAL + #ifndef CRYP_HEADERWIDTHUNIT_BYTE + /* or harware that does not support partial block */ + || sz == 0 || partial != 0 + #endif + #ifndef STM32_AESGCM_PARTIAL /* or authIn is not a multiple of 4 */ - || authPadSz != authInSz || sz == 0 || partial != 0 -#endif + || authPadSz != authInSz + #endif ) { useSwGhash = 1; } @@ -6545,17 +7012,42 @@ static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz #if defined(STM32_HAL_V2) hcryp.Init.Algorithm = CRYP_AES_GCM; + #ifdef CRYP_HEADERWIDTHUNIT_BYTE + /* V2 with CRYP_HEADERWIDTHUNIT_BYTE uses byte size for header */ + hcryp.Init.HeaderSize = authPadSz; + #else hcryp.Init.HeaderSize = authPadSz/sizeof(word32); + #endif #ifdef STM32_AESGCM_PARTIAL hcryp.Init.HeaderPadSize = authPadSz - authInSz; #endif - ByteReverseWords(partialBlock, ctr, AES_BLOCK_SIZE); - hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock; + #ifdef CRYP_KEYIVCONFIG_ONCE + /* allows repeated calls to HAL_CRYP_Encrypt */ + hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE; + #endif + ByteReverseWords(ctr, ctr, AES_BLOCK_SIZE); + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr; HAL_CRYP_Init(&hcryp); + #ifndef CRYP_KEYIVCONFIG_ONCE /* GCM payload phase - can handle partial blocks */ status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT); + #else + /* GCM payload phase - blocks */ + if (blocks) { + status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, + (blocks * AES_BLOCK_SIZE), (uint32_t*)out, STM32_HAL_TIMEOUT); + } + /* GCM payload phase - partial remainder */ + if (status == HAL_OK && (partial != 0 || blocks == 0)) { + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)partialBlock, partial, + (uint32_t*)partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + #endif if (status == HAL_OK && !useSwGhash) { /* Compute the authTag */ status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag, @@ -6663,6 +7155,7 @@ static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz #endif /* STM32_CRYPTO_AES_GCM */ #ifdef WOLFSSL_AESNI +/* For performance reasons, this code needs to be not inlined. */ int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, byte* authTag, word32 authTagSz, @@ -6880,7 +7373,6 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif - /* AES GCM Decrypt */ #if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) #ifdef FREESCALE_LTC_AES_GCM @@ -6968,7 +7460,7 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, GHASH(aes, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE); } - /* Make copy of expected authTag, which could get corrupted in some + /* Make copy of expected authTag, which could get corrupted in some * Cube HAL versions without proper partial block support. * For TLS blocks the authTag is after the output buffer, so save it */ XMEMCPY(tagExpected, authTag, authTagSz); @@ -6984,16 +7476,20 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, /* for cases where hardware cannot be used for authTag calculate it */ /* if IV is not 12 calculate GHASH using software */ - if (ivSz != GCM_NONCE_MID_SZ || sz == 0 || partial != 0 -#ifndef STM32_AESGCM_PARTIAL + if (ivSz != GCM_NONCE_MID_SZ + #ifndef CRYP_HEADERWIDTHUNIT_BYTE + /* or harware that does not support partial block */ + || sz == 0 || partial != 0 + #endif + #ifndef STM32_AESGCM_PARTIAL /* or authIn is not a multiple of 4 */ || authPadSz != authInSz -#endif + #endif ) { - GHASH(aes, authIn, authInSz, in, sz, (byte*)tag, sizeof(tag)); - wc_AesEncrypt(aes, (byte*)ctr, (byte*)partialBlock); - xorbuf(tag, partialBlock, sizeof(tag)); - tagComputed = 1; + GHASH(aes, authIn, authInSz, in, sz, (byte*)tag, sizeof(tag)); + wc_AesEncrypt(aes, (byte*)ctr, (byte*)partialBlock); + xorbuf(tag, partialBlock, sizeof(tag)); + tagComputed = 1; } /* if using hardware for authentication tag make sure its aligned and zero padded */ @@ -7029,18 +7525,42 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, #if defined(STM32_HAL_V2) hcryp.Init.Algorithm = CRYP_AES_GCM; + #ifdef CRYP_HEADERWIDTHUNIT_BYTE + /* V2 with CRYP_HEADERWIDTHUNIT_BYTE uses byte size for header */ + hcryp.Init.HeaderSize = authPadSz; + #else hcryp.Init.HeaderSize = authPadSz/sizeof(word32); + #endif #ifdef STM32_AESGCM_PARTIAL hcryp.Init.HeaderPadSize = authPadSz - authInSz; #endif - ByteReverseWords(partialBlock, ctr, AES_BLOCK_SIZE); - hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock; + #ifdef CRYP_KEYIVCONFIG_ONCE + /* allows repeated calls to HAL_CRYP_Decrypt */ + hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE; + #endif + ByteReverseWords(ctr, ctr, AES_BLOCK_SIZE); + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr; HAL_CRYP_Init(&hcryp); - /* GCM payload phase - can handle partial blocks */ + #ifndef CRYP_KEYIVCONFIG_ONCE status = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in, (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT); - if (status == HAL_OK && tagComputed == 0) { + #else + /* GCM payload phase - blocks */ + if (blocks) { + status = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in, + (blocks * AES_BLOCK_SIZE), (uint32_t*)out, STM32_HAL_TIMEOUT); + } + /* GCM payload phase - partial remainder */ + if (status == HAL_OK && (partial != 0 || blocks == 0)) { + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)partialBlock, partial, +( uint32_t*)partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + #endif + if (status == HAL_OK && !tagComputed) { /* Compute the authTag */ status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag, STM32_HAL_TIMEOUT); @@ -7125,7 +7645,7 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, if (status != SUCCESS) ret = AES_GCM_AUTH_E; if (tagComputed == 0) - XMEMCPY(tag, partialBlock, authTagSz); + XMEMCPY(tag, partialBlock, authTagSz); #endif /* WOLFSSL_STM32_CUBEMX */ wolfSSL_CryptHwMutexUnLock(); @@ -7145,6 +7665,7 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, #endif /* STM32_CRYPTO_AES_GCM */ #ifdef WOLFSSL_AESNI +/* For performance reasons, this code needs to be not inlined. */ int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, @@ -7379,6 +7900,1177 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } #endif #endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ + +#ifdef WOLFSSL_AESGCM_STREAM +/* Initialize the AES GCM cipher with an IV. C implementation. + * + * @param [in, out] aes AES object. + * @param [in] iv IV/nonce buffer. + * @param [in] ivSz Length of IV/nonce data. + */ +static void AesGcmInit_C(Aes* aes, const byte* iv, word32 ivSz) +{ + ALIGN32 byte counter[AES_BLOCK_SIZE]; + + if (ivSz == GCM_NONCE_MID_SZ) { + /* Counter is IV with bottom 4 bytes set to: 0x00,0x00,0x00,0x01. */ + XMEMCPY(counter, iv, ivSz); + XMEMSET(counter + GCM_NONCE_MID_SZ, 0, + AES_BLOCK_SIZE - GCM_NONCE_MID_SZ - 1); + counter[AES_BLOCK_SIZE - 1] = 1; + } + else { + /* Counter is GHASH of IV. */ + #ifdef OPENSSL_EXTRA + word32 aadTemp = aes->aadLen; + aes->aadLen = 0; + #endif + GHASH(aes, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE); + #ifdef OPENSSL_EXTRA + aes->aadLen = aadTemp; + #endif + } + + /* Copy in the counter for use with cipher. */ + XMEMCPY(AES_COUNTER(aes), counter, AES_BLOCK_SIZE); + /* Encrypt initial counter into a buffer for GCM. */ + wc_AesEncrypt(aes, counter, AES_INITCTR(aes)); + /* Reset state fields. */ + aes->over = 0; + aes->aSz = 0; + aes->cSz = 0; + /* Initialization for GHASH. */ + GHASH_INIT(aes); +} + +/* Update the AES GCM cipher with data. C implementation. + * + * Only enciphers data. + * + * @param [in, out] aes AES object. + * @param [in] out Cipher text or plaintext buffer. + * @param [in] in Plaintext or cipher text buffer. + * @param [in] sz Length of data. + */ +static void AesGcmCryptUpdate_C(Aes* aes, byte* out, const byte* in, word32 sz) +{ + word32 blocks; + word32 partial; + + /* Check if previous encrypted block was not used up. */ + if (aes->over > 0) { + byte pSz = AES_BLOCK_SIZE - aes->over; + if (pSz > sz) pSz = sz; + + /* Use some/all of last encrypted block. */ + xorbufout(out, AES_LASTBLOCK(aes) + aes->over, in, pSz); + aes->over = (aes->over + pSz) & (AES_BLOCK_SIZE - 1); + + /* Some data used. */ + sz -= pSz; + in += pSz; + out += pSz; + } + + /* Calculate the number of blocks needing to be encrypted and any leftover. + */ + blocks = sz / AES_BLOCK_SIZE; + partial = sz & (AES_BLOCK_SIZE - 1); + +#if defined(HAVE_AES_ECB) + /* Some hardware acceleration can gain performance from doing AES encryption + * of the whole buffer at once. + * Overwrites the cipher text before using plaintext - no inline encryption. + */ + if ((out != in) && blocks > 0) { + word32 b; + /* Place incrementing counter blocks into cipher text. */ + for (b = 0; b < blocks; b++) { + IncrementGcmCounter(AES_COUNTER(aes)); + XMEMCPY(out + b * AES_BLOCK_SIZE, AES_COUNTER(aes), AES_BLOCK_SIZE); + } + + /* Encrypt counter blocks. */ + wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks); + /* XOR in plaintext. */ + xorbuf(out, in, AES_BLOCK_SIZE * blocks); + /* Skip over processed data. */ + in += AES_BLOCK_SIZE * blocks; + out += AES_BLOCK_SIZE * blocks; + } + else +#endif /* HAVE_AES_ECB */ + { + /* Encrypt block by block. */ + while (blocks--) { + ALIGN32 byte scratch[AES_BLOCK_SIZE]; + IncrementGcmCounter(AES_COUNTER(aes)); + /* Encrypt counter into a buffer. */ + wc_AesEncrypt(aes, AES_COUNTER(aes), scratch); + /* XOR plain text into encrypted counter into cipher text buffer. */ + xorbufout(out, scratch, in, AES_BLOCK_SIZE); + /* Data complete. */ + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + } + + if (partial != 0) { + /* Generate an extra block and use up as much as needed. */ + IncrementGcmCounter(AES_COUNTER(aes)); + /* Encrypt counter into cache. */ + wc_AesEncrypt(aes, AES_COUNTER(aes), AES_LASTBLOCK(aes)); + /* XOR plain text into encrypted counter into cipher text buffer. */ + xorbufout(out, AES_LASTBLOCK(aes), in, partial); + /* Keep amount of encrypted block used. */ + aes->over = partial; + } +} + +/* Calculates authentication tag for AES GCM. C implementation. + * + * @param [in, out] aes AES object. + * @param [out] authTag Buffer to store authentication tag in. + * @param [in] authTagSz Length of tag to create. + */ +static void AesGcmFinal_C(Aes* aes, byte* authTag, word32 authTagSz) +{ + /* Calculate authentication tag. */ + GHASH_FINAL(aes, authTag, authTagSz); + /* XOR in as much of encrypted counter as is required. */ + xorbuf(authTag, AES_INITCTR(aes), authTagSz); +#ifdef OPENSSL_EXTRA + /* store AAD size for next call */ + aes->aadLen = aes->aSz; +#endif + /* Zeroize last block to protect sensitive data. */ + ForceZero(AES_LASTBLOCK(aes), AES_BLOCK_SIZE); +} + +#ifdef WOLFSSL_AESNI +/* Assembly code implementations in: aes_gcm_asm.S */ +#ifdef HAVE_INTEL_AVX2 +extern void AES_GCM_init_avx2(const unsigned char* key, int nr, + const unsigned char* ivec, unsigned int ibytes, unsigned char* h, + unsigned char* counter, unsigned char* initCtr); +extern void AES_GCM_aad_update_avx2(const unsigned char* addt, + unsigned int abytes, unsigned char* tag, unsigned char* h); +extern void AES_GCM_encrypt_block_avx2(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned char* counter); +extern void AES_GCM_ghash_block_avx2(const unsigned char* data, + unsigned char* tag, unsigned char* h); + +extern void AES_GCM_encrypt_update_avx2(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned int nbytes, + unsigned char* tag, unsigned char* h, unsigned char* counter); +extern void AES_GCM_encrypt_final_avx2(unsigned char* tag, + unsigned char* authTag, unsigned int tbytes, unsigned int nbytes, + unsigned int abytes, unsigned char* h, unsigned char* initCtr); +#endif +#ifdef HAVE_INTEL_AVX1 +extern void AES_GCM_init_avx1(const unsigned char* key, int nr, + const unsigned char* ivec, unsigned int ibytes, unsigned char* h, + unsigned char* counter, unsigned char* initCtr); +extern void AES_GCM_aad_update_avx1(const unsigned char* addt, + unsigned int abytes, unsigned char* tag, unsigned char* h); +extern void AES_GCM_encrypt_block_avx1(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned char* counter); +extern void AES_GCM_ghash_block_avx1(const unsigned char* data, + unsigned char* tag, unsigned char* h); + +extern void AES_GCM_encrypt_update_avx1(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned int nbytes, + unsigned char* tag, unsigned char* h, unsigned char* counter); +extern void AES_GCM_encrypt_final_avx1(unsigned char* tag, + unsigned char* authTag, unsigned int tbytes, unsigned int nbytes, + unsigned int abytes, unsigned char* h, unsigned char* initCtr); +#endif +extern void AES_GCM_init_aesni(const unsigned char* key, int nr, + const unsigned char* ivec, unsigned int ibytes, unsigned char* h, + unsigned char* counter, unsigned char* initCtr); +extern void AES_GCM_aad_update_aesni(const unsigned char* addt, + unsigned int abytes, unsigned char* tag, unsigned char* h); +extern void AES_GCM_encrypt_block_aesni(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned char* counter); +extern void AES_GCM_ghash_block_aesni(const unsigned char* data, + unsigned char* tag, unsigned char* h); + +extern void AES_GCM_encrypt_update_aesni(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned int nbytes, + unsigned char* tag, unsigned char* h, unsigned char* counter); +extern void AES_GCM_encrypt_final_aesni(unsigned char* tag, + unsigned char* authTag, unsigned int tbytes, unsigned int nbytes, + unsigned int abytes, unsigned char* h, unsigned char* initCtr); + +/* Initialize the AES GCM cipher with an IV. AES-NI implementations. + * + * @param [in, out] aes AES object. + * @param [in] iv IV/nonce buffer. + * @param [in] ivSz Length of IV/nonce data. + */ +static void AesGcmInit_aesni(Aes* aes, const byte* iv, word32 ivSz) +{ + /* Reset state fields. */ + aes->aSz = 0; + aes->cSz = 0; + /* Set tag to all zeros as initial value. */ + XMEMSET(AES_TAG(aes), 0, AES_BLOCK_SIZE); + /* Reset counts of AAD and cipher text. */ + aes->aOver = 0; + aes->cOver = 0; + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + SAVE_VECTOR_REGISTERS(); + AES_GCM_init_avx2((byte*)aes->key, aes->rounds, iv, ivSz, aes->H, + AES_COUNTER(aes), AES_INITCTR(aes)); + RESTORE_VECTOR_REGISTERS(); + } + else +#endif +#ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + SAVE_VECTOR_REGISTERS(); + AES_GCM_init_avx1((byte*)aes->key, aes->rounds, iv, ivSz, aes->H, + AES_COUNTER(aes), AES_INITCTR(aes)); + RESTORE_VECTOR_REGISTERS(); + } + else +#endif + { + SAVE_VECTOR_REGISTERS(); + AES_GCM_init_aesni((byte*)aes->key, aes->rounds, iv, ivSz, aes->H, + AES_COUNTER(aes), AES_INITCTR(aes)); + RESTORE_VECTOR_REGISTERS(); + } +} + +/* Update the AES GCM for encryption with authentication data. + * + * Implementation uses AVX2, AVX1 or straight AES-NI optimized assembly code. + * + * @param [in, out] aes AES object. + * @param [in] a Buffer holding authentication data. + * @param [in] aSz Length of authentication data in bytes. + * @param [in] endA Whether no more authentication data is expected. + */ +static void AesGcmAadUpdate_aesni(Aes* aes, const byte* a, word32 aSz, int endA) +{ + word32 blocks; + int partial; + + if (aSz != 0 && a != NULL) { + /* Total count of AAD updated. */ + aes->aSz += aSz; + /* Check if we have unprocessed data. */ + if (aes->aOver > 0) { + /* Calculate amount we can use - fill up the block. */ + byte sz = AES_BLOCK_SIZE - aes->aOver; + if (sz > aSz) { + sz = aSz; + } + /* Copy extra into last GHASH block array and update count. */ + XMEMCPY(AES_LASTGBLOCK(aes) + aes->aOver, a, sz); + aes->aOver += sz; + if (aes->aOver == AES_BLOCK_SIZE) { + /* We have filled up the block and can process. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + else + #endif + { + AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + /* Reset count. */ + aes->aOver = 0; + } + /* Used up some data. */ + aSz -= sz; + a += sz; + } + + /* Calculate number of blocks of AAD and the leftover. */ + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + if (blocks > 0) { + /* GHASH full blocks now. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_aad_update_avx2(a, blocks * AES_BLOCK_SIZE, + AES_TAG(aes), aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_aad_update_avx1(a, blocks * AES_BLOCK_SIZE, + AES_TAG(aes), aes->H); + } + else + #endif + { + AES_GCM_aad_update_aesni(a, blocks * AES_BLOCK_SIZE, + AES_TAG(aes), aes->H); + } + /* Skip over to end of AAD blocks. */ + a += blocks * AES_BLOCK_SIZE; + } + if (partial != 0) { + /* Cache the partial block. */ + XMEMCPY(AES_LASTGBLOCK(aes), a, partial); + aes->aOver = (byte)partial; + } + } + if (endA && (aes->aOver > 0)) { + /* No more AAD coming and we have a partial block. */ + /* Fill the rest of the block with zeros. */ + XMEMSET(AES_LASTGBLOCK(aes) + aes->aOver, 0, + AES_BLOCK_SIZE - aes->aOver); + /* GHASH last AAD block. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H); + } + else + #endif + { + AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + /* Clear partial count for next time through. */ + aes->aOver = 0; + } +} + +/* Update the AES GCM for encryption with data and/or authentication data. + * + * Implementation uses AVX2, AVX1 or straight AES-NI optimized assembly code. + * + * @param [in, out] aes AES object. + * @param [out] c Buffer to hold cipher text. + * @param [in] p Buffer holding plaintext. + * @param [in] cSz Length of cipher text/plaintext in bytes. + * @param [in] a Buffer holding authentication data. + * @param [in] aSz Length of authentication data in bytes. + */ +static void AesGcmEncryptUpdate_aesni(Aes* aes, byte* c, const byte* p, + word32 cSz, const byte* a, word32 aSz) +{ + word32 blocks; + int partial; + + SAVE_VECTOR_REGISTERS(); + /* Hash in A, the Authentication Data */ + AesGcmAadUpdate_aesni(aes, a, aSz, (cSz > 0) && (c != NULL)); + + /* Encrypt plaintext and Hash in C, the Cipher text */ + if (cSz != 0 && c != NULL) { + /* Update count of cipher text we have hashed. */ + aes->cSz += cSz; + if (aes->cOver > 0) { + /* Calculate amount we can use - fill up the block. */ + byte sz = AES_BLOCK_SIZE - aes->cOver; + if (sz > cSz) { + sz = cSz; + } + /* Encrypt some of the plaintext. */ + xorbuf(AES_LASTGBLOCK(aes) + aes->cOver, p, sz); + XMEMCPY(c, AES_LASTGBLOCK(aes) + aes->cOver, sz); + /* Update count of unsed encrypted counter. */ + aes->cOver += sz; + if (aes->cOver == AES_BLOCK_SIZE) { + /* We have filled up the block and can process. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + else + #endif + { + AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + /* Reset count. */ + aes->cOver = 0; + } + /* Used up some data. */ + cSz -= sz; + p += sz; + c += sz; + } + + /* Calculate number of blocks of plaintext and the leftover. */ + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + if (blocks > 0) { + /* Encrypt and GHASH full blocks now. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_update_avx2((byte*)aes->key, aes->rounds, c, p, + blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H, + AES_COUNTER(aes)); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_update_avx1((byte*)aes->key, aes->rounds, c, p, + blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H, + AES_COUNTER(aes)); + } + else + #endif + { + AES_GCM_encrypt_update_aesni((byte*)aes->key, aes->rounds, c, p, + blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H, + AES_COUNTER(aes)); + } + /* Skip over to end of blocks. */ + p += blocks * AES_BLOCK_SIZE; + c += blocks * AES_BLOCK_SIZE; + } + if (partial != 0) { + /* Encrypt the counter - XOR in zeros as proxy for plaintext. */ + XMEMSET(AES_LASTGBLOCK(aes), 0, AES_BLOCK_SIZE); + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_block_avx2((byte*)aes->key, aes->rounds, + AES_LASTGBLOCK(aes), AES_LASTGBLOCK(aes), AES_COUNTER(aes)); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_block_avx1((byte*)aes->key, aes->rounds, + AES_LASTGBLOCK(aes), AES_LASTGBLOCK(aes), AES_COUNTER(aes)); + } + else + #endif + { + AES_GCM_encrypt_block_aesni((byte*)aes->key, aes->rounds, + AES_LASTGBLOCK(aes), AES_LASTGBLOCK(aes), AES_COUNTER(aes)); + } + /* XOR the remaining plaintext to calculate cipher text. + * Keep cipher text for GHASH of last partial block. + */ + xorbuf(AES_LASTGBLOCK(aes), p, partial); + XMEMCPY(c, AES_LASTGBLOCK(aes), partial); + /* Update count of the block used. */ + aes->cOver = (byte)partial; + } + } + RESTORE_VECTOR_REGISTERS(); +} + +/* Finalize the AES GCM for encryption and calculate the authentication tag. + * + * Calls AVX2, AVX1 or straight AES-NI optimized assembly code. + * + * @param [in, out] aes AES object. + * @param [in] authTag Buffer to hold authentication tag. + * @param [in] authTagSz Length of authentication tag in bytes. + * @return 0 on success. + */ +static void AesGcmEncryptFinal_aesni(Aes* aes, byte* authTag, word32 authTagSz) +{ + /* AAD block incomplete when > 0 */ + byte over = aes->aOver; + + SAVE_VECTOR_REGISTERS(); + if (aes->cOver > 0) { + /* Cipher text block incomplete. */ + over = aes->cOver; + } + if (over > 0) { + /* Fill the rest of the block with zeros. */ + XMEMSET(AES_LASTGBLOCK(aes) + over, 0, AES_BLOCK_SIZE - over); + /* GHASH last cipher block. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H); + } + else + #endif + { + AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes), + aes->H); + } + } + /* Calculate the authentication tag. */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_final_avx2(AES_TAG(aes), authTag, authTagSz, aes->cSz, + aes->aSz, aes->H, AES_INITCTR(aes)); + } + else +#endif +#ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_final_avx1(AES_TAG(aes), authTag, authTagSz, aes->cSz, + aes->aSz, aes->H, AES_INITCTR(aes)); + } + else +#endif + { + AES_GCM_encrypt_final_aesni(AES_TAG(aes), authTag, authTagSz, aes->cSz, + aes->aSz, aes->H, AES_INITCTR(aes)); + } + RESTORE_VECTOR_REGISTERS(); +} + +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +/* Assembly code implementations in: aes_gcm_asm.S */ +#ifdef HAVE_INTEL_AVX2 +extern void AES_GCM_decrypt_update_avx2(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned int nbytes, + unsigned char* tag, unsigned char* h, unsigned char* counter); +extern void AES_GCM_decrypt_final_avx2(unsigned char* tag, + const unsigned char* authTag, unsigned int tbytes, unsigned int nbytes, + unsigned int abytes, unsigned char* h, unsigned char* initCtr, int* res); +#endif +#ifdef HAVE_INTEL_AVX1 +extern void AES_GCM_decrypt_update_avx1(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned int nbytes, + unsigned char* tag, unsigned char* h, unsigned char* counter); +extern void AES_GCM_decrypt_final_avx1(unsigned char* tag, + const unsigned char* authTag, unsigned int tbytes, unsigned int nbytes, + unsigned int abytes, unsigned char* h, unsigned char* initCtr, int* res); +#endif +extern void AES_GCM_decrypt_update_aesni(const unsigned char* key, int nr, + unsigned char* out, const unsigned char* in, unsigned int nbytes, + unsigned char* tag, unsigned char* h, unsigned char* counter); +extern void AES_GCM_decrypt_final_aesni(unsigned char* tag, + const unsigned char* authTag, unsigned int tbytes, unsigned int nbytes, + unsigned int abytes, unsigned char* h, unsigned char* initCtr, int* res); + +/* Update the AES GCM for decryption with data and/or authentication data. + * + * @param [in, out] aes AES object. + * @param [out] p Buffer to hold plaintext. + * @param [in] c Buffer holding ciper text. + * @param [in] cSz Length of cipher text/plaintext in bytes. + * @param [in] a Buffer holding authentication data. + * @param [in] aSz Length of authentication data in bytes. + */ +static void AesGcmDecryptUpdate_aesni(Aes* aes, byte* p, const byte* c, + word32 cSz, const byte* a, word32 aSz) +{ + word32 blocks; + int partial; + + SAVE_VECTOR_REGISTERS(); + /* Hash in A, the Authentication Data */ + AesGcmAadUpdate_aesni(aes, a, aSz, (cSz > 0) && (c != NULL)); + + /* Hash in C, the Cipher text, and decrypt. */ + if (cSz != 0 && p != NULL) { + /* Update count of cipher text we have hashed. */ + aes->cSz += cSz; + if (aes->cOver > 0) { + /* Calculate amount we can use - fill up the block. */ + byte sz = AES_BLOCK_SIZE - aes->cOver; + if (sz > cSz) { + sz = cSz; + } + /* Keep a copy of the cipher text for GHASH. */ + XMEMCPY(AES_LASTBLOCK(aes) + aes->cOver, c, sz); + /* Decrypt some of the cipher text. */ + xorbuf(AES_LASTGBLOCK(aes) + aes->cOver, c, sz); + XMEMCPY(p, AES_LASTGBLOCK(aes) + aes->cOver, sz); + /* Update count of unsed encrypted counter. */ + aes->cOver += sz; + if (aes->cOver == AES_BLOCK_SIZE) { + /* We have filled up the block and can process. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_ghash_block_avx2(AES_LASTBLOCK(aes), AES_TAG(aes), + aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_ghash_block_avx1(AES_LASTBLOCK(aes), AES_TAG(aes), + aes->H); + } + else + #endif + { + AES_GCM_ghash_block_aesni(AES_LASTBLOCK(aes), AES_TAG(aes), + aes->H); + } + /* Reset count. */ + aes->cOver = 0; + } + /* Used up some data. */ + cSz -= sz; + c += sz; + p += sz; + } + + /* Calculate number of blocks of plaintext and the leftover. */ + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + if (blocks > 0) { + /* Decrypt and GHASH full blocks now. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_decrypt_update_avx2((byte*)aes->key, aes->rounds, p, c, + blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H, + AES_COUNTER(aes)); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_decrypt_update_avx1((byte*)aes->key, aes->rounds, p, c, + blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H, + AES_COUNTER(aes)); + } + else + #endif + { + AES_GCM_decrypt_update_aesni((byte*)aes->key, aes->rounds, p, c, + blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H, + AES_COUNTER(aes)); + } + /* Skip over to end of blocks. */ + c += blocks * AES_BLOCK_SIZE; + p += blocks * AES_BLOCK_SIZE; + } + if (partial != 0) { + /* Encrypt the counter - XOR in zeros as proxy for cipher text. */ + XMEMSET(AES_LASTGBLOCK(aes), 0, AES_BLOCK_SIZE); + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_block_avx2((byte*)aes->key, aes->rounds, + AES_LASTGBLOCK(aes), AES_LASTGBLOCK(aes), AES_COUNTER(aes)); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_block_avx1((byte*)aes->key, aes->rounds, + AES_LASTGBLOCK(aes), AES_LASTGBLOCK(aes), AES_COUNTER(aes)); + } + else + #endif + { + AES_GCM_encrypt_block_aesni((byte*)aes->key, aes->rounds, + AES_LASTGBLOCK(aes), AES_LASTGBLOCK(aes), AES_COUNTER(aes)); + } + /* Keep cipher text for GHASH of last partial block. */ + XMEMCPY(AES_LASTBLOCK(aes), c, partial); + /* XOR the remaining cipher text to calculate plaintext. */ + xorbuf(AES_LASTGBLOCK(aes), c, partial); + XMEMCPY(p, AES_LASTGBLOCK(aes), partial); + /* Update count of the block used. */ + aes->cOver = (byte)partial; + } + } + RESTORE_VECTOR_REGISTERS(); +} + +/* Finalize the AES GCM for decryption and check the authentication tag. + * + * Calls AVX2, AVX1 or straight AES-NI optimized assembly code. + * + * @param [in, out] aes AES object. + * @param [in] authTag Buffer holding authentication tag. + * @param [in] authTagSz Length of authentication tag in bytes. + * @return 0 on success. + * @return AES_GCM_AUTH_E when authentication tag doesn't match calculated + * value. + */ +static int AesGcmDecryptFinal_aesni(Aes* aes, const byte* authTag, + word32 authTagSz) +{ + int ret = 0; + int res; + /* AAD block incomplete when > 0 */ + byte over = aes->aOver; + byte *lastBlock = AES_LASTGBLOCK(aes); + + SAVE_VECTOR_REGISTERS(); + if (aes->cOver > 0) { + /* Cipher text block incomplete. */ + over = aes->cOver; + lastBlock = AES_LASTBLOCK(aes); + } + if (over > 0) { + /* Zeroize the unused part of the block. */ + XMEMSET(lastBlock + over, 0, AES_BLOCK_SIZE - over); + /* Hash the last block of cipher text. */ + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_ghash_block_avx2(lastBlock, AES_TAG(aes), aes->H); + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_ghash_block_avx1(lastBlock, AES_TAG(aes), aes->H); + } + else + #endif + { + AES_GCM_ghash_block_aesni(lastBlock, AES_TAG(aes), aes->H); + } + } + /* Calculate and compare the authentication tag. */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_decrypt_final_avx2(AES_TAG(aes), authTag, authTagSz, aes->cSz, + aes->aSz, aes->H, AES_INITCTR(aes), &res); + } + else +#endif +#ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_decrypt_final_avx1(AES_TAG(aes), authTag, authTagSz, aes->cSz, + aes->aSz, aes->H, AES_INITCTR(aes), &res); + } + else +#endif + { + AES_GCM_decrypt_final_aesni(AES_TAG(aes), authTag, authTagSz, aes->cSz, + aes->aSz, aes->H, AES_INITCTR(aes), &res); + } + RESTORE_VECTOR_REGISTERS(); + /* Return error code when calculated doesn't match input. */ + if (res == 0) { + ret = AES_GCM_AUTH_E; + } + return ret; +} +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* WOLFSSL_AESNI */ + +/* Initialize an AES GCM cipher for encryption or decryption. + * + * Must call wc_AesInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [in] key Buffer holding key. + * @param [in] len Length of key in bytes. + * @param [in] iv Buffer holding IV/nonce. + * @param [in] ivSz Length of IV/nonce in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when aes is NULL, or a length is non-zero but buffer + * is NULL, or the IV is NULL and no previous IV has been set. + * @return MEMORY_E when dynamic memory allocation fails. (WOLFSSL_SMALL_STACK) + */ +int wc_AesGcmInit(Aes* aes, const byte* key, word32 len, const byte* iv, + word32 ivSz) +{ + int ret = 0; + + /* Check validity of parameters. */ + if ((aes == NULL) || ((len > 0) && (key == NULL)) || + ((ivSz == 0) && (iv != NULL)) || (ivSz > AES_BLOCK_SIZE) || + ((ivSz > 0) && (iv == NULL))) { + ret = BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_AESNI) + if ((ret == 0) && (aes->streamData == NULL)) { + /* Allocate buffers for streaming. */ + aes->streamData = (byte*)XMALLOC(5 * AES_BLOCK_SIZE, aes->heap, + DYNAMIC_TYPE_AES); + if (aes->streamData == NULL) { + ret = MEMORY_E; + } + } +#endif + + /* Set the key if passed in. */ + if ((ret == 0) && (key != NULL)) { + ret = wc_AesGcmSetKey(aes, key, len); + } + + if (ret == 0) { + /* Setup with IV if needed. */ + if (iv != NULL) { + /* Cache the IV in AES GCM object. */ + XMEMCPY((byte*)aes->reg, iv, ivSz); + aes->nonceSz = ivSz; + } + else if (aes->nonceSz != 0) { + /* Copy out the cached copy. */ + iv = (byte*)aes->reg; + ivSz = aes->nonceSz; + } + + if (iv != NULL) { + /* Initialize with the IV. */ + #ifdef WOLFSSL_AESNI + if (haveAESNI + #ifdef HAVE_INTEL_AVX2 + || IS_INTEL_AVX2(intel_flags) + #endif + #ifdef HAVE_INTEL_AVX1 + || IS_INTEL_AVX1(intel_flags) + #endif + ) { + AesGcmInit_aesni(aes, iv, ivSz); + } + else + #endif + { + AesGcmInit_C(aes, iv, ivSz); + } + + aes->nonceSet = 1; + } + } + + return ret; +} + +/* Initialize an AES GCM cipher for encryption. + * + * Must call wc_AesInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [in] key Buffer holding key. + * @param [in] len Length of key in bytes. + * @param [in] iv Buffer holding IV/nonce. + * @param [in] ivSz Length of IV/nonce in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when aes is NULL, or a length is non-zero but buffer + * is NULL, or the IV is NULL and no previous IV has been set. + */ +int wc_AesGcmEncryptInit(Aes* aes, const byte* key, word32 len, const byte* iv, + word32 ivSz) +{ + return wc_AesGcmInit(aes, key, len, iv, ivSz); +} + +/* Initialize an AES GCM cipher for encryption or decryption. Get IV. + * + * Must call wc_AesInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [in] key Buffer holding key. + * @param [in] len Length of key in bytes. + * @param [in] iv Buffer holding IV/nonce. + * @param [in] ivSz Length of IV/nonce in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when aes is NULL, or a length is non-zero but buffer + * is NULL, or the IV is NULL and no previous IV has been set. + */ +int wc_AesGcmEncryptInit_ex(Aes* aes, const byte* key, word32 len, byte* ivOut, + word32 ivOutSz) +{ + XMEMCPY(ivOut, aes->reg, ivOutSz); + return wc_AesGcmInit(aes, key, len, NULL, 0); +} + +/* Update the AES GCM for encryption with data and/or authentication data. + * + * All the AAD must be passed to update before the plaintext. + * Last part of AAD can be passed with first part of plaintext. + * + * Must set key and IV before calling this function. + * Must call wc_AesGcmInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [out] out Buffer to hold cipher text. + * @param [in] in Buffer holding plaintext. + * @param [in] sz Length of plaintext in bytes. + * @param [in] authIn Buffer holding authentication data. + * @param [in] authInSz Length of authentication data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when aes is NULL, or a length is non-zero but buffer + * is NULL. + */ +int wc_AesGcmEncryptUpdate(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + /* Check validity of parameters. */ + if ((aes == NULL) || ((authInSz > 0) && (authIn == NULL)) || ((sz > 0) && + ((out == NULL) || (in == NULL)))) { + ret = BAD_FUNC_ARG; + } + + /* Check key has been set. */ + if ((ret == 0) && (!aes->gcmKeySet)) { + ret = MISSING_KEY; + } + /* Check IV has been set. */ + if ((ret == 0) && (!aes->nonceSet)) { + ret = MISSING_IV; + } + + if ((ret == 0) && aes->ctrSet && (aes->aSz == 0) && (aes->cSz == 0)) { + aes->invokeCtr[0]++; + if (aes->invokeCtr[0] == 0) { + aes->invokeCtr[1]++; + if (aes->invokeCtr[1] == 0) + ret = AES_GCM_OVERFLOW_E; + } + } + + if (ret == 0) { + /* Encrypt with AAD and/or plaintext. */ + #if defined(WOLFSSL_AESNI) + if (haveAESNI + #ifdef HAVE_INTEL_AVX2 + || IS_INTEL_AVX2(intel_flags) + #endif + #ifdef HAVE_INTEL_AVX1 + || IS_INTEL_AVX1(intel_flags) + #endif + ) { + AesGcmEncryptUpdate_aesni(aes, out, in, sz, authIn, authInSz); + } + else + #endif + { + /* Encrypt the plaintext. */ + AesGcmCryptUpdate_C(aes, out, in, sz); + /* Update the authenication tag with any authentication data and the + * new cipher text. */ + GHASH_UPDATE(aes, authIn, authInSz, out, sz); + } + } + + return ret; +} + +/* Finalize the AES GCM for encryption and return the authentication tag. + * + * Must set key and IV before calling this function. + * Must call wc_AesGcmInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [out] authTag Buffer to hold authentication tag. + * @param [in] authTagSz Length of authentication tag in bytes. + * @return 0 on success. + */ +int wc_AesGcmEncryptFinal(Aes* aes, byte* authTag, word32 authTagSz) +{ + int ret = 0; + + /* Check validity of parameters. */ + if ((aes == NULL) || (authTag == NULL) || (authTagSz > AES_BLOCK_SIZE) || + (authTagSz == 0)) { + ret = BAD_FUNC_ARG; + } + + /* Check key has been set. */ + if ((ret == 0) && (!aes->gcmKeySet)) { + ret = MISSING_KEY; + } + /* Check IV has been set. */ + if ((ret == 0) && (!aes->nonceSet)) { + ret = MISSING_IV; + } + + if (ret == 0) { + /* Calculate authentication tag. */ + #ifdef WOLFSSL_AESNI + if (haveAESNI + #ifdef HAVE_INTEL_AVX2 + || IS_INTEL_AVX2(intel_flags) + #endif + #ifdef HAVE_INTEL_AVX1 + || IS_INTEL_AVX1(intel_flags) + #endif + ) { + AesGcmEncryptFinal_aesni(aes, authTag, authTagSz); + } + else + #endif + { + AesGcmFinal_C(aes, authTag, authTagSz); + } + } + + if ((ret == 0) && aes->ctrSet) { + IncCtr((byte*)aes->reg, aes->nonceSz); + } + + return ret; +} + +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +/* Initialize an AES GCM cipher for decryption. + * + * Must call wc_AesInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [in] key Buffer holding key. + * @param [in] len Length of key in bytes. + * @param [in] iv Buffer holding IV/nonce. + * @param [in] ivSz Length of IV/nonce in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when aes is NULL, or a length is non-zero but buffer + * is NULL, or the IV is NULL and no previous IV has been set. + */ +int wc_AesGcmDecryptInit(Aes* aes, const byte* key, word32 len, const byte* iv, + word32 ivSz) +{ + return wc_AesGcmInit(aes, key, len, iv, ivSz); +} + +/* Update the AES GCM for decryption with data and/or authentication data. + * + * All the AAD must be passed to update before the cipher text. + * Last part of AAD can be passed with first part of cipher text. + * + * Must set key and IV before calling this function. + * Must call wc_AesGcmInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [out] out Buffer to hold plaintext. + * @param [in] in Buffer holding cipher text. + * @param [in] sz Length of cipher text in bytes. + * @param [in] authIn Buffer holding authentication data. + * @param [in] authInSz Length of authentication data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when aes is NULL, or a length is non-zero but buffer + * is NULL. + */ +int wc_AesGcmDecryptUpdate(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + /* Check validity of parameters. */ + if ((aes == NULL) || ((authInSz > 0) && (authIn == NULL)) || ((sz > 0) && + ((out == NULL) || (in == NULL)))) { + ret = BAD_FUNC_ARG; + } + + /* Check key has been set. */ + if ((ret == 0) && (!aes->gcmKeySet)) { + ret = MISSING_KEY; + } + /* Check IV has been set. */ + if ((ret == 0) && (!aes->nonceSet)) { + ret = MISSING_IV; + } + + if (ret == 0) { + /* Decrypt with AAD and/or cipher text. */ + #if defined(WOLFSSL_AESNI) + if (haveAESNI + #ifdef HAVE_INTEL_AVX2 + || IS_INTEL_AVX2(intel_flags) + #endif + #ifdef HAVE_INTEL_AVX1 + || IS_INTEL_AVX1(intel_flags) + #endif + ) { + AesGcmDecryptUpdate_aesni(aes, out, in, sz, authIn, authInSz); + } + else + #endif + { + /* Update the authenication tag with any authentication data and + * cipher text. */ + GHASH_UPDATE(aes, authIn, authInSz, in, sz); + /* Decrypt the cipher text. */ + AesGcmCryptUpdate_C(aes, out, in, sz); + } + } + + return ret; +} + +/* Finalize the AES GCM for decryption and check the authentication tag. + * + * Must set key and IV before calling this function. + * Must call wc_AesGcmInit() before calling this function. + * + * @param [in, out] aes AES object. + * @param [in] authTag Buffer holding authentication tag. + * @param [in] authTagSz Length of authentication tag in bytes. + * @return 0 on success. + */ +int wc_AesGcmDecryptFinal(Aes* aes, const byte* authTag, word32 authTagSz) +{ + int ret = 0; + + /* Check validity of parameters. */ + if ((aes == NULL) || (authTag == NULL) || (authTagSz > AES_BLOCK_SIZE) || + (authTagSz == 0)) { + ret = BAD_FUNC_ARG; + } + + /* Check key has been set. */ + if ((ret == 0) && (!aes->gcmKeySet)) { + ret = MISSING_KEY; + } + /* Check IV has been set. */ + if ((ret == 0) && (!aes->nonceSet)) { + ret = MISSING_IV; + } + + if (ret == 0) { + /* Calculate authentication tag and compare with one passed in.. */ + #ifdef WOLFSSL_AESNI + if (haveAESNI + #ifdef HAVE_INTEL_AVX2 + || IS_INTEL_AVX2(intel_flags) + #endif + #ifdef HAVE_INTEL_AVX1 + || IS_INTEL_AVX1(intel_flags) + #endif + ) { + ret = AesGcmDecryptFinal_aesni(aes, authTag, authTagSz); + } + else + #endif + { + ALIGN32 byte calcTag[AES_BLOCK_SIZE]; + /* Calculate authentication tag. */ + AesGcmFinal_C(aes, calcTag, authTagSz); + /* Check calculated tag matches the one passed in. */ + if (ConstantCompare(authTag, calcTag, authTagSz) != 0) { + ret = AES_GCM_AUTH_E; + } + } + } + + return ret; +} +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* WOLFSSL_AESGCM_STREAM */ #endif /* WOLFSSL_XILINX_CRYPT */ #endif /* end of block for AESGCM implementation selection */ @@ -7406,6 +9098,9 @@ int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz) * counter to 32-bits. (SP 800-38D 8.3) */ aes->invokeCtr[0] = 0; aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + #ifdef WOLFSSL_AESGCM_STREAM + aes->ctrSet = 1; + #endif aes->nonceSz = ivSz; } @@ -7443,6 +9138,9 @@ int wc_AesGcmSetIV(Aes* aes, word32 ivSz, * counter to 32-bits. (SP 800-38D 8.3) */ aes->invokeCtr[0] = 0; aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + #ifdef WOLFSSL_AESGCM_STREAM + aes->ctrSet = 1; + #endif aes->nonceSz = ivSz; } @@ -7632,7 +9330,8 @@ int wc_AesCcmCheckTagSize(int sz) #elif defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-CCM mode" -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \ + !defined(WOLFSSL_QNX_CAAM) /* implemented in wolfcrypt/src/port/caam_aes.c */ #elif defined(WOLFSSL_SILABS_SE_ACCEL) @@ -7728,7 +9427,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, if (status != 0) { return status; } - + status = wolfSSL_CryptHwMutexLock(); if (status != 0) return status; @@ -8204,6 +9903,18 @@ int wc_AesInit(Aes* aes, void* heap, int devId) aes->aadLen = 0; #endif #endif + +#ifdef WOLFSSL_AESGCM_STREAM +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_AESNI) + aes->streamData = NULL; +#endif + aes->keylen = 0; + aes->nonceSz = 0; + aes->gcmKeySet = 0; + aes->nonceSet = 0; + aes->ctrSet = 0; +#endif + return ret; } @@ -8282,6 +9993,12 @@ void wc_AesFree(Aes* aes) #if defined(WOLFSSL_IMXRT_DCP) DCPAesFree(aes); #endif +#if defined(WOLFSSL_AESGCM_STREAM) && defined(WOLFSSL_SMALL_STACK) && \ + !defined(WOLFSSL_AESNI) + if (aes->streamData != NULL) { + XFREE(aes->streamData, aes->heap, DYNAMIC_TYPE_AES); + } +#endif } @@ -8323,7 +10040,8 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize) #endif /* !WOLFSSL_TI_CRYPT */ #ifdef HAVE_AES_ECB -#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \ + !defined(WOLFSSL_QNX_CAAM) /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ #elif defined(WOLFSSL_AFALG) @@ -8898,25 +10616,18 @@ static WC_INLINE void DecrementKeyWrapCounter(byte* inOutCtr) } } -/* perform AES key wrap (RFC3394), return out sz on success, negative on err */ -int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, - byte* out, word32 outSz, const byte* iv) +int wc_AesKeyWrap_ex(Aes *aes, const byte* in, word32 inSz, byte* out, + word32 outSz, const byte* iv) { -#ifdef WOLFSSL_SMALL_STACK - Aes *aes = NULL; -#else - Aes aes[1]; -#endif - int aes_inited = 0; - byte* r; word32 i; - int ret, j; + byte* r; + int j; byte t[KEYWRAP_BLOCK_SIZE]; byte tmp[AES_BLOCK_SIZE]; /* n must be at least 2, output size is n + 8 bytes */ - if (key == NULL || in == NULL || inSz < 2 || + if (aes == NULL || in == NULL || inSz < 2 || out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE)) return BAD_FUNC_ARG; @@ -8924,11 +10635,9 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, if (inSz % KEYWRAP_BLOCK_SIZE != 0) return BAD_FUNC_ARG; -#ifdef WOLFSSL_SMALL_STACK - if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL, - DYNAMIC_TYPE_AES)) == NULL) - return MEMORY_E; -#endif + r = out + 8; + XMEMCPY(r, in, inSz); + XMEMSET(t, 0, sizeof(t)); /* user IV is optional */ if (iv == NULL) { @@ -8937,23 +10646,8 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE); } - r = out + 8; - XMEMCPY(r, in, inSz); - XMEMSET(t, 0, sizeof(t)); - - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) - goto out; - else - aes_inited = 1; - - ret = wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION); - if (ret != 0) - goto out; - for (j = 0; j <= 5; j++) { for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) { - /* load R[i] */ XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE); @@ -8973,35 +10667,59 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, /* C[0] = A */ XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE); - ret = 0; - - out: - - if (aes_inited) - wc_AesFree(aes); -#ifdef WOLFSSL_SMALL_STACK - if (aes) - XFREE(aes, NULL, DYNAMIC_TYPE_AES); -#endif - - if (ret != 0) - return ret; - else - return inSz + KEYWRAP_BLOCK_SIZE; + return inSz + KEYWRAP_BLOCK_SIZE; } -int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, - byte* out, word32 outSz, const byte* iv) +/* perform AES key wrap (RFC3394), return out sz on success, negative on err */ +int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv) { #ifdef WOLFSSL_SMALL_STACK Aes *aes = NULL; #else Aes aes[1]; #endif - int aes_inited = 0; + int ret; + + /* n must be at least 2, output size is n + 8 bytes */ + if (key == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL, + DYNAMIC_TYPE_AES)) == NULL) + return MEMORY_E; +#endif + + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) + goto out; + + ret = wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION); + if (ret != 0) { + wc_AesFree(aes); + goto out; + } + + ret = wc_AesKeyWrap_ex(aes, in, inSz, out, outSz, iv); + + wc_AesFree(aes); + + out: +#ifdef WOLFSSL_SMALL_STACK + if (aes != NULL) + XFREE(aes, NULL, DYNAMIC_TYPE_AES); +#endif + + return ret; +} + +int wc_AesKeyUnWrap_ex(Aes *aes, const byte* in, word32 inSz, byte* out, + word32 outSz, const byte* iv) +{ byte* r; word32 i, n; - int ret, j; + int j; byte t[KEYWRAP_BLOCK_SIZE]; byte tmp[AES_BLOCK_SIZE]; @@ -9011,9 +10729,7 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; - (void)iv; - - if (key == NULL || in == NULL || inSz < 3 || + if (aes == NULL || in == NULL || inSz < 3 || out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE)) return BAD_FUNC_ARG; @@ -9021,34 +10737,17 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, if (inSz % KEYWRAP_BLOCK_SIZE != 0) return BAD_FUNC_ARG; -#ifdef WOLFSSL_SMALL_STACK - if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL, - DYNAMIC_TYPE_AES)) == NULL) - return MEMORY_E; -#endif - /* user IV optional */ - if (iv != NULL) { + if (iv != NULL) expIv = iv; - } else { + else expIv = defaultIV; - } /* A = C[0], R[i] = C[i] */ XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE); XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE); XMEMSET(t, 0, sizeof(t)); - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) - goto out; - else - aes_inited = 1; - - ret = wc_AesSetKey(aes, key, keySz, NULL, AES_DECRYPTION); - if (ret != 0) - goto out; - /* initialize counter to 6n */ n = (inSz - 1) / KEYWRAP_BLOCK_SIZE; InitKeyWrapCounter(t, 6 * n); @@ -9071,24 +10770,55 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, } /* verify IV */ - if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0) { - ret = BAD_KEYWRAP_IV_E; + if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0) + return BAD_KEYWRAP_IV_E; + + return inSz - KEYWRAP_BLOCK_SIZE; +} + +int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv) +{ +#ifdef WOLFSSL_SMALL_STACK + Aes *aes = NULL; +#else + Aes aes[1]; +#endif + int ret; + + (void)iv; + + if (key == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL, + DYNAMIC_TYPE_AES)) == NULL) + return MEMORY_E; +#endif + + + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) + goto out; + + ret = wc_AesSetKey(aes, key, keySz, NULL, AES_DECRYPTION); + if (ret != 0) { + wc_AesFree(aes); goto out; } - out: + ret = wc_AesKeyUnWrap_ex(aes, in, inSz, out, outSz, iv); - if (aes_inited) - wc_AesFree(aes); + wc_AesFree(aes); + + out: #ifdef WOLFSSL_SMALL_STACK if (aes) XFREE(aes, NULL, DYNAMIC_TYPE_AES); #endif - if (ret != 0) - return ret; - else - return inSz - KEYWRAP_BLOCK_SIZE; + return ret; } #endif /* HAVE_AES_KEYWRAP */ diff --git a/wolfcrypt/src/aes_asm.S b/wolfcrypt/src/aes_asm.S index ae1c801d6..9a31cb6c0 100644 --- a/wolfcrypt/src/aes_asm.S +++ b/wolfcrypt/src/aes_asm.S @@ -1,6 +1,6 @@ /* aes_asm.S * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/aes_asm.asm b/wolfcrypt/src/aes_asm.asm index b3cc94d9e..8f071b352 100644 --- a/wolfcrypt/src/aes_asm.asm +++ b/wolfcrypt/src/aes_asm.asm @@ -1,6 +1,6 @@ ; /* aes_asm.asm ; * -; * Copyright (C) 2006-2020 wolfSSL Inc. +; * Copyright (C) 2006-2021 wolfSSL Inc. ; * ; * This file is part of wolfSSL. ; * @@ -19,6 +19,7 @@ ; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA ; */ + ; ; ; /* See Intel Advanced Encryption Standard (AES) Instructions Set White Paper diff --git a/wolfcrypt/src/aes_gcm_asm.S b/wolfcrypt/src/aes_gcm_asm.S index 035de515a..1a1641056 100644 --- a/wolfcrypt/src/aes_gcm_asm.S +++ b/wolfcrypt/src/aes_gcm_asm.S @@ -1,6 +1,6 @@ /* aes_gcm_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -3418,6 +3418,2778 @@ L_AES_GCM_decrypt_cmp_tag_done: #ifndef __APPLE__ .size AES_GCM_decrypt,.-AES_GCM_decrypt #endif /* __APPLE__ */ +#ifdef WOLFSSL_AESGCM_STREAM +#ifndef __APPLE__ +.text +.globl AES_GCM_init_aesni +.type AES_GCM_init_aesni,@function +.align 16 +AES_GCM_init_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_init_aesni +.p2align 4 +_AES_GCM_init_aesni: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + movq %rdx, %r10 + movl %ecx, %r11d + movq 32(%rsp), %rax + subq $16, %rsp + pxor %xmm4, %xmm4 + movl %r11d, %edx + cmpl $12, %edx + jne L_AES_GCM_init_aesni_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + pinsrq $0x00, (%r10), %xmm4 + pinsrd $2, 8(%r10), %xmm4 + pinsrd $3, %ecx, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + movdqa %xmm4, %xmm1 + movdqa (%rdi), %xmm5 + pxor %xmm5, %xmm1 + movdqa 16(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 32(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 48(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 64(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 80(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 96(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 112(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 128(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 144(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $11, %esi + movdqa 160(%rdi), %xmm7 + jl L_AES_GCM_init_aesni_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 176(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $13, %esi + movdqa 192(%rdi), %xmm7 + jl L_AES_GCM_init_aesni_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 208(%rdi), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 224(%rdi), %xmm7 +L_AES_GCM_init_aesni_calc_iv_12_last: + aesenclast %xmm7, %xmm5 + aesenclast %xmm7, %xmm1 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + movdqa %xmm1, %xmm15 + jmp L_AES_GCM_init_aesni_iv_done +L_AES_GCM_init_aesni_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + movdqa (%rdi), %xmm5 + aesenc 16(%rdi), %xmm5 + aesenc 32(%rdi), %xmm5 + aesenc 48(%rdi), %xmm5 + aesenc 64(%rdi), %xmm5 + aesenc 80(%rdi), %xmm5 + aesenc 96(%rdi), %xmm5 + aesenc 112(%rdi), %xmm5 + aesenc 128(%rdi), %xmm5 + aesenc 144(%rdi), %xmm5 + cmpl $11, %esi + movdqa 160(%rdi), %xmm9 + jl L_AES_GCM_init_aesni_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 176(%rdi), %xmm5 + cmpl $13, %esi + movdqa 192(%rdi), %xmm9 + jl L_AES_GCM_init_aesni_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 208(%rdi), %xmm5 + movdqa 224(%rdi), %xmm9 +L_AES_GCM_init_aesni_calc_iv_1_aesenc_avx_last: + aesenclast %xmm9, %xmm5 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_init_aesni_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_init_aesni_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_init_aesni_calc_iv_16_loop: + movdqu (%r10,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_init_aesni_calc_iv_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_init_aesni_calc_iv_done +L_AES_GCM_init_aesni_calc_iv_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %r13d, %r13d + movdqa %xmm8, (%rsp) +L_AES_GCM_init_aesni_calc_iv_loop: + movzbl (%r10,%rcx,1), %r12d + movb %r12b, (%rsp,%r13,1) + incl %ecx + incl %r13d + cmpl %edx, %ecx + jl L_AES_GCM_init_aesni_calc_iv_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 +L_AES_GCM_init_aesni_calc_iv_done: + # T = Encrypt counter + pxor %xmm0, %xmm0 + shll $3, %edx + pinsrq $0x00, %rdx, %xmm0 + pxor %xmm0, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + # Encrypt counter + movdqa (%rdi), %xmm8 + pxor %xmm4, %xmm8 + aesenc 16(%rdi), %xmm8 + aesenc 32(%rdi), %xmm8 + aesenc 48(%rdi), %xmm8 + aesenc 64(%rdi), %xmm8 + aesenc 80(%rdi), %xmm8 + aesenc 96(%rdi), %xmm8 + aesenc 112(%rdi), %xmm8 + aesenc 128(%rdi), %xmm8 + aesenc 144(%rdi), %xmm8 + cmpl $11, %esi + movdqa 160(%rdi), %xmm9 + jl L_AES_GCM_init_aesni_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%rdi), %xmm8 + cmpl $13, %esi + movdqa 192(%rdi), %xmm9 + jl L_AES_GCM_init_aesni_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%rdi), %xmm8 + movdqa 224(%rdi), %xmm9 +L_AES_GCM_init_aesni_calc_iv_2_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqa %xmm8, %xmm15 +L_AES_GCM_init_aesni_iv_done: + movdqa %xmm15, (%rax) + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + paddd L_aes_gcm_one(%rip), %xmm4 + movdqa %xmm5, (%r8) + movdqa %xmm4, (%r9) + addq $16, %rsp + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size AES_GCM_init_aesni,.-AES_GCM_init_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_aad_update_aesni +.type AES_GCM_aad_update_aesni,@function +.align 16 +AES_GCM_aad_update_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_aad_update_aesni +.p2align 4 +_AES_GCM_aad_update_aesni: +#endif /* __APPLE__ */ + movq %rcx, %rax + movdqa (%rdx), %xmm5 + movdqa (%rax), %xmm6 + xorl %ecx, %ecx +L_AES_GCM_aad_update_aesni_16_loop: + movdqu (%rdi,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm5 + pshufd $0x4e, %xmm5, %xmm1 + pshufd $0x4e, %xmm6, %xmm2 + movdqa %xmm6, %xmm3 + movdqa %xmm6, %xmm0 + pclmulqdq $0x11, %xmm5, %xmm3 + pclmulqdq $0x00, %xmm5, %xmm0 + pxor %xmm5, %xmm1 + pxor %xmm6, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm4 + movdqa %xmm3, %xmm5 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm5 + movdqa %xmm4, %xmm0 + movdqa %xmm5, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm4 + pslld $0x01, %xmm5 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm5 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + movdqa %xmm4, %xmm0 + movdqa %xmm4, %xmm1 + movdqa %xmm4, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm4 + movdqa %xmm4, %xmm2 + movdqa %xmm4, %xmm3 + movdqa %xmm4, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm4, %xmm2 + pxor %xmm2, %xmm5 + addl $16, %ecx + cmpl %esi, %ecx + jl L_AES_GCM_aad_update_aesni_16_loop + movdqa %xmm5, (%rdx) + repz retq +#ifndef __APPLE__ +.size AES_GCM_aad_update_aesni,.-AES_GCM_aad_update_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_block_aesni +.type AES_GCM_encrypt_block_aesni,@function +.align 16 +AES_GCM_encrypt_block_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_block_aesni +.p2align 4 +_AES_GCM_encrypt_block_aesni: +#endif /* __APPLE__ */ + movq %rdx, %r10 + movq %rcx, %r11 + movdqa (%r8), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%rdi), %xmm8 + movdqa %xmm9, (%r8) + aesenc 16(%rdi), %xmm8 + aesenc 32(%rdi), %xmm8 + aesenc 48(%rdi), %xmm8 + aesenc 64(%rdi), %xmm8 + aesenc 80(%rdi), %xmm8 + aesenc 96(%rdi), %xmm8 + aesenc 112(%rdi), %xmm8 + aesenc 128(%rdi), %xmm8 + aesenc 144(%rdi), %xmm8 + cmpl $11, %esi + movdqa 160(%rdi), %xmm9 + jl L_AES_GCM_encrypt_block_aesni_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%rdi), %xmm8 + cmpl $13, %esi + movdqa 192(%rdi), %xmm9 + jl L_AES_GCM_encrypt_block_aesni_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%rdi), %xmm8 + movdqa 224(%rdi), %xmm9 +L_AES_GCM_encrypt_block_aesni_aesenc_block_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqu (%r11), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%r10) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_block_aesni,.-AES_GCM_encrypt_block_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_ghash_block_aesni +.type AES_GCM_ghash_block_aesni,@function +.align 16 +AES_GCM_ghash_block_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_ghash_block_aesni +.p2align 4 +_AES_GCM_ghash_block_aesni: +#endif /* __APPLE__ */ + movdqa (%rsi), %xmm4 + movdqa (%rdx), %xmm5 + movdqu (%rdi), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm6 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm6 + pxor %xmm1, %xmm4 + movdqa %xmm6, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm6 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm6 + por %xmm1, %xmm4 + movdqa %xmm6, %xmm0 + movdqa %xmm6, %xmm1 + movdqa %xmm6, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm6 + movdqa %xmm6, %xmm2 + movdqa %xmm6, %xmm3 + movdqa %xmm6, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm6, %xmm2 + pxor %xmm2, %xmm4 + movdqa %xmm4, (%rsi) + repz retq +#ifndef __APPLE__ +.size AES_GCM_ghash_block_aesni,.-AES_GCM_ghash_block_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_update_aesni +.type AES_GCM_encrypt_update_aesni,@function +.align 16 +AES_GCM_encrypt_update_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_update_aesni +.p2align 4 +_AES_GCM_encrypt_update_aesni: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + movq %rdx, %r10 + movq %rcx, %r11 + movq 32(%rsp), %rax + movq 40(%rsp), %r12 + subq $0xa0, %rsp + movdqa (%r9), %xmm6 + movdqa (%rax), %xmm5 + movdqa %xmm5, %xmm9 + movdqa %xmm5, %xmm8 + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + xorq %r14, %r14 + cmpl $0x80, %r8d + movl %r8d, %r13d + jl L_AES_GCM_encrypt_update_aesni_done_128 + andl $0xffffff80, %r13d + movdqa %xmm6, %xmm2 + # H ^ 1 + movdqa %xmm5, (%rsp) + # H ^ 2 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm5, %xmm10 + movdqa %xmm5, %xmm11 + movdqa %xmm5, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm5, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm0 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm0 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm0 + movdqa %xmm0, 16(%rsp) + # H ^ 3 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm1 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm1 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm1 + movdqa %xmm1, 32(%rsp) + # H ^ 4 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm3 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm3 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm3 + movdqa %xmm3, 48(%rsp) + # H ^ 5 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 64(%rsp) + # H ^ 6 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 80(%rsp) + # H ^ 7 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 96(%rsp) + # H ^ 8 + pshufd $0x4e, %xmm3, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm3, %xmm11 + pclmulqdq $0x00, %xmm3, %xmm8 + pxor %xmm3, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 112(%rsp) + # First 128 bytes of input + movdqa (%r12), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%rdi), %xmm7 + movdqa %xmm0, (%r12) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 16(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 32(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 48(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 64(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 80(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 96(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 112(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 128(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 144(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $11, %esi + movdqa 160(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_aesni_enc_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %esi + movdqa 192(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_aesni_enc_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%rdi), %xmm7 +L_AES_GCM_encrypt_update_aesni_enc_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%r11), %xmm0 + movdqu 16(%r11), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%r10) + movdqu %xmm9, 16(%r10) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%r11), %xmm0 + movdqu 48(%r11), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%r10) + movdqu %xmm11, 48(%r10) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%r11), %xmm0 + movdqu 80(%r11), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%r10) + movdqu %xmm13, 80(%r10) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%r11), %xmm0 + movdqu 112(%r11), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%r10) + movdqu %xmm15, 112(%r10) + cmpl $0x80, %r13d + movl $0x80, %r14d + jle L_AES_GCM_encrypt_update_aesni_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_update_aesni_ghash_128: + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + movdqa (%r12), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%rdi), %xmm7 + movdqa %xmm0, (%r12) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 112(%rsp), %xmm7 + movdqu -128(%rdx), %xmm0 + aesenc 16(%rdi), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + pxor %xmm2, %xmm0 + pshufd $0x4e, %xmm7, %xmm1 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm7, %xmm1 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm3 + pclmulqdq $0x11, %xmm7, %xmm3 + aesenc 16(%rdi), %xmm9 + aesenc 16(%rdi), %xmm10 + movdqa %xmm0, %xmm2 + pclmulqdq $0x00, %xmm7, %xmm2 + aesenc 16(%rdi), %xmm11 + aesenc 16(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm1 + aesenc 16(%rdi), %xmm13 + aesenc 16(%rdi), %xmm14 + aesenc 16(%rdi), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm3, %xmm1 + movdqa 96(%rsp), %xmm7 + movdqu -112(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 32(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 32(%rdi), %xmm9 + aesenc 32(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 32(%rdi), %xmm11 + aesenc 32(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 32(%rdi), %xmm13 + aesenc 32(%rdi), %xmm14 + aesenc 32(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 80(%rsp), %xmm7 + movdqu -96(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 48(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 48(%rdi), %xmm9 + aesenc 48(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 48(%rdi), %xmm11 + aesenc 48(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 48(%rdi), %xmm13 + aesenc 48(%rdi), %xmm14 + aesenc 48(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 64(%rsp), %xmm7 + movdqu -80(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 64(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 64(%rdi), %xmm9 + aesenc 64(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 64(%rdi), %xmm11 + aesenc 64(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 64(%rdi), %xmm13 + aesenc 64(%rdi), %xmm14 + aesenc 64(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 48(%rsp), %xmm7 + movdqu -64(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 80(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 80(%rdi), %xmm9 + aesenc 80(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 80(%rdi), %xmm11 + aesenc 80(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 80(%rdi), %xmm13 + aesenc 80(%rdi), %xmm14 + aesenc 80(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 32(%rsp), %xmm7 + movdqu -48(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 96(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 96(%rdi), %xmm9 + aesenc 96(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 96(%rdi), %xmm11 + aesenc 96(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 96(%rdi), %xmm13 + aesenc 96(%rdi), %xmm14 + aesenc 96(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 16(%rsp), %xmm7 + movdqu -32(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 112(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 112(%rdi), %xmm9 + aesenc 112(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 112(%rdi), %xmm11 + aesenc 112(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 112(%rdi), %xmm13 + aesenc 112(%rdi), %xmm14 + aesenc 112(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa (%rsp), %xmm7 + movdqu -16(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 128(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 128(%rdi), %xmm9 + aesenc 128(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 128(%rdi), %xmm11 + aesenc 128(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 128(%rdi), %xmm13 + aesenc 128(%rdi), %xmm14 + aesenc 128(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa %xmm1, %xmm5 + psrldq $8, %xmm1 + pslldq $8, %xmm5 + aesenc 144(%rdi), %xmm8 + pxor %xmm5, %xmm2 + pxor %xmm1, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm4 + movdqa %xmm2, %xmm5 + aesenc 144(%rdi), %xmm9 + pslld $31, %xmm7 + pslld $30, %xmm4 + pslld $25, %xmm5 + aesenc 144(%rdi), %xmm10 + pxor %xmm4, %xmm7 + pxor %xmm5, %xmm7 + aesenc 144(%rdi), %xmm11 + movdqa %xmm7, %xmm4 + pslldq $12, %xmm7 + psrldq $4, %xmm4 + aesenc 144(%rdi), %xmm12 + pxor %xmm7, %xmm2 + movdqa %xmm2, %xmm5 + movdqa %xmm2, %xmm1 + movdqa %xmm2, %xmm0 + aesenc 144(%rdi), %xmm13 + psrld $0x01, %xmm5 + psrld $2, %xmm1 + psrld $7, %xmm0 + aesenc 144(%rdi), %xmm14 + pxor %xmm1, %xmm5 + pxor %xmm0, %xmm5 + aesenc 144(%rdi), %xmm15 + pxor %xmm4, %xmm5 + pxor %xmm5, %xmm2 + pxor %xmm3, %xmm2 + cmpl $11, %esi + movdqa 160(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_aesni_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %esi + movdqa 192(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_aesni_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%rdi), %xmm7 +L_AES_GCM_encrypt_update_aesni_aesenc_128_ghash_avx_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rcx), %xmm0 + movdqu 16(%rcx), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rdx) + movdqu %xmm9, 16(%rdx) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rcx), %xmm0 + movdqu 48(%rcx), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rdx) + movdqu %xmm11, 48(%rdx) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rcx), %xmm0 + movdqu 80(%rcx), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rdx) + movdqu %xmm13, 80(%rdx) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rcx), %xmm0 + movdqu 112(%rcx), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rdx) + movdqu %xmm15, 112(%rdx) + addl $0x80, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_encrypt_update_aesni_ghash_128 +L_AES_GCM_encrypt_update_aesni_end_128: + movdqa L_aes_gcm_bswap_mask(%rip), %xmm4 + pshufb %xmm4, %xmm8 + pshufb %xmm4, %xmm9 + pshufb %xmm4, %xmm10 + pshufb %xmm4, %xmm11 + pxor %xmm2, %xmm8 + pshufb %xmm4, %xmm12 + pshufb %xmm4, %xmm13 + pshufb %xmm4, %xmm14 + pshufb %xmm4, %xmm15 + movdqa 112(%rsp), %xmm7 + pshufd $0x4e, %xmm8, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm8, %xmm3 + pclmulqdq $0x00, %xmm8, %xmm0 + pxor %xmm8, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm4 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 96(%rsp), %xmm7 + pshufd $0x4e, %xmm9, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm9, %xmm3 + pclmulqdq $0x00, %xmm9, %xmm0 + pxor %xmm9, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 80(%rsp), %xmm7 + pshufd $0x4e, %xmm10, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm10, %xmm3 + pclmulqdq $0x00, %xmm10, %xmm0 + pxor %xmm10, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 64(%rsp), %xmm7 + pshufd $0x4e, %xmm11, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm11, %xmm3 + pclmulqdq $0x00, %xmm11, %xmm0 + pxor %xmm11, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 48(%rsp), %xmm7 + pshufd $0x4e, %xmm12, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm12, %xmm3 + pclmulqdq $0x00, %xmm12, %xmm0 + pxor %xmm12, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 32(%rsp), %xmm7 + pshufd $0x4e, %xmm13, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm13, %xmm3 + pclmulqdq $0x00, %xmm13, %xmm0 + pxor %xmm13, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 16(%rsp), %xmm7 + pshufd $0x4e, %xmm14, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm14, %xmm3 + pclmulqdq $0x00, %xmm14, %xmm0 + pxor %xmm14, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa (%rsp), %xmm7 + pshufd $0x4e, %xmm15, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm15, %xmm3 + pclmulqdq $0x00, %xmm15, %xmm0 + pxor %xmm15, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa %xmm4, %xmm0 + movdqa %xmm4, %xmm1 + movdqa %xmm4, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm4 + movdqa %xmm4, %xmm2 + movdqa %xmm4, %xmm3 + movdqa %xmm4, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm4, %xmm2 + pxor %xmm2, %xmm6 + movdqa (%rsp), %xmm5 +L_AES_GCM_encrypt_update_aesni_done_128: + movl %r8d, %edx + cmpl %edx, %r14d + jge L_AES_GCM_encrypt_update_aesni_done_enc + movl %r8d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %r14d + jge L_AES_GCM_encrypt_update_aesni_last_block_done + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + movdqa (%r12), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%rdi), %xmm8 + movdqa %xmm9, (%r12) + aesenc 16(%rdi), %xmm8 + aesenc 32(%rdi), %xmm8 + aesenc 48(%rdi), %xmm8 + aesenc 64(%rdi), %xmm8 + aesenc 80(%rdi), %xmm8 + aesenc 96(%rdi), %xmm8 + aesenc 112(%rdi), %xmm8 + aesenc 128(%rdi), %xmm8 + aesenc 144(%rdi), %xmm8 + cmpl $11, %esi + movdqa 160(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_aesni_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%rdi), %xmm8 + cmpl $13, %esi + movdqa 192(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_aesni_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%rdi), %xmm8 + movdqa 224(%rdi), %xmm9 +L_AES_GCM_encrypt_update_aesni_aesenc_block_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + addl $16, %r14d + cmpl %r13d, %r14d + jge L_AES_GCM_encrypt_update_aesni_last_block_ghash +L_AES_GCM_encrypt_update_aesni_last_block_start: + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + movdqa (%r12), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%rdi), %xmm8 + movdqa %xmm9, (%r12) + movdqa %xmm6, %xmm10 + pclmulqdq $16, %xmm5, %xmm10 + aesenc 16(%rdi), %xmm8 + aesenc 32(%rdi), %xmm8 + movdqa %xmm6, %xmm11 + pclmulqdq $0x01, %xmm5, %xmm11 + aesenc 48(%rdi), %xmm8 + aesenc 64(%rdi), %xmm8 + movdqa %xmm6, %xmm12 + pclmulqdq $0x00, %xmm5, %xmm12 + aesenc 80(%rdi), %xmm8 + movdqa %xmm6, %xmm1 + pclmulqdq $0x11, %xmm5, %xmm1 + aesenc 96(%rdi), %xmm8 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm2 + psrldq $8, %xmm10 + pslldq $8, %xmm2 + aesenc 112(%rdi), %xmm8 + movdqa %xmm1, %xmm3 + pxor %xmm12, %xmm2 + pxor %xmm10, %xmm3 + movdqa L_aes_gcm_mod2_128(%rip), %xmm0 + movdqa %xmm2, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 128(%rdi), %xmm8 + pshufd $0x4e, %xmm2, %xmm10 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 144(%rdi), %xmm8 + pshufd $0x4e, %xmm10, %xmm6 + pxor %xmm11, %xmm6 + pxor %xmm3, %xmm6 + cmpl $11, %esi + movdqa 160(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_aesni_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 176(%rdi), %xmm8 + cmpl $13, %esi + movdqa 192(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_aesni_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 208(%rdi), %xmm8 + movdqa 224(%rdi), %xmm9 +L_AES_GCM_encrypt_update_aesni_aesenc_gfmul_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + addl $16, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_encrypt_update_aesni_last_block_start +L_AES_GCM_encrypt_update_aesni_last_block_ghash: + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_encrypt_update_aesni_last_block_done: +L_AES_GCM_encrypt_update_aesni_done_enc: + movdqa %xmm6, (%r9) + addq $0xa0, %rsp + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_update_aesni,.-AES_GCM_encrypt_update_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_final_aesni +.type AES_GCM_encrypt_final_aesni,@function +.align 16 +AES_GCM_encrypt_final_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_final_aesni +.p2align 4 +_AES_GCM_encrypt_final_aesni: +#endif /* __APPLE__ */ + pushq %r13 + movq %rdx, %rax + movl %ecx, %r10d + movl %r8d, %r11d + movq 16(%rsp), %r8 + subq $16, %rsp + movdqa (%rdi), %xmm4 + movdqa (%r9), %xmm5 + movdqa (%r8), %xmm6 + movdqa %xmm5, %xmm9 + movdqa %xmm5, %xmm8 + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + movl %r10d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + pinsrq $0x00, %rdx, %xmm0 + pinsrq $0x01, %rcx, %xmm0 + pxor %xmm0, %xmm4 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm4, %xmm10 + movdqa %xmm4, %xmm11 + movdqa %xmm4, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm4, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm4 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm4 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + movdqa %xmm6, %xmm0 + pxor %xmm4, %xmm0 + cmpl $16, %eax + je L_AES_GCM_encrypt_final_aesni_store_tag_16 + xorq %rcx, %rcx + movdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_final_aesni_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%rsi,%rcx,1) + incl %ecx + cmpl %eax, %ecx + jne L_AES_GCM_encrypt_final_aesni_store_tag_loop + jmp L_AES_GCM_encrypt_final_aesni_store_tag_done +L_AES_GCM_encrypt_final_aesni_store_tag_16: + movdqu %xmm0, (%rsi) +L_AES_GCM_encrypt_final_aesni_store_tag_done: + addq $16, %rsp + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_final_aesni,.-AES_GCM_encrypt_final_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_update_aesni +.type AES_GCM_decrypt_update_aesni,@function +.align 16 +AES_GCM_decrypt_update_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_update_aesni +.p2align 4 +_AES_GCM_decrypt_update_aesni: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + pushq %r15 + movq %rdx, %r10 + movq %rcx, %r11 + movq 40(%rsp), %rax + movq 48(%rsp), %r12 + subq $0xa8, %rsp + movdqa (%r9), %xmm6 + movdqa (%rax), %xmm5 + movdqa %xmm5, %xmm9 + movdqa %xmm5, %xmm8 + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + xorl %r14d, %r14d + cmpl $0x80, %r8d + movl %r8d, %r13d + jl L_AES_GCM_decrypt_update_aesni_done_128 + andl $0xffffff80, %r13d + movdqa %xmm6, %xmm2 + # H ^ 1 + movdqa %xmm5, (%rsp) + # H ^ 2 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm5, %xmm10 + movdqa %xmm5, %xmm11 + movdqa %xmm5, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm5, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm0 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm0 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm0 + movdqa %xmm0, 16(%rsp) + # H ^ 3 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm1 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm1 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm1 + movdqa %xmm1, 32(%rsp) + # H ^ 4 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm3 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm3 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm3 + movdqa %xmm3, 48(%rsp) + # H ^ 5 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 64(%rsp) + # H ^ 6 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 80(%rsp) + # H ^ 7 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 96(%rsp) + # H ^ 8 + pshufd $0x4e, %xmm3, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm3, %xmm11 + pclmulqdq $0x00, %xmm3, %xmm8 + pxor %xmm3, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 112(%rsp) +L_AES_GCM_decrypt_update_aesni_ghash_128: + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + movdqa (%r12), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%rdi), %xmm7 + movdqa %xmm0, (%r12) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 112(%rsp), %xmm7 + movdqu (%rcx), %xmm0 + aesenc 16(%rdi), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + pxor %xmm2, %xmm0 + pshufd $0x4e, %xmm7, %xmm1 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm7, %xmm1 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm3 + pclmulqdq $0x11, %xmm7, %xmm3 + aesenc 16(%rdi), %xmm9 + aesenc 16(%rdi), %xmm10 + movdqa %xmm0, %xmm2 + pclmulqdq $0x00, %xmm7, %xmm2 + aesenc 16(%rdi), %xmm11 + aesenc 16(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm1 + aesenc 16(%rdi), %xmm13 + aesenc 16(%rdi), %xmm14 + aesenc 16(%rdi), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm3, %xmm1 + movdqa 96(%rsp), %xmm7 + movdqu 16(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 32(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 32(%rdi), %xmm9 + aesenc 32(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 32(%rdi), %xmm11 + aesenc 32(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 32(%rdi), %xmm13 + aesenc 32(%rdi), %xmm14 + aesenc 32(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 80(%rsp), %xmm7 + movdqu 32(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 48(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 48(%rdi), %xmm9 + aesenc 48(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 48(%rdi), %xmm11 + aesenc 48(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 48(%rdi), %xmm13 + aesenc 48(%rdi), %xmm14 + aesenc 48(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 64(%rsp), %xmm7 + movdqu 48(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 64(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 64(%rdi), %xmm9 + aesenc 64(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 64(%rdi), %xmm11 + aesenc 64(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 64(%rdi), %xmm13 + aesenc 64(%rdi), %xmm14 + aesenc 64(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 48(%rsp), %xmm7 + movdqu 64(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 80(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 80(%rdi), %xmm9 + aesenc 80(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 80(%rdi), %xmm11 + aesenc 80(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 80(%rdi), %xmm13 + aesenc 80(%rdi), %xmm14 + aesenc 80(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 32(%rsp), %xmm7 + movdqu 80(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 96(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 96(%rdi), %xmm9 + aesenc 96(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 96(%rdi), %xmm11 + aesenc 96(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 96(%rdi), %xmm13 + aesenc 96(%rdi), %xmm14 + aesenc 96(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 16(%rsp), %xmm7 + movdqu 96(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 112(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 112(%rdi), %xmm9 + aesenc 112(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 112(%rdi), %xmm11 + aesenc 112(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 112(%rdi), %xmm13 + aesenc 112(%rdi), %xmm14 + aesenc 112(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa (%rsp), %xmm7 + movdqu 112(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 128(%rdi), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 128(%rdi), %xmm9 + aesenc 128(%rdi), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 128(%rdi), %xmm11 + aesenc 128(%rdi), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 128(%rdi), %xmm13 + aesenc 128(%rdi), %xmm14 + aesenc 128(%rdi), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa %xmm1, %xmm5 + psrldq $8, %xmm1 + pslldq $8, %xmm5 + aesenc 144(%rdi), %xmm8 + pxor %xmm5, %xmm2 + pxor %xmm1, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm4 + movdqa %xmm2, %xmm5 + aesenc 144(%rdi), %xmm9 + pslld $31, %xmm7 + pslld $30, %xmm4 + pslld $25, %xmm5 + aesenc 144(%rdi), %xmm10 + pxor %xmm4, %xmm7 + pxor %xmm5, %xmm7 + aesenc 144(%rdi), %xmm11 + movdqa %xmm7, %xmm4 + pslldq $12, %xmm7 + psrldq $4, %xmm4 + aesenc 144(%rdi), %xmm12 + pxor %xmm7, %xmm2 + movdqa %xmm2, %xmm5 + movdqa %xmm2, %xmm1 + movdqa %xmm2, %xmm0 + aesenc 144(%rdi), %xmm13 + psrld $0x01, %xmm5 + psrld $2, %xmm1 + psrld $7, %xmm0 + aesenc 144(%rdi), %xmm14 + pxor %xmm1, %xmm5 + pxor %xmm0, %xmm5 + aesenc 144(%rdi), %xmm15 + pxor %xmm4, %xmm5 + pxor %xmm5, %xmm2 + pxor %xmm3, %xmm2 + cmpl $11, %esi + movdqa 160(%rdi), %xmm7 + jl L_AES_GCM_decrypt_update_aesni_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %esi + movdqa 192(%rdi), %xmm7 + jl L_AES_GCM_decrypt_update_aesni_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%rdi), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%rdi), %xmm7 +L_AES_GCM_decrypt_update_aesni_aesenc_128_ghash_avx_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rcx), %xmm0 + movdqu 16(%rcx), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rdx) + movdqu %xmm9, 16(%rdx) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rcx), %xmm0 + movdqu 48(%rcx), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rdx) + movdqu %xmm11, 48(%rdx) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rcx), %xmm0 + movdqu 80(%rcx), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rdx) + movdqu %xmm13, 80(%rdx) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rcx), %xmm0 + movdqu 112(%rcx), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rdx) + movdqu %xmm15, 112(%rdx) + addl $0x80, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_decrypt_update_aesni_ghash_128 + movdqa %xmm2, %xmm6 + movdqa (%rsp), %xmm5 +L_AES_GCM_decrypt_update_aesni_done_128: + movl %r8d, %edx + cmpl %edx, %r14d + jge L_AES_GCM_decrypt_update_aesni_done_dec + movl %r8d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %r14d + jge L_AES_GCM_decrypt_update_aesni_last_block_done +L_AES_GCM_decrypt_update_aesni_last_block_start: + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + movdqu (%rcx), %xmm1 + movdqa %xmm5, %xmm0 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm1 + pxor %xmm6, %xmm1 + movdqa (%r12), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%rdi), %xmm8 + movdqa %xmm9, (%r12) + movdqa %xmm1, %xmm10 + pclmulqdq $16, %xmm0, %xmm10 + aesenc 16(%rdi), %xmm8 + aesenc 32(%rdi), %xmm8 + movdqa %xmm1, %xmm11 + pclmulqdq $0x01, %xmm0, %xmm11 + aesenc 48(%rdi), %xmm8 + aesenc 64(%rdi), %xmm8 + movdqa %xmm1, %xmm12 + pclmulqdq $0x00, %xmm0, %xmm12 + aesenc 80(%rdi), %xmm8 + movdqa %xmm1, %xmm1 + pclmulqdq $0x11, %xmm0, %xmm1 + aesenc 96(%rdi), %xmm8 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm2 + psrldq $8, %xmm10 + pslldq $8, %xmm2 + aesenc 112(%rdi), %xmm8 + movdqa %xmm1, %xmm3 + pxor %xmm12, %xmm2 + pxor %xmm10, %xmm3 + movdqa L_aes_gcm_mod2_128(%rip), %xmm0 + movdqa %xmm2, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 128(%rdi), %xmm8 + pshufd $0x4e, %xmm2, %xmm10 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 144(%rdi), %xmm8 + pshufd $0x4e, %xmm10, %xmm6 + pxor %xmm11, %xmm6 + pxor %xmm3, %xmm6 + cmpl $11, %esi + movdqa 160(%rdi), %xmm9 + jl L_AES_GCM_decrypt_update_aesni_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 176(%rdi), %xmm8 + cmpl $13, %esi + movdqa 192(%rdi), %xmm9 + jl L_AES_GCM_decrypt_update_aesni_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 208(%rdi), %xmm8 + movdqa 224(%rdi), %xmm9 +L_AES_GCM_decrypt_update_aesni_aesenc_gfmul_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + addl $16, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_decrypt_update_aesni_last_block_start +L_AES_GCM_decrypt_update_aesni_last_block_done: +L_AES_GCM_decrypt_update_aesni_done_dec: + movdqa %xmm6, (%r9) + addq $0xa8, %rsp + popq %r15 + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_update_aesni,.-AES_GCM_decrypt_update_aesni +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_final_aesni +.type AES_GCM_decrypt_final_aesni,@function +.align 16 +AES_GCM_decrypt_final_aesni: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_final_aesni +.p2align 4 +_AES_GCM_decrypt_final_aesni: +#endif /* __APPLE__ */ + pushq %r13 + pushq %rbp + pushq %r12 + movq %rdx, %rax + movl %ecx, %r10d + movl %r8d, %r11d + movq 32(%rsp), %r8 + movq 40(%rsp), %rbp + subq $16, %rsp + movdqa (%rdi), %xmm6 + movdqa (%r9), %xmm5 + movdqa (%r8), %xmm15 + movdqa %xmm5, %xmm9 + movdqa %xmm5, %xmm8 + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + movl %r10d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + pinsrq $0x00, %rdx, %xmm0 + pinsrq $0x01, %rcx, %xmm0 + pxor %xmm0, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm6 + movdqa %xmm15, %xmm0 + pxor %xmm6, %xmm0 + cmpl $16, %eax + je L_AES_GCM_decrypt_final_aesni_cmp_tag_16 + subq $16, %rsp + xorq %rcx, %rcx + xorq %r12, %r12 + movdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_final_aesni_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%rsi,%rcx,1), %r13b + orb %r13b, %r12b + incl %ecx + cmpl %eax, %ecx + jne L_AES_GCM_decrypt_final_aesni_cmp_tag_loop + cmpb $0x00, %r12b + sete %r12b + addq $16, %rsp + xorq %rcx, %rcx + jmp L_AES_GCM_decrypt_final_aesni_cmp_tag_done +L_AES_GCM_decrypt_final_aesni_cmp_tag_16: + movdqu (%rsi), %xmm1 + pcmpeqb %xmm1, %xmm0 + pmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %r12d, %r12d + cmpl $0xffff, %edx + sete %r12b +L_AES_GCM_decrypt_final_aesni_cmp_tag_done: + movl %r12d, (%rbp) + addq $16, %rsp + popq %r12 + popq %rbp + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_final_aesni,.-AES_GCM_decrypt_final_aesni +#endif /* __APPLE__ */ +#endif /* WOLFSSL_AESGCM_STREAM */ #ifdef HAVE_INTEL_AVX1 #ifndef __APPLE__ .data @@ -3732,7 +6504,7 @@ L_AES_GCM_encrypt_avx1_calc_iv_lt16: subq $16, %rsp vpxor %xmm8, %xmm8, %xmm8 xorl %ebx, %ebx - vmovdqa %xmm8, (%rsp) + vmovdqu %xmm8, (%rsp) L_AES_GCM_encrypt_avx1_calc_iv_loop: movzbl (%rax,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -3740,7 +6512,7 @@ L_AES_GCM_encrypt_avx1_calc_iv_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_encrypt_avx1_calc_iv_loop - vmovdqa (%rsp), %xmm8 + vmovdqu (%rsp), %xmm8 addq $16, %rsp vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 vpxor %xmm8, %xmm4, %xmm4 @@ -3929,7 +6701,7 @@ L_AES_GCM_encrypt_avx1_calc_aad_lt16: subq $16, %rsp vpxor %xmm8, %xmm8, %xmm8 xorl %ebx, %ebx - vmovdqa %xmm8, (%rsp) + vmovdqu %xmm8, (%rsp) L_AES_GCM_encrypt_avx1_calc_aad_loop: movzbl (%r12,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -3937,7 +6709,7 @@ L_AES_GCM_encrypt_avx1_calc_aad_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_encrypt_avx1_calc_aad_loop - vmovdqa (%rsp), %xmm8 + vmovdqu (%rsp), %xmm8 addq $16, %rsp vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 vpxor %xmm8, %xmm6, %xmm6 @@ -5012,7 +7784,7 @@ L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last: vaesenclast %xmm9, %xmm4, %xmm4 subq $16, %rsp xorl %ecx, %ecx - vmovdqa %xmm4, (%rsp) + vmovdqu %xmm4, (%rsp) L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_loop: movzbl (%rdi,%rbx,1), %r13d xorb (%rsp,%rcx,1), %r13b @@ -5031,7 +7803,7 @@ L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_byte_loop: cmpl $16, %ecx jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_byte_loop L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_finish_enc: - vmovdqa (%rsp), %xmm4 + vmovdqu (%rsp), %xmm4 addq $16, %rsp vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 vpxor %xmm4, %xmm6, %xmm6 @@ -5109,7 +7881,7 @@ L_AES_GCM_encrypt_avx1_done_enc: cmpl $16, %r14d je L_AES_GCM_encrypt_avx1_store_tag_16 xorq %rcx, %rcx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_encrypt_avx1_store_tag_loop: movzbl (%rsp,%rcx,1), %r13d movb %r13b, (%r8,%rcx,1) @@ -5314,7 +8086,7 @@ L_AES_GCM_decrypt_avx1_calc_iv_lt16: subq $16, %rsp vpxor %xmm8, %xmm8, %xmm8 xorl %ebx, %ebx - vmovdqa %xmm8, (%rsp) + vmovdqu %xmm8, (%rsp) L_AES_GCM_decrypt_avx1_calc_iv_loop: movzbl (%rax,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -5322,7 +8094,7 @@ L_AES_GCM_decrypt_avx1_calc_iv_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_decrypt_avx1_calc_iv_loop - vmovdqa (%rsp), %xmm8 + vmovdqu (%rsp), %xmm8 addq $16, %rsp vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 vpxor %xmm8, %xmm4, %xmm4 @@ -5511,7 +8283,7 @@ L_AES_GCM_decrypt_avx1_calc_aad_lt16: subq $16, %rsp vpxor %xmm8, %xmm8, %xmm8 xorl %ebx, %ebx - vmovdqa %xmm8, (%rsp) + vmovdqu %xmm8, (%rsp) L_AES_GCM_decrypt_avx1_calc_aad_loop: movzbl (%r12,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -5519,7 +8291,7 @@ L_AES_GCM_decrypt_avx1_calc_aad_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_decrypt_avx1_calc_aad_loop - vmovdqa (%rsp), %xmm8 + vmovdqu (%rsp), %xmm8 addq $16, %rsp vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 vpxor %xmm8, %xmm6, %xmm6 @@ -6178,9 +8950,9 @@ L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last: vaesenclast %xmm9, %xmm4, %xmm4 subq $32, %rsp xorl %ecx, %ecx - vmovdqa %xmm4, (%rsp) + vmovdqu %xmm4, (%rsp) vpxor %xmm0, %xmm0, %xmm0 - vmovdqa %xmm0, 16(%rsp) + vmovdqu %xmm0, 16(%rsp) L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop: movzbl (%rdi,%rbx,1), %r13d movb %r13b, 16(%rsp,%rcx,1) @@ -6190,7 +8962,7 @@ L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop: incl %ecx cmpl %edx, %ebx jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop - vmovdqa 16(%rsp), %xmm4 + vmovdqu 16(%rsp), %xmm4 addq $32, %rsp vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 vpxor %xmm4, %xmm6, %xmm6 @@ -6270,7 +9042,7 @@ L_AES_GCM_decrypt_avx1_done_dec: subq $16, %rsp xorq %rcx, %rcx xorq %rbx, %rbx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_decrypt_avx1_cmp_tag_loop: movzbl (%rsp,%rcx,1), %r13d xorb (%r8,%rcx,1), %r13b @@ -6305,6 +9077,2345 @@ L_AES_GCM_decrypt_avx1_cmp_tag_done: #ifndef __APPLE__ .size AES_GCM_decrypt_avx1,.-AES_GCM_decrypt_avx1 #endif /* __APPLE__ */ +#ifdef WOLFSSL_AESGCM_STREAM +#ifndef __APPLE__ +.text +.globl AES_GCM_init_avx1 +.type AES_GCM_init_avx1,@function +.align 16 +AES_GCM_init_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_init_avx1 +.p2align 4 +_AES_GCM_init_avx1: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + movq %rdx, %r10 + movl %ecx, %r11d + movq 24(%rsp), %rax + subq $16, %rsp + vpxor %xmm4, %xmm4, %xmm4 + movl %r11d, %edx + cmpl $12, %edx + jne L_AES_GCM_init_avx1_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + vpinsrq $0x00, (%r10), %xmm4, %xmm4 + vpinsrd $2, 8(%r10), %xmm4, %xmm4 + vpinsrd $3, %ecx, %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa (%rdi), %xmm5 + vpxor %xmm5, %xmm4, %xmm1 + vmovdqa 16(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 32(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 48(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 64(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 80(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 96(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 112(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 128(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 144(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_init_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_init_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_init_avx1_calc_iv_12_last: + vaesenclast %xmm7, %xmm5, %xmm5 + vaesenclast %xmm7, %xmm1, %xmm1 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + vmovdqa %xmm1, %xmm15 + jmp L_AES_GCM_init_avx1_iv_done +L_AES_GCM_init_avx1_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%rdi), %xmm5 + vaesenc 16(%rdi), %xmm5, %xmm5 + vaesenc 32(%rdi), %xmm5, %xmm5 + vaesenc 48(%rdi), %xmm5, %xmm5 + vaesenc 64(%rdi), %xmm5, %xmm5 + vaesenc 80(%rdi), %xmm5, %xmm5 + vaesenc 96(%rdi), %xmm5, %xmm5 + vaesenc 112(%rdi), %xmm5, %xmm5 + vaesenc 128(%rdi), %xmm5, %xmm5 + vaesenc 144(%rdi), %xmm5, %xmm5 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm9 + jl L_AES_GCM_init_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 176(%rdi), %xmm5, %xmm5 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm9 + jl L_AES_GCM_init_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 208(%rdi), %xmm5, %xmm5 + vmovdqa 224(%rdi), %xmm9 +L_AES_GCM_init_avx1_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm9, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_init_avx1_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_init_avx1_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_init_avx1_calc_iv_16_loop: + vmovdqu (%r10,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_init_avx1_calc_iv_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_init_avx1_calc_iv_done +L_AES_GCM_init_avx1_calc_iv_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %r13d, %r13d + vmovdqu %xmm8, (%rsp) +L_AES_GCM_init_avx1_calc_iv_loop: + movzbl (%r10,%rcx,1), %r12d + movb %r12b, (%rsp,%r13,1) + incl %ecx + incl %r13d + cmpl %edx, %ecx + jl L_AES_GCM_init_avx1_calc_iv_loop + vmovdqu (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 +L_AES_GCM_init_avx1_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%rdi), %xmm8 + vpxor %xmm4, %xmm8, %xmm8 + vaesenc 16(%rdi), %xmm8, %xmm8 + vaesenc 32(%rdi), %xmm8, %xmm8 + vaesenc 48(%rdi), %xmm8, %xmm8 + vaesenc 64(%rdi), %xmm8, %xmm8 + vaesenc 80(%rdi), %xmm8, %xmm8 + vaesenc 96(%rdi), %xmm8, %xmm8 + vaesenc 112(%rdi), %xmm8, %xmm8 + vaesenc 128(%rdi), %xmm8, %xmm8 + vaesenc 144(%rdi), %xmm8, %xmm8 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm9 + jl L_AES_GCM_init_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%rdi), %xmm8, %xmm8 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm9 + jl L_AES_GCM_init_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%rdi), %xmm8, %xmm8 + vmovdqa 224(%rdi), %xmm9 +L_AES_GCM_init_avx1_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm8, %xmm15 +L_AES_GCM_init_avx1_iv_done: + vmovdqa %xmm15, (%rax) + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm4, %xmm4 + vmovdqa %xmm5, (%r8) + vmovdqa %xmm4, (%r9) + vzeroupper + addq $16, %rsp + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size AES_GCM_init_avx1,.-AES_GCM_init_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_aad_update_avx1 +.type AES_GCM_aad_update_avx1,@function +.align 16 +AES_GCM_aad_update_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_aad_update_avx1 +.p2align 4 +_AES_GCM_aad_update_avx1: +#endif /* __APPLE__ */ + movq %rcx, %rax + vmovdqa (%rdx), %xmm5 + vmovdqa (%rax), %xmm6 + xorl %ecx, %ecx +L_AES_GCM_aad_update_avx1_16_loop: + vmovdqu (%rdi,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm5, %xmm5 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm5, %xmm1 + vpshufd $0x4e, %xmm6, %xmm2 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm0 + vpxor %xmm5, %xmm1, %xmm1 + vpxor %xmm6, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm4 + vmovdqa %xmm3, %xmm5 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm5, %xmm5 + vpsrld $31, %xmm4, %xmm0 + vpsrld $31, %xmm5, %xmm1 + vpslld $0x01, %xmm4, %xmm4 + vpslld $0x01, %xmm5, %xmm5 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm5, %xmm5 + vpor %xmm0, %xmm4, %xmm4 + vpor %xmm1, %xmm5, %xmm5 + vpslld $31, %xmm4, %xmm0 + vpslld $30, %xmm4, %xmm1 + vpslld $25, %xmm4, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + vpsrld $0x01, %xmm4, %xmm2 + vpsrld $2, %xmm4, %xmm3 + vpsrld $7, %xmm4, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm4, %xmm2, %xmm2 + vpxor %xmm2, %xmm5, %xmm5 + addl $16, %ecx + cmpl %esi, %ecx + jl L_AES_GCM_aad_update_avx1_16_loop + vmovdqa %xmm5, (%rdx) + vzeroupper + repz retq +#ifndef __APPLE__ +.size AES_GCM_aad_update_avx1,.-AES_GCM_aad_update_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_block_avx1 +.type AES_GCM_encrypt_block_avx1,@function +.align 16 +AES_GCM_encrypt_block_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_block_avx1 +.p2align 4 +_AES_GCM_encrypt_block_avx1: +#endif /* __APPLE__ */ + movq %rdx, %r10 + movq %rcx, %r11 + vmovdqa (%r8), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, (%r8) + vpxor (%rdi), %xmm8, %xmm8 + vaesenc 16(%rdi), %xmm8, %xmm8 + vaesenc 32(%rdi), %xmm8, %xmm8 + vaesenc 48(%rdi), %xmm8, %xmm8 + vaesenc 64(%rdi), %xmm8, %xmm8 + vaesenc 80(%rdi), %xmm8, %xmm8 + vaesenc 96(%rdi), %xmm8, %xmm8 + vaesenc 112(%rdi), %xmm8, %xmm8 + vaesenc 128(%rdi), %xmm8, %xmm8 + vaesenc 144(%rdi), %xmm8, %xmm8 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm9 + jl L_AES_GCM_encrypt_block_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%rdi), %xmm8, %xmm8 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm9 + jl L_AES_GCM_encrypt_block_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%rdi), %xmm8, %xmm8 + vmovdqa 224(%rdi), %xmm9 +L_AES_GCM_encrypt_block_avx1_aesenc_block_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqu (%r11), %xmm9 + vpxor %xmm9, %xmm8, %xmm8 + vmovdqu %xmm8, (%r10) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vzeroupper + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_block_avx1,.-AES_GCM_encrypt_block_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_ghash_block_avx1 +.type AES_GCM_ghash_block_avx1,@function +.align 16 +AES_GCM_ghash_block_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_ghash_block_avx1 +.p2align 4 +_AES_GCM_ghash_block_avx1: +#endif /* __APPLE__ */ + vmovdqa (%rsi), %xmm4 + vmovdqa (%rdx), %xmm5 + vmovdqu (%rdi), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm6 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm6, %xmm6 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm6, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm6, %xmm6 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm6, %xmm6 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm6, %xmm0 + vpslld $30, %xmm6, %xmm1 + vpslld $25, %xmm6, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + vpsrld $0x01, %xmm6, %xmm2 + vpsrld $2, %xmm6, %xmm3 + vpsrld $7, %xmm6, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm6, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + vmovdqa %xmm4, (%rsi) + vzeroupper + repz retq +#ifndef __APPLE__ +.size AES_GCM_ghash_block_avx1,.-AES_GCM_ghash_block_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_update_avx1 +.type AES_GCM_encrypt_update_avx1,@function +.align 16 +AES_GCM_encrypt_update_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_update_avx1 +.p2align 4 +_AES_GCM_encrypt_update_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + movq %rdx, %r10 + movq %rcx, %r11 + movq 32(%rsp), %rax + movq 40(%rsp), %r12 + subq $0xa0, %rsp + vmovdqa (%r9), %xmm6 + vmovdqa (%rax), %xmm5 + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm8, %xmm5, %xmm5 + xorl %r14d, %r14d + cmpl $0x80, %r8d + movl %r8d, %r13d + jl L_AES_GCM_encrypt_update_avx1_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm6, %xmm2 + # H ^ 1 + vmovdqa %xmm5, (%rsp) + # H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm0 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm0, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm0, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm1 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm1, %xmm1 + vmovdqa %xmm1, 32(%rsp) + # H ^ 4 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm3 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm3, %xmm3 + vmovdqa %xmm3, 48(%rsp) + # H ^ 5 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm0, %xmm9 + vpshufd $0x4e, %xmm1, %xmm10 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm8 + vpxor %xmm0, %xmm9, %xmm9 + vpxor %xmm1, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 64(%rsp) + # H ^ 6 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm8 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 80(%rsp) + # H ^ 7 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm1, %xmm9 + vpshufd $0x4e, %xmm3, %xmm10 + vpclmulqdq $0x11, %xmm1, %xmm3, %xmm11 + vpclmulqdq $0x00, %xmm1, %xmm3, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm3, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 96(%rsp) + # H ^ 8 + vpclmulqdq $0x00, %xmm3, %xmm3, %xmm8 + vpclmulqdq $0x11, %xmm3, %xmm3, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 112(%rsp) + # First 128 bytes of input + vmovdqa (%r12), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%rdi), %xmm7 + vmovdqa %xmm0, (%r12) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 16(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 48(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 64(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 80(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 96(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 128(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 144(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx1_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx1_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_encrypt_update_avx1_aesenc_128_enc_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%r11), %xmm0 + vmovdqu 16(%r11), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%r10) + vmovdqu %xmm9, 16(%r10) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%r11), %xmm0 + vmovdqu 48(%r11), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%r10) + vmovdqu %xmm11, 48(%r10) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%r11), %xmm0 + vmovdqu 80(%r11), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%r10) + vmovdqu %xmm13, 80(%r10) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%r11), %xmm0 + vmovdqu 112(%r11), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%r10) + vmovdqu %xmm15, 112(%r10) + cmpl $0x80, %r13d + movl $0x80, %r14d + jle L_AES_GCM_encrypt_update_avx1_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_update_avx1_ghash_128: + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + vmovdqa (%r12), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%rdi), %xmm7 + vmovdqa %xmm0, (%r12) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsp), %xmm7 + vmovdqu -128(%rdx), %xmm0 + vaesenc 16(%rdi), %xmm8, %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm3 + vaesenc 16(%rdi), %xmm9, %xmm9 + vaesenc 16(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm2 + vaesenc 16(%rdi), %xmm11, %xmm11 + vaesenc 16(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm1, %xmm1 + vaesenc 16(%rdi), %xmm13, %xmm13 + vaesenc 16(%rdi), %xmm14, %xmm14 + vaesenc 16(%rdi), %xmm15, %xmm15 + vpxor %xmm2, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa 96(%rsp), %xmm7 + vmovdqu -112(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 32(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 32(%rdi), %xmm9, %xmm9 + vaesenc 32(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 32(%rdi), %xmm11, %xmm11 + vaesenc 32(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 32(%rdi), %xmm13, %xmm13 + vaesenc 32(%rdi), %xmm14, %xmm14 + vaesenc 32(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 80(%rsp), %xmm7 + vmovdqu -96(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 48(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 48(%rdi), %xmm9, %xmm9 + vaesenc 48(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 48(%rdi), %xmm11, %xmm11 + vaesenc 48(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 48(%rdi), %xmm13, %xmm13 + vaesenc 48(%rdi), %xmm14, %xmm14 + vaesenc 48(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 64(%rsp), %xmm7 + vmovdqu -80(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 64(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 64(%rdi), %xmm9, %xmm9 + vaesenc 64(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 64(%rdi), %xmm11, %xmm11 + vaesenc 64(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 64(%rdi), %xmm13, %xmm13 + vaesenc 64(%rdi), %xmm14, %xmm14 + vaesenc 64(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 48(%rsp), %xmm7 + vmovdqu -64(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 80(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 80(%rdi), %xmm9, %xmm9 + vaesenc 80(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 80(%rdi), %xmm11, %xmm11 + vaesenc 80(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 80(%rdi), %xmm13, %xmm13 + vaesenc 80(%rdi), %xmm14, %xmm14 + vaesenc 80(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 32(%rsp), %xmm7 + vmovdqu -48(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 96(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 96(%rdi), %xmm9, %xmm9 + vaesenc 96(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 96(%rdi), %xmm11, %xmm11 + vaesenc 96(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 96(%rdi), %xmm13, %xmm13 + vaesenc 96(%rdi), %xmm14, %xmm14 + vaesenc 96(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 16(%rsp), %xmm7 + vmovdqu -32(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 112(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 112(%rdi), %xmm9, %xmm9 + vaesenc 112(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 112(%rdi), %xmm11, %xmm11 + vaesenc 112(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 112(%rdi), %xmm13, %xmm13 + vaesenc 112(%rdi), %xmm14, %xmm14 + vaesenc 112(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa (%rsp), %xmm7 + vmovdqu -16(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 128(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 128(%rdi), %xmm9, %xmm9 + vaesenc 128(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 128(%rdi), %xmm11, %xmm11 + vaesenc 128(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 128(%rdi), %xmm13, %xmm13 + vaesenc 128(%rdi), %xmm14, %xmm14 + vaesenc 128(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vpslldq $8, %xmm1, %xmm5 + vpsrldq $8, %xmm1, %xmm1 + vaesenc 144(%rdi), %xmm8, %xmm8 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm1, %xmm3, %xmm3 + vaesenc 144(%rdi), %xmm9, %xmm9 + vpslld $31, %xmm2, %xmm7 + vpslld $30, %xmm2, %xmm4 + vpslld $25, %xmm2, %xmm5 + vaesenc 144(%rdi), %xmm10, %xmm10 + vpxor %xmm4, %xmm7, %xmm7 + vpxor %xmm5, %xmm7, %xmm7 + vaesenc 144(%rdi), %xmm11, %xmm11 + vpsrldq $4, %xmm7, %xmm4 + vpslldq $12, %xmm7, %xmm7 + vaesenc 144(%rdi), %xmm12, %xmm12 + vpxor %xmm7, %xmm2, %xmm2 + vpsrld $0x01, %xmm2, %xmm5 + vaesenc 144(%rdi), %xmm13, %xmm13 + vpsrld $2, %xmm2, %xmm1 + vpsrld $7, %xmm2, %xmm0 + vaesenc 144(%rdi), %xmm14, %xmm14 + vpxor %xmm1, %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vaesenc 144(%rdi), %xmm15, %xmm15 + vpxor %xmm4, %xmm5, %xmm5 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm3, %xmm2, %xmm2 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_encrypt_update_avx1_aesenc_128_ghash_avx_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rcx), %xmm0 + vmovdqu 48(%rcx), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rcx), %xmm0 + vmovdqu 112(%rcx), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + addl $0x80, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_encrypt_update_avx1_ghash_128 +L_AES_GCM_encrypt_update_avx1_end_128: + vmovdqa L_avx1_aes_gcm_bswap_mask(%rip), %xmm4 + vpshufb %xmm4, %xmm8, %xmm8 + vpshufb %xmm4, %xmm9, %xmm9 + vpshufb %xmm4, %xmm10, %xmm10 + vpshufb %xmm4, %xmm11, %xmm11 + vpxor %xmm2, %xmm8, %xmm8 + vpshufb %xmm4, %xmm12, %xmm12 + vpshufb %xmm4, %xmm13, %xmm13 + vpshufb %xmm4, %xmm14, %xmm14 + vpshufb %xmm4, %xmm15, %xmm15 + vmovdqa (%rsp), %xmm7 + vmovdqa 16(%rsp), %xmm5 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm15, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm15, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm15, %xmm7, %xmm0 + vpxor %xmm15, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm4 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm14, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm14, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm14, %xmm5, %xmm0 + vpxor %xmm14, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 32(%rsp), %xmm7 + vmovdqa 48(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm13, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm13, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm13, %xmm7, %xmm0 + vpxor %xmm13, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm12, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm12, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm12, %xmm5, %xmm0 + vpxor %xmm12, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 64(%rsp), %xmm7 + vmovdqa 80(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm11, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm11, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm11, %xmm7, %xmm0 + vpxor %xmm11, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm10, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm10, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm10, %xmm5, %xmm0 + vpxor %xmm10, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 96(%rsp), %xmm7 + vmovdqa 112(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm9, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm9, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm9, %xmm7, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm8, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm8, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm8, %xmm5, %xmm0 + vpxor %xmm8, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm4, %xmm0 + vpslld $30, %xmm4, %xmm1 + vpslld $25, %xmm4, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + vpsrld $0x01, %xmm4, %xmm2 + vpsrld $2, %xmm4, %xmm3 + vpsrld $7, %xmm4, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm4, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + vmovdqa (%rsp), %xmm5 +L_AES_GCM_encrypt_update_avx1_done_128: + movl %r8d, %edx + cmpl %edx, %r14d + jge L_AES_GCM_encrypt_update_avx1_done_enc + movl %r8d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %r14d + jge L_AES_GCM_encrypt_update_avx1_last_block_done + vmovdqa (%r12), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, (%r12) + vpxor (%rdi), %xmm8, %xmm8 + vaesenc 16(%rdi), %xmm8, %xmm8 + vaesenc 32(%rdi), %xmm8, %xmm8 + vaesenc 48(%rdi), %xmm8, %xmm8 + vaesenc 64(%rdi), %xmm8, %xmm8 + vaesenc 80(%rdi), %xmm8, %xmm8 + vaesenc 96(%rdi), %xmm8, %xmm8 + vaesenc 112(%rdi), %xmm8, %xmm8 + vaesenc 128(%rdi), %xmm8, %xmm8 + vaesenc 144(%rdi), %xmm8, %xmm8 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%rdi), %xmm8, %xmm8 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%rdi), %xmm8, %xmm8 + vmovdqa 224(%rdi), %xmm9 +L_AES_GCM_encrypt_update_avx1_aesenc_block_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqu (%r11,%r14,1), %xmm9 + vpxor %xmm9, %xmm8, %xmm8 + vmovdqu %xmm8, (%r10,%r14,1) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + addl $16, %r14d + cmpl %r13d, %r14d + jge L_AES_GCM_encrypt_update_avx1_last_block_ghash +L_AES_GCM_encrypt_update_avx1_last_block_start: + vmovdqu (%r11,%r14,1), %xmm13 + vmovdqa (%r12), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, (%r12) + vpxor (%rdi), %xmm8, %xmm8 + vpclmulqdq $16, %xmm5, %xmm6, %xmm10 + vaesenc 16(%rdi), %xmm8, %xmm8 + vaesenc 32(%rdi), %xmm8, %xmm8 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm11 + vaesenc 48(%rdi), %xmm8, %xmm8 + vaesenc 64(%rdi), %xmm8, %xmm8 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm12 + vaesenc 80(%rdi), %xmm8, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm1 + vaesenc 96(%rdi), %xmm8, %xmm8 + vpxor %xmm11, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm2 + vpsrldq $8, %xmm10, %xmm10 + vaesenc 112(%rdi), %xmm8, %xmm8 + vpxor %xmm12, %xmm2, %xmm2 + vpxor %xmm10, %xmm1, %xmm3 + vmovdqa L_avx1_aes_gcm_mod2_128(%rip), %xmm0 + vpclmulqdq $16, %xmm0, %xmm2, %xmm11 + vaesenc 128(%rdi), %xmm8, %xmm8 + vpshufd $0x4e, %xmm2, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpclmulqdq $16, %xmm0, %xmm10, %xmm11 + vaesenc 144(%rdi), %xmm8, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpxor %xmm3, %xmm10, %xmm6 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%rdi), %xmm8, %xmm8 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm9 + jl L_AES_GCM_encrypt_update_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%rdi), %xmm8, %xmm8 + vmovdqa 224(%rdi), %xmm9 +L_AES_GCM_encrypt_update_avx1_aesenc_gfmul_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm13, %xmm0 + vpxor %xmm0, %xmm8, %xmm8 + vmovdqu %xmm8, (%r10,%r14,1) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + addl $16, %r14d + vpxor %xmm8, %xmm6, %xmm6 + cmpl %r13d, %r14d + jl L_AES_GCM_encrypt_update_avx1_last_block_start +L_AES_GCM_encrypt_update_avx1_last_block_ghash: + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_encrypt_update_avx1_last_block_done: +L_AES_GCM_encrypt_update_avx1_done_enc: + vmovdqa %xmm6, (%r9) + vzeroupper + addq $0xa0, %rsp + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_update_avx1,.-AES_GCM_encrypt_update_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_final_avx1 +.type AES_GCM_encrypt_final_avx1,@function +.align 16 +AES_GCM_encrypt_final_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_final_avx1 +.p2align 4 +_AES_GCM_encrypt_final_avx1: +#endif /* __APPLE__ */ + pushq %r13 + movq %rdx, %rax + movl %ecx, %r10d + movl %r8d, %r11d + movq 16(%rsp), %r8 + subq $16, %rsp + vmovdqa (%rdi), %xmm4 + vmovdqa (%r9), %xmm5 + vmovdqa (%r8), %xmm6 + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm8, %xmm5, %xmm5 + movl %r10d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpinsrq $0x01, %rcx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm4, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm4, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm4, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm4 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm4, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm6, %xmm4, %xmm0 + cmpl $16, %eax + je L_AES_GCM_encrypt_final_avx1_store_tag_16 + xorq %rcx, %rcx + vmovdqu %xmm0, (%rsp) +L_AES_GCM_encrypt_final_avx1_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%rsi,%rcx,1) + incl %ecx + cmpl %eax, %ecx + jne L_AES_GCM_encrypt_final_avx1_store_tag_loop + jmp L_AES_GCM_encrypt_final_avx1_store_tag_done +L_AES_GCM_encrypt_final_avx1_store_tag_16: + vmovdqu %xmm0, (%rsi) +L_AES_GCM_encrypt_final_avx1_store_tag_done: + vzeroupper + addq $16, %rsp + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_final_avx1,.-AES_GCM_encrypt_final_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_update_avx1 +.type AES_GCM_decrypt_update_avx1,@function +.align 16 +AES_GCM_decrypt_update_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_update_avx1 +.p2align 4 +_AES_GCM_decrypt_update_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + movq %rdx, %r10 + movq %rcx, %r11 + movq 32(%rsp), %rax + movq 40(%rsp), %r12 + subq $0xa8, %rsp + vmovdqa (%r9), %xmm6 + vmovdqa (%rax), %xmm5 + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm8, %xmm5, %xmm5 + xorl %r14d, %r14d + cmpl $0x80, %r8d + movl %r8d, %r13d + jl L_AES_GCM_decrypt_update_avx1_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm6, %xmm2 + # H ^ 1 + vmovdqa %xmm5, (%rsp) + # H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm0 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm0, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm0, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm1 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm1, %xmm1 + vmovdqa %xmm1, 32(%rsp) + # H ^ 4 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm3 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm3, %xmm3 + vmovdqa %xmm3, 48(%rsp) + # H ^ 5 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm0, %xmm9 + vpshufd $0x4e, %xmm1, %xmm10 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm8 + vpxor %xmm0, %xmm9, %xmm9 + vpxor %xmm1, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 64(%rsp) + # H ^ 6 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm8 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 80(%rsp) + # H ^ 7 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm1, %xmm9 + vpshufd $0x4e, %xmm3, %xmm10 + vpclmulqdq $0x11, %xmm1, %xmm3, %xmm11 + vpclmulqdq $0x00, %xmm1, %xmm3, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm3, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 96(%rsp) + # H ^ 8 + vpclmulqdq $0x00, %xmm3, %xmm3, %xmm8 + vpclmulqdq $0x11, %xmm3, %xmm3, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 112(%rsp) +L_AES_GCM_decrypt_update_avx1_ghash_128: + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + vmovdqa (%r12), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%rdi), %xmm7 + vmovdqa %xmm0, (%r12) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsp), %xmm7 + vmovdqu (%rcx), %xmm0 + vaesenc 16(%rdi), %xmm8, %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm3 + vaesenc 16(%rdi), %xmm9, %xmm9 + vaesenc 16(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm2 + vaesenc 16(%rdi), %xmm11, %xmm11 + vaesenc 16(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm1, %xmm1 + vaesenc 16(%rdi), %xmm13, %xmm13 + vaesenc 16(%rdi), %xmm14, %xmm14 + vaesenc 16(%rdi), %xmm15, %xmm15 + vpxor %xmm2, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa 96(%rsp), %xmm7 + vmovdqu 16(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 32(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 32(%rdi), %xmm9, %xmm9 + vaesenc 32(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 32(%rdi), %xmm11, %xmm11 + vaesenc 32(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 32(%rdi), %xmm13, %xmm13 + vaesenc 32(%rdi), %xmm14, %xmm14 + vaesenc 32(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 80(%rsp), %xmm7 + vmovdqu 32(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 48(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 48(%rdi), %xmm9, %xmm9 + vaesenc 48(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 48(%rdi), %xmm11, %xmm11 + vaesenc 48(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 48(%rdi), %xmm13, %xmm13 + vaesenc 48(%rdi), %xmm14, %xmm14 + vaesenc 48(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 64(%rsp), %xmm7 + vmovdqu 48(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 64(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 64(%rdi), %xmm9, %xmm9 + vaesenc 64(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 64(%rdi), %xmm11, %xmm11 + vaesenc 64(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 64(%rdi), %xmm13, %xmm13 + vaesenc 64(%rdi), %xmm14, %xmm14 + vaesenc 64(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 48(%rsp), %xmm7 + vmovdqu 64(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 80(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 80(%rdi), %xmm9, %xmm9 + vaesenc 80(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 80(%rdi), %xmm11, %xmm11 + vaesenc 80(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 80(%rdi), %xmm13, %xmm13 + vaesenc 80(%rdi), %xmm14, %xmm14 + vaesenc 80(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 32(%rsp), %xmm7 + vmovdqu 80(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 96(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 96(%rdi), %xmm9, %xmm9 + vaesenc 96(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 96(%rdi), %xmm11, %xmm11 + vaesenc 96(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 96(%rdi), %xmm13, %xmm13 + vaesenc 96(%rdi), %xmm14, %xmm14 + vaesenc 96(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 16(%rsp), %xmm7 + vmovdqu 96(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 112(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 112(%rdi), %xmm9, %xmm9 + vaesenc 112(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 112(%rdi), %xmm11, %xmm11 + vaesenc 112(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 112(%rdi), %xmm13, %xmm13 + vaesenc 112(%rdi), %xmm14, %xmm14 + vaesenc 112(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa (%rsp), %xmm7 + vmovdqu 112(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 128(%rdi), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 128(%rdi), %xmm9, %xmm9 + vaesenc 128(%rdi), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 128(%rdi), %xmm11, %xmm11 + vaesenc 128(%rdi), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 128(%rdi), %xmm13, %xmm13 + vaesenc 128(%rdi), %xmm14, %xmm14 + vaesenc 128(%rdi), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vpslldq $8, %xmm1, %xmm5 + vpsrldq $8, %xmm1, %xmm1 + vaesenc 144(%rdi), %xmm8, %xmm8 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm1, %xmm3, %xmm3 + vaesenc 144(%rdi), %xmm9, %xmm9 + vpslld $31, %xmm2, %xmm7 + vpslld $30, %xmm2, %xmm4 + vpslld $25, %xmm2, %xmm5 + vaesenc 144(%rdi), %xmm10, %xmm10 + vpxor %xmm4, %xmm7, %xmm7 + vpxor %xmm5, %xmm7, %xmm7 + vaesenc 144(%rdi), %xmm11, %xmm11 + vpsrldq $4, %xmm7, %xmm4 + vpslldq $12, %xmm7, %xmm7 + vaesenc 144(%rdi), %xmm12, %xmm12 + vpxor %xmm7, %xmm2, %xmm2 + vpsrld $0x01, %xmm2, %xmm5 + vaesenc 144(%rdi), %xmm13, %xmm13 + vpsrld $2, %xmm2, %xmm1 + vpsrld $7, %xmm2, %xmm0 + vaesenc 144(%rdi), %xmm14, %xmm14 + vpxor %xmm1, %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vaesenc 144(%rdi), %xmm15, %xmm15 + vpxor %xmm4, %xmm5, %xmm5 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm3, %xmm2, %xmm2 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_decrypt_update_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_decrypt_update_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_decrypt_update_avx1_aesenc_128_ghash_avx_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rcx), %xmm0 + vmovdqu 48(%rcx), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rcx), %xmm0 + vmovdqu 112(%rcx), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + addl $0x80, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_decrypt_update_avx1_ghash_128 + vmovdqa %xmm2, %xmm6 + vmovdqa (%rsp), %xmm5 +L_AES_GCM_decrypt_update_avx1_done_128: + movl %r8d, %edx + cmpl %edx, %r14d + jge L_AES_GCM_decrypt_update_avx1_done_dec + movl %r8d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %r14d + jge L_AES_GCM_decrypt_update_avx1_last_block_done +L_AES_GCM_decrypt_update_avx1_last_block_start: + vmovdqu (%r11,%r14,1), %xmm13 + vmovdqa %xmm5, %xmm0 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm13, %xmm1 + vpxor %xmm6, %xmm1, %xmm1 + vmovdqa (%r12), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, (%r12) + vpxor (%rdi), %xmm8, %xmm8 + vpclmulqdq $16, %xmm0, %xmm1, %xmm10 + vaesenc 16(%rdi), %xmm8, %xmm8 + vaesenc 32(%rdi), %xmm8, %xmm8 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm11 + vaesenc 48(%rdi), %xmm8, %xmm8 + vaesenc 64(%rdi), %xmm8, %xmm8 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm12 + vaesenc 80(%rdi), %xmm8, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vaesenc 96(%rdi), %xmm8, %xmm8 + vpxor %xmm11, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm2 + vpsrldq $8, %xmm10, %xmm10 + vaesenc 112(%rdi), %xmm8, %xmm8 + vpxor %xmm12, %xmm2, %xmm2 + vpxor %xmm10, %xmm1, %xmm3 + vmovdqa L_avx1_aes_gcm_mod2_128(%rip), %xmm0 + vpclmulqdq $16, %xmm0, %xmm2, %xmm11 + vaesenc 128(%rdi), %xmm8, %xmm8 + vpshufd $0x4e, %xmm2, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpclmulqdq $16, %xmm0, %xmm10, %xmm11 + vaesenc 144(%rdi), %xmm8, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpxor %xmm3, %xmm10, %xmm6 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm9 + jl L_AES_GCM_decrypt_update_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%rdi), %xmm8, %xmm8 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm9 + jl L_AES_GCM_decrypt_update_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%rdi), %xmm8, %xmm8 + vmovdqa 224(%rdi), %xmm9 +L_AES_GCM_decrypt_update_avx1_aesenc_gfmul_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm13, %xmm0 + vpxor %xmm0, %xmm8, %xmm8 + vmovdqu %xmm8, (%r10,%r14,1) + addl $16, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_decrypt_update_avx1_last_block_start +L_AES_GCM_decrypt_update_avx1_last_block_done: +L_AES_GCM_decrypt_update_avx1_done_dec: + vmovdqa %xmm6, (%r9) + vzeroupper + addq $0xa8, %rsp + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_update_avx1,.-AES_GCM_decrypt_update_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_final_avx1 +.type AES_GCM_decrypt_final_avx1,@function +.align 16 +AES_GCM_decrypt_final_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_final_avx1 +.p2align 4 +_AES_GCM_decrypt_final_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %rbp + pushq %r12 + movq %rdx, %rax + movl %ecx, %r10d + movl %r8d, %r11d + movq 32(%rsp), %r8 + movq 40(%rsp), %rbp + subq $16, %rsp + vmovdqa (%rdi), %xmm6 + vmovdqa (%r9), %xmm5 + vmovdqa (%r8), %xmm15 + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm8, %xmm5, %xmm5 + movl %r10d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpinsrq $0x01, %rcx, %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm6, %xmm6 + vpxor %xmm15, %xmm6, %xmm0 + cmpl $16, %eax + je L_AES_GCM_decrypt_final_avx1_cmp_tag_16 + subq $16, %rsp + xorq %rcx, %rcx + xorq %r12, %r12 + vmovdqu %xmm0, (%rsp) +L_AES_GCM_decrypt_final_avx1_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%rsi,%rcx,1), %r13b + orb %r13b, %r12b + incl %ecx + cmpl %eax, %ecx + jne L_AES_GCM_decrypt_final_avx1_cmp_tag_loop + cmpb $0x00, %r12b + sete %r12b + addq $16, %rsp + xorq %rcx, %rcx + jmp L_AES_GCM_decrypt_final_avx1_cmp_tag_done +L_AES_GCM_decrypt_final_avx1_cmp_tag_16: + vmovdqu (%rsi), %xmm1 + vpcmpeqb %xmm1, %xmm0, %xmm0 + vpmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %r12d, %r12d + cmpl $0xffff, %edx + sete %r12b +L_AES_GCM_decrypt_final_avx1_cmp_tag_done: + movl %r12d, (%rbp) + vzeroupper + addq $16, %rsp + popq %r12 + popq %rbp + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_final_avx1,.-AES_GCM_decrypt_final_avx1 +#endif /* __APPLE__ */ +#endif /* WOLFSSL_AESGCM_STREAM */ #endif /* HAVE_INTEL_AVX1 */ #ifdef HAVE_INTEL_AVX2 #ifndef __APPLE__ @@ -6561,7 +11672,7 @@ L_AES_GCM_encrypt_avx2_calc_iv_16_loop: L_AES_GCM_encrypt_avx2_calc_iv_lt16: vpxor %xmm0, %xmm0, %xmm0 xorl %ebx, %ebx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_encrypt_avx2_calc_iv_loop: movzbl (%rax,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -6569,7 +11680,7 @@ L_AES_GCM_encrypt_avx2_calc_iv_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_encrypt_avx2_calc_iv_loop - vmovdqa (%rsp), %xmm0 + vmovdqu (%rsp), %xmm0 vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 vpxor %xmm0, %xmm4, %xmm4 # ghash_gfmul_avx @@ -6773,7 +11884,7 @@ L_AES_GCM_encrypt_avx2_calc_aad_16_loop: L_AES_GCM_encrypt_avx2_calc_aad_lt16: vpxor %xmm0, %xmm0, %xmm0 xorl %ebx, %ebx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_encrypt_avx2_calc_aad_loop: movzbl (%r12,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -6781,7 +11892,7 @@ L_AES_GCM_encrypt_avx2_calc_aad_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_encrypt_avx2_calc_aad_loop - vmovdqa (%rsp), %xmm0 + vmovdqu (%rsp), %xmm0 vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 vpxor %xmm0, %xmm6, %xmm6 # ghash_gfmul_avx @@ -7674,8 +12785,8 @@ L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last: vaesenclast %xmm0, %xmm4, %xmm4 xorl %ecx, %ecx vpxor %xmm0, %xmm0, %xmm0 - vmovdqa %xmm4, (%rsp) - vmovdqa %xmm0, 16(%rsp) + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm0, 16(%rsp) L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop: movzbl (%rdi,%rbx,1), %r13d xorb (%rsp,%rcx,1), %r13b @@ -7686,7 +12797,7 @@ L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop: cmpl %edx, %ebx jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_finish_enc: - vmovdqa 16(%rsp), %xmm4 + vmovdqu 16(%rsp), %xmm4 vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 vpxor %xmm4, %xmm6, %xmm6 # ghash_gfmul_red @@ -7737,7 +12848,7 @@ L_AES_GCM_encrypt_avx2_done_enc: cmpl $16, %r14d je L_AES_GCM_encrypt_avx2_store_tag_16 xorq %rcx, %rcx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_encrypt_avx2_store_tag_loop: movzbl (%rsp,%rcx,1), %r13d movb %r13b, (%r15,%rcx,1) @@ -7871,7 +12982,7 @@ L_AES_GCM_decrypt_avx2_calc_iv_16_loop: L_AES_GCM_decrypt_avx2_calc_iv_lt16: vpxor %xmm0, %xmm0, %xmm0 xorl %ebx, %ebx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_decrypt_avx2_calc_iv_loop: movzbl (%rax,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -7879,7 +12990,7 @@ L_AES_GCM_decrypt_avx2_calc_iv_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_decrypt_avx2_calc_iv_loop - vmovdqa (%rsp), %xmm0 + vmovdqu (%rsp), %xmm0 vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 vpxor %xmm0, %xmm4, %xmm4 # ghash_gfmul_avx @@ -8083,7 +13194,7 @@ L_AES_GCM_decrypt_avx2_calc_aad_16_loop: L_AES_GCM_decrypt_avx2_calc_aad_lt16: vpxor %xmm0, %xmm0, %xmm0 xorl %ebx, %ebx - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_decrypt_avx2_calc_aad_loop: movzbl (%r12,%rcx,1), %r13d movb %r13b, (%rsp,%rbx,1) @@ -8091,7 +13202,7 @@ L_AES_GCM_decrypt_avx2_calc_aad_loop: incl %ebx cmpl %edx, %ecx jl L_AES_GCM_decrypt_avx2_calc_aad_loop - vmovdqa (%rsp), %xmm0 + vmovdqu (%rsp), %xmm0 vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 vpxor %xmm0, %xmm6, %xmm6 # ghash_gfmul_avx @@ -8634,8 +13745,8 @@ L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last: vaesenclast %xmm1, %xmm4, %xmm4 xorl %ecx, %ecx vpxor %xmm0, %xmm0, %xmm0 - vmovdqa %xmm4, (%rsp) - vmovdqa %xmm0, 16(%rsp) + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm0, 16(%rsp) L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop: movzbl (%rdi,%rbx,1), %r13d movb %r13b, 16(%rsp,%rcx,1) @@ -8645,7 +13756,7 @@ L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop: incl %ecx cmpl %edx, %ebx jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop - vmovdqa 16(%rsp), %xmm4 + vmovdqu 16(%rsp), %xmm4 vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 vpxor %xmm4, %xmm6, %xmm6 # ghash_gfmul_red @@ -8697,7 +13808,7 @@ L_AES_GCM_decrypt_avx2_done_dec: je L_AES_GCM_decrypt_avx2_cmp_tag_16 xorq %rdx, %rdx xorq %rax, %rax - vmovdqa %xmm0, (%rsp) + vmovdqu %xmm0, (%rsp) L_AES_GCM_decrypt_avx2_cmp_tag_loop: movzbl (%rsp,%rdx,1), %r13d xorb (%r14,%rdx,1), %r13b @@ -8730,6 +13841,1993 @@ L_AES_GCM_decrypt_avx2_cmp_tag_done: #ifndef __APPLE__ .size AES_GCM_decrypt_avx2,.-AES_GCM_decrypt_avx2 #endif /* __APPLE__ */ +#ifdef WOLFSSL_AESGCM_STREAM +#ifndef __APPLE__ +.text +.globl AES_GCM_init_avx2 +.type AES_GCM_init_avx2,@function +.align 16 +AES_GCM_init_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_init_avx2 +.p2align 4 +_AES_GCM_init_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + movq %rdx, %r10 + movl %ecx, %r11d + movq 24(%rsp), %rax + subq $16, %rsp + vpxor %xmm4, %xmm4, %xmm4 + movl %r11d, %edx + cmpl $12, %edx + je L_AES_GCM_init_avx2_iv_12 + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%rdi), %xmm5 + vaesenc 16(%rdi), %xmm5, %xmm5 + vaesenc 32(%rdi), %xmm5, %xmm5 + vaesenc 48(%rdi), %xmm5, %xmm5 + vaesenc 64(%rdi), %xmm5, %xmm5 + vaesenc 80(%rdi), %xmm5, %xmm5 + vaesenc 96(%rdi), %xmm5, %xmm5 + vaesenc 112(%rdi), %xmm5, %xmm5 + vaesenc 128(%rdi), %xmm5, %xmm5 + vaesenc 144(%rdi), %xmm5, %xmm5 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm0 + jl L_AES_GCM_init_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 176(%rdi), %xmm5, %xmm5 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm0 + jl L_AES_GCM_init_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 208(%rdi), %xmm5, %xmm5 + vmovdqa 224(%rdi), %xmm0 +L_AES_GCM_init_avx2_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_init_avx2_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_init_avx2_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_init_avx2_calc_iv_16_loop: + vmovdqu (%r10,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm6 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm6, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm6, %xmm6 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm6, %xmm6 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm6, %xmm0 + vpshufd $0x4e, %xmm6, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_init_avx2_calc_iv_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_init_avx2_calc_iv_done +L_AES_GCM_init_avx2_calc_iv_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqu %xmm0, (%rsp) +L_AES_GCM_init_avx2_calc_iv_loop: + movzbl (%r10,%rcx,1), %r12d + movb %r12b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_init_avx2_calc_iv_loop + vmovdqu (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm6 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm6, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm6, %xmm6 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm6, %xmm6 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm6, %xmm0 + vpshufd $0x4e, %xmm6, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 +L_AES_GCM_init_avx2_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm6 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm6, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm6, %xmm6 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm6, %xmm6 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm6, %xmm0 + vpshufd $0x4e, %xmm6, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%rdi), %xmm7 + vpxor %xmm4, %xmm7, %xmm7 + vaesenc 16(%rdi), %xmm7, %xmm7 + vaesenc 32(%rdi), %xmm7, %xmm7 + vaesenc 48(%rdi), %xmm7, %xmm7 + vaesenc 64(%rdi), %xmm7, %xmm7 + vaesenc 80(%rdi), %xmm7, %xmm7 + vaesenc 96(%rdi), %xmm7, %xmm7 + vaesenc 112(%rdi), %xmm7, %xmm7 + vaesenc 128(%rdi), %xmm7, %xmm7 + vaesenc 144(%rdi), %xmm7, %xmm7 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm0 + jl L_AES_GCM_init_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm7, %xmm7 + vaesenc 176(%rdi), %xmm7, %xmm7 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm0 + jl L_AES_GCM_init_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm7, %xmm7 + vaesenc 208(%rdi), %xmm7, %xmm7 + vmovdqa 224(%rdi), %xmm0 +L_AES_GCM_init_avx2_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm0, %xmm7, %xmm7 + jmp L_AES_GCM_init_avx2_iv_done +L_AES_GCM_init_avx2_iv_12: + # # Calculate values when IV is 12 bytes + # Set counter based on IV + vmovdqa L_avx2_aes_gcm_bswap_one(%rip), %xmm4 + vmovdqa (%rdi), %xmm5 + vpblendd $7, (%r10), %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa 16(%rdi), %xmm6 + vpxor %xmm5, %xmm4, %xmm7 + vaesenc %xmm6, %xmm5, %xmm5 + vaesenc %xmm6, %xmm7, %xmm7 + vmovdqa 32(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 48(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 64(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 80(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 96(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 112(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 128(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 144(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm0 + jl L_AES_GCM_init_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 176(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm0 + jl L_AES_GCM_init_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 208(%rdi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm7, %xmm7 + vmovdqa 224(%rdi), %xmm0 +L_AES_GCM_init_avx2_calc_iv_12_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vaesenclast %xmm0, %xmm7, %xmm7 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 +L_AES_GCM_init_avx2_iv_done: + vmovdqa %xmm7, (%rax) + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vmovdqa %xmm5, (%r8) + vmovdqa %xmm4, (%r9) + vzeroupper + addq $16, %rsp + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size AES_GCM_init_avx2,.-AES_GCM_init_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_aad_update_avx2 +.type AES_GCM_aad_update_avx2,@function +.align 16 +AES_GCM_aad_update_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_aad_update_avx2 +.p2align 4 +_AES_GCM_aad_update_avx2: +#endif /* __APPLE__ */ + movq %rcx, %rax + vmovdqa (%rdx), %xmm4 + vmovdqa (%rax), %xmm5 + xorl %ecx, %ecx +L_AES_GCM_aad_update_avx2_16_loop: + vmovdqu (%rdi,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm6 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm6, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm6, %xmm6 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm6, %xmm6 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm6, %xmm0 + vpshufd $0x4e, %xmm6, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + addl $16, %ecx + cmpl %esi, %ecx + jl L_AES_GCM_aad_update_avx2_16_loop + vmovdqa %xmm4, (%rdx) + vzeroupper + repz retq +#ifndef __APPLE__ +.size AES_GCM_aad_update_avx2,.-AES_GCM_aad_update_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_block_avx2 +.type AES_GCM_encrypt_block_avx2,@function +.align 16 +AES_GCM_encrypt_block_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_block_avx2 +.p2align 4 +_AES_GCM_encrypt_block_avx2: +#endif /* __APPLE__ */ + movq %rdx, %r10 + movq %rcx, %r11 + subq $0x98, %rsp + vmovdqa (%r8), %xmm3 + # aesenc_block + vmovdqa %xmm3, %xmm1 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1, %xmm0 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm1, %xmm1 + vpxor (%rdi), %xmm0, %xmm0 + vmovdqa 16(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 32(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 48(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 64(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 80(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 96(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 112(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 128(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 144(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa %xmm1, %xmm3 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm1 + jl L_AES_GCM_encrypt_block_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 176(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm1 + jl L_AES_GCM_encrypt_block_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 208(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 224(%rdi), %xmm1 +L_AES_GCM_encrypt_block_avx2_aesenc_block_last: + vaesenclast %xmm1, %xmm0, %xmm0 + vmovdqu (%r11), %xmm1 + vpxor %xmm1, %xmm0, %xmm0 + vmovdqu %xmm0, (%r10) + vmovdqa %xmm3, (%r8) + vzeroupper + addq $0x98, %rsp + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_block_avx2,.-AES_GCM_encrypt_block_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_ghash_block_avx2 +.type AES_GCM_ghash_block_avx2,@function +.align 16 +AES_GCM_ghash_block_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_ghash_block_avx2 +.p2align 4 +_AES_GCM_ghash_block_avx2: +#endif /* __APPLE__ */ + vmovdqa (%rsi), %xmm4 + vmovdqa (%rdx), %xmm5 + vmovdqu (%rdi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm6 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm6, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm6, %xmm6 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm6, %xmm6 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm6, %xmm0 + vpshufd $0x4e, %xmm6, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + vmovdqa %xmm4, (%rsi) + vzeroupper + repz retq +#ifndef __APPLE__ +.size AES_GCM_ghash_block_avx2,.-AES_GCM_ghash_block_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_update_avx2 +.type AES_GCM_encrypt_update_avx2,@function +.align 16 +AES_GCM_encrypt_update_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_update_avx2 +.p2align 4 +_AES_GCM_encrypt_update_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + movq %rdx, %r10 + movq %rcx, %r11 + movq 32(%rsp), %rax + movq 40(%rsp), %r12 + subq $0x98, %rsp + vmovdqa (%r9), %xmm6 + vmovdqa (%rax), %xmm5 + vmovdqa (%r12), %xmm4 + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + xorl %r14d, %r14d + cmpl $0x80, %r8d + movl %r8d, %r13d + jl L_AES_GCM_encrypt_update_avx2_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm4, 128(%rsp) + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm3 + # H ^ 1 and H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm10 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm9, %xmm10, %xmm0 + vmovdqa %xmm5, (%rsp) + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 and H ^ 4 + vpclmulqdq $16, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm10 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm12 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm13 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm2 + vpxor %xmm9, %xmm10, %xmm1 + vmovdqa %xmm1, 32(%rsp) + vmovdqa %xmm2, 48(%rsp) + # H ^ 5 and H ^ 6 + vpclmulqdq $16, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm10 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm9 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm12 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm13 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 64(%rsp) + vmovdqa %xmm0, 80(%rsp) + # H ^ 7 and H ^ 8 + vpclmulqdq $16, %xmm1, %xmm2, %xmm11 + vpclmulqdq $0x01, %xmm1, %xmm2, %xmm10 + vpclmulqdq $0x00, %xmm1, %xmm2, %xmm9 + vpclmulqdq $0x11, %xmm1, %xmm2, %xmm12 + vpclmulqdq $0x00, %xmm2, %xmm2, %xmm13 + vpclmulqdq $0x11, %xmm2, %xmm2, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 96(%rsp) + vmovdqa %xmm0, 112(%rsp) + # First 128 bytes of input + # aesenc_128 + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rdi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 16(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 48(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 64(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 80(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 96(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 128(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 144(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx2_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx2_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_encrypt_update_avx2_aesenc_128_enc_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%r11), %xmm0 + vmovdqu 16(%r11), %xmm1 + vmovdqu 32(%r11), %xmm2 + vmovdqu 48(%r11), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%r10) + vmovdqu %xmm9, 16(%r10) + vmovdqu %xmm10, 32(%r10) + vmovdqu %xmm11, 48(%r10) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%r11), %xmm0 + vmovdqu 80(%r11), %xmm1 + vmovdqu 96(%r11), %xmm2 + vmovdqu 112(%r11), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%r10) + vmovdqu %xmm13, 80(%r10) + vmovdqu %xmm14, 96(%r10) + vmovdqu %xmm15, 112(%r10) + cmpl $0x80, %r13d + movl $0x80, %r14d + jle L_AES_GCM_encrypt_update_avx2_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_update_avx2_ghash_128: + # aesenc_128_ghash + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rdi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + # aesenc_pclmul_1 + vmovdqu -128(%rdx), %xmm1 + vmovdqu 16(%rdi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vmovdqa 112(%rsp), %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm5 + vpclmulqdq $0x01, %xmm2, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm6 + vpclmulqdq $0x11, %xmm2, %xmm1, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_2 + vmovdqu -112(%rdx), %xmm1 + vmovdqa 96(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 32(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -96(%rdx), %xmm1 + vmovdqa 80(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 48(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -80(%rdx), %xmm1 + vmovdqa 64(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 64(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -64(%rdx), %xmm1 + vmovdqa 48(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 80(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -48(%rdx), %xmm1 + vmovdqa 32(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 96(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -32(%rdx), %xmm1 + vmovdqa 16(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 112(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -16(%rdx), %xmm1 + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 128(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_l + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm4, %xmm6, %xmm6 + vpxor %xmm3, %xmm5, %xmm5 + vpslldq $8, %xmm5, %xmm1 + vpsrldq $8, %xmm5, %xmm5 + vmovdqa 144(%rdi), %xmm4 + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm0 + vaesenc %xmm4, %xmm8, %xmm8 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm5, %xmm7, %xmm7 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm9, %xmm9 + vaesenc %xmm4, %xmm10, %xmm10 + vaesenc %xmm4, %xmm11, %xmm11 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm12, %xmm12 + vaesenc %xmm4, %xmm13, %xmm13 + vaesenc %xmm4, %xmm14, %xmm14 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm7, %xmm6, %xmm6 + vaesenc %xmm4, %xmm15, %xmm15 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_encrypt_update_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_encrypt_update_avx2_aesenc_128_ghash_avx_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vmovdqu 96(%rcx), %xmm2 + vmovdqu 112(%rcx), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + # aesenc_128_ghash - end + addl $0x80, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_encrypt_update_avx2_ghash_128 +L_AES_GCM_encrypt_update_avx2_end_128: + vmovdqa L_avx2_aes_gcm_bswap_mask(%rip), %xmm4 + vpshufb %xmm4, %xmm8, %xmm8 + vpshufb %xmm4, %xmm9, %xmm9 + vpshufb %xmm4, %xmm10, %xmm10 + vpshufb %xmm4, %xmm11, %xmm11 + vpshufb %xmm4, %xmm12, %xmm12 + vpshufb %xmm4, %xmm13, %xmm13 + vpshufb %xmm4, %xmm14, %xmm14 + vpshufb %xmm4, %xmm15, %xmm15 + vpxor %xmm6, %xmm8, %xmm8 + vmovdqu (%rsp), %xmm7 + vpclmulqdq $16, %xmm15, %xmm7, %xmm5 + vpclmulqdq $0x01, %xmm15, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm15, %xmm7, %xmm4 + vpclmulqdq $0x11, %xmm15, %xmm7, %xmm6 + vpxor %xmm1, %xmm5, %xmm5 + vmovdqu 16(%rsp), %xmm7 + vpclmulqdq $16, %xmm14, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm14, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm14, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm14, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 32(%rsp), %xmm15 + vmovdqu 48(%rsp), %xmm7 + vpclmulqdq $16, %xmm13, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm13, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm13, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm13, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm12, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm12, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm12, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm12, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 64(%rsp), %xmm15 + vmovdqu 80(%rsp), %xmm7 + vpclmulqdq $16, %xmm11, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm11, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm11, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm11, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm10, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm10, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm10, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm10, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 96(%rsp), %xmm15 + vmovdqu 112(%rsp), %xmm7 + vpclmulqdq $16, %xmm9, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm9, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm9, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm9, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm8, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm8, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm8, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm8, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpslldq $8, %xmm5, %xmm7 + vpsrldq $8, %xmm5, %xmm5 + vpxor %xmm7, %xmm4, %xmm4 + vpxor %xmm5, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm4, %xmm0 + vpshufd $0x4e, %xmm4, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa (%rsp), %xmm5 + vmovdqu 128(%rsp), %xmm4 +L_AES_GCM_encrypt_update_avx2_done_128: + cmpl %r8d, %r14d + je L_AES_GCM_encrypt_update_avx2_done_enc + movl %r8d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %r14d + jge L_AES_GCM_encrypt_update_avx2_last_block_done + # aesenc_block + vmovdqa %xmm4, %xmm1 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1, %xmm0 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm1, %xmm1 + vpxor (%rdi), %xmm0, %xmm0 + vmovdqa 16(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 32(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 48(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 64(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 80(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 96(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 112(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 128(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 144(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa %xmm1, %xmm4 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm1 + jl L_AES_GCM_encrypt_update_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 176(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm1 + jl L_AES_GCM_encrypt_update_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 208(%rdi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 224(%rdi), %xmm1 +L_AES_GCM_encrypt_update_avx2_aesenc_block_last: + vaesenclast %xmm1, %xmm0, %xmm0 + vmovdqu (%r11,%r14,1), %xmm1 + vpxor %xmm1, %xmm0, %xmm0 + vmovdqu %xmm0, (%r10,%r14,1) + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + addl $16, %r14d + cmpl %r13d, %r14d + jge L_AES_GCM_encrypt_update_avx2_last_block_ghash +L_AES_GCM_encrypt_update_avx2_last_block_start: + vmovdqu (%r11,%r14,1), %xmm12 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm11 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + # aesenc_gfmul_sb + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm2 + vpclmulqdq $16, %xmm5, %xmm6, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm8 + vpxor (%rdi), %xmm11, %xmm11 + vaesenc 16(%rdi), %xmm11, %xmm11 + vpxor %xmm2, %xmm3, %xmm3 + vpslldq $8, %xmm3, %xmm2 + vpsrldq $8, %xmm3, %xmm3 + vaesenc 32(%rdi), %xmm11, %xmm11 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 48(%rdi), %xmm11, %xmm11 + vaesenc 64(%rdi), %xmm11, %xmm11 + vaesenc 80(%rdi), %xmm11, %xmm11 + vpshufd $0x4e, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 96(%rdi), %xmm11, %xmm11 + vaesenc 112(%rdi), %xmm11, %xmm11 + vaesenc 128(%rdi), %xmm11, %xmm11 + vpshufd $0x4e, %xmm2, %xmm2 + vaesenc 144(%rdi), %xmm11, %xmm11 + vpxor %xmm3, %xmm8, %xmm8 + vpxor %xmm8, %xmm2, %xmm2 + vmovdqa 160(%rdi), %xmm0 + cmpl $11, %esi + jl L_AES_GCM_encrypt_update_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc 176(%rdi), %xmm11, %xmm11 + vmovdqa 192(%rdi), %xmm0 + cmpl $13, %esi + jl L_AES_GCM_encrypt_update_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc 208(%rdi), %xmm11, %xmm11 + vmovdqa 224(%rdi), %xmm0 +L_AES_GCM_encrypt_update_avx2_aesenc_gfmul_sb_last: + vaesenclast %xmm0, %xmm11, %xmm11 + vpxor %xmm1, %xmm2, %xmm6 + vpxor %xmm12, %xmm11, %xmm11 + vmovdqu %xmm11, (%r10,%r14,1) + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + addl $16, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_encrypt_update_avx2_last_block_start +L_AES_GCM_encrypt_update_avx2_last_block_ghash: + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm10 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm9 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm9, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm9 + vpsrldq $8, %xmm10, %xmm10 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm10, %xmm6, %xmm6 + vpxor %xmm9, %xmm6, %xmm6 + vpxor %xmm8, %xmm6, %xmm6 +L_AES_GCM_encrypt_update_avx2_last_block_done: +L_AES_GCM_encrypt_update_avx2_done_enc: + vmovdqa %xmm6, (%r9) + vmovdqa %xmm4, (%r12) + vzeroupper + addq $0x98, %rsp + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_update_avx2,.-AES_GCM_encrypt_update_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_final_avx2 +.type AES_GCM_encrypt_final_avx2,@function +.align 16 +AES_GCM_encrypt_final_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_final_avx2 +.p2align 4 +_AES_GCM_encrypt_final_avx2: +#endif /* __APPLE__ */ + pushq %r13 + movl %ecx, %r10d + movl %r8d, %r11d + movq 16(%rsp), %rax + subq $16, %rsp + vmovdqa (%rdi), %xmm4 + vmovdqa (%r9), %xmm5 + vmovdqa (%rax), %xmm6 + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + # calc_tag + shlq $3, %r10 + vpinsrq $0x00, %r10, %xmm0, %xmm0 + shlq $3, %r11 + vpinsrq $0x01, %r11, %xmm1, %xmm1 + vpblendd $12, %xmm1, %xmm0, %xmm0 + vpxor %xmm4, %xmm0, %xmm0 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm0, %xmm7 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm2 + vpxor %xmm3, %xmm7, %xmm7 + vpslldq $8, %xmm7, %xmm3 + vpsrldq $8, %xmm7, %xmm7 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm0 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm7, %xmm0, %xmm0 + vpxor %xmm3, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm6, %xmm0, %xmm0 + # store_tag + cmpl $16, %edx + je L_AES_GCM_encrypt_final_avx2_store_tag_16 + xorq %rcx, %rcx + vmovdqu %xmm0, (%rsp) +L_AES_GCM_encrypt_final_avx2_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%rsi,%rcx,1) + incl %ecx + cmpl %edx, %ecx + jne L_AES_GCM_encrypt_final_avx2_store_tag_loop + jmp L_AES_GCM_encrypt_final_avx2_store_tag_done +L_AES_GCM_encrypt_final_avx2_store_tag_16: + vmovdqu %xmm0, (%rsi) +L_AES_GCM_encrypt_final_avx2_store_tag_done: + vzeroupper + addq $16, %rsp + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_final_avx2,.-AES_GCM_encrypt_final_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_update_avx2 +.type AES_GCM_decrypt_update_avx2,@function +.align 16 +AES_GCM_decrypt_update_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_update_avx2 +.p2align 4 +_AES_GCM_decrypt_update_avx2: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + movq %rdx, %r10 + movq %rcx, %r11 + movq 32(%rsp), %rax + movq 40(%rsp), %r12 + subq $0xa8, %rsp + vmovdqa (%r9), %xmm6 + vmovdqa (%rax), %xmm5 + vmovdqa (%r12), %xmm4 + # Calculate H + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + xorl %r14d, %r14d + cmpl $0x80, %r8d + movl %r8d, %r13d + jl L_AES_GCM_decrypt_update_avx2_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm4, 128(%rsp) + vmovdqa %xmm15, 144(%rsp) + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm3 + # H ^ 1 and H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm10 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm9, %xmm10, %xmm0 + vmovdqa %xmm5, (%rsp) + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 and H ^ 4 + vpclmulqdq $16, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm10 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm12 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm13 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm2 + vpxor %xmm9, %xmm10, %xmm1 + vmovdqa %xmm1, 32(%rsp) + vmovdqa %xmm2, 48(%rsp) + # H ^ 5 and H ^ 6 + vpclmulqdq $16, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm10 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm9 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm12 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm13 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 64(%rsp) + vmovdqa %xmm0, 80(%rsp) + # H ^ 7 and H ^ 8 + vpclmulqdq $16, %xmm1, %xmm2, %xmm11 + vpclmulqdq $0x01, %xmm1, %xmm2, %xmm10 + vpclmulqdq $0x00, %xmm1, %xmm2, %xmm9 + vpclmulqdq $0x11, %xmm1, %xmm2, %xmm12 + vpclmulqdq $0x00, %xmm2, %xmm2, %xmm13 + vpclmulqdq $0x11, %xmm2, %xmm2, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 96(%rsp) + vmovdqa %xmm0, 112(%rsp) +L_AES_GCM_decrypt_update_avx2_ghash_128: + # aesenc_128_ghash + leaq (%r11,%r14,1), %rcx + leaq (%r10,%r14,1), %rdx + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rdi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + # aesenc_pclmul_1 + vmovdqu (%rcx), %xmm1 + vmovdqu 16(%rdi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vmovdqa 112(%rsp), %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm5 + vpclmulqdq $0x01, %xmm2, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm6 + vpclmulqdq $0x11, %xmm2, %xmm1, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_2 + vmovdqu 16(%rcx), %xmm1 + vmovdqa 96(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 32(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 32(%rcx), %xmm1 + vmovdqa 80(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 48(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 48(%rcx), %xmm1 + vmovdqa 64(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 64(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 64(%rcx), %xmm1 + vmovdqa 48(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 80(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 80(%rcx), %xmm1 + vmovdqa 32(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 96(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 96(%rcx), %xmm1 + vmovdqa 16(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 112(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 112(%rcx), %xmm1 + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 128(%rdi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_l + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm4, %xmm6, %xmm6 + vpxor %xmm3, %xmm5, %xmm5 + vpslldq $8, %xmm5, %xmm1 + vpsrldq $8, %xmm5, %xmm5 + vmovdqa 144(%rdi), %xmm4 + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm0 + vaesenc %xmm4, %xmm8, %xmm8 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm5, %xmm7, %xmm7 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm9, %xmm9 + vaesenc %xmm4, %xmm10, %xmm10 + vaesenc %xmm4, %xmm11, %xmm11 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm12, %xmm12 + vaesenc %xmm4, %xmm13, %xmm13 + vaesenc %xmm4, %xmm14, %xmm14 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm7, %xmm6, %xmm6 + vaesenc %xmm4, %xmm15, %xmm15 + cmpl $11, %esi + vmovdqa 160(%rdi), %xmm7 + jl L_AES_GCM_decrypt_update_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %esi + vmovdqa 192(%rdi), %xmm7 + jl L_AES_GCM_decrypt_update_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rdi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rdi), %xmm7 +L_AES_GCM_decrypt_update_avx2_aesenc_128_ghash_avx_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vmovdqu 96(%rcx), %xmm2 + vmovdqu 112(%rcx), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + # aesenc_128_ghash - end + addl $0x80, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_decrypt_update_avx2_ghash_128 + vmovdqa (%rsp), %xmm5 + vmovdqa 128(%rsp), %xmm4 + vmovdqa 144(%rsp), %xmm15 +L_AES_GCM_decrypt_update_avx2_done_128: + cmpl %r8d, %r14d + jge L_AES_GCM_decrypt_update_avx2_done_dec + movl %r8d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %r14d + jge L_AES_GCM_decrypt_update_avx2_last_block_done +L_AES_GCM_decrypt_update_avx2_last_block_start: + vmovdqu (%r11,%r14,1), %xmm11 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm10 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm11, %xmm12 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm6, %xmm12, %xmm12 + # aesenc_gfmul_sb + vpclmulqdq $0x01, %xmm5, %xmm12, %xmm2 + vpclmulqdq $16, %xmm5, %xmm12, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm12, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm12, %xmm8 + vpxor (%rdi), %xmm10, %xmm10 + vaesenc 16(%rdi), %xmm10, %xmm10 + vpxor %xmm2, %xmm3, %xmm3 + vpslldq $8, %xmm3, %xmm2 + vpsrldq $8, %xmm3, %xmm3 + vaesenc 32(%rdi), %xmm10, %xmm10 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 48(%rdi), %xmm10, %xmm10 + vaesenc 64(%rdi), %xmm10, %xmm10 + vaesenc 80(%rdi), %xmm10, %xmm10 + vpshufd $0x4e, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 96(%rdi), %xmm10, %xmm10 + vaesenc 112(%rdi), %xmm10, %xmm10 + vaesenc 128(%rdi), %xmm10, %xmm10 + vpshufd $0x4e, %xmm2, %xmm2 + vaesenc 144(%rdi), %xmm10, %xmm10 + vpxor %xmm3, %xmm8, %xmm8 + vpxor %xmm8, %xmm2, %xmm2 + vmovdqa 160(%rdi), %xmm0 + cmpl $11, %esi + jl L_AES_GCM_decrypt_update_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc 176(%rdi), %xmm10, %xmm10 + vmovdqa 192(%rdi), %xmm0 + cmpl $13, %esi + jl L_AES_GCM_decrypt_update_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc 208(%rdi), %xmm10, %xmm10 + vmovdqa 224(%rdi), %xmm0 +L_AES_GCM_decrypt_update_avx2_aesenc_gfmul_sb_last: + vaesenclast %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm2, %xmm6 + vpxor %xmm11, %xmm10, %xmm10 + vmovdqu %xmm10, (%r10,%r14,1) + addl $16, %r14d + cmpl %r13d, %r14d + jl L_AES_GCM_decrypt_update_avx2_last_block_start +L_AES_GCM_decrypt_update_avx2_last_block_done: +L_AES_GCM_decrypt_update_avx2_done_dec: + vmovdqa %xmm6, (%r9) + vmovdqa %xmm4, (%r12) + vzeroupper + addq $0xa8, %rsp + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_update_avx2,.-AES_GCM_decrypt_update_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_final_avx2 +.type AES_GCM_decrypt_final_avx2,@function +.align 16 +AES_GCM_decrypt_final_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_final_avx2 +.p2align 4 +_AES_GCM_decrypt_final_avx2: +#endif /* __APPLE__ */ + pushq %r13 + pushq %rbp + movl %ecx, %r10d + movl %r8d, %r11d + movq 24(%rsp), %rax + movq 32(%rsp), %rbp + subq $16, %rsp + vmovdqa (%rdi), %xmm4 + vmovdqa (%r9), %xmm5 + vmovdqa (%rax), %xmm6 + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + # calc_tag + shlq $3, %r10 + vpinsrq $0x00, %r10, %xmm0, %xmm0 + shlq $3, %r11 + vpinsrq $0x01, %r11, %xmm1, %xmm1 + vpblendd $12, %xmm1, %xmm0, %xmm0 + vpxor %xmm4, %xmm0, %xmm0 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm0, %xmm7 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm2 + vpxor %xmm3, %xmm7, %xmm7 + vpslldq $8, %xmm7, %xmm3 + vpsrldq $8, %xmm7, %xmm7 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm0 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm7, %xmm0, %xmm0 + vpxor %xmm3, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm6, %xmm0, %xmm0 + # cmp_tag + cmpl $16, %edx + je L_AES_GCM_decrypt_final_avx2_cmp_tag_16 + xorq %rcx, %rcx + xorq %r9, %r9 + vmovdqu %xmm0, (%rsp) +L_AES_GCM_decrypt_final_avx2_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%rsi,%rcx,1), %r13b + orb %r13b, %r9b + incl %ecx + cmpl %edx, %ecx + jne L_AES_GCM_decrypt_final_avx2_cmp_tag_loop + cmpb $0x00, %r9b + sete %r9b + jmp L_AES_GCM_decrypt_final_avx2_cmp_tag_done +L_AES_GCM_decrypt_final_avx2_cmp_tag_16: + vmovdqu (%rsi), %xmm1 + vpcmpeqb %xmm1, %xmm0, %xmm0 + vpmovmskb %xmm0, %rcx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %r9d, %r9d + cmpl $0xffff, %ecx + sete %r9b +L_AES_GCM_decrypt_final_avx2_cmp_tag_done: + movl %r9d, (%rbp) + vzeroupper + addq $16, %rsp + popq %rbp + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_final_avx2,.-AES_GCM_decrypt_final_avx2 +#endif /* __APPLE__ */ +#endif /* WOLFSSL_AESGCM_STREAM */ #endif /* HAVE_INTEL_AVX2 */ #if defined(__linux__) && defined(__ELF__) diff --git a/wolfcrypt/src/arc4.c b/wolfcrypt/src/arc4.c index 7eb8268e3..05c91dce3 100644 --- a/wolfcrypt/src/arc4.c +++ b/wolfcrypt/src/arc4.c @@ -1,6 +1,6 @@ /* arc4.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/asm.c b/wolfcrypt/src/asm.c index 0af4447c7..b7f53d073 100644 --- a/wolfcrypt/src/asm.c +++ b/wolfcrypt/src/asm.c @@ -1,6 +1,6 @@ /* asm.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index c645e2666..9213486ef 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1,6 +1,6 @@ /* asn.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -114,6 +114,10 @@ ASN Options: #include #endif +#ifdef WOLFSSL_QNX_CAAM + #include +#endif + #ifndef NO_RSA #include #if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) @@ -384,6 +388,7 @@ static int SetASNNull(byte* output) return 2; } +#ifndef NO_CERTS /* Get the DER/BER encoding of an ASN.1 BOOLEAN. * * input Buffer holding DER/BER encoded data. @@ -413,7 +418,7 @@ static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx) *inOutIdx = idx; return b; } - +#endif /* !NO_CERTS*/ #ifdef ASN1_SET_BOOLEAN /* Set the DER/BER encoding of the ASN.1 NULL element. * Note: Function not required as yet. @@ -497,6 +502,7 @@ static int GetASNInt(const byte* input, word32* inOutIdx, int* len, return 0; } +#ifndef NO_CERTS /* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than * 7 bits. * @@ -526,7 +532,7 @@ static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx) *inOutIdx = idx; return b; } - +#endif /* !NO_CERTS */ #if !defined(NO_DSA) && !defined(NO_SHA) static const char sigSha1wDsaName[] = "SHAwDSA"; @@ -678,6 +684,7 @@ int SetASNInt(int len, byte firstByte, byte* output) #if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_CERT_GEN) && \ !defined(NO_RSA)) || ((defined(WOLFSSL_KEY_GEN) || \ + (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || \ defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) /* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int. * The number is assumed to be positive. @@ -906,7 +913,7 @@ int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) if (mp_init(mpi) != MP_OKAY) return MP_INIT_E; - if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) { + if (mp_read_unsigned_bin(mpi, input + idx, length) != 0) { mp_clear(mpi); return ASN_GETINT_E; } @@ -1458,6 +1465,18 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef WOLFSSL_SHA512 static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; #endif +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + static const byte hashSha3_224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 7}; +#endif +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + static const byte hashSha3_256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 8}; +#endif +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + static const byte hashSha3_384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 9}; +#endif +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + static const byte hashSha3_512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 10}; +#endif /* hmacType */ #ifndef NO_HMAC @@ -1759,6 +1778,32 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(hashSha512hOid); break; #endif + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + case SHA3_224h: + oid = hashSha3_224hOid; + *oidSz = sizeof(hashSha3_224hOid); + break; + #endif + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + case SHA3_256h: + oid = hashSha3_256hOid; + *oidSz = sizeof(hashSha3_256hOid); + break; + #endif + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + case SHA3_384h: + oid = hashSha3_384hOid; + *oidSz = sizeof(hashSha3_384hOid); + break; + #endif + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + case SHA3_512h: + oid = hashSha3_512hOid; + *oidSz = sizeof(hashSha3_512hOid); + break; + #endif + default: + break; } break; @@ -1996,6 +2041,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(blkDes3CbcOid); break; #endif /* !NO_DES3 */ + default: + break; } break; @@ -2010,6 +2057,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = ocspNonceOid; *oidSz = sizeof(ocspNonceOid); break; + default: + break; } break; #endif /* HAVE_OCSP */ @@ -2068,6 +2117,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(ocspNoCheckOid); break; #endif + default: + break; } break; @@ -2078,6 +2129,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAuthKeyOid; *oidSz = sizeof(extAuthKeyOid); break; + default: + break; } #endif break; @@ -2094,6 +2147,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAuthInfoCaIssuerOid; *oidSz = sizeof(extAuthInfoCaIssuerOid); break; + default: + break; } break; @@ -2103,6 +2158,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extCertPolicyAnyOid; *oidSz = sizeof(extCertPolicyAnyOid); break; + default: + break; } break; @@ -2112,6 +2169,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extAltNamesHwNameOid; *oidSz = sizeof(extAltNamesHwNameOid); break; + default: + break; } break; @@ -2145,6 +2204,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extExtKeyUsageOcspSignOid; *oidSz = sizeof(extExtKeyUsageOcspSignOid); break; + default: + break; } break; @@ -2154,6 +2215,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = pbkdf2Oid; *oidSz = sizeof(pbkdf2Oid); break; + default: + break; } break; @@ -2182,6 +2245,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = pbes2; *oidSz = sizeof(pbes2); break; + default: + break; } break; @@ -2211,6 +2276,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(wrapPwriKekOid); break; #endif + default: + break; } break; @@ -2246,6 +2313,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid); break; #endif + default: + break; } break; @@ -2276,6 +2345,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(hmacSha512Oid); break; #endif + default: + break; } break; #endif /* !NO_HMAC */ @@ -2287,6 +2358,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = zlibCompress; *oidSz = sizeof(zlibCompress); break; + default: + break; } break; #endif /* HAVE_LIBZ */ @@ -2297,6 +2370,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = dnsSRVOid; *oidSz = sizeof(dnsSRVOid); break; + default: + break; } break; case oidTlsExtType: @@ -2305,6 +2380,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = tlsFeatureOid; *oidSz = sizeof(tlsFeatureOid); break; + default: + break; } break; #endif /* WOLFSSL_APACHE_HTTPD */ @@ -2319,6 +2396,8 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = attrSerialNumberOid; *oidSz = sizeof(attrSerialNumberOid); break; + default: + break; } break; #endif @@ -2771,7 +2850,7 @@ int ToTraditional(byte* input, word32 sz) #endif /* HAVE_PKCS8 || HAVE_PKCS12 */ -#ifdef HAVE_PKCS8 +#if defined(HAVE_PKCS8) && !defined(NO_CERTS) /* find beginning of traditional key inside PKCS#8 unencrypted buffer * return traditional length on success, with inOutIdx at beginning of @@ -2865,7 +2944,6 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, * no header information just INTEGER */ sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); tmpSz += sz; keyIdx += sz; - /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ if (curveOID != NULL && oidSz > 0) { @@ -2901,7 +2979,7 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, return tmpSz + sz; } -#endif /* HAVE_PKCS8 */ +#endif /* HAVE_PKCS8 && !NO_CERTS */ #if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY) /* check that the private key is a pair for the public key @@ -3496,8 +3574,7 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { WOLFSSL_MSG("Error generating random salt"); #ifdef WOLFSSL_SMALL_STACK - if (saltTmp != NULL) - XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -3698,43 +3775,75 @@ static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id, return ret; } -/* Converts Encrypted PKCS#8 to 'traditional' (i.e. PKCS#8 removed from - * decrypted key.) +/* PKCS#8 encryption from RFC 5208 + * This function takes in an unencrypted PKCS#8 DER key and converts it to + * PKCS#8 encrypted format. The resulting encrypted key can be decrypted using + * wc_DecryptPKCS8Key. + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData } + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * EncryptedData ::= OCTET STRING + * + * key DER buffer containing the unencrypted PKCS#8 key. + * keySz The size of the key buffer. + * out The buffer to place the encrypted key in. + * outSz The size of the out buffer. + * password The password to use for the password-based encryption algorithm. + * passwordSz The length of the password (not including the NULL terminator). + * vPKCS The PKCS version to use. Can be 1 for PKCS12 or PKCS5. + * pbeOid The OID of the PBE scheme to use (e.g. PBES2 or one of the OIDs + for PBES1 in RFC 2898 A.3) + * encAlgId The encryption algorithm ID to use (e.g. AES256CBCb). + * salt The salt buffer to use. If NULL, a random salt will be used. + * saltSz The length of the salt buffer. Can be 0 if passing NULL for salt. + * itt The number of iterations to use for the KDF. + * rng A pointer to an initialized WC_RNG object. + * heap A pointer to the heap use for dynamic allocation. Can be NULL. + * + * Returns the size of the encrypted key placed in out. In error cases, returns + * negative values. */ -int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, - const char* password, int passwordSz, int vPKCS, int vAlgo, +int wc_EncryptPKCS8Key(byte* key, word32 keySz, byte* out, word32 outSz, + const char* password, int passwordSz, int vPKCS, int pbeOid, int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap) { - int ret = 0; - int version, blockSz, id; - word32 idx = 0, encIdx; #ifdef WOLFSSL_SMALL_STACK byte* saltTmp = NULL; #else byte saltTmp[MAX_SALT_SIZE]; #endif - byte cbcIv[MAX_IV_SIZE]; - byte *pkcs8Key = NULL; - word32 pkcs8KeySz = 0, padSz = 0; - int algId = 0; - const byte* curveOid = NULL; - word32 curveOidSz = 0; - const byte* pbeOid = NULL; - word32 pbeOidSz = 0; + int ret = 0; + int version = 0; + int pbeId = 0; + int blockSz = 0; const byte* encOid = NULL; int encOidSz = 0; - word32 pbeLen = 0, kdfLen = 0, encLen = 0; - word32 innerLen = 0, outerLen; + word32 padSz = 0; + word32 innerLen = 0; + word32 outerLen = 0; + const byte* pbeOidBuf = NULL; + word32 pbeOidBufSz = 0; + word32 pbeLen = 0; + word32 kdfLen = 0; + word32 encLen = 0; + byte cbcIv[MAX_IV_SIZE]; + word32 idx = 0; + word32 encIdx = 0; - ret = CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz); - /* create random salt if one not provided */ + (void)heap; + + WOLFSSL_ENTER("wc_EncryptPKCS8Key"); + + ret = CheckAlgo(vPKCS, pbeOid, &pbeId, &version, &blockSz); if (ret == 0 && (salt == NULL || saltSz == 0)) { saltSz = 8; #ifdef WOLFSSL_SMALL_STACK saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (saltTmp == NULL) - return MEMORY_E; + ret = MEMORY_E; #endif salt = saltTmp; @@ -3743,52 +3852,25 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, #ifdef WOLFSSL_SMALL_STACK XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ret; - } - } - - if (ret == 0) { - /* check key type and get OID if ECC */ - ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap); - if (ret == 1) - ret = 0; - } - if (ret == 0) { - ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid, - curveOidSz); - if (ret == LENGTH_ONLY_E) - ret = 0; - } - if (ret == 0) { - pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (pkcs8Key == NULL) - ret = MEMORY_E; - } - if (ret == 0) { - ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId, - curveOid, curveOidSz); - if (ret >= 0) { - pkcs8KeySz = ret; - ret = 0; } } if (ret == 0 && version == PKCS5v2) - ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &id, &blockSz); + ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &pbeId, &blockSz); if (ret == 0) { - padSz = (blockSz - (pkcs8KeySz & (blockSz - 1))) & (blockSz - 1); + padSz = (blockSz - (keySz & (blockSz - 1))) & (blockSz - 1); /* inner = OCT salt INT itt */ innerLen = 2 + saltSz + 2 + (itt < 256 ? 1 : 2); if (version != PKCS5v2) { - pbeOid = OidFromId(id, oidPBEType, &pbeOidSz); + pbeOidBuf = OidFromId(pbeId, oidPBEType, &pbeOidBufSz); /* pbe = OBJ pbse1 SEQ [ inner ] */ - pbeLen = 2 + pbeOidSz + 2 + innerLen; + pbeLen = 2 + pbeOidBufSz + 2 + innerLen; } else { - pbeOid = pbes2; - pbeOidSz = sizeof(pbes2); + pbeOidBuf = pbes2; + pbeOidBufSz = sizeof(pbes2); /* kdf = OBJ pbkdf2 [ SEQ innerLen ] */ kdfLen = 2 + sizeof(pbkdf2Oid) + 2 + innerLen; /* enc = OBJ enc_alg OCT iv */ @@ -3802,35 +3884,35 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, if (ret == 0) { /* outer = SEQ [ pbe ] OCT encrypted_PKCS#8_key */ outerLen = 2 + pbeLen; - outerLen += SetOctetString(pkcs8KeySz + padSz, out); - outerLen += pkcs8KeySz + padSz; + outerLen += SetOctetString(keySz + padSz, out); + outerLen += keySz + padSz; idx += SetSequence(outerLen, out + idx); - encIdx = idx + outerLen - pkcs8KeySz - padSz; + encIdx = idx + outerLen - keySz - padSz; /* Put Encrypted content in place. */ - XMEMCPY(out + encIdx, pkcs8Key, pkcs8KeySz); + XMEMCPY(out + encIdx, key, keySz); if (padSz > 0) { - XMEMSET(out + encIdx + pkcs8KeySz, padSz, padSz); - pkcs8KeySz += padSz; + XMEMSET(out + encIdx + keySz, padSz, padSz); + keySz += padSz; } - ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, - out + encIdx, pkcs8KeySz, version, cbcIv, 1, 0); + ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, pbeId, + out + encIdx, keySz, version, cbcIv, 1, 0); } if (ret == 0) { if (version != PKCS5v2) { /* PBE algorithm */ idx += SetSequence(pbeLen, out + idx); - idx += SetObjectId(pbeOidSz, out + idx); - XMEMCPY(out + idx, pbeOid, pbeOidSz); - idx += pbeOidSz; + idx += SetObjectId(pbeOidBufSz, out + idx); + XMEMCPY(out + idx, pbeOidBuf, pbeOidBufSz); + idx += pbeOidBufSz; } else { /* PBES2 algorithm identifier */ idx += SetSequence(pbeLen, out + idx); - idx += SetObjectId(pbeOidSz, out + idx); - XMEMCPY(out + idx, pbeOid, pbeOidSz); - idx += pbeOidSz; + idx += SetObjectId(pbeOidBufSz, out + idx); + XMEMCPY(out + idx, pbeOidBuf, pbeOidBufSz); + idx += pbeOidBufSz; /* PBES2 Parameters: SEQ [ kdf ] SEQ [ enc ] */ idx += SetSequence(2 + kdfLen + 2 + encLen, out + idx); /* KDF Algorithm Identifier */ @@ -3842,7 +3924,7 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, idx += SetSequence(innerLen, out + idx); idx += SetOctetString(saltSz, out + idx); XMEMCPY(out + idx, salt, saltSz); idx += saltSz; - ret = SetShortInt(out, &idx, itt, *outSz); + ret = SetShortInt(out, &idx, itt, outSz); if (ret > 0) ret = 0; } @@ -3858,23 +3940,115 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, XMEMCPY(out + idx, cbcIv, blockSz); idx += blockSz; } - idx += SetOctetString(pkcs8KeySz, out + idx); + idx += SetOctetString(keySz, out + idx); /* Default PRF - no need to write out OID */ - idx += pkcs8KeySz; + idx += keySz; ret = idx; } - if (pkcs8Key != NULL) { - ForceZero(pkcs8Key, pkcs8KeySz); - XFREE(pkcs8Key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #ifdef WOLFSSL_SMALL_STACK if (saltTmp != NULL) { XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif + WOLFSSL_LEAVE("wc_EncryptPKCS8Key", ret); + + return ret; +} + +/* PKCS#8 decryption from RFC 5208 + * + * NOTE: input buffer is overwritten with decrypted data! + * + * This function takes an encrypted PKCS#8 DER key and decrypts it to PKCS#8 + * unencrypted DER. Undoes the encryption done by wc_EncryptPKCS8Key. Returns + * the length of the decrypted buffer or a negative value if there was an error. + */ +int wc_DecryptPKCS8Key(byte* input, word32 sz, const char* password, + int passwordSz) +{ + int ret; + int length; + word32 inOutIdx = 0; + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ret = ASN_PARSE_E; + } + else { + ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password, + passwordSz); + if (ret > 0) { + XMEMMOVE(input, input + inOutIdx, ret); + } + } + + if (ret > 0) { + /* DecryptContent will decrypt the data, but it will leave any padding + * bytes intact. This code calculates the length without the padding + * and we return that to the user. */ + inOutIdx = 0; + if (GetSequence(input, &inOutIdx, &length, ret) < 0) { + ret = ASN_PARSE_E; + } + else { + ret = inOutIdx + length; + } + } + + return ret; +} + +/* Takes an unencrypted, traditional DER-encoded key and converts it to a PKCS#8 + * encrypted key. */ +int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng, + void* heap) +{ + int ret = 0; + byte *pkcs8Key = NULL; + word32 pkcs8KeySz = 0; + int algId = 0; + const byte* curveOid = NULL; + word32 curveOidSz = 0; + + if (ret == 0) { + /* check key type and get OID if ECC */ + ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap); + if (ret == 1) + ret = 0; + } + if (ret == 0) { + ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid, + curveOidSz); + if (ret == LENGTH_ONLY_E) + ret = 0; + } + if (ret == 0) { + pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs8Key == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId, + curveOid, curveOidSz); + if (ret >= 0) { + pkcs8KeySz = ret; + ret = 0; + } + } + if (ret == 0) { + ret = wc_EncryptPKCS8Key(pkcs8Key, pkcs8KeySz, out, *outSz, password, + passwordSz, vPKCS, vAlgo, encAlgId, salt, saltSz, itt, rng, heap); + } + + if (pkcs8Key != NULL) { + ForceZero(pkcs8Key, pkcs8KeySz); + XFREE(pkcs8Key, heap, DYNAMIC_TYPE_TMP_BUFFER); + } + (void)rng; return ret; @@ -4051,25 +4225,16 @@ exit_dc: return ret; } - /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning of input */ -int ToTraditionalEnc(byte* input, word32 sz,const char* password, +int ToTraditionalEnc(byte* input, word32 sz, const char* password, int passwordSz, word32* algId) { - int ret, length; - word32 inOutIdx = 0; + int ret; - if (GetSequence(input, &inOutIdx, &length, sz) < 0) { - ret = ASN_PARSE_E; - } - else { - ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password, - passwordSz); - if (ret > 0) { - XMEMMOVE(input, input + inOutIdx, ret); - ret = ToTraditional_ex(input, ret, algId); - } + ret = wc_DecryptPKCS8Key(input, sz, password, passwordSz); + if (ret > 0) { + ret = ToTraditional_ex(input, ret, algId); } return ret; @@ -4174,7 +4339,13 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, seqSz += sz; tmpIdx = 0; - seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr); + ret = SetShortInt(shr, &tmpIdx, itt, maxShr); + if (ret >= 0) { + seqSz += ret; + } + else { + return ret; + } innerSz += seqSz + SetSequence(seqSz, seq); totalSz += innerSz + SetSequence(innerSz, seq); @@ -4515,6 +4686,60 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, #endif /* !NO_RSA */ #ifndef NO_DH +#if defined(WOLFSSL_DH_EXTRA) +/* + * Decodes DH public key to fill specified DhKey. + * + * return 0 on success, negative on failure + */ +int wc_DhPublicKeyDecode(const byte* input, word32* inOutIdx, + DhKey* key, word32 inSz) +{ + int ret = 0; + int length; + word32 oid = 0; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + ret = GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz); + if (oid != DHk || ret < 0) + return ASN_DH_KEY_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0) + return ASN_DH_KEY_E; + + if (GetInt(&key->g, input, inOutIdx, inSz) < 0) { + mp_clear(&key->p); + return ASN_DH_KEY_E; + } + ret = (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) == 0); + if (ret > 0) { + /* Found Bit String WOLFSSL_DH_EXTRA is required to access DhKey.pub */ + if (GetInt(&key->pub, input, inOutIdx, inSz) < 0) { + mp_clear(&key->p); + mp_clear(&key->g); + return ASN_DH_KEY_E; + } + } + else { + mp_clear(&key->p); + mp_clear(&key->g); + return ASN_DH_KEY_E; + } + return 0; +} +#endif /* WOLFSSL_DH_EXTRA */ + /* Supports either: * - DH params G/P (PKCS#3 DH) file or * - DH key file (if WOLFSSL_DH_EXTRA enabled) */ @@ -4560,11 +4785,10 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) if (ret == ASN_DH_KEY_E) { *inOutIdx = temp; - /* the version (0) */ - if (GetASNInt(input, inOutIdx, &length, inSz) < 0) { - return ASN_PARSE_E; + /* the version (0) - private only (for public skip) */ + if (GetASNInt(input, inOutIdx, &length, inSz) == 0) { + *inOutIdx += length; } - *inOutIdx += length; /* Size of dhKeyAgreement section */ if (GetSequence(input, inOutIdx, &length, inSz) < 0) @@ -4620,6 +4844,156 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) return ret; } +#ifdef WOLFSSL_DH_EXTRA + +/* Export DH Key (private or public) */ +int wc_DhKeyToDer(DhKey* key, byte* output, word32* outSz, int exportPriv) +{ + int ret, privSz = 0, pubSz = 0, keySz; + word32 idx, total; + + if (key == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* determine size */ + if (exportPriv) { + /* octect string: priv */ + privSz = SetASNIntMP(&key->priv, -1, NULL); + idx = 1 + SetLength(privSz, NULL) + privSz; /* +1 for ASN_OCTET_STRING */ + } + else { + /* bit string: public */ + pubSz = SetASNIntMP(&key->pub, -1, NULL); + idx = SetBitString(pubSz, 0, NULL) + pubSz; + } + keySz = idx; + + /* DH Parameters sequence with P and G */ + total = 0; + ret = wc_DhParamsToDer(key, NULL, &total); + if (ret != LENGTH_ONLY_E) + return ret; + idx += total; + + /* object dhKeyAgreement 1.2.840.113549.1.3.1 */ + idx += SetObjectId(sizeof(keyDhOid), NULL); + idx += sizeof(keyDhOid); + /* sequence */ + idx += SetSequence(idx, NULL); + if (exportPriv) { + /* version: 0 (ASN_INTEGER, 0x01, 0x00) */ + idx += 3; + } + /* sequence */ + total = idx + SetSequence(idx, NULL); + + /* if no output, then just getting size */ + if (output == NULL) { + *outSz = total; + return LENGTH_ONLY_E; + } + + /* make sure output fits in buffer */ + if (total > *outSz) { + return BUFFER_E; + } + total = idx; + + /* sequence */ + idx = SetSequence(total, output); + if (exportPriv) { + /* version: 0 */ + idx += SetMyVersion(0, output + idx, 0); + } + /* sequence - all but pub/priv */ + idx += SetSequence(total - keySz - idx, output + idx); + /* object dhKeyAgreement 1.2.840.113549.1.3.1 */ + idx += SetObjectId(sizeof(keyDhOid), output + idx); + XMEMCPY(output + idx, keyDhOid, sizeof(keyDhOid)); + idx += sizeof(keyDhOid); + + /* DH Parameters sequence with P and G */ + total = *outSz - idx; + ret = wc_DhParamsToDer(key, output + idx, &total); + if (ret < 0) + return ret; + idx += total; + + /* octect string: priv */ + if (exportPriv) { + idx += SetOctetString(privSz, output + idx); + idx += SetASNIntMP(&key->priv, -1, output + idx); + } + else { + /* bit string: public */ + idx += SetBitString(pubSz, 0, output + idx); + idx += SetASNIntMP(&key->pub, -1, output + idx); + } + *outSz = idx; + + return idx; +} + +int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz) +{ + return wc_DhKeyToDer(key, out, outSz, 0); +} +int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz) +{ + return wc_DhKeyToDer(key, out, outSz, 1); +} + + +/* Convert DH key parameters to DER format, write to output (outSz) + * If output is NULL then max expected size is set to outSz and LENGTH_ONLY_E is + * returned. + * + * Note : static function due to redefinition complications with DhKey and FIPS + * version 2 build. + * + * return bytes written on success */ +int wc_DhParamsToDer(DhKey* key, byte* output, word32* outSz) +{ + word32 idx, total; + + if (key == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* determine size */ + /* integer - g */ + idx = SetASNIntMP(&key->g, -1, NULL); + /* integer - p */ + idx += SetASNIntMP(&key->p, -1, NULL); + total = idx; + /* sequence */ + idx += SetSequence(idx, NULL); + + if (output == NULL) { + *outSz = idx; + return LENGTH_ONLY_E; + } + /* make sure output fits in buffer */ + if (idx > *outSz) { + return BUFFER_E; + } + + + /* write DH parameters */ + /* sequence - for P and G only */ + idx = SetSequence(total, output); + /* integer - p */ + idx += SetASNIntMP(&key->p, -1, output + idx); + /* integer - g */ + idx += SetASNIntMP(&key->g, -1, output + idx); + *outSz = idx; + + return idx; +} + +#endif /* WOLFSSL_DH_EXTRA */ + int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz) { @@ -4668,6 +5042,7 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, int length; int ret = 0; word32 oid; + word32 maxIdx; if (input == NULL || inOutIdx == NULL || key == NULL) return BAD_FUNC_ARG; @@ -4675,10 +5050,11 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->q, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0 || - GetInt(&key->y, input, inOutIdx, inSz) < 0 ) + maxIdx = (word32)(*inOutIdx + length); + if (GetInt(&key->p, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->q, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->g, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->y, input, inOutIdx, maxIdx) < 0 ) ret = ASN_DH_KEY_E; if (ret != 0) { @@ -4710,6 +5086,27 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, return ret; } +int wc_DsaParamsDecode(const byte* input, word32* inOutIdx, DsaKey* key, + word32 inSz) +{ + int length; + word32 maxIdx; + + if (input == NULL || inOutIdx == NULL || key == NULL) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + maxIdx = (word32)(*inOutIdx + length); + if (GetInt(&key->p, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->q, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->g, input, inOutIdx, maxIdx) < 0) + return ASN_DH_KEY_E; + + return 0; +} + int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, word32 inSz) @@ -4788,6 +5185,7 @@ int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, static mp_int* GetDsaInt(DsaKey* key, int idx) { + /* Other functions depend on this order. Please don't change it. */ if (idx == 0) return &key->p; if (idx == 1) @@ -4803,11 +5201,11 @@ static mp_int* GetDsaInt(DsaKey* key, int idx) } /* Release Tmp DSA resources */ -static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap) +static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap, int ints) { int i; - for (i = 0; i < DSA_INTS; i++) + for (i = 0; i < ints; i++) XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA); (void)heap; @@ -4982,8 +5380,10 @@ int wc_SetDsaPublicKey(byte* output, DsaKey* key, XMEMCPY(output + idx, g, gSz); idx += gSz; /* bit string */ - XMEMCPY(output + idx, bitString, bitStringSz); - idx += bitStringSz; + if (bitStringSz > 0) { + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } /* y */ XMEMCPY(output + idx, y, ySz); idx += ySz; @@ -5005,11 +5405,10 @@ int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen) } #endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */ -/* Convert private DsaKey key to DER format, write to output (inLen), - return bytes written */ -int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) +static int DsaKeyIntsToDer(DsaKey* key, byte* output, word32 inLen, + int ints, int includeVersion) { - word32 seqSz, verSz, rawLen, intTotalLen = 0; + word32 seqSz = 0, verSz = 0, rawLen, intTotalLen = 0; word32 sizes[DSA_INTS]; int i, j, outLen, ret = 0, mpSz; @@ -5017,17 +5416,14 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) byte ver[MAX_VERSION_SZ]; byte* tmps[DSA_INTS]; - if (!key || !output) + if (ints > DSA_INTS) return BAD_FUNC_ARG; - if (key->type != DSA_PRIVATE) - return BAD_FUNC_ARG; - - for (i = 0; i < DSA_INTS; i++) + for (i = 0; i < ints; i++) tmps[i] = NULL; /* write all big ints from key to DER tmps */ - for (i = 0; i < DSA_INTS; i++) { + for (i = 0; i < ints; i++) { mp_int* keyInt = GetDsaInt(key, i); rawLen = mp_unsigned_bin_size(keyInt) + 1; @@ -5047,35 +5443,62 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) } if (ret != 0) { - FreeTmpDsas(tmps, key->heap); + FreeTmpDsas(tmps, key->heap, ints); return ret; } /* make headers */ - verSz = SetMyVersion(0, ver, FALSE); + if (includeVersion) + verSz = SetMyVersion(0, ver, FALSE); seqSz = SetSequence(verSz + intTotalLen, seq); outLen = seqSz + verSz + intTotalLen; if (outLen > (int)inLen) { - FreeTmpDsas(tmps, key->heap); + FreeTmpDsas(tmps, key->heap, ints); return BAD_FUNC_ARG; } /* write to output */ XMEMCPY(output, seq, seqSz); j = seqSz; - XMEMCPY(output + j, ver, verSz); - j += verSz; + if (includeVersion) { + XMEMCPY(output + j, ver, verSz); + j += verSz; + } - for (i = 0; i < DSA_INTS; i++) { + for (i = 0; i < ints; i++) { XMEMCPY(output + j, tmps[i], sizes[i]); j += sizes[i]; } - FreeTmpDsas(tmps, key->heap); + FreeTmpDsas(tmps, key->heap, ints); return outLen; } +/* Convert private DsaKey key to DER format, write to output (inLen), + return bytes written */ +int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) +{ + if (!key || !output) + return BAD_FUNC_ARG; + + if (key->type != DSA_PRIVATE) + return BAD_FUNC_ARG; + + return DsaKeyIntsToDer(key, output, inLen, DSA_INTS, 1); +} + +/* Convert DsaKey parameters to DER format, write to output (inLen), + return bytes written. Version is excluded to be compatible with + OpenSSL d2i_DSAparams */ +int wc_DsaKeyToParamsDer(DsaKey* key, byte* output, word32 inLen) +{ + if (!key || !output) + return BAD_FUNC_ARG; + + return DsaKeyIntsToDer(key, output, inLen, DSA_PARAM_INTS, 0); +} + #endif /* NO_DSA */ void InitDecodedCert(DecodedCert* cert, @@ -6121,6 +6544,15 @@ int GetName(DecodedCert* cert, int nameType, int maxIdx) nid = NID_domainComponent; #endif /* OPENSSL_EXTRA */ break; + case ASN_FAVOURITE_DRINK: + copy = WOLFSSL_FAVOURITE_DRINK; + copyLen = sizeof(WOLFSSL_FAVOURITE_DRINK) - 1; + #if (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) \ + && !defined(WOLFCRYPT_ONLY) + nid = NID_favouriteDrink; + #endif /* OPENSSL_EXTRA */ + break; default: WOLFSSL_MSG("Unknown pilot attribute type"); @@ -6792,6 +7224,7 @@ int DecodeToKey(DecodedCert* cert, int verify) return ret; } +#ifndef NO_CERTS static int GetSignature(DecodedCert* cert) { int length; @@ -6811,6 +7244,7 @@ static int GetSignature(DecodedCert* cert) return 0; } +#endif static word32 SetOctetString8Bit(word32 len, byte* output) { @@ -6831,7 +7265,7 @@ static word32 SetDigest(const byte* digest, word32 digSz, byte* output) static word32 BytePrecision(word32 value) { word32 i; - for (i = sizeof(value); i; --i) + for (i = (word32)sizeof(value); i; --i) if (value >> ((i - 1) * WOLFSSL_BIT_SIZE)) break; @@ -7118,8 +7552,6 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, { int ret = 0; - (void)verify; - switch (sigOID) { #if defined(WOLFSSL_MD2) case CTC_MD2wRSA: @@ -7207,6 +7639,14 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, WOLFSSL_MSG("Hash for Signature has unsupported type"); } + (void)buf; + (void)bufSz; + (void)sigOID; + (void)digest; + (void)digestSz; + (void)typeH; + (void)verify; + return ret; } #endif /* !NO_ASN_CRYPT */ @@ -7320,7 +7760,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx, } if ((ret = wc_DsaPublicKeyDecode(key, &idx, sigCtx->key.dsa, keySz)) != 0) { - WOLFSSL_MSG("ASN Key decode error RSA"); + WOLFSSL_MSG("ASN Key decode error DSA"); goto exit_cs; } if (sigSz != DSA_SIG_SIZE) { @@ -7661,6 +8101,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } /* SIG_STATE_CHECK */ + + default: + break; } /* switch (sigCtx->state) */ exit_cs: @@ -7814,6 +8257,8 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) #endif /* !WOLFSSL_NO_ASN_STRICT */ break; } + default: + break; }; /* switch */ base = base->next; } @@ -7893,6 +8338,8 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) } break; } + default: + break; } /* switch */ base = base->next; } @@ -8081,9 +8528,8 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) break; } if (input[idx + i] == '/') { - i = strLen; /* error, found relative path since '/' was - * encountered before ':'. Returning error - * value in next if statement. */ + WOLFSSL_MSG("\tAlt Name must be absolute URI"); + return ASN_ALT_NAME_E; } } @@ -8192,6 +8638,14 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } + /* Certiciates issued with this OID in the subject alt name are for + * verifying signatures created on a module. + * RFC 4108 Section 5. */ + if (cert->hwType != NULL) { + WOLFSSL_MSG("\tAlready seen Hardware Module Name"); + return ASN_PARSE_E; + } + if (GetASNTag(input, &idx, &tag, sz) < 0) { return ASN_PARSE_E; } @@ -8611,6 +9065,8 @@ static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert) case EKU_OCSP_SIGN_OID: cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN; break; + default: + break; } #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -8751,8 +9207,10 @@ int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz) val = in[inIdx++]; w = XSNPRINTF(out, outSz, "%u.%u", val / 40, val % 40); - if (w < 0) + if (w < 0) { + w = BUFFER_E; goto exit; + } outIdx += w; val = 0; @@ -8767,8 +9225,10 @@ int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz) /* write val as text into out */ val += in[inIdx]; w = XSNPRINTF(out + outIdx, outSz - outIdx, ".%u", val); - if (w < 0) + if (w < 0 || (word32)w > outSz - outIdx) { + w = BUFFER_E; goto exit; + } outIdx += w; val = 0; } @@ -9991,7 +10451,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) cert->ca->keyOID, cert->signature, cert->sigLength, cert->signatureOID, tsip_encRsaKeyIdx)) != 0) { - if (ret != 0 && ret != WC_PENDING_E) { + if (ret != WC_PENDING_E) { WOLFSSL_MSG("Confirm signature failed"); } return ret; @@ -10341,7 +10801,8 @@ wcchar END_PUB_KEY = "-----END PUBLIC KEY-----"; const int pem_struct_min_sz = XSTR_SIZEOF("-----BEGIN X509 CRL-----" "-----END X509 CRL-----"); -static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine) +static WC_INLINE const char* SkipEndOfLineChars(const char* line, + const char* endOfLine) { /* eat end of line characters */ while (line < endOfLine && @@ -10521,18 +10982,19 @@ int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo) return ret; } -int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, size_t bufSz) +int wc_EncryptedInfoParse(EncryptedInfo* info, const char** pBuffer, + size_t bufSz) { - int err = 0; - char* bufferStart; - char* bufferEnd; - char* line; - word32 lineSz; - char* finish; - word32 finishSz; - char* start = NULL; - word32 startSz; - char* newline = NULL; + int err = 0; + const char* bufferStart; + const char* bufferEnd; + char* line; + word32 lineSz; + char* finish; + word32 finishSz; + char* start = NULL; + word32 startSz; + const char* newline = NULL; if (info == NULL || pBuffer == NULL || bufSz == 0) return BAD_FUNC_ARG; @@ -10801,10 +11263,10 @@ int PemToDer(const unsigned char* buff, long longSz, int type, { const char* header = NULL; const char* footer = NULL; - char* headerEnd; - char* footerEnd; - char* consumedEnd; - char* bufferEnd = (char*)(buff + longSz); + const char* headerEnd; + const char* footerEnd; + const char* consumedEnd; + const char* bufferEnd = (const char*)(buff + longSz); long neededSz; int ret = 0; int sz = (int)longSz; @@ -10877,7 +11339,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, if (!headerEnd) { #ifdef OPENSSL_EXTRA if (type == PRIVATEKEY_TYPE) { - char* beginEnd; + const char* beginEnd; int endLen; /* see if there is a -----BEGIN * PRIVATE KEY----- header */ headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz); @@ -10899,6 +11361,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 || beginEnd - headerEnd > PEM_LINE_LEN) { WOLFSSL_MSG("Couldn't find PEM header"); + WOLFSSL_ERROR(ASN_NO_PEM_HEADER); return ASN_NO_PEM_HEADER; } @@ -10911,6 +11374,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, (unsigned int)((char*)buff + sz - beginEnd)); if (!footer) { WOLFSSL_MSG("Couldn't find PEM footer"); + WOLFSSL_ERROR(ASN_NO_PEM_HEADER); return ASN_NO_PEM_HEADER; } @@ -10936,6 +11400,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, if (!headerEnd) { WOLFSSL_MSG("Couldn't find PEM header"); + WOLFSSL_ERROR(ASN_NO_PEM_HEADER); return ASN_NO_PEM_HEADER; } #else @@ -10992,7 +11457,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, } if (info) - info->consumed = (long)(consumedEnd - (char*)buff); + info->consumed = (long)(consumedEnd - (const char*)buff); /* set up der buffer */ neededSz = (long)(footerEnd - headerEnd); @@ -11101,8 +11566,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, * then strip this padding before proceeding: * der->length -= padVal; */ - if (der->length > 0 && - der->length > DES_BLOCK_SIZE && + if (der->length > DES_BLOCK_SIZE && (der->length % DES_BLOCK_SIZE) != 0) { padVal = der->buffer[der->length-1]; if (padVal < DES_BLOCK_SIZE) { @@ -12108,7 +12572,7 @@ int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen, #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS) /* older version of ecc.c can not handle dp being NULL */ - if (key != NULL && key->dp == NULL) { + if (key->dp == NULL) { keySz = 1 + 2 * MAX_ECC_BYTES; ret = LENGTH_ONLY_E; } @@ -12354,6 +12818,7 @@ int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen, #ifdef WOLFSSL_CERT_GEN +#ifndef NO_ASN_TIME static WC_INLINE byte itob(int number) { return (byte)number + 0x30; @@ -12387,7 +12852,7 @@ static void SetTime(struct tm* date, byte* output) output[i] = 'Z'; /* Zulu profile */ } - +#endif #ifdef WOLFSSL_ALT_NAMES @@ -12410,16 +12875,6 @@ static int CopyValidity(byte* output, Cert* cert) #endif -/* ASN Encoded Name field */ -typedef struct EncodedName { - int nameLen; /* actual string value length */ - int totalLen; /* total encoded length */ - int type; /* type of name */ - int used; /* are we actually using this one */ - byte encoded[CTC_NAME_SIZE * 2]; /* encoding */ -} EncodedName; - - /* Get Which Name from index */ const char* GetOneCertName(CertName* name, int idx) { @@ -12998,285 +13453,161 @@ int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names) * nameStr value to be encoded * nameType type of encoding i.e CTC_UTF8 * type id of attribute i.e ASN_COMMON_NAME - * + * emailType type of email i.e CTC_UTF8 * returns length on success */ -static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, - byte type) +static int wc_EncodeName_ex(EncodedName* name, const char* nameStr, char nameType, + byte type, byte emailType) { word32 idx = 0; + /* bottom up */ + byte firstLen[1 + MAX_LENGTH_SZ]; + byte secondLen[MAX_LENGTH_SZ]; + byte sequence[MAX_SEQ_SZ]; + byte set[MAX_SET_SZ]; - if (nameStr) { - /* bottom up */ - byte firstLen[1 + MAX_LENGTH_SZ]; - byte secondLen[MAX_LENGTH_SZ]; - byte sequence[MAX_SEQ_SZ]; - byte set[MAX_SET_SZ]; + int strLen; + int thisLen; + int firstSz, secondSz, seqSz, setSz; - int strLen = (int)XSTRLEN(nameStr); - int thisLen = strLen; - int firstSz, secondSz, seqSz, setSz; - - if (strLen == 0) { /* no user data for this item */ - name->used = 0; - return 0; - } - - /* Restrict country code size */ - if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) { - WOLFSSL_MSG("Country code size error"); - return ASN_COUNTRY_SIZE_E; - } - - secondSz = SetLength(strLen, secondLen); - thisLen += secondSz; - switch (type) { - case ASN_EMAIL_NAME: /* email */ - thisLen += EMAIL_JOINT_LEN; - firstSz = EMAIL_JOINT_LEN; - break; - - case ASN_DOMAIN_COMPONENT: - thisLen += PILOT_JOINT_LEN; - firstSz = PILOT_JOINT_LEN; - break; - - default: - thisLen++; /* str type */ - thisLen += JOINT_LEN; - firstSz = JOINT_LEN + 1; - } - thisLen++; /* id type */ - firstSz = SetObjectId(firstSz, firstLen); - thisLen += firstSz; - - seqSz = SetSequence(thisLen, sequence); - thisLen += seqSz; - setSz = SetSet(thisLen, set); - thisLen += setSz; - - if (thisLen > (int)sizeof(name->encoded)) { - return BUFFER_E; - } - - /* store it */ - idx = 0; - /* set */ - XMEMCPY(name->encoded, set, setSz); - idx += setSz; - /* seq */ - XMEMCPY(name->encoded + idx, sequence, seqSz); - idx += seqSz; - /* asn object id */ - XMEMCPY(name->encoded + idx, firstLen, firstSz); - idx += firstSz; - switch (type) { - case ASN_EMAIL_NAME: - { - const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x09, 0x01, 0x16 }; - /* email joint id */ - XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); - idx += (int)sizeof(EMAIL_OID); - } - break; - - case ASN_DOMAIN_COMPONENT: - { - const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89, - 0x93, 0xF2, 0x2C, 0x64, 0x01 - }; - - XMEMCPY(name->encoded + idx, PILOT_OID, - sizeof(PILOT_OID)); - idx += (int)sizeof(PILOT_OID); - /* id type */ - name->encoded[idx++] = type; - /* str type */ - name->encoded[idx++] = nameType; - } - break; - - default: - name->encoded[idx++] = 0x55; - name->encoded[idx++] = 0x04; - /* id type */ - name->encoded[idx++] = type; - /* str type */ - name->encoded[idx++] = nameType; - } - /* second length */ - XMEMCPY(name->encoded + idx, secondLen, secondSz); - idx += secondSz; - /* str value */ - XMEMCPY(name->encoded + idx, nameStr, strLen); - idx += strLen; - - name->type = type; - name->totalLen = idx; - name->used = 1; - } - else + if (nameStr == NULL) { name->used = 0; + return 0; + } + thisLen = strLen = (int)XSTRLEN(nameStr); + if (strLen == 0) { /* no user data for this item */ + name->used = 0; + return 0; + } + + /* Restrict country code size */ + if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) { + WOLFSSL_MSG("Country code size error"); + return ASN_COUNTRY_SIZE_E; + } + + secondSz = SetLength(strLen, secondLen); + thisLen += secondSz; + switch (type) { + case ASN_EMAIL_NAME: /* email */ + thisLen += EMAIL_JOINT_LEN; + firstSz = EMAIL_JOINT_LEN; + break; + + case ASN_DOMAIN_COMPONENT: + thisLen += PILOT_JOINT_LEN; + firstSz = PILOT_JOINT_LEN; + break; + + default: + thisLen++; /* str type */ + thisLen += JOINT_LEN; + firstSz = JOINT_LEN + 1; + } + thisLen++; /* id type */ + firstSz = SetObjectId(firstSz, firstLen); + thisLen += firstSz; + + seqSz = SetSequence(thisLen, sequence); + thisLen += seqSz; + setSz = SetSet(thisLen, set); + thisLen += setSz; + + if (thisLen > (int)sizeof(name->encoded)) { + return BUFFER_E; + } + + /* store it */ + idx = 0; + /* set */ + XMEMCPY(name->encoded, set, setSz); + idx += setSz; + /* seq */ + XMEMCPY(name->encoded + idx, sequence, seqSz); + idx += seqSz; + /* asn object id */ + XMEMCPY(name->encoded + idx, firstLen, firstSz); + idx += firstSz; + switch (type) { + case ASN_EMAIL_NAME: + { + const byte EMAIL_OID[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 + }; + /* email joint id */ + XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); + idx += (int)sizeof(EMAIL_OID); + name->encoded[idx++] = emailType; + break; + } + + case ASN_DOMAIN_COMPONENT: + { + const byte PILOT_OID[] = { + 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01 + }; + + XMEMCPY(name->encoded + idx, PILOT_OID, sizeof(PILOT_OID)); + idx += (int)sizeof(PILOT_OID); + /* id type */ + name->encoded[idx++] = type; + /* str type */ + name->encoded[idx++] = nameType; + break; + } + + default: + name->encoded[idx++] = 0x55; + name->encoded[idx++] = 0x04; + /* id type */ + name->encoded[idx++] = type; + /* str type */ + name->encoded[idx++] = nameType; + } + /* second length */ + XMEMCPY(name->encoded + idx, secondLen, secondSz); + idx += secondSz; + /* str value */ + XMEMCPY(name->encoded + idx, nameStr, strLen); + idx += strLen; + + name->type = type; + name->totalLen = idx; + name->used = 1; return idx; } - - - -/* Guarded by either - * A) WOLFSSL_WPAS_SMALL is on or - * B) (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_CERT_GEN + - * (WOLFSSL_CERT_REQ or WOLFSSL_CERT_EXT or OPENSSL_EXTRA) has been - * defined +/* canonical encoding one attribute of the name (issuer/subject) + * call wc_EncodeName_ex with CTC_UTF8 for email type + * + * name structure to hold result of encoding + * nameStr value to be encoded + * nameType type of encoding i.e CTC_UTF8 + * type id of attribute i.e ASN_COMMON_NAME + * + * returns length on success */ -#if defined(WOLFSSL_WPAS_SMALL) || \ - (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ - defined(WOLFSSL_CERT_GEN) && \ - (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \ - defined(OPENSSL_EXTRA)) -/* Converts from NID_* value to wolfSSL value if needed */ -static int ConvertNIDToWolfSSL(int nid) +int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr, char nameType, + byte type) { - switch (nid) { - case NID_commonName : return ASN_COMMON_NAME; - case NID_surname : return ASN_SUR_NAME; - case NID_countryName: return ASN_COUNTRY_NAME; - case NID_localityName: return ASN_LOCALITY_NAME; - case NID_stateOrProvinceName: return ASN_STATE_NAME; - case NID_organizationName: return ASN_ORG_NAME; - case NID_organizationalUnitName: return ASN_ORGUNIT_NAME; - case NID_emailAddress: return ASN_EMAIL_NAME; - case NID_serialNumber: return ASN_SERIAL_NUMBER; - case NID_businessCategory: return ASN_BUS_CAT; - case NID_domainComponent: return ASN_DOMAIN_COMPONENT; - default: - WOLFSSL_MSG("Attribute NID not found"); - return -1; - } + return wc_EncodeName_ex(name, nameStr, nameType, type, 0x0c/* CTC_UTF8 */); } - -/* Converts the x509 name structure into DER format. +/* Encodes one attribute of the name (issuer/subject) + * call we_EncodeName_ex with 0x16, IA5String for email type + * name structure to hold result of encoding + * nameStr value to be encoded + * nameType type of encoding i.e CTC_UTF8 + * type id of attribute i.e ASN_COMMON_NAME * - * out pointer to either a pre setup buffer or a pointer to null for - * creating a dynamic buffer. In the case that a pre-existing buffer is - * used out will be incremented the size of the DER buffer on success. - * - * returns the size of the buffer on success, or negative value with failure + * returns length on success */ -int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) +int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, + byte type) { - int totalBytes = 0, i, idx; - byte temp[MAX_SEQ_SZ]; - byte *output, *local = NULL; -#ifdef WOLFSSL_SMALL_STACK - EncodedName* names = NULL; -#else - EncodedName names[MAX_NAME_ENTRIES]; -#endif - - if (out == NULL || name == NULL) - return BAD_FUNC_ARG; - -#ifdef WOLFSSL_SMALL_STACK - names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (names == NULL) - return MEMORY_E; -#endif - - XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES); - - for (i = 0; i < MAX_NAME_ENTRIES; i++) { - WOLFSSL_X509_NAME_ENTRY* entry; - int ret; - - entry = wolfSSL_X509_NAME_get_entry(name, i); - if (entry != NULL && entry->set == 1) { - const char* nameStr; - int type; - WOLFSSL_ASN1_STRING* data; - - data = wolfSSL_X509_NAME_ENTRY_get_data(entry); - if (data == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - WOLFSSL_MSG("Error getting entry data"); - return WOLFSSL_FATAL_ERROR; - } - - nameStr = (const char*)wolfSSL_ASN1_STRING_data(data); - type = wolfSSL_ASN1_STRING_type(data); - - switch (type) { - case MBSTRING_UTF8: - type = CTC_UTF8; - break; - case V_ASN1_PRINTABLESTRING: - type = CTC_PRINTABLE; - break; - default: - WOLFSSL_MSG("Unknown encoding type conversion UTF8 by default"); - type = CTC_UTF8; - } - ret = wc_EncodeName(&names[i], nameStr, type, - ConvertNIDToWolfSSL(entry->nid)); - if (ret < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - WOLFSSL_MSG("EncodeName failed"); - return WOLFSSL_FATAL_ERROR; - } - totalBytes += ret; - } - } - - /* header */ - idx = SetSequence(totalBytes, temp); - if (totalBytes + idx > ASN_NAME_MAX) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX"); - return BUFFER_E; - } - - /* check if using buffer passed in */ - if (*out == NULL) { - *out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL, - DYNAMIC_TYPE_OPENSSL); - if (*out == NULL) { - return MEMORY_E; - } - } - output = *out; - - idx = SetSequence(totalBytes, output); - totalBytes += idx; - for (i = 0; i < MAX_NAME_ENTRIES; i++) { - if (names[i].used) { - XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); - idx += names[i].totalLen; - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - /* used existing buffer passed in, so increment pointer */ - if (local == NULL) { - *out += totalBytes; - } - return totalBytes; + return wc_EncodeName_ex(name, nameStr, nameType, type, ASN_IA5_STRING); } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - - /* encode CertName into output, return total bytes written */ int SetName(byte* output, word32 outputSz, CertName* name) { @@ -13417,6 +13748,7 @@ int SetName(byte* output, word32 outputSz, CertName* name) * return size in bytes written to output, 0 on error */ static int SetValidity(byte* output, int daysValid) { +#ifndef NO_ASN_TIME byte before[MAX_DATE_SIZE]; byte after[MAX_DATE_SIZE]; @@ -13486,6 +13818,11 @@ static int SetValidity(byte* output, int daysValid) XMEMCPY(output + seqSz + beforeSz, after, afterSz); return seqSz + beforeSz + afterSz; +#else + (void)output; + (void)daysValid; + return NOT_COMPILED_IN; +#endif } /* encode info from cert into DER encoded format */ @@ -15744,7 +16081,7 @@ int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap) oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x); } - if ((idx+(word32)i) > *outSz) { + if ((idx+(word32)i) >= *outSz) { XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); return BUFFER_E; } @@ -15976,6 +16313,14 @@ int DecodeECC_DSA_Sig_Bin(const byte* sig, word32 sigLen, byte* r, word32* rLen, if (s) XMEMCPY(s, (byte*)sig + idx, len); +#ifndef NO_STRICT_ECDSA_LEN + /* sanity check that the index has been advanced all the way to the end of + * the buffer */ + if (idx + len != sigLen) { + ret = ASN_ECC_KEY_E; + } +#endif + return ret; } #endif @@ -16011,6 +16356,16 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) return ASN_ECC_KEY_E; } +#ifndef NO_STRICT_ECDSA_LEN + /* sanity check that the index has been advanced all the way to the end of + * the buffer */ + if (idx != sigLen) { + mp_clear(r); + mp_clear(s); + return ASN_ECC_KEY_E; + } +#endif + return 0; } #endif @@ -16178,6 +16533,10 @@ static int ASNToHexString(const byte* input, word32* inOutIdx, char** out, } str = (char*)XMALLOC(len * 2 + 1, heap, heapType); + if (str == NULL) { + return MEMORY_E; + } + for (i=0; idp->size; + +#ifdef WOLFSSL_QNX_CAAM + /* check if is a black key, and add MAC size if so */ + if (key->blackKey > 0) { + privSz = privSz + WC_CAAM_MAC_SZ; + } +#endif + #ifndef WOLFSSL_NO_MALLOC prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -16512,7 +16879,12 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, return BUFFER_E; } #endif - prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]); + if (privSz < ASN_LONG_LENGTH) { + prvidx += SetOctetString8Bit(privSz, &prv[prvidx]); + } + else { + prvidx += SetOctetString(privSz, &prv[prvidx]); + } ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz); if (ret < 0) { #ifndef WOLFSSL_NO_MALLOC @@ -16569,7 +16941,17 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq); totalSz = prvidx + pubidx + curveidx + verSz + seqSz; - if (totalSz > (int)inLen) { + if (output == NULL) { + *inLen = totalSz; + #ifndef WOLFSSL_NO_MALLOC + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + #endif + return LENGTH_ONLY_E; + } + if (inLen != NULL && totalSz > (int)*inLen) { #ifndef WOLFSSL_NO_MALLOC XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); if (pubIn) { @@ -16615,17 +16997,33 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, * length on success else < 0 */ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) { - return wc_BuildEccKeyDer(key, output, inLen, 1); + return wc_BuildEccKeyDer(key, output, &inLen, 1); } +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_EccKeyDerSize(ecc_key* key, int pub) +{ + word32 sz = 0; + int ret; + + ret = wc_BuildEccKeyDer(key, NULL, &sz, pub); + + if (ret != LENGTH_ONLY_E) { + return ret; + } + return sz; + } /* Write only private ecc key to DER format, * length on success else < 0 */ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) { - return wc_BuildEccKeyDer(key, output, inLen, 0); + return wc_BuildEccKeyDer(key, output, &inLen, 0); } + + #ifdef HAVE_PKCS8 /* Write only private ecc key or both private and public parts to unencrypted * PKCS#8 format. @@ -16647,6 +17045,7 @@ static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, #else byte* tmpDer = NULL; #endif + word32 sz = ECC_BUFSIZE; if (key == NULL || key->dp == NULL || outLen == NULL) return BAD_FUNC_ARG; @@ -16665,7 +17064,7 @@ static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, #endif XMEMSET(tmpDer, 0, ECC_BUFSIZE); - tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, includePublic); + tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, &sz, includePublic); if (tmpDerSz < 0) { #ifndef WOLFSSL_NO_MALLOC XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -17185,12 +17584,16 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, ret = GetOctetString(source, &idx, &length, size); if (ret < 0) return ret; + if (length > (int)sizeof(single->issuerHash)) + return BUFFER_E; XMEMCPY(single->issuerHash, source + idx, length); idx += length; /* Save reference to the hash of the issuer public key */ ret = GetOctetString(source, &idx, &length, size); if (ret < 0) return ret; + if (length > (int)sizeof(single->issuerKeyHash)) + return BUFFER_E; XMEMCPY(single->issuerKeyHash, source + idx, length); idx += length; @@ -17442,9 +17845,20 @@ static int DecodeResponseData(byte* source, if (single->next == NULL) { return MEMORY_E; } + XMEMSET(single->next, 0, sizeof(OcspEntry)); + + single->next->status = (CertStatus*)XMALLOC(sizeof(CertStatus), + resp->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (single->next->status == NULL) { + XFREE(single->next, resp->heap, DYNAMIC_TYPE_OCSP_ENTRY); + single->next = NULL; + return MEMORY_E; + } + XMEMSET(single->next->status, 0, sizeof(CertStatus)); + + single->next->isDynamic = 1; + single = single->next; - XMEMSET(single, 0, sizeof(OcspEntry)); - single->isDynamic = 1; } } @@ -17640,8 +18054,10 @@ void FreeOcspResponse(OcspResponse* resp) OcspEntry *single, *next; for (single = resp->single; single; single = next) { next = single->next; - if (single->isDynamic) + if (single->isDynamic) { + XFREE(single->status, resp->heap, DYNAMIC_TYPE_OCSP_STATUS); XFREE(single, resp->heap, DYNAMIC_TYPE_OCSP_ENTRY); + } } } @@ -17954,9 +18370,10 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) for (single = resp->single; single; single = next) { cmp = req->serialSz - single->status->serialSz; if (cmp == 0) { - if ((XMEMCMP(req->serial, single->status->serial, req->serialSz) == 0) - && (XMEMCMP(req->issuerHash, single->issuerHash, OCSP_DIGEST_SIZE) == 0) - && (XMEMCMP(req->issuerKeyHash, single->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) { + cmp = XMEMCMP(req->serial, single->status->serial, req->serialSz) + || XMEMCMP(req->issuerHash, single->issuerHash, OCSP_DIGEST_SIZE) + || XMEMCMP(req->issuerKeyHash, single->issuerKeyHash, OCSP_DIGEST_SIZE); + if (cmp == 0) { /* match found */ if (resp->single != single && prev) { /* move to top of list */ @@ -18146,7 +18563,10 @@ static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf, word32* inOutIdx, int sz) { word32 oid, dateIdx, idx, checkIdx; - int version, doNextDate = 1; + int version; +#ifdef WOLFSSL_NO_CRL_NEXT_DATE + int doNextDate = 1; +#endif byte tag; if (dcrl == NULL || inOutIdx == NULL || buf == NULL) { @@ -18185,7 +18605,10 @@ static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf, #endif } - if (doNextDate) { +#ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (doNextDate)x +#endif + { #ifndef NO_ASN_TIME if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) { WOLFSSL_MSG("CRL after date is no longer valid"); @@ -18565,15 +18988,19 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) else { mimeType = MIME_HDR; } - start = end = 0; + start = 0; lineLen = XSTRLEN(curLine); + if (lineLen == 0) { + ret = BAD_FUNC_ARG; + goto error; + } for (pos = 0; pos < lineLen; pos++) { char cur = curLine[pos]; if (mimeStatus == MIME_NAMEATTR && ((cur == ':' && mimeType == MIME_HDR) || (cur == '=' && - mimeType == MIME_PARAM))) { + mimeType == MIME_PARAM)) && pos >= 1) { mimeStatus = MIME_BODYVAL; end = pos-1; ret = wc_MIME_header_strip(curLine, &nameAttr, start, end); @@ -18582,7 +19009,7 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) } start = pos+1; } - else if (mimeStatus == MIME_BODYVAL && cur == ';') { + else if (mimeStatus == MIME_BODYVAL && cur == ';' && pos >= 1) { end = pos-1; ret = wc_MIME_header_strip(curLine, &bodyVal, start, end); if (ret) { @@ -18590,7 +19017,9 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) } if (mimeType == MIME_HDR) { nextHdr->name = nameAttr; + nameAttr = NULL; nextHdr->body = bodyVal; + bodyVal = NULL; nextHdr->next = curHdr; curHdr = nextHdr; nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL, @@ -18603,7 +19032,9 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) } else { nextParam->attribute = nameAttr; + nameAttr = NULL; nextParam->value = bodyVal; + bodyVal = NULL; nextParam->next = curHdr->params; curHdr->params = nextParam; nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL, @@ -18632,7 +19063,9 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) } if (mimeType == MIME_HDR) { nextHdr->name = nameAttr; + nameAttr = NULL; nextHdr->body = bodyVal; + bodyVal = NULL; nextHdr->next = curHdr; curHdr = nextHdr; nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL, @@ -18644,7 +19077,9 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr)); } else { nextParam->attribute = nameAttr; + nameAttr = NULL; nextParam->value = bodyVal; + bodyVal = NULL; nextParam->next = curHdr->params; curHdr->params = nextParam; nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL, @@ -18670,8 +19105,10 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) error: wc_MIME_free_hdrs(curHdr); wc_MIME_free_hdrs(nextHdr); - XFREE(nameAttr, NULL, DYNAMIC_TYPE_PKCS7); - XFREE(bodyVal, NULL, DYNAMIC_TYPE_PKCS7); + if (nameAttr != NULL) + XFREE(nameAttr, NULL, DYNAMIC_TYPE_PKCS7); + if (bodyVal != NULL) + XFREE(bodyVal, NULL, DYNAMIC_TYPE_PKCS7); XFREE(nextParam, NULL, DYNAMIC_TYPE_PKCS7); return ret; @@ -18762,6 +19199,41 @@ MimeParam* wc_MIME_find_param_attr(const char* attribute, return param; } +/***************************************************************************** +* wc_MIME_canonicalize - Canonicalize a line by converting all line endings +* to CRLF. +* +* RETURNS: +* returns a pointer to a canonicalized line on success, NULL on error. +*/ +char* wc_MIME_canonicalize(const char* line) +{ + size_t end = 0; + char* canonLine = NULL; + + if (line == NULL || XSTRLEN(line) == 0) { + return NULL; + } + + end = XSTRLEN(line); + while (end >= 1 && ((line[end-1] == '\r') || (line[end-1] == '\n'))) { + end--; + } + + /* Need 2 chars for \r\n and 1 for EOL */ + canonLine = (char*)XMALLOC((end+3)*sizeof(char), NULL, DYNAMIC_TYPE_PKCS7); + if (canonLine == NULL) { + return NULL; + } + + XSTRNCPY(canonLine, line, end); + canonLine[end] = '\r'; + canonLine[end+1] = '\n'; + canonLine[end+2] = '\0'; + + return canonLine; +} + /***************************************************************************** * wc_MIME_free_hdrs - Frees all MIME headers, parameters and strings starting from * the provided header pointer. diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 1d89fbe78..90ab9861f 100644 --- a/wolfcrypt/src/blake2b.c +++ b/wolfcrypt/src/blake2b.c @@ -12,7 +12,7 @@ */ /* blake2b.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -152,6 +152,7 @@ int blake2b_init( blake2b_state *S, const byte outlen ) int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, const byte keylen ) { + int ret = 0; blake2b_param P[1]; if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return BAD_FUNC_ARG; @@ -178,10 +179,8 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, P->depth = 1; #endif - { - int ret = blake2b_init_param( S, P ); - if ( ret < 0 ) return ret; - } + ret = blake2b_init_param( S, P ); + if ( ret < 0 ) return ret; { #ifdef WOLFSSL_SMALL_STACK @@ -196,7 +195,7 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); XMEMCPY( block, key, keylen ); - blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); + ret = blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ /* memory */ @@ -204,7 +203,7 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif } - return 0; + return ret; } static WC_INLINE int blake2b_compress( diff --git a/wolfcrypt/src/blake2s.c b/wolfcrypt/src/blake2s.c index 7c74cac15..e1086c4dd 100644 --- a/wolfcrypt/src/blake2s.c +++ b/wolfcrypt/src/blake2s.c @@ -12,7 +12,7 @@ */ /* blake2s.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -148,6 +148,7 @@ int blake2s_init( blake2s_state *S, const byte outlen ) int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, const byte keylen ) { + int ret = 0; blake2s_param P[1]; if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return BAD_FUNC_ARG; @@ -174,11 +175,9 @@ int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, P->depth = 1; #endif - { - int ret = blake2s_init_param( S, P ); - if (ret < 0) - return ret; - } + ret = blake2s_init_param( S, P ); + if (ret < 0) + return ret; { #ifdef WOLFSSL_SMALL_STACK @@ -193,7 +192,7 @@ int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, XMEMSET( block, 0, BLAKE2S_BLOCKBYTES ); XMEMCPY( block, key, keylen ); - blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); + ret = blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from */ /* memory */ @@ -201,7 +200,7 @@ int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif } - return 0; + return ret; } static WC_INLINE int blake2s_compress( diff --git a/wolfcrypt/src/camellia.c b/wolfcrypt/src/camellia.c index 89ee6617a..a7cb268b7 100644 --- a/wolfcrypt/src/camellia.c +++ b/wolfcrypt/src/camellia.c @@ -27,7 +27,7 @@ /* camellia.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/chacha.c b/wolfcrypt/src/chacha.c index 32feccf86..464a20e6a 100644 --- a/wolfcrypt/src/chacha.c +++ b/wolfcrypt/src/chacha.c @@ -1,6 +1,6 @@ /* chacha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index 86edc0b97..417b3e226 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -1,6 +1,6 @@ /* chacha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/chacha_asm.S b/wolfcrypt/src/chacha_asm.S index f5f6989fd..61ac921ac 100644 --- a/wolfcrypt/src/chacha_asm.S +++ b/wolfcrypt/src/chacha_asm.S @@ -1,6 +1,6 @@ /* chacha_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index 916b5ea80..93486eda6 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -1,6 +1,6 @@ /* cmac.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,6 +25,9 @@ #endif #include +#ifdef WOLFSSL_QNX_CAAM +#include +#endif #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) @@ -51,6 +54,10 @@ #include #include +#ifdef WOLF_CRYPTO_CB + #include +#endif + static void ShiftAndXorRb(byte* out, byte* in) { @@ -72,17 +79,38 @@ static void ShiftAndXorRb(byte* out, byte* in) } -int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz, - int type, void* unused) + +/* returns 0 on success */ +int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz, + int type, void* unused, void* heap, int devId) { int ret; (void)unused; + (void)heap; + (void)devId; - if (cmac == NULL || key == NULL || keySz == 0 || type != WC_CMAC_AES) + if (cmac == NULL || keySz == 0 || type != WC_CMAC_AES) return BAD_FUNC_ARG; XMEMSET(cmac, 0, sizeof(Cmac)); + +#ifdef WOLF_CRYPTO_CB + if (devId != INVALID_DEVID) { + cmac->devId = devId; + cmac->devCtx = NULL; + + ret = wc_CryptoCb_Cmac(cmac, key, keySz, NULL, 0, NULL, NULL, + type, unused); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + + if (key == NULL) + return BAD_FUNC_ARG; + ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION); if (ret == 0) { byte l[AES_BLOCK_SIZE]; @@ -97,11 +125,37 @@ int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz, } +int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz, + int type, void* unused) +{ +#ifdef WOLFSSL_QNX_CAAM + return wc_InitCmac_ex(cmac, key, keySz, type, unused, NULL, + WOLFSSL_CAAM_DEVID); +#else + return wc_InitCmac_ex(cmac, key, keySz, type, unused, NULL, INVALID_DEVID); +#endif +} + + + int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz) { +#ifdef WOLF_CRYPTO_CB + int ret; +#endif + if ((cmac == NULL) || (in == NULL && inSz != 0)) return BAD_FUNC_ARG; +#ifdef WOLF_CRYPTO_CB + if (cmac->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Cmac(cmac, NULL, 0, in, inSz, + NULL, NULL, 0, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif while (inSz != 0) { word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz); XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add); @@ -127,6 +181,9 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz) int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz) { +#ifdef WOLF_CRYPTO_CB + int ret; +#endif const byte* subKey; if (cmac == NULL || out == NULL || outSz == NULL) @@ -135,6 +192,15 @@ int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz) if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) return BUFFER_E; +#ifdef WOLF_CRYPTO_CB + if (cmac->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz, 0, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + if (cmac->bufferSz == AES_BLOCK_SIZE) { subKey = cmac->k1; } diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index 4764d1f57..30ce6ea10 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -1,6 +1,6 @@ /* coding.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -118,23 +118,40 @@ int Base64_SkipNewline(const byte* in, word32 *inLen, { word32 len = *inLen; word32 j = *outJ; - if (len && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) { - byte endLine = in[j++]; + byte curChar; + + if (len == 0) { + return BUFFER_E; + } + curChar = in[j]; + + while (len > 1 && curChar == ' ') { + /* skip whitespace in the middle or end of line */ + curChar = in[++j]; len--; - while (len && endLine == ' ') { /* allow trailing whitespace */ - endLine = in[j++]; - len--; - } - if (endLine == '\r') { + } + if (len && (curChar == '\r' || curChar == '\n')) { + j++; + len--; + if (curChar == '\r') { if (len) { - endLine = in[j++]; + curChar = in[j++]; len--; } } - if (endLine != '\n') { + if (curChar != '\n') { WOLFSSL_MSG("Bad end of line in Base64 Decode"); return ASN_INPUT_E; } + + if (len) { + curChar = in[j]; + } + } + while (len && curChar == ' ') { + if (--len > 0) { + curChar = in[++j]; + } } if (!len) { return BUFFER_E; diff --git a/wolfcrypt/src/compress.c b/wolfcrypt/src/compress.c index adebbf458..36f2931ca 100644 --- a/wolfcrypt/src/compress.c +++ b/wolfcrypt/src/compress.c @@ -1,6 +1,6 @@ /* compress.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/cpuid.c b/wolfcrypt/src/cpuid.c index 006da8cf7..1214ba429 100644 --- a/wolfcrypt/src/cpuid.c +++ b/wolfcrypt/src/cpuid.c @@ -1,6 +1,6 @@ /* cpuid.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index b0957e85b..e15706108 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -1,6 +1,6 @@ /* cryptocb.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -15,7 +15,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ /* This framework provides a central place for crypto hardware integration @@ -706,5 +707,43 @@ int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz) return wc_CryptoCb_TranslateErrorCode(ret); } #endif /* !WC_NO_RNG */ +#ifdef WOLFSSL_CMAC +int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz, + const byte* in, word32 inSz, byte* out, word32* outSz, int type, + void* ctx) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (cmac) { + dev = wc_CryptoCb_FindDevice(cmac->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CMAC; + + cryptoInfo.cmac.cmac = cmac; + cryptoInfo.cmac.ctx = ctx; + cryptoInfo.cmac.key = key; + cryptoInfo.cmac.in = in; + cryptoInfo.cmac.out = out; + cryptoInfo.cmac.outSz = outSz; + cryptoInfo.cmac.keySz = keySz; + cryptoInfo.cmac.inSz = inSz; + cryptoInfo.cmac.type = type; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif #endif /* WOLF_CRYPTO_CB */ diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index 8d086bed5..265aea482 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -1,6 +1,6 @@ /* curve25519.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -55,11 +55,12 @@ static const unsigned char kCurve25519BasePoint[CURVE25519_KEYSIZE] = {9}; /* compute the public key from an existing private key, using bare vectors. * - * return value is propagated from curve25519() (0 on success), or ECC_BAD_ARG_E, - * and the byte vectors are little endian. + * return value is propagated from curve25519() (0 on success), or + * ECC_BAD_ARG_E, and the byte vectors are little endian. */ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size, - const byte* priv) { + const byte* priv) +{ int ret; if ((public_size != CURVE25519_KEYSIZE) || @@ -79,7 +80,8 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size, { const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint(); ECPoint wc_pub; - ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass); /* input basepoint on Weierstrass curve */ + /* input basepoint on Weierstrass curve */ + ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass); if (ret == 0) XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE); } @@ -100,21 +102,22 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size, return ret; } -/* compute the public key from an existing private key, with supplied basepoint, using bare vectors. +/* compute the public key from an existing private key, with supplied basepoint, + * using bare vectors. * * return value is propagated from curve25519() (0 on success), * and the byte vectors are little endian. */ int wc_curve25519_generic(int public_size, byte* pub, int private_size, const byte* priv, - int basepoint_size, const byte* basepoint) { - int ret; - + int basepoint_size, const byte* basepoint) +{ #ifdef FREESCALE_LTC_ECC /* unsupported with NXP LTC, onlly supports single basepoint with * nxp_ltc_curve25519_GetBasePoint() */ return WC_HW_E; #else + int ret; if ((public_size != CURVE25519_KEYSIZE) || (private_size != CURVE25519_KEYSIZE) || @@ -143,7 +146,6 @@ int wc_curve25519_generic(int public_size, byte* pub, #endif return ret; - #endif /* FREESCALE_LTC_ECC */ } @@ -191,7 +193,8 @@ int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) ret = wc_curve25519_make_priv(rng, keysize, key->k.point); if (ret < 0) return ret; - return wc_curve25519_make_pub((int)sizeof key->p.point, key->p.point, sizeof key->k.point, key->k.point); + return wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point, + (int)sizeof(key->k.point), key->k.point); } #ifdef HAVE_CURVE25519_SHARED_SECRET @@ -225,7 +228,9 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key, return ECC_BAD_ARG_E; #ifdef FREESCALE_LTC_ECC - ret = nxp_ltc_curve25519(&o, private_key->k.point, &public_key->p, kLTC_Curve25519 /* input point P on Curve25519 */); + /* input point P on Curve25519 */ + ret = nxp_ltc_curve25519(&o, private_key->k.point, &public_key->p, + kLTC_Curve25519); #else #if defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM) SAVE_VECTOR_REGISTERS(); diff --git a/wolfcrypt/src/curve448.c b/wolfcrypt/src/curve448.c index 135f2380e..e926351fd 100644 --- a/wolfcrypt/src/curve448.c +++ b/wolfcrypt/src/curve448.c @@ -1,6 +1,6 @@ /* curve448.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index a6548dc5d..62b21c812 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -1,6 +1,6 @@ /* des3.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -719,9 +719,17 @@ int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { int ret = 0; - byte* dkey1 = (byte*)des->key[0]; - byte* dkey2 = (byte*)des->key[1]; - byte* dkey3 = (byte*)des->key[2]; + byte* dkey1; + byte* dkey2; + byte* dkey3; + + if (des == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + dkey1 = (byte*)des->key[0]; + dkey2 = (byte*)des->key[1]; + dkey3 = (byte*)des->key[2]; XMEMCPY(dkey1, key, 8); /* set key 1 */ XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ @@ -835,9 +843,17 @@ int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { int i = 0, ret = 0; - byte* dkey1 = (byte*)des->key[0]; - byte* dkey2 = (byte*)des->key[1]; - byte* dkey3 = (byte*)des->key[2]; + byte* dkey1; + byte* dkey2; + byte* dkey3; + + if (des == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + dkey1 = (byte*)des->key[0]; + dkey2 = (byte*)des->key[1]; + dkey3 = (byte*)des->key[2]; XMEMCPY(dkey1, key, 8); /* set key 1 */ XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ @@ -1771,9 +1787,9 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) if (des == NULL) { return BAD_FUNC_ARG; } - if (des && iv) + if (iv) XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); - else if (des) + else XMEMSET(des->reg, 0, DES_BLOCK_SIZE); return 0; diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 245765c02..79895267d 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1,6 +1,6 @@ /* dh.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -2126,7 +2126,6 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, const byte* pub, word32 pubSz) { byte havePriv, havePub; - mp_int *keyPriv = NULL, *keyPub = NULL; if (key == NULL) { return BAD_FUNC_ARG; @@ -2154,7 +2153,6 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, mp_clear(&key->priv); havePriv = 0; } else { - keyPriv = &key->priv; WOLFSSL_MSG("DH Private Key Set"); } } @@ -2172,16 +2170,14 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, if (mp_read_unsigned_bin(&key->pub, pub, pubSz) != MP_OKAY) { mp_clear(&key->pub); havePub = 0; + if (havePriv) { + mp_clear(&key->priv); + havePriv = 0; /* set to 0 to error out with failed read pub */ + } } else { - keyPub = &key->pub; WOLFSSL_MSG("DH Public Key Set"); } } - /* Free Memory if error occurred */ - if (havePriv == 0 && keyPriv != NULL) - mp_clear(keyPriv); - if (havePub == 0 && keyPub != NULL) - mp_clear(keyPub); if (havePriv == 0 && havePub == 0) { return MEMORY_E; diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index dbfa010ef..53a8d6099 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -1,6 +1,6 @@ /* dsa.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index f073f0c3a..7f34a6d95 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1,6 +1,6 @@ /* ecc.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -49,17 +49,21 @@ Possible ECC enable options: * Includes the curve "a" variable in calculation * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off * ECC_CACHE_CURVE: Enables cache of curve info to improve performance - default: off + * default: off * FP_ECC: ECC Fixed Point Cache default: off + * FP cache is not supported for SECP160R1, SECP160R2, + * SECP160K1 and SECP224K1. These do not work with scalars + * that are the length of the order when the order is + * longer than the prime. * USE_ECC_B_PARAM: Enable ECC curve B param default: off - (on for HAVE_COMP_KEY) + * (on for HAVE_COMP_KEY) * WOLFSSL_ECC_CURVE_STATIC: default off (on for windows) - For the ECC curve paramaters `ecc_set_type` use fixed - array for hex string - * WC_ECC_NONBLOCK: Enable non-blocking support for sign/verify. - Requires SP with WOLFSSL_SP_NONBLOCK - * WC_ECC_NONBLOCK_ONLY Enable the non-blocking function only, no fall-back to - normal blocking API's + * For the ECC curve paramaters `ecc_set_type` use fixed + * array for hex string + * WC_ECC_NONBLOCK: Enable non-blocking support for sign/verify. + * Requires SP with WOLFSSL_SP_NONBLOCK + * WC_ECC_NONBLOCK_ONLY Enable the non-blocking function only, no fall-back to + * normal blocking API's * WOLFSSL_ECDSA_SET_K: Enables the setting of the 'k' value to use during ECDSA * signing. If the value is invalid, a new random 'k' is * generated in the loop. (For testing) @@ -127,7 +131,9 @@ ECC Curve Sizes: #include #endif -#ifdef HAVE_ECC_ENCRYPT +#if defined(HAVE_ECC_ENCRYPT) || defined(WOLFSSL_ECDSA_SET_K) || \ + defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K) #include #include #endif @@ -159,6 +165,10 @@ ECC Curve Sizes: #include #endif +#if defined(WOLFSSL_QNX_CAAM) + #include +#endif + #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) #define GEN_MEM_ERR MP_MEM #elif defined(USE_FAST_MATH) @@ -167,6 +177,9 @@ ECC Curve Sizes: #define GEN_MEM_ERR MP_MEM #endif +/* forward declarations */ +static int wc_ecc_new_point_ex(ecc_point** point, void* heap); +static void wc_ecc_del_point_ex(ecc_point* p, void* heap); /* internal ECC states */ enum { @@ -289,6 +302,7 @@ enum { #endif /* HAVE_ECC_SECPR2 */ #endif /* ECC128 */ #ifdef ECC160 +#ifndef FP_ECC #ifndef NO_ECC_SECP #ifdef HAVE_OID_ENCODING #define CODED_SECP160R1 {1,3,132,0,8} @@ -334,6 +348,7 @@ enum { #endif #define ecc_oid_secp160k1_sz CODED_SECP160K1_SZ #endif /* HAVE_ECC_KOBLITZ */ +#endif /* !FP_ECC */ #ifdef HAVE_ECC_BRAINPOOL #ifdef HAVE_OID_ENCODING #define CODED_BRAINPOOLP160R1 {1,3,36,3,3,2,8,1,1,1} @@ -443,7 +458,7 @@ enum { #endif #define ecc_oid_secp224r1_sz CODED_SECP224R1_SZ #endif /* !NO_ECC_SECP */ - #ifdef HAVE_ECC_KOBLITZ + #if defined(HAVE_ECC_KOBLITZ) && !defined(FP_ECC) #ifdef HAVE_OID_ENCODING #define CODED_SECP224K1 {1,3,132,0,32} #define CODED_SECP224K1_SZ 5 @@ -457,7 +472,7 @@ enum { #define ecc_oid_secp224k1 CODED_SECP224K1 #endif #define ecc_oid_secp224k1_sz CODED_SECP224K1_SZ - #endif /* HAVE_ECC_KOBLITZ */ + #endif /* HAVE_ECC_KOBLITZ && !FP_ECC */ #ifdef HAVE_ECC_BRAINPOOL #ifdef HAVE_OID_ENCODING #define CODED_BRAINPOOLP224R1 {1,3,36,3,3,2,8,1,1,5} @@ -731,6 +746,7 @@ const ecc_set_type ecc_sets[] = { #endif /* HAVE_ECC_SECPR2 */ #endif /* ECC128 */ #ifdef ECC160 +#ifndef FP_ECC #ifndef NO_ECC_SECP { 20, /* size/bytes */ @@ -782,6 +798,7 @@ const ecc_set_type ecc_sets[] = { 1, /* cofactor */ }, #endif /* HAVE_ECC_KOBLITZ */ +#endif /* !FP_ECC */ #ifdef HAVE_ECC_BRAINPOOL { 20, /* size/bytes */ @@ -905,7 +922,7 @@ const ecc_set_type ecc_sets[] = { 1, /* cofactor */ }, #endif /* !NO_ECC_SECP */ - #ifdef HAVE_ECC_KOBLITZ + #if defined(HAVE_ECC_KOBLITZ) && !defined(FP_ECC) { 28, /* size/bytes */ ECC_SECP224K1, /* ID */ @@ -921,7 +938,7 @@ const ecc_set_type ecc_sets[] = { ECC_SECP224K1_OID, /* oid sum */ 1, /* cofactor */ }, - #endif /* HAVE_ECC_KOBLITZ */ + #endif /* HAVE_ECC_KOBLITZ && !FP_ECC */ #ifdef HAVE_ECC_BRAINPOOL { 28, /* size/bytes */ @@ -1134,6 +1151,26 @@ const ecc_set_type ecc_sets[] = { }, #endif /* !NO_ECC_SECP */ #endif /* ECC521 */ +#ifdef WOLFCRYPT_HAVE_SAKKE + { + 128, + ECC_SAKKE_1, + "SAKKE1", + "997ABB1F0A563FDA65C61198DAD0657A416C0CE19CB48261BE9AE358B3E01A2EF40AAB27E2FC0F1B228730D531A59CB0E791B39FF7C88A19356D27F4A666A6D0E26C6487326B4CD4512AC5CD65681CE1B6AFF4A831852A82A7CF3C521C3C09AA9F94D6AF56971F1FFCE3E82389857DB080C5DF10AC7ACE87666D807AFEA85FEB", + "997ABB1F0A563FDA65C61198DAD0657A416C0CE19CB48261BE9AE358B3E01A2EF40AAB27E2FC0F1B228730D531A59CB0E791B39FF7C88A19356D27F4A666A6D0E26C6487326B4CD4512AC5CD65681CE1B6AFF4A831852A82A7CF3C521C3C09AA9F94D6AF56971F1FFCE3E82389857DB080C5DF10AC7ACE87666D807AFEA85FE8", + "0", + "265EAEC7C2958FF69971846636B4195E905B0338672D20986FA6B8D62CF8068BBD02AAC9F8BF03C6C8A1CC354C69672C39E46CE7FDF222864D5B49FD2999A9B4389B1921CC9AD335144AB173595A07386DABFD2A0C614AA0A9F3CF14870F026AA7E535ABD5A5C7C7FF38FA08E2615F6C203177C42B1EB3A1D99B601EBFAA17FB", + "53FC09EE332C29AD0A7990053ED9B52A2B1A2FD60AEC69C698B2F204B6FF7CBFB5EDB6C0F6CE2308AB10DB9030B09E1043D5F22CDB9DFA55718BD9E7406CE8909760AF765DD5BCCB337C86548B72F2E1A702C3397A60DE74A7C1514DBA66910DD5CFB4CC80728D87EE9163A5B63F73EC80EC46C4967E0979880DC8ABEAE63895", + "0A8249063F6009F1F9F1F0533634A135D3E82016029906963D778D821E141178F5EA69F4654EC2B9E7F7F5E5F0DE55F66B598CCF9A140B2E416CFF0CA9E032B970DAE117AD547C6CCAD696B5B7652FE0AC6F1E80164AA989492D979FC5A4D5F213515AD7E9CB99A980BDAD5AD5BB4636ADB9B5706A67DCDE75573FD71BEF16D7", + #ifndef WOLFSSL_ECC_CURVE_STATIC + NULL, 0, + #else + {0}, 0, + #endif + 0, + 4, + }, +#endif #if defined(WOLFSSL_CUSTOM_CURVES) && defined(ECC_CACHE_CURVE) /* place holder for custom curve index for cache */ { @@ -1178,7 +1215,8 @@ static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); #if (defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)) && \ - !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) + !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ + !defined(WOLFSSL_CRYPTOCELL) static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, mp_int* prime, mp_int* order); #endif @@ -1245,7 +1283,7 @@ enum ecc_curve_load_mask { #endif #define DECLARE_CURVE_SPECS(curve, intcount) ecc_curve_spec* curve = NULL - #define ALLOC_CURVE_SPECS(intcount) + #define ALLOC_CURVE_SPECS(intcount, err) #define FREE_CURVE_SPECS() #elif defined(WOLFSSL_SMALL_STACK) #define DECLARE_CURVE_SPECS(curve, intcount) \ @@ -1255,12 +1293,13 @@ enum ecc_curve_load_mask { XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ curve->spec_count = intcount - #define ALLOC_CURVE_SPECS(intcount) \ + #define ALLOC_CURVE_SPECS(intcount, err) \ spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \ DYNAMIC_TYPE_ECC); \ if (spec_ints == NULL) \ - return MEMORY_E; \ - curve->spec_ints = spec_ints + err = MEMORY_E; \ + else \ + curve->spec_ints = spec_ints #define FREE_CURVE_SPECS() \ XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC) #else @@ -1271,7 +1310,7 @@ enum ecc_curve_load_mask { XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ curve->spec_ints = spec_ints; \ curve->spec_count = intcount - #define ALLOC_CURVE_SPECS(intcount) + #define ALLOC_CURVE_SPECS(intcount, err) #define FREE_CURVE_SPECS() #endif /* ECC_CACHE_CURVE */ @@ -1327,7 +1366,7 @@ static void wc_ecc_curve_free(ecc_curve_spec* curve) } } -static int wc_ecc_curve_cache_load_item(ecc_curve_spec* curve, const char* src, +static int wc_ecc_curve_cache_load_item(ecc_curve_spec* curve, const char* src, mp_int** dst, byte mask) { int err; @@ -1513,7 +1552,7 @@ const char* wc_ecc_get_name(int curve_id) int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) { - if (keysize <= 0 && curve_id < 0) { + if (key == NULL || (keysize <= 0 && curve_id < 0)) { return BAD_FUNC_ARG; } @@ -2250,7 +2289,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, #endif } - +#if !defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_STM32_PKA) /** Map a projective Jacobian point back to affine space P [in/out] The point to map @@ -2469,6 +2508,7 @@ done: return ECC_BAD_ARG_E; #endif } +#endif /* !FREESCALE_LTC_ECC && !WOLFSSL_STM32_PKA */ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) { @@ -2486,8 +2526,8 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) #define WINSIZE 4 #define M_POINTS 8 -static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M, - mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng) +static int ecc_mulmod(const mp_int* k, ecc_point* tG, ecc_point* R, + ecc_point** M, mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng) { int err = MP_OKAY; int i; @@ -2707,8 +2747,8 @@ static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p, * * Assumes: k < order. */ -static int ecc_mulmod(mp_int* k, ecc_point* P, ecc_point* Q, ecc_point** R, - mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng) +static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q, + ecc_point** R, mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng) { int err = MP_OKAY; int bytes = (mp_count_bits(modulus) + 7) / 8; @@ -2718,6 +2758,7 @@ static int ecc_mulmod(mp_int* k, ecc_point* P, ecc_point* Q, ecc_point** R, int t = 0; mp_digit b; mp_digit v = 0; + mp_int* kt = R[2]->x; #ifndef WC_NO_CACHE_RESISTANT /* First bit always 1 (fix at end) and swap equals first bit */ int swap = 1; @@ -2754,12 +2795,15 @@ static int ecc_mulmod(mp_int* k, ecc_point* P, ecc_point* Q, ecc_point** R, if (cnt > t) { cnt = t; } - err = mp_grow(k, modulus->used + 1); + err = mp_copy(k, kt); + } + if (err == MP_OKAY) { + err = mp_grow(kt, modulus->used + 1); } /* Step 2: for j = 1 to t-1 do */ for (i = 1; (err == MP_OKAY) && (i < t); i++) { if (--cnt == 0) { - v = k->dp[j++]; + v = kt->dp[j++]; cnt = DIGIT_BIT; } @@ -2850,7 +2894,7 @@ static int ecc_mulmod(mp_int* k, ecc_point* P, ecc_point* Q, ecc_point** R, #endif -/* Convert the point to montogmery form. +/* Convert the point to montgomery form. * * @param [in] p Point to convert. * @param [out] r Point in montgomery form. @@ -2963,18 +3007,22 @@ static void ecc_key_tmp_final(ecc_key* key, void* heap) return MP_OKAY on success */ #ifdef FP_ECC -static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, WC_RNG* rng, int map, void* heap) +static int normal_ecc_mulmod(const mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, WC_RNG* rng, int map, + void* heap) #else -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap) #endif #if !defined(WOLFSSL_SP_MATH) { ecc_point *tG, *M[M_POINTS]; +#ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_tG, lcl_M[M_POINTS]; +#endif int i, err; #ifdef WOLFSSL_SMALL_STACK_CACHE - ecc_key *key = (ecc_key *)XMALLOC(sizeof *key, heap, DYNAMIC_TYPE_ECC); + ecc_key *key = (ecc_key *)XMALLOC(sizeof(*key), heap, DYNAMIC_TYPE_ECC); #endif mp_digit mp; @@ -3000,9 +3048,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, /* alloc ram for window temps */ for (i = 0; i < M_POINTS; i++) { - M[i] = wc_ecc_new_point_h(heap); - if (M[i] == NULL) { - err = MEMORY_E; + #ifdef WOLFSSL_NO_MALLOC + M[i] = &lcl_M[i]; + #endif + err = wc_ecc_new_point_ex(&M[i], heap); + if (err != MP_OKAY) { goto exit; } #ifdef WOLFSSL_SMALL_STACK_CACHE @@ -3011,9 +3061,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, } /* make a copy of G in case R==G */ - tG = wc_ecc_new_point_h(heap); - if (tG == NULL) { - err = MEMORY_E; +#ifdef WOLFSSL_NO_MALLOC + tG = &lcl_tG; +#endif + err = wc_ecc_new_point_ex(&tG, heap); + if (err != MP_OKAY) { goto exit; } if ((err = ecc_point_to_mont(G, tG, modulus, heap)) != MP_OKAY) { @@ -3037,10 +3089,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, exit: /* done */ - wc_ecc_del_point_h(tG, heap); + wc_ecc_del_point_ex(tG, heap); for (i = 0; i < M_POINTS; i++) { - wc_ecc_del_point_h(M[i], heap); + wc_ecc_del_point_ex(M[i], heap); } + #ifdef WOLFSSL_SMALL_STACK_CACHE if (key) { if (R) @@ -3094,12 +3147,15 @@ exit: (1==map, 0 == leave in projective) return MP_OKAY on success */ -int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap) #if !defined(WOLFSSL_SP_MATH) { ecc_point *tG, *M[M_POINTS]; +#ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_tG, lcl_M[M_POINTS]; +#endif int i, err; #ifdef WOLFSSL_SMALL_STACK_CACHE ecc_key key; @@ -3124,11 +3180,13 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, R->key = &key; #endif /* WOLFSSL_SMALL_STACK_CACHE */ - /* alloc ram for window temps */ - for (i = 0; i < M_POINTS; i++) { - M[i] = wc_ecc_new_point_h(heap); - if (M[i] == NULL) { - err = MEMORY_E; + /* alloc ram for window temps */ + for (i = 0; i < M_POINTS; i++) { + #ifdef WOLFSSL_NO_MALLOC + M[i] = &lcl_M[i]; + #endif + err = wc_ecc_new_point_ex(&M[i], heap); + if (err != MP_OKAY) { goto exit; } #ifdef WOLFSSL_SMALL_STACK_CACHE @@ -3137,9 +3195,11 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, } /* make a copy of G in case R==G */ - tG = wc_ecc_new_point_h(heap); - if (tG == NULL) { - err = MEMORY_E; +#ifdef WOLFSSL_NO_MALLOC + tG = &lcl_tG; +#endif + err = wc_ecc_new_point_ex(&tG, heap); + if (err != MP_OKAY) { goto exit; } if ((err = ecc_point_to_mont(G, tG, modulus, heap)) != MP_OKAY) { @@ -3172,15 +3232,15 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, if (err == MP_OKAY) err = mp_sub_d(order, 1, &t); if (err == MP_OKAY) { - int kIsMinusOne = (mp_cmp(k, &t) == MP_EQ); + int kIsMinusOne = (mp_cmp((mp_int*)k, &t) == MP_EQ); err = mp_cond_copy(tG->x, kIsMinusOne, R->x); - if (err == 0) { + if (err == MP_OKAY) { err = mp_sub(modulus, tG->y, &t); } - if (err == 0) { + if (err == MP_OKAY) { err = mp_cond_copy(&t, kIsMinusOne, R->y); } - if (err == 0) { + if (err == MP_OKAY) { err = mp_cond_copy(tG->z, kIsMinusOne, R->z); } } @@ -3198,9 +3258,9 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, exit: /* done */ - wc_ecc_del_point_h(tG, heap); + wc_ecc_del_point_ex(tG, heap); for (i = 0; i < M_POINTS; i++) { - wc_ecc_del_point_h(M[i], heap); + wc_ecc_del_point_ex(M[i], heap); } #ifdef WOLFSSL_SMALL_STACK_CACHE R->key = NULL; @@ -3251,7 +3311,7 @@ exit: otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map) { return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); @@ -3260,25 +3320,37 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, #endif /* !WOLFSSL_ATECC508A */ /** + * Allocate a new ECC point (if one not provided) * use a heap hint when creating new ecc_point * return an allocated point on success or NULL on failure - */ -ecc_point* wc_ecc_new_point_h(void* heap) +*/ +static int wc_ecc_new_point_ex(ecc_point** point, void* heap) { + int err = MP_OKAY; ecc_point* p; - (void)heap; + if (point == NULL) { + return BAD_FUNC_ARG; + } - p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC); + p = *point; +#ifndef WOLFSSL_NO_MALLOC if (p == NULL) { - return NULL; + p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC); + } +#endif + if (p == NULL) { + return MEMORY_E; } XMEMSET(p, 0, sizeof(ecc_point)); #ifndef ALT_ECC_SIZE - if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) { + err = mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifndef WOLFSSL_NO_MALLOC XFREE(p, heap, DYNAMIC_TYPE_ECC); - return NULL; + #endif + return err; } #else p->x = (mp_int*)&p->xyz[0]; @@ -3289,39 +3361,54 @@ ecc_point* wc_ecc_new_point_h(void* heap) alt_fp_init(p->z); #endif - return p; + *point = p; + (void)heap; + return err; +} +ecc_point* wc_ecc_new_point_h(void* heap) +{ + ecc_point* p = NULL; + (void)wc_ecc_new_point_ex(&p, heap); + return p; } - - -/** - Allocate a new ECC point - return A newly allocated point or NULL on error -*/ ecc_point* wc_ecc_new_point(void) { - return wc_ecc_new_point_h(NULL); + ecc_point* p = NULL; + (void)wc_ecc_new_point_ex(&p, NULL); + return p; } - -void wc_ecc_del_point_h(ecc_point* p, void* heap) -{ - /* prevents free'ing null arguments */ - if (p != NULL) { - mp_clear(p->x); - mp_clear(p->y); - mp_clear(p->z); - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } - (void)heap; -} - - /** Free an ECC point from memory p The point to free */ +static void wc_ecc_del_point_ex(ecc_point* p, void* heap) +{ + if (p != NULL) { + mp_clear(p->x); + mp_clear(p->y); + mp_clear(p->z); + #ifndef WOLFSSL_NO_MALLOC + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } + (void)heap; +} +void wc_ecc_del_point_h(ecc_point* p, void* heap) +{ + wc_ecc_del_point_ex(p, heap); +} void wc_ecc_del_point(ecc_point* p) { - wc_ecc_del_point_h(p, NULL); + wc_ecc_del_point_ex(p, NULL); +} + +void wc_ecc_forcezero_point(ecc_point* p) +{ + if (p != NULL) { + mp_forcezero(p->x); + mp_forcezero(p->y); + mp_forcezero(p->z); + } } @@ -3329,7 +3416,7 @@ void wc_ecc_del_point(ecc_point* p) p The point to copy r The created point */ -int wc_ecc_copy_point(ecc_point* p, ecc_point *r) +int wc_ecc_copy_point(const ecc_point* p, ecc_point *r) { int ret; @@ -3799,8 +3886,8 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, } /* Verify domain params supplied */ - if (wc_ecc_is_valid_idx(private_key->idx) == 0 || - wc_ecc_is_valid_idx(public_key->idx) == 0) { + if (wc_ecc_is_valid_idx(private_key->idx) == 0 || private_key->dp == NULL || + wc_ecc_is_valid_idx(public_key->idx) == 0 || public_key->dp == NULL) { return ECC_BAD_ARG_E; } @@ -3824,7 +3911,7 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, err = CRYS_ECDH_SVDP_DH(&public_key->ctx.pubKey, &private_key->ctx.privKey, out, - outlen, + (uint32_t*)outlen, &tempBuff); if (err != SA_SILIB_RET_OK){ @@ -3850,13 +3937,19 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, int err = MP_OKAY; #if !defined(WOLFSSL_SP_MATH) ecc_point* result = NULL; + #ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_result; + #endif word32 x = 0; #endif mp_int* k = &private_key->k; #ifdef HAVE_ECC_CDH mp_int k_lcl; +#endif WOLFSSL_ENTER("wc_ecc_shared_secret_gen_sync"); + +#ifdef HAVE_ECC_CDH /* if cofactor flag has been set */ if (private_key->flags & WC_ECC_FLAG_COFACTOR) { mp_digit cofactor = (mp_digit)private_key->dp->cofactor; @@ -3873,8 +3966,6 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, } } } -#else - WOLFSSL_ENTER("wc_ecc_shared_secret_gen_sync"); #endif #ifdef WOLFSSL_HAVE_SP_ECC @@ -3909,13 +4000,16 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, mp_digit mp = 0; /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { -#ifdef HAVE_ECC_CDH + #ifdef WOLFSSL_NO_MALLOC + result = &lcl_result; + #endif + err = wc_ecc_new_point_ex(&result, private_key->heap); + if (err != MP_OKAY) { + #ifdef HAVE_ECC_CDH if (k == &k_lcl) mp_clear(k); -#endif - return MEMORY_E; + #endif + return err; } #ifdef ECC_TIMING_RESISTANT @@ -3956,7 +4050,7 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, } *outlen = x; - wc_ecc_del_point_h(result, private_key->heap); + wc_ecc_del_point_ex(result, private_key->heap); } #endif #ifdef HAVE_ECC_CDH @@ -3977,7 +4071,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, int err; #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) - if (private_key->dp + if (private_key->dp #ifdef WOLFSSL_CUSTOM_CURVES && private_key->dp->id != ECC_CURVE_CUSTOM #endif @@ -4039,7 +4133,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, byte* out, word32 *outlen) { - int err; + int err = MP_OKAY; DECLARE_CURVE_SPECS(curve, 3); if (private_key == NULL || point == NULL || out == NULL || @@ -4048,9 +4142,12 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, } /* load curve info */ - ALLOC_CURVE_SPECS(3); - err = wc_ecc_curve_load(private_key->dp, &curve, + ALLOC_CURVE_SPECS(3, err); + if (err == MP_OKAY) { + err = wc_ecc_curve_load(private_key->dp, &curve, (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER)); + } + if (err != MP_OKAY) { FREE_CURVE_SPECS(); return err; @@ -4101,7 +4198,7 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, } /* Verify domain params supplied */ - if (wc_ecc_is_valid_idx(private_key->idx) == 0) { + if (wc_ecc_is_valid_idx(private_key->idx) == 0 || private_key->dp == NULL) { WOLFSSL_MSG("wc_ecc_is_valid_idx failed"); return ECC_BAD_ARG_E; } @@ -4161,21 +4258,23 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, /* Checks if a point p lies on the curve with index curve_idx */ int wc_ecc_point_is_on_curve(ecc_point *p, int curve_idx) { - int err; + int err = MP_OKAY; DECLARE_CURVE_SPECS(curve, 3); if (p == NULL) return BAD_FUNC_ARG; /* is the IDX valid ? */ - if (wc_ecc_is_valid_idx(curve_idx) != 1) { + if (wc_ecc_is_valid_idx(curve_idx) == 0) { return ECC_BAD_ARG_E; } - ALLOC_CURVE_SPECS(3); - err = wc_ecc_curve_load(wc_ecc_get_curve_params(curve_idx), &curve, + ALLOC_CURVE_SPECS(3, err); + if (err == MP_OKAY) { + err = wc_ecc_curve_load(wc_ecc_get_curve_params(curve_idx), &curve, ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_BF); + } if (err == MP_OKAY) { err = wc_ecc_is_point(p, curve->Af, curve->Bf, curve->prime); } @@ -4209,8 +4308,12 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) int err; byte buf[ECC_MAXSIZE_GEN]; - /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ - /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ + if (rng == NULL || size > ECC_MAXSIZE_GEN || k == NULL || order == NULL) { + return BAD_FUNC_ARG; + } + + /* generate 8 extra bytes to mitigate bias from the modulo operation below */ + /* see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)' */ size += 8; /* make up random string */ @@ -4218,7 +4321,7 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) /* load random buffer data into k */ if (err == 0) - err = mp_read_unsigned_bin(k, (byte*)buf, size); + err = mp_read_unsigned_bin(k, buf, size); /* the key should be smaller than the order of base point */ if (err == MP_OKAY) { @@ -4272,6 +4375,9 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, && !defined(WOLFSSL_SILABS_SE_ACCEL) #if !defined(WOLFSSL_SP_MATH) ecc_point* base = NULL; + #ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_base; + #endif #endif ecc_point* pub; DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); @@ -4304,7 +4410,9 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, else { /* load curve info */ if (err == MP_OKAY) { - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); + } + if (err == MP_OKAY) { err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); } } @@ -4350,10 +4458,11 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, #else { mp_digit mp = 0; + #ifdef WOLFSSL_NO_MALLOC + base = &lcl_base; + #endif + err = wc_ecc_new_point_ex(&base, key->heap); - base = wc_ecc_new_point_h(key->heap); - if (base == NULL) - err = MEMORY_E; /* read in the x/y for this key */ if (err == MP_OKAY) err = mp_copy(curve->Gx, base->x); @@ -4378,7 +4487,7 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, err = ecc_map_ex(pub, curve->prime, mp, 1); } - wc_ecc_del_point_h(base, key->heap); + wc_ecc_del_point_ex(base, key->heap); } #endif @@ -4542,7 +4651,7 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, } #elif defined(WOLFSSL_CRYPTOCELL) - pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(key->dp->id)); raw_size = (word32)(key->dp->size)*2 + 1; /* generate first key pair */ @@ -4563,7 +4672,7 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, err = CRYS_ECPKI_ExportPublKey(&key->ctx.pubKey, CRYS_EC_PointUncompressed, &ucompressed_key[0], - &raw_size); + (uint32_t*)&raw_size); if (err == SA_SILIB_RET_OK && key->pubkey.x && key->pubkey.y) { err = mp_read_unsigned_bin(key->pubkey.x, @@ -4577,7 +4686,7 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, if (err == MP_OKAY) { err = CRYS_ECPKI_ExportPrivKey(&key->ctx.privKey, ucompressed_key, - &raw_size); + (uint32_t*)&raw_size); } if (err == SA_SILIB_RET_OK) { @@ -4619,7 +4728,9 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id, /* load curve info */ if (err == MP_OKAY) { - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); + } + if (err == MP_OKAY) { err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); } @@ -4729,11 +4840,15 @@ static void wc_ecc_dump_oids(void) WOLFSSL_ABI ecc_key* wc_ecc_key_new(void* heap) { + int devId = INVALID_DEVID; ecc_key* key; +#ifdef WOLFSSL_QNX_CAAM + devId = WOLFSSL_CAAM_DEVID; +#endif key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); if (key) { - if (wc_ecc_init_ex(key, heap, INVALID_DEVID) != 0) { + if (wc_ecc_init_ex(key, heap, devId) != 0) { XFREE(key, heap, DYNAMIC_TYPE_ECC); key = NULL; } @@ -4836,7 +4951,11 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) int wc_ecc_init(ecc_key* key) { +#ifdef WOLFSSL_QNX_CAAM + return wc_ecc_init_ex(key, NULL, WOLFSSL_CAAM_DEVID); +#else return wc_ecc_init_ex(key, NULL, INVALID_DEVID); +#endif } #ifdef WOLF_CRYPTO_CB @@ -4896,12 +5015,15 @@ int wc_ecc_set_flags(ecc_key* key, word32 flags) static int wc_ecc_get_curve_order_bit_count(const ecc_set_type* dp) { - int err; + int err = MP_OKAY; word32 orderBits; DECLARE_CURVE_SPECS(curve, 1); - ALLOC_CURVE_SPECS(1); - err = wc_ecc_curve_load(dp, &curve, ECC_CURVE_FIELD_ORDER); + ALLOC_CURVE_SPECS(1, err); + if (err == MP_OKAY) { + err = wc_ecc_curve_load(dp, &curve, ECC_CURVE_FIELD_ORDER); + } + if (err != 0) { FREE_CURVE_SPECS(); return err; @@ -4979,7 +5101,8 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, } hash_mode = cc310_hashModeECC(msgLenInBytes); if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) { - hash_mode = cc310_hashModeECC(keysize); + (void)cc310_hashModeECC(keysize); + /* Ignoring returned value */ hash_mode = CRYS_ECPKI_HASH_SHA256_mode; } @@ -4993,7 +5116,7 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, (byte*)in, msgLenInBytes, out, - &raw_sig_size); + (uint32_t*)&raw_sig_size); if (err != SA_SILIB_RET_OK){ WOLFSSL_MSG("CRYS_ECDSA_Sign failed"); @@ -5126,8 +5249,7 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, #endif #endif - if (in == NULL || out == NULL || outlen == NULL || key == NULL || - rng == NULL) { + if (in == NULL || out == NULL || outlen == NULL || key == NULL) { return ECC_BAD_ARG_E; } @@ -5140,6 +5262,11 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, } #endif + if (rng == NULL) { + WOLFSSL_MSG("rng was NULL"); + return ECC_BAD_ARG_E; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) /* handle async cases */ err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key); @@ -5201,6 +5328,51 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, } #endif /* !NO_ASN */ +#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) +/* returns MP_OKAY on success */ +static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key) +{ + int err = MP_OKAY; + DECLARE_CURVE_SPECS(curve, 1); + ALLOC_CURVE_SPECS(1, err); + + /* get curve order */ + if (err == MP_OKAY) { + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + } + + if (err == MP_OKAY) { + /* if key->sign_k is NULL then create a buffer for the mp_int + * if not NULL then assume the user correctly set deterministic flag and + * that the key->sign_k holds a previously malloc'd mp_int buffer */ + if (key->sign_k == NULL) { + key->sign_k = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, + DYNAMIC_TYPE_ECC); + } + + if (key->sign_k) { + /* currently limiting to SHA256 for auto create */ + if (mp_init(key->sign_k) != MP_OKAY || + wc_ecc_gen_deterministic_k(in, inlen, + WC_HASH_TYPE_SHA256, &key->k, key->sign_k, + curve->order, key->heap) != 0) { + mp_free(key->sign_k); + XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); + key->sign_k = NULL; + err = ECC_PRIV_KEY_E; + } + } + else { + err = MEMORY_E; + } + } + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + return err; +} +#endif /* WOLFSSL_ECDSA_DETERMINISTIC_K */ + #if defined(WOLFSSL_STM32_PKA) int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, ecc_key* key, mp_int *r, mp_int *s) @@ -5209,6 +5381,160 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #elif !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ !defined(WOLFSSL_CRYPTOCELL) +#ifndef WOLFSSL_SP_MATH +static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, + ecc_curve_spec* curve, mp_int* e, mp_int* r, + mp_int* s) +{ + int err = MP_OKAY; + int loop_check = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* b = NULL; +#else + mp_int b[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (b == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + err = mp_init(b); + } + +#ifdef WOLFSSL_CUSTOM_CURVES + /* if custom curve, apply params to pubkey */ + if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) { + err = wc_ecc_set_custom_curve(pubkey, key->dp); + } +#endif + + if (err == MP_OKAY) { + /* Generate blinding value - non-zero value. */ + do { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } + + err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order); + } + while (err == MP_ZERO_E); + loop_check = 0; + } + + for (; err == MP_OKAY;) { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } +#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K) + if (key->sign_k != NULL) { + if (loop_check > 1) { + err = RNG_FAILURE_E; + break; + } + + /* use provided sign_k */ + err = mp_copy(key->sign_k, &pubkey->k); + if (err != MP_OKAY) break; + + /* free sign_k, so only used once */ + mp_forcezero(key->sign_k); + mp_free(key->sign_k); + XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); + key->sign_k = NULL; + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + loop_check = 64; + #endif + #ifdef WOLFSSL_ECDSA_DETERMINISTIC_K + if (key->deterministic == 1) { + /* sign_k generated earlier in function for SP calls. + * Only go through the loop once and fail if error */ + loop_check = 64; + } + #endif + + /* compute public key based on provided "k" */ + err = ecc_make_pub_ex(pubkey, curve, NULL, rng); + } + else +#endif + { + err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey, + key->dp->id); + } + if (err != MP_OKAY) break; + + /* find r = x1 mod n */ + err = mp_mod(pubkey->pubkey.x, curve->order, r); + if (err != MP_OKAY) break; + + if (mp_iszero(r) == MP_NO) { + mp_int* ep = &pubkey->k; + mp_int* kp = &pubkey->k; + mp_int* x = &key->k; + + /* find s = (e + xr)/k + = b.(e/k.b + x.r/k.b) */ + + /* k' = k.b */ + err = mp_mulmod(&pubkey->k, b, curve->order, kp); + if (err != MP_OKAY) break; + + /* k' = 1/k.b + = 1/k' */ + err = mp_invmod(kp, curve->order, kp); + if (err != MP_OKAY) break; + + /* s = x.r */ + err = mp_mulmod(x, r, curve->order, s); + if (err != MP_OKAY) break; + + /* s = x.r/k.b + = k'.s */ + err = mp_mulmod(kp, s, curve->order, s); + if (err != MP_OKAY) break; + + /* e' = e/k.b + = e.k' */ + err = mp_mulmod(kp, e, curve->order, ep); + if (err != MP_OKAY) break; + + /* s = e/k.b + x.r/k.b = (e + x.r)/k.b + = e' + s */ + err = mp_addmod_ct(ep, s, curve->order, s); + if (err != MP_OKAY) break; + + /* s = b.(e + x.r)/k.b = (e + x.r)/k + = b.s */ + err = mp_mulmod(s, b, curve->order, s); + if (err != MP_OKAY) break; + + if (mp_iszero(s) == MP_NO) { + /* sign successful */ + break; + } + } + #ifndef ALT_ECC_SIZE + mp_clear(pubkey->pubkey.x); + mp_clear(pubkey->pubkey.y); + mp_clear(pubkey->pubkey.z); + #endif + mp_forcezero(&pubkey->k); + } + mp_clear(b); +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif + /** Sign a message digest in The message digest to sign @@ -5230,6 +5556,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #endif #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA))) DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); @@ -5248,26 +5575,36 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } /* is the IDX valid ? */ - if (wc_ecc_is_valid_idx(key->idx) != 1) { + if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { return ECC_BAD_ARG_E; } #if defined(WOLFSSL_SP_MATH) - if (key->idx == ECC_CUSTOM_IDX || - (ecc_sets[key->idx].id != ECC_SECP256R1 && + if (key->idx == ECC_CUSTOM_IDX || + (ecc_sets[key->idx].id != ECC_SECP256R1 && ecc_sets[key->idx].id != ECC_SECP384R1)) { return WC_KEY_SIZE_E; } #endif -#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \ - defined(WOLFSSL_HAVE_SP_ECC) +#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) + /* generate deterministic 'k' value to be used either with SP or normal */ + if (key->deterministic == 1) { + if (deterministic_sign_helper(in, inlen, key)) { + WOLFSSL_MSG("Error generating deterministic k to sign"); + return ECC_PRIV_KEY_E; + } + } +#endif + +#if defined(WOLFSSL_HAVE_SP_ECC) if (key->idx != ECC_CUSTOM_IDX #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC #endif ) { - #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) + #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) \ + || defined(WOLFSSL_ECDSA_DETERMINISTIC_K) mp_int* sign_k = key->sign_k; #else mp_int* sign_k = NULL; @@ -5281,19 +5618,19 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (ecc_sets[key->idx].id == ECC_SECP256R1) { #ifdef WC_ECC_NONBLOCK if (key->nb_ctx) { - return sp_ecc_sign_256_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, + return sp_ecc_sign_256_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, &key->k, r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ - err = sp_ecc_sign_256_nb(&nb_ctx.sp_ctx, in, inlen, rng, + err = sp_ecc_sign_256_nb(&nb_ctx.sp_ctx, in, inlen, rng, &key->k, r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif #endif /* WC_ECC_NONBLOCK */ #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, sign_k, + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, sign_k, key->heap); #endif } @@ -5302,19 +5639,19 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (ecc_sets[key->idx].id == ECC_SECP384R1) { #ifdef WC_ECC_NONBLOCK if (key->nb_ctx) { - return sp_ecc_sign_384_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, + return sp_ecc_sign_384_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, &key->k, r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ - err = sp_ecc_sign_384_nb(&nb_ctx.sp_ctx, in, inlen, rng, + err = sp_ecc_sign_384_nb(&nb_ctx.sp_ctx, in, inlen, rng, &key->k, r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif #endif /* WC_ECC_NONBLOCK */ #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, sign_k, + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, sign_k, key->heap); #endif } @@ -5368,22 +5705,26 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } /* load curve info */ -#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); +#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K) + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); #else - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); - } - else - #endif - { - ALLOC_CURVE_SPECS(1); - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); - } + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + } + else + #endif + { + ALLOC_CURVE_SPECS(1, err); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + } #endif /* load digest into e */ @@ -5394,7 +5735,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, /* truncate down to byte size, may be all that's needed */ if ((WOLFSSL_BIT_SIZE * inlen) > orderBits) inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; - err = mp_read_unsigned_bin(e, (byte*)in, inlen); + err = mp_read_unsigned_bin(e, in, inlen); /* may still need bit truncation too */ if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits) @@ -5403,7 +5744,6 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, /* make up a key and export the public copy */ if (err == MP_OKAY) { - int loop_check = 0; #ifdef WOLFSSL_SMALL_STACK ecc_key* pubkey; #else @@ -5491,149 +5831,15 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #endif /* don't use async for key, since we don't support async return here */ - if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap, - INVALID_DEVID)) == MP_OKAY) { - #ifdef WOLFSSL_SMALL_STACK - mp_int* b = NULL; - #else - mp_int b[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + err = wc_ecc_init_ex(pubkey, key->heap, INVALID_DEVID); if (err == MP_OKAY) { - b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, - DYNAMIC_TYPE_ECC); - if (b == NULL) - err = MEMORY_E; - } - #endif - - if (err == MP_OKAY) { - err = mp_init(b); - } - - #ifdef WOLFSSL_CUSTOM_CURVES - /* if custom curve, apply params to pubkey */ - if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) { - err = wc_ecc_set_custom_curve(pubkey, key->dp); - } - #endif - - if (err == MP_OKAY) { - /* Generate blinding value - non-zero value. */ - do { - if (++loop_check > 64) { - err = RNG_FAILURE_E; - break; - } - - err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order); - } - while (err == MP_ZERO_E); - loop_check = 0; - } - - for (; err == MP_OKAY;) { - if (++loop_check > 64) { - err = RNG_FAILURE_E; - break; - } - #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) - if (key->sign_k != NULL) { - if (loop_check > 1) { - err = RNG_FAILURE_E; - break; - } - - /* use provided sign_k */ - err = mp_copy(key->sign_k, &pubkey->k); - if (err != MP_OKAY) break; - - /* free sign_k, so only used once */ - mp_forcezero(key->sign_k); - mp_free(key->sign_k); - XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); - key->sign_k = NULL; - #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - loop_check = 64; + err = ecc_sign_hash_sw(key, pubkey, rng, curve, e, r, s); + wc_ecc_free(pubkey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC); #endif - - /* compute public key based on provided "k" */ - err = ecc_make_pub_ex(pubkey, curve, NULL, rng); - } - else - #endif - { - err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey, - key->dp->id); - } - if (err != MP_OKAY) break; - - /* find r = x1 mod n */ - err = mp_mod(pubkey->pubkey.x, curve->order, r); - if (err != MP_OKAY) break; - - if (mp_iszero(r) == MP_NO) { - mp_int* ep = &pubkey->k; - mp_int* kp = &pubkey->k; - mp_int* x = &key->k; - - /* find s = (e + xr)/k - = b.(e/k.b + x.r/k.b) */ - - /* k' = k.b */ - err = mp_mulmod(&pubkey->k, b, curve->order, kp); - if (err != MP_OKAY) break; - - /* k' = 1/k.b - = 1/k' */ - err = mp_invmod(kp, curve->order, kp); - if (err != MP_OKAY) break; - - /* s = x.r */ - err = mp_mulmod(x, r, curve->order, s); - if (err != MP_OKAY) break; - - /* s = x.r/k.b - = k'.s */ - err = mp_mulmod(kp, s, curve->order, s); - if (err != MP_OKAY) break; - - /* e' = e/k.b - = e.k' */ - err = mp_mulmod(kp, e, curve->order, ep); - if (err != MP_OKAY) break; - - /* s = e/k.b + x.r/k.b = (e + x.r)/k.b - = e' + s */ - err = mp_addmod_ct(ep, s, curve->order, s); - if (err != MP_OKAY) break; - - /* s = b.(e + x.r)/k.b = (e + x.r)/k - = b.s */ - err = mp_mulmod(s, b, curve->order, s); - if (err != MP_OKAY) break; - - if (mp_iszero(s) == MP_NO) { - /* sign successful */ - break; - } - } - #ifndef ALT_ECC_SIZE - mp_clear(pubkey->pubkey.x); - mp_clear(pubkey->pubkey.y); - mp_clear(pubkey->pubkey.z); - #endif - mp_forcezero(&pubkey->k); } - mp_clear(b); - #ifdef WOLFSSL_SMALL_STACK - XFREE(b, key->heap, DYNAMIC_TYPE_ECC); - #endif - wc_ecc_free(pubkey); - #ifdef WOLFSSL_SMALL_STACK - XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC); - #endif } } @@ -5648,18 +5854,282 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return err; } +#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) +/* helper function to do HMAC operations + * returns 0 on success and updates "out" buffer + */ +static int _HMAC_K(byte* K, word32 KSz, byte* V, word32 VSz, + const byte* h1, word32 h1Sz, byte* x, word32 xSz, byte* oct, + byte* out, enum wc_HashType hashType, void* heap) { + Hmac hmac; + int ret, init; + + ret = init = wc_HmacInit(&hmac, heap, 0); + if (ret == 0) + ret = wc_HmacSetKey(&hmac, hashType, K, KSz); + + if (ret == 0) + ret = wc_HmacUpdate(&hmac, V, VSz); + + if (ret == 0 && oct != NULL) + ret = wc_HmacUpdate(&hmac, oct, 1); + + if (ret == 0) + ret = wc_HmacUpdate(&hmac, x, xSz); + + if (ret == 0) + ret = wc_HmacUpdate(&hmac, h1, h1Sz); + + if (ret == 0) + ret = wc_HmacFinal(&hmac, out); + + if (init == 0) + wc_HmacFree(&hmac); + + return ret; +} + + +/* Generates a deterministic key based of the message using RFC6979 + * @param [in] hash Hash value to sign + * @param [in] hashSz Size of 'hash' buffer passed in + * @param [in] hashType Type of hash to use with deterministic k gen, i.e. + * WC_HASH_TYPE_SHA256 + * @param [in] priv Current ECC private key set + * @param [out] k An initialized mp_int to set the k value generated in + * @param [in] order ECC order parameter to use with generation + * @return 0 on success. + */ +int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz, + enum wc_HashType hashType, mp_int* priv, mp_int* k, mp_int* order, + void* heap) +{ + int ret = 0, qbits = 0; +#ifndef WOLFSSL_SMALL_STACK + byte h1[WC_MAX_DIGEST_SIZE]; + byte V[WC_MAX_DIGEST_SIZE]; + byte K[WC_MAX_DIGEST_SIZE]; + byte x[MAX_ECC_BYTES]; +#else + byte *h1 = NULL; + byte *V = NULL; + byte *K = NULL; + byte *x = NULL; +#endif + word32 xSz, VSz, KSz, h1len; + byte intOct; + mp_int z1; + + if (hash == NULL || k == NULL || order == NULL) { + return BAD_FUNC_ARG; + } + + if (hashSz > WC_MAX_DIGEST_SIZE) { + WOLFSSL_MSG("hash size was too large!"); + return BAD_FUNC_ARG; + } + + if ((xSz = mp_unsigned_bin_size(priv)) > MAX_ECC_BYTES) { + WOLFSSL_MSG("private key larger than max expected!"); + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + h1 = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_DIGEST); + if (h1 == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) { + V = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (V == NULL) + ret = MEMORY_E; + } + + if (ret == 0) { + K = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (K == NULL) + ret = MEMORY_E; + } + + if (ret == 0) { + x = (byte*)XMALLOC(MAX_ECC_BYTES, heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (x == NULL) + ret = MEMORY_E; + } + + /* bail out if any error has been hit at this point */ + if (ret != 0) { + if (x != NULL) + XFREE(x, heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (K != NULL) + XFREE(K, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (V != NULL) + XFREE(V, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (h1 != NULL) + XFREE(h1, heap, DYNAMIC_TYPE_DIGEST); + return ret; + } +#endif + + VSz = KSz = h1len = hashSz; + + /* 3.2 b. Set V = 0x01 0x01 ... */ + XMEMSET(V, 0x01, VSz); + + /* 3.2 c. Set K = 0x00 0x00 ... */ + XMEMSET(K, 0x00, KSz); + + mp_init(&z1); /* always init z1 and free z1 */ + ret = mp_to_unsigned_bin(priv, x); + if (ret == 0) { + qbits = mp_count_bits(order); + ret = mp_read_unsigned_bin(&z1, hash, hashSz); + } + + /* bits2octets on h1 */ + if (ret == 0) { + /* right shift by bits in hash minus bits in order */ + mp_rshb(&z1, (hashSz * WOLFSSL_BIT_SIZE) - qbits); + XMEMSET(h1, 0, sizeof(h1)); + + /* mod reduce by order using conditional subtract */ + if (mp_cmp(&z1, order) == MP_GT) { + mp_sub(&z1, order, &z1); + h1len = mp_unsigned_bin_size(&z1); + if (h1len < 0 || h1len > WC_MAX_DIGEST_SIZE) { + ret = BUFFER_E; + } + else { + ret = mp_to_unsigned_bin(&z1, h1); + } + } + else { + /* use original hash and keep leading 0's */ + h1len = hashSz; + XMEMCPY(h1, hash, hashSz); + } + } + mp_free(&z1); + + /* 3.2 step d. K = HMAC_K(V || 0x00 || int2octests(x) || bits2octests(h1) */ + if (ret == 0) { + intOct = 0x00; + ret = _HMAC_K(K, KSz, V, VSz, h1, h1len, x, xSz, &intOct, K, + hashType, heap); + } + + /* 3.2 step e. V = HMAC_K(V) */ + if (ret == 0) { + ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V, hashType, + heap); + } + + + /* 3.2 step f. K = HMAC_K(V || 0x01 || int2octests(x) || bits2octests(h1) */ + if (ret == 0) { + intOct = 0x01; + ret = _HMAC_K(K, KSz, V, VSz, h1, h1len, x, xSz, &intOct, K, hashType, + heap); + } + + /* 3.2 step g. V = HMAC_K(V) */ + if (ret == 0) { + ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V, hashType, + heap); + } + + /* 3.2 step h. loop through the next steps until a valid value is found */ + if (ret == 0 ) { + int err; + + intOct = 0x00; + do { + err = 0; /* start as good until generated k is tested */ + + /* 3.2 step h.2 when tlen < qlen do V = HMAC_K(V); T = T || V */ + ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V, hashType, + heap); + if (ret == 0) { + mp_clear(k); /* 3.2 step h.1 clear T */ + ret = mp_read_unsigned_bin(k, V, VSz); + } + + if ((ret == 0) && ((int)(VSz * WOLFSSL_BIT_SIZE) != qbits)) { + /* handle odd case where shift of 'k' is needed with RFC 6979 + * k = bits2int(T) in section 3.2 h.3 */ + mp_rshb(k, (VSz * WOLFSSL_BIT_SIZE) - qbits); + } + + /* 3.2 step h.3 the key should be smaller than the order of base + * point */ + if (ret == 0) { + if (mp_cmp(k, order) != MP_LT) { + err = MP_VAL; + } else if (mp_iszero(k) == MP_YES) { + /* no 0 key's */ + err = MP_ZERO_E; + } + } + + /* 3.2 step h.3 if there was a problem with 'k' generated then try + * again K = HMAC_K(V || 0x00) and V = HMAC_K(V) */ + if (ret == 0 && err != 0) { + ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, &intOct, K, + hashType, heap); + if (ret == 0) { + ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V, + hashType, heap); + } + } + } while (ret == 0 && err != 0); + } + +#ifdef WOLFSSL_SMALL_STACK + if (x != NULL) + XFREE(x, heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (K != NULL) + XFREE(K, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (V != NULL) + XFREE(V, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (h1 != NULL) + XFREE(h1, heap, DYNAMIC_TYPE_DIGEST); +#endif + + return ret; +} + + +/* Sets the deterministic flag for 'k' generation with sign. + * returns 0 on success + */ +int wc_ecc_set_deterministic(ecc_key* key, byte flag) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + key->deterministic = flag; + return 0; +} +#endif + + #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key) { - int ret; + int ret = MP_OKAY; DECLARE_CURVE_SPECS(curve, 1); if (k == NULL || klen == 0 || key == NULL) { return BAD_FUNC_ARG; } - ALLOC_CURVE_SPECS(1); - ret = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + ALLOC_CURVE_SPECS(1, ret); + if (ret == MP_OKAY) { + ret = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + } + if (ret != 0) { FREE_CURVE_SPECS(); return ret; @@ -5742,6 +6212,13 @@ int wc_ecc_free(ecc_key* key) wc_ecc_free_async(key); #endif +#ifdef WOLFSSL_QNX_CAAM + /* free secure memory */ + if (key->blackKey > 0) { + caamFreePart(key->partNum); + } +#endif + #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) atmel_ecc_free(key->slot); key->slot = ATECC_INVALID_SLOT; @@ -5819,7 +6296,18 @@ int ecc_projective_add_point_safe(ecc_point* A, ecc_point* B, ecc_point* R, if ((err == MP_OKAY) && mp_iszero(R->z)) { /* When all zero then should have done a double */ if (mp_iszero(R->x) && mp_iszero(R->y)) { - err = ecc_projective_dbl_point(B, R, a, modulus, mp); + if (mp_iszero(B->z)) { + err = wc_ecc_copy_point(B, R); + if (err == MP_OKAY) { + err = mp_montgomery_calc_normalization(R->z, modulus); + } + if (err == MP_OKAY) { + err = ecc_projective_dbl_point(R, R, a, modulus, mp); + } + } + else { + err = ecc_projective_dbl_point(B, R, a, modulus, mp); + } } /* When only Z zero then result is infinity */ else { @@ -5892,10 +6380,18 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point** precomp = NULL; #else ecc_point* precomp[SHAMIR_PRECOMP_SZ]; + #ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_precomp[SHAMIR_PRECOMP_SZ]; + #endif #endif unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; - unsigned char* tA; - unsigned char* tB; +#ifdef WOLFSSL_NO_MALLOC + unsigned char tA[ECC_BUFSIZE]; + unsigned char tB[ECC_BUFSIZE]; +#else + unsigned char* tA = NULL; + unsigned char* tB = NULL; +#endif int err = MP_OKAY, first, x, y; mp_digit mp = 0; @@ -5905,6 +6401,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, return ECC_BAD_ARG_E; } +#ifndef WOLFSSL_NO_MALLOC /* allocate memory */ tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); if (tA == NULL) { @@ -5915,6 +6412,8 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); return GEN_MEM_ERR; } +#endif + #ifdef WOLFSSL_SMALL_STACK precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap, DYNAMIC_TYPE_ECC_BUFFER); @@ -5932,6 +6431,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); #endif + if (key.t1 == NULL || key.t2 == NULL #ifdef ALT_ECC_SIZE || key.x == NULL || key.y == NULL || key.z == NULL @@ -5982,11 +6482,12 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, /* allocate the table */ if (err == MP_OKAY) { for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { - precomp[x] = wc_ecc_new_point_h(heap); - if (precomp[x] == NULL) { - err = GEN_MEM_ERR; + #ifdef WOLFSSL_NO_MALLOC + precomp[x] = &lcl_precomp[x]; + #endif + err = wc_ecc_new_point_ex(&precomp[x], heap); + if (err != MP_OKAY) break; - } #ifdef WOLFSSL_SMALL_STACK_CACHE precomp[x]->key = &key; #endif @@ -6052,12 +6553,11 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) { /* precomp [0,i](A + B) table */ - err = ecc_projective_dbl_point_safe(precomp[1<<2], precomp[2<<2], a, - modulus, mp); + err = ecc_projective_dbl_point_safe(precomp[4], precomp[8], a, modulus, mp); } if (err == MP_OKAY) { - err = ecc_projective_add_point_safe(precomp[1<<2], precomp[2<<2], - precomp[3<<2], a, modulus, mp, NULL); + err = ecc_projective_add_point_safe(precomp[4], precomp[8], precomp[12], a, + modulus, mp, NULL); } if (err == MP_OKAY) { @@ -6080,7 +6580,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, bitbufB = tB[0]; /* for every byte of the multiplicands */ - for (x = 0;; ) { + for (x = 0; x < (int)len || nibble != 3; ) { /* grab a nibble */ if (++nibble == 4) { if (x == (int)len) break; @@ -6147,7 +6647,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, /* clean up */ for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { - wc_ecc_del_point_h(precomp[x], heap); + wc_ecc_del_point_ex(precomp[x], heap); } ForceZero(tA, ECC_BUFSIZE); @@ -6165,9 +6665,10 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, #ifdef WOLFSSL_SMALL_STACK XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); #endif +#ifndef WOLFSSL_NO_MALLOC XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); - +#endif return err; } @@ -6317,13 +6818,16 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, } #endif /* !NO_ASN */ +#if !defined(WOLFSSL_STM32_PKA) && !defined(WOLFSSL_PSOC6_CRYPTO) static int wc_ecc_check_r_s_range(ecc_key* key, mp_int* r, mp_int* s) { - int err; + int err = MP_OKAY; DECLARE_CURVE_SPECS(curve, 1); - ALLOC_CURVE_SPECS(1); - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + ALLOC_CURVE_SPECS(1, err); + if (err == MP_OKAY) { + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + } if (err != 0) { FREE_CURVE_SPECS(); return err; @@ -6343,6 +6847,8 @@ static int wc_ecc_check_r_s_range(ecc_key* key, mp_int* r, mp_int* s) FREE_CURVE_SPECS(); return err; } +#endif /* !WOLFSSL_STM32_PKA && !WOLFSSL_PSOC6_CRYPTO */ + /** Verify an ECC signature @@ -6381,6 +6887,9 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #elif !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; + #ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_mG, lcl_mQ; + #endif #ifdef WOLFSSL_SMALL_STACK mp_int* v = NULL; mp_int* w = NULL; @@ -6409,7 +6918,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, *res = 0; /* is the IDX valid ? */ - if (wc_ecc_is_valid_idx(key->idx) != 1) { + if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { return ECC_BAD_ARG_E; } @@ -6519,25 +7028,24 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC) if (key->handle != -1) { - return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, + return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } if (wolfSSL_GetHandleCbSet() == 1) { - return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, + return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } #endif #if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC) - if (key->idx == ECC_CUSTOM_IDX || - (ecc_sets[key->idx].id != ECC_SECP256R1 && + if (key->idx == ECC_CUSTOM_IDX || + (ecc_sets[key->idx].id != ECC_SECP256R1 && ecc_sets[key->idx].id != ECC_SECP384R1)) { return WC_KEY_SIZE_E; } #endif -#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \ - defined(WOLFSSL_HAVE_SP_ECC) +#if defined(WOLFSSL_HAVE_SP_ECC) if (key->idx != ECC_CUSTOM_IDX #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC @@ -6553,21 +7061,21 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, if (ecc_sets[key->idx].id == ECC_SECP256R1) { #ifdef WC_ECC_NONBLOCK if (key->nb_ctx) { - return sp_ecc_verify_256_nb(&key->nb_ctx->sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + return sp_ecc_verify_256_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ - err = sp_ecc_verify_256_nb(&nb_ctx.sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + err = sp_ecc_verify_256_nb(&nb_ctx.sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif #endif /* WC_ECC_NONBLOCK */ #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); #endif } @@ -6576,21 +7084,21 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, if (ecc_sets[key->idx].id == ECC_SECP384R1) { #ifdef WC_ECC_NONBLOCK if (key->nb_ctx) { - return sp_ecc_verify_384_nb(&key->nb_ctx->sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + return sp_ecc_verify_384_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ - err = sp_ecc_verify_384_nb(&nb_ctx.sp_ctx, hash, hashlen, - key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, + err = sp_ecc_verify_384_nb(&nb_ctx.sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif #endif /* WC_ECC_NONBLOCK */ #if !defined(WC_ECC_NONBLOCK) || (defined(WC_ECC_NONBLOCK) && !defined(WC_ECC_NONBLOCK_ONLY)) - return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, + return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); #endif } @@ -6599,7 +7107,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #endif #if !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) - ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) err = wc_ecc_alloc_mpint(key, &key->e); @@ -6712,10 +7220,16 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* allocate points */ if (err == MP_OKAY) { - mG = wc_ecc_new_point_h(key->heap); - mQ = wc_ecc_new_point_h(key->heap); - if (mQ == NULL || mG == NULL) - err = MEMORY_E; + #ifdef WOLFSSL_NO_MALLOC + mG = &lcl_mG; + #endif + err = wc_ecc_new_point_ex(&mG, key->heap); + } + if (err == MP_OKAY) { + #ifdef WOLFSSL_NO_MALLOC + mQ = &lcl_mQ; + #endif + err = wc_ecc_new_point_ex(&mQ, key->heap); } /* w = s^-1 mod n */ @@ -6809,8 +7323,8 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, } /* cleanup */ - wc_ecc_del_point_h(mG, key->heap); - wc_ecc_del_point_h(mQ, key->heap); + wc_ecc_del_point_ex(mG, key->heap); + wc_ecc_del_point_ex(mQ, key->heap); mp_clear(e); if (did_init) { @@ -6846,8 +7360,9 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #ifdef HAVE_ECC_KEY_IMPORT /* import point from der * if shortKeySize != 0 then keysize is always (inLen-1)>>1 */ -int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, - ecc_point* point, int shortKeySize) +int wc_ecc_import_point_der_ex(const byte* in, word32 inLen, + const int curve_idx, ecc_point* point, + int shortKeySize) { int err = 0; #ifdef HAVE_COMP_KEY @@ -6912,7 +7427,7 @@ int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, /* read data */ if (err == MP_OKAY) - err = mp_read_unsigned_bin(point->x, (byte*)in, keysize); + err = mp_read_unsigned_bin(point->x, in, keysize); #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ @@ -6938,12 +7453,14 @@ int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, mp_int t1, t2; DECLARE_CURVE_SPECS(curve, 3); - ALLOC_CURVE_SPECS(3); + ALLOC_CURVE_SPECS(3, err); - if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) - err = MEMORY_E; - else - did_init = 1; + if (err == MP_OKAY) { + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) + err = MEMORY_E; + else + did_init = 1; + } /* load curve info */ if (err == MP_OKAY) @@ -7015,7 +7532,7 @@ int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, #ifdef HAVE_COMP_KEY if (compressed == 0) #endif - err = mp_read_unsigned_bin(point->y, (byte*)in + keysize, keysize); + err = mp_read_unsigned_bin(point->y, in + keysize, keysize); } if (err == MP_OKAY) err = mp_set(point->z, 1); @@ -7030,7 +7547,7 @@ int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, } /* function for backwards compatiblity with previous implementations */ -int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, +int wc_ecc_import_point_der(const byte* in, word32 inLen, const int curve_idx, ecc_point* point) { return wc_ecc_import_point_der_ex(in, inLen, curve_idx, point, 1); @@ -7209,9 +7726,23 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) if (key->type == ECC_PRIVATEKEY_ONLY) return ECC_PRIVATEONLY_E; - if (key->type == 0 || - wc_ecc_is_valid_idx(key->idx) == 0 || - key->dp == NULL) { +#ifdef WOLFSSL_QNX_CAAM + /* check if public key in secure memory */ + if (key->securePubKey > 0) { + int keySz = wc_ecc_size(key); + + /* store byte point type */ + out[0] = ECC_POINT_UNCOMP; + + if (caamReadPartition((CAAM_ADDRESS)key->securePubKey, out+1, keySz*2) != 0) + return WC_HW_E; + + *outLen = 1 + 2*keySz; + return MP_OKAY; + } +#endif + + if (key->type == 0 || wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL){ return ECC_BAD_ARG_E; } @@ -7416,19 +7947,24 @@ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) /* validate privkey * generator == pubkey, 0 on success */ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { - int err = MP_OKAY; + int err; ecc_point* base = NULL; ecc_point* res = NULL; +#ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_base; + ecc_point lcl_res; +#endif DECLARE_CURVE_SPECS(curve, 3); if (key == NULL) return BAD_FUNC_ARG; - ALLOC_CURVE_SPECS(3); + ALLOC_CURVE_SPECS(3, err); - res = wc_ecc_new_point_h(key->heap); - if (res == NULL) - err = MEMORY_E; +#ifdef WOLFSSL_NO_MALLOC + res = &lcl_res; +#endif + err = wc_ecc_new_point_ex(&res, key->heap); #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 @@ -7449,9 +7985,12 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #endif #endif { - base = wc_ecc_new_point_h(key->heap); - if (base == NULL) - err = MEMORY_E; + if (err == MP_OKAY) { + #ifdef WOLFSSL_NO_MALLOC + base = &lcl_base; + #endif + err = wc_ecc_new_point_ex(&base, key->heap); + } if (err == MP_OKAY) { /* load curve info */ @@ -7489,8 +8028,8 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) } wc_ecc_curve_free(curve); - wc_ecc_del_point_h(res, key->heap); - wc_ecc_del_point_h(base, key->heap); + wc_ecc_del_point_ex(res, key->heap); + wc_ecc_del_point_ex(base, key->heap); FREE_CURVE_SPECS(); return err; @@ -7517,11 +8056,13 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) /* Hardware based private key, so this operation is not supported */ err = MP_OKAY; /* just report success */ #else - ALLOC_CURVE_SPECS(2); + err = MP_OKAY; + ALLOC_CURVE_SPECS(2, err); /* load curve info */ - err = wc_ecc_curve_load(key->dp, &curve, - (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); if (err == MP_OKAY) err = ecc_check_privkey_gen(key, curve->Af, curve->prime); @@ -7542,15 +8083,19 @@ static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, mp_int* prime, mp_int* order) { ecc_point* inf = NULL; - int err; +#ifdef WOLFSSL_NO_MALLOC + ecc_point lcl_inf; +#endif + int err; if (key == NULL) return BAD_FUNC_ARG; - inf = wc_ecc_new_point_h(key->heap); - if (inf == NULL) - err = MEMORY_E; - else { +#ifdef WOLFSSL_NO_MALLOC + inf = &lcl_inf; +#endif + err = wc_ecc_new_point_ex(&inf, key->heap); + if (err == MP_OKAY) { #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && @@ -7581,7 +8126,7 @@ static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, #endif } - wc_ecc_del_point_h(inf, key->heap); + wc_ecc_del_point_ex(inf, key->heap); return err; } @@ -7597,9 +8142,10 @@ int wc_ecc_get_generator(ecc_point* ecp, int curve_idx) if (!ecp || curve_idx < 0 || curve_idx > (int)(ECC_SET_COUNT-1)) return BAD_FUNC_ARG; - ALLOC_CURVE_SPECS(2); + ALLOC_CURVE_SPECS(2, err); - err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, + if (err == MP_OKAY) + err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); if (err == MP_OKAY) err = mp_copy(curve->Gx, ecp->x); @@ -7619,7 +8165,7 @@ int wc_ecc_get_generator(ecc_point* ecp, int curve_idx) int wc_ecc_check_key(ecc_key* key) { #ifndef WOLFSSL_SP_MATH - int err; + int err = MP_OKAY; #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ !defined(WOLFSSL_CRYPTOCELL) mp_int* b = NULL; @@ -7640,13 +8186,19 @@ int wc_ecc_check_key(ecc_key* key) #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - return sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, + return sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, key->type == ECC_PRIVATEKEY ? &key->k : NULL, key->heap); } #endif #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - return sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, + return sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, + key->type == ECC_PRIVATEKEY ? &key->k : NULL, key->heap); + } +#endif +#ifdef WOLFSSL_SP_1024 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SAKKE_1) { + return sp_ecc_check_key_1024(key->pubkey.x, key->pubkey.y, key->type == ECC_PRIVATEKEY ? &key->k : NULL, key->heap); } #endif @@ -7656,13 +8208,14 @@ int wc_ecc_check_key(ecc_key* key) #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) || \ defined(WOLFSSL_CRYPTOCELL) || defined(WOLFSSL_SILABS_SE_ACCEL) - err = 0; /* consider key check success on ATECC508/608A */ + err = 0; /* consider key check success on ATECC508/608A and CryptoCell */ + (void)err; #else #ifdef USE_ECC_B_PARAM - ALLOC_CURVE_SPECS(4); + ALLOC_CURVE_SPECS(4, err); #else - ALLOC_CURVE_SPECS(3); + ALLOC_CURVE_SPECS(3, err); #ifndef WOLFSSL_SMALL_STACK b = &b_lcl; #else @@ -7675,6 +8228,18 @@ int wc_ecc_check_key(ecc_key* key) XMEMSET(b, 0, sizeof(mp_int)); #endif + #ifdef WOLFSSL_QNX_CAAM + /* NIST P256 keys can be black encrypted ones */ + if (key->blackKey > 0 && wc_ecc_size(key) == 32) { + /* encrypted key was used */ + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + FREE_CURVE_SPECS(); + return 0; + } + #endif + /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */ /* pubkey point cannot be at infinity */ if (wc_ecc_point_is_at_infinity(&key->pubkey)) { @@ -7686,7 +8251,8 @@ int wc_ecc_check_key(ecc_key* key) } /* load curve info */ - err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER #ifdef USE_ECC_B_PARAM | ECC_CURVE_FIELD_BF @@ -7751,9 +8317,8 @@ int wc_ecc_check_key(ecc_key* key) #endif FREE_CURVE_SPECS(); - - return err; #endif /* WOLFSSL_ATECC508A */ + return err; #else return WC_KEY_SIZE_E; #endif /* !WOLFSSL_SP_MATH */ @@ -7770,7 +8335,10 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #endif int keysize = 0; byte pointType; - +#ifdef WOLFSSL_CRYPTOCELL + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_BUILD_TempData_t tempBuff; +#endif if (in == NULL || key == NULL) return BAD_FUNC_ARG; @@ -7842,7 +8410,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, /* read data */ if (err == MP_OKAY) - err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in, keysize); + err = mp_read_unsigned_bin(key->pubkey.x, in, keysize); #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ @@ -7851,9 +8419,10 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, int did_init = 0; DECLARE_CURVE_SPECS(curve, 3); - ALLOC_CURVE_SPECS(3); + ALLOC_CURVE_SPECS(3, err); - if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) + if (err == MP_OKAY && + mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; else did_init = 1; @@ -7940,17 +8509,32 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, if (compressed == 0) #endif { - err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in + keysize, + err = mp_read_unsigned_bin(key->pubkey.y, in + keysize, keysize); } } if (err == MP_OKAY) err = mp_set(key->pubkey.z, 1); -#ifdef WOLFSSL_SILABS_SE_ACCEL - err = silabs_ecc_import(key, keysize); -#endif +#ifdef WOLFSSL_CRYPTOCELL + if (err == MP_OKAY) { + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(key->dp->id)); + /* create public key from external key buffer */ + err = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, + (byte*)in-1, /* re-adjust */ + inLen+1, /* original input */ + &key->ctx.pubKey, + &tempBuff); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed"); + } + } +#elif defined(WOLFSSL_SILABS_SE_ACCEL) + if (err == MP_OKAY) + err = silabs_ecc_import(key, keysize); +#endif #ifdef WOLFSSL_VALIDATE_ECC_IMPORT if (err == MP_OKAY) err = wc_ecc_check_key(key); @@ -7988,7 +8572,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, return BAD_FUNC_ARG; } - if (wc_ecc_is_valid_idx(key->idx) == 0) { + if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { return ECC_BAD_ARG_E; } keySz = key->dp->size; @@ -8003,9 +8587,31 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, /* Hardware cannot export private portion */ return NOT_COMPILED_IN; #else - err = wc_export_int(&key->k, d, dLen, keySz, encType); - if (err != MP_OKAY) - return err; + #ifdef WOLFSSL_QNX_CAAM + if (encType == WC_TYPE_BLACK_KEY) { + if (key->blackKey > 0) { + if (*dLen < keySz + WC_CAAM_MAC_SZ) { + *dLen = keySz + WC_CAAM_MAC_SZ; + return BUFFER_E; + } + + if (caamReadPartition(key->blackKey, d, keySz + WC_CAAM_MAC_SZ) != 0) + return WC_HW_E; + + *dLen = keySz + WC_CAAM_MAC_SZ; + } + else { + WOLFSSL_MSG("No black key stored in structure"); + return BAD_FUNC_ARG; + } + } + else + #endif + { + err = wc_export_int(&key->k, d, dLen, keySz, encType); + if (err != MP_OKAY) + return err; + } #endif } @@ -8041,6 +8647,14 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) return BAD_FUNC_ARG; } +#ifdef WOLFSSL_QNX_CAAM + /* check if black key in secure memory */ + if (key->blackKey > 0) { + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, + WC_TYPE_BLACK_KEY); + } +#endif + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, WC_TYPE_UNSIGNED_BIN); } @@ -8079,7 +8693,6 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, int ret; #ifdef WOLFSSL_CRYPTOCELL const CRYS_ECPKI_Domain_t* pDomain; - CRYS_ECPKI_BUILD_TempData_t tempBuff; #endif if (key == NULL || priv == NULL) return BAD_FUNC_ARG; @@ -8110,23 +8723,9 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, return ret; #ifdef WOLFSSL_CRYPTOCELL - pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); - - if (pub != NULL && pub[0] != '\0') { - /* create public key from external key buffer */ - ret = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, - (byte*)pub, - pubSz, - &key->ctx.pubKey, - &tempBuff); - - if (ret != SA_SILIB_RET_OK){ - WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed"); - return ret; - } - } - /* import private key */ - if (priv != NULL && priv[0] != '\0') { + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(key->dp->id)); + /* import private key - priv checked for NULL at top */ + if (priv[0] != '\0') { /* Create private key from external key buffer*/ ret = CRYS_ECPKI_BuildPrivKey(pDomain, @@ -8148,11 +8747,42 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, if (ret == MP_OKAY) { if (pub) { ret = silabs_ecc_import(key, key->dp->size); - } else - { + } + else { ret = silabs_ecc_import_private(key, key->dp->size); } } +#elif defined(WOLFSSL_QNX_CAAM) + if ((wc_ecc_size(key) + WC_CAAM_MAC_SZ) == (int)privSz) { + int part = caamFindUnusuedPartition(); + if (part >= 0) { + CAAM_ADDRESS vaddr = caamGetPartition(part, privSz*3); + if (vaddr == 0) { + WOLFSSL_MSG("Unable to get partition"); + return MEMORY_E; + } + + key->partNum = part; + key->blackKey = (word32)vaddr; + if (caamWriteToPartition(vaddr, priv, privSz) != 0) + return WC_HW_E; + + if (pub != NULL) { + /* +1 to account for x963 compressed bit */ + if (caamWriteToPartition(vaddr + privSz, pub + 1, pubSz - 1) != 0) + return WC_HW_E; + key->securePubKey = (word32)vaddr + privSz; + } + } + else { + WOLFSSL_MSG("Unable to find an unused partition"); + return MEMORY_E; + } + } + else { + WOLFSSL_MSG("Importing key that is not a black key!"); + ret = mp_read_unsigned_bin(&key->k, priv, privSz); + } #else ret = mp_read_unsigned_bin(&key->k, priv, privSz); @@ -8396,7 +9026,7 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, } if (err == MP_OKAY) { - pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(key->dp->id)); /* create public key from external key buffer */ err = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, @@ -8552,7 +9182,7 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, /* key size in octets */ int wc_ecc_size(ecc_key* key) { - if (key == NULL) + if (key == NULL || key->dp == NULL) return 0; return key->dp->size; @@ -8576,7 +9206,7 @@ int wc_ecc_sig_size_calc(int sz) } /* maximum signature size based on actual key curve */ -int wc_ecc_sig_size(ecc_key* key) +int wc_ecc_sig_size(const ecc_key* key) { int maxSigSz; int orderBits, keySz; @@ -9424,10 +10054,14 @@ static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, } /* perform a fixed point ECC mulmod */ -static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, +static int accel_fp_mul(int idx, const mp_int* k, ecc_point *R, mp_int* a, mp_int* modulus, mp_digit mp, int map) { -#define KB_SIZE 128 +#ifdef WOLFCRYPT_HAVE_SAKKE + #define KB_SIZE 256 +#else + #define KB_SIZE 128 +#endif #ifdef WOLFSSL_SMALL_STACK unsigned char* kb = NULL; @@ -9457,6 +10091,9 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, err = MP_INIT_E; goto done; } + if ((err = mp_copy(k, tk)) != MP_OKAY) + goto done; + /* if it's smaller than modulus we fine */ if (mp_unsigned_bin_size(k) > mp_unsigned_bin_size(modulus)) { /* find order */ @@ -9474,18 +10111,10 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, } /* k must be less than modulus */ - if (mp_cmp(k, order) != MP_LT) { - if ((err = mp_mod(k, order, tk)) != MP_OKAY) { + if (mp_cmp(tk, order) != MP_LT) { + if ((err = mp_mod(tk, order, tk)) != MP_OKAY) { goto done; } - } else { - if ((err = mp_copy(k, tk)) != MP_OKAY) { - goto done; - } - } - } else { - if ((err = mp_copy(k, tk)) != MP_OKAY) { - goto done; } } @@ -10011,7 +10640,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap) { #if !defined(WOLFSSL_SP_MATH) @@ -10120,7 +10749,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap) { #if !defined(WOLFSSL_SP_MATH) @@ -11356,9 +11985,7 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen if (key->type == ECC_PRIVATEKEY_ONLY) return ECC_PRIVATEONLY_E; - if (key->type == 0 || - wc_ecc_is_valid_idx(key->idx) == 0 || - key->dp == NULL) { + if (key->type == 0 || wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL){ return ECC_BAD_ARG_E; } diff --git a/wolfcrypt/src/eccsi.c b/wolfcrypt/src/eccsi.c new file mode 100644 index 000000000..4b29dead1 --- /dev/null +++ b/wolfcrypt/src/eccsi.c @@ -0,0 +1,2230 @@ +/* eccsi.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFCRYPT_HAVE_ECCSI + +#include +#include +#include +#ifdef WOLFSSL_HAVE_SP_ECC + #include +#endif + +/** + * Initialize the components of the ECCSI key and use the specified curve. + * + * Must be called before performing any operations. + * Free the ECCSI key with wc_FreeEccsiKey() when no longer needed. + * + * @param [in] key ECCSI key to initialize. + * @param [in] heap Heap hint. + * @param [in] devId Device identifier. + * Use INVALID_DEVID when no device used. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, void* heap, + int devId) +{ + int err = 0; + ecc_key* ecc = NULL; + ecc_key* pubkey = NULL; + EccsiKeyParams* params = NULL; + + if (key == NULL) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + XMEMSET(key, 0, sizeof(*key)); + key->heap = heap; + params = &key->params; + + err = wc_ecc_init_ex(&key->ecc, heap, devId); + } + if (err == 0) { + ecc = &key->ecc; + err = wc_ecc_init_ex(&key->pubkey, heap, devId); + } + if (err == 0) { + key->pvt = wc_ecc_new_point_h(heap); + if (key->pvt == NULL) { + err = MEMORY_E; + } + } + if (err == 0) { + pubkey = &key->pubkey; + err = mp_init_multi(¶ms->order, +#ifdef WOLFCRYPT_ECCSI_CLIENT + ¶ms->a, ¶ms->b, ¶ms->prime, &key->tmp, &key->ssk +#else + NULL, NULL, NULL, NULL, NULL +#endif + ); + } + if (err == 0) { + err = wc_ecc_set_curve(&key->ecc, keySz, curveId); + } + if (err == 0) { + err = wc_ecc_set_curve(&key->pubkey, keySz, curveId); + } + + if (err != 0) { + wc_ecc_free(pubkey); + wc_ecc_free(ecc); + } + + return err; +} + +/** + * Initialize the components of the ECCSI key. + * Default curve used: NIST_P256 (ECC_SECP256R1) + * + * Must be called before performing any operations. + * Free the ECCSI key with wc_FreeEccsiKey() when no longer needed. + * + * @param [in] key ECCSI key to initialize. + * @param [in] heap Heap hint. + * @param [in] devId Device identifier. + * Use INVALID_DEVID when no device used. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_InitEccsiKey(EccsiKey* key, void* heap, int devId) +{ + return wc_InitEccsiKey_ex(key, 32, ECC_SECP256R1, heap, devId); +} + +/** + * Frees memory associated with components of the ECCIS key. + * + * Must be called when finished with the ECCIS key. + * + * @param [in] key ECCIS key. + */ +void wc_FreeEccsiKey(EccsiKey* key) +{ + if (key != NULL) { + EccsiKeyParams* params = &key->params; + + wc_ecc_del_point_h(params->base, key->heap); +#ifdef WOLFCRYPT_ECCSI_CLIENT + mp_free(&key->ssk); + mp_free(&key->tmp); + mp_free(¶ms->prime); + mp_free(¶ms->b); + mp_free(¶ms->a); +#endif + mp_free(¶ms->order); + wc_ecc_del_point_h(key->pvt, key->heap); + wc_ecc_free(&key->pubkey); + wc_ecc_free(&key->ecc); + } +} + +/* + * Order, as a hex string in the ECC object, loaded into mp_int in key. + * Flags that the order is available so it isn't loaded multiple times. + * + * @param [in] key ECCSI key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_load_order(EccsiKey* key) +{ + int err = 0; + + if (!key->params.haveOrder) { + err = mp_read_radix(&key->params.order, key->ecc.dp->order, + MP_RADIX_HEX); + if (err == 0) { + key->params.haveOrder = 1; + } + } + + return err; +} + +#ifdef WOLFCRYPT_ECCSI_CLIENT +/* + * Parameters, as a hex strings in the ECC object, loaded into mp_ints in key. + * + * Parameters loaded: order, A, B, prime. + * Flags that each parameter is available so they aren't loaded multiple times. + * + * @param [in] key ECCSI key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_load_ecc_params(EccsiKey* key) +{ + int err = 0; + EccsiKeyParams* params = &key->params; + + err = eccsi_load_order(key); + if ((err == 0) && (!params->haveA)) { + err = mp_read_radix(¶ms->a, key->ecc.dp->Af, MP_RADIX_HEX); + if (err == 0) { + params->haveA = 1; + } + } + if ((err == 0) && (!params->haveB)) { + err = mp_read_radix(¶ms->b, key->ecc.dp->Bf, MP_RADIX_HEX); + if (err == 0) { + params->haveB = 1; + } + } + if ((err == 0) && (!params->havePrime)) { + err = mp_read_radix(¶ms->prime, key->ecc.dp->prime, MP_RADIX_HEX); + if (err == 0) { + params->havePrime = 1; + } + } + + return err; +} +#endif /* WOLFCRYPT_ECCSI_CLIENT */ + +/* + * Get the base point, hex encoded in the ECC object, as an ecc_point. + * + * Flags that base is available so it isn't loaded multiple times. + + * @param [in] key ECCSI key. + * @param [out] base Base point of curve. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_load_base(EccsiKey* key) +{ + int err = 0; + EccsiKeyParams* params = &key->params; + + if (!params->haveBase) { + if (params->base == NULL) { + params->base = wc_ecc_new_point_h(key->heap); + if (params->base == NULL) { + err = MEMORY_E; + } + } + if (err == 0) { + err = mp_read_radix(params->base->x, key->ecc.dp->Gx, MP_RADIX_HEX); + } + if (err == 0) { + err = mp_read_radix(params->base->y, key->ecc.dp->Gy, MP_RADIX_HEX); + } + if (err == 0) { + err = mp_set(params->base->z, 1); + } + if (err == 0) { + params->haveBase = 1; + } + } + + return err; +} + +/* + * Encode the base point of the curve. + * + * Base point is hex encoded in the ECC object or cached as an ECC point from + * previous load calls. + * + * @param [in] key ECCSI key. + * @param [out] data Buffer to encode base point into. + * @param [out] dataSz Length of base point in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_encode_base(EccsiKey* key, byte* data, word32* dataSz) +{ + int err; + int idx = wc_ecc_get_curve_idx(key->ecc.dp->id); + + err = eccsi_load_base(key); + if (err == 0) { + err = wc_ecc_export_point_der(idx, key->params.base, data, dataSz); + } + + return err; +} + +#ifndef WOLFSSL_HAVE_SP_ECC +/* + * Convert the KPAK to montgomery form. + * + * The KPAK is needed in Montgomery form for verification. + * + * @param [in] key ECCSI key. + * @return 0 on success. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_kpak_to_mont(EccsiKey* key) +{ + int err = 0; + ecc_point* kpak = &key->ecc.pubkey; + mp_int* mu = &key->tmp; + mp_int* prime = &key->params.prime; + + if (!key->kpakMont) { + err = mp_montgomery_calc_normalization(mu, prime); + if (err == 0) { + err = mp_mulmod(kpak->x, mu, prime, kpak->x); + } + if (err == 0) { + err = mp_mulmod(kpak->y, mu, prime, kpak->y); + } + if (err == 0) { + err = mp_mulmod(kpak->z, mu, prime, kpak->z); + } + if (err == 0) { + key->kpakMont = 1; + } + } + + return err; +} +#endif + +/* + * Convert the KPAK from montgomery form. + * + * The KPAK is needed in Montgomery form for verification. + * + * @param [in] key ECCSI key. + * @return 0 on success. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_kpak_from_mont(EccsiKey* key) +{ + int err = 0; + ecc_point* kpak = &key->ecc.pubkey; + mp_digit mp; + mp_int* prime = &key->params.prime; + + if (key->kpakMont) { + err = mp_montgomery_setup(prime, &mp); + if (err == 0) { + err = mp_montgomery_reduce(kpak->x, prime, mp); + } + if (err == 0) { + err = mp_montgomery_reduce(kpak->y, prime, mp); + } + if (err == 0) { + err = mp_montgomery_reduce(kpak->z, prime, mp); + } + if (err == 0) { + key->kpakMont = 0; + } + } + + return err; +} + +/* + * Compute HS = hash( G | KPAK | ID | PVT ) + * + * Use when making a (SSK,PVT) pair, signing and verifying. + * + * @param [in] key ECCSI key. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] id Identity to create hash from. + * @param [in] idSz Length of identity in bytes. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @param [out] hash Buffer to hold hash data. + * @param [out] hashSz Length of hash data in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_compute_hs(EccsiKey* key, enum wc_HashType hashType, + const byte* id, word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz) +{ + int err; + word32 dataSz = 0; + int idx = wc_ecc_get_curve_idx(key->ecc.dp->id); + ecc_point* kpak = &key->ecc.pubkey; + + /* HS = hash( G | KPAK | ID | PVT ) */ + err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID); + if (err == 0) { + /* Base Point - G */ + dataSz = sizeof(key->data); + err = eccsi_encode_base(key, key->data, &dataSz); + } + if (err == 0) { + err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz); + } + if (err == 0) { + err = eccsi_kpak_from_mont(key); + } + if (err == 0) { + dataSz = sizeof(key->data); + /* KPAK - public key */ + err = wc_ecc_export_point_der(idx, kpak, key->data, &dataSz); + } + if (err == 0) { + err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz); + } + if (err == 0) { + /* Id - Signer's ID */ + err = wc_HashUpdate(&key->hash, hashType, id, idSz); + } + if (err == 0) { + dataSz = sizeof(key->data); + /* PVT - Public Validation Token */ + err = wc_ecc_export_point_der(idx, pvt, key->data, &dataSz); + } + if (err == 0) { + /* PVT - Public Validation Token */ + err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz); + } + if (err == 0) { + err = wc_HashFinal(&key->hash, hashType, hash); + } + + if (err == 0) { + *hashSz = (byte)wc_HashGetDigestSize(hashType); + } + + return err; +} + +#ifdef WOLFCRYPT_ECCSI_KMS +/** + * Generate KMS Secret Auth Key (KSAK) and KMS Public Auth Key (KPAK). + * + * RFC 6507, Section 4.2 + * + * Called when establishing a new KMS.\n + * KSAK must be kept secret while KPAK is required by clients for signing + * and verifying.\n + * Export key using wc_ExportEccsiKey(), once generated, to reuse the key.\n + * Export KPAK using wc_ExportEccsiPublicKey(), once generate to send to + * clients. + * + * Creates a random private key and multiplies it by the base point to calculate + * the public key. + * + * @param [in] key ECCSI key. + * @param [in] rng Random number generator. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or rng is NULL. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +int wc_MakeEccsiKey(EccsiKey* key, WC_RNG* rng) +{ + int err = 0; + + if ((key == NULL) || (rng == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = wc_ecc_make_key_ex(rng, key->ecc.dp->size, &key->ecc, + key->ecc.dp->id); + } + + return err; +} + +/* + * Encode a point into a buffer. + * + * X and y ordinate of point concatenated. Each number is zero padded tosize. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] point ECC point to encode. + * @param [in] size Size of prime in bytes - maximum ordinate length. + * @param [out] data Buffer to hold encoded data. + * NULL when needing length of encoded data. + * @param [in,out] sz In, the size of the buffer in bytes. + * Out, the size of the encoded data in bytes. + * @param [in] raw On 0, prepend descriptor byte. + * On 1, only include ordinates. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz will hold the size in bytes of + * the encoded data. + * @return BUFFER_E when size of buffer is too small. + */ +static int eccsi_encode_point(ecc_point* point, word32 size, byte* data, + word32* sz, int raw) +{ + int err = 0; + + if (data == NULL) { + *sz = size * 2 + !raw; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*sz < size * 2 + !raw)) { + err = BUFFER_E; + } + + if (err == 0) { + if (!raw) { + data[0] = 0x04; + data++; + } + + /* Write out the point's x ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(point->x, data, size); + } + if (err == 0) { + data += size; + /* Write out the point's y ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(point->y, data, size); + } + if (err == 0) { + *sz = size * 2 + !raw; + } + + return err; +} + +/* + * Decode the data into an ECC point. + * + * X and y ordinate of point concatenated. Each number is zero padded to + * key size. Supports prepended descriptor byte (0x04). + * + * @param [out] point ECC point to encode. + * @param [in] size Size of prime in bytes - maximum ordinate length. + * @param [in] data Encoded public key. + * @param [in] sz Size of the encoded public key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or z is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_decode_point(ecc_point* point, word32 size, const byte* data, + word32 sz) +{ + int err = 0; + + if ((sz != size * 2) && (sz != size * 2 + 1)) { + err = BUFFER_E; + } + + if ((err == 0) && (sz & 1)) { + if (data[0] != 0x04) { + err = ASN_PARSE_E; + } + data++; + } + + if (err == 0) { + /* Read the public key point's x value from key size bytes. */ + err = mp_read_unsigned_bin(point->x, data, size); + } + if (err == 0) { + data += size; + /* Read the public key point's y value from key size bytes. */ + err = mp_read_unsigned_bin(point->y, data, size); + } + if (err == 0) { + err = mp_set(point->z, 1); + } + + return err; +} + +/* + * Encode the ECCSI key. + * + * Encodes the private key as big-endian bytes of fixed length. + * Encodes the public key x and y ordinates as big-endian bytes of fixed length. + * + * @param [in] key ECCSI key. + * @param [out] data Buffer to hold encoded ECCSI key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK). + */ +static int eccsi_encode_key(EccsiKey* key, byte* data) +{ + int err; + word32 sz = (word32)key->ecc.dp->size * 2; + + /* Write out the secret value into key size bytes. */ + err = mp_to_unsigned_bin_len(&key->ecc.k, data, key->ecc.dp->size); + if (err == 0) { + data += key->ecc.dp->size; + /* Write the public key. */ + err = eccsi_encode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size, + data, &sz, 1); + } + + return err; +} + +/** + * Export the ECCSI key as encoded public/private ECC key. + * + * Use when saving the KMS key pair. + * + * Private key, x ordinate of public key and y ordinate of public key + * concatenated. Each number is zero padded to key size. + * + * @param [in] key ECCSI key. + * @param [out] data Buffer to hold encoded ECCSI key. + * NULL when requesting required length. + * @param [in,out] sz On in, size of buffer in bytes. + * On out, size of encoded ECCSI key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL + * @return BAD_STATE_E when no key to export. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when the buffer passed in is too small. + * @return MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK). + */ +int wc_ExportEccsiKey(EccsiKey* key, byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) { + err = BAD_STATE_E; + } + + if (err == 0) { + if (data == NULL) { + *sz = key->ecc.dp->size * 3; + err = LENGTH_ONLY_E; + } + else if (*sz < (word32)key->ecc.dp->size * 3) { + err = BUFFER_E; + } + else { + *sz = key->ecc.dp->size * 3; + } + } + if (err == 0) { + err = eccsi_kpak_from_mont(key); + } + if (err == 0) { + /* Encode key */ + err = eccsi_encode_key(key, data); + } + + return err; +} + +/* + * Import the ECCSI key as encoded public/private ECC key. + * + * Decodes the private key as big-endian bytes of fixed length. + * Decodes the public key x and y ordinates as big-endian bytes of fixed length. + * + * @param [in] key ECCSI key. + * @param [in] data Buffer holding encoded ECCSI key. + * @return 0 on success. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_decode_key(EccsiKey* key, const byte* data) +{ + int err; + + /* Read the secret value from key size bytes. */ + err = mp_read_unsigned_bin(&key->ecc.k, data, key->ecc.dp->size); + if (err == 0) { + data += key->ecc.dp->size; + /* Read public key. */ + err = eccsi_decode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size, + data, key->ecc.dp->size * 2); + } + + return err; +} + +/** + * Import the ECCSI key as encoded public/private ECC key. + * + * Use when restoring the KMS key pair. + * + * Private key, x ordinate of public key and y ordinate of public key + * concatenated. Each number is zero padded to key size. + * + * @param [in] key ECCSI key. + * @param [in] data Buffer holding encoded ECCSI key. + * @param [in] sz Size of encoded ECCSI key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or data is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_ImportEccsiKey(EccsiKey* key, const byte* data, word32 sz) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (sz != (word32)key->ecc.dp->size * 3)) { + err = BUFFER_E; + } + + if (err == 0) { + key->kpakMont = 0; + + /* Decode key */ + err = eccsi_decode_key(key, data); + } + if (err == 0) { + key->ecc.type = ECC_PRIVATEKEY; + } + + return err; +} + +/** + * Export the ECCSI private key. + * + * Use when saving the KMS key. + * + * Private key is zero padded to key size. + * + * @param [in] key ECCSI key. + * @param [out] data Buffer to hold encoded ECCSI private key. + * NULL when requesting required length. + * @param [in,out] sz On in, size of buffer in bytes. + * On out, size of encoded ECCSI private key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL + * @return BAD_STATE_E when no key to export. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when the buffer passed in is too small. + * @return MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK). + */ +int wc_ExportEccsiPrivateKey(EccsiKey* key, byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) { + err = BAD_STATE_E; + } + + if (err == 0) { + if (data == NULL) { + *sz = key->ecc.dp->size; + err = LENGTH_ONLY_E; + } + else if (*sz < (word32)key->ecc.dp->size) { + err = BUFFER_E; + } + else { + *sz = key->ecc.dp->size; + } + } + if (err == 0) { + err = mp_to_unsigned_bin_len(&key->ecc.k, data, key->ecc.dp->size); + } + + return err; +} + +/** + * Import the ECCSI private key. + * + * Use when restoring the KMS key pair. + * + * Private key is zero padded to key size. + * + * @param [in] key ECCSI key. + * @param [in] data Buffer holding encoded ECCSI private key. + * @param [in] sz Size of encoded ECCSI private key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or data is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_ImportEccsiPrivateKey(EccsiKey* key, const byte* data, word32 sz) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (sz != (word32)key->ecc.dp->size)) { + err = BUFFER_E; + } + + if (err == 0) { + err = mp_read_unsigned_bin(&key->ecc.k, data, key->ecc.dp->size); + } + + return err; +} + +/** + * Export the KMS Public Auth Key (KPAK) from the ECCSI object. + * + * KPAK is required by all clients in order to perform cryptographic operations. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key ECCSI key. + * @param [out] data Buffer to hold the encoded public key. + * @param [in,out] sz On in, size of buffer in bytes. + * On out, length of encoded public key in bytes. + * @param [in] raw On 0, prepend descriptor byte. + * On 1, only include ordinates. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when the buffer passed in is too small. + */ +int wc_ExportEccsiPublicKey(EccsiKey* key, byte* data, word32* sz, int raw) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) && + (key->ecc.type != ECC_PUBLICKEY)) { + err = BAD_STATE_E; + } + + if ((err == 0) && (data != NULL)) { + err = eccsi_kpak_from_mont(key); + } + if (err == 0) { + /* Write out public key. */ + err = eccsi_encode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size, + data, sz, raw); + } + + return err; +} + +/* + * Generates an (SSK, PVT) Pair - signing key pair. + * + * RFC 6507, Section 5.1.1 + * + * @param [in] key ECCSI key. + * @param [in] rng Random number generator. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] id Identity to create hash from. + * @param [in] idSz Length of identity in bytes. + * @param [out] ssk Secret Signing Key as an MP integer. + * @param [out] pvt Public Validation Token (PVT) as an ECC point. + * @return 0 on success. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_make_pair(EccsiKey* key, WC_RNG* rng, + enum wc_HashType hashType, const byte* id, word32 idSz, mp_int* ssk, + ecc_point* pvt) +{ + int err = 0; + byte hashSz = 0; + int genTryCnt = 0; + + do { + /* Don't infinitely make pairs when random number generator fails. */ + if ((++genTryCnt) > ECCSI_MAX_GEN_COUNT) { + err = RNG_FAILURE_E; + } + + if (err == 0) { + /* Step 1 and 2: Generate ephemeral key - v, PVT = [v]G */ + err = wc_ecc_make_key_ex(rng, key->ecc.dp->size, &key->pubkey, + key->ecc.dp->id); + } + if (err == 0) { + err = wc_ecc_copy_point(&key->pubkey.pubkey, pvt); + } + + /* Step 3: Compute HS */ + if (err == 0) { + hashSz = (byte)sizeof(key->data); + err = eccsi_compute_hs(key, hashType, id, idSz, pvt, key->data, + &hashSz); + } + + /* Step 4: Compute SSK = ( KSAK + HS * v ) modulo q */ + if (err == 0) { + err = mp_read_unsigned_bin(ssk, key->data, hashSz); + } + if (err == 0) { + err = mp_mulmod(ssk, &key->pubkey.k, &key->params.order, ssk); + } + if (err == 0) { + err = mp_addmod(ssk, &key->ecc.k, &key->params.order, ssk); + } + } + while ((err == 0) && (mp_iszero(ssk) || + (mp_cmp(ssk, &key->ecc.k) == MP_EQ))); + /* Step 5: ensure SSK and HS are non-zero (code lines above) */ + + /* Step 6: Copy out SSK (done during calc) and PVT. Erase v */ + mp_forcezero(&key->pubkey.k); + + return err; +} + +/** + * Generates an (SSK, PVT) Pair - signing key pair. + * + * RFC 6507, Section 5.1.1 + * + * ID should include information to indicate a revocation date.\n + * SSK must be zeroized after sending to client.\n + * SSK is sent to signing client only.\n + * PVT is sent to all client types. + * + * @param [in] key ECCSI key. + * @param [in] rng Random number generator. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] id Identity to create hash from. + * @param [in] idSz Length of identity in bytes. + * @param [out] ssk Secret Signing Key as an MP integer. + * @param [out] pvt Public Validation Token (PVT) as an ECC point. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rng, id, ssk or pvt is NULL. + * @return BAD_STATE_E when curve not set (key not set). + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +int wc_MakeEccsiPair(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType, + const byte* id, word32 idSz, mp_int* ssk, ecc_point* pvt) +{ + int err = 0; + + if ((key == NULL) || (rng == NULL) || (id == NULL) || (ssk == NULL) || + (pvt == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) { + err = BAD_STATE_E; + } + + if (err == 0) { + err = eccsi_load_order(key); + } + if (err == 0) { + err = eccsi_make_pair(key, rng, hashType, id, idSz, ssk, pvt); + } + + return err; +} + +/** + * Encode the SSK and PVT into a buffer. + * + * SSK and PVT required by client signing messages. + * + * @param [in] key ECCSI key. + * @param [in] ssk Secret Signing Key as an MP integer. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @param [out] data Buffer to encode key pair into. + * @param [in,out] sz In, size of buffer in bytes. + * Out, size of encoded pair data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, ssk, pvt or sz is NULL. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + */ +int wc_EncodeEccsiPair(const EccsiKey* key, mp_int* ssk, ecc_point* pvt, + byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (ssk == NULL) || (pvt == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (data == NULL)) { + *sz = key->ecc.dp->size * 3; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*sz < (word32)(key->ecc.dp->size * 3))) { + err = BUFFER_E; + } + + if (err == 0) { + err = mp_to_unsigned_bin_len(ssk, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Write out the PVT's x ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(pvt->x, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Write out the PVT's y ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(pvt->y, data, key->ecc.dp->size); + } + if (err == 0) { + *sz = key->ecc.dp->size * 3; + } + + return err; +} + +/** + * Encode the Secret Signing Key (SSK). + * + * Use when saving the key pair. + * + * SSK is zero padded to key size. + * + * @param [in] key ECCSI key. + * @param [in] ssk Secret Signing Key as an MP integer. + * @param [out] data Buffer to hold encoded SSK. + * NULL when requesting required length. + * @param [in,out] sz On in, size of buffer in bytes. + * On out, size of encoded ECCSI key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, ssk or sz is NULL + * @return BAD_STATE_E when no key to export. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when the buffer passed in is too small. + * @return MEMORY_E when dynamic memory allocation fails (WOLFSSL_SMALL_STACK). + */ +int wc_EncodeEccsiSsk(const EccsiKey* key, mp_int* ssk, byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (ssk == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY)) { + err = BAD_STATE_E; + } + + if (err == 0) { + if (data == NULL) { + *sz = key->ecc.dp->size; + err = LENGTH_ONLY_E; + } + else if (*sz < (word32)key->ecc.dp->size) { + err = BUFFER_E; + } + else { + *sz = key->ecc.dp->size; + } + } + if (err == 0) { + err = mp_to_unsigned_bin_len(ssk, data, key->ecc.dp->size); + } + + return err; +} + +/** + * Decode the Secret Signing Key (SSK). + * + * Use when restoring the key pair. + * + * SSK is zero padded to key size. + * + * @param [in] key ECCSI key. + * @param [in] data Buffer holding encoded ECCSI key. + * @param [in] sz Size of encoded ECCSI key in bytes. + * @param [out] ssk Secret Signing Key as an MP integer. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, data or ssk is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_DecodeEccsiSsk(const EccsiKey* key, const byte* data, word32 sz, + mp_int* ssk) +{ + int err = 0; + + if ((key == NULL) || (data == NULL) || (ssk == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (sz != (word32)key->ecc.dp->size)) { + err = BUFFER_E; + } + + if (err == 0) { + err = mp_read_unsigned_bin(ssk, data, key->ecc.dp->size); + } + + return err; +} + +/** + * Encode the PVT into a buffer. + * + * PVT required by client verifying messages. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key ECCSI key. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @param [out] data Buffer to encode key pair into. + * @param [in,out] sz In, size of buffer in bytes. + * Out, size of encoded pair data in bytes. + * @param [in] raw On 0, prepend descriptor byte. + * On 1, only include ordinates. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, pvt or sz is NULL. + * @return BAD_STATE_E when PVT has not been set. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + */ +int wc_EncodeEccsiPvt(const EccsiKey* key, ecc_point* pvt, byte* data, + word32* sz, int raw) +{ + int err = 0; + + if ((key == NULL) || (pvt == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = eccsi_encode_point(pvt, (word32)key->ecc.dp->size, data, sz, raw); + } + + return err; +} + +#endif /* WOLFCRYPT_ECCSI_KMS */ + +#ifdef WOLFCRYPT_ECCSI_CLIENT +/** + * Decode the SSK and PVT data into separate variables. + * + * A signing client decodes the data so that it can validate the pair and sign. + * + * @param [in] key ECCSI key. + * @param [in] data Buffer holding key pair data. + * @param [in] sz Size of data in bytes. + * @param [out] ssk Secret Signing Key as an MP integer. + * @param [out] pvt Public Validation Token (PVT) as an ECC point. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, data, ssk or pvt is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_DecodeEccsiPair(const EccsiKey* key, const byte* data, word32 sz, + mp_int* ssk, ecc_point* pvt) +{ + int err = 0; + + if ((key == NULL) || (data == NULL) || (ssk == NULL) || (pvt == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (sz != (word32)(key->ecc.dp->size * 3))) { + err = BUFFER_E; + } + + if (err == 0) { + /* Read the SSK value from key size bytes. */ + err = mp_read_unsigned_bin(ssk, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Read the PVT's x value from key size bytes. */ + err = mp_read_unsigned_bin(pvt->x, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Read the PVT's y value from key size bytes. */ + err = mp_read_unsigned_bin(pvt->y, data, key->ecc.dp->size); + } + if (err == 0) { + err = mp_set(pvt->z, 1); + } + + return err; +} + +/** + * Decode the PVT data into an ECC point. + * + * A verifying client decodes the data so that it can verify a message. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key ECCSI key. + * @param [in] data Buffer holding PVT data. + * @param [in] sz Size of data in bytes. + * @param [out] pvt Public Validation Token (PVT) as an ECC point. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, data, ssk or pvt is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_DecodeEccsiPvt(const EccsiKey* key, const byte* data, word32 sz, + ecc_point* pvt) +{ + int err = 0; + + if ((key == NULL) || (data == NULL) || (pvt == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = eccsi_decode_point(pvt, (word32)key->ecc.dp->size, data, sz); + } + + return err; +} + +/** + * Decode the PVT data, from a signature, into an ECC point. + * + * A verifying client decodes the data so that it can calculate the identity + * hash. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key ECCSI key. + * @param [in] sig Buffer holding signature data. + * @param [in] sz Size of data in bytes. + * @param [out] pvt Public Validation Token (PVT) as an ECC point. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, data, ssk or pvt is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_DecodeEccsiPvtFromSig(const EccsiKey* key, const byte* sig, word32 sz, + ecc_point* pvt) +{ + int err = 0; + + if ((key == NULL) || (sig == NULL) || (pvt == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + word32 rSz = key->ecc.dp->size * 2; + err = eccsi_decode_point(pvt, (word32)key->ecc.dp->size, sig + rSz, + sz - rSz); + } + + return err; +} + +/** + * Import the KMS Public Auth Key (KPAK) into the ECCSI object. + * + * Clients import the KPAK to perform cryptographic operations. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key ECCSI key. + * @param [in] data Encoded public key as an array of bytes. + * @param [in] sz Length of encoded KPAK in bytes. + * @param [in] trusted 1 when public key is trusted. + * 0 when validation is required to be performed. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or data is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return ECC_OUT_OF_RANGE_E when point is invalid. + * @return ECC_INF_E when point is at infinity and invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_ImportEccsiPublicKey(EccsiKey* key, const byte* data, word32 sz, + int trusted) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + key->kpakMont = 0; + + /* Read the public key. */ + err = eccsi_decode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size, + data, sz); + } + if (err == 0) { + key->ecc.type = ECC_PUBLICKEY; + } + if ((err == 0) && (!trusted)) { + err = wc_ecc_check_key(&key->ecc); + } + + return err; +} + +/* + * Scalar multiply the base point of the curve and add a point. + * + * @param [in] key ECCSI key. + * @param [in] n MP integer representing scalar to multiply by. + * @param [in] a ECC point to add. + * @param [out] res ECC point representation of the resulting point. + * @param [in] mp Montgomery reduction multiplier. + * @param [in] map 0 indicates to leave in projective representation. + * 1 indicates map projective point to affine. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_mulmod_base_add(EccsiKey* key, const mp_int* n, + ecc_point* a, ecc_point* res, mp_digit mp, int map) +{ + int err = 0; + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) { + err = sp_ecc_mulmod_base_add_256(n, a, 1, res, map, key->heap); + } + else +#endif +#endif +#ifndef WOLFSSL_SP_MATH + { + EccsiKeyParams* params = &key->params; + err = wc_ecc_mulmod(n, params->base, params->base, ¶ms->a, + ¶ms->prime, 0); + key->params.haveBase = 0; + if (err == 0) { + err = ecc_projective_add_point(params->base, a, res, ¶ms->a, + ¶ms->prime, mp); + } + if ((err == 0) && map) { + err = ecc_map(res, ¶ms->prime, mp); + } + } +#else + { + err = NOT_COMPILED_IN; + } + (void)mp; +#endif + + return err; +} + +/* + * Scalar multiply a point on the curve. + * + * @param [in] key ECCSI key. + * @param [in] n MP integer representing scalar to multiply by. + * @param [in] point ECC point representation of a point on the curve. + * @param [out] res ECC point representation of the resulting point. + * @param [in] map 0 indicates to leave in projective representation. + * 1 indicates map projective point to affine. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_mulmod_point(EccsiKey* key, const mp_int* n, ecc_point* point, + ecc_point* res, int map) +{ + int err; + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) { + err = sp_ecc_mulmod_256(n, point, res, map, key->heap); + } + else +#endif +#endif + { + EccsiKeyParams* params = &key->params; + + err = wc_ecc_mulmod(n, point, res, ¶ms->a, ¶ms->prime, map); + } + + return err; +} + +/* + * Scalar multiply a point on the curve and add a. + * + * @param [in] key ECCSI key. + * @param [in] n MP integer representing scalar to multiply by. + * @param [in] point ECC point representation of a point on the curve. + * @param [in] a ECC point to add. + * @param [out] res ECC point representation of the resulting point. + * @param [in] mp Montgomery reduction multiplier. + * @param [in] map 0 indicates to leave in projective representation. + * 1 indicates map projective point to affine. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_mulmod_point_add(EccsiKey* key, const mp_int* n, + ecc_point* point, ecc_point* a, ecc_point* res, mp_digit mp, int map) +{ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + int err = NOT_COMPILED_IN; + + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) { + err = sp_ecc_mulmod_add_256(n, point, a, 0, res, map, key->heap); + } + + (void)mp; + + return err; +#endif +#else + int err; + EccsiKeyParams* params = &key->params; + + err = wc_ecc_mulmod(n, point, res, ¶ms->a, ¶ms->prime, 0); + if (err == 0) { + err = ecc_projective_add_point(res, a, res, &key->params.a, + ¶ms->prime, mp); + } + if ((err == 0) && map) { + err = ecc_map(res, ¶ms->prime, mp); + } + + return err; +#endif +} + +/** + * Validate an (SSV, PVT) Pair. + * + * RFC 6507, Section 5.1.2 + * + * A signing client should validate the key pair before first use. + * + * @param [in] key ECCSI key. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] id Identity to create hash from. + * @param [in] idSz Length of identity in bytes. + * @param [in] ssk Secret Signing Key as an MP integer. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @param [out] valid 1 when pair is valid and 0 otherwise. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, id, ssk, pvt or valid is NULL. + * @return BAD_STATE_E when curve not set (key not set). + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return IS_POINT_E when point is not on the curve. + * @return Other -ve value when an internal operation fails. + */ +int wc_ValidateEccsiPair(EccsiKey* key, enum wc_HashType hashType, + const byte* id, word32 idSz, const mp_int* ssk, ecc_point* pvt, + int* valid) +{ + int err = 0; + ecc_point* res = NULL; + mp_int* hs = NULL; + mp_digit mp = 0; + byte hashSz = 0; + EccsiKeyParams* params = &key->params; + + if ((key == NULL) || (id == NULL) || (ssk == NULL) || (pvt == NULL) || + (valid == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) && + (key->ecc.type != ECC_PUBLICKEY)) { + err = BAD_STATE_E; + } + + if (err == 0) { + hs = &key->tmp; + res = &key->pubkey.pubkey; + + err = eccsi_load_base(key); + } + if (err == 0) { + err = eccsi_load_ecc_params(key); + } + if (err == 0) { + err = mp_montgomery_setup(¶ms->prime, &mp); + } + + /* Step 1: Validate PVT is on curve */ + if (err == 0) { + err = wc_ecc_is_point(pvt, ¶ms->a, ¶ms->b, ¶ms->prime); + if (err == -1) { + err = IS_POINT_E; + } + } + + /* Step 2: Compute HS = hash( G | KPAK | ID | PVT ) */ + if (err == 0) { + hashSz = (byte)sizeof(key->data); + /* Converts KPAK from mont. */ + err = eccsi_compute_hs(key, hashType, id, idSz, pvt, key->data, + &hashSz); + } + + /* Step 3: Validate that KPAK = [SSK]G - [HS]PVT */ + if (err == 0) { + err = mp_read_unsigned_bin(hs, key->data, hashSz); + } + /* [HS]PVT */ + if (err == 0) { + err = eccsi_mulmod_point(key, hs, pvt, res, 0); + } + /* -[HS]PVT */ + if (err == 0) { + err = mp_sub(¶ms->prime, res->y, res->y); + } + /* [SSK]G + -[HS]PVT */ + if (err == 0) { + err = eccsi_mulmod_base_add(key, ssk, res, res, mp, 1); + } + if (valid != NULL) { + *valid = (err == 0); + if (err == 0) { + ecc_point* kpak = &key->ecc.pubkey; + /* Compare KPAK and [SSK]G + -[HS]PVT */ + *valid = (wc_ecc_cmp_point(res, kpak) == MP_EQ); + } + } + + return err; +} + +/** + * Validate Public Validation Token (PVT) is on the curve. + * + * RFC 6507, Section 5.1.2, Step 1 + * + * A verifying client should validate the PVT before first use. + * + * @param [in] key ECCSI key. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @param [out] valid 1 when PVT is valid and 0 otherwise. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, pvt or valid is NULL. + * @return BAD_STATE_E when curve not set (key not set). + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +int wc_ValidateEccsiPvt(EccsiKey* key, const ecc_point* pvt, int* valid) +{ + int err = 0; + + if ((key == NULL)| (pvt == NULL) || (valid == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = wc_ecc_set_curve(&key->pubkey, key->ecc.dp->size, + key->ecc.dp->id); + } + if (err == 0) { + err = wc_ecc_copy_point(pvt, &key->pubkey.pubkey); + } + if (err == 0) { + *valid = (wc_ecc_check_key(&key->pubkey) == 0); + } + + return err; +} + +/** + * Creates the Hash of the ID and PVT with the ECCSI key. + * + * The hash ID is required as input to the sign and verify operations.\n + * Signing clients may cache this value. + * + * RFC 6507, Section 5.2.1, Step 3 + * + * Set the calculated hash internally for use. + * + * @param [in] key ECCSI key. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] id Identity to create hash from. + * @param [in] idSz Length of identity in bytes. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @param [out] hash Buffer to hold hash result. + * @param [out] hashSz Length of hash data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, id, pvt, hash or hashSz is NULL. + * @return BAD_STATE_E when public key not set. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +int wc_HashEccsiId(EccsiKey* key, enum wc_HashType hashType, const byte* id, + word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz) +{ + int err = 0; + + if ((key == NULL) || (id == NULL) || (pvt == NULL) || (hash == NULL) || + (hashSz == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) && + (key->ecc.type != ECC_PUBLICKEY)) { + err = BAD_STATE_E; + } + /* Load the curve parameters for operations */ + if (err == 0) { + err = eccsi_load_ecc_params(key); + } + if (err == 0) { + err = eccsi_compute_hs(key, hashType, id, idSz, pvt, hash, hashSz); + } + if (err == 0) { + XMEMCPY(key->idHash, hash, *hashSz); + key->idHashSz = *hashSz; + } + + return err; +} + +/** + * Set the identity hash for use with signing/verification. + * + * @param [in] key ECCSI key. + * @param [in] hash Buffer with hash of identity. + * @param [in] hashSz Length of hash data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or hash is NULL, or hashSz is greater than + * WC_MAX_DIGEST_SIZE. + */ +int wc_SetEccsiHash(EccsiKey* key, const byte* hash, byte hashSz) +{ + int err = 0; + + if ((key == NULL) || (hash == NULL) || (hashSz > WC_MAX_DIGEST_SIZE)) { + err = BAD_FUNC_ARG; + } + if (err == 0) { + XMEMCPY(key->idHash, hash, hashSz); + key->idHashSz = hashSz; + } + + return err; +} + +/** + * Set an (SSV, PVT) Pair for signing. + * + * @param [in] key ECCSI key. + * @param [in] ssk Secret Signing Key as an MP integer. + * @param [in] pvt Public Validation Token (PVT) as an ECC point. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, ssk or pvt is NULL. + * @return MP math errors when copy fails + */ +int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, const ecc_point* pvt) +{ + int err = 0; + + if ((key == NULL) || (ssk == NULL) || (pvt == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = mp_copy(ssk, &key->ssk); + } + + if (err == 0) { + err = wc_ecc_copy_point(pvt, key->pvt); + } + + return err; +} + +#ifdef ECCSI_ORDER_MORE_BITS_THAN_PRIME +/* + * Fit the number to the maximum number of bytes. + * + * If the number is too big then subtract from order. + * RFC 6507, Section 5.2.1, Note at end. + * This should only happen when order is larger than prime in bits. + * + * @param [in] a MP integer to fix. + * @param [in] order MP integer representing order of curve. + * @param [in] max Maximum number of bytes to encode into. + * @param [out] r MP integer that is the result after fixing. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_fit_to_octets(const mp_int* a, mp_int* order, int max, + mp_int* r) +{ + int err; + + if (mp_count_bits(a) > max * 8) { + err = mp_sub(order, (mp_int*)a, r); + } + else + { + err = mp_copy(a, r); + } + + return err; +} +#else +/* + * Fit the number to the maximum number of bytes. + * + * If the number is too big then subtract from order. + * RFC 6507, Section 5.2.1, Note at end. + * This should only happen when order is larger than prime in bits. + * + * @param [in] a MP integer to fix. + * @param [in] order MP integer representing order of curve. + * @param [in] max Maximum number of bytes to encode into. + * @param [out] r MP integer that is the result after fixing. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int eccsi_fit_to_octets(const mp_int* a, const mp_int* order, int max, + mp_int* r) +{ + (void)order; + (void)max; + + /* Duplicate line to stop static analyzer complaining. */ + return mp_copy(a, r); +} +#endif + +/* + * Compute the HE = hash( HS | r | M ), hash value of signature. + * + * Partial result required for signing and verification. + * + * @param [in] key ECCSI key. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] r MP integer that is the first signature element. + * @param [in] msg Message of signature. + * @param [in] msgSz Length of message in bytes. + * @param [out] he Signature hash. + * @param [out] heSz Length of signature hash in bytes + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_compute_he(EccsiKey* key, enum wc_HashType hashType, + mp_int* r, const byte* msg, word32 msgSz, byte* he, word32* heSz) +{ + int err = 0; + word32 dataSz = key->ecc.dp->size; + + /* HE = hash( HS | r | M ) */ + err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID); + if (err == 0) { + /* HS */ + err = wc_HashUpdate(&key->hash, hashType, key->idHash, key->idHashSz); + } + if (err == 0) { + err = mp_to_unsigned_bin_len(r, key->data, dataSz); + } + if (err == 0) { + /* r */ + err = wc_HashUpdate(&key->hash, hashType, key->data, dataSz); + } + if (err == 0) { + /* M */ + err = wc_HashUpdate(&key->hash, hashType, msg, msgSz); + } + if (err == 0) { + err = wc_HashFinal(&key->hash, hashType, he); + } + if (err == 0) { + *heSz = wc_HashGetDigestSize(hashType); + } + + return err; +} + +/* + * Encode the signature = ( r | s | PVT ) + * + * @param [in] key ECCSI key. + * @param [in] r MP integer that is the first signature element. + * @param [in] s MP integer that is the second signature element. + * @param [in] pvt ECC point representing Public Validation Token. + * @param [out] sig Signature of message. + * @param [out] sigSz Length of signature in bytes. + */ +static int eccsi_encode_sig(const EccsiKey* key, mp_int* r, mp_int* s, + byte* sig, word32* sigSz) +{ + int err; + word32 sz = key->ecc.dp->size; + + err = mp_to_unsigned_bin_len(r, sig, sz); + if (err == 0) { + err = mp_to_unsigned_bin_len(s, sig + sz, sz); + } + if (err == 0) { + *sigSz = key->ecc.dp->size * 2 + 1; + err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(key->ecc.dp->id), + key->pvt, sig + sz * 2, sigSz); + } + if (err == 0) { + *sigSz = sz * 4 + 1; + } + + return err; +} + +/* + * Sign the ECCSI hash (of ID with the key) to two mp_int objects: r and s. + * + * RFC 6507, Section 5.2.1, Steps 1 to 4 + * + * @param [in] key ECCSI key. + * @param [in] rng Random number generator. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] msg Message to sign. + * @param [in] msgSz Length of message in bytes. + * @param [out] r First big number integer part of signature. + * @param [out] s Second big number integer part of signature. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_gen_sig(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType, + const byte* msg, word32 msgSz, mp_int* r, mp_int* s) +{ + int err = 0; + word32 sz = key->ecc.dp->size; + word32 heSz = 0; + const mp_int* jx = NULL; + mp_int* he = &key->tmp; + int genTryCnt = 0; + + do { + /* Don't infinitely gen sigs when random number generator fails. */ + if ((++genTryCnt) > ECCSI_MAX_GEN_COUNT) { + err = RNG_FAILURE_E; + } + + if (err == 0) { + /* Step 1 and 2: Generate ephemeral key - j, J = [j]G, r = Jx */ + err = wc_ecc_make_key_ex(rng, sz, &key->pubkey, key->ecc.dp->id); + } + if (err == 0) { + jx = key->pubkey.pubkey.x; + err = eccsi_fit_to_octets(jx, &key->params.order, sz, r); + } + + /* Step 3: Compute HE = hash( HS | r | M ) */ + if (err == 0) { + err = eccsi_compute_he(key, hashType, r, msg, msgSz, key->data, + &heSz); + } + + /* Step 4: Verify that HE + r * SSK is non-zero modulo q */ + if (err == 0) { + err = mp_read_unsigned_bin(he, key->data, heSz); + } + /* s' = r * SSK */ + if (err == 0) { + err = mp_mulmod(r, &key->ssk, &key->params.order, s); + } + /* s' = HE + r * SSK */ + if (err == 0) { + err = mp_addmod(he, s, &key->params.order, s); + } + } + while ((err == 0) && (mp_iszero(s) || (mp_cmp(s, he) == MP_EQ))); + + return err; +} + + +/** + * Sign the ECCSI hash (of ID with the key). + * + * RFC 6507, Section 5.2.1 + * + * Must have imported KPAK using wc_ImportEccsiPublicKey() before calling.\n + * Use wc_HashEccsiId() to calculate the hash and wc_SetEccsiHash() to set + * the identity hash to use. + * + * @param [in] key ECCSI key. + * @param [in] rng Random number generator. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] msg Message to sign. + * @param [in] msgSz Length of message in bytes. + * @param [out] sig Signature of message. + * @param [out] sigSz Length of signature in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rng, msg or sigSz is NULL. + * @return BAD_STATE_E when the curve or id hash has not been set (no key set). + * @return LENGTH_ONLY_E when sig is NULL - sigSz is set. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +int wc_SignEccsiHash(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType, + const byte* msg, word32 msgSz, byte* sig, word32* sigSz) +{ + int err = 0; + mp_int* r = NULL; + mp_int* s = NULL; + mp_int* j = NULL; + word32 sz = 0; + + if ((key == NULL) || (rng == NULL) || (msg == NULL) || (sigSz == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->ecc.type != ECC_PUBLICKEY) && + (key->ecc.type != ECC_PRIVATEKEY)) { + err = BAD_STATE_E; + } + if ((err == 0) && (sig != NULL) && (key->idHashSz == 0)) { + err = BAD_STATE_E; + } + + if (err == 0) { + sz = key->ecc.dp->size; + if (sig == NULL) { + *sigSz = sz * 4 + 1; + err = LENGTH_ONLY_E; + } + } + if ((err == 0) && (*sigSz < sz * 4 + 1)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + r = key->pubkey.pubkey.y; + s = key->pubkey.pubkey.z; + + err = eccsi_load_order(key); + } + + if (err == 0) { + /* Steps 1 to 4. */ + err = eccsi_gen_sig(key, rng, hashType, msg, msgSz, r, s); + } + + /* Step 5: s' = ( (( HE + r * SSK )^-1) * j ) modulo q, erase j */ + if (err == 0) { + err = mp_invmod(s, &key->params.order, s); + } + if (err == 0) { + j = &key->pubkey.k; + err = mp_mulmod(s, j, &key->params.order, s); + } + if (err == 0) { + mp_forcezero(j); + + /* Step 6: s = s' fitted */ + err = eccsi_fit_to_octets(s, &key->params.order, sz, s); + } + + /* Step 7: Output Signature = ( r | s | PVT ) */ + if (err == 0) { + err = eccsi_encode_sig(key, r, s, sig, sigSz); + } + + return err; +} + +/* + * Decode the s part of the signature = ( r | s | PVT ) + * + * @param [in] key ECCSI key. + * @param [in] sig Signature of message. + * @param [in] sigSz Length of signature in bytes. + * @param [out] s MP integer that is the second signature element. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_decode_sig_s(const EccsiKey* key, const byte* sig, + word32 sigSz, mp_int* s) +{ + int err = 0; + word32 sz = key->ecc.dp->size; + + if (sigSz != sz * 4 + 1) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = mp_read_unsigned_bin(s, sig + sz, sz); + } + + return err; +} + +/* + * Decode the r and pvt part of the signature = ( r | s | PVT ) + * + * @param [in] key ECCSI key. + * @param [in] sig Signature of message. + * @param [in] sigSz Length of signature in bytes. + * @param [out] r MP integer that is the first signature element. + * @param [out] pvt ECC point representing Public Validation Token. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value when an internal operation fails. + */ +static int eccsi_decode_sig_r_pvt(const EccsiKey* key, const byte* sig, + word32 sigSz, mp_int* r, ecc_point* pvt) +{ + int err = 0; + word32 sz = key->ecc.dp->size; + + if (sigSz != sz * 4 + 1) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = mp_read_unsigned_bin(r, sig, sz); + } + if (err == 0) { + err = wc_ecc_import_point_der(sig + sz * 2, sz * 2 + 1, + wc_ecc_get_curve_idx(key->ecc.dp->id), pvt); + } + + return err; +} + +/* + * Calculate Y point as part of verification process. + * + * Y = [HS]PVT + KPAK + * + * @param [in] key ECCSI key. + * @param [in] pvt ECC point representing Public Validation Token. + * @param [in] mp Montgomery reduction multiplier. + * @param [out] y ECC point representing calculated value Y. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +static int eccsi_calc_y(EccsiKey* key, ecc_point* pvt, mp_digit mp, + ecc_point* y) +{ + int err; + mp_int* hs = &key->ssk; + + err = mp_read_unsigned_bin(hs, key->idHash, key->idHashSz); +#ifndef WOLFSSL_HAVE_SP_ECC + /* Need KPAK in montogmery form. */ + if (err == 0) { + err = eccsi_kpak_to_mont(key); + } +#endif + /* [HS]PVT + KPAK */ + if (err == 0) { + ecc_point* kpak = &key->ecc.pubkey; + err = eccsi_mulmod_point_add(key, hs, pvt, kpak, y, mp, 1); + } + + return err; +} + +/* + * Calculate J point as part of verification process. + * + * J = [s]( [HE]G + [r]Y ) + * + * @param [in] key ECCSI key. + * @param [in] hem MP int representation of HE = Hash (hs, r and message). + * @param [in] sig Signature of message. + * @param [in] sigSz Length of signature in bytes. + * @param [in] y ECC point representing [r]Y. + * @param [in] mp Montgomery reduction multiplier. + * @param [out] j ECC point representing calculated value J. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +static int eccsi_calc_j(EccsiKey* key, const mp_int* hem, const byte* sig, + word32 sigSz, ecc_point* y, mp_digit mp, ecc_point* j) +{ + int err; + mp_int* s = &key->tmp; + + /* [HE]G + [r]Y */ + err = eccsi_mulmod_base_add(key, hem, y, j, mp, 1); + if (err == 0) { + err = eccsi_decode_sig_s(key, sig, sigSz, s); + } + /* [s]( [HE]G + [r]Y ) */ + if (err == 0) { + err = eccsi_mulmod_point(key, s, j, j, 1); + } + + return err; +} + +/** + * Verify the ECCSI hash (of ID with the key). + * + * RFC 6507, Section 5.2.2 + * + * Must have imported KPAK using wc_ImportEccsiPublicKey() before calling.\n + * Use wc_HashEccsiId() to calculate the hash and wc_SetEccsiHash() to set + * the identity hash to use. + * + * @param [in] key ECCSI key. + * @param [in] hashType Type of hash algorithm. e.g. WC_SHA256 + * @param [in] msg Message to verify. + * @param [in] msgSz Length of message in bytes. + * @param [in] sig Signature of message. + * @param [in] sigSz Length of signature in bytes. + * @param [out] verified 1 when the signature was verified and 0 otherwise. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, hash, msg, sig or ret is NULL. + * @return BAD_STATE_E when the curve or id hash has not been set (no key set). + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType, + const byte* msg, word32 msgSz, const byte* sig, word32 sigSz, + int* verified) +{ + int err = 0; + byte* he = NULL; + word32 heSz = 0; + mp_int* r = NULL; + mp_int* jx = NULL; + mp_int* hem = NULL; + ecc_point* pvt = NULL; + ecc_point* y = NULL; + ecc_point* j = NULL; + mp_digit mp = 0; + EccsiKeyParams* params = &key->params; + + if ((key == NULL) || (msg == NULL) || (sig == NULL) || (verified == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->ecc.type != ECC_PRIVATEKEY) && + (key->ecc.type != ECC_PUBLICKEY)) { + err = BAD_STATE_E; + } + if ((err == 0) && (key->idHashSz == 0)) { + err = BAD_STATE_E; + } + + /* Decode the signature into components. */ + if (err == 0) { + r = &key->pubkey.k; + pvt = &key->pubkey.pubkey; + err = eccsi_decode_sig_r_pvt(key, sig, sigSz, r, pvt); + } + + /* Load the curve parameters for operations */ + if (err == 0) { + err = eccsi_load_base(key); + } + if (err == 0) { + err = eccsi_load_ecc_params(key); + } + if (err == 0) { + err = mp_montgomery_setup(¶ms->prime, &mp); + } + + /* Step 1: Validate PVT is on curve */ + if (err == 0) { + err = wc_ecc_is_point(pvt, ¶ms->a, ¶ms->b, ¶ms->prime); + } + + /* Step 2: Compute HS = hash( G | KPAK | ID | PVT ) + * HS is key->idHash, key->idHashSz */ + + /* Step 3: Compute HE = hash( HS | r | M ) */ + if (err == 0) { + he = key->data; + err = eccsi_compute_he(key, hashType, r, msg, msgSz, he, &heSz); + } + + /* Step 4: Y = [HS]PVT + KPAK */ + if (err == 0) { + y = pvt; + err = eccsi_calc_y(key, pvt, mp, y); + } + + /* Step 5: Compute J = [s]( [HE]G + [r]Y ) */ + /* [r]Y */ + if (err == 0) { + hem = &key->tmp; + err = mp_read_unsigned_bin(hem, he, heSz); + } + if (err == 0) { + err = eccsi_mulmod_point(key, r, y, y, 0); + } + if (err == 0) { + j = params->base; + err = eccsi_calc_j(key, hem, sig, sigSz, y, mp, j); + key->params.haveBase = 0; + } + + /* Step 6: Jx fitting, compare with r */ + if (err == 0) { + jx = &key->tmp; + err = eccsi_fit_to_octets(j->x, ¶ms->order, key->ecc.dp->size, jx); + } + + if (verified != NULL) { + *verified = ((err == 0) && (mp_cmp(jx, r) == MP_EQ)); + } + + return err; +} +#endif /* WOLFCRYPT_ECCSI_CLIENT */ + +#endif /* WOLFCRYPT_HAVE_ECCSI */ + diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 64aee3389..f8928871f 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -1,6 +1,6 @@ /* ed25519.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -450,8 +450,8 @@ int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, msgLen length of msg array res will be 1 on successful verify and 0 on unsuccessful key Ed25519 public key - context extra sigining data - contextLen length of extra sigining data + context extra signing data + contextLen length of extra signing data return 0 and res of 1 on success */ int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, @@ -469,8 +469,8 @@ int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, hashLen length of hash array res will be 1 on successful verify and 0 on unsuccessful key Ed25519 public key - context extra sigining data - contextLen length of extra sigining data + context extra signing data + contextLen length of extra signing data return 0 and res of 1 on success */ int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, @@ -488,8 +488,8 @@ int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, msgLen length of msg array res will be 1 on successful verify and 0 on unsuccessful key Ed25519 public key - context extra sigining data - contextLen length of extra sigining data + context extra signing data + contextLen length of extra signing data return 0 and res of 1 on success */ int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, @@ -811,4 +811,3 @@ int wc_ed25519_sig_size(ed25519_key* key) } #endif /* HAVE_ED25519 */ - diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index 366c7105b..bb401d28c 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -1,6 +1,6 @@ /* ed448.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index b9ec96085..7b1252bcf 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -1,6 +1,6 @@ /* error.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -518,6 +518,18 @@ const char* wc_GetErrorString(int error) case ASN_SELF_SIGNED_E: return "ASN self-signed certificate error"; + case SAKKE_VERIFY_FAIL_E: + return "SAKKE derivation verification error"; + + case MISSING_IV: + return "Required IV not set"; + + case MISSING_KEY: + return "Required key not set"; + + case BAD_LENGTH_E: + return "Value of length parameter is invalid."; + default: return "unknown error number"; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 697edf344..f1b2705f4 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1,6 +1,6 @@ /* evp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -44,6 +44,7 @@ #include #include +#include #ifndef NO_AES #ifdef HAVE_AES_CBC @@ -176,6 +177,8 @@ static const char EVP_NULL[] = "NULL"; #define EVP_NULL_SIZE 4 +#define EVP_PKEY_PRINT_LINE_WIDTH_MAX 80 +#define EVP_PKEY_PRINT_DIGITS_PER_LINE 15 static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); @@ -553,6 +556,7 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, } #if defined(HAVE_AESGCM) +#ifndef WOLFSSL_AESGCM_STREAM static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { @@ -570,11 +574,13 @@ static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, } return 0; } +#endif /* WOLFSSL_AESGCM_STREAM */ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) { +#ifndef WOLFSSL_AESGCM_STREAM int ret = 0; *outl = inl; @@ -606,8 +612,42 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, } return WOLFSSL_SUCCESS; +#else + int ret; + + /* When out is NULL then this is AAD. */ + if (out == NULL) { + if (ctx->enc) { + ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, in, + inl); + } + else { + ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, in, + inl); + } + } + /* When out is not NULL then this is plaintext/cipher text. */ + else { + if (ctx->enc) { + ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, out, in, inl, NULL, + 0); + } + else { + ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, out, in, inl, NULL, + 0); + } + } + *outl = inl; + if (ret == 0) { + ret = WOLFSSL_SUCCESS; + } + else { + ret = WOLFSSL_FAILURE; + } + return ret; +#endif /* WOLFSSL_AESGCM_STREAM */ } -#endif +#endif /* HAVE_AESGCM */ /* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, @@ -626,16 +666,16 @@ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, *outl = 0; #if !defined(NO_AES) && defined(HAVE_AESGCM) - switch (ctx->cipherType) { - case AES_128_GCM_TYPE: - case AES_192_GCM_TYPE: - case AES_256_GCM_TYPE: -/* if out == NULL, in/inl contains the additional authenticated data for GCM */ - return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl); - default: - /* fall-through */ - break; - } + switch (ctx->cipherType) { + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + /* if out == NULL, in/inl contains the additional authenticated data * for GCM */ + return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl); + default: + /* fall-through */ + break; + } #endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */ if (out == NULL) { @@ -770,6 +810,7 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, case AES_128_GCM_TYPE: case AES_192_GCM_TYPE: case AES_256_GCM_TYPE: +#ifndef WOLFSSL_AESGCM_STREAM if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0) || (ctx->gcmBufferLen == 0)) { if (ctx->enc) @@ -799,6 +840,24 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, else { *outl = 0; } +#else + /* No data to return - all handled in Update. */ + *outl = 0; + if (ctx->enc) { + ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes, ctx->authTag, + ctx->authTagSz); + } + else { + ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, ctx->authTag, + ctx->authTagSz); + } + if (ret == 0) { + ret = WOLFSSL_SUCCESS; + } + else { + ret = WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_AESGCM_STREAM */ /* Clear IV, since IV reuse is not recommended for AES GCM. */ XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); break; @@ -1206,7 +1265,7 @@ unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) case AES_128_GCM_TYPE: case AES_192_GCM_TYPE: case AES_256_GCM_TYPE: - return WOLFSSL_EVP_CIPH_GCM_MODE & + return WOLFSSL_EVP_CIPH_GCM_MODE | WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER; #endif #if defined(WOLFSSL_AES_COUNTER) @@ -1263,7 +1322,7 @@ unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) { if (cipher == NULL) return 0; - return WOLFSSL_CIPHER_mode(cipher); + return WOLFSSL_CIPHER_mode(cipher) & WOLFSSL_EVP_CIPH_MODE; } void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) @@ -1310,16 +1369,27 @@ int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) * * return WOLFSSL_SUCCESS on success */ +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +void wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) +#else int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) +#endif { - if (ctx == NULL) return 0; + if (ctx == NULL) +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + return; +#else + return 0; +#endif WOLFSSL_ENTER("EVP_PKEY_CTX_free"); if (ctx->pkey != NULL) wolfSSL_EVP_PKEY_free(ctx->pkey); if (ctx->peerKey != NULL) wolfSSL_EVP_PKEY_free(ctx->peerKey); XFREE(ctx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); +#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L return WOLFSSL_SUCCESS; +#endif } @@ -1442,8 +1512,8 @@ int wolfSSL_EVP_PKEY_CTX_ctrl_str(WOLFSSL_EVP_PKEY_CTX *ctx, } #endif /* NO_WOLFSSL_STUB */ -#if !defined(NO_DH) && defined(HAVE_ECC) -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION!=2)) +#if (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || defined(HAVE_ECC) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { int len; @@ -1552,7 +1622,7 @@ int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_ return WOLFSSL_SUCCESS; } #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* !NO_DH || HAVE_ECC */ +#endif /* (!NO_DH && WOLFSSL_DH_EXTRA) || HAVE_ECC */ /* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer. * @@ -1750,7 +1820,7 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char * switch (ctx->pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: - len = wolfSSL_RSA_private_encrypt((int)tbslen, (unsigned char*)tbs, sig, + len = wolfSSL_RSA_private_encrypt((int)tbslen, tbs, sig, ctx->pkey->rsa, ctx->padding); if (len < 0) break; @@ -1975,17 +2045,30 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey) } #endif +/* wolfSSL_EVP_PKEY_cmp + * returns 0 on success, -1 on failure. + * + * This behavior is different from openssl. + * EVP_PKEY_cmp returns: + * 1 : two keys match + * 0 : do not match + * -1: key types are different + * -2: the operation is not supported + * If you want this function behave the same as openSSL, + * define WOLFSSL_ERROR_CODE_OPENSSL so that WS_RETURN_CODE translates return + * codes to match OpenSSL equivalent behavior. + */ WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b) { int ret = -1; /* failure */ int a_sz = 0, b_sz = 0; if (a == NULL || b == NULL) - return ret; + return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); /* check its the same type of key */ if (a->type != b->type) - return ret; + return WS_RETURN_CODE(ret, -1); /* get size based on key type */ switch (a->type) { @@ -2006,30 +2089,172 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EV break; #endif /* HAVE_ECC */ default: - return ret; + return WS_RETURN_CODE(ret, -2); } /* switch (a->type) */ /* check size */ if (a_sz <= 0 || b_sz <= 0 || a_sz != b_sz) { - return ret; + return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); } /* check public key size */ if (a->pkey_sz > 0 && b->pkey_sz > 0 && a->pkey_sz != b->pkey_sz) { - return ret; + return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); } /* check public key */ if (a->pkey.ptr && b->pkey.ptr) { if (XMEMCMP(a->pkey.ptr, b->pkey.ptr, a->pkey_sz) != 0) { - return ret; + return WS_RETURN_CODE(ret, WOLFSSL_FAILURE); } } +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + ret = 1; /* the keys match */ +#else ret = 0; /* success */ - +#endif return ret; } +/** + * validate DH algorithm parameters + * @param dh_key a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @return WOLFSSL_SUCCESS on success, otherwise failure + */ +static int DH_param_check(WOLFSSL_DH* dh_key) +{ + int ret = WOLFSSL_SUCCESS; + WOLFSSL_BN_CTX* ctx = NULL; + WOLFSSL_BIGNUM *num1 = NULL; + WOLFSSL_BIGNUM *num2 = NULL; + + WOLFSSL_ENTER("DH_param_check"); + + ctx = wolfSSL_BN_CTX_new(); + if (ctx == NULL) { + WOLFSSL_MSG("failed to allocate memory"); + return WOLFSSL_FAILURE; + } + + num1 = wolfSSL_BN_new(); + num2 = wolfSSL_BN_new(); + if (num1 == NULL || num2 == NULL) { + WOLFSSL_MSG("failed to assign big number"); + ret = WOLFSSL_FAILURE; + } + + /* prime check */ + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_is_odd(dh_key->p) == 0){ + WOLFSSL_MSG("dh_key->p is not prime"); + ret = WOLFSSL_FAILURE; + } /* TODO safe prime check. need BN_rshift1 */ + + /* generator check */ + if (ret == WOLFSSL_SUCCESS && + (wolfSSL_BN_is_one(dh_key->g) || + wolfSSL_BN_is_negative(dh_key->g) || + wolfSSL_BN_is_zero(dh_key->g))) { + WOLFSSL_MSG("dh_key->g is not suitable generator"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_cmp(dh_key->p, dh_key->g) <= 0) { + WOLFSSL_MSG("dh_key->g is not suitable generator"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS && + dh_key->q != NULL) + { + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_mod_exp(num1, dh_key->g, dh_key->q, dh_key->p, ctx) == + WOLFSSL_FAILURE) { + WOLFSSL_MSG("BN_mod_exp failed"); + ret = WOLFSSL_FAILURE; + } + else + if (ret == WOLFSSL_SUCCESS && + wolfSSL_BN_is_one(num1) == WOLFSSL_FAILURE) { + WOLFSSL_MSG("dh_key->g is not suitable generator"); + ret = WOLFSSL_FAILURE; + } +#ifdef WOLFSSL_KEY_GEN + /* test if the number q is prime. */ + if (ret == WOLFSSL_SUCCESS && + (wolfSSL_BN_is_prime_ex(dh_key->q, 64, ctx, NULL) <= 0)) { + WOLFSSL_MSG("dh_key->q is not prime or error during check."); + ret = WOLFSSL_FAILURE; + } /* else TODO check q div q - 1. need BN_div */ +#endif + } + + /* clean up */ + wolfSSL_BN_CTX_free(ctx); + wolfSSL_BN_free(num1); + wolfSSL_BN_free(num2); + + WOLFSSL_LEAVE("DH_param_check", WOLFSSL_SUCCESS); + return ret; +} +/** + * validate the algorithm parameters + * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @return WOLFSSL_SUCCESS on success, otherwise failure + */ +int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx) +{ + int type; + int ret; + WOLFSSL_DH* dh_key = NULL; + + /* sanity check */ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + type = wolfSSL_EVP_PKEY_type(wolfSSL_EVP_PKEY_base_id(ctx->pkey)); + switch (type) { + #if !defined(NO_RSA) + case EVP_PKEY_RSA: + WOLFSSL_MSG("EVP_PKEY_RSA not yet implemented"); + return WOLFSSL_FAILURE; + #endif + #if defined(HAVE_ECC) + case EVP_PKEY_EC: + WOLFSSL_MSG("EVP_PKEY_EC not yet implemented"); + return WOLFSSL_FAILURE; + #endif + #if !defined(NO_DSA) + case EVP_PKEY_DSA: + WOLFSSL_MSG("EVP_PKEY_DSA not yet implemented"); + return WOLFSSL_FAILURE; + #endif + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENSSH) + #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) + case EVP_PKEY_DH: + dh_key = wolfSSL_EVP_PKEY_get1_DH(ctx->pkey); + if (dh_key != NULL) { + ret = DH_param_check(dh_key); + wolfSSL_DH_free(dh_key); + } + else + ret = WOLFSSL_FAILURE; + return ret; + #endif + #endif + default: + WOLFSSL_MSG("Unknown PKEY type"); + break; + } + + (void)ret; + (void)DH_param_check; + (void)dh_key; + return WOLFSSL_FAILURE; +} + /* Initialize structure for signing * * ctx WOLFSSL_EVP_MD_CTX structure to initialize @@ -2156,7 +2381,10 @@ int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, switch (pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: { - int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + int nid; + const WOLFSSL_EVP_MD *ctxmd = wolfSSL_EVP_MD_CTX_md(ctx); + if (ctxmd == NULL) break; + nid = wolfSSL_EVP_MD_type(ctxmd); if (nid < 0) break; return wolfSSL_RSA_sign(nid, md, mdsize, sigret, siglen, pkey->rsa); @@ -2215,7 +2443,7 @@ int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t l * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, - unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey) + const unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey) { int ret; unsigned char md[WC_MAX_DIGEST_SIZE]; @@ -2232,7 +2460,10 @@ int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, switch (pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: { - int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + int nid; + const WOLFSSL_EVP_MD *ctxmd = wolfSSL_EVP_MD_CTX_md(ctx); + if (ctxmd == NULL) break; + nid = wolfSSL_EVP_MD_type(ctxmd); if (nid < 0) break; return wolfSSL_RSA_verify(nid, md, mdsize, sig, (unsigned int)siglen, pkey->rsa); @@ -2608,7 +2839,11 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: { unsigned int sigSz; - int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + int nid; + const WOLFSSL_EVP_MD *md = wolfSSL_EVP_MD_CTX_md(ctx); + if (md == NULL) + break; + nid = wolfSSL_EVP_MD_type(md); if (nid < 0) break; ret = wolfSSL_RSA_sign_generic_padding(nid, digest, hashLen, @@ -2701,7 +2936,11 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, switch (ctx->pctx->pkey->type) { #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) case EVP_PKEY_RSA: { - int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + int nid; + const WOLFSSL_EVP_MD *md = wolfSSL_EVP_MD_CTX_md(ctx); + if (md == NULL) + return WOLFSSL_FAILURE; + nid = wolfSSL_EVP_MD_type(md); if (nid < 0) return WOLFSSL_FAILURE; return wolfSSL_RSA_verify_ex(nid, digest, hashLen, sig, @@ -3324,6 +3563,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #endif /* !NO_MD5 */ +#ifndef NO_WOLFSSL_STUB + void wolfSSL_EVP_set_pw_prompt(const char *prompt) + { + (void)prompt; + WOLFSSL_STUB("EVP_set_pw_prompt"); + } +#endif + #ifndef NO_WOLFSSL_STUB const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void) { @@ -3477,7 +3724,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) { int ret; if (src->isHMAC) { - ret = wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac); + return wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac); } else { switch (src->macType) { @@ -3571,8 +3818,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ret = BAD_FUNC_ARG; break; } + return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } - return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } /* copies structure in to the structure out @@ -4042,14 +4289,13 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ret = WOLFSSL_FAILURE; break; } + /* arg is 4...(ctx->ivSz - 8) */ + XMEMCPY(ctx->iv, ptr, arg); if (wc_InitRng(&rng) != 0) { WOLFSSL_MSG("wc_InitRng failed"); ret = WOLFSSL_FAILURE; break; } - if (arg) { - XMEMCPY(ctx->iv, ptr, arg); - } if (wc_RNG_GenerateBlock(&rng, ctx->iv + arg, ctx->ivSz - arg) != 0) { /* rng is freed immediately after if block so no need @@ -4073,10 +4319,18 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) WOLFSSL_MSG("Key or IV not set"); break; } - if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, ctx->ivSz)) != 0) { + if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, + ctx->ivSz)) != 0) { WOLFSSL_MSG("wc_AesGcmSetIV failed"); ret = WOLFSSL_FAILURE; } +#ifdef WOLFSSL_AESGCM_STREAM + /* Initialize using IV cached in Aes object. */ + if (wc_AesGcmInit(&ctx->cipher.aes, NULL, 0, NULL, 0) != 0) { + WOLFSSL_MSG("wc_AesGcmInit failed"); + ret = WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_AESGCM_STREAM */ /* OpenSSL increments the IV. Not sure why */ IncCtr(ctx->iv, ctx->ivSz); break; @@ -4110,6 +4364,16 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) { WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); if (ctx) { +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) + #if defined(HAVE_AESGCM) && defined(WOLFSSL_AESGCM_STREAM) + if ((ctx->cipherType == AES_128_GCM_TYPE) || + (ctx->cipherType == AES_192_GCM_TYPE) || + (ctx->cipherType == AES_256_GCM_TYPE)) { + wc_AesFree(&ctx->cipher.aes); + } + #endif /* HAVE_AESGCM && WOLFSSL_AESGCM_STREAM */ +#endif /* not FIPS or new FIPS */ ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ ctx->keyLen = 0; #ifdef HAVE_AESGCM @@ -4373,14 +4637,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ctx->authTagSz = AES_BLOCK_SIZE; ctx->ivSz = GCM_NONCE_MID_SZ; +#ifndef WOLFSSL_AESGCM_STREAM if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { WOLFSSL_MSG("wc_AesGcmSetKey() failed"); return WOLFSSL_FAILURE; } +#endif /* !WOLFSSL_AESGCM_STREAM */ if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); return WOLFSSL_FAILURE; } +#ifdef WOLFSSL_AESGCM_STREAM + /* Initialize with key and IV if available. */ + if (wc_AesGcmInit(&ctx->cipher.aes, key, + (key == NULL) ? 0 : ctx->keyLen, iv, + (iv == NULL) ? 0 : GCM_NONCE_MID_SZ) != 0) { + WOLFSSL_MSG("wc_AesGcmInit() failed"); + return WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_AESGCM_STREAM */ if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; } @@ -4398,14 +4673,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ctx->authTagSz = AES_BLOCK_SIZE; ctx->ivSz = GCM_NONCE_MID_SZ; +#ifndef WOLFSSL_AESGCM_STREAM if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { WOLFSSL_MSG("wc_AesGcmSetKey() failed"); return WOLFSSL_FAILURE; } +#endif /* !WOLFSSL_AESGCM_STREAM */ if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); return WOLFSSL_FAILURE; } +#ifdef WOLFSSL_AESGCM_STREAM + /* Initialize with key and IV if available. */ + if (wc_AesGcmInit(&ctx->cipher.aes, key, + (key == NULL) ? 0 : ctx->keyLen, iv, + (iv == NULL) ? 0 : GCM_NONCE_MID_SZ) != 0) { + WOLFSSL_MSG("wc_AesGcmInit() failed"); + return WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_AESGCM_STREAM */ if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; } @@ -4423,14 +4709,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ctx->authTagSz = AES_BLOCK_SIZE; ctx->ivSz = GCM_NONCE_MID_SZ; +#ifndef WOLFSSL_AESGCM_STREAM if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { WOLFSSL_MSG("wc_AesGcmSetKey() failed"); return WOLFSSL_FAILURE; } +#endif /* !WOLFSSL_AESGCM_STREAM */ if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); return WOLFSSL_FAILURE; } +#ifdef WOLFSSL_AESGCM_STREAM + /* Initialize with key and IV if available. */ + if (wc_AesGcmInit(&ctx->cipher.aes, + key, (key == NULL) ? 0 : ctx->keyLen, + iv, (iv == NULL) ? 0 : GCM_NONCE_MID_SZ) != 0) { + WOLFSSL_MSG("wc_AesGcmInit() failed"); + return WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_AESGCM_STREAM */ if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; } @@ -4482,7 +4779,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { - ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, AES_ENCRYPTION, 1); if (ret != 0) return WOLFSSL_FAILURE; @@ -4510,7 +4807,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { - ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, AES_ENCRYPTION, 1); if (ret != 0) return WOLFSSL_FAILURE; @@ -4536,7 +4833,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { - ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); } if (ret != 0) @@ -5262,6 +5559,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) case AES_192_GCM_TYPE : case AES_256_GCM_TYPE : WOLFSSL_MSG("AES GCM"); +#ifndef WOLFSSL_AESGCM_STREAM if (!dst) { ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len); } @@ -5275,6 +5573,50 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) len, ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz); } +#else + /* Do one shot operation with streaming API as other + * initialization set up for streaming. */ + ret = wc_AesGcmInit(&ctx->cipher.aes, NULL, 0, ctx->iv, + ctx->ivSz); + /* No destination means only AAD. */ + if ((ret == 0) && (dst == NULL)) { + if (ctx->enc) { + ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, NULL, + NULL, 0, src, len); + } + else { + ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, NULL, + NULL, 0, src, len); + } + } + /* Only plaintext/cipher text. */ + else if (ret == 0) { + if (ctx->enc) { + ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, dst, src, + len, NULL, 0); + } + else { + ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, dst, src, + len, NULL, 0); + if (ret == 0) { + ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, + ctx->authTag, ctx->authTagSz); + } + } + } + if (ret == 0) { + if (ctx->enc) { + /* Calculate authentication tag. */ + ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes, + ctx->authTag, ctx->authTagSz); + } + else { + /* Calculate authentication tag and compare. */ + ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, + ctx->authTag, ctx->authTagSz); + } + } +#endif /* WOLFSSL_AESGCM_STREAM */ if (ret == 0) ret = len; break; @@ -5991,9 +6333,8 @@ WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) } #endif /* HAVE_ECC */ -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) -#if !defined(NO_DH) && !defined(NO_FILESYSTEM) -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENSSH) +#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM) /* with set1 functions the pkey struct does not own the DH structure * Build the following DH Key format from the passed in WOLFSSL_DH * then store in WOLFSSL_EVP_PKEY in DER format. @@ -6040,7 +6381,7 @@ int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) ret = wc_DhParamsToDer(dhkey,NULL,&derSz); } - if (derSz <= 0 || ret != LENGTH_ONLY_E) { + if (derSz == 0 || ret != LENGTH_ONLY_E) { WOLFSSL_MSG("Failed to get size of DH Key"); return WOLFSSL_FAILURE; } @@ -6072,7 +6413,6 @@ int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) return WOLFSSL_SUCCESS; } -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key) { @@ -6082,7 +6422,6 @@ WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key) return key->dh; } -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key) { WOLFSSL_DH* local = NULL; @@ -6116,8 +6455,7 @@ WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key) return local; } -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* NO_DH && NO_FILESYSTEM */ +#endif /* NO_DH && WOLFSSL_DH_EXTRA && NO_FILESYSTEM */ int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key) { @@ -6710,17 +7048,24 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap) XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); pkey->heap = heap; pkey->type = WOLFSSL_EVP_PKEY_DEFAULT; + + /* init of mutex needs to come before wolfSSL_EVP_PKEY_free */ + ret = wc_InitMutex(&pkey->refMutex); + if (ret != 0){ + XFREE(pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); + WOLFSSL_MSG("Issue initializing mutex"); + return NULL; + } + #ifndef HAVE_FIPS ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID); #else ret = wc_InitRng(&pkey->rng); #endif pkey->references = 1; - wc_InitMutex(&pkey->refMutex); /* init of mutex needs to come before - * wolfSSL_EVP_PKEY_free */ if (ret != 0){ wolfSSL_EVP_PKEY_free(pkey); - WOLFSSL_MSG("memory failure"); + WOLFSSL_MSG("Issue initializing RNG"); return NULL; } } @@ -6803,6 +7148,887 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) } } } +#if defined(OPENSSL_EXTRA) + +/* Indent writes white spaces of the number specified by "indents" + * to the BIO. The number of white spaces is limited from 0 to + * EVP_PKEY_PRINT_INDENT_MAX. + * returns the amount written to BIO. + */ +static int Indent(WOLFSSL_BIO* out, int indents) +{ + int i; + char space = ' '; + if (out == NULL) { + return 0; + } + if (indents > EVP_PKEY_PRINT_INDENT_MAX) { + indents = EVP_PKEY_PRINT_INDENT_MAX; + } + for (i = 0; i < indents; i++) { + if (wolfSSL_BIO_write(out, &space, 1) < 0) { + break; + } + } + return indents -i; +} +/* PrintHexWithColon dump byte-data specified by "input" to the "out". + * Each line has leading white spaces( "indent" gives the number ) plus + * four spaces, then hex coded 15 byte data with separator ":" follow. + * Each line looks like: + * " 00:e6:ab: --- 9f:ef:" + * Parmeters: + * out bio to output dump data + * input buffer holding data to dump + * inlen input data size + * indent the number of spaces for indent + * Returns 1 on success, 0 on failure. + */ +static int PrintHexWithColon(WOLFSSL_BIO* out, const byte* input, + int inlen, int indent) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* buff = NULL; +#else + byte buff[EVP_PKEY_PRINT_LINE_WIDTH_MAX] = { 0 }; +#endif /* WOLFSSL_SMALL_STACK */ + int ret = WOLFSSL_SUCCESS; + word32 in = 0; + word32 i; + int idx; + const byte* data; + word32 outSz; + byte outHex[3]; + + if (!out || !input || inlen <= 0) { + return WOLFSSL_FAILURE; + } + + if (indent < 0) { + indent = 0; + } + if (indent > EVP_PKEY_PRINT_INDENT_MAX) { + indent = EVP_PKEY_PRINT_INDENT_MAX; + } + + data = input; + +#ifdef WOLFSSL_SMALL_STACK + buff = (byte*)XMALLOC(EVP_PKEY_PRINT_LINE_WIDTH_MAX, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (!buff) { + return WOLFSSL_FAILURE; + } +#endif + + /* print pub element */ + idx = 0; + + for (in = 0; in < (word32)inlen && ret == WOLFSSL_SUCCESS; in += + EVP_PKEY_PRINT_DIGITS_PER_LINE ) { + Indent(out, indent); + for (i = 0; (i < EVP_PKEY_PRINT_DIGITS_PER_LINE) && + (in + i < (word32)inlen); i++) { + + if (ret == WOLFSSL_SUCCESS) { + outSz = sizeof(outHex); + ret = Base16_Encode((const byte*)&data[in + i], 1, + outHex, &outSz) == 0; + } + if (ret == WOLFSSL_SUCCESS) { + XMEMCPY(buff + idx, outHex, 2); + idx += 2; + + if (in + i != (word32)inlen -1) { + XMEMSET(buff + idx, ':', 1); + idx += 1; + } + } + } + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_BIO_write(out, buff, idx) > 0; + } + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_BIO_write(out, "\n", 1) > 0; + } + if (ret == WOLFSSL_SUCCESS) { + XMEMSET(buff, 0, EVP_PKEY_PRINT_LINE_WIDTH_MAX); + idx = 0; + } + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} +#if !defined(NO_RSA) +/* PrintPubKeyRSA is a helper function for wolfSSL_EVP_PKEY_print_public + * to parse a DER format RSA public key specified in the second parameter. + * Parameters: + * out bio to output dump data + * pkey buffer holding public key data + * pkeySz public key data size + * indent the number of spaces for indent + * bitlen bit size of the given key + * pctx context(not used) + * Returns 1 on success, 0 on failure. +*/ +static int PrintPubKeyRSA(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, + int indent, int bitlen, ASN1_PCTX* pctx) +{ + byte buff[8] = { 0 }; + word32 inOutIdx = 0; + word32 nSz; /* size of modulus */ + word32 eSz; /* size of public exponent */ + const byte* n = NULL; + const byte* e = NULL; /* pointer to modulus/exponent */ + int idx; + int wsz; + word32 i; + unsigned long exponent = 0; + mp_int a; + char line[32] = { 0 }; + + (void)pctx; + + if( mp_init(&a) != 0) { + return WOLFSSL_FAILURE; + } + if (indent < 0) { + indent = 0; + } + if (indent > EVP_PKEY_PRINT_INDENT_MAX) { + indent = EVP_PKEY_PRINT_INDENT_MAX; + } + /* parse key to get modulus and exponent */ + if (wc_RsaPublicKeyDecode_ex(pkey, &inOutIdx, pkeySz, + &n, &nSz, &e, &eSz) != 0) { + return WOLFSSL_FAILURE; + } + + /* print out public key elements */ + idx = 0; + XMEMSET(buff, 0, sizeof(buff)); + Indent(out, indent); + XSTRNCPY(line, "RSA Public-Key: (", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (mp_set_int(&a, bitlen) != 0) { + return WOLFSSL_FAILURE; + } + if (mp_todecimal(&a, (char*)buff) != 0) { + return WOLFSSL_FAILURE; + } + wsz = (int)XSTRLEN((const char*)buff); + + if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, " bit)\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + /* print Modulus */ + Indent(out, indent); + XSTRNCPY(line, "Modulus:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + + /* print modulus with leading zero if exists */ + if (*n & 0x80 && *(n-1) == 0) { + n--; + nSz++; + } + if (PrintHexWithColon(out, n, nSz, indent + 4) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + /* print public Exponent */ + idx = 0; + Indent(out, indent); + XSTRNCPY(line, "Exponent: ", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + for (i = 0; i < eSz; i++) { + exponent <<= 8; + exponent += e[i]; + } + + XMEMSET(buff, 0, sizeof(buff)); + if (mp_set_int(&a, exponent) != 0) { + return WOLFSSL_FAILURE; + } + if (mp_todecimal(&a, (char*)buff) != 0) { + return WOLFSSL_FAILURE; + } + wsz = (int)XSTRLEN((const char*)buff); + + if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, " (0x", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + XMEMSET(buff, 0, sizeof(buff)); + if (mp_tohex(&a, (char*)buff) != 0) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(out, buff, (int)XSTRLEN((const char*)buff)) <= 0) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, ")\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} +#endif /* !NO_RSA */ + +#if defined(HAVE_ECC) +/* PrintPubKeyEC is a helper function for wolfSSL_EVP_PKEY_print_public + * to parse a DER format ECC public key specified in the second parameter. + * Parameters: + * out bio to output dump data + * pkey buffer holding public key data + * pkeySz public key data size + * indent the number of spaces for indent + * bitlen bit size of the given key + * pctx context(not used) + * Returns 1 on success, 0 on failure. +*/ +static int PrintPubKeyEC(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, + int indent, int bitlen, ASN1_PCTX* pctx) +{ + byte* pub = NULL; + word32 pubSz = 0; + byte buff[8] = { 0 }; + int res = WOLFSSL_SUCCESS; + word32 inOutIdx = 0; + int curveId = 0; + const byte* curveOID = NULL; + word32 oidSz = 0; + const char* OIDName = NULL; + const char* nistCurveName = NULL; + int nid; + int idx = 0; + int wsz = 0; + mp_int a; + ecc_key key; + char line[32] = { 0 }; + (void)pctx; + + if( mp_init(&a) != 0) { + return WOLFSSL_FAILURE; + } + if (indent < 0) { + indent = 0; + } + if (indent > EVP_PKEY_PRINT_INDENT_MAX) { + indent = EVP_PKEY_PRINT_INDENT_MAX; + } + + res = wc_ecc_init(&key) == 0; + + if (res == WOLFSSL_SUCCESS) { + res = wc_EccPublicKeyDecode(pkey, &inOutIdx, &key, pkeySz) == 0; + } + + if (res == WOLFSSL_SUCCESS) { + curveId = wc_ecc_get_oid(key.dp->oidSum, &curveOID, &oidSz); + res = curveId > 0 && oidSz > 0; + } + + /* get NIST curve name */ + if (res == WOLFSSL_SUCCESS) { + nid = EccEnumToNID(curveId); + if (nid != -1) { + /* look up object name and nist curve name*/ + OIDName = wolfSSL_OBJ_nid2sn(nid); + nistCurveName = wolfSSL_EC_curve_nid2nist(nid); + res = (nistCurveName != NULL) && (OIDName != NULL); + } + else { + res = WOLFSSL_FAILURE; + } + } + if (res == WOLFSSL_SUCCESS) { + pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (pub == NULL) { + return WOLFSSL_FAILURE; + } + pubSz = ECC_BUFSIZE; + XMEMSET(pub, 0, ECC_BUFSIZE); + + res = wc_ecc_export_x963(&key, pub, &pubSz) == 0; + } + if (res == WOLFSSL_SUCCESS) { + idx = 0; + res = Indent(out, indent) >= 0; + } + if (res == WOLFSSL_SUCCESS) { + XSTRNCPY(line, "Public-Key: (", sizeof(line)); + res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = mp_set_int(&a, bitlen) == 0; + } + if (res == WOLFSSL_SUCCESS) { + res = mp_todecimal(&a, (char*)buff) == 0; + } + if (res == WOLFSSL_SUCCESS) { + wsz = (int)XSTRLEN((const char*)buff); + } + if (res == WOLFSSL_SUCCESS) { + res = wolfSSL_BIO_write(out, buff + idx, wsz) >= 0; + } + if (res == WOLFSSL_SUCCESS) { + XSTRNCPY(line, " bit)\n", sizeof(line)); + res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = Indent(out, indent) >= 0; + } + if (res == WOLFSSL_SUCCESS) { + /* print pub element */ + XSTRNCPY(line, "pub:\n", sizeof(line)); + res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = PrintHexWithColon(out, pub, pubSz, indent + 4); + } + if (res == WOLFSSL_SUCCESS) { + res = Indent(out, indent) >= 0; + } + if (res == WOLFSSL_SUCCESS) { + /* print OID in name */ + XSTRNCPY(line, "ASN1 OID: ", sizeof(line)); + res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = wolfSSL_BIO_write(out, OIDName, (int)XSTRLEN(OIDName)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = wolfSSL_BIO_write(out, "\n", 1) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = Indent(out, indent) >= 0; + } + if (res == WOLFSSL_SUCCESS) { + /* print NIST curve name */ + XSTRNCPY(line, "NIST CURVE: ", sizeof(line)); + res = wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = wolfSSL_BIO_write(out, nistCurveName, + (int)XSTRLEN(nistCurveName)) > 0; + } + if (res == WOLFSSL_SUCCESS) { + res = wolfSSL_BIO_write(out, "\n", 1) > 0; + } + + if (pub != NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_ECC_BUFFER); + pub = NULL; + } + + return res; +} +#endif /* HAVE_ECC */ + +#if !defined(NO_DSA) +/* PrintPubKeyDSA is a helper function for wolfSSL_EVP_PKEY_print_public + * to parse a DER format DSA public key specified in the second parameter. + * Parameters: + * out bio to output dump data + * pkey buffer holding public key data + * pkeySz public key data size + * indent the number of spaces for indent + * bitlen bit size of the given key + * pctx context(not used) + * Returns 1 on success, 0 on failure. +*/ +static int PrintPubKeyDSA(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, + int indent, int bitlen, ASN1_PCTX* pctx) +{ + + byte buff[8] = { 0 }; + int length; + int res; + word32 inOutIdx = 0; + word32 oid; + byte tagFound; + byte *p = NULL, * q = NULL, * g = NULL, * y = NULL; + int pSz, qSz, gSz, ySz; + int idx; + int wsz; + mp_int a; + char line[32] = { 0 }; + + if( mp_init(&a) != 0) + return WOLFSSL_FAILURE; + + inOutIdx = 0; + (void)pctx; + + if (indent < 0) { + indent = 0; + } + if (indent > EVP_PKEY_PRINT_INDENT_MAX) { + indent = EVP_PKEY_PRINT_INDENT_MAX; + } + if (GetSequence(pkey, &inOutIdx, &length, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + if (GetSequence(pkey, &inOutIdx, &length, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + res = GetObjectId(pkey, &inOutIdx, &oid, oidIgnoreType, pkeySz); + if (res != 0) { + return WOLFSSL_FAILURE; + } + if (GetSequence(pkey, &inOutIdx, &length, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + /* find P */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + p = (byte*)(pkey + inOutIdx); + pSz = length; + + if (bitlen == 0) { + if (*p == 0) { + bitlen = (pSz - 1) * 8; /* remove leading zero */ + } + else { + bitlen = pSz * 8; + } + } + + inOutIdx += length; + /* find Q */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + q = (byte*)(pkey + inOutIdx); + qSz = length; + inOutIdx += length; + + /* find G */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + g = (byte*)(pkey + inOutIdx); + gSz = length; + inOutIdx += length; + /* find Y */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_BIT_STRING) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + inOutIdx++; /* skip the first byte( unused byte number)*/ + + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, &length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + y = (byte*)(pkey + inOutIdx); + ySz = length; + + idx = 0; + XMEMSET(buff, 0, sizeof(buff)); + Indent(out, indent); + XSTRNCPY(line, "DSA Public-Key: (", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (mp_set_int(&a, bitlen) != 0) { + return WOLFSSL_FAILURE; + } + if (mp_todecimal(&a, (char*)buff) != 0) { + return WOLFSSL_FAILURE; + } + wsz = (int)XSTRLEN((const char*)buff); + if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, " bit)\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + /* print pub element */ + Indent(out, indent); + XSTRNCPY(line, "pub:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (PrintHexWithColon(out, y, ySz, indent + 4) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + /* print P element */ + Indent(out, indent); + XSTRNCPY(line, "P:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (PrintHexWithColon(out, p, pSz, indent + 4) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + /* print Q element */ + Indent(out, indent); + XSTRNCPY(line, "Q:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (PrintHexWithColon(out, q, qSz, indent + 4) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + /* print G element */ + Indent(out, indent); + XSTRNCPY(line, "G:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (PrintHexWithColon(out, g, gSz, indent + 4) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DSA */ + +#if defined(WOLFSSL_DH_EXTRA) +/* PrintPubKeyDH is a helper function for wolfSSL_EVP_PKEY_print_public + * to parse a DER format DH public key specified in the second parameter. + * Parameters: + * out bio to output dump data + * pkey buffer holding public key data + * pkeySz public key data size + * indent the number of spaces for indent + * bitlen bit size of the given key + * pctx context(not used) + * Returns 1 on success, 0 on failure. +*/ +static int PrintPubKeyDH(WOLFSSL_BIO* out, const byte* pkey, int pkeySz, + int indent, int bitlen, ASN1_PCTX* pctx) +{ + + byte buff[8] = { 0 }; + word32 length; + word32 inOutIdx; + word32 oid; + byte tagFound; + byte* prime = NULL; + int primeSz; + byte generator; + byte* publicKey = NULL; + int publicKeySz; + int idx; + int wsz; + word32 outSz; + byte outHex[3]; + mp_int a; + char line[32] = { 0 }; + + if( mp_init(&a) != 0) + return WOLFSSL_FAILURE; + + inOutIdx = 0; + (void)pctx; + + if (indent < 0) { + indent = 0; + } + if (indent > EVP_PKEY_PRINT_INDENT_MAX) { + indent = EVP_PKEY_PRINT_INDENT_MAX; + } + if (GetSequence(pkey, &inOutIdx, (int*)&length, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + if (GetSequence(pkey, &inOutIdx, (int*)&length, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + if (GetObjectId(pkey, &inOutIdx, &oid, oidIgnoreType, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + if (GetSequence(pkey, &inOutIdx, (int*)&length, pkeySz) < 0) { + return WOLFSSL_FAILURE; + } + /* get prime element */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + prime = (byte*)(pkey + inOutIdx); + primeSz = length; + inOutIdx += length; + + /* get generator element */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + if (length != 1) { + return WOLFSSL_FAILURE; + } + generator = *(pkey + inOutIdx); + inOutIdx += length; + + /* get public-key element */ + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_BIT_STRING) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + inOutIdx ++; + if (GetASNTag(pkey, &inOutIdx, &tagFound, pkeySz) != 0) { + return WOLFSSL_FAILURE; + } + if (tagFound != ASN_INTEGER) { + return WOLFSSL_FAILURE; + } + if (GetLength(pkey, &inOutIdx, (int*)&length, pkeySz) <= 0) { + return WOLFSSL_FAILURE; + } + publicKeySz = length; + publicKey = (byte*)(pkey + inOutIdx); + + if (bitlen == 0) { + if (*publicKey == 0) { + bitlen = (publicKeySz - 1) * 8; + } + else { + bitlen = publicKeySz * 8; + } + } + + /* print elements */ + idx = 0; + Indent(out, indent); + XSTRNCPY(line, "DH Public-Key: (", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (mp_set_int(&a, bitlen) != 0) { + return WOLFSSL_FAILURE; + } + if (mp_todecimal(&a, (char*)buff) != 0) { + return WOLFSSL_FAILURE; + } + wsz = (int)XSTRLEN((const char*)buff); + if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, " bit)\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + Indent(out, indent); + XSTRNCPY(line, "public-key:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (PrintHexWithColon(out, publicKey, publicKeySz, indent + 4) + != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + Indent(out, indent); + XSTRNCPY(line, "prime:\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (PrintHexWithColon(out, prime, primeSz, indent + 4) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + idx = 0; + XMEMSET(buff, 0, sizeof(buff)); + Indent(out, indent); + XSTRNCPY(line, "generator: ", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + if (mp_set_int(&a, generator) != 0) { + return WOLFSSL_FAILURE; + } + if (mp_todecimal(&a, (char*)buff) != 0) { + return WOLFSSL_FAILURE; + } + wsz = (int)XSTRLEN((const char*)buff); + if (wolfSSL_BIO_write(out, buff + idx, wsz) <= 0) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, " (0x", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + idx = 0; + XMEMSET(buff, 0, sizeof(buff)); + outSz = sizeof(outHex); + if (Base16_Encode((const byte*)&generator, 1, outHex, &outSz ) != 0) { + return WOLFSSL_FAILURE; + } + if (idx + 2 < (int)sizeof(buff) ) { + XMEMCPY(buff + idx, outHex, 2); + idx += 2; + } + if (wolfSSL_BIO_write(out, buff, idx) <= 0 ) { + return WOLFSSL_FAILURE; + } + XSTRNCPY(line, ")\n", sizeof(line)); + if (wolfSSL_BIO_write(out, line, (int)XSTRLEN(line)) <= 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_DH_EXTRA */ + +/* wolfSSL_EVP_PKEY_print_public parses the specified key then + * outputs public key info in human readable format to the specified BIO. + * White spaces of the same number which 'indent" gives, will be added to + * each line to output and ignores pctx parameter. + * Parameters: + * out bio to output dump data + * pkey buffer holding public key data + * indent the number of spaces for indent + * pctx context(not used) + * Returns 1 on success, 0 or negative on error, -2 means specified key + * algo is not supported. + * Can handle RSA, ECC, DSA and DH public keys. + */ +int wolfSSL_EVP_PKEY_print_public(WOLFSSL_BIO* out, + const WOLFSSL_EVP_PKEY* pkey, int indent, ASN1_PCTX* pctx) +{ + int res; + int keybits; /* bit length of the key */ + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_print_public"); + + if (pkey == NULL || out == NULL) { + return 0; + } + if (indent < 0) { + indent = 0; + } + if (indent > EVP_PKEY_PRINT_INDENT_MAX) { + indent = EVP_PKEY_PRINT_INDENT_MAX; + } + switch (pkey->type) { + case EVP_PKEY_RSA: + +#if !defined(NO_RSA) + keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; + res = PrintPubKeyRSA( + out, + (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ + pkey->pkey_sz, /* raw pkey size */ + indent, /* indent size */ + keybits, /* bit length of the key */ + pctx); /* not used */ +#else + res = WOLFSSL_UNKNOWN; /* not supported algo */ +#endif + break; + + case EVP_PKEY_EC: + +#if defined(HAVE_ECC) + keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; + res = PrintPubKeyEC( + out, + (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ + pkey->pkey_sz, /* raw pkey size */ + indent, /* indent size */ + keybits, /* bit length of the key */ + pctx); /* not used */ +#else + res = WOLFSSL_UNKNOWN; /* not supported algo */ +#endif + break; + + case EVP_PKEY_DSA: + +#if !defined(NO_DSA) + keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; + res = PrintPubKeyDSA( + out, + (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ + pkey->pkey_sz, /* raw pkey size */ + indent, /* indent size */ + keybits, /* bit length of the key */ + pctx); /* not used */ +#else + res = WOLFSSL_UNKNOWN; /* not supported algo */ +#endif + break; + + case EVP_PKEY_DH: + +#if defined(WOLFSSL_DH_EXTRA) + keybits = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey) * 8; + res = PrintPubKeyDH( + out, + (byte*)(pkey->pkey.ptr), /* buffer for pkey raw data */ + pkey->pkey_sz, /* raw pkey size */ + indent, /* indent size */ + keybits, /* bit length of the key */ + pctx); /* not used */ +#else + res = WOLFSSL_UNKNOWN; /* not supported algo */ +#endif + break; + + default: + res = WOLFSSL_UNKNOWN; /* not supported algo */ + break; + } + return res; +} +#endif /* OPENSSL_EXTRA */ #if !defined(NO_PWDBASED) int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, diff --git a/wolfcrypt/src/fe_low_mem.c b/wolfcrypt/src/fe_low_mem.c index b42cdfdfd..f683cd7d5 100644 --- a/wolfcrypt/src/fe_low_mem.c +++ b/wolfcrypt/src/fe_low_mem.c @@ -1,6 +1,6 @@ /* fe_low_mem.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c index 8a0248a5f..9fc299d2c 100644 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -1,6 +1,6 @@ /* fe_operations.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fe_x25519_asm.S b/wolfcrypt/src/fe_x25519_asm.S index 2a85fab8d..48b1a17f5 100644 --- a/wolfcrypt/src/fe_x25519_asm.S +++ b/wolfcrypt/src/fe_x25519_asm.S @@ -1,6 +1,6 @@ /* fe_x25519_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mont_small.i b/wolfcrypt/src/fp_mont_small.i index 380b0a25b..4cfe411f0 100644 --- a/wolfcrypt/src/fp_mont_small.i +++ b/wolfcrypt/src/fp_mont_small.i @@ -1,6 +1,6 @@ /* fp_mont_small.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_12.i b/wolfcrypt/src/fp_mul_comba_12.i index 0f0683d74..8d29a06fd 100644 --- a/wolfcrypt/src/fp_mul_comba_12.i +++ b/wolfcrypt/src/fp_mul_comba_12.i @@ -1,6 +1,6 @@ /* fp_mul_comba_12.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_17.i b/wolfcrypt/src/fp_mul_comba_17.i index fb3205515..c5e1a7203 100644 --- a/wolfcrypt/src/fp_mul_comba_17.i +++ b/wolfcrypt/src/fp_mul_comba_17.i @@ -1,6 +1,6 @@ /* fp_mul_comba_17.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_20.i b/wolfcrypt/src/fp_mul_comba_20.i index 372f51f41..599d3e516 100644 --- a/wolfcrypt/src/fp_mul_comba_20.i +++ b/wolfcrypt/src/fp_mul_comba_20.i @@ -1,6 +1,6 @@ /* fp_mul_comba_20.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_24.i b/wolfcrypt/src/fp_mul_comba_24.i index 17705f7df..561dda2db 100644 --- a/wolfcrypt/src/fp_mul_comba_24.i +++ b/wolfcrypt/src/fp_mul_comba_24.i @@ -1,6 +1,6 @@ /* fp_mul_comba_24.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_28.i b/wolfcrypt/src/fp_mul_comba_28.i index 594db74ef..a2ae5606d 100644 --- a/wolfcrypt/src/fp_mul_comba_28.i +++ b/wolfcrypt/src/fp_mul_comba_28.i @@ -1,6 +1,6 @@ /* fp_mul_comba_28.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_3.i b/wolfcrypt/src/fp_mul_comba_3.i index 0befff860..a4981726a 100644 --- a/wolfcrypt/src/fp_mul_comba_3.i +++ b/wolfcrypt/src/fp_mul_comba_3.i @@ -1,6 +1,6 @@ /* fp_mul_comba_3.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_32.i b/wolfcrypt/src/fp_mul_comba_32.i index 97dc076be..63543435d 100644 --- a/wolfcrypt/src/fp_mul_comba_32.i +++ b/wolfcrypt/src/fp_mul_comba_32.i @@ -1,6 +1,6 @@ /* fp_mul_comba_32.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_4.i b/wolfcrypt/src/fp_mul_comba_4.i index 803c6151a..6f6f542bb 100644 --- a/wolfcrypt/src/fp_mul_comba_4.i +++ b/wolfcrypt/src/fp_mul_comba_4.i @@ -1,6 +1,6 @@ /* fp_mul_comba_4.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_48.i b/wolfcrypt/src/fp_mul_comba_48.i index 0d1533458..c1f307f76 100644 --- a/wolfcrypt/src/fp_mul_comba_48.i +++ b/wolfcrypt/src/fp_mul_comba_48.i @@ -1,6 +1,6 @@ /* fp_mul_comba_48.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_6.i b/wolfcrypt/src/fp_mul_comba_6.i index 815badcb8..a076e47ab 100644 --- a/wolfcrypt/src/fp_mul_comba_6.i +++ b/wolfcrypt/src/fp_mul_comba_6.i @@ -1,6 +1,6 @@ /* fp_mul_comba_6.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_64.i b/wolfcrypt/src/fp_mul_comba_64.i index 7080fa2a3..ba6a21a4a 100644 --- a/wolfcrypt/src/fp_mul_comba_64.i +++ b/wolfcrypt/src/fp_mul_comba_64.i @@ -1,6 +1,6 @@ /* fp_mul_comba_64.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_7.i b/wolfcrypt/src/fp_mul_comba_7.i index b969a9a3b..bc07b24ab 100644 --- a/wolfcrypt/src/fp_mul_comba_7.i +++ b/wolfcrypt/src/fp_mul_comba_7.i @@ -1,6 +1,6 @@ /* fp_mul_comba_7.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_8.i b/wolfcrypt/src/fp_mul_comba_8.i index 1d61a7781..f8fc01ea9 100644 --- a/wolfcrypt/src/fp_mul_comba_8.i +++ b/wolfcrypt/src/fp_mul_comba_8.i @@ -1,6 +1,6 @@ /* fp_mul_comba_8.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_9.i b/wolfcrypt/src/fp_mul_comba_9.i index 0eedd7597..87eef030b 100644 --- a/wolfcrypt/src/fp_mul_comba_9.i +++ b/wolfcrypt/src/fp_mul_comba_9.i @@ -1,6 +1,6 @@ /* fp_mul_comba_9.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_small_set.i b/wolfcrypt/src/fp_mul_comba_small_set.i index 62ab909cf..d2d12d31e 100644 --- a/wolfcrypt/src/fp_mul_comba_small_set.i +++ b/wolfcrypt/src/fp_mul_comba_small_set.i @@ -1,6 +1,6 @@ /* fp_mul_comba_small_set.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_12.i b/wolfcrypt/src/fp_sqr_comba_12.i index cded4b123..5aa809e4e 100644 --- a/wolfcrypt/src/fp_sqr_comba_12.i +++ b/wolfcrypt/src/fp_sqr_comba_12.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_12.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_17.i b/wolfcrypt/src/fp_sqr_comba_17.i index d2418d931..c669683ed 100644 --- a/wolfcrypt/src/fp_sqr_comba_17.i +++ b/wolfcrypt/src/fp_sqr_comba_17.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_17.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_20.i b/wolfcrypt/src/fp_sqr_comba_20.i index 78fd3fd96..0d965a81b 100644 --- a/wolfcrypt/src/fp_sqr_comba_20.i +++ b/wolfcrypt/src/fp_sqr_comba_20.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_20.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_24.i b/wolfcrypt/src/fp_sqr_comba_24.i index 602b36c09..971ddd2b9 100644 --- a/wolfcrypt/src/fp_sqr_comba_24.i +++ b/wolfcrypt/src/fp_sqr_comba_24.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_24.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_28.i b/wolfcrypt/src/fp_sqr_comba_28.i index 57c1acc30..7c4c78850 100644 --- a/wolfcrypt/src/fp_sqr_comba_28.i +++ b/wolfcrypt/src/fp_sqr_comba_28.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_28.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_3.i b/wolfcrypt/src/fp_sqr_comba_3.i index 51c3d7422..3b47cba8c 100644 --- a/wolfcrypt/src/fp_sqr_comba_3.i +++ b/wolfcrypt/src/fp_sqr_comba_3.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_3.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_32.i b/wolfcrypt/src/fp_sqr_comba_32.i index 4fcf3497b..02b027385 100644 --- a/wolfcrypt/src/fp_sqr_comba_32.i +++ b/wolfcrypt/src/fp_sqr_comba_32.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_32.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_4.i b/wolfcrypt/src/fp_sqr_comba_4.i index b7f257288..13935083c 100644 --- a/wolfcrypt/src/fp_sqr_comba_4.i +++ b/wolfcrypt/src/fp_sqr_comba_4.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_4.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_48.i b/wolfcrypt/src/fp_sqr_comba_48.i index 0f24532b1..d817aa9b5 100644 --- a/wolfcrypt/src/fp_sqr_comba_48.i +++ b/wolfcrypt/src/fp_sqr_comba_48.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_48.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_6.i b/wolfcrypt/src/fp_sqr_comba_6.i index b36416844..1e4651a9d 100644 --- a/wolfcrypt/src/fp_sqr_comba_6.i +++ b/wolfcrypt/src/fp_sqr_comba_6.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_6.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_64.i b/wolfcrypt/src/fp_sqr_comba_64.i index b9b2c8ab7..f8af68dc7 100644 --- a/wolfcrypt/src/fp_sqr_comba_64.i +++ b/wolfcrypt/src/fp_sqr_comba_64.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_64.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_7.i b/wolfcrypt/src/fp_sqr_comba_7.i index 09bf9954a..807ef5920 100644 --- a/wolfcrypt/src/fp_sqr_comba_7.i +++ b/wolfcrypt/src/fp_sqr_comba_7.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_7.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_8.i b/wolfcrypt/src/fp_sqr_comba_8.i index 23fd8e41d..53054689b 100644 --- a/wolfcrypt/src/fp_sqr_comba_8.i +++ b/wolfcrypt/src/fp_sqr_comba_8.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_8.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_9.i b/wolfcrypt/src/fp_sqr_comba_9.i index ed6451a77..c405c954f 100644 --- a/wolfcrypt/src/fp_sqr_comba_9.i +++ b/wolfcrypt/src/fp_sqr_comba_9.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_9.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_small_set.i b/wolfcrypt/src/fp_sqr_comba_small_set.i index a81ee10e2..64ae83c3d 100644 --- a/wolfcrypt/src/fp_sqr_comba_small_set.i +++ b/wolfcrypt/src/fp_sqr_comba_small_set.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_small_set.i * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/ge_low_mem.c b/wolfcrypt/src/ge_low_mem.c index a6b5b68be..a7b793842 100644 --- a/wolfcrypt/src/ge_low_mem.c +++ b/wolfcrypt/src/ge_low_mem.c @@ -1,6 +1,6 @@ /* ge_low_mem.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index beaa56e66..f743ef87b 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -1,6 +1,6 @@ /* ge_operations.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index b820dc3c5..b58a2c33a 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -1,6 +1,6 @@ /* hash.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -1381,7 +1381,7 @@ int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags) } #endif /* !WOLFSSL_NOSHA3_512 */ -#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) +#ifdef WOLFSSL_SHAKE256 int wc_Shake256Hash(const byte* data, word32 len, byte* hash, word32 hashLen) { @@ -1418,7 +1418,7 @@ int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags) return ret; } -#endif /* WOLFSSL_SHAKE_256 && !WOLFSSL_NO_SHAKE256 */ +#endif /* WOLFSSL_SHAKE_256 */ #endif /* WOLFSSL_SHA3 */ #endif /* !NO_HASH_WRAPPER */ diff --git a/wolfcrypt/src/hc128.c b/wolfcrypt/src/hc128.c index 96f02d16d..26592b765 100644 --- a/wolfcrypt/src/hc128.c +++ b/wolfcrypt/src/hc128.c @@ -1,6 +1,6 @@ /* hc128.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -33,7 +33,7 @@ #include #ifdef NO_INLINE #include - #include + #include #else #define WOLFSSL_MISC_INCLUDED #include @@ -116,23 +116,23 @@ static void generate_keystream(HC128* ctx, word32* keystream) } else { - ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; - step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); - step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]); - step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]); - step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]); - step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]); - step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]); - step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]); - step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]); - step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]); - step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]); - step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]); - step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]); - step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]); - step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]); - step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]); - step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]); + ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; + step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); + step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]); + step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]); + step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]); + step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]); + step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]); + step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]); + step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]); + step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]); + step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]); + step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]); + step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]); + step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]); + step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]); + step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]); + step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]); } } @@ -241,7 +241,7 @@ static void Hc128_SetIV(HC128* ctx, const byte* inIv) else XMEMSET(iv, 0, sizeof(iv)); - for (i = 0; i < (128 >> 5); i++) + for (i = 0; i < (128 >> 5); i++) ctx->iv[i] = LITTLE32(iv[i]); for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4]; @@ -249,26 +249,26 @@ static void Hc128_SetIV(HC128* ctx, const byte* inIv) /* expand the key and IV into the table T */ /* (expand the key and IV into the table P and Q) */ - for (i = 0; i < 8; i++) ctx->T[i] = ctx->key[i]; - for (i = 8; i < 16; i++) ctx->T[i] = ctx->iv[i-8]; + for (i = 0; i < 8; i++) ctx->T[i] = ctx->key[i]; + for (i = 8; i < 16; i++) ctx->T[i] = ctx->iv[i-8]; for (i = 16; i < (256+16); i++) - ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + + ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + ctx->T[i-16]+i; - for (i = 0; i < 16; i++) ctx->T[i] = ctx->T[256+i]; + for (i = 0; i < 16; i++) ctx->T[i] = ctx->T[256+i]; - for (i = 16; i < 1024; i++) - ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + + for (i = 16; i < 1024; i++) + ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + ctx->T[i-16]+256+i; /* initialize counter1024, X and Y */ - ctx->counter1024 = 0; - for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i]; + ctx->counter1024 = 0; + for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i]; for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i]; /* run the cipher 1024 steps before generating the output */ - for (i = 0; i < 64; i++) setup_update(ctx); + for (i = 0; i < 64; i++) setup_update(ctx); } @@ -342,25 +342,25 @@ static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64) { - generate_keystream(ctx, keystream); + generate_keystream(ctx, keystream); /* unroll loop */ - ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); - ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); - ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); - ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); - ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); - ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); - ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); - ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); - ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); - ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); - ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); - ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); - ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); - ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); - ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); - ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); + ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); + ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); + ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); + ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); + ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); + ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); + ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); + ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); + ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); + ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); + ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); + ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); + ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); + ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); + ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); + ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); } if (msglen > 0) @@ -378,7 +378,7 @@ static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, #endif for (i = 0; i < msglen; i++) - output[i] = input[i] ^ ((byte*)keystream)[i]; + output[i] = input[i] ^ ((byte*)keystream)[i]; } return 0; diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index f0e62c76e..4344fb962 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -1,6 +1,6 @@ /* hmac.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -200,62 +200,66 @@ int wc_HmacSizeByType(int type) int _InitHmac(Hmac* hmac, int type, void* heap) { int ret = 0; - +#ifdef WOLF_CRYPTO_CB + int devId = hmac->devId; +#else + int devId = INVALID_DEVID; +#endif switch (type) { #ifndef NO_MD5 case WC_MD5: - ret = wc_InitMd5(&hmac->hash.md5); + ret = wc_InitMd5_ex(&hmac->hash.md5, heap, devId); break; #endif /* !NO_MD5 */ #ifndef NO_SHA case WC_SHA: - ret = wc_InitSha(&hmac->hash.sha); + ret = wc_InitSha_ex(&hmac->hash.sha, heap, devId); break; #endif /* !NO_SHA */ #ifdef WOLFSSL_SHA224 case WC_SHA224: - ret = wc_InitSha224(&hmac->hash.sha224); + ret = wc_InitSha224_ex(&hmac->hash.sha224, heap, devId); break; #endif /* WOLFSSL_SHA224 */ #ifndef NO_SHA256 case WC_SHA256: - ret = wc_InitSha256(&hmac->hash.sha256); + ret = wc_InitSha256_ex(&hmac->hash.sha256, heap, devId); break; #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 case WC_SHA384: - ret = wc_InitSha384(&hmac->hash.sha384); + ret = wc_InitSha384_ex(&hmac->hash.sha384, heap, devId); break; #endif /* WOLFSSL_SHA384 */ #ifdef WOLFSSL_SHA512 case WC_SHA512: - ret = wc_InitSha512(&hmac->hash.sha512); + ret = wc_InitSha512_ex(&hmac->hash.sha512, heap, devId); break; #endif /* WOLFSSL_SHA512 */ #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 case WC_SHA3_224: - ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID); + ret = wc_InitSha3_224(&hmac->hash.sha3, heap, devId); break; #endif #ifndef WOLFSSL_NOSHA3_256 case WC_SHA3_256: - ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID); + ret = wc_InitSha3_256(&hmac->hash.sha3, heap, devId); break; #endif #ifndef WOLFSSL_NOSHA3_384 case WC_SHA3_384: - ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID); + ret = wc_InitSha3_384(&hmac->hash.sha3, heap, devId); break; #endif #ifndef WOLFSSL_NOSHA3_512 case WC_SHA3_512: - ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID); + ret = wc_InitSha3_512(&hmac->hash.sha3, heap, devId); break; #endif #endif @@ -1164,6 +1168,8 @@ void wc_HmacFree(Hmac* hmac) wc_Sha512Free(&hmac->hash.sha512); break; #endif /* WOLFSSL_SHA512 */ + default: + break; } } diff --git a/wolfcrypt/src/idea.c b/wolfcrypt/src/idea.c index 600c90654..1fb82e69b 100644 --- a/wolfcrypt/src/idea.c +++ b/wolfcrypt/src/idea.c @@ -1,6 +1,6 @@ /* idea.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 196feb42b..c5a14e50c 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -8,6 +8,7 @@ EXTRA_DIST += wolfcrypt/src/asm.c EXTRA_DIST += wolfcrypt/src/aes_asm.asm EXTRA_DIST += wolfcrypt/src/wc_dsp.c EXTRA_DIST += wolfcrypt/src/sp_dsp32.c +EXTRA_DIST += wolfcrypt/src/sp_x86_64_asm.asm EXTRA_DIST += \ wolfcrypt/src/ecc_fp.c \ @@ -64,9 +65,15 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/xilinx/xil-aesgcm.c \ wolfcrypt/src/port/caam/caam_aes.c \ wolfcrypt/src/port/caam/caam_driver.c \ - wolfcrypt/src/port/caam/caam_init.c \ + wolfcrypt/src/port/caam/caam_error.c \ + wolfcrypt/src/port/caam/caam_qnx.c \ + wolfcrypt/src/port/caam/caam_integrity.c \ wolfcrypt/src/port/caam/caam_sha.c \ wolfcrypt/src/port/caam/caam_doc.pdf \ + wolfcrypt/src/port/caam/wolfcaam_init.c \ + wolfcrypt/src/port/caam/wolfcaam_qnx.c \ + wolfcrypt/src/port/caam/wolfcaam_ecdsa.c \ + wolfcrypt/src/port/caam/wolfcaam_cmac.c \ wolfcrypt/src/port/silabs/silabs_aes.c \ wolfcrypt/src/port/silabs/silabs_ecc.c \ wolfcrypt/src/port/silabs/silabs_hash.c \ @@ -132,3 +139,10 @@ endif if BUILD_CRYPTOAUTHLIB src_libwolfssl_la_SOURCES += wolfcrypt/src/port/atmel/atmel.c endif + +if BUILD_CAAM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_init.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_qnx.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_ecdsa.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_cmac.c +endif diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 81987f96d..d2c33ba36 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -1,6 +1,6 @@ /* integer.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -238,7 +238,7 @@ void mp_forcezero(mp_int * a) /* get the size for an unsigned equivalent */ -int mp_unsigned_bin_size (mp_int * a) +int mp_unsigned_bin_size (const mp_int * a) { int size = mp_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); @@ -246,7 +246,7 @@ int mp_unsigned_bin_size (mp_int * a) /* returns the number of bits in an int */ -int mp_count_bits (mp_int * a) +int mp_count_bits (const mp_int * a) { int r; mp_digit q; @@ -350,7 +350,7 @@ int mp_init_copy (mp_int * a, mp_int * b) /* copy, b = a */ -int mp_copy (mp_int * a, mp_int * b) +int mp_copy (const mp_int * a, mp_int * b) { int res, n; @@ -686,7 +686,8 @@ int mp_mod_2d (mp_int * a, int b, mp_int * c) /* clear the digit that is not completely outside/inside the modulus */ x = DIGIT_BIT - (b % DIGIT_BIT); if (x != DIGIT_BIT) { - c->dp[b / DIGIT_BIT] &= ~((mp_digit)0) >> (x + ((sizeof(mp_digit)*8) - DIGIT_BIT)); + c->dp[b / DIGIT_BIT] &= + ((mp_digit)~((mp_digit)0)) >> (x + ((sizeof(mp_digit)*8) - DIGIT_BIT)); } mp_clamp (c); return MP_OKAY; @@ -868,16 +869,13 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) return MP_VAL; } if (mp_isone(P)) { - mp_set(Y, 0); - return MP_OKAY; + return mp_set(Y, 0); } if (mp_iszero(X)) { - mp_set(Y, 1); - return MP_OKAY; + return mp_set(Y, 1); } if (mp_iszero(G)) { - mp_set(Y, 0); - return MP_OKAY; + return mp_set(Y, 0); } /* if exponent X is negative we have to recurse */ @@ -1449,10 +1447,16 @@ int mp_set (mp_int * a, mp_digit b) /* check if a bit is set */ int mp_is_bit_set (mp_int *a, mp_digit b) { - if ((mp_digit)a->used < b/DIGIT_BIT) - return 0; + mp_digit i = b / DIGIT_BIT; /* word index */ + mp_digit s = b % DIGIT_BIT; /* bit index */ - return (int)((a->dp[b/DIGIT_BIT] >> b%DIGIT_BIT) & (mp_digit)1); + if ((mp_digit)a->used <= i) { + /* no words available at that bit count */ + return 0; + } + + /* get word and shift bit to check down to index 0 */ + return (int)((a->dp[i] >> s) & (mp_digit)1); } /* c = a mod b, 0 <= c < b */ @@ -2409,7 +2413,7 @@ int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y) } /* swap res with Y */ - mp_copy(res, Y); + err = mp_copy(res, Y); LBL_RES:mp_clear (res); LBL_M: @@ -4302,6 +4306,8 @@ int mp_add_d (mp_int* a, mp_digit b, mp_int* c) int res, ix, oldused; mp_digit *tmpa, *tmpc, mu; + if (b > MP_DIGIT_MAX) return MP_VAL; + /* grow c as required */ if (c->alloc < a->used + 1) { if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { @@ -5039,6 +5045,11 @@ int mp_lcm (mp_int * a, mp_int * b, mp_int * c) int res; mp_int t1, t2; + /* LCM of 0 and any number is undefined as 0 is not in the set of values + * being used. */ + if (mp_iszero (a) == MP_YES || mp_iszero (b) == MP_YES) { + return MP_VAL; + } if ((res = mp_init_multi (&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { return res; @@ -5083,6 +5094,10 @@ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) /* either zero than gcd is the largest */ if (mp_iszero (a) == MP_YES) { + /* GCD of 0 and 0 is undefined as all integers divide 0. */ + if (mp_iszero (b) == MP_YES) { + return MP_VAL; + } return mp_abs (b, c); } if (mp_iszero (b) == MP_YES) { @@ -5218,9 +5233,11 @@ int mp_read_radix (mp_int * a, const char *str, int radix) */ if (y < radix) { if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + mp_zero(a); return res; } if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + mp_zero(a); return res; } } else { diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index f6fc1fca1..97e145524 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -1,6 +1,6 @@ /* logging.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,11 +34,19 @@ #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) -static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */ +static +#ifdef ERROR_QUEUE_PER_THREAD +THREAD_LS_T +#endif +wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */ /* accessing any node from the queue should be wrapped in a lock of * debug_mutex */ -static void* wc_error_heap; +static +#ifdef ERROR_QUEUE_PER_THREAD +THREAD_LS_T +#endif +void* wc_error_heap; struct wc_error_queue { void* heap; /* the heap hint used with nodes creation */ struct wc_error_queue* next; @@ -48,9 +56,20 @@ struct wc_error_queue { int value; int line; }; +#ifdef ERROR_QUEUE_PER_THREAD +THREAD_LS_T +#endif volatile struct wc_error_queue* wc_errors; -static struct wc_error_queue* wc_current_node; -static struct wc_error_queue* wc_last_node; +static +#ifdef ERROR_QUEUE_PER_THREAD +THREAD_LS_T +#endif +struct wc_error_queue* wc_current_node; +static +#ifdef ERROR_QUEUE_PER_THREAD +THREAD_LS_T +#endif +struct wc_error_queue* wc_last_node; /* pointer to last node in queue to make insertion O(1) */ #endif @@ -122,7 +141,7 @@ const char *wolfSSL_configure_args(void) { #endif } -const char *wolfSSL_global_cflags(void) { +PEDANTIC_EXTENSION const char *wolfSSL_global_cflags(void) { #ifdef LIBWOLFSSL_GLOBAL_CFLAGS /* the spaces on either side are to make matching simple and efficient. */ return " " LIBWOLFSSL_GLOBAL_CFLAGS " "; @@ -208,20 +227,24 @@ void wolfSSL_Debugging_OFF(void) */ void WOLFSSL_START(int funcNum) { - double now = current_time(0) * 1000.0; -#ifdef WOLFSSL_FUNC_TIME_LOG - fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]); -#endif - wc_func_start[funcNum] = now; + if (funcNum < WC_FUNC_COUNT) { + double now = current_time(0) * 1000.0; + #ifdef WOLFSSL_FUNC_TIME_LOG + fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]); + #endif + wc_func_start[funcNum] = now; + } } void WOLFSSL_END(int funcNum) { - double now = current_time(0) * 1000.0; - wc_func_time[funcNum] += now - wc_func_start[funcNum]; -#ifdef WOLFSSL_FUNC_TIME_LOG - fprintf(stderr, "%17.3f: END - %s\n", now, wc_func_name[funcNum]); -#endif + if (funcNum < WC_FUNC_COUNT) { + double now = current_time(0) * 1000.0; + wc_func_time[funcNum] += now - wc_func_start[funcNum]; + #ifdef WOLFSSL_FUNC_TIME_LOG + fprintf(stderr, "%17.3f: END - %s\n", now, wc_func_name[funcNum]); + #endif + } } void WOLFSSL_TIME(int count) diff --git a/wolfcrypt/src/md2.c b/wolfcrypt/src/md2.c index c2f34203d..d4f16859f 100644 --- a/wolfcrypt/src/md2.c +++ b/wolfcrypt/src/md2.c @@ -1,6 +1,6 @@ /* md2.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/md4.c b/wolfcrypt/src/md4.c index f6f67454a..d6e061051 100644 --- a/wolfcrypt/src/md4.c +++ b/wolfcrypt/src/md4.c @@ -1,6 +1,6 @@ /* md4.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index 7bc2489e8..a0fcf9380 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -1,6 +1,6 @@ /* md5.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -127,7 +127,7 @@ static int Transform(wc_Md5* md5, const byte* data) #ifdef FREESCALE_MMCAU_CLASSIC_SHA cau_md5_hash_n((byte*)data, 1, (unsigned char*)md5->digest); #else - MMCAU_MD5_HashN((byte*)data, 1, (word32*)md5->digest); + MMCAU_MD5_HashN((byte*)data, 1, (uint32_t*)md5->digest); #endif wolfSSL_CryptHwMutexUnLock(); } @@ -148,7 +148,7 @@ static int Transform_Len(wc_Md5* md5, const byte* data, word32 len) #ifdef FREESCALE_MMCAU_CLASSIC_SHA cau_md5_hash_n(local, 1, (unsigned char*)md5->digest); #else - MMCAU_MD5_HashN(local, 1, (word32*)md5->digest); + MMCAU_MD5_HashN(local, 1, (uint32_t*)md5->digest); #endif data += WC_MD5_BLOCK_SIZE; len -= WC_MD5_BLOCK_SIZE; @@ -162,7 +162,7 @@ static int Transform_Len(wc_Md5* md5, const byte* data, word32 len) (unsigned char*)md5->digest); #else MMCAU_MD5_HashN((byte*)data, len / WC_MD5_BLOCK_SIZE, - (word32*)md5->digest); + (uint32_t*)md5->digest); #endif } wolfSSL_CryptHwMutexUnLock(); @@ -174,7 +174,8 @@ static int Transform_Len(wc_Md5* md5, const byte* data, word32 len) #include #define HAVE_MD5_CUST_API -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM) /* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */ #define HAVE_MD5_CUST_API #else @@ -195,7 +196,7 @@ static int Transform_Len(wc_Md5* md5, const byte* data, word32 len) static int Transform(wc_Md5* md5, const byte* data) { - word32* buffer = (word32*)data; + const word32* buffer = (const word32*)data; /* Copy context->state[] to working vars */ word32 a = md5->digest[0]; word32 b = md5->digest[1]; @@ -550,7 +551,20 @@ int wc_Md5Copy(wc_Md5* src, wc_Md5* dst) return ret; } - +#ifdef OPENSSL_EXTRA +/* Apply MD5 transformation to the data */ +/* @param md5 a pointer to wc_MD5 structure */ +/* @param data data to be applied MD5 transformation */ +/* @return 0 on successful, otherwise non-zero on failure */ +int wc_Md5Transform(wc_Md5* md5, const byte* data) +{ + /* sanity check */ + if (md5 == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + return Transform(md5, data); +} +#endif #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) int wc_Md5SetFlags(wc_Md5* md5, word32 flags) { diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 2352c5e00..5f2b39e73 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -1,6 +1,6 @@ /* memory.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -1031,7 +1031,7 @@ void XFREE(void *p, void* heap, int type) void *xmalloc(size_t n, void* heap, int type, const char* func, const char* file, unsigned int line) { - void* p; + void* p = NULL; word32* p32; if (malloc_function) @@ -1039,11 +1039,13 @@ void *xmalloc(size_t n, void* heap, int type, const char* func, else p32 = malloc(n + sizeof(word32) * 4); - p32[0] = (word32)n; - p = (void*)(p32 + 4); + if (p32 != NULL) { + p32[0] = (word32)n; + p = (void*)(p32 + 4); - fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n, type, - func, file, line); + fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n, + type, func, file, line); + } (void)heap; diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index d82d5dbc7..991cc2307 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -1,6 +1,6 @@ /* misc.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -81,6 +81,30 @@ masking and clearing memory logic. return y ? _lrotr(x, y) : x; } +#elif defined(__CCRX__) + + #include /* get intrinsic definitions */ + + #if !defined(NO_INLINE) + + #define rotlFixed(x, y) _builtin_rotl(x, y) + + #define rotrFixed(x, y) _builtin_rotr(x, y) + + #else /* create real function */ + + WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y) + { + return _builtin_rotl(x, y); + } + + WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y) + { + return _builtin_rotr(x, y); + } + + #endif + #else /* generic */ /* This routine performs a left circular arithmetic shift of by value. */ @@ -115,6 +139,9 @@ WC_STATIC WC_INLINE word16 rotrFixed16(word16 x, word16 y) #endif /* WC_RC2 */ /* This routine performs a byte swap of 32-bit word value. */ +#if defined(__CCRX__) && !defined(NO_INLINE) // shortest version for CC-RX + #define ByteReverseWord32(value) _builtin_revl(value) +#else WC_STATIC WC_INLINE word32 ByteReverseWord32(word32 value) { #ifdef PPC_INTRINSICS @@ -124,6 +151,8 @@ WC_STATIC WC_INLINE word32 ByteReverseWord32(word32 value) return (word32)__REV(value); #elif defined(KEIL_INTRINSICS) return (word32)__rev(value); +#elif defined(__CCRX__) + return (word32)_builtin_revl(value); #elif defined(WOLF_ALLOW_BUILTIN) && \ defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3) return (word32)__builtin_bswap32(value); @@ -153,6 +182,7 @@ WC_STATIC WC_INLINE word32 ByteReverseWord32(word32 value) return rotlFixed(value, 16U); #endif } +#endif /* __CCRX__ */ /* This routine performs a byte swap of words array of a given count. */ WC_STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in, word32 byteCount) diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 10bb8b3cc..7c3eb8994 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -1,6 +1,6 @@ /* pkcs12.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,6 +58,7 @@ enum { WC_PKCS12_ENCRYPTED_DATA = 656, WC_PKCS12_DATA_OBJ_SZ = 11, + WC_PKCS12_MAC_SALT_SZ = 8, }; static const byte WC_PKCS12_ENCRYPTED_OID[] = @@ -536,6 +537,7 @@ static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz, /* get hash type used and resulting size of HMAC key */ hashT = wc_OidGetHash(mac->oid); if (hashT == WC_HASH_TYPE_NONE) { + ForceZero(unicodePasswd, MAX_UNICODE_SZ); WOLFSSL_MSG("Unsupported hash used"); return BAD_FUNC_ARG; } @@ -543,12 +545,15 @@ static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz, /* check out buffer is large enough */ if (kLen < 0 || outSz < (word32)kLen) { + ForceZero(unicodePasswd, MAX_UNICODE_SZ); return BAD_FUNC_ARG; } /* idx contains size of unicodePasswd */ - if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, - mac->saltSz, mac->itt, kLen, (int)hashT, id, pkcs12->heap)) < 0) { + ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, mac->saltSz, + mac->itt, kLen, (int)hashT, id, pkcs12->heap); + ForceZero(unicodePasswd, MAX_UNICODE_SZ); + if (ret < 0) { return ret; } @@ -751,7 +756,14 @@ int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) outerSz += mac->saltSz; /* MAC iterations */ - outerSz += SetShortInt(ASNSHORT, &tmpIdx, mac->itt, MAX_SHORT_SZ); + ret = SetShortInt(ASNSHORT, &tmpIdx, mac->itt, MAX_SHORT_SZ); + if (ret >= 0) { + outerSz += ret; + ret = 0; + } + else { + return ret; + } /* sequence of inner data */ outerSz += SetSequence(innerSz, seq); @@ -1431,7 +1443,7 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, word32 sz; word32 totalSz = 0; int ret; - + byte* pkcs8Key = NULL; if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL || pass == NULL) { @@ -1444,6 +1456,7 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, if (out != NULL) { tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */ sz = *outSz - tmpIdx; + pkcs8Key = out + tmpIdx; } /* case of no encryption */ @@ -1461,8 +1474,8 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, } /* PKCS#8 wrapping around key */ - ret = wc_CreatePKCS8Key(out + tmpIdx, &sz, key, keySz, algoID, - curveOID, oidSz); + ret = wc_CreatePKCS8Key(pkcs8Key, &sz, key, keySz, algoID, curveOID, + oidSz); } else { WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag"); @@ -1472,7 +1485,7 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, vAlgo = 10; } - ret = UnTraditionalEnc(key, keySz, out + tmpIdx, &sz, pass, passSz, + ret = UnTraditionalEnc(key, keySz, pkcs8Key, &sz, pass, passSz, vPKCS, vAlgo, NULL, 0, itt, rng, heap); } if (ret == LENGTH_ONLY_E) { @@ -1813,6 +1826,7 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ WOLFSSL_MSG("Buffer not large enough for DATA OID"); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); return BUFFER_E; } XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); @@ -1820,6 +1834,7 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, /* copy over encrypted data */ if (idx + encSz > *outSz){ + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); return BUFFER_E; } XMEMCPY(out + idx, tmp, encSz); @@ -2341,8 +2356,9 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, mac->itt = macIter; /* set mac salt */ - mac->saltSz = 8; - mac->salt = (byte*)XMALLOC(mac->saltSz, heap, DYNAMIC_TYPE_PKCS); + mac->saltSz = WC_PKCS12_MAC_SALT_SZ; + mac->salt = (byte*)XMALLOC(WC_PKCS12_MAC_SALT_SZ, heap, + DYNAMIC_TYPE_PKCS); if (mac->salt == NULL) { wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 439d272b5..e257bb8f2 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1,6 +1,6 @@ /* pkcs7.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -1100,6 +1100,16 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) return ret; } + if (dCert->pubKeySize > (MAX_RSA_INT_SZ + MAX_RSA_E_SZ) || + dCert->serialSz > MAX_SN_SZ) { + WOLFSSL_MSG("Invalid size in certificate\n"); + FreeDecodedCert(dCert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + return ASN_PARSE_E; + } + XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize); pkcs7->publicKeySz = dCert->pubKeySize; pkcs7->publicKeyOID = dCert->keyOID; @@ -4917,16 +4927,27 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, der = pkcs7->der; pkcs7->der = NULL; #endif - contentDynamic = pkcs7->contentDynamic; version = pkcs7->version; - if (ret == 0) { byte isDynamic = pkcs7->isDynamic; #ifndef NO_PKCS7_STREAM PKCS7State* stream = pkcs7->stream; pkcs7->stream = NULL; #endif + + /* Save dynamic content before freeing PKCS7 struct */ + if (pkcs7->contentDynamic != NULL) { + contentDynamic = (byte*)XMALLOC(contentSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (contentDynamic == NULL) { + ret = MEMORY_E; + break; + } + XMEMCPY(contentDynamic, pkcs7->contentDynamic, + contentSz); + } + /* Free pkcs7 resources but not the structure itself */ pkcs7->isDynamic = 0; wc_PKCS7_Free(pkcs7); @@ -4934,11 +4955,18 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* This will reset PKCS7 structure and then set the * certificate */ ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + + /* Restore pkcs7->contentDynamic from above, will be + * freed by application with wc_PKCS7_Free() */ + if (contentDynamic != NULL) { + pkcs7->contentDynamic = contentDynamic; + contentDynamic = NULL; + } + #ifndef NO_PKCS7_STREAM pkcs7->stream = stream; #endif } - pkcs7->contentDynamic = contentDynamic; pkcs7->version = version; #ifdef ASN_BER_TO_DER pkcs7->der = der; @@ -5059,6 +5087,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); if (pkcs7->stream->flagOne) { pkiMsg2 = pkiMsg; + + /* check if using internal stream buffer and should adjust sz */ + if (pkiMsg != in && pkcs7->stream->length > 0) { + pkiMsg2Sz = pkcs7->stream->length; + } } /* restore content type */ @@ -5118,7 +5151,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } } else { - /* last state expect the reset of the buffer */ + /* last state expect the rest of the buffer */ pkcs7->stream->expected = (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + pkcs7->stream->length; } @@ -5137,6 +5170,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); if (pkcs7->stream->flagOne) { pkiMsg2 = pkiMsg; + + /* check if using internal stream buffer and should adjust sz */ + if (pkiMsg != in && pkcs7->stream->length > 0) { + pkiMsg2Sz = pkcs7->stream->length; + } } /* restore content */ @@ -8308,18 +8346,14 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, case WC_PKCS7_DECRYPT_KTRI_2: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, - &pkiMsg, idx)) != 0) { + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, idx)) != 0) { return ret; } - rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, - in, inSz); - if (rc < 0) { - ret = (int)rc; - break; + if (in != pkiMsg) { + pkiMsgSz = pkcs7->stream->length; } - pkiMsgSz = (word32)rc; wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); @@ -8405,6 +8439,9 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + if (KEYID_SIZE > pkiMsgSz - (*idx)) + return BUFFER_E; + /* if we found correct recipient, SKID will match */ if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, KEYID_SIZE) == 0) { @@ -11371,6 +11408,10 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, ret = ASN_PARSE_E; } + if (ret == 0) { + pkcs7->contentOID = contentType; + } + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { ret = ASN_PARSE_E; diff --git a/wolfcrypt/src/poly1305.c b/wolfcrypt/src/poly1305.c index 4fde6be95..1bf0013dd 100644 --- a/wolfcrypt/src/poly1305.c +++ b/wolfcrypt/src/poly1305.c @@ -1,6 +1,6 @@ /* poly1305.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -109,7 +109,7 @@ static word32 cpu_flags_set = 0; #elif defined(__GNUC__) #if defined(__SIZEOF_INT128__) - typedef unsigned __int128 word128; + PEDANTIC_EXTENSION typedef unsigned __int128 word128; #else typedef unsigned word128 __attribute__((mode(TI))); #endif @@ -723,8 +723,10 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) poly1305_calc_powers_avx2(ctx); poly1305_blocks_avx2(ctx, ctx->buffer, sizeof(ctx->buffer)); ctx->leftover = 0; - } else + } + else { SAVE_VECTOR_REGISTERS(); + } /* process full blocks */ if (bytes >= sizeof(ctx->buffer)) { @@ -804,8 +806,8 @@ int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad) XMEMSET(padding, 0, sizeof(padding)); /* Pad length to 16 bytes */ - paddingLen = -(int)lenToPad & (WC_POLY1305_PAD_SZ - 1); - if (paddingLen > 0) { + paddingLen = (-(int)lenToPad) & (WC_POLY1305_PAD_SZ - 1); + if ((paddingLen > 0) && (paddingLen < WC_POLY1305_PAD_SZ)) { ret = wc_Poly1305Update(ctx, padding, paddingLen); } return ret; @@ -870,8 +872,8 @@ int wc_Poly1305_EncodeSizes64(Poly1305* ctx, word64 aadSz, word64 dataSz) tagSz : Size of input tag buffer (must be at least WC_POLY1305_MAC_SZ(16)) */ -int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, - byte* input, word32 sz, byte* tag, word32 tagSz) +int wc_Poly1305_MAC(Poly1305* ctx, const byte* additional, word32 addSz, + const byte* input, word32 sz, byte* tag, word32 tagSz) { int ret; diff --git a/wolfcrypt/src/poly1305_asm.S b/wolfcrypt/src/poly1305_asm.S index 126e59aca..7b2265fe6 100644 --- a/wolfcrypt/src/poly1305_asm.S +++ b/wolfcrypt/src/poly1305_asm.S @@ -1,6 +1,6 @@ /* poly1305_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/Espressif/esp32_aes.c b/wolfcrypt/src/port/Espressif/esp32_aes.c index f2fb8a5be..cce7a3016 100644 --- a/wolfcrypt/src/port/Espressif/esp32_aes.c +++ b/wolfcrypt/src/port/Espressif/esp32_aes.c @@ -1,6 +1,6 @@ /* esp32_aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/Espressif/esp32_mp.c b/wolfcrypt/src/port/Espressif/esp32_mp.c index 2174089b1..2fb719d6e 100644 --- a/wolfcrypt/src/port/Espressif/esp32_mp.c +++ b/wolfcrypt/src/port/Espressif/esp32_mp.c @@ -1,6 +1,6 @@ /* esp32_mp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -94,6 +94,7 @@ static int esp_mp_hw_lock() /* Enable RSA hardware */ periph_module_enable(PERIPH_RSA_MODULE); + DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); return ret; } /* diff --git a/wolfcrypt/src/port/Espressif/esp32_sha.c b/wolfcrypt/src/port/Espressif/esp32_sha.c index 94789cd64..2f8f38fd9 100644 --- a/wolfcrypt/src/port/Espressif/esp32_sha.c +++ b/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -1,6 +1,6 @@ /* esp32_sha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/Espressif/esp32_util.c b/wolfcrypt/src/port/Espressif/esp32_util.c index b501b5ea6..d73cd2fe8 100644 --- a/wolfcrypt/src/port/Espressif/esp32_util.c +++ b/wolfcrypt/src/port/Espressif/esp32_util.c @@ -1,6 +1,6 @@ /* esp32_util.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c b/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c index ce04ff54f..e4fd7f93d 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c @@ -1,6 +1,6 @@ /* renesas_tsip_aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c b/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c index b12d8eee9..c485eecd5 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c @@ -1,6 +1,6 @@ /* renesas_tsip_sha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_util.c b/wolfcrypt/src/port/Renesas/renesas_tsip_util.c index 1ed66e6bb..6c4a93622 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_util.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_util.c @@ -1,6 +1,6 @@ /* renesas_tsip_util.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/af_alg/afalg_aes.c b/wolfcrypt/src/port/af_alg/afalg_aes.c index 2d1d41a6a..a5dbd79c4 100644 --- a/wolfcrypt/src/port/af_alg/afalg_aes.c +++ b/wolfcrypt/src/port/af_alg/afalg_aes.c @@ -1,6 +1,6 @@ /* afalg_aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -565,7 +565,6 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, authTagSz); if (ret != 0) { - perror("set tag"); WOLFSSL_MSG("Unable to set AF_ALG tag size "); return WC_AFALG_SOCK_E; } diff --git a/wolfcrypt/src/port/af_alg/afalg_hash.c b/wolfcrypt/src/port/af_alg/afalg_hash.c index 41e57bc80..6b2069a34 100644 --- a/wolfcrypt/src/port/af_alg/afalg_hash.c +++ b/wolfcrypt/src/port/af_alg/afalg_hash.c @@ -1,6 +1,6 @@ /* afalg_hash.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -44,11 +44,11 @@ static void AfalgHashFree(wolfssl_AFALG_Hash* hash) return; if (hash->alFd > 0) { - close(hash->alFd); + (void)close(hash->alFd); hash->alFd = -1; /* avoid possible double close on socket */ } if (hash->rdFd > 0) { - close(hash->rdFd); + (void)close(hash->rdFd); hash->rdFd = -1; /* avoid possible double close on socket */ } @@ -86,7 +86,7 @@ static int AfalgHashInit(wolfssl_AFALG_Hash* hash, void* heap, int devId, hash->rdFd = wc_Afalg_CreateRead(hash->alFd, WC_TYPE_HASH, type); if (hash->rdFd < 0) { - close(hash->alFd); + (void)close(hash->alFd); return WC_AFALG_SOCK_E; } diff --git a/wolfcrypt/src/port/af_alg/wc_afalg.c b/wolfcrypt/src/port/af_alg/wc_afalg.c index 0a91b5180..5e0ad7e39 100644 --- a/wolfcrypt/src/port/af_alg/wc_afalg.c +++ b/wolfcrypt/src/port/af_alg/wc_afalg.c @@ -1,6 +1,6 @@ /* wc_afalg.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/arm/armv8-32-curve25519.S b/wolfcrypt/src/port/arm/armv8-32-curve25519.S index 1fcf6f869..26fe61855 100644 --- a/wolfcrypt/src/port/arm/armv8-32-curve25519.S +++ b/wolfcrypt/src/port/arm/armv8-32-curve25519.S @@ -1,6 +1,6 @@ /* armv8-32-curve25519 * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,7 +23,7 @@ * cd ../scripts * ruby ./x25519/x25519.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.S */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(HAVE_CURVE25519) #ifndef __aarch64__ .text .align 2 @@ -6008,7 +6008,7 @@ fe_ge_sub: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} .size fe_ge_sub,.-fe_ge_sub #endif /* !__aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && HAVE_CURVE25519 */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/wolfcrypt/src/port/arm/armv8-32-curve25519.c b/wolfcrypt/src/port/arm/armv8-32-curve25519.c index c2c73f3c3..ddc08f644 100644 --- a/wolfcrypt/src/port/arm/armv8-32-curve25519.c +++ b/wolfcrypt/src/port/arm/armv8-32-curve25519.c @@ -1,6 +1,6 @@ /* armv8-32-curve25519 * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,7 +23,7 @@ * cd ../scripts * ruby ./x25519/x25519.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.c */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(HAVE_CURVE25519) #ifndef __aarch64__ #include #ifdef HAVE_CONFIG_H @@ -5573,4 +5573,4 @@ void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz } #endif /* !__aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && HAVE_CURVE25519 */ diff --git a/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S b/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S index 685f87cc7..c42cf63b1 100644 --- a/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +++ b/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S @@ -1,6 +1,6 @@ /* armv8-32-sha512-asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,7 +23,7 @@ * cd ../scripts * ruby ./sha2/sha512.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(WOLFSSL_SHA512) #ifndef __aarch64__ #ifdef WOLFSSL_ARMASM_NO_NEON .text @@ -5331,7 +5331,7 @@ L_sha512_len_neon_start: .size Transform_Sha512_Len,.-Transform_Sha512_Len #endif /* !WOLFSSL_ARMASM_NO_NEON */ #endif /* !__aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && WOLFSSL_SHA512 */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c b/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c index 6786d30b0..53e5b9743 100644 --- a/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c +++ b/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c @@ -1,6 +1,6 @@ /* armv8-32-sha512-asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,7 +23,7 @@ * cd ../scripts * ruby ./sha2/sha512.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(WOLFSSL_SHA512) #ifndef __aarch64__ #include #ifdef HAVE_CONFIG_H @@ -4776,4 +4776,4 @@ void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) #endif /* !WOLFSSL_ARMASM_NO_NEON */ #endif /* !__aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index 021ee7963..bdb075eb0 100644 --- a/wolfcrypt/src/port/arm/armv8-aes.c +++ b/wolfcrypt/src/port/arm/armv8-aes.c @@ -1,6 +1,6 @@ /* armv8-aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -461,10 +461,20 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { word32 numBlocks = sz / AES_BLOCK_SIZE; - if (aes == NULL || out == NULL || (in == NULL && sz > 0)) { + if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; } + if (sz == 0) { + return 0; + } + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + /* do as many block size ops as possible */ if (numBlocks > 0) { word32* key = aes->key; @@ -665,11 +675,22 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { word32 numBlocks = sz / AES_BLOCK_SIZE; - if (aes == NULL || out == NULL || (in == NULL && sz > 0) - || sz % AES_BLOCK_SIZE != 0) { + if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; } + if (sz == 0) { + return 0; + } + + if (sz % AES_BLOCK_SIZE) { +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + return BAD_LENGTH_E; +#else + return BAD_FUNC_ARG; +#endif + } + /* do as many block size ops as possible */ if (numBlocks > 0) { word32* key = aes->key; @@ -3043,10 +3064,20 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, { word32 numBlocks = sz / AES_BLOCK_SIZE; - if (aes == NULL || out == NULL || (in == NULL && sz > 0)) { + if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; } + if (sz == 0) { + return 0; + } + +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + if (sz % AES_BLOCK_SIZE) { + return BAD_LENGTH_E; + } +#endif + /* do as many block size ops as possible */ if (numBlocks > 0) { word32* keyPt = aes->key; @@ -3275,11 +3306,22 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, { word32 numBlocks = sz / AES_BLOCK_SIZE; - if (aes == NULL || out == NULL || (in == NULL && sz > 0) - || sz % AES_BLOCK_SIZE != 0) { + if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; } + if (sz == 0) { + return 0; + } + + if (sz % AES_BLOCK_SIZE) { +#ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS + return BAD_LENGTH_E; +#else + return BAD_FUNC_ARG; +#endif + } + /* do as many block size ops as possible */ if (numBlocks > 0) { word32* keyPt = aes->key; diff --git a/wolfcrypt/src/port/arm/armv8-chacha.c b/wolfcrypt/src/port/arm/armv8-chacha.c index 11473d47e..c6af98a67 100644 --- a/wolfcrypt/src/port/arm/armv8-chacha.c +++ b/wolfcrypt/src/port/arm/armv8-chacha.c @@ -1,6 +1,6 @@ /* armv8-chacha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -17,7 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - * */ /* The paper NEON crypto by Daniel J. Bernstein and Peter Schwabe was used to optimize for ARM diff --git a/wolfcrypt/src/port/arm/armv8-curve25519.S b/wolfcrypt/src/port/arm/armv8-curve25519.S index e8da5267f..d07210a68 100644 --- a/wolfcrypt/src/port/arm/armv8-curve25519.S +++ b/wolfcrypt/src/port/arm/armv8-curve25519.S @@ -1,6 +1,6 @@ /* armv8-curve25519 * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,7 +28,7 @@ * cd ../scripts * ruby ./x25519/x25519.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(HAVE_CURVE25519) #ifdef __aarch64__ #ifndef __APPLE__ .text @@ -860,6 +860,9 @@ _fe_invert: str x0, [x29, #144] str x1, [x29, #152] add x0, x29, #16 +#ifndef NDEBUG + ldr x1, [x29, #152] +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else @@ -872,12 +875,18 @@ _fe_invert: #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ ldr x1, [x29, #152] add x2, x29, #48 #ifndef __APPLE__ @@ -894,6 +903,9 @@ _fe_invert: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #16 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else @@ -908,12 +920,18 @@ _fe_invert: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x20, #4 + mov x20, #3 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_invert1: #ifndef __APPLE__ @@ -921,10 +939,12 @@ L_fe_invert1: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert1 + subs x20, x20, #1 + bcs L_fe_invert1 add x0, x29, #48 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul @@ -938,7 +958,10 @@ L_fe_invert1: #else bl _fe_sq #endif /* __APPLE__ */ - mov x20, #9 + mov x20, #8 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_invert2: #ifndef __APPLE__ @@ -946,9 +969,14 @@ L_fe_invert2: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert2 + subs x20, x20, #1 + bcs L_fe_invert2 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul @@ -956,12 +984,18 @@ L_fe_invert2: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x20, #19 + mov x20, #18 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_fe_invert3: #ifndef __APPLE__ @@ -969,17 +1003,22 @@ L_fe_invert3: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert3 + subs x20, x20, #1 + bcs L_fe_invert3 add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x20, #10 + mov x20, #9 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_invert4: #ifndef __APPLE__ @@ -987,10 +1026,12 @@ L_fe_invert4: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert4 + subs x20, x20, #1 + bcs L_fe_invert4 add x0, x29, #48 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul @@ -1004,7 +1045,10 @@ L_fe_invert4: #else bl _fe_sq #endif /* __APPLE__ */ - mov x20, #49 + mov x20, #48 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_invert5: #ifndef __APPLE__ @@ -1012,9 +1056,14 @@ L_fe_invert5: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert5 + subs x20, x20, #1 + bcs L_fe_invert5 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul @@ -1022,12 +1071,18 @@ L_fe_invert5: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x20, #0x63 + mov x20, #0x62 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_fe_invert6: #ifndef __APPLE__ @@ -1035,17 +1090,22 @@ L_fe_invert6: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert6 + subs x20, x20, #1 + bcs L_fe_invert6 add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x20, #50 + mov x20, #49 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_invert7: #ifndef __APPLE__ @@ -1053,17 +1113,22 @@ L_fe_invert7: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert7 + subs x20, x20, #1 + bcs L_fe_invert7 add x0, x29, #48 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x20, #5 + mov x20, #4 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 L_fe_invert8: #ifndef __APPLE__ @@ -1071,10 +1136,12 @@ L_fe_invert8: #else bl _fe_sq #endif /* __APPLE__ */ - sub x20, x20, #1 - cmp x20, #0 - bne L_fe_invert8 + subs x20, x20, #1 + bcs L_fe_invert8 ldr x0, [x29, #144] +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ add x2, x29, #16 #ifndef __APPLE__ bl fe_mul @@ -2428,12 +2495,18 @@ L_curve25519_bits: #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #16 add x2, x29, #0x50 #ifndef __APPLE__ @@ -2450,6 +2523,9 @@ L_curve25519_bits: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else @@ -2464,12 +2540,18 @@ L_curve25519_bits: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x70 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x24, #4 + mov x24, #3 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_curve25519_inv_1: #ifndef __APPLE__ @@ -2477,10 +2559,12 @@ L_curve25519_inv_1: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_1 + subs x24, x24, #1 + bcs L_curve25519_inv_1 add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul @@ -2494,7 +2578,10 @@ L_curve25519_inv_1: #else bl _fe_sq #endif /* __APPLE__ */ - mov x24, #9 + mov x24, #8 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_curve25519_inv_2: #ifndef __APPLE__ @@ -2502,9 +2589,14 @@ L_curve25519_inv_2: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_2 + subs x24, x24, #1 + bcs L_curve25519_inv_2 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul @@ -2512,12 +2604,18 @@ L_curve25519_inv_2: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x90 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x24, #19 + mov x24, #18 +#ifndef NDEBUG + add x0, x29, #0x90 +#endif /* !NDEBUG */ add x1, x29, #0x90 L_curve25519_inv_3: #ifndef __APPLE__ @@ -2525,17 +2623,22 @@ L_curve25519_inv_3: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_3 + subs x24, x24, #1 + bcs L_curve25519_inv_3 add x0, x29, #0x70 +#ifndef NDEBUG + add x1, x29, #0x90 +#endif /* !NDEBUG */ add x2, x29, #0x70 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x24, #10 + mov x24, #9 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_curve25519_inv_4: #ifndef __APPLE__ @@ -2543,10 +2646,12 @@ L_curve25519_inv_4: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_4 + subs x24, x24, #1 + bcs L_curve25519_inv_4 add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul @@ -2560,7 +2665,10 @@ L_curve25519_inv_4: #else bl _fe_sq #endif /* __APPLE__ */ - mov x24, #49 + mov x24, #48 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_curve25519_inv_5: #ifndef __APPLE__ @@ -2568,9 +2676,14 @@ L_curve25519_inv_5: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_5 + subs x24, x24, #1 + bcs L_curve25519_inv_5 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul @@ -2578,12 +2691,18 @@ L_curve25519_inv_5: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x90 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x24, #0x63 + mov x24, #0x62 +#ifndef NDEBUG + add x0, x29, #0x90 +#endif /* !NDEBUG */ add x1, x29, #0x90 L_curve25519_inv_6: #ifndef __APPLE__ @@ -2591,17 +2710,22 @@ L_curve25519_inv_6: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_6 + subs x24, x24, #1 + bcs L_curve25519_inv_6 add x0, x29, #0x70 +#ifndef NDEBUG + add x1, x29, #0x90 +#endif /* !NDEBUG */ add x2, x29, #0x70 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x24, #50 + mov x24, #49 +#ifndef NDEBUG + add x0, x29, #0x70 +#endif /* !NDEBUG */ add x1, x29, #0x70 L_curve25519_inv_7: #ifndef __APPLE__ @@ -2609,17 +2733,22 @@ L_curve25519_inv_7: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_7 + subs x24, x24, #1 + bcs L_curve25519_inv_7 add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #0x70 +#endif /* !NDEBUG */ add x2, x29, #0x50 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x24, #5 + mov x24, #4 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_curve25519_inv_8: #ifndef __APPLE__ @@ -2627,10 +2756,12 @@ L_curve25519_inv_8: #else bl _fe_sq #endif /* __APPLE__ */ - sub x24, x24, #1 - cmp x24, #0 - bne L_curve25519_inv_8 + subs x24, x24, #1 + bcs L_curve25519_inv_8 add x0, x29, #16 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul @@ -2805,11 +2936,14 @@ _fe_pow22523: #endif /* __APPLE__ */ stp x29, x30, [sp, #-144]! add x29, sp, #0 - str x21, [x29, #136] + str x23, [x29, #136] # pow22523 str x0, [x29, #112] str x1, [x29, #120] add x0, x29, #16 +#ifndef NDEBUG + ldr x1, [x29, #120] +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else @@ -2822,12 +2956,18 @@ _fe_pow22523: #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ ldr x1, [x29, #120] add x2, x29, #48 #ifndef __APPLE__ @@ -2843,11 +2983,20 @@ _fe_pow22523: #else bl _fe_mul #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #16 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #16 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ +#ifndef NDEBUG + add x0, x29, #16 +#endif /* !NDEBUG */ add x1, x29, #48 add x2, x29, #16 #ifndef __APPLE__ @@ -2862,7 +3011,10 @@ _fe_pow22523: #else bl _fe_sq #endif /* __APPLE__ */ - mov x21, #4 + mov x23, #3 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 L_fe_pow22523_1: #ifndef __APPLE__ @@ -2870,10 +3022,12 @@ L_fe_pow22523_1: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_1 + subs x23, x23, #1 + bcs L_fe_pow22523_1 add x0, x29, #16 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ add x2, x29, #16 #ifndef __APPLE__ bl fe_mul @@ -2887,7 +3041,10 @@ L_fe_pow22523_1: #else bl _fe_sq #endif /* __APPLE__ */ - mov x21, #9 + mov x23, #8 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 L_fe_pow22523_2: #ifndef __APPLE__ @@ -2895,9 +3052,14 @@ L_fe_pow22523_2: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_2 + subs x23, x23, #1 + bcs L_fe_pow22523_2 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ add x2, x29, #16 #ifndef __APPLE__ bl fe_mul @@ -2905,12 +3067,18 @@ L_fe_pow22523_2: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x21, #19 + mov x23, #18 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_pow22523_3: #ifndef __APPLE__ @@ -2918,17 +3086,22 @@ L_fe_pow22523_3: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_3 + subs x23, x23, #1 + bcs L_fe_pow22523_3 add x0, x29, #48 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x21, #10 + mov x23, #9 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 L_fe_pow22523_4: #ifndef __APPLE__ @@ -2936,10 +3109,12 @@ L_fe_pow22523_4: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_4 + subs x23, x23, #1 + bcs L_fe_pow22523_4 add x0, x29, #16 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ add x2, x29, #16 #ifndef __APPLE__ bl fe_mul @@ -2953,7 +3128,10 @@ L_fe_pow22523_4: #else bl _fe_sq #endif /* __APPLE__ */ - mov x21, #49 + mov x23, #48 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 L_fe_pow22523_5: #ifndef __APPLE__ @@ -2961,9 +3139,14 @@ L_fe_pow22523_5: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_5 + subs x23, x23, #1 + bcs L_fe_pow22523_5 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ add x2, x29, #16 #ifndef __APPLE__ bl fe_mul @@ -2971,12 +3154,18 @@ L_fe_pow22523_5: bl _fe_mul #endif /* __APPLE__ */ add x0, x29, #0x50 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ #ifndef __APPLE__ bl fe_sq #else bl _fe_sq #endif /* __APPLE__ */ - mov x21, #0x63 + mov x23, #0x62 +#ifndef NDEBUG + add x0, x29, #0x50 +#endif /* !NDEBUG */ add x1, x29, #0x50 L_fe_pow22523_6: #ifndef __APPLE__ @@ -2984,17 +3173,22 @@ L_fe_pow22523_6: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_6 + subs x23, x23, #1 + bcs L_fe_pow22523_6 add x0, x29, #48 +#ifndef NDEBUG + add x1, x29, #0x50 +#endif /* !NDEBUG */ add x2, x29, #48 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x21, #50 + mov x23, #49 +#ifndef NDEBUG + add x0, x29, #48 +#endif /* !NDEBUG */ add x1, x29, #48 L_fe_pow22523_7: #ifndef __APPLE__ @@ -3002,17 +3196,22 @@ L_fe_pow22523_7: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_7 + subs x23, x23, #1 + bcs L_fe_pow22523_7 add x0, x29, #16 +#ifndef NDEBUG + add x1, x29, #48 +#endif /* !NDEBUG */ add x2, x29, #16 #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - mov x21, #2 + mov x23, #1 +#ifndef NDEBUG + add x0, x29, #16 +#endif /* !NDEBUG */ add x1, x29, #16 L_fe_pow22523_8: #ifndef __APPLE__ @@ -3020,17 +3219,19 @@ L_fe_pow22523_8: #else bl _fe_sq #endif /* __APPLE__ */ - sub x21, x21, #1 - cmp x21, #0 - bne L_fe_pow22523_8 + subs x23, x23, #1 + bcs L_fe_pow22523_8 ldr x0, [x29, #112] +#ifndef NDEBUG + add x1, x29, #16 +#endif /* !NDEBUG */ ldr x2, [x29, #120] #ifndef __APPLE__ bl fe_mul #else bl _fe_mul #endif /* __APPLE__ */ - ldr x21, [x29, #136] + ldr x23, [x29, #136] ldp x29, x30, [sp], #0x90 ret #ifndef __APPLE__ @@ -7271,7 +7472,7 @@ _fe_ge_sub: .size fe_ge_sub,.-fe_ge_sub #endif /* __APPLE__ */ #endif /* __aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && HAVE_CURVE25519 */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/wolfcrypt/src/port/arm/armv8-curve25519.c b/wolfcrypt/src/port/arm/armv8-curve25519.c index a72ae8fbd..81352c705 100644 --- a/wolfcrypt/src/port/arm/armv8-curve25519.c +++ b/wolfcrypt/src/port/arm/armv8-curve25519.c @@ -1,6 +1,6 @@ /* armv8-curve25519 * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,17 +28,14 @@ * cd ../scripts * ruby ./x25519/x25519.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.c */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(HAVE_CURVE25519) #ifdef __aarch64__ #include void fe_init() { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" "\n\t" - "ldp x29, x30, [sp], #16\n\t" : : : "memory" @@ -48,14 +45,11 @@ void fe_init() void fe_frombytes(fe out, const unsigned char* in) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" "ldp x2, x3, [%x[in]]\n\t" "ldp x4, x5, [%x[in], #16]\n\t" "and x5, x5, #0x7fffffffffffffff\n\t" "stp x2, x3, [%x[out]]\n\t" "stp x4, x5, [%x[out], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [out] "+r" (out), [in] "+r" (in) : : "memory", "x2", "x3", "x4", "x5", "x6" @@ -65,8 +59,6 @@ void fe_frombytes(fe out, const unsigned char* in) void fe_tobytes(unsigned char* out, const fe n) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" "mov x7, #19\n\t" "ldp x2, x3, [%x[n]]\n\t" "ldp x4, x5, [%x[n], #16]\n\t" @@ -82,7 +74,6 @@ void fe_tobytes(unsigned char* out, const fe n) "and x5, x5, #0x7fffffffffffffff\n\t" "stp x2, x3, [%x[out]]\n\t" "stp x4, x5, [%x[out], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [out] "+r" (out), [n] "+r" (n) : : "memory", "x2", "x3", "x4", "x5", "x6", "x7" @@ -92,13 +83,10 @@ void fe_tobytes(unsigned char* out, const fe n) void fe_1(fe n) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Set one */ "mov x1, #1\n\t" "stp x1, xzr, [%x[n]]\n\t" "stp xzr, xzr, [%x[n], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [n] "+r" (n) : : "memory", "x1" @@ -108,12 +96,9 @@ void fe_1(fe n) void fe_0(fe n) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Set zero */ "stp xzr, xzr, [%x[n]]\n\t" "stp xzr, xzr, [%x[n], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [n] "+r" (n) : : "memory" @@ -123,14 +108,11 @@ void fe_0(fe n) void fe_copy(fe r, const fe a) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Copy */ "ldp x2, x3, [%x[a]]\n\t" "ldp x4, x5, [%x[a], #16]\n\t" "stp x2, x3, [%x[r]]\n\t" "stp x4, x5, [%x[r], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [r] "+r" (r), [a] "+r" (a) : : "memory", "x2", "x3", "x4", "x5" @@ -140,8 +122,6 @@ void fe_copy(fe r, const fe a) void fe_sub(fe r, const fe a, const fe b) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Sub */ "ldp x3, x4, [%x[a]]\n\t" "ldp x5, x6, [%x[a], #16]\n\t" @@ -163,7 +143,6 @@ void fe_sub(fe r, const fe a, const fe b) "adc x6, x6, x13\n\t" "stp x3, x4, [%x[r]]\n\t" "stp x5, x6, [%x[r], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13" @@ -173,8 +152,6 @@ void fe_sub(fe r, const fe a, const fe b) void fe_add(fe r, const fe a, const fe b) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Add */ "ldp x3, x4, [%x[a]]\n\t" "ldp x5, x6, [%x[a], #16]\n\t" @@ -196,7 +173,6 @@ void fe_add(fe r, const fe a, const fe b) "sbc x6, x6, x13\n\t" "stp x3, x4, [%x[r]]\n\t" "stp x5, x6, [%x[r], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13" @@ -206,8 +182,6 @@ void fe_add(fe r, const fe a, const fe b) void fe_neg(fe r, const fe a) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" "ldp x2, x3, [%x[a]]\n\t" "ldp x4, x5, [%x[a], #16]\n\t" "mov x6, #-19\n\t" @@ -220,7 +194,6 @@ void fe_neg(fe r, const fe a) "sbc x9, x9, x5\n\t" "stp x6, x7, [%x[r]]\n\t" "stp x8, x9, [%x[r], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [r] "+r" (r), [a] "+r" (a) : : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" @@ -230,8 +203,6 @@ void fe_neg(fe r, const fe a) int fe_isnonzero(const fe a) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" "mov x6, #19\n\t" "ldp x1, x2, [%x[a]]\n\t" "ldp x3, x4, [%x[a], #16]\n\t" @@ -248,7 +219,6 @@ int fe_isnonzero(const fe a) "orr %x[a], x1, x2\n\t" "orr x3, x3, x4\n\t" "orr %x[a], %x[a], x3\n\t" - "ldp x29, x30, [sp], #16\n\t" : [a] "+r" (a) : : "memory", "x1", "x2", "x3", "x4", "x5", "x6" @@ -259,8 +229,6 @@ int fe_isnonzero(const fe a) int fe_isnegative(const fe a) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" "mov x6, #19\n\t" "ldp x1, x2, [%x[a]]\n\t" "ldp x3, x4, [%x[a], #16]\n\t" @@ -270,7 +238,6 @@ int fe_isnegative(const fe a) "adc x5, x4, xzr\n\t" "and %x[a], x1, #1\n\t" "eor %x[a], %x[a], x5, lsr 63\n\t" - "ldp x29, x30, [sp], #16\n\t" : [a] "+r" (a) : : "memory", "x1", "x2", "x3", "x4", "x5", "x6" @@ -495,8 +462,6 @@ void fe_cmov_table(fe* r, fe* base, signed char b) void fe_mul(fe r, const fe a, const fe b) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Multiply */ "ldp x14, x15, [%x[a]]\n\t" "ldp x16, x17, [%x[a], #16]\n\t" @@ -637,7 +602,6 @@ void fe_mul(fe r, const fe a, const fe b) /* Store */ "stp x6, x7, [%x[r]]\n\t" "stp x8, x9, [%x[r], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22" @@ -647,8 +611,6 @@ void fe_mul(fe r, const fe a, const fe b) void fe_sq(fe r, const fe a) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" /* Square */ "ldp x13, x14, [%x[a]]\n\t" "ldp x15, x16, [%x[a], #16]\n\t" @@ -755,7 +717,6 @@ void fe_sq(fe r, const fe a) /* Store */ "stp x5, x6, [%x[r]]\n\t" "stp x7, x8, [%x[r], #16]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [r] "+r" (r), [a] "+r" (a) : : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16" @@ -771,6 +732,9 @@ void fe_invert(fe r, const fe a) "str %x[r], [x29, #144]\n\t" "str %x[a], [x29, #152]\n\t" "add x0, x29, #16\n\t" +#ifndef NDEBUG + "ldr x1, [x29, #152]\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else @@ -783,12 +747,18 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "ldr x1, [x29, #152]\n\t" "add x2, x29, #48\n\t" #ifndef __APPLE__ @@ -805,6 +775,9 @@ void fe_invert(fe r, const fe a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #16\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else @@ -819,12 +792,18 @@ void fe_invert(fe r, const fe a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x20, #4\n\t" + "mov x20, #3\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_invert1_%=: \n\t" @@ -833,10 +812,12 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert1_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert1_%=\n\t" "add x0, x29, #48\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -850,7 +831,10 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x20, #9\n\t" + "mov x20, #8\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_invert2_%=: \n\t" @@ -859,9 +843,14 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert2_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert2_%=\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -869,12 +858,18 @@ void fe_invert(fe r, const fe a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x20, #19\n\t" + "mov x20, #18\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_fe_invert3_%=: \n\t" @@ -883,17 +878,22 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert3_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert3_%=\n\t" "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x20, #10\n\t" + "mov x20, #9\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_invert4_%=: \n\t" @@ -902,10 +902,12 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert4_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert4_%=\n\t" "add x0, x29, #48\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -919,7 +921,10 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x20, #49\n\t" + "mov x20, #48\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_invert5_%=: \n\t" @@ -928,9 +933,14 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert5_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert5_%=\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -938,12 +948,18 @@ void fe_invert(fe r, const fe a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x20, #0x63\n\t" + "mov x20, #0x62\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_fe_invert6_%=: \n\t" @@ -952,17 +968,22 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert6_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert6_%=\n\t" "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x20, #50\n\t" + "mov x20, #49\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_invert7_%=: \n\t" @@ -971,17 +992,22 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert7_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert7_%=\n\t" "add x0, x29, #48\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x20, #5\n\t" + "mov x20, #4\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "\n" "L_fe_invert8_%=: \n\t" @@ -990,10 +1016,12 @@ void fe_invert(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x20, x20, #1\n\t" - "cmp x20, #0\n\t" - "bne L_fe_invert8_%=\n\t" + "subs x20, x20, #1\n\t" + "bcs L_fe_invert8_%=\n\t" "ldr x0, [x29, #144]\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ "add x2, x29, #16\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -1003,7 +1031,7 @@ void fe_invert(fe r, const fe a) "ldp x29, x30, [sp], #0xa0\n\t" : [r] "+r" (r), [a] "+r" (a) : - : "memory", "x20" + : "memory", "x2", "x20" ); } @@ -2334,12 +2362,18 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #16\n\t" "add x2, x29, #0x50\n\t" #ifndef __APPLE__ @@ -2356,6 +2390,9 @@ int curve25519(byte* r, const byte* n, const byte* a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else @@ -2370,12 +2407,18 @@ int curve25519(byte* r, const byte* n, const byte* a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x70\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x24, #4\n\t" + "mov x24, #3\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_1_%=: \n\t" @@ -2384,10 +2427,12 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_1_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_1_%=\n\t" "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2401,7 +2446,10 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x24, #9\n\t" + "mov x24, #8\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_2_%=: \n\t" @@ -2410,9 +2458,14 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_2_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_2_%=\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2420,12 +2473,18 @@ int curve25519(byte* r, const byte* n, const byte* a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x90\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x24, #19\n\t" + "mov x24, #18\n\t" +#ifndef NDEBUG + "add x0, x29, #0x90\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x90\n\t" "\n" "L_curve25519_inv_3_%=: \n\t" @@ -2434,17 +2493,22 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_3_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_3_%=\n\t" "add x0, x29, #0x70\n\t" +#ifndef NDEBUG + "add x1, x29, #0x90\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x70\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x24, #10\n\t" + "mov x24, #9\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_4_%=: \n\t" @@ -2453,10 +2517,12 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_4_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_4_%=\n\t" "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2470,7 +2536,10 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x24, #49\n\t" + "mov x24, #48\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_5_%=: \n\t" @@ -2479,9 +2548,14 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_5_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_5_%=\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2489,12 +2563,18 @@ int curve25519(byte* r, const byte* n, const byte* a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x90\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x24, #0x63\n\t" + "mov x24, #0x62\n\t" +#ifndef NDEBUG + "add x0, x29, #0x90\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x90\n\t" "\n" "L_curve25519_inv_6_%=: \n\t" @@ -2503,17 +2583,22 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_6_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_6_%=\n\t" "add x0, x29, #0x70\n\t" +#ifndef NDEBUG + "add x1, x29, #0x90\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x70\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x24, #50\n\t" + "mov x24, #49\n\t" +#ifndef NDEBUG + "add x0, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x70\n\t" "\n" "L_curve25519_inv_7_%=: \n\t" @@ -2522,17 +2607,22 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_7_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_7_%=\n\t" "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #0x70\n\t" +#endif /* !NDEBUG */ "add x2, x29, #0x50\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x24, #5\n\t" + "mov x24, #4\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_curve25519_inv_8_%=: \n\t" @@ -2541,10 +2631,12 @@ int curve25519(byte* r, const byte* n, const byte* a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x24, x24, #1\n\t" - "cmp x24, #0\n\t" - "bne L_curve25519_inv_8_%=\n\t" + "subs x24, x24, #1\n\t" + "bcs L_curve25519_inv_8_%=\n\t" "add x0, x29, #16\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2710,6 +2802,9 @@ void fe_pow22523(fe r, const fe a) "str %x[r], [x29, #112]\n\t" "str %x[a], [x29, #120]\n\t" "add x0, x29, #16\n\t" +#ifndef NDEBUG + "ldr x1, [x29, #120]\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else @@ -2722,12 +2817,18 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "ldr x1, [x29, #120]\n\t" "add x2, x29, #48\n\t" #ifndef __APPLE__ @@ -2743,11 +2844,20 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #16\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #16\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ +#ifndef NDEBUG + "add x0, x29, #16\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "add x2, x29, #16\n\t" #ifndef __APPLE__ @@ -2762,7 +2872,10 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x21, #4\n\t" + "mov x23, #3\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_1_%=: \n\t" @@ -2771,10 +2884,12 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_1_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_1_%=\n\t" "add x0, x29, #16\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ "add x2, x29, #16\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2788,7 +2903,10 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x21, #9\n\t" + "mov x23, #8\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_2_%=: \n\t" @@ -2797,9 +2915,14 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_2_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_2_%=\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ "add x2, x29, #16\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2807,12 +2930,18 @@ void fe_pow22523(fe r, const fe a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x21, #19\n\t" + "mov x23, #18\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_pow22523_3_%=: \n\t" @@ -2821,17 +2950,22 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_3_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_3_%=\n\t" "add x0, x29, #48\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x21, #10\n\t" + "mov x23, #9\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_4_%=: \n\t" @@ -2840,10 +2974,12 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_4_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_4_%=\n\t" "add x0, x29, #16\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ "add x2, x29, #16\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2857,7 +2993,10 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x21, #49\n\t" + "mov x23, #48\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_5_%=: \n\t" @@ -2866,9 +3005,14 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_5_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_5_%=\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ "add x2, x29, #16\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2876,12 +3020,18 @@ void fe_pow22523(fe r, const fe a) "bl _fe_mul\n\t" #endif /* __APPLE__ */ "add x0, x29, #0x50\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ #ifndef __APPLE__ "bl fe_sq\n\t" #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "mov x21, #0x63\n\t" + "mov x23, #0x62\n\t" +#ifndef NDEBUG + "add x0, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x1, x29, #0x50\n\t" "\n" "L_fe_pow22523_6_%=: \n\t" @@ -2890,17 +3040,22 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_6_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_6_%=\n\t" "add x0, x29, #48\n\t" +#ifndef NDEBUG + "add x1, x29, #0x50\n\t" +#endif /* !NDEBUG */ "add x2, x29, #48\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x21, #50\n\t" + "mov x23, #49\n\t" +#ifndef NDEBUG + "add x0, x29, #48\n\t" +#endif /* !NDEBUG */ "add x1, x29, #48\n\t" "\n" "L_fe_pow22523_7_%=: \n\t" @@ -2909,17 +3064,22 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_7_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_7_%=\n\t" "add x0, x29, #16\n\t" +#ifndef NDEBUG + "add x1, x29, #48\n\t" +#endif /* !NDEBUG */ "add x2, x29, #16\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" #else "bl _fe_mul\n\t" #endif /* __APPLE__ */ - "mov x21, #2\n\t" + "mov x23, #1\n\t" +#ifndef NDEBUG + "add x0, x29, #16\n\t" +#endif /* !NDEBUG */ "add x1, x29, #16\n\t" "\n" "L_fe_pow22523_8_%=: \n\t" @@ -2928,10 +3088,12 @@ void fe_pow22523(fe r, const fe a) #else "bl _fe_sq\n\t" #endif /* __APPLE__ */ - "sub x21, x21, #1\n\t" - "cmp x21, #0\n\t" - "bne L_fe_pow22523_8_%=\n\t" + "subs x23, x23, #1\n\t" + "bcs L_fe_pow22523_8_%=\n\t" "ldr x0, [x29, #112]\n\t" +#ifndef NDEBUG + "add x1, x29, #16\n\t" +#endif /* !NDEBUG */ "ldr x2, [x29, #120]\n\t" #ifndef __APPLE__ "bl fe_mul\n\t" @@ -2941,7 +3103,7 @@ void fe_pow22523(fe r, const fe a) "ldp x29, x30, [sp], #0x80\n\t" : [r] "+r" (r), [a] "+r" (a) : - : "memory", "x21" + : "memory", "x2", "x23" ); } @@ -3391,7 +3553,7 @@ void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py, const fe pz, con void fe_ge_to_p3(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz, const fe pt) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-80]!\n\t" + "stp x29, x30, [sp, #-96]!\n\t" "add x29, sp, #0\n\t" "str %x[ry], [x29, #16]\n\t" "str %x[rz], [x29, #24]\n\t" @@ -3959,7 +4121,7 @@ void fe_ge_to_p3(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe /* Store */ "stp x3, x4, [x0]\n\t" "stp x5, x6, [x0, #16]\n\t" - "ldp x29, x30, [sp], #0x50\n\t" + "ldp x29, x30, [sp], #0x60\n\t" : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) : : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26" @@ -4513,8 +4675,11 @@ void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz, const fe pt, const fe qxy2d, const fe qyplusx, const fe qyminusx) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-80]!\n\t" + "stp x29, x30, [sp, #-112]!\n\t" "add x29, sp, #0\n\t" + "str %x[qyminusx], [sp, #104]\n\t" + "str %x[qyplusx], [sp, #96]\n\t" + "str %x[qxy2d], [sp, #88]\n\t" "str %x[rx], [x29, #16]\n\t" "str %x[ry], [x29, #24]\n\t" "str %x[rz], [x29, #32]\n\t" @@ -4560,7 +4725,7 @@ void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "adcs x10, x10, x28\n\t" "adc x11, x11, x26\n\t" "ldr x0, [x29, #32]\n\t" - "ldr x2, [x29, #168]\n\t" + "ldr x2, [sp, #96]\n\t" /* Multiply */ "ldp x21, x22, [x2]\n\t" "ldp x23, x24, [x2, #16]\n\t" @@ -4698,7 +4863,7 @@ void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "adc x15, x15, xzr\n\t" /* Store */ "ldr x0, [x29, #24]\n\t" - "ldr x1, [x29, #176]\n\t" + "ldr x1, [sp, #104]\n\t" /* Multiply */ "ldp x21, x22, [x1]\n\t" "ldp x23, x24, [x1, #16]\n\t" @@ -4872,7 +5037,7 @@ void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "stp x16, x17, [x1]\n\t" "stp x19, x20, [x1, #16]\n\t" "ldr x0, [x29, #40]\n\t" - "ldr x1, [x29, #160]\n\t" + "ldr x1, [sp, #88]\n\t" "ldr x3, [x29, #72]\n\t" /* Multiply */ "ldp x16, x17, [x1]\n\t" @@ -5066,21 +5231,21 @@ void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "stp x14, x15, [x0, #16]\n\t" "stp x16, x17, [x1]\n\t" "stp x19, x20, [x1, #16]\n\t" - "ldp x29, x30, [sp], #0x50\n\t" - : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + "ldp x29, x30, [sp], #0x70\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt), [qxy2d] "+r" (qxy2d), [qyplusx] "+r" (qyplusx), [qyminusx] "+r" (qyminusx) : - : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + : "memory", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - (void)qxy2d; - (void)qyplusx; - (void)qyminusx; } void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz, const fe pt, const fe qxy2d, const fe qyplusx, const fe qyminusx) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-80]!\n\t" + "stp x29, x30, [sp, #-112]!\n\t" "add x29, sp, #0\n\t" + "str %x[qyminusx], [sp, #104]\n\t" + "str %x[qyplusx], [sp, #96]\n\t" + "str %x[qxy2d], [sp, #88]\n\t" "str %x[rx], [x29, #16]\n\t" "str %x[ry], [x29, #24]\n\t" "str %x[rz], [x29, #32]\n\t" @@ -5126,7 +5291,7 @@ void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "adcs x10, x10, x28\n\t" "adc x11, x11, x26\n\t" "ldr x0, [x29, #32]\n\t" - "ldr x2, [x29, #176]\n\t" + "ldr x2, [sp, #104]\n\t" /* Multiply */ "ldp x21, x22, [x2]\n\t" "ldp x23, x24, [x2, #16]\n\t" @@ -5264,7 +5429,7 @@ void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "adc x15, x15, xzr\n\t" /* Store */ "ldr x0, [x29, #24]\n\t" - "ldr x1, [x29, #168]\n\t" + "ldr x1, [sp, #96]\n\t" /* Multiply */ "ldp x21, x22, [x1]\n\t" "ldp x23, x24, [x1, #16]\n\t" @@ -5438,7 +5603,7 @@ void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "stp x16, x17, [x1]\n\t" "stp x19, x20, [x1, #16]\n\t" "ldr x0, [x29, #40]\n\t" - "ldr x1, [x29, #160]\n\t" + "ldr x1, [sp, #88]\n\t" "ldr x3, [x29, #72]\n\t" /* Multiply */ "ldp x16, x17, [x1]\n\t" @@ -5632,21 +5797,22 @@ void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe p "stp x14, x15, [x1, #16]\n\t" "stp x16, x17, [x0]\n\t" "stp x19, x20, [x0, #16]\n\t" - "ldp x29, x30, [sp], #0x50\n\t" - : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + "ldp x29, x30, [sp], #0x70\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt), [qxy2d] "+r" (qxy2d), [qyplusx] "+r" (qyplusx), [qyminusx] "+r" (qyminusx) : - : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + : "memory", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - (void)qxy2d; - (void)qyplusx; - (void)qyminusx; } void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz, const fe pt, const fe qz, const fe qt2d, const fe qyplusx, const fe qyminusx) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-80]!\n\t" + "stp x29, x30, [sp, #-128]!\n\t" "add x29, sp, #0\n\t" + "str %x[qyminusx], [sp, #120]\n\t" + "str %x[qyplusx], [sp, #112]\n\t" + "str %x[qt2d], [sp, #104]\n\t" + "str %x[qz], [sp, #96]\n\t" "str %x[rx], [x29, #16]\n\t" "str %x[ry], [x29, #24]\n\t" "str %x[rz], [x29, #32]\n\t" @@ -5692,7 +5858,7 @@ void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "adcs x10, x10, x28\n\t" "adc x11, x11, x26\n\t" "ldr x0, [x29, #32]\n\t" - "ldr x2, [x29, #176]\n\t" + "ldr x2, [sp, #112]\n\t" /* Multiply */ "ldp x21, x22, [x2]\n\t" "ldp x23, x24, [x2, #16]\n\t" @@ -5830,7 +5996,7 @@ void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "adc x15, x15, xzr\n\t" /* Store */ "ldr x0, [x29, #24]\n\t" - "ldr x1, [x29, #184]\n\t" + "ldr x1, [sp, #120]\n\t" /* Multiply */ "ldp x21, x22, [x1]\n\t" "ldp x23, x24, [x1, #16]\n\t" @@ -6005,7 +6171,7 @@ void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "stp x19, x20, [x1, #16]\n\t" "ldr x0, [x29, #48]\n\t" "ldr x1, [x29, #64]\n\t" - "ldr x2, [x29, #160]\n\t" + "ldr x2, [sp, #96]\n\t" /* Multiply */ "ldp x12, x13, [x1]\n\t" "ldp x14, x15, [x1, #16]\n\t" @@ -6161,7 +6327,7 @@ void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "sbcs x6, x6, x28\n\t" "sbc x7, x7, x26\n\t" "ldr x0, [x29, #40]\n\t" - "ldr x1, [x29, #168]\n\t" + "ldr x1, [sp, #104]\n\t" "ldr x2, [x29, #72]\n\t" /* Multiply */ "ldp x16, x17, [x1]\n\t" @@ -6337,22 +6503,22 @@ void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "stp x14, x15, [x0, #16]\n\t" "stp x16, x17, [x1]\n\t" "stp x19, x20, [x1, #16]\n\t" - "ldp x29, x30, [sp], #0x50\n\t" - : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + "ldp x29, x30, [sp], #0x80\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt), [qz] "+r" (qz), [qt2d] "+r" (qt2d), [qyplusx] "+r" (qyplusx), [qyminusx] "+r" (qyminusx) : - : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + : "memory", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - (void)qz; - (void)qt2d; - (void)qyplusx; - (void)qyminusx; } void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz, const fe pt, const fe qz, const fe qt2d, const fe qyplusx, const fe qyminusx) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-80]!\n\t" + "stp x29, x30, [sp, #-128]!\n\t" "add x29, sp, #0\n\t" + "str %x[qyminusx], [sp, #120]\n\t" + "str %x[qyplusx], [sp, #112]\n\t" + "str %x[qt2d], [sp, #104]\n\t" + "str %x[qz], [sp, #96]\n\t" "str %x[rx], [x29, #16]\n\t" "str %x[ry], [x29, #24]\n\t" "str %x[rz], [x29, #32]\n\t" @@ -6398,7 +6564,7 @@ void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "adcs x10, x10, x28\n\t" "adc x11, x11, x26\n\t" "ldr x0, [x29, #32]\n\t" - "ldr x2, [x29, #184]\n\t" + "ldr x2, [sp, #120]\n\t" /* Multiply */ "ldp x21, x22, [x2]\n\t" "ldp x23, x24, [x2, #16]\n\t" @@ -6536,7 +6702,7 @@ void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "adc x15, x15, xzr\n\t" /* Store */ "ldr x0, [x29, #24]\n\t" - "ldr x1, [x29, #176]\n\t" + "ldr x1, [sp, #112]\n\t" /* Multiply */ "ldp x21, x22, [x1]\n\t" "ldp x23, x24, [x1, #16]\n\t" @@ -6711,7 +6877,7 @@ void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "stp x19, x20, [x1, #16]\n\t" "ldr x0, [x29, #48]\n\t" "ldr x1, [x29, #64]\n\t" - "ldr x2, [x29, #160]\n\t" + "ldr x2, [sp, #96]\n\t" /* Multiply */ "ldp x12, x13, [x1]\n\t" "ldp x14, x15, [x1, #16]\n\t" @@ -6867,7 +7033,7 @@ void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "sbcs x6, x6, x28\n\t" "sbc x7, x7, x26\n\t" "ldr x0, [x29, #40]\n\t" - "ldr x1, [x29, #168]\n\t" + "ldr x1, [sp, #104]\n\t" "ldr x2, [x29, #72]\n\t" /* Multiply */ "ldp x16, x17, [x1]\n\t" @@ -7043,16 +7209,12 @@ void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz "stp x14, x15, [x0, #16]\n\t" "stp x16, x17, [x1]\n\t" "stp x19, x20, [x1, #16]\n\t" - "ldp x29, x30, [sp], #0x50\n\t" - : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + "ldp x29, x30, [sp], #0x80\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt), [qz] "+r" (qz), [qt2d] "+r" (qt2d), [qyplusx] "+r" (qyplusx), [qyminusx] "+r" (qyminusx) : - : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + : "memory", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - (void)qz; - (void)qt2d; - (void)qyplusx; - (void)qyminusx; } #endif /* __aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && HAVE_CURVE25519 */ diff --git a/wolfcrypt/src/port/arm/armv8-poly1305.c b/wolfcrypt/src/port/arm/armv8-poly1305.c index 11f3c7c63..18f255952 100644 --- a/wolfcrypt/src/port/arm/armv8-poly1305.c +++ b/wolfcrypt/src/port/arm/armv8-poly1305.c @@ -1,6 +1,6 @@ /* armv8-poly1305.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/arm/armv8-sha256.c b/wolfcrypt/src/port/arm/armv8-sha256.c index 264c8e8ed..d2acf9edb 100644 --- a/wolfcrypt/src/port/arm/armv8-sha256.c +++ b/wolfcrypt/src/port/arm/armv8-sha256.c @@ -1,6 +1,6 @@ /* armv8-sha256.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -96,6 +96,188 @@ static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len) #ifdef __aarch64__ +/* First block is in sha256->buffer and rest in data. */ +static WC_INLINE void Sha256Transform(wc_Sha256* sha256, const byte* data, + word32 numBlocks) +{ + word32* k = (word32*)K; + + __asm__ volatile ( + "#load leftover data\n" + "LD1 {v0.2d-v3.2d}, %[buffer] \n" + + "#load current digest\n" + "LD1 {v12.2d-v13.2d}, %[digest] \n" + "MOV w8, %w[blocks] \n" + "REV32 v0.16b, v0.16b \n" + "REV32 v1.16b, v1.16b \n" + "REV32 v2.16b, v2.16b \n" + "REV32 v3.16b, v3.16b \n" + + "#load K values in \n" + "LD1 {v16.4s-v19.4s}, [%[k]], #64 \n" + "LD1 {v20.4s-v23.4s}, [%[k]], #64 \n" + "MOV v14.16b, v12.16b \n" /* store digest for add at the end */ + "MOV v15.16b, v13.16b \n" + "LD1 {v24.4s-v27.4s}, [%[k]], #64 \n" + "LD1 {v28.4s-v31.4s}, [%[k]], #64 \n" + + /* beginning of SHA256 block operation */ + "1:\n" + /* Round 1 */ + "MOV v4.16b, v0.16b \n" + "ADD v0.4s, v0.4s, v16.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 2 */ + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v1.4s, v17.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 3 */ + "SHA256SU0 v1.4s, v2.4s \n" + "ADD v0.4s, v2.4s, v18.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v1.4s, v3.4s, v4.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 4 */ + "SHA256SU0 v2.4s, v3.4s \n" + "ADD v0.4s, v3.4s, v19.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v2.4s, v4.4s, v1.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 5 */ + "SHA256SU0 v3.4s, v4.4s \n" + "ADD v0.4s, v4.4s, v20.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v3.4s, v1.4s, v2.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 6 */ + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v1.4s, v21.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 7 */ + "SHA256SU0 v1.4s, v2.4s \n" + "ADD v0.4s, v2.4s, v22.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v1.4s, v3.4s, v4.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 8 */ + "SHA256SU0 v2.4s, v3.4s \n" + "ADD v0.4s, v3.4s, v23.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v2.4s, v4.4s, v1.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 9 */ + "SHA256SU0 v3.4s, v4.4s \n" + "ADD v0.4s, v4.4s, v24.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v3.4s, v1.4s, v2.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 10 */ + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v1.4s, v25.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 11 */ + "SHA256SU0 v1.4s, v2.4s \n" + "ADD v0.4s, v2.4s, v26.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v1.4s, v3.4s, v4.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 12 */ + "SHA256SU0 v2.4s, v3.4s \n" + "ADD v0.4s, v3.4s, v27.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v2.4s, v4.4s, v1.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 13 */ + "SHA256SU0 v3.4s, v4.4s \n" + "ADD v0.4s, v4.4s, v28.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v3.4s, v1.4s, v2.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 14 */ + "ADD v0.4s, v1.4s, v29.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 15 */ + "ADD v0.4s, v2.4s, v30.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 16 */ + "ADD v0.4s, v3.4s, v31.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + "#Add working vars back into digest state \n" + "SUB w8, w8, #1 \n" + "ADD v12.4s, v12.4s, v14.4s \n" + "ADD v13.4s, v13.4s, v15.4s \n" + + "#check if more blocks should be done\n" + "CBZ w8, 2f \n" + + "#load in message and schedule updates \n" + "LD1 {v0.2d-v3.2d}, [%[dataIn]], #64 \n" + "MOV v14.16b, v12.16b \n" + "MOV v15.16b, v13.16b \n" + "REV32 v0.16b, v0.16b \n" + "REV32 v1.16b, v1.16b \n" + "REV32 v2.16b, v2.16b \n" + "REV32 v3.16b, v3.16b \n" + "B 1b \n" /* do another block */ + + "2:\n" + "STP q12, q13, %[out] \n" + + : [out] "=m" (sha256->digest), "=m" (sha256->buffer), "=r" (numBlocks), + "=r" (data), "=r" (k) + : [k] "4" (k), [digest] "m" (sha256->digest), [buffer] "m" (sha256->buffer), + [blocks] "2" (numBlocks), [dataIn] "3" (data) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", + "v15", "v16", "v17", "v18", "v19", "v20", "v21", + "v22", "v23", "v24", "v25", "v26", "v27", "v28", + "v29", "v30", "v31", "w8" + ); +} + /* ARMv8 hardware acceleration */ static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) { @@ -115,184 +297,11 @@ static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 le numBlocks = (len + sha256->buffLen)/WC_SHA256_BLOCK_SIZE; if (numBlocks > 0) { - word32* k = (word32*)K; - /* get leftover amount after blocks */ add = (len + sha256->buffLen) - numBlocks * WC_SHA256_BLOCK_SIZE; - __asm__ volatile ( - "#load leftover data\n" - "LD1 {v0.2d-v3.2d}, %[buffer] \n" - "#load current digest\n" - "LD1 {v12.2d-v13.2d}, %[digest] \n" - "MOV w8, %w[blocks] \n" - "REV32 v0.16b, v0.16b \n" - "REV32 v1.16b, v1.16b \n" - "REV32 v2.16b, v2.16b \n" - "REV32 v3.16b, v3.16b \n" - - "#load K values in \n" - "LD1 {v16.4s-v19.4s}, [%[k]], #64 \n" - "LD1 {v20.4s-v23.4s}, [%[k]], #64 \n" - "MOV v14.16b, v12.16b \n" /* store digest for add at the end */ - "MOV v15.16b, v13.16b \n" - "LD1 {v24.4s-v27.4s}, [%[k]], #64 \n" - "LD1 {v28.4s-v31.4s}, [%[k]], #64 \n" - - /* beginning of SHA256 block operation */ - "1:\n" - /* Round 1 */ - "MOV v4.16b, v0.16b \n" - "ADD v0.4s, v0.4s, v16.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 2 */ - "SHA256SU0 v4.4s, v1.4s \n" - "ADD v0.4s, v1.4s, v17.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v4.4s, v2.4s, v3.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 3 */ - "SHA256SU0 v1.4s, v2.4s \n" - "ADD v0.4s, v2.4s, v18.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v1.4s, v3.4s, v4.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 4 */ - "SHA256SU0 v2.4s, v3.4s \n" - "ADD v0.4s, v3.4s, v19.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v2.4s, v4.4s, v1.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 5 */ - "SHA256SU0 v3.4s, v4.4s \n" - "ADD v0.4s, v4.4s, v20.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v3.4s, v1.4s, v2.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 6 */ - "SHA256SU0 v4.4s, v1.4s \n" - "ADD v0.4s, v1.4s, v21.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v4.4s, v2.4s, v3.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 7 */ - "SHA256SU0 v1.4s, v2.4s \n" - "ADD v0.4s, v2.4s, v22.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v1.4s, v3.4s, v4.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 8 */ - "SHA256SU0 v2.4s, v3.4s \n" - "ADD v0.4s, v3.4s, v23.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v2.4s, v4.4s, v1.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 9 */ - "SHA256SU0 v3.4s, v4.4s \n" - "ADD v0.4s, v4.4s, v24.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v3.4s, v1.4s, v2.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 10 */ - "SHA256SU0 v4.4s, v1.4s \n" - "ADD v0.4s, v1.4s, v25.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v4.4s, v2.4s, v3.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 11 */ - "SHA256SU0 v1.4s, v2.4s \n" - "ADD v0.4s, v2.4s, v26.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v1.4s, v3.4s, v4.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 12 */ - "SHA256SU0 v2.4s, v3.4s \n" - "ADD v0.4s, v3.4s, v27.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v2.4s, v4.4s, v1.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 13 */ - "SHA256SU0 v3.4s, v4.4s \n" - "ADD v0.4s, v4.4s, v28.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256SU1 v3.4s, v1.4s, v2.4s \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 14 */ - "ADD v0.4s, v1.4s, v29.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 15 */ - "ADD v0.4s, v2.4s, v30.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - /* Round 16 */ - "ADD v0.4s, v3.4s, v31.4s \n" - "MOV v11.16b, v12.16b \n" - "SHA256H q12, q13, v0.4s \n" - "SHA256H2 q13, q11, v0.4s \n" - - "#Add working vars back into digest state \n" - "SUB w8, w8, #1 \n" - "ADD v12.4s, v12.4s, v14.4s \n" - "ADD v13.4s, v13.4s, v15.4s \n" - - "#check if more blocks should be done\n" - "CBZ w8, 2f \n" - - "#load in message and schedule updates \n" - "LD1 {v0.2d-v3.2d}, [%[dataIn]], #64 \n" - "MOV v14.16b, v12.16b \n" - "MOV v15.16b, v13.16b \n" - "REV32 v0.16b, v0.16b \n" - "REV32 v1.16b, v1.16b \n" - "REV32 v2.16b, v2.16b \n" - "REV32 v3.16b, v3.16b \n" - "B 1b \n" /* do another block */ - - "2:\n" - "STP q12, q13, %[out] \n" - - : [out] "=m" (sha256->digest), "=m" (sha256->buffer), "=r" (numBlocks), - "=r" (data), "=r" (k) - : [k] "4" (k), [digest] "m" (sha256->digest), [buffer] "m" (sha256->buffer), - [blocks] "2" (numBlocks), [dataIn] "3" (data) - : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", - "v8", "v9", "v10", "v11", "v12", "v13", "v14", - "v15", "v16", "v17", "v18", "v19", "v20", "v21", - "v22", "v23", "v24", "v25", "v26", "v27", "v28", - "v29", "v30", "v31", "w8" - ); + Sha256Transform(sha256, data, numBlocks); + data += numBlocks * WC_SHA256_BLOCK_SIZE - sha256->buffLen; AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); @@ -658,6 +667,202 @@ static WC_INLINE int Sha256Final(wc_Sha256* sha256, byte* hash) #else /* not using 64 bit */ +static WC_INLINE void Sha256Transform(wc_Sha256* sha256, const byte* data, + word32 numBlocks) +{ + word32* bufPt = sha256->buffer; + word32* digPt = sha256->digest; + + __asm__ volatile ( + "#load leftover data\n" + "VLDM %[buffer]!, {q0-q3} \n" + + "#load current digest\n" + "VLDM %[digest], {q12-q13} \n" + "MOV r8, %[blocks] \n" + "VREV32.8 q0, q0 \n" + "VREV32.8 q1, q1 \n" + "VREV32.8 q2, q2 \n" + "VREV32.8 q3, q3 \n" + "VLDM %[k]! ,{q5-q8} \n" + "VLDM %[k]! ,{q9}\n" + + "VMOV.32 q14, q12 \n" /* store digest for add at the end */ + "VMOV.32 q15, q13 \n" + + /* beginning of SHA256 block operation */ + "1:\n" + + /* Round 1 */ + "VMOV.32 q4, q0 \n" + "VADD.i32 q0, q0, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 2 */ + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q6 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 3 */ + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q7 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 4 */ + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q8 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 5 */ + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q9 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 6 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 7 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 8 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 9 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 10 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 11 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 12 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 13 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 14 */ + "VLD1.32 {q10}, [%[k]]! \n" + "VADD.i32 q0, q1, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 15 */ + "VLD1.32 {q10}, [%[k]]! \n" + "VADD.i32 q0, q2, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 16 */ + "VLD1.32 {q10}, [%[k]] \n" + "SUB r8, r8, #1 \n" + "VADD.i32 q0, q3, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + "#Add working vars back into digest state \n" + "VADD.i32 q12, q12, q14 \n" + "VADD.i32 q13, q13, q15 \n" + + "#check if more blocks should be done\n" + "CMP r8, #0 \n" + "BEQ 2f \n" + + "#load in message and schedule updates \n" + "VLD1.32 {q0}, [%[dataIn]]! \n" + "VLD1.32 {q1}, [%[dataIn]]! \n" + "VLD1.32 {q2}, [%[dataIn]]! \n" + "VLD1.32 {q3}, [%[dataIn]]! \n" + + /* reset K pointer */ + "SUB %[k], %[k], #160 \n" + "VREV32.8 q0, q0 \n" + "VREV32.8 q1, q1 \n" + "VREV32.8 q2, q2 \n" + "VREV32.8 q3, q3 \n" + "VMOV.32 q14, q12 \n" + "VMOV.32 q15, q13 \n" + "B 1b \n" /* do another block */ + + "2:\n" + "VST1.32 {q12, q13}, [%[out]] \n" + + : [out] "=r" (digPt), "=r" (bufPt), "=r" (numBlocks), + "=r" (data) + : [k] "r" (K), [digest] "0" (digPt), [buffer] "1" (bufPt), + [blocks] "2" (numBlocks), [dataIn] "3" (data) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", + "q15", "r8" + ); +} + /* ARMv8 hardware acceleration Aarch32 */ static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) { @@ -677,198 +882,11 @@ static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 le numBlocks = (len + sha256->buffLen)/WC_SHA256_BLOCK_SIZE; if (numBlocks > 0) { - word32* bufPt = sha256->buffer; - word32* digPt = sha256->digest; /* get leftover amount after blocks */ add = (len + sha256->buffLen) - numBlocks * WC_SHA256_BLOCK_SIZE; - __asm__ volatile ( - "#load leftover data\n" - "VLDM %[buffer]!, {q0-q3} \n" - "#load current digest\n" - "VLDM %[digest], {q12-q13} \n" - "MOV r8, %[blocks] \n" - "VREV32.8 q0, q0 \n" - "VREV32.8 q1, q1 \n" - "VREV32.8 q2, q2 \n" - "VREV32.8 q3, q3 \n" - "VLDM %[k]! ,{q5-q8} \n" - "VLDM %[k]! ,{q9}\n" - - "VMOV.32 q14, q12 \n" /* store digest for add at the end */ - "VMOV.32 q15, q13 \n" - - /* beginning of SHA256 block operation */ - "1:\n" - - /* Round 1 */ - "VMOV.32 q4, q0 \n" - "VADD.i32 q0, q0, q5 \n" - "VMOV.32 q11, q12 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 2 */ - "SHA256SU0.32 q4, q1 \n" - "VADD.i32 q0, q1, q6 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q4, q2, q3 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 3 */ - "SHA256SU0.32 q1, q2 \n" - "VADD.i32 q0, q2, q7 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q1, q3, q4 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 4 */ - "SHA256SU0.32 q2, q3 \n" - "VADD.i32 q0, q3, q8 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q2, q4, q1 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 5 */ - "SHA256SU0.32 q3, q4 \n" - "VADD.i32 q0, q4, q9 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q3, q1, q2 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 6 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q4, q1 \n" - "VADD.i32 q0, q1, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q4, q2, q3 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 7 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q1, q2 \n" - "VADD.i32 q0, q2, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q1, q3, q4 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 8 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q2, q3 \n" - "VADD.i32 q0, q3, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q2, q4, q1 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 9 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q3, q4 \n" - "VADD.i32 q0, q4, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q3, q1, q2 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 10 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q4, q1 \n" - "VADD.i32 q0, q1, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q4, q2, q3 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 11 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q1, q2 \n" - "VADD.i32 q0, q2, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q1, q3, q4 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 12 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q2, q3 \n" - "VADD.i32 q0, q3, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q2, q4, q1 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 13 */ - "VLD1.32 {q10}, [%[k]]! \n" - "SHA256SU0.32 q3, q4 \n" - "VADD.i32 q0, q4, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256SU1.32 q3, q1, q2 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 14 */ - "VLD1.32 {q10}, [%[k]]! \n" - "VADD.i32 q0, q1, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 15 */ - "VLD1.32 {q10}, [%[k]]! \n" - "VADD.i32 q0, q2, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - /* Round 16 */ - "VLD1.32 {q10}, [%[k]] \n" - "SUB r8, r8, #1 \n" - "VADD.i32 q0, q3, q10 \n" - "VMOV.32 q11, q12 \n" - "SHA256H.32 q12, q13, q0 \n" - "SHA256H2.32 q13, q11, q0 \n" - - "#Add working vars back into digest state \n" - "VADD.i32 q12, q12, q14 \n" - "VADD.i32 q13, q13, q15 \n" - - "#check if more blocks should be done\n" - "CMP r8, #0 \n" - "BEQ 2f \n" - - "#load in message and schedule updates \n" - "VLD1.32 {q0}, [%[dataIn]]! \n" - "VLD1.32 {q1}, [%[dataIn]]! \n" - "VLD1.32 {q2}, [%[dataIn]]! \n" - "VLD1.32 {q3}, [%[dataIn]]! \n" - - /* reset K pointer */ - "SUB %[k], %[k], #160 \n" - "VREV32.8 q0, q0 \n" - "VREV32.8 q1, q1 \n" - "VREV32.8 q2, q2 \n" - "VREV32.8 q3, q3 \n" - "VMOV.32 q14, q12 \n" - "VMOV.32 q15, q13 \n" - "B 1b \n" /* do another block */ - - "2:\n" - "VST1.32 {q12, q13}, [%[out]] \n" - - : [out] "=r" (digPt), "=r" (bufPt), "=r" (numBlocks), - "=r" (data) - : [k] "r" (K), [digest] "0" (digPt), [buffer] "1" (bufPt), - [blocks] "2" (numBlocks), [dataIn] "3" (data) - : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", - "q8", "q9", "q10", "q11", "q12", "q13", "q14", - "q15", "r8" - ); + Sha256Transform(sha256, data, numBlocks); + data += numBlocks * WC_SHA256_BLOCK_SIZE - sha256->buffLen; AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); @@ -1401,6 +1419,22 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) return ret; } +#ifdef OPENSSL_EXTRA +int wc_Sha256Transform(wc_Sha256* sha256, const unsigned char* data) +{ + if (sha256 == NULL || data == NULL) { + return BAD_FUNC_ARG; + } +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(sha256->buffer, (word32*)data, WC_SHA256_BLOCK_SIZE); +#else + XMEMCPY(sha256->buffer, data, WC_SHA256_BLOCK_SIZE); +#endif + Sha256Transform(sha256, data, 1); + return 0; +} +#endif + #endif /* !NO_SHA256 */ diff --git a/wolfcrypt/src/port/arm/armv8-sha512-asm.S b/wolfcrypt/src/port/arm/armv8-sha512-asm.S index 8cff141da..9b28a8231 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512-asm.S +++ b/wolfcrypt/src/port/arm/armv8-sha512-asm.S @@ -1,6 +1,6 @@ /* armv8-sha512-asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,7 +28,7 @@ * cd ../scripts * ruby ./sha2/sha512.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(WOLFSSL_SHA512) #ifdef __aarch64__ #ifndef __APPLE__ .text @@ -162,16 +162,18 @@ _Transform_Sha512_Len: stp d8, d9, [x29, #96] stp d10, d11, [x29, #112] #ifndef __APPLE__ - adr x3, L_SHA512_transform_neon_len_k + adrp x3, L_SHA512_transform_neon_len_k + add x3, x3, :lo12:L_SHA512_transform_neon_len_k #else - adrp x3, L_SHA512_transform_neon_len_k@PAGE - add x3, x3, :lo12:L_SHA512_transform_neon_len_k@PAGEOFF + adrp x3, L_SHA512_transform_neon_len_k@PAGE + add x3, x3, :lo12:L_SHA512_transform_neon_len_k@PAGEOFF #endif /* __APPLE__ */ #ifndef __APPLE__ - adr x27, L_SHA512_transform_neon_len_ror8 + adrp x27, L_SHA512_transform_neon_len_ror8 + add x27, x27, :lo12:L_SHA512_transform_neon_len_ror8 #else - adrp x27, L_SHA512_transform_neon_len_ror8@PAGE - add x27, x27, :lo12:L_SHA512_transform_neon_len_ror8@PAGEOFF + adrp x27, L_SHA512_transform_neon_len_ror8@PAGE + add x27, x27, :lo12:L_SHA512_transform_neon_len_ror8@PAGEOFF #endif /* __APPLE__ */ ld1 {v11.16b}, [x27] # Load digest into working vars @@ -1065,10 +1067,11 @@ L_sha512_len_neon_start: add x5, x5, x20 add x4, x4, x19 #ifndef __APPLE__ - adr x3, L_SHA512_transform_neon_len_k + adrp x3, L_SHA512_transform_neon_len_k + add x3, x3, :lo12:L_SHA512_transform_neon_len_k #else - adrp x3, L_SHA512_transform_neon_len_k@PAGE - add x3, x3, :lo12:L_SHA512_transform_neon_len_k@PAGEOFF + adrp x3, L_SHA512_transform_neon_len_k@PAGE + add x3, x3, :lo12:L_SHA512_transform_neon_len_k@PAGEOFF #endif /* __APPLE__ */ subs w2, w2, #0x80 bne L_sha512_len_neon_begin @@ -1090,7 +1093,7 @@ L_sha512_len_neon_start: .size Transform_Sha512_Len,.-Transform_Sha512_Len #endif /* __APPLE__ */ #endif /* __aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && WOLFSSL_SHA512 */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/wolfcrypt/src/port/arm/armv8-sha512-asm.c b/wolfcrypt/src/port/arm/armv8-sha512-asm.c index 49dffd778..87e7496f0 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512-asm.c +++ b/wolfcrypt/src/port/arm/armv8-sha512-asm.c @@ -1,6 +1,6 @@ /* armv8-sha512-asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,7 +28,7 @@ * cd ../scripts * ruby ./sha2/sha512.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.c */ -#ifdef WOLFSSL_ARMASM +#if defined(WOLFSSL_ARMASM) && defined(WOLFSSL_SHA512) #ifdef __aarch64__ #include @@ -123,19 +123,19 @@ static const uint64_t L_SHA512_transform_neon_len_ror8[] = { void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) { __asm__ __volatile__ ( - "stp x29, x30, [sp, #-16]!\n\t" - "add x29, sp, #0\n\t" #ifndef __APPLE__ - "adr x3, %[L_SHA512_transform_neon_len_k]\n\t" + "adrp x3, %[L_SHA512_transform_neon_len_k]\n\t" + "add x3, x3, :lo12:%[L_SHA512_transform_neon_len_k]\n\t" #else - "adrp x3, %[L_SHA512_transform_neon_len_k]@PAGE\n\t" - "add x3, x3, %[L_SHA512_transform_neon_len_k]@PAGEOFF\n\t" + "adrp x3, %[L_SHA512_transform_neon_len_k]@PAGE\n\t" + "add x3, x3, %[L_SHA512_transform_neon_len_k]@PAGEOFF\n\t" #endif /* __APPLE__ */ #ifndef __APPLE__ - "adr x27, %[L_SHA512_transform_neon_len_ror8]\n\t" + "adrp x27, %[L_SHA512_transform_neon_len_ror8]\n\t" + "add x27, x27, :lo12:%[L_SHA512_transform_neon_len_ror8]\n\t" #else - "adrp x27, %[L_SHA512_transform_neon_len_ror8]@PAGE\n\t" - "add x27, x27, %[L_SHA512_transform_neon_len_ror8]@PAGEOFF\n\t" + "adrp x27, %[L_SHA512_transform_neon_len_ror8]@PAGE\n\t" + "add x27, x27, %[L_SHA512_transform_neon_len_ror8]@PAGEOFF\n\t" #endif /* __APPLE__ */ "ld1 {v11.16b}, [x27]\n\t" /* Load digest into working vars */ @@ -1031,10 +1031,11 @@ void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) "add x5, x5, x20\n\t" "add x4, x4, x19\n\t" #ifndef __APPLE__ - "adr x3, %[L_SHA512_transform_neon_len_k]\n\t" + "adrp x3, %[L_SHA512_transform_neon_len_k]\n\t" + "add x3, x3, :lo12:%[L_SHA512_transform_neon_len_k]\n\t" #else - "adrp x3, %[L_SHA512_transform_neon_len_k]@PAGE\n\t" - "add x3, x3, %[L_SHA512_transform_neon_len_k]@PAGEOFF\n\t" + "adrp x3, %[L_SHA512_transform_neon_len_k]@PAGE\n\t" + "add x3, x3, %[L_SHA512_transform_neon_len_k]@PAGEOFF\n\t" #endif /* __APPLE__ */ "subs %w[len], %w[len], #0x80\n\t" "bne L_sha512_len_neon_begin_%=\n\t" @@ -1042,7 +1043,6 @@ void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) "stp x6, x7, [%x[sha512], #16]\n\t" "stp x8, x9, [%x[sha512], #32]\n\t" "stp x10, x11, [%x[sha512], #48]\n\t" - "ldp x29, x30, [sp], #16\n\t" : [sha512] "+r" (sha512), [data] "+r" (data), [len] "+r" (len) : [L_SHA512_transform_neon_len_k] "S" (L_SHA512_transform_neon_len_k), [L_SHA512_transform_neon_len_ror8] "S" (L_SHA512_transform_neon_len_ror8) : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11" @@ -1050,4 +1050,4 @@ void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) } #endif /* __aarch64__ */ -#endif /* WOLFSSL_ARMASM */ +#endif /* WOLFSSL_ARMASM && WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/port/arm/armv8-sha512.c b/wolfcrypt/src/port/arm/armv8-sha512.c index 83008d924..956ee3c3c 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512.c +++ b/wolfcrypt/src/port/arm/armv8-sha512.c @@ -1,6 +1,6 @@ /* sha512.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -483,6 +483,17 @@ void wc_Sha512Free(wc_Sha512* sha512) #endif } +#ifdef OPENSSL_EXTRA +int wc_Sha512Transform(wc_Sha512* sha512, const unsigned char* data) +{ + if (sha512 == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + Transform_Sha512_Len(sha512, data, WC_SHA512_BLOCK_SIZE); + return 0; +} +#endif + #endif /* WOLFSSL_SHA512 */ /* -------------------------------------------------------------------------- */ diff --git a/wolfcrypt/src/port/arm/cryptoCell.c b/wolfcrypt/src/port/arm/cryptoCell.c index c3bd2d9c5..4297b50fc 100644 --- a/wolfcrypt/src/port/arm/cryptoCell.c +++ b/wolfcrypt/src/port/arm/cryptoCell.c @@ -1,6 +1,6 @@ /* cryptoCell.c * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/arm/cryptoCellHash.c b/wolfcrypt/src/port/arm/cryptoCellHash.c index bc729f7f0..9e0497ef8 100644 --- a/wolfcrypt/src/port/arm/cryptoCellHash.c +++ b/wolfcrypt/src/port/arm/cryptoCellHash.c @@ -1,6 +1,6 @@ /* cryptoCellHash.c * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/atmel/atmel.c b/wolfcrypt/src/port/atmel/atmel.c index 5f9f597f1..42615b2b9 100644 --- a/wolfcrypt/src/port/atmel/atmel.c +++ b/wolfcrypt/src/port/atmel/atmel.c @@ -1,6 +1,6 @@ /* atmel.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -190,7 +190,11 @@ int wolfCrypt_ATECC_SetConfig(ATCAIfaceCfg* cfg) XMEMSET(&cfg_ateccx08a_i2c_pi, 0, sizeof(cfg_ateccx08a_i2c_pi)); cfg_ateccx08a_i2c_pi.iface_type = cfg->iface_type; cfg_ateccx08a_i2c_pi.devtype = cfg->devtype; - cfg_ateccx08a_i2c_pi.atcai2c.slave_address = cfg->atcai2c.slave_address; +#ifdef ATCA_ENABLE_DEPRECATED + cfg_ateccx08a_i2c_pi.atcai2c.slave_address = cfg->atcai2c.slave_address; +#else + cfg_ateccx08a_i2c_pi.atcai2c.address = cfg->atcai2c.address; +#endif cfg_ateccx08a_i2c_pi.atcai2c.bus = cfg->atcai2c.bus; cfg_ateccx08a_i2c_pi.atcai2c.baud = cfg->atcai2c.baud; cfg_ateccx08a_i2c_pi.wake_delay = cfg->wake_delay; @@ -259,7 +263,12 @@ int atmel_ecc_alloc(int slotType) goto exit; case ATMEL_SLOT_ECDHE: slotId = ATECC_SLOT_ECDHE_PRIV; + #ifdef WOLFSSL_ATECC_TNGTLS + /* not reserved in mSlotList, so return */ + goto exit; + #else break; + #endif case ATMEL_SLOT_ECDHE_ENC: slotId = ATECC_SLOT_ENC_PARENT; #ifdef WOLFSSL_ATECC_TNGTLS @@ -389,7 +398,7 @@ void atmel_show_rev_info(void) #ifdef WOLFSSL_ATECC_DEBUG word32 revision = 0; atmel_get_rev_info(&revision); - printf("ATECC508A Revision: %x\n", (word32)revision); + printf("ATECC608 Revision: %x\n", (word32)revision); #endif } @@ -453,12 +462,15 @@ int atmel_ecc_sign(int slotId, const byte* message, byte* signature) } int atmel_ecc_verify(const byte* message, const byte* signature, - const byte* pubkey, int* verified) + const byte* pubkey, int* pVerified) { int ret; + bool verified = false; - ret = atcab_verify_extern(message, signature, pubkey, (bool*)verified); + ret = atcab_verify_extern(message, signature, pubkey, &verified); ret = atmel_ecc_translate_err(ret); + if (pVerified) + *pVerified = (int)verified; return ret; } @@ -513,7 +525,11 @@ int atmel_init(void) XMEMSET(&cfg_ateccx08a_i2c_pi, 0, sizeof(cfg_ateccx08a_i2c_pi)); cfg_ateccx08a_i2c_pi.iface_type = ATCA_I2C_IFACE; cfg_ateccx08a_i2c_pi.devtype = ATECC_DEV_TYPE; +#ifdef ATCA_ENABLE_DEPRECATED cfg_ateccx08a_i2c_pi.atcai2c.slave_address = ATECC_I2C_ADDR; +#else + cfg_ateccx08a_i2c_pi.atcai2c.address = ATECC_I2C_ADDR; +#endif cfg_ateccx08a_i2c_pi.atcai2c.bus = ATECC_I2C_BUS; cfg_ateccx08a_i2c_pi.atcai2c.baud = 400000; cfg_ateccx08a_i2c_pi.wake_delay = 1500; @@ -915,62 +931,72 @@ exit: static int atcatls_set_certificates(WOLFSSL_CTX *ctx) { - #ifndef ATCATLS_TNGTLS_SIGNER_CERT_SIZE - #define ATCATLS_TNGTLS_SIGNER_CERT_SIZE 0x208 - #endif - #ifndef ATCATLS_TNGTLS_DEVICE_CERT_SIZE - #define ATCATLS_TNGTLS_DEVICE_CERT_SIZE 0x222 - #endif - #ifndef ATCATLS_TNGTLS_CERT_BUFF_SIZE - #define ATCATLS_TNGTLS_CERT_BUFF_SIZE (ATCATLS_TNGTLS_SIGNER_CERT_SIZE +\ - ATCATLS_TNGTLS_DEVICE_CERT_SIZE) - #endif - int ret = 0; ATCA_STATUS status; - size_t signerCertSize = ATCATLS_TNGTLS_SIGNER_CERT_SIZE; - size_t deviceCertSize = ATCATLS_TNGTLS_DEVICE_CERT_SIZE; - uint8_t certBuffer[ATCATLS_TNGTLS_CERT_BUFF_SIZE]; + size_t signerCertSize=0; + size_t deviceCertSize=0; + uint8_t *certBuffer; - /*Read signer cert*/ - status = tng_atcacert_read_signer_cert(&certBuffer[ATCATLS_TNGTLS_DEVICE_CERT_SIZE], + /* fetch signer cert size */ + status=tng_atcacert_read_signer_cert(NULL, &signerCertSize); + if (ATCA_SUCCESS != status) { + #ifdef WOLFSSL_ATECC_DEBUG + printf("Failed reading Signer cert size(0x%x)\r\n", status); + #endif + return WOLFSSL_FAILURE; + } + + /* fetch device cert size */ + status=tng_atcacert_read_device_cert(NULL, &deviceCertSize, NULL); + if (ATCA_SUCCESS != status) { + #ifdef WOLFSSL_ATECC_DEBUG + printf("Failed reading device cert size(0x%x)\r\n", status); + #endif + return WOLFSSL_FAILURE; + } + certBuffer=(uint8_t*)XMALLOC(signerCertSize+deviceCertSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if(NULL == certBuffer){ + #ifdef WOLFSSL_ATECC_DEBUG + printf("Failed allocating space for certBuffer\r\n"); + #endif + return WOLFSSL_FAILURE; + } + + /* Read signer cert */ + status = tng_atcacert_read_signer_cert(&certBuffer[deviceCertSize], &signerCertSize); if (ATCA_SUCCESS != status) { + #ifdef WOLFSSL_ATECC_DEBUG + printf("Error reading signer cert(0x%x)\r\n", status); + #endif + XFREE(certBuffer,NULL,DYNAMIC_TYPE_TMP_BUFFER); ret = atmel_ecc_translate_err(ret); return ret; } - if (signerCertSize != ATCATLS_TNGTLS_SIGNER_CERT_SIZE) { - #ifdef WOLFSSL_ATECC_DEBUG - printf("signer cert size != ATCATLS_TNGTLS_SIGNER_CERT_SIZE.(%d)\r\n", - signerCertSize); - #endif - return WOLFSSL_FAILURE; - } - /*Read device cert signed by the signer above*/ - status = tng_atcacert_read_device_cert(certBuffer, &deviceCertSize,\ - &certBuffer[ATCATLS_TNGTLS_DEVICE_CERT_SIZE]); + /* Read device cert signed by the signer above */ + status = tng_atcacert_read_device_cert(certBuffer, &deviceCertSize, + &certBuffer[deviceCertSize]); if (ATCA_SUCCESS != status) { + #ifdef WOLFSSL_ATECC_DEBUG + printf("Error reading device cert(0x%x)\r\n", status); + #endif + XFREE(certBuffer,NULL,DYNAMIC_TYPE_TMP_BUFFER); ret = atmel_ecc_translate_err(ret); return ret; } - if (deviceCertSize != ATCATLS_TNGTLS_DEVICE_CERT_SIZE) { - #ifdef WOLFSSL_ATECC_DEBUG - printf("device cert size != ATCATLS_TNGTLS_DEVICE_CERT_SIZE.(%d)\r\n", - deviceCertSize); - #endif - return WOLFSSL_FAILURE; - } ret = wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, - (const unsigned char*)certBuffer, ATCATLS_TNGTLS_CERT_BUFF_SIZE, + (const unsigned char*)certBuffer, signerCertSize+deviceCertSize, WOLFSSL_FILETYPE_ASN1); if (ret != WOLFSSL_SUCCESS) { + printf("Error registering certificate chain\r\n"); ret = -1; } else { - ret = 0; + ret = 0; } + XFREE(certBuffer,NULL,DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -985,7 +1011,7 @@ int atcatls_set_callbacks(WOLFSSL_CTX* ctx) ret = atcatls_set_certificates(ctx); if (ret != 0) { #ifdef WOLFSSL_ATECC_DEBUG - printf("atcatls_set_certificates failed. (%d)\r\n",ret); + printf("atcatls_set_certificates failed. (%d)\r\n", ret); #endif } #endif diff --git a/wolfcrypt/src/port/caam/caam_aes.c b/wolfcrypt/src/port/caam/caam_aes.c index c83e6c931..e90982641 100644 --- a/wolfcrypt/src/port/caam/caam_aes.c +++ b/wolfcrypt/src/port/caam/caam_aes.c @@ -1,6 +1,6 @@ /* caam_aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -142,7 +142,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, arg[1] = keySz; arg[2] = blocks * AES_BLOCK_SIZE; - if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { + if ((ret = wc_caamAddAndWait(buf, 4, arg, CAAM_AESCBC)) != 0) { WOLFSSL_MSG("Error with CAAM AES CBC encrypt"); return ret; } diff --git a/wolfcrypt/src/port/caam/caam_driver.c b/wolfcrypt/src/port/caam/caam_driver.c index 5d44f2da8..105bc7d28 100644 --- a/wolfcrypt/src/port/caam/caam_driver.c +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -1,6 +1,6 @@ /* caam_driver.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,78 +19,44 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#if defined(__INTEGRITY) || defined(INTEGRITY) -/* build into Integrity kernel */ -#include -#include "wolfssl/wolfcrypt/port/caam/caam_driver.h" +#if (defined(__INTEGRITY) || defined(INTEGRITY)) || \ + (defined(__QNX__) || defined(__QNXNTO__)) -#define CAAM_READ(reg) *(volatile unsigned int*)(reg) -#define CAAM_WRITE(reg, in) *(volatile unsigned int*)(reg) = (in); +#if defined(__QNX__) || defined(__QNXNTO__) + #include + #include + #include + #include -#define DESC_COUNT 1 -#define MAX_BUF 20 -#define BUFFER_COUNT (MAX_BUF * DESC_COUNT) + #include "caam_qnx.h" +#endif -/* CAAM descriptors can only be 64 unsigned ints */ -#define MAX_DESC_SZ 64 +#include "caam_driver.h" +#include "caam_error.h" -/* 64 byte buffer for when data crosses a page boundary */ -#define ALIGN_BUF 16 +#include /* for memcpy / memset */ -/* MAX_CTX is 64 bytes (sha512 digest) + 8 bytes (CAAM length value) */ -#define MAX_CTX 18 - -#define MIN_READ_REG 0xF2100000 -#define MAX_READ_REG 0XF2110000 struct JobRing { - Address JobIn; - Address JobOut; - Address Desc; + CAAM_ADDRESS JobIn; + CAAM_ADDRESS JobOut; + CAAM_ADDRESS Desc; + void* VirtualIn; + void* VirtualOut; + void* VirtualDesc; Value page; /* page allocation for descriptor to use */ -}; - -struct buffer { - Address data; - Address dataSz; -}; - -/* CAAM descriptor */ -struct DescStruct { - struct IORequestStruct TheIORequest; - struct CAAM_DEVICE* caam; - struct buffer buf[MAX_BUF]; /* buffers holding data input address */ - UINT4 desc[MAX_DESC_SZ]; /* max size of 64 word32 */ - UINT4 aadSzBuf[4]; /* Formatted AAD size for CCM */ - UINT4 alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page - align */ - UINT4 iv[MAX_CTX]; /* AES IV and also hash state */ - UINT4 ctxBuf[MAX_CTX]; /* key */ - Address output; /* address to output buffer */ - Address ctxOut; /* address to update buffer holding state */ - Value alignIdx;/* index for align buffer */ - Value idx; /* index for descriptor buffer */ - Value headIdx; /* for first portion of descriptor buffer */ - Value lastIdx; /* for last portion of descriptor buffer */ - Value outputIdx; /* idx to output buffer in "buf" */ - Value inputSz; /* size of input buffer */ - Value ctxSz; /* size of CTX/Key buffer */ - Value aadSz; /* AAD size for CCM */ - Value lastFifo; - Value type; - Value state; - Value DescriptorCount; - Boolean running; /* True if building/running descriptor is - in process */ + CAAM_MUTEX jr_lock; }; struct CAAM_DEVICE { +#if defined(__INTEGRITY) || defined(INTEGRITY) struct IODeviceVectorStruct caamVector; struct IODescriptorStruct IODescriptorArray[BUFFER_COUNT]; struct DescStruct DescArray[DESC_COUNT]; volatile Value InterruptStatus; CALL HandleInterruptCall; +#endif struct JobRing ring; }; @@ -98,175 +64,402 @@ struct CAAM_DEVICE { static struct CAAM_DEVICE caam; +/* function declarations */ +Error caamAddJob(DESCSTRUCT* desc); +Error caamDoJob(DESCSTRUCT* desc); + + /****************************************************************************** Internal CAAM Job Ring and partition functions ****************************************************************************/ +#ifdef CAAM_DEBUG_MODE +/* runs a descriptor in debug mode */ +static Error caamDebugDesc(struct DescStruct* desc) +{ + int z; + int sz; + unsigned int flag = 0x20000000; + + /* clear and set desc size */ + sz = desc->desc[0] & 0x0000007F; + CAAM_WRITE(CAAM_DECORR, 1); /* ask for DECO permissions */ + printf("CAAM_DECORR = 0x%08X\n", CAAM_READ(CAAM_DECORR)); + printf("STATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS)); + printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4)); + printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04)); + + printf("Descriptor input :\n"); + /* write descriptor into descriptor buffer */ + for (z = 0; z < sz; z = z + 1) { + CAAM_WRITE(CAAM_DODESB + (z*4), desc->desc[z]); + printf("\t0x%08X\n", desc->desc[z]); + } + printf("\n"); + + printf("command size = %d\n", sz); + if (sz > 4) { + flag |= 0x10000000; + } + + CAAM_WRITE(CAAM_DODAR+4, desc->caam->ring.Desc); + /* set WHL bit since we loaded the entire descriptor */ + CAAM_WRITE(CAAM_DOJQCR_MS, flag); + + printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4)); + printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", CAAM_READ(0x8E04)); + + /* DECO buffer */ + printf("DECO BUFFER [0x%08X]:\n", CAAM_READ(CAAM_DODAR+4)); + printf("\tSTATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS)); + printf("\tJRSTAR_JR0 : 0x%08X\n", CAAM_READ(0x1044)); + for (z = 0; z < sz; z = z + 1) { + printf("\t0x%08X\n", CAAM_READ(CAAM_DODESB + (z*4))); + } + + + //D0JQCR_LS + printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804)); + printf("Desc = 0x%08X\n", desc->caam->ring.Desc); + + + /* DECO buffer */ + printf("DECO BUFFER [0x%08X]:\n", CAAM_READ(CAAM_DODAR+4)); + printf("\tSTATUS : 0x%08X\n", CAAM_READ(CAAM_DOOPSTA_MS)); + printf("\tJRSTAR_JR0 : 0x%08X\n", CAAM_READ(0x1044)); + for (z = 0; z < sz; z = z + 1) { + printf("\t0x%08X\n", CAAM_READ(CAAM_DODESB + (z*4))); + } + + printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804)); + printf("CAAM STATUS : 0x%08X\n", CAAM_READ(0x0FD4)); + while ((CAAM_READ(0x8E04) & 0x80000000U) != 0U) { + printf("DECO DRG (bit 32 is valid -- running) : 0x%08X\n", + CAAM_READ(0x8E04)); + sleep(1); + } + CAAM_WRITE(CAAM_DECORR, 0); /* free DECO */ + printf("done with debug job\n"); + return Success; +} +#endif /* CAAM_DEBUG_MODE */ + + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +static void printSecureMemoryInfo() +{ + unsigned int SMVID_MS, SMVID_LS; + + printf("SMSTA = 0x%08X\n", CAAM_READ(0x1FB4)); + printf("SMPO = 0x%08X\n", CAAM_READ(CAAM_SM_SMPO)); + SMVID_MS = CAAM_READ(CAAM_SM_SMVID_MS); + SMVID_LS = CAAM_READ(CAAM_SM_SMVID_LS); + printf("\tNumber Partitions : %d\n", ((SMVID_MS >> 12) & 0xFU)); + printf("\tNumber Pages : %d\n", (SMVID_MS & 0x3FFU)); + printf("\tPage Size : 2^%d\n", ((SMVID_LS >> 16) & 0x7U)); +} +#endif + /* flush job ring and reset */ static Error caamReset(void) { int t = 100000; /* time out counter for flushing job ring */ /* make sure interrupts are masked in JRCFGR0_LS register */ - CAAM_WRITE(CAAM_BASE | 0x1054, CAAM_READ(CAAM_BASE | 0x1054) | 1); + CAAM_WRITE(0x1054, CAAM_READ(0x1054) | 1); /* flush and reset job rings using JRCR0 register */ - CAAM_WRITE(CAAM_BASE | 0x106C, 1); + CAAM_WRITE(0x106C, 1); /* check register JRINTR for if halt is in progress */ - while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x104C) & 0x4) == 0x4)) t--; + while (t > 0 && ((CAAM_READ(0x104C) & 0x4) == 0x4)) { t = t - 1; } if (t == 0) { /*unrecoverable failure, the job ring is locked, up hard reset needed*/ - return NotRestartable; + return -1;//NotRestartable; } /* now that flush has been done restart the job ring */ t = 100000; - CAAM_WRITE(CAAM_BASE | 0x106C, 1); - while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x106C) & 1) == 1)) t--; + CAAM_WRITE(0x106C, 1); + while (t > 0 && ((CAAM_READ(0x106C) & 1) == 1)) { t = t - 1; } if (t == 0) { /*unrecoverable failure, reset bit did not return to 0 */ - return NotRestartable; + return -1;//NotRestartable; } /* reset most registers and state machines in CAAM using MCFGR register also reset DMA */ - CAAM_WRITE(CAAM_BASE | 0x0004, 0x90000000); + CAAM_WRITE(0x0004, 0x90000000); + + /* DAR 0x0120 can be used to check if hung */ + + /* DDR */ + CAAM_WRITE(0x0124, 1); return Success; } -/* returns MemoryMapMayNotBeEmpty if page/par is already owned - * returns Success on success - * all other returns is an error state - */ -static Error caamCreatePartition(unsigned char page, unsigned char par) + +/* free the page and dealloc */ +static Error caamFreePage(unsigned int page) { - /* check ownership of partition */ - if ((CAAM_READ(CAAM_BASE | 0x1FBC) & (0x3 << (par * 2))) > 0) { - return MemoryMapMayNotBeEmpty; + /* owns the page can dealloc it */ + CAAM_WRITE(CAAM_SM_CMD, (page << 16U) | 0x2U); + while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); + } + if ((CAAM_READ(CAAM_SM_STATUS) & 0x00003000) > 0) { + /* error while deallocating page */ + WOLFSSL_MSG("error while deallocating page"); + return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ + } + WOLFSSL_MSG("free'd page"); + return Success; +} + +/* free the partition and dealloc */ +Error caamFreePart(unsigned int part) +{ + unsigned int status; + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("freeing partition %d\n", part); + #endif + CAAM_WRITE(CAAM_SM_CMD, (part << 8U) | 0x3U); + + status = CAAM_READ(CAAM_SM_STATUS); + while (((status & 0x00004000U) > 0U) && ((status & 0x00003000U) == 0U)) { + CAAM_CPU_CHILL(); + status = CAAM_READ(CAAM_SM_STATUS); } - /* set generic all access permissions, gets reset later */ - CAAM_WRITE(CAAM_BASE | (0x1108 + (par * 16)), 0xF); - CAAM_WRITE(CAAM_BASE | (0x110C + (par * 16)), 0xF); - CAAM_WRITE(CAAM_BASE | (0x1104 + (par * 16)), 0xFF); - - /* check ownership of page */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); - /* wait for inquiry cmd to complete */ - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + if (((status & 0x00003000U) > 0U) || ((status & 0x0000C000U) > 0U)) { + /* error while deallocating page */ + WOLFSSL_MSG("error while deallocating partition"); + return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ } - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) == 0xC0) { - /* owns the page can dealloc it */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x2); - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) {} - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { - /* error while deallocating page */ - return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ + WOLFSSL_MSG("free'd partition"); + return Success; +} + + +/* find all partitions we own and free them */ +static Error caamFreeAllPart() +{ + unsigned int SMPO; + unsigned int i; + + WOLFSSL_MSG("Free all partitions"); + SMPO = CAAM_READ(0x1FBC); + for (i = 0; i < 15U; i = i + 1U) { + if ((SMPO & (0x3U << (i * 2U))) == (0x3U << (i * 2U))) { + caamFreePart(i); } } - else { - /* check if owned by someone else */ - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) != 0) { + + return 0; +} + + +/* search through the partitions to find an unused one + * returns negative value on failure, on success returns 0 or greater + */ +int caamFindUnusuedPartition() +{ + unsigned int SMPO; + unsigned int i; + int ret = -1; + + SMPO = CAAM_READ(0x1FBC); + for (i = 0; i < 15U; i = i + 1) { + if ((SMPO & (0x3U << (i * 2U))) == 0U) { + ret = (int)i; + break; + } + } + + return ret; +} + + +/* flag contains how the parition is set i.e CSP flag and read/write access + * it also contains if locked + */ +static Error caamCreatePartition(unsigned int page, unsigned int par, + unsigned int flag) +{ + + unsigned int status; + + /* check ownership of partition */ + status = CAAM_READ(0x1FBC); + if ((status & (0x3U << (par * 2))) > 0) { + if ((status & (0x3U << (par * 2))) == (0x3U << (par * 2))) { + WOLFSSL_MSG("we own this partition!"); + } + else { return MemoryMapMayNotBeEmpty; } } - /* allocate page to partition */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | (par << 8) | 0x1); + CAAM_WRITE(0x1A04 + (par * 16), flag); + + /* dealloc page if we own it */ + CAAM_WRITE(CAAM_SM_CMD, (page << 16) | 0x5); + while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); + } + if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0xC0) { + if (caamFreePage(page) != Success) { + return MemoryMapMayNotBeEmpty; + } + } + else if ((CAAM_READ(CAAM_SM_STATUS) & 0x000000C0) == 0x00) { + WOLFSSL_MSG("page available and un-owned"); + } + else { + WOLFSSL_MSG("we don't own the page..."); + return -1; + } + + CAAM_WRITE(CAAM_SM_CMD, (page << 16) | (par << 8) | 0x1); /* wait for alloc cmd to complete */ - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { - } - - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { - return MemoryOperationNotPerformed; - } - - /* double check ownership now of page */ - CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); - /* wait for inquiry cmd to complete */ - while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { - } - if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000000F) == 0 || - (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { - /* page not owned */ - return MemoryOperationNotPerformed; + while ((CAAM_READ(CAAM_SM_STATUS) & 0x00004000) > 0 && + (CAAM_READ(CAAM_SM_STATUS) & 0x00003000) == 0) { + CAAM_CPU_CHILL(); } return Success; } -/* Gets the status of a job. Returns Waiting if no output jobs ready to be +/* return a partitions physical address on success, returns 0 on fail */ +CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag) +{ + int err; + + (void)flag; /* flag is for future changes to flag passed when creating */ + + /* create and claim the partition */ + err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | + CAAM_SM_CSP | CAAM_SM_ALL_RW); + if (err != Success) { + WOLFSSL_MSG("Error creating partiions for secure ecc key"); + return 0; + } + + return (CAAM_ADDRESS)(CAAM_PAGE + (part << 12)); +} + + +/* Gets the status of a job. Returns CAAM_WAITING if no output jobs ready to be * read. - * If no jobs are done then return Waiting + * If no jobs are done then return CAAM_WAITING * If jobs are done but does not match desc then return NoActivityReady * Status holds the error values if any */ -static Error caamGetJob(struct CAAM_DEVICE* dev, UINT4* status) +static Error caamGetJob(struct CAAM_DEVICE* dev, unsigned int* status) { - UINT4 reg = CAAM_READ(CAAM_BASE | 0x1044); /* JRSTAR0 status */ + unsigned int reg; if (status) { *status = 0; } - /* check for DECO, CCB, and Job Ring error state JRSTAR0 register */ - if (((reg & 0xF0000000) == 0x20000000) || /* CCB error */ - ((reg & 0xF0000000) == 0x40000000)|| /* DECO error */ - ((reg & 0xF0000000) == 0x60000000)) { /* Job Ring error */ - - if ((reg & 0x0000000F) > 0) { - *status = reg; - return Failure; - } - } +#ifdef CAAM_DEBUG_MODE + (void)dev; + return Success; +#endif /* Check number of done jobs in output list */ - reg = CAAM_READ(CAAM_BASE | 0x103C); + reg = CAAM_READ(0x103C); +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("number of jobs in output list = 0x%08X\n", reg); +#endif if ((reg & 0x000003FF) > 0) { - UINT4* out = (UINT4*)(dev->ring.JobOut); - if (status) { - *status = out[1]; + unsigned int *pt; + + if (CAAM_ADR_SYNC(caam.ring.VirtualOut, (2 * CAAM_JOBRING_SIZE * + sizeof(unsigned int))) != 0) { + return -1; } - if ((dev->ring.Desc ^ 0xF0000000) != out[0]) { - db_printf("CAAM job completed vs expected mismatch"); - return NoActivityReady; - } - - if (out[1] > 0) { - return Failure; + /* sanity check on job out */ + pt = (unsigned int*)caam.ring.VirtualOut; + if (pt[0] != caam.ring.Desc) { + return -1; } + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("\tjob 0x%08X done - result 0x%08X\n", pt[0], pt[1]); + #endif + *status = pt[1]; /* increment jobs removed */ - CAAM_WRITE(CAAM_BASE | 0x1034, 1); + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("removing job from list\n"); + fflush(stdout); + #endif + CAAM_WRITE(0x1034, 1); } else { /* check if the CAAM is idle and not processing any descriptors */ - if ((CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000002) == 2 /* idle */ - && (CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000001) == 0) { + if ((CAAM_READ(0x0FD4) & 0x00000002) == 2 /* idle */ + && (CAAM_READ(0x0FD4) & 0x00000001) == 0) { + WOLFSSL_MSG("caam is idle....."); return NoActivityReady; } - - return Waiting; + return CAAM_WAITING; } + (void)dev; - return Success; + CAAM_WRITE(JRCFGR_JR0_LS, 0); + if (*status == 0) { + return Success; + } + return Failure; } +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +/* debug print out JDKEK */ +static void print_jdkek() +{ + int i; + + printf("JDKEK = "); + for (i = 0; i < 8; i = i + 1) { + printf("%08X ", CAAM_READ(0x0400 + (i*4))); + } + printf("\n"); +} +#endif + + +/* instantiate RNG and create JDKEK, TDKEK, and TDSK key */ +static unsigned int wc_rng_start[] = { + CAAM_HEAD | 0x00000006, + CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00000004, /* Instantiate RNG handle 0 with TRNG */ + CAAM_JUMP | 0x02000001, /* wait for Class1 RNG and jump to next cmd */ + CAAM_LOAD | 0x00880004, /* Load to clear written register */ + 0x00000001, /* reset done interrupt */ + CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00001000 /* Generate secure keys */ +}; + + + /* Initialize CAAM RNG * returns 0 on success */ -static int caamInitRng(struct CAAM_DEVICE* dev) +int caamInitRng(struct CAAM_DEVICE* dev); +int caamInitRng(struct CAAM_DEVICE* dev) { - UINT4 reg, status; + DESCSTRUCT desc; + unsigned int reg, status; int ret = 0; + memset(&desc, 0, sizeof(DESCSTRUCT)); + /* Set up use of the TRNG for seeding wolfSSL HASH-DRBG */ + /* check out the status and see if already setup */ CAAM_WRITE(CAAM_RTMCTL, CAAM_PRGM); CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | 0x40); /* reset */ @@ -288,81 +481,153 @@ static int caamInitRng(struct CAAM_DEVICE* dev) reg |= CAAM_CTLERR; CAAM_WRITE(CAAM_RTMCTL, reg); - /* check input slot is available and then add */ - if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { - UINT4* in = (UINT4*)dev->ring.JobIn; + /* check out the status and see if already setup */ + reg = CAAM_READ(CAAM_RDSTA); + if (((reg >> 16) & 0xF) > 0) { + WOLFSSL_MSG("RNG is in error state"); + caamReset(); + } - memcpy((unsigned char*)dev->ring.Desc, (unsigned char*)wc_rng_start, - sizeof(wc_rng_start)); + if (reg & (1U << 30)) { + WOLFSSL_MSG("JKDKEK rng was setup using a non determinstic key"); + return 0; + } - in[0] = dev->ring.Desc ^ 0xF0000000; /* physical address */ + if (CAAM_READ(0x1014) > 0) { + int i; + #ifdef CAAM_DEBUG_MODE + for (i = 0; i < 6; i = i + 1) { + desc.desc[desc.idx++] = wc_rng_start[i]; + } + + desc.caam = dev; + ret = caamDoJob(&desc); + #else + unsigned int *pt = (unsigned int*)caam.ring.VirtualDesc; + for (i = 0; i < 6; i = i + 1) { + pt[i] = wc_rng_start[i]; + } + pt = (unsigned int*)caam.ring.VirtualIn; + pt[0] = (unsigned int)caam.ring.Desc; + + /* start process */ + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("incrementing job count\n"); + fflush(stdout); + #endif CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + #endif } else { - return Waiting; + return CAAM_WAITING; } do { ret = caamGetJob(dev, &status); - /* @TODO use a better way to chill out CPU. */ - } while (ret == Waiting); + CAAM_CPU_CHILL(); + } while (ret == CAAM_WAITING); - return ret; + if (ret == Success) + return 0; + return -1; } -static Error caamDoJob(struct DescStruct* desc) +/* Take in a descriptor and add it to the job list */ +Error caamAddJob(DESCSTRUCT* desc) { - Error ret; - UINT4 status; - /* clear and set desc size */ desc->desc[0] &= 0xFFFFFF80; - desc->desc[0] += desc->idx; + desc->desc[0] += desc->idx + (desc->startIdx << 16); + CAAM_LOCK_MUTEX(&caam.ring.jr_lock); /* check input slot is available and then add */ - if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { - UINT4* in = (UINT4*)desc->caam->ring.JobIn; + if (CAAM_READ(0x1014) > 0) { + int i; + unsigned int *pt; - memcpy((unsigned char*)desc->caam->ring.Desc, (unsigned char*)desc->desc, - (desc->idx + 1) * sizeof(UINT4)); + pt = (unsigned int*)caam.ring.VirtualDesc; + #if defined(WOLFSSL_CAAM_PRINT) + printf("Doing Job :\n"); + #endif + for (i = 0; i < desc->idx; i = i + 1) { + pt[i] = desc->desc[i]; + #if defined(WOLFSSL_CAAM_PRINT) + printf("\tCMD %02d [%p] = 0x%08X\n", i+1, pt + i, + desc->desc[i]); + #endif + } - in[0] = desc->caam->ring.Desc ^ 0xF0000000; /* physical address */ + pt = (unsigned int*)caam.ring.VirtualIn; + pt[0] = (unsigned int)caam.ring.Desc; + + if (CAAM_ADR_SYNC(caam.ring.VirtualDesc, + desc->idx * sizeof(unsigned int)) != 0) { + return -1; + } + + if (CAAM_ADR_SYNC(caam.ring.VirtualIn, + CAAM_JOBRING_SIZE * sizeof(unsigned int)) != 0) { + return -1; + } + + #ifdef CAAM_DEBUG_MODE + caamDebugDesc(desc); + #else + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("started job 0x%08X done\n", (unsigned int)caam.ring.Desc); + #endif CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + #endif } else { - return Waiting; + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("SLOT = 0x%08X, IRJAR0 = 0x%08X\n", CAAM_READ(0x1014), + CAAM_READ(CAAM_IRJAR0)); + printf("Number of job in done queue = 0x%08X\n", CAAM_READ(0x103C)); + #endif + CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock); + return CAAM_WAITING; + } + CAAM_UNLOCK_MUTEX(&caam.ring.jr_lock); + return Success; +} + + +/* Synchronous job completion, add it to job queue and wait till finished */ +Error caamDoJob(DESCSTRUCT* desc) +{ + Error ret; + unsigned int status; + + ret = caamAddJob(desc); + if (ret != Success) { + return ret; } do { ret = caamGetJob(desc->caam, &status); - /* @TODO use a better way to chill out CPU. */ - } while (ret == Waiting); + CAAM_CPU_CHILL(); + } while (ret == CAAM_WAITING); + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("job status = 0x%08X, ret = %d\n", status, ret); + #endif if (status != 0 || ret != Success) { - #if 0 - /* Used during testing to print out descriptor */ - { - char msg[2048]; - char* pt = msg; - int z; - - memset(msg, 0, sizeof(msg)); - for (z = 0; z < desc->idx; z++) { - snprintf(pt, sizeof(msg) - (z * 21), "desc[%d] = 0x%8.8x, ", - z, desc->desc[z]); - pt += 21; - } - snprintf(pt, sizeof(msg) - (z * 21), "status = 0x%8.8x\n", status); - if (desc->buf[0].data != 0) { /* for testing */ - memcpy((char*)desc->buf[0].data, msg, sizeof(msg)); - } - } - #endif - - /* try to reset after error */ - caamReset(); + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + int i; + for (i = 0; i < desc->idx; i = i + 1) { + printf("\tCMD %02d = 0x%08X\n", i+1, desc->desc[i]); + } + printf("\n"); + #endif + /* consider any job ring errors as fatal, and try reset */ + if (caamParseJRError(CAAM_READ(JRINTR_JR0)) != 0) { + caamReset(); + } + caamParseError(status); return ret; } @@ -370,188 +635,79 @@ static Error caamDoJob(struct DescStruct* desc) } -/* handle input or output buffers - * NOTES: if sz == 0 then read all the rest of the buffers available - * when align == 1 then there is no alignment constraints - * - * returns the data size in bytes on success. With failure a negative value is - * returned. - */ -static int caamAddIO(struct DescStruct* desc, UINT4 options, UINT4 sz, - UINT4 align, UINT4* idx) -{ - int i, outSz = 0; - - if (align == 0) { - return -1; /* programming error */ - } - - for (i = *idx; i < desc->DescriptorCount; i++) { - /* input must be a multiple of "align" bytes */ - struct buffer* buf = &desc->buf[i]; - int blocks = buf->dataSz / align; - Address data = buf->data; - Address dataSz = buf->dataSz; - - if (outSz >= sz && sz != 0) { - break; - } - - if (dataSz % align > 0) { - /* store potential overlap */ - int tmpSz = dataSz % align; - int add = (tmpSz < (align - desc->alignIdx)) ? tmpSz : - align - desc->alignIdx; - unsigned char* local = (unsigned char*)desc->alignBuf; - - /* if already something in the buffer then add from front */ - if (desc->alignIdx > 0) { - memcpy((unsigned char*)&local[desc->alignIdx], - (unsigned char*)data, add); - data += add; - } - else { - memcpy((unsigned char*)&local[desc->alignIdx], - (unsigned char*)data + (blocks * align), add); - } - dataSz -= add; - desc->alignIdx += add; - } - - if (desc->alignIdx == align) { - desc->lastFifo = desc->idx; - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; - } - desc->desc[desc->idx++] = options + desc->alignIdx; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); - ASP_FlushCaches((Address)desc->alignBuf, desc->alignIdx); - outSz += desc->alignIdx; - } - - if (blocks > 0) { - desc->lastFifo = desc->idx; - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; - } - desc->desc[desc->idx++] = options + (blocks * align); - desc->desc[desc->idx++] = BSP_VirtualToPhysical(data); - outSz += (blocks * align); - - /* only one buffer available for align cases so exit here and make - a new descriptor after running current one */ - if (desc->alignIdx == align) { - desc->alignIdx = 0; - i++; /* start at next buffer */ - break; - } - } - } - - *idx = i; - return outSz; -} - - -/****************************************************************************** - IODevice Register Read and Write - ****************************************************************************/ - -static Error caamReadRegister(IODeviceVector ioCaam, Value reg, Value *out) -{ - if (reg < MIN_READ_REG || reg > MAX_READ_REG) { - return IllegalRegisterNumber; - } - - switch (reg) { - case CAAM_STATUS: - case CAAM_VERSION_MS: - case CAAM_VERSION_LS: - case CAMM_SUPPORT_MS: - case CAMM_SUPPORT_LS: - case CAAM_RTMCTL: - *out = CAAM_READ(reg); - break; - - default: - return IllegalRegisterNumber; - } - - (void)ioCaam; - return Success; -} - - -static Error caamWriteRegister(IODeviceVector ioCaam, Value reg, Value in) -{ - /* Should be no need for writes */ - return OperationNotAllowedOnTheUniversalIODevice; -} - - /****************************************************************************** CAAM Blob Operations ****************************************************************************/ -/* limit on size due to size of job ring being 64 word32's */ -static Error caamBlob(struct DescStruct* desc) +/* limit on size due to size of job ring being 64 unsigned int's */ +int caamBlob(DESCSTRUCT* desc) { + void *vaddrOut, *vaddr, *keymod; Error err; - UINT4 keyType = 0x00000C08; /* default red */ - UINT4 i = 0; - int sz = 0, ret; + unsigned int keyType = 0x00000C08; /* default red */ + unsigned int i = 0; + int inputSz; + int outputSz; if (desc->idx + 3 > MAX_DESC_SZ) { return Failure; } - /*default to Red Key type, with offset of 12 and 8 byte load to context 2*/ - desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | CAAM_IMM | keyType); + /* doing black blobs */ + if (desc->state) { + WOLFSSL_MSG("making a black blob"); + keyType = 0x00000010; + } + + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | keyType); /* add key modifier */ - if (i < desc->DescriptorCount) { - UINT4* pt; - Address data = desc->buf[i].data; - Address dataSz = desc->buf[i].dataSz; + keymod = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(keymod, desc->buf[i].dataSz); + i++; - pt = (UINT4*)data; - if (dataSz < 8) { /* expecting 8 bytes for key modifier*/ - return TooManyBuffers; - } - desc->desc[desc->idx++] = pt[0]; - desc->desc[desc->idx++] = pt[1]; + inputSz = desc->buf[i].dataSz; + if (desc->state && (desc->type == CAAM_BLOB_ENCAP)) { + /* black keys with CCM have mac at the end */ + inputSz += BLACK_KEY_MAC_SZ; } + vaddr = CAAM_ADR_MAP(desc->buf[i].data, inputSz, 1); + /* add input */ - while (sz < desc->inputSz && i < desc->DescriptorCount) { - ret = caamAddIO(desc, CAAM_SEQI, desc->inputSz - sz, 1, &i); - if (ret < 0) { /* handle error case */ - return TooManyBuffers; - } - sz += ret; - } + desc->desc[desc->idx++] = CAAM_SEQI + desc->buf[i].dataSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr, inputSz); + i++; desc->outputIdx = i; - /* add output */ - if (caamAddIO(desc, CAAM_SEQO, 0, 1, &i) < 0) { - return TooManyBuffers; + outputSz = desc->buf[i].dataSz; + if (desc->state && (desc->type == CAAM_BLOB_DECAP)) { + /* black keys with CCM have mac at the end */ + outputSz += BLACK_KEY_MAC_SZ; } + vaddrOut = CAAM_ADR_MAP(desc->buf[i].data, outputSz, 0); + /* add output */ + desc->desc[desc->idx++] = CAAM_SEQO + desc->buf[i].dataSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddrOut, outputSz); if (desc->idx + 1 > MAX_DESC_SZ) { return Failure; } - desc->desc[desc->idx++] = CAAM_OP | CAAM_OPID_BLOB | desc->type; + desc->desc[desc->idx] = CAAM_OP | CAAM_OPID_BLOB | desc->type; - if ((err = caamDoJob(desc)) != Success) { - return err; + if (desc->state) { + desc->desc[desc->idx] |= 0x104; /* EKT and Black_key (key is covered) */ } + desc->idx++; + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); - /* flush output buffers */ - for (i = desc->outputIdx; i < desc->DescriptorCount; i++) { - ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); - } + CAAM_ADR_UNMAP(keymod, desc->buf[0].data, desc->buf[0].dataSz, 0); + CAAM_ADR_UNMAP(vaddr, desc->buf[1].data, inputSz, 0); + CAAM_ADR_UNMAP(vaddrOut, desc->buf[2].data, outputSz, 1); - return Success; + return err; } @@ -559,771 +715,573 @@ static Error caamBlob(struct DescStruct* desc) CAAM AES Operations ****************************************************************************/ -/* returns amount written on success and negative value in error case. - * Is different from caamAddIO in that it only adds a single input buffer - * rather than multiple ones. - */ -static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align, - UINT4 totalSz) +int caamAesCmac(DESCSTRUCT* desc, int sz, unsigned int args[4]) { - int sz; - UINT4 i = *idx; + Error err; + unsigned int keySz; + unsigned int macSz = 0; + void *vaddr[4] = {0}; + unsigned int vidx = 0; + unsigned int ctx; + unsigned int isBlackKey; + int i; - /* handle alignment constraints on input */ - if (desc->alignIdx > 0) { - sz = desc->alignIdx; + isBlackKey = args[2]; + keySz = args[1]; - /* if there is more input buffers then add part of it */ - if (i < desc->outputIdx && i < desc->DescriptorCount) { - sz = align - desc->alignIdx; - sz = (sz <= desc->buf[i].dataSz) ? sz : desc->buf[i].dataSz; - memcpy((unsigned char*)(desc->alignBuf) + desc->alignIdx, - (unsigned char*)(desc->buf[i].data), sz); + /* Get CTX physical address */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[1].data, desc->buf[1].dataSz, 1); + ctx = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], desc->buf[1].dataSz); + vidx++; - desc->buf[i].dataSz -= sz; - desc->buf[i].data += sz; - sz += desc->alignIdx; + /* LOAD KEY */ + desc->desc[desc->idx] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + keySz; + if (isBlackKey) { + desc->desc[desc->idx] |= CAAM_LOAD_BLACK_KEY; + macSz = BLACK_KEY_MAC_SZ; + } + desc->idx++; + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[0].data, desc->buf[0].dataSz + macSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[0].dataSz + macSz); + #if 0 + { + unsigned int p; byte* pt = (byte*)vaddr[vidx]; + printf("Using key [%d]:", desc->buf[0].dataSz + macSz); + for (p = 0; p < keySz; p++) + printf("%02X", pt[p]); + printf("\n"); + } + #endif + vidx++; + + /* Load in CTX only when not initialization */ + if ((desc->state & CAAM_ALG_INIT) == 0) { + int ofst = 0; + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + + desc->buf[1].dataSz; + desc->desc[desc->idx++] = ctx; + + #if 0 + { + unsigned int z; byte* pt = (byte*)vaddr[0]; + printf("loading in CTX [%d] :", desc->buf[1].dataSz); + for (z = 0; z < 32; z++) + printf("%02X", pt[z]); + printf("\n"); } + #endif + } - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; + /* add protinfo to operation command */ + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | desc->state; + + /* add in all input buffers */ + for (i = 2; i < sz; i = i + 1) { + desc->desc[desc->idx] = (CAAM_FIFO_L | CAAM_CLASS1 | FIFOL_TYPE_MSG) + + desc->buf[i].dataSz; + if (i+1 == sz) { + /* this is the last input buffer, signal the HW with LC1 bit */ + desc->desc[desc->idx] |= FIFOL_TYPE_LC1; } - ASP_FlushCaches((Address)desc->alignBuf, sz); - desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | - CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); - desc->alignIdx = 0; + desc->idx++; + + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + + #if 0 + { + unsigned int z; byte* pt = (byte*)vaddr[vidx]; + printf("MSG [%d] :", desc->buf[i].dataSz); + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + + vidx++; + } + + /* if there is no input buffers than add in a single FIFO LOAD to kick off + * the operation */ + if (sz == 2) { /* only key and ctx buffer */ + desc->desc[desc->idx++] = CAAM_FIFO_L | FIFOL_TYPE_LC1 | CAAM_CLASS1 | + FIFOL_TYPE_MSG; + vaddr[vidx] = CAAM_ADR_MAP(0, 0, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], 0); + vidx++; + } + + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | 32; + desc->desc[desc->idx++] = ctx; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + #if 0 + { + unsigned int z; byte* pt = (byte*)vaddr[0]; + printf("CTX: "); + for (z = 0; z < 32; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + + vidx = 0; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[1].data, desc->buf[1].dataSz, 1); + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[0].data, desc->buf[0].dataSz + macSz, 0); + if (sz == 2) { + CAAM_ADR_UNMAP(vaddr[vidx], 0, 0, 0); } else { - sz = desc->buf[i].dataSz; - if ((totalSz + sz) == desc->inputSz) { /* not an issue on final */ - align = 1; + for (i = 2; i < sz; i = i + 1) { /* unmap the input buffers */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, + desc->buf[i].dataSz, 0); } - - desc->alignIdx = sz % align; - if (desc->alignIdx != 0) { - sz -= desc->alignIdx; - memcpy((unsigned char*)desc->alignBuf, - (unsigned char*)(desc->buf[i].data) + sz, - desc->alignIdx); - } - - if (desc->idx + 2 > MAX_DESC_SZ) { - return -1; - } - desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | - CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->buf[i].data); - i++; } - *idx = i; - return sz; + return err; } -/* returns enum Success on success, all other return values should be - * considered an error. - * - * ofst is the amount of leftover buffer from previous calls - * inputSz is the amount of input in bytes that is being matched to output - */ -static Error caamAesOutput(struct DescStruct* desc, int* ofst, UINT4 inputSz) -{ - int offset = *ofst; - - if (desc->output != 0 && offset > 0 && inputSz > 0) { - UINT4 addSz; - - /* handle potential leftovers */ - addSz = (inputSz >= offset) ? offset : inputSz; - - inputSz -= addSz; - desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + addSz; - if (inputSz > 0) { /* check if expecting more output */ - desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; - } - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->output); - - if (addSz == offset) { - /* reset */ - desc->output = 0; - offset = 0; - } - else { - offset -= addSz; - desc->output += addSz; - - if (offset < 0) { - return TransferFailed; - } - } - } - - for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { - struct buffer* buf = &desc->buf[desc->lastIdx]; - - if (inputSz > 0) { - int tmp; - - if (buf->dataSz <= inputSz) { - tmp = buf->dataSz; - } - else { - offset = buf->dataSz - inputSz; - tmp = inputSz; - desc->output = buf->data + tmp; - } - inputSz -= tmp; - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + tmp; - if (inputSz > 0) { /* check if expecting more output */ - desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; - } - desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); - } - else { - break; - } - } - - *ofst = offset; - return Success; -} - - -/* check size of output and get starting buffer for it */ -static Error caamAesOutSz(struct DescStruct* desc, UINT4 i) -{ - int sz = 0; - - for (desc->outputIdx = i; desc->outputIdx < desc->DescriptorCount && - sz < desc->inputSz; desc->outputIdx++) { - sz += desc->buf[desc->outputIdx].dataSz; - } - desc->lastIdx = desc->outputIdx; - - /* make certain that output size is same as input */ - sz = 0; - for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { - sz += desc->buf[desc->lastIdx].dataSz; - } - if (sz != desc->inputSz) { - return SizeIsTooLarge; - } - desc->lastIdx = desc->outputIdx; - - return Success; -} - - -/* AES operations follow the buffer sequence of KEY -> (IV) -> Input -> Output - */ -static Error caamAes(struct DescStruct* desc) -{ - struct buffer* ctx[3]; - struct buffer* iv[3]; - Value ofst = 0; - Error err; - UINT4 i, totalSz = 0; - int ctxIdx = 0; - int ivIdx = 0; - int offset = 0; - int align = 1; - int sz = 0; - - int ctxSz = desc->ctxSz; - - if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { - return IllegalStatusNumber; - } - - if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) { - return ArgumentError; - } - - /* get key */ - for (i = 0; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->ctxBuf; - - if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { - ctx[ctxIdx] = buf; - sz += buf->dataSz; - - memcpy((unsigned char*)&local[offset], - (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz); - offset += ctx[ctxIdx]->dataSz; - ctxIdx++; - } - else { - break; - } - } - - /* sanity checks on size of key */ - if (sz > ctxSz) { - return SizeIsTooLarge; - } - if (ctxSz > (MAX_CTX * sizeof(UINT4)) - 16) { - return ArgumentError; - } - - /* Flush cache of ctx buffer then : - Add KEY Load command 0x0220000X - Add address to read key from 0xXXXXXXXX */ - ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); - - /* get IV if needed by algorithm */ - switch (desc->type) { - case CAAM_AESECB: - break; - - case CAAM_AESCTR: - ofst = 0x00001000; - /* fall through because states are the same only the offset changes */ - - case CAAM_AESCBC: - { - int maxSz = 16; /* default to CBC/CTR max size */ - - sz = 0; - offset = 0; - for (; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->iv; - - if (sz < maxSz) { - iv[ivIdx] = buf; - - if (buf->dataSz + sz > maxSz) { - return SizeIsTooLarge; - } - - sz += buf->dataSz; - memcpy((unsigned char*)&local[offset], - (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz); - offset += iv[ivIdx]->dataSz; - ivIdx++; - } - else { - break; - } - } - - if (sz != maxSz) { - /* invalid IV size */ - return SizeIsTooLarge; - } - - ASP_FlushCaches((Address)desc->iv, maxSz); - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + maxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); - } - break; - - default: - return OperationNotImplemented; - } - - /* write operation */ - if (desc->idx + 1 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | - CAAM_ALG_UPDATE | desc->state; - - /* find output buffers */ - if (caamAesOutSz(desc, i) != Success) { - return SizeIsTooLarge; - } - - /* set alignment constraints */ - if (desc->type == CAAM_AESCBC || desc->type == CAAM_AESECB) { - align = 16; - } - - /* indefinite loop for input/output buffers */ - desc->headIdx = desc->idx; - desc->output = 0; - offset = 0; /* store left over amount for output buffer */ - do { - desc->idx = desc->headIdx; /* reset for each loop */ - - /* add a single input buffer (multiple ones was giving deco watch dog - * time out errors on the FIFO load of 1c. - * @TODO this could be a place for optimization if more data could be - * loaded in at one time */ - if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) { - return TransferFailed; - } - totalSz += sz; - - if (caamAesOutput(desc, &offset, sz) != Success) { - return TransferFailed; - } - - /* store updated IV */ - if (ivIdx > 0) { - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | 16; - desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); - } - - if ((err = caamDoJob(desc)) != Success) { - return err; - } - ASP_FlushCaches((Address)desc->iv, 16); - } while (desc->lastIdx < desc->DescriptorCount || offset > 0); - - /* flush output buffers */ - for (i = desc->outputIdx; i < desc->lastIdx; i++) { - ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); - } - - /* handle case with IV */ - if (ivIdx > 0) { - unsigned char* pt = (unsigned char*)desc->iv; - ASP_FlushCaches((Address)pt, 16); - for (i = 0; i < ivIdx; i++) { - memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); - pt += iv[i]->dataSz; - ASP_FlushCaches(iv[i]->data, iv[i]->dataSz); - } - } - - return Success; -} - - -/****************************************************************************** - CAAM AEAD Operations - ****************************************************************************/ - -/* AEAD operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> (AD) - * -> Input -> Output - * - */ -static Error caamAead(struct DescStruct* desc) -{ - struct buffer* ctx[3]; - struct buffer* iv[3]; - Value ofst = 0; - UINT4 state = CAAM_ALG_INIT; - UINT4 totalSz = 0; - Error err; - UINT4 i; - int ctxIdx = 0; - int ivIdx = 0; - int offset = 0; - int sz = 0; - int ivSz = 32; /* size of B0 | CTR0 for CCM mode */ - int ctxSz = desc->ctxSz; - int align = 16; /* input should be multiples of 16 bytes unless is final */ - int opIdx; - - if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { - return IllegalStatusNumber; - } - - /* sanity check is valid AES key size */ - if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) { - return ArgumentError; - } - - /* get key */ - for (i = 0; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->ctxBuf; - - if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { - ctx[ctxIdx] = buf; - sz += buf->dataSz; - - memcpy((unsigned char*)&local[offset], - (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz); - offset += ctx[ctxIdx]->dataSz; - ctxIdx++; - } - else { - break; - } - } - - /* sanity checks on size of key */ - if (sz > ctxSz) { - return SizeIsTooLarge; - } - - /* Flush cache of ctx buffer then : - Add KEY Load command 0x0220000X - Add address to read key from 0xXXXXXXXX */ - ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); - - desc->headIdx = desc->idx; - desc->output = 0; - offset = 0; /* store left over amount for output buffer */ - do { - desc->idx = desc->headIdx; /* reset for each loop */ - - /* write operation */ - if (desc->idx + 1 > MAX_DESC_SZ) { - return TransferFailed; - } - opIdx = desc->idx; - desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | state | desc->type | - desc->state; - - /* get IV if needed by algorithm */ - switch (desc->type) { - case CAAM_AESCCM: - if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { - sz = 0; - offset = 0; - for (; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->iv; - - if (sz < ivSz) { - iv[ivIdx] = buf; - - if (buf->dataSz + sz > ivSz) { - return SizeIsTooLarge; - } - - sz += buf->dataSz; - memcpy((unsigned char*)&local[offset], - (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz); - offset += iv[ivIdx]->dataSz; - ivIdx++; - } - else { - break; - } - } - - if (sz != ivSz) { - /* invalid IV size */ - return SizeIsTooLarge; - } - offset = 0; - } - - ASP_FlushCaches((Address)desc->iv, ivSz); - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) - + ivSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); - break; - - default: - return OperationNotImplemented; - } - - - /********* handle AAD -- is only done with Init **********************/ - if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { - if ((desc->type == CAAM_AESCCM) && (desc->aadSz > 0)) { - /* set formatted AAD buffer size for CCM */ - ASP_FlushCaches((Address)desc->aadSzBuf, sizeof(desc->aadSzBuf)); - desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | - FIFOL_TYPE_AAD + desc->aadSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->aadSzBuf); - - /* now set aadSz to unformatted version for getting buffers */ - if (desc->aadSz == 2) { - unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = (((UINT4)pt[0] & 0xFF) << 8) | - ((UINT4)pt[1] & 0xFF); - } - else { - unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = (((UINT4)pt[2] & 0xFF) << 24) | - (((UINT4)pt[3] & 0xFF) << 16) | - (((UINT4)pt[4] & 0xFF) << 8) | - ((UINT4)pt[5] & 0xFF); - } - } - - /* get additional data buffers */ - if (desc->aadSz > 0) { - sz = 0; - for (; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - if (sz < desc->aadSz) { - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->lastFifo = desc->idx; - desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | - FIFOL_TYPE_AAD + buf->dataSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); - sz += buf->dataSz; - } - else { - break; - } - } - - /* flush AAD from FIFO and pad it to 16 byte block */ - desc->desc[desc->lastFifo] |= FIFOL_TYPE_FC1; - } - - /* find output buffers */ - if (caamAesOutSz(desc, i) != Success) { - return SizeIsTooLarge; - } - } - - /* handle alignment constraints on input */ - if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) { - return TransferFailed; - } - totalSz += sz; - - /* handle output buffers */ - if (caamAesOutput(desc, &offset, sz) != Success) { - return TransferFailed; - } - - /* store updated IV, if is last then set offset and final for MAC */ - if ((desc->lastIdx == desc->DescriptorCount) && (offset == 0)) { - ivSz = 16; - if (desc->state == CAAM_ENC) { - ofst = 32 << 8; /* offset is in 15-8 bits */ - } - else { - ofst = 0; - } - desc->desc[opIdx] |= CAAM_ALG_FINAL; - } - else { - /* if not final then store and use ctr and encrypted ctr from - context dword 2,3 and 4,5. Also store MAC and AAD info from - context dword 6. */ - ivSz = 56; - ofst = 0; - } - - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | ivSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); - - if ((err = caamDoJob(desc)) != Success) { - return err; - } - state = CAAM_ALG_UPDATE; - } while (desc->lastIdx < desc->DescriptorCount || offset > 0); - - /* flush output buffers */ - for (i = desc->outputIdx; i < desc->lastIdx; i++) { - ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); - } - - /* handle case with IV (This is also the output of MAC with AES-CCM) */ - if (ivIdx > 0) { - unsigned char* pt = (unsigned char*)desc->iv; - ASP_FlushCaches((Address)pt, ivSz); - for (i = 0; i < ivIdx; i++) { - memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); - pt += iv[i]->dataSz; - ASP_FlushCaches(iv[i]->data, iv[i]->dataSz); - } - } - - return Success; -} - - -/****************************************************************************** - CAAM SHA Operations - ****************************************************************************/ -static int shaSize(struct DescStruct* desc) -{ - /* sanity check on dataSz for context */ - switch (desc->type) { - case CAAM_MD5: - return CAAM_MD5_CTXSZ; - - case CAAM_SHA: - return CAAM_SHA_CTXSZ; - - case CAAM_SHA224: - return CAAM_SHA224_CTXSZ; - - case CAAM_SHA256: - return CAAM_SHA256_CTXSZ; - - case CAAM_SHA384: - return CAAM_SHA384_CTXSZ; - - case CAAM_SHA512: - return CAAM_SHA512_CTXSZ; - - default: - return 0; - } -} - -/* SHA operations - * start: the index to start traversing through buffers. It's needed to allow - * for HMAC to reuse this code. +/* ECDSA generate black key * * return Success on success. All other return values are considered a fail * case. */ -static Error caamSha(struct DescStruct* desc, int start) +int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]) { - struct buffer* ctx[3]; Error err; - UINT4 i; - int sz = 0; - int ctxIdx = 0; - int offset = 0; + unsigned int part = 0; + unsigned int isBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int phys; + void *vaddr[2]; - int ctxSz = shaSize(desc); - - /* get context */ - for (i = start; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)desc->iv; - - if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { - ctx[ctxIdx] = buf; - sz += buf->dataSz; - - if (ctx[ctxIdx]->dataSz + offset > (MAX_CTX * sizeof(UINT4))) { - return SizeIsTooLarge; - } - memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[ctxIdx]->data, - ctx[ctxIdx]->dataSz); - offset += ctx[ctxIdx]->dataSz; - ctxIdx++; - } - else { - break; - } + if (args != NULL) { + isBlackKey = args[0]; + pdECDSEL = args[1]; } - if (sz > ctxSz || ctxSz > (MAX_CTX * sizeof(UINT4))) { - return SizeIsTooLarge; + vaddr[0] = NULL; + vaddr[1] = NULL; + + desc->desc[desc->idx++] = pdECDSEL; + if (isBlackKey == 1) { + /* create secure partition for private key out */ + part = caamFindUnusuedPartition(); + if (part < 0) { + WOLFSSL_MSG("error finding an unused partition for new key"); + return -1; + } + + /* create and claim the partition */ + err = caamCreatePartition(part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK | + CAAM_SM_CSP | CAAM_SM_ALL_RW); + if (err != Success) { + WOLFSSL_MSG("error creating partition for secure ecc key"); + return -1; + } + + /* map secure partition to virtual address */ + phys = (CAAM_PAGE + (part << 12)); + buf[0].TheAddress = phys; + desc->desc[desc->idx++] = phys; + + /* public x,y out */ + buf[1].TheAddress = buf[0].TheAddress + BLACK_KEY_MAC_SZ + buf[0].Length; + desc->desc[desc->idx++] = phys + BLACK_KEY_MAC_SZ + buf[0].Length; + } + else { + vaddr[0] = CAAM_ADR_MAP(0, buf[0].Length, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[0], buf[0].Length); + + vaddr[1] = CAAM_ADR_MAP(0, buf[1].Length, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], buf[1].Length); } - ASP_FlushCaches((Address)desc->iv, ctxSz); - /*Manage Context (current digest + 8 byte running message length)*/ - if ((desc->state & CAAM_ALG_INIT) != CAAM_ALG_INIT) { - /* don't load into the class 2 context register on inti. - Found that loading in caused context to not get set. */ - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2) + ctxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (isBlackKey == 1) { + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; } + desc->desc[desc->idx++] |= CAAM_PKHA_ECC; - /* add operation command */ - desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS2 | desc->state | - desc->type; - - /* Check case where there is no input. - In all cases the FIFO Load should be flushed. */ - if (i == desc->DescriptorCount) { - desc->lastFifo = desc->idx; - if (desc->idx + 1 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS2 | - FIFOL_TYPE_MSG | CAAM_IMM; - } - - /* save index for looping over input */ - desc->headIdx = desc->idx; do { - desc->idx = desc->headIdx; /* reset for each loop */ - if (i < desc->DescriptorCount) { - /* input must be a multiple of 64 bytes unless in final call */ - if (((desc->state & CAAM_ALG_FINAL) == CAAM_ALG_FINAL)) { - if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | - FIFOL_TYPE_MSG), 0, 1, &i) < 0) { - return TooManyBuffers; - } - } - else { - if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | - FIFOL_TYPE_MSG), 0, 64, &i) < 0) { - return TooManyBuffers; - } - } - } + err = caamDoJob(desc); + } while (err == CAAM_WAITING); - desc->desc[desc->lastFifo] |= FIFOL_TYPE_LC2; - - /* set context out */ - if (desc->idx + 2 > MAX_DESC_SZ) { - return TransferFailed; - } - desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS2 + ctxSz; - desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); - - if ((err = caamDoJob(desc)) != Success) { - return err; - } - /* flush context output for each loop */ - ASP_FlushCaches((Address)desc->iv, ctxSz); - } while (i < desc->DescriptorCount); - - /* store context to buffers */ - { - unsigned char* pt = (unsigned char*)desc->iv; - for (i = 0; i < ctxIdx; i++) { - memcpy((unsigned char*)ctx[i]->data, pt, ctx[i]->dataSz); - pt += ctx[i]->dataSz; - ASP_FlushCaches(ctx[i]->data, ctx[i]->dataSz); - } + if (isBlackKey == 1) { + /* store partition number holding black keys */ + if (err != Success) + caamFreePart(part); + else + args[2] = part; + } + else { + /* copy non black keys out to buffers */ + CAAM_ADR_UNMAP(vaddr[0], buf[0].TheAddress, buf[0].Length, 1); + CAAM_ADR_UNMAP(vaddr[1], buf[1].TheAddress, buf[1].Length, 1); } - return Success; + return err; +} + + + +/* ECDSA verify signature + * + * return Success on success. All other return values are considered a fail + * case. + */ +int caamECDSAVerify(DESCSTRUCT* desc, CAAM_BUFFER* buf, int sz, + unsigned int args[4]) +{ + unsigned int isBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int msgSz = 0; + unsigned int vidx = 0; + unsigned int L; + int i = 0; + Error err; + void *vaddr[MAX_ECDSA_VERIFY_ADDR]; + + if (args != NULL) { + isBlackKey = args[0]; + pdECDSEL = args[1]; + msgSz = args[2]; + } + + if (sz > MAX_ECDSA_VERIFY_ADDR) { + return -1; + } + + if (pdECDSEL == 0) { + return -1; + } + else { + L = args[3]; /* keysize */ + desc->desc[desc->idx++] = pdECDSEL; + } + + /* public key */ + if (!isBlackKey) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx = vidx + 1; + } + else { + desc->desc[desc->idx++] = desc->buf[i].data; + } + i = i + 1; + + /* message */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx = vidx + 1; i = i + 1; + + /* r */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx = vidx + 1; i = i + 1; + + /* s */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx = vidx + 1; i = i + 1; + + /* tmp buffer */ + vaddr[vidx] = CAAM_ADR_MAP(0, 2*L, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], 2*L); + if (msgSz > 0) { + desc->desc[desc->idx++] = msgSz; + } + + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (msgSz > 0) { + desc->desc[desc->idx] |= CAAM_ECDSA_MESREP_HASHED; + } + desc->desc[desc->idx++] |= CAAM_PKHA_ECC; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + vidx = 0; i = 0; + if (!isBlackKey) { + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + } + i = i + 1; + + /* msg , r, s, tmp */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + i = i + 1; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + i = i + 1; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + i = i + 1; + CAAM_ADR_UNMAP(vaddr[vidx++], 0, 2*L, 0); + + return err; +} + + +/* ECDSA generate signature + * + * return Success on success. All other return values are considered a fail + * case. + */ +int caamECDSASign(DESCSTRUCT* desc, int sz, unsigned int args[4]) +{ + Error err; + unsigned int isBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int msgSz = 0; + unsigned int vidx = 0; + int i = 0; + void *vaddr[MAX_ECDSA_SIGN_ADDR]; + + if ((args == NULL) || (sz > MAX_ECDSA_SIGN_ADDR)) { + return -1; + } + + isBlackKey = args[0]; + pdECDSEL = args[1]; + msgSz = args[2]; + if (pdECDSEL == 0) { + return -1; + } + + /* using parameters already in hardware */ + desc->desc[desc->idx++] = pdECDSEL; + + /* private key */ + if (isBlackKey != 1) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + #if 0 + { + unsigned int z; unsigned char* pt; + printf("private :"); + pt = (unsigned char*)desc->buf[i].data; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + vidx++; + } + else { + desc->desc[desc->idx++] = desc->buf[i].data; + } + i++; + + for (; i < sz; i = i + 1) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + #if 0 + { + unsigned int z; + unsigned char *pt = (unsigned char*)vaddr[vidx]; + printf("input index %d/%d\n", i, sz); + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; + } + + desc->desc[desc->idx++] = msgSz; + + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (isBlackKey) { /* set flag to use AES-CCM with black key */ + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; + } + + /* add protinfo to operation command */ + desc->desc[desc->idx++] |= CAAM_ECDSA_MESREP_HASHED | CAAM_PKHA_ECC; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + vidx = 0; i = 0; + if (!isBlackKey) { + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); + } + i++; + + /* msg */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 0); i++; + + /* copy out the r and s values */ + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 1); i++; + CAAM_ADR_UNMAP(vaddr[vidx++], desc->buf[i].data, desc->buf[i].dataSz, 1); i++; + + return err; +} + + +/* ECDH generate shared secret + * + * return Success on success. All other return values are considered a fail + * case. + */ +int caamECDSA_ECDH(DESCSTRUCT* desc, int sz, unsigned int args[4]) +{ + Error err; + unsigned int isBlackKey = 0; + unsigned int peerBlackKey = 0; + unsigned int pdECDSEL = 0; + unsigned int vidx = 0; + int i = 0; + void* vaddr[sz]; + + if (args != NULL) { + isBlackKey = args[0]; + peerBlackKey = args[1]; + pdECDSEL = args[2]; + } + + if (pdECDSEL == 0) { + return -1; + } + else { + /* using parameters already in hardware */ + desc->desc[desc->idx++] = pdECDSEL; + } + + /* public key */ + if (!peerBlackKey) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + #if 0 + { + unsigned int z; byte* pt; + printf("pubkey :"); + pt = (byte*)desc->buf[i].data; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + vidx++; + } + else { + desc->desc[desc->idx++] = desc->buf[i].data; + } + i++; + + /* private key */ + if (isBlackKey != 1) { + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + #if 0 + { + unsigned int z; byte* pt; + printf("private :"); + pt = (byte*)desc->buf[i].data; + for (z = 0; z < desc->buf[i].dataSz; z++) + printf("%02X", pt[z]); + printf("\n"); + } + #endif + vidx++; + } + else { + desc->desc[desc->idx++] = desc->buf[i].data; + } + i++; + + /* shared output */ + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + i++; vidx++; + + /* add protinfo to operation command */ + desc->startIdx = desc->idx; + + /* add operation command OPTYPE PROTOID */ + desc->desc[desc->idx] = CAAM_OP | CAAM_PROT_UNIDI | desc->type; + if (isBlackKey == 1) { + desc->desc[desc->idx] |= CAAM_PKHA_ENC_PRI_AESCCM; + } + + /* add protinfo to operation command */ + desc->desc[desc->idx++] |= CAAM_PKHA_ECC; + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + vidx = 0; i = 0; + if (pdECDSEL == 0) { + /* unmap prime key */ + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; i++; + } + + if (peerBlackKey != 1) { + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; + } + i++; + + if (isBlackKey != 1) { + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; + } + i++; + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 1); + vidx++; i++; + + if (pdECDSEL == 0) { + /* unmap A , B*/ + CAAM_ADR_UNMAP(vaddr[vidx], desc->buf[i].data, desc->buf[i].dataSz, 0); + vidx++; i++; + } + return err; } /****************************************************************************** - CAAM TRNG Operations + IODevice Start, Transfer and Finish Buffer ****************************************************************************/ - -/* If Entropy is not ready then return Waiting */ -static Error caamRng(struct DescStruct* desc) +/* If Entropy is not ready then return CAAM_WAITING */ +int caamTRNG(unsigned char *out, int outSz) { int sz = 0; - int i; - - Address reg; /* RTENT reg to read */ - int ofst = sizeof(UINT4); + CAAM_ADDRESS reg; /* RTENT reg to read */ + unsigned char* local; + int ofst = sizeof(unsigned int); /* Check ENT_VAL bit to make sure entropy is ready */ - if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != - CAAM_ENTVAL) { - return Waiting; + if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != CAAM_ENTVAL) { + return CAAM_WAITING; } /* check state of TRNG */ @@ -1332,382 +1290,222 @@ static Error caamRng(struct DescStruct* desc) } /* read entropy from RTENT registers */ - reg = CAAM_RTENT0; + reg = CAAM_RTENT0; + sz = outSz; + local = out; - for (i = 0; i < desc->DescriptorCount; i++) { - struct buffer* buf = &desc->buf[i]; - unsigned char* local = (unsigned char*)buf->data; - sz = buf->dataSz; - - while (sz > 3 && reg <= CAAM_RTENT11) { - *((UINT4*)local) = CAAM_READ(reg); - reg += ofst; - local += ofst; - sz -= ofst; - } - - if (reg > CAAM_RTENT11 && sz > 0) { - return SizeIsTooLarge; - } - - /* handle non word32 size amount left over */ - if (sz > 0) { - UINT4 tmp = CAAM_READ(reg); - memcpy(local, (unsigned char*)&tmp, sz); - } - - ASP_FlushCaches(buf->data, buf->dataSz); + while (sz > 3 && reg <= CAAM_RTENT_MAX) { + unsigned int data = CAAM_READ(reg); + *((unsigned int*)local) = data; + reg += ofst; + local += ofst; + sz -= ofst; } + if (reg > CAAM_RTENT_MAX && sz > 0) { + return -1; + } - /* read RTENT11 to trigger new entropy generation */ - if (reg != CAAM_RTENT11) { - CAAM_READ(CAAM_RTENT11); + /* handle non unsigned int size amount left over */ + if (sz > 0) { + unsigned int tmp = CAAM_READ(reg); + memcpy(local, (unsigned char*)&tmp, sz); + } + + /* read the max RTENT to trigger new entropy generation */ + if (reg != CAAM_RTENT_MAX) { + CAAM_READ(CAAM_RTENT_MAX); } return Success; } -/****************************************************************************** - IODevice Start, Transfer and Finish Buffer - ****************************************************************************/ -/* args[0] holds the state such as encrypt/decrypt or init/update/final - * args[1] holds the ctx/key size - * args[2] holds the input size - * args[3] dependent on algo (such as AAD size with AES-CCM) */ -static Error caamTransferStart(IODeviceVector ioCaam, - Value type, const volatile Value args[4]) +/* cover a plain text key and make it a black key */ +int caamKeyCover(DESCSTRUCT* desc, int sz, unsigned int args[4]) { - struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)ioCaam; - struct DescStruct* desc; + Error err; + unsigned int vidx = 0; + int i = 0; + void* vaddr[2]; - /* currently only one desc is available for use */ - desc = &local->DescArray[0]; + (void)args; - /* check if the desc is idle before using */ - if (GetIORequestStatus((IORequest)desc) != IdleIORequest) { - return ResourceNotAvailable; + if (sz > 2) { + return -1; } + /* add input key */ + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1) + + desc->buf[i].dataSz; + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz, 1); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz); + vidx++; + i++; + + /* add output */ + desc->desc[desc->idx++] = (CAAM_FIFO_S | CAAM_CLASS1 | desc->state) + + desc->buf[i].dataSz; + vaddr[vidx] = CAAM_ADR_MAP(desc->buf[i].data, desc->buf[i].dataSz + + BLACK_KEY_MAC_SZ, 0); + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[vidx], + desc->buf[i].dataSz + BLACK_KEY_MAC_SZ); + +#if 0 + /* sanity check can we load it? used for debugging and testing */ + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | 0x500000) + + desc->buf[i].dataSz; + desc->desc[desc->idx++] = CAAM_ADR_TO_PHYSICAL(vaddr[1], desc->buf[1].dataSz); +#endif + + do { + err = caamDoJob(desc); + } while (err == CAAM_WAITING); + + CAAM_ADR_UNMAP(vaddr[0], desc->buf[0].data, desc->buf[0].dataSz, 0); + CAAM_ADR_UNMAP(vaddr[1], desc->buf[1].data, desc->buf[1].dataSz + + BLACK_KEY_MAC_SZ, 1); + return err; +} + + +/****************************************************************************** + Init + ****************************************************************************/ + +/* initialize a DESCSTRUCT for an operation */ +void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4], + CAAM_BUFFER* buf, int sz) +{ + int i; + + desc->type = type; desc->idx = 0; desc->output = 0; desc->ctxOut = 0; desc->outputIdx = 0; desc->alignIdx = 0; desc->lastFifo = 0; - desc->state = args[0]; - desc->ctxSz = args[1]; - desc->inputSz = args[2]; + if (args == NULL) { + desc->state = 0; + desc->ctxSz = 0; + desc->inputSz = 0; + } + else { + desc->state = args[0]; + desc->ctxSz = args[1]; + desc->inputSz = args[2]; + } desc->aadSz = 0; + desc->DescriptorCount = sz; + desc->startIdx = 0; desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/ - switch (type) { - case CAAM_AESECB: - case CAAM_AESCBC: - if (desc->inputSz % 16 != 0) { - return ArgumentError; - } - /* fall through to break */ - case CAAM_AESCTR: - break; - - case CAAM_AESCCM: - memset((unsigned char*)desc->aadSzBuf, 0, sizeof(desc->aadSzBuf)); - if (args[3] > 0) { - /* encode the length in */ - if (args[3] <= 0xFEFF) { - unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = 2; - pt[0] = ((args[3] & 0xFF00) >> 8); - pt[1] = (args[3] & 0x00FF); - } - else if (args[3] <= 0xFFFFFFFF) { - unsigned char* pt = (unsigned char*)desc->aadSzBuf; - desc->aadSz = 6; - pt[0] = 0xFF; pt[1] = 0xFE; - pt[2] = ((args[3] & 0xFF000000) >> 24); - pt[3] = ((args[3] & 0x00FF0000) >> 16); - pt[4] = ((args[3] & 0x0000FF00) >> 8); - pt[5] = (args[3] & 0x000000FF); - } - } - break; - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - break; - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - break; - - case CAAM_ENTROPY: - break; - - default: - /* unknown type */ - return UsageNotSupported; + for (i = 0; i < sz; i = i + 1) { + desc->buf[i].data = buf[i].TheAddress; + desc->buf[i].dataSz = buf[i].Length; } - - desc->DescriptorCount = 0; - desc->type = type; - desc->running = true; - StartIORequest((IORequest)desc); - - /* For now only require READ permissions */ - SetIORequestBufferPermissions((IORequest)desc, MEMORY_READ); - return Success; } -static Error caamTransferBuffer(IODeviceVector TheIODeviceVector, - IORequest req, IODescriptor NewIODescriptor, - Address data, Address dataSz) +int InitCAAM(void) { - struct DescStruct* desc = (struct DescStruct*)req; - Error err; - - switch (desc->type) { - case CAAM_AESECB: - case CAAM_AESCTR: - case CAAM_AESCBC: - case CAAM_AESCCM: - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - case CAAM_ENTROPY: - { /* set buffer for transfer finish */ - struct buffer* buf; - if (desc->DescriptorCount >= MAX_BUF) { - return TooManyBuffers; - } - buf = &desc->buf[desc->DescriptorCount]; - buf->data = data; - buf->dataSz = dataSz; - } - err = Success; - break; - - default: - err = UsageNotSupported; - } - - if (err != Success) { - desc->running = false; - DismissIORequest(req); - return err; - } - - desc->DescriptorCount++; - return Success; -} - - -static Error caamTransferFinish(IODeviceVector ioCaam, IORequest req) -{ - struct DescStruct* desc = (struct DescStruct*)req; Error ret; - /* construct desc */ - switch (desc->type) { - case CAAM_AESECB: - case CAAM_AESCTR: - case CAAM_AESCBC: - ret = caamAes(desc); - break; - - case CAAM_AESCCM: - ret = caamAead(desc); - break; - - case CAAM_MD5: - case CAAM_SHA: - case CAAM_SHA224: - case CAAM_SHA256: - case CAAM_SHA384: - case CAAM_SHA512: - ret = caamSha(desc, 0); - break; - - case CAAM_ENTROPY: - ret = caamRng(desc); - break; - - case CAAM_BLOB_ENCAP: - case CAAM_BLOB_DECAP: - ret = caamBlob(desc); - break; - - default: - ret = UsageNotSupported; - } - - desc->running = false; - DismissIORequest(req); - return ret; -} - - -/****************************************************************************** - IODevice Interrupt and Init - ****************************************************************************/ - -static Error caamTransferWrite(IODeviceVector ioCaam, - IORequest req, Value dataSz, const volatile Value *data) -{ - DismissIORequest(req); - return UsageNotSupported; -} - - -static void caamTransferAbort(IODeviceVector ioCaam, IORequest req) -{ - DismissIORequest(req); -} - - -static void caamTransferRecall(IODeviceVector ioCaam, IODescriptor req) -{ - -} - - -static void HandleInterrupt(Address id) -{ - struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)id; - Value InterruptStatus = INTERRUPT_AtomicWrite(&local->InterruptStatus, 0); - int i; - - /* Loop through descriptors and try to dismiss them */ - for (i = 0; i < DESC_COUNT; i++) { - struct DescStruct* desc = &local->DescArray[i]; - if (InterruptStatus & (1 << i)) { - desc->running = false; - if (GetIORequestStatus((IORequest)desc) == IORequestSuspended) { - ContinueIORequest((IORequest)desc); - } - else { - DismissIORequest((IORequest)desc); - } - } - } -} - - -static Error caamCreate(IODeviceVector ioCaam) -{ - return Success; -} - - -void InitCAAM(void) -{ - /* get IO vector and set it up */ - IODeviceVector ioCaam = &caam.caamVector; - unsigned int reg; - int i; - Error ret; - - - ioCaam->Create = &caamCreate; - ioCaam->ReadRegister = &caamReadRegister; - ioCaam->WriteRegister = &caamWriteRegister; - - ioCaam->TransferStart = &caamTransferStart; - ioCaam->TransferBuffer = &caamTransferBuffer; - ioCaam->TransferWrite = &caamTransferWrite; - ioCaam->TransferFinish = &caamTransferFinish; - ioCaam->TransferAbort = &caamTransferAbort; - ioCaam->TransferRecall = &caamTransferRecall; -#ifdef HARDWARE_CACHE_COHERENCY - ioCaam->IOSynchronizationNotRequired = 1; -#endif - - RegisterIODeviceVector(ioCaam, DRIVER_NAME); - RequestIOTerminationTask(ioCaam, 10); - - /* Initialize descriptors */ - for (i = 0; i < BUFFER_COUNT; i++) { - InitializeIODescriptor(ioCaam, &caam.IODescriptorArray[i]); - } - - /* Initialize Descriptors */ - for (i = 0; i < DESC_COUNT; i++) { - InitializeIORequest(ioCaam, &caam.DescArray[i].TheIORequest, - IOREQUEST_STANDARD); - caam.DescArray[i].running = false; - caam.DescArray[i].caam = &caam; - } - - - /* call interrupt to make IORequests available */ - caam.InterruptStatus = 0; - INTERRUPT_InitCall(&caam.HandleInterruptCall, - &HandleInterrupt, "Start up CAAM IORequest"); - - /* set clock speed for CAAM. Setting it here to allow for restricting - access */ - #define REGS_CCM_BASE (0xf20c4000) - #define HW_CCM_CCGR0_ADDR (0xf20c4068) - #define CG(x) (3 << (x*2)) - - reg = CG(6) | CG(5) | CG(4); - *(volatile unsigned int*)HW_CCM_CCGR0_ADDR = - *(volatile unsigned int*)HW_CCM_CCGR0_ADDR | reg; - - /* set up job ring */ - - /* @TODO create partition in physical memory for job rings - current partition security is set to the default */ - for (i = 1; i < CAAM_PAGE_MAX; i++) { - ret = caamCreatePartition(i, i); - if (ret == 0) { - break; - } - - if (ret != MemoryMapMayNotBeEmpty) { - INTERRUPT_Panic(); - } - } - + /* map to memory addresses needed for accessing CAAM */ + ret = CAAM_SET_BASEADDR(); if (ret != 0) { - INTERRUPT_Panic(); + return ret; } - caam.ring.page = i; - caam.ring.JobIn = (CAAM_PAGE + (i << 12)); - caam.ring.JobOut = caam.ring.JobIn + 16; - caam.ring.Desc = caam.ring.JobOut + 16; + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("CHANUM_MS = 0x%08X\n", CAAM_READ(0x0FF0)); + printf("DECO0MIDR_MS = 0x%08X\n", CAAM_READ(0x00A0)); + printf("SCFGR = 0x%08X\n", CAAM_READ(0x000C)); + print_jdkek(); + printSecureMemoryInfo(); + printf("JR0MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0010), + CAAM_READ(0x0014)); + printf("JR1MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0018), + CAAM_READ(0x001C)); + printf("JR2MIDR_MS, _LS = 0x%08X , 0x%08X\n", CAAM_READ(0x0020), + CAAM_READ(0x0024)); + #endif - /* set physical address of job rings */ - CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn ^ 0xF0000000); - CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut ^ 0xF0000000); + ret = Failure; + for (caam.ring.page = 1; caam.ring.page < 7; + caam.ring.page = caam.ring.page + 1) { + ret = caamCreatePartition(caam.ring.page, caam.ring.page, + CAAM_SM_CSP | CAAM_SM_ALL_RW); + if (ret == Success) + break; + } + if (ret != Success) { + return -1; + } - /* Initialize job ring sizes to 1 */ - CAAM_WRITE(CAAM_IRSR0, 1); - CAAM_WRITE(CAAM_ORSR0, 1); + caam.ring.JobIn = CAAM_PAGE + (caam.ring.page << 12U); + caam.ring.JobOut = caam.ring.JobIn + (CAAM_JOBRING_SIZE * + sizeof(unsigned int)); + caam.ring.Desc = caam.ring.JobOut + (2 * CAAM_JOBRING_SIZE * + sizeof(unsigned int)); + + CAAM_INIT_MUTEX(&caam.ring.jr_lock); + + caam.ring.VirtualIn = mmap_device_memory(NULL, + CAAM_JOBRING_SIZE * sizeof(unsigned int), + PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS, caam.ring.JobIn); + memset(caam.ring.VirtualIn, 0, CAAM_JOBRING_SIZE * sizeof(unsigned int)); + caam.ring.VirtualOut = mmap_device_memory(NULL, + 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int), + PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS, caam.ring.JobOut); + memset(caam.ring.VirtualOut, 0, 2 * CAAM_JOBRING_SIZE * sizeof(unsigned int)); + caam.ring.VirtualDesc = mmap_device_memory(NULL, + CAAM_DESC_MAX * CAAM_JOBRING_SIZE, + PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_SHARED | MAP_PHYS, caam.ring.Desc); + memset(caam.ring.VirtualDesc, 0, CAAM_DESC_MAX * CAAM_JOBRING_SIZE); + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("extra wolfssl debug - Setting JOB IN 0x%08X\n", caam.ring.JobIn); + printf("extra wolfssl debug - Setting JOB OUT 0x%08X\n", caam.ring.JobOut); + printf("extra wolfssl debug - Setting DESC 0x%08X\n", caam.ring.Desc); + #endif + CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn); + CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut); + + /* Initialize job ring sizes */ + CAAM_WRITE(CAAM_IRSR0, CAAM_JOBRING_SIZE); + CAAM_WRITE(CAAM_ORSR0, CAAM_JOBRING_SIZE); /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */ - CAAM_WRITE((CAAM_BASE | 0x0004), CAAM_READ(CAAM_BASE | 0x0004) | 0x40000000); + CAAM_WRITE(0x0004, CAAM_READ(0x0004) | 0x40000000); /* start up RNG if not already started */ if (caamInitRng(&caam) != 0) { + WOLFSSL_MSG("Error initializing RNG"); INTERRUPT_Panic(); + return -1; } + + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + print_jdkek(); + printf("FADR = 0x%08X\n", CAAM_READ(0x0FCC)); + printf("RTMCTL = 0x%08X\n", CAAM_READ(0x0600)); + #endif + WOLFSSL_MSG("Successfully initilazed CAAM driver"); + return 0; } -void (*__ghsentry_bspuserinit_InitCAAM)(void) = &InitCAAM; -#endif /* INTEGRITY */ +int CleanupCAAM() +{ + CAAM_FREE_MUTEX(&caam.ring.jr_lock); + CAAM_UNSET_BASEADDR(); + caamFreeAllPart(); + return 0; +} +#endif diff --git a/wolfcrypt/src/port/caam/caam_error.c b/wolfcrypt/src/port/caam/caam_error.c new file mode 100644 index 000000000..0a21ae291 --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_error.c @@ -0,0 +1,207 @@ +/* caam_error.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include "caam_driver.h" +#include "caam_error.h" + +/* return a negative value if CAAM reset needed */ +int caamParseCCBError(unsigned int error) +{ + int ret = 0; + switch((error >> 4) & 0xF) { + case 0: + WOLFSSL_MSG("\tCHAID: CCB"); + break; + + case 1: + WOLFSSL_MSG("\tCHAID: AESA"); + break; + + case 2: + WOLFSSL_MSG("\tCHAID: DESA"); + break; + + case 3: + WOLFSSL_MSG("\tCHAID: AFHA (ARC4)"); + break; + + case 4: + WOLFSSL_MSG("\tCHAID: MDHA hash"); + break; + + case 5: + WOLFSSL_MSG("\tCHAID: RNG - ERRID:"); + ret = -1; /* treat RNG errors as fatal */ + switch(error & 0xF) { + case 3: + WOLFSSL_MSG(" RNG instantiate error"); + break; + + case 4: + WOLFSSL_MSG(" RNG not instantiated error"); + break; + + case 5: + WOLFSSL_MSG(" RNG test instantiate error"); + break; + + case 6: + WOLFSSL_MSG(" RNG prediction resistance error"); + break; + + default: + WOLFSSL_MSG(" Unknown"); + } + break; + + case 8: + WOLFSSL_MSG("\tCHAID: PKHA"); + break; + + default: + WOLFSSL_MSG("\tCHAID: Unknown CCB error"); + } + return ret; +} + + +/* return a negative value for an error that requires CAAM reset */ +int caamParseDECOError(unsigned int error) +{ + int ret = 0; + switch (error & 0xFF) { + case 0x04: + WOLFSSL_MSG("\tInvalid Descriptor Command"); + break; + + case 0x06: + WOLFSSL_MSG("\tInvalid KEY Command"); + break; + + case 0x07: + WOLFSSL_MSG("\tInvalid Load Command"); + break; + + case 0x08: + WOLFSSL_MSG("\tInvalid Store Command"); + break; + + case 0x09: + WOLFSSL_MSG("\tInvalid Operation Command"); + break; + + case 0x82: + WOLFSSL_MSG("\tInvalid PRB setting"); + break; + + case 0x86: + WOLFSSL_MSG("\tVerify ECC/RSA signature fail"); + break; + + default: + WOLFSSL_MSG("\tUnknown error"); + } + return ret; +} + + +/* return a negative value if CAAM should be reset after error */ +int caamParseError(unsigned int error) +{ + int ret = 0; + + /* print out of index of error + unsigned int idx; + idx = (error >> 8) & 0xFF; + printf("idx of error = %d\n", idx); + */ + + if ((error & 0x40000000) > 0) { + WOLFSSL_MSG("[DECO Error]"); + ret = caamParseDECOError(error); + } + + if ((error & 0x20000000) > 0) { + WOLFSSL_MSG("[CCB Error]"); + ret = caamParseCCBError(error); + } + return ret; +} + + +/* parses a Job Ring Interrupt Status report + * returns 0 if there is no error */ +unsigned int caamParseJRError(unsigned int error) +{ + unsigned int err = (error >> 8) & 0x1F; + + if (error & 0x10) { + WOLFSSL_MSG("Job Ring Interrupt ENTER_FAIL"); + } + + if (error & 0x20) { + WOLFSSL_MSG("Job Ring Interrupt EXIT_FAIL"); + } + + switch (err) { + case 0x00: + /* no error */ + break; + + case 0x01: + WOLFSSL_MSG("Error writing status to output ring"); + break; + + case 0x03: + WOLFSSL_MSG("Bad input ring address"); + break; + + case 0x04: + WOLFSSL_MSG("Bad output ring address"); + break; + + case 0x05: + WOLFSSL_MSG("Fatal, invalid write to input ring"); + break; + + case 0x06: + WOLFSSL_MSG("Invalid write to output ring"); + break; + + case 0x07: + WOLFSSL_MSG("Job ring released before halted"); + break; + + case 0x08: + WOLFSSL_MSG("Removed too many jobs"); + break; + + case 0x09: + WOLFSSL_MSG("Added too many jobs"); + break; + + default: + WOLFSSL_MSG("Unknown error"); + break; + } + return err; +} + diff --git a/wolfcrypt/src/port/caam/caam_init.c b/wolfcrypt/src/port/caam/caam_init.c deleted file mode 100644 index 014341cd6..000000000 --- a/wolfcrypt/src/port/caam/caam_init.c +++ /dev/null @@ -1,289 +0,0 @@ -/* caam_init.c - * - * Copyright (C) 2006-2020 wolfSSL Inc. - * - * This file is part of wolfSSL. - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - */ - - -#include - -#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ - defined(WOLFSSL_IMX6_CAAM_BLOB) - -#include -#include -#include - -#define WC_CAAM_BLOB_SZ 48 - -#ifndef WC_CAAM_PASSWORD - #define WC_CAAM_PASSWORD "!systempassword" -#endif - -#if defined(__INTEGRITY) || defined(INTEGRITY) - #include - #include - static IODevice caam = NULLIODevice; -#endif - -#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) -#include -#include - -static void wc_caamBanner(void) -{ - printf("********* wolfSSL Version %s : Printing Out CAAM Information ********\n", - LIBWOLFSSL_VERSION_STRING); - printf("CAAM Status [0x%8.8x] = 0x%8.8x\n", - CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS)); - printf("CAAM Version MS Register [0x%8.8x] = 0x%8.8x\n", - CAAM_VERSION_MS, WC_CAAM_READ(CAAM_VERSION_MS)); - printf("CAAM Version LS Register [0x%8.8x] = 0x%8.8x\n", - CAAM_VERSION_LS, WC_CAAM_READ(CAAM_VERSION_LS)); - printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n", - CAMM_SUPPORT_MS, WC_CAAM_READ(CAMM_SUPPORT_MS)); - printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n", - CAMM_SUPPORT_LS, WC_CAAM_READ(CAMM_SUPPORT_LS)); - printf("********************************************************************\n\n"); -} -#endif - - -/* Allow runtime setting for CAAM IODevice in case user wants to use password - * at run time. - * - * returns 0 on success - * - * NOTE this is how IODevice is defined in INTEGRITY "typedef struct - * IODeviceStruct *IODevice;" - */ -int wc_caamSetResource(IODevice ioDev) -{ - WOLFSSL_MSG("Setting CAAM driver"); - caam = ioDev; - - return 0; -} - -/* Check hardware support - * - * returns 0 on success - */ -int wc_caamInit(void) -{ - int ret; - word32 reg; - - /* get the driver up */ - if (caam == NULLIODevice) { - WOLFSSL_MSG("Starting CAAM driver"); - if ((ret = (int)RequestResource((Object *)&caam, "wolfSSL_CAAM_Driver", - WC_CAAM_PASSWORD)) != (int)Success) { - WOLFSSL_MSG("Unable to get the CAAM IODevice, check password?"); - WOLFSSL_LEAVE("wc_caamInit: error from driver = ", ret); - ret = 0; /* not a hard failure because user can set resource */ - } - } - -#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) - /* print out CAAM version/info and wolfSSL version */ - wc_caamBanner(); -#endif - - /* check that for implemented modules - * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG */ - reg = WC_CAAM_READ(CAMM_SUPPORT_LS); - - #ifndef WC_NO_RNG - if (((reg & 0x000F0000) >> 16) > 0) { - WOLFSSL_MSG("Found CAAM RNG hardware module"); - if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) { - WOLFSSL_MSG("Error CAAM RNG has not been set up"); - } - } - #endif - - #ifndef NO_SHA256 - if ((reg & 0x0000F000) > 0) { - WOLFSSL_MSG("Found CAAM MDHA module"); - } - else { - WOLFSSL_MSG("Hashing not supported by CAAM"); - return WC_HW_E; - } - #endif - - #ifndef NO_AES - if ((reg & 0x0000000F) > 0) { - WOLFSSL_MSG("Found CAAM AES module"); - } - else { - WOLFSSL_MSG("AES not supported by CAAM"); - return WC_HW_E; - } - #endif - - (void)ret; - return 0; -} - - -int wc_caamFree(void) -{ - return 0; -} - - -word32 wc_caamReadRegister(word32 reg) -{ - Value out = 0; - - if (caam == NULLIODevice) { - WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); - return 0; - } - - if (ReadIODeviceRegister(caam, reg, &out) != Success) { - WOLFSSL_MSG("Error reading register\n"); - } - - return (word32)out; -} - -void wc_caamWriteRegister(word32 reg, word32 value) -{ - if (caam == NULLIODevice) { - WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); - return; - } - - if (WriteIODeviceRegister(caam, reg, value) != Success) { - WOLFSSL_MSG("Error writing to register\n"); - } -} - - -/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E - * in the case that the driver is waiting for a resource or RAN_BLOCK_E if - * waiting for entropy. */ -int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type) -{ - int ret; - if (caam == NULLIODevice) { - WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); - return WC_HW_E; - } - - if ((ret = SynchronousSendIORequest(caam, type, (const Value*)arg, buf)) - != Success) { - #if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) - printf("ret of SynchronousSendIORequest = %d type = %d\n", ret, type); - #endif - - /* if waiting for resource or RNG return waiting */ - if (ret == Waiting) { - WOLFSSL_MSG("Waiting on entropy from driver"); - return RAN_BLOCK_E; - } - - if (ret == ResourceNotAvailable) { - WOLFSSL_MSG("Waiting on CAAM driver"); - return WC_HW_WAIT_E; - } - - return WC_HW_E; - } - - (void)ret; - return 0; -} - - -int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz) -{ - Buffer in[3]; - word32 arg[4]; - int ret; - word32 local[2] = {0,0}; - - if (data == NULL || out == NULL || outSz == NULL || - *outSz < dataSz + WC_CAAM_BLOB_SZ) { - return BAD_FUNC_ARG; - } - - in[0].BufferType = DataBuffer; - in[0].TheAddress = (Address)local; - in[0].Length = sizeof(local); - - in[1].BufferType = DataBuffer; - in[1].TheAddress = (Address)data; - in[1].Length = dataSz; - - in[2].BufferType = DataBuffer | LastBuffer; - in[2].TheAddress = (Address)out; - in[2].Length = dataSz + WC_CAAM_BLOB_SZ; - - arg[2] = dataSz; - - if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_ENCAP)) != 0) { - WOLFSSL_MSG("Error with CAAM blob create"); - return ret; - } - - *outSz = dataSz + WC_CAAM_BLOB_SZ; - return 0; -} - - -int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz) -{ - Buffer in[3]; - word32 arg[4]; - int ret; - word32 local[2] = {0,0}; - - if (data == NULL || out == NULL || outSz == NULL || - *outSz < dataSz - WC_CAAM_BLOB_SZ) { - return BAD_FUNC_ARG; - } - - in[0].BufferType = DataBuffer; - in[0].TheAddress = (Address)local; - in[0].Length = sizeof(local); - - in[0].BufferType = DataBuffer; - in[0].TheAddress = (Address)data; - in[0].Length = dataSz; - - in[1].BufferType = DataBuffer | LastBuffer; - in[1].TheAddress = (Address)out; - in[1].Length = dataSz - WC_CAAM_BLOB_SZ; - - arg[2] = dataSz; - - if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_DECAP)) != 0) { - WOLFSSL_MSG("Error with CAAM blob create"); - return ret; - } - - *outSz = dataSz - WC_CAAM_BLOB_SZ; - return 0; -} - -#endif /* WOLFSSL_IMX6_CAAM */ - diff --git a/wolfcrypt/src/port/caam/caam_integrity.c b/wolfcrypt/src/port/caam/caam_integrity.c new file mode 100644 index 000000000..1cf93d5cd --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_integrity.c @@ -0,0 +1,1713 @@ +/* caam_integrity.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#if defined(__INTEGRITY) || defined(INTEGRITY) + +/* build into Integrity kernel */ +#include +#include "wolfssl/wolfcrypt/port/caam/caam_driver.h" + +#define CAAM_READ(reg) *(volatile unsigned int*)(reg) +#define CAAM_WRITE(reg, in) *(volatile unsigned int*)(reg) = (in); + +#define DESC_COUNT 1 +#define MAX_BUF 20 +#define BUFFER_COUNT (MAX_BUF * DESC_COUNT) + +/* CAAM descriptors can only be 64 unsigned ints */ +#define MAX_DESC_SZ 64 + +/* 64 byte buffer for when data crosses a page boundary */ +#define ALIGN_BUF 16 + +/* MAX_CTX is 64 bytes (sha512 digest) + 8 bytes (CAAM length value) */ +#define MAX_CTX 18 + +#define MIN_READ_REG 0xF2100000 +#define MAX_READ_REG 0XF2110000 + +struct JobRing { + Address JobIn; + Address JobOut; + Address Desc; + Value page; /* page allocation for descriptor to use */ +}; + +struct buffer { + Address data; + Address dataSz; +}; + +/* CAAM descriptor */ +struct DescStruct { + struct IORequestStruct TheIORequest; + struct CAAM_DEVICE* caam; + struct buffer buf[MAX_BUF]; /* buffers holding data input address */ + UINT4 desc[MAX_DESC_SZ]; /* max size of 64 word32 */ + UINT4 aadSzBuf[4]; /* Formatted AAD size for CCM */ + UINT4 alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page + align */ + UINT4 iv[MAX_CTX]; /* AES IV and also hash state */ + UINT4 ctxBuf[MAX_CTX]; /* key */ + Address output; /* address to output buffer */ + Address ctxOut; /* address to update buffer holding state */ + Value alignIdx;/* index for align buffer */ + Value idx; /* index for descriptor buffer */ + Value headIdx; /* for first portion of descriptor buffer */ + Value lastIdx; /* for last portion of descriptor buffer */ + Value outputIdx; /* idx to output buffer in "buf" */ + Value inputSz; /* size of input buffer */ + Value ctxSz; /* size of CTX/Key buffer */ + Value aadSz; /* AAD size for CCM */ + Value lastFifo; + Value type; + Value state; + Value DescriptorCount; + Boolean running; /* True if building/running descriptor is + in process */ +}; + +struct CAAM_DEVICE { + struct IODeviceVectorStruct caamVector; + struct IODescriptorStruct IODescriptorArray[BUFFER_COUNT]; + struct DescStruct DescArray[DESC_COUNT]; + volatile Value InterruptStatus; + CALL HandleInterruptCall; + struct JobRing ring; +}; + +#define DRIVER_NAME "wolfSSL_CAAM_Driver" + +static struct CAAM_DEVICE caam; + +/****************************************************************************** + Internal CAAM Job Ring and partition functions + ****************************************************************************/ + +/* flush job ring and reset */ +static Error caamReset(void) +{ + int t = 100000; /* time out counter for flushing job ring */ + + /* make sure interrupts are masked in JRCFGR0_LS register */ + CAAM_WRITE(CAAM_BASE | 0x1054, CAAM_READ(CAAM_BASE | 0x1054) | 1); + + /* flush and reset job rings using JRCR0 register */ + CAAM_WRITE(CAAM_BASE | 0x106C, 1); + + /* check register JRINTR for if halt is in progress */ + while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x104C) & 0x4) == 0x4)) t--; + if (t == 0) { + /*unrecoverable failure, the job ring is locked, up hard reset needed*/ + return NotRestartable; + } + + /* now that flush has been done restart the job ring */ + t = 100000; + CAAM_WRITE(CAAM_BASE | 0x106C, 1); + while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x106C) & 1) == 1)) t--; + if (t == 0) { + /*unrecoverable failure, reset bit did not return to 0 */ + return NotRestartable; + } + + /* reset most registers and state machines in CAAM using MCFGR register + also reset DMA */ + CAAM_WRITE(CAAM_BASE | 0x0004, 0x90000000); + + return Success; +} + +/* returns MemoryMapMayNotBeEmpty if page/par is already owned + * returns Success on success + * all other returns is an error state + */ +static Error caamCreatePartition(unsigned char page, unsigned char par) +{ + /* check ownership of partition */ + if ((CAAM_READ(CAAM_BASE | 0x1FBC) & (0x3 << (par * 2))) > 0) { + return MemoryMapMayNotBeEmpty; + } + + /* set generic all access permissions, gets reset later */ + CAAM_WRITE(CAAM_BASE | (0x1108 + (par * 16)), 0xF); + CAAM_WRITE(CAAM_BASE | (0x110C + (par * 16)), 0xF); + CAAM_WRITE(CAAM_BASE | (0x1104 + (par * 16)), 0xFF); + + /* check ownership of page */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); + /* wait for inquiry cmd to complete */ + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + } + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) == 0xC0) { + /* owns the page can dealloc it */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x2); + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) {} + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { + /* error while deallocating page */ + return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ + } + } + else { + /* check if owned by someone else */ + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) != 0) { + return MemoryMapMayNotBeEmpty; + } + } + + /* allocate page to partition */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | (par << 8) | 0x1); + /* wait for alloc cmd to complete */ + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + } + + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { + return MemoryOperationNotPerformed; + } + + /* double check ownership now of page */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); + /* wait for inquiry cmd to complete */ + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + } + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000000F) == 0 || + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { + /* page not owned */ + return MemoryOperationNotPerformed; + } + + return Success; +} + + +/* Gets the status of a job. Returns Waiting if no output jobs ready to be + * read. + * If no jobs are done then return Waiting + * If jobs are done but does not match desc then return NoActivityReady + * Status holds the error values if any */ +static Error caamGetJob(struct CAAM_DEVICE* dev, UINT4* status) +{ + UINT4 reg = CAAM_READ(CAAM_BASE | 0x1044); /* JRSTAR0 status */ + if (status) { + *status = 0; + } + + /* check for DECO, CCB, and Job Ring error state JRSTAR0 register */ + if (((reg & 0xF0000000) == 0x20000000) || /* CCB error */ + ((reg & 0xF0000000) == 0x40000000)|| /* DECO error */ + ((reg & 0xF0000000) == 0x60000000)) { /* Job Ring error */ + + if ((reg & 0x0000000F) > 0) { + *status = reg; + return Failure; + } + } + + /* Check number of done jobs in output list */ + reg = CAAM_READ(CAAM_BASE | 0x103C); + if ((reg & 0x000003FF) > 0) { + UINT4* out = (UINT4*)(dev->ring.JobOut); + if (status) { + *status = out[1]; + } + + if ((dev->ring.Desc ^ 0xF0000000) != out[0]) { + db_printf("CAAM job completed vs expected mismatch"); + return NoActivityReady; + } + + if (out[1] > 0) { + return Failure; + } + + /* increment jobs removed */ + CAAM_WRITE(CAAM_BASE | 0x1034, 1); + } + else { + /* check if the CAAM is idle and not processing any descriptors */ + if ((CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000002) == 2 /* idle */ + && (CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000001) == 0) { + return NoActivityReady; + } + + return Waiting; + } + + return Success; +} + + +/* Initialize CAAM RNG + * returns 0 on success */ +static int caamInitRng(struct CAAM_DEVICE* dev) +{ + UINT4 reg, status; + int ret = 0; + + /* Set up use of the TRNG for seeding wolfSSL HASH-DRBG */ + CAAM_WRITE(CAAM_RTMCTL, CAAM_PRGM); + CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | 0x40); /* reset */ + + /* Set up reading from TRNG */ + CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | CAAM_TRNG); + + /* Set up delay for TRNG @TODO Optimizations? + * Shift left with RTSDCTL because 0-15 is for sample number + * Also setting the max and min frequencies */ + CAAM_WRITE(CAAM_RTSDCTL, (CAAM_ENT_DLY << 16) | 0x09C4); + CAAM_WRITE(CAAM_RTFRQMIN, CAAM_ENT_DLY >> 1); /* 1/2 */ + CAAM_WRITE(CAAM_RTFRQMAX, CAAM_ENT_DLY << 3); /* up to 8x */ + + /* Set back to run mode and clear RTMCL error bit */ + reg = CAAM_READ(CAAM_RTMCTL) ^ CAAM_PRGM; + + CAAM_WRITE(CAAM_RTMCTL, reg); + reg = CAAM_READ(CAAM_RTMCTL); + reg |= CAAM_CTLERR; + CAAM_WRITE(CAAM_RTMCTL, reg); + + /* check input slot is available and then add */ + if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { + UINT4* in = (UINT4*)dev->ring.JobIn; + + memcpy((unsigned char*)dev->ring.Desc, (unsigned char*)wc_rng_start, + sizeof(wc_rng_start)); + + in[0] = dev->ring.Desc ^ 0xF0000000; /* physical address */ + CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + } + else { + return Waiting; + } + + do { + ret = caamGetJob(dev, &status); + /* @TODO use a better way to chill out CPU. */ + } while (ret == Waiting); + + return ret; +} + + +static Error caamDoJob(struct DescStruct* desc) +{ + Error ret; + UINT4 status; + + /* clear and set desc size */ + desc->desc[0] &= 0xFFFFFF80; + desc->desc[0] += desc->idx; + + /* check input slot is available and then add */ + if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { + UINT4* in = (UINT4*)desc->caam->ring.JobIn; + + memcpy((unsigned char*)desc->caam->ring.Desc, (unsigned char*)desc->desc, + (desc->idx + 1) * sizeof(UINT4)); + + in[0] = desc->caam->ring.Desc ^ 0xF0000000; /* physical address */ + CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + } + else { + return Waiting; + } + + do { + ret = caamGetJob(desc->caam, &status); + /* @TODO use a better way to chill out CPU. */ + } while (ret == Waiting); + + if (status != 0 || ret != Success) { + #if 0 + /* Used during testing to print out descriptor */ + { + char msg[2048]; + char* pt = msg; + int z; + + memset(msg, 0, sizeof(msg)); + for (z = 0; z < desc->idx; z++) { + snprintf(pt, sizeof(msg) - (z * 21), "desc[%d] = 0x%8.8x, ", + z, desc->desc[z]); + pt += 21; + } + snprintf(pt, sizeof(msg) - (z * 21), "status = 0x%8.8x\n", status); + if (desc->buf[0].data != 0) { /* for testing */ + memcpy((char*)desc->buf[0].data, msg, sizeof(msg)); + } + } + #endif + + + /* try to reset after error */ + caamReset(); + return ret; + } + + return Success; +} + + +/* handle input or output buffers + * NOTES: if sz == 0 then read all the rest of the buffers available + * when align == 1 then there is no alignment constraints + * + * returns the data size in bytes on success. With failure a negative value is + * returned. + */ +static int caamAddIO(struct DescStruct* desc, UINT4 options, UINT4 sz, + UINT4 align, UINT4* idx) +{ + int i, outSz = 0; + + if (align == 0) { + return -1; /* programming error */ + } + + for (i = *idx; i < desc->DescriptorCount; i++) { + /* input must be a multiple of "align" bytes */ + struct buffer* buf = &desc->buf[i]; + int blocks = buf->dataSz / align; + Address data = buf->data; + Address dataSz = buf->dataSz; + + if (outSz >= sz && sz != 0) { + break; + } + + if (dataSz % align > 0) { + /* store potential overlap */ + int tmpSz = dataSz % align; + int add = (tmpSz < (align - desc->alignIdx)) ? tmpSz : + align - desc->alignIdx; + unsigned char* local = (unsigned char*)desc->alignBuf; + + /* if already something in the buffer then add from front */ + if (desc->alignIdx > 0) { + memcpy((unsigned char*)&local[desc->alignIdx], + (unsigned char*)data, add); + data += add; + } + else { + memcpy((unsigned char*)&local[desc->alignIdx], + (unsigned char*)data + (blocks * align), add); + } + dataSz -= add; + desc->alignIdx += add; + } + + if (desc->alignIdx == align) { + desc->lastFifo = desc->idx; + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = options + desc->alignIdx; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); + ASP_FlushCaches((Address)desc->alignBuf, desc->alignIdx); + outSz += desc->alignIdx; + } + + if (blocks > 0) { + desc->lastFifo = desc->idx; + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = options + (blocks * align); + desc->desc[desc->idx++] = BSP_VirtualToPhysical(data); + outSz += (blocks * align); + + /* only one buffer available for align cases so exit here and make + a new descriptor after running current one */ + if (desc->alignIdx == align) { + desc->alignIdx = 0; + i++; /* start at next buffer */ + break; + } + } + } + + *idx = i; + return outSz; +} + + +/****************************************************************************** + IODevice Register Read and Write + ****************************************************************************/ + +static Error caamReadRegister(IODeviceVector ioCaam, Value reg, Value *out) +{ + if (reg < MIN_READ_REG || reg > MAX_READ_REG) { + return IllegalRegisterNumber; + } + + switch (reg) { + case CAAM_STATUS: + case CAAM_VERSION_MS: + case CAAM_VERSION_LS: + case CAMM_SUPPORT_MS: + case CAMM_SUPPORT_LS: + case CAAM_RTMCTL: + *out = CAAM_READ(reg); + break; + + default: + return IllegalRegisterNumber; + } + + (void)ioCaam; + return Success; +} + + +static Error caamWriteRegister(IODeviceVector ioCaam, Value reg, Value in) +{ + /* Should be no need for writes */ + return OperationNotAllowedOnTheUniversalIODevice; +} + + +/****************************************************************************** + CAAM Blob Operations + ****************************************************************************/ + +/* limit on size due to size of job ring being 64 word32's */ +static Error caamBlob(struct DescStruct* desc) +{ + Error err; + UINT4 keyType = 0x00000C08; /* default red */ + UINT4 i = 0; + int sz = 0, ret; + + if (desc->idx + 3 > MAX_DESC_SZ) { + return Failure; + } + + /*default to Red Key type, with offset of 12 and 8 byte load to context 2*/ + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | CAAM_IMM | keyType); + + /* add key modifier */ + if (i < desc->DescriptorCount) { + UINT4* pt; + Address data = desc->buf[i].data; + Address dataSz = desc->buf[i].dataSz; + + pt = (UINT4*)data; + if (dataSz < 8) { /* expecting 8 bytes for key modifier*/ + return TooManyBuffers; + } + desc->desc[desc->idx++] = pt[0]; + desc->desc[desc->idx++] = pt[1]; + } + + /* add input */ + while (sz < desc->inputSz && i < desc->DescriptorCount) { + ret = caamAddIO(desc, CAAM_SEQI, desc->inputSz - sz, 1, &i); + if (ret < 0) { /* handle error case */ + return TooManyBuffers; + } + sz += ret; + } + desc->outputIdx = i; + + /* add output */ + if (caamAddIO(desc, CAAM_SEQO, 0, 1, &i) < 0) { + return TooManyBuffers; + } + + if (desc->idx + 1 > MAX_DESC_SZ) { + return Failure; + } + desc->desc[desc->idx++] = CAAM_OP | CAAM_OPID_BLOB | desc->type; + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + + /* flush output buffers */ + for (i = desc->outputIdx; i < desc->DescriptorCount; i++) { + ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); + } + + return Success; +} + + +/****************************************************************************** + CAAM AES Operations + ****************************************************************************/ + +/* returns amount written on success and negative value in error case. + * Is different from caamAddIO in that it only adds a single input buffer + * rather than multiple ones. + */ +static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align, + UINT4 totalSz) +{ + int sz; + UINT4 i = *idx; + + /* handle alignment constraints on input */ + if (desc->alignIdx > 0) { + sz = desc->alignIdx; + + /* if there is more input buffers then add part of it */ + if (i < desc->outputIdx && i < desc->DescriptorCount) { + sz = align - desc->alignIdx; + sz = (sz <= desc->buf[i].dataSz) ? sz : desc->buf[i].dataSz; + memcpy((unsigned char*)(desc->alignBuf) + desc->alignIdx, + (unsigned char*)(desc->buf[i].data), sz); + + desc->buf[i].dataSz -= sz; + desc->buf[i].data += sz; + sz += desc->alignIdx; + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + ASP_FlushCaches((Address)desc->alignBuf, sz); + desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | + CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); + desc->alignIdx = 0; + } + else { + sz = desc->buf[i].dataSz; + if ((totalSz + sz) == desc->inputSz) { /* not an issue on final */ + align = 1; + } + + desc->alignIdx = sz % align; + if (desc->alignIdx != 0) { + sz -= desc->alignIdx; + memcpy((unsigned char*)desc->alignBuf, + (unsigned char*)(desc->buf[i].data) + sz, + desc->alignIdx); + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | + CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->buf[i].data); + i++; + } + + *idx = i; + return sz; +} + + +/* returns enum Success on success, all other return values should be + * considered an error. + * + * ofst is the amount of leftover buffer from previous calls + * inputSz is the amount of input in bytes that is being matched to output + */ +static Error caamAesOutput(struct DescStruct* desc, int* ofst, UINT4 inputSz) +{ + int offset = *ofst; + + if (desc->output != 0 && offset > 0 && inputSz > 0) { + UINT4 addSz; + + /* handle potential leftovers */ + addSz = (inputSz >= offset) ? offset : inputSz; + + inputSz -= addSz; + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + addSz; + if (inputSz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->output); + + if (addSz == offset) { + /* reset */ + desc->output = 0; + offset = 0; + } + else { + offset -= addSz; + desc->output += addSz; + + if (offset < 0) { + return TransferFailed; + } + } + } + + for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { + struct buffer* buf = &desc->buf[desc->lastIdx]; + + if (inputSz > 0) { + int tmp; + + if (buf->dataSz <= inputSz) { + tmp = buf->dataSz; + } + else { + offset = buf->dataSz - inputSz; + tmp = inputSz; + desc->output = buf->data + tmp; + } + inputSz -= tmp; + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + tmp; + if (inputSz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); + } + else { + break; + } + } + + *ofst = offset; + return Success; +} + + +/* check size of output and get starting buffer for it */ +static Error caamAesOutSz(struct DescStruct* desc, UINT4 i) +{ + int sz = 0; + + for (desc->outputIdx = i; desc->outputIdx < desc->DescriptorCount && + sz < desc->inputSz; desc->outputIdx++) { + sz += desc->buf[desc->outputIdx].dataSz; + } + desc->lastIdx = desc->outputIdx; + + /* make certain that output size is same as input */ + sz = 0; + for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { + sz += desc->buf[desc->lastIdx].dataSz; + } + if (sz != desc->inputSz) { + return SizeIsTooLarge; + } + desc->lastIdx = desc->outputIdx; + + return Success; +} + + +/* AES operations follow the buffer sequence of KEY -> (IV) -> Input -> Output + */ +static Error caamAes(struct DescStruct* desc) +{ + struct buffer* ctx[3]; + struct buffer* iv[3]; + Value ofst = 0; + Error err; + UINT4 i, totalSz = 0; + int ctxIdx = 0; + int ivIdx = 0; + int offset = 0; + int align = 1; + int sz = 0; + + int ctxSz = desc->ctxSz; + + if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { + return IllegalStatusNumber; + } + + if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) { + return ArgumentError; + } + + /* get key */ + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->ctxBuf; + + if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + ctx[ctxIdx] = buf; + sz += buf->dataSz; + + memcpy((unsigned char*)&local[offset], + (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz); + offset += ctx[ctxIdx]->dataSz; + ctxIdx++; + } + else { + break; + } + } + + /* sanity checks on size of key */ + if (sz > ctxSz) { + return SizeIsTooLarge; + } + if (ctxSz > (MAX_CTX * sizeof(UINT4)) - 16) { + return ArgumentError; + } + + /* Flush cache of ctx buffer then : + Add KEY Load command 0x0220000X + Add address to read key from 0xXXXXXXXX */ + ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); + + /* get IV if needed by algorithm */ + switch (desc->type) { + case CAAM_AESECB: + break; + + case CAAM_AESCTR: + ofst = 0x00001000; + /* fall through because states are the same only the offset changes */ + + case CAAM_AESCBC: + { + int maxSz = 16; /* default to CBC/CTR max size */ + + sz = 0; + offset = 0; + for (; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->iv; + + if (sz < maxSz) { + iv[ivIdx] = buf; + + if (buf->dataSz + sz > maxSz) { + return SizeIsTooLarge; + } + + sz += buf->dataSz; + memcpy((unsigned char*)&local[offset], + (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz); + offset += iv[ivIdx]->dataSz; + ivIdx++; + } + else { + break; + } + } + + if (sz != maxSz) { + /* invalid IV size */ + return SizeIsTooLarge; + } + + ASP_FlushCaches((Address)desc->iv, maxSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + maxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); + } + break; + + default: + return OperationNotImplemented; + } + + /* write operation */ + if (desc->idx + 1 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | + CAAM_ALG_UPDATE | desc->state; + + /* find output buffers */ + if (caamAesOutSz(desc, i) != Success) { + return SizeIsTooLarge; + } + + /* set alignment constraints */ + if (desc->type == CAAM_AESCBC || desc->type == CAAM_AESECB) { + align = 16; + } + + /* indefinite loop for input/output buffers */ + desc->headIdx = desc->idx; + desc->output = 0; + offset = 0; /* store left over amount for output buffer */ + do { + desc->idx = desc->headIdx; /* reset for each loop */ + + /* add a single input buffer (multiple ones was giving deco watch dog + * time out errors on the FIFO load of 1c. + * @TODO this could be a place for optimization if more data could be + * loaded in at one time */ + if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) { + return TransferFailed; + } + totalSz += sz; + + if (caamAesOutput(desc, &offset, sz) != Success) { + return TransferFailed; + } + + /* store updated IV */ + if (ivIdx > 0) { + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | 16; + desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + } + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + ASP_FlushCaches((Address)desc->iv, 16); + } while (desc->lastIdx < desc->DescriptorCount || offset > 0); + + /* flush output buffers */ + for (i = desc->outputIdx; i < desc->lastIdx; i++) { + ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); + } + + /* handle case with IV */ + if (ivIdx > 0) { + unsigned char* pt = (unsigned char*)desc->iv; + ASP_FlushCaches((Address)pt, 16); + for (i = 0; i < ivIdx; i++) { + memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); + pt += iv[i]->dataSz; + ASP_FlushCaches(iv[i]->data, iv[i]->dataSz); + } + } + + return Success; +} + + +/****************************************************************************** + CAAM AEAD Operations + ****************************************************************************/ + +/* AEAD operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> (AD) + * -> Input -> Output + * + */ +static Error caamAead(struct DescStruct* desc) +{ + struct buffer* ctx[3]; + struct buffer* iv[3]; + Value ofst = 0; + UINT4 state = CAAM_ALG_INIT; + UINT4 totalSz = 0; + Error err; + UINT4 i; + int ctxIdx = 0; + int ivIdx = 0; + int offset = 0; + int sz = 0; + int ivSz = 32; /* size of B0 | CTR0 for CCM mode */ + int ctxSz = desc->ctxSz; + int align = 16; /* input should be multiples of 16 bytes unless is final */ + int opIdx; + + if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { + return IllegalStatusNumber; + } + + /* sanity check is valid AES key size */ + if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) { + return ArgumentError; + } + + /* get key */ + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->ctxBuf; + + if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + ctx[ctxIdx] = buf; + sz += buf->dataSz; + + memcpy((unsigned char*)&local[offset], + (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz); + offset += ctx[ctxIdx]->dataSz; + ctxIdx++; + } + else { + break; + } + } + + /* sanity checks on size of key */ + if (sz > ctxSz) { + return SizeIsTooLarge; + } + + /* Flush cache of ctx buffer then : + Add KEY Load command 0x0220000X + Add address to read key from 0xXXXXXXXX */ + ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); + + desc->headIdx = desc->idx; + desc->output = 0; + offset = 0; /* store left over amount for output buffer */ + do { + desc->idx = desc->headIdx; /* reset for each loop */ + + /* write operation */ + if (desc->idx + 1 > MAX_DESC_SZ) { + return TransferFailed; + } + opIdx = desc->idx; + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | state | desc->type | + desc->state; + + /* get IV if needed by algorithm */ + switch (desc->type) { + case CAAM_AESCCM: + if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { + sz = 0; + offset = 0; + for (; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->iv; + + if (sz < ivSz) { + iv[ivIdx] = buf; + + if (buf->dataSz + sz > ivSz) { + return SizeIsTooLarge; + } + + sz += buf->dataSz; + memcpy((unsigned char*)&local[offset], + (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz); + offset += iv[ivIdx]->dataSz; + ivIdx++; + } + else { + break; + } + } + + if (sz != ivSz) { + /* invalid IV size */ + return SizeIsTooLarge; + } + offset = 0; + } + + ASP_FlushCaches((Address)desc->iv, ivSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + + ivSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); + break; + + default: + return OperationNotImplemented; + } + + + /********* handle AAD -- is only done with Init **********************/ + if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { + if ((desc->type == CAAM_AESCCM) && (desc->aadSz > 0)) { + /* set formatted AAD buffer size for CCM */ + ASP_FlushCaches((Address)desc->aadSzBuf, sizeof(desc->aadSzBuf)); + desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_AAD + desc->aadSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->aadSzBuf); + + /* now set aadSz to unformatted version for getting buffers */ + if (desc->aadSz == 2) { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = (((UINT4)pt[0] & 0xFF) << 8) | + ((UINT4)pt[1] & 0xFF); + } + else { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = (((UINT4)pt[2] & 0xFF) << 24) | + (((UINT4)pt[3] & 0xFF) << 16) | + (((UINT4)pt[4] & 0xFF) << 8) | + ((UINT4)pt[5] & 0xFF); + } + } + + /* get additional data buffers */ + if (desc->aadSz > 0) { + sz = 0; + for (; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + if (sz < desc->aadSz) { + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->lastFifo = desc->idx; + desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_AAD + buf->dataSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); + sz += buf->dataSz; + } + else { + break; + } + } + + /* flush AAD from FIFO and pad it to 16 byte block */ + desc->desc[desc->lastFifo] |= FIFOL_TYPE_FC1; + } + + /* find output buffers */ + if (caamAesOutSz(desc, i) != Success) { + return SizeIsTooLarge; + } + } + + /* handle alignment constraints on input */ + if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) { + return TransferFailed; + } + totalSz += sz; + + /* handle output buffers */ + if (caamAesOutput(desc, &offset, sz) != Success) { + return TransferFailed; + } + + /* store updated IV, if is last then set offset and final for MAC */ + if ((desc->lastIdx == desc->DescriptorCount) && (offset == 0)) { + ivSz = 16; + if (desc->state == CAAM_ENC) { + ofst = 32 << 8; /* offset is in 15-8 bits */ + } + else { + ofst = 0; + } + desc->desc[opIdx] |= CAAM_ALG_FINAL; + } + else { + /* if not final then store and use ctr and encrypted ctr from + context dword 2,3 and 4,5. Also store MAC and AAD info from + context dword 6. */ + ivSz = 56; + ofst = 0; + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | ivSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + state = CAAM_ALG_UPDATE; + } while (desc->lastIdx < desc->DescriptorCount || offset > 0); + + /* flush output buffers */ + for (i = desc->outputIdx; i < desc->lastIdx; i++) { + ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); + } + + /* handle case with IV (This is also the output of MAC with AES-CCM) */ + if (ivIdx > 0) { + unsigned char* pt = (unsigned char*)desc->iv; + ASP_FlushCaches((Address)pt, ivSz); + for (i = 0; i < ivIdx; i++) { + memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); + pt += iv[i]->dataSz; + ASP_FlushCaches(iv[i]->data, iv[i]->dataSz); + } + } + + return Success; +} + + +/****************************************************************************** + CAAM SHA Operations + ****************************************************************************/ +static int shaSize(struct DescStruct* desc) +{ + /* sanity check on dataSz for context */ + switch (desc->type) { + case CAAM_MD5: + return CAAM_MD5_CTXSZ; + + case CAAM_SHA: + return CAAM_SHA_CTXSZ; + + case CAAM_SHA224: + return CAAM_SHA224_CTXSZ; + + case CAAM_SHA256: + return CAAM_SHA256_CTXSZ; + + case CAAM_SHA384: + return CAAM_SHA384_CTXSZ; + + case CAAM_SHA512: + return CAAM_SHA512_CTXSZ; + + default: + return 0; + } +} + +/* SHA operations + * start: the index to start traversing through buffers. It's needed to allow + * for HMAC to reuse this code. + * + * return Success on success. All other return values are considered a fail + * case. + */ +static Error caamSha(struct DescStruct* desc, int start) +{ + struct buffer* ctx[3]; + Error err; + UINT4 i; + int sz = 0; + int ctxIdx = 0; + int offset = 0; + + int ctxSz = shaSize(desc); + + /* get context */ + for (i = start; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->iv; + + if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + ctx[ctxIdx] = buf; + sz += buf->dataSz; + + if (ctx[ctxIdx]->dataSz + offset > (MAX_CTX * sizeof(UINT4))) { + return SizeIsTooLarge; + } + memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[ctxIdx]->data, + ctx[ctxIdx]->dataSz); + offset += ctx[ctxIdx]->dataSz; + ctxIdx++; + } + else { + break; + } + } + if (sz > ctxSz || ctxSz > (MAX_CTX * sizeof(UINT4))) { + return SizeIsTooLarge; + } + + ASP_FlushCaches((Address)desc->iv, ctxSz); + /*Manage Context (current digest + 8 byte running message length)*/ + if ((desc->state & CAAM_ALG_INIT) != CAAM_ALG_INIT) { + /* don't load into the class 2 context register on inti. + Found that loading in caused context to not get set. */ + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2) + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + } + + /* add operation command */ + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS2 | desc->state | + desc->type; + + /* Check case where there is no input. + In all cases the FIFO Load should be flushed. */ + if (i == desc->DescriptorCount) { + desc->lastFifo = desc->idx; + if (desc->idx + 1 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS2 | + FIFOL_TYPE_MSG | CAAM_IMM; + } + + /* save index for looping over input */ + desc->headIdx = desc->idx; + do { + desc->idx = desc->headIdx; /* reset for each loop */ + if (i < desc->DescriptorCount) { + /* input must be a multiple of 64 bytes unless in final call */ + if (((desc->state & CAAM_ALG_FINAL) == CAAM_ALG_FINAL)) { + if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | + FIFOL_TYPE_MSG), 0, 1, &i) < 0) { + return TooManyBuffers; + } + } + else { + if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | + FIFOL_TYPE_MSG), 0, 64, &i) < 0) { + return TooManyBuffers; + } + } + } + + desc->desc[desc->lastFifo] |= FIFOL_TYPE_LC2; + + /* set context out */ + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS2 + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + /* flush context output for each loop */ + ASP_FlushCaches((Address)desc->iv, ctxSz); + } while (i < desc->DescriptorCount); + + /* store context to buffers */ + { + unsigned char* pt = (unsigned char*)desc->iv; + for (i = 0; i < ctxIdx; i++) { + memcpy((unsigned char*)ctx[i]->data, pt, ctx[i]->dataSz); + pt += ctx[i]->dataSz; + ASP_FlushCaches(ctx[i]->data, ctx[i]->dataSz); + } + } + + return Success; +} + + +/****************************************************************************** + CAAM TRNG Operations + ****************************************************************************/ + +/* If Entropy is not ready then return Waiting */ +static Error caamRng(struct DescStruct* desc) +{ + int sz = 0; + int i; + + Address reg; /* RTENT reg to read */ + int ofst = sizeof(UINT4); + + + /* Check ENT_VAL bit to make sure entropy is ready */ + if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != + CAAM_ENTVAL) { + return Waiting; + } + + /* check state of TRNG */ + if ((CAAM_READ(CAAM_RTSTATUS) & 0x0000FFFF) > 0) { + return Failure; + } + + /* read entropy from RTENT registers */ + reg = CAAM_RTENT0; + + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)buf->data; + sz = buf->dataSz; + + while (sz > 3 && reg <= CAAM_RTENT11) { + *((UINT4*)local) = CAAM_READ(reg); + reg += ofst; + local += ofst; + sz -= ofst; + } + + if (reg > CAAM_RTENT11 && sz > 0) { + return SizeIsTooLarge; + } + + /* handle non word32 size amount left over */ + if (sz > 0) { + UINT4 tmp = CAAM_READ(reg); + memcpy(local, (unsigned char*)&tmp, sz); + } + + ASP_FlushCaches(buf->data, buf->dataSz); + } + + + /* read RTENT11 to trigger new entropy generation */ + if (reg != CAAM_RTENT11) { + CAAM_READ(CAAM_RTENT11); + } + + return Success; +} + + +/****************************************************************************** + IODevice Start, Transfer and Finish Buffer + ****************************************************************************/ +/* args[0] holds the state such as encrypt/decrypt or init/update/final + * args[1] holds the ctx/key size + * args[2] holds the input size + * args[3] dependent on algo (such as AAD size with AES-CCM) */ +static Error caamTransferStart(IODeviceVector ioCaam, + Value type, const volatile Value args[4]) +{ + struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)ioCaam; + struct DescStruct* desc; + + /* currently only one desc is available for use */ + desc = &local->DescArray[0]; + + /* check if the desc is idle before using */ + if (GetIORequestStatus((IORequest)desc) != IdleIORequest) { + return ResourceNotAvailable; + } + + desc->idx = 0; + desc->output = 0; + desc->ctxOut = 0; + desc->outputIdx = 0; + desc->alignIdx = 0; + desc->lastFifo = 0; + desc->state = args[0]; + desc->ctxSz = args[1]; + desc->inputSz = args[2]; + desc->aadSz = 0; + desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/ + + switch (type) { + case CAAM_AESECB: + case CAAM_AESCBC: + if (desc->inputSz % 16 != 0) { + return ArgumentError; + } + /* fall through to break */ + case CAAM_AESCTR: + break; + + case CAAM_AESCCM: + memset((unsigned char*)desc->aadSzBuf, 0, sizeof(desc->aadSzBuf)); + if (args[3] > 0) { + /* encode the length in */ + if (args[3] <= 0xFEFF) { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = 2; + pt[0] = ((args[3] & 0xFF00) >> 8); + pt[1] = (args[3] & 0x00FF); + } + else if (args[3] <= 0xFFFFFFFF) { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = 6; + pt[0] = 0xFF; pt[1] = 0xFE; + pt[2] = ((args[3] & 0xFF000000) >> 24); + pt[3] = ((args[3] & 0x00FF0000) >> 16); + pt[4] = ((args[3] & 0x0000FF00) >> 8); + pt[5] = (args[3] & 0x000000FF); + } + } + break; + + case CAAM_MD5: + case CAAM_SHA: + case CAAM_SHA224: + case CAAM_SHA256: + case CAAM_SHA384: + case CAAM_SHA512: + break; + + case CAAM_BLOB_ENCAP: + case CAAM_BLOB_DECAP: + break; + + case CAAM_ENTROPY: + break; + + default: + /* unknown type */ + return UsageNotSupported; + } + + desc->DescriptorCount = 0; + desc->type = type; + desc->running = true; + StartIORequest((IORequest)desc); + + /* For now only require READ permissions */ + SetIORequestBufferPermissions((IORequest)desc, MEMORY_READ); + return Success; +} + + +static Error caamTransferBuffer(IODeviceVector TheIODeviceVector, + IORequest req, IODescriptor NewIODescriptor, + Address data, Address dataSz) +{ + struct DescStruct* desc = (struct DescStruct*)req; + Error err; + + switch (desc->type) { + case CAAM_AESECB: + case CAAM_AESCTR: + case CAAM_AESCBC: + case CAAM_AESCCM: + + case CAAM_MD5: + case CAAM_SHA: + case CAAM_SHA224: + case CAAM_SHA256: + case CAAM_SHA384: + case CAAM_SHA512: + + case CAAM_BLOB_ENCAP: + case CAAM_BLOB_DECAP: + case CAAM_ENTROPY: + { /* set buffer for transfer finish */ + struct buffer* buf; + if (desc->DescriptorCount >= MAX_BUF) { + return TooManyBuffers; + } + buf = &desc->buf[desc->DescriptorCount]; + buf->data = data; + buf->dataSz = dataSz; + } + err = Success; + break; + + default: + err = UsageNotSupported; + } + + if (err != Success) { + desc->running = false; + DismissIORequest(req); + return err; + } + + desc->DescriptorCount++; + return Success; +} + + +static Error caamTransferFinish(IODeviceVector ioCaam, IORequest req) +{ + struct DescStruct* desc = (struct DescStruct*)req; + Error ret; + + /* construct desc */ + switch (desc->type) { + case CAAM_AESECB: + case CAAM_AESCTR: + case CAAM_AESCBC: + ret = caamAes(desc); + break; + + case CAAM_AESCCM: + ret = caamAead(desc); + break; + + case CAAM_MD5: + case CAAM_SHA: + case CAAM_SHA224: + case CAAM_SHA256: + case CAAM_SHA384: + case CAAM_SHA512: + ret = caamSha(desc, 0); + break; + + case CAAM_ENTROPY: + ret = caamRng(desc); + break; + + case CAAM_BLOB_ENCAP: + case CAAM_BLOB_DECAP: + ret = caamBlob(desc); + break; + + default: + ret = UsageNotSupported; + } + + desc->running = false; + DismissIORequest(req); + return ret; +} + + +/****************************************************************************** + IODevice Interrupt and Init + ****************************************************************************/ + +static Error caamTransferWrite(IODeviceVector ioCaam, + IORequest req, Value dataSz, const volatile Value *data) +{ + DismissIORequest(req); + return UsageNotSupported; +} + + +static void caamTransferAbort(IODeviceVector ioCaam, IORequest req) +{ + DismissIORequest(req); +} + + +static void caamTransferRecall(IODeviceVector ioCaam, IODescriptor req) +{ + +} + + +static void HandleInterrupt(Address id) +{ + struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)id; + Value InterruptStatus = INTERRUPT_AtomicWrite(&local->InterruptStatus, 0); + int i; + + /* Loop through descriptors and try to dismiss them */ + for (i = 0; i < DESC_COUNT; i++) { + struct DescStruct* desc = &local->DescArray[i]; + if (InterruptStatus & (1 << i)) { + desc->running = false; + if (GetIORequestStatus((IORequest)desc) == IORequestSuspended) { + ContinueIORequest((IORequest)desc); + } + else { + DismissIORequest((IORequest)desc); + } + } + } +} + + +static Error caamCreate(IODeviceVector ioCaam) +{ + return Success; +} + + +void InitCAAM(void) +{ + /* get IO vector and set it up */ + IODeviceVector ioCaam = &caam.caamVector; + unsigned int reg; + int i; + Error ret; + + + ioCaam->Create = &caamCreate; + ioCaam->ReadRegister = &caamReadRegister; + ioCaam->WriteRegister = &caamWriteRegister; + + ioCaam->TransferStart = &caamTransferStart; + ioCaam->TransferBuffer = &caamTransferBuffer; + ioCaam->TransferWrite = &caamTransferWrite; + ioCaam->TransferFinish = &caamTransferFinish; + ioCaam->TransferAbort = &caamTransferAbort; + ioCaam->TransferRecall = &caamTransferRecall; +#ifdef HARDWARE_CACHE_COHERENCY + ioCaam->IOSynchronizationNotRequired = 1; +#endif + + RegisterIODeviceVector(ioCaam, DRIVER_NAME); + RequestIOTerminationTask(ioCaam, 10); + + /* Initialize descriptors */ + for (i = 0; i < BUFFER_COUNT; i++) { + InitializeIODescriptor(ioCaam, &caam.IODescriptorArray[i]); + } + + /* Initialize Descriptors */ + for (i = 0; i < DESC_COUNT; i++) { + InitializeIORequest(ioCaam, &caam.DescArray[i].TheIORequest, + IOREQUEST_STANDARD); + caam.DescArray[i].running = false; + caam.DescArray[i].caam = &caam; + } + + + /* call interrupt to make IORequests available */ + caam.InterruptStatus = 0; + INTERRUPT_InitCall(&caam.HandleInterruptCall, + &HandleInterrupt, "Start up CAAM IORequest"); + + /* set clock speed for CAAM. Setting it here to allow for restricting + access */ + #define REGS_CCM_BASE (0xf20c4000) + #define HW_CCM_CCGR0_ADDR (0xf20c4068) + #define CG(x) (3 << (x*2)) + + reg = CG(6) | CG(5) | CG(4); + *(volatile unsigned int*)HW_CCM_CCGR0_ADDR = + *(volatile unsigned int*)HW_CCM_CCGR0_ADDR | reg; + + /* set up job ring */ + + /* @TODO create partition in physical memory for job rings + current partition security is set to the default */ + for (i = 1; i < CAAM_PAGE_MAX; i++) { + ret = caamCreatePartition(i, i); + if (ret == 0) { + break; + } + + if (ret != MemoryMapMayNotBeEmpty) { + INTERRUPT_Panic(); + } + } + + if (ret != 0) { + INTERRUPT_Panic(); + } + + caam.ring.page = i; + caam.ring.JobIn = (CAAM_PAGE + (i << 12)); + caam.ring.JobOut = caam.ring.JobIn + 16; + caam.ring.Desc = caam.ring.JobOut + 16; + + /* set physical address of job rings */ + CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn ^ 0xF0000000); + CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut ^ 0xF0000000); + + /* Initialize job ring sizes to 1 */ + CAAM_WRITE(CAAM_IRSR0, 1); + CAAM_WRITE(CAAM_ORSR0, 1); + + /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */ + CAAM_WRITE((CAAM_BASE | 0x0004), CAAM_READ(CAAM_BASE | 0x0004) | 0x40000000); + + /* start up RNG if not already started */ + if (caamInitRng(&caam) != 0) { + INTERRUPT_Panic(); + } +} + +void (*__ghsentry_bspuserinit_InitCAAM)(void) = &InitCAAM; + +#endif /* INTEGRITY */ diff --git a/wolfcrypt/src/port/caam/caam_qnx.c b/wolfcrypt/src/port/caam/caam_qnx.c new file mode 100644 index 000000000..0aa47dd05 --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_qnx.c @@ -0,0 +1,1289 @@ +/* caam_qnx.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include "caam_driver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* virtual address for accessing CAAM addresses */ +uintptr_t virtual_base = 0; + +/* keep track of which ID memory belongs to so it can be free'd up */ +#define MAX_PART 7 +pthread_mutex_t sm_mutex; +CAAM_ADDRESS sm_ownerId[MAX_PART]; + +/* variables for I/O of resource manager */ +resmgr_connect_funcs_t connect_funcs; +resmgr_io_funcs_t io_funcs; +dispatch_t *dpp; +resmgr_attr_t rattr; +dispatch_context_t *ctp; +iofunc_attr_t ioattr; + +int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb); +int io_open (resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle, + void *extra); +int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb); +int io_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb); +int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb); + + +/* read the contents at offset from BASE address */ +unsigned int CAAM_READ(unsigned int ofst) { + return in32(virtual_base + ofst); +} + + +/* takes in offset from BASE address */ +void CAAM_WRITE(unsigned int ofst, unsigned int in) +{ + out32(virtual_base + ofst, in); +} + + +/* Sets the base address to use for read/write + * returns 0 on success + */ +int CAAM_SET_BASEADDR() +{ + /* address range for CAAM is CAAM_BASE plus 0x10000 */ + virtual_base = mmap_device_io(0x00010000, CAAM_BASE); + if (virtual_base == (uintptr_t)MAP_FAILED) { + WOLFSSL_MSG("Unable to map virtual memory"); + return -1; + } + return 0; +} + + +/* cleans up having set the base address */ +void CAAM_UNSET_BASEADDR() +{ + munmap_device_io(virtual_base, 0x00010000); +} + +/* convert a virtual address to a physical address + * returns the physical address on success + */ +CAAM_ADDRESS CAAM_ADR_TO_PHYSICAL(void* in, int inSz) +{ + off64_t ofst = 0; + int ret, count = 0;; + + if (in == NULL) + return 0; + + if (inSz == 0) + inSz = 1; + + do { + ret = mem_offset64(in, NOFD, inSz, &ofst, NULL); + if (ret != 0) { + WOLFSSL_MSG("posix offset failed"); + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + perror("posix offset failed : "); + #endif + } + msync(in, inSz, MS_INVALIDATE); + count++; + } while (ret != 0 && ret == -1 && count < 5); + + return (CAAM_ADDRESS)ofst; +} + + +/* convert a physical address to virtual address + * returns the virtual address on success + */ +CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int len) +{ + void* ret; + ret = mmap_device_memory(NULL, len, PROT_READ | PROT_WRITE | PROT_NOCACHE, + 0, in); + return (CAAM_ADDRESS)ret; +} + + +/* map a virtual address to a created coherent physical address + * returns the mapped address on success + */ +void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy) +{ + int sz; + void *vaddr; + + sz = inSz; + if (inSz == 0) { + sz = 1; + } + + vaddr = mmap(NULL, sz, PROT_READ | PROT_WRITE | PROT_NOCACHE, + MAP_PHYS | MAP_SHARED | MAP_ANON, NOFD, 0); + if (vaddr == MAP_FAILED) { + WOLFSSL_MSG("Failed to map memory"); + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + perror("Failed to map memory : "); + #endif + } + else { + if (copy && in != 0 && inSz > 0) { + memcpy((unsigned char*)vaddr, (unsigned char*)in, inSz); + } + + if (msync(vaddr, sz, MS_SYNC) != 0) { + WOLFSSL_MSG("Failed to sync memory after copy"); + } + } + return vaddr; +} + + +/* un map address, should be called when done with a mapped address */ +void CAAM_ADR_UNMAP(void* vaddr, unsigned int out, int outSz, + unsigned char copy) +{ + int sz; + + sz = outSz; + if (outSz == 0) + sz = 1; + + if (msync(vaddr, sz, MS_SYNC) != 0) { + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + perror("Failed to sync output"); + #endif + /* even though the address was not synced up still try to copy and + unmap it */ + } + + if (copy && out != 0 && outSz > 0) { + memcpy((unsigned char*)out, (unsigned char*)vaddr, outSz); + } + munmap(vaddr, sz); +} + + +/* syncoronize virtual buffer with physical + * return 0 on success */ +int CAAM_ADR_SYNC(void* vaddr, int sz) +{ + if (msync(vaddr, sz, MS_SYNC) != 0) { + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + perror("address sync failed"); + #endif + return -1; + } + return 0; +} + + +/* macros for QNX devctl commands */ +#define WC_TRNG_CMD __DIOTF(_DCMD_ALL, CAAM_ENTROPY, iov_t) +#define WC_CAAM_GET_PART __DIOTF(_DCMD_ALL, CAAM_GET_PART, iov_t) +#define WC_CAAM_FREE_PART __DIOT(_DCMD_ALL, CAAM_FREE_PART, iov_t) +#define WC_CAAM_FIND_PART __DIOTF(_DCMD_ALL, CAAM_FIND_PART, iov_t) +#define WC_CAAM_READ_PART __DIOTF(_DCMD_ALL, CAAM_READ_PART, iov_t) +#define WC_CAAM_WRITE_PART __DIOT(_DCMD_ALL, CAAM_WRITE_PART, iov_t) + +#define WC_CAAM_ECDSA_KEYPAIR __DIOTF(_DCMD_ALL, CAAM_ECDSA_KEYPAIR, iov_t) +#define WC_CAAM_ECDSA_VERIFY __DIOT(_DCMD_ALL, CAAM_ECDSA_VERIFY, iov_t) +#define WC_CAAM_ECDSA_SIGN __DIOTF(_DCMD_ALL, CAAM_ECDSA_SIGN, iov_t) +#define WC_CAAM_ECDSA_ECDH __DIOTF(_DCMD_ALL, CAAM_ECDSA_ECDH, iov_t) + +#define WC_CAAM_BLOB_ENCAP __DIOTF(_DCMD_ALL, CAAM_BLOB_ENCAP, iov_t) +#define WC_CAAM_BLOB_DECAP __DIOTF(_DCMD_ALL, CAAM_BLOB_DECAP, iov_t) + +#define WC_CAAM_CMAC __DIOTF(_DCMD_ALL, CAAM_CMAC, iov_t) + +#define WC_CAAM_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t) + + +/* partAddr is virtual address + * partSz size expected to access + * + * returns 0 on ok + */ +static int sanityCheckPartitionAddress(CAAM_ADDRESS partAddr, int partSz) +{ + if (partAddr < CAAM_PAGE || partAddr > CAAM_PAGE * MAX_PART || + partSz > 4096) { + WOLFSSL_MSG("error in physical address range"); + return -1; + } + return 0; +} + + +/* return 0 on success */ +static int getArgs(unsigned int args[4], resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int *idx, unsigned int maxIdx) +{ + int expectedSz; + iov_t in_iov; + + expectedSz = sizeof(unsigned int) * 4; + if (*idx + expectedSz > maxIdx) { + WOLFSSL_MSG("not enough for arguments"); + return -1; + } + + SETIOV(&in_iov, args, expectedSz); + if (resmgr_msgreadv(ctp, &in_iov, 1, *idx) != expectedSz) { + WOLFSSL_MSG("unexpected msg size read"); + return -1; + } + *idx += expectedSz; + return 0; +} + + +/* helper function to setup and run CMAC operation + * returns EOK on success + */ +static int doCMAC(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], + unsigned int idx) +{ + DESCSTRUCT desc; + CAAM_BUFFER tmp[3]; + iov_t in_iovs[3], out_iov; + + int msgSz = 0, ret, numBuf, keySz; + unsigned char ctx[32]; /* running CMAC context is a constant 32 bytes */ + unsigned char keybuf[32 + BLACK_KEY_MAC_SZ];/*max AES key size is 32 + MAC*/ + unsigned char *buf = NULL; + + numBuf = 2; /* start with 2 (key + ctx) for case with no msg input */ + keySz = args[1]; + if (args[2] == 1) { /* is it a black key? */ + keySz = keySz + BLACK_KEY_MAC_SZ; + } + SETIOV(&in_iovs[0], keybuf, keySz); + SETIOV(&in_iovs[1], ctx, sizeof(ctx)); + msgSz = args[3]; + if (msgSz < 0) { + WOLFSSL_MSG("CMAC msg size was a negative value"); + return EBADMSG; + } + + if (msgSz > 0) { + buf = (unsigned char*)CAAM_ADR_MAP(0, msgSz, 0); + if (buf == NULL) { + return ECANCELED; + } + SETIOV(&in_iovs[2], buf, msgSz); + numBuf = numBuf + 1; /* increase buffer size by one when adding msg */ + } + + ret = resmgr_msgreadv(ctp, in_iovs, numBuf, idx); + if (ret < (msgSz + keySz + sizeof(ctx))) { + /* sanity check that enough data was sent */ + if (buf != NULL) + CAAM_ADR_UNMAP(buf, 0, msgSz, 0); + return EOVERFLOW; + } + + tmp[0].TheAddress = (CAAM_ADDRESS)keybuf; + tmp[0].Length = args[1]; + + tmp[1].TheAddress = (CAAM_ADDRESS)ctx; + tmp[1].Length = sizeof(ctx); + + if (msgSz > 0) { + tmp[2].TheAddress = (CAAM_ADDRESS)buf; + tmp[2].Length = msgSz; + } + caamDescInit(&desc, CAAM_CMAC, args, tmp, numBuf); + ret = caamAesCmac(&desc, numBuf, args); + if (msgSz > 0) { + if (buf != NULL) + CAAM_ADR_UNMAP(buf, 0, msgSz, 0); + } + + if (ret != Success) { + return EBADMSG; + } + SETIOV(&out_iov, ctx, sizeof(ctx)); + + /* extra sanity check that out buffer is large enough */ + if (sizeof(ctx) > msg->o.nbytes) { + return EOVERFLOW; + } + ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + if (ret < 0) { + return ECANCELED; + } + + return EOK; +} + + +/* helper function to setup and run TRNG operation + * returns EOK on success + */ +static int doTRNG(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], + unsigned int idx) +{ + int length, ret; + unsigned char *buf; + iov_t out_iov; + + length = args[0]; + + /* sanity check that length out is not over the edge */ + if (length > msg->o.nbytes) { + WOLFSSL_MSG("Length too large for TRNG out size available"); + return EOVERFLOW; + } + + if (length > 0) { + buf = (unsigned char*)CAAM_ADR_MAP(0, length, 0); + if (buf == NULL) { + return ECANCELED; + } + + ret = caamTRNG(buf, length); + if (ret == CAAM_WAITING) { + /* waiting for more entropy */ + CAAM_ADR_UNMAP(buf, 0, length, 0); + return EAGAIN; + } + + SETIOV(&out_iov, buf, length); + ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + CAAM_ADR_UNMAP(buf, 0, length, 0); + if (ret < 0) { + return ECANCELED; + } + } + return EOK; +} + + +/* helper function to setup and run BLOB operation + * returns EOK on success + */ +static int doBLOB(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], + unsigned int idx) +{ + int WC_CAAM_BLOB_SZ = 48; /* extra blob size from manual */ + int dir, ret, inSz, outSz; + DESCSTRUCT desc; + CAAM_BUFFER tmp[3]; + iov_t in_iovs[2], out_iov; + + unsigned char *inBuf, *outBuf; + unsigned char keymod[BLACK_BLOB_KEYMOD_SZ]; + /* 16 is max size for keymod (8 with red blobs and 16 with black) */ + + if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) { + dir = CAAM_BLOB_ENCAP; + } + else { + dir = CAAM_BLOB_DECAP; + } + + inSz = args[2]; + if (inSz < 0) { + return EBADMSG; + } + + if (args[0] == 1 && dir == CAAM_BLOB_ENCAP) { + inSz = inSz + BLACK_KEY_MAC_SZ; + } + + SETIOV(&in_iovs[0], keymod, args[3]); + if ((inSz + args[3]) > (ctp->size - idx)) { + return EOVERFLOW; + } + + inBuf = (unsigned char*)CAAM_ADR_MAP(0, inSz, 0); + if (inBuf == NULL) { + return ECANCELED; + } + SETIOV(&in_iovs[1], inBuf, inSz); + ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); + if (ret < inSz + args[3]) { + return EBADMSG; + } + + /* key mod */ + tmp[0].TheAddress = (CAAM_ADDRESS)keymod; + tmp[0].Length = args[3]; + + /* input */ + tmp[1].TheAddress = (CAAM_ADDRESS)inBuf; + tmp[1].Length = args[2]; + + /* output */ + outSz = args[2]; + if (msg->i.dcmd == WC_CAAM_BLOB_ENCAP) { + outSz = outSz + WC_CAAM_BLOB_SZ; + } + else { + outSz = outSz - WC_CAAM_BLOB_SZ; + } + if (outSz < 0) { + return EBADMSG; + } + + if (args[0] == 1 && dir == CAAM_BLOB_DECAP) { + outBuf = (unsigned char*)CAAM_ADR_MAP(0, outSz + BLACK_KEY_MAC_SZ, 0); + } + else { + outBuf = (unsigned char*)CAAM_ADR_MAP(0, outSz, 0); + } + if (outBuf == NULL) { + CAAM_ADR_UNMAP(inBuf, 0, inSz, 0); + return ECANCELED; + } + tmp[2].TheAddress = (CAAM_ADDRESS)outBuf; + tmp[2].Length = outSz; + + caamDescInit(&desc, dir, args, tmp, 3); + ret = caamBlob(&desc); + CAAM_ADR_UNMAP(inBuf, 0, inSz, 0); + + /* adjust outSz for MAC tag at the end of black key */ + if (args[0] == 1 && dir == CAAM_BLOB_DECAP) { + outSz = outSz + BLACK_KEY_MAC_SZ; + } + + if (ret != Success) { + CAAM_ADR_UNMAP(outBuf, 0, outSz, 0); + return ECANCELED; + } + + CAAM_ADR_SYNC(outBuf, outSz); + SETIOV(&out_iov, outBuf, outSz); + if (outSz > msg->o.nbytes) { + CAAM_ADR_UNMAP(outBuf, 0, outSz, 0); + return EOVERFLOW; + } + ret = resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + CAAM_ADR_UNMAP(outBuf, 0, outSz, 0); + if (ret < 0) { + return ECANCELED; + } + return EOK; +} + + +/* helper function to setup and make ECC key + * returns EOK on success + */ +static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4], + unsigned int idx, iofunc_ocb_t *ocb) +{ + int ret; + DESCSTRUCT desc; + CAAM_BUFFER tmp[2]; + iov_t in_iovs[2], out_iovs[3]; + + SETIOV(&in_iovs[0], &tmp[0], sizeof(CAAM_BUFFER)); + SETIOV(&in_iovs[1], &tmp[1], sizeof(CAAM_BUFFER)); + ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); + + caamDescInit(&desc, CAAM_ECDSA_KEYPAIR, args, tmp, 2); + ret = caamECDSAMake(&desc, tmp, args); + if (ret != Success) { + return ECANCELED; + } + + SETIOV(&out_iovs[0], &tmp[0], sizeof(CAAM_BUFFER)); + SETIOV(&out_iovs[1], &tmp[1], sizeof(CAAM_BUFFER)); + SETIOV(&out_iovs[2], args, sizeof(int) * 4); + ret = resmgr_msgwritev(ctp, &out_iovs[0], 3, sizeof(msg->o)); + if (ret < 0) { + return ECANCELED; + } + + /* claim ownership of a secure memory location */ + pthread_mutex_lock(&sm_mutex); + sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb; + pthread_mutex_unlock(&sm_mutex); + + return EOK; +} + + +/* helper function to setup and do ECC verify + * returns EOK on success + */ +static int doECDSA_VERIFY(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx) +{ + DESCSTRUCT desc; + CAAM_BUFFER tmp[5]; + iov_t in_iovs[4]; + int ret, pubSz; + + unsigned char *hash, *pubkey = NULL, *r, *s; + CAAM_ADDRESS securePub; + + if (args[0] == 1) { + pubSz = sizeof(CAAM_ADDRESS); + + SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS)); + } + else { + pubSz = args[3]*2; + pubkey = (unsigned char*)CAAM_ADR_MAP(0, pubSz, 0); + if (pubkey == NULL) { + return ECANCELED; + } + + SETIOV(&in_iovs[0], pubkey, args[3]*2); + } + + hash = (unsigned char*)CAAM_ADR_MAP(0, args[2], 0); + if (hash == NULL) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0); + return ECANCELED; + } + SETIOV(&in_iovs[1], hash, args[2]); + + r = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (r == NULL) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0); + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + return ECANCELED; + } + SETIOV(&in_iovs[2], r, args[3]); + + s = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (s == NULL) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0); + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + CAAM_ADR_UNMAP(r, 0, args[3], 0); + return ECANCELED; + } + SETIOV(&in_iovs[3], s, args[3]); + + ret = resmgr_msgreadv(ctp, in_iovs, 4, idx); + if (((args[3] * 2) + args[2] + pubSz) > ret) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0); + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + CAAM_ADR_UNMAP(r, 0, args[3], 0); + CAAM_ADR_UNMAP(s, 0, args[3], 0); + return EOVERFLOW; + } + + /* setup CAAM buffers to pass to driver */ + if (args[0] == 1) { + tmp[0].TheAddress = securePub; + } + else { + tmp[0].TheAddress = (CAAM_ADDRESS)pubkey; + } + tmp[0].Length = args[3]*2; + + tmp[1].TheAddress = (CAAM_ADDRESS)hash; + tmp[1].Length = args[2]; + + tmp[2].TheAddress = (CAAM_ADDRESS)r; + tmp[2].Length = args[3]; + + tmp[3].TheAddress = (CAAM_ADDRESS)s; + tmp[3].Length = args[3]; + + if (pubkey != NULL) + CAAM_ADR_SYNC(pubkey, pubSz); + CAAM_ADR_SYNC(hash, args[2]); + CAAM_ADR_SYNC(r, args[3]); + CAAM_ADR_SYNC(s, args[3]); + caamDescInit(&desc, CAAM_ECDSA_VERIFY, args, tmp, 4); + ret = caamECDSAVerify(&desc, tmp, 4, args); + + /* free all buffers before inspecting the return value */ + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + CAAM_ADR_UNMAP(r, 0, args[3], 0); + CAAM_ADR_UNMAP(s, 0, args[3], 0); + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, pubSz, 0); + + if (ret != Success) { + return EBADMSG; + } + return EOK; +} + + +/* helper function to setup and do ECC sign + * returns EOK on success + */ +static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx) +{ + int ret, keySz; + DESCSTRUCT desc; + CAAM_BUFFER tmp[4]; + + unsigned char *key = NULL, *hash, *r, *s; + CAAM_ADDRESS blackKey; + + iov_t in_iovs[2], out_iovs[2]; + + if (args[0] == 1) { + keySz = sizeof(CAAM_ADDRESS); + SETIOV(&in_iovs[0], &blackKey, sizeof(CAAM_ADDRESS)); + } + else { + keySz = args[3]; + key = (unsigned char*)CAAM_ADR_MAP(0, keySz, 0); + if (key == NULL) { + return ECANCELED; + } + SETIOV(&in_iovs[0], key, keySz); + } + + hash = (unsigned char*)CAAM_ADR_MAP(0, args[2], 0); + if (hash == NULL) { + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + return ECANCELED; + } + SETIOV(&in_iovs[1], hash, args[2]); + ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); + if ((keySz + args[2]) > ret) { + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + return EOVERFLOW; + } + + + /* setup CAAM buffers to pass to driver */ + if (args[0] == 1) { + tmp[0].TheAddress = blackKey; + } + else { + tmp[0].TheAddress = (CAAM_ADDRESS)key; + } + tmp[0].Length = args[3]; + + tmp[1].TheAddress = (CAAM_ADDRESS)hash; + tmp[1].Length = args[2]; + + r = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (r == NULL) { + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + return ECANCELED; + } + tmp[2].TheAddress = (CAAM_ADDRESS)r; + tmp[2].Length = args[3]; + + s = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (s == NULL) { + CAAM_ADR_UNMAP(r, 0, args[3], 0); + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + return ECANCELED; + } + tmp[3].TheAddress = (CAAM_ADDRESS)s; + tmp[3].Length = args[3]; + + caamDescInit(&desc, CAAM_ECDSA_SIGN, args, tmp, 4); + ret = caamECDSASign(&desc, 4, args); + CAAM_ADR_UNMAP(hash, 0, args[2], 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, keySz, 0); + if (ret != Success) { + CAAM_ADR_UNMAP(s, 0, args[3], 0); + CAAM_ADR_UNMAP(r, 0, args[3], 0); + return EBADMSG; + } + + if ((args[3] * 2) > msg->o.nbytes) { + CAAM_ADR_UNMAP(s, 0, args[3], 0); + CAAM_ADR_UNMAP(r, 0, args[3], 0); + return EOVERFLOW; + } + + CAAM_ADR_SYNC(r, args[3]); + CAAM_ADR_SYNC(s, args[3]); + SETIOV(&out_iovs[0], r, args[3]); + SETIOV(&out_iovs[1], s, args[3]); + + ret = resmgr_msgwritev(ctp, &out_iovs[0], 2, sizeof(msg->o)); + CAAM_ADR_UNMAP(s, 0, args[3], 0); + CAAM_ADR_UNMAP(r, 0, args[3], 0); + if (ret < 0) { + return ECANCELED; + } + return EOK; +} + + +/* helper function to setup and get an ECC shared secret + * returns EOK on success + */ +static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx) +{ + int ret; + DESCSTRUCT desc; + CAAM_BUFFER tmp[3]; + int expectedSz = 0; + iov_t in_iovs[2], out_iov; + + unsigned char *pubkey = NULL, *key = NULL, *shared; + CAAM_ADDRESS securePub, blackKey; + + /* when using memory in secure partition just send the address */ + if (args[1] == 1) { + SETIOV(&in_iovs[0], &securePub, sizeof(CAAM_ADDRESS)); + expectedSz += sizeof(CAAM_ADDRESS); + } + else { + pubkey = (unsigned char*)CAAM_ADR_MAP(0, args[3]*2, 0); + if (pubkey == NULL) { + return ECANCELED; + } + + SETIOV(&in_iovs[0], pubkey, args[3]*2); + expectedSz += args[3]*2; + } + + if (args[0] == 1) { + SETIOV(&in_iovs[1], &blackKey, sizeof(CAAM_ADDRESS)); + expectedSz += sizeof(CAAM_ADDRESS); + } + else { + key = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (key == NULL) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0); + return ECANCELED; + } + + SETIOV(&in_iovs[1], key, args[3]); + expectedSz += args[3]; + } + + ret = resmgr_msgreadv(ctp, in_iovs, 2, idx); + if (expectedSz > ret) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, args[3], 0); + return ECANCELED; + } + + /* setup CAAM buffers to pass to driver */ + if (args[1] == 1) { + tmp[0].TheAddress = securePub; + } + else { + tmp[0].TheAddress = (CAAM_ADDRESS)pubkey; + } + tmp[0].Length = args[3]*2; + + if (args[0] == 1) { + tmp[1].TheAddress = blackKey; + } + else { + tmp[1].TheAddress = (CAAM_ADDRESS)key; + } + tmp[1].Length = args[3]; + + shared = (unsigned char*)CAAM_ADR_MAP(0, args[3], 0); + if (shared == NULL) { + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, args[3], 0); + return ECANCELED; + } + + tmp[2].TheAddress = (CAAM_ADDRESS)shared; + tmp[2].Length = args[3]; + caamDescInit(&desc, CAAM_ECDSA_ECDH, args, tmp, 3); + ret = caamECDSA_ECDH(&desc, 3, args); + if (pubkey != NULL) + CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0); + if (key != NULL) + CAAM_ADR_UNMAP(key, 0, args[3], 0); + + if (ret != Success) { + CAAM_ADR_UNMAP(shared, 0, args[3], 0); + return EBADMSG; + } + + if (args[3] > msg->o.nbytes) { + CAAM_ADR_UNMAP(shared, 0, args[3], 0); + return EOVERFLOW; + } + CAAM_ADR_SYNC(shared, args[3]); + SETIOV(&out_iov, shared, args[3]); + resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + CAAM_ADR_UNMAP(shared, 0, args[3], 0); + return EOK; +} + + +/* helper function to setup and cover data + * returns EOK on success + */ +static int doFIFO_S(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx) +{ + int ret; + DESCSTRUCT desc; + CAAM_BUFFER tmp[2]; + iov_t in_iov, out_iov; + unsigned char *inBuf, *outBuf; + + inBuf = (unsigned char*)CAAM_ADR_MAP(0, args[1], 0); + if (inBuf == NULL) { + return ECANCELED; + } + + SETIOV(&in_iov, inBuf, args[1]); + ret = resmgr_msgreadv(ctp, &in_iov, 1, idx); + if (ret < args[1]) { + return EBADMSG; + } + + outBuf = (unsigned char*)CAAM_ADR_MAP(0, args[1] + BLACK_KEY_MAC_SZ, 0); + if (outBuf == NULL) { + CAAM_ADR_UNMAP(inBuf, 0, args[1], 0); + return ECANCELED; + } + + tmp[0].TheAddress = (CAAM_ADDRESS)inBuf; + tmp[0].Length = args[1]; + tmp[1].TheAddress = (CAAM_ADDRESS)outBuf; + tmp[1].Length = args[1]; /* tmp1 actually needs an additional 16 bytes + * for MAC */ + + caamDescInit(&desc, CAAM_FIFO_S, args, tmp, 2); + ret = caamKeyCover(&desc, 2, args); + CAAM_ADR_UNMAP(inBuf, 0, args[1], 0); + if (ret != Success) { + CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0); + return EBADMSG; + } + + if (args[1] + BLACK_KEY_MAC_SZ > msg->o.nbytes) { + CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0); + WOLFSSL_MSG("would cause output buffer overflow"); + return EOVERFLOW; + } + + SETIOV(&out_iov, outBuf, args[1] + BLACK_KEY_MAC_SZ); + resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + CAAM_ADR_UNMAP(outBuf, 0, args[1] + BLACK_KEY_MAC_SZ, 0); + return EOK; +} + + +/* helper function to get partition + * returns EOK on success + */ +static int doGET_PART(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb) +{ + int partNumber; + int partSz; + CAAM_ADDRESS partAddr; + iov_t out_iov; + + partNumber = args[0]; + partSz = args[1]; + + partAddr = caamGetPartition(partNumber, partSz, 0); + if (partAddr == 0) { + return EBADMSG; + } + + SETIOV(&out_iov, &partAddr, sizeof(CAAM_ADDRESS)); + resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + + pthread_mutex_lock(&sm_mutex); + sm_ownerId[partNumber] = (CAAM_ADDRESS)ocb; + pthread_mutex_unlock(&sm_mutex); + return EOK; +} + + +/* helper function to write to a partition + * returns EOK on success + */ +static int doWRITE_PART(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx) +{ + int partSz, ret; + CAAM_ADDRESS partAddr; + CAAM_ADDRESS vaddr; + unsigned char *buf; + iov_t in_iov; + + /* get arguments */ + partAddr = args[0]; + partSz = args[1]; + + buf = (unsigned char*)CAAM_ADR_MAP(0, partSz, 0); + if (buf == NULL) { + return ECANCELED; + } + + SETIOV(&in_iov, buf, partSz); + ret = resmgr_msgreadv(ctp, &in_iov, 1, idx); + if (ret != partSz) { + CAAM_ADR_UNMAP(buf, 0, partSz, 0); + return EBADMSG; + } + + /* sanity check on address and length */ + if (sanityCheckPartitionAddress(partAddr, partSz) != 0) { + CAAM_ADR_UNMAP(buf, 0, partSz, 0); + return EBADMSG; + } + + vaddr = CAAM_ADR_TO_VIRTUAL(partAddr, partSz); + if (vaddr == 0) { + CAAM_ADR_UNMAP(buf, 0, partSz, 0); + return ECANCELED; + } + + CAAM_ADR_UNMAP(buf, vaddr, partSz, 1); + CAAM_ADR_UNMAP((void*)vaddr, 0, partSz, 0); + return EOK; +} + + +/* helper function to read a partition + * returns EOK on success + */ +static int doREAD_PART(resmgr_context_t *ctp, io_devctl_t *msg, + unsigned int args[4], unsigned int idx) +{ + int partSz; + CAAM_ADDRESS partAddr; + CAAM_ADDRESS vaddr; + unsigned char *buf; + iov_t out_iov; + + /* get arguments */ + partAddr = args[0]; + partSz = args[1]; + + if (partSz > msg->o.nbytes) { + WOLFSSL_MSG("not enough space to store read bytes"); + return EOVERFLOW; + } + + /* sanity check on address and length */ + if (sanityCheckPartitionAddress(partAddr, partSz) != 0) { + return EBADMSG; + } + + buf = (unsigned char*)CAAM_ADR_MAP(0, partSz, 0); + if (buf == NULL) { + return ECANCELED; + } + + vaddr = CAAM_ADR_TO_VIRTUAL(partAddr, partSz); + if (vaddr == 0) { + CAAM_ADR_UNMAP(buf, 0, partSz, 0); + return ECANCELED; + } + + memcpy(buf, (unsigned char*)vaddr, partSz); + SETIOV(&out_iov, buf, partSz); + resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + CAAM_ADR_UNMAP(buf, 0, partSz, 0); + CAAM_ADR_UNMAP((void*)vaddr, 0, partSz, 0); + return EOK; +} + + +int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb) +{ + int ret = EBADMSG; + unsigned int idx = sizeof(msg->i); + unsigned int args[4]; + iov_t out_iov; + + /* check if at least got the msg header */ + if( ctp->size < sizeof(msg->i) ) { + return EBADMSG; + } + + if ((ret = iofunc_devctl_default (ctp, msg, ocb)) != _RESMGR_DEFAULT) { + return ret; + } + + /* check callers access rights for read/write */ + if ((ret = iofunc_devctl_verify(ctp, msg, ocb, + _IO_DEVCTL_VERIFY_OCB_READ | _IO_DEVCTL_VERIFY_OCB_WRITE)) + != EOK) { + WOLFSSL_MSG("issue verify devctl"); + return ret; + } + /* _IO_DEVCTL_VERIFY_PRIV : restrict to root */ + /* _IO_DEVCTL_VERIFY_ACC_ISUID : restrict to owner of device */ + /* _IO_DEVCTL_VERIFY_ACC_ISGID : restrict to group permissions */ + + if (getArgs(args, ctp, msg, &idx, ctp->size) != 0) { + WOLFSSL_MSG("issue reading arguments"); + return EBADMSG; + } + + switch (msg->i.dcmd) { + case WC_CAAM_CMAC: + ret = doCMAC(ctp, msg, args, idx); + break; + + case WC_TRNG_CMD: + ret = doTRNG(ctp, msg, args, idx); + break; + + case WC_CAAM_BLOB_ENCAP: + case WC_CAAM_BLOB_DECAP: + ret = doBLOB(ctp, msg, args, idx); + break; + + case WC_CAAM_ECDSA_KEYPAIR: + ret = doECDSA_KEYPAIR(ctp, msg, args, idx, ocb); + break; + + case WC_CAAM_ECDSA_VERIFY: + ret = doECDSA_VERIFY(ctp, msg, args, idx); + break; + + case WC_CAAM_ECDSA_SIGN: + ret = doECDSA_SIGN(ctp, msg, args, idx); + break; + + case WC_CAAM_ECDSA_ECDH: + ret = doECDSA_ECDH(ctp, msg, args, idx); + break; + + case WC_CAAM_FIFO_S: + ret = doFIFO_S(ctp, msg, args, idx); + break; + + case WC_CAAM_GET_PART: + ret = doGET_PART(ctp, msg, args, idx, ocb); + break; + + case WC_CAAM_FREE_PART: + caamFreePart(args[0]); + + pthread_mutex_lock(&sm_mutex); + sm_ownerId[args[0]] = 0; + pthread_mutex_unlock(&sm_mutex); + ret = EOK; + break; + + case WC_CAAM_FIND_PART: + ret = caamFindUnusuedPartition(); + if (ret < 0) { + /* none found, try again later */ + return EAGAIN; + } + SETIOV(&out_iov, &ret, sizeof(ret)); + resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o)); + ret = EOK; + break; + + case WC_CAAM_WRITE_PART: + ret = doWRITE_PART(ctp, msg, args, idx); + break; + + case WC_CAAM_READ_PART: + ret = doREAD_PART(ctp, msg, args, idx); + break; + + default: + WOLFSSL_MSG("unknown option"); + return (ENOSYS); + } + + return ret; +} + + +int io_open(resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle, + void *extra) +{ + WOLFSSL_MSG("starting up"); + return (iofunc_open_default (ctp, msg, handle, extra)); +} + + +int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb) +{ + int i; + + WOLFSSL_MSG("shutting down"); + + /* free up any dangling owned memory */ + pthread_mutex_lock(&sm_mutex); + for (i = 0; i < MAX_PART; i++) { + if (sm_ownerId[i] == (CAAM_ADDRESS)ocb) { + sm_ownerId[i] = 0; + #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) + printf("found dangiling partition at index %d\n", i); + #endif + caamFreePart(i); + } + } + pthread_mutex_unlock(&sm_mutex); + return iofunc_close_ocb_default(ctp, reserved, ocb); +} + + +#if 0 +static int getSupported(char* in) +{ + //printf("CAAM Status [0x%8.8x] = 0x%8.8x\n", + // CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS)); + printf("CAAM Version MS Register [0x%8.8x] = 0x%8.8x\n", + CAAM_VERSION_MS, CAAM_READ(CAAM_VERSION_MS)); + printf("CAAM Version LS Register [0x%8.8x] = 0x%8.8x\n", + CAAM_VERSION_LS, CAAM_READ(CAAM_VERSION_LS)); + printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n", + CAMM_SUPPORT_MS, CAAM_READ(CAMM_SUPPORT_MS)); + printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n", + CAMM_SUPPORT_LS, CAAM_READ(CAMM_SUPPORT_LS)); + + return strlen(in)+1; +} +#endif + +char cannedResponse[] = { + "wolfCrypt QNX CAAM driver\n" + "Supports:\n" + "\tAES-CMAC\n" + "\tECC (sign, verify, ecdh, keygen)\n" + "\tBlobs (black and red)\n" +}; + +/* read is only used to get banner info of the driver */ +int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb) +{ + int status; + + /* check callers access rights */ + if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) { + return (status); + } + + /* only support read not pread */ + if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) { + return (ENOSYS); + } + + if (ocb->offset == 0) { /* just fill up what can */ + int sz = min(msg->i.nbytes, sizeof(cannedResponse)); + MsgReply(ctp->rcvid, sz, cannedResponse, sz); + ocb->offset += sz; + } + else { + MsgReply(ctp->rcvid, EOK, NULL, 0); + } + + return (_RESMGR_NOREPLY); +} + + +int io_write(resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb) +{ + (void)ctp; + (void)msg; + (void)ocb; + + /* write is not supported */ + return (ENOSYS); +} + + +int main(int argc, char *argv[]) +{ + int name; + int i; + + pthread_mutex_init(&sm_mutex, NULL); + for (i = 0; i < MAX_PART; i++) { + sm_ownerId[i] = 0; + } + + if (InitCAAM() != 0) { + WOLFSSL_MSG("unable to start up caam driver!"); + exit(1); + } + + dpp = dispatch_create(); + if (dpp == NULL) { + exit (1); + } + memset (&rattr, 0, sizeof (rattr)); + iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs, + _RESMGR_IO_NFUNCS, &io_funcs); + + connect_funcs.open = io_open; + io_funcs.close_ocb = io_close_ocb; + io_funcs.read = io_read; + io_funcs.write = io_write; + io_funcs.devctl = io_devctl; + + iofunc_attr_init (&ioattr, S_IFCHR | 0666, NULL, NULL); + name = resmgr_attach (dpp, &rattr, "/dev/wolfCrypt", + _FTYPE_ANY, 0, &connect_funcs, &io_funcs, &ioattr); + if (name == -1) { + exit (1); + } + + ctp = dispatch_context_alloc(dpp); + while (1) { + ctp = dispatch_block(ctp); + if (ctp == NULL) { + CleanupCAAM(); + exit (1); + } + dispatch_handler (ctp); + } + + pthread_mutex_destroy(&sm_mutex); + CleanupCAAM(); + return 0; +} + diff --git a/wolfcrypt/src/port/caam/caam_sha.c b/wolfcrypt/src/port/caam/caam_sha.c index 74d62fb97..b681617ef 100644 --- a/wolfcrypt/src/port/caam/caam_sha.c +++ b/wolfcrypt/src/port/caam/caam_sha.c @@ -1,6 +1,6 @@ /* caam_sha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/caam/wolfcaam_cmac.c b/wolfcrypt/src/port/caam/wolfcaam_cmac.c new file mode 100644 index 000000000..c59bfca13 --- /dev/null +++ b/wolfcrypt/src/port/caam/wolfcaam_cmac.c @@ -0,0 +1,172 @@ +/* wolfcaam_cmac.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_QNX_CAAM) + +#include +#include +#include +#include + +/* returns 0 on success */ +int wc_CAAM_Cmac(Cmac* cmac, const byte* key, word32 keySz, const byte* in, + word32 inSz, byte* out, word32* outSz, int type, void* ctx) +{ + word32 args[4] = {0}; + CAAM_BUFFER buf[9]; + word32 idx = 0; + byte scratch[AES_BLOCK_SIZE]; + int ret; + int blocks = 0; + + byte* pt = (byte*)in; + int sz = inSz; + (void)type; + + args[0] = 0; + if (outSz != NULL && *outSz > 16) { + return BAD_FUNC_ARG; + } + + if (key != NULL || ctx != NULL) { + XMEMSET(&cmac->aes, 0, sizeof(Aes)); + if (ctx != NULL) { + cmac->blackKey = 1; + XMEMCPY((byte*)cmac->aes.key, (byte*)ctx, keySz + 16); + } + else { + cmac->blackKey = 0; + XMEMCPY((byte*)cmac->aes.key, (byte*)key, keySz); + } + cmac->keylen = keySz; + cmac->initialized = 0; + cmac->bufferSz = 0; + XMEMSET(cmac->buffer, 0, AES_BLOCK_SIZE); + return 0; + } + + buf[idx].TheAddress = (CAAM_ADDRESS)cmac->aes.key; + buf[idx].Length = cmac->keylen; + idx++; + + buf[idx].TheAddress = (CAAM_ADDRESS)cmac->ctx; + buf[idx].Length = sizeof(cmac->ctx); + idx++; + + if (in != NULL) { + args[0] |= CAAM_ALG_UPDATE; + + /* first take care of any left overs */ + if (cmac->bufferSz > 0) { + word32 add = min(sz, AES_BLOCK_SIZE - cmac->bufferSz); + XMEMCPY(&cmac->buffer[cmac->bufferSz], pt, add); + + cmac->bufferSz += add; + pt += add; + sz -= add; + } + + /* flash out temporary storage for block size if full and more data + * is coming, otherwise hold it until final operation */ + if (cmac->bufferSz == AES_BLOCK_SIZE && (sz > 0)) { + buf[idx].TheAddress = (CAAM_ADDRESS)scratch; + buf[idx].Length = cmac->bufferSz; + idx++; + blocks++; + cmac->bufferSz = 0; + XMEMCPY(scratch, (byte*)cmac->buffer, AES_BLOCK_SIZE); + } + + /* In order to trigger read of CTX state there needs to be some data + * saved until final call */ + if ((sz >= AES_BLOCK_SIZE) && (sz % AES_BLOCK_SIZE == 0)) { + + if (cmac->bufferSz > 0) { + /* this case should never be hit */ + return BAD_FUNC_ARG; + } + + XMEMCPY(&cmac->buffer[0], pt + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + cmac->bufferSz = AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + } + + if (sz >= AES_BLOCK_SIZE) { + buf[idx].TheAddress = (CAAM_ADDRESS)pt; + buf[idx].Length = sz - (sz % AES_BLOCK_SIZE); + blocks += sz / AES_BLOCK_SIZE; + sz -= buf[idx].Length; + pt += buf[idx].Length; + idx++; + } + + } + + if (out != NULL) { + /* handle any leftovers */ + if (cmac->bufferSz > 0) { + buf[idx].TheAddress = (CAAM_ADDRESS)cmac->buffer; + buf[idx].Length = cmac->bufferSz; + idx++; + } + + args[0] |= CAAM_ALG_FINAL; + blocks++; /* always run on final call */ + } + + /* set key size */ + args[1] = cmac->keylen; + args[2] = cmac->blackKey; + + /* only call down to CAAM if we have a full block to do or is final */ + if (blocks > 0) { + if (cmac->initialized == 0) { + args[0] |= CAAM_ALG_INIT; + cmac->initialized = 1; + } + + ret = wc_caamAddAndWait(buf, idx, args, CAAM_CMAC); + if (ret != 0) { + return -1; + } + } + + if (out != NULL) { + XMEMCPY(out, cmac->ctx, *outSz); + } + + /* store leftovers */ + if (sz > 0) { + word32 add = min(sz, AES_BLOCK_SIZE - cmac->bufferSz); + XMEMCPY(&cmac->buffer[cmac->bufferSz], pt, add); + cmac->bufferSz += add; + } + + return 0; +} + +#endif diff --git a/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c b/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c new file mode 100644 index 000000000..0f5f2f967 --- /dev/null +++ b/wolfcrypt/src/port/caam/wolfcaam_ecdsa.c @@ -0,0 +1,470 @@ +/* wolfcaam_ecdsa.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(HAVE_ECC) && defined(WOLFSSL_QNX_CAAM) + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include + +#include +#include + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +#include +#endif + +/* helper function get the ECDSEL value, this is a value that signals the + * hardware to use preloaded curve parameters + */ +static word32 GetECDSEL(int curveId, word32 PD_BIT) +{ + word32 ecdsel = 0; + + switch (curveId) { + case ECC_SECP192R1: + ecdsel = (PD_BIT | CAAM_ECDSA_P192); + break; + + case ECC_SECP224R1: + ecdsel = (PD_BIT | CAAM_ECDSA_P224); + break; + + case ECC_CURVE_DEF: + case ECC_SECP256R1: + ecdsel = (PD_BIT | CAAM_ECDSA_P256); + break; + + case ECC_SECP384R1: + ecdsel = (PD_BIT | CAAM_ECDSA_P384); + break; + + case ECC_SECP521R1: + ecdsel = (PD_BIT | CAAM_ECDSA_P521); + break; + + default: + WOLFSSL_MSG("not using preset curve parameters"); + } + + return ecdsel; +} + + +/* create signature using CAAM + * returns MP_OKAY on success + */ +int wc_CAAM_EccSign(const byte* in, int inlen, byte* out, word32* outlen, + WC_RNG *rng, ecc_key *key) +{ + const ecc_set_type* dp; + word32 args[4] = {0}; + CAAM_BUFFER buf[9] = {0}; + int ret, keySz; + word32 ecdsel = 0; + byte r[MAX_ECC_BYTES] = {0}; + byte s[MAX_ECC_BYTES] = {0}; + word32 idx = 0; + + byte pk[MAX_ECC_BYTES] = {0}; + + (void)rng; + if (key->dp != NULL) { + dp = key->dp; + } + else { + dp = wc_ecc_get_curve_params(key->idx); + } + + if (dp->id != ECC_SECP256R1) { + WOLFSSL_MSG("Limiting CAAM to P256 for now"); + return CRYPTOCB_UNAVAILABLE; + } + + /* check for known predetermined parameters */ + ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_PD); + if (ecdsel == 0) { + WOLFSSL_MSG("Unsupported curve type\n"); + return BAD_FUNC_ARG; + } + + keySz = wc_ecc_size(key); + + /* private key */ + if (key->blackKey > 0) { + buf[idx].TheAddress = (CAAM_ADDRESS)key->blackKey; + args[0] = 1; /* is a black key */ + } + else { + if (mp_to_unsigned_bin_len(&key->k, pk, keySz) != MP_OKAY) { + return MP_TO_E; + } + buf[idx].TheAddress = (CAAM_ADDRESS)pk; + args[0] = 0; /* non black key */ + } + buf[idx].Length = keySz; + idx++; + + /* hash to sign */ + buf[idx].TheAddress = (CAAM_ADDRESS)in; + buf[idx].Length = inlen; + idx++; + + /* r output */ + buf[idx].TheAddress = (CAAM_ADDRESS)r; + buf[idx].Length = keySz; + idx++; + + /* s output */ + buf[idx].TheAddress = (CAAM_ADDRESS)s; + buf[idx].Length = keySz; + idx++; + + args[1] = ecdsel; + args[2] = inlen; + args[3] = keySz; + + ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_SIGN); + if (ret != 0) + return -1; + + /* convert signature from raw bytes to signature format */ + { + mp_int mpr, mps; + + mp_init(&mpr); + mp_init(&mps); + + mp_read_unsigned_bin(&mpr, r, 32); + mp_read_unsigned_bin(&mps, s, 32); + + ret = StoreECC_DSA_Sig(out, outlen, &mpr, &mps); + mp_free(&mpr); + mp_free(&mps); + if (ret != 0) { + WOLFSSL_MSG("Issue converting to signature\n"); + return -1; + } + } + + return MP_OKAY; +} + + +/* verify with individual r and s signature parts + * returns MP_OKAY on success and sets 'res' to 1 if verified + */ +static int wc_CAAM_EccVerify_ex(mp_int* r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +{ + const ecc_set_type* dp; + word32 args[4] = {0}; + CAAM_BUFFER buf[9] = {0}; + int ret; + int keySz; + word32 idx = 0; + word32 ecdsel = 0; + + byte rbuf[MAX_ECC_BYTES] = {0}; + byte sbuf[MAX_ECC_BYTES] = {0}; + + byte qx[MAX_ECC_BYTES] = {0}; + byte qy[MAX_ECC_BYTES] = {0}; + byte qxy[MAX_ECC_BYTES * 2] = {0}; + byte tmp[MAX_ECC_BYTES * 2] = {0}; + word32 qxLen, qyLen; + + if (key->dp != NULL) { + dp = key->dp; + } + else { + dp = wc_ecc_get_curve_params(key->idx); + } + + /* right now only support P256 @TODO */ + if (dp->id != ECC_SECP256R1) { + WOLFSSL_MSG("Only support P256 verify with CAAM for now"); + return CRYPTOCB_UNAVAILABLE; + } + + /* check for known predetermined parameters */ + ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_PD); + + if (ecdsel == 0) { + WOLFSSL_MSG("Curve parameters not supported"); + return CRYPTOCB_UNAVAILABLE; + } + + /* Wx,y public key */ + keySz = wc_ecc_size(key); + if (key->securePubKey > 0) { + buf[idx].TheAddress = (CAAM_ADDRESS)key->securePubKey; + buf[idx].Length = keySz * 2; + args[0] = 1; /* using public key in secure memory */ + } + else { + qxLen = qyLen = MAX_ECC_BYTES; + wc_ecc_export_public_raw(key, qx, &qxLen, qy, &qyLen); + XMEMCPY(qxy, qx, qxLen); + XMEMCPY(qxy+qxLen, qy, qyLen); + buf[idx].TheAddress = (CAAM_ADDRESS)qxy; + buf[idx].Length = qxLen + qyLen; + } + idx++; + + buf[idx].TheAddress = (CAAM_ADDRESS)hash; + buf[idx].Length = hashlen; + idx++; + + if (mp_to_unsigned_bin_len(r, rbuf, keySz) != MP_OKAY) { + return MP_TO_E; + } + + buf[idx].TheAddress = (CAAM_ADDRESS)rbuf; + buf[idx].Length = keySz; + idx++; + + if (mp_to_unsigned_bin_len(s, sbuf, keySz) != MP_OKAY) { + return MP_TO_E; + } + + buf[idx].TheAddress = (CAAM_ADDRESS)sbuf; + buf[idx].Length = keySz; + idx++; + + /* temporary scratch buffer, the manual calls for it and HW expects it */ + buf[idx].TheAddress = (CAAM_ADDRESS)tmp; + buf[idx].Length = sizeof(tmp); + idx++; + + args[1] = ecdsel; + args[2] = hashlen; + args[3] = wc_ecc_size(key); + ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_VERIFY); + + *res = 0; + if (ret == 0) + *res = 1; + + return MP_OKAY; +} + + +/* Verify with ASN1 syntax around the signature + * returns MP_OKAY on success + */ +int wc_CAAM_EccVerify(const byte* sig, word32 siglen, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +{ + int ret; + mp_int r, s; + + + mp_init(&r); + mp_init(&s); + DecodeECC_DSA_Sig(sig, siglen, &r, &s); + ret = wc_CAAM_EccVerify_ex(&r, &s, hash, hashlen, res, key); + + mp_free(&r); + mp_free(&s); + return ret; +} + + +/* Does ECDH operation using CAAM and returns MP_OKAY on success */ +int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out, + word32* outlen) +{ + const ecc_set_type* dp; + word32 args[4] = {0}; + CAAM_BUFFER buf[9] = {0}; + int ret, keySz; + word32 ecdsel = 0; /* ecc parameters in hardware */ + word32 idx = 0; + + byte pk[MAX_ECC_BYTES] = {0}; + byte qx[MAX_ECC_BYTES] = {0}; + byte qy[MAX_ECC_BYTES] = {0}; + byte qxy[MAX_ECC_BYTES * 2] = {0}; + word32 qxSz, qySz; + + if (private_key->dp != NULL) { + dp = private_key->dp; + } + else { + dp = wc_ecc_get_curve_params(private_key->idx); + } + + if (dp->id != ECC_SECP256R1) { + return CRYPTOCB_UNAVAILABLE; + } + + /* check for known predetermined parameters */ + ecdsel = GetECDSEL(dp->id, CAAM_ECDSA_KEYGEN_PD); + if (ecdsel == 0) { /* predefined value not known, loading all parameters */ + WOLFSSL_MSG("Unsupported curve parameters"); + return CRYPTOCB_UNAVAILABLE; + } + + keySz = wc_ecc_size(private_key); + if (*outlen < (word32)keySz) { + WOLFSSL_MSG("out buffer is to small"); + return BUFFER_E; + } + + /* public key */ + if (public_key->securePubKey > 0) { + buf[idx].TheAddress = (CAAM_ADDRESS)public_key->securePubKey; + buf[idx].Length = keySz * 2; + args[1] = 1; /* using public key with secure memory address */ + } + else { + qxSz = qySz = MAX_ECC_BYTES; + wc_ecc_export_public_raw(public_key, qx, &qxSz, qy, &qySz); + XMEMCPY(qxy, qx, qxSz); + XMEMCPY(qxy+qxSz, qy, qySz); + buf[idx].TheAddress = (CAAM_ADDRESS)qxy; + buf[idx].Length = qxSz + qySz; + } + idx++; + + /* private key */ + if (private_key->blackKey > 0) { + buf[idx].TheAddress = (CAAM_ADDRESS)private_key->blackKey; + args[0] = 1; /* is a black key */ + } + else { + if (keySz > MAX_ECC_BYTES) { + return BUFFER_E; + } + + if (mp_to_unsigned_bin_len(&private_key->k, pk, keySz) != MP_OKAY) { + return MP_TO_E; + } + + buf[idx].TheAddress = (CAAM_ADDRESS)pk; + args[0] = 0; /* non black key */ + } + buf[idx].Length = keySz; + idx++; + + /* output shared secret */ + buf[idx].TheAddress = (CAAM_ADDRESS)out; + buf[idx].Length = keySz; + idx++; + + args[2] = ecdsel; + args[3] = keySz; + ret = wc_caamAddAndWait(buf, idx, args, CAAM_ECDSA_ECDH); + if (ret == 0) { + *outlen = keySz; + return MP_OKAY; + } + else { + return -1; + } +} + + +/* [ private black key ] [ x , y ] */ +int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId) +{ + word32 args[4] = {0}; + CAAM_BUFFER buf[2] = {0}; + word32 ecdsel = 0; + + int ret; + + byte s[MAX_ECC_BYTES] = {0}; + byte xy[MAX_ECC_BYTES*2] = {0}; + + key->type = ECC_PRIVATEKEY; + + /* if set to default curve then assume SECP256R1 */ + if (keySize == 32 && curveId == ECC_CURVE_DEF) curveId = ECC_SECP256R1; + + if (curveId != ECC_SECP256R1) { + /* currently only implemented P256 support */ + return CRYPTOCB_UNAVAILABLE; + } + + ecdsel = GetECDSEL(curveId, CAAM_ECDSA_KEYGEN_PD); + if (ecdsel == 0) { + WOLFSSL_MSG("unknown key type or size"); + return CRYPTOCB_UNAVAILABLE; + } + + (void)rng; + + buf[0].TheAddress = (CAAM_ADDRESS)s; + buf[0].Length = keySize; + buf[1].TheAddress = (CAAM_ADDRESS)xy; + buf[1].Length = keySize*2; + + args[0] = 1; /* Creating Black Key */ + args[1] = ecdsel; + + ret = wc_caamAddAndWait(buf, 2, args, CAAM_ECDSA_KEYPAIR); + if (args[0] == 1 && ret == 0) { + key->blackKey = (word32)buf[0].TheAddress; + key->securePubKey = (word32)buf[1].TheAddress; + key->partNum = args[2]; + return MP_OKAY; + } + if (args[0] == 0 && ret == 0) { + if (wc_ecc_import_unsigned(key, xy, xy + keySize, + s, curveId) != 0) { + WOLFSSL_MSG("issue importing key"); + return -1; + } + return MP_OKAY; + } + return -1; +} + + +/* if dealing with a black encrypted key then it can not be checked */ +int wc_CAAM_EccCheckPrivKey(ecc_key* key, const byte* pubKey, word32 pubKeySz) { + (void)pubKey; + (void)pubKeySz; + + if (key->dp->id == ECC_SECP256R1 && key->blackKey > 0) { + return 0; + } + return CRYPTOCB_UNAVAILABLE; +} + +#endif /* HAVE_ECC && WOLFSSL_QNX_CAAM */ diff --git a/wolfcrypt/src/port/caam/wolfcaam_init.c b/wolfcrypt/src/port/caam/wolfcaam_init.c new file mode 100644 index 000000000..aa1d44e73 --- /dev/null +++ b/wolfcrypt/src/port/caam/wolfcaam_init.c @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB) + +#include +#include +#include + +/* determine which porting header to include */ +#if defined(__INTEGRITY) || defined(INTEGRITY) + #ifndef WC_CAAM_PASSWORD + #define WC_CAAM_PASSWORD "!systempassword" + #endif + + #include + static IODevice caam = NULLIODevice; + #define CAAM_SEND_REQUEST(type, sz, arg, buf) \ + SynchronousSendIORequest(caam, (type), (const Value*)(arg), (buf)) +#endif + + + +#if defined(__INTEGRITY) || defined(INTEGRITY) +/* Allow runtime setting for CAAM IODevice in case user wants to use password + * at run time. + * + * returns 0 on success + * + * NOTE this is how IODevice is defined in INTEGRITY "typedef struct + * IODeviceStruct *IODevice;" + */ +int wc_caamSetResource(IODevice ioDev) +{ + WOLFSSL_MSG("Setting CAAM driver"); + caam = ioDev; + return 0; +} +#endif + + +/* used to route crypto operations through crypto callback */ +static int wc_CAAM_router(int devId, wc_CryptoInfo* info, void* ctx) +{ + int ret = CRYPTOCB_UNAVAILABLE; + + (void)ctx; + (void)devId; + switch (info->algo_type) { + case WC_ALGO_TYPE_PK: + switch (info->pk.type) { + case WC_PK_TYPE_ECDSA_SIGN: + ret = wc_CAAM_EccSign(info->pk.eccsign.in, + info->pk.eccsign.inlen, info->pk.eccsign.out, + info->pk.eccsign.outlen, info->pk.eccsign.rng, + info->pk.eccsign.key); + break; + + case WC_PK_TYPE_ECDSA_VERIFY: + ret = wc_CAAM_EccVerify(info->pk.eccverify.sig, + info->pk.eccverify.siglen, info->pk.eccverify.hash, + info->pk.eccverify.hashlen, info->pk.eccverify.res, + info->pk.eccverify.key); + break; + + case WC_PK_TYPE_EC_KEYGEN: + ret = wc_CAAM_MakeEccKey(info->pk.eckg.rng, + info->pk.eckg.size, info->pk.eckg.key, + info->pk.eckg.curveId); + break; + + case WC_PK_TYPE_ECDH: + ret = wc_CAAM_Ecdh(info->pk.ecdh.private_key, + info->pk.ecdh.public_key, info->pk.ecdh.out, + info->pk.ecdh.outlen); + break; + + case WC_PK_TYPE_EC_CHECK_PRIV_KEY: + ret = wc_CAAM_EccCheckPrivKey(info->pk.ecc_check.key, + info->pk.ecc_check.pubKey, + info->pk.ecc_check.pubKeySz); + break; + + default: + WOLFSSL_MSG("unsupported public key operation"); + } + break; + + case WC_ALGO_TYPE_CMAC: + #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && \ + defined(WOLFSSL_AES_DIRECT) + ret = wc_CAAM_Cmac(info->cmac.cmac, info->cmac.key, + info->cmac.keySz, info->cmac.in, info->cmac.inSz, + info->cmac.out, info->cmac.outSz, info->cmac.type, + info->cmac.ctx); + #else + WOLFSSL_MSG("CMAC not compiled in"); + ret = NOT_COMPILED_IN; + #endif + break; + + case WC_ALGO_TYPE_NONE: + case WC_ALGO_TYPE_HASH: + case WC_ALGO_TYPE_CIPHER: + case WC_ALGO_TYPE_RNG: + case WC_ALGO_TYPE_SEED: + case WC_ALGO_TYPE_HMAC: + default: + /* Not implemented yet with CAAM */ + ret = CRYPTOCB_UNAVAILABLE; + } + + return ret; +} + + +/* Check hardware support + * + * returns 0 on success + */ +int wc_caamInit(void) +{ + WOLFSSL_MSG("Starting interface with CAAM driver"); + if (CAAM_INIT_INTERFACE() != 0) { + WOLFSSL_MSG("Error initializing CAAM"); + return -1; + } + +#if 0 + /* check that for implemented modules + * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG, 28-31 public key module */ + reg = WC_CAAM_READ(CAMM_SUPPORT_LS); + + #ifndef WC_NO_RNG + if (((reg & 0x000F0000) >> 16) > 0) { + WOLFSSL_MSG("Found CAAM RNG hardware module"); + if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) { + WOLFSSL_MSG("Error CAAM RNG has not been set up"); + } + } + #endif + + #ifndef NO_SHA256 + if ((reg & 0x0000F000) > 0) { + WOLFSSL_MSG("Found CAAM MDHA module"); + } + else { + WOLFSSL_MSG("Hashing not supported by CAAM"); + return WC_HW_E; + } + #endif + + #ifndef NO_AES + if ((reg & 0x0000000F) > 0) { + WOLFSSL_MSG("Found CAAM AES module"); + } + else { + WOLFSSL_MSG("AES not supported by CAAM"); + return WC_HW_E; + } + #endif + + #ifdef HAVE_ECC + if ((reg & 0xF0000000) > 0) { + WOLFSSL_MSG("Found CAAM Public Key module"); + } + else { + WOLFSSL_MSG("Public Key not supported by CAAM"); + } + #endif +#endif + + return wc_CryptoDev_RegisterDevice(WOLFSSL_CAAM_DEVID, wc_CAAM_router, + NULL); +} + + +/* free up all resources used for CAAM */ +int wc_caamFree(void) +{ + CAAM_FREE_INTERFACE(); + return 0; +} + + +#ifndef WOLFSSL_QNX_CAAM +word32 wc_caamReadRegister(word32 reg) +{ + word32 out = 0; + + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return 0; + } + + if (ReadIODeviceRegister(caam, reg, &out) != Success) { + WOLFSSL_MSG("Error reading register\n"); + } + + return (word32)out; +} + + +/* returns 0 on success */ +int wc_caamWriteRegister(word32 reg, word32 value) +{ + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return -1; + } + + if (WriteIODeviceRegister(caam, reg, value) != Success) { + WOLFSSL_MSG("Error writing to register\n"); + } + return 0; +} +#endif + + +/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E + * in the case that the driver is waiting for a resource or RAN_BLOCK_E if + * waiting for entropy. */ +int wc_caamAddAndWait(CAAM_BUFFER* buf, int sz, word32 arg[4], word32 type) +{ + int ret; +#ifdef DEBUG_WOLFSSL + static int wait = 0; +#endif + +#ifndef WOLFSSL_QNX_CAAM + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return WC_HW_E; + } +#endif + + if ((ret = CAAM_SEND_REQUEST(type, sz, arg, buf)) != Success) { + /* if waiting for resource or RNG return waiting */ + if (ret == CAAM_WAITING) { + #ifdef DEBUG_WOLFSSL + if (wait == 0) { + wait = 1; + WOLFSSL_MSG("Waiting on entropy from driver"); + } + fprintf(stderr, "."); + #endif + return RAN_BLOCK_E; + } + + if (ret == ResourceNotAvailable) { + WOLFSSL_MSG("Waiting on CAAM driver"); + return WC_HW_WAIT_E; + } + + return WC_HW_E; + } +#ifdef DEBUG_WOLFSSL + if (wait) { + wait = 0; + fprintf(stderr, "\n"); + } +#endif + + (void)ret; + return 0; +} + + +/* Create a red or black blob + * + * mod : key modifier, expected 8 bytes for RED key types and 16 for BLACK + * if 'mod' is null than 0's are used + * + * returns 0 on success + */ +int wc_caamCreateBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz, + int type, byte* mod, word32 modSz) +{ + CAAM_BUFFER in[3]; + word32 arg[4]; + int ret; + byte local[WC_CAAM_BLACK_KEYMOD_SZ] = {0}; + byte* keyMod; + int keyModSz; + + keyMod = mod; + XMEMSET(local, 0, sizeof(local)); + if (data == NULL || out == NULL || outSz == NULL || + *outSz < dataSz + WC_CAAM_BLOB_SZ) { + return BAD_FUNC_ARG; + } + + if (type == WC_CAAM_BLOB_RED) { + arg[0] = 0; + if (mod != NULL) { + if (modSz != WC_CAAM_RED_KEYMOD_SZ) { + WOLFSSL_MSG("bad key mod red size"); + return BAD_FUNC_ARG; + } + } + keyModSz = WC_CAAM_RED_KEYMOD_SZ; + } + else if (type == WC_CAAM_BLOB_BLACK) { + arg[0] = 1; + if (mod != NULL) { + if (modSz != WC_CAAM_BLACK_KEYMOD_SZ) { + WOLFSSL_MSG("bad key mod black size"); + return BAD_FUNC_ARG; + } + } + keyModSz = WC_CAAM_BLACK_KEYMOD_SZ; + } + else { + WOLFSSL_MSG("unknown blob type!"); + return BAD_FUNC_ARG; + } + + if (mod == NULL) { + WOLFSSL_MSG("using local all 0's key modifier"); + keyMod = local; + } + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (CAAM_ADDRESS)keyMod; + in[0].Length = keyModSz; + + in[1].BufferType = DataBuffer; + in[1].TheAddress = (CAAM_ADDRESS)data; + in[1].Length = dataSz; + + in[2].BufferType = DataBuffer | LastBuffer; + in[2].TheAddress = (CAAM_ADDRESS)out; + in[2].Length = dataSz + WC_CAAM_BLOB_SZ; + + arg[2] = dataSz; + arg[3] = keyModSz; + + if ((ret = wc_caamAddAndWait(in, 3, arg, CAAM_BLOB_ENCAP)) != 0) { + WOLFSSL_MSG("Error with CAAM blob create"); + return ret; + } + + *outSz = dataSz + WC_CAAM_BLOB_SZ; + return 0; +} + + +/* create a red key blob + * returns 0 on success */ +int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz) +{ + return wc_caamCreateBlob_ex(data, dataSz, out, outSz, WC_CAAM_BLOB_RED, + NULL, 0); +} + + +/* uncover black or red keys + * returns 0 on success */ +int wc_caamOpenBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz, + int type, byte* mod, word32 modSz) +{ + CAAM_BUFFER in[3]; + word32 arg[4]; + int ret; + byte local[WC_CAAM_BLACK_KEYMOD_SZ]; + byte* keyMod; + int keyModSz; + + keyMod = mod; + XMEMSET(local, 0, sizeof(local)); + + if (data == NULL || out == NULL || outSz == NULL || + *outSz < dataSz - WC_CAAM_BLOB_SZ) { + WOLFSSL_MSG("NULL argument or outSz is too small"); + return BAD_FUNC_ARG; + } + + if (type == WC_CAAM_BLOB_RED) { + arg[0] = 0; + if (mod != NULL) { + if (modSz != WC_CAAM_RED_KEYMOD_SZ) { + WOLFSSL_MSG("bad key mod red size"); + return BAD_FUNC_ARG; + } + } + keyModSz = WC_CAAM_RED_KEYMOD_SZ; + } + else if (type == WC_CAAM_BLOB_BLACK) { + arg[0] = 1; + if (mod != NULL) { + if (modSz != WC_CAAM_BLACK_KEYMOD_SZ) { + WOLFSSL_MSG("bad key mod black size"); + return BAD_FUNC_ARG; + } + } + keyModSz = WC_CAAM_BLACK_KEYMOD_SZ; + } + else { + WOLFSSL_MSG("unknown blob type!"); + return BAD_FUNC_ARG; + } + + if (mod == NULL) { + WOLFSSL_MSG("using local all 0's key modifier"); + keyMod = local; + } + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (CAAM_ADDRESS)keyMod; + in[0].Length = keyModSz; + + in[1].BufferType = DataBuffer; + in[1].TheAddress = (CAAM_ADDRESS)data; + in[1].Length = dataSz; + + in[2].BufferType = DataBuffer | LastBuffer; + in[2].TheAddress = (CAAM_ADDRESS)out; + in[2].Length = dataSz - WC_CAAM_BLOB_SZ; + + arg[2] = dataSz; + arg[3] = keyModSz; + + if ((ret = wc_caamAddAndWait(in, 3, arg, CAAM_BLOB_DECAP)) != 0) { + WOLFSSL_MSG("Error with CAAM blob open"); + return ret; + } + + *outSz = dataSz - WC_CAAM_BLOB_SZ; + return 0; +} + + +/* open a red blob + * returns 0 on success */ +int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz) +{ + return wc_caamOpenBlob_ex(data, dataSz, out, outSz, WC_CAAM_BLOB_RED, + NULL, 0); +} + + +/* outSz gets set to key size plus 16 for mac and padding + * return 0 on success + */ +int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, int flag) +{ + CAAM_BUFFER buf[2]; + word32 arg[4]; + int ret; + + if (*outSz < inSz + WC_CAAM_MAC_SZ) { + return BUFFER_E; + } + + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (CAAM_ADDRESS)in; + buf[0].Length = inSz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (CAAM_ADDRESS)out; + buf[1].Length = inSz; + + (void)flag; /* for now defaulting to use highest security AES-CCM here */ + arg[0] = CAAM_FIFO_CCM_FLAG; + arg[1] = inSz; + if ((ret = wc_caamAddAndWait(buf, 2, arg, CAAM_FIFO_S)) != 0) { + WOLFSSL_MSG("Error with CAAM blob create"); + return ret; + } + + *outSz = inSz + WC_CAAM_MAC_SZ; + return 0; +} + + +/* return 0 or greater on success for the partition number available + * returns a negative value on failure + */ +int caamFindUnusuedPartition() +{ + CAAM_BUFFER buf[1]; + word32 arg[4]; + int ret = 0; + + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (CAAM_ADDRESS)&ret; + buf[0].Length = sizeof(int); + + if ((wc_caamAddAndWait(buf, 1, arg, CAAM_FIND_PART)) != 0) { + WOLFSSL_MSG("Error finding a partition to use"); + return -1; + } + + return ret; +} + + +/* return the address of the given partition number "part" */ +CAAM_ADDRESS caamGetPartition(int part, int sz) +{ + CAAM_BUFFER buf[1]; + word32 arg[4]; + CAAM_ADDRESS ret = 0; + + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (CAAM_ADDRESS)(&ret); + buf[0].Length = sizeof(int); + + arg[0] = part; + arg[1] = sz; + + if ((wc_caamAddAndWait(buf, 1, arg, CAAM_GET_PART)) != 0) { + WOLFSSL_MSG("Error getting a partition"); + return -1; + } + + return ret; +} + + +/* Internal function to free a secure partition + * return 0 on success */ +int caamFreePart(int partNum) +{ + word32 arg[4]; + + arg[0] = partNum; + + if ((wc_caamAddAndWait(NULL, 0, arg, CAAM_FREE_PART)) != 0) { + WOLFSSL_MSG("Error freeing a partition"); + return -1; + } + + return 0; +} + + +/* Internal function to help write to a secure partition + * return 0 on success */ +int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* in, int inSz) +{ + CAAM_BUFFER buf[1]; + word32 arg[4]; + + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (CAAM_ADDRESS)in; + buf[0].Length = inSz; + + arg[0] = addr; + arg[1] = inSz; + + if ((wc_caamAddAndWait(buf, 1, arg, CAAM_WRITE_PART)) != 0) { + WOLFSSL_MSG("Error writing to a partition"); + return -1; + } + + return 0; +} + + +/* Internal function to help read from a secure partition + * return 0 on success */ +int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz) +{ + CAAM_BUFFER buf[1]; + word32 arg[4]; + + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (CAAM_ADDRESS)out; + buf[0].Length = outSz; + + arg[0] = addr; + arg[1] = outSz; + + if ((wc_caamAddAndWait(buf, 1, arg, CAAM_READ_PART)) != 0) { + WOLFSSL_MSG("Error reading a partition"); + return -1; + } + + return 0; +} + +#endif /* WOLFSSL_IMX6_CAAM */ + diff --git a/wolfcrypt/src/port/caam/wolfcaam_qnx.c b/wolfcrypt/src/port/caam/wolfcaam_qnx.c new file mode 100644 index 000000000..1e9c50ef3 --- /dev/null +++ b/wolfcrypt/src/port/caam/wolfcaam_qnx.c @@ -0,0 +1,352 @@ +/* wolfcaam_qnx.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_QNX_CAAM) + +#include +#include +#include +#include +#include +#include + +/* for devctl use */ +int caamFd = -1; +wolfSSL_Mutex caamMutex; + +/* return 0 on success */ +int wc_CAAMInitInterface() +{ + if (wc_InitMutex(&caamMutex) != 0) { + WOLFSSL_MSG("Could not init mutex"); + return -1; + } + + caamFd = open("/dev/wolfCrypt", O_RDWR); + if (caamFd < 0) { + WOLFSSL_MSG("Could not open /dev/wolfCrypt"); + return -1; + } + + return 0; +} + + +void wc_CAAMFreeInterface() +{ + wc_FreeMutex(&caamMutex); + if (caamFd >= 0) + close(caamFd); +} + +#define WC_TRNG_CMD __DIOTF(_DCMD_ALL, CAAM_ENTROPY, iov_t) +#define WC_CAAM_GET_PART __DIOTF(_DCMD_ALL, CAAM_GET_PART, iov_t) +#define WC_CAAM_FREE_PART __DIOT(_DCMD_ALL, CAAM_FREE_PART, iov_t) +#define WC_CAAM_FIND_PART __DIOTF(_DCMD_ALL, CAAM_FIND_PART, iov_t) +#define WC_CAAM_READ_PART __DIOTF(_DCMD_ALL, CAAM_READ_PART, iov_t) +#define WC_CAAM_WRITE_PART __DIOT(_DCMD_ALL, CAAM_WRITE_PART, iov_t) + +#define WC_CAAM_ECDSA_KEYPAIR __DIOTF(_DCMD_ALL, CAAM_ECDSA_KEYPAIR, iov_t) +#define WC_CAAM_ECDSA_VERIFY __DIOT(_DCMD_ALL, CAAM_ECDSA_VERIFY, iov_t) +#define WC_CAAM_ECDSA_SIGN __DIOTF(_DCMD_ALL, CAAM_ECDSA_SIGN, iov_t) +#define WC_CAAM_ECDSA_ECDH __DIOTF(_DCMD_ALL, CAAM_ECDSA_ECDH, iov_t) + +#define WC_CAAM_BLOB_ENCAP __DIOTF(_DCMD_ALL, CAAM_BLOB_ENCAP, iov_t) +#define WC_CAAM_BLOB_DECAP __DIOTF(_DCMD_ALL, CAAM_BLOB_DECAP, iov_t) + +#define WC_CAAM_CMAC __DIOTF(_DCMD_ALL, CAAM_CMAC, iov_t) + +#define WC_CAAM_FIFO_S __DIOTF(_DCMD_ALL, CAAM_FIFO_S, iov_t) + +#define MAX_IN_IOVS 5 +#define MAX_OUT_IOVS 3 + +/* Do a synchronous operations and block till done + * returns 0 on success */ +int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, + int sz) +{ + int ret, inIdx = 0, outIdx = 0; + int cmd = 0; + iov_t in[MAX_IN_IOVS], out[MAX_OUT_IOVS]; + CAAM_ADDRESS pubkey, privkey; + + if (args != NULL) { + SETIOV(&in[inIdx], args, sizeof(unsigned int) * 4); + inIdx = inIdx + 1; + } + else { + unsigned int localArgs[4] = {0}; + SETIOV(&in[inIdx], localArgs, sizeof(unsigned int) * 4); + inIdx = inIdx + 1; + } + + switch (type) { + case CAAM_ENTROPY: + SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length)); + outIdx = outIdx + 1; + cmd = WC_TRNG_CMD; + break; + + case CAAM_GET_PART: + SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length)); + outIdx = outIdx + 1; + cmd = WC_CAAM_GET_PART; + break; + + case CAAM_FREE_PART: + cmd = WC_CAAM_FREE_PART; + break; + + case CAAM_FIND_PART: + SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length)); + outIdx = outIdx + 1; + cmd = WC_CAAM_FIND_PART; + break; + + case CAAM_READ_PART: + SETIOV(&out[outIdx], (buf->TheAddress), (buf->Length)); + outIdx = outIdx + 1; + cmd = WC_CAAM_READ_PART; + break; + + case CAAM_WRITE_PART: + SETIOV(&in[inIdx], (buf->TheAddress), (buf->Length)); + inIdx = inIdx + 1; + cmd = WC_CAAM_WRITE_PART; + break; + + case CAAM_ECDSA_KEYPAIR: + /* set input to get lengths */ + SETIOV(&in[inIdx], &buf[0], sizeof(CAAM_BUFFER)); + inIdx = inIdx + 1; + + SETIOV(&in[inIdx], &buf[1], sizeof(CAAM_BUFFER)); + inIdx = inIdx + 1; + + /* set output to store directly to CAAM_BUFFER's */ + SETIOV(&out[outIdx], &buf[0], sizeof(CAAM_BUFFER)); + outIdx = outIdx + 1; + + SETIOV(&out[outIdx], &buf[1], sizeof(CAAM_BUFFER)); + outIdx = outIdx + 1; + + /* get args for updated partition number used */ + SETIOV(&out[outIdx], args, sizeof(unsigned int) * 4); + outIdx = outIdx + 1; + + cmd = WC_CAAM_ECDSA_KEYPAIR; + break; + + case CAAM_ECDSA_VERIFY: + /* public key */ + if (args[0] == 1) { + pubkey = buf[0].TheAddress; + SETIOV(&in[inIdx], &pubkey, sizeof(CAAM_ADDRESS)); + inIdx = inIdx + 1; + } + else { + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + } + + /* msg */ + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); + inIdx = inIdx + 1; + + /* r */ + SETIOV(&in[inIdx], buf[2].TheAddress, buf[2].Length); + inIdx = inIdx + 1; + + /* s */ + SETIOV(&in[inIdx], buf[3].TheAddress, buf[3].Length); + inIdx = inIdx + 1; + + cmd = WC_CAAM_ECDSA_VERIFY; + break; + + case CAAM_ECDSA_SIGN: + /* private key */ + if (args[0] == 1) { + privkey = buf[0].TheAddress; + SETIOV(&in[inIdx], &privkey, sizeof(CAAM_ADDRESS)); + inIdx = inIdx + 1; + } + else { + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + } + + /* msg */ + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); + inIdx = inIdx + 1; + + /* r out */ + SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length); + outIdx = outIdx + 1; + + /* s out */ + SETIOV(&out[outIdx], buf[3].TheAddress, buf[3].Length); + outIdx = outIdx + 1; + + cmd = WC_CAAM_ECDSA_SIGN; + break; + + case CAAM_ECDSA_ECDH: + /* when using memory in secure partition just send the address */ + if (args[1] == 1) { + pubkey = buf[0].TheAddress; + SETIOV(&in[inIdx], &pubkey, sizeof(CAAM_ADDRESS)); + inIdx = inIdx + 1; + } + else { + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + } + + /* private key */ + if (args[0] == 1) { + privkey = buf[1].TheAddress; + SETIOV(&in[inIdx], &privkey, sizeof(CAAM_ADDRESS)); + inIdx = inIdx + 1; + } + else { + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); + inIdx = inIdx + 1; + } + + /* shared secret */ + SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length); + outIdx = outIdx + 1; + + cmd = WC_CAAM_ECDSA_ECDH; + break; + + case CAAM_BLOB_ENCAP: + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + + if (args[0] == 1) { + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length + WC_CAAM_MAC_SZ); + inIdx = inIdx + 1; + } + else { + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); + inIdx = inIdx + 1; + } + + SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length); + outIdx = outIdx + 1; + cmd = WC_CAAM_BLOB_ENCAP; + break; + + case CAAM_BLOB_DECAP: + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); + inIdx = inIdx + 1; + + if (args[0] == 1) { + SETIOV(&out[outIdx], buf[2].TheAddress, + buf[2].Length + WC_CAAM_MAC_SZ); + outIdx = outIdx + 1; + } + else { + SETIOV(&out[outIdx], buf[2].TheAddress, buf[2].Length); + outIdx = outIdx + 1; + } + + cmd = WC_CAAM_BLOB_DECAP; + break; + + case CAAM_CMAC: + { + int i; + + if (args[2] == 1) { + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length + 16); + inIdx = inIdx + 1; + } + else { + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + } + + SETIOV(&in[inIdx], buf[1].TheAddress, buf[1].Length); + inIdx = inIdx + 1; + + /* get input buffers */ + args[3] = 0; + for (i = 2; i < sz && i < MAX_IN_IOVS; i++) { + SETIOV(&in[inIdx], buf[i].TheAddress, buf[i].Length); + inIdx = inIdx + 1; + args[3] += buf[i].Length; + } + + SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length); + outIdx = outIdx + 1; + } + cmd = WC_CAAM_CMAC; + break; + + case CAAM_FIFO_S: + SETIOV(&in[inIdx], buf[0].TheAddress, buf[0].Length); + inIdx = inIdx + 1; + + SETIOV(&out[outIdx], buf[1].TheAddress, buf[1].Length + WC_CAAM_MAC_SZ); + outIdx = outIdx + 1; + cmd = WC_CAAM_FIFO_S; + break; + + default: + WOLFSSL_MSG("Unknown/unsupported type"); + return -1; + } + + ret = wc_LockMutex(&caamMutex); + if (ret == 0) { + ret = devctlv(caamFd, cmd, inIdx, outIdx, in, out, NULL); + wc_UnLockMutex(&caamMutex); + } + + if (ret != 0) { + if (ret == EFAULT) { + WOLFSSL_MSG("bad address on one of the in/out buffers"); + return -1; + } + + if (ret == EAGAIN && type == CAAM_ENTROPY) { + return CAAM_WAITING; + } + return -1; + } + + return Success; +} + +#endif diff --git a/wolfcrypt/src/port/cavium/cavium_octeon_sync.c b/wolfcrypt/src/port/cavium/cavium_octeon_sync.c index 078e8cb52..8329e5c77 100644 --- a/wolfcrypt/src/port/cavium/cavium_octeon_sync.c +++ b/wolfcrypt/src/port/cavium/cavium_octeon_sync.c @@ -1,13 +1,13 @@ /* cavium_octeon_sync.c * - * Copyright(C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL.(formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or - *(at your option) any later version. + * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifdef HAVE_CONFIG_H diff --git a/wolfcrypt/src/port/cypress/psoc6_crypto.c b/wolfcrypt/src/port/cypress/psoc6_crypto.c index b00be7714..05e63b0c8 100644 --- a/wolfcrypt/src/port/cypress/psoc6_crypto.c +++ b/wolfcrypt/src/port/cypress/psoc6_crypto.c @@ -1,6 +1,6 @@ /* psoc6_crypto.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/devcrypto/devcrypto_aes.c b/wolfcrypt/src/port/devcrypto/devcrypto_aes.c index 1f6d09d72..5a7221b4d 100644 --- a/wolfcrypt/src/port/devcrypto/devcrypto_aes.c +++ b/wolfcrypt/src/port/devcrypto/devcrypto_aes.c @@ -1,6 +1,6 @@ /* devcrypto_aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/devcrypto/devcrypto_hash.c b/wolfcrypt/src/port/devcrypto/devcrypto_hash.c index f73224dd8..09ed5f1ab 100644 --- a/wolfcrypt/src/port/devcrypto/devcrypto_hash.c +++ b/wolfcrypt/src/port/devcrypto/devcrypto_hash.c @@ -1,6 +1,6 @@ /* devcrypto_hash.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/devcrypto/wc_devcrypto.c b/wolfcrypt/src/port/devcrypto/wc_devcrypto.c index 2c80518a3..23a613932 100644 --- a/wolfcrypt/src/port/devcrypto/wc_devcrypto.c +++ b/wolfcrypt/src/port/devcrypto/wc_devcrypto.c @@ -1,6 +1,6 @@ /* wc_devcrypto.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -72,7 +72,7 @@ int wc_DevCryptoCreate(WC_CRYPTODEV* ctx, int type, byte* key, word32 keySz) } if (fcntl(fd, F_SETFD, 1) == -1) { WOLFSSL_MSG("Error setting F_SETFD with fcntl"); - close(fd); + (void)close(fd); return WC_DEVCRYPTO_E; } @@ -89,7 +89,7 @@ int wc_DevCryptoCreate(WC_CRYPTODEV* ctx, int type, byte* key, word32 keySz) } if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) { - close(fd); + (void)close(fd); WOLFSSL_MSG("Error starting cryptodev session"); return WC_DEVCRYPTO_E; } @@ -108,7 +108,7 @@ void wc_DevCryptoFree(WC_CRYPTODEV* ctx) if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { WOLFSSL_MSG("Error stopping cryptodev session"); } - close(ctx->cfd); + (void)close(ctx->cfd); } } diff --git a/wolfcrypt/src/port/intel/quickassist_sync.c b/wolfcrypt/src/port/intel/quickassist_sync.c index e03bca91f..14a45dc99 100644 --- a/wolfcrypt/src/port/intel/quickassist_sync.c +++ b/wolfcrypt/src/port/intel/quickassist_sync.c @@ -1,8 +1,8 @@ /* quickassist_sync.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifdef HAVE_CONFIG_H diff --git a/wolfcrypt/src/port/mynewt/mynewt_port.c b/wolfcrypt/src/port/mynewt/mynewt_port.c index 8a4e903fb..ee284d76b 100644 --- a/wolfcrypt/src/port/mynewt/mynewt_port.c +++ b/wolfcrypt/src/port/mynewt/mynewt_port.c @@ -1,6 +1,6 @@ /* mynewt_port.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/nrf51.c b/wolfcrypt/src/port/nrf51.c index 042fe9da4..4a2eda0bb 100644 --- a/wolfcrypt/src/port/nrf51.c +++ b/wolfcrypt/src/port/nrf51.c @@ -1,6 +1,6 @@ /* nrf51.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/nxp/dcp_port.c b/wolfcrypt/src/port/nxp/dcp_port.c index 5ef5b7588..f00089409 100644 --- a/wolfcrypt/src/port/nxp/dcp_port.c +++ b/wolfcrypt/src/port/nxp/dcp_port.c @@ -1,6 +1,6 @@ /* dcp_port.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,24 +19,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include -#ifdef NO_INLINE - #include -#else - #define WOLFSSL_MISC_INCLUDED - #include -#endif +#ifdef WOLFSSL_IMXRT_DCP #include #include #include #include -#ifdef WOLFSSL_IMXRT_DCP #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) && defined(DCP_USE_DCACHE) && (DCP_USE_DCACHE == 1U) #error "DCACHE not supported by this driver. Please undefine DCP_USE_DCACHE." #endif @@ -45,14 +40,14 @@ #define DCP_USE_OTP_KEY 0 /* Set to 1 to select OTP key for AES encryption/decryption. */ #endif -#include "fsl_device_registers.h" -#include "fsl_debug_console.h" #include "fsl_dcp.h" #ifndef SINGLE_THREADED +#define dcp_lock_init() wolfSSL_CryptHwMutexInit() #define dcp_lock() wolfSSL_CryptHwMutexLock() -#define dcp_unlock() wolfSSL_CryptHwMutexLock() +#define dcp_unlock() wolfSSL_CryptHwMutexUnLock() #else +#define dcp_lock_init() do{}while(0) #define dcp_lock() do{}while(0) #define dcp_unlock() do{}while(0) #endif @@ -126,6 +121,7 @@ static int dcp_get_channel(void) if (dcp_status[i] == 0) { dcp_status[i]++; ret = dcp_channels[i]; + break; } } dcp_unlock(); @@ -161,6 +157,7 @@ static int dcp_key_slot(int ch) int wc_dcp_init(void) { dcp_config_t dcpConfig; + dcp_lock_init(); dcp_lock(); DCP_GetDefaultConfig(&dcpConfig); @@ -202,8 +199,8 @@ int DCPAesInit(Aes *aes) if (ch == 0) return WC_PENDING_E; XMEMSET(&aes->handle, 0, sizeof(aes->handle)); - aes->handle.channel = ch; - aes->handle.keySlot = dcp_key_slot(aes->handle.channel); + aes->handle.channel = (dcp_channel_t)ch; + aes->handle.keySlot = (dcp_key_slot_t)dcp_key_slot(aes->handle.channel); aes->handle.swapConfig = kDCP_NoSwap; return 0; } @@ -211,8 +208,11 @@ int DCPAesInit(Aes *aes) void DCPAesFree(Aes *aes) { dcp_free(aes->handle.channel); + aes->handle.channel = 0; } + +static unsigned char aes_key_aligned[16] __attribute__((aligned(0x10))); int DCPAesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, int dir) { @@ -227,10 +227,12 @@ int DCPAesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, if (len != 16) return BAD_FUNC_ARG; if (aes->handle.channel == 0) { - return BAD_FUNC_ARG; + if (DCPAesInit(aes) != 0) + return WC_HW_E; } dcp_lock(); - status = DCP_AES_SetKey(DCP, &aes->handle, key, 16); + memcpy(aes_key_aligned, key, 16); + status = DCP_AES_SetKey(DCP, &aes->handle, aes_key_aligned, 16); if (status != kStatus_Success) status = WC_HW_E; else { @@ -317,8 +319,8 @@ int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) dcp_lock(); (void)devId; XMEMSET(sha256, 0, sizeof(wc_Sha256)); - sha256->handle.channel = ch; - sha256->handle.keySlot = keyslot; + sha256->handle.channel = (dcp_channel_t)ch; + sha256->handle.keySlot = (dcp_key_slot_t)keyslot; sha256->handle.swapConfig = kDCP_NoSwap; ret = DCP_HASH_Init(DCP, &sha256->handle, &sha256->ctx, kDCP_Sha256); if (ret != kStatus_Success) @@ -328,11 +330,6 @@ int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) return ret; } -int wc_InitSha256(wc_Sha256* sha256) -{ - return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); -} - void DCPSha256Free(wc_Sha256* sha256) { if (sha256) @@ -434,8 +431,8 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) dcp_lock(); (void)devId; XMEMSET(sha, 0, sizeof(wc_Sha)); - sha->handle.channel = ch; - sha->handle.keySlot = keyslot; + sha->handle.channel = (dcp_channel_t)ch; + sha->handle.keySlot = (dcp_key_slot_t)keyslot; sha->handle.swapConfig = kDCP_NoSwap; ret = DCP_HASH_Init(DCP, &sha->handle, &sha->ctx, kDCP_Sha1); if (ret != kStatus_Success) @@ -444,11 +441,6 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) return ret; } -int wc_InitSha(wc_Sha* sha) -{ - return wc_InitSha_ex(sha, NULL, INVALID_DEVID); -} - void DCPShaFree(wc_Sha* sha) { if (sha) diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index dd8a88098..8e3e5cf37 100644 --- a/wolfcrypt/src/port/nxp/ksdk_port.c +++ b/wolfcrypt/src/port/nxp/ksdk_port.c @@ -1,6 +1,6 @@ /* ksdk_port.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -42,6 +42,11 @@ #define ERROR_OUT(res) { ret = (res); goto done; } +/* For debugging only - Enable this to do software tests of each operation */ +/* #define ENABLE_NXPLTC_TESTS */ +#ifdef ENABLE_NXPLTC_TESTS +static int doLtcTest = 0; +#endif int ksdk_port_init(void) { @@ -95,7 +100,8 @@ static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) sz = mp_unsigned_bin_size(A); #ifndef WOLFSSL_SP_MATH - res = mp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ + /* result is lsbyte at lowest addr as required by LTC */ + res = mp_to_unsigned_lsb_bin(A, dst); #else res = mp_to_unsigned_bin(A, dst); if (res == MP_OKAY) { @@ -109,58 +115,86 @@ static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) /* LTC TFM */ #if defined(FREESCALE_LTC_TFM) - /* these function are used by wolfSSL upper layers (like RSA) */ /* c = a * b */ int mp_mul(mp_int *A, mp_int *B, mp_int *C) { int res = MP_OKAY; + status_t status; int szA, szB; + +#ifdef ENABLE_NXPLTC_TESTS + mp_int t; + mp_init(&t); + if (doLtcTest) + wolfcrypt_mp_mul(A, B, &t); +#endif + szA = mp_unsigned_bin_size(A); szB = mp_unsigned_bin_size(B); - /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call software mul */ + /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call + * software mul */ if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) { - int neg = 0; - -#ifndef WOLFSSL_SP_MATH - neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG; -#endif + uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrN = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); /* unsigned multiply */ - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + int neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG; +#endif - if (ptrA && ptrB && ptrC) { - uint16_t sizeA, sizeB; + if (ptrA && ptrB && ptrN && ptrC) { + uint16_t sizeA, sizeB, sizeN, sizeC = 0; res = ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); if (res == MP_OKAY) { - XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); + sizeN = sizeA + sizeB; + XMEMSET(ptrN, 0xFF, sizeN); + XMEMSET(ptrC, 0, LTC_MAX_INT_BYTES); - LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, - kLTC_PKHA_TimingEqualized); + status = LTC_PKHA_ModMul(LTC_BASE, + ptrA, sizeA, /* first integer */ + ptrB, sizeB, /* second integer */ + ptrN, sizeN, /* modulus */ + ptrC, &sizeC, /* out */ + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + if (status == kStatus_Success) { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(C, ptrC, sizeC); - ltc_reverse_array(ptrB, sizeB); - res = mp_read_unsigned_bin(C, ptrB, sizeB); +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + /* fix sign */ + C->sign = neg; +#endif + } + else { + res = MP_VAL; + } } } -#ifndef WOLFSSL_SP_MATH - /* fix sign */ - C->sign = neg; -#endif if (ptrA) { XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); } if (ptrB) { XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); } + if (ptrN) { + XFREE(ptrN, NULL, DYNAMIC_TYPE_BIGINT); + } if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } @@ -172,6 +206,18 @@ int mp_mul(mp_int *A, mp_int *B, mp_int *C) res = wolfcrypt_mp_mul(A, B, C); #endif } + +#ifdef ENABLE_NXPLTC_TESTS + /* compare hardware vs software */ + if (doLtcTest && mp_cmp(&t, C) != MP_EQ) { + printf("mp_mul test fail!\n"); + + mp_dump("C", C, 0); + mp_dump("C soft", &t, 0); + } + mp_clear(&t); +#endif + return res; } @@ -179,21 +225,29 @@ int mp_mul(mp_int *A, mp_int *B, mp_int *C) int mp_mod(mp_int *a, mp_int *b, mp_int *c) { int res = MP_OKAY; -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; + +#ifdef ENABLE_NXPLTC_TESTS + mp_int t; + mp_init(&t); + if (doLtcTest) + wolfcrypt_mp_mod(a, b, &t); +#endif + szA = mp_unsigned_bin_size(a); szB = mp_unsigned_bin_size(b); - if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) - { -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int neg = 0; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); + if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { + uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); -#ifndef WOLFSSL_SP_MATH +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) /* get sign for the result */ - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + int neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; #endif /* get remainder of unsigned a divided by unsigned b */ @@ -205,10 +259,17 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); if (res == MP_OKAY) { if (kStatus_Success == - LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, + &sizeC, kLTC_PKHA_IntegerArith)) { ltc_reverse_array(ptrC, sizeC); res = mp_read_unsigned_bin(c, ptrC, sizeC); + +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + /* fix sign */ + c->sign = neg; +#endif } else { res = MP_VAL; @@ -219,11 +280,6 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) res = MP_MEM; } -#ifndef WOLFSSL_SP_MATH - /* fix sign */ - c->sign = neg; -#endif - if (ptrA) { XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); } @@ -233,12 +289,26 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) res = wolfcrypt_mp_mod(a, b, c); +#else + res = NOT_COMPILED_IN; +#endif } -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + +#ifdef ENABLE_NXPLTC_TESTS + /* compare hardware vs software */ + if (doLtcTest && mp_cmp(&t, c) != MP_EQ) { + printf("mp_mod test fail!\n"); + + mp_dump("C", c, 0); + mp_dump("C soft", &t, 0); + } + mp_clear(&t); +#endif + return res; } @@ -246,15 +316,24 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) int mp_invmod(mp_int *a, mp_int *b, mp_int *c) { int res = MP_OKAY; -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; + +#ifdef ENABLE_NXPLTC_TESTS + mp_int t; + mp_init(&t); + if (doLtcTest) + wolfcrypt_mp_invmod(a, b, &t); +#endif + szA = mp_unsigned_bin_size(a); szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { -#endif - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); + uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); + uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, + DYNAMIC_TYPE_BIGINT); if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; @@ -262,12 +341,27 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + + /* if a >= b then reduce */ + /* TODO: Perhaps always do mod reduce depending on hardware performance */ + if (res == MP_OKAY && + LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrB, sizeB) >= 0) { + if (LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, + ptrA, &sizeA, kLTC_PKHA_IntegerArith) != kStatus_Success) { + res = MP_VAL; + } + } if (res == MP_OKAY) { - if (kStatus_Success == - LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { + if (LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, + &sizeC, kLTC_PKHA_IntegerArith) == kStatus_Success) { ltc_reverse_array(ptrC, sizeC); res = mp_read_unsigned_bin(c, ptrC, sizeC); + + +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + c->sign = a->sign; +#endif } else { res = MP_VAL; @@ -278,9 +372,6 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) res = MP_MEM; } -#ifndef WOLFSSL_SP_MATH - c->sign = a->sign; -#endif if (ptrA) { XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); } @@ -290,12 +381,26 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) res = wolfcrypt_mp_invmod(a, b, c); +#else + res = NOT_COMPILED_IN; +#endif } -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + +#ifdef ENABLE_NXPLTC_TESTS + /* compare hardware vs software */ + if (doLtcTest && mp_cmp(&t, c) != MP_EQ) { + printf("mp_invmod test fail!\n"); + + mp_dump("C", c, 0); + mp_dump("C soft", &t, 0); + } + mp_clear(&t); +#endif + return res; } @@ -303,76 +408,81 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) { int res = MP_OKAY; -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + status_t status; int szA, szB, szC; + +#ifdef ENABLE_NXPLTC_TESTS + mp_int t; + mp_init(&t); + if (doLtcTest) + wolfcrypt_mp_mulmod(a, b, c, &t); +#endif + szA = mp_unsigned_bin_size(a); szB = mp_unsigned_bin_size(b); szC = mp_unsigned_bin_size(c); - if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - mp_int t; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrD = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && + (szC <= LTC_MAX_INT_BYTES)) + { + uint8_t *ptrA, *ptrB, *ptrC, *ptrD; - /* if A or B is negative, subtract abs(A) or abs(B) from modulus to get positive integer representation of the - * same number */ - res = mp_init(&t); -#ifndef WOLFSSL_SP_MATH - if (a->sign) { - if (res == MP_OKAY) - res = mp_add(a, c, &t); - if (res == MP_OKAY) - res = mp_copy(&t, a); - } - if (b->sign) { - if (res == MP_OKAY) - res = mp_add(b, c, &t); - if (res == MP_OKAY) - res = mp_copy(&t, b); - } + ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrD = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + + /* unsigned multiply */ +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + int neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; #endif - if (res == MP_OKAY && ptrA && ptrB && ptrC && ptrD) { - uint16_t sizeA, sizeB, sizeC, sizeD; + if (ptrA && ptrB && ptrC && ptrD) { + uint16_t sizeA, sizeB, sizeC, sizeD = 0; + /* Multiply A * B = D */ res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + /* modulus C is all F's for integer multiply */ + sizeC = sizeA + sizeB; + XMEMSET(ptrC, 0xFF, sizeC); + XMEMSET(ptrD, 0, LTC_MAX_INT_BYTES); + + status = LTC_PKHA_ModMul(LTC_BASE, + ptrA, sizeA, /* first integer */ + ptrB, sizeB, /* second integer */ + ptrC, sizeC, /* modulus */ + ptrD, &sizeD, /* out */ + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + if (status != kStatus_Success) + res = MP_VAL; + } + /* load modulus */ if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); - - /* (A*B)mod C = ((A mod C) * (B mod C)) mod C */ - if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { - if (kStatus_Success != - LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrC, sizeC, ptrA, &sizeA, kLTC_PKHA_IntegerArith)) - { - res = MP_VAL; - } - } - if (res == MP_OKAY && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) - { - if (kStatus_Success != - LTC_PKHA_ModRed(LTC_BASE, ptrB, sizeB, ptrC, sizeC, ptrB, &sizeB, kLTC_PKHA_IntegerArith)) - { - res = MP_VAL; - } - } - + /* perform D mod C = D */ if (res == MP_OKAY) { - if (kStatus_Success != LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, sizeC, ptrD, &sizeD, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, - kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized)) - { + status = LTC_PKHA_ModRed(LTC_BASE, + ptrD, sizeD, + ptrC, sizeC, + ptrD, &sizeD, + kLTC_PKHA_IntegerArith); + if (status != kStatus_Success) res = MP_VAL; - } } - if (res == MP_OKAY) { ltc_reverse_array(ptrD, sizeD); res = mp_read_unsigned_bin(d, ptrD, sizeD); + +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + /* fix sign */ + d->sign = neg; +#endif } } else { @@ -391,127 +501,222 @@ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) if (ptrD) { XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT); } - #ifndef USE_FAST_MATH - mp_clear(&t); - #endif -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) res = wolfcrypt_mp_mulmod(a, b, c, d); +#else + res = NOT_COMPILED_IN; +#endif } -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + +#ifdef ENABLE_NXPLTC_TESTS + /* compare hardware vs software */ + if (doLtcTest && mp_cmp(&t, d) != MP_EQ) { + printf("mp_mulmod test fail!\n"); + + mp_dump("D", d, 0); + mp_dump("D soft", &t, 0); + } + mp_clear(&t); +#endif + return res; } /* Y = G^X mod P */ -int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) +int ltc_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int useConstTime) { int res = MP_OKAY; -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) - int szA, szB, szC; - mp_int tmp; + int szG, szX, szP; - /* if G cannot fit into LTC_PKHA, reduce it */ - szA = mp_unsigned_bin_size(G); - if (szA > LTC_MAX_INT_BYTES) { - res = mp_init(&tmp); - if (res != MP_OKAY) - return res; - if ((res = mp_mod(G, P, &tmp)) != MP_OKAY) { - return res; - } - G = &tmp; - szA = mp_unsigned_bin_size(G); - } - - szB = mp_unsigned_bin_size(X); - szC = mp_unsigned_bin_size(P); - - if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - mp_int t; - - uint16_t sizeG, sizeX, sizeP; - uint8_t *ptrG = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrX = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrP = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); - - /* if G is negative, add modulus to convert to positive number for LTC */ - res = mp_init(&t); -#ifndef WOLFSSL_SP_MATH - if (G->sign) { - if (res == MP_OKAY) - res = mp_add(G, P, &t); - if (res == MP_OKAY) - res = mp_copy(&t, G); - } +#ifdef ENABLE_NXPLTC_TESTS + mp_int t; + mp_init(&t); + if (doLtcTest) + wolfcrypt_mp_exptmod(G, X, P, &t); #endif - if (res == MP_OKAY && ptrG && ptrX && ptrP) { + szG = mp_unsigned_bin_size(G); + szX = mp_unsigned_bin_size(X); + szP = mp_unsigned_bin_size(P); + + if ((szG <= LTC_MAX_INT_BYTES) && + (szX <= LTC_MAX_INT_BYTES) && + (szP <= LTC_MAX_INT_BYTES)) + { + uint16_t sizeG, sizeX, sizeP, sizeY; + uint8_t *ptrG, *ptrX, *ptrP, *ptrY; + + ptrG = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrX = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrP = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrY = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + if (ptrG && ptrX && ptrP && ptrY) { res = ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); - /* if number if greater that modulo, we must first reduce due to LTC requirement on modular exponentiaton */ - /* it needs number less than modulus. */ - /* we can take advantage of modular arithmetic rule that: A^B mod C = ( (A mod C)^B ) mod C - and so we do first (A mod N) : LTC does not give size requirement on A versus N, - and then the modular exponentiation. - */ - /* if G >= P then */ - if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { - res = (int)LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrG, &sizeG, kLTC_PKHA_IntegerArith); - - if (res != kStatus_Success) { - res = MP_VAL; - } + /* if G >= P then reduce */ + /* TODO: Perhaps always do mod reduce depending on hardware performance */ + if (res == MP_OKAY && + LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { + res = LTC_PKHA_ModRed(LTC_BASE, + ptrG, sizeG, + ptrP, sizeP, + ptrG, &sizeG, kLTC_PKHA_IntegerArith); + res = (res == kStatus_Success) ? MP_OKAY: MP_VAL; } - if (res == MP_OKAY) { - res = (int)LTC_PKHA_ModExp(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrX, sizeX, ptrP, &sizeP, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); - - if (res != kStatus_Success) { - res = MP_VAL; - } - else { - ltc_reverse_array(ptrP, sizeP); - res = mp_read_unsigned_bin(Y, ptrP, sizeP); - } + res = LTC_PKHA_ModExp(LTC_BASE, + ptrG, sizeG, /* integer input */ + ptrP, sizeP, /* modulus */ + ptrX, sizeX, /* expenoent */ + ptrY, &sizeY, /* out */ + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + useConstTime ? kLTC_PKHA_TimingEqualized : + kLTC_PKHA_NoTimingEqualized); + res = (res == kStatus_Success) ? MP_OKAY: MP_VAL; + } + if (res == MP_OKAY) { + ltc_reverse_array(ptrY, sizeY); + res = mp_read_unsigned_bin(Y, ptrY, sizeY); } } else { res = MP_MEM; } - if (ptrG) { - XFREE(ptrG, NULL, DYNAMIC_TYPE_BIGINT); - } - if (ptrX) { - XFREE(ptrX, NULL, DYNAMIC_TYPE_BIGINT); + if (ptrY) { + XFREE(ptrY, NULL, DYNAMIC_TYPE_BIGINT); } if (ptrP) { XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT); } - #ifndef USE_FAST_MATH - mp_clear(&t); - #endif -#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + if (ptrX) { + XFREE(ptrX, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrG) { + XFREE(ptrG, NULL, DYNAMIC_TYPE_BIGINT); + } } else { +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) res = wolfcrypt_mp_exptmod(G, X, P, Y); +#else + res = NOT_COMPILED_IN; +#endif } -#ifndef USE_FAST_MATH - if (szA > LTC_MAX_INT_BYTES) - mp_clear(&tmp); +#ifdef ENABLE_NXPLTC_TESTS + /* compare hardware vs software */ + if (doLtcTest && mp_cmp(&t, Y) != MP_EQ) { + printf("mp_exptmod test fail!\n"); + + mp_dump("Y", Y, 0); + mp_dump("Y soft", &t, 0); + } + mp_clear(&t); #endif -#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } +int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) +{ + return ltc_mp_exptmod(G, X, P, Y, 1); +} + +int mp_exptmod_nct(mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + return ltc_mp_exptmod(G, X, P, Y, 0); +} + +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || \ + defined(WOLFSSL_KEY_GEN) +int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +{ + int res = MP_OKAY; + int szA; + +#ifdef ENABLE_NXPLTC_TESTS + int result_soft = 0; + if (doLtcTest) + mp_prime_is_prime_ex(a, t, &result_soft, rng); +#endif + + szA = mp_unsigned_bin_size(a); + if (szA <= LTC_MAX_INT_BYTES) { + uint16_t sizeA, sizeB; + uint8_t *ptrA, *ptrB; + + sizeB = mp_count_bits(a); + /* The base size is the number of bits / 8. One is added if the number + * of bits isn't an even 8. */ + sizeB = (sizeB / 8) + ((sizeB % 8) ? 1 : 0); + + ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + ptrB = (uint8_t*)XMALLOC(sizeB, NULL, DYNAMIC_TYPE_BIGINT); + if (ptrA == NULL || ptrB == NULL) { + res = MEMORY_E; + } + + if (res == MP_OKAY) { + #ifndef WC_NO_RNG + /* A NULL rng will return as bad function arg */ + res = wc_RNG_GenerateBlock(rng, ptrB, sizeB); + #else + res = NOT_COMPILED_IN; + #endif + } + + if (res == MP_OKAY) { + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + } + if (res == MP_OKAY) { + if (LTC_PKHA_PrimalityTest(LTC_BASE, + ptrB, sizeB, /* seed */ + (uint8_t*)&t, sizeof(t), /* trials */ + ptrA, sizeA, /* candidate */ + (bool*)result) != kStatus_Success) { + res = MP_MEM; + } + } + + if (ptrB) { + XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrA) { + XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); + } + } + else { +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + res = wolfcrypt_mp_prime_is_prime_ex(a, t, result, rng); +#else + res = NOT_COMPILED_IN; +#endif + } + +#ifdef ENABLE_NXPLTC_TESTS + /* compare hardware vs software */ + if (doLtcTest && *result != result_soft) { + printf("Fail! mp_prime_is_prime_ex %d != %d\n", *result, result_soft); + } +#endif + + return res; +} + +int mp_prime_is_prime(mp_int* a, int t, int* result) +{ + /* the NXP LTC prime check requires an RNG, so use software version */ + return wolfcrypt_mp_prime_is_prime_ex(a, t, result, NULL); +} +#endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */ + #endif /* FREESCALE_LTC_TFM */ @@ -519,7 +724,8 @@ int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) #if defined(HAVE_ECC) && defined(FREESCALE_LTC_ECC) /* convert from mp_int to LTC integer, as array of bytes of size sz. - * if mp_int has less bytes than sz, add zero bytes at most significant byte positions. + * if mp_int has less bytes than sz, add zero bytes at most significant byte + * positions. * This is when for example modulus is 32 bytes (P-256 curve) * and mp_int has only 31 bytes, we add leading zeros * so that result array has 32 bytes, same as modulus (sz). @@ -555,7 +761,8 @@ static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) return res; } -/* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA driver functions */ +/* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA + * driver functions */ #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #define ECC192 #endif @@ -575,7 +782,7 @@ static const uint8_t ltc_ecc256_modulus[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; -static const uint8_t ltc_ecc256_r2modn[32] = { +static const uint8_t ltc_ecc256_r2modn[32] = { /* R^2 mod N */ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00}; @@ -696,7 +903,7 @@ static int ltc_get_ecc_specs(const uint8_t **modulus, const uint8_t **r2modn, (1==map, 0 == leave in projective) return MP_OKAY on success */ -int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex(const mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, mp_int *modulus, int map, void* heap) { ltc_pkha_ecc_point_t B; @@ -707,9 +914,6 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, status_t status; int res; - (void)a; - (void)heap; - uint8_t Gxbin[LTC_MAX_ECC_BITS / 8]; uint8_t Gybin[LTC_MAX_ECC_BITS / 8]; uint8_t kbin[LTC_MAX_INT_BYTES]; @@ -719,6 +923,9 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, const uint8_t *bCurveParam; const uint8_t *r2modn; + (void)a; + (void)heap; + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; } @@ -726,26 +933,33 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, szModulus = mp_unsigned_bin_size(modulus); szkbin = mp_unsigned_bin_size(k); - res = ltc_get_from_mp_int(kbin, k, szkbin); + /* make sure LTC big number variable is large enough */ + if (szModulus > LTC_MAX_INT_BYTES / 2) { + return MP_MEM; + } + + res = ltc_get_from_mp_int(kbin, (mp_int*)k, szkbin); if (res == MP_OKAY) res = ltc_get_from_mp_int(Gxbin, G->x, szModulus); if (res == MP_OKAY) res = ltc_get_from_mp_int(Gybin, G->y, szModulus); - if (res != MP_OKAY) return res; size = szModulus; + /* find LTC friendly parameters for the selected curve */ - if (0 != ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size)) { + if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, + size) != 0) { return ECC_BAD_ARG_E; } B.X = &Gxbin[0]; B.Y = &Gybin[0]; - status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn, aCurveParam, bCurveParam, size, - kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith, &B, &point_of_infinity); + status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn, + aCurveParam, bCurveParam, size, kLTC_PKHA_TimingEqualized, + kLTC_PKHA_IntegerArith, &B, &point_of_infinity); if (status != kStatus_Success) { return MP_VAL; } @@ -758,7 +972,8 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, /* if k is negative, we compute the multiplication with abs(-k) * with result (x, y) and modify the result to (x, -y) */ -#ifndef WOLFSSL_SP_MATH +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) R->y->sign = k->sign; #endif } @@ -768,7 +983,7 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, return res; } -int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap) { @@ -777,6 +992,16 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, heap); } +int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) +{ + /* this is handled in hardware, so no projective mapping needed */ + (void)P; + (void)modulus; + (void)mp; + (void)ct; + return MP_OKAY; +} + int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) { int res; @@ -796,7 +1021,8 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) size = mp_unsigned_bin_size(m); /* find LTC friendly parameters for the selected curve */ - if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size) != 0) { + if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, + size) != 0) { res = ECC_BAD_ARG_E; } else { @@ -817,8 +1043,8 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) B.X = Qxbin; B.Y = Qybin; - status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn, aCurveParam, bCurveParam, size, - kLTC_PKHA_IntegerArith, &A); + status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn, + aCurveParam, bCurveParam, size, kLTC_PKHA_IntegerArith, &A); if (status != kStatus_Success) { res = MP_VAL; } @@ -856,7 +1082,8 @@ static const uint8_t invThree[32] = { /* * * finds square root in finite field when modulus congruent to 5 modulo 8 - * this is fixed to curve25519 modulus 2^255 - 19 which is congruent to 5 modulo 8 + * this is fixed to curve25519 modulus 2^255 - 19 which is congruent to + * 5 modulo 8. * * This function solves equation: res^2 = a mod (2^255 - 19) * @@ -918,8 +1145,9 @@ status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA, } /* I = I - 1 */ - XMEMSET(VV, 0xff, sizeof(VV)); /* just temp for maximum integer - for non-modular subtract */ - if (0 <= LTC_PKHA_CompareBigNum(I, szI, &one, sizeof(one))) { + /* just temp for maximum integer - for non-modular subtract */ + XMEMSET(VV, 0xff, sizeof(VV)); + if (LTC_PKHA_CompareBigNum(I, szI, &one, sizeof(one)) >= 0) { if (status == kStatus_Success) { status = LTC_PKHA_ModSub1(LTC_BASE, I, szI, &one, sizeof(one), VV, sizeof(VV), I, &szI); @@ -1131,7 +1359,8 @@ status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint) /* if type is set, the input point p is in Montgomery curve coordinates, so there is a map to Weierstrass curve */ /* q output point is always in Montgomery curve coordinates */ -int nxp_ltc_curve25519(ECPoint *q, const byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_system_t type) +int nxp_ltc_curve25519(ECPoint *q, const byte *n, const ECPoint *p, + fsl_ltc_ecc_coordinate_system_t type) { status_t status; ltc_pkha_ecc_point_t ltcPoint; @@ -1571,7 +1800,8 @@ status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey, return status; } -/* LSByte first of Ed25519 parameter l = 2^252 + 27742317777372353535851937790883648493 */ +/* LSByte first of Ed25519 parameter l = 2^252 + + * 27742317777372353535851937790883648493 */ static const uint8_t l_coefEdDSA[] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/wolfcrypt/src/port/pic32/pic32mz-crypt.c b/wolfcrypt/src/port/pic32/pic32mz-crypt.c index 80920110e..5db1e4ad4 100644 --- a/wolfcrypt/src/port/pic32/pic32mz-crypt.c +++ b/wolfcrypt/src/port/pic32/pic32mz-crypt.c @@ -1,6 +1,6 @@ /* pic32mz-crypt.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/silabs/silabs_aes.c b/wolfcrypt/src/port/silabs/silabs_aes.c index e98b52f77..2177a58e6 100644 --- a/wolfcrypt/src/port/silabs/silabs_aes.c +++ b/wolfcrypt/src/port/silabs/silabs_aes.c @@ -1,6 +1,6 @@ /* silabs_aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/silabs/silabs_ecc.c b/wolfcrypt/src/port/silabs/silabs_ecc.c index 10c243784..b41c9ec80 100644 --- a/wolfcrypt/src/port/silabs/silabs_ecc.c +++ b/wolfcrypt/src/port/silabs/silabs_ecc.c @@ -1,6 +1,6 @@ /* silabs_ecc.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -303,21 +303,30 @@ int silabs_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, sl_se_command_context_t cmd; sl_se_key_descriptor_t key_out; sl_se_key_descriptor_t pub_key; - uint32_t pub_sz = 0; sl_status_t sl_stat; + /* `sl_se_ecdh_compute_shared_secret` returns the full coordinate + * point, but `wc_ecc_shared_secret` should only return the x + * coordinate. This buffer is used to hold the output of the + * secure element output and only the first half is copied to the + * `out` buffer. + */ + byte fullpoint[2 * ECC_MAX_CRYPTO_HW_SIZE]; + pub_key = public_key->key; pub_key.flags = SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY; - *outlen = pub_key.size * 2; - pub_sz = pub_key.size * 2; + if (*outlen < pub_key.size) { + return BUFFER_E; + } + pub_sz = pub_key.size * 2; XMEMSET(&key_out, 0, sizeof(key_out)); key_out.type = SL_SE_KEY_TYPE_SYMMETRIC; key_out.storage.method = SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT; - key_out.storage.location.buffer.pointer = out; + key_out.storage.location.buffer.pointer = fullpoint; key_out.size = pub_sz; key_out.storage.location.buffer.size = pub_sz; @@ -327,6 +336,11 @@ int silabs_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, &pub_key, &key_out); + if (sl_stat == SL_STATUS_OK) { + *outlen = pub_key.size; + XMEMCPY(out, fullpoint, *outlen); + } + return (sl_stat == SL_STATUS_OK) ? 0 : WC_HW_E; } diff --git a/wolfcrypt/src/port/silabs/silabs_hash.c b/wolfcrypt/src/port/silabs/silabs_hash.c index 8de8cdd61..afb48a0af 100644 --- a/wolfcrypt/src/port/silabs/silabs_hash.c +++ b/wolfcrypt/src/port/silabs/silabs_hash.c @@ -1,6 +1,6 @@ /* silabs_se_hash.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/silabs/silabs_random.c b/wolfcrypt/src/port/silabs/silabs_random.c index 582f400a8..c4a35d167 100644 --- a/wolfcrypt/src/port/silabs/silabs_random.c +++ b/wolfcrypt/src/port/silabs/silabs_random.c @@ -1,6 +1,6 @@ /* silabs_random.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/st/stm32.c b/wolfcrypt/src/port/st/stm32.c index 17778c097..3879ba177 100644 --- a/wolfcrypt/src/port/st/stm32.c +++ b/wolfcrypt/src/port/st/stm32.c @@ -1,6 +1,6 @@ /* stm32.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -294,6 +294,9 @@ int wc_Stm32_Aes_Init(Aes* aes, CRYP_HandleTypeDef* hcryp) hcryp->Init.pKey = (STM_CRYPT_TYPE*)aes->key; #ifdef STM32_HAL_V2 hcryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE; + #ifdef CRYP_HEADERWIDTHUNIT_BYTE + hcryp->Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE; + #endif #endif return 0; @@ -383,19 +386,19 @@ extern PKA_HandleTypeDef hpka; * and mp_int has only 31 bytes, we add leading zeros * so that result array has 32 bytes, same as modulus (sz). */ -static int stm32_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) +static int stm32_get_from_mp_int(uint8_t *dst, const mp_int *a, int sz) { int res; int szbin; int offset; - if (!a || !dst || (sz < 0)) - return -1; + if (a == NULL || dst == NULL || sz < 0) + return BAD_FUNC_ARG; /* check how many bytes are in the mp_int */ szbin = mp_unsigned_bin_size(a); - if ((szbin < 0) || (szbin > sz)) - return -1; + if (szbin < 0 || szbin > sz) + return BUFFER_E; /* compute offset from dst */ offset = sz - szbin; @@ -409,7 +412,7 @@ static int stm32_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) XMEMSET(dst, 0, offset); /* convert mp_int to array of bytes */ - res = mp_to_unsigned_bin(a, dst + offset); + res = mp_to_unsigned_bin((mp_int*)a, dst + offset); return res; } @@ -460,7 +463,6 @@ static const uint8_t stm32_ecc192_order[ECC192_KEYSIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 }; -static const uint32_t stm32_ecc192_cofactor = 1U; #endif /* ECC192 */ /* P-224 */ @@ -497,8 +499,6 @@ static const uint8_t stm32_ecc224_order[ECC224_KEYSIZE] = { 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D }; -static const uint32_t stm32_ecc224_cofactor = 1U; - #endif /* ECC224 */ /* P-256 */ @@ -535,8 +535,6 @@ static const uint8_t stm32_ecc256_order[ECC256_KEYSIZE] = { 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51 }; -static const uint32_t stm32_ecc256_cofactor = 1U; - #endif /* ECC256 */ /* P-384 */ @@ -583,7 +581,6 @@ static const uint8_t stm32_ecc384_order[ECC384_KEYSIZE] = { 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 }; -static const uint32_t stm32_ecc384_cofactor = 1U; #endif /* ECC384 */ static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, @@ -597,7 +594,7 @@ static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, *GenPointX = stm32_ecc256_pointX; *GenPointY = stm32_ecc256_pointY; *coef_sign = &stm32_ecc256_coef_sign; - *order = stm32_ecc256_order; + if (order) *order = stm32_ecc256_order; break; #ifdef ECC224 case 28: @@ -606,7 +603,7 @@ static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, *GenPointX = stm32_ecc224_pointX; *GenPointY = stm32_ecc224_pointY; *coef_sign = &stm32_ecc224_coef; - *order = stm32_ecc224_order; + if (order) *order = stm32_ecc224_order; break; #endif #ifdef ECC192 @@ -616,7 +613,7 @@ static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, *GenPointX = stm32_ecc192_pointX; *GenPointY = stm32_ecc192_pointY; *coef_sign = &stm32_ecc192_coef; - *order = stm32_ecc192_order; + if (order) *order = stm32_ecc192_order; break; #endif #ifdef ECC384 @@ -626,11 +623,11 @@ static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, *GenPointX = stm32_ecc384_pointX; *GenPointY = stm32_ecc384_pointY; *coef_sign = &stm32_ecc384_coef; - *order = stm32_ecc384_order; + if (order) *order = stm32_ecc384_order; break; #endif default: - return -1; + return NOT_COMPILED_IN; } return 0; } @@ -646,7 +643,7 @@ static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, (1==map, 0 == leave in projective) return MP_OKAY on success */ -int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex(const mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, mp_int *modulus, int map, void* heap) { PKA_ECCMulInTypeDef pka_mul; @@ -661,7 +658,7 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, uint8_t kbin[STM32_MAX_ECC_SIZE]; uint8_t PtXbin[STM32_MAX_ECC_SIZE]; uint8_t PtYbin[STM32_MAX_ECC_SIZE]; - const uint8_t *prime, *coef, *gen_x, *gen_y, *order; + const uint8_t *prime, *coef, *gen_x, *gen_y; const uint32_t *coef_sign; (void)a; (void)heap; @@ -688,10 +685,9 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, size = (uint8_t)szModulus; /* find STM32_PKA friendly parameters for the selected curve */ - if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) { + if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, NULL, size)) { return ECC_BAD_ARG_E; } - (void)order; pka_mul.modulusSize = szModulus; pka_mul.coefSign = *coef_sign; @@ -725,7 +721,7 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, return res; } -int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap) { @@ -734,6 +730,16 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, heap); } +int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) +{ + /* this is handled in hardware, so no projective mapping needed */ + (void)P; + (void)modulus; + (void)mp; + (void)ct; + return MP_OKAY; +} + int stm32_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, word32 hashlen, int* res, ecc_key* key) { @@ -823,7 +829,7 @@ int stm32_ecc_sign_hash_ex(const byte* hash, word32 hashlen, WC_RNG* rng, const uint8_t *prime, *coef, *gen_x, *gen_y, *order; const uint32_t *coef_sign; XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignInTypeDef)); - XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignOutTypeDef)); + XMEMSET(&pka_ecc_out, 0x00, sizeof(PKA_ECDSASignOutTypeDef)); if (r == NULL || s == NULL || hash == NULL || key == NULL) { return ECC_BAD_ARG_E; diff --git a/wolfcrypt/src/port/st/stsafe.c b/wolfcrypt/src/port/st/stsafe.c index 239b159ae..1151e7430 100644 --- a/wolfcrypt/src/port/st/stsafe.c +++ b/wolfcrypt/src/port/st/stsafe.c @@ -1,6 +1,6 @@ /* stsafe.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 52f2ceb97..ae7a2faef 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -1,6 +1,6 @@ /* port/ti/ti-aes.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/ti/ti-ccm.c b/wolfcrypt/src/port/ti/ti-ccm.c index 5c0051e03..9af5ede2e 100644 --- a/wolfcrypt/src/port/ti/ti-ccm.c +++ b/wolfcrypt/src/port/ti/ti-ccm.c @@ -1,6 +1,6 @@ /* port/ti/ti_ccm.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/ti/ti-des3.c b/wolfcrypt/src/port/ti/ti-des3.c index 6e93567d7..788ec8b4e 100644 --- a/wolfcrypt/src/port/ti/ti-des3.c +++ b/wolfcrypt/src/port/ti/ti-des3.c @@ -1,6 +1,6 @@ /* port/ti/ti-des.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index ab8f2cc22..09ec8aa5a 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -1,6 +1,6 @@ /* port/ti/ti-hash.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -107,6 +107,9 @@ static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 XMEMSET(h, 0, sizeof(h)); #endif + if (result == NULL) { + return BAD_FUNC_ARG; + } XMEMCPY(result, h, hsize); return 0; diff --git a/wolfcrypt/src/port/xilinx/xil-aesgcm.c b/wolfcrypt/src/port/xilinx/xil-aesgcm.c index 6af4b3177..8aa71c7a8 100644 --- a/wolfcrypt/src/port/xilinx/xil-aesgcm.c +++ b/wolfcrypt/src/port/xilinx/xil-aesgcm.c @@ -1,6 +1,6 @@ /* xil-aesgcm.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/xilinx/xil-sha3.c b/wolfcrypt/src/port/xilinx/xil-sha3.c index 2f42e1d78..f116c1b96 100644 --- a/wolfcrypt/src/port/xilinx/xil-sha3.c +++ b/wolfcrypt/src/port/xilinx/xil-sha3.c @@ -1,6 +1,6 @@ /* xil-sha3.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 5a8251550..cd3fa2491 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -1,6 +1,6 @@ /* pwdbased.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -125,6 +125,8 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, if (err != 0) break; } + if (err != 0) break; + if (keyLeft) { store = min(keyLeft, diestLen); XMEMCPY(&key[keyLen - keyLeft], digest, store); @@ -376,7 +378,7 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, (void)heap; - if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) { + if (output == NULL || passLen <= 0 || saltLen <= 0 || kLen < 0) { return BAD_FUNC_ARG; } @@ -387,11 +389,15 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, ret = wc_HashGetDigestSize(hashT); if (ret < 0) return ret; + if (ret == 0) + return BAD_STATE_E; u = ret; ret = wc_HashGetBlockSize(hashT); if (ret < 0) return ret; + if (ret == 0) + return BAD_STATE_E; v = ret; #ifdef WOLFSSL_SMALL_STACK @@ -411,10 +417,10 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, dLen = v; sLen = v * ((saltLen + v - 1) / v); - if (passLen) - pLen = v * ((passLen + v - 1) / v); - else - pLen = 0; + + /* with passLen checked at the top of the function for >= 0 then passLen + * must be 1 or greater here and is always 'true' */ + pLen = v * ((passLen + v - 1) / v); iLen = sLen + pLen; totalLen = dLen + sLen + pLen; diff --git a/wolfcrypt/src/rabbit.c b/wolfcrypt/src/rabbit.c index 820fd0ac3..ce774b07f 100644 --- a/wolfcrypt/src/rabbit.c +++ b/wolfcrypt/src/rabbit.c @@ -1,6 +1,6 @@ /* rabbit.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 15127b084..32af3022f 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1,6 +1,6 @@ /* random.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -310,7 +310,7 @@ enum { drbgReseed = 1, drbgGenerateW = 2, drbgGenerateH = 3, - drbgInitV + drbgInitV = 4 }; typedef struct DRBG_internal DRBG_internal; @@ -353,7 +353,8 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); - for (i = 0, ctr = 1; i < len; i++, ctr++) { + ctr = 1; + for (i = 0; i < len; i++) { #ifndef WOLFSSL_SMALL_STACK_CACHE #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId); @@ -362,12 +363,12 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, #endif if (ret != 0) break; - - if (ret == 0) #endif - ret = wc_Sha256Update(sha, &ctr, sizeof(ctr)); - if (ret == 0) + ret = wc_Sha256Update(sha, &ctr, sizeof(ctr)); + if (ret == 0) { + ctr++; ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits)); + } if (ret == 0) { /* churning V is the only string that doesn't have the type added */ @@ -551,10 +552,12 @@ static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen if (dLen > 0 && sLen > 0 && dLen >= sLen) { int sIdx, dIdx; - for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--) { + dIdx = dLen - 1; + for (sIdx = sLen - 1; sIdx >= 0; sIdx--) { carry += (word16)d[dIdx] + (word16)s[sIdx]; d[dIdx] = (byte)carry; carry >>= 8; + dIdx--; } for (; carry != 0 && dIdx >= 0; dIdx--) { @@ -809,7 +812,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, } if (ret == DRBG_SUCCESS) - ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg, + ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg, seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ, nonce, nonceSz, rng->heap, devId); @@ -918,7 +921,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) return BAD_FUNC_ARG; if (sz == 0) - return 0; + return 0; #ifdef WOLF_CRYPTO_CB if (rng->devId != INVALID_DEVID) { @@ -1793,131 +1796,135 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #endif /* WOLFSSL_PIC32MZ_RNG */ +#elif defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA) + /* + * wc_Generates a RNG seed using the Random Number Generator Accelerator + * on the Kinetis K70. Documentation located in Chapter 37 of + * K70 Sub-Family Reference Manual (see Note 3 in the README for link). + */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + + /* turn on RNGA module */ + #if defined(SIM_SCGC3_RNGA_MASK) + SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK; + #endif + #if defined(SIM_SCGC6_RNGA_MASK) + /* additionally needed for at least K64F */ + SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK; + #endif + + /* set SLP bit to 0 - "RNGA is not in sleep mode" */ + RNG_CR &= ~RNG_CR_SLP_MASK; + + /* set HA bit to 1 - "security violations masked" */ + RNG_CR |= RNG_CR_HA_MASK; + + /* set GO bit to 1 - "output register loaded with data" */ + RNG_CR |= RNG_CR_GO_MASK; + + for (i = 0; i < sz; i++) { + + /* wait for RNG FIFO to be full */ + while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {} + + /* get value */ + output[i] = RNG_OR; + } + + return 0; + } + +#elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB) + /* + * wc_Generates a RNG seed using the Random Number Generator (RNGB) + * on the Kinetis K53. Documentation located in Chapter 33 of + * K53 Sub-Family Reference Manual (see note in the README for link). + */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + + /* turn on RNGB module */ + SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK; + + /* reset RNGB */ + RNG_CMD |= RNG_CMD_SR_MASK; + + /* FIFO generate interrupt, return all zeros on underflow, + * set auto reseed */ + RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK); + + /* gen seed, clear interrupts, clear errors */ + RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK); + + /* wait for seeding to complete */ + while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {} + + for (i = 0; i < sz; i++) { + + /* wait for a word to be available from FIFO */ + while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {} + + /* get value */ + output[i] = RNG_OUT; + } + + return 0; + } + +#elif defined(FREESCALE_KSDK_2_0_TRNG) + #ifndef TRNG0 + #define TRNG0 TRNG + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + status_t status; + status = TRNG_GetRandomData(TRNG0, output, sz); + if (status == kStatus_Success) + { + return(0); + } + else + { + return RAN_BLOCK_E; + } + } + +#elif defined(FREESCALE_KSDK_2_0_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + status_t status; + status = RNGA_GetRandomData(RNG, output, sz); + if (status == kStatus_Success) + { + return(0); + } + else + { + return RAN_BLOCK_E; + } + } + + +#elif defined(FREESCALE_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz); + return 0; + } + #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \ - defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) - - #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA) - /* - * wc_Generates a RNG seed using the Random Number Generator Accelerator - * on the Kinetis K70. Documentation located in Chapter 37 of - * K70 Sub-Family Reference Manual (see Note 3 in the README for link). - */ - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - word32 i; - - /* turn on RNGA module */ - #if defined(SIM_SCGC3_RNGA_MASK) - SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK; - #endif - #if defined(SIM_SCGC6_RNGA_MASK) - /* additionally needed for at least K64F */ - SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK; - #endif - - /* set SLP bit to 0 - "RNGA is not in sleep mode" */ - RNG_CR &= ~RNG_CR_SLP_MASK; - - /* set HA bit to 1 - "security violations masked" */ - RNG_CR |= RNG_CR_HA_MASK; - - /* set GO bit to 1 - "output register loaded with data" */ - RNG_CR |= RNG_CR_GO_MASK; - - for (i = 0; i < sz; i++) { - - /* wait for RNG FIFO to be full */ - while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {} - - /* get value */ - output[i] = RNG_OR; - } - - return 0; - } - - #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB) - /* - * wc_Generates a RNG seed using the Random Number Generator (RNGB) - * on the Kinetis K53. Documentation located in Chapter 33 of - * K53 Sub-Family Reference Manual (see note in the README for link). - */ - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - - /* turn on RNGB module */ - SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK; - - /* reset RNGB */ - RNG_CMD |= RNG_CMD_SR_MASK; - - /* FIFO generate interrupt, return all zeros on underflow, - * set auto reseed */ - RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK); - - /* gen seed, clear interrupts, clear errors */ - RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK); - - /* wait for seeding to complete */ - while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {} - - for (i = 0; i < sz; i++) { - - /* wait for a word to be available from FIFO */ - while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {} - - /* get value */ - output[i] = RNG_OUT; - } - - return 0; - } - - #elif defined(FREESCALE_KSDK_2_0_TRNG) - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - status_t status; - status = TRNG_GetRandomData(TRNG0, output, sz); - if (status == kStatus_Success) - { - return(0); - } - else - { - return RAN_BLOCK_E; - } - } - - #elif defined(FREESCALE_KSDK_2_0_RNGA) - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - status_t status; - status = RNGA_GetRandomData(RNG, output, sz); - if (status == kStatus_Success) - { - return(0); - } - else - { - return RAN_BLOCK_E; - } - } - - - #elif defined(FREESCALE_RNGA) - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz); - return 0; - } - - #else - #define USE_TEST_GENSEED - #endif /* FREESCALE_K70_RNGA */ + defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + /* + * Fallback to USE_TEST_GENSEED if a FREESCALE platform did not match any + * of the TRNG/RNGA/RNGB support + */ + #define USE_TEST_GENSEED #elif defined(WOLFSSL_SILABS_SE_ACCEL) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) @@ -1957,7 +1964,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) ((wolfssl_word)&output[i] % sizeof(word32)) != 0 ) { /* Single byte at a time */ - word32 tmpRng = 0; + uint32_t tmpRng = 0; if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) { wolfSSL_CryptHwMutexUnLock(); return RAN_BLOCK_E; @@ -1966,7 +1973,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } else { /* Use native 32 instruction */ - if (HAL_RNG_GenerateRandomNumber(&hrng, (word32*)&output[i]) != HAL_OK) { + if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) { wolfSSL_CryptHwMutexUnLock(); return RAN_BLOCK_E; } @@ -2236,19 +2243,35 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #elif defined(INTIME_RTOS) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int ret = 0; - - (void)os; + uint32_t randval; + word32 len; if (output == NULL) { return BUFFER_E; } - /* Note: Investigate better solution */ - /* no return to check */ - arc4random_buf(output, sz); + #ifdef INTIMEVER + /* If INTIMEVER exists then it is INTIME RTOS v6 or later */ + #define INTIME_RAND_FUNC arc4random + len = 4; + #else + /* v5 and older */ + #define INTIME_RAND_FUNC rand + srand(time(0)); + len = 2; /* don't use all 31 returned bits */ + #endif - return ret; + while (sz > 0) { + if (sz < len) + len = sz; + randval = INTIME_RAND_FUNC(); + XMEMCPY(output, &randval, len); + output += len; + sz -= len; + } + (void)os; + + return 0; } #elif defined(WOLFSSL_WICED) @@ -2306,13 +2329,14 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG)) #include - #include int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - Buffer buf[1]; - int ret = 0; - int times = 1000, i; + unsigned int args[4] = {0}; + CAAM_BUFFER buf[1]; + int ret = 0; + int times = 1000, i; /* 1000 is an arbitrary number chosen */ + word32 idx = 0; (void)os; @@ -2320,25 +2344,29 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return BUFFER_E; } - buf[0].BufferType = DataBuffer | LastBuffer; - buf[0].TheAddress = (Address)output; - buf[0].Length = sz; - /* Check Waiting to make sure entropy is ready */ for (i = 0; i < times; i++) { - ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY); - if (ret == Success) { - break; + buf[0].BufferType = DataBuffer | LastBuffer; + buf[0].TheAddress = (CAAM_ADDRESS)(output + idx); + buf[0].Length = ((sz - idx) < WC_CAAM_MAX_ENTROPY)? + sz - idx : WC_CAAM_MAX_ENTROPY; + + args[0] = buf[0].Length; + ret = wc_caamAddAndWait(buf, 1, args, CAAM_ENTROPY); + if (ret == 0) { + idx += buf[0].Length; + if (idx == sz) + break; } /* driver could be waiting for entropy */ - if (ret != RAN_BLOCK_E) { + if (ret != RAN_BLOCK_E && ret != 0) { return ret; } usleep(100); } - if (i == times && ret != Success) { + if (i == times && ret != 0) { return RNG_FAILURE_E; } else { /* Success case */ @@ -2553,6 +2581,18 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } +#elif defined(DOLPHIN_EMULATOR) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + (void)os; + srand(time(NULL)); + for (i = 0; i < sz; i++) + output[i] = (byte)rand(); + return 0; + } + #elif defined(NO_DEV_RANDOM) #error "you need to write an os specific wc_GenerateSeed() here" diff --git a/wolfcrypt/src/rc2.c b/wolfcrypt/src/rc2.c index 51a6b7193..9051c5f5e 100644 --- a/wolfcrypt/src/rc2.c +++ b/wolfcrypt/src/rc2.c @@ -1,6 +1,6 @@ /* rc2.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/ripemd.c b/wolfcrypt/src/ripemd.c index 484c62fe4..323e0edc4 100644 --- a/wolfcrypt/src/ripemd.c +++ b/wolfcrypt/src/ripemd.c @@ -1,6 +1,6 @@ /* ripemd.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index f1512174b..e10a1f58a 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -1,6 +1,6 @@ /* rsa.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -171,12 +171,12 @@ int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, } -int wc_RsaEncryptSize(RsaKey* key) +int wc_RsaEncryptSize(const RsaKey* key) { if (key == NULL) { return BAD_FUNC_ARG; } - return RsaEncryptSize_fips(key); + return RsaEncryptSize_fips((RsaKey*)key); } @@ -397,7 +397,7 @@ int wc_InitRsaKey_Label(RsaKey* key, const char* label, void* heap, int devId) */ int wc_InitRsaHw(RsaKey* key) { - unsigned char* m; /* RSA modulous */ + unsigned char* m; /* RSA modulus */ word32 e = 0; /* RSA public exponent */ int mSz; int eSz; @@ -673,7 +673,7 @@ int wc_CheckRsaKey(RsaKey* key) break; #endif /* WOLFSSL_SP_4096 */ default: - /* If using only single precsision math then issue key size + /* If using only single precision math then issue key size * error, otherwise fall-back to multi-precision math * calculation */ #if defined(WOLFSSL_SP_MATH) @@ -1282,11 +1282,10 @@ static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, } } - #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) - if (msg != NULL) { - XFREE(msg, heap, DYNAMIC_TYPE_RSA_BUFFER); - } - #endif +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + /* msg is always not NULL as we bail on allocation failure */ + XFREE(msg, heap, DYNAMIC_TYPE_RSA_BUFFER); +#endif return ret; } #endif /* WC_RSA_PSS */ @@ -1666,7 +1665,11 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, } /* check the padding until we find the separator */ - for (i = 2; i < pkcsBlockLen && pkcsBlock[i++] == 0xFF; ) { } + for (i = 2; i < pkcsBlockLen; ) { + if (pkcsBlock[i++] != 0xFF) { + break; + } + } /* Minimum of 11 bytes of pre-message data and must have separator. */ if (i < RSA_MIN_PAD_SZ || pkcsBlock[i-1] != 0) { @@ -1682,8 +1685,9 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, word16 j; word16 pastSep = 0; + i = 0; /* Decrypted with private key - unpad must be constant time. */ - for (i = 0, j = 2; j < pkcsBlockLen; j++) { + for (j = 2; j < pkcsBlockLen; j++) { /* Update i if not passed the separator and at separator. */ i |= (~pastSep) & ctMask16Eq(pkcsBlock[j], 0x00) & (j + 1); pastSep |= ctMask16Eq(pkcsBlock[j], 0x00); @@ -2199,6 +2203,8 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: return sp_RsaPublic_2048(in, inLen, &key->e, &key->n, out, outLen); + default: + break; } } #endif @@ -2228,6 +2234,8 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen); + default: + break; } } #endif @@ -2257,6 +2265,8 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: return sp_RsaPublic_4096(in, inLen, &key->e, &key->n, out, outLen); + default: + break; } } #endif @@ -2273,16 +2283,19 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, tmp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); if (tmp == NULL) return MEMORY_E; -#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) #ifdef WC_RSA_BLINDING +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA); if (rnd == NULL) { XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return MEMORY_E; } rndi = rnd + 1; -#endif /* WC_RSA_BLINDING */ +#else + rnd = NULL; + rndi = NULL; #endif +#endif /* WC_RSA_BLINDING */ #endif /* WOLFSSL_SMALL_STACK */ if (mp_init(tmp) != MP_OKAY) @@ -2302,7 +2315,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, #endif #ifndef TEST_UNPAD_CONSTANT_TIME - if (ret == 0 && mp_read_unsigned_bin(tmp, (byte*)in, inLen) != MP_OKAY) + if (ret == 0 && mp_read_unsigned_bin(tmp, in, inLen) != MP_OKAY) ret = MP_READ_E; if (ret == 0) { @@ -3009,7 +3022,7 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, labelSz : size of optional label buffer saltLen : Length of salt used in PSS rng : random number generator */ -static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, +static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, word32 outLen, byte** outPtr, RsaKey* key, int rsa_type, byte pad_value, int pad_type, enum wc_HashType hash, int mgf, @@ -3128,10 +3141,11 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, if (outPtr == NULL) { #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) if (rsa_type == RSA_PRIVATE_DECRYPT) { - word32 i, j; + word32 i = 0; + word32 j; int start = (int)((size_t)pad - (size_t)key->data); - for (i = 0, j = 0; j < key->dataLen; j++) { + for (j = 0; j < key->dataLen; j++) { out[i] = key->data[j]; c = ctMaskGTE(j, start); c &= ctMaskLT(i, outLen); @@ -3265,7 +3279,7 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, #else rng = NULL; #endif - return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key, RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); } @@ -3282,7 +3296,7 @@ int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, #else rng = NULL; #endif - return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key, RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label, labelSz, 0, rng); } @@ -3334,11 +3348,11 @@ int wc_RsaSSL_Verify_ex2(const byte* in, word32 inLen, byte* out, word32 outLen #endif #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER - return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key, RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, pad_type, hash, wc_hash2mgf(hash), NULL, 0, RSA_PSS_SALT_LEN_DEFAULT, rng); #else - return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key, RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, pad_type, hash, wc_hash2mgf(hash), NULL, 0, RSA_PSS_SALT_LEN_DISCOVER, rng); #endif @@ -3466,7 +3480,11 @@ int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, word32 outLen, int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig, word32 sigSz, enum wc_HashType hashType) { - return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, inSz, 0); +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, RSA_PSS_SALT_LEN_DEFAULT, 0); +#else + return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, RSA_PSS_SALT_LEN_DISCOVER, 0); +#endif } /* Checks the PSS data to ensure that the signature matches. @@ -3512,7 +3530,7 @@ int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, byte* sig, #endif } #ifndef WOLFSSL_PSS_LONG_SALT - else if ((word32)saltLen > inSz) { + else if (saltLen > (int)inSz) { ret = PSS_SALTLEN_E; } #endif @@ -3727,7 +3745,7 @@ int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, word32 outLen, #if !defined(WOLFSSL_RSA_VERIFY_ONLY) || !defined(WOLFSSL_SP_MATH) || \ defined(WC_RSA_PSS) -int wc_RsaEncryptSize(RsaKey* key) +int wc_RsaEncryptSize(const RsaKey* key) { int ret; diff --git a/wolfcrypt/src/sakke.c b/wolfcrypt/src/sakke.c new file mode 100644 index 000000000..b2bf0b42e --- /dev/null +++ b/wolfcrypt/src/sakke.c @@ -0,0 +1,6811 @@ +/* sakke.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFSSL_HAVE_SP_ECC + #include +#endif + +#ifdef WOLFCRYPT_HAVE_SAKKE + +#include +#include +#include + +/* SAKKE Build Options: + * WOLFSSL_SAKKE_SMALL: Small code size version of SAKKE. + * WOLFSSL_SAKKE_SMALL_MODEXP: Small code size for just SAKKE modexp. + */ + + +#ifdef WOLFCRYPT_SAKKE_CLIENT +/* + * Initialize the client components of the SAKKE key. + * + * @param [in] key SAKKE key to initialize. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_init_client(SakkeKey* key) +{ + int err = 0; + + key->tmp.p1 = wc_ecc_new_point_h(key->ecc.heap); + if (key->tmp.p1 == NULL) { + err = MEMORY_E; + } + if (err == 0) { + key->tmp.p2 = wc_ecc_new_point_h(key->ecc.heap); + if (key->tmp.p2 == NULL) { + err = MEMORY_E; + } + } + if (err == 0) { + key->tmp.p3 = wc_ecc_new_point_h(key->ecc.heap); + if (key->tmp.p3 == NULL) { + err = MEMORY_E; + } + } + if (err == 0) { + key->rsk.rsk = wc_ecc_new_point_h(key->ecc.heap); + if (key->rsk.rsk == NULL) { + err = MEMORY_E; + } + } + if (err == 0) { + key->i.i = wc_ecc_new_point_h(key->ecc.heap); + if (key->i.i == NULL) { + err = MEMORY_E; + } + } + + return err; +} +#endif + +/** + * Initialize the components of the SAKKE key. + * + * Must be called before performing any operations. + * Free the SAKKE key with wc_FreeSakkeKey() when no longer needed. + * + * @param [in] key SAKKE key to initialize. + * @param [in] keySize Size of the curve. For SAKKE set 1, use 128. + * @param [in] curveId ID of curve. For SAKKE set 1, use ECC_SAKKE_1. + * @param [in] heap Heap hint. + * @param [in] devId Device identifier. + * Use INVALID_DEVID when no device used. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_InitSakkeKey_ex(SakkeKey* key, int keySize, int curveId, void* heap, + int devId) +{ + int err = 0; + SakkeKeyParams* params = NULL; + + if (key == NULL) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + XMEMSET(key, 0, sizeof(*key)); + key->heap = heap; + params = &key->params; + + err = wc_ecc_init_ex(&key->ecc, heap, devId); + } + if (err == 0) { + err = wc_ecc_set_curve(&key->ecc, keySize, curveId); + } + if (err == 0) { + params->base = wc_ecc_new_point_h(key->ecc.heap); + if (params->base == NULL) { + err = MEMORY_E; + } +#ifdef WOLFCRYPT_SAKKE_CLIENT + if (err == 0) { + err = sakke_init_client(key); + } +#endif + if (err == 0) { + err = mp_init_multi(¶ms->prime, ¶ms->q, ¶ms->g, + ¶ms->a, &key->tmp.m1, +#ifdef WOLFCRYPT_SAKKE_CLIENT + &key->tmp.m2 +#else + NULL +#endif + ); + } + if (err == 0) { + key->mpInit = 1; + } + + if (err != 0) { + wc_FreeSakkeKey(key); + } + } + + return err; +} + +/** + * Initialize the components of the SAKKE key. + * + * Must be called before performing any operations. + * Free the SAKKE key with wc_FreeSakkeKey() when no longer needed. + * + * @param [in] key SAKKE key to initialize. + * @param [in] heap Heap hint. + * @param [in] devId Device identifier. + * Use INVALID_DEVID when no device used. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_InitSakkeKey(SakkeKey* key, void* heap, int devId) +{ + return wc_InitSakkeKey_ex(key, 128, ECC_SAKKE_1, heap, devId); +} + +/** + * Frees memory associated with components of the SAKKE key. + * + * Must be called when finished with the SAKKE key. + * + * @param [in] key SAKKE key. + */ +void wc_FreeSakkeKey(SakkeKey* key) +{ + if (key != NULL) { + SakkeKeyParams* params = &key->params; + + if (key->mpInit) { + mp_free(¶ms->prime); + mp_free(¶ms->q); + mp_free(¶ms->g); + mp_free(¶ms->a); + mp_free(&key->tmp.m1); +#ifdef WOLFCRYPT_SAKKE_CLIENT + mp_free(&key->tmp.m2); +#endif + } +#ifdef WOLFCRYPT_SAKKE_CLIENT + if (key->i.i != NULL) { + wc_ecc_del_point_h(key->i.i, key->ecc.heap); + } + if (key->rsk.rsk != NULL) { + wc_ecc_del_point_h(key->rsk.rsk, key->ecc.heap); + } + if (key->tmp.p3 != NULL) { + wc_ecc_del_point_h(key->tmp.p3, key->ecc.heap); + } + if (key->tmp.p2 != NULL) { + wc_ecc_del_point_h(key->tmp.p2, key->ecc.heap); + } + if (key->tmp.p1 != NULL) { + wc_ecc_del_point_h(key->tmp.p1, key->ecc.heap); + } +#endif + if (params->base != NULL) { + wc_ecc_del_point_h(params->base, key->ecc.heap); + } + wc_ecc_free(&key->ecc); + } +} + +/* + * Load order (q), prime (p) and a, hex strings in ECC object, into fields of + * key. + * + * Flags that the p, q and a are available so it isn't loaded multiple times. + * + * @param [in] key SAKKE key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_load_params(SakkeKey* key) +{ + int err = 0; + SakkeKeyParams* params = &key->params; + + if (!params->havePrime) { + /* Load prime or modulus from string. */ + err = mp_read_radix(¶ms->prime, key->ecc.dp->prime, MP_RADIX_HEX); + if (err == 0) { + params->havePrime = 1; + } + } + if (!params->haveQ) { + /* Load order from string. */ + err = mp_read_radix(¶ms->q, key->ecc.dp->order, MP_RADIX_HEX); + if (err == 0) { + params->haveQ = 1; + } + } + if (!params->haveA) { + /* Load parameter A from string. */ + err = mp_read_radix(¶ms->a, key->ecc.dp->Af, MP_RADIX_HEX); + if (err == 0) { + params->haveA = 1; + } + } + + return err; +} + +/* + * Load the base point, hex encoded in the ECC object, as an ecc_point. + * + * @param [in] key SAKKE key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_load_base_point(SakkeKey* key) +{ + int err = 0; + SakkeKeyParams* params = &key->params; + + if (!params->haveBase) { + /* Load base point modulus from string. */ + err = mp_read_radix(params->base->x, key->ecc.dp->Gx, MP_RADIX_HEX); + if (err == 0) { + err = mp_read_radix(params->base->y, key->ecc.dp->Gy, MP_RADIX_HEX); + } + if (err == 0) { + /* Affine co-ordinates have a Z of 1 in Jacobian. */ + err = mp_set(params->base->z, 1); + } + if (err == 0) { + /* Base point loaded. */ + params->haveBase = 1; + } + } + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_ECC +/* + * Scalar multiply the base point. + * + * @param [in] key SAKKE key. + * @param [in] n MP integer that is the scalar. + * @param [out] res ECC point to hold the result. + * @param [in] map Map the result to affine co-ordinates. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_mulmod_base(SakkeKey* key, const mp_int* n, ecc_point* res, + int map) +{ + int err = NOT_COMPILED_IN; + +#ifdef WOLFSSL_SP_1024 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { + err = sp_ecc_mulmod_base_1024(n, res, map, key->heap); + } +#endif + + return err; +} + +/* + * Scalar multiply the base point and add a point. + * + * @param [in] key SAKKE key. + * @param [in] n MP integer that is the scalar. + * @param [in] a ECC point to add. + * @param [out] res ECC point to hold the result. + * @param [in] map Map the result to affine co-ordinates. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_mulmod_base_add(SakkeKey* key, const mp_int* n, + const ecc_point* a, ecc_point* res, int map) +{ + int err = NOT_COMPILED_IN; + +#ifdef WOLFSSL_SP_1024 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { + err = sp_ecc_mulmod_base_add_1024(n, a, 0, res, map, key->heap); + } +#endif + + return err; +} +#else +/* + * Scalar multiply the base point. + * + * @param [in] key SAKKE key. + * @param [in] n MP integer that is the scalar. + * @param [out] res ECC point to hold the result. + * @param [in] map Map the result to affine co-ordinates. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_mulmod_base(SakkeKey* key, const mp_int* n, ecc_point* res, + int map) +{ + int err; + SakkeKeyParams* params = &key->params; + + err = wc_ecc_mulmod(n, params->base, res, ¶ms->a, ¶ms->prime, map); + + return err; +} + +/* + * Scalar multiply the base point and add a point. + * + * @param [in] key SAKKE key. + * @param [in] n MP integer that is the scalar. + * @param [in] a ECC point to add. Point ordinates must be in Montgomery + * form. + * @param [out] res ECC point to hold the result. + * @param [in] map Map the result to affine co-ordinates. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_mulmod_base_add(SakkeKey* key, const mp_int* n, ecc_point* a, + ecc_point* res, int map) +{ + int err; + mp_digit mp = 0; + SakkeKeyParams* params = &key->params; + + /* Scalar multiply base by n - leaves ordinates in Montogmert form. */ + err = wc_ecc_mulmod(n, params->base, res, ¶ms->a, ¶ms->prime, 0); + if (err == 0) { + err = mp_montgomery_setup(¶ms->prime, &mp); + } + if (err == 0) { + /* Add a to result. */ + err = ecc_projective_add_point(res, a, res, ¶ms->a, + ¶ms->prime, mp); + } + if ((err == 0) && map) { + /* Map result back to affine co-ordinates. */ + err = ecc_map(res, ¶ms->prime, mp); + } + + return err; +} +#endif + +#ifdef WOLFSSL_HAVE_SP_ECC +/* + * Scalar multiply a point. + * + * @param [in] key SAKKE key. + * @param [in] n MP integer that is the scalar. + * @param [in] p ECC point to multiply. + * @param [in] table Precomputation table for p. May be NULL. + * @param [out] res ECC point to hold the result. + * @param [in] map Map the result to affine co-ordinates. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_mulmod_point(SakkeKey* key, const mp_int* n, + const ecc_point* p, byte* table, ecc_point* res, int map) +{ + int err = NOT_COMPILED_IN; + +#ifdef WOLFSSL_SP_1024 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { + if (table == NULL) { + err = sp_ecc_mulmod_1024(n, p, res, map, key->heap); + } + else { + err = sp_ecc_mulmod_table_1024(n, p, table, res, map, key->heap); + } + } +#endif + + return err; +} +#else +/* + * Scalar multiply a point. + * + * @param [in] key SAKKE key. + * @param [in] n MP integer that is the scalar. + * @param [in] p ECC point to multiply. + * @param [in] table Precomputation table for p. May be NULL. + * @param [out] res ECC point to hold the result. + * @param [in] map Map the result to affine co-ordinates. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_mulmod_point(SakkeKey* key, const mp_int* n, ecc_point* p, + const byte* table, ecc_point* res, int map) +{ + int err; + SakkeKeyParams* params = &key->params; + + err = wc_ecc_mulmod(n, p, res, ¶ms->a, ¶ms->prime, map); + + (void)table; + return err; +} +#endif + +#ifdef WOLFCRYPT_SAKKE_KMS +/** + * Generate KMS Master Secret (z_T) and KMS Public Key (Z_T). + * + * RFC 6508, Section 4.1 + * + * Called when establishing a new KMS.\n + * z_T must be kept secret while Z_T is required by clients for encapsulating + * and deriving. + * Export key using wc_ExportSakkeKey(), once generated, to reuse the key.\n + * Export KPAK using wc_ExportSakkePublicKey(), once generate to send to + * clients. + * + * @param [in] key SAKKE key. + * @param [in] rng Random number generator. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or rng is NULL. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +int wc_MakeSakkeKey(SakkeKey* key, WC_RNG* rng) +{ + int err = 0; + int digits = 0; + + if ((key == NULL) || (rng == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + digits = (key->ecc.dp->size * 8 + DIGIT_BIT - 1) / DIGIT_BIT; + + err = sakke_load_params(key); + } + if (err == 0) { + err = sakke_load_base_point(key); + } + if (err == 0) { + int genTryCnt = 0; + + /* Generate a random number that is not 0 - master secret. */ + do { + /* Don't infinitely loop on random number generation failure. */ + if ((++genTryCnt) > SAKKE_MAX_GEN_COUNT) { + err = RNG_FAILURE_E; + } + if (err == 0) { + err = mp_rand(&key->ecc.k, digits, rng); + } + if (err == 0) { + err = mp_mod(&key->ecc.k, &key->params.q, &key->ecc.k); + } + } + while ((err == 0) && mp_iszero(&key->ecc.k)); + } + if (err == 0) { + /* Calculate public key by multiply master secret by base point. */ + err = sakke_mulmod_base(key, &key->ecc.k, &key->ecc.pubkey, 1); + } + if (err == 0) { + key->ecc.type = ECC_PRIVATEKEY; + } + + return err; +} + +/** + * Generates the KMS Public Key (Z_T) from the KMS Master Secret (z_T). + * + * Only z_T is required to calculate Receiver Secret Key (RSK). + * + * @param [in] key SAKKE key. + * @param [out] pub ECC point containing KPAK. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or pub is NULL. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +int wc_MakeSakkePublicKey(SakkeKey* key, ecc_point* pub) +{ + int err = 0; + + if ((key == NULL) || (pub == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + err = sakke_load_base_point(key); + } + if (err == 0) { + err = sakke_mulmod_base(key, &key->ecc.k, pub, 1); + } + + return err; +} + +/** + * Export the SAKKE key as encoded public/private ECC key. + * + * Use when saving the KMS key pair. + * + * Private key, x ordinate of public key and y ordinate of public key + * concatenated. Each number is zero padded to key size. + * + * @param [in] key SAKKE key. + * @param [out] data Buffer to hold encoded SAKKE key. + * @param [in,out] sz In, size of buffer in bytes. + * Out, size of encoded SAKKE key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when size of buffer is too small. + */ +int wc_ExportSakkeKey(SakkeKey* key, byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (data == NULL)) { + *sz = 3 * key->ecc.dp->size; + err = LENGTH_ONLY_E; + } + if ((err >= 0) && (*sz < (word32)(3 * key->ecc.dp->size))) { + err = BUFFER_E; + } + if (err == 0) { + /* Write out the secret value into key size bytes. */ + err = mp_to_unsigned_bin_len(&key->ecc.k, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Write out the public key point's x ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(key->ecc.pubkey.x, data, + key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Write out the public key point's y ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(key->ecc.pubkey.y, data, + key->ecc.dp->size); + } + if (err == 0) { + *sz = 3 * key->ecc.dp->size; + } + + return err; +} + +/** + * Import the SAKKE key as DER encoded public/private ECC key. + * + * Use when restoring the KMS key pair. + * + * Private key, x ordinate of public key and y ordinate of public key + * concatenated. Each number is zero padded to key size. + * + * @param [in] key SAKKE key. + * @param [in] data Buffer holding encoded SAKKE key. + * @param [in] sz Size of encoded SAKKE key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or data is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_ImportSakkeKey(SakkeKey* key, const byte* data, word32 sz) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (sz != (word32)key->ecc.dp->size * 3)) { + err = BUFFER_E; + } + + if (err == 0) { + /* Read the secret value from key size bytes. */ + err = mp_read_unsigned_bin(&key->ecc.k, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Read the public key point's x value from key size bytes. */ + err = mp_read_unsigned_bin(key->ecc.pubkey.x, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Read the public key point's y value from key size bytes. */ + err = mp_read_unsigned_bin(key->ecc.pubkey.y, data, key->ecc.dp->size); + } + if (err == 0) { + err = mp_set(key->ecc.pubkey.z, 1); + } + if (err == 0) { + key->ecc.type = ECC_PRIVATEKEY; + } + + return err; +} + +/** + * Export the SAKKE key as DER encoded private ECC key. + * + * Use when saving the KMS private key. + * + * Private key zero padded to key size. + * + * @param [in] key SAKKE key. + * @param [out] data Buffer to hold encoded SAKKE key. + * @param [in,out] sz In, size of buffer in bytes. + * Out, size of encoded SAKKE key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz is set. + * @return BUFFER_E when size of buffer is too small. + */ +int wc_ExportSakkePrivateKey(SakkeKey* key, byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (data == NULL)) { + *sz = key->ecc.dp->size; + err = LENGTH_ONLY_E; + } + if ((err >= 0) && (*sz < (word32)key->ecc.dp->size)) { + err = BUFFER_E; + } + if (err == 0) { + /* Write out the secret value into key size bytes. */ + err = mp_to_unsigned_bin_len(&key->ecc.k, data, key->ecc.dp->size); + } + if (err == 0) { + *sz = key->ecc.dp->size; + } + + return err; +} + +/** + * Import the SAKKE key as DER encoded private ECC key. + * + * Use when restoring the KMS private key. + * Use wc_MakeSakkePublicKey() to recalculate the public key. + * + * Private key zero padded to key size. + * + * @param [in] key SAKKE key. + * @param [in] data Buffer holding encoded SAKKE key. + * @param [in] sz Size of encoded SAKKE key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or data is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_ImportSakkePrivateKey(SakkeKey* key, const byte* data, word32 sz) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (sz != (word32)key->ecc.dp->size)) { + err = BUFFER_E; + } + + if (err == 0) { + /* Read the secret value from key size bytes. */ + err = mp_read_unsigned_bin(&key->ecc.k, data, key->ecc.dp->size); + } + + return err; +} + +/* + * Convert the public key from montgomery form. + * + * The public key is needed in Montgomery form for validation and derivation. + * + * @param [in] key SAKKE key. + * @return 0 on success. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +static int sakke_z_from_mont(SakkeKey* key) +{ + int err = 0; + mp_digit mp; + ecc_point* z = &key->ecc.pubkey; + mp_int* prime = &key->params.prime; + + if (key->zMont) { + err = mp_montgomery_setup(prime, &mp); + if (err == 0) { + err = mp_montgomery_reduce(z->x, prime, mp); + } + if (err == 0) { + err = mp_montgomery_reduce(z->y, prime, mp); + } + if (err == 0) { + err = mp_montgomery_reduce(z->z, prime, mp); + } + if (err == 0) { + key->zMont = 0; + } + } + + return err; +} + +/* + * Encode a point into a buffer. + * + * X and y ordinate of point concatenated. Each number is zero padded tosize. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] point ECC point to encode. + * @param [in] size Size of prime in bytes - maximum ordinate length. + * @param [out] data Buffer to hold encoded data. + * NULL when needing length of encoded data. + * @param [in,out] sz In, the size of the buffer in bytes. + * Out, the size of the encoded data in bytes. + * @param [in] raw On 0, prepend descriptor byte. + * On 1, only include ordinates. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz will hold the size in bytes of + * the encoded data. + * @return BUFFER_E when size of buffer is too small. + */ +static int sakke_encode_point(ecc_point* point, word32 size, byte* data, + word32* sz, int raw) +{ + int err = 0; + + if (data == NULL) { + *sz = size * 2 + !raw; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*sz < size * 2 + !raw)) { + err = BUFFER_E; + } + + if (err == 0) { + if (!raw) { + data[0] = 0x04; + data++; + } + + /* Write out the point's x ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(point->x, data, size); + } + if (err == 0) { + data += size; + /* Write out the point's y ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(point->y, data, size); + } + if (err == 0) { + *sz = size * 2 + !raw; + } + + return err; +} + +/* + * Decode the data into an ECC point. + * + * X and y ordinate of point concatenated. Each number is zero padded to + * key size. Supports prepended descriptor byte (0x04). + * + * @param [out] point ECC point to encode. + * @param [in] size Size of prime in bytes - maximum ordinate length. + * @param [in] data Encoded public key. + * @param [in] sz Size of the encoded public key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or z is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +static int sakke_decode_point(ecc_point* point, word32 size, const byte* data, + word32 sz) +{ + int err = 0; + + if ((sz != size * 2) && (sz != size * 2 + 1)) { + err = BUFFER_E; + } + + if ((err == 0) && (sz & 1)) { + if (data[0] != 0x04) { + err = ASN_PARSE_E; + } + data++; + } + + if (err == 0) { + /* Read the public key point's x value from key size bytes. */ + err = mp_read_unsigned_bin(point->x, data, size); + } + if (err == 0) { + data += size; + /* Read the public key point's y value from key size bytes. */ + err = mp_read_unsigned_bin(point->y, data, size); + } + if (err == 0) { + err = mp_set(point->z, 1); + } + + return err; +} + + +/** + * Encode the KMS public key (Z_T) into a buffer. + * + * Z_T is required by all clients in order to perform cryptographic operations. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key SAKKE key. + * @param [out] data Buffer to hold encoded data. + * NULL when needing length of encoded data. + * @param [in,out] sz In, the size of the buffer in bytes. + * Out, the size of the encoded data in bytes. + * @param [in] raw On 0, prepend descriptor byte. + * On 1, only include ordinates. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz will hold the size in bytes of + * the encoded data. + * @return BUFFER_E when size of buffer is too small. + */ +int wc_ExportSakkePublicKey(SakkeKey* key, byte* data, word32* sz, int raw) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (data != NULL)) { + err = sakke_z_from_mont(key); + } + + if (err == 0) { + err = sakke_encode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size, + data, sz, raw); + } + + return err; +} + +/** + * Calculates the Receiver Secret Key (RSK) for the identity. + * + * RFC 6508, Section 6.1.1 + * + * RSK = [ (a + z_T) ^ 1 modulo q ]P\n + * RSK is required by receiver to derive SSV. + * + * @param [in] key SAKKE key. + * @param [in] id Identity to create hash for. + * @param [in] idSz Length of identity in bytes. + * @param [out] rsk Receiver Secret Key as an ECC point. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, id, or rsk is NULL. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return Other value when an an internal operation fails. + */ +int wc_MakeSakkeRsk(SakkeKey* key, const byte* id, word16 idSz, ecc_point* rsk) +{ + int err = 0; + mp_int* a = NULL; + + if ((key == NULL) || (id == NULL) || (rsk == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + err = sakke_load_base_point(key); + } + + /* Compute RSK = [ (a + z_T) ^ 1 modulo q ]P */ + if (err == 0) { + a = &key->tmp.m1; + err = mp_read_unsigned_bin(a, id, idSz); + } + /* a + z_T */ + if (err == 0) { + err = mp_addmod(a, &key->ecc.k, &key->params.q, a); + } + /* (a + z_T) ^ 1 modulo q */ + if (err == 0) { + err = mp_invmod(a, &key->params.q, a); + } + + /* [ (a + z_T) ^ 1 modulo q ]P */ + if (err == 0) { + err = sakke_mulmod_base(key, a, rsk, 1); + } + + return err; +} + +/** + * Encode the SAKKE Receiver Secret Key (RSK) as DER encoded public ECC key. + * + * Encode the RSK to send to ther receiving client. + * + * X and y ordinate of RSK point concatenated. Each number is zero padded to + * key size. + * Descriptor byte (0x04) is prepeneded when not raw. + * + * @param [in] key SAKKE key. + * @param [in] rsk ECC point that is the Receiver Secret Key (RSK). + * @param [out] out Buffer to hold encoded RSK. + * @param [in,out] sz In, size of buffer in bytes. + * Out, size of encoded RSK in bytes. + * @param [in] raw On 0, prepend descriptor byte. + * On 1, only include ordinates. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rsk, or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL - sz will hold the size in bytes of + * the encoded data. + * @return BUFFER_E when size of buffer is too small. + */ +int wc_EncodeSakkeRsk(const SakkeKey* key, ecc_point* rsk, byte* out, + word32* sz, int raw) +{ + int err = 0; + + if ((key == NULL) || (rsk == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_encode_point(rsk, (word32)key->ecc.dp->size, out, sz, raw); + } + + return err; +} + +#endif /* WOLFCRYPT_SAKKE_KMS */ + +#ifdef WOLFCRYPT_SAKKE_CLIENT + +/** + * Decode the KMS public key (Z_T) into the key. + * + * A client imports Z_T to perform derivation of SSV. + * + * X and y ordinate of public key concatenated. Each number is zero padded to + * key size. Supports prepended descriptor byte (0x04). + * + * @param [in] key SAKKE key. + * @param [in] data Encoded public key. + * @param [in] sz Size of the encoded public key in bytes. + * @param [in] trusted 1 when public key is trusted. + * 0 when validation is required to be performed. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or z is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + * @return ECC_OUT_OF_RANGE_E when point is invalid. + * @return ECC_INF_E when point is at infinity and invalid. + */ +int wc_ImportSakkePublicKey(SakkeKey* key, const byte* data, word32 sz, + int trusted) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_decode_point(&key->ecc.pubkey, (word32)key->ecc.dp->size, + data, sz); + } + if (err == 0) { + key->ecc.type = ECC_PUBLICKEY; + key->zMont = 0; + } + if ((err == 0) && (!trusted)) { + err = wc_ecc_check_key(&key->ecc); + } + + return err; +} + +/** + * Decode the SAKKE Receiver Secret Key (RSK) as DER encoded public ECC key. + * + * A receiving client needs the RSK for deriving SSV. + * + * X and y ordinate of RSK point concatenated. Each number is zero padded to + * key size. Supports prepended descriptor byte (0x04). + * + * @param [in] key SAKKE key. + * @param [in] data Buffer holding encoded SAKKE key. + * @param [in] sz Size of encoded RSK in bytes. + * @param [out] rsk ECC point to hold the Receiver Secret Key (RSK). + * @return 0 on success. + * @return BAD_FUNC_ARG when key, data or rsk is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return ASN_PARSE_E when format byte is invalid. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_DecodeSakkeRsk(const SakkeKey* key, const byte* data, word32 sz, + ecc_point* rsk) +{ + int err = 0; + + if ((key == NULL) || (data == NULL) || (rsk == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_decode_point(rsk, (word32)key->ecc.dp->size, data, sz); + } + + return err; +} + +/** + * Decode the SAKKE Receiver Secret Key (RSK) as DER encoded public ECC key and + * stores internally. + * + * A receiving client needs the RSK for deriving SSV. + * + * X and y ordinate of RSK point concatenated. Each number is zero padded to + * key size. Supports prepended descriptor byte (0x04). + * + * @param [in] key SAKKE key. + * @param [in] data Buffer holding encoded SAKKE key. + * @param [in] sz Size of encoded RSK in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or data is NULL. + * @return BUFFER_E when size of data is not equal to the expected size. + * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. + */ +int wc_ImportSakkeRsk(SakkeKey* key, const byte* data, word32 sz) +{ + int err = 0; + + if ((key == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = wc_DecodeSakkeRsk(key, data, sz, key->rsk.rsk); + } + + return err; +} + +/* Base (g) for SAKKE parameter set 1. */ +static const byte sakke_param_set_1_base[] = { + 0x66, 0xFC, 0x2A, 0x43, 0x2B, 0x6E, 0xA3, 0x92, + 0x14, 0x8F, 0x15, 0x86, 0x7D, 0x62, 0x30, 0x68, + 0xC6, 0xA8, 0x7B, 0xD1, 0xFB, 0x94, 0xC4, 0x1E, + 0x27, 0xFA, 0xBE, 0x65, 0x8E, 0x01, 0x5A, 0x87, + 0x37, 0x1E, 0x94, 0x74, 0x4C, 0x96, 0xFE, 0xDA, + 0x44, 0x9A, 0xE9, 0x56, 0x3F, 0x8B, 0xC4, 0x46, + 0xCB, 0xFD, 0xA8, 0x5D, 0x5D, 0x00, 0xEF, 0x57, + 0x70, 0x72, 0xDA, 0x8F, 0x54, 0x17, 0x21, 0xBE, + 0xEE, 0x0F, 0xAE, 0xD1, 0x82, 0x8E, 0xAB, 0x90, + 0xB9, 0x9D, 0xFB, 0x01, 0x38, 0xC7, 0x84, 0x33, + 0x55, 0xDF, 0x04, 0x60, 0xB4, 0xA9, 0xFD, 0x74, + 0xB4, 0xF1, 0xA3, 0x2B, 0xCA, 0xFA, 0x1F, 0xFA, + 0xD6, 0x82, 0xC0, 0x33, 0xA7, 0x94, 0x2B, 0xCC, + 0xE3, 0x72, 0x0F, 0x20, 0xB9, 0xB7, 0xB0, 0x40, + 0x3C, 0x8C, 0xAE, 0x87, 0xB7, 0xA0, 0x04, 0x2A, + 0xCD, 0xE0, 0xFA, 0xB3, 0x64, 0x61, 0xEA, 0x46 +}; + +/* + * Load Pairing Base (g), hex strings in ECC object, into field of key. + * + * Flags that the g is available so it isn't loaded multiple times. + * + * @param [in] key SAKKE key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_load_pairing_base(SakkeKey* key) +{ + int err = 0; + SakkeKeyParams* params = &key->params; + + if (!params->haveG) { + if (key->ecc.dp->id != ECC_SAKKE_1) { + err = NOT_COMPILED_IN; + } + if (err == 0) { + err = mp_read_unsigned_bin(¶ms->g, sakke_param_set_1_base, + sizeof(sakke_param_set_1_base)); + if (err == 0) { + params->haveG = 1; + } + } + } + + return err; +} + +#ifndef WOLFSSL_HAVE_SP_ECC +/* + * Put point into Montgomery form. + * + * @param [in] p ECC point. + * @param [in] prime Prime modulus. + * @param [in] mu Temporary MP integer to hold mu. + * @param [in] set 1 when mu is set and 0 when it needs to be calculated. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_point_to_mont(ecc_point* p, mp_int* prime, mp_int* mu, int set) +{ + int err = 0; + + if (!set) { + /* Calculate multiplier that converts to Montgmery form. */ + err = mp_montgomery_calc_normalization(mu, prime); + } + if (err == 0) { + err = mp_mulmod(p->x, mu, prime, p->x); + } + if (err == 0) { + err = mp_mulmod(p->y, mu, prime, p->y); + } + if (err == 0) { + err = mp_mulmod(p->z, mu, prime, p->z); + } + + return err; +} + +/* + * Take point out of Montgomery form. + * + * @param [in] p ECC point. + * @param [in] prime Prime modulus. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_point_from_mont(ecc_point* p, mp_int* prime, mp_digit mp) +{ + int err; + + err = mp_montgomery_reduce(p->x, prime, mp); + if (err == 0) { + err = mp_montgomery_reduce(p->y, prime, mp); + } + if (err == 0) { + err = mp_montgomery_reduce(p->z, prime, mp); + } + + return err; +} + +/* + * Put Z into Montgomery form. + * + * @param [in] key SAKKE key. + * @param [in] mu Temporary MP integer. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_z_to_mont(SakkeKey* key, mp_int* tmp) +{ + int err = 0; + ecc_point* z = &key->ecc.pubkey; + + if (!key->zMont) { + err = sakke_point_to_mont(z, &key->params.prime, tmp, 0); + if (err == 0) { + key->zMont = 1; + } + } + + return err; +} +#endif + +#ifdef WOLFSSL_HAVE_SP_ECC +/** + * Generate a pre-computation table for the RSK point. + * + * The table contains sensitive data. + * + * @param [in] key SAKKE key. + * @param [in] rsk Point to generate table for. + * @param [out] table Pre-generated values. Passing NULL indicates that + * the length of the table is required. + * @param [in,out] len On in, the size of table buffer in bytes. + * On out, the size of the pre-generated data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rsk or len is NULL. + * @return LENGTH_ONLY_E when table is NULL. + * @return BAD_LENGTH_E when table is specified and len is too small. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_GenerateSakkeRskTable(const SakkeKey* key, const ecc_point* rsk, + byte* table, word32* len) +{ + int err = 0; + + if ((key == NULL) || (rsk == NULL) || (len == 0)) { + err = BAD_FUNC_ARG; + } + if (err == 0) { +#ifdef WOLFSSL_SP_1024 + err = sp_Pairing_gen_precomp_1024(rsk, table, len); +#else + err = NOT_COMPILED_IN; +#endif + } + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [out] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_pairing(const SakkeKey* key, const ecc_point* p, + const ecc_point* q, mp_int* r, const byte* table, word32 len) +{ + int err = NOT_COMPILED_IN; + +#ifdef WOLFSSL_SP_1024 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { + if (table == NULL) { + err = sp_Pairing_1024(p, q, r); + } + else { + err = sp_Pairing_precomp_1024(p, q, r, table, len); + } + } +#else + (void)key; + (void)p; + (void)q; + (void)r; + (void)table; + (void)len; +#endif + + return err; +} + +#else /* WOLFSSL_HAVE_SP_ECC */ +/** + * Generate a pre-computation table for the RSK point. + * + * Empty table as not supported in this implementation. + * + * @param [in] key SAKKE key. + * @param [in] rsk Point to generate table for. + * @param [out] table Pre-generated values. Passing NULL indicates that + * the length of the table is required. + * @param [in,out] len On in, the size of table buffer in bytes. + * On out, the size of the pre-generated data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rsk or len is NULL. + * @return LENGTH_ONLY_E when table is NULL. + * @return BAD_LENGTH_E when table is specified and len is too small. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_GenerateSakkeRskTable(const SakkeKey* key, const ecc_point* rsk, + byte* table, word32* len) +{ + int err = 0; + + if ((key == NULL) || (rsk == NULL) || (len == 0)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)table; + + return err; +} + +/* + * Square a modulo m in Montgomery. + * + * @param [in] a MP integer that is number to square. + * @param [in] m MP integer that is modulus. + * @param [out] r MP integer that is the result. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_mont_sqrmod(mp_int* a, mp_int* m, mp_int* r, mp_digit mp) +{ + int err; + + err = mp_sqr(a, r); + if (err == 0) { + err = mp_montgomery_reduce(r, m, mp); + } + + return err; +} + +/* + * Multiply a by b modulo m in Montgomery. + * + * @param [in] a MP integer that is first number to multiply. + * @param [in] b MP integer that is second number to multiply. + * @param [in] m MP integer that is modulus. + * @param [out] r MP integer that is the result. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_mont_mulmod(mp_int* a, mp_int* b, mp_int* m, mp_int* r, + mp_digit mp) +{ + int err; + + err = mp_mul(a, b, r); + if (err == 0) { + err = mp_montgomery_reduce(r, m, mp); + } + + return err; +} + +/* + * Add a and b modulo m. r = a + b % m + * + * @param [in] a MP integer that is first number to add. + * @param [in] b MP integer that is second number to add. + * @param [out] m MP integer that is modulus. + * @param [in] r MP integer that is the result. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_addmod(mp_int* a, mp_int* b, mp_int* m, mp_int* r) +{ + int err; + + err = mp_add(a, b, r); + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + + return err; +} + +/* + * Triple a modulo m. r = 3.a % m + * + * @param [in] a MP integer that is number to triple + * @param [out] m MP integer that is modulus. + * @param [in] r MP integer that is the result. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_tplmod(mp_int* a, mp_int* m, mp_int* r) +{ + int err; + + err = mp_mul_d(a, 3, r); + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + if ((err == 0) && (mp_cmp(r, m) != MP_LT)) { + err = mp_sub(r, m, r); + } + + return err; +} + +/* + * Subtract b from a modulo m. r = a - b % m + * + * @param [in] a MP integer that is first number to add. + * @param [in] b MP integer that is second number to add. + * @param [in] m MP integer that is modulus. + * @param [out] r MP integer that is the result. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_submod(mp_int* a, mp_int* b, mp_int* m, mp_int* r) +{ + int err; + +#if !defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE) + err = mp_sub(a, b, r); + if ((err == 0) && mp_isneg(r)) { + err = mp_add(r, m, r); + } +#else + err = sp_submod_ct(a, b, m, r); +#endif + + return err; +} + +/* + * Square the element of PF_p[q] (projectivization of F_p with order q). + * + * Calculation: + * r.x = (p.x + p.y) * (p.x - p.y) + * r.y = (p.x * p.y) * 2 + * + * @param [in] p MP projective integer - value to square. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r MP projective integer - Result of square. + * @param [in] t1 MP integer temporary. + * @param [in] t2 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_proj_sqr(mp_proj* p, mp_int* prime, mp_digit mp, mp_proj* r, + mp_int* t1, mp_int* t2) +{ + int err; + + /* t1 = p.x + p.y */ + err = sakke_addmod(p->x, p->y, prime, t1); + /* t2 = p.x - p.y */ + if (err == 0) { + err = sakke_submod(p->x, p->y, prime, t2); + } + /* r.y = p.x * p.y */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, p->y, prime, r->y, mp); + } + /* r.x = (p.x + p.y) * (p.x - p.y) */ + if (err == 0) { + err = sakke_mont_mulmod(t1, t2, prime, r->x, mp); + } + /* r.y = (p.x * p.y) * 2 */ + if (err == 0) { + err = sakke_addmod(r->y, r->y, prime, r->y); + } + + return err; +} + +/* + * Multiply two elements of PF_p[q] (projectivization of F_p with order q). + * + * q must not be the same object as r. + * Calculation: + * r.x = (p.x * q.x) - (p.y * q.y) + * r.y = (p.x * q.y) + (p.y * q.x) + * + * @param [in] p MP projective integer - first value to multiply. + * @param [in] q MP projective integer - second value to multiply. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Result of operation. + * @param [in] t1 MP integer temporary. + * @param [in] t2 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_proj_mul(mp_proj* p, mp_proj* q, mp_int* prime, mp_digit mp, + mp_proj* r, mp_int* t1, mp_int* t2) +{ + int err; + + /* t1 = p.x * q.y */ + err = sakke_mont_mulmod(p->x, q->y, prime, t1, mp); + /* r->x = p.x * q.x */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, q->x, prime, r->x, mp); + } + /* t2 = p.y * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, q->y, prime, t2, mp); + } + /* r.x = (p.x * q.x) - (p.y * q.y) */ + if (err == 0) { + err = sakke_submod(r->x, t2, prime, r->x); + } + /* r.y = p.y * q.x */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, q->x, prime, r->y, mp); + } + /* r.y = (p.x * q.y) + (p.y * q.x) */ + if (err == 0) { + err = sakke_addmod(t1, r->y, prime, r->y); + } + + return err; +} + +/* + * Multiply two elements of PF_p[q] (projectivization of F_p with order q). + * + * q must not be the same object as r. + * Calculation: + * r.x = (p.x * q.x) - (p.y * q.y) + * r.y = (p.x * q.y) + (p.y * q.x) + * But qx = 1 + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * @param [in] p MP projective integer - first value to multiply. + * @param [in] q MP projective integer - second value to multiply. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Result of operation. + * @param [in] t1 MP integer temporary. + * @param [in] t2 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_proj_mul_qx1(mp_proj* p, mp_int* q, mp_int* prime, mp_digit mp, + mp_proj* r, mp_int* t1, mp_int* t2) +{ + int err; + + /* t1 = p.x * q.y */ + err = sakke_mont_mulmod(p->x, q, prime, t1, mp); + /* t2 = p.y * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, q, prime, t2, mp); + } + /* r.x = p.x - (p.y * q.y) */ + if (err == 0) { + err = sakke_submod(p->x, t2, prime, r->x); + } + /* r.y = (p.x * q.y) + p.y */ + if (err == 0) { + err = sakke_addmod(t1, p->y, prime, r->y); + } + + return err; +} + +/* + * Calculate the gradient of line through P, P and [-2]P. + * + * @param [in] p ECC point - first point on the elliptic curve. + * @param [in] t2 MP integer temporary. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] l MP integer representing gradient. + * @param [out] z2 MP integer representing p.z^2. + */ +static int sakke_calc_dbl_rx(ecc_point* p, ecc_point* q, mp_int* prime, + mp_digit mp, mp_proj* r, mp_int* l, mp_int* z2) +{ + int err; + mp_int* t = r->y; + + /* z2 = p.z^2 */ + err = sakke_mont_sqrmod(p->z, prime, z2, mp); + /* t = p.x + p.z^2 */ + if (err == 0) { + err = sakke_addmod(p->x, z2, prime, l); + } + /* r1 = p.x - p.z^2 */ + if (err == 0) { + err = sakke_submod(p->x, z2, prime, t); + } + /* l = ((p.x - p.z^2) * (p.x + p.z^2) = p.x ^ 2 - p.z^4 */ + if (err == 0) { + err = sakke_mont_mulmod(l, t, prime, l, mp); + } + /* l = ((p.x ^ 2) - p.z^4) * 3 */ + if (err == 0) { + err = sakke_tplmod(l, prime, l); + } + /* t = q.x * p.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(q->x, z2, prime, t, mp); + } + /* t = p.x + q.x * p.z^2 */ + if (err == 0) { + err = sakke_addmod(p->x, t, prime, t); + } + /* r.x = l * (p.x + q.x * p.z^2) */ + if (err == 0) { + err = sakke_mont_mulmod(l, t, prime, r->x, mp); + } + + return err; +} + +#ifdef WOLFSSL_SAKKE_SMALL +/* + * Calculate gradient of line through P, P and [-2]P and accumulate line. + * + * Calculation: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y + * v* = v*^2 * r* + * + * @param [in] p ECC point - first point on the elliptic curve. + * @param [in] q ECC point - second point on the elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r MP projective integer - gradient in PF_p[q]. + * @param [in] t1 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_dbl(mp_proj* v, ecc_point* p, ecc_point* q, + mp_int* prime, mp_digit mp, mp_proj* r, mp_int** t) +{ + int err; + mp_int* t1 = t[0]; + mp_int* t2 = r->z; + mp_int* z2 = t[1]; + mp_int* l = t1; + + /* v = v^2 */ + err = sakke_proj_sqr(v, prime, mp, v, t1, t2); + /* l = 3 * (p.x^2 - p.z^4), z2 = p.z^2, rx = l * (p.x + q.x * p.z^2) */ + if (err == 0) { + err = sakke_calc_dbl_rx(p, q, prime, mp, r, l, z2); + } + /* t1 = p.y ^ 2 */ + if (err == 0) { + err = sakke_mont_sqrmod(p->y, prime, t1, mp); + } + /* t1 = 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_addmod(t1, t1, prime, t1); + } + /* r.x -= 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_submod(r->x, t1, prime, r->x); + } + /* r.y = p.y * 2 */ + if (err == 0) { + err = sakke_addmod(p->y, p->y, prime, r->y); + } + /* r.y = (p.y * 2) * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, q->y, prime, r->y, mp); + } + /* t2 = p.z^3 */ + if (err == 0) { + err = sakke_mont_mulmod(p->z, z2, prime, t2, mp); + } + /* r.y *= p.z^3 */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, t2, prime, r->y, mp); + } + /* v = v^2 * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + return err; +} + +/* + * Calculate gradient of line through C, P and -C-P and accumulate line. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * + * @param [in] p First point on elliptic curve. + * @param [in] q Second point on elliptic curve. + * @param [in] c Third point on elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Resulting gradient in PF_p[q]. + * @param [in] t MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_add_one(mp_proj* v, mp_int* prime, mp_digit mp, + ecc_point* p, ecc_point* q, ecc_point* c, mp_proj* r, mp_int* t1) +{ + int err; + mp_int* t2 = r->z; + + /* r.x = (q.x + p.x) * c.y */ + err = sakke_addmod(q->x, p->x, prime, r->x); + if (err == 0) { + err = sakke_mont_mulmod(r->x, c->y, prime, r->x, mp); + } + /* t2 = c.z^2 */ + if (err == 0) { + err = sakke_mont_sqrmod(c->z, prime, t2, mp); + } + /* t = q.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(q->x, t2, prime, t1, mp); + } + /* t = q.x * c.z^2 + c.x */ + if (err == 0) { + err = sakke_addmod(t1, c->x, prime, t1); + } + /* t = (q.x * c.z^2 + c.x) * p.y */ + if (err == 0) { + err = sakke_mont_mulmod(t1, p->y, prime, t1, mp); + } + /* t *= c.z */ + if (err == 0) { + err = sakke_mont_mulmod(t1, c->z, prime, t1, mp); + } + /* r.x -= t */ + if (err == 0) { + err = sakke_submod(r->x, t1, prime, r->x); + } + /* t = p.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, t2, prime, t1, mp); + } + /* r.y = c.x - p.x * c.z^2 */ + if (err == 0) { + err = sakke_submod(c->x, t1, prime, r->y); + } + /* r.y = (c.x - p.x) * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, q->y, prime, r->y, mp); + } + /* r.y = c.x - p.x) * q.y * c.z */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, c->z, prime, r->y, mp); + } + /* v = v * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + return err; +} +#else +/* + * Calculate gradient of line through P, P and [-2]P and accumulate line. + * Double the point p. + * + * Calculation: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in] p ECC point - first point on the elliptic curve. + * @param [in] q ECC point - second point on the elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r MP projective integer - gradient in PF_p[q]. + * @param [in] t1 MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_dbl(mp_proj* v, ecc_point* p, ecc_point* q, + mp_int* prime, mp_digit mp, mp_proj* r, mp_int** t) +{ + int err; + mp_int* t1 = t[0]; + mp_int* t2 = r->z; + mp_int* z2 = t[1]; + mp_int tmp[2]; + mp_int* l = &tmp[0]; + mp_int* ty = &tmp[1]; + + err = mp_init(l); + if (err == 0) { + err = mp_init(ty); + } + + /* v = v^2 */ + if (err == 0) { + err = sakke_proj_sqr(v, prime, mp, v, t1, t2); + } + /* l = 3 * (p.x^2 - p.z^4), z2 = p.z^2, rx = l * (p.x + q.x * p.z^2) */ + if (err == 0) { + err = sakke_calc_dbl_rx(p, q, prime, mp, r, l, z2); + } + /* ty = p.y ^ 2 */ + if (err == 0) { + err = sakke_mont_sqrmod(p->y, prime, ty, mp); + } + /* ty = 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_addmod(ty, ty, prime, ty); + } + /* r.x -= 2 * (p.y ^ 2) */ + if (err == 0) { + err = sakke_submod(r->x, ty, prime, r->x); + } + /* r.y = p.y * 2 */ + if (err == 0) { + err = sakke_addmod(p->y, p->y, prime, r->y); + } + /* r.y = p.y * 2 * p.z */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, p->z, prime, p->z, mp); + } + /* r.y = p.y * 2 * p.z^3 */ + if (err == 0) { + err = sakke_mont_mulmod(p->z, z2, prime, r->y, mp); + } + /* r.y = (p.y * 2 * p.z^3) * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(r->y, q->y, prime, r->y, mp); + } + /* v = v^2 * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + /* Double point using previously calculated values + * l = 3 * (X - Z^2).(X + Z^2) + * ty = 2 * Y^2 + * Z = 2 * Y * Z + */ + /* Y = 2 * 2 * Y^2 */ + if (err == 0) { + err = sakke_addmod(ty, ty, prime, p->y); + } + /* T2 = 4 * Y^4 */ + if (err == 0) { + err = sakke_mont_sqrmod(ty, prime, t2, mp); + } + /* T2 = 8 * Y^4 */ + if (err == 0) { + err = sakke_addmod(t2, t2, prime, t2); + } + /* Y = Y * X */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, p->x, prime, p->y, mp); + } + /* X = l * l */ + if (err == 0) { + err = sakke_mont_sqrmod(l, prime, p->x, mp); + } + /* X = X - Y */ + if (err == 0) { + err = sakke_submod(p->x, p->y, prime, p->x); + } + /* X = X - Y */ + if (err == 0) { + err = sakke_submod(p->x, p->y, prime, p->x); + } + /* Y = Y - X */ + if (err == 0) { + err = sakke_submod(p->y, p->x, prime, p->y); + } + /* Y = Y * l */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, l, prime, p->y, mp); + } + /* Y = Y - T2 */ + if (err == 0) { + err = sakke_submod(p->y, t2, prime, p->y); + } + + mp_free(ty); + mp_free(l); + + return err; +} + +/* + * Calculate gradient of line through C, P and -C-P and accumulate line. + * Add point p into c. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in] p First point on elliptic curve. + * @param [in] q Second point on elliptic curve. + * @param [in] c Third point on elliptic curve. + * @param [in] prime MP integer that is the modulus of the field. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @param [out] r Resulting gradient in PF_p[q]. + * @param [in] t MP integer temporary. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_accumulate_line_add_one(mp_proj* v, mp_int* prime, mp_digit mp, + ecc_point* p, ecc_point* q, ecc_point* c, mp_proj* r, mp_int** t) +{ + int err; + mp_int* t1 = t[0]; + mp_int* t2 = t[1]; + mp_int tmp[4]; + mp_int* h = &tmp[0]; + mp_int* ty = &tmp[1]; + mp_int* tz = &tmp[2]; + mp_int* t3 = &tmp[3]; + + err = mp_init_multi(h, ty, tz, t3, NULL, NULL); + + /* r.x = (q.x + p.x) * c.y */ + if (err == 0) { + err = sakke_addmod(q->x, p->x, prime, r->x); + } + if (err == 0) { + err = sakke_mont_mulmod(r->x, c->y, prime, r->x, mp); + } + /* tz = c.z^2 */ + if (err == 0) { + err = sakke_mont_sqrmod(c->z, prime, tz, mp); + } + /* t = q.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(q->x, tz, prime, t1, mp); + } + /* t = q.x * c.z^2 + c.x */ + if (err == 0) { + err = sakke_addmod(t1, c->x, prime, t1); + } + /* ty = p.y * c.z */ + if (err == 0) { + err = sakke_mont_mulmod(p->y, c->z, prime, ty, mp); + } + /* t = (q.x * c.z^2 + c.x) * p.y * c.z */ + if (err == 0) { + err = sakke_mont_mulmod(t1, ty, prime, t1, mp); + } + /* r.x -= t */ + if (err == 0) { + err = sakke_submod(r->x, t1, prime, r->x); + } + /* t = p.x * c.z^2 */ + if (err == 0) { + err = sakke_mont_mulmod(p->x, tz, prime, t1, mp); + } + /* h = c.x - p.x * c.z^2 */ + if (err == 0) { + err = sakke_submod(c->x, t1, prime, h); + } + /* t3 = (c.x - p.x * c.z^2 ) * c.z*/ + if (err == 0) { + err = sakke_mont_mulmod(h, c->z, prime, t3, mp); + } + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + if (err == 0) { + err = sakke_mont_mulmod(t3, q->y, prime, r->y, mp); + } + /* v = v * r */ + if (err == 0) { + err = sakke_proj_mul(v, r, prime, mp, v, t1, t2); + } + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * ty = p.y * c.z + * tz = c.z^2 + * t3 = (c.x - p.x * c.z^2) * c.z + */ + + /* R = p.y * c.z^3 - c.y */ + if (err == 0) { + err = sakke_mont_mulmod(ty, tz, prime, ty, mp); + } + if (err == 0) { + err = sakke_submod(ty, c->y, prime, ty); + } + /* c'.z = -H * c.z */ + if (err == 0) { + err = sakke_submod(prime, t3, prime, c->z); + } + /* c'.x = R^2 + H^3 - 2 * c.x * H^2 */ + if (err == 0) { + err = sakke_mont_sqrmod(ty, prime, t1, mp); + } + if (err == 0) { + err = sakke_mont_sqrmod(h, prime, t2, mp); + } + if (err == 0) { + err = sakke_mont_mulmod(c->x, t2, prime, t3, mp); + } + if (err == 0) { + err = sakke_mont_mulmod(t2, h, prime, t2, mp); + } + if (err == 0) { + err = sakke_addmod(t1, t2, prime, c->x); + } + if (err == 0) { + err = sakke_addmod(t3, t3, prime, t1); + } + if (err == 0) { + err = sakke_submod(c->x, t1, prime, c->x); + } + /* c'.y = R * (c.x * H^2 - c'.x) + c.y * H^3 */ + if (err == 0) { + err = sakke_submod(t3, c->x, prime, t3); + } + if (err == 0) { + err = sakke_mont_mulmod(t3, ty, prime, t3, mp); + } + if (err == 0) { + err = sakke_mont_mulmod(t2, c->y, prime, t2, mp); + } + if (err == 0) { + err = sakke_addmod(t3, t2, prime, c->y); + } + + mp_free(t3); + mp_free(tz); + mp_free(ty); + mp_free(h); + + return err; +} +#endif /* WOLFSSL_SAKKE_SMALL */ + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [out] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_pairing(SakkeKey* key, ecc_point* p, ecc_point* q, mp_int* r, + const byte* table, word32 len) +{ + int err; + ecc_point* v = key->params.base; + ecc_point* c = key->tmp.p1; + mp_proj* t2 = key->tmp.p3; + mp_int* t3 = &key->tmp.m2; + mp_int* prime = &key->params.prime; + mp_int* t[] = { &key->tmp.m1, t3 }; + int i; + mp_digit mp = 0; + SakkeKeyParams* params = &key->params; + + (void)table; + (void)len; + + err = sakke_point_to_mont(p, prime, &key->tmp.m1, 0); + if (err == 0) { + err = sakke_point_to_mont(q, prime, &key->tmp.m1, 1); + } + if (err == 0) { + err = wc_ecc_copy_point(p, c); + } + /* Set v to 1. */ + if (err == 0) { + params->haveBase = 0; + err = mp_set(v->x, 1); + } + if (err == 0) { + err = mp_set(v->y, 0); + } + if (err == 0) { + err = mp_montgomery_setup(prime, &mp); + } + + for (i = mp_count_bits(¶ms->q) - 2; (err == 0) && (i >= 0); i--) { +#ifdef WOLFSSL_SAKKE_SMALL + /* Accumulate line into v and double point. */ + err = sakke_accumulate_line_dbl(v, c, q, prime, mp, t2, t); + if (err == 0) { + err = ecc_projective_dbl_point(c, c, NULL, prime, mp); + } + + if ((err == 0) && (i > 0) && mp_is_bit_set(¶ms->q, i)) { + /* Accumulate line into v and add P into C. */ + err = sakke_accumulate_line_add_one(v, prime, mp, p, q, c, t2, + &key->tmp.m1); + if (err == 0) { + err = ecc_projective_add_point(p, c, c, NULL, prime, mp); + } + } +#else + /* Accumulate line into v and double point. */ + err = sakke_accumulate_line_dbl(v, c, q, prime, mp, t2, t); + + if ((err == 0) && (i > 0) && mp_is_bit_set(¶ms->q, i)) { + /* Accumulate line into v and add P into C. */ + err = sakke_accumulate_line_add_one(v, prime, mp, p, q, c, t2, t); + } +#endif /* WOLFSSL_SAKKE_SMALL */ + } + + /* Final exponentiation */ + if (err == 0) { + err = sakke_proj_sqr(v, prime, mp, v, &key->tmp.m1, t3); + } + if (err == 0) { + err = sakke_proj_sqr(v, prime, mp, v, &key->tmp.m1, t3); + } + /* Convert from PF_p[q] to F_p */ + if (err == 0) { + err = mp_invmod(v->x, prime, r); + } + if (err == 0) { + err = mp_mulmod(r, v->y, prime, r); + } + + if (err == 0) { + err = sakke_point_from_mont(p, prime, mp); + } + if (err == 0) { + err = sakke_point_from_mont(q, prime, mp); + } + + return err; +} +#endif /* WOLFSSL_HAVE_SP_ECC */ + +/** + * Set the Receiver Secret Key (RSK) and any table associated with it. + * + * @param [in] key SAKKE key. + * @param [in] rsk Receiver Secret Key (RSK) as an ECC point. + * @param [in] table Pre-computation table. May be NULL. + * @param [in] len Size of pre-compuration table in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or rsk is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_SetSakkeRsk(SakkeKey* key, const ecc_point* rsk, byte* table, word32 len) +{ + int err = 0; + + if ((key == NULL) || (rsk == NULL)) { + err = BAD_FUNC_ARG; + } + if (err == 0) { + key->rsk.set = 0; + err = wc_ecc_copy_point(rsk, key->rsk.rsk); + } + if (err == 0) { + key->rsk.table = table; + key->rsk.tableLen = len; + key->rsk.set = 1; + } + + return err; +} + +/* + * Compute the elliptic curve point I for device B. Partial for point R. + * + * RFC 6508, Section 6.2.1, Step 3.\n + * RFC 6508, Section 6.2.2, Step 5.\n + * I = [b]P + Z_S + * + * @param [in] key SAKKE key. + * @param [in] id Identifier to of device B. + * @param [in] idSz Size of identifier in bytes. + * @param [out] i ECC point - partial for point R. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_compute_point_i(SakkeKey* key, const byte* id, word16 idSz, + ecc_point* i) +{ + int err; + mp_int* b = &key->ecc.k; + + /* Load b - ID of receiver */ + err = mp_read_unsigned_bin(b, id, idSz); + if (err == 0) { + err = sakke_load_base_point(key); + } +#ifndef WOLFSSL_HAVE_SP_ECC + /* Convert to montgomery form for add operation. */ + if (err == 0) { + err = sakke_z_to_mont(key, &key->tmp.m2); + } +#endif + /* [b]P + Z_S */ + if (err == 0) { + ecc_point* z = &key->ecc.pubkey; + err = sakke_mulmod_base_add(key, b, z, i, 1); + } + return err; +} + +/** + * Validate the Receiver Secret Key (RSK) with the identity. + * + * RFC 6508, Section 6.1.2 + * + * A receiving client should validate an RSK before use. + * + * @param [in] key SAKKE key. + * @param [in] id Identity to use. + * @param [in] idSz Size of identity in bytes. + * @param [in] rsk Receiver Secret Key as an ECC point. + * @param [out] valid 1 indicates RSK is valid for identity. + * 0 otherwise. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, id, rsk or valid is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int wc_ValidateSakkeRsk(SakkeKey* key, const byte* id, word16 idSz, + ecc_point* rsk, int* valid) +{ + int err = 0; + mp_int* a = NULL; + + if ((key == NULL) || (id == NULL) || (rsk == NULL) || (valid == NULL)) { + err = BAD_FUNC_ARG; + } + + /* Load elliptic curve parameters */ + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + err = sakke_load_base_point(key); + } + /* Load pairing base - g */ + if (err == 0) { + err = sakke_load_pairing_base(key); + } + /* Load a - identifier */ + if (err == 0) { + a = &key->tmp.m1; + err = mp_read_unsigned_bin(a, id, idSz); + } + + if (err == 0) { + /* I = [b]P + Z_S */ + err = sakke_compute_point_i(key, id, idSz, key->i.i); + if ((err == 0) && (idSz <= SAKKE_ID_MAX_SIZE)) { + XMEMCPY(key->i.id, id, idSz); + key->i.idSz = idSz; + } + } + /* < [a]P + Z, K_(a,T) > = < K_(a,T), [a]P + Z > = < rsk, i >*/ + if (err == 0) { + err = sakke_pairing(key, rsk, key->i.i, a, NULL, 0); + } + + /* Compare pairing result with generator. */ + if (valid != NULL) { + *valid = ((err == 0) && (mp_cmp(a, &key->params.g) == MP_EQ)); + } + + return err; +} + +/** + * Get the size of the authentication data that is the first part of the + * encapsulated data. + * + * Clients need to know how long the authentication data so as the SSV starts + * after the authentication data in a buffer.\n + * For SAKKE parameter set 1: 257 bytes + * + * @param [in] key SAKKE key. + * @param [out] authSz Size of authentication data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or authSz is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int wc_GetSakkeAuthSize(SakkeKey* key, word16* authSz) +{ + int err = 0; + + if ((key == NULL) || (authSz == NULL)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + word16 n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8); + *authSz = 1 + 2 * n; + } + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_ECC +/* + * Modular exponentiate the value in F_p*. + * + * @param [in] key SAKKE key. + * @param [in] b MP integer that is the base to exponentiate. + * @param [in] e MP integer that is the exponent. + * @param [out] r Result of exponentiation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_modexp(const SakkeKey* key, const mp_int* b, mp_int* e, + mp_int* r) +{ + int err = NOT_COMPILED_IN; + +#ifdef WOLFSSL_SP_1024 + if ((key->ecc.idx != ECC_CUSTOM_IDX) && + (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { + err = sp_ModExp_Fp_star_1024(b, e, r); + } +#endif + + return err; +} +#else +#ifdef WOLFSSL_SAKKE_SMALL +/* + * Modular exponentiate the value in F_p*. + * + * @param [in] key SAKKE key. + * @param [in] b MP integer that is the base to exponentiate. + * @param [in] e MP integer that is the exponent. + * @param [out] c Result of exponentiation. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_modexp_loop(SakkeKey* key, mp_int* b, mp_int* e, mp_proj* c, + mp_digit mp) +{ + int err; + mp_int* t1 = &key->tmp.m1; + mp_int* t2 = &key->tmp.m2; + mp_int* by = key->tmp.p1->z; + mp_int* prime = &key->params.prime; + int i; + + /* Set the working value to the base in PF_p[q] */ + err = mp_montgomery_calc_normalization(c->x, prime); + /* Set c->y as montgomery form of b - base */ + if (err == 0) { + err = mp_mulmod(b, c->x, prime, by); + } + /* Set by as montgomery form of b - base */ + if (err == 0) { + err = mp_copy(by, c->y); + } + /* Simple non-constant time exponentiation over a field. */ + for (i = mp_count_bits(e) - 2; (err == 0) && (i >= 0); i--) { + err = sakke_proj_sqr(c, prime, mp, c, t1, t2); + if (err == 0) { + if (mp_is_bit_set(e, i)) { + err = sakke_proj_mul_qx1(c, by, prime, mp, c, t1, t2); + } + } + } + + return err; +} + +#elif defined(WOLFSSL_SAKKE_SMALL_MODEXP) || !defined(USE_FAST_MATH) + +/* + * Modular exponentiate the value in F_p*. + * + * @param [in] key SAKKE key. + * @param [in] b MP integer that is the base to exponentiate. + * @param [in] e MP integer that is the exponent. + * @param [out] r Result of exponentiation. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_modexp_loop(SakkeKey* key, mp_int* b, mp_int* e, mp_proj* r, + mp_digit mp) +{ + int err; +#ifdef WC_NO_CACHE_RESISTANT + mp_proj* c[2] = { r, key->tmp.p2 }; +#else + mp_proj* c[3] = { r, key->tmp.p3, key->tmp.p2 }; +#endif + mp_int* t1 = &key->tmp.m1; + mp_int* t2 = &key->tmp.m2; + mp_int* by = key->tmp.p1->z; + mp_int* prime = &key->params.prime; + int i; + + /* Set the working value to the base in PF_p[q] */ + err = mp_montgomery_calc_normalization(c[0]->x, prime); + /* Set c[0] to [mont_one, zero] */ + if (err == 0) { + mp_zero(c[0]->y); + + /* Set 'by' to montgomery form of 'b' - base */ + err = mp_mulmod(b, c[0]->x, prime, by); + } + for (i = mp_count_bits(&key->params.q) - 1; (err == 0) && (i >= 0); i--) { + int j = mp_is_bit_set(e, i); + err = sakke_proj_sqr(c[0], prime, mp, c[0], t1, t2); + if (err == 0) { +#ifdef WC_NO_CACHE_RESISTANT + err = sakke_proj_mul_qx1(c[0], by, prime, mp, c[j^1], t1, t2); +#else + err = sakke_proj_mul_qx1(c[0], by, prime, mp, c[2], t1, t2); + mp_copy(c[2]->x, + (mp_int*) ( ((wolfssl_word)c[0]->x & wc_off_on_addr[j]) + + ((wolfssl_word)c[1]->x & wc_off_on_addr[j^1]) ) ); + mp_copy(c[2]->y, + (mp_int*) ( ((wolfssl_word)c[0]->y & wc_off_on_addr[j]) + + ((wolfssl_word)c[1]->y & wc_off_on_addr[j^1]) ) ); +#endif + } + } + + return err; +} + +#else + +/* Table for 8-bit striping exponentiation. */ +static const byte sakke_1024_g_table[256][128] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x59, 0xe9, 0x3c, 0x6a, 0x6b, 0xd3, 0xba, 0xf4, 0xaf, 0xd5, + 0x88, 0x91, 0xe8, 0x6c, 0xb2, 0x21, 0x61, 0x52, 0xba, 0x02, + 0xc7, 0x27, 0xc9, 0x8e, 0x21, 0xf1, 0x1c, 0x06, 0x7d, 0x3b, + 0x4f, 0x7d, 0x66, 0xdb, 0xd0, 0x9a, 0x9b, 0x67, 0xe0, 0x96, + 0x6f, 0xaf, 0x7a, 0x00, 0x61, 0xc1, 0xf3, 0x0d, 0x0e, 0x74, + 0x1a, 0x1b, 0x2d, 0x8e, 0xae, 0x58, 0xd6, 0xd8, 0x59, 0xbf, + 0x16, 0xac, 0x6c, 0x6f, 0xad, 0xde, 0xdc, 0x85, 0x8f, 0x88, + 0x71, 0x7c, 0x27, 0xbe, 0x88, 0x2c, 0x2f, 0xd1, 0x51, 0xe6, + 0xd8, 0x9e, 0x2d, 0x14, 0x72, 0xbf, 0x1a, 0xfb, 0x3a, 0xf4, + 0x9b, 0xb4, 0xb3, 0x65, 0x76, 0xd1, 0x26, 0x46, 0xf8, 0x15, + 0x82, 0x64, 0x24, 0x75, 0x40, 0xe8, 0xf3, 0xdf, 0x43, 0xca, + 0x4a, 0x73, 0xea, 0xc9, 0xe9, 0x71, 0xe1, 0x00, 0x7a, 0x58, + 0x17, 0x0a, 0x46, 0xd2, 0x33, 0x5c, 0x16, 0x85 }, + { 0x63, 0xef, 0x18, 0x7b, 0x74, 0xf6, 0x2e, 0x03, 0xbe, 0x85, + 0xac, 0x6a, 0x9b, 0x6a, 0x52, 0xb9, 0x5f, 0x19, 0xc2, 0x0d, + 0x6f, 0x83, 0x73, 0xd3, 0x16, 0xf1, 0x86, 0x31, 0x50, 0xa9, + 0xd0, 0xd9, 0x13, 0x94, 0x6d, 0x17, 0x9f, 0x7b, 0xfa, 0x2e, + 0xdd, 0x9f, 0x6a, 0x91, 0x0a, 0x18, 0x0e, 0xb6, 0x51, 0xf7, + 0x11, 0x9b, 0x4a, 0xc8, 0x43, 0x1c, 0xfd, 0x45, 0x62, 0x67, + 0x40, 0x38, 0x98, 0x13, 0x81, 0x3d, 0x1c, 0xb2, 0x2e, 0xcb, + 0x96, 0x52, 0xb9, 0xbd, 0x3a, 0xfd, 0xf5, 0xcb, 0x6a, 0xb5, + 0x11, 0x8b, 0xd7, 0x92, 0xc1, 0x13, 0x99, 0xfa, 0x97, 0x53, + 0x79, 0x4c, 0x8f, 0x5c, 0x14, 0x18, 0x85, 0x88, 0xaa, 0x99, + 0x3f, 0x52, 0x09, 0x28, 0x9e, 0xa5, 0xa4, 0x4e, 0xa1, 0x9f, + 0x65, 0x30, 0xbb, 0xc9, 0xcc, 0x9f, 0x00, 0xae, 0xf1, 0xe6, + 0xe5, 0x4d, 0xd3, 0x6f, 0x71, 0xdd, 0x45, 0x94 }, + { 0x4f, 0xe6, 0x79, 0x1c, 0xf1, 0x92, 0xda, 0x23, 0x90, 0xdc, + 0xc7, 0x94, 0xdd, 0xac, 0x2c, 0xda, 0x50, 0x5e, 0x8e, 0xc2, + 0xeb, 0x19, 0x96, 0x33, 0x68, 0x2e, 0xcc, 0x49, 0x47, 0x68, + 0x5f, 0xbe, 0xab, 0x0c, 0xb6, 0x3c, 0x12, 0x9f, 0x85, 0xcb, + 0xb1, 0x36, 0x09, 0x86, 0x15, 0x55, 0x9c, 0x41, 0x7f, 0xf3, + 0x35, 0x4e, 0x3f, 0x98, 0x60, 0xc8, 0xa0, 0xed, 0x29, 0x9b, + 0x0f, 0x5c, 0x6c, 0xd1, 0xae, 0x18, 0x28, 0x30, 0x73, 0x3f, + 0xa3, 0xbe, 0x93, 0x3e, 0x0d, 0x41, 0xb3, 0x30, 0xbc, 0x4d, + 0x5b, 0x40, 0x74, 0x74, 0xbb, 0x60, 0xf8, 0xcf, 0xbd, 0xa4, + 0x1b, 0x1f, 0x72, 0x41, 0x09, 0x8b, 0x6f, 0xdb, 0xf0, 0xa2, + 0xc7, 0xaf, 0xd8, 0x1d, 0x73, 0x92, 0xf7, 0x41, 0xce, 0x42, + 0x9b, 0x60, 0x1c, 0x1b, 0xdb, 0x57, 0x2b, 0xec, 0x82, 0xf8, + 0x7c, 0x37, 0x6b, 0x7f, 0x01, 0x6f, 0x45, 0xe7 }, + { 0x04, 0x48, 0x2a, 0x18, 0x56, 0x1d, 0xb2, 0x97, 0x55, 0x5d, + 0x1f, 0xfe, 0xbe, 0x78, 0xd9, 0xd2, 0x18, 0xc2, 0x1f, 0x61, + 0x1a, 0x04, 0x01, 0x70, 0x30, 0x95, 0x70, 0xc4, 0x4e, 0x9a, + 0x1e, 0x52, 0xfa, 0x4d, 0xb1, 0x14, 0x8e, 0x95, 0x07, 0x61, + 0x30, 0xcf, 0xa7, 0xce, 0x5c, 0xac, 0x4a, 0xab, 0xb5, 0x5e, + 0xfd, 0xd0, 0x60, 0x68, 0x9a, 0x9a, 0xea, 0x52, 0xd0, 0x26, + 0x23, 0x3f, 0x98, 0xd5, 0xaa, 0xa7, 0xa6, 0x1a, 0x7b, 0x81, + 0xce, 0xa6, 0x43, 0x0a, 0x6d, 0xe5, 0xe8, 0x8c, 0xea, 0xf6, + 0x9d, 0xfd, 0xe9, 0xed, 0xb2, 0xc1, 0x7b, 0x09, 0x00, 0xc8, + 0x75, 0xe2, 0x71, 0x3b, 0xd7, 0x21, 0x0c, 0x44, 0x71, 0xc6, + 0xdb, 0x41, 0x81, 0xcc, 0x23, 0x7c, 0x7e, 0x88, 0xe9, 0x61, + 0xb3, 0x22, 0xcc, 0x84, 0x5e, 0x65, 0x1d, 0x57, 0x17, 0xc1, + 0x94, 0xa4, 0x23, 0xd5, 0x05, 0xe8, 0x73, 0x3c }, + { 0x83, 0x3a, 0x0f, 0xf8, 0xde, 0xdb, 0xf8, 0x9f, 0x1a, 0x9c, + 0x3f, 0x25, 0x68, 0xcc, 0xdb, 0x44, 0xfa, 0x13, 0x50, 0xd3, + 0xe7, 0x34, 0x27, 0x02, 0x0d, 0x26, 0x7f, 0xd9, 0x86, 0x92, + 0x07, 0x7a, 0x66, 0xe1, 0xa4, 0x9f, 0xd7, 0x35, 0x57, 0xe9, + 0x5b, 0x51, 0x85, 0x4d, 0x35, 0x45, 0x96, 0x68, 0x40, 0xc2, + 0x7a, 0x04, 0x32, 0xa3, 0xd2, 0x22, 0x96, 0x3b, 0x05, 0x3e, + 0xd7, 0xb2, 0xea, 0x45, 0xc8, 0xe4, 0x49, 0x9c, 0x57, 0x12, + 0x8d, 0x37, 0xd6, 0xf2, 0x1f, 0x1a, 0x7e, 0x44, 0xfe, 0xb5, + 0x28, 0xfc, 0x30, 0x7c, 0x45, 0x31, 0xbc, 0x60, 0x56, 0x0b, + 0xee, 0x25, 0xbd, 0x8c, 0x22, 0x60, 0xa0, 0xe5, 0x4f, 0x02, + 0xf3, 0x37, 0x36, 0x30, 0x72, 0x3c, 0x99, 0xfc, 0x21, 0x88, + 0xab, 0x4f, 0x81, 0x69, 0xf9, 0x46, 0x61, 0xcd, 0xc1, 0xe7, + 0xe7, 0x75, 0x8a, 0xc2, 0x73, 0xd4, 0x86, 0xd8 }, + { 0x69, 0x2b, 0x3c, 0xe3, 0xeb, 0x24, 0x96, 0x5f, 0x2e, 0x2d, + 0xf9, 0x5a, 0x85, 0xf8, 0x11, 0xa0, 0x74, 0x1f, 0xd5, 0x1a, + 0xf4, 0xf0, 0x5c, 0x0c, 0x03, 0xf7, 0x3e, 0xa6, 0xa2, 0xb7, + 0x44, 0xf1, 0x1f, 0xec, 0x95, 0xe1, 0xd8, 0xa1, 0x05, 0x8a, + 0x22, 0xd6, 0x39, 0xc8, 0xcb, 0x11, 0x87, 0xdb, 0x42, 0x13, + 0xbe, 0x88, 0x2d, 0xd0, 0x6e, 0xc0, 0xf3, 0x66, 0xed, 0x59, + 0xe9, 0xdb, 0xad, 0xd1, 0x33, 0x9e, 0xda, 0xd6, 0xa1, 0xd5, + 0xc2, 0x70, 0xe5, 0x13, 0x35, 0x0b, 0xe6, 0xeb, 0x26, 0x0b, + 0x04, 0xbe, 0x5a, 0xee, 0xb4, 0xc1, 0x6a, 0x2a, 0x56, 0xfe, + 0xe0, 0x7b, 0x09, 0x8c, 0x0a, 0x88, 0x93, 0x1b, 0xa5, 0x1e, + 0xa6, 0x25, 0x75, 0xa6, 0xe5, 0x6b, 0xb9, 0xe2, 0xa9, 0x0c, + 0x51, 0x4d, 0x3b, 0x72, 0x94, 0xf3, 0x27, 0xd0, 0xf0, 0xcc, + 0xa8, 0xc4, 0x19, 0xc7, 0xab, 0x37, 0x6b, 0x76 }, + { 0x33, 0x3e, 0x43, 0x0a, 0xf4, 0x00, 0x42, 0xd6, 0xc0, 0xcf, + 0x0a, 0xaf, 0x81, 0xde, 0x5f, 0xe0, 0x77, 0x41, 0x91, 0xb1, + 0x89, 0xef, 0x09, 0xf2, 0x64, 0x47, 0x90, 0x38, 0x70, 0x36, + 0x1f, 0x25, 0x32, 0xd6, 0x43, 0x31, 0xd4, 0x12, 0x83, 0x27, + 0x8c, 0x4e, 0x85, 0x33, 0x54, 0x52, 0x64, 0x3c, 0x05, 0xb9, + 0x49, 0x1c, 0xa0, 0x9d, 0x46, 0x95, 0x58, 0x1f, 0xa3, 0x97, + 0x3d, 0x65, 0x29, 0x36, 0x54, 0xc2, 0x40, 0xd7, 0x7d, 0x2a, + 0xf8, 0x31, 0x17, 0x4d, 0x0b, 0x40, 0x74, 0xe2, 0x52, 0xf9, + 0x2f, 0x42, 0x6c, 0xae, 0x4d, 0xe4, 0xe6, 0x65, 0xc8, 0x14, + 0x5c, 0x6d, 0xb2, 0xed, 0xbe, 0x8c, 0x16, 0x3d, 0x9a, 0x01, + 0xe0, 0xab, 0x96, 0xee, 0x43, 0xec, 0xf4, 0x63, 0x47, 0xa3, + 0x76, 0x16, 0x66, 0xa4, 0x6e, 0xa5, 0x8f, 0x92, 0x81, 0x6f, + 0x0c, 0xe6, 0xcb, 0x72, 0xd2, 0xa1, 0x27, 0xb4 }, + { 0x10, 0xe8, 0xb3, 0x1d, 0xd6, 0xbb, 0xd7, 0x08, 0xae, 0x12, + 0x76, 0x36, 0x2f, 0x77, 0x91, 0xd1, 0xbb, 0x18, 0xd1, 0x75, + 0x4a, 0xeb, 0x02, 0xa3, 0x8a, 0xdc, 0x6f, 0xe5, 0x45, 0x9e, + 0xa4, 0x62, 0xeb, 0x9a, 0x71, 0xa1, 0x15, 0xaa, 0xa4, 0x08, + 0x94, 0xfe, 0x18, 0x62, 0x65, 0x72, 0xcd, 0x52, 0xb3, 0xa1, + 0x04, 0xe5, 0xcd, 0xde, 0xb5, 0x8c, 0x3f, 0xc2, 0x1e, 0x74, + 0x04, 0x63, 0x13, 0x86, 0xb5, 0x44, 0x34, 0x83, 0xfe, 0x3e, + 0xe7, 0x55, 0x94, 0x8a, 0x37, 0xaf, 0xf1, 0x3b, 0x85, 0x87, + 0xd9, 0xd0, 0x4d, 0xd9, 0x65, 0xc9, 0x13, 0xbb, 0x1f, 0xfc, + 0x9d, 0x7d, 0x0b, 0x06, 0x10, 0x37, 0xef, 0x29, 0x1e, 0xa4, + 0x85, 0x03, 0x73, 0x60, 0xa4, 0x01, 0x3c, 0x5f, 0x18, 0x08, + 0xb6, 0x64, 0x57, 0xa7, 0x73, 0x06, 0xb5, 0x3f, 0x79, 0xbe, + 0x5d, 0xf0, 0x4d, 0xe4, 0xcf, 0x26, 0xd3, 0xb7 }, + { 0x64, 0x85, 0x52, 0x4c, 0x0c, 0xdc, 0xc4, 0xbc, 0xfd, 0x26, + 0x1c, 0x83, 0x2a, 0x84, 0x95, 0xab, 0x38, 0x64, 0x6b, 0x32, + 0xe7, 0xac, 0x0a, 0x06, 0x9a, 0x87, 0x39, 0x3f, 0x5b, 0x6f, + 0x55, 0x57, 0x3c, 0x8e, 0x1d, 0xb2, 0xda, 0x0a, 0x55, 0x68, + 0xcb, 0x1f, 0xbc, 0x54, 0xf3, 0x5e, 0x1a, 0x88, 0xcf, 0xcb, + 0x6e, 0xae, 0x4f, 0xdc, 0x3f, 0x7f, 0xfe, 0x59, 0x0d, 0xfe, + 0x03, 0x6c, 0x03, 0x57, 0x90, 0x38, 0xf9, 0x5d, 0x2f, 0xbe, + 0xb5, 0x4c, 0x6d, 0xc7, 0xfc, 0x7c, 0x26, 0xd5, 0x5e, 0xf5, + 0x97, 0x82, 0xe9, 0xe4, 0x93, 0x82, 0x54, 0x7a, 0xb1, 0x65, + 0x4d, 0x17, 0x1a, 0xf9, 0x9c, 0x15, 0x18, 0x77, 0xe2, 0xb0, + 0x26, 0xb1, 0xe8, 0x5b, 0x38, 0xdc, 0xd6, 0x30, 0x74, 0xce, + 0x15, 0xb8, 0x03, 0xad, 0x24, 0x77, 0x56, 0x67, 0x61, 0x66, + 0xb8, 0x7f, 0x03, 0xe5, 0x3e, 0xd9, 0xf1, 0xaf }, + { 0x1f, 0x76, 0xf3, 0xf2, 0xf2, 0x34, 0x56, 0x3c, 0xa4, 0x06, + 0x1c, 0x7a, 0x2d, 0xf8, 0xb4, 0x49, 0x65, 0x46, 0xa6, 0x0c, + 0x00, 0xa3, 0x3d, 0x80, 0x24, 0x07, 0x8b, 0xac, 0xfa, 0x38, + 0x3f, 0x09, 0xa6, 0x50, 0xa8, 0xf5, 0x63, 0x2d, 0x28, 0xb2, + 0x32, 0x75, 0x8d, 0x24, 0x57, 0x4b, 0x99, 0x97, 0x13, 0x5c, + 0x44, 0x37, 0x19, 0x81, 0x18, 0x2d, 0x5d, 0x51, 0x81, 0xd5, + 0xb9, 0x14, 0xbe, 0x7c, 0x70, 0x0b, 0x19, 0x03, 0x57, 0x0c, + 0xbb, 0x5b, 0x92, 0x41, 0x1f, 0xeb, 0x91, 0x7b, 0x1e, 0x7a, + 0xb9, 0xf0, 0x76, 0x4d, 0x49, 0xa0, 0x1f, 0x05, 0x38, 0x18, + 0x6a, 0xe9, 0xd2, 0xa1, 0x82, 0xcb, 0x23, 0x37, 0x88, 0x3a, + 0xba, 0x5d, 0xbd, 0x93, 0x88, 0x42, 0x27, 0xf0, 0x89, 0xaf, + 0xf7, 0x42, 0x2a, 0xa0, 0x3f, 0xba, 0x35, 0xa6, 0x42, 0x8a, + 0x1a, 0xbf, 0xb3, 0xe2, 0xc4, 0xa6, 0xff, 0x2a }, + { 0x04, 0x92, 0x4f, 0xfb, 0x3d, 0x10, 0x8e, 0x05, 0xd0, 0xf3, + 0x67, 0xbb, 0x04, 0x9e, 0xa7, 0x26, 0xc0, 0x28, 0xca, 0x94, + 0x4e, 0xd2, 0xa5, 0x38, 0xfd, 0x9f, 0xc3, 0x3c, 0x04, 0xed, + 0x89, 0x9d, 0x3c, 0x25, 0x62, 0xaf, 0xf1, 0xd4, 0x99, 0x5a, + 0xaf, 0x92, 0xa4, 0xcc, 0xdc, 0x84, 0xbc, 0x92, 0x3a, 0x6f, + 0x93, 0xdd, 0x18, 0x12, 0xac, 0xb7, 0x7f, 0x87, 0x80, 0x26, + 0x2e, 0xe5, 0xfd, 0xe8, 0xa9, 0x8a, 0x5a, 0x8c, 0x9b, 0xb9, + 0x44, 0x3a, 0xb2, 0x7b, 0xf6, 0x93, 0x11, 0x6b, 0x74, 0x88, + 0xa9, 0x9f, 0x29, 0x15, 0x3a, 0xdc, 0xe7, 0x1e, 0xf8, 0x31, + 0x46, 0x4f, 0x7d, 0x0a, 0xfa, 0x48, 0x85, 0x76, 0x1f, 0x41, + 0xed, 0x56, 0xba, 0x82, 0x35, 0xf3, 0x11, 0x7b, 0x5f, 0x6d, + 0xb2, 0xdf, 0x79, 0x07, 0x05, 0x56, 0x1f, 0x69, 0xc8, 0x7a, + 0x9a, 0xa2, 0xc1, 0x43, 0x44, 0xc4, 0x36, 0xb0 }, + { 0x4d, 0xfc, 0xe8, 0x09, 0xc3, 0x80, 0xae, 0x35, 0x08, 0xcd, + 0x84, 0x9c, 0xc1, 0x46, 0x84, 0x26, 0x58, 0xa8, 0x2b, 0x76, + 0x9f, 0x14, 0x27, 0x99, 0x87, 0x80, 0xa7, 0x84, 0xf3, 0xc5, + 0x3b, 0xce, 0xda, 0xd9, 0xe1, 0x82, 0x90, 0x62, 0xfa, 0x49, + 0xb4, 0x0b, 0x07, 0x2e, 0x25, 0x07, 0x26, 0x61, 0x79, 0xa7, + 0xb2, 0xcb, 0x15, 0x08, 0x27, 0x2a, 0xc9, 0x7e, 0x24, 0xa3, + 0x92, 0x5e, 0x5f, 0x4e, 0xf8, 0xa0, 0xdf, 0x66, 0xe0, 0x12, + 0x90, 0xd3, 0x4a, 0xe8, 0xb7, 0xd4, 0x20, 0x99, 0x1b, 0x8c, + 0x4b, 0x8e, 0xbb, 0x8e, 0x14, 0xd7, 0xe9, 0x5b, 0x76, 0x73, + 0x91, 0xc0, 0x41, 0xd6, 0xe1, 0x8e, 0x42, 0x4e, 0x20, 0x64, + 0x6e, 0xbe, 0x55, 0x7b, 0xe6, 0x1f, 0xd3, 0x2b, 0x5e, 0x1c, + 0x69, 0x77, 0xd3, 0xb3, 0x30, 0x25, 0xe2, 0xea, 0xe4, 0x8c, + 0x06, 0x54, 0x8e, 0x3d, 0xc6, 0x73, 0x56, 0x2f }, + { 0x0d, 0x07, 0x59, 0x08, 0xb8, 0xa0, 0x68, 0x02, 0xdc, 0x7d, + 0xaf, 0xf8, 0x93, 0x39, 0xbd, 0x23, 0xc5, 0x62, 0x59, 0x5d, + 0xe4, 0x28, 0xa4, 0x08, 0x59, 0xe9, 0xe8, 0x1d, 0xe2, 0x15, + 0x3c, 0x22, 0x24, 0xa5, 0x71, 0x53, 0x9f, 0x3a, 0x53, 0x2f, + 0x30, 0x7f, 0xd7, 0xd8, 0x47, 0xd0, 0x12, 0x28, 0x7f, 0xce, + 0xcb, 0x04, 0x5c, 0x4e, 0xd9, 0xba, 0xf1, 0x73, 0xdc, 0x2e, + 0x81, 0xdc, 0x56, 0xb3, 0x1e, 0x10, 0xf1, 0x39, 0xd1, 0x5c, + 0x8d, 0x8a, 0x83, 0xfa, 0x8c, 0xc5, 0xca, 0x91, 0x6e, 0x7c, + 0xd6, 0x89, 0x13, 0x82, 0x45, 0xf0, 0xff, 0x47, 0x4c, 0x65, + 0x26, 0x23, 0x55, 0x4a, 0xdf, 0x3c, 0x34, 0x10, 0x2c, 0x26, + 0xbb, 0x2d, 0x1b, 0x2b, 0x10, 0xcc, 0x60, 0x0b, 0xe2, 0x7d, + 0x02, 0x63, 0xd5, 0x2d, 0xa0, 0x15, 0x97, 0x79, 0x30, 0xdd, + 0x45, 0x06, 0x9c, 0xb2, 0xd5, 0x27, 0xb7, 0x80 }, + { 0x24, 0xfa, 0x96, 0x1c, 0x2f, 0x08, 0x53, 0x5a, 0xf2, 0xcd, + 0xe2, 0x15, 0xa4, 0x36, 0x0d, 0xfe, 0xfb, 0xee, 0xd7, 0xed, + 0x70, 0x0c, 0x11, 0x51, 0x28, 0x3f, 0x74, 0x4d, 0x39, 0x3f, + 0x2e, 0x2a, 0xb6, 0x86, 0x12, 0xb9, 0xf0, 0x49, 0x28, 0xe9, + 0xf5, 0xda, 0xfc, 0xec, 0x52, 0x61, 0x17, 0xe5, 0xef, 0x0d, + 0x22, 0x44, 0x1c, 0xfc, 0xbc, 0x52, 0x88, 0x3d, 0x0b, 0xb5, + 0xa8, 0xd6, 0x4e, 0xf6, 0x39, 0x2f, 0x28, 0x96, 0x27, 0x26, + 0x95, 0xbe, 0x01, 0x48, 0xcf, 0x1c, 0x79, 0x10, 0xc6, 0x82, + 0x5c, 0x05, 0xc2, 0xf5, 0x6d, 0xca, 0x36, 0x15, 0x83, 0xb9, + 0x60, 0x21, 0xf6, 0x22, 0xda, 0x0d, 0x1f, 0x02, 0xa2, 0xe4, + 0x85, 0x59, 0xf8, 0x51, 0x88, 0xc0, 0xd2, 0x61, 0x59, 0xca, + 0x41, 0x3b, 0x88, 0xfc, 0xd2, 0x4f, 0xbe, 0x99, 0xb2, 0xe5, + 0x87, 0x0a, 0xf2, 0xa7, 0xde, 0x08, 0x5f, 0x2a }, + { 0x37, 0x1c, 0xc2, 0x3d, 0xfc, 0x4f, 0x01, 0x14, 0x94, 0xd7, + 0xa0, 0x3d, 0x4a, 0x6f, 0xb6, 0xe1, 0x20, 0x1f, 0x61, 0xd1, + 0x77, 0x52, 0xfa, 0x60, 0x8e, 0xff, 0x77, 0xe3, 0x75, 0x56, + 0x03, 0xf3, 0xf6, 0x35, 0xb1, 0xfc, 0x8f, 0x4d, 0x7d, 0x4e, + 0x5e, 0x1b, 0x8b, 0x7f, 0xe5, 0x0e, 0xe1, 0x73, 0x8c, 0xeb, + 0x75, 0x9f, 0x39, 0xad, 0x43, 0xab, 0x27, 0x3e, 0x1c, 0x8f, + 0x41, 0x95, 0x01, 0x58, 0xc0, 0x32, 0x14, 0xe9, 0xcc, 0x94, + 0x2f, 0x9e, 0x5a, 0x57, 0xf4, 0x86, 0xc9, 0x89, 0x51, 0x45, + 0xba, 0xb4, 0x6a, 0xf4, 0xd6, 0xc2, 0x7d, 0x12, 0x18, 0xb1, + 0x91, 0xdf, 0xcc, 0x89, 0xa0, 0x60, 0x22, 0x84, 0xf3, 0x45, + 0x68, 0x96, 0x43, 0xdb, 0x17, 0x4d, 0xaa, 0x90, 0x6e, 0x82, + 0xd5, 0x44, 0x64, 0x30, 0x57, 0xd8, 0xfb, 0xd9, 0x03, 0x26, + 0x07, 0x67, 0xdb, 0x3f, 0x61, 0x6d, 0xf7, 0xf6 }, + { 0x92, 0xb6, 0xbc, 0xa0, 0x0c, 0x80, 0xfb, 0x7f, 0x3e, 0x60, + 0x2e, 0x4f, 0xc9, 0xf4, 0xd7, 0x8f, 0x33, 0x0f, 0x6a, 0x7a, + 0xf1, 0xbc, 0x13, 0xe8, 0x03, 0xc2, 0xc0, 0xe8, 0x5b, 0xa6, + 0xe6, 0xc6, 0x06, 0xf6, 0xa5, 0x8d, 0x76, 0x40, 0xc3, 0x0e, + 0x70, 0xd9, 0x7d, 0x07, 0x26, 0xdd, 0xe2, 0x4a, 0x45, 0x69, + 0x7e, 0x91, 0xe8, 0x7d, 0x34, 0x74, 0x40, 0xa4, 0x94, 0xd3, + 0x3a, 0x80, 0x20, 0x38, 0x3f, 0x9a, 0x6d, 0x78, 0x99, 0xcb, + 0x39, 0x53, 0x12, 0x80, 0xf1, 0x56, 0xe0, 0x02, 0x40, 0xf2, + 0x88, 0x36, 0xcd, 0x08, 0xdc, 0x4c, 0x80, 0x7b, 0xdc, 0x4f, + 0x7e, 0x36, 0x08, 0x10, 0x01, 0x27, 0xcc, 0x28, 0xc1, 0x64, + 0x6f, 0x57, 0x64, 0x2f, 0x77, 0xa8, 0x92, 0x02, 0xf6, 0x50, + 0xb3, 0x1b, 0x6d, 0x19, 0x6e, 0xbf, 0x36, 0x4d, 0x9c, 0x06, + 0x28, 0x9b, 0x11, 0x5d, 0xda, 0x90, 0xc3, 0x51 }, + { 0x71, 0xff, 0x62, 0xc9, 0x4f, 0x02, 0xf8, 0x9d, 0xe7, 0xdb, + 0x4b, 0x98, 0xcf, 0x33, 0x87, 0x1c, 0x21, 0x5a, 0xd8, 0x30, + 0x1f, 0x27, 0x7e, 0x31, 0x9a, 0xaf, 0x6e, 0x67, 0x79, 0x0e, + 0x30, 0x88, 0xd7, 0xec, 0x5e, 0xda, 0xa3, 0xb6, 0x27, 0x59, + 0xf4, 0x01, 0x41, 0xb8, 0x3f, 0xd5, 0x8f, 0x65, 0xfe, 0x2b, + 0xae, 0x08, 0x4a, 0x9b, 0x63, 0xb6, 0xa4, 0xe1, 0xd8, 0x72, + 0x5c, 0xde, 0xbb, 0x70, 0xe8, 0xf0, 0x9e, 0x7e, 0x00, 0xf0, + 0xc0, 0xf9, 0xcd, 0x47, 0x2a, 0xfa, 0xea, 0x3b, 0x91, 0x53, + 0xed, 0xfb, 0x7b, 0xaa, 0x4a, 0x92, 0xca, 0x27, 0x0b, 0xee, + 0x9c, 0xee, 0x1b, 0xb1, 0x41, 0x3f, 0x6b, 0x4e, 0x32, 0xad, + 0xa7, 0xcc, 0x19, 0x54, 0x81, 0xc3, 0x29, 0xc4, 0x92, 0xb0, + 0xa3, 0x30, 0x0e, 0x82, 0x57, 0x12, 0xb8, 0xb1, 0x6f, 0x12, + 0x2e, 0x3d, 0x5c, 0x83, 0x5f, 0x00, 0x82, 0x2e }, + { 0x40, 0xfd, 0x47, 0xe7, 0x5f, 0x95, 0x82, 0x73, 0xe6, 0xa8, + 0x3f, 0xe9, 0xdf, 0x1b, 0xba, 0x69, 0x6c, 0x18, 0xb3, 0x50, + 0x84, 0xef, 0x6b, 0x4c, 0xf1, 0xe1, 0x9f, 0xc6, 0xfd, 0xc3, + 0x7d, 0xda, 0x38, 0xdb, 0xb6, 0x3e, 0xa3, 0xd2, 0x66, 0x1c, + 0xd3, 0xaa, 0x0f, 0x7d, 0xd2, 0x22, 0x64, 0x32, 0xed, 0xde, + 0x69, 0x2a, 0x72, 0xcc, 0xd1, 0xf0, 0x92, 0xed, 0xc4, 0xb1, + 0xb6, 0xd4, 0xf6, 0x8a, 0x75, 0x3f, 0x28, 0xa0, 0x33, 0xaf, + 0x53, 0x6b, 0x8b, 0x83, 0x2d, 0x46, 0xf5, 0x98, 0x28, 0xc1, + 0xe1, 0xe9, 0xf9, 0x90, 0xca, 0x04, 0x41, 0x80, 0xa4, 0xc5, + 0x98, 0xe1, 0x09, 0xe6, 0x50, 0x33, 0x83, 0xf5, 0xef, 0x9f, + 0xff, 0xf1, 0x20, 0xa5, 0x3b, 0x11, 0xa8, 0xa5, 0xf1, 0xcd, + 0x65, 0x78, 0xe2, 0xee, 0x4a, 0xcd, 0x5e, 0xbc, 0x71, 0xe6, + 0xaa, 0x4c, 0x71, 0x02, 0x2a, 0x4a, 0x84, 0xd9 }, + { 0x5b, 0x1c, 0x11, 0x57, 0xe6, 0x39, 0x33, 0x8c, 0x0b, 0x33, + 0x4d, 0x98, 0xdf, 0xfb, 0xe2, 0x86, 0x68, 0xd8, 0x21, 0x11, + 0xd8, 0x54, 0xa6, 0x95, 0x18, 0xb9, 0xfa, 0xb3, 0xf9, 0xb6, + 0xae, 0x43, 0x1a, 0xc1, 0x6a, 0x26, 0x1f, 0x57, 0x8a, 0xa3, + 0x20, 0xcf, 0x0b, 0x97, 0xf7, 0x30, 0x08, 0x4d, 0xe5, 0x2c, + 0x01, 0x39, 0xec, 0x6c, 0x21, 0x74, 0x14, 0xd6, 0x8a, 0x08, + 0x41, 0x13, 0x42, 0x5c, 0x2d, 0x85, 0xd4, 0x52, 0x1b, 0x46, + 0x83, 0x37, 0x93, 0x38, 0x9c, 0x05, 0x41, 0x71, 0xfb, 0x69, + 0x95, 0xd5, 0xc9, 0x6e, 0xb5, 0xa2, 0x19, 0x50, 0xcf, 0xc2, + 0x21, 0x4a, 0x8a, 0xc8, 0xff, 0x88, 0x69, 0xbe, 0xeb, 0xa1, + 0x2e, 0xb6, 0xef, 0xc2, 0xdd, 0x9e, 0xc8, 0x8e, 0x69, 0x86, + 0x25, 0x48, 0x6d, 0xbb, 0xfc, 0x1e, 0xea, 0xb6, 0xf2, 0xfb, + 0x5b, 0x88, 0xb7, 0x46, 0x26, 0x71, 0x40, 0xa4 }, + { 0x96, 0x3a, 0xb8, 0x3a, 0xa7, 0x56, 0xee, 0xf4, 0x84, 0xde, + 0x9c, 0xb8, 0x33, 0xe5, 0x0a, 0xb3, 0xce, 0x16, 0x48, 0x01, + 0x6e, 0x1c, 0x63, 0x44, 0xe4, 0xd3, 0xfc, 0x44, 0xda, 0x0f, + 0xd5, 0x91, 0xb6, 0xad, 0x1c, 0xf4, 0x78, 0x5e, 0x67, 0xa3, + 0x0a, 0xc3, 0xbd, 0x66, 0xc7, 0x79, 0x1a, 0x48, 0x1f, 0x91, + 0x65, 0x1c, 0x7d, 0xa1, 0x2c, 0x10, 0x4f, 0xd1, 0xac, 0xe6, + 0x81, 0xc6, 0x5f, 0x57, 0xab, 0x18, 0xd8, 0x30, 0xea, 0x6e, + 0xdc, 0xa8, 0x28, 0x09, 0xc7, 0x64, 0xa4, 0xf3, 0x2c, 0x9d, + 0x16, 0xe7, 0x06, 0xe7, 0x05, 0x6d, 0xcf, 0x94, 0xcb, 0x2d, + 0x66, 0xa3, 0x63, 0x24, 0x20, 0xdc, 0x31, 0x6d, 0xc6, 0x5f, + 0xcb, 0x54, 0xdc, 0xe4, 0xf4, 0x2b, 0xa3, 0xc5, 0xfe, 0x69, + 0x4c, 0x73, 0x8d, 0xc6, 0x4e, 0xd2, 0x02, 0xfc, 0x92, 0xc2, + 0x90, 0xed, 0xaa, 0xb1, 0x72, 0xb6, 0xbb, 0x8f }, + { 0x44, 0x34, 0x80, 0xfc, 0xbe, 0x45, 0xc5, 0x58, 0x6b, 0x82, + 0xb8, 0x99, 0x07, 0x6b, 0x98, 0x84, 0xc8, 0x9b, 0x91, 0xfd, + 0x83, 0xc1, 0xdc, 0x07, 0x66, 0x59, 0x4a, 0xaa, 0x83, 0x73, + 0x82, 0xda, 0x01, 0x1b, 0x25, 0x21, 0xa6, 0x0c, 0xfb, 0x6a, + 0x03, 0x7d, 0x13, 0x21, 0xb9, 0x9f, 0x4e, 0x3b, 0x8e, 0x55, + 0x09, 0x69, 0x7d, 0x7d, 0x95, 0x78, 0x81, 0x89, 0xe8, 0xb0, + 0x7c, 0x20, 0xbf, 0xd8, 0x36, 0x45, 0xbc, 0xb6, 0x33, 0x19, + 0xad, 0xac, 0xfe, 0x8c, 0x39, 0x0d, 0xbb, 0xa7, 0x55, 0x70, + 0x71, 0x00, 0x6f, 0x29, 0x04, 0x05, 0x7d, 0xce, 0x3f, 0xee, + 0x20, 0x4d, 0xf5, 0x50, 0x71, 0xbc, 0x84, 0xe5, 0x5b, 0x3e, + 0xe7, 0xc9, 0x9e, 0x15, 0xd1, 0x6e, 0x7d, 0x58, 0x8a, 0x3c, + 0x35, 0x64, 0x96, 0x56, 0x88, 0x15, 0x5c, 0xfe, 0x45, 0xfe, + 0x94, 0x4b, 0x47, 0xd8, 0xdf, 0x4e, 0xa5, 0xa3 }, + { 0x97, 0x11, 0x8a, 0x88, 0xcf, 0xfa, 0xa7, 0xeb, 0xab, 0x6d, + 0x1e, 0xb0, 0xa1, 0x70, 0x03, 0x71, 0xb9, 0xd3, 0x55, 0xcf, + 0x8e, 0xb0, 0x3e, 0x6d, 0x9b, 0x6c, 0x22, 0x4b, 0xf6, 0xd7, + 0x2b, 0x58, 0xd5, 0xb1, 0x38, 0xd8, 0xc4, 0x42, 0xbe, 0x82, + 0xc2, 0xda, 0xda, 0x9e, 0x06, 0x5a, 0x8e, 0xe9, 0x38, 0x14, + 0x90, 0x71, 0xd3, 0x16, 0x05, 0xac, 0xdb, 0xef, 0x7c, 0x00, + 0xc1, 0x17, 0xa7, 0x8d, 0xa3, 0x86, 0x89, 0x17, 0xe7, 0x21, + 0xba, 0x7b, 0x24, 0x12, 0x84, 0xed, 0x24, 0x57, 0x2a, 0xc6, + 0xc2, 0xa9, 0xd0, 0xf2, 0xfb, 0x43, 0xa8, 0x6a, 0xb2, 0x29, + 0x65, 0x37, 0xfb, 0xfe, 0x9b, 0x77, 0xef, 0x3e, 0x6b, 0x31, + 0xd6, 0xf9, 0x61, 0x52, 0x42, 0xe2, 0xd0, 0xe4, 0x0f, 0xa5, + 0x47, 0x87, 0x4a, 0xec, 0x4f, 0x2e, 0x3e, 0x85, 0x7a, 0x7a, + 0xf8, 0xff, 0xff, 0xb4, 0x91, 0x14, 0x22, 0x1a }, + { 0x17, 0xc0, 0x77, 0x8d, 0x4b, 0x71, 0xfa, 0x82, 0xd5, 0x6a, + 0x17, 0x7a, 0xa5, 0x73, 0x38, 0x7c, 0x30, 0xb5, 0x40, 0x5a, + 0x27, 0x0f, 0x45, 0xf6, 0x55, 0x4f, 0xe7, 0x63, 0xfe, 0x52, + 0xea, 0xe7, 0xdb, 0xa2, 0xba, 0x26, 0x85, 0xc3, 0xfc, 0x72, + 0xe4, 0xe7, 0x62, 0x99, 0x8a, 0x02, 0x23, 0xa5, 0xa4, 0x2c, + 0x02, 0xf4, 0x10, 0x2f, 0xee, 0x2a, 0xa2, 0x73, 0x00, 0x83, + 0x3b, 0x06, 0xef, 0xa5, 0x5b, 0xa7, 0x0a, 0x49, 0x8a, 0x88, + 0x2f, 0xf2, 0xb8, 0x58, 0x63, 0x7b, 0x14, 0xb3, 0xe5, 0x01, + 0xa8, 0xb0, 0xd8, 0x20, 0x3e, 0xf2, 0xa1, 0xc4, 0x9d, 0x35, + 0x2f, 0xbb, 0x0f, 0xbf, 0xb7, 0x81, 0xe7, 0x79, 0xa3, 0xca, + 0xa0, 0x20, 0x70, 0xb4, 0x24, 0xe0, 0xdd, 0x81, 0x04, 0x77, + 0x4f, 0xbf, 0x80, 0x83, 0xc8, 0x1b, 0xa9, 0x3a, 0x68, 0x66, + 0xbf, 0x9c, 0x59, 0xa2, 0xcd, 0xec, 0xb5, 0xd8 }, + { 0x12, 0x19, 0xd5, 0xc8, 0x57, 0x1f, 0xe4, 0xc6, 0xd6, 0xce, + 0x84, 0xe1, 0xa4, 0x52, 0xed, 0x66, 0x9f, 0xfe, 0xc3, 0xa1, + 0xe2, 0xbf, 0x5d, 0x84, 0x6d, 0xd1, 0x2a, 0xe0, 0x1a, 0xd2, + 0x3a, 0x38, 0x5a, 0x8d, 0xb7, 0x9b, 0xa9, 0x6c, 0xc9, 0xa3, + 0x72, 0x3f, 0x43, 0x09, 0xa0, 0xff, 0xce, 0x0e, 0x7a, 0x0d, + 0x91, 0x57, 0x37, 0x85, 0x9a, 0x6a, 0x16, 0xe1, 0x2c, 0x45, + 0xe8, 0x6d, 0x5f, 0xd5, 0xf2, 0x24, 0x95, 0x2b, 0x18, 0x69, + 0x1c, 0x4a, 0x76, 0x8b, 0xca, 0x70, 0x05, 0x28, 0xbd, 0x40, + 0xa1, 0xa1, 0xde, 0xcd, 0x96, 0x7a, 0x2e, 0xca, 0x8c, 0x3f, + 0xa1, 0x77, 0xf5, 0xb0, 0x43, 0x77, 0x40, 0xfa, 0x45, 0x18, + 0xba, 0x09, 0xf3, 0xc4, 0xa2, 0xf5, 0xac, 0x9d, 0x9e, 0xbb, + 0xa9, 0x78, 0xc9, 0x88, 0x4e, 0x56, 0x65, 0x6e, 0xc5, 0x72, + 0x0e, 0x6d, 0xff, 0x1d, 0x27, 0x35, 0xe3, 0x7b }, + { 0x2c, 0x8d, 0x7a, 0xb2, 0xd6, 0x57, 0xf2, 0x30, 0x13, 0x14, + 0xa8, 0x2f, 0x7e, 0x62, 0x6f, 0x42, 0x70, 0xb5, 0x7e, 0x1f, + 0x0b, 0xe2, 0x9e, 0xce, 0x76, 0xf9, 0x28, 0x39, 0x3a, 0x07, + 0x93, 0xf9, 0x3c, 0x29, 0x6b, 0x0d, 0xd2, 0x34, 0xa0, 0x7a, + 0x28, 0x65, 0xdd, 0x61, 0xcb, 0xa5, 0x7c, 0xc8, 0x43, 0x08, + 0xf7, 0x62, 0xa0, 0x4e, 0x6b, 0x87, 0x21, 0x6a, 0x61, 0xd0, + 0x7f, 0xac, 0x67, 0xc6, 0x95, 0xcd, 0x99, 0x90, 0xeb, 0x24, + 0xc3, 0x88, 0x14, 0x84, 0xbd, 0xb1, 0x8b, 0xac, 0x11, 0xd6, + 0x51, 0xd3, 0xd0, 0x75, 0xa9, 0x74, 0x3e, 0x6b, 0xff, 0xff, + 0xca, 0xd8, 0xe5, 0x80, 0xbd, 0xbd, 0x0f, 0x82, 0xb0, 0xed, + 0x8d, 0x15, 0x02, 0x74, 0xe6, 0x12, 0x7e, 0x51, 0x57, 0xbb, + 0x09, 0x09, 0x3a, 0x3a, 0xb3, 0x9d, 0x2f, 0x03, 0xe7, 0x73, + 0x43, 0xea, 0xa6, 0x7f, 0x26, 0x29, 0x69, 0xeb }, + { 0x22, 0x99, 0xd2, 0x77, 0x4b, 0x09, 0xd9, 0x58, 0x96, 0xeb, + 0x70, 0x5a, 0x1b, 0x40, 0x4c, 0x44, 0x59, 0x60, 0x13, 0xdb, + 0x94, 0xa2, 0x0b, 0x11, 0xb0, 0xfd, 0x1c, 0xd5, 0xd1, 0xd3, + 0x98, 0xfb, 0xd4, 0x42, 0x8b, 0x2e, 0xed, 0x8c, 0xd5, 0x9a, + 0x74, 0x74, 0xbf, 0x0d, 0x77, 0xf8, 0x4a, 0x34, 0x6c, 0x98, + 0xd0, 0x5d, 0xc6, 0x7d, 0x6a, 0x8a, 0x69, 0xce, 0xd5, 0xaa, + 0xac, 0xa2, 0xd7, 0xef, 0xda, 0x89, 0x78, 0xbd, 0x29, 0xe3, + 0x7f, 0xeb, 0x11, 0x8a, 0xab, 0x77, 0x5a, 0x4d, 0xf3, 0x81, + 0x99, 0xda, 0xe4, 0x69, 0xd4, 0x5e, 0xbb, 0xa7, 0x8c, 0x4b, + 0x14, 0xdd, 0x9d, 0xf6, 0x43, 0x6a, 0x22, 0x9f, 0x89, 0xf5, + 0x8d, 0xd0, 0x96, 0x3f, 0x63, 0xe6, 0x65, 0xd8, 0x13, 0x10, + 0x10, 0x8d, 0xdf, 0x51, 0xea, 0xa5, 0x6e, 0xf8, 0x3b, 0x44, + 0x67, 0xcf, 0x58, 0x92, 0x08, 0x25, 0xe4, 0xd6 }, + { 0x21, 0xac, 0x67, 0x79, 0x19, 0x36, 0x61, 0x8e, 0xaf, 0x9f, + 0xfa, 0x57, 0x27, 0xb4, 0x6c, 0x26, 0x97, 0x1b, 0x73, 0x6f, + 0x52, 0xca, 0x0d, 0x50, 0x71, 0xc4, 0x41, 0x35, 0xf0, 0xb6, + 0x59, 0x34, 0xc7, 0xad, 0x1d, 0x2b, 0x82, 0x1c, 0x44, 0x6b, + 0xe8, 0xd3, 0x8b, 0x48, 0x25, 0x31, 0x7e, 0x95, 0x0c, 0xf5, + 0x62, 0x91, 0xac, 0xe0, 0x07, 0x4e, 0x69, 0x25, 0xb1, 0xb3, + 0x04, 0x2d, 0xf4, 0x8e, 0x33, 0x6f, 0xd1, 0x3d, 0x91, 0x6e, + 0xe9, 0x8b, 0xed, 0x5d, 0x51, 0x89, 0xbe, 0xc4, 0xf8, 0xa0, + 0xdc, 0x96, 0x3f, 0x2d, 0x41, 0x1d, 0xb5, 0xf6, 0xa4, 0xb2, + 0x80, 0xcd, 0xe5, 0x3c, 0x01, 0xfd, 0x40, 0x5a, 0xe2, 0x87, + 0x8f, 0xcd, 0xc6, 0x8c, 0x58, 0x66, 0xd8, 0xe1, 0x3e, 0x9f, + 0x1d, 0xb2, 0xac, 0x19, 0x8f, 0x1e, 0xbf, 0x6d, 0xd3, 0x1e, + 0x5b, 0x9c, 0xd5, 0x8d, 0xc6, 0x43, 0x97, 0xe6 }, + { 0x0e, 0x8e, 0xc1, 0xe7, 0x0e, 0x62, 0xd9, 0xd8, 0x66, 0x3d, + 0x88, 0xd6, 0x24, 0x48, 0x3a, 0x56, 0x01, 0x5f, 0x7e, 0x78, + 0x92, 0xc2, 0xe1, 0xbb, 0x30, 0x46, 0x3e, 0xe4, 0xe7, 0xf7, + 0xbe, 0x9f, 0x61, 0x22, 0x11, 0xdb, 0xee, 0x01, 0x64, 0xcd, + 0xc3, 0xf1, 0xc4, 0x31, 0xb2, 0x61, 0xca, 0x1c, 0xff, 0xa3, + 0x49, 0x6a, 0x3e, 0x60, 0x2f, 0x74, 0xfc, 0x0e, 0x1a, 0x45, + 0x61, 0x5a, 0x43, 0x89, 0x4f, 0x39, 0x89, 0x97, 0x0f, 0xf2, + 0x7b, 0x9c, 0x70, 0x97, 0x8a, 0x59, 0x03, 0x7c, 0x19, 0xb8, + 0x13, 0xd6, 0xf3, 0x75, 0xa0, 0xf2, 0x28, 0x14, 0xdf, 0xc1, + 0x9b, 0x09, 0xb3, 0x3c, 0x36, 0x25, 0x6f, 0xcd, 0x42, 0x36, + 0x38, 0x07, 0xb7, 0xd3, 0x49, 0x20, 0x33, 0xf8, 0x4d, 0xf5, + 0xd4, 0xb4, 0x12, 0x72, 0x24, 0x73, 0x97, 0xbd, 0xfc, 0x18, + 0xab, 0x42, 0x0e, 0x3f, 0x2d, 0x7f, 0xbc, 0xd2 }, + { 0x65, 0x3a, 0x79, 0x5f, 0x5d, 0x10, 0x36, 0x35, 0xd8, 0x50, + 0xc1, 0xc0, 0x1b, 0x6b, 0x73, 0xfd, 0xe2, 0xa2, 0xbd, 0x12, + 0xf4, 0xb1, 0x3e, 0x5b, 0x76, 0xaa, 0x0f, 0x56, 0x86, 0x4d, + 0x83, 0x26, 0x58, 0x19, 0x2c, 0x86, 0xa2, 0x94, 0xa3, 0x25, + 0x67, 0xb1, 0x21, 0x7e, 0xd0, 0x77, 0x36, 0x66, 0xe1, 0x84, + 0x7a, 0x4c, 0x49, 0x5d, 0x83, 0x25, 0x78, 0x30, 0xae, 0x28, + 0x9b, 0x23, 0x7e, 0x91, 0x59, 0xef, 0x6c, 0xdd, 0xe0, 0xb9, + 0x14, 0x53, 0x42, 0xee, 0x03, 0x82, 0x4c, 0x67, 0xa7, 0x71, + 0xb7, 0x4b, 0x3d, 0xe7, 0x95, 0x9c, 0x48, 0xe3, 0x30, 0x78, + 0x5b, 0xd4, 0x88, 0xd2, 0x21, 0xa1, 0x31, 0x6d, 0x02, 0x3e, + 0xdd, 0x58, 0xa3, 0x15, 0x90, 0x34, 0x48, 0x20, 0xa5, 0x17, + 0x36, 0x17, 0x99, 0xac, 0x17, 0x5d, 0x66, 0x40, 0x07, 0x1a, + 0xa8, 0x8c, 0xcc, 0x29, 0x8a, 0x08, 0x78, 0xdd }, + { 0x30, 0xdf, 0xc4, 0x7b, 0xd4, 0x44, 0x67, 0x5e, 0x08, 0x3f, + 0x65, 0xa5, 0xfb, 0x9d, 0x79, 0x76, 0x11, 0x18, 0x6d, 0x31, + 0x9a, 0x40, 0xda, 0x4b, 0xd2, 0x89, 0xeb, 0x4f, 0x27, 0xfb, + 0x0f, 0xd1, 0xf9, 0x94, 0xa1, 0x14, 0x7c, 0x6a, 0x42, 0xb1, + 0x46, 0xec, 0xbd, 0x3f, 0x1f, 0xef, 0x20, 0xe9, 0xbd, 0x75, + 0x73, 0x9c, 0xee, 0x7d, 0xaa, 0x26, 0xc9, 0x97, 0xf9, 0x3e, + 0xb2, 0x12, 0x5e, 0x8e, 0x14, 0xf9, 0x70, 0xcb, 0xdb, 0x45, + 0xd7, 0x63, 0x0b, 0x12, 0x83, 0x9a, 0xc5, 0xd1, 0xb1, 0x13, + 0xe2, 0x06, 0xb1, 0xd8, 0x1d, 0xb7, 0x25, 0xc7, 0x3a, 0xa7, + 0x04, 0xde, 0xe2, 0xb1, 0x2d, 0x52, 0xb0, 0xe5, 0x28, 0x8d, + 0x27, 0xf1, 0x31, 0xb5, 0xbc, 0xa7, 0xd7, 0xc3, 0xc9, 0x76, + 0x03, 0xd0, 0xb3, 0x5b, 0x8e, 0x5e, 0x7f, 0xa0, 0x2b, 0x60, + 0xcf, 0xe2, 0x89, 0x85, 0x50, 0xdc, 0xb1, 0x99 }, + { 0x57, 0x2a, 0x59, 0x1f, 0x54, 0xc2, 0x12, 0xcf, 0xe1, 0x6f, + 0xe8, 0x72, 0x39, 0x7f, 0x25, 0x01, 0x15, 0x35, 0xc7, 0xda, + 0xae, 0x0f, 0xe2, 0x18, 0x9a, 0xc5, 0x2a, 0x4d, 0x40, 0x7a, + 0x3a, 0xa0, 0x98, 0x3a, 0xf1, 0x75, 0x25, 0x18, 0x49, 0x39, + 0x5d, 0xa6, 0x9e, 0x0b, 0xeb, 0x1a, 0xe2, 0x89, 0x27, 0x61, + 0x92, 0xbf, 0x07, 0xd7, 0xc3, 0xc8, 0x86, 0xe1, 0x14, 0xa6, + 0x2d, 0xdf, 0x7a, 0xc6, 0x17, 0x07, 0x3c, 0xe6, 0x3e, 0x2f, + 0x69, 0x84, 0xb7, 0xbe, 0x23, 0x36, 0xc4, 0xb7, 0x8e, 0x1c, + 0xa3, 0x51, 0x4b, 0x21, 0x98, 0x83, 0x11, 0x0f, 0xb1, 0xa3, + 0xdf, 0x7a, 0x30, 0x59, 0x06, 0x8e, 0xa2, 0xb9, 0xc2, 0x04, + 0x56, 0xa6, 0xa2, 0x14, 0xab, 0x07, 0x02, 0xdf, 0x8b, 0x53, + 0x35, 0x61, 0x25, 0x02, 0x7e, 0x54, 0xb4, 0xd4, 0xe8, 0x12, + 0xbc, 0xfc, 0x5a, 0xe2, 0x9e, 0xaa, 0xdf, 0xe8 }, + { 0x65, 0xc2, 0xcb, 0xe1, 0xd8, 0xc8, 0x2c, 0x3c, 0x80, 0xc8, + 0x65, 0x53, 0x24, 0x91, 0x9a, 0x4e, 0x12, 0x0c, 0x6f, 0xbc, + 0x6c, 0x8b, 0x19, 0x0e, 0x81, 0x42, 0xdb, 0x5c, 0x90, 0xaf, + 0xd0, 0x7b, 0x6e, 0x3e, 0x49, 0x9d, 0x8d, 0x15, 0x76, 0x7a, + 0x90, 0x2f, 0xe9, 0x29, 0xf9, 0x08, 0xab, 0x43, 0xa3, 0x84, + 0x67, 0xdc, 0xe5, 0x3d, 0x1a, 0xa9, 0x15, 0xbc, 0xf3, 0xc6, + 0x11, 0xcb, 0x8c, 0x31, 0xf1, 0xd3, 0x62, 0x2b, 0x67, 0xf3, + 0x3f, 0x76, 0xb7, 0x05, 0xed, 0x61, 0x3d, 0x67, 0x4f, 0xe5, + 0xbb, 0xa5, 0x97, 0xce, 0xca, 0x03, 0x06, 0xd8, 0x6d, 0x96, + 0x71, 0xc0, 0x2f, 0xed, 0x95, 0x78, 0xbd, 0x3c, 0xbf, 0x9b, + 0xf2, 0x21, 0x26, 0xd4, 0xf9, 0xce, 0xb4, 0xb2, 0x3e, 0xef, + 0xd6, 0x90, 0x3f, 0x05, 0x43, 0x18, 0x32, 0x77, 0x33, 0xbc, + 0x49, 0x66, 0x84, 0x19, 0x09, 0xa5, 0x55, 0x3a }, + { 0x83, 0x14, 0x40, 0xd5, 0x3b, 0xa7, 0x7f, 0x66, 0xd8, 0x05, + 0x50, 0x16, 0x0e, 0x78, 0x88, 0xb9, 0x25, 0x33, 0xad, 0x58, + 0xa0, 0xdc, 0xf4, 0xab, 0x43, 0x53, 0xd7, 0x2e, 0x1a, 0x09, + 0x98, 0x52, 0x46, 0xdb, 0x73, 0x8d, 0xdf, 0xae, 0x7a, 0x1a, + 0x78, 0x3e, 0xff, 0x1b, 0x94, 0xef, 0x7e, 0xd3, 0xa5, 0xc4, + 0xf1, 0xdc, 0x22, 0x9b, 0xd3, 0xde, 0x8c, 0x3c, 0xa3, 0x49, + 0x73, 0xe1, 0xd2, 0xf1, 0x5e, 0x34, 0xe3, 0x00, 0x47, 0x73, + 0x81, 0x83, 0x92, 0xea, 0x15, 0xec, 0x95, 0x01, 0x17, 0x70, + 0x82, 0x9b, 0xc6, 0xb3, 0x41, 0x3f, 0x57, 0x9e, 0xb6, 0x88, + 0x42, 0x77, 0x08, 0x45, 0x2d, 0x44, 0x79, 0xc1, 0x62, 0xe5, + 0x67, 0x9d, 0xd1, 0x58, 0x76, 0x47, 0x2c, 0xf6, 0x6b, 0xa0, + 0xee, 0xd7, 0x27, 0xdc, 0x3b, 0x0a, 0x86, 0xe8, 0x62, 0x45, + 0x68, 0x4c, 0xda, 0x20, 0xa6, 0x60, 0xbb, 0x63 }, + { 0x50, 0x4c, 0x3a, 0x8a, 0x6d, 0x5f, 0x45, 0x66, 0x4a, 0x98, + 0x5a, 0x70, 0xe1, 0x5a, 0x28, 0x15, 0x38, 0x53, 0x99, 0xcd, + 0xbc, 0xf1, 0x19, 0xca, 0x57, 0x39, 0xac, 0x8f, 0x98, 0x5f, + 0xb4, 0x6d, 0xe9, 0x56, 0x63, 0xcc, 0x1b, 0x41, 0x1e, 0x3e, + 0x3c, 0xd1, 0x7f, 0x7f, 0x82, 0x14, 0x7b, 0x71, 0x7e, 0x0c, + 0x7a, 0x3c, 0x64, 0xca, 0xdf, 0xc6, 0x04, 0x88, 0x38, 0x2f, + 0x48, 0x53, 0x6b, 0x3b, 0xc9, 0x97, 0x7d, 0xb5, 0x63, 0x8c, + 0xe1, 0x1a, 0xea, 0x3f, 0xce, 0x98, 0x3d, 0xe0, 0x78, 0xdd, + 0x73, 0x5b, 0x86, 0x0a, 0x10, 0x1e, 0x85, 0x17, 0x92, 0x9d, + 0x7f, 0x66, 0xdf, 0xd2, 0x7a, 0x66, 0xc4, 0x5c, 0x28, 0xe6, + 0x1d, 0x3e, 0x44, 0xf0, 0xe8, 0x97, 0xf3, 0xe8, 0x82, 0x0b, + 0x3c, 0x0d, 0x5d, 0x06, 0x6e, 0x29, 0xd0, 0xfa, 0x46, 0xac, + 0xf4, 0x3e, 0x2e, 0x32, 0xf6, 0x11, 0xb2, 0xda }, + { 0x49, 0x6e, 0x46, 0x99, 0xc7, 0x1d, 0x21, 0xd2, 0xc2, 0x7a, + 0xf0, 0xb1, 0x69, 0xf5, 0x6a, 0xdd, 0x38, 0xca, 0xf7, 0xd0, + 0x77, 0xfd, 0xc5, 0x20, 0xbf, 0x2e, 0xa6, 0xc9, 0xf8, 0x43, + 0x04, 0x22, 0x5e, 0xca, 0xc3, 0xe5, 0x6d, 0xe9, 0x37, 0xdc, + 0x2a, 0xe6, 0x84, 0xde, 0x55, 0x37, 0xb7, 0xda, 0x85, 0xa7, + 0xa9, 0xc3, 0xe6, 0xe2, 0x8e, 0xac, 0xbc, 0x70, 0xb3, 0xce, + 0xa6, 0x96, 0x73, 0xea, 0xb3, 0x5e, 0x56, 0x7e, 0xa6, 0xe8, + 0xa3, 0xbb, 0x4c, 0x23, 0xc6, 0xb6, 0x67, 0x0b, 0x27, 0x02, + 0xa2, 0xdc, 0x00, 0x1d, 0x7e, 0xe8, 0x1e, 0xe1, 0x6a, 0xd3, + 0x89, 0x56, 0xaa, 0xbc, 0xc6, 0x74, 0x29, 0x83, 0x24, 0x30, + 0xe5, 0xa1, 0x29, 0xed, 0x23, 0x4d, 0x24, 0x1c, 0x43, 0x7c, + 0xe2, 0x5f, 0x98, 0x5c, 0xff, 0x38, 0x50, 0x94, 0x74, 0xe3, + 0x00, 0xb5, 0x52, 0x83, 0xb8, 0xfa, 0x53, 0xc7 }, + { 0x13, 0x38, 0x91, 0x73, 0x13, 0x03, 0x7f, 0xe8, 0x4f, 0x2b, + 0x5c, 0xcf, 0xcb, 0x37, 0x44, 0xb5, 0x35, 0x4c, 0xdc, 0xdb, + 0xe5, 0xf0, 0x69, 0x52, 0xc1, 0x4b, 0x21, 0x5e, 0xb0, 0xd6, + 0x86, 0x3a, 0x8b, 0xa0, 0xd9, 0xe9, 0xae, 0xab, 0x51, 0xf9, + 0xd6, 0x7a, 0xac, 0xaf, 0x76, 0x5b, 0xa2, 0x68, 0xce, 0xb4, + 0x0e, 0xdc, 0x95, 0x11, 0x67, 0xb7, 0x97, 0xbf, 0x6a, 0x54, + 0x22, 0x03, 0xd5, 0xc4, 0x5a, 0x21, 0xec, 0xe6, 0x2c, 0xd6, + 0x40, 0xc5, 0xbd, 0x01, 0xfa, 0x86, 0xbb, 0x04, 0x79, 0x3b, + 0xc4, 0x63, 0xbd, 0xa6, 0x17, 0xc0, 0x81, 0xb8, 0x40, 0xbf, + 0xd0, 0x80, 0x81, 0xf3, 0x21, 0x6a, 0xbc, 0x85, 0x97, 0x52, + 0x36, 0x86, 0xbd, 0xcc, 0x65, 0x9b, 0xcf, 0xaf, 0x48, 0x33, + 0xe0, 0x9b, 0xc2, 0xe3, 0x76, 0x84, 0x0e, 0xb2, 0xa6, 0x14, + 0xba, 0x14, 0xfc, 0x82, 0x9f, 0xa9, 0x34, 0x67 }, + { 0x42, 0x2e, 0xb5, 0x73, 0xf3, 0x83, 0x3f, 0xbd, 0x4c, 0x81, + 0x02, 0xb4, 0x6d, 0xa1, 0xf3, 0x45, 0xd2, 0xce, 0xfa, 0x09, + 0x69, 0x5e, 0x3a, 0x02, 0x02, 0xc5, 0x10, 0x4d, 0x4d, 0xea, + 0x47, 0x96, 0x50, 0xf0, 0xc0, 0xa6, 0x04, 0x85, 0xdf, 0xf4, + 0x4b, 0xb2, 0x95, 0x2e, 0x55, 0xfb, 0xdb, 0xac, 0x9e, 0x7a, + 0x9b, 0x46, 0x3b, 0x45, 0xfe, 0xa5, 0xae, 0xc0, 0xfc, 0xb2, + 0x6b, 0xc8, 0xaa, 0x2a, 0x68, 0x07, 0x41, 0x72, 0x54, 0x33, + 0x04, 0xef, 0x0b, 0xc4, 0x93, 0xf9, 0x50, 0xa3, 0x4a, 0x7b, + 0xec, 0xc4, 0xcf, 0xb0, 0x26, 0x09, 0x90, 0xc8, 0xbb, 0x57, + 0x76, 0x2d, 0x38, 0xf3, 0x7e, 0x01, 0x81, 0xe3, 0x4e, 0xb9, + 0xc7, 0xce, 0xa9, 0x5c, 0x4b, 0xcd, 0x41, 0x9f, 0xde, 0x8e, + 0x53, 0x14, 0xfd, 0xac, 0x17, 0xbc, 0x44, 0xae, 0x2a, 0xc6, + 0xee, 0x68, 0x06, 0x40, 0x45, 0x00, 0x3c, 0xd1 }, + { 0x36, 0x85, 0x41, 0xcf, 0x2c, 0x25, 0x25, 0x82, 0xcf, 0xba, + 0x27, 0xd7, 0xa0, 0xda, 0x2d, 0xc6, 0xa9, 0xfb, 0xbb, 0x4c, + 0xb7, 0xfd, 0x2b, 0x05, 0x7d, 0x19, 0xb9, 0xc2, 0x72, 0x79, + 0x99, 0xff, 0x09, 0xfe, 0xbc, 0x9c, 0x74, 0x73, 0x12, 0xe1, + 0x40, 0xf1, 0xc7, 0xe1, 0x66, 0xa3, 0xf2, 0xbf, 0xee, 0x63, + 0xfa, 0x8b, 0x88, 0x9d, 0xf8, 0xbc, 0x26, 0xea, 0x5a, 0x54, + 0xd6, 0x60, 0x59, 0xfe, 0xf2, 0xe2, 0x0c, 0xb4, 0x5b, 0x0f, + 0xd3, 0xad, 0xc8, 0x9e, 0x89, 0x20, 0xcb, 0xa0, 0x3c, 0xdc, + 0xf2, 0xa6, 0xba, 0x41, 0xda, 0xfb, 0x73, 0x6a, 0x72, 0x53, + 0x76, 0xac, 0x54, 0xb1, 0x27, 0x23, 0xcf, 0x7c, 0x94, 0xe2, + 0x64, 0xea, 0x58, 0x03, 0x57, 0xc1, 0xe9, 0x19, 0x07, 0x28, + 0x14, 0x59, 0xb0, 0x86, 0x1f, 0x6d, 0x97, 0x14, 0xba, 0x0e, + 0xac, 0x59, 0x2e, 0xb6, 0xa6, 0xad, 0x3f, 0x47 }, + { 0x59, 0xa5, 0xbf, 0x59, 0x22, 0x26, 0x13, 0x34, 0xb8, 0x97, + 0x78, 0x80, 0x22, 0x41, 0xa5, 0x66, 0x07, 0x3b, 0xf8, 0x69, + 0xc7, 0xf9, 0x27, 0xe9, 0x09, 0xd8, 0xcf, 0x2d, 0x86, 0xa5, + 0x86, 0xf4, 0x16, 0x69, 0x78, 0x6a, 0x97, 0xe9, 0x4c, 0x11, + 0xe2, 0x64, 0xfa, 0x41, 0xb6, 0xa1, 0x3d, 0x00, 0xb0, 0x0d, + 0xbf, 0x9d, 0x2a, 0xc1, 0xaf, 0x48, 0xe6, 0x7c, 0x10, 0x2a, + 0xf5, 0x15, 0xe2, 0x3e, 0x34, 0xb4, 0x73, 0xf0, 0x65, 0x4b, + 0xe2, 0xf2, 0xd0, 0x20, 0x8a, 0x03, 0xbd, 0x07, 0xd8, 0x77, + 0xd5, 0xa6, 0xf2, 0xaf, 0xac, 0x06, 0x7f, 0xe8, 0x79, 0x75, + 0x41, 0xb6, 0x0e, 0x84, 0x2d, 0xc2, 0x69, 0xb5, 0x3c, 0x2a, + 0xaf, 0xc8, 0xdf, 0xc2, 0x4e, 0x6a, 0xe1, 0x8f, 0x08, 0x0f, + 0x79, 0x5b, 0x1b, 0x67, 0x7d, 0xe5, 0xac, 0xfa, 0x33, 0x3a, + 0x51, 0x0d, 0x3c, 0x9e, 0x22, 0x79, 0x9d, 0x37 }, + { 0x46, 0x75, 0x64, 0xc1, 0x43, 0xeb, 0x79, 0x9c, 0xf1, 0x4e, + 0xf6, 0x18, 0xd3, 0xd3, 0xe0, 0xf8, 0x04, 0xda, 0x45, 0xf8, + 0x98, 0x4c, 0xfd, 0x36, 0x8d, 0x0b, 0x5c, 0xbe, 0x4a, 0xcc, + 0x5f, 0x4d, 0x77, 0xe7, 0xe0, 0x79, 0xb1, 0x3f, 0x3b, 0xd1, + 0x36, 0xdd, 0xc2, 0x37, 0x2a, 0xaa, 0x91, 0x35, 0xaa, 0x1b, + 0x05, 0xe0, 0x39, 0x84, 0x8b, 0xc9, 0x9c, 0xaa, 0x06, 0xb7, + 0xa6, 0x15, 0x6f, 0x8a, 0x6a, 0x6a, 0x71, 0xaa, 0xda, 0xdb, + 0x47, 0xfb, 0xf9, 0x38, 0x60, 0xd0, 0x94, 0x22, 0x81, 0x00, + 0x82, 0x67, 0xfd, 0x78, 0xf8, 0xdd, 0x3c, 0x6c, 0x08, 0xbe, + 0xe9, 0xf1, 0xd9, 0x1b, 0x9a, 0xa0, 0xda, 0x93, 0xcf, 0xcc, + 0xda, 0xa7, 0xd3, 0x97, 0x07, 0x88, 0x87, 0x67, 0xa9, 0xd4, + 0x6a, 0x7f, 0x18, 0x6c, 0x1a, 0xbc, 0xeb, 0x96, 0x99, 0x72, + 0xe9, 0xd1, 0xc9, 0x1e, 0x81, 0x34, 0x71, 0x91 }, + { 0x8a, 0x0d, 0xee, 0x16, 0x4e, 0xe9, 0x84, 0xd5, 0x0d, 0x0f, + 0x7a, 0xdb, 0xed, 0x6a, 0x1e, 0x03, 0x17, 0x73, 0xf0, 0x16, + 0x7b, 0x7c, 0x50, 0xd9, 0x06, 0x8f, 0x39, 0xcb, 0x4f, 0x81, + 0xe0, 0x9e, 0xfe, 0x8d, 0x72, 0x8c, 0x7a, 0x03, 0x62, 0x18, + 0xf3, 0x16, 0x77, 0x32, 0x2f, 0x15, 0xb8, 0x50, 0x9f, 0x71, + 0xbc, 0x0c, 0xa5, 0xd2, 0xa0, 0x06, 0xa2, 0x8f, 0xe1, 0x28, + 0xc7, 0x9e, 0xdc, 0xb2, 0x8e, 0xb4, 0x8b, 0x15, 0x01, 0x1b, + 0xc6, 0xf3, 0xac, 0x92, 0xb6, 0xa2, 0xea, 0x87, 0x74, 0x86, + 0x61, 0xc5, 0x03, 0x18, 0x94, 0xd3, 0x5c, 0x61, 0xa2, 0xfe, + 0xb4, 0xaf, 0x68, 0xa2, 0xb9, 0xb0, 0x32, 0x23, 0x5f, 0xc1, + 0x43, 0xba, 0xec, 0x39, 0x90, 0x95, 0xd5, 0x75, 0x6d, 0x20, + 0xb8, 0xaa, 0x03, 0x7f, 0x33, 0xaf, 0x92, 0xdc, 0x47, 0x52, + 0x8d, 0x72, 0x59, 0x04, 0xb6, 0xff, 0xf5, 0xd7 }, + { 0x7b, 0x04, 0xb5, 0xd2, 0xee, 0x97, 0xce, 0x23, 0x2c, 0xe7, + 0xfe, 0x7d, 0xb6, 0xf6, 0xbe, 0xd2, 0x9e, 0x9d, 0xb1, 0x9f, + 0xc1, 0xf0, 0x00, 0x73, 0x77, 0x78, 0xa9, 0x66, 0x3f, 0xe0, + 0xa1, 0x7c, 0xe8, 0x9b, 0xbc, 0x1d, 0x7b, 0x62, 0x84, 0x03, + 0xf1, 0xe8, 0x0c, 0x84, 0x55, 0x4c, 0xc2, 0x77, 0xf9, 0x7c, + 0xfd, 0x0e, 0x7e, 0x20, 0xa2, 0xc3, 0x31, 0x0d, 0x91, 0xf1, + 0xe3, 0xe1, 0x81, 0x09, 0xc0, 0x36, 0x7e, 0xf8, 0xbb, 0xaa, + 0x1e, 0x8c, 0x6a, 0x8e, 0x45, 0x3e, 0xc7, 0xee, 0x80, 0x8d, + 0xdb, 0x8d, 0x1b, 0x57, 0xc9, 0x1e, 0x21, 0x5f, 0x56, 0xa7, + 0x85, 0xf9, 0x40, 0x44, 0x5e, 0x43, 0xbb, 0xb4, 0x6a, 0xa6, + 0x3f, 0x19, 0x61, 0xe2, 0x14, 0xc4, 0xc7, 0x51, 0xa4, 0x0c, + 0xce, 0x36, 0xb8, 0x08, 0x4d, 0x9f, 0xe8, 0x6c, 0x30, 0x05, + 0x50, 0x49, 0x91, 0xbf, 0x47, 0x36, 0x6e, 0x6f }, + { 0x1c, 0x6a, 0x95, 0xa4, 0xc9, 0x9b, 0xe3, 0x1c, 0x51, 0x5b, + 0x08, 0x1c, 0x9c, 0x7b, 0x27, 0x2c, 0x4f, 0x14, 0xd0, 0x32, + 0x37, 0x86, 0x97, 0x7a, 0xd8, 0x51, 0x19, 0xa0, 0xa8, 0xd8, + 0x18, 0x22, 0xe5, 0x46, 0x5a, 0x55, 0x33, 0x88, 0x63, 0x72, + 0x3a, 0xe2, 0x1b, 0x23, 0xa6, 0xdd, 0x80, 0x2f, 0xcd, 0x4d, + 0x50, 0x89, 0xc6, 0x22, 0xd6, 0xe3, 0x07, 0x29, 0x02, 0xd7, + 0x66, 0xe3, 0xad, 0xf0, 0x0a, 0xa2, 0xac, 0x6e, 0xcf, 0xa5, + 0x18, 0x57, 0x2e, 0xc6, 0xf0, 0xbb, 0xe1, 0xbb, 0xef, 0x41, + 0x60, 0x77, 0x38, 0xfb, 0xe0, 0xc1, 0x48, 0xec, 0xc7, 0x35, + 0x17, 0x31, 0xc3, 0xc3, 0xc3, 0x7c, 0x83, 0x3a, 0x10, 0x13, + 0xe9, 0x56, 0xd5, 0x1f, 0x3d, 0x56, 0x68, 0x61, 0xe7, 0x78, + 0x51, 0xe0, 0x1a, 0x73, 0x4c, 0x5e, 0x8e, 0xb8, 0x10, 0x97, + 0x5b, 0x54, 0x6b, 0xc7, 0x82, 0xc5, 0xfa, 0xf8 }, + { 0x72, 0x70, 0x8a, 0x02, 0x30, 0xa8, 0x64, 0xc9, 0xa5, 0xc0, + 0x9c, 0x84, 0x14, 0xf6, 0x87, 0x9c, 0xd4, 0xb3, 0x91, 0x9e, + 0x08, 0x18, 0xe4, 0xbe, 0x4c, 0xec, 0x87, 0x09, 0xe6, 0x56, + 0x25, 0xfb, 0x5c, 0x91, 0x22, 0x6e, 0xba, 0x9a, 0xbd, 0xa3, + 0x2a, 0x46, 0x48, 0x81, 0x34, 0xbd, 0x9a, 0xf1, 0x83, 0x6f, + 0x61, 0x64, 0x4b, 0x70, 0xab, 0x45, 0x99, 0xdd, 0x0a, 0xd6, + 0xdb, 0xbb, 0xa8, 0xfe, 0x47, 0x5a, 0x79, 0x23, 0xb7, 0x5f, + 0x3b, 0x76, 0xf4, 0xaa, 0xda, 0xb8, 0x1a, 0x1d, 0x9f, 0xb1, + 0x6f, 0x87, 0xbd, 0xf4, 0x75, 0xcb, 0xad, 0x1f, 0x92, 0xc9, + 0xc0, 0x98, 0xf0, 0x81, 0xd9, 0x27, 0xf4, 0x12, 0xab, 0x39, + 0x82, 0x48, 0x9e, 0x27, 0xae, 0xf5, 0xd2, 0xc4, 0xcc, 0xad, + 0xe8, 0x48, 0x82, 0x9c, 0x18, 0x23, 0x4d, 0x17, 0xde, 0x1c, + 0xa6, 0xb1, 0x4a, 0xd5, 0xc2, 0x82, 0x13, 0x63 }, + { 0x74, 0x91, 0xc7, 0x4c, 0x73, 0x26, 0x5d, 0x21, 0x7d, 0xb5, + 0x5c, 0x0b, 0x43, 0x69, 0x51, 0x13, 0x95, 0x25, 0xc4, 0x73, + 0x73, 0x46, 0x7e, 0x9d, 0xf1, 0x69, 0xd3, 0xcc, 0xfa, 0xe1, + 0x03, 0xf7, 0xc8, 0x65, 0xf9, 0xfb, 0x61, 0xa8, 0x5b, 0xd5, + 0x9e, 0x08, 0x18, 0x69, 0xf7, 0x09, 0x69, 0x1c, 0xcf, 0xe8, + 0xb5, 0xce, 0xbb, 0x16, 0xb5, 0x15, 0x35, 0x5e, 0xb6, 0xe2, + 0x3e, 0x5c, 0x1b, 0x2a, 0xdb, 0x62, 0xd5, 0xb0, 0xb3, 0x5c, + 0x93, 0x65, 0x2b, 0x59, 0x06, 0x49, 0xc9, 0x79, 0x3e, 0x1c, + 0x73, 0x3d, 0xa7, 0x13, 0xce, 0xc6, 0xf4, 0x32, 0xe2, 0x41, + 0x6c, 0x2a, 0xbb, 0x04, 0x3d, 0xa3, 0x82, 0x4c, 0x71, 0x46, + 0x90, 0x88, 0x08, 0x81, 0xd7, 0x0f, 0x0f, 0xee, 0x0e, 0x28, + 0x78, 0x5c, 0xa1, 0xba, 0xe0, 0x9c, 0x7f, 0x9d, 0x45, 0xba, + 0x4f, 0x33, 0xc0, 0xb1, 0xf3, 0x4a, 0x46, 0x6c }, + { 0x8b, 0xcf, 0xd3, 0xe5, 0x74, 0x17, 0x68, 0x41, 0x68, 0x29, + 0xd1, 0xc2, 0x68, 0x90, 0x6b, 0x76, 0xb7, 0x32, 0x9f, 0xab, + 0xbc, 0xe6, 0x86, 0x64, 0xcb, 0x59, 0x14, 0x93, 0xc6, 0xe8, + 0xdc, 0xbb, 0x00, 0xfd, 0x4b, 0x01, 0x0b, 0x3b, 0xa2, 0x2e, + 0xe5, 0x48, 0x7e, 0x25, 0xd3, 0xdd, 0x4a, 0xbd, 0x1f, 0xda, + 0x9f, 0x37, 0xc8, 0x5d, 0x3c, 0xb9, 0xd6, 0xc4, 0x70, 0x9f, + 0x01, 0x2a, 0xa3, 0xba, 0x69, 0xe7, 0x57, 0x84, 0xd9, 0xfc, + 0x5a, 0xdc, 0x93, 0xe2, 0x95, 0xc8, 0x59, 0x74, 0xb2, 0x01, + 0xda, 0xa7, 0xd8, 0x98, 0xe4, 0x2b, 0xcd, 0x5a, 0x2d, 0xfb, + 0x29, 0xee, 0x59, 0xef, 0x9c, 0xed, 0x31, 0x7c, 0xcf, 0x6b, + 0xae, 0xb8, 0x2c, 0x8e, 0xac, 0x86, 0xc5, 0x8c, 0xd6, 0x22, + 0x19, 0xa1, 0x1b, 0x8a, 0xc6, 0x33, 0xba, 0x4b, 0x26, 0x0b, + 0x31, 0x2e, 0xd5, 0xbf, 0x80, 0xd2, 0xb9, 0x4d }, + { 0x53, 0xca, 0xdc, 0xf7, 0xbd, 0x37, 0xab, 0x49, 0x3e, 0x18, + 0xd1, 0xe4, 0x90, 0x5a, 0x93, 0x78, 0xbd, 0x78, 0x01, 0x0e, + 0x1d, 0xb9, 0x32, 0xad, 0xf1, 0x4d, 0xda, 0x81, 0x52, 0x89, + 0x04, 0x18, 0x6f, 0x54, 0x25, 0x09, 0x05, 0x7f, 0xe9, 0x1e, + 0xd1, 0xe5, 0xf8, 0xaf, 0x67, 0x1e, 0xc3, 0x79, 0xd9, 0xe8, + 0xd2, 0x06, 0x40, 0x22, 0xa6, 0x91, 0x09, 0xd7, 0x97, 0x0b, + 0x50, 0x74, 0x62, 0x57, 0x83, 0x44, 0x6b, 0x89, 0x6a, 0xf2, + 0x0e, 0xad, 0xd5, 0x8b, 0x3d, 0xf2, 0x2f, 0x58, 0x63, 0x89, + 0x0a, 0x06, 0x96, 0x48, 0x27, 0xdf, 0xfd, 0x4f, 0x15, 0x52, + 0x7e, 0x5e, 0x1f, 0x99, 0x22, 0x27, 0x53, 0x65, 0xe0, 0xd8, + 0x77, 0x92, 0x47, 0x87, 0xb9, 0x37, 0xf7, 0xc3, 0xc0, 0x68, + 0xba, 0x16, 0x95, 0xf0, 0xb2, 0xf1, 0x11, 0x87, 0x08, 0x33, + 0x06, 0x88, 0x27, 0x34, 0xd3, 0xc8, 0xc3, 0x14 }, + { 0x90, 0x84, 0x99, 0x64, 0xbf, 0x8c, 0x62, 0xb1, 0x69, 0xbd, + 0x75, 0xe9, 0xc3, 0x2d, 0x10, 0x46, 0x75, 0x42, 0xa5, 0xae, + 0xb6, 0x9a, 0x97, 0x60, 0x10, 0x6f, 0x19, 0x0a, 0xa6, 0x50, + 0xec, 0x5c, 0x36, 0x94, 0x14, 0x85, 0x10, 0xf2, 0x62, 0x24, + 0x3d, 0xcd, 0xb9, 0xd2, 0x1e, 0x79, 0x42, 0x9e, 0xca, 0xf6, + 0x78, 0x4b, 0x49, 0x1f, 0x2b, 0xed, 0x01, 0x8b, 0x4e, 0xab, + 0x9e, 0x42, 0x87, 0x9c, 0x61, 0x75, 0x2e, 0x59, 0xda, 0x55, + 0xdd, 0x53, 0x4e, 0x10, 0x64, 0x82, 0x23, 0x96, 0x24, 0xd1, + 0x8c, 0x1e, 0x58, 0x67, 0x7d, 0xc9, 0xe5, 0x95, 0xab, 0xa6, + 0x79, 0x4b, 0xb1, 0x73, 0xb3, 0x17, 0xb3, 0x01, 0x83, 0x45, + 0xe2, 0x2b, 0x6a, 0x33, 0x64, 0x91, 0xb0, 0xf8, 0x12, 0x20, + 0x6d, 0x15, 0xd8, 0x86, 0x60, 0x6c, 0x88, 0x8a, 0xbf, 0x67, + 0x1b, 0xb5, 0xed, 0xf7, 0x5e, 0x53, 0xd0, 0xff }, + { 0x3d, 0x7f, 0x6f, 0xfa, 0x46, 0x8c, 0xd7, 0xe8, 0xc2, 0xb7, + 0x5b, 0xe4, 0x73, 0x58, 0x0d, 0x22, 0xd4, 0xed, 0xbd, 0x5e, + 0x08, 0xdc, 0x4c, 0xc0, 0xcd, 0xee, 0x18, 0xf0, 0xe9, 0x3c, + 0x92, 0x68, 0x3e, 0x19, 0x49, 0xab, 0xf6, 0xb7, 0xde, 0x33, + 0xf6, 0x86, 0x22, 0x09, 0xc4, 0x21, 0xfb, 0x7a, 0xbd, 0x86, + 0xd2, 0xca, 0xc4, 0x10, 0x12, 0x4b, 0x49, 0xd3, 0x2d, 0x7b, + 0x87, 0x5e, 0xc5, 0x16, 0xc9, 0x21, 0xb3, 0x37, 0x60, 0x89, + 0xa4, 0xf2, 0x96, 0xfd, 0xa5, 0x0e, 0xbb, 0x5a, 0x42, 0xf8, + 0xf9, 0xb4, 0x38, 0x2d, 0x4e, 0x62, 0x42, 0x3e, 0x6e, 0x67, + 0xfe, 0xbd, 0x7c, 0x71, 0x48, 0x7c, 0x1b, 0x0c, 0xbb, 0x8f, + 0x67, 0x72, 0xde, 0x9a, 0x92, 0xa9, 0x3a, 0x9d, 0xa5, 0x1a, + 0x17, 0x88, 0x18, 0x48, 0x62, 0x64, 0x9d, 0xb5, 0xf0, 0x56, + 0xb1, 0x39, 0x0c, 0xf6, 0x5a, 0x93, 0xc6, 0x61 }, + { 0x8f, 0xb1, 0x2d, 0x3f, 0x6d, 0xde, 0x74, 0xe6, 0x40, 0x99, + 0x4d, 0x6f, 0xfd, 0x43, 0x4e, 0x7c, 0x3e, 0x18, 0xc4, 0xfd, + 0x22, 0x54, 0xab, 0xee, 0x30, 0x3f, 0x9e, 0xb9, 0x1d, 0x16, + 0xa5, 0x55, 0x3f, 0x06, 0x4e, 0xd4, 0x51, 0x1e, 0x60, 0x19, + 0x56, 0x75, 0x28, 0xe3, 0x9c, 0x9c, 0x60, 0x17, 0xb5, 0x41, + 0x92, 0x03, 0x94, 0x92, 0xf2, 0x3a, 0x5f, 0xc6, 0x89, 0x35, + 0x54, 0x8b, 0xa5, 0x62, 0x55, 0x77, 0x1b, 0xf5, 0x55, 0x65, + 0x16, 0x33, 0x65, 0x9a, 0x34, 0x2c, 0xd8, 0x3c, 0x21, 0xf4, + 0x56, 0x12, 0x46, 0x7f, 0x7f, 0x19, 0x5b, 0x60, 0x85, 0x19, + 0xdf, 0x2b, 0xb2, 0xae, 0x4d, 0x82, 0xbc, 0x69, 0x0a, 0xf5, + 0x42, 0xdc, 0xe6, 0x8e, 0x56, 0x68, 0x0b, 0x08, 0x90, 0xfe, + 0xed, 0xc9, 0x9d, 0x75, 0x9d, 0xa6, 0x97, 0x03, 0x38, 0xdf, + 0xea, 0x7b, 0x29, 0x0c, 0xdf, 0xfb, 0xd5, 0xd1 }, + { 0x3f, 0xcc, 0x67, 0x31, 0x75, 0xd2, 0x37, 0xb1, 0x4f, 0x93, + 0x03, 0xa2, 0x06, 0xff, 0x34, 0x53, 0xbe, 0x94, 0x6a, 0x59, + 0x19, 0xab, 0x1c, 0x97, 0xe7, 0x85, 0x8e, 0xcd, 0x37, 0x59, + 0x81, 0xec, 0x9b, 0x64, 0x3e, 0x77, 0x86, 0x7c, 0xa0, 0xe9, + 0x5f, 0x20, 0xfd, 0x2e, 0x4f, 0x47, 0x49, 0x9d, 0xaf, 0x77, + 0x1f, 0x6d, 0xfe, 0x23, 0x9f, 0x83, 0x29, 0xdd, 0x85, 0x0a, + 0x26, 0x8a, 0x5a, 0xf7, 0x87, 0x89, 0x69, 0x96, 0x29, 0x32, + 0xfb, 0x89, 0x13, 0x58, 0xf9, 0x7b, 0x4c, 0x2f, 0x13, 0x07, + 0x14, 0x68, 0x1a, 0x14, 0xf6, 0xf5, 0x80, 0xa0, 0x4a, 0x2b, + 0x69, 0x6a, 0x71, 0x6b, 0xa4, 0xdd, 0xe8, 0x9f, 0xfa, 0xd0, + 0x57, 0x8c, 0xae, 0x91, 0x4f, 0x21, 0x28, 0x23, 0x07, 0x8a, + 0xc3, 0xef, 0x45, 0x3e, 0x09, 0xf0, 0xb8, 0x7b, 0x7e, 0x4d, + 0x6c, 0x63, 0x81, 0xa2, 0x29, 0x3c, 0xb7, 0xa4 }, + { 0x64, 0x51, 0x46, 0xfd, 0xc7, 0x15, 0x1c, 0x34, 0xd4, 0x13, + 0x45, 0xdc, 0xb3, 0xfa, 0x86, 0x85, 0x75, 0xf0, 0xfb, 0xac, + 0xaf, 0x42, 0x99, 0x39, 0x24, 0xec, 0x69, 0x03, 0x7e, 0x62, + 0xa1, 0x88, 0xbe, 0xbe, 0x30, 0xcf, 0xa1, 0xf5, 0x24, 0x9c, + 0xc3, 0xa5, 0xa0, 0x5d, 0x56, 0x46, 0x12, 0xb7, 0x15, 0x44, + 0x24, 0xa3, 0x6b, 0x0f, 0x25, 0x4b, 0x60, 0xdd, 0x62, 0xcf, + 0xdf, 0x0c, 0xb3, 0xc2, 0x2a, 0x2f, 0x5d, 0x62, 0xf1, 0x0f, + 0xdb, 0xd2, 0x56, 0x08, 0x5a, 0x59, 0x5b, 0x51, 0xbc, 0x46, + 0x12, 0xf3, 0xe4, 0xc0, 0x9f, 0xb3, 0xf1, 0xdc, 0x1d, 0x4c, + 0x93, 0xf4, 0x7d, 0xeb, 0x92, 0x6b, 0xf2, 0x12, 0x08, 0x55, + 0x2c, 0x37, 0xa1, 0x22, 0x24, 0x29, 0xcb, 0xfd, 0x95, 0xa6, + 0x4a, 0xaf, 0xfa, 0xf7, 0x0e, 0x1f, 0xc1, 0x40, 0x1b, 0x90, + 0x50, 0x9d, 0xeb, 0xd5, 0xdf, 0x21, 0xf9, 0x20 }, + { 0x44, 0x8d, 0x3d, 0x72, 0xab, 0xfb, 0x9f, 0x2e, 0x2a, 0x7c, + 0xa4, 0xa9, 0x4d, 0x00, 0x5d, 0xda, 0x6d, 0xc7, 0x85, 0x05, + 0x6c, 0x05, 0x0a, 0x74, 0x92, 0xd7, 0x0a, 0x9f, 0x54, 0xba, + 0x14, 0xce, 0xca, 0xd0, 0x3b, 0xe7, 0xc0, 0x58, 0xfa, 0x80, + 0x1d, 0xc0, 0x77, 0x55, 0x29, 0xaa, 0x26, 0x5d, 0x43, 0x4d, + 0x09, 0xb9, 0x81, 0x97, 0xbe, 0x85, 0x7a, 0xf2, 0xd3, 0x5f, + 0x98, 0x58, 0xfa, 0x48, 0xf1, 0x78, 0x9c, 0x69, 0x6e, 0xd1, + 0xa9, 0xc3, 0x01, 0xbc, 0x30, 0x05, 0x7b, 0xb1, 0xd0, 0x00, + 0x6e, 0x21, 0xd5, 0x8f, 0xd3, 0x14, 0x12, 0xb8, 0x95, 0x45, + 0xa6, 0xaa, 0x51, 0xdc, 0x5a, 0x74, 0xca, 0x53, 0x19, 0x19, + 0xef, 0x3d, 0x8e, 0x00, 0x20, 0x37, 0x57, 0xac, 0x7e, 0x50, + 0xfc, 0x17, 0xbb, 0xa6, 0xf1, 0x36, 0x00, 0x63, 0x26, 0xe1, + 0xec, 0xec, 0x63, 0x3a, 0xba, 0x19, 0x24, 0xf9 }, + { 0x76, 0x88, 0x14, 0x79, 0xcb, 0x70, 0x19, 0xa5, 0x72, 0x49, + 0x71, 0x75, 0xd9, 0x2a, 0x30, 0x9f, 0x28, 0x5a, 0x33, 0xdf, + 0x99, 0x63, 0xc4, 0x59, 0x4d, 0x8c, 0x5d, 0x67, 0x25, 0x92, + 0x8c, 0x78, 0x20, 0x81, 0x78, 0xec, 0x96, 0xf2, 0xfd, 0x89, + 0x3d, 0xcd, 0x13, 0x1f, 0xb4, 0x6f, 0x7c, 0xbc, 0xb8, 0x25, + 0xb1, 0x62, 0xd0, 0xe2, 0xf3, 0x37, 0x40, 0x2e, 0xf5, 0x84, + 0xe5, 0x48, 0x44, 0xc9, 0x10, 0x8a, 0x28, 0xb8, 0xf6, 0xa4, + 0x47, 0x0a, 0x0c, 0x61, 0xec, 0x99, 0x56, 0x66, 0xef, 0xdf, + 0xd3, 0xaa, 0xc7, 0x15, 0xa5, 0x0e, 0xaa, 0x91, 0x13, 0xad, + 0xe4, 0xec, 0x5f, 0xf6, 0xe4, 0xa3, 0x95, 0x5c, 0xe4, 0x2a, + 0x3c, 0xd9, 0xf3, 0x3b, 0xb3, 0xf4, 0x56, 0x13, 0x4b, 0x07, + 0x44, 0x14, 0x86, 0x83, 0x51, 0xbc, 0xa9, 0xae, 0x81, 0x5a, + 0xdc, 0x56, 0xf1, 0x45, 0x29, 0xb3, 0x39, 0x89 }, + { 0x67, 0x0e, 0xb0, 0x1c, 0x5e, 0x5a, 0x86, 0x26, 0xf3, 0x76, + 0x00, 0xfb, 0x53, 0x2c, 0xe1, 0x80, 0x67, 0x13, 0x52, 0x60, + 0x59, 0xfa, 0xe5, 0x06, 0x50, 0xb9, 0xd0, 0x6e, 0xdd, 0xab, + 0xed, 0x19, 0xa4, 0x79, 0x24, 0x1c, 0x9f, 0xff, 0x0e, 0x3a, + 0xde, 0x25, 0x3f, 0x4c, 0x56, 0xcc, 0xe8, 0x15, 0xc3, 0x59, + 0x25, 0xd0, 0x4b, 0x18, 0x69, 0x2d, 0x17, 0x91, 0x4e, 0x1d, + 0xb0, 0xb7, 0x12, 0xa7, 0x1c, 0xff, 0x0e, 0xe7, 0xd0, 0x8a, + 0x26, 0x5d, 0x75, 0xb8, 0xd5, 0x75, 0x8b, 0xf2, 0xe1, 0xd7, + 0x4b, 0xc0, 0x62, 0x64, 0xa0, 0xb2, 0xae, 0xe5, 0xc2, 0xc5, + 0x63, 0xb4, 0x4a, 0x9e, 0xad, 0x62, 0x63, 0x60, 0x44, 0x21, + 0x2a, 0x33, 0x54, 0x15, 0xe8, 0xa2, 0x2c, 0xe0, 0x03, 0xa5, + 0xe2, 0x1a, 0x5e, 0x11, 0xb9, 0xad, 0x92, 0xbf, 0x65, 0xdb, + 0xba, 0x43, 0xa1, 0x14, 0x91, 0x76, 0x7e, 0xed }, + { 0x50, 0x48, 0x52, 0xe7, 0x63, 0x5d, 0xff, 0x27, 0xb7, 0x7f, + 0x03, 0x66, 0x00, 0x75, 0x16, 0x6a, 0x2d, 0x0f, 0x2f, 0x98, + 0x1c, 0xba, 0xae, 0x32, 0x1f, 0xa9, 0xc8, 0xf5, 0x91, 0x12, + 0xf7, 0xd6, 0x2e, 0xe9, 0xcc, 0x15, 0x4b, 0xb9, 0x0b, 0x1f, + 0x23, 0x55, 0x29, 0x32, 0x7f, 0x4b, 0x79, 0x6b, 0x7b, 0x82, + 0x12, 0x50, 0xdb, 0x23, 0x45, 0xe9, 0x80, 0x93, 0x89, 0x9e, + 0x5d, 0x64, 0xee, 0xce, 0x7d, 0x93, 0x23, 0x40, 0x97, 0x5a, + 0x46, 0xf0, 0xa6, 0x9e, 0x94, 0x30, 0xb5, 0xe4, 0xb4, 0x76, + 0xfc, 0x3b, 0x3b, 0x4e, 0x7c, 0x2d, 0x13, 0x22, 0x43, 0x52, + 0xf3, 0x8d, 0xbe, 0xac, 0x7e, 0xff, 0x69, 0xa1, 0x04, 0xf2, + 0x92, 0x24, 0xdd, 0xf1, 0x91, 0x78, 0x05, 0x41, 0x2a, 0x1a, + 0x38, 0x45, 0xcf, 0x08, 0xec, 0xc5, 0x7f, 0x24, 0x31, 0xad, + 0xdf, 0x73, 0xc0, 0xaf, 0x73, 0xcd, 0xbb, 0x43 }, + { 0x99, 0x2f, 0xe1, 0x51, 0xf7, 0xe9, 0x0c, 0xc4, 0xfb, 0x24, + 0xdc, 0x40, 0x52, 0x40, 0xf8, 0xb0, 0x50, 0xd0, 0xce, 0xe7, + 0x61, 0x8c, 0xe6, 0xc4, 0x3f, 0x4c, 0x9a, 0x19, 0xb9, 0x1e, + 0xae, 0x9c, 0x2f, 0x3a, 0x73, 0x08, 0xe9, 0xa9, 0xe1, 0x3f, + 0xd0, 0x5e, 0xf6, 0x9b, 0xe8, 0x66, 0x7d, 0x30, 0xab, 0xff, + 0xd9, 0xfc, 0xa9, 0xc7, 0xde, 0xb9, 0xa0, 0x53, 0x00, 0x02, + 0x05, 0x8b, 0x31, 0x77, 0x8a, 0x31, 0xb1, 0x2a, 0x1f, 0xab, + 0xf0, 0x27, 0x77, 0x35, 0x14, 0x0e, 0xd3, 0xc4, 0x29, 0xa0, + 0xc6, 0x6f, 0xd6, 0x17, 0x38, 0x53, 0xaf, 0x38, 0x71, 0x30, + 0x5c, 0x24, 0x2d, 0x95, 0x09, 0x08, 0xb0, 0x1b, 0x16, 0xd3, + 0xcb, 0xe8, 0xe9, 0x93, 0xad, 0x01, 0xde, 0x92, 0x84, 0xba, + 0xaa, 0xf6, 0x32, 0x6c, 0x07, 0x6a, 0xec, 0x6c, 0x90, 0x78, + 0x2f, 0x0f, 0x3c, 0xe5, 0xa2, 0xf3, 0x92, 0xfa }, + { 0x5a, 0x68, 0xbf, 0xa8, 0x4c, 0x5b, 0x71, 0xe0, 0x13, 0x4e, + 0xcf, 0x4b, 0x9c, 0x8e, 0xb9, 0xfb, 0x1d, 0xc8, 0x16, 0x8a, + 0x99, 0x2b, 0xcc, 0x2a, 0xca, 0x92, 0xe4, 0x84, 0x9b, 0x60, + 0x82, 0xa9, 0x73, 0x21, 0xbe, 0xb9, 0xa2, 0xb0, 0xab, 0xd2, + 0x6e, 0xea, 0x5e, 0x98, 0x38, 0xa5, 0xe3, 0x3d, 0x62, 0x6e, + 0xe7, 0x5f, 0xc4, 0x41, 0x32, 0x5c, 0xc4, 0x45, 0x1e, 0x9c, + 0xef, 0x10, 0x35, 0x50, 0xa9, 0xbe, 0x08, 0x0a, 0xcd, 0x50, + 0xe9, 0x6b, 0xba, 0x5b, 0xb4, 0xa8, 0x47, 0x47, 0x55, 0x73, + 0x20, 0xb8, 0x4f, 0xa8, 0x48, 0x0c, 0xb3, 0xae, 0xe3, 0x8c, + 0xb0, 0x9f, 0xdd, 0x98, 0xef, 0xec, 0x98, 0x21, 0xe1, 0xae, + 0xa3, 0x1e, 0x48, 0xc6, 0x97, 0xb4, 0x27, 0xb0, 0x44, 0xf0, + 0xa8, 0x28, 0xa4, 0xde, 0xd6, 0x9d, 0x87, 0x87, 0x2f, 0x98, + 0x44, 0x54, 0xdb, 0x31, 0x38, 0xf1, 0x97, 0xaa }, + { 0x78, 0xac, 0xfd, 0xf9, 0x9f, 0x5e, 0xf4, 0x39, 0x56, 0xce, + 0x6e, 0xf7, 0xbe, 0xf1, 0x62, 0x8f, 0xd1, 0x5c, 0x8f, 0xa0, + 0xa6, 0x33, 0x7b, 0x7c, 0x4b, 0xc2, 0x4a, 0x46, 0x08, 0x5a, + 0xd5, 0xe7, 0xeb, 0x40, 0xb0, 0x45, 0x81, 0x89, 0x7b, 0xc1, + 0xff, 0x98, 0x2e, 0x0a, 0x0d, 0x5c, 0xa5, 0x77, 0x71, 0xe0, + 0xdc, 0x98, 0x40, 0x11, 0xa3, 0x96, 0x91, 0xca, 0x1e, 0x3a, + 0xb8, 0xcb, 0xbb, 0xec, 0x6a, 0xb3, 0x63, 0xa8, 0x50, 0x9b, + 0xef, 0x61, 0x48, 0x71, 0x54, 0x8a, 0xe2, 0x41, 0x8f, 0x2e, + 0x6a, 0x22, 0xf4, 0x93, 0xf4, 0xdb, 0x3c, 0x0e, 0x2f, 0x5a, + 0x24, 0x53, 0x02, 0x6d, 0x39, 0x17, 0xed, 0x16, 0x86, 0x5b, + 0x0d, 0x3b, 0x9d, 0x04, 0x14, 0xde, 0x58, 0x85, 0x5b, 0x1c, + 0x0c, 0x26, 0xd1, 0x05, 0xff, 0xf9, 0x55, 0x02, 0xf8, 0xb0, + 0xb4, 0xff, 0x3b, 0x45, 0xff, 0x0a, 0x2b, 0xfb }, + { 0x0a, 0xd9, 0x2d, 0x73, 0xd0, 0x75, 0xa3, 0x66, 0x8c, 0xb4, + 0xb4, 0x8c, 0xb0, 0x61, 0xc9, 0x49, 0x6f, 0x10, 0xae, 0x0f, + 0x90, 0x8b, 0x4a, 0x29, 0x66, 0xbc, 0xb8, 0xf0, 0x8b, 0xaa, + 0x6e, 0xd2, 0xf2, 0x5c, 0x93, 0xf6, 0x90, 0xae, 0x48, 0x90, + 0x2d, 0xfc, 0x53, 0x32, 0x37, 0xde, 0x86, 0x1f, 0xe8, 0xda, + 0x25, 0x3c, 0xbf, 0x31, 0xbe, 0x71, 0x98, 0x62, 0xbb, 0x76, + 0xa0, 0x41, 0x23, 0x1a, 0x53, 0x81, 0x52, 0x18, 0xb8, 0x3a, + 0x58, 0xe0, 0xe2, 0x30, 0x6e, 0xa0, 0xae, 0x36, 0xb6, 0xf7, + 0xde, 0x76, 0xa1, 0x24, 0x05, 0xe9, 0xf1, 0x23, 0xcd, 0x93, + 0x39, 0x29, 0x48, 0x14, 0xcc, 0x52, 0xd2, 0xd6, 0x02, 0x67, + 0x1f, 0x4a, 0x34, 0x87, 0x39, 0xed, 0xc6, 0xb9, 0xdf, 0xa2, + 0x2e, 0x1b, 0x95, 0x42, 0x02, 0xa0, 0xc7, 0x7f, 0x61, 0xc4, + 0x45, 0xbf, 0x7f, 0x15, 0xf8, 0x52, 0x01, 0x89 }, + { 0x95, 0xbb, 0xd8, 0xa0, 0x70, 0xa6, 0xe9, 0xae, 0x8e, 0xf4, + 0xdc, 0xaf, 0x07, 0x5b, 0x3c, 0xed, 0x1a, 0x4f, 0xe9, 0x34, + 0x27, 0x9a, 0xa6, 0x6b, 0x1b, 0x78, 0xb4, 0xba, 0x0b, 0x50, + 0xa9, 0xeb, 0x5e, 0xbf, 0x80, 0xb7, 0x94, 0xb9, 0x0b, 0xcf, + 0x08, 0xfa, 0x64, 0xd3, 0x46, 0x42, 0x10, 0x97, 0xdc, 0x2a, + 0xc1, 0x7b, 0xa3, 0xd7, 0xd8, 0x8f, 0xec, 0x1c, 0xcf, 0xd1, + 0x98, 0xc3, 0x11, 0x63, 0x9a, 0xdc, 0x51, 0x51, 0xb3, 0xae, + 0xd5, 0xf6, 0x3e, 0xf2, 0xcb, 0x4d, 0x4a, 0xeb, 0x7f, 0xe8, + 0xf2, 0x2a, 0x8f, 0x4b, 0x02, 0xf4, 0x01, 0x61, 0x84, 0x7b, + 0x79, 0x95, 0x13, 0xe6, 0x81, 0xed, 0xea, 0x3b, 0xe0, 0x93, + 0xd4, 0xbe, 0x89, 0x02, 0xbe, 0x99, 0x15, 0x4b, 0x34, 0x66, + 0xc2, 0x80, 0x47, 0x78, 0xc6, 0x20, 0x80, 0xcd, 0x89, 0xab, + 0xbf, 0xb9, 0x5f, 0xed, 0xc2, 0xca, 0x54, 0x8a }, + { 0x37, 0x5a, 0x88, 0x4f, 0xc1, 0x25, 0xa9, 0x19, 0x48, 0x0d, + 0xc6, 0x6f, 0xb8, 0x86, 0x7a, 0x2a, 0xad, 0x14, 0x70, 0x59, + 0xf2, 0x0d, 0xfc, 0xf5, 0xa0, 0xa1, 0x0d, 0x6d, 0xdf, 0xb9, + 0xcf, 0x21, 0xe2, 0x9f, 0xb0, 0x60, 0x2a, 0xeb, 0xe4, 0x87, + 0xab, 0x1d, 0x86, 0xb7, 0x2a, 0x35, 0x94, 0x7f, 0x89, 0x30, + 0x53, 0xfc, 0xc0, 0x55, 0x4e, 0xc1, 0x69, 0xff, 0x35, 0xea, + 0x51, 0x4f, 0x5c, 0x04, 0xca, 0xc1, 0xe5, 0xd0, 0xbd, 0x07, + 0xd9, 0x0f, 0xfa, 0x42, 0x9c, 0x71, 0xe2, 0xf0, 0xe3, 0x89, + 0x07, 0x2b, 0xaa, 0x63, 0x5c, 0x16, 0xd3, 0x36, 0x31, 0x4e, + 0xf4, 0xe0, 0xaa, 0xde, 0x06, 0x6a, 0x2b, 0xfa, 0xaf, 0x47, + 0x8e, 0x83, 0x5c, 0x42, 0xe2, 0x47, 0xc9, 0xec, 0xfc, 0x1b, + 0xd6, 0xa7, 0x75, 0x67, 0xa8, 0x87, 0xb8, 0x23, 0xe3, 0x63, + 0x59, 0xf9, 0x24, 0x95, 0xe6, 0x14, 0xbb, 0xd0 }, + { 0x26, 0x8d, 0x81, 0x8b, 0x08, 0xcb, 0x84, 0xec, 0x66, 0xbb, + 0x09, 0x3b, 0x38, 0x41, 0x53, 0x79, 0x9f, 0xe0, 0xdd, 0xa7, + 0x19, 0x68, 0x83, 0x8a, 0x01, 0xcd, 0xcd, 0xe2, 0x4f, 0xd1, + 0x2a, 0xdb, 0xde, 0xc7, 0x5c, 0x81, 0xaf, 0xa6, 0x3c, 0x55, + 0xc7, 0x30, 0x3c, 0x80, 0x1e, 0xaa, 0x8c, 0x47, 0x26, 0xaa, + 0x69, 0xea, 0x60, 0x79, 0xc9, 0xa0, 0xfd, 0x97, 0xfb, 0xb0, + 0xb9, 0x1a, 0x67, 0x63, 0xfd, 0xf3, 0x67, 0x63, 0x54, 0x1e, + 0x06, 0x67, 0xb9, 0x3e, 0xd9, 0xc9, 0x2f, 0x1c, 0x59, 0x50, + 0x40, 0x32, 0x5f, 0x99, 0xc8, 0xd3, 0x06, 0x68, 0xba, 0xeb, + 0xc6, 0x64, 0xd1, 0x3a, 0x0d, 0x86, 0x67, 0x88, 0x64, 0xa0, + 0xe4, 0xfd, 0x73, 0xca, 0xf7, 0x70, 0x7e, 0xc0, 0x1b, 0xdb, + 0x1a, 0x54, 0x1a, 0x16, 0x1e, 0x2a, 0x87, 0x5c, 0x6d, 0xab, + 0x17, 0x8c, 0xbe, 0x2e, 0x12, 0x17, 0xf7, 0xea }, + { 0x8b, 0x02, 0x73, 0x5c, 0x05, 0x6c, 0xa4, 0x4b, 0x84, 0x19, + 0xed, 0x4b, 0x01, 0xb5, 0x3a, 0x56, 0x3e, 0xb9, 0x3b, 0x33, + 0x4f, 0x5f, 0x2b, 0xf5, 0x11, 0x71, 0xfe, 0x3c, 0x44, 0x35, + 0x51, 0x6a, 0xe2, 0x4c, 0x02, 0x8a, 0x2e, 0x7a, 0x20, 0x8e, + 0x81, 0x6b, 0x63, 0x3a, 0x0f, 0x97, 0x91, 0x89, 0x88, 0x3f, + 0xad, 0x37, 0xbd, 0x70, 0x7c, 0x2e, 0xa5, 0xe7, 0x7e, 0xed, + 0x3a, 0x7d, 0x83, 0x75, 0x86, 0xef, 0x4e, 0xdb, 0x33, 0x9e, + 0x4a, 0x78, 0x7f, 0x7d, 0x31, 0x64, 0x2b, 0x72, 0x01, 0x40, + 0xb5, 0xae, 0x04, 0xe4, 0x64, 0x38, 0xd7, 0xee, 0x37, 0xb0, + 0xcb, 0x5b, 0x9f, 0xa8, 0xe0, 0x66, 0xda, 0x40, 0x99, 0xf2, + 0xb2, 0x4e, 0xe9, 0xde, 0x24, 0x0c, 0x10, 0x13, 0xbe, 0xcc, + 0xc1, 0xab, 0x4f, 0xc3, 0x2e, 0x67, 0x47, 0x3d, 0x10, 0x3b, + 0x73, 0xda, 0xe3, 0x58, 0x41, 0x58, 0x05, 0x55 }, + { 0x40, 0x0e, 0x3a, 0xa0, 0x4b, 0x4d, 0x85, 0xfe, 0x5a, 0xb4, + 0x5c, 0x3f, 0x04, 0x36, 0x50, 0x42, 0x58, 0x22, 0xa7, 0x82, + 0xfd, 0x35, 0x40, 0xd8, 0xb3, 0x2e, 0xcf, 0x7e, 0x58, 0x77, + 0x3d, 0x4c, 0xf5, 0x71, 0xff, 0xdb, 0xc3, 0x00, 0x6c, 0x0d, + 0xd1, 0xf0, 0x02, 0x4c, 0x8a, 0x0c, 0x81, 0x82, 0x3e, 0x14, + 0x9a, 0xf9, 0x5e, 0x98, 0x97, 0x34, 0x16, 0x7d, 0x82, 0x81, + 0xd7, 0xe3, 0xad, 0x1b, 0xba, 0xe6, 0xc7, 0xfe, 0x8e, 0x1b, + 0x76, 0xc2, 0xd9, 0x55, 0x2d, 0x19, 0xaf, 0xbc, 0xe2, 0x65, + 0x97, 0xc6, 0x76, 0x8e, 0xe6, 0x49, 0x1f, 0xfe, 0x48, 0x5d, + 0x7a, 0xb4, 0x0d, 0x99, 0x5b, 0xc9, 0xec, 0x71, 0xbc, 0x5a, + 0x91, 0xbd, 0xf9, 0x2f, 0xac, 0x12, 0x0e, 0x6e, 0x2b, 0xfc, + 0x3b, 0x21, 0x1d, 0xe4, 0xc0, 0x26, 0xf3, 0xfc, 0x28, 0xc1, + 0xb8, 0x9b, 0xb4, 0x64, 0xe1, 0x01, 0x91, 0x95 }, + { 0x13, 0x1c, 0x3d, 0xa2, 0x8d, 0xa6, 0xe0, 0x39, 0x4a, 0x42, + 0xb9, 0xac, 0xf3, 0xa6, 0xa1, 0x98, 0x36, 0x2f, 0x76, 0x47, + 0xad, 0xaf, 0x1f, 0x4d, 0x09, 0xc1, 0x57, 0xd4, 0x4a, 0x13, + 0x00, 0x9b, 0xc8, 0x07, 0xc7, 0x79, 0x96, 0x71, 0x85, 0xb1, + 0x27, 0xc3, 0xe0, 0x32, 0x67, 0xcb, 0x58, 0x6f, 0x3e, 0xd3, + 0x50, 0xb9, 0xf1, 0x64, 0x51, 0xa7, 0xa3, 0xc2, 0x85, 0x06, + 0xc8, 0x9f, 0xc3, 0xf5, 0xfe, 0xd6, 0x60, 0xd5, 0x06, 0x21, + 0xa9, 0x9b, 0xff, 0x38, 0x67, 0xb8, 0xa5, 0x01, 0x22, 0x96, + 0x65, 0xb2, 0x2e, 0xc9, 0x73, 0xc2, 0x53, 0xdb, 0xda, 0x17, + 0xc4, 0x1b, 0xc5, 0x10, 0x7a, 0xb7, 0x5e, 0x13, 0xaa, 0xc3, + 0xe5, 0xe0, 0xac, 0x2e, 0x65, 0x92, 0x23, 0xb1, 0xc6, 0x0e, + 0xc7, 0x7d, 0x37, 0xa2, 0xed, 0x64, 0x24, 0x13, 0x60, 0x74, + 0x47, 0x32, 0x16, 0x49, 0x5e, 0x46, 0xe4, 0xa2 }, + { 0x71, 0xd1, 0xa4, 0x6a, 0x34, 0x54, 0x5c, 0xe9, 0xde, 0x80, + 0x98, 0xad, 0x44, 0xaa, 0x0f, 0xf0, 0xb9, 0x20, 0xaa, 0xc1, + 0xb2, 0xc1, 0x76, 0x15, 0xa7, 0xc0, 0x74, 0xf1, 0x1c, 0xb0, + 0xe8, 0xff, 0x13, 0x15, 0x14, 0xd7, 0x5d, 0x75, 0xf1, 0x54, + 0x6b, 0x79, 0xcf, 0x97, 0xc4, 0xc6, 0x90, 0xc9, 0x0f, 0xf7, + 0x83, 0x8b, 0x9d, 0xf1, 0xe7, 0xc8, 0x06, 0x0c, 0xa4, 0xdf, + 0xcb, 0x02, 0xdb, 0x90, 0x60, 0xc2, 0x61, 0xaf, 0x73, 0x0e, + 0x83, 0xfd, 0x19, 0x8c, 0x44, 0x4b, 0xf4, 0xc2, 0x08, 0x3c, + 0x99, 0xbb, 0x45, 0x04, 0xcd, 0x3b, 0x2f, 0x32, 0x3d, 0x32, + 0xd6, 0x10, 0xfd, 0xa2, 0x51, 0xb9, 0xc5, 0x8d, 0x41, 0x1a, + 0x80, 0xf5, 0xf4, 0xa2, 0x7c, 0x08, 0x99, 0xbd, 0xec, 0x03, + 0xf8, 0x12, 0xf4, 0x15, 0xb4, 0x25, 0xd0, 0x4f, 0x44, 0x36, + 0x4a, 0x78, 0x5f, 0xf1, 0xa7, 0xda, 0x83, 0xba }, + { 0x6c, 0xd2, 0x69, 0x9f, 0x11, 0x67, 0xf5, 0x21, 0xb9, 0x5c, + 0xc4, 0x16, 0x53, 0x3d, 0x0a, 0xcb, 0x39, 0x64, 0xff, 0x3a, + 0x24, 0xc5, 0x2d, 0x4b, 0x3e, 0x90, 0xd7, 0x16, 0x36, 0x48, + 0xfa, 0xb9, 0x00, 0x8e, 0xab, 0xdf, 0x32, 0x5f, 0xc1, 0x3a, + 0xd8, 0xcc, 0xf9, 0x0c, 0x17, 0xd3, 0xb6, 0xd5, 0x82, 0x4f, + 0xda, 0xdd, 0x5e, 0x4d, 0x60, 0xf6, 0x0f, 0x47, 0xb3, 0xa8, + 0x4f, 0x78, 0x54, 0x0b, 0xc3, 0xb4, 0x4a, 0x85, 0x60, 0xa4, + 0x56, 0x41, 0x1f, 0x65, 0xda, 0xfd, 0x6e, 0x65, 0xe3, 0xd7, + 0xf6, 0x37, 0xa5, 0x88, 0x79, 0x3c, 0xec, 0xcf, 0xc5, 0x41, + 0x0d, 0xb6, 0xca, 0x3b, 0xed, 0x06, 0x27, 0xd3, 0x8b, 0xa4, + 0x8d, 0x72, 0x62, 0x2c, 0xaa, 0x5a, 0xab, 0x2a, 0xc5, 0xd4, + 0xd1, 0x30, 0xa0, 0xd8, 0xec, 0xc3, 0x77, 0x2d, 0xda, 0x0d, + 0x76, 0x17, 0x8f, 0x76, 0xfa, 0x1b, 0x38, 0x2e }, + { 0x32, 0x7c, 0x06, 0x3f, 0xda, 0x34, 0x5d, 0xc2, 0x19, 0xee, + 0xe2, 0x74, 0xc7, 0xee, 0xb8, 0x26, 0xfa, 0x2e, 0xfc, 0xb8, + 0x6c, 0x88, 0xc9, 0x65, 0xe8, 0xf0, 0x37, 0x42, 0x30, 0xab, + 0x19, 0x6f, 0x93, 0x38, 0xc3, 0x4d, 0xf2, 0x73, 0x55, 0x69, + 0x4b, 0x4b, 0x19, 0xa6, 0xc6, 0x1a, 0x04, 0xbc, 0x0d, 0xe4, + 0x17, 0xeb, 0xe2, 0xba, 0xc3, 0x9b, 0xd3, 0x0f, 0xe4, 0x0b, + 0xa5, 0x8a, 0xcb, 0xb4, 0x7b, 0xbd, 0xc7, 0x49, 0x16, 0xab, + 0x7b, 0x5e, 0xe1, 0x5f, 0x28, 0x2c, 0x08, 0x7a, 0xda, 0xdd, + 0x89, 0x27, 0x95, 0xa7, 0x58, 0x57, 0x42, 0xf2, 0xeb, 0x70, + 0x93, 0xd0, 0xcd, 0x8f, 0x14, 0x42, 0x22, 0xdd, 0x68, 0x93, + 0x7c, 0x5a, 0x8c, 0x82, 0x54, 0x00, 0x34, 0xf8, 0x30, 0xf3, + 0x73, 0x26, 0xb0, 0x3d, 0xcf, 0xe2, 0x99, 0xd1, 0xbd, 0xfb, + 0x2d, 0x8c, 0x0b, 0x3b, 0x12, 0xf4, 0xf3, 0xac }, + { 0x02, 0x0f, 0x19, 0xd1, 0xc0, 0xdf, 0x68, 0x56, 0xeb, 0x6b, + 0x9d, 0x2a, 0x36, 0x70, 0x11, 0x2c, 0x9a, 0xfb, 0xa8, 0x22, + 0x48, 0xb0, 0x1a, 0xf2, 0x7a, 0x42, 0xa9, 0x4b, 0xda, 0x5f, + 0xa5, 0xbf, 0x1a, 0xf4, 0xc4, 0x96, 0x6c, 0x27, 0xb8, 0x3b, + 0x72, 0xaa, 0x22, 0xb2, 0xee, 0xcb, 0x4f, 0x87, 0x06, 0x23, + 0xa1, 0xfe, 0x39, 0xf3, 0xcd, 0x22, 0x1b, 0xe4, 0xe0, 0x59, + 0x93, 0xb4, 0x87, 0x80, 0x37, 0x04, 0x00, 0xf2, 0x13, 0x0b, + 0xfb, 0x7c, 0xd1, 0x59, 0x50, 0x9e, 0xda, 0x81, 0x33, 0x36, + 0xe5, 0x8d, 0xfc, 0xc8, 0x36, 0x6d, 0x6a, 0x5f, 0xc4, 0x21, + 0x6b, 0x79, 0x02, 0x2d, 0xe2, 0x71, 0xc3, 0xe7, 0xc2, 0xaa, + 0xb1, 0xc2, 0x5a, 0x16, 0xe6, 0x4e, 0xcc, 0x7b, 0x14, 0x02, + 0xa8, 0x66, 0xbb, 0xe9, 0x86, 0x9d, 0x19, 0x43, 0xae, 0xfe, + 0xab, 0x39, 0x9e, 0xff, 0x5b, 0x47, 0xcd, 0x53 }, + { 0x79, 0xe7, 0x27, 0x20, 0xb0, 0x05, 0x05, 0x44, 0xf7, 0x57, + 0xe1, 0xff, 0x0c, 0x88, 0x8f, 0x60, 0x99, 0xd0, 0x90, 0xeb, + 0xac, 0xca, 0x11, 0x60, 0x54, 0xb0, 0x09, 0x2a, 0xf1, 0x8a, + 0x07, 0x70, 0x26, 0x27, 0x43, 0x86, 0x8b, 0x4f, 0x6b, 0xba, + 0x47, 0x69, 0x9e, 0xbe, 0x72, 0x0c, 0x3a, 0xdb, 0x91, 0x60, + 0x58, 0xec, 0x5b, 0x23, 0x17, 0x27, 0x5f, 0xba, 0x16, 0xd3, + 0xcc, 0xdd, 0xef, 0xce, 0x79, 0xfb, 0xbf, 0xd3, 0xa3, 0xd0, + 0x57, 0xcf, 0xe3, 0x7e, 0xe2, 0xf2, 0x4c, 0xd6, 0x11, 0x47, + 0x3b, 0x93, 0x7e, 0xe3, 0x3a, 0x48, 0x62, 0x68, 0xe9, 0xff, + 0x02, 0x3d, 0x10, 0x28, 0x5a, 0x24, 0x94, 0x40, 0x30, 0x2d, + 0xd2, 0xbc, 0xcc, 0x4d, 0x9a, 0x78, 0x0a, 0x19, 0xe6, 0x52, + 0x58, 0x40, 0xb6, 0x18, 0xeb, 0xc6, 0xdb, 0x1d, 0xe5, 0xc5, + 0x37, 0x05, 0x1a, 0x86, 0xa4, 0xdb, 0xba, 0x20 }, + { 0x00, 0x1d, 0x3c, 0xe3, 0x70, 0x15, 0x84, 0x6d, 0xe4, 0x28, + 0xb2, 0xb5, 0x95, 0x11, 0xa0, 0x56, 0xa4, 0x48, 0x79, 0x27, + 0x38, 0xa1, 0x93, 0x9d, 0x37, 0xaf, 0x7f, 0x83, 0xfb, 0xd1, + 0x5e, 0x05, 0xe9, 0xb5, 0xbb, 0x45, 0x2a, 0x9f, 0x55, 0x8c, + 0x58, 0xda, 0xa7, 0x3a, 0xa1, 0x26, 0x85, 0x1c, 0x14, 0xa3, + 0x85, 0x4e, 0xcb, 0xc5, 0x38, 0xf9, 0x70, 0xc7, 0x9c, 0x56, + 0x66, 0xcd, 0xbd, 0x8d, 0xe9, 0x61, 0xaf, 0x3e, 0x77, 0x43, + 0xa9, 0x85, 0xf2, 0x52, 0xca, 0x0c, 0x78, 0x93, 0x75, 0xa1, + 0x9f, 0x29, 0xd9, 0x7b, 0xde, 0x16, 0x67, 0x6f, 0x54, 0x84, + 0x55, 0xa0, 0xb9, 0x80, 0x44, 0x6d, 0xd2, 0x45, 0x3c, 0x39, + 0x5a, 0x3e, 0xe7, 0xaa, 0xd6, 0x1f, 0xd6, 0xba, 0x48, 0xc0, + 0xa1, 0xdf, 0xb1, 0xa3, 0x97, 0x4e, 0xaa, 0xe6, 0xb3, 0x10, + 0x63, 0x2a, 0xcf, 0x25, 0x28, 0x20, 0xa2, 0x39 }, + { 0x4b, 0xb8, 0xc6, 0xfc, 0x40, 0xaf, 0xc6, 0x84, 0xb3, 0x28, + 0x03, 0x60, 0x79, 0x0b, 0x7a, 0x04, 0x05, 0x75, 0x90, 0x47, + 0xfc, 0x58, 0x5e, 0x46, 0x07, 0x1b, 0xd5, 0xfc, 0x11, 0xd4, + 0x01, 0x94, 0x34, 0xcc, 0x13, 0x4a, 0xfc, 0xd2, 0xc4, 0x04, + 0xe7, 0x36, 0x94, 0xbc, 0xf3, 0x69, 0x3a, 0x18, 0xcc, 0x12, + 0xa4, 0x9d, 0x56, 0x83, 0x3e, 0xdc, 0x65, 0xed, 0x39, 0xc7, + 0x59, 0x4d, 0x02, 0xb3, 0xb4, 0xc8, 0x0e, 0x2f, 0xff, 0xb8, + 0x16, 0x5d, 0x91, 0xcd, 0xd7, 0x54, 0x75, 0x0f, 0x28, 0xe4, + 0xb1, 0xa1, 0xf7, 0x0b, 0x51, 0x2f, 0x79, 0x7c, 0xa5, 0xab, + 0x62, 0xb8, 0xd9, 0x08, 0x97, 0xb1, 0x95, 0x10, 0x44, 0xe6, + 0xc3, 0x43, 0xf5, 0x39, 0x2e, 0x56, 0x2e, 0x7d, 0xe7, 0xc0, + 0xf6, 0xdb, 0xf3, 0xe3, 0x93, 0x8a, 0x00, 0x9c, 0x56, 0x64, + 0xd6, 0xbe, 0x36, 0xb9, 0xe1, 0x45, 0xb1, 0xd7 }, + { 0x36, 0x99, 0xa8, 0x81, 0xb6, 0xa7, 0x7e, 0x78, 0x2e, 0x8f, + 0xea, 0x9e, 0x9a, 0x13, 0x5d, 0x89, 0xd4, 0xf9, 0xcf, 0xa5, + 0x6c, 0x43, 0x28, 0x27, 0x99, 0xa3, 0xe8, 0x8d, 0x10, 0xff, + 0xa6, 0x90, 0xc0, 0x3f, 0x5d, 0xf9, 0x59, 0x12, 0x0b, 0xfc, + 0x56, 0x96, 0xd5, 0x45, 0x36, 0xd5, 0x05, 0x29, 0xac, 0xd1, + 0xd6, 0xf2, 0x70, 0x9d, 0xc5, 0x90, 0x86, 0x0c, 0x21, 0x8a, + 0xc8, 0x2c, 0x9c, 0x16, 0x2f, 0x12, 0x4e, 0x3b, 0x29, 0x35, + 0x19, 0xeb, 0xeb, 0x8a, 0xf4, 0x44, 0x01, 0x99, 0xb5, 0x3c, + 0x48, 0x7f, 0xe9, 0xcd, 0x9f, 0xeb, 0xc0, 0x05, 0x39, 0xe4, + 0xec, 0xf0, 0x8c, 0xb8, 0x14, 0x39, 0x37, 0xe5, 0xb6, 0xd6, + 0x60, 0x07, 0x27, 0x3b, 0xfe, 0xa3, 0x66, 0xc0, 0xa9, 0x36, + 0x9c, 0x6e, 0x69, 0x68, 0xa4, 0x0d, 0xb1, 0x33, 0xc9, 0xde, + 0x31, 0x20, 0xe2, 0xdd, 0xfd, 0x0f, 0x87, 0x96 }, + { 0x4f, 0x3a, 0x4b, 0x03, 0x20, 0x8a, 0xff, 0x8b, 0x1d, 0xf0, + 0x8e, 0x9f, 0x82, 0x53, 0x51, 0x87, 0x72, 0x71, 0xf3, 0x9e, + 0x5e, 0xc3, 0x1c, 0xaa, 0xca, 0x94, 0x75, 0xe9, 0x78, 0x1c, + 0xb4, 0x73, 0xb9, 0xe0, 0x8e, 0xc0, 0x3d, 0x7a, 0x4d, 0x52, + 0x83, 0x8d, 0xaa, 0x54, 0xd3, 0xb7, 0xc2, 0x35, 0xee, 0x2c, + 0xd2, 0x0d, 0x6a, 0x8d, 0x4f, 0x9f, 0x8c, 0x23, 0xc2, 0x5f, + 0x14, 0x26, 0xa8, 0x0d, 0x79, 0x5e, 0xc6, 0xcb, 0xc5, 0xe6, + 0x7c, 0x02, 0x94, 0xdb, 0xdf, 0xe2, 0xe9, 0xac, 0x3a, 0x75, + 0x82, 0xc5, 0x3a, 0x7e, 0x88, 0x34, 0xe9, 0xc5, 0xcb, 0xde, + 0x41, 0x6e, 0x20, 0x58, 0xb3, 0x7f, 0x06, 0xc1, 0x71, 0x51, + 0x4f, 0x7c, 0xbf, 0x4d, 0xb7, 0xe2, 0xe9, 0xb3, 0x65, 0x37, + 0x10, 0x6f, 0xe9, 0xcf, 0x3a, 0x2d, 0xf1, 0xd2, 0x81, 0x54, + 0x5b, 0xca, 0x33, 0x72, 0x1e, 0xb1, 0xc6, 0x4d }, + { 0x6d, 0x87, 0x44, 0x46, 0xa6, 0xd1, 0x79, 0xfd, 0x9e, 0x52, + 0x5c, 0x03, 0x0b, 0x5a, 0x7b, 0x80, 0x44, 0xf2, 0x4f, 0x4a, + 0x52, 0xae, 0x84, 0xdb, 0x49, 0xbe, 0x1c, 0x18, 0x7a, 0x02, + 0x32, 0x5e, 0x13, 0x15, 0x2b, 0x3e, 0xb0, 0x20, 0x60, 0x7a, + 0x56, 0xd7, 0x14, 0xab, 0xd1, 0x04, 0x9d, 0xf4, 0xc4, 0x3d, + 0x54, 0xfa, 0x5a, 0xc4, 0x88, 0xaa, 0x9f, 0x53, 0x59, 0xfd, + 0xdf, 0x86, 0xe0, 0xa2, 0xf9, 0x60, 0x38, 0x68, 0x6d, 0xf2, + 0x0d, 0x7c, 0xb4, 0xec, 0xd5, 0xdb, 0xd7, 0x2b, 0x21, 0xc1, + 0x24, 0x54, 0xbb, 0x9c, 0x42, 0x1e, 0xec, 0x37, 0xb9, 0x63, + 0x4a, 0x97, 0xe3, 0xe0, 0xf1, 0x6e, 0xb1, 0x14, 0x63, 0x4e, + 0x07, 0xd8, 0xe3, 0x11, 0x8b, 0x0f, 0x98, 0x52, 0xaf, 0xb3, + 0x6d, 0x1d, 0x23, 0xe3, 0x7f, 0xa6, 0xda, 0x22, 0x6d, 0x4e, + 0x0f, 0x7b, 0x81, 0x07, 0x1e, 0xd0, 0x95, 0xf8 }, + { 0x3c, 0xf3, 0x84, 0xc9, 0xff, 0x9c, 0x56, 0x09, 0x95, 0xa4, + 0xac, 0xa9, 0x7b, 0xb7, 0x0f, 0x3d, 0x95, 0xa3, 0x97, 0x34, + 0x90, 0x4f, 0xc5, 0x31, 0x17, 0xf5, 0x14, 0xad, 0x07, 0xac, + 0x75, 0x9d, 0x0f, 0x5d, 0x79, 0x1f, 0xaf, 0x08, 0x48, 0xbc, + 0x5c, 0xaa, 0xc2, 0x70, 0x7d, 0xeb, 0x85, 0x80, 0xa0, 0xed, + 0xc4, 0xa7, 0x42, 0xc1, 0xd2, 0x13, 0xe0, 0x3f, 0x1f, 0x34, + 0xf3, 0xfd, 0x3b, 0x74, 0x6e, 0x1a, 0x0f, 0x01, 0xf5, 0x7f, + 0x7c, 0xeb, 0x27, 0xfb, 0xa8, 0x76, 0xcf, 0x28, 0xcc, 0xc2, + 0x05, 0xf6, 0xdf, 0x92, 0x31, 0xae, 0x94, 0xe4, 0x99, 0xc2, + 0xb4, 0xdc, 0xf8, 0xd4, 0x4f, 0x12, 0x4e, 0x19, 0xe0, 0xdf, + 0x88, 0xfe, 0xe9, 0x1a, 0x71, 0xa7, 0x5a, 0x6d, 0x9d, 0xc6, + 0x9e, 0xa1, 0x1f, 0xd5, 0x31, 0x6c, 0x37, 0x81, 0xcc, 0xc8, + 0xd2, 0x9d, 0x07, 0xaa, 0xbe, 0x9a, 0x42, 0xf5 }, + { 0x2b, 0x24, 0x88, 0x50, 0xee, 0x73, 0xdf, 0x26, 0x3c, 0x67, + 0xe7, 0x3c, 0x71, 0x03, 0x07, 0x70, 0x8c, 0x8c, 0x54, 0x05, + 0xd8, 0x56, 0x0a, 0x65, 0x26, 0x48, 0x28, 0xd9, 0xd4, 0x55, + 0xe8, 0x20, 0x85, 0x52, 0x5d, 0x65, 0xbe, 0x99, 0xa6, 0x08, + 0x09, 0x98, 0x06, 0xbb, 0x74, 0x7e, 0x5d, 0x2a, 0xf4, 0xd9, + 0x7a, 0xfb, 0x14, 0x83, 0x21, 0xbd, 0xf3, 0x80, 0xfc, 0xb5, + 0x05, 0xe4, 0x51, 0xe9, 0x51, 0x17, 0x4e, 0x1a, 0x57, 0x7b, + 0x24, 0xf4, 0xb6, 0xc5, 0xd9, 0x91, 0x62, 0x93, 0x62, 0xe1, + 0x1e, 0xf3, 0x39, 0xb7, 0xfe, 0x24, 0xf3, 0x9a, 0x90, 0x58, + 0x0b, 0x90, 0xce, 0x26, 0xa8, 0xe1, 0xca, 0x86, 0x02, 0xa8, + 0x79, 0xb2, 0x09, 0xf7, 0x2b, 0x4a, 0x1b, 0x8d, 0xe7, 0x2b, + 0xf7, 0xb3, 0x49, 0x72, 0x17, 0x42, 0x67, 0x6b, 0x03, 0x99, + 0x70, 0x05, 0x06, 0xba, 0xce, 0x1f, 0xc9, 0xe3 }, + { 0x93, 0x8b, 0x3b, 0xcc, 0x6a, 0x3a, 0xc2, 0x15, 0x17, 0x26, + 0x1e, 0xce, 0x74, 0x41, 0x4a, 0x1c, 0xa1, 0x08, 0xb5, 0x4d, + 0x1d, 0x46, 0x21, 0xd1, 0x52, 0x48, 0x67, 0x58, 0xe8, 0x1b, + 0x0d, 0xf0, 0xac, 0x07, 0xf2, 0xa3, 0x73, 0xce, 0x49, 0xe8, + 0xb2, 0xf9, 0xd4, 0x41, 0xc1, 0x26, 0xbc, 0xbe, 0x63, 0x48, + 0xf7, 0xf2, 0xe6, 0x6c, 0x66, 0xf6, 0x4b, 0x90, 0x36, 0x3d, + 0x74, 0xc6, 0x69, 0x75, 0x12, 0x48, 0xc5, 0x8f, 0x62, 0xd8, + 0x43, 0xb9, 0x6c, 0x56, 0xb8, 0xef, 0x81, 0x0f, 0xcc, 0x6c, + 0xdb, 0x0e, 0x58, 0x7c, 0xb5, 0xed, 0x29, 0x45, 0x07, 0x1a, + 0x02, 0x10, 0xa6, 0xb2, 0x34, 0x4a, 0x52, 0xc2, 0x07, 0xd6, + 0xa8, 0xb2, 0x3e, 0x40, 0x07, 0xa2, 0x86, 0x19, 0x1f, 0x2c, + 0xa1, 0xc7, 0x78, 0x22, 0x4c, 0x18, 0x4f, 0xb4, 0x10, 0xb2, + 0x21, 0x73, 0xcd, 0xe6, 0x85, 0x41, 0x15, 0x9f }, + { 0x6c, 0xff, 0x58, 0xa5, 0xd9, 0xe8, 0x9d, 0x6b, 0x24, 0xe8, + 0xc9, 0xed, 0x15, 0x30, 0x73, 0x41, 0x98, 0x47, 0x46, 0x07, + 0x84, 0xe8, 0x3c, 0x06, 0x8a, 0xe7, 0xe0, 0xe8, 0xf2, 0xda, + 0xce, 0x56, 0x79, 0x70, 0x17, 0x9b, 0x93, 0x74, 0x7e, 0xa5, + 0x60, 0xf7, 0xa1, 0xb5, 0xa5, 0x5b, 0x44, 0xb7, 0xae, 0x46, + 0x55, 0xe5, 0x74, 0xd6, 0xeb, 0x5f, 0xb5, 0x66, 0xb7, 0x90, + 0x92, 0x53, 0x3d, 0x97, 0x74, 0x02, 0x05, 0x76, 0x56, 0xf7, + 0x6d, 0x5f, 0x81, 0x8c, 0x2a, 0xec, 0xf5, 0x54, 0x2d, 0xf5, + 0xe6, 0x0f, 0xb6, 0x1a, 0xda, 0x0b, 0xb6, 0x4c, 0xf3, 0x04, + 0xfc, 0x58, 0x49, 0x10, 0x1b, 0x06, 0x1c, 0x3a, 0x04, 0x34, + 0xaa, 0xa6, 0x57, 0xa9, 0x97, 0x08, 0x96, 0x06, 0xdc, 0xd7, + 0x3a, 0xcb, 0x8e, 0x65, 0xfb, 0x2a, 0x80, 0xe8, 0x80, 0x36, + 0xa9, 0xe4, 0xa1, 0x6b, 0xe4, 0xde, 0xd3, 0x40 }, + { 0x5f, 0xe4, 0xac, 0x8f, 0x31, 0xb7, 0x93, 0x27, 0x5f, 0x67, + 0xf8, 0xaa, 0xeb, 0x93, 0x6a, 0xf7, 0x3c, 0x62, 0x7f, 0xc5, + 0x48, 0x63, 0xb3, 0xac, 0xc3, 0x3f, 0x83, 0xd8, 0x04, 0x6e, + 0x2e, 0x48, 0x7f, 0xa8, 0x47, 0xe6, 0x6e, 0xc1, 0x3f, 0x84, + 0x13, 0x3d, 0x54, 0x44, 0xcc, 0xc8, 0xc7, 0xdf, 0xb1, 0xd4, + 0x04, 0xdc, 0x38, 0xd3, 0x17, 0xe0, 0x0b, 0x68, 0x0b, 0x0a, + 0xff, 0x18, 0x20, 0xb8, 0xfb, 0xbb, 0x2f, 0xa6, 0xd0, 0x23, + 0x3f, 0xdc, 0x35, 0x00, 0x10, 0x13, 0x80, 0x9f, 0x50, 0xf4, + 0x05, 0x5c, 0x3b, 0x1e, 0x9b, 0x45, 0x38, 0x96, 0xd1, 0x48, + 0x46, 0x7d, 0x60, 0x7d, 0x97, 0x98, 0x25, 0x5e, 0x90, 0x7a, + 0x03, 0xe4, 0x15, 0xb7, 0xf7, 0x99, 0x8d, 0x0b, 0x09, 0xbd, + 0x88, 0x05, 0xe1, 0xd1, 0xf2, 0x25, 0x1d, 0x2f, 0xe7, 0xd6, + 0x50, 0x8c, 0x01, 0xb0, 0x03, 0xe5, 0x1f, 0x68 }, + { 0x81, 0x37, 0x71, 0x64, 0x12, 0x1c, 0x05, 0x48, 0x20, 0x93, + 0x1c, 0x89, 0xeb, 0x2a, 0xbd, 0xad, 0x86, 0xe2, 0x54, 0xc9, + 0x69, 0x77, 0xa4, 0x20, 0x29, 0x0d, 0x95, 0xf2, 0x20, 0x10, + 0xf2, 0xe7, 0x8d, 0xcc, 0x0c, 0x42, 0x49, 0xa2, 0x78, 0x64, + 0x69, 0xc9, 0xcf, 0xb0, 0xb1, 0x84, 0xce, 0xe8, 0xdd, 0x8d, + 0xec, 0x2b, 0x34, 0xe7, 0xe7, 0x12, 0x55, 0xc3, 0x85, 0x93, + 0x00, 0xbb, 0x42, 0xdc, 0xba, 0xfc, 0x1d, 0x34, 0x6b, 0x83, + 0xe9, 0x5c, 0x18, 0x63, 0x7c, 0x7c, 0x7f, 0xef, 0x96, 0xd0, + 0x06, 0x6c, 0x55, 0xfb, 0x99, 0xa4, 0x6e, 0xaf, 0x54, 0x54, + 0xa7, 0xd4, 0x69, 0x37, 0x1c, 0x95, 0xfd, 0xd1, 0x1f, 0x04, + 0x9c, 0x22, 0xbc, 0xd4, 0x7b, 0x01, 0x87, 0x26, 0x6f, 0xb0, + 0x7b, 0x4a, 0x05, 0xdb, 0x12, 0xa3, 0xad, 0x5c, 0x7e, 0xd4, + 0x58, 0x1a, 0xa4, 0xbf, 0x8b, 0x6f, 0x40, 0x1e }, + { 0x79, 0xc2, 0x80, 0xee, 0x9c, 0xd2, 0xdb, 0x98, 0xbf, 0x24, + 0x73, 0x5c, 0xd2, 0xf1, 0x46, 0xfe, 0x4d, 0x7b, 0xb3, 0x61, + 0x82, 0xe8, 0xc5, 0xba, 0x92, 0x32, 0xb3, 0x7e, 0xa6, 0x00, + 0x85, 0x15, 0x31, 0xfc, 0x58, 0x82, 0xf8, 0xf2, 0xc0, 0x75, + 0x8c, 0xcd, 0x79, 0xb0, 0x67, 0x62, 0x2c, 0x9e, 0xe0, 0xcf, + 0x16, 0xee, 0xc4, 0x7c, 0xa8, 0x96, 0xd7, 0xf6, 0x58, 0x52, + 0x7c, 0x25, 0x0c, 0x78, 0x57, 0x3e, 0xbd, 0x17, 0x51, 0xfd, + 0xff, 0x34, 0x56, 0x2a, 0xbc, 0xfa, 0x67, 0x7d, 0x0a, 0x92, + 0xba, 0xda, 0xd7, 0xb1, 0x02, 0xf7, 0x1b, 0xef, 0x3e, 0x2c, + 0xfb, 0xd9, 0xb3, 0x85, 0x38, 0x2a, 0x24, 0x2f, 0xa7, 0xf9, + 0x62, 0x74, 0x46, 0x17, 0x5f, 0x02, 0x73, 0x7d, 0x48, 0x76, + 0xee, 0xdf, 0x6e, 0x13, 0x88, 0xc2, 0x10, 0x78, 0xa7, 0xad, + 0x62, 0x66, 0xb2, 0x5e, 0x9c, 0x5a, 0x8e, 0xdf }, + { 0x75, 0x80, 0x73, 0xa4, 0xa9, 0xe3, 0xff, 0x4f, 0x9f, 0xd9, + 0xf7, 0x91, 0x52, 0xc8, 0xf4, 0x08, 0x3f, 0x9d, 0xd5, 0x78, + 0xb5, 0xbe, 0x5b, 0xe4, 0x26, 0xdb, 0xc5, 0x8e, 0x73, 0xe4, + 0x0e, 0x3b, 0xe0, 0xb0, 0x44, 0x26, 0xb5, 0x1e, 0x38, 0xbc, + 0x3e, 0x3a, 0xf3, 0xc6, 0x9c, 0x66, 0x27, 0x4b, 0x1b, 0x2b, + 0xf8, 0x9f, 0x18, 0x3e, 0xae, 0x42, 0x6c, 0x51, 0x23, 0x5c, + 0xce, 0xe6, 0xb6, 0x06, 0x57, 0x0c, 0x5b, 0xb7, 0x81, 0x6b, + 0x62, 0x30, 0x24, 0xd2, 0x8c, 0xa0, 0x6b, 0xc1, 0x4b, 0x2e, + 0x17, 0xaa, 0x5a, 0xea, 0x8e, 0x1a, 0xb8, 0x20, 0x73, 0x39, + 0xe7, 0x21, 0x67, 0x6d, 0xe2, 0x50, 0xab, 0x83, 0x89, 0x97, + 0x82, 0xc1, 0x00, 0x1c, 0xac, 0xf0, 0x64, 0xdc, 0x9f, 0xc4, + 0x88, 0x5e, 0xa8, 0xc0, 0x49, 0x16, 0xb0, 0x4a, 0xc4, 0x8e, + 0xbd, 0xcc, 0x82, 0x03, 0xf2, 0xb4, 0x81, 0x22 }, + { 0x3f, 0x3e, 0x34, 0x58, 0xfa, 0xf6, 0x6a, 0xa8, 0x93, 0x42, + 0xa7, 0xfa, 0x86, 0x61, 0xd3, 0x2d, 0xfb, 0xab, 0x9f, 0xa1, + 0x49, 0xe9, 0xe1, 0x04, 0x06, 0xe5, 0x25, 0x99, 0xb4, 0xfd, + 0x4c, 0x45, 0x2d, 0x21, 0x64, 0x76, 0x08, 0xc7, 0xf3, 0xff, + 0x3d, 0x0b, 0x10, 0xbf, 0xfd, 0x7b, 0xe6, 0xc7, 0xbd, 0xa4, + 0xc8, 0x24, 0x29, 0x7e, 0xe2, 0x03, 0x4b, 0xc0, 0xd0, 0x30, + 0xa9, 0xfd, 0x97, 0x83, 0x14, 0x64, 0x6e, 0x53, 0xcf, 0x4b, + 0x84, 0x32, 0xde, 0xf4, 0x44, 0xc1, 0x13, 0x66, 0x84, 0x3a, + 0x56, 0xd5, 0x75, 0x0c, 0x3c, 0x47, 0x4d, 0xbd, 0x2e, 0x16, + 0x6d, 0xe7, 0xc8, 0xa0, 0xe2, 0x4c, 0xc5, 0xd1, 0x8a, 0x2a, + 0x75, 0x53, 0x66, 0x07, 0xe8, 0x4b, 0xd3, 0x85, 0xac, 0x79, + 0x54, 0x13, 0xf2, 0x06, 0xbf, 0xd6, 0x13, 0xa2, 0xa1, 0xb6, + 0x7d, 0x27, 0xb0, 0x57, 0x86, 0x91, 0xca, 0x22 }, + { 0x64, 0x0d, 0x20, 0xc4, 0x34, 0xc2, 0x94, 0xef, 0x1e, 0x9e, + 0x17, 0xed, 0x6c, 0x48, 0x29, 0x5e, 0x44, 0x1e, 0xed, 0xe2, + 0x2a, 0x0e, 0x2f, 0x63, 0x56, 0xd9, 0xf8, 0x07, 0x3c, 0x83, + 0x14, 0xae, 0xe7, 0x7b, 0x2e, 0x4c, 0xc1, 0x43, 0x3d, 0x67, + 0xc8, 0xee, 0x32, 0x3e, 0x30, 0xc7, 0x8d, 0x2b, 0xd8, 0x2d, + 0x5e, 0x9f, 0x65, 0x45, 0x7d, 0x95, 0x87, 0x34, 0xed, 0xdc, + 0xfc, 0x40, 0xe8, 0x1b, 0xb7, 0x63, 0x87, 0x58, 0x35, 0x29, + 0x2c, 0x32, 0xb8, 0xfa, 0x29, 0x56, 0x19, 0x9e, 0x5f, 0x98, + 0xf9, 0x9e, 0xe9, 0xdf, 0xed, 0xe1, 0xf0, 0x9c, 0x8a, 0x69, + 0x65, 0x53, 0xfd, 0x9b, 0xb9, 0xc3, 0x42, 0x3e, 0xca, 0x49, + 0x51, 0x5a, 0x29, 0x35, 0x02, 0x76, 0xcd, 0x9c, 0x9b, 0xf4, + 0xef, 0xf5, 0xb6, 0x77, 0xd4, 0xac, 0x49, 0xdf, 0x64, 0xeb, + 0x51, 0xec, 0x35, 0xaf, 0x95, 0x15, 0x97, 0xaa }, + { 0x0f, 0x9c, 0x1c, 0xa8, 0xc0, 0xd9, 0x28, 0x16, 0xb9, 0x68, + 0x90, 0x2a, 0xc7, 0x2e, 0x05, 0xc1, 0x8e, 0xe4, 0x0d, 0x66, + 0x34, 0x9a, 0xa6, 0x39, 0xf3, 0x9e, 0x46, 0x09, 0x91, 0x2b, + 0xd1, 0x7a, 0xdf, 0xe5, 0x2b, 0x11, 0x87, 0x6c, 0x29, 0xc3, + 0x69, 0xa0, 0x74, 0xb6, 0x28, 0x57, 0x42, 0xe8, 0xb6, 0x30, + 0x2b, 0x33, 0x0f, 0x32, 0xd3, 0x67, 0x8b, 0xc4, 0x09, 0x4d, + 0x57, 0x46, 0x0e, 0x65, 0xca, 0x8e, 0x35, 0x1d, 0xfc, 0x9f, + 0x1b, 0x73, 0x4e, 0x46, 0x1a, 0xca, 0x6d, 0x4a, 0xd4, 0xc2, + 0x29, 0xb6, 0xef, 0x13, 0x30, 0x3f, 0x07, 0xa8, 0x8d, 0x9d, + 0x47, 0xdc, 0x25, 0x49, 0xfc, 0x46, 0xd8, 0x0b, 0xdc, 0xfc, + 0x1d, 0xe5, 0x0d, 0xb7, 0xb3, 0x6e, 0x74, 0x07, 0x45, 0xac, + 0xd5, 0x2a, 0x07, 0x4c, 0x35, 0x45, 0xf3, 0x15, 0x05, 0x3a, + 0x4e, 0x9a, 0x0b, 0x8e, 0x32, 0x84, 0xd5, 0x13 }, + { 0x7e, 0x31, 0xc1, 0x2f, 0x45, 0xd3, 0x6e, 0xc5, 0x34, 0xbd, + 0x9b, 0xa7, 0x09, 0x8a, 0x82, 0x40, 0x9b, 0x9a, 0xce, 0xc6, + 0xe6, 0xe6, 0xff, 0x33, 0x63, 0x94, 0x9c, 0x91, 0x3e, 0x72, + 0x63, 0xf8, 0x3d, 0xb4, 0x7f, 0x70, 0xc6, 0x5e, 0x3e, 0xaf, + 0x48, 0x59, 0x3d, 0xb8, 0xb6, 0x63, 0x0f, 0xb1, 0x83, 0x20, + 0x27, 0x89, 0xd7, 0x69, 0x4f, 0x9b, 0x58, 0xad, 0x74, 0xb0, + 0x7b, 0x29, 0x0d, 0xfd, 0x5e, 0xa6, 0x0d, 0xfa, 0x66, 0x08, + 0xb3, 0x88, 0xcf, 0x25, 0x67, 0x30, 0x0a, 0x3b, 0x13, 0x26, + 0x73, 0x13, 0x99, 0xa3, 0x0b, 0x4d, 0xca, 0x09, 0x4b, 0x63, + 0x88, 0x54, 0xd5, 0x37, 0x34, 0x51, 0x72, 0xc9, 0x18, 0xcb, + 0x65, 0xe4, 0x08, 0xf9, 0x13, 0xa3, 0x20, 0xd8, 0x97, 0xf0, + 0xc5, 0xcc, 0xb6, 0xaa, 0x53, 0x47, 0x15, 0xd3, 0x62, 0x8c, + 0x1e, 0xbb, 0xaa, 0xb3, 0x67, 0x43, 0x3d, 0xf3 }, + { 0x1a, 0x21, 0x9c, 0x45, 0x32, 0x6d, 0x53, 0x57, 0x4d, 0xe4, + 0x1a, 0x30, 0x7e, 0x23, 0xba, 0x60, 0xac, 0x19, 0x6c, 0xf5, + 0x33, 0x7c, 0xa1, 0xbb, 0xc5, 0x3b, 0x7e, 0x03, 0xfc, 0x4f, + 0xbb, 0x2e, 0x86, 0xbe, 0x92, 0xd3, 0xef, 0xc4, 0xd9, 0x3c, + 0x4f, 0x64, 0xee, 0x41, 0x0e, 0x2b, 0x37, 0x47, 0x74, 0x1f, + 0x0d, 0x73, 0x15, 0x6c, 0x4e, 0xe1, 0xfa, 0x91, 0x92, 0x5d, + 0xdc, 0xc7, 0x22, 0x23, 0x76, 0xb3, 0xbf, 0xad, 0xfc, 0x94, + 0x70, 0x76, 0x33, 0x6e, 0x30, 0x9e, 0xde, 0x13, 0xfd, 0x1b, + 0x7a, 0x46, 0x31, 0xbe, 0x79, 0x69, 0xa1, 0x0d, 0xfd, 0xd5, + 0xfc, 0x30, 0xcf, 0xfb, 0xb4, 0x06, 0x66, 0x0c, 0x8d, 0xfa, + 0x95, 0x9c, 0xb3, 0xbc, 0xb9, 0xc3, 0x00, 0x5f, 0x94, 0x43, + 0x1f, 0x97, 0x1e, 0xfa, 0xcb, 0x00, 0x24, 0xab, 0x61, 0xd8, + 0xbe, 0x28, 0x1d, 0x68, 0x0d, 0xfd, 0x2d, 0xd7 }, + { 0x17, 0xaa, 0xa9, 0x99, 0xbc, 0x90, 0x19, 0x2f, 0xe0, 0x2b, + 0xcf, 0x77, 0xb6, 0xd0, 0xbf, 0x93, 0x6a, 0xc1, 0x53, 0x7e, + 0xf8, 0x03, 0x06, 0x62, 0xf0, 0x4c, 0xe5, 0x90, 0xbe, 0xa6, + 0x94, 0x03, 0x73, 0xcd, 0x50, 0x2d, 0x43, 0x74, 0x42, 0xd1, + 0x92, 0xff, 0x23, 0x29, 0x95, 0x56, 0x6b, 0xe6, 0x42, 0x2a, + 0x33, 0x0a, 0xc4, 0xf8, 0x9c, 0xb8, 0x95, 0x3e, 0x69, 0xb2, + 0x5b, 0x53, 0xf1, 0xc3, 0x4d, 0x6c, 0x45, 0x7f, 0x69, 0xe5, + 0x7f, 0x8e, 0xfd, 0x0d, 0xe2, 0xcb, 0x2b, 0x0c, 0x81, 0x20, + 0x78, 0xe1, 0x0e, 0xc1, 0x82, 0xcc, 0x60, 0x43, 0x99, 0x7c, + 0x8e, 0x35, 0xa2, 0xfc, 0x0e, 0xdb, 0xc0, 0xce, 0xc2, 0xe2, + 0xff, 0xdc, 0x77, 0x71, 0xc2, 0x63, 0x90, 0x67, 0x3d, 0x8a, + 0x19, 0x2f, 0x2e, 0x23, 0x18, 0x06, 0x7b, 0x6c, 0x99, 0x63, + 0xfd, 0xcf, 0x7e, 0xf8, 0xaa, 0x4d, 0xb0, 0xbc }, + { 0x6b, 0x28, 0x2a, 0xf0, 0xa5, 0xf3, 0xb2, 0x4a, 0xfb, 0xd5, + 0xff, 0x8c, 0x22, 0x64, 0x74, 0xbc, 0x3b, 0x4b, 0x2d, 0x8f, + 0xbe, 0x76, 0x08, 0xef, 0xa2, 0x8f, 0xd8, 0x6b, 0xa5, 0xbf, + 0xd2, 0x67, 0x0f, 0x45, 0x6a, 0x4c, 0x0f, 0x97, 0xfa, 0x97, + 0x78, 0xbe, 0xdd, 0xe1, 0x21, 0x4f, 0x96, 0xc5, 0xe8, 0x92, + 0x5e, 0x91, 0xb4, 0x3b, 0x68, 0x13, 0x0a, 0x44, 0xa0, 0xe5, + 0x0e, 0x4a, 0x49, 0xbe, 0x94, 0xb5, 0x5c, 0x87, 0x4f, 0xf0, + 0x6b, 0x25, 0xf4, 0x00, 0xac, 0x1e, 0xdd, 0x20, 0x45, 0xc0, + 0x72, 0x17, 0xfd, 0xd9, 0xbd, 0xd6, 0x72, 0xcf, 0x23, 0xf9, + 0x9c, 0x36, 0xdd, 0x95, 0xf7, 0xa9, 0xa6, 0xff, 0x3b, 0x35, + 0xea, 0x17, 0xe2, 0x7c, 0x1a, 0x14, 0x40, 0xe5, 0x5b, 0x88, + 0x46, 0x2f, 0x83, 0x5d, 0xee, 0x43, 0x3b, 0x94, 0x68, 0x51, + 0x0d, 0x3d, 0x56, 0x43, 0x8e, 0x55, 0xdb, 0x2e }, + { 0x6d, 0x4f, 0x5d, 0x23, 0x54, 0x70, 0x6e, 0xbf, 0xb6, 0x64, + 0xf5, 0x29, 0xee, 0x8d, 0x97, 0x62, 0x13, 0xe6, 0x44, 0x27, + 0x2b, 0x41, 0x2d, 0xfb, 0x42, 0x9d, 0x16, 0x7b, 0x48, 0x02, + 0xc2, 0x45, 0x76, 0xa5, 0x45, 0xc6, 0xc2, 0xbe, 0x9f, 0x3d, + 0x80, 0xb0, 0xbd, 0x68, 0xb2, 0x30, 0x6b, 0x0e, 0xee, 0x37, + 0x8b, 0xf4, 0xa8, 0x02, 0x45, 0xde, 0x69, 0xe9, 0xbe, 0x5c, + 0x59, 0x45, 0x50, 0x88, 0x2a, 0x2b, 0x2d, 0x2d, 0x0b, 0xfd, + 0x87, 0xb1, 0x10, 0x2d, 0xdf, 0x09, 0x8f, 0xd2, 0xfb, 0x64, + 0x14, 0x5d, 0x94, 0x66, 0x95, 0xa7, 0xac, 0xb4, 0x91, 0x14, + 0x14, 0xd3, 0x08, 0x3e, 0x16, 0xc4, 0x3f, 0x94, 0x66, 0xd3, + 0x75, 0x54, 0x78, 0x33, 0x72, 0xbd, 0x6e, 0x3d, 0xeb, 0x44, + 0x68, 0x42, 0x59, 0x1c, 0x38, 0xd6, 0xa4, 0x45, 0xe2, 0x8c, + 0x78, 0xfc, 0x02, 0x5f, 0x63, 0x41, 0xa5, 0x95 }, + { 0x4a, 0xaf, 0x0b, 0x4f, 0xd6, 0x5d, 0x34, 0xad, 0x6e, 0xda, + 0x93, 0xc4, 0x40, 0xdb, 0x81, 0xb4, 0x55, 0x1f, 0xc8, 0x72, + 0xb9, 0x97, 0x7d, 0x90, 0xe7, 0x8b, 0xd7, 0xa5, 0x74, 0x07, + 0x0b, 0xb3, 0x9c, 0x2a, 0x5e, 0x92, 0x58, 0xf3, 0x75, 0x80, + 0xb2, 0x08, 0x51, 0x70, 0x01, 0x16, 0xde, 0xb6, 0xe0, 0xfe, + 0x46, 0x78, 0x24, 0xd0, 0x5f, 0x74, 0xd2, 0xf0, 0xa7, 0xdd, + 0x2f, 0x07, 0xae, 0xa3, 0xa9, 0xe3, 0xd5, 0x9f, 0x79, 0xb7, + 0x8a, 0x26, 0x72, 0xeb, 0xa5, 0x7e, 0x88, 0x18, 0x43, 0x4d, + 0x02, 0x8d, 0xca, 0x62, 0x63, 0xc9, 0x64, 0x87, 0x3e, 0x30, + 0x8e, 0x6f, 0xf3, 0x7d, 0xcb, 0xa6, 0x33, 0x5c, 0xe6, 0xce, + 0xa7, 0xac, 0x78, 0x1e, 0x0a, 0x12, 0x6d, 0x42, 0xb3, 0xb8, + 0x1e, 0x5b, 0xfd, 0xc8, 0x07, 0xe0, 0x7b, 0xb6, 0xd0, 0xbf, + 0x35, 0xc8, 0xf2, 0xb6, 0x00, 0xba, 0x9f, 0x88 }, + { 0x8b, 0x2c, 0xbd, 0x39, 0x82, 0xbc, 0x63, 0x37, 0xa1, 0xd4, + 0x16, 0x5b, 0x1c, 0x2e, 0x14, 0xd7, 0xf9, 0x9c, 0x52, 0x6b, + 0xd6, 0xeb, 0xf3, 0xa9, 0x14, 0x4d, 0xad, 0xe1, 0xa7, 0x21, + 0xec, 0xd9, 0x72, 0xae, 0xc5, 0x77, 0xb2, 0xc1, 0x1f, 0xb1, + 0x16, 0xde, 0xde, 0x4e, 0x09, 0x70, 0x18, 0xc7, 0x11, 0xa5, + 0xa8, 0x04, 0x8b, 0xe4, 0x4a, 0xa0, 0x06, 0xf9, 0x83, 0x6b, + 0x85, 0x72, 0x86, 0x36, 0x64, 0xde, 0x98, 0x9a, 0x25, 0xbc, + 0x04, 0xdb, 0xc1, 0xcd, 0xd5, 0x2f, 0xa0, 0x61, 0xdb, 0xdb, + 0x4e, 0xef, 0x38, 0x6b, 0x8b, 0xd9, 0xc4, 0x66, 0xb2, 0x49, + 0x0f, 0xc0, 0x92, 0x1d, 0x32, 0xdd, 0xd8, 0xdb, 0xfa, 0xb5, + 0x17, 0x3b, 0x86, 0x85, 0xef, 0x3c, 0xae, 0x87, 0x8f, 0xa3, + 0xec, 0x58, 0xb0, 0x9e, 0x7d, 0xad, 0xbc, 0x18, 0x1e, 0xad, + 0x9b, 0xef, 0x25, 0x06, 0x35, 0x14, 0xc7, 0xaf }, + { 0x57, 0xe2, 0x83, 0x04, 0x7d, 0xbe, 0x36, 0x70, 0x22, 0x0e, + 0xea, 0xec, 0x8f, 0xc5, 0xc8, 0x31, 0x86, 0xc2, 0x82, 0x4e, + 0x87, 0x4c, 0xcd, 0x58, 0x39, 0x9a, 0x79, 0xc8, 0xf0, 0x24, + 0x3c, 0xf5, 0x23, 0xdf, 0x80, 0xe6, 0x08, 0x6e, 0x33, 0xf6, + 0x04, 0x1e, 0xc0, 0xb5, 0x45, 0x61, 0x6b, 0xfd, 0xd1, 0x55, + 0xf5, 0x78, 0x03, 0xbf, 0x1d, 0x4c, 0xcc, 0x64, 0xee, 0xb3, + 0x35, 0xde, 0xea, 0xe7, 0x9a, 0xa3, 0xf4, 0xb3, 0xee, 0x40, + 0x5e, 0x89, 0xc7, 0x0c, 0xa9, 0x3b, 0x06, 0xba, 0x06, 0xd2, + 0xca, 0x14, 0xf1, 0xa7, 0xa3, 0x19, 0x48, 0x8a, 0xbd, 0x32, + 0x98, 0xd1, 0x48, 0x7c, 0x2a, 0x2d, 0x3f, 0xc2, 0x57, 0xb3, + 0xc5, 0x76, 0x2b, 0x9c, 0x83, 0x07, 0xd1, 0x30, 0xc6, 0x34, + 0xea, 0x45, 0x0b, 0xa2, 0x02, 0xf6, 0xcf, 0x9d, 0x42, 0xec, + 0x28, 0xec, 0x1b, 0xf2, 0x8a, 0x52, 0xe9, 0x91 }, + { 0x4f, 0x12, 0xe0, 0x37, 0x69, 0x6f, 0xfd, 0xa6, 0xe8, 0xbe, + 0xe9, 0xd4, 0xc9, 0x1d, 0x60, 0x63, 0xd0, 0xd3, 0xcb, 0x56, + 0x19, 0xd4, 0xa2, 0xd7, 0x3a, 0xc0, 0xfb, 0xd5, 0x7c, 0xba, + 0x21, 0x7d, 0xeb, 0x28, 0x9d, 0x0a, 0xa9, 0x36, 0x17, 0xb0, + 0x5e, 0xcb, 0xbc, 0x8c, 0xad, 0x54, 0xef, 0x05, 0xef, 0x96, + 0xf7, 0x31, 0x53, 0xde, 0x1b, 0x2f, 0x96, 0xb3, 0x7e, 0x87, + 0xb6, 0x05, 0x47, 0x05, 0x46, 0x98, 0x99, 0x25, 0x20, 0x30, + 0xfa, 0x5a, 0x76, 0xd4, 0xf2, 0xb7, 0x0c, 0xa3, 0x76, 0x01, + 0x65, 0xc0, 0xf4, 0x92, 0x53, 0x39, 0x8a, 0x72, 0x65, 0x5c, + 0x4b, 0x9b, 0x28, 0x42, 0x3b, 0x20, 0xd7, 0x6b, 0xf7, 0x5e, + 0x52, 0x2b, 0xc8, 0x8d, 0x40, 0x44, 0xad, 0xba, 0x80, 0x49, + 0x84, 0x36, 0xbd, 0xd0, 0x6a, 0x99, 0x8b, 0xeb, 0xb1, 0xd2, + 0x6e, 0x60, 0xb6, 0x98, 0xfb, 0xcd, 0xf6, 0x66 }, + { 0x83, 0xd2, 0x33, 0x3e, 0xb1, 0x26, 0x6f, 0x91, 0xa8, 0xf7, + 0x8e, 0xa7, 0x58, 0x58, 0xaf, 0xb2, 0x1a, 0x49, 0x6e, 0xa9, + 0x5b, 0x52, 0x1e, 0xcb, 0x73, 0xe6, 0x9c, 0x6e, 0xa9, 0x44, + 0x8b, 0x02, 0xf8, 0x88, 0xe9, 0x2c, 0xf2, 0x77, 0xba, 0xb1, + 0x45, 0xb2, 0x32, 0xb2, 0x9b, 0xd6, 0x44, 0x4a, 0x61, 0xa0, + 0x86, 0x6d, 0x32, 0x02, 0x53, 0x71, 0x9d, 0x9e, 0xd8, 0x9f, + 0xf9, 0xc1, 0xd4, 0xdd, 0x8c, 0x34, 0xd2, 0x2c, 0xb9, 0x5a, + 0xe1, 0x6a, 0x74, 0xe7, 0xce, 0xe7, 0x93, 0xc4, 0x80, 0x4e, + 0xfb, 0x6b, 0xa8, 0x8c, 0x70, 0xa8, 0xa0, 0xfa, 0x36, 0x46, + 0x4c, 0x65, 0x14, 0x6d, 0x13, 0x20, 0xfa, 0x15, 0xb4, 0x84, + 0x4b, 0x28, 0x4e, 0x2a, 0x12, 0x46, 0xa4, 0x54, 0x73, 0x83, + 0x81, 0x34, 0x80, 0x4a, 0x5c, 0x55, 0x37, 0x86, 0x51, 0x9a, + 0x4c, 0xcf, 0xa4, 0x22, 0x15, 0xf1, 0xa6, 0x10 }, + { 0x73, 0x62, 0xf1, 0x3e, 0xc5, 0xa3, 0x16, 0x21, 0x46, 0x35, + 0x32, 0x15, 0x2f, 0x40, 0xa5, 0x5b, 0x82, 0x26, 0xb6, 0xaf, + 0xb7, 0xd1, 0xe5, 0x86, 0x8e, 0xdb, 0x61, 0x22, 0xf8, 0xe8, + 0x6e, 0xf3, 0x28, 0xb2, 0x28, 0x0e, 0x3d, 0x40, 0x75, 0x4c, + 0xa0, 0x1e, 0x0f, 0x59, 0x6b, 0xf7, 0x6d, 0xad, 0x17, 0xde, + 0x4b, 0xfe, 0xd5, 0xbe, 0xe3, 0x97, 0xd6, 0xb4, 0x3e, 0xf6, + 0xf4, 0x5d, 0x9f, 0xbb, 0xb3, 0x97, 0x8d, 0xb8, 0xd8, 0x54, + 0xdf, 0xb2, 0x52, 0x8f, 0xef, 0x00, 0x93, 0xf5, 0x5f, 0x0a, + 0xe8, 0x12, 0x01, 0x19, 0x70, 0xe7, 0x3d, 0x77, 0x15, 0x9d, + 0x66, 0x60, 0xa8, 0x11, 0x7a, 0x87, 0x69, 0xf1, 0xf2, 0x88, + 0x89, 0x3c, 0xd6, 0x96, 0x05, 0xb6, 0xab, 0x30, 0x18, 0xd2, + 0x24, 0x1b, 0xa1, 0xee, 0x1a, 0xe1, 0x50, 0xa2, 0xfc, 0x9c, + 0x1c, 0x63, 0x32, 0x88, 0x67, 0xb4, 0x78, 0xd7 }, + { 0x2f, 0x10, 0x69, 0x3f, 0xa3, 0x8c, 0x0e, 0xad, 0xd9, 0xb1, + 0x6f, 0x02, 0xda, 0x0a, 0x20, 0xa8, 0xf0, 0x86, 0x1d, 0x92, + 0x90, 0x98, 0x36, 0x95, 0x1f, 0xc3, 0x9b, 0xac, 0x89, 0xf0, + 0xbf, 0x0b, 0xe7, 0xaf, 0x9c, 0xd7, 0x2f, 0x2b, 0x39, 0x9e, + 0x0e, 0xb1, 0xe7, 0x15, 0xff, 0x56, 0x8f, 0x64, 0x2c, 0x91, + 0x15, 0x4e, 0xae, 0xc8, 0x91, 0xf9, 0x63, 0xe2, 0xfd, 0xbf, + 0xb6, 0xc1, 0xa4, 0x55, 0xb6, 0x51, 0x0c, 0xd8, 0xe3, 0xa8, + 0xd0, 0xd5, 0xd9, 0x36, 0x1d, 0x68, 0x39, 0x87, 0x79, 0x5e, + 0x37, 0x6f, 0x4f, 0x58, 0xf0, 0xaa, 0x86, 0x08, 0xbb, 0xf0, + 0xa8, 0x1a, 0x4b, 0x6f, 0xbb, 0xf4, 0x18, 0x94, 0x56, 0x88, + 0x81, 0x4b, 0x49, 0x47, 0x50, 0xa5, 0xce, 0xce, 0xd2, 0x19, + 0x4f, 0x1b, 0x8c, 0xc0, 0xa6, 0x5f, 0xa5, 0x1c, 0x36, 0x57, + 0x79, 0x2e, 0xb2, 0x7c, 0x73, 0xc0, 0xc4, 0x30 }, + { 0x98, 0x5f, 0x83, 0xe4, 0x4f, 0xe7, 0xa0, 0x43, 0x27, 0x75, + 0xdb, 0xdd, 0x96, 0x43, 0x7c, 0xdb, 0x1e, 0xff, 0x68, 0xd4, + 0xad, 0x6f, 0x19, 0x40, 0x5b, 0x53, 0xd2, 0x79, 0x9d, 0xaa, + 0x9e, 0x4f, 0x25, 0x51, 0xc8, 0xe4, 0xaf, 0x39, 0x53, 0xc8, + 0x7c, 0x7a, 0xfb, 0x14, 0x08, 0xea, 0x2f, 0x6e, 0x82, 0x8c, + 0x3a, 0x05, 0xd5, 0x9c, 0xda, 0x99, 0xa6, 0x86, 0xae, 0x49, + 0x47, 0xf3, 0x82, 0x83, 0x64, 0xba, 0x66, 0xfc, 0x8f, 0xaa, + 0x62, 0x9e, 0x67, 0x59, 0xac, 0xfe, 0x10, 0xd6, 0x33, 0xac, + 0x9c, 0xbd, 0x11, 0x13, 0xdc, 0x96, 0xa2, 0x01, 0x1f, 0xb2, + 0xf8, 0x9f, 0x36, 0x9e, 0xe5, 0x48, 0x04, 0xb6, 0x18, 0x91, + 0x1e, 0xd6, 0x06, 0x26, 0xe4, 0x68, 0xbf, 0xd6, 0xa9, 0xf6, + 0x35, 0xa6, 0xf9, 0x74, 0x84, 0x2f, 0x2f, 0xd9, 0x08, 0x7b, + 0x07, 0xa6, 0xce, 0x91, 0x0c, 0x06, 0xde, 0xd2 }, + { 0x0c, 0x88, 0xe5, 0x40, 0x0f, 0xe9, 0x62, 0xf1, 0x54, 0xd7, + 0x79, 0xd5, 0x50, 0xdc, 0xc7, 0x99, 0xbb, 0xf1, 0x5a, 0x6f, + 0x1e, 0x78, 0x1c, 0xa7, 0x2d, 0x9f, 0x17, 0x9c, 0x0d, 0x8c, + 0xbc, 0x2e, 0x68, 0xfd, 0xda, 0xa9, 0x92, 0xc0, 0x03, 0xb3, + 0x07, 0x01, 0x9c, 0x93, 0x1a, 0x44, 0x3c, 0xfa, 0xb0, 0x7d, + 0x2c, 0xd1, 0xe9, 0xdf, 0x45, 0xcc, 0xa5, 0x25, 0x9e, 0x63, + 0x9a, 0xbc, 0x45, 0x2a, 0xee, 0x66, 0x84, 0xba, 0xe3, 0x4c, + 0x5c, 0x22, 0x5a, 0xc5, 0xee, 0xa3, 0xf8, 0xb2, 0x4f, 0x0e, + 0x3d, 0xc3, 0xf0, 0x76, 0x9c, 0x8a, 0xc1, 0xe1, 0x0c, 0x5b, + 0x02, 0x8b, 0x74, 0xf4, 0x1b, 0x68, 0x70, 0x79, 0xcf, 0x02, + 0xed, 0x94, 0x33, 0x40, 0x4c, 0x11, 0x20, 0x18, 0x39, 0xd6, + 0xb5, 0x2d, 0x70, 0x13, 0x11, 0x60, 0xc2, 0x4b, 0x57, 0x51, + 0x89, 0x60, 0x3c, 0x16, 0xea, 0xf4, 0x52, 0x94 }, + { 0x8e, 0x25, 0x60, 0xb8, 0xaf, 0x11, 0x07, 0x15, 0x4e, 0x5d, + 0xe4, 0x99, 0x3a, 0x25, 0xce, 0xd6, 0xeb, 0xae, 0xa0, 0x19, + 0xfa, 0x87, 0x77, 0x2f, 0x89, 0xf3, 0x36, 0x27, 0x3b, 0x3a, + 0x2c, 0xd7, 0x8c, 0x17, 0xae, 0x85, 0x98, 0x7b, 0x90, 0x7a, + 0x8c, 0x19, 0xfd, 0x8f, 0x92, 0x2d, 0xbc, 0xe8, 0x67, 0x4e, + 0xac, 0x95, 0x5a, 0x33, 0x06, 0x5a, 0xeb, 0xbb, 0x1f, 0xaf, + 0xee, 0xd0, 0xe1, 0x97, 0x7b, 0x32, 0x8e, 0x6f, 0xf2, 0xbc, + 0x37, 0x92, 0x75, 0x98, 0x84, 0x64, 0xb8, 0x0e, 0x32, 0xae, + 0xbb, 0x9d, 0x5a, 0x38, 0xf7, 0x4f, 0x8d, 0x3a, 0xe2, 0x80, + 0x14, 0xc1, 0x07, 0x5e, 0x3c, 0x8e, 0xce, 0xca, 0xf0, 0x84, + 0x8a, 0x75, 0x3e, 0xf2, 0x33, 0x4c, 0x9d, 0x9e, 0x5a, 0xeb, + 0xc6, 0x80, 0xf7, 0x5b, 0x4b, 0xf6, 0x3a, 0x3c, 0xab, 0x6a, + 0x84, 0xf7, 0x1a, 0x6a, 0xe8, 0xf4, 0x43, 0x57 }, + { 0x59, 0x00, 0x5f, 0x22, 0x83, 0x24, 0xf2, 0xe5, 0xfe, 0xf3, + 0xd9, 0x2b, 0x92, 0xfd, 0x9a, 0x29, 0x88, 0xbe, 0x0c, 0x92, + 0x8f, 0x92, 0x23, 0x15, 0x23, 0x0c, 0xc7, 0x7c, 0x53, 0x91, + 0xca, 0x50, 0xb4, 0x1a, 0xb2, 0x65, 0x23, 0x31, 0xd6, 0x11, + 0x61, 0x27, 0x5a, 0xc2, 0x0a, 0xdf, 0x09, 0xc7, 0x40, 0x40, + 0x34, 0x5c, 0x8e, 0x0a, 0x28, 0xab, 0x89, 0x29, 0xd4, 0xde, + 0x97, 0x52, 0x3b, 0x1f, 0x60, 0x78, 0x34, 0x0a, 0x65, 0x10, + 0x46, 0xd5, 0x27, 0x19, 0xdb, 0x5d, 0xa3, 0x83, 0xbb, 0xa7, + 0x49, 0xa8, 0x02, 0x00, 0xb1, 0x16, 0x01, 0x18, 0x1e, 0x0b, + 0x15, 0xcd, 0x3a, 0x94, 0x08, 0xff, 0x22, 0x23, 0x76, 0x32, + 0x9d, 0xfd, 0x95, 0x0e, 0xb6, 0x38, 0x28, 0x31, 0x9c, 0xdd, + 0x27, 0xc7, 0x45, 0xa1, 0x07, 0x9f, 0xba, 0xb2, 0xcf, 0x9e, + 0x56, 0xd3, 0x74, 0x6c, 0x31, 0x41, 0xab, 0xa6 }, + { 0x57, 0xa7, 0x8e, 0x26, 0xd7, 0x83, 0xdf, 0x6e, 0xe4, 0x49, + 0x59, 0x36, 0xb4, 0x3b, 0xae, 0x8d, 0xe9, 0x79, 0x18, 0x51, + 0x32, 0x62, 0xa3, 0x38, 0x00, 0x85, 0xac, 0x6e, 0x17, 0x38, + 0x2d, 0xa1, 0x00, 0x80, 0xfc, 0x0c, 0xf3, 0x9e, 0xad, 0x9c, + 0x2d, 0xf1, 0x90, 0xac, 0xb0, 0xe0, 0x86, 0x18, 0x97, 0x71, + 0x43, 0x01, 0x44, 0xa6, 0x63, 0xda, 0x19, 0x17, 0x57, 0x14, + 0x85, 0x58, 0xca, 0x58, 0xd0, 0xa7, 0x51, 0xf1, 0x48, 0x8c, + 0x0d, 0xe6, 0x91, 0x3d, 0xd0, 0x1c, 0xb1, 0x8b, 0x72, 0xb2, + 0x54, 0x89, 0x16, 0xf7, 0x3f, 0xf3, 0x89, 0x7f, 0x2b, 0x70, + 0x43, 0xb1, 0x50, 0x44, 0x6c, 0xde, 0x8c, 0x97, 0xf9, 0x32, + 0x3a, 0x86, 0x56, 0xb6, 0x85, 0xa7, 0x5d, 0x92, 0x66, 0xc5, + 0x97, 0x3f, 0xbe, 0x73, 0xaa, 0xc0, 0xe9, 0x66, 0xfb, 0x79, + 0x6b, 0xb1, 0x75, 0x0c, 0x3c, 0x4c, 0x1c, 0x74 }, + { 0x1c, 0xa3, 0x70, 0xc5, 0x81, 0xc4, 0x72, 0xe8, 0x32, 0x51, + 0xe4, 0x12, 0x8f, 0x6a, 0xda, 0x87, 0xb4, 0xc5, 0x33, 0xa7, + 0xf6, 0xd3, 0x5b, 0x7e, 0x85, 0x24, 0x07, 0xd8, 0x08, 0xd8, + 0xa0, 0x36, 0x41, 0x91, 0x04, 0x8f, 0xac, 0x0f, 0x46, 0x2d, + 0x6c, 0xa5, 0xef, 0x6a, 0xc4, 0x54, 0xe2, 0x88, 0xe6, 0xec, + 0x93, 0x01, 0xe0, 0x84, 0x17, 0xd7, 0x65, 0x8f, 0x58, 0x9b, + 0x0c, 0x45, 0x44, 0xd0, 0xec, 0xfa, 0x24, 0x45, 0xad, 0x96, + 0xad, 0xc3, 0xc4, 0x6b, 0x39, 0x18, 0x67, 0xf0, 0x86, 0x43, + 0xe5, 0xd7, 0xa6, 0x7d, 0xc2, 0x0e, 0xf5, 0x00, 0x9c, 0x8d, + 0x59, 0xf5, 0x40, 0xdf, 0x57, 0x9d, 0x72, 0xdf, 0x32, 0x32, + 0x33, 0xb9, 0x3d, 0xeb, 0x8c, 0x54, 0x27, 0x83, 0x18, 0x86, + 0xcf, 0x3b, 0x2b, 0x49, 0xa9, 0x27, 0x94, 0x10, 0xc3, 0xac, + 0x16, 0x1b, 0x34, 0x6f, 0x40, 0xdb, 0xdd, 0xd8 }, + { 0x25, 0x84, 0xb3, 0x4c, 0x4c, 0x33, 0xac, 0x79, 0x32, 0xdb, + 0x52, 0xf4, 0xe6, 0x26, 0x5b, 0xaa, 0x53, 0xd0, 0x44, 0x8a, + 0x1d, 0xbd, 0x3b, 0x03, 0x83, 0xbf, 0x46, 0x4e, 0x2e, 0xfd, + 0x90, 0x03, 0x71, 0xa1, 0x17, 0x20, 0x2b, 0x42, 0x50, 0x72, + 0x6c, 0x31, 0x1c, 0x3d, 0xc0, 0x86, 0x7e, 0x39, 0xca, 0xd4, + 0x67, 0xb5, 0x08, 0xcd, 0x1c, 0xd2, 0x0d, 0xd2, 0x80, 0x1d, + 0xf9, 0x9d, 0xae, 0x74, 0x22, 0x4b, 0x28, 0x82, 0xe1, 0x88, + 0xf1, 0x2d, 0xb5, 0xde, 0xcf, 0xd0, 0x23, 0x90, 0x4c, 0x35, + 0x0b, 0xf1, 0x61, 0xa1, 0xc7, 0xbd, 0x31, 0xf7, 0x78, 0xde, + 0x52, 0x3a, 0x9c, 0xda, 0x12, 0x8b, 0xb5, 0xfe, 0x87, 0xf4, + 0xf5, 0xb0, 0x1f, 0xdb, 0x49, 0x05, 0xaa, 0xbf, 0x41, 0x16, + 0x32, 0x02, 0x73, 0x12, 0x87, 0x9c, 0xfd, 0x19, 0x98, 0xb3, + 0x94, 0xbd, 0x51, 0x71, 0xa8, 0x01, 0xb6, 0x8a }, + { 0x7e, 0x81, 0x13, 0x74, 0x3f, 0x9a, 0xb0, 0x85, 0xac, 0xdd, + 0xb6, 0xff, 0x95, 0x1c, 0xa4, 0x9a, 0xe1, 0xc8, 0x35, 0x45, + 0x69, 0x80, 0x7b, 0xaa, 0xaf, 0xb6, 0x02, 0x69, 0xff, 0x51, + 0xa9, 0xff, 0xfe, 0x6a, 0xd2, 0x2e, 0xf2, 0xd5, 0x73, 0x7c, + 0x6b, 0x3f, 0xaa, 0xbe, 0x18, 0x78, 0x97, 0xe0, 0x59, 0x27, + 0xdd, 0x51, 0xdc, 0x7c, 0xb4, 0x88, 0x00, 0x26, 0x67, 0x06, + 0x4d, 0xf6, 0xc7, 0xd0, 0x2e, 0x42, 0xc3, 0xe1, 0x62, 0xee, + 0x7c, 0xc8, 0x76, 0xdd, 0x30, 0x45, 0xa8, 0xb9, 0xa6, 0x57, + 0x3f, 0x27, 0x18, 0x54, 0xac, 0x05, 0x45, 0x24, 0x04, 0xc2, + 0xbb, 0x36, 0xfa, 0x17, 0xd8, 0x0d, 0x45, 0x5d, 0x18, 0x5c, + 0x48, 0x74, 0x91, 0x3d, 0x42, 0x2e, 0x71, 0xf7, 0xfd, 0x60, + 0xb5, 0xf8, 0xa5, 0xe7, 0x40, 0xba, 0x45, 0xfb, 0xe5, 0x23, + 0x3c, 0xb8, 0x63, 0x89, 0x2a, 0xee, 0xc6, 0x88 }, + { 0x43, 0x6b, 0x8c, 0x64, 0xdf, 0x84, 0x85, 0xa6, 0x00, 0x1c, + 0x79, 0x18, 0xba, 0x56, 0xfa, 0x91, 0x63, 0x76, 0xc1, 0xa2, + 0x63, 0xdb, 0x2b, 0xfe, 0xfe, 0x0c, 0x9f, 0x81, 0x39, 0x6d, + 0xa4, 0x22, 0xe4, 0x53, 0x86, 0x67, 0x32, 0xa1, 0xad, 0x94, + 0x23, 0xe0, 0xb4, 0x6c, 0xae, 0xec, 0x0b, 0xfe, 0x97, 0xd7, + 0x1e, 0xff, 0x50, 0x04, 0xf2, 0x86, 0xbb, 0x07, 0x6b, 0x98, + 0xe3, 0x91, 0xc0, 0xcd, 0xda, 0x77, 0x4d, 0xe5, 0xf5, 0xff, + 0x43, 0xcb, 0x0c, 0x1c, 0x15, 0x5a, 0x23, 0x86, 0xc4, 0x53, + 0x98, 0x45, 0xcd, 0x06, 0x15, 0xb0, 0xcd, 0x5e, 0x2f, 0xd0, + 0x9d, 0xb0, 0xe5, 0x89, 0x66, 0x9c, 0xb5, 0x38, 0x12, 0xd3, + 0x6c, 0x46, 0xd1, 0xd3, 0x3e, 0x02, 0xd0, 0xb8, 0x04, 0x09, + 0xb4, 0x7d, 0x91, 0x91, 0x8e, 0xa8, 0xce, 0x11, 0x17, 0xe1, + 0xad, 0x72, 0x2a, 0x8b, 0x83, 0x0a, 0x88, 0xb1 }, + { 0x52, 0x66, 0xca, 0x9e, 0x6d, 0xbe, 0x95, 0xe1, 0x1d, 0xf7, + 0xaa, 0xe4, 0x07, 0x68, 0xcb, 0x66, 0x6f, 0x7c, 0x90, 0xe1, + 0x53, 0x7d, 0xa5, 0xff, 0xe5, 0xdc, 0xde, 0x62, 0x17, 0x95, + 0x44, 0x05, 0x50, 0x60, 0x07, 0x5e, 0x02, 0x43, 0xdc, 0xb6, + 0xe5, 0x01, 0x85, 0x17, 0xcd, 0x51, 0xe5, 0x3f, 0xe6, 0x14, + 0x14, 0x8e, 0xd4, 0x73, 0x94, 0xa3, 0x79, 0x90, 0x8b, 0x90, + 0x8c, 0x92, 0x79, 0x9d, 0xe4, 0xf9, 0xd4, 0x1e, 0x18, 0xd9, + 0x70, 0x68, 0xdd, 0x7d, 0x68, 0xc9, 0x43, 0xc8, 0xc2, 0x86, + 0x63, 0x3b, 0x95, 0xde, 0xb2, 0x3b, 0x41, 0xdf, 0x01, 0xa5, + 0x2e, 0x33, 0x07, 0x1a, 0x34, 0x7a, 0x54, 0x89, 0x16, 0xaf, + 0xfc, 0x94, 0x51, 0xdc, 0x5a, 0x77, 0x65, 0xd3, 0x0c, 0x18, + 0xee, 0xbd, 0xdf, 0xa6, 0x1e, 0x94, 0xa0, 0x77, 0xdf, 0x84, + 0x88, 0x11, 0x7e, 0x9d, 0x8a, 0xb7, 0x64, 0xbc }, + { 0x41, 0xf3, 0x25, 0xb9, 0x9c, 0xd8, 0x4a, 0x2b, 0xc1, 0x7a, + 0x09, 0x20, 0x1f, 0xc6, 0x70, 0x3a, 0x0f, 0x32, 0xb4, 0x49, + 0x4f, 0xb4, 0xcb, 0x67, 0xa9, 0x75, 0x04, 0x4e, 0x62, 0x6b, + 0xea, 0x27, 0x7d, 0xec, 0x36, 0x2b, 0x7b, 0xd3, 0xe2, 0x20, + 0x89, 0x9a, 0x20, 0xb4, 0x14, 0x6e, 0xf8, 0xff, 0x20, 0x7c, + 0x13, 0x47, 0x2b, 0x2f, 0x3b, 0xff, 0x6f, 0xb8, 0xcb, 0x1d, + 0x14, 0x96, 0x0d, 0x7c, 0xf1, 0xe2, 0x98, 0xfd, 0x94, 0x0c, + 0xe1, 0xe8, 0x8f, 0x34, 0xe1, 0x74, 0x86, 0xc3, 0x1f, 0xf0, + 0x35, 0x19, 0xc6, 0xe3, 0x19, 0xfd, 0x70, 0xc1, 0x3e, 0x6e, + 0x69, 0x24, 0x30, 0x25, 0x7c, 0xfc, 0x21, 0x38, 0xa1, 0xe8, + 0xfd, 0xe5, 0xa4, 0xfd, 0xb3, 0x41, 0x84, 0x40, 0xeb, 0x04, + 0xf4, 0x9d, 0xf9, 0xe4, 0xaf, 0x5a, 0x7c, 0x38, 0xe5, 0x40, + 0x84, 0xdd, 0xee, 0x6d, 0x13, 0x86, 0xb3, 0xdb }, + { 0x56, 0xb3, 0x0f, 0xb6, 0xe5, 0x8c, 0xea, 0x9e, 0x7d, 0xb3, + 0xd3, 0x7b, 0xd9, 0xaa, 0x18, 0xfd, 0x49, 0xef, 0x46, 0x70, + 0xeb, 0x8c, 0x34, 0x68, 0x00, 0xf2, 0xe3, 0xac, 0x24, 0x2c, + 0xa8, 0xfd, 0x89, 0x47, 0xba, 0x6d, 0x9b, 0xfd, 0x07, 0xdd, + 0xc6, 0x47, 0x70, 0x5e, 0xa7, 0x61, 0xba, 0x43, 0x3d, 0xb6, + 0xd2, 0x8d, 0x23, 0x40, 0x0a, 0xa7, 0x59, 0x23, 0x52, 0x1f, + 0x1d, 0xac, 0x89, 0x44, 0xdf, 0xe2, 0xdc, 0x47, 0xf1, 0x7b, + 0x73, 0x41, 0x98, 0x27, 0x6d, 0x96, 0x28, 0x9e, 0x7b, 0xb9, + 0x2a, 0x57, 0x8c, 0xb5, 0x06, 0x3e, 0x7b, 0x38, 0x59, 0x05, + 0xe1, 0xd9, 0x4b, 0xed, 0x33, 0x8d, 0x34, 0x06, 0x47, 0x04, + 0xa6, 0x20, 0x08, 0x3b, 0xa8, 0xef, 0x28, 0x22, 0x4d, 0x86, + 0x4c, 0xe5, 0xe7, 0x48, 0x49, 0x8e, 0x00, 0x72, 0x8a, 0xfc, + 0x31, 0x2e, 0xd5, 0x13, 0xce, 0x28, 0x43, 0xa4 }, + { 0x13, 0x53, 0xcc, 0x57, 0x58, 0xbd, 0xd1, 0x46, 0x89, 0x90, + 0x81, 0xe5, 0xdc, 0xcf, 0x7f, 0x07, 0xe4, 0x72, 0xfb, 0x8b, + 0x17, 0xc0, 0xd9, 0x69, 0x58, 0xf8, 0x8c, 0x51, 0xc6, 0x52, + 0x3a, 0x79, 0x3e, 0xdf, 0x81, 0xf5, 0x85, 0xd3, 0xcd, 0x83, + 0xde, 0xa9, 0xb4, 0xfa, 0xf8, 0x72, 0x04, 0xae, 0x30, 0x92, + 0x23, 0x77, 0x90, 0xbb, 0x1c, 0xd8, 0xc4, 0xe0, 0xb7, 0xf8, + 0x94, 0x39, 0x2a, 0x91, 0x78, 0xb6, 0x34, 0xa5, 0xad, 0xe8, + 0xa8, 0x8d, 0x0b, 0xfa, 0xef, 0xa5, 0x1f, 0x2f, 0xae, 0xcb, + 0xc3, 0x4e, 0x40, 0x75, 0x65, 0xf8, 0x07, 0xd3, 0x21, 0x23, + 0x53, 0x3c, 0xb2, 0xe8, 0x1c, 0x3a, 0x3b, 0xed, 0x9a, 0x44, + 0x92, 0x4b, 0x00, 0x8a, 0x20, 0xd8, 0x87, 0x98, 0x3a, 0xda, + 0x44, 0x1f, 0x7a, 0xf9, 0x22, 0xdc, 0x87, 0x32, 0xc8, 0x91, + 0x07, 0xec, 0xdc, 0xaa, 0xcd, 0x80, 0xa4, 0x28 }, + { 0x3e, 0xc2, 0x18, 0x5d, 0xf4, 0x51, 0xdf, 0x58, 0x72, 0x3a, + 0x83, 0x0e, 0x5a, 0x21, 0xe7, 0x89, 0x8d, 0x1d, 0xf4, 0x3c, + 0xbb, 0x1c, 0xc1, 0xf1, 0x8f, 0x41, 0x93, 0xa9, 0xa6, 0xb1, + 0x6e, 0xbd, 0xbc, 0x69, 0xcf, 0xc0, 0x52, 0x87, 0x7a, 0xe5, + 0x75, 0xf4, 0xe5, 0x70, 0xf8, 0xa3, 0x62, 0x35, 0xa5, 0x58, + 0xf9, 0x28, 0x15, 0x5c, 0xe6, 0xde, 0x8a, 0x79, 0x7f, 0xc7, + 0x95, 0x8d, 0xdb, 0xad, 0x49, 0x68, 0x5d, 0x86, 0xcd, 0x39, + 0xe4, 0x2b, 0x84, 0x16, 0xa7, 0xe0, 0x72, 0xd6, 0x72, 0x97, + 0xf1, 0x58, 0x3e, 0xd6, 0x27, 0xf8, 0x12, 0x94, 0x2a, 0xb3, + 0xa1, 0x64, 0x6a, 0x7b, 0x8e, 0x82, 0xd9, 0x35, 0xbf, 0x51, + 0x20, 0x47, 0x04, 0x0c, 0x8d, 0x94, 0x34, 0xa0, 0xdc, 0xe8, + 0xb8, 0xe7, 0x59, 0xe8, 0xb5, 0xa2, 0x64, 0x9b, 0x89, 0xc7, + 0x28, 0xa5, 0x64, 0x97, 0x39, 0xbf, 0x6e, 0x18 }, + { 0x89, 0xb3, 0x56, 0xb6, 0xa2, 0x11, 0xab, 0xe5, 0x30, 0x87, + 0xdc, 0x5c, 0xe9, 0xd4, 0x47, 0xa3, 0x5f, 0x1d, 0xe8, 0xcc, + 0x39, 0xbd, 0xd6, 0x66, 0xbc, 0x93, 0xc5, 0xf3, 0x54, 0x97, + 0xaa, 0x72, 0xb5, 0x27, 0xc5, 0x7b, 0x8b, 0xc9, 0x76, 0x07, + 0xb4, 0xa6, 0x7a, 0xe7, 0xd3, 0x89, 0x51, 0xe0, 0xb0, 0xd8, + 0x4b, 0x1f, 0x8d, 0x7d, 0x43, 0x29, 0x8e, 0x40, 0x61, 0x21, + 0x06, 0xbc, 0x05, 0x50, 0xba, 0x18, 0x8c, 0x56, 0x7b, 0xc2, + 0x8b, 0x9d, 0x60, 0x24, 0x2a, 0xcb, 0x12, 0xf0, 0xd2, 0xc8, + 0x69, 0xd4, 0x9c, 0xe1, 0xc7, 0x78, 0x50, 0xbe, 0x35, 0x03, + 0x14, 0x9f, 0x37, 0xf3, 0x51, 0xf9, 0xb7, 0xdd, 0x2d, 0x25, + 0x04, 0x7a, 0xe0, 0x9c, 0x92, 0xe0, 0x2d, 0x93, 0xa0, 0x9f, + 0x80, 0xf6, 0x69, 0x82, 0xc6, 0xcc, 0x6e, 0x51, 0xd4, 0x12, + 0xb9, 0xd4, 0xc7, 0xd7, 0x1f, 0x0b, 0xc2, 0xd7 }, + { 0x39, 0xc4, 0xf1, 0x0d, 0x57, 0xc5, 0xd1, 0x26, 0x65, 0x6f, + 0x18, 0xe0, 0x8a, 0x0d, 0x4f, 0x52, 0x7e, 0x12, 0x02, 0xbe, + 0x87, 0xad, 0xc2, 0xf9, 0x4e, 0xf3, 0xa8, 0x0e, 0xdc, 0x60, + 0xee, 0xe5, 0x2c, 0xc2, 0x7c, 0xef, 0x00, 0xbf, 0x79, 0x28, + 0xe1, 0xbb, 0x97, 0x02, 0x55, 0x84, 0xbc, 0x86, 0x9c, 0xf5, + 0x81, 0x7f, 0x87, 0x64, 0x86, 0x43, 0x01, 0x16, 0x19, 0xc9, + 0xcb, 0x16, 0x2d, 0xc2, 0xee, 0x62, 0x8e, 0xce, 0xf4, 0x26, + 0xda, 0xea, 0x63, 0xe1, 0x1d, 0x26, 0x37, 0x43, 0x36, 0x58, + 0x11, 0xb0, 0x4f, 0x72, 0x0e, 0x41, 0xd9, 0x4e, 0x56, 0x64, + 0xa2, 0xda, 0x8b, 0x86, 0x57, 0xa3, 0xf5, 0xb5, 0x6b, 0xf7, + 0xad, 0xac, 0x9e, 0x5c, 0x41, 0x3a, 0xbf, 0xc9, 0x1c, 0x1d, + 0x4b, 0x72, 0x0f, 0xb8, 0x0b, 0xaa, 0xa8, 0x71, 0xb7, 0xa9, + 0xed, 0x6d, 0xb0, 0xaf, 0xdf, 0xdc, 0xc8, 0x37 }, + { 0x41, 0x4b, 0x54, 0x2d, 0x49, 0x15, 0x2b, 0x00, 0xcf, 0xf1, + 0x64, 0x78, 0x90, 0x69, 0xfb, 0xcc, 0x0b, 0x9a, 0x17, 0x07, + 0xb6, 0xe5, 0x79, 0xcf, 0x44, 0xc6, 0xc9, 0x77, 0x5a, 0xed, + 0x24, 0xc4, 0xfd, 0xe5, 0xbe, 0x8d, 0x73, 0xf7, 0xe3, 0x39, + 0x28, 0x17, 0xeb, 0xb3, 0xd4, 0x6f, 0xf5, 0x1b, 0xbe, 0xc7, + 0x76, 0x7e, 0xc7, 0xd4, 0xc5, 0x56, 0xf2, 0xb6, 0x37, 0x25, + 0xf1, 0xaa, 0x12, 0x02, 0xa7, 0xbc, 0x17, 0x75, 0x89, 0x4c, + 0x44, 0x44, 0xc8, 0x41, 0xe9, 0xea, 0x3b, 0xd1, 0x62, 0x83, + 0x6d, 0x1e, 0x6d, 0x35, 0xa8, 0x1a, 0x0a, 0x78, 0x7d, 0xac, + 0x80, 0xd0, 0x81, 0x1a, 0xc7, 0x2d, 0x79, 0xb6, 0x8b, 0x67, + 0x02, 0x06, 0x8d, 0x84, 0xed, 0xc1, 0xcd, 0xad, 0x4b, 0xd4, + 0xee, 0x54, 0x55, 0x5b, 0x09, 0x18, 0xa5, 0x18, 0xaa, 0x9d, + 0xb3, 0xa9, 0xb6, 0x8c, 0xe8, 0x8a, 0xec, 0xd3 }, + { 0x52, 0x67, 0x8d, 0x6a, 0xe0, 0x0b, 0x8b, 0x2a, 0x43, 0x97, + 0x78, 0x74, 0x44, 0x4e, 0x85, 0x15, 0x3c, 0x73, 0x62, 0xfa, + 0x96, 0x08, 0xf5, 0xbf, 0xf4, 0x8e, 0x62, 0x3e, 0x27, 0x0d, + 0x17, 0xa6, 0x13, 0x33, 0x8e, 0xf8, 0xed, 0x55, 0x6a, 0x6c, + 0x74, 0xab, 0x92, 0x48, 0xd1, 0x84, 0x30, 0x07, 0xaf, 0x1f, + 0x4a, 0x6e, 0x74, 0x0d, 0xb2, 0x9c, 0xb2, 0xe4, 0xd6, 0x6c, + 0x1b, 0xa2, 0xae, 0xa9, 0x70, 0x8f, 0x9b, 0x32, 0x44, 0xaf, + 0x08, 0x2e, 0xe1, 0x31, 0xe8, 0x8f, 0x94, 0x50, 0x69, 0x0a, + 0x9f, 0x9d, 0x35, 0xac, 0x81, 0xc6, 0xe6, 0xd7, 0x3e, 0xf0, + 0x56, 0x02, 0x90, 0x13, 0xe4, 0xec, 0xc7, 0x88, 0xc6, 0x17, + 0x05, 0x12, 0x0e, 0x70, 0x42, 0x5f, 0xb5, 0x12, 0xde, 0xbb, + 0x20, 0xaf, 0x5b, 0x7f, 0x4e, 0x1b, 0x90, 0xe6, 0x71, 0x3a, + 0x33, 0xc3, 0x1e, 0x58, 0x60, 0x6e, 0x17, 0x3b }, + { 0x70, 0x40, 0xba, 0x5b, 0xc1, 0x0c, 0xee, 0xdd, 0x04, 0x5a, + 0xc6, 0x14, 0xc8, 0xef, 0xce, 0xa6, 0x23, 0xa5, 0x9c, 0x1d, + 0xbf, 0x22, 0xf6, 0x82, 0xb8, 0xee, 0x84, 0x2a, 0x5d, 0x99, + 0x74, 0xc9, 0x4b, 0x58, 0xf9, 0xb2, 0xd3, 0x05, 0x3b, 0x4f, + 0x3e, 0xcd, 0x40, 0x75, 0x0f, 0x79, 0x48, 0xa9, 0x0e, 0x41, + 0x19, 0x6e, 0xf6, 0xd2, 0xd7, 0xff, 0xf3, 0x9c, 0x49, 0x0e, + 0x5a, 0xa5, 0x69, 0x5c, 0xfa, 0xb4, 0x18, 0xd3, 0x2c, 0x1b, + 0xf9, 0x06, 0x1a, 0x33, 0xe9, 0x4f, 0x3f, 0x7d, 0x9e, 0x09, + 0x2b, 0xd6, 0x18, 0x04, 0x93, 0x33, 0x44, 0x85, 0x25, 0x8c, + 0x2c, 0x52, 0xa5, 0x71, 0xf8, 0x9b, 0x85, 0x09, 0xd4, 0x14, + 0x2d, 0xfd, 0x49, 0x1f, 0x0e, 0x03, 0xf4, 0x96, 0x92, 0x7a, + 0x5f, 0x81, 0x52, 0xd6, 0x65, 0x3c, 0xa9, 0x2b, 0xc0, 0xab, + 0x5d, 0xff, 0x1c, 0x59, 0xdf, 0x36, 0xae, 0xb4 }, + { 0x90, 0x43, 0xa6, 0xd6, 0x0b, 0xd1, 0xc9, 0xc1, 0x3d, 0x28, + 0x1e, 0x1a, 0xfe, 0x87, 0x32, 0x48, 0xff, 0x2d, 0xff, 0x4e, + 0x70, 0xf4, 0xea, 0xa3, 0xfa, 0xc3, 0xe5, 0x82, 0x43, 0x65, + 0x78, 0x4a, 0x97, 0xd2, 0xb7, 0x21, 0xb7, 0x74, 0xc3, 0x1e, + 0xaf, 0x9a, 0x23, 0xe8, 0xe7, 0xe3, 0x86, 0x0e, 0xc1, 0xfe, + 0x0d, 0x8a, 0xde, 0x1d, 0x33, 0x6f, 0x65, 0x27, 0x34, 0x9f, + 0xfb, 0x29, 0x4c, 0x4a, 0x2f, 0xd4, 0xf0, 0xc6, 0x5b, 0x25, + 0xf0, 0x06, 0x34, 0x92, 0x27, 0x6b, 0x86, 0x67, 0x69, 0x6b, + 0x1e, 0x01, 0xa7, 0x42, 0x28, 0x14, 0xc1, 0x77, 0x88, 0x86, + 0xd8, 0x76, 0xd2, 0xcd, 0xa9, 0xd2, 0x9d, 0x76, 0x94, 0xf1, + 0x27, 0x3b, 0x61, 0x73, 0x0a, 0x09, 0x66, 0x50, 0x1a, 0xd9, + 0x3d, 0x4f, 0x31, 0xa6, 0x35, 0x03, 0x18, 0x43, 0x27, 0xe0, + 0x2c, 0x36, 0x4f, 0x81, 0x51, 0x5a, 0x1a, 0x96 }, + { 0x26, 0x36, 0x2b, 0x48, 0x3a, 0x12, 0x5f, 0x35, 0xb0, 0x76, + 0x0a, 0x3c, 0xb7, 0x3e, 0xac, 0x46, 0xe4, 0x5c, 0x75, 0xdf, + 0xff, 0xaa, 0xd0, 0x78, 0x7b, 0xd2, 0xc1, 0x38, 0x1e, 0x35, + 0x79, 0xb2, 0x95, 0x77, 0x1f, 0xa2, 0xdb, 0x4e, 0x80, 0x1a, + 0x79, 0xbc, 0x85, 0xc6, 0x4e, 0x8d, 0xa1, 0x54, 0x2c, 0x8d, + 0x38, 0x34, 0x40, 0xc9, 0x2a, 0xf9, 0xfb, 0x12, 0xea, 0x4d, + 0xf5, 0x97, 0xf6, 0x63, 0xc3, 0xc3, 0x46, 0x3a, 0xe4, 0x06, + 0x98, 0x80, 0x99, 0x6b, 0x08, 0x22, 0xce, 0xdf, 0xcd, 0x94, + 0x8a, 0xd7, 0xa0, 0x3a, 0x9c, 0xbe, 0x10, 0x6f, 0xb8, 0x01, + 0xc8, 0x3d, 0x34, 0xa2, 0xea, 0x06, 0x92, 0x87, 0x54, 0xbd, + 0x61, 0x62, 0x00, 0xf3, 0x2a, 0xc1, 0x60, 0xcc, 0xe0, 0x08, + 0x88, 0xac, 0x1b, 0x2d, 0xed, 0x5c, 0xab, 0xbc, 0x3b, 0xe3, + 0x15, 0x11, 0xa0, 0xfe, 0x76, 0x6c, 0x79, 0x37 }, + { 0x2e, 0x95, 0x2b, 0x20, 0x55, 0x5c, 0x93, 0x5e, 0x45, 0x2f, + 0xe2, 0x31, 0x09, 0xff, 0x59, 0xba, 0x9c, 0x86, 0xe0, 0xb2, + 0x96, 0xc6, 0xb5, 0xee, 0x92, 0xc2, 0x65, 0x63, 0xc1, 0x43, + 0x92, 0x73, 0x5a, 0xce, 0x53, 0xd1, 0xbe, 0xe0, 0xf2, 0xe9, + 0x19, 0x3f, 0x88, 0xc8, 0x05, 0x4d, 0x54, 0x71, 0x7b, 0x60, + 0xd4, 0x64, 0xa7, 0xbf, 0x21, 0xda, 0x45, 0xe4, 0xf2, 0xa5, + 0xbe, 0xa9, 0xcd, 0x49, 0x21, 0xfb, 0xd3, 0x10, 0x1e, 0x06, + 0xd4, 0x85, 0x39, 0x1f, 0x68, 0x8a, 0x44, 0xf9, 0x71, 0x45, + 0xa5, 0xee, 0xb2, 0xb1, 0x4c, 0x0d, 0xa1, 0xe9, 0xfd, 0x3d, + 0x20, 0xea, 0xff, 0x55, 0x2b, 0xac, 0xdb, 0x70, 0x90, 0x72, + 0xcb, 0x86, 0xb3, 0x33, 0x8b, 0x07, 0xbb, 0x86, 0xaf, 0x5e, + 0x4b, 0x75, 0x2d, 0x0e, 0xe8, 0x77, 0x69, 0xe9, 0xee, 0x71, + 0x25, 0xc6, 0x8d, 0x28, 0xee, 0xfc, 0x3e, 0x89 }, + { 0x12, 0x36, 0xd0, 0x17, 0x30, 0x37, 0x8e, 0x4b, 0x1c, 0x0a, + 0x84, 0xc9, 0xeb, 0x53, 0xef, 0x06, 0xa5, 0xc1, 0x48, 0x96, + 0xdb, 0x2f, 0x02, 0x73, 0x2b, 0xcd, 0x96, 0xb0, 0xb0, 0x93, + 0x77, 0xe0, 0xff, 0x60, 0x4a, 0x11, 0x17, 0x55, 0x9a, 0x30, + 0x7c, 0x14, 0xef, 0x33, 0x53, 0xb1, 0xfa, 0x97, 0x7a, 0xaa, + 0x53, 0xf2, 0xa4, 0x4d, 0x2f, 0xa8, 0x8e, 0xf8, 0x3f, 0xb3, + 0x9d, 0x6e, 0xbc, 0xb1, 0xa5, 0xc2, 0x6e, 0x3a, 0x7f, 0xbd, + 0x85, 0x6d, 0x02, 0x51, 0x13, 0xec, 0x6c, 0x12, 0x20, 0x76, + 0x28, 0x35, 0xb3, 0x86, 0x18, 0x1e, 0x5e, 0x33, 0xbc, 0x70, + 0x2f, 0x26, 0xa2, 0x63, 0xec, 0xc9, 0x58, 0x0e, 0x2e, 0xc9, + 0x35, 0x5f, 0xf2, 0xb5, 0x10, 0x3e, 0x45, 0xb6, 0x00, 0x7b, + 0x1b, 0x86, 0xe6, 0x8a, 0x5d, 0xbe, 0xd4, 0x3d, 0xfc, 0x58, + 0x2a, 0x84, 0x6b, 0xca, 0xd7, 0x5f, 0x88, 0x6e }, + { 0x02, 0xa4, 0x80, 0x14, 0x62, 0x0c, 0xb5, 0x6e, 0x35, 0x3c, + 0x2d, 0x85, 0x4b, 0x9e, 0xc7, 0xea, 0xe6, 0x16, 0xf5, 0x55, + 0x6c, 0x97, 0xf0, 0xe9, 0x19, 0x88, 0x19, 0x41, 0xd1, 0x46, + 0x58, 0xf3, 0xb3, 0xfc, 0xd3, 0x65, 0x24, 0x38, 0x90, 0x6d, + 0xbb, 0x0c, 0x5d, 0x66, 0x74, 0xcc, 0x95, 0xcb, 0x7d, 0x2c, + 0x72, 0x7d, 0xba, 0x75, 0x30, 0xe9, 0x3b, 0xdd, 0xe1, 0xa8, + 0x70, 0x6e, 0xf8, 0x17, 0x65, 0xba, 0xf5, 0x94, 0x33, 0x0a, + 0x32, 0x82, 0xf0, 0xec, 0x0b, 0x38, 0x42, 0x31, 0x45, 0x76, + 0x55, 0x4f, 0xbb, 0x9f, 0xed, 0x01, 0x08, 0x00, 0x86, 0x52, + 0x46, 0x29, 0x0e, 0x2b, 0xe7, 0xe2, 0x37, 0x12, 0x71, 0x4c, + 0x93, 0x4b, 0xc2, 0xb0, 0x13, 0x00, 0xdf, 0xa0, 0x61, 0x3b, + 0xc3, 0x4b, 0x29, 0xae, 0x47, 0x68, 0x64, 0x60, 0x97, 0xae, + 0xd7, 0x48, 0x1c, 0x8f, 0xc0, 0x84, 0x37, 0x3b }, + { 0x1d, 0x8b, 0xde, 0x6f, 0x8f, 0x21, 0x7f, 0xe0, 0x31, 0x39, + 0x04, 0x14, 0xb5, 0x5f, 0x75, 0xf3, 0xa4, 0x4e, 0x2c, 0x25, + 0xc3, 0x55, 0x6d, 0x18, 0xbe, 0x2d, 0xa8, 0x87, 0xa2, 0xe8, + 0xc3, 0xda, 0x43, 0x04, 0x46, 0x60, 0x91, 0xeb, 0x25, 0x99, + 0x19, 0x2a, 0x64, 0xb7, 0x36, 0x9f, 0x46, 0xc7, 0x32, 0x39, + 0x5d, 0xee, 0x1e, 0x01, 0x14, 0xde, 0xee, 0x95, 0x7c, 0x67, + 0x49, 0xfc, 0xb8, 0x80, 0xde, 0xc0, 0xff, 0xbf, 0x8e, 0xc9, + 0x55, 0xfd, 0x99, 0xab, 0x26, 0xbd, 0x9f, 0x15, 0x4d, 0x1f, + 0xf0, 0xa7, 0xb4, 0x27, 0xaa, 0xda, 0xc2, 0x58, 0xf5, 0xd6, + 0x3b, 0xbb, 0x83, 0x83, 0x50, 0x83, 0xe8, 0x7e, 0x1b, 0x46, + 0xd8, 0x28, 0x93, 0x7d, 0x71, 0x7c, 0x9c, 0x27, 0x69, 0xd0, + 0x11, 0xc5, 0x22, 0x9a, 0x1c, 0x54, 0x90, 0x59, 0xba, 0xa6, + 0x11, 0xd6, 0xd2, 0x3d, 0x50, 0x6c, 0xcd, 0x38 }, + { 0x34, 0x9c, 0x69, 0x43, 0xc6, 0x10, 0x13, 0xc1, 0xf5, 0x65, + 0xb2, 0x8b, 0xcc, 0x83, 0x20, 0x9e, 0xb3, 0x6e, 0xd3, 0x5c, + 0xde, 0xb9, 0x3b, 0x87, 0xb9, 0xb0, 0x0a, 0x02, 0x36, 0x0d, + 0x3a, 0x26, 0xdc, 0x37, 0x5c, 0x84, 0xee, 0x8d, 0x21, 0x39, + 0xd8, 0x19, 0x6b, 0x5b, 0xb6, 0xfc, 0x65, 0x5a, 0x74, 0xfc, + 0x2a, 0x6a, 0xbf, 0xb1, 0x76, 0x38, 0x79, 0x93, 0xf5, 0x7a, + 0xac, 0x94, 0xd4, 0xd1, 0x59, 0x4d, 0x4d, 0x43, 0xf8, 0x8b, + 0x05, 0xe6, 0x41, 0x4d, 0xec, 0xcb, 0xa6, 0x72, 0xba, 0x38, + 0xf4, 0x21, 0x38, 0x26, 0x6f, 0x1b, 0xb6, 0x5c, 0x93, 0x97, + 0xc9, 0x7a, 0xb1, 0x0f, 0xec, 0x10, 0xdb, 0xe0, 0x67, 0x16, + 0x5a, 0x06, 0x07, 0x76, 0x86, 0x2b, 0xbc, 0xb7, 0xd6, 0xf0, + 0x58, 0x46, 0x6e, 0x54, 0xf1, 0x9c, 0xb0, 0x6e, 0xcb, 0x9f, + 0x03, 0xcd, 0x39, 0xf8, 0xa2, 0x02, 0x89, 0x24 }, + { 0x05, 0x65, 0x87, 0xab, 0x89, 0xc2, 0xd8, 0xfa, 0xa3, 0x2f, + 0x32, 0x7e, 0x87, 0x25, 0x57, 0x69, 0x21, 0x19, 0x52, 0x99, + 0x08, 0x17, 0xc5, 0xc2, 0x9c, 0xf8, 0x42, 0xd5, 0x27, 0x18, + 0x2a, 0xc9, 0xd0, 0xd3, 0xa1, 0x77, 0x07, 0x38, 0x96, 0x35, + 0x96, 0x08, 0x9e, 0x8a, 0x5f, 0x0e, 0x12, 0x9b, 0x3a, 0x7f, + 0x3e, 0x90, 0xf4, 0xbd, 0x1f, 0x91, 0xc9, 0x91, 0xf1, 0xc7, + 0xed, 0x0b, 0xd5, 0x0a, 0x24, 0x3a, 0x66, 0x6e, 0x53, 0x37, + 0xf4, 0x53, 0xc5, 0xa8, 0xe2, 0xec, 0x21, 0x46, 0x7e, 0xbf, + 0x2d, 0x74, 0x29, 0x38, 0x73, 0x7c, 0x70, 0xf0, 0x40, 0x0b, + 0xa5, 0x79, 0xba, 0xef, 0x0c, 0x18, 0x74, 0x9f, 0x75, 0x64, + 0x08, 0x50, 0x99, 0x3e, 0xb6, 0xf4, 0x58, 0xa2, 0x21, 0xc2, + 0xb7, 0x80, 0xd5, 0xc2, 0xc4, 0x71, 0x47, 0x00, 0x20, 0x7e, + 0xd1, 0xb3, 0x94, 0x44, 0x4d, 0xe6, 0xc8, 0x8a }, + { 0x1b, 0x87, 0xf2, 0xed, 0xb8, 0x6c, 0xdb, 0xde, 0x81, 0x5f, + 0x15, 0x65, 0x3f, 0x1d, 0x0f, 0x6c, 0xc4, 0x38, 0x76, 0x4b, + 0xf6, 0xca, 0xae, 0x00, 0x63, 0xd0, 0xa0, 0xe9, 0x0f, 0xb1, + 0x54, 0x38, 0x6f, 0x3c, 0x0d, 0x68, 0x88, 0x3e, 0x09, 0x72, + 0x58, 0xfd, 0x14, 0x37, 0x6f, 0xff, 0x25, 0x4f, 0xc2, 0xca, + 0xee, 0x3f, 0x31, 0x90, 0xb5, 0x1e, 0xc2, 0xa8, 0x9e, 0x9f, + 0xc4, 0x05, 0x2e, 0xe1, 0xc4, 0xad, 0x91, 0x8f, 0x7e, 0x87, + 0x2a, 0xbb, 0x0e, 0x5b, 0x34, 0xd8, 0x9b, 0xd2, 0x70, 0x3e, + 0x6b, 0xe8, 0x4c, 0x8f, 0x2a, 0xc2, 0xd2, 0xf6, 0x57, 0xc9, + 0x50, 0x36, 0x36, 0xb3, 0x59, 0x76, 0x89, 0x49, 0x4c, 0x5e, + 0xb6, 0x1a, 0x8c, 0x13, 0x5f, 0x03, 0x02, 0x1f, 0xa9, 0xab, + 0x46, 0xb9, 0x5f, 0xaf, 0xf7, 0xcb, 0x98, 0xe5, 0x14, 0x44, + 0x00, 0x85, 0x62, 0xed, 0x1c, 0xe4, 0x73, 0x3d }, + { 0x8e, 0x02, 0x27, 0xc4, 0x3e, 0x95, 0xbc, 0x23, 0xb2, 0x2b, + 0x87, 0xb1, 0xc4, 0xa3, 0xe5, 0x9e, 0xbe, 0x3f, 0x3c, 0x77, + 0x88, 0x84, 0x8a, 0x99, 0x37, 0x4b, 0xf4, 0x16, 0x97, 0x12, + 0xa0, 0xca, 0xe2, 0x43, 0x0d, 0xe8, 0xed, 0xfc, 0xa0, 0xcc, + 0x8d, 0xf9, 0xcb, 0x47, 0x7e, 0xb8, 0x05, 0x6d, 0x87, 0xb9, + 0xb9, 0x4d, 0x39, 0x63, 0x29, 0x90, 0x4d, 0x62, 0x1e, 0x73, + 0xba, 0x32, 0x23, 0xa3, 0xb0, 0x50, 0x79, 0x1e, 0x7a, 0xa8, + 0xcc, 0x54, 0xce, 0x3e, 0x84, 0xe0, 0x2d, 0x10, 0x52, 0xc2, + 0x07, 0x70, 0xf0, 0x7a, 0x95, 0xd6, 0x80, 0x66, 0x0e, 0x3f, + 0x55, 0x56, 0xc4, 0x70, 0x31, 0xc6, 0x00, 0x54, 0x50, 0xbd, + 0xc2, 0x98, 0xd1, 0xef, 0xfb, 0xac, 0xff, 0xd9, 0xdd, 0x8f, + 0x37, 0x79, 0xa3, 0xe4, 0xb5, 0xa7, 0xce, 0x6b, 0xa7, 0x79, + 0x35, 0x79, 0x2b, 0xbb, 0x2b, 0x0b, 0x15, 0xb1 }, + { 0x14, 0xb1, 0x5a, 0xb5, 0x40, 0x54, 0x5d, 0x6e, 0x84, 0x8e, + 0xcb, 0x11, 0x4e, 0xa2, 0x06, 0xbc, 0x52, 0x8e, 0x59, 0x93, + 0x53, 0x94, 0xe9, 0x50, 0x5e, 0x9a, 0x26, 0xd3, 0x38, 0xa0, + 0x84, 0xdb, 0x3a, 0x3c, 0x16, 0xb3, 0xbd, 0xa9, 0xf3, 0x06, + 0xb3, 0xae, 0x38, 0x99, 0x4b, 0x7e, 0xf0, 0xe2, 0xc6, 0xf9, + 0xdd, 0x0d, 0xa6, 0x16, 0x5e, 0x5d, 0x22, 0x8a, 0x46, 0xe4, + 0x37, 0x8c, 0x26, 0x1d, 0xb9, 0x8e, 0xce, 0x1b, 0x0c, 0x1a, + 0x8d, 0xeb, 0xd0, 0x0e, 0x60, 0x3a, 0xbb, 0x3f, 0x82, 0x98, + 0x86, 0xec, 0xa7, 0x14, 0x32, 0x24, 0xb4, 0xf5, 0x1c, 0xc5, + 0x74, 0xcb, 0x8b, 0xdc, 0xc9, 0x0c, 0xd0, 0x28, 0x33, 0xe0, + 0x67, 0xcd, 0xca, 0xe3, 0x02, 0x17, 0x3a, 0x1f, 0xda, 0xf1, + 0xea, 0xd7, 0xdc, 0xcd, 0x5d, 0xf5, 0xff, 0x05, 0x6e, 0xeb, + 0x00, 0x0e, 0x22, 0xa8, 0x32, 0x10, 0x96, 0x4d }, + { 0x74, 0x2b, 0xbe, 0xd8, 0xc4, 0x38, 0x9e, 0x2e, 0x1e, 0x16, + 0xac, 0x76, 0x00, 0x9a, 0x55, 0xf5, 0xce, 0x57, 0xe1, 0xca, + 0x61, 0x2b, 0x57, 0x1f, 0xcb, 0xba, 0x6e, 0x30, 0x47, 0xea, + 0x72, 0x2f, 0xdf, 0x20, 0xe0, 0xe9, 0x4b, 0x63, 0xd7, 0x01, + 0xdb, 0xee, 0x97, 0xa8, 0x18, 0xfb, 0xf9, 0xfa, 0xca, 0x88, + 0x95, 0x3d, 0x60, 0x94, 0x76, 0x3c, 0xcc, 0x89, 0x6a, 0xe7, + 0x29, 0x2e, 0x9d, 0x87, 0xd6, 0xf1, 0x8d, 0x2f, 0x3f, 0x09, + 0xb4, 0xee, 0xc0, 0xad, 0x9f, 0xfa, 0xc8, 0x7b, 0x28, 0xe1, + 0xa4, 0xee, 0x0d, 0xef, 0x0d, 0x5d, 0x4e, 0x05, 0x79, 0xa0, + 0xd4, 0xe7, 0x45, 0x87, 0x08, 0x0b, 0x5f, 0x23, 0x25, 0xd9, + 0x81, 0x76, 0xa7, 0xe0, 0x33, 0xf9, 0xb5, 0x69, 0x90, 0x72, + 0xcb, 0x8e, 0x3d, 0xfe, 0x2b, 0xe1, 0x60, 0xfd, 0x7a, 0xa5, + 0x0f, 0x6d, 0x86, 0xc9, 0x66, 0x4c, 0x59, 0xa2 }, + { 0x97, 0xbd, 0x5a, 0x14, 0xb5, 0xc9, 0x41, 0x24, 0x15, 0x1e, + 0x33, 0x08, 0xf7, 0xcd, 0xd6, 0x9b, 0x71, 0x7d, 0x1c, 0xe6, + 0xe1, 0xec, 0xc1, 0x7c, 0xb3, 0x90, 0x8b, 0xbf, 0xb8, 0x65, + 0xc7, 0xf9, 0xb6, 0xbc, 0x34, 0xe8, 0x7d, 0x11, 0xe4, 0x15, + 0xed, 0x8b, 0x3d, 0xfe, 0xeb, 0x8f, 0xe0, 0xc9, 0xe6, 0xc3, + 0x5b, 0xb3, 0x4b, 0x18, 0x7c, 0x7d, 0x4c, 0x82, 0x60, 0x57, + 0x46, 0xe2, 0xa2, 0x78, 0xc8, 0xc2, 0xe0, 0x2d, 0x1f, 0x72, + 0xe0, 0x11, 0x4d, 0x88, 0xd5, 0x40, 0xe3, 0x64, 0xab, 0x94, + 0x78, 0x9d, 0xba, 0x22, 0xa9, 0xb7, 0xad, 0x78, 0x7d, 0x54, + 0xc6, 0x4b, 0x54, 0xe6, 0x6a, 0x7d, 0xde, 0x68, 0xa6, 0xe0, + 0x8c, 0xb5, 0xca, 0xc7, 0x07, 0xf8, 0xfa, 0x1f, 0x24, 0xd8, + 0xca, 0x1f, 0x4b, 0xbb, 0xfd, 0x5b, 0xc1, 0x64, 0x3a, 0xbf, + 0x23, 0xea, 0x86, 0xdc, 0xc1, 0xdc, 0x2c, 0x73 }, + { 0x31, 0x7c, 0x6d, 0x31, 0x48, 0xcc, 0x54, 0x69, 0xf8, 0x92, + 0xc5, 0x8c, 0x86, 0x4f, 0xba, 0x2e, 0x50, 0xf5, 0x3b, 0xe4, + 0xa6, 0x42, 0x4c, 0x2a, 0x4d, 0x63, 0x36, 0x7a, 0xff, 0xab, + 0xda, 0x18, 0xf0, 0x53, 0xe8, 0x48, 0x0c, 0xec, 0x8b, 0x9a, + 0xb0, 0xd9, 0xb9, 0xba, 0x26, 0xf8, 0x30, 0x5f, 0x03, 0x89, + 0xbb, 0xd8, 0xca, 0x60, 0x13, 0xc3, 0xaf, 0x77, 0xd2, 0xd1, + 0x0a, 0x8a, 0x0a, 0xf4, 0x52, 0xe8, 0x4c, 0x5f, 0xa2, 0x0c, + 0x8b, 0x96, 0x9d, 0xf7, 0x6b, 0x9b, 0x58, 0x2d, 0xe7, 0x5f, + 0xce, 0x84, 0x35, 0xa8, 0x55, 0x0f, 0x29, 0xd8, 0xb4, 0xf1, + 0x5f, 0x52, 0xc7, 0x2a, 0x45, 0xf4, 0xb8, 0xb4, 0x93, 0x74, + 0x5a, 0xbb, 0xbf, 0xdd, 0x7e, 0x52, 0xe5, 0x5b, 0xe6, 0x5e, + 0x91, 0xe5, 0x70, 0x3d, 0x4b, 0x6d, 0xdd, 0x42, 0xc4, 0x0e, + 0xe0, 0x1c, 0x62, 0xfe, 0x81, 0xe8, 0x28, 0x61 }, + { 0x6a, 0xe5, 0x97, 0x39, 0x9d, 0xa0, 0xb8, 0xfd, 0x45, 0x16, + 0x51, 0xf0, 0xee, 0x3d, 0x3f, 0x17, 0x9c, 0xc3, 0x48, 0x3c, + 0x1d, 0x90, 0x63, 0x0b, 0x37, 0x69, 0x79, 0x6a, 0xc2, 0x76, + 0x3c, 0x30, 0x49, 0x02, 0x22, 0x79, 0x52, 0x5f, 0x86, 0x36, + 0xf9, 0xd7, 0x06, 0x41, 0xec, 0xcb, 0xc1, 0x1c, 0xfc, 0x1a, + 0xe3, 0xf5, 0xef, 0xbe, 0x40, 0x08, 0x6d, 0xb9, 0x6d, 0x16, + 0xdc, 0x3f, 0x49, 0xda, 0xe9, 0xa1, 0xd2, 0x7f, 0x02, 0x2d, + 0xe1, 0x81, 0x59, 0xaf, 0xce, 0x48, 0x11, 0x0e, 0x0d, 0x6e, + 0xa0, 0x14, 0x6b, 0x5a, 0x41, 0x25, 0x2a, 0x19, 0x7f, 0xbe, + 0xf6, 0x8a, 0x71, 0x8e, 0xb2, 0x3d, 0x6b, 0x01, 0x40, 0x2f, + 0xe0, 0xc1, 0x0e, 0xa0, 0x8d, 0x5d, 0x20, 0x22, 0xff, 0x20, + 0x40, 0x8f, 0x55, 0x24, 0x0b, 0xc9, 0x31, 0x0f, 0xac, 0xae, + 0x0c, 0x35, 0x25, 0xb0, 0x2c, 0xb7, 0xd4, 0x2b }, + { 0x66, 0x49, 0x04, 0x8d, 0xbc, 0x63, 0xfe, 0x72, 0xa8, 0x4e, + 0xe5, 0xf1, 0xe7, 0x44, 0xb8, 0x2b, 0x9e, 0xf9, 0xcf, 0x3e, + 0xf1, 0x51, 0xa7, 0x26, 0x8a, 0x85, 0x95, 0xb2, 0xfa, 0x2a, + 0xff, 0xfc, 0x8f, 0xe7, 0x3b, 0xff, 0x97, 0xb6, 0x49, 0x7e, + 0x28, 0x88, 0x05, 0x34, 0xd3, 0x46, 0xf2, 0x14, 0x1a, 0x89, + 0xae, 0x22, 0xd6, 0xcf, 0x00, 0x7a, 0xb0, 0xff, 0x72, 0x26, + 0x2d, 0x97, 0xa7, 0x74, 0xee, 0x26, 0x1f, 0xb1, 0x5a, 0x2a, + 0xfa, 0x4c, 0xc5, 0x64, 0x86, 0x1f, 0xfd, 0x5f, 0x87, 0xb7, + 0xcf, 0x2c, 0x5b, 0x59, 0x8e, 0x61, 0xf9, 0x44, 0xc0, 0x6f, + 0x4a, 0x85, 0x4e, 0x0c, 0x33, 0x89, 0x1d, 0x5f, 0x23, 0x2a, + 0x5e, 0xfd, 0x55, 0xbe, 0xb6, 0x25, 0x4b, 0xd5, 0x07, 0x94, + 0x93, 0x6c, 0x20, 0x75, 0x42, 0x29, 0x30, 0xb1, 0x73, 0xd8, + 0x57, 0xb1, 0x3b, 0xc7, 0xbf, 0xf4, 0xd2, 0xee }, + { 0x4e, 0xb9, 0x3b, 0x5c, 0xf3, 0xfa, 0x49, 0xec, 0x6f, 0x2d, + 0x7a, 0xda, 0x0f, 0x13, 0x87, 0x3a, 0x3e, 0x0e, 0x98, 0xe2, + 0xa9, 0x3b, 0x0d, 0xe4, 0x96, 0xf0, 0x52, 0x6d, 0x16, 0xab, + 0xed, 0xdd, 0x2c, 0x9c, 0x1c, 0xc1, 0x83, 0xf0, 0xf1, 0xc9, + 0xfa, 0x17, 0x63, 0x77, 0xef, 0x6b, 0x1e, 0x86, 0x48, 0xb7, + 0x93, 0x56, 0xcf, 0x6c, 0x80, 0xc7, 0x09, 0x13, 0x6a, 0x6e, + 0x28, 0x30, 0xec, 0xe2, 0x85, 0x06, 0xab, 0x37, 0x9c, 0x58, + 0x1e, 0x46, 0xdc, 0xcc, 0xbf, 0xb5, 0x7d, 0x65, 0x48, 0x68, + 0x31, 0x8d, 0xbc, 0x70, 0x34, 0xb0, 0xab, 0x0b, 0x5a, 0x03, + 0x2f, 0x8a, 0xa2, 0x9b, 0xe3, 0xdb, 0x4a, 0x6d, 0xd2, 0x26, + 0xbf, 0xfc, 0x14, 0x8e, 0x81, 0x49, 0x3d, 0x9f, 0xfa, 0xb5, + 0x22, 0x6f, 0xd4, 0x7b, 0x0b, 0xd8, 0x25, 0xaa, 0xda, 0xa0, + 0x91, 0xb7, 0xbb, 0x78, 0x1e, 0x8b, 0x76, 0x0d }, + { 0x2b, 0x58, 0x2d, 0x93, 0x7c, 0x04, 0x3f, 0x68, 0xcd, 0xf5, + 0xc9, 0x0b, 0xc7, 0x00, 0x1c, 0xc8, 0x53, 0xe7, 0x81, 0xde, + 0x86, 0x80, 0x41, 0x72, 0x56, 0x05, 0xe2, 0x23, 0xe9, 0xc6, + 0xc4, 0xe0, 0xbf, 0x56, 0x54, 0x06, 0xa1, 0x9d, 0x48, 0xb6, + 0x82, 0xcf, 0xfd, 0xb3, 0xd9, 0x9f, 0x0c, 0x16, 0x18, 0x9a, + 0x5c, 0xc8, 0xbd, 0x8a, 0x68, 0x78, 0x12, 0xae, 0xef, 0xef, + 0xef, 0x3d, 0x51, 0x73, 0x93, 0x1c, 0x3f, 0x52, 0x75, 0x87, + 0x8a, 0x2a, 0xaf, 0xbb, 0xb6, 0x85, 0xfd, 0x33, 0x67, 0x6f, + 0x82, 0x22, 0x24, 0x19, 0xc1, 0x3c, 0xa2, 0xca, 0xbb, 0x9e, + 0x88, 0x97, 0x05, 0xba, 0x00, 0x68, 0x1d, 0x84, 0x9a, 0x57, + 0x55, 0x52, 0x79, 0xb7, 0x1b, 0x00, 0x14, 0xdf, 0x49, 0x1c, + 0x3f, 0x6f, 0xd1, 0x3d, 0x74, 0xf5, 0xc4, 0x02, 0x3f, 0x51, + 0xbd, 0x89, 0xf7, 0xe5, 0xe1, 0x1f, 0xae, 0x32 }, + { 0x78, 0x61, 0x51, 0x09, 0x86, 0x2d, 0xb4, 0xc0, 0x4f, 0xa4, + 0x9c, 0xe3, 0xfa, 0x57, 0x4a, 0xfd, 0xc1, 0xd8, 0xeb, 0x48, + 0xeb, 0x7c, 0xee, 0x9a, 0x4b, 0xee, 0x10, 0xd7, 0xb3, 0xf2, + 0xf7, 0xaa, 0xfe, 0x8e, 0x33, 0xcd, 0xe9, 0x3a, 0xcf, 0xcd, + 0x91, 0x5c, 0x3d, 0x06, 0xf5, 0x08, 0x64, 0xa3, 0x71, 0xcb, + 0x93, 0x6b, 0x83, 0x1e, 0xdd, 0xfb, 0xa8, 0xe3, 0x92, 0x64, + 0x9e, 0x34, 0x8c, 0x09, 0xce, 0xed, 0x17, 0x2c, 0x2f, 0x11, + 0xc4, 0x1c, 0x85, 0xe2, 0x11, 0x03, 0xd9, 0xef, 0xf3, 0x2a, + 0x78, 0x75, 0x0d, 0xb4, 0xc9, 0x8d, 0xbd, 0xd5, 0xdc, 0xba, + 0xc9, 0xf3, 0xb5, 0x7f, 0xa2, 0x1c, 0x5d, 0x60, 0x38, 0x26, + 0x54, 0x77, 0x65, 0x06, 0xc0, 0x97, 0xb3, 0xd2, 0x07, 0xff, + 0xf6, 0x6f, 0xa7, 0x33, 0x80, 0xf5, 0xe2, 0xb6, 0x9e, 0xca, + 0xa1, 0x16, 0x5c, 0x82, 0x81, 0xab, 0xc2, 0xae }, + { 0x54, 0x0b, 0x6b, 0xb7, 0x6b, 0xc9, 0xc0, 0x25, 0x9f, 0x9a, + 0x28, 0xab, 0x84, 0x16, 0x1c, 0x68, 0x6d, 0x51, 0xf9, 0x3c, + 0x3a, 0xa9, 0x56, 0xf9, 0xb4, 0xd8, 0x0e, 0xc0, 0xc3, 0xaf, + 0xa2, 0xcf, 0x64, 0x37, 0x36, 0x05, 0x54, 0x28, 0xde, 0xb5, + 0x0c, 0x8a, 0xdc, 0x05, 0x34, 0x37, 0x4c, 0x20, 0x18, 0xd4, + 0x04, 0xe4, 0x67, 0xb8, 0xe8, 0x7b, 0x57, 0xb7, 0x8b, 0x93, + 0x8e, 0xec, 0x6e, 0x1e, 0x9b, 0x0a, 0x43, 0xee, 0x28, 0x4d, + 0x3c, 0xcf, 0xbb, 0xe4, 0xed, 0x12, 0xf4, 0x27, 0xef, 0x5a, + 0x7a, 0x14, 0xcf, 0xfe, 0x82, 0xbd, 0x5f, 0xcd, 0x2a, 0x3a, + 0x43, 0x97, 0xd7, 0xcd, 0xbb, 0x24, 0x37, 0x9a, 0xe0, 0x94, + 0x51, 0xb4, 0xf1, 0xab, 0xc7, 0x6e, 0xe1, 0xe8, 0xf8, 0xc3, + 0xa4, 0x54, 0x63, 0x1a, 0xa1, 0x44, 0xfd, 0x0f, 0x0d, 0xa5, + 0x3f, 0xe3, 0xf4, 0x80, 0x7a, 0xe7, 0x2c, 0x21 }, + { 0x89, 0x7c, 0xab, 0x14, 0x92, 0xe0, 0x38, 0x8c, 0x2c, 0xa2, + 0x58, 0x67, 0x52, 0xdd, 0x50, 0xf6, 0xe1, 0xc2, 0x87, 0x76, + 0x5e, 0x20, 0xe8, 0x18, 0x3d, 0xb7, 0xd1, 0xa3, 0x44, 0x61, + 0xcd, 0x29, 0xe0, 0xb5, 0x05, 0xa1, 0x75, 0x02, 0x05, 0x38, + 0xf6, 0x9d, 0x98, 0xf0, 0x7c, 0xad, 0xf0, 0xe9, 0xdc, 0xe7, + 0xda, 0xbe, 0x0c, 0x92, 0x4d, 0x60, 0x2a, 0x97, 0x3d, 0x97, + 0xaa, 0xbf, 0x65, 0x85, 0x43, 0xaf, 0xbc, 0x78, 0xea, 0x36, + 0x2f, 0x45, 0x43, 0x6d, 0xb2, 0x93, 0x1d, 0x62, 0x98, 0xeb, + 0x2e, 0x4a, 0x83, 0x7e, 0xb9, 0xbc, 0x53, 0xde, 0x6a, 0x21, + 0xe9, 0xad, 0x58, 0x77, 0x57, 0x0f, 0x1f, 0xb0, 0x7a, 0x49, + 0xac, 0xdc, 0x78, 0x9a, 0xea, 0xfa, 0xe1, 0x45, 0xbb, 0xa8, + 0xcd, 0x81, 0x4e, 0xf5, 0x66, 0x12, 0xd8, 0x6e, 0x05, 0xd0, + 0x04, 0xe1, 0x73, 0x4c, 0x32, 0x1d, 0x31, 0x5d }, + { 0x64, 0xb0, 0x07, 0x63, 0x47, 0x6b, 0x0e, 0xc5, 0xdc, 0x62, + 0xc4, 0xa4, 0xff, 0xf6, 0x73, 0xaa, 0x2f, 0xf4, 0x7d, 0xac, + 0x30, 0xeb, 0x93, 0xa5, 0x2c, 0x82, 0x2e, 0x67, 0x20, 0xa5, + 0x18, 0x2d, 0xab, 0x90, 0x6b, 0xa3, 0xbf, 0x6c, 0xd9, 0x49, + 0x82, 0xf6, 0x29, 0xaa, 0xa6, 0xc2, 0x4f, 0xa6, 0x56, 0x4f, + 0x2a, 0x4d, 0xcf, 0x0a, 0xc9, 0x3e, 0x44, 0xf8, 0xf7, 0xfb, + 0x14, 0xfa, 0x88, 0xd2, 0xd8, 0x83, 0x62, 0x8b, 0x6c, 0x91, + 0x2f, 0xe0, 0x70, 0xd2, 0xed, 0x84, 0x0d, 0x1a, 0x83, 0x1e, + 0x74, 0x98, 0x4b, 0x11, 0xf3, 0x83, 0x37, 0x1c, 0x44, 0x92, + 0x81, 0x05, 0xb9, 0x74, 0x11, 0xa0, 0x86, 0xad, 0x0d, 0x3a, + 0x7a, 0xc8, 0x96, 0x74, 0x06, 0x87, 0xbf, 0x2c, 0x40, 0x58, + 0x14, 0x15, 0xc1, 0x1d, 0x36, 0x4c, 0xa4, 0x38, 0x20, 0x0a, + 0x59, 0xed, 0x38, 0x13, 0x0d, 0x8b, 0xab, 0x8a }, + { 0x7d, 0xd2, 0x2e, 0xa6, 0x66, 0x18, 0xed, 0x8c, 0x29, 0x1f, + 0xb8, 0x2c, 0x09, 0xe5, 0x0e, 0x84, 0x25, 0x55, 0x94, 0x24, + 0x19, 0xd6, 0x8e, 0x36, 0xe3, 0x92, 0x51, 0x53, 0x57, 0x6c, + 0xa9, 0x64, 0x0b, 0x52, 0xc3, 0x9f, 0xb0, 0x70, 0xa2, 0x93, + 0x80, 0x17, 0x8b, 0x12, 0xc2, 0x37, 0x00, 0x2a, 0xfb, 0xc7, + 0x6f, 0x56, 0xe1, 0x21, 0x7a, 0x95, 0x42, 0xda, 0xf0, 0xbb, + 0x9e, 0xf5, 0x55, 0x1c, 0x21, 0x7c, 0xab, 0x32, 0xc3, 0x9b, + 0x5a, 0xcf, 0x3f, 0x8f, 0xc0, 0x9d, 0xdc, 0x08, 0x4e, 0x01, + 0xd8, 0x78, 0x49, 0x35, 0x01, 0xec, 0x5c, 0xf1, 0xcc, 0xfd, + 0x3b, 0x33, 0xce, 0x26, 0xca, 0xd0, 0x7c, 0xe7, 0xf4, 0xc4, + 0x07, 0x38, 0xee, 0xd4, 0xc7, 0xf1, 0x3e, 0x29, 0x6c, 0x25, + 0x36, 0x93, 0xb1, 0xdb, 0x7f, 0x73, 0xb7, 0xef, 0x99, 0x52, + 0x1e, 0x3f, 0x53, 0x3e, 0xb3, 0xc9, 0xa4, 0x04 }, + { 0x31, 0x37, 0x7c, 0x66, 0x5f, 0x18, 0xfc, 0xc8, 0x95, 0x59, + 0xc8, 0x8a, 0xb1, 0x3b, 0x74, 0x89, 0x5c, 0x8f, 0x98, 0xfc, + 0x51, 0xca, 0xdf, 0x0f, 0x68, 0x5f, 0xf9, 0x4b, 0xbd, 0x3b, + 0x9d, 0x82, 0x95, 0xf9, 0x49, 0x30, 0xda, 0xc6, 0xf7, 0x90, + 0x60, 0xaf, 0xd4, 0x47, 0xb6, 0xf6, 0xa9, 0x16, 0x41, 0x64, + 0x03, 0xc1, 0x14, 0x14, 0xa4, 0x85, 0x67, 0xa9, 0xf6, 0x33, + 0x20, 0x1a, 0x42, 0x37, 0x6b, 0x0d, 0x3d, 0xdd, 0x83, 0x24, + 0x7b, 0x72, 0x8c, 0xf4, 0xeb, 0x32, 0x82, 0xe5, 0x74, 0x2b, + 0x39, 0xa1, 0x48, 0x92, 0x96, 0x95, 0x7f, 0x34, 0x2c, 0x75, + 0xd4, 0xb9, 0x30, 0x63, 0x57, 0x18, 0x95, 0x6d, 0x7f, 0x26, + 0xe5, 0x12, 0x77, 0xfc, 0x1e, 0x6e, 0xe5, 0x37, 0x9f, 0x5a, + 0x84, 0x5a, 0xde, 0x0c, 0xc7, 0x04, 0x55, 0x62, 0xfb, 0x25, + 0x7f, 0xfe, 0x84, 0x4b, 0x49, 0xcb, 0xb3, 0xbf }, + { 0x3d, 0xac, 0xc5, 0x0c, 0xa1, 0x1e, 0x52, 0x71, 0x3a, 0x5f, + 0xd6, 0x95, 0x58, 0x7e, 0xda, 0xbd, 0xef, 0x45, 0x42, 0x3c, + 0x64, 0x8a, 0x01, 0x79, 0xe2, 0x89, 0xd0, 0x24, 0x0c, 0x8f, + 0x45, 0x24, 0xb3, 0x5a, 0x98, 0x24, 0x00, 0xd5, 0xe4, 0x67, + 0xd8, 0xf9, 0x93, 0xb6, 0x05, 0x62, 0x4d, 0xd2, 0xfc, 0xf3, + 0x64, 0xfa, 0xa9, 0x50, 0x70, 0xe0, 0x44, 0x09, 0x76, 0x63, + 0x03, 0xd3, 0xe6, 0x0a, 0xe5, 0x2e, 0xfb, 0x53, 0x69, 0xe9, + 0x0a, 0x6f, 0x43, 0x98, 0x80, 0xcf, 0x25, 0x96, 0xda, 0xd2, + 0x75, 0x2e, 0xd1, 0x59, 0x71, 0xbf, 0xe6, 0x07, 0x9d, 0x95, + 0xcd, 0x4f, 0xb0, 0x9a, 0x19, 0xb5, 0x0c, 0x2d, 0xd4, 0x8a, + 0xf7, 0xb4, 0xb3, 0x75, 0x7e, 0x93, 0xe8, 0x5d, 0x75, 0x76, + 0xcb, 0x63, 0x2d, 0xcc, 0xca, 0x9f, 0x01, 0xcc, 0x36, 0xf8, + 0x35, 0xc5, 0xde, 0x09, 0x7d, 0xcf, 0xb3, 0x5f }, + { 0x86, 0x69, 0x49, 0xe1, 0x69, 0x47, 0x44, 0xf7, 0x46, 0x9b, + 0x75, 0x61, 0x23, 0x24, 0x8a, 0x31, 0xbe, 0xd3, 0xf2, 0xc3, + 0xe0, 0x69, 0xdf, 0x05, 0x5d, 0xd2, 0xdf, 0x7a, 0x60, 0xdf, + 0x19, 0x4d, 0xcd, 0x1e, 0xfd, 0xb4, 0xf3, 0xe9, 0xdf, 0x64, + 0x6f, 0xd5, 0x76, 0x87, 0xf9, 0xdd, 0x9f, 0x0a, 0x7a, 0xb2, + 0x44, 0x04, 0xb1, 0x7b, 0x28, 0x42, 0xe5, 0x1a, 0x0d, 0x53, + 0x88, 0x07, 0xf3, 0xa0, 0x0a, 0x9b, 0xa3, 0x85, 0xb9, 0xbf, + 0xd2, 0xfb, 0xf3, 0xfb, 0x62, 0x10, 0xae, 0xc2, 0x3e, 0xaf, + 0xf7, 0xb7, 0xb9, 0xba, 0xdf, 0x1c, 0xdb, 0x49, 0xf3, 0x5e, + 0x45, 0x18, 0xaa, 0x28, 0x6f, 0xd0, 0xb6, 0xc6, 0x4d, 0x28, + 0xd8, 0x48, 0x1e, 0x45, 0x80, 0x7f, 0x5c, 0xe9, 0xbe, 0x78, + 0x2e, 0x8a, 0xa4, 0x6d, 0xcb, 0xe1, 0x70, 0x53, 0xc5, 0x27, + 0xcb, 0x3e, 0x4f, 0x94, 0x64, 0x99, 0xae, 0x4c }, + { 0x57, 0x43, 0x52, 0xb8, 0x8b, 0x1f, 0xa5, 0x98, 0xdc, 0x38, + 0x84, 0xff, 0x5b, 0x08, 0x31, 0x77, 0xc2, 0xd3, 0x83, 0x73, + 0x94, 0xf7, 0xec, 0x4e, 0x37, 0xa5, 0x05, 0x69, 0xc2, 0x95, + 0xdc, 0x46, 0xfa, 0x84, 0x4e, 0xb0, 0x7b, 0x96, 0xd4, 0x80, + 0x0d, 0x2b, 0x84, 0x1b, 0x33, 0x29, 0xdb, 0x82, 0x85, 0x2d, + 0x44, 0x35, 0x4e, 0x2d, 0x5d, 0xd0, 0xd7, 0x9d, 0xb1, 0xbb, + 0xd7, 0x4c, 0x70, 0x91, 0x3b, 0x66, 0x4b, 0x1e, 0x7d, 0x08, + 0x77, 0xb5, 0x50, 0x01, 0x39, 0x4e, 0x99, 0x0c, 0x03, 0xa0, + 0x38, 0x59, 0x8e, 0xa1, 0x06, 0x6c, 0xb4, 0xd7, 0x93, 0xaf, + 0x1f, 0xbd, 0xd3, 0xb2, 0x18, 0xab, 0xc9, 0x58, 0x1c, 0x3e, + 0x84, 0x8e, 0x3d, 0x58, 0x0c, 0x92, 0xe9, 0x21, 0xb2, 0x3c, + 0xf2, 0x90, 0x2c, 0xd6, 0xf3, 0x33, 0xf5, 0x4a, 0x6f, 0xbf, + 0x3a, 0x9a, 0x0d, 0xa5, 0x3f, 0x4a, 0xb0, 0x7a }, + { 0x3e, 0x43, 0x1a, 0xf2, 0x06, 0xae, 0x3c, 0x4f, 0x24, 0x18, + 0xc6, 0x24, 0xd3, 0xb6, 0xa3, 0xa1, 0x38, 0x84, 0xd5, 0xd8, + 0xf8, 0x53, 0xa9, 0x4e, 0x5f, 0xcb, 0xcc, 0x09, 0x69, 0x96, + 0x01, 0x1a, 0x44, 0x45, 0x21, 0xa1, 0x09, 0x9f, 0x68, 0x73, + 0x3f, 0x20, 0x43, 0x40, 0xd2, 0x94, 0x64, 0x93, 0x25, 0x3a, + 0x3a, 0x69, 0xf0, 0xd6, 0x78, 0x2b, 0xa9, 0x63, 0x35, 0xbc, + 0x09, 0x1c, 0x19, 0xeb, 0x4e, 0x76, 0x48, 0xc7, 0x61, 0xc2, + 0x20, 0x1d, 0x99, 0x6c, 0xca, 0xf0, 0xde, 0x20, 0x28, 0xd8, + 0x2e, 0xc2, 0x7e, 0x49, 0x28, 0x59, 0x85, 0xdf, 0x8a, 0x84, + 0xec, 0x00, 0xba, 0xa7, 0x01, 0x98, 0xdd, 0x9d, 0xa8, 0x60, + 0x78, 0x27, 0x0d, 0x56, 0x7c, 0x44, 0xab, 0x59, 0x7b, 0xe6, + 0x5f, 0xd0, 0x3c, 0x19, 0xfd, 0x26, 0x0b, 0x48, 0x7e, 0xaf, + 0xed, 0x21, 0x93, 0xf7, 0x0d, 0x5d, 0x7c, 0xe9 }, + { 0x6d, 0xad, 0x3f, 0x15, 0xe2, 0x66, 0x4d, 0x35, 0x1c, 0x3d, + 0x7d, 0x82, 0xa2, 0x03, 0xce, 0xf1, 0x8a, 0x0f, 0xbb, 0xd1, + 0x86, 0xbb, 0xfa, 0x41, 0xf2, 0x69, 0x31, 0xba, 0xad, 0x89, + 0x6c, 0x2a, 0xcd, 0x57, 0x76, 0x66, 0x53, 0xbb, 0xb3, 0x43, + 0x4f, 0x1c, 0x96, 0x86, 0x11, 0xe9, 0x35, 0xc5, 0x7f, 0xc2, + 0xa3, 0xed, 0x85, 0x1e, 0xe4, 0x1e, 0xfd, 0x1b, 0xfe, 0x44, + 0x1a, 0x94, 0x2f, 0x7d, 0x33, 0x6a, 0x4f, 0xda, 0xae, 0xfd, + 0xb6, 0x46, 0xd0, 0x90, 0xa6, 0xa3, 0xaa, 0x45, 0x6d, 0x6f, + 0xfe, 0xb2, 0xaf, 0xa6, 0x36, 0xf0, 0xb7, 0x55, 0x43, 0xae, + 0x07, 0x41, 0xd9, 0x2f, 0x29, 0x00, 0xa8, 0x6d, 0x15, 0x98, + 0x50, 0x93, 0xa6, 0xd3, 0xbf, 0x3a, 0xf4, 0xd0, 0x54, 0x41, + 0x07, 0x68, 0x36, 0x50, 0x1a, 0xae, 0xd0, 0xc0, 0x33, 0xc3, + 0xf9, 0x67, 0xd9, 0x39, 0x83, 0xd3, 0x81, 0xf1 }, + { 0x24, 0x38, 0xe9, 0xd4, 0x5f, 0x51, 0x7a, 0x3f, 0xc8, 0x7a, + 0x53, 0x90, 0x27, 0xd2, 0xd5, 0x5f, 0xfc, 0x3e, 0xe7, 0xc6, + 0x0b, 0xff, 0x83, 0x7c, 0x56, 0x59, 0x0b, 0xa4, 0x93, 0x83, + 0xd2, 0xd3, 0x08, 0xe5, 0x84, 0x48, 0x67, 0x23, 0x75, 0xc5, + 0x11, 0x09, 0xa6, 0x13, 0xdf, 0x3a, 0x8d, 0xc3, 0x51, 0x7f, + 0x2f, 0x1d, 0xbe, 0xbd, 0x01, 0x29, 0xb0, 0x69, 0x59, 0x9d, + 0xf8, 0x95, 0x8c, 0x6f, 0x7a, 0x41, 0x40, 0x21, 0x71, 0x98, + 0xb2, 0x1b, 0x97, 0x4a, 0x9f, 0x03, 0x8c, 0x0a, 0xcb, 0xa7, + 0x06, 0x1b, 0xc9, 0x26, 0xc3, 0xd9, 0x6a, 0x19, 0x15, 0x09, + 0x0f, 0x55, 0xd9, 0x90, 0x3c, 0x43, 0x5e, 0x76, 0x90, 0x4a, + 0x33, 0xc5, 0x8e, 0xb6, 0x2c, 0xc2, 0x78, 0xc6, 0xf1, 0x33, + 0x21, 0xd5, 0x62, 0x19, 0xc5, 0xb6, 0xe7, 0xdf, 0xb1, 0x28, + 0xd1, 0x94, 0x0b, 0x7d, 0x12, 0xec, 0x35, 0xa1 }, + { 0x13, 0xf3, 0x90, 0x11, 0xaf, 0xe3, 0x0e, 0x01, 0x00, 0xa8, + 0xb7, 0xb2, 0x96, 0x20, 0x0e, 0x67, 0x9d, 0x2a, 0x97, 0xcd, + 0xff, 0x79, 0x5b, 0xb3, 0xf4, 0xad, 0xa5, 0x11, 0xbd, 0x41, + 0x6b, 0x67, 0xdd, 0xb4, 0x7c, 0x73, 0x68, 0xf1, 0xf7, 0xf2, + 0x8b, 0x33, 0xef, 0x46, 0x2a, 0x51, 0x34, 0x90, 0xf1, 0xb4, + 0x63, 0x3c, 0xd7, 0x70, 0x1f, 0x5b, 0x20, 0x5b, 0x4c, 0x89, + 0x1b, 0xe2, 0x81, 0xcb, 0x71, 0x50, 0xe0, 0x4b, 0x6b, 0xbc, + 0x4f, 0xb1, 0xf7, 0x37, 0xc3, 0xc2, 0xf1, 0xda, 0x60, 0x10, + 0x6f, 0x14, 0x42, 0x9c, 0xd0, 0xb3, 0xe2, 0x31, 0xbd, 0x0d, + 0xac, 0x54, 0xe6, 0x3f, 0x24, 0x90, 0x61, 0xc6, 0x1d, 0x94, + 0x12, 0xe5, 0x1e, 0xb5, 0xae, 0xf1, 0xcd, 0xc9, 0x97, 0xb6, + 0x5d, 0xdf, 0xe5, 0x5f, 0x1a, 0x32, 0xf3, 0xc9, 0xbe, 0xd5, + 0xc4, 0xa4, 0x53, 0x08, 0x88, 0x15, 0xaf, 0x3c }, + { 0x45, 0x8d, 0x4b, 0x6b, 0x68, 0x07, 0x03, 0xb6, 0x17, 0xa7, + 0xce, 0x24, 0xcb, 0xda, 0x1b, 0x0b, 0x29, 0x84, 0x66, 0xd4, + 0x72, 0x2b, 0x7b, 0xc9, 0xbc, 0x07, 0x5b, 0x73, 0xd8, 0xc4, + 0xba, 0x8b, 0x33, 0xdd, 0x77, 0xa0, 0x1c, 0xf2, 0xb8, 0x66, + 0x24, 0x97, 0xe0, 0xbf, 0xa4, 0xd8, 0xd0, 0x18, 0xfe, 0x31, + 0x1a, 0xd0, 0x1b, 0xbd, 0xa0, 0x05, 0xce, 0xea, 0x99, 0xd5, + 0x56, 0x41, 0x51, 0x10, 0x29, 0x3b, 0xb5, 0xe7, 0x53, 0x5c, + 0x5d, 0x0b, 0x2a, 0x83, 0x8c, 0xa8, 0x26, 0x3b, 0x60, 0x62, + 0x3f, 0x90, 0xd7, 0x10, 0x68, 0xc0, 0xe5, 0x84, 0xcb, 0xb8, + 0x30, 0x24, 0x99, 0x80, 0x45, 0xdf, 0xde, 0x8d, 0x80, 0x45, + 0x26, 0x8b, 0xca, 0x77, 0xf8, 0x79, 0x30, 0x68, 0x1c, 0x9a, + 0x51, 0x5a, 0x50, 0x61, 0x10, 0xf3, 0x4a, 0x29, 0xff, 0x46, + 0x3d, 0xd2, 0x96, 0xef, 0x7b, 0xd0, 0xc8, 0x27 }, + { 0x5f, 0x13, 0xf5, 0xfa, 0xb6, 0xfb, 0xbf, 0x91, 0x62, 0x8e, + 0x3b, 0x06, 0x56, 0x68, 0xf9, 0x5c, 0x00, 0xae, 0x04, 0x57, + 0x62, 0x4d, 0xb0, 0x1a, 0x32, 0x59, 0xef, 0x18, 0x2f, 0x72, + 0x55, 0x6b, 0x68, 0xef, 0x0b, 0x70, 0x8f, 0x27, 0xd4, 0x9f, + 0x21, 0xae, 0x03, 0x19, 0x97, 0x84, 0x70, 0x64, 0xfe, 0x5b, + 0x5c, 0xb5, 0x85, 0xc9, 0xeb, 0x8a, 0x3e, 0xfc, 0x2e, 0x9b, + 0x1b, 0x48, 0x20, 0xc3, 0xea, 0xe9, 0x5e, 0xa5, 0x99, 0x23, + 0x02, 0x20, 0xe1, 0x0a, 0x14, 0x49, 0xa1, 0xb3, 0x64, 0x10, + 0x46, 0xb9, 0xb0, 0x00, 0x73, 0x04, 0x02, 0xbd, 0x18, 0x12, + 0xe8, 0x19, 0x36, 0x94, 0xd0, 0x0d, 0x7a, 0x4a, 0xdc, 0x3c, + 0x2f, 0x65, 0x49, 0xa8, 0x69, 0x8b, 0x58, 0x58, 0xf9, 0x94, + 0xf7, 0x00, 0x05, 0xa5, 0x69, 0x6e, 0x4d, 0x32, 0x0a, 0x0d, + 0x8a, 0x26, 0xa2, 0x0e, 0x4d, 0x54, 0xd8, 0xb2 }, + { 0x21, 0x96, 0x49, 0x5d, 0xa3, 0x7b, 0xa4, 0xa2, 0x11, 0x62, + 0x5a, 0x44, 0x05, 0xf8, 0x02, 0xf6, 0x35, 0x0d, 0xc5, 0x65, + 0x6f, 0x5a, 0x17, 0x4d, 0x7c, 0x0a, 0x3c, 0x53, 0x17, 0x71, + 0x3a, 0x1a, 0x37, 0xc9, 0xe3, 0xa2, 0xe8, 0x03, 0xe6, 0x9c, + 0x90, 0xac, 0xb2, 0x90, 0x25, 0xce, 0xc9, 0x9c, 0x73, 0x71, + 0x3e, 0x66, 0x55, 0xbf, 0x1c, 0xa7, 0x0e, 0xed, 0x92, 0xdf, + 0x6b, 0x9c, 0x48, 0x2d, 0xfd, 0xf0, 0xec, 0xe7, 0xc3, 0x59, + 0x89, 0xca, 0x1f, 0x0f, 0xdf, 0x17, 0x7d, 0x11, 0x67, 0x4e, + 0xf7, 0x41, 0xc8, 0xf2, 0x29, 0x0d, 0xf0, 0x5c, 0xc4, 0xd3, + 0x31, 0x7b, 0x68, 0x21, 0x7f, 0xfd, 0xde, 0xfa, 0x6a, 0xbc, + 0x9a, 0x66, 0xe3, 0xab, 0xea, 0x66, 0xbf, 0x88, 0xea, 0x8b, + 0x36, 0x77, 0xae, 0xa1, 0xbd, 0xe9, 0x6f, 0x88, 0x3e, 0xc8, + 0x7c, 0x6e, 0xd9, 0xae, 0x3a, 0x9b, 0x0d, 0xc6 }, + { 0x93, 0xad, 0x0e, 0xb0, 0x04, 0x47, 0x5f, 0x08, 0x29, 0x71, + 0xce, 0xa7, 0x3d, 0x56, 0xfa, 0x62, 0x5a, 0xa0, 0xc4, 0x7d, + 0x6c, 0xe5, 0x48, 0xa0, 0x04, 0xa1, 0x79, 0x40, 0xd2, 0x18, + 0x97, 0xc1, 0x33, 0xef, 0x7b, 0xc3, 0x42, 0x7f, 0x34, 0x35, + 0x2c, 0x3c, 0x8c, 0xbd, 0x14, 0x41, 0x54, 0xb0, 0x9f, 0xf1, + 0x09, 0x52, 0x9a, 0xaa, 0xa4, 0x04, 0xc4, 0x8e, 0xfc, 0x6b, + 0x95, 0xb1, 0x97, 0xf9, 0xf3, 0x69, 0x31, 0x29, 0x8e, 0x8f, + 0x7d, 0xb5, 0x97, 0x09, 0xbc, 0x28, 0x51, 0x6e, 0xc8, 0xec, + 0x84, 0xad, 0xb1, 0xa2, 0xd7, 0x38, 0xf1, 0xff, 0x3c, 0x2b, + 0x79, 0x86, 0xcb, 0x6e, 0xc2, 0x50, 0xbe, 0xef, 0xce, 0x58, + 0x0a, 0xe2, 0x2b, 0xc5, 0xc6, 0xa0, 0xce, 0xab, 0xdf, 0xe2, + 0x66, 0x9e, 0xab, 0x9e, 0x91, 0xd7, 0x65, 0xd1, 0x4c, 0xf4, + 0x00, 0xcb, 0x2f, 0xd3, 0x13, 0x14, 0x26, 0x80 }, + { 0x73, 0xf8, 0xc3, 0xf0, 0xea, 0x41, 0xc0, 0x34, 0x44, 0x08, + 0xdd, 0x42, 0x58, 0x44, 0xd1, 0xf9, 0x2b, 0x95, 0x22, 0x09, + 0x57, 0x6e, 0x58, 0x8d, 0xc5, 0xfc, 0x88, 0xd5, 0x44, 0x17, + 0xea, 0xde, 0x05, 0x86, 0xf7, 0x2f, 0xbc, 0xcd, 0xe4, 0x51, + 0xe5, 0x67, 0x4c, 0x4b, 0xf8, 0x23, 0xd7, 0x97, 0xef, 0x8a, + 0x94, 0x48, 0xc9, 0x01, 0x6c, 0x8c, 0x1d, 0x56, 0x46, 0xb8, + 0x14, 0x3f, 0xe0, 0x79, 0xc0, 0x4e, 0xd0, 0xb7, 0x26, 0xe6, + 0x62, 0xf7, 0x25, 0x4c, 0x05, 0xc3, 0xe0, 0x2f, 0xcc, 0xcf, + 0x18, 0xf6, 0xf0, 0x9c, 0x13, 0x02, 0xe3, 0x23, 0x3c, 0x38, + 0xd3, 0xfb, 0x68, 0x7a, 0x5b, 0x3d, 0x63, 0xa9, 0xb8, 0xd5, + 0xd3, 0x39, 0x22, 0xde, 0x62, 0x74, 0xe3, 0x86, 0x3b, 0x6b, + 0x50, 0xf2, 0x61, 0xe4, 0x77, 0xf7, 0x65, 0x15, 0xe8, 0xdd, + 0x7a, 0x0b, 0x69, 0x67, 0x98, 0x8a, 0x99, 0x63 }, + { 0x01, 0x08, 0xae, 0x39, 0xad, 0xbe, 0xdd, 0x75, 0xdf, 0xed, + 0x25, 0xd9, 0x7c, 0xaa, 0x51, 0xb8, 0x7c, 0xf9, 0xd4, 0x07, + 0x21, 0x34, 0x1a, 0x8a, 0x0f, 0x26, 0x87, 0x45, 0xfc, 0xa3, + 0x25, 0xe4, 0xa2, 0xe0, 0x58, 0xfc, 0xb1, 0x5a, 0xe2, 0x06, + 0xa1, 0x4e, 0x05, 0x52, 0x2d, 0x16, 0xe3, 0x61, 0x96, 0x3d, + 0xee, 0xa6, 0x28, 0xb7, 0x91, 0xcc, 0xef, 0xff, 0x6d, 0xae, + 0x33, 0x21, 0xed, 0xcd, 0x74, 0x9e, 0x0d, 0x98, 0xea, 0x36, + 0xa0, 0x15, 0x62, 0x6e, 0xec, 0xf1, 0x29, 0x3a, 0xa8, 0xcf, + 0xaa, 0x58, 0x44, 0x28, 0x51, 0x9f, 0x7b, 0xf3, 0x78, 0x04, + 0xc9, 0xad, 0x85, 0x7c, 0xae, 0xa6, 0x1d, 0x39, 0x09, 0x44, + 0xcb, 0x20, 0x88, 0x8e, 0x0d, 0xb5, 0xbe, 0x17, 0x6e, 0x8f, + 0x15, 0xa0, 0x3b, 0x14, 0x27, 0xf3, 0x3a, 0xc7, 0x18, 0x36, + 0x89, 0x53, 0x4f, 0xc8, 0x5d, 0xf7, 0x63, 0xdd }, + { 0x80, 0x7c, 0x06, 0xd8, 0xeb, 0x13, 0xc1, 0xdf, 0x34, 0x8b, + 0xb4, 0x2f, 0xa0, 0xc4, 0x52, 0x33, 0x88, 0x48, 0x08, 0x9b, + 0xac, 0x85, 0xa4, 0xe1, 0xdf, 0xfc, 0x46, 0xab, 0xd5, 0x09, + 0x7e, 0x1f, 0x0c, 0x9a, 0xad, 0x75, 0x44, 0x5d, 0xad, 0x00, + 0x88, 0x89, 0x1e, 0x36, 0xfb, 0x3a, 0x9b, 0x17, 0xfb, 0xbe, + 0x4b, 0xe8, 0x1e, 0xe0, 0xa5, 0x99, 0xc3, 0xf6, 0x5b, 0x99, + 0x46, 0xc5, 0xda, 0xfc, 0xdd, 0xc8, 0x38, 0x03, 0x9d, 0x59, + 0x51, 0x1a, 0x16, 0xaf, 0x05, 0x99, 0x0c, 0xc6, 0x9c, 0x89, + 0xfc, 0x8b, 0xef, 0xe7, 0x54, 0xe3, 0x09, 0x0b, 0xde, 0x10, + 0xb0, 0x73, 0xe9, 0xbb, 0x00, 0x4d, 0x24, 0xdb, 0x7d, 0xae, + 0x8d, 0x0b, 0x91, 0xc8, 0x77, 0x3a, 0x53, 0xe6, 0xe2, 0x61, + 0xd8, 0xa6, 0xaa, 0x05, 0xb1, 0x1e, 0xab, 0x0c, 0x73, 0x25, + 0x54, 0xd1, 0x78, 0xf3, 0xa9, 0xe8, 0x8f, 0x63 }, + { 0x16, 0x42, 0x4c, 0x6c, 0x99, 0x60, 0x7a, 0x61, 0xb2, 0xfd, + 0xfa, 0x36, 0xb5, 0x53, 0x99, 0xfc, 0x26, 0x92, 0xc6, 0x26, + 0x17, 0x58, 0x3b, 0x53, 0xaa, 0xc4, 0xff, 0xcf, 0xc3, 0x9b, + 0x06, 0x34, 0x93, 0xf1, 0x80, 0xf7, 0xfa, 0x2f, 0x35, 0x8b, + 0x5d, 0xf7, 0x6b, 0x3a, 0xef, 0x0f, 0x27, 0x5a, 0x08, 0xff, + 0x7d, 0x15, 0x99, 0x82, 0x11, 0xa4, 0x89, 0xb5, 0x68, 0x81, + 0xf7, 0x21, 0x09, 0xbd, 0xce, 0x15, 0x25, 0xc9, 0xed, 0x39, + 0x9c, 0x0e, 0x97, 0x4d, 0xb3, 0xde, 0xda, 0x86, 0x1d, 0x3b, + 0x53, 0xa9, 0xa9, 0x42, 0x99, 0x8c, 0x95, 0xfb, 0xe5, 0x93, + 0x43, 0xe4, 0x60, 0xad, 0x1a, 0xf2, 0x7b, 0xdb, 0x20, 0x1a, + 0x8b, 0x70, 0x55, 0x7c, 0x24, 0x48, 0x4c, 0x92, 0xa0, 0x2f, + 0x8f, 0xdb, 0xba, 0x9d, 0x54, 0x83, 0x8b, 0xb7, 0xb7, 0xaf, + 0x00, 0xa9, 0x69, 0xec, 0x98, 0xee, 0x0e, 0xf6 }, + { 0x55, 0x44, 0xe6, 0x02, 0xa4, 0xf4, 0x47, 0x8a, 0xdd, 0xda, + 0xf4, 0xb9, 0xfb, 0x58, 0x31, 0xb1, 0x3d, 0xfe, 0x6b, 0xc1, + 0x72, 0x53, 0xa5, 0x1b, 0xa3, 0xc9, 0xad, 0xff, 0xac, 0xcc, + 0xb8, 0x5c, 0x47, 0x4a, 0x3e, 0x14, 0xf0, 0x3d, 0xed, 0x28, + 0x3d, 0x16, 0xfc, 0x45, 0x45, 0xb0, 0xe9, 0xeb, 0xa9, 0xe6, + 0x55, 0xe4, 0x2e, 0x7f, 0x34, 0x04, 0x44, 0xff, 0x67, 0xb9, + 0xed, 0x64, 0xd1, 0x2c, 0xd4, 0x39, 0x61, 0x41, 0x4b, 0x8e, + 0xfa, 0x0c, 0x88, 0xae, 0x40, 0x98, 0xbc, 0xc7, 0x72, 0x72, + 0xbc, 0xec, 0xd2, 0x58, 0xca, 0xf2, 0xd1, 0x22, 0x98, 0x38, + 0x45, 0x50, 0x9b, 0xe9, 0x96, 0x74, 0x30, 0xb7, 0xab, 0x25, + 0xa9, 0xdf, 0x69, 0x1a, 0x32, 0xc8, 0x2e, 0x99, 0xef, 0xe8, + 0xb0, 0x89, 0x25, 0x44, 0xc1, 0xc2, 0xfe, 0x3a, 0xf4, 0x18, + 0x5d, 0xd6, 0x5c, 0x55, 0xdd, 0x27, 0x44, 0xa9 }, + { 0x57, 0x35, 0x99, 0x5c, 0xe2, 0x41, 0xd2, 0x61, 0xdd, 0x7d, + 0x3e, 0xdd, 0x1e, 0xd6, 0x0f, 0x42, 0xc1, 0xa4, 0xcd, 0xce, + 0x2d, 0xec, 0x53, 0xcf, 0x80, 0xb7, 0xec, 0xdc, 0x22, 0x99, + 0x4b, 0x43, 0x72, 0x0b, 0x59, 0xde, 0x19, 0xb1, 0xb5, 0x40, + 0xd0, 0xf7, 0x0e, 0x6e, 0xb2, 0x79, 0x46, 0x81, 0x76, 0xc8, + 0x8b, 0xd2, 0x09, 0xd0, 0x9a, 0xf1, 0x83, 0x10, 0x74, 0x46, + 0xcb, 0x42, 0x03, 0x3c, 0x20, 0x53, 0xc5, 0xe0, 0x1f, 0x6c, + 0x7d, 0x29, 0x83, 0x49, 0xdd, 0x73, 0xc2, 0x90, 0xd9, 0xd8, + 0x16, 0x3d, 0x05, 0x00, 0xed, 0x94, 0x58, 0x70, 0x35, 0x2c, + 0x8c, 0x3f, 0x2d, 0x34, 0x1a, 0xb1, 0xe9, 0xd9, 0xe1, 0xe9, + 0x08, 0x83, 0x30, 0x8c, 0xae, 0x27, 0x42, 0xdb, 0x7b, 0x42, + 0xc5, 0xa8, 0x01, 0x22, 0x71, 0x6f, 0x63, 0xbd, 0xc8, 0xef, + 0x89, 0x7c, 0x53, 0x13, 0xba, 0xa8, 0x0b, 0x4f }, + { 0x88, 0x54, 0x86, 0xdf, 0x3e, 0xc4, 0x5e, 0xf0, 0xe4, 0x68, + 0xed, 0x5f, 0x04, 0x9a, 0x69, 0x17, 0xbb, 0xd3, 0xb0, 0x81, + 0x8a, 0x95, 0x40, 0xc2, 0x5c, 0xc2, 0x28, 0x21, 0x76, 0x8a, + 0xd9, 0x9a, 0xf8, 0x72, 0x9b, 0xc0, 0xea, 0xce, 0x64, 0xc9, + 0xac, 0x39, 0x04, 0xe4, 0xc9, 0xcf, 0x34, 0x65, 0xdb, 0x9a, + 0x59, 0x84, 0xbb, 0x1f, 0xf9, 0x4d, 0xd1, 0x43, 0xb2, 0xda, + 0x4a, 0x4c, 0x5e, 0x89, 0x7b, 0x0c, 0x46, 0xcd, 0x7c, 0x1b, + 0x7d, 0xfd, 0x1b, 0x71, 0x85, 0xcf, 0x08, 0x86, 0x87, 0x73, + 0xec, 0x49, 0x74, 0x21, 0x5b, 0x60, 0x0f, 0x33, 0x4e, 0xee, + 0x44, 0x19, 0x61, 0x18, 0xa1, 0xf5, 0xab, 0xde, 0xb0, 0x33, + 0xe3, 0x03, 0x1b, 0xec, 0xc0, 0x1e, 0xeb, 0xbd, 0x27, 0x1e, + 0xc6, 0x12, 0x68, 0x56, 0xc1, 0x64, 0x33, 0xab, 0x33, 0x88, + 0xdc, 0x4b, 0xa3, 0xfb, 0xa0, 0x23, 0x70, 0x56 }, + { 0x31, 0xce, 0xcf, 0xe8, 0xd4, 0xab, 0x96, 0x2d, 0xc5, 0xdd, + 0x4d, 0x3e, 0xc9, 0x1f, 0xf9, 0xd7, 0x29, 0x08, 0x32, 0x87, + 0xaa, 0xa4, 0xce, 0x0c, 0x33, 0xd8, 0x16, 0x97, 0xf1, 0x19, + 0xd6, 0xe0, 0x4d, 0x0e, 0x8b, 0xcf, 0x99, 0x4f, 0xc5, 0x03, + 0x1a, 0x0b, 0x96, 0xe4, 0x0f, 0x81, 0xf9, 0x1c, 0x98, 0xb5, + 0xd0, 0xab, 0x18, 0x5e, 0xae, 0x19, 0x29, 0xe1, 0x1a, 0xa2, + 0x68, 0x85, 0xe6, 0xb9, 0xbc, 0xb0, 0xe8, 0xa2, 0x71, 0xd3, + 0x68, 0x10, 0x9e, 0x24, 0x96, 0x0f, 0x1a, 0x1b, 0x73, 0xc6, + 0x76, 0x07, 0xdd, 0x08, 0x55, 0xef, 0x8d, 0xef, 0xac, 0xa6, + 0x9a, 0xe8, 0x24, 0x1e, 0xe8, 0xff, 0x20, 0x55, 0xa3, 0x1b, + 0x19, 0xfe, 0x33, 0x39, 0xcc, 0xb0, 0x07, 0x0b, 0x32, 0x5b, + 0xe3, 0x24, 0x3d, 0xb2, 0x71, 0x9f, 0x25, 0xa7, 0xb4, 0x51, + 0x6a, 0x94, 0x2c, 0x93, 0x4b, 0xdf, 0xf4, 0x64 }, + { 0x69, 0x61, 0xb4, 0x6a, 0xda, 0x25, 0x47, 0xb3, 0x5d, 0x8f, + 0x3c, 0xf0, 0x9a, 0x6a, 0x4e, 0xc3, 0x11, 0xb0, 0x86, 0x3b, + 0xd6, 0xd6, 0xf1, 0xd2, 0x72, 0xfe, 0xfc, 0x05, 0x75, 0xd9, + 0xcb, 0x3d, 0x2b, 0x7c, 0x79, 0x45, 0xff, 0x32, 0x52, 0xf8, + 0x65, 0xff, 0xa5, 0xf6, 0x6c, 0x74, 0x2a, 0xc4, 0x48, 0x0e, + 0xd4, 0xfb, 0xc5, 0x51, 0x6c, 0xa9, 0xf5, 0x02, 0xf6, 0x6d, + 0xec, 0xd6, 0xfa, 0x3d, 0x83, 0x9a, 0xa7, 0xbd, 0xc9, 0xd2, + 0x0f, 0xf1, 0x10, 0x09, 0xc0, 0xd9, 0xb4, 0xfb, 0xb5, 0x9c, + 0x98, 0x00, 0xa2, 0x3f, 0xae, 0xcd, 0x69, 0x75, 0x96, 0x63, + 0xe6, 0xad, 0x5b, 0xb5, 0x23, 0xbd, 0x8e, 0x9d, 0xe8, 0x4d, + 0xa3, 0xd0, 0xfa, 0x90, 0xfe, 0x59, 0x02, 0xd4, 0x92, 0x1c, + 0x36, 0xa0, 0xe5, 0xdd, 0x32, 0xb3, 0xb1, 0x94, 0x36, 0xdf, + 0x43, 0x7b, 0xfd, 0x9a, 0xfc, 0x8b, 0x21, 0xe8 }, + { 0x6a, 0x63, 0xa9, 0x0c, 0x53, 0x75, 0x52, 0x12, 0x19, 0x64, + 0xe2, 0x2f, 0x07, 0x81, 0xaa, 0xd9, 0x89, 0xa9, 0xa3, 0x2e, + 0xcd, 0x3f, 0x79, 0x4f, 0xdd, 0xae, 0xc4, 0x2b, 0x73, 0xce, + 0x5b, 0xe9, 0x2e, 0x25, 0x4d, 0x9e, 0x36, 0x05, 0x1f, 0x9f, + 0x1e, 0xb5, 0x1f, 0x32, 0x54, 0xe8, 0x41, 0x23, 0x69, 0x7e, + 0x20, 0xa2, 0x97, 0x07, 0xfa, 0x21, 0xda, 0x78, 0x2d, 0x1d, + 0x93, 0x41, 0x3c, 0xa7, 0xd6, 0x71, 0x20, 0xe6, 0xb6, 0x55, + 0xaf, 0x5d, 0xf9, 0x78, 0x1e, 0xdd, 0x24, 0x6e, 0x3f, 0xd2, + 0x4e, 0x4b, 0x88, 0xed, 0xfb, 0x8c, 0xe1, 0x90, 0xa6, 0xe7, + 0x19, 0xfd, 0x9c, 0x6f, 0x40, 0x0e, 0xa1, 0xf9, 0x1d, 0x44, + 0x70, 0x9d, 0x54, 0xf0, 0xec, 0xa1, 0x7a, 0x5b, 0xdb, 0x28, + 0xa0, 0x4c, 0x1e, 0xd5, 0x54, 0x6b, 0x57, 0xaf, 0x14, 0xd9, + 0xd0, 0x7b, 0x58, 0x7e, 0xcb, 0x35, 0xe2, 0xac }, + { 0x51, 0xed, 0x4a, 0x22, 0xd1, 0x51, 0xd9, 0x0e, 0xff, 0xc8, + 0x9f, 0xfd, 0x82, 0x55, 0x29, 0x61, 0xa5, 0x47, 0x64, 0x46, + 0x82, 0x35, 0xcd, 0x0b, 0x8c, 0x27, 0xf8, 0x92, 0x86, 0x17, + 0xf1, 0x65, 0xc2, 0x0b, 0x93, 0x07, 0x0e, 0x02, 0x1e, 0xd3, + 0xa5, 0x3a, 0x81, 0xb3, 0x6e, 0xa5, 0x02, 0xea, 0x80, 0x9b, + 0xf0, 0x74, 0xe8, 0x44, 0xa5, 0x76, 0xab, 0xcc, 0x78, 0x13, + 0x5c, 0xa4, 0x71, 0xdd, 0xd6, 0xed, 0x58, 0x16, 0x5b, 0xa3, + 0xf4, 0xa1, 0x65, 0x88, 0x80, 0xc1, 0x5a, 0x4d, 0x3e, 0x7c, + 0xf8, 0x65, 0x80, 0x21, 0x7b, 0x37, 0x0f, 0x7f, 0x08, 0x6a, + 0x3c, 0xdf, 0x0c, 0xd6, 0xd2, 0xf6, 0x01, 0x66, 0x77, 0x14, + 0x3e, 0xb9, 0x4d, 0x4f, 0xe4, 0xa2, 0x96, 0x72, 0x38, 0x8c, + 0x51, 0x9b, 0x2c, 0x01, 0x66, 0x8a, 0xb7, 0x4f, 0x61, 0x08, + 0x76, 0x55, 0x4e, 0x00, 0x3d, 0x7a, 0xcb, 0xbb }, + { 0x2d, 0x69, 0x51, 0xbc, 0x2b, 0x8b, 0x5c, 0xe5, 0x41, 0x73, + 0xd9, 0x4a, 0xe9, 0xf4, 0x92, 0x56, 0xeb, 0x7a, 0xfe, 0x26, + 0x74, 0xa9, 0x79, 0x3c, 0x0d, 0x5f, 0x6f, 0xb1, 0xd2, 0xd1, + 0x69, 0xbf, 0x93, 0xdf, 0x3f, 0x2a, 0xe1, 0xef, 0x97, 0x12, + 0xaf, 0x0a, 0x92, 0x60, 0x6c, 0x29, 0xfe, 0x48, 0x7a, 0x87, + 0x21, 0x38, 0x23, 0x50, 0x0e, 0xcc, 0x0e, 0x29, 0x71, 0x1f, + 0x71, 0x06, 0x61, 0x5e, 0x41, 0xc5, 0x3c, 0xf6, 0x28, 0xce, + 0x68, 0x5f, 0x68, 0xfc, 0x32, 0x0c, 0x5e, 0xd7, 0xc8, 0x97, + 0xf2, 0xa6, 0x0d, 0x2d, 0x6c, 0xeb, 0x5d, 0x5e, 0xfd, 0x67, + 0x48, 0x0e, 0xce, 0x64, 0x3b, 0x9b, 0x75, 0xa7, 0xa0, 0x55, + 0xdb, 0x50, 0xbf, 0x7d, 0x3e, 0xf9, 0xbe, 0x15, 0xb5, 0x72, + 0x96, 0x5f, 0xea, 0x8d, 0x91, 0xa3, 0xbb, 0x27, 0xca, 0xf2, + 0x37, 0xd6, 0x96, 0x3a, 0x44, 0x97, 0x01, 0xb4 }, + { 0x65, 0xc4, 0x8e, 0x78, 0xe0, 0x8c, 0xc5, 0xf0, 0xa2, 0x4e, + 0xba, 0x02, 0x16, 0x5b, 0x3a, 0xee, 0x46, 0x49, 0x04, 0xc1, + 0xb8, 0x3b, 0x93, 0xf9, 0x75, 0xc4, 0xd0, 0x89, 0xa7, 0xaf, + 0x22, 0x68, 0x0b, 0xad, 0x73, 0x0c, 0xbc, 0xf9, 0x31, 0xa0, + 0x32, 0x20, 0x48, 0xb1, 0x44, 0x7b, 0x5e, 0x6d, 0x92, 0x43, + 0x53, 0xf5, 0x8b, 0x92, 0xa7, 0x42, 0xd4, 0xb6, 0x4d, 0x78, + 0xe7, 0x0e, 0x16, 0x27, 0x83, 0xd9, 0x5d, 0x9c, 0x2b, 0x87, + 0x4f, 0x55, 0x82, 0x0a, 0x8f, 0x66, 0x71, 0x1e, 0x71, 0xa0, + 0xc7, 0x95, 0xcb, 0x7d, 0xc2, 0x74, 0x35, 0x19, 0x6e, 0x7f, + 0xea, 0x3a, 0x0b, 0x0f, 0x42, 0xf1, 0x29, 0x57, 0x34, 0x15, + 0xcf, 0xc7, 0x75, 0x18, 0xd4, 0x99, 0x4e, 0x8b, 0x8f, 0x42, + 0x9e, 0xee, 0x33, 0x3f, 0x24, 0x8f, 0x86, 0xf4, 0xe1, 0x09, + 0xdd, 0x00, 0x7d, 0x9f, 0x90, 0x4e, 0x22, 0x2e }, + { 0x36, 0xb5, 0xcd, 0x2c, 0x7a, 0x6b, 0x22, 0x6f, 0xf6, 0x3d, + 0xd9, 0xff, 0xd4, 0x38, 0xba, 0x2d, 0x40, 0x2d, 0x57, 0x85, + 0xa8, 0xd9, 0xa3, 0xcb, 0xe2, 0x28, 0x0f, 0xa6, 0xef, 0x24, + 0x54, 0x45, 0xe1, 0x06, 0xf4, 0x89, 0x08, 0xb0, 0x55, 0x3a, + 0xd8, 0x28, 0x67, 0xed, 0xb2, 0x89, 0x5d, 0x2e, 0xf0, 0x6f, + 0x0a, 0x46, 0x25, 0xe7, 0xec, 0xe0, 0x38, 0x09, 0xfa, 0x28, + 0x07, 0xd3, 0xe0, 0x13, 0x76, 0xa3, 0xf2, 0xd1, 0x10, 0xf1, + 0x8d, 0x12, 0xdb, 0xf6, 0x7f, 0x0b, 0x4d, 0x31, 0x88, 0xc0, + 0xf5, 0x4d, 0x3e, 0xee, 0x94, 0x73, 0x51, 0x07, 0xfb, 0x1c, + 0x58, 0x1c, 0x31, 0x20, 0x4c, 0xef, 0x28, 0x4a, 0xdf, 0x8f, + 0x59, 0xfc, 0xec, 0x77, 0x03, 0x01, 0xcb, 0x14, 0xb2, 0x14, + 0x3b, 0x06, 0x56, 0x83, 0xd8, 0xcd, 0xfc, 0xea, 0x23, 0xb4, + 0x1a, 0x1c, 0x73, 0xce, 0xde, 0x22, 0x2c, 0x22 }, + { 0x08, 0xd7, 0xc1, 0x44, 0xdb, 0x39, 0xbf, 0xd8, 0x06, 0x92, + 0xf4, 0xc5, 0x39, 0xa5, 0x1d, 0xc8, 0xd2, 0x7c, 0xc9, 0x60, + 0xf7, 0x44, 0x5e, 0x8a, 0x18, 0xf7, 0x3c, 0xaf, 0x52, 0x23, + 0x89, 0xff, 0x45, 0x59, 0x3d, 0xf1, 0x37, 0x6a, 0x9a, 0xb6, + 0x14, 0xe1, 0x82, 0xa7, 0x93, 0xcf, 0x99, 0xc4, 0xff, 0x50, + 0x15, 0x1e, 0xea, 0xa7, 0x4d, 0xf8, 0x8d, 0x0e, 0x85, 0xf9, + 0x36, 0xa5, 0x1a, 0x37, 0xc6, 0xa2, 0x1d, 0x11, 0x2f, 0x41, + 0x22, 0x44, 0x74, 0x83, 0x97, 0x79, 0x0c, 0xc2, 0xe8, 0x10, + 0x74, 0x50, 0x19, 0x83, 0x78, 0x1a, 0x67, 0x8a, 0x0d, 0x47, + 0x5d, 0x79, 0x8d, 0x93, 0x5a, 0x5e, 0xa1, 0x9e, 0xaf, 0x39, + 0xc8, 0x5a, 0xf1, 0xa3, 0x90, 0xa3, 0x57, 0xfa, 0x9b, 0x45, + 0x9c, 0xd8, 0x64, 0xd8, 0x0b, 0x41, 0x45, 0x20, 0xc7, 0x50, + 0x87, 0xff, 0x4e, 0x20, 0x54, 0x56, 0x79, 0xa7 }, + { 0x5f, 0x2a, 0xa8, 0xee, 0xba, 0xb7, 0x02, 0x02, 0x8e, 0x2c, + 0x38, 0x79, 0x04, 0x00, 0x4a, 0xd9, 0x1d, 0x30, 0x50, 0xae, + 0xb5, 0xee, 0x14, 0x7b, 0x4c, 0x38, 0x5e, 0x8b, 0xc7, 0x36, + 0x7d, 0x1f, 0xb5, 0x90, 0x52, 0x64, 0x0f, 0x9b, 0x2b, 0x49, + 0xf3, 0xfe, 0x9c, 0x42, 0xbb, 0x0c, 0xd2, 0xbf, 0x01, 0x97, + 0x24, 0x3e, 0xe3, 0x47, 0x69, 0x4a, 0x3f, 0xe1, 0xe8, 0xb5, + 0x89, 0x83, 0x08, 0xe3, 0x95, 0xe9, 0x5b, 0xb8, 0xa8, 0xde, + 0x7a, 0xa4, 0x7c, 0xc6, 0xe8, 0x38, 0x5f, 0xce, 0x17, 0xbd, + 0xf3, 0xc1, 0xa1, 0x01, 0x61, 0x30, 0xa4, 0xc6, 0x7a, 0x96, + 0x6d, 0x8b, 0xd1, 0x58, 0x7b, 0x7e, 0x77, 0x31, 0x23, 0x74, + 0x2a, 0x67, 0x8c, 0xdf, 0xf0, 0xec, 0xcd, 0x74, 0xdb, 0x6b, + 0xd6, 0x41, 0x87, 0xea, 0x91, 0x92, 0xd4, 0x8c, 0x21, 0x56, + 0x80, 0x9c, 0x0d, 0x96, 0x3e, 0xcc, 0xa7, 0x73 }, + { 0x62, 0x50, 0x1a, 0x98, 0xb4, 0x6f, 0xf9, 0x49, 0xa3, 0x16, + 0x49, 0x80, 0x83, 0xc9, 0xf2, 0x24, 0xe8, 0x84, 0xac, 0x76, + 0x78, 0x4b, 0xe8, 0x2f, 0xd9, 0xff, 0x03, 0x40, 0x02, 0xbc, + 0xd3, 0xc7, 0xc2, 0x82, 0x78, 0xb4, 0x86, 0x6e, 0x5a, 0xe8, + 0x59, 0xdc, 0x52, 0xe6, 0x1e, 0xa6, 0xf0, 0x6e, 0xed, 0xcf, + 0x2d, 0x1a, 0xe2, 0xd9, 0xd3, 0x86, 0x95, 0x9a, 0xfc, 0xba, + 0x8e, 0x2d, 0x85, 0xd1, 0x2b, 0xab, 0xb2, 0x7e, 0x18, 0xbe, + 0x05, 0xf6, 0x7d, 0xab, 0xa1, 0x27, 0x05, 0xeb, 0x67, 0xb8, + 0x26, 0xf6, 0xee, 0x3b, 0x0f, 0xcb, 0x53, 0x4c, 0xef, 0x34, + 0x9c, 0x61, 0xc6, 0x82, 0xe4, 0xd6, 0x0a, 0x69, 0xe8, 0xd3, + 0xe6, 0x42, 0xdd, 0x46, 0xa5, 0xaa, 0x68, 0x5e, 0xda, 0x10, + 0x6e, 0xbf, 0xb7, 0xbf, 0x38, 0x80, 0xd0, 0xa1, 0x9f, 0x66, + 0xe2, 0x08, 0xd4, 0x64, 0x12, 0x66, 0x52, 0x4b }, + { 0x49, 0x7b, 0x15, 0xfe, 0xfd, 0x3f, 0xc6, 0x65, 0xcc, 0x9c, + 0x5f, 0x73, 0xa1, 0xf3, 0x53, 0x1a, 0xab, 0xaa, 0x4c, 0x49, + 0xc0, 0xde, 0xa5, 0x86, 0x78, 0x49, 0x9b, 0x73, 0x91, 0xf9, + 0xda, 0x5e, 0xd1, 0xac, 0xf7, 0xa0, 0xb5, 0xc4, 0xeb, 0x10, + 0xfd, 0x74, 0x10, 0x1c, 0x9a, 0x6f, 0xea, 0x8a, 0x51, 0x9d, + 0x21, 0x33, 0xd5, 0x9b, 0x17, 0x41, 0xbd, 0x9a, 0x8e, 0x31, + 0x4f, 0x0d, 0x1b, 0x70, 0x52, 0xfb, 0xf5, 0x4d, 0xce, 0xcc, + 0xfe, 0x77, 0x62, 0x28, 0x06, 0xe0, 0x2e, 0xa8, 0xab, 0xd3, + 0x81, 0x30, 0xc9, 0xb0, 0xed, 0x55, 0x3e, 0xac, 0xfa, 0x3c, + 0x91, 0x97, 0x20, 0xaa, 0x45, 0x36, 0xa2, 0x88, 0xda, 0xc8, + 0x46, 0xe6, 0x4b, 0x19, 0xe8, 0x25, 0x30, 0x02, 0x8c, 0x8d, + 0x3d, 0x67, 0xca, 0x6a, 0x33, 0xdb, 0xa5, 0xe0, 0xe4, 0xbd, + 0x56, 0x3f, 0x7d, 0x9a, 0xad, 0x26, 0x40, 0x86 }, + { 0x18, 0xd4, 0x6a, 0x6c, 0x9e, 0x51, 0x4c, 0xb7, 0xb7, 0xae, + 0x7e, 0x5c, 0x2f, 0xf6, 0x37, 0xe6, 0xc2, 0xee, 0xbd, 0x13, + 0xed, 0xea, 0x10, 0x71, 0xda, 0xfa, 0x33, 0xfe, 0x06, 0x80, + 0x12, 0xca, 0x40, 0x5d, 0x3e, 0x84, 0xd6, 0x30, 0x8e, 0xdc, + 0xdd, 0x8d, 0xff, 0xbf, 0x86, 0xa9, 0xb7, 0xce, 0x2a, 0x80, + 0xd0, 0xd2, 0x42, 0xc0, 0x07, 0xf4, 0x99, 0xaa, 0x68, 0xac, + 0xba, 0x3e, 0xbd, 0x91, 0x8f, 0x31, 0xf0, 0x44, 0x3e, 0x21, + 0x6d, 0xbf, 0x9c, 0xd0, 0x6d, 0x31, 0xca, 0x90, 0xf0, 0x2e, + 0x81, 0x09, 0xfc, 0x75, 0xa2, 0x9c, 0x53, 0x9f, 0x8c, 0x8c, + 0xdb, 0xa2, 0x02, 0xa0, 0xf5, 0xb4, 0xc8, 0x65, 0x22, 0xf8, + 0x4a, 0xc3, 0x7d, 0xa9, 0xdb, 0xb0, 0x3d, 0xd3, 0x9a, 0xb2, + 0x53, 0x9a, 0xf4, 0x91, 0xa0, 0xfe, 0xc7, 0x19, 0x2a, 0x6f, + 0x8a, 0x56, 0xcb, 0xaa, 0xf4, 0x55, 0x68, 0xe9 }, + { 0x55, 0x04, 0x46, 0x01, 0xd3, 0xf6, 0x2e, 0x40, 0x69, 0xe6, + 0xf8, 0xe4, 0x5a, 0x38, 0xfe, 0xf9, 0x10, 0xd5, 0x4f, 0x8a, + 0x7e, 0x93, 0x05, 0x0d, 0x45, 0xf9, 0x3d, 0x41, 0xa0, 0x6e, + 0x70, 0x8c, 0x3f, 0x0d, 0xb5, 0xcd, 0x7b, 0xb5, 0xe7, 0x51, + 0x37, 0x0d, 0xe9, 0xc8, 0xdc, 0xd7, 0x05, 0xad, 0x14, 0x10, + 0x9d, 0x29, 0x7c, 0x29, 0x54, 0xf3, 0xab, 0x0b, 0x36, 0xf9, + 0xd8, 0x51, 0x76, 0xac, 0x70, 0xeb, 0x06, 0x03, 0x6d, 0xa7, + 0xa5, 0x2b, 0x74, 0x07, 0xa7, 0x88, 0xb1, 0x41, 0x71, 0xb9, + 0x6c, 0xfe, 0x05, 0x71, 0x13, 0xac, 0x73, 0x45, 0x2e, 0x0d, + 0x83, 0x25, 0xa3, 0x25, 0xfd, 0x40, 0xac, 0x0a, 0xbc, 0xda, + 0xb4, 0xce, 0xb4, 0xe4, 0xc4, 0xeb, 0x2f, 0x3e, 0x42, 0xae, + 0x8a, 0xdd, 0x07, 0x45, 0xdd, 0xb2, 0x49, 0x7c, 0xba, 0xf4, + 0x86, 0x8c, 0xbb, 0x22, 0xa7, 0x8b, 0x78, 0x02 }, + { 0x0d, 0xa3, 0x13, 0xfc, 0xd7, 0xb0, 0xec, 0x4f, 0x56, 0x3a, + 0x8f, 0xf7, 0xc6, 0xf5, 0xd7, 0xdb, 0xf3, 0x42, 0x52, 0x09, + 0x3d, 0xd7, 0x9f, 0x93, 0xa1, 0x21, 0x18, 0xac, 0x9a, 0x2b, + 0xd0, 0x1b, 0x27, 0x07, 0x41, 0x76, 0xf5, 0x32, 0x97, 0x3f, + 0x47, 0x7c, 0xa3, 0xdb, 0x9f, 0xf1, 0x00, 0xbc, 0xbc, 0xb5, + 0x31, 0x89, 0x70, 0xc2, 0xae, 0xe3, 0xe2, 0x22, 0x0e, 0x85, + 0x9a, 0xee, 0xfe, 0x98, 0x33, 0x65, 0xc8, 0xe5, 0x29, 0xad, + 0x51, 0x66, 0x90, 0x42, 0x59, 0x6b, 0x91, 0x79, 0x2e, 0x6b, + 0x1c, 0xde, 0x06, 0xe7, 0x40, 0x0d, 0x14, 0x4f, 0x1d, 0x21, + 0xfb, 0xfa, 0x29, 0x51, 0xfc, 0x83, 0x39, 0x72, 0x1f, 0xfe, + 0x29, 0xad, 0x5f, 0x82, 0x7c, 0xd8, 0x66, 0x3e, 0x11, 0x23, + 0x6f, 0xb8, 0x54, 0x20, 0x74, 0xd7, 0x41, 0xd0, 0x00, 0x14, + 0xd1, 0xc5, 0xc9, 0x10, 0x06, 0xcb, 0x9c, 0xc9 }, + { 0x63, 0x63, 0x0b, 0xe8, 0xdb, 0x41, 0x4a, 0xcc, 0x62, 0x02, + 0x30, 0xd8, 0x1e, 0x82, 0x29, 0x0e, 0x44, 0x16, 0x74, 0x10, + 0xa1, 0x16, 0x2d, 0x03, 0x50, 0x94, 0x0c, 0x26, 0x94, 0x1c, + 0x25, 0x54, 0xad, 0xfa, 0xe4, 0xe1, 0x73, 0x10, 0x83, 0xef, + 0x6d, 0x7c, 0x2e, 0xa0, 0xf8, 0x70, 0x46, 0x64, 0xe2, 0x95, + 0x9b, 0xea, 0x09, 0xc2, 0x8f, 0x27, 0x3a, 0xf0, 0xec, 0xbb, + 0xca, 0x3d, 0xe5, 0x0c, 0x47, 0x3d, 0x50, 0xd6, 0x1f, 0x1b, + 0x7f, 0x00, 0x4d, 0x29, 0xa6, 0x16, 0xf0, 0x3d, 0x06, 0x60, + 0xd5, 0x53, 0x1a, 0x0d, 0x04, 0x9a, 0xea, 0xc2, 0x2d, 0x2b, + 0xf4, 0xff, 0xc9, 0xe2, 0xce, 0x18, 0x0d, 0x3e, 0x9a, 0x74, + 0x7c, 0xb0, 0x04, 0x2a, 0x48, 0x71, 0x39, 0x94, 0x67, 0xb8, + 0xa8, 0x23, 0xca, 0x21, 0xd7, 0x0c, 0x00, 0x89, 0x3e, 0x9c, + 0x37, 0x12, 0x5a, 0x8c, 0x15, 0xaa, 0x25, 0x57 }, + { 0x30, 0x6a, 0x98, 0x71, 0xf1, 0x66, 0x88, 0xed, 0x29, 0x58, + 0x45, 0xc0, 0x68, 0x54, 0x4e, 0xb0, 0x68, 0x07, 0x4f, 0x37, + 0xd5, 0xe5, 0xaa, 0x72, 0xeb, 0x0c, 0xd4, 0x78, 0xf8, 0xac, + 0x8f, 0x89, 0xfc, 0xe5, 0x18, 0x6c, 0xe5, 0x58, 0xf6, 0xbe, + 0x36, 0x9b, 0x3e, 0x98, 0xbb, 0x44, 0x3c, 0x07, 0x56, 0xae, + 0xaf, 0xa8, 0x5a, 0x14, 0x36, 0xfa, 0x3d, 0x4f, 0xd9, 0x77, + 0x26, 0x1d, 0x1b, 0x79, 0xca, 0x3d, 0x70, 0x25, 0x58, 0xe2, + 0x60, 0x6d, 0x1f, 0x69, 0xb2, 0x0c, 0x13, 0xce, 0xa0, 0x45, + 0x9d, 0x99, 0x7d, 0x18, 0xb4, 0xb7, 0x0c, 0x4c, 0xbf, 0x3f, + 0x38, 0xf4, 0x49, 0xb9, 0xdc, 0x38, 0x88, 0x3e, 0x04, 0xd6, + 0xde, 0x2c, 0x59, 0xad, 0x1b, 0x4d, 0x33, 0xdd, 0x6c, 0x40, + 0x2d, 0x89, 0x49, 0xe7, 0x58, 0x23, 0xeb, 0x62, 0xf8, 0x79, + 0xbf, 0x8d, 0x52, 0x22, 0x8a, 0x7d, 0x2e, 0x41 }, + { 0x28, 0x33, 0xac, 0x41, 0xe8, 0x10, 0x3e, 0x37, 0x64, 0x43, + 0xeb, 0xe0, 0x58, 0xe5, 0x7c, 0xd4, 0x71, 0xab, 0xa7, 0x31, + 0x93, 0xc9, 0xd5, 0x88, 0x93, 0x06, 0x21, 0x5b, 0x77, 0xf4, + 0xc0, 0x1c, 0x55, 0x1e, 0x7a, 0x17, 0x6e, 0x72, 0xa1, 0x3d, + 0xf9, 0xfa, 0x62, 0x8d, 0x1b, 0xea, 0xa5, 0x11, 0xf6, 0xd4, + 0x18, 0xf8, 0x82, 0x07, 0x5f, 0x91, 0xc0, 0x75, 0xc7, 0x01, + 0xf5, 0x32, 0x70, 0x1b, 0x28, 0xe6, 0xf6, 0x31, 0x82, 0xa9, + 0xd2, 0x2b, 0x4a, 0xf2, 0x2b, 0xc0, 0x0a, 0xc9, 0xc2, 0xde, + 0x60, 0xe5, 0x64, 0xd8, 0xc7, 0xaf, 0xb8, 0x99, 0x35, 0x28, + 0x32, 0x38, 0x9a, 0x2d, 0x60, 0x23, 0x87, 0xb6, 0xef, 0x20, + 0xc5, 0xbf, 0xee, 0x67, 0xa9, 0xbe, 0x01, 0x52, 0xc0, 0xdb, + 0x41, 0x20, 0x1e, 0xdf, 0x27, 0xca, 0x0e, 0x6f, 0x65, 0x8f, + 0xbc, 0x45, 0x1e, 0x9d, 0x63, 0x4e, 0xc1, 0x36 }, + { 0x12, 0x0c, 0xd4, 0x54, 0xa4, 0x9d, 0x63, 0x03, 0x67, 0x30, + 0x20, 0xed, 0x0b, 0xcf, 0x35, 0x38, 0xbd, 0x59, 0xc7, 0x57, + 0xde, 0x5c, 0x01, 0x91, 0x65, 0x5b, 0xa9, 0xe4, 0x08, 0x77, + 0x87, 0xd9, 0xe1, 0xdc, 0xbc, 0xd6, 0x99, 0x76, 0x32, 0x7e, + 0xf4, 0x2f, 0xaa, 0x97, 0x20, 0x6b, 0x5f, 0xaa, 0xc0, 0x9c, + 0x1c, 0x5a, 0x47, 0x22, 0xb4, 0xd7, 0xec, 0xb6, 0x8b, 0xd1, + 0x04, 0xba, 0xa4, 0x31, 0x1b, 0x87, 0xa5, 0x8e, 0x13, 0x93, + 0xc6, 0xe6, 0xd5, 0xf3, 0x23, 0xf8, 0x27, 0x32, 0x04, 0x49, + 0x7d, 0x5a, 0x27, 0x00, 0xdc, 0xfa, 0x19, 0x41, 0xb4, 0x38, + 0xe4, 0xcf, 0xfd, 0xc6, 0x03, 0x39, 0x35, 0x12, 0xaf, 0xe7, + 0x9d, 0x34, 0x3d, 0xc2, 0x9d, 0x7c, 0x1f, 0x0b, 0x8c, 0x57, + 0xa7, 0x28, 0xac, 0x3d, 0x9d, 0xa8, 0x1c, 0x08, 0xdb, 0x24, + 0x7e, 0x56, 0x4b, 0x86, 0x8d, 0xa5, 0xec, 0x5c }, + { 0x02, 0x1c, 0xfd, 0x16, 0x7f, 0xde, 0xea, 0x3e, 0x8e, 0xf1, + 0x67, 0x7e, 0x70, 0x19, 0x33, 0x6e, 0xd5, 0x69, 0x84, 0x96, + 0xeb, 0x40, 0x54, 0xbc, 0x15, 0x1f, 0x69, 0x3a, 0x9b, 0xe0, + 0x24, 0x30, 0xa6, 0x7a, 0xd9, 0xf6, 0x8f, 0x01, 0x03, 0xcb, + 0x75, 0x8d, 0xaf, 0x64, 0x5e, 0xb3, 0x3e, 0x34, 0x66, 0xda, + 0xe2, 0xc2, 0xd4, 0x67, 0xfa, 0x92, 0xde, 0x1f, 0xaa, 0x12, + 0x0b, 0xc9, 0xae, 0xc1, 0x2e, 0xf0, 0x5b, 0x4b, 0x0e, 0x93, + 0xdf, 0xf2, 0xbd, 0x16, 0xf5, 0x58, 0x29, 0xdb, 0xdd, 0xcd, + 0xef, 0x2f, 0xf3, 0x80, 0x21, 0xa4, 0xf0, 0xd3, 0x3d, 0xe4, + 0x87, 0xf0, 0x47, 0x21, 0xab, 0x5c, 0x64, 0x2e, 0xd3, 0xa6, + 0x9b, 0x95, 0x77, 0x74, 0x9b, 0x6a, 0x68, 0x41, 0x5a, 0x8d, + 0x06, 0x65, 0xbc, 0x00, 0x3e, 0xf0, 0x2c, 0xce, 0x58, 0xee, + 0xeb, 0xfd, 0xb8, 0xf4, 0xca, 0xb0, 0xf9, 0xee }, + { 0x07, 0x26, 0x5b, 0x46, 0xc7, 0x3c, 0xf7, 0x8e, 0x71, 0xed, + 0xcd, 0x9c, 0xa2, 0x05, 0x95, 0xa3, 0x5d, 0xed, 0xc2, 0x31, + 0xeb, 0x12, 0x8b, 0xb6, 0x80, 0x7c, 0x22, 0xdf, 0xbf, 0x8e, + 0xd5, 0x9c, 0xc8, 0x8f, 0xa8, 0x17, 0xfd, 0x0a, 0xe2, 0x8a, + 0xdc, 0x0c, 0x7e, 0x57, 0x99, 0x74, 0x30, 0x2c, 0xaf, 0x86, + 0xe3, 0x91, 0xed, 0x2a, 0xb5, 0x1a, 0xb9, 0x7a, 0xd5, 0xf9, + 0x22, 0x4a, 0x47, 0x0f, 0xfa, 0xeb, 0x52, 0xef, 0x15, 0x60, + 0x08, 0xb5, 0x52, 0x67, 0x07, 0x3f, 0x66, 0x34, 0x3d, 0x5a, + 0x0d, 0x8f, 0x71, 0x7e, 0x3d, 0x3b, 0xb1, 0x8b, 0xfd, 0xb1, + 0x67, 0x76, 0x30, 0x4a, 0xe4, 0xca, 0x1e, 0x5e, 0xc7, 0xb7, + 0x0f, 0x39, 0x93, 0xc8, 0x55, 0x36, 0x8d, 0x10, 0xf2, 0xcf, + 0x77, 0x13, 0x70, 0x3b, 0xde, 0x37, 0xd6, 0x4a, 0xd2, 0x54, + 0x5c, 0x73, 0x71, 0x5f, 0xdf, 0x5c, 0x36, 0xf3 }, + { 0x36, 0xc5, 0x75, 0x4b, 0x31, 0xd1, 0x49, 0x6c, 0x6e, 0x9d, + 0x66, 0x7d, 0x0c, 0xc2, 0xf4, 0xbd, 0x8f, 0x47, 0x57, 0x5d, + 0x06, 0x44, 0x08, 0x0e, 0xdd, 0x88, 0xde, 0xee, 0x7a, 0x0a, + 0xc6, 0xe9, 0x6d, 0xcc, 0xa4, 0x9b, 0x49, 0xc1, 0x2a, 0xa2, + 0xcd, 0x9c, 0x0c, 0x08, 0xad, 0xaf, 0x79, 0x6f, 0x33, 0x3f, + 0x27, 0xd0, 0xf8, 0xa4, 0x3a, 0x97, 0x03, 0x89, 0xf3, 0x41, + 0x3b, 0xd3, 0x43, 0x02, 0xf8, 0xad, 0xf7, 0x2f, 0x06, 0x95, + 0x7b, 0x1f, 0xea, 0x39, 0x9c, 0xaa, 0x25, 0x57, 0x75, 0x3b, + 0x55, 0xea, 0x0e, 0x3a, 0x69, 0x73, 0xb9, 0x5a, 0x0e, 0x0e, + 0x1b, 0x1a, 0x52, 0x3c, 0x42, 0x8d, 0x23, 0x9e, 0xa8, 0xaa, + 0x7a, 0x94, 0x3f, 0x3b, 0xaf, 0x82, 0x6d, 0xfa, 0x5b, 0x86, + 0x0f, 0xc4, 0xc5, 0x9a, 0xaf, 0x89, 0xc4, 0x02, 0x77, 0x16, + 0x73, 0xdd, 0x99, 0xf0, 0xbd, 0x66, 0x23, 0x2f }, + { 0x06, 0xfb, 0xf8, 0x61, 0x19, 0x46, 0x94, 0x4e, 0xfc, 0x8a, + 0x8a, 0xc9, 0xa2, 0x97, 0x5e, 0xb5, 0xa2, 0xdd, 0xad, 0xe5, + 0xc1, 0x64, 0xd9, 0x4f, 0x40, 0xc0, 0x15, 0x32, 0xc9, 0x58, + 0x22, 0xde, 0xc0, 0x78, 0x44, 0x94, 0xc4, 0x8a, 0xf5, 0xae, + 0x3d, 0x67, 0x42, 0xe9, 0x6b, 0x0b, 0x17, 0x05, 0xa9, 0x4c, + 0x3a, 0x40, 0x50, 0x51, 0x3d, 0xed, 0x6c, 0x49, 0x07, 0x5b, + 0x37, 0xef, 0x67, 0x77, 0x1c, 0x09, 0xdf, 0xf3, 0xc4, 0x18, + 0x00, 0xc5, 0x52, 0x97, 0xda, 0x6b, 0x4b, 0x23, 0xe4, 0xba, + 0x1c, 0x18, 0xd0, 0xf7, 0xcd, 0x6d, 0xef, 0x49, 0xc9, 0x05, + 0x46, 0x6a, 0x74, 0x0f, 0x8c, 0x79, 0x63, 0x39, 0x84, 0x4a, + 0x80, 0x79, 0x97, 0x4e, 0x4b, 0x0e, 0xaf, 0x4e, 0x92, 0x1b, + 0x80, 0x55, 0xa6, 0x99, 0x11, 0x22, 0x7e, 0x78, 0x9c, 0x4f, + 0x91, 0x20, 0x04, 0x6e, 0xf3, 0x23, 0xd8, 0x4b }, + { 0x5e, 0x9c, 0xa0, 0xfd, 0x1f, 0x0f, 0xa9, 0xea, 0x5e, 0x64, + 0x29, 0x53, 0x04, 0xbb, 0x5a, 0xb1, 0x2a, 0x7d, 0x84, 0x11, + 0xa0, 0x3e, 0x8f, 0x0e, 0xd9, 0xd1, 0x96, 0x53, 0xd9, 0x5e, + 0xef, 0xa1, 0x83, 0x3d, 0x46, 0xa1, 0x36, 0x19, 0xcf, 0x4d, + 0x96, 0xd2, 0xe9, 0x57, 0x9d, 0xa0, 0x79, 0x33, 0x7c, 0x88, + 0xb1, 0x0b, 0x23, 0xd3, 0x43, 0x4e, 0xc9, 0x21, 0xe6, 0x9d, + 0x95, 0x71, 0xae, 0x28, 0x42, 0x2c, 0x32, 0x6d, 0xf0, 0x66, + 0x12, 0xa5, 0xe4, 0x0a, 0xbc, 0x9d, 0x5c, 0xbf, 0x6b, 0xf3, + 0x4c, 0x5f, 0x2a, 0x2a, 0xfb, 0x65, 0xbd, 0x03, 0x98, 0x2b, + 0x61, 0xf5, 0xb3, 0x0a, 0x1a, 0x23, 0x7b, 0xeb, 0x07, 0x1a, + 0xe4, 0xd7, 0x41, 0x7c, 0x05, 0xfe, 0xf5, 0x9b, 0x0f, 0xde, + 0xf8, 0xb9, 0xd8, 0x3b, 0x58, 0xc8, 0x1d, 0x04, 0x0f, 0xeb, + 0x2d, 0x65, 0x33, 0x8e, 0x3f, 0x45, 0xaa, 0x97 }, + { 0x94, 0x06, 0x22, 0xb3, 0xc6, 0x83, 0x6a, 0xf8, 0x8c, 0xc2, + 0x04, 0x5b, 0x49, 0x95, 0x5f, 0x34, 0x69, 0xb1, 0xf1, 0xc7, + 0x36, 0x24, 0x24, 0xa6, 0x75, 0xb3, 0x18, 0xdc, 0x76, 0x93, + 0x69, 0x14, 0xd3, 0x39, 0x17, 0x17, 0x06, 0x4d, 0xdc, 0x77, + 0xea, 0xcc, 0x55, 0x13, 0x65, 0x64, 0x78, 0xe3, 0x7b, 0xc9, + 0x3a, 0x45, 0x03, 0xe3, 0xe0, 0x13, 0x7f, 0x16, 0x5f, 0xd3, + 0xa8, 0xf9, 0xac, 0x8a, 0x6a, 0xdc, 0x4b, 0x9e, 0x1e, 0x84, + 0x72, 0x8b, 0x26, 0xe3, 0x6f, 0xbe, 0x61, 0xf6, 0x4b, 0x56, + 0xfc, 0x79, 0x56, 0x2c, 0xd4, 0x03, 0x4a, 0x9a, 0xc1, 0xfc, + 0x9c, 0x7b, 0xc7, 0x58, 0xc6, 0xa3, 0xe9, 0x52, 0xdc, 0x2c, + 0x0d, 0x17, 0x46, 0x7c, 0x65, 0xfb, 0x9e, 0xfc, 0xff, 0xdb, + 0x0e, 0xb2, 0xe2, 0xda, 0x40, 0xbf, 0xe7, 0x8a, 0x95, 0xa2, + 0x5b, 0xd5, 0x45, 0x71, 0x19, 0x7c, 0x5d, 0xc4 }, + { 0x80, 0xbb, 0x16, 0x64, 0x78, 0x5b, 0xed, 0xb6, 0xb9, 0xf4, + 0x98, 0x24, 0xbd, 0xe6, 0xbd, 0x71, 0xe2, 0xb4, 0x9c, 0x8c, + 0xcf, 0xde, 0x33, 0x68, 0xd8, 0xa9, 0x98, 0xa4, 0xf1, 0x90, + 0xa2, 0xc8, 0x2e, 0x0f, 0x86, 0x08, 0x3c, 0x23, 0xba, 0x9c, + 0x1e, 0xf1, 0xea, 0x8a, 0x49, 0x7a, 0x40, 0xda, 0xaf, 0x3f, + 0x5d, 0xe2, 0xce, 0xd2, 0xbf, 0x77, 0x69, 0xaa, 0x40, 0x75, + 0xae, 0x9c, 0x44, 0xb2, 0x0f, 0x82, 0xb3, 0xa6, 0xad, 0x98, + 0x02, 0xb6, 0x47, 0xe9, 0x7d, 0xa8, 0xf0, 0x16, 0x52, 0xa4, + 0xde, 0x6d, 0x87, 0x54, 0x6f, 0xc8, 0x3b, 0x11, 0x05, 0x41, + 0xaf, 0x9d, 0x3d, 0x26, 0x22, 0x46, 0xc6, 0x32, 0x1e, 0x0a, + 0x67, 0x3e, 0x14, 0xa5, 0x8c, 0xf0, 0xc4, 0xd5, 0x5b, 0x97, + 0xab, 0xd5, 0x3b, 0x29, 0x62, 0x5d, 0xd3, 0xf8, 0xf1, 0x15, + 0x47, 0x10, 0xcc, 0xb7, 0x0d, 0x99, 0x79, 0x73 }, + { 0x07, 0x7b, 0xa5, 0xea, 0x41, 0x21, 0x23, 0x50, 0xed, 0xfc, + 0x15, 0x48, 0x63, 0xb8, 0x5a, 0x35, 0x95, 0x10, 0x79, 0x18, + 0x11, 0x0c, 0x77, 0x9c, 0x96, 0x95, 0x98, 0xdd, 0xcc, 0x58, + 0x00, 0x0b, 0x64, 0x97, 0x59, 0x63, 0xcb, 0x11, 0x8f, 0xf9, + 0x79, 0xea, 0x49, 0xc2, 0x54, 0xe2, 0x9c, 0xdc, 0xcd, 0x65, + 0xd2, 0x37, 0x1f, 0x20, 0xb3, 0x22, 0x7d, 0x5a, 0x6f, 0xf6, + 0x54, 0xeb, 0x49, 0xff, 0x0b, 0x66, 0xd7, 0x89, 0x76, 0xf8, + 0x2d, 0xbd, 0xb6, 0xba, 0x85, 0x00, 0x8b, 0xb4, 0xcb, 0x93, + 0xc3, 0xbf, 0xd6, 0xa8, 0x3e, 0x70, 0x86, 0xfa, 0x2f, 0xb9, + 0xe0, 0xc3, 0xa2, 0xa7, 0xba, 0x07, 0x9f, 0x15, 0x53, 0xde, + 0x13, 0x3b, 0x23, 0x38, 0x46, 0x1e, 0x70, 0xcf, 0x87, 0x93, + 0xb2, 0x73, 0x15, 0x5e, 0xe5, 0x61, 0xac, 0x5e, 0x68, 0x83, + 0x05, 0xe5, 0x75, 0xfe, 0xfd, 0x14, 0x5c, 0xb5 }, + { 0x6b, 0x20, 0x06, 0xdf, 0x45, 0x91, 0xa2, 0xe2, 0xba, 0xf7, + 0x58, 0x1d, 0x9b, 0xc7, 0x7d, 0x21, 0x5b, 0x3c, 0x81, 0xb2, + 0xf4, 0x73, 0x96, 0x53, 0x09, 0x01, 0x26, 0x5c, 0xaf, 0xf0, + 0x75, 0x86, 0x81, 0x38, 0x99, 0x5a, 0x52, 0x35, 0x0e, 0x80, + 0xc9, 0x31, 0x79, 0xbd, 0xd3, 0xf5, 0x5c, 0x07, 0xab, 0xe5, + 0x23, 0x6e, 0x62, 0x99, 0xae, 0x7f, 0x2b, 0xe7, 0x02, 0x0d, + 0x45, 0xad, 0x59, 0x20, 0x9d, 0x28, 0x6e, 0xa7, 0x2c, 0xda, + 0xde, 0x77, 0xd5, 0x69, 0xaf, 0x36, 0x9a, 0xbf, 0x49, 0xee, + 0xd4, 0x6e, 0xc7, 0xe5, 0xf4, 0x64, 0xe8, 0xb3, 0xbb, 0x1d, + 0x31, 0xd1, 0x0e, 0x80, 0xc7, 0x60, 0x01, 0xdc, 0x1f, 0x98, + 0x8a, 0x32, 0xf1, 0x0f, 0x19, 0x12, 0xed, 0xc5, 0x80, 0x6d, + 0x02, 0x72, 0x43, 0x12, 0x14, 0x45, 0x05, 0x02, 0xa0, 0xab, + 0x0b, 0x3a, 0x38, 0xd3, 0xcd, 0xd8, 0x6f, 0x61 }, + { 0x53, 0x21, 0x7e, 0xa6, 0xbd, 0x26, 0xb5, 0x50, 0x85, 0x5b, + 0x91, 0x1c, 0x66, 0x86, 0x8a, 0xfc, 0x84, 0x95, 0x40, 0xc0, + 0x32, 0xc3, 0x8e, 0x83, 0x24, 0xd1, 0x16, 0xe6, 0x38, 0xd6, + 0xb0, 0xa0, 0x26, 0x2a, 0x6f, 0xb8, 0xc9, 0x17, 0xb1, 0x6c, + 0xd6, 0xc1, 0x2e, 0x10, 0x62, 0x57, 0x41, 0xa4, 0x5c, 0x8d, + 0x7a, 0x75, 0x27, 0x55, 0xf8, 0x94, 0xb4, 0x76, 0xf4, 0x1e, + 0x9d, 0xc1, 0x2c, 0xe9, 0x10, 0xd0, 0xcb, 0x97, 0x6f, 0xa8, + 0xb7, 0x75, 0x70, 0xa9, 0xf4, 0x0c, 0x15, 0x31, 0xc0, 0x5a, + 0x54, 0xf1, 0xa7, 0x01, 0x35, 0x7f, 0x67, 0x9e, 0x4f, 0x8a, + 0x61, 0x84, 0xd2, 0x12, 0x5c, 0xaf, 0x84, 0x72, 0x8f, 0x25, + 0x53, 0xd5, 0x12, 0x5e, 0xd5, 0x71, 0x8d, 0x33, 0x00, 0x0e, + 0x7f, 0x99, 0x93, 0x1f, 0x53, 0x6a, 0x96, 0x2b, 0xb4, 0xfd, + 0xb2, 0xfe, 0x50, 0xa8, 0x96, 0x5b, 0x1b, 0xc1 }, + { 0x03, 0x86, 0x93, 0x1e, 0xd9, 0xad, 0xbe, 0xef, 0x64, 0xbd, + 0x60, 0x01, 0x61, 0x83, 0x0a, 0xc2, 0xa0, 0x8d, 0x33, 0x79, + 0xf9, 0x78, 0x1b, 0x12, 0x99, 0x89, 0x3d, 0xd0, 0xf2, 0xbd, + 0x29, 0x5b, 0xf8, 0xe2, 0xd1, 0x73, 0x60, 0x44, 0xa9, 0xa6, + 0xa9, 0xe0, 0x8d, 0xcb, 0x4a, 0x6d, 0x65, 0xa1, 0xc8, 0x1e, + 0x01, 0xc9, 0xe9, 0xa0, 0x6f, 0x07, 0xa7, 0x27, 0xda, 0xcc, + 0x35, 0xcc, 0x05, 0x2f, 0x0f, 0x93, 0x8d, 0x1e, 0x42, 0xce, + 0x9e, 0xa8, 0xc4, 0xfa, 0xe9, 0xe8, 0xc3, 0xd4, 0xb1, 0xe1, + 0xa0, 0x7a, 0x96, 0xb3, 0x41, 0xc8, 0x15, 0xef, 0x6d, 0xc3, + 0xb8, 0x48, 0x38, 0x1a, 0x4f, 0xf7, 0xab, 0x7d, 0xaa, 0x2d, + 0xe4, 0xa5, 0x43, 0x44, 0x96, 0x4e, 0xb8, 0x5e, 0xca, 0xcb, + 0xd2, 0x6e, 0x96, 0x8d, 0xa9, 0xcb, 0xe6, 0x21, 0x14, 0x6c, + 0xfc, 0x84, 0x04, 0x73, 0x25, 0x9f, 0x52, 0xb4 }, + { 0x2c, 0xaa, 0xf7, 0x49, 0x15, 0x04, 0x1c, 0x20, 0x0e, 0x49, + 0x67, 0xcd, 0xb4, 0xa8, 0x74, 0x8b, 0xcd, 0x3a, 0x21, 0xd6, + 0xd5, 0x8c, 0x6d, 0xb8, 0x1b, 0xa0, 0x97, 0xfc, 0xb7, 0x66, + 0x86, 0x3d, 0x81, 0xce, 0x36, 0xef, 0x8b, 0xbd, 0xcc, 0xb2, + 0x45, 0x9e, 0x93, 0x67, 0xbf, 0x32, 0x0e, 0x0e, 0x82, 0x59, + 0x68, 0x87, 0xe5, 0xef, 0x50, 0x2f, 0x67, 0x7e, 0xdc, 0x88, + 0x29, 0x72, 0x72, 0x1a, 0x75, 0xba, 0xcd, 0x75, 0x0f, 0x9c, + 0x6c, 0x40, 0x41, 0x86, 0x79, 0xfd, 0x49, 0xff, 0xf5, 0xc4, + 0x55, 0xcb, 0xe7, 0x09, 0x03, 0x31, 0x6a, 0xd2, 0x35, 0x4f, + 0xf4, 0x47, 0x11, 0x15, 0x94, 0xcd, 0x61, 0xca, 0x2e, 0x78, + 0x69, 0x9c, 0xe4, 0xd6, 0x3b, 0xc2, 0x38, 0xcf, 0x53, 0x6e, + 0xba, 0xed, 0xed, 0x9d, 0x2b, 0x67, 0xe3, 0x55, 0xbb, 0x07, + 0xd0, 0xd7, 0xab, 0xb3, 0xd0, 0x98, 0x85, 0xa5 }, + { 0x86, 0xd7, 0xf5, 0x32, 0x45, 0xfe, 0x3b, 0xd8, 0x65, 0xa1, + 0xbb, 0xe2, 0x93, 0x50, 0x36, 0x1e, 0xc7, 0xc7, 0x1f, 0x3d, + 0x09, 0xd8, 0xff, 0x91, 0x36, 0xe8, 0x86, 0xe2, 0x70, 0xb0, + 0x55, 0x18, 0xb5, 0x6e, 0x45, 0xf1, 0xad, 0x50, 0xd9, 0xd9, + 0x6b, 0xb5, 0xd5, 0x11, 0xc1, 0x8a, 0x2b, 0xe7, 0x65, 0x6a, + 0x47, 0xca, 0x57, 0xd1, 0xa1, 0x70, 0x11, 0x72, 0x5d, 0x69, + 0xab, 0xac, 0x96, 0xf9, 0x30, 0x2c, 0x8f, 0x78, 0xf5, 0x67, + 0x23, 0xde, 0xb9, 0x09, 0xd2, 0x32, 0xd9, 0x25, 0xdc, 0xf2, + 0x9c, 0xe8, 0xe6, 0x81, 0x2d, 0xf3, 0x1f, 0xa4, 0x6c, 0xa8, + 0xb3, 0x20, 0x35, 0x6d, 0x39, 0x82, 0x48, 0xd0, 0xab, 0x75, + 0x7a, 0xe5, 0xb7, 0x0b, 0x26, 0x8e, 0xd1, 0xa5, 0x78, 0x1a, + 0x8c, 0x86, 0xb3, 0xe4, 0xea, 0x23, 0x22, 0x47, 0x15, 0x45, + 0x44, 0xf9, 0x80, 0x06, 0x6e, 0xd2, 0x04, 0x24 }, + { 0x68, 0x2a, 0x55, 0xe3, 0x86, 0xc0, 0xb4, 0xdd, 0x5a, 0x4c, + 0x3c, 0x6f, 0xcb, 0xc1, 0xff, 0x85, 0x52, 0xc9, 0x4d, 0x0f, + 0x7d, 0x83, 0x6c, 0x5a, 0x5f, 0xfe, 0x5f, 0x94, 0x3d, 0xb6, + 0x08, 0x3c, 0x68, 0xee, 0xea, 0x62, 0xea, 0xe7, 0x5b, 0x16, + 0x68, 0xa6, 0x76, 0xdb, 0x88, 0x37, 0xd5, 0x1d, 0x00, 0x7f, + 0x3b, 0xaf, 0x24, 0x19, 0x8f, 0xd2, 0x4f, 0x5b, 0x45, 0x39, + 0x6e, 0x2b, 0xd8, 0x11, 0x0f, 0xb2, 0x39, 0xa8, 0x57, 0x9b, + 0xcc, 0x13, 0x36, 0x9f, 0x3b, 0xd9, 0x83, 0x55, 0xb0, 0x58, + 0x58, 0x30, 0x06, 0x44, 0xfb, 0xea, 0x45, 0xb8, 0x4d, 0xa3, + 0xb9, 0xdb, 0x88, 0x7e, 0xc6, 0x66, 0xd3, 0xe3, 0xac, 0x54, + 0x90, 0x89, 0x8d, 0x1c, 0xfa, 0xe5, 0x0e, 0x52, 0x26, 0xcd, + 0x01, 0xb4, 0xb6, 0x97, 0x50, 0x98, 0x8b, 0xc3, 0xd9, 0x13, + 0x99, 0xf1, 0x6e, 0xb6, 0xb0, 0xbf, 0x71, 0x9a }, + { 0x02, 0x22, 0x7f, 0xa6, 0xfe, 0xfe, 0x4d, 0xcd, 0x05, 0x4f, + 0x25, 0x42, 0xe4, 0x0d, 0x39, 0x05, 0xd2, 0xcd, 0xf0, 0x1b, + 0x76, 0x88, 0xd7, 0x0c, 0xdc, 0xec, 0xc3, 0xab, 0x7b, 0x4c, + 0x7c, 0x91, 0xad, 0x73, 0x70, 0x52, 0xc6, 0xfd, 0xd7, 0xa6, + 0x41, 0x5d, 0x46, 0xa0, 0x85, 0x2f, 0x76, 0x11, 0x2c, 0xc3, + 0x0a, 0x31, 0xff, 0x4b, 0x04, 0x5c, 0x9b, 0xc7, 0xfd, 0x4f, + 0x14, 0x52, 0xd0, 0xac, 0x6c, 0x44, 0x76, 0x84, 0x49, 0xcd, + 0xc2, 0x1a, 0x15, 0x43, 0xf2, 0x7e, 0x23, 0x24, 0xa6, 0x8b, + 0xc8, 0x99, 0x27, 0xe6, 0x8a, 0x87, 0x72, 0x27, 0x1b, 0x13, + 0x34, 0x2f, 0x14, 0x29, 0x66, 0x29, 0x89, 0x0d, 0x39, 0x65, + 0xec, 0xc3, 0xe5, 0xe7, 0xd6, 0xae, 0x0c, 0xc5, 0xb7, 0x5a, + 0x46, 0xe3, 0x22, 0x76, 0x02, 0x6c, 0x34, 0xc7, 0x24, 0x5d, + 0xc8, 0xf2, 0x35, 0xa4, 0x58, 0x74, 0x95, 0xaa }, + { 0x54, 0x7e, 0x24, 0x9a, 0x29, 0x26, 0x97, 0x78, 0x44, 0x6e, + 0x6a, 0x62, 0x15, 0xeb, 0xc7, 0xd0, 0x34, 0x27, 0xe5, 0x4d, + 0x7d, 0xd3, 0x75, 0x78, 0x64, 0xfc, 0x55, 0xfc, 0x28, 0xff, + 0xba, 0x81, 0x97, 0x1e, 0xb9, 0x15, 0xd5, 0xc4, 0xe8, 0x43, + 0x5f, 0x37, 0x16, 0xdf, 0xe3, 0x42, 0x0e, 0xea, 0xf5, 0xa5, + 0xc2, 0x2e, 0xbb, 0xc9, 0xf1, 0xa5, 0x64, 0xd1, 0x6e, 0x9f, + 0x88, 0x11, 0x67, 0xf4, 0xb0, 0x21, 0xe1, 0x4e, 0x07, 0x10, + 0xae, 0x9a, 0xbc, 0x1f, 0x27, 0x9d, 0x68, 0xfa, 0x4f, 0xce, + 0x21, 0xc9, 0x55, 0xf9, 0x8e, 0x08, 0xcb, 0x04, 0x09, 0x59, + 0xd0, 0x44, 0xb4, 0xcb, 0xec, 0xa0, 0x9d, 0x10, 0x90, 0xbf, + 0x96, 0xf7, 0xc5, 0xe5, 0xcb, 0x12, 0x8e, 0x09, 0x4f, 0x2c, + 0x8b, 0x22, 0x8e, 0xfe, 0xed, 0x46, 0xfd, 0xfd, 0x22, 0x5d, + 0x18, 0x05, 0xef, 0xd9, 0xb7, 0x51, 0x94, 0x8b }, + { 0x45, 0xa4, 0x1c, 0xc0, 0xd2, 0xb0, 0x8e, 0xea, 0xc4, 0x2d, + 0xc7, 0x45, 0xbf, 0xe6, 0xc1, 0xeb, 0x1c, 0x68, 0x5c, 0xea, + 0x3c, 0x61, 0x32, 0xe6, 0xfc, 0xeb, 0x5c, 0x90, 0x8b, 0xcb, + 0x25, 0x05, 0x34, 0x79, 0xbe, 0xa1, 0xc2, 0x20, 0x21, 0x8b, + 0x74, 0x75, 0xe0, 0xe8, 0x31, 0x91, 0xd4, 0xe3, 0xd2, 0x45, + 0x65, 0x69, 0x79, 0x32, 0xa1, 0xf0, 0xe5, 0x7e, 0x4d, 0x29, + 0x61, 0x6f, 0xde, 0xda, 0x7f, 0xfd, 0xdf, 0x84, 0x03, 0xdc, + 0xf1, 0xce, 0xa0, 0xc5, 0xbb, 0x1d, 0xdd, 0xee, 0xc0, 0x25, + 0x18, 0xc9, 0x9d, 0x83, 0xaa, 0x2f, 0x7d, 0x51, 0x3d, 0x2c, + 0x09, 0xba, 0xf9, 0x34, 0x28, 0x23, 0x5b, 0x41, 0x27, 0xea, + 0x9d, 0xe5, 0xe7, 0x0a, 0xf6, 0x51, 0x51, 0xe1, 0x0a, 0x63, + 0xf3, 0xd8, 0xb4, 0xe6, 0xcd, 0xcc, 0x79, 0x55, 0xcf, 0x50, + 0x47, 0x06, 0x86, 0x8a, 0xa1, 0xff, 0xda, 0x27 }, + { 0x12, 0x87, 0x63, 0xc9, 0x42, 0xee, 0x40, 0xc8, 0xba, 0x85, + 0x0a, 0xc9, 0xd0, 0x87, 0xda, 0x02, 0xa8, 0x4c, 0x06, 0xb6, + 0xb6, 0xac, 0x2a, 0xf6, 0x36, 0x2d, 0x7a, 0x77, 0xd8, 0x8e, + 0x69, 0x44, 0x2d, 0x32, 0x59, 0xd4, 0x8a, 0x0f, 0x29, 0x8c, + 0x0f, 0x0b, 0xd9, 0xbd, 0x28, 0xff, 0xf6, 0xdd, 0x14, 0x56, + 0x01, 0xed, 0x3d, 0x58, 0x9b, 0xea, 0xc8, 0x7b, 0xe1, 0xe4, + 0x49, 0xdf, 0x78, 0x1e, 0x96, 0x32, 0x3d, 0x25, 0x24, 0x21, + 0xe3, 0x75, 0xb2, 0xaf, 0xbd, 0xdc, 0x0d, 0xf3, 0x18, 0x4e, + 0x93, 0xdf, 0x7d, 0xa4, 0x98, 0x4f, 0xd1, 0x1f, 0x2c, 0x9e, + 0x4f, 0x52, 0xa2, 0x85, 0x74, 0x1a, 0x4f, 0x54, 0x12, 0xd2, + 0xa9, 0xbe, 0xb1, 0x7e, 0xdc, 0x1e, 0xa7, 0x58, 0x5e, 0xeb, + 0x4c, 0x66, 0x41, 0xff, 0x96, 0x2f, 0xa1, 0x7c, 0xf7, 0x0e, + 0x3e, 0xa9, 0xb2, 0xc7, 0x4d, 0xbb, 0xf0, 0xe1 }, + { 0x75, 0xe9, 0x6b, 0xcc, 0xfc, 0x4f, 0x74, 0xd2, 0x1e, 0x82, + 0x04, 0xb7, 0x68, 0xbb, 0x63, 0x7f, 0x6a, 0x7e, 0x00, 0x67, + 0xb4, 0x12, 0x6d, 0x72, 0x5e, 0x8c, 0xa1, 0xf9, 0xb2, 0x0f, + 0xcd, 0x74, 0x7e, 0x8d, 0xa5, 0x13, 0x99, 0xb3, 0xa0, 0xeb, + 0x21, 0x60, 0xcb, 0x18, 0xb1, 0x3e, 0xb7, 0x1b, 0x07, 0x36, + 0x55, 0x61, 0xb1, 0xc9, 0x95, 0xf3, 0xb4, 0x76, 0x56, 0x5e, + 0x03, 0x21, 0x81, 0x23, 0x3f, 0x1d, 0x8d, 0x88, 0xc1, 0xde, + 0x7e, 0xbc, 0xfe, 0x9f, 0xda, 0x66, 0x8b, 0x88, 0x17, 0x52, + 0x5b, 0x29, 0xd2, 0x13, 0x9a, 0x2e, 0x8e, 0x03, 0x7c, 0x75, + 0xf5, 0xc4, 0xcb, 0x08, 0x85, 0x48, 0xb2, 0x11, 0x5d, 0xa3, + 0x86, 0x61, 0x57, 0x67, 0xe9, 0x63, 0x1d, 0x14, 0x70, 0xfe, + 0xde, 0xd2, 0x7c, 0xc2, 0x00, 0x44, 0x34, 0xb0, 0x8f, 0x6e, + 0x29, 0xa8, 0x0f, 0x07, 0xac, 0xba, 0xc1, 0x78 }, + { 0x30, 0x9a, 0x6e, 0x9a, 0xba, 0x26, 0x89, 0x49, 0xd8, 0x8f, + 0x56, 0x6b, 0xa1, 0x6e, 0x52, 0x3d, 0x8a, 0x86, 0xf0, 0x9b, + 0x5d, 0x6b, 0x81, 0x96, 0xae, 0xba, 0x4f, 0xe4, 0x8a, 0xe5, + 0xb6, 0x87, 0xfe, 0x02, 0xf8, 0x3c, 0xb1, 0x48, 0x76, 0x27, + 0x9c, 0x57, 0xb0, 0x29, 0xcf, 0x3d, 0xe4, 0x92, 0x98, 0x5e, + 0xf8, 0xd2, 0x42, 0xd1, 0xd9, 0x92, 0xe8, 0x0b, 0x2e, 0x7a, + 0xc1, 0x5b, 0x24, 0x89, 0xa7, 0x67, 0x26, 0x83, 0xea, 0x87, + 0x6f, 0x48, 0x60, 0x08, 0x3b, 0xd8, 0x81, 0x50, 0x91, 0x29, + 0xa9, 0x78, 0x88, 0x36, 0x4f, 0x53, 0xf5, 0x5f, 0x91, 0xd8, + 0x5d, 0x46, 0x4d, 0x6f, 0xd5, 0xb7, 0x12, 0xb6, 0xbf, 0x83, + 0x6c, 0x07, 0x15, 0x0f, 0x64, 0xa8, 0x46, 0xd1, 0xea, 0x98, + 0x7d, 0x2a, 0xdf, 0x58, 0x50, 0x58, 0x7c, 0x38, 0x45, 0x25, + 0x18, 0x9d, 0x1f, 0xdc, 0x0d, 0x19, 0x71, 0x6e }, + { 0x04, 0x58, 0x25, 0x8a, 0xd7, 0x59, 0x37, 0x89, 0xee, 0xb3, + 0x66, 0x53, 0x57, 0x69, 0xb2, 0x02, 0xe3, 0x59, 0x78, 0xfd, + 0x71, 0x4f, 0xea, 0x55, 0xcf, 0x96, 0x73, 0xc7, 0x75, 0xd6, + 0x8a, 0xc1, 0xd4, 0x2e, 0x87, 0x7f, 0xdb, 0x2a, 0x35, 0x8a, + 0x92, 0x4d, 0xbe, 0x7d, 0x53, 0xbe, 0x7e, 0xfd, 0xd3, 0x1c, + 0xcf, 0xd6, 0x21, 0xc2, 0xb6, 0x3d, 0x26, 0x7f, 0x8d, 0x8f, + 0x8e, 0x1e, 0xee, 0x88, 0x0f, 0xbb, 0x17, 0x14, 0x1f, 0xa2, + 0x64, 0xe8, 0xa1, 0x5b, 0x33, 0x62, 0xc4, 0x9d, 0x5c, 0xcb, + 0xc5, 0x81, 0xef, 0x87, 0xeb, 0x90, 0x86, 0x81, 0xc0, 0xc3, + 0xac, 0xdb, 0x75, 0x50, 0xed, 0x3a, 0x8f, 0xa1, 0x5a, 0x85, + 0xbe, 0xd3, 0x6c, 0xc5, 0xcc, 0x7b, 0xeb, 0x01, 0x7f, 0xe0, + 0x9f, 0x5c, 0x1a, 0x5f, 0xe7, 0x0f, 0xb8, 0xc5, 0x0c, 0x4d, + 0xef, 0x27, 0xee, 0x50, 0xbd, 0xfb, 0xe9, 0x7a }, + { 0x53, 0xf4, 0xa3, 0xe0, 0x95, 0xb7, 0x73, 0x58, 0xa2, 0xb8, + 0x80, 0xe5, 0x6f, 0x86, 0xc0, 0x29, 0x00, 0x4b, 0x87, 0x57, + 0xe4, 0x1f, 0xac, 0xc0, 0xba, 0xaf, 0x66, 0x3c, 0x96, 0xd1, + 0x09, 0x91, 0x7f, 0x74, 0x91, 0x5b, 0x2e, 0x84, 0xec, 0x34, + 0xbe, 0xe1, 0x48, 0x43, 0x4f, 0x02, 0x90, 0x4b, 0x83, 0xc8, + 0xf6, 0xa6, 0xe7, 0xb6, 0xd8, 0x86, 0xc0, 0x89, 0x5b, 0xff, + 0x39, 0x77, 0x7e, 0x00, 0xb3, 0x5f, 0xce, 0x26, 0xd6, 0xb3, + 0xc7, 0x42, 0x98, 0xc0, 0x56, 0x58, 0x43, 0x34, 0x6b, 0x9c, + 0xe0, 0xee, 0x85, 0x1d, 0xa3, 0x07, 0x67, 0xc3, 0xf5, 0x6a, + 0x8d, 0xef, 0x0f, 0x0e, 0x6b, 0x5f, 0x28, 0x5d, 0x67, 0x45, + 0xca, 0x2e, 0x89, 0x2e, 0x0e, 0x66, 0xcb, 0xa7, 0x0d, 0x2e, + 0x66, 0x57, 0x2d, 0x40, 0x58, 0x57, 0x57, 0x79, 0xdf, 0xa2, + 0x5d, 0xf7, 0x1a, 0x74, 0xa0, 0x42, 0xdb, 0xdf }, + { 0x0a, 0x99, 0xe6, 0x53, 0xd7, 0x23, 0xd2, 0x36, 0xaa, 0xf9, + 0x8d, 0x74, 0x69, 0x08, 0xd5, 0x63, 0x85, 0x01, 0x56, 0x2e, + 0x30, 0x5e, 0x99, 0xf0, 0x13, 0xa3, 0xf1, 0x45, 0x51, 0xd9, + 0x10, 0x73, 0x7c, 0x26, 0x4e, 0x6d, 0x48, 0x3e, 0xd8, 0x9a, + 0x16, 0xe8, 0xd9, 0x89, 0x24, 0x9e, 0x26, 0xf2, 0xfe, 0xb8, + 0xcc, 0xa0, 0xc4, 0x58, 0x45, 0xcf, 0x97, 0xc8, 0xdc, 0x0e, + 0xfc, 0x1c, 0xb5, 0xb5, 0xd3, 0x59, 0x47, 0xf5, 0xf3, 0xa8, + 0xf7, 0xf0, 0x38, 0xee, 0xc0, 0xcd, 0x28, 0x5d, 0xf2, 0xbf, + 0x42, 0xaa, 0x1a, 0xb6, 0x2b, 0x77, 0xb7, 0xa9, 0xe2, 0x6d, + 0x90, 0xb1, 0x76, 0x31, 0x91, 0x60, 0x7d, 0x2e, 0xfa, 0xea, + 0x79, 0x75, 0x7c, 0xb6, 0xf0, 0x6b, 0xcb, 0xf8, 0xa0, 0xc1, + 0xcb, 0x5a, 0xba, 0x60, 0xc5, 0x77, 0xaf, 0xab, 0x5a, 0xeb, + 0x11, 0xbb, 0x08, 0xce, 0x89, 0xfc, 0x48, 0xe7 }, + { 0x3a, 0x95, 0xcb, 0x45, 0x01, 0x0f, 0xcb, 0xc0, 0xb5, 0x95, + 0xdb, 0xd1, 0x3e, 0xeb, 0xf7, 0xea, 0x96, 0x50, 0xfc, 0x31, + 0x75, 0x32, 0x55, 0x48, 0x9f, 0x76, 0x87, 0x75, 0x33, 0x26, + 0x39, 0xe7, 0xd9, 0x73, 0x43, 0xee, 0x83, 0x23, 0xdd, 0xfa, + 0xfe, 0x20, 0x21, 0xe3, 0x42, 0x48, 0xe3, 0xd8, 0xc1, 0x26, + 0xa9, 0x3a, 0x0d, 0x0e, 0x30, 0x63, 0xcf, 0x74, 0x72, 0x73, + 0xf7, 0x84, 0x85, 0x23, 0xc5, 0xcd, 0x9a, 0xbe, 0x29, 0xb7, + 0x4d, 0x9a, 0x9a, 0xd3, 0x18, 0x93, 0x8c, 0x17, 0x0a, 0x36, + 0xa6, 0xf2, 0xdf, 0x8b, 0x46, 0x65, 0x52, 0xdb, 0xc6, 0x0f, + 0xf5, 0x7a, 0xab, 0x79, 0x3a, 0x2d, 0x61, 0x25, 0x4b, 0xe1, + 0x13, 0x78, 0xe9, 0x07, 0x22, 0x9f, 0xd2, 0x29, 0x0c, 0x16, + 0x81, 0xb5, 0xc1, 0x63, 0x06, 0x7b, 0x9a, 0xa1, 0xa1, 0x60, + 0x23, 0x53, 0x6f, 0x46, 0xab, 0xbc, 0x05, 0x59 }, + { 0x36, 0x6d, 0x22, 0x2e, 0x03, 0x0b, 0x72, 0x45, 0x5d, 0x71, + 0x3c, 0x1d, 0xda, 0xd6, 0x72, 0xc3, 0x93, 0x59, 0x7f, 0x66, + 0x32, 0x97, 0x84, 0xf1, 0x48, 0x5b, 0xb4, 0x36, 0xcd, 0xba, + 0x93, 0xda, 0x01, 0x70, 0x2d, 0xc1, 0x47, 0x44, 0xae, 0xe6, + 0xa5, 0xfb, 0x63, 0x9b, 0x41, 0xcc, 0xab, 0xa3, 0x2a, 0x2f, + 0xa3, 0xa0, 0x24, 0x53, 0x2a, 0xb3, 0x01, 0x57, 0xca, 0xa4, + 0x8c, 0xd0, 0x92, 0xda, 0xf0, 0x07, 0x7c, 0xdb, 0xd2, 0x7e, + 0x64, 0xdb, 0x54, 0x5d, 0x09, 0x25, 0x51, 0x86, 0xd2, 0x18, + 0x1a, 0x5b, 0xc3, 0xc3, 0xa6, 0x90, 0x2b, 0xda, 0x0c, 0x57, + 0x98, 0xab, 0x32, 0xcd, 0x08, 0xd2, 0x79, 0x65, 0xc0, 0xb0, + 0x91, 0xca, 0xd8, 0xce, 0x02, 0xa9, 0x2c, 0x77, 0x71, 0x69, + 0x43, 0x8a, 0x8d, 0xd1, 0xcb, 0x4b, 0xc1, 0xd5, 0xc4, 0x8f, + 0x95, 0x4e, 0x68, 0xcb, 0x39, 0xd7, 0xff, 0x2e }, + { 0x90, 0x72, 0xba, 0x99, 0x79, 0xde, 0xfd, 0x25, 0x17, 0x3d, + 0xcc, 0xd2, 0x06, 0x61, 0xbf, 0xda, 0x44, 0x28, 0x71, 0x53, + 0xd3, 0x08, 0x93, 0xfd, 0x4b, 0xb7, 0x6e, 0x73, 0xe5, 0x93, + 0x2b, 0x7e, 0x05, 0x5e, 0xa6, 0xdd, 0xad, 0xf1, 0xb3, 0x68, + 0x43, 0x40, 0x8d, 0xe1, 0x5f, 0x97, 0x1b, 0x8e, 0x4e, 0x8b, + 0x31, 0x45, 0xdd, 0x2f, 0x17, 0x59, 0x98, 0xed, 0x14, 0x99, + 0x2b, 0x8a, 0x78, 0xd8, 0x6d, 0xc5, 0xfe, 0xe7, 0x3f, 0x48, + 0xca, 0x07, 0x66, 0x92, 0x71, 0x2c, 0x7b, 0x5a, 0xd0, 0x7d, + 0xae, 0x14, 0x11, 0x47, 0xd3, 0x2a, 0xcd, 0x21, 0x0b, 0x8e, + 0xbf, 0x05, 0xa5, 0x38, 0xbf, 0x49, 0x72, 0x2a, 0x80, 0xa5, + 0xcf, 0x11, 0x44, 0x60, 0x7b, 0x53, 0xfa, 0x65, 0x7a, 0x1a, + 0x03, 0x10, 0x0f, 0xce, 0x40, 0x1b, 0xa9, 0x0d, 0xa4, 0x4d, + 0xd5, 0x0b, 0x48, 0x75, 0x57, 0x3e, 0xa5, 0xb2 }, + { 0x8d, 0x92, 0xc6, 0xbd, 0x35, 0x54, 0x6c, 0x29, 0x26, 0xac, + 0x96, 0x52, 0x43, 0x9d, 0x16, 0x54, 0x7e, 0x8f, 0x23, 0xd9, + 0xb6, 0xa8, 0x8f, 0x46, 0x7e, 0x60, 0x8d, 0x97, 0x7d, 0x6c, + 0x02, 0xee, 0x4d, 0x81, 0x5a, 0x40, 0x7f, 0x0f, 0x15, 0x3f, + 0x6b, 0x19, 0xbe, 0xa9, 0x35, 0xe1, 0x1b, 0xda, 0x33, 0xb2, + 0x88, 0x6d, 0x6b, 0x87, 0x1f, 0x8d, 0x56, 0x17, 0x1e, 0xcf, + 0xb0, 0xa0, 0xf5, 0x92, 0x6a, 0xe0, 0xe2, 0x2b, 0xfb, 0xdf, + 0xa5, 0xba, 0xea, 0x3e, 0x8a, 0xc6, 0x8a, 0xd1, 0x22, 0x42, + 0xa6, 0xe4, 0xc9, 0x87, 0x72, 0x9c, 0x09, 0xe3, 0x4e, 0xd0, + 0x72, 0xb3, 0x8f, 0x0e, 0xc9, 0xb3, 0x6a, 0x38, 0x28, 0x6f, + 0x3f, 0x3d, 0xf1, 0xd5, 0x0b, 0x0e, 0x8b, 0xb1, 0xcd, 0x3a, + 0x9c, 0x43, 0xfb, 0xf1, 0x64, 0x9f, 0xc8, 0x31, 0xce, 0xe8, + 0x47, 0x4d, 0xe4, 0xdd, 0x96, 0x20, 0xea, 0x39 }, + { 0x4e, 0x4b, 0xec, 0x17, 0x5c, 0x1a, 0xe5, 0xc0, 0x8d, 0x43, + 0xd8, 0x98, 0x8d, 0xd8, 0x27, 0xea, 0xf8, 0x05, 0x39, 0x6c, + 0x29, 0x05, 0x3e, 0xf5, 0x30, 0xaa, 0x52, 0xb1, 0xcb, 0xbb, + 0x54, 0x70, 0xa8, 0x8f, 0xda, 0xbf, 0x78, 0x88, 0x4c, 0x25, + 0x54, 0xbf, 0x9d, 0xe1, 0x53, 0xbd, 0xe6, 0x3d, 0xbe, 0x6a, + 0x50, 0x2b, 0x81, 0xf9, 0x0b, 0xdc, 0x97, 0xad, 0xec, 0x2d, + 0xf0, 0xa6, 0x21, 0xb0, 0xab, 0xcc, 0x81, 0x5a, 0xfa, 0x57, + 0xae, 0x0a, 0x91, 0x6a, 0x77, 0x9c, 0xbd, 0xa0, 0xb9, 0x47, + 0x87, 0x4e, 0xe8, 0x40, 0xf9, 0x3f, 0x58, 0x1c, 0x12, 0x45, + 0xad, 0xbc, 0x43, 0x5c, 0xfe, 0xe1, 0x9e, 0xce, 0x2e, 0x1f, + 0x1c, 0xd4, 0x4b, 0xc3, 0x57, 0xd1, 0xb2, 0x26, 0xde, 0x80, + 0x84, 0x99, 0xfb, 0xe3, 0x52, 0x54, 0x3e, 0x0e, 0x42, 0xf8, + 0xb3, 0xe0, 0xd7, 0xce, 0xab, 0xeb, 0x0f, 0xf7 }, + { 0x7a, 0x4a, 0xa3, 0xf5, 0x6f, 0x9d, 0xed, 0x24, 0x72, 0xe6, + 0x7d, 0x1a, 0xb4, 0x87, 0x76, 0x77, 0x64, 0x7e, 0x3d, 0x28, + 0xec, 0x7e, 0x81, 0xa2, 0x02, 0xb9, 0x4c, 0xb3, 0x32, 0x92, + 0x81, 0x3a, 0x44, 0x9c, 0x20, 0xa5, 0x98, 0xf5, 0x08, 0xa8, + 0xa9, 0xc8, 0x08, 0x00, 0xec, 0x2c, 0x63, 0xfe, 0x2c, 0x0e, + 0x8f, 0x30, 0xff, 0x56, 0xa9, 0xa1, 0xa6, 0xdc, 0xe0, 0x67, + 0xb4, 0xe8, 0x33, 0xa5, 0x0b, 0xd4, 0xbc, 0x6b, 0xd4, 0xfd, + 0x13, 0x5e, 0x47, 0x70, 0x45, 0x81, 0xb9, 0x0a, 0xf0, 0xb5, + 0x8d, 0x1b, 0x95, 0xd0, 0x9e, 0xd7, 0x46, 0xf0, 0x64, 0x4b, + 0xba, 0x98, 0x16, 0xe3, 0x51, 0x58, 0xe7, 0x91, 0x5f, 0xd2, + 0x84, 0x3f, 0xe7, 0xd8, 0xa6, 0x85, 0x2e, 0xf3, 0xd7, 0x02, + 0xa5, 0xdd, 0x45, 0x7c, 0x4a, 0x3f, 0x19, 0xea, 0x9a, 0x94, + 0xbf, 0x84, 0x83, 0xa2, 0xfc, 0xc0, 0x96, 0x76 }, + { 0x60, 0x28, 0x2a, 0x7b, 0xf7, 0xf0, 0xad, 0xe1, 0x0c, 0xbd, + 0x7d, 0xc8, 0xc0, 0xa2, 0x69, 0xc5, 0xdc, 0x9d, 0xfa, 0x4f, + 0xb4, 0x1a, 0xb5, 0xdf, 0x48, 0xfc, 0xeb, 0xde, 0x9f, 0xd0, + 0x9d, 0xf8, 0x15, 0x99, 0x2f, 0xb4, 0x28, 0xd6, 0x9b, 0x12, + 0x38, 0xe0, 0xbf, 0x42, 0x1a, 0x19, 0x27, 0x4f, 0xc1, 0xee, + 0xb3, 0xf3, 0xa9, 0xd3, 0xfe, 0x55, 0x67, 0xdc, 0xa1, 0x9d, + 0xcd, 0xce, 0x38, 0x1e, 0x77, 0x5d, 0xce, 0x9d, 0xb0, 0x51, + 0x2e, 0xa6, 0x96, 0xcc, 0x64, 0x0f, 0xcd, 0x3f, 0x4b, 0xb7, + 0x74, 0xf8, 0xfe, 0xe0, 0x34, 0xa2, 0xc8, 0x3b, 0x5a, 0xc6, + 0x81, 0x32, 0xaf, 0xfa, 0x1f, 0xcf, 0x97, 0x54, 0x4f, 0xc5, + 0x9b, 0x3f, 0x9c, 0x54, 0x23, 0xa4, 0x78, 0xe4, 0x39, 0xcf, + 0x8d, 0x24, 0xdc, 0x81, 0x2d, 0x4f, 0xb2, 0x42, 0xcb, 0x50, + 0x55, 0x9e, 0xf1, 0xba, 0xe2, 0x7a, 0x00, 0x45 }, + { 0x5f, 0x4a, 0xe9, 0xc7, 0x23, 0xc6, 0xb9, 0x42, 0x3f, 0xd2, + 0x86, 0xd9, 0x4a, 0x5f, 0xbe, 0x70, 0xe4, 0x7a, 0x75, 0x39, + 0x68, 0xcc, 0x39, 0xed, 0x2d, 0x6a, 0x40, 0x7d, 0xfb, 0xc5, + 0xc3, 0x72, 0x55, 0x50, 0xf7, 0xac, 0xd8, 0xc7, 0x3a, 0x43, + 0xe9, 0x01, 0x66, 0xd0, 0x0f, 0xa5, 0x16, 0xae, 0x5f, 0xb7, + 0x42, 0xf9, 0x19, 0x01, 0x91, 0x38, 0xc3, 0x0b, 0x71, 0x4e, + 0x16, 0xfe, 0x46, 0x6a, 0xf1, 0xe8, 0x2f, 0xfe, 0x00, 0x86, + 0x9b, 0xcd, 0x38, 0x69, 0x2c, 0xa8, 0x2c, 0xad, 0x14, 0x40, + 0x4c, 0x99, 0xf2, 0x58, 0x91, 0xa7, 0xb6, 0x42, 0xc6, 0x3a, + 0x34, 0x17, 0xb5, 0xe6, 0xb4, 0x05, 0xf2, 0x1b, 0x69, 0xfb, + 0xc7, 0x77, 0x6a, 0x10, 0x67, 0x68, 0x28, 0xf9, 0x4f, 0x1f, + 0x65, 0x16, 0x38, 0xa3, 0x22, 0xc8, 0x3c, 0x42, 0x06, 0x1d, + 0x7c, 0x07, 0xe5, 0x38, 0xdc, 0xee, 0xa2, 0xe7 }, + { 0x92, 0xa0, 0x14, 0x23, 0xdc, 0x46, 0xaf, 0xd2, 0x9c, 0xd3, + 0xe2, 0x91, 0x40, 0x1a, 0xa5, 0x03, 0x93, 0x9a, 0x7f, 0x26, + 0xac, 0xa4, 0xaa, 0x80, 0x2f, 0x64, 0xce, 0x73, 0x51, 0x0e, + 0x4d, 0x9c, 0xa2, 0x35, 0x27, 0x35, 0x2f, 0x27, 0x52, 0xaf, + 0xf5, 0xb3, 0xb4, 0xc6, 0xc9, 0x01, 0x42, 0x0c, 0x32, 0xee, + 0x98, 0xd4, 0x15, 0x66, 0x1c, 0x2d, 0x88, 0xb3, 0x46, 0x49, + 0x6b, 0x73, 0x66, 0xa9, 0xbb, 0xca, 0xdb, 0x87, 0x7a, 0x68, + 0xfc, 0x0a, 0xa4, 0xbc, 0xa8, 0x6e, 0xa8, 0x65, 0x88, 0x17, + 0xb9, 0x8c, 0x47, 0x1e, 0xf9, 0xe5, 0xee, 0x02, 0xc4, 0x15, + 0x1b, 0x0a, 0xa3, 0x76, 0x61, 0xb3, 0x25, 0x48, 0x8a, 0x0d, + 0x9f, 0x21, 0x95, 0xea, 0x44, 0x9a, 0x01, 0xfb, 0xfd, 0xd4, + 0xb0, 0x51, 0x28, 0x6d, 0x45, 0xd0, 0x16, 0xda, 0x19, 0x92, + 0xd9, 0x6a, 0x2d, 0xda, 0x53, 0xf4, 0xd5, 0x61 }, + { 0x0f, 0xc8, 0xfe, 0x1e, 0xaa, 0x88, 0xcb, 0x9b, 0x90, 0x74, + 0x87, 0x06, 0x16, 0x1c, 0x51, 0x5b, 0x6f, 0x2c, 0x42, 0x8b, + 0x89, 0x60, 0x95, 0x7e, 0xf9, 0x60, 0xb5, 0xb9, 0x94, 0x06, + 0xc3, 0xbd, 0x86, 0xdc, 0x2b, 0xa3, 0xe4, 0x88, 0x78, 0x9e, + 0x9c, 0xa1, 0x9a, 0x43, 0xd9, 0x9b, 0x08, 0x57, 0x2a, 0x22, + 0x62, 0x63, 0x16, 0xa4, 0xc8, 0x7e, 0x04, 0x57, 0x9f, 0x2c, + 0xac, 0xb5, 0xe4, 0x6e, 0x9f, 0x62, 0x30, 0xd7, 0x74, 0x24, + 0x01, 0x95, 0x82, 0x3f, 0xee, 0x7a, 0x82, 0x56, 0x6a, 0xbd, + 0x27, 0x4d, 0xd8, 0x5e, 0x05, 0x8d, 0x90, 0xbd, 0xe8, 0x7f, + 0x7d, 0x01, 0x7a, 0x67, 0x56, 0xfb, 0x9a, 0xb7, 0x13, 0xe2, + 0x48, 0x14, 0x19, 0x41, 0x96, 0x3e, 0x25, 0xbb, 0x86, 0x48, + 0xf1, 0x28, 0xda, 0x8c, 0x90, 0x0f, 0xb7, 0xd5, 0x27, 0xfa, + 0xe9, 0xf2, 0x4b, 0xe1, 0x1c, 0x2f, 0x7d, 0xbd }, + { 0x2d, 0x0b, 0xa8, 0x62, 0xdf, 0xd3, 0x78, 0x9f, 0x3c, 0x95, + 0x4d, 0x86, 0xd9, 0x98, 0x92, 0xdd, 0x39, 0x28, 0x5e, 0x51, + 0x5d, 0xc6, 0xdc, 0xbe, 0x3a, 0xd2, 0x75, 0x30, 0x5e, 0x88, + 0x74, 0xc5, 0xc6, 0xcc, 0xf5, 0xce, 0x70, 0x1a, 0xfb, 0xf3, + 0x2b, 0x3f, 0x1d, 0xab, 0xa2, 0xc4, 0xb1, 0x60, 0x95, 0xe8, + 0xf4, 0x6e, 0x78, 0xc1, 0x31, 0x8f, 0xe1, 0x50, 0xb6, 0xb4, + 0x2b, 0xf3, 0x29, 0x41, 0xdf, 0x36, 0x7c, 0x75, 0x1d, 0x89, + 0x83, 0x7e, 0xb1, 0x39, 0x1e, 0x70, 0xc8, 0x60, 0xf3, 0xff, + 0xc2, 0x64, 0x86, 0x8e, 0x16, 0x2c, 0xab, 0x31, 0xbd, 0x7e, + 0xa7, 0x03, 0x5e, 0x6f, 0x75, 0x29, 0x35, 0x4c, 0x24, 0x10, + 0xf8, 0xbe, 0x75, 0xc2, 0x2b, 0xe6, 0x2f, 0x9c, 0xf6, 0x4e, + 0x96, 0x35, 0xf3, 0x93, 0xbb, 0x3c, 0xa4, 0x8b, 0x15, 0x59, + 0x68, 0xae, 0x1b, 0xed, 0xfe, 0xb9, 0x0f, 0x2d }, + { 0x96, 0x3c, 0x87, 0x12, 0x4d, 0x41, 0xdb, 0xfc, 0xcc, 0xf6, + 0x4c, 0x75, 0x48, 0xa3, 0x76, 0xda, 0x70, 0x53, 0x75, 0xa4, + 0x09, 0xb6, 0x23, 0x5b, 0x0d, 0x12, 0x9f, 0x4a, 0x89, 0x49, + 0x76, 0x81, 0x26, 0x4c, 0xf1, 0xf9, 0xe2, 0x3c, 0xfb, 0xb7, + 0x7b, 0xe7, 0xee, 0xca, 0xa9, 0x33, 0xae, 0x7a, 0x5d, 0x3e, + 0x36, 0x7f, 0xb7, 0xf7, 0x0d, 0x81, 0xb9, 0x77, 0x17, 0x55, + 0x92, 0xa5, 0xed, 0x54, 0xc1, 0xd2, 0x8c, 0x9f, 0xd5, 0x35, + 0x4d, 0x69, 0xee, 0x33, 0x4d, 0xa1, 0xd1, 0x36, 0x67, 0x77, + 0x5e, 0xb0, 0x92, 0x5e, 0x9a, 0x81, 0xe5, 0x1e, 0xa9, 0x35, + 0x3d, 0xde, 0xa4, 0xee, 0x2f, 0x39, 0xfc, 0xcd, 0x60, 0xd7, + 0xfe, 0x6f, 0xc7, 0x06, 0x9b, 0x52, 0x0b, 0xf8, 0xd0, 0xd9, + 0x3f, 0xbd, 0xeb, 0x35, 0x4e, 0xae, 0xb7, 0x6a, 0xbb, 0xcc, + 0xea, 0xcd, 0x8e, 0xe8, 0xb4, 0x72, 0xe1, 0xaf }, + { 0x2d, 0x03, 0xeb, 0x3c, 0xff, 0x55, 0xd7, 0xbd, 0x17, 0x51, + 0xfb, 0xad, 0xa8, 0xce, 0xc7, 0xef, 0xb2, 0x96, 0xbe, 0x59, + 0x5d, 0x57, 0xbe, 0xac, 0x71, 0xda, 0x4f, 0xfa, 0x4e, 0x00, + 0xc0, 0xc0, 0x9d, 0x8f, 0xbb, 0x9e, 0x2e, 0xcf, 0x3c, 0x63, + 0x3e, 0xb6, 0x63, 0x0a, 0xee, 0xee, 0x42, 0x15, 0xfb, 0x9e, + 0x02, 0x84, 0xe3, 0xe6, 0x96, 0xbb, 0x53, 0xe8, 0xbd, 0xf9, + 0x43, 0xad, 0x74, 0x9c, 0xff, 0xca, 0x86, 0xaf, 0xf8, 0x48, + 0xc1, 0x06, 0xd0, 0xa2, 0x5d, 0x9a, 0xd8, 0x0a, 0x7f, 0x60, + 0x85, 0x6a, 0xff, 0x17, 0xbb, 0x51, 0x91, 0x1e, 0x43, 0x4d, + 0x76, 0x51, 0x90, 0x29, 0xec, 0x72, 0x0a, 0x7d, 0x19, 0xfd, + 0x29, 0x72, 0x0c, 0xea, 0x0e, 0xba, 0xd8, 0x67, 0xf7, 0x7f, + 0xe0, 0xe1, 0x9b, 0xdb, 0x01, 0x95, 0x73, 0x3b, 0x12, 0xb5, + 0xba, 0xe2, 0x90, 0xcb, 0xde, 0x36, 0xa8, 0x14 }, + { 0x84, 0x2e, 0x40, 0xc1, 0xc5, 0x4b, 0xac, 0xd9, 0xa3, 0xca, + 0x8d, 0x24, 0xa7, 0xcf, 0x61, 0xb7, 0xc2, 0x4f, 0x8a, 0x79, + 0x3e, 0xe6, 0xb7, 0xa7, 0xd9, 0x09, 0x32, 0x1b, 0x66, 0x37, + 0x82, 0x6b, 0xb9, 0x43, 0x85, 0xa2, 0x63, 0xef, 0xcd, 0x37, + 0x2d, 0x44, 0xc7, 0x37, 0xec, 0x2e, 0xe4, 0x11, 0x62, 0x69, + 0x84, 0xfe, 0xed, 0x21, 0x9b, 0x6c, 0x88, 0x9e, 0xe7, 0x71, + 0xf7, 0x55, 0xba, 0x6e, 0x88, 0x9f, 0x9b, 0xd7, 0x6b, 0xd7, + 0x33, 0x5e, 0xf3, 0xc4, 0x46, 0x0f, 0x13, 0xb0, 0xf3, 0xe3, + 0x6f, 0x14, 0xef, 0xb5, 0x5e, 0xe8, 0xed, 0x23, 0xc2, 0x82, + 0x72, 0xb3, 0x8c, 0xb9, 0x5d, 0x5b, 0x89, 0x1d, 0xf4, 0x4b, + 0x3f, 0x71, 0x03, 0x5b, 0x44, 0x2d, 0xf6, 0x04, 0xaa, 0xd9, + 0xd9, 0xe0, 0xa8, 0x78, 0xf2, 0x76, 0x0d, 0x14, 0x7e, 0xe2, + 0xeb, 0x16, 0x92, 0x5f, 0x04, 0xf2, 0xec, 0x1d }, + { 0x0e, 0x63, 0x31, 0x9a, 0xca, 0xc9, 0x13, 0x28, 0xa5, 0x96, + 0xb7, 0xcb, 0xbc, 0x31, 0xfe, 0x6c, 0x2d, 0x52, 0x66, 0xac, + 0x51, 0x28, 0xfc, 0x09, 0x77, 0x73, 0xc2, 0xa5, 0x62, 0x23, + 0xd0, 0x93, 0xcc, 0x6a, 0xe2, 0x97, 0x28, 0x5a, 0x40, 0x9f, + 0xd5, 0x96, 0x48, 0x14, 0x0d, 0x93, 0x32, 0xd2, 0x8c, 0xaf, + 0x6d, 0x9a, 0xcc, 0x87, 0x97, 0xcc, 0xb7, 0xf4, 0xcb, 0x08, + 0xe3, 0x07, 0x75, 0x13, 0xac, 0x52, 0x76, 0xc1, 0xdd, 0xe4, + 0x55, 0x06, 0xc5, 0x54, 0xec, 0x0a, 0xca, 0x5f, 0xca, 0x2f, + 0x82, 0x7f, 0x82, 0xca, 0x1e, 0xfe, 0x42, 0xd0, 0xbd, 0xac, + 0x5b, 0xf6, 0x57, 0xb2, 0xe2, 0x80, 0x69, 0x0d, 0xec, 0xb4, + 0xc6, 0x69, 0x59, 0x67, 0x16, 0xe6, 0xfe, 0xd1, 0x13, 0x11, + 0xe1, 0x77, 0x02, 0x32, 0x8c, 0xca, 0x4f, 0x5b, 0x30, 0xcd, + 0x5a, 0x26, 0x8e, 0xd6, 0xa6, 0x61, 0xd8, 0x43 }, + { 0x88, 0x83, 0x9d, 0xa2, 0x18, 0x72, 0x70, 0x5a, 0x49, 0x39, + 0xec, 0xef, 0x28, 0xe1, 0xa7, 0xc2, 0x0b, 0x7a, 0x9d, 0x51, + 0xff, 0xa5, 0xa3, 0x5b, 0x27, 0xa5, 0xa2, 0x22, 0xff, 0x83, + 0x89, 0xe2, 0xb0, 0x73, 0xbc, 0x04, 0xb3, 0xab, 0xaf, 0x32, + 0x90, 0xf3, 0x80, 0x18, 0x9b, 0x4c, 0xe3, 0xb6, 0x93, 0x4d, + 0xef, 0xa4, 0x9c, 0x22, 0xa0, 0x06, 0xb4, 0x15, 0x28, 0xb5, + 0x9b, 0x7b, 0x42, 0xd5, 0x5b, 0x1a, 0x3d, 0xb5, 0x69, 0xd3, + 0xe6, 0xa1, 0xe3, 0x65, 0x9c, 0x29, 0x0b, 0xfc, 0xc7, 0xf5, + 0x03, 0x79, 0xa9, 0x6b, 0x3f, 0xcc, 0xc5, 0x2d, 0x3d, 0xfc, + 0xf1, 0xb8, 0x52, 0x6c, 0x07, 0x0e, 0x9d, 0x5f, 0xa3, 0x8d, + 0xaa, 0x9a, 0xc5, 0x54, 0x82, 0xc6, 0xcf, 0x10, 0xe2, 0x5b, + 0x9b, 0x14, 0x86, 0xb6, 0x60, 0xde, 0x28, 0x5e, 0x60, 0x5a, + 0xb5, 0xcd, 0x2f, 0xad, 0xf0, 0x36, 0x0a, 0xc2 }, + { 0x64, 0x12, 0x8c, 0xfe, 0xa1, 0xf5, 0x0c, 0x26, 0xfc, 0x59, + 0xcc, 0xa7, 0x1d, 0x2e, 0x21, 0xc9, 0x39, 0xd0, 0xa5, 0x1d, + 0x44, 0x15, 0xc3, 0x69, 0xf3, 0x7f, 0xb2, 0xeb, 0xdb, 0x68, + 0x1b, 0x90, 0x35, 0x79, 0x1b, 0x90, 0xe9, 0xea, 0xef, 0x52, + 0x8f, 0x88, 0xb1, 0xdb, 0xb0, 0x52, 0x19, 0x0b, 0x1f, 0xaa, + 0x36, 0xb9, 0x6f, 0xc0, 0x51, 0x80, 0x42, 0x94, 0xf4, 0xf7, + 0x35, 0x5b, 0x67, 0x76, 0xc9, 0x34, 0xdb, 0x47, 0x0e, 0x72, + 0x73, 0xef, 0x21, 0x7f, 0x27, 0x57, 0x30, 0x00, 0xe9, 0xac, + 0xf5, 0xcc, 0xa6, 0x4a, 0xdd, 0x20, 0x38, 0x5a, 0xe7, 0x26, + 0x9c, 0x86, 0xfa, 0x2e, 0xe3, 0xca, 0xfe, 0xe5, 0x71, 0xe6, + 0x37, 0x3e, 0x3d, 0x13, 0xd4, 0xda, 0xfc, 0x0c, 0x10, 0x5f, + 0x9f, 0x21, 0x3a, 0xca, 0xf1, 0x26, 0x58, 0x98, 0x1d, 0x50, + 0x56, 0xb6, 0x6c, 0x30, 0x70, 0x1c, 0xe2, 0x9a }, + { 0x93, 0x63, 0x4a, 0x09, 0xbd, 0xab, 0xcb, 0xda, 0x01, 0x4f, + 0x54, 0xda, 0x17, 0x4a, 0x13, 0x2e, 0x32, 0x2c, 0xf0, 0xc2, + 0x7c, 0xe9, 0x87, 0x1b, 0x45, 0x99, 0xe9, 0x05, 0xe2, 0x53, + 0xe3, 0x7d, 0xd8, 0x65, 0xd0, 0x59, 0x01, 0x6d, 0xae, 0x01, + 0x09, 0x10, 0x49, 0xdb, 0x88, 0xb3, 0xa2, 0x06, 0xc6, 0x6b, + 0xa6, 0x86, 0x8f, 0x12, 0xcf, 0xd3, 0xdd, 0x4e, 0x27, 0x08, + 0x30, 0xc9, 0x28, 0xd1, 0x84, 0x92, 0x28, 0xc0, 0xd5, 0x1a, + 0xa4, 0x75, 0x78, 0xdf, 0xf0, 0x0c, 0xd4, 0x48, 0xf3, 0x45, + 0x3d, 0x18, 0xf0, 0xed, 0xf3, 0x82, 0x30, 0xf7, 0xf3, 0x9f, + 0x00, 0x33, 0xfa, 0xa8, 0xbb, 0xb0, 0x07, 0x5c, 0xa3, 0x46, + 0xbc, 0x83, 0xaf, 0x98, 0x41, 0x44, 0x04, 0x41, 0x93, 0xca, + 0x7c, 0xec, 0x5c, 0x7e, 0x24, 0x9c, 0xd3, 0x40, 0xf0, 0x59, + 0xf0, 0x36, 0x78, 0xa2, 0xe8, 0xf5, 0xb0, 0xb5 }, + { 0x26, 0x6c, 0xb4, 0x67, 0xbc, 0x06, 0x35, 0x7e, 0x4b, 0x4c, + 0x5b, 0xf2, 0x26, 0xde, 0xee, 0xe7, 0xc4, 0x08, 0xc3, 0x2d, + 0x9d, 0xcc, 0x22, 0xb2, 0x36, 0x20, 0x77, 0xa3, 0xb4, 0x04, + 0x87, 0x63, 0x1e, 0xd6, 0x72, 0xda, 0x4f, 0x87, 0xd7, 0x8e, + 0x30, 0x2f, 0x90, 0x9c, 0xd1, 0x39, 0xd6, 0x3b, 0x53, 0x72, + 0x77, 0x7b, 0x37, 0x3e, 0x0c, 0xfb, 0x97, 0xf0, 0x00, 0x9a, + 0x3f, 0x1c, 0xf6, 0x1e, 0xbb, 0xc1, 0x10, 0x71, 0xb9, 0xde, + 0xda, 0x81, 0xe4, 0xcb, 0xa6, 0x01, 0x6f, 0xa9, 0x5e, 0xab, + 0x72, 0x95, 0x57, 0x2b, 0x80, 0x38, 0xe6, 0x6d, 0x29, 0x65, + 0x5c, 0xf1, 0x2b, 0x5f, 0x46, 0xfd, 0x7e, 0x9b, 0x6b, 0x85, + 0xa9, 0x84, 0x7c, 0xfe, 0x91, 0x3a, 0xb8, 0x32, 0x22, 0x38, + 0x17, 0x10, 0xc5, 0x7e, 0x18, 0x66, 0xc1, 0xa4, 0xc1, 0x24, + 0x62, 0x82, 0x6b, 0x27, 0xa9, 0xa2, 0xe3, 0x04 }, + { 0x4b, 0x1d, 0x5a, 0x1b, 0x52, 0x45, 0x4e, 0xe1, 0xbc, 0xb0, + 0x29, 0xa8, 0x3c, 0x8f, 0x2a, 0xf3, 0x78, 0x2f, 0xd0, 0xd1, + 0xf7, 0x47, 0x3a, 0xc1, 0x7e, 0xe7, 0xb5, 0xbc, 0x53, 0x15, + 0xb8, 0xd7, 0x09, 0x32, 0xbf, 0xcb, 0xa1, 0xb7, 0xd1, 0x20, + 0x15, 0x48, 0x82, 0x8e, 0xc3, 0x6a, 0xb6, 0x11, 0xc1, 0x54, + 0xe8, 0x92, 0x63, 0xab, 0x8c, 0x9e, 0x68, 0xb2, 0xf4, 0xeb, + 0x9d, 0x5c, 0xf3, 0x64, 0xe3, 0xc3, 0x28, 0x7d, 0x09, 0xf3, + 0x51, 0x1d, 0x60, 0x6e, 0x1e, 0xb9, 0x88, 0x70, 0xdc, 0x95, + 0x55, 0xca, 0xa8, 0x33, 0xa5, 0x36, 0xbf, 0x78, 0xcf, 0x44, + 0xb2, 0xec, 0xf1, 0x99, 0x11, 0xa6, 0x5b, 0x34, 0xae, 0x3e, + 0xfa, 0x00, 0x4b, 0x84, 0x14, 0x35, 0x8d, 0xde, 0x2b, 0x9e, + 0x65, 0x97, 0x4b, 0x4f, 0xd0, 0x78, 0x3c, 0x1a, 0xa4, 0xdb, + 0x6f, 0xaa, 0x41, 0x54, 0xb5, 0x63, 0x63, 0xe8 }, + { 0x81, 0x86, 0xb9, 0x3f, 0x50, 0x8e, 0x4b, 0x27, 0xe0, 0x74, + 0x39, 0xfa, 0xb6, 0x22, 0xd4, 0x2a, 0xc8, 0x31, 0xfd, 0xce, + 0x12, 0x0b, 0xf6, 0x19, 0x6f, 0xc0, 0x77, 0x62, 0xbe, 0x6a, + 0xbb, 0xd0, 0xbb, 0xf7, 0xee, 0x13, 0x3e, 0xa5, 0xa2, 0xec, + 0x0d, 0x4e, 0x56, 0xf1, 0x30, 0xee, 0xa0, 0xe3, 0x10, 0x81, + 0x0f, 0x3d, 0x52, 0x07, 0xec, 0x91, 0x7c, 0xc8, 0x00, 0xd4, + 0x65, 0x75, 0x7d, 0x4e, 0x32, 0x87, 0x36, 0x1b, 0x0d, 0xf5, + 0x11, 0xc8, 0xd7, 0xde, 0x5e, 0x12, 0xfc, 0xa3, 0xda, 0xda, + 0xba, 0x31, 0xf6, 0xb5, 0xb1, 0x5e, 0x08, 0x0a, 0x90, 0x12, + 0x3a, 0x0a, 0x79, 0x7e, 0x81, 0x07, 0x88, 0xb3, 0xf1, 0xca, + 0xac, 0xfa, 0x5a, 0x43, 0x5c, 0x62, 0x15, 0x63, 0x36, 0x0e, + 0x39, 0x56, 0x37, 0x35, 0x52, 0x5e, 0x18, 0x8c, 0x09, 0x9d, + 0x12, 0xfe, 0x51, 0x74, 0x63, 0xd5, 0x2c, 0x0c }, + { 0x0b, 0xf9, 0x7e, 0x97, 0xc9, 0xee, 0x2b, 0x2a, 0x47, 0x43, + 0xde, 0x57, 0xf3, 0x4a, 0x9b, 0xfa, 0x79, 0xcf, 0xc6, 0xd7, + 0x22, 0xc3, 0xab, 0x57, 0x12, 0xbf, 0xff, 0x1a, 0x27, 0xb5, + 0x21, 0x4e, 0xb1, 0x39, 0xc0, 0x76, 0x90, 0xbe, 0x35, 0x7e, + 0x30, 0x08, 0x6c, 0xf4, 0x43, 0x58, 0x0b, 0x7a, 0xab, 0xa6, + 0x58, 0x91, 0x05, 0xd4, 0x11, 0x0a, 0x4b, 0xb8, 0x63, 0xb9, + 0xd9, 0x47, 0x7c, 0x91, 0x35, 0x1e, 0x6a, 0x00, 0x9b, 0x7d, + 0x9b, 0x1c, 0x7b, 0x5d, 0xc4, 0x44, 0x83, 0x1c, 0x04, 0x97, + 0xec, 0xb0, 0x1c, 0x0b, 0xbe, 0xb4, 0xd6, 0x44, 0xed, 0x30, + 0xed, 0x65, 0xce, 0x68, 0xb8, 0xfe, 0x50, 0xaa, 0x50, 0x57, + 0xa4, 0xfc, 0x3d, 0x82, 0xc1, 0xcf, 0x16, 0x68, 0x1f, 0x5f, + 0x5d, 0xda, 0x7e, 0x04, 0x2c, 0x05, 0xbf, 0xaf, 0x7d, 0xb4, + 0xc6, 0x19, 0xd1, 0x54, 0x09, 0x31, 0x28, 0x67 }, + { 0x8f, 0xe5, 0x48, 0x2c, 0x3e, 0x40, 0xaa, 0xbb, 0x3b, 0xd9, + 0x1b, 0xb4, 0xfe, 0xaa, 0xc2, 0x3f, 0x57, 0x6a, 0x87, 0x0d, + 0x56, 0x76, 0xf1, 0x20, 0xe6, 0xbf, 0xa9, 0xe0, 0x0a, 0x9d, + 0x0b, 0xc8, 0x6b, 0x7a, 0xc0, 0xab, 0x9e, 0x69, 0xd9, 0x4e, + 0x3d, 0xe3, 0x7a, 0x9a, 0x9f, 0x5e, 0xf4, 0x39, 0xe2, 0x2c, + 0x79, 0x76, 0xad, 0x47, 0x35, 0x99, 0xd3, 0xd7, 0x41, 0x6e, + 0x1d, 0x2d, 0xc7, 0xdf, 0x9e, 0xb8, 0x1a, 0x0f, 0x32, 0xf1, + 0x28, 0x06, 0x18, 0x96, 0xec, 0xda, 0xb3, 0x93, 0x97, 0x30, + 0x65, 0xce, 0x25, 0xf1, 0x95, 0xbc, 0x3e, 0x13, 0x98, 0xa6, + 0x97, 0xa4, 0x62, 0xfd, 0xcc, 0x09, 0x1a, 0xc6, 0xf6, 0x8b, + 0x0d, 0x9a, 0x0d, 0x99, 0x7e, 0x83, 0x61, 0x2b, 0x65, 0xf6, + 0x91, 0x8a, 0x54, 0xce, 0x18, 0xea, 0x6c, 0x30, 0x6e, 0x8b, + 0x96, 0xec, 0x4e, 0xc8, 0xdd, 0xa1, 0x9e, 0x96 }, + { 0x39, 0x28, 0xc6, 0x69, 0xbb, 0xc8, 0xbc, 0x3f, 0x4a, 0xeb, + 0x62, 0x06, 0xb4, 0x2d, 0x3b, 0xf6, 0x18, 0x9e, 0xd1, 0x8b, + 0x6b, 0x4b, 0x5c, 0x8d, 0x95, 0xa9, 0x13, 0xb9, 0xca, 0xd2, + 0xde, 0xd6, 0xa6, 0x7c, 0x11, 0x4c, 0x64, 0x27, 0x5d, 0x2c, + 0x4c, 0x91, 0x8b, 0xb1, 0x23, 0xda, 0xb5, 0x66, 0xa7, 0xd4, + 0x84, 0xbe, 0x0f, 0x64, 0x0a, 0x5f, 0xc5, 0xc0, 0x09, 0xa1, + 0x52, 0x19, 0x9f, 0x43, 0x69, 0x67, 0x9f, 0x1e, 0x50, 0xb4, + 0xd1, 0x8f, 0xc8, 0x7e, 0xf5, 0x15, 0xb6, 0x4a, 0xe8, 0xb6, + 0xdc, 0x62, 0x07, 0x8d, 0xf0, 0x2e, 0xb0, 0xda, 0x99, 0x61, + 0xf5, 0xbc, 0xe7, 0x1c, 0x29, 0x4e, 0x80, 0x3d, 0xe0, 0xad, + 0x30, 0x8f, 0xb4, 0x1c, 0x5c, 0x6c, 0x8f, 0x3a, 0x25, 0xd0, + 0x61, 0x92, 0x4c, 0x3e, 0xb8, 0x03, 0x4f, 0x1d, 0x20, 0x38, + 0x85, 0xae, 0x67, 0xc2, 0xce, 0x9a, 0x4d, 0x1e }, + { 0x6c, 0xcc, 0x88, 0x8f, 0x35, 0x51, 0x34, 0xf6, 0x17, 0x04, + 0xd2, 0xe1, 0x91, 0x50, 0xd0, 0xd9, 0x81, 0xc3, 0x5b, 0x3e, + 0xf0, 0x71, 0xcd, 0xe4, 0xf0, 0x1d, 0xff, 0x93, 0x73, 0x89, + 0x27, 0x54, 0x3b, 0xaa, 0xdc, 0x8b, 0x21, 0xd4, 0x05, 0xd1, + 0x1b, 0x14, 0xd9, 0xe6, 0xbe, 0xa1, 0xc1, 0xfd, 0xad, 0xee, + 0xfa, 0x98, 0xc2, 0x59, 0xd0, 0xd4, 0x68, 0x1d, 0xf6, 0xdd, + 0xa7, 0xc9, 0x30, 0xeb, 0x7f, 0xae, 0x8b, 0xbe, 0x4e, 0x3b, + 0x2f, 0x0d, 0x31, 0x67, 0x4a, 0x4f, 0x67, 0xce, 0xe9, 0x84, + 0x5a, 0xd8, 0xa5, 0x96, 0x21, 0x21, 0xb7, 0x7b, 0x42, 0x60, + 0x42, 0xbc, 0x40, 0x7b, 0x85, 0xc4, 0x90, 0x44, 0x8f, 0xbd, + 0xd3, 0x6f, 0x33, 0x1e, 0xf3, 0xaa, 0xc9, 0x4e, 0x7a, 0x91, + 0x12, 0xa4, 0x03, 0xf6, 0x2a, 0x44, 0xf2, 0x61, 0x79, 0xa1, + 0xde, 0x4b, 0xea, 0x4a, 0xda, 0xcb, 0x4b, 0x64 }, + { 0x2f, 0x15, 0x19, 0x80, 0xb2, 0x6f, 0xae, 0xf9, 0x6a, 0xfa, + 0x63, 0x57, 0xad, 0x4e, 0xd7, 0xbd, 0x03, 0x5f, 0xf1, 0x10, + 0xc8, 0xc0, 0xf8, 0x15, 0x8f, 0x79, 0x2b, 0x21, 0x1a, 0xca, + 0x3c, 0xe9, 0x53, 0xd5, 0xb8, 0x43, 0x74, 0xb9, 0x13, 0x93, + 0xa1, 0x7e, 0x14, 0x84, 0x25, 0x9d, 0x52, 0x54, 0x17, 0xed, + 0x0f, 0x5d, 0x39, 0x73, 0xca, 0xcf, 0xa4, 0x84, 0x13, 0x78, + 0xfa, 0xb1, 0xe8, 0xbe, 0xcb, 0x8f, 0xd9, 0x8b, 0x9c, 0xbd, + 0x35, 0x1a, 0x31, 0x20, 0x24, 0xa9, 0x09, 0xb8, 0xce, 0x1e, + 0x0b, 0x8c, 0x1a, 0x82, 0x99, 0xad, 0x8e, 0xb7, 0x68, 0x25, + 0xa6, 0xe6, 0x01, 0x4e, 0xdc, 0xfc, 0x12, 0x76, 0xf4, 0xce, + 0xba, 0xeb, 0xf3, 0x2f, 0x0d, 0xcd, 0x1e, 0xde, 0xfe, 0xde, + 0x67, 0xaa, 0xbc, 0xa3, 0x26, 0x5f, 0xf7, 0x95, 0x9d, 0xdd, + 0xf8, 0xd3, 0x6f, 0x0e, 0x7a, 0xd7, 0x50, 0x4c }, + { 0x35, 0x4b, 0x05, 0xb7, 0x0a, 0xc5, 0x8d, 0x65, 0x6c, 0x80, + 0x5c, 0xe8, 0xbe, 0xb5, 0x4a, 0xaa, 0x1c, 0x21, 0x90, 0x85, + 0xa8, 0xeb, 0x99, 0x20, 0xf7, 0xbe, 0x03, 0x89, 0x20, 0x5c, + 0x4e, 0x92, 0x3a, 0x20, 0x2c, 0x70, 0xfd, 0x22, 0xdf, 0x11, + 0xe6, 0x17, 0x32, 0x71, 0xf4, 0xab, 0x67, 0xb3, 0x44, 0xed, + 0xf3, 0xf9, 0x13, 0xbe, 0xee, 0xf6, 0x63, 0x8f, 0x6b, 0x74, + 0x94, 0x98, 0xfd, 0x7d, 0xc7, 0x1d, 0xb2, 0x90, 0x15, 0xa3, + 0x1b, 0xdf, 0x83, 0x81, 0xe3, 0xd8, 0x0a, 0xef, 0x5a, 0x85, + 0x03, 0x1d, 0xb9, 0xe7, 0xf3, 0x35, 0x5a, 0x17, 0xba, 0xaa, + 0x17, 0x67, 0x9d, 0x88, 0xc6, 0x58, 0x6d, 0x6c, 0xf4, 0xc0, + 0xb6, 0xce, 0x47, 0xec, 0x3e, 0x5a, 0x97, 0x92, 0x6c, 0x05, + 0xb7, 0x5b, 0x12, 0x1f, 0xbb, 0xc2, 0xbc, 0x03, 0x99, 0x55, + 0x0c, 0x86, 0x31, 0xda, 0x29, 0xd2, 0xd4, 0x39 }, + { 0x48, 0xdc, 0x55, 0xc4, 0xae, 0x35, 0x23, 0xa1, 0xd4, 0x1b, + 0xe8, 0x93, 0xcf, 0x09, 0xfa, 0xc2, 0x3e, 0x7d, 0xac, 0xb8, + 0x70, 0xac, 0xc7, 0x05, 0x99, 0x38, 0xf9, 0x32, 0xe5, 0x5e, + 0xfc, 0xf9, 0x61, 0x96, 0xe2, 0x17, 0xa4, 0x68, 0x1b, 0xe2, + 0x84, 0x7a, 0xf9, 0xfc, 0x44, 0x82, 0xf1, 0x3b, 0xf3, 0x1d, + 0x33, 0x32, 0xec, 0xa6, 0x86, 0x30, 0xf3, 0x24, 0x1a, 0xb8, + 0xa9, 0xf8, 0x1a, 0x18, 0xa3, 0x2f, 0xb5, 0xbc, 0xbb, 0xbc, + 0xe7, 0x6f, 0x52, 0x59, 0x1a, 0xc3, 0x2f, 0xf0, 0xa7, 0x2b, + 0x00, 0x05, 0x8e, 0x3f, 0x5c, 0x3d, 0x97, 0x1e, 0xb7, 0x13, + 0x8a, 0x7f, 0x96, 0x5c, 0x7d, 0x01, 0xa7, 0x3e, 0x8c, 0xe3, + 0xa6, 0x6c, 0xae, 0x1a, 0xff, 0xbe, 0x82, 0x4f, 0x3c, 0xdd, + 0xcc, 0xfb, 0x01, 0xee, 0xc4, 0x2d, 0x4c, 0xad, 0x50, 0xcd, + 0x71, 0x71, 0xe2, 0x36, 0x7a, 0x91, 0x70, 0xe9 }, + { 0x5f, 0x6a, 0x8e, 0xdd, 0x0b, 0x6d, 0xc0, 0x21, 0x40, 0x5c, + 0xe4, 0xc5, 0x66, 0xe3, 0x8c, 0x68, 0x87, 0x25, 0xe2, 0x4b, + 0xb9, 0x3b, 0x9c, 0x33, 0xcb, 0x94, 0xcc, 0xff, 0x98, 0x6b, + 0x8d, 0x62, 0x19, 0xf2, 0x9d, 0x71, 0x8b, 0x8a, 0xf2, 0xcd, + 0x85, 0x1c, 0x9f, 0x4b, 0x1d, 0x0d, 0x7b, 0x3a, 0x5d, 0x67, + 0xb9, 0x73, 0xba, 0x15, 0x59, 0x04, 0xcd, 0xeb, 0xa9, 0xf7, + 0x71, 0x31, 0x3c, 0x58, 0x18, 0x70, 0x70, 0x75, 0x8a, 0x51, + 0xcf, 0x02, 0x15, 0x4e, 0x10, 0x77, 0x8a, 0xf5, 0x88, 0x69, + 0x38, 0x2e, 0xb6, 0xe7, 0xa5, 0x12, 0x15, 0x1c, 0x98, 0x2d, + 0xef, 0x67, 0x97, 0xd0, 0x0e, 0x38, 0x41, 0x78, 0x06, 0x40, + 0x83, 0xc7, 0xd2, 0x45, 0x2f, 0x13, 0x56, 0xaf, 0x25, 0xc9, + 0xeb, 0x41, 0xe4, 0x6e, 0xc3, 0x62, 0x68, 0x98, 0x97, 0x0c, + 0x8e, 0x62, 0x38, 0x26, 0xa5, 0x09, 0x21, 0x93 }, + { 0x1c, 0xa6, 0x50, 0x72, 0xca, 0x7f, 0x87, 0xac, 0x2e, 0x12, + 0xe0, 0x7a, 0x9e, 0xb8, 0x14, 0xbb, 0x9b, 0x33, 0x48, 0x0d, + 0x5a, 0x87, 0x97, 0xd3, 0x15, 0x6c, 0xcb, 0x70, 0x8b, 0xfb, + 0x7c, 0xf0, 0x84, 0x0f, 0x04, 0x21, 0xf2, 0x7d, 0xb4, 0x90, + 0xcc, 0xe6, 0x56, 0x2b, 0xf4, 0x3c, 0xe0, 0x1e, 0x64, 0x8d, + 0xa3, 0x42, 0x0e, 0xa2, 0x43, 0xdb, 0xe4, 0x42, 0x8a, 0xcd, + 0xdf, 0x32, 0x57, 0x97, 0x4c, 0xa2, 0xb9, 0xe4, 0x4f, 0xe1, + 0xf7, 0x39, 0x53, 0x79, 0x51, 0xb3, 0xb8, 0xa5, 0x97, 0x94, + 0x00, 0x5c, 0xfb, 0xba, 0x4e, 0xa4, 0x57, 0xa8, 0x78, 0x04, + 0x66, 0x4a, 0x04, 0xaa, 0xb2, 0x6d, 0x4c, 0xd5, 0x8f, 0x16, + 0xbc, 0xe3, 0xa4, 0xcf, 0xfb, 0xc1, 0x2d, 0x8c, 0x69, 0x20, + 0x10, 0x28, 0x3f, 0x36, 0x97, 0x66, 0x2f, 0x76, 0xa4, 0x07, + 0x83, 0x70, 0x4c, 0xa5, 0x8f, 0x9a, 0x86, 0x90 }, + { 0x46, 0x2c, 0xaf, 0xb6, 0xcb, 0xad, 0x3c, 0xee, 0xac, 0x44, + 0xfd, 0x91, 0x35, 0xff, 0xff, 0x64, 0xac, 0xa6, 0x63, 0x99, + 0x1f, 0xb3, 0x07, 0xa1, 0x05, 0x5d, 0xec, 0x1c, 0x14, 0xf9, + 0xa1, 0x92, 0x9f, 0x7a, 0xff, 0x32, 0x49, 0xfa, 0xca, 0xba, + 0xd0, 0xd7, 0x10, 0xc0, 0x68, 0x98, 0x09, 0x85, 0x7f, 0xad, + 0x3b, 0xd1, 0xe6, 0x67, 0x54, 0x3c, 0x4d, 0xd2, 0xdb, 0x49, + 0x96, 0x46, 0xaa, 0x34, 0xef, 0x8d, 0x44, 0x3e, 0x0d, 0x85, + 0x8c, 0x5f, 0x39, 0xb7, 0x52, 0x43, 0x8b, 0xbe, 0x33, 0x91, + 0x1d, 0x96, 0xb5, 0x07, 0x89, 0xb7, 0x8d, 0xa8, 0x9b, 0x74, + 0xd8, 0xfe, 0x56, 0x47, 0xdd, 0x68, 0x56, 0xed, 0x1e, 0xa4, + 0x7d, 0x80, 0x06, 0x8f, 0xc1, 0xc1, 0x53, 0x0e, 0x59, 0xe3, + 0x68, 0xb5, 0x66, 0xaf, 0xfd, 0xca, 0x40, 0xa7, 0x46, 0xdb, + 0xfb, 0xb3, 0x21, 0xcf, 0x2b, 0x9d, 0x25, 0xa0 }, + { 0x12, 0x93, 0xc9, 0x8c, 0x6c, 0xd9, 0x36, 0x08, 0x2a, 0x29, + 0x15, 0x03, 0xb5, 0x46, 0xea, 0xfd, 0xd2, 0xfb, 0x77, 0x18, + 0x3e, 0x8f, 0x9d, 0x13, 0x23, 0x15, 0x5e, 0x22, 0x51, 0x3f, + 0x83, 0xc0, 0xaa, 0x78, 0x4f, 0xab, 0x65, 0xf4, 0x85, 0x76, + 0x06, 0xfe, 0xe7, 0xfe, 0xd9, 0xba, 0xa6, 0xd3, 0x0f, 0x75, + 0xd2, 0x35, 0xa7, 0x32, 0xd1, 0xcc, 0xbc, 0x87, 0x5d, 0x03, + 0x0a, 0x2e, 0xbe, 0x41, 0xdf, 0xef, 0xc9, 0x7d, 0xa9, 0xc3, + 0x91, 0x7f, 0x4e, 0x7e, 0x8d, 0xfc, 0x25, 0xa9, 0xa1, 0x2b, + 0xa1, 0xa2, 0xbe, 0x74, 0x6e, 0xf1, 0x83, 0x31, 0x18, 0x75, + 0x39, 0x3d, 0x1c, 0x93, 0xe2, 0x98, 0x15, 0xef, 0x04, 0x3e, + 0x72, 0x6b, 0x91, 0x4a, 0xf7, 0x87, 0x9f, 0x59, 0xdd, 0xfa, + 0x55, 0xf8, 0x95, 0xf7, 0x35, 0xcc, 0x82, 0xb8, 0x74, 0x04, + 0x16, 0x60, 0xa6, 0x47, 0xde, 0x32, 0x37, 0xdd }, + { 0x53, 0xb7, 0x9a, 0xa1, 0x68, 0xea, 0x94, 0xba, 0x73, 0xe4, + 0xb5, 0xf3, 0xe4, 0x6f, 0x8f, 0xb1, 0xed, 0xb2, 0x58, 0x4c, + 0x39, 0x46, 0x98, 0x8b, 0xc6, 0x92, 0x9c, 0xd4, 0xfd, 0xfd, + 0x61, 0x4f, 0xa0, 0xa4, 0x7f, 0x05, 0x06, 0x4e, 0x71, 0x42, + 0x16, 0xe7, 0x9e, 0x41, 0x74, 0xad, 0x91, 0x07, 0xd0, 0x5c, + 0x23, 0xc5, 0x49, 0x40, 0xc3, 0xe8, 0x58, 0xcf, 0xb2, 0xfb, + 0x1a, 0xe9, 0xd7, 0xc7, 0xbe, 0x1c, 0x0f, 0xb8, 0xa1, 0xbd, + 0x18, 0x9e, 0xca, 0x83, 0xcb, 0x86, 0xe7, 0x7b, 0x11, 0x1a, + 0xb0, 0xb0, 0x28, 0x9c, 0x8c, 0x87, 0x53, 0x0d, 0x49, 0x5f, + 0x6a, 0xbf, 0x33, 0xb3, 0x75, 0x22, 0x82, 0x38, 0xc7, 0x08, + 0x87, 0xe7, 0x71, 0xc1, 0xb7, 0xd7, 0xc7, 0xdb, 0x4a, 0x36, + 0xb7, 0x11, 0xa6, 0xab, 0x40, 0x3d, 0x96, 0xea, 0xfa, 0xc7, + 0x72, 0x78, 0x12, 0x51, 0x49, 0xd5, 0x3b, 0x77 }, + { 0x82, 0x90, 0xd6, 0xd1, 0x56, 0xc2, 0xe8, 0x33, 0x40, 0xa6, + 0xf7, 0xd5, 0xf3, 0x87, 0x2c, 0x9d, 0x15, 0x0f, 0xb4, 0xa9, + 0x58, 0x40, 0x11, 0x04, 0xc8, 0x9d, 0xc0, 0x1b, 0x32, 0x81, + 0x51, 0xe1, 0xe5, 0xef, 0x49, 0x97, 0xc8, 0x3a, 0xf2, 0xa8, + 0x04, 0x09, 0x99, 0x03, 0xc9, 0xd5, 0xda, 0x0f, 0xb9, 0x28, + 0x7f, 0x58, 0x53, 0x46, 0x61, 0x1d, 0x64, 0x00, 0xbc, 0x54, + 0x23, 0x45, 0x96, 0xc4, 0x0d, 0x53, 0x9d, 0x8d, 0x47, 0x39, + 0x7c, 0x05, 0x23, 0x11, 0x98, 0x69, 0x29, 0xfe, 0x89, 0xa2, + 0x64, 0x96, 0x8e, 0xe6, 0x51, 0x2c, 0x67, 0x38, 0xfe, 0xd5, + 0xab, 0xce, 0x7b, 0x4e, 0xc0, 0x14, 0x02, 0x2e, 0xaf, 0x3d, + 0xf1, 0x9e, 0xfa, 0xfe, 0xef, 0x1e, 0x4b, 0x30, 0xa9, 0xdd, + 0x93, 0x9a, 0xd3, 0xa5, 0xbb, 0xa0, 0x67, 0x82, 0x17, 0x28, + 0x21, 0x6f, 0xaf, 0xce, 0x44, 0xbb, 0xb6, 0xa1 }, + { 0x50, 0x6e, 0xf1, 0xab, 0x30, 0x4f, 0xab, 0xb0, 0x6f, 0xa1, + 0xd9, 0x69, 0xee, 0x95, 0x2e, 0x14, 0x45, 0x9f, 0x29, 0x7b, + 0xa0, 0xaa, 0x98, 0x4e, 0x00, 0xf3, 0x32, 0xe1, 0xec, 0x47, + 0xb3, 0xcf, 0xfd, 0x22, 0x3e, 0x26, 0xf0, 0x6a, 0x2a, 0x08, + 0x51, 0xcc, 0x6e, 0xf9, 0xb3, 0x3f, 0xa0, 0xe1, 0x1b, 0xea, + 0xd0, 0x2c, 0xa6, 0x75, 0x23, 0x5a, 0x6e, 0x6b, 0x55, 0xe9, + 0xdb, 0x32, 0x16, 0x60, 0x23, 0x80, 0xed, 0x5c, 0xed, 0x96, + 0x78, 0x11, 0xcc, 0x20, 0x8d, 0xe6, 0x33, 0xaa, 0xfc, 0xa5, + 0xa2, 0x71, 0x4c, 0xa6, 0x0b, 0xca, 0xdb, 0x5f, 0xe6, 0x2a, + 0xe5, 0x2d, 0x2d, 0x67, 0x84, 0xa9, 0xb4, 0x25, 0x57, 0xfe, + 0x0d, 0xc7, 0xb8, 0x09, 0xd4, 0x23, 0x59, 0xa4, 0xd7, 0x89, + 0x00, 0x7e, 0xda, 0x13, 0x4a, 0x39, 0x69, 0xec, 0x57, 0xfa, + 0xf8, 0x46, 0x37, 0xc6, 0xd8, 0x54, 0x69, 0x46 }, + { 0x41, 0x5b, 0x7d, 0xbf, 0x15, 0x20, 0x03, 0x44, 0xda, 0xaf, + 0x3f, 0xdb, 0x4d, 0x85, 0xc6, 0x78, 0x6c, 0xcd, 0x2f, 0xbf, + 0xf7, 0x1a, 0x70, 0x6e, 0x14, 0x04, 0xcc, 0xf8, 0xb9, 0x8f, + 0xcb, 0xc7, 0xfa, 0xbe, 0x77, 0x43, 0xfa, 0x8f, 0xeb, 0x1f, + 0xe1, 0x4a, 0x45, 0x6f, 0x8e, 0xed, 0x67, 0x65, 0x6e, 0xec, + 0x74, 0xd2, 0x37, 0x9d, 0x92, 0xd1, 0xdf, 0xea, 0x34, 0x23, + 0xd4, 0xdc, 0xbc, 0x3c, 0xdd, 0x35, 0x4c, 0xac, 0xbd, 0xc8, + 0x9a, 0x16, 0xa2, 0x8d, 0x63, 0x3d, 0xdf, 0x73, 0xad, 0x9c, + 0x36, 0xa6, 0xaf, 0x39, 0xe3, 0x07, 0x1b, 0x58, 0xf5, 0x09, + 0x0a, 0x7e, 0xa7, 0x30, 0x75, 0xaa, 0xa2, 0xda, 0xf1, 0xa5, + 0x9d, 0xd1, 0xc3, 0xd5, 0x66, 0xac, 0xeb, 0x3f, 0x9d, 0xeb, + 0x27, 0xce, 0x71, 0x30, 0xb9, 0x6f, 0xea, 0x9f, 0xa9, 0x84, + 0x11, 0xb4, 0xeb, 0x27, 0x35, 0xbf, 0xf1, 0x63 }, + { 0x1e, 0xc3, 0x14, 0xf1, 0xaf, 0x58, 0x87, 0x9d, 0x52, 0x5d, + 0xc9, 0xbd, 0xec, 0x83, 0x1d, 0x59, 0xfc, 0xe0, 0xfa, 0xfc, + 0xc1, 0x75, 0xd4, 0x3f, 0x00, 0x69, 0x65, 0xed, 0xb4, 0x12, + 0x2e, 0x05, 0x35, 0x22, 0xce, 0xf0, 0xa2, 0xb5, 0x51, 0x1c, + 0x76, 0x9a, 0x2e, 0xf9, 0x85, 0xf0, 0x68, 0xaa, 0x01, 0xdc, + 0x4c, 0x3f, 0xe6, 0x93, 0x65, 0x08, 0xf9, 0x31, 0x8c, 0x91, + 0x97, 0xf0, 0x0f, 0x11, 0x45, 0x49, 0x97, 0x51, 0x86, 0x32, + 0x0a, 0x01, 0x0c, 0xda, 0x36, 0xd9, 0x6e, 0x0e, 0x54, 0xc2, + 0xfc, 0x6a, 0xc6, 0xc6, 0x0f, 0xeb, 0x9f, 0x3b, 0x71, 0x2f, + 0xa1, 0x3c, 0xe9, 0xe5, 0xa2, 0xb8, 0x4b, 0xc7, 0x09, 0x5d, + 0x93, 0xc8, 0xf2, 0x90, 0xfd, 0x67, 0xd2, 0x89, 0xf0, 0x3a, + 0x4c, 0x32, 0x06, 0x8a, 0x3d, 0x68, 0xcb, 0x80, 0x32, 0x72, + 0x97, 0x01, 0x05, 0x86, 0x7d, 0x83, 0x77, 0xa7 }, + { 0x17, 0xe9, 0x1d, 0x12, 0x7f, 0xff, 0x57, 0x88, 0xad, 0x5c, + 0xc0, 0x8f, 0x2d, 0xc1, 0x05, 0xde, 0x71, 0x93, 0x6c, 0xb4, + 0x52, 0xab, 0xfa, 0x6b, 0x76, 0x51, 0x35, 0xd2, 0x3d, 0xe5, + 0xa6, 0x64, 0xbb, 0x32, 0xf1, 0x7c, 0x96, 0x93, 0x9c, 0x82, + 0xe0, 0xc8, 0xb6, 0xf7, 0xf5, 0x87, 0x5a, 0xec, 0xa9, 0x31, + 0xb9, 0x9d, 0x77, 0x46, 0xe0, 0xc7, 0xd3, 0xbb, 0x0a, 0x97, + 0x26, 0xec, 0xcf, 0xa0, 0xf0, 0x01, 0xc4, 0x6e, 0xdd, 0x2f, + 0x9e, 0x6f, 0x01, 0x8b, 0x1c, 0x63, 0xae, 0x4b, 0x9b, 0xc6, + 0x34, 0x13, 0x02, 0xf9, 0xf7, 0xde, 0x17, 0x11, 0x50, 0x77, + 0x33, 0x20, 0xb5, 0x42, 0xf8, 0xdf, 0xcd, 0xe4, 0xa3, 0x8f, + 0x63, 0x7e, 0xc2, 0xc5, 0x39, 0x2b, 0x10, 0xfc, 0xe5, 0x34, + 0x68, 0x87, 0xaa, 0x7e, 0x14, 0xda, 0x45, 0x7e, 0x3f, 0x74, + 0x06, 0x63, 0xfe, 0xef, 0x2c, 0x83, 0x10, 0xc2 }, + { 0x11, 0x8f, 0x3b, 0x4b, 0x3d, 0xdd, 0x0c, 0x01, 0xdf, 0x24, + 0x22, 0x82, 0xaf, 0xc4, 0xa0, 0xd5, 0x16, 0x29, 0xf7, 0xc2, + 0x63, 0xf7, 0xb9, 0x7e, 0xf3, 0x01, 0xa3, 0x8f, 0xb1, 0x8a, + 0xe1, 0xf9, 0xca, 0x7c, 0x98, 0xed, 0x57, 0x25, 0x71, 0xdf, + 0x6e, 0x65, 0x3e, 0xa4, 0x1d, 0xeb, 0x3e, 0x28, 0x99, 0x58, + 0x4a, 0xeb, 0x91, 0xd4, 0xa3, 0xb6, 0x0d, 0x76, 0x59, 0x57, + 0xb5, 0x99, 0x73, 0x2d, 0x35, 0x49, 0x97, 0xe4, 0x77, 0x96, + 0x3e, 0x0e, 0xa7, 0xbd, 0x46, 0x92, 0x8c, 0x36, 0x5a, 0xec, + 0x54, 0x50, 0x9e, 0x65, 0xd1, 0x2a, 0x19, 0xee, 0x39, 0x52, + 0x49, 0xa3, 0xd2, 0x89, 0xe9, 0xc7, 0x3e, 0xa6, 0x62, 0x27, + 0xce, 0x9d, 0x6b, 0x31, 0xc8, 0xab, 0x4b, 0x52, 0x00, 0x86, + 0x78, 0x4b, 0xc6, 0x44, 0xd4, 0xfd, 0x19, 0xc7, 0x76, 0xd4, + 0xbe, 0x92, 0xce, 0xd3, 0xb7, 0xe0, 0x51, 0xca }, + { 0x01, 0xd0, 0xa6, 0x7c, 0x8d, 0x03, 0xe7, 0x27, 0x3b, 0x9b, + 0x53, 0x6a, 0x44, 0xf1, 0x70, 0x24, 0x22, 0xce, 0x8a, 0x79, + 0x44, 0xf5, 0x93, 0xc2, 0x21, 0xd2, 0xb6, 0x31, 0x21, 0xb6, + 0x17, 0x10, 0x1d, 0xbd, 0xbd, 0x1a, 0xc2, 0xdd, 0x61, 0x7f, + 0x87, 0x8e, 0xcc, 0x0d, 0x00, 0x71, 0x5b, 0xa1, 0x15, 0x61, + 0x8d, 0x0b, 0x1b, 0xdf, 0xe5, 0x2f, 0x5b, 0xc1, 0x8b, 0x4f, + 0xdf, 0x75, 0x86, 0x95, 0x73, 0x5e, 0xb6, 0x86, 0xe7, 0x7a, + 0x4c, 0x05, 0xa3, 0xe1, 0x78, 0x34, 0x5b, 0x08, 0x46, 0xe5, + 0xc2, 0x44, 0xa6, 0x09, 0x5d, 0xd6, 0x14, 0x7a, 0x83, 0x63, + 0x7f, 0xfb, 0x3e, 0xcc, 0x1d, 0xba, 0xc0, 0xbe, 0x87, 0x86, + 0x7e, 0x60, 0xd9, 0x8b, 0x16, 0xff, 0x49, 0x60, 0x4c, 0xf7, + 0x6d, 0x86, 0x1a, 0xef, 0x84, 0xda, 0x8c, 0x58, 0xd1, 0x75, + 0x74, 0xa0, 0xa0, 0xa8, 0x7a, 0xd4, 0x76, 0x2b }, + { 0x1b, 0x62, 0x5b, 0x06, 0x7d, 0xa6, 0x32, 0x0f, 0xc9, 0xad, + 0xba, 0x24, 0x99, 0x7c, 0x08, 0xe6, 0xdd, 0x52, 0x7b, 0x43, + 0xc5, 0x6b, 0xb0, 0x44, 0xca, 0xdd, 0x2d, 0xfa, 0x48, 0x6e, + 0x2f, 0x84, 0x5a, 0xd8, 0xb5, 0x72, 0xc9, 0x50, 0xd5, 0xd4, + 0x7f, 0x47, 0xd4, 0x56, 0xb4, 0xed, 0x85, 0x69, 0x52, 0x36, + 0x4b, 0xa1, 0xfa, 0xbd, 0x59, 0x52, 0xcd, 0x57, 0x2d, 0xfd, + 0x2a, 0xf0, 0x3b, 0x37, 0x59, 0x6c, 0xce, 0xb5, 0xd2, 0xe8, + 0x65, 0x0a, 0x03, 0xd5, 0x45, 0x21, 0x11, 0xe6, 0x8d, 0xa6, + 0x7b, 0x67, 0xec, 0xdb, 0xe7, 0x6c, 0x0d, 0x63, 0x74, 0xa6, + 0x9b, 0xdd, 0x4c, 0xb6, 0x63, 0xe3, 0x71, 0x35, 0xe8, 0x1d, + 0xd8, 0x3c, 0x7a, 0x45, 0x01, 0x9b, 0x5d, 0x16, 0xa4, 0x2c, + 0x4a, 0x18, 0xe9, 0x47, 0x79, 0x90, 0xfb, 0x88, 0xc2, 0xae, + 0x7b, 0x96, 0x42, 0x36, 0x1e, 0x46, 0x53, 0x3c }, + { 0x33, 0x3e, 0xca, 0x96, 0x19, 0xfc, 0x94, 0x8d, 0xbd, 0xf1, + 0x43, 0x28, 0x84, 0x00, 0x73, 0x6e, 0x15, 0x39, 0x79, 0x21, + 0xa7, 0x07, 0x66, 0x39, 0x13, 0xf5, 0xca, 0x6f, 0xbf, 0x06, + 0x97, 0x68, 0x32, 0x1f, 0xaa, 0xc2, 0x98, 0x26, 0x65, 0x6a, + 0xc4, 0xca, 0x56, 0x7c, 0x36, 0x0c, 0xb3, 0x65, 0xf6, 0x68, + 0x20, 0x65, 0x3f, 0x7d, 0xf0, 0xc2, 0x6d, 0x6e, 0x32, 0x58, + 0x24, 0x33, 0xda, 0x34, 0xdb, 0x1f, 0x80, 0xc6, 0x34, 0xd8, + 0x52, 0xd7, 0x87, 0xdc, 0xb5, 0x34, 0x2b, 0x41, 0xc5, 0xdd, + 0x6b, 0x24, 0x5e, 0x5c, 0x1f, 0x49, 0x09, 0x8b, 0x2b, 0x97, + 0x1c, 0xba, 0x87, 0x15, 0x6b, 0xc9, 0xf3, 0x3c, 0x43, 0x4f, + 0xbb, 0xa9, 0x75, 0x8b, 0xbf, 0x44, 0x43, 0x88, 0xfe, 0x88, + 0x38, 0xb5, 0xc0, 0x1b, 0x2f, 0x01, 0xaf, 0x6f, 0xeb, 0xeb, + 0x44, 0xdf, 0xaa, 0x7b, 0x4f, 0xd8, 0x44, 0x6d }, + { 0x72, 0xfc, 0x21, 0x10, 0x87, 0x28, 0xd1, 0x35, 0xae, 0x9d, + 0x9c, 0x07, 0x4c, 0xcf, 0x07, 0x46, 0x4d, 0x25, 0xc7, 0x42, + 0xf2, 0xcd, 0x13, 0x4f, 0x76, 0x50, 0x82, 0xa5, 0x37, 0xe7, + 0xb1, 0x5d, 0x55, 0x7b, 0x32, 0x2a, 0x65, 0xcd, 0x44, 0x9d, + 0x98, 0x7d, 0xa7, 0x4a, 0xe5, 0x4b, 0x64, 0xa7, 0xf3, 0x5e, + 0x8c, 0xf1, 0x33, 0x93, 0x74, 0x3e, 0x90, 0xc1, 0x6e, 0xeb, + 0xcb, 0x25, 0xb9, 0x99, 0x5a, 0x17, 0xf8, 0xe5, 0x1d, 0x61, + 0x6e, 0x91, 0xd7, 0x24, 0x08, 0xdc, 0x52, 0x35, 0x96, 0x61, + 0x5d, 0xb3, 0x56, 0x5a, 0x7f, 0x5c, 0x01, 0xf0, 0x2b, 0x3a, + 0x13, 0xa4, 0x13, 0xfb, 0x3b, 0x5b, 0xaa, 0xd3, 0x62, 0x36, + 0x54, 0x70, 0x3f, 0xe7, 0x62, 0x3c, 0x7a, 0x4f, 0xbc, 0xfc, + 0xe9, 0x48, 0x38, 0xc2, 0x51, 0x8f, 0xd4, 0x1d, 0xbb, 0xca, + 0x23, 0x33, 0x79, 0x48, 0xac, 0x77, 0x5d, 0x81 }, + { 0x48, 0x09, 0x46, 0xf8, 0xb1, 0x1e, 0xd9, 0x2d, 0x23, 0x8e, + 0xf1, 0x7c, 0x88, 0x40, 0xa6, 0xc6, 0xe1, 0xa2, 0x73, 0x8e, + 0xa1, 0x7e, 0x35, 0xa4, 0xe5, 0x73, 0xf6, 0x48, 0x9d, 0xef, + 0xf9, 0xa0, 0x03, 0x80, 0x3d, 0x84, 0x56, 0x17, 0x70, 0x40, + 0x1e, 0xe4, 0x8d, 0xe3, 0x2f, 0x7b, 0x16, 0x5b, 0x76, 0x0f, + 0x8d, 0x28, 0x5c, 0x2f, 0xfc, 0x3c, 0x22, 0x8a, 0x39, 0x1b, + 0x5d, 0x33, 0x6d, 0x51, 0xfb, 0xbd, 0xcf, 0x0c, 0x7d, 0x3d, + 0xe6, 0x66, 0xeb, 0x9a, 0xde, 0x06, 0x9a, 0x3d, 0xf8, 0x5e, + 0x4a, 0x1f, 0xee, 0x78, 0xbc, 0xe8, 0x20, 0x62, 0x91, 0xc8, + 0xcc, 0xa9, 0x55, 0xa0, 0x60, 0x81, 0x4a, 0x9e, 0xa6, 0xfb, + 0xe5, 0x50, 0xc8, 0xee, 0xd7, 0x7d, 0x58, 0x67, 0x55, 0xf3, + 0x59, 0x09, 0xd8, 0x3f, 0x95, 0xcf, 0x45, 0x80, 0x55, 0xff, + 0xa9, 0x06, 0xb2, 0x03, 0xf9, 0x60, 0x04, 0xc8 }, + { 0x8d, 0xab, 0x61, 0xfd, 0xc7, 0x38, 0x69, 0x02, 0x16, 0xe8, + 0xe8, 0xae, 0xcf, 0x68, 0xaf, 0xc7, 0xf8, 0x6f, 0x2b, 0xe6, + 0xc1, 0xf8, 0x53, 0x9f, 0xc0, 0x1c, 0x2e, 0xb2, 0x46, 0x46, + 0x4d, 0x9e, 0xa1, 0xae, 0x66, 0x6b, 0x4b, 0xa8, 0x46, 0xe4, + 0xcb, 0x3b, 0x43, 0x61, 0xe4, 0xbb, 0xd0, 0x07, 0x00, 0x89, + 0xc0, 0x6e, 0x7d, 0x06, 0xe6, 0x84, 0xe2, 0x77, 0x5e, 0xb6, + 0x09, 0x92, 0xf7, 0xd0, 0x3b, 0x72, 0xb0, 0x4d, 0x6c, 0x2b, + 0x7d, 0xd4, 0xc8, 0x86, 0x9a, 0xba, 0xe2, 0x0f, 0xd6, 0x24, + 0x84, 0x97, 0x50, 0x96, 0x2c, 0xaa, 0xf8, 0x92, 0xa1, 0xa9, + 0x90, 0x24, 0xc6, 0x30, 0xb8, 0xc0, 0x48, 0xa4, 0x88, 0x99, + 0xab, 0x18, 0xd6, 0xf4, 0x0e, 0x2f, 0x67, 0x86, 0x62, 0x98, + 0x58, 0x7a, 0x19, 0xe6, 0x5c, 0x5e, 0x53, 0xeb, 0x36, 0x95, + 0x84, 0xc7, 0x47, 0xa8, 0xfd, 0x71, 0xf1, 0x19 }, + { 0x6f, 0x77, 0xe6, 0x2d, 0xf9, 0x9b, 0x29, 0xe7, 0xe0, 0x3c, + 0xa8, 0x79, 0x11, 0x8f, 0x69, 0x0c, 0x9d, 0xef, 0x7a, 0xd1, + 0x67, 0xb9, 0x7e, 0xe1, 0x3e, 0xb2, 0x1b, 0x14, 0xcb, 0xd7, + 0xce, 0xf1, 0x55, 0xbe, 0x8a, 0x15, 0x2c, 0xaf, 0x08, 0x0e, + 0x5e, 0xce, 0x77, 0xab, 0xb8, 0x16, 0x9f, 0xed, 0x86, 0x94, + 0x22, 0x9f, 0x31, 0xdc, 0xc9, 0x57, 0xa1, 0x04, 0x44, 0xeb, + 0xa5, 0x90, 0x70, 0x0d, 0x80, 0x27, 0x14, 0xc1, 0x9e, 0xc5, + 0x15, 0x02, 0x87, 0x7f, 0x8b, 0xcf, 0x3f, 0x06, 0xfd, 0xc2, + 0x1d, 0xe7, 0x6a, 0xed, 0x91, 0x1f, 0x32, 0xe6, 0xd3, 0xd2, + 0x39, 0xbb, 0x34, 0x86, 0x54, 0x02, 0x35, 0xb2, 0xba, 0x2b, + 0x08, 0xc4, 0x62, 0x1a, 0x2d, 0x88, 0xb5, 0x20, 0x34, 0xd4, + 0x78, 0xb4, 0xac, 0xd4, 0x29, 0x7e, 0xff, 0x4f, 0x9b, 0xa2, + 0x42, 0xa5, 0xc9, 0x03, 0xd5, 0x4d, 0x1d, 0x45 }, + { 0x63, 0x81, 0x9c, 0x91, 0xc3, 0xd2, 0xcf, 0x80, 0x79, 0x9d, + 0x78, 0x86, 0x81, 0x84, 0xf0, 0xeb, 0x23, 0x44, 0xe0, 0x0f, + 0x68, 0xbe, 0xd1, 0x02, 0xee, 0x6d, 0x75, 0x78, 0xc1, 0xcf, + 0x55, 0x80, 0x86, 0x13, 0x60, 0x73, 0x2e, 0x5a, 0x8b, 0xe6, + 0xae, 0x5e, 0x2e, 0x76, 0xd6, 0x69, 0x84, 0x0a, 0x31, 0x4d, + 0x5d, 0x57, 0x77, 0x3b, 0x7b, 0x3a, 0x91, 0xe0, 0xa2, 0xef, + 0x06, 0xc0, 0xcc, 0x42, 0x99, 0xaa, 0xfa, 0xbf, 0xf8, 0x5c, + 0x3f, 0xbf, 0x11, 0xaa, 0x01, 0x2f, 0xff, 0x3b, 0xf3, 0xb5, + 0x97, 0x92, 0xa8, 0xfd, 0x6f, 0x38, 0xea, 0xc7, 0x22, 0xeb, + 0x71, 0x13, 0xa8, 0x13, 0x35, 0x9f, 0x34, 0x65, 0xb4, 0x66, + 0x4b, 0x71, 0xb0, 0x2f, 0x17, 0x55, 0xe0, 0x35, 0x73, 0x54, + 0x1c, 0xd1, 0x17, 0x7b, 0xa4, 0x53, 0x64, 0x01, 0xaa, 0xd6, + 0xa2, 0x71, 0xbd, 0xed, 0xe4, 0x0b, 0xbf, 0x59 }, + { 0x67, 0xd4, 0x8d, 0x12, 0x82, 0x65, 0xd7, 0xee, 0xc8, 0x0a, + 0xfe, 0xec, 0x55, 0xe4, 0x9b, 0x47, 0xe4, 0x3a, 0x0b, 0xe7, + 0x0a, 0x2f, 0x8c, 0xab, 0xc0, 0xd0, 0x31, 0x9a, 0x50, 0x4b, + 0x6b, 0xc1, 0xe0, 0xfc, 0x16, 0xd3, 0x4e, 0xbd, 0x45, 0x3e, + 0xe1, 0x31, 0xcc, 0x9a, 0xbd, 0xa6, 0x12, 0x5a, 0x10, 0xb2, + 0xcf, 0xe7, 0x97, 0x6a, 0x84, 0x4b, 0x1f, 0xf6, 0x0c, 0x51, + 0xa0, 0xd3, 0xd8, 0x1a, 0xc5, 0xb3, 0x37, 0x6f, 0x17, 0x1d, + 0x12, 0x04, 0x5a, 0xab, 0xf3, 0x91, 0xfa, 0xde, 0x65, 0x00, + 0xeb, 0xf5, 0x75, 0x89, 0x2a, 0xea, 0x4f, 0xbf, 0xf9, 0x66, + 0x64, 0xee, 0x1b, 0xf9, 0x6b, 0x91, 0xcb, 0x2a, 0xc0, 0x7c, + 0xe4, 0xc4, 0x7b, 0x70, 0x3d, 0x07, 0xf5, 0xf0, 0x90, 0x70, + 0x38, 0xa7, 0x9e, 0xc3, 0xa1, 0xfc, 0xeb, 0x12, 0x67, 0xea, + 0xca, 0x53, 0x92, 0xe1, 0x78, 0x84, 0xb0, 0x73 }, + { 0x27, 0x95, 0x0e, 0x38, 0xe8, 0x38, 0x4d, 0xc7, 0xa3, 0xd7, + 0xeb, 0xc3, 0x1f, 0x0e, 0x43, 0xf5, 0x2c, 0xf1, 0x13, 0xa9, + 0x28, 0xb0, 0x1d, 0xf5, 0xd4, 0x90, 0x0d, 0x0f, 0x10, 0xd1, + 0xc1, 0x84, 0x3e, 0xfc, 0xaa, 0x50, 0xab, 0xf2, 0x94, 0x01, + 0xfe, 0x8b, 0xb1, 0x20, 0x5e, 0xe6, 0x05, 0x96, 0xfd, 0xd5, + 0x6b, 0x1b, 0x4d, 0xc9, 0x27, 0xcd, 0x95, 0xf6, 0x2c, 0x85, + 0xc5, 0xb6, 0x49, 0xd4, 0x84, 0x22, 0x9d, 0xf4, 0x75, 0x61, + 0xa0, 0x10, 0x47, 0x2d, 0xdc, 0x3d, 0x64, 0xa2, 0xf9, 0xa8, + 0xde, 0xe7, 0xca, 0x2b, 0x75, 0xba, 0x8c, 0x3d, 0x89, 0xa2, + 0x42, 0xe7, 0xf7, 0x7e, 0x62, 0x93, 0xfb, 0xb6, 0x39, 0xca, + 0x07, 0x20, 0x4e, 0xbc, 0x6b, 0xd1, 0x1d, 0xb0, 0xae, 0x73, + 0x66, 0xcd, 0xd7, 0x1a, 0xbd, 0x0e, 0x27, 0x48, 0x0a, 0x63, + 0x06, 0x8d, 0x59, 0xa7, 0xea, 0x2d, 0x56, 0xd6 }, + { 0x54, 0xff, 0x78, 0x84, 0x79, 0xb2, 0x5d, 0x71, 0xa1, 0xc9, + 0x98, 0x13, 0xff, 0x22, 0x25, 0xab, 0xae, 0x80, 0x45, 0x3f, + 0xbb, 0x1e, 0x5b, 0xd8, 0xa7, 0xf0, 0x44, 0x0c, 0x9f, 0x68, + 0x4f, 0x25, 0x33, 0x5c, 0xc4, 0xf8, 0x5d, 0x15, 0xdf, 0xbf, + 0xff, 0x3a, 0xba, 0x5c, 0x69, 0x62, 0x80, 0x46, 0x55, 0xce, + 0x84, 0x91, 0x58, 0x80, 0xcd, 0xaf, 0x8e, 0xe0, 0x0e, 0x1a, + 0x8e, 0xef, 0x6c, 0xc9, 0x4e, 0x01, 0x41, 0xae, 0x85, 0x02, + 0xaa, 0x89, 0x20, 0x73, 0x95, 0x4c, 0xd2, 0xe9, 0x6d, 0xdf, + 0x14, 0x42, 0xbf, 0x36, 0x7d, 0xd4, 0xc5, 0x31, 0x46, 0x71, + 0x6f, 0x79, 0xa9, 0x25, 0xe7, 0xe7, 0xbb, 0x48, 0x27, 0xfa, + 0x4e, 0xb2, 0x1f, 0x6b, 0x4c, 0x93, 0x46, 0x89, 0x2f, 0xe3, + 0x74, 0xcb, 0x4b, 0x9f, 0xd0, 0x33, 0x04, 0x8b, 0x5d, 0xe9, + 0xea, 0xb2, 0x1f, 0xf0, 0xe1, 0xd0, 0xfa, 0x79 }, + { 0x8a, 0xdb, 0xad, 0x85, 0x3f, 0x18, 0x30, 0xfe, 0x4e, 0x4e, + 0x45, 0x73, 0xee, 0x30, 0xb2, 0x86, 0x8a, 0xcd, 0xa9, 0x65, + 0x9f, 0xa1, 0x01, 0xe6, 0x17, 0x87, 0x55, 0x00, 0x28, 0xc9, + 0x30, 0x2c, 0x06, 0x9e, 0x82, 0xdc, 0x36, 0x78, 0xa4, 0x27, + 0xd6, 0xa2, 0xc0, 0x1d, 0x8b, 0x6a, 0x6c, 0x6b, 0x28, 0x94, + 0x5e, 0x31, 0xc9, 0x55, 0xae, 0xad, 0x91, 0x53, 0x62, 0xdc, + 0xb7, 0x86, 0xea, 0x9f, 0x33, 0x9d, 0xf0, 0x81, 0x0c, 0xcd, + 0x9e, 0xc9, 0xc6, 0x8f, 0x1b, 0x3b, 0x4a, 0x2c, 0x08, 0xe3, + 0xbb, 0x74, 0xe5, 0x8f, 0xdc, 0xb0, 0xc0, 0x0f, 0xe3, 0x28, + 0x54, 0x41, 0x8d, 0xf9, 0x0d, 0x2b, 0x50, 0xa5, 0xa5, 0xad, + 0xc0, 0x41, 0x81, 0x15, 0xe2, 0x4a, 0x46, 0x04, 0xfa, 0x3b, + 0x21, 0xf6, 0x92, 0x26, 0x46, 0x5b, 0xe6, 0xf3, 0xa5, 0x1e, + 0x27, 0xc6, 0xee, 0x30, 0xde, 0x40, 0xb0, 0x68 }, + { 0x73, 0x93, 0x00, 0x36, 0xc0, 0x94, 0x5e, 0x5f, 0xf3, 0x42, + 0xc1, 0xaa, 0x02, 0x7e, 0x71, 0xc1, 0xb7, 0x5c, 0x41, 0xa6, + 0x66, 0xcb, 0xc9, 0x6c, 0xf5, 0x88, 0xb4, 0xf8, 0x17, 0x17, + 0xe1, 0xaf, 0x14, 0xeb, 0x86, 0xf3, 0x58, 0x40, 0x7a, 0x1d, + 0xdb, 0xe3, 0x86, 0xcb, 0x81, 0x6c, 0x07, 0x30, 0x40, 0x3f, + 0x16, 0x8c, 0x30, 0x26, 0xcd, 0x41, 0x95, 0xb1, 0x6c, 0xcc, + 0xcd, 0x5e, 0x87, 0xe7, 0x40, 0xd8, 0x6f, 0x30, 0x12, 0x43, + 0xf3, 0xef, 0x40, 0x90, 0xcf, 0xa6, 0x1b, 0x46, 0x4b, 0x28, + 0xcd, 0xbc, 0x2a, 0xd2, 0x09, 0x84, 0xfb, 0x0e, 0x6a, 0xa1, + 0xf5, 0xde, 0x8e, 0x1c, 0x0f, 0x7f, 0x45, 0x6b, 0x9c, 0xf2, + 0xe2, 0x33, 0x6d, 0x4f, 0x3c, 0xec, 0x67, 0x66, 0x7c, 0xc1, + 0xfc, 0xc2, 0xf4, 0x2f, 0xda, 0xf7, 0xf3, 0x9b, 0xcc, 0x79, + 0x06, 0x0a, 0xe1, 0x1f, 0x09, 0x69, 0xd5, 0x24 }, + { 0x8b, 0xc6, 0xec, 0x4a, 0xe4, 0x29, 0x65, 0xe2, 0x5b, 0xd1, + 0x01, 0x82, 0xaa, 0x7c, 0x99, 0xd3, 0x9c, 0x28, 0xa9, 0x67, + 0x73, 0xea, 0xf2, 0x23, 0xcf, 0x56, 0x13, 0x48, 0xe0, 0x96, + 0x1b, 0x31, 0x45, 0xb9, 0xe6, 0x1b, 0x73, 0x1f, 0xc4, 0x47, + 0x61, 0xa5, 0x14, 0xe1, 0xb5, 0x24, 0x63, 0x2f, 0x43, 0x4a, + 0xc7, 0xb1, 0x64, 0xac, 0x8f, 0x15, 0x70, 0x5d, 0xdd, 0x5a, + 0xd9, 0x11, 0x08, 0xcc, 0xda, 0xcd, 0xfd, 0x5d, 0xd2, 0x9c, + 0x01, 0xaa, 0x4b, 0xd7, 0xd6, 0x9d, 0x61, 0x17, 0x9c, 0xae, + 0x17, 0x15, 0x90, 0x3e, 0x6a, 0x4f, 0x69, 0x85, 0x92, 0xb3, + 0x05, 0xd1, 0x02, 0x2c, 0xeb, 0x91, 0x69, 0x64, 0x2e, 0x08, + 0xf1, 0x8f, 0xd5, 0xbc, 0x8b, 0x98, 0x68, 0x19, 0xf5, 0x51, + 0x4f, 0x25, 0x78, 0x8b, 0x59, 0x1d, 0xf4, 0x18, 0x1a, 0xab, + 0x95, 0x4f, 0x75, 0x7d, 0x22, 0xcd, 0xaf, 0x42 }, + { 0x8e, 0x85, 0x43, 0x7d, 0xbe, 0x9c, 0x7e, 0x15, 0x2b, 0x3c, + 0x8f, 0x71, 0xdc, 0xeb, 0x89, 0x55, 0xab, 0x01, 0x2c, 0x2c, + 0x58, 0x47, 0xa4, 0xd7, 0x28, 0x44, 0xd9, 0x6a, 0x98, 0x2f, + 0xc0, 0xd4, 0xd6, 0xa7, 0xdf, 0x0d, 0xaa, 0x60, 0xaa, 0x6a, + 0xd3, 0x08, 0xfc, 0x21, 0xae, 0x9b, 0x2a, 0xa8, 0xfc, 0x9a, + 0xc3, 0xb9, 0x48, 0xd6, 0x5c, 0xbb, 0xe5, 0x65, 0x43, 0x1c, + 0x8b, 0x65, 0xc9, 0xa1, 0xe3, 0x14, 0x71, 0xee, 0x6b, 0xe6, + 0xc8, 0xca, 0x73, 0x24, 0x83, 0xe3, 0x51, 0xb7, 0xda, 0x61, + 0xa0, 0xac, 0xfc, 0xa2, 0x2b, 0x29, 0xb2, 0xb7, 0x51, 0x0e, + 0x18, 0x60, 0x84, 0x57, 0xaa, 0x6e, 0x66, 0x55, 0xfc, 0x9c, + 0xbb, 0x60, 0x54, 0xa6, 0x06, 0xfe, 0x43, 0x7c, 0x40, 0x1e, + 0x36, 0x0c, 0xff, 0x54, 0x80, 0x0c, 0x09, 0x38, 0x8a, 0x30, + 0xd0, 0x96, 0xe5, 0xc0, 0xe7, 0xf2, 0xa3, 0x2b }, +}; + +/* + * Loop for modular exponentiate the value in F_p*. + * + * Using 8-bit stripe table. + * + * @param [in] key SAKKE key. + * @param [in] b MP integer that is the base to exponentiate. + * @param [in] e MP integer that is the exponent. + * @param [out] c Result of exponentiation. + * @param [in] mp Multiplier to use when converting from Montgomery form. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_modexp_loop(SakkeKey* key, const mp_int* b, mp_int* e, + mp_proj* c, mp_digit mp) +{ + int err = 0; + mp_int* t1 = &key->tmp.m1; + mp_int* t2 = &key->tmp.m2; + mp_int* by = key->tmp.p1->z; + mp_int* prime = &key->params.prime; + unsigned char eb[128]; + int i; + int y; + + /* Use table for values of b exponentiated. */ + (void)b; + + (void)mp_to_unsigned_bin_len(e, eb, sizeof(eb)); + + /* Set the working value to the base in PF_p[q] */ + err = mp_montgomery_calc_normalization(c->x, prime); + if (err == 0) { + y = (eb[112] >> 7) & 1; + y |= ((eb[ 96] >> 7) & 1) << 1; + y |= ((eb[ 80] >> 7) & 1) << 2; + y |= ((eb[ 64] >> 7) & 1) << 3; + y |= ((eb[ 48] >> 7) & 1) << 4; + y |= ((eb[ 32] >> 7) & 1) << 5; + y |= ((eb[ 16] >> 7) & 1) << 6; + y |= ((eb[ 0] >> 7) & 1) << 7; + + (void)mp_read_unsigned_bin(c->y, sakke_1024_g_table[y], 128); + } + for (i = 128 - 2; (err == 0) && (i >= 0); i--) { + y = (eb[127 - i / 8 ] >> (i & 0x7)) & 1; + y |= ((eb[127 - (i / 8 + 16)] >> (i & 0x7)) & 1) << 1; + y |= ((eb[127 - (i / 8 + 32)] >> (i & 0x7)) & 1) << 2; + y |= ((eb[127 - (i / 8 + 48)] >> (i & 0x7)) & 1) << 3; + y |= ((eb[127 - (i / 8 + 64)] >> (i & 0x7)) & 1) << 4; + y |= ((eb[127 - (i / 8 + 80)] >> (i & 0x7)) & 1) << 5; + y |= ((eb[127 - (i / 8 + 96)] >> (i & 0x7)) & 1) << 6; + y |= ((eb[127 - (i / 8 + 112)] >> (i & 0x7)) & 1) << 7; + + err = sakke_proj_sqr(c, prime, mp, c, t1, t2); + if (err == 0) { + (void)mp_read_unsigned_bin(by, sakke_1024_g_table[y], 128); + err = sakke_proj_mul_qx1(c, by, prime, mp, c, t1, t2); + } + } + + return err; +} +#endif /* WOLFSSL_SAKKE_SMALL */ + +/* + * Modular exponentiate the value in F_p*. + * + * @param [in] key SAKKE key. + * @param [in] b MP integer that is the base to exponentiate. + * @param [in] e MP integer that is the exponent. + * @param [out] r Result of exponentiation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_modexp(SakkeKey* key, mp_int* b, mp_int* e, mp_int* r) +{ + int err; + mp_digit mp; + mp_int* prime = &key->params.prime; + mp_proj* c = key->tmp.p1; + + (void)b; + + err = mp_montgomery_setup(prime, &mp); + if (err == 0) { + err = sakke_modexp_loop(key, b, e, c, mp); + } + + if (err == 0) { + err = mp_montgomery_reduce(c->x, prime, mp); + } + if (err == 0) { + err = mp_montgomery_reduce(c->y, prime, mp); + } + /* Convert value back from PF_p[q] to F_p* */ + if (err == 0) { + err = mp_invmod(c->x, prime, c->x); + } + if (err == 0) { + err = mp_mulmod(c->x, c->y, prime, r); + } + + return err; +} +#endif /* WOLFSSL_HAVE_SP_ECC */ + +/* + * Calculate the hash values h and v. + * + * RFC 6508, section 5.1, Steps 4.a and 4.b. + * + * @param [in] key SAKKE key. + * @param [in] hashType Hash algorithm to use. + * @param [in] hashSz Size of output of hash algorithm in bytes. + * @param [in] a Hash of data and extra. + * @param [in] h Rolling hash result. + * @param [out] v Output bytes of hashing. + * @return 0 on success. + * @return BAD_FUNC_ARG when hashType is not supported. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_calc_h_v(SakkeKey* key, enum wc_HashType hashType, + word32 hashSz, const byte* a, byte* h, byte* v) +{ + int err; + + /* Step 4.a: h_i = hashfn(h_(i - 1)) */ + err = wc_HashUpdate(&key->hash, hashType, h, hashSz); + if (err == 0) { + err = wc_HashFinal(&key->hash, hashType, h); + } + + /* Step 4.b: v_i = hashfn(h_i | A) */ + if (err == 0) { + err = wc_HashUpdate(&key->hash, hashType, h, hashSz); + } + if (err == 0) { + err = wc_HashUpdate(&key->hash, hashType, a, hashSz); + } + if (err == 0) { + err = wc_HashFinal(&key->hash, hashType, v); + } + + return err; +} + +/* + * XOR hash output v into output, with length n, starting at index i. + * + * @param [in] v Output bytes of hashing. + * @param [in] hashSz Size of output of hash algorithm in bytes. + * @param [in,out] out Data to be XORed. + * @param [in] idx Index to start XORing into. + * @param [in] n Length of data to XOR (mask) in bytes. + */ +static void sakke_xor_in_v(const byte* v, word32 hashSz, byte* out, int idx, + int n) +{ + int o; + word32 i; + + if (idx == 0) { + i = hashSz - (n % hashSz); + if (i == hashSz) { + i = 0; + } + } + else { + i = 0; + } + o = i; + for (; i < hashSz; i++) { + out[idx + i - o] ^= v[i]; + } +} + +/* + * Hash octet strings to an integer range. + * + * RFC 6508, section 5.1, Steps 1 to 4. + * + * @param [in] key SAKKE key. + * @param [in] hashType Hash algorithm to use. + * @param [in] data First block of data. + * @param [in] sz Size of first block of data in bytes. + * @param [in] extra Extra block of data. + * @param [in] extraSz Size of extra block of data in bytes. + * @param [out] a Output bytes of hashing. + * @return 0 on success. + * @return BAD_FUNC_ARG when hashType is not supported. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_calc_a(SakkeKey* key, enum wc_HashType hashType, + const byte* data, word32 sz, const byte* extra, word32 extraSz, byte* a) +{ + int err; + + /* Step 1: A = hashfn( s ), where s = data | extra */ + err = wc_HashInit_ex(&key->hash, hashType, key->heap, INVALID_DEVID); + if (err == 0) { + err = wc_HashUpdate(&key->hash, hashType, data, sz); + } + if ((err == 0) && (extra != NULL)) { + err = wc_HashUpdate(&key->hash, hashType, extra, extraSz); + } + if (err == 0) { + err = wc_HashFinal(&key->hash, hashType, a); + } + + return err; +} + +/* + * Hash octet strings to an integer range. + * + * RFC 6508, section 5.1, Steps 1 to 4. + * + * @param [in] key SAKKE key. + * @param [in] hashType Hash algorithm to use. + * @param [in] a Hash of original data. + * @param [out] out Output bytes of hashing. + * @param [in] n Size of output buffer in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when hashType is not supported. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_hash_to_range(SakkeKey* key, enum wc_HashType hashType, + const byte* a, byte* out, word32 n) +{ + int err = 0; + byte h[WC_MAX_DIGEST_SIZE]; + byte v[WC_MAX_DIGEST_SIZE]; + word32 hashSz = 1; + word32 i; + + /* Step 1: A = hashfn( s ), where s = data | extra + * See sakke_calc_a (need function parameters to be 7 or less) + */ + + /* Step 2: h_0 = 00...00, a string of null bits of length hashlen bits */ + err = wc_HashGetDigestSize(hashType); + if (err > 0) { + hashSz = (word32)err; + XMEMSET(h, 0, hashSz); + err = 0; /* reset err value after getting digest size */ + } + else if (err == 0) { + /* invalid hash digest size */ + err = BAD_FUNC_ARG; + } + + /* Step 3: l = Ceiling(lg(n)/hashlen) */ + /* Step 4: For each i in 1 to l, do */ + for (i = 0; (err == 0) && (i < n); i += hashSz) { + /* Steps 4.a and 4.b */ + err = sakke_calc_h_v(key, hashType, hashSz, a, h, v); + + /* XOR in the result into output buffer. */ + if (err == 0) { + sakke_xor_in_v(v, hashSz, out, i, n); + } + } + + return err; +} + +/* + * Hash octet strings to an integer range - RFC 6508 section 5.1. + * Steps 1 to 6. + * + * @param [in] key SAKKE key. + * @param [in] hashType Hash algorithm to use. + * @param [in] a Hash of original data. + * @param [in] q MP integer representing modulus. + * @param [in] n Size of output in bytes. + * @param [out] r MP integer representing modulo reduced hashes. + * @return 0 on success. + * @return BAD_FUNC_ARG when hashType is not supported. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_hash_to_range_int(SakkeKey* key, enum wc_HashType hashType, + const byte* a, mp_int* q, word32 n, mp_int* r) +{ + int err; + byte* rb = key->data; + + /* Make all zeros so that hash output can be XORed in. */ + XMEMSET(rb, 0, n); + + /* Steps 1-4 */ + err = sakke_hash_to_range(key, hashType, a, rb, n); + if (err == 0) { + /* Steps 5 v' = v_1 | ... | v_l */ + err = mp_read_unsigned_bin(r, rb, n); + } + if (err == 0) { + /* Steps 6 v = v' mod n */ + err = mp_mod(r, q, r); + } + + return err; +} + +/** + * Set the identity to perform operations with. + * + * @param [in] key SAKKE key. + * @param [in] id Identity. + * @param [in] idSz Size of identity in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or id is NULL or idSz > SAKKE_ID_MAX_SIZE. + */ +int wc_SetSakkeIdentity(SakkeKey* key, const byte* id, word16 idSz) +{ + int err = 0; + + if ((key == NULL) || (id == NULL) || (idSz > SAKKE_ID_MAX_SIZE)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + XMEMCPY(key->id, id, idSz); + key->idSz = idSz; + } + + return err; +} + +/** + * Compute the elliptic curve point I for identity. Partial for point R. + * + * RFC 6508, Section 6.2.1, Step 3.\n + * RFC 6508, Section 6.2.2, Step 5.\n + * I = [b]P + Z_S + * + * @param [in] key SAKKE key. + * @param [in] id Identity. + * @param [in] idSz Size of identity in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or id is NULL or idSz > SAKKE_ID_MAX_SIZE. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int wc_MakeSakkePointI(SakkeKey* key, const byte* id, word16 idSz) +{ + int err = 0; + + if ((key == NULL) || (id == NULL) || (idSz > SAKKE_ID_MAX_SIZE)) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + /* I = [b]P + Z_S */ + err = sakke_compute_point_i(key, id, idSz, key->i.i); + } + if (err == 0) { + XMEMCPY(key->i.id, id, idSz); + key->i.idSz = idSz; + } + + return err; +} + +/** + * Get the elliptic curve point I - a partial calculation for point R. + * + * RFC 6508, Section 6.2.1, Step 3.\n + * RFC 6508, Section 6.2.2, Step 5.\n + * I = [b]P + Z_S + * + * @param [in] key SAKKE key. + * @param [out] data Encoding of point I. + * @param [in,out] sz On in, the size of data in bytes. + * On out, the size of the encoding in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or sz is NULL. + * @return LENGTH_ONLY_E when data is NULL. Number of bytes required returned + * in sz. + * @return BUFFER_E when sz is too small to hold encoding. + */ +int wc_GetSakkePointI(SakkeKey* key, byte* data, word32* sz) +{ + int err = 0; + + if ((key == NULL) || (sz == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (data == NULL)) { + *sz = key->ecc.dp->size * 2; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*sz < (word32)key->ecc.dp->size * 2)) { + err = BUFFER_E; + } + + if (err == 0) { + /* Write out the x ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(key->i.i->x, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Write data the y ordinate into key size bytes. */ + err = mp_to_unsigned_bin_len(key->i.i->y, data, key->ecc.dp->size); + } + if (err == 0) { + *sz = key->ecc.dp->size * 2; + } + + return err; +} + +/** + * Set the elliptic curve point I - a partial calucation for point R - and the + * identity that it belongs to. + * + * RFC 6508, Section 6.2.1, Step 3.\n + * RFC 6508, Section 6.2.2, Step 5.\n + * I = [b]P + Z_S + * + * @param [in] key SAKKE key. + * @param [out] data Encoding of point I. + * @param [in,out] sz On in, the size of data in bytes. + * On out, the size of the encoding in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, id or data is NULL. + * @return BUFFER_E when idSz is too big to store or sz is not the required + * size. + */ +int wc_SetSakkePointI(SakkeKey* key, const byte* id, word16 idSz, + const byte* data, word32 sz) +{ + int err = 0; + + if ((key == NULL) || (id == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && ((idSz > SAKKE_ID_MAX_SIZE) || + (sz != (word32)key->ecc.dp->size * 2))) { + err = BUFFER_E; + } + + if (err == 0) { + /* Read the x value from key size bytes. */ + err = mp_read_unsigned_bin(key->i.i->x, data, key->ecc.dp->size); + } + if (err == 0) { + data += key->ecc.dp->size; + /* Read the y value from key size bytes. */ + err = mp_read_unsigned_bin(key->i.i->y, data, key->ecc.dp->size); + } + if (err == 0) { + err = mp_set(key->i.i->z, 1); + } + if (err == 0) { + XMEMCPY(key->i.id, id, idSz); + key->i.idSz = idSz; + } + + return err; +} + +/** + * Generate the pre-computation table for point I. + * + * A reference to the table is stored if successfully generated. + * + * @param [in] key SAKKE key. + * @param [in,out] table Pre-computation table. + * NULL to indicate that only length required. + * @param [in,out] len On in, the size of table buffer in bytes. + * On out, the size of table data in bytes. + * @return BAD_FUNC_ARG then key or len is NULL. + * @return LENGTH_ONLY_E when only the length is returned. + * @return BUFFER_E when len is too small. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wc_GenerateSakkePointITable(SakkeKey* key, byte* table, word32* len) +{ + int err = 0; + + if ((key == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_HAVE_SP_ECC + if (err == 0) { + err = sp_ecc_gen_table_1024(key->i.i, table, len, key->heap); + } + if (err == 0) { + key->i.table = table; + key->i.tableLen = *len; + } +#else + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + *len = 0; + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + key->i.table = table; + key->i.tableLen = *len; + } + (void)table; +#endif + + return err; +} + +/** + * Sets the pre-computation table for point I. + * Speeds up making and deriving the encapsulated SSV. + * + * @param [in] key SAKKE key. + * @param [in] table Pre-computation table for Point I. + * @param [in] len Length of pre-computation table in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or table is NULL. + */ +int wc_SetSakkePointITable(SakkeKey* key, byte* table, word32 len) +{ + int err = 0; +#ifdef WOLFSSL_HAVE_SP_ECC + word32 sz = 0; +#endif + + if ((key == NULL) || (table == NULL)) { + err = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_HAVE_SP_ECC + if (err == 0) { + err = sp_ecc_gen_table_1024(key->i.i, NULL, &sz, NULL); + if (err == LENGTH_ONLY_E) { + err = 0; + } + } + if ((err == 0) && (len != sz)) { + err = BUFFER_E; + } +#else + if ((err == 0) && (len != 0)) { + err = BUFFER_E; + } +#endif + + if (err == 0) { + key->i.table = table; + key->i.tableLen = len; + } + + return err; +} + +/** + * Clears the pre-computation table for point I. + * + * Must be called once the table has been disposed of. + * + * @param [in] key SAKKE key. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + */ +int wc_ClearSakkePointITable(SakkeKey* key) +{ + int err = 0; + + if (key == NULL) { + err = BAD_FUNC_ARG; + } + + if (err == 0) { + key->i.table = NULL; + key->i.tableLen = 0; + } + + return err; +} + +/* + * Compute the elliptic curve point R for device B. + * + * RFC 6508, Section 6.2.1, Step 3.\n + * RFC 6508, Section 6.2.2, Step 5.\n + * R = [r]([b]P + Z_S) + * + * @param [in] key SAKKE key. + * @param [in] id Identifier to of device B. + * @param [in] idSz Size of identifier in bytes. + * @param [in] z ECC point - KMS Public Key Z_S. + * @param [in] n Number of bytes in r. + * @param [in] out Result R encoded to bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sakke_compute_point_r(SakkeKey* key, const byte* id, word16 idSz, + const mp_int* r, word32 n, byte* out) +{ + int err = 0; + ecc_point* i = key->i.i; + ecc_point* rp = key->tmp.p2; + word32 sz; + + if ((key->i.idSz == 0) || (key->i.idSz != idSz) || + (XMEMCMP(id, key->i.id, idSz) != 0)) { + /* I = [b]P + Z_S */ + err = sakke_compute_point_i(key, id, idSz, i); + if ((err == 0) && (idSz <= SAKKE_ID_MAX_SIZE)) { + XMEMCPY(key->i.id, id, idSz); + key->i.idSz = idSz; + } + key->i.table = NULL; + key->i.tableLen = 0; + } + /* [r]([b]P + Z_S) */ + if (err == 0) { + err = sakke_mulmod_point(key, r, i, key->i.table, rp, 1); + } + /* Export to canonical form */ + if (err == 0) { + sz = n * 2 + 1; + err = wc_ecc_export_point_der(wc_ecc_get_curve_idx(key->ecc.dp->id), rp, + out, &sz); + } + + return err; +} + +/** + * Makes the Shared Secret Value (SSV) encapsulated and returns the + * authentication data. + * + * RFC 6508, Section 6.2.1. + * + * SSV is overwritten with encapsulated SSV. + * + * Call wc_SetSakkeIdentity() to set the identity to use with operation. + * + * @param [in] key SAKKE key. + * @param [in,out] ssv On in, Shared Secret Value (SSV) data. + * On out, encrypted Shared Secret Value (SSV) data. + * @param [in] ssvSz Size of SSV in bytes. + * @param [in] hashType Hash algorithm to use. + * @param [out] auth Authentication data. + * @param [out] authSz Size of authentication data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, ssv or encSz is NULL, ssvSz is to big or + * encSz is too small. + * @return BAD_STATE_E when identity not set. + * @return LENGTH_ONLY_E when auth is NULL. authSz contains required size of + * auth in bytes. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int wc_MakeSakkeEncapsulatedSSV(SakkeKey* key, enum wc_HashType hashType, + byte* ssv, word16 ssvSz, byte* auth, word16* authSz) +{ + int err = 0; + mp_int* r = NULL; + word16 n = 0; + word16 outSz = 0; + byte a[WC_MAX_DIGEST_SIZE]; + + if ((key == NULL) || (ssv == NULL) || (authSz == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (key->idSz == 0)) { + err = BAD_STATE_E; + } + + /* Load parameters */ + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8); + + /* Uncompressed point */ + outSz = 1 + 2 * n; + + if ((auth != NULL) && (*authSz < outSz)) { + err = BAD_FUNC_ARG; + } + } + if (err == 0) { + *authSz = outSz; + + if (auth == NULL) { + err = LENGTH_ONLY_E; + } + } + + if (err == 0) { + err = sakke_load_base_point(key); + } + if (err == 0) { + err = sakke_load_pairing_base(key); + } + + /* Step 1: Generate a random SSV 0..(2^n)-1 + * Already generated - see wc_MakeSakkeEncapsulated() + */ + /* Step 2: Compute r = HashToIntegerRange( SSV | b, q, Hash ) */ + if (err == 0) { + err = sakke_calc_a(key, hashType, ssv, ssvSz, key->id, key->idSz, a); + } + if (err == 0) { + r = key->tmp.p3->z; + err = sakke_hash_to_range_int(key, hashType, a, &key->params.q, n, r); + } + /* Step 3: Compute R_(b,S) = [r]([b]P + Z_S) in E(F_p) */ + if (err == 0) { + err = sakke_compute_point_r(key, key->id, key->idSz, r, n, auth); + } + + /* Step 4.a: Compute g^r */ + if (err == 0) { + err = sakke_modexp(key, &key->params.g, r, r); + } + + /* Step 4.b: Compute H := SSV XOR HashToIntegerRange( g^r, 2^n, Hash ) */ + if (err == 0) { + err = mp_to_unsigned_bin_len(r, key->data, n); + } + /* ssv ^= HashToIntegerRange( g^r, 2^n, Hash ) */ + if (err == 0) { + err = sakke_calc_a(key, hashType, key->data, n, NULL, 0, a); + } + if (err == 0) { + err = sakke_hash_to_range(key, hashType, a, ssv, ssvSz); + } + + /* Step 5: Form the Encapsulated Data ( R_(b,S), H ) + * R_(b,S) encoded in sakke_compute_point_r, H is a pointer into enc. + */ + + /* Step 6: Output SSV - already encoded in buffer */ + + return err; +} + +/** + * Generate a random Shared Secret Value (SSV). + * + * RFC 6508, Section 6.2.1, Step 1. + * + * @param [in] key SAKKE key. + * @param [in] rng Random number generator. + * @param [out] ssv Shared Secret Value (SSV) data. + * @param [out] ssvSz Size of SSV in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, rng or ssvSz is NULL or ssvSz is to small. + * @return LENGTH_ONLY_E when ssv is NULL. ssvSz contains the required size of + * in bytes. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int wc_GenerateSakkeSSV(SakkeKey* key, WC_RNG* rng, byte* ssv, word16* ssvSz) +{ + int err = 0; + word16 n = 0; + + if ((key == NULL) || (rng == NULL) || (ssvSz == NULL)) { + err = BAD_FUNC_ARG; + } + + /* Load parameters */ + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8); + + if ((ssv != NULL) && (*ssvSz > n)) { + err = BAD_FUNC_ARG; + } + } + if (err == 0) { + /* Return length only if an ouput buffer is NULL. */ + if (ssv == NULL) { + *ssvSz = (word16) (n / 8); + err = LENGTH_ONLY_E; + } + else { + n = *ssvSz; + } + } + + /* Step 1: Select a random ephemeral integer value. Range 0..(2^n - 1) */ + if (err == 0) { + err = wc_RNG_GenerateBlock(rng, ssv, n); + } + + return err; +} + +/** + * Derive the Shared Secret Value from the encapsulated data using the set + * RSK + * + * RFC 6508, Section 6.2.2. + * + * Encapsulated SSV is overwritten with SSV. + * + * Call wc_SetSakkeIdentity() to set the identity to use with operation. + * + * Call wc_SetSakkeRSK() to set the Receiver Secret Key (RSK) to use with + * operation. + * + * @param [in] key SAKKE key. + * @param [in] hashType Hash algorithm to use. + * @param [in,out] ssv On in, encrypted Secret Shared Value (SSV) data. + * On out, Secret Shared Value (SSV) data. + * @param [in] ssvSz Size of SSV in bytes. + * @param [in] auth Authentication data. + * @param [in] authSz Size of authentication data in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, ssv or auth is NULL. + * @return BAD_STATE_E when RSK or identity not set. + * @return SAKKE_VERIFY_FAIL_E when calculated R doesn't match the encapsulated + * data's R. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, byte* ssv, + word16 ssvSz, const byte* auth, word16 authSz) +{ + int err = 0; + word16 n = 0; + ecc_point* r = NULL; + mp_int* w = NULL; + mp_int* ri = NULL; + byte* wb = NULL; + byte* test = NULL; + byte a[WC_MAX_DIGEST_SIZE] = {0}; + + if ((key == NULL) || (ssv == NULL) || (auth == NULL)) { + err = BAD_FUNC_ARG; + } + if ((err == 0) && (!key->rsk.set || (key->idSz == 0))) { + err = BAD_STATE_E; + } + + /* Load parameters */ + if (err == 0) { + err = sakke_load_params(key); + } + if (err == 0) { + n = (word16)((mp_count_bits(&key->params.prime) + 7) / 8); + + if (authSz != 2 * n + 1) { + err = BAD_FUNC_ARG; + } + } + if (err == 0) { + err = sakke_load_base_point(key); + } + + /* Step 1: Parse the Encapsulated Data ( R_(b,S), H ) + * H = auth, so already extracted. */ + if (err == 0) { + r = key->tmp.p2; + + err = wc_ecc_import_point_der(auth, n * 2 + 1, + wc_ecc_get_curve_idx(key->ecc.dp->id), r); + } + + /* Step 2: w = < R_(b,S), K_(b,S) > = < K_(b,S), R_(b,S) > = < rsk , r > */ + if (err == 0) { + w = &key->tmp.m1; + + err = sakke_pairing(key, key->rsk.rsk, r, w, key->rsk.table, + key->rsk.tableLen); + } + + /* Step 3: Compute SSV = H XOR HashToIntegerRange( w, 2^n, Hash ) */ + if (err == 0) { + wb = key->data; + err = mp_to_unsigned_bin_len(w, wb, n); + } + /* HashToIntegerRange( w, 2^n, Hash ) */ + if (err == 0) { + err = sakke_calc_a(key, hashType, wb, n, NULL, 0, a); + } + if (err == 0) { + err = sakke_hash_to_range(key, hashType, a, ssv, ssvSz); + } + + /* Step 4: r = HashToIntegerRange( SSV | b, q, Hash ) */ + if (err == 0) { + err = sakke_calc_a(key, hashType, ssv, ssvSz, key->id, key->idSz, a); + } + if (err == 0) { + ri = &key->tmp.m1; + err = sakke_hash_to_range_int(key, hashType, a, &key->params.q, n, ri); + } + + /* Step 5: Compute TEST = [r]([b]P + Z_S) == R_(b,S) */ + if (err == 0) { + test = key->data; + + err = sakke_compute_point_r(key, key->id, key->idSz, ri, n, test); + } + if ((err == 0) && (XMEMCMP(auth, test, 2 * n + 1) != 0)) { + err = SAKKE_VERIFY_FAIL_E; + } + + return err; +} +#endif /* WOLFCRYPT_SAKKE_CLIENT */ + +#endif /* WOLFCRYPT_HAVE_SAKKE */ + diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 63f4ed402..4b654217c 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1,6 +1,6 @@ /* sha.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -284,7 +284,8 @@ return ret; } -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM) /* wolfcrypt/src/port/caam/caam_sha.c */ #elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ @@ -329,6 +330,7 @@ /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */ #elif defined(WOLFSSL_IMXRT_DCP) + #include /* implemented in wolfcrypt/src/port/nxp/dcp_port.c */ #elif defined(WOLFSSL_SILABS_SE_ACCEL) @@ -494,6 +496,7 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) sha->heap = heap; #ifdef WOLF_CRYPTO_CB sha->devId = devId; + sha->devCtx = NULL; #endif #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ @@ -773,6 +776,21 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) return ret; } +#if defined(OPENSSL_EXTRA) +/* Apply SHA1 transformation to the data */ +/* @param sha a pointer to wc_Sha structure */ +/* @param data data to be applied SHA1 transformation */ +/* @return 0 on successful, otherwise non-zero on failure */ +int wc_ShaTransform(wc_Sha* sha, const unsigned char* data) +{ + /* sanity check */ + if (sha == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + return (Transform(sha, data)); +} +#endif + #endif /* USE_SHA_SOFTWARE_IMPL */ @@ -808,7 +826,8 @@ void wc_ShaFree(wc_Sha* sha) #endif /* !WOLFSSL_TI_HASH */ #endif /* HAVE_FIPS */ -#ifndef WOLFSSL_TI_HASH +#if !defined(WOLFSSL_TI_HASH) && !defined(WOLFSSL_IMXRT_DCP) + #if !defined(WOLFSSL_RENESAS_TSIP_CRYPT) || \ defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) int wc_ShaGetHash(wc_Sha* sha, byte* hash) @@ -873,7 +892,7 @@ int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) return ret; } #endif /* defined(WOLFSSL_RENESAS_TSIP_CRYPT) ... */ -#endif /* !WOLFSSL_TI_HASH */ +#endif /* !WOLFSSL_TI_HASH && !WOLFSSL_IMXRT_DCP */ #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 50b8cf60f..4bee0ccc3 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -1,6 +1,6 @@ /* sha256.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -130,8 +130,6 @@ where 0 <= L < 2^64. #elif defined(WOLFSSL_CRYPTOCELL) /* wc_port.c includes wolfcrypt/src/port/arm/cryptoCellHash.c */ -#elif defined(WOLFSSL_IMXRT_DCP) - #elif defined(WOLFSSL_PSOC6_CRYPTO) @@ -169,6 +167,9 @@ where 0 <= L < 2^64. #ifndef NO_AVX2_SUPPORT #define HAVE_INTEL_AVX2 #endif +#else + #undef HAVE_INTEL_AVX1 + #undef HAVE_INTEL_AVX2 #endif /* USE_INTEL_SPEEDUP */ #if defined(HAVE_INTEL_AVX2) @@ -177,7 +178,8 @@ where 0 <= L < 2^64. #if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \ - (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \ + (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH) || \ + defined(WOLFSSL_QNX_CAAM)) && \ !defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH) && \ (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)) && \ (!defined(WOLFSSL_RENESAS_TSIP_CRYPT) || defined(NO_WOLFSSL_RENESAS_TSIP_HASH)) && \ @@ -397,6 +399,7 @@ static int InitSha256(wc_Sha256* sha256) sha256->heap = heap; #ifdef WOLF_CRYPTO_CB sha256->devId = devId; + sha256->devCtx = NULL; #endif #ifdef WOLFSSL_SMALL_STACK_CACHE sha256->W = NULL; @@ -583,7 +586,8 @@ static int InitSha256(wc_Sha256* sha256) return ret; } -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM) /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ #elif defined(WOLFSSL_AFALG_HASH) @@ -841,7 +845,7 @@ static int InitSha256(wc_Sha256* sha256) S[i] = sha256->digest[i]; for (i = 0; i < 16; i++) - W[i] = *((word32*)&data[i*sizeof(word32)]); + W[i] = *((const word32*)&data[i*sizeof(word32)]); for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++) W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; @@ -1295,6 +1299,19 @@ static int InitSha256(wc_Sha256* sha256) return InitSha256(sha256); /* reset state */ } + #if defined(OPENSSL_EXTRA) +/* Apply SHA256 transformation to the data */ +/* @param sha a pointer to wc_Sha256 structure */ +/* @param data data to be applied SHA256 transformation */ +/* @return 0 on successful, otherwise non-zero on failure */ + int wc_Sha256Transform(wc_Sha256* sha, const unsigned char* data) + { + if (sha == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + return (Transform_Sha256(sha, data)); + } + #endif #endif /* XTRANSFORM */ #ifdef WOLFSSL_SHA224 @@ -1353,7 +1370,8 @@ static int InitSha256(wc_Sha256* sha256) return ret; } -#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM) /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ #elif defined(WOLFSSL_AFALG_HASH) diff --git a/wolfcrypt/src/sha256_asm.S b/wolfcrypt/src/sha256_asm.S index bb2e6bb8c..8d1e469e1 100644 --- a/wolfcrypt/src/sha256_asm.S +++ b/wolfcrypt/src/sha256_asm.S @@ -1,6 +1,6 @@ /* sha256_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 8cd9c9d58..7382ba55b 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -1,6 +1,6 @@ /* sha3.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -545,16 +545,32 @@ static void BlockSha3(word64 *s) */ static word64 Load64BitBigEndian(const byte* a) { -#ifdef BIG_ENDIAN_ORDER +#if defined(BIG_ENDIAN_ORDER) || (WOLFSSL_GENERAL_ALIGNMENT == 1) word64 n = 0; int i; for (i = 0; i < 8; i++) n |= (word64)a[i] << (8 * i); + return n; +#elif ((WOLFSSL_GENERAL_ALIGNMENT > 0) && (WOLFSSL_GENERAL_ALIGNMENT == 4)) + word64 n; + + n = *(word32*) a; + n |= ((word64)*(word32*)(a + 4)) << 32; + + return n; +#elif ((WOLFSSL_GENERAL_ALIGNMENT > 0) && (WOLFSSL_GENERAL_ALIGNMENT == 2)) + word64 n; + + n = *(word16*) a; + n |= ((word64)*(word16*)(a + 2)) << 16; + n |= ((word64)*(word16*)(a + 4)) << 32; + n |= ((word64)*(word16*)(a + 6)) << 48; + return n; #else - return *(word64*)a; + return *(const word64*)a; #endif } @@ -636,30 +652,38 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) * len Number of bytes in output. * returns 0 on success. */ -static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, byte l) +static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l) { + word32 rate = p * 8; + word32 j; byte i; - byte *state = (byte *)sha3->s; - sha3->t[p * 8 - 1] = 0x00; + sha3->t[rate - 1] = 0x00; #ifdef WOLFSSL_HASH_FLAGS - if (p == WC_SHA3_256_COUNT && sha3->flags & WC_HASH_SHA3_KECCAK256) { + if (p == WC_SHA3_256_COUNT && sha3->flags & WC_HASH_SHA3_KECCAK256) padChar = 0x01; - } #endif - sha3->t[ sha3->i] = padChar; - sha3->t[p * 8 - 1] |= 0x80; - for (i=sha3->i + 1; i < p * 8 - 1; i++) + sha3->t[sha3->i ] = padChar; + sha3->t[rate - 1] |= 0x80; + for (i=sha3->i + 1; i < rate - 1; i++) sha3->t[i] = 0; for (i = 0; i < p; i++) sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); - BlockSha3(sha3->s); -#if defined(BIG_ENDIAN_ORDER) - ByteReverseWords64(sha3->s, sha3->s, ((l+7)/8)*8); -#endif - for (i = 0; i < l; i++) - hash[i] = state[i]; - + for (j = 0; l - j >= rate; j += rate) { + BlockSha3(sha3->s); + #if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64((word64*)(hash + j), sha3->s, rate); + #else + XMEMCPY(hash + j, sha3->s, rate); + #endif + } + if (j != l) { + BlockSha3(sha3->s); + #if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64(sha3->s, sha3->s, rate); + #endif + XMEMCPY(hash + j, sha3->s, l - j); + } return 0; } @@ -763,7 +787,7 @@ static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len) } #endif /* WOLFSSL_ASYNC_CRYPT */ - ret = Sha3Final(sha3, 0x06, hash, p, len); + ret = Sha3Final(sha3, 0x06, hash, p, (word32)len); if (ret != 0) return ret; @@ -1144,7 +1168,7 @@ int wc_Sha3_GetFlags(wc_Sha3* sha3, word32* flags) } #endif -#if defined(WOLFSSL_SHAKE256) +#ifdef WOLFSSL_SHAKE256 /* Initialize the state for a Shake256 hash operation. * * shake wc_Shake object holding state. diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index ef09e5404..48744e661 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -1,6 +1,6 @@ /* sha512.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -185,7 +185,8 @@ } #endif -#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM) /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ #elif defined(WOLFSSL_SILABS_SHA384) @@ -916,7 +917,58 @@ void wc_Sha512Free(wc_Sha512* sha512) wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512); #endif /* WOLFSSL_ASYNC_CRYPT */ } +#if defined(OPENSSL_EXTRA) +/* Apply SHA512 transformation to the data */ +/* @param sha a pointer to wc_Sha512 structure */ +/* @param data data to be applied SHA512 transformation */ +/* @return 0 on successful, otherwise non-zero on failure */ +int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data) +{ + int ret ; + /* back up buffer */ + #if defined(WOLFSSL_SMALL_STACK) + word64* buffer; + buffer = (word64*) XMALLOC(sizeof(word64) * 16, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; + #else + word64 buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64)]; + #endif + + /* sanity check */ + if (sha == NULL || data == NULL) { + #if defined(WOLFSSL_SMALL_STACK) + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BAD_FUNC_ARG; + } +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + Sha512_SetTransform(); +#endif +#if defined(LITTLE_ENDIAN_ORDER) +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) +#endif + { + ByteReverseWords64((word64*)data, (word64*)data, + WC_SHA512_BLOCK_SIZE); + } +#endif + + XMEMCPY(buffer, sha->buffer, WC_SHA512_BLOCK_SIZE); + XMEMCPY(sha->buffer, data, WC_SHA512_BLOCK_SIZE); + + ret = Transform_Sha512(sha); + + XMEMCPY(sha->buffer, buffer, WC_SHA512_BLOCK_SIZE); + #if defined(WOLFSSL_SMALL_STACK) + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; +} +#endif #endif /* WOLFSSL_SHA512 */ /* -------------------------------------------------------------------------- */ @@ -924,7 +976,8 @@ void wc_Sha512Free(wc_Sha512* sha512) /* -------------------------------------------------------------------------- */ #ifdef WOLFSSL_SHA384 -#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \ + !defined(WOLFSSL_QNX_CAAM) /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ #elif defined(WOLFSSL_SILABS_SHA512) diff --git a/wolfcrypt/src/sha512_asm.S b/wolfcrypt/src/sha512_asm.S index d72c24e8d..12fc4bb45 100644 --- a/wolfcrypt/src/sha512_asm.S +++ b/wolfcrypt/src/sha512_asm.S @@ -1,6 +1,6 @@ /* sha512_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index 6e623a130..948d17c33 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -1,6 +1,6 @@ /* signature.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -48,6 +48,13 @@ /* Signature wrapper disabled check */ #ifndef NO_SIG_WRAPPER +#ifdef WOLFSSL_CRYPTOCELL +extern int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig, + RsaKey* key, CRYS_RSA_HASH_OpMode_t mode); +extern int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, CRYS_RSA_HASH_OpMode_t mode); +#endif + #if !defined(NO_RSA) && !defined(NO_ASN) static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte* hash_data, word32 hash_len, word32* hash_enc_len) @@ -178,12 +185,12 @@ int wc_SignatureVerifyHash( #ifndef NO_RSA #ifdef WOLFSSL_CRYPTOCELL if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { - ret = cc310_RsaSSL_Verify(hash_data, hash_len, (byte*)sig, key, - cc310_hashModeRSA(hash_type, 0)); + ret = cc310_RsaSSL_Verify(hash_data, hash_len, (byte*)sig, + (RsaKey*)key, cc310_hashModeRSA(hash_type, 0)); } else { - ret = cc310_RsaSSL_Verify(hash_data, hash_len, (byte*)sig, key, - cc310_hashModeRSA(hash_type, 1)); + ret = cc310_RsaSSL_Verify(hash_data, hash_len, (byte*)sig, + (RsaKey*)key, cc310_hashModeRSA(hash_type, 1)); } #else @@ -400,12 +407,12 @@ int wc_SignatureGenerateHash_ex( /* use expected signature size (incoming sig_len could be larger buffer */ *sig_len = wc_SignatureGetSize(sig_type, key, key_len); if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { - ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, key, - cc310_hashModeRSA(hash_type, 0)); + ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + (RsaKey*)key, cc310_hashModeRSA(hash_type, 0)); } else { - ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, key, - cc310_hashModeRSA(hash_type, 1)); + ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + (RsaKey*)key, cc310_hashModeRSA(hash_type, 1)); } #else /* Create signature using provided RSA key */ diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index c5828082d..c14a231ad 100644 --- a/wolfcrypt/src/sp_arm32.c +++ b/wolfcrypt/src/sp_arm32.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,7 +58,8 @@ */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -100,7 +101,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -134,7 +136,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -173,7 +177,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_2048_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 2048 / 8 - 1; a[j] = 0; @@ -215,66 +222,60 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "sub sp, sp, #32\n\t" "mov r10, #0\n\t" "# A[0] * B[0]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r3, r4, r8, r9\n\t" + "ldr r11, [%[a], #0]\n\t" + "ldr r12, [%[b], #0]\n\t" + "umull r3, r4, r11, r12\n\t" "mov r5, #0\n\t" "str r3, [sp]\n\t" "# A[0] * B[1]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" "# A[1] * B[0]\n\t" "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #4]\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r11, [%[a], #4]\n\t" + "ldr r12, [%[b], #4]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" "# A[0] * B[2]\n\t" "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #8]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[1] * B[1]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[0]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #8]\n\t" "# A[0] * B[3]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" "# A[1] * B[2]\n\t" - "ldr r8, [%[a], #4]\n\t" "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[2] * B[1]\n\t" "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -286,13 +287,25 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #12]\n\t" - "# A[0] * B[4]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r11, [%[a], #8]\n\t" + "ldr r12, [%[b], #8]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" "# A[1] * B[3]\n\t" "ldr r8, [%[a], #4]\n\t" "ldr r9, [%[b], #12]\n\t" @@ -300,30 +313,15 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[2] * B[2]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[1]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[0]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #16]\n\t" "# A[0] * B[5]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" @@ -337,16 +335,14 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[2] * B[3]\n\t" - "ldr r8, [%[a], #8]\n\t" "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[3] * B[2]\n\t" "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -365,20 +361,32 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #20]\n\t" - "# A[0] * B[6]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #24]\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" - "# A[1] * B[5]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #20]\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r11, [%[a], #12]\n\t" + "ldr r12, [%[b], #12]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" "# A[2] * B[4]\n\t" "ldr r8, [%[a], #8]\n\t" "ldr r9, [%[b], #16]\n\t" @@ -386,37 +394,22 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[3] * B[3]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[4] * B[2]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[1]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[0]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #24]\n\t" "# A[0] * B[7]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" @@ -437,16 +430,14 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[3] * B[4]\n\t" - "ldr r8, [%[a], #12]\n\t" "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[4] * B[3]\n\t" "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -472,20 +463,32 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #28]\n\t" - "# A[1] * B[7]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #28]\n\t" + "# A[7] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r10, r10\n\t" - "# A[2] * B[6]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #24]\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r11, [%[a], #16]\n\t" + "ldr r12, [%[b], #16]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" "# A[3] * B[5]\n\t" "ldr r8, [%[a], #12]\n\t" "ldr r9, [%[b], #20]\n\t" @@ -493,30 +496,16 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[4] * B[4]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[5] * B[3]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[6] * B[2]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[7] * B[1]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -524,7 +513,6 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r5, [%[r], #32]\n\t" "# A[2] * B[7]\n\t" "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -537,16 +525,14 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[4] * B[5]\n\t" - "ldr r8, [%[a], #16]\n\t" "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[5] * B[4]\n\t" "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -565,13 +551,25 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [%[r], #36]\n\t" - "# A[3] * B[7]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #28]\n\t" + "# A[7] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r11, [%[a], #20]\n\t" + "ldr r12, [%[b], #20]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" "# A[4] * B[6]\n\t" "ldr r8, [%[a], #16]\n\t" "ldr r9, [%[b], #24]\n\t" @@ -579,23 +577,9 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[5] * B[5]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[6] * B[4]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[7] * B[3]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -603,22 +587,19 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r4, [%[r], #40]\n\t" "# A[4] * B[7]\n\t" "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r10, r10\n\t" "# A[5] * B[6]\n\t" - "ldr r8, [%[a], #20]\n\t" "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[6] * B[5]\n\t" "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -630,71 +611,52 @@ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [%[r], #44]\n\t" + "# A[7] * B[5]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r11, [%[a], #24]\n\t" + "ldr r12, [%[b], #24]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" "# A[5] * B[7]\n\t" "ldr r8, [%[a], #20]\n\t" "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r10, r10\n\t" - "# A[6] * B[6]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[7] * B[5]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [%[r], #48]\n\t" "# A[6] * B[7]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" "# A[7] * B[6]\n\t" "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [%[r], #52]\n\t" "# A[7] * B[7]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adc r3, r3, r7\n\t" "str r5, [%[r], #56]\n\t" "str r3, [%[r], #60]\n\t" - "ldr r3, [sp, #0]\n\t" - "ldr r4, [sp, #4]\n\t" - "ldr r5, [sp, #8]\n\t" - "ldr r6, [sp, #12]\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [sp, #16]\n\t" - "ldr r4, [sp, #20]\n\t" - "ldr r5, [sp, #24]\n\t" - "ldr r6, [sp, #28]\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - "add sp, sp, #32\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "sub %[r], %[r], #32\n\t" : : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); } @@ -707,7 +669,7 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) { __asm__ __volatile__ ( "sub sp, sp, #32\n\t" - "mov r14, #0\n\t" + "mov r12, #0\n\t" "# A[0] * A[0]\n\t" "ldr r10, [%[a], #0]\n\t" "umull r8, r3, r10, r10\n\t" @@ -719,10 +681,10 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [sp, #4]\n\t" "# A[0] * A[2]\n\t" "ldr r10, [%[a], #8]\n\t" @@ -730,16 +692,16 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" + "adc r3, r12, r12\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "# A[1] * A[1]\n\t" "ldr r10, [%[a], #4]\n\t" "umull r8, r9, r10, r10\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "str r4, [sp, #8]\n\t" "# A[0] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" @@ -747,20 +709,20 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" + "adc r4, r12, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "# A[1] * A[2]\n\t" "ldr r10, [%[a], #8]\n\t" "ldr r8, [%[a], #4]\n\t" "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "str r2, [sp, #12]\n\t" "# A[0] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" @@ -768,26 +730,26 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[1] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" "ldr r8, [%[a], #4]\n\t" "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[2] * A[2]\n\t" "ldr r10, [%[a], #8]\n\t" "umull r8, r9, r10, r10\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [sp, #16]\n\t" "# A[0] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" @@ -801,14 +763,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -828,14 +790,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" "umull r8, r9, r10, r10\n\t" @@ -844,7 +806,7 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r2, r2, r5\n\t" "adcs r3, r3, r6\n\t" "adc r4, r4, r7\n\t" @@ -861,21 +823,21 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -895,14 +857,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" "umull r8, r9, r10, r10\n\t" @@ -911,7 +873,7 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r4, r4, r5\n\t" "adcs r2, r2, r6\n\t" "adc r3, r3, r7\n\t" @@ -928,14 +890,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -949,26 +911,26 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[4] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[5] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "umull r8, r9, r10, r10\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [%[r], #40]\n\t" "# A[4] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" @@ -976,20 +938,20 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" + "adc r3, r12, r12\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "# A[5] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "ldr r8, [%[a], #20]\n\t" "umull r8, r9, r10, r8\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "str r4, [%[r], #44]\n\t" "# A[5] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" @@ -997,16 +959,16 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" + "adc r4, r12, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "# A[6] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "umull r8, r9, r10, r10\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "str r2, [%[r], #48]\n\t" "# A[6] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" @@ -1014,10 +976,10 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [%[r], #52]\n\t" "# A[7] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" @@ -1026,26 +988,14 @@ static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) "adc r2, r2, r9\n\t" "str r4, [%[r], #56]\n\t" "str r2, [%[r], #60]\n\t" - "ldr r2, [sp, #0]\n\t" - "ldr r3, [sp, #4]\n\t" - "ldr r4, [sp, #8]\n\t" - "ldr r8, [sp, #12]\n\t" - "str r2, [%[r], #0]\n\t" - "str r3, [%[r], #4]\n\t" - "str r4, [%[r], #8]\n\t" - "str r8, [%[r], #12]\n\t" - "ldr r2, [sp, #16]\n\t" - "ldr r3, [sp, #20]\n\t" - "ldr r4, [sp, #24]\n\t" - "ldr r8, [sp, #28]\n\t" - "str r2, [%[r], #16]\n\t" - "str r3, [%[r], #20]\n\t" - "str r4, [%[r], #24]\n\t" - "str r8, [%[r], #28]\n\t" - "add sp, sp, #32\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "sub %[r], %[r], #32\n\t" : : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12" ); } @@ -1312,7 +1262,9 @@ SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, sp_digit a1[8]; sp_digit b1[8]; sp_digit z2[16]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_8(a1, a, &a[8]); cb = sp_2048_add_8(b1, b, &b[8]); @@ -1699,7 +1651,9 @@ SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, sp_digit a1[16]; sp_digit b1[16]; sp_digit z2[32]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_16(a1, a, &a[16]); cb = sp_2048_add_16(b1, b, &b[16]); @@ -2342,7 +2296,9 @@ SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, sp_digit a1[32]; sp_digit b1[32]; sp_digit z2[64]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_32(a1, a, &a[32]); cb = sp_2048_add_32(b1, b, &b[32]); @@ -2857,7 +2813,7 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -2866,7 +2822,8 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -2875,7 +2832,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -2925,499 +2882,437 @@ static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #28]\n\t" "# A[8] * B\n\t" "ldr r8, [%[a], #32]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #32]\n\t" "# A[9] * B\n\t" "ldr r8, [%[a], #36]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #36]\n\t" "# A[10] * B\n\t" "ldr r8, [%[a], #40]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #40]\n\t" "# A[11] * B\n\t" "ldr r8, [%[a], #44]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #44]\n\t" "# A[12] * B\n\t" "ldr r8, [%[a], #48]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #48]\n\t" "# A[13] * B\n\t" "ldr r8, [%[a], #52]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #52]\n\t" "# A[14] * B\n\t" "ldr r8, [%[a], #56]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #56]\n\t" "# A[15] * B\n\t" "ldr r8, [%[a], #60]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #60]\n\t" "# A[16] * B\n\t" "ldr r8, [%[a], #64]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #64]\n\t" "# A[17] * B\n\t" "ldr r8, [%[a], #68]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #68]\n\t" "# A[18] * B\n\t" "ldr r8, [%[a], #72]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #72]\n\t" "# A[19] * B\n\t" "ldr r8, [%[a], #76]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #76]\n\t" "# A[20] * B\n\t" "ldr r8, [%[a], #80]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[21] * B\n\t" "ldr r8, [%[a], #84]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[22] * B\n\t" "ldr r8, [%[a], #88]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #88]\n\t" "# A[23] * B\n\t" "ldr r8, [%[a], #92]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #92]\n\t" "# A[24] * B\n\t" "ldr r8, [%[a], #96]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #96]\n\t" "# A[25] * B\n\t" "ldr r8, [%[a], #100]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #100]\n\t" "# A[26] * B\n\t" "ldr r8, [%[a], #104]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #104]\n\t" "# A[27] * B\n\t" "ldr r8, [%[a], #108]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #108]\n\t" "# A[28] * B\n\t" "ldr r8, [%[a], #112]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #112]\n\t" "# A[29] * B\n\t" "ldr r8, [%[a], #116]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #116]\n\t" "# A[30] * B\n\t" "ldr r8, [%[a], #120]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #120]\n\t" "# A[31] * B\n\t" "ldr r8, [%[a], #124]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #124]\n\t" "# A[32] * B\n\t" "ldr r8, [%[a], #128]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #128]\n\t" "# A[33] * B\n\t" "ldr r8, [%[a], #132]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #132]\n\t" "# A[34] * B\n\t" "ldr r8, [%[a], #136]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #136]\n\t" "# A[35] * B\n\t" "ldr r8, [%[a], #140]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #140]\n\t" "# A[36] * B\n\t" "ldr r8, [%[a], #144]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #144]\n\t" "# A[37] * B\n\t" "ldr r8, [%[a], #148]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #148]\n\t" "# A[38] * B\n\t" "ldr r8, [%[a], #152]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #152]\n\t" "# A[39] * B\n\t" "ldr r8, [%[a], #156]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #156]\n\t" "# A[40] * B\n\t" "ldr r8, [%[a], #160]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #160]\n\t" "# A[41] * B\n\t" "ldr r8, [%[a], #164]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #164]\n\t" "# A[42] * B\n\t" "ldr r8, [%[a], #168]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #168]\n\t" "# A[43] * B\n\t" "ldr r8, [%[a], #172]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #172]\n\t" "# A[44] * B\n\t" "ldr r8, [%[a], #176]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #176]\n\t" "# A[45] * B\n\t" "ldr r8, [%[a], #180]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #180]\n\t" "# A[46] * B\n\t" "ldr r8, [%[a], #184]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #184]\n\t" "# A[47] * B\n\t" "ldr r8, [%[a], #188]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #188]\n\t" "# A[48] * B\n\t" "ldr r8, [%[a], #192]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #192]\n\t" "# A[49] * B\n\t" "ldr r8, [%[a], #196]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #196]\n\t" "# A[50] * B\n\t" "ldr r8, [%[a], #200]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #200]\n\t" "# A[51] * B\n\t" "ldr r8, [%[a], #204]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #204]\n\t" "# A[52] * B\n\t" "ldr r8, [%[a], #208]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #208]\n\t" "# A[53] * B\n\t" "ldr r8, [%[a], #212]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #212]\n\t" "# A[54] * B\n\t" "ldr r8, [%[a], #216]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #216]\n\t" "# A[55] * B\n\t" "ldr r8, [%[a], #220]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #220]\n\t" "# A[56] * B\n\t" "ldr r8, [%[a], #224]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #224]\n\t" "# A[57] * B\n\t" "ldr r8, [%[a], #228]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #228]\n\t" "# A[58] * B\n\t" "ldr r8, [%[a], #232]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #232]\n\t" "# A[59] * B\n\t" "ldr r8, [%[a], #236]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #236]\n\t" "# A[60] * B\n\t" "ldr r8, [%[a], #240]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #240]\n\t" "# A[61] * B\n\t" "ldr r8, [%[a], #244]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #244]\n\t" "# A[62] * B\n\t" "ldr r8, [%[a], #248]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #248]\n\t" "# A[63] * B\n\t" "ldr r8, [%[a], #252]\n\t" @@ -3666,6 +3561,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -3674,13 +3570,12 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -3688,7 +3583,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -3696,7 +3591,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3705,7 +3600,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3714,7 +3609,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3723,7 +3618,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3732,7 +3627,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #24]\n\t" "adc r5, r5, #0\n\t" "# a[i+7] += m[7] * mu\n\t" - "ldr r7, [%[m], #28]\n\t" + "ldr r7, [%[m], #28]\n\t" "ldr r9, [%[a], #28]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3741,7 +3636,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #28]\n\t" "adc r4, r4, #0\n\t" "# a[i+8] += m[8] * mu\n\t" - "ldr r7, [%[m], #32]\n\t" + "ldr r7, [%[m], #32]\n\t" "ldr r9, [%[a], #32]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3750,7 +3645,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #32]\n\t" "adc r5, r5, #0\n\t" "# a[i+9] += m[9] * mu\n\t" - "ldr r7, [%[m], #36]\n\t" + "ldr r7, [%[m], #36]\n\t" "ldr r9, [%[a], #36]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3759,7 +3654,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #36]\n\t" "adc r4, r4, #0\n\t" "# a[i+10] += m[10] * mu\n\t" - "ldr r7, [%[m], #40]\n\t" + "ldr r7, [%[m], #40]\n\t" "ldr r9, [%[a], #40]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3768,7 +3663,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #40]\n\t" "adc r5, r5, #0\n\t" "# a[i+11] += m[11] * mu\n\t" - "ldr r7, [%[m], #44]\n\t" + "ldr r7, [%[m], #44]\n\t" "ldr r9, [%[a], #44]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3777,7 +3672,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #44]\n\t" "adc r4, r4, #0\n\t" "# a[i+12] += m[12] * mu\n\t" - "ldr r7, [%[m], #48]\n\t" + "ldr r7, [%[m], #48]\n\t" "ldr r9, [%[a], #48]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3786,7 +3681,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #48]\n\t" "adc r5, r5, #0\n\t" "# a[i+13] += m[13] * mu\n\t" - "ldr r7, [%[m], #52]\n\t" + "ldr r7, [%[m], #52]\n\t" "ldr r9, [%[a], #52]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3795,7 +3690,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #52]\n\t" "adc r4, r4, #0\n\t" "# a[i+14] += m[14] * mu\n\t" - "ldr r7, [%[m], #56]\n\t" + "ldr r7, [%[m], #56]\n\t" "ldr r9, [%[a], #56]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3804,7 +3699,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #56]\n\t" "adc r5, r5, #0\n\t" "# a[i+15] += m[15] * mu\n\t" - "ldr r7, [%[m], #60]\n\t" + "ldr r7, [%[m], #60]\n\t" "ldr r9, [%[a], #60]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3813,7 +3708,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #60]\n\t" "adc r4, r4, #0\n\t" "# a[i+16] += m[16] * mu\n\t" - "ldr r7, [%[m], #64]\n\t" + "ldr r7, [%[m], #64]\n\t" "ldr r9, [%[a], #64]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3822,7 +3717,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #64]\n\t" "adc r5, r5, #0\n\t" "# a[i+17] += m[17] * mu\n\t" - "ldr r7, [%[m], #68]\n\t" + "ldr r7, [%[m], #68]\n\t" "ldr r9, [%[a], #68]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3831,7 +3726,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #68]\n\t" "adc r4, r4, #0\n\t" "# a[i+18] += m[18] * mu\n\t" - "ldr r7, [%[m], #72]\n\t" + "ldr r7, [%[m], #72]\n\t" "ldr r9, [%[a], #72]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3840,7 +3735,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #72]\n\t" "adc r5, r5, #0\n\t" "# a[i+19] += m[19] * mu\n\t" - "ldr r7, [%[m], #76]\n\t" + "ldr r7, [%[m], #76]\n\t" "ldr r9, [%[a], #76]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3849,7 +3744,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #76]\n\t" "adc r4, r4, #0\n\t" "# a[i+20] += m[20] * mu\n\t" - "ldr r7, [%[m], #80]\n\t" + "ldr r7, [%[m], #80]\n\t" "ldr r9, [%[a], #80]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3858,7 +3753,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #80]\n\t" "adc r5, r5, #0\n\t" "# a[i+21] += m[21] * mu\n\t" - "ldr r7, [%[m], #84]\n\t" + "ldr r7, [%[m], #84]\n\t" "ldr r9, [%[a], #84]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3867,7 +3762,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #84]\n\t" "adc r4, r4, #0\n\t" "# a[i+22] += m[22] * mu\n\t" - "ldr r7, [%[m], #88]\n\t" + "ldr r7, [%[m], #88]\n\t" "ldr r9, [%[a], #88]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3876,7 +3771,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #88]\n\t" "adc r5, r5, #0\n\t" "# a[i+23] += m[23] * mu\n\t" - "ldr r7, [%[m], #92]\n\t" + "ldr r7, [%[m], #92]\n\t" "ldr r9, [%[a], #92]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3885,7 +3780,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #92]\n\t" "adc r4, r4, #0\n\t" "# a[i+24] += m[24] * mu\n\t" - "ldr r7, [%[m], #96]\n\t" + "ldr r7, [%[m], #96]\n\t" "ldr r9, [%[a], #96]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3894,7 +3789,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #96]\n\t" "adc r5, r5, #0\n\t" "# a[i+25] += m[25] * mu\n\t" - "ldr r7, [%[m], #100]\n\t" + "ldr r7, [%[m], #100]\n\t" "ldr r9, [%[a], #100]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3903,7 +3798,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #100]\n\t" "adc r4, r4, #0\n\t" "# a[i+26] += m[26] * mu\n\t" - "ldr r7, [%[m], #104]\n\t" + "ldr r7, [%[m], #104]\n\t" "ldr r9, [%[a], #104]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3912,7 +3807,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #104]\n\t" "adc r5, r5, #0\n\t" "# a[i+27] += m[27] * mu\n\t" - "ldr r7, [%[m], #108]\n\t" + "ldr r7, [%[m], #108]\n\t" "ldr r9, [%[a], #108]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3921,7 +3816,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #108]\n\t" "adc r4, r4, #0\n\t" "# a[i+28] += m[28] * mu\n\t" - "ldr r7, [%[m], #112]\n\t" + "ldr r7, [%[m], #112]\n\t" "ldr r9, [%[a], #112]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3930,7 +3825,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #112]\n\t" "adc r5, r5, #0\n\t" "# a[i+29] += m[29] * mu\n\t" - "ldr r7, [%[m], #116]\n\t" + "ldr r7, [%[m], #116]\n\t" "ldr r9, [%[a], #116]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3939,7 +3834,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r9, [%[a], #116]\n\t" "adc r4, r4, #0\n\t" "# a[i+30] += m[30] * mu\n\t" - "ldr r7, [%[m], #120]\n\t" + "ldr r7, [%[m], #120]\n\t" "ldr r9, [%[a], #120]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -3970,7 +3865,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); @@ -3985,8 +3880,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_32(r, a, b); sp_2048_mont_reduce_32(r, m, mp); @@ -3999,8 +3894,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_32(r, a); sp_2048_mont_reduce_32(r, m, mp); @@ -4053,243 +3948,213 @@ static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #28]\n\t" "# A[8] * B\n\t" "ldr r8, [%[a], #32]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #32]\n\t" "# A[9] * B\n\t" "ldr r8, [%[a], #36]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #36]\n\t" "# A[10] * B\n\t" "ldr r8, [%[a], #40]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #40]\n\t" "# A[11] * B\n\t" "ldr r8, [%[a], #44]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #44]\n\t" "# A[12] * B\n\t" "ldr r8, [%[a], #48]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #48]\n\t" "# A[13] * B\n\t" "ldr r8, [%[a], #52]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #52]\n\t" "# A[14] * B\n\t" "ldr r8, [%[a], #56]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #56]\n\t" "# A[15] * B\n\t" "ldr r8, [%[a], #60]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #60]\n\t" "# A[16] * B\n\t" "ldr r8, [%[a], #64]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #64]\n\t" "# A[17] * B\n\t" "ldr r8, [%[a], #68]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #68]\n\t" "# A[18] * B\n\t" "ldr r8, [%[a], #72]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #72]\n\t" "# A[19] * B\n\t" "ldr r8, [%[a], #76]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #76]\n\t" "# A[20] * B\n\t" "ldr r8, [%[a], #80]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[21] * B\n\t" "ldr r8, [%[a], #84]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[22] * B\n\t" "ldr r8, [%[a], #88]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #88]\n\t" "# A[23] * B\n\t" "ldr r8, [%[a], #92]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #92]\n\t" "# A[24] * B\n\t" "ldr r8, [%[a], #96]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #96]\n\t" "# A[25] * B\n\t" "ldr r8, [%[a], #100]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #100]\n\t" "# A[26] * B\n\t" "ldr r8, [%[a], #104]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #104]\n\t" "# A[27] * B\n\t" "ldr r8, [%[a], #108]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #108]\n\t" "# A[28] * B\n\t" "ldr r8, [%[a], #112]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #112]\n\t" "# A[29] * B\n\t" "ldr r8, [%[a], #116]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #116]\n\t" "# A[30] * B\n\t" "ldr r8, [%[a], #120]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #120]\n\t" "# A[31] * B\n\t" "ldr r8, [%[a], #124]\n\t" @@ -4836,35 +4701,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 64]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -4912,34 +4773,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -4960,9 +4821,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4981,35 +4841,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 64]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -5073,34 +4929,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -5122,16 +4978,15 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -5148,7 +5003,7 @@ static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m) sp_2048_sub_in_place_64(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -5527,6 +5382,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -5535,13 +5391,12 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -5549,7 +5404,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -5557,7 +5412,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5566,7 +5421,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5575,7 +5430,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5584,7 +5439,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5593,7 +5448,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #24]\n\t" "adc r5, r5, #0\n\t" "# a[i+7] += m[7] * mu\n\t" - "ldr r7, [%[m], #28]\n\t" + "ldr r7, [%[m], #28]\n\t" "ldr r9, [%[a], #28]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5602,7 +5457,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #28]\n\t" "adc r4, r4, #0\n\t" "# a[i+8] += m[8] * mu\n\t" - "ldr r7, [%[m], #32]\n\t" + "ldr r7, [%[m], #32]\n\t" "ldr r9, [%[a], #32]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5611,7 +5466,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #32]\n\t" "adc r5, r5, #0\n\t" "# a[i+9] += m[9] * mu\n\t" - "ldr r7, [%[m], #36]\n\t" + "ldr r7, [%[m], #36]\n\t" "ldr r9, [%[a], #36]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5620,7 +5475,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #36]\n\t" "adc r4, r4, #0\n\t" "# a[i+10] += m[10] * mu\n\t" - "ldr r7, [%[m], #40]\n\t" + "ldr r7, [%[m], #40]\n\t" "ldr r9, [%[a], #40]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5629,7 +5484,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #40]\n\t" "adc r5, r5, #0\n\t" "# a[i+11] += m[11] * mu\n\t" - "ldr r7, [%[m], #44]\n\t" + "ldr r7, [%[m], #44]\n\t" "ldr r9, [%[a], #44]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5638,7 +5493,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #44]\n\t" "adc r4, r4, #0\n\t" "# a[i+12] += m[12] * mu\n\t" - "ldr r7, [%[m], #48]\n\t" + "ldr r7, [%[m], #48]\n\t" "ldr r9, [%[a], #48]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5647,7 +5502,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #48]\n\t" "adc r5, r5, #0\n\t" "# a[i+13] += m[13] * mu\n\t" - "ldr r7, [%[m], #52]\n\t" + "ldr r7, [%[m], #52]\n\t" "ldr r9, [%[a], #52]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5656,7 +5511,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #52]\n\t" "adc r4, r4, #0\n\t" "# a[i+14] += m[14] * mu\n\t" - "ldr r7, [%[m], #56]\n\t" + "ldr r7, [%[m], #56]\n\t" "ldr r9, [%[a], #56]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5665,7 +5520,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #56]\n\t" "adc r5, r5, #0\n\t" "# a[i+15] += m[15] * mu\n\t" - "ldr r7, [%[m], #60]\n\t" + "ldr r7, [%[m], #60]\n\t" "ldr r9, [%[a], #60]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5674,7 +5529,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #60]\n\t" "adc r4, r4, #0\n\t" "# a[i+16] += m[16] * mu\n\t" - "ldr r7, [%[m], #64]\n\t" + "ldr r7, [%[m], #64]\n\t" "ldr r9, [%[a], #64]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5683,7 +5538,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #64]\n\t" "adc r5, r5, #0\n\t" "# a[i+17] += m[17] * mu\n\t" - "ldr r7, [%[m], #68]\n\t" + "ldr r7, [%[m], #68]\n\t" "ldr r9, [%[a], #68]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5692,7 +5547,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #68]\n\t" "adc r4, r4, #0\n\t" "# a[i+18] += m[18] * mu\n\t" - "ldr r7, [%[m], #72]\n\t" + "ldr r7, [%[m], #72]\n\t" "ldr r9, [%[a], #72]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5701,7 +5556,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #72]\n\t" "adc r5, r5, #0\n\t" "# a[i+19] += m[19] * mu\n\t" - "ldr r7, [%[m], #76]\n\t" + "ldr r7, [%[m], #76]\n\t" "ldr r9, [%[a], #76]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5710,7 +5565,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #76]\n\t" "adc r4, r4, #0\n\t" "# a[i+20] += m[20] * mu\n\t" - "ldr r7, [%[m], #80]\n\t" + "ldr r7, [%[m], #80]\n\t" "ldr r9, [%[a], #80]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5719,7 +5574,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #80]\n\t" "adc r5, r5, #0\n\t" "# a[i+21] += m[21] * mu\n\t" - "ldr r7, [%[m], #84]\n\t" + "ldr r7, [%[m], #84]\n\t" "ldr r9, [%[a], #84]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5728,7 +5583,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #84]\n\t" "adc r4, r4, #0\n\t" "# a[i+22] += m[22] * mu\n\t" - "ldr r7, [%[m], #88]\n\t" + "ldr r7, [%[m], #88]\n\t" "ldr r9, [%[a], #88]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5737,7 +5592,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #88]\n\t" "adc r5, r5, #0\n\t" "# a[i+23] += m[23] * mu\n\t" - "ldr r7, [%[m], #92]\n\t" + "ldr r7, [%[m], #92]\n\t" "ldr r9, [%[a], #92]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5746,7 +5601,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #92]\n\t" "adc r4, r4, #0\n\t" "# a[i+24] += m[24] * mu\n\t" - "ldr r7, [%[m], #96]\n\t" + "ldr r7, [%[m], #96]\n\t" "ldr r9, [%[a], #96]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5755,7 +5610,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #96]\n\t" "adc r5, r5, #0\n\t" "# a[i+25] += m[25] * mu\n\t" - "ldr r7, [%[m], #100]\n\t" + "ldr r7, [%[m], #100]\n\t" "ldr r9, [%[a], #100]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5764,7 +5619,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #100]\n\t" "adc r4, r4, #0\n\t" "# a[i+26] += m[26] * mu\n\t" - "ldr r7, [%[m], #104]\n\t" + "ldr r7, [%[m], #104]\n\t" "ldr r9, [%[a], #104]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5773,7 +5628,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #104]\n\t" "adc r5, r5, #0\n\t" "# a[i+27] += m[27] * mu\n\t" - "ldr r7, [%[m], #108]\n\t" + "ldr r7, [%[m], #108]\n\t" "ldr r9, [%[a], #108]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5782,7 +5637,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #108]\n\t" "adc r4, r4, #0\n\t" "# a[i+28] += m[28] * mu\n\t" - "ldr r7, [%[m], #112]\n\t" + "ldr r7, [%[m], #112]\n\t" "ldr r9, [%[a], #112]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5791,7 +5646,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #112]\n\t" "adc r5, r5, #0\n\t" "# a[i+29] += m[29] * mu\n\t" - "ldr r7, [%[m], #116]\n\t" + "ldr r7, [%[m], #116]\n\t" "ldr r9, [%[a], #116]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5800,7 +5655,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #116]\n\t" "adc r4, r4, #0\n\t" "# a[i+30] += m[30] * mu\n\t" - "ldr r7, [%[m], #120]\n\t" + "ldr r7, [%[m], #120]\n\t" "ldr r9, [%[a], #120]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5809,7 +5664,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #120]\n\t" "adc r5, r5, #0\n\t" "# a[i+31] += m[31] * mu\n\t" - "ldr r7, [%[m], #124]\n\t" + "ldr r7, [%[m], #124]\n\t" "ldr r9, [%[a], #124]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5818,7 +5673,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #124]\n\t" "adc r4, r4, #0\n\t" "# a[i+32] += m[32] * mu\n\t" - "ldr r7, [%[m], #128]\n\t" + "ldr r7, [%[m], #128]\n\t" "ldr r9, [%[a], #128]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5827,7 +5682,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #128]\n\t" "adc r5, r5, #0\n\t" "# a[i+33] += m[33] * mu\n\t" - "ldr r7, [%[m], #132]\n\t" + "ldr r7, [%[m], #132]\n\t" "ldr r9, [%[a], #132]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5836,7 +5691,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #132]\n\t" "adc r4, r4, #0\n\t" "# a[i+34] += m[34] * mu\n\t" - "ldr r7, [%[m], #136]\n\t" + "ldr r7, [%[m], #136]\n\t" "ldr r9, [%[a], #136]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5845,7 +5700,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #136]\n\t" "adc r5, r5, #0\n\t" "# a[i+35] += m[35] * mu\n\t" - "ldr r7, [%[m], #140]\n\t" + "ldr r7, [%[m], #140]\n\t" "ldr r9, [%[a], #140]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5854,7 +5709,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #140]\n\t" "adc r4, r4, #0\n\t" "# a[i+36] += m[36] * mu\n\t" - "ldr r7, [%[m], #144]\n\t" + "ldr r7, [%[m], #144]\n\t" "ldr r9, [%[a], #144]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5863,7 +5718,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #144]\n\t" "adc r5, r5, #0\n\t" "# a[i+37] += m[37] * mu\n\t" - "ldr r7, [%[m], #148]\n\t" + "ldr r7, [%[m], #148]\n\t" "ldr r9, [%[a], #148]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5872,7 +5727,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #148]\n\t" "adc r4, r4, #0\n\t" "# a[i+38] += m[38] * mu\n\t" - "ldr r7, [%[m], #152]\n\t" + "ldr r7, [%[m], #152]\n\t" "ldr r9, [%[a], #152]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5881,7 +5736,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #152]\n\t" "adc r5, r5, #0\n\t" "# a[i+39] += m[39] * mu\n\t" - "ldr r7, [%[m], #156]\n\t" + "ldr r7, [%[m], #156]\n\t" "ldr r9, [%[a], #156]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5890,7 +5745,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #156]\n\t" "adc r4, r4, #0\n\t" "# a[i+40] += m[40] * mu\n\t" - "ldr r7, [%[m], #160]\n\t" + "ldr r7, [%[m], #160]\n\t" "ldr r9, [%[a], #160]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5899,7 +5754,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #160]\n\t" "adc r5, r5, #0\n\t" "# a[i+41] += m[41] * mu\n\t" - "ldr r7, [%[m], #164]\n\t" + "ldr r7, [%[m], #164]\n\t" "ldr r9, [%[a], #164]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5908,7 +5763,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #164]\n\t" "adc r4, r4, #0\n\t" "# a[i+42] += m[42] * mu\n\t" - "ldr r7, [%[m], #168]\n\t" + "ldr r7, [%[m], #168]\n\t" "ldr r9, [%[a], #168]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5917,7 +5772,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #168]\n\t" "adc r5, r5, #0\n\t" "# a[i+43] += m[43] * mu\n\t" - "ldr r7, [%[m], #172]\n\t" + "ldr r7, [%[m], #172]\n\t" "ldr r9, [%[a], #172]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5926,7 +5781,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #172]\n\t" "adc r4, r4, #0\n\t" "# a[i+44] += m[44] * mu\n\t" - "ldr r7, [%[m], #176]\n\t" + "ldr r7, [%[m], #176]\n\t" "ldr r9, [%[a], #176]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5935,7 +5790,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #176]\n\t" "adc r5, r5, #0\n\t" "# a[i+45] += m[45] * mu\n\t" - "ldr r7, [%[m], #180]\n\t" + "ldr r7, [%[m], #180]\n\t" "ldr r9, [%[a], #180]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5944,7 +5799,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #180]\n\t" "adc r4, r4, #0\n\t" "# a[i+46] += m[46] * mu\n\t" - "ldr r7, [%[m], #184]\n\t" + "ldr r7, [%[m], #184]\n\t" "ldr r9, [%[a], #184]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5953,7 +5808,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #184]\n\t" "adc r5, r5, #0\n\t" "# a[i+47] += m[47] * mu\n\t" - "ldr r7, [%[m], #188]\n\t" + "ldr r7, [%[m], #188]\n\t" "ldr r9, [%[a], #188]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5962,7 +5817,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #188]\n\t" "adc r4, r4, #0\n\t" "# a[i+48] += m[48] * mu\n\t" - "ldr r7, [%[m], #192]\n\t" + "ldr r7, [%[m], #192]\n\t" "ldr r9, [%[a], #192]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5971,7 +5826,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #192]\n\t" "adc r5, r5, #0\n\t" "# a[i+49] += m[49] * mu\n\t" - "ldr r7, [%[m], #196]\n\t" + "ldr r7, [%[m], #196]\n\t" "ldr r9, [%[a], #196]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5980,7 +5835,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #196]\n\t" "adc r4, r4, #0\n\t" "# a[i+50] += m[50] * mu\n\t" - "ldr r7, [%[m], #200]\n\t" + "ldr r7, [%[m], #200]\n\t" "ldr r9, [%[a], #200]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5989,7 +5844,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #200]\n\t" "adc r5, r5, #0\n\t" "# a[i+51] += m[51] * mu\n\t" - "ldr r7, [%[m], #204]\n\t" + "ldr r7, [%[m], #204]\n\t" "ldr r9, [%[a], #204]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -5998,7 +5853,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #204]\n\t" "adc r4, r4, #0\n\t" "# a[i+52] += m[52] * mu\n\t" - "ldr r7, [%[m], #208]\n\t" + "ldr r7, [%[m], #208]\n\t" "ldr r9, [%[a], #208]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6007,7 +5862,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #208]\n\t" "adc r5, r5, #0\n\t" "# a[i+53] += m[53] * mu\n\t" - "ldr r7, [%[m], #212]\n\t" + "ldr r7, [%[m], #212]\n\t" "ldr r9, [%[a], #212]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6016,7 +5871,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #212]\n\t" "adc r4, r4, #0\n\t" "# a[i+54] += m[54] * mu\n\t" - "ldr r7, [%[m], #216]\n\t" + "ldr r7, [%[m], #216]\n\t" "ldr r9, [%[a], #216]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6025,7 +5880,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #216]\n\t" "adc r5, r5, #0\n\t" "# a[i+55] += m[55] * mu\n\t" - "ldr r7, [%[m], #220]\n\t" + "ldr r7, [%[m], #220]\n\t" "ldr r9, [%[a], #220]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6034,7 +5889,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #220]\n\t" "adc r4, r4, #0\n\t" "# a[i+56] += m[56] * mu\n\t" - "ldr r7, [%[m], #224]\n\t" + "ldr r7, [%[m], #224]\n\t" "ldr r9, [%[a], #224]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6043,7 +5898,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #224]\n\t" "adc r5, r5, #0\n\t" "# a[i+57] += m[57] * mu\n\t" - "ldr r7, [%[m], #228]\n\t" + "ldr r7, [%[m], #228]\n\t" "ldr r9, [%[a], #228]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6052,7 +5907,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #228]\n\t" "adc r4, r4, #0\n\t" "# a[i+58] += m[58] * mu\n\t" - "ldr r7, [%[m], #232]\n\t" + "ldr r7, [%[m], #232]\n\t" "ldr r9, [%[a], #232]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6061,7 +5916,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #232]\n\t" "adc r5, r5, #0\n\t" "# a[i+59] += m[59] * mu\n\t" - "ldr r7, [%[m], #236]\n\t" + "ldr r7, [%[m], #236]\n\t" "ldr r9, [%[a], #236]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6070,7 +5925,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #236]\n\t" "adc r4, r4, #0\n\t" "# a[i+60] += m[60] * mu\n\t" - "ldr r7, [%[m], #240]\n\t" + "ldr r7, [%[m], #240]\n\t" "ldr r9, [%[a], #240]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6079,7 +5934,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #240]\n\t" "adc r5, r5, #0\n\t" "# a[i+61] += m[61] * mu\n\t" - "ldr r7, [%[m], #244]\n\t" + "ldr r7, [%[m], #244]\n\t" "ldr r9, [%[a], #244]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6088,7 +5943,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r9, [%[a], #244]\n\t" "adc r4, r4, #0\n\t" "# a[i+62] += m[62] * mu\n\t" - "ldr r7, [%[m], #248]\n\t" + "ldr r7, [%[m], #248]\n\t" "ldr r9, [%[a], #248]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -6119,7 +5974,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca); @@ -6134,8 +5989,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_64(r, a, b); sp_2048_mont_reduce_64(r, m, mp); @@ -6148,8 +6003,8 @@ static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_64(r, a); sp_2048_mont_reduce_64(r, m, mp); @@ -7125,35 +6980,31 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 128]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_2048_mont_setup(m, &mp); @@ -7201,34 +7052,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -7249,9 +7100,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -7270,35 +7120,31 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 128]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_2048_mont_setup(m, &mp); @@ -7362,34 +7208,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -7411,9 +7257,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -7434,19 +7279,18 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128], m[64], r[128]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 256) { @@ -7460,22 +7304,18 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 64 * 2; - m = r + 64 * 2; - } #endif if (err == MP_OKAY) { + r = a + 64 * 2; + m = r + 64 * 2; ah = a + 64; sp_2048_from_bin(ah, 64, in, inLen); @@ -7548,10 +7388,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -7781,13 +7620,17 @@ static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[64 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -7816,13 +7659,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 64; m = a + 128; @@ -7833,31 +7678,36 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_2048_from_mp(m, 64, mm); err = sp_2048_mod_exp_64(r, a, d, 2048, m, 0); } + if (err == MP_OKAY) { sp_2048_to_bin(r, out); *outLen = 256; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[64 * 2]; - sp_digit p[32], q[32], dp[32]; - sp_digit tmpa[64], tmpb[64]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[32 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -7877,31 +7727,23 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 64 * 2; q = p + 32; qi = dq = dp = q + 32; tmpa = qi + 32; tmpb = tmpa + 64; - - r = t + 64; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_2048_from_bin(a, 64, in, inLen); sp_2048_from_mp(p, 32, pm); sp_2048_from_mp(q, 32, qm); @@ -7933,18 +7775,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 32 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -7968,17 +7807,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 64; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -7991,14 +7832,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -8025,10 +7868,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -8472,34 +8318,31 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[193]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 128; -#else - tmp = &td[128]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_64(norm, m); @@ -8517,34 +8360,34 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_2048_lshift_64(r, norm, (byte)y); + sp_2048_lshift_64(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -8555,7 +8398,7 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, sp_2048_mont_sqr_64(r, r, m, mp); sp_2048_mont_sqr_64(r, r, m, mp); - sp_2048_lshift_64(r, r, (byte)y); + sp_2048_lshift_64(r, r, y); sp_2048_mul_d_64(tmp, norm, r[64]); r[64] = 0; o = sp_2048_add_64(r, r, tmp); @@ -8570,9 +8413,8 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -8591,11 +8433,13 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; word32 i; @@ -8630,6 +8474,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -8651,10 +8496,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -8691,7 +8539,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -8705,7 +8553,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -8747,7 +8596,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -8781,7 +8631,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -8820,7 +8672,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_3072_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 3072 / 8 - 1; a[j] = 0; @@ -8862,66 +8717,60 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "sub sp, sp, #48\n\t" "mov r10, #0\n\t" "# A[0] * B[0]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r3, r4, r8, r9\n\t" + "ldr r11, [%[a], #0]\n\t" + "ldr r12, [%[b], #0]\n\t" + "umull r3, r4, r11, r12\n\t" "mov r5, #0\n\t" "str r3, [sp]\n\t" "# A[0] * B[1]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" "# A[1] * B[0]\n\t" "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #4]\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r11, [%[a], #4]\n\t" + "ldr r12, [%[b], #4]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" "# A[0] * B[2]\n\t" "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #8]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[1] * B[1]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[0]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #8]\n\t" "# A[0] * B[3]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" "# A[1] * B[2]\n\t" - "ldr r8, [%[a], #4]\n\t" "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[2] * B[1]\n\t" "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -8933,13 +8782,25 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #12]\n\t" - "# A[0] * B[4]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r11, [%[a], #8]\n\t" + "ldr r12, [%[b], #8]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" "# A[1] * B[3]\n\t" "ldr r8, [%[a], #4]\n\t" "ldr r9, [%[b], #12]\n\t" @@ -8947,30 +8808,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[2] * B[2]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[1]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[0]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #16]\n\t" "# A[0] * B[5]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" @@ -8984,16 +8830,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[2] * B[3]\n\t" - "ldr r8, [%[a], #8]\n\t" "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[3] * B[2]\n\t" "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -9012,20 +8856,32 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #20]\n\t" - "# A[0] * B[6]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #24]\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" - "# A[1] * B[5]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #20]\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r11, [%[a], #12]\n\t" + "ldr r12, [%[b], #12]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" "# A[2] * B[4]\n\t" "ldr r8, [%[a], #8]\n\t" "ldr r9, [%[b], #16]\n\t" @@ -9033,37 +8889,22 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[3] * B[3]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[4] * B[2]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[1]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[0]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #24]\n\t" "# A[0] * B[7]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" @@ -9084,16 +8925,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[3] * B[4]\n\t" - "ldr r8, [%[a], #12]\n\t" "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[4] * B[3]\n\t" "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -9119,44 +8958,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #28]\n\t" - "# A[0] * B[8]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #32]\n\t" + "# A[8] * B[0]\n\t" + "ldr r8, [%[a], #32]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r10, r10\n\t" - "# A[1] * B[7]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[6]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[3] * B[5]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[4] * B[4]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[5] * B[3]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -9168,23 +8978,49 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[7] * B[1]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r11, [%[a], #16]\n\t" + "ldr r12, [%[b], #16]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[8] * B[0]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[0] * B[8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #32]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #32]\n\t" "# A[0] * B[9]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #36]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" @@ -9212,16 +9048,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[4] * B[5]\n\t" - "ldr r8, [%[a], #16]\n\t" "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[5] * B[4]\n\t" "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -9254,58 +9088,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #36]\n\t" - "# A[0] * B[10]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #40]\n\t" + "# A[10] * B[0]\n\t" + "ldr r8, [%[a], #40]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" - "# A[1] * B[9]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[2] * B[8]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[7]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[6]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[5] * B[5]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[6] * B[4]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[7] * B[3]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[9] * B[1]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -9317,23 +9108,63 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[9] * B[1]\n\t" - "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[10] * B[0]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r11, [%[a], #20]\n\t" + "ldr r12, [%[b], #20]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[8]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[1] * B[9]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[0] * B[10]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #40]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #40]\n\t" "# A[0] * B[11]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" @@ -9368,16 +9199,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[5] * B[6]\n\t" - "ldr r8, [%[a], #20]\n\t" "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[6] * B[5]\n\t" "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -9417,58 +9246,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #44]\n\t" - "# A[1] * B[11]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" - "# A[2] * B[10]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[3] * B[9]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[4] * B[8]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[7]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[6]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[7] * B[5]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[8] * B[4]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[10] * B[2]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #8]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -9480,16 +9266,57 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[10] * B[2]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #8]\n\t" + "# A[8] * B[4]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[11] * B[1]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r11, [%[a], #24]\n\t" + "ldr r12, [%[b], #24]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[9]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[10]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[1] * B[11]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -9497,7 +9324,6 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r3, [%[r], #48]\n\t" "# A[2] * B[11]\n\t" "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -9524,16 +9350,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[6] * B[7]\n\t" - "ldr r8, [%[a], #24]\n\t" "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[7] * B[6]\n\t" "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -9566,44 +9390,15 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [%[r], #52]\n\t" - "# A[3] * B[11]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r10, r10\n\t" - "# A[4] * B[10]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[5] * B[9]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[6] * B[8]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[7] * B[7]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[8] * B[6]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #24]\n\t" + "# A[10] * B[4]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -9615,16 +9410,43 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[10] * B[4]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[8] * B[6]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[7]\n\t" + "ldr r11, [%[a], #28]\n\t" + "ldr r12, [%[b], #28]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #32]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[11] * B[3]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[5] * B[9]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[10]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[11]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -9632,7 +9454,6 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r5, [%[r], #56]\n\t" "# A[4] * B[11]\n\t" "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -9652,16 +9473,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[7] * B[8]\n\t" - "ldr r8, [%[a], #28]\n\t" "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[8] * B[7]\n\t" "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -9687,20 +9506,32 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [%[r], #60]\n\t" - "# A[5] * B[11]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" - "# A[6] * B[10]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #40]\n\t" + "# A[10] * B[6]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" + "# A[9] * B[7]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[8]\n\t" + "ldr r11, [%[a], #32]\n\t" + "ldr r12, [%[b], #32]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" "# A[7] * B[9]\n\t" "ldr r8, [%[a], #28]\n\t" "ldr r9, [%[b], #36]\n\t" @@ -9708,30 +9539,16 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[8] * B[8]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #32]\n\t" + "# A[6] * B[10]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #40]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[9] * B[7]\n\t" - "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[10] * B[6]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[11] * B[5]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #20]\n\t" + "# A[5] * B[11]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -9739,7 +9556,6 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r4, [%[r], #64]\n\t" "# A[6] * B[11]\n\t" "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -9752,16 +9568,14 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[8] * B[9]\n\t" - "ldr r8, [%[a], #32]\n\t" "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[9] * B[8]\n\t" "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -9780,13 +9594,25 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [%[r], #68]\n\t" - "# A[7] * B[11]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[7]\n\t" + "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" + "# A[10] * B[8]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[9]\n\t" + "ldr r11, [%[a], #36]\n\t" + "ldr r12, [%[b], #36]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" "# A[8] * B[10]\n\t" "ldr r8, [%[a], #32]\n\t" "ldr r9, [%[b], #40]\n\t" @@ -9794,23 +9620,9 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[9] * B[9]\n\t" - "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[10] * B[8]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[11] * B[7]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #28]\n\t" + "# A[7] * B[11]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -9818,22 +9630,19 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r3, [%[r], #72]\n\t" "# A[8] * B[11]\n\t" "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" "# A[9] * B[10]\n\t" - "ldr r8, [%[a], #36]\n\t" "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[10] * B[9]\n\t" "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -9845,79 +9654,54 @@ static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [%[r], #76]\n\t" + "# A[11] * B[9]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[10] * B[10]\n\t" + "ldr r11, [%[a], #40]\n\t" + "ldr r12, [%[b], #40]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" "# A[9] * B[11]\n\t" "ldr r8, [%[a], #36]\n\t" "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[10] * B[10]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[11] * B[9]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[10] * B[11]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #44]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" "# A[11] * B[10]\n\t" "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[11] * B[11]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adc r5, r5, r7\n\t" "str r4, [%[r], #88]\n\t" "str r5, [%[r], #92]\n\t" - "ldr r3, [sp, #0]\n\t" - "ldr r4, [sp, #4]\n\t" - "ldr r5, [sp, #8]\n\t" - "ldr r6, [sp, #12]\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [sp, #16]\n\t" - "ldr r4, [sp, #20]\n\t" - "ldr r5, [sp, #24]\n\t" - "ldr r6, [sp, #28]\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - "ldr r3, [sp, #32]\n\t" - "ldr r4, [sp, #36]\n\t" - "ldr r5, [sp, #40]\n\t" - "ldr r6, [sp, #44]\n\t" - "str r3, [%[r], #32]\n\t" - "str r4, [%[r], #36]\n\t" - "str r5, [%[r], #40]\n\t" - "str r6, [%[r], #44]\n\t" - "add sp, sp, #48\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "sub %[r], %[r], #48\n\t" : : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); } @@ -9930,7 +9714,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) { __asm__ __volatile__ ( "sub sp, sp, #48\n\t" - "mov r14, #0\n\t" + "mov r12, #0\n\t" "# A[0] * A[0]\n\t" "ldr r10, [%[a], #0]\n\t" "umull r8, r3, r10, r10\n\t" @@ -9942,10 +9726,10 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [sp, #4]\n\t" "# A[0] * A[2]\n\t" "ldr r10, [%[a], #8]\n\t" @@ -9953,16 +9737,16 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" + "adc r3, r12, r12\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "# A[1] * A[1]\n\t" "ldr r10, [%[a], #4]\n\t" "umull r8, r9, r10, r10\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "str r4, [sp, #8]\n\t" "# A[0] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" @@ -9970,20 +9754,20 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" + "adc r4, r12, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "# A[1] * A[2]\n\t" "ldr r10, [%[a], #8]\n\t" "ldr r8, [%[a], #4]\n\t" "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "str r2, [sp, #12]\n\t" "# A[0] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" @@ -9991,26 +9775,26 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[1] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" "ldr r8, [%[a], #4]\n\t" "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[2] * A[2]\n\t" "ldr r10, [%[a], #8]\n\t" "umull r8, r9, r10, r10\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [sp, #16]\n\t" "# A[0] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" @@ -10024,14 +9808,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10051,14 +9835,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[3]\n\t" "ldr r10, [%[a], #12]\n\t" "umull r8, r9, r10, r10\n\t" @@ -10067,7 +9851,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r2, r2, r5\n\t" "adcs r3, r3, r6\n\t" "adc r4, r4, r7\n\t" @@ -10084,21 +9868,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10118,21 +9902,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[4]\n\t" "ldr r10, [%[a], #16]\n\t" "umull r8, r9, r10, r10\n\t" @@ -10141,7 +9925,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r4, r4, r5\n\t" "adcs r2, r2, r6\n\t" "adc r3, r3, r7\n\t" @@ -10158,28 +9942,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10199,28 +9983,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[5] * A[5]\n\t" "ldr r10, [%[a], #20]\n\t" "umull r8, r9, r10, r10\n\t" @@ -10229,7 +10013,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r3, r3, r5\n\t" "adcs r4, r4, r6\n\t" "adc r2, r2, r7\n\t" @@ -10246,35 +10030,35 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[2] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #8]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[5] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "ldr r8, [%[a], #20]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10294,28 +10078,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[3] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #12]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[5] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" "ldr r8, [%[a], #20]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[6] * A[6]\n\t" "ldr r10, [%[a], #24]\n\t" "umull r8, r9, r10, r10\n\t" @@ -10324,7 +10108,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r2, r2, r5\n\t" "adcs r3, r3, r6\n\t" "adc r4, r4, r7\n\t" @@ -10341,28 +10125,28 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[4] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #16]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[5] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "ldr r8, [%[a], #20]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[6] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" "ldr r8, [%[a], #24]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10382,21 +10166,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[5] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #20]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[6] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "ldr r8, [%[a], #24]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[7] * A[7]\n\t" "ldr r10, [%[a], #28]\n\t" "umull r8, r9, r10, r10\n\t" @@ -10405,7 +10189,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r4, r4, r5\n\t" "adcs r2, r2, r6\n\t" "adc r3, r3, r7\n\t" @@ -10422,21 +10206,21 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[6] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #24]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[7] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "ldr r8, [%[a], #28]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10456,14 +10240,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[7] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #28]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[8] * A[8]\n\t" "ldr r10, [%[a], #32]\n\t" "umull r8, r9, r10, r10\n\t" @@ -10472,7 +10256,7 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r7, r7, r7\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r3, r3, r5\n\t" "adcs r4, r4, r6\n\t" "adc r2, r2, r7\n\t" @@ -10489,14 +10273,14 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "# A[8] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "ldr r8, [%[a], #32]\n\t" "umull r8, r9, r10, r8\n\t" "adds r5, r5, r8\n\t" "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" + "adc r7, r7, r12\n\t" "adds r5, r5, r5\n\t" "adcs r6, r6, r6\n\t" "adc r7, r7, r7\n\t" @@ -10510,26 +10294,26 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" + "adc r4, r12, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "# A[8] * A[10]\n\t" "ldr r10, [%[a], #40]\n\t" "ldr r8, [%[a], #32]\n\t" "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "# A[9] * A[9]\n\t" "ldr r10, [%[a], #36]\n\t" "umull r8, r9, r10, r10\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "str r2, [%[r], #72]\n\t" "# A[8] * A[11]\n\t" "ldr r10, [%[a], #44]\n\t" @@ -10537,20 +10321,20 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" + "adc r2, r12, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "# A[9] * A[10]\n\t" "ldr r10, [%[a], #40]\n\t" "ldr r8, [%[a], #36]\n\t" "umull r8, r9, r10, r8\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "adds r3, r3, r8\n\t" "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" + "adc r2, r2, r12\n\t" "str r3, [%[r], #76]\n\t" "# A[9] * A[11]\n\t" "ldr r10, [%[a], #44]\n\t" @@ -10558,16 +10342,16 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" + "adc r3, r12, r12\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "# A[10] * A[10]\n\t" "ldr r10, [%[a], #40]\n\t" "umull r8, r9, r10, r10\n\t" "adds r4, r4, r8\n\t" "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" + "adc r3, r3, r12\n\t" "str r4, [%[r], #80]\n\t" "# A[10] * A[11]\n\t" "ldr r10, [%[a], #44]\n\t" @@ -10575,10 +10359,10 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "umull r8, r9, r10, r8\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" + "adc r4, r12, r12\n\t" "adds r2, r2, r8\n\t" "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" + "adc r4, r4, r12\n\t" "str r2, [%[r], #84]\n\t" "# A[11] * A[11]\n\t" "ldr r10, [%[a], #44]\n\t" @@ -10587,34 +10371,16 @@ static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) "adc r4, r4, r9\n\t" "str r3, [%[r], #88]\n\t" "str r4, [%[r], #92]\n\t" - "ldr r2, [sp, #0]\n\t" - "ldr r3, [sp, #4]\n\t" - "ldr r4, [sp, #8]\n\t" - "ldr r8, [sp, #12]\n\t" - "str r2, [%[r], #0]\n\t" - "str r3, [%[r], #4]\n\t" - "str r4, [%[r], #8]\n\t" - "str r8, [%[r], #12]\n\t" - "ldr r2, [sp, #16]\n\t" - "ldr r3, [sp, #20]\n\t" - "ldr r4, [sp, #24]\n\t" - "ldr r8, [sp, #28]\n\t" - "str r2, [%[r], #16]\n\t" - "str r3, [%[r], #20]\n\t" - "str r4, [%[r], #24]\n\t" - "str r8, [%[r], #28]\n\t" - "ldr r2, [sp, #32]\n\t" - "ldr r3, [sp, #36]\n\t" - "ldr r4, [sp, #40]\n\t" - "ldr r8, [sp, #44]\n\t" - "str r2, [%[r], #32]\n\t" - "str r3, [%[r], #36]\n\t" - "str r4, [%[r], #40]\n\t" - "str r8, [%[r], #44]\n\t" - "add sp, sp, #48\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "sub %[r], %[r], #48\n\t" : : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12" ); } @@ -10965,7 +10731,9 @@ SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, sp_digit a1[12]; sp_digit b1[12]; sp_digit z2[24]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_12(a1, a, &a[12]); cb = sp_3072_add_12(b1, b, &b[12]); @@ -11480,7 +11248,9 @@ SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, sp_digit a1[24]; sp_digit b1[24]; sp_digit z2[48]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_24(a1, a, &a[24]); cb = sp_3072_add_24(b1, b, &b[24]); @@ -12379,7 +12149,9 @@ SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, sp_digit a1[48]; sp_digit b1[48]; sp_digit z2[96]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_48(a1, a, &a[48]); cb = sp_3072_add_48(b1, b, &b[48]); @@ -12894,7 +12666,7 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -12903,7 +12675,8 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -12912,7 +12685,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -12962,755 +12735,661 @@ static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #28]\n\t" "# A[8] * B\n\t" "ldr r8, [%[a], #32]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #32]\n\t" "# A[9] * B\n\t" "ldr r8, [%[a], #36]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #36]\n\t" "# A[10] * B\n\t" "ldr r8, [%[a], #40]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #40]\n\t" "# A[11] * B\n\t" "ldr r8, [%[a], #44]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #44]\n\t" "# A[12] * B\n\t" "ldr r8, [%[a], #48]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #48]\n\t" "# A[13] * B\n\t" "ldr r8, [%[a], #52]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #52]\n\t" "# A[14] * B\n\t" "ldr r8, [%[a], #56]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #56]\n\t" "# A[15] * B\n\t" "ldr r8, [%[a], #60]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #60]\n\t" "# A[16] * B\n\t" "ldr r8, [%[a], #64]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #64]\n\t" "# A[17] * B\n\t" "ldr r8, [%[a], #68]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #68]\n\t" "# A[18] * B\n\t" "ldr r8, [%[a], #72]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #72]\n\t" "# A[19] * B\n\t" "ldr r8, [%[a], #76]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #76]\n\t" "# A[20] * B\n\t" "ldr r8, [%[a], #80]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[21] * B\n\t" "ldr r8, [%[a], #84]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[22] * B\n\t" "ldr r8, [%[a], #88]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #88]\n\t" "# A[23] * B\n\t" "ldr r8, [%[a], #92]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #92]\n\t" "# A[24] * B\n\t" "ldr r8, [%[a], #96]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #96]\n\t" "# A[25] * B\n\t" "ldr r8, [%[a], #100]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #100]\n\t" "# A[26] * B\n\t" "ldr r8, [%[a], #104]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #104]\n\t" "# A[27] * B\n\t" "ldr r8, [%[a], #108]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #108]\n\t" "# A[28] * B\n\t" "ldr r8, [%[a], #112]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #112]\n\t" "# A[29] * B\n\t" "ldr r8, [%[a], #116]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #116]\n\t" "# A[30] * B\n\t" "ldr r8, [%[a], #120]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #120]\n\t" "# A[31] * B\n\t" "ldr r8, [%[a], #124]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #124]\n\t" "# A[32] * B\n\t" "ldr r8, [%[a], #128]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #128]\n\t" "# A[33] * B\n\t" "ldr r8, [%[a], #132]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #132]\n\t" "# A[34] * B\n\t" "ldr r8, [%[a], #136]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #136]\n\t" "# A[35] * B\n\t" "ldr r8, [%[a], #140]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #140]\n\t" "# A[36] * B\n\t" "ldr r8, [%[a], #144]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #144]\n\t" "# A[37] * B\n\t" "ldr r8, [%[a], #148]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #148]\n\t" "# A[38] * B\n\t" "ldr r8, [%[a], #152]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #152]\n\t" "# A[39] * B\n\t" "ldr r8, [%[a], #156]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #156]\n\t" "# A[40] * B\n\t" "ldr r8, [%[a], #160]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #160]\n\t" "# A[41] * B\n\t" "ldr r8, [%[a], #164]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #164]\n\t" "# A[42] * B\n\t" "ldr r8, [%[a], #168]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #168]\n\t" "# A[43] * B\n\t" "ldr r8, [%[a], #172]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #172]\n\t" "# A[44] * B\n\t" "ldr r8, [%[a], #176]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #176]\n\t" "# A[45] * B\n\t" "ldr r8, [%[a], #180]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #180]\n\t" "# A[46] * B\n\t" "ldr r8, [%[a], #184]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #184]\n\t" "# A[47] * B\n\t" "ldr r8, [%[a], #188]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #188]\n\t" "# A[48] * B\n\t" "ldr r8, [%[a], #192]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #192]\n\t" "# A[49] * B\n\t" "ldr r8, [%[a], #196]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #196]\n\t" "# A[50] * B\n\t" "ldr r8, [%[a], #200]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #200]\n\t" "# A[51] * B\n\t" "ldr r8, [%[a], #204]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #204]\n\t" "# A[52] * B\n\t" "ldr r8, [%[a], #208]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #208]\n\t" "# A[53] * B\n\t" "ldr r8, [%[a], #212]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #212]\n\t" "# A[54] * B\n\t" "ldr r8, [%[a], #216]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #216]\n\t" "# A[55] * B\n\t" "ldr r8, [%[a], #220]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #220]\n\t" "# A[56] * B\n\t" "ldr r8, [%[a], #224]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #224]\n\t" "# A[57] * B\n\t" "ldr r8, [%[a], #228]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #228]\n\t" "# A[58] * B\n\t" "ldr r8, [%[a], #232]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #232]\n\t" "# A[59] * B\n\t" "ldr r8, [%[a], #236]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #236]\n\t" "# A[60] * B\n\t" "ldr r8, [%[a], #240]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #240]\n\t" "# A[61] * B\n\t" "ldr r8, [%[a], #244]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #244]\n\t" "# A[62] * B\n\t" "ldr r8, [%[a], #248]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #248]\n\t" "# A[63] * B\n\t" "ldr r8, [%[a], #252]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #252]\n\t" "# A[64] * B\n\t" "ldr r8, [%[a], #256]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #256]\n\t" "# A[65] * B\n\t" "ldr r8, [%[a], #260]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #260]\n\t" "# A[66] * B\n\t" "ldr r8, [%[a], #264]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #264]\n\t" "# A[67] * B\n\t" "ldr r8, [%[a], #268]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #268]\n\t" "# A[68] * B\n\t" "ldr r8, [%[a], #272]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #272]\n\t" "# A[69] * B\n\t" "ldr r8, [%[a], #276]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #276]\n\t" "# A[70] * B\n\t" "ldr r8, [%[a], #280]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #280]\n\t" "# A[71] * B\n\t" "ldr r8, [%[a], #284]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #284]\n\t" "# A[72] * B\n\t" "ldr r8, [%[a], #288]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #288]\n\t" "# A[73] * B\n\t" "ldr r8, [%[a], #292]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #292]\n\t" "# A[74] * B\n\t" "ldr r8, [%[a], #296]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #296]\n\t" "# A[75] * B\n\t" "ldr r8, [%[a], #300]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #300]\n\t" "# A[76] * B\n\t" "ldr r8, [%[a], #304]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #304]\n\t" "# A[77] * B\n\t" "ldr r8, [%[a], #308]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #308]\n\t" "# A[78] * B\n\t" "ldr r8, [%[a], #312]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #312]\n\t" "# A[79] * B\n\t" "ldr r8, [%[a], #316]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #316]\n\t" "# A[80] * B\n\t" "ldr r8, [%[a], #320]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #320]\n\t" "# A[81] * B\n\t" "ldr r8, [%[a], #324]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #324]\n\t" "# A[82] * B\n\t" "ldr r8, [%[a], #328]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #328]\n\t" "# A[83] * B\n\t" "ldr r8, [%[a], #332]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #332]\n\t" "# A[84] * B\n\t" "ldr r8, [%[a], #336]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #336]\n\t" "# A[85] * B\n\t" "ldr r8, [%[a], #340]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #340]\n\t" "# A[86] * B\n\t" "ldr r8, [%[a], #344]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #344]\n\t" "# A[87] * B\n\t" "ldr r8, [%[a], #348]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #348]\n\t" "# A[88] * B\n\t" "ldr r8, [%[a], #352]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #352]\n\t" "# A[89] * B\n\t" "ldr r8, [%[a], #356]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #356]\n\t" "# A[90] * B\n\t" "ldr r8, [%[a], #360]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #360]\n\t" "# A[91] * B\n\t" "ldr r8, [%[a], #364]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #364]\n\t" "# A[92] * B\n\t" "ldr r8, [%[a], #368]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #368]\n\t" "# A[93] * B\n\t" "ldr r8, [%[a], #372]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #372]\n\t" "# A[94] * B\n\t" "ldr r8, [%[a], #376]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #376]\n\t" "# A[95] * B\n\t" "ldr r8, [%[a], #380]\n\t" @@ -14039,6 +13718,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -14047,13 +13727,12 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -14061,7 +13740,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -14069,7 +13748,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14078,7 +13757,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14087,7 +13766,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14096,7 +13775,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14105,7 +13784,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #24]\n\t" "adc r5, r5, #0\n\t" "# a[i+7] += m[7] * mu\n\t" - "ldr r7, [%[m], #28]\n\t" + "ldr r7, [%[m], #28]\n\t" "ldr r9, [%[a], #28]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14114,7 +13793,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #28]\n\t" "adc r4, r4, #0\n\t" "# a[i+8] += m[8] * mu\n\t" - "ldr r7, [%[m], #32]\n\t" + "ldr r7, [%[m], #32]\n\t" "ldr r9, [%[a], #32]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14123,7 +13802,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #32]\n\t" "adc r5, r5, #0\n\t" "# a[i+9] += m[9] * mu\n\t" - "ldr r7, [%[m], #36]\n\t" + "ldr r7, [%[m], #36]\n\t" "ldr r9, [%[a], #36]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14132,7 +13811,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #36]\n\t" "adc r4, r4, #0\n\t" "# a[i+10] += m[10] * mu\n\t" - "ldr r7, [%[m], #40]\n\t" + "ldr r7, [%[m], #40]\n\t" "ldr r9, [%[a], #40]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14141,7 +13820,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #40]\n\t" "adc r5, r5, #0\n\t" "# a[i+11] += m[11] * mu\n\t" - "ldr r7, [%[m], #44]\n\t" + "ldr r7, [%[m], #44]\n\t" "ldr r9, [%[a], #44]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14150,7 +13829,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #44]\n\t" "adc r4, r4, #0\n\t" "# a[i+12] += m[12] * mu\n\t" - "ldr r7, [%[m], #48]\n\t" + "ldr r7, [%[m], #48]\n\t" "ldr r9, [%[a], #48]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14159,7 +13838,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #48]\n\t" "adc r5, r5, #0\n\t" "# a[i+13] += m[13] * mu\n\t" - "ldr r7, [%[m], #52]\n\t" + "ldr r7, [%[m], #52]\n\t" "ldr r9, [%[a], #52]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14168,7 +13847,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #52]\n\t" "adc r4, r4, #0\n\t" "# a[i+14] += m[14] * mu\n\t" - "ldr r7, [%[m], #56]\n\t" + "ldr r7, [%[m], #56]\n\t" "ldr r9, [%[a], #56]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14177,7 +13856,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #56]\n\t" "adc r5, r5, #0\n\t" "# a[i+15] += m[15] * mu\n\t" - "ldr r7, [%[m], #60]\n\t" + "ldr r7, [%[m], #60]\n\t" "ldr r9, [%[a], #60]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14186,7 +13865,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #60]\n\t" "adc r4, r4, #0\n\t" "# a[i+16] += m[16] * mu\n\t" - "ldr r7, [%[m], #64]\n\t" + "ldr r7, [%[m], #64]\n\t" "ldr r9, [%[a], #64]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14195,7 +13874,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #64]\n\t" "adc r5, r5, #0\n\t" "# a[i+17] += m[17] * mu\n\t" - "ldr r7, [%[m], #68]\n\t" + "ldr r7, [%[m], #68]\n\t" "ldr r9, [%[a], #68]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14204,7 +13883,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #68]\n\t" "adc r4, r4, #0\n\t" "# a[i+18] += m[18] * mu\n\t" - "ldr r7, [%[m], #72]\n\t" + "ldr r7, [%[m], #72]\n\t" "ldr r9, [%[a], #72]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14213,7 +13892,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #72]\n\t" "adc r5, r5, #0\n\t" "# a[i+19] += m[19] * mu\n\t" - "ldr r7, [%[m], #76]\n\t" + "ldr r7, [%[m], #76]\n\t" "ldr r9, [%[a], #76]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14222,7 +13901,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #76]\n\t" "adc r4, r4, #0\n\t" "# a[i+20] += m[20] * mu\n\t" - "ldr r7, [%[m], #80]\n\t" + "ldr r7, [%[m], #80]\n\t" "ldr r9, [%[a], #80]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14231,7 +13910,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #80]\n\t" "adc r5, r5, #0\n\t" "# a[i+21] += m[21] * mu\n\t" - "ldr r7, [%[m], #84]\n\t" + "ldr r7, [%[m], #84]\n\t" "ldr r9, [%[a], #84]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14240,7 +13919,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #84]\n\t" "adc r4, r4, #0\n\t" "# a[i+22] += m[22] * mu\n\t" - "ldr r7, [%[m], #88]\n\t" + "ldr r7, [%[m], #88]\n\t" "ldr r9, [%[a], #88]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14249,7 +13928,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #88]\n\t" "adc r5, r5, #0\n\t" "# a[i+23] += m[23] * mu\n\t" - "ldr r7, [%[m], #92]\n\t" + "ldr r7, [%[m], #92]\n\t" "ldr r9, [%[a], #92]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14258,7 +13937,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #92]\n\t" "adc r4, r4, #0\n\t" "# a[i+24] += m[24] * mu\n\t" - "ldr r7, [%[m], #96]\n\t" + "ldr r7, [%[m], #96]\n\t" "ldr r9, [%[a], #96]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14267,7 +13946,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #96]\n\t" "adc r5, r5, #0\n\t" "# a[i+25] += m[25] * mu\n\t" - "ldr r7, [%[m], #100]\n\t" + "ldr r7, [%[m], #100]\n\t" "ldr r9, [%[a], #100]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14276,7 +13955,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #100]\n\t" "adc r4, r4, #0\n\t" "# a[i+26] += m[26] * mu\n\t" - "ldr r7, [%[m], #104]\n\t" + "ldr r7, [%[m], #104]\n\t" "ldr r9, [%[a], #104]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14285,7 +13964,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #104]\n\t" "adc r5, r5, #0\n\t" "# a[i+27] += m[27] * mu\n\t" - "ldr r7, [%[m], #108]\n\t" + "ldr r7, [%[m], #108]\n\t" "ldr r9, [%[a], #108]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14294,7 +13973,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #108]\n\t" "adc r4, r4, #0\n\t" "# a[i+28] += m[28] * mu\n\t" - "ldr r7, [%[m], #112]\n\t" + "ldr r7, [%[m], #112]\n\t" "ldr r9, [%[a], #112]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14303,7 +13982,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #112]\n\t" "adc r5, r5, #0\n\t" "# a[i+29] += m[29] * mu\n\t" - "ldr r7, [%[m], #116]\n\t" + "ldr r7, [%[m], #116]\n\t" "ldr r9, [%[a], #116]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14312,7 +13991,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #116]\n\t" "adc r4, r4, #0\n\t" "# a[i+30] += m[30] * mu\n\t" - "ldr r7, [%[m], #120]\n\t" + "ldr r7, [%[m], #120]\n\t" "ldr r9, [%[a], #120]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14321,7 +14000,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #120]\n\t" "adc r5, r5, #0\n\t" "# a[i+31] += m[31] * mu\n\t" - "ldr r7, [%[m], #124]\n\t" + "ldr r7, [%[m], #124]\n\t" "ldr r9, [%[a], #124]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14330,7 +14009,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #124]\n\t" "adc r4, r4, #0\n\t" "# a[i+32] += m[32] * mu\n\t" - "ldr r7, [%[m], #128]\n\t" + "ldr r7, [%[m], #128]\n\t" "ldr r9, [%[a], #128]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14339,7 +14018,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #128]\n\t" "adc r5, r5, #0\n\t" "# a[i+33] += m[33] * mu\n\t" - "ldr r7, [%[m], #132]\n\t" + "ldr r7, [%[m], #132]\n\t" "ldr r9, [%[a], #132]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14348,7 +14027,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #132]\n\t" "adc r4, r4, #0\n\t" "# a[i+34] += m[34] * mu\n\t" - "ldr r7, [%[m], #136]\n\t" + "ldr r7, [%[m], #136]\n\t" "ldr r9, [%[a], #136]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14357,7 +14036,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #136]\n\t" "adc r5, r5, #0\n\t" "# a[i+35] += m[35] * mu\n\t" - "ldr r7, [%[m], #140]\n\t" + "ldr r7, [%[m], #140]\n\t" "ldr r9, [%[a], #140]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14366,7 +14045,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #140]\n\t" "adc r4, r4, #0\n\t" "# a[i+36] += m[36] * mu\n\t" - "ldr r7, [%[m], #144]\n\t" + "ldr r7, [%[m], #144]\n\t" "ldr r9, [%[a], #144]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14375,7 +14054,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #144]\n\t" "adc r5, r5, #0\n\t" "# a[i+37] += m[37] * mu\n\t" - "ldr r7, [%[m], #148]\n\t" + "ldr r7, [%[m], #148]\n\t" "ldr r9, [%[a], #148]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14384,7 +14063,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #148]\n\t" "adc r4, r4, #0\n\t" "# a[i+38] += m[38] * mu\n\t" - "ldr r7, [%[m], #152]\n\t" + "ldr r7, [%[m], #152]\n\t" "ldr r9, [%[a], #152]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14393,7 +14072,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #152]\n\t" "adc r5, r5, #0\n\t" "# a[i+39] += m[39] * mu\n\t" - "ldr r7, [%[m], #156]\n\t" + "ldr r7, [%[m], #156]\n\t" "ldr r9, [%[a], #156]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14402,7 +14081,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #156]\n\t" "adc r4, r4, #0\n\t" "# a[i+40] += m[40] * mu\n\t" - "ldr r7, [%[m], #160]\n\t" + "ldr r7, [%[m], #160]\n\t" "ldr r9, [%[a], #160]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14411,7 +14090,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #160]\n\t" "adc r5, r5, #0\n\t" "# a[i+41] += m[41] * mu\n\t" - "ldr r7, [%[m], #164]\n\t" + "ldr r7, [%[m], #164]\n\t" "ldr r9, [%[a], #164]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14420,7 +14099,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #164]\n\t" "adc r4, r4, #0\n\t" "# a[i+42] += m[42] * mu\n\t" - "ldr r7, [%[m], #168]\n\t" + "ldr r7, [%[m], #168]\n\t" "ldr r9, [%[a], #168]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14429,7 +14108,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #168]\n\t" "adc r5, r5, #0\n\t" "# a[i+43] += m[43] * mu\n\t" - "ldr r7, [%[m], #172]\n\t" + "ldr r7, [%[m], #172]\n\t" "ldr r9, [%[a], #172]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14438,7 +14117,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #172]\n\t" "adc r4, r4, #0\n\t" "# a[i+44] += m[44] * mu\n\t" - "ldr r7, [%[m], #176]\n\t" + "ldr r7, [%[m], #176]\n\t" "ldr r9, [%[a], #176]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14447,7 +14126,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #176]\n\t" "adc r5, r5, #0\n\t" "# a[i+45] += m[45] * mu\n\t" - "ldr r7, [%[m], #180]\n\t" + "ldr r7, [%[m], #180]\n\t" "ldr r9, [%[a], #180]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14456,7 +14135,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r9, [%[a], #180]\n\t" "adc r4, r4, #0\n\t" "# a[i+46] += m[46] * mu\n\t" - "ldr r7, [%[m], #184]\n\t" + "ldr r7, [%[m], #184]\n\t" "ldr r9, [%[a], #184]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -14487,7 +14166,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); @@ -14502,8 +14181,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_48(r, a, b); sp_3072_mont_reduce_48(r, m, mp); @@ -14516,8 +14195,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_48(r, a); sp_3072_mont_reduce_48(r, m, mp); @@ -14570,371 +14249,325 @@ static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #28]\n\t" "# A[8] * B\n\t" "ldr r8, [%[a], #32]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #32]\n\t" "# A[9] * B\n\t" "ldr r8, [%[a], #36]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #36]\n\t" "# A[10] * B\n\t" "ldr r8, [%[a], #40]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #40]\n\t" "# A[11] * B\n\t" "ldr r8, [%[a], #44]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #44]\n\t" "# A[12] * B\n\t" "ldr r8, [%[a], #48]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #48]\n\t" "# A[13] * B\n\t" "ldr r8, [%[a], #52]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #52]\n\t" "# A[14] * B\n\t" "ldr r8, [%[a], #56]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #56]\n\t" "# A[15] * B\n\t" "ldr r8, [%[a], #60]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #60]\n\t" "# A[16] * B\n\t" "ldr r8, [%[a], #64]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #64]\n\t" "# A[17] * B\n\t" "ldr r8, [%[a], #68]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #68]\n\t" "# A[18] * B\n\t" "ldr r8, [%[a], #72]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #72]\n\t" "# A[19] * B\n\t" "ldr r8, [%[a], #76]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #76]\n\t" "# A[20] * B\n\t" "ldr r8, [%[a], #80]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[21] * B\n\t" "ldr r8, [%[a], #84]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[22] * B\n\t" "ldr r8, [%[a], #88]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #88]\n\t" "# A[23] * B\n\t" "ldr r8, [%[a], #92]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #92]\n\t" "# A[24] * B\n\t" "ldr r8, [%[a], #96]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #96]\n\t" "# A[25] * B\n\t" "ldr r8, [%[a], #100]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #100]\n\t" "# A[26] * B\n\t" "ldr r8, [%[a], #104]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #104]\n\t" "# A[27] * B\n\t" "ldr r8, [%[a], #108]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #108]\n\t" "# A[28] * B\n\t" "ldr r8, [%[a], #112]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #112]\n\t" "# A[29] * B\n\t" "ldr r8, [%[a], #116]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #116]\n\t" "# A[30] * B\n\t" "ldr r8, [%[a], #120]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #120]\n\t" "# A[31] * B\n\t" "ldr r8, [%[a], #124]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #124]\n\t" "# A[32] * B\n\t" "ldr r8, [%[a], #128]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #128]\n\t" "# A[33] * B\n\t" "ldr r8, [%[a], #132]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #132]\n\t" "# A[34] * B\n\t" "ldr r8, [%[a], #136]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #136]\n\t" "# A[35] * B\n\t" "ldr r8, [%[a], #140]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #140]\n\t" "# A[36] * B\n\t" "ldr r8, [%[a], #144]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #144]\n\t" "# A[37] * B\n\t" "ldr r8, [%[a], #148]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #148]\n\t" "# A[38] * B\n\t" "ldr r8, [%[a], #152]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #152]\n\t" "# A[39] * B\n\t" "ldr r8, [%[a], #156]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #156]\n\t" "# A[40] * B\n\t" "ldr r8, [%[a], #160]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #160]\n\t" "# A[41] * B\n\t" "ldr r8, [%[a], #164]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #164]\n\t" "# A[42] * B\n\t" "ldr r8, [%[a], #168]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #168]\n\t" "# A[43] * B\n\t" "ldr r8, [%[a], #172]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #172]\n\t" "# A[44] * B\n\t" "ldr r8, [%[a], #176]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #176]\n\t" "# A[45] * B\n\t" "ldr r8, [%[a], #180]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #180]\n\t" "# A[46] * B\n\t" "ldr r8, [%[a], #184]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #184]\n\t" "# A[47] * B\n\t" "ldr r8, [%[a], #188]\n\t" @@ -15657,35 +15290,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 96]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -15733,34 +15362,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -15781,9 +15410,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -15802,35 +15430,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 96]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -15894,34 +15518,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -15943,16 +15567,15 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -15969,7 +15592,7 @@ static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m) sp_3072_sub_in_place_96(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -16508,6 +16131,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -16516,13 +16140,12 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -16530,7 +16153,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -16538,7 +16161,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16547,7 +16170,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16556,7 +16179,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16565,7 +16188,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16574,7 +16197,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #24]\n\t" "adc r5, r5, #0\n\t" "# a[i+7] += m[7] * mu\n\t" - "ldr r7, [%[m], #28]\n\t" + "ldr r7, [%[m], #28]\n\t" "ldr r9, [%[a], #28]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16583,7 +16206,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #28]\n\t" "adc r4, r4, #0\n\t" "# a[i+8] += m[8] * mu\n\t" - "ldr r7, [%[m], #32]\n\t" + "ldr r7, [%[m], #32]\n\t" "ldr r9, [%[a], #32]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16592,7 +16215,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #32]\n\t" "adc r5, r5, #0\n\t" "# a[i+9] += m[9] * mu\n\t" - "ldr r7, [%[m], #36]\n\t" + "ldr r7, [%[m], #36]\n\t" "ldr r9, [%[a], #36]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16601,7 +16224,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #36]\n\t" "adc r4, r4, #0\n\t" "# a[i+10] += m[10] * mu\n\t" - "ldr r7, [%[m], #40]\n\t" + "ldr r7, [%[m], #40]\n\t" "ldr r9, [%[a], #40]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16610,7 +16233,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #40]\n\t" "adc r5, r5, #0\n\t" "# a[i+11] += m[11] * mu\n\t" - "ldr r7, [%[m], #44]\n\t" + "ldr r7, [%[m], #44]\n\t" "ldr r9, [%[a], #44]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16619,7 +16242,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #44]\n\t" "adc r4, r4, #0\n\t" "# a[i+12] += m[12] * mu\n\t" - "ldr r7, [%[m], #48]\n\t" + "ldr r7, [%[m], #48]\n\t" "ldr r9, [%[a], #48]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16628,7 +16251,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #48]\n\t" "adc r5, r5, #0\n\t" "# a[i+13] += m[13] * mu\n\t" - "ldr r7, [%[m], #52]\n\t" + "ldr r7, [%[m], #52]\n\t" "ldr r9, [%[a], #52]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16637,7 +16260,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #52]\n\t" "adc r4, r4, #0\n\t" "# a[i+14] += m[14] * mu\n\t" - "ldr r7, [%[m], #56]\n\t" + "ldr r7, [%[m], #56]\n\t" "ldr r9, [%[a], #56]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16646,7 +16269,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #56]\n\t" "adc r5, r5, #0\n\t" "# a[i+15] += m[15] * mu\n\t" - "ldr r7, [%[m], #60]\n\t" + "ldr r7, [%[m], #60]\n\t" "ldr r9, [%[a], #60]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16655,7 +16278,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #60]\n\t" "adc r4, r4, #0\n\t" "# a[i+16] += m[16] * mu\n\t" - "ldr r7, [%[m], #64]\n\t" + "ldr r7, [%[m], #64]\n\t" "ldr r9, [%[a], #64]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16664,7 +16287,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #64]\n\t" "adc r5, r5, #0\n\t" "# a[i+17] += m[17] * mu\n\t" - "ldr r7, [%[m], #68]\n\t" + "ldr r7, [%[m], #68]\n\t" "ldr r9, [%[a], #68]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16673,7 +16296,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #68]\n\t" "adc r4, r4, #0\n\t" "# a[i+18] += m[18] * mu\n\t" - "ldr r7, [%[m], #72]\n\t" + "ldr r7, [%[m], #72]\n\t" "ldr r9, [%[a], #72]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16682,7 +16305,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #72]\n\t" "adc r5, r5, #0\n\t" "# a[i+19] += m[19] * mu\n\t" - "ldr r7, [%[m], #76]\n\t" + "ldr r7, [%[m], #76]\n\t" "ldr r9, [%[a], #76]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16691,7 +16314,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #76]\n\t" "adc r4, r4, #0\n\t" "# a[i+20] += m[20] * mu\n\t" - "ldr r7, [%[m], #80]\n\t" + "ldr r7, [%[m], #80]\n\t" "ldr r9, [%[a], #80]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16700,7 +16323,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #80]\n\t" "adc r5, r5, #0\n\t" "# a[i+21] += m[21] * mu\n\t" - "ldr r7, [%[m], #84]\n\t" + "ldr r7, [%[m], #84]\n\t" "ldr r9, [%[a], #84]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16709,7 +16332,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #84]\n\t" "adc r4, r4, #0\n\t" "# a[i+22] += m[22] * mu\n\t" - "ldr r7, [%[m], #88]\n\t" + "ldr r7, [%[m], #88]\n\t" "ldr r9, [%[a], #88]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16718,7 +16341,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #88]\n\t" "adc r5, r5, #0\n\t" "# a[i+23] += m[23] * mu\n\t" - "ldr r7, [%[m], #92]\n\t" + "ldr r7, [%[m], #92]\n\t" "ldr r9, [%[a], #92]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16727,7 +16350,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #92]\n\t" "adc r4, r4, #0\n\t" "# a[i+24] += m[24] * mu\n\t" - "ldr r7, [%[m], #96]\n\t" + "ldr r7, [%[m], #96]\n\t" "ldr r9, [%[a], #96]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16736,7 +16359,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #96]\n\t" "adc r5, r5, #0\n\t" "# a[i+25] += m[25] * mu\n\t" - "ldr r7, [%[m], #100]\n\t" + "ldr r7, [%[m], #100]\n\t" "ldr r9, [%[a], #100]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16745,7 +16368,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #100]\n\t" "adc r4, r4, #0\n\t" "# a[i+26] += m[26] * mu\n\t" - "ldr r7, [%[m], #104]\n\t" + "ldr r7, [%[m], #104]\n\t" "ldr r9, [%[a], #104]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16754,7 +16377,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #104]\n\t" "adc r5, r5, #0\n\t" "# a[i+27] += m[27] * mu\n\t" - "ldr r7, [%[m], #108]\n\t" + "ldr r7, [%[m], #108]\n\t" "ldr r9, [%[a], #108]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16763,7 +16386,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #108]\n\t" "adc r4, r4, #0\n\t" "# a[i+28] += m[28] * mu\n\t" - "ldr r7, [%[m], #112]\n\t" + "ldr r7, [%[m], #112]\n\t" "ldr r9, [%[a], #112]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16772,7 +16395,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #112]\n\t" "adc r5, r5, #0\n\t" "# a[i+29] += m[29] * mu\n\t" - "ldr r7, [%[m], #116]\n\t" + "ldr r7, [%[m], #116]\n\t" "ldr r9, [%[a], #116]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16781,7 +16404,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #116]\n\t" "adc r4, r4, #0\n\t" "# a[i+30] += m[30] * mu\n\t" - "ldr r7, [%[m], #120]\n\t" + "ldr r7, [%[m], #120]\n\t" "ldr r9, [%[a], #120]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16790,7 +16413,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #120]\n\t" "adc r5, r5, #0\n\t" "# a[i+31] += m[31] * mu\n\t" - "ldr r7, [%[m], #124]\n\t" + "ldr r7, [%[m], #124]\n\t" "ldr r9, [%[a], #124]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16799,7 +16422,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #124]\n\t" "adc r4, r4, #0\n\t" "# a[i+32] += m[32] * mu\n\t" - "ldr r7, [%[m], #128]\n\t" + "ldr r7, [%[m], #128]\n\t" "ldr r9, [%[a], #128]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16808,7 +16431,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #128]\n\t" "adc r5, r5, #0\n\t" "# a[i+33] += m[33] * mu\n\t" - "ldr r7, [%[m], #132]\n\t" + "ldr r7, [%[m], #132]\n\t" "ldr r9, [%[a], #132]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16817,7 +16440,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #132]\n\t" "adc r4, r4, #0\n\t" "# a[i+34] += m[34] * mu\n\t" - "ldr r7, [%[m], #136]\n\t" + "ldr r7, [%[m], #136]\n\t" "ldr r9, [%[a], #136]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16826,7 +16449,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #136]\n\t" "adc r5, r5, #0\n\t" "# a[i+35] += m[35] * mu\n\t" - "ldr r7, [%[m], #140]\n\t" + "ldr r7, [%[m], #140]\n\t" "ldr r9, [%[a], #140]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16835,7 +16458,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #140]\n\t" "adc r4, r4, #0\n\t" "# a[i+36] += m[36] * mu\n\t" - "ldr r7, [%[m], #144]\n\t" + "ldr r7, [%[m], #144]\n\t" "ldr r9, [%[a], #144]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16844,7 +16467,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #144]\n\t" "adc r5, r5, #0\n\t" "# a[i+37] += m[37] * mu\n\t" - "ldr r7, [%[m], #148]\n\t" + "ldr r7, [%[m], #148]\n\t" "ldr r9, [%[a], #148]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16853,7 +16476,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #148]\n\t" "adc r4, r4, #0\n\t" "# a[i+38] += m[38] * mu\n\t" - "ldr r7, [%[m], #152]\n\t" + "ldr r7, [%[m], #152]\n\t" "ldr r9, [%[a], #152]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16862,7 +16485,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #152]\n\t" "adc r5, r5, #0\n\t" "# a[i+39] += m[39] * mu\n\t" - "ldr r7, [%[m], #156]\n\t" + "ldr r7, [%[m], #156]\n\t" "ldr r9, [%[a], #156]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16871,7 +16494,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #156]\n\t" "adc r4, r4, #0\n\t" "# a[i+40] += m[40] * mu\n\t" - "ldr r7, [%[m], #160]\n\t" + "ldr r7, [%[m], #160]\n\t" "ldr r9, [%[a], #160]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16880,7 +16503,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #160]\n\t" "adc r5, r5, #0\n\t" "# a[i+41] += m[41] * mu\n\t" - "ldr r7, [%[m], #164]\n\t" + "ldr r7, [%[m], #164]\n\t" "ldr r9, [%[a], #164]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16889,7 +16512,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #164]\n\t" "adc r4, r4, #0\n\t" "# a[i+42] += m[42] * mu\n\t" - "ldr r7, [%[m], #168]\n\t" + "ldr r7, [%[m], #168]\n\t" "ldr r9, [%[a], #168]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16898,7 +16521,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #168]\n\t" "adc r5, r5, #0\n\t" "# a[i+43] += m[43] * mu\n\t" - "ldr r7, [%[m], #172]\n\t" + "ldr r7, [%[m], #172]\n\t" "ldr r9, [%[a], #172]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16907,7 +16530,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #172]\n\t" "adc r4, r4, #0\n\t" "# a[i+44] += m[44] * mu\n\t" - "ldr r7, [%[m], #176]\n\t" + "ldr r7, [%[m], #176]\n\t" "ldr r9, [%[a], #176]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16916,7 +16539,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #176]\n\t" "adc r5, r5, #0\n\t" "# a[i+45] += m[45] * mu\n\t" - "ldr r7, [%[m], #180]\n\t" + "ldr r7, [%[m], #180]\n\t" "ldr r9, [%[a], #180]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16925,7 +16548,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #180]\n\t" "adc r4, r4, #0\n\t" "# a[i+46] += m[46] * mu\n\t" - "ldr r7, [%[m], #184]\n\t" + "ldr r7, [%[m], #184]\n\t" "ldr r9, [%[a], #184]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16934,7 +16557,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #184]\n\t" "adc r5, r5, #0\n\t" "# a[i+47] += m[47] * mu\n\t" - "ldr r7, [%[m], #188]\n\t" + "ldr r7, [%[m], #188]\n\t" "ldr r9, [%[a], #188]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16943,7 +16566,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #188]\n\t" "adc r4, r4, #0\n\t" "# a[i+48] += m[48] * mu\n\t" - "ldr r7, [%[m], #192]\n\t" + "ldr r7, [%[m], #192]\n\t" "ldr r9, [%[a], #192]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16952,7 +16575,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #192]\n\t" "adc r5, r5, #0\n\t" "# a[i+49] += m[49] * mu\n\t" - "ldr r7, [%[m], #196]\n\t" + "ldr r7, [%[m], #196]\n\t" "ldr r9, [%[a], #196]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16961,7 +16584,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #196]\n\t" "adc r4, r4, #0\n\t" "# a[i+50] += m[50] * mu\n\t" - "ldr r7, [%[m], #200]\n\t" + "ldr r7, [%[m], #200]\n\t" "ldr r9, [%[a], #200]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16970,7 +16593,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #200]\n\t" "adc r5, r5, #0\n\t" "# a[i+51] += m[51] * mu\n\t" - "ldr r7, [%[m], #204]\n\t" + "ldr r7, [%[m], #204]\n\t" "ldr r9, [%[a], #204]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16979,7 +16602,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #204]\n\t" "adc r4, r4, #0\n\t" "# a[i+52] += m[52] * mu\n\t" - "ldr r7, [%[m], #208]\n\t" + "ldr r7, [%[m], #208]\n\t" "ldr r9, [%[a], #208]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16988,7 +16611,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #208]\n\t" "adc r5, r5, #0\n\t" "# a[i+53] += m[53] * mu\n\t" - "ldr r7, [%[m], #212]\n\t" + "ldr r7, [%[m], #212]\n\t" "ldr r9, [%[a], #212]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -16997,7 +16620,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #212]\n\t" "adc r4, r4, #0\n\t" "# a[i+54] += m[54] * mu\n\t" - "ldr r7, [%[m], #216]\n\t" + "ldr r7, [%[m], #216]\n\t" "ldr r9, [%[a], #216]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17006,7 +16629,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #216]\n\t" "adc r5, r5, #0\n\t" "# a[i+55] += m[55] * mu\n\t" - "ldr r7, [%[m], #220]\n\t" + "ldr r7, [%[m], #220]\n\t" "ldr r9, [%[a], #220]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17015,7 +16638,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #220]\n\t" "adc r4, r4, #0\n\t" "# a[i+56] += m[56] * mu\n\t" - "ldr r7, [%[m], #224]\n\t" + "ldr r7, [%[m], #224]\n\t" "ldr r9, [%[a], #224]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17024,7 +16647,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #224]\n\t" "adc r5, r5, #0\n\t" "# a[i+57] += m[57] * mu\n\t" - "ldr r7, [%[m], #228]\n\t" + "ldr r7, [%[m], #228]\n\t" "ldr r9, [%[a], #228]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17033,7 +16656,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #228]\n\t" "adc r4, r4, #0\n\t" "# a[i+58] += m[58] * mu\n\t" - "ldr r7, [%[m], #232]\n\t" + "ldr r7, [%[m], #232]\n\t" "ldr r9, [%[a], #232]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17042,7 +16665,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #232]\n\t" "adc r5, r5, #0\n\t" "# a[i+59] += m[59] * mu\n\t" - "ldr r7, [%[m], #236]\n\t" + "ldr r7, [%[m], #236]\n\t" "ldr r9, [%[a], #236]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17051,7 +16674,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #236]\n\t" "adc r4, r4, #0\n\t" "# a[i+60] += m[60] * mu\n\t" - "ldr r7, [%[m], #240]\n\t" + "ldr r7, [%[m], #240]\n\t" "ldr r9, [%[a], #240]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17060,7 +16683,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #240]\n\t" "adc r5, r5, #0\n\t" "# a[i+61] += m[61] * mu\n\t" - "ldr r7, [%[m], #244]\n\t" + "ldr r7, [%[m], #244]\n\t" "ldr r9, [%[a], #244]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17069,7 +16692,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #244]\n\t" "adc r4, r4, #0\n\t" "# a[i+62] += m[62] * mu\n\t" - "ldr r7, [%[m], #248]\n\t" + "ldr r7, [%[m], #248]\n\t" "ldr r9, [%[a], #248]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17078,7 +16701,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #248]\n\t" "adc r5, r5, #0\n\t" "# a[i+63] += m[63] * mu\n\t" - "ldr r7, [%[m], #252]\n\t" + "ldr r7, [%[m], #252]\n\t" "ldr r9, [%[a], #252]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17087,7 +16710,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #252]\n\t" "adc r4, r4, #0\n\t" "# a[i+64] += m[64] * mu\n\t" - "ldr r7, [%[m], #256]\n\t" + "ldr r7, [%[m], #256]\n\t" "ldr r9, [%[a], #256]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17096,7 +16719,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #256]\n\t" "adc r5, r5, #0\n\t" "# a[i+65] += m[65] * mu\n\t" - "ldr r7, [%[m], #260]\n\t" + "ldr r7, [%[m], #260]\n\t" "ldr r9, [%[a], #260]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17105,7 +16728,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #260]\n\t" "adc r4, r4, #0\n\t" "# a[i+66] += m[66] * mu\n\t" - "ldr r7, [%[m], #264]\n\t" + "ldr r7, [%[m], #264]\n\t" "ldr r9, [%[a], #264]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17114,7 +16737,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #264]\n\t" "adc r5, r5, #0\n\t" "# a[i+67] += m[67] * mu\n\t" - "ldr r7, [%[m], #268]\n\t" + "ldr r7, [%[m], #268]\n\t" "ldr r9, [%[a], #268]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17123,7 +16746,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #268]\n\t" "adc r4, r4, #0\n\t" "# a[i+68] += m[68] * mu\n\t" - "ldr r7, [%[m], #272]\n\t" + "ldr r7, [%[m], #272]\n\t" "ldr r9, [%[a], #272]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17132,7 +16755,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #272]\n\t" "adc r5, r5, #0\n\t" "# a[i+69] += m[69] * mu\n\t" - "ldr r7, [%[m], #276]\n\t" + "ldr r7, [%[m], #276]\n\t" "ldr r9, [%[a], #276]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17141,7 +16764,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #276]\n\t" "adc r4, r4, #0\n\t" "# a[i+70] += m[70] * mu\n\t" - "ldr r7, [%[m], #280]\n\t" + "ldr r7, [%[m], #280]\n\t" "ldr r9, [%[a], #280]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17150,7 +16773,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #280]\n\t" "adc r5, r5, #0\n\t" "# a[i+71] += m[71] * mu\n\t" - "ldr r7, [%[m], #284]\n\t" + "ldr r7, [%[m], #284]\n\t" "ldr r9, [%[a], #284]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17159,7 +16782,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #284]\n\t" "adc r4, r4, #0\n\t" "# a[i+72] += m[72] * mu\n\t" - "ldr r7, [%[m], #288]\n\t" + "ldr r7, [%[m], #288]\n\t" "ldr r9, [%[a], #288]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17168,7 +16791,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #288]\n\t" "adc r5, r5, #0\n\t" "# a[i+73] += m[73] * mu\n\t" - "ldr r7, [%[m], #292]\n\t" + "ldr r7, [%[m], #292]\n\t" "ldr r9, [%[a], #292]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17177,7 +16800,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #292]\n\t" "adc r4, r4, #0\n\t" "# a[i+74] += m[74] * mu\n\t" - "ldr r7, [%[m], #296]\n\t" + "ldr r7, [%[m], #296]\n\t" "ldr r9, [%[a], #296]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17186,7 +16809,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #296]\n\t" "adc r5, r5, #0\n\t" "# a[i+75] += m[75] * mu\n\t" - "ldr r7, [%[m], #300]\n\t" + "ldr r7, [%[m], #300]\n\t" "ldr r9, [%[a], #300]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17195,7 +16818,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #300]\n\t" "adc r4, r4, #0\n\t" "# a[i+76] += m[76] * mu\n\t" - "ldr r7, [%[m], #304]\n\t" + "ldr r7, [%[m], #304]\n\t" "ldr r9, [%[a], #304]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17204,7 +16827,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #304]\n\t" "adc r5, r5, #0\n\t" "# a[i+77] += m[77] * mu\n\t" - "ldr r7, [%[m], #308]\n\t" + "ldr r7, [%[m], #308]\n\t" "ldr r9, [%[a], #308]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17213,7 +16836,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #308]\n\t" "adc r4, r4, #0\n\t" "# a[i+78] += m[78] * mu\n\t" - "ldr r7, [%[m], #312]\n\t" + "ldr r7, [%[m], #312]\n\t" "ldr r9, [%[a], #312]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17222,7 +16845,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #312]\n\t" "adc r5, r5, #0\n\t" "# a[i+79] += m[79] * mu\n\t" - "ldr r7, [%[m], #316]\n\t" + "ldr r7, [%[m], #316]\n\t" "ldr r9, [%[a], #316]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17231,7 +16854,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #316]\n\t" "adc r4, r4, #0\n\t" "# a[i+80] += m[80] * mu\n\t" - "ldr r7, [%[m], #320]\n\t" + "ldr r7, [%[m], #320]\n\t" "ldr r9, [%[a], #320]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17240,7 +16863,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #320]\n\t" "adc r5, r5, #0\n\t" "# a[i+81] += m[81] * mu\n\t" - "ldr r7, [%[m], #324]\n\t" + "ldr r7, [%[m], #324]\n\t" "ldr r9, [%[a], #324]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17249,7 +16872,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #324]\n\t" "adc r4, r4, #0\n\t" "# a[i+82] += m[82] * mu\n\t" - "ldr r7, [%[m], #328]\n\t" + "ldr r7, [%[m], #328]\n\t" "ldr r9, [%[a], #328]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17258,7 +16881,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #328]\n\t" "adc r5, r5, #0\n\t" "# a[i+83] += m[83] * mu\n\t" - "ldr r7, [%[m], #332]\n\t" + "ldr r7, [%[m], #332]\n\t" "ldr r9, [%[a], #332]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17267,7 +16890,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #332]\n\t" "adc r4, r4, #0\n\t" "# a[i+84] += m[84] * mu\n\t" - "ldr r7, [%[m], #336]\n\t" + "ldr r7, [%[m], #336]\n\t" "ldr r9, [%[a], #336]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17276,7 +16899,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #336]\n\t" "adc r5, r5, #0\n\t" "# a[i+85] += m[85] * mu\n\t" - "ldr r7, [%[m], #340]\n\t" + "ldr r7, [%[m], #340]\n\t" "ldr r9, [%[a], #340]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17285,7 +16908,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #340]\n\t" "adc r4, r4, #0\n\t" "# a[i+86] += m[86] * mu\n\t" - "ldr r7, [%[m], #344]\n\t" + "ldr r7, [%[m], #344]\n\t" "ldr r9, [%[a], #344]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17294,7 +16917,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #344]\n\t" "adc r5, r5, #0\n\t" "# a[i+87] += m[87] * mu\n\t" - "ldr r7, [%[m], #348]\n\t" + "ldr r7, [%[m], #348]\n\t" "ldr r9, [%[a], #348]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17303,7 +16926,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #348]\n\t" "adc r4, r4, #0\n\t" "# a[i+88] += m[88] * mu\n\t" - "ldr r7, [%[m], #352]\n\t" + "ldr r7, [%[m], #352]\n\t" "ldr r9, [%[a], #352]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17312,7 +16935,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #352]\n\t" "adc r5, r5, #0\n\t" "# a[i+89] += m[89] * mu\n\t" - "ldr r7, [%[m], #356]\n\t" + "ldr r7, [%[m], #356]\n\t" "ldr r9, [%[a], #356]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17321,7 +16944,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #356]\n\t" "adc r4, r4, #0\n\t" "# a[i+90] += m[90] * mu\n\t" - "ldr r7, [%[m], #360]\n\t" + "ldr r7, [%[m], #360]\n\t" "ldr r9, [%[a], #360]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17330,7 +16953,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #360]\n\t" "adc r5, r5, #0\n\t" "# a[i+91] += m[91] * mu\n\t" - "ldr r7, [%[m], #364]\n\t" + "ldr r7, [%[m], #364]\n\t" "ldr r9, [%[a], #364]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17339,7 +16962,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #364]\n\t" "adc r4, r4, #0\n\t" "# a[i+92] += m[92] * mu\n\t" - "ldr r7, [%[m], #368]\n\t" + "ldr r7, [%[m], #368]\n\t" "ldr r9, [%[a], #368]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17348,7 +16971,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #368]\n\t" "adc r5, r5, #0\n\t" "# a[i+93] += m[93] * mu\n\t" - "ldr r7, [%[m], #372]\n\t" + "ldr r7, [%[m], #372]\n\t" "ldr r9, [%[a], #372]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17357,7 +16980,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r9, [%[a], #372]\n\t" "adc r4, r4, #0\n\t" "# a[i+94] += m[94] * mu\n\t" - "ldr r7, [%[m], #376]\n\t" + "ldr r7, [%[m], #376]\n\t" "ldr r9, [%[a], #376]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -17388,7 +17011,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca); @@ -17403,8 +17026,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_96(r, a, b); sp_3072_mont_reduce_96(r, m, mp); @@ -17417,8 +17040,8 @@ static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_96(r, a); sp_3072_mont_reduce_96(r, m, mp); @@ -18746,35 +18369,31 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 192]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 192), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 192; -#else - t[i] = &td[i * 192]; -#endif } sp_3072_mont_setup(m, &mp); @@ -18822,34 +18441,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 96); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -18870,9 +18489,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -18891,35 +18509,31 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 192]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 192), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 192; -#else - t[i] = &td[i * 192]; -#endif } sp_3072_mont_setup(m, &mp); @@ -18983,34 +18597,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 96); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -19032,9 +18646,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -19055,19 +18668,18 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[192], m[96], r[192]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[96 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 384) { @@ -19081,22 +18693,18 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 96 * 2; - m = r + 96 * 2; - } #endif if (err == MP_OKAY) { + r = a + 96 * 2; + m = r + 96 * 2; ah = a + 96; sp_3072_from_bin(ah, 96, in, inLen); @@ -19169,10 +18777,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -19482,13 +19089,17 @@ static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_dig * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[96 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -19517,13 +19128,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 96; m = a + 192; @@ -19534,31 +19147,36 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_3072_from_mp(m, 96, mm); err = sp_3072_mod_exp_96(r, a, d, 3072, m, 0); } + if (err == MP_OKAY) { sp_3072_to_bin(r, out); *outLen = 384; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 96); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 96); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[96 * 2]; - sp_digit p[48], q[48], dp[48]; - sp_digit tmpa[96], tmpb[96]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[48 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -19578,31 +19196,23 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 96 * 2; q = p + 48; qi = dq = dp = q + 48; tmpa = qi + 48; tmpb = tmpa + 96; - - r = t + 96; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_3072_from_bin(a, 96, in, inLen); sp_3072_from_mp(p, 48, pm); sp_3072_from_mp(q, 48, qm); @@ -19634,18 +19244,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 48 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -19669,17 +19276,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 96; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 96; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -19692,14 +19301,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 96; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -19726,10 +19337,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[192], e[96], m[96]; + sp_digit b[192]; + sp_digit e[96]; + sp_digit m[96]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -20365,34 +19979,31 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[289]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 192; -#else - tmp = &td[192]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_96(norm, m); @@ -20410,34 +20021,34 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_3072_lshift_96(r, norm, (byte)y); + sp_3072_lshift_96(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -20448,7 +20059,7 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, sp_3072_mont_sqr_96(r, r, m, mp); sp_3072_mont_sqr_96(r, r, m, mp); - sp_3072_lshift_96(r, r, (byte)y); + sp_3072_lshift_96(r, r, y); sp_3072_mul_d_96(tmp, norm, r[96]); r[96] = 0; o = sp_3072_add_96(r, r, tmp); @@ -20463,9 +20074,8 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -20484,11 +20094,13 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[192], e[96], m[96]; + sp_digit b[192]; + sp_digit e[96]; + sp_digit m[96]; sp_digit* r = b; word32 i; @@ -20523,6 +20135,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -20544,10 +20157,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -20584,7 +20200,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -20598,7 +20214,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -20640,7 +20257,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -20674,7 +20292,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -20713,7 +20333,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_4096_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 4096 / 8 - 1; a[j] = 0; @@ -21822,7 +21445,9 @@ SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, sp_digit a1[64]; sp_digit b1[64]; sp_digit z2[128]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_64(a1, a, &a[64]); cb = sp_2048_add_64(b1, b, &b[64]); @@ -22101,7 +21726,8 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -22110,7 +21736,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -22160,1011 +21786,885 @@ static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #28]\n\t" "# A[8] * B\n\t" "ldr r8, [%[a], #32]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #32]\n\t" "# A[9] * B\n\t" "ldr r8, [%[a], #36]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #36]\n\t" "# A[10] * B\n\t" "ldr r8, [%[a], #40]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #40]\n\t" "# A[11] * B\n\t" "ldr r8, [%[a], #44]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #44]\n\t" "# A[12] * B\n\t" "ldr r8, [%[a], #48]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #48]\n\t" "# A[13] * B\n\t" "ldr r8, [%[a], #52]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #52]\n\t" "# A[14] * B\n\t" "ldr r8, [%[a], #56]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #56]\n\t" "# A[15] * B\n\t" "ldr r8, [%[a], #60]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #60]\n\t" "# A[16] * B\n\t" "ldr r8, [%[a], #64]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #64]\n\t" "# A[17] * B\n\t" "ldr r8, [%[a], #68]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #68]\n\t" "# A[18] * B\n\t" "ldr r8, [%[a], #72]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #72]\n\t" "# A[19] * B\n\t" "ldr r8, [%[a], #76]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #76]\n\t" "# A[20] * B\n\t" "ldr r8, [%[a], #80]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[21] * B\n\t" "ldr r8, [%[a], #84]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[22] * B\n\t" "ldr r8, [%[a], #88]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #88]\n\t" "# A[23] * B\n\t" "ldr r8, [%[a], #92]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #92]\n\t" "# A[24] * B\n\t" "ldr r8, [%[a], #96]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #96]\n\t" "# A[25] * B\n\t" "ldr r8, [%[a], #100]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #100]\n\t" "# A[26] * B\n\t" "ldr r8, [%[a], #104]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #104]\n\t" "# A[27] * B\n\t" "ldr r8, [%[a], #108]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #108]\n\t" "# A[28] * B\n\t" "ldr r8, [%[a], #112]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #112]\n\t" "# A[29] * B\n\t" "ldr r8, [%[a], #116]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #116]\n\t" "# A[30] * B\n\t" "ldr r8, [%[a], #120]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #120]\n\t" "# A[31] * B\n\t" "ldr r8, [%[a], #124]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #124]\n\t" "# A[32] * B\n\t" "ldr r8, [%[a], #128]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #128]\n\t" "# A[33] * B\n\t" "ldr r8, [%[a], #132]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #132]\n\t" "# A[34] * B\n\t" "ldr r8, [%[a], #136]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #136]\n\t" "# A[35] * B\n\t" "ldr r8, [%[a], #140]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #140]\n\t" "# A[36] * B\n\t" "ldr r8, [%[a], #144]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #144]\n\t" "# A[37] * B\n\t" "ldr r8, [%[a], #148]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #148]\n\t" "# A[38] * B\n\t" "ldr r8, [%[a], #152]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #152]\n\t" "# A[39] * B\n\t" "ldr r8, [%[a], #156]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #156]\n\t" "# A[40] * B\n\t" "ldr r8, [%[a], #160]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #160]\n\t" "# A[41] * B\n\t" "ldr r8, [%[a], #164]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #164]\n\t" "# A[42] * B\n\t" "ldr r8, [%[a], #168]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #168]\n\t" "# A[43] * B\n\t" "ldr r8, [%[a], #172]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #172]\n\t" "# A[44] * B\n\t" "ldr r8, [%[a], #176]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #176]\n\t" "# A[45] * B\n\t" "ldr r8, [%[a], #180]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #180]\n\t" "# A[46] * B\n\t" "ldr r8, [%[a], #184]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #184]\n\t" "# A[47] * B\n\t" "ldr r8, [%[a], #188]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #188]\n\t" "# A[48] * B\n\t" "ldr r8, [%[a], #192]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #192]\n\t" "# A[49] * B\n\t" "ldr r8, [%[a], #196]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #196]\n\t" "# A[50] * B\n\t" "ldr r8, [%[a], #200]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #200]\n\t" "# A[51] * B\n\t" "ldr r8, [%[a], #204]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #204]\n\t" "# A[52] * B\n\t" "ldr r8, [%[a], #208]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #208]\n\t" "# A[53] * B\n\t" "ldr r8, [%[a], #212]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #212]\n\t" "# A[54] * B\n\t" "ldr r8, [%[a], #216]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #216]\n\t" "# A[55] * B\n\t" "ldr r8, [%[a], #220]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #220]\n\t" "# A[56] * B\n\t" "ldr r8, [%[a], #224]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #224]\n\t" "# A[57] * B\n\t" "ldr r8, [%[a], #228]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #228]\n\t" "# A[58] * B\n\t" "ldr r8, [%[a], #232]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #232]\n\t" "# A[59] * B\n\t" "ldr r8, [%[a], #236]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #236]\n\t" "# A[60] * B\n\t" "ldr r8, [%[a], #240]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #240]\n\t" "# A[61] * B\n\t" "ldr r8, [%[a], #244]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #244]\n\t" "# A[62] * B\n\t" "ldr r8, [%[a], #248]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #248]\n\t" "# A[63] * B\n\t" "ldr r8, [%[a], #252]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #252]\n\t" "# A[64] * B\n\t" "ldr r8, [%[a], #256]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #256]\n\t" "# A[65] * B\n\t" "ldr r8, [%[a], #260]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #260]\n\t" "# A[66] * B\n\t" "ldr r8, [%[a], #264]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #264]\n\t" "# A[67] * B\n\t" "ldr r8, [%[a], #268]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #268]\n\t" "# A[68] * B\n\t" "ldr r8, [%[a], #272]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #272]\n\t" "# A[69] * B\n\t" "ldr r8, [%[a], #276]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #276]\n\t" "# A[70] * B\n\t" "ldr r8, [%[a], #280]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #280]\n\t" "# A[71] * B\n\t" "ldr r8, [%[a], #284]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #284]\n\t" "# A[72] * B\n\t" "ldr r8, [%[a], #288]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #288]\n\t" "# A[73] * B\n\t" "ldr r8, [%[a], #292]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #292]\n\t" "# A[74] * B\n\t" "ldr r8, [%[a], #296]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #296]\n\t" "# A[75] * B\n\t" "ldr r8, [%[a], #300]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #300]\n\t" "# A[76] * B\n\t" "ldr r8, [%[a], #304]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #304]\n\t" "# A[77] * B\n\t" "ldr r8, [%[a], #308]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #308]\n\t" "# A[78] * B\n\t" "ldr r8, [%[a], #312]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #312]\n\t" "# A[79] * B\n\t" "ldr r8, [%[a], #316]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #316]\n\t" "# A[80] * B\n\t" "ldr r8, [%[a], #320]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #320]\n\t" "# A[81] * B\n\t" "ldr r8, [%[a], #324]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #324]\n\t" "# A[82] * B\n\t" "ldr r8, [%[a], #328]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #328]\n\t" "# A[83] * B\n\t" "ldr r8, [%[a], #332]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #332]\n\t" "# A[84] * B\n\t" "ldr r8, [%[a], #336]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #336]\n\t" "# A[85] * B\n\t" "ldr r8, [%[a], #340]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #340]\n\t" "# A[86] * B\n\t" "ldr r8, [%[a], #344]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #344]\n\t" "# A[87] * B\n\t" "ldr r8, [%[a], #348]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #348]\n\t" "# A[88] * B\n\t" "ldr r8, [%[a], #352]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #352]\n\t" "# A[89] * B\n\t" "ldr r8, [%[a], #356]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #356]\n\t" "# A[90] * B\n\t" "ldr r8, [%[a], #360]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #360]\n\t" "# A[91] * B\n\t" "ldr r8, [%[a], #364]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #364]\n\t" "# A[92] * B\n\t" "ldr r8, [%[a], #368]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #368]\n\t" "# A[93] * B\n\t" "ldr r8, [%[a], #372]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #372]\n\t" "# A[94] * B\n\t" "ldr r8, [%[a], #376]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #376]\n\t" "# A[95] * B\n\t" "ldr r8, [%[a], #380]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #380]\n\t" "# A[96] * B\n\t" "ldr r8, [%[a], #384]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #384]\n\t" "# A[97] * B\n\t" "ldr r8, [%[a], #388]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #388]\n\t" "# A[98] * B\n\t" "ldr r8, [%[a], #392]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #392]\n\t" "# A[99] * B\n\t" "ldr r8, [%[a], #396]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #396]\n\t" "# A[100] * B\n\t" "ldr r8, [%[a], #400]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #400]\n\t" "# A[101] * B\n\t" "ldr r8, [%[a], #404]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #404]\n\t" "# A[102] * B\n\t" "ldr r8, [%[a], #408]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #408]\n\t" "# A[103] * B\n\t" "ldr r8, [%[a], #412]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #412]\n\t" "# A[104] * B\n\t" "ldr r8, [%[a], #416]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #416]\n\t" "# A[105] * B\n\t" "ldr r8, [%[a], #420]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #420]\n\t" "# A[106] * B\n\t" "ldr r8, [%[a], #424]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #424]\n\t" "# A[107] * B\n\t" "ldr r8, [%[a], #428]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #428]\n\t" "# A[108] * B\n\t" "ldr r8, [%[a], #432]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #432]\n\t" "# A[109] * B\n\t" "ldr r8, [%[a], #436]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #436]\n\t" "# A[110] * B\n\t" "ldr r8, [%[a], #440]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #440]\n\t" "# A[111] * B\n\t" "ldr r8, [%[a], #444]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #444]\n\t" "# A[112] * B\n\t" "ldr r8, [%[a], #448]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #448]\n\t" "# A[113] * B\n\t" "ldr r8, [%[a], #452]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #452]\n\t" "# A[114] * B\n\t" "ldr r8, [%[a], #456]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #456]\n\t" "# A[115] * B\n\t" "ldr r8, [%[a], #460]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #460]\n\t" "# A[116] * B\n\t" "ldr r8, [%[a], #464]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #464]\n\t" "# A[117] * B\n\t" "ldr r8, [%[a], #468]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #468]\n\t" "# A[118] * B\n\t" "ldr r8, [%[a], #472]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #472]\n\t" "# A[119] * B\n\t" "ldr r8, [%[a], #476]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #476]\n\t" "# A[120] * B\n\t" "ldr r8, [%[a], #480]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #480]\n\t" "# A[121] * B\n\t" "ldr r8, [%[a], #484]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #484]\n\t" "# A[122] * B\n\t" "ldr r8, [%[a], #488]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #488]\n\t" "# A[123] * B\n\t" "ldr r8, [%[a], #492]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #492]\n\t" "# A[124] * B\n\t" "ldr r8, [%[a], #496]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #496]\n\t" "# A[125] * B\n\t" "ldr r8, [%[a], #500]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #500]\n\t" "# A[126] * B\n\t" "ldr r8, [%[a], #504]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #504]\n\t" "# A[127] * B\n\t" "ldr r8, [%[a], #508]\n\t" @@ -23195,7 +22695,7 @@ static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m) sp_4096_sub_in_place_128(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -23894,6 +23394,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -23902,13 +23403,12 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -23916,7 +23416,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -23924,7 +23424,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23933,7 +23433,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23942,7 +23442,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23951,7 +23451,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23960,7 +23460,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #24]\n\t" "adc r5, r5, #0\n\t" "# a[i+7] += m[7] * mu\n\t" - "ldr r7, [%[m], #28]\n\t" + "ldr r7, [%[m], #28]\n\t" "ldr r9, [%[a], #28]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23969,7 +23469,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #28]\n\t" "adc r4, r4, #0\n\t" "# a[i+8] += m[8] * mu\n\t" - "ldr r7, [%[m], #32]\n\t" + "ldr r7, [%[m], #32]\n\t" "ldr r9, [%[a], #32]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23978,7 +23478,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #32]\n\t" "adc r5, r5, #0\n\t" "# a[i+9] += m[9] * mu\n\t" - "ldr r7, [%[m], #36]\n\t" + "ldr r7, [%[m], #36]\n\t" "ldr r9, [%[a], #36]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23987,7 +23487,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #36]\n\t" "adc r4, r4, #0\n\t" "# a[i+10] += m[10] * mu\n\t" - "ldr r7, [%[m], #40]\n\t" + "ldr r7, [%[m], #40]\n\t" "ldr r9, [%[a], #40]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -23996,7 +23496,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #40]\n\t" "adc r5, r5, #0\n\t" "# a[i+11] += m[11] * mu\n\t" - "ldr r7, [%[m], #44]\n\t" + "ldr r7, [%[m], #44]\n\t" "ldr r9, [%[a], #44]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24005,7 +23505,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #44]\n\t" "adc r4, r4, #0\n\t" "# a[i+12] += m[12] * mu\n\t" - "ldr r7, [%[m], #48]\n\t" + "ldr r7, [%[m], #48]\n\t" "ldr r9, [%[a], #48]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24014,7 +23514,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #48]\n\t" "adc r5, r5, #0\n\t" "# a[i+13] += m[13] * mu\n\t" - "ldr r7, [%[m], #52]\n\t" + "ldr r7, [%[m], #52]\n\t" "ldr r9, [%[a], #52]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24023,7 +23523,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #52]\n\t" "adc r4, r4, #0\n\t" "# a[i+14] += m[14] * mu\n\t" - "ldr r7, [%[m], #56]\n\t" + "ldr r7, [%[m], #56]\n\t" "ldr r9, [%[a], #56]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24032,7 +23532,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #56]\n\t" "adc r5, r5, #0\n\t" "# a[i+15] += m[15] * mu\n\t" - "ldr r7, [%[m], #60]\n\t" + "ldr r7, [%[m], #60]\n\t" "ldr r9, [%[a], #60]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24041,7 +23541,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #60]\n\t" "adc r4, r4, #0\n\t" "# a[i+16] += m[16] * mu\n\t" - "ldr r7, [%[m], #64]\n\t" + "ldr r7, [%[m], #64]\n\t" "ldr r9, [%[a], #64]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24050,7 +23550,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #64]\n\t" "adc r5, r5, #0\n\t" "# a[i+17] += m[17] * mu\n\t" - "ldr r7, [%[m], #68]\n\t" + "ldr r7, [%[m], #68]\n\t" "ldr r9, [%[a], #68]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24059,7 +23559,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #68]\n\t" "adc r4, r4, #0\n\t" "# a[i+18] += m[18] * mu\n\t" - "ldr r7, [%[m], #72]\n\t" + "ldr r7, [%[m], #72]\n\t" "ldr r9, [%[a], #72]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24068,7 +23568,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #72]\n\t" "adc r5, r5, #0\n\t" "# a[i+19] += m[19] * mu\n\t" - "ldr r7, [%[m], #76]\n\t" + "ldr r7, [%[m], #76]\n\t" "ldr r9, [%[a], #76]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24077,7 +23577,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #76]\n\t" "adc r4, r4, #0\n\t" "# a[i+20] += m[20] * mu\n\t" - "ldr r7, [%[m], #80]\n\t" + "ldr r7, [%[m], #80]\n\t" "ldr r9, [%[a], #80]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24086,7 +23586,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #80]\n\t" "adc r5, r5, #0\n\t" "# a[i+21] += m[21] * mu\n\t" - "ldr r7, [%[m], #84]\n\t" + "ldr r7, [%[m], #84]\n\t" "ldr r9, [%[a], #84]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24095,7 +23595,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #84]\n\t" "adc r4, r4, #0\n\t" "# a[i+22] += m[22] * mu\n\t" - "ldr r7, [%[m], #88]\n\t" + "ldr r7, [%[m], #88]\n\t" "ldr r9, [%[a], #88]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24104,7 +23604,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #88]\n\t" "adc r5, r5, #0\n\t" "# a[i+23] += m[23] * mu\n\t" - "ldr r7, [%[m], #92]\n\t" + "ldr r7, [%[m], #92]\n\t" "ldr r9, [%[a], #92]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24113,7 +23613,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #92]\n\t" "adc r4, r4, #0\n\t" "# a[i+24] += m[24] * mu\n\t" - "ldr r7, [%[m], #96]\n\t" + "ldr r7, [%[m], #96]\n\t" "ldr r9, [%[a], #96]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24122,7 +23622,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #96]\n\t" "adc r5, r5, #0\n\t" "# a[i+25] += m[25] * mu\n\t" - "ldr r7, [%[m], #100]\n\t" + "ldr r7, [%[m], #100]\n\t" "ldr r9, [%[a], #100]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24131,7 +23631,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #100]\n\t" "adc r4, r4, #0\n\t" "# a[i+26] += m[26] * mu\n\t" - "ldr r7, [%[m], #104]\n\t" + "ldr r7, [%[m], #104]\n\t" "ldr r9, [%[a], #104]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24140,7 +23640,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #104]\n\t" "adc r5, r5, #0\n\t" "# a[i+27] += m[27] * mu\n\t" - "ldr r7, [%[m], #108]\n\t" + "ldr r7, [%[m], #108]\n\t" "ldr r9, [%[a], #108]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24149,7 +23649,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #108]\n\t" "adc r4, r4, #0\n\t" "# a[i+28] += m[28] * mu\n\t" - "ldr r7, [%[m], #112]\n\t" + "ldr r7, [%[m], #112]\n\t" "ldr r9, [%[a], #112]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24158,7 +23658,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #112]\n\t" "adc r5, r5, #0\n\t" "# a[i+29] += m[29] * mu\n\t" - "ldr r7, [%[m], #116]\n\t" + "ldr r7, [%[m], #116]\n\t" "ldr r9, [%[a], #116]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24167,7 +23667,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #116]\n\t" "adc r4, r4, #0\n\t" "# a[i+30] += m[30] * mu\n\t" - "ldr r7, [%[m], #120]\n\t" + "ldr r7, [%[m], #120]\n\t" "ldr r9, [%[a], #120]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24176,7 +23676,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #120]\n\t" "adc r5, r5, #0\n\t" "# a[i+31] += m[31] * mu\n\t" - "ldr r7, [%[m], #124]\n\t" + "ldr r7, [%[m], #124]\n\t" "ldr r9, [%[a], #124]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24185,7 +23685,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #124]\n\t" "adc r4, r4, #0\n\t" "# a[i+32] += m[32] * mu\n\t" - "ldr r7, [%[m], #128]\n\t" + "ldr r7, [%[m], #128]\n\t" "ldr r9, [%[a], #128]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24194,7 +23694,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #128]\n\t" "adc r5, r5, #0\n\t" "# a[i+33] += m[33] * mu\n\t" - "ldr r7, [%[m], #132]\n\t" + "ldr r7, [%[m], #132]\n\t" "ldr r9, [%[a], #132]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24203,7 +23703,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #132]\n\t" "adc r4, r4, #0\n\t" "# a[i+34] += m[34] * mu\n\t" - "ldr r7, [%[m], #136]\n\t" + "ldr r7, [%[m], #136]\n\t" "ldr r9, [%[a], #136]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24212,7 +23712,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #136]\n\t" "adc r5, r5, #0\n\t" "# a[i+35] += m[35] * mu\n\t" - "ldr r7, [%[m], #140]\n\t" + "ldr r7, [%[m], #140]\n\t" "ldr r9, [%[a], #140]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24221,7 +23721,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #140]\n\t" "adc r4, r4, #0\n\t" "# a[i+36] += m[36] * mu\n\t" - "ldr r7, [%[m], #144]\n\t" + "ldr r7, [%[m], #144]\n\t" "ldr r9, [%[a], #144]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24230,7 +23730,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #144]\n\t" "adc r5, r5, #0\n\t" "# a[i+37] += m[37] * mu\n\t" - "ldr r7, [%[m], #148]\n\t" + "ldr r7, [%[m], #148]\n\t" "ldr r9, [%[a], #148]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24239,7 +23739,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #148]\n\t" "adc r4, r4, #0\n\t" "# a[i+38] += m[38] * mu\n\t" - "ldr r7, [%[m], #152]\n\t" + "ldr r7, [%[m], #152]\n\t" "ldr r9, [%[a], #152]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24248,7 +23748,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #152]\n\t" "adc r5, r5, #0\n\t" "# a[i+39] += m[39] * mu\n\t" - "ldr r7, [%[m], #156]\n\t" + "ldr r7, [%[m], #156]\n\t" "ldr r9, [%[a], #156]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24257,7 +23757,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #156]\n\t" "adc r4, r4, #0\n\t" "# a[i+40] += m[40] * mu\n\t" - "ldr r7, [%[m], #160]\n\t" + "ldr r7, [%[m], #160]\n\t" "ldr r9, [%[a], #160]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24266,7 +23766,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #160]\n\t" "adc r5, r5, #0\n\t" "# a[i+41] += m[41] * mu\n\t" - "ldr r7, [%[m], #164]\n\t" + "ldr r7, [%[m], #164]\n\t" "ldr r9, [%[a], #164]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24275,7 +23775,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #164]\n\t" "adc r4, r4, #0\n\t" "# a[i+42] += m[42] * mu\n\t" - "ldr r7, [%[m], #168]\n\t" + "ldr r7, [%[m], #168]\n\t" "ldr r9, [%[a], #168]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24284,7 +23784,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #168]\n\t" "adc r5, r5, #0\n\t" "# a[i+43] += m[43] * mu\n\t" - "ldr r7, [%[m], #172]\n\t" + "ldr r7, [%[m], #172]\n\t" "ldr r9, [%[a], #172]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24293,7 +23793,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #172]\n\t" "adc r4, r4, #0\n\t" "# a[i+44] += m[44] * mu\n\t" - "ldr r7, [%[m], #176]\n\t" + "ldr r7, [%[m], #176]\n\t" "ldr r9, [%[a], #176]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24302,7 +23802,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #176]\n\t" "adc r5, r5, #0\n\t" "# a[i+45] += m[45] * mu\n\t" - "ldr r7, [%[m], #180]\n\t" + "ldr r7, [%[m], #180]\n\t" "ldr r9, [%[a], #180]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24311,7 +23811,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #180]\n\t" "adc r4, r4, #0\n\t" "# a[i+46] += m[46] * mu\n\t" - "ldr r7, [%[m], #184]\n\t" + "ldr r7, [%[m], #184]\n\t" "ldr r9, [%[a], #184]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24320,7 +23820,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #184]\n\t" "adc r5, r5, #0\n\t" "# a[i+47] += m[47] * mu\n\t" - "ldr r7, [%[m], #188]\n\t" + "ldr r7, [%[m], #188]\n\t" "ldr r9, [%[a], #188]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24329,7 +23829,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #188]\n\t" "adc r4, r4, #0\n\t" "# a[i+48] += m[48] * mu\n\t" - "ldr r7, [%[m], #192]\n\t" + "ldr r7, [%[m], #192]\n\t" "ldr r9, [%[a], #192]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24338,7 +23838,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #192]\n\t" "adc r5, r5, #0\n\t" "# a[i+49] += m[49] * mu\n\t" - "ldr r7, [%[m], #196]\n\t" + "ldr r7, [%[m], #196]\n\t" "ldr r9, [%[a], #196]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24347,7 +23847,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #196]\n\t" "adc r4, r4, #0\n\t" "# a[i+50] += m[50] * mu\n\t" - "ldr r7, [%[m], #200]\n\t" + "ldr r7, [%[m], #200]\n\t" "ldr r9, [%[a], #200]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24356,7 +23856,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #200]\n\t" "adc r5, r5, #0\n\t" "# a[i+51] += m[51] * mu\n\t" - "ldr r7, [%[m], #204]\n\t" + "ldr r7, [%[m], #204]\n\t" "ldr r9, [%[a], #204]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24365,7 +23865,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #204]\n\t" "adc r4, r4, #0\n\t" "# a[i+52] += m[52] * mu\n\t" - "ldr r7, [%[m], #208]\n\t" + "ldr r7, [%[m], #208]\n\t" "ldr r9, [%[a], #208]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24374,7 +23874,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #208]\n\t" "adc r5, r5, #0\n\t" "# a[i+53] += m[53] * mu\n\t" - "ldr r7, [%[m], #212]\n\t" + "ldr r7, [%[m], #212]\n\t" "ldr r9, [%[a], #212]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24383,7 +23883,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #212]\n\t" "adc r4, r4, #0\n\t" "# a[i+54] += m[54] * mu\n\t" - "ldr r7, [%[m], #216]\n\t" + "ldr r7, [%[m], #216]\n\t" "ldr r9, [%[a], #216]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24392,7 +23892,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #216]\n\t" "adc r5, r5, #0\n\t" "# a[i+55] += m[55] * mu\n\t" - "ldr r7, [%[m], #220]\n\t" + "ldr r7, [%[m], #220]\n\t" "ldr r9, [%[a], #220]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24401,7 +23901,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #220]\n\t" "adc r4, r4, #0\n\t" "# a[i+56] += m[56] * mu\n\t" - "ldr r7, [%[m], #224]\n\t" + "ldr r7, [%[m], #224]\n\t" "ldr r9, [%[a], #224]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24410,7 +23910,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #224]\n\t" "adc r5, r5, #0\n\t" "# a[i+57] += m[57] * mu\n\t" - "ldr r7, [%[m], #228]\n\t" + "ldr r7, [%[m], #228]\n\t" "ldr r9, [%[a], #228]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24419,7 +23919,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #228]\n\t" "adc r4, r4, #0\n\t" "# a[i+58] += m[58] * mu\n\t" - "ldr r7, [%[m], #232]\n\t" + "ldr r7, [%[m], #232]\n\t" "ldr r9, [%[a], #232]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24428,7 +23928,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #232]\n\t" "adc r5, r5, #0\n\t" "# a[i+59] += m[59] * mu\n\t" - "ldr r7, [%[m], #236]\n\t" + "ldr r7, [%[m], #236]\n\t" "ldr r9, [%[a], #236]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24437,7 +23937,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #236]\n\t" "adc r4, r4, #0\n\t" "# a[i+60] += m[60] * mu\n\t" - "ldr r7, [%[m], #240]\n\t" + "ldr r7, [%[m], #240]\n\t" "ldr r9, [%[a], #240]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24446,7 +23946,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #240]\n\t" "adc r5, r5, #0\n\t" "# a[i+61] += m[61] * mu\n\t" - "ldr r7, [%[m], #244]\n\t" + "ldr r7, [%[m], #244]\n\t" "ldr r9, [%[a], #244]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24455,7 +23955,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #244]\n\t" "adc r4, r4, #0\n\t" "# a[i+62] += m[62] * mu\n\t" - "ldr r7, [%[m], #248]\n\t" + "ldr r7, [%[m], #248]\n\t" "ldr r9, [%[a], #248]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24464,7 +23964,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #248]\n\t" "adc r5, r5, #0\n\t" "# a[i+63] += m[63] * mu\n\t" - "ldr r7, [%[m], #252]\n\t" + "ldr r7, [%[m], #252]\n\t" "ldr r9, [%[a], #252]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24473,7 +23973,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #252]\n\t" "adc r4, r4, #0\n\t" "# a[i+64] += m[64] * mu\n\t" - "ldr r7, [%[m], #256]\n\t" + "ldr r7, [%[m], #256]\n\t" "ldr r9, [%[a], #256]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24482,7 +23982,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #256]\n\t" "adc r5, r5, #0\n\t" "# a[i+65] += m[65] * mu\n\t" - "ldr r7, [%[m], #260]\n\t" + "ldr r7, [%[m], #260]\n\t" "ldr r9, [%[a], #260]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24491,7 +23991,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #260]\n\t" "adc r4, r4, #0\n\t" "# a[i+66] += m[66] * mu\n\t" - "ldr r7, [%[m], #264]\n\t" + "ldr r7, [%[m], #264]\n\t" "ldr r9, [%[a], #264]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24500,7 +24000,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #264]\n\t" "adc r5, r5, #0\n\t" "# a[i+67] += m[67] * mu\n\t" - "ldr r7, [%[m], #268]\n\t" + "ldr r7, [%[m], #268]\n\t" "ldr r9, [%[a], #268]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24509,7 +24009,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #268]\n\t" "adc r4, r4, #0\n\t" "# a[i+68] += m[68] * mu\n\t" - "ldr r7, [%[m], #272]\n\t" + "ldr r7, [%[m], #272]\n\t" "ldr r9, [%[a], #272]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24518,7 +24018,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #272]\n\t" "adc r5, r5, #0\n\t" "# a[i+69] += m[69] * mu\n\t" - "ldr r7, [%[m], #276]\n\t" + "ldr r7, [%[m], #276]\n\t" "ldr r9, [%[a], #276]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24527,7 +24027,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #276]\n\t" "adc r4, r4, #0\n\t" "# a[i+70] += m[70] * mu\n\t" - "ldr r7, [%[m], #280]\n\t" + "ldr r7, [%[m], #280]\n\t" "ldr r9, [%[a], #280]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24536,7 +24036,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #280]\n\t" "adc r5, r5, #0\n\t" "# a[i+71] += m[71] * mu\n\t" - "ldr r7, [%[m], #284]\n\t" + "ldr r7, [%[m], #284]\n\t" "ldr r9, [%[a], #284]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24545,7 +24045,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #284]\n\t" "adc r4, r4, #0\n\t" "# a[i+72] += m[72] * mu\n\t" - "ldr r7, [%[m], #288]\n\t" + "ldr r7, [%[m], #288]\n\t" "ldr r9, [%[a], #288]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24554,7 +24054,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #288]\n\t" "adc r5, r5, #0\n\t" "# a[i+73] += m[73] * mu\n\t" - "ldr r7, [%[m], #292]\n\t" + "ldr r7, [%[m], #292]\n\t" "ldr r9, [%[a], #292]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24563,7 +24063,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #292]\n\t" "adc r4, r4, #0\n\t" "# a[i+74] += m[74] * mu\n\t" - "ldr r7, [%[m], #296]\n\t" + "ldr r7, [%[m], #296]\n\t" "ldr r9, [%[a], #296]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24572,7 +24072,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #296]\n\t" "adc r5, r5, #0\n\t" "# a[i+75] += m[75] * mu\n\t" - "ldr r7, [%[m], #300]\n\t" + "ldr r7, [%[m], #300]\n\t" "ldr r9, [%[a], #300]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24581,7 +24081,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #300]\n\t" "adc r4, r4, #0\n\t" "# a[i+76] += m[76] * mu\n\t" - "ldr r7, [%[m], #304]\n\t" + "ldr r7, [%[m], #304]\n\t" "ldr r9, [%[a], #304]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24590,7 +24090,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #304]\n\t" "adc r5, r5, #0\n\t" "# a[i+77] += m[77] * mu\n\t" - "ldr r7, [%[m], #308]\n\t" + "ldr r7, [%[m], #308]\n\t" "ldr r9, [%[a], #308]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24599,7 +24099,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #308]\n\t" "adc r4, r4, #0\n\t" "# a[i+78] += m[78] * mu\n\t" - "ldr r7, [%[m], #312]\n\t" + "ldr r7, [%[m], #312]\n\t" "ldr r9, [%[a], #312]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24608,7 +24108,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #312]\n\t" "adc r5, r5, #0\n\t" "# a[i+79] += m[79] * mu\n\t" - "ldr r7, [%[m], #316]\n\t" + "ldr r7, [%[m], #316]\n\t" "ldr r9, [%[a], #316]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24617,7 +24117,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #316]\n\t" "adc r4, r4, #0\n\t" "# a[i+80] += m[80] * mu\n\t" - "ldr r7, [%[m], #320]\n\t" + "ldr r7, [%[m], #320]\n\t" "ldr r9, [%[a], #320]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24626,7 +24126,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #320]\n\t" "adc r5, r5, #0\n\t" "# a[i+81] += m[81] * mu\n\t" - "ldr r7, [%[m], #324]\n\t" + "ldr r7, [%[m], #324]\n\t" "ldr r9, [%[a], #324]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24635,7 +24135,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #324]\n\t" "adc r4, r4, #0\n\t" "# a[i+82] += m[82] * mu\n\t" - "ldr r7, [%[m], #328]\n\t" + "ldr r7, [%[m], #328]\n\t" "ldr r9, [%[a], #328]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24644,7 +24144,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #328]\n\t" "adc r5, r5, #0\n\t" "# a[i+83] += m[83] * mu\n\t" - "ldr r7, [%[m], #332]\n\t" + "ldr r7, [%[m], #332]\n\t" "ldr r9, [%[a], #332]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24653,7 +24153,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #332]\n\t" "adc r4, r4, #0\n\t" "# a[i+84] += m[84] * mu\n\t" - "ldr r7, [%[m], #336]\n\t" + "ldr r7, [%[m], #336]\n\t" "ldr r9, [%[a], #336]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24662,7 +24162,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #336]\n\t" "adc r5, r5, #0\n\t" "# a[i+85] += m[85] * mu\n\t" - "ldr r7, [%[m], #340]\n\t" + "ldr r7, [%[m], #340]\n\t" "ldr r9, [%[a], #340]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24671,7 +24171,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #340]\n\t" "adc r4, r4, #0\n\t" "# a[i+86] += m[86] * mu\n\t" - "ldr r7, [%[m], #344]\n\t" + "ldr r7, [%[m], #344]\n\t" "ldr r9, [%[a], #344]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24680,7 +24180,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #344]\n\t" "adc r5, r5, #0\n\t" "# a[i+87] += m[87] * mu\n\t" - "ldr r7, [%[m], #348]\n\t" + "ldr r7, [%[m], #348]\n\t" "ldr r9, [%[a], #348]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24689,7 +24189,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #348]\n\t" "adc r4, r4, #0\n\t" "# a[i+88] += m[88] * mu\n\t" - "ldr r7, [%[m], #352]\n\t" + "ldr r7, [%[m], #352]\n\t" "ldr r9, [%[a], #352]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24698,7 +24198,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #352]\n\t" "adc r5, r5, #0\n\t" "# a[i+89] += m[89] * mu\n\t" - "ldr r7, [%[m], #356]\n\t" + "ldr r7, [%[m], #356]\n\t" "ldr r9, [%[a], #356]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24707,7 +24207,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #356]\n\t" "adc r4, r4, #0\n\t" "# a[i+90] += m[90] * mu\n\t" - "ldr r7, [%[m], #360]\n\t" + "ldr r7, [%[m], #360]\n\t" "ldr r9, [%[a], #360]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24716,7 +24216,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #360]\n\t" "adc r5, r5, #0\n\t" "# a[i+91] += m[91] * mu\n\t" - "ldr r7, [%[m], #364]\n\t" + "ldr r7, [%[m], #364]\n\t" "ldr r9, [%[a], #364]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24725,7 +24225,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #364]\n\t" "adc r4, r4, #0\n\t" "# a[i+92] += m[92] * mu\n\t" - "ldr r7, [%[m], #368]\n\t" + "ldr r7, [%[m], #368]\n\t" "ldr r9, [%[a], #368]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24734,7 +24234,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #368]\n\t" "adc r5, r5, #0\n\t" "# a[i+93] += m[93] * mu\n\t" - "ldr r7, [%[m], #372]\n\t" + "ldr r7, [%[m], #372]\n\t" "ldr r9, [%[a], #372]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24743,7 +24243,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #372]\n\t" "adc r4, r4, #0\n\t" "# a[i+94] += m[94] * mu\n\t" - "ldr r7, [%[m], #376]\n\t" + "ldr r7, [%[m], #376]\n\t" "ldr r9, [%[a], #376]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24752,7 +24252,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #376]\n\t" "adc r5, r5, #0\n\t" "# a[i+95] += m[95] * mu\n\t" - "ldr r7, [%[m], #380]\n\t" + "ldr r7, [%[m], #380]\n\t" "ldr r9, [%[a], #380]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24761,7 +24261,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #380]\n\t" "adc r4, r4, #0\n\t" "# a[i+96] += m[96] * mu\n\t" - "ldr r7, [%[m], #384]\n\t" + "ldr r7, [%[m], #384]\n\t" "ldr r9, [%[a], #384]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24770,7 +24270,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #384]\n\t" "adc r5, r5, #0\n\t" "# a[i+97] += m[97] * mu\n\t" - "ldr r7, [%[m], #388]\n\t" + "ldr r7, [%[m], #388]\n\t" "ldr r9, [%[a], #388]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24779,7 +24279,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #388]\n\t" "adc r4, r4, #0\n\t" "# a[i+98] += m[98] * mu\n\t" - "ldr r7, [%[m], #392]\n\t" + "ldr r7, [%[m], #392]\n\t" "ldr r9, [%[a], #392]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24788,7 +24288,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #392]\n\t" "adc r5, r5, #0\n\t" "# a[i+99] += m[99] * mu\n\t" - "ldr r7, [%[m], #396]\n\t" + "ldr r7, [%[m], #396]\n\t" "ldr r9, [%[a], #396]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24797,7 +24297,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #396]\n\t" "adc r4, r4, #0\n\t" "# a[i+100] += m[100] * mu\n\t" - "ldr r7, [%[m], #400]\n\t" + "ldr r7, [%[m], #400]\n\t" "ldr r9, [%[a], #400]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24806,7 +24306,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #400]\n\t" "adc r5, r5, #0\n\t" "# a[i+101] += m[101] * mu\n\t" - "ldr r7, [%[m], #404]\n\t" + "ldr r7, [%[m], #404]\n\t" "ldr r9, [%[a], #404]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24815,7 +24315,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #404]\n\t" "adc r4, r4, #0\n\t" "# a[i+102] += m[102] * mu\n\t" - "ldr r7, [%[m], #408]\n\t" + "ldr r7, [%[m], #408]\n\t" "ldr r9, [%[a], #408]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24824,7 +24324,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #408]\n\t" "adc r5, r5, #0\n\t" "# a[i+103] += m[103] * mu\n\t" - "ldr r7, [%[m], #412]\n\t" + "ldr r7, [%[m], #412]\n\t" "ldr r9, [%[a], #412]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24833,7 +24333,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #412]\n\t" "adc r4, r4, #0\n\t" "# a[i+104] += m[104] * mu\n\t" - "ldr r7, [%[m], #416]\n\t" + "ldr r7, [%[m], #416]\n\t" "ldr r9, [%[a], #416]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24842,7 +24342,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #416]\n\t" "adc r5, r5, #0\n\t" "# a[i+105] += m[105] * mu\n\t" - "ldr r7, [%[m], #420]\n\t" + "ldr r7, [%[m], #420]\n\t" "ldr r9, [%[a], #420]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24851,7 +24351,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #420]\n\t" "adc r4, r4, #0\n\t" "# a[i+106] += m[106] * mu\n\t" - "ldr r7, [%[m], #424]\n\t" + "ldr r7, [%[m], #424]\n\t" "ldr r9, [%[a], #424]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24860,7 +24360,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #424]\n\t" "adc r5, r5, #0\n\t" "# a[i+107] += m[107] * mu\n\t" - "ldr r7, [%[m], #428]\n\t" + "ldr r7, [%[m], #428]\n\t" "ldr r9, [%[a], #428]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24869,7 +24369,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #428]\n\t" "adc r4, r4, #0\n\t" "# a[i+108] += m[108] * mu\n\t" - "ldr r7, [%[m], #432]\n\t" + "ldr r7, [%[m], #432]\n\t" "ldr r9, [%[a], #432]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24878,7 +24378,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #432]\n\t" "adc r5, r5, #0\n\t" "# a[i+109] += m[109] * mu\n\t" - "ldr r7, [%[m], #436]\n\t" + "ldr r7, [%[m], #436]\n\t" "ldr r9, [%[a], #436]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24887,7 +24387,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #436]\n\t" "adc r4, r4, #0\n\t" "# a[i+110] += m[110] * mu\n\t" - "ldr r7, [%[m], #440]\n\t" + "ldr r7, [%[m], #440]\n\t" "ldr r9, [%[a], #440]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24896,7 +24396,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #440]\n\t" "adc r5, r5, #0\n\t" "# a[i+111] += m[111] * mu\n\t" - "ldr r7, [%[m], #444]\n\t" + "ldr r7, [%[m], #444]\n\t" "ldr r9, [%[a], #444]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24905,7 +24405,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #444]\n\t" "adc r4, r4, #0\n\t" "# a[i+112] += m[112] * mu\n\t" - "ldr r7, [%[m], #448]\n\t" + "ldr r7, [%[m], #448]\n\t" "ldr r9, [%[a], #448]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24914,7 +24414,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #448]\n\t" "adc r5, r5, #0\n\t" "# a[i+113] += m[113] * mu\n\t" - "ldr r7, [%[m], #452]\n\t" + "ldr r7, [%[m], #452]\n\t" "ldr r9, [%[a], #452]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24923,7 +24423,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #452]\n\t" "adc r4, r4, #0\n\t" "# a[i+114] += m[114] * mu\n\t" - "ldr r7, [%[m], #456]\n\t" + "ldr r7, [%[m], #456]\n\t" "ldr r9, [%[a], #456]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24932,7 +24432,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #456]\n\t" "adc r5, r5, #0\n\t" "# a[i+115] += m[115] * mu\n\t" - "ldr r7, [%[m], #460]\n\t" + "ldr r7, [%[m], #460]\n\t" "ldr r9, [%[a], #460]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24941,7 +24441,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #460]\n\t" "adc r4, r4, #0\n\t" "# a[i+116] += m[116] * mu\n\t" - "ldr r7, [%[m], #464]\n\t" + "ldr r7, [%[m], #464]\n\t" "ldr r9, [%[a], #464]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24950,7 +24450,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #464]\n\t" "adc r5, r5, #0\n\t" "# a[i+117] += m[117] * mu\n\t" - "ldr r7, [%[m], #468]\n\t" + "ldr r7, [%[m], #468]\n\t" "ldr r9, [%[a], #468]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24959,7 +24459,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #468]\n\t" "adc r4, r4, #0\n\t" "# a[i+118] += m[118] * mu\n\t" - "ldr r7, [%[m], #472]\n\t" + "ldr r7, [%[m], #472]\n\t" "ldr r9, [%[a], #472]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24968,7 +24468,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #472]\n\t" "adc r5, r5, #0\n\t" "# a[i+119] += m[119] * mu\n\t" - "ldr r7, [%[m], #476]\n\t" + "ldr r7, [%[m], #476]\n\t" "ldr r9, [%[a], #476]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24977,7 +24477,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #476]\n\t" "adc r4, r4, #0\n\t" "# a[i+120] += m[120] * mu\n\t" - "ldr r7, [%[m], #480]\n\t" + "ldr r7, [%[m], #480]\n\t" "ldr r9, [%[a], #480]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24986,7 +24486,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #480]\n\t" "adc r5, r5, #0\n\t" "# a[i+121] += m[121] * mu\n\t" - "ldr r7, [%[m], #484]\n\t" + "ldr r7, [%[m], #484]\n\t" "ldr r9, [%[a], #484]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -24995,7 +24495,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #484]\n\t" "adc r4, r4, #0\n\t" "# a[i+122] += m[122] * mu\n\t" - "ldr r7, [%[m], #488]\n\t" + "ldr r7, [%[m], #488]\n\t" "ldr r9, [%[a], #488]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -25004,7 +24504,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #488]\n\t" "adc r5, r5, #0\n\t" "# a[i+123] += m[123] * mu\n\t" - "ldr r7, [%[m], #492]\n\t" + "ldr r7, [%[m], #492]\n\t" "ldr r9, [%[a], #492]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -25013,7 +24513,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #492]\n\t" "adc r4, r4, #0\n\t" "# a[i+124] += m[124] * mu\n\t" - "ldr r7, [%[m], #496]\n\t" + "ldr r7, [%[m], #496]\n\t" "ldr r9, [%[a], #496]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -25022,7 +24522,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #496]\n\t" "adc r5, r5, #0\n\t" "# a[i+125] += m[125] * mu\n\t" - "ldr r7, [%[m], #500]\n\t" + "ldr r7, [%[m], #500]\n\t" "ldr r9, [%[a], #500]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -25031,7 +24531,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r9, [%[a], #500]\n\t" "adc r4, r4, #0\n\t" "# a[i+126] += m[126] * mu\n\t" - "ldr r7, [%[m], #504]\n\t" + "ldr r7, [%[m], #504]\n\t" "ldr r9, [%[a], #504]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -25062,7 +24562,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_4096_cond_sub_128(a - 128, a, m, (sp_digit)0 - ca); @@ -25077,8 +24577,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_128(r, a, b); sp_4096_mont_reduce_128(r, m, mp); @@ -25091,8 +24591,8 @@ static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_128(r, a); sp_4096_mont_reduce_128(r, m, mp); @@ -26772,35 +26272,31 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 256]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 256; -#else - t[i] = &td[i * 256]; -#endif } sp_4096_mont_setup(m, &mp); @@ -26848,34 +26344,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 128); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -26896,9 +26392,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -26917,35 +26412,31 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 256]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 256; -#else - t[i] = &td[i * 256]; -#endif } sp_4096_mont_setup(m, &mp); @@ -27009,34 +26500,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 128); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -27058,9 +26549,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -27081,19 +26571,18 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[256], m[128], r[256]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[128 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 512) { @@ -27107,22 +26596,18 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 128 * 2; - m = r + 128 * 2; - } #endif if (err == MP_OKAY) { + r = a + 128 * 2; + m = r + 128 * 2; ah = a + 128; sp_4096_from_bin(ah, 128, in, inLen); @@ -27195,10 +26680,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -27588,13 +27072,17 @@ static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_dig * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[128 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -27623,13 +27111,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 128; m = a + 256; @@ -27640,31 +27130,36 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_4096_from_mp(m, 128, mm); err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0); } + if (err == MP_OKAY) { sp_4096_to_bin(r, out); *outLen = 512; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 128); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 128); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128 * 2]; - sp_digit p[64], q[64], dp[64]; - sp_digit tmpa[128], tmpb[128]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -27684,31 +27179,23 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 128 * 2; q = p + 64; qi = dq = dp = q + 64; tmpa = qi + 64; tmpb = tmpa + 128; - - r = t + 128; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_4096_from_bin(a, 128, in, inLen); sp_4096_from_mp(p, 64, pm); sp_4096_from_mp(q, 64, qm); @@ -27740,18 +27227,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 64 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -27775,17 +27259,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 128; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 128; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -27798,14 +27284,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 128; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -27832,10 +27320,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[256], e[128], m[128]; + sp_digit b[256]; + sp_digit e[128]; + sp_digit m[128]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -28663,34 +28154,31 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[385]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 256; -#else - tmp = &td[256]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_128(norm, m); @@ -28708,34 +28196,34 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_4096_lshift_128(r, norm, (byte)y); + sp_4096_lshift_128(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -28746,7 +28234,7 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, sp_4096_mont_sqr_128(r, r, m, mp); sp_4096_mont_sqr_128(r, r, m, mp); - sp_4096_lshift_128(r, r, (byte)y); + sp_4096_lshift_128(r, r, y); sp_4096_mul_d_128(tmp, norm, r[128]); r[128] = 0; o = sp_4096_add_128(r, r, tmp); @@ -28761,9 +28249,8 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -28782,11 +28269,13 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[256], e[128], m[128]; + sp_digit b[256]; + sp_digit e[128]; + sp_digit m[128]; sp_digit* r = b; word32 i; @@ -28821,6 +28310,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -28833,19 +28323,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, } #endif /* WOLFSSL_HAVE_SP_DH */ -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 8]; + /* Y ordinate of point. */ sp_digit y[2 * 8]; + /* Z ordinate of point. */ sp_digit z[2 * 8]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -28915,50 +28409,1134 @@ static const sp_digit p256_b[8] = { }; #endif -static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p) +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #28\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #32\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #56\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p)) #else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap) +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r11, [%[a], #0]\n\t" + "ldr r12, [%[b], #0]\n\t" + "umull r3, r4, r11, r12\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r11, [%[a], #4]\n\t" + "ldr r12, [%[b], #4]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r11, [%[a], #8]\n\t" + "ldr r12, [%[b], #8]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r11, [%[a], #12]\n\t" + "ldr r12, [%[b], #12]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[7] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r11, [%[a], #16]\n\t" + "ldr r12, [%[b], #16]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[7] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r11, [%[a], #20]\n\t" + "ldr r12, [%[b], #20]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[7] * B[5]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r11, [%[a], #24]\n\t" + "ldr r12, [%[b], #24]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[6] * B[7]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[7] * B[7]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "sub %[r], %[r], #32\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); } +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #28\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #32\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #56\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r12, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [%[r], #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [%[r], #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [%[r], #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [%[r], #52]\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adc r2, r2, r9\n\t" + "str r4, [%[r], #56]\n\t" + "str r2, [%[r], #60]\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "sub %[r], %[r], #32\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "rsbs %[c], %[c], #0\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "sbc %[c], r4, r4\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ /* Multiply a number by Montogmery normalizer mod modulus (prime). * * r The resulting Montgomery form number. @@ -29211,7 +29789,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -29245,7 +29824,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -29281,7 +29862,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) * p Point of type sp_point_256 (result). * pm Point of type ecc_point. */ -static void sp_256_point_from_ecc_point_8(sp_point_256* p, const ecc_point* pm) +static void sp_256_point_from_ecc_point_8(sp_point_256* p, + const ecc_point* pm) { XMEMSET(p->x, 0, sizeof(p->x)); XMEMSET(p->y, 0, sizeof(p->y)); @@ -29308,17 +29890,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = 8; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 8; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -29331,14 +29915,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 8; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -30571,7 +31157,7 @@ static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint32_t p256_mod_minus_2[8] = { @@ -30894,6 +31480,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -30902,13 +31489,12 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -30916,7 +31502,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -30924,7 +31510,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -30933,7 +31519,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -30942,7 +31528,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -30951,7 +31537,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -30982,7 +31568,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca); @@ -30994,7 +31580,8 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*8; @@ -31030,106 +31617,6 @@ static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "add r12, %[a], #32\n\t" - "\n1:\n\t" - "adds %[c], %[c], #-1\n\t" - "ldr r4, [%[a]], #4\n\t" - "ldr r5, [%[a]], #4\n\t" - "ldr r6, [%[a]], #4\n\t" - "ldr r7, [%[a]], #4\n\t" - "ldr r8, [%[b]], #4\n\t" - "ldr r9, [%[b]], #4\n\t" - "ldr r10, [%[b]], #4\n\t" - "ldr r14, [%[b]], #4\n\t" - "adcs r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r]], #4\n\t" - "str r5, [%[r]], #4\n\t" - "str r6, [%[r]], #4\n\t" - "str r7, [%[r]], #4\n\t" - "mov r4, #0\n\t" - "adc %[c], r4, #0\n\t" - "cmp %[a], r12\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); - - return c; -} - -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r12, #0\n\t" - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[a], #4]\n\t" - "ldr r6, [%[a], #8]\n\t" - "ldr r7, [%[a], #12]\n\t" - "ldr r8, [%[b], #0]\n\t" - "ldr r9, [%[b], #4]\n\t" - "ldr r10, [%[b], #8]\n\t" - "ldr r14, [%[b], #12]\n\t" - "adds r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r], #0]\n\t" - "str r5, [%[r], #4]\n\t" - "str r6, [%[r], #8]\n\t" - "str r7, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[a], #20]\n\t" - "ldr r6, [%[a], #24]\n\t" - "ldr r7, [%[a], #28]\n\t" - "ldr r8, [%[b], #16]\n\t" - "ldr r9, [%[b], #20]\n\t" - "ldr r10, [%[b], #24]\n\t" - "ldr r14, [%[b], #28]\n\t" - "adcs r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r], #16]\n\t" - "str r5, [%[r], #20]\n\t" - "str r6, [%[r], #24]\n\t" - "str r7, [%[r], #28]\n\t" - "adc %[c], r12, r12\n\t" - : [c] "+r" (c) - : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -31687,104 +32174,6 @@ static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_d sp_256_mont_sub_8(y, y, t2, p256_mod); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "add r12, %[a], #32\n\t" - "\n1:\n\t" - "rsbs %[c], %[c], #0\n\t" - "ldr r4, [%[a]], #4\n\t" - "ldr r5, [%[a]], #4\n\t" - "ldr r6, [%[a]], #4\n\t" - "ldr r7, [%[a]], #4\n\t" - "ldr r8, [%[b]], #4\n\t" - "ldr r9, [%[b]], #4\n\t" - "ldr r10, [%[b]], #4\n\t" - "ldr r14, [%[b]], #4\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "sbcs r7, r7, r14\n\t" - "str r4, [%[r]], #4\n\t" - "str r5, [%[r]], #4\n\t" - "str r6, [%[r]], #4\n\t" - "str r7, [%[r]], #4\n\t" - "sbc %[c], r4, r4\n\t" - "cmp %[a], r12\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); - - return c; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r3, [%[a], #0]\n\t" - "ldr r4, [%[a], #4]\n\t" - "ldr r5, [%[a], #8]\n\t" - "ldr r6, [%[a], #12]\n\t" - "ldr r7, [%[b], #0]\n\t" - "ldr r8, [%[b], #4]\n\t" - "ldr r9, [%[b], #8]\n\t" - "ldr r10, [%[b], #12]\n\t" - "subs r3, r3, r7\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [%[a], #16]\n\t" - "ldr r4, [%[a], #20]\n\t" - "ldr r5, [%[a], #24]\n\t" - "ldr r6, [%[a], #28]\n\t" - "ldr r7, [%[b], #16]\n\t" - "ldr r8, [%[b], #20]\n\t" - "ldr r9, [%[b], #24]\n\t" - "ldr r10, [%[b], #28]\n\t" - "sbcs r3, r3, r7\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - "sbc %[c], %[c], #0\n\t" - : [c] "+r" (c) - : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Compare two numbers to determine if they are equal. * Constant time implementation. * @@ -32008,8 +32397,8 @@ static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_8(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -32164,9 +32553,11 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Simple, smaller code size and memory size, of windowing. - * Calculate uindow of 4 bits. - * Only add points from table. + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 256 doubles. + * 76 adds. * * r Resulting point. * g Point to multiply. @@ -32179,55 +32570,55 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table, static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td[16]; - sp_point_256 rtd; - sp_digit tmpd[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 t[16 + 1]; + sp_digit tmp[2 * 8 * 5]; +#endif + sp_point_256* rt = NULL; #ifndef WC_NO_CACHE_RESISTANT - sp_point_256 pd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* p = NULL; +#else + sp_point_256 p[1]; #endif -#endif - sp_point_256* t; - sp_point_256* rt; -#ifndef WC_NO_CACHE_RESISTANT - sp_point_256* p; -#endif - sp_digit* tmp; +#endif /* !WC_NO_CACHE_RESISTANT */ sp_digit n; int i; - int c, y; - int err; + int c; + int y; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -#ifndef WC_NO_CACHE_RESISTANT - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 17, heap, DYNAMIC_TYPE_ECC); -#else - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 16, heap, DYNAMIC_TYPE_ECC); -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + #ifndef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), + heap, DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } + #endif + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { -#ifndef WC_NO_CACHE_RESISTANT - #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - p = t + 16; - #else - p = &pd; - #endif -#endif + rt = t + 16; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; @@ -32268,7 +32659,7 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons i = 6; n = k[i+1] << 0; c = 28; - y = n >> 28; + y = (int)(n >> 28); #ifndef WC_NO_CACHE_RESISTANT if (ct) { sp_256_get_point_16_8(rt, t, y); @@ -32315,30 +32706,39 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_256) * 16); - XFREE(t, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmpd, sizeof(tmpd)); - ForceZero(td, sizeof(td)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif - sp_256_point_free_8(rt, 1, heap); + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 8 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#ifndef WC_NO_CACHE_RESISTANT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (p != NULL) + #endif + { + ForceZero(p, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* !WC_NO_CACHE_RESISTANT */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_256 { - sp_digit x[8]; - sp_digit y[8]; -} sp_table_entry_256; - #ifdef FP_ECC /* Double the Montgomery form projective point p a number of times. * @@ -32347,7 +32747,8 @@ typedef struct sp_table_entry_256 { * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*8; @@ -32428,6 +32829,36 @@ static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t) sp_256_div2_8(y, y, p256_mod); } +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +#endif /* FP_ECC */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[8]; + sp_digit y[8]; +} sp_table_entry_256; + +#ifdef FP_ECC #endif /* FP_ECC */ /* Add two Montgomery form projective points. The second point has a q value of * one. @@ -32513,29 +32944,11 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, #ifdef WOLFSSL_SP_SMALL #ifdef FP_ECC -/* Convert the projective point to affine. - * Ordinates are in Montgomery form. - * - * a Point to convert. - * t Temporary data. - */ -static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 8; - sp_digit* tmp = t + 4 * 8; - - sp_256_mont_inv_8(t1, a->z, tmp); - - sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); - - sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); - XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); -} - /* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 64 bits between * * a The base point. * table Place to store generated point data. @@ -32545,26 +32958,30 @@ static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_8(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_8(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -32609,9 +33026,10 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a, } } - sp_256_point_free_8(s2, 0, heap); - sp_256_point_free_8(s1, 0, heap); - sp_256_point_free_8( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -32670,8 +33088,10 @@ static void sp_256_get_entry_16_8(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 4 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -32685,17 +33105,19 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 8 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -32703,27 +33125,30 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=63; j<4; j++,x+=64) { + x = 63; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 64; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -32737,8 +33162,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=62; i>=0; i--) { y = 0; - for (j=0,x=i; j<4; j++,x+=64) { + x = i; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 64; } sp_256_proj_point_dbl_8(rt, rt, t); @@ -32764,13 +33191,12 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(rt, 0, heap); return err; } @@ -32780,16 +33206,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[8]; + /* Y ordinate of point that table was generated from. */ sp_digit y[8]; + /* Precomputation table for point. */ sp_table_entry_256 table[16]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -32797,9 +33232,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -32908,6 +33349,10 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ #else #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 32 bits between * * a The base point. * table Place to store generated point data. @@ -32917,26 +33362,30 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ static int sp_256_gen_stripe_table_8(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_8(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -32981,9 +33430,10 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a, } } - sp_256_point_free_8(s2, 0, heap); - sp_256_point_free_8(s1, 0, heap); - sp_256_point_free_8( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -33042,8 +33492,10 @@ static void sp_256_get_entry_256_8(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -33057,17 +33509,19 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 8 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -33075,27 +33529,30 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=31; j<8; j++,x+=32) { + x = 31; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 32; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -33109,8 +33566,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=30; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=32) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 32; } sp_256_proj_point_dbl_8(rt, rt, t); @@ -33136,13 +33595,12 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(rt, 0, heap); return err; } @@ -33152,16 +33610,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[8]; + /* Y ordinate of point that table was generated from. */ sp_digit y[8]; + /* Precomputation table for point. */ sp_table_entry_256 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -33169,9 +33636,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -33288,28 +33761,31 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 8, km); sp_256_point_from_ecc_point_8(point, gm); @@ -33320,17 +33796,101 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_8(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[8 + 8 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_8(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 8; + + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + sp_256_point_from_ecc_point_8(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_8(point, point, addP, tmp); + + if (map) { + sp_256_map_8(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 64 between points. + */ static const sp_table_entry_256 p256_table[16] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -33415,6 +33975,11 @@ static const sp_table_entry_256 p256_table[16] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -33430,6 +33995,10 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 32 between points. + */ static const sp_table_entry_256 p256_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -34714,6 +35283,11 @@ static const sp_table_entry_256 p256_table[256] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -34739,28 +35313,30 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 8, km); @@ -34770,12 +35346,90 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_8(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[8 + 8 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (8 + 8 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_8(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 8; + + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_8(point, point, addP, tmp); + + if (map) { + sp_256_map_8(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -34793,7 +35447,7 @@ static int sp_256_iszero_8(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -34840,7 +35494,8 @@ static void sp_256_add_one_8(sp_digit* a) */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -34903,41 +35558,46 @@ static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[8]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_256_point_new_8(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_8(rng, k); } if (err == MP_OKAY) { @@ -34962,15 +35622,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_8(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_8(infinity, 1, heap); -#endif - sp_256_point_free_8(point, 1, heap); return err; } @@ -34984,7 +35643,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_256_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 256 / 8 - 1; a[j] = 0; @@ -35025,33 +35687,35 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; if (*outLen < 32U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -35064,576 +35728,18 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(point, 0, heap); return err; } #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -#ifdef WOLFSSL_SP_SMALL -/* Multiply a and b into r. (r = a * b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - __asm__ __volatile__ ( - "sub sp, sp, #64\n\t" - "mov r5, #0\n\t" - "mov r6, #0\n\t" - "mov r7, #0\n\t" - "mov r8, #0\n\t" - "\n1:\n\t" - "subs r3, r5, #28\n\t" - "it cc\n\t" - "movcc r3, #0\n\t" - "sub r4, r5, r3\n\t" - "\n2:\n\t" - "ldr r14, [%[a], r3]\n\t" - "ldr r12, [%[b], r4]\n\t" - "umull r9, r10, r14, r12\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, #0\n\t" - "add r3, r3, #4\n\t" - "sub r4, r4, #4\n\t" - "cmp r3, #32\n\t" - "beq 3f\n\t" - "cmp r3, r5\n\t" - "ble 2b\n\t" - "\n3:\n\t" - "str r6, [sp, r5]\n\t" - "mov r6, r7\n\t" - "mov r7, r8\n\t" - "mov r8, #0\n\t" - "add r5, r5, #4\n\t" - "cmp r5, #56\n\t" - "ble 1b\n\t" - "str r6, [sp, r5]\n\t" - "\n4:\n\t" - "ldr r6, [sp, #0]\n\t" - "ldr r7, [sp, #4]\n\t" - "ldr r8, [sp, #8]\n\t" - "ldr r3, [sp, #12]\n\t" - "str r6, [%[r], #0]\n\t" - "str r7, [%[r], #4]\n\t" - "str r8, [%[r], #8]\n\t" - "str r3, [%[r], #12]\n\t" - "add sp, sp, #16\n\t" - "add %[r], %[r], #16\n\t" - "subs r5, r5, #16\n\t" - "bgt 4b\n\t" - : [r] "+r" (r) - : [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); -} - -#else -/* Multiply a and b into r. (r = a * b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - __asm__ __volatile__ ( - "sub sp, sp, #32\n\t" - "mov r10, #0\n\t" - "# A[0] * B[0]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r3, r4, r8, r9\n\t" - "mov r5, #0\n\t" - "str r3, [sp]\n\t" - "# A[0] * B[1]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r10, r10\n\t" - "# A[1] * B[0]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "str r4, [sp, #4]\n\t" - "# A[0] * B[2]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[1] * B[1]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[0]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "str r5, [sp, #8]\n\t" - "# A[0] * B[3]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r10, r10\n\t" - "# A[1] * B[2]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[2] * B[1]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[3] * B[0]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "str r3, [sp, #12]\n\t" - "# A[0] * B[4]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r10, r10\n\t" - "# A[1] * B[3]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[2] * B[2]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[1]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[0]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "str r4, [sp, #16]\n\t" - "# A[0] * B[5]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[1] * B[4]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[3]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[3] * B[2]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[4] * B[1]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[5] * B[0]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "str r5, [sp, #20]\n\t" - "# A[0] * B[6]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r10, r10\n\t" - "# A[1] * B[5]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[2] * B[4]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[3] * B[3]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[4] * B[2]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[1]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[0]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "str r3, [sp, #24]\n\t" - "# A[0] * B[7]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r10, r10\n\t" - "# A[1] * B[6]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[2] * B[5]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[4]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[3]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[5] * B[2]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[6] * B[1]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[7] * B[0]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "str r4, [sp, #28]\n\t" - "# A[1] * B[7]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[2] * B[6]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[3] * B[5]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[4] * B[4]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[5] * B[3]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[6] * B[2]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[7] * B[1]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "str r5, [%[r], #32]\n\t" - "# A[2] * B[7]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r10, r10\n\t" - "# A[3] * B[6]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[4] * B[5]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[4]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[3]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[7] * B[2]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "str r3, [%[r], #36]\n\t" - "# A[3] * B[7]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r10, r10\n\t" - "# A[4] * B[6]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[5] * B[5]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[6] * B[4]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[7] * B[3]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "str r4, [%[r], #40]\n\t" - "# A[4] * B[7]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[5] * B[6]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[6] * B[5]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[7] * B[4]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "str r5, [%[r], #44]\n\t" - "# A[5] * B[7]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r10, r10\n\t" - "# A[6] * B[6]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[7] * B[5]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "str r3, [%[r], #48]\n\t" - "# A[6] * B[7]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r10, r10\n\t" - "# A[7] * B[6]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "str r4, [%[r], #52]\n\t" - "# A[7] * B[7]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adc r3, r3, r7\n\t" - "str r5, [%[r], #56]\n\t" - "str r3, [%[r], #60]\n\t" - "ldr r3, [sp, #0]\n\t" - "ldr r4, [sp, #4]\n\t" - "ldr r5, [sp, #8]\n\t" - "ldr r6, [sp, #12]\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [sp, #16]\n\t" - "ldr r4, [sp, #20]\n\t" - "ldr r5, [sp, #24]\n\t" - "ldr r6, [sp, #28]\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - "add sp, sp, #32\n\t" - : - : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" - ); -} - -#endif /* WOLFSSL_SP_SMALL */ #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) #ifdef WOLFSSL_SP_SMALL @@ -35778,51 +35884,45 @@ static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" @@ -35981,435 +36081,6 @@ static WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) #ifdef WOLFSSL_SP_SMALL -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "sub sp, sp, #64\n\t" - "mov r12, #0\n\t" - "mov r6, #0\n\t" - "mov r7, #0\n\t" - "mov r8, #0\n\t" - "mov r5, #0\n\t" - "\n1:\n\t" - "subs r3, r5, #28\n\t" - "it cc\n\t" - "movcc r3, r12\n\t" - "sub r4, r5, r3\n\t" - "\n2:\n\t" - "cmp r4, r3\n\t" - "beq 4f\n\t" - "ldr r14, [%[a], r3]\n\t" - "ldr r9, [%[a], r4]\n\t" - "umull r9, r10, r14, r9\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, r12\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, r12\n\t" - "bal 5f\n\t" - "\n4:\n\t" - "ldr r14, [%[a], r3]\n\t" - "umull r9, r10, r14, r14\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, r12\n\t" - "\n5:\n\t" - "add r3, r3, #4\n\t" - "sub r4, r4, #4\n\t" - "cmp r3, #32\n\t" - "beq 3f\n\t" - "cmp r3, r4\n\t" - "bgt 3f\n\t" - "cmp r3, r5\n\t" - "ble 2b\n\t" - "\n3:\n\t" - "str r6, [sp, r5]\n\t" - "mov r6, r7\n\t" - "mov r7, r8\n\t" - "mov r8, #0\n\t" - "add r5, r5, #4\n\t" - "cmp r5, #56\n\t" - "ble 1b\n\t" - "str r6, [sp, r5]\n\t" - "\n4:\n\t" - "ldr r6, [sp, #0]\n\t" - "ldr r7, [sp, #4]\n\t" - "ldr r8, [sp, #8]\n\t" - "ldr r3, [sp, #12]\n\t" - "str r6, [%[r], #0]\n\t" - "str r7, [%[r], #4]\n\t" - "str r8, [%[r], #8]\n\t" - "str r3, [%[r], #12]\n\t" - "add sp, sp, #16\n\t" - "add %[r], %[r], #16\n\t" - "subs r5, r5, #16\n\t" - "bgt 4b\n\t" - : [r] "+r" (r) - : [a] "r" (a) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" - ); -} - -#else -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "sub sp, sp, #32\n\t" - "mov r14, #0\n\t" - "# A[0] * A[0]\n\t" - "ldr r10, [%[a], #0]\n\t" - "umull r8, r3, r10, r10\n\t" - "mov r4, #0\n\t" - "str r8, [sp]\n\t" - "# A[0] * A[1]\n\t" - "ldr r10, [%[a], #4]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [sp, #4]\n\t" - "# A[0] * A[2]\n\t" - "ldr r10, [%[a], #8]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "# A[1] * A[1]\n\t" - "ldr r10, [%[a], #4]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "str r4, [sp, #8]\n\t" - "# A[0] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "# A[1] * A[2]\n\t" - "ldr r10, [%[a], #8]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "str r2, [sp, #12]\n\t" - "# A[0] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[1] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[2] * A[2]\n\t" - "ldr r10, [%[a], #8]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [sp, #16]\n\t" - "# A[0] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [sp, #20]\n\t" - "# A[0] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r4, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r2, r2, r5\n\t" - "adcs r3, r3, r6\n\t" - "adc r4, r4, r7\n\t" - "str r2, [sp, #24]\n\t" - "# A[0] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r2, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r3, r3, r5\n\t" - "adcs r4, r4, r6\n\t" - "adc r2, r2, r7\n\t" - "str r3, [sp, #28]\n\t" - "# A[1] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[2] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [%[r], #32]\n\t" - "# A[2] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r4, #0\n\t" - "mov r7, #0\n\t" - "# A[3] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r2, r2, r5\n\t" - "adcs r3, r3, r6\n\t" - "adc r4, r4, r7\n\t" - "str r2, [%[r], #36]\n\t" - "# A[3] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[4] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[5] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [%[r], #40]\n\t" - "# A[4] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "# A[5] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "str r4, [%[r], #44]\n\t" - "# A[5] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "# A[6] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "str r2, [%[r], #48]\n\t" - "# A[6] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [%[r], #52]\n\t" - "# A[7] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r4, r4, r8\n\t" - "adc r2, r2, r9\n\t" - "str r4, [%[r], #56]\n\t" - "str r2, [%[r], #60]\n\t" - "ldr r2, [sp, #0]\n\t" - "ldr r3, [sp, #4]\n\t" - "ldr r4, [sp, #8]\n\t" - "ldr r8, [sp, #12]\n\t" - "str r2, [%[r], #0]\n\t" - "str r3, [%[r], #4]\n\t" - "str r4, [%[r], #8]\n\t" - "str r8, [%[r], #12]\n\t" - "ldr r2, [sp, #16]\n\t" - "ldr r3, [sp, #20]\n\t" - "ldr r4, [sp, #24]\n\t" - "ldr r8, [sp, #28]\n\t" - "str r2, [%[r], #16]\n\t" - "str r3, [%[r], #20]\n\t" - "str r4, [%[r], #24]\n\t" - "str r8, [%[r], #28]\n\t" - "add sp, sp, #32\n\t" - : - : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" - ); -} - -#endif /* WOLFSSL_SP_SMALL */ -#ifdef WOLFSSL_SP_SMALL /* Order-2 for the P256 curve. */ static const uint32_t p256_order_minus_2[8] = { 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, @@ -36417,7 +36088,7 @@ static const uint32_t p256_order_minus_2[8] = { }; #else /* The low half of the order-2 of the P256 curve. */ -static const uint32_t p256_order_low[4] = { +static const sp_int_digit p256_order_low[4] = { 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU }; #endif /* WOLFSSL_SP_SMALL */ @@ -36563,7 +36234,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ for (i=127; i>=112; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -36573,7 +36244,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ for (i=107; i>=64; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -36583,7 +36254,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ for (i=59; i>=32; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -36593,7 +36264,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ for (i=27; i>=0; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -36604,12 +36275,63 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(k); + + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -36644,8 +36366,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -36663,13 +36385,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 8, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_8(rng, ctx->k); @@ -36697,6 +36416,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_8(ctx->r, p256_order); sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_8(ctx->r); + + sp_256_from_mp(ctx->x, 8, priv); + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); ctx->state = 4; break; } @@ -36753,6 +36475,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -36785,72 +36510,55 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*8]; - sp_digit xd[2*8]; - sp_digit kd[2*8]; - sp_digit rd[2*8]; - sp_digit td[3 * 2*8]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 8]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 8; - x = d + 2 * 8; - k = d + 4 * 8; - r = d + 6 * 8; - tmp = d + 8 * 8; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 8; + k = e + 4 * 8; + r = e + 6 * 8; + tmp = e + 8 * 8; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 8, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 8, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_8(rng, k); @@ -36860,7 +36568,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -36871,38 +36579,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_8(r); - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_8(k, k, p256_norm_order); - err = sp_256_mod_8(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_8(k); - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_8(kInv, k, tmp); - sp_256_norm_8(kInv); + sp_256_from_mp(x, 8, priv); + sp_256_from_bin(e, 8, hash, (int)hashLen); - /* s = r * x + e */ - sp_256_mul_8(x, x, r); - err = sp_256_mod_8(x, x, p256_order); + err = sp_256_calc_s_8(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_8(x); - carry = sp_256_add_8(s, e, x); - sp_256_cond_sub_8(s, s, p256_order, 0 - carry); - sp_256_norm_8(s); - c = sp_256_cmp_8(s, p256_order); - sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_8(s); - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_8(s, s, kInv); - sp_256_norm_8(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_8(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -36916,20 +36605,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_8(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -37222,6 +36915,96 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ + + sp_256_proj_point_add_8(p1, p1, p2, tmp); + if (sp_256_iszero_8(p1->z)) { + if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { + sp_256_proj_point_dbl_8(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_256_mod_inv_8(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_256_mul_8(s, s, p256_norm_order); + } + err = sp_256_mod_8(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + +#else + { + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_8(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -37240,8 +37023,7 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -37260,8 +37042,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -37276,7 +37059,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); sp_256_from_mp(ctx->s, 8, sm); sp_256_from_mp(ctx->p2.x, 8, pX); sp_256_from_mp(ctx->p2.y, 8, pY); @@ -37334,57 +37117,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_8(ctx->p1.z)) { - if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<8; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -37392,22 +37151,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_8(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -37415,130 +37175,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*8]; - sp_digit u2d[2*8]; - sp_digit sd[2*8]; - sp_digit tmpd[2*8 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 8]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_8(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 8; - u2 = d + 2 * 8; - s = d + 4 * 8; - tmp = d + 6 * 8; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 8; + s = u1 + 4 * 8; + tmp = u1 + 6 * 8; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 8, hash, (int)hashLen); - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); sp_256_from_mp(s, 8, sm); sp_256_from_mp(p2->x, 8, pX); sp_256_from_mp(p2->y, 8, pY); sp_256_from_mp(p2->z, 8, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_256_mod_inv_8(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_8(s, s, p256_norm_order); - } - err = sp_256_mod_8(s, s, p256_order); + err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_8(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_8(s, s, tmp); - sp_256_mont_mul_order_8(u1, u1, s); - sp_256_mont_mul_order_8(u2, u2, s); - } - -#else - { - sp_256_mont_mul_order_8(u1, u1, s); - sp_256_mont_mul_order_8(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_256_proj_point_add_8(p1, p1, p2, tmp); - if (sp_256_iszero_8(p1->z)) { - if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { - sp_256_proj_point_dbl_8(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); } @@ -37549,7 +37242,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); carry = sp_256_add_8(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -37557,26 +37250,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_8(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_8(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p1, 0, heap); - sp_256_point_free_8(p2, 0, heap); return err; } @@ -37590,34 +37283,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_8(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*8]; - sp_digit t2d[2*8]; + sp_digit t1[8 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 8; - t2 = d + 2 * 8; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 8; sp_256_sqr_8(t1, point->y); (void)sp_256_mod_8(t1, t1, p256_mod); @@ -37637,10 +37322,9 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -37653,16 +37337,23 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_8(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 8, pX); sp_256_from_mp(pub->y, 8, pY); @@ -37671,7 +37362,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_8(pub, NULL); } - sp_256_point_free_8(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -37687,47 +37381,48 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[8]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; - sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_256_point_new_8(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_256* pub = NULL; +#else + sp_digit priv[8]; + sp_point_256 pub[2]; #endif + sp_point_256* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 8, pX); sp_256_from_mp(pub->y, 8, pY); sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); @@ -37741,12 +37436,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || - sp_256_cmp_8(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_8(pub->x, p256_mod) >= 0) || + (sp_256_cmp_8(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -37758,12 +37452,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_8(p->x) == 0) || - (sp_256_iszero_8(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) || + (sp_256_iszero_8(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -37771,22 +37463,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_8(p->x, pub->x) != 0 || - sp_256_cmp_8(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_8(p->x, pub->x) != 0) || + (sp_256_cmp_8(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(pub, 0, heap); return err; } @@ -37810,33 +37500,35 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; - err = sp_256_point_new_8(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 8, pX); sp_256_from_mp(p->y, 8, pY); sp_256_from_mp(p->z, 8, pZ); @@ -37857,13 +37549,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(q, 0, NULL); - sp_256_point_free_8(p, 0, NULL); return err; } @@ -37882,25 +37573,28 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_8(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -37921,12 +37615,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, NULL); return err; } @@ -37941,32 +37635,36 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_8(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 8, pX); sp_256_from_mp(p->y, 8, pY); sp_256_from_mp(p->z, 8, pZ); - sp_256_map_8(p, p, tmp); + sp_256_map_8(p, p, tmp); } if (err == MP_OKAY) { @@ -37979,12 +37677,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, NULL); return err; } @@ -37997,31 +37695,23 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_8(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 8]; - sp_digit t2d[2 * 8]; + sp_digit t1[4 * 8]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 8; - t2 = d + 2 * 8; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 8; { /* t2 = y ^ 0x2 */ @@ -38056,10 +37746,9 @@ static int sp_256_mont_sqrt_8(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -38075,31 +37764,22 @@ static int sp_256_mont_sqrt_8(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 8]; - sp_digit yd[2 * 8]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 8]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 8; - y = d + 2 * 8; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 8; sp_256_from_mp(x, 8, xm); err = sp_256_mod_mul_norm_8(x, x, p256_mod); @@ -38132,10 +37812,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -38146,9 +37825,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 12]; + /* Y ordinate of point. */ sp_digit y[2 * 12]; + /* Z ordinate of point. */ sp_digit z[2 * 12]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; @@ -38218,336 +37901,6 @@ static const sp_digit p384_b[12] = { }; #endif -static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* t; -#else - int64_t t[12]; -#endif - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); - if (t == NULL) { - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ - t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11]; - /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ - t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11]; - /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ - t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11]; - /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ - t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11]; - /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ - t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11]; - /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ - t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11]; - /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ - t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11]; - /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ - t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11]; - /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ - t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8]; - /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ - t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9]; - /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ - t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10]; - /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ - t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - o = t[11] >> 32; t[11] &= 0xffffffff; - t[0] += o; - t[1] -= o; - t[3] += o; - t[4] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - - r[0] = t[0]; - r[1] = t[1]; - r[2] = t[2]; - r[3] = t[3]; - r[4] = t[4]; - r[5] = t[5]; - r[6] = t[6]; - r[7] = t[7]; - r[8] = t[8]; - r[9] = t[9]; - r[10] = t[10]; - r[11] = t[11]; - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) - XFREE(t, NULL, DYNAMIC_TYPE_ECC); -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 32 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 32 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xffffffff; - s = 32U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 32U) <= (word32)DIGIT_BIT) { - s += 32U; - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 32) { - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - s = 32 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_384. - * - * p Point of type sp_point_384 (result). - * pm Point of type ecc_point. - */ -static void sp_384_point_from_ecc_point_12(sp_point_384* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_384_from_mp(p->x, 12, pm->x); - sp_384_from_mp(p->y, 12, pm->y); - sp_384_from_mp(p->z, 12, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_384_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 32 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); - r->used = 12; - mp_clamp(r); -#elif DIGIT_BIT < 32 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 12; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 32) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 32 - s; - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 12; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 32 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 32 - s; - } - else { - s += 32; - } - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_384 to type ecc_point. - * - * p Point of type sp_point_384. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) -{ - int err; - - err = sp_384_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pm->z); - } - - return err; -} - #ifdef WOLFSSL_SP_SMALL /* Multiply a and b into r. (r = a * b) * @@ -38622,66 +37975,60 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "sub sp, sp, #48\n\t" "mov r10, #0\n\t" "# A[0] * B[0]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r3, r4, r8, r9\n\t" + "ldr r11, [%[a], #0]\n\t" + "ldr r12, [%[b], #0]\n\t" + "umull r3, r4, r11, r12\n\t" "mov r5, #0\n\t" "str r3, [sp]\n\t" "# A[0] * B[1]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" "# A[1] * B[0]\n\t" "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #4]\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r11, [%[a], #4]\n\t" + "ldr r12, [%[b], #4]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" "# A[0] * B[2]\n\t" "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #8]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[1] * B[1]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[0]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #0]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #8]\n\t" "# A[0] * B[3]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" "# A[1] * B[2]\n\t" - "ldr r8, [%[a], #4]\n\t" "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[2] * B[1]\n\t" "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -38693,13 +38040,25 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #12]\n\t" - "# A[0] * B[4]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r11, [%[a], #8]\n\t" + "ldr r12, [%[b], #8]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" "# A[1] * B[3]\n\t" "ldr r8, [%[a], #4]\n\t" "ldr r9, [%[b], #12]\n\t" @@ -38707,30 +38066,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[2] * B[2]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[1]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[0]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #16]\n\t" "# A[0] * B[5]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" @@ -38744,16 +38088,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[2] * B[3]\n\t" - "ldr r8, [%[a], #8]\n\t" "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[3] * B[2]\n\t" "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -38772,20 +38114,32 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #20]\n\t" - "# A[0] * B[6]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #24]\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" - "# A[1] * B[5]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #20]\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r11, [%[a], #12]\n\t" + "ldr r12, [%[b], #12]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" "# A[2] * B[4]\n\t" "ldr r8, [%[a], #8]\n\t" "ldr r9, [%[b], #16]\n\t" @@ -38793,37 +38147,22 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[3] * B[3]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[4] * B[2]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #8]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[1]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #4]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[0]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #24]\n\t" "# A[0] * B[7]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" @@ -38844,16 +38183,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[3] * B[4]\n\t" - "ldr r8, [%[a], #12]\n\t" "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[4] * B[3]\n\t" "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #12]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -38879,44 +38216,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #28]\n\t" - "# A[0] * B[8]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #32]\n\t" + "# A[8] * B[0]\n\t" + "ldr r8, [%[a], #32]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r10, r10\n\t" - "# A[1] * B[7]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[2] * B[6]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[3] * B[5]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[4] * B[4]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[5] * B[3]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -38928,23 +38236,49 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[7] * B[1]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r11, [%[a], #16]\n\t" + "ldr r12, [%[b], #16]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[8] * B[0]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[0] * B[8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #32]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #32]\n\t" "# A[0] * B[9]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #36]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" @@ -38972,16 +38306,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[4] * B[5]\n\t" - "ldr r8, [%[a], #16]\n\t" "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[5] * B[4]\n\t" "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -39014,58 +38346,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [sp, #36]\n\t" - "# A[0] * B[10]\n\t" - "ldr r8, [%[a], #0]\n\t" - "ldr r9, [%[b], #40]\n\t" + "# A[10] * B[0]\n\t" + "ldr r8, [%[a], #40]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" - "# A[1] * B[9]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[2] * B[8]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[3] * B[7]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[4] * B[6]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[5] * B[5]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[6] * B[4]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #16]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[7] * B[3]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[9] * B[1]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -39077,23 +38366,63 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[9] * B[1]\n\t" - "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[10] * B[0]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #0]\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r11, [%[a], #20]\n\t" + "ldr r12, [%[b], #20]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[8]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[1] * B[9]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[0] * B[10]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #40]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [sp, #40]\n\t" "# A[0] * B[11]\n\t" - "ldr r8, [%[a], #0]\n\t" "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" @@ -39128,16 +38457,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[5] * B[6]\n\t" - "ldr r8, [%[a], #20]\n\t" "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[6] * B[5]\n\t" "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -39177,58 +38504,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [sp, #44]\n\t" - "# A[1] * B[11]\n\t" - "ldr r8, [%[a], #4]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" - "# A[2] * B[10]\n\t" - "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[3] * B[9]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[4] * B[8]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[5] * B[7]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[6] * B[6]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[7] * B[5]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #20]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[8] * B[4]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[10] * B[2]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #8]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -39240,16 +38524,57 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[10] * B[2]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #8]\n\t" + "# A[8] * B[4]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[11] * B[1]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #4]\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r11, [%[a], #24]\n\t" + "ldr r12, [%[b], #24]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[9]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[10]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[1] * B[11]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -39257,7 +38582,6 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r3, [%[r], #48]\n\t" "# A[2] * B[11]\n\t" "ldr r8, [%[a], #8]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -39284,16 +38608,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[6] * B[7]\n\t" - "ldr r8, [%[a], #24]\n\t" "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[7] * B[6]\n\t" "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -39326,44 +38648,15 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [%[r], #52]\n\t" - "# A[3] * B[11]\n\t" - "ldr r8, [%[a], #12]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r10, r10\n\t" - "# A[4] * B[10]\n\t" - "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[5] * B[9]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[6] * B[8]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[7] * B[7]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[8] * B[6]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #24]\n\t" + "# A[10] * B[4]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #16]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -39375,16 +38668,43 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[10] * B[4]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #16]\n\t" + "# A[8] * B[6]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[7]\n\t" + "ldr r11, [%[a], #28]\n\t" + "ldr r12, [%[b], #28]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #32]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" - "# A[11] * B[3]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #12]\n\t" + "# A[5] * B[9]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[10]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[11]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -39392,7 +38712,6 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r5, [%[r], #56]\n\t" "# A[4] * B[11]\n\t" "ldr r8, [%[a], #16]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -39412,16 +38731,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[7] * B[8]\n\t" - "ldr r8, [%[a], #28]\n\t" "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "# A[8] * B[7]\n\t" "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" @@ -39447,20 +38764,32 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [%[r], #60]\n\t" - "# A[5] * B[11]\n\t" - "ldr r8, [%[a], #20]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" - "# A[6] * B[10]\n\t" - "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #40]\n\t" + "# A[10] * B[6]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #24]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" + "# A[9] * B[7]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[8]\n\t" + "ldr r11, [%[a], #32]\n\t" + "ldr r12, [%[b], #32]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" "# A[7] * B[9]\n\t" "ldr r8, [%[a], #28]\n\t" "ldr r9, [%[b], #36]\n\t" @@ -39468,30 +38797,16 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[8] * B[8]\n\t" - "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #32]\n\t" + "# A[6] * B[10]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #40]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" - "# A[9] * B[7]\n\t" - "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #28]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[10] * B[6]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #24]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" - "# A[11] * B[5]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #20]\n\t" + "# A[5] * B[11]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" @@ -39499,7 +38814,6 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r4, [%[r], #64]\n\t" "# A[6] * B[11]\n\t" "ldr r8, [%[a], #24]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" @@ -39512,16 +38826,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[8] * B[9]\n\t" - "ldr r8, [%[a], #32]\n\t" "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "# A[9] * B[8]\n\t" "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" @@ -39540,13 +38852,25 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [%[r], #68]\n\t" - "# A[7] * B[11]\n\t" - "ldr r8, [%[a], #28]\n\t" - "ldr r9, [%[b], #44]\n\t" + "# A[11] * B[7]\n\t" + "ldr r9, [%[b], #28]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" + "# A[10] * B[8]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[9]\n\t" + "ldr r11, [%[a], #36]\n\t" + "ldr r12, [%[b], #36]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" "# A[8] * B[10]\n\t" "ldr r8, [%[a], #32]\n\t" "ldr r9, [%[b], #40]\n\t" @@ -39554,23 +38878,9 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" - "# A[9] * B[9]\n\t" - "ldr r8, [%[a], #36]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[10] * B[8]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #32]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" - "# A[11] * B[7]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #28]\n\t" + "# A[7] * B[11]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" @@ -39578,22 +38888,19 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "str r3, [%[r], #72]\n\t" "# A[8] * B[11]\n\t" "ldr r8, [%[a], #32]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r10, r10\n\t" "# A[9] * B[10]\n\t" - "ldr r8, [%[a], #36]\n\t" "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "# A[10] * B[9]\n\t" "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" @@ -39605,83 +38912,1339 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "adcs r5, r5, r7\n\t" "adc r3, r3, r10\n\t" "str r4, [%[r], #76]\n\t" + "# A[11] * B[9]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[10] * B[10]\n\t" + "ldr r11, [%[a], #40]\n\t" + "ldr r12, [%[b], #40]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" "# A[9] * B[11]\n\t" "ldr r8, [%[a], #36]\n\t" "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r10, r10\n\t" - "# A[10] * B[10]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" - "# A[11] * B[9]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #36]\n\t" - "umull r6, r7, r8, r9\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r7\n\t" "adc r4, r4, r10\n\t" "str r5, [%[r], #80]\n\t" "# A[10] * B[11]\n\t" - "ldr r8, [%[a], #40]\n\t" - "ldr r9, [%[b], #44]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r11, r9\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r10, r10\n\t" "# A[11] * B[10]\n\t" "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #40]\n\t" - "umull r6, r7, r8, r9\n\t" + "umull r6, r7, r8, r12\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" "adc r5, r5, r10\n\t" "str r3, [%[r], #84]\n\t" "# A[11] * B[11]\n\t" - "ldr r8, [%[a], #44]\n\t" - "ldr r9, [%[b], #44]\n\t" "umull r6, r7, r8, r9\n\t" "adds r4, r4, r6\n\t" "adc r5, r5, r7\n\t" "str r4, [%[r], #88]\n\t" "str r5, [%[r], #92]\n\t" - "ldr r3, [sp, #0]\n\t" - "ldr r4, [sp, #4]\n\t" - "ldr r5, [sp, #8]\n\t" - "ldr r6, [sp, #12]\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [sp, #16]\n\t" - "ldr r4, [sp, #20]\n\t" - "ldr r5, [sp, #24]\n\t" - "ldr r6, [sp, #28]\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - "ldr r3, [sp, #32]\n\t" - "ldr r4, [sp, #36]\n\t" - "ldr r5, [sp, #40]\n\t" - "ldr r6, [sp, #44]\n\t" - "str r3, [%[r], #32]\n\t" - "str r4, [%[r], #36]\n\t" - "str r5, [%[r], #40]\n\t" - "str r6, [%[r], #44]\n\t" - "add sp, sp, #48\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "sub %[r], %[r], #48\n\t" : : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); } #endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #96\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #44\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #48\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #88\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #48\n\t" + "mov r12, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[0] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #32]\n\t" + "# A[0] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #36]\n\t" + "# A[0] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #40]\n\t" + "# A[0] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #44]\n\t" + "# A[1] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #48]\n\t" + "# A[2] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #52]\n\t" + "# A[3] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[4] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #56]\n\t" + "# A[4] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[5] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #60]\n\t" + "# A[5] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[6] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #64]\n\t" + "# A[6] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[7] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #68]\n\t" + "# A[7] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[8] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[9] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [%[r], #72]\n\t" + "# A[8] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[9] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [%[r], #76]\n\t" + "# A[9] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[10] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [%[r], #80]\n\t" + "# A[10] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [%[r], #84]\n\t" + "# A[11] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adc r4, r4, r9\n\t" + "str r3, [%[r], #88]\n\t" + "str r4, [%[r], #92]\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "sub %[r], %[r], #48\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #48\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #48\n\t" + "\n1:\n\t" + "rsbs %[c], %[c], #0\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "sbc %[c], r4, r4\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r7, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "ldr r10, [%[b], #44]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[12]; +#endif + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + r[8] = t[8]; + r[9] = t[9]; + r[10] = t[10]; + r[11] = t[11]; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_12(sp_point_384* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_384_from_mp(p->x, 12, pm->x); + sp_384_from_mp(p->y, 12, pm->y); + sp_384_from_mp(p->z, 12, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); + r->used = 12; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -39802,6 +40365,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp_digit ca = 0; __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" "# i = 0\n\t" "mov r12, #0\n\t" "ldr r10, [%[a], #0]\n\t" @@ -39810,13 +40374,12 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "# mu = a[i] * mp\n\t" "mul r8, %[mp], r10\n\t" "# a[i+0] += m[0] * mu\n\t" - "ldr r7, [%[m], #0]\n\t" "ldr r9, [%[a], #0]\n\t" - "umull r6, r7, r8, r7\n\t" + "umull r6, r7, r8, r11\n\t" "adds r10, r10, r6\n\t" "adc r5, r7, #0\n\t" "# a[i+1] += m[1] * mu\n\t" - "ldr r7, [%[m], #4]\n\t" + "ldr r7, [%[m], #4]\n\t" "ldr r9, [%[a], #4]\n\t" "umull r6, r7, r8, r7\n\t" "adds r10, r14, r6\n\t" @@ -39824,7 +40387,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "adds r10, r10, r5\n\t" "adc r4, r4, #0\n\t" "# a[i+2] += m[2] * mu\n\t" - "ldr r7, [%[m], #8]\n\t" + "ldr r7, [%[m], #8]\n\t" "ldr r14, [%[a], #8]\n\t" "umull r6, r7, r8, r7\n\t" "adds r14, r14, r6\n\t" @@ -39832,7 +40395,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "adds r14, r14, r4\n\t" "adc r5, r5, #0\n\t" "# a[i+3] += m[3] * mu\n\t" - "ldr r7, [%[m], #12]\n\t" + "ldr r7, [%[m], #12]\n\t" "ldr r9, [%[a], #12]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39841,7 +40404,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #12]\n\t" "adc r4, r4, #0\n\t" "# a[i+4] += m[4] * mu\n\t" - "ldr r7, [%[m], #16]\n\t" + "ldr r7, [%[m], #16]\n\t" "ldr r9, [%[a], #16]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39850,7 +40413,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #16]\n\t" "adc r5, r5, #0\n\t" "# a[i+5] += m[5] * mu\n\t" - "ldr r7, [%[m], #20]\n\t" + "ldr r7, [%[m], #20]\n\t" "ldr r9, [%[a], #20]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39859,7 +40422,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #20]\n\t" "adc r4, r4, #0\n\t" "# a[i+6] += m[6] * mu\n\t" - "ldr r7, [%[m], #24]\n\t" + "ldr r7, [%[m], #24]\n\t" "ldr r9, [%[a], #24]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39868,7 +40431,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #24]\n\t" "adc r5, r5, #0\n\t" "# a[i+7] += m[7] * mu\n\t" - "ldr r7, [%[m], #28]\n\t" + "ldr r7, [%[m], #28]\n\t" "ldr r9, [%[a], #28]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39877,7 +40440,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #28]\n\t" "adc r4, r4, #0\n\t" "# a[i+8] += m[8] * mu\n\t" - "ldr r7, [%[m], #32]\n\t" + "ldr r7, [%[m], #32]\n\t" "ldr r9, [%[a], #32]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39886,7 +40449,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #32]\n\t" "adc r5, r5, #0\n\t" "# a[i+9] += m[9] * mu\n\t" - "ldr r7, [%[m], #36]\n\t" + "ldr r7, [%[m], #36]\n\t" "ldr r9, [%[a], #36]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39895,7 +40458,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r9, [%[a], #36]\n\t" "adc r4, r4, #0\n\t" "# a[i+10] += m[10] * mu\n\t" - "ldr r7, [%[m], #40]\n\t" + "ldr r7, [%[m], #40]\n\t" "ldr r9, [%[a], #40]\n\t" "umull r6, r7, r8, r7\n\t" "adds r9, r9, r6\n\t" @@ -39926,7 +40489,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, "str r14, [%[a], #4]\n\t" : [ca] "+r" (ca), [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" ); sp_384_cond_sub_12(a - 12, a, m, (sp_digit)0 - ca); @@ -39941,788 +40504,13 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_12(r, a, b); sp_384_mont_reduce_12(r, m, mp); } -#ifdef WOLFSSL_SP_SMALL -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "sub sp, sp, #96\n\t" - "mov r12, #0\n\t" - "mov r6, #0\n\t" - "mov r7, #0\n\t" - "mov r8, #0\n\t" - "mov r5, #0\n\t" - "\n1:\n\t" - "subs r3, r5, #44\n\t" - "it cc\n\t" - "movcc r3, r12\n\t" - "sub r4, r5, r3\n\t" - "\n2:\n\t" - "cmp r4, r3\n\t" - "beq 4f\n\t" - "ldr r14, [%[a], r3]\n\t" - "ldr r9, [%[a], r4]\n\t" - "umull r9, r10, r14, r9\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, r12\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, r12\n\t" - "bal 5f\n\t" - "\n4:\n\t" - "ldr r14, [%[a], r3]\n\t" - "umull r9, r10, r14, r14\n\t" - "adds r6, r6, r9\n\t" - "adcs r7, r7, r10\n\t" - "adc r8, r8, r12\n\t" - "\n5:\n\t" - "add r3, r3, #4\n\t" - "sub r4, r4, #4\n\t" - "cmp r3, #48\n\t" - "beq 3f\n\t" - "cmp r3, r4\n\t" - "bgt 3f\n\t" - "cmp r3, r5\n\t" - "ble 2b\n\t" - "\n3:\n\t" - "str r6, [sp, r5]\n\t" - "mov r6, r7\n\t" - "mov r7, r8\n\t" - "mov r8, #0\n\t" - "add r5, r5, #4\n\t" - "cmp r5, #88\n\t" - "ble 1b\n\t" - "str r6, [sp, r5]\n\t" - "\n4:\n\t" - "ldr r6, [sp, #0]\n\t" - "ldr r7, [sp, #4]\n\t" - "ldr r8, [sp, #8]\n\t" - "ldr r3, [sp, #12]\n\t" - "str r6, [%[r], #0]\n\t" - "str r7, [%[r], #4]\n\t" - "str r8, [%[r], #8]\n\t" - "str r3, [%[r], #12]\n\t" - "add sp, sp, #16\n\t" - "add %[r], %[r], #16\n\t" - "subs r5, r5, #16\n\t" - "bgt 4b\n\t" - : [r] "+r" (r) - : [a] "r" (a) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" - ); -} - -#else -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "sub sp, sp, #48\n\t" - "mov r14, #0\n\t" - "# A[0] * A[0]\n\t" - "ldr r10, [%[a], #0]\n\t" - "umull r8, r3, r10, r10\n\t" - "mov r4, #0\n\t" - "str r8, [sp]\n\t" - "# A[0] * A[1]\n\t" - "ldr r10, [%[a], #4]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [sp, #4]\n\t" - "# A[0] * A[2]\n\t" - "ldr r10, [%[a], #8]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "# A[1] * A[1]\n\t" - "ldr r10, [%[a], #4]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "str r4, [sp, #8]\n\t" - "# A[0] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "# A[1] * A[2]\n\t" - "ldr r10, [%[a], #8]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "str r2, [sp, #12]\n\t" - "# A[0] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[1] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[2] * A[2]\n\t" - "ldr r10, [%[a], #8]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [sp, #16]\n\t" - "# A[0] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [sp, #20]\n\t" - "# A[0] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r4, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[3]\n\t" - "ldr r10, [%[a], #12]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r2, r2, r5\n\t" - "adcs r3, r3, r6\n\t" - "adc r4, r4, r7\n\t" - "str r2, [sp, #24]\n\t" - "# A[0] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r2, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r3, r3, r5\n\t" - "adcs r4, r4, r6\n\t" - "adc r2, r2, r7\n\t" - "str r3, [sp, #28]\n\t" - "# A[0] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[4]\n\t" - "ldr r10, [%[a], #16]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [sp, #32]\n\t" - "# A[0] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r4, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r2, r2, r5\n\t" - "adcs r3, r3, r6\n\t" - "adc r4, r4, r7\n\t" - "str r2, [sp, #36]\n\t" - "# A[0] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r2, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[5] * A[5]\n\t" - "ldr r10, [%[a], #20]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r3, r3, r5\n\t" - "adcs r4, r4, r6\n\t" - "adc r2, r2, r7\n\t" - "str r3, [sp, #40]\n\t" - "# A[0] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #0]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[1] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[2] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[5] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [sp, #44]\n\t" - "# A[1] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #4]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r4, #0\n\t" - "mov r7, #0\n\t" - "# A[2] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[3] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[5] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[6] * A[6]\n\t" - "ldr r10, [%[a], #24]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r2, r2, r5\n\t" - "adcs r3, r3, r6\n\t" - "adc r4, r4, r7\n\t" - "str r2, [%[r], #48]\n\t" - "# A[2] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r2, #0\n\t" - "mov r7, #0\n\t" - "# A[3] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[4] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[5] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[6] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r3, r3, r5\n\t" - "adcs r4, r4, r6\n\t" - "adc r2, r2, r7\n\t" - "str r3, [%[r], #52]\n\t" - "# A[3] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[4] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[5] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[6] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[7] * A[7]\n\t" - "ldr r10, [%[a], #28]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [%[r], #56]\n\t" - "# A[4] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r4, #0\n\t" - "mov r7, #0\n\t" - "# A[5] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[6] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[7] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r2, r2, r5\n\t" - "adcs r3, r3, r6\n\t" - "adc r4, r4, r7\n\t" - "str r2, [%[r], #60]\n\t" - "# A[5] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r2, #0\n\t" - "mov r7, #0\n\t" - "# A[6] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[7] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[8] * A[8]\n\t" - "ldr r10, [%[a], #32]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r3, r3, r5\n\t" - "adcs r4, r4, r6\n\t" - "adc r2, r2, r7\n\t" - "str r3, [%[r], #64]\n\t" - "# A[6] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r5, r6, r10, r8\n\t" - "mov r3, #0\n\t" - "mov r7, #0\n\t" - "# A[7] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "# A[8] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "ldr r8, [%[a], #32]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r5, r5, r8\n\t" - "adcs r6, r6, r9\n\t" - "adc r7, r7, r14\n\t" - "adds r5, r5, r5\n\t" - "adcs r6, r6, r6\n\t" - "adc r7, r7, r7\n\t" - "adds r4, r4, r5\n\t" - "adcs r2, r2, r6\n\t" - "adc r3, r3, r7\n\t" - "str r4, [%[r], #68]\n\t" - "# A[7] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "# A[8] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #32]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "# A[9] * A[9]\n\t" - "ldr r10, [%[a], #36]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "str r2, [%[r], #72]\n\t" - "# A[8] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #32]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r14, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "# A[9] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "ldr r8, [%[a], #36]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "adds r3, r3, r8\n\t" - "adcs r4, r4, r9\n\t" - "adc r2, r2, r14\n\t" - "str r3, [%[r], #76]\n\t" - "# A[9] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #36]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r14, r14\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "# A[10] * A[10]\n\t" - "ldr r10, [%[a], #40]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r4, r4, r8\n\t" - "adcs r2, r2, r9\n\t" - "adc r3, r3, r14\n\t" - "str r4, [%[r], #80]\n\t" - "# A[10] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "ldr r8, [%[a], #40]\n\t" - "umull r8, r9, r10, r8\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r14, r14\n\t" - "adds r2, r2, r8\n\t" - "adcs r3, r3, r9\n\t" - "adc r4, r4, r14\n\t" - "str r2, [%[r], #84]\n\t" - "# A[11] * A[11]\n\t" - "ldr r10, [%[a], #44]\n\t" - "umull r8, r9, r10, r10\n\t" - "adds r3, r3, r8\n\t" - "adc r4, r4, r9\n\t" - "str r3, [%[r], #88]\n\t" - "str r4, [%[r], #92]\n\t" - "ldr r2, [sp, #0]\n\t" - "ldr r3, [sp, #4]\n\t" - "ldr r4, [sp, #8]\n\t" - "ldr r8, [sp, #12]\n\t" - "str r2, [%[r], #0]\n\t" - "str r3, [%[r], #4]\n\t" - "str r4, [%[r], #8]\n\t" - "str r8, [%[r], #12]\n\t" - "ldr r2, [sp, #16]\n\t" - "ldr r3, [sp, #20]\n\t" - "ldr r4, [sp, #24]\n\t" - "ldr r8, [sp, #28]\n\t" - "str r2, [%[r], #16]\n\t" - "str r3, [%[r], #20]\n\t" - "str r4, [%[r], #24]\n\t" - "str r8, [%[r], #28]\n\t" - "ldr r2, [sp, #32]\n\t" - "ldr r3, [sp, #36]\n\t" - "ldr r4, [sp, #40]\n\t" - "ldr r8, [sp, #44]\n\t" - "str r2, [%[r], #32]\n\t" - "str r3, [%[r], #36]\n\t" - "str r4, [%[r], #40]\n\t" - "str r8, [%[r], #44]\n\t" - "add sp, sp, #48\n\t" - : - : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" - ); -} - -#endif /* WOLFSSL_SP_SMALL */ /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -40730,8 +40518,8 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_12(r, a); sp_384_mont_reduce_12(r, m, mp); @@ -40755,7 +40543,7 @@ static void sp_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint32_t p384_mod_minus_2[12] = { @@ -41044,7 +40832,8 @@ static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*12; @@ -41080,122 +40869,6 @@ static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "add r12, %[a], #48\n\t" - "\n1:\n\t" - "adds %[c], %[c], #-1\n\t" - "ldr r4, [%[a]], #4\n\t" - "ldr r5, [%[a]], #4\n\t" - "ldr r6, [%[a]], #4\n\t" - "ldr r7, [%[a]], #4\n\t" - "ldr r8, [%[b]], #4\n\t" - "ldr r9, [%[b]], #4\n\t" - "ldr r10, [%[b]], #4\n\t" - "ldr r14, [%[b]], #4\n\t" - "adcs r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r]], #4\n\t" - "str r5, [%[r]], #4\n\t" - "str r6, [%[r]], #4\n\t" - "str r7, [%[r]], #4\n\t" - "mov r4, #0\n\t" - "adc %[c], r4, #0\n\t" - "cmp %[a], r12\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); - - return c; -} - -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r12, #0\n\t" - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[a], #4]\n\t" - "ldr r6, [%[a], #8]\n\t" - "ldr r7, [%[a], #12]\n\t" - "ldr r8, [%[b], #0]\n\t" - "ldr r9, [%[b], #4]\n\t" - "ldr r10, [%[b], #8]\n\t" - "ldr r14, [%[b], #12]\n\t" - "adds r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r], #0]\n\t" - "str r5, [%[r], #4]\n\t" - "str r6, [%[r], #8]\n\t" - "str r7, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[a], #20]\n\t" - "ldr r6, [%[a], #24]\n\t" - "ldr r7, [%[a], #28]\n\t" - "ldr r8, [%[b], #16]\n\t" - "ldr r9, [%[b], #20]\n\t" - "ldr r10, [%[b], #24]\n\t" - "ldr r14, [%[b], #28]\n\t" - "adcs r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r], #16]\n\t" - "str r5, [%[r], #20]\n\t" - "str r6, [%[r], #24]\n\t" - "str r7, [%[r], #28]\n\t" - "ldr r4, [%[a], #32]\n\t" - "ldr r5, [%[a], #36]\n\t" - "ldr r6, [%[a], #40]\n\t" - "ldr r7, [%[a], #44]\n\t" - "ldr r8, [%[b], #32]\n\t" - "ldr r9, [%[b], #36]\n\t" - "ldr r10, [%[b], #40]\n\t" - "ldr r14, [%[b], #44]\n\t" - "adcs r4, r4, r8\n\t" - "adcs r5, r5, r9\n\t" - "adcs r6, r6, r10\n\t" - "adcs r7, r7, r14\n\t" - "str r4, [%[r], #32]\n\t" - "str r5, [%[r], #36]\n\t" - "str r6, [%[r], #40]\n\t" - "str r7, [%[r], #44]\n\t" - "adc %[c], r12, r12\n\t" - : [c] "+r" (c) - : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -41242,120 +40915,6 @@ static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_digit* m sp_384_cond_sub_12(r, r, m, 0 - o); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "add r12, %[a], #48\n\t" - "\n1:\n\t" - "rsbs %[c], %[c], #0\n\t" - "ldr r4, [%[a]], #4\n\t" - "ldr r5, [%[a]], #4\n\t" - "ldr r6, [%[a]], #4\n\t" - "ldr r7, [%[a]], #4\n\t" - "ldr r8, [%[b]], #4\n\t" - "ldr r9, [%[b]], #4\n\t" - "ldr r10, [%[b]], #4\n\t" - "ldr r14, [%[b]], #4\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "sbcs r7, r7, r14\n\t" - "str r4, [%[r]], #4\n\t" - "str r5, [%[r]], #4\n\t" - "str r6, [%[r]], #4\n\t" - "str r7, [%[r]], #4\n\t" - "sbc %[c], r4, r4\n\t" - "cmp %[a], r12\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" - ); - - return c; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r3, [%[a], #0]\n\t" - "ldr r4, [%[a], #4]\n\t" - "ldr r5, [%[a], #8]\n\t" - "ldr r6, [%[a], #12]\n\t" - "ldr r7, [%[b], #0]\n\t" - "ldr r8, [%[b], #4]\n\t" - "ldr r9, [%[b], #8]\n\t" - "ldr r10, [%[b], #12]\n\t" - "subs r3, r3, r7\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [%[a], #16]\n\t" - "ldr r4, [%[a], #20]\n\t" - "ldr r5, [%[a], #24]\n\t" - "ldr r6, [%[a], #28]\n\t" - "ldr r7, [%[b], #16]\n\t" - "ldr r8, [%[b], #20]\n\t" - "ldr r9, [%[b], #24]\n\t" - "ldr r10, [%[b], #28]\n\t" - "sbcs r3, r3, r7\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - "ldr r3, [%[a], #32]\n\t" - "ldr r4, [%[a], #36]\n\t" - "ldr r5, [%[a], #40]\n\t" - "ldr r6, [%[a], #44]\n\t" - "ldr r7, [%[b], #32]\n\t" - "ldr r8, [%[b], #36]\n\t" - "ldr r9, [%[b], #40]\n\t" - "ldr r10, [%[b], #44]\n\t" - "sbcs r3, r3, r7\n\t" - "sbcs r4, r4, r8\n\t" - "sbcs r5, r5, r9\n\t" - "sbcs r6, r6, r10\n\t" - "str r3, [%[r], #32]\n\t" - "str r4, [%[r], #36]\n\t" - "str r5, [%[r], #40]\n\t" - "str r6, [%[r], #44]\n\t" - "sbc %[c], %[c], #0\n\t" - : [c] "+r" (c) - : [r] "r" (r), [a] "r" (a), [b] "r" (b) - : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -41968,8 +41527,8 @@ static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_12(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -42148,9 +41707,11 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Simple, smaller code size and memory size, of windowing. - * Calculate uindow of 4 bits. - * Only add points from table. + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 384 doubles. + * 108 adds. * * r Resulting point. * g Point to multiply. @@ -42163,55 +41724,55 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table, static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td[16]; - sp_point_384 rtd; - sp_digit tmpd[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 t[16 + 1]; + sp_digit tmp[2 * 12 * 6]; +#endif + sp_point_384* rt = NULL; #ifndef WC_NO_CACHE_RESISTANT - sp_point_384 pd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* p = NULL; +#else + sp_point_384 p[1]; #endif -#endif - sp_point_384* t; - sp_point_384* rt; -#ifndef WC_NO_CACHE_RESISTANT - sp_point_384* p; -#endif - sp_digit* tmp; +#endif /* !WC_NO_CACHE_RESISTANT */ sp_digit n; int i; - int c, y; - int err; + int c; + int y; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -#ifndef WC_NO_CACHE_RESISTANT - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 17, heap, DYNAMIC_TYPE_ECC); -#else - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + #ifndef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), + heap, DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } + #endif + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { -#ifndef WC_NO_CACHE_RESISTANT - #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - p = t + 16; - #else - p = &pd; - #endif -#endif + rt = t + 16; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; @@ -42252,7 +41813,7 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con i = 10; n = k[i+1] << 0; c = 28; - y = n >> 28; + y = (int)(n >> 28); #ifndef WC_NO_CACHE_RESISTANT if (ct) { sp_384_get_point_16_12(rt, t, y); @@ -42299,30 +41860,39 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 12 * 6); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_384) * 16); - XFREE(t, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmpd, sizeof(tmpd)); - ForceZero(td, sizeof(td)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif - sp_384_point_free_12(rt, 1, heap); + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 12 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#ifndef WC_NO_CACHE_RESISTANT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (p != NULL) + #endif + { + ForceZero(p, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* !WC_NO_CACHE_RESISTANT */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_384 { - sp_digit x[12]; - sp_digit y[12]; -} sp_table_entry_384; - #ifdef FP_ECC /* Double the Montgomery form projective point p a number of times. * @@ -42331,7 +41901,8 @@ typedef struct sp_table_entry_384 { * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*12; @@ -42412,6 +41983,36 @@ static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) sp_384_div2_12(y, y, p384_mod); } +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 12; + sp_digit* tmp = t + 4 * 12; + + sp_384_mont_inv_12(t1, a->z, tmp); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod)); +} + +#endif /* FP_ECC */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[12]; + sp_digit y[12]; +} sp_table_entry_384; + +#ifdef FP_ECC #endif /* FP_ECC */ /* Add two Montgomery form projective points. The second point has a q value of * one. @@ -42497,29 +42098,11 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, #ifdef WOLFSSL_SP_SMALL #ifdef FP_ECC -/* Convert the projective point to affine. - * Ordinates are in Montgomery form. - * - * a Point to convert. - * t Temporary data. - */ -static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 12; - sp_digit* tmp = t + 4 * 12; - - sp_384_mont_inv_12(t1, a->z, tmp); - - sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); - - sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); - XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod)); -} - /* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 96 bits between * * a The base point. * table Place to store generated point data. @@ -42529,26 +42112,30 @@ static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_12(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_12(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -42593,9 +42180,10 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a, } } - sp_384_point_free_12(s2, 0, heap); - sp_384_point_free_12(s1, 0, heap); - sp_384_point_free_12( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -42670,8 +42258,10 @@ static void sp_384_get_entry_16_12(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 4 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^96, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -42685,17 +42275,19 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 12 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -42703,27 +42295,30 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=95; j<4; j++,x+=96) { + x = 95; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 96; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -42737,8 +42332,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=94; i>=0; i--) { y = 0; - for (j=0,x=i; j<4; j++,x+=96) { + x = i; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 96; } sp_384_proj_point_dbl_12(rt, rt, t); @@ -42764,13 +42361,12 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(rt, 0, heap); return err; } @@ -42780,16 +42376,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[12]; + /* Y ordinate of point that table was generated from. */ sp_digit y[12]; + /* Precomputation table for point. */ sp_table_entry_384 table[16]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -42797,9 +42402,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -42908,6 +42519,10 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp #else #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 48 bits between * * a The base point. * table Place to store generated point data. @@ -42917,26 +42532,30 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp static int sp_384_gen_stripe_table_12(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_12(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -42981,9 +42600,10 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a, } } - sp_384_point_free_12(s2, 0, heap); - sp_384_point_free_12(s1, 0, heap); - sp_384_point_free_12( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -43058,8 +42678,10 @@ static void sp_384_get_entry_256_12(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -43073,17 +42695,19 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 12 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -43091,27 +42715,30 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 47; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 48; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -43125,8 +42752,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=46; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 48; } sp_384_proj_point_dbl_12(rt, rt, t); @@ -43152,13 +42781,12 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(rt, 0, heap); return err; } @@ -43168,16 +42796,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[12]; + /* Y ordinate of point that table was generated from. */ sp_digit y[12]; + /* Precomputation table for point. */ sp_table_entry_384 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -43185,9 +42822,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -43304,28 +42947,31 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 12, km); sp_384_point_from_ecc_point_12(point, gm); @@ -43336,17 +42982,101 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_12(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[12 + 12 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_12(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 12; + + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(point, gm); + sp_384_point_from_ecc_point_12(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_12(point, point, addP, tmp); + + if (map) { + sp_384_map_12(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 96 between points. + */ static const sp_table_entry_384 p384_table[16] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -43431,6 +43161,11 @@ static const sp_table_entry_384 p384_table[16] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^96, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -43446,6 +43181,10 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 48 between points. + */ static const sp_table_entry_384 p384_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -44730,6 +44469,11 @@ static const sp_table_entry_384 p384_table[256] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -44755,28 +44499,30 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 12, km); @@ -44786,12 +44532,90 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_12(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[12 + 12 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (12 + 12 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_12(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 12; + + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_12(point, point, addP, tmp); + + if (map) { + sp_384_map_12(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -44810,7 +44634,7 @@ static int sp_384_iszero_12(const sp_digit* a) a[8] | a[9] | a[10] | a[11]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -44869,7 +44693,8 @@ static void sp_384_add_one_12(sp_digit* a) */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -44932,41 +44757,46 @@ static int sp_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[12]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_384_point_new_12(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_12(rng, k); } if (err == MP_OKAY) { @@ -44991,15 +44821,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_12(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_12(infinity, 1, heap); -#endif - sp_384_point_free_12(point, 1, heap); return err; } @@ -45013,7 +44842,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_384_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 384 / 8 - 1; a[j] = 0; @@ -45054,33 +44886,35 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; if (*outLen < 48U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -45093,12 +44927,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(point, 0, heap); return err; } @@ -45265,83 +45099,73 @@ static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, "str r3, [%[r]]\n\t" "# A[1] * B\n\t" "ldr r8, [%[a], #4]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #4]\n\t" "# A[2] * B\n\t" "ldr r8, [%[a], #8]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #8]\n\t" "# A[3] * B\n\t" "ldr r8, [%[a], #12]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #12]\n\t" "# A[4] * B\n\t" "ldr r8, [%[a], #16]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #16]\n\t" "# A[5] * B\n\t" "ldr r8, [%[a], #20]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #20]\n\t" "# A[6] * B\n\t" "ldr r8, [%[a], #24]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #24]\n\t" "# A[7] * B\n\t" "ldr r8, [%[a], #28]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #28]\n\t" "# A[8] * B\n\t" "ldr r8, [%[a], #32]\n\t" - "mov r4, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r5, r5, r6\n\t" "adcs r3, r3, r7\n\t" - "adc r4, r4, r10\n\t" + "adc r4, r10, r10\n\t" "str r5, [%[r], #32]\n\t" "# A[9] * B\n\t" "ldr r8, [%[a], #36]\n\t" - "mov r5, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r3, r3, r6\n\t" "adcs r4, r4, r7\n\t" - "adc r5, r5, r10\n\t" + "adc r5, r10, r10\n\t" "str r3, [%[r], #36]\n\t" "# A[10] * B\n\t" "ldr r8, [%[a], #40]\n\t" - "mov r3, #0\n\t" "umull r6, r7, %[b], r8\n\t" "adds r4, r4, r6\n\t" "adcs r5, r5, r7\n\t" - "adc r3, r3, r10\n\t" + "adc r3, r10, r10\n\t" "str r4, [%[r], #40]\n\t" "# A[11] * B\n\t" "ldr r8, [%[a], #44]\n\t" @@ -45513,7 +45337,6 @@ static const uint32_t p384_order_minus_2[12] = { /* The low half of the order-2 of the P384 curve. */ static const uint32_t p384_order_low[6] = { 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U - }; #endif /* WOLFSSL_SP_SMALL */ @@ -45661,7 +45484,7 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_12(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_12(t2, t2); - if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_384_mont_mul_order_12(t2, t2, a); } } @@ -45670,12 +45493,63 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(k, k, p384_norm_order); + err = sp_384_mod_12(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(k); + + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_12(kInv, k, tmp); + sp_384_norm_12(kInv); + + /* s = r * x + e */ + sp_384_mul_12(x, x, r); + err = sp_384_mod_12(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(x); + carry = sp_384_add_12(s, e, x); + sp_384_cond_sub_12(s, s, p384_order, 0 - carry); + sp_384_norm_12(s); + c = sp_384_cmp_12(s, p384_order); + sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(s, s, kInv); + sp_384_norm_12(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -45710,8 +45584,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -45729,13 +45603,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 12, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_12(rng, ctx->k); @@ -45763,6 +45634,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_12(ctx->r, p384_order); sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_12(ctx->r); + + sp_384_from_mp(ctx->x, 12, priv); + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); ctx->state = 4; break; } @@ -45819,6 +45693,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -45851,72 +45728,55 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*12]; - sp_digit xd[2*12]; - sp_digit kd[2*12]; - sp_digit rd[2*12]; - sp_digit td[3 * 2*12]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 12]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 12; - x = d + 2 * 12; - k = d + 4 * 12; - r = d + 6 * 12; - tmp = d + 8 * 12; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 12; + k = e + 4 * 12; + r = e + 6 * 12; + tmp = e + 8 * 12; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 12, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 12, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_12(rng, k); @@ -45926,7 +45786,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -45937,38 +45797,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_12(r); - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_12(k, k, p384_norm_order); - err = sp_384_mod_12(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_12(k); - /* kInv = 1/k mod order */ - sp_384_mont_inv_order_12(kInv, k, tmp); - sp_384_norm_12(kInv); + sp_384_from_mp(x, 12, priv); + sp_384_from_bin(e, 12, hash, (int)hashLen); - /* s = r * x + e */ - sp_384_mul_12(x, x, r); - err = sp_384_mod_12(x, x, p384_order); + err = sp_384_calc_s_12(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_12(x); - carry = sp_384_add_12(s, e, x); - sp_384_cond_sub_12(s, s, p384_order, 0 - carry); - sp_384_norm_12(s); - c = sp_384_cmp_12(s, p384_order); - sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_12(s); - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_12(s, s, kInv); - sp_384_norm_12(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_12(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -45982,20 +45823,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 12); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_12(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -46331,6 +46176,100 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ + + sp_384_proj_point_add_12(p1, p1, p2, tmp); + if (sp_384_iszero_12(p1->z)) { + if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { + sp_384_proj_point_dbl_12(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_12(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_384_mul_12(s, s, p384_norm_order); + } + err = sp_384_mod_12(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_384_mont_inv_order_12(s, s, tmp); + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + +#else + { + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_12(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -46349,8 +46288,7 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -46369,8 +46307,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -46385,7 +46324,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); sp_384_from_mp(ctx->s, 12, sm); sp_384_from_mp(ctx->p2.x, 12, pX); sp_384_from_mp(ctx->p2.y, 12, pY); @@ -46443,57 +46382,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_12(ctx->p1.z)) { - if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<12; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -46501,22 +46416,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_12(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -46524,134 +46440,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*12]; - sp_digit u2d[2*12]; - sp_digit sd[2*12]; - sp_digit tmpd[2*12 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 12]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_12(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 12; - u2 = d + 2 * 12; - s = d + 4 * 12; - tmp = d + 6 * 12; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 12; + s = u1 + 4 * 12; + tmp = u1 + 6 * 12; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 12, hash, (int)hashLen); - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); sp_384_from_mp(s, 12, sm); sp_384_from_mp(p2->x, 12, pX); sp_384_from_mp(p2->y, 12, pY); sp_384_from_mp(p2->z, 12, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_12(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_384_mul_12(s, s, p384_norm_order); - } - err = sp_384_mod_12(s, s, p384_order); + err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_12(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_384_mont_inv_order_12(s, s, tmp); - sp_384_mont_mul_order_12(u1, u1, s); - sp_384_mont_mul_order_12(u2, u2, s); - } - -#else - { - sp_384_mont_mul_order_12(u1, u1, s); - sp_384_mont_mul_order_12(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_384_proj_point_add_12(p1, p1, p2, tmp); - if (sp_384_iszero_12(p1->z)) { - if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { - sp_384_proj_point_dbl_12(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - p1->x[8] = 0; - p1->x[9] = 0; - p1->x[10] = 0; - p1->x[11] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); } @@ -46662,7 +46507,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); carry = sp_384_add_12(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -46670,26 +46515,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_12(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_12(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p1, 0, heap); - sp_384_point_free_12(p2, 0, heap); return err; } @@ -46703,34 +46548,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_12(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*12]; - sp_digit t2d[2*12]; + sp_digit t1[12 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 12; - t2 = d + 2 * 12; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 12; sp_384_sqr_12(t1, point->y); (void)sp_384_mod_12(t1, t1, p384_mod); @@ -46750,10 +46587,9 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -46766,16 +46602,23 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_12(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 12, pX); sp_384_from_mp(pub->y, 12, pY); @@ -46784,7 +46627,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_12(pub, NULL); } - sp_384_point_free_12(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -46800,47 +46646,48 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[12]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; - sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_384_point_new_12(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_384* pub = NULL; +#else + sp_digit priv[12]; + sp_point_384 pub[2]; #endif + sp_point_384* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 12, pX); sp_384_from_mp(pub->y, 12, pY); sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); @@ -46854,12 +46701,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_12(pub->x, p384_mod) >= 0 || - sp_384_cmp_12(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_12(pub->x, p384_mod) >= 0) || + (sp_384_cmp_12(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -46871,12 +46717,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_12(p->x) == 0) || - (sp_384_iszero_12(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) || + (sp_384_iszero_12(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -46884,22 +46728,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_12(p->x, pub->x) != 0 || - sp_384_cmp_12(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_12(p->x, pub->x) != 0) || + (sp_384_cmp_12(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(pub, 0, heap); return err; } @@ -46923,33 +46765,35 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; - err = sp_384_point_new_12(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 12, pX); sp_384_from_mp(p->y, 12, pY); sp_384_from_mp(p->z, 12, pZ); @@ -46970,13 +46814,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(q, 0, NULL); - sp_384_point_free_12(p, 0, NULL); return err; } @@ -46995,25 +46838,28 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_12(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -47034,12 +46880,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, NULL); return err; } @@ -47054,32 +46900,36 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_12(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 12, pX); sp_384_from_mp(p->y, 12, pY); sp_384_from_mp(p->z, 12, pZ); - sp_384_map_12(p, p, tmp); + sp_384_map_12(p, p, tmp); } if (err == MP_OKAY) { @@ -47092,12 +46942,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, NULL); return err; } @@ -47110,43 +46960,28 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_12(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 12]; - sp_digit t2d[2 * 12]; - sp_digit t3d[2 * 12]; - sp_digit t4d[2 * 12]; - sp_digit t5d[2 * 12]; + sp_digit t1[5 * 2 * 12]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 12; - t2 = d + 2 * 12; - t3 = d + 4 * 12; - t4 = d + 6 * 12; - t5 = d + 8 * 12; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 12; + t3 = t1 + 4 * 12; + t4 = t1 + 6 * 12; + t5 = t1 + 8 * 12; { /* t2 = y ^ 0x2 */ @@ -47206,10 +47041,9 @@ static int sp_384_mont_sqrt_12(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -47225,31 +47059,22 @@ static int sp_384_mont_sqrt_12(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 12]; - sp_digit yd[2 * 12]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 12]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 12; - y = d + 2 * 12; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 12; sp_384_from_mp(x, 12, xm); err = sp_384_mod_mul_norm_12(x, x, p384_mod); @@ -47282,16 +47107,15910 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 32]; + /* Y ordinate of point. */ + sp_digit y[2 * 32]; + /* Z ordinate of point. */ + sp_digit z[2 * 32]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r11, [%[a], #0]\n\t" + "ldr r12, [%[b], #0]\n\t" + "umull r3, r4, r11, r12\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r11, [%[a], #4]\n\t" + "ldr r12, [%[b], #4]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r11, [%[a], #8]\n\t" + "ldr r12, [%[b], #8]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r11, [%[a], #12]\n\t" + "ldr r12, [%[b], #12]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[8] * B[0]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r11, [%[a], #16]\n\t" + "ldr r12, [%[b], #16]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[0] * B[8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #32]\n\t" + "# A[0] * B[9]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[1]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[0]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #36]\n\t" + "# A[10] * B[0]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[9] * B[1]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[2]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r11, [%[a], #20]\n\t" + "ldr r12, [%[b], #20]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[8]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[1] * B[9]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[0] * B[10]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #40]\n\t" + "# A[0] * B[11]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[10]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[9]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[3]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[2]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[1]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[0]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #44]\n\t" + "# A[12] * B[0]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[11] * B[1]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[2]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[3]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[4]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r11, [%[a], #24]\n\t" + "ldr r12, [%[b], #24]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[9]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[10]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[1] * B[11]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[0] * B[12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #48]\n\t" + "# A[0] * B[13]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[11]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[10]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[9]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[7]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[5]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[4]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[3]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[2]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[1]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[0]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #52]\n\t" + "# A[14] * B[0]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[13] * B[1]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[2]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[3]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[4]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[5]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[6]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[7]\n\t" + "ldr r11, [%[a], #28]\n\t" + "ldr r12, [%[b], #28]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[9]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[10]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[11]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[1] * B[13]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[0] * B[14]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #56]\n\t" + "# A[0] * B[15]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[14]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[13]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[12]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[11]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[10]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[9]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[7]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[6]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[5]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[4]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[3]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[2]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[1]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[0]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #60]\n\t" + "# A[15] * B[1]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[14] * B[2]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[3]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[4]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[5]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[6]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[7]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[8]\n\t" + "ldr r11, [%[a], #32]\n\t" + "ldr r12, [%[b], #32]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[9]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[10]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[11]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[12]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[13]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[14]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[1] * B[15]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[2] * B[15]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[3] * B[14]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[13]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[12]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[11]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[10]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[9]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[8]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[7]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[6]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[5]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[4]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[3]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[2]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[15] * B[3]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[14] * B[4]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[5]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[6]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[7]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[8]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[9]\n\t" + "ldr r11, [%[a], #36]\n\t" + "ldr r12, [%[b], #36]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[10]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[11]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[12]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[13]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[14]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[15]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[4] * B[15]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[5] * B[14]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[13]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[12]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[11]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[10]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[9]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[8]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[7]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[6]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[5]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[4]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[15] * B[5]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[14] * B[6]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[7]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[8]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[9]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[10]\n\t" + "ldr r11, [%[a], #40]\n\t" + "ldr r12, [%[b], #40]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[11]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[12]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[13]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[14]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[15]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[6] * B[15]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[7] * B[14]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[13]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[12]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[11]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[10]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[9]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[8]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[7]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[6]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[15] * B[7]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[14] * B[8]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[9]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[10]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[11]\n\t" + "ldr r11, [%[a], #44]\n\t" + "ldr r12, [%[b], #44]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[12]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[13]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[14]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[15]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[8] * B[15]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[9] * B[14]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[13]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[12]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[11]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[10]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[9]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[8]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[15] * B[9]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[14] * B[10]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[11]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[12]\n\t" + "ldr r11, [%[a], #48]\n\t" + "ldr r12, [%[b], #48]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[13]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[14]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[15]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[10] * B[15]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[11] * B[14]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[13]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[12]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[11]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[10]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[15] * B[11]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[14] * B[12]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[13]\n\t" + "ldr r11, [%[a], #52]\n\t" + "ldr r12, [%[b], #52]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[14]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[15]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[12] * B[15]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[13] * B[14]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[13]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[12]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[15] * B[13]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[14] * B[14]\n\t" + "ldr r11, [%[a], #56]\n\t" + "ldr r12, [%[b], #56]\n\t" + "umull r6, r7, r11, r12\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[15]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[14] * B[15]\n\t" + "umull r6, r7, r11, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[15] * B[14]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r6, r7, r8, r12\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[15] * B[15]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r3, [%[r], #120]\n\t" + "str r4, [%[r], #124]\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "ldm sp!, {r3, r4, r5, r6}\n\t" + "stm %[r]!, {r3, r4, r5, r6}\n\t" + "sub %[r], %[r], #64\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r12, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[0] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #32]\n\t" + "# A[0] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #36]\n\t" + "# A[0] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #40]\n\t" + "# A[0] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #44]\n\t" + "# A[0] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #48]\n\t" + "# A[0] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #52]\n\t" + "# A[0] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #56]\n\t" + "# A[0] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[2] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #60]\n\t" + "# A[1] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[3] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #64]\n\t" + "# A[2] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[4] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #68]\n\t" + "# A[3] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[4] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[5] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[9] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #72]\n\t" + "# A[4] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[5] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[6] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[9] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #76]\n\t" + "# A[5] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[6] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[7] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[9] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[10] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #80]\n\t" + "# A[6] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[7] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[8] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[9] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[10] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #84]\n\t" + "# A[7] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[8] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[9] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[10] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[11] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #88]\n\t" + "# A[8] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[9] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[10] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[11] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #92]\n\t" + "# A[9] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[10] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[11] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[12] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #96]\n\t" + "# A[10] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[11] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "# A[12] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r12\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #100]\n\t" + "# A[11] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[12] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "# A[13] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [%[r], #104]\n\t" + "# A[12] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r12, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "# A[13] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r12\n\t" + "str r2, [%[r], #108]\n\t" + "# A[13] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r12, r12\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "# A[14] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r12\n\t" + "str r3, [%[r], #112]\n\t" + "# A[14] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r12, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r12\n\t" + "str r4, [%[r], #116]\n\t" + "# A[15] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adc r3, r3, r9\n\t" + "str r2, [%[r], #120]\n\t" + "str r3, [%[r], #124]\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "ldm sp!, {r2, r3, r4, r8}\n\t" + "stm %[r]!, {r2, r3, r4, r8}\n\t" + "sub %[r], %[r], #64\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r12" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u; + sp_digit ca; + sp_digit cb; + + ca = sp_1024_add_16(a1, a, &a[16]); + cb = sp_1024_add_16(b1, b, &b[16]); + u = ca & cb; + sp_1024_mul_16(z1, a1, b1); + sp_1024_mul_16(z2, &a[16], &b[16]); + sp_1024_mul_16(z0, a, b); + sp_1024_mask_16(r + 32, a1, 0 - cb); + sp_1024_mask_16(b1, b1, 0 - ca); + u += sp_1024_add_16(r + 32, r + 32, b1); + u += sp_1024_sub_in_place_32(z1, z2); + u += sp_1024_sub_in_place_32(z1, z0); + u += sp_1024_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + (void)sp_1024_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_1024_add_16(a1, a, &a[16]); + sp_1024_sqr_16(z1, a1); + sp_1024_sqr_16(z2, &a[16]); + sp_1024_sqr_16(z0, a); + sp_1024_mask_16(r + 32, a1, 0 - u); + u += sp_1024_add_16(r + 32, r + 32, r + 32); + u += sp_1024_sub_in_place_32(z1, z2); + u += sp_1024_sub_in_place_32(z1, z0); + u += sp_1024_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + (void)sp_1024_add_32(r + 32, r + 32, z2); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #124\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #128\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #248\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #124\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #128\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #248\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* !WOLFSSL_SP_SMALL */ +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[32] = { + 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823, + 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8, + 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4, + 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27, + 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198, + 0x0a563fda,0x997abb1f +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[32] = { + 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc, + 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57, + 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b, + 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8, + 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67, + 0xf5a9c025,0x668544e0 +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x7c8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[32] = { + 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08, + 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a, + 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd, + 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9, + 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466, + 0xc2958ff6,0x265eaec7 +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5, + 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339, + 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7, + 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0, + 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005, + 0x332c29ad,0x53fc09ee, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a, + 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80, + 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c, + 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4, + 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053, + 0x3f6009f1,0x0a824906, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #128\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #128\n\t" + "blt 1b\n\t" + "str r3, [%[r], #128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #124]\n\t" + "str r5, [%[r], #128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int32_t sp_1024_cmp_32(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #124\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + sp_digit hi = t1[32 + i] - (t1[32 + i] == div); + r1 = div_1024_word_32(hi, t1[32 + i - 1], div); + + sp_1024_mul_d_32(t2, d, r1); + t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_1024_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2); + sp_1024_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_1024_cmp_32(t1, d) >= 0; + sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_1024_div_32(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + sp_1024_mul_32(r, a, p1024_norm_mod); + return sp_1024_mod_32(r, r, m); +} + + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_32(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 32, pm->x); + sp_1024_from_mp(p->y, 32, pm->y); + sp_1024_from_mp(p->z, 32, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldr r11, [%[m], #0]\n\t" + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r11\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "ldr r9, [%[a], #128]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #128]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #128\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + "ldr r6, [%[m], #124]\n\t" + "subs r9, r6, r9\n\t" + "neg %[ca], %[ca]\n\t" + "sbc r9, r9, r9\n\t" + "orr %[ca], %[ca], r9\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12", "r11" + ); + + sp_1024_cond_sub_32(a - 32, a, m, ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_32(r, a, b); + sp_1024_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_32(r, a); + sp_1024_mont_reduce_32(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 32]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 32); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_1024_norm_32(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + int32_t n; + + sp_1024_mont_inv_32(t1, p->z, t + 2*32); + + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 32, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_32(r->x, p1024_mod); + sp_1024_cond_sub_32(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 32, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_32(r->y, p1024_mod); + sp_1024_cond_sub_32(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldr r14, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r14, r14, r7\n\t" + "neg r12, r12\n\t" + "sbc r14, r14, r14\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r14\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldr r4, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r4, r4, r14\n\t" + "neg r12, r12\n\t" + "sbc r4, r4, r4\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r4\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldr r4, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r4, r4, r14\n\t" + "neg r12, r12\n\t" + "sbc r4, r4, r4\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r4\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + "sub %[m], %[m], #128\n\t" + "sub %[a], %[a], #128\n\t" + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adds r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldr r7, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r7, r7, r14\n\t" + "neg r12, r12\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r7\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "subs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbc r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sbc r12, r12, r12\n\t" + "sub %[r], %[r], #128\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #128\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adds r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "adc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +static void sp_1024_rshift1_32(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r2, [%[a]]\n\t" + "ldr r3, [%[a], #4]\n\t" + "lsr r2, r2, #1\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r2, [%[r], #0]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r3, [%[r], #4]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r4, [%[r], #8]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r2, [%[r], #12]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r3, [%[r], #16]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r4, [%[r], #20]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r2, [%[r], #24]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r3, [%[r], #28]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r4, [%[r], #32]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r2, [%[r], #36]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r3, [%[r], #40]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r4, [%[r], #44]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r2, [%[r], #48]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r3, [%[r], #52]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #64]\n\t" + "str r4, [%[r], #56]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #68]\n\t" + "str r2, [%[r], #60]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #72]\n\t" + "str r3, [%[r], #64]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #76]\n\t" + "str r4, [%[r], #68]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #80]\n\t" + "str r2, [%[r], #72]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #84]\n\t" + "str r3, [%[r], #76]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #88]\n\t" + "str r4, [%[r], #80]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #92]\n\t" + "str r2, [%[r], #84]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #96]\n\t" + "str r3, [%[r], #88]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #100]\n\t" + "str r4, [%[r], #92]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #104]\n\t" + "str r2, [%[r], #96]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #108]\n\t" + "str r3, [%[r], #100]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #112]\n\t" + "str r4, [%[r], #104]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #116]\n\t" + "str r2, [%[r], #108]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #120]\n\t" + "str r3, [%[r], #112]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #124]\n\t" + "str r4, [%[r], #116]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "str r2, [%[r], #120]\n\t" + "str r3, [%[r], #124]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_1024_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1)); + sp_1024_rshift1_32(r, r); + r[31] |= o << 31; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_32_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_32_ctx; + +static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*32; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_32(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_32(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_32(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_32(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_32(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_32(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_32(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_32(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_32(y, y, t2, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "rsbs %[c], %[c], #0\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "sbc %[c], r4, r4\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r7, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "ldr r10, [%[b], #44]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r7, [%[b], #48]\n\t" + "ldr r8, [%[b], #52]\n\t" + "ldr r9, [%[b], #56]\n\t" + "ldr r10, [%[b], #60]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #48]\n\t" + "str r4, [%[r], #52]\n\t" + "str r5, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r7, [%[b], #64]\n\t" + "ldr r8, [%[b], #68]\n\t" + "ldr r9, [%[b], #72]\n\t" + "ldr r10, [%[b], #76]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #64]\n\t" + "str r4, [%[r], #68]\n\t" + "str r5, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r7, [%[b], #80]\n\t" + "ldr r8, [%[b], #84]\n\t" + "ldr r9, [%[b], #88]\n\t" + "ldr r10, [%[b], #92]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #80]\n\t" + "str r4, [%[r], #84]\n\t" + "str r5, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r7, [%[b], #96]\n\t" + "ldr r8, [%[b], #100]\n\t" + "ldr r9, [%[b], #104]\n\t" + "ldr r10, [%[b], #108]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #96]\n\t" + "str r4, [%[r], #100]\n\t" + "str r5, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r7, [%[b], #112]\n\t" + "ldr r8, [%[b], #116]\n\t" + "ldr r9, [%[b], #120]\n\t" + "ldr r10, [%[b], #124]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #112]\n\t" + "str r4, [%[r], #116]\n\t" + "str r5, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) | + (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) | + (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) | + (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) | + (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_32_ctx { + int state; + sp_1024_proj_point_dbl_32_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_32_ctx; + +static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*32; + ctx->t3 = t + 4*32; + ctx->t4 = t + 6*32; + ctx->t5 = t + 8*32; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_32(ctx->t1, p1024_mod, q->y); + sp_1024_norm_32(ctx->t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_32_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_32(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_32(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_32(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_32(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_32(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_32(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* t3 = t + 4*32; + sp_digit* t4 = t + 6*32; + sp_digit* t5 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_32(t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_32(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_32(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_32(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_32(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(x, x, t5, p1024_mod); + sp_1024_mont_dbl_32(t1, y, p1024_mod); + sp_1024_mont_sub_32(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_32(y, y, x, p1024_mod); + sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(y, y, t5, p1024_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 1024 doubles. + * 268 adds. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[16 + 1]; + sp_digit tmp[2 * 32 * 5]; +#endif + sp_point_1024* rt = NULL; + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 16; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod); + (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod); + (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod); + t[1].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 30; + n = k[i+1] << 0; + c = 28; + y = (int)(n >> 28); + XMEMCPY(rt, &t[y], sizeof(sp_point_1024)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_add_32(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_1024_map_32(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 32 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*32; + sp_digit* b = t + 4*32; + sp_digit* t1 = t + 6*32; + sp_digit* t2 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_32(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_32(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(t2, b, p1024_mod); + sp_1024_mont_sub_32(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_32(y, b, x, p1024_mod); + sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(y, y, p1024_mod); + sp_1024_mont_sub_32(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_32(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(t2, b, p1024_mod); + sp_1024_mont_sub_32(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_32(y, b, x, p1024_mod); + sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(y, y, p1024_mod); + sp_1024_mont_sub_32(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_32(y, y, p1024_mod); +} + +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* tmp = t + 4 * 32; + + sp_1024_mont_inv_32(t1, a->z, tmp); + + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[32]; + sp_digit y[32]; +} sp_table_entry_1024; + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* t3 = t + 4*32; + sp_digit* t4 = t + 6*32; + sp_digit* t5 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_32(t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_32(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_32(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_32(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_32(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_32(t1, t3, p1024_mod); + sp_1024_mont_sub_32(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_32(t3, t3, x, p1024_mod); + sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(y, t3, t5, p1024_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 256 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_32(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_32(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<4; i++) { + sp_1024_proj_point_dbl_n_32(t, 256, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^256, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 32 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 255; + for (j=0; j<4; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 256; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=254; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<4; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 256; + } + + sp_1024_proj_point_dbl_32(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_32(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_32(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[32]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[32]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[16]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 32 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#else +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_32(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_32(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_32(t, 128, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 32 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_32(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_32(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_32(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[32]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[32]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 32 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(point, gm); + + err = sp_1024_ecc_mulmod_32(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 256 between points. + */ +static const sp_table_entry_1024 p1024_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0, + 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995, + 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867, + 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173, + 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc, + 0x1c49f80b,0x8dfff96a }, + { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88, + 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16, + 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e, + 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf, + 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329, + 0xde3c01f3,0x2aa1207b } }, + /* 2 */ + { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f, + 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab, + 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa, + 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9, + 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec, + 0xdf9398a4,0x40247985 }, + { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb, + 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861, + 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36, + 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd, + 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb, + 0xc8b79d80,0x1a6fd1e6 } }, + /* 3 */ + { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452, + 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e, + 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d, + 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37, + 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4, + 0x15614750,0x29b7d4dc }, + { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54, + 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7, + 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a, + 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903, + 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310, + 0x5382497e,0x5d092802 } }, + /* 4 */ + { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6, + 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd, + 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd, + 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521, + 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494, + 0x0f1fa7d7,0x2ab3bd47 }, + { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135, + 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2, + 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f, + 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c, + 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1, + 0x4c27d229,0x93a4b416 } }, + /* 5 */ + { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1, + 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519, + 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e, + 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30, + 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6, + 0x32ee7763,0x342ce0d7 }, + { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a, + 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858, + 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66, + 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433, + 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb, + 0xe156fd20,0x455f4af3 } }, + /* 6 */ + { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9, + 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee, + 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d, + 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8, + 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead, + 0x5c37c334,0x65713c29 }, + { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6, + 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424, + 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862, + 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1, + 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5, + 0x3bae3c38,0x6b0e996c } }, + /* 7 */ + { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269, + 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7, + 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da, + 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e, + 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342, + 0x678223f8,0x4022a205 }, + { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d, + 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6, + 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd, + 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21, + 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11, + 0x24a6a956,0x312179cb } }, + /* 8 */ + { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41, + 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7, + 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b, + 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5, + 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1, + 0x04ecf056,0x325d2796 }, + { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1, + 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153, + 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c, + 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9, + 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e, + 0xe32a79d3,0x19d48546 } }, + /* 9 */ + { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0, + 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea, + 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df, + 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634, + 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d, + 0xb4e453b0,0x1b3ace6c }, + { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35, + 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630, + 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824, + 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387, + 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64, + 0x192f0a14,0x538ec33e } }, + /* 10 */ + { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8, + 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699, + 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984, + 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32, + 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076, + 0xb6f8aa25,0x13cbee76 }, + { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23, + 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492, + 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e, + 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50, + 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c, + 0xe02e8967,0x4e0a1ada } }, + /* 11 */ + { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67, + 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198, + 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7, + 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d, + 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6, + 0x9f99c999,0x733e30d9 }, + { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7, + 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a, + 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a, + 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0, + 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492, + 0xb79a5c0c,0x56facb39 } }, + /* 12 */ + { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6, + 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c, + 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e, + 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb, + 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52, + 0xf18c2b91,0x57ea2b4b }, + { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a, + 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee, + 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069, + 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b, + 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927, + 0xea7935c9,0x60480b46 } }, + /* 13 */ + { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7, + 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117, + 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5, + 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0, + 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb, + 0x9a8f88cc,0x0774a0d3 }, + { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f, + 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61, + 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91, + 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df, + 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303, + 0x2432014b,0x08151954 } }, + /* 14 */ + { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28, + 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20, + 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1, + 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55, + 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7, + 0xf0860497,0x1fe09f94 }, + { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c, + 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a, + 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994, + 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa, + 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c, + 0xdb62526a,0x4de95786 } }, + /* 15 */ + { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96, + 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5, + 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5, + 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc, + 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e, + 0xe636980c,0x1c94418b }, + { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a, + 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4, + 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98, + 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474, + 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422, + 0xb55235ba,0x611bfbb2 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^256, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0, + 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995, + 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867, + 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173, + 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc, + 0x1c49f80b,0x8dfff96a }, + { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88, + 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16, + 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e, + 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf, + 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329, + 0xde3c01f3,0x2aa1207b } }, + /* 2 */ + { { 0x01900955,0xa95b6dae,0xceb4656d,0xa5dc9cc1,0xe72fe95b,0x50c78907, + 0xa040c334,0xa1ae5447,0x7952ea6e,0x91191370,0x6d097305,0x54ff7343, + 0xbda4d10f,0xa4db0074,0x91644070,0xfd5306f1,0x8b24522c,0x14b9fe73, + 0x7849f762,0x1468dad6,0xb0dcd2e4,0x87b29a18,0x5e1ad492,0xadd7f1a1, + 0xdbba2a1a,0x9ac63a81,0x81223379,0x01379c5b,0xb0e53bc8,0xf402b2f0, + 0x0bf13b61,0x8c3eb27f }, + { 0xe513696f,0x9a4ad3e1,0x18c81ffa,0x0350ba5c,0x3c033d13,0x1e2fc136, + 0x17a531bc,0x53da6e71,0x1aed610d,0x42ec6490,0xe99ff567,0xd33e8df7, + 0x3deed12a,0xe4aad73e,0x180f4deb,0xd983b465,0x502f30b4,0x99365269, + 0xa8918d7f,0x7e2799ab,0x700fc79a,0x0ffe84b6,0x40bfd8c2,0x7b4400d6, + 0x5d2641bd,0xc3a21d21,0xc32621cb,0x79839442,0xb1401e83,0xace6500b, + 0x251c4310,0x7bf4163e } }, + /* 3 */ + { { 0xe3fd589e,0x1c174f88,0xdf974a03,0xdb501790,0x3e70549f,0xd09623e3, + 0x15924f34,0x8d091eff,0xf9b65ac5,0xeef79cad,0x3f69c2cf,0xd2cc4262, + 0x52cd82bc,0x817d9032,0xa5f1dddd,0xacf4f4d9,0x5011b6bd,0xd0612635, + 0x2ed140c9,0x9f74490d,0x4db686d2,0x64092e8c,0x776b0fcc,0x225eef16, + 0xdf16aeb6,0x0e8c01e9,0x84bbd82a,0x62836741,0x8956e337,0x757574e2, + 0x705a7f07,0x9871edc6 }, + { 0x776535f7,0xbd0b76d5,0x2635b3b8,0x5214d602,0x9d216f64,0xc0c25ad9, + 0x5515bf75,0xfd4df3a7,0x5e9f1675,0x24a625bc,0x406873e7,0x3c35efb7, + 0xbb2e5c4a,0xef5c9a33,0x806b198a,0xa971b35e,0xa3c690ed,0x9f5c0ca5, + 0x8e1e2341,0xa8d5dd89,0x955ad9e4,0x4cecbcce,0x248d3416,0x2ecf4407, + 0x45c0af6e,0x1abb3811,0x1c780fff,0x3f4bee82,0xc272ed57,0xd14df768, + 0x371637ad,0x397ed10a } }, + /* 4 */ + { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f, + 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab, + 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa, + 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9, + 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec, + 0xdf9398a4,0x40247985 }, + { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb, + 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861, + 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36, + 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd, + 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb, + 0xc8b79d80,0x1a6fd1e6 } }, + /* 5 */ + { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452, + 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e, + 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d, + 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37, + 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4, + 0x15614750,0x29b7d4dc }, + { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54, + 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7, + 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a, + 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903, + 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310, + 0x5382497e,0x5d092802 } }, + /* 6 */ + { { 0xff2f780d,0x583a2b7e,0xd7d76b1d,0x34d26820,0x86f74aec,0xe3c32847, + 0x10823feb,0x0fd42212,0xfb5e7bf4,0x227e417e,0xa568f8cd,0x510d49b6, + 0x1781bbec,0x53bce7d6,0x2f3718b7,0x9cfe3f22,0xd9de6c1f,0x7f44e89f, + 0x3fac9b55,0xf1cc553f,0xe6f300bc,0x9d2d0846,0x9f0ae6b1,0x976c82a2, + 0x24b8bbe0,0xe63dbf5e,0x973a5aa7,0x4cac7f45,0x84dd33c7,0xc6eb6237, + 0x142fee5d,0x0a26e434 }, + { 0xacaa9a08,0x8081339f,0x5246ece1,0x40f31105,0x61393747,0x892c8170, + 0x242f02e1,0x8d8d4103,0x3b5de98a,0x482bfd20,0x5abbe952,0x89ef946b, + 0x37698249,0xb8d218b9,0x66617c7a,0xd5268e89,0x8b7d2b91,0x962e7551, + 0xfe8d67c3,0x2c5c7973,0x2b017c51,0x42e3150a,0xc1a29469,0x6f4e5ebc, + 0x531c7083,0xa39910ce,0xb77b9e50,0xaf4f6eb4,0xda120ad0,0x68cbb175, + 0xb92636ec,0x19497c61 } }, + /* 7 */ + { { 0x417659a8,0x6920b0c6,0x92cb28ff,0xc77ab9c7,0xb687797f,0x55b67180, + 0xe7759363,0x4caf58c1,0x5561b186,0x5155bdb6,0x780f4946,0x2e64e355, + 0x229a8b20,0xeb0ac9b7,0x2571bd60,0x88594d78,0xe3fa78f9,0x5dcc0939, + 0x2ac2d379,0x7b8b4830,0xb90f1444,0x505fbf60,0x3ce4b3c1,0xac610e81, + 0xd59b5c18,0x39a4f27a,0x7cea0222,0x5fa33973,0x8dff1c7b,0xe578730b, + 0x517bf7a6,0x96b91b8b }, + { 0x9aac087c,0xc1a991f4,0x6cfdb28d,0xce62f74e,0x5f7600d6,0x08d6ff9a, + 0xf917f9c9,0xd781cd04,0x3de52dbf,0x7796f5f6,0x2ed72180,0xe7db64e0, + 0x6fa4137d,0x0f0876f6,0x3ca1f716,0x3271ee64,0x7c4ab8a3,0xcb9b2058, + 0x39481047,0xcba17107,0x598c5c37,0xdf9a190d,0x6f20e125,0x0cb6e72a, + 0xf4f2902d,0xa3142204,0x7ce2dcfb,0x42d28cb9,0xa3d3c351,0xdf261b8a, + 0xcffc249d,0x73f3d315 } }, + /* 8 */ + { { 0xe6fd3673,0x5d86855b,0x9d214b7b,0x309b70af,0xdcc46cd3,0x8d332f90, + 0x595510de,0xe553c015,0x38c1251c,0x5746a096,0x85cc1bc9,0xcd7cea5b, + 0x002eba8f,0x4ffa1468,0x22fcd77c,0x10a3cb70,0xc4ea05e3,0xb6999dfb, + 0x4efa756e,0x3375a0d0,0xdced5fd8,0x4d90279e,0x251fd56e,0x48192403, + 0x82a4c5f1,0xe87633a4,0x1b34105b,0x3170d130,0x7247e578,0x93998b0f, + 0x436ba1fa,0x88934f64 }, + { 0x4713eabc,0xf09f43b0,0xaccdc517,0x4ca7dd91,0xef13ca7c,0x27daa63b, + 0x2588184b,0x8b2e5a7a,0xd95dc269,0x0a8cb612,0xe1f2f14c,0x346975a2, + 0xe172935c,0x1f29b8ed,0xd40bc1e3,0xc3cbfd6e,0x132623da,0xd3f46b3f, + 0xfb0b7681,0xc115be6d,0x56da4344,0x5e31c345,0xa8e43d98,0xa7c63f18, + 0x4bddb4ea,0x55cb2083,0x4a54f58c,0xb16a0c38,0x46fd69d9,0x74eacca2, + 0x153548e1,0x0d1898bb } }, + /* 9 */ + { { 0xe35ef043,0x4ea73461,0x3496b564,0x107b67d9,0xd0f83a3c,0xd62c173b, + 0x51d29c35,0xfad4b038,0x71b1c1a4,0x3f42882a,0x54b43b9e,0x5d2bcf66, + 0x2abdf543,0xc77b15aa,0xdabe3dc1,0x5cb38a80,0xa481673b,0x15fda0ae, + 0xe7b90ebe,0x86996b4d,0x2bc8f3d8,0x84f87e25,0x37c4e424,0xaded03d6, + 0xd7a7afd8,0xe5ede666,0xa1ccb93a,0x80dd95a2,0x46fba391,0xa55cfd25, + 0x46f82e60,0x2bdab1dc }, + { 0xfa6fed61,0x7a4de22b,0xcc8dd94e,0xca458aa5,0x071222f5,0x3e372df1, + 0xe5aff377,0x06a4b44f,0x4a738e6d,0xbc2d0ba7,0x5f31f136,0x1a470e1d, + 0xe102a911,0x77ff933a,0x310c7885,0x8b380a50,0x783fc5ac,0x9f3c0228, + 0x44725d06,0xec668925,0x5ac84221,0x878f0e16,0xcfda6e8a,0x9a3af1af, + 0x78cd2aba,0x0183ed37,0x826d0eae,0x32cdbd60,0xcbee6415,0xb3234661, + 0xb9c10120,0x353eb892 } }, + /* 10 */ + { { 0x10b5521e,0xc8fdcad6,0x52e702f0,0x1a11b440,0x8ffda49c,0x6302680d, + 0xcbf36bad,0xcdb9654a,0x4c10a2d7,0x7b58ce11,0xe630e7e0,0x1e5d1f7d, + 0x6760a813,0x8cbe3d7d,0x6480d77f,0xeb35866b,0x7f036219,0x58728cf3, + 0x42a8a757,0xdd5865ed,0x906a2870,0x283f1f1d,0xa51f906b,0x79e23fa4, + 0x543b20a8,0xf2ac6e83,0xb81e7754,0x4f0b6379,0x840016ee,0x57fbc0d4, + 0xe621b67d,0x8da20771 }, + { 0xecce65ec,0x3c855004,0xb748185e,0x76d10d1f,0x78797ad2,0x64be7bca, + 0x77e54aad,0x43444db0,0xbe0df0ff,0x17b6b0c9,0x055086a4,0x8fc4256c, + 0xfd74d5a3,0xf952c43b,0x01c4edb8,0x501e005a,0x4a57e328,0xd5172dfc, + 0x535d6ee3,0xdb40ce4e,0x0c650918,0xbaef1e5c,0x857561fc,0xe85145e7, + 0x34a224c6,0xe468536a,0x0ec0e0a2,0x69a8e227,0x242b03fc,0xb3f52247, + 0xc3bebd5f,0x862f55e2 } }, + /* 11 */ + { { 0x226049fe,0x2d6a390f,0xdcbbc9fb,0xcc92a578,0x97634fb7,0xa52feca4, + 0x3dea5893,0x2b340cb6,0x2a49e916,0xa39f338a,0x949e41f3,0x26b2df3d, + 0x065a7e40,0xc71c7cdb,0x468281a2,0x4a9b84a0,0x731eeeca,0x63eeb503, + 0x76cbb725,0xe6d09134,0xb94a678c,0x0cf979a9,0x808fd9f1,0xb44d8c3b, + 0xe0afc5b9,0xe60da613,0x3ea5be69,0x52dce7de,0xdc1ee74f,0x3a5d6864, + 0x3bc80790,0x71ab2891 }, + { 0x3b5b60ad,0xcf618fc4,0x4a0c3184,0x0afb5e30,0xbc403302,0xd22381cc, + 0xdb1c0c66,0x33cf8953,0xa6112a8d,0x9c994e4d,0xd1967a86,0xd7aae2c3, + 0x5b7acd29,0xc28d5493,0x6c9a57fb,0x8075bd13,0x9c8427f9,0xc9c0373e, + 0x193225f5,0x2cbca18d,0x442c018c,0x73777d13,0xfbb3a727,0xebe5ed47, + 0x1962dc18,0x70437d49,0x2dc08806,0xf39c1e09,0x15fff35c,0x03e9c6f7, + 0x5e360a65,0x8d087bb6 } }, + /* 12 */ + { { 0x3fdc1844,0xbe212302,0x105eac56,0x6eca27ef,0xf168a348,0x2183a606, + 0xe1d7a4cb,0x295f807d,0x7ef5d43e,0x7246a632,0xc77025c7,0xae143205, + 0xf3484e3e,0x4bdfc7ca,0xdf52c075,0xec939895,0xd7a9cac0,0x82e655f6, + 0x8baeddb0,0x985dfe20,0x527de731,0x79c817e4,0x313de1ea,0x30ce0fbc, + 0xcc4f6cbb,0x9df95b89,0xf5bb20cd,0xf2aedf1e,0x1a8cfb01,0xfc1e0a89, + 0x63edb7ec,0x225ed34a }, + { 0xbabb1a85,0x3e13154d,0x1e6a565a,0xd3d8dae7,0xab4b100f,0xd3217d56, + 0xebc78e1a,0xd44d934e,0x48e73d37,0x0215321b,0x201e43cb,0xbbc90bfa, + 0x27500905,0x3c23f1d0,0xc86691a1,0x2a2e5000,0x6065841c,0x08b2bad2, + 0x30026b60,0x15d41caf,0x5276ce61,0x1712c2f4,0x15932ffb,0x01c4c3e7, + 0x6a74caf2,0x7894e13d,0x0c0537a4,0x02d6f5df,0xc2b1c97e,0xa8fb7602, + 0xd0887c7b,0x612b60e5 } }, + /* 13 */ + { { 0xba245d6b,0xefd495cf,0xa2ce3ff6,0x5cf0cbb7,0xdff5feee,0x24da2ac0, + 0xcf28c6a3,0x90c914f8,0x4308a56b,0x72fdb50d,0x13d72034,0x03dbf779, + 0x822ac9e9,0xcfa5ec91,0x3aea3e81,0x0dde73c8,0x66289139,0x545ba962, + 0xca6acbd3,0xa52f648b,0x98a0683a,0xff6f276e,0xa378ed52,0x2536d3ac, + 0x885ac1d9,0x353c2c54,0x00bc84a7,0xcaff52da,0x37684167,0x3971f81c, + 0xd2d7986e,0x0f7334e1 }, + { 0x6596067e,0xafbb5c83,0x38c19806,0x33e54e19,0x39cb0dcc,0x8285d967, + 0x424035f9,0x2b53f43d,0xdfef9095,0x38c531f8,0xdb0f571a,0x90fbe8e4, + 0xa39ca787,0x9a0c1ed2,0x606f2620,0x2fecc1d6,0x72b7cb4a,0x9dc890b1, + 0xccbb7868,0xc33ca6fb,0xfe73ee49,0xd1b11082,0xfcb66c48,0x590b7d17, + 0x86e14573,0x9356b0a6,0x053ead85,0x75d682c4,0xc54d30fb,0xb2ae55fa, + 0xf8aee949,0x67636a72 } }, + /* 14 */ + { { 0xb91d6bea,0x638063bc,0x923ecb96,0xae263a2e,0xc627aca6,0x9d7b0992, + 0x77af9e7e,0xc6ed001a,0x24aafebb,0x9214accf,0x78055a90,0xa3564b96, + 0xe027499d,0x00999b1c,0xe46a06a5,0xe413a4e1,0x2e51efe7,0xa05d13f6, + 0x9ba843be,0x35e87d34,0x3183159e,0x0a633825,0x54601923,0x6023e8ba, + 0xb7fd1cf2,0x9b107721,0xfdf2fd53,0x46b5542b,0x1c18af38,0xb314f4f8, + 0x60ac8965,0x086f9876 }, + { 0x8cbb9850,0x76701954,0xa20d2c8c,0x6210b730,0x5335670c,0x4084d057, + 0x0324baea,0x3ecdc595,0xc76ee9b4,0x607fc5f2,0x440ffa64,0xf393d00f, + 0x2dc1463c,0xe0111796,0x9c7725e7,0xf00b8251,0x5bd1d186,0x35e60736, + 0x2cf72aac,0xf3d8554c,0xefa3497d,0xb4dd0fde,0xf646ad11,0xd712268c, + 0x9f7b8ead,0x07c20afb,0xfc06dfe5,0x630969d4,0x7245549a,0x76b7df1c, + 0xe61ae810,0x681f9403 } }, + /* 15 */ + { { 0xc9a0623b,0x7cad5163,0x67fab8d4,0xdbf82957,0x81af7c7c,0x2ccab0ec, + 0xe966d5c2,0x469e38c8,0xf0d4e41c,0x34430d52,0xa52b359c,0x426075a2, + 0x33bd0127,0x242dd3e3,0x9fed2341,0xcda3f635,0xd7d52ffa,0x4df33730, + 0x7640c3ef,0x5fff56f0,0x1bbde57c,0x4783c21c,0xeb8bb336,0xd8784a2a, + 0xead08405,0x1ec7c533,0xf9b62bd4,0x4b7f1423,0x7075d4af,0x5543145c, + 0xba60590a,0x0c9de94a }, + { 0x95d5682b,0x8ed72735,0x2ec276ed,0x711c4283,0x8b36a0d2,0xd1f4aed5, + 0x8498a88f,0x62ab40c4,0x4480f451,0x58c8fc62,0xb79cffe2,0x8bc8ca4b, + 0x701a359d,0x90ab583c,0x3fd5d15d,0xaee31a73,0xc912333c,0x02a5597b, + 0xb6c3e3c2,0x1019cae4,0x29938088,0xe513042c,0xf47c8199,0x0e00283d, + 0xf2a00e92,0x90d68e58,0xa775ae3b,0x69e2df41,0x871c30b2,0xb8d2eca5, + 0xbb1de396,0x733dca0e } }, + /* 16 */ + { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6, + 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd, + 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd, + 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521, + 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494, + 0x0f1fa7d7,0x2ab3bd47 }, + { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135, + 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2, + 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f, + 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c, + 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1, + 0x4c27d229,0x93a4b416 } }, + /* 17 */ + { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1, + 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519, + 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e, + 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30, + 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6, + 0x32ee7763,0x342ce0d7 }, + { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a, + 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858, + 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66, + 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433, + 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb, + 0xe156fd20,0x455f4af3 } }, + /* 18 */ + { { 0x754ec21c,0xc057f262,0xe3a1ba38,0x3eacd4c9,0x116c1fe9,0x3a0210d1, + 0xeacc8ab6,0xe4ea4e94,0xea6f32ca,0x31c00c9a,0x86b975ce,0x5cb6239d, + 0xa14ea1e9,0x654d5d8c,0x5067fc8b,0x230d31f4,0x6355fecb,0x48bb90cb, + 0xdc172e8e,0x78f81ece,0xcb006737,0x288380a8,0xe162d012,0x19b02e01, + 0xc5af145c,0x0e087a06,0xb72dc354,0xf04dc8b7,0x8de3c066,0xf70ef214, + 0x13009fb7,0x4f148243 }, + { 0x6e2055e2,0x5e004fce,0x86c32067,0x89e247ea,0x5f9daaa2,0x4ebcbd95, + 0xceb7f63b,0xd15f212f,0x863784a0,0x5ecc5c1f,0x75760251,0x53b3800b, + 0x8a6a2954,0xeb9301c3,0xa13cdd19,0x0f16ba18,0x887c2d24,0x8313d251, + 0x9a9413f6,0xf9923585,0xfe3fd7c5,0x423405e6,0x16e0ee05,0x678aeb34, + 0x3fadaab0,0x1f3be7bb,0x82884471,0x7901fa2c,0x4d662ff6,0xc950db30, + 0x3c01170b,0x74d5d2d4 } }, + /* 19 */ + { { 0x2b5bfe11,0xa3002dc0,0x52d321e7,0x0733410d,0x9679ba89,0x15920f65, + 0x685b236e,0x0e248c14,0x346f6040,0x8cfab594,0x40c717f0,0x9f57afb7, + 0x66044576,0x0dbab28c,0x9cdc3247,0x0fa09968,0xc230ed05,0x41e02ae2, + 0xe45bef74,0x0d961554,0xce4d7b6f,0x9688a982,0x5e62d22e,0xfadefac7, + 0xbd2cba28,0xaf1512a6,0xbe7c749f,0x78868e62,0xae9f5a6b,0x88048d81, + 0xc5857a29,0x6b1a5442 }, + { 0x43242066,0x9f5ab9ad,0x2ccca2ae,0x0afef1b5,0x988edc4e,0xb1b43ec7, + 0x0341b0d5,0x0d0c00f1,0xb50aab37,0x4d68b8f7,0xf3a64a99,0x9a8e4e6f, + 0x7f1a684e,0x198338fb,0x351a0f5c,0x8bc0e748,0xdac44515,0x2cacf2cd, + 0x5e9ff76b,0xc14d3999,0x16393055,0x54a01b3f,0x888d8376,0x6ac3eea5, + 0x723277b1,0xb84d9a9a,0xe11dbbbf,0x99132691,0xabb67178,0x597717ae, + 0x8bb14ac8,0x4c213526 } }, + /* 20 */ + { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9, + 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee, + 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d, + 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8, + 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead, + 0x5c37c334,0x65713c29 }, + { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6, + 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424, + 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862, + 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1, + 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5, + 0x3bae3c38,0x6b0e996c } }, + /* 21 */ + { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269, + 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7, + 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da, + 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e, + 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342, + 0x678223f8,0x4022a205 }, + { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d, + 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6, + 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd, + 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21, + 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11, + 0x24a6a956,0x312179cb } }, + /* 22 */ + { { 0x07615ac2,0xa94cc3ca,0x121ad581,0x85865e64,0xa7986b79,0xae47616f, + 0x9d5e0f1d,0x395a40eb,0x3d9457ea,0xa9143264,0xfa2865d9,0x8de6d6a3, + 0x1014ae8c,0x0771db96,0x976a87cb,0x77a7cce6,0x143a0f60,0xa7de42e1, + 0xd993d934,0xe203cc09,0x98ec4c3d,0x92018693,0x3a25df4b,0xd77546d8, + 0x62b02d6b,0x0ad9eb47,0xd05a7189,0xfaaaf208,0x431221bb,0x5238181f, + 0x733511ea,0x417d6c78 }, + { 0x0e91e9a8,0x3cbd81b7,0xc370d6b3,0x73340418,0x8eaa2373,0x825db10a, + 0x6c7d6756,0x8f2b09e4,0x94c33ded,0xe288ee9b,0x1695e3fb,0xcd8426bb, + 0xdce9e888,0xa6176c86,0x6165e362,0x3f4c8922,0x6063fb09,0x514e411f, + 0xc8f9e04c,0x6907ac20,0xdfd2ad61,0xcef7469c,0x8452199a,0xba30bae4, + 0x12ac3462,0x30681293,0xc92d482d,0x011be873,0xe8330995,0xff4cbf89, + 0xd1470a0a,0x02189d52 } }, + /* 23 */ + { { 0x92599c69,0x73e419dd,0x7fec32ca,0x5b94221b,0x09bbfbfd,0xb2bf9bd2, + 0x63ed895b,0x61ea97a4,0x3f486f79,0x6609146b,0xfd141a39,0xbd1c7a05, + 0x83d64135,0xc79ec8cf,0x9883507b,0x7f8fd42f,0x17b3d027,0xafcb53b7, + 0x67ca5a21,0x86658dcd,0xcd149786,0xa6a6c0ac,0x34b95067,0x16f3d70e, + 0xdf44958c,0x371208e3,0xec280212,0xd2dd64e6,0x30782c71,0x33b2c4ab, + 0x521176fa,0x7bbf8abd }, + { 0xa78b981a,0xbe9e4aaf,0x304ec828,0x788b4e36,0x3959dea3,0x0c45cf39, + 0x240b39c7,0x70a9bdd3,0x28383b7d,0x499cd7dd,0x307a1026,0x30690b2e, + 0xee92f1b3,0x2262d598,0xb4725a48,0xc62d77de,0x7bc3aa0e,0xa16f25bc, + 0xd15ef7fa,0x62dd8b65,0x0b96d68f,0xd979221d,0xa00f1906,0xb92885c3, + 0xeb74c740,0xfa476b9b,0xc7576222,0x217ddbb5,0x5788504f,0xc2782c30, + 0xf812716b,0x860d096c } }, + /* 24 */ + { { 0x4d79bbf9,0xfebc337d,0x69f74f80,0x5d53eab8,0x33104d53,0xff36a095, + 0x196f8b97,0x2ab820da,0x75ce6909,0x961d3d1f,0x04683754,0xb197ec04, + 0x93a6cb9b,0xa68ce1bf,0xc5f021a3,0x503456ff,0x8940ffdb,0xb50a2db1, + 0xef004209,0x77c50f8f,0x04965875,0xd635d177,0x8bb8770a,0x725766d9, + 0xa078e53e,0x8e19b028,0xf9fc8378,0x364d4cca,0xf0dd39a0,0x1a3df411, + 0x03adf920,0x7e80e442 }, + { 0x539a1ddf,0x4b5f8a57,0xee486562,0xd248e7ae,0x816021e1,0x1c7b491d, + 0xfd36d2c4,0x2e7b871b,0x0aec00d9,0xda38b504,0x6193f1b3,0xf2827612, + 0xfb1f78d6,0x69c3fe86,0xe827ac33,0x56c8b786,0x3487c8f7,0x1687f6c7, + 0x19dee5bc,0xab8f2217,0xff399418,0x04e8473f,0xa9027c80,0xf384c014, + 0xaa1d2e28,0x9967be9a,0xe065eef1,0x869686d3,0xc7bd837c,0x737c6b08, + 0x9e8bd863,0x5dcab5d1 } }, + /* 25 */ + { { 0x9a7d772b,0x0784283a,0xe540959b,0x6b49e525,0x86414ab5,0x546bb008, + 0x9d74b2a9,0xd4448162,0x203b0b1b,0x267890ad,0xc8d3f86b,0x1e7a82bc, + 0xd85a83c7,0x1352bfb5,0xfad07ccf,0xf29f16e3,0x41e0c43f,0xc02a63b8, + 0x6b379fef,0x904f22c5,0xb1244f26,0x19d8a653,0x3a28bdea,0x6635b6df, + 0xf6d455ce,0x18b68851,0x9cff3735,0x74ac2818,0x8b2cbdab,0xad40f9df, + 0xadc9d498,0x08cc2d9e }, + { 0xc170c84b,0x2e6a6866,0x5a49a484,0xbb989e8b,0xd04c8992,0x7b0e00e0, + 0x61b3a423,0x55ad3478,0xb0d01899,0x3c952450,0xe3100cb3,0xe3922155, + 0xf03276d0,0x19265b6e,0x76d42b53,0x0fe8595a,0xfc6353b6,0x0a96dee0, + 0x246f893e,0x761e0dc8,0xf0a74cba,0x4ec902be,0x3fdfad9b,0x61008684, + 0x4fdb6975,0x5d6a60e4,0x7ef7590a,0x3f53aac8,0x12870a37,0xd29e6be0, + 0x55aa55b0,0x991fadc1 } }, + /* 26 */ + { { 0xb4844ffe,0x82bc4b0f,0x60f8b871,0x73922714,0x4ce3f1f3,0x8ac000e2, + 0x163519ec,0xf0d548b4,0x88288b5f,0x7aaf842b,0x2bdc9a70,0x9e8b0c4c, + 0x4ba5fd67,0xa06d5152,0xf93cdec3,0xd0b1afa0,0xdf89f8f0,0x280955ba, + 0xeea32c92,0x86cbe92d,0x3fe05be4,0x0cae3f99,0xfa6919aa,0xf2607095, + 0x6e0f1b8b,0x0f54741e,0x30ecf988,0x2aed1f74,0x734991d7,0x9296f76b, + 0x259f0fe9,0x66cf8d28 }, + { 0x226f5868,0x9b01905b,0x16909e9e,0xc102e88c,0x4a37eb54,0x2bd08916, + 0xc9816323,0xf72253e8,0x86bac53c,0x37f84e9d,0xafeaaaf7,0x2e352454, + 0x2ca0046e,0x67c86f77,0x6663372e,0x86bce50e,0xb6950a04,0xf6a3a960, + 0xfc1aba93,0x61f994d7,0xc1326e6e,0x1957c12b,0x2e56b005,0x9b658fe4, + 0x8592740c,0x9cd297fc,0x177f26a5,0x7654ce9b,0xa79d2ebb,0xaaa699db, + 0x0ecb6448,0x5fca0c5a } }, + /* 27 */ + { { 0x569a6663,0xe26e25f3,0xe6aa4ca7,0x09597ee7,0x8d18b80c,0x25a4cda6, + 0x22926730,0x450602b5,0x07387209,0x9af5f650,0x26733a53,0xfeeedb34, + 0x86572951,0x0f5ce768,0x8398ae9a,0x872a360b,0x2b30f6c3,0x60347a80, + 0x1a162158,0xd2113b23,0xee6c6dec,0x6fd9cf92,0x5cbcf9e6,0x85f0a5a8, + 0x2ba3fe84,0xd7a5a6e4,0x51ecd727,0xaafe6720,0xa2081a10,0xe09c6bb2, + 0xb973b0b4,0x657acbf0 }, + { 0xc274c8d4,0x3130466f,0x30a994d1,0x42765176,0x7079435f,0x217258ca, + 0xeb897a06,0x44850406,0x561ee130,0xf38dfeee,0xaa1778bb,0x11f4facf, + 0xb9abb9e9,0x765c6617,0xd8f10932,0xb135499b,0xa73b9159,0xc0eb6337, + 0x6f7e8b6a,0xf2c1ccf1,0x187def53,0x5b32c03a,0x830b9c62,0x89ad1d49, + 0x2f10e538,0x1735eae3,0x9d5f55bc,0xb1cbd9c2,0xe539db0d,0x42428c47, + 0xc852b3bb,0x3d2da412 } }, + /* 28 */ + { { 0x871f2865,0x97702b6e,0x142920d6,0x56cb639f,0x45b58611,0x328522a0, + 0xf3b13812,0xf3943ad1,0x712206e8,0xe6c2200a,0xa34d59ea,0xc2890e5a, + 0xf6b7f759,0xab52fd40,0x180bf567,0xf522c8de,0xaccee396,0x181e97b2, + 0xc4ea5cbb,0xe0375819,0xab51d3ef,0x0d9985e8,0xbcb50fd8,0xe26c96ca, + 0x97e1c80d,0xfb9d6b13,0xf796357d,0x582b1814,0x07f4c7fb,0x89a78221, + 0xc0357e61,0x02aeef2d }, + { 0x2c7ec9be,0x2ba7926f,0x7258b201,0x292f307e,0xc6fa6b4a,0x74e62a10, + 0xe2bcc5ab,0x80c08549,0x7bb8c073,0xb4160db8,0x329f194d,0xd5ef0529, + 0x6dda4a9c,0x0eb8da14,0x15ea23d1,0x0b5d43d2,0xfc34bfae,0x6cebef02, + 0x848757a7,0xacd364d0,0x2d34cca3,0xc1401368,0x1d2d95e2,0x09ca6742, + 0x786eaa28,0xc3fd1d6e,0xa2965fec,0x9eb1136d,0xc0779203,0x48871baa, + 0x4b15aeb0,0x6b446c01 } }, + /* 29 */ + { { 0x25e8fe80,0xc819eb2e,0x98238a17,0x2b5f7906,0x81e41849,0xd6f1e996, + 0x98ea6d45,0x58ad8ad6,0xbfd02e40,0x5bae5ad4,0xa812416d,0x016dc327, + 0xa3347ca1,0x8b31a985,0x82a65391,0x0b4da610,0xb48c35fb,0x1cb91b2d, + 0xd2aaf8c4,0x9e96817c,0xcdfdcdc0,0x1a630483,0x12b69254,0x70559361, + 0xf8a2a097,0x5fdcd712,0x35cc5281,0x59ab623a,0x932b6095,0x30c8ebe0, + 0xb08e052f,0x8613424b }, + { 0xb2231d8a,0x28902063,0xd9a61667,0xb0f62329,0x071a9f27,0xaafa0fe7, + 0x603f047e,0x6bcd8960,0xfd92a1c3,0x118cca76,0x71d483b6,0x3414e62b, + 0xba705262,0xa123ccdd,0xfd9b5c5a,0x1a576437,0x4c8d0fa3,0xa5301bc2, + 0x102427cd,0x96f0ad44,0xd3aa6c02,0x0e6fb5e0,0x072a3996,0xcd8c4880, + 0x840d3fad,0x4dafca12,0xde91d541,0x29f4ca3d,0x8441734d,0x0037c598, + 0x9ccfe57c,0x86333a99 } }, + /* 30 */ + { { 0xecf53b40,0xd213a751,0x2f78a542,0xcff2c6f2,0xf13ae56d,0x0f59f0e2, + 0x0e61748e,0x91f8ccbf,0xd72c4145,0x0aadecb9,0x4c9cdcb7,0x6b2ed852, + 0x1eaffc70,0x8e00b72c,0xaa728102,0x89b24285,0xb679cafa,0xaa7ea7e0, + 0x4f0a6f6f,0x5d2b8c26,0x0e804397,0x7ed7b173,0xc8573049,0x5a93eb45, + 0x0986e93e,0xc92bf5d4,0x6a20c0af,0x526b5a9c,0xb99dc3af,0x0adf47c9, + 0xba202cc9,0x12b25fe2 }, + { 0x33eea395,0x09b8d78a,0xf633fc5c,0xc7a93618,0x270eceef,0x7e821629, + 0xc628ed0c,0x524779b8,0xa1d68939,0x91db5ca1,0x586edc90,0x8626e18e, + 0xfeb3f3bf,0xfe023e8b,0x0250171c,0x6279fde1,0x55e172de,0xe52ec7dc, + 0xc6d4ca45,0x445e8695,0xbdbc10f1,0x42de3878,0x6fc3835e,0x2b114de8, + 0x7e10b652,0x9faba456,0x390e78fe,0x4111d82a,0xaedf0aca,0x576b61c2, + 0x74accb74,0x216279a9 } }, + /* 31 */ + { { 0x4047f747,0xc14cdabf,0xc1315a1e,0x03ca233d,0x40e5d0a7,0x59e7cbd3, + 0xbb413869,0x1fd0c4e9,0x0f01fbd8,0x189d08b1,0xa76b823d,0x50449c42, + 0x398b00a1,0x81c224a1,0x8e8179e4,0x08084e4f,0x698e41e9,0xfd8af994, + 0x5610bf2e,0x1e30e37c,0xa7d2790f,0x4e6a043f,0xb3195388,0x9d96e60c, + 0x03799dfd,0xe75f986d,0xf8ff902f,0x3b4a8f11,0x7588416e,0xfa945378, + 0x9827535e,0x20683e3f }, + { 0xd0378878,0xcb582e26,0xa7945787,0x9e214c23,0x8f6688b3,0x13d000bf, + 0x40515270,0x7548d4f5,0x40111f5d,0x7113c15d,0xa8bff902,0x3bf5a526, + 0x9b4945cc,0xbda6b010,0xbc2f3a05,0x83dcc74e,0x43efdfa1,0x2aef6284, + 0x565c5bf4,0xd2e60ee9,0x592f243a,0x4f0fa10d,0x1bc3bf51,0x6ae58b32, + 0x60576a74,0x813b0868,0x4d73081a,0x0bc023f8,0x32dcee59,0x9fd03aa0, + 0x27d6c795,0x5e416bf5 } }, + /* 32 */ + { { 0x026cc23c,0x24313760,0xb5b29058,0xf819aaee,0xc5d2ee17,0xa92272f8, + 0xee5cc402,0x8048e7cb,0x77def07d,0xdbc7d6ee,0xf6af821e,0x61d69244, + 0x996cbb89,0x5f7966ed,0x96a155a4,0xf81b17ea,0x03f3ed56,0xb2d9ef70, + 0xe882a5b2,0x5e6e5906,0xae947180,0x86fa1072,0x658c76f4,0x34d9fc51, + 0xcb035aa0,0x9f603dc0,0x75be6481,0xb7b39feb,0xcf04a9ef,0xca87554a, + 0x87b4fde3,0x4ff682ec }, + { 0xd0a10ad5,0x3125627f,0x968e6f45,0x7fd45c72,0x806a1163,0x2981bd6b, + 0xde5033e3,0xb92de1cd,0xbf4f8988,0x3b44b45e,0xdae7e1dc,0xca1b9896, + 0x0778d878,0x52166e5a,0xa5116847,0x82d472be,0xf2895445,0xfbdd382a, + 0x5d6ec4c9,0x22ed1602,0xb6552b02,0x3614eb1c,0xa1e6210f,0x63c5df73, + 0x021a74a7,0xe9160285,0xc65cbd4d,0xa44ca400,0x0f15e299,0x48cb187e, + 0x3402507c,0x51eb818e } }, + /* 33 */ + { { 0xb92100ab,0x1fc1d178,0x9605b839,0xdf2e3d60,0xb71e59d0,0x12a7c255, + 0x14fcbe04,0x3f8b6675,0x59fd06af,0x0e8a3935,0x12020d07,0x56326502, + 0x528e7be5,0x6696fcd1,0x0c7b7654,0x6588514b,0x5912a5b5,0x0cd80f8c, + 0xf324cb7f,0x8bafef04,0xc6da3d75,0x6b53eecf,0x31d1df2f,0xedef48d8, + 0x73812b6d,0xf336b965,0xee626031,0xc82eae4a,0xd244f09b,0x300abd32, + 0x31d9647f,0x8b0af955 }, + { 0x2e603544,0xb770180a,0x221acd9e,0x2b573ac3,0x62407032,0x3a17f665, + 0xb89abc3d,0xad3e74ad,0xd793225a,0x8a3d2e3a,0xef02564b,0x457bba04, + 0xfc2dd2b5,0x8875652f,0xe67143e8,0xd2905d15,0x02e48d70,0x6d884b42, + 0xc7636a57,0x06f99219,0x35e378df,0xa8dc3421,0x10c64a02,0x95c1d73d, + 0xcc157a66,0xcd6a4ece,0x8e24a354,0xbadcc1c8,0x9839329d,0x8024f1b2, + 0x4da48ad0,0x5363e549 } }, + /* 34 */ + { { 0xe23fc641,0x1f5523b7,0x86667063,0xfe54e72f,0x8e009d2f,0x294a15f5, + 0x8c57f5e1,0xf203997f,0xb16d64dc,0xa229724c,0x4baa2ffb,0x697be4fd, + 0x0a6e8ed6,0x3f507e46,0x78508536,0x0afe3a5d,0x95408208,0xeeef6cdd, + 0xf2c4237c,0x701fd889,0x5c385253,0x496d883a,0x72a212f1,0xe25c67ed, + 0x1ff78fcd,0x4b416783,0xc16f4146,0xe9967004,0xc45b0697,0xfa45c3a1, + 0x3fbd30c3,0x63334018 }, + { 0xa2fbbbce,0x39c9a0cc,0xaa0cb744,0x876f6e5c,0x3438ece3,0x9ce6010e, + 0x13802d82,0x0aad148e,0x9cd45a1b,0x9c3e5c60,0x7bcfc1e0,0x875cb859, + 0xd8584dd0,0xb19ff790,0xd81c2a2b,0x2598b81e,0x02be07e3,0x118bdf2f, + 0xb9765ce9,0x074fc8ee,0xb24f95ae,0x125e9d88,0x0c98f09d,0x3bb12cdc, + 0xa0b74b27,0x4a6aee07,0xc08077ce,0x4723d2f9,0xbea8026f,0x959447d6, + 0x16280b73,0x93a7075c } }, + /* 35 */ + { { 0x715b27f9,0x26bbefe2,0x2a280923,0xa935a5e2,0xfd58a26a,0x5ddf23af, + 0x7c138694,0x54c83e16,0x892a2153,0x44799bc9,0x9b8d09f5,0x4e6e4710, + 0xd588ea68,0xc63af616,0x883ab1b6,0x5e896706,0x3d209336,0x3c1393a0, + 0x92c23dda,0xd02f2921,0xdcf6ea43,0xab70cb7a,0x791559e1,0x12434ea8, + 0x6d70ff0b,0x040680db,0x2832ba45,0x1a10fe52,0xe5f0cb8f,0xd69f9c08, + 0x44b141fd,0x1a7422ac }, + { 0x9f40b675,0xc3a9dd2e,0xfcc71f39,0x2a7c6603,0x1948e342,0x18939a61, + 0xed0ab484,0x8f3b6158,0xee31ca6b,0xa3aa7d97,0xf7a8db63,0xbc1e865e, + 0x2c7c62e4,0x315f8c09,0x9f5c6d0f,0xa260788f,0x4b6f3ec5,0xb1833129, + 0x36b4d849,0x73adbcd6,0xbc699a9b,0x66e14890,0x2a1175e7,0xbf3790d8, + 0xfc53ca4f,0x7f43605a,0x87ff6091,0x577f6c47,0x600c82b6,0x827c7552, + 0x9d25599c,0x0944d630 } }, + /* 36 */ + { { 0xe6ab9620,0xcfdeb63e,0x786cd808,0xdff4fa6d,0x456320b3,0x145edd82, + 0xc4943915,0x2ae5f862,0xb73b3f87,0x9508e813,0xe52f97a9,0x3bd805f3, + 0xc9829b62,0xf71b5c28,0x86e0cefc,0xb394c70e,0x23bdb36e,0x534fb1a9, + 0xdbe27e5a,0xd64f5862,0x83ab6169,0xbae23df3,0x27c828cb,0xdd6df1b1, + 0x3a307a8a,0x1901899f,0x811ddf66,0x36cc8659,0x79943b77,0xa3cb7774, + 0x6fd86576,0x7d89f383 }, + { 0xc9f92b2b,0xf8564242,0xc46e32bd,0x700c6a75,0x7f99a5c5,0x93e768b7, + 0x03149568,0xb6efe858,0xc2ce6709,0xbbfe8a19,0xee6ec493,0x721a3b1b, + 0xc371c28d,0x26eeeea9,0x15177e1d,0xd798115e,0xb068a5a5,0xd7bf3bce, + 0x46d2b4b2,0xdf8da220,0x59be9dfc,0x3df0995b,0x77640b79,0xc96897bc, + 0x5a2bd3c5,0xce0cf4c2,0x89afe744,0x16f45d6e,0x3a8509bb,0xb53f3acb, + 0x63f2a6e6,0x449af81f } }, + /* 37 */ + { { 0xa16d9377,0xc2fcf132,0x7e1a2f9e,0x9ab377b3,0x86d19ae5,0x72e1a12e, + 0xd013bbb1,0xd2b12e66,0xcb5f66ba,0x0972e055,0x399eab50,0xd11de1c0, + 0xc65f5ec2,0xc1f314fd,0x8a9ff593,0xfc311841,0xe05246e6,0xdf73c1ec, + 0x1625056d,0xc28d1363,0x6fb25e19,0x30a9dbd7,0x845cd2d7,0x049ed244, + 0xd36e852d,0xc779b83f,0xf68c8a83,0x85a35fc7,0xc95e8033,0x299bf1e1, + 0x20891af5,0x0e8617c3 }, + { 0x67c81b5c,0x53720602,0xe737873c,0x2fa89dcd,0xa8144fd0,0x2a7430b0, + 0x26208c83,0x3006c5a7,0xd8ea40f5,0x4e066660,0x896413a4,0x9dd025f9, + 0x46b9149f,0xbdf380cc,0x0a125cc2,0x80156619,0x52793c37,0x04d6a3b7, + 0x6b7a62f2,0xb6001374,0x585d5978,0xa9cfe268,0x8395fe66,0xdcad0cb8, + 0x46b261f6,0xbab468fc,0x9d9d9218,0xca0ef5ef,0x5e452402,0xc507d4a8, + 0x326cf687,0x6f4404f1 } }, + /* 38 */ + { { 0x4febd3ff,0xa3e1920b,0xfdfd2bba,0xca6234d8,0xe19a9829,0xb7d1af2a, + 0xc6f5bc20,0x23de1610,0xdaa39ca9,0xe204dbf3,0x6d8c70ab,0x2a2de9b8, + 0x7c9d370b,0x272e0c37,0xe565510e,0x80914c06,0x57cbb6b0,0xb611e7a8, + 0xd8266a6e,0x076fc6ef,0x3095801c,0xdfac34ee,0xb9e24063,0x69ff40a2, + 0x787aa5c5,0xa7ba31a9,0x33c70cd2,0x0e4d1fdf,0x6895f074,0x903e3132, + 0x7fb671e2,0x905771f8 }, + { 0xa4062bee,0x5199ba0d,0x94d7d9f9,0x18e7238c,0x1e0922c0,0xf53f29bc, + 0xb12d855f,0xde9b2a81,0x6d68ca29,0x649f3eed,0xc50c097f,0x64adfc34, + 0x9db398a0,0x81964ab9,0x7a587224,0x00d59c47,0x74c5903a,0x09fea396, + 0x15043dd0,0x6aafd8ee,0x5f1ecc20,0xc5721a6e,0x0db9b7b4,0xb6d6a483, + 0x66c8d52a,0x06ffc617,0xacc82a27,0x3de241d6,0x27f2f7a8,0x0605f052, + 0x6404decc,0x6a22953b } }, + /* 39 */ + { { 0x74fce389,0x92452d8f,0x2afa5564,0x059634c0,0xf0ed7825,0x9377ccbb, + 0x37718e0d,0x89f4045b,0x9fa69a4d,0x11074e7d,0x7295b0ba,0x5d70bb07, + 0xf107ede6,0xb22d54ad,0xa1a29c7b,0x5c39a3d8,0xd795e3ab,0x37236c02, + 0x2b589951,0xf7282d00,0x5790bee2,0x5e2265be,0xa8e65ea2,0x91e0ea11, + 0x6001cebd,0x0e71a708,0x2c1c5402,0x16900f5a,0x357f6981,0xc3b2d5c0, + 0x619e3427,0x528c9ea0 }, + { 0x5f26c577,0x1edc86b4,0x9438bd45,0xf8074708,0x792582a7,0x2dfe1013, + 0xde1e569f,0xe08eaca0,0x9a55a356,0x5f952efa,0xe4976216,0xa4d80b53, + 0xcd5d71f2,0xd2b65855,0x66cea3f0,0x246704bf,0x492323ca,0x193f641f, + 0x9adb1325,0xa681855c,0x2d19d652,0x86d522ce,0x5b82ed7b,0x53609f10, + 0x8e150d29,0x3b0f0094,0x0b13e891,0x23ad8bfb,0xf794b449,0xcbb1556c, + 0x738bcf57,0x200f9093 } }, + /* 40 */ + { { 0x8388387f,0xf9b22fc5,0x28e883c5,0xcf26f170,0xd1b7973c,0x447cab90, + 0xf6ec9171,0x8d5d4ea2,0xc30cdbc0,0x2e16f498,0x48623c2b,0xdc92910c, + 0x30dbc545,0xeb1491b0,0x14de21b0,0x631deb2e,0x2fe830f4,0x04a21066, + 0x379c1f3f,0xa4c6979c,0xfb06a795,0x8a732b68,0x1619dfa9,0x3a44327a, + 0x8dbe2c9b,0x91a307d3,0x03989fea,0x939bc8d2,0x0f4a331f,0x3daabaf2, + 0xdd0f55dc,0x5c307e98 }, + { 0x35b233da,0xbbc4e0c4,0x22f6f985,0xe3d29085,0xa8b02468,0x99dd2d21, + 0xa96916e7,0x978f40e9,0x614bcced,0x0327d86c,0xb290762c,0x95e95502, + 0xa879f2ed,0x0ffd2197,0x50e0bd33,0xc4365137,0x0827c4c4,0x26c3148a, + 0x3fcfc0b2,0xc79812a8,0x31928589,0xc3d8d17e,0x8830f42d,0x8b572cfe, + 0x4b07f83f,0x7cd9ff92,0x0a51148f,0x331ca950,0x4c59f9ac,0xd0c53968, + 0xc1434785,0x1df16dfa } }, + /* 41 */ + { { 0x68bcacc3,0xcc7bb4ac,0x430f58cf,0x06ded34f,0xd461855a,0xc59f9f4f, + 0x45c9f0bc,0xf5491994,0x4375c892,0xdc5f7ec6,0x3c85983a,0x1b8708f1, + 0x82fcd087,0xb32a5cc4,0x2d6b4c0f,0xefdcdc35,0x8ac6fb2d,0x4bb24f04, + 0x33906471,0x5982d4f5,0xb83a3ac4,0x162eb52f,0x2337a223,0x7130df28, + 0xcbc3dbd3,0xdce7b802,0x2467ac0e,0x8b395959,0x1b56717e,0x21d3d2e8, + 0x46512617,0x729a7f50 }, + { 0x8420f90a,0x874ed1aa,0x0fe4c855,0x6368e19e,0xb0be74af,0xb62d4aaa, + 0x8ca60ca9,0x76fcc480,0x7645a867,0xf310b5a5,0xddb1b24c,0x131bac9b, + 0x2dea5b44,0xef77d71d,0x72fcc64e,0x4706d210,0x673d77f0,0x29b92691, + 0xe89e0663,0x22e00bf3,0x74077d40,0x472d0cd3,0x829232e2,0x3e21040d, + 0x38dc8533,0x2f916dfb,0x14b8f667,0x48bbb59b,0xd44be19d,0x19de9f4a, + 0x232d9d5c,0x7f6d3649 } }, + /* 42 */ + { { 0x6e794819,0x3bd064de,0xf82ebda1,0x5a6b694e,0xb91e2804,0x1f017fe0, + 0x07a43cd2,0x190d31f3,0x630433e9,0x6c26f226,0x0abfdcb4,0xba488aa7, + 0xa46411c0,0x418d9085,0xbffb5880,0x1b934fe6,0xe200f849,0x75d1e237, + 0xa55413db,0xdf04d63f,0xe23b3f77,0xe216ed75,0x0f91bd30,0xa05866cb, + 0x7729c509,0x84c395d9,0x452ab2d7,0xec97e188,0x0093d686,0x8cb7c1f9, + 0x628f086c,0x2d032395 }, + { 0x4a44b4c5,0xa81c9407,0xcc702c98,0xb9846879,0xceb0dc97,0xcb502287, + 0x6e3aa321,0x30301126,0xe4c256c2,0xc0ac8763,0xe55b4845,0x65034d20, + 0xf240f35b,0xaa96a040,0x7cf7eedc,0x046d26d3,0x3b810656,0x62a5a8e1, + 0x83d70c2b,0x86044b97,0x59e4da8f,0x2fbaff88,0x5457f5d1,0x929d901a, + 0xb531b757,0xd29e1eb2,0x9e4e9739,0x214dabdc,0x4eaa9bd9,0x5bd724fc, + 0x1ef9bb9b,0x734c12b3 } }, + /* 43 */ + { { 0x92f9b086,0x98fe3c2e,0xb3fd4544,0x4641b93e,0x5c02c65c,0x47ce208b, + 0xc4f03242,0x8a52dca1,0x679d29f6,0xb5ec17d9,0x9406f5f4,0x11d2fed0, + 0x0d9ba811,0x260f63dc,0x15472a3f,0xde2b056f,0x007290e6,0x1b170d9f, + 0xb6b5c8f9,0xa2e23e8d,0xcf34c3ee,0x345a2839,0x1b973ee2,0x9bdc5461, + 0xbb24d1c5,0x65bda6c2,0x3c6141a1,0x97d52ba3,0x9d2eb201,0x47bb1612, + 0x21fbe49f,0x7c558a87 }, + { 0x3f350fec,0xb9485a52,0x6a38d4c0,0x016678c5,0x0d5aa64d,0x8ef346a2, + 0xd96da2e4,0xb85daa02,0x4f647b3c,0x845ec4ea,0x0d5e946c,0xc0d1a6ca, + 0x4fa9f4ab,0x41d8d1c1,0x9c8b1303,0x43972cc5,0x434ffbfb,0x67e1f48d, + 0x819d2318,0x350ce93a,0x6ddef23f,0x49f53090,0x200cf12c,0x3c2e6cf9, + 0x640432fc,0x42691cc1,0x72496b52,0xbfff74b4,0x020a97be,0x44527c9f, + 0x7b3c4348,0x34cd7dca } }, + /* 44 */ + { { 0x59e7fe87,0xf031761a,0x0047cd72,0xb1eae31a,0xfae30f62,0x27902e68, + 0xb71db143,0xa666f48d,0x0e0038f4,0x75ee6678,0x02bdd76d,0x3b45ac67, + 0xa0d6cd5c,0x0d2fb828,0x9d8c5b11,0x27ce7f1d,0x120b5e96,0x141fe0e4, + 0xb9267c37,0x95a1b984,0xd60312cd,0x5206e589,0xda549356,0x1867342e, + 0x070c74ac,0x374520b9,0x9557b0b3,0x2703cbb5,0xa6ed8c14,0xf621f59c, + 0xabf7b887,0x7ceb1cc2 }, + { 0xdb7fd65b,0x0647a5bb,0x36c9457c,0xd8d45cc0,0x9e12718a,0xc6da99db, + 0xe93a7fb1,0xed1dbbf4,0xbd1566a1,0x4512c95c,0xdbc0c919,0x4861ba00, + 0x9e7f5269,0x3c6cc298,0x0941aaae,0x67196150,0xc8c538e3,0xbfcf5d0f, + 0xa25a551f,0xad6e9929,0x17ca0f26,0x90710985,0xfa89ef7e,0x743b78ea, + 0x71ab4549,0x39d5ea31,0xe6d1c36d,0x7442f3f3,0x059d568d,0x25a683e0, + 0x227ced5c,0x1f629a99 } }, + /* 45 */ + { { 0xe45a1c3e,0x8925ddac,0x41f7545f,0x72d29365,0x37e7f828,0x45622fcb, + 0x3e4c79d2,0x88234513,0x9c2645d6,0x5dffaf84,0x994802b9,0x3078f4dd, + 0x9d339fa0,0x566927f0,0x9fd91dcc,0x9a500a1e,0x0ab0abd7,0xce008180, + 0x8194e5df,0xd97135a3,0x98adf088,0x9e876307,0x9a45a2a7,0x3baf01b8, + 0x788b4399,0x6fed6154,0xe77a997d,0x980e5722,0x2a378eed,0xaac90ffa, + 0x8bd805a2,0x4a75fda2 }, + { 0x55e74cbc,0xd09a8fbb,0xfab18f25,0x737738ce,0x9764ec3a,0x0fc23ad6, + 0xe7e0ad31,0xc5a7d35b,0xe481cc9b,0xe75e068e,0x3d4aec34,0xf0c2ea99, + 0x0d4a63c4,0xf1324fe8,0x99b0592c,0x5dbb7c16,0xa7e0f46b,0x442d674d, + 0xa300faea,0x5a5d66c7,0x3333ac83,0xe83dc821,0x8c408496,0x70ef812e, + 0x99ef5fc1,0x96e1dcb6,0x1734e862,0x6e2b771b,0x583507d8,0x04629cdc, + 0x23d8179a,0x5819f9ae } }, + /* 46 */ + { { 0x6aa78811,0xd9969121,0x2103e7c3,0xf64ee8f4,0x22b9e698,0xddf01070, + 0x4f582cde,0xe6001f9e,0x2ecfac1a,0x24a608af,0x06393009,0x6ef4c784, + 0xebf72911,0x5262eae6,0x8c4ee5a0,0xddbd0af5,0xecd87bc7,0x875aff90, + 0x6f24f114,0x2fddb34c,0xe865f172,0x48104281,0x886c1b9a,0x95692426, + 0x9ef4231f,0x6f5f3208,0xd0a7e82e,0xaf587acf,0x9ac395c8,0xd6571917, + 0x1364a750,0x7459603c }, + { 0xf41ae519,0x1c2475bf,0x4af8f251,0x34401fb1,0xaefb2c3d,0x70ddfcd2, + 0x51cdaf08,0x9b2d385b,0x8208bb19,0x8531c256,0x4c33f3f6,0x16c89df6, + 0x24571769,0xc23cfa99,0x86d010ba,0x2339b51e,0x22638313,0x08db0e8d, + 0x00fedeb7,0xf769e179,0xa3687ef1,0x3fd96dcb,0x91476475,0xcd046b23, + 0x0c45c8dd,0xf3ff2064,0xb8343d78,0xefd167bd,0x4b77ee90,0x493ccb6d, + 0xb3cf7b45,0x33025513 } }, + /* 47 */ + { { 0x35eaaca1,0x36f00469,0x89119102,0x0c384b75,0xe6d2954c,0xcb375665, + 0xb1e9d6d7,0xcb9199b9,0xc29c2757,0x75852349,0xb8e738d0,0x89cbd1ba, + 0x5923a427,0x9b8dbe90,0x18fe1889,0xa237793e,0xa742e083,0xa4271757, + 0x4eebd613,0x8c4979d2,0xd4f2cf77,0x40325054,0x958705de,0xa3b8a091, + 0x33d999ba,0x1b191bd9,0x3b0fee1e,0xbafefba4,0x3facdf14,0xb3bad184, + 0x4387561c,0x9328adb0 }, + { 0xf906b872,0xabe84e80,0x78262665,0x705523a0,0x3398ccf7,0xd89c6a7e, + 0xf55b5323,0x2fab551d,0x0554dea8,0xa0578eca,0x375589cd,0xef26523d, + 0x864ad750,0xd8fd6242,0x178fe1fe,0x93f27fc5,0x9df87422,0x7b3e6f30, + 0x3750d054,0x2862e49e,0x5dc038a1,0x7d90c6b2,0x84db682b,0xc1a1ae22, + 0x9881930a,0x47f3dab7,0xbaf3e0a4,0x30e6bd52,0xf62d25c5,0x0680025b, + 0xadd0d5e7,0x0aa1f3cf } }, + /* 48 */ + { { 0x22a10453,0xa9822190,0x2a03a10b,0xdd1eb91c,0x96646f3b,0xafbb5d95, + 0xf38b6fc6,0xa58de344,0xb8cfca1d,0xce47c3e5,0x0f70da04,0xfcd8e16d, + 0xda262ed6,0xac44349b,0xc56e2f8e,0x9320d87b,0x19138e58,0x9ce3ea08, + 0xa2b236c0,0xa5862dff,0x8e7efb0d,0x6b0f9a5c,0x16ac78eb,0x4b53432b, + 0x709b51af,0x6ff43105,0x8f519628,0x08e236f8,0xeed403ad,0x1f93f176, + 0x9636545e,0x559337e0 }, + { 0xd8fd807a,0x30ddf738,0xab131222,0xf4e0ec9d,0x625afbc3,0x14a2f4db, + 0x9f12f895,0xd5b70604,0xac3044fd,0xb46f3c23,0xf540148f,0x1b232d1f, + 0x39b4e554,0x61b458f5,0x0dd70b75,0xf694b24a,0x289581d9,0x0fc64299, + 0xee5fe22d,0xc05d49be,0x6a18bf63,0x7af3447f,0x7f1929d6,0xe96a1dc2, + 0xc1551e8c,0x6afe6028,0x2b5d4fa2,0x27dacaf3,0x545c2cb4,0x4a1631bc, + 0xb0c914d3,0x930070f9 } }, + /* 49 */ + { { 0x69a9bc05,0xd2f32c5e,0x589c4b73,0x0a5c19c6,0x94665f9c,0x095c9e5e, + 0xbcfb4c39,0x8ab0f293,0x1ddb7c31,0xb9070877,0x66b38048,0x894e9658, + 0x606bd9bd,0xf19a90cf,0xb6fd2d69,0xcc1d58df,0x461d8a69,0x886dcc4e, + 0xf9ce4831,0xc455c277,0x765f8a82,0x749a5996,0xc3badc8d,0x2ffc668c, + 0x9112cdab,0x38018396,0xb243c7cb,0xa98795c3,0x010a2224,0x8775f310, + 0x587b5e14,0x043a2141 }, + { 0x3a873752,0x7bbe9dbc,0x2f442fee,0xee1493f4,0xc18c2181,0x981ca2c8, + 0xe29769e7,0x00ce3090,0xde768c5f,0xb4626ac8,0x34d7677e,0x33e9ce46, + 0xe0fa94e6,0xf89c2cad,0x41f5b5bf,0x04f5cc11,0x2228c12c,0x2565f736, + 0x0c05cce5,0xf1bf706a,0xbe487c4f,0x5d07ffff,0xa499f1a4,0x3ec43c09, + 0x98d94800,0x4f4e79bb,0x073f12f8,0x8a335a16,0x0f970d6d,0x4bb5eaf7, + 0xf24d0ae8,0x18d0747b } }, + /* 50 */ + { { 0x84601faf,0x58d3c77c,0xaf1c1f72,0xc9465be2,0xd116d806,0xff626798, + 0xd5b0d93c,0x3996c0c6,0x5ec6723a,0x2fa1ad75,0x03ba5349,0x966a8144, + 0x2ac34d8a,0xdc4c9422,0xed675865,0xddf471de,0x953d528f,0xd8aca597, + 0x24ebf67d,0xb2e463b5,0x7e25b4d3,0x25824871,0x43159daa,0x23c5adba, + 0x83357540,0x5458f9c6,0xf938b1a6,0xcf685da7,0xcefed231,0x981a4fda, + 0x08bb5e59,0x711093ed }, + { 0x401f161a,0x12aa3fc6,0x974c5e87,0xf7358560,0x17b5df82,0x4aa252fb, + 0xa48e6299,0xb0b82b07,0x29dd847d,0x00234157,0x4529c5a6,0xf1e54d00, + 0x6d98f538,0xcc1c539e,0x28d3abcb,0x36162b53,0x2a84f0cd,0x75a37938, + 0x4dee7484,0xf717a81b,0x4c23bf1b,0x16cf35fb,0x787e8b3e,0x7fd1c29f, + 0x59b79ab0,0xb7da7e68,0x85f6c60b,0x072100a0,0xe7ed48b5,0x31840159, + 0x4d9c97d4,0x17898bda } }, + /* 51 */ + { { 0xae1b8cf8,0xcd8483d8,0xe9a28856,0x323d4b42,0x204a4bc2,0x7633584f, + 0xca7a69fa,0x4e0b2228,0xf757bab2,0x8afbda8b,0x6cc5f9ca,0x85b24088, + 0xd41a95c3,0x47fb4813,0xc2aabe6b,0x3f1bc53c,0x1ad1599d,0xf22cda3f, + 0xc31ea9b1,0x1b2ec081,0x01614ac1,0x048f304b,0xc6afa7ab,0xce31cee9, + 0x4140dc3d,0x55af7633,0xdce8abba,0x84b7ab37,0xc7cf3efe,0x50de7648, + 0x15356ab2,0x73a88dcf }, + { 0x06e83b39,0x3f868288,0x9f44037d,0x477a4413,0x17dbc841,0xf9058b0f, + 0x54d17549,0x2db64f4f,0xf2307ffe,0xa23cea6a,0x4f126261,0x393efd55, + 0x10f37f26,0x2f4e658a,0xf4ee1e35,0xa4437ce3,0xa93cde8b,0x64ef42a7, + 0x939aa901,0x1debc9f4,0x3d7b5cd4,0x44223d6a,0xf88a3acc,0x789a6a11, + 0x2c608a2d,0x56fb9df8,0xbbf56c06,0xe79db8e3,0x668fa300,0x73c56af2, + 0xae396a1e,0x52f32b17 } }, + /* 52 */ + { { 0xe714f71a,0x56f524c1,0x9add8519,0xc1be1262,0x65cadbe3,0xad9189d8, + 0x5a0fb649,0xd88bf5c8,0x21d192d9,0x9efa6a92,0x6f724b6f,0xe3fe8389, + 0xb250119c,0xec3fae24,0x2ae0d3c0,0x4b6af9f6,0xd619624d,0x8fceba0b, + 0x2fdb6e3a,0x7dc3092b,0x3263cd29,0xc91da376,0xf95c43bd,0x30c0761e, + 0xcdeb44d9,0x89136400,0x43c0d31d,0xfd7dce84,0x9871899f,0x78fec3b1, + 0xefdf58c1,0x79e14d28 }, + { 0x9bb40c55,0xe3822235,0x0ed07a42,0x0a27202d,0x4838c1f4,0x48e6c1a9, + 0xd864a78e,0x2b5f24a7,0x0c6c55c9,0x7e7f140a,0xce12d508,0xe62c104a, + 0xc11b1e10,0x9b0a1a7e,0xafbb3dd5,0xfd8a275f,0x9a3b6b30,0xdff354fe, + 0x46602a01,0x5a105d9e,0x93bb65f7,0x3d371b4d,0x0f82fdeb,0xda5cbf0b, + 0xde468545,0x4601229b,0xc73d517e,0x505e10b9,0x672ff492,0x77cfa541, + 0x99566ce2,0x0d8ec28a } }, + /* 53 */ + { { 0xcbeee995,0x014cf73e,0xd491e80c,0xb2eb88bc,0xd9aba5d4,0x615a6cad, + 0x9304c84d,0x2f7d4633,0x8ab03c9a,0xba0501d2,0x91babb94,0xc8f723de, + 0x50405772,0xc885f977,0xc7fcb094,0xb5e1d2b3,0xdf96c71a,0x61ee7995, + 0x3464499e,0xb8c8daab,0x5f607932,0xdb425ddd,0xb1243587,0x70251ca1, + 0x9fc74340,0x26d7d3be,0xc902ac89,0x8c179310,0x4559a74f,0x72522c15, + 0xc3734afc,0x86001e27 }, + { 0xe7693947,0x13b00ba5,0x012c062b,0x6478641e,0xe85490a8,0xe1a438e0, + 0xd9574d5e,0x5173dbbf,0x9bd3ba61,0x9532eb8c,0x5f3ea075,0x1f41bcb8, + 0x8cbb92b9,0xac1cc247,0x1ef901b4,0x0f34648e,0xd2b3b2ee,0xdd929d1e, + 0xc3d75bfc,0x470f1eab,0x139cf4d2,0x5cdbc6f7,0xf0424953,0xcd86454d, + 0x47fcb383,0x1e079812,0x17df930c,0xb9f209b4,0x114ebc00,0x4225fc31, + 0x347946c1,0x020591cb } }, + /* 54 */ + { { 0x275e0af4,0xe3003721,0xe78a4a4b,0x721141ef,0xd1757485,0x666cfcf6, + 0x168e659e,0x5fa1d737,0x0e2842ee,0x263e3e54,0x948bd5f6,0xadecc3d4, + 0x246b104a,0x019de03d,0xf343d818,0xf8a9e903,0x5b0c0d31,0xcb57ba4a, + 0x51e2765f,0x8246c506,0x6519bf67,0x80c5751f,0xf2119a01,0x5f05c200, + 0x7821d4f4,0x7e6487b8,0x261c3a06,0x262f94aa,0x72146052,0x56cfe489, + 0xa1df05ef,0x5119985f }, + { 0xb18586c0,0x5819497d,0xc6eeaa62,0x004415d6,0x97cda28b,0x7c6a46b6, + 0x7c194594,0x9a149b28,0x4ed3a506,0xb56369fa,0x43c94cb4,0x7092aa66, + 0xa9e9eee2,0x55bce73a,0x77893509,0x34bb2870,0x06eb5326,0x8af95fb0, + 0x9638f485,0x87cd0323,0x5ba75bf8,0x29376268,0x9d42d581,0xf32d6f3d, + 0x65c6d64d,0xa4cad574,0xb2cded41,0x985f50fb,0x9006a067,0xcf34ce0e, + 0x58a57f9a,0x59eaf265 } }, + /* 55 */ + { { 0x6ec3876f,0x7b407efb,0xf0f48648,0x780c6123,0xbf893039,0x2abb56ff, + 0x45a91ab0,0x9592eaa0,0x78811b82,0xce5b84d7,0x1f9f3fc9,0x86a71a34, + 0xf0e7e13b,0xc17fdd86,0x655a0880,0x88ed8297,0x81d5e666,0x75d6dc74, + 0x1d171797,0xeffc9df6,0xe3f79e1f,0x36ad4c8d,0x2046192e,0xdb15317d, + 0x274fda62,0x78c9fa7a,0x82dd9914,0x04ec924f,0x3a64971c,0x059d1e38, + 0x2620bbfb,0x3b4450ea }, + { 0xc776dcdb,0x3db7a955,0x81c8ba47,0x35c4a57c,0x505760fb,0xae285003, + 0xb3aec353,0xe3e80691,0x47117be5,0x380335be,0x056ccf61,0xe1c47e3a, + 0x33977916,0x253cfdeb,0xf5cb7ee1,0x3decdfba,0x7cf4b704,0xf3c9794f, + 0x9ff81462,0x2401680c,0xbe3daa9f,0x4e440e11,0x69f91d8a,0xc5d04377, + 0xcb5e9c5d,0x4106c7a8,0x33b7d24d,0x191909a1,0x3764b4a2,0xe893c838, + 0xc429b614,0x4a7fe30c } }, + /* 56 */ + { { 0x2455c7c5,0xe78f3a70,0x70157754,0x5b7636e8,0x7623262c,0xf32c4524, + 0x1bc780c7,0x2c98b11e,0x915ed877,0xd48eaeac,0x199265f4,0xbb04d3c0, + 0xcfa5200f,0x6b52b19b,0x93ea3fe8,0xc46a0981,0xba758059,0xd82c733d, + 0x1896aacc,0xd324bbd6,0xce8ecd51,0xac09a2fc,0x02fc44b3,0x529918fd, + 0xaaa1784b,0xf0c45e4a,0xfe22085c,0x35626340,0xc50c7d61,0x53cbb676, + 0x65126b23,0x83fa1ea3 }, + { 0x10ccc646,0x60ac86da,0x7b0451e9,0x2ce0637f,0x8a088610,0xbbbcf630, + 0x20349982,0x23c19019,0xfc0bcda0,0x707fc39c,0x1bd4fd7d,0x7f4d1f15, + 0x44713bbb,0xd6a64e74,0xc5ac9e60,0x57bdc676,0x37b61169,0x456c5303, + 0xdcf40a1d,0xd3451396,0x4997d2c7,0xf3edec25,0xc2c4a739,0x534ae9a4, + 0x6a6ad2e2,0x1401397e,0x23e95f81,0x20769d4d,0xde98fabf,0xcee007c6, + 0x931c51e0,0x61409779 } }, + /* 57 */ + { { 0x15156623,0x3ddb32db,0xab7a67c2,0x68137fbc,0x6f19e3c2,0x26011f50, + 0x89924c61,0x34218b02,0xc6804c1c,0x492a0b0f,0xafaae6a7,0xd65be706, + 0x0d01be61,0x3b13d23e,0xf87f4c69,0x44545b47,0x04dc1aa3,0xd42236e2, + 0x3c5161ec,0x6135261d,0xbd88bc07,0x1eb46a63,0x1599d720,0x78c6d836, + 0x69baf0f3,0xf6955fe1,0x17072820,0x467eebd6,0x3e3a340a,0x2f1b8a2a, + 0x2d0b5f88,0x636dac76 }, + { 0xb4c80af3,0x94280db9,0x4e3892ab,0x9a189cd1,0xd1477ddc,0x26e702e0, + 0x68f9f14f,0xe91aee38,0x80baa0b2,0x2864f63a,0x8b714a29,0xacd81f73, + 0xc5fe7cb6,0x30e1b870,0xb10837fd,0x883ea1c3,0x6b20489f,0x2da27953, + 0x58a2da5f,0x3aeb2a68,0x03a8fa14,0xe2330bf2,0xdc70b1c4,0xb5c488b5, + 0x299678f4,0x0a78c4d9,0x25df675c,0x233bd098,0x7b67d368,0x37b5c076, + 0x4d0bef3f,0x2f6dbdfe } }, + /* 58 */ + { { 0x2e4da7c7,0x2f8472fd,0xae677932,0x708cfc91,0x3dc268e2,0x364af08a, + 0x799a2424,0x0f10dfe0,0x71d58bff,0xef912d58,0x988962e6,0x6bf35dfc, + 0x5f47ea0a,0x28b96fa9,0xaad308c1,0x734a79ea,0x9f437bba,0x95730337, + 0x6cf54f75,0x002cbd8e,0xe7632eec,0x47606dcf,0x53193104,0x404b5ecb, + 0x0acf729d,0x0ae0897c,0x3bddf1de,0x89628b86,0xf87d7448,0xeced154e, + 0x458d5d4e,0x5cb6e197 }, + { 0x008c75ed,0x98cef197,0xf6eeaaf8,0x7cf49d3e,0x1875e96d,0x1d6f9e02, + 0xdd9b0d8a,0xfcec2cfe,0xb9576daa,0x38a61cfe,0x36a7dbb8,0x10003f39, + 0x23b814f4,0xb37c3868,0xb80e3153,0x9fb66dcb,0x059847a8,0x9e7e2eba, + 0x35a72770,0xa4ec63fd,0xfc9e0ed0,0x311f3d91,0xd515baa4,0x3c1dc094, + 0xa08cd4e3,0x75a06ebc,0x2ed5eeaa,0xab617238,0xe1f52c1f,0x2e82bbb0, + 0x5175d6e5,0x2149d630 } }, + /* 59 */ + { { 0x5f9311f6,0xee1a8e6f,0xbabc1f85,0xc97e3c9f,0xb494209a,0x4fa7c52e, + 0x19774fe1,0x04c2f51c,0x8555844f,0x5cefd122,0xb5873ab3,0xb53862a3, + 0xcbed19fc,0x768efdd6,0xee58469a,0xcdc12479,0x3d80c09c,0x11237e31, + 0xc044c28c,0xdd74a290,0xbd47e287,0x9ee6517a,0xad0ffeef,0xc2421228, + 0x818d281f,0x4273088f,0x43ec0de1,0xebc744bc,0xb415bd73,0x5b26eccf, + 0xcb07c26c,0x14e2f350 }, + { 0x4216946b,0x548d2a10,0x7a4bd92d,0x6e801f07,0x43695160,0x5996d0a3, + 0x63a197c9,0x0f1b5c2f,0x061f77c9,0x79da3c4f,0x93ff7b22,0x1c1cd634, + 0xa234123f,0x5e61b650,0xf284033c,0x826b34c5,0xc2f34214,0x718b90e8, + 0xae806ec5,0xa5f35620,0xe324a9b4,0xa2fae345,0x8b53cb51,0x8c0bb95e, + 0xf9965778,0xc94f6ac2,0x6b9def32,0x07ec607d,0xd0ed8f27,0x63bf1dba, + 0xdcb61e4f,0x58537e02 } }, + /* 60 */ + { { 0x64f80ba2,0x1f64b064,0x0559a45b,0xe8e055e7,0xf1f4b634,0xc3262b34, + 0xde8c8482,0xef4f7d5f,0xc30c780a,0x9d55dea0,0xcfa1e693,0x1740afb9, + 0x7460c34b,0x2cfe6a66,0x1187c1ee,0xf6695941,0x5f974d94,0x1382f277, + 0x004549eb,0x1ca0ace4,0xbabded02,0xf8244b3f,0x4e3653ea,0xc36f4d06, + 0xc55c5f83,0xeab9f0dc,0xacebce90,0xd93b9cef,0x19061425,0x16658e72, + 0x82d7970d,0x4857835f }, + { 0xd2576210,0xdcd525bc,0xd51b5443,0x9f378aa7,0x1bd83994,0xfe97bf17, + 0xf38ac621,0x930d0f63,0x818408cc,0xaf8f2c17,0x260f53f6,0x2692c87e, + 0xdb0a75e4,0x0ee45407,0xffdb1b37,0x0ec47ae5,0x7aa6a44b,0x769129dc, + 0x2e40b75d,0xb6f932b2,0x95ef3b77,0xe06764d0,0x68bc63e8,0x28fd47f5, + 0x9c0014c0,0xd1810494,0xd7995d8e,0x90e2d3fd,0x6c2a85af,0xeb39a05d, + 0xa21f3128,0x6c0277bd } }, + /* 61 */ + { { 0xb509e7ef,0xe41b7086,0x3d7f9f91,0x8842ec7b,0x5526b88b,0xcd285f94, + 0x051dd0ab,0x6e44e064,0x774f1ceb,0x90198c10,0x123e661b,0x6ecabe98, + 0x32f647d9,0x44811136,0x26c52aee,0x1dd82b45,0x939dc9d5,0xd650907f, + 0xfcd455bf,0xbd5eeef2,0x8d2e5d7c,0x7815a4dd,0x88bc9f2a,0x5ad4ec92, + 0x57a3b322,0xc6f10d0b,0x20b9cbdb,0xe8d0c1e7,0x9b774ee8,0x5a0b071a, + 0xf22fcf8f,0x3067bc9a }, + { 0xb7ca9326,0xe0e589f2,0xb1224f63,0x17a106fd,0x747a57bd,0xb2354521, + 0x62b0882e,0x2614982d,0x4391ffcf,0x7f3af544,0xa84e440d,0x1aaa337b, + 0x941bb071,0x28ea37b0,0x2e4a7f54,0xa957dcb4,0x1a6ad5fb,0xe7ab662c, + 0xf7c36a20,0xd135e381,0x9baa0b6b,0x42e7980c,0x94e4671f,0x4237030c, + 0x8b0922e3,0x24cc63ff,0x445a589f,0xd10d5279,0xa870ff6c,0xbb99d316, + 0xa996c195,0x390c83ca } }, + /* 62 */ + { { 0xffc4a73f,0x50d3fa82,0x3bd53303,0x2665d635,0x264bb77d,0x80a06f8a, + 0x22d73d84,0x81c04a6e,0x0323b8aa,0x2409cff5,0x8c4c4d5a,0x31dce217, + 0x0c0f9c19,0x374aa80e,0x00186bb8,0x0b25a387,0xaaf1487f,0xd0b77a10, + 0xab498de1,0x15f39ad5,0x1aa0c116,0x92e32da6,0x96e25ce8,0x228e3dbd, + 0x5e8646d1,0xb57c88dc,0x267b1c68,0x672b1164,0x600bdec5,0x5d0d807f, + 0x223e573a,0x3ea4007d }, + { 0xa595d0a3,0xd76debd0,0xaff0b3b4,0xa6bd76cb,0x9b1bdb97,0xbf2c154f, + 0x4c714c71,0x62b19ab4,0x221af663,0xc9bf33b9,0x8c941ef6,0x23d87c49, + 0xd79f0f6d,0x255804c3,0x2a7acbc1,0x6f1a1005,0x550528af,0x5dab79d9, + 0xc8d16213,0xfd77a6f0,0xde5e1029,0x40508b6d,0xf95da12b,0xd95ac0f2, + 0x758a8ba1,0x8860af71,0x7160c8fb,0x0b194c83,0xce004d34,0xa40e6c80, + 0x6b14aaa0,0x09f82a17 } }, + /* 63 */ + { { 0xc21366dc,0x60abe588,0xaf75daf9,0x729c0a4f,0xacb93ed4,0x70501fd9, + 0x87a16d70,0xb97e744e,0x98e7361b,0xa42e0a7a,0x28b54cf3,0x1acdaff2, + 0xb7bd9078,0xf087ccbb,0x663250e7,0xda6f3983,0xbaf07c09,0x66d693ee, + 0x8cbaf157,0x79baf4c3,0xdfca99d0,0x5a984e07,0xf26d8dab,0xab4d3247, + 0x7eba36f9,0x4d0be701,0x0e8dd216,0x37bb9e65,0x531c4f03,0x72aa4e24, + 0xb753d85a,0x77d1e984 }, + { 0xd8e62367,0xd9373239,0xb9820cf1,0x3361848b,0x5a9c97c4,0x00c7e344, + 0x14f960fc,0x9a0ec9ae,0x740474b5,0xcf41f0cf,0xece065d5,0xa5eede8f, + 0x9e808610,0xb1de5a4e,0xae0cf75d,0x17c44ae4,0x6b148d0b,0x2fa56323, + 0xd29ff2dc,0x64fa740f,0x88cb212e,0xc605eb8a,0x6a863016,0xf2c771ad, + 0x607b4c17,0x6d6112e7,0x40d49785,0xfe90ec07,0xe256e0e5,0x599be18b, + 0xca54adb0,0x4e6eabec } }, + /* 64 */ + { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41, + 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7, + 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b, + 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5, + 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1, + 0x04ecf056,0x325d2796 }, + { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1, + 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153, + 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c, + 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9, + 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e, + 0xe32a79d3,0x19d48546 } }, + /* 65 */ + { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0, + 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea, + 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df, + 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634, + 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d, + 0xb4e453b0,0x1b3ace6c }, + { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35, + 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630, + 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824, + 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387, + 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64, + 0x192f0a14,0x538ec33e } }, + /* 66 */ + { { 0xa19b56cf,0x193496fe,0x7bb99acd,0x663d77f4,0x57d0a881,0x8f04afa8, + 0x082835fd,0xcced3da2,0x5d82cec7,0x7e21faed,0xf8009c85,0x6e175b99, + 0x2d05a307,0xd9c6e31b,0x81487d82,0x96948d4a,0xd46f6655,0x86ebd3f2, + 0x773ccc49,0x86851aa8,0x8b1640a6,0x3e220f22,0x41a20b75,0x9f06e3a8, + 0x90ac0a6f,0x2cfffe5e,0x8ebeb3fb,0xf5a9b1da,0x6e08e2c9,0x2587d997, + 0x03e9f401,0x6fd60298 }, + { 0x8eb7516a,0x54709f8d,0xbdc598ab,0x83058a74,0x87e801ce,0xd234dd98, + 0xd17b8a96,0xfd0f9d90,0x6e90f6ab,0xaa1e549f,0x5a7ed55b,0x2496ff80, + 0x6c254c19,0x0d9f657a,0xb8962575,0x3cdea49c,0x2dff27de,0xb685a3f0, + 0xdb8bc04b,0x3c50e7fd,0x987236b0,0x904ff0ff,0xbb0d5055,0x494298fd, + 0xe14be8d0,0x34b3386d,0x7c3d30d6,0x7ad34e9c,0xe159fdd9,0x1f2b32bd, + 0xc761e5c0,0x84cfa23c } }, + /* 67 */ + { { 0x8b99b964,0x13bc11eb,0x58e2fc47,0x8e280c0a,0xd4c9a54b,0x870fbc49, + 0xbf6e20fa,0x37a334a2,0xd7c88cfa,0xee583d0d,0xef4af1da,0x05e029a8, + 0x0c2ef8a6,0x6d55e234,0x209e9b62,0x61b6fdfe,0xbb8e080f,0x3b1dad26, + 0x9392fc1a,0x5adbc162,0x0aae3f4e,0x02ac0fe6,0xc2bf4d5b,0x8d99801a, + 0xc282fed2,0x2333f93f,0xb52db33f,0x16dcb10c,0xc55752e7,0x09f90f84, + 0xc84a0d8e,0x287d4c51 }, + { 0x0e9867da,0x5fa58201,0x1a874cda,0x614589b3,0xfbdee22e,0x005e27c5, + 0xe612bda8,0xe357fef5,0x2d3635f9,0x4e0dbedf,0x6f125a86,0x62be70e4, + 0x0d94a2e5,0xa09b9884,0x28b5e5d1,0x7eb99a15,0x751028b5,0x21b9416e, + 0xe06d2cc4,0x1b137fd7,0xfea09845,0x6fa1f517,0xffcecbd7,0x3ba1e966, + 0x832f453e,0xd4c89a4a,0xeca68fa1,0x07b1e2af,0x4bd395a3,0xd0fb4453, + 0xd8ef9e13,0x0132a3dc } }, + /* 68 */ + { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8, + 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699, + 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984, + 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32, + 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076, + 0xb6f8aa25,0x13cbee76 }, + { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23, + 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492, + 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e, + 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50, + 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c, + 0xe02e8967,0x4e0a1ada } }, + /* 69 */ + { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67, + 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198, + 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7, + 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d, + 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6, + 0x9f99c999,0x733e30d9 }, + { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7, + 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a, + 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a, + 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0, + 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492, + 0xb79a5c0c,0x56facb39 } }, + /* 70 */ + { { 0xa3018bfa,0x019165a2,0x9ffad984,0x100c6b24,0x55341a9b,0xbbf1b1f6, + 0x25dc4cc9,0xe6bd1d97,0x2bfffe60,0x52850ed5,0x7e5509ab,0x24e992cc, + 0x4ceb59f1,0xff6c502e,0x1aa7d148,0x2f0b3573,0xe7e3aa46,0xe90c1ddd, + 0xd1142880,0xbaec9f45,0x65be5dd5,0x475cfd26,0x1febce13,0x83abb14e, + 0x80942d30,0x6aba4829,0x297e82c8,0x1e1b235d,0x50d8218d,0xb771cdbe, + 0xd94d6cbb,0x88599266 }, + { 0x155ccaf2,0x08847290,0x7c5b773e,0x8679ebc7,0xb2dd08ed,0xa88b2dd1, + 0x87d475db,0x960a180e,0x6694d02a,0x80fdb6b7,0x3f3f9e96,0x3e8758c9, + 0x4ad836c4,0xbda3f6fa,0x32fb387d,0x9400c581,0x2550200f,0x25a78542, + 0x776ecf18,0x2a97c351,0x566db59a,0x03ebf46e,0x26545eda,0x4743a280, + 0xcf74ab44,0xed169d84,0x88cb3f69,0xbaab931d,0xd8257196,0x70ae932c, + 0xa0c09719,0x797224a6 } }, + /* 71 */ + { { 0x441f3567,0x632923f8,0x2e24bf1d,0xc11c3168,0xb7671fff,0x4b97726b, + 0x7a5e1a22,0x601746a7,0x3addb417,0x53dddea0,0x7f59b846,0x57867a3c, + 0x56cd7ff7,0xb012a987,0xf19ba9a8,0x1bd5fec9,0xf8306748,0x750379a2, + 0xab8c05d1,0x7763445d,0x7903f42a,0x5d7f441b,0xa903e46d,0xc011674d, + 0xadd126c1,0x1b1d3c4d,0x61455b40,0xa2752aac,0x555c356e,0x4da42a68, + 0xd820852c,0x3ff09c15 }, + { 0xf9cb7784,0x4c0a1bce,0x2422f305,0xaec539bc,0x0c414aa7,0x5f40f9fd, + 0xffd42bc4,0xd3aa316c,0x2f358e15,0x42f5a4c3,0xd6e27682,0x00bdcd9e, + 0xf8a5ecee,0x069f789f,0x05e14f5d,0x8078018e,0x8b40c741,0x2bb3e493, + 0x7917f72d,0x5dbc8c1d,0xcc57150c,0xe0eea664,0xc3fa8920,0xa25ecc5a, + 0x1c797164,0x3c21b0f5,0x634ad16b,0x8f09a2f2,0x58391d9a,0x8e730fc5, + 0x4fdfae4c,0x47ef1805 } }, + /* 72 */ + { { 0x3da285e4,0x9965f3d1,0x3a01e3f4,0xba7d4dba,0x61214ad0,0x4738413a, + 0x22397549,0xd3b7d535,0x5a730b92,0xa53dbdcf,0x332d165d,0x3130d92b, + 0x82f97ef4,0x44a28541,0x44dce1b6,0xbf62221c,0x7e2a0ec9,0xbba13858, + 0xcbfad998,0x33f32c8d,0xb5fed44b,0x409e5f3f,0xc66217bb,0x5c328c65, + 0xfcdf71a9,0xb00db69f,0xb8920788,0xa23c2a21,0x3ae6464b,0xf8ab28e6, + 0xb8de0861,0x1a6b6e9c }, + { 0x06af77aa,0xaf6ec2b6,0xa887f065,0x2e60f5cd,0x9f498c56,0x87d21400, + 0xfcbaaf4b,0xdb595b59,0x271ab855,0x0fb592a1,0xd4349b0c,0xa0ce10e5, + 0x887d8c9c,0x9d6187d8,0x154bd6db,0x03ee95f9,0x5d06c999,0x8fe53213, + 0xfb6a64d0,0xf4a7bc30,0x66a4cb60,0x3d22af0d,0x5d37367c,0x16952cef, + 0x997d8e55,0x6f0ea734,0x731732d0,0xb447c70f,0xa9cb3942,0x00ab3034, + 0x28510fd0,0x79dd0180 } }, + /* 73 */ + { { 0x3ac7424e,0x04e0033a,0x60fda4d0,0xdb06b688,0xbcb772fb,0x236a9766, + 0xf297cda4,0x294a8e2b,0xdb013c6e,0x4b0aab85,0x8723a3ad,0x3d2aec98, + 0x13c84a6b,0x0cae32cd,0x70ec169e,0x21888f5e,0x42a88262,0x739633bd, + 0x7b60d9b8,0x68ac792e,0x10769fe1,0x89f2b722,0xd24bed34,0x8f3fcfe6, + 0xa3eb24aa,0xd35efb88,0x484c706b,0xddecfa3f,0x929ece0d,0x7cc119a9, + 0x8d405436,0x87e5ad45 }, + { 0x7d1000a7,0xba99aa9d,0xae823833,0x8b94affc,0xdfb83dc5,0xc8229628, + 0x845a418d,0x2f59fe11,0x5d417054,0xa8b970f8,0x72b71581,0x8918c265, + 0xc0d1dd17,0xe4ef477d,0x3afad7c0,0xb50b4cf3,0x01870a5b,0x21baea79, + 0xbb3a2868,0xc77087f9,0x124a59cd,0x7857531e,0x57f43239,0xed74c26f, + 0x0164c94a,0xd5f5ae25,0xf094bf74,0x6608b7e2,0xfdceea32,0xf4cdb5ba, + 0x990cc045,0x0b712519 } }, + /* 74 */ + { { 0x88d5c64d,0x5a290ca1,0xa7492534,0x0596d749,0x2a00e925,0xa04b0d3d, + 0xcaf7b66b,0x082cd02c,0xecdded83,0x912b50c2,0xff31646e,0x813ce9de, + 0xc75fff95,0x62ae70c7,0x7e2a4615,0x6f6852e0,0x03804fd1,0x320fd7d0, + 0x8218e8d9,0xb1a2a4dd,0xafc645d7,0x4918a6fb,0xe8d9fdbe,0xfb080fa1, + 0x4470b6ee,0x33d4d08a,0x6d974ef7,0xd2ba2077,0x69dae5d2,0x8ecb95a7, + 0x7d69596d,0x7a3f423a }, + { 0x9a929387,0x362d2ca6,0xcb1c1fff,0xabdb7581,0x7e51b6cb,0xd892ec9f, + 0x3a4e131f,0xee8d8632,0x5bd87561,0x4680e3f1,0xd4e7e732,0xe3a597e1, + 0x5581fefe,0x3cc72b7c,0xca8cae0b,0xf3e77f8a,0x5e2fd4af,0xfcc7d7dc, + 0x21355b79,0xdd3a4552,0xa2c07177,0x546b24f2,0x0689621f,0x415b532d, + 0x3f78163e,0x2be9af51,0x33d7ed21,0x27d63b9b,0x96802943,0xab019ef2, + 0x1623faf4,0x2da5fc55 } }, + /* 75 */ + { { 0xc8a5c600,0x62429cf3,0x3fe33e7c,0xa7a80c22,0x0a57ddcb,0x9ffda740, + 0x925b0c74,0xd1ae156d,0x6b100eb0,0x097a43f9,0xef943c81,0x169e945c, + 0x1128cf24,0xa1f734e5,0x419f0133,0x04387c4a,0x01044024,0xc007868b, + 0x90359cf2,0xe5416abf,0x478d54e3,0xf9c76fee,0x42a2173e,0x66219da6, + 0x9fe30141,0x61e03156,0x93ef247e,0xa0ff5ce3,0x072b6592,0x811792ba, + 0x70c854d3,0x855f0219 }, + { 0x847314c4,0x61fbfb6c,0xeb45b96a,0x97906155,0x6ba2afac,0x7102e146, + 0xab949781,0xed51f975,0xc110c4fe,0x9d2f5b17,0xaff57667,0x7ac8ce70, + 0x6eb244e7,0xe7366a21,0x551c65c7,0xdd1bbcec,0xe1a859de,0xb525060a, + 0x8ba7d2e7,0x7a048174,0xab8ea8c4,0xe1a2c541,0x6fdff078,0x6e7824c3, + 0x14874b04,0x79b49fc7,0x06b1f733,0x22ae337f,0x6f8fe6cf,0x1c352192, + 0x525d0797,0x292236cf } }, + /* 76 */ + { { 0x7d8b29dc,0xcdb8d80a,0x08ea648a,0xd17a2024,0xae92be91,0x7db12c5e, + 0xfda72fbc,0x1f347d18,0x9e760c6f,0x11374b40,0xd8e38d91,0x7361e8f1, + 0x739ac1f4,0x7714be9d,0xb4df5c4e,0xc1f9701c,0x6f72cae1,0xd9138ed8, + 0x6ad180c4,0x1c7fe1f7,0x9e2dbf9c,0xf8c185be,0x7c70c44d,0x835db269, + 0xb0d15b5f,0xf997cfea,0x61e6545e,0x5101445a,0x25184e5e,0x16b06884, + 0x7521e7aa,0x7cfac359 }, + { 0x3c0bc53a,0x81182167,0x7e751367,0x84b5ede3,0xa3657a18,0x3ca255fd, + 0xba1fdd98,0x096abbf4,0xc5da77d8,0x9ce8369f,0xaab342c5,0xf27b9ae7, + 0x972059f1,0x06c91bd6,0x914ecfe9,0xee0dab30,0x93f53f12,0xbb647fbb, + 0xffa57e0e,0x30c38a7a,0x9f2ad607,0x517d06ef,0xbb99dcc9,0x49728d87, + 0x446080a1,0xb0034af1,0x12b9c17d,0xcc810c3f,0x772a22a0,0x7225f14f, + 0x1ddf82bd,0x6ce3dc7f } }, + /* 77 */ + { { 0xa4397830,0xc07cd835,0xf4733306,0x4dd9290c,0x29989e8c,0xdd35d3a8, + 0x563d8152,0x79902559,0xe87de61b,0xf278d911,0x1024e35c,0x9c7340c7, + 0x4a0d0e59,0x2d444461,0xf32626a1,0x63e7608f,0xc4c9baa9,0x627a37e9, + 0x76fffd25,0x0c56dc51,0xcef2a1cd,0xcb6defc8,0xefc559d9,0xcbcc0d56, + 0x041cb692,0xe45f3fc5,0xe5161e09,0xcd05c239,0x5c3b559c,0x2a731ee9, + 0xa3d0a16d,0x85151122 }, + { 0x86ff19e2,0x782d0335,0x1da28603,0xc2c60daa,0x557c7eed,0xb2e78cfe, + 0x1bc4e8b0,0xa8f6f984,0x3df35c67,0xcc1f9b4b,0x4764462a,0x96e13603, + 0x7c7ae0b0,0xbf910b97,0x51435956,0x27c7f305,0xf631eae5,0xc14db15c, + 0x7e69b34c,0xa51d6142,0x5fc12ff2,0xdec82851,0xfb887162,0xfcceae13, + 0xde1488bd,0xda332ac1,0x2ee3e74c,0xa20374e2,0xf0ae069c,0x597ea1a1, + 0x77bdec04,0x8b1159f2 } }, + /* 78 */ + { { 0x2f961d30,0x4af71a44,0x7ac7248f,0xbdf968a8,0xb1a906cd,0xd32df87c, + 0x04abf925,0x00c10e26,0xb9f04d4c,0xb8711759,0x939705da,0x00d54e60, + 0xc9f80849,0xf7587433,0x6a7a2375,0x2e9abade,0x94ac17ac,0x5676d478, + 0xc202d99c,0x4ca0525b,0xabfae73d,0x95b8bcad,0x3405991b,0x2371ed38, + 0x458a99c3,0x2b69e47a,0x2b78c866,0x7cac0b18,0xe0232c7c,0x6ceaa79b, + 0x588f7459,0x0bd86433 }, + { 0x7e734189,0xdea1a8b4,0xcfe5fa17,0x52c5ac88,0x11437664,0x444a4d4e, + 0xaf9e9750,0xc2522308,0xd30c6b3b,0x78b1d0c3,0x4c6df477,0x2edae5f0, + 0x2ee88dd7,0x53131d9a,0xacc93e34,0xc4e380ee,0xa8db0e8e,0xd499b1ac, + 0x7f5d49d7,0x77348c16,0x1556ccd7,0xc9663257,0x2611d13d,0x65ce0e8c, + 0xb5a2fdcc,0x2c95fe66,0x8658faa1,0x26698832,0x31c32c98,0xda87d1f4, + 0xfcd91907,0x46650598 } }, + /* 79 */ + { { 0x6b4a5efa,0x4c6c13cc,0x1d07b265,0xc481989b,0x8bdc69c0,0x10b966ce, + 0x2c2531d4,0xf54cfaa2,0xcad0a100,0xcb5f1808,0xee5da449,0xbeb52538, + 0xbedd83cc,0xa6240085,0xd6255c78,0xe792dacf,0x2062058f,0x88371906, + 0xed1658c1,0x96615e83,0x7d28d542,0x4b549b27,0x83b75df3,0xeaf127db, + 0x17fbb942,0x4f60df6d,0xf6f7c930,0xd08631db,0x6018789f,0x17c38f98, + 0xb9a9280c,0x0c43574a }, + { 0x1d20cad0,0x76eb324c,0x8c61108a,0x90decb09,0x6f06d36d,0xa6e9d39c, + 0xbc0da197,0x6cd978ba,0x507ac5ce,0x5948b1c0,0xc5497eb5,0x2bd47164, + 0x4d5914e3,0x2a9c4c0f,0xa759f03c,0x772c5046,0x69ac847e,0xe7d7328a, + 0x3048b330,0xa8d57d0c,0x40f7bace,0xe60034e0,0xa85f1790,0x823d9193, + 0x5c859736,0xa6e9b66c,0x679e1022,0x22ca2c7a,0x09023fa4,0x00e7a19c, + 0x2726d5b9,0x324999f1 } }, + /* 80 */ + { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6, + 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c, + 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e, + 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb, + 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52, + 0xf18c2b91,0x57ea2b4b }, + { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a, + 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee, + 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069, + 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b, + 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927, + 0xea7935c9,0x60480b46 } }, + /* 81 */ + { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7, + 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117, + 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5, + 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0, + 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb, + 0x9a8f88cc,0x0774a0d3 }, + { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f, + 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61, + 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91, + 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df, + 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303, + 0x2432014b,0x08151954 } }, + /* 82 */ + { { 0xfb7b2108,0xf9236d89,0xad75f9aa,0x3ecc83cc,0xb4e1da11,0xf7c72b15, + 0x0315c362,0x552aeaef,0xf272fe3f,0x11e140ed,0x87843ee8,0x99d79bf6, + 0x1d9bb25b,0xce6b54fd,0x5b1bad74,0xb20b0e21,0x5b84c90d,0x54a0214f, + 0xfca6cec9,0x459bbf52,0x9e4df76f,0xe363c48d,0xd64cf17e,0x3045f84e, + 0xf62ada48,0x8402a167,0x6a74ca01,0x2c9e1bf3,0xf691c42d,0xe8cf9d41, + 0xc2c4b874,0x5abf2178 }, + { 0xf3b3bccd,0x4777966b,0xbe3e0caa,0x0047e0f0,0x8c7d5043,0xcb8383b3, + 0x946fd5fc,0xe77e3baf,0xe9ec0e87,0x79baa785,0xc8a18d25,0xd83c557c, + 0x25befcfe,0x9b96e5af,0x98c71b61,0x4f05d15e,0x77e62da1,0x081f991a, + 0xcbaa3821,0x1c6ec781,0xe54d9bfb,0x7522f65d,0x44ed1430,0xf5d05573, + 0x95cafdda,0x3035b31f,0x6378f5bf,0x47e67f43,0x5270b9d9,0x029f7cad, + 0x4d916a48,0x15ad1587 } }, + /* 83 */ + { { 0xaa588ae4,0x00de2ece,0xa371a232,0x552ebc58,0x71230444,0xd00ea934, + 0xe4b1832d,0xafbfa67d,0xb689e843,0x29216341,0x61f4e2e8,0x1f96bbbd, + 0x04c29dc5,0x95420684,0x42317fd1,0xc7fe3827,0x63483162,0xe0a0aec6, + 0x0700184f,0xfc2b94d1,0xfe1fbd85,0x07219973,0xfb074352,0x648b6ab1, + 0xc46e5392,0x23bbdaad,0x00fa56ff,0x0db8dd1f,0x866725f6,0x104815eb, + 0x52e81963,0x3f9c4cca }, + { 0x32ce637e,0xff36b297,0xf5d25cdd,0x81a15f2d,0x8b02ad97,0x1a1d052d, + 0xcfbab3e9,0x2e5f3bbc,0x614eeb75,0x60d2cbd7,0xcd5a793a,0xd4491843, + 0xcdba2144,0x2242cf75,0x88b99766,0xa20705e7,0xec77e132,0x64e12cc0, + 0xb61a9b05,0xb1c14df6,0x74825b5a,0x8fd97f04,0x3da31223,0x95604821, + 0x4d30c70d,0xde486727,0x1c12ee69,0xbcab8f15,0x668d893d,0x5dc638b4, + 0x223f574b,0x6479dad6 } }, + /* 84 */ + { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28, + 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20, + 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1, + 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55, + 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7, + 0xf0860497,0x1fe09f94 }, + { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c, + 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a, + 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994, + 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa, + 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c, + 0xdb62526a,0x4de95786 } }, + /* 85 */ + { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96, + 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5, + 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5, + 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc, + 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e, + 0xe636980c,0x1c94418b }, + { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a, + 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4, + 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98, + 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474, + 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422, + 0xb55235ba,0x611bfbb2 } }, + /* 86 */ + { { 0xf00ad2a1,0xbdbaa55e,0x14a290d7,0x29efa85e,0xe92b1694,0x3b4a4768, + 0x11ec8130,0x67111bcd,0x88bd27b2,0x0e425702,0xd9a03c06,0xf28cf2a3, + 0xf318884a,0xbb7c8d2d,0xe3aaeb20,0xe2ea1462,0x43b85d77,0x33535804, + 0x554ee9bd,0x81ee4482,0xe6aa198f,0xeb2eee9e,0xc26c5944,0x7a5aa804, + 0x82ab167c,0xa0ef2da5,0x02fe21a5,0x5a2ab476,0x3370298e,0x169cb3b8, + 0x0eb3aa8d,0x86e6c544 }, + { 0x0b793d9b,0xede03321,0x1ddb5ece,0xf79fade1,0x68930b64,0xf73fda92, + 0xfe4fd1b2,0x06aad97d,0x92a4dc88,0x073a5b1d,0xbc976d75,0x8af8cbd8, + 0x63ce26c0,0x60b4abb1,0xdcb1fb06,0x9c8300a9,0xda95b3d3,0x335a594c, + 0xb37eac87,0x1f97d7d4,0x20eefaab,0xa3d2eba2,0xf3e828c8,0x3258c906, + 0x85ab7781,0xc832616f,0x8c28b617,0x72597192,0x3233b82d,0xcd7196bc, + 0x19fa126d,0x83867eb9 } }, + /* 87 */ + { { 0x22474edb,0x774fe73e,0x1a84e1ae,0x2a766394,0x9c6dd6e3,0x270329ad, + 0x14f8bf5d,0x00c4a415,0xd2267b90,0x3ce2ea37,0x11d24fae,0x12753015, + 0x263a1b78,0x7c14d854,0x1ae0b206,0x20c8401b,0x081f49fc,0xf32a011b, + 0x959c6df8,0x1e8123fb,0x800e1d06,0xa328dc7c,0x24259a9a,0x5876a378, + 0xb7ef6c37,0x23ada8b5,0xa93d4c9f,0x023f6b6e,0xffb6389f,0x89f5414d, + 0xe628b39e,0x4b26bba2 }, + { 0x5d318454,0xd30b1cb4,0xd7436cb6,0x123b749f,0x568a7461,0x3110c726, + 0x1c84fd1e,0xc85de123,0x08403d55,0xa5f8d6e6,0x9b1fabf8,0x395b6e13, + 0x3cfedce0,0xfe6d68c3,0x94b91110,0x1d90381f,0x2dcc6eb7,0xf0a8ea81, + 0x7e90ca2b,0x59e80413,0xc8a25c5a,0xbeb5fc07,0x5d84663c,0x009c253a, + 0x910b6a7c,0x00b15073,0x4108f8d5,0x8607da4c,0xcb901e65,0x02c3d9c3, + 0x2c9615c6,0x4d697bc5 } }, + /* 88 */ + { { 0xefa8fb40,0xe0db1ef0,0x5ba3989c,0x29021c5b,0x809d19df,0xa8d6fb15, + 0x4c1219e1,0x6b787b73,0x14ef05e2,0x6417e168,0x8f9796e2,0x449342db, + 0xbf84421b,0x2f878a5e,0xe94a4536,0xe71916d7,0xae119693,0x9818bba3, + 0x5768804e,0xec674be9,0xf8424f8a,0x0a26074c,0x466ce6ab,0xdbc93b9d, + 0xc920078b,0xb3f15a98,0x3870f1a3,0x9d10fd0d,0xe4e785a7,0xa61241d9, + 0xe6c8cd80,0x76ca87a1 }, + { 0xe02e48b7,0x4357fb56,0xcc09e9c6,0xfbd14b13,0x24069cf0,0xdb5f2435, + 0x2c3b01a9,0xf878165c,0xe6956dad,0xe549e7c4,0xbbd60b68,0xf2fe9538, + 0x059dc653,0x952f856b,0xb377fe9b,0xd3f60225,0xbfe908c4,0x6a0c7328, + 0xbc8f5f2d,0xce6aa2d3,0x24425050,0xf7213443,0x3d3b3ce5,0x17e1266a, + 0xc1677512,0x75b5e43f,0x37fb894a,0x15927062,0x2be3e375,0x15260753, + 0x6da3b7be,0x27e7f2c6 } }, + /* 89 */ + { { 0xe6a15883,0x638f65ad,0x66afdb33,0xd4a7e68c,0xd3f12de5,0x6207b6ab, + 0x37b87810,0x1c6ff950,0x64acf6d3,0xc0d44cb2,0xf2be78c2,0x163ac601, + 0x1636980e,0x1c63cc5a,0x95c9349b,0x3e92cfe8,0x41ec7220,0x7738e0d8, + 0x2d5fa961,0x6169d764,0xc3e028e9,0x2aa776c1,0xb16d5409,0x93dc5646, + 0x706df4d9,0xa0b27fb5,0xce9c6b97,0x9e991170,0x53c85f40,0xea8e42be, + 0x83246528,0x02e96437 }, + { 0xae78ea1f,0x91540add,0x7b670e96,0x51a1b74d,0xf7006826,0xf9936441, + 0x7d7520c7,0x8f97d6ea,0x69ce12e1,0x0faa6a02,0x79208342,0x2590aca8, + 0x75614436,0x7a483863,0xf381408f,0x07c6149e,0xd7853406,0x733bf584, + 0x9abbb6f7,0x8761b010,0xf528a09a,0xe4eb249f,0x2e00ae3c,0x08781ed8, + 0x2178effa,0x864c1b25,0x9d513a7e,0xcc1e62a2,0x1919062f,0xedb8b94e, + 0x4f16527d,0x739f53da } }, + /* 90 */ + { { 0x924adc5f,0x7a5f4a88,0xa818f56d,0x95646c16,0x7795f954,0x0ec49129, + 0xd19c5400,0x2b48753d,0x205912b4,0x16fa236b,0xe87a4946,0x6b3d65f3, + 0x045fd066,0xa7174a01,0x12a5e140,0xb6350313,0xa96b8623,0xa79c4b44, + 0x9ab003d5,0x7a339d65,0x3826f31a,0xc72f30c6,0x6f7090cd,0xb4e7390c, + 0x906ebe24,0x59ac6c36,0xbba4505a,0x39a7f06d,0xc58c413a,0x839991e1, + 0xa20e0e84,0x020c23ff }, + { 0xafc74661,0x120e4ada,0x277fc065,0x37bbcf63,0xb6dce799,0x41049cf6, + 0x7b161ba1,0x5b8d6b53,0xa9610fb2,0x22218431,0xdfdde769,0xde9ec9d1, + 0x42d80630,0xd32bfa4d,0x6244df4b,0x3885702a,0x45592dfb,0xcdedd1ed, + 0xfb4e01b8,0x0e1df45b,0x86e215b0,0x8f4bded2,0x6a937e6a,0x80935487, + 0x8130f723,0x415278ba,0x38a821f8,0xc6dc4692,0xfd8b4f8a,0x2207b119, + 0xf9269cef,0x76e7bf53 } }, + /* 91 */ + { { 0x27ebd187,0x5f128428,0xb65aadbb,0x8d3320ab,0x72258695,0xb042765a, + 0x8f0986ab,0xda3f33f9,0xaebff503,0x411807a7,0x825f71a5,0x25c776ca, + 0xff7df24b,0xc0de7bed,0x165f1fb4,0xda8b0f42,0x731f3ae3,0x5f3ff737, + 0x193e0a52,0x4cd1d7e7,0xb6b3ba46,0x8df84aa3,0xaa1f3782,0xba84b897, + 0xe7733ac7,0x6e7960cc,0x50981a21,0x4d46d6ab,0x7cbb80ed,0x1ec12c25, + 0x2b96ef09,0x79e7ad27 }, + { 0x8f30caae,0x3cd970dc,0x0a6ebef4,0x85cabcf1,0xc714616d,0x63c1863e, + 0x519e3a98,0x1c50db0b,0x64cb13d6,0xf39b8963,0x22547b69,0xdf67d81f, + 0xd67db0cc,0x7157abb9,0x889491b7,0xccca25ba,0x7a27e0dc,0xf689207c, + 0x0fd43281,0x34ae8fbe,0x5720ec09,0xa5d91f73,0xcdfd7bed,0xb2f61909, + 0x4a039e32,0x1ec10232,0xdb0d8fdc,0xd3c3d65e,0x4fe5005d,0x32c916c8, + 0x4c0bea94,0x7f8c37ac } }, + /* 92 */ + { { 0x43ac05e5,0x33ec1e54,0xcd8d3825,0xda4a4da4,0x88bf9e2b,0x86d88c0b, + 0xb53811dc,0x34d71dd0,0xa3c3aba4,0x655040d2,0xb61611be,0x2bc40949, + 0x279a4fa0,0x1c2d426e,0x3b065ac3,0x535a5aa2,0xc52ea890,0xdaa8a32f, + 0x9fddad22,0x5a5deca7,0x2ab3b26f,0x911f05fd,0xf37cd81e,0x5dace7db, + 0x90d16b8c,0x0e0e44e7,0xe4f5894e,0x15e68aed,0xfc92a74f,0xafe04999, + 0x970e7c2f,0x1d7703aa }, + { 0x3f0062a9,0xa8a4c81d,0xd96a20ba,0xe31eb2b8,0x864bd101,0x66dd98df, + 0x4413b614,0xba05f592,0xe9a555f8,0x51a67a0d,0x2e4b52d1,0xacc2f097, + 0x7184ab23,0xab5daaec,0x7c7f691b,0xce08b43e,0x76c427f4,0x520e530b, + 0xe423ebdc,0x7d352069,0x34df14ce,0x6b5e39e8,0x446305ac,0x3dcbf295, + 0xfe34cdc1,0x682cb2e1,0x111f5afb,0xd4ac45d1,0x47f296f9,0xc5ef63cd, + 0x93c20871,0x0a2c40ec } }, + /* 93 */ + { { 0xaf5747db,0x09bc384f,0xc06ab86b,0x3bad6086,0x9e7c1547,0xa406882e, + 0x55977abf,0x2d5326d1,0xda81deb0,0x063a9a05,0x524b6111,0x9a86e4a7, + 0x4ab2eb90,0x1402f87a,0xd5c600ba,0x7d0721d4,0xf289fdbf,0x1a2fd9a9, + 0xecde6f07,0xf5dce66d,0xdab9fa73,0x62171277,0x6c474bab,0x6d2dc49f, + 0x76eed033,0xdc017e1f,0x4da825d3,0xb97175c0,0x54b05e43,0x6c297e3d, + 0x56c9c87e,0x2efb4546 }, + { 0x8b21c064,0xa4712b00,0x4a70629e,0xd186fe42,0x9b74f0af,0x6435b340, + 0x7ec9e629,0x6965aa43,0xc4c60d08,0xdda14673,0xbf3057aa,0x0b656670, + 0x3ce86f60,0x7f05e840,0x04401a16,0xc05073a9,0x294e607e,0x16b1e638, + 0x69cf7046,0x20783252,0xe8ce7d3a,0x2941141b,0x7577053d,0xd38ad8d3, + 0xcaa6630d,0xdba68fb3,0xe9504350,0xecbeaff1,0x1d2d760b,0x9f5166d5, + 0x462891e4,0x337532ce } }, + /* 94 */ + { { 0x3a00bb9b,0x3f111853,0x45f66685,0x2d2ffbae,0xd4aee24d,0x9ae11a85, + 0x0341856e,0x18ba1e1b,0x2731349f,0xa9ac8178,0x545715b5,0xc13dfd4a, + 0x5daad2ea,0xa5f7423c,0x535b76a7,0x30a483b9,0xff873e9b,0x92e9ada4, + 0x723a1055,0x15662d84,0x8edac4e0,0xb935497b,0x39d8fa70,0x61b6441a, + 0x40d1589f,0x1541d756,0xf0a05f0a,0x62994237,0x6bb28908,0xfd8b0034, + 0xd4cd32bf,0x192a2b5d }, + { 0x365ced07,0x63576628,0x05de1d1f,0x029f32fb,0xbf40a7aa,0x6d17b9bc, + 0x9bb50a47,0x1b1b2a08,0x795a6278,0x9389abbb,0xb34fc19b,0x52cff60f, + 0x387d8739,0xf3ab9492,0x6920ccd6,0xa8f053e6,0x63a9b4f0,0x3ef2dd4b, + 0x51e82129,0x9ab0ede1,0x0838bfa1,0xafba0c0b,0x9ffc11be,0x2bd5a7ac, + 0x95cc0878,0x058bfd95,0xf8c2f0c6,0x686d48a3,0x1d9b31ba,0xc33abaaf, + 0x3bc0c268,0x632e2289 } }, + /* 95 */ + { { 0x15a1ccca,0x1c851d20,0x7e522bc3,0x4efe290c,0x18eab053,0x0b741d55, + 0xbc85e217,0xae656197,0x01cf8b29,0xae13141e,0x66948478,0x2e2cb593, + 0xc31bd8ae,0xeb57bb0f,0xc264e788,0xdecef5d6,0x9cb96d86,0x6fa856cc, + 0x279183da,0x2db16813,0x383d796a,0xf03f3820,0x1d0c6fed,0x58a456ff, + 0x8a6abd9b,0x25589805,0x83f96f19,0x339f52c5,0xda7e9ea7,0xcf6ded8f, + 0x5d1ccd45,0x68c3d9c1 }, + { 0xe6b392b7,0x67e26265,0x775d9509,0xcec1d9bf,0xd76514f7,0xe16abcd4, + 0x0de72e1c,0xd86f59b2,0x1adfb033,0xa66e43cd,0x05e457cc,0xdb344340, + 0x5681daa2,0xb67a7916,0xf0114731,0xc32e7bab,0xd3b1e961,0x066fe16e, + 0xf63d26e6,0x924e298e,0x541add6d,0x9bea0dd8,0x9982f971,0xef9500df, + 0xc5f076ac,0x5c876e63,0xb23d396b,0x55e12ae5,0x2ec6747a,0x09efbb36, + 0x233286a5,0x8f2055ee } }, + /* 96 */ + { { 0xb82c1af0,0x4a4ab9e3,0xf2cae264,0xfc65e9e7,0x60187d46,0x4feaac0a, + 0xe393b363,0x27d3f335,0x819bacce,0x9c9f7c00,0xb8aa6611,0x3f7418b5, + 0x372aae95,0xffa94557,0x8db38589,0x937d7804,0x6f1fbc1c,0xd10c86df, + 0xa2f0a0ce,0x48aebd89,0x367439eb,0xae5d5fa2,0x3f17d2d8,0x103a6a0b, + 0x411d9894,0xf233f68a,0x218b67a2,0x7fece8b3,0x2319bf06,0x0422540f, + 0x340d322e,0x1292c8c9 }, + { 0x0386463d,0xf5eb5587,0x0371d97f,0xd4bbc2b2,0x0b819c5a,0x1b364571, + 0xcf04ad41,0x0cbb42d6,0x66939ec1,0x5d819c76,0xa01847e7,0x8745ac13, + 0x1c7232e4,0x4f704b02,0xacb05780,0x2c9e58a0,0xb561e295,0x9523b8b3, + 0x79f9ba35,0x3384df00,0x1eaa9628,0x78231fc2,0x8aea2b90,0xa2eac54f, + 0x30d1c263,0x8075ed77,0xfb339000,0xacb44ed5,0xf011293a,0x92546ac2, + 0xeb821764,0x7c78762b } }, + /* 97 */ + { { 0x067902b6,0xb8f7d6fb,0xd1735980,0xb2823a43,0x59741ddd,0x062cfb12, + 0x4033f95c,0x6e391b07,0x68589b8c,0x3831d0a3,0x522290f2,0xe3474d49, + 0x222e1f3a,0x4dab14d6,0x53f08d39,0x8f00fcde,0x707f28f5,0x559917ae, + 0x068e607c,0x166aa0ba,0xd7e1f824,0x602713e7,0x4d6a328f,0x7c255540, + 0x9890cd2a,0x0d2e3264,0xeca0b20a,0xf2207944,0x52f4e09c,0x5c98dc07, + 0xd84de81d,0x69403504 }, + { 0xe5407206,0xf8b7b366,0x0d88fa8c,0x1ecf54cf,0xf7272e6f,0x6fefe548, + 0x81ab4468,0xd6531372,0x4e474408,0x52cb5f0e,0x6490737f,0x9e426b3a, + 0x4980d071,0x2576c19b,0x0f272caf,0x91f34628,0x468f31c9,0x78e60a4f, + 0x90844d89,0x8776a329,0xb951582b,0x8a55700c,0x14b1adbf,0xab1af365, + 0xfbd343ef,0x22ebff92,0xb7d81f34,0x32f9fb01,0xba6b30e1,0xad850e06, + 0xbc5f9546,0x6da9e027 } }, + /* 98 */ + { { 0x5c9490ce,0x21eee4c2,0x0df68381,0xa96ec4a3,0xa4a9368e,0xe6c607e0, + 0x4bc262f3,0xd8b0492a,0x460c34ff,0x0846a210,0x28df33cd,0xf7ff7a64, + 0x21827612,0x10c55044,0x149bcd01,0x9d25fce9,0xcfc613dc,0x725611cd, + 0x97f51ce5,0x159f7e88,0x4e8c08b5,0x3fa3bf31,0x75e7538f,0xea156115, + 0x91c84020,0xd1e0a951,0xcf02ad0a,0x0d2268ba,0x058b8e5f,0xa04c6ac4, + 0xb3515912,0x773b40b9 }, + { 0x3631cfd2,0x00ff2cdc,0x807737bc,0x14c4c2d3,0x338a5270,0xd600616a, + 0xb32cabde,0xd0e3306d,0xa70b17ca,0x336738ea,0x79f353ee,0xf2f4aa8d, + 0x576f3ad3,0x712f6ad9,0x89b2bce0,0xe4279852,0xda92ca30,0x05d8f94d, + 0xd8492dd9,0x9891d475,0x4d15e4bd,0x3e06a5ca,0x254eabbd,0x4725d4eb, + 0xc0ed513c,0x31394ace,0xbbfaae6c,0x7e0f9859,0x833fd137,0xdc125546, + 0xc56c4f75,0x12b46385 } }, + /* 99 */ + { { 0x932951de,0x810dbebd,0x5aa69c94,0x96959d42,0xecb2f08d,0x5fc49c04, + 0x2250b82c,0xac74f0cc,0x3aec4e1d,0x96a439a5,0x90499acd,0xc33cab9a, + 0x54d9b3af,0x2fccde66,0x3863ae8b,0xf4af285c,0x46febf88,0x2373373e, + 0x3c9ab7ed,0x751d672c,0xfe12020c,0xc1c51130,0x52f3e56e,0xad82402f, + 0xa4a64a81,0x3489ab7a,0xd9f163f2,0x0a1fb661,0x0e553317,0x17c69be1, + 0x7d88d417,0x61c1935e }, + { 0x3492ae43,0x2e722d9b,0x0538f05a,0x1ef89d95,0x200aab63,0xae77e588, + 0xeba4b117,0x2872c120,0x3a461cb8,0x5c2432c8,0xcb938f26,0x315b3434, + 0x8c4c7dc0,0x05bf2ac5,0x596b378d,0xd2e501dd,0xcb890c30,0xa8506c9f, + 0x7c361f0c,0x3d0af461,0x5a35cbae,0x21f7b718,0xf3fc0138,0xbd1035f1, + 0x8b248edf,0x74628af5,0x48c9cae0,0x8d6421d0,0x2ca18773,0x75e3da39, + 0x71d3db94,0x27ad0df2 } }, + /* 100 */ + { { 0x305b5aed,0x9e3bda79,0x5998d6a7,0x2c67d4a4,0x0f7eb700,0xc855e1d3, + 0x147d1c44,0xc18a7e9e,0xc89540ed,0x3ea99618,0x7e6bfd20,0xa53be20a, + 0xecc14437,0xc9487e64,0x34ef85c6,0x72979207,0xd5e1ebd5,0xfa0d4e71, + 0x4d48d6b6,0xfda2b1e6,0x66e200d4,0x782a1e05,0x5a5366a1,0x2a3c70da, + 0x1a473738,0xfe3fbd2b,0x7fe020e8,0xd7ef8c06,0xeacfb665,0xec686fde, + 0x6dd1542f,0x5d9b5e27 }, + { 0xcb3e472e,0x3637c5a5,0x30a1405e,0x2153d927,0xb4498558,0x009992e5, + 0xf39a0851,0x18f00ccd,0xb5c6c560,0x26237c11,0x1343540e,0x418ed408, + 0x7e7f3184,0xfef7cbf0,0xbf48576b,0xecd92366,0xbc94c91a,0x1b75be1a, + 0x4a162276,0x8e1778de,0xc5c6bcb8,0xc52e57d3,0x5ab71858,0x5cc382c7, + 0x3f6e39f9,0xe12c2c28,0xd62735fc,0x4c7e0ef2,0x835a5996,0xe071deb1, + 0xcbb8c766,0x24f891cd } }, + /* 101 */ + { { 0x6778c1e2,0x24ef60bf,0x00d5be5c,0xff49c03d,0x2f01a09f,0xec11986e, + 0xae096e58,0x59a728a4,0x7077984c,0xaabbcedb,0x870ca5a5,0xfb473bd2, + 0x4de30e3d,0x8c928c61,0x4f67abca,0x3fae7f9a,0xec21a9cf,0x83c2b2eb, + 0x9cd9b5de,0xafa70d62,0xc60b18df,0xadeaea59,0x4049b54c,0xd5fef7be, + 0x6dd310e3,0xfceebc76,0x8f6321cc,0x7748efe3,0x18ee8af5,0xfe9c32b1, + 0xd42df612,0x863ac3cf }, + { 0xb85a2fe2,0x0a36fca7,0xee429dc6,0xf3e70d08,0x141c3944,0x8c9ba209, + 0x67272a0a,0x306a8106,0xf968bd06,0xe69a1555,0x153c603d,0xb86f7e47, + 0xef56e4fa,0x9706614a,0x98780b4c,0xc0dc36b8,0x3a1d3263,0x43657fe2, + 0x435522c9,0x01f97a86,0xedfef679,0xd91897f6,0x6daa17a0,0xebbe31d4, + 0x85accfbd,0x6f179100,0x8f9fc1de,0xe0da6e32,0xe1e7142c,0x1c9d53db, + 0x8b86725a,0x3e3f1b1e } }, + /* 102 */ + { { 0x7b7fbf05,0xb7ea15c0,0x1f1a3882,0x992f11b6,0xd1dcd1bc,0xc9ddd95a, + 0xad0f7e8b,0x31f5b7fa,0xfca7ab79,0x2936e5eb,0x19a55be6,0x30f417dc, + 0x43cde554,0x1f6f4e43,0x82f044bf,0x971f5e65,0x4288c408,0x73c3b8e4, + 0xb807f575,0x61aac59f,0x818b58f0,0xa64ee2dd,0x97a3b0d3,0x6f7a0a60, + 0x0394b058,0x8b85ecc8,0xbfb3517d,0x9a059474,0xa79c3f06,0x89ad5977, + 0x700a8025,0x81208ed8 }, + { 0x14c4ce37,0x10935099,0xa1aa48a6,0xf34bb843,0x580d58e8,0x86007024, + 0xb375b8ba,0x6db42c49,0xed3bde83,0xac365524,0x649233b6,0x5521e1b4, + 0x64dd946f,0xbc7cc5d5,0xbfb5b6ae,0x9c14b035,0x0146c1a3,0x7f22ba18, + 0x872214f5,0x0b62fbbc,0xb4921764,0x3acfd7f7,0xcb4d6df1,0x5ff10da1, + 0x62600a91,0x660e2620,0x81d9167f,0x7ac7da9d,0xb6e7a199,0x6e8e260c, + 0x80deb3c2,0x44383fb8 } }, + /* 103 */ + { { 0xe44f9af6,0xe107f01d,0x8cb1fa1c,0x36381a4d,0xfb7dd493,0xe65be3ec, + 0x26a8839f,0xd0b8435a,0x3ec789d8,0xee60f915,0x2bcc5e1f,0xe25fea50, + 0x7e44a81c,0x0477c0c5,0x230ba5b8,0x349e9f83,0xde180dd9,0xdd42f32f, + 0x64a3d11c,0x8b039eaf,0xbeb7083a,0x80ef884e,0xf12742cb,0x288e60c4, + 0x720a0262,0x44156cc5,0x7253b77f,0xcd547de6,0xa6013a59,0x9829a6ec, + 0x0d548445,0x8aee708f }, + { 0x32c54409,0x18f22d9c,0x75ebaac4,0xa9ebfa46,0x86284981,0x90e2e928, + 0x6b3a8e0c,0xd0201f6f,0xbd77641e,0xc973016c,0x70170575,0xf926f2f0, + 0xfec0ce01,0x4984048f,0xf319d304,0xbf696211,0xc91a88c4,0x74b5c844, + 0xe0030a82,0x4c40fbce,0xe4f6d521,0xbed67525,0x29d67d1e,0xaf7e47cc, + 0xc21d3536,0xfa307db8,0xbbb29405,0x56b6c46a,0x033e805f,0xf059a7e3, + 0x6096a5a0,0x970f61fe } }, + /* 104 */ + { { 0x1bec8e4a,0x1bc53d23,0x35a6034c,0x8809ac14,0x509e464d,0x4ee081da, + 0x8a488235,0x496ae1fd,0x325864b6,0xa1ae9863,0x74cd069f,0xbaca13e9, + 0xb1d8a6b4,0x3738cc58,0xe76b9da4,0x5fa71f58,0xc7eb16fb,0xc919be88, + 0xad4e429d,0xf5c8f13f,0x2499f9ed,0x4583b671,0xa10d8bd7,0xbce20115, + 0x5790bb7e,0xf66d7605,0x482b78dd,0x9316aede,0x75f855fa,0xe0d8fb2d, + 0x5a7dcca7,0x404b5b94 }, + { 0x517a15c7,0xf9ee682a,0xef880202,0xaae4cfbc,0x5106a354,0xcee2c139, + 0x170febe7,0x5de60192,0x73d0c54b,0x589e39fd,0x8c9092b7,0x195c7135, + 0x0a7bfe5f,0xcb7ed53f,0xf61cc979,0x2bd9242a,0x5395f7d9,0x8d2ef16c, + 0x70b32f09,0x0d4ac1ca,0x52d185c1,0xa587526d,0x942d6195,0x2932b04a, + 0xa500b0ac,0xfe25a979,0x562fd230,0x5fa1f4ae,0x20da253c,0x60f55af2, + 0x83146002,0x7faa11b5 } }, + /* 105 */ + { { 0x6e402149,0xb0ba4f0c,0x963cc119,0x3584cc1d,0xa6527476,0x7740dc1a, + 0xc95715f2,0x3f77ff75,0x3f89fb0e,0xb2f234ad,0xef9be3ff,0x55159032, + 0x04237e82,0xfc9fb21d,0xa153ed93,0xeb2eff38,0x10041d13,0x89d53ae0, + 0x7f1bd828,0xcf2e545b,0x43953ea5,0xdd4a27ce,0xd85e75c8,0x00d2e5d4, + 0x241be1c3,0xeb93ed62,0x0242032d,0x1e53f25f,0xc3a4e701,0xb9957636, + 0xed98febf,0x14b63a52 }, + { 0x71c43336,0x7610b553,0x23a4824b,0x19dfd4a6,0x0286051b,0x7b97a2e0, + 0x8f5f1edb,0x86abbb9c,0x9b67daad,0x67a57d77,0xcd5ffafb,0x8ace506d, + 0x89ac3c63,0x85da9f95,0x75a3d150,0x081cbaa8,0xe9346ed2,0x03353d8f, + 0xa1f9a02d,0xb2ab61f1,0x3a659c71,0xb0cb0937,0x4f5df8a1,0xb7e0e30b, + 0xeb7d5a1d,0x77c4c741,0x728e5cf0,0x8f046c9c,0xf7c171ac,0x32dd0bc7, + 0x836d2655,0x02485873 } }, + /* 106 */ + { { 0x75a4cd8d,0xcd40dd23,0x97bcba78,0x132ca433,0x258d61f5,0x30c5cd84, + 0xda1e8e68,0x0a7ec059,0x1d65d40a,0x07a8f171,0xf4350d76,0x869e655e, + 0x5983ae42,0xb98ce6f0,0x9d8bebd0,0x7b61391d,0xb1ba5d49,0x3a529e25, + 0x1f6b2cf6,0x46f732e9,0x3fa3b629,0xbd66ec6a,0xc3ef0ed2,0x397950ec, + 0x5f08b476,0xee9008cb,0x965a0e2e,0xfd6be425,0x1177bc87,0x78ed513c, + 0xfe512dae,0x6798cedf }, + { 0x1b97c5c6,0x49e3f8fd,0x78c3b33f,0x39fbab3e,0x40f595ba,0x44274412, + 0x5d7d4376,0x174225b9,0x79c44777,0x880b3fcc,0x3296b245,0xdc3aca83, + 0x1734e184,0x55913df7,0x9c934472,0xa4db23d3,0xd1420a11,0xcebb3733, + 0xf3608bdc,0xb9d20cf9,0x30cfe13f,0xa618acf6,0x5f30874c,0x75f06b31, + 0x9f0005a5,0x506efe7f,0x01bfc9db,0x8aaea78c,0xf78e7c41,0xf9179255, + 0x52e96395,0x3ea7aed2 } }, + /* 107 */ + { { 0x5b06ae25,0x98617e04,0xcb5750ef,0xbcac148d,0x604c2ba2,0x91ea2f0e, + 0x76b78975,0x00c19f6b,0x651da181,0x79b9b6d0,0xc945705b,0xf3225beb, + 0x5c005bf1,0x30b435f3,0xbc24d86d,0x440b4482,0xd6373777,0x2b8f0996, + 0x1c44b4dc,0x65fd6c56,0x30906999,0xe9405ee6,0x08aa1ec1,0x19ff0924, + 0x3d2f2895,0xeef3246a,0xbc746797,0x016c3765,0xd0705f7e,0x62d2569f, + 0x05250044,0x6a8ad39c }, + { 0x46be7282,0xe45f020d,0x21380f12,0x9405afed,0xd5da6ad0,0x4cdca5bd, + 0x7f8be61e,0xc2d6f184,0x596b8178,0x20132953,0x7a8df954,0x8d3b1e7b, + 0x39572b4d,0x757c61bb,0x80cc3b56,0xd749b57b,0x37b3ffec,0x9590ff93, + 0x145dc94d,0x39bbb653,0x2335e573,0x70c1c606,0xf763feba,0x9c2e72d7, + 0xcc61b732,0x4768e424,0xaa73f2ca,0x777d2fa6,0xc5cb58cd,0xdee4dbaa, + 0x9cfae1aa,0x1a181179 } }, + /* 108 */ + { { 0x77575ed0,0x6f6ff62f,0x7d1da99b,0x18f14fa9,0x69efd7f6,0x2e72aefb, + 0xddc28633,0xc45ab4cb,0x586c5834,0xb0e20d48,0x39775dd8,0xd397011a, + 0xf4134498,0x0130c808,0xf5115ed8,0x2d408eba,0x0260ded9,0xc506a05c, + 0x19cab911,0x9e5b7362,0xe8693a86,0x4cf508c6,0xcc773617,0x4e71245f, + 0x95d89ca3,0x2f71aa1f,0x607bbc98,0x4bba7c6a,0x212b7fd2,0xf3a515e7, + 0x9230f5a8,0x7d2ddc75 }, + { 0x4ed2cae8,0x3d05816d,0xb9c00377,0x4cf6bc7d,0x646b08d4,0xc23e98e6, + 0x4b9c0180,0xf9ee6c61,0xef9179c1,0xe11c9a13,0x8ed9688a,0xa5b6147e, + 0xd06670a7,0x7afeb648,0x17685275,0xd670333c,0x75f9e8f2,0xa89dd969, + 0x37a68ade,0xbb57228d,0x454cb186,0x21a05d5e,0x063dd550,0x4810158f, + 0x4cb6caf3,0x92dd4f08,0x7854abe7,0x70c4d852,0x6e729d76,0x845969dc, + 0xb1bf40ba,0x5a52f87a } }, + /* 109 */ + { { 0x09ecacbd,0xed019e91,0x7b89bdea,0x6544023d,0x5707371e,0x7cc51f0b, + 0x16c8e217,0x14832b04,0x81259ab5,0xb1aa6682,0x23e361d4,0x6e100f92, + 0xe3a95c2a,0xe593eee9,0x16c10e26,0x699b6bbd,0x9473a13f,0xad487873, + 0xb274987c,0xf1c14dc5,0x2559e2e9,0x57dc0075,0xc3d47ad2,0x8449849d, + 0xdd527793,0x83df278a,0xeefd5b99,0x770e3ec8,0x76bd02a0,0x2ae58446, + 0x3e705ffe,0x17f02764 }, + { 0x29abea1f,0xdda4010d,0x2407ac4c,0x636b9695,0x0433218b,0x96a60129, + 0x163d534a,0xf221fc3b,0xccc20565,0x05ba15be,0x96285577,0x1238e54d, + 0x878804d3,0x1b144257,0xa89a9fe4,0x96fbf304,0x4be642b1,0xc8a7f06c, + 0x6e2b085e,0xdd1a20e8,0xff4a591d,0x8f7f27c2,0xa4a343b8,0xc17b0753, + 0xbb173d4d,0x684b1e88,0x3dc07bbe,0x3accea44,0x4c441d77,0xdb15c88d, + 0x53e5957e,0x0ef0309a } }, + /* 110 */ + { { 0xfa8e5b60,0x4fc25721,0x691c0bb2,0x646938ad,0x0b0a2248,0xe46d4b76, + 0x7de16877,0x863f9ac2,0x2721c630,0x503bb6ef,0x0b67fb02,0xf8c199df, + 0xe07abd39,0x78c1ed72,0xb32f0dda,0xcf9deb7b,0x6c3c89f3,0xaff726f0, + 0x1972225a,0xb7008b2d,0x4f145f5c,0x8f5a6117,0x457c4f37,0x4e0e6f8c, + 0x1c453c64,0x8bbdaa44,0xa6e92c80,0x57be326d,0x5d773561,0xa9bc3fd9, + 0xbb37b72a,0x3d3b6cc6 }, + { 0x9722c880,0x6e6f12cc,0x286b6889,0x3a1b6ae7,0xad2fafec,0xba1cc09b, + 0x43bb8bef,0xad64ad7a,0x97c3f4c3,0xa5af6a00,0xc353a91b,0x2afcb0d9, + 0x69ccbf6b,0xca13fcab,0xf2abc190,0x699a1391,0x23a247e5,0x2dbd5542, + 0x95488d9a,0xe206180f,0x1244cc3c,0xba9e7bff,0x87d3a365,0x29297abe, + 0xfa4ca5e2,0x4054fa38,0x67be1b6c,0xb390623d,0x78f41a44,0x1fa67c57, + 0xc7b544e7,0x2e946e43 } }, + /* 111 */ + { { 0xc60934ae,0x2980fddf,0x164206d1,0x2c3e7eff,0x416ed75a,0xf75e7f96, + 0x5cd0b2dc,0xfac60cf3,0x1faad87b,0xddc4bece,0x9849e5dd,0x753fa87c, + 0x2c1bf1ae,0xc5d516a3,0x14732b4b,0x565dbea8,0xce48696b,0x007ebe3a, + 0xcdb97694,0x40ca74d6,0x65e4e7be,0x3f5cd270,0x3aac4ebc,0x74847c01, + 0x43d6c3a1,0x6762e034,0x467a076a,0x690d8c95,0x1eda677d,0x768d78d6, + 0x0181d8c2,0x0997ce55 }, + { 0x965a0b81,0x9297746c,0xe5e12dfa,0x48b58be6,0x715f437f,0x5573b3c4, + 0xb565c459,0xe425e907,0x1582797c,0x4f43f512,0x8ea5474f,0xe5dafa6f, + 0x13de04ac,0x2aeb8fbe,0xe8a07c83,0xed7f95f0,0x662c09fe,0x3e012a6e, + 0xc742cf17,0xbf96e9b8,0xe28a1c45,0x8ea5759a,0x5cf4e2f3,0x475941b4, + 0xf901a019,0x7dd3c02d,0x70916b2e,0xe7a4deea,0x2fa9b988,0x50b272b5, + 0xd0917fe6,0x96f9f09f } }, + /* 112 */ + { { 0x2c310a96,0x78e8aac4,0xf7a2a734,0x32a98303,0x23962207,0xc46ca83d, + 0xd9541280,0xad131e6e,0x2cabe911,0x5791fc5e,0x841b6c68,0x50cb77eb, + 0x3d3c8878,0xaff93dea,0xf1007bce,0x06541f1d,0x55cdf1fd,0x4ee729c2, + 0x323e3972,0xe0f71317,0xad4d08c1,0xa2de7a41,0xa35e22bf,0xa9912abf, + 0x89b03325,0xa050122b,0x06514d4e,0x8b9e51f4,0x79d3e0ab,0x423c7aad, + 0x40b8fea5,0x71998e26 }, + { 0xceb6ed78,0x40140fcd,0x18534516,0x653cf377,0xe8d60dcc,0x0450b65a, + 0x9dac55f8,0xce6c1a76,0xae05686c,0x8a96a92d,0x12712562,0x2fe44762, + 0xa4f39425,0x747bcb50,0xfc531fc2,0xf0ec6ff2,0x10fe9ff0,0xc97c3447, + 0x9c792cff,0xfb488783,0x026fb019,0x552c5248,0xd804c290,0x4001a29c, + 0x35c8ca73,0x742b5ad8,0x6ee5dfa0,0xc3781f17,0x3dfa4ab1,0xca6b85f0, + 0x0b0d32ac,0x8389941a } }, + /* 113 */ + { { 0xde067dff,0xc0f062a2,0xbcb80162,0xd4f32690,0x0707a2bd,0x98cd990d, + 0xfae4a391,0x5afc63b8,0xb32ad814,0x684f1b7b,0xf199dfb1,0xb0a2dce2, + 0x48f25848,0x2260e17f,0xc2d5e862,0x7393db00,0x338cf171,0x9e88f854, + 0x02acf522,0x00679429,0x6835af3d,0x19157cb8,0xb8a2614c,0x2faa6f92, + 0x134ec46c,0x04ff95f5,0xfb7a8135,0xcf00626e,0xb37a4704,0x454b3d05, + 0x2694ec25,0x1fbfda31 }, + { 0xc8f69c77,0xfdebb657,0xa3df88fa,0x92a8278b,0xc1fb78b4,0x463b5571, + 0x11c71a33,0xd2066a1a,0x089958b0,0x10c88143,0xcf9d67a6,0xb975c7e0, + 0x73037b8f,0xdaa5d208,0x40bf5861,0x5ee5005d,0x7dba69a9,0x300e6ce7, + 0xc962cc74,0x893c3cb3,0x4cf84055,0x0ac98629,0x225c9d70,0x0a7ef63a, + 0xb91e47e8,0xfe184869,0x8c2f84be,0x1b9d7deb,0xc0e278bf,0x67788915, + 0xc426f19e,0x4f9488ca } }, + /* 114 */ + { { 0xdd51b8ce,0x610dfcd4,0x36230e80,0x08579278,0x36599562,0xedc7ff1c, + 0xe2cae877,0x905ead4b,0xe7967608,0xa1c325d9,0xbd38926c,0x3e39eddd, + 0x5f6f0a4e,0xda92c868,0xf47a0fa4,0xe16f800a,0xe5f60aab,0x50b4db5b, + 0x983853d3,0x3665412f,0x9b79789c,0x64b62250,0x4e0e72b2,0xea560058, + 0xe555c2bb,0xabbd4901,0x17292e11,0x378419a7,0xe174218f,0x6e0b5aaa, + 0x8f796b92,0x688e0684 }, + { 0x313b8f64,0xcdfef641,0x942c7462,0xaef11b7b,0x5c0d8abd,0x067cfb77, + 0xaf4041a9,0x608ea5f0,0x6935210f,0x23d5bd82,0x27917a08,0x5ab904fc, + 0x45d22d21,0x85dbb1fe,0x4d36159f,0xc3d5e509,0x1d39b8f2,0xaebb528e, + 0xf44acef0,0xdd5ca828,0x20c57a54,0x24209adf,0x78f95f44,0x5742b433, + 0xa9337d37,0xd11fa7d9,0xc64cfdb7,0xd66a0c09,0x9bb817ec,0x56e55b8f, + 0xe4c41265,0x1723c7e3 } }, + /* 115 */ + { { 0xdc8b43f3,0x9a6486d8,0x26409e68,0xfc3e0e61,0xd9b46003,0x1889c437, + 0x6284ec7b,0x3a850335,0x6a9dbaea,0x5a3665c4,0xe978933c,0x7bf6941d, + 0x69341490,0x1ed5a510,0x8cb8002d,0x664a7b7a,0x60ed0a59,0x603f76e4, + 0x1f4ebf27,0xc3e06ba3,0xf2c38a7f,0x296ced41,0xcf1db08a,0x2ac18f79, + 0xcde7a3b6,0xc919e882,0xdbf68b06,0x15e77d29,0x4e947cb5,0x21978baa, + 0x7630993a,0x84bf542b }, + { 0xe364f21e,0xc1decda9,0x012e557e,0x0d6cf345,0x588f90e1,0xba246848, + 0xe3b104b8,0x9f6dda4b,0xe3aef57a,0x6bf7a346,0xe8327ea9,0x210299fe, + 0xda95e6c7,0xaa99f487,0xd2cdf645,0x24ff813e,0x8bd414b8,0xd1dbb2d2, + 0xcafa1a61,0x065101af,0x9cdebda4,0x7d9f4b9a,0xe41039e4,0xaf41b395, + 0xc50adf42,0xe3e9e6ba,0x341e9e49,0x4f2133ae,0xcb157f23,0x4968c0f3, + 0xda068153,0x383f827b } }, + /* 116 */ + { { 0x6583ff4c,0x2ec46a21,0x4ad709e7,0x4e645a29,0xc04ca12a,0xdc66e9cf, + 0x9160a7e5,0x82f128f4,0x569c762e,0xbfb227b1,0xc2edb8e7,0xf80c7963, + 0x49a0f688,0xa7dafe06,0x2d14b8cc,0xb7e41754,0x86de40be,0x3a0c5c53, + 0x1db79331,0xf0d05286,0xfbfe071b,0xb902ce69,0x210e9903,0x61e46956, + 0xf703ebb8,0xfaef874e,0xdd5f78b6,0xf668947e,0x5af5ea3a,0x6fe86547, + 0x43f94625,0x3b121f15 }, + { 0x659275e9,0x5b26e847,0x6d0fce50,0x47581cfd,0x8aa3f1ef,0x55f5cbfd, + 0xe484e60e,0x1e7be315,0xfe9698e4,0xd8f1a20f,0x7ab04784,0x25d46da9, + 0x834cdb3e,0xa526db75,0x8d08a009,0x1fd408d9,0x5b5ca816,0xfc004b20, + 0x65e4bbe8,0x5b3e3bb3,0x759bb6ef,0xf50cc125,0xc2fac737,0xf05fa817, + 0xd273951a,0x9ee102d2,0xfecb3367,0x2a8e540b,0x2a6a515f,0x673446fb, + 0x37290c83,0x5505e1d1 } }, + /* 117 */ + { { 0xd15e68a6,0x0c3014a1,0x64dd35e5,0x6f9f0b26,0x03ad67f9,0x18c3742d, + 0xd2c14484,0x74818c0e,0x0d41a3cb,0xc5181169,0xc49f3e9e,0x65c8c83f, + 0x2c279386,0x9b260c61,0xced04e9c,0xf6086fae,0xfd7c4758,0xa7b2cceb, + 0x90297fd8,0x4b3c3133,0x09701ac8,0xca8264e8,0x508b3762,0x9f976a87, + 0x983a8dfe,0x5d582714,0xd9d598e9,0x350d2669,0x0f6fd348,0x85cb89cb, + 0xa574317c,0x617d80d4 }, + { 0x70022b67,0x4cef267e,0x3768b94a,0x80536bb5,0xd2784462,0x3153a566, + 0x38243919,0x49054d44,0x5df78c4a,0x8d11e172,0xd5a1e35a,0x9b252a71, + 0x8171e31d,0x07866c80,0x1b38a00e,0x0a8501db,0xce770236,0x2ed932b8, + 0x8edaf7d0,0xa2d77609,0xb93006e9,0x3aee5dab,0xbbfeb036,0xfaffc8c4, + 0x4e21b38b,0x077b9678,0xdca8e069,0x491fc59f,0x0e938471,0x3f624f55, + 0x7cd1780b,0x5156f508 } }, + /* 118 */ + { { 0x0206e8d0,0x58234e22,0x7f15af32,0xf5f6f5d4,0xd638950f,0xafab7289, + 0x7d4495f4,0x66ec4d09,0x68da80a9,0xad890c5d,0x64f8a36b,0xe4aa0920, + 0x0f4d5c5f,0x799e257e,0x24495e31,0x44c677ae,0xa5b8e352,0x720387b3, + 0x75a287b9,0x703790f4,0xc3c1f2f7,0x54895cc5,0x41a7fa41,0xb8680f9b, + 0xb00b008b,0xfcd47458,0xba6473cb,0x149cc838,0xac9be19a,0x78ed5f7a, + 0xb33765ba,0x5254599c }, + { 0xa21b54c4,0x08739679,0xb6497d9d,0x029ece2a,0xc8488640,0xf14f1a92, + 0xe9fa79d9,0xae48dcff,0x46c208db,0x14b911c2,0xdae3f69e,0x5ab0fbf2, + 0xd1edb838,0x180ac87e,0x188586bb,0x146fd718,0x5467cbd0,0x210eb654, + 0x1667cfee,0xaa239408,0xb73d1a60,0xdb125c1a,0x881c1cbe,0xde685300, + 0x37c30232,0xfe34c713,0x6f3c8d18,0xc6c6070e,0xb4af4e83,0x07e365ba, + 0xdcf82b45,0x22f0a7ed } }, + /* 119 */ + { { 0xea7f1b7f,0xe262791f,0xdcff09d4,0x9c3d8c5d,0x39c7dc58,0x86c2a9c3, + 0x4276e8c0,0x4dad4017,0xe9fe1d56,0x0a918f59,0x2aa810c9,0xb8d79670, + 0x4aa5cdc4,0xeb7a8836,0xe7afa72e,0xfc4c23bb,0x4ac86908,0x4dbb5c9e, + 0x6a0c7e6f,0x37e39013,0x49c218d2,0x855d7001,0x94b324a2,0xe475bc67, + 0x6287a071,0xc98a8dc6,0x5fb4323c,0x395a299b,0x0c0389e9,0xe186c3ee, + 0x16734c46,0x79f81e6f }, + { 0x364f3c4e,0x83f2c1f3,0x1367e14b,0x536b2ac5,0x5933e43d,0x44a6dcfc, + 0x10d961fe,0x34e59475,0x7e3f2aae,0x08234ece,0xbdea7f25,0xcb92e00a, + 0xa791a124,0x1efba4f0,0x1192d53a,0xc2086fd2,0xb51c8af6,0xfec0d0fc, + 0xdc0f1b5f,0x48d1b2ca,0x812dbe19,0xb07a388f,0xdedbdd45,0x40873a6a, + 0xd702589a,0xbc2a1268,0x17e27b64,0xbbf6e3a8,0x6d386e85,0x73ee5663, + 0x9de7c000,0x442ecd37 } }, + /* 120 */ + { { 0x8a2f90a6,0xb4cd1ae6,0x6f5ad0cc,0xf277d41d,0x401d4b8e,0x6a3828c4, + 0xd8376631,0xe817a134,0xf5e1124b,0x142b758d,0xfd6b95e4,0x25fbc69d, + 0xd74a9e3e,0xa30c9f5f,0xd89663ce,0x5ac0f163,0x0ce6386d,0x32a9eef7, + 0xd8ed5544,0x7a690ea5,0x9889427a,0x5de23ff0,0xeaaced58,0x75ad36a5, + 0xd3e18465,0x3514a6c1,0x7f093910,0x3d9162c3,0xe33d56e8,0x5c10add9, + 0x06aa691e,0x85176b73 }, + { 0x28a21e38,0xa32110fa,0x5773d538,0x97b6379d,0x2d020dc4,0xd3697bbf, + 0x961833cd,0x59177593,0xe5fa8516,0x6d7045fa,0x786ab5d2,0x3390f29a, + 0xdc4f5b70,0xac0bda30,0xdcc615c6,0xcca0240a,0xc5146d91,0x8e1f1702, + 0xa72cef87,0xceb472d0,0x0b669ba1,0x84840708,0x7e61aa0a,0x79b08f9d, + 0x4669560b,0x388160be,0x948eb71e,0x23935c2d,0x9431590c,0xd7fd83c0, + 0x6e5768b3,0x8ab154bb } }, + /* 121 */ + { { 0x353c4a96,0x28686003,0x905cd835,0x4e5c60e8,0x8f66f8cc,0xbd591364, + 0x9faccf9e,0xb6b80b98,0xe32639e5,0xbc1c1fae,0x278aadeb,0x2f6396d2, + 0x1898202d,0x00a796d0,0x3a474835,0x18ab548f,0xb31b0e3e,0xacd056c3, + 0x0164512d,0x15ba68dd,0x4b03f3bc,0x203836d9,0xd8f206c5,0xd64eca6b, + 0x9f1779b6,0x931a361e,0x52ab34a8,0xd82690fc,0x92922e22,0x342bb8e0, + 0xe00b02a9,0x1bfcdd84 }, + { 0x75a365d9,0x310b9a43,0x08d8fb03,0xd4ade15e,0xd742df83,0x9c9753d7, + 0xde318742,0xcf7309d4,0x3360ace0,0x1228e212,0xf7669643,0x1043d238, + 0xf90f5a53,0xfc2adbed,0x7b5f9397,0x41d64cb7,0xc446d010,0x5200b30a, + 0x231720fe,0xc3c8642d,0xb9aa2075,0xfcc0122d,0x041eae47,0x856e3b12, + 0x68c876a4,0x45864455,0x233606b1,0x1a1c7842,0x227757bf,0x9b766d1f, + 0xf7b9d4f1,0x25b78a3b } }, + /* 122 */ + { { 0x156707ce,0x90835718,0x4314f90a,0x9bdc2398,0x8be57dbd,0x017c885a, + 0xad63a4b8,0xd4bba225,0x15aacffd,0x5ce71b86,0x72954722,0x5f266475, + 0x4f0ad3dd,0x0a80f1f7,0xfc352ed7,0x010538a3,0x4203c6ca,0xf8a64045, + 0x330c73b4,0x2b2c7a88,0x02dcac1b,0xb3433ee6,0xed2b17c7,0x2e0499cf, + 0xbd6329c7,0x9f8681a4,0x36fadc37,0x38979946,0x92b7895b,0xdc5650c8, + 0x65a51cf0,0x70ab9570 }, + { 0x7b585d93,0x46778ec4,0xa633fe4e,0xca6d3610,0x4ea0311a,0x21da154e, + 0xbd64002f,0xaf22190b,0xd91cb7a9,0x9e633ac7,0xee6837d7,0xed13c31f, + 0x1616ee8a,0xda4a07d7,0x3afcd616,0xd78a2732,0xba14d694,0xc06696e5, + 0x4df58420,0x733754d7,0x2778e3c9,0xe85e504e,0x55b5a5c2,0x3055aa0c, + 0x8a3acb5c,0x313df538,0x2a088eda,0x5896acb5,0x84c85dde,0xfc8842a0, + 0x51dde6be,0x5fec9f79 } }, + /* 123 */ + { { 0xfe519f99,0x5ebc2c7c,0xe5410353,0xe396bd80,0x8a3988f3,0xaded9402, + 0xd601bda1,0x1c03b735,0x14ce64ac,0xfd302036,0x01240290,0x5837ebe9, + 0xa554097d,0xcaaea1a3,0xb0b88139,0xdce73d25,0xecb090b9,0x35ed412b, + 0xd63dab3c,0x99029ff7,0x062db071,0x555437d9,0x42a4c11d,0x277d2f56, + 0x24fc9109,0x477fa645,0x2799254d,0x7b12e9b7,0xd84c618c,0x7ad2ae22, + 0xce8ed195,0x0a8d5663 }, + { 0x0a21fde1,0x43ac5163,0x6903d849,0xcfcf5dd6,0x5fdd6281,0x6d2499ee, + 0x77a49a34,0x4dedc6f0,0x2875c06f,0x46bda2c0,0x347b8046,0xd0e0e0f6, + 0x5e67836f,0x1058169b,0xde8a8042,0xc961912a,0xa93b3d32,0xdf3fea0a, + 0x0c576bc5,0x9f138edb,0xd8d37e47,0x7971ad6e,0xcce5e7cb,0xeab85739, + 0x1d202b40,0x88a4b434,0xe3a1fd26,0x5d842557,0xb3a86f91,0x872fabd5, + 0x6aa4629f,0x95b93493 } }, + /* 124 */ + { { 0x99f951de,0x9998a701,0xf058db45,0x8fade596,0xf3d03dd3,0x4d479c1e, + 0x33b141d3,0x6e928d5d,0xacfe8a40,0x9a465800,0xc1cefa3d,0xd108ad2f, + 0xe013726e,0x64b96921,0x8e83bb9f,0xb9b6a6b6,0x1242e544,0x29f1e6dc, + 0x2f65966b,0xd3f8f676,0x5e105b41,0xa34dd096,0x16011e1c,0xd4e9139a, + 0x2515541b,0xeea4dc68,0xc822166d,0x6f8030ac,0x31d16124,0xbdc7ae1d, + 0x621afa7d,0x2e25ef51 }, + { 0xdd8e7357,0x2533cf8f,0xeaceddb8,0x333ba218,0x0784d2ac,0x68e3e31d, + 0xf2804ae2,0x1c927f36,0x77e7ad7e,0x01433d22,0x587f78a0,0x0b401cf0, + 0xaa0027ae,0x9dfcf036,0x1d9a46b5,0xc9e46c8b,0x1f288d32,0xaa6de486, + 0x1b8a043d,0xdd56da2f,0xf2d0bb56,0x346230e5,0x19defb56,0x19f0b6e4, + 0x21d2c874,0x55ec37cd,0xb70e45b3,0x3dbf0397,0xac7ce852,0xf0862a8d, + 0xe141f3d6,0x87979ea7 } }, + /* 125 */ + { { 0x7f1c747f,0x9b7e7b3f,0xc6e63369,0x151a4c1d,0xb372dba0,0x4273ff70, + 0xd3ee54fe,0xca6d2234,0xd33cae0f,0x12fc8e0c,0x5dd6f10c,0x27328538, + 0xf01a9cf9,0xc86f3fbd,0xe36cae91,0x5322677f,0x2fefea44,0x39a70033, + 0xce8af217,0x2c9ca328,0xf6a731f4,0xc0256776,0x66a96813,0xc687b3df, + 0x8db2eda8,0x194aab12,0xeec4febd,0xde30dc5a,0x979241b2,0xc052236a, + 0xc23d4c16,0x3ec98802 }, + { 0x4072f74d,0x0f9e760c,0xab594059,0xe78eb0de,0xc9b009c2,0xdb3dea40, + 0x38b59ae5,0x47e875f0,0x2b4daa06,0xf40eb436,0x090f3788,0x9a6a4f92, + 0xedbfaf8b,0xefebe9af,0x9867e256,0xf87f96a5,0x75ab6aeb,0x1e6fed23, + 0x3fdb13cb,0x17f2782a,0x70fa2621,0x5102c71e,0xfd4c0dbe,0x5d2b06ec, + 0x30347297,0x537cc268,0x2b67e780,0x8dbf5e2b,0xba25da32,0x2f633f3a, + 0xefaec914,0x3e9315e8 } }, + /* 126 */ + { { 0x239a9ea9,0x9255cfa5,0x0be33a62,0x20f3c690,0x9cb642bd,0x759eeb4b, + 0x00bae718,0x3316c546,0xf3410f84,0x874a76d5,0x90f129b6,0x123b502e, + 0x12851f1c,0xadc8f9a8,0x1b62408c,0xf57b764a,0x1a80777b,0x116ec01f, + 0x1f0ddc5c,0x746ecef2,0xe5a6a5a7,0x3c49d47c,0x06e955ba,0x1e15dbe7, + 0xb45d79b0,0x629c0c79,0x778d1087,0x11278308,0x8c6a22d7,0x22585dc7, + 0x0a682791,0x2ed02a0d }, + { 0x4daa2682,0x53043416,0x01359625,0x0e26d32b,0xbd867097,0x449c834a, + 0xee77ae2e,0x11a19d2b,0x3af6c169,0x39bd529a,0x5cd61054,0x36cca5c0, + 0xdc6c0fe1,0x6370a59b,0xb93d5135,0xca420d27,0x554c451a,0xd8730d45, + 0x96cdebf2,0xebd258c9,0xa50f9a05,0x0cb1b990,0x7b0f0151,0x69a8c97a, + 0x11d217e1,0x2cc36d34,0x752f75e8,0xf117688a,0xa09b2a61,0x1db01394, + 0xa9efd7dd,0x14627844 } }, + /* 127 */ + { { 0x232803cf,0x6bca3aed,0x9a96ff34,0xc1e4398b,0x74ab788b,0xcaf6757f, + 0x7e68c04d,0xc3a53e00,0x5cb7cd20,0x5f969c19,0xdc068bca,0xf28b65a6, + 0x1d863032,0xe3ca01d3,0x87808e14,0x9b733b81,0xefe618be,0xb5d704d9, + 0xb01b946d,0x276f3542,0xfbedddbf,0xe057e19e,0x903275ce,0x7d182f2b, + 0x880f7bc6,0x3cdc5f77,0x78476c14,0xd6f03d3f,0xa9ba5072,0x035f5557, + 0xb4029628,0x7acb57b6 }, + { 0x44e6b07c,0xd2413569,0xe1c7345d,0x451c4cc9,0xe273b9fb,0x407444d8, + 0xb88e34fc,0xfe496079,0xf152776d,0x77d184cf,0xc742299c,0x6d1033b9, + 0x77bf2897,0x29a0a684,0xee8f0420,0x59ffdf10,0x44bb56d6,0x4e17146c, + 0xfb9ae855,0x831d06c2,0xd93e7cd5,0xb2cb82db,0x3c96b607,0x83381c46, + 0x7549e2a8,0x06aed251,0x774a21d4,0xef97891c,0x8675fbdd,0xae9807c7, + 0x6363516c,0x6a5a05b9 } }, + /* 128 */ + { { 0x6a8f4f33,0x92e71ea6,0x4dea8f4a,0xf2fc6fc6,0xfee88461,0xd356252c, + 0x08954d08,0x59b0a83e,0x468ab766,0x5bd68c23,0x900f8d04,0x40281357, + 0x52b867ae,0x181c19c0,0x18764c41,0x986a5169,0x13575d24,0xcb01dfae, + 0x593677b7,0x17269ae5,0x46dc9b19,0xf6d17025,0xc40097c8,0x8de68499, + 0x259c407b,0x76df0032,0x17d29d8b,0x4091aad9,0x4a7ab5f6,0xa7f46d21, + 0x70ece48c,0x688054b4 }, + { 0x51a5b86c,0xf0d168aa,0x95777247,0x2437e4d8,0xf1720329,0xae844076, + 0x9647a54e,0x0a7ac87d,0x0405622c,0x1e597a4b,0xf0a79f2f,0xedefe5c6, + 0x4d55156d,0xaf3ef0c2,0xef047cf6,0x917fb04e,0x54b62137,0x3792799f, + 0x314be0b8,0x875ea32f,0x0c466b0c,0xe157c65b,0x7e218978,0xd28c90ce, + 0xcde587af,0xb90fc3ba,0x8b877bed,0xdd32d71c,0xca8e10cd,0x3b432200, + 0xd94f6e53,0x0021f419 } }, + /* 129 */ + { { 0x43519d26,0x2191122c,0x40a51845,0xbdafac1d,0x548bb89f,0xcc6f71e9, + 0x16844bf9,0x9ef3375c,0x178e8d55,0xe7789f79,0x1f8be1c5,0x04f599b6, + 0x2cbbde40,0x8088c99a,0x893206c9,0x8939a260,0xfcd30851,0xa1ae4bff, + 0xe08feafe,0x664cb3fe,0xff14aabc,0x61f38099,0x2a841ef9,0x0d8394cc, + 0x17f01db6,0x75fad8ad,0x6debb773,0x6fc34576,0xa4252512,0x1e716b05, + 0x29e1ed9f,0x79855880 }, + { 0x95106473,0xa2cb3aaa,0x5a61da04,0x95fafa41,0x539563c0,0xfd3c9362, + 0x95312b87,0xbaa48091,0xbf885c76,0x6c7e7582,0x230c78d5,0x70f6dab6, + 0x7747440d,0x8ce3051c,0xffdb6186,0x6dbebd14,0x190e4096,0xb0e041fa, + 0x6ee62e2a,0xba10c466,0x74f333d6,0x93d57e2a,0xfe7b9b66,0x006aadc4, + 0x06d2837d,0xfaf72f6c,0x910741ea,0x318cc5e6,0x65692477,0x9c502609, + 0x1d0fb08d,0x95d823c3 } }, + /* 130 */ + { { 0x140528a5,0x6aeebd86,0x53979bc8,0xf268c2ba,0x4ec144ab,0xb1bc9b8a, + 0x82a7d7ed,0x1efabb0d,0x4e0118d8,0xf12c70d1,0xa1c1558e,0x31607168, + 0xe4b7e73e,0x33e428b7,0x83aec9dd,0x63176637,0xe12ac35c,0x5172ffbe, + 0xbc17b2a4,0x37df0bfb,0x741f812a,0x4212f870,0xe2888f9c,0x3dcecbdb, + 0x756ca55d,0xa9dc15aa,0xb9028e41,0xf31918ec,0x6aeadb03,0x7ede0285, + 0x78654f54,0x0e2708d5 }, + { 0xcde20f88,0x2270cc53,0x5f5b1039,0x9338272c,0x5dcb1dbf,0x5042e19e, + 0xb72d74c1,0x4b3de219,0x2aaaaa55,0x16c49a8b,0xbba86ba6,0x008443e5, + 0x20cf1695,0xee6bcd72,0xa89abd11,0x59ffac6b,0xf115639d,0x2831217b, + 0xf34cba52,0xe4d28af2,0x0727a906,0xf27f03e7,0x69017766,0x6842c79f, + 0x7a81123e,0xcb3469bd,0xa42973b8,0x48c0f346,0x23990dbd,0xfc5784a6, + 0xfb299678,0x0d3dab3b } }, + /* 131 */ + { { 0xce29c3cc,0x8f8376e6,0xf016cbc6,0xcb0507ec,0x5e394ce1,0xdebff996, + 0x73c50d41,0x24fc526f,0x2d16ce3d,0x4edd5a54,0x91c13141,0xbb37bdd9, + 0xe33a8606,0xe3442ef2,0xc0629da8,0x2ae90337,0x592ab331,0x57faec64, + 0xd82b857b,0x1a938997,0xa3373176,0xad6c8cb9,0x9086751f,0x82595de2, + 0x18c17196,0xa81e97fb,0xbf697357,0xe4f48a13,0x5cb89f69,0xa1387c2e, + 0x5874b426,0x530b4eeb }, + { 0xbab7b5ae,0xe9f275a1,0x03a57bf4,0xbb69dc4d,0xa45c505b,0xc974dc4a, + 0x416ac402,0x726369f3,0xaed985dc,0x735e4e78,0xcdd446a1,0x0548d879, + 0x9e16b02a,0x84ceb069,0x789b11a6,0xf73f6fa4,0xb2a4e784,0x6aa0c41f, + 0x93a9b697,0xb1f76902,0xf03a8ab2,0x814cce00,0x844d66c1,0x64cb255b, + 0x30952201,0xb794e7d6,0x3da32271,0xe052d4e4,0x08b6a4d9,0x5278b2e7, + 0x80c6577f,0x90942552 } }, + /* 132 */ + { { 0x0d5b4c2f,0xd269a14d,0x5c8a649c,0x2b8fc59b,0xb0e37d4a,0x95becb3a, + 0x9111037e,0xfda1a768,0x94e35322,0x5810e05a,0xa178fafc,0xa24dcc12, + 0x8e3dce62,0x5c2c63b2,0x9452c444,0x995c3f17,0x42d45161,0x35330ec3, + 0xb4ef8129,0xa025a60a,0x8bae9c13,0x85493252,0xe2e3caf8,0x25d1a606, + 0x3649bf47,0xd44091ab,0x704ec5f1,0xc7d0afbf,0xbd8b3333,0x27bd1d62, + 0xcfe616f5,0x50570111 }, + { 0xf534356b,0xd0084ace,0x4b4b0fbc,0x9df1de05,0xcee04dc1,0x021afe05, + 0x361b78e1,0x64bde688,0xef78d38b,0xa324fcc7,0xeb0a5e4e,0xfeb372ce, + 0x65811996,0xef04fcb3,0x5eb0ab4e,0x7dce5d50,0x238c586e,0x1e29b588, + 0xbcd80037,0xde5e3197,0x4806b9cf,0x8bf5e451,0xd18e67ab,0x4330968b, + 0xf9f63fad,0x26a7d04e,0xb5c18bb4,0xa1c7f123,0x25dce22c,0x485b8482, + 0xd540e79f,0x8ff0b36f } }, + /* 133 */ + { { 0x3ff42cff,0x99f2e2f4,0x1c35317c,0xa3c19f9d,0xaba1b545,0xdb749392, + 0x4afa9a32,0x84232b05,0xd7dcd436,0x0b855d46,0x45cf9915,0x8ac35e20, + 0xf001a218,0xd7cf22c7,0xed408305,0x057d35ae,0x553ccfcd,0x25a4a519, + 0x93e2b939,0x5e565793,0x3422ec27,0xa20332b0,0x3ac53958,0x9b09005e, + 0x79e9b163,0x628051a3,0xfc6618d6,0xb4a0dc09,0x6748e7af,0x9e0e857f, + 0xc577d63e,0x71b28eee }, + { 0x99726bf8,0x4942b0cd,0x1c208f3c,0x1290a3b9,0xb0598eaa,0xfd7290e7, + 0xa25a9128,0xc6a7791f,0xc037d7da,0x2d33db24,0x70e2837b,0xc21efeb0, + 0xe3dae2a0,0xbf70d96e,0x85076027,0x43ed8191,0x4d4ad7e3,0x4aeb0aa8, + 0xe8c5b74c,0xbc75101f,0xad26ebdd,0xdbfb2a6e,0x6b78aa4e,0xba812068, + 0xe1159848,0xc94aa8f2,0x3eba5c4e,0x0d10d9db,0x6318295a,0xce7fec47, + 0x330d925a,0x7294711a } }, + /* 134 */ + { { 0x32bbd495,0xfce45904,0xbe54973f,0x330f4dd1,0x5d9c3f4e,0x006bee1d, + 0x59ba7204,0x40ee6078,0x42c2c768,0xc194fd3f,0xe9fe88be,0xa0e76b12, + 0xec2b0210,0x17cddddb,0x00811ec7,0x689d436b,0x284be9e4,0xa6a6ba37, + 0x007d4114,0xabc395b2,0x0f11e744,0xf8cdf9f3,0xe9396402,0xc5febec8, + 0xeeb46285,0x8a751743,0xc6e0d137,0x99bf8782,0xbeb292e3,0x3965e170, + 0x5801fd5f,0x001c39d8 }, + { 0xda4a0912,0xf4805cb9,0x4410bca4,0xd27cb76a,0xec71d65b,0xef3dcb8e, + 0x4816849a,0x780fbb2b,0xa8b24635,0xef6a7026,0x12c44e68,0x15625c88, + 0x4d7a74a8,0x624c232c,0x4b1631e4,0x81a77037,0xdb917c2e,0x04e4f7f1, + 0x1f61ed95,0x1d0465fd,0xcbde6e3d,0xb1048049,0xd7131fcf,0x637ce0c1, + 0x8ada4715,0x22e4dbc2,0xace99726,0xf7530c5c,0xee287450,0xa0160dcc, + 0xbb91af13,0x9132e670 } }, + /* 135 */ + { { 0x7996099d,0x8057efe2,0xa06e608c,0xb72344db,0xd0958588,0xeb4a8740, + 0x79e5aee9,0xe53daf06,0x908a2fad,0xc9560a9a,0x107e706a,0x7f4be131, + 0x2830246a,0x6d5f3d9b,0x27cca3e6,0xa5f8e8da,0x4c28f292,0xeb51dca6, + 0xf31dfd78,0x4cfa310e,0x2ca073e5,0x92e0c7c2,0xa40da683,0x102f1694, + 0x750d38fc,0x16bb07cc,0xbadae035,0x703e83e2,0xb4d3c9dd,0xea93c066, + 0x79940ed1,0x7d0b03e5 }, + { 0x4dd94c63,0x5fe7ea30,0x738b0b3a,0x57ef01c5,0xa14e6b4b,0x9534a78c, + 0xa5353276,0x07622cde,0x7c22d006,0xaf696a07,0x7d46b209,0x733c1886, + 0x626c2b4a,0x9654ccbb,0xa84f3c4c,0xa098d3a1,0x2d734b74,0x3596f9ed, + 0x5d551c90,0xdfd3021a,0x1ec5123f,0xe2ba7d2f,0xb2c1aa39,0xf9726925, + 0xf8eb2927,0xd2e75d0e,0x19192a6f,0xfaba712e,0x9b83e50e,0xa606b43a, + 0xdab5de60,0x31b1782f } }, + /* 136 */ + { { 0x4034db92,0x878dba45,0x8f34dc4d,0xa3977901,0xdf754c33,0x8d004f2e, + 0xcd563a88,0xeaa5954a,0xbb5ffad1,0xa29d6c89,0xb0d8bdb8,0xa8adf655, + 0x8cdbdb47,0xf7fb842d,0x80d3205b,0xb72e3a03,0x7cac7ca9,0xc335b0b2, + 0xd8a5475d,0xffc60bcb,0xeba4d25f,0x736f7719,0x0c50fca6,0x3d901c38, + 0x80c01900,0x1fdacf7b,0x5681f84d,0x75cf658f,0x5cefbbc1,0x57a7e634, + 0x3e07ed1f,0x6fc0fbe5 }, + { 0xb81b0e5f,0x496d116b,0x2ac853b8,0xd82dd2a5,0x327387f0,0x357e22d4, + 0xba912c59,0x3e332a84,0x49d5dcc1,0x8b71c643,0x438d85d3,0x0c982ee9, + 0xbf7fcd4e,0x90b9553c,0x38fed5e3,0x2cb39bbc,0x5ac42903,0xa2c67c9c, + 0xbf07da55,0xebf21217,0xa0b9e4ee,0x55ac05ad,0x8ee9e0c6,0x10bb12c2, + 0x48bb6e3f,0x5cf3aee5,0x8b046e91,0x4ae7269c,0xaa0e553f,0xcb266012, + 0xa94c8fc8,0x701935a1 } }, + /* 137 */ + { { 0xa4626dea,0xde58d41d,0x15b9039f,0x25ef66ca,0x3164e65b,0x99a810a4, + 0x748cfccf,0x9fe6daad,0x2f142fa9,0x7ab9a6bd,0x5d471796,0xa4cba168, + 0x6bc3a39b,0x12d30b36,0x8bf45076,0x1f46a5dc,0x1421ac0e,0xb868e529, + 0x59bba1c4,0x7a686206,0xda698b90,0x2b4b552e,0xe5453707,0x5039dcd4, + 0x9e90165f,0x42a07a9e,0xd7d45dfc,0xa838fff3,0x3b5ceb30,0x41991e5a, + 0x969ca600,0x6c961ec8 }, + { 0xc4e7eb46,0x703bdc1b,0x596c7b48,0xd6bac557,0x66afd74d,0x4f9917cd, + 0x656ce6f3,0x56355105,0x32497175,0x3d1fb50c,0x63effb2d,0xfda6783e, + 0xeefaa2bd,0xbd79f1f3,0x17af9ef7,0xa4efbe54,0x5a55b7a4,0x6cef6462, + 0x1a713304,0x116f3238,0xb95625a3,0xdb2a2a7f,0x0b027e96,0x6a0aa43a, + 0x4832b3bc,0x458fe5d2,0x5adfaac0,0x523418df,0xc49e7f9a,0xc05a89cb, + 0x69e24b53,0x830883d8 } }, + /* 138 */ + { { 0x02557389,0x959b1c62,0xadefc0bc,0x5fe5ce97,0x8330f383,0x893bbe7f, + 0x16cfb81e,0x27e0c6af,0xd04428fd,0x6f64e65b,0xb79e6182,0x53de9245, + 0x487e11ca,0x08a313c1,0x445bce93,0x65cec3b9,0xd67ed49e,0x33bc0314, + 0x30782352,0x69f36b24,0x93ad31d2,0xd78e5daf,0xc780890c,0xf2682b70, + 0x9e45efe9,0x7015c34f,0xe6cbafea,0x135d4ba4,0x7e3fcc6c,0x43a378a4, + 0x96638f8c,0x2376f97f }, + { 0xae575b99,0x0a6e1ec0,0x81b970dc,0x7e14cb4f,0xd3a73947,0xf00a3824, + 0xfb235a9d,0x0b4b9c81,0x5bf62944,0x8d15115f,0x1e165d7a,0xcfd35b43, + 0xb2ee3e3b,0x5d12fea2,0xf5182e7b,0x629984a6,0xc365d08e,0x4e43e2f3, + 0x30f36e72,0x99327091,0xfd345401,0x698b4a00,0xbaf96dce,0x23c4fd0e, + 0x23675554,0xa60ba0ae,0xb0325784,0x51bdac2d,0x215464a1,0x8ab4190a, + 0x6bf10296,0x8c461661 } }, + /* 139 */ + { { 0x2d1f36a5,0xeffca258,0x894c5f2d,0x0eded2b2,0x43ced84f,0x35a5cdb8, + 0xdb0e3b9b,0x290f8982,0x0719a112,0xcce0eaf0,0x39a362d6,0xd0e657e4, + 0x62697e47,0x5516a55d,0x8e636514,0x269e1f77,0xd50269bc,0x5e3dedcb, + 0x441c57c5,0xecec2300,0xc705578d,0xdb83f31c,0x1e489eab,0x1bdefb73, + 0x395fcdb4,0x20b678cf,0xff9db001,0x908cf91c,0x55f52cc8,0xcbebc6f4, + 0xb4c61162,0x155ea622 }, + { 0x876fa42e,0x94be2f1f,0x7fadeee7,0xab5e8749,0x38c865af,0x692e70f5, + 0xdf8059b0,0x16e99b84,0x8b5a7ac9,0x0ceb606e,0x2d463d2b,0xced23357, + 0x2a9a09a0,0x2d0f2623,0x3861fbdf,0x2529998c,0xc1be310b,0x711888a7, + 0x0d8aade3,0x9b1229c5,0x3b13533d,0xdbcf9b78,0xff029708,0x3ca746f8, + 0xda83ef88,0xa5a013a1,0x4ab28444,0x8e904d18,0xbcbd4aba,0x2fe84b3d, + 0x259058c3,0x8f570f24 } }, + /* 140 */ + { { 0x2ca9c508,0xdeb66c8a,0x69d6b780,0x2dc5bec2,0x88ead600,0x16d61266, + 0x49d72614,0x61841b97,0xce472e6f,0x41e40e6c,0x1fa7a876,0xada24264, + 0xcc3997a0,0x45b9fd33,0x7c15dcf4,0xb25e8fa9,0x12e9629d,0x0124ceb2, + 0x7db3d956,0x3a8c72c6,0x7c1a7844,0x8e2ded2b,0x6dd027ff,0x94ab09c6, + 0x7e7a2bc6,0xf89a057d,0xcf70c763,0xad8bf226,0xc8a26212,0x4cb268e7, + 0xb2c44c1d,0x3d171e87 }, + { 0x8ce49820,0x382ac16e,0xc0c44dc9,0x24ee45e2,0x73e858c4,0x0ec67912, + 0x46327cf9,0x918cb25c,0xc6159c1f,0x43e3876b,0x37545cb3,0xb6b6e0e0, + 0x5d12347e,0x64b839ab,0xa300d541,0x72e09274,0x881c1169,0x26ab28e6, + 0xeb75a843,0x4a580fff,0x359120df,0x0a5802ca,0x3209f4a3,0x7fee82d0, + 0x8e6a9380,0xb518016b,0xc2ee11ca,0xb99c6c70,0xab9d4ec7,0x16105af1, + 0x34cd9004,0x234e98f8 } }, + /* 141 */ + { { 0x14db9cda,0xff435208,0x96adec90,0x99cfdc47,0xaf458b6d,0x843aaa6f, + 0x743eaa31,0x3f1f7415,0x61735d81,0x915e192e,0x0ac595d5,0x3441a22d, + 0xc044bc8d,0x704bbf67,0xbe23a236,0x2f960471,0x15d1d557,0xcc326388, + 0x76b1dd94,0x9410230b,0x0c1c8a67,0xf2e5439f,0x833c910d,0x56b141ac, + 0x865b84df,0x467c999f,0x21f02b7b,0x1b0251fa,0x96216950,0xde5b5260, + 0xce3a1e93,0x6a2130e3 }, + { 0x4b3ca1a7,0xd21b67a0,0x00c0ce80,0xaf42ed53,0x932cf07a,0x22ccd368, + 0x5c25c35a,0x36523a81,0x8dd04d06,0xecdd3958,0xb2f93a3b,0x73da3502, + 0xd5e5b530,0x4c5e0c3c,0x13268777,0xef9f5486,0x1e742292,0xed87fefc, + 0xa24e5ede,0x6d9ac29e,0x33849f1a,0x08abc9f0,0x40f23905,0xb09b2292, + 0x7f934353,0x6791072c,0xe6aeb550,0x102a6381,0x96feb870,0x3ee07409, + 0x9c4d2830,0x34f06faa } }, + /* 142 */ + { { 0x2348f005,0x869dc79f,0xdf4920b1,0x9b5c5d71,0x6dee64a4,0xfd1b57ca, + 0xe82a4fb4,0x21b7f734,0xb9578366,0x637cb834,0x7d287d96,0xc934101b, + 0x0392ecab,0x1590f8ac,0x7f75f4e3,0x280dc373,0x6a61ac62,0x8b36f50f, + 0xa65568da,0x74f58304,0xd930870a,0x80d792a9,0xfc8895cc,0x6d17b192, + 0x4914939f,0x498392fa,0xd41d5b9e,0xaf36027d,0x5caa82b5,0x452d79e2, + 0xf4115d1a,0x764d47b1 }, + { 0xa2ee8b9c,0x5df22303,0x85dfcd48,0x1b9f72d3,0x10813a37,0x6b42b983, + 0x3de741f5,0xe28c523b,0xf303bb5b,0x0857625a,0xac9bf9af,0x926f299a, + 0x0d445b34,0x21beac08,0xd6ba2c0e,0x6a523a02,0x7fce2864,0xe302a1b1, + 0xe300c1ea,0x4516a235,0x7b4a9311,0x4543736a,0xc0cc89f7,0xd3c0b9e8, + 0x40ed88de,0x0481904f,0x3cb7fc70,0x4f269b56,0x321b9738,0x09a1d53a, + 0x230a3810,0x1c0dd9c3 } }, + /* 143 */ + { { 0xc46a7d9a,0xffaa1f67,0xbedf91cc,0x64743334,0x47a42f2e,0x45833a74, + 0x241ffaa9,0x67980051,0x335efe6b,0x70979a84,0xf08b2403,0x5f0613f5, + 0x64f211dc,0x6bb22fcd,0xa0572cfc,0xe1b8b2a3,0x7950a14a,0x19e0eb41, + 0x3eb6cd4c,0xe634bb29,0x470a25ff,0x31a04b25,0xa3d15a0a,0xa41f7ac9, + 0xbf2fede9,0xefed85ec,0x81b94a00,0x1f581f5f,0x9ef4a15c,0xaa3996b0, + 0xb06041bc,0x52d8be39 }, + { 0xfd631a2f,0xbd1536f6,0xb351a8dc,0x91fae7f0,0x9b126212,0xd1a590c7, + 0x2bd0f435,0x52d4875f,0x92b0ea70,0x9aedb6d3,0xb83ab89e,0x0bd0abdc, + 0x89fe192c,0x827a1062,0x102a0bda,0x6566a960,0xce036814,0xda083037, + 0x58639405,0x30bed79f,0xdbca8df9,0x972019b6,0xefdaa3f5,0x89201286, + 0x5236b892,0xb337b996,0x28fc2e73,0x11d3e38e,0x880e8da3,0x70787f41, + 0xdae4a45d,0x6cff6367 } }, + /* 144 */ + { { 0xf89a8bb4,0xbd3d0433,0x93b98f71,0x42144c33,0x03470a2d,0x82b616c8, + 0xe5da089e,0x98fcc757,0x7bf5fda6,0x542354ef,0x9ebd34cc,0x1885c253, + 0xbec5dd0d,0x2e20b285,0x782a1bca,0xe71bbbe1,0x9b854ef0,0x959ded30, + 0x8997fa6a,0x17249979,0xd81f3c45,0x50cf8fa8,0x60c11152,0xa9a3b517, + 0xecf845ea,0xc9b0ef7d,0xb9fed11b,0xc9339e23,0x28256080,0xc93e9c5c, + 0x613ec1e7,0x1d2c8217 }, + { 0x987cfc93,0x7381347d,0xf187f810,0x047603bb,0x1250ca31,0x3fa6bc9d, + 0xbb055bf3,0x480091e0,0x3a3af87c,0xbdf95f1a,0x140540ab,0xe2687770, + 0xd7fe045b,0x998df730,0xb723bc2d,0xb398135f,0x15ebec46,0xac230f8c, + 0x5f5561c0,0xe08e1830,0xda60a47f,0x7c0fbf4c,0xe16d4bfc,0x06e95c24, + 0x74617e92,0x74163495,0x4ae0c20e,0x39719869,0x2131e2b6,0xfe269312, + 0x0a537722,0x25486e36 } }, + /* 145 */ + { { 0x53572806,0x618795ca,0x656968e1,0xb2c89449,0x3fb323ae,0x149c2c97, + 0x409bc7d6,0xfb15de26,0xc79121b3,0xa90cda72,0x204cabbb,0x6d2fa14e, + 0x91604125,0xcbcda6f7,0xb435f947,0x25086261,0xc282eb10,0xdb686c38, + 0xf1a791cb,0x51016d62,0x61a2266c,0x6b1c7ed1,0x271d74a6,0x26780666, + 0x824287a4,0xb5ffeda1,0xbbe4f0f3,0xcbe503ff,0xb9482a74,0xd7f7f0be, + 0x088493f1,0x751b2358 }, + { 0xe9c9be68,0xd597b9d6,0x67d10c6c,0x1794b5c4,0x7762b2f4,0xa88cdc3d, + 0xa1b44e11,0x6d94a63a,0xaaa8eca8,0xfb0bbbb9,0xc963d87f,0xf4b0f2d0, + 0x5dc7075d,0xb753062c,0x49933989,0xfed726ac,0x57f9ccde,0x5da60638, + 0x75f8c766,0x221c392a,0x5dc672ca,0xcd264d95,0xb66ecc8d,0x7004ff22, + 0x18a458ba,0xfb1aa9ae,0x8babd653,0xea9644df,0x2ba0de7c,0xa9378e80, + 0xca2c6c75,0x144cc12d } }, + /* 146 */ + { { 0x2989aa3a,0x593a0a1d,0x59e6e64d,0xd83f2283,0xd32e732e,0xe938b0cb, + 0x3c3cb249,0xf4c464c5,0xf89ea6ac,0x9750a5f8,0x346cfc32,0x467e5bbf, + 0x37b2b809,0xc9bfab9d,0x3b339c6d,0xf8eb7453,0x3b766dee,0x3fe01fbe, + 0xef6aea27,0xb3154254,0x7be61b10,0x555c3df2,0xdd818488,0x70fb6d81, + 0xbbe714f9,0xda1af3a4,0x9d18f693,0x575f2017,0x2465b839,0xdc08fc6b, + 0x6b84a951,0x874ecf33 }, + { 0xbbb3f6be,0x624af83e,0x08bb423d,0xf578fbb9,0xd7873527,0x5623b0ba, + 0xa62e0442,0xc3659bd8,0xfe236f79,0x2903b167,0xe53f26a6,0x55a430c6, + 0x3ad712cf,0x222547ae,0x76eb272b,0xb73890d7,0x3d628df9,0x95b4f70b, + 0x53eae4ac,0x9f0e13b0,0xe7f2174e,0x5b4f5138,0x98dbae17,0x75482cf9, + 0x44518480,0x2b69bbde,0xcafef15c,0x4f279652,0xb6bcaf19,0xa0a3ef2b, + 0xce4c634f,0x31fb8581 } }, + /* 147 */ + { { 0x615cd607,0x398306d1,0xaa32c3a6,0x680c9faa,0x7779131d,0xe87a705b, + 0x36708b00,0x1031013a,0x9445297f,0x814fa0e1,0xa6a79b56,0x70c5583a, + 0x4b16bed4,0x03039cbf,0xaaaaf8d3,0x18a7ca8d,0x5cdb68a5,0xf33159e7, + 0xd23814fa,0xdea0e738,0x8d0f4f9f,0xeb352718,0xdcdff032,0xb0b76609, + 0x3d48338b,0x65ba8ea9,0x55dd507a,0x18044d82,0x4a4a50b4,0x844a223e, + 0x18e19e54,0x98323000 }, + { 0x57f3d5a6,0x28a21027,0x6e8cadcd,0xffce5648,0x02551f3b,0x9590381b, + 0x935ebdf1,0xb26cc64f,0xc083aa6e,0x60611291,0x88e4cf41,0xcd988a66, + 0xdd53b1b5,0x581c3f73,0x77fc621d,0x78c804a9,0xfadca2fa,0x31874330, + 0xc83ccf02,0xf7008da4,0xa79a4707,0xc4122a1d,0x4a915eb5,0x9a8e0d3f, + 0xd0123660,0xa2de157d,0x65ead2a0,0x45ef43b2,0x188db285,0xd0a22ade, + 0x922e0caa,0x8abbe39e } }, + /* 148 */ + { { 0x3a2d2f01,0xb4446905,0x5dc6685c,0xd27c3193,0x1d74a027,0x6a908bbf, + 0x5b50ec1d,0x01da350f,0x3f3c2e26,0x1d3dd45e,0xb836ee92,0xf66e11d0, + 0x474b979c,0x7e03908f,0x98b87834,0x19e7c5b9,0xbd3d1de9,0xa741d3fe, + 0x1ef6059b,0x63c68e8d,0x3674e247,0x9b9ff939,0x3e7e67f6,0x1d7d53e7, + 0xaee9e248,0x698dc326,0xb3bd984c,0x52f23eda,0x6f8fe8a7,0xf95e31b0, + 0xc3d0ba95,0x0f15b4d0 }, + { 0x790a8d85,0x8f2f6635,0xe2595af1,0x51bffbae,0x24b51287,0xd15b7ec6, + 0x3234715d,0x7639b6ab,0x2bc5441d,0x0cdd5299,0xf6d05833,0x54800ea4, + 0xf6d6e360,0x21efd752,0x19290613,0xc0b7ffe5,0xeea898cd,0xb68a5825, + 0x22982266,0xecedba92,0xbbd06bb2,0x678a91b0,0x4bb6b0cb,0xb2436dc0, + 0xcaf8ea98,0xcf7a99e7,0x71aa05bb,0xb92d0e6e,0xf5993eb1,0xbf8d0471, + 0x20385ddb,0x515db378 } }, + /* 149 */ + { { 0x6f5bef22,0xee43eaaa,0x20348712,0x952d2698,0x7a3af6c6,0x1e4c484e, + 0x9a8c9403,0x18d434c6,0x5001899a,0x63e5d741,0xfe8ea40c,0x5238dbbc, + 0x96798721,0xca6cc8d2,0x04acbde8,0x73db6aee,0xb7f993ce,0xbf69328d, + 0xad45e334,0xa3f79bbf,0x7c1f1630,0x8c51ec93,0x9b00a6de,0x4907325f, + 0x12d82bc3,0x49e6acb4,0x0ec59fc9,0x5901b36d,0x9cf34e3b,0xcb09b710, + 0x1abf4c02,0x2de0487e }, + { 0x8dd9d484,0x18b722f3,0x7c77bacc,0x83349393,0x93d92b8a,0x58dbb8f1, + 0x8e3fac25,0x80d78d50,0x745f4a7d,0xf0500981,0x877cc29d,0xd072bfed, + 0xc30a89f8,0x67abf8f2,0x9a0820d7,0x92c567ea,0x8a3a5738,0x425ab12e, + 0xf055521b,0xc162faeb,0xb94ea5e9,0xee1c4f26,0x3d71e546,0x1e414994, + 0x43e8be1d,0x258183b8,0xef9eae0b,0x44917c82,0x73874a30,0x6813a457, + 0xcc42f86e,0x6f6ac071 } }, + /* 150 */ + { { 0x4dd6e3b1,0xd38822ad,0xad620869,0xfc78e1cc,0x2cacde80,0xe7843845, + 0xa8469fe3,0x121cc14a,0xe67e8ef2,0x8e8f3da7,0x4d347448,0xdb83d16e, + 0x798631f4,0x3ba1dd98,0x0a4c4c17,0xdfab5977,0x3edc701f,0x1f0a1306, + 0x6cd8ff28,0x4649d601,0xbcc55bc9,0x2267230b,0x5760412a,0x02a19c60, + 0x328faef6,0xc719d5f1,0xf67eaad9,0x27cb969e,0x719bafb5,0xf342530e, + 0xff5a82cb,0x6e2c24cc }, + { 0xadaf8793,0x6313024b,0x035c948e,0x944bccf1,0x953500bf,0xe9a066b7, + 0x1d116765,0x7991a946,0x9fd93c78,0x95addb2e,0xe92e5495,0x05d2c037, + 0x9f03e5cf,0xcb145b18,0x95aa1f72,0x81ae48ca,0x135a6e4f,0x203f2702, + 0x49b2a7d5,0x2bcef5a2,0x02d7f2a3,0x0687a900,0x6c6745b0,0x2f7d3228, + 0x86507305,0x3da8a875,0x2e8dc58f,0xbe38b884,0xdbf11185,0x6b48bf34, + 0x97c08f91,0x5af7fd0d } }, + /* 151 */ + { { 0xf4a224a5,0x55f9b950,0xcc50273a,0x41904574,0x643f1fd5,0x34f81330, + 0x0e50f783,0x996801bb,0x89581712,0x866d7403,0xa4091d36,0xdb9a405d, + 0x16a46fe7,0xf1e379df,0x83bf9168,0x8d04a93f,0x32b20bca,0xae4c8335, + 0xf72a1c10,0x99d334b1,0xd8195db4,0x8fbc9977,0xfba14b5d,0xcaeb3dff, + 0x76daf476,0x60fef022,0xdb5b72f4,0x4b948dfe,0xb6dfb062,0x5185c925, + 0x9609d4ae,0x27a9c381 }, + { 0xf12a93af,0x73c37346,0x5536634d,0x028b707c,0x498193d1,0x8efa58d5, + 0xef21b69d,0x4f83a5cc,0xa788a0e2,0x05cbb0a3,0x65b13c98,0x01031781, + 0x2b73784c,0xfea20e58,0xe50361f2,0xdf9713a0,0xd0cc22d9,0x31449a0f, + 0x7c5e2e1b,0x183752e7,0xb67044cf,0x6e44d6bd,0x733e177a,0x012dde95, + 0x08ee2c23,0x68b49669,0x1f5f1949,0xd9bb0541,0x6acd886f,0x95182c71, + 0xfbde9244,0x1c690694 } }, + /* 152 */ + { { 0x3a880026,0x5db67d17,0x125d95f2,0x89c4f0a0,0x3f6cb7a4,0x29050551, + 0x5cbbdca5,0x3eb231d1,0x972bcbd3,0xf8cffc99,0xad55a03a,0xcb4ef4d4, + 0x22867c2f,0x944d47ca,0x0ead1aa5,0x96d88548,0xcbc8b045,0x76a57cf8, + 0x005e55a0,0xdfe5844b,0x1d18a097,0x5e9e7e19,0x52923c74,0x957a26e8, + 0x7f5db339,0xd0867b79,0x63bed0c8,0x2553408e,0x689ad23c,0x1596e5d5, + 0xa504c339,0x7b8c13d6 }, + { 0x52fb6901,0x2fc43aad,0x16ca253b,0x1c0313f9,0x515aadc6,0x1475830a, + 0x7f577dc2,0xc93d1926,0xf723c0dd,0x26e52e8e,0x3eb9f6da,0x2f1e0eb8, + 0xf180376d,0x9979de82,0xb0834939,0x43e28ecb,0xa39c38e7,0x9a2d51dc, + 0xa8e3f6b5,0x6e6063a9,0x4b9b3270,0x4cf1da3a,0xd2f8915d,0x6e5348a2, + 0x50507912,0x5e75e3e0,0x20d383fa,0xaeffce57,0x8fd2fb29,0x1d6d53cc, + 0x696f4cd0,0x0e3c3ef6 } }, + /* 153 */ + { { 0x21ee1d83,0x3bc337c1,0x787b7788,0x97e08f6d,0x138fa4ce,0xbf709fcc, + 0xa0348e58,0xbaf77647,0xa55e672d,0x04f8babc,0x7d5ec5dd,0x0ed2919d, + 0x33e99218,0x8ce64bff,0x24b059af,0xac09fc57,0xdc5e32ba,0x506831f9, + 0x465af6a9,0x26a22677,0xc97f1ff8,0x3c5efe66,0xbc6087fd,0x1515e0d6, + 0xaa8edc6b,0xb1a39c5e,0x0e79ed29,0x3dd816bb,0xbc3788b8,0x6cc13769, + 0xc092a51c,0x463098e3 }, + { 0xc8bd0fa7,0x3a6408c7,0xce6bde49,0xd1764311,0x283ef7be,0xe315e108, + 0x99b5d938,0x8213cc77,0x45a49a6b,0xaf7f1581,0xe529e4d1,0xd00fdb0f, + 0xce66c9d6,0x55d38f77,0x1bd4b952,0xb4f7ccc0,0xaf71f986,0x8d975b49, + 0xcd64d00a,0x12b59fcb,0xa5a3bad7,0x1860e504,0x2b5c89f1,0x6d976044, + 0x7a3e231f,0xfed0c659,0x178cba92,0x58114c33,0x6698e11e,0xe2e74c06, + 0xa348b85a,0x7f8fd093 } }, + /* 154 */ + { { 0xc19428af,0xf24592ca,0x3a308665,0x192a1c81,0xe30bbd7f,0x42589812, + 0x836c6bb9,0x10db0723,0x598e4987,0x9c7a41e9,0x6ead6f4b,0x8aff179e, + 0x75862c44,0x70f8f9b9,0x6f21983e,0x6b3b0237,0x98e65152,0x25d83e9b, + 0xd751218a,0x3b2d26a8,0x9d6f1da6,0x9508281a,0xa5a81f74,0x8df78d05, + 0xe4687471,0xd79ee559,0x6787d8cc,0x2060ca57,0xa8476c95,0x427a84ff, + 0xe6435131,0x87b64c51 }, + { 0x4b30d3c4,0x87f46f65,0x23b4ef14,0xcdec4c5c,0x63ca4d68,0xb3b74766, + 0xcf3fb56d,0x1df34269,0x0fd7d46a,0xd4f139c4,0x6a69a8bd,0xa3b7c7c7, + 0xcbadd7d2,0xee56b4c9,0xac942334,0xb28ff342,0x786f1da3,0x0046fdfa, + 0xb700c82e,0xce5d149c,0x50966597,0xca30ef81,0xfcff4bdd,0x44a20609, + 0x44925268,0x0f2f65e7,0xd4021f38,0xe5b6552c,0x042dbbd0,0x77ea9c2a, + 0xd9c062f5,0x8c95267c } }, + /* 155 */ + { { 0x5fc1abb1,0x6655032e,0x12fe4743,0x2215af54,0x29f05ef5,0xfd657560, + 0xdc191be9,0xb0e73325,0xc08639b0,0x7ab3c65e,0x1c3e6673,0x67507f51, + 0xc8615555,0x638befc3,0x42f0c4ad,0x5d0188cf,0xd896186d,0x843a301c, + 0xb2c6741e,0x045603f7,0xfa3cd1d0,0xf7545c0c,0x4a40672e,0xf612affd, + 0x45b9e8dd,0x56197c9f,0x87922d74,0xb453237d,0x4b2d59bf,0xbf132e3a, + 0xb84a6a16,0x8afa1b73 }, + { 0xe793ac70,0x6b3596ea,0xeef6dd10,0x4c94ef8e,0x70422e40,0x926b4fa2, + 0xe9e5d763,0xc8c71dce,0xf512aadf,0x352fcb70,0xa883975f,0x1b7ba138, + 0x058c3b13,0x57991390,0x97740fd1,0x9692092a,0x160b0697,0x19ad945b, + 0x10837ab2,0xbc634388,0xf174bb71,0x76ee11c4,0xab1b80eb,0x6111bfc1, + 0x70ec458a,0xbc82bac8,0x312d3325,0xeee60127,0xb240adc8,0xb4118b1a, + 0x2b5a093c,0x67211191 } }, + /* 156 */ + { { 0xf55cf9bf,0x91e99306,0xa46b96d9,0x9b045308,0x9e7a65df,0xae3c1e1d, + 0xc731bcbb,0x453cb151,0xa4d58a61,0x14be5227,0x97c74cc2,0x39dac922, + 0x822e00d6,0x4d0f7a45,0xc62b03df,0xafeb1d51,0xbaa18b2d,0xbb1dc3a4, + 0xdf2b74f0,0x7f3c7178,0x896b6a33,0xfcd328a6,0x1dce055f,0xe95ed454, + 0x6a4e2b87,0x97fbc76b,0xfa59dce9,0xe5ec67f1,0xcc0367c1,0x052368ac, + 0x54e4a3fe,0x7c863916 }, + { 0xca7388cf,0x55e94b5e,0xc0335d38,0x17cc0a60,0x616f85ba,0x9b69b78b, + 0x10122980,0x705d02ef,0x1cfd0a79,0x565a6e80,0x7d1ee352,0xeb74a96d, + 0x427b9dad,0x5c8832ed,0xe6d5330f,0x96ea8528,0x18d24ee8,0x30d8862b, + 0x9ff939f7,0x9cd38ed5,0x01060252,0x690fc9a2,0x2303b3ff,0xc62d88b8, + 0xdd52b469,0xfc42d7a4,0x8cad2d93,0x06f8dfa2,0x60920438,0x50236090, + 0xfce855ad,0x32582758 } }, + /* 157 */ + { { 0x359e8c60,0xeb20e45f,0x364ca186,0xc71bb8a5,0xdff8e110,0x02b15071, + 0x4c93e578,0x074e91d3,0xb829d0d8,0xc0326e00,0x626a83fa,0x3c192258, + 0xfb29a09e,0x387a64d5,0xe5ac5c82,0xcaaa3d34,0xada2da29,0x8ed685e5, + 0xeb29650e,0x92720267,0x763802f3,0xf7184b19,0xdf6b1aea,0x23f5dd0e, + 0x25e6125d,0xbe1fa347,0x0c872a1a,0xd6287f9d,0xac57c3af,0x49aa93d2, + 0x5bda7656,0x1a4e6a71 }, + { 0x554d1267,0x1a126ede,0x1cd02b48,0x37f94533,0xce31fb1d,0xd70af04c, + 0x097dc012,0xcf410b0b,0x36c7b6c5,0x930e1d17,0xc6891085,0x902fee41, + 0x79fb638f,0x349ba4a7,0xacd6f8df,0xa16c5821,0x2e076ace,0xfb3b83c1, + 0xe501d14d,0x6b8d033b,0x20f2d2da,0x0593d452,0x99df1880,0x3752526d, + 0x9feb33a6,0xca32351c,0x1f6ef456,0xd91343bc,0x35b9dc8a,0xc74857db, + 0x85b4e832,0x856a7c93 } }, + /* 158 */ + { { 0x0d0a5583,0xa007d002,0xeda4658a,0x2f1301dd,0x34d939be,0x91c07964, + 0xa70c0836,0xa0cb6780,0xbe81e540,0xc0b4df95,0x5d4ac8b8,0x6cbbcd34, + 0x54756239,0x57c52ed0,0x1805ceb6,0xcac2dca4,0x79344255,0x915ee6ab, + 0x24c9a2a6,0x366def31,0x8c12c674,0xbd3b962f,0x7dbb7c3b,0xaab64f1b, + 0xe22bb95b,0x3c0e4553,0xc4c63b74,0x2408feba,0x2a4da631,0x3ca77312, + 0xc636da40,0x62889084 }, + { 0x8cb8d208,0xa457fd53,0x543f06d4,0x7a8f8009,0xf2eff2ab,0xb66de154, + 0xf72517e7,0xfddb28eb,0xf9389d2c,0x0149fe66,0xd85b88ce,0x79e8773f, + 0x0ba543f7,0x452e090b,0xb0b03fc0,0xdeb9b5cf,0x6c5ed77b,0x3113448a, + 0x8ffc0372,0x3609f3cf,0x5c1b4c4a,0x2bc9c46d,0x8fa59be9,0xe66f3bf3, + 0xcdb02691,0x1396bf5f,0x009f88f9,0xf1ec59d4,0x2ad9dfe3,0xc2903456, + 0x5ada4d58,0x79d8122c } }, + /* 159 */ + { { 0xaa529507,0x14d4e4ce,0x74655d00,0x056a0814,0x4f0fc474,0xc0d30a38, + 0x3443cb8e,0x8a8203ea,0x97f1728d,0x33c62fb0,0xb520ef52,0x8a38dcfd, + 0x7cac9d3e,0xa0f90d5d,0x873cea50,0x28a7b0bf,0x6c6c41cb,0xd115ae3a, + 0xa13812c1,0xa35171da,0x624d507e,0x25d4bba5,0x7e98f42f,0x91dad289, + 0x96a41371,0xffd6b1e9,0xb69e5b77,0xd46c2125,0x20c4f707,0xc7d2b424, + 0x8142557a,0x2ab3af95 }, + { 0x6a5372a6,0x86ca074c,0x56292ba7,0x728fb83e,0x77741cf5,0x745596dc, + 0x520ef49d,0x70b4cea1,0x61e46472,0x1472fe34,0x3fb8ac5d,0xf4d6bd66, + 0xc10bc071,0x46e52cc9,0x371a3461,0x28794efe,0x276fe877,0xa4850718, + 0x9bef5ab4,0xedad5773,0x3f15c815,0x24c2d9ff,0x8f8395c3,0x188950e5, + 0x80b6a855,0xbae40996,0x8a8803e1,0x4f53e22c,0x039d25ee,0xaf233f61, + 0x250409ca,0x07db2c35 } }, + /* 160 */ + { { 0x037d4703,0xc7f3b8db,0xc5f488b9,0xe83708df,0x8471d402,0x1fba830f, + 0x5a2faae9,0xa55ee8d2,0x5404fc1e,0xc2e5bf10,0xaa2d5651,0x647d5027, + 0x7ebaf5f9,0x37a53c0c,0x95b30abf,0x7adf0bb2,0xd64c93ba,0x5a62e1fe, + 0xe2ef4a78,0x7ffc18c0,0x4d2cd04f,0x139dd9d9,0x5ea0af02,0x253fbab7, + 0x0fef9acf,0x7c8100ea,0xc8615aa7,0x74c5384d,0x9fe52069,0xcb28682d, + 0xcf7dd759,0x08b6ca8f }, + { 0x036c3b5a,0xe04e5bea,0x7f9f2b4b,0x38726102,0x29797c0f,0xa9fca570, + 0x82879ea3,0x1656180b,0x607f0ddf,0x153389bb,0x67b0e087,0x99a1223c, + 0x9d897fc7,0x0d1808ec,0x916edf19,0x9470711a,0x07217118,0xf8f52f2b, + 0xd18888b6,0x5d8b29ff,0x4cc6f900,0xef1e22c5,0xeb24877f,0xc4036165, + 0x35479525,0xfda95233,0x6861468a,0xd622a421,0x74faba08,0x5d043b07, + 0x0d31a7d2,0x2c337b02 } }, + /* 161 */ + { { 0xea22fa65,0x7b2305bc,0xd159f63a,0xbe183ef4,0x3f35923f,0x3473d87d, + 0xc11d7753,0xb27fb306,0x2a054cff,0x702e7e6b,0xaf185619,0x3ce9f97c, + 0x4e7d51c5,0x83550243,0xf356ac5b,0xa63e3d82,0xd7645131,0x867b7caa, + 0xa671fc9d,0xee85e6af,0x2b07cd77,0x3b985ede,0xffda5193,0x07d598b0, + 0xa942dc36,0xb10eca39,0x506218a9,0x17f3dcee,0x06b7d5ca,0x3d94e8d1, + 0xed8831c9,0x509b2634 }, + { 0x48caed54,0xb1b9414e,0xcbf51e97,0x77a78c6c,0x4de9b258,0xa4688c8d, + 0x91ee3d78,0x0024137c,0xe30ee64c,0xa68f9234,0x88190d78,0x573255bc, + 0xba80690b,0x41e8e05f,0xec354f4c,0x50038d84,0xdfa52816,0xb18f02d6, + 0xccb63fda,0xc47f9007,0xe98ae455,0x29d480fb,0x5d0e319d,0x4ac45d22, + 0x026db719,0xd06f3575,0x2c3587b9,0x733b9e20,0x2c317727,0x22483992, + 0x54bb8752,0x1592d5a7 } }, + /* 162 */ + { { 0xcf7453f0,0x5778d9a2,0xed83c1f0,0xaffb899a,0xe0a82ba7,0xae6506d3, + 0xea3d5081,0x32c84e1a,0x810aa38b,0x9ad528c0,0xbd37d041,0xb1fdb020, + 0xd06ce41f,0x78d6cbe1,0x2e74b7f6,0xd287f0f0,0xc43bb022,0xf5cd2575, + 0xf81a71b3,0x6d28f2f3,0xc633e7f4,0xe65bb1f5,0xc4fc580e,0x32e5fc1c, + 0xbb7b07a5,0xcd55539f,0xc3caaf3a,0xb5a94471,0x4cc22d2d,0xb958bdf4, + 0x77a2777c,0x1614bdbd }, + { 0xed0ab04d,0x4c1f0230,0x6e2082ea,0xae347b00,0xc42c5b5f,0x9f10bc63, + 0xde019935,0xb0539e6f,0x65dd0825,0xd89bd4e7,0xbbceda16,0x92260fef, + 0xe62aca32,0x8aaa755c,0x5ec82c5f,0xed762fa9,0x18650768,0x99e64c01, + 0xc92e348c,0x57dd6245,0x31ea6d68,0x0db88a77,0x07b44736,0xef0012ab, + 0x171d70fe,0xb9356b94,0x03f891b0,0xe68b0628,0xb79c20a2,0x3a54a53a, + 0xb00b0728,0x489656c7 } }, + /* 163 */ + { { 0x71353c25,0xe43649ba,0x13f67e24,0x517f27a1,0x1c1eb9e3,0x10bd333a, + 0x78e29bf9,0x94e1c05c,0x4743f15d,0x84fe7d97,0x90da2df0,0x9c874908, + 0x53673be1,0x82403fa7,0x1baea1b1,0x7ebf5db4,0x24180ead,0xcfe0ae35, + 0xc2f50c3f,0x1d15873f,0x70661cd9,0x16851ad6,0xa51e8c2c,0x802968d9, + 0xe0161099,0xe7d1a9cd,0xa8a7ea56,0x2b153c89,0x06e3c498,0x6d41b789, + 0xd6769dcb,0x082bb2e9 }, + { 0xc4d6615f,0x6180ef46,0x01b9829c,0xfc629dc1,0x0fb264ca,0xde222ec0, + 0x10ecc2c4,0xc5457e06,0x1eea2c4d,0x95ce599f,0x8f9c5b2c,0x0433fa72, + 0xcd6310f9,0xee035462,0xce2e2253,0x84c57c3b,0x96d87e44,0x6c8ec31a, + 0xa452c5a7,0x30bfe393,0xa047b235,0xc592b140,0xc018545e,0x7bd8be18, + 0x5c178c46,0x794e0107,0x2e23005b,0x48471946,0x622a54f3,0x2665e237, + 0x901c9042,0x36451a46 } }, + /* 164 */ + { { 0x19893e71,0x17802d18,0x539a2082,0xa1765d8b,0x2302ecfc,0xfc6aea01, + 0x365bf59d,0x8d4cf51b,0x0d232a80,0x87741d72,0x18e80427,0xac343eb3, + 0xe74739ec,0x553ecb2f,0x1a8b07ca,0xaeca79a8,0x56f4ab3a,0x089ff322, + 0x3fa1d1f7,0x5e95d729,0xf62a9a16,0x260569ae,0xaa08ddc2,0x5e776232, + 0x1b7bb54a,0x93fabec3,0x743d56e7,0x48a20956,0xeb0ebeff,0x749cdb12, + 0x69b8fcf1,0x705307a4 }, + { 0xe488310b,0x7a8e4c04,0x5325cd7b,0x12726e32,0x4983efac,0x5d0fd8b0, + 0x02ddb913,0x796e552c,0x77b9685c,0x0eeca3f7,0xb15f24a3,0x9b766e89, + 0x48efc979,0x7c2736d6,0xa8021c6c,0x3d619685,0xa0b2f1ea,0xfe33e278, + 0xb676d6b0,0x95c69879,0x1af4e0be,0xa0747319,0x36c4ee55,0xa2fab5f1, + 0x59e5f3b9,0x6938b8ff,0x39cafe6e,0x1e114da4,0x6a6ad120,0xc9595ec3, + 0x57e62aec,0x80f79bd0 } }, + /* 165 */ + { { 0x60af09b3,0x3cef42a7,0x933dfe14,0x3c016ebd,0xed85eaa8,0x720cf1e0, + 0xceaa3bc9,0xd4f5e99f,0xb7106f97,0x7216b9d2,0xc9668ad2,0x65f34c36, + 0x5b0c651f,0xa8fb82bc,0xf2fda4de,0x20f42f1c,0xd21f659e,0xeb31ab2c, + 0xa13d1618,0xb7a776c7,0x38662be5,0xec441022,0xcad08e0b,0xc825da70, + 0x022c0180,0x99299079,0x2aef9ffd,0x7623bda0,0xf5c58b50,0xde84f4f3, + 0xd824ff19,0x5f5a5da4 }, + { 0x7e8311dc,0x5737257e,0x466cf136,0xdef94f51,0xb05ca21a,0xa73e1645, + 0x02e4ab37,0x38ea9b3c,0x8579165b,0x7760eac9,0xc24b01a4,0xdffdd047, + 0x3fb95584,0x188d4fd1,0x25548bda,0xfaac38b8,0x59e9dcac,0x1a79a6f0, + 0x09a2700f,0x983f720f,0xfb8a7e48,0x8cbba554,0x47a1fad5,0x38a19968, + 0x5abd6b5e,0x11856547,0xf3716ec2,0x75113d31,0x4212907b,0x1391e781, + 0x0dc15889,0x5319c801 } }, + /* 166 */ + { { 0x6b61c3af,0x2320136e,0x07b4bb68,0x1d40f2de,0x380c97f0,0x651dee7f, + 0x6a8c313a,0xa978ba70,0x2011ca10,0x22c587d6,0xab1f445b,0x48bba218, + 0xe50444e6,0x8c5eaf07,0x442fccf9,0x5549f02a,0x3d80493d,0x2564746f, + 0x79c04591,0x42d24f61,0xabdc8887,0x1600fa18,0xded38f8f,0x5cb8600a, + 0x923aeb46,0xa4bf9b90,0x1e1c578a,0xd63fee35,0xebb9ea14,0xf3c9c5ac, + 0xf11a4ff0,0x3d13314d }, + { 0xb4513d1e,0xe5cc662d,0xd55952bd,0xde78a8c5,0xe7f86d0a,0xe8a37a3f, + 0x7a04f0c5,0xca2d12a4,0x2e25d06c,0x4c6696e4,0xb2136071,0x52614698, + 0x89f6e1cb,0xf4d2701b,0x80efd95e,0xaafd6177,0xc5bb6907,0xe6d73ac4, + 0x420db35a,0x49e874ac,0xf2751fa0,0x11631de4,0xa1fa2edd,0xb29f7336, + 0xb7fd794d,0x4c406864,0xe22f92a6,0x73cb21d3,0x2043cc76,0xeae904e6, + 0xb322c6ad,0x67f28a9f } }, + /* 167 */ + { { 0xca148ab5,0x7c17b258,0xb3c60051,0xb9a1976f,0xc8f28df9,0xea260698, + 0xe8d45017,0x87b2cc74,0x0578a422,0x37257329,0x17bec732,0x81d5ee25, + 0x1d48bbc4,0xd7411fcf,0x487f5cfe,0x46217e6b,0x41eb8e1b,0xcb007ac5, + 0xe05a00c8,0xc41c57a6,0xd2f9fa99,0x1f954d2b,0x40941cad,0x370bd5db, + 0x3829509d,0xe487879c,0x5ceca5ee,0x4c137552,0xfd3efb9e,0xe8ef7fa4, + 0x1bd1bdb2,0x5ff09174 }, + { 0x579c6632,0x791912a4,0xb8a20815,0xbb19a44f,0x535639d3,0xf4f97b84, + 0xbc3c9bce,0xe57e2bcb,0xf19e6410,0x122b3f2b,0x1357d9ad,0x1f0189da, + 0x79e5ff66,0x675573bb,0xef2f3c4c,0x444e5c98,0x04d10731,0xd6f61e20, + 0xac75d635,0x0dfa366f,0x2c854f23,0x9fc47c86,0x0ad0850b,0xc04ae43e, + 0x2f720c32,0x5ce94f64,0xa753bc9d,0x67efae65,0xb0373a63,0xc27d30d3, + 0x29721646,0x6681013a } }, + /* 168 */ + { { 0xe84509df,0x1385d913,0xcf339376,0xe978bedd,0x3423a148,0x2df425d3, + 0xee8cb579,0x43fa0ae3,0x31c4553c,0xf015369d,0xdfbf1d48,0x05cf08bb, + 0x9444244a,0xadff4be6,0xa35dda33,0x01635f81,0xe76fab7c,0x085c8949, + 0x16737783,0x4bd7fcde,0xa254f8d2,0xfd8cb52c,0x413ec985,0x62168a66, + 0x7a9026cc,0xf2db9741,0x50e1e1b7,0x3962ee56,0xd3beffde,0xbee0a346, + 0x0bdfab1f,0x3b35b72f }, + { 0x535c3749,0xbff8de9f,0x8add9c48,0x23c1f20f,0xc8f8f663,0xa975b37b, + 0xe8f3ae49,0x2529e475,0x1d5e2628,0xc32f10d5,0x67862f1d,0x5ac0d297, + 0x854cbe36,0x13c79338,0x4b67e462,0x48f004ef,0xe5d10ee1,0xfa37a150, + 0xd28288a0,0x4974778d,0xcfb73f4d,0x96830a66,0x07804952,0x9f444013, + 0x9760b694,0x8233c709,0x25b75c99,0x8340cca5,0xc771f99c,0x3f62e40b, + 0xcd95c685,0x47d0a1eb } }, + /* 169 */ + { { 0x652811f1,0x266f4fff,0x62ef3002,0xeaacaa93,0x50cba0ca,0x6c387a55, + 0x007f5467,0xa350142a,0x202f2673,0xc7fd102a,0x33dc6e65,0x5daee570, + 0x064a63d9,0x60682ec3,0x462b251e,0x46cf0bb0,0x5da936e7,0x0e030ca5, + 0x434265b5,0xc87a60f2,0x69b4e8f5,0x9637b2bb,0x7ad7770a,0x601fb58c, + 0xed3a15a6,0x1f2147f6,0x2995e961,0x05b47d5e,0x83213a16,0xcb0ca9b3, + 0x4995a85c,0x8f4b614a }, + { 0x4b4eb3c1,0x5aa8ec19,0x20323a70,0x8c549ac4,0x4f6cc6aa,0x00d49322, + 0x45f9a5a3,0x0e53b9bb,0x0897abbb,0xe46ef110,0xd7acd7d0,0xfe873e57, + 0x0f7cb588,0x7cfccfe5,0xc85557d1,0x0ea53d65,0x7288f2e2,0xfdd9eb44, + 0xc0eb68a8,0xab2dedfa,0x08603a0c,0x58221470,0x00feb06c,0x69464689, + 0x25e5caac,0x804cf5bf,0x9fc91ae9,0xd8559858,0x73c45eae,0xed9378b1, + 0x524c9801,0x8f942d02 } }, + /* 170 */ + { { 0x8e845808,0x1f1ec302,0xb77abfc5,0xc302bffa,0xf8d97dc7,0x26afd4b9, + 0x3aac594b,0x3d3a83c4,0x674d94dc,0xe3b74bd1,0xcaa5911c,0x4464b737, + 0x871c2cd2,0x62925773,0x3b4440fe,0x419f2485,0xe052ad7d,0xdda6a0f3, + 0x846c86c0,0x645280d6,0xf8324f42,0xa25689fa,0x07cf117a,0xc74ad1e8, + 0x8ddc9db7,0x5626dea0,0x966fc85d,0x52620373,0xf3b1eb53,0xe0ad57c3, + 0x949c1acb,0x38300252 }, + { 0x5e744723,0xa0ef5a40,0x1ae08481,0xdb5bcf75,0xfec1f76f,0xabfad8cc, + 0xfab37fc6,0xfba5d831,0xc8fedb78,0xbe39e248,0xad93f310,0xa5cfad5f, + 0x913d5c24,0x747fdb1e,0x4518b7f5,0x052a47c9,0x7cfb4327,0x9e208d6c, + 0x70e538be,0xb135cb9c,0x5bb17916,0x36352759,0x5b3106c7,0xa2c07880, + 0xc209bb06,0xd2d42a06,0xd3c504ad,0xb525b471,0x822ce034,0xc9f4b368, + 0xeb4185a5,0x15f18796 } }, + /* 171 */ + { { 0x0aee4684,0x094dea06,0x7cdbdbc8,0x42b21f06,0xb1931319,0xa439e149, + 0x81a7dba6,0xea4bdd41,0x3c2ae80f,0xc6213706,0x12823dc2,0xb58b0967, + 0x832611b1,0x7443d515,0x13c20384,0x2e16f831,0x2bd992d2,0x0ce204d6, + 0xf419388b,0x499dbcd6,0x1d3778c7,0x492ded1d,0xc5ddae73,0x9d5bd74f, + 0x994b6259,0xd4813d52,0x0e86ca68,0x191d9cf6,0xf3e9c2ac,0x562179ea, + 0x9fee1238,0x6146f1f3 }, + { 0x078e2aa6,0xbd06d33e,0x9dee9265,0x693af7f7,0xdaa40e84,0xd56e0f81, + 0x9b9a407e,0x05fbbb88,0xede99519,0xdcf44adc,0x092dba39,0x7f71f8d3, + 0x4231774b,0x675b5da5,0xa5f605eb,0x7456a251,0x87a39a9e,0x9031d4af, + 0x05b474bd,0xdb430006,0xb665aa91,0xbda5dbf2,0x6631eeb4,0x5d1a3df5, + 0x62377c58,0x028149ef,0x685d0bff,0x2e1af4e9,0x82a465de,0xe0ea0875, + 0x06bd0050,0x95543f9e } }, + /* 172 */ + { { 0x85d7c6ef,0xf7cbc6f4,0x63b1bc24,0xcad8084d,0xbf8cba62,0xdf90ce88, + 0xb455c192,0x98e4b686,0x774fc6ed,0x6146b8d5,0x7ae20077,0x70e2389e, + 0x61c22529,0x5241c479,0x3884e5f5,0x7d221510,0x17e28273,0xd6d20ce2, + 0x4f2674f8,0xe3119f51,0x70c011db,0x85459055,0xfcfb760e,0xdfab75d9, + 0x9e8c2a19,0x9546362a,0x4a7d4b27,0x4b6d3f8a,0xee5d698c,0xa5c87104, + 0x2ba296ff,0x6db43478 }, + { 0x5c3f0d95,0x06486493,0x4e748895,0x8917db82,0x6b2f3e44,0xf73fdf62, + 0x2b7f574b,0xc60edc54,0xaf732723,0xbe1c09a2,0x7cad114c,0x7d34669d, + 0x321aaff9,0x9646600a,0xed0cd61c,0xb94e2bba,0xdec4750e,0x866e1a41, + 0xb1a89f58,0xa1be990d,0xf2759693,0xc39e4d6c,0xc0e0dddf,0x11cfb780, + 0xd99c8a41,0xf0afcd7f,0x6e1c3050,0xcebffadb,0x96d2c6e4,0x4f3981b0, + 0x2ae27a94,0x07a791e7 } }, + /* 173 */ + { { 0x1e9f0300,0xe70e9047,0xbccdf904,0xe0253ad9,0xff053078,0x51c0289d, + 0xae893462,0xf1ef092e,0xa4846845,0x2c90a91a,0xf1dad4b4,0x1946eda0, + 0x33df67b2,0xf07650f3,0x0b15a014,0xc6e988db,0xb542f0f9,0x72e0c66e, + 0xe0c0378f,0x5d4b6311,0xae86950d,0x548badaa,0xb35f1c8f,0x6801638d, + 0x944d1ad4,0x129e3216,0x40471d32,0x9951bac8,0x85e94dde,0x03cc29f3, + 0x4543ecac,0x6d6acc2e }, + { 0x57b2d299,0xeb999e95,0xe3d721cd,0x3a2bcd9b,0xbb4cb444,0x2e60384f, + 0xdc060faa,0xae177709,0x8c987cde,0x74f0e6d3,0x1076fbed,0x9a237cf8, + 0x7983fbff,0x69af1513,0x323f9584,0x6c3f7a1d,0x6db64398,0x3e21cacf, + 0x96703d92,0x7cd8134f,0xb8393f76,0x0755898f,0x2e825222,0x1b5b28bc, + 0x7924aa7c,0xb78799c1,0x81427a8a,0x1db378f2,0xff289492,0xd5a451b1, + 0x3d3c46ee,0x79d18212 } }, + /* 174 */ + { { 0x109d5589,0x1a3edff9,0x029b4499,0xded52eb4,0xb4b54adf,0x13eb9d30, + 0xa27bff67,0x4f9214c1,0x67f0f460,0x4c817ee7,0xc3a50e28,0xbadf8d83, + 0x94026237,0xc5dc03c9,0x966647c1,0x5f29581b,0x8a0687f3,0x10b6a089, + 0x31634517,0xae787cec,0x62e75188,0x2001dba5,0x45e2c3fb,0x55d4e1a7, + 0xb67d3395,0xbfcacdeb,0xbc6842ee,0xa1a0af9c,0x3e88580b,0x50590a2b, + 0xa784cdc8,0x73104491 }, + { 0x2648d676,0x44ca2cdf,0x4f1b12b1,0x9a85eca5,0x2980e1eb,0x1b9dac94, + 0x1ac8aa89,0xf30d3709,0xc719e195,0x73072ab7,0x2f703797,0xba518c82, + 0xac0067f6,0xac090e14,0x8dcd2927,0x0e6cfc70,0x21e7da63,0x4f5889e2, + 0x8371c7c6,0xb4aaa40b,0x8f7878c9,0x1f9dabe2,0xd84caf3f,0xf78aed6b, + 0x9e0e1d92,0x3c39dd07,0x122424dc,0x680be5fb,0x0bdc0099,0xf41b214d, + 0x5180c54f,0x6a8f8fc9 } }, + /* 175 */ + { { 0x53235132,0x62a1ed63,0x59dba88b,0x1db233f1,0x291efdd8,0x85625452, + 0xb25111ae,0xc7505297,0x1d701bd8,0xb5921af9,0x9774f45d,0xb4d05d72, + 0xf18e73ff,0x6e3d4c5e,0x899b3038,0x897d985f,0xc89b1558,0x8a9c30fb, + 0x4d13181c,0x3c92d1a3,0x2223320e,0x292e86ba,0x01ceed02,0xcf2454c2, + 0x583f309f,0x27a45f74,0xad0fd1a3,0x75a6102c,0xcb9c7538,0xdb4f45d2, + 0xdb283fd7,0x4752d8c1 }, + { 0xd5dff4d5,0x514d6cea,0x45a827f4,0x74cd5fdb,0x4fc7135e,0x1070a60c, + 0x1be5778e,0xdec0bb78,0x58dc6b08,0x271e12cd,0x54bc2496,0xb765089b, + 0x619098ac,0x6ddf2c63,0x67528832,0xfd6ebac6,0xc2508af1,0xeaa2d025, + 0x4dcfc1f0,0x13c2cda8,0x45510be0,0x1c7836a8,0x1a886801,0x3904688d, + 0xafaf2545,0x643132aa,0x2830a88d,0x49685577,0x8744b470,0x569491ca, + 0x75fb8552,0x3a6518f3 } }, + /* 176 */ + { { 0x224042a0,0xaaa8ed50,0x2452f1e6,0x6cb4e3b0,0x768211d8,0xedca5f4c, + 0xef4d5d3f,0x4e0fe3f9,0x522d46e5,0x33a8e2a4,0xf1446775,0x5998e21f, + 0xf592d01b,0x1496c50e,0x83a67739,0x69104c2f,0x472bbf00,0x28670bcb, + 0x503177bd,0x8ea883b2,0x7d2712a2,0xc5d8bc05,0xb439c994,0x41ef9317, + 0xdcda1aff,0x9801d3a8,0x7038f6fb,0xd686eeb5,0xfbfbf820,0xe80c5cd0, + 0xedc25817,0x540ac363 }, + { 0xfe7f43df,0xa71969a9,0x2c1b9e4c,0xe6653808,0x859c2917,0xad9677d8, + 0x96aa4404,0xbaca9545,0xff1297da,0x0e9d855f,0x22aea7de,0x1f61897b, + 0x36f13f8e,0x96edccfd,0x16e200df,0x627d3070,0xc98988a4,0x729f0736, + 0x97f231d2,0x95e25e60,0xf6048752,0xaf7f221b,0x4019b299,0xd6682609, + 0x26b4b1d9,0x1d99de09,0x1acdd7a3,0xec47cf66,0x6ebe15e9,0x4de9f2b3, + 0xfa16974f,0x17db32ec } }, + /* 177 */ + { { 0x6cf40599,0x75ef6919,0x00c020ea,0x7ea10dfb,0xfcaaf679,0x3da5ae7b, + 0x88ddd678,0x0d663ca3,0x255bcfcd,0x5a21f8fe,0xe344bc7e,0xe9c3f538, + 0x548e0632,0x35f62b1d,0x43c6e64d,0x654f2425,0x26993627,0xc755a7a6, + 0xb0f41324,0xa3b7c5f7,0x3a2180f3,0x05697f79,0x1e81675b,0x6cf85fb1, + 0xe53428f5,0x6d3cdb35,0x52d28b02,0xe3aa1591,0xf7a3fb78,0xa8470255, + 0xa194445d,0x460bd01b }, + { 0xc24d8077,0xbc34dc23,0x4c720d2c,0x82f4b580,0x6f5d1ffe,0xa29da911, + 0x92783ce2,0x578af520,0xb5904af3,0xe29f51ab,0xf7aa1190,0x46c570d7, + 0x571bddf0,0x4a522fba,0xae89bb51,0xbf4e2a06,0x59f3444d,0x799b35cc, + 0x26cc2557,0xc3028367,0xafcec177,0x94a4e985,0x7c36cbd0,0xadaf7dcb, + 0x75d39077,0xed31b787,0x2d3e24bc,0x52d6904f,0x1f95421b,0xc5ca2669, + 0x1734878d,0x7d342c3c } }, + /* 178 */ + { { 0x11fd127f,0xe5cf2c0a,0x119e4c5e,0x66d36bb8,0x6ef56ac3,0x621ab252, + 0xe5430675,0x30cfeaee,0xac3e9619,0x2ede27d2,0xf8fce671,0x6413513a, + 0x075f4c3d,0x6159c61b,0x59069d98,0xd447efe9,0xea76aea9,0xaf8d6f68, + 0x0f5bd164,0xac5dc61b,0x1e88bb98,0xdbab446e,0x1ba92320,0x618b8b16, + 0x78989865,0xa0eafb3c,0xc08b7e82,0x0c7abcc2,0x20d160bb,0x10f09b6e, + 0x8e4c63a7,0x5be0afa6 }, + { 0x1bbbf49c,0x82ab6d38,0x8c0703fe,0x3e09ce49,0xe10f4263,0xeca58b5d, + 0xda5a4532,0xd9cc6581,0xf618f7b7,0x07e18876,0x250f7fe7,0x0419a5e3, + 0xde6b86be,0xbb1a9e90,0x37359169,0x584a7deb,0x5149db2c,0x38eb3489, + 0xb0ebabb8,0x14546a33,0xc2f88a92,0x0067f0b0,0x0a2db019,0xbde0dfe7, + 0xc63e6f3e,0xba51b06c,0xe9206fad,0xa19127b9,0xfe80dc0a,0xe4eb5e87, + 0xd4de30ae,0x1e6fccf5 } }, + /* 179 */ + { { 0xaa8ac924,0xb57dff66,0xc298b3e8,0x06e9ad31,0x65fb080c,0xd140e329, + 0x1d95c93f,0x7dab211d,0x8a180caa,0x6d68d842,0xa20ded69,0x1a929408, + 0x38df461f,0xa8151753,0x60eae932,0xff5604ae,0x7dae4c0b,0x901b9e49, + 0xde262e89,0x4573a97f,0xf1084983,0xed69d9a4,0x64724f1d,0x8ffa022f, + 0xea85a15f,0xd5f1c2e4,0x01453794,0x4c626ce9,0xbf0907dd,0x80440cd6, + 0x5ddaa837,0x4522d461 }, + { 0xebfbe7c5,0x8895f079,0x84ef3446,0x30ea1ded,0xd4a1ab96,0x716a9eb6, + 0x50a30c68,0x1a4a5d22,0x0043bbaa,0x5a16631c,0x5010e5f5,0xbd107502, + 0x3d8c0556,0xbffe3e9d,0x07772419,0x31b30b18,0x84b82297,0x90ff7ef0, + 0xf21a18c3,0x00c37d75,0x565bb8f8,0x18d0a635,0x45e3bceb,0xbac1da2a, + 0x23f0b08d,0x1c38e90c,0x5fbc5ac5,0xf1ba1aa2,0xdda71fc6,0x09d5256b, + 0x6d7e40ba,0x346501a9 } }, + /* 180 */ + { { 0xcc2b0f1d,0x86be448c,0xac4c3703,0xe3eb45c9,0x9fc96bbf,0x5387f65d, + 0x5ae27fda,0xcef3c4e9,0x1bc18089,0xa008f776,0x22ca18a1,0xf374a084, + 0x53b73371,0xee882842,0x7cc09354,0xcb6fc6d8,0x61496d6b,0x8489ec1b, + 0x49e325c4,0xa92c29b9,0x7bdec166,0x15c6ca52,0xdcea2813,0x95444eee, + 0x3a21154f,0x34683eb3,0xd39061cf,0x8fb26f98,0x06c940bb,0xc3b08aa8, + 0xe554c96d,0x7c1d42cf }, + { 0xdc110aa7,0x766e703f,0xf362e378,0xab7b79d7,0x5aadca3c,0xd259c75d, + 0x60be3373,0x2a6eca79,0x06c4e8ff,0xf4744a4b,0xf3b705bf,0xb2842cce, + 0xae304b53,0x1a3af5aa,0x1b2d31b8,0x7bbfa201,0x4bee88d9,0xc4ba6eba, + 0x565cb839,0x2d3565ce,0xdaf7ece8,0x24808696,0xe6959745,0x2c7ccce7, + 0xe94f9837,0xefd6eb3c,0x3811a326,0x0a33b4cf,0xfffa93a6,0x14203f43, + 0x73c31d90,0x031e9828 } }, + /* 181 */ + { { 0x765a17ff,0x4fefecfc,0xd1290a65,0xa09f3888,0x938da038,0xbf265c46, + 0xa169ad46,0x4bb6145d,0x23a62fe8,0x33cf8214,0xabc860a5,0x562df571, + 0x815c38c4,0xbf2a90fa,0x17eda875,0x45ba1d6e,0x946fa5e1,0x799d881a, + 0xb90f5a3b,0x6c1be784,0xb10ff52a,0x0910a37c,0xa4f4fd36,0xc38c1fe4, + 0x8e2d3ba0,0xc3180fc5,0xb17a6187,0x3e2ff050,0x943a35c2,0x3a00059b, + 0xa28cc51c,0x494d3645 }, + { 0x4ba021f8,0x398426b6,0x796deb6c,0xd14c9083,0x7e36c762,0x6d2e5395, + 0x751cf216,0x8f556eca,0x19b24a19,0xdaca1e00,0x4b20c2ae,0x47887da4, + 0xff41a733,0x93ed4ccd,0x5c7c0cd7,0x8d717c44,0x91bf7009,0xcc48634a, + 0x3b59bbaf,0xa1f146f9,0xe5624f15,0xdd38bb39,0x303f8443,0x96d41aad, + 0x4bf104fc,0x6b670f03,0x29706582,0x0503f9ed,0xb34200f5,0x768e1f47, + 0xbbd4c6f3,0x3cfdcc5e } }, + /* 182 */ + { { 0xb523e13d,0x536c2a86,0x2920d0a0,0x1014a458,0xe7571296,0x3d52b478, + 0x7eb51bea,0x05746066,0x87b0e919,0x709f7861,0x686888e8,0x028aed88, + 0xd94afcd4,0x79a809d7,0xe2129af3,0x50c6032f,0x983c4082,0x75e4be72, + 0x7ab3be8e,0x98331bbb,0xb618c728,0xd31a032c,0x3f59c4a4,0x36dd85a1, + 0xed4f61e2,0xdbece345,0x1e571715,0xba7aaccd,0x64a1ebd7,0x138c58da, + 0x3d1aeea1,0x89296d0f }, + { 0xcca82c97,0xb165288f,0x1427e8dc,0x26c6c12d,0x4c3edda9,0x66a94f07, + 0xeaa01ebe,0x94600e1e,0x30f5e86d,0x14abce7c,0xcb456a31,0x741d7020, + 0x279f42c2,0xab05aa13,0xd4238468,0x70b60faf,0x318d39e6,0xa18efec1, + 0x8920b318,0xeb07f1ac,0xd8399e03,0x01e3cba8,0x3c81a301,0x65f8932e, + 0xccc667d8,0xae8bca7d,0xa268607c,0xcee1ae79,0xcac0a12c,0x3182e64c, + 0x2b1a4c54,0x9233a2f7 } }, + /* 183 */ + { { 0x0acbee17,0x717e8df6,0x5c24fcdc,0x0f0959c2,0xe54ffcb0,0x46f09887, + 0xd285116b,0xb993deca,0xbba1fa51,0x0bfaa4f8,0xd0f2183e,0x9c9249ef, + 0x96847779,0xf93cb358,0x2322d421,0x284bfb7f,0xd42af009,0x40cc709a, + 0x9bb1d615,0xc69f2274,0x717c3c6a,0x76f50b3a,0xbb9c5eeb,0x8b21e985, + 0xa4783b5f,0x58fb19ae,0x52e1c3e7,0x04c86b9b,0xf2971ac8,0xaca59092, + 0x21ed8291,0x2bb26a69 }, + { 0x15f81416,0x98a34435,0xaaff5bb4,0x086e72e7,0x0317261c,0x3d1f64de, + 0x5c0a1cfe,0x31c0786c,0xb3683401,0x542ea4d8,0x1a39b4cd,0x2f77273a, + 0xcbef27f1,0x14fe7ee1,0x16bb27dc,0xee7fc09e,0x410e5dc7,0xc0dccc17, + 0x1943b3dd,0xa3466742,0x3f31c1b7,0x92934b60,0xc22c1070,0x0186ded9, + 0x799f966b,0xa37ee8ba,0x249b0893,0x0f3bfcb4,0x2e92d4de,0xbae61447, + 0xe196eb08,0x937cb3f8 } }, + /* 184 */ + { { 0x16fbfdce,0x57c0e77c,0xc98d4cc0,0xea034cc9,0x42572d20,0xe7606d72, + 0x0019a83c,0x9861b55c,0xf1597162,0x80ba2803,0x05a0fd7b,0x0f4141dd, + 0x4b0daaa2,0x8865913b,0xaa3848ec,0xe6685746,0x3e0485d2,0x16d15a5a, + 0x3b6905dd,0x81c0c774,0x818af2ba,0xcec31b7d,0xd2b74b78,0x80d8f194, + 0x543e2f28,0xca659db2,0x9fb07c1c,0x31b83a7d,0x1f1048c0,0x86537fdc, + 0x78586a11,0x4d57bb07 }, + { 0x53b396b6,0xbc4b768a,0x93b51dac,0xbc8b24c4,0xa30ae1b3,0x33e511eb, + 0x945147c5,0x893bbd95,0x179fe3ce,0x6cc86031,0x3f920bd4,0x34b0a167, + 0x6b256160,0xb32912eb,0x9d168d83,0xbc69a2a4,0xef0dd128,0xb4949e7a, + 0x872699e1,0x2613419a,0xbf21376b,0x06c58477,0xa4f97147,0xe55b1909, + 0x7b9b745f,0x63d6eb75,0x08df3c85,0xb5365b29,0x55fcfae3,0x0e257e43, + 0x979f2aa8,0x1067c118 } }, + /* 185 */ + { { 0x32bf8883,0xc8455084,0x6fd06667,0x4755286a,0x77c2335d,0xd70b0f8f, + 0x2f4a2c94,0x678e60da,0xd118acf5,0xa468d8ac,0xbf5b90d9,0xce93830b, + 0xed4e9104,0xea4b1c74,0x27776ea4,0xac67316d,0x361bab12,0xb98ad75c, + 0x99122451,0xc323d482,0x530a43ae,0x26440220,0x3292d5a5,0x3a44532e, + 0x5fecf1bc,0xdb48694b,0xc667b8b8,0xe4e0516e,0xa4306ade,0xb3aa595f, + 0xf34e9725,0x7e4f7091 }, + { 0xb7f70919,0x3f3816e9,0x16b003f5,0x765216ed,0x778c99e5,0x46c6cff4, + 0x30a51810,0xe6a5abe8,0x45e728db,0xef6f49e6,0xcaccefd6,0x6fdd73ea, + 0x8c37f3f7,0xec394e6f,0xb6407fc3,0x73320802,0x96625cbd,0x988e8f7a, + 0x7cabfb00,0x83292363,0x407f359a,0x258ba9df,0xccbfae50,0xff01aee5, + 0xfe251813,0xfbeaeace,0x83f1cba1,0x9c69f161,0x9eadcdb5,0x512c58ad, + 0x6ccce8bd,0x2ae49cd4 } }, + /* 186 */ + { { 0xc40849f2,0x1239b0e3,0xa441098c,0x5136a4cd,0xe547f649,0x61535a99, + 0x7a9bbac6,0x92e4bdc4,0x53547af6,0x195a1646,0x8b47a74a,0x85ecb319, + 0x9de6a2b2,0x278553fc,0x0e2ba52d,0x471c038a,0x35bcba93,0x12ba1b88, + 0x6f31eca2,0xd4bf50da,0x802b32c6,0xd146e3f6,0x3c64c8c4,0x0c9c0131, + 0xeed21297,0xad30f12d,0x9c68530f,0x9b75bffb,0x8918de51,0x23c0ad3e, + 0xa73771b7,0x180e9d52 }, + { 0x29ab77b0,0xc316542f,0xf7aee628,0xdd411d9c,0x353c2f40,0x044c0685, + 0x4b0ae4cf,0x638dc7e4,0x95fc266f,0xa0924185,0xfd2feb7d,0x639da671, + 0x5ea39798,0x56858ed5,0x58f3832a,0x7a694f31,0xd316d831,0xa94233c6, + 0x30a35a7b,0x2fcacb26,0xf1ff713b,0xfef8f7dd,0x59eee2f3,0x8b9b4525, + 0x156d064a,0xd1b4f91b,0x2f5cfcfc,0x177866c2,0x3777eb41,0x12bc2566, + 0xd8ab85b4,0x21ca6f3c } }, + /* 187 */ + { { 0xa3e66635,0x0e162b13,0x2a9f76af,0x1ef20a2b,0x46db3356,0xab473a30, + 0x7802bb8d,0x0840bd77,0xa699b44c,0x5b6baf5e,0x1b2207f1,0xc6e11900, + 0x790b0105,0xe5de16a9,0xdb67f004,0x22b12f15,0x8a025d25,0x185fad45, + 0xdf0a1142,0xbccf6953,0xf45034c0,0x4c42129b,0x1c277bff,0x0f740400, + 0x280a9e18,0x6e440b4c,0x842aa2b4,0x767de8f5,0x05e8d94f,0x3de20ab8, + 0x20227635,0x5aff5859 }, + { 0xa8458e40,0x805acd20,0x149732bd,0x5a5557d8,0x5f1ca72d,0xc7074131, + 0x952b5323,0x7f2e269c,0x6494fadf,0x5c592556,0x1a7d2666,0x153b7acd, + 0x86fe2865,0xa6df063d,0x57d53b6b,0x1e91db13,0xe93ead01,0x9195bb89, + 0x2963bfe6,0x3d71e1af,0x88278886,0xfab2b9c2,0x3b859b6f,0x77836692, + 0xf7029dd1,0x6e695174,0x7b984561,0xc7987876,0x5907d849,0x64fb4f1d, + 0x88d8a977,0x3eab7e1c } }, + /* 188 */ + { { 0x52e5718b,0xc73a94b6,0xf4cee1e9,0xe3aefa54,0x553eedea,0x654e9e63, + 0x5f3aca1a,0xf2541e1b,0x0d083316,0xd7129489,0xfb7f950e,0x7965af63, + 0xc74e3e4a,0xd8fc9e0d,0xeaf79ebc,0xb4ee48d2,0x8b7787e6,0xa458a86a, + 0xf7cceaf0,0xd8c7621f,0xdf67980d,0x8228eeff,0xf9106727,0x210d4742, + 0xb07e3629,0x91f63501,0x7971e29d,0x441761c6,0x03a3b8a5,0xc0ccc65f, + 0x38e09544,0x3491da4f }, + { 0xcb062eae,0x6706d046,0x5d08776d,0xee7db735,0x292315d2,0x80de8052, + 0xc402bbdb,0x40785662,0x26ed3337,0x5f93525c,0x7d568ed3,0x6cea14d6, + 0x66888b1e,0x916a1189,0x5dc71675,0x0fbd5205,0xe4575df2,0x833d1077, + 0xec092335,0x4e93100a,0x6cd85389,0x2f9e1d01,0x43226368,0xeebd3725, + 0x1ba4cfd7,0x401d172b,0x574c5838,0x377dab9d,0x80d517de,0xaeaa6958, + 0x6ad15a18,0x0c843dfd } }, + /* 189 */ + { { 0xc9373300,0x455811ff,0x99fdc300,0x1c39332a,0x353cb655,0xe19bb81c, + 0x96a83d27,0x774b924a,0xb2ee3f1a,0xcbfc8fcb,0x010d56c7,0xaf278ec4, + 0xe0abaf79,0x6fde682f,0x7339aebf,0x7566d072,0x71205db6,0xbd35ad5d, + 0x7051c9d0,0xb5bbe694,0xd3a3067c,0x577db480,0x572d7530,0x2c70ff54, + 0xe06d853d,0xe8615aec,0x05abfb5d,0x71999ccb,0xea0a8ed7,0xeeefc96b, + 0x35f6df69,0x2dcc469d }, + { 0xc65f0e77,0xcca6cd06,0xbd71b14a,0xddcc7980,0x3c93cc00,0xb6221f8b, + 0xae8cbf57,0xddfcd5b3,0x76f8e63f,0xbc92973f,0x06e132b7,0xe9848a34, + 0xd51ec9e2,0x4cc59a03,0x3a33081a,0x9c9d32bb,0x80e8466b,0x00121052, + 0x1bbe7295,0xc2b0032a,0x24938448,0xdbfc6572,0xb6bba0ff,0xe972a0ce, + 0xc0a94802,0xf60c0a4f,0x599d8bc7,0xf62c41cc,0x312da0b8,0x820c96ee, + 0xcdbdf9fc,0x5a1a65db } }, + /* 190 */ + { { 0x42485684,0xbfba691a,0x29c470c9,0x613116b9,0xe62a0519,0xb4b01971, + 0x5ff499da,0xf3245aa6,0xa5238eff,0xc2ef87f4,0xcc9d5515,0xc16dc6ba, + 0x2dbdacac,0x5a7f227e,0xa9bbaecb,0x8dedaac4,0x2e7c9885,0xff308a6d, + 0xe6895593,0x4c6f2fc2,0x177e0611,0x3655f285,0x300b1bee,0xa63e8d06, + 0x13c17b54,0xbed0ce79,0xc4974262,0xca4abe35,0xbc4e4037,0xf4b44a17, + 0xefe5fbd9,0x5ae95099 }, + { 0x804f7455,0x122e5ee7,0x22066682,0x341a4997,0x7795e333,0x97d24c31, + 0xe48efced,0x12f4123c,0x19fbc21c,0xe8738d92,0x0663a3ae,0xbb3bdc61, + 0x8593a6db,0x3603d8c2,0xe3c1ac75,0x926227f2,0x5eaae519,0xfea92ac0, + 0xfd6812ac,0x5b596f0b,0xfc2a82dc,0x3ce7e844,0x63522b27,0x3840481a, + 0x52867895,0x836088b1,0x26588688,0x21ffb7cc,0x2f4a7cac,0x0ca33161, + 0xa3edd298,0x4110667e } }, + /* 191 */ + { { 0xc2d04b63,0x81830357,0xf4929a18,0x3fc5a34d,0x22d195df,0xc73bf6da, + 0xcb432473,0x14df2f89,0xe997f138,0x345afe5c,0x8b9604f4,0xd8e3f5f9, + 0x50c10ae5,0xad7942e9,0xeed25ff3,0xcefd5447,0x0e73c0cc,0xbf68e51e, + 0xab54fa4c,0x5b1ad591,0x12b61c8c,0x8bbc1105,0xb5abf760,0xbb932913, + 0x01e79649,0xdb1231be,0x040ccbe7,0xd0a83e91,0x90a96db9,0x3dde426f, + 0x34df11ea,0x1cceb645 }, + { 0x0c6d0f55,0x2d210c4f,0x9c673c9d,0x6cadf61b,0xa9ce3fbb,0xdd7f9919, + 0x93b063e4,0x135f494c,0x145a93be,0x580bdb3c,0x0f52ef7c,0x4d872332, + 0x8814bb6a,0x74d876e8,0xc7a97dee,0x4f6f723a,0x3e3cd833,0x7de2b8f0, + 0xae720270,0x6162f082,0xddfa486e,0xe88ec2d4,0x8d3a17c6,0xd965c859, + 0x3980171a,0x62e59e54,0xbbef6b22,0x0ab6285d,0x4d48b203,0x3cf45195, + 0x4ea25ea3,0x1f175233 } }, + /* 192 */ + { { 0x3467ea91,0x808a765b,0xfd2d9c45,0x3f4632ee,0x9cf2bc6f,0x7b75dc6d, + 0x359813ae,0xefc8d240,0xe44cbd8d,0x23ecb209,0x21525622,0x59ba10e3, + 0x3f1ee19a,0xfa14d934,0xfb0c48f7,0xdf97c21b,0xea30d437,0xc4e62890, + 0x651475c2,0xb286e2a4,0x126672a5,0x291f01e4,0x31aab3b8,0x9c6fda5c, + 0xe17d22ec,0xb7277a5a,0x914f0bad,0xbd88ed83,0x6a2392e1,0xd0b05d1b, + 0x65893c2b,0x4cb8af90 }, + { 0xbb4b1953,0xa2b02057,0xf597f6ee,0x4ce08b44,0x5e6412c8,0x854f5d9b, + 0xb3cd4919,0x1913262d,0x6e42bb5d,0x902762e4,0xd78e7f60,0x8355c8e6, + 0x38b6c16c,0x8efaa824,0xe550f618,0xd0173790,0xe57d778e,0x118af462, + 0x715b4714,0xa16ad5e8,0x41dea4f9,0x900596c3,0x280ca610,0x2a957c32, + 0x374c65a1,0x2faee800,0x50080414,0xdb105127,0xff080fa1,0x8c1db931, + 0xd79878fc,0x486a5c25 } }, + /* 193 */ + { { 0x941b4f36,0x0521e213,0xf803b4f9,0xbaacfb14,0x52a54ba8,0xfdf1e22e, + 0x8fe4796c,0xacfabbba,0x58dbacb6,0xae0788db,0xc19dfa51,0xdf98d736, + 0x35a716ee,0x155c286a,0x9c86461b,0xbe7d4676,0x63a64a5e,0x50b6380f, + 0x9f609262,0x14b41914,0xa2dfc5b3,0x0919a7d0,0xcef466ac,0xc454da55, + 0x6986aaec,0x93fa4a24,0x71a49ced,0x5090b171,0xc1fa75ad,0x602f1d6c, + 0x78e4c054,0x5d269f89 }, + { 0x14920419,0x3a74030c,0x90968739,0x0845d868,0xeeb70fa6,0x81b994c4, + 0xd9fc5bcb,0xabcaa06d,0xf58f8f2d,0x06539427,0xb1dc52aa,0x35c85f67, + 0x2c911baa,0x5a7d8d72,0xaec2d834,0x4041005c,0x7a8e5347,0xb5868a44, + 0x8de512c3,0x04ee180b,0x211168eb,0x4daa66e5,0x2317cd8a,0xc0bd5dab, + 0x61164df6,0xa1d4185d,0x1dbad7c9,0xacedca26,0x09b02683,0x0fe4b5ac, + 0x26d9550f,0x8ac9995a } }, + /* 194 */ + { { 0x2640a39d,0xb2c8dc9b,0xede0c9f9,0x21ff0b38,0xa1ecba0a,0x74f469bd, + 0x080d0417,0x8a902ccd,0xf4994604,0xe956fa32,0x9776ab15,0x348f85cf, + 0x0066f492,0xc21fc6ee,0xfeeef367,0x35b1ebfe,0x4613e5ed,0x7804581c, + 0xea6ba071,0xcbdfe8e6,0x950d73ed,0xddfcaa32,0x1da48889,0xc9747936, + 0xdbaffbd1,0xce867c8c,0x1cbaeae7,0xd267431f,0x897912c8,0x68255045, + 0xd7ea1e4d,0x0c7c1ddc }, + { 0x1ce963a7,0x53aa30cc,0xc4c5fade,0x7352f64c,0x2828afbf,0x2b9aa2f8, + 0xca212107,0x64273c56,0x85a576dc,0xaadd7654,0x90b5c77c,0x6196ac3e, + 0xd1aaf39b,0x20d43e9f,0xcd05cbc4,0xfc392062,0x4c0ff2fd,0x14163872, + 0x2ae821e6,0xcf32b8d8,0x3fa7a3f0,0x5f58f943,0xf644ca92,0xaebf1d2d, + 0x1918a75f,0x0c061563,0x6b876118,0x7989b5ed,0xad412441,0xbf342445, + 0x1df633ab,0x24ffc9ae } }, + /* 195 */ + { { 0x93c7cb2b,0x89fcdc05,0x590053fb,0xc1243b95,0x6182343c,0x601debcf, + 0x66c18a63,0x364546ef,0xec913287,0xa5290701,0xf9788c31,0xc35b8026, + 0x92d1f7d7,0x852b862a,0x0aa79728,0x1809cb05,0xa3cb2005,0x897d467c, + 0x9ef5b946,0xf20c77c0,0xf2241984,0xc3372c42,0xf35bb206,0xda053e0d, + 0xa9c140b5,0xbc26c6d0,0xcb56fb33,0x61cfcc0c,0x299b3968,0x1c3cf9ef, + 0x40621ba4,0x89e4d3d1 }, + { 0xa45a9be3,0xd35e80e7,0x07356fbd,0xc4daa578,0xb967bc2f,0x0186d62e, + 0x47cd16e3,0xa702679e,0x5f30ce9b,0xca2f1c02,0x1f864f50,0xf1205b46, + 0x85061d66,0x7fd6d797,0x8a08809e,0x47edc4f6,0x9a4d3ae2,0x5dac0449, + 0x6d1f9da8,0xf844664a,0xd7a83a71,0x9f30ce84,0xeaac33f1,0xe9382bac, + 0x948622ab,0x1f033831,0xf7681eb2,0xb037a4ba,0x99a1b5c7,0xd156a908, + 0xe6f1d0fb,0x675d3e6f } }, + /* 196 */ + { { 0x707193e5,0xd9767ffd,0x810358e5,0xe478aa91,0x328d8ef7,0x5634f9ff, + 0x6dbbd9a7,0x913a0ee8,0x7e215686,0x379b2968,0x89d9da38,0x903f410a, + 0x1b1334d2,0xd9f8d7b9,0xbd82efb5,0x9fe74229,0x3803c778,0xdb568b62, + 0xd3d25344,0x93e9a350,0x724497e8,0x559c35b0,0xa169e23b,0xc472d436, + 0xcc5b4c69,0x09864632,0x83c7f531,0x9f6d759d,0x1e497888,0xa91cf1db, + 0x60af1a4b,0x5f7f92fe }, + { 0x0545167e,0xf18a1cc6,0xaffa88e0,0x55ee2e02,0x432a7bcf,0x24cdff51, + 0xa7510866,0x7382da42,0x40511af7,0xe894c11f,0x2aaf1423,0xaa4e4e31, + 0xf63dd2ae,0x8c3d36f0,0xd7660635,0xfc5c9550,0x37ea7eab,0x01253731, + 0x39b950f6,0x2a5cd598,0x40e63442,0x95a0f601,0xf2ac7045,0x905e238e, + 0x446b0f73,0x44bacc0e,0xc448578a,0x4cd4206e,0xa5bd7803,0x367b1aaa, + 0x0a2b458d,0x25beced9 } }, + /* 197 */ + { { 0x0c33a8fb,0x079a7382,0x0f25dc1d,0xcfbf6cd1,0xc6d482b6,0x4ffc73f8, + 0x07bf844a,0x3e51f18c,0x599162f0,0xa7651236,0x14013811,0xac59a74e, + 0xe55018a0,0x957a6865,0xe3ca09b1,0xe1ec51bd,0xa960253f,0xbc0c7eb3, + 0x7de03f84,0xe83bfd14,0x52fbdb09,0xc0540ed1,0xcea15ec1,0x6ba52edd, + 0x4b261307,0xf3d30ed5,0xe8397206,0x9bd7bae8,0x096373aa,0xf20d8692, + 0xc3b0bf63,0x0a616a4b }, + { 0x6e1339c9,0x2075f3ed,0xbf8b00a6,0x7afaa072,0xbccd9b47,0xdfafec82, + 0x00ca54c7,0x4713158f,0x38bc31ae,0x449102f1,0x310dfc8a,0xaf98f158, + 0x59e954d4,0xc9ef2075,0xc527a0c4,0xe8021af9,0x7a192023,0x6e801277, + 0x7fb02377,0x635f538c,0xe8c9e951,0x5df1974f,0x15cc9097,0x0287faed, + 0xf7a5115c,0xfa0728f0,0x0fac623d,0x90dbfbe6,0x0311ba09,0xa8d40fd4, + 0x07c6464c,0x876d154e } }, + /* 198 */ + { { 0xc2d3ea8a,0xd3a4d6d2,0xa842600e,0x36be681b,0xe4070672,0xc53f100d, + 0x6a7d7a7b,0xe3e5b6fe,0x5d5e1a83,0x6e6994f9,0x76097c2a,0x07cacd22, + 0xa6791011,0x12d98dba,0x102e0e24,0xddfc4461,0xd493272a,0x4815dbc2, + 0xa9436696,0x7e38e64b,0x32b2bf90,0x4960eb1a,0xd928e28b,0xda457525, + 0x2a077c9e,0x72f75b39,0x7fd61d00,0x27760cbb,0x0f4b1456,0xaf235d1b, + 0xe76d1700,0x3040c23b }, + { 0x4efa9a70,0xb10dc55b,0x53e86610,0xd4de414f,0x09f8a27f,0x3d95c113, + 0x06661d3c,0x505109a5,0x60eb513e,0xcaa2994a,0x1e7d338b,0x3ee41537, + 0x4651e71f,0x4fd145fc,0xcbc313b4,0x51bbf838,0x1eb92150,0xb039e078, + 0x14bf5ac7,0xe8696b44,0x8be0d48c,0x2d667188,0xdd8f2b6f,0xbe93b2f5, + 0xeb8a7f8a,0xc1dfd1e7,0x90f751c5,0x862b3dd9,0xa32a74be,0x1eb1ad58, + 0x1ebbc9a2,0x5486d79a } }, + /* 199 */ + { { 0xa1359e13,0xcb2e34ff,0x28196051,0x202d8dbf,0x23564b5e,0xe95e023d, + 0x42f6ac12,0xfb1340b6,0xb653725d,0x543ba852,0x8d2466ad,0x81aedcd6, + 0x547c728b,0xbf780224,0x9569fb65,0x559f8a11,0xdfb22ec9,0x505b7a62, + 0x9eed5e52,0x07107540,0x299f6f11,0x9c899288,0x3db6f8c7,0xa7d69261, + 0xb3ca79a9,0x30eb7fb3,0xfb2160b0,0xcab99bb8,0xd28b409a,0xd2012568, + 0x5ac45f8b,0x380f1b0f }, + { 0xe6a0068f,0xc0b99e6b,0xc8a73753,0x4b67cf2a,0xb2faeb7c,0xa6c9a548, + 0x340260c3,0x7f417f99,0xcc0f739e,0x8ee56855,0x780949da,0xf08b510f, + 0x8d5c6eff,0xb1770fc2,0xfd96a7bb,0xb4f5abee,0xf2665a2a,0xa07b1136, + 0xb601dcf9,0x2fb380a4,0x162becc6,0xcc803614,0xee6b83b3,0x3498fb96, + 0xa8c17eeb,0xea9b0fd6,0xa177efc2,0x5834b5ba,0x5b110b3e,0x929044f5, + 0xebd7285e,0x4abedded } }, + /* 200 */ + { { 0x700ef376,0x3355e1b9,0x66cdabff,0xd56e5d9a,0x47e87646,0xb3dc2575, + 0x00f79369,0x28f44b8a,0xa0c52e29,0x08c32b1e,0x3729b392,0x5a78de12, + 0xb26d239d,0x4184519a,0xe0ce4a6b,0x23f6b4b7,0xacb2a9f9,0x235f6f8a, + 0xe2064a59,0xbb8bc454,0x1bf3062e,0x37efd034,0x94dff6f9,0x6bac683b, + 0x8aa7fa06,0xc3364b1e,0xce0b3745,0x0616772a,0xd1e3fb0f,0x46f08d08, + 0x18e132d3,0x6a20abb3 }, + { 0x6a85cbc7,0xea831016,0x934f9aa7,0xd0990946,0xe778f1b3,0xc2211088, + 0x2247b799,0x7ea4ff8f,0x454484ce,0xb3171d71,0x4f98c364,0x29403949, + 0x97df1458,0x5da911f3,0x09439116,0xa6b58093,0x174238bc,0x75f9509a, + 0x8209758d,0xfeb51821,0xa47925d0,0xae0c6021,0xaf8a315e,0x0e946694, + 0x6bad04b7,0xae7af8a3,0xf072447d,0x44c15e7f,0xa5456ffe,0x5184668a, + 0xbf36b977,0x45e353a7 } }, + /* 201 */ + { { 0x93092f71,0x76056764,0xf5b92d71,0xeb66b6c2,0xe2c8b6c5,0x9db3149b, + 0x20c0363e,0xf62f583a,0x03cd7097,0x688acd33,0xebb916ac,0x85d0c0f8, + 0x84c19b0e,0x1bf7462c,0x7c4a6ad1,0xc76ed5f9,0xd119f369,0xec8b88ba, + 0xebe50b83,0x59b8371b,0x866706a6,0x0cc69508,0xf8373d2c,0x531c75a3, + 0x2a5a02fb,0x4e1cd3a3,0xda39a1d0,0xe8274778,0x75da333e,0xedfc5bbb, + 0xca79bd36,0x15941f24 }, + { 0xa77dd512,0x42e8c0f8,0x1dc365f6,0xa91b59a7,0x08753862,0xe80d14cd, + 0xd272faca,0x1624230d,0x4027cb5a,0xeea3ec16,0xc1ef9f03,0xc1700b59, + 0x0da3148d,0xd411c127,0xc4181af1,0x801ee448,0x9e3a900b,0xedf28559, + 0x0d09affd,0x5d67b0bd,0x8b370024,0xd839df96,0xe6f836b8,0x3b6307e0, + 0xbd3201c9,0x5382e588,0x7a1d02bb,0x636d8a6b,0x968641e9,0x70b7db76, + 0x118fad03,0x6d17c34a } }, + /* 202 */ + { { 0xc181c99b,0xcf608841,0xc87bdcaf,0xb65dc901,0x3720dabe,0xb460b447, + 0x5377515b,0x4c79c396,0x0a96c277,0xd447f22e,0x2ac0f440,0x0d952130, + 0xc90583ad,0x8330b26b,0x928904a0,0xe25e977a,0x85c50b18,0x1deaffd9, + 0xa5ad5f6a,0xcf4dbcb7,0xc8a37ed5,0xcbcd0019,0x1e9850b6,0x7846dd90, + 0xb0b8e605,0x1ac8194a,0x34132f90,0xb9728571,0xf56ee28b,0x4ce9f149, + 0x3e9e1d4e,0x1ab9b5a4 }, + { 0x314fa7a3,0x206dab92,0x478ff963,0xcc4af0f0,0x904d9fdb,0x4cce1713, + 0x12c045fe,0xac20a2eb,0xfd8f6d7d,0x44fc5478,0xca7b6ffa,0x886e72c5, + 0x6fd6f758,0x7fa4529b,0x92a820d5,0x4df1d1b1,0x2789f149,0x3d812f9f, + 0xaabb53d2,0x9842f083,0x2a03ab32,0x2648539b,0xb1512502,0x631ce090, + 0x731f6bd5,0xe1294d15,0x9436e634,0xb229361d,0x3ca966af,0x8c4281c4, + 0xc21ab3ed,0x24b34956 } }, + /* 203 */ + { { 0x659824e2,0x49bdcb86,0x4e13e74c,0x6dc4ce48,0x6bbe1eea,0xa4c01a26, + 0x1e3ec457,0x47b2b8e7,0x2f5a8e4b,0x7e8b15e0,0xe333530d,0xe81eb6e6, + 0x17a45202,0xacba369e,0xd70e4c9f,0x81241431,0x3e12beb8,0xc190af4b, + 0x11f486fd,0x53270523,0x29fb2bce,0x9f6c41e1,0xb70f6c08,0xbe6287eb, + 0x3feb4477,0x1479850a,0x9bcf18bb,0xfcfdfb11,0xda80d040,0x925c292f, + 0x7e3c5bf9,0x212d65e5 }, + { 0xca15cf08,0x23adb386,0x81e172eb,0x4dfa4ac4,0x4d42d0c0,0x9d1dbf93, + 0x74404dc7,0xd9cf6073,0xe932bfcd,0x60508441,0x1c682a98,0x9ae910ca, + 0x41ac1cc0,0x9528fc18,0xdbbed630,0xe6a120ae,0x30ccf250,0x94e0e1ec, + 0xe58bbf2f,0xfe84ba54,0x9faa4415,0xc66d0b4f,0xecee7ce5,0x0c58f1e7, + 0x6fa6873a,0x7a1d43eb,0x399f1348,0x96c6c5a0,0xe6727ab7,0xe6ef9aaa, + 0x9a5c2447,0x66afa554 } }, + /* 204 */ + { { 0xc980e91d,0xda5aaba8,0x6ac98efa,0xa93cf509,0x8da32662,0xb0990e0a, + 0x0081453e,0x01d21530,0x3d71de84,0x2bb0d33e,0x3e19a012,0x465f6d80, + 0x78a838e7,0x5902ff4c,0x1931348c,0x74e2afb7,0x9cfb057b,0xa4932757, + 0x3ad03f8f,0x761ea642,0x58ffa40a,0xb7d4c245,0x77a87e30,0xb5e9c0d9, + 0xc9c84d26,0xd1c5edba,0x3d1963a0,0xeca8839a,0xebf6bf0d,0xbc6f2f35, + 0x0d58abdf,0x01ef0631 }, + { 0x3ecdcbb0,0x2bf90316,0x27c1c955,0x19e2d728,0x9575c930,0x9e527030, + 0x96983930,0x0dc1c5a9,0x7cd082df,0xef9f80ff,0xdf97e051,0xcd915075, + 0x9cc61b55,0xf286fffe,0x80f24cc4,0x352db38f,0x36523ae3,0xed9b99ec, + 0x10b104a9,0x109a8ca8,0x305203ad,0xc2700fe7,0x769400f5,0x2a2ee24e, + 0xee0c452c,0xd595d399,0xf7f02a41,0x0ab75d6a,0x0db730b7,0x34108099, + 0x5e8d1202,0x0e4f5ffd } }, + /* 205 */ + { { 0x0ff14c38,0xbd1c6444,0xaece11f2,0x9a5b59fa,0x22af6330,0xaa4605a7, + 0x82af24ee,0xddc9f65a,0xeb9a1159,0xf4ee4bfe,0x74e84eaf,0x2463d076, + 0x0e0baace,0x88cbe1e0,0xd5fabdcb,0x7ca568ea,0xc57eb99d,0xbd80d524, + 0xe9be9873,0x9c46572c,0x7300b85e,0x918a1dcd,0x40f54176,0x49221312, + 0xb5b14236,0xf7e324ff,0x2434f16a,0x40dda501,0xa133d97c,0x08833421, + 0x0876f020,0x33d41161 }, + { 0x9878e5ec,0x7531a36b,0x46918232,0x5de3e321,0xd0a30464,0xd15f9a33, + 0xaa173659,0x734c1b87,0xf925d4fe,0xac2094a2,0xc262b0f4,0x43c965a1, + 0x447d5cbc,0x759c903e,0x05239300,0x92af215e,0x1f593f34,0xfffb6d5f, + 0xc3cddb5f,0x65943b4b,0xbfdd5408,0x9d03a29c,0x198d76c0,0x8f7cda6b, + 0xc0f27b59,0xc0790a22,0x8cb58ccf,0xba557a84,0x76c54fdc,0x5922052d, + 0x47b6b466,0x2d3de7aa } }, + /* 206 */ + { { 0x65add3b7,0xaade7462,0xabf24c2a,0xe5888f35,0xe1a57d93,0xd41549ca, + 0x2c76f7bf,0x0e22e18e,0xbe3202b3,0x67f288ea,0x1d1d0f0a,0xb79a66ba, + 0x2881ad18,0x0e0ab749,0xc7adb0e9,0x7d424086,0x2842132f,0x870c32c5, + 0x58f9a09e,0x858477f1,0xec025589,0x422a9372,0xa5098777,0xbe428c5c, + 0x57660058,0x45b79564,0x957f37cf,0x6c7fc631,0xd6316289,0x8b7023dd, + 0x5b1c12a6,0x47003bb6 }, + { 0xc91c1c96,0xd99401c1,0x27a12970,0xaa5dcdf9,0xc3c29107,0x3ab92e17, + 0xa3fe4710,0x26fce8f7,0x4ee998ee,0xb0d09d5e,0x8e3a41f8,0xafa62204, + 0xa26ca506,0xb1c012a5,0x99b57252,0x2c6f734c,0x512f7fe1,0x1093d79f, + 0xacee19a6,0x2f30906e,0x056d1ea6,0x6bff8381,0xeff35f21,0x61c75856, + 0xc1ad2224,0x6e07e978,0x6b20fde8,0x2cca6ca1,0x633fe81b,0xab4d6d2d, + 0xb06a2ce6,0x73dff504 } }, + /* 207 */ + { { 0xd8e20fb8,0x8b615805,0x82b533f0,0x7c6873e4,0x56a854ca,0x5205f001, + 0xcb369211,0x87fec6ac,0xc7f092b7,0x1fa3c0ec,0xe845fe4c,0x5b36647e, + 0xf8b1f112,0xd4781e85,0x8b0f1a6f,0xc6526839,0xdcb8eb92,0xceeb8c6c, + 0x8e5f6d52,0x133f0ead,0xc8d934dc,0x31883e23,0x428ac45a,0x214ed5bd, + 0xdbbfca85,0xf77ca492,0x07e5ae13,0xdf4113fe,0x72ab05fb,0x63e4a0d2, + 0x7148f535,0x7544d0b7 }, + { 0x80797ace,0x4fe8d134,0xaf86d97e,0x216d6aa0,0xef5a68fc,0xdbf0a688, + 0x9f9b2684,0x18b26f45,0x8999d2fc,0x52fefcfa,0x62423955,0xd5af8d82, + 0xf63a3780,0x8f123469,0xdcd4feaf,0x2933454f,0xa73b5d09,0xba8018b7, + 0xe5552c18,0x9af1f276,0xff26bb1c,0xc5d4773d,0x06dd4f44,0x9ef49410, + 0x5f39ba49,0xad8f12f9,0xf66ca4f2,0x5767f6dc,0x7922f59a,0xba8773f1, + 0xc1e42d49,0x220081ea } }, + /* 208 */ + { { 0xba37a0ba,0x3043d573,0xdd176df6,0x05a431bc,0xc42070f7,0x03322cfc, + 0x67c2d109,0x5cabd30e,0xcbf8bcfa,0x362c95de,0x7787b10b,0xd767d277, + 0x6ec05e64,0x612c915e,0xce69c30e,0x9e669631,0x682e2635,0x27c9dd8f, + 0x95ffcc38,0x79021f12,0x8a2adca2,0x06a8ee79,0x4b5d500a,0x8e00e784, + 0x8d80d6c5,0x87746fc7,0x915f10cc,0x246053be,0x219f6fd8,0x844e328b, + 0x11bd3733,0x620541ac }, + { 0x509e5a29,0x0f7fd382,0xb432531e,0x8748d7d0,0xcd3883b9,0x8f749354, + 0x8bfbb17a,0xc6b8ac74,0x05f2d2c5,0xa4616a66,0x1bcb1b83,0xb3d96625, + 0x2fee265a,0xcf753104,0xdb225058,0xc70d73fb,0xf0c2d556,0x1211d434, + 0x54b259b3,0x862061d8,0xc42b3f7d,0xffe4606d,0xe86a4949,0x4c5c8585, + 0x160eedac,0x04ddcc8b,0x568e2420,0x1804ce67,0x42141656,0x91f3855a, + 0xf932be97,0x7f378198 } }, + /* 209 */ + { { 0xdfa6639a,0x9a374bda,0x02ab7391,0x0cbd48d4,0x47031e2d,0x5c5ef236, + 0xd0599d1f,0xb49ee2bc,0xe0d38443,0xd285eb60,0x269392e8,0xdbbea92f, + 0xb8bc538f,0x91455fbf,0xe469b768,0xae259ff1,0x41de5682,0xc1cecb1f, + 0x9952d1ae,0xc876f071,0xe7bf7446,0x1ce25181,0x282ad2f1,0xcb93ad86, + 0x6ba4ef67,0x8fa3cd31,0xe507aa3e,0xfce68a04,0xa61bb608,0xced74170, + 0xf6ac10d0,0x6de716b3 }, + { 0x172d6dc5,0xd4e58d04,0x6397c65c,0xbed2cde6,0x0c9eb4e8,0x7ae77e18, + 0x75fa2edb,0x56275468,0xa91e6738,0x4b30324e,0x235c8b2e,0x6023a856, + 0xa8f92887,0x9df6d6c2,0xf6f5e8b5,0xec2c185f,0x3ad5748a,0x7892e12b, + 0xd54aefbc,0x7aebb4f2,0xee868821,0x14915448,0xb1d9bd5b,0xa26c5f71, + 0x2ff00df7,0xe5ccd166,0xb95b1dee,0xebc99f17,0x3fe1f774,0x90983616, + 0xbb3d25b0,0x51f90830 } }, + /* 210 */ + { { 0xf2922461,0x49376fa1,0x1650d0d1,0xdbb1b1c3,0x0dd8608d,0x92b91c33, + 0x36b89906,0x3e612c4b,0xdf560052,0xe1977b0b,0x636a2545,0xf8afff70, + 0x11723d8e,0xcda7d278,0x81bde7ba,0x0b0bc4bb,0xed2a578e,0x3cb080b2, + 0x171b2e02,0x5bda0d0d,0x941bb9ae,0xf6df38cf,0xc14a65c5,0x85dd81db, + 0xc19dd98e,0x7f98c82d,0x52206f93,0xc613747f,0x5f5bbe78,0x9e13a2c2, + 0x0aa34be7,0x5eed218e }, + { 0x01d4dc0b,0xe1565754,0xf566bb07,0xa1ae5f27,0xb82225d5,0xe985ebeb, + 0x1189ec6b,0x5f3ad21c,0xecce4d9d,0x17da518c,0xd6b65b59,0xc84a2d3e, + 0x8ffa771c,0x7f988175,0x2ac69a7a,0x50d6ae12,0xc6e6846d,0xcb7f30b1, + 0x5bd0bb13,0x8c023a60,0xd73f2407,0x9a10fecd,0xe5f0a996,0x8c5158cc, + 0xbd8f5806,0xd26bf615,0x915a46e1,0xaf32ea87,0x0287d308,0xeaf74e81, + 0xa6264254,0x8c14ba06 } }, + /* 211 */ + { { 0xb17ee201,0x0c877895,0x88e57a77,0xc05aa471,0x97822456,0x19c3e763, + 0xc9c3ba1d,0x0be6f8c0,0xb4389ebe,0xfe85f4ff,0x0ce7fbb6,0x538bccce, + 0x65266c64,0x876eab2a,0xcf9a3842,0x5c9ac690,0xccc8f981,0x9f5cf3b1, + 0x9cf687de,0xfa17be6a,0x83835c15,0xfcfc10fc,0x150ef2eb,0x086b0fdb, + 0x884a52e6,0x9f97ecd9,0xb0cd1eb8,0x416e6fa2,0x3ecc03ba,0xe2bd1599, + 0xeabb165e,0x645c0a5d }, + { 0x50aa7e31,0xd94c4205,0x2f851da5,0xaec8df0c,0x3c726e6a,0x99646909, + 0x2619bf9a,0x72dbdc36,0xe253fbd5,0x1b4260e0,0x8c709e06,0x97c259fb, + 0xcddaec5b,0xfabf7cbb,0xe4b703e9,0xb4d5e8b1,0x0734efdd,0x1b06e56e, + 0x1f55f8a5,0x02d4a4f9,0x3f565c8d,0x7f8608ba,0x816d1d94,0x822f47d2, + 0x5ce7b136,0x0cc36156,0x31d04242,0xe46ee5ef,0x683567f6,0xb2a65f70, + 0xd2fa6c91,0x27e9ff40 } }, + /* 212 */ + { { 0xd7e952e7,0x75251893,0xc735bf18,0x15b30583,0x96fe0491,0x732b5992, + 0x806d2fca,0x27451858,0x1b885ed9,0x71ab76a0,0x6d9f55ec,0xbdce9d97, + 0x48f2ba9c,0x3da60b20,0x592b132b,0x6977c086,0x099051d7,0xb6dca9cb, + 0xd188ae25,0xd9c2ab23,0xe20aaf3d,0x9f469f3f,0x5aad74d0,0xdbd1f7cf, + 0x22a9eb3b,0x3d5efe5c,0x137010c4,0x8c5edfa2,0x57870260,0xada2217b, + 0x3dac9776,0x4feee567 }, + { 0xb5d3d780,0x30e18d52,0x07166744,0x4dadb5d3,0x5a742156,0x320d386e, + 0x8d6bbb86,0x5d8c290e,0x2d263dd1,0x981a4323,0x98984636,0x33d0e7ca, + 0xa519acb1,0x5138784d,0xdddc81ff,0x832e3fab,0x3199a43a,0xfc278594, + 0x32743163,0x5b4cabcf,0x74f94fa7,0x9fa010bd,0x5694a627,0xc28a743d, + 0xcb657a24,0xc1d2a888,0xe86a25ea,0x7eef2503,0x04c561ff,0xed11a5d3, + 0x9c9ede0e,0x4fe818e7 } }, + /* 213 */ + { { 0x7fc1c7ff,0x00252c9d,0x9fa89ad1,0xa9bd419d,0x4064e9cc,0xc93a124a, + 0x43942ecc,0x384cbcb8,0x8749695b,0x004c21fd,0x421165bf,0x69c81d9f, + 0xdde01102,0xe2325628,0x5a9b004d,0xec937457,0xf6dcfc21,0xfb3346bf, + 0x4d372c7d,0xac4da64b,0xf20494e2,0xcecb7ad3,0xe867c150,0x562c41b5, + 0xc2b723d8,0x299395ce,0x7ee53231,0xc91adfc5,0xf10b6597,0xe06f1161, + 0xb74d3ffc,0x81915529 }, + { 0x6ed9d4ee,0x8ec12431,0x689aff01,0x3dffa154,0x2a89a3f4,0x4aba349f, + 0xd467efb2,0x2db1e8e2,0x039102e2,0x18dea354,0xe52f082b,0x422ab853, + 0xed36dd47,0x7130a2c1,0x0295d1ee,0xca60e86d,0x7c7f5ad3,0xe6ac6808, + 0xde864658,0x0f83cecf,0x461d1265,0x72e66c21,0xbd385099,0xfeef4150, + 0xa6632289,0x0f183f3a,0x792dc795,0x275454be,0x11367702,0x2744c11b, + 0xe8ea6ef3,0x7d06bcc7 } }, + /* 214 */ + { { 0x7090212f,0x89285942,0x5521e844,0x691b7d4c,0xbe2dbb92,0x4c038422, + 0xbd81f880,0x317721ed,0xac89bc36,0xc136cbee,0x7b8f004d,0x4f71b60b, + 0x4e218ab8,0x269132d0,0xe6cc814d,0xb0e2496e,0x75fadc15,0x0b2ce317, + 0x66d223c5,0x82e3c084,0x4c612f8b,0x9721caa6,0xa4b65355,0x59a751eb, + 0xc7d3d9d1,0x3433aad5,0xe80d4246,0x1e61b9d2,0xfc673caa,0x149f655f, + 0xd0f9cb92,0x48b52b99 }, + { 0xefdc05be,0xa3915399,0x13e095e9,0xde70db18,0xcddb3fda,0x447862e9, + 0x1a009451,0xa2b03162,0x23920ea3,0x4b27980c,0xa23b8feb,0xac5394f1, + 0x3e5616d4,0x163f7256,0xb714219a,0xaa0ff93f,0x93d62474,0xd26f96d2, + 0x7dcfe276,0xdd212ea8,0x47038d15,0xab27bf2f,0xf418168e,0xe58c8325, + 0xb32a989a,0xe3704222,0xbfc9f13b,0xa3694390,0x0d0684ad,0xf16e2606, + 0x9d8c76ec,0x17c0de87 } }, + /* 215 */ + { { 0xdcc01958,0xbca5f453,0x1ce88393,0x7d945954,0x561f5b6d,0x5e6350a1, + 0x7e2d36bc,0x291c3c86,0xa5ac3a6c,0xf6c7ed84,0xd98006cd,0x7913c40b, + 0x5671ec3b,0xf78bb087,0xb43e89a9,0x1c928f6e,0xae1ea1ed,0xfdf28df3, + 0xb924b2b5,0x62bba5b1,0x1a116e05,0x491d2705,0x167ed3e3,0x08ec02b7, + 0x5bc0b046,0xe291cf7b,0x8c5d7f59,0x30e50169,0xf5c799b7,0x0c7c350d, + 0x0ac6e1d7,0x6862b9e2 }, + { 0x9ffa1f64,0x56c6f4e7,0xa1e24349,0xfed6a91a,0xcdb75232,0xe9a0ee0c, + 0x0322d607,0xbfc90b37,0x462fef87,0x29480ad2,0xc2bfcf34,0xfc214969, + 0xa539e38f,0x6e5211e0,0x12a5149c,0x2a59ec26,0xd706b532,0x195fe212, + 0xe99c8429,0xf77fb108,0x5dc80482,0x74ceaea3,0xbd92d298,0xa5a6030b, + 0xaaea15ee,0xad42dca5,0x4987109c,0xd6ac3bc7,0x290af649,0xc64e1c40, + 0x51f8de6c,0x5093fa2d } }, + /* 216 */ + { { 0x4c2d553b,0xc4cf3280,0x3b966c29,0xdc1abe22,0x2296914a,0x556a549c, + 0x999976c9,0xd8c9f8b5,0x776e83f3,0xc22c57bd,0x7c85ec57,0x4f2942ab, + 0x6e2c61f5,0xef3407e5,0xf213db48,0xf005e8ca,0xf32698c7,0x470c853d, + 0xcac0a54b,0xe6f488d7,0x60b7501e,0xb6bd6bed,0x714a4bd9,0xf0103106, + 0x6e098894,0x5285bc3b,0xf5f92a00,0xec06741a,0xef7ef24a,0x32f16426, + 0x6c77a438,0x12f9c44d }, + { 0x83313a1c,0x1951e964,0x33c58b37,0x98edd3da,0xc7ac4044,0x4edbbf52, + 0x0dcb5ee8,0x866ca6f7,0x6dd422f8,0xec0ae8f5,0x0661ec2e,0x1077bc54, + 0xd422523c,0x6d39913a,0x58e7cb3e,0xd105e1e8,0xc979bb45,0x47c9397f, + 0x0997b592,0x3221d4a9,0xe8952fe7,0x0ef628a3,0x4e946241,0xd08d5827, + 0x59780f40,0x64cbed0f,0x08e110ec,0x13d7c227,0x7679b1a3,0xd186d866, + 0x26ae1d18,0x02f75e4e } }, + /* 217 */ + { { 0x47f307d7,0x1b637ebf,0xd0141477,0x6b644a6a,0x2e05a80c,0x82a33d65, + 0xfed07b31,0xc8f1a0f3,0x3696e597,0xc09ee7f9,0xc7ffc01e,0xcdaa7ec3, + 0xf8f373b9,0x549f88fe,0xc3bb8989,0xc88d1961,0xdfcaa7b7,0xd92a4fe9, + 0x3ae4ab20,0x12ff9ee2,0xf5ecb1a5,0xf5aea641,0xe32fb47d,0xe769237f, + 0x25d085c0,0x96a5c420,0x26c755a2,0xdc912558,0x9bce9723,0x580b985f, + 0x63961941,0x72b1b566 }, + { 0x790e5558,0x9d708a08,0x0689af80,0x98536041,0x42313b5f,0xe85e7b8a, + 0x55a49d1a,0xe6ba1292,0xac371b0b,0x5e76c4b0,0x938e6e19,0x58504f39, + 0x60ae9a21,0x8dd41422,0x968485ce,0xd8b04e9b,0x887efe43,0xf94c4ba5, + 0xf11c5e73,0x11268e67,0xcf6b99c4,0x92623e28,0x7a0a9662,0xf2d0aaa8, + 0x4ca02ed3,0xb266772a,0x2d63b551,0x68ee8e4e,0x2e78b5b5,0xcdebb299, + 0xe17225ad,0x5df19216 } }, + /* 218 */ + { { 0x8df2e7e3,0x20027e1e,0xd8da07de,0xb183cc68,0x4b4ae694,0xce35ba69, + 0x3ca62e88,0x896d97df,0x52efed2c,0x3de4713b,0x26bd084f,0xd006c40e, + 0xfc81923b,0x1e9b71bb,0x1aacc6b0,0x9991c7b6,0x8f656840,0x650c9364, + 0x87f47524,0x138561d1,0xbffd3ca2,0x610f2b11,0xfa191418,0x96915faf, + 0x955e5309,0x8f1236de,0xa1872d79,0x613cbeea,0x66a2a48b,0x7f7b44ea, + 0xe0a89c32,0x452265c2 }, + { 0x25430010,0x4ad5ec79,0xebd090c0,0xcac786ff,0x20a9d3f5,0xa5f9f4ff, + 0xa3edc65f,0xfcbf4112,0x0cf3eb11,0x8824839c,0x8aa5b700,0xb8dd6d4e, + 0xb7568ab8,0xe2271dfd,0xb744560e,0xe43ec373,0x1cf75296,0x78eaf926, + 0x3fa96d9b,0x1809ae0e,0xdc25dfd5,0x0b312d2d,0x6bab7711,0x6b8f78b4, + 0xb5ecf1e4,0x069efc8d,0x609fecaa,0xc1952bae,0x5f4dbde1,0x43e302ed, + 0x1e078555,0x14b02bf9 } }, + /* 219 */ + { { 0xb87e5b57,0x2c71c768,0xf531a557,0x0bcc78f7,0xf7597dc8,0x4ff93f8b, + 0x139e175f,0xb28e026d,0xcb94ca6c,0x6b83b727,0x0079f7fc,0x2eafe3b2, + 0xcf3bd170,0x2aca54de,0x6af0dc6c,0x17c4133c,0xccf5e35e,0xbea1e665, + 0x345505c6,0xa6691a48,0xe6100b89,0x2633abd0,0xc17d0388,0x966c6706, + 0x1a0cf90c,0x7aefffbe,0xd0add64c,0x4d847be7,0xaea2aa46,0xd49bcdfb, + 0x2cc7d0a5,0x85e07e74 }, + { 0x0bc25bca,0x23aae0a6,0xe44f64ec,0x6e8e55f1,0xb607b773,0xe1e696d8, + 0xd3005909,0xaa90a746,0x2cbc4990,0x072b1ccd,0xc68e2f5d,0x0d0fe6c6, + 0x53e28ec9,0x920ec5f0,0xf0040cc1,0x79b21fb4,0xfcc4a2c7,0xa7375bd3, + 0xe1bac7dd,0xf5f5def9,0x35c0f8d3,0xdc315d79,0x2cacd318,0x7117c170, + 0xe926f71c,0x6f2823c4,0xed02f39a,0x38db58bb,0x7db69323,0xe5b49231, + 0x8d49f430,0x0964039f } }, + /* 220 */ + { { 0x56999eba,0x21774f16,0xb1de6305,0x3d8ee287,0xde0b2669,0xd81af726, + 0x3f8942a1,0x37446939,0xea03e13c,0xbcf6b615,0x94e273cf,0xd30c0c35, + 0xc6725c56,0x4fd33a56,0xa8be97a2,0xa57534ad,0x7c22a251,0x799242a6, + 0x9d0c5c49,0x4e51bdb5,0xc6a42768,0xd7cd76cc,0xd426bf59,0x914097ac, + 0x66e9beb2,0x59404a2c,0x5c96e3e9,0x4738fe98,0xaad666d0,0xbcbb3e0e, + 0x63bc5e56,0x626b0fd2 }, + { 0xe1a1ec42,0x47217dba,0xab5acc50,0xaa6ae7db,0x865331d1,0xb7e1ab1e, + 0x3d30126f,0xb8453070,0xdee61851,0x280649e0,0xea689544,0x8806f4a3, + 0xcb56f632,0x4bbe43ad,0xbcaff94f,0x036b9bda,0xbd0637be,0x0d941e65, + 0x686f3abb,0x82179d44,0xaad6afd6,0x1486912c,0xff7e1534,0x9a3b891e, + 0xeb86fd96,0x88c426ce,0x117928c3,0xb56e6a81,0x96399e00,0x933e7135, + 0xa17b6ac1,0x09bbddd9 } }, + /* 221 */ + { { 0xe4fd3673,0x75e39c1d,0xa65c8e07,0xf880d9d1,0x7289c7fe,0x4725c1dc, + 0x3529d200,0x5b6735ee,0x3c747af3,0xc1f8f2ed,0x912efdf5,0x5cf3998f, + 0x49859c39,0xed722618,0x0e69795d,0x23793a2f,0x86b1d2a7,0x8a6ab8d6, + 0x22a882e4,0x00c815de,0xf9db8d7e,0xbe77d6fc,0x02267547,0x0886fb32, + 0x49c10edc,0xb62687d4,0x7c83ed4c,0x9f1c3e17,0x5af366ea,0xe6d5d7f0, + 0xd1efad24,0x2eaa01b8 }, + { 0x1f357c74,0x5e47fb70,0xa9e3b794,0x93085c4a,0x6e85a905,0x4f098733, + 0xbe0244c9,0xf53808ff,0xa3b5660d,0x91dddf93,0xf3b95ed6,0x8b76377b, + 0xbb3920d4,0x91b911b7,0x86a13cf3,0x7ccf08bf,0xea018e58,0x53ed8f97, + 0x78c55194,0xb1ea4343,0xe0d2d5a6,0x8e6adde9,0x9b96259a,0xfc2b248f, + 0xeef17ddd,0x96ebceae,0x557f9c85,0xf694b443,0x07d5bba8,0x48cd150f, + 0xb4c1986b,0x02d31de9 } }, + /* 222 */ + { { 0xde79499d,0xa6bb9e1e,0xfd0fc2ad,0xf6ca8ff8,0x1a7d9356,0xbec0f8e8, + 0xe8f06327,0xbc3d1c9f,0x3b300beb,0x805c7217,0x413c181b,0x00420a08, + 0xf0ca9d01,0x9e9a167e,0x1aeeddd6,0x076c909d,0x8e3a8a72,0x64a1997f, + 0xa77b429e,0x3ce7f7a7,0x5c94d3e9,0xaac0fbf4,0xe6d48407,0xf37694a7, + 0xa91921e7,0xf56679e2,0xee1dbbd6,0xf23fe0f3,0xcbf9fa99,0xc7917566, + 0xe0f4d765,0x965860f2 }, + { 0x7fa5f79c,0xe734702b,0x5af2d26d,0x930bd426,0x6c73e0ce,0x45bd8b98, + 0x4ee44a2d,0x7dbe7bed,0x956c8a1a,0xc129e024,0x77cdf80e,0x6fdc05ac, + 0x589ca59b,0x70a6ba2b,0x999825af,0xfc484021,0x7a23f0b6,0x1d284b54, + 0x28a0a8af,0xb1da10a4,0x2b2af6d8,0xb1eb1b31,0x33935ee3,0xf051443a, + 0x8effa6ec,0x7a07eb26,0xd662654c,0x16ee4086,0x4549ee4c,0x7a7bc501, + 0x1fa98a52,0x65081032 } }, + /* 223 */ + { { 0xb67ed9b2,0x49f0e460,0xc36d93d2,0x0cda0fd0,0x88c75e1c,0xbb5963e9, + 0x614bc0c9,0x757bbe93,0x9a768605,0x9a9b8801,0x48edc544,0xa8b7e2af, + 0xb51a5985,0x9e77ed9e,0xebbf024c,0xdd025274,0x1545c636,0x598b6288, + 0x4800dba0,0x39bdaed0,0x81e2a23a,0x7fc20139,0x550cb4f2,0xdc66fd5c, + 0xb52068c7,0xad27032f,0x8169fa15,0xc9a0bcae,0x3a7ca8a2,0x60606f21, + 0x9862652f,0x98295046 }, + { 0x2e11c128,0x3e374600,0x0e6dca7e,0x80dfae5d,0xd9552264,0xe44016e2, + 0x880b7143,0xf65f88f2,0x526b881c,0xca3d28d4,0xdfb86afe,0xf9c59dd1, + 0x4c74f958,0x548860c2,0x9cb69f4f,0xd06ea43c,0x7334ecec,0x5343c9ae, + 0x35329713,0x5cc2ccd6,0x5f3a6c0c,0xa95ff403,0xb372653b,0x2e01a1cc, + 0xa250523d,0x31510fdf,0xa6227eb2,0xeee538e2,0xca23cd10,0xeadfc8a0, + 0x3e78f54b,0x4b7e6e1b } }, + /* 224 */ + { { 0xdb5f928b,0x79c9076f,0xb7347cec,0xe6250bb6,0xac00ec41,0x54b67798, + 0x9d9619c7,0x900d20ba,0x59e4343f,0xed42c0d0,0x451935d7,0x3df39e85, + 0x64f701ce,0x26391182,0xe1f87aac,0xce8f2554,0x65f91aaa,0xfddd6789, + 0xa324539f,0x96cd163f,0x4bace995,0x5c815f2c,0xa94f9ea5,0xd78c8c2a, + 0xef24e455,0x7ab2aff4,0x1cddc26a,0xf0ed6409,0x00ca2822,0x954a420b, + 0xd3297658,0x0611c4c5 }, + { 0xa9e81829,0xf192001c,0x08a282cc,0xded33320,0x8f9ded9b,0x0bfd7de1, + 0xb7889003,0x6793ac0d,0x3577a5dd,0xbb00d91d,0x802d3c2b,0xe17a23a7, + 0xfb549014,0xff95f88c,0xc71b6e07,0x7cd1bf4b,0x23588c8b,0x2e3b24a0, + 0xa4112076,0x9b5335b8,0xc4056d30,0x2481c05e,0xe916a1b5,0x55c7410c, + 0x850179f4,0xbbe03271,0xb3cd1208,0x15e6c177,0x90cbfe50,0x509a24c0, + 0x1c108566,0x82079529 } }, + /* 225 */ + { { 0x1c7d353e,0x5d2d3cff,0x7de0ce3b,0xd5e7eccd,0x6ca87635,0xb4b1075f, + 0x25f9ad3e,0xda8404e0,0x205cb5ae,0x6b963e89,0x09f221a1,0x9e5ee0d8, + 0xea41aca4,0xd64c85d9,0x34442a34,0x6a46c4e9,0x3cf655a4,0xac6ff97e, + 0xe5417d7c,0x76565c1e,0xeebf9c4c,0x681009a9,0x88da6388,0x95b61d39, + 0xf6b472c6,0x6402b46a,0x0b7f1171,0x1fde5165,0xbe0c05e3,0x94f8f273, + 0xa88344a7,0x7487b036 }, + { 0x9c3e2370,0xa860e575,0xf8048719,0x19d58193,0xa6e2f9aa,0x3a0dbf3c, + 0x6144719b,0xb6c7e959,0xdeffec21,0xa9049c74,0x3f50cebf,0x8ba064b2, + 0x49a1de15,0xb12822c0,0xb1d527f2,0xb654b7d9,0x0ffd0430,0xc470859d, + 0x4f05446b,0x37c74a67,0xa3add995,0xe553251b,0xe33533b5,0x4a3ed6cb, + 0x27e419ce,0x2f2f44d0,0xa5d1b979,0x2d84ee82,0xdb6fa69f,0xcc76b123, + 0x21fa3bdd,0x834f85c5 } }, + /* 226 */ + { { 0x2ce9b31a,0x329347c1,0xfe3fb3b7,0x1d88522a,0x52ff90fd,0x4bcefb4d, + 0x2b1a081d,0x53b17386,0x2a411f08,0x538c11ba,0x141b603a,0x7895b93c, + 0xb10bd741,0x2993b9aa,0x09912986,0xccbbd046,0xeea0aba5,0x669fafb0, + 0x35661897,0xd4844622,0x367ffa54,0x4a63b89c,0x1c3478da,0xcbad5d1d, + 0xaa6034f7,0xc5339227,0xe61b1391,0x0e6d705f,0xf74ff515,0xdd14b660, + 0x5332b54c,0x639d8b0a }, + { 0x162217cd,0xfa423162,0x811c28e6,0x2e0e4a2a,0x21766dc0,0x68d9ce18, + 0x046a06ef,0x51263739,0xdde92101,0x44eea231,0x114298d3,0x0607c8f2, + 0x63d957e9,0x27f272ba,0xa5e8cae1,0xe7ce80cc,0x24f7a63f,0x5816ebe2, + 0x89673e34,0x4dece5a7,0x536babd4,0x13756a22,0xe3bf77af,0x644d61ae, + 0x2bcf98bc,0x60b2bf6e,0x29fa962c,0x3b0b59f3,0xabb50023,0xb0769a1a, + 0x0c75402c,0x40903136 } }, + /* 227 */ + { { 0x1670433f,0x84d2873a,0x25493dfc,0xc9394df6,0x80fcf89e,0xeb05a19a, + 0xdb297616,0xe39e4310,0xd9e63046,0x50742dc9,0x1de9ca9e,0xf31ad8c8, + 0xfb7b1d0d,0x86aabf94,0x1b3c82d1,0x36cda27a,0x39702d84,0xfb1a2ef4, + 0x46081299,0x280bfddc,0xd2396238,0xe4b2b48d,0x7b3c9353,0x2db2c2f3, + 0x12fb8a69,0xd5b5b317,0x08180474,0xf9b87a3b,0x1e952578,0xd8590986, + 0xf37a2bc8,0x80668eed }, + { 0xb39a0249,0xe2edcd35,0xb2f8aeae,0xaf230cd4,0x7223df05,0x295b15e4, + 0xe0e937f4,0xbb66982a,0x8cbc9162,0x019d2b72,0xcf49dca1,0x5c512ae9, + 0x630f07b4,0x11b491a7,0xa03874e9,0x48d4f34c,0x44cb7433,0xc1fd0ea6, + 0xf95b30c3,0x13f79ae1,0xed8b60ac,0x40362d4d,0x61ead81c,0x9e8314ff, + 0x498c3d28,0xed600dd4,0xc2521702,0x5fcb1c19,0x3a9c1f33,0x592329fc, + 0x1bde6ce9,0x04677548 } }, + /* 228 */ + { { 0x39233c96,0xee3de56e,0x80737eaf,0x868c409c,0x201abc68,0xacae11bd, + 0x2b486205,0x0f2cea9b,0x6f19056c,0xe32387e1,0xa5dc2a41,0xea75365a, + 0x12b4be86,0x76c29acc,0x8d63294d,0xa01fcab7,0x0cab9f24,0x81dbe88b, + 0xf414c054,0x76646e5b,0xcb96b7aa,0xfe111893,0x7664e097,0xb649f5b1, + 0x53fcf5a9,0xa196422e,0x0b7ff634,0x5978c9bd,0x3c229895,0xb5feb38e, + 0x0833c456,0x038a49fb }, + { 0x13e93257,0x35e3818c,0xa612741b,0x14cebc9d,0x7caac06b,0x4f6e9249, + 0x3daa1116,0x82278e33,0x4de2034a,0xe7cc565e,0x0a1ba630,0xbb7dc95f, + 0x66956fbd,0x81dd9f23,0xbb132dd6,0xc63e6319,0xfc241337,0x6e22b022, + 0x7e8beb1c,0x23848193,0xd8c938ac,0x83b1994d,0xa6bb5644,0xb54cfaca, + 0x06f91807,0x1a7cd44e,0xa8f8d9f3,0x1dd439bb,0x7f74a8e6,0x660c2a78, + 0x121b5660,0x4bb76e22 } }, + /* 229 */ + { { 0xe6354817,0x7a151e8a,0xf038b438,0x33d494ea,0x85958986,0x4c86c688, + 0x1dcbac12,0x72153827,0xc0edad06,0xf487af8c,0xe500e5d6,0xad33051f, + 0xd6e47f55,0x0a711b1b,0x8c746ad5,0xa68709a7,0x6402f35e,0x27f17262, + 0xfb30c130,0xc6d08efa,0xc06c7497,0x9ef1c041,0xdcc3e2da,0xd0c74ece, + 0x092e1073,0x30c5f96e,0x2aa12b74,0x0f1393cf,0x2107eb02,0x24584016, + 0x7b76f98b,0x8843d25f }, + { 0xedb2a83e,0x4e1501dc,0x2bb8d724,0xbcfe8fb0,0xd925df62,0x09020659, + 0x42ab6fc3,0x3c715dcf,0xa0f09dfd,0x73c05055,0xe3590aea,0x126745d8, + 0x76ff749e,0x5382f4d8,0xa920c663,0xfc69feef,0x9fd711ca,0xde160211, + 0x9075c4d5,0x4219c3bd,0x3ded6bf2,0x3800cbd1,0x6263a116,0x8c7ea0eb, + 0x7d264c37,0x35bd7958,0x7159c98c,0x56e22e45,0xfa7373b5,0x71bf2a2d, + 0x8935c949,0x0503f939 } }, + /* 230 */ + { { 0x71dad4f6,0x65addc66,0x024bea1b,0x238e4889,0xf605d3dd,0xfb76c8e2, + 0xb0d96b89,0x13d5f5de,0x6601b2cb,0xe0b5ba35,0x83e3d254,0xe37d491d, + 0x240c8ea7,0xe8860423,0xe91c99ba,0x374182f3,0xa87ad919,0x26c2caf9, + 0xf574f295,0x4b13040a,0x944000a3,0x5b9bced1,0x06df42e7,0x4ccc57be, + 0x4bd1089d,0x22e8ec50,0xdddbb500,0x0c53177a,0x9ecfeadb,0x690d31d2, + 0x176668f9,0x735778fe }, + { 0x843c1137,0x0f86ee3e,0x3f0b73cd,0x3c1c42fa,0x8ab20e3a,0x0e75679d, + 0x16242fae,0x6f95f1f4,0x39b092e4,0x7b88e11c,0x4c236ac0,0x1629403e, + 0x2dac02e6,0x66105f41,0x862e0632,0x74dc28a7,0xf3b23c8d,0x2118ffb2, + 0x0745ffbf,0x1182417c,0x4c05711e,0x49b55a04,0xcefbe4de,0x2c665b74, + 0x97bf7107,0x1cc4c01d,0xc54f0676,0xb2ca06da,0x7450d0f8,0xfc599daa, + 0x1a3182a1,0x52e637a6 } }, + /* 231 */ + { { 0x6bebc6db,0x481700f1,0xf9503d92,0x4a6b45db,0x5d153919,0xc715cd3c, + 0xe5ad2abc,0x942a1c05,0xab7b466f,0x36a82433,0xba13918b,0xba413bed, + 0x90f4e6ce,0x698a5624,0xf3f1f3ca,0xbb720da6,0x63471ab3,0x2116d41d, + 0x303d3609,0xe00d2227,0x463ba69e,0x7fd4cc00,0x62845fd1,0xac609e4d, + 0x80adc9c7,0x63603b2c,0x45fafbca,0xbf16fc9a,0xc4bc94ab,0x41007f7f, + 0xa74b1698,0x7c916b4f }, + { 0x78bac2d4,0xc1026f91,0x2601a875,0x8a2e8098,0x0073d640,0xad2f276e, + 0xfcc1fb88,0x443610c4,0xca6b291f,0x5727b822,0x88ec60fc,0x0645532c, + 0xed9ad48b,0x51e48899,0xf543f103,0x841b48b5,0xd591ceeb,0xa6ccb1be, + 0x9dcf5a8b,0xfc4adf0f,0xb347ddb4,0x3a7ca020,0xcb44c521,0xaa1accc2, + 0x0527c0c4,0x773b6828,0x7023cf50,0xaa374c10,0x6b74c926,0x733d1000, + 0x77a8d07c,0x1ff3916f } }, + /* 232 */ + { { 0xf997939d,0xaa218fe4,0x791583b3,0x3d4dfbbb,0x87f7560b,0xb3a7b5da, + 0x5da92c98,0xa9c02801,0x46666f4a,0xe1eb4aad,0x14ce9dd7,0x2eb17a51, + 0xef8f3076,0xf46a66a4,0x810e546e,0x900b45c6,0x4baf04dd,0xf7af2258, + 0x5c84d42f,0x3cc1c872,0x8e4c83de,0x3093f225,0x170d88b2,0x62fade41, + 0xac076e44,0xe19612e4,0x32dd141b,0xf48d7346,0x925e34da,0xc1b1f759, + 0x072b90c9,0x19ed1a56 }, + { 0x6c735473,0x9cf7fcde,0x6003bc3e,0xaab88e67,0xfb199bb8,0x12187cbc, + 0x9accccbd,0xbb730441,0xb0f65459,0x214aff3c,0x6f926282,0x6aec81a3, + 0x9f9d20b8,0xaa82cb32,0x5773cc90,0x82f3f90f,0xf62257e1,0x4af60e6b, + 0xbd4762df,0xf18b44bf,0xdb970753,0x3948b129,0x7c22c18e,0xc6e920e9, + 0x57be97ad,0x393d6208,0x46b637f9,0xe8d7382c,0xf1fed1d5,0xf6625ccb, + 0x68681599,0x6f31e0f9 } }, + /* 233 */ + { { 0x82b8f204,0xc45afe55,0xd358b54a,0xac0441b6,0xacd5f5ed,0x7213e7bf, + 0x139bcd93,0x1914c70b,0x96dbcbb0,0x714b4581,0x1ed35d21,0xe9297d35, + 0x6a3e1f20,0x8f640837,0x2f3cd705,0x150a8a9d,0xdcdd9f6d,0xfb36e801, + 0x5cf56d82,0x5a54eb65,0x92aa5a21,0x7610500c,0x3b089f03,0xd10d0ae2, + 0xc42b66e8,0x491b2079,0x0eee8d48,0x4af1ae3d,0x41556f45,0x137e4c28, + 0x63d8a7e6,0x875e3308 }, + { 0xaf6c0acc,0xdc80fddc,0xbb1e7c08,0xd5ad1e66,0x828585ad,0xdc717ae1, + 0x275c7da6,0xbdc54340,0xd26b9e15,0xf4b4c852,0x6a05fa50,0x5f0a1fbf, + 0x817bcb32,0xc6f81e47,0x70ff2e1d,0x2cbd4328,0x67c7f7fc,0x8a249016, + 0xb585a6c4,0xd045acb7,0x4666c057,0x2e972ad4,0xe6d7d63d,0xc74d87cf, + 0x0e274144,0xf7067d87,0x8b2584ae,0xb2ca157a,0x75f0fdeb,0x495c5bfb, + 0xf386e009,0x5abb0581 } }, + /* 234 */ + { { 0xf0c97f57,0x8be62d2b,0x962f28c7,0x0fe04871,0x47b50abb,0xc548a467, + 0x44fa09ed,0xf6b26e03,0xab05a96e,0xfd44c6e3,0x70e6ae82,0xedb0032c, + 0xd7e4899d,0x28bd402b,0x9b7c11c2,0x43f2e963,0xce913716,0x0ec3fc0e, + 0x02fd0f8c,0x769b8bc9,0x7cabc3ac,0x9d9cb3aa,0x06924cc9,0xe88a8892, + 0x42609014,0xa51461aa,0x962e79e0,0xc7f4aa8b,0x8b1b3e80,0x4ef0210a, + 0x1bfee4bc,0x70544680 }, + { 0x121901c1,0xfab3d713,0xfead54aa,0xe90a2627,0xbc08ba23,0x64f6d285, + 0x36ec227e,0x8d993015,0x06c191ab,0x99a16ab9,0xf649ce2c,0x86b1cf5b, + 0x66be3a80,0x59206759,0xccba2cf0,0x18836279,0xeff53486,0x2c157b87, + 0x4b223af2,0xbfac9896,0x0aae7a57,0xcd0fd4f0,0x63218a80,0xdaddb940, + 0xdf88f14e,0x3844bb79,0xb71ed9fd,0xc1b3e3d4,0xd6205036,0x6c634a13, + 0xb8680a6b,0x6f56aecf } }, + /* 235 */ + { { 0xd9205c5d,0xb01dc803,0x67123929,0x68955f7d,0x9d9b6565,0x3debbffd, + 0xd3b1acfe,0xb844395e,0x6094eeff,0x04328b21,0x22991feb,0x6631ffa8, + 0x190dd075,0x0dde66e6,0xe8577c05,0x75b03c55,0x91722407,0x6c91ce5f, + 0x8ebb3a3f,0x9a288a40,0x058a1396,0x1d376f8a,0x9a6e0676,0xf3a59457, + 0x7b71d288,0x103029c5,0xb44c30c0,0x0843f428,0x730e0b9c,0xd8e6aff8, + 0x4ed644ad,0x7b6be811 }, + { 0x3d3aa54e,0x3ec38e4a,0xd83d509a,0x10233943,0x243955e2,0xf84aa621, + 0xf51d3d44,0x29104717,0x7eca4e37,0x62d2442c,0x85fa55de,0x8c5a523d, + 0x851da1b5,0xc6f5ccda,0x20001468,0x044bcaa8,0xe01702e0,0xf7501e68, + 0xe6a0acec,0xf0819359,0xac0ef0b2,0x33dda6ad,0xfd964f01,0x97aeedc8, + 0x530b90d8,0x48dacd0e,0xb84122eb,0x4c5fad6f,0xd700a1de,0x2284ec1e, + 0xdbca5474,0x86f9a835 } }, + /* 236 */ + { { 0x450cc69f,0x0e1d9055,0xc9edf98f,0x50eb14bc,0xee7eba01,0x1bb94e77, + 0x998f8e53,0x5f7a6737,0x1b16eef0,0x588384e3,0xd85c5e15,0xbb928723, + 0xcbd952aa,0xfe51e345,0x7e241674,0xc5d0ee28,0x100182f0,0xfdc146ef, + 0xe7f5be2c,0x0f739e92,0xb656bd3e,0x501ab3af,0x5168e289,0xb1552dde, + 0xb8ee104a,0x940dfe31,0xc4304475,0x42923603,0xc460a913,0x9306f114, + 0x03b51f86,0x5bfa9faf }, + { 0x107b258e,0x2a23f52c,0xd66341dc,0x989e82bb,0x823cff1a,0x54a3ced8, + 0x719b491f,0xf45b7794,0x2433dfb8,0x898c2218,0xc49250ee,0x0f9dd91c, + 0x4fa17655,0x50c2a2ae,0x2c327f45,0xf7aa1ce4,0x583b1e41,0x13a15ad6, + 0xa1bfad9e,0x9aa0d5a5,0x8e1fbdcd,0x9b1caa28,0x915f7f87,0xaf9283b6, + 0x87e81a1e,0xc10e4e0c,0x1080d296,0x04fdca56,0x12755bd8,0x6acc9616, + 0x828feeda,0x1b1266aa } }, + /* 237 */ + { { 0x774ee49c,0x4ebc0a00,0xcb6237d7,0x776f6852,0x5df938a3,0xfc0544ac, + 0xb6fbfbbd,0xc3388ec8,0x745f2eae,0x84ac8bcd,0xb1ece937,0xa9c56609, + 0x7de8fa13,0x656fb6ac,0xa532b871,0x5f8ded74,0xaa889f09,0xab0d428b, + 0x10b7aec2,0x43b27f28,0xfeecb34c,0x26426e1e,0x9e89c2db,0x44431b6b, + 0x39211090,0xaac4bc5d,0x4fd81058,0x926f7368,0x471ef60e,0x452fa691, + 0x218d7a23,0x33517fdb }, + { 0x593c4a36,0xa9c33f46,0x36b1a9ee,0xac69d718,0x4277beec,0x55a20c1d, + 0x7e4f179c,0x3e8ca24e,0xd46d88a2,0x57373369,0x730702f8,0x71ceb1cc, + 0x35eed574,0x8b184d97,0x0704cec2,0x7f4517a2,0xd7062a53,0x7f129d18, + 0xb1d77e1c,0x07a4571b,0x8350d8b2,0x774ac309,0x61fab8ef,0x27b2919f, + 0xb5dd801b,0xa7c4cc13,0x1434591f,0xe7e6255b,0x5a3592b3,0x349937b8, + 0x30c77549,0x31fac63d } }, + /* 238 */ + { { 0x04913fb6,0x2ee8cf1b,0x1769a6b3,0x7e401350,0x783e61f0,0x790ebb71, + 0xe27f2ffe,0x1e5107f9,0xedaf89bf,0x124ba67f,0xe58de68d,0x189200e1, + 0x6df5abee,0x962732a3,0xacbeb4aa,0x72cc37cf,0xe93c5a76,0xb0c5fa96, + 0xde63393b,0x4c2a317c,0x830b2d6c,0x97f65e67,0x1be5b96a,0x4afc3504, + 0x730ce66d,0x0bf40a60,0x9340d84f,0x96a1ba79,0x07626b08,0x3ee18254, + 0x7ab0cbf5,0x01db35db }, + { 0xac0efee2,0x6e0fbc2d,0xd71dbb45,0x8406ebcd,0x19b69abe,0xe72bde3e, + 0x37e01822,0x49cb7e61,0x11458b4c,0xcbb8c01c,0x687c5d63,0x420b4847, + 0x454c6776,0x1847dfa1,0xd1839d18,0xbede911d,0x278df046,0x1b9dc9c9, + 0x881a336c,0x294bd62b,0x93e77adc,0x7f096879,0x43ce3ba7,0x7ac90665, + 0x7764eefc,0x148695fd,0x9ac465cf,0xe0c20f0b,0xa6e2cdb1,0x636e8d28, + 0xd755341d,0x7b6ba98c } }, + /* 239 */ + { { 0xc1881ab4,0xcb1d9e03,0xb3168c88,0x19c25d55,0x282364ce,0xa82d3d47, + 0xf161aa24,0x95994390,0xe1ebb2c9,0x7838bc00,0xbdec7a75,0x8fd5dfcc, + 0x4ff7220a,0x4dd203c2,0x0efeff48,0x5ec173b3,0x16428b35,0x99f1d2b3, + 0x056e813f,0xc06bd9e5,0xc0b319f1,0x929172ba,0xfd223b15,0x6ae0e384, + 0x98d091ed,0xbd01059e,0xa654648e,0x6b3168e4,0x3375e798,0x2211447f, + 0x71eb4508,0x47e81019 }, + { 0xbc8c290d,0x7045d45a,0x810fb33a,0xa33d1355,0x46fbbf2f,0x2baf0092, + 0x385c7cd9,0xacff3f1b,0xe161985c,0xc5b150ec,0x2a888748,0xc6ee0a7f, + 0x5e88dcc8,0x9d888c8e,0xccb86443,0x4dd735f2,0x3c40f6f2,0xcc1e13b7, + 0xf3fed691,0xfc3a25ff,0x257ee5c7,0x4cb43b17,0xf32db135,0xaa654f93, + 0x02dff2d3,0x44f58d0a,0xa8ca6394,0x78e3f188,0xf3e86697,0x39646cce, + 0xe0dce87b,0x785b1902 } }, + /* 240 */ + { { 0xa92f9a20,0xfcce2361,0x9d64540e,0xb7bdca87,0x1d00d7c5,0xd4739a85, + 0x2e97c926,0x067ac8dc,0x78da6a8b,0x2aea3ffe,0x63c51b69,0x6828bf54, + 0x7155141a,0x76f1c479,0x3977d810,0xf4bcbef6,0x541bce7a,0x75bc4949, + 0xd17041a5,0xe01f4066,0x87755eaf,0xd282d5bd,0x59e7ae80,0x6e2107dd, + 0x382ab36f,0xaa56e166,0xb9d1d634,0x65ee8ef6,0xce4ed844,0x99a2160a, + 0xb7712c27,0x6557c367 }, + { 0xd75b6e52,0x561b0268,0x118d0e89,0xb0813640,0x6a2eb1ae,0xcff53330, + 0x6d090894,0x4e462226,0xb5fc1d48,0xbb351227,0x57a3062d,0x9365ea07, + 0xd66e2dc5,0x4caca37b,0xb9095887,0x220d7d23,0x8c4473bf,0x9c0fd393, + 0x6787da4f,0xadff370a,0xd057f4b8,0xef0aebcc,0x1173f33a,0x205e744c, + 0x925a26b4,0xb8d1f0a5,0x722fbbfd,0xa9364f49,0x8227d284,0xc891ae77, + 0xa0e08ab4,0x15c40d04 } }, + /* 241 */ + { { 0x2a0e18d1,0x9baf169a,0x4c0327c2,0x9971c017,0x7bc262ce,0xd81a323f, + 0x818ff379,0x2099db8d,0x4cd3c330,0x663f663d,0x011a0553,0xef5325c3, + 0xf980a470,0x9cd70bdc,0x1c9ed070,0xe64452d1,0xac676e13,0xafbf43f4, + 0xae85c2a5,0x97bec0a6,0x470490c4,0x2faae550,0x491e6ba9,0x0ab97a87, + 0xaafa9914,0x4055f537,0x36726557,0xfc95adbb,0xd119d6bf,0x646343b9, + 0x9d341e37,0x788e94a0 }, + { 0x9c53461a,0x053a6fe5,0x08e3b6ed,0x75ec897e,0x0768d939,0xa8f5d2f3, + 0xcc213d4f,0x9bd6bff6,0x05b0147c,0x590c7b41,0x7c7b8169,0x20a3628b, + 0x5bce78e9,0xc66a086e,0x4dec1d8f,0x3dd4d282,0xc19dcce9,0x890acf44, + 0xd8435a7e,0x6632d875,0xea6381b2,0x590167c1,0xf0dcc128,0xb2259797, + 0x46f8d463,0x91a612b4,0xc15efa39,0x42185d78,0x119f6788,0xdf55ec37, + 0x780dea93,0x91b19cc6 } }, + /* 242 */ + { { 0xcb5d8b80,0xebf2709d,0xfc35660e,0x03b96182,0x055ef969,0xb873d991, + 0xe47c4342,0xd1ea4b4d,0xd54f8867,0xcc4b9244,0xfd8d77ef,0x93b1a2ca, + 0xe8c1f563,0x068d24e7,0x49973056,0x5f5fabb6,0x0542374f,0x83248c50, + 0x3f38e913,0xc36de2b5,0x7bb680be,0xed07e8eb,0xd8f313b5,0x964813d7, + 0xafd2d392,0x7bb6a069,0x0848a31a,0xc06d848e,0xe4f0c325,0x6867fb2f, + 0x067343af,0x3c2ba834 }, + { 0x9d3ad63b,0xab62d775,0x59e0eb1f,0x3f9cab97,0x3885e117,0x70332a63, + 0xe20b2f9e,0xf22cafce,0x49eca947,0xb529ba7e,0x6228d88d,0x24954216, + 0x39239561,0x80ea23ec,0xd4370644,0x1b8907e7,0x563e4e44,0x4b7fa455, + 0xb2a4b0fa,0xcca9829e,0x48060792,0xd0a720a4,0x246991ce,0x8ccdda0c, + 0x348d086b,0x37a2325b,0xf60aee13,0x566ed509,0x147f253f,0x3d30e091, + 0xc1073bd8,0x1fa627a5 } }, + /* 243 */ + { { 0x42478fd4,0xa11222a2,0x670b2000,0xacf4c6f1,0x8359c6de,0xf71bb04f, + 0x7b93cdbc,0x618e2829,0x230db60b,0x96e1bae3,0x965b3b29,0xf17fd3b4, + 0xbc7055dd,0xa58639c6,0x4b817d7f,0xc3ea92ed,0xd23b08a4,0x9082b2a6, + 0xdc17010e,0x8471228a,0x20e89d97,0x753b9e46,0x03ff77c9,0xcf7e4f97, + 0x2bbe60e5,0x6c3f8245,0xb80e017d,0x9e432cbc,0xc0a45edb,0x150a5acd, + 0x4798743e,0x67b8bd05 }, + { 0xf4797cf7,0xe66079b4,0xd03fde02,0xe31c998a,0x54caaef1,0x5aa3763a, + 0xf7649711,0x64d9a1fe,0xaf29b1a7,0x7ce0dc73,0xfb66ca93,0x6661b083, + 0x32fb6a78,0xbf4d74fe,0xdf00a561,0x25f6ef09,0x831d1159,0x2bc4383f, + 0x536bde37,0x6d5cc10c,0x882cc65b,0xd4945f9f,0x451a99b8,0x81f48f13, + 0x6bac11a4,0x140161cd,0xf18a4a0a,0x9d94d4ed,0xa467a824,0x65363165, + 0xa4c9aedf,0x74297aa9 } }, + /* 244 */ + { { 0xe21124ba,0xc49758a4,0xa87ffbd2,0x99bd8198,0x3d6638a8,0x45fbcdd1, + 0x15f7bf76,0x94645ff8,0xc4e6d57e,0x5fa6736f,0x92e61db9,0x1eae6475, + 0xcbdf944a,0x79575c0c,0x25b31d74,0xa3d13047,0x4cab5ae6,0x7881df22, + 0x1a2887f2,0x8dbfd299,0xa26ac459,0x23d07590,0xd8661d4a,0x2e589852, + 0x8a0140f7,0x37b5c13b,0x3fb3782a,0x0f94199e,0x1bc14e90,0x722aa059, + 0xd55bbb12,0x89aab7ba }, + { 0xd656bdc7,0x8b345a96,0xe176cd3b,0x43bdc8af,0x32d64c43,0xd69518b6, + 0x79b82b41,0xfcf364a7,0xffb0cf82,0x907b344e,0x5101287b,0xf3d0c83c, + 0x34cd90ef,0xe9f26a59,0x07082b5c,0xe5f5aaf2,0xece7c165,0x4eb72c75, + 0xbe986cd6,0xe9590a81,0xff1536aa,0xfeef498f,0xa8263d5e,0x04560243, + 0x54ae872b,0x940be14f,0xe3207686,0xbee7bcc9,0xc1bc4d7a,0xd496a27d, + 0x5940ab46,0x002dc297 } }, + /* 245 */ + { { 0xb69d60c3,0xee533937,0xfe972755,0x260be552,0xc0c725a6,0xb11fb78d, + 0xcab2e7c2,0x6982c27e,0xee2322cb,0x4bceedd9,0x122704f7,0x952b19ed, + 0x854a6165,0x2df4c285,0x7b192485,0xba40b5bf,0x0119f52a,0xfcbca950, + 0xe5add86f,0x7467d1cb,0xd9d0f2c1,0x9bf536fb,0xb8d4ebc9,0x3c296e34, + 0x05a81317,0x0495f8f4,0x73335f76,0x8c59e8d6,0xe0542122,0x0b53d324, + 0x3c3bda73,0x4d564535 }, + { 0x7e5c0877,0x7322f800,0x0ca9a764,0x481b43e6,0xa2c12716,0x231f4f4b, + 0xed3136c2,0x09596857,0x38db30de,0xae826322,0x99908ebc,0x652fad40, + 0xaf0d231e,0x0b8d1814,0x09cbc349,0x2680c54b,0x4bf3bf8e,0xfd4562f3, + 0x092b595f,0x2985090b,0x5e15fc34,0xe6f39ca4,0xbc378168,0x70175191, + 0x845a4a87,0x906944b3,0x82a1541a,0xacc6d74a,0xb155c8b4,0xadc9bab3, + 0x77306c62,0x1f2f89ce } }, + /* 246 */ + { { 0x9affefdf,0x8253ef41,0x4cf9256b,0x05d7ece5,0xb444e483,0x377002f2, + 0xcba5471f,0xb189755f,0xd5cbe015,0xc88483cb,0x6a0b8429,0x254f7c69, + 0x61f3f61d,0x18850bd4,0x0a247157,0x7ba21089,0xd92eeb0d,0x35abbc2e, + 0x965dec89,0xfb56cabe,0xbc55684a,0x9da23724,0x6a7a7492,0xd8ba396f, + 0x2ef4ba46,0xfcb90db7,0x9909b27a,0xdd234fe0,0x76f4366e,0xbdf3c164, + 0x17e50d47,0x09c8097f }, + { 0x60050c07,0x6a04b140,0x43a8e37e,0xc29e8318,0xbb55e41f,0xcb9429b2, + 0x2ce60e3a,0xed2fea5a,0xdb9d82f4,0xdc7b1ff3,0x687d37fa,0x48ebecc3, + 0xecb07539,0x79153e32,0x57075692,0x6a60054f,0x800759ba,0x3871cd0c, + 0x30922df1,0x17a7386f,0x83357b7c,0x4e9fc59e,0x39415186,0x1d26b3a9, + 0xd34db889,0x912a0222,0x59fcdb71,0x6672fcf4,0x44ff3036,0x5a3f268d, + 0x6911e16c,0x6f113ed3 } }, + /* 247 */ + { { 0x1836f1c9,0x52a9df59,0x4232307d,0xfa6519f5,0x5ded285a,0x8406c701, + 0xaf627f75,0x0a1545ca,0xace0417d,0xae1111ee,0xa6113443,0xfb28bdf6, + 0x52dbcbcb,0xde9ef0ab,0x7813e658,0xe9dc181b,0x99127225,0x0b1dabdb, + 0x22814c59,0x5f0598e3,0xd934ee7e,0x5c3b966e,0xb99ba4bf,0x4eb84eda, + 0x3c1b55e7,0xb2919a34,0x94aa860f,0xa9addb49,0xf6811ff6,0x1b7220df, + 0xd1a183e2,0x6636a23b }, + { 0x20587283,0xdf5d5a2d,0xef07fc5d,0x0b3822c9,0x0ef6de38,0x1786bd55, + 0x25d1671d,0x163cf907,0x1cdb1def,0x74bf971f,0x0842fc4a,0x5749e830, + 0x27f854f7,0x0e2edbc7,0xbce24acb,0xbb27bbda,0x05bed08d,0xc1b19cec, + 0xf7c904bc,0xaada123e,0xd89982db,0x02429f1b,0x65f6e632,0x49d3616e, + 0xee59fd32,0xa3789fa8,0xfe9f29f5,0x160ba3ba,0xaf5378a0,0x0f2d3b61, + 0x73c2a6f8,0x7aeecc76 } }, + /* 248 */ + { { 0xdc43b0db,0xf3a4757c,0x98119cad,0x3d8a4e85,0x4616c156,0xf8095bf6, + 0x4f533e97,0x3e2a07bc,0x39cfc5ad,0xa9824367,0xcd68052c,0x18a6ba3a, + 0x8a1cec66,0xbd60e590,0x02b1b695,0xae3841a5,0x190a195b,0x986dff12, + 0xad31fd9b,0x2df2beac,0xcc728f7b,0x7d893224,0x0cf0a992,0xc38ea738, + 0x586a44ea,0xa8439a80,0x1615f03c,0xede7f7f0,0x27a1f885,0x48249908, + 0xb78a7645,0x28ec4006 }, + { 0xa2fe0009,0xe1820c2e,0xf13874e9,0xe11ba5d2,0xc524db52,0x97522454, + 0x7fede529,0x4d477426,0x9b2500d4,0x01d3419a,0x1869244b,0xce08a492, + 0xdd1be1b9,0xba169023,0x32a301e0,0x242c3e54,0x70906788,0x9b56f7ba, + 0xc74a8cc4,0xf0ad2a09,0xd76f9439,0x99cd1841,0x621fb60e,0xeddafe0b, + 0xbc397634,0x056bee54,0xff7f0a84,0x4653f860,0x2011c0af,0x6bd4876f, + 0x0c9525c3,0x134f4cc7 } }, + /* 249 */ + { { 0xe938dff4,0x9621a3ec,0x486a79a3,0x7d101a7b,0xde950537,0xf2c4ef97, + 0xe65d87db,0xf3184099,0x373b8cfa,0xb89c7ffb,0xe842916e,0x68baa505, + 0x4ebea764,0xa790fd09,0xe592892b,0x679df6d4,0xfcfed741,0x2023331c, + 0x9880ff21,0x0bf4efd2,0xd0344501,0x7ca78ddd,0x342858c8,0x2cb09ecb, + 0x2575487a,0x9e5eb6dc,0xebcb0491,0x50675a15,0x7381d471,0x09d2e74f, + 0x83d3d6f4,0x6ea37829 }, + { 0x4e5cc40a,0xc65c094b,0x1af37dfb,0x7a2e3f6a,0xf9026e44,0xef677e9d, + 0x93880f53,0xb7878c95,0x7f644aa9,0x4aa30b07,0x2f208c3c,0xa0c51683, + 0x658d663b,0x7c0277ae,0xae1d9130,0xef0b3c38,0x695c3ea4,0x302f37a7, + 0x6a0c5e0d,0xe004c1c5,0x20cbcf9f,0x9fd495c4,0x568a0e7c,0x706d5b9d, + 0x59286454,0x8b225dff,0x8d9a709c,0x527d4465,0x87c08d68,0x47c558da, + 0xbb4ef07d,0x606ee6e6 } }, + /* 250 */ + { { 0x57c621f6,0x02d99fc7,0x7fe83d48,0x292e40c1,0x9ef199b0,0x1bdfc7a1, + 0xe62c7666,0x78a04102,0xe6738753,0x16cda370,0x1e3a65af,0xbc81974d, + 0xf78fe209,0x19742048,0xbf5981c6,0xc83a058a,0x9c89702d,0xf26b2434, + 0x9d1a678a,0x988b2f1e,0xff29ae29,0x472bf9b0,0x1d7cf5ec,0xa143e398, + 0xb268ddd8,0x9c9d7e45,0x5fc4ff76,0x166cda55,0xa4aa7673,0x6044cdf0, + 0xe9148707,0x49dba6f7 }, + { 0xa758e37a,0x20e47fb2,0x2d8eaf66,0xaf6b31d7,0x6f9c2210,0x352ad5f9, + 0x90efc32b,0x0093f727,0x41e4b264,0x435c99dc,0x05b15795,0xbfa878e0, + 0x0e673575,0x99c520a4,0x87eea759,0xca682594,0xf12a348b,0x029f7b81, + 0x2aa2ce35,0xa547cc18,0xead5e2c5,0xa11d874b,0x55682cdf,0x9af0349b, + 0x8bbe8e66,0xf86ebfea,0xf55394ab,0x3dab8782,0xebc8eb8f,0x458bf797, + 0x9b7de78c,0x4890a7a4 } }, + /* 251 */ + { { 0x8da995f6,0xd7299689,0xec6156ef,0xd39eaae7,0x356a82d5,0x6959040c, + 0xc135bcfe,0xb2046b21,0x0f595c78,0xea720b64,0xe7c5fb40,0x02824efa, + 0x0edb3bfc,0x97d8fd4c,0x79f24ebe,0x12f02905,0x187ea6b9,0x16fc47cf, + 0x789d5c23,0xc219fd27,0x89263ecc,0x233a6b6c,0x8b6d30a6,0x823634b2, + 0xc9b33680,0xca352e25,0x40c77456,0x9388d6ca,0x3c92065b,0xf8e55b0b, + 0x02439a76,0x5c17474b }, + { 0x8aaccab5,0xd888e7c2,0xaaced05b,0x18027836,0xccec0f65,0x185b877d, + 0x125c2882,0x93cadc1c,0x67fdc54c,0x45df540a,0xc2788a33,0x4f3c86e2, + 0xe3a0fa2c,0x3e874469,0x273983cf,0xc59daa47,0x4a96d8a5,0x3063c48b, + 0xc2e58915,0xc38d2bcf,0x84e428c3,0x90e78b87,0xf0c4fd53,0x900a292c, + 0x941e6005,0xb7f92db7,0x6ca53a1c,0x95679241,0xb1ab0fa7,0x35f6f31d, + 0x7b58408c,0x5d675eb4 } }, + /* 252 */ + { { 0x870c6025,0xaeee1a77,0x91a2dfca,0xfc4a23b7,0x386b64c4,0x7b0e60c4, + 0xe5ae72b1,0xd5d5b17d,0x9eefa212,0x6dfc88ac,0xd4038b96,0x4feaefbe, + 0x8e2d2ecc,0x099ac356,0x012af207,0x548ea612,0x89c31218,0x4ffed9db, + 0xe0e67331,0x1c1e91c4,0xaf8300e0,0x009bb64f,0x6773c3be,0x8780501c, + 0xc08219fa,0xe0cd6ede,0xf81b06ff,0x7c055e07,0xe080b36f,0x82b63f9c, + 0x0a9feca3,0x02fccbaf }, + { 0xb47cac61,0x9991d4d1,0xab86e12c,0x2e9d1687,0x2b94f042,0x8c6855ec, + 0x48e648e5,0xca400519,0xef89ac57,0x9ba91fb2,0x1be792cd,0x4f419206, + 0xbd0f1e15,0x82d221cb,0xfc444019,0x062eb13b,0x99790fdc,0xf3a97c32, + 0x6067a64b,0x4e796d94,0x6d23775a,0xc46dd300,0xed7f0f23,0x8672c4d5, + 0x3b4f63d7,0x821851dc,0xd26273f2,0x50a3ae0c,0xeac60f6f,0x800e58fc, + 0x13845545,0x56f1e456 } }, + /* 253 */ + { { 0x32c24f3b,0x01ccb3f6,0x06d817e6,0x99eb1c7f,0x6aa26776,0x8dc640bb, + 0x0845d5e0,0x7838affe,0xf81a79a8,0xf34fecb1,0x3e6819b0,0x6a2e282d, + 0x8237a4b8,0xc4b977ce,0x87636439,0x0f46b3db,0x97970497,0xa465f540, + 0x8791be43,0xd7e08762,0x34198ec6,0x00220b6c,0x093d94bb,0x57b38637, + 0x29d690b2,0x84012e16,0x20aad1a4,0x02ec9db5,0x85dc34e3,0xafee2fc6, + 0x25500cf8,0x911d1936 }, + { 0xf5e5af5b,0x13b1bd58,0x7b6a22a7,0xa7ca263b,0xf3af2adc,0xab6bec4d, + 0xa04420bd,0x16651e59,0x4ba36c11,0x3b448b3b,0xff424310,0x3c62bfcd, + 0xf1a96cbb,0xde15c4a5,0xe4d1f980,0xbe0ad8a1,0x36673a3a,0x812bd14e, + 0x9212acdd,0x40303af6,0x576095ce,0x8f6dab9c,0x107f5ca5,0x7df1882a, + 0x8896a3b0,0xb903e63c,0xd863b3f0,0xf5048544,0xc09887de,0x5e5019b9, + 0xa0f53865,0x2be744fe } }, + /* 254 */ + { { 0x5b50f324,0x054cd05f,0x1ea3c7a2,0xb9b1eb24,0x7ff8e6b7,0x4a858a5c, + 0xec040882,0xd83902fe,0xd0cba9bd,0x72b26494,0xb29c9e1e,0xd0176f90, + 0xcebadb81,0x05d4eb02,0x372b8bfc,0x874405b1,0x79ead190,0x5c412881, + 0xec2b48cd,0xd44a3dd3,0x3f4d5033,0x84499a77,0x564c3a09,0xb37b38cd, + 0xf42e803b,0x80e99497,0xb8f518b2,0xc07b47a0,0x3568fde4,0xc710e3c5, + 0xcead0e7a,0x735f542f }, + { 0x38380039,0xcaa9a171,0xf74d19c8,0xadfafe17,0xccbc1a8b,0x92d4393e, + 0xfe029705,0x3c5dbf39,0x930e9b36,0x4552b5ab,0x2afd494a,0x7ee63032, + 0x3f02ac43,0x826a9ad7,0x99356298,0x98c53562,0x7342bb39,0x0c869f87, + 0xe4f9b79a,0xd7510020,0xd34789a9,0x6361d1a4,0xcfa85637,0xf0ded5ba, + 0x88ac07e4,0x407ee73f,0x09ef1cbd,0xfac7d03f,0x4d475bad,0x25d697cb, + 0x14bd399e,0x1e984c9d } }, + /* 255 */ + { { 0x4850c817,0xc76d0561,0x3489812d,0xb08a5b19,0x5e58cbbe,0x7273d154, + 0x4be61e5a,0x8900b5fa,0xd7aeb8e1,0xaa088691,0xd35a3d4b,0xe66666af, + 0x57ec7d3d,0x38a2c199,0x668d6f5c,0xa0648e8f,0x7adc1746,0x1f9fc92c, + 0x843065c3,0x23a116c0,0x61e6ae69,0x36370a20,0x2aa47e73,0x626c3736, + 0xdeff6d84,0x540c25f2,0xcdbed2d4,0x9804824c,0x039a9492,0x4b5bfce0, + 0x76942e01,0x6c474a56 }, + { 0x7d88e3a1,0x3aeb9a41,0xc484742a,0x105d3c88,0x3fe61131,0xe59de8d1, + 0x1a869e8b,0x148f5b6b,0xaa75d90a,0x7a8abc59,0x62146013,0x2f0c9bc7, + 0xc3824cd9,0x43faa747,0x6a5d0b92,0x81763a18,0x9bcbaebc,0xbbc341bc, + 0xf745d1dd,0xe1813160,0xb75ce5f4,0xa53ce52d,0xd50de4c2,0x15eae66c, + 0x75d7656d,0x5ed8996c,0xc4ca552a,0xe4ff5711,0x3c5305b4,0x215e985a, + 0xfa1ba2ce,0x6b258954 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#endif + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + + err = sp_1024_ecc_mulmod_base_32(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[32 + 32 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (32 + 32 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 32; + + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_ecc_mulmod_base_32(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_1024_proj_point_add_32(point, point, addP, tmp); + + if (map) { + sp_1024_map_32(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 32]; +#endif + int err = MP_OKAY; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 32, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_32(point, gm); + err = sp_1024_gen_stripe_table_32(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(point, gm); + +#ifndef WOLFSSL_SP_SMALL + err = sp_1024_ecc_mulmod_stripe_32(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_32(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_32(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_32(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_32(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_32(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_32(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_32(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_32(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_32(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_32(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_32(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_32(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 32]; + sp_digit tx[2 * 32]; + sp_digit ty[2 * 32]; + sp_digit b[2 * 32]; + sp_digit e[2 * 32]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 32 * 2; + ty = td + 5 * 32 * 2; + b = td + 6 * 32 * 2; + e = td + 7 * 32 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 32, base); + sp_1024_from_mp(e, 32, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32); + sp_1024_mul_32(b, b, p1024_norm_mod); + err = sp_1024_mod_32(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 32); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_32(tx, ty, t); + if ((e[i / 32] >> (i % 32)) & 1) { + sp_1024_proj_mul_qx1_32(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_32(tx, tx, t); + + XMEMSET(tx + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_32(r, tx, ty); + err = sp_1024_mod_32(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][32] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 }, + { 0x335c1685, 0x170a46d2, 0xe1007a58, 0xeac9e971, 0x43ca4a73, + 0x40e8f3df, 0x82642475, 0x2646f815, 0xb36576d1, 0x3af49bb4, + 0x72bf1afb, 0xd89e2d14, 0x2fd151e6, 0x27be882c, 0x8f88717c, + 0xaddedc85, 0x16ac6c6f, 0xd6d859bf, 0x2d8eae58, 0x0e741a1b, + 0x61c1f30d, 0x6faf7a00, 0x9b67e096, 0x66dbd09a, 0x7d3b4f7d, + 0x21f11c06, 0xc727c98e, 0x6152ba02, 0xe86cb221, 0xafd58891, + 0x6bd3baf4, 0x59e93c6a }, + { 0x71dd4594, 0xe54dd36f, 0x00aef1e6, 0xbbc9cc9f, 0xa19f6530, + 0x9ea5a44e, 0x3f520928, 0x8588aa99, 0x8f5c1418, 0x9753794c, + 0xc11399fa, 0x118bd792, 0xf5cb6ab5, 0xb9bd3afd, 0x2ecb9652, + 0x813d1cb2, 0x40389813, 0xfd456267, 0x4ac8431c, 0x51f7119b, + 0x0a180eb6, 0xdd9f6a91, 0x9f7bfa2e, 0x13946d17, 0x50a9d0d9, + 0x16f18631, 0x6f8373d3, 0x5f19c20d, 0x9b6a52b9, 0xbe85ac6a, + 0x74f62e03, 0x63ef187b }, + { 0x016f45e7, 0x7c376b7f, 0x2bec82f8, 0x1c1bdb57, 0xce429b60, + 0x7392f741, 0xc7afd81d, 0x6fdbf0a2, 0x7241098b, 0xbda41b1f, + 0xbb60f8cf, 0x5b407474, 0xb330bc4d, 0x933e0d41, 0x733fa3be, + 0xae182830, 0x0f5c6cd1, 0xa0ed299b, 0x3f9860c8, 0x7ff3354e, + 0x15559c41, 0xb1360986, 0x129f85cb, 0xab0cb63c, 0x47685fbe, + 0x682ecc49, 0xeb199633, 0x505e8ec2, 0xddac2cda, 0x90dcc794, + 0xf192da23, 0x4fe6791c }, + { 0x05e8733c, 0x94a423d5, 0x1d5717c1, 0xcc845e65, 0xe961b322, + 0x237c7e88, 0xdb4181cc, 0x0c4471c6, 0x713bd721, 0x00c875e2, + 0xb2c17b09, 0x9dfde9ed, 0xe88ceaf6, 0x430a6de5, 0x7b81cea6, + 0xaaa7a61a, 0x233f98d5, 0xea52d026, 0x60689a9a, 0xb55efdd0, + 0x5cac4aab, 0x30cfa7ce, 0x8e950761, 0xfa4db114, 0x4e9a1e52, + 0x309570c4, 0x1a040170, 0x18c21f61, 0xbe78d9d2, 0x555d1ffe, + 0x561db297, 0x04482a18 }, + { 0x73d486d8, 0xe7758ac2, 0x61cdc1e7, 0x8169f946, 0x2188ab4f, + 0x723c99fc, 0xf3373630, 0xa0e54f02, 0xbd8c2260, 0x560bee25, + 0x4531bc60, 0x28fc307c, 0x7e44feb5, 0xd6f21f1a, 0x57128d37, + 0xc8e4499c, 0xd7b2ea45, 0x963b053e, 0x32a3d222, 0x40c27a04, + 0x35459668, 0x5b51854d, 0xd73557e9, 0x66e1a49f, 0x8692077a, + 0x0d267fd9, 0xe7342702, 0xfa1350d3, 0x68ccdb44, 0x1a9c3f25, + 0xdedbf89f, 0x833a0ff8 }, + { 0xab376b76, 0xa8c419c7, 0x27d0f0cc, 0x3b7294f3, 0xa90c514d, + 0xe56bb9e2, 0xa62575a6, 0x931ba51e, 0x098c0a88, 0x56fee07b, + 0xb4c16a2a, 0x04be5aee, 0xe6eb260b, 0xe513350b, 0xa1d5c270, + 0x339edad6, 0xe9dbadd1, 0xf366ed59, 0x2dd06ec0, 0x4213be88, + 0xcb1187db, 0x22d639c8, 0xd8a1058a, 0x1fec95e1, 0xa2b744f1, + 0x03f73ea6, 0xf4f05c0c, 0x741fd51a, 0x85f811a0, 0x2e2df95a, + 0xeb24965f, 0x692b3ce3 }, + { 0xd2a127b4, 0x0ce6cb72, 0x8f92816f, 0x66a46ea5, 0x47a37616, + 0x43ecf463, 0xe0ab96ee, 0x163d9a01, 0xb2edbe8c, 0xc8145c6d, + 0x4de4e665, 0x2f426cae, 0x74e252f9, 0x174d0b40, 0x7d2af831, + 0x54c240d7, 0x3d652936, 0x581fa397, 0xa09d4695, 0x05b9491c, + 0x5452643c, 0x8c4e8533, 0xd4128327, 0x32d64331, 0x70361f25, + 0x64479038, 0x89ef09f2, 0x774191b1, 0x81de5fe0, 0xc0cf0aaf, + 0xf40042d6, 0x333e430a }, + { 0xcf26d3b7, 0x5df04de4, 0xb53f79be, 0x57a77306, 0x1808b664, + 0xa4013c5f, 0x85037360, 0xef291ea4, 0x0b061037, 0x1ffc9d7d, + 0x65c913bb, 0xd9d04dd9, 0xf13b8587, 0x948a37af, 0xfe3ee755, + 0xb5443483, 0x04631386, 0x3fc21e74, 0xcddeb58c, 0xb3a104e5, + 0x6572cd52, 0x94fe1862, 0x15aaa408, 0xeb9a71a1, 0x459ea462, + 0x8adc6fe5, 0x4aeb02a3, 0xbb18d175, 0x2f7791d1, 0xae127636, + 0xd6bbd708, 0x10e8b31d }, + { 0x3ed9f1af, 0xb87f03e5, 0x56676166, 0x03ad2477, 0x74ce15b8, + 0x38dcd630, 0x26b1e85b, 0x1877e2b0, 0x1af99c15, 0xb1654d17, + 0x9382547a, 0x9782e9e4, 0x26d55ef5, 0x6dc7fc7c, 0x2fbeb54c, + 0x9038f95d, 0x036c0357, 0xfe590dfe, 0x4fdc3f7f, 0xcfcb6eae, + 0xf35e1a88, 0xcb1fbc54, 0xda0a5568, 0x3c8e1db2, 0x5b6f5557, + 0x9a87393f, 0xe7ac0a06, 0x38646b32, 0x2a8495ab, 0xfd261c83, + 0x0cdcc4bc, 0x6485524c }, + { 0xc4a6ff2a, 0x1abfb3e2, 0x35a6428a, 0x2aa03fba, 0x89aff742, + 0x884227f0, 0xba5dbd93, 0x2337883a, 0xd2a182cb, 0x38186ae9, + 0x49a01f05, 0xb9f0764d, 0x917b1e7a, 0x92411feb, 0x570cbb5b, + 0x700b1903, 0xb914be7c, 0x5d5181d5, 0x1981182d, 0x135c4437, + 0x574b9997, 0x32758d24, 0x632d28b2, 0xa650a8f5, 0xfa383f09, + 0x24078bac, 0x00a33d80, 0x6546a60c, 0x2df8b449, 0xa4061c7a, + 0xf234563c, 0x1f76f3f2 }, + { 0x44c436b0, 0x9aa2c143, 0x1f69c87a, 0x79070556, 0x5f6db2df, + 0x35f3117b, 0xed56ba82, 0x85761f41, 0x7d0afa48, 0xf831464f, + 0x3adce71e, 0xa99f2915, 0x116b7488, 0xb27bf693, 0x9bb9443a, + 0xa98a5a8c, 0x2ee5fde8, 0x7f878026, 0x1812acb7, 0x3a6f93dd, + 0xdc84bc92, 0xaf92a4cc, 0xf1d4995a, 0x3c2562af, 0x04ed899d, + 0xfd9fc33c, 0x4ed2a538, 0xc028ca94, 0x049ea726, 0xd0f367bb, + 0x3d108e05, 0x04924ffb }, + { 0xc673562f, 0x06548e3d, 0xe2eae48c, 0xd3b33025, 0x5e1c6977, + 0xe61fd32b, 0x6ebe557b, 0x424e2064, 0x41d6e18e, 0x767391c0, + 0x14d7e95b, 0x4b8ebb8e, 0x20991b8c, 0x4ae8b7d4, 0xe01290d3, + 0xf8a0df66, 0x925e5f4e, 0xc97e24a3, 0x1508272a, 0x79a7b2cb, + 0x25072661, 0xb40b072e, 0x9062fa49, 0xdad9e182, 0xf3c53bce, + 0x8780a784, 0x9f142799, 0x58a82b76, 0xc1468426, 0x08cd849c, + 0xc380ae35, 0x4dfce809 }, + { 0xd527b780, 0x45069cb2, 0x977930dd, 0xd52da015, 0xe27d0263, + 0x10cc600b, 0xbb2d1b2b, 0x34102c26, 0x554adf3c, 0x4c652623, + 0x45f0ff47, 0xd6891382, 0xca916e7c, 0x83fa8cc5, 0xd15c8d8a, + 0x1e10f139, 0x81dc56b3, 0xf173dc2e, 0x5c4ed9ba, 0x7fcecb04, + 0x47d01228, 0x307fd7d8, 0x9f3a532f, 0x24a57153, 0xe2153c22, + 0x59e9e81d, 0xe428a408, 0xc562595d, 0x9339bd23, 0xdc7daff8, + 0xb8a06802, 0x0d075908 }, + { 0xde085f2a, 0x870af2a7, 0xbe99b2e5, 0x88fcd24f, 0x59ca413b, + 0x88c0d261, 0x8559f851, 0x1f02a2e4, 0xf622da0d, 0x83b96021, + 0x6dca3615, 0x5c05c2f5, 0x7910c682, 0x0148cf1c, 0x272695be, + 0x392f2896, 0xa8d64ef6, 0x883d0bb5, 0x1cfcbc52, 0xef0d2244, + 0x526117e5, 0xf5dafcec, 0xf04928e9, 0xb68612b9, 0x393f2e2a, + 0x283f744d, 0x700c1151, 0xfbeed7ed, 0xa4360dfe, 0xf2cde215, + 0x2f08535a, 0x24fa961c }, + { 0x616df7f6, 0x0767db3f, 0xfbd90326, 0x643057d8, 0x6e82d544, + 0x174daa90, 0x689643db, 0x2284f345, 0xcc89a060, 0x18b191df, + 0xd6c27d12, 0xbab46af4, 0xc9895145, 0x5a57f486, 0xcc942f9e, + 0xc03214e9, 0x41950158, 0x273e1c8f, 0x39ad43ab, 0x8ceb759f, + 0xe50ee173, 0x5e1b8b7f, 0x8f4d7d4e, 0xf635b1fc, 0x755603f3, + 0x8eff77e3, 0x7752fa60, 0x201f61d1, 0x4a6fb6e1, 0x94d7a03d, + 0xfc4f0114, 0x371cc23d }, + { 0xda90c351, 0x289b115d, 0x364d9c06, 0x6d196ebf, 0xf650b31b, + 0x77a89202, 0x6f57642f, 0xcc28c164, 0x08100127, 0xdc4f7e36, + 0xdc4c807b, 0x8836cd08, 0xe00240f2, 0x1280f156, 0x99cb3953, + 0x3f9a6d78, 0x3a802038, 0x40a494d3, 0xe87d3474, 0x45697e91, + 0x26dde24a, 0x70d97d07, 0x7640c30e, 0x06f6a58d, 0x5ba6e6c6, + 0x03c2c0e8, 0xf1bc13e8, 0x330f6a7a, 0xc9f4d78f, 0x3e602e4f, + 0x0c80fb7f, 0x92b6bca0 }, + { 0x5f00822e, 0x2e3d5c83, 0xb8b16f12, 0x0e825712, 0x92b0a330, + 0x81c329c4, 0xa7cc1954, 0x6b4e32ad, 0x1bb1413f, 0x0bee9cee, + 0x4a92ca27, 0xedfb7baa, 0xea3b9153, 0xcd472afa, 0x00f0c0f9, + 0xe8f09e7e, 0x5cdebb70, 0xa4e1d872, 0x4a9b63b6, 0xfe2bae08, + 0x3fd58f65, 0xf40141b8, 0xa3b62759, 0xd7ec5eda, 0x790e3088, + 0x9aaf6e67, 0x1f277e31, 0x215ad830, 0xcf33871c, 0xe7db4b98, + 0x4f02f89d, 0x71ff62c9 }, + { 0x2a4a84d9, 0xaa4c7102, 0x5ebc71e6, 0xe2ee4acd, 0xf1cd6578, + 0x3b11a8a5, 0xfff120a5, 0x83f5ef9f, 0x09e65033, 0xa4c598e1, + 0xca044180, 0xe1e9f990, 0xf59828c1, 0x8b832d46, 0x33af536b, + 0x753f28a0, 0xb6d4f68a, 0x92edc4b1, 0x72ccd1f0, 0xedde692a, + 0xd2226432, 0xd3aa0f7d, 0xa3d2661c, 0x38dbb63e, 0xfdc37dda, + 0xf1e19fc6, 0x84ef6b4c, 0x6c18b350, 0xdf1bba69, 0xe6a83fe9, + 0x5f958273, 0x40fd47e7 }, + { 0x267140a4, 0x5b88b746, 0xeab6f2fb, 0x6dbbfc1e, 0x69862548, + 0xdd9ec88e, 0x2eb6efc2, 0x69beeba1, 0x8ac8ff88, 0xcfc2214a, + 0xb5a21950, 0x95d5c96e, 0x4171fb69, 0x93389c05, 0x1b468337, + 0x2d85d452, 0x4113425c, 0x14d68a08, 0xec6c2174, 0xe52c0139, + 0xf730084d, 0x20cf0b97, 0x1f578aa3, 0x1ac16a26, 0xf9b6ae43, + 0x18b9fab3, 0xd854a695, 0x68d82111, 0xdffbe286, 0x0b334d98, + 0xe639338c, 0x5b1c1157 }, + { 0x72b6bb8f, 0x90edaab1, 0x02fc92c2, 0x8dc64ed2, 0xfe694c73, + 0xf42ba3c5, 0xcb54dce4, 0x316dc65f, 0x632420dc, 0xcb2d66a3, + 0x056dcf94, 0x16e706e7, 0xa4f32c9d, 0x2809c764, 0xea6edca8, + 0xab18d830, 0x81c65f57, 0x4fd1ace6, 0x7da12c10, 0x1f91651c, + 0xc7791a48, 0x0ac3bd66, 0x785e67a3, 0xb6ad1cf4, 0xda0fd591, + 0xe4d3fc44, 0x6e1c6344, 0xce164801, 0x33e50ab3, 0x84de9cb8, + 0xa756eef4, 0x963ab83a }, + { 0xdf4ea5a3, 0x944b47d8, 0x5cfe45fe, 0x96568815, 0x8a3c3564, + 0xd16e7d58, 0xe7c99e15, 0x84e55b3e, 0xf55071bc, 0x3fee204d, + 0x04057dce, 0x71006f29, 0xbba75570, 0xfe8c390d, 0x3319adac, + 0x3645bcb6, 0x7c20bfd8, 0x8189e8b0, 0x7d7d9578, 0x8e550969, + 0xb99f4e3b, 0x037d1321, 0xa60cfb6a, 0x011b2521, 0x837382da, + 0x66594aaa, 0x83c1dc07, 0xc89b91fd, 0x076b9884, 0x6b82b899, + 0xbe45c558, 0x443480fc }, + { 0x9114221a, 0xf8ffffb4, 0x3e857a7a, 0x4aec4f2e, 0x0fa54787, + 0x42e2d0e4, 0xd6f96152, 0xef3e6b31, 0xfbfe9b77, 0xb2296537, + 0xfb43a86a, 0xc2a9d0f2, 0x24572ac6, 0x241284ed, 0xe721ba7b, + 0xa3868917, 0xc117a78d, 0xdbef7c00, 0xd31605ac, 0x38149071, + 0x065a8ee9, 0xc2dada9e, 0xc442be82, 0xd5b138d8, 0xf6d72b58, + 0x9b6c224b, 0x8eb03e6d, 0xb9d355cf, 0xa1700371, 0xab6d1eb0, + 0xcffaa7eb, 0x97118a88 }, + { 0xcdecb5d8, 0xbf9c59a2, 0xa93a6866, 0x8083c81b, 0x04774fbf, + 0x24e0dd81, 0xa02070b4, 0xe779a3ca, 0x0fbfb781, 0x9d352fbb, + 0x3ef2a1c4, 0xa8b0d820, 0x14b3e501, 0xb858637b, 0x8a882ff2, + 0x5ba70a49, 0x3b06efa5, 0xa2730083, 0x102fee2a, 0xa42c02f4, + 0x8a0223a5, 0xe4e76299, 0x85c3fc72, 0xdba2ba26, 0xfe52eae7, + 0x554fe763, 0x270f45f6, 0x30b5405a, 0xa573387c, 0xd56a177a, + 0x4b71fa82, 0x17c0778d }, + { 0x2735e37b, 0x0e6dff1d, 0x656ec572, 0xc9884e56, 0x9ebba978, + 0xa2f5ac9d, 0xba09f3c4, 0x40fa4518, 0xf5b04377, 0x8c3fa177, + 0x967a2eca, 0xa1a1decd, 0x0528bd40, 0x768bca70, 0x18691c4a, + 0xf224952b, 0xe86d5fd5, 0x16e12c45, 0x37859a6a, 0x7a0d9157, + 0xa0ffce0e, 0x723f4309, 0xa96cc9a3, 0x5a8db79b, 0x1ad23a38, + 0x6dd12ae0, 0xe2bf5d84, 0x9ffec3a1, 0xa452ed66, 0xd6ce84e1, + 0x571fe4c6, 0x1219d5c8 }, + { 0x262969eb, 0x43eaa67f, 0x2f03e773, 0x3a3ab39d, 0x57bb0909, + 0xe6127e51, 0x8d150274, 0x0f82b0ed, 0xe580bdbd, 0xffffcad8, + 0xa9743e6b, 0x51d3d075, 0x8bac11d6, 0x1484bdb1, 0xeb24c388, + 0x95cd9990, 0x7fac67c6, 0x216a61d0, 0xa04e6b87, 0x4308f762, + 0xcba57cc8, 0x2865dd61, 0xd234a07a, 0x3c296b0d, 0x3a0793f9, + 0x76f92839, 0x0be29ece, 0x70b57e1f, 0x7e626f42, 0x1314a82f, + 0xd657f230, 0x2c8d7ab2 }, + { 0x0825e4d6, 0x67cf5892, 0x6ef83b44, 0xdf51eaa5, 0x1310108d, + 0x63e665d8, 0x8dd0963f, 0x229f89f5, 0x9df6436a, 0x8c4b14dd, + 0xd45ebba7, 0x99dae469, 0x5a4df381, 0x118aab77, 0x29e37feb, + 0xda8978bd, 0xaca2d7ef, 0x69ced5aa, 0xc67d6a8a, 0x6c98d05d, + 0x77f84a34, 0x7474bf0d, 0xed8cd59a, 0xd4428b2e, 0xd1d398fb, + 0xb0fd1cd5, 0x94a20b11, 0x596013db, 0x1b404c44, 0x96eb705a, + 0x4b09d958, 0x2299d277 }, + { 0xc64397e6, 0x5b9cd58d, 0xbf6dd31e, 0xac198f1e, 0x3e9f1db2, + 0x5866d8e1, 0x8fcdc68c, 0x405ae287, 0xe53c01fd, 0xa4b280cd, + 0x411db5f6, 0xdc963f2d, 0xbec4f8a0, 0xed5d5189, 0x916ee98b, + 0x336fd13d, 0x042df48e, 0x6925b1b3, 0xace0074e, 0x0cf56291, + 0x25317e95, 0xe8d38b48, 0x821c446b, 0xc7ad1d2b, 0xf0b65934, + 0x71c44135, 0x52ca0d50, 0x971b736f, 0x27b46c26, 0xaf9ffa57, + 0x1936618e, 0x21ac6779 }, + { 0x2d7fbcd2, 0xab420e3f, 0x97bdfc18, 0x12722473, 0x4df5d4b4, + 0x492033f8, 0x3807b7d3, 0x6fcd4236, 0xb33c3625, 0xdfc19b09, + 0xa0f22814, 0x13d6f375, 0x037c19b8, 0x70978a59, 0x0ff27b9c, + 0x4f398997, 0x615a4389, 0xfc0e1a45, 0x3e602f74, 0xffa3496a, + 0xb261ca1c, 0xc3f1c431, 0xee0164cd, 0x612211db, 0xe7f7be9f, + 0x30463ee4, 0x92c2e1bb, 0x015f7e78, 0x24483a56, 0x663d88d6, + 0x0e62d9d8, 0x0e8ec1e7 }, + { 0x8a0878dd, 0xa88ccc29, 0x6640071a, 0x99ac175d, 0xa5173617, + 0x90344820, 0xdd58a315, 0x316d023e, 0x88d221a1, 0x30785bd4, + 0x959c48e3, 0xb74b3de7, 0x4c67a771, 0x42ee0382, 0xe0b91453, + 0x59ef6cdd, 0x9b237e91, 0x7830ae28, 0x495d8325, 0xe1847a4c, + 0xd0773666, 0x67b1217e, 0xa294a325, 0x58192c86, 0x864d8326, + 0x76aa0f56, 0xf4b13e5b, 0xe2a2bd12, 0x1b6b73fd, 0xd850c1c0, + 0x5d103635, 0x653a795f }, + { 0x50dcb199, 0xcfe28985, 0x7fa02b60, 0xb35b8e5e, 0xc97603d0, + 0xbca7d7c3, 0x27f131b5, 0xb0e5288d, 0xe2b12d52, 0x3aa704de, + 0x1db725c7, 0xe206b1d8, 0xc5d1b113, 0x0b12839a, 0xdb45d763, + 0x14f970cb, 0xb2125e8e, 0xc997f93e, 0xee7daa26, 0xbd75739c, + 0x1fef20e9, 0x46ecbd3f, 0x7c6a42b1, 0xf994a114, 0x27fb0fd1, + 0xd289eb4f, 0x9a40da4b, 0x11186d31, 0xfb9d7976, 0x083f65a5, + 0xd444675e, 0x30dfc47b }, + { 0x9eaadfe8, 0xbcfc5ae2, 0xb4d4e812, 0x25027e54, 0x8b533561, + 0xab0702df, 0x56a6a214, 0xa2b9c204, 0x3059068e, 0xb1a3df7a, + 0x9883110f, 0xa3514b21, 0xc4b78e1c, 0xb7be2336, 0x3e2f6984, + 0x17073ce6, 0x2ddf7ac6, 0x86e114a6, 0x07d7c3c8, 0x276192bf, + 0xeb1ae289, 0x5da69e0b, 0x25184939, 0x983af175, 0x407a3aa0, + 0x9ac52a4d, 0xae0fe218, 0x1535c7da, 0x397f2501, 0xe16fe872, + 0x54c212cf, 0x572a591f }, + { 0x09a5553a, 0x49668419, 0x327733bc, 0x3f054318, 0x3eefd690, + 0xf9ceb4b2, 0xf22126d4, 0xbd3cbf9b, 0x2fed9578, 0x6d9671c0, + 0xca0306d8, 0xbba597ce, 0x3d674fe5, 0xb705ed61, 0x67f33f76, + 0xf1d3622b, 0x11cb8c31, 0x15bcf3c6, 0xe53d1aa9, 0xa38467dc, + 0xf908ab43, 0x902fe929, 0x8d15767a, 0x6e3e499d, 0x90afd07b, + 0x8142db5c, 0x6c8b190e, 0x120c6fbc, 0x24919a4e, 0x80c86553, + 0xd8c82c3c, 0x65c2cbe1 }, + { 0xa660bb63, 0x684cda20, 0x86e86245, 0x27dc3b0a, 0x6ba0eed7, + 0x76472cf6, 0x679dd158, 0x79c162e5, 0x08452d44, 0xb6884277, + 0x413f579e, 0x829bc6b3, 0x95011770, 0x92ea15ec, 0x47738183, + 0x5e34e300, 0x73e1d2f1, 0x8c3ca349, 0x229bd3de, 0xa5c4f1dc, + 0x94ef7ed3, 0x783eff1b, 0xdfae7a1a, 0x46db738d, 0x1a099852, + 0x4353d72e, 0xa0dcf4ab, 0x2533ad58, 0x0e7888b9, 0xd8055016, + 0x3ba77f66, 0x831440d5 }, + { 0xf611b2da, 0xf43e2e32, 0xd0fa46ac, 0x5d066e29, 0x820b3c0d, + 0xe897f3e8, 0x1d3e44f0, 0xc45c28e6, 0xdfd27a66, 0x929d7f66, + 0x101e8517, 0x735b860a, 0x3de078dd, 0xea3fce98, 0x638ce11a, + 0xc9977db5, 0x48536b3b, 0x0488382f, 0x64cadfc6, 0x7e0c7a3c, + 0x82147b71, 0x3cd17f7f, 0x1b411e3e, 0xe95663cc, 0x985fb46d, + 0x5739ac8f, 0xbcf119ca, 0x385399cd, 0xe15a2815, 0x4a985a70, + 0x6d5f4566, 0x504c3a8a }, + { 0xb8fa53c7, 0x00b55283, 0x509474e3, 0x985cff38, 0x437ce25f, + 0x234d241c, 0xe5a129ed, 0x29832430, 0xaabcc674, 0x6ad38956, + 0x7ee81ee1, 0xa2dc001d, 0x670b2702, 0x4c23c6b6, 0xa6e8a3bb, + 0xb35e567e, 0xa69673ea, 0xbc70b3ce, 0xe6e28eac, 0x85a7a9c3, + 0x5537b7da, 0x2ae684de, 0x6de937dc, 0x5ecac3e5, 0xf8430422, + 0xbf2ea6c9, 0x77fdc520, 0x38caf7d0, 0x69f56add, 0xc27af0b1, + 0xc71d21d2, 0x496e4699 }, + { 0x9fa93467, 0xba14fc82, 0x0eb2a614, 0xc2e37684, 0x4833e09b, + 0x659bcfaf, 0x3686bdcc, 0xbc859752, 0x81f3216a, 0x40bfd080, + 0x17c081b8, 0xc463bda6, 0xbb04793b, 0xbd01fa86, 0x2cd640c5, + 0x5a21ece6, 0x2203d5c4, 0x97bf6a54, 0x951167b7, 0xceb40edc, + 0x765ba268, 0xd67aacaf, 0xaeab51f9, 0x8ba0d9e9, 0xb0d6863a, + 0xc14b215e, 0xe5f06952, 0x354cdcdb, 0xcb3744b5, 0x4f2b5ccf, + 0x13037fe8, 0x13389173 }, + { 0x45003cd1, 0xee680640, 0x44ae2ac6, 0xfdac17bc, 0xde8e5314, + 0x4bcd419f, 0xc7cea95c, 0x81e34eb9, 0x38f37e01, 0xbb57762d, + 0x260990c8, 0xecc4cfb0, 0x50a34a7b, 0x0bc493f9, 0x543304ef, + 0x68074172, 0x6bc8aa2a, 0xaec0fcb2, 0x3b45fea5, 0x9e7a9b46, + 0x55fbdbac, 0x4bb2952e, 0x0485dff4, 0x50f0c0a6, 0x4dea4796, + 0x02c5104d, 0x695e3a02, 0xd2cefa09, 0x6da1f345, 0x4c8102b4, + 0xf3833fbd, 0x422eb573 }, + { 0xa6ad3f47, 0xac592eb6, 0x9714ba0e, 0xb0861f6d, 0x07281459, + 0x57c1e919, 0x64ea5803, 0xcf7c94e2, 0x54b12723, 0x725376ac, + 0xdafb736a, 0xf2a6ba41, 0xcba03cdc, 0xc89e8920, 0x5b0fd3ad, + 0xf2e20cb4, 0xd66059fe, 0x26ea5a54, 0x889df8bc, 0xee63fa8b, + 0x66a3f2bf, 0x40f1c7e1, 0x747312e1, 0x09febc9c, 0x727999ff, + 0x7d19b9c2, 0xb7fd2b05, 0xa9fbbb4c, 0xa0da2dc6, 0xcfba27d7, + 0x2c252582, 0x368541cf }, + { 0x22799d37, 0x510d3c9e, 0xacfa333a, 0x1b677de5, 0x080f795b, + 0x4e6ae18f, 0xafc8dfc2, 0x69b53c2a, 0x0e842dc2, 0x797541b6, + 0xac067fe8, 0xd5a6f2af, 0xbd07d877, 0xd0208a03, 0x654be2f2, + 0x34b473f0, 0xf515e23e, 0xe67c102a, 0x2ac1af48, 0xb00dbf9d, + 0xb6a13d00, 0xe264fa41, 0x97e94c11, 0x1669786a, 0x86a586f4, + 0x09d8cf2d, 0xc7f927e9, 0x073bf869, 0x2241a566, 0xb8977880, + 0x22261334, 0x59a5bf59 }, + { 0x81347191, 0xe9d1c91e, 0xeb969972, 0x186c1abc, 0xa9d46a7f, + 0x07888767, 0xdaa7d397, 0xda93cfcc, 0xd91b9aa0, 0x08bee9f1, + 0xf8dd3c6c, 0x8267fd78, 0x94228100, 0xf93860d0, 0xdadb47fb, + 0x6a6a71aa, 0xa6156f8a, 0x9caa06b7, 0x39848bc9, 0xaa1b05e0, + 0x2aaa9135, 0x36ddc237, 0xb13f3bd1, 0x77e7e079, 0x4acc5f4d, + 0x8d0b5cbe, 0x984cfd36, 0x04da45f8, 0xd3d3e0f8, 0xf14ef618, + 0x43eb799c, 0x467564c1 }, + { 0xb6fff5d7, 0x8d725904, 0x92dc4752, 0x037f33af, 0x6d20b8aa, + 0x9095d575, 0x43baec39, 0x32235fc1, 0x68a2b9b0, 0xa2feb4af, + 0x94d35c61, 0x61c50318, 0xea877486, 0xac92b6a2, 0x011bc6f3, + 0x8eb48b15, 0xc79edcb2, 0xa28fe128, 0xa5d2a006, 0x9f71bc0c, + 0x2f15b850, 0xf3167732, 0x7a036218, 0xfe8d728c, 0x4f81e09e, + 0x068f39cb, 0x7b7c50d9, 0x1773f016, 0xed6a1e03, 0x0d0f7adb, + 0x4ee984d5, 0x8a0dee16 }, + { 0x47366e6f, 0x504991bf, 0xe86c3005, 0xb8084d9f, 0xa40cce36, + 0x14c4c751, 0x3f1961e2, 0xbbb46aa6, 0x40445e43, 0x56a785f9, + 0xc91e215f, 0xdb8d1b57, 0xc7ee808d, 0x6a8e453e, 0xbbaa1e8c, + 0xc0367ef8, 0xe3e18109, 0x310d91f1, 0x7e20a2c3, 0xf97cfd0e, + 0x554cc277, 0xf1e80c84, 0x7b628403, 0xe89bbc1d, 0x3fe0a17c, + 0x7778a966, 0xc1f00073, 0x9e9db19f, 0xb6f6bed2, 0x2ce7fe7d, + 0xee97ce23, 0x7b04b5d2 }, + { 0x82c5faf8, 0x5b546bc7, 0x8eb81097, 0x1a734c5e, 0xe77851e0, + 0x3d566861, 0xe956d51f, 0x833a1013, 0xc3c3c37c, 0xc7351731, + 0xe0c148ec, 0x607738fb, 0xe1bbef41, 0x2ec6f0bb, 0xcfa51857, + 0x0aa2ac6e, 0x66e3adf0, 0x072902d7, 0xc622d6e3, 0xcd4d5089, + 0xa6dd802f, 0x3ae21b23, 0x33886372, 0xe5465a55, 0xa8d81822, + 0xd85119a0, 0x3786977a, 0x4f14d032, 0x9c7b272c, 0x515b081c, + 0xc99be31c, 0x1c6a95a4 }, + { 0xc2821363, 0xa6b14ad5, 0x4d17de1c, 0x829c1823, 0xccade848, + 0xaef5d2c4, 0x82489e27, 0xf412ab39, 0xf081d927, 0x92c9c098, + 0x75cbad1f, 0x6f87bdf4, 0x1a1d9fb1, 0xf4aadab8, 0xb75f3b76, + 0x475a7923, 0xdbbba8fe, 0x99dd0ad6, 0x4b70ab45, 0x836f6164, + 0x34bd9af1, 0x2a464881, 0xba9abda3, 0x5c91226e, 0xe65625fb, + 0x4cec8709, 0x0818e4be, 0xd4b3919e, 0x14f6879c, 0xa5c09c84, + 0x30a864c9, 0x72708a02 }, + { 0xf34a466c, 0x4f33c0b1, 0x7f9d45ba, 0xa1bae09c, 0x0e28785c, + 0xd70f0fee, 0x90880881, 0x824c7146, 0xbb043da3, 0xe2416c2a, + 0xcec6f432, 0x733da713, 0xc9793e1c, 0x2b590649, 0xb35c9365, + 0xdb62d5b0, 0x3e5c1b2a, 0x355eb6e2, 0xbb16b515, 0xcfe8b5ce, + 0xf709691c, 0x9e081869, 0x61a85bd5, 0xc865f9fb, 0xfae103f7, + 0xf169d3cc, 0x73467e9d, 0x9525c473, 0x43695113, 0x7db55c0b, + 0x73265d21, 0x7491c74c }, + { 0x80d2b94d, 0x312ed5bf, 0xba4b260b, 0x1b8ac633, 0xd62219a1, + 0xac86c58c, 0xaeb82c8e, 0x317ccf6b, 0x59ef9ced, 0x2dfb29ee, + 0xe42bcd5a, 0xdaa7d898, 0x5974b201, 0x93e295c8, 0xd9fc5adc, + 0x69e75784, 0x012aa3ba, 0xd6c4709f, 0xc85d3cb9, 0x1fda9f37, + 0xd3dd4abd, 0xe5487e25, 0x0b3ba22e, 0x00fd4b01, 0xc6e8dcbb, + 0xcb591493, 0xbce68664, 0xb7329fab, 0x68906b76, 0x6829d1c2, + 0x74176841, 0x8bcfd3e5 }, + { 0xd3c8c314, 0x06882734, 0x11870833, 0x95f0b2f1, 0xc068ba16, + 0xb937f7c3, 0x77924787, 0x5365e0d8, 0x1f992227, 0x15527e5e, + 0x27dffd4f, 0x0a069648, 0x2f586389, 0xd58b3df2, 0x6af20ead, + 0x83446b89, 0x50746257, 0x09d7970b, 0x4022a691, 0xd9e8d206, + 0x671ec379, 0xd1e5f8af, 0x057fe91e, 0x6f542509, 0x52890418, + 0xf14dda81, 0x1db932ad, 0xbd78010e, 0x905a9378, 0x3e18d1e4, + 0xbd37ab49, 0x53cadcf7 }, + { 0x5e53d0ff, 0x1bb5edf7, 0x888abf67, 0xd886606c, 0x12206d15, + 0x6491b0f8, 0xe22b6a33, 0xb3018345, 0xb173b317, 0xaba6794b, + 0x7dc9e595, 0x8c1e5867, 0x239624d1, 0x4e106482, 0xda55dd53, + 0x61752e59, 0x9e42879c, 0x018b4eab, 0x491f2bed, 0xcaf6784b, + 0x1e79429e, 0x3dcdb9d2, 0x10f26224, 0x36941485, 0xa650ec5c, + 0x106f190a, 0xb69a9760, 0x7542a5ae, 0xc32d1046, 0x69bd75e9, + 0xbf8c62b1, 0x90849964 }, + { 0x5a93c661, 0xb1390cf6, 0x9db5f056, 0x18486264, 0xa51a1788, + 0x92a93a9d, 0x6772de9a, 0x1b0cbb8f, 0x7c71487c, 0x6e67febd, + 0x4e62423e, 0xf9b4382d, 0xbb5a42f8, 0x96fda50e, 0x6089a4f2, + 0xc921b337, 0x875ec516, 0x49d32d7b, 0xc410124b, 0xbd86d2ca, + 0xc421fb7a, 0xf6862209, 0xf6b7de33, 0x3e1949ab, 0xe93c9268, + 0xcdee18f0, 0x08dc4cc0, 0xd4edbd5e, 0x73580d22, 0xc2b75be4, + 0x468cd7e8, 0x3d7f6ffa }, + { 0xdffbd5d1, 0xea7b290c, 0x970338df, 0x9d759da6, 0x90feedc9, + 0x56680b08, 0x42dce68e, 0xbc690af5, 0xb2ae4d82, 0x8519df2b, + 0x7f195b60, 0x5612467f, 0xd83c21f4, 0x659a342c, 0x55651633, + 0x55771bf5, 0x548ba562, 0x5fc68935, 0x9492f23a, 0xb5419203, + 0x9c9c6017, 0x567528e3, 0x511e6019, 0x3f064ed4, 0x1d16a555, + 0x303f9eb9, 0x2254abee, 0x3e18c4fd, 0xfd434e7c, 0x40994d6f, + 0x6dde74e6, 0x8fb12d3f }, + { 0x293cb7a4, 0x6c6381a2, 0xb87b7e4d, 0x453e09f0, 0x078ac3ef, + 0x4f212823, 0x578cae91, 0xe89ffad0, 0x716ba4dd, 0x4a2b696a, + 0xf6f580a0, 0x14681a14, 0x4c2f1307, 0x1358f97b, 0x2932fb89, + 0x87896996, 0x268a5af7, 0x29dd850a, 0xfe239f83, 0xaf771f6d, + 0x4f47499d, 0x5f20fd2e, 0x867ca0e9, 0x9b643e77, 0x375981ec, + 0xe7858ecd, 0x19ab1c97, 0xbe946a59, 0x06ff3453, 0x4f9303a2, + 0x75d237b1, 0x3fcc6731 }, + { 0xdf21f920, 0x509debd5, 0xc1401b90, 0xfaf70e1f, 0x95a64aaf, + 0x2429cbfd, 0x2c37a122, 0xf2120855, 0x7deb926b, 0x1d4c93f4, + 0x9fb3f1dc, 0x12f3e4c0, 0x5b51bc46, 0x56085a59, 0xf10fdbd2, + 0x2a2f5d62, 0xdf0cb3c2, 0x60dd62cf, 0x6b0f254b, 0x154424a3, + 0x564612b7, 0xc3a5a05d, 0xa1f5249c, 0xbebe30cf, 0x7e62a188, + 0x24ec6903, 0xaf429939, 0x75f0fbac, 0xb3fa8685, 0xd41345dc, + 0xc7151c34, 0x645146fd }, + { 0xba1924f9, 0xecec633a, 0x006326e1, 0xbba6f136, 0x7e50fc17, + 0x203757ac, 0xef3d8e00, 0xca531919, 0x51dc5a74, 0x9545a6aa, + 0xd31412b8, 0x6e21d58f, 0x7bb1d000, 0x01bc3005, 0x6ed1a9c3, + 0xf1789c69, 0x9858fa48, 0x7af2d35f, 0x8197be85, 0x434d09b9, + 0x29aa265d, 0x1dc07755, 0xc058fa80, 0xcad03be7, 0x54ba14ce, + 0x92d70a9f, 0x6c050a74, 0x6dc78505, 0x4d005dda, 0x2a7ca4a9, + 0xabfb9f2e, 0x448d3d72 }, + { 0x29b33989, 0xdc56f145, 0xa9ae815a, 0x868351bc, 0x4b074414, + 0xb3f45613, 0x3cd9f33b, 0x955ce42a, 0x5ff6e4a3, 0x13ade4ec, + 0xa50eaa91, 0xd3aac715, 0x5666efdf, 0x0c61ec99, 0xf6a4470a, + 0x108a28b8, 0xe54844c9, 0x402ef584, 0xd0e2f337, 0xb825b162, + 0xb46f7cbc, 0x3dcd131f, 0x96f2fd89, 0x208178ec, 0x25928c78, + 0x4d8c5d67, 0x9963c459, 0x285a33df, 0xd92a309f, 0x72497175, + 0xcb7019a5, 0x76881479 }, + { 0x91767eed, 0xba43a114, 0x92bf65db, 0x5e11b9ad, 0x03a5e21a, + 0xe8a22ce0, 0x2a335415, 0x63604421, 0x4a9ead62, 0xc2c563b4, + 0xa0b2aee5, 0x4bc06264, 0x8bf2e1d7, 0x75b8d575, 0xd08a265d, + 0x1cff0ee7, 0xb0b712a7, 0x17914e1d, 0x4b18692d, 0xc35925d0, + 0x56cce815, 0xde253f4c, 0x9fff0e3a, 0xa479241c, 0xddabed19, + 0x50b9d06e, 0x59fae506, 0x67135260, 0x532ce180, 0xf37600fb, + 0x5e5a8626, 0x670eb01c }, + { 0x73cdbb43, 0xdf73c0af, 0x7f2431ad, 0xcf08ecc5, 0x2a1a3845, + 0x91780541, 0x9224ddf1, 0x69a104f2, 0xbeac7eff, 0x4352f38d, + 0x7c2d1322, 0xfc3b3b4e, 0xb5e4b476, 0xa69e9430, 0x975a46f0, + 0x7d932340, 0x5d64eece, 0x8093899e, 0xdb2345e9, 0x7b821250, + 0x7f4b796b, 0x23552932, 0x4bb90b1f, 0x2ee9cc15, 0x9112f7d6, + 0x1fa9c8f5, 0x1cbaae32, 0x2d0f2f98, 0x0075166a, 0xb77f0366, + 0x635dff27, 0x504852e7 }, + { 0xa2f392fa, 0x2f0f3ce5, 0xec6c9078, 0x326c076a, 0x84baaaf6, + 0xad01de92, 0xcbe8e993, 0xb01b16d3, 0x2d950908, 0x71305c24, + 0x3853af38, 0xc66fd617, 0xd3c429a0, 0x7735140e, 0x1fabf027, + 0x8a31b12a, 0x058b3177, 0xa0530002, 0xa9c7deb9, 0xabffd9fc, + 0xe8667d30, 0xd05ef69b, 0xe9a9e13f, 0x2f3a7308, 0xb91eae9c, + 0x3f4c9a19, 0x618ce6c4, 0x50d0cee7, 0x5240f8b0, 0xfb24dc40, + 0xf7e90cc4, 0x992fe151 }, + { 0x38f197aa, 0x4454db31, 0x87872f98, 0xa4ded69d, 0x44f0a828, + 0x97b427b0, 0xa31e48c6, 0x9821e1ae, 0xdd98efec, 0xe38cb09f, + 0x480cb3ae, 0x20b84fa8, 0x47475573, 0xba5bb4a8, 0xcd50e96b, + 0xa9be080a, 0xef103550, 0xc4451e9c, 0xc441325c, 0x626ee75f, + 0x38a5e33d, 0x6eea5e98, 0xa2b0abd2, 0x7321beb9, 0x9b6082a9, + 0xca92e484, 0x992bcc2a, 0x1dc8168a, 0x9c8eb9fb, 0x134ecf4b, + 0x4c5b71e0, 0x5a68bfa8 }, + { 0xff0a2bfb, 0xb4ff3b45, 0x5502f8b0, 0xd105fff9, 0x5b1c0c26, + 0x14de5885, 0x0d3b9d04, 0xed16865b, 0x026d3917, 0x2f5a2453, + 0xf4db3c0e, 0x6a22f493, 0xe2418f2e, 0x4871548a, 0x509bef61, + 0x6ab363a8, 0xb8cbbbec, 0x91ca1e3a, 0x4011a396, 0x71e0dc98, + 0x0d5ca577, 0xff982e0a, 0x81897bc1, 0xeb40b045, 0x085ad5e7, + 0x4bc24a46, 0xa6337b7c, 0xd15c8fa0, 0xbef1628f, 0x56ce6ef7, + 0x9f5ef439, 0x78acfdf9 }, + { 0xf8520189, 0x45bf7f15, 0xc77f61c4, 0x954202a0, 0xdfa22e1b, + 0x39edc6b9, 0x1f4a3487, 0xd2d60267, 0x4814cc52, 0xcd933929, + 0x05e9f123, 0xde76a124, 0xae36b6f7, 0xe2306ea0, 0xb83a58e0, + 0x53815218, 0xa041231a, 0x9862bb76, 0xbf31be71, 0xe8da253c, + 0x37de861f, 0x2dfc5332, 0x90ae4890, 0xf25c93f6, 0x8baa6ed2, + 0x66bcb8f0, 0x908b4a29, 0x6f10ae0f, 0xb061c949, 0x8cb4b48c, + 0xd075a366, 0x0ad92d73 }, + { 0xc2ca548a, 0xbfb95fed, 0x80cd89ab, 0x4778c620, 0x3466c280, + 0xbe99154b, 0xd4be8902, 0xea3be093, 0x13e681ed, 0x847b7995, + 0x02f40161, 0xf22a8f4b, 0x4aeb7fe8, 0x3ef2cb4d, 0xb3aed5f6, + 0x9adc5151, 0x98c31163, 0xec1ccfd1, 0xa3d7d88f, 0xdc2ac17b, + 0x46421097, 0x08fa64d3, 0x94b90bcf, 0x5ebf80b7, 0x0b50a9eb, + 0x1b78b4ba, 0x279aa66b, 0x1a4fe934, 0x075b3ced, 0x8ef4dcaf, + 0x70a6e9ae, 0x95bbd8a0 }, + { 0xe614bbd0, 0x59f92495, 0xb823e363, 0x7567a887, 0xfc1bd6a7, + 0xe247c9ec, 0x8e835c42, 0x2bfaaf47, 0xaade066a, 0x314ef4e0, + 0x5c16d336, 0x072baa63, 0xe2f0e389, 0xfa429c71, 0xbd07d90f, + 0xcac1e5d0, 0x514f5c04, 0x69ff35ea, 0xc0554ec1, 0x893053fc, + 0x2a35947f, 0xab1d86b7, 0x2aebe487, 0xe29fb060, 0xdfb9cf21, + 0xa0a10d6d, 0xf20dfcf5, 0xad147059, 0xb8867a2a, 0x480dc66f, + 0xc125a919, 0x375a884f }, + { 0x1217f7ea, 0x178cbe2e, 0x875c6dab, 0x1a161e2a, 0x1bdb1a54, + 0xf7707ec0, 0xe4fd73ca, 0x678864a0, 0xd13a0d86, 0xbaebc664, + 0xc8d30668, 0x40325f99, 0x2f1c5950, 0xb93ed9c9, 0x541e0667, + 0xfdf36763, 0xb91a6763, 0xfd97fbb0, 0x6079c9a0, 0x26aa69ea, + 0x1eaa8c47, 0xc7303c80, 0xafa63c55, 0xdec75c81, 0x4fd12adb, + 0x01cdcde2, 0x1968838a, 0x9fe0dda7, 0x38415379, 0x66bb093b, + 0x08cb84ec, 0x268d818b }, + { 0x41580555, 0x73dae358, 0x473d103b, 0x4fc32e67, 0xbeccc1ab, + 0x240c1013, 0xb24ee9de, 0xda4099f2, 0x9fa8e066, 0x37b0cb5b, + 0x6438d7ee, 0xb5ae04e4, 0x2b720140, 0x7f7d3164, 0x339e4a78, + 0x86ef4edb, 0x3a7d8375, 0xa5e77eed, 0xbd707c2e, 0x883fad37, + 0x0f979189, 0x816b633a, 0x2e7a208e, 0xe24c028a, 0x4435516a, + 0x1171fe3c, 0x4f5f2bf5, 0x3eb93b33, 0x01b53a56, 0x8419ed4b, + 0x056ca44b, 0x8b02735c }, + { 0xe1019195, 0xb89bb464, 0xf3fc28c1, 0x1de4c026, 0x2bfc3b21, + 0xac120e6e, 0x91bdf92f, 0xec71bc5a, 0x0d995bc9, 0x485d7ab4, + 0xe6491ffe, 0x97c6768e, 0xafbce265, 0xd9552d19, 0x8e1b76c2, + 0xbae6c7fe, 0xd7e3ad1b, 0x167d8281, 0x5e989734, 0x3e149af9, + 0x8a0c8182, 0xd1f0024c, 0xc3006c0d, 0xf571ffdb, 0x58773d4c, + 0xb32ecf7e, 0xfd3540d8, 0x5822a782, 0x04365042, 0x5ab45c3f, + 0x4b4d85fe, 0x400e3aa0 }, + { 0x5e46e4a2, 0x47321649, 0x24136074, 0x37a2ed64, 0xc60ec77d, + 0x659223b1, 0xe5e0ac2e, 0x5e13aac3, 0xc5107ab7, 0xda17c41b, + 0x73c253db, 0x65b22ec9, 0xa5012296, 0xff3867b8, 0x0621a99b, + 0xfed660d5, 0xc89fc3f5, 0xa3c28506, 0xf16451a7, 0x3ed350b9, + 0x67cb586f, 0x27c3e032, 0x967185b1, 0xc807c779, 0x4a13009b, + 0x09c157d4, 0xadaf1f4d, 0x362f7647, 0xf3a6a198, 0x4a42b9ac, + 0x8da6e039, 0x131c3da2 }, + { 0xa7da83ba, 0x4a785ff1, 0xd04f4436, 0xf415b425, 0xec03f812, + 0x7c0899bd, 0x80f5f4a2, 0xc58d411a, 0xfda251b9, 0x3d32d610, + 0xcd3b2f32, 0x99bb4504, 0xf4c2083c, 0x198c444b, 0x730e83fd, + 0x60c261af, 0xcb02db90, 0x060ca4df, 0x9df1e7c8, 0x0ff7838b, + 0xc4c690c9, 0x6b79cf97, 0x5d75f154, 0x131514d7, 0x1cb0e8ff, + 0xa7c074f1, 0xb2c17615, 0xb920aac1, 0x44aa0ff0, 0xde8098ad, + 0x34545ce9, 0x71d1a46a }, + { 0xfa1b382e, 0x76178f76, 0x772dda0d, 0xa0d8ecc3, 0xc5d4d130, + 0xaa5aab2a, 0x8d72622c, 0x27d38ba4, 0xca3bed06, 0xc5410db6, + 0x793ceccf, 0xf637a588, 0x6e65e3d7, 0x1f65dafd, 0x60a45641, + 0xc3b44a85, 0x4f78540b, 0x0f47b3a8, 0x5e4d60f6, 0x824fdadd, + 0x17d3b6d5, 0xd8ccf90c, 0x325fc13a, 0x008eabdf, 0x3648fab9, + 0x3e90d716, 0x24c52d4b, 0x3964ff3a, 0x533d0acb, 0xb95cc416, + 0x1167f521, 0x6cd2699f }, + { 0x12f4f3ac, 0x2d8c0b3b, 0x99d1bdfb, 0xb03dcfe2, 0x30f37326, + 0x540034f8, 0x7c5a8c82, 0x22dd6893, 0xcd8f1442, 0xeb7093d0, + 0x585742f2, 0x892795a7, 0x087adadd, 0xe15f282c, 0x16ab7b5e, + 0x7bbdc749, 0xa58acbb4, 0xd30fe40b, 0xe2bac39b, 0x0de417eb, + 0xc61a04bc, 0x4b4b19a6, 0xf2735569, 0x9338c34d, 0x30ab196f, + 0xe8f03742, 0x6c88c965, 0xfa2efcb8, 0xc7eeb826, 0x19eee274, + 0xda345dc2, 0x327c063f }, + { 0x5b47cd53, 0xab399eff, 0x1943aefe, 0xbbe9869d, 0x1402a866, + 0xe64ecc7b, 0xb1c25a16, 0xc3e7c2aa, 0x022de271, 0xc4216b79, + 0x366d6a5f, 0xe58dfcc8, 0xda813336, 0xd159509e, 0x130bfb7c, + 0x370400f2, 0x93b48780, 0x1be4e059, 0x39f3cd22, 0x0623a1fe, + 0xeecb4f87, 0x72aa22b2, 0x6c27b83b, 0x1af4c496, 0xda5fa5bf, + 0x7a42a94b, 0x48b01af2, 0x9afba822, 0x3670112c, 0xeb6b9d2a, + 0xc0df6856, 0x020f19d1 }, + { 0xa4dbba20, 0x37051a86, 0xdb1de5c5, 0xb618ebc6, 0xe6525840, + 0x9a780a19, 0xd2bccc4d, 0x9440302d, 0x10285a24, 0xe9ff023d, + 0x3a486268, 0x3b937ee3, 0x4cd61147, 0xe37ee2f2, 0xa3d057cf, + 0x79fbbfd3, 0xccddefce, 0x5fba16d3, 0x5b231727, 0x916058ec, + 0x720c3adb, 0x47699ebe, 0x8b4f6bba, 0x26274386, 0xf18a0770, + 0x54b0092a, 0xacca1160, 0x99d090eb, 0x0c888f60, 0xf757e1ff, + 0xb0050544, 0x79e72720 }, + { 0x2820a239, 0x632acf25, 0xaae6b310, 0xb1a3974e, 0x48c0a1df, + 0xd61fd6ba, 0x5a3ee7aa, 0xd2453c39, 0xb980446d, 0x548455a0, + 0xde16676f, 0x9f29d97b, 0x789375a1, 0xf252ca0c, 0x7743a985, + 0xe961af3e, 0x66cdbd8d, 0x70c79c56, 0xcbc538f9, 0x14a3854e, + 0xa126851c, 0x58daa73a, 0x2a9f558c, 0xe9b5bb45, 0xfbd15e05, + 0x37af7f83, 0x38a1939d, 0xa4487927, 0x9511a056, 0xe428b2b5, + 0x7015846d, 0x001d3ce3 }, + { 0xe145b1d7, 0xd6be36b9, 0x009c5664, 0xf3e3938a, 0xe7c0f6db, + 0x2e562e7d, 0xc343f539, 0x951044e6, 0xd90897b1, 0xa5ab62b8, + 0x512f797c, 0xb1a1f70b, 0x750f28e4, 0x91cdd754, 0xffb8165d, + 0xb4c80e2f, 0x594d02b3, 0x65ed39c7, 0x56833edc, 0xcc12a49d, + 0xf3693a18, 0xe73694bc, 0xfcd2c404, 0x34cc134a, 0x11d40194, + 0x071bd5fc, 0xfc585e46, 0x05759047, 0x790b7a04, 0xb3280360, + 0x40afc684, 0x4bb8c6fc }, + { 0xfd0f8796, 0x3120e2dd, 0xb133c9de, 0x6968a40d, 0xa9369c6e, + 0xfea366c0, 0x6007273b, 0x37e5b6d6, 0x8cb81439, 0x39e4ecf0, + 0x9febc005, 0x487fe9cd, 0x0199b53c, 0xeb8af444, 0x293519eb, + 0x2f124e3b, 0xc82c9c16, 0x860c218a, 0x709dc590, 0xacd1d6f2, + 0x36d50529, 0x5696d545, 0x59120bfc, 0xc03f5df9, 0x10ffa690, + 0x99a3e88d, 0x6c432827, 0xd4f9cfa5, 0x9a135d89, 0x2e8fea9e, + 0xb6a77e78, 0x3699a881 }, + { 0x1eb1c64d, 0x5bca3372, 0xf1d28154, 0xe9cf3a2d, 0x6537106f, + 0xb7e2e9b3, 0x4f7cbf4d, 0x06c17151, 0x2058b37f, 0xcbde416e, + 0x8834e9c5, 0x82c53a7e, 0xe9ac3a75, 0x94dbdfe2, 0xc5e67c02, + 0x795ec6cb, 0x1426a80d, 0x8c23c25f, 0x6a8d4f9f, 0xee2cd20d, + 0xd3b7c235, 0x838daa54, 0x3d7a4d52, 0xb9e08ec0, 0x781cb473, + 0xca9475e9, 0x5ec31caa, 0x7271f39e, 0x82535187, 0x1df08e9f, + 0x208aff8b, 0x4f3a4b03 }, + { 0x1ed095f8, 0x0f7b8107, 0xda226d4e, 0x23e37fa6, 0xafb36d1d, + 0x8b0f9852, 0x07d8e311, 0xb114634e, 0xe3e0f16e, 0xb9634a97, + 0x421eec37, 0x2454bb9c, 0xd72b21c1, 0xb4ecd5db, 0x6df20d7c, + 0xf9603868, 0xdf86e0a2, 0x9f5359fd, 0x5ac488aa, 0xc43d54fa, + 0xd1049df4, 0x56d714ab, 0xb020607a, 0x13152b3e, 0x7a02325e, + 0x49be1c18, 0x52ae84db, 0x44f24f4a, 0x0b5a7b80, 0x9e525c03, + 0xa6d179fd, 0x6d874446 }, + { 0xbe9a42f5, 0xd29d07aa, 0x3781ccc8, 0x1fd5316c, 0x9dc69ea1, + 0x71a75a6d, 0x88fee91a, 0x4e19e0df, 0xf8d44f12, 0x99c2b4dc, + 0x31ae94e4, 0x05f6df92, 0xcf28ccc2, 0x27fba876, 0xf57f7ceb, + 0x6e1a0f01, 0xf3fd3b74, 0xe03f1f34, 0x42c1d213, 0xa0edc4a7, + 0x7deb8580, 0x5caac270, 0xaf0848bc, 0x0f5d791f, 0x07ac759d, + 0x17f514ad, 0x904fc531, 0x95a39734, 0x7bb70f3d, 0x95a4aca9, + 0xff9c5609, 0x3cf384c9 }, + { 0xce1fc9e3, 0x700506ba, 0x676b0399, 0x49721742, 0xe72bf7b3, + 0x2b4a1b8d, 0x79b209f7, 0xca8602a8, 0xce26a8e1, 0x90580b90, + 0xfe24f39a, 0x1ef339b7, 0x629362e1, 0xb6c5d991, 0x577b24f4, + 0x51174e1a, 0x05e451e9, 0xf380fcb5, 0x148321bd, 0xf4d97afb, + 0x747e5d2a, 0x099806bb, 0xbe99a608, 0x85525d65, 0xd455e820, + 0x264828d9, 0xd8560a65, 0x8c8c5405, 0x71030770, 0x3c67e73c, + 0xee73df26, 0x2b248850 }, + { 0x8541159f, 0x2173cde6, 0x4fb410b2, 0x78224c18, 0x1f2ca1c7, + 0x07a28619, 0xa8b23e40, 0x52c207d6, 0xa6b2344a, 0x071a0210, + 0xb5ed2945, 0xdb0e587c, 0x810fcc6c, 0x6c56b8ef, 0x62d843b9, + 0x1248c58f, 0x74c66975, 0x4b90363d, 0xe66c66f6, 0x6348f7f2, + 0xc126bcbe, 0xb2f9d441, 0x73ce49e8, 0xac07f2a3, 0xe81b0df0, + 0x52486758, 0x1d4621d1, 0xa108b54d, 0x74414a1c, 0x17261ece, + 0x6a3ac215, 0x938b3bcc }, + { 0xe4ded340, 0xa9e4a16b, 0x80e88036, 0x8e65fb2a, 0xdcd73acb, + 0x97089606, 0xaaa657a9, 0x1c3a0434, 0x49101b06, 0xf304fc58, + 0xda0bb64c, 0xe60fb61a, 0xf5542df5, 0x818c2aec, 0x56f76d5f, + 0x74020576, 0x92533d97, 0xb566b790, 0x74d6eb5f, 0xae4655e5, + 0xa55b44b7, 0x60f7a1b5, 0x93747ea5, 0x7970179b, 0xf2dace56, + 0x8ae7e0e8, 0x84e83c06, 0x98474607, 0x15307341, 0x24e8c9ed, + 0xd9e89d6b, 0x6cff58a5 }, + { 0x03e51f68, 0x508c01b0, 0x1d2fe7d6, 0xe1d1f225, 0x09bd8805, + 0xf7998d0b, 0x03e415b7, 0x255e907a, 0x607d9798, 0xd148467d, + 0x9b453896, 0x055c3b1e, 0x809f50f4, 0x35001013, 0xd0233fdc, + 0xfbbb2fa6, 0xff1820b8, 0x0b680b0a, 0x38d317e0, 0xb1d404dc, + 0xccc8c7df, 0x133d5444, 0x6ec13f84, 0x7fa847e6, 0x046e2e48, + 0xc33f83d8, 0x4863b3ac, 0x3c627fc5, 0xeb936af7, 0x5f67f8aa, + 0x31b79327, 0x5fe4ac8f }, + { 0x8b6f401e, 0x581aa4bf, 0xad5c7ed4, 0x05db12a3, 0x6fb07b4a, + 0x7b018726, 0x9c22bcd4, 0xfdd11f04, 0x69371c95, 0x5454a7d4, + 0x99a46eaf, 0x066c55fb, 0x7fef96d0, 0x18637c7c, 0x6b83e95c, + 0xbafc1d34, 0x00bb42dc, 0x55c38593, 0x34e7e712, 0xdd8dec2b, + 0xb184cee8, 0x69c9cfb0, 0x49a27864, 0x8dcc0c42, 0x2010f2e7, + 0x290d95f2, 0x6977a420, 0x86e254c9, 0xeb2abdad, 0x20931c89, + 0x121c0548, 0x81377164 }, + { 0x9c5a8edf, 0x6266b25e, 0x1078a7ad, 0x6e1388c2, 0x4876eedf, + 0x5f02737d, 0x62744617, 0x242fa7f9, 0xb385382a, 0x3e2cfbd9, + 0x02f71bef, 0xbadad7b1, 0x677d0a92, 0x562abcfa, 0x51fdff34, + 0x573ebd17, 0x7c250c78, 0xd7f65852, 0xc47ca896, 0xe0cf16ee, + 0x67622c9e, 0x8ccd79b0, 0xf8f2c075, 0x31fc5882, 0xa6008515, + 0x9232b37e, 0x82e8c5ba, 0x4d7bb361, 0xd2f146fe, 0xbf24735c, + 0x9cd2db98, 0x79c280ee }, + { 0xf2b48122, 0xbdcc8203, 0xb04ac48e, 0xa8c04916, 0x9fc4885e, + 0xacf064dc, 0x82c1001c, 0xab838997, 0x676de250, 0x7339e721, + 0x8e1ab820, 0x17aa5aea, 0x6bc14b2e, 0x24d28ca0, 0x816b6230, + 0x570c5bb7, 0xcee6b606, 0x6c51235c, 0x183eae42, 0x1b2bf89f, + 0x9c66274b, 0x3e3af3c6, 0xb51e38bc, 0xe0b04426, 0x73e40e3b, + 0x26dbc58e, 0xb5be5be4, 0x3f9dd578, 0x52c8f408, 0x9fd9f791, + 0xa9e3ff4f, 0x758073a4 }, + { 0x8691ca22, 0x7d27b057, 0x13a2a1b6, 0xf206bfd6, 0xac795413, + 0xe84bd385, 0x75536607, 0xc5d18a2a, 0xc8a0e24c, 0x2e166de7, + 0x3c474dbd, 0x56d5750c, 0x1366843a, 0xdef444c1, 0xcf4b8432, + 0x14646e53, 0xa9fd9783, 0x4bc0d030, 0x297ee203, 0xbda4c824, + 0xfd7be6c7, 0x3d0b10bf, 0x08c7f3ff, 0x2d216476, 0xb4fd4c45, + 0x06e52599, 0x49e9e104, 0xfbab9fa1, 0x8661d32d, 0x9342a7fa, + 0xfaf66aa8, 0x3f3e3458 }, + { 0x951597aa, 0x51ec35af, 0x49df64eb, 0xb677d4ac, 0x9bf4eff5, + 0x0276cd9c, 0x515a2935, 0x423eca49, 0xfd9bb9c3, 0x8a696553, + 0xede1f09c, 0xf99ee9df, 0x199e5f98, 0xb8fa2956, 0x35292c32, + 0xb7638758, 0xfc40e81b, 0x8734eddc, 0x65457d95, 0xd82d5e9f, + 0x30c78d2b, 0xc8ee323e, 0xc1433d67, 0xe77b2e4c, 0x3c8314ae, + 0x56d9f807, 0x2a0e2f63, 0x441eede2, 0x6c48295e, 0x1e9e17ed, + 0x34c294ef, 0x640d20c4 }, + { 0x3284d513, 0x4e9a0b8e, 0xf315053a, 0x074c3545, 0x45acd52a, + 0xb36e7407, 0x1de50db7, 0xd80bdcfc, 0x2549fc46, 0x8d9d47dc, + 0x303f07a8, 0x29b6ef13, 0x6d4ad4c2, 0x4e461aca, 0xfc9f1b73, + 0xca8e351d, 0x57460e65, 0x8bc4094d, 0x0f32d367, 0xb6302b33, + 0x285742e8, 0x69a074b6, 0x876c29c3, 0xdfe52b11, 0x912bd17a, + 0xf39e4609, 0x349aa639, 0x8ee40d66, 0xc72e05c1, 0xb968902a, + 0xc0d92816, 0x0f9c1ca8 }, + { 0x67433df3, 0x1ebbaab3, 0x15d3628c, 0xb6aa5347, 0x97f0c5cc, + 0x13a320d8, 0x65e408f9, 0x72c918cb, 0xd5373451, 0x4b638854, + 0x0b4dca09, 0x731399a3, 0x0a3b1326, 0xcf256730, 0x6608b388, + 0x5ea60dfa, 0x7b290dfd, 0x58ad74b0, 0xd7694f9b, 0x83202789, + 0xb6630fb1, 0x48593db8, 0xc65e3eaf, 0x3db47f70, 0x3e7263f8, + 0x63949c91, 0xe6e6ff33, 0x9b9acec6, 0x098a8240, 0x34bd9ba7, + 0x45d36ec5, 0x7e31c12f }, + { 0x0dfd2dd7, 0xbe281d68, 0x24ab61d8, 0x1efacb00, 0x94431f97, + 0xb9c3005f, 0x959cb3bc, 0x660c8dfa, 0xcffbb406, 0xfdd5fc30, + 0x7969a10d, 0x7a4631be, 0xde13fd1b, 0x336e309e, 0xfc947076, + 0x76b3bfad, 0xdcc72223, 0xfa91925d, 0x156c4ee1, 0x741f0d73, + 0x0e2b3747, 0x4f64ee41, 0xefc4d93c, 0x86be92d3, 0xfc4fbb2e, + 0xc53b7e03, 0x337ca1bb, 0xac196cf5, 0x7e23ba60, 0x4de41a30, + 0x326d5357, 0x1a219c45 }, + { 0xaa4db0bc, 0xfdcf7ef8, 0x7b6c9963, 0x2e231806, 0x3d8a192f, + 0xc2639067, 0xffdc7771, 0xc0cec2e2, 0xa2fc0edb, 0x997c8e35, + 0x82cc6043, 0x78e10ec1, 0x2b0c8120, 0xfd0de2cb, 0x69e57f8e, + 0x4d6c457f, 0x5b53f1c3, 0x953e69b2, 0xc4f89cb8, 0x422a330a, + 0x95566be6, 0x92ff2329, 0x437442d1, 0x73cd502d, 0xbea69403, + 0xf04ce590, 0xf8030662, 0x6ac1537e, 0xb6d0bf93, 0xe02bcf77, + 0xbc90192f, 0x17aaa999 }, + { 0x8e55db2e, 0x0d3d5643, 0x3b946851, 0x835dee43, 0x5b88462f, + 0x1a1440e5, 0xea17e27c, 0xa6ff3b35, 0xdd95f7a9, 0x23f99c36, + 0xbdd672cf, 0x7217fdd9, 0xdd2045c0, 0xf400ac1e, 0x4ff06b25, + 0x94b55c87, 0x0e4a49be, 0x0a44a0e5, 0xb43b6813, 0xe8925e91, + 0x214f96c5, 0x78bedde1, 0x0f97fa97, 0x0f456a4c, 0xa5bfd267, + 0xa28fd86b, 0xbe7608ef, 0x3b4b2d8f, 0x226474bc, 0xfbd5ff8c, + 0xa5f3b24a, 0x6b282af0 }, + { 0x6341a595, 0x78fc025f, 0xa445e28c, 0x591c38d6, 0xeb446842, + 0x72bd6e3d, 0x75547833, 0x3f9466d3, 0x083e16c4, 0x911414d3, + 0x95a7acb4, 0x145d9466, 0x8fd2fb64, 0x102ddf09, 0x0bfd87b1, + 0x2a2b2d2d, 0x59455088, 0x69e9be5c, 0xa80245de, 0xee378bf4, + 0xb2306b0e, 0x80b0bd68, 0xc2be9f3d, 0x76a545c6, 0x4802c245, + 0x429d167b, 0x2b412dfb, 0x13e64427, 0xee8d9762, 0xb664f529, + 0x54706ebf, 0x6d4f5d23 }, + { 0x00ba9f88, 0x35c8f2b6, 0x7bb6d0bf, 0xfdc807e0, 0xb3b81e5b, + 0x0a126d42, 0xa7ac781e, 0x335ce6ce, 0xf37dcba6, 0x3e308e6f, + 0x63c96487, 0x028dca62, 0x8818434d, 0x72eba57e, 0x79b78a26, + 0xa9e3d59f, 0x2f07aea3, 0xd2f0a7dd, 0x24d05f74, 0xe0fe4678, + 0x0116deb6, 0xb2085170, 0x58f37580, 0x9c2a5e92, 0x74070bb3, + 0xe78bd7a5, 0xb9977d90, 0x551fc872, 0x40db81b4, 0x6eda93c4, + 0xd65d34ad, 0x4aaf0b4f }, + { 0x3514c7af, 0x9bef2506, 0xbc181ead, 0xb09e7dad, 0x8fa3ec58, + 0xef3cae87, 0x173b8685, 0xd8dbfab5, 0x921d32dd, 0xb2490fc0, + 0x8bd9c466, 0x4eef386b, 0xa061dbdb, 0xc1cdd52f, 0x25bc04db, + 0x64de989a, 0x85728636, 0x06f9836b, 0x8be44aa0, 0x11a5a804, + 0x097018c7, 0x16dede4e, 0xb2c11fb1, 0x72aec577, 0xa721ecd9, + 0x144dade1, 0xd6ebf3a9, 0xf99c526b, 0x1c2e14d7, 0xa1d4165b, + 0x82bc6337, 0x8b2cbd39 }, + { 0x8a52e991, 0x28ec1bf2, 0xcf9d42ec, 0x0ba202f6, 0xc634ea45, + 0x8307d130, 0xc5762b9c, 0x3fc257b3, 0x487c2a2d, 0xbd3298d1, + 0xa319488a, 0xca14f1a7, 0x06ba06d2, 0xc70ca93b, 0xee405e89, + 0x9aa3f4b3, 0x35deeae7, 0xcc64eeb3, 0x03bf1d4c, 0xd155f578, + 0x45616bfd, 0x041ec0b5, 0x086e33f6, 0x23df80e6, 0xf0243cf5, + 0x399a79c8, 0x874ccd58, 0x86c2824e, 0x8fc5c831, 0x220eeaec, + 0x7dbe3670, 0x57e28304 }, + { 0xfbcdf666, 0x6e60b698, 0x8bebb1d2, 0xbdd06a99, 0x80498436, + 0x4044adba, 0x522bc88d, 0xd76bf75e, 0x28423b20, 0x655c4b9b, + 0x53398a72, 0x65c0f492, 0x0ca37601, 0x76d4f2b7, 0x2030fa5a, + 0x46989925, 0xb6054705, 0x96b37e87, 0x53de1b2f, 0xef96f731, + 0xad54ef05, 0x5ecbbc8c, 0xa93617b0, 0xeb289d0a, 0x7cba217d, + 0x3ac0fbd5, 0x19d4a2d7, 0xd0d3cb56, 0xc91d6063, 0xe8bee9d4, + 0x696ffda6, 0x4f12e037 }, + { 0x15f1a610, 0x4ccfa422, 0x3786519a, 0x804a5c55, 0x73838134, + 0x1246a454, 0x4b284e2a, 0xfa15b484, 0x146d1320, 0x36464c65, + 0x70a8a0fa, 0xfb6ba88c, 0x93c4804e, 0x74e7cee7, 0xb95ae16a, + 0x8c34d22c, 0xf9c1d4dd, 0x9d9ed89f, 0x32025371, 0x61a0866d, + 0x9bd6444a, 0x45b232b2, 0xf277bab1, 0xf888e92c, 0xa9448b02, + 0x73e69c6e, 0x5b521ecb, 0x1a496ea9, 0x5858afb2, 0xa8f78ea7, + 0xb1266f91, 0x83d2333e }, + { 0x67b478d7, 0x1c633288, 0x50a2fc9c, 0xa1ee1ae1, 0x18d2241b, + 0x05b6ab30, 0x893cd696, 0x69f1f288, 0xa8117a87, 0x159d6660, + 0x70e73d77, 0xe8120119, 0x93f55f0a, 0x528fef00, 0xd854dfb2, + 0xb3978db8, 0xf45d9fbb, 0xd6b43ef6, 0xd5bee397, 0x17de4bfe, + 0x6bf76dad, 0xa01e0f59, 0x3d40754c, 0x28b2280e, 0xf8e86ef3, + 0x8edb6122, 0xb7d1e586, 0x8226b6af, 0x2f40a55b, 0x46353215, + 0xc5a31621, 0x7362f13e }, + { 0x73c0c430, 0x792eb27c, 0xa51c3657, 0x8cc0a65f, 0xd2194f1b, + 0x50a5cece, 0x814b4947, 0x18945688, 0x4b6fbbf4, 0xbbf0a81a, + 0xf0aa8608, 0x376f4f58, 0x3987795e, 0xd9361d68, 0xe3a8d0d5, + 0xb6510cd8, 0xb6c1a455, 0x63e2fdbf, 0xaec891f9, 0x2c91154e, + 0xff568f64, 0x0eb1e715, 0x2f2b399e, 0xe7af9cd7, 0x89f0bf0b, + 0x1fc39bac, 0x90983695, 0xf0861d92, 0xda0a20a8, 0xd9b16f02, + 0xa38c0ead, 0x2f10693f }, + { 0x0c06ded2, 0x07a6ce91, 0x2fd9087b, 0xf974842f, 0xa9f635a6, + 0xe468bfd6, 0x1ed60626, 0x04b61891, 0x369ee548, 0x1fb2f89f, + 0xdc96a201, 0x9cbd1113, 0x10d633ac, 0x6759acfe, 0x8faa629e, + 0x64ba66fc, 0x47f38283, 0xa686ae49, 0xd59cda99, 0x828c3a05, + 0x08ea2f6e, 0x7c7afb14, 0xaf3953c8, 0x2551c8e4, 0x9daa9e4f, + 0x5b53d279, 0xad6f1940, 0x1eff68d4, 0x96437cdb, 0x2775dbdd, + 0x4fe7a043, 0x985f83e4 }, + { 0xeaf45294, 0x89603c16, 0xc24b5751, 0x70131160, 0x39d6b52d, + 0x4c112018, 0xed943340, 0x7079cf02, 0x74f41b68, 0x0c5b028b, + 0x9c8ac1e1, 0x3dc3f076, 0xf8b24f0e, 0x5ac5eea3, 0xe34c5c22, + 0xee6684ba, 0x9abc452a, 0xa5259e63, 0xe9df45cc, 0xb07d2cd1, + 0x1a443cfa, 0x07019c93, 0x92c003b3, 0x68fddaa9, 0x0d8cbc2e, + 0x2d9f179c, 0x1e781ca7, 0xbbf15a6f, 0x50dcc799, 0x54d779d5, + 0x0fe962f1, 0x0c88e540 }, + { 0xe8f44357, 0x84f71a6a, 0x3a3cab6a, 0xf75b4bf6, 0x5aebc680, + 0x334c9d9e, 0x8a753ef2, 0xcecaf084, 0x075e3c8e, 0xe28014c1, + 0xf74f8d3a, 0xbb9d5a38, 0xb80e32ae, 0x75988464, 0xf2bc3792, + 0x7b328e6f, 0xeed0e197, 0xebbb1faf, 0x5a33065a, 0x674eac95, + 0x922dbce8, 0x8c19fd8f, 0x987b907a, 0x8c17ae85, 0x3b3a2cd7, + 0x89f33627, 0xfa87772f, 0xebaea019, 0x3a25ced6, 0x4e5de499, + 0xaf110715, 0x8e2560b8 }, + { 0x3141aba6, 0x56d3746c, 0xbab2cf9e, 0x45a1079f, 0x9cdd27c7, + 0xb6382831, 0x9dfd950e, 0x22237632, 0x3a9408ff, 0x1e0b15cd, + 0xb1160118, 0x49a80200, 0xa383bba7, 0x2719db5d, 0x651046d5, + 0x6078340a, 0x97523b1f, 0x8929d4de, 0x8e0a28ab, 0x4040345c, + 0x0adf09c7, 0x61275ac2, 0x2331d611, 0xb41ab265, 0x5391ca50, + 0x230cc77c, 0x8f922315, 0x88be0c92, 0x92fd9a29, 0xfef3d92b, + 0x8324f2e5, 0x59005f22 }, + { 0x3c4c1c74, 0x6bb1750c, 0xe966fb79, 0xbe73aac0, 0x66c5973f, + 0x85a75d92, 0x3a8656b6, 0x8c97f932, 0x50446cde, 0x2b7043b1, + 0x3ff3897f, 0x548916f7, 0xb18b72b2, 0x913dd01c, 0x488c0de6, + 0xd0a751f1, 0x8558ca58, 0x19175714, 0x44a663da, 0x97714301, + 0xb0e08618, 0x2df190ac, 0xf39ead9c, 0x0080fc0c, 0x17382da1, + 0x0085ac6e, 0x3262a338, 0xe9791851, 0xb43bae8d, 0xe4495936, + 0xd783df6e, 0x57a78e26 }, + { 0x40dbddd8, 0x161b346f, 0x9410c3ac, 0x2b49a927, 0x1886cf3b, + 0x8c542783, 0x33b93deb, 0x72df3232, 0x40df579d, 0x9c8d59f5, + 0xc20ef500, 0xe5d7a67d, 0x67f08643, 0xc46b3918, 0xad96adc3, + 0xecfa2445, 0x0c4544d0, 0x658f589b, 0xe08417d7, 0xe6ec9301, + 0xc454e288, 0x6ca5ef6a, 0xac0f462d, 0x4191048f, 0x08d8a036, + 0x852407d8, 0xf6d35b7e, 0xb4c533a7, 0x8f6ada87, 0x3251e412, + 0x81c472e8, 0x1ca370c5 }, + { 0xa801b68a, 0x94bd5171, 0xfd1998b3, 0x7312879c, 0x41163202, + 0x4905aabf, 0xf5b01fdb, 0xb5fe87f4, 0x9cda128b, 0x78de523a, + 0xc7bd31f7, 0x0bf161a1, 0x23904c35, 0xb5decfd0, 0xe188f12d, + 0x224b2882, 0xf99dae74, 0x0dd2801d, 0x08cd1cd2, 0xcad467b5, + 0xc0867e39, 0x6c311c3d, 0x2b425072, 0x71a11720, 0x2efd9003, + 0x83bf464e, 0x1dbd3b03, 0x53d0448a, 0xe6265baa, 0x32db52f4, + 0x4c33ac79, 0x2584b34c }, + { 0x2aeec688, 0x3cb86389, 0x45fbe523, 0xa5e740ba, 0xfd60b5f8, + 0x422e71f7, 0x4874913d, 0x455d185c, 0xfa17d80d, 0x04c2bb36, + 0xac054524, 0x3f271854, 0xa8b9a657, 0x76dd3045, 0x62ee7cc8, + 0x2e42c3e1, 0x4df6c7d0, 0x00266706, 0xdc7cb488, 0x5927dd51, + 0x187897e0, 0x6b3faabe, 0xf2d5737c, 0xfe6ad22e, 0xff51a9ff, + 0xafb60269, 0x69807baa, 0xe1c83545, 0x951ca49a, 0xacddb6ff, + 0x3f9ab085, 0x7e811374 }, + { 0x830a88b1, 0xad722a8b, 0xce1117e1, 0x91918ea8, 0x0409b47d, + 0x3e02d0b8, 0x6c46d1d3, 0xb53812d3, 0xe589669c, 0x2fd09db0, + 0x15b0cd5e, 0x9845cd06, 0x2386c453, 0x0c1c155a, 0xf5ff43cb, + 0xda774de5, 0xe391c0cd, 0xbb076b98, 0x5004f286, 0x97d71eff, + 0xaeec0bfe, 0x23e0b46c, 0x32a1ad94, 0xe4538667, 0x396da422, + 0xfe0c9f81, 0x63db2bfe, 0x6376c1a2, 0xba56fa91, 0x001c7918, + 0xdf8485a6, 0x436b8c64 }, + { 0x8ab764bc, 0x88117e9d, 0xa077df84, 0xdfa61e94, 0x0c18eebd, + 0x5a7765d3, 0xfc9451dc, 0x548916af, 0x071a347a, 0x01a52e33, + 0xb23b41df, 0x633b95de, 0x43c8c286, 0xdd7d68c9, 0x18d97068, + 0xe4f9d41e, 0x8c92799d, 0x79908b90, 0xd47394a3, 0xe614148e, + 0xcd51e53f, 0xe5018517, 0x0243dcb6, 0x5060075e, 0x17954405, + 0xe5dcde62, 0x537da5ff, 0x6f7c90e1, 0x0768cb66, 0x1df7aae4, + 0x6dbe95e1, 0x5266ca9e }, + { 0x1386b3db, 0x84ddee6d, 0x7c38e540, 0xf9e4af5a, 0xeb04f49d, + 0xb3418440, 0xfde5a4fd, 0x2138a1e8, 0x30257cfc, 0x3e6e6924, + 0x19fd70c1, 0x3519c6e3, 0x86c31ff0, 0x8f34e174, 0x940ce1e8, + 0xf1e298fd, 0x14960d7c, 0x6fb8cb1d, 0x2b2f3bff, 0x207c1347, + 0x146ef8ff, 0x899a20b4, 0x7bd3e220, 0x7dec362b, 0x626bea27, + 0xa975044e, 0x4fb4cb67, 0x0f32b449, 0x1fc6703a, 0xc17a0920, + 0x9cd84a2b, 0x41f325b9 }, + { 0xce2843a4, 0x312ed513, 0x00728afc, 0xe748498e, 0x4d864ce5, + 0xa8ef2822, 0xa620083b, 0x34064704, 0x4bed338d, 0x5905e1d9, + 0x063e7b38, 0x2a578cb5, 0x289e7bb9, 0x98276d96, 0xf17b7341, + 0xdfe2dc47, 0x1dac8944, 0x5923521f, 0x23400aa7, 0x3db6d28d, + 0xa761ba43, 0xc647705e, 0x9bfd07dd, 0x8947ba6d, 0x242ca8fd, + 0x00f2e3ac, 0xeb8c3468, 0x49ef4670, 0xd9aa18fd, 0x7db3d37b, + 0xe58cea9e, 0x56b30fb6 }, + { 0xcd80a428, 0x07ecdcaa, 0x8732c891, 0x7af922dc, 0x3ada441f, + 0x20d88798, 0x924b008a, 0x3bed9a44, 0xb2e81c3a, 0x2123533c, + 0x65f807d3, 0xc34e4075, 0x1f2faecb, 0x0bfaefa5, 0xade8a88d, + 0x78b634a5, 0x94392a91, 0xc4e0b7f8, 0x90bb1cd8, 0x30922377, + 0xf87204ae, 0xdea9b4fa, 0x85d3cd83, 0x3edf81f5, 0xc6523a79, + 0x58f88c51, 0x17c0d969, 0xe472fb8b, 0xdccf7f07, 0x899081e5, + 0x58bdd146, 0x1353cc57 }, + { 0x39bf6e18, 0x28a56497, 0x649b89c7, 0x59e8b5a2, 0xdce8b8e7, + 0x8d9434a0, 0x2047040c, 0xd935bf51, 0x6a7b8e82, 0x2ab3a164, + 0x27f81294, 0xf1583ed6, 0x72d67297, 0x8416a7e0, 0xcd39e42b, + 0x49685d86, 0x958ddbad, 0x8a797fc7, 0x155ce6de, 0xa558f928, + 0xf8a36235, 0x75f4e570, 0x52877ae5, 0xbc69cfc0, 0xa6b16ebd, + 0x8f4193a9, 0xbb1cc1f1, 0x8d1df43c, 0x5a21e789, 0x723a830e, + 0xf451df58, 0x3ec2185d }, + { 0x1f0bc2d7, 0xb9d4c7d7, 0x6e51d412, 0x6982c6cc, 0xa09f80f6, + 0x92e02d93, 0x047ae09c, 0xb7dd2d25, 0x37f351f9, 0x3503149f, + 0xc77850be, 0x69d49ce1, 0x12f0d2c8, 0x60242acb, 0x7bc28b9d, + 0xba188c56, 0x06bc0550, 0x8e406121, 0x8d7d4329, 0xb0d84b1f, + 0xd38951e0, 0xb4a67ae7, 0x8bc97607, 0xb527c57b, 0x5497aa72, + 0xbc93c5f3, 0x39bdd666, 0x5f1de8cc, 0xe9d447a3, 0x3087dc5c, + 0xa211abe5, 0x89b356b6 }, + { 0xdfdcc837, 0xed6db0af, 0xa871b7a9, 0x0fb80baa, 0x1c1d4b72, + 0x413abfc9, 0xadac9e5c, 0xf5b56bf7, 0x8b8657a3, 0x5664a2da, + 0x0e41d94e, 0x11b04f72, 0x37433658, 0x63e11d26, 0xf426daea, + 0xee628ece, 0xcb162dc2, 0x011619c9, 0x87648643, 0x9cf5817f, + 0x5584bc86, 0xe1bb9702, 0x00bf7928, 0x2cc27cef, 0xdc60eee5, + 0x4ef3a80e, 0x87adc2f9, 0x7e1202be, 0x8a0d4f52, 0x656f18e0, + 0x57c5d126, 0x39c4f10d }, + { 0xe88aecd3, 0xb3a9b68c, 0xa518aa9d, 0x555b0918, 0x4bd4ee54, + 0xedc1cdad, 0x02068d84, 0x79b68b67, 0x811ac72d, 0x7dac80d0, + 0xa81a0a78, 0x6d1e6d35, 0x3bd16283, 0xc841e9ea, 0x894c4444, + 0xa7bc1775, 0xf1aa1202, 0xf2b63725, 0xc7d4c556, 0xbec7767e, + 0xd46ff51b, 0x2817ebb3, 0x73f7e339, 0xfde5be8d, 0x5aed24c4, + 0x44c6c977, 0xb6e579cf, 0x0b9a1707, 0x9069fbcc, 0xcff16478, + 0x49152b00, 0x414b542d }, + { 0x606e173b, 0x33c31e58, 0x90e6713a, 0x5b7f4e1b, 0xdebb20af, + 0x425fb512, 0x05120e70, 0xc788c617, 0x9013e4ec, 0x3ef05602, + 0x81c6e6d7, 0x9f9d35ac, 0x9450690a, 0xe131e88f, 0x44af082e, + 0x708f9b32, 0x1ba2aea9, 0xb2e4d66c, 0x740db29c, 0xaf1f4a6e, + 0xd1843007, 0x74ab9248, 0xed556a6c, 0x13338ef8, 0x270d17a6, + 0xf48e623e, 0x9608f5bf, 0x3c7362fa, 0x444e8515, 0x43977874, + 0xe00b8b2a, 0x52678d6a }, + { 0xdf36aeb4, 0x5dff1c59, 0xa92bc0ab, 0x52d6653c, 0x927a5f81, + 0x0e03f496, 0x2dfd491f, 0x8509d414, 0xa571f89b, 0x258c2c52, + 0x93334485, 0x2bd61804, 0x3f7d9e09, 0x1a33e94f, 0x2c1bf906, + 0xfab418d3, 0x5aa5695c, 0xf39c490e, 0xf6d2d7ff, 0x0e41196e, + 0x0f7948a9, 0x3ecd4075, 0xd3053b4f, 0x4b58f9b2, 0x5d9974c9, + 0xb8ee842a, 0xbf22f682, 0x23a59c1d, 0xc8efcea6, 0x045ac614, + 0xc10ceedd, 0x7040ba5b }, + { 0x515a1a96, 0x2c364f81, 0x184327e0, 0x31a63503, 0x1ad93d4f, + 0x0a096650, 0x273b6173, 0x9d7694f1, 0xd2cda9d2, 0x8886d876, + 0x2814c177, 0x1e01a742, 0x8667696b, 0x3492276b, 0x5b25f006, + 0x2fd4f0c6, 0xfb294c4a, 0x6527349f, 0xde1d336f, 0xc1fe0d8a, + 0xe7e3860e, 0xaf9a23e8, 0xb774c31e, 0x97d2b721, 0x4365784a, + 0xfac3e582, 0x70f4eaa3, 0xff2dff4e, 0xfe873248, 0x3d281e1a, + 0x0bd1c9c1, 0x9043a6d6 }, + { 0x766c7937, 0x1511a0fe, 0xabbc3be3, 0x1b2ded5c, 0xe00888ac, + 0x2ac160cc, 0x616200f3, 0x928754bd, 0x34a2ea06, 0xb801c83d, + 0x9cbe106f, 0x8ad7a03a, 0xcedfcd94, 0x996b0822, 0xe4069880, + 0xc3c3463a, 0xf597f663, 0xfb12ea4d, 0x40c92af9, 0x2c8d3834, + 0x4e8da154, 0x79bc85c6, 0xdb4e801a, 0x95771fa2, 0x1e3579b2, + 0x7bd2c138, 0xffaad078, 0xe45c75df, 0xb73eac46, 0xb0760a3c, + 0x3a125f35, 0x26362b48 }, + { 0xeefc3e89, 0x25c68d28, 0x69e9ee71, 0x2d0ee877, 0xaf5e4b75, + 0x8b07bb86, 0xcb86b333, 0xdb709072, 0xff552bac, 0xfd3d20ea, + 0x4c0da1e9, 0xa5eeb2b1, 0x44f97145, 0x391f688a, 0x1e06d485, + 0x21fbd310, 0xbea9cd49, 0x45e4f2a5, 0xa7bf21da, 0x7b60d464, + 0x054d5471, 0x193f88c8, 0xbee0f2e9, 0x5ace53d1, 0xc1439273, + 0x92c26563, 0x96c6b5ee, 0x9c86e0b2, 0x09ff59ba, 0x452fe231, + 0x555c935e, 0x2e952b20 }, + { 0xd75f886e, 0x2a846bca, 0xd43dfc58, 0xe68a5dbe, 0x007b1b86, + 0x103e45b6, 0x355ff2b5, 0x580e2ec9, 0xa263ecc9, 0xbc702f26, + 0x181e5e33, 0x2835b386, 0x6c122076, 0x025113ec, 0x7fbd856d, + 0xa5c26e3a, 0x9d6ebcb1, 0x8ef83fb3, 0xa44d2fa8, 0x7aaa53f2, + 0x53b1fa97, 0x7c14ef33, 0x17559a30, 0xff604a11, 0xb09377e0, + 0x2bcd96b0, 0xdb2f0273, 0xa5c14896, 0xeb53ef06, 0x1c0a84c9, + 0x30378e4b, 0x1236d017 }, + { 0xc084373b, 0xd7481c8f, 0x646097ae, 0x29ae4768, 0x613bc34b, + 0x1300dfa0, 0x934bc2b0, 0x3712714c, 0x0e2be7e2, 0x86524629, + 0xed010800, 0x554fbb9f, 0x42314576, 0xf0ec0b38, 0x330a3282, + 0x65baf594, 0x706ef817, 0x3bdde1a8, 0xba7530e9, 0x7d2c727d, + 0x74cc95cb, 0xbb0c5d66, 0x2438906d, 0xb3fcd365, 0xd14658f3, + 0x19881941, 0x6c97f0e9, 0xe616f555, 0x4b9ec7ea, 0x353c2d85, + 0x620cb56e, 0x02a48014 }, + { 0x506ccd38, 0x11d6d23d, 0x9059baa6, 0x229a1c54, 0x69d011c5, + 0x717c9c27, 0xd828937d, 0xe87e1b46, 0x83835083, 0xf5d63bbb, + 0xaadac258, 0xf0a7b427, 0x9f154d1f, 0x99ab26bd, 0x8ec955fd, + 0xdec0ffbf, 0x49fcb880, 0xee957c67, 0x1e0114de, 0x32395dee, + 0x369f46c7, 0x192a64b7, 0x91eb2599, 0x43044660, 0xa2e8c3da, + 0xbe2da887, 0xc3556d18, 0xa44e2c25, 0xb55f75f3, 0x31390414, + 0x8f217fe0, 0x1d8bde6f }, + { 0xa2028924, 0x03cd39f8, 0xb06ecb9f, 0x6e54f19c, 0xd6f05846, + 0x862bbcb7, 0x5a060776, 0xdbe06716, 0xb10fec10, 0x9397c97a, + 0x6f1bb65c, 0xf4213826, 0xa672ba38, 0x414deccb, 0xf88b05e6, + 0x594d4d43, 0xac94d4d1, 0x7993f57a, 0xbfb17638, 0x74fc2a6a, + 0xb6fc655a, 0xd8196b5b, 0xee8d2139, 0xdc375c84, 0x360d3a26, + 0xb9b00a02, 0xdeb93b87, 0xb36ed35c, 0xcc83209e, 0xf565b28b, + 0xc61013c1, 0x349c6943 }, + { 0x4de6c88a, 0xd1b39444, 0x4700207e, 0xd5c2c471, 0x21c2b780, + 0xb6f458a2, 0x0850993e, 0x749f7564, 0xbaef0c18, 0x400ba579, + 0x737c70f0, 0x2d742938, 0x21467ebf, 0xc5a8e2ec, 0x5337f453, + 0x243a666e, 0xed0bd50a, 0xc991f1c7, 0xf4bd1f91, 0x3a7f3e90, + 0x5f0e129b, 0x96089e8a, 0x07389635, 0xd0d3a177, 0x27182ac9, + 0x9cf842d5, 0x0817c5c2, 0x21195299, 0x87255769, 0xa32f327e, + 0x89c2d8fa, 0x056587ab }, + { 0x1ce4733d, 0x008562ed, 0x98e51444, 0x5faff7cb, 0xa9ab46b9, + 0x5f03021f, 0xb61a8c13, 0x89494c5e, 0x36b35976, 0x57c95036, + 0x2ac2d2f6, 0x6be84c8f, 0x9bd2703e, 0x0e5b34d8, 0x7e872abb, + 0xc4ad918f, 0xc4052ee1, 0xc2a89e9f, 0x3190b51e, 0xc2caee3f, + 0x6fff254f, 0x58fd1437, 0x883e0972, 0x6f3c0d68, 0x0fb15438, + 0x63d0a0e9, 0xf6caae00, 0xc438764b, 0x3f1d0f6c, 0x815f1565, + 0xb86cdbde, 0x1b87f2ed }, + { 0x2b0b15b1, 0x35792bbb, 0xce6ba779, 0xa3e4b5a7, 0xdd8f3779, + 0xfbacffd9, 0xc298d1ef, 0x005450bd, 0xc47031c6, 0x0e3f5556, + 0x95d68066, 0x0770f07a, 0x2d1052c2, 0xce3e84e0, 0x7aa8cc54, + 0xb050791e, 0xba3223a3, 0x4d621e73, 0x39632990, 0x87b9b94d, + 0x7eb8056d, 0x8df9cb47, 0xedfca0cc, 0xe2430de8, 0x9712a0ca, + 0x374bf416, 0x88848a99, 0xbe3f3c77, 0xc4a3e59e, 0xb22b87b1, + 0x3e95bc23, 0x8e0227c4 }, + { 0x3210964d, 0x000e22a8, 0xff056eeb, 0xdccd5df5, 0xdaf1ead7, + 0x02173a1f, 0x67cdcae3, 0xd02833e0, 0x8bdcc90c, 0x1cc574cb, + 0x3224b4f5, 0x86eca714, 0xbb3f8298, 0xd00e603a, 0x0c1a8deb, + 0xb98ece1b, 0x378c261d, 0x228a46e4, 0xa6165e5d, 0xc6f9dd0d, + 0x4b7ef0e2, 0xb3ae3899, 0xbda9f306, 0x3a3c16b3, 0x38a084db, + 0x5e9a26d3, 0x5394e950, 0x528e5993, 0x4ea206bc, 0x848ecb11, + 0x40545d6e, 0x14b15ab5 }, + { 0x664c59a2, 0x0f6d86c9, 0x60fd7aa5, 0x3dfe2be1, 0x9072cb8e, + 0x33f9b569, 0x8176a7e0, 0x5f2325d9, 0x4587080b, 0x79a0d4e7, + 0x0d5d4e05, 0xa4ee0def, 0xc87b28e1, 0xc0ad9ffa, 0x3f09b4ee, + 0xd6f18d2f, 0x292e9d87, 0xcc896ae7, 0x6094763c, 0xca88953d, + 0x18fbf9fa, 0xdbee97a8, 0x4b63d701, 0xdf20e0e9, 0x47ea722f, + 0xcbba6e30, 0x612b571f, 0xce57e1ca, 0x009a55f5, 0x1e16ac76, + 0xc4389e2e, 0x742bbed8 }, + { 0xc1dc2c73, 0x23ea86dc, 0xc1643abf, 0x4bbbfd5b, 0x24d8ca1f, + 0x07f8fa1f, 0x8cb5cac7, 0xde68a6e0, 0x54e66a7d, 0x7d54c64b, + 0xa9b7ad78, 0x789dba22, 0xe364ab94, 0x4d88d540, 0x1f72e011, + 0xc8c2e02d, 0x46e2a278, 0x4c826057, 0x4b187c7d, 0xe6c35bb3, + 0xeb8fe0c9, 0xed8b3dfe, 0x7d11e415, 0xb6bc34e8, 0xb865c7f9, + 0xb3908bbf, 0xe1ecc17c, 0x717d1ce6, 0xf7cdd69b, 0x151e3308, + 0xb5c94124, 0x97bd5a14 }, + { 0x81e82861, 0xe01c62fe, 0xdd42c40e, 0x703d4b6d, 0xe65e91e5, + 0x7e52e55b, 0x5abbbfdd, 0xb8b49374, 0xc72a45f4, 0xb4f15f52, + 0x550f29d8, 0xce8435a8, 0x582de75f, 0x9df76b9b, 0xa20c8b96, + 0x52e84c5f, 0x0a8a0af4, 0xaf77d2d1, 0xca6013c3, 0x0389bbd8, + 0x26f8305f, 0xb0d9b9ba, 0x0cec8b9a, 0xf053e848, 0xffabda18, + 0x4d63367a, 0xa6424c2a, 0x50f53be4, 0x864fba2e, 0xf892c58c, + 0x48cc5469, 0x317c6d31 }, + { 0x2cb7d42b, 0x0c3525b0, 0x310facae, 0x55240bc9, 0xff20408f, + 0x8d5d2022, 0xe0c10ea0, 0x6b01402f, 0x718eb23d, 0x7fbef68a, + 0x41252a19, 0xa0146b5a, 0x110e0d6e, 0x59afce48, 0x022de181, + 0xe9a1d27f, 0xdc3f49da, 0x6db96d16, 0xefbe4008, 0xfc1ae3f5, + 0xeccbc11c, 0xf9d70641, 0x525f8636, 0x49022279, 0xc2763c30, + 0x3769796a, 0x1d90630b, 0x9cc3483c, 0xee3d3f17, 0x451651f0, + 0x9da0b8fd, 0x6ae59739 }, + { 0xbff4d2ee, 0x57b13bc7, 0x30b173d8, 0x20754229, 0x0794936c, + 0xb6254bd5, 0x5efd55be, 0x1d5f232a, 0x4e0c3389, 0xc06f4a85, + 0x8e61f944, 0xcf2c5b59, 0xfd5f87b7, 0xc564861f, 0x5a2afa4c, + 0xee261fb1, 0x2d97a774, 0xb0ff7226, 0xd6cf007a, 0x1a89ae22, + 0xd346f214, 0x28880534, 0x97b6497e, 0x8fe73bff, 0xfa2afffc, + 0x8a8595b2, 0xf151a726, 0x9ef9cf3e, 0xe744b82b, 0xa84ee5f1, + 0xbc63fe72, 0x6649048d }, + { 0x1e8b760d, 0x91b7bb78, 0x25aadaa0, 0xd47b0bd8, 0xfab5226f, + 0x81493d9f, 0xbffc148e, 0x4a6dd226, 0xa29be3db, 0x5a032f8a, + 0x34b0ab0b, 0x318dbc70, 0x7d654868, 0xdcccbfb5, 0x9c581e46, + 0x8506ab37, 0x2830ece2, 0x09136a6e, 0xcf6c80c7, 0x48b79356, + 0xef6b1e86, 0xfa176377, 0x83f0f1c9, 0x2c9c1cc1, 0x16abeddd, + 0x96f0526d, 0xa93b0de4, 0x3e0e98e2, 0x0f13873a, 0x6f2d7ada, + 0xf3fa49ec, 0x4eb93b5c }, + { 0xe11fae32, 0xbd89f7e5, 0xc4023f51, 0xd13d74f5, 0x491c3f6f, + 0x1b0014df, 0x555279b7, 0x1d849a57, 0x05ba0068, 0xbb9e8897, + 0xc13ca2ca, 0x82222419, 0xfd33676f, 0xafbbb685, 0x75878a2a, + 0x931c3f52, 0xef3d5173, 0x12aeefef, 0xbd8a6878, 0x189a5cc8, + 0xd99f0c16, 0x82cffdb3, 0xa19d48b6, 0xbf565406, 0xe9c6c4e0, + 0x5605e223, 0x86804172, 0x53e781de, 0xc7001cc8, 0xcdf5c90b, + 0x7c043f68, 0x2b582d93 }, + { 0x81abc2ae, 0xa1165c82, 0xe2b69eca, 0xa73380f5, 0x07fff66f, + 0xc097b3d2, 0x54776506, 0x5d603826, 0xb57fa21c, 0xdcbac9f3, + 0xc98dbdd5, 0x78750db4, 0xd9eff32a, 0x85e21103, 0x2f11c41c, + 0xceed172c, 0x9e348c09, 0xa8e39264, 0x831eddfb, 0x71cb936b, + 0xf50864a3, 0x915c3d06, 0xe93acfcd, 0xfe8e33cd, 0xb3f2f7aa, + 0x4bee10d7, 0xeb7cee9a, 0xc1d8eb48, 0xfa574afd, 0x4fa49ce3, + 0x862db4c0, 0x78615109 }, + { 0x7ae72c21, 0x3fe3f480, 0xfd0f0da5, 0x631aa144, 0xf8c3a454, + 0xc76ee1e8, 0x51b4f1ab, 0x379ae094, 0xd7cdbb24, 0x2a3a4397, + 0x82bd5fcd, 0x7a14cffe, 0xf427ef5a, 0xbbe4ed12, 0x284d3ccf, + 0x9b0a43ee, 0x8eec6e1e, 0x57b78b93, 0x67b8e87b, 0x18d404e4, + 0x34374c20, 0x0c8adc05, 0x5428deb5, 0x64373605, 0xc3afa2cf, + 0xb4d80ec0, 0x3aa956f9, 0x6d51f93c, 0x84161c68, 0x9f9a28ab, + 0x6bc9c025, 0x540b6bb7 }, + { 0x321d315d, 0x04e1734c, 0xd86e05d0, 0x4ef56612, 0xbba8cd81, + 0xeafae145, 0xacdc789a, 0x1fb07a49, 0x5877570f, 0x6a21e9ad, + 0xb9bc53de, 0x2e4a837e, 0x1d6298eb, 0x436db293, 0xea362f45, + 0x43afbc78, 0xaabf6585, 0x2a973d97, 0x0c924d60, 0xdce7dabe, + 0x7cadf0e9, 0xf69d98f0, 0x75020538, 0xe0b505a1, 0x4461cd29, + 0x3db7d1a3, 0x5e20e818, 0xe1c28776, 0x52dd50f6, 0x2ca25867, + 0x92e0388c, 0x897cab14 }, + { 0x0d8bab8a, 0x59ed3813, 0xa438200a, 0xc11d364c, 0x40581415, + 0x0687bf2c, 0x7ac89674, 0x86ad0d3a, 0xb97411a0, 0x44928105, + 0xf383371c, 0x74984b11, 0x0d1a831e, 0x70d2ed84, 0x6c912fe0, + 0xd883628b, 0x14fa88d2, 0x44f8f7fb, 0xcf0ac93e, 0x564f2a4d, + 0xa6c24fa6, 0x82f629aa, 0xbf6cd949, 0xab906ba3, 0x20a5182d, + 0x2c822e67, 0x30eb93a5, 0x2ff47dac, 0xfff673aa, 0xdc62c4a4, + 0x476b0ec5, 0x64b00763 }, + { 0xb3c9a404, 0x1e3f533e, 0xb7ef9952, 0xb1db7f73, 0x6c253693, + 0xc7f13e29, 0x0738eed4, 0x7ce7f4c4, 0xce26cad0, 0xccfd3b33, + 0x01ec5cf1, 0xd8784935, 0xdc084e01, 0x3f8fc09d, 0xc39b5acf, + 0x217cab32, 0x9ef5551c, 0x42daf0bb, 0xe1217a95, 0xfbc76f56, + 0xc237002a, 0x80178b12, 0xb070a293, 0x0b52c39f, 0x576ca964, + 0xe3925153, 0x19d68e36, 0x25559424, 0x09e50e84, 0x291fb82c, + 0x6618ed8c, 0x7dd22ea6 }, + { 0x49cbb3bf, 0x7ffe844b, 0x5562fb25, 0xde0cc704, 0x9f5a845a, + 0x1e6ee537, 0xe51277fc, 0x956d7f26, 0x30635718, 0x2c75d4b9, + 0x96957f34, 0x39a14892, 0x82e5742b, 0x8cf4eb32, 0x83247b72, + 0x6b0d3ddd, 0x201a4237, 0x67a9f633, 0x1414a485, 0x416403c1, + 0xb6f6a916, 0x60afd447, 0xdac6f790, 0x95f94930, 0xbd3b9d82, + 0x685ff94b, 0x51cadf0f, 0x5c8f98fc, 0xb13b7489, 0x9559c88a, + 0x5f18fcc8, 0x31377c66 }, + { 0x7dcfb35f, 0x35c5de09, 0x01cc36f8, 0x2dccca9f, 0x7576cb63, + 0x7e93e85d, 0xf7b4b375, 0x0c2dd48a, 0xb09a19b5, 0x9d95cd4f, + 0x71bfe607, 0x752ed159, 0x2596dad2, 0x439880cf, 0x69e90a6f, + 0xe52efb53, 0x03d3e60a, 0x44097663, 0xa95070e0, 0xfcf364fa, + 0x05624dd2, 0xd8f993b6, 0x00d5e467, 0xb35a9824, 0x0c8f4524, + 0xe289d024, 0x648a0179, 0xef45423c, 0x587edabd, 0x3a5fd695, + 0xa11e5271, 0x3dacc50c }, + { 0x6499ae4c, 0xcb3e4f94, 0x7053c527, 0xa46dcbe1, 0xbe782e8a, + 0x807f5ce9, 0xd8481e45, 0xb6c64d28, 0xaa286fd0, 0xf35e4518, + 0xdf1cdb49, 0xf7b7b9ba, 0xaec23eaf, 0xf3fb6210, 0xb9bfd2fb, + 0x0a9ba385, 0x8807f3a0, 0xe51a0d53, 0xb17b2842, 0x7ab24404, + 0xf9dd9f0a, 0x6fd57687, 0xf3e9df64, 0xcd1efdb4, 0x60df194d, + 0x5dd2df7a, 0xe069df05, 0xbed3f2c3, 0x23248a31, 0x469b7561, + 0x694744f7, 0x866949e1 }, + { 0x3f4ab07a, 0x3a9a0da5, 0xf54a6fbf, 0x2cd6f333, 0xb23cf290, + 0x0c92e921, 0x848e3d58, 0xc9581c3e, 0xd3b218ab, 0x93af1fbd, + 0x066cb4d7, 0x38598ea1, 0x990c03a0, 0x5001394e, 0x7d0877b5, + 0x3b664b1e, 0xd74c7091, 0xd79db1bb, 0x4e2d5dd0, 0x852d4435, + 0x3329db82, 0x0d2b841b, 0x7b96d480, 0xfa844eb0, 0xc295dc46, + 0x37a50569, 0x94f7ec4e, 0xc2d38373, 0x5b083177, 0xdc3884ff, + 0x8b1fa598, 0x574352b8 }, + { 0x0d5d7ce9, 0xed2193f7, 0x0b487eaf, 0x3c19fd26, 0x7be65fd0, + 0x7c44ab59, 0x78270d56, 0xdd9da860, 0xbaa70198, 0x8a84ec00, + 0x285985df, 0x2ec27e49, 0xde2028d8, 0x996ccaf0, 0x61c2201d, + 0x4e7648c7, 0x091c19eb, 0xa96335bc, 0xf0d6782b, 0x253a3a69, + 0xd2946493, 0x3f204340, 0x099f6873, 0x444521a1, 0x6996011a, + 0x5fcbcc09, 0xf853a94e, 0x3884d5d8, 0xd3b6a3a1, 0x2418c624, + 0x06ae3c4f, 0x3e431af2 }, + { 0x83d381f1, 0xf967d939, 0xd0c033c3, 0x36501aae, 0x54410768, + 0xbf3af4d0, 0x5093a6d3, 0xa86d1598, 0xd92f2900, 0x43ae0741, + 0x36f0b755, 0xfeb2afa6, 0xaa456d6f, 0xd090a6a3, 0xaefdb646, + 0x336a4fda, 0x1a942f7d, 0xfd1bfe44, 0x851ee41e, 0x7fc2a3ed, + 0x11e935c5, 0x4f1c9686, 0x53bbb343, 0xcd577666, 0xad896c2a, + 0xf26931ba, 0x86bbfa41, 0x8a0fbbd1, 0xa203cef1, 0x1c3d7d82, + 0xe2664d35, 0x6dad3f15 }, + { 0x12ec35a1, 0xd1940b7d, 0xe7dfb128, 0x6219c5b6, 0xf13321d5, + 0x2cc278c6, 0x33c58eb6, 0x5e76904a, 0xd9903c43, 0x15090f55, + 0xc3d96a19, 0x061bc926, 0x8c0acba7, 0x974a9f03, 0x7198b21b, + 0x7a414021, 0xf8958c6f, 0xb069599d, 0xbebd0129, 0x517f2f1d, + 0xdf3a8dc3, 0x1109a613, 0x672375c5, 0x08e58448, 0x9383d2d3, + 0x56590ba4, 0x0bff837c, 0xfc3ee7c6, 0x27d2d55f, 0xc87a5390, + 0x5f517a3f, 0x2438e9d4 }, + { 0x8815af3c, 0xc4a45308, 0xf3c9bed5, 0xe55f1a32, 0x97b65ddf, + 0xaef1cdc9, 0x12e51eb5, 0x61c61d94, 0xe63f2490, 0xbd0dac54, + 0xd0b3e231, 0x6f14429c, 0xf1da6010, 0xf737c3c2, 0x6bbc4fb1, + 0x7150e04b, 0x1be281cb, 0x205b4c89, 0xd7701f5b, 0xf1b4633c, + 0x2a513490, 0x8b33ef46, 0x68f1f7f2, 0xddb47c73, 0xbd416b67, + 0xf4ada511, 0xff795bb3, 0x9d2a97cd, 0x96200e67, 0x00a8b7b2, + 0xafe30e01, 0x13f39011 }, + { 0x7bd0c827, 0x3dd296ef, 0x4a29ff46, 0x506110f3, 0x1c9a515a, + 0xf8793068, 0x268bca77, 0xde8d8045, 0x998045df, 0xcbb83024, + 0x68c0e584, 0x3f90d710, 0x263b6062, 0x2a838ca8, 0x535c5d0b, + 0x293bb5e7, 0x56415110, 0xceea99d5, 0x1bbda005, 0xfe311ad0, + 0xa4d8d018, 0x2497e0bf, 0x1cf2b866, 0x33dd77a0, 0xd8c4ba8b, + 0xbc075b73, 0x722b7bc9, 0x298466d4, 0xcbda1b0b, 0x17a7ce24, + 0x680703b6, 0x458d4b6b }, + { 0x4d54d8b2, 0x8a26a20e, 0x4d320a0d, 0x05a5696e, 0xf994f700, + 0x698b5858, 0x2f6549a8, 0x7a4adc3c, 0x3694d00d, 0x1812e819, + 0x730402bd, 0x46b9b000, 0xa1b36410, 0xe10a1449, 0x99230220, + 0xeae95ea5, 0x1b4820c3, 0x3efc2e9b, 0x85c9eb8a, 0xfe5b5cb5, + 0x97847064, 0x21ae0319, 0x8f27d49f, 0x68ef0b70, 0x2f72556b, + 0x3259ef18, 0x624db01a, 0x00ae0457, 0x5668f95c, 0x628e3b06, + 0xb6fbbf91, 0x5f13f5fa }, + { 0x3a9b0dc6, 0x7c6ed9ae, 0x6f883ec8, 0xaea1bde9, 0xea8b3677, + 0xea66bf88, 0x9a66e3ab, 0xdefa6abc, 0x68217ffd, 0xc4d3317b, + 0x290df05c, 0xf741c8f2, 0x7d11674e, 0x1f0fdf17, 0xc35989ca, + 0xfdf0ece7, 0x6b9c482d, 0x0eed92df, 0x55bf1ca7, 0x73713e66, + 0x25cec99c, 0x90acb290, 0xe803e69c, 0x37c9e3a2, 0x17713a1a, + 0x7c0a3c53, 0x6f5a174d, 0x350dc565, 0x05f802f6, 0x11625a44, + 0xa37ba4a2, 0x2196495d }, + { 0x13142680, 0x00cb2fd3, 0x65d14cf4, 0xab9e91d7, 0xdfe2669e, + 0xc6a0ceab, 0x0ae22bc5, 0xbeefce58, 0xcb6ec250, 0x3c2b7986, + 0xd738f1ff, 0x84adb1a2, 0x516ec8ec, 0x9709bc28, 0x8e8f7db5, + 0xf3693129, 0x95b197f9, 0xc48efc6b, 0x9aaaa404, 0x9ff10952, + 0x144154b0, 0x2c3c8cbd, 0x427f3435, 0x33ef7bc3, 0xd21897c1, + 0x04a17940, 0x6ce548a0, 0x5aa0c47d, 0x3d56fa62, 0x2971cea7, + 0x04475f08, 0x93ad0eb0 }, + { 0x988a9963, 0x7a0b6967, 0x6515e8dd, 0x61e477f7, 0x3b6b50f2, + 0x6274e386, 0xd33922de, 0x63a9b8d5, 0x687a5b3d, 0x3c38d3fb, + 0x1302e323, 0x18f6f09c, 0xe02fcccf, 0x254c05c3, 0x26e662f7, + 0xc04ed0b7, 0x143fe079, 0x1d5646b8, 0xc9016c8c, 0xef8a9448, + 0xf823d797, 0xe5674c4b, 0xbccde451, 0x0586f72f, 0x4417eade, + 0xc5fc88d5, 0x576e588d, 0x2b952209, 0x5844d1f9, 0x4408dd42, + 0xea41c034, 0x73f8c3f0 }, + { 0x5df763dd, 0x89534fc8, 0x3ac71836, 0x3b1427f3, 0x6e8f15a0, + 0x0db5be17, 0xcb20888e, 0x1d390944, 0x857caea6, 0x7804c9ad, + 0x519f7bf3, 0xaa584428, 0x293aa8cf, 0x626eecf1, 0xea36a015, + 0x749e0d98, 0x3321edcd, 0xefff6dae, 0x28b791cc, 0x963deea6, + 0x2d16e361, 0xa14e0552, 0xb15ae206, 0xa2e058fc, 0xfca325e4, + 0x0f268745, 0x21341a8a, 0x7cf9d407, 0x7caa51b8, 0xdfed25d9, + 0xadbedd75, 0x0108ae39 }, + { 0xa9e88f63, 0x54d178f3, 0xab0c7325, 0xaa05b11e, 0xe261d8a6, + 0x773a53e6, 0x8d0b91c8, 0x24db7dae, 0xe9bb004d, 0xde10b073, + 0x54e3090b, 0xfc8befe7, 0x0cc69c89, 0x16af0599, 0x9d59511a, + 0xddc83803, 0x46c5dafc, 0xc3f65b99, 0x1ee0a599, 0xfbbe4be8, + 0xfb3a9b17, 0x88891e36, 0x445dad00, 0x0c9aad75, 0xd5097e1f, + 0xdffc46ab, 0xac85a4e1, 0x8848089b, 0xa0c45233, 0x348bb42f, + 0xeb13c1df, 0x807c06d8 }, + { 0x98ee0ef6, 0x00a969ec, 0x8bb7b7af, 0xba9d5483, 0xa02f8fdb, + 0x24484c92, 0x8b70557c, 0x7bdb201a, 0x60ad1af2, 0xe59343e4, + 0x998c95fb, 0x53a9a942, 0xda861d3b, 0x974db3de, 0xed399c0e, + 0xce1525c9, 0xf72109bd, 0x89b56881, 0x998211a4, 0x08ff7d15, + 0xef0f275a, 0x5df76b3a, 0xfa2f358b, 0x93f180f7, 0xc39b0634, + 0xaac4ffcf, 0x17583b53, 0x2692c626, 0xb55399fc, 0xb2fdfa36, + 0x99607a61, 0x16424c6c }, + { 0xdd2744a9, 0x5dd65c55, 0xfe3af418, 0x2544c1c2, 0xefe8b089, + 0x32c82e99, 0xa9df691a, 0x30b7ab25, 0x9be99674, 0x98384550, + 0xcaf2d122, 0xbcecd258, 0xbcc77272, 0x88ae4098, 0x4b8efa0c, + 0xd4396141, 0xed64d12c, 0x44ff67b9, 0x2e7f3404, 0xa9e655e4, + 0x45b0e9eb, 0x3d16fc45, 0xf03ded28, 0x474a3e14, 0xacccb85c, + 0xa3c9adff, 0x7253a51b, 0x3dfe6bc1, 0xfb5831b1, 0xdddaf4b9, + 0xa4f4478a, 0x5544e602 }, + { 0xbaa80b4f, 0x897c5313, 0x63bdc8ef, 0x0122716f, 0x7b42c5a8, + 0xae2742db, 0x0883308c, 0xe9d9e1e9, 0x2d341ab1, 0x352c8c3f, + 0xed945870, 0x163d0500, 0xc290d9d8, 0x8349dd73, 0x1f6c7d29, + 0x2053c5e0, 0xcb42033c, 0x83107446, 0x09d09af1, 0x76c88bd2, + 0xb2794681, 0xd0f70e6e, 0x19b1b540, 0x720b59de, 0x22994b43, + 0x80b7ecdc, 0x2dec53cf, 0xc1a4cdce, 0x1ed60f42, 0xdd7d3edd, + 0xe241d261, 0x5735995c }, + { 0xa0237056, 0xdc4ba3fb, 0x33ab3388, 0x6856c164, 0x271ec612, + 0xc01eebbd, 0xe3031bec, 0xabdeb033, 0x6118a1f5, 0x4eee4419, + 0x5b600f33, 0xec497421, 0x08868773, 0x1b7185cf, 0x7c1b7dfd, + 0x7b0c46cd, 0x4a4c5e89, 0xd143b2da, 0xbb1ff94d, 0xdb9a5984, + 0xc9cf3465, 0xac3904e4, 0xeace64c9, 0xf8729bc0, 0x768ad99a, + 0x5cc22821, 0x8a9540c2, 0xbbd3b081, 0x049a6917, 0xe468ed5f, + 0x3ec45ef0, 0x885486df }, + { 0x4bdff464, 0x6a942c93, 0x25a7b451, 0x3db2719f, 0x325be324, + 0xccb0070b, 0x19fe3339, 0x2055a31b, 0x241ee8ff, 0xaca69ae8, + 0x55ef8def, 0x7607dd08, 0x1a1b73c6, 0x9e24960f, 0x71d36810, + 0xbcb0e8a2, 0x6885e6b9, 0x29e11aa2, 0x185eae19, 0x98b5d0ab, + 0x0f81f91c, 0x1a0b96e4, 0x994fc503, 0x4d0e8bcf, 0xf119d6e0, + 0x33d81697, 0xaaa4ce0c, 0x29083287, 0xc91ff9d7, 0xc5dd4d3e, + 0xd4ab962d, 0x31cecfe8 }, + { 0xfc8b21e8, 0x437bfd9a, 0xb19436df, 0xe5dd32b3, 0x921c36a0, + 0xfe5902d4, 0xa3d0fa90, 0x8e9de84d, 0x5bb523bd, 0x9663e6ad, + 0xaecd6975, 0x9800a23f, 0xb4fbb59c, 0x1009c0d9, 0xc9d20ff1, + 0x839aa7bd, 0xecd6fa3d, 0xf502f66d, 0xc5516ca9, 0x480ed4fb, + 0x6c742ac4, 0x65ffa5f6, 0xff3252f8, 0x2b7c7945, 0x75d9cb3d, + 0x72fefc05, 0xd6d6f1d2, 0x11b0863b, 0x9a6a4ec3, 0x5d8f3cf0, + 0xda2547b3, 0x6961b46a }, + { 0xcb35e2ac, 0xd07b587e, 0x57af14d9, 0x1ed5546b, 0xdb28a04c, + 0xeca17a5b, 0x709d54f0, 0xa1f91d44, 0x9c6f400e, 0xa6e719fd, + 0xfb8ce190, 0x4e4b88ed, 0x246e3fd2, 0xf9781edd, 0xb655af5d, + 0xd67120e6, 0x93413ca7, 0xda782d1d, 0x9707fa21, 0x697e20a2, + 0x54e84123, 0x1eb51f32, 0x36051f9f, 0x2e254d9e, 0x73ce5be9, + 0xddaec42b, 0xcd3f794f, 0x89a9a32e, 0x0781aad9, 0x1964e22f, + 0x53755212, 0x6a63a90c }, + { 0x3d7acbbb, 0x76554e00, 0xb74f6108, 0x2c01668a, 0x388c519b, + 0xe4a29672, 0x3eb94d4f, 0x01667714, 0x0cd6d2f6, 0x086a3cdf, + 0x7b370f7f, 0xf8658021, 0x5a4d3e7c, 0x658880c1, 0x5ba3f4a1, + 0xd6ed5816, 0x5ca471dd, 0xabcc7813, 0xe844a576, 0x809bf074, + 0x6ea502ea, 0xa53a81b3, 0x0e021ed3, 0xc20b9307, 0x8617f165, + 0x8c27f892, 0x8235cd0b, 0xa5476446, 0x82552961, 0xffc89ffd, + 0xd151d90e, 0x51ed4a22 }, + { 0x449701b4, 0x37d6963a, 0xbb27caf2, 0xea8d91a3, 0xb572965f, + 0x3ef9be15, 0xdb50bf7d, 0x75a7a055, 0xce643b9b, 0xfd67480e, + 0x6ceb5d5e, 0xf2a60d2d, 0x5ed7c897, 0x68fc320c, 0x28ce685f, + 0x41c53cf6, 0x7106615e, 0x0e29711f, 0x23500ecc, 0x7a872138, + 0x6c29fe48, 0xaf0a9260, 0xe1ef9712, 0x93df3f2a, 0xd2d169bf, + 0x0d5f6fb1, 0x74a9793c, 0xeb7afe26, 0xe9f49256, 0x4173d94a, + 0x2b8b5ce5, 0x2d6951bc }, + { 0x904e222e, 0xdd007d9f, 0x86f4e109, 0x333f248f, 0x8f429eee, + 0xd4994e8b, 0xcfc77518, 0x29573415, 0x0b0f42f1, 0x6e7fea3a, + 0xc2743519, 0xc795cb7d, 0x711e71a0, 0x820a8f66, 0x2b874f55, + 0x83d95d9c, 0xe70e1627, 0xd4b64d78, 0x8b92a742, 0x924353f5, + 0x447b5e6d, 0x322048b1, 0xbcf931a0, 0x0bad730c, 0xa7af2268, + 0x75c4d089, 0xb83b93f9, 0x464904c1, 0x165b3aee, 0xa24eba02, + 0xe08cc5f0, 0x65c48e78 }, + { 0xde222c22, 0x1a1c73ce, 0xfcea23b4, 0x5683d8cd, 0xb2143b06, + 0x0301cb14, 0x59fcec77, 0x284adf8f, 0x31204cef, 0xfb1c581c, + 0x94735107, 0xf54d3eee, 0x4d3188c0, 0xdbf67f0b, 0x10f18d12, + 0x76a3f2d1, 0x07d3e013, 0x3809fa28, 0x25e7ece0, 0xf06f0a46, + 0xb2895d2e, 0xd82867ed, 0x08b0553a, 0xe106f489, 0xef245445, + 0xe2280fa6, 0xa8d9a3cb, 0x402d5785, 0xd438ba2d, 0xf63dd9ff, + 0x7a6b226f, 0x36b5cd2c }, + { 0x545679a7, 0x87ff4e20, 0x4520c750, 0x64d80b41, 0x9b459cd8, + 0x90a357fa, 0xc85af1a3, 0xa19eaf39, 0x8d935a5e, 0x0d475d79, + 0x781a678a, 0x74501983, 0x0cc2e810, 0x74839779, 0x2f412244, + 0xc6a21d11, 0x36a51a37, 0x8d0e85f9, 0xeaa74df8, 0xff50151e, + 0x93cf99c4, 0x14e182a7, 0x376a9ab6, 0x45593df1, 0x522389ff, + 0x18f73caf, 0xf7445e8a, 0xd27cc960, 0x39a51dc8, 0x0692f4c5, + 0xdb39bfd8, 0x08d7c144 }, + { 0x3ecca773, 0x809c0d96, 0xd48c2156, 0x87ea9192, 0xdb6bd641, + 0xf0eccd74, 0x2a678cdf, 0x77312374, 0xd1587b7e, 0x7a966d8b, + 0x6130a4c6, 0xf3c1a101, 0x5fce17bd, 0x7cc6e838, 0xa8de7aa4, + 0x95e95bb8, 0x898308e3, 0x3fe1e8b5, 0xe347694a, 0x0197243e, + 0xbb0cd2bf, 0xf3fe9c42, 0x0f9b2b49, 0xb5905264, 0xc7367d1f, + 0x4c385e8b, 0xb5ee147b, 0x1d3050ae, 0x04004ad9, 0x8e2c3879, + 0xbab70202, 0x5f2aa8ee }, + { 0x1266524b, 0xe208d464, 0xd0a19f66, 0xb7bf3880, 0xda106ebf, + 0xa5aa685e, 0xe642dd46, 0x0a69e8d3, 0xc682e4d6, 0xef349c61, + 0x0fcb534c, 0x26f6ee3b, 0x05eb67b8, 0x7daba127, 0x18be05f6, + 0x2babb27e, 0x8e2d85d1, 0x959afcba, 0xe2d9d386, 0xedcf2d1a, + 0x1ea6f06e, 0x59dc52e6, 0x866e5ae8, 0xc28278b4, 0x02bcd3c7, + 0xd9ff0340, 0x784be82f, 0xe884ac76, 0x83c9f224, 0xa3164980, + 0xb46ff949, 0x62501a98 }, + { 0xad264086, 0x563f7d9a, 0xa5e0e4bd, 0xca6a33db, 0x8c8d3d67, + 0xe8253002, 0x46e64b19, 0xa288dac8, 0x20aa4536, 0xfa3c9197, + 0xed553eac, 0x8130c9b0, 0x2ea8abd3, 0x622806e0, 0xceccfe77, + 0x52fbf54d, 0x4f0d1b70, 0xbd9a8e31, 0xd59b1741, 0x519d2133, + 0x9a6fea8a, 0xfd74101c, 0xb5c4eb10, 0xd1acf7a0, 0x91f9da5e, + 0x78499b73, 0xc0dea586, 0xabaa4c49, 0xa1f3531a, 0xcc9c5f73, + 0xfd3fc665, 0x497b15fe }, + { 0xf45568e9, 0x8a56cbaa, 0xc7192a6f, 0xf491a0fe, 0x9ab2539a, + 0xdbb03dd3, 0x4ac37da9, 0xc86522f8, 0x02a0f5b4, 0x8c8cdba2, + 0xa29c539f, 0x8109fc75, 0xca90f02e, 0x9cd06d31, 0x3e216dbf, + 0x8f31f044, 0xba3ebd91, 0x99aa68ac, 0x42c007f4, 0x2a80d0d2, + 0x86a9b7ce, 0xdd8dffbf, 0xd6308edc, 0x405d3e84, 0x068012ca, + 0xdafa33fe, 0xedea1071, 0xc2eebd13, 0x2ff637e6, 0xb7ae7e5c, + 0x9e514cb7, 0x18d46a6c }, + { 0xa78b7802, 0x868cbb22, 0x497cbaf4, 0x0745ddb2, 0x42ae8add, + 0xc4eb2f3e, 0xb4ceb4e4, 0xac0abcda, 0xa325fd40, 0x2e0d8325, + 0x13ac7345, 0x6cfe0571, 0xb14171b9, 0x7407a788, 0x6da7a52b, + 0x70eb0603, 0xd85176ac, 0xab0b36f9, 0x7c2954f3, 0x14109d29, + 0xdcd705ad, 0x370de9c8, 0x7bb5e751, 0x3f0db5cd, 0xa06e708c, + 0x45f93d41, 0x7e93050d, 0x10d54f8a, 0x5a38fef9, 0x69e6f8e4, + 0xd3f62e40, 0x55044601 }, + { 0x06cb9cc9, 0xd1c5c910, 0x41d00014, 0x542074d7, 0x11236fb8, + 0x7cd8663e, 0x29ad5f82, 0x39721ffe, 0x2951fc83, 0x1d21fbfa, + 0x400d144f, 0x1cde06e7, 0x91792e6b, 0x9042596b, 0x29ad5166, + 0x3365c8e5, 0x9aeefe98, 0xe2220e85, 0x70c2aee3, 0xbcb53189, + 0x9ff100bc, 0x477ca3db, 0xf532973f, 0x27074176, 0x9a2bd01b, + 0xa12118ac, 0x3dd79f93, 0xf3425209, 0xc6f5d7db, 0x563a8ff7, + 0xd7b0ec4f, 0x0da313fc }, + { 0x15aa2557, 0x37125a8c, 0x00893e9c, 0xca21d70c, 0x67b8a823, + 0x48713994, 0x7cb0042a, 0x0d3e9a74, 0xc9e2ce18, 0x2d2bf4ff, + 0x049aeac2, 0xd5531a0d, 0xf03d0660, 0x4d29a616, 0x1f1b7f00, + 0x473d50d6, 0xca3de50c, 0x3af0ecbb, 0x09c28f27, 0xe2959bea, + 0xf8704664, 0x6d7c2ea0, 0x731083ef, 0xadfae4e1, 0x941c2554, + 0x50940c26, 0xa1162d03, 0x44167410, 0x1e82290e, 0x620230d8, + 0xdb414acc, 0x63630be8 }, + { 0x8a7d2e41, 0xbf8d5222, 0xeb62f879, 0x49e75823, 0x6c402d89, + 0x1b4d33dd, 0xde2c59ad, 0x883e04d6, 0x49b9dc38, 0xbf3f38f4, + 0xb4b70c4c, 0x9d997d18, 0x13cea045, 0x1f69b20c, 0x58e2606d, + 0xca3d7025, 0x261d1b79, 0x3d4fd977, 0x5a1436fa, 0x56aeafa8, + 0xbb443c07, 0x369b3e98, 0xe558f6be, 0xfce5186c, 0xf8ac8f89, + 0xeb0cd478, 0xd5e5aa72, 0x68074f37, 0x68544eb0, 0x295845c0, + 0xf16688ed, 0x306a9871 }, + { 0x634ec136, 0xbc451e9d, 0x0e6f658f, 0x1edf27ca, 0xc0db4120, + 0xa9be0152, 0xc5bfee67, 0x87b6ef20, 0x9a2d6023, 0x35283238, + 0xc7afb899, 0x60e564d8, 0x0ac9c2de, 0x4af22bc0, 0x82a9d22b, + 0x28e6f631, 0xf532701b, 0xc075c701, 0x82075f91, 0xf6d418f8, + 0x1beaa511, 0xf9fa628d, 0x6e72a13d, 0x551e7a17, 0x77f4c01c, + 0x9306215b, 0x93c9d588, 0x71aba731, 0x58e57cd4, 0x6443ebe0, + 0xe8103e37, 0x2833ac41 }, + { 0x8da5ec5c, 0x7e564b86, 0x1c08db24, 0xac3d9da8, 0x8c57a728, + 0x9d7c1f0b, 0x9d343dc2, 0x3512afe7, 0xfdc60339, 0xb438e4cf, + 0xdcfa1941, 0x7d5a2700, 0x27320449, 0xd5f323f8, 0x1393c6e6, + 0x1b87a58e, 0x04baa431, 0xecb68bd1, 0x4722b4d7, 0xc09c1c5a, + 0x206b5faa, 0xf42faa97, 0x9976327e, 0xe1dcbcd6, 0x087787d9, + 0x655ba9e4, 0xde5c0191, 0xbd59c757, 0x0bcf3538, 0x673020ed, + 0xa49d6303, 0x120cd454 }, + { 0xcab0f9ee, 0xebfdb8f4, 0x2cce58ee, 0xbc003ef0, 0x5a8d0665, + 0x9b6a6841, 0x9b957774, 0x642ed3a6, 0x4721ab5c, 0x3de487f0, + 0x21a4f0d3, 0xef2ff380, 0x29dbddcd, 0xbd16f558, 0x0e93dff2, + 0x2ef05b4b, 0x0bc9aec1, 0xde1faa12, 0xd467fa92, 0x66dae2c2, + 0x5eb33e34, 0x758daf64, 0x8f0103cb, 0xa67ad9f6, 0x9be02430, + 0x151f693a, 0xeb4054bc, 0xd5698496, 0x7019336e, 0x8ef1677e, + 0x7fdeea3e, 0x021cfd16 }, + { 0xdf5c36f3, 0x5c73715f, 0xd64ad254, 0x703bde37, 0xf2cf7713, + 0x55368d10, 0x0f3993c8, 0x1e5ec7b7, 0x304ae4ca, 0xfdb16776, + 0x3d3bb18b, 0x0d8f717e, 0x66343d5a, 0x5267073f, 0x156008b5, + 0xfaeb52ef, 0x224a470f, 0xb97ad5f9, 0xed2ab51a, 0xaf86e391, + 0x9974302c, 0xdc0c7e57, 0xfd0ae28a, 0xc88fa817, 0xbf8ed59c, + 0x807c22df, 0xeb128bb6, 0x5dedc231, 0xa20595a3, 0x71edcd9c, + 0xc73cf78e, 0x07265b46 }, + { 0xbd66232f, 0x73dd99f0, 0xc4027716, 0xc59aaf89, 0x5b860fc4, + 0xaf826dfa, 0x7a943f3b, 0x239ea8aa, 0x523c428d, 0x0e0e1b1a, + 0x6973b95a, 0x55ea0e3a, 0x2557753b, 0xea399caa, 0x06957b1f, + 0xf8adf72f, 0x3bd34302, 0x0389f341, 0xf8a43a97, 0x333f27d0, + 0xadaf796f, 0xcd9c0c08, 0x49c12aa2, 0x6dcca49b, 0x7a0ac6e9, + 0xdd88deee, 0x0644080e, 0x8f47575d, 0x0cc2f4bd, 0x6e9d667d, + 0x31d1496c, 0x36c5754b }, + { 0xf323d84b, 0x9120046e, 0x7e789c4f, 0xa6991122, 0x921b8055, + 0x4b0eaf4e, 0x8079974e, 0x6339844a, 0x740f8c79, 0xc905466a, + 0xcd6def49, 0x1c18d0f7, 0x4b23e4ba, 0x5297da6b, 0xc41800c5, + 0x1c09dff3, 0x37ef6777, 0x6c49075b, 0x50513ded, 0xa94c3a40, + 0x6b0b1705, 0x3d6742e9, 0xc48af5ae, 0xc0784494, 0xc95822de, + 0x40c01532, 0xc164d94f, 0xa2ddade5, 0xa2975eb5, 0xfc8a8ac9, + 0x1946944e, 0x06fbf861 }, + { 0x3f45aa97, 0x2d65338e, 0x1d040feb, 0xd83b58c8, 0x0fdef8b9, + 0x05fef59b, 0xe4d7417c, 0x7beb071a, 0xb30a1a23, 0x982b61f5, + 0xfb65bd03, 0x4c5f2a2a, 0x5cbf6bf3, 0xe40abc9d, 0xf06612a5, + 0x422c326d, 0x9571ae28, 0xc921e69d, 0x23d3434e, 0x7c88b10b, + 0x9da07933, 0x96d2e957, 0x3619cf4d, 0x833d46a1, 0xd95eefa1, + 0xd9d19653, 0xa03e8f0e, 0x2a7d8411, 0x04bb5ab1, 0x5e642953, + 0x1f0fa9ea, 0x5e9ca0fd }, + { 0x197c5dc4, 0x5bd54571, 0xe78a95a2, 0xe2da40bf, 0xffdb0eb2, + 0x65fb9efc, 0x0d17467c, 0xe952dc2c, 0xc758c6a3, 0xc1fc9c7b, + 0xd4034a9a, 0xfc79562c, 0x61f64b56, 0x26e36fbe, 0x1e84728b, + 0x6adc4b9e, 0xa8f9ac8a, 0x7f165fd3, 0x03e3e013, 0x7bc93a45, + 0x656478e3, 0xeacc5513, 0x064ddc77, 0xd3391717, 0x76936914, + 0x75b318dc, 0x362424a6, 0x69b1f1c7, 0x49955f34, 0x8cc2045b, + 0xc6836af8, 0x940622b3 }, + { 0x0d997973, 0x4710ccb7, 0xd3f8f115, 0x3b29625d, 0x5b97abd5, + 0x8cf0c4d5, 0x673e14a5, 0xc6321e0a, 0x3d262246, 0x0541af9d, + 0x6fc83b11, 0xde6d8754, 0xf01652a4, 0x47e97da8, 0xad9802b6, + 0x0f82b3a6, 0xae9c44b2, 0x69aa4075, 0xced2bf77, 0xaf3f5de2, + 0x497a40da, 0x1ef1ea8a, 0x3c23ba9c, 0x2e0f8608, 0xf190a2c8, + 0xd8a998a4, 0xcfde3368, 0xe2b49c8c, 0xbde6bd71, 0xb9f49824, + 0x785bedb6, 0x80bb1664 }, + { 0xfd145cb5, 0x05e575fe, 0xac5e6883, 0x155ee561, 0x8793b273, + 0x461e70cf, 0x133b2338, 0x9f1553de, 0xa2a7ba07, 0x2fb9e0c3, + 0x3e7086fa, 0xc3bfd6a8, 0x8bb4cb93, 0xb6ba8500, 0x76f82dbd, + 0x0b66d789, 0x54eb49ff, 0x7d5a6ff6, 0x1f20b322, 0xcd65d237, + 0x54e29cdc, 0x79ea49c2, 0xcb118ff9, 0x64975963, 0xcc58000b, + 0x969598dd, 0x110c779c, 0x95107918, 0x63b85a35, 0xedfc1548, + 0x41212350, 0x077ba5ea }, + { 0xcdd86f61, 0x0b3a38d3, 0x0502a0ab, 0x43121445, 0x806d0272, + 0x1912edc5, 0x8a32f10f, 0x01dc1f98, 0x0e80c760, 0xbb1d31d1, + 0xf464e8b3, 0xd46ec7e5, 0x9abf49ee, 0xd569af36, 0x2cdade77, + 0x9d286ea7, 0x45ad5920, 0x2be7020d, 0x6299ae7f, 0xabe5236e, + 0xd3f55c07, 0xc93179bd, 0x52350e80, 0x8138995a, 0xaff07586, + 0x0901265c, 0xf4739653, 0x5b3c81b2, 0x9bc77d21, 0xbaf7581d, + 0x4591a2e2, 0x6b2006df }, + { 0x965b1bc1, 0xb2fe50a8, 0x962bb4fd, 0x931f536a, 0x000e7f99, + 0xd5718d33, 0x53d5125e, 0x84728f25, 0xd2125caf, 0x4f8a6184, + 0x357f679e, 0x54f1a701, 0x1531c05a, 0x70a9f40c, 0x6fa8b775, + 0x10d0cb97, 0x9dc12ce9, 0xb476f41e, 0x2755f894, 0x5c8d7a75, + 0x625741a4, 0xd6c12e10, 0xc917b16c, 0x262a6fb8, 0x38d6b0a0, + 0x24d116e6, 0x32c38e83, 0x849540c0, 0x66868afc, 0x855b911c, + 0xbd26b550, 0x53217ea6 }, + { 0x259f52b4, 0xfc840473, 0xe621146c, 0x968da9cb, 0xcacbd26e, + 0x964eb85e, 0xe4a54344, 0xab7daa2d, 0x381a4ff7, 0x6dc3b848, + 0x41c815ef, 0xa07a96b3, 0xc3d4b1e1, 0xc4fae9e8, 0x42ce9ea8, + 0x0f938d1e, 0x35cc052f, 0xa727dacc, 0xe9a06f07, 0xc81e01c9, + 0x4a6d65a1, 0xa9e08dcb, 0x6044a9a6, 0xf8e2d173, 0xf2bd295b, + 0x99893dd0, 0xf9781b12, 0xa08d3379, 0x61830ac2, 0x64bd6001, + 0xd9adbeef, 0x0386931e }, + { 0xd09885a5, 0xd0d7abb3, 0xe355bb07, 0xed9d2b67, 0x536ebaed, + 0x3bc238cf, 0x699ce4d6, 0x61ca2e78, 0x111594cd, 0x354ff447, + 0x03316ad2, 0x55cbe709, 0x49fff5c4, 0x418679fd, 0x0f9c6c40, + 0x75bacd75, 0x2972721a, 0x677edc88, 0xe5ef502f, 0x82596887, + 0xbf320e0e, 0x459e9367, 0x8bbdccb2, 0x81ce36ef, 0xb766863d, + 0x1ba097fc, 0xd58c6db8, 0xcd3a21d6, 0xb4a8748b, 0x0e4967cd, + 0x15041c20, 0x2caaf749 }, + { 0x6ed20424, 0x44f98006, 0x22471545, 0xb3e4ea23, 0x781a8c86, + 0x268ed1a5, 0x7ae5b70b, 0x48d0ab75, 0x356d3982, 0x6ca8b320, + 0x2df31fa4, 0x9ce8e681, 0xd925dcf2, 0xb909d232, 0xf56723de, + 0x302c8f78, 0xabac96f9, 0x11725d69, 0x57d1a170, 0x656a47ca, + 0xc18a2be7, 0x6bb5d511, 0xad50d9d9, 0xb56e45f1, 0x70b05518, + 0x36e886e2, 0x09d8ff91, 0xc7c71f3d, 0x9350361e, 0x65a1bbe2, + 0x45fe3bd8, 0x86d7f532 }, + { 0xb0bf719a, 0x99f16eb6, 0x8bc3d913, 0xb6975098, 0x26cd01b4, + 0xfae50e52, 0x90898d1c, 0xd3e3ac54, 0x887ec666, 0x4da3b9db, + 0xfbea45b8, 0x58300644, 0x8355b058, 0x369f3bd9, 0x579bcc13, + 0x0fb239a8, 0x6e2bd811, 0x4f5b4539, 0x24198fd2, 0x007f3baf, + 0x8837d51d, 0x68a676db, 0xeae75b16, 0x68eeea62, 0x3db6083c, + 0x5ffe5f94, 0x7d836c5a, 0x52c94d0f, 0xcbc1ff85, 0x5a4c3c6f, + 0x86c0b4dd, 0x682a55e3 }, + { 0x587495aa, 0xc8f235a4, 0x34c7245d, 0x2276026c, 0xb75a46e3, + 0xd6ae0cc5, 0xecc3e5e7, 0x890d3965, 0x14296629, 0x1b13342f, + 0x8a877227, 0xc89927e6, 0x2324a68b, 0x1543f27e, 0x49cdc21a, + 0x6c447684, 0x1452d0ac, 0x9bc7fd4f, 0xff4b045c, 0x2cc30a31, + 0x852f7611, 0x415d46a0, 0xc6fdd7a6, 0xad737052, 0x7b4c7c91, + 0xdcecc3ab, 0x7688d70c, 0xd2cdf01b, 0xe40d3905, 0x054f2542, + 0xfefe4dcd, 0x02227fa6 }, + { 0xb751948b, 0x1805efd9, 0xfdfd225d, 0x8efeed46, 0x4f2c8b22, + 0xcb128e09, 0x96f7c5e5, 0x9d1090bf, 0xb4cbeca0, 0x0959d044, + 0x8e08cb04, 0x21c955f9, 0x68fa4fce, 0xbc1f279d, 0x0710ae9a, + 0xb021e14e, 0x881167f4, 0x64d16e9f, 0xbbc9f1a5, 0xf5a5c22e, + 0xe3420eea, 0x5f3716df, 0xd5c4e843, 0x971eb915, 0x28ffba81, + 0x64fc55fc, 0x7dd37578, 0x3427e54d, 0x15ebc7d0, 0x446e6a62, + 0x29269778, 0x547e249a }, + { 0xa1ffda27, 0x4706868a, 0x7955cf50, 0xb4e6cdcc, 0x0a63f3d8, + 0xf65151e1, 0x9de5e70a, 0x5b4127ea, 0xf9342823, 0x3d2c09ba, + 0xaa2f7d51, 0x18c99d83, 0xddeec025, 0xa0c5bb1d, 0x03dcf1ce, + 0x7ffddf84, 0x616fdeda, 0xe57e4d29, 0x7932a1f0, 0xd2456569, + 0x3191d4e3, 0x7475e0e8, 0xc220218b, 0x3479bea1, 0x8bcb2505, + 0xfceb5c90, 0x3c6132e6, 0x1c685cea, 0xbfe6c1eb, 0xc42dc745, + 0xd2b08eea, 0x45a41cc0 }, + { 0x4dbbf0e1, 0x3ea9b2c7, 0xa17cf70e, 0x41ff962f, 0x5eeb4c66, + 0xdc1ea758, 0xa9beb17e, 0x4f5412d2, 0xa285741a, 0x2c9e4f52, + 0x984fd11f, 0x93df7da4, 0x0df3184e, 0xb2afbddc, 0x2421e375, + 0x96323d25, 0x49df781e, 0xc87be1e4, 0x3d589bea, 0x145601ed, + 0x28fff6dd, 0x0f0bd9bd, 0x8a0f298c, 0x2d3259d4, 0xd88e6944, + 0x362d7a77, 0xb6ac2af6, 0xa84c06b6, 0xd087da02, 0xba850ac9, + 0x42ee40c8, 0x128763c9 }, + { 0xacbac178, 0x29a80f07, 0x34b08f6e, 0x7cc20044, 0x70feded2, + 0xe9631d14, 0x86615767, 0xb2115da3, 0xcb088548, 0x7c75f5c4, + 0x9a2e8e03, 0x5b29d213, 0x8b881752, 0xfe9fda66, 0xc1de7ebc, + 0x3f1d8d88, 0x03218123, 0xb476565e, 0xb1c995f3, 0x07365561, + 0xb13eb71b, 0x2160cb18, 0x99b3a0eb, 0x7e8da513, 0xb20fcd74, + 0x5e8ca1f9, 0xb4126d72, 0x6a7e0067, 0x68bb637f, 0x1e8204b7, + 0xfc4f74d2, 0x75e96bcc }, + { 0x0d19716e, 0x189d1fdc, 0x7c384525, 0xdf585058, 0xea987d2a, + 0x64a846d1, 0x6c07150f, 0x12b6bf83, 0x4d6fd5b7, 0x91d85d46, + 0x4f53f55f, 0xa9788836, 0x81509129, 0x60083bd8, 0xea876f48, + 0xa7672683, 0xc15b2489, 0xe80b2e7a, 0x42d1d992, 0x985ef8d2, + 0xcf3de492, 0x9c57b029, 0xb1487627, 0xfe02f83c, 0x8ae5b687, + 0xaeba4fe4, 0x5d6b8196, 0x8a86f09b, 0xa16e523d, 0xd88f566b, + 0xba268949, 0x309a6e9a }, + { 0xbdfbe97a, 0xef27ee50, 0xb8c50c4d, 0x1a5fe70f, 0x7fe09f5c, + 0xcc7beb01, 0xbed36cc5, 0x8fa15a85, 0x7550ed3a, 0xc0c3acdb, + 0xeb908681, 0xc581ef87, 0xc49d5ccb, 0xa15b3362, 0x1fa264e8, + 0x0fbb1714, 0x8e1eee88, 0x267f8d8f, 0x21c2b63d, 0xd31ccfd6, + 0x53be7efd, 0x924dbe7d, 0xdb2a358a, 0xd42e877f, 0x75d68ac1, + 0xcf9673c7, 0x714fea55, 0xe35978fd, 0x5769b202, 0xeeb36653, + 0xd7593789, 0x0458258a }, + { 0xa042dbdf, 0x5df71a74, 0x5779dfa2, 0x2d405857, 0x0d2e6657, + 0x0e66cba7, 0xca2e892e, 0x285d6745, 0x0f0e6b5f, 0xf56a8def, + 0xa30767c3, 0xe0ee851d, 0x43346b9c, 0x98c05658, 0xd6b3c742, + 0xb35fce26, 0x39777e00, 0xc0895bff, 0xe7b6d886, 0x83c8f6a6, + 0x4f02904b, 0xbee14843, 0x2e84ec34, 0x7f74915b, 0x96d10991, + 0xbaaf663c, 0xe41facc0, 0x004b8757, 0x6f86c029, 0xa2b880e5, + 0x95b77358, 0x53f4a3e0 }, + { 0x89fc48e7, 0x11bb08ce, 0xafab5aeb, 0xba60c577, 0xa0c1cb5a, + 0xf06bcbf8, 0x79757cb6, 0x7d2efaea, 0x76319160, 0xe26d90b1, + 0x2b77b7a9, 0x42aa1ab6, 0x285df2bf, 0x38eec0cd, 0xf3a8f7f0, + 0xd35947f5, 0xfc1cb5b5, 0x97c8dc0e, 0xc45845cf, 0xfeb8cca0, + 0x249e26f2, 0x16e8d989, 0x483ed89a, 0x7c264e6d, 0x51d91073, + 0x13a3f145, 0x305e99f0, 0x8501562e, 0x6908d563, 0xaaf98d74, + 0xd723d236, 0x0a99e653 }, + { 0xabbc0559, 0x23536f46, 0x9aa1a160, 0xc163067b, 0x0c1681b5, + 0x229fd229, 0x1378e907, 0x61254be1, 0xab793a2d, 0xc60ff57a, + 0x466552db, 0xa6f2df8b, 0x8c170a36, 0x9ad31893, 0x29b74d9a, + 0xc5cd9abe, 0xf7848523, 0xcf747273, 0x0d0e3063, 0xc126a93a, + 0x4248e3d8, 0xfe2021e3, 0x8323ddfa, 0xd97343ee, 0x332639e7, + 0x9f768775, 0x75325548, 0x9650fc31, 0x3eebf7ea, 0xb595dbd1, + 0x010fcbc0, 0x3a95cb45 }, + { 0x39d7ff2e, 0x954e68cb, 0xc1d5c48f, 0x8dd1cb4b, 0x7169438a, + 0x02a92c77, 0x91cad8ce, 0x7965c0b0, 0x32cd08d2, 0x0c5798ab, + 0xa6902bda, 0x1a5bc3c3, 0x5186d218, 0x545d0925, 0xd27e64db, + 0xf0077cdb, 0x8cd092da, 0x0157caa4, 0x24532ab3, 0x2a2fa3a0, + 0x41ccaba3, 0xa5fb639b, 0x4744aee6, 0x01702dc1, 0xcdba93da, + 0x485bb436, 0x329784f1, 0x93597f66, 0xdad672c3, 0x5d713c1d, + 0x030b7245, 0x366d222e }, + { 0x573ea5b2, 0xd50b4875, 0xa90da44d, 0x0fce401b, 0x7a1a0310, + 0x7b53fa65, 0xcf114460, 0x722a80a5, 0xa538bf49, 0x0b8ebf05, + 0xd32acd21, 0xae141147, 0x7b5ad07d, 0x6692712c, 0x3f48ca07, + 0x6dc5fee7, 0x2b8a78d8, 0x98ed1499, 0xdd2f1759, 0x4e8b3145, + 0x5f971b8e, 0x43408de1, 0xadf1b368, 0x055ea6dd, 0xe5932b7e, + 0x4bb76e73, 0xd30893fd, 0x44287153, 0x0661bfda, 0x173dccd2, + 0x79defd25, 0x9072ba99 }, + { 0x9620ea39, 0x474de4dd, 0xc831cee8, 0xfbf1649f, 0xcd3a9c43, + 0x0b0e8bb1, 0x3f3df1d5, 0x6a38286f, 0x8f0ec9b3, 0x4ed072b3, + 0x729c09e3, 0xa6e4c987, 0x8ad12242, 0xea3e8ac6, 0xfbdfa5ba, + 0x6ae0e22b, 0xb0a0f592, 0x56171ecf, 0x6b871f8d, 0x33b2886d, + 0x35e11bda, 0x6b19bea9, 0x7f0f153f, 0x4d815a40, 0x7d6c02ee, + 0x7e608d97, 0xb6a88f46, 0x7e8f23d9, 0x439d1654, 0x26ac9652, + 0x35546c29, 0x8d92c6bd }, + { 0xabeb0ff7, 0xb3e0d7ce, 0x3e0e42f8, 0xfbe35254, 0xde808499, + 0x57d1b226, 0x1cd44bc3, 0x9ece2e1f, 0x435cfee1, 0x1245adbc, + 0xf93f581c, 0x874ee840, 0xbda0b947, 0x916a779c, 0xfa57ae0a, + 0xabcc815a, 0xf0a621b0, 0x97adec2d, 0x81f90bdc, 0xbe6a502b, + 0x53bde63d, 0x54bf9de1, 0x78884c25, 0xa88fdabf, 0xcbbb5470, + 0x30aa52b1, 0x29053ef5, 0xf805396c, 0x8dd827ea, 0x8d43d898, + 0x5c1ae5c0, 0x4e4bec17 }, + { 0xfcc09676, 0xbf8483a2, 0x19ea9a94, 0x457c4a3f, 0xd702a5dd, + 0xa6852ef3, 0x843fe7d8, 0xe7915fd2, 0x16e35158, 0x644bba98, + 0x9ed746f0, 0x8d1b95d0, 0xb90af0b5, 0x47704581, 0xd4fd135e, + 0x0bd4bc6b, 0xb4e833a5, 0xa6dce067, 0xff56a9a1, 0x2c0e8f30, + 0xec2c63fe, 0xa9c80800, 0x98f508a8, 0x449c20a5, 0x3292813a, + 0x02b94cb3, 0xec7e81a2, 0x647e3d28, 0xb4877677, 0x72e67d1a, + 0x6f9ded24, 0x7a4aa3f5 }, + { 0xe27a0045, 0x559ef1ba, 0xb242cb50, 0xdc812d4f, 0x39cf8d24, + 0x23a478e4, 0x9b3f9c54, 0x97544fc5, 0xaffa1fcf, 0x5ac68132, + 0x34a2c83b, 0x74f8fee0, 0xcd3f4bb7, 0x96cc640f, 0xb0512ea6, + 0x775dce9d, 0xcdce381e, 0x67dca19d, 0xa9d3fe55, 0xc1eeb3f3, + 0x1a19274f, 0x38e0bf42, 0x28d69b12, 0x15992fb4, 0x9fd09df8, + 0x48fcebde, 0xb41ab5df, 0xdc9dfa4f, 0xc0a269c5, 0x0cbd7dc8, + 0xf7f0ade1, 0x60282a7b }, + { 0xdceea2e7, 0x7c07e538, 0x3c42061d, 0x38a322c8, 0x4f1f6516, + 0x676828f9, 0xc7776a10, 0xf21b69fb, 0xb5e6b405, 0xc63a3417, + 0x91a7b642, 0x4c99f258, 0x2cad1440, 0x38692ca8, 0x00869bcd, + 0xf1e82ffe, 0x16fe466a, 0xc30b714e, 0x19019138, 0x5fb742f9, + 0x0fa516ae, 0xe90166d0, 0xd8c73a43, 0x5550f7ac, 0xfbc5c372, + 0x2d6a407d, 0x68cc39ed, 0xe47a7539, 0x4a5fbe70, 0x3fd286d9, + 0x23c6b942, 0x5f4ae9c7 }, + { 0x53f4d561, 0xd96a2dda, 0x16da1992, 0x286d45d0, 0xfdd4b051, + 0x449a01fb, 0x9f2195ea, 0x25488a0d, 0xa37661b3, 0xc4151b0a, + 0xf9e5ee02, 0xb98c471e, 0xa8658817, 0xa4bca86e, 0x7a68fc0a, + 0xbbcadb87, 0x6b7366a9, 0x88b34649, 0x15661c2d, 0x32ee98d4, + 0xc901420c, 0xf5b3b4c6, 0x2f2752af, 0xa2352735, 0x510e4d9c, + 0x2f64ce73, 0xaca4aa80, 0x939a7f26, 0x401aa503, 0x9cd3e291, + 0xdc46afd2, 0x92a01423 }, + { 0x1c2f7dbd, 0xe9f24be1, 0xb7d527fa, 0xda8c900f, 0x8648f128, + 0x963e25bb, 0x48141941, 0x9ab713e2, 0x7a6756fb, 0xe87f7d01, + 0x058d90bd, 0x274dd85e, 0x82566abd, 0x823fee7a, 0x74240195, + 0x9f6230d7, 0xacb5e46e, 0x04579f2c, 0x16a4c87e, 0x2a226263, + 0xd99b0857, 0x9ca19a43, 0xe488789e, 0x86dc2ba3, 0x9406c3bd, + 0xf960b5b9, 0x8960957e, 0x6f2c428b, 0x161c515b, 0x90748706, + 0xaa88cb9b, 0x0fc8fe1e }, + { 0xfeb90f2d, 0x68ae1bed, 0xa48b1559, 0xf393bb3c, 0xf64e9635, + 0x2be62f9c, 0xf8be75c2, 0x354c2410, 0x5e6f7529, 0xbd7ea703, + 0x162cab31, 0xc264868e, 0xc860f3ff, 0xb1391e70, 0x1d89837e, + 0xdf367c75, 0x2bf32941, 0xe150b6b4, 0x78c1318f, 0x95e8f46e, + 0xa2c4b160, 0x2b3f1dab, 0x701afbf3, 0xc6ccf5ce, 0x5e8874c5, + 0x3ad27530, 0x5dc6dcbe, 0x39285e51, 0xd99892dd, 0x3c954d86, + 0xdfd3789f, 0x2d0ba862 }, + { 0xb472e1af, 0xeacd8ee8, 0xb76abbcc, 0xeb354eae, 0xd0d93fbd, + 0x9b520bf8, 0xfe6fc706, 0xfccd60d7, 0xa4ee2f39, 0xa9353dde, + 0x9a81e51e, 0x5eb0925e, 0xd1366777, 0xee334da1, 0xd5354d69, + 0xc1d28c9f, 0x92a5ed54, 0xb9771755, 0xb7f70d81, 0x5d3e367f, + 0xa933ae7a, 0x7be7eeca, 0xe23cfbb7, 0x264cf1f9, 0x89497681, + 0x0d129f4a, 0x09b6235b, 0x705375a4, 0x48a376da, 0xccf64c75, + 0x4d41dbfc, 0x963c8712 }, + { 0xde36a814, 0xbae290cb, 0x733b12b5, 0x9bdb0195, 0xf77fe0e1, + 0x0ebad867, 0x29720cea, 0x0a7d19fd, 0x9029ec72, 0x434d7651, + 0xbb51911e, 0x856aff17, 0xd80a7f60, 0xd0a25d9a, 0xf848c106, + 0xffca86af, 0x43ad749c, 0x53e8bdf9, 0xe3e696bb, 0xfb9e0284, + 0xeeee4215, 0x3eb6630a, 0x2ecf3c63, 0x9d8fbb9e, 0x4e00c0c0, + 0x71da4ffa, 0x5d57beac, 0xb296be59, 0xa8cec7ef, 0x1751fbad, + 0xff55d7bd, 0x2d03eb3c }, + { 0x04f2ec1d, 0xeb16925f, 0x0d147ee2, 0xa878f276, 0xaad9d9e0, + 0x442df604, 0x3f71035b, 0x891df44b, 0x8cb95d5b, 0xc28272b3, + 0x5ee8ed23, 0x6f14efb5, 0x13b0f3e3, 0xf3c4460f, 0x6bd7335e, + 0x889f9bd7, 0xf755ba6e, 0x889ee771, 0xed219b6c, 0x626984fe, + 0xec2ee411, 0x2d44c737, 0x63efcd37, 0xb94385a2, 0x6637826b, + 0xd909321b, 0x3ee6b7a7, 0xc24f8a79, 0xa7cf61b7, 0xa3ca8d24, + 0xc54bacd9, 0x842e40c1 }, + { 0xa661d843, 0x5a268ed6, 0x4f5b30cd, 0x02328cca, 0x1311e177, + 0x16e6fed1, 0xc6695967, 0x690decb4, 0x57b2e280, 0xbdac5bf6, + 0x1efe42d0, 0x827f82ca, 0xca5fca2f, 0xc554ec0a, 0xdde45506, + 0xac5276c1, 0xe3077513, 0xb7f4cb08, 0xcc8797cc, 0x8caf6d9a, + 0x0d9332d2, 0xd5964814, 0x285a409f, 0xcc6ae297, 0x6223d093, + 0x7773c2a5, 0x5128fc09, 0x2d5266ac, 0xbc31fe6c, 0xa596b7cb, + 0xcac91328, 0x0e63319a }, + { 0xf0360ac2, 0xb5cd2fad, 0x285e605a, 0x86b660de, 0xe25b9b14, + 0x82c6cf10, 0xaa9ac554, 0x9d5fa38d, 0x526c070e, 0x3dfcf1b8, + 0x3fccc52d, 0x0379a96b, 0x0bfcc7f5, 0xe3659c29, 0x69d3e6a1, + 0x5b1a3db5, 0x9b7b42d5, 0xb41528b5, 0x9c22a006, 0x934defa4, + 0x9b4ce3b6, 0x90f38018, 0xb3abaf32, 0xb073bc04, 0xff8389e2, + 0x27a5a222, 0xffa5a35b, 0x0b7a9d51, 0x28e1a7c2, 0x4939ecef, + 0x1872705a, 0x88839da2 }, + { 0x701ce29a, 0x56b66c30, 0x58981d50, 0x3acaf126, 0x105f9f21, + 0xd4dafc0c, 0x373e3d13, 0xfee571e6, 0xfa2ee3ca, 0xe7269c86, + 0xdd20385a, 0xf5cca64a, 0x3000e9ac, 0x217f2757, 0x0e7273ef, + 0xc934db47, 0x355b6776, 0x4294f4f7, 0x6fc05180, 0x1faa36b9, + 0xb052190b, 0x8f88b1db, 0xe9eaef52, 0x35791b90, 0xdb681b90, + 0xf37fb2eb, 0x4415c369, 0x39d0a51d, 0x1d2e21c9, 0xfc59cca7, + 0xa1f50c26, 0x64128cfe }, + { 0xe8f5b0b5, 0xf03678a2, 0xd340f059, 0x5c7e249c, 0x93ca7cec, + 0x41440441, 0xbc83af98, 0x075ca346, 0xfaa8bbb0, 0xf39f0033, + 0xf38230f7, 0x3d18f0ed, 0xd448f345, 0x78dff00c, 0xd51aa475, + 0x849228c0, 0x30c928d1, 0xdd4e2708, 0x8f12cfd3, 0xc66ba686, + 0x88b3a206, 0x091049db, 0x016dae01, 0xd865d059, 0xe253e37d, + 0x4599e905, 0x7ce9871b, 0x322cf0c2, 0x174a132e, 0x014f54da, + 0xbdabcbda, 0x93634a09 }, + { 0xa9a2e304, 0x62826b27, 0xc1a4c124, 0xc57e1866, 0x22381710, + 0x913ab832, 0xa9847cfe, 0x7e9b6b85, 0x2b5f46fd, 0x29655cf1, + 0x8038e66d, 0x7295572b, 0x6fa95eab, 0xe4cba601, 0xb9deda81, + 0xbbc11071, 0x3f1cf61e, 0x97f0009a, 0x373e0cfb, 0x5372777b, + 0xd139d63b, 0x302f909c, 0x4f87d78e, 0x1ed672da, 0xb4048763, + 0x362077a3, 0x9dcc22b2, 0xc408c32d, 0x26deeee7, 0x4b4c5bf2, + 0xbc06357e, 0x266cb467 }, + { 0xb56363e8, 0x6faa4154, 0x3c1aa4db, 0x4b4fd078, 0x2b9e6597, + 0x14358dde, 0xfa004b84, 0x5b34ae3e, 0xf19911a6, 0xcf44b2ec, + 0xa536bf78, 0x55caa833, 0x8870dc95, 0x606e1eb9, 0x09f3511d, + 0xe3c3287d, 0x9d5cf364, 0x68b2f4eb, 0x63ab8c9e, 0xc154e892, + 0xc36ab611, 0x1548828e, 0xa1b7d120, 0x0932bfcb, 0x5315b8d7, + 0x7ee7b5bc, 0xf7473ac1, 0x782fd0d1, 0x3c8f2af3, 0xbcb029a8, + 0x52454ee1, 0x4b1d5a1b }, + { 0x63d52c0c, 0x12fe5174, 0x188c099d, 0x3735525e, 0x360e3956, + 0x5c621563, 0xacfa5a43, 0x88b3f1ca, 0x797e8107, 0x90123a0a, + 0xb15e080a, 0xba31f6b5, 0xfca3dada, 0xd7de5e12, 0x0df511c8, + 0x3287361b, 0x65757d4e, 0x7cc800d4, 0x5207ec91, 0x10810f3d, + 0x30eea0e3, 0x0d4e56f1, 0x3ea5a2ec, 0xbbf7ee13, 0xbe6abbd0, + 0x6fc07762, 0x120bf619, 0xc831fdce, 0xb622d42a, 0xe07439fa, + 0x508e4b27, 0x8186b93f }, + { 0x09312867, 0xc619d154, 0xbfaf7db4, 0x7e042c05, 0x1f5f5dda, + 0xc1cf1668, 0xa4fc3d82, 0x50aa5057, 0xce68b8fe, 0xed30ed65, + 0xbeb4d644, 0xecb01c0b, 0x831c0497, 0x7b5dc444, 0x9b7d9b1c, + 0x351e6a00, 0xd9477c91, 0x4bb863b9, 0x05d4110a, 0xaba65891, + 0x43580b7a, 0x30086cf4, 0x90be357e, 0xb139c076, 0x27b5214e, + 0x12bfff1a, 0x22c3ab57, 0x79cfc6d7, 0xf34a9bfa, 0x4743de57, + 0xc9ee2b2a, 0x0bf97e97 }, + { 0xdda19e96, 0x96ec4ec8, 0x6c306e8b, 0x54ce18ea, 0x65f6918a, + 0x7e83612b, 0x0d9a0d99, 0x1ac6f68b, 0x62fdcc09, 0x98a697a4, + 0x95bc3e13, 0x65ce25f1, 0xb3939730, 0x1896ecda, 0x32f12806, + 0x9eb81a0f, 0x1d2dc7df, 0xd3d7416e, 0xad473599, 0xe22c7976, + 0x9f5ef439, 0x3de37a9a, 0x9e69d94e, 0x6b7ac0ab, 0x0a9d0bc8, + 0xe6bfa9e0, 0x5676f120, 0x576a870d, 0xfeaac23f, 0x3bd91bb4, + 0x3e40aabb, 0x8fe5482c }, + { 0xce9a4d1e, 0x85ae67c2, 0x4f1d2038, 0x4c3eb803, 0x25d06192, + 0x5c6c8f3a, 0x308fb41c, 0x803de0ad, 0xe71c294e, 0x9961f5bc, + 0xf02eb0da, 0xdc62078d, 0xb64ae8b6, 0xc87ef515, 0x50b4d18f, + 0x69679f1e, 0x52199f43, 0xc5c009a1, 0x0f640a5f, 0xa7d484be, + 0x23dab566, 0x4c918bb1, 0x64275d2c, 0xa67c114c, 0xcad2ded6, + 0x95a913b9, 0x6b4b5c8d, 0x189ed18b, 0xb42d3bf6, 0x4aeb6206, + 0xbbc8bc3f, 0x3928c669 }, + { 0xdacb4b64, 0xde4bea4a, 0xf26179a1, 0x03f62a44, 0x7a9112a4, + 0xf3aac94e, 0xd36f331e, 0x90448fbd, 0x407b85c4, 0x426042bc, + 0x2121b77b, 0x5ad8a596, 0x67cee984, 0x31674a4f, 0x4e3b2f0d, + 0x7fae8bbe, 0xa7c930eb, 0x681df6dd, 0xc259d0d4, 0xadeefa98, + 0xbea1c1fd, 0x1b14d9e6, 0x21d405d1, 0x3baadc8b, 0x73892754, + 0xf01dff93, 0xf071cde4, 0x81c35b3e, 0x9150d0d9, 0x1704d2e1, + 0x355134f6, 0x6ccc888f }, + { 0x7ad7504c, 0xf8d36f0e, 0xf7959ddd, 0xbca3265f, 0xfede67aa, + 0x0dcd1ede, 0xbaebf32f, 0x1276f4ce, 0x014edcfc, 0x6825a6e6, + 0x99ad8eb7, 0x0b8c1a82, 0x09b8ce1e, 0x312024a9, 0x9cbd351a, + 0xcb8fd98b, 0xfab1e8be, 0xa4841378, 0x3973cacf, 0x17ed0f5d, + 0x259d5254, 0xa17e1484, 0x74b91393, 0x53d5b843, 0x1aca3ce9, + 0x8f792b21, 0xc8c0f815, 0x035ff110, 0xad4ed7bd, 0x6afa6357, + 0xb26faef9, 0x2f151980 }, + { 0x29d2d439, 0x0c8631da, 0xbc039955, 0x121fbbc2, 0x6c05b75b, + 0x3e5a9792, 0xb6ce47ec, 0x6d6cf4c0, 0x9d88c658, 0xbaaa1767, + 0xf3355a17, 0x031db9e7, 0x0aef5a85, 0x8381e3d8, 0x15a31bdf, + 0xc71db290, 0x9498fd7d, 0x638f6b74, 0x13beeef6, 0x44edf3f9, + 0xf4ab67b3, 0xe6173271, 0xfd22df11, 0x3a202c70, 0x205c4e92, + 0xf7be0389, 0xa8eb9920, 0x1c219085, 0xbeb54aaa, 0x6c805ce8, + 0x0ac58d65, 0x354b05b7 }, + { 0x7a9170e9, 0x7171e236, 0x4cad50cd, 0x01eec42d, 0x3cddccfb, + 0xffbe824f, 0xa66cae1a, 0xa73e8ce3, 0x965c7d01, 0xb7138a7f, + 0x5c3d971e, 0x00058e3f, 0x2ff0a72b, 0x52591ac3, 0xbbbce76f, + 0xa32fb5bc, 0xa9f81a18, 0xf3241ab8, 0xeca68630, 0xf31d3332, + 0x4482f13b, 0x847af9fc, 0xa4681be2, 0x6196e217, 0xe55efcf9, + 0x9938f932, 0x70acc705, 0x3e7dacb8, 0xcf09fac2, 0xd41be893, + 0xae3523a1, 0x48dc55c4 }, + { 0xa5092193, 0x8e623826, 0x6898970c, 0xe46ec362, 0x25c9eb41, + 0x2f1356af, 0x83c7d245, 0x41780640, 0x97d00e38, 0x982def67, + 0xa512151c, 0x382eb6e7, 0x8af58869, 0x154e1077, 0x8a51cf02, + 0x18707075, 0x71313c58, 0xcdeba9f7, 0xba155904, 0x5d67b973, + 0x1d0d7b3a, 0x851c9f4b, 0x8b8af2cd, 0x19f29d71, 0x986b8d62, + 0xcb94ccff, 0xb93b9c33, 0x8725e24b, 0x66e38c68, 0x405ce4c5, + 0x0b6dc021, 0x5f6a8edd }, + { 0x8f9a8690, 0x83704ca5, 0x2f76a407, 0x3f369766, 0x69201028, + 0xfbc12d8c, 0xbce3a4cf, 0x4cd58f16, 0x04aab26d, 0x7804664a, + 0x4ea457a8, 0x005cfbba, 0xb8a59794, 0x537951b3, 0x4fe1f739, + 0x4ca2b9e4, 0xdf325797, 0xe4428acd, 0x0ea243db, 0x648da342, + 0xf43ce01e, 0xcce6562b, 0xf27db490, 0x840f0421, 0x8bfb7cf0, + 0x156ccb70, 0x5a8797d3, 0x9b33480d, 0x9eb814bb, 0x2e12e07a, + 0xca7f87ac, 0x1ca65072 }, + { 0x2b9d25a0, 0xfbb321cf, 0x40a746db, 0x66affdca, 0x59e368b5, + 0xc1c1530e, 0x7d80068f, 0x56ed1ea4, 0x5647dd68, 0x9b74d8fe, + 0x89b78da8, 0x1d96b507, 0x8bbe3391, 0x39b75243, 0x0d858c5f, + 0xef8d443e, 0x9646aa34, 0x4dd2db49, 0xe667543c, 0x7fad3bd1, + 0x68980985, 0xd0d710c0, 0x49facaba, 0x9f7aff32, 0x14f9a192, + 0x055dec1c, 0x1fb307a1, 0xaca66399, 0x35ffff64, 0xac44fd91, + 0xcbad3cee, 0x462cafb6 }, + { 0xde3237dd, 0x1660a647, 0x82b87404, 0x95f735cc, 0xddfa55f8, + 0xf7879f59, 0x726b914a, 0x15ef043e, 0x1c93e298, 0x1875393d, + 0x6ef18331, 0xa1a2be74, 0x25a9a12b, 0x4e7e8dfc, 0xa9c3917f, + 0xdfefc97d, 0x0a2ebe41, 0xbc875d03, 0xa732d1cc, 0x0f75d235, + 0xd9baa6d3, 0x06fee7fe, 0x65f48576, 0xaa784fab, 0x513f83c0, + 0x23155e22, 0x3e8f9d13, 0xd2fb7718, 0xb546eafd, 0x2a291503, + 0x6cd93608, 0x1293c98c }, + { 0x49d53b77, 0x72781251, 0x96eafac7, 0xa6ab403d, 0x4a36b711, + 0xb7d7c7db, 0x87e771c1, 0x8238c708, 0x33b37522, 0x495f6abf, + 0x8c87530d, 0xb0b0289c, 0xe77b111a, 0xca83cb86, 0xa1bd189e, + 0xbe1c0fb8, 0x1ae9d7c7, 0x58cfb2fb, 0x4940c3e8, 0xd05c23c5, + 0x74ad9107, 0x16e79e41, 0x064e7142, 0xa0a47f05, 0xfdfd614f, + 0xc6929cd4, 0x3946988b, 0xedb2584c, 0xe46f8fb1, 0x73e4b5f3, + 0x68ea94ba, 0x53b79aa1 }, + { 0x44bbb6a1, 0x216fafce, 0x67821728, 0xd3a5bba0, 0xa9dd939a, + 0xef1e4b30, 0xf19efafe, 0x022eaf3d, 0x7b4ec014, 0xfed5abce, + 0x512c6738, 0x64968ee6, 0x29fe89a2, 0x23119869, 0x47397c05, + 0x0d539d8d, 0x234596c4, 0x6400bc54, 0x5346611d, 0xb9287f58, + 0xc9d5da0f, 0x04099903, 0xc83af2a8, 0xe5ef4997, 0x328151e1, + 0xc89dc01b, 0x58401104, 0x150fb4a9, 0xf3872c9d, 0x40a6f7d5, + 0x56c2e833, 0x8290d6d1 }, + { 0xd8546946, 0xf84637c6, 0x69ec57fa, 0xda134a39, 0xd789007e, + 0xd42359a4, 0x0dc7b809, 0xb42557fe, 0x2d6784a9, 0xe62ae52d, + 0x0bcadb5f, 0xa2714ca6, 0x33aafca5, 0xcc208de6, 0xed967811, + 0x2380ed5c, 0xdb321660, 0x6e6b55e9, 0xa675235a, 0x1bead02c, + 0xb33fa0e1, 0x51cc6ef9, 0xf06a2a08, 0xfd223e26, 0xec47b3cf, + 0x00f332e1, 0xa0aa984e, 0x459f297b, 0xee952e14, 0x6fa1d969, + 0x304fabb0, 0x506ef1ab }, + { 0x35bff163, 0x11b4eb27, 0xea9fa984, 0x7130b96f, 0x9deb27ce, + 0x66aceb3f, 0x9dd1c3d5, 0xa2daf1a5, 0xa73075aa, 0xf5090a7e, + 0xe3071b58, 0x36a6af39, 0xdf73ad9c, 0xa28d633d, 0xbdc89a16, + 0xdd354cac, 0xd4dcbc3c, 0xdfea3423, 0x379d92d1, 0x6eec74d2, + 0x8eed6765, 0xe14a456f, 0xfa8feb1f, 0xfabe7743, 0xb98fcbc7, + 0x1404ccf8, 0xf71a706e, 0x6ccd2fbf, 0x4d85c678, 0xdaaf3fdb, + 0x15200344, 0x415b7dbf }, + { 0x7d8377a7, 0x97010586, 0xcb803272, 0x068a3d68, 0xf03a4c32, + 0xfd67d289, 0x93c8f290, 0x4bc7095d, 0xe9e5a2b8, 0x712fa13c, + 0x0feb9f3b, 0xfc6ac6c6, 0x6e0e54c2, 0x0cda36d9, 0x86320a01, + 0x45499751, 0x97f00f11, 0xf9318c91, 0xe6936508, 0x01dc4c3f, + 0x85f068aa, 0x769a2ef9, 0xa2b5511c, 0x3522cef0, 0xb4122e05, + 0x006965ed, 0xc175d43f, 0xfce0fafc, 0xec831d59, 0x525dc9bd, + 0xaf58879d, 0x1ec314f1 }, + { 0x2c8310c2, 0x0663feef, 0x457e3f74, 0xaa7e14da, 0xe5346887, + 0x392b10fc, 0x637ec2c5, 0xcde4a38f, 0xb542f8df, 0x50773320, + 0xf7de1711, 0x341302f9, 0xae4b9bc6, 0x018b1c63, 0xdd2f9e6f, + 0xf001c46e, 0x26eccfa0, 0xd3bb0a97, 0x7746e0c7, 0xa931b99d, + 0xf5875aec, 0xe0c8b6f7, 0x96939c82, 0xbb32f17c, 0x3de5a664, + 0x765135d2, 0x52abfa6b, 0x71936cb4, 0x2dc105de, 0xad5cc08f, + 0x7fff5788, 0x17e91d12 }, + { 0xb7e051ca, 0xbe92ced3, 0x19c776d4, 0xc644d4fd, 0x0086784b, + 0xc8ab4b52, 0xce9d6b31, 0x3ea66227, 0xd289e9c7, 0x395249a3, + 0xd12a19ee, 0x54509e65, 0x8c365aec, 0xa7bd4692, 0x77963e0e, + 0x354997e4, 0xb599732d, 0x0d765957, 0x91d4a3b6, 0x99584aeb, + 0x1deb3e28, 0x6e653ea4, 0x572571df, 0xca7c98ed, 0xb18ae1f9, + 0xf301a38f, 0x63f7b97e, 0x1629f7c2, 0xafc4a0d5, 0xdf242282, + 0x3ddd0c01, 0x118f3b4b }, + { 0x7ad4762b, 0x74a0a0a8, 0x8c58d175, 0x1aef84da, 0x4cf76d86, + 0x16ff4960, 0x7e60d98b, 0xc0be8786, 0x3ecc1dba, 0x83637ffb, + 0x5dd6147a, 0xc244a609, 0x5b0846e5, 0xa3e17834, 0xe77a4c05, + 0x735eb686, 0xdf758695, 0x5bc18b4f, 0x1bdfe52f, 0x15618d0b, + 0x00715ba1, 0x878ecc0d, 0xc2dd617f, 0x1dbdbd1a, 0x21b61710, + 0x21d2b631, 0x44f593c2, 0x22ce8a79, 0x44f17024, 0x3b9b536a, + 0x8d03e727, 0x01d0a67c }, + { 0x1e46533c, 0x7b964236, 0xfb88c2ae, 0xe9477990, 0xa42c4a18, + 0x019b5d16, 0xd83c7a45, 0x7135e81d, 0x4cb663e3, 0x74a69bdd, + 0xe76c0d63, 0x7b67ecdb, 0x11e68da6, 0x03d54521, 0xd2e8650a, + 0x596cceb5, 0x2af03b37, 0xcd572dfd, 0xfabd5952, 0x52364ba1, + 0xb4ed8569, 0x7f47d456, 0xc950d5d4, 0x5ad8b572, 0x486e2f84, + 0xcadd2dfa, 0xc56bb044, 0xdd527b43, 0x997c08e6, 0xc9adba24, + 0x7da6320f, 0x1b625b06 }, + { 0x4fd8446d, 0x44dfaa7b, 0xaf6febeb, 0xc01b2f01, 0xfe8838b5, + 0xbf444388, 0xbba9758b, 0xf33c434f, 0x87156bc9, 0x2b971cba, + 0x1f49098b, 0x6b245e5c, 0x2b41c5dd, 0x87dcb534, 0x34d852d7, + 0xdb1f80c6, 0x2433da34, 0x6d6e3258, 0x3f7df0c2, 0xf6682065, + 0x360cb365, 0xc4ca567c, 0x9826656a, 0x321faac2, 0xbf069768, + 0x13f5ca6f, 0xa7076639, 0x15397921, 0x8400736e, 0xbdf14328, + 0x19fc948d, 0x333eca96 }, + { 0xac775d81, 0x23337948, 0xd41dbbca, 0x38c2518f, 0xbcfce948, + 0x623c7a4f, 0x54703fe7, 0xaad36236, 0x13fb3b5b, 0x2b3a13a4, + 0x7f5c01f0, 0x5db3565a, 0x52359661, 0xd72408dc, 0x1d616e91, + 0x5a17f8e5, 0xcb25b999, 0x90c16eeb, 0x3393743e, 0xf35e8cf1, + 0xe54b64a7, 0x987da74a, 0x65cd449d, 0x557b322a, 0x37e7b15d, + 0x765082a5, 0xf2cd134f, 0x4d25c742, 0x4ccf0746, 0xae9d9c07, + 0x8728d135, 0x72fc2110 }, + { 0xf96004c8, 0xa906b203, 0x458055ff, 0xd83f95cf, 0x55f35909, + 0xd77d5867, 0xe550c8ee, 0x4a9ea6fb, 0x55a06081, 0x91c8cca9, + 0xbce82062, 0x4a1fee78, 0x9a3df85e, 0xeb9ade06, 0x7d3de666, + 0xfbbdcf0c, 0x5d336d51, 0x228a391b, 0x5c2ffc3c, 0x760f8d28, + 0x2f7b165b, 0x1ee48de3, 0x56177040, 0x03803d84, 0x9deff9a0, + 0xe573f648, 0xa17e35a4, 0xe1a2738e, 0x8840a6c6, 0x238ef17c, + 0xb11ed92d, 0x480946f8 }, + { 0xfd71f119, 0x84c747a8, 0x53eb3695, 0x19e65c5e, 0x6298587a, + 0x0e2f6786, 0xab18d6f4, 0x48a48899, 0xc630b8c0, 0xa1a99024, + 0x2caaf892, 0x84975096, 0xe20fd624, 0xc8869aba, 0x6c2b7dd4, + 0x3b72b04d, 0x0992f7d0, 0xe2775eb6, 0x7d06e684, 0x0089c06e, + 0xe4bbd007, 0xcb3b4361, 0x4ba846e4, 0xa1ae666b, 0x46464d9e, + 0xc01c2eb2, 0xc1f8539f, 0xf86f2be6, 0xcf68afc7, 0x16e8e8ae, + 0xc7386902, 0x8dab61fd }, + { 0xd54d1d45, 0x42a5c903, 0xff4f9ba2, 0xacd4297e, 0x34d478b4, + 0x2d88b520, 0x08c4621a, 0x35b2ba2b, 0x34865402, 0xd3d239bb, + 0x911f32e6, 0x1de76aed, 0x3f06fdc2, 0x877f8bcf, 0x9ec51502, + 0x802714c1, 0xa590700d, 0xa10444eb, 0x31dcc957, 0x8694229f, + 0xb8169fed, 0x5ece77ab, 0x2caf080e, 0x55be8a15, 0xcbd7cef1, + 0x3eb21b14, 0x67b97ee1, 0x9def7ad1, 0x118f690c, 0xe03ca879, + 0xf99b29e7, 0x6f77e62d }, + { 0xe40bbf59, 0xa271bded, 0x6401aad6, 0x177ba453, 0x73541cd1, + 0x1755e035, 0x4b71b02f, 0x3465b466, 0xa813359f, 0x22eb7113, + 0x6f38eac7, 0x9792a8fd, 0xff3bf3b5, 0x11aa012f, 0xf85c3fbf, + 0x99aafabf, 0x06c0cc42, 0x91e0a2ef, 0x773b7b3a, 0x314d5d57, + 0xd669840a, 0xae5e2e76, 0x2e5a8be6, 0x86136073, 0xc1cf5580, + 0xee6d7578, 0x68bed102, 0x2344e00f, 0x8184f0eb, 0x799d7886, + 0xc3d2cf80, 0x63819c91 }, + { 0x7884b073, 0xca5392e1, 0xeb1267ea, 0x9ec3a1fc, 0x907038a7, + 0x3d07f5f0, 0xe4c47b70, 0xcb2ac07c, 0x1bf96b91, 0xf96664ee, + 0x2aea4fbf, 0xebf57589, 0xfade6500, 0x5aabf391, 0x171d1204, + 0xc5b3376f, 0xa0d3d81a, 0x1ff60c51, 0x976a844b, 0x10b2cfe7, + 0xbda6125a, 0xe131cc9a, 0x4ebd453e, 0xe0fc16d3, 0x504b6bc1, + 0xc0d0319a, 0x0a2f8cab, 0xe43a0be7, 0x55e49b47, 0xc80afeec, + 0x8265d7ee, 0x67d48d12 }, + { 0xea2d56d6, 0x068d59a7, 0x27480a63, 0xd71abd0e, 0xae7366cd, + 0x6bd11db0, 0x07204ebc, 0xfbb639ca, 0xf77e6293, 0x89a242e7, + 0x75ba8c3d, 0xdee7ca2b, 0x64a2f9a8, 0x472ddc3d, 0x7561a010, + 0x84229df4, 0xc5b649d4, 0x95f62c85, 0x4dc927cd, 0xfdd56b1b, + 0x5ee60596, 0xfe8bb120, 0xabf29401, 0x3efcaa50, 0x10d1c184, + 0xd4900d0f, 0x28b01df5, 0x2cf113a9, 0x1f0e43f5, 0xa3d7ebc3, + 0xe8384dc7, 0x27950e38 }, + { 0xe1d0fa79, 0xeab21ff0, 0x048b5de9, 0x4b9fd033, 0x2fe374cb, + 0x4c934689, 0x4eb21f6b, 0xbb4827fa, 0xa925e7e7, 0x46716f79, + 0x7dd4c531, 0x1442bf36, 0xd2e96ddf, 0x2073954c, 0x8502aa89, + 0x4e0141ae, 0x8eef6cc9, 0x8ee00e1a, 0x5880cdaf, 0x55ce8491, + 0x69628046, 0xff3aba5c, 0x5d15dfbf, 0x335cc4f8, 0x9f684f25, + 0xa7f0440c, 0xbb1e5bd8, 0xae80453f, 0xff2225ab, 0xa1c99813, + 0x79b25d71, 0x54ff7884 }, + { 0xde40b068, 0x27c6ee30, 0xe6f3a51e, 0x9226465b, 0xfa3b21f6, + 0xe24a4604, 0xc0418115, 0x50a5a5ad, 0x8df90d2b, 0xe3285441, + 0xdcb0c00f, 0xbb74e58f, 0x4a2c08e3, 0xc68f1b3b, 0x0ccd9ec9, + 0x339df081, 0xb786ea9f, 0x915362dc, 0xc955aead, 0x28945e31, + 0x8b6a6c6b, 0xd6a2c01d, 0x3678a427, 0x069e82dc, 0x28c9302c, + 0x17875500, 0x9fa101e6, 0x8acda965, 0xee30b286, 0x4e4e4573, + 0x3f1830fe, 0x8adbad85 }, + { 0x0969d524, 0x060ae11f, 0xf39bcc79, 0xf42fdaf7, 0x7cc1fcc2, + 0x3cec6766, 0xe2336d4f, 0x456b9cf2, 0x8e1c0f7f, 0x6aa1f5de, + 0x0984fb0e, 0xcdbc2ad2, 0x1b464b28, 0x4090cfa6, 0x1243f3ef, + 0x40d86f30, 0xcd5e87e7, 0x95b16ccc, 0x3026cd41, 0x403f168c, + 0x816c0730, 0xdbe386cb, 0x58407a1d, 0x14eb86f3, 0x1717e1af, + 0xf588b4f8, 0x66cbc96c, 0xb75c41a6, 0x027e71c1, 0xf342c1aa, + 0xc0945e5f, 0x73930036 }, + { 0x22cdaf42, 0x954f757d, 0xf4181aab, 0x788b591d, 0xf5514f25, + 0x8b986819, 0xf18fd5bc, 0x69642e08, 0x022ceb91, 0x92b305d1, + 0x6a4f6985, 0x1715903e, 0x61179cae, 0x4bd7d69d, 0xd29c01aa, + 0xdacdfd5d, 0xd91108cc, 0x705ddd5a, 0x64ac8f15, 0x434ac7b1, + 0xb524632f, 0x61a514e1, 0x731fc447, 0x45b9e61b, 0xe0961b31, + 0xcf561348, 0x73eaf223, 0x9c28a967, 0xaa7c99d3, 0x5bd10182, + 0xe42965e2, 0x8bc6ec4a }, + { 0xe7f2a32b, 0xd096e5c0, 0x09388a30, 0xff54800c, 0x401e360c, + 0x06fe437c, 0xbb6054a6, 0x6655fc9c, 0x8457aa6e, 0x510e1860, + 0x2b29b2b7, 0xa0acfca2, 0x51b7da61, 0x732483e3, 0x6be6c8ca, + 0xe31471ee, 0x8b65c9a1, 0xe565431c, 0x48d65cbb, 0xfc9ac3b9, + 0xae9b2aa8, 0xd308fc21, 0xaa60aa6a, 0xd6a7df0d, 0x982fc0d4, + 0x2844d96a, 0x5847a4d7, 0xab012c2c, 0xdceb8955, 0x2b3c8f71, + 0xbe9c7e15, 0x8e85437d }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 32]; + sp_digit tx[2 * 32]; + sp_digit ty[2 * 32]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 32 * 2; + ty = td + 5 * 32 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 32); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_32(tx, ty, t); + sp_1024_proj_mul_qx1_32(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_32(tx, tx, t); + sp_1024_mont_mul_32(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_32(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = px + py */ + sp_1024_mont_add_32(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_32(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_32(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_32(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_32(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_32(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_32(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_32(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + sp_1024_mont_inv_32(t1, p->z, t2); + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 32); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 32; + sp_digit* pz2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* l = t + 8 * 32; + sp_digit* ty = t + 10 * 32; + + /* v = v^2 */ + sp_1024_proj_sqr_32(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_32(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_32(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_32(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_32(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_32(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_32(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_32(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_32(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* h = t + 8 * 32; + sp_digit* r = t + 10 * 32; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_32(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_32(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_32(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_32(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_32(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_32(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_32(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_32(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_32(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_32(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_32(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_32(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit qx_px[2 * 32]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_32(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + qx_px = td + 8 * 32 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + + sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* h = t + 8 * 32; + sp_digit* r = t + 10 * 32; + + /* h = p.z^2 */ + sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_32(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_32(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_32(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_32(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_32(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_32(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 32; + sp_digit* pz2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* l = t + 8 * 32; + sp_digit* ty = t + 10 * 32; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_32(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_32(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_32(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_32(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_32(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_32(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[64]; + sp_digit (*pre_vy)[64]; + sp_digit (*pre_nvy)[64]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit pre_vx[16][64]; + sp_digit pre_vy[16][64]; + sp_digit pre_nvy[16][64]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_32(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2); + pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2); + pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2); + pre_p = (sp_point_1024*)(td + 56 * 32 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32); + sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32); + sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 32; + sp_digit* t2 = t + 2 * 2 * 32; + sp_digit* l = t + 4 * 2 * 32; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_32(l, py, p1024_mod); + sp_1024_mont_inv_32(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_32(t2, t1, p1024_mod); + sp_1024_mont_add_32(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_32(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 32); + XMEMCPY(cr, t2, sizeof(sp_digit) * 32); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 32; + sp_digit* c = t + 2 * 2 * 32; + sp_digit* l = t + 4 * 2 * 32; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_32(l, cx, px, p1024_mod); + sp_1024_mont_inv_32(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_32(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_32(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 32); + XMEMCPY(cr, c, sizeof(sp_digit) * 32); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 32; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_32(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_32(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 32]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 32 * 2); +#endif + + sp_1024_point_from_ecc_point_32(p, pm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_32(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_32(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_32(c, c, t); + sp_1024_mont_map_32(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t); + sp_1024_mont_map_32(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_32(c, c, neg, t); + sp_1024_mont_map_32(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_32(c, c, t); + sp_1024_mont_map_32(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(neg, 1, NULL); + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[64]; + sp_digit (*pre_vy)[64]; + sp_digit (*pre_nvy)[64]; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit pre_vx[16][64]; + sp_digit pre_vy[16][64]; + sp_digit pre_nvy[16][64]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2); + pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2); + pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32); + sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32); + sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_32(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] | + a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] | + a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_32(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[32 * 4]; +#endif + sp_digit* t2 = NULL; + int32_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 32; + + sp_1024_sqr_32(t1, point->y); + (void)sp_1024_mod_32(t1, t1, p1024_mod); + sp_1024_sqr_32(t2, point->x); + (void)sp_1024_mod_32(t2, t2, p1024_mod); + sp_1024_mul_32(t2, t2, point->x); + (void)sp_1024_mod_32(t2, t2, p1024_mod); + (void)sp_1024_sub_32(t2, p1024_mod, t2); + sp_1024_mont_add_32(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_32(t1, p1024_mod); + sp_1024_cond_sub_32(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(t1); + if (!sp_1024_iszero_32(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 32, pX); + sp_1024_from_mp(pub->y, 32, pY); + sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_32(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[32]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 32, pX); + sp_1024_from_mp(pub->y, 32, pY); + sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 32, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_32(pub->x) != 0) && + (sp_1024_iszero_32(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_32(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) || + (sp_1024_iszero_32(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_32(p->x, pub->x) != 0) || + (sp_1024_cmp_32(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* WOLFSSL_SP_ARM32_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c index f35d68429..c5b80e9f2 100644 --- a/wolfcrypt/src/sp_arm64.c +++ b/wolfcrypt/src/sp_arm64.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,7 +58,8 @@ */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j; + int i; + int j; byte* d; for (i = n - 1,j = 0; i >= 7; i -= 8) { @@ -111,7 +112,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -145,7 +147,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -184,7 +188,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_2048_to_bin(sp_digit* r, byte* a) { - int i, j; + int i; + int j; for (i = 31, j = 0; i >= 0; i--) { a[j++] = r[i] >> 56; @@ -207,422 +212,412 @@ static void sp_2048_to_bin(sp_digit* r, byte* a) */ static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) { - sp_digit tmp[8]; - __asm__ __volatile__ ( - "ldp x9, x10, [%[a], 0]\n\t" - "ldp x11, x12, [%[a], 16]\n\t" - "ldp x13, x14, [%[a], 32]\n\t" - "ldp x15, x16, [%[a], 48]\n\t" - "ldp x17, x19, [%[b], 0]\n\t" - "ldp x20, x21, [%[b], 16]\n\t" - "ldp x22, x23, [%[b], 32]\n\t" - "ldp x24, x25, [%[b], 48]\n\t" + "ldp x8, x9, [%[a], 0]\n\t" + "ldp x10, x11, [%[a], 16]\n\t" + "ldp x12, x13, [%[a], 32]\n\t" + "ldp x14, x15, [%[a], 48]\n\t" + "ldp x16, x17, [%[b], 0]\n\t" + "ldp x19, x20, [%[b], 16]\n\t" + "ldp x21, x22, [%[b], 32]\n\t" + "ldp x23, x24, [%[b], 48]\n\t" "# A[0] * B[0]\n\t" - "mul x4, x9, x17\n\t" - "umulh x5, x9, x17\n\t" - "str x4, [%[tmp]]\n\t" + "mul x3, x8, x16\n\t" + "umulh x4, x8, x16\n\t" + "str x3, [%[r]]\n\t" "# A[0] * B[1]\n\t" - "mul x7, x9, x19\n\t" - "umulh x8, x9, x19\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x8, x17\n\t" + "umulh x7, x8, x17\n\t" + "adds x4, x4, x6\n\t" "# A[1] * B[0]\n\t" - "mul x7, x10, x17\n\t" - "adc x6, xzr, x8\n\t" - "umulh x8, x10, x17\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[tmp], 8]\n\t" - "adc x4, xzr, xzr\n\t" + "mul x6, x9, x16\n\t" + "adc x5, xzr, x7\n\t" + "umulh x7, x9, x16\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 8]\n\t" + "adc x3, xzr, xzr\n\t" "# A[0] * B[2]\n\t" - "mul x7, x9, x20\n\t" - "umulh x8, x9, x20\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x8, x19\n\t" + "umulh x7, x8, x19\n\t" + "adds x5, x5, x6\n\t" "# A[1] * B[1]\n\t" - "mul x7, x10, x19\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x10, x19\n\t" - "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x9, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x9, x17\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[2] * B[0]\n\t" - "mul x7, x11, x17\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x11, x17\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[tmp], 16]\n\t" - "adc x5, x5, xzr\n\t" + "mul x6, x10, x16\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x16\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 16]\n\t" + "adc x4, x4, xzr\n\t" "# A[0] * B[3]\n\t" - "mul x7, x9, x21\n\t" - "umulh x8, x9, x21\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x8, x20\n\t" + "umulh x7, x8, x20\n\t" + "adds x3, x3, x6\n\t" "# A[1] * B[2]\n\t" - "mul x7, x10, x20\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x10, x20\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x9, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x9, x19\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[2] * B[1]\n\t" - "mul x7, x11, x19\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x11, x19\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x10, x17\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x10, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[3] * B[0]\n\t" - "mul x7, x12, x17\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x12, x17\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[tmp], 24]\n\t" - "adc x6, x6, xzr\n\t" + "mul x6, x11, x16\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x16\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 24]\n\t" + "adc x5, x5, xzr\n\t" "# A[0] * B[4]\n\t" - "mul x7, x9, x22\n\t" - "umulh x8, x9, x22\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x8, x21\n\t" + "umulh x7, x8, x21\n\t" + "adds x4, x4, x6\n\t" "# A[1] * B[3]\n\t" - "mul x7, x10, x21\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x10, x21\n\t" - "adc x4, xzr, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x9, x20\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x9, x20\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[2] * B[2]\n\t" - "mul x7, x11, x20\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x11, x20\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x10, x19\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x10, x19\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[3] * B[1]\n\t" - "mul x7, x12, x19\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x12, x19\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x11, x17\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x11, x17\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[4] * B[0]\n\t" - "mul x7, x13, x17\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x13, x17\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[tmp], 32]\n\t" - "adc x4, x4, xzr\n\t" + "mul x6, x12, x16\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x16\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 32]\n\t" + "adc x3, x3, xzr\n\t" "# A[0] * B[5]\n\t" - "mul x7, x9, x23\n\t" - "umulh x8, x9, x23\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x8, x22\n\t" + "umulh x7, x8, x22\n\t" + "adds x5, x5, x6\n\t" "# A[1] * B[4]\n\t" - "mul x7, x10, x22\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x10, x22\n\t" - "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x9, x21\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x9, x21\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[2] * B[3]\n\t" - "mul x7, x11, x21\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x11, x21\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x10, x20\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[3] * B[2]\n\t" - "mul x7, x12, x20\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x12, x20\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x11, x19\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x11, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[4] * B[1]\n\t" - "mul x7, x13, x19\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x13, x19\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x12, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x12, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[5] * B[0]\n\t" - "mul x7, x14, x17\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x14, x17\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[tmp], 40]\n\t" - "adc x5, x5, xzr\n\t" + "mul x6, x13, x16\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x16\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 40]\n\t" + "adc x4, x4, xzr\n\t" "# A[0] * B[6]\n\t" - "mul x7, x9, x24\n\t" - "umulh x8, x9, x24\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x8, x23\n\t" + "umulh x7, x8, x23\n\t" + "adds x3, x3, x6\n\t" "# A[1] * B[5]\n\t" - "mul x7, x10, x23\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x10, x23\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x9, x22\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x9, x22\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[2] * B[4]\n\t" - "mul x7, x11, x22\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x11, x22\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x10, x21\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x10, x21\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[3] * B[3]\n\t" - "mul x7, x12, x21\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x12, x21\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x11, x20\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x20\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[4] * B[2]\n\t" - "mul x7, x13, x20\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x13, x20\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x12, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x12, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[5] * B[1]\n\t" - "mul x7, x14, x19\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x14, x19\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x13, x17\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x13, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[6] * B[0]\n\t" - "mul x7, x15, x17\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x15, x17\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[tmp], 48]\n\t" - "adc x6, x6, xzr\n\t" + "mul x6, x14, x16\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x14, x16\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 48]\n\t" + "adc x5, x5, xzr\n\t" "# A[0] * B[7]\n\t" - "mul x7, x9, x25\n\t" - "umulh x8, x9, x25\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x8, x24\n\t" + "umulh x7, x8, x24\n\t" + "adds x4, x4, x6\n\t" "# A[1] * B[6]\n\t" - "mul x7, x10, x24\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x10, x24\n\t" - "adc x4, xzr, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x9, x23\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x9, x23\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[2] * B[5]\n\t" - "mul x7, x11, x23\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x11, x23\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x10, x22\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x10, x22\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[3] * B[4]\n\t" - "mul x7, x12, x22\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x12, x22\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x11, x21\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x11, x21\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[4] * B[3]\n\t" - "mul x7, x13, x21\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x13, x21\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x12, x20\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x20\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[5] * B[2]\n\t" - "mul x7, x14, x20\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x14, x20\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x13, x19\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x13, x19\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[6] * B[1]\n\t" - "mul x7, x15, x19\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x15, x19\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x14, x17\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x14, x17\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[7] * B[0]\n\t" - "mul x7, x16, x17\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x16, x17\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[tmp], 56]\n\t" - "adc x4, x4, xzr\n\t" + "mul x6, x15, x16\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x15, x16\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 56]\n\t" + "adc x3, x3, xzr\n\t" "# A[1] * B[7]\n\t" - "mul x7, x10, x25\n\t" - "umulh x8, x10, x25\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x9, x24\n\t" + "umulh x7, x9, x24\n\t" + "adds x5, x5, x6\n\t" "# A[2] * B[6]\n\t" - "mul x7, x11, x24\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x11, x24\n\t" - "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x10, x23\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x23\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[3] * B[5]\n\t" - "mul x7, x12, x23\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x12, x23\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x11, x22\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x11, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[4] * B[4]\n\t" - "mul x7, x13, x22\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x13, x22\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x12, x21\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x12, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[5] * B[3]\n\t" - "mul x7, x14, x21\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x14, x21\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x13, x20\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[6] * B[2]\n\t" - "mul x7, x15, x20\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x15, x20\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x14, x19\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x14, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[7] * B[1]\n\t" - "mul x7, x16, x19\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x16, x19\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[r], 64]\n\t" - "adc x5, x5, xzr\n\t" + "mul x6, x15, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x15, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 64]\n\t" + "adc x4, x4, xzr\n\t" "# A[2] * B[7]\n\t" - "mul x7, x11, x25\n\t" - "umulh x8, x11, x25\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x10, x24\n\t" + "umulh x7, x10, x24\n\t" + "adds x3, x3, x6\n\t" "# A[3] * B[6]\n\t" - "mul x7, x12, x24\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x12, x24\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[4] * B[5]\n\t" - "mul x7, x13, x23\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x13, x23\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[5] * B[4]\n\t" - "mul x7, x14, x22\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x14, x22\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[6] * B[3]\n\t" - "mul x7, x15, x21\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x15, x21\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[7] * B[2]\n\t" - "mul x7, x16, x20\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x16, x20\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[r], 72]\n\t" - "adc x6, x6, xzr\n\t" - "# A[3] * B[7]\n\t" - "mul x7, x12, x25\n\t" - "umulh x8, x12, x25\n\t" - "adds x5, x5, x7\n\t" - "# A[4] * B[6]\n\t" - "mul x7, x13, x24\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x13, x24\n\t" - "adc x4, xzr, xzr\n\t" - "adds x5, x5, x7\n\t" - "# A[5] * B[5]\n\t" - "mul x7, x14, x23\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x14, x23\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "# A[6] * B[4]\n\t" - "mul x7, x15, x22\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x15, x22\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "# A[7] * B[3]\n\t" - "mul x7, x16, x21\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x16, x21\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[r], 80]\n\t" - "adc x4, x4, xzr\n\t" - "# A[4] * B[7]\n\t" - "mul x7, x13, x25\n\t" - "umulh x8, x13, x25\n\t" - "adds x6, x6, x7\n\t" - "# A[5] * B[6]\n\t" - "mul x7, x14, x24\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x14, x24\n\t" + "mul x6, x11, x23\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x23\n\t" "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" - "# A[6] * B[5]\n\t" - "mul x7, x15, x23\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x15, x23\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B[5]\n\t" + "mul x6, x12, x22\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x12, x22\n\t" "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "# A[7] * B[4]\n\t" - "mul x7, x16, x22\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x16, x22\n\t" + "adds x3, x3, x6\n\t" + "# A[5] * B[4]\n\t" + "mul x6, x13, x21\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x13, x21\n\t" "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[r], 88]\n\t" + "adds x3, x3, x6\n\t" + "# A[6] * B[3]\n\t" + "mul x6, x14, x20\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x14, x20\n\t" "adc x5, x5, xzr\n\t" - "# A[5] * B[7]\n\t" - "mul x7, x14, x25\n\t" - "umulh x8, x14, x25\n\t" - "adds x4, x4, x7\n\t" - "# A[6] * B[6]\n\t" - "mul x7, x15, x24\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x15, x24\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[7] * B[5]\n\t" - "mul x7, x16, x23\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x16, x23\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[r], 96]\n\t" - "adc x6, x6, xzr\n\t" - "# A[6] * B[7]\n\t" - "mul x7, x15, x25\n\t" - "umulh x8, x15, x25\n\t" - "adds x5, x5, x7\n\t" - "# A[7] * B[6]\n\t" - "mul x7, x16, x24\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x16, x24\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B[2]\n\t" + "mul x6, x15, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x15, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 72]\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[7]\n\t" + "mul x6, x11, x24\n\t" + "umulh x7, x11, x24\n\t" + "adds x4, x4, x6\n\t" + "# A[4] * B[6]\n\t" + "mul x6, x12, x23\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x23\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B[5]\n\t" + "mul x6, x13, x22\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x13, x22\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[6] * B[4]\n\t" + "mul x6, x14, x21\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x14, x21\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[7] * B[3]\n\t" + "mul x6, x15, x20\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x15, x20\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 80]\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[7]\n\t" + "mul x6, x12, x24\n\t" + "umulh x7, x12, x24\n\t" + "adds x5, x5, x6\n\t" + "# A[5] * B[6]\n\t" + "mul x6, x13, x23\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x23\n\t" "adc x4, xzr, xzr\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[r], 104]\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B[5]\n\t" + "mul x6, x14, x22\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x14, x22\n\t" "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[7] * B[4]\n\t" + "mul x6, x15, x21\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x15, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 88]\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[7]\n\t" + "mul x6, x13, x24\n\t" + "umulh x7, x13, x24\n\t" + "adds x3, x3, x6\n\t" + "# A[6] * B[6]\n\t" + "mul x6, x14, x23\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x14, x23\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B[5]\n\t" + "mul x6, x15, x22\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x15, x22\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 96]\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[7]\n\t" + "mul x6, x14, x24\n\t" + "umulh x7, x14, x24\n\t" + "adds x4, x4, x6\n\t" + "# A[7] * B[6]\n\t" + "mul x6, x15, x23\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x15, x23\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 104]\n\t" + "adc x3, x3, xzr\n\t" "# A[7] * B[7]\n\t" - "mul x7, x16, x25\n\t" - "umulh x8, x16, x25\n\t" - "adds x6, x6, x7\n\t" - "adc x4, x4, x8\n\t" - "stp x6, x4, [%[r], 112]\n\t" - "ldp x9, x10, [%[tmp], 0]\n\t" - "ldp x11, x12, [%[tmp], 16]\n\t" - "ldp x13, x14, [%[tmp], 32]\n\t" - "ldp x15, x16, [%[tmp], 48]\n\t" - "stp x9, x10, [%[r], 0]\n\t" - "stp x11, x12, [%[r], 16]\n\t" - "stp x13, x14, [%[r], 32]\n\t" - "stp x15, x16, [%[r], 48]\n\t" + "mul x6, x15, x24\n\t" + "umulh x7, x15, x24\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "stp x5, x3, [%[r], 112]\n\t" : - : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) - : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25" + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24" ); } @@ -1208,7 +1203,6 @@ SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) u += sp_2048_add_16(r + 8, r + 8, z1); u += sp_2048_add_8(r + 16, r + 16, z2); sp_2048_add_zero_8(r + 24, z2 + 8, u); - } /* Sub b from a into a. (a -= b) @@ -1629,7 +1623,6 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) u += sp_2048_add_32(r + 16, r + 16, z1); u += sp_2048_add_16(r + 32, r + 32, z2); sp_2048_add_zero_16(r + 48, z2 + 16, u); - } #endif /* !WOLFSSL_SP_SMALL */ @@ -2033,7 +2026,7 @@ static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -2042,7 +2035,8 @@ static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -2052,7 +2046,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**64 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -2495,7 +2489,6 @@ static sp_digit sp_2048_cond_sub_16(sp_digit* r, const sp_digit* a, const sp_dig SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, sp_digit mp) { - sp_digit ca = 0; __asm__ __volatile__ ( "ldp x14, x15, [%[m], 0]\n\t" @@ -2505,6 +2498,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, "ldp x23, x24, [%[m], 64]\n\t" "ldp x25, x26, [%[m], 80]\n\t" "ldp x27, x28, [%[m], 96]\n\t" + "mov x3, xzr\n\t" "# i = 16\n\t" "mov x4, 16\n\t" "ldp x12, x13, [%[a], 0]\n\t" @@ -2645,25 +2639,78 @@ SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, "adc x6, x6, xzr\n\t" "umulh x8, x8, x9\n\t" "adds x6, x6, x7\n\t" - "adcs x8, x8, %[ca]\n\t" + "adcs x8, x8, x3\n\t" "str x11, [%[a], 112]\n\t" - "cset %[ca], cs\n\t" + "cset x3, cs\n\t" "adds x10, x10, x6\n\t" "ldr x11, [%[a], 128]\n\t" "str x10, [%[a], 120]\n\t" "adcs x11, x11, x8\n\t" "str x11, [%[a], 128]\n\t" - "adc %[ca], %[ca], xzr\n\t" + "adc x3, x3, xzr\n\t" "subs x4, x4, 1\n\t" "add %[a], %[a], 8\n\t" "bne 1b\n\t" - "stp x12, x13, [%[a], 0]\n\t" - : [ca] "+r" (ca), [a] "+r" (a) + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "neg x3, x3\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 128\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "ldp x11, x10, [x9, 48]\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "and x21, x21, x3\n\t" + "sbcs x13, x13, x20\n\t" + "and x22, x22, x3\n\t" + "sbcs x11, x11, x21\n\t" + "stp x12, x13, [%[a], 32]\n\t" + "sbcs x10, x10, x22\n\t" + "stp x11, x10, [%[a], 48]\n\t" + "ldp x12, x13, [x9, 64]\n\t" + "and x23, x23, x3\n\t" + "ldp x11, x10, [x9, 80]\n\t" + "and x24, x24, x3\n\t" + "sbcs x12, x12, x23\n\t" + "and x25, x25, x3\n\t" + "sbcs x13, x13, x24\n\t" + "and x26, x26, x3\n\t" + "sbcs x11, x11, x25\n\t" + "stp x12, x13, [%[a], 64]\n\t" + "sbcs x10, x10, x26\n\t" + "stp x11, x10, [%[a], 80]\n\t" + "ldp x7, x8, [%[m], 112]\n\t" + "ldp x12, x13, [x9, 96]\n\t" + "and x27, x27, x3\n\t" + "ldp x11, x10, [x9, 112]\n\t" + "and x28, x28, x3\n\t" + "sbcs x12, x12, x27\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x28\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 96]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 112]\n\t" + : [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca); } /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -2675,8 +2722,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_16(r, a, b); sp_2048_mont_reduce_16(r, m, mp); @@ -2689,8 +2736,8 @@ static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_16(r, a); sp_2048_mont_reduce_16(r, m, mp); @@ -3156,35 +3203,31 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 32]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 32), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 32; -#else - t[i] = &td[i * 32]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3232,34 +3275,34 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 16); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 60); + y = (byte)(n >> 60); n <<= 4; c = 60; } else if (c < 4) { - y = (int)(n >> 60); + y = (byte)(n >> 60); n = e[i--]; c = 4 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 60) & 0xf); + y = (byte)((n >> 60) & 0xf); n <<= 4; c -= 4; } @@ -3280,9 +3323,8 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -3301,35 +3343,31 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 32]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 32), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 32; -#else - t[i] = &td[i * 32]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3393,34 +3431,34 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 16); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else if (c < 5) { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } @@ -3442,16 +3480,15 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -3468,7 +3505,7 @@ static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m) sp_2048_sub_in_place_32(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -3636,7 +3673,6 @@ static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_dig SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp) { - sp_digit ca = 0; __asm__ __volatile__ ( "ldp x14, x15, [%[m], 0]\n\t" @@ -3646,6 +3682,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "ldp x23, x24, [%[m], 64]\n\t" "ldp x25, x26, [%[m], 80]\n\t" "ldp x27, x28, [%[m], 96]\n\t" + "mov x3, xzr\n\t" "# i = 32\n\t" "mov x4, 32\n\t" "ldp x12, x13, [%[a], 0]\n\t" @@ -3946,25 +3983,134 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, "adc x6, x6, xzr\n\t" "umulh x8, x8, x9\n\t" "adds x6, x6, x7\n\t" - "adcs x8, x8, %[ca]\n\t" + "adcs x8, x8, x3\n\t" "str x11, [%[a], 240]\n\t" - "cset %[ca], cs\n\t" + "cset x3, cs\n\t" "adds x10, x10, x6\n\t" "ldr x11, [%[a], 256]\n\t" "str x10, [%[a], 248]\n\t" "adcs x11, x11, x8\n\t" "str x11, [%[a], 256]\n\t" - "adc %[ca], %[ca], xzr\n\t" + "adc x3, x3, xzr\n\t" "subs x4, x4, 1\n\t" "add %[a], %[a], 8\n\t" "bne 1b\n\t" - "stp x12, x13, [%[a], 0]\n\t" - : [ca] "+r" (ca), [a] "+r" (a) + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "neg x3, x3\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 256\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "ldp x11, x10, [x9, 48]\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "and x21, x21, x3\n\t" + "sbcs x13, x13, x20\n\t" + "and x22, x22, x3\n\t" + "sbcs x11, x11, x21\n\t" + "stp x12, x13, [%[a], 32]\n\t" + "sbcs x10, x10, x22\n\t" + "stp x11, x10, [%[a], 48]\n\t" + "ldp x12, x13, [x9, 64]\n\t" + "and x23, x23, x3\n\t" + "ldp x11, x10, [x9, 80]\n\t" + "and x24, x24, x3\n\t" + "sbcs x12, x12, x23\n\t" + "and x25, x25, x3\n\t" + "sbcs x13, x13, x24\n\t" + "and x26, x26, x3\n\t" + "sbcs x11, x11, x25\n\t" + "stp x12, x13, [%[a], 64]\n\t" + "sbcs x10, x10, x26\n\t" + "stp x11, x10, [%[a], 80]\n\t" + "ldp x7, x8, [%[m], 112]\n\t" + "ldp x12, x13, [x9, 96]\n\t" + "and x27, x27, x3\n\t" + "ldp x11, x10, [x9, 112]\n\t" + "and x28, x28, x3\n\t" + "sbcs x12, x12, x27\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x28\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 96]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 112]\n\t" + "ldp x5, x6, [%[m], 128]\n\t" + "ldp x7, x8, [%[m], 144]\n\t" + "ldp x12, x13, [x9, 128]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 144]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 128]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 144]\n\t" + "ldp x5, x6, [%[m], 160]\n\t" + "ldp x7, x8, [%[m], 176]\n\t" + "ldp x12, x13, [x9, 160]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 176]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 160]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 176]\n\t" + "ldp x5, x6, [%[m], 192]\n\t" + "ldp x7, x8, [%[m], 208]\n\t" + "ldp x12, x13, [x9, 192]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 208]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 192]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 208]\n\t" + "ldp x5, x6, [%[m], 224]\n\t" + "ldp x7, x8, [%[m], 240]\n\t" + "ldp x12, x13, [x9, 224]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 240]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 224]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 240]\n\t" + : [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); } /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -3976,8 +4122,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_32(r, a, b); sp_2048_mont_reduce_32(r, m, mp); @@ -3990,8 +4136,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_32(r, a); sp_2048_mont_reduce_32(r, m, mp); @@ -4621,35 +4767,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 64]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -4697,34 +4839,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 60); + y = (byte)(n >> 60); n <<= 4; c = 60; } else if (c < 4) { - y = (int)(n >> 60); + y = (byte)(n >> 60); n = e[i--]; c = 4 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 60) & 0xf); + y = (byte)((n >> 60) & 0xf); n <<= 4; c -= 4; } @@ -4745,9 +4887,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4766,35 +4907,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 64]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -4858,34 +4995,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else if (c < 5) { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } @@ -4907,9 +5044,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4930,19 +5066,18 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[64], m[32], r[64]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[32 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 256) { @@ -4956,22 +5091,18 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 32 * 2; - m = r + 32 * 2; - } #endif if (err == MP_OKAY) { + r = a + 32 * 2; + m = r + 32 * 2; ah = a + 32; sp_2048_from_bin(ah, 32, in, inLen); @@ -5044,10 +5175,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -5173,13 +5303,17 @@ static sp_digit sp_2048_cond_add_16(sp_digit* r, const sp_digit* a, const sp_dig * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[32 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -5208,13 +5342,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 32; m = a + 64; @@ -5225,31 +5361,36 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_2048_from_mp(m, 32, mm); err = sp_2048_mod_exp_32(r, a, d, 2048, m, 0); } + if (err == MP_OKAY) { sp_2048_to_bin(r, out); *outLen = 256; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 32); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 32); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[32 * 2]; - sp_digit p[16], q[16], dp[16]; - sp_digit tmpa[32], tmpb[32]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[16 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -5269,31 +5410,23 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 32 * 2; q = p + 16; qi = dq = dp = q + 16; tmpa = qi + 16; tmpb = tmpa + 32; - - r = t + 32; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_2048_from_bin(a, 32, in, inLen); sp_2048_from_mp(p, 16, pm); sp_2048_from_mp(q, 16, qm); @@ -5325,18 +5458,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 16 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -5360,17 +5490,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 32; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 32; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -5383,14 +5515,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 32; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -5417,10 +5551,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -5673,34 +5810,31 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[97]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 97, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 64; -#else - tmp = &td[64]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_32(norm, m); @@ -5718,34 +5852,34 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } - sp_2048_lshift_32(r, norm, (byte)y); + sp_2048_lshift_32(r, norm, y); for (; i>=0 || c>=6; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -5757,7 +5891,7 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, sp_2048_mont_sqr_32(r, r, m, mp); sp_2048_mont_sqr_32(r, r, m, mp); - sp_2048_lshift_32(r, r, (byte)y); + sp_2048_lshift_32(r, r, y); sp_2048_mul_d_32(tmp, norm, r[32]); r[32] = 0; o = sp_2048_add_32(r, r, tmp); @@ -5772,9 +5906,8 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -5793,11 +5926,13 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; word32 i; @@ -5832,6 +5967,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -5853,10 +5989,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[32], e[16], m[16]; + sp_digit b[32]; + sp_digit e[16]; + sp_digit m[16]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -5893,7 +6032,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -5907,7 +6046,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j; + int i; + int j; byte* d; for (i = n - 1,j = 0; i >= 7; i -= 8) { @@ -5960,7 +6100,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -5994,7 +6135,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -6033,7 +6176,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_3072_to_bin(sp_digit* r, byte* a) { - int i, j; + int i; + int j; for (i = 47, j = 0; i >= 0; i--) { a[j++] = r[i] >> 56; @@ -8130,7 +8274,6 @@ SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) u += sp_3072_add_24(r + 12, r + 12, z1); u += sp_3072_add_12(r + 24, r + 24, z2); sp_3072_add_zero_12(r + 36, z2 + 12, u); - } /* Sub b from a into a. (a -= b) @@ -8665,7 +8808,6 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) u += sp_3072_add_48(r + 24, r + 24, z1); u += sp_3072_add_24(r + 48, r + 48, z2); sp_3072_add_zero_24(r + 72, z2 + 24, u); - } #endif /* !WOLFSSL_SP_SMALL */ @@ -9069,7 +9211,7 @@ static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -9078,7 +9220,8 @@ static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -9088,7 +9231,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**64 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -9695,7 +9838,6 @@ static sp_digit sp_3072_cond_sub_24(sp_digit* r, const sp_digit* a, const sp_dig SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, sp_digit mp) { - sp_digit ca = 0; __asm__ __volatile__ ( "ldp x14, x15, [%[m], 0]\n\t" @@ -9705,6 +9847,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, "ldp x23, x24, [%[m], 64]\n\t" "ldp x25, x26, [%[m], 80]\n\t" "ldp x27, x28, [%[m], 96]\n\t" + "mov x3, xzr\n\t" "# i = 24\n\t" "mov x4, 24\n\t" "ldp x12, x13, [%[a], 0]\n\t" @@ -9925,25 +10068,106 @@ SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, "adc x6, x6, xzr\n\t" "umulh x8, x8, x9\n\t" "adds x6, x6, x7\n\t" - "adcs x8, x8, %[ca]\n\t" + "adcs x8, x8, x3\n\t" "str x11, [%[a], 176]\n\t" - "cset %[ca], cs\n\t" + "cset x3, cs\n\t" "adds x10, x10, x6\n\t" "ldr x11, [%[a], 192]\n\t" "str x10, [%[a], 184]\n\t" "adcs x11, x11, x8\n\t" "str x11, [%[a], 192]\n\t" - "adc %[ca], %[ca], xzr\n\t" + "adc x3, x3, xzr\n\t" "subs x4, x4, 1\n\t" "add %[a], %[a], 8\n\t" "bne 1b\n\t" - "stp x12, x13, [%[a], 0]\n\t" - : [ca] "+r" (ca), [a] "+r" (a) + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "neg x3, x3\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 192\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "ldp x11, x10, [x9, 48]\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "and x21, x21, x3\n\t" + "sbcs x13, x13, x20\n\t" + "and x22, x22, x3\n\t" + "sbcs x11, x11, x21\n\t" + "stp x12, x13, [%[a], 32]\n\t" + "sbcs x10, x10, x22\n\t" + "stp x11, x10, [%[a], 48]\n\t" + "ldp x12, x13, [x9, 64]\n\t" + "and x23, x23, x3\n\t" + "ldp x11, x10, [x9, 80]\n\t" + "and x24, x24, x3\n\t" + "sbcs x12, x12, x23\n\t" + "and x25, x25, x3\n\t" + "sbcs x13, x13, x24\n\t" + "and x26, x26, x3\n\t" + "sbcs x11, x11, x25\n\t" + "stp x12, x13, [%[a], 64]\n\t" + "sbcs x10, x10, x26\n\t" + "stp x11, x10, [%[a], 80]\n\t" + "ldp x7, x8, [%[m], 112]\n\t" + "ldp x12, x13, [x9, 96]\n\t" + "and x27, x27, x3\n\t" + "ldp x11, x10, [x9, 112]\n\t" + "and x28, x28, x3\n\t" + "sbcs x12, x12, x27\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x28\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 96]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 112]\n\t" + "ldp x5, x6, [%[m], 128]\n\t" + "ldp x7, x8, [%[m], 144]\n\t" + "ldp x12, x13, [x9, 128]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 144]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 128]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 144]\n\t" + "ldp x5, x6, [%[m], 160]\n\t" + "ldp x7, x8, [%[m], 176]\n\t" + "ldp x12, x13, [x9, 160]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 176]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 160]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 176]\n\t" + : [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca); } /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -9955,8 +10179,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_24(r, a, b); sp_3072_mont_reduce_24(r, m, mp); @@ -9969,8 +10193,8 @@ static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_24(r, a); sp_3072_mont_reduce_24(r, m, mp); @@ -10560,35 +10784,31 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 48]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 48), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 48; -#else - t[i] = &td[i * 48]; -#endif } sp_3072_mont_setup(m, &mp); @@ -10636,34 +10856,34 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 24); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 60); + y = (byte)(n >> 60); n <<= 4; c = 60; } else if (c < 4) { - y = (int)(n >> 60); + y = (byte)(n >> 60); n = e[i--]; c = 4 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 60) & 0xf); + y = (byte)((n >> 60) & 0xf); n <<= 4; c -= 4; } @@ -10684,9 +10904,8 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -10705,35 +10924,31 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 48]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 48), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 48; -#else - t[i] = &td[i * 48]; -#endif } sp_3072_mont_setup(m, &mp); @@ -10797,34 +11012,34 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 24); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else if (c < 5) { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } @@ -10846,16 +11061,15 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -10872,7 +11086,7 @@ static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m) sp_3072_sub_in_place_48(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -11096,7 +11310,6 @@ static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_dig SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp) { - sp_digit ca = 0; __asm__ __volatile__ ( "ldp x14, x15, [%[m], 0]\n\t" @@ -11106,6 +11319,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "ldp x23, x24, [%[m], 64]\n\t" "ldp x25, x26, [%[m], 80]\n\t" "ldp x27, x28, [%[m], 96]\n\t" + "mov x3, xzr\n\t" "# i = 48\n\t" "mov x4, 48\n\t" "ldp x12, x13, [%[a], 0]\n\t" @@ -11566,25 +11780,190 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, "adc x6, x6, xzr\n\t" "umulh x8, x8, x9\n\t" "adds x6, x6, x7\n\t" - "adcs x8, x8, %[ca]\n\t" + "adcs x8, x8, x3\n\t" "str x11, [%[a], 368]\n\t" - "cset %[ca], cs\n\t" + "cset x3, cs\n\t" "adds x10, x10, x6\n\t" "ldr x11, [%[a], 384]\n\t" "str x10, [%[a], 376]\n\t" "adcs x11, x11, x8\n\t" "str x11, [%[a], 384]\n\t" - "adc %[ca], %[ca], xzr\n\t" + "adc x3, x3, xzr\n\t" "subs x4, x4, 1\n\t" "add %[a], %[a], 8\n\t" "bne 1b\n\t" - "stp x12, x13, [%[a], 0]\n\t" - : [ca] "+r" (ca), [a] "+r" (a) + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "neg x3, x3\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 384\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "ldp x11, x10, [x9, 48]\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "and x21, x21, x3\n\t" + "sbcs x13, x13, x20\n\t" + "and x22, x22, x3\n\t" + "sbcs x11, x11, x21\n\t" + "stp x12, x13, [%[a], 32]\n\t" + "sbcs x10, x10, x22\n\t" + "stp x11, x10, [%[a], 48]\n\t" + "ldp x12, x13, [x9, 64]\n\t" + "and x23, x23, x3\n\t" + "ldp x11, x10, [x9, 80]\n\t" + "and x24, x24, x3\n\t" + "sbcs x12, x12, x23\n\t" + "and x25, x25, x3\n\t" + "sbcs x13, x13, x24\n\t" + "and x26, x26, x3\n\t" + "sbcs x11, x11, x25\n\t" + "stp x12, x13, [%[a], 64]\n\t" + "sbcs x10, x10, x26\n\t" + "stp x11, x10, [%[a], 80]\n\t" + "ldp x7, x8, [%[m], 112]\n\t" + "ldp x12, x13, [x9, 96]\n\t" + "and x27, x27, x3\n\t" + "ldp x11, x10, [x9, 112]\n\t" + "and x28, x28, x3\n\t" + "sbcs x12, x12, x27\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x28\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 96]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 112]\n\t" + "ldp x5, x6, [%[m], 128]\n\t" + "ldp x7, x8, [%[m], 144]\n\t" + "ldp x12, x13, [x9, 128]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 144]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 128]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 144]\n\t" + "ldp x5, x6, [%[m], 160]\n\t" + "ldp x7, x8, [%[m], 176]\n\t" + "ldp x12, x13, [x9, 160]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 176]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 160]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 176]\n\t" + "ldp x5, x6, [%[m], 192]\n\t" + "ldp x7, x8, [%[m], 208]\n\t" + "ldp x12, x13, [x9, 192]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 208]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 192]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 208]\n\t" + "ldp x5, x6, [%[m], 224]\n\t" + "ldp x7, x8, [%[m], 240]\n\t" + "ldp x12, x13, [x9, 224]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 240]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 224]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 240]\n\t" + "ldp x5, x6, [%[m], 256]\n\t" + "ldp x7, x8, [%[m], 272]\n\t" + "ldp x12, x13, [x9, 256]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 272]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 256]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 272]\n\t" + "ldp x5, x6, [%[m], 288]\n\t" + "ldp x7, x8, [%[m], 304]\n\t" + "ldp x12, x13, [x9, 288]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 304]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 288]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 304]\n\t" + "ldp x5, x6, [%[m], 320]\n\t" + "ldp x7, x8, [%[m], 336]\n\t" + "ldp x12, x13, [x9, 320]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 336]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 320]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 336]\n\t" + "ldp x5, x6, [%[m], 352]\n\t" + "ldp x7, x8, [%[m], 368]\n\t" + "ldp x12, x13, [x9, 352]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 368]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 352]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 368]\n\t" + : [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); } /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -11596,8 +11975,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_48(r, a, b); sp_3072_mont_reduce_48(r, m, mp); @@ -11610,8 +11989,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_48(r, a); sp_3072_mont_reduce_48(r, m, mp); @@ -12393,35 +12772,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 96]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -12469,34 +12844,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 60); + y = (byte)(n >> 60); n <<= 4; c = 60; } else if (c < 4) { - y = (int)(n >> 60); + y = (byte)(n >> 60); n = e[i--]; c = 4 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 60) & 0xf); + y = (byte)((n >> 60) & 0xf); n <<= 4; c -= 4; } @@ -12517,9 +12892,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -12538,35 +12912,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 96]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -12630,34 +13000,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else if (c < 5) { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } @@ -12679,9 +13049,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -12702,19 +13071,18 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[96], m[48], r[96]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[48 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 384) { @@ -12728,22 +13096,18 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 48 * 2; - m = r + 48 * 2; - } #endif if (err == MP_OKAY) { + r = a + 48 * 2; + m = r + 48 * 2; ah = a + 48; sp_3072_from_bin(ah, 48, in, inLen); @@ -12816,10 +13180,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -12973,13 +13336,17 @@ static sp_digit sp_3072_cond_add_24(sp_digit* r, const sp_digit* a, const sp_dig * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[48 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -13008,13 +13375,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 48; m = a + 96; @@ -13025,31 +13394,36 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_3072_from_mp(m, 48, mm); err = sp_3072_mod_exp_48(r, a, d, 3072, m, 0); } + if (err == MP_OKAY) { sp_3072_to_bin(r, out); *outLen = 384; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 48); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 48); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[48 * 2]; - sp_digit p[24], q[24], dp[24]; - sp_digit tmpa[48], tmpb[48]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[24 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -13069,31 +13443,23 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 48 * 2; q = p + 24; qi = dq = dp = q + 24; tmpa = qi + 24; tmpb = tmpa + 48; - - r = t + 48; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_3072_from_bin(a, 48, in, inLen); sp_3072_from_mp(p, 24, pm); sp_3072_from_mp(q, 24, qm); @@ -13125,18 +13491,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 24 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -13160,17 +13523,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 48; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 48; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -13183,14 +13548,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 48; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -13217,10 +13584,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -13569,34 +13939,31 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[145]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 145, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 96; -#else - tmp = &td[96]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_48(norm, m); @@ -13614,34 +13981,34 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } - sp_3072_lshift_48(r, norm, (byte)y); + sp_3072_lshift_48(r, norm, y); for (; i>=0 || c>=6; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -13653,7 +14020,7 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, sp_3072_mont_sqr_48(r, r, m, mp); sp_3072_mont_sqr_48(r, r, m, mp); - sp_3072_lshift_48(r, r, (byte)y); + sp_3072_lshift_48(r, r, y); sp_3072_mul_d_48(tmp, norm, r[48]); r[48] = 0; o = sp_3072_add_48(r, r, tmp); @@ -13668,9 +14035,8 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -13689,11 +14055,13 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; word32 i; @@ -13728,6 +14096,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -13749,10 +14118,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[48], e[24], m[24]; + sp_digit b[48]; + sp_digit e[24]; + sp_digit m[24]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -13789,7 +14161,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -13803,7 +14175,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j; + int i; + int j; byte* d; for (i = n - 1,j = 0; i >= 7; i -= 8) { @@ -13856,7 +14229,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -13890,7 +14264,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -13929,7 +14305,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_4096_to_bin(sp_digit* r, byte* a) { - int i, j; + int i; + int j; for (i = 63, j = 0; i >= 0; i--) { a[j++] = r[i] >> 56; @@ -14659,7 +15036,6 @@ SP_NOINLINE static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a) u += sp_4096_add_64(r + 32, r + 32, z1); u += sp_4096_add_32(r + 64, r + 64, z2); sp_4096_add_zero_32(r + 96, z2 + 32, u); - } #endif /* !WOLFSSL_SP_SMALL */ @@ -14861,7 +15237,8 @@ static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a) */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -14871,7 +15248,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**64 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -15475,7 +15852,7 @@ static void sp_4096_mont_norm_64(sp_digit* r, const sp_digit* m) sp_4096_sub_in_place_64(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -15755,7 +16132,6 @@ static sp_digit sp_4096_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_dig SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp) { - sp_digit ca = 0; __asm__ __volatile__ ( "ldp x14, x15, [%[m], 0]\n\t" @@ -15765,6 +16141,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, "ldp x23, x24, [%[m], 64]\n\t" "ldp x25, x26, [%[m], 80]\n\t" "ldp x27, x28, [%[m], 96]\n\t" + "mov x3, xzr\n\t" "# i = 64\n\t" "mov x4, 64\n\t" "ldp x12, x13, [%[a], 0]\n\t" @@ -16385,25 +16762,246 @@ SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, "adc x6, x6, xzr\n\t" "umulh x8, x8, x9\n\t" "adds x6, x6, x7\n\t" - "adcs x8, x8, %[ca]\n\t" + "adcs x8, x8, x3\n\t" "str x11, [%[a], 496]\n\t" - "cset %[ca], cs\n\t" + "cset x3, cs\n\t" "adds x10, x10, x6\n\t" "ldr x11, [%[a], 512]\n\t" "str x10, [%[a], 504]\n\t" "adcs x11, x11, x8\n\t" "str x11, [%[a], 512]\n\t" - "adc %[ca], %[ca], xzr\n\t" + "adc x3, x3, xzr\n\t" "subs x4, x4, 1\n\t" "add %[a], %[a], 8\n\t" "bne 1b\n\t" - "stp x12, x13, [%[a], 0]\n\t" - : [ca] "+r" (ca), [a] "+r" (a) + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "neg x3, x3\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 512\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "ldp x11, x10, [x9, 48]\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "and x21, x21, x3\n\t" + "sbcs x13, x13, x20\n\t" + "and x22, x22, x3\n\t" + "sbcs x11, x11, x21\n\t" + "stp x12, x13, [%[a], 32]\n\t" + "sbcs x10, x10, x22\n\t" + "stp x11, x10, [%[a], 48]\n\t" + "ldp x12, x13, [x9, 64]\n\t" + "and x23, x23, x3\n\t" + "ldp x11, x10, [x9, 80]\n\t" + "and x24, x24, x3\n\t" + "sbcs x12, x12, x23\n\t" + "and x25, x25, x3\n\t" + "sbcs x13, x13, x24\n\t" + "and x26, x26, x3\n\t" + "sbcs x11, x11, x25\n\t" + "stp x12, x13, [%[a], 64]\n\t" + "sbcs x10, x10, x26\n\t" + "stp x11, x10, [%[a], 80]\n\t" + "ldp x7, x8, [%[m], 112]\n\t" + "ldp x12, x13, [x9, 96]\n\t" + "and x27, x27, x3\n\t" + "ldp x11, x10, [x9, 112]\n\t" + "and x28, x28, x3\n\t" + "sbcs x12, x12, x27\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x28\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 96]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 112]\n\t" + "ldp x5, x6, [%[m], 128]\n\t" + "ldp x7, x8, [%[m], 144]\n\t" + "ldp x12, x13, [x9, 128]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 144]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 128]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 144]\n\t" + "ldp x5, x6, [%[m], 160]\n\t" + "ldp x7, x8, [%[m], 176]\n\t" + "ldp x12, x13, [x9, 160]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 176]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 160]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 176]\n\t" + "ldp x5, x6, [%[m], 192]\n\t" + "ldp x7, x8, [%[m], 208]\n\t" + "ldp x12, x13, [x9, 192]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 208]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 192]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 208]\n\t" + "ldp x5, x6, [%[m], 224]\n\t" + "ldp x7, x8, [%[m], 240]\n\t" + "ldp x12, x13, [x9, 224]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 240]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 224]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 240]\n\t" + "ldp x5, x6, [%[m], 256]\n\t" + "ldp x7, x8, [%[m], 272]\n\t" + "ldp x12, x13, [x9, 256]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 272]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 256]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 272]\n\t" + "ldp x5, x6, [%[m], 288]\n\t" + "ldp x7, x8, [%[m], 304]\n\t" + "ldp x12, x13, [x9, 288]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 304]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 288]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 304]\n\t" + "ldp x5, x6, [%[m], 320]\n\t" + "ldp x7, x8, [%[m], 336]\n\t" + "ldp x12, x13, [x9, 320]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 336]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 320]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 336]\n\t" + "ldp x5, x6, [%[m], 352]\n\t" + "ldp x7, x8, [%[m], 368]\n\t" + "ldp x12, x13, [x9, 352]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 368]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 352]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 368]\n\t" + "ldp x5, x6, [%[m], 384]\n\t" + "ldp x7, x8, [%[m], 400]\n\t" + "ldp x12, x13, [x9, 384]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 400]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 384]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 400]\n\t" + "ldp x5, x6, [%[m], 416]\n\t" + "ldp x7, x8, [%[m], 432]\n\t" + "ldp x12, x13, [x9, 416]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 432]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 416]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 432]\n\t" + "ldp x5, x6, [%[m], 448]\n\t" + "ldp x7, x8, [%[m], 464]\n\t" + "ldp x12, x13, [x9, 448]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 464]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 448]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 464]\n\t" + "ldp x5, x6, [%[m], 480]\n\t" + "ldp x7, x8, [%[m], 496]\n\t" + "ldp x12, x13, [x9, 480]\n\t" + "and x5, x5, x3\n\t" + "ldp x11, x10, [x9, 496]\n\t" + "and x6, x6, x3\n\t" + "sbcs x12, x12, x5\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x6\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 480]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 496]\n\t" + : [a] "+r" (a) : [m] "r" (m), [mp] "r" (mp) : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" ); - sp_4096_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca); } /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -16415,8 +17013,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_64(r, a, b); sp_4096_mont_reduce_64(r, m, mp); @@ -16429,8 +17027,8 @@ static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_64(r, a); sp_4096_mont_reduce_64(r, m, mp); @@ -17364,35 +17962,31 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 128]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_4096_mont_setup(m, &mp); @@ -17440,34 +18034,34 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 60); + y = (byte)(n >> 60); n <<= 4; c = 60; } else if (c < 4) { - y = (int)(n >> 60); + y = (byte)(n >> 60); n = e[i--]; c = 4 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 60) & 0xf); + y = (byte)((n >> 60) & 0xf); n <<= 4; c -= 4; } @@ -17488,9 +18082,8 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -17509,35 +18102,31 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 128]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_4096_mont_setup(m, &mp); @@ -17601,34 +18190,34 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else if (c < 5) { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } @@ -17650,9 +18239,8 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -17673,19 +18261,18 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128], m[64], r[128]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 512) { @@ -17699,22 +18286,18 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 64 * 2; - m = r + 64 * 2; - } #endif if (err == MP_OKAY) { + r = a + 64 * 2; + m = r + 64 * 2; ah = a + 64; sp_4096_from_bin(ah, 64, in, inLen); @@ -17787,10 +18370,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -17972,13 +18554,17 @@ static sp_digit sp_4096_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[64 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -18007,13 +18593,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 64; m = a + 128; @@ -18024,31 +18612,36 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_4096_from_mp(m, 64, mm); err = sp_4096_mod_exp_64(r, a, d, 4096, m, 0); } + if (err == MP_OKAY) { sp_4096_to_bin(r, out); *outLen = 512; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[64 * 2]; - sp_digit p[32], q[32], dp[32]; - sp_digit tmpa[64], tmpb[64]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[32 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -18068,31 +18661,23 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 64 * 2; q = p + 32; qi = dq = dp = q + 32; tmpa = qi + 32; tmpb = tmpa + 64; - - r = t + 64; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_4096_from_bin(a, 64, in, inLen); sp_4096_from_mp(p, 32, pm); sp_4096_from_mp(q, 32, qm); @@ -18124,18 +18709,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 32 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -18159,17 +18741,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 64; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -18182,14 +18766,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -18216,10 +18802,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -18664,34 +19253,31 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[193]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 128; -#else - tmp = &td[128]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_64(norm, m); @@ -18709,34 +19295,34 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } - sp_4096_lshift_64(r, norm, (byte)y); + sp_4096_lshift_64(r, norm, y); for (; i>=0 || c>=6; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -18748,7 +19334,7 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, sp_4096_mont_sqr_64(r, r, m, mp); sp_4096_mont_sqr_64(r, r, m, mp); - sp_4096_lshift_64(r, r, (byte)y); + sp_4096_lshift_64(r, r, y); sp_4096_mul_d_64(tmp, norm, r[64]); r[64] = 0; o = sp_4096_add_64(r, r, tmp); @@ -18763,9 +19349,8 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -18784,11 +19369,13 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; word32 i; @@ -18823,6 +19410,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -18835,19 +19423,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, } #endif /* WOLFSSL_HAVE_SP_DH */ -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 4]; + /* Y ordinate of point. */ sp_digit y[2 * 4]; + /* Z ordinate of point. */ sp_digit z[2 * 4]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -18919,48 +19511,309 @@ static const sp_digit p256_b[4] = { }; #endif -static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p) +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 24\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 32\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 48\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), NULL, &(p)) #else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap) +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; + sp_digit tmp[4]; + + __asm__ __volatile__ ( + "ldp x16, x17, [%[a], 0]\n\t" + "ldp x21, x22, [%[b], 0]\n\t" + "# A[0] * B[0]\n\t" + "mul x8, x16, x21\n\t" + "ldr x19, [%[a], 16]\n\t" + "umulh x9, x16, x21\n\t" + "ldr x23, [%[b], 16]\n\t" + "# A[0] * B[1]\n\t" + "mul x4, x16, x22\n\t" + "ldr x20, [%[a], 24]\n\t" + "umulh x5, x16, x22\n\t" + "ldr x24, [%[b], 24]\n\t" + "adds x9, x9, x4\n\t" + "# A[1] * B[0]\n\t" + "mul x4, x17, x21\n\t" + "adc x10, xzr, x5\n\t" + "umulh x5, x17, x21\n\t" + "adds x9, x9, x4\n\t" + "# A[0] * B[2]\n\t" + "mul x4, x16, x23\n\t" + "adcs x10, x10, x5\n\t" + "umulh x5, x16, x23\n\t" + "adc x11, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * B[1]\n\t" + "mul x4, x17, x22\n\t" + "adc x11, x11, x5\n\t" + "umulh x5, x17, x22\n\t" + "adds x10, x10, x4\n\t" + "# A[2] * B[0]\n\t" + "mul x4, x19, x21\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x19, x21\n\t" + "adc x12, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * B[3]\n\t" + "mul x4, x16, x24\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x16, x24\n\t" + "adc x12, x12, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * B[2]\n\t" + "mul x4, x17, x23\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x23\n\t" + "adc x13, xzr, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * B[1]\n\t" + "mul x4, x19, x22\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x19, x22\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[3] * B[0]\n\t" + "mul x4, x20, x21\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x20, x21\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * B[3]\n\t" + "mul x4, x17, x24\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x24\n\t" + "adc x13, x13, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * B[2]\n\t" + "mul x4, x19, x23\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x19, x23\n\t" + "adc x14, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * B[1]\n\t" + "mul x4, x20, x22\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x20, x22\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * B[3]\n\t" + "mul x4, x19, x24\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x19, x24\n\t" + "adc x14, x14, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * B[2]\n\t" + "mul x4, x20, x23\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x20, x23\n\t" + "adc x15, xzr, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * B[3]\n\t" + "mul x4, x20, x24\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x20, x24\n\t" + "adc x15, x15, xzr\n\t" + "adds x14, x14, x4\n\t" + "adc x15, x15, x5\n\t" + "stp x8, x9, [%[r], 0]\n\t" + "stp x10, x11, [%[r], 16]\n\t" + "stp x12, x13, [%[r], 32]\n\t" + "stp x14, x15, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x4", "x5", "x6", "x7", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_4(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x16, x17, [%[a], 0]\n\t" + "# A[0] * A[1]\n\t" + "mul x9, x16, x17\n\t" + "ldr x19, [%[a], 16]\n\t" + "umulh x10, x16, x17\n\t" + "ldr x20, [%[a], 24]\n\t" + "# A[0] * A[2]\n\t" + "mul x4, x16, x19\n\t" + "umulh x5, x16, x19\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * A[3]\n\t" + "mul x4, x16, x20\n\t" + "adc x11, xzr, x5\n\t" + "umulh x5, x16, x20\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[2]\n\t" + "mul x4, x17, x19\n\t" + "adc x12, xzr, x5\n\t" + "umulh x5, x17, x19\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[3]\n\t" + "mul x4, x17, x20\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x20\n\t" + "adc x13, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * A[3]\n\t" + "mul x4, x19, x20\n\t" + "adc x13, x13, x5\n\t" + "umulh x5, x19, x20\n\t" + "adds x13, x13, x4\n\t" + "adc x14, xzr, x5\n\t" + "# Double\n\t" + "adds x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "# A[0] * A[0]\n\t" + "mul x8, x16, x16\n\t" + "adcs x14, x14, x14\n\t" + "umulh x3, x16, x16\n\t" + "cset x15, cs\n\t" + "# A[1] * A[1]\n\t" + "mul x4, x17, x17\n\t" + "adds x9, x9, x3\n\t" + "umulh x5, x17, x17\n\t" + "adcs x10, x10, x4\n\t" + "# A[2] * A[2]\n\t" + "mul x6, x19, x19\n\t" + "adcs x11, x11, x5\n\t" + "umulh x7, x19, x19\n\t" + "adcs x12, x12, x6\n\t" + "# A[3] * A[3]\n\t" + "mul x16, x20, x20\n\t" + "adcs x13, x13, x7\n\t" + "umulh x17, x20, x20\n\t" + "adcs x14, x14, x16\n\t" + "adc x15, x15, x17\n\t" + "stp x8, x9, [%[r], 0]\n\t" + "stp x10, x11, [%[r], 16]\n\t" + "stp x12, x13, [%[r], 32]\n\t" + "stp x14, x15, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; } /* Multiply a number by Montogmery normalizer mod modulus (prime). @@ -19047,7 +19900,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -19081,7 +19935,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -19117,7 +19973,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) * p Point of type sp_point_256 (result). * pm Point of type ecc_point. */ -static void sp_256_point_from_ecc_point_4(sp_point_256* p, const ecc_point* pm) +static void sp_256_point_from_ecc_point_4(sp_point_256* p, + const ecc_point* pm) { XMEMSET(p->x, 0, sizeof(p->x)); XMEMSET(p->y, 0, sizeof(p->y)); @@ -19144,17 +20001,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = 4; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 4; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -19167,14 +20026,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 4; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -19609,7 +20470,7 @@ static void sp_256_mont_sqr_n_4(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint64_t p256_mod_minus_2[4] = { @@ -19803,35 +20664,6 @@ static sp_digit sp_256_cond_sub_4(sp_digit* r, const sp_digit* a, const sp_digit return (sp_digit)r; } -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - __asm__ __volatile__ ( - "ldp x3, x4, [%[a], 0]\n\t" - "ldp x7, x8, [%[b], 0]\n\t" - "subs x3, x3, x7\n\t" - "ldp x5, x6, [%[a], 16]\n\t" - "sbcs x4, x4, x8\n\t" - "ldp x9, x10, [%[b], 16]\n\t" - "sbcs x5, x5, x9\n\t" - "stp x3, x4, [%[r], 0]\n\t" - "sbcs x6, x6, x10\n\t" - "stp x5, x6, [%[r], 16]\n\t" - "csetm %[r], cc\n\t" - : [r] "+r" (r) - : [a] "r" (a), [b] "r" (b) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" - ); - - return (sp_digit)r; -} - #define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4 /* Reduce the number back to 256 bits using Montgomery reduction. @@ -19996,7 +20828,8 @@ SP_NOINLINE static void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m, * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*4; @@ -20514,7 +21347,8 @@ static void sp_256_mont_dbl_sub_4(sp_digit* r, const sp_digit* a, const sp_digit * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*4; @@ -20812,8 +21646,8 @@ static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_4(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -20906,8 +21740,8 @@ static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, cons * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* p, - int n, int m, sp_digit* t) +static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, + const sp_point_256* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*4; @@ -20918,6 +21752,7 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* sp_digit* y = r[(1<x[i]; @@ -20934,7 +21769,10 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* /* W = Z^4 */ sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); sp_256_mont_sub_4(t1, t1, w, p256_mod); @@ -20942,14 +21780,14 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* /* B = X*Y^2 */ sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); - x = r[(1<y); + sp_256_norm_4(negy); sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); sp_256_proj_point_add_4(rt, rt, p, tmp); } @@ -21293,24 +22133,25 @@ static int sp_256_ecc_mulmod_win_add_sub_4(sp_point_256* r, const sp_point_256* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } +#ifndef WC_NO_CACHE_RESISTANT /* A table entry for pre-computed points. */ typedef struct sp_table_entry_256 { sp_digit x[4]; sp_digit y[4]; } sp_table_entry_256; +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Add two Montgomery form projective points. The second point has a q value of * one. * Only the first point can be the same pointer as the result point. @@ -21416,12 +22257,11 @@ static void sp_256_proj_to_affine_4(sp_point_256* a, sp_digit* t) XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); } -#endif /* FP_ECC */ -#ifndef WC_NO_CACHE_RESISTANT -#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ -#ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 6 + * 64 entries + * 42 bits between * * a The base point. * table Place to store generated point data. @@ -21431,26 +22271,30 @@ static void sp_256_proj_to_affine_4(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_4(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_4(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -21495,9 +22339,10 @@ static int sp_256_gen_stripe_table_4(const sp_point_256* a, } } - sp_256_point_free_4(s2, 0, heap); - sp_256_point_free_4(s1, 0, heap); - sp_256_point_free_4( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -21541,8 +22386,10 @@ static void sp_256_get_entry_64_4(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 6 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^42, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -21556,17 +22403,19 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -21574,27 +22423,30 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=42; j<6 && x<256; j++,x+=43) { + x = 42; + for (j=0; j<6 && x<256; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 43; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -21608,8 +22460,10 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=41; i>=0; i--) { y = 0; - for (j=0,x=i; j<6 && x<256; j++,x+=43) { + x = i; + for (j=0; j<6 && x<256; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 43; } sp_256_proj_point_dbl_4(rt, rt, t); @@ -21635,33 +22489,41 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ #ifdef FP_ECC #ifndef FP_ENTRIES #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[4]; + /* Y ordinate of point that table was generated from. */ sp_digit y[4]; + /* Precomputation table for point. */ sp_table_entry_256 table[64]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -21669,9 +22531,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -21779,9 +22647,13 @@ static int sp_256_ecc_mulmod_4(sp_point_256* r, const sp_point_256* g, const sp_ #else #if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 32 bits between * * a The base point. * table Place to store generated point data. @@ -21791,26 +22663,30 @@ static int sp_256_ecc_mulmod_4(sp_point_256* r, const sp_point_256* g, const sp_ static int sp_256_gen_stripe_table_4(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_4(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -21855,9 +22731,10 @@ static int sp_256_gen_stripe_table_4(const sp_point_256* a, } } - sp_256_point_free_4(s2, 0, heap); - sp_256_point_free_4(s1, 0, heap); - sp_256_point_free_4( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -21901,8 +22778,10 @@ static void sp_256_get_entry_256_4(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -21916,17 +22795,19 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -21934,27 +22815,30 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=31; j<8; j++,x+=32) { + x = 31; + for (j=0; j<8; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 32; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -21968,8 +22852,10 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=30; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=32) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 32; } sp_256_proj_point_dbl_4(rt, rt, t); @@ -21995,33 +22881,41 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ #ifdef FP_ECC #ifndef FP_ENTRIES #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[4]; + /* Y ordinate of point that table was generated from. */ sp_digit y[4]; + /* Precomputation table for point. */ sp_table_entry_256 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -22029,9 +22923,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -22148,28 +23048,31 @@ static int sp_256_ecc_mulmod_4(sp_point_256* r, const sp_point_256* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[4]; +#endif int err = MP_OKAY; - err = sp_256_point_new_4(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 4, km); sp_256_point_from_ecc_point_4(point, gm); @@ -22180,18 +23083,102 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_4(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[4 + 4 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (4 + 4 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_4(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 4; + + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(point, gm); + sp_256_point_from_ecc_point_4(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_4(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_4(point, point, addP, tmp); + + if (map) { + sp_256_map_4(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_4(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL #ifndef WC_NO_CACHE_RESISTANT +/* Striping precomputation table. + * 6 points combined into a table of 64 points. + * Distance of 43 between points. + */ static const sp_table_entry_256 p256_table[64] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00 }, @@ -22516,6 +23503,11 @@ static const sp_table_entry_256 p256_table[64] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^42, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -22531,6 +23523,10 @@ static int sp_256_ecc_mulmod_base_4(sp_point_256* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 32 between points. + */ static const sp_table_entry_256 p256_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00 }, @@ -23815,6 +24811,11 @@ static const sp_table_entry_256 p256_table[256] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -23865,7 +24866,8 @@ static const uint8_t recode_neg_4_7[130] = { */ static void sp_256_ecc_recode_7_4(const sp_digit* k, ecc_recode_256* v) { - int i, j; + int i; + int j; uint8_t y; int carry = 0; int o; @@ -35909,35 +36911,41 @@ static int sp_256_ecc_mulmod_add_only_4(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit tmpd[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 rt[2]; + sp_digit tmp[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* tmp; - sp_digit* negy; + sp_digit* negy = NULL; int i; ecc_recode_256 v[37]; - int err; + int err = MP_OKAY; (void)g; (void)ct; (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) - err = sp_256_point_new_4(heap, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; -#else - tmp = tmpd; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif - negy = tmp; + + if (err == MP_OKAY) { + negy = tmp; + p = rt + 1; + } if (err == MP_OKAY) { sp_256_ecc_recode_7_4(k, v); @@ -35970,6 +36978,7 @@ static int sp_256_ecc_mulmod_add_only_4(sp_point_256* r, const sp_point_256* g, } p->infinity = !v[i].i; sp_256_sub_4(negy, p256_mod, p->y); + sp_256_norm_4(negy); sp_256_cond_copy_4(p->y, negy, 0 - v[i].neg); sp_256_proj_point_add_qz1_4(rt, rt, p, tmp); } @@ -35981,16 +36990,19 @@ static int sp_256_ecc_mulmod_add_only_4(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return MP_OKAY; } @@ -36022,28 +37034,30 @@ static int sp_256_ecc_mulmod_base_4(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[4]; +#endif int err = MP_OKAY; - err = sp_256_point_new_4(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 4, km); @@ -36053,12 +37067,90 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_4(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[4 + 4 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (4 + 4 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_4(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 4; + + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_4(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_4(point, point, addP, tmp); + + if (map) { + sp_256_map_4(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_4(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -36076,7 +37168,7 @@ static int sp_256_iszero_4(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -36108,7 +37200,8 @@ static void sp_256_add_one_4(sp_digit* a) */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j; + int i; + int j; byte* d; for (i = n - 1,j = 0; i >= 7; i -= 8) { @@ -36182,41 +37275,46 @@ static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[4]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_256_point_new_4(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_4(rng, k); } if (err == MP_OKAY) { @@ -36241,15 +37339,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_4(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_4(infinity, 1, heap); -#endif - sp_256_point_free_4(point, 1, heap); return err; } @@ -36263,7 +37360,8 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_256_to_bin(sp_digit* r, byte* a) { - int i, j; + int i; + int j; for (i = 3, j = 0; i >= 0; i--) { a[j++] = r[i] >> 56; @@ -36289,33 +37387,35 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[4]; +#endif int err = MP_OKAY; if (*outLen < 32U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -36328,219 +37428,18 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(point, 0, heap); return err; } #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - __asm__ __volatile__ ( - "ldp x3, x4, [%[a], 0]\n\t" - "ldp x7, x8, [%[b], 0]\n\t" - "adds x3, x3, x7\n\t" - "ldp x5, x6, [%[a], 16]\n\t" - "adcs x4, x4, x8\n\t" - "ldp x9, x10, [%[b], 16]\n\t" - "adcs x5, x5, x9\n\t" - "stp x3, x4, [%[r], 0]\n\t" - "adcs x6, x6, x10\n\t" - "stp x5, x6, [%[r], 16]\n\t" - "cset %[r], cs\n\t" - : [r] "+r" (r) - : [a] "r" (a), [b] "r" (b) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" - ); - - return (sp_digit)r; -} - -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -#ifdef WOLFSSL_SP_SMALL -/* Multiply a and b into r. (r = a * b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_digit tmp[8]; - - __asm__ __volatile__ ( - "mov x5, 0\n\t" - "mov x6, 0\n\t" - "mov x7, 0\n\t" - "mov x8, 0\n\t" - "\n1:\n\t" - "subs x3, x5, 24\n\t" - "csel x3, xzr, x3, cc\n\t" - "sub x4, x5, x3\n\t" - "\n2:\n\t" - "ldr x10, [%[a], x3]\n\t" - "ldr x11, [%[b], x4]\n\t" - "mul x9, x10, x11\n\t" - "umulh x10, x10, x11\n\t" - "adds x6, x6, x9\n\t" - "adcs x7, x7, x10\n\t" - "adc x8, x8, xzr\n\t" - "add x3, x3, #8\n\t" - "sub x4, x4, #8\n\t" - "cmp x3, 32\n\t" - "b.eq 3f\n\t" - "cmp x3, x5\n\t" - "b.le 2b\n\t" - "\n3:\n\t" - "str x6, [%[r], x5]\n\t" - "mov x6, x7\n\t" - "mov x7, x8\n\t" - "mov x8, #0\n\t" - "add x5, x5, #8\n\t" - "cmp x5, 48\n\t" - "b.le 1b\n\t" - "str x6, [%[r], x5]\n\t" - : - : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" - ); - - XMEMCPY(r, tmp, sizeof(tmp)); -} - -#else -/* Multiply a and b into r. (r = a * b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) -{ - sp_digit tmp[4]; - - __asm__ __volatile__ ( - "ldp x16, x17, [%[a], 0]\n\t" - "ldp x21, x22, [%[b], 0]\n\t" - "# A[0] * B[0]\n\t" - "mul x8, x16, x21\n\t" - "ldr x19, [%[a], 16]\n\t" - "umulh x9, x16, x21\n\t" - "ldr x23, [%[b], 16]\n\t" - "# A[0] * B[1]\n\t" - "mul x4, x16, x22\n\t" - "ldr x20, [%[a], 24]\n\t" - "umulh x5, x16, x22\n\t" - "ldr x24, [%[b], 24]\n\t" - "adds x9, x9, x4\n\t" - "# A[1] * B[0]\n\t" - "mul x4, x17, x21\n\t" - "adc x10, xzr, x5\n\t" - "umulh x5, x17, x21\n\t" - "adds x9, x9, x4\n\t" - "# A[0] * B[2]\n\t" - "mul x4, x16, x23\n\t" - "adcs x10, x10, x5\n\t" - "umulh x5, x16, x23\n\t" - "adc x11, xzr, xzr\n\t" - "adds x10, x10, x4\n\t" - "# A[1] * B[1]\n\t" - "mul x4, x17, x22\n\t" - "adc x11, x11, x5\n\t" - "umulh x5, x17, x22\n\t" - "adds x10, x10, x4\n\t" - "# A[2] * B[0]\n\t" - "mul x4, x19, x21\n\t" - "adcs x11, x11, x5\n\t" - "umulh x5, x19, x21\n\t" - "adc x12, xzr, xzr\n\t" - "adds x10, x10, x4\n\t" - "# A[0] * B[3]\n\t" - "mul x4, x16, x24\n\t" - "adcs x11, x11, x5\n\t" - "umulh x5, x16, x24\n\t" - "adc x12, x12, xzr\n\t" - "adds x11, x11, x4\n\t" - "# A[1] * B[2]\n\t" - "mul x4, x17, x23\n\t" - "adcs x12, x12, x5\n\t" - "umulh x5, x17, x23\n\t" - "adc x13, xzr, xzr\n\t" - "adds x11, x11, x4\n\t" - "# A[2] * B[1]\n\t" - "mul x4, x19, x22\n\t" - "adcs x12, x12, x5\n\t" - "umulh x5, x19, x22\n\t" - "adc x13, x13, xzr\n\t" - "adds x11, x11, x4\n\t" - "# A[3] * B[0]\n\t" - "mul x4, x20, x21\n\t" - "adcs x12, x12, x5\n\t" - "umulh x5, x20, x21\n\t" - "adc x13, x13, xzr\n\t" - "adds x11, x11, x4\n\t" - "# A[1] * B[3]\n\t" - "mul x4, x17, x24\n\t" - "adcs x12, x12, x5\n\t" - "umulh x5, x17, x24\n\t" - "adc x13, x13, xzr\n\t" - "adds x12, x12, x4\n\t" - "# A[2] * B[2]\n\t" - "mul x4, x19, x23\n\t" - "adcs x13, x13, x5\n\t" - "umulh x5, x19, x23\n\t" - "adc x14, xzr, xzr\n\t" - "adds x12, x12, x4\n\t" - "# A[3] * B[1]\n\t" - "mul x4, x20, x22\n\t" - "adcs x13, x13, x5\n\t" - "umulh x5, x20, x22\n\t" - "adc x14, x14, xzr\n\t" - "adds x12, x12, x4\n\t" - "# A[2] * B[3]\n\t" - "mul x4, x19, x24\n\t" - "adcs x13, x13, x5\n\t" - "umulh x5, x19, x24\n\t" - "adc x14, x14, xzr\n\t" - "adds x13, x13, x4\n\t" - "# A[3] * B[2]\n\t" - "mul x4, x20, x23\n\t" - "adcs x14, x14, x5\n\t" - "umulh x5, x20, x23\n\t" - "adc x15, xzr, xzr\n\t" - "adds x13, x13, x4\n\t" - "# A[3] * B[3]\n\t" - "mul x4, x20, x24\n\t" - "adcs x14, x14, x5\n\t" - "umulh x5, x20, x24\n\t" - "adc x15, x15, xzr\n\t" - "adds x14, x14, x4\n\t" - "adc x15, x15, x5\n\t" - "stp x8, x9, [%[r], 0]\n\t" - "stp x10, x11, [%[r], 16]\n\t" - "stp x12, x13, [%[r], 32]\n\t" - "stp x14, x15, [%[r], 48]\n\t" - : - : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) - : "memory", "x4", "x5", "x6", "x7", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15" - ); -} - -#endif /* WOLFSSL_SP_SMALL */ #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) /* Sub b from a into a. (a -= b) @@ -36743,83 +37642,6 @@ static WC_INLINE int sp_256_mod_4(sp_digit* r, const sp_digit* a, const sp_digit #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -static void sp_256_sqr_4(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "ldp x16, x17, [%[a], 0]\n\t" - "# A[0] * A[1]\n\t" - "mul x9, x16, x17\n\t" - "ldr x19, [%[a], 16]\n\t" - "umulh x10, x16, x17\n\t" - "ldr x20, [%[a], 24]\n\t" - "# A[0] * A[2]\n\t" - "mul x4, x16, x19\n\t" - "umulh x5, x16, x19\n\t" - "adds x10, x10, x4\n\t" - "# A[0] * A[3]\n\t" - "mul x4, x16, x20\n\t" - "adc x11, xzr, x5\n\t" - "umulh x5, x16, x20\n\t" - "adds x11, x11, x4\n\t" - "# A[1] * A[2]\n\t" - "mul x4, x17, x19\n\t" - "adc x12, xzr, x5\n\t" - "umulh x5, x17, x19\n\t" - "adds x11, x11, x4\n\t" - "# A[1] * A[3]\n\t" - "mul x4, x17, x20\n\t" - "adcs x12, x12, x5\n\t" - "umulh x5, x17, x20\n\t" - "adc x13, xzr, xzr\n\t" - "adds x12, x12, x4\n\t" - "# A[2] * A[3]\n\t" - "mul x4, x19, x20\n\t" - "adc x13, x13, x5\n\t" - "umulh x5, x19, x20\n\t" - "adds x13, x13, x4\n\t" - "adc x14, xzr, x5\n\t" - "# Double\n\t" - "adds x9, x9, x9\n\t" - "adcs x10, x10, x10\n\t" - "adcs x11, x11, x11\n\t" - "adcs x12, x12, x12\n\t" - "adcs x13, x13, x13\n\t" - "# A[0] * A[0]\n\t" - "mul x8, x16, x16\n\t" - "adcs x14, x14, x14\n\t" - "umulh x3, x16, x16\n\t" - "cset x15, cs\n\t" - "# A[1] * A[1]\n\t" - "mul x4, x17, x17\n\t" - "adds x9, x9, x3\n\t" - "umulh x5, x17, x17\n\t" - "adcs x10, x10, x4\n\t" - "# A[2] * A[2]\n\t" - "mul x6, x19, x19\n\t" - "adcs x11, x11, x5\n\t" - "umulh x7, x19, x19\n\t" - "adcs x12, x12, x6\n\t" - "# A[3] * A[3]\n\t" - "mul x16, x20, x20\n\t" - "adcs x13, x13, x7\n\t" - "umulh x17, x20, x20\n\t" - "adcs x14, x14, x16\n\t" - "adc x15, x15, x17\n\t" - "stp x8, x9, [%[r], 0]\n\t" - "stp x10, x11, [%[r], 16]\n\t" - "stp x12, x13, [%[r], 32]\n\t" - "stp x14, x15, [%[r], 48]\n\t" - : - : [r] "r" (r), [a] "r" (a) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" - ); -} - #ifdef WOLFSSL_SP_SMALL /* Order-2 for the P256 curve. */ static const uint64_t p256_order_minus_2[4] = { @@ -36828,7 +37650,7 @@ static const uint64_t p256_order_minus_2[4] = { }; #else /* The low half of the order-2 of the P256 curve. */ -static const uint64_t p256_order_low[2] = { +static const sp_int_digit p256_order_low[2] = { 0xf3b9cac2fc63254fU,0xbce6faada7179e84U }; #endif /* WOLFSSL_SP_SMALL */ @@ -36974,7 +37796,7 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ for (i=127; i>=112; i--) { sp_256_mont_sqr_order_4(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_4(t2, t2, a); } } @@ -36984,7 +37806,7 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ for (i=107; i>=64; i--) { sp_256_mont_sqr_order_4(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_4(t2, t2, a); } } @@ -36994,7 +37816,7 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ for (i=59; i>=32; i--) { sp_256_mont_sqr_order_4(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_4(t2, t2, a); } } @@ -37004,7 +37826,7 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ for (i=27; i>=0; i--) { sp_256_mont_sqr_order_4(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_4(t2, t2, a); } } @@ -37015,12 +37837,63 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_4(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int64_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_4(k, k, p256_norm_order); + err = sp_256_mod_4(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(k); + + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_4(kInv, k, tmp); + sp_256_norm_4(kInv); + + /* s = r * x + e */ + sp_256_mul_4(x, x, r); + err = sp_256_mod_4(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(x); + carry = sp_256_add_4(s, e, x); + sp_256_cond_sub_4(s, s, p256_order, 0 - carry); + sp_256_norm_4(s); + c = sp_256_cmp_4(s, p256_order); + sp_256_cond_sub_4(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_4(s, s, kInv); + sp_256_norm_4(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -37055,8 +37928,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -37074,13 +37947,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 4, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_4(rng, ctx->k); @@ -37108,6 +37978,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_4(ctx->r, p256_order); sp_256_cond_sub_4(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_4(ctx->r); + + sp_256_from_mp(ctx->x, 4, priv); + sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); ctx->state = 4; break; } @@ -37164,6 +38037,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -37196,72 +38072,55 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*4]; - sp_digit xd[2*4]; - sp_digit kd[2*4]; - sp_digit rd[2*4]; - sp_digit td[3 * 2*4]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 4]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int64_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_256_point_new_4(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 4; - x = d + 2 * 4; - k = d + 4 * 4; - r = d + 6 * 4; - tmp = d + 8 * 4; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 4; + k = e + 4 * 4; + r = e + 6 * 4; + tmp = e + 8 * 4; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 4, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 4, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_4(rng, k); @@ -37271,7 +38130,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -37282,38 +38141,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_4(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_4(r); - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_4(k, k, p256_norm_order); - err = sp_256_mod_4(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_4(k); - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_4(kInv, k, tmp); - sp_256_norm_4(kInv); + sp_256_from_mp(x, 4, priv); + sp_256_from_bin(e, 4, hash, (int)hashLen); - /* s = r * x + e */ - sp_256_mul_4(x, x, r); - err = sp_256_mod_4(x, x, p256_order); + err = sp_256_calc_s_4(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_4(x); - carry = sp_256_add_4(s, e, x); - sp_256_cond_sub_4(s, s, p256_order, 0 - carry); - sp_256_norm_4(s); - c = sp_256_cmp_4(s, p256_order); - sp_256_cond_sub_4(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_4(s); - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_4(s, s, kInv); - sp_256_norm_4(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_4(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_4(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -37327,20 +38167,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_4(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 4); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -37633,6 +38477,92 @@ static int sp_256_mod_inv_4(sp_digit* r, const sp_digit* a, } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_4(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ + + sp_256_proj_point_add_4(p1, p1, p2, tmp); + if (sp_256_iszero_4(p1->z)) { + if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { + sp_256_proj_point_dbl_4(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_4(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_256_mod_inv_4(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_256_mul_4(s, s, p256_norm_order); + } + err = sp_256_mod_4(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_256_mont_inv_order_4(s, s, tmp); + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + +#else + { + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_256_ecc_mulmod_base_4(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_4(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_4(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_4(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -37651,8 +38581,7 @@ static int sp_256_mod_inv_4(sp_digit* r, const sp_digit* a, * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -37671,8 +38600,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -37687,7 +38617,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 4, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->u2, 4, rm); sp_256_from_mp(ctx->s, 4, sm); sp_256_from_mp(ctx->p2.x, 4, pX); sp_256_from_mp(ctx->p2.y, 4, pY); @@ -37745,57 +38675,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_4(ctx->p1.z)) { - if (sp_256_iszero_4(ctx->p1.x) && sp_256_iszero_4(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<4; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->u2, 4, rm); err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_4(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int64_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int64_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->u2, 4, rm); carry = sp_256_add_4(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -37803,22 +38709,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_4(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -37826,126 +38733,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*4]; - sp_digit u2d[2*4]; - sp_digit sd[2*4]; - sp_digit tmpd[2*4 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 4]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int64_t c; - int err; + int64_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_4(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 4; - u2 = d + 2 * 4; - s = d + 4 * 4; - tmp = d + 6 * 4; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 4; + s = u1 + 4 * 4; + tmp = u1 + 6 * 4; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 4, hash, (int)hashLen); - sp_256_from_mp(u2, 4, r); + sp_256_from_mp(u2, 4, rm); sp_256_from_mp(s, 4, sm); sp_256_from_mp(p2->x, 4, pX); sp_256_from_mp(p2->y, 4, pY); sp_256_from_mp(p2->z, 4, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_256_mod_inv_4(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_4(s, s, p256_norm_order); - } - err = sp_256_mod_4(s, s, p256_order); + err = sp_256_calc_vfy_point_4(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_4(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_4(s, s, tmp); - sp_256_mont_mul_order_4(u1, u1, s); - sp_256_mont_mul_order_4(u2, u2, s); - } - -#else - { - sp_256_mont_mul_order_4(u1, u1, s); - sp_256_mont_mul_order_4(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_256_ecc_mulmod_base_4(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_4(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_4(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_256_proj_point_add_4(p1, p1, p2, tmp); - if (sp_256_iszero_4(p1->z)) { - if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { - sp_256_proj_point_dbl_4(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 4, r); + sp_256_from_mp(u2, 4, rm); err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); } @@ -37956,7 +38800,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 4, r); + sp_256_from_mp(u2, 4, rm); carry = sp_256_add_4(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -37964,26 +38808,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_4(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_4(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p1, 0, heap); - sp_256_point_free_4(p2, 0, heap); return err; } @@ -37997,34 +38841,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_4(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*4]; - sp_digit t2d[2*4]; + sp_digit t1[4 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 4; - t2 = d + 2 * 4; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 4; sp_256_sqr_4(t1, point->y); (void)sp_256_mod_4(t1, t1, p256_mod); @@ -38044,10 +38880,9 @@ static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -38060,16 +38895,23 @@ static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_4(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 4, pX); sp_256_from_mp(pub->y, 4, pY); @@ -38078,7 +38920,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_4(pub, NULL); } - sp_256_point_free_4(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -38094,47 +38939,48 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[4]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; - sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_256_point_new_4(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_256* pub = NULL; +#else + sp_digit priv[4]; + sp_point_256 pub[2]; #endif + sp_point_256* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 4, pX); sp_256_from_mp(pub->y, 4, pY); sp_256_from_bin(pub->z, 4, one, (int)sizeof(one)); @@ -38148,12 +38994,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || - sp_256_cmp_4(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_4(pub->x, p256_mod) >= 0) || + (sp_256_cmp_4(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -38165,12 +39010,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_4(p->x) == 0) || - (sp_256_iszero_4(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_4(p->x) == 0) || + (sp_256_iszero_4(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -38178,22 +39021,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_256_ecc_mulmod_base_4(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_4(p->x, pub->x) != 0 || - sp_256_cmp_4(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_4(p->x, pub->x) != 0) || + (sp_256_cmp_4(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(pub, 0, heap); return err; } @@ -38217,33 +39058,35 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 4 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 4 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; - err = sp_256_point_new_4(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_4(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 4, pX); sp_256_from_mp(p->y, 4, pY); sp_256_from_mp(p->z, 4, pZ); @@ -38264,13 +39107,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(q, 0, NULL); - sp_256_point_free_4(p, 0, NULL); return err; } @@ -38289,25 +39131,28 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 4 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 4 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_4(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -38328,12 +39173,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, NULL); return err; } @@ -38348,32 +39193,36 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 4 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 4 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_4(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 4, pX); sp_256_from_mp(p->y, 4, pY); sp_256_from_mp(p->z, 4, pZ); - sp_256_map_4(p, p, tmp); + sp_256_map_4(p, p, tmp); } if (err == MP_OKAY) { @@ -38386,12 +39235,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, NULL); return err; } @@ -38404,31 +39253,23 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_4(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 4]; - sp_digit t2d[2 * 4]; + sp_digit t1[4 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 4; - t2 = d + 2 * 4; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 4; { /* t2 = y ^ 0x2 */ @@ -38463,10 +39304,9 @@ static int sp_256_mont_sqrt_4(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -38482,31 +39322,22 @@ static int sp_256_mont_sqrt_4(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 4]; - sp_digit yd[2 * 4]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 4]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 4; - y = d + 2 * 4; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 4; sp_256_from_mp(x, 4, xm); err = sp_256_mod_mul_norm_4(x, x, p256_mod); @@ -38539,10 +39370,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -38553,9 +39383,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 6]; + /* Y ordinate of point. */ sp_digit y[2 * 6]; + /* Z ordinate of point. */ sp_digit z[2 * 6]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; @@ -38593,8 +39427,9 @@ static const sp_digit p384_norm_order[6] = { #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) /* The Montogmery multiplier for order of the curve P384. */ -static sp_digit p384_mp_order = 0x6ed46089e88fdc45l; +static sp_digit p384_mp_order = 0x6ed46089e88fdc45L; #endif +#ifdef WOLFSSL_SP_SMALL /* The base point of curve P384. */ static const sp_point_384 p384_base = { /* X ordinate */ @@ -38618,6 +39453,7 @@ static const sp_point_384 p384_base = { /* infinity */ 0 }; +#endif /* WOLFSSL_SP_SMALL */ #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) static const sp_digit p384_b[6] = { 0x2a85c8edd3ec2aefL,0xc656398d8a2ed19dL,0x0314088f5013875aL, @@ -38625,397 +39461,6 @@ static const sp_digit p384_b[6] = { }; #endif -static int sp_384_point_new_ex_6(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_6(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mod_mul_norm_6(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* td; -#else - int64_t td[12]; - int64_t a32d[12]; -#endif - int64_t* t; - int64_t* a32; - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (td == NULL) { - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = td; - a32 = td + 12; -#else - t = td; - a32 = a32d; -#endif - - a32[0] = a[0] & 0xffffffff; - a32[1] = a[0] >> 32; - a32[2] = a[1] & 0xffffffff; - a32[3] = a[1] >> 32; - a32[4] = a[2] & 0xffffffff; - a32[5] = a[2] >> 32; - a32[6] = a[3] & 0xffffffff; - a32[7] = a[3] >> 32; - a32[8] = a[4] & 0xffffffff; - a32[9] = a[4] >> 32; - a32[10] = a[5] & 0xffffffff; - a32[11] = a[5] >> 32; - - /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ - t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; - /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ - t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; - /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ - t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; - /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ - t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; - /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ - t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; - /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ - t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; - /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ - t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; - /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ - t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; - /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ - t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; - /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ - t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; - /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ - t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; - /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ - t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - o = t[11] >> 32; t[11] &= 0xffffffff; - t[0] += o; - t[1] -= o; - t[3] += o; - t[4] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - - r[0] = (t[1] << 32) | t[0]; - r[1] = (t[3] << 32) | t[2]; - r[2] = (t[5] << 32) | t[4]; - r[3] = (t[7] << 32) | t[6]; - r[4] = (t[9] << 32) | t[8]; - r[5] = (t[11] << 32) | t[10]; - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) - XFREE(td, NULL, DYNAMIC_TYPE_ECC); -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 64 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 64 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xffffffffffffffffl; - s = 64U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 64U) <= (word32)DIGIT_BIT) { - s += 64U; - r[j] &= 0xffffffffffffffffl; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 64) { - r[j] &= 0xffffffffffffffffl; - if (j + 1 >= size) { - break; - } - s = 64 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_384. - * - * p Point of type sp_point_384 (result). - * pm Point of type ecc_point. - */ -static void sp_384_point_from_ecc_point_6(sp_point_384* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_384_from_mp(p->x, 6, pm->x); - sp_384_from_mp(p->y, 6, pm->y); - sp_384_from_mp(p->z, 6, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_384_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 64 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 6); - r->used = 6; - mp_clamp(r); -#elif DIGIT_BIT < 64 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 6; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 64) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 64 - s; - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 6; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 64 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 64 - s; - } - else { - s += 64; - } - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_384 to type ecc_point. - * - * p Point of type sp_point_384. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_384_point_to_ecc_point_6(const sp_point_384* p, ecc_point* pm) -{ - int err; - - err = sp_384_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pm->z); - } - - return err; -} - -/* Conditionally copy a into r using the mask m. - * m is -1 to copy and 0 when not. - * - * r A single precision number to copy over. - * a A single precision number to copy. - * m Mask value to apply. - */ -static void sp_384_cond_copy_6(sp_digit* r, const sp_digit* a, sp_digit m) -{ - __asm__ __volatile__ ( - "ldp x3, x4, [%[r], 0]\n\t" - "ldp x5, x6, [%[r], 16]\n\t" - "ldp x7, x8, [%[r], 32]\n\t" - "ldp x9, x10, [%[a], 0]\n\t" - "ldp x11, x12, [%[a], 16]\n\t" - "ldp x13, x14, [%[a], 32]\n\t" - "eor x9, x9, x3\n\t" - "eor x10, x10, x4\n\t" - "eor x11, x11, x5\n\t" - "eor x12, x12, x6\n\t" - "eor x13, x13, x7\n\t" - "eor x14, x14, x8\n\t" - "and x9, x9, %[m]\n\t" - "and x10, x10, %[m]\n\t" - "and x11, x11, %[m]\n\t" - "and x12, x12, %[m]\n\t" - "and x13, x13, %[m]\n\t" - "and x14, x14, %[m]\n\t" - "eor x3, x3, x9\n\t" - "eor x4, x4, x10\n\t" - "eor x5, x5, x11\n\t" - "eor x6, x6, x12\n\t" - "eor x7, x7, x13\n\t" - "eor x8, x8, x14\n\t" - "stp x3, x4, [%[r], 0]\n\t" - "stp x5, x6, [%[r], 16]\n\t" - "stp x7, x8, [%[r], 32]\n\t" - : - : [r] "r" (r), [a] "r" (a), [m] "r" (m) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" - ); -} - #ifdef WOLFSSL_SP_SMALL /* Multiply a and b into r. (r = a * b) * @@ -39076,395 +39521,242 @@ static void sp_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b) */ static void sp_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b) { - sp_digit tmp[6]; - __asm__ __volatile__ ( - "ldp x9, x10, [%[a], 0]\n\t" - "ldp x11, x12, [%[a], 16]\n\t" - "ldp x13, x14, [%[a], 32]\n\t" - "ldp x15, x16, [%[b], 0]\n\t" - "ldp x17, x19, [%[b], 16]\n\t" - "ldp x20, x21, [%[b], 32]\n\t" + "ldp x8, x9, [%[a], 0]\n\t" + "ldp x10, x11, [%[a], 16]\n\t" + "ldp x12, x13, [%[a], 32]\n\t" + "ldp x14, x15, [%[b], 0]\n\t" + "ldp x16, x17, [%[b], 16]\n\t" + "ldp x19, x20, [%[b], 32]\n\t" "# A[0] * B[0]\n\t" - "mul x4, x9, x15\n\t" - "umulh x5, x9, x15\n\t" - "str x4, [%[tmp]]\n\t" + "mul x3, x8, x14\n\t" + "umulh x4, x8, x14\n\t" + "str x3, [%[r]]\n\t" "# A[0] * B[1]\n\t" - "mul x7, x9, x16\n\t" - "umulh x8, x9, x16\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x8, x15\n\t" + "umulh x7, x8, x15\n\t" + "adds x4, x4, x6\n\t" "# A[1] * B[0]\n\t" - "mul x7, x10, x15\n\t" - "adc x6, xzr, x8\n\t" - "umulh x8, x10, x15\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[tmp], 8]\n\t" - "adc x4, xzr, xzr\n\t" + "mul x6, x9, x14\n\t" + "adc x5, xzr, x7\n\t" + "umulh x7, x9, x14\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 8]\n\t" + "adc x3, xzr, xzr\n\t" "# A[0] * B[2]\n\t" - "mul x7, x9, x17\n\t" - "umulh x8, x9, x17\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x8, x16\n\t" + "umulh x7, x8, x16\n\t" + "adds x5, x5, x6\n\t" "# A[1] * B[1]\n\t" - "mul x7, x10, x16\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x10, x16\n\t" - "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x9, x15\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x9, x15\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[2] * B[0]\n\t" - "mul x7, x11, x15\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x11, x15\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[tmp], 16]\n\t" - "adc x5, x5, xzr\n\t" + "mul x6, x10, x14\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x14\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 16]\n\t" + "adc x4, x4, xzr\n\t" "# A[0] * B[3]\n\t" - "mul x7, x9, x19\n\t" - "umulh x8, x9, x19\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x8, x17\n\t" + "umulh x7, x8, x17\n\t" + "adds x3, x3, x6\n\t" "# A[1] * B[2]\n\t" - "mul x7, x10, x17\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x10, x17\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x9, x16\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x9, x16\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[2] * B[1]\n\t" - "mul x7, x11, x16\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x11, x16\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x10, x15\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x10, x15\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" "# A[3] * B[0]\n\t" - "mul x7, x12, x15\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x12, x15\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[tmp], 24]\n\t" - "adc x6, x6, xzr\n\t" + "mul x6, x11, x14\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x14\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 24]\n\t" + "adc x5, x5, xzr\n\t" "# A[0] * B[4]\n\t" - "mul x7, x9, x20\n\t" - "umulh x8, x9, x20\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x8, x19\n\t" + "umulh x7, x8, x19\n\t" + "adds x4, x4, x6\n\t" "# A[1] * B[3]\n\t" - "mul x7, x10, x19\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x10, x19\n\t" - "adc x4, xzr, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x9, x17\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x9, x17\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[2] * B[2]\n\t" - "mul x7, x11, x17\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x11, x17\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x10, x16\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x10, x16\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[3] * B[1]\n\t" - "mul x7, x12, x16\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x12, x16\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" + "mul x6, x11, x15\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x11, x15\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" "# A[4] * B[0]\n\t" - "mul x7, x13, x15\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x13, x15\n\t" - "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[tmp], 32]\n\t" - "adc x4, x4, xzr\n\t" + "mul x6, x12, x14\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x14\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 32]\n\t" + "adc x3, x3, xzr\n\t" "# A[0] * B[5]\n\t" - "mul x7, x9, x21\n\t" - "umulh x8, x9, x21\n\t" - "adds x6, x6, x7\n\t" + "mul x6, x8, x20\n\t" + "umulh x7, x8, x20\n\t" + "adds x5, x5, x6\n\t" "# A[1] * B[4]\n\t" - "mul x7, x10, x20\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x10, x20\n\t" - "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" - "# A[2] * B[3]\n\t" - "mul x7, x11, x19\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x11, x19\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "# A[3] * B[2]\n\t" - "mul x7, x12, x17\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x12, x17\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "# A[4] * B[1]\n\t" - "mul x7, x13, x16\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x13, x16\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "# A[5] * B[0]\n\t" - "mul x7, x14, x15\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x14, x15\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[tmp], 40]\n\t" - "adc x5, x5, xzr\n\t" - "# A[1] * B[5]\n\t" - "mul x7, x10, x21\n\t" - "umulh x8, x10, x21\n\t" - "adds x4, x4, x7\n\t" - "# A[2] * B[4]\n\t" - "mul x7, x11, x20\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x11, x20\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[3] * B[3]\n\t" - "mul x7, x12, x19\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x12, x19\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[4] * B[2]\n\t" - "mul x7, x13, x17\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x13, x17\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "# A[5] * B[1]\n\t" - "mul x7, x14, x16\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x14, x16\n\t" - "adc x6, x6, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[r], 48]\n\t" - "adc x6, x6, xzr\n\t" - "# A[2] * B[5]\n\t" - "mul x7, x11, x21\n\t" - "umulh x8, x11, x21\n\t" - "adds x5, x5, x7\n\t" - "# A[3] * B[4]\n\t" - "mul x7, x12, x20\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x12, x20\n\t" + "mul x6, x9, x19\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x9, x19\n\t" "adc x4, xzr, xzr\n\t" - "adds x5, x5, x7\n\t" - "# A[4] * B[3]\n\t" - "mul x7, x13, x19\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x13, x19\n\t" + "adds x5, x5, x6\n\t" + "# A[2] * B[3]\n\t" + "mul x6, x10, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x17\n\t" "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "# A[5] * B[2]\n\t" - "mul x7, x14, x17\n\t" - "adcs x6, x6, x8\n\t" - "umulh x8, x14, x17\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B[2]\n\t" + "mul x6, x11, x16\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x11, x16\n\t" "adc x4, x4, xzr\n\t" - "adds x5, x5, x7\n\t" - "adcs x6, x6, x8\n\t" - "str x5, [%[r], 56]\n\t" + "adds x5, x5, x6\n\t" + "# A[4] * B[1]\n\t" + "mul x6, x12, x15\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x12, x15\n\t" "adc x4, x4, xzr\n\t" - "# A[3] * B[5]\n\t" - "mul x7, x12, x21\n\t" - "umulh x8, x12, x21\n\t" - "adds x6, x6, x7\n\t" - "# A[4] * B[4]\n\t" - "mul x7, x13, x20\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x13, x20\n\t" + "adds x5, x5, x6\n\t" + "# A[5] * B[0]\n\t" + "mul x6, x13, x14\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x14\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 40]\n\t" + "adc x4, x4, xzr\n\t" + "# A[1] * B[5]\n\t" + "mul x6, x9, x20\n\t" + "umulh x7, x9, x20\n\t" + "adds x3, x3, x6\n\t" + "# A[2] * B[4]\n\t" + "mul x6, x10, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x10, x19\n\t" "adc x5, xzr, xzr\n\t" - "adds x6, x6, x7\n\t" + "adds x3, x3, x6\n\t" + "# A[3] * B[3]\n\t" + "mul x6, x11, x17\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B[2]\n\t" + "mul x6, x12, x16\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x12, x16\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[5] * B[1]\n\t" + "mul x6, x13, x15\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x13, x15\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 48]\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[5]\n\t" + "mul x6, x10, x20\n\t" + "umulh x7, x10, x20\n\t" + "adds x4, x4, x6\n\t" + "# A[3] * B[4]\n\t" + "mul x6, x11, x19\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x11, x19\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[4] * B[3]\n\t" + "mul x6, x12, x17\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x17\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B[2]\n\t" + "mul x6, x13, x16\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x13, x16\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 56]\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[5]\n\t" + "mul x6, x11, x20\n\t" + "umulh x7, x11, x20\n\t" + "adds x5, x5, x6\n\t" + "# A[4] * B[4]\n\t" + "mul x6, x12, x19\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x12, x19\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" "# A[5] * B[3]\n\t" - "mul x7, x14, x19\n\t" - "adcs x4, x4, x8\n\t" - "umulh x8, x14, x19\n\t" - "adc x5, x5, xzr\n\t" - "adds x6, x6, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x6, [%[r], 64]\n\t" - "adc x5, x5, xzr\n\t" + "mul x6, x13, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 64]\n\t" + "adc x4, x4, xzr\n\t" "# A[4] * B[5]\n\t" - "mul x7, x13, x21\n\t" - "umulh x8, x13, x21\n\t" - "adds x4, x4, x7\n\t" + "mul x6, x12, x20\n\t" + "umulh x7, x12, x20\n\t" + "adds x3, x3, x6\n\t" "# A[5] * B[4]\n\t" - "mul x7, x14, x20\n\t" - "adcs x5, x5, x8\n\t" - "umulh x8, x14, x20\n\t" - "adc x6, xzr, xzr\n\t" - "adds x4, x4, x7\n\t" - "adcs x5, x5, x8\n\t" - "str x4, [%[r], 72]\n\t" - "adc x6, x6, xzr\n\t" + "mul x6, x13, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x13, x19\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 72]\n\t" + "adc x5, x5, xzr\n\t" "# A[5] * B[5]\n\t" - "mul x7, x14, x21\n\t" - "umulh x8, x14, x21\n\t" - "adds x5, x5, x7\n\t" - "adc x6, x6, x8\n\t" - "stp x5, x6, [%[r], 80]\n\t" - "ldp x9, x10, [%[tmp], 0]\n\t" - "ldp x11, x12, [%[tmp], 16]\n\t" - "ldp x13, x14, [%[tmp], 32]\n\t" - "stp x9, x10, [%[r], 0]\n\t" - "stp x11, x12, [%[r], 16]\n\t" - "stp x13, x14, [%[r], 32]\n\t" + "mul x6, x13, x20\n\t" + "umulh x7, x13, x20\n\t" + "adds x4, x4, x6\n\t" + "adc x5, x5, x7\n\t" + "stp x4, x5, [%[r], 80]\n\t" : - : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) - : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21" + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" ); } #endif /* WOLFSSL_SP_SMALL */ -/* Conditionally subtract b from a using the mask m. - * m is -1 to subtract and 0 when not copying. - * - * r A single precision number representing condition subtract result. - * a A single precision number to subtract from. - * b A single precision number to subtract. - * m Mask value to apply. - */ -static sp_digit sp_384_cond_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, - sp_digit m) -{ - __asm__ __volatile__ ( - - "ldp x5, x7, [%[b], 0]\n\t" - "ldp x11, x12, [%[b], 16]\n\t" - "ldp x4, x6, [%[a], 0]\n\t" - "and x5, x5, %[m]\n\t" - "ldp x9, x10, [%[a], 16]\n\t" - "and x7, x7, %[m]\n\t" - "subs x4, x4, x5\n\t" - "and x11, x11, %[m]\n\t" - "sbcs x6, x6, x7\n\t" - "and x12, x12, %[m]\n\t" - "sbcs x9, x9, x11\n\t" - "stp x4, x6, [%[r], 0]\n\t" - "sbcs x10, x10, x12\n\t" - "stp x9, x10, [%[r], 16]\n\t" - "ldp x5, x7, [%[b], 32]\n\t" - "ldp x4, x6, [%[a], 32]\n\t" - "and x5, x5, %[m]\n\t" - "and x7, x7, %[m]\n\t" - "sbcs x4, x4, x5\n\t" - "sbcs x6, x6, x7\n\t" - "stp x4, x6, [%[r], 32]\n\t" - "csetm %[r], cc\n\t" - : [r] "+r" (r) - : [a] "r" (a), [b] "r" (b), [m] "r" (m) - : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" - ); - - return (sp_digit)r; -} - -#define sp_384_mont_reduce_order_6 sp_384_mont_reduce_6 - -/* Reduce the number back to 384 bits using Montgomery reduction. - * - * a A single precision number to reduce in place. - * m The single precision number representing the modulus. - * mp The digit representing the negative inverse of m mod 2^n. - */ -SP_NOINLINE static void sp_384_mont_reduce_6(sp_digit* a, const sp_digit* m, - sp_digit mp) -{ - sp_digit ca = 0; - - __asm__ __volatile__ ( - "ldp x14, x15, [%[m], 0]\n\t" - "ldp x16, x17, [%[m], 16]\n\t" - "ldp x19, x20, [%[m], 32]\n\t" - "# i = 6\n\t" - "mov x4, 6\n\t" - "ldp x12, x13, [%[a], 0]\n\t" - "\n1:\n\t" - "# mu = a[i] * mp\n\t" - "mul x9, %[mp], x12\n\t" - "# a[i+0] += m[0] * mu\n\t" - "mul x7, x14, x9\n\t" - "umulh x8, x14, x9\n\t" - "adds x12, x12, x7\n\t" - "# a[i+1] += m[1] * mu\n\t" - "mul x7, x15, x9\n\t" - "adc x6, x8, xzr\n\t" - "umulh x8, x15, x9\n\t" - "adds x12, x13, x7\n\t" - "# a[i+2] += m[2] * mu\n\t" - "ldr x13, [%[a], 16]\n\t" - "adc x5, x8, xzr\n\t" - "mul x7, x16, x9\n\t" - "adds x12, x12, x6\n\t" - "umulh x8, x16, x9\n\t" - "adc x5, x5, xzr\n\t" - "adds x13, x13, x7\n\t" - "# a[i+3] += m[3] * mu\n\t" - "ldr x10, [%[a], 24]\n\t" - "adc x6, x8, xzr\n\t" - "mul x7, x17, x9\n\t" - "adds x13, x13, x5\n\t" - "umulh x8, x17, x9\n\t" - "adc x6, x6, xzr\n\t" - "adds x10, x10, x7\n\t" - "# a[i+4] += m[4] * mu\n\t" - "ldr x11, [%[a], 32]\n\t" - "adc x5, x8, xzr\n\t" - "adds x10, x10, x6\n\t" - "mul x7, x19, x9\n\t" - "adc x5, x5, xzr\n\t" - "umulh x8, x19, x9\n\t" - "str x10, [%[a], 24]\n\t" - "adds x11, x11, x7\n\t" - "# a[i+5] += m[5] * mu\n\t" - "ldr x10, [%[a], 40]\n\t" - "adc x6, x8, xzr\n\t" - "adds x11, x11, x5\n\t" - "mul x7, x20, x9\n\t" - "adc x6, x6, xzr\n\t" - "umulh x8, x20, x9\n\t" - "adds x6, x6, x7\n\t" - "adcs x8, x8, %[ca]\n\t" - "str x11, [%[a], 32]\n\t" - "cset %[ca], cs\n\t" - "adds x10, x10, x6\n\t" - "ldr x11, [%[a], 48]\n\t" - "str x10, [%[a], 40]\n\t" - "adcs x11, x11, x8\n\t" - "str x11, [%[a], 48]\n\t" - "adc %[ca], %[ca], xzr\n\t" - "subs x4, x4, 1\n\t" - "add %[a], %[a], 8\n\t" - "bne 1b\n\t" - "stp x12, x13, [%[a], 0]\n\t" - : [ca] "+r" (ca), [a] "+r" (a) - : [m] "r" (m), [mp] "r" (mp) - : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" - ); - - sp_384_cond_sub_6(a - 6, a, m, (sp_digit)0 - ca); -} - -/* Multiply two Montogmery form numbers mod the modulus (prime). - * (r = a * b mod m) - * - * r Result of multiplication. - * a First number to multiply in Montogmery form. - * b Second number to multiply in Montogmery form. - * m Modulus (prime). - * mp Montogmery mulitplier. - */ -static void sp_384_mont_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) -{ - sp_384_mul_6(r, a, b); - sp_384_mont_reduce_6(r, m, mp); -} - #ifdef WOLFSSL_SP_SMALL /* Square a and put result in r. (r = a * a) * @@ -39681,6 +39973,593 @@ static void sp_384_sqr_6(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_add_6(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldr x3, [%[a], 32]\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x7, [%[b], 32]\n\t" + "ldr x8, [%[b], 40]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x3, [%[r], 32]\n\t" + "str x4, [%[r], 40]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_sub_6(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldr x3, [%[a], 32]\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x7, [%[b], 32]\n\t" + "ldr x8, [%[b], 40]\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "str x3, [%[r], 32]\n\t" + "str x4, [%[r], 40]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mod_mul_norm_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[2 * 12]; +#endif + int64_t* a32 = NULL; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + a32 = t + 12; + + a32[0] = a[0] & 0xffffffff; + a32[1] = a[0] >> 32; + a32[2] = a[1] & 0xffffffff; + a32[3] = a[1] >> 32; + a32[4] = a[2] & 0xffffffff; + a32[5] = a[2] >> 32; + a32[6] = a[3] & 0xffffffff; + a32[7] = a[3] >> 32; + a32[8] = a[4] & 0xffffffff; + a32[9] = a[4] >> 32; + a32[10] = a[5] & 0xffffffff; + a32[11] = a[5] >> 32; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = (t[1] << 32) | t[0]; + r[1] = (t[3] << 32) | t[2]; + r[2] = (t[5] << 32) | t[4]; + r[3] = (t[7] << 32) | t[6]; + r[4] = (t[9] << 32) | t[8]; + r[5] = (t[11] << 32) | t[10]; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_6(sp_point_384* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_384_from_mp(p->x, 6, pm->x); + sp_384_from_mp(p->y, 6, pm->y); + sp_384_from_mp(p->z, 6, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 6); + r->used = 6; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 6; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 6; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else { + s += 64; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_6(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +static void sp_384_cond_copy_6(sp_digit* r, const sp_digit* a, sp_digit m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[r], 0]\n\t" + "ldp x5, x6, [%[r], 16]\n\t" + "ldp x7, x8, [%[r], 32]\n\t" + "ldp x9, x10, [%[a], 0]\n\t" + "ldp x11, x12, [%[a], 16]\n\t" + "ldp x13, x14, [%[a], 32]\n\t" + "eor x9, x9, x3\n\t" + "eor x10, x10, x4\n\t" + "eor x11, x11, x5\n\t" + "eor x12, x12, x6\n\t" + "eor x13, x13, x7\n\t" + "eor x14, x14, x8\n\t" + "and x9, x9, %[m]\n\t" + "and x10, x10, %[m]\n\t" + "and x11, x11, %[m]\n\t" + "and x12, x12, %[m]\n\t" + "and x13, x13, %[m]\n\t" + "and x14, x14, %[m]\n\t" + "eor x3, x3, x9\n\t" + "eor x4, x4, x10\n\t" + "eor x5, x5, x11\n\t" + "eor x6, x6, x12\n\t" + "eor x7, x7, x13\n\t" + "eor x8, x8, x14\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "stp x7, x8, [%[r], 32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_384_cond_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +} + +#define sp_384_mont_reduce_order_6 sp_384_mont_reduce_6 + +/* Reduce the number back to 384 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_384_mont_reduce_6(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "mov x3, xzr\n\t" + "# i = 6\n\t" + "mov x4, 6\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, x3\n\t" + "str x11, [%[a], 32]\n\t" + "cset x3, cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 48]\n\t" + "str x10, [%[a], 40]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 48]\n\t" + "adc x3, x3, xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "neg x3, x3\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 48\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "sbcs x13, x13, x20\n\t" + "stp x12, x13, [%[a], 32]\n\t" + : [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" + ); + +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_384_mont_mul_6(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_384_mul_6(r, a, b); + sp_384_mont_reduce_6(r, m, mp); +} + /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -39688,8 +40567,8 @@ static void sp_384_sqr_6(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_6(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_6(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_6(r, a); sp_384_mont_reduce_6(r, m, mp); @@ -39713,7 +40592,7 @@ static void sp_384_mont_sqr_n_6(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint64_t p384_mod_minus_2[6] = { @@ -39907,7 +40786,8 @@ static int64_t sp_384_cmp_6(const sp_digit* a, const sp_digit* b) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*6; @@ -39943,43 +40823,6 @@ static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_384_add_6(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - __asm__ __volatile__ ( - "ldp x3, x4, [%[a], 0]\n\t" - "ldp x7, x8, [%[b], 0]\n\t" - "adds x3, x3, x7\n\t" - "ldp x5, x6, [%[a], 16]\n\t" - "adcs x4, x4, x8\n\t" - "ldp x9, x10, [%[b], 16]\n\t" - "adcs x5, x5, x9\n\t" - "stp x3, x4, [%[r], 0]\n\t" - "adcs x6, x6, x10\n\t" - "stp x5, x6, [%[r], 16]\n\t" - "ldr x3, [%[a], 32]\n\t" - "ldr x4, [%[a], 40]\n\t" - "ldr x7, [%[b], 32]\n\t" - "ldr x8, [%[b], 40]\n\t" - "adcs x3, x3, x7\n\t" - "adcs x4, x4, x8\n\t" - "str x3, [%[r], 32]\n\t" - "str x4, [%[r], 40]\n\t" - "cset %[r], cs\n\t" - : [r] "+r" (r) - : [a] "r" (a), [b] "r" (b) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" - ); - - return (sp_digit)r; -} - /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -40026,43 +40869,6 @@ static void sp_384_mont_tpl_6(sp_digit* r, const sp_digit* a, const sp_digit* m) sp_384_cond_sub_6(r, r, m, 0 - o); } -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -static sp_digit sp_384_sub_6(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - __asm__ __volatile__ ( - "ldp x3, x4, [%[a], 0]\n\t" - "ldp x7, x8, [%[b], 0]\n\t" - "subs x3, x3, x7\n\t" - "ldp x5, x6, [%[a], 16]\n\t" - "sbcs x4, x4, x8\n\t" - "ldp x9, x10, [%[b], 16]\n\t" - "sbcs x5, x5, x9\n\t" - "stp x3, x4, [%[r], 0]\n\t" - "sbcs x6, x6, x10\n\t" - "stp x5, x6, [%[r], 16]\n\t" - "ldr x3, [%[a], 32]\n\t" - "ldr x4, [%[a], 40]\n\t" - "ldr x7, [%[b], 32]\n\t" - "ldr x8, [%[b], 40]\n\t" - "sbcs x3, x3, x7\n\t" - "sbcs x4, x4, x8\n\t" - "str x3, [%[r], 32]\n\t" - "str x4, [%[r], 40]\n\t" - "csetm %[r], cc\n\t" - : [r] "+r" (r) - : [a] "r" (a), [b] "r" (b) - : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" - ); - - return (sp_digit)r; -} - /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -40389,7 +41195,8 @@ static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_d * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_6(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_6(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*6; @@ -40693,8 +41500,8 @@ static int sp_384_proj_point_add_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_6(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -40787,8 +41594,8 @@ static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, cons * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* p, - int n, int m, sp_digit* t) +static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, + const sp_point_384* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*6; @@ -40799,6 +41606,7 @@ static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* sp_digit* y = r[(1<x[i]; @@ -40815,7 +41623,10 @@ static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* /* W = Z^4 */ sp_384_mont_sqr_6(w, z, p384_mod, p384_mp_mod); sp_384_mont_sqr_6(w, w, p384_mod, p384_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); sp_384_mont_sub_6(t1, t1, w, p384_mod); @@ -40823,14 +41634,14 @@ static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* /* B = X*Y^2 */ sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); sp_384_mont_mul_6(b, t2, x, p384_mod, p384_mp_mod); - x = r[(1<y); + sp_384_norm_6(negy); sp_384_cond_copy_6(p->y, negy, (sp_digit)0 - v[i].neg); sp_384_proj_point_add_6(rt, rt, p, tmp); } @@ -41186,26 +41999,25 @@ static int sp_384_ecc_mulmod_win_add_sub_6(sp_point_384* r, const sp_point_384* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(rt, 0, heap); return err; } +#ifndef WC_NO_CACHE_RESISTANT /* A table entry for pre-computed points. */ typedef struct sp_table_entry_384 { sp_digit x[6]; sp_digit y[6]; } sp_table_entry_384; -#ifdef FP_ECC -#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Add two Montgomery form projective points. The second point has a q value of * one. * Only the first point can be the same pointer as the result point. @@ -41312,6 +42124,10 @@ static void sp_384_proj_to_affine_6(sp_point_384* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 6 + * 64 entries + * 64 bits between * * a The base point. * table Place to store generated point data. @@ -41321,26 +42137,30 @@ static void sp_384_proj_to_affine_6(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_6(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_6(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -41364,14 +42184,14 @@ static int sp_384_gen_stripe_table_6(const sp_point_384* a, XMEMCPY(table[1].x, t->x, sizeof(table->x)); XMEMCPY(table[1].y, t->y, sizeof(table->y)); - for (i=1; i<8; i++) { - sp_384_proj_point_dbl_n_6(t, 48, tmp); + for (i=1; i<6; i++) { + sp_384_proj_point_dbl_n_6(t, 64, tmp); sp_384_proj_to_affine_6(t, tmp); XMEMCPY(table[1<x, sizeof(table->x)); XMEMCPY(table[1<y, sizeof(table->y)); } - for (i=1; i<8; i++) { + for (i=1; i<6; i++) { XMEMCPY(s1->x, table[1<x)); XMEMCPY(s1->y, table[1<y)); for (j=(1<y[3] = 0; r->y[4] = 0; r->y[5] = 0; - for (i = 1; i < 256; i++) { + for (i = 1; i < 64; i++) { mask = 0 - (i == idx); r->x[0] |= mask & table[i].x[0]; r->x[1] |= mask & table[i].x[1]; @@ -41438,8 +42260,10 @@ static void sp_384_get_entry_256_6(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -41453,17 +42277,19 @@ static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 6 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 6 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -41471,31 +42297,34 @@ static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_6(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 63; + for (j=0; j<6; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 64; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { - sp_384_get_entry_256_6(rt, table, y); + sp_384_get_entry_64_6(rt, table, y); } else #endif { @@ -41503,16 +42332,18 @@ static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); } rt->infinity = !y; - for (i=46; i>=0; i--) { + for (i=62; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<6; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 64; } sp_384_proj_point_dbl_6(rt, rt, t); #ifndef WC_NO_CACHE_RESISTANT if (ct) { - sp_384_get_entry_256_6(p, table, y); + sp_384_get_entry_64_6(p, table, y); } else #endif @@ -41532,32 +42363,41 @@ static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(rt, 0, heap); return err; } +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ #ifdef FP_ECC #ifndef FP_ENTRIES #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[6]; + /* Y ordinate of point that table was generated from. */ sp_digit y[6]; - sp_table_entry_384 table[256]; + /* Precomputation table for point. */ + sp_table_entry_384 table[64]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -41565,9 +42405,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -41673,6 +42519,407 @@ static int sp_384_ecc_mulmod_6(sp_point_384* r, const sp_point_384* g, const sp_ #endif } +#else +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 48 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_6(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; +#endif + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_6(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_6(t, 48, tmp); + sp_384_proj_to_affine_6(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_384_proj_point_add_qz1_6(t, s1, s2, tmp); + sp_384_proj_to_affine_6(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#ifndef WC_NO_CACHE_RESISTANT +/* Touch each possible entry that could be being copied. + * + * r Point to copy into. + * table Table - start of the entires to access + * idx Index of entry to retrieve. + */ +static void sp_384_get_entry_256_6(sp_point_384* r, + const sp_table_entry_384* table, int idx) +{ + int i; + sp_digit mask; + + r->x[0] = 0; + r->x[1] = 0; + r->x[2] = 0; + r->x[3] = 0; + r->x[4] = 0; + r->x[5] = 0; + r->y[0] = 0; + r->y[1] = 0; + r->y[2] = 0; + r->y[3] = 0; + r->y[4] = 0; + r->y[5] = 0; + for (i = 1; i < 256; i++) { + mask = 0 - (i == idx); + r->x[0] |= mask & table[i].x[0]; + r->x[1] |= mask & table[i].x[1]; + r->x[2] |= mask & table[i].x[2]; + r->x[3] |= mask & table[i].x[3]; + r->x[4] |= mask & table[i].x[4]; + r->x[5] |= mask & table[i].x[5]; + r->y[0] |= mask & table[i].y[0]; + r->y[1] |= mask & table[i].y[1]; + r->y[2] |= mask & table[i].y[2]; + r->y[3] |= mask & table[i].y[3]; + r->y[4] |= mask & table[i].y[4]; + r->y[5] |= mask & table[i].y[5]; + } +} +#endif /* !WC_NO_CACHE_RESISTANT */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 6 * 6]; +#endif + sp_point_384* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + x = 47; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 48; + } + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_256_6(rt, table, y); + } else + #endif + { + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + } + rt->infinity = !y; + for (i=46; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 48; + } + + sp_384_proj_point_dbl_6(rt, rt, t); + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_256_6(p, table, y); + } + else + #endif + { + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + } + p->infinity = !y; + sp_384_proj_point_add_qz1_6(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_6(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[6]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[6]; + /* Precomputation table for point. */ + sp_table_entry_384 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_384_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_6(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_6(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_win_add_sub_6(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 6 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_6(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_win_add_sub_6(r, g, k, map, ct, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_6(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif /* !WC_NO_CACHE_RESISTANT */ /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * @@ -41683,28 +42930,31 @@ static int sp_384_ecc_mulmod_6(sp_point_384* r, const sp_point_384* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[6]; +#endif int err = MP_OKAY; - err = sp_384_point_new_6(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 6, km); sp_384_point_from_ecc_point_6(point, gm); @@ -41715,16 +42965,450 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_6(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(point, 0, heap); return err; } +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[6 + 6 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (6 + 6 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 6; + + sp_384_from_mp(k, 6, km); + sp_384_point_from_ecc_point_6(point, gm); + sp_384_point_from_ecc_point_6(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_6(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_6(point, point, addP, tmp); + + if (map) { + sp_384_map_6(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +#ifndef WC_NO_CACHE_RESISTANT +/* Striping precomputation table. + * 6 points combined into a table of 64 points. + * Distance of 64 between points. + */ +static const sp_table_entry_384 p384_table[64] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x3dd0756649c0b528L,0x20e378e2a0d6ce38L,0x879c3afc541b4d6eL, + 0x6454868459a30effL,0x812ff723614ede2bL,0x4d3aadc2299e1513L }, + { 0x23043dad4b03a4feL,0xa1bfa8bf7bb4a9acL,0x8bade7562e83b050L, + 0xc6c3521968f4ffd9L,0xdd8002263969a840L,0x2b78abc25a15c5e9L } }, + /* 2 */ + { { 0xa54768dab1b43eefL,0x13e41f47e14fda22L,0x774df203faef6863L, + 0xf795a034bd7471b3L,0xf0958718b47de2e9L,0xc92f7888e1160cffL }, + { 0x86ded97b0146c790L,0x015918f5480a4b7bL,0x05588920424e8459L, + 0x37455914eecf8b2bL,0xe7d3df1fb968a6faL,0x07a0ffd6bad0719fL } }, + /* 3 */ + { { 0xda37cd535c54db6fL,0x0e37890a91f06c5cL,0x1730ef7be7ae7db5L, + 0x2b3dcd51ff045f54L,0xf5db3c3c72cc8451L,0x3165d6efcf0c185cL }, + { 0x177c4f6bf5958d78L,0xcb29d22f8d676a9fL,0x3bcf0068792ac96dL, + 0x60d1c6b719df5641L,0x426e412a68a099f8L,0xf9ca0c5c9f74d52bL } }, + /* 4 */ + { { 0xf186d6bcc88d568aL,0x872bc4c7528535ddL,0xc9e7432edfe64dc3L, + 0xd9fc4832d795ea57L,0xf4ffdb81c845af2bL,0x66d7e7882b670517L }, + { 0xa7c1be04d7b7a1c6L,0xbed88479d5b2a249L,0x62ff8aba03f2ef6dL, + 0x60ecaac420dc701dL,0x9f4b559f4ff10119L,0x0582c9313cd54fd0L } }, + /* 5 */ + { { 0x394fb84de86e3f64L,0xfe4a36e7ff13314eL,0xa1e44b14dc261ec2L, + 0x3924e50a7420408fL,0x637e330242ed7626L,0xeb657b10fd711ba4L }, + { 0xc16d01c5340949bbL,0x30e043267f1f42c7L,0xe7465819b056d872L, + 0x3386f1c6886fb3dbL,0x5be463a5be56f774L,0xa96fd3b74694e15aL } }, + /* 6 */ + { { 0x95dd5ee5a98b4254L,0xea328205aa845e67L,0x98640fb5a1e36348L, + 0xd1bc5c251add5ee7L,0xc3158a423d11b799L,0x5feb68ed47c83d54L }, + { 0x7c5a1204963a207bL,0x2f2b2c7eee4671f8L,0xb63d291cd42867a6L, + 0x0b073620139530f4L,0xbe149492abb05b99L,0x21417da455accd2aL } }, + /* 7 */ + { { 0x9408555e9e5eba15L,0x416250137b7572c5L,0xfa53ee50bfff6ea7L, + 0x3d682de1e7b178c3L,0xb3e8769dec329f53L,0x1ab8c82e9eb524f4L }, + { 0x5bbd538dde2f1eb9L,0x1d1b0bea2b19c51eL,0xf785f9b98cb06eeeL, + 0x5cff29c6f58f21d5L,0x44aaa52245cbaef3L,0xd60c19427de40246L } }, + /* 8 */ + { { 0x378205de2f9fbe67L,0xc4afcb837f728e44L,0xdbcec06c682e00f1L, + 0xf2a145c3114d5423L,0xa01d98747a52463eL,0xfc0935b17d717b0aL }, + { 0x9653bc4fd4d01f95L,0x9aa83ea89560ad34L,0xf77943dcaf8e3f3fL, + 0x70774a10e86fe16eL,0x6b62e6f1bf9ffdcfL,0x8a72f39e588745c9L } }, + /* 9 */ + { { 0x73ade4da2341c342L,0xdd326e54ea704422L,0x336c7d983741cef3L, + 0x1eafa00d59e61549L,0xcd3ed892bd9a3efdL,0x03faf26cc5c6c7e4L }, + { 0x087e2fcf3045f8acL,0x14a65532174f1e73L,0x2cf84f28fe0af9a7L, + 0xddfd7a842cdc935bL,0x4c0f117b6929c895L,0x356572d64c8bcfccL } }, + /* 10 */ + { { 0x984a6aed6420bc66L,0x6d90e0e0896a24a6L,0xe0adb93a18713003L, + 0xf00d424c1a8369fcL,0x636ebf14712ae802L,0xee39ff8ebe9d739aL }, + { 0xb330dd3e94f6d1dcL,0x6ba6780eb7731cf8L,0x4e569408198be5a2L, + 0x6639523b0193a22cL,0x6978cc9d91aa1455L,0x62062d8f329f9763L } }, + /* 11 */ + { { 0x7159107d80efff78L,0xf8ed5f8e8e4c39d5L,0x64a2265cc15e679cL, + 0xfc514e17a6d96c81L,0x59c86545f093e0a8L,0x804b0a588b5a336aL }, + { 0x94c32118cb9dcbcaL,0x2deb0e385d45251dL,0xd1092b0986869572L, + 0x073bf838fb2e9f97L,0x76b6d7d6de700fcbL,0xd2a6d110f2ddce5fL } }, + /* 12 */ + { { 0x6da7ccd0229de19eL,0x5050d45df0aa039dL,0xf9f01d68d9e7a861L, + 0x6d8b9f2000aa05f2L,0xae3d9698742cd4d9L,0x43e477abd560c394L }, + { 0x73d594991cb6dd81L,0x689162b2fac3f62eL,0xd6187ca864d1d0d5L, + 0xe8421a0d2f067457L,0x9b266acbea7c3a8dL,0x707e0e6e44df5cb3L } }, + /* 13 */ + { { 0x604b2a1a026511a0L,0xd4f6cf16256f4076L,0x7d823347b315a642L, + 0x8f805833786aa438L,0x9883df85f04bb4b3L,0x02bc10305bba6d84L }, + { 0xfe39a024a72c03acL,0xa980db635f2dbfd0L,0xcd53149f4f259ec6L, + 0xe969079b43f53f97L,0xd3849fdb42f9f27cL,0xd2cfd3f842653dc9L } }, + /* 14 */ + { { 0xbf69fe6a6abe7d80L,0x4932288192bb50e2L,0xc9e2f7fb61e8b18dL, + 0x24c74788f6c82421L,0xe79e5e3011c0b244L,0xd6612c70e0484571L }, + { 0x7863ff927ef82d17L,0x692790feb0a1b01cL,0xa2d6ffb5afe51546L, + 0xacdb43f26cf550c6L,0x3b3243dfaecfaf8fL,0x9557335ac233bcd9L } }, + /* 15 */ + { { 0x25e08c8faff5b387L,0x112c11e2d06208ceL,0x61031c1765234214L, + 0xba06f5550514764dL,0xfaacf6f39bd197d0L,0xe4b032321464a57fL }, + { 0x00c19adfe35dcd69L,0x81b75730a1c2646cL,0x47baa4fee0c50e32L, + 0xe9297832bcaddb3bL,0x1768d2f9d712c6cfL,0xfcef29fdb82e9eeaL } }, + /* 16 */ + { { 0xdbe04c3044ce3ad8L,0x995fbb1b4ce8aad5L,0xdbf8b54670911457L, + 0x9e683b5b3f7a1757L,0x7b89a08a9c7bd62cL,0x448865a40b3fc97eL }, + { 0x0ac9abfc3bb01e94L,0xa07760421e756124L,0x0aa6c335d9deed97L, + 0xe270580f72603e08L,0x70857a946c783bb2L,0xa0047774caa929aeL } }, + /* 17 */ + { { 0x56211190a353e889L,0x052917c3190eb198L,0xadfd85b03eee3d12L, + 0xde1d761779fd9c91L,0x05be51b7bf500159L,0x271f07178fcb87f1L }, + { 0x02673e273a75ac71L,0xb1b7246eda12da8dL,0xb25647928f5fb8c0L, + 0x0a22cbe1063b1d7fL,0xb0d7a7365649976eL,0x8f8e6e289e96b15dL } }, + /* 18 */ + { { 0x8fc113f98312351cL,0xe837b9e0c5eff002L,0x7cb9ef074dad72fcL, + 0x18a8d43eb5eb7ee3L,0x2cf3ae844925efdbL,0x376e9e857756ec6aL }, + { 0xf77a79c8a3e3705fL,0x2d590b7d6c5fbab3L,0xa59713e27a4766c3L, + 0xb5da6a6861544174L,0xadb04a8adab1fe76L,0x03b6138d375143b4L } }, + /* 19 */ + { { 0x20d88a80c1bfa043L,0x88806999672583ceL,0x195a89eaaea9b605L, + 0x0b9b4e8532bac07bL,0x8279965683868df6L,0x83c58afab52711a9L }, + { 0xb895c13d1c869283L,0x00f98d046206dde6L,0x76caaa22884bf311L, + 0x22b2137f995b29a5L,0x7f645809b098b07bL,0xa540c8a6050e2552L } }, + /* 20 */ + { { 0x47980509e562d904L,0xe736f89d031e112cL,0xbc6bfb0765d8ae25L, + 0xe9ed4cc4ca459646L,0xf540e90e2fff67ffL,0x836280eb1a314e11L }, + { 0xa710b25041610627L,0xefc22b1573a9f9a2L,0x60f20789456498c0L, + 0x417920438052f4e7L,0x5c850903d5c0e80dL,0x52df5275bf1d8815L } }, + /* 21 */ + { { 0x25539de98ece218dL,0xb36574a8dca420baL,0x9d1812680e0d07feL, + 0xea79a5f5ad3ed34fL,0x8b739ad57c9277cfL,0xd88659886ee9a930L }, + { 0xaf07bfb621591a3eL,0xe0138c6508f3524fL,0xd3128f1297ee315eL, + 0x67f8641e21045f63L,0x3e1a96b140c73a2dL,0x8976b70305f51122L } }, + /* 22 */ + { { 0xdeaf635731960db4L,0x680b054e5948d7f7L,0x0841e40fd272bb5cL, + 0x94d37db26e36117dL,0xaf2d001547f63ec8L,0x82665cdc47493309L }, + { 0xfe90e844abbe3851L,0x8357709afb79bc0cL,0x811a64d2b6bcc044L, + 0x1937c988882b3415L,0xe8b28724e267b271L,0x84d1eed0af89ed33L } }, + /* 23 */ + { { 0x52b8234f54c894a7L,0xfe54146fa2d11b70L,0x6412b5eb0aab6097L, + 0xa62499906a13a9daL,0xd2b1eb50adc448caL,0xe7ab51f9b115ab92L }, + { 0x4638ee62e76551d8L,0x74c3c1e1afe9c98dL,0x59000ad060d77322L, + 0x0a4b105ba06adc9aL,0xcdaeb4a496a6f616L,0x8c79c4a1864b49dcL } }, + /* 24 */ + { { 0xc09c32d1c0b1bf15L,0x005d510f88d74e44L,0x031f9a9afc2c089eL, + 0x08aac7294ba183f0L,0xf227a7ceaf2245ebL,0xb4ec33cbb3a864ffL }, + { 0xdb76decd570a24f3L,0xea59387a12283a9eL,0x81b7c569341ef9a4L, + 0xad7c98bd8d77833aL,0x2182133b49ca80ffL,0x1de1d456085802b7L } }, + /* 25 */ + { { 0xeead25b2e1c02860L,0xb2ae43694ff42d2eL,0x4b39a2ddfd61c1b0L, + 0x29c826ea968718a5L,0x877fdf15d9751a0aL,0x00b321dfb54affdfL }, + { 0x3c7c0778d4d5dbf7L,0x858a0fdccfc47423L,0xbd8e6544185b3063L, + 0xa22c3ef62da46a04L,0x5c2d84016a6c0ce1L,0x260246eddd6329aeL } }, + /* 26 */ + { { 0x71753fc00c6463f6L,0x7ec14c015c6c9e33L,0x28b9ab9441ce6153L, + 0x3a1ac251a6702c8dL,0x2b124bc49ed6cb1fL,0x7a11c4be4fc7383fL }, + { 0x1414913509fac991L,0xf7c188d3cb1ee336L,0x754bc47391c3f406L, + 0x71d34587cad39500L,0x213dd1a7dd0399a1L,0x8457a8f671d05899L } }, + /* 27 */ + { { 0xa921ca662e9c06d3L,0x1d8974e89ba6521fL,0xbb465c775f79f791L, + 0x8f983f083a3954c8L,0x8492f8398b3935dcL,0x2b87d9c290c04426L }, + { 0xcec76ea403e60a28L,0x648e9830aa631308L,0x7b542f791eb86b73L, + 0xfc8cc9a3150d854dL,0x2be86940bfcc83feL,0x2e58a13ac88c7585L } }, + /* 28 */ + { { 0x19249a8fd1bc237fL,0xdec1c6a563505555L,0xc8256977bad2a93bL, + 0x78533659fc598170L,0x888a6578ee7e53cbL,0x28783b0e33766db3L }, + { 0xcf791e56e42c28f2L,0xfbf8dde8f9c37f4cL,0xf0ffaf1712c05395L, + 0xd27d21e9daf2f012L,0xf90432da9a7be009L,0xa459c036a8012f28L } }, + /* 29 */ + { { 0x4d99a7cac8b1c6d4L,0x8088818825c899c0L,0xbd27e9be2ebdeb3dL, + 0x73c3e0aa054e77c1L,0x180c848498534ce5L,0x750d52f754ffa9cdL }, + { 0x5f26eeb16f702f4cL,0x427fc6e4cc76d8f4L,0x93126b8d026b631dL, + 0x5356b93917e145a7L,0xc79ca872c0be7c84L,0x3fca7cad4b615fb7L } }, + /* 30 */ + { { 0xed48fe78d0241021L,0x252b14a0142f7f8eL,0x19ab85c6db573a09L, + 0x546c3960f3df906fL,0xc688f4b22c810ea8L,0xbccf0cca5ff9e108L }, + { 0x34f4609e3f2cc69bL,0xf3b1efe414afe4f4L,0x5d809cef37a8ef74L, + 0xa8d1978a176ba328L,0x75dde11fdf59ecb9L,0x34eeeaffa9916ee2L } }, + /* 31 */ + { { 0xe7f603f248e83c85L,0xa94a539cfa581815L,0x5a61a596dba360b7L, + 0x6cc51dd16a77ef79L,0x4ff36ae0fdbceb9dL,0xfcff65323e8a9c07L }, + { 0x0ba0ce5436d4d0b8L,0x98087a452464efc2L,0xd456843bcc1a2ba7L, + 0x677384a53853e04cL,0x625d32d56c7971deL,0x86882509f724b331L } }, + /* 32 */ + { { 0xc20fb9111a42e5e7L,0x075a678b81d12863L,0x12bcbc6a5cc0aa89L, + 0x5279c6ab4fb9f01eL,0xbc8e178911ae1b89L,0xae74a706c290003cL }, + { 0x9949d6ec79df3f45L,0xba18e26296c8d37fL,0x68de6ee2dd2275bfL, + 0xa9e4fff8c419f1d5L,0xbc759ca4a52b5a40L,0xff18cbd863b0996dL } }, + /* 33 */ + { { 0x684a681892a5eeeaL,0x1f5b193242a09264L,0x30bd8695d98a2f34L, + 0x6e775e019a8601fcL,0x8126bdc24ca956f8L,0x149e73d9e5595daaL }, + { 0x876428401f851e83L,0x4b8863dbd3a7c4a0L,0xe1e43b3d8c95d7d9L, + 0x7f1e307ea60fd528L,0xbf2fa5d134341610L,0x11ad4a8181c502d3L } }, + /* 34 */ + { { 0xc7df022e782dd401L,0xd15aa9a9a7bcc543L,0x6aa42774b94df1d0L, + 0xab2660c30592a13eL,0xaf4e40809ffc40c7L,0x01152c8d9cd52b10L }, + { 0x649de1d99034a33aL,0x2b9d0ef0d758abfcL,0xdddd0bc2d458adddL, + 0xe5366ac9c09837f8L,0xa003abbb7b1ae35fL,0x880062887ab1fddeL } }, + /* 35 */ + { { 0x6b6c8f055288f1b4L,0xba05407c033738b4L,0x26cac3a941a955e3L, + 0x28f1692f8e0e0601L,0x2032cb36842c4887L,0x6adeba457d76b20fL }, + { 0xd282c2ce654c6f5cL,0x30584ca5be9ba4f1L,0x45d766a01b2c528bL, + 0xe918bad7c0c6f8ccL,0x1e050b2a0560f070L,0x4fc95de12d6dd010L } }, + /* 36 */ + { { 0x2bb26072150191d5L,0xea2617618108dcf6L,0x4dfa1303e6083c63L, + 0xfa4e0709e2876fb8L,0xf901fed0b1668763L,0xf01c53aeb82c967aL }, + { 0xb43e59d39ed827e8L,0xb58e157e57774eefL,0x57ee54e31b83dceeL, + 0x3d896f32613aa922L,0x69d40667b5c7bfc5L,0xd402b5cb77a2c0d8L } }, + /* 37 */ + { { 0xabeb70127d3c9923L,0x412ada8dd7ecb93aL,0xeb64dc910b71ae2fL, + 0x52ef537aa9ab061aL,0x0863970fc1b55faeL,0xfaff5fb9b1182dbdL }, + { 0x5551d6fed0abaa17L,0x7bb3e02072d641f6L,0x939d7793aa9d288cL, + 0x1450f8bf9078e2c2L,0x24ccd102a086b6aeL,0x57d1796f6a3f8a5fL } }, + /* 38 */ + { { 0x1023120683ce1f76L,0xd16d4b9f03ee406fL,0x9d39c39883caa4b7L, + 0x875732f5ce299b93L,0x1e6a425d2f121f4aL,0x4b1f1d835d8c3279L }, + { 0xe655f58856dd6a6cL,0x23f106475843fd34L,0x932b7d942bad6ce2L, + 0x70a0580e6772a52eL,0x3240118ac88537afL,0x9ccb2ca9d2407224L } }, + /* 39 */ + { { 0xa6a40db8710f2324L,0xb3567518c2a8a09aL,0x8816442841b5650aL, + 0x2a352ed27570ba50L,0x23ee46b94c85d77eL,0x643aceffd858a8c3L }, + { 0xe067908de3f02e82L,0x8d5869f2ffb8cf81L,0x4713f0820bc8ad7eL, + 0xe1ee44c780057c40L,0xb34395087d2cf34eL,0x4307b0e10336a207L } }, + /* 40 */ + { { 0xe9c1e45746e4d003L,0xa23978c394332057L,0x0e2f300829575db6L, + 0x50a51ff490441e9eL,0x38ce3ed0508d4a07L,0x6a997411cfd7224eL }, + { 0x4d147c31da6b1e1dL,0xedf604b2da8a3547L,0x7a1b8cf0d5e9ceedL, + 0xd74e501213544e6aL,0xcc49f8da4ad968f9L,0xfb87e604cc69ada9L } }, + /* 41 */ + { { 0xde79409bdf166882L,0xd645b836d46cc527L,0xda4a02f3b6c3eb28L, + 0x845e3c5900e7cf86L,0x733bdc9b604c6d80L,0xe3a1244b847acd97L }, + { 0x421312d6d128842cL,0x81f71feaa1c598efL,0xc619465545eaf796L, + 0x1ffb85121f338b6cL,0xe7aed7106632f064L,0xf8d1ffb7f5b6e510L } }, + /* 42 */ + { { 0x7d3f031f3eace851L,0xef43ab7025923624L,0xbae811881af6cdecL, + 0xb7e93b49ea862112L,0xe35a4fc6af23aba2L,0xc52e1fc0aecc593eL }, + { 0xbffa292428148b99L,0xd08040fc89e3d795L,0x7da320032db47b3aL, + 0xe78b44e5a0eb7aa3L,0xd1648ec8f0ec090bL,0x4048dba7740fe871L } }, + /* 43 */ + { { 0x6fddb89fa00a14acL,0x844f991508aa06e7L,0x6d5ac4a9f76aca7dL, + 0xfba1ba85e9fa4d51L,0x159633bbb2ea0fc7L,0xa2eb0e4b76ba2854L }, + { 0x8a858155c11f5398L,0x30a96e535e8ea044L,0x696210c197e05a47L, + 0x86e55f9415036f4bL,0x0c93ea9c6a96d9d7L,0xb7ba506179eba3daL } }, + /* 44 */ + { { 0xd305c733cd94d7b2L,0x9ea33e363e7955b2L,0x78a98855bc73812fL, + 0xfb1b791d48a3a9a0L,0x6e5107ee04014aafL,0x0412b2c00ea07de0L }, + { 0xdd3a2408ddcaca68L,0x5d18e69ae3344f29L,0x3ce65481f9017408L, + 0x50abb4568cbd64fbL,0x442fa5098916a9ebL,0x16b3ddc7c538c410L } }, + /* 45 */ + { { 0x6757dbfd25e331abL,0x0efde50ba3eaafbcL,0x1cd46222d531d29cL, + 0x1b713ca93561cb2bL,0x7d07334bfb5bc99dL,0x95dba43e885a417dL }, + { 0x1c9c3f3f77823a59L,0x43533ba83220cb7fL,0x1b918bc182e3e401L, + 0x66a039aacd3fec87L,0x1d39dbb02dad36d5L,0x554025959dc04be4L } }, + /* 46 */ + { { 0xdf39920847744933L,0x4264f7ea82524dd6L,0xdb57ec08e5182c6dL, + 0x2d6778e705c5e7bfL,0x3f37793f96f53ea2L,0x6472cbae05c47e48L }, + { 0x9e6dd60fbf78067cL,0xa2817ec2cef34088L,0xde4715b8168edde9L, + 0x6c57105146bf31e1L,0x98113fbbc4272bc0L,0x03bb7922cc3b90c3L } }, + /* 47 */ + { { 0xe0f23be157d88fefL,0x4125c55b0ca27a01L,0xeadf527e14a71262L, + 0x1f2e803ccc4e9a04L,0x32e07b47d68c4fcfL,0x1577fab79db5070bL }, + { 0xd786d6e57831990aL,0xf64ff4b154fbde40L,0x4bac5b034f9450aeL, + 0x06ae25e055116af9L,0x33d84ea2d7b4fcfcL,0x44a92e73569c3b9eL } }, + /* 48 */ + { { 0xf5bdccbabad0cb7fL,0x370f43ca958edd05L,0x3dd8232b04904a26L, + 0x3f8106682f4458e8L,0xdfcb67b99b3ace7eL,0x54e42f2d3e1241fcL }, + { 0xe30f3fb0db889300L,0x4ca0184b483e51fcL,0x5a32d097a638dac6L, + 0x567a2b5ec62a1db0L,0x2a756ba3c446456cL,0x6919026dd9f8d5c0L } }, + /* 49 */ + { { 0x7f6493fc4fec874aL,0x8bb8a674d47a0770L,0x90bad2a652bd4f0cL, + 0x16badbe2f5733b07L,0x93be07cf93a1f802L,0x1e37a01541c395f7L }, + { 0xfe2c0fd6216582b3L,0xdcd98bc81627180dL,0x41e037268e8c9f1eL, + 0x93dbc22cfe8f45afL,0x5728c8a6ff45e059L,0x4f2f15cfca4a98cdL } }, + /* 50 */ + { { 0xdbe2ec5d656e7d76L,0x84ad1b4bae2757bbL,0xc9297e7a0d4fec75L, + 0xfcc673eecad3ba87L,0xb0f77621dfd1671aL,0x5c386e449704a8c7L }, + { 0xce78f03f3e29256dL,0x0b185938c3a6ed2fL,0x7b1e2fae7824819bL, + 0x5a85d7f1f2d9313cL,0x238bd27973595b0fL,0x5fbf6b675c1cd2dcL } }, + /* 51 */ + { { 0x84d1ffb88a3e2412L,0xf01605926515f2feL,0x0e26ea9889905340L, + 0xbfd7a1b7203bd3d4L,0x5301273a88ea0bdaL,0x2f424475b28dd43eL }, + { 0x31014a2b33c28afaL,0xffbdea0c01e220eaL,0x681c64e8460b81d5L, + 0xdbe6f7286a91e1d5L,0x068bf36332619ad5L,0x4946291f27976c74L } }, + /* 52 */ + { { 0xa081a9462068e4b0L,0x1a8f5df609bfdad0L,0x5fbba5bcef28dd35L, + 0xa3e60d4f031ff71eL,0x2d47689b702ca18eL,0xd283f247c9b8e66bL }, + { 0x63e65dd7859ea140L,0x123da61f42aacdc3L,0xa8a9e893336f680cL, + 0x1cc4e12ac23d43acL,0x421e80d586a1fff8L,0x833d60d543deecc9L } }, + /* 53 */ + { { 0x3c25b57c29014f8fL,0xa19fcb1e35d8e122L,0x916c0e3ceda32ac8L, + 0x9a23d289f36b6096L,0x5099038439a39871L,0xdc5b77b661c64196L }, + { 0x5a7d9917942bf2b6L,0xd21853934f41cf6dL,0x90ff1016fcc45c2fL, + 0x9891093deb8938aaL,0xe3c49b1baac4e6e9L,0x0f21a1d1d7a8e91eL } }, + /* 54 */ + { { 0x3a808e336f364b7eL,0x6a96d1b8bfa17359L,0x3387ec8552b36545L, + 0x2fde350af712180cL,0x9219d6f4703a2183L,0x8ba27e0086457946L }, + { 0x7446bca0ed80a9afL,0xbaf78b6f7203637aL,0x0304129d497c9d0fL, + 0x6df1e0356a883b68L,0x93ea2bb5e8018c47L,0xc86fd77cdb46443cL } }, + /* 55 */ + { { 0x8de865d255dc2427L,0x74f7f83d6f72d126L,0xee1111786c7e665aL, + 0x272a8b3dddf44f12L,0xad3546449164eb4fL,0x2ffbdb586859d68fL }, + { 0xbefd36c509701865L,0x63c256162c983d01L,0x15a7ba0b2eb68703L, + 0x3318a82b5bb0fafcL,0x8e930fa9a0804f38L,0xb7459eb6be60ed1dL } }, + /* 56 */ + { { 0xace01c514260b948L,0x04a6080f49210f78L,0x0d1eef6b2241b00dL, + 0x85a25069ef63912aL,0xcc96c4ec13dd8bc2L,0x90f14d1140d7e234L }, + { 0xae33f18ca69c8dc3L,0x76921f2a9adfa431L,0x18158ccf048c9f49L, + 0x90bcf7fbfb8fb345L,0x0d50b4dc38b3ff5dL,0x3914ea0b59ef84a8L } }, + /* 57 */ + { { 0x4929d3f9d4e37cf3L,0x622183d1b24c24c0L,0x65cec0675f904d34L, + 0x65f9931a8a6f76faL,0xeed975b0e73282f2L,0xa045552a5e1625fdL }, + { 0xfd6b3e02f8fe8e42L,0x5f9f40256203907cL,0x8307eedb42b2c264L, + 0x2fb3ee719f757e92L,0x4502f2ecdc157ea8L,0xd976e7755d1cc0d5L } }, + /* 58 */ + { { 0xe46fb9a28fe1946eL,0xe91df3ed63bdde6eL,0x2e995306e9c28432L, + 0x7b3a6fe10988235bL,0xc55199f077f92a71L,0x47dd034853cb7950L }, + { 0xead52de2b727a6d1L,0xb87c9f75eea9c8daL,0xf3e2f3280d944f21L, + 0xce82734edd751eddL,0xfb83225ce616cedcL,0x15850e4b4a31eb49L } }, + /* 59 */ + { { 0x92c4b6d50196ad3aL,0x0205ea484e1205e4L,0x8e08a97c0afc5affL, + 0xda8687c6727827ebL,0x2eace83106e398aaL,0x3a086c0f6d69e4e8L }, + { 0x5ff9b7aaf286e62aL,0xc428503962aae55eL,0x4ebd4258d9530a3fL, + 0x57ea313a8afc7fcbL,0x6d30a67522c18879L,0xd3c00cc994afb659L } }, + /* 60 */ + { { 0x53ee47c5dee0d48bL,0xbd9e84ad9dfa2397L,0x2d581e12f81ba5e2L, + 0x26269f4f132cd325L,0x9e6224df58860a5fL,0x9306c607ff55522aL }, + { 0xb48af6d4146950e5L,0x09920ed00436805eL,0x3a1bc276cdce7eaeL, + 0x55ba728ac39a425eL,0x6a04d4e6d961d03eL,0x13891c66736e684aL } }, + /* 61 */ + { { 0x7c75175a04cd04d6L,0xb76f9bd909c27a17L,0xa0cff6d408e5fe36L, + 0xc9097695dcd5ef90L,0x26bea24585e28054L,0x658e03c61580f068L }, + { 0x0da9f75e811eed27L,0x086e5e04aca0d2eeL,0xd4c157faa53a6787L, + 0x2e9266d2b40a595cL,0x8f1cb52698fa0820L,0x32a74240a1aef514L } }, + /* 62 */ + { { 0xeb42e3d91ae86e7cL,0xd6956c8ce04a5026L,0x4c0b8b980f4302ebL, + 0xde43c938b37211fdL,0x9fa6a158e7090f80L,0x5f3c9afc73c47fb6L }, + { 0x2dc4f109f850a4d0L,0x56e63a4b6fd49d6aL,0x8e80a0694cbff048L, + 0x18d8b8cf2284afb0L,0x61dd086dc89363a1L,0x034c2202c37342a4L } }, + /* 63 */ + { { 0x1ae0c4e11c718580L,0x303f48a6bf99a0bfL,0xa5551e4491ae219fL, + 0xdc41d9bd55a05287L,0xd5aa73e36872b123L,0x6fd94b0ce6395bf6L }, + { 0xbb95fdbac00afbc1L,0x9cd96208497cac10L,0x8adbd8c1ca51afeaL, + 0x94fedafbf3bc5f5fL,0x29c0217bdf9f5371L,0x5c13eb4bd9024634L } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_384_ecc_mulmod_stripe_6(r, &p384_base, p384_table, + k, map, ct, heap); +} + +#else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 48 between points. + */ static const sp_table_entry_384 p384_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -43009,6 +44693,11 @@ static const sp_table_entry_384 p384_table[256] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -43023,6 +44712,18023 @@ static int sp_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, k, map, ct, heap); } +#endif /* WC_NO_CACHE_RESISTANT */ +#else +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_6_7[130] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static const uint8_t recode_neg_6_7[130] = { + 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, 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, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to perform. + */ +static void sp_384_ecc_recode_7_6(const sp_digit* k, ecc_recode_384* v) +{ + int i; + int j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<55; i++) { + y = (int8_t)n; + if (o + 7 < 64) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 64) { + n >>= 7; + if (++j < 6) + n = k[j]; + o = 0; + } + else if (++j < 6) { + n = k[j]; + y |= (uint8_t)((n << (64 - o)) & 0x7f); + o -= 57; + n >>= o; + } + + y += (uint8_t)carry; + v[i].i = recode_index_6_7[y]; + v[i].neg = recode_neg_6_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +#ifndef WC_NO_CACHE_RESISTANT +/* Touch each possible entry that could be being copied. + * + * r Point to copy into. + * table Table - start of the entires to access + * idx Index of entry to retrieve. + */ +static void sp_384_get_entry_65_6(sp_point_384* r, + const sp_table_entry_384* table, int idx) +{ + int i; + sp_digit mask; + + r->x[0] = 0; + r->x[1] = 0; + r->x[2] = 0; + r->x[3] = 0; + r->x[4] = 0; + r->x[5] = 0; + r->y[0] = 0; + r->y[1] = 0; + r->y[2] = 0; + r->y[3] = 0; + r->y[4] = 0; + r->y[5] = 0; + for (i = 1; i < 65; i++) { + mask = 0 - (i == idx); + r->x[0] |= mask & table[i].x[0]; + r->x[1] |= mask & table[i].x[1]; + r->x[2] |= mask & table[i].x[2]; + r->x[3] |= mask & table[i].x[3]; + r->x[4] |= mask & table[i].x[4]; + r->x[5] |= mask & table[i].x[5]; + r->y[0] |= mask & table[i].y[0]; + r->y[1] |= mask & table[i].y[1]; + r->y[2] |= mask & table[i].y[2]; + r->y[3] |= mask & table[i].y[3]; + r->y[4] |= mask & table[i].y[4]; + r->y[5] |= mask & table[i].y[5]; + } +} +#endif /* !WC_NO_CACHE_RESISTANT */ +static const sp_table_entry_384 p384_table[3575] = { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 0 */ + { { 0x3dd0756649c0b528L,0x20e378e2a0d6ce38L,0x879c3afc541b4d6eL, + 0x6454868459a30effL,0x812ff723614ede2bL,0x4d3aadc2299e1513L }, + { 0x23043dad4b03a4feL,0xa1bfa8bf7bb4a9acL,0x8bade7562e83b050L, + 0xc6c3521968f4ffd9L,0xdd8002263969a840L,0x2b78abc25a15c5e9L } }, + /* 2 << 0 */ + { { 0xc8229e55783dde91L,0x8e6c8f2e022b53f0L,0x3504e6f0ff9d48a1L, + 0xda821495f0687f50L,0x9c90a4fd2de4b506L,0xdb93b776427460c3L }, + { 0x42ea84633140bfdaL,0xe8e8e4a8c2aaccd8L,0x15e4f18bdc588258L, + 0x09f1fe415172bad9L,0x070d430900b0e684L,0xe34947f7123df0c2L } }, + /* 3 << 0 */ + { { 0x05e4dbe6c1dc4073L,0xc54ea9fff04f779cL,0x6b2034e9a170ccf0L, + 0x3a48d732d51c6c3eL,0xe36f7e2d263aa470L,0xd283fe68e7c1c3acL }, + { 0x7e284821c04ee157L,0x92d789a77ae0e36dL,0x132663c04ef67446L, + 0x68012d5ad2e1d0b4L,0xf6db68b15102b339L,0x465465fc983292afL } }, + /* 4 << 0 */ + { { 0x0aae8477ebb68f2cL,0x30594ccbee0421e3L,0x2e4f153b0aecac46L, + 0x078358d4736400adL,0xfb40f647d685d979L,0xcfeee6dd34179228L }, + { 0x54f3e8e79b3a03b2L,0xe74bb7f17bfec97eL,0x8e3e61a34c542ad1L, + 0x147162d30418c693L,0xe607b9e33820017dL,0x50946875303df319L } }, + /* 5 << 0 */ + { { 0xbb595eba68f1f0dfL,0xc185c0cbcc873466L,0x7f1eb1b5293c703bL, + 0x60db2cf5aacc05e6L,0xc676b987e2e8e4c6L,0xe1bb26b11d178ffbL }, + { 0x2b694ba07073fa21L,0x22c16e2e72f34566L,0x80b61b3101c35b99L, + 0x4b237faf982c0411L,0xe6c5944024de236dL,0x4db1c9d6e209e4a3L } }, + /* 6 << 0 */ + { { 0x7eb5c9317d56dad8L,0xcb2454b339d3413aL,0xec52930f580d57f2L, + 0x2a33f6661bdf6015L,0x4f0f6a962b02d33bL,0xc482e189f0430c40L }, + { 0x3f62b16ea7b08203L,0x739ac69d5b3d4dceL,0x8bd4bffcb79e33b0L, + 0x93c9e5f61b546f05L,0x586d8ededf21559aL,0xc9962152af2a9ebaL } }, + /* 7 << 0 */ + { { 0xdf13b9d17d69222bL,0x4ce6415f874774b1L,0x731edcf8211faa95L, + 0x5f4215d1659753edL,0xf893db589db2df55L,0x932c9f811c89025bL }, + { 0x0996b2207706a61eL,0x135349d5a8641c79L,0x65aad76f50130844L, + 0x0ff37c0401fff780L,0xf57f238e693b0706L,0xd90a16b6af6c9b3eL } }, + /* 8 << 0 */ + { { 0x23f60a05dd9bcbbaL,0x9e336de5ae9b587aL,0x1c5c2e7193d7e30fL, + 0x1d9aebd64f3ddb37L,0x1c7b5fe116b66423L,0x5db4f184349cd9b1L }, + { 0x0d2cfe83e6655a44L,0x836dbb36b7e55e87L,0x701754bf7d8686e4L, + 0xe9923263a42dbba2L,0x7008d943c48ecf0eL,0x3c0c6dd70d27ef61L } }, + /* 9 << 0 */ + { { 0x2f5d200e2353b92fL,0xe35d87293fd7e4f9L,0x26094833a96d745dL, + 0xdc351dc13cbfff3fL,0x26d464c6dad54d6aL,0x5cab1d1d53636c6aL }, + { 0xf2813072b18ec0b0L,0x3777e270d742aa2fL,0x27f061c7033ca7c2L, + 0xa6ecaccc68ead0d8L,0x7d9429f4ee69a754L,0xe770633431e8f5c6L } }, + /* 10 << 0 */ + { { 0x845539d3c8d99c02L,0x2a15a9a6e58d6787L,0xe9f6368eab225fa3L, + 0x54a612d7eb32cabeL,0xc2f646025c4845ecL,0xa91a5280db1c212eL }, + { 0xbb971f78e67b5fceL,0x03a530eb13b9e85cL,0x592ac0ba794eabfdL, + 0x81961b8ccfd7fd1dL,0x3e03370a47a9b8aaL,0x6eb995bec80174e8L } }, + /* 11 << 0 */ + { { 0xc7708b19b68b8c7dL,0x4532077c44377abaL,0x0dcc67706cdad64fL, + 0x01b8bf56147b6602L,0xf8d89885f0561d79L,0x9c19e9fc7ba9c437L }, + { 0x764eb146bdc4ba25L,0x604fe46bac144b83L,0x3ce813298a77e780L, + 0x2e070f36fe9e682eL,0x41821d0c3a53287aL,0x9aa62f9f3533f918L } }, + /* 12 << 0 */ + { { 0x3db8477270313de0L,0xd4258cc55d970420L,0x03aced26c8edfee1L, + 0xf67eb42235d77d83L,0x523c40dbcf9ab45cL,0x627b415f9c35b26dL }, + { 0xfacc45e48be55ed8L,0x80d60af627aa651aL,0x8c79848fd0e102acL, + 0x40c64a4e66bed5afL,0x0329eab1f7942f0eL,0x0c6e430ef9c4af3dL } }, + /* 13 << 0 */ + { { 0x9b7aeb7e75ccbdfbL,0xb25e28c5f6749a95L,0x8a7a8e4633b7d4aeL, + 0xdb5203a8d9c1bd56L,0xd2657265ed22df97L,0xb51c56e18cf23c94L }, + { 0xf4d394596c3d812dL,0xd8e88f1a87cae0c2L,0x789a2a48cf4d0fe3L, + 0xb7feac2dfec38d60L,0x81fdbd1c3b490ec3L,0x4617adb7cc6979e1L } }, + /* 14 << 0 */ + { { 0x5865e5018f75244cL,0xd02225fb01ec909fL,0xca6b1af8b1f85c2aL, + 0x44ce05ff88957166L,0x8058994c5710c0c9L,0x46d227c432f6b1baL }, + { 0xbe4b4a9003cb68e5L,0x540b8b82730a99d1L,0x1ecc8585e11dbbbfL, + 0x72445345d9c3b691L,0x647d24db13690a74L,0x4429839ddefbadf5L } }, + /* 15 << 0 */ + { { 0x446ad8884709f4a9L,0x2b7210e2ec3dabd8L,0x83ccf19550e07b34L, + 0x59500917789b3075L,0x0fc01fd4eb085993L,0xfb62d26f4903026bL }, + { 0x2309cc9d6fe989bbL,0x61609cbd144bd586L,0x4b23d3a0de06610cL, + 0xdddc2866d898f470L,0x8733fc41400c5797L,0x5a68c6fed0bc2716L } }, + /* 16 << 0 */ + { { 0xda6e8a7f7c33ed91L,0x992afb5b0ecdd2d8L,0x37cf65517917652aL, + 0x317b63ea2887d5ffL,0x37065f5313bdc3faL,0xa10896aa435abaa1L }, + { 0x9b21615fefabca26L,0xeb07ddea230cf00dL,0x914871dc154d410fL, + 0xb333bdfbc88ee148L,0x51c305c6a72d1967L,0x659db48181ef2513L } }, + /* 17 << 0 */ + { { 0x8903e1304b4a3cd0L,0x3ea4ea4c8ff1f43eL,0xe6fc3f2af655a10dL, + 0x7be3737d524ffefcL,0x9f6928555330455eL,0x524f166ee475ce70L }, + { 0x3fcc69cd6c12f055L,0x4e23b6ffd5b9c0daL,0x49ce6993336bf183L, + 0xf87d6d854a54504aL,0x25eb5df1b3c2677aL,0xac37986f55b164c9L } }, + /* 18 << 0 */ + { { 0x5dfee73ce5b82700L,0x198fd3f0f38f6662L,0x3bd1c8f62edb0dbdL, + 0x55a96a6879909f08L,0x68a2324355671693L,0x57505d8d67497030L }, + { 0x8a60717f75c64513L,0x54b867b7f78aa7deL,0xc266eb8441129858L, + 0x6ffcfc7ca4cfd9bbL,0x9bdd6a092945a757L,0x91700b247eb1be63L } }, + /* 19 << 0 */ + { { 0x82a2ed4abaa84c08L,0x22c4cc5f41a8c912L,0xca109c3b154aad5eL, + 0x23891298fc38538eL,0xb3b6639c539802aeL,0xfa0f1f450390d706L }, + { 0x46b78e5db0dc21d0L,0xa8c72d3cc3da2eacL,0x9170b3786ff2f643L, + 0x3f5a799bb67f30c3L,0x15d1dc778264b672L,0xa1d47b23e9577764L } }, + /* 20 << 0 */ + { { 0xad610a2d94a70ec1L,0xcd96f20591e71d16L,0x713466708cbaffc7L, + 0xf78cff0cd467f03aL,0x98ca8dd42d96c936L,0x1d1cdf7b5f223465L }, + { 0xe27a189460d4db60L,0x25f546ab321828ffL,0x9933fb25dccd4df3L, + 0x422da643ffe6132bL,0x5e01b72b4718bbc7L,0xab9dd81052ebfb01L } }, + /* 21 << 0 */ + { { 0x08265e510422ce2fL,0x88e0d496dd2f9e21L,0x30128aa06177f75dL, + 0x2e59ab62bd9ebe69L,0x1b1a0f6c5df0e537L,0xab16c626dac012b5L }, + { 0x8014214b008c5de7L,0xaa740a9e38f17beaL,0x262ebb498a149098L, + 0xb454111e8527cd59L,0x266ad15aacea5817L,0x21824f411353ccbaL } }, + /* 22 << 0 */ + { { 0x4f595351262bb775L,0x981b788d16f325b8L,0xccd57831927ed783L, + 0xc382472ebe0e1fdbL,0xfd7a8b13f0681fcaL,0xe082882d69059095L }, + { 0x4d1c3049faa71fdcL,0xf9d62fd9c9576c69L,0x7b1ab489cbf837b7L, + 0xc764edf840d0fcf7L,0x50fc847215809cddL,0x671d69c98fcd8418L } }, + /* 23 << 0 */ + { { 0xd1b4e74d12e3683bL,0x990ed20b569b8ef6L,0xb9d3dd25429c0a18L, + 0x1c75b8ab2a351783L,0x61e4ca2b905432f0L,0x80826a69eea8f224L }, + { 0x7fc33a6bec52abadL,0x0bcca3f0a65e4813L,0x7ad8a132a527cebeL, + 0xf0138950eaf22c7eL,0x282d2437566718c1L,0x9dfccb0de2212559L } }, + /* 24 << 0 */ + { { 0x259f272cfab816a7L,0x20c1b8e0d809afcdL,0x540c045a409c930bL, + 0x563361909bd5c2f7L,0x38076e8fca77d74fL,0x4f13f901fc55723fL }, + { 0x890932d7bd3d10c3L,0x98d82ad1da247ec8L,0xdf5579fa4bea82ddL, + 0xe8277439a0f9ad3aL,0x1395a87966a4e904L,0x150808e625a302c9L } }, + /* 25 << 0 */ + { { 0x1e93722758ce3b83L,0xbb280dfa3cb3fb36L,0x57d0f3d2e2be174aL, + 0x9bd51b99208abe1eL,0x3809ab50de248024L,0xc29c6e2ca5bb7331L }, + { 0x9944fd2e61124f05L,0x83ccbc4e9009e391L,0x01628f059424a3ccL, + 0xd6a2f51dea8e4344L,0xda3e1a3d4cebc96eL,0x1fe6fb42e97809dcL } }, + /* 26 << 0 */ + { { 0x6423197d2afd473dL,0xb0391b37897b93f5L,0x6efedb8023bf0b90L, + 0x808497b7b0bba4a7L,0xf14b309f03fa90f2L,0x37a45bdb091cbb80L }, + { 0xedda4ae48a8f5dcbL,0xdb3f422d95e16d6eL,0x25c7b9146f5f24c7L, + 0x5d512df99d42a727L,0xbf2c0862697c08fdL,0x47d98a9df092241cL } }, + /* 27 << 0 */ + { { 0xa04482d2467d66e4L,0xcf1912934d78291dL,0x8e0d4168482396f9L, + 0x7228e2d5d18f14d0L,0x2f7e8d509c6a58feL,0xe8ca780e373e5aecL }, + { 0x42aad1d61b68e9f8L,0x58a6d7f569e2f8f4L,0xd779adfe31da1beaL, + 0x7d26540638c85a85L,0x67e67195d44d3cdfL,0x17820a0bc5134ed7L } }, + /* 28 << 0 */ + { { 0xc76afaa373b64643L,0x4169b4117b3c1220L,0x550e0bee8ff22c6fL, + 0x8fb0c597a4da3e15L,0xd8232f8b4e492aa8L,0x55be5764d37da1a2L }, + { 0xf1bc89b628e77f9eL,0x9ff769c4875fee0fL,0x184bd4733ad6983aL, + 0xc48ee6f3b033c112L,0x792377fbf8eb8319L,0x05cdca3fe7988176L } }, + /* 29 << 0 */ + { { 0x019d6ac5d3021470L,0x25846b66780443d6L,0xce3c15ed55c97647L, + 0x3dc22d490e3feb0fL,0x2065b7cba7df26e4L,0xc8b00ae8187cea1fL }, + { 0x1a5284a0865dded3L,0x293c164920c83de2L,0xab178d26cce851b3L, + 0x8e6db10b404505fbL,0xf6f57e7190c82033L,0x1d2a1c015977f16cL } }, + /* 30 << 0 */ + { { 0x6a7a3464d0cbcea0L,0x76aad8b813126388L,0x519b9fd50a183232L, + 0x15f9abe1feb6b100L,0x7002990485ba4143L,0x92cea8f4c4360dd8L }, + { 0xdc6c5d1dc12748a1L,0x1846eefcdd3eb156L,0x3117dd04d47a41dcL, + 0x96c21b29f6a167f2L,0xf569446a27555692L,0x941292e500f88cb2L } }, + /* 31 << 0 */ + { { 0xa39c89317c8906a4L,0xb6e7ecdd9e821ee6L,0x2ecf8340f0df4fe6L, + 0xd42f7dc953c14965L,0x1afb51a3e3ba8285L,0x6c07c4040a3305d1L }, + { 0xdab83288127fc1daL,0xbc0a699b374c4b08L,0x402a9bab42eb20ddL, + 0xd7dd464f045a7a1cL,0x5b3d0d6d36beecc4L,0x475a3e756398a19dL } }, + /* 32 << 0 */ + { { 0xad852b878c0a64a4L,0x0d784cf208f779d5L,0x1896b9fcc651b1ddL, + 0xba8953d612e8dc87L,0x3a9865baa631cfb0L,0x5dd2a4a0626b3d79L }, + { 0x1148bc72687c20bbL,0xa372dfc2f2a52bfdL,0x77315f9e9448fd08L, + 0x4bcb06f00a2377b6L,0x73b42725b35b4ff0L,0xc510ad93aabca99fL } }, + /* 33 << 0 */ + { { 0x61333a382fb3ba63L,0xdf330d9d5b943c86L,0xbbc7c7ee955ef3afL, + 0xda631fc160f09efbL,0x68af622641d5c400L,0xcc9e97a46c833e9dL }, + { 0x7fd73e8e3a625e76L,0x13bf6124c209e55eL,0x08467cea48b90b91L, + 0x8a416eb9bb6f0abaL,0x6fcc93a1b8c31072L,0xa7fd2b619057dad7L } }, + /* 34 << 0 */ + { { 0x80b309dd2ada5bf4L,0x0648c2cd2d668c41L,0x45700722abb9102fL, + 0x9d6ac102b4e25201L,0x7ec2bc1cd50b3e6dL,0xcdb55e6ba07b7caeL }, + { 0xebcbda0786da3943L,0x470ddc68f8a57f48L,0x9e1418a4554557c3L, + 0x02d00cfb8a76b2d6L,0x03c050a061520726L,0xa964eefbfdadd24eL } }, + /* 35 << 0 */ + { { 0x58a5b5433720ec9bL,0xbb3800d52d7c2fb4L,0x4a508620dde6bd0aL, + 0x65f16273a02583fdL,0x832bd8e34fc78523L,0xd6149f75e9417bc6L }, + { 0xfeb026e93deeb52aL,0x0ce18088a55e0956L,0x50018998988092a2L, + 0x22f19fab28f35eeeL,0xac8a877f52ccd35cL,0xb13a8ad830e23f26L } }, + /* 36 << 0 */ + { { 0xf216aa2531238ed0L,0x4a13260770b1b757L,0xa39180d45c2c7ce1L, + 0x9f82b7fbab52606cL,0x6f01faee26946e78L,0x1608643883061d37L }, + { 0x597edf370fb077bcL,0x1d11bc5ed6e28138L,0x10209418c167fd20L, + 0x6a3258ec33f55675L,0xdf33eed7b73401b1L,0xf699887b806085b7L } }, + /* 37 << 0 */ + { { 0x0202d57de44f61a3L,0x4027704bb5630ef2L,0xa129e2dff5b54a5dL, + 0xacb60a7597482b86L,0x9261ede87ef27114L,0x1eba28f3defc58b5L }, + { 0x6c91c0c98be5589eL,0x2f1643d514594beeL,0x2ea912435d2ca034L, + 0xb50649a894047d1fL,0x284fcbb5638ca337L,0xfa0e07b7fe85bf85L } }, + /* 38 << 0 */ + { { 0x4703cd85891f8ffeL,0x018843c01c0d7702L,0xf3d752f5ad6cbeacL, + 0x479ecf018173fb32L,0x6b464412bc9a48c7L,0x47ba96091da7b147L }, + { 0x91af26eaabc13488L,0x87c183c3e1a0e06cL,0xdae2479844956b93L, + 0xf300e1c648347f9aL,0x129be314974320a4L,0x1f466694520618f2L } }, + /* 39 << 0 */ + { { 0x7d894f80506e0e42L,0xd984244a8e3d2c46L,0x6d7edf642b7f006fL, + 0x36a1cd6dde9b6230L,0xc9985040b76c0665L,0x587df4d6b89b1fc2L }, + { 0x4c0638476a71ae7aL,0x7b2b0ab3e8294747L,0x345c553ab53153b8L, + 0xb646e453436d9fe2L,0x1a95355f1cd60340L,0x2d7bc128074968fbL } }, + /* 40 << 0 */ + { { 0x6048c6949399c38aL,0x43a53ff21beb359eL,0x86fcfe4760be3ebcL, + 0xae78bc3a3134216cL,0x3b021cf316d7a9adL,0x51c4b1b36a4d6e81L }, + { 0x54b9cd8db593d816L,0x1df8cc84a69ea3a3L,0x98ff87f7370eb744L, + 0x63a00a0a60e0aa2aL,0xdbb22c9ddeb46e6cL,0xdfd92b6da914bb01L } }, + /* 41 << 0 */ + { { 0xad148e87bca6d14cL,0x41dfd24d456a201eL,0x73a82933a80d68f3L, + 0x89746c8d852ca035L,0xe3bc778895fd71aeL,0x8764cd2cda92245dL }, + { 0xa2fe2c4782eb23e2L,0x5ac762e00f3c9d6eL,0x57860ce121646f31L, + 0xbdc9d6c34f9f589aL,0x679952c7d193272eL,0x82ea702eeb18f1c5L } }, + /* 42 << 0 */ + { { 0x18ef56cd5d76b881L,0x31b22efc5df46c66L,0x4b21c4f3eb6c7e62L, + 0x3fd72a308f234c86L,0xe983e169ffff96c7L,0x7438b4933c1e593cL }, + { 0x863a23a3a553e8e3L,0x0d959ba9796d9129L,0x25d0caaeda1eadf4L, + 0xe739fb61eaa67763L,0x50029568472a7175L,0xdb6829c2f002bb6eL } }, + /* 43 << 0 */ + { { 0x37fa935500846d44L,0x09112fc50578bc8cL,0xdad9f5b239c4943dL, + 0x7314f5f0416dbd86L,0x5cf095a901fefb56L,0x35178bad22dab393L }, + { 0xcf79fc1b36baf1a7L,0x1b7ee42d749e5498L,0xbce78aa9ede314bbL, + 0xaaf8e0f6bd0628dfL,0xa974b09415cbf948L,0x8f3f1f63c9632b78L } }, + /* 44 << 0 */ + { { 0x1c5f0e5b36a400d3L,0xae97af8bf240b30aL,0x767b4ad7f8f99b51L, + 0xd50a288981ea36c2L,0x04ce2a21986c5ce6L,0x9c7e7754a320d352L }, + { 0xc3336331bbad8346L,0x7cc82a4df1698fb2L,0xc680176505c7ad6cL, + 0x47678afb27dda8e5L,0xade6096d02e543aeL,0x5fb28e322a1dd73bL } }, + /* 45 << 0 */ + { { 0xd4c411564fddda5bL,0xd4af65c673ad9112L,0xffe8e0bb39eb8f59L, + 0xb0040c0e8d6fcf13L,0x99e1c0c61f2bb599L,0x9c94c858b2ac3405L }, + { 0x8f8878d76eeed85dL,0x62b2f54351fcca3fL,0xeb3b44a9e5b56918L, + 0x16f96676b7234e93L,0x17477722bd2af19eL,0x42eb2979db83a485L } }, + /* 46 << 0 */ + { { 0xa618d7479fc4f435L,0x9f24fba649ddd10eL,0x60976b01b472d789L, + 0x9266634957719f54L,0xd9c79db800541257L,0x374aa9069481ed0dL }, + { 0x60efb1147fdc2d7aL,0xa1590c30ecf58643L,0xd7a198a4185a849cL, + 0x19ab802314eb4ab9L,0xc82d5998ec090d06L,0xfc539eb3e259c7dbL } }, + /* 47 << 0 */ + { { 0x6f888f7df0c668caL,0x65c788785f0dc66cL,0xbfb185125f5b07a0L, + 0x780abff7d878acd0L,0x504f21b1570cf950L,0xea5b37c5da233371L }, + { 0x487ae8bd22437ed1L,0x9c701758249cf9b7L,0xf86562a898fb34ffL, + 0xdfeea1a265e0fc91L,0xeef006912e20fc23L,0xac9dfec7dfa72a8bL } }, + /* 48 << 0 */ + { { 0x3ccf806ab35bf6cfL,0x2d368d48e7f30c2bL,0x4f504e06ea52bef9L, + 0x40d01ff53a7d2f3cL,0x62e5c5d3e73a1bc9L,0x66e4794bae7d7400L }, + { 0x3d30625e5ffef312L,0x4580609da766ddf1L,0x5c3ca10d04bab985L, + 0x2605ca009da2a2caL,0x48eab00eb5c9462cL,0x271e42a12624a583L } }, + /* 49 << 0 */ + { { 0xfa5c3aef697136c6L,0x8ea5af63a5ea6fb8L,0xa669156542e365a4L, + 0x47c56c115b6e3386L,0x1197832bcea03f56L,0x0b470bb250e4ea9eL }, + { 0x3113c74313b25712L,0x8d6c174ed2497d48L,0xfc4486ee49c9ebe8L, + 0x2487edd57f82bdd3L,0x771e64415b57be2fL,0x2d1cc518e28b2bdbL } }, + /* 50 << 0 */ + { { 0xa96763d2fba32d1fL,0x172cfe4ecb5af900L,0x510bd675cb2ec3f1L, + 0xbeabb91ac3c90051L,0x9cbf755b46f97ac7L,0xa820e8303a5d50d1L }, + { 0x83a9f17e308c4545L,0xdf7dc7053048461aL,0x6124642f0f32b151L, + 0xc1b444139333e405L,0x6f7bfa7e13a4f7d6L,0x6f58fa8b7181c2a1L } }, + /* 51 << 0 */ + { { 0x2c4ccac72070ac8dL,0x1947c0caec4a22b8L,0xa5e0fb598c5a78d9L, + 0x464ae8d241a84de7L,0x3dba16e9daaabc27L,0x16634a504f35cb3cL }, + { 0xadc18bf9b16ec84fL,0x324d067e7359dd35L,0xdaeac0c3570543f0L, + 0x0b2240003c887d36L,0xc69489e2373f1a0dL,0x518b047dcbaa0d97L } }, + /* 52 << 0 */ + { { 0x8f6468656f9201b9L,0x8a944b316b326232L,0x5687d1dca6ccfd35L, + 0x0bedaa85e5377c00L,0x252b48f5cd8d7d77L,0x4b820d9b31d83660L }, + { 0xa9e5af3ccae07f15L,0x0a8930fc1208b9faL,0x6d0a166ced3c3b7aL, + 0x90e2aead7f78aaf8L,0x222465866e5ede76L,0xc5cc339dcba1fd4bL } }, + /* 53 << 0 */ + { { 0x3b1bddc6fbde49efL,0xdaed7c268a0915ccL,0x0b0110610f0422a2L, + 0xcf485c74a7c54b16L,0x642ec4e615c3aae2L,0xa8ba8f10e0f383eaL }, + { 0x2a2054b495618501L,0xebec6442089efa8bL,0x5786a19a4e2fa83eL, + 0xd2c71ad139069963L,0xadc93d9a481765e2L,0xedf2e3eb7ecc9485L } }, + /* 54 << 0 */ + { { 0x11853add834e6c54L,0xab2f15202175fbf4L,0xcff00bd23c9b5a41L, + 0x075134ebabd64a6aL,0x48c075daaadd6150L,0x4576a6497cb89442L }, + { 0x340a767034adeda3L,0x8dbb571c77fcd1f4L,0x0bf879d693b44ea6L, + 0x1ae1dd97d13444bbL,0x6e9e86bb7b1eb77aL,0x420eb673906a2949L } }, + /* 55 << 0 */ + { { 0xbcab5f60069f3367L,0xfd6622bc1718ec3cL,0xa4fb7867e3a142d6L, + 0x6078d8bf085faeb3L,0xfa5cbfda60f4554fL,0xb3fcd5d1690cd408L }, + { 0x4ebdee7d281f7884L,0x82af23aa180a63a7L,0x8de3107c3d079f61L, + 0x17c6b5cbbe2334f8L,0x6a91e73997d0fa06L,0x7460257314ceeed4L } }, + /* 56 << 0 */ + { { 0x483350a5ebb8cdadL,0xd4215b4fc7a8baa1L,0x8b6fc785e692fdd2L, + 0x2629ba4fd1deca25L,0xe9981ea6820da79fL,0x7772a913e6436cc1L }, + { 0xd141235c553fb41dL,0x28179e6cc852f64bL,0xb623a1aeeb8cc21cL, + 0x05826192490bb572L,0x56fefff326f349ceL,0x31ff648e0f88b82dL } }, + /* 57 << 0 */ + { { 0xb14ba61cf97f865cL,0x73bae4c1694b8b0dL,0xa14967dfac4bbf62L, + 0x1e9dd1509bf446e0L,0xc052f3eb1c99ceefL,0x814d7fa07a78c189L }, + { 0xa101a483ab74b05dL,0x7788c258a1737b65L,0x0d60bab7e809a13cL, + 0x8f427bc473c81d5bL,0xd2e130552952c1fcL,0x0a823b9a4b26df63L } }, + /* 58 << 0 */ + { { 0x941c5c257d0be180L,0x341cf9d9c46785afL,0xdab9dc0015b0fa13L, + 0xa58db4ea4f96af4fL,0x9e9520bf57acc87aL,0x104cec0666ac72e0L }, + { 0x9f3f7baa1929e675L,0xb8b4ac9ffa80380aL,0xb5f157aa569b57d8L, + 0xe11699e909fa58a1L,0xc08595e35548fbeaL,0x2b51995f794da901L } }, + /* 59 << 0 */ + { { 0xaf467ce227bf64c9L,0xdfca6897f929974cL,0x64473b595c322738L, + 0x96a917cf1ed0e315L,0x3703435b0de64db9L,0x9ba039679267b646L }, + { 0xdf0c2aae3a522fbeL,0x41bdb741b335eff0L,0xaccf2edd7b059703L, + 0x6fb34b3028463cceL,0x96d9ba0bd9e3ca19L,0xff336f12504655c1L } }, + /* 60 << 0 */ + { { 0xc711d5d1c425543eL,0xa61fada6fb4f60e8L,0x0402d5c4eb809f85L, + 0x84b7c2fed74cccd4L,0x61bba736a55b5277L,0x95bb80cece47968cL }, + { 0x09f92adc16eb7b95L,0xf0e0f4f7e682aa29L,0xacd70b86ad2a20fcL, + 0xbb45a51f948a8375L,0x29fc3b284892e676L,0x8dd21bf0b4ea4f51L } }, + /* 61 << 0 */ + { { 0x48da1fd3fc60a6e0L,0x54fb5a34222241e8L,0x6035e34f772ae080L, + 0x5ff77ff2332982d0L,0x2366467300fe51fdL,0xc93ea049ef6ba006L }, + { 0x6640f1177d381266L,0x394d32cd6ae9f4acL,0xe6a7885370d303ebL, + 0x0dda19ffe5275767L,0xb0a6c77201466d23L,0xc4cc11451fc69829L } }, + /* 62 << 0 */ + { { 0x49a04dc0f5acf772L,0x1e659730c1fb476eL,0x0c7d749907dbb9afL, + 0x03b9f1cebfec21daL,0xd194b7054b14d117L,0xcb4c0a54561fedf2L }, + { 0xaf623d3f21da4d42L,0x5f5e9b1fd630c145L,0x65609e59d9ff0abaL, + 0x3d2508922ba9239bL,0xcac324ec82c4faa7L,0x0902cc23149446b8L } }, + /* 63 << 0 */ + { { 0xc5c0e6d7aaed89c0L,0x6ce8ead6149a1896L,0x7a50f7458c949f8fL, + 0xcd7e35f76e2b71aaL,0xf6159e519a049f7aL,0x1c9bf0b0f1e52d1eL }, + { 0x3bb6c1f518202c80L,0x8d3a5f621ecd7b1aL,0x3bb034e888d17f19L, + 0xdc89bd4997d4048dL,0xf5af7b8e3735df22L,0x52bb3712a0a689e8L } }, + /* 64 << 0 */ + { { 0xed4de4f88e89b258L,0x957c980f297a9a37L,0xe04b3d30f8a0580dL, + 0xa309199dca57b7bdL,0xfc8e87cf3be44d56L,0x4f5d5ab6d1b30e5cL }, + { 0xb213c6a030a9325bL,0x0fd1c52df091bc01L,0xfe51bbbf1090fedeL, + 0x6d97cabc301fe259L,0x3ee127895ecd3fe8L,0x888b708b9404ca51L } }, + /* 0 << 7 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 7 */ + { { 0xe484fd9f8258030fL,0x0f4fa5eff21af80aL,0xc0dd449e7c1c3984L, + 0xf313389118eb5195L,0x0336aab8777a16d2L,0xa6661cc4c241720aL }, + { 0x678db970a7efacd0L,0x228968656461e382L,0x5d85a0e4a022c7a4L, + 0xb01f1e0434a02a6bL,0x2657eedda5791ce3L,0x239dcab2a277ac5bL } }, + /* 2 << 7 */ + { { 0x9a7a5b426ae54da1L,0xcfcadaab7040b022L,0x7539438e3d9f0e61L, + 0x013c6719e328c2e2L,0x7f4a706ccccbf891L,0xa335ab82735a2d28L }, + { 0x46694ef03d984124L,0x0e0bdfabc166b337L,0x9d54ed8b423d47e4L, + 0x8075a8cbf44c9180L,0xd4f5b184abe9b384L,0x424dd00b41abdc75L } }, + /* 3 << 7 */ + { { 0x99a710b1400f1d87L,0xec3ca386ee47be8bL,0x3a00dcad37168feeL, + 0x1a69d6741765a0dfL,0x85233afe917c4909L,0xa3aa97a4e9bd6210L }, + { 0x01010526310885f3L,0x21c5de3fb5007b08L,0x5df0c6efee8ddabdL, + 0x5d17d45a0f6dfdefL,0xb73d831a251c9f79L,0x397779e6cb1df19dL } }, + /* 4 << 7 */ + { { 0x5e2cb07fd7801edfL,0xf9fa2c0b3adc065aL,0xa296c53fd4de1f25L, + 0xd408060c838f7169L,0x68e19d7b2e8a6ce7L,0x2cc6e06c94b58671L }, + { 0x93d02a07c1cb6151L,0xa10fb4cf35003126L,0x6aa069f51aa3bc4eL, + 0x0e44fbf0dd09b142L,0xe264f343832e5945L,0x5dca2adc1fc166acL } }, + /* 5 << 7 */ + { { 0x5f63e391d7afb4c6L,0x85208bcd2bcb4a76L,0x10022d53c3da8fd7L, + 0x607538c007e50047L,0xdbdb0e7212793242L,0x8e6b9f6135eb668fL }, + { 0xbe5632887e1da455L,0x5e73e1a06e544e82L,0x0c28a5d29a2da4deL, + 0x62b30a8822326300L,0x470764f16013086eL,0xcbe2c34cd3ef5fbbL } }, + /* 6 << 7 */ + { { 0x9ee4f522b0f6c604L,0x5b8a689d52736e58L,0x0d5f396db7edb07cL, + 0x09b3457c2e829063L,0xf1d28188f83495daL,0xba2511e6cce559b8L }, + { 0x17cbaf57d8f90669L,0x3ba19a1c514eacf0L,0x298208995145b8fdL, + 0x92cb5da81a33b1a7L,0xca49fe334c5149e9L,0x5c499b661772b4c0L } }, + /* 7 << 7 */ + { { 0xb98266b132508180L,0xf5008b926719d49dL,0x50c513f98069ffe6L, + 0x99ceb828a7c6f38eL,0x375b8a8225e2a436L,0xb8197f6c416c073dL }, + { 0x01663a25eadf09ddL,0xfa2ca1571d7ff230L,0xf3b65b2545284aa4L, + 0x144dbefe648bd565L,0x6095ed8ab4c24e35L,0xe1f1fa3696ff2020L } }, + /* 8 << 7 */ + { { 0x56ad7582a0eb176aL,0x085b5a366e19aa00L,0x85f2c6ffe2c8b036L, + 0x55c6d357fcd7336bL,0xb1ecc56d22a46acdL,0x8e0f976736277ac7L }, + { 0xa4ed11e901878921L,0xd38355667f4fb650L,0x5fdaba45266158aaL, + 0x6f0b27fd89e0dff0L,0x32ef7ae2eb6b02d0L,0x2f145871cc1b46e1L } }, + /* 9 << 7 */ + { { 0xc7698dfd4b449cfeL,0x78aacb7bd1517720L,0xaf0f6ef574cd5f32L, + 0x026f1826f17954e3L,0x33ef67ab2453185bL,0x82f0fcc90a420c0fL }, + { 0x5b444b3645f154b1L,0xb27c4ece70d17f90L,0x6417e0d039282194L, + 0xebfb5fa001aa4f4fL,0x9cc5d0b573932754L,0xe8b56699704ffd85L } }, + /* 10 << 7 */ + { { 0xc112733b9d4075dcL,0x349281c187737549L,0xbb7d8e0181009785L, + 0x7640a3e2bfe16c4fL,0x4e34813ec1d9f810L,0x61985fbc8d2605d7L }, + { 0x2a544cd8e3f66442L,0x48879af56a7c9e94L,0x9e6157bacec18a7eL, + 0xa555fc9511b882d6L,0x4305a4dd04f86563L,0xc58ed7631d0fd96eL } }, + /* 11 << 7 */ + { { 0xaaeec0f9b726e2edL,0x243ba6614493d146L,0xd799c3408980a9fbL, + 0x886e4f44ed060f57L,0x52126b82c1f83f6eL,0x8b4978441df301ceL }, + { 0xeb2a98abcdc4e434L,0x87dec119474e2c77L,0xcbbc613092eb1528L, + 0xb0b0bcf7c454f37eL,0x404d97a7e1a919d3L,0x26d1baa825e62c30L } }, + /* 12 << 7 */ + { { 0xf04145e82d2696b3L,0xaffb66acf4fb2928L,0x9ffcba4e12aa299fL, + 0xcc5ec24991b3b517L,0x9edcd4616f81c747L,0x0a96090a77a883ebL }, + { 0x9b0bab58a2aa4badL,0x76359a5e8f9b84e7L,0xfe8cd81e438a9d43L, + 0xf40e2b5e25ca8b3cL,0x4254030067bc720cL,0x883002a46b2446a3L } }, + /* 13 << 7 */ + { { 0x4b43bd3206c3aa7bL,0x83ca2db60a470b08L,0x07c1036c06f22f37L, + 0x312e04d7bbb46ed2L,0x6a1d70a40193e5f6L,0xc69720e8ba8a3f38L }, + { 0x2c003429468a04b1L,0x885c43bfbc83fe25L,0x65a65259393e00e8L, + 0x7154c7ac2af17741L,0x682224d331dda744L,0x6183dd8bc80b57f5L } }, + /* 14 << 7 */ + { { 0x80e1cd16c496089aL,0x7a59f4c06ec2000fL,0x67a019d509ddce06L, + 0x52573e3e70c4b032L,0x16d253e14d3ba57eL,0xa43c6d42162504f7L }, + { 0xa237bbf952ff95e4L,0x81187e659acb7273L,0x4b13531a1f384daeL, + 0x39067f3398125165L,0xe98fb141672dccc1L,0x594baca0a75e27b5L } }, + /* 15 << 7 */ + { { 0x85e12293c205465bL,0x57bbcfb1b71cbe44L,0x201ed45c1bc85881L, + 0xccbc39d5ccbe7dacL,0xc509b77f9277f310L,0x171b603aca1b70efL }, + { 0x9b99605504d2dbbeL,0x986d6323451c918dL,0x75ad922f63c6fb03L, + 0x69e2cca49630182fL,0x1389a2b7f7b34d1fL,0xa66a80323d4f7c7fL } }, + /* 16 << 7 */ + { { 0xe65245cef6e9f82cL,0x9e234dfff6da7b5aL,0x5677c121bad2c806L, + 0xc52dec32060fcf24L,0x78d070675d78cccaL,0x630002ea1bc8b6fbL }, + { 0xc5cb86beeb2e99aeL,0xf13981e78551d16fL,0xfbb7cdf2c92a70d7L, + 0x5a9ff1f1f53cd2a1L,0xfdbe6b7a984f1139L,0x4403d046a470a9f1L } }, + /* 17 << 7 */ + { { 0xdf8c9325efcc63faL,0xe0d35cd966563147L,0x140b9a8bc144d7b9L, + 0x492bfbd70c17c75fL,0x3cbc2b644c5c4d8bL,0xfecfaf47ff8a3328L }, + { 0xaf341aa179b8c3d5L,0x5e72713ff04f29e6L,0x652219fb9f5b6fb6L, + 0x9deeba3f0764460fL,0xb8c2bfa5fa069d0fL,0x5d3e6fefe57be3e2L } }, + /* 18 << 7 */ + { { 0x52c9b94decd84cacL,0x34c2d0ad446dc59bL,0x5563701d951878ceL, + 0x92e2fc1c843c9b1cL,0x2309a5f13dfc7a98L,0xdaf117dc0c57a156L }, + { 0x5739190d359fb843L,0xd433e9bb4b88e3a8L,0x4d6bb0e2c47a1f45L, + 0x511eaa33d7b59627L,0x42ef82c5e389e532L,0x641a0bdcd75f4c08L } }, + /* 19 << 7 */ + { { 0x3ae32dbdc7e30cc3L,0x0c970135af5d0ea3L,0x8fc38e50bd9a0528L, + 0xdb0506791bfa634aL,0xf3514fbd245cb0dcL,0x3a3c8c6982319ddeL }, + { 0x92136baf6426632fL,0xabc3e24aabdd5641L,0x8ccae1429cc004baL, + 0x6c9834d8b3ee0d66L,0xa807ab63e1f7e8d7L,0xb4598e2a220aea7cL } }, + /* 20 << 7 */ + { { 0x19821469d678d1a3L,0xf9fa42e60df2f58dL,0x1177daf49f284ba0L, + 0x6dd2ad3d2a201dafL,0x667b0e383d427075L,0x39b76d1d4212b65aL }, + { 0xc6720ae0bf3612fcL,0x72559d98775f8137L,0x466e8e4476c48a09L, + 0xa05f8eb07fb5428aL,0x7fa1fbce5e36b7d3L,0x13bab84f8d1fdcd1L } }, + /* 21 << 7 */ + { { 0xf1876140ed6f3524L,0x47171ee5cb94b2adL,0x56d836abcb8de844L, + 0x346e80890d3b4271L,0x0110df1fdabf6a02L,0x6850fba1f571cb92L }, + { 0x490cd9af6209f064L,0x41f32d5f1cf5636cL,0x558bb7ddc328f9dcL, + 0x44abd0b9d32e3e4dL,0x2c42a5607fc2ff0eL,0x8b1dc5e12c9931f5L } }, + /* 22 << 7 */ + { { 0x6a35f6efdca1ce69L,0x04216d3184de3658L,0x3c3010df732f31b1L, + 0xe4421a872c1444b8L,0x17c987a3c59c1ccbL,0xd67159dba297df1bL }, + { 0xd13aa7a0bc96041dL,0x686d7b77f44c3d8fL,0x6c2e505f09b2b933L, + 0x8c04eb8256161b34L,0x61785cb4b344bec6L,0x60b4d06cbf8b0b45L } }, + /* 23 << 7 */ + { { 0xe5b055481883c1bcL,0xd5bc37684597b8afL,0xa71ae49adb2fae11L, + 0xc1ac1b3e050327f0L,0xd990b2a668f3cb1aL,0x566e5175b74a3228L }, + { 0x348d382957909fe3L,0xe849dd8dd03c2374L,0x4f31a278150fb5b4L, + 0xbfe265cf168c0798L,0x2737c156ce6a34beL,0x4478d6ae4aa6b73fL } }, + /* 24 << 7 */ + { { 0xb5b16cd48d040c69L,0xfdaba315f95a2dc4L,0xc9fef34961ce4704L, + 0x5fe87a0ddbb53ed6L,0x3f0ccc7973d70f93L,0x4601d1bc46724a1aL }, + { 0x5c4a15ae24f08565L,0x5eda1e8aaa577320L,0xe31ebb35bb32d307L, + 0xcdc6f13bdc770a0eL,0xbe3ae514c434c2f8L,0x57c7fdf63a0ef0d1L } }, + /* 25 << 7 */ + { { 0x85165ea2d71c01a5L,0x3935171c99a29e59L,0x2aa1b5837d326190L, + 0xb1d702f8e79f3959L,0x94100c65c6ddffd0L,0xd1d56d626a9c54c6L }, + { 0x5c93b4cf7ce12b66L,0xfc28574bb32a90caL,0xcd654a96e755969cL, + 0xa06f436cd1bec664L,0x9b27c110ffb6f3e6L,0x529b77d317b476c4L } }, + /* 26 << 7 */ + { { 0x04c3d9e162ccecd4L,0x6050bc1221cb59a1L,0xb33847543cbb7e07L, + 0xef2201ac4cf1be50L,0x99c3dda42d2ac886L,0xad19cb0ab776eff3L }, + { 0xd326dd7f5a3d9036L,0x9fe56af2e5b27667L,0x3d849fc072cea4d1L, + 0x262a0cbcd6aa9e3cL,0x8286211885401b09L,0x8ec71d4b98fe8047L } }, + /* 27 << 7 */ + { { 0x9b769cc43c6b2de7L,0x433d4c26acb13b6dL,0x52878f517530ef4fL, + 0xd0e7ce94b0c5354aL,0x5b094d461d92dbc1L,0x75f681449e4ffb31L }, + { 0xb9b9e97351b9d1e1L,0xc147ba4698661569L,0x2a06f4cb7a239309L, + 0xd5cb5ad420928958L,0xbde0283bd5bdf5c6L,0xb91664a082e43c18L } }, + /* 28 << 7 */ + { { 0x8fc0cfa6e51d078aL,0x431d9dd5744ca779L,0x37a4f3120e96e887L, + 0x9c3624fa03ea5144L,0x47d5ecda0b1127f4L,0x018ad424807cf96dL }, + { 0x58ba530f586b16b9L,0xec7271ed72f47883L,0x8d2918da0281ac88L, + 0x6d0f14ef002330c9L,0x1a90a01591dc35caL,0xeb8e71e9c81607dcL } }, + /* 29 << 7 */ + { { 0x2eab9c5ee6d01fd3L,0xe030e6d23fa77f57L,0xff41311877edc0e9L, + 0x7817766bb47ca351L,0x70c987e36cb15abaL,0xc3c867ace19c5aa4L }, + { 0xc24ec23ea05c3810L,0x3965a165c4f0f350L,0x52af99cf7c0d8e5bL, + 0x2d95d23c106e0b12L,0x27507b297f6d44d3L,0x33da846858b191f9L } }, + /* 30 << 7 */ + { { 0x8e5785629aa664e0L,0xf3a1cfc329a97c9bL,0x91ce3b404037bd09L, + 0x34c447b07f9f2482L,0xebe360164010c2a6L,0x7b8b9b3afdc0a861L }, + { 0x0e60c49199c4ff9fL,0xf1cf53b1053e703bL,0xabeae550dd974a16L, + 0x28ac5a34994ea50eL,0x9384617d27329793L,0xd04db83ddad0aec7L } }, + /* 31 << 7 */ + { { 0xcb0ec2bd4b1537bcL,0xd0de683cbac6569bL,0x0688dbee5c96afb7L, + 0x7c7d192f3324ab6fL,0x1455b1e6165fe655L,0x32d135a1ccfe9e1cL }, + { 0x05a80a2af9e1a86fL,0xdc946c70479c71f1L,0xf8b9ad985aaa0ff3L, + 0x78cf198ef195bbceL,0xadbc082dfcee6b59L,0xe6e1fa844cd19e25L } }, + /* 32 << 7 */ + { { 0xeb06571c0f547ebaL,0xf292c38d6246c0dcL,0xa185966726eed224L, + 0x8d9e56e46100e387L,0x470506b9dc6298d1L,0xb19e084cf3350ad0L }, + { 0x83eb62a812abd898L,0x70f152cc2222342cL,0xb089e880e1bd4a82L, + 0xd4d1e70fcaf3b3fcL,0xd0b1ec6395ffd65cL,0x79f27f3a9b184ebbL } }, + /* 33 << 7 */ + { { 0xb4a7435231a3e816L,0xba8a0af2fd4ada3aL,0x1622289dd8fed2e4L, + 0xb71e579e31d3745cL,0xb090650704a50576L,0xc98b5f20123f900fL }, + { 0x3799ee82d3587b21L,0xafdd6dc79d9abe55L,0x4053ee2aba64b9d7L, + 0xa816246657b3f258L,0xd9b5c4c4690b1169L,0x32c1d3afd091d158L } }, + /* 34 << 7 */ + { { 0xff5a9c58de97d0d7L,0xec086138feede4acL,0x55b14035ebf47cecL, + 0xc0b3e061c619fe18L,0x5644c092ead4ebe9L,0xa1a4f7a41e5e0a61L }, + { 0x8698da06d179219cL,0x86f560bc3f88f732L,0x6ad10b3f1e34a23dL, + 0xd4326bb71307ede6L,0xc93cd2a19b3045adL,0x5a0b733dd8a5160aL } }, + /* 35 << 7 */ + { { 0x68ef87cdeaedf10dL,0x5ce97a07bed10cb6L,0x9b8dbd896ed762c1L, + 0x1a72b05333c1dcd8L,0x6718eff90f97cfa6L,0x02f886e57dda698bL }, + { 0x9db378a8c724f4c7L,0x5b55b8383fa6548aL,0x9935a70ecb24bdf9L, + 0xf5da6936e9de8ae0L,0x3b3a10a79b0c4bcfL,0xe4e6a6e86361c492L } }, + /* 36 << 7 */ + { { 0xb37fc581c634a8f8L,0x06f06c93de1d01acL,0x0f2dac8452fed4ccL, + 0x1673c81bda53f81fL,0x963e500e61e11c94L,0xe86ff87e2144d55fL }, + { 0x343ddf389bbaec76L,0x16a13527806df1edL,0x1361b5ac0a9edd65L, + 0xf20507fe33c0124fL,0xdf64ec1e4e8e0d18L,0x3f6a42e27860a8f2L } }, + /* 37 << 7 */ + { { 0xe6db1c43d38266a7L,0x55bee1a3adec0d4dL,0xe41c403ed56d2f9dL, + 0x5fb703f24d3cd93cL,0x4d7ae8c53d2a7ccaL,0x65c8ac50ffa5fff2L }, + { 0x128814ec264dfa80L,0x08d1372ea642513fL,0xfc5ea1615343a57bL, + 0xc70a6f2f9a2f3f3cL,0xfe61c499df4963f1L,0x2b711eee5cea1508L } }, + /* 38 << 7 */ + { { 0xfc3e9fb252f9a4f3L,0x8bbeeff32180cd36L,0x274312dbd6438c99L, + 0xbd30984a55612a57L,0x344006d609381db3L,0xd9b696f62bcac509L }, + { 0x481e4ea3bef646d0L,0x213033d430561b68L,0xf46bf9a05453f623L, + 0x2af3c4a46d848d97L,0xc35e55a543efa02eL,0x8da254342462874dL } }, + /* 39 << 7 */ + { { 0x1f7fda656a12b927L,0xf628cfac876b9303L,0x1904a0b5d0d0d0b2L, + 0x46d486f6f2894b1dL,0xd35cb5610d243bfeL,0xe759579b851a568eL }, + { 0xb99572e2c1aeda5cL,0x872e16fb1c54cd1eL,0xf5ec9e42a60fdc40L, + 0x59b03a6201a4b019L,0x9c5e7f87e272e064L,0x6240282f24c918a2L } }, + /* 40 << 7 */ + { { 0xc2467f9ab92a9a13L,0x0c3ee8eb6add349aL,0x59250eda45e99644L, + 0x22ce0635c8a2df27L,0xec7b643e312e8698L,0x334ccf2eaebd1587L }, + { 0x0c1c68736bca2900L,0x00beb4c209826cb1L,0x12dbb586cde6b725L, + 0x8d7cee6c66dfed41L,0xc38deba2014de4c8L,0xa3ba6ec76248442dL } }, + /* 41 << 7 */ + { { 0x870be3ebef38abf3L,0x6e0cf541f74dc605L,0x499976bcda4bc168L, + 0x5513c6122548b3b8L,0x5b9a054c3f647360L,0xa47f9f8bde929154L }, + { 0xa2ae9ccbb8ec35b4L,0x934c5c0a4d9857e3L,0xc9dd66cc4b4f01ffL, + 0x42a1afa2e5b5e147L,0xc284e464f3d9b380L,0x67845404e21bbe63L } }, + /* 42 << 7 */ + { { 0x9ec1ed3342ec772dL,0xa77e1ecf5501609bL,0xb059e214a02906f8L, + 0x35b2ebceb28e4d14L,0xb8453ec22cf036eaL,0xe621234b2518fe75L }, + { 0x079d7d11f03cd158L,0x357492f91b2f011aL,0x3c2186da0661992aL, + 0x7adc1c0fe5df978aL,0x88d329db5300cdccL,0xd915c2444c0d644dL } }, + /* 43 << 7 */ + { { 0x1b9797a8f0ff03f6L,0x00dafe43f41c9284L,0x1e565c33f2bdc817L, + 0x63b77ad9784b1a5dL,0x3304540e74aa6079L,0x630524f3d7181d2bL }, + { 0xb4fe5fcca2804658L,0x1e48e50b9e393a6eL,0xb5bccd49397a94a5L, + 0x95394743eef17accL,0x4d67ba5226dd1687L,0x80965c3432349d9fL } }, + /* 44 << 7 */ + { { 0x1d70669e49f1216eL,0x8645472fa5fca474L,0x9242e8ddfc400357L, + 0xe7ac31548623996fL,0x37b9e68ce61aecb5L,0x7d2e10fdb997e4c9L }, + { 0xc0cb59a6c2086dc9L,0xb38e2032d7952172L,0x78eaecf6eebac939L, + 0xece490b42f5dbaaeL,0xdb17501dcdc32565L,0x59bd392ab133bf99L } }, + /* 45 << 7 */ + { { 0x71554fae07de21a7L,0x3dd66b8bcc42db25L,0x9da85c0f0636e9a4L, + 0x61fef273904930d8L,0xcc8f527b73369e81L,0x4207dfab7caeacd8L }, + { 0x99e5d1404fc763d7L,0x5cc6a3739f4e8947L,0x9ef14ec1cde33eaeL, + 0x25eb3aa8095872d2L,0x0db8268d7d9e6dd9L,0x38846510c2ccfe92L } }, + /* 46 << 7 */ + { { 0xce6197e822d0a502L,0x69df7f8e09d45970L,0x0274f48b7eb4718dL, + 0x47461334a8c22b75L,0x89cebf17bf25b9abL,0x57c042f6fdfea412L }, + { 0xb19c338644346b96L,0xdba17de06ba014c4L,0x6697687a5f844d69L, + 0xf16dee4c1a66c6faL,0x7f916e47fdafd0d7L,0x1c3842d2340f158cL } }, + /* 47 << 7 */ + { { 0x417c9ab760efab2aL,0x1745d5c2f0065f75L,0x1a7d86f2ed71b350L, + 0x6d4d504feee5c850L,0x4ae7ee0da657b859L,0x1f72ded53c302a3fL }, + { 0x08779fdae7b22e51L,0xb04c1c0446d90bfdL,0x4dc97219712f96d0L, + 0xb15e8c0041a6be82L,0x384a02cca3804090L,0xcea45861babd1ee5L } }, + /* 48 << 7 */ + { { 0x3c686079d42aeb95L,0xc162e5e985e3ea0fL,0x34cf58611bbb2455L, + 0x7650de1d8773b064L,0x3b7562c6d2bab35dL,0x83191b4433d0741bL }, + { 0x4b604db03a6bd9cfL,0x87cd84db074aed21L,0x02a042d2d4f91f9cL, + 0x5a5d52e5e42c2a67L,0x31291acd1d5f216aL,0x9c3971bccd6203c8L } }, + /* 49 << 7 */ + { { 0xec931d6599e9ec3fL,0xe9d780c64bd554d9L,0xa580534502eca45cL, + 0x84701f1ac1276ca3L,0xcb7ba786d5f9438bL,0xf3a27508c85f663aL }, + { 0x044df512118c9421L,0x1109fd431039871bL,0x7865443de2378386L, + 0x7a5e2d49e70297abL,0x112763ca6824d2b3L,0x8a05f2c90e84bba5L } }, + /* 50 << 7 */ + { { 0xde3bfdebff044924L,0xd7f2a5181a0458f9L,0xc03df0c00139d557L, + 0x7a958c60cd3ad0d4L,0xec9f2f9759a43584L,0x5e0fbba950d8b4b6L }, + { 0x5fbc5e3888245837L,0x17235805a267a54aL,0xdc24a508db55d65bL, + 0x431e4d5623c704d1L,0xb1f85b2277585f9cL,0xb288f25ed0b1c374L } }, + /* 51 << 7 */ + { { 0xd8fd5b405a37c029L,0x5c9d827fe4d37effL,0xe024d7952e046275L, + 0x0661277f913c55c6L,0x21ee10eb904b3679L,0x32c582e066778adfL }, + { 0xc353ab1fba8d17daL,0x1d4ab06b5658ea17L,0xb908cb88a2d70bb4L, + 0xfc215909a98daaebL,0x7aea6c8777000e24L,0x19e0acbe38446e20L } }, + /* 52 << 7 */ + { { 0x1bc3803e2f98532bL,0x39d0c3258754d142L,0xa7b035c5d739eaefL, + 0xd36ddeb8fbfdea2dL,0x7df72a94bdf64f2aL,0xab4ad6b880bc3c47L }, + { 0xdf386df3877fa482L,0x4b94260470519bc3L,0xa3399d91d20e1e04L, + 0x7f5208b797cf58ccL,0x528f6a2814424c00L,0x83d74730bd900d10L } }, + /* 53 << 7 */ + { { 0x501c657f34ded7f1L,0x9071027e12fa53bbL,0x395e16aedff079ccL, + 0xea95dc84770ac4b2L,0x4d2aa60a41355974L,0xe04effa507f12473L }, + { 0x38ca98385cd1c738L,0x3c067a0b683c0dbaL,0x55ad2dec67589842L, + 0xe51550f7dfdae3c8L,0x21a56717214d51aeL,0x75b6a4a012a0fdcdL } }, + /* 54 << 7 */ + { { 0xd63605266a4ea95bL,0x180f72d403e67090L,0x7faf4529751c8c9fL, + 0x1ab7b50d00e4252aL,0xc0e69adf34811274L,0x5c4c83495e99c6ccL }, + { 0xcc9467f29a9e02a9L,0x5402c2da5c4fc719L,0x1dff8c5d3f6d5bddL, + 0x88a7d27a2c653c3cL,0x067f31183a050dc7L,0xca0f7dafc4f0236eL } }, + /* 55 << 7 */ + { { 0xa09306e9ca177c3bL,0xea84f03ed0552a4dL,0x7ae9024f3c00d359L, + 0xe189ebc33aa619faL,0x4adeefac8354579bL,0x90168ef9699db1ebL }, + { 0x75319141ad87490aL,0x7b48fe7629c1bf84L,0x00ae82c7a2235f2aL, + 0x6292c9cf68562b59L,0x0b6500943935ca20L,0x39f22cb027f33addL } }, + /* 56 << 7 */ + { { 0x92e4c851aa1ef488L,0x4f91fc22846528a9L,0xaa2f5d2d5dc13a84L, + 0xba06aa68f1072d4dL,0xf4f3b17c5e3a2ba9L,0xff36a5355e4dde77L }, + { 0xe8ef143aae17dddcL,0xcc82631ba1fcd4ecL,0x97db807ec7d3963bL, + 0xe4aff04521d85ce2L,0x2d6480e674667392L,0xc8ce97f3a55d0b3fL } }, + /* 57 << 7 */ + { { 0x1a32b8457962a675L,0xd78efd71723d217dL,0x9b03d6573b41a2c5L, + 0x1116f33589a380b1L,0x2c0359af931ee15bL,0x8a53744f239ba4c4L }, + { 0x4801397dc78cdc83L,0xc43b9f0434ae4453L,0x9cc8f6cec356a35bL, + 0xd5a74c2a648b39e6L,0xa54d668c0d5e78fbL,0x36257047cfcb8f6aL } }, + /* 58 << 7 */ + { { 0xabeef3461549c215L,0xfec59db2ce4aee45L,0xa1743a0f5305df83L, + 0x9d598abdf211bacfL,0xd14609dd52a513fdL,0xd3dc446be00d4ad0L }, + { 0xbd8883e9b272211aL,0xe991e57757879fd6L,0x5a093d372b732171L, + 0xdd901071f55f18dbL,0x87f04c0034fecfd1L,0x2c07df27c94f6a5bL } }, + /* 59 << 7 */ + { { 0x518e3ced1c17df0cL,0xf8971149ff5dbc4eL,0x5fec8bfe0ac9d27cL, + 0x41d68852489eed7dL,0xf48ef4bf3c3c4725L,0x3b8d9eee7681eceaL }, + { 0x7743ededdaae4bdcL,0xb9665ef5d1bcf697L,0x9d77f535471bb958L, + 0xb5db5b96d752b2ddL,0x2cd3c919c368982dL,0xf8297660e9cff6d7L } }, + /* 60 << 7 */ + { { 0x39e7da1028946a2eL,0x4e628a96c3a76f7cL,0x43b8b808e9f6000aL, + 0x86cbd25ca48bbb79L,0x5ce825e273092951L,0x43a6031df0cbee32L }, + { 0x6d685a594923485dL,0x8d4483ed81a17f47L,0xf61d329bbc379719L, + 0x9deef7d0f6596ee8L,0x0314a572541b1222L,0xe2b34d387ea7d376L } }, + /* 61 << 7 */ + { { 0x05ff6faa31f43d37L,0xfb83f23211b801f6L,0x238792d519b223a4L, + 0x28edadcce004f601L,0xf77747b3bdeb7597L,0x2178dbe21e6575d4L }, + { 0xd48ec49842870ba2L,0x7733661d15dca6dfL,0x08212e2f83393416L, + 0xffa1bfe2614c545cL,0xfaf4ab8494254145L,0xd8f9eb48000d250cL } }, + /* 62 << 7 */ + { { 0x9ff4f289a66132a2L,0xc54fb8001e098994L,0x09d3cd6624cc2471L, + 0x6d0f74167838e14bL,0x7438cd2dc540cbdaL,0x193b16817d6fa8b4L }, + { 0x487a7dedab33c6f3L,0x625eb8cf02f5aa09L,0xd8039682501323bdL, + 0x9de122e38e216951L,0x40a8fbde0711c51aL,0xf192b5c283a474c3L } }, + /* 63 << 7 */ + { { 0x3782cbda57e04e9cL,0xec639886e41b30dfL,0x4cd14afd12d2f686L, + 0x0aa093ee8b768113L,0x6cfc12cdad598f9dL,0xe4a62f1194bcce0fL }, + { 0xd5035fab150ad4f2L,0xb3cd4871ae2e8da4L,0x49c9e78271ad9c3dL, + 0xdcafeb34825690cdL,0xc05fb7a38c246f85L,0xefe16be3a82cc013L } }, + /* 64 << 7 */ + { { 0xd42777314c14ee0eL,0xda8146d15e881c3fL,0x6b0746b099f1867cL, + 0x1ec73d72602dd4ccL,0x27fae51538081120L,0x6a677bdc2f8b2f2dL }, + { 0xb924af64d60544e9L,0x1439e183dcfc6b16L,0x4e88e9ae068565acL, + 0x8a3dbd25a9a4f146L,0xdb4a3e483f93f734L,0xb1971c058f1d33bcL } }, + /* 0 << 14 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 14 */ + { { 0x721bb8363a7f43c3L,0xab5b3108c12dca0fL,0x9cc9a78934853870L, + 0x78b604a7af598c4fL,0xd370375e476f27c8L,0x9f0415b80b15cba5L }, + { 0x2bcfd9a4d400dc1fL,0x2a6fe03b4bc62dddL,0xb05a6464a211b19fL, + 0xce059d419990b504L,0x011c5f87d94951d3L,0x13cec08900d9c7b0L } }, + /* 2 << 14 */ + { { 0xf365419f9b280fd9L,0x13e3b12746365672L,0x8a91c165c41880aaL, + 0x3eb27a97f9712fbdL,0xa6587aec76c55678L,0x7c3a04b702cd79cfL }, + { 0xfc878f9cda712eb8L,0x076e61170fca3e02L,0x09a184d8caf6df5eL, + 0xd32bf232aabcde75L,0xf601d0de03de597aL,0x85d2b5fcc5da2858L } }, + /* 3 << 14 */ + { { 0x3075a7636c888df8L,0x6305c20472e21527L,0x6b1d683e8798aad9L, + 0x0d09624680706369L,0x91db5e7f7b854739L,0x0e63cc6e02d72332L }, + { 0xe929e3ea1f7ff6ccL,0xd53a18a145595925L,0x867916cb93af8be1L, + 0x757e9f56c5c305eeL,0x3f9071c75c83063cL,0xccc0f92d7f6d5bb7L } }, + /* 4 << 14 */ + { { 0xb6029961ae899afaL,0x8eedd66e681b6e1bL,0x82db693b4df3e5b1L, + 0xb5131488a0c3e357L,0xbfb01ff3ccb2f577L,0x28ea947027a72cc3L }, + { 0x26170928e39e325eL,0x42d4876b84f80188L,0x0bec6a634c872d76L, + 0xa0a7cc90b14d9c9fL,0x8a32d2c44f6c7778L,0xe7cd346e3b889a4cL } }, + /* 5 << 14 */ + { { 0xab35a14f5a4a3753L,0x1d0d5a142bbbd563L,0x54cfffc5998d4514L, + 0x1c02f381a77ed59bL,0xe4a7a6ab21c9c190L,0x50059df54a9adb60L }, + { 0x2d0383ba34bd7008L,0x894889bedf1a4f41L,0xe541c62612ac407dL, + 0xcc0e417964c3b62bL,0xdb8ca1f33a0978b2L,0x4ef45a2d287e8c6cL } }, + /* 6 << 14 */ + { { 0xea95b5c9437f2efbL,0x67d3e9b58e52ce8eL,0xfb33102488ff5455L, + 0x883ec9fcc3101dedL,0x056218e20ca5f1f9L,0x4c9b2483bccc65d8L }, + { 0x13199b26123db2ecL,0xbc1d82479aff90dbL,0xc4a9311d367516f6L, + 0x3b40c867cb6e90d6L,0xff674ff84034415cL,0x2787db45a1821e7eL } }, + /* 7 << 14 */ + { { 0xacc263fcadeb8508L,0xb52ebcd719854c90L,0x3d54e7805f2ce0aaL, + 0x2fc056a97e02e760L,0x47e7173e32da5f93L,0x1d468de3fa893134L }, + { 0x9adc877dd73396b5L,0x430826afeeb00c82L,0xfde2c3da96a673caL, + 0x467575ad33e43f9cL,0xc3b2c3a1ec1df2f0L,0xf0348e6f2252a8a6L } }, + /* 8 << 14 */ + { { 0x860ef794609683acL,0xf0631ad39af1c522L,0x322c83662ee7f522L, + 0x58ccd95f54122af0L,0x7454880c2bbb2d80L,0xea173d8286d8d577L }, + { 0xd5a3057cea1cc801L,0xfd08d482bbb2a189L,0x26aac99ec3c512f8L, + 0xc3eac036556d891eL,0x866c3aa7bf9f6112L,0x7c4c8fb9c144f7e9L } }, + /* 9 << 14 */ + { { 0x989eef73a9109d83L,0xbe43bd378edd17dfL,0x14a63abd1b17029bL, + 0xfd14ae365ff76860L,0x689dd0a6b8730632L,0x01eb37f147342f9aL }, + { 0x619bab45e6c446a3L,0x93d26fc97abddba4L,0xda6c120486ffa4cdL, + 0xc608937548758279L,0xaf074ea3034a7230L,0xf220244b82ce176dL } }, + /* 10 << 14 */ + { { 0xc0c1eb0f8343f5ddL,0xa205e66a0126fa2dL,0x37530a3244fd8be4L, + 0x3c7af6f696ab64cfL,0x1f04305076657202L,0x2c59d31c828f3fb1L }, + { 0xa61cba51e7f5926eL,0xb2de427391ebeb81L,0x976f2c34bb855476L, + 0x0c6c02c3269e4f86L,0xc69bed8fe2e01fffL,0x19aa421c480bf7b4L } }, + /* 11 << 14 */ + { { 0xb32e8e229affa929L,0x69ebb533bb7db327L,0x10ac3360a8a8d088L, + 0x066cffa7c485517fL,0x2393e74c12b8eebaL,0xb3a8825a596c8412L }, + { 0xe2b99fc3bc8b6b92L,0xd7716da085ca802dL,0x92f6693f4de5101fL, + 0xe8b0442304be34eaL,0x05b44ef648324966L,0xa89d9499413df57fL } }, + /* 12 << 14 */ + { { 0xad0d24c7b617206bL,0xb8be483f9dd13f59L,0xa55134ff7655aa29L, + 0xa3d103857a5e217eL,0xfbb9eeb53a21b295L,0x1de71555c84a136dL }, + { 0x7579398e0b7487b3L,0xc6ca9575a14dce87L,0x99b32e1e46452257L, + 0x99d54955479d8f2cL,0xc2a8a6a1930b80efL,0x58d9db81656c850bL } }, + /* 13 << 14 */ + { { 0x0c8fe2e04d89b43aL,0xe4d923e77a04e492L,0x49ecb701617df01cL, + 0x6d80f249bff9a819L,0xf01e604acb7f86c1L,0xd6d3a6664b7f1455L }, + { 0x657801c19188fb17L,0x339d79450dc92875L,0xca798cf57ec0b757L, + 0xc0808852a62301c2L,0x2dda13558266c908L,0x22bcde8f5e55da21L } }, + /* 14 << 14 */ + { { 0x6c85a0eda682508cL,0x8350b515edcce6c8L,0xa84a67656f95898dL, + 0x55b0ae971e419847L,0x11115c6edd6a885dL,0x6f0beaf64fb174a4L }, + { 0xaaae44b2815af3afL,0xcf0697b9927a2c1cL,0x37639d62d7d645eeL, + 0x157b7eda2effec37L,0xb55e50759b9c66e6L,0x33a66a1f85f597ecL } }, + /* 15 << 14 */ + { { 0x8260c5339b49bb46L,0x3f3df9d6437cac27L,0xd0723229d972d2a8L, + 0xe544a216d0dd92abL,0xeea4a0f5a03588f6L,0x54006166b218dec0L }, + { 0x0fae2be85778113bL,0xbb9618d68d570227L,0x3ba87360297a47aaL, + 0x9483a8399a76dd6eL,0xa803edaf6eb061b7L,0x6790050cf8067cf4L } }, + /* 16 << 14 */ + { { 0x171898aa8f7782b6L,0x8b7a706b499b3a81L,0xbc0e835ffdb2c1baL, + 0x4ee30281591f5aafL,0xfd71de3bcc272c6aL,0x532800c46e93f68aL }, + { 0x35ee08048365c576L,0x6c2bcc94cd4c0221L,0x49f37ff5957b2ff6L, + 0x315d8e7e5ec029c0L,0x33230602ef324c12L,0xf5847f9b966b2578L } }, + /* 17 << 14 */ + { { 0xed88aa550bf098d0L,0xbc9888fd75f90180L,0x9040919207713428L, + 0x38922bbc1a1f71ddL,0xa430fb65bfbf0f55L,0xa258b9ba867c1998L }, + { 0xa7f69b03b7294c58L,0x2ec0c5de84dbc1e5L,0x41c9e5207dba8d62L, + 0x545573f1795d8285L,0x1c24a375d3075041L,0x687e1cc8fb6b88dcL } }, + /* 18 << 14 */ + { { 0xc29b123e1453b1e1L,0xefb0778820059b44L,0x15554ade9291671eL, + 0xeb5a1980429dea37L,0xf96dacbb6c4b867dL,0x4f5563d6abab4d68L }, + { 0xb5b0ecffcbe76297L,0x5a22996a51d6bd43L,0x0088ec95b7e5cfc6L, + 0x4863a5a1fe373e05L,0x42b7925bc244d93dL,0x85bad13540117113L } }, + /* 19 << 14 */ + { { 0x01725fbe8201fae2L,0xee4d7d382dc34bbbL,0xaddf878afd7c35bdL, + 0x56522d5865536719L,0x595c3dd8f772d4cfL,0xd87c5b6045af30b9L }, + { 0x9cc20b9de7992d5dL,0xdfd53d58d56f1964L,0xaf2947bdc7d42a68L, + 0x9322b73dd19e8ad3L,0xa73a9e843243a6d7L,0x9c7dc57992c203d3L } }, + /* 20 << 14 */ + { { 0x86283e21f9daa551L,0x47fd23f81f696f1bL,0x7d029b1bb9784a9aL, + 0x7c7798bea0c0acb5L,0x41241c716d7c682bL,0x11c6c1131d33c2b0L }, + { 0x5d469ca23565cf32L,0xa949f022bad4bdbfL,0x3d054cc2a13cf4cdL, + 0x13bd21669e3ce279L,0x01bc70e68a4beafcL,0xb39e351d8aba087eL } }, + /* 21 << 14 */ + { { 0x92efa2ebfa6cb068L,0x934209b29235050bL,0xc446ee28d5000c05L, + 0xd4e51912862fb7ecL,0xa53940f111193db0L,0x5f2ef2aa82a7fc57L }, + { 0x1a6b30ecb0210f49L,0x4ab1dac73899548aL,0xb116cc3186737a03L, + 0x56cb33809ebfa5b6L,0x8ac3b61fdfd918b2L,0x65867e3ca102e1feL } }, + /* 22 << 14 */ + { { 0x26072a5d82357232L,0x3762764e9f0fd2f1L,0x9c5813f60c16733eL, + 0xea2e0e03718951d4L,0xae195bd469e63818L,0x241a4afcfa2f9a6eL }, + { 0x0e97519f9165d59aL,0x416bd37358e5af1bL,0xc4e811288197b7ecL, + 0x4145be2c9c6ba0d0L,0xc82cb2a17d40b98aL,0xc3c28487bccfa8b8L } }, + /* 23 << 14 */ + { { 0x920949a810476d2fL,0x5b387bbe2502c026L,0xd1d61a9acd7f026bL, + 0x81003d7ceea9a3f8L,0x6191c15fba5b78aaL,0xacbed41e30ad7befL }, + { 0x1427f1fd6740f72cL,0xb4b5e7c93c475735L,0x6a374d1773029d5dL, + 0xc1e4bfdacd622400L,0x670b9e36c2686dccL,0x1bb236e08dd4085dL } }, + /* 24 << 14 */ + { { 0x84aa863ea4ee10a1L,0x24d805a687919ccdL,0x553f3206b5c399b2L, + 0x775b92173cc109bdL,0x25c01263fe384088L,0xa3c4418bd5f743cfL }, + { 0x3d69705ddf91f1f0L,0x547d46269ebddad1L,0x0198ab1a2626cebdL, + 0xaf8320f285b1afe8L,0xb9c0968ce17e6efdL,0xfedc75c290215bb6L } }, + /* 25 << 14 */ + { { 0x1d375f7dcee34c76L,0x2295f8dbaa486096L,0xd18577928285cb84L, + 0x53fe6bd5e8c46c3bL,0x6f6cb6c068ba071dL,0x654ab4e8964e0f1bL }, + { 0xc70857a9edf6aa40L,0xc313c7852fd26360L,0xd705a86a995998d9L, + 0x413d35efd6989c8dL,0xddc0b2070df131bbL,0x21f64be59c7d70f8L } }, + /* 26 << 14 */ + { { 0x8061d340143ff74dL,0x59e94fc6a23aa7b3L,0xf7c79a0b914c3b81L, + 0x5a836211702c6ae7L,0x2570d63c718123c3L,0x7e86d11ec9f5ce3cL }, + { 0x80f03f9717bcce3bL,0x073975b1465a7446L,0x29f66de7cb357aceL, + 0xe87bd12c04894fb0L,0xfc501a2651a0b5aeL,0x20a3170c02207a3bL } }, + /* 27 << 14 */ + { { 0xaab1f0fa2785a18eL,0xa50192fdb37c657aL,0xe7073b27f0c8a908L, + 0xf3e0451b2c82fce1L,0x8237e128c290240fL,0xc1c631621bbf66cdL }, + { 0x9bbcc2afb6639b7cL,0x07643d299bf0e0c6L,0xf7f070c7671c5be5L, + 0xb09a423a9870ac6aL,0x324503506656cda2L,0x4f404be80584abc2L } }, + /* 28 << 14 */ + { { 0x3ee52d8f5fe63bd4L,0x09f8405c7a7da77cL,0x35ce95c61881a757L, + 0x0a8cf9d9c13e3707L,0xe71258d548d2d3f6L,0xcf4fd6910bbe7c0dL }, + { 0xbd6496e1fb9479f1L,0x711c669aab8cb3a2L,0xcbe8501358cfdfb4L, + 0x655c902b59275b4aL,0x7e0ff05b20f722baL,0xcb00031d42b17aadL } }, + /* 29 << 14 */ + { { 0xc568cee0cef0ae1dL,0x1b3422ca7a55aae0L,0x8dcce5058bb536b8L, + 0x12df74bee92759c9L,0x029abaf02ef962c4L,0x5d30b4359bb1240fL }, + { 0xc62fe8e7d03a850eL,0x67da35b5b08dcab6L,0x6f4d4e75e8ca1131L, + 0x53d6fbf81bd5bf97L,0x596d850ceaa0b2c6L,0x32e918240e8d39b5L } }, + /* 30 << 14 */ + { { 0x3360ff11d54bf1a4L,0xbab994cb5c79494bL,0x953ad553757d7771L, + 0xf17f14f068b58ed5L,0x223615317523c422L,0xf0f05f965ebf0d49L }, + { 0x3386676549182267L,0xf87eccc1ad71c3ebL,0xd7708e18913d8dcaL, + 0x27fe27e1b193eef9L,0x33376365cc45e65dL,0x599b4778d700ac20L } }, + /* 31 << 14 */ + { { 0xb118f73509ebb3c5L,0x7299c7844d0d36efL,0x409ef9cde10b249fL, + 0x040f91d0156401b9L,0x6b9fa5b107467a49L,0x2ede334334415300L }, + { 0x0b3abc9c0edc8055L,0x58f850958ca04aa2L,0xeb0d3202e568b6a6L, + 0x5e57bb1a159dce4cL,0x8d3780e03b68641eL,0x78eb21a0d9f50517L } }, + /* 32 << 14 */ + { { 0xda643272ed068028L,0x86b52135a91fb87fL,0x23865a7c35b43943L, + 0x6ac015884606bbf2L,0x9660ab721559fb9aL,0x1fcb09e73ce2f1a5L }, + { 0x62af29ab793d2f0cL,0xad5aaef53aee7efcL,0xee9f29b744c11037L, + 0xb2a19cf1d36c2571L,0xb87d88e265b552b7L,0xd8b4f172beb253d4L } }, + /* 33 << 14 */ + { { 0x6776241470c50124L,0x157c591f57d0eb9bL,0x99e1e2d769b4bcc2L, + 0x81c2b923a9d94ed3L,0xbdd9294fecbf3becL,0x3825c29a4c4fb135L }, + { 0x431d9f26e915cc2eL,0xc4fb48afec1a4835L,0x97f426c09ada831dL, + 0x0be0cf81d5c48eddL,0x166ee4243d02771fL,0x810bb518b09de508L } }, + /* 34 << 14 */ + { { 0x9f4dd8185038ba67L,0x5ff1572801111ed1L,0x900d44f163de4d57L, + 0xa36c1a67d5db5e67L,0x2f01142e2bf5cea7L,0x1519ae1f59aefbf4L }, + { 0x7b963d1f6d989fcaL,0xa5bb3cb85fce44e1L,0x61087c9672fd3285L, + 0xfb2fc6c1c597ef26L,0x5548e25c81e70a6aL,0xa6c53d67a229d7bbL } }, + /* 35 << 14 */ + { { 0x9d11a26ab9678e36L,0x8142106fbe07b082L,0x3c31548b322fda75L, + 0xa87215ceb7299565L,0xb5229b119ea80113L,0x7221a40f43ae700eL }, + { 0x1ad48de8cc00aef7L,0xc4573660d266daa8L,0x1cb020a65761657bL, + 0x9e799be24588c895L,0x3d209df968561484L,0xa0fb323295fec6d8L } }, + /* 36 << 14 */ + { { 0x9292138a3acde05fL,0x7b23f51a50f9e7f0L,0x6ad891a1af59b585L, + 0xbd394db79654da39L,0xcb8c47315f7c6edbL,0x367bbb5d6d2d6e5aL }, + { 0x8df2c759f51dd55eL,0xce0924d8e6c3517dL,0x49c46188097a8072L, + 0x47169f40980170a7L,0x56198937b96df7ebL,0x09572534531fb3b6L } }, + /* 37 << 14 */ + { { 0x04c18873d2eef240L,0x5752cce75106879cL,0x4b7fbe6bd9736e37L, + 0x7c7f1de4c85990afL,0x0cda6f07a2324ca7L,0x0894eafa4d80c28eL }, + { 0x24bd95890ae7e6d9L,0x050d526aaba494a3L,0x4b05455ee583fb5dL, + 0x3b5fb27c6049bb23L,0xc7c9da6ecb5b411eL,0xc1f2528ebc38336dL } }, + /* 38 << 14 */ + { { 0x8b177119d62ff4b1L,0xb0c02e2783150269L,0xdbeee1f8428f9e51L, + 0x2a55661225ff00dbL,0xb4ebcf98cd0d526aL,0xc69f721fc0efa6abL }, + { 0x0ceeceb516e29d31L,0x0bf4510127d1c530L,0xad942f1f42a7383dL, + 0x2cf389eb03b8fa98L,0x1aa647651ec6acf0L,0xf7ac647c202433b9L } }, + /* 39 << 14 */ + { { 0x880bfb2caa7fcbf4L,0x18c2b739731cd693L,0xd093ada3ae39b46eL, + 0xd48a288796c6fb7cL,0xed7c405daf96bbfcL,0x6b63b9ee256335e4L }, + { 0xfd4795ec7ee8e89cL,0x4f3fa1ccb07320d6L,0xe16c594206b0078dL, + 0xb8c95b563a0b2914L,0x2b5b5ab42b337970L,0xcf612b4cb9f75ea9L } }, + /* 40 << 14 */ + { { 0xbfe63081596eecd6L,0x20eb6fb0a3a194fbL,0x4497ec2b8751a73eL, + 0xf90e9e4cf88ba0e5L,0xd5a9c5d55974eca2L,0x9fc120ade4f3e171L }, + { 0x9ae058a633330640L,0xbda3227855bc8aaaL,0x7851cdbc1c9688a9L, + 0xf68d7d9e1d950edfL,0xc89c645074e06425L,0x62406f3b6116d386L } }, + /* 41 << 14 */ + { { 0x1094390070e509fdL,0x0a8e3db09af61ad1L,0xa487a61538d7aa57L, + 0xa9d56bc5ed020b3bL,0x7ed2294f638b35f8L,0x53d6870dc95fb42eL }, + { 0x85e828494c2207d7L,0xf88831baf0556be9L,0x64a547979fe416c3L, + 0xd61b652e779bebaeL,0xd3f43e2f2c0ccce6L,0xd5119f341f680ab7L } }, + /* 42 << 14 */ + { { 0x466f42a1191938bdL,0x95ec31c036f1dae5L,0xa7f350d2feaa8b55L, + 0x66434577555c505cL,0x0c668e73f55d1ca4L,0xd6af5ba4a7bd7449L }, + { 0x581e14ac1a79d8c9L,0x9761d9763054e915L,0x928e7415d69220a6L, + 0xc5bf4bb405bc4a22L,0xad033b7c45d52313L,0x4e67962c75d66dc7L } }, + /* 43 << 14 */ + { { 0xc60e17b2e2300049L,0x731c2fa54107f308L,0x848f6db7cc2982b3L, + 0xf251c21085275d38L,0xf5cac5b2128c8a96L,0x3c012933405b27f0L }, + { 0x9b0a61520b8b15b7L,0xb1c32dc691fa4548L,0xbe7b7654f366d677L, + 0x7e1f33277147a660L,0x11e31a0eeae310bcL,0x3edef63c1b86b525L } }, + /* 44 << 14 */ + { { 0x6f7e7259c6334c8cL,0xe34cba49b4f2333bL,0x157bf099211d08c5L, + 0x9e39c5442988a4daL,0x796ed9f17a998311L,0x3f4da896d8d349e6L }, + { 0x8ab75656fab28acaL,0x3e215d5342d14b21L,0x50008fd7bec23301L, + 0xd6ee4853446e2c56L,0x203ff1c880da14bcL,0x27a4bfbbc333ba74L } }, + /* 45 << 14 */ + { { 0x745e69dfb3d54e52L,0x1ab2a03e7c405cbfL,0xda71141e0bc431b5L, + 0xb3a47e71aafa7c19L,0x5329594fa88a4905L,0x489b5928973aba07L }, + { 0xbe31a4d37350ad6dL,0x177e5285478a42a4L,0x45a101bf848eba6aL, + 0x4287dfd949936d31L,0xbc4c491dc82823c9L,0x87c816aaeb8b8055L } }, + /* 46 << 14 */ + { { 0x66f5337cf309ced6L,0x897cbcb9eb5ed3cbL,0xeffb601762c35fd5L, + 0xb4b702f081fd31f3L,0xd5203833f66f6120L,0x1d2d5ef318a84d91L }, + { 0x22f9fae70edb3857L,0x034197b3cef00765L,0x16d8c6b493643908L, + 0x90ac59e16c51708bL,0xbed18da32edffd9dL,0xc90ac893e750df1eL } }, + /* 47 << 14 */ + { { 0x4a0af827bdb07e48L,0x5588631e131f46ebL,0xda550ce1e503169dL, + 0x0e16b540f2cf2f14L,0xea19a70dc79930abL,0x5654aa5fa8925651L }, + { 0x2f1a14906104f9c7L,0x98420d6c654cf319L,0xf967467f3ca96df3L, + 0x6abe4e32dee1fc07L,0x913bdf2bbd07d17cL,0xf96f70eda8ef9068L } }, + /* 48 << 14 */ + { { 0xa0096d10b7f8286aL,0x493e88563015be8dL,0xa221d57c17f70125L, + 0x4f932f4fe425eb77L,0xf0fa00df78ddfe95L,0x68165f257866f01fL }, + { 0x01345af4b1693425L,0x3fc8d3a6bad5603fL,0x4269006f0bf46cf5L, + 0x96e3b6b77e340ce9L,0x2a4bda69df7c68b7L,0x9649d8b91b6574c2L } }, + /* 49 << 14 */ + { { 0x98f55e59112ef290L,0xa5516c3568909cdaL,0x40407393235165f1L, + 0x6eeeae510991970cL,0xae79ce1faaa6d26fL,0x8bc719b441d43f67L }, + { 0x4a7af92a39cc89a3L,0xf6d14f9a85c8ab12L,0xb9bfca97eb8d4851L, + 0x926b8155cd52b2f3L,0xdd17dbd48fa94f9fL,0xaf68726447cac5cbL } }, + /* 50 << 14 */ + { { 0x39d7c1729517c2c0L,0x6f795181166e2f50L,0x9f6ecb5dc0ad8b54L, + 0xb480afac8e75ce4bL,0xf51569203dd5ad07L,0x87c855e73799b80dL }, + { 0xea8c34d9538ebc9eL,0x67bebb6a957b303aL,0xc6511b7b4dfc6d7bL, + 0x9a40cf5885b02ee1L,0xf4fffbbdecc59a6fL,0xe85a7c115cebfbcaL } }, + /* 51 << 14 */ + { { 0xffa0118c4a33265cL,0x4c4051d583e0bb83L,0xcde22f8d7007d078L, + 0xae9ebbc2932cba29L,0x297c2252f7a82223L,0x662814f41a09fbdaL }, + { 0x3bfd965640be805aL,0xe49901e592acce09L,0x4e201930bbb6bb43L, + 0xfe94eb4dcc018aa2L,0x454d8c611dcf97a5L,0x11d8e3a230f1011dL } }, + /* 52 << 14 */ + { { 0xe745ee2c36cc8b1bL,0xb40c94e6e328c813L,0x4144aecd8bd107b9L, + 0xc35567890ea88fd2L,0x017460e30492a810L,0x0c63cd4410b8bea1L }, + { 0x9123e9a3c890f74cL,0x940fe6590cea499cL,0xbe306232c82e1bdeL, + 0x40544f6bc041d7ecL,0x46de1f3b477a7dafL,0x336551f6951f1295L } }, + /* 53 << 14 */ + { { 0x2a61217a09b3b9a1L,0x0736704635b71125L,0xfddbf1933df24d57L, + 0x33ddabcb4592d748L,0x2fa9ff8a25309e3aL,0xdca2dd2892a0e76aL }, + { 0x706350255dfbd02cL,0xe01c2553b6306b8dL,0xb14132905e91ddecL, + 0xf45221866f6de6fbL,0x2d48d001b440319aL,0x926e9b64fe67f843L } }, + /* 54 << 14 */ + { { 0x5580401264e2c160L,0xe154925a9a6c256bL,0xce2df32922260b79L, + 0x74824410c546d756L,0x2a1d0a5f79887083L,0xa2c040c5da3f7d48L }, + { 0x74058ecbc14f96b8L,0xe69c09d73415e476L,0xe5a93bb47a443fc0L, + 0xe1bb24800c31d7b0L,0x4701d669f4ab0610L,0x0ad815841eeb23e9L } }, + /* 55 << 14 */ + { { 0x823cd737d72b5925L,0xee09efb9fa38cb06L,0x6828dced4a21e81eL, + 0xab67b37bf365e481L,0x3995edd2b5a7c630L,0x4c24ac8806930b7cL }, + { 0xfd7264d36dedce0eL,0xdcab1e333e76fe1aL,0x6b40889a89a94f97L, + 0x7a1fd432b2a3b0e3L,0x121efaea3ffe933eL,0xa81f6c6f843c3553L } }, + /* 56 << 14 */ + { { 0x26301455e5488aceL,0xdf39099881a20dc7L,0xac7d6049ee06c7f3L, + 0x547e8df33f248fe7L,0x5fc4b74213743dceL,0xa97721bc4c398630L }, + { 0x6b7877cc258aea47L,0x1cedce562d5c28d6L,0x7e930e419428d66eL, + 0x42c80757b97faf54L,0x091fe5ab3812e632L,0x2c29fd42e2e359bbL } }, + /* 57 << 14 */ + { { 0x2d9e65a61d7b990aL,0x8a9ab4bee2a8a6a9L,0x8658c36985e3eea6L, + 0xf352787df0de0b23L,0x872db1de1161aa92L,0xf2648c972190acbfL }, + { 0x9a34f1d09de72e41L,0x13860f846c086516L,0x2e9211b824127c21L, + 0x4e1623bba3697c37L,0x41d71f1df579c733L,0x33f0ebf7ca9f68aeL } }, + /* 58 << 14 */ + { { 0x9b51f4ca9f5a40c2L,0x38b59573682e2132L,0x5765e89dc556998cL, + 0x102fe894698a4a8cL,0x0bbcae977c6964d6L,0x8548f2c6dd7bb12cL }, + { 0x32c11ed9e49848d9L,0x1ee1b525135aefc2L,0xade5d14e812a5e4bL, + 0x0e122e7e15bb167bL,0x321594d4ec5c3594L,0xbcea8723a7c02afeL } }, + /* 59 << 14 */ + { { 0xdbf91edcaf87c75aL,0x9710003266582706L,0xb10cb32b1133a7b3L, + 0x70f5d71767e068daL,0x8d937e56b8e0c9a2L,0xd8a2652ee2a9afd7L }, + { 0x94d6cae9cc90c6ccL,0x3512f3abe94f68ffL,0x931ea6f09331ad40L, + 0x71621013daa3d4f1L,0x591c40bfb668a992L,0x5494cc174c6868e5L } }, + /* 60 << 14 */ + { { 0x7981826070ececc7L,0x8cc0b6e071cfc0e1L,0x998df6590276a6bcL, + 0xffb5bec11a43be05L,0xb93b1543f2beb640L,0x337703d456f3719bL }, + { 0xce74c17cd40a7375L,0x6aef79cab1aece94L,0xc5bdfb388876d218L, + 0xf71ce9cccea91445L,0x471cdbd1ed6e5f5dL,0xe0cc79cf10e56c08L } }, + /* 61 << 14 */ + { { 0x2b17e181794ebe48L,0x6111c897f28cdd32L,0x4d59199062dfeee5L, + 0x7b9d070241b14904L,0xa1ad534d5fea4804L,0xc08915d953b16c22L }, + { 0xa57c883e8ac9ddedL,0x589474dcda1d1bf0L,0x31cbf32ce9aa8e7dL, + 0x2abe9b60f0930d84L,0x604731b0cbdd031aL,0xbc35b1e4e9e1b3c1L } }, + /* 62 << 14 */ + { { 0x39300d55efeff954L,0xa9cf57f34fe9cffdL,0xe3315321b15aebbdL, + 0x26354c57b840b080L,0x2c690488476abf35L,0xa7303fe6d480cf33L }, + { 0xa50865295706c3b1L,0x4c26034eed0b2342L,0xf08d67be9ae9c452L, + 0xd4dbb9f5046c7d0dL,0x4435f1a3f9e5393bL,0xf47aae68cd4d5de8L } }, + /* 63 << 14 */ + { { 0xce9e5ddc06d5f48bL,0x22c1cd3e0ef642baL,0x2ad48eb9e9b8a960L, + 0x330074883ce26679L,0x495e62428d2de642L,0xcba5bf37e03b1a77L }, + { 0x9382c92de716624dL,0x410d212350a33e4fL,0xe55ee116e953e7edL, + 0x27e9a0584b840616L,0x560a5e4939473bd8L,0xbc1e795b382f3a95L } }, + /* 64 << 14 */ + { { 0x31bdb48372876ae8L,0xe3325d98961ed1bfL,0x18c042469b6fc64dL, + 0x0dcc15fa15786b8cL,0x81acdb068e63da4aL,0xd3a4b643dada70fbL }, + { 0x46361afedea424ebL,0xdc2d2cae89b92970L,0xf389b61b615694e6L, + 0x7036def1872951d2L,0x40fd3bdad93badc7L,0x45ab6321380a68d3L } }, + /* 0 << 21 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 21 */ + { { 0xc5cf8997ce0b5b72L,0x350adde19d7154baL,0x8139681e307b254aL, + 0xcc87fb5775cd94d7L,0x90e7027478684954L,0xc4fdf4c095ceb991L }, + { 0x91bbc0ab8762c84cL,0x5e09e226ce09e8adL,0x1cb83d704b93d45fL, + 0xe2299024f541da1fL,0x3eef7ce14b7ffd10L,0x53ee63bbb3fc1b9aL } }, + /* 2 << 21 */ + { { 0xe5004e8003682f59L,0xccdb9cb7f642ac0fL,0x405f50d1bd869f77L, + 0xecffa54de7ebea2cL,0x3354dc22d87620baL,0x01bb2988b1c01ff4L }, + { 0xd9370076e16477fdL,0x45303d2a2e71ba4bL,0xc0de76273291e5c5L, + 0x5cfebd87f0a7ca55L,0xde1162809e592a30L,0xdd26e577a78ebce4L } }, + /* 3 << 21 */ + { { 0x1e9b23b9ff1735a8L,0xc3bf3d5b2b0e4b7bL,0xd4cc00fe59b7721cL, + 0xd5c36f9c9e2f4cebL,0xdeca06bac90af70eL,0x42676f12416ee799L }, + { 0x0d7afe1b6f748c6fL,0x0b7a6de539c39d55L,0x11e43d6ee6eaed18L, + 0x5baf8602496087e0L,0xf833634fb1a3a66eL,0x25098c8a79398677L } }, + /* 4 << 21 */ + { { 0xe141e763d4720770L,0xb9739e70ddb3b450L,0x46e6cde496131446L, + 0x0458a5d5cb6c2ef7L,0xb7747634532f9fd8L,0xf62d372116544457L }, + { 0xbfacb4ded3100854L,0x70788a31b39d3f62L,0x9b543220f22d92e4L, + 0xaa4590f655723258L,0xc7b6730e01ddb8bcL,0xae252cf869e1e7bdL } }, + /* 5 << 21 */ + { { 0xc618cf0ddd4b8d8dL,0x471cda8640dcfbfbL,0xba0dd7ac08882ce6L, + 0x58e5d2f56cd336e7L,0xcdda8301af096540L,0xf6d268463cf31600L }, + { 0x6150cd982197efd5L,0x4440fbfa55fb0877L,0xca31871c90757f1dL, + 0xc4a1faacbdd756c8L,0xc9d4ac1bcbb8421eL,0x3c0c2914b17c43beL } }, + /* 6 << 21 */ + { { 0x46fdb65caa6fe9eaL,0xe0d48e5e05494cd9L,0x5adef5704afbf837L, + 0xc96ba4b91c9e2cadL,0x1e8158f7054a158cL,0x47be73209e38b88dL }, + { 0x9b99971e6d2993ecL,0xac9b0bfadf980eccL,0x9da09642d96ca391L, + 0xd67105369bf4305cL,0x40cc1adfa0dfafaeL,0xe27e32f8a209699bL } }, + /* 7 << 21 */ + { { 0xeaaddeb836e87d82L,0xc12587a71ffd7210L,0xf93d2f5c731f6838L, + 0xb96594e8f7097a65L,0x08d6717ab016e8d3L,0x9c378de81984d825L }, + { 0x627d41e7cb2a0c26L,0x1f447501c697ceb1L,0x8dc40831c760550bL, + 0x70ad48707fac97b0L,0x5ac7f22e7021c170L,0xa6f730e4929d5931L } }, + /* 8 << 21 */ + { { 0x7d27d71fd186cb09L,0x67cb7f4e3bc213c7L,0x418cafeb6075b2cfL, + 0xc0d691e6d93a06f7L,0xc16a95259dd001b9L,0xa0583230026f17b9L }, + { 0x4c1041b07845900bL,0x2874079147a22aaeL,0x8d08efd62c1758e9L, + 0x9cc6f207e6c3229aL,0xec69e902082d8924L,0x9cfa1deaf331dfe7L } }, + /* 9 << 21 */ + { { 0x7b5ab2afbce81cd9L,0xd25fa34b12028b49L,0xf9d65e6b63a659beL, + 0x6f88f1ddfffb943cL,0x38eb0d02b871cd5fL,0x732afedc558ad949L }, + { 0x4093ab05367d424eL,0xf73b23ad29de1be7L,0xce1c0093e7a50181L, + 0x6d05cbbe1e412cb9L,0xd3c1148b773a394cL,0xe04b5fdd38e50316L } }, + /* 10 << 21 */ + { { 0x1793535b8d0ce0f4L,0xe9b054b1ab73f7daL,0xd82a3ac1ee7bc6e2L, + 0xb28ad846b847f39eL,0x40975fa2fc10c012L,0x8de998619aafe68eL }, + { 0xa73f442584878534L,0xbe3118cb7a36a0d7L,0x3763a49e8fa37fc9L, + 0xf3f8ef82361f32b9L,0xea66f9978c1aebc4L,0x88600d648d9d024cL } }, + /* 11 << 21 */ + { { 0x11f842ca150a3325L,0xbae115c3185a385fL,0xddf9643637561bb0L, + 0xecea0cd9a4115fe4L,0x297720665893a694L,0x837e6880df408cfbL }, + { 0xfeb8f511e0a7fb68L,0xd21869dfa062b60fL,0xe2b60f46ca6a5e72L, + 0x64bbec184931d188L,0xfb09c90fe3ef3378L,0x67cbeffacd767337L } }, + /* 12 << 21 */ + { { 0xd35832381b289f6eL,0x10dac54a0aeb3bcaL,0x4df1c08d6692339aL, + 0x2968edec20054647L,0x34072618d74235a4L,0x00b4a7ae71d6064aL }, + { 0x23a8900e25c23f8fL,0xda0cb7fad7d0f1b5L,0x266211c56c8ecdbbL, + 0x0a4351b97bc27e4dL,0x98d54c97fc234258L,0x5ba534071e1a4dfaL } }, + /* 13 << 21 */ + { { 0xf07cfcdd77f083bdL,0x89bcae29d46712c6L,0x2089c3ab0f09bb8bL, + 0x3ede5a2a6b9a4028L,0x27ee18fe013066deL,0xc2bebbb416fcdda3L }, + { 0x6b3926af3a87cd68L,0xf52f0ef9f9a7b831L,0x4a39660a1ffc01b2L, + 0xe98f718d91aa6719L,0x8b0626f111d48e8dL,0x4a6a2e5b2bd93db3L } }, + /* 14 << 21 */ + { { 0xc3ddb6123ef24470L,0x98b66569bb3f99edL,0xccc537153a97a015L, + 0x0d9a6b4d04937b8cL,0x854d081ad9a575f7L,0x347bf0c0127fbd90L }, + { 0x6baa47a5c30987f1L,0x164b390dbfd0b503L,0x6672d1afe6a1f565L, + 0x9a50ee5828d5bb14L,0x2e23ab480d0226fcL,0x33eb052365cdbdbaL } }, + /* 15 << 21 */ + { { 0xa32d1a27d904eb73L,0x6fcad8d0c43c978dL,0x8cf1e7a19c0842f5L, + 0x2a6fa6d800328ae2L,0xa5905f67a1e3b06dL,0x458c8badaa8df96aL }, + { 0xee5b20c0b0d4b89bL,0x352ae0c4815c1af8L,0x546a7d7e6dd73b70L, + 0xa99882225f753229L,0xa38eb5d7efde47e2L,0x8290aaed92635ab1L } }, + /* 16 << 21 */ + { { 0x8ec4335fabe7c60eL,0x01f198c10a6a9fb5L,0x3ff96de001141ab6L, + 0xb21acc2c2eca98a1L,0x6154849010fdf648L,0x2c01a99cd1403e8bL }, + { 0xf1a35f306fa509d7L,0xf7715fe3e3f08e9fL,0x89c26c077fc9a752L, + 0x8d2535fe420d48a0L,0x80ec5ddd52fe2e73L,0x041b8df071704f39L } }, + /* 17 << 21 */ + { { 0x96882074659a0a12L,0xdb0d63032a6bb752L,0x2a1fb2d740c2194dL, + 0xeb6b45ba2c184444L,0x10ee44368c179d33L,0x906d0e509391917fL }, + { 0x11bead88ca3bcba2L,0x25914dae4253fb99L,0x0445b31013c25404L, + 0x2a2eac6d515f53baL,0xa746a1d662bf0a11L,0xc7576a4c6573c4f1L } }, + /* 18 << 21 */ + { { 0xec159ed060c5bee9L,0x80282ff007746414L,0x8d53f05f40a97a54L, + 0xc92d8789f5d4eedeL,0x1edd798132344c09L,0x3bb9a444a92c7b36L }, + { 0xbf130f5cdd6c8903L,0xd270e7cf676fcab9L,0xac49744bdc5ae6f9L, + 0xbd0ccfcb40e39281L,0x222efa16a981b3f7L,0x92bcd2d700aeeadfL } }, + /* 19 << 21 */ + { { 0xecfdb91489c73e10L,0x83a5168becffe79cL,0x6a0d57c123e97ffbL, + 0x774121ca4b130cc3L,0x8556fdc5486967a6L,0x1249448d5fe4a7f5L }, + { 0x8c2c14440e93c114L,0xcde258573bc68985L,0x697ba7b0952758a2L, + 0x0d962b377aee19e3L,0xdb31fe8582c4c640L,0x6ecfaf36c89b4b85L } }, + /* 20 << 21 */ + { { 0xf1e8c5a0e06b40eeL,0xa55909fe59836af3L,0x77a13be8a3a4ed95L, + 0x47408650bbbcde0aL,0x95b455c2b4fba7b7L,0x4983f5ca4321117aL }, + { 0x37bab5d1e18d304fL,0x0edf3733f1d29206L,0xe23e4db4dab91670L, + 0x602a5265923ab7c4L,0x53ee98c6eb920a03L,0x1b592b626f25489cL } }, + /* 21 << 21 */ + { { 0x66c981d9d3543689L,0x20500cd7bb8f53bdL,0x807d43605179af77L, + 0x7280a7b27c286404L,0x75a74e630976a65fL,0x2ba9ad9df11c3bdfL }, + { 0x23f38f950ec6c760L,0xcad599102b858cc1L,0x4d9adb7efec23c19L, + 0xbabb6e45095e85c5L,0xfab66a97e5dac2e4L,0xcde4b15a08baf1f4L } }, + /* 22 << 21 */ + { { 0x148aad3207089d6aL,0x3ab5b0790303c267L,0x7d13995bc3153026L, + 0xeba27c192287f305L,0x5faa453367ae45bdL,0xbbb561db2f4e9488L }, + { 0x254d8977c8493163L,0x60d468fc5c544164L,0x0b6309a3a2758037L, + 0x8480e16b1f9add24L,0xf1d99fd2902ec661L,0xd32df254cb6dd6f4L } }, + /* 23 << 21 */ + { { 0x9a17f5c3610178b9L,0x75dded80bada5aadL,0x158249c23dbeb289L, + 0x1d0671cac300cf49L,0xa1649bd0886902f2L,0x79b0d6ed7d13be62L }, + { 0x78253e7549e2327aL,0x5629cc509af110ecL,0x4373a20059f8765cL, + 0x739f33289d9c5f3aL,0x3c7d5cfe9a5f997eL,0xf044d90d0559357eL } }, + /* 24 << 21 */ + { { 0x20aa15d97ab838e6L,0x6cefdd5a0c827ed1L,0xe2f205caef579e8fL, + 0xad27e38b325981bfL,0x087b8284c3438be8L,0x2095dfcf422360d9L }, + { 0x87cdf5ad76d096bfL,0xf1b97ce1e022adc3L,0xa71240c189104665L, + 0xeb5a175c9c1578e8L,0xbd66910ad150ffa2L,0xac277af811459a28L } }, + /* 25 << 21 */ + { { 0x7db4df62417fb54dL,0xf6c1e7f04dfb7c05L,0xfdcbd3777aa8ceb5L, + 0x0364b3bd89c24333L,0x8a721718fdd3dcafL,0x9a6015dcec2848f1L }, + { 0xd6571930d35ad1a9L,0x154a929199369196L,0xf3be7e228e514732L, + 0xfa3eef28b7fd3aacL,0x0bc3b2a69f60d298L,0xf6327920febfca58L } }, + /* 26 << 21 */ + { { 0x3b9de1baf8dc6030L,0xacc4224a2107fd1eL,0xa7d32fe86dcef0d2L, + 0x353d5e88dd83fb28L,0xd552c3ce50bfb0b2L,0x69bc0e686cc8ee7dL }, + { 0x965c0ca21d9c74d9L,0x5cd163a406ac3ecdL,0x57910a828e98b581L, + 0x1d0fa7523d992afbL,0x862d3184e7d12701L,0xab6a288c6c7d161aL } }, + /* 27 << 21 */ + { { 0x04caa9caf4f2b3e9L,0xcdb896141af43dd4L,0xb09444fd4e74ee8bL, + 0x9428849fec05d35cL,0xe29bb0e94765c0e5L,0x138c45f176d25d2eL }, + { 0xbf041131a0184d83L,0xaf321573991ddc4cL,0x058760a8ef31df7dL, + 0xe0b94b57f80dcf5fL,0x75572221850a4a6eL,0xc735580c104a4a1fL } }, + /* 28 << 21 */ + { { 0x9ba102f1a6b735daL,0xe073232edfbe7d06L,0xa8ac24ba57266a16L, + 0x07458ea42d5c4bb0L,0xfbdd0f0574868e1bL,0x73fa612a3921fe7aL }, + { 0x26f6714b0b32d8e2L,0x7a3cb2b48bceb95eL,0x756a68c6290f204aL, + 0x148fbb787fdf2b7eL,0x639ece6c57fe0da0L,0x315aee1e9a92b7e7L } }, + /* 29 << 21 */ + { { 0x22dc170769d10661L,0x8d89cd1c71fd40f7L,0xa22f11bfa2545040L, + 0x1247d019d44c2446L,0x8d17daaba08235c7L,0x7e6863b9fae7874dL }, + { 0x6d57431c0490d338L,0xc1459e61809d1f9aL,0x4eb14dce95b64852L, + 0x8d3a04e6a7b5a861L,0xfed631ee7bfa24a7L,0xf8f86f27af11723bL } }, + /* 30 << 21 */ + { { 0xb43b14146e63c833L,0x497a5f98c1ec160aL,0x112223de83eb3709L, + 0x293964a88d100b9bL,0x6db1d1931e3b2db3L,0x264bc83d71eced39L }, + { 0x8418eb43aa89c967L,0x51d41bff76f8620aL,0xa4017ee5cc416467L, + 0x1cc527231e216e36L,0x76ba536ce8069a6fL,0xa239b54acb77b981L } }, + /* 31 << 21 */ + { { 0xa05f2dbc37544476L,0xf18dbcd71b797f65L,0xc78131376d50cd5eL, + 0x2b509a4d6dee11daL,0xfc0f0584beba1b6aL,0x3282624a9d53bd6bL }, + { 0xa0944e5c16b7187bL,0x468a79b8aa2f99e9L,0x32e4644b38bc4ed9L, + 0x5bc375d7e7cf71feL,0xe18e3c0956617861L,0xbce9ccbce69255bfL } }, + /* 32 << 21 */ + { { 0x498808edc65fafceL,0x3676a7cc4e806bc3L,0x796e25f176c6b964L, + 0x1aced64bac474261L,0xa62470fc29a460c1L,0x77501dce5e751e48L }, + { 0xcc00053b6d9e3641L,0x2b5bc4ae9a3f5a0bL,0xddaccc2e3f9ca178L, + 0xad33f34a0b80d1b0L,0x6a76df9364642225L,0xc145f36f778e761bL } }, + /* 33 << 21 */ + { { 0x377fc5ac575e74f6L,0xfefeb2327736739fL,0x62ba076a9fc2d5c5L, + 0x6f3c6084baf0269aL,0xce2917688fa7c145L,0xa60bb8905b3f2333L }, + { 0xa811055dd900095aL,0x92d95e7b385bd4f2L,0xba54f444d33c2a43L, + 0xc1b131327d12754fL,0xdcdb54821556f5e3L,0x55377fc539ca4b94L } }, + /* 34 << 21 */ + { { 0x455f65d1a0cbee78L,0x554eccb566225edbL,0x306400b47a4e014fL, + 0xef3e02eb7b67025aL,0x7d4efbaa997a633aL,0xd43c6eb8672c90b2L }, + { 0x0ed2d88d7519da07L,0x864377854b9d51e8L,0xd5900a2e2e3ab57cL, + 0xc02f046b69bb0a39L,0x06d825a6bff12faaL,0xa12e5b0d5d3ac267L } }, + /* 35 << 21 */ + { { 0x1716be5ba10508b4L,0x8706acbe7e37fbebL,0x3881f54e44e3d127L, + 0x54e20622a864d77dL,0x26a194616b83325eL,0x0d57be814c15a8f4L }, + { 0xb10c0cd07b53b476L,0x3d016ea097d39c64L,0x4d7df7c15315bdadL, + 0x6fe5a1acf060cf4dL,0xd5e3d05396846b79L,0xebc878f79e3c8028L } }, + /* 36 << 21 */ + { { 0x5b849ed8d0d193acL,0xe983abf773950501L,0x5ca162770854a569L, + 0xb0b284d26904bdceL,0x9c769d269d4fadecL,0x98e5e9b912677284L }, + { 0xd9246836b557f2cfL,0xbd47433069d46374L,0xbce8b27b9b063a22L, + 0x08da2eca37c5ba26L,0x9e742de8d4b26479L,0x643b752c102aa36cL } }, + /* 37 << 21 */ + { { 0xb72fae566fad22d5L,0x1e921426cf2fd62bL,0x9f31293d4c225102L, + 0x78d43a621975afbbL,0xce2787303cfee30eL,0xb88590d77a82613eL }, + { 0x42f86567560b932aL,0xc2d98915a7c9ed68L,0xe70e41fb349a9750L, + 0x7e7fdd2c79f9582bL,0xf3d6ab07da737c0bL,0xba247c0b9f3cf823L } }, + /* 38 << 21 */ + { { 0x4bebaf153dffdbd3L,0xc37d4a04fcc967a6L,0xeabab9aca0435a65L, + 0xf23d1d58f9ae9c52L,0xce229a798cc8f7b6L,0x4a61e6ebf5e11e61L }, + { 0x770e1dc6b20f2d8bL,0x199d20e8cfb9e820L,0x9fd709c4c381a22bL, + 0x6f53a358b1d52a98L,0x4b1a018c66f511faL,0xc7d2d49375d3a666L } }, + /* 39 << 21 */ + { { 0x3b2db5e5550791d3L,0x034ed5665bbb686eL,0xf019f161e033e3eeL, + 0x33198653acd2f0b5L,0x368d89e41ee8273cL,0xa7ac3b507f26daffL }, + { 0x73d8d7df006c0037L,0x98b5937de73cf271L,0xc3bc340be917247dL, + 0x799ea890e45f37afL,0x27be0f5a25e8dd2fL,0xd70ec41c3bb16923L } }, + /* 40 << 21 */ + { { 0xd30302352679072fL,0x73dfdc0f95dad4c8L,0x53649b575c4630f1L, + 0x60197fc08d098d74L,0x9c295d54647f5cbcL,0xfa5f1bc6c0813efcL }, + { 0xf6e08007d2e49417L,0x4f7d4b3dab579569L,0x7af3e08e11d9b388L, + 0x073ec38a5db61c65L,0x9b480cb89db4dc4dL,0x9be2ce7e372fa82aL } }, + /* 41 << 21 */ + { { 0xd87c0b55ed1b6d83L,0x3b47443adfae29cdL,0x16c5b0e52147bfdeL, + 0x98812fd0663cbdbcL,0xe3cea04955ffe911L,0xfc1e9d9cc5df31caL }, + { 0x7ffa90f9902c4ab1L,0x2cf973c3669a857fL,0x89243cfc94b109adL, + 0x222d6fdb536ee544L,0xa48b1b15fd488c22L,0x7120e3f0f318ba27L } }, + /* 42 << 21 */ + { { 0xfbb8a3cd47813054L,0xa2d7255d462ac3f3L,0x341bc10babdfa7adL, + 0x01efa884ceb9ea50L,0x30fa0f903f5bd09cL,0x8aa309453abd108aL }, + { 0x0ab7fe23f9ecab6fL,0x0585f72a5ec032bcL,0x686a7d71cf9f4fcdL, + 0x096bbf04f769be8dL,0xa309931250b64584L,0x67be53402e216060L } }, + /* 43 << 21 */ + { { 0x4e14fa6eef252e90L,0x2ca968579b7db6f2L,0xf80772e3653f1662L, + 0x4f89e666cd28bb05L,0x7fa800cc77eef62eL,0xa3f6ef5963b2f3e2L }, + { 0x438d564bc81e600aL,0x8978912de14c1434L,0x33732892ea695891L, + 0xaf6aef0b1dc8caceL,0xcbf9580b7c509cb1L,0x2db9fbc11ed6fbdfL } }, + /* 44 << 21 */ + { { 0x408805a1fa7052bdL,0xe4eb27f75f825c13L,0x0a0cc8fa37ee34a7L, + 0x737b99a40c59156fL,0x78c2a5d8e1b55c30L,0x89d70b62bcbb2196L }, + { 0x07ad36911e862a0fL,0xaa1c9118c41cc693L,0x7e6f544c4e1f7359L, + 0xa5f4f5891bf9474fL,0xa711efd9ef56df82L,0x0428edb7e3de91fcL } }, + /* 45 << 21 */ + { { 0x67f403610905be0fL,0xffe68b80c12178bcL,0x41bef79ec6a673aeL, + 0x347e8ba81bc77376L,0xd49956d60e589da2L,0xadd54508fed84dabL }, + { 0x18868a4a462749f4L,0x2048cd88ed323e71L,0x7b27932aa28d1f02L, + 0x3cf6107412e4ddccL,0x0f6198631360ecc5L,0x40e5e08b1330d33bL } }, + /* 46 << 21 */ + { { 0x79b68071e3ad573bL,0xcb070412723966f5L,0xf4610fd1964b453fL, + 0xfdc9dbbc8bcee838L,0x3e191f3bb5ca4f20L,0x90d85084c02e0af0L }, + { 0x4e3f57a70ee64025L,0x63f339acdea07a5cL,0xf255b5045eb4081aL, + 0xe42bd241b4cbb0bbL,0xafa58985ff68c5c3L,0xd36cf7175b55e6e5L } }, + /* 47 << 21 */ + { { 0xf2b06f4b95d37e50L,0x7da1d2af3747c79eL,0x18a37dad6ad0092cL, + 0x9f4a6f081a8f207bL,0xeb1fd3f2cf0fed15L,0xfb9911e4384eb46bL }, + { 0x5f07c680b87cb035L,0xc49935d189e1531aL,0x718f6bd09ea02056L, + 0xadafb67b18a4ca31L,0x26cb0f368477f396L,0xec7775df62ec2172L } }, + /* 48 << 21 */ + { { 0xdffb03aec10b43aeL,0x39b1266e9433a54bL,0x4c262521b19fe0dbL, + 0x0ec1e54f3d5c7feeL,0x2856510b05e68e1eL,0x49382c1edc80b8a6L }, + { 0x80a509312471bdd5L,0xe8cde18581974aa9L,0xca6112ee28235c52L, + 0xd28a0eb8301f9653L,0x22b11e26e11fcdf8L,0x97e6fc5de4d735f3L } }, + /* 49 << 21 */ + { { 0x7fc264d35b253506L,0x1a11dd9cdfe2be8fL,0x2cbcf79c711185a3L, + 0x2208200a46806ddcL,0xf2764b6524e75d8aL,0x71a71bcdfcb43c25L }, + { 0xddd0cd3586a895caL,0x5ec28b469e2caf5dL,0xeb749df9f6614957L, + 0xdae1dd77eddd371fL,0x7ce493b556dde554L,0xc1627c06d6e5653cL } }, + /* 50 << 21 */ + { { 0x7926553cdea7472aL,0xe1e9480d3ba7f351L,0x242a641b1b6a2fe5L, + 0xf4af10091f790122L,0x5a2e2f95967810a0L,0xf1eaec6e2ed57598L }, + { 0x34a32da96b9f2421L,0xdc32daa8dd820372L,0x8b2539fc37a067ecL, + 0x2a495112820969ffL,0xea7c1829a699c283L,0xb4a1083dc2c58cbbL } }, + /* 51 << 21 */ + { { 0x1bcc30812e59d7a4L,0x557be0b2fac34690L,0x5b2868db673254faL, + 0x62e150a49e1302c3L,0xe29e9b445772138eL,0xc76bf4fd7ccb31daL }, + { 0x8d687bbb34c905c9L,0xf4f207030786eeb2L,0xe56a494c38deb469L, + 0x759e75e2cc6bbfa8L,0xb11903aaa59eb766L,0x3f6928c5c68b3bf8L } }, + /* 52 << 21 */ + { { 0x27fa09ebcdded185L,0x763b655c36d090e3L,0xbc586674dd864c93L, + 0xa1f84ff34c7074b8L,0xdf5261d17cf08435L,0xc57860f6fbdaff3fL }, + { 0xfa49af22252d7f08L,0x2367bf8c8db5f89fL,0xad6443ce6dade92dL, + 0xdc5265138d1af3f1L,0x62a282ecc720ce46L,0x1769b74c9808b416L } }, + /* 53 << 21 */ + { { 0x4ee11333ec598f02L,0x4613ba038c7eaad5L,0x48e0bfe61b1ccd1dL, + 0x6e115b6b507b705aL,0xc4d38e4992874d89L,0x30460a066dc59fc4L }, + { 0x75de8dcba0f7ea87L,0xba96718125101367L,0x9d7b03314a742660L, + 0xb4ca381d8c304133L,0xb87b896d65846055L,0x8dd96f0513d381dfL } }, + /* 54 << 21 */ + { { 0x43716f0c3e25b7b3L,0x00caad210aeb5d75L,0xbfee232559a6cb66L, + 0x06c1d812ad059aaaL,0x42d0af57c8bcc046L,0x37968ef70e409a85L }, + { 0xc5c3812ee3be328eL,0xaaa74bf166547ad7L,0xb292af92a15a0db1L, + 0xc0645385e5d5cdbcL,0x2dcf4ca937ec2c28L,0x3f75d089f0cb1694L } }, + /* 55 << 21 */ + { { 0x7e71fba26c0204d3L,0x6191ad249a40b4aeL,0xe2c7ab6bdda24cecL, + 0x5a8fc77e95b26a2dL,0xa6d8b2e43f1c7e44L,0x42d485e4e0a0e08bL }, + { 0x8697386ed7e3b896L,0x5b960d76ee7e58caL,0xda950e9a3fce610cL, + 0xb85c7842803c67dbL,0xed8a53535e62ff2aL,0xfe6b0e2c4d674e7fL } }, + /* 56 << 21 */ + { { 0x46a2a08be26d822eL,0x63537bc689d6d6deL,0x28c556a2b3df9fbcL, + 0x81d3161eb121d512L,0x4e27ce0b123bc86cL,0x1ebadb85bfb240d1L }, + { 0x86edb71a1156314dL,0xf8ac56fd113961bdL,0x2f6bc6d8067f586fL, + 0xf558b8833fe8e532L,0xe9433e2321a7997fL,0xb86f039c87e53b9bL } }, + /* 57 << 21 */ + { { 0xc022a16d78329681L,0xc3da7bf76b1226d5L,0x47ef18daa85c69e3L, + 0x4614f0ee45cecdbaL,0x9126fc2640f19d1eL,0xcdecb2693f5ca09aL }, + { 0xb62a831257a020e3L,0x5f9a8ddc8330d472L,0x37e58ab3eb208a24L, + 0xe64ed285ee4b8687L,0x752fa22a74a82625L,0xa67e24609b25fbafL } }, + /* 58 << 21 */ + { { 0x89e3d770e6b94044L,0x50f50d1675a1a8c9L,0xe73c51d95344c139L, + 0x97a8dd8411723e9bL,0xba0663c57de5dcf2L,0xf26eee6c3a6b588fL }, + { 0x6275b2a9211b989eL,0x32ab4b311608f16eL,0x9e47b2943fdde5b5L, + 0x63c50a50614bae9eL,0xffe4ef05e31c05e7L,0x2fea9142b7db4ba7L } }, + /* 59 << 21 */ + { { 0x27f286db0874c6f6L,0x26de6376e6ec0054L,0x56458a082ca84fc7L, + 0x07bcd4011fccf1b2L,0xb8548e74bae6f486L,0x0ea5857a0de2964fL }, + { 0x8e8df866e50fd2a4L,0x3b07d1a8710fc74aL,0x3e4cc4f5a1fe92b9L, + 0x7380d0836e52d244L,0x4d75e1c12796278bL,0x9eb279258d33f4d5L } }, + /* 60 << 21 */ + { { 0xce7abd1ba225f084L,0x696e1eaff803ee75L,0x66f2789989415775L, + 0x14df21a29eb4991eL,0x012a6413fe2a0769L,0x022cf1c8626f421cL }, + { 0xd4644d0460ab4299L,0xa43cc1732a8d453fL,0x7c4ab8c20ed14031L, + 0xd5854b98e14605f7L,0xd9a98c51fa7ff2cdL,0x7dbe8cbc46baf2c0L } }, + /* 61 << 21 */ + { { 0xf26574593c42ae9eL,0x7c3e5c13bbc289fcL,0xb815fe3fe096e7bfL, + 0x3eb67095da54264eL,0xbf5ca7c4ff3f8128L,0x8fc4a3f865db4dd4L }, + { 0x3af47b17ee382cfdL,0x8854132fd95520f4L,0x3387b11d33c5588eL, + 0x5d7eb66c0c662f93L,0xcad581933b18885eL,0x8d1c069a6f23c209L } }, + /* 62 << 21 */ + { { 0xa9498fb5212ee678L,0xa8824b696ade4a39L,0x422c074e0a406cc2L, + 0x7d38de650a2beef0L,0x482d16f81eed5bbfL,0x1c882006f18380a1L }, + { 0xf90f6c2bb98445e2L,0x36aa980b2c738d70L,0x4caff65b6785ad58L, + 0x1c282becf95863f8L,0x59ad267c5350b79fL,0x53ea042721cedec9L } }, + /* 63 << 21 */ + { { 0x5cc362909fa3481cL,0x1321acdd7292ac86L,0xcc30550378f4d6abL, + 0xf7917237e7d9154eL,0x591e5ba81fb39377L,0x0a387e4f7c541c76L }, + { 0x99685212a38570cfL,0x5cce35c8624cd61bL,0x375c68133aed79d0L, + 0xf72d4b068197e487L,0xcd672f7d129775c5L,0x944ef37f1cd768f6L } }, + /* 64 << 21 */ + { { 0x9c66a32becc5f6daL,0xe4ff40431719ba2cL,0x8c6cfab721e716efL, + 0x32c8fccb96ed74e6L,0x475890dd0b110c83L,0xdfada95f5cb4eefeL }, + { 0x9d7b89a693240fe1L,0x6afdb2d0210b776fL,0xc3f0b55bca7a7d52L, + 0xa6e56a0655d04585L,0x818e221c4257acc5L,0x05207b63fcb8d39eL } }, + /* 0 << 28 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 28 */ + { { 0x0a74da82d8ada6ccL,0xc6b98a3cbea55457L,0x896c26bb57c2f5acL, + 0x981e2f72845d45e4L,0xca152b877e9a7d36L,0x49666d457b582e8fL }, + { 0xea3b9bda49fc20b9L,0x5bcbc84a7c71f153L,0xd346fc5d5748a654L, + 0x7ac2f217622665eeL,0xbb5efe7fb6f16e27L,0xb1810a70644c9dc8L } }, + /* 2 << 28 */ + { { 0x98d089819bc5917bL,0x9f90885d187fac5dL,0x651b18287cfc13dbL, + 0x2d606e4c8655a658L,0xba64d3c563c91b71L,0x36c7d7d8b82a5090L }, + { 0x2d1dff02cab1d598L,0xa95788d7be78f90dL,0x1ac2ee6b0ea1fe01L, + 0xc100b60cd5c1273cL,0x4496084ceae603e7L,0x7fcaaf5f77c2fdfbL } }, + /* 3 << 28 */ + { { 0xa93fec0861b06e05L,0x0bebc26b7dfe6802L,0xc00b45a5cce5662fL, + 0x2e8a0a7f83a9a4a9L,0x6e0cdebbc0bbeb63L,0xc56a20fe63ccd80fL }, + { 0xfc10fa08b51f1f89L,0x4848392020ad9243L,0xfda69cc66bf53af8L, + 0x474b7440f10bb6c9L,0xcda9db3b1e7625e1L,0xe2f62c1e1dc7f3cbL } }, + /* 4 << 28 */ + { { 0xe8e3225a6abdd842L,0x8c85f18f3b367b02L,0xf147a4219f42edb9L, + 0x6d4bc00d0d411d4dL,0xa1a13a2770014bb4L,0xb896d97bfa10166fL }, + { 0xb2a1dfa70c302c6dL,0x0a24bd5d808a63a4L,0x8409a3a2f88c7359L, + 0x071f3838347726a0L,0xd18a551c27507bb9L,0xe0c4cc34b359b167L } }, + /* 5 << 28 */ + { { 0xeaaaf4602a44610fL,0x94d330b10392ac47L,0x989b9b673fe123f1L, + 0xe2ca56ddd8fd0129L,0x77d6d0cd624982a4L,0x55d4b2c371e1fec7L }, + { 0x3e9a04a0360e013cL,0x1d227ea9c9cde585L,0xac2b08e24fed8f86L, + 0xa1d1357ce199e8dbL,0x7cf06ec8e99cc964L,0xd9bc3a7fd85ec63bL } }, + /* 6 << 28 */ + { { 0x7d111c67017c633cL,0xadd9e9bd7d128a9cL,0x4cd8730c6db857e9L, + 0x3c9c03e9f4b46d12L,0xd42f0242a78472dcL,0x3fc0bcb2260841bbL }, + { 0x6332b11a8783f828L,0x65229d2af7be37ddL,0x402f28eee7e8944aL, + 0x3d1bab505ab28372L,0x6944e82cad5e1ff3L,0x65a94c0de8c75729L } }, + /* 7 << 28 */ + { { 0xa151dcbc2f7f3633L,0x4305312a98969226L,0x947afc00604d46e1L, + 0xc3c9d57572f3e28cL,0xce4c1cbd14b1cd1dL,0x8fe9a81df80dea45L }, + { 0x50920f3a9685f603L,0x51d380f00b80d89eL,0x19978ba13f798e32L, + 0x1294aaa6c5edde47L,0x280002c2be714a1eL,0xd998669ef212603cL } }, + /* 8 << 28 */ + { { 0xa44f6ef880e9d9f3L,0xaa7621e91d14d618L,0xcb0e4ed80eaf6671L, + 0x2bf485f8181514a2L,0x74670e180a2927eaL,0xe1b5461612c14645L }, + { 0x4068c0742a67ed61L,0xd10c7a57739063caL,0x391b651d698b2816L, + 0xf310d1696da14fa8L,0xa089be6bd8a578b1L,0xa314b3a844389ad7L } }, + /* 9 << 28 */ + { { 0x688ce85068fd73ecL,0x2cfb41040db1f500L,0x5d943b8d5b9bbc41L, + 0x861867f5403f3973L,0xc331110a2c766363L,0xb28a6bc153aaceeeL }, + { 0x2ab6e7aaadbee7a4L,0x316ca45c2f2b9569L,0xcac646e561d2428aL, + 0x6fd28dadc7cb6291L,0x2e28f68741e20ff4L,0x8cfe90eebd189d34L } }, + /* 10 << 28 */ + { { 0x09b8ed53339da6adL,0xe40727af26f54b8eL,0xc4a105979990fdb2L, + 0xb808656b5108236aL,0xb4411363aa4bd584L,0x19e90149288a0328L }, + { 0x5795d8a8fb0592f8L,0x313c68833213c929L,0x62eecb5b48f79d47L, + 0x3afcfdbab29ca224L,0x0072847d40075b08L,0x078eef3dd1fe0c8fL } }, + /* 11 << 28 */ + { { 0x719b51f20ca20aaeL,0x01ad630824b47b92L,0xd32460c2d3c807deL, + 0x8497786b0a1785f5L,0x8bd521355d714ee5L,0xc267724ed00f741eL }, + { 0xe5578dca9c266820L,0x97ff60085b62d484L,0x84c70e92e3bd1869L, + 0x412759e34dfa679fL,0x6bccc33fce497e18L,0xfb92405669056198L } }, + /* 12 << 28 */ + { { 0x664ff05368ed0760L,0xc3cdc99138fae9feL,0x3fe057aaf1f30a86L, + 0xbae990222d08c72aL,0x4f5faf3f6f09e13fL,0x44461a4413d26b29L }, + { 0xc2504c1bf95418edL,0x12766ea7db3ff26cL,0x2f956e9507a22399L, + 0x2716e70f5a00cdd3L,0x80c020140e9fba99L,0xbe587ac30519875dL } }, + /* 13 << 28 */ + { { 0x5e4bb6b83b23d2a1L,0x819a7c7705c9888cL,0x59e4c48ad0fec7f7L, + 0x4b212b21d6bb71abL,0x370cb90bcbf213f2L,0xf1ea07e0817549b0L }, + { 0x20e3115351a37b92L,0x30f9e70158d444c0L,0x7ac3a37b0b791ab7L, + 0xe456fd475265e4cfL,0x3e3f27ca29580ae8L,0x5d68a40daa2a1654L } }, + /* 14 << 28 */ + { { 0x14203d8720cbb917L,0x284e0c9db2a7424eL,0x99eb2911cefe7139L, + 0xa709c50f42925411L,0xa5a7543e5c79a13aL,0xe262025c6f45f023L }, + { 0x3966fd18828b9f40L,0xc660846913693115L,0xd7dfbcf644373027L, + 0x8e73fe6bbade7645L,0x88267c7b1de0dbd8L,0x1231ac99ce4e8c9eL } }, + /* 15 << 28 */ + { { 0xfd928bd90ba99806L,0x799ac97d1a864172L,0x5436a8cd129682b9L, + 0x4bcacda54e96fecbL,0x453af995c5db1451L,0x8fd382e07073b98fL }, + { 0x17165b8a644a7bbdL,0xd17d2d80b6118620L,0x2a4bf1b2c8cd1bcfL, + 0xdc7aad959ccc119aL,0x6d34084c3bcdbeadL,0xcbc5c5557e0663c8L } }, + /* 16 << 28 */ + { { 0xba86aec170128295L,0x83a09b65c12f35ceL,0x8978ff0789df2f80L, + 0x85750cfd97a773d5L,0x806bb730fc3f35f6L,0x04503422fed868c9L }, + { 0xdc0fcde086ffdbaeL,0x8f4297e11860f43bL,0xfefb7d028d3ad6cdL, + 0x5c652b5997293550L,0x32e12942ed5cfbbaL,0x06192aaf98800d22L } }, + /* 17 << 28 */ + { { 0x9bb8cf660002f389L,0x217219af51505913L,0xfea1388999ef8797L, + 0xad1b2383235597c4L,0x85ffabb70a3e3536L,0xd8235d9da00c725aL }, + { 0xfa9b0f4ba704dac0L,0x99d76ddc2f57fb9aL,0x5ed3683b18428507L, + 0x9e42bc54435307f2L,0x3167de67b4f36896L,0x8a0f99a0d539d713L } }, + /* 18 << 28 */ + { { 0xf0b92b8a4642d9b2L,0xce97828a3f50c883L,0xa33d62936f0b1194L, + 0x23417e0f3692f5b5L,0xc79b9491fb0b95bdL,0x5410e8c95e836b2aL }, + { 0x2b84078d29798fc7L,0xa8732e78d6628695L,0x39da93f898c766aaL, + 0x0797832d305e464bL,0x246069ab163f9f4bL,0xb867dcef53fb6170L } }, + /* 19 << 28 */ + { { 0x949c63730ced5c37L,0x6f8cd6e4fdb6464eL,0xbea902ae2e056dd4L, + 0x43871371fa0d560cL,0x162128e9e9ec2208L,0x84deda5c25060c6aL }, + { 0xa8a8a27c14160ed1L,0xf24bf3dda33b53cdL,0xd12038a976a6d272L, + 0xe64d6384ee8f2b15L,0xc404d580d3e91d69L,0x62cdb886a4888d17L } }, + /* 20 << 28 */ + { { 0xccf0fb423c9eb0caL,0x8703c6694aa03b40L,0x44c735a74001af07L, + 0x9616dd932e874ed1L,0x5c2e8520474ba621L,0xddf13cd3fa93d8b4L }, + { 0xd68c9b4575df1b67L,0x4cd242288f80d389L,0x0f1a16bcc09f47fcL, + 0xc414dc6a9cd4842aL,0xbb0fa94f1f353c6dL,0x405124551950d073L } }, + /* 21 << 28 */ + { { 0xbfe176f2dfb520a6L,0xf51917bced96d0abL,0x8131985078b11135L, + 0x6397f1288f006a55L,0x9877f30e576b5132L,0xe0cd103bec781571L }, + { 0xb4bf74e5bcfd5046L,0x04333aa4be9cc561L,0xc6dd1dbc1e066ca1L, + 0x03c926e1d3718e62L,0x13bf83d404309072L,0x79649ba0ba28ac51L } }, + /* 22 << 28 */ + { { 0xcb1a73c55abfe8a1L,0xe9e2e220deae1d92L,0x2d953d00514befaeL, + 0x74024df9b7940bcaL,0x9a2cad0cd13f4a3aL,0x8790b699360795fcL }, + { 0x63957f3b5e9982eaL,0x491bf3155b7d256eL,0x5708bd4dd23324e7L, + 0x9f11ddd397c4c8c2L,0x1823762f5b7f5162L,0xc45a3976cbfc9dd2L } }, + /* 23 << 28 */ + { { 0x806134cd30731f5cL,0x04522c23487c778cL,0x99b6e6a1651640a5L, + 0xe2d20ed87e9898d1L,0xcad25762069e56d9L,0xd4184f6e29ddfc7bL }, + { 0x1017badcc1aeaa34L,0x7d3700e7f3c62e08L,0x203dcf8d5e42399bL, + 0x05986c66b72795c7L,0x0b56ad9cc0925f02L,0x1f0e895bfe0e3bd3L } }, + /* 24 << 28 */ + { { 0x935b9e244d2edd5fL,0xfeb46fb5efb287b8L,0xa51700a3f5018b92L, + 0xc328beba23864e2aL,0x113b5c9a995f70c1L,0xc0b11c22da1b5d51L }, + { 0x9b99b907f4a360cbL,0xf4ee9995adf0b094L,0xf67c7cf2f94b3f0eL, + 0x664a51a1dcaf10ccL,0xa3709ccce937a669L,0xea97bace4862f098L } }, + /* 25 << 28 */ + { { 0x62c7dd9ed537ed6bL,0x8a82ae7ccc168feeL,0x96fcf8d19d00a4a9L, + 0xfeef6ec205096874L,0xc828c68969f4485fL,0xdc4903a6322563f0L }, + { 0x5339cad7d3280a32L,0x42ae434909ff15cfL,0x94cdb7790bbb6af4L, + 0x480f8a5515721529L,0xc2f9c4dc0ff28eb2L,0x9d2a405e1ff6e3d5L } }, + /* 26 << 28 */ + { { 0xfeebe7d29309e729L,0xd322c38aa30a4eb9L,0x18cb0ce12f4f5c8eL, + 0x08a073a04262105eL,0x6ca92585933f888aL,0xf4a080c903ca1489L }, + { 0x5e678c7949c8daf0L,0xcd6ef6ba5abfcf82L,0x61faba612a4fc564L, + 0x7cacb3dcee0b306eL,0x9fcfafadb5aae2a9L,0x193e841c4b8fb04bL } }, + /* 27 << 28 */ + { { 0x4db6f5f07ed99ce4L,0x1257bd9c2456059bL,0x546c764b43d3590eL, + 0x6d5062adebba72d6L,0x6858f04e2e8d99fcL,0x46554047b4eeee5fL }, + { 0xff433f63535f2da3L,0xd76777542b76d2e8L,0xeb6be9c88e838a3fL, + 0xb7a2d2c1145f8bf4L,0xf3ba128703bb278aL,0xd88cd51530c4a1a4L } }, + /* 28 << 28 */ + { { 0x51758334c942a3f5L,0x7cc01e8832182ba6L,0x772af25774de4fe6L, + 0xb1b3c448e9667bf8L,0x71cb27388079caf6L,0x48890c641d823a40L }, + { 0x47a5887b0e9edbdaL,0x916dfb0cbe089e5aL,0x3185090e1eb42ddfL, + 0x3c7eaa13b7f3af26L,0x940ed8c79e9963b2L,0xd85e77db3426ac10L } }, + /* 29 << 28 */ + { { 0xf21b47bfd7bbbfa1L,0xf757cb309ea0ea77L,0x6df7f53783b2a6dbL, + 0xb0808cf99eb8ed81L,0xc526bb6b64edb3b6L,0x24f1612068f72d82L }, + { 0x3e2e6af8f01cee94L,0xd2e01f947847ca60L,0x079dac3539e68ac2L, + 0xc30720b270cedeaaL,0x2f97f968fa6bf057L,0x2dba403babf6a743L } }, + /* 30 << 28 */ + { { 0xed99932452c802f1L,0x99f6864c5cb78b2eL,0x8f8a0a709b9c3693L, + 0x0b931016e2f598bbL,0x7edbb1b3a614fc15L,0xa0321b50e79f74c2L }, + { 0x834f3ee994bfa457L,0x5ffa9613006907b4L,0xa37e9b83d779b46cL, + 0x7a21743cf33b791eL,0x6646b89dcc28a011L,0x9b975ef8e2ba76f8L } }, + /* 31 << 28 */ + { { 0x166c7151ec72cbfcL,0x3d1f2450c9e519ceL,0xfdcc648e7efc0fa1L, + 0x3f5f90cf6db6d516L,0x8a5dd3df145830f8L,0x4d9938da4e5858e6L }, + { 0xe598f9d4dede1584L,0x2de5a26cf5c8f4e4L,0x495b750f364e20f6L, + 0x29291c445b718188L,0xe560d9ee3733ce27L,0x99b9d27d5b9d206cL } }, + /* 32 << 28 */ + { { 0x162cdf342efffd95L,0x92111fdad59086e8L,0x4478d114454eb977L, + 0x8ce403d8dea38a67L,0xd459633b7435728aL,0x3a7be4e3a63b0504L }, + { 0x0c74066b335dba3eL,0x4e8fb1d7c6ea6ee5L,0x3398b588a99690edL, + 0x4949517c3ad77562L,0xf9824f09cbbb60eeL,0x9fdcafdf85660becL } }, + /* 33 << 28 */ + { { 0x368bea127aa62889L,0x6096730506e1046fL,0xe69be05e564f219cL, + 0x064b9d7c01eab75cL,0xf16ccc9e0152981dL,0x708827acb178a3deL }, + { 0x320f6a8a93248b89L,0x532acc568084908eL,0xe494cd1f6ab586d3L, + 0x59c74cacabbdcde3L,0x3ccf84a62259abeeL,0x6657d1fad96bd141L } }, + /* 34 << 28 */ + { { 0x5d3a8252aa0a9dcdL,0x540e037af97fe26aL,0x4cbb768ca3f68f56L, + 0xf9608732652d7058L,0x5fae0f9f72cea8b9L,0x1a7edfd97d980da5L }, + { 0x9f00ee611791c34dL,0x6c95404c2bc25810L,0xabb1089e043a9faeL, + 0xe36fe9e1a7881ae0L,0xf163dc460fc04e9dL,0xb6955f2f129c7940L } }, + /* 35 << 28 */ + { { 0xa22ebfc7c23bcd94L,0xa653b119684fe9f2L,0xe469e28646b59d70L, + 0x0720daf3dad96b47L,0x5066df7871288c07L,0x7648d7d82905b5a2L }, + { 0xc6ab9c5c0a30a65aL,0xa00539f34930712aL,0x6a64738c7e894bdeL, + 0xd7f3a7459e8eafdfL,0x652a58ff8ce9f7b2L,0x7c9d02e4cb3782bdL } }, + /* 36 << 28 */ + { { 0xf26bd8618875d9e8L,0x22e2380dbea9c273L,0x5f15183791995508L, + 0xb97f40a6648aa1c6L,0x7478f5f83977d848L,0x21e876ae35b57de6L }, + { 0xf620b180a93fc7f6L,0xf49bd07e1b148996L,0xfb0857261c4f60e1L, + 0x6a6653af7ad6b84dL,0x913a2d022e05b686L,0x94746629407dda9aL } }, + /* 37 << 28 */ + { { 0xc662b0f68a97c714L,0x69fbf7d1b8fbbb02L,0xf3bb5a9c5cdff85dL, + 0xfade6eb036ee44f3L,0x6eb4b8266d0905c8L,0x6ab3e4a4391a34d6L }, + { 0xf490046478e7bdb1L,0x8bcd4bf23272c400L,0xdf9a81b78d2c9573L, + 0xb9a0ea166af43695L,0x3298a5d071fe768aL,0x53eeeb4333e87bd2L } }, + /* 38 << 28 */ + { { 0x87cdbfe6bb531d08L,0x384bcd0357957992L,0xc654e2c942008cffL, + 0xd12b50285002e06aL,0x41a34286a67db410L,0x31a109d99d6b2c01L }, + { 0x14d642da2ed35f38L,0xa06a846048ffd04fL,0x8291190cbdbeef68L, + 0xc8106239e43bb0c9L,0x4d7aa992c4bea448L,0x107b86efba3dd9b5L } }, + /* 39 << 28 */ + { { 0x3d870c3144fc1cd3L,0x34409eec0085e7b3L,0x67d5c1340d0395e6L, + 0x9c30dedae3f36689L,0x988ac951d268cc91L,0xdb05825bd2c9dfdfL }, + { 0x30ccc3b75d349fd5L,0x63383c0f60c3a79bL,0x4f45c81732c71964L, + 0x456679642fef028cL,0x82454c12cf4053f0L,0x7c1310fbed8077f0L } }, + /* 40 << 28 */ + { { 0xb8465d16da684157L,0xdadde1abb238faaeL,0xe2cd45e7c6b9bea8L, + 0x7251d4a15cf413d5L,0x615cea8baae1765bL,0x75aa831813f36885L }, + { 0x7d5b0bf7b8767cc1L,0xec38a8ff8022968cL,0x034805b62a07faebL, + 0x916f9eb033b7321eL,0x34963633c0c577ceL,0x8ee07efdabb8d3ceL } }, + /* 41 << 28 */ + { { 0x498606fc2d15a409L,0x2398e109d5fdcb60L,0x8ed8fcbc36540c3cL, + 0x94404e2bc1db3193L,0xe62b808b28db1c38L,0x545b60871ad1d686L }, + { 0xe8bf6489740f4264L,0x7ee76fe71809505cL,0xaa95b8c86f45a011L, + 0x9bd6111b55c715c3L,0xc5c736bc33165913L,0xf1e8cdf282f6c7a9L } }, + /* 42 << 28 */ + { { 0xeb09e7fa949d05b5L,0x49394c1b8d014014L,0x644874d73eb7abd7L, + 0x89c666e5679d2a01L,0x6ea98cbbd315bc8eL,0xd919142a37fa5a26L }, + { 0x042fbac56d0239b6L,0xbff2b086837c510fL,0x21e4d279d9883ed7L, + 0x6416e0239713c2b2L,0x3742c6d14ea05144L,0xff591d8fd5b00fb2L } }, + /* 43 << 28 */ + { { 0x0ae21b83c138ed42L,0xf1b0895a2ff30df8L,0x4d5d634d9559c6e1L, + 0xfd02f3a3098e5c4aL,0x7bc6b63152bb211dL,0x498a68fffb69f0ecL }, + { 0xd6fd5f443e69b479L,0x5ea1877d8c740d2eL,0xfaaff5f0ca605f02L, + 0xb3022f9839a03f5bL,0x3feb7c13aa253725L,0x119097a89dc33a73L } }, + /* 44 << 28 */ + { { 0xa0bd6c0da8a29345L,0xc676b6c55d7f5ef9L,0x303b6d7c20ad7259L, + 0x06542a19d8fe09a7L,0x5a06653ca959014aL,0xf45fd79a5bcfe0cbL }, + { 0x29058d984e583468L,0xf1bd25e60cd7afc0L,0x2a88246ef7dbe54cL, + 0x680eaff835e0ef3dL,0x5942c97f726e59b9L,0x43e971398d5c0825L } }, + /* 45 << 28 */ + { { 0x6656b318f7378bf8L,0xf9a838df182f1a29L,0x0d62dc5ede475756L, + 0x97564544585bcab5L,0x3e99f44c857a13cfL,0x8c3a0a940cbdde00L }, + { 0xa7be375833dd2d24L,0x629040f1bbb1c7eeL,0x0bb2ced27f0eab7aL, + 0xb86f1e1e9f474277L,0x60539a544a14ac4eL,0x9860f986aa90977fL } }, + /* 46 << 28 */ + { { 0x143fdef1fe944aacL,0xfd6700fdd24f606cL,0x5dad2e41737404a9L, + 0xb16c5d42953abdccL,0x132b5cd995be01c9L,0x2bf605d86fd01c6bL }, + { 0xed62526c8803881dL,0x3429579201788c26L,0x553f8e0f8d62ab25L, + 0x3b2df9cf9850ff9bL,0xb320ec40acb513b3L,0x86d61c988875dfe7L } }, + /* 47 << 28 */ + { { 0xe5fbda4daab3cc32L,0x556fcd2535d469a0L,0x414673d91c02fb7bL, + 0xc14ee9fd8bfe6a4cL,0x8ba0959d1133d9f3L,0x086a7c94e94338ddL }, + { 0x92c2f484cdd5a1b9L,0x97bb21f6ea0e0f9eL,0x99756b285411da59L, + 0x4b79c4663be739b3L,0x73502d3e706078fdL,0x6bb794100da7aea4L } }, + /* 48 << 28 */ + { { 0x2daddb11a406d4d7L,0xb02b5da5a2a33d81L,0xb73ce82721a6aa89L, + 0x10919587467506deL,0x0927724c428d8daaL,0x0ede991f7c17adfdL }, + { 0x8518dab1bf7ddb3dL,0x04b091c42a54e1b8L,0x5943c37f89e7a398L, + 0x8e63f5e8e273f6f3L,0xc6d0352b83143d22L,0x30e43182ebd1628eL } }, + /* 49 << 28 */ + { { 0x9bc5af5aedf58e50L,0x31a3beeeb0d51722L,0x5789fcf98cd467aaL, + 0x85d974897793faafL,0xcf09224ecc18f367L,0x4f293783ec7957b4L }, + { 0xb044c854c0be350cL,0x027caaf72a63996cL,0x5341b3f3cb85de2fL, + 0x0d261d80b106359aL,0xf63bfe7a8456af12L,0xa954c4400174c82cL } }, + /* 50 << 28 */ + { { 0xaf752854b02aceb3L,0x000c5c4222c194b3L,0x7e953b78ebd2e61aL, + 0x44dd61b4b9d68960L,0x282ef4216d454ed1L,0xffed862aa402ca61L }, + { 0x5fffddeed3e189e2L,0xf36379990daffe3dL,0x1b09a625857a8a00L, + 0x3e64ff63c1ced62aL,0x9acc484d10b63647L,0x5a470aef3afc8675L } }, + /* 51 << 28 */ + { { 0xe21acfec09ebdbaeL,0x512c66a729b064faL,0x15c08e1191835db7L, + 0x78fff5d665203a4aL,0x99259d961c73615cL,0x85b444b9f36024bbL }, + { 0x4909772df16932deL,0xcc4a526899a3863bL,0xe54557bd2ebff8faL, + 0x1a9b05b709bee4c1L,0x0d2ce396bdb2b785L,0xbd15bcec8ce7ef40L } }, + /* 52 << 28 */ + { { 0x606658a99991167eL,0xb8773e1572c4b43dL,0x6cb364cde025abceL, + 0xafa58e9b0c5a653eL,0xa7e35a54134a68bfL,0xcb831d42ba4d9db6L }, + { 0xae37348ede83ef97L,0x4ac64a6a62ddd553L,0x5feb5e0d715bb6b4L, + 0xf876efae043424b2L,0x7b56a291ad91a9efL,0x817c7053356f3adeL } }, + /* 53 << 28 */ + { { 0x0dbd99249e88115fL,0xecb57472bc568c61L,0xfa4f4a47c1058746L, + 0xb19006014d92c079L,0xe693577091026a8cL,0xebde8e65eefe8740L }, + { 0xe8bc6b3480a93b35L,0xc1c8fc0635518beeL,0xf7f4b448a47cdd36L, + 0xe4d040e0db4f3e42L,0x025fbdfb88345042L,0xfe6cc10f3fbe045dL } }, + /* 54 << 28 */ + { { 0x63ba344a1c20cb4fL,0x55f11c207e8cccf6L,0xe66e1641b5b1046cL, + 0x51cf6dbe758a460bL,0xe786a81e91bb5101L,0x6f4a976209cd4365L }, + { 0xe88b4d03fc565022L,0x46006d0ebfdf8ec6L,0x10a3e85781f4e635L, + 0x28ea91360a4a2e82L,0xf890ea9e757b38dcL,0x89c6789261312e2aL } }, + /* 55 << 28 */ + { { 0x8ce54e2a65d9fc54L,0x4776c1f13bfc0c09L,0x5d15fced99476b22L, + 0x2c5399bc1142dc7bL,0x6faef9d96c6ad87bL,0x4f238e48ca5126cbL }, + { 0xbc7136d607849dc2L,0xc840ccb1e30377a8L,0x30e0f0373a371bafL, + 0x5b8eef9bdfce4735L,0x1662184e514bb217L,0x010ebb8579e0918dL } }, + /* 56 << 28 */ + { { 0x3d6e8d6d8dff7dffL,0x6b6c194ad5be4ad1L,0x57b93f2db6fcd08bL, + 0x99f09948f3761f23L,0x4062f3d6ac8b018fL,0x4b58ac05a27af72cL }, + { 0x4abcc81504d0cdfdL,0xa50043e0bda4b02fL,0xe11297e527a9c083L, + 0x2b2d8d529779c5b3L,0x3de3d330dfdecfedL,0xfe2487caae7fc522L } }, + /* 57 << 28 */ + { { 0xc510bb0b7e7a66ceL,0x54a3e0111332f2c3L,0x6331badedc885f5cL, + 0x1a73c8aedc47d8b2L,0xc657edbb95d4e933L,0x30994aa335dc3ccdL }, + { 0x832d586fafe5be42L,0x3392b07ad44de522L,0x1bcea9a62982450cL, + 0x8237bf2b3709f75bL,0xfa4f2501ea9d03f0L,0xcf492df7bdacd276L } }, + /* 58 << 28 */ + { { 0x2d0f7f28af4ecf83L,0xc2863ae4d48229efL,0xc989ff3d7001268dL, + 0x7f07adb6ba225adeL,0x1564c1db450a15ddL,0x3bfea98c6524d417L }, + { 0xee3cd3ef2cc20833L,0x055c569dba767b1aL,0xef2eaf51351b1279L, + 0x4e02b1d163b809d2L,0xf0e943d00a14c115L,0x2bb3bc3f32f55210L } }, + /* 59 << 28 */ + { { 0x8f577dd79ed385ffL,0xdbcf0548a1fdcac6L,0x38555497c2352ff2L, + 0x33e2ed85eb9edab2L,0xbe4bd6db9e649ecbL,0xea3668f72c6e7488L }, + { 0x841627b8f4b91b7bL,0x2d61a0f7d487c7a7L,0x1932b198142d1dc2L, + 0x06dbb39a1a792783L,0x5be16e570bede1faL,0x4d3b197bdffceb55L } }, + /* 60 << 28 */ + { { 0x1c2fc5088f7a83e5L,0xa7c56233b9970c92L,0x949c71738bafa66fL, + 0x1e299b2d5bbb0490L,0xb9a79e7c18fcb9e8L,0xe6372ce69cb5cc50L }, + { 0x114fc628f465c6aaL,0xc55395208cb797f6L,0x7df94ed7a73ad211L, + 0x41eb8e1f8e0cd008L,0xb028725a004cbb0dL,0x1340186d372c1656L } }, + /* 61 << 28 */ + { { 0x5162886c203a829aL,0x60dbd8d464416392L,0x60589a51b5a10685L, + 0xa79ca259113476a8L,0xbf4f71100d7b37dcL,0x1a1b3fdf78bbb029L }, + { 0x2954d3454799a0bdL,0x7459eac788c256efL,0x61ac72653800707cL, + 0xd861f7764cc84f7dL,0x29f4e5bf84faae3aL,0x7975c9555aa1236cL } }, + /* 62 << 28 */ + { { 0x65f28419238c3c84L,0xf07d83ed90f1ecd1L,0x10307e1bf6567704L, + 0xa94dddb389d17845L,0xaa56f72788f39175L,0x01cf57e2a7aa55f7L }, + { 0x98f4340e77f21e8cL,0x8cd3e0a2adb036c0L,0x5c49ebf4af6b46ddL, + 0x312a2c32455f6897L,0x52fb4f488b517f06L,0xb0f373d442beff4bL } }, + /* 63 << 28 */ + { { 0xd9694bd9af44f9ceL,0xaf2cfbbc1ee29f43L,0xaf352b1c880f80ddL, + 0x3fdabd2142297787L,0xf5a2acc21c7916b3L,0x6154b3f2cc0d85f0L }, + { 0xb9ff2bea0bc58e86L,0x359eb0750561c3d1L,0xbb5a318fb93be593L, + 0x34af9320bff0b3b3L,0x3cbe89341d967c37L,0xd08e5f46a8e9a750L } }, + /* 64 << 28 */ + { { 0x4074ee27978029bbL,0xa9394bdabae0d0c0L,0xaa01d53972cecb4bL, + 0x4b0cf1279a7dd9c4L,0x3e3e3f165bc787cfL,0xdf48f7e1942de53fL }, + { 0x0cc69719567b9d0eL,0x631e33158d0d2750L,0x9fedc1e292314a09L, + 0x7547d22614a1adcbL,0x405561a48662b86aL,0x149fa2b1f5480b7dL } }, + /* 0 << 35 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 35 */ + { { 0x923d0b44bda4aaa7L,0xced14ce4fee29f7bL,0x1656be009cf5b87dL, + 0x13a37d0d1d61103dL,0x1d705880fb652393L,0x870a31bbed712ed8L }, + { 0x15ad02e6ad7c21e3L,0xf004e447c36c2831L,0x56aa376cba2b3ffdL, + 0xc3be2b2f9745443cL,0x47c8a870eb903660L,0x976c303e6c6c192dL } }, + /* 2 << 35 */ + { { 0x148bd39cf4fb80d4L,0x469b208cfff04e65L,0xf397fbe2ce548415L, + 0x441e5c2c87fdde9fL,0x6366b49ffee9c179L,0x38d02bd32938dc71L }, + { 0x26d450fac49c5444L,0x4569f95d2b23d3d7L,0x5f68bf4d298fd876L, + 0xe86df047544768b6L,0x40b69a32f8491267L,0xcbf3adf9f917c71aL } }, + /* 3 << 35 */ + { { 0x32498d4d8125489cL,0x965e8d07a5a46ae0L,0x6cea5e47e96a7e29L, + 0xf78293a4668039ffL,0x62548a96f63edd32L,0xe8e6af95a83e8256L }, + { 0x76e60c3b0db6263bL,0xa1ee4b0621b3d668L,0xa17dbf8b9e49b0b5L, + 0x4b29ba127eb366fdL,0x5e0ed781d29b565fL,0x8cb50d53199b36f9L } }, + /* 4 << 35 */ + { { 0xa66c703529aa3150L,0xd038a5ab479e61fcL,0xdee33e96b5ab5410L, + 0xd068929c7c57d123L,0x0839a208f1d6ad37L,0x8f523dab123f8178L }, + { 0xb3e5e524a67d3840L,0x88bda75e52eb59dfL,0x513a0ab7389f2dd3L, + 0x3197a145890bba6fL,0x61add75b6f66bf09L,0x5c9dfc154eef1722L } }, + /* 5 << 35 */ + { { 0x66dc285007769b1bL,0xe07fb7414d71fac4L,0x5ae688a6c2abbe60L, + 0x08ae92fadcbfd296L,0xbc291256b43044d1L,0x0e1d71ed9fcdf213L }, + { 0xf0c5b28102485685L,0x5d3f9302e3f68f42L,0xbbbfac50ffe4f036L, + 0xb5b5f26174fdba44L,0x4ebe1d070d746760L,0xbb0f7812c37f04b7L } }, + /* 6 << 35 */ + { { 0x810b6ab36df1199dL,0xc229308bb4f293b7L,0x3cf838dd89897750L, + 0x3e391e4e7a336c9aL,0x70148337176f89c0L,0x54b15bacbc4f1e22L }, + { 0x32b104f92c0f2885L,0x2c39cefa67034f2aL,0xb8310437bf178ac1L, + 0x722299f5c99370d5L,0x0a493cf0332b93a8L,0x00e0ab41a420f719L } }, + /* 7 << 35 */ + { { 0xf25925434cab24daL,0x52be9bbce7c3b9c5L,0xaab7a8b64660d1a0L, + 0x09738b819a9600f4L,0x58f0c86637de9e3cL,0x0aea5cc15db31f4fL }, + { 0xe480406f499868beL,0x0d8fc7f0f6913a44L,0x7282364435f2e14eL, + 0xb147b31045e37a93L,0xb1e7aa5bf15c1af7L,0xa8685068b03e7713L } }, + /* 8 << 35 */ + { { 0x21feb7fc21c34c2bL,0xab6a553addb0140eL,0x03a6557624b04e6fL, + 0x2531f186342cb0adL,0x088c4d54a24f6426L,0x9a0ee15c06a873eaL }, + { 0xdbe0253fd33bc748L,0xdad3339f5db8ac9eL,0xeaaf368173e65901L, + 0x71f1fab2ccbfa504L,0xb7b845224b0e163eL,0xe0fca8373c779f3bL } }, + /* 9 << 35 */ + { { 0x710988eb46baf373L,0x8cceb935b57d5018L,0x1864603fa45fdf17L, + 0x3dcaae73ef48e6d0L,0xadd9420b590322c5L,0x947783e39b135f67L }, + { 0xfde763688bf5049fL,0xf00e4c182caa4023L,0x4d3b0f23d355b3d6L, + 0x181fabcc20d5799dL,0x29499b40ab2ad0afL,0xf6e66328f9a938aaL } }, + /* 10 << 35 */ + { { 0xcd7b3c42bcbe922dL,0x2fe02b3b95dd1a5cL,0xeb66bcbd24ef5c38L, + 0x7edcc21ce579c309L,0x7b19d49116f6c900L,0x36019ecdb6317c2cL }, + { 0x554ba55391d9001cL,0xa5e30b9814f31e44L,0x3d1fe33bffda4032L, + 0x5dfec4782306675cL,0xbe59305e000c91e7L,0x3c4e52a325a6b879L } }, + /* 11 << 35 */ + { { 0x02fcc14ec5ea88acL,0xca29bb6d56d093b6L,0x876aeda90e6fe94dL, + 0xfa11a142d7225a9dL,0xfea3ca053d03fed8L,0x435854c6c54d5962L }, + { 0xd770737454a6dfd5L,0xb8960017a3e55d02L,0xd4015a0c04d65c3eL, + 0x397f93d1e98a1204L,0xb0efa2e55f3ed850L,0x18f244698a3ec67bL } }, + /* 12 << 35 */ + { { 0xa35802f5d62cd9f9L,0x0ca9c15d4148436eL,0x261a991d472b9d21L, + 0xd81a1ed6a2f8e875L,0x942f213a699b6d63L,0x041a12fc0ae57758L }, + { 0x61191c82bd70aabbL,0x3776eb8bee4c23b3L,0xabe23e8652511222L, + 0x66dd967d30dabb91L,0x77650c597ed27424L,0x08ea2ebdab25a050L } }, + /* 13 << 35 */ + { { 0xa410ba3ab6cb5a02L,0x6eb40d15d07c5c6bL,0x0de81e9107dcc811L, + 0x996f46eb2631b7afL,0x5a350ba75b7a22f3L,0xf42b24e7634159afL }, + { 0x07bae0abc30952fdL,0x3488cda2d644e0b0L,0x23ae40d0e2111e12L, + 0x650af54ec80cdb56L,0x0f33a30b7d4aa2a8L,0x4e8d3e98442a00e8L } }, + /* 14 << 35 */ + { { 0xa624ab3759a8bc95L,0x4b7e3fa61c971228L,0xe8229c4273aa694bL, + 0x0cc31029779288abL,0xf8eff30f57575e0eL,0xee5e01947d52803eL }, + { 0x32d87e558a78f632L,0x48a06031e454904eL,0xaa2cb8dd16c6e626L, + 0xadd098ac2c140452L,0xd25f285d2d3031b1L,0xfb5fbbe175b59543L } }, + /* 15 << 35 */ + { { 0x2297041fd7a21503L,0xfe7738c2657f03f0L,0x994a8deb168fa34aL, + 0x0c772e02a53c4fdbL,0x67f835d150124cd3L,0x0e0d26356993cbbeL }, + { 0x9857ed845257f11dL,0xdc23a728ac556942L,0xf0e1bb29deb32a7fL, + 0xb8c3c43fee0d70f4L,0xc294b0efc60ad214L,0xa4d438dc679067caL } }, + /* 16 << 35 */ + { { 0x520b0bb905c755e4L,0xa2c2c59bf89f0048L,0x85c1c73a73c23975L, + 0x6e4dec49783aabbaL,0x69f0c69bb0463155L,0x61a42b949c97b17bL }, + { 0x55af24a945d331a3L,0x4b0e63f8f5fe81fdL,0x4034283d708671c4L, + 0x200ddab35fd9001aL,0xe45f28e4342eaf3bL,0x3e8375b41ba936c4L } }, + /* 17 << 35 */ + { { 0xcde014bbc613b1faL,0x5ad97babcdf992c2L,0x9fe05b9fea13e2d8L, + 0x93b553e290c4031fL,0xd62bc0818c727bebL,0x284fb61f888306caL }, + { 0xa63f8dcd1101abd6L,0xfe02dc120e962b27L,0xab169958115301e7L, + 0x8822f954462209baL,0xb3ba3e721198428aL,0x9a73ed38d74c88f8L } }, + /* 18 << 35 */ + { { 0x7db497e17da2f887L,0x0995648b683f3507L,0x50e3ff74f5935bd2L, + 0xdec083e2708c88dcL,0xbcc3bc3125129bccL,0x7a3fd7a80a407b41L }, + { 0x46ab826c25e0ab93L,0x28e891ec54944cfcL,0x637be168f55c6cbfL, + 0xfa34e9942a65216eL,0xd23e99afe3a43c84L,0x6d09d189e6fd958bL } }, + /* 19 << 35 */ + { { 0x8aa6ca1381bbd283L,0x3a0633f4ee167a15L,0x7f297c8b9e3b18e6L, + 0xbead8a50c71fea64L,0xa11b2fdd457aebbfL,0xd7fc286f85bc7bd2L }, + { 0x2922ae5bad1c9d9dL,0xa07741c2ef9ac174L,0x24dab2d457fa8f9fL, + 0xd7078d946116a870L,0x4b45107834117a37L,0x19a4dd21c73c857dL } }, + /* 20 << 35 */ + { { 0xa2f9b4e4bac5d14bL,0x9f904a3eb8699164L,0x63585978fec79b4fL, + 0xbcc9b60ebff45cd8L,0x2e515592a5d63de5L,0xc47a048c3bcc637aL }, + { 0x0523810643aba777L,0xf6818e4c77e67aacL,0x9d5827d238f962b3L, + 0x28a904c6a003988dL,0xc06bc833551f4575L,0x61f6bcc2221cffefL } }, + /* 21 << 35 */ + { { 0xf7cfbbe5055a5623L,0x1f8af775e66d2a5bL,0x0cac440268831d8cL, + 0xd25185890d0e6f2fL,0xf17838a3182f90f1L,0xefdf6f20737f163dL }, + { 0xc3198af0542242e9L,0xf77c3d28209efb0bL,0x1df6d0da8de7be08L, + 0x22ef7367901a6590L,0xfa9b4af44b776d27L,0xdc49102c88ace4f6L } }, + /* 22 << 35 */ + { { 0x60c7d148bafa9cc9L,0x0afc5fe2516b87fbL,0x02e20acff795ff60L, + 0xd1ba069151f32975L,0x8547e7f757be2399L,0x4bdf6abfa0d1b33eL }, + { 0xc793832fa06077f9L,0xad55cccb2d874993L,0x5e217b27314387d8L, + 0x744d7b06e7f2ec4cL,0x761aa86d24fa58b1L,0x41400d9657dd313dL } }, + /* 23 << 35 */ + { { 0xd17f68da759d20f0L,0xc141ca6827b7eaa7L,0x3796db8bdaff5c66L, + 0x067119dca1e5220bL,0x174f11777158ddbbL,0xa80365d8cf8bf75eL }, + { 0x0a79f74933567f05L,0x8c2826123c99bb4fL,0xe448c2bdcd6ae726L, + 0x1ae05aac2ad4b0e0L,0xf90dddcb16442420L,0x37465a1ea75c28e3L } }, + /* 24 << 35 */ + { { 0xf58e05c53178468fL,0xa17c8b868328a2efL,0x1bb22cb44ce0c2f8L, + 0x1ab807b51aab9089L,0x2aafa8c91e76fafdL,0x58cdf95fb4801546L }, + { 0x2c1e4ef8d5d699f1L,0x1583a2aa4cd433bdL,0x571dcaec7f4f9b10L, + 0xf62b696b27156c5eL,0x77d2443448820bb9L,0x94e4cfcc11dd3e55L } }, + /* 25 << 35 */ + { { 0xc3fd1feac00e6c7fL,0xf4e42ddabd322507L,0x1ce3e0da023469ebL, + 0xf81769d2d788b1c2L,0x505cec4c62353342L,0xd4049907ba759922L }, + { 0x9ff98f06618ee939L,0xfa63b3606bd55f31L,0x3fcce488cc4d2515L, + 0xeb6e92e91d629e19L,0xcae4190bff892af7L,0x3e7b780dca80cb44L } }, + /* 26 << 35 */ + { { 0xbc923fdfaf54b58bL,0x2aef31d88767acdeL,0xfbebb8f07f28a3d4L, + 0xce5feafe694fe977L,0x606afb0ac9da1ee5L,0x559866a0b74f7c42L }, + { 0xd935191fdc85f22cL,0x5c3002d7c8ce3240L,0xecd278c198452214L, + 0x665b3176821a3606L,0xce05a914baf26fb7L,0xa178860b60e4e8b8L } }, + /* 27 << 35 */ + { { 0x135c82b55000cc19L,0x34537edf8b2c55b4L,0xfcb6aac2b37acc8cL, + 0xa882e25e8ce8d7f5L,0x531756e98c7ff1eeL,0xdcdaced9ad6312b0L }, + { 0x309a469b7f3aef9dL,0xf306e32588d8772fL,0xe7e6f3abd4dc0d90L, + 0x816b01ae49878940L,0x1cb084e84ba5e2c8L,0x395af25b005d08b3L } }, + /* 28 << 35 */ + { { 0x3832cfd59093efcaL,0x3fda8380ed8b34d7L,0x874ec122e2bd4004L, + 0x3761e9c44270b9ccL,0x6eb2fb1166e640d5L,0x2a45ad23e6dfd0fdL }, + { 0xdcb3272bf8dd082cL,0x7d84341f17486485L,0x0f46b1fda4ca2644L, + 0x81a1ab1e82baf37dL,0xbb1d72713b322f65L,0x1571e326f4038252L } }, + /* 29 << 35 */ + { { 0x4e00aa41d9acdec7L,0xb2b701bf9f80dff4L,0xc366ce97d5e71e0eL, + 0x28c2b4e9ed09255bL,0xef54a1a535086ba6L,0xee2e43f2a1c8b39eL }, + { 0x346f22f5d9143a78L,0x71fc5c06f1053377L,0x1789f7644737b5bfL, + 0xc9f83ee8b0df2648L,0xf91a29e9073ee793L,0x18eb801e3ab450a1L } }, + /* 30 << 35 */ + { { 0x1c3df0914085f0b6L,0xc60c47f5cede211bL,0x7bdead8650b6e857L, + 0xc68645be2cf9aad6L,0x8d970a94d01540f6L,0x9346f253782ec6a1L }, + { 0x3da31263c1b23981L,0x53076158dbabfb68L,0x22947b9f743dfba4L, + 0x872e60061c56f47aL,0xe973d81c2b3b8417L,0xb98216184b1fed56L } }, + /* 31 << 35 */ + { { 0x29fa699b8873de48L,0x64f9e1124932447fL,0x4fb0e009e4c20d43L, + 0x748a0cdf78016262L,0x4891badb7bd23ea8L,0xf1300a437f56368cL }, + { 0x178efa9de8f1f8bbL,0xc31cdb4098a31dd6L,0xc2d5bfbad2c43f9cL, + 0xf377e2cc8678d990L,0xd42d274808d19833L,0x2d72fd4de5ad5e63L } }, + /* 32 << 35 */ + { { 0xb083ba6aec074aeaL,0x46fac5ef7f0b505bL,0x95367a21fc82dc03L, + 0x227be26a9d3679d8L,0xc70f6d6c7e9724c0L,0xcd68c757f9ebec0fL }, + { 0x29dde03e8ff321b2L,0xf84ad7bb031939dcL,0xdaf590c90f602f4bL, + 0x17c5288849722bc4L,0xa8df99f0089b22b6L,0xc21bc5d4e59b9b90L } }, + /* 33 << 35 */ + { { 0x44e6089f006e422dL,0xb4a99bc45b029c6eL,0xd14bd00e6f289edcL, + 0x8ebbedfa25c50773L,0x5bdad80851d3ade5L,0xe4e70c3094727960L }, + { 0x29b759e863ab2622L,0xe20ad36b134d5982L,0x27c8387f4070e06eL, + 0x9fae222556593896L,0x299a0f0c3b199172L,0x476fe70977a39ca4L } }, + /* 34 << 35 */ + { { 0xc91a3d2ef4d0d8a4L,0x450193a819e05a78L,0x0e59e0b89eec69eeL, + 0x2ba20f00138fbf46L,0x5c9fea780e8ae694L,0x62c81c8cc6b73372L }, + { 0x2a1df446ff0997a2L,0x929364ab692bb930L,0x4c4a956436cb618cL, + 0xc55020a0526be5dbL,0x151f18a02c64c026L,0x2ec5becd61724143L } }, + /* 35 << 35 */ + { { 0x139c7d788713439bL,0x46f7bd4b1e19b1caL,0x74259a28b47977d7L, + 0x89a912cb8ab1817aL,0x4428e45f06419142L,0x11b9c4836b34a2d5L }, + { 0xb613563a29487118L,0x81f4502ab6249a60L,0xe28685843d4ddecfL, + 0x138c97297bd250dfL,0x733f2201aaac4593L,0xee6b85ad5d061887L } }, + /* 36 << 35 */ + { { 0xbff288ed74006fd8L,0x388c5a34ded657eeL,0x47d400a2d61a2995L, + 0x54c684af1eba1f65L,0xd1ba6975b1b4452bL,0xb23dda26f2f8283aL }, + { 0x6bff7acf86803147L,0x839571e5e8ea5923L,0xc89e1048dbc4ccc5L, + 0x1fa0221120102232L,0xbf7b8f902d4e4406L,0x14c5de43576aba0eL } }, + /* 37 << 35 */ + { { 0x6c55807bfd2f9b11L,0xb01d9f7239e338efL,0x94f6531135628879L, + 0xae51cf0b0ec6f5b4L,0x387223cfd36b9719L,0xeeb02cc6f2fb192cL }, + { 0x867611ec43c9e89cL,0x5b15785f97930887L,0xb792b88b57ab078bL, + 0x0c54de110bdc03cdL,0x5785811a30d0eee3L,0xb73bb98436b88b00L } }, + /* 38 << 35 */ + { { 0x0d0ba3c06fba6f94L,0x7f7e0f5cf29713c2L,0xa8cce53ba6b94d6cL, + 0xbea99382df40fd27L,0xb3ff1c56bcd4f8b2L,0x19124644418f108fL }, + { 0x6fc5260727c26f18L,0xbc5e23d682c7c8f9L,0x12aa5e8e099b8cb3L, + 0x9d94d88614c579f9L,0x5c629d7a47395f32L,0x9cd280633efbbea0L } }, + /* 39 << 35 */ + { { 0xf0bbf8e88edb7b56L,0x9a76ad71adeb43ccL,0xd99a92528643e982L, + 0x6468ff05cf17f5b5L,0xe6589476d56b985eL,0xdca4273cbe446b3dL }, + { 0xd430e3a47b9dbac1L,0xe075c00f4cfe735dL,0x3ba43fef12395845L, + 0x6895f0c3dcb49ce9L,0xd868006aa92843dbL,0x968a8ceec0d5bc9eL } }, + /* 40 << 35 */ + { { 0xc0387b57f440fe92L,0xce8bad38e291c443L,0x022052e5f9e88be0L, + 0x6f949fe261615c9cL,0xf4874e2d84725fc1L,0x06fb244b73a394ebL }, + { 0xb70553c678208bd8L,0xab1829c028704d28L,0x1453ee1a807b160bL, + 0xa1da80c34649d33aL,0x072e02e056c32ee1L,0x79baa98f3f590646L } }, + /* 41 << 35 */ + { { 0x1613a710b0fef3f2L,0x9ae438012edeec54L,0x07824d08579c3130L, + 0xc2beaf806ba2b1fbL,0x7df3c459fc9e85e5L,0x8debf613dbd63acbL }, + { 0x2774ab78f04f3526L,0x36e7ff55a5285219L,0xf2adccaf4ab04c77L, + 0x14add3d8aa43fbfeL,0x387e4965e3026ac4L,0x154801a1c77391ddL } }, + /* 42 << 35 */ + { { 0x28687291933bc404L,0x6a13b0cc9ba35fa8L,0xd3d1746931c5d126L, + 0x1c81ce5df9727cfbL,0x14f66be860b464eaL,0x0bbdefb8c10ea9f6L }, + { 0x5679a0e5e8d06c95L,0x380161d83dbfd6e3L,0x6cdd31f20523e6d1L, + 0x2ff419e0c4b4c439L,0xc7439153e217782cL,0xb1b74383f6dc5d95L } }, + /* 43 << 35 */ + { { 0xcf0d1d2d03746e38L,0x8476c982916e077eL,0x93de41516dfdc6d3L, + 0x15010d26b78cf13fL,0xbab5a5de97cb08c0L,0x37f0673014a31939L }, + { 0x777c709f6819b0f4L,0xe3c2d2f7114a32e7L,0xf0227e19ec047092L, + 0xe1416f34b817e1e1L,0x4d7db41419c6c3f6L,0xf12a13a9d01aecb1L } }, + /* 44 << 35 */ + { { 0xa09e68e61f023abeL,0xbc432449aae2d6c8L,0x61e22f727cb683dfL, + 0x0b5bbc0fd81a0e89L,0x18ea4e774581f128L,0x28df9961cd70a12aL }, + { 0xb0d3b19f8b8bc10bL,0x0805d1439844e7f8L,0xe3ed3d40675ab6a9L, + 0x026d1200f75e2859L,0x1802457b8bb10969L,0xf94c62b3eadab8caL } }, + /* 45 << 35 */ + { { 0x518e9c4220d03ce7L,0x6c44676187811010L,0x07ff38f99d9be611L, + 0x5c2bac105cf0cfd2L,0x4e5cc677d5881c2dL,0x02dc395f08e39281L }, + { 0xc3ef99142044f4e9L,0x0203508c20c8c831L,0xd1276c030e0524c9L, + 0x5525c0af5402f999L,0x5c9a43aa49c2371bL,0x6d7b6700d28cbb59L } }, + /* 46 << 35 */ + { { 0xdec3ab0f7bae55e1L,0x6bae4baf56152625L,0x1d597c0c839b5d6aL, + 0x243692a966b3b169L,0x37f2ca8eb01c6d34L,0x5baa355aae5c05baL }, + { 0xe0b84c28af384b13L,0x6a2c9386667cd513L,0xc361a75d78319608L, + 0x0c317ac596ca528dL,0xe243aa8672f0a5e0L,0xedcf9f5fa1d1677eL } }, + /* 47 << 35 */ + { { 0x88e5cf3f74a0a7d2L,0xa25a3883cac23d4fL,0x7be2fc2ba6eb3d72L, + 0x188be28d391326cdL,0xeca6aa726f3db24fL,0x237cd6f70b9a11a1L }, + { 0xafeca5436fecffeaL,0xa32291510e6d18f3L,0x46699e2500dd8b76L, + 0x5edb4b1a331eaa12L,0xecf6d8a472ce0658L,0xd91af8da6b80e9e2L } }, + /* 48 << 35 */ + { { 0x7af5da7b63ec62d4L,0x74dc387261dbdee2L,0x7d08dbd360b519a4L, + 0x4e785f79459ef257L,0xe3e7d5a485fa9e7fL,0xea60c815e9b5665fL }, + { 0x2e570d18c209caf9L,0x7bae108371818d1eL,0x5db42a0a398d749aL, + 0x149740ff4f555604L,0x72e4f06bbcee0abdL,0x0ecc0cb581ad0830L } }, + /* 49 << 35 */ + { { 0x43550eea0a34451dL,0x8b0b97e9c3aa33e3L,0xdd974528da22dbdeL, + 0x0337c64dabff3ed2L,0xb50da9e9230cc211L,0x931f891c004d17d0L }, + { 0x8b7f9ccbff366019L,0x5483938033d76a4bL,0x52fceec1950ef740L, + 0x5b19b50cd18125d1L,0xbbb661f55b9011c7L,0xfbf0ec747beda7fdL } }, + /* 50 << 35 */ + { { 0xebca6bbec047276bL,0xcda078e05c3018c5L,0x4620dedda223af10L, + 0x962f389ad02fd60cL,0x901fab93baab3894L,0x5ecbbd7506eab11eL }, + { 0x865dc95e62203b9cL,0x04a599844acf85edL,0x877e94647607236eL, + 0x09592a5684609563L,0x6535176ace76d699L,0x44f2d997ce8812e9L } }, + /* 51 << 35 */ + { { 0xa09c9ab62285b330L,0x6058d94a9b145627L,0x7b4b4141da3c3571L, + 0xc9347a16033b665cL,0x95e9b4f01a33d052L,0x35520f3cd46c67b1L }, + { 0x24938cb136042a9aL,0x5eeaec9de73b7354L,0xed47914931f08616L, + 0xb0187b2b713a2114L,0x03c49947e3b76d73L,0x79b5778a2e94fc7eL } }, + /* 52 << 35 */ + { { 0x6bb19d2162de1ccfL,0x3810bdb3339162c2L,0xeb56c72b6aa09df6L, + 0xac66c58d1d415050L,0x922cd7e74ad9cc85L,0x09e3585f91168090L }, + { 0xffc9a98d31b918a6L,0xc273e186c73c7513L,0xd506753f12a77342L, + 0xe288a471e5edd613L,0x0f358d310cacf05eL,0xfbadfa2d9a63fcfcL } }, + /* 53 << 35 */ + { { 0x020e282989cf155bL,0xa1fa6eaac7f481edL,0xba422e09c5c89724L, + 0x43da4df7cad8186eL,0x1bea459cba3ca738L,0xe9f0afdd0c64bc9bL }, + { 0x4c3b3b8e3592686eL,0x7e6938a7b43ea3f7L,0x8e01a54e7ba7dad8L, + 0x33ecd36ea9c68839L,0x1abd6e125e7e993bL,0x29947e126531feb6L } }, + /* 54 << 35 */ + { { 0xb0fe9b7912a193a0L,0xfa19ad4be4bbd264L,0xd5bf0e5409918851L, + 0xd07d8e5729cf45b0L,0x228e67cc7744259dL,0x786ea24843ed0fc4L }, + { 0x7f700231873cd08dL,0x394db4a70ef49109L,0x699047c06a8197f7L, + 0xf5b168443021ff8fL,0x4c8bb55026621cabL,0x6f28b013065208f1L } }, + /* 55 << 35 */ + { { 0x2fb3a7601f809545L,0x8006902ae93849c6L,0x37cc848c9bd9e1bcL, + 0xf4cd31559d0f6340L,0x357772ac4baef442L,0x0f46d0f77d533f1bL }, + { 0x4121411fd9c12bd0L,0x304083dedb70e364L,0xff6b7a1ccecbeb3dL, + 0xb444b5972aadc899L,0x29ec79bfdb8b3731L,0x864d8d917fbd8982L } }, + /* 56 << 35 */ + { { 0xa79feacac241c5bfL,0xc86df4c017861e6dL,0xaecd1722a699282eL, + 0xcce5e345a0464190L,0x0a79c23deca4f6d4L,0x64603ff16a6e7967L }, + { 0x02e24234aa7312c2L,0xa9e1fc7791a1b587L,0x1daef29f94526a4bL, + 0xa7db710a62ead861L,0xb387fec78869446bL,0xee2171015db19f08L } }, + /* 57 << 35 */ + { { 0x79a0feabe64fb245L,0x5799eea096a4e94cL,0x2592e7a333b063a6L, + 0x2cac3c2ef1063574L,0xb9cea04a7f4755d4L,0xb8e40abaa0bf858dL }, + { 0xe1723d963ffa32a3L,0x6547b4402701eb1eL,0x16ec552a4da9b337L, + 0x75f7f4a8fe0555eeL,0xf97e465014f1c2b2L,0x5495fce3d9ccf8a2L } }, + /* 58 << 35 */ + { { 0xffd160fb62c1b457L,0x62efe01fc4d91f7fL,0xc54f75b5208dd413L, + 0x089514d3e78124d0L,0x752a9ae8c2945054L,0x466636fbdbffa78bL }, + { 0x32936281a265949eL,0xd657c0f084b4d11fL,0x199d8641af455a47L, + 0x1eb24cc7dbd9852aL,0xd2ce80f856bfbbafL,0x1b31b23ceb862890L } }, + /* 59 << 35 */ + { { 0xc866d2a5fcd5aaf4L,0x4ac2b7f57e21250eL,0xa78cd3cbc50b4a92L, + 0x2485c3435a5c541bL,0x555db4dc7ef371eeL,0xcd9d6d9c1304f782L }, + { 0xae86a22974b4d57aL,0x68c93bc8dd4cdd8fL,0x7b95411098b9fd49L, + 0x0dd480b9399d8d4bL,0x0e27be29f2665c52L,0xce8a1ef9d920a5c8L } }, + /* 60 << 35 */ + { { 0x10a6bd0cfc0395b9L,0xe30bf6d06a5e8107L,0xc8aa2483167930d4L, + 0xee75885006e7e1c2L,0x4ee64cfcedcb7788L,0x9498e9bbf2f1d7ecL }, + { 0x084d2350ae0fcdb4L,0x4398ee677f4d25ccL,0xc1ddca395db85bfaL, + 0xefd4819747961197L,0xbd16037f2265195cL,0x1c61a6fc56daae6dL } }, + /* 61 << 35 */ + { { 0x640cf6b17f7c8c50L,0xdffddf2209d44051L,0x837275314e3c038eL, + 0x3164d1875aa8d8a1L,0xb37590bcfceb1066L,0x5e4fab4200d489f6L }, + { 0xc1e5dca3f8105ea2L,0xfdd1b0751c7f8679L,0x571d7dd14f14ac54L, + 0x84cc453155cfb741L,0x49d0b1be48823448L,0x8365f1f3f798b5d9L } }, + /* 62 << 35 */ + { { 0x9f2409cb6a564a3cL,0x9266799ae5134e54L,0x39aa3697fac47921L, + 0xdf3db1f32c0b4dbdL,0xfa37a085f096ec03L,0xb99cfe05afaa0f3fL }, + { 0xc9e00e43df458860L,0xbeb7e60ace2bb0b0L,0xdfe2be57cac8d7e0L, + 0x6ec03d799162b2ffL,0xdfe3a6225d1122dcL,0x9f04dcc8b6014310L } }, + /* 63 << 35 */ + { { 0x30471bf9b42ba5c0L,0x19073fd0c9d26763L,0x92817e8059c1017cL, + 0x29248f743da195b3L,0x029d7e7be928767bL,0xf1a3a08a049a0080L }, + { 0x8ec4f3e6e20c1d68L,0xae815a11f3ad30feL,0xdd0a6083f76f43afL, + 0x197d29fe49465bebL,0xf1a40ae996316f4bL,0xec47d65e59bafbc0L } }, + /* 64 << 35 */ + { { 0x6f57752951c2bb65L,0x4a0c1c284b874bdbL,0x19a1842778b96c6dL, + 0xa674f9922f593505L,0x5abeeec46b7209d6L,0x42d15d0147cf5fffL }, + { 0xe24509b7b49e3b4eL,0x81be939c639ee6e8L,0x7f7daf595761e8e3L, + 0xed5cfcb8d420a288L,0x365b29eb7a0ff696L,0x7d14680599a1ac8fL } }, + /* 0 << 42 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 42 */ + { { 0x9ee1ec3aadcdaa68L,0xd98c498fdcbb6548L,0x32b9737588102ac0L, + 0xdd296cf9c08527f4L,0xb74f8145fae3dfbeL,0x84131eb96cd7cc4fL }, + { 0xa0f2fe7a927ff15bL,0x6b0ade4deee1a4b4L,0x6e7df2d40eeb90a7L, + 0xe2f46e20be4de684L,0xcd28feba3fdd06bcL,0x8e4205aee6d6d9f6L } }, + /* 2 << 42 */ + { { 0x35d47426f78d33efL,0x4af25db28440c42cL,0xbd6a15e22e91bf5eL, + 0xe366a84cc08b6b1aL,0x759c122f55b97de8L,0xecec558f08a03f29L }, + { 0xdcc9fca2ea9d2060L,0xb3e49b8e9f361fe1L,0xdeae39029b59cd04L, + 0xf532ede06f5e5bd4L,0x84fbeeb936099f4dL,0x73576b1f088d2052L } }, + /* 3 << 42 */ + { { 0xee43828c6b512bc6L,0xf73dc9f550b91e60L,0x68f23f30f5dbde6bL, + 0xaf2fe9e3ddd15e00L,0xfbf34dae86578d49L,0x689796556c130010L }, + { 0x137a5fc309942897L,0xff1f0bfe9959f06dL,0x2dd0a04abd7ee14bL, + 0x59c46072e54e2161L,0xf470bdaeea7518adL,0xce556e4340c471cdL } }, + /* 4 << 42 */ + { { 0x2ba8c79022b25f2eL,0xf4670a511af0f4a8L,0x6842f36a2fc2451eL, + 0xfc5c9558bb91e1e3L,0x035d1dfcc3ead762L,0x3d0721cb031e5556L }, + { 0x3af0cc813af18a2eL,0x7888cee2bd11a363L,0x80c3de0a6ade1d12L, + 0xe8c3a5bd93b2dcb5L,0xe3adbd7c90a2214dL,0xfe8646d51192948dL } }, + /* 5 << 42 */ + { { 0x9214cd4bf1c7ed94L,0x4887c7c63738f386L,0xa72ba72bf623e542L, + 0x3c52a464f67d6004L,0xcdb6171d09b9a4ffL,0xe5eb77d160aba627L }, + { 0x7aa9836f39d6afdcL,0xa3fa3a520e0a1e18L,0xe90bd925dee3a4c4L, + 0x47e8eeafd9a94dcfL,0x34302a4921e16feaL,0xe32a62eb8ae23949L } }, + /* 6 << 42 */ + { { 0xd1d70db31df1d1f2L,0x22ebc9bd9fec1f42L,0xde5ac585d11d3205L, + 0x0e4584ab282d4d6eL,0xc87607928f78b85bL,0x48a85682af1fbb6dL }, + { 0x64d012ceae0947bfL,0xab792bbf25e22366L,0x250d40d4a3a030deL, + 0xe9b49f0877e26b9cL,0xe7d30c828c0f2249L,0x2b77b40b97c676a2L } }, + /* 7 << 42 */ + { { 0xa89144b89efc8fe2L,0x23625c36e13b79c9L,0x4fdea1d3a047ad35L, + 0xd0b0ee0d4ae78e01L,0xc224b3f3eac4e606L,0x4360e8acfa41bd81L }, + { 0xb2c69238062437e7L,0x86ce8de0decd1245L,0x2ce4be3dfa9d07bdL, + 0xfd09aa853d268d06L,0x4cd874264a162aafL,0x1b28f72e9d45e849L } }, + /* 8 << 42 */ + { { 0x65026297ba958101L,0xbeb4adf98eef151dL,0x623763a460c8bbf7L, + 0xfa8f5ad78b2a7120L,0xfd744bdf085497e7L,0xf9b6f97e2ba35618L }, + { 0x0cebfe9df8a15e86L,0x47a6d01329576088L,0x655817a3fcf19627L, + 0x30ab44f7c2f11261L,0xbb001c9dddf2c850L,0xb45c7eff073260c3L } }, + /* 9 << 42 */ + { { 0x609a02d031716f88L,0xdff6246c45421ce4L,0x544f3162142838d9L, + 0x8842dcbe36b57d38L,0x2818919c57f561e2L,0x87f5acca318373aeL }, + { 0x42773fb72edf1501L,0xff92c38648e9d8a3L,0x21a81668ccd5a860L, + 0xbac5cf837328cee1L,0x7441f749ddc53a05L,0x987d3a1cb5abe243L } }, + /* 10 << 42 */ + { { 0x3b7c44f8fb90e50fL,0xeafeda047cc384fbL,0x9a33e377de65e34eL, + 0x303f568095094a58L,0x4c0f2e932292809cL,0x920c9c12160b30f2L }, + { 0x31d14e1414b268d4L,0x9964173f1eadb1dcL,0x8e22b362eccb0f39L, + 0x81dccdf83bf9ece1L,0x8e2fda43a40503b1L,0xdb647ac13e112199L } }, + /* 11 << 42 */ + { { 0x9c23216f096c21adL,0xae259a6d41fa37f2L,0xefe0a8c9efe96f6aL, + 0x5631701dd6a27744L,0xed8d0219b3017563L,0xbe2723bca0867a0cL }, + { 0xe02bcb56687b62cfL,0xf26c0f77b96f66a9L,0x43e46251fd16fa3bL, + 0x206a180a44033302L,0xcfa96b556121888eL,0x50567a7789dabe7fL } }, + /* 12 << 42 */ + { { 0xb08fb1175cf3e702L,0x7379b1978023df0aL,0x73aefc7b6f954966L, + 0xc0fb886f76bd243cL,0x871eacc5ce09d5a8L,0x9f55b0a4e773f049L }, + { 0x92945c84415d725dL,0xcd57391f0112ad84L,0x4762bc1d0509d73fL, + 0x15cf97f10f1af175L,0x1f855695328c160fL,0x32cb87263b439f0cL } }, + /* 13 << 42 */ + { { 0xb27e344ae6361abdL,0xa53690eb474027a8L,0x500db02d683a8ef4L, + 0x547ecd17819df66cL,0xc35cd4cc91360e21L,0x6ea003a16026dfedL }, + { 0x45e77cda22395207L,0x1e8e103f91264683L,0x130f2d2b3bd6328eL, + 0x6ae25c819af8973dL,0x6b0f90a0d32d7134L,0x0280a95755c62195L } }, + /* 14 << 42 */ + { { 0x23781958cd8bb5aeL,0xe3d30c5417dd827aL,0xf974e0076bedf762L, + 0xd8154b6273264accL,0xf10fd9bb167b9396L,0x967c5acbe9652a0cL }, + { 0x46775025a28fa76cL,0x17ac7cb32ece9d3cL,0x5fd8968ce04a833eL, + 0x96ed5b49fcd20a43L,0x1d209e85289f9c68L,0x4d7473518ce51950L } }, + /* 15 << 42 */ + { { 0x6f5c8f3475214c1eL,0x3d5560bae192d11eL,0xd8a63ff0d7af2e6fL, + 0x5fb858be9069fe09L,0x83956dcd8cc663f9L,0x52d30c3b838bce30L }, + { 0xf354f6d75569122aL,0xfcef54d1fa68f566L,0xc75b01e79020dfe9L, + 0xaac66895774b952bL,0xb2a58a299468cebeL,0xa994a3b487c81a42L } }, + /* 16 << 42 */ + { { 0xfa7d1236e2319f38L,0x9ba1a1c0a551d3feL,0x9ea27288beb1282bL, + 0x1c069efa07fee8a9L,0x5749c7b55870fee9L,0xbedca76fafcec6faL }, + { 0xa3f8f1b14c63c5e2L,0xaa1bb15694758ac3L,0x753329a9b59dc06eL, + 0xfa8e5f5b98a92c38L,0x6b6f46fd3c2b4662L,0x716f41a1ec04c6c6L } }, + /* 17 << 42 */ + { { 0xa882aa6389201dffL,0x3441fde55bfcde3fL,0x220cca60cb543f54L, + 0x2af1cb29d764d74bL,0x47ae56d0517617c6L,0x05b98dee0342bf55L }, + { 0x214f4b11b4e28cfaL,0xa6ebcdf5093691ffL,0xe49ca185f61d29acL, + 0xd304ac40fd8c9018L,0x196161a0f889b7c7L,0x3b704d52dcfc6c91L } }, + /* 18 << 42 */ + { { 0xb405aff88886500aL,0xd88008bebeeabe24L,0x9457cdf30bc931b2L, + 0x8e5fd378f4c5aac1L,0xdec408107bc2bb98L,0xf86424c598b16f6eL }, + { 0xb6af27b634df75d8L,0x1bd3082125943a31L,0x51176cfcec993c24L, + 0xcfc1433accbd192dL,0x324a5e1e2993be83L,0x34169fc1d06215adL } }, + /* 19 << 42 */ + { { 0x41aa181ad260133aL,0x627dbe0346e236d2L,0x717fba9cfb8cc72bL, + 0x6e21d03d69bbc9e7L,0xd903e845241abdecL,0xd17879fa3c20cb6eL }, + { 0xe6141bd463a360b8L,0xa784a651e86cdcb9L,0x80fe8dd11f9147fdL, + 0x641241c6de155420L,0x1caef32ba71f3546L,0x28c3a51a79fdf82aL } }, + /* 20 << 42 */ + { { 0xaa16c27a84a3d033L,0xc207a4990c11c9caL,0x7ae2d193aae87c9cL, + 0x125ab459916d634eL,0x02ded714cfa65b4bL,0x6efe84944e212e22L }, + { 0x97c48a1888766168L,0x663ccc9dd9c85b9aL,0x6fe8b77b2652f501L, + 0x1daa602d078efd38L,0x35885364dbcb8299L,0x25bd1826b8240626L } }, + /* 21 << 42 */ + { { 0x6621d504af748cb6L,0x3940e5e08dacbf89L,0x9fdd8eeaf546daffL, + 0x18fc70d4b42f9507L,0x09bc4af9a3fcc42cL,0x9199b08f4165304cL }, + { 0x039d45bed3d0e9eaL,0x0963ede2a6464c2bL,0x77f47a62b5215830L, + 0x3a0ce54c3e540cdeL,0x34cf6031b2be8f77L,0xeb143e60201083efL } }, + /* 22 << 42 */ + { { 0x21404da5442467a1L,0xe73047597f7023e0L,0x836439a8213ff492L, + 0x105fe0e37ca0fc37L,0x73835ac85b303c34L,0xe29d830e0057ac8cL }, + { 0x457d083e3b5f41bdL,0x228b26c357341890L,0x8e8f194c4109bf9dL, + 0xd032cf2b6e4a39e3L,0x012e9515d88f9292L,0xd1a4cd32e957e163L } }, + /* 23 << 42 */ + { { 0xec56b72f4ab23680L,0x7cb58e727f22217eL,0x6e98647bd045d18dL, + 0x2b7c9caa9a73b956L,0xc414eabef120122aL,0x45d9036bb6e1b134L }, + { 0xe963c88388abd93fL,0x257f3b619180cb9aL,0x915fee5cb6ca7abdL, + 0x2166402cdb7b1bb1L,0x636f85f6541614e4L,0x81f91a1849d9e527L } }, + /* 24 << 42 */ + { { 0x0430af7759b11c7aL,0xf71cc5b1d4f47acaL,0xe1a7905f12e9190fL, + 0x1c689b7012db9e14L,0x6bdd3dc90abaeeacL,0x97f1c244504f0319L }, + { 0x874afd61a7a54b51L,0xd4604ecbe3d979b8L,0x0d33eee1ebf4aab1L, + 0xa3631cac1aa49fe6L,0x0d8340fbf2217cfdL,0xf6373284423b7e77L } }, + /* 25 << 42 */ + { { 0xc6cdb5ba6f7972d7L,0x7ac7d438907d281eL,0x9160a8f5c01044ddL, + 0x3d74d7eac19ba8f9L,0xf7c7f93f112433e5L,0x2ab355a2012236d3L }, + { 0x1168ce913009447eL,0xbefde8dba26e3458L,0x6f9837db49ec8169L, + 0xb4d1e35c86782931L,0x41440a76d711e5f4L,0x8fc7a5aeacb5cd89L } }, + /* 26 << 42 */ + { { 0x73719fe8286e8aa5L,0xff8663419982a4a4L,0x684511702fb2db95L, + 0x4f1c0eab01d80ea1L,0x2bc50da5530af14eL,0x00d1d5b506071a95L }, + { 0xdb618990a6b374b1L,0x06ad90084e79ebe5L,0x281d01a424a63b70L, + 0x87dbd6d5348625fbL,0xdc90f0bef576b1a9L,0x1a9ef270987747a3L } }, + /* 27 << 42 */ + { { 0x135e416ed651b9b0L,0xe55f7f104a5e7979L,0xe55df2550f0729d2L, + 0x666f2744e33ada22L,0x4968bb982cbcb4a8L,0x7ad4e7811028dd81L }, + { 0x0e59f0dcd7ca8b60L,0xd71628cdd2a600b2L,0x7eaf6d308b0af99cL, + 0x6224b6452900105cL,0xe0513f4388650f12L,0x2a63822a6f6c5234L } }, + /* 28 << 42 */ + { { 0xf8c07373078a045eL,0x998b2d52a81724d2L,0x2b97faf1a6305a28L, + 0x5bc61f67f3e0f93dL,0x7238583cd7aeb8c1L,0x851ecc4b39f5f24bL }, + { 0x1cc8b4689992c20cL,0x73168a863c8553dbL,0x1b9a5f95ba2641adL, + 0x87a0c362ce9d565bL,0x07fb51b2e1eedc62L,0xdb300ac6a973903dL } }, + /* 29 << 42 */ + { { 0x789ca390f33e8516L,0x6a7f594cdee7f1caL,0xb4b6b9ca988005a6L, + 0x14f7b4806cad024bL,0x682a86285a576b68L,0xf188c74e40e1984dL }, + { 0x3584b5e6bf6f19c6L,0xa350b1d2b7467bf3L,0x3b3bb966aa3d1266L, + 0xebbd2c782804d8a3L,0x91a272d36a9caf4eL,0x553ada4158fa7041L } }, + /* 30 << 42 */ + { { 0xb564a0d9807e30a8L,0xaba07b1534a637ccL,0x010e76c5840d8e37L, + 0xb6dcb9ac95f6765eL,0x2f5f8fe103b3ec08L,0x10c5a24fb48363efL }, + { 0x5ddacb2709c4dc1eL,0x8e2884b1e03bafc5L,0x84d56df3cfc2d599L, + 0xc8e2da84ab78ec0dL,0xace4663f900084c6L,0x98d9a1df5d49f42eL } }, + /* 31 << 42 */ + { { 0xb10ca6eea690d9c8L,0x0b8b39efd5e0d490L,0x2685d320e63807d4L, + 0xca40d0ee83116ce2L,0xe1e1434fca51b48dL,0x178a91afeddde4a9L }, + { 0x64f59e3fd0dace59L,0x57b33c26278b1820L,0x2ca13b041550875aL, + 0xb21f675a4e0db4aaL,0x2bbb3edb0216d3c8L,0x7f39955b96ec8017L } }, + /* 32 << 42 */ + { { 0x78a53b5a9563e3bbL,0x19c75eb286af355cL,0x3520f427019a6f8eL, + 0xde6fcad6dc3ad0baL,0xfec96e4f79745b7cL,0x5e566bbdb133f2dcL }, + { 0x50088a2b26561be7L,0x16275b4cc5fddfc7L,0xf21332ff23ae4b9dL, + 0x8cbc659e85246712L,0x27fa9c8df50b515eL,0x25ecf745494ac8b7L } }, + /* 33 << 42 */ + { { 0x7cb130e0837ab43fL,0x8a1f00127b9f6c17L,0xbf827f6d17fa5e12L, + 0xc181b1264914a231L,0x8ce70fb6986288a8L,0x9832863fcd1c276eL }, + { 0x738e99819622ecd1L,0xdfc1b43cb73807abL,0x7254b4cf1b673290L, + 0x2d689f38fb20f902L,0x86460de83c34960eL,0x8453896aed8f62e0L } }, + /* 34 << 42 */ + { { 0x9f74efc606f4904cL,0xa280e4c26d3bc556L,0x974f9bdb75975ee2L, + 0x1bc0e7fb6dacde9fL,0x2a110d4c49649375L,0x045432c09090d834L }, + { 0x84295a20195083cbL,0x92ea17cac7dcf71bL,0x3acced0be70be8c7L, + 0x3703dfc007e28816L,0x37fbf2d1e869fb8eL,0x8c6b0bbef9c35ff8L } }, + /* 35 << 42 */ + { { 0x04a991812f1d2778L,0x0d78573685b91ae0L,0x8c32d6046a5252a0L, + 0x12b043131a0df85eL,0x40c4db631ee669b6L,0x0f499408f18f5f9cL }, + { 0x0dcdefabbfe9a187L,0xbd371c45ca650d7dL,0x33819eb00a36748bL, + 0x82d1af1f29034844L,0x301f906d96257b2fL,0x862728ea9395c666L } }, + /* 36 << 42 */ + { { 0x33a2194f40175152L,0x0f7ddc1dbb13f08bL,0x7c08860850b54274L, + 0x7ebb2c11e41f0795L,0xf915683fbe20d37fL,0xcbcc14889daacec5L }, + { 0xfb02c20fea459050L,0xe964d76ad5815aa3L,0x0e009be9496bbf2dL, + 0x8233690eb42d0f7fL,0x98ee83d49168eb0eL,0x34c3b6f3621fa292L } }, + /* 37 << 42 */ + { { 0x29555d79b0221994L,0x1dd689dd4c9e8f29L,0xcb83ed2c853f5261L, + 0x04b1475e0d9b0670L,0xa28b15e7df2ec34eL,0x094409b5e60a168eL }, + { 0xe4b9fd0e16ed42fdL,0x02f97e84a138f2f6L,0x91dc216ce13520dfL, + 0x59564eda7a245e5dL,0x825278be8478befaL,0x69daadd20328c4d1L } }, + /* 38 << 42 */ + { { 0x6ffade389995db43L,0x88974055790f4b92L,0x082e5add525d19e1L, + 0x002c414897bd9931L,0x3f093b3b5461cff7L,0xafc95b0042b8d3f2L }, + { 0x0a8f7687a993155dL,0x1edfdf616c2bb58aL,0xb5be2d4fc44049e4L, + 0x6fd505bb8dfdf4e7L,0x5386f02a41af5871L,0x8178817569121027L } }, + /* 39 << 42 */ + { { 0x1deada722706171eL,0x1baf4c9aee773c6cL,0x458efac06977d673L, + 0x1f2c2f38646e29b5L,0x36ece91a53323300L,0xab51a49bc4d598e8L }, + { 0x7802760ed8e41d8aL,0x2996f790587425a5L,0x227165b73ca21bedL, + 0x0d9e5c5283536ec3L,0x6232f2e089701806L,0xc55e80a2894e2577L } }, + /* 40 << 42 */ + { { 0x437b7224641e3bd1L,0x84e39f7980a58460L,0x68e5292709759523L, + 0x0176a3ace77f5904L,0xde92fb15e151e242L,0x79965c9aeb1438d4L }, + { 0x318a810a596700b9L,0xa8a6ec57c2198cbeL,0xd7709aaabf030fd2L, + 0xb432023472f5d326L,0xc9945214b03bce50L,0x0bc06d9bd4ecba09L } }, + /* 41 << 42 */ + { { 0x30630eefaadf21b4L,0x94896f68042fb57aL,0xe678fc3eb312e7daL, + 0x325cd2bc5c94c991L,0xd4eece20bea4e518L,0x9d9d65e925eab2abL }, + { 0x5439c348676454e8L,0x9eb68953be1e48ccL,0xbeea9da27b625a31L, + 0xbd82c6ee48cc200eL,0xba9fc94444b9dc77L,0xb31bdebe1eb9283aL } }, + /* 42 << 42 */ + { { 0x1ac1a09d07abf58bL,0x7372e532b5770f9dL,0xe1716687c12fe180L, + 0xd91f4d36c715009eL,0x5d8885cfd6fe1cd3L,0xc0ab5a13aea65e52L }, + { 0xa5fe05a0838e5e05L,0x590cc325971fb33fL,0x3bd8234a4653bf57L, + 0xb83300373708c1aaL,0x27453d3b0e84e8fdL,0x9dd3f05399cf918fL } }, + /* 43 << 42 */ + { { 0xaf6f26c3a36468a3L,0xcab875f28d9fc8deL,0x0209b1ad52f4479dL, + 0xc9941cb5459542cdL,0x91603260a0212b68L,0x98018317345673edL }, + { 0x2b02a35ef98b810fL,0x15953f78b714fb32L,0xf9f9c61eb71a4b4aL, + 0x959b1473a8505b7aL,0x331d32cb4c6ec97cL,0xb1d2dd44e49f189aL } }, + /* 44 << 42 */ + { { 0xdfb0508345c0a2acL,0xd13790035eacfb2fL,0xe9872d766a2e126cL, + 0xd2a89cbd39a02d27L,0xf45baf72d754b7c2L,0x37985ef8c6c61bafL }, + { 0xbbcd3ef2da1c46b1L,0x5af5dda43a355d83L,0x9f7ce4281d67a984L, + 0xf19526926fa33654L,0x2abccb55567b3b71L,0x1b3704f3300cf29fL } }, + /* 45 << 42 */ + { { 0x9dcfaf21712af69cL,0x26de8fb05291cd70L,0xc778294742072171L, + 0x889b9fbc8c617e24L,0x5971e60cc2926862L,0xdd8e70bddc022533L }, + { 0xc783e1e30a369db0L,0x37f562ab07b2bb92L,0x5043f3d40c060f44L, + 0xa9650f47a3e17ac4L,0x3b8cd7ad18010ceaL,0xeed5de39969849e7L } }, + /* 46 << 42 */ + { { 0xf93c3ccb6044ade6L,0xd14a13f8fd376746L,0x1fc20e6fd718a98eL, + 0x9f63c6673e31573eL,0xe99b7693a8e0c66cL,0xdad4615c1e5b5f5dL }, + { 0xcbdb7200ac98f5a3L,0x31414469668ab045L,0x82e92df9bacf0ac7L, + 0xa61f4e8371bfdf94L,0xce8cb699d1bc5deeL,0x42da8ac72f2f837cL } }, + /* 47 << 42 */ + { { 0x0b6252fc32a4e8a0L,0xac1e457dd7170402L,0x76faaffeb121e40fL, + 0xd2dc3cb84ddebd9aL,0x303e47cf362348a1L,0xe37e824a829d9806L }, + { 0x419cc2cc7c2ec135L,0x3eab37024cecfdceL,0xf0c9f19088403d18L, + 0x73c8984daf61b6a3L,0xa2d44d9e00c232a1L,0x61fdf4883cf1cecdL } }, + /* 48 << 42 */ + { { 0xa1972c2196fffb94L,0xbe04093099d7633bL,0xb116ff407e23d66eL, + 0xcb12b2bb949a19f1L,0x75df10ee79e49e91L,0xa3bf90764890bcf4L }, + { 0xcbaa76a609a30252L,0x17c224a90ee5728eL,0xcbc56e5cf4f3f4cbL, + 0x8a07110f4fe868a5L,0x23289f2125e110a2L,0x0289c12bd7693c45L } }, + /* 49 << 42 */ + { { 0x4a9c6f8bea96a0f4L,0x78262a3499e3aaa3L,0x513a8e2028b2634bL, + 0x5ba40287d85d74b0L,0x5702d11d440fcbbfL,0x1933c88a0df91fbdL }, + { 0x642247909a0aff2aL,0x85dc2ca13734398cL,0x1009884fd7aa787aL, + 0xc666a62a0e73f4f5L,0x491bb941cce66210L,0xda8e896bcd173443L } }, + /* 50 << 42 */ + { { 0xdc9b37a7c6e32022L,0x158cd4bb342a148aL,0xd62d371cf06287a0L, + 0xba027eb6e9fe0a01L,0x8e7c6f5372017d09L,0x13c5d6ce9381d9c7L }, + { 0xbd0bc2d46e32f045L,0x52cf0f2554ab7f2aL,0x2e674e50085643f2L, + 0x77bc15aef1662819L,0x57f9e3c4f2ebe66eL,0x839aaebadd284956L } }, + /* 51 << 42 */ + { { 0x752bc171ed9d735cL,0x76d96d3419ad5c26L,0x9549ad3e25c1d83aL, + 0x8f6fed53cd460d20L,0x04504f7c7b619b69L,0x68265559c566f393L }, + { 0x5e39e108804598edL,0xace859b01f4538edL,0x4b8503070c85e5daL, + 0x9f087821abcd4ecaL,0x126d3850c8d0def4L,0x66971fe5263457b2L } }, + /* 52 << 42 */ + { { 0xa82ac9983a4bc15bL,0x28697435c930e4f1L,0x191ebdb6b0c9cef3L, + 0xff05f8e875748872L,0x5b86940237343b20L,0xa7bce94beedfe44fL }, + { 0xfc271e2778f4e1fdL,0x652c5a187734db66L,0x108f61c87efc9a9cL, + 0x01db328970ed1dc1L,0x2bc509afd249f61cL,0x0d2e6b4cfeed393dL } }, + /* 53 << 42 */ + { { 0x691199d77a477295L,0x1f0679a661746b75L,0xf3a51493c9f936d7L, + 0x1fcb336a445af5f6L,0x9880cdebb94ce08fL,0x784fa04a22a6b57aL }, + { 0xc85fe18caa97c3bbL,0x27294a3baabe9b50L,0x9418a5b7b673c915L, + 0x686cd97a15dceed5L,0x6d1c9dc70f22ae6aL,0xed88e02dc02212d3L } }, + /* 54 << 42 */ + { { 0xa62c358dcf616234L,0x85402ffad40aae7cL,0x315ce9f151a7614aL, + 0x6f7e796f5d0c7d7dL,0x73bf57faf3444d22L,0xb5e71e7a224b77c0L }, + { 0x94c40681541ee741L,0x40c97253d6837e1bL,0x1058fe7bb1f1c742L, + 0x3206256f9b24d65cL,0x0abb12a78169ba8dL,0x01fcdb7beae85db9L } }, + /* 55 << 42 */ + { { 0x868f294309fdbd8aL,0xd9c11e7ebdd6c274L,0x3be4d8e7fdcb4fb7L, + 0xcd8c40ad17305d10L,0xf12c97642abde5eaL,0xc9e16d8256776e80L }, + { 0x279c0248df05235cL,0x4bdd8b136d8e4b89L,0xab8bbe8d7c47d2c5L, + 0x12ba8b9e255c665cL,0xd585ce64d140a518L,0x55947e69eb4d353dL } }, + /* 56 << 42 */ + { { 0x06ba6db1f184c91fL,0x3c0a348a45fd0382L,0x0d535b6e4434b527L, + 0x7bbfa2c8692bae0bL,0x5c59a08ebe7fe51cL,0xbaa7d2be36e80cb8L }, + { 0x8a42d8d1bed3cae8L,0xd9e0bc0d15ff4962L,0xe51fce93644c75ffL, + 0x40222561b9392d63L,0x8ab1d286023b4787L,0xfa85c220a1b3190dL } }, + /* 57 << 42 */ + { { 0x294845c28ed1d81eL,0xc0402af2dbe7fdbaL,0xbb56d86d67abe6a1L, + 0x2e61f65b2ed330e4L,0x2893eaebffdf0fd1L,0x06cff97a75fb77dcL }, + { 0x2911ebac1c90fe64L,0xd9c40d77e5ee3458L,0xf5b8b1d4b355f191L, + 0x5be71a4ef365bc6bL,0xe2db432f5277b244L,0x3272a28327235b87L } }, + /* 58 << 42 */ + { { 0xe5105755e6b16cbfL,0xba9fb47b536a49f0L,0x03ac0c10c75ad751L, + 0x9090bc328a2d65a0L,0xcecc7202852b3d23L,0xd214f70128f67958L }, + { 0x379899b1f3695cabL,0x8f3d02e9bd3342c2L,0x9870a7f9e24e7bc1L, + 0x7277e115f723893eL,0x6932ceef0f6f1936L,0xd0bf06dde171306dL } }, + /* 59 << 42 */ + { { 0x815cabeb17832ce7L,0x65afc856a2a4864cL,0x9fe4ae1aa4939a4dL, + 0x7005cbd90729a3c0L,0x887f0cca791e8ad6L,0x55cad97a85aca45aL }, + { 0x3e89d294493c7dcfL,0xf4ae5277ae8ed154L,0x507a3fd0a08fbcdbL, + 0x4df3c552f86677fdL,0x6529f9ace3a82131L,0x09efe1fba53a7c67L } }, + /* 60 << 42 */ + { { 0xbbcfa42d21fe8f67L,0x82983012de2be980L,0x88bb9704aa8e17a0L, + 0x100ad5e784772203L,0x2867168965479d29L,0x0334f9c5c2d9d5d3L }, + { 0x49032c1a83a6cf83L,0xc257b0901dad479aL,0xf64177dea7e3636cL, + 0xb2b5747874a315abL,0x210b11cda170ccbcL,0x80509b7480d80177L } }, + /* 61 << 42 */ + { { 0xe98ad30696993a74L,0xa7dc8330f0484940L,0xc30319fdd61b83d0L, + 0x76e2755809873771L,0x33f4f43ecaedda98L,0x68d5ffe3639c8d3eL }, + { 0xe3cf3b850059b2d9L,0x7f3ecb2f6a3d057eL,0xb569c24b9b8b7466L, + 0xeed92f2ac38ccd58L,0xc16a4e8ce765a2f7L,0xa3a7b6552de9cb38L } }, + /* 62 << 42 */ + { { 0x496de6fa0640df83L,0xa4e500a36c77c97dL,0x45609036947aed3cL, + 0x0edb9422423fc5d8L,0xd0c01b2e68f70746L,0xae44ae0e6d77f3a3L }, + { 0x7cc7e90635adba9cL,0x107a3b46a8413303L,0x9e3eeab98916817eL, + 0x1a99dab86fb74601L,0xb4e8466c1064b039L,0x249149146fcbadeeL } }, + /* 63 << 42 */ + { { 0x89643fa624798452L,0x179b3bd76ee52833L,0x343096e54430c6b3L, + 0x589dba3323461536L,0x59073225c3433575L,0x540f9ce317d80d42L }, + { 0xcd04b14d3aea6c82L,0x9be179b0efc9f455L,0x0ad6fb0791e57cbaL, + 0x33894fa262706b10L,0x2cbc270886bf6926L,0x2cf067e64ea48c6bL } }, + /* 64 << 42 */ + { { 0x298647532b0c535bL,0x90dd695370506296L,0x038cd6b4216ab9acL, + 0x3df9b7b7be12d76aL,0x13f4d9785f347bdbL,0x222c5c9c13e94489L }, + { 0x5f8e796f2680dc64L,0x120e7cb758352417L,0x254b5d8ad10740b8L, + 0xc38b8efb5337dee6L,0xf688c2e194f02247L,0x7b5c75f36c25bc4cL } }, + /* 0 << 49 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 49 */ + { { 0x36c9dbbefda8520eL,0x573507ce6ae3ea98L,0x1ab38db696a8f9f1L, + 0xe031d2356b01e6bcL,0x10466ae68afc4adaL,0x3b35df41ed9c44e4L }, + { 0x61272c12c7bd99e8L,0x6a4ae7b4805afd79L,0xf4c47a910ecc49ebL, + 0xeb95dfeccbe84d5cL,0x43f3b71c8ee497d7L,0x2547af524c6fece4L } }, + /* 2 << 49 */ + { { 0xe323ed0cced45039L,0x04ce0b67a90aa713L,0x9c092f06e8d68e4eL, + 0xd8f5555ad0742e5dL,0xe2d175bf00d3df92L,0x8ca55f154f71aeabL }, + { 0xd1762d72642d391dL,0x0dfdd3c2aec466bdL,0x2caacb4c6281f2a7L, + 0x635ba4703603e53aL,0x94a9811d49fecf29L,0x3a42cf09466bf361L } }, + /* 3 << 49 */ + { { 0xe63fbb10b5356889L,0x5995a0a92e73aba2L,0x5cea30677afd4bf7L, + 0x4494e39dfd37120dL,0x8c572c7249d718a7L,0xfe159c275fa305fbL }, + { 0x751c217fc276c40fL,0x44d0643c45e40857L,0x9a996e6efe7a6486L, + 0x1a4f6d10f53b0e47L,0x651390ecd15fd593L,0xe0c1181d739ee9eeL } }, + /* 4 << 49 */ + { { 0x0f05710b11bccf2fL,0x7113085a7aec1bc6L,0x137da67a46b8d0e2L, + 0x454b89fc698b78ccL,0xf2a6e1de258a9393L,0x5f1804e716488e69L }, + { 0x7c6c550215b3bf35L,0x3b0e09a5b05c2ec1L,0x4b9de30e92f15247L, + 0x09d4ca9327e70a0aL,0x9c8b16340d149363L,0x54a8287cce642137L } }, + /* 5 << 49 */ + { { 0x3a05e7d5ca2af43fL,0x068953f975009801L,0xd6c8a76c06740141L, + 0x7e1df1038a831fa9L,0xfe06e2bae39046f3L,0xda5264a0e1807c29L }, + { 0x1be4ffedff5d4808L,0x299d6537c52be83cL,0x1b38adba11834a9cL, + 0x6074a60b1248fd42L,0xd9a0bd2e041b5430L,0xf222ba84a7b76b03L } }, + /* 6 << 49 */ + { { 0x49ecd6f3346a764eL,0xe46847f14105e657L,0xce9cb2b57550f608L, + 0x45f1a1f7f4cf062eL,0xcdb19a112c27d38aL,0x36d375b284e50b19L }, + { 0xf43691540dba6405L,0x4c9dc863040354dcL,0x7229e70ea24d09cfL, + 0xe72aa86c7cf6831bL,0x487fb68425392838L,0xe88bed04430b9b47L } }, + /* 7 << 49 */ + { { 0x9f77b8c5d1164788L,0x45bcd4c1d7b5c5dcL,0xed22ecf3d88c2357L, + 0x330272ad07de1cf8L,0xd9749f7f4ca13a48L,0x4964ce5d1383ce08L }, + { 0xc033d516b0d0dbb3L,0x056ae73bf51943c3L,0x495cf7e057105e88L, + 0x08ced52e56462560L,0xe9578aa713ca1a7dL,0xe9b045c5a9717f7eL } }, + /* 8 << 49 */ + { { 0xf8a8499b666fa8a8L,0xd0f9401571bba84aL,0xb85e1b1d515e1328L, + 0x88a2636ba941e788L,0xa045241d2b5dd8d8L,0x161be476332f0350L }, + { 0x96c4b205a18fac6bL,0x5cbe8d5e73fc5337L,0x6fc33fc6d00b6029L, + 0x07a914ee89aa3b79L,0x35353eb7a4d4dd00L,0xc026bdc0673e8956L } }, + /* 9 << 49 */ + { { 0x1e551f9bce0b6f8cL,0x1fe7ea4618495e1dL,0x3f6f28742dc0e878L, + 0xb778c12844c43f20L,0xbddc28eb8a250230L,0xd8571a4aac6c3d17L }, + { 0xb9dcaec9730c8a1eL,0x512cee9993fbcf87L,0x0df3a1379bafe001L, + 0x8530e501e2a2b9bbL,0x6d38ba8995ebf91fL,0x704b81a7792cef7aL } }, + /* 10 << 49 */ + { { 0xccda372167103852L,0xf78d22470c54de53L,0xebd16036afa44aa5L, + 0x7b88024864a24ab9L,0x86b38e961c2bc78eL,0xd0aa0d058d63b295L }, + { 0x24912955c62fcbf1L,0x77a68156b9ac435cL,0x432401c71b360b26L, + 0x091f19f34c58ef8cL,0x3a4a61f483d46c9dL,0xad0e5c72e8d616cdL } }, + /* 11 << 49 */ + { { 0x668d598ad1666826L,0x6ffed334fba0ba63L,0xe71e3359d7cddc30L, + 0xa9c15c2d9fb9998eL,0x6966d350612230b9L,0xbca3ed23ae4fe0edL }, + { 0x537cac1b3caa3edfL,0x4f4a737ef33c180cL,0xf8d8f796f8807a7bL, + 0x5c7cf072d1aab3e2L,0x7f0ccb9dfff736e4L,0x71bf0732ef11266aL } }, + /* 12 << 49 */ + { { 0x33b029bccdaa6831L,0x2548552d4c1f9cedL,0x35f1a002dece1c8cL, + 0xc6b87fd7acc23aa5L,0x0b8bb275bab029a4L,0xf07bc06730bfb42dL }, + { 0x1688ff5d1f69ce9dL,0xeedb7b5edb10585eL,0xb7a88cf0d432c197L, + 0x20731bdd015a350aL,0x5fa1835463223f5cL,0xe392e1318024693fL } }, + /* 13 << 49 */ + { { 0x61ada737c3449cb3L,0x071062504ca876ffL,0xcd98a39001d1403eL, + 0x197c845096ded881L,0xd060160568cacebbL,0x7e1b37d1dc3ddff4L }, + { 0xfdc1bcb5d1725e92L,0x11cbe941bf0856d2L,0x63fd35d050199657L, + 0x208a1047b9790d10L,0x52790ce61af4301dL,0x75e6d83beff28b69L } }, + /* 14 << 49 */ + { { 0xdfaeea0a0154731eL,0x9e53419de15a0388L,0x2ad6a83c25a992c8L, + 0xa2ba020fe125501aL,0x894ebaf8d4dd04dcL,0xd48cb95850765559L }, + { 0xf9b58d0980dec92bL,0x2a0e11659da299d7L,0x3c081853efe9cb11L, + 0xb9f3b702a511c5e0L,0xa8f7a25f70486180L,0xc0358b25591b3e2fL } }, + /* 15 << 49 */ + { { 0x00333fa6fa806947L,0x7e4dcfb3504b3e19L,0x8326b0acad4a5dfdL, + 0x9ffc65eac7b12e49L,0xed3b7c0258d16eeeL,0x79fccfb434a4222eL }, + { 0x4a8070a0e556357fL,0x554fe2c9ec97769eL,0xcc405a57da691714L, + 0x12927897856f590eL,0xd4805b93ba198dcbL,0x2649be2e4b18444bL } }, + /* 16 << 49 */ + { { 0xf36e8398eaddf274L,0xe41553a16a5e4ddbL,0x36ab07464efc5b0cL, + 0xb211e59ad316c434L,0x2515ec9f16ccf839L,0x6ecb746503dc6a07L }, + { 0x842b7275c65c1b07L,0xf7ceeec535750ab6L,0x967d711ccef5255dL, + 0xcd3bfb075108cb92L,0xe50c0d8aec1b9740L,0x9e8d56611a9e6308L } }, + /* 17 << 49 */ + { { 0xfcb12ba3aae18c46L,0xb55e959c6e21d463L,0xf720d19f4a4f6f21L, + 0x1c2ff60ed4320c5fL,0x4ce5e1ac1a1b40b8L,0xfdebfb81ff6fb9a0L }, + { 0xd6c37d8a9c67c07eL,0x55167952012fc09fL,0x5dc722b52c306c4dL, + 0x1efad8d2bc1f65e1L,0xa1478f3da52556ecL,0x54cbfb884a795dd5L } }, + /* 18 << 49 */ + { { 0x84f8ea13ccb8a36aL,0x5f7aeeffa05709a2L,0x4942d04e60574f37L, + 0x855b13e9e048b400L,0x747e4067a6b59c09L,0xc349fb05074d3990L }, + { 0x398e6afaec2c7e03L,0xce361865ec2d5a4cL,0xfc04bf8eb6f57d22L, + 0xf0e0b84c759ce6c6L,0xb65141235ee7e528L,0x8ca144bdf5c0f9b9L } }, + /* 19 << 49 */ + { { 0x5868449bc6e0124eL,0xdd65ffc1e68ad5eaL,0xe126665f4f577466L, + 0x8ade5cee2defe8deL,0x7c1cf7f07beddf87L,0x0e0e066a362c5956L }, + { 0xac2aff4e15563b47L,0xa28ab875620d1299L,0x91f67b3fd8caa497L, + 0x91bef53394fc08a3L,0x0fa27d9cd99918f5L,0x205b6c1f60b67bd9L } }, + /* 20 << 49 */ + { { 0xc1370daef6a58536L,0x6f2e5b37c56b0ae9L,0x5511d68292f6b6a3L, + 0x2e9e5034ae575249L,0x3e5a32f81d14bed7L,0xa346a86f75efd17aL }, + { 0x4f2510a60309fd7aL,0x689ecd74d0b1425eL,0x9e9bebe19f771e24L, + 0x20188045adc5b48cL,0xe49811b6b845230bL,0x420855ec5a8687f8L } }, + /* 21 << 49 */ + { { 0x705a9ab30aa1a423L,0xcb01466fb49830c4L,0x1db1768581a75897L, + 0xcaacb855e341f157L,0x9b13cd497a0d3c38L,0x119b4d47e177fcb3L }, + { 0x0d8f7c2639788712L,0xbda0f3180642bd4aL,0xdd4bd88bd4616239L, + 0x9a3ecf978df1b895L,0xd0d54caf4a6dc07fL,0xa7ed6bfb31810203L } }, + /* 22 << 49 */ + { { 0xe650e49abae1b94dL,0xb6b162e6e3199794L,0xdc706859b4ec0480L, + 0x28b618c24b1a06caL,0x0929a001403acdc2L,0x796dfd972da3aefdL }, + { 0x16389072ef4c1673L,0x600d8bd7fc94a4f5L,0xf003214de5f386a9L, + 0xa7af0499e62cbb48L,0x750a3b00de82bad5L,0x6c615b838e7dc8eeL } }, + /* 23 << 49 */ + { { 0xe1916cb4eae432e5L,0x81f3e48acc193889L,0x54d58685ba922a4fL, + 0xeffcc528bf11b76bL,0x2f70d38f8171c971L,0x547ce8ccb3a5669aL }, + { 0x3acd91b878e6d0beL,0x372dbf2c689c2913L,0x9fceb5bbd0aae543L, + 0xc601f9622830a977L,0xd55e74509f874dffL,0x77ff8ab4822878caL } }, + /* 24 << 49 */ + { { 0x283eec26d71543a6L,0x98fa08bea7627841L,0x269a83b827ad302dL, + 0x225f2f12bde3fdd0L,0x046fcf380130b3a6L,0xea733c1ac3ed9043L }, + { 0xf870f14d70aa08d1L,0x643d18b834391e0bL,0xf3e1d5f4847be772L, + 0xa9498223d0ed73a0L,0x6933ccf014b3babbL,0xc2439ae437f08f70L } }, + /* 25 << 49 */ + { { 0x503414d0f2cb5475L,0x51b9497cb24cbf9eL,0x57359dee2f4c7746L, + 0xee7125c3f3118a94L,0x2f0db706e4ea33d6L,0x885e8c3eddff7f63L }, + { 0x752f594b628432f0L,0xcfadea7779852e2bL,0x4f733b8ba2ba4b7fL, + 0x163c8c2e530f763eL,0xf95a7b57ff05a7e9L,0xd4768d242d7be01fL } }, + /* 26 << 49 */ + { { 0xb643f4e0f88d049bL,0x5e0ac1fb12682fcfL,0xeaf7874d9f981c8fL, + 0x9c2adfd2b1af779dL,0x9a7abeaddaa8c275L,0x09ad552124cacec4L }, + { 0x069cd5c40ead1646L,0x5186bf190a6157d1L,0xcc222a9396503506L, + 0xfeaa7bdebd29686eL,0xb0d65b0da7257c8dL,0xc31c0a8898aa227fL } }, + /* 27 << 49 */ + { { 0x5495f21c9fe88a48L,0x01f580ac590c1966L,0x1ad433ba39810166L, + 0xecbc67003a5187f6L,0x38d36c3bd4216887L,0x49653585e27b615cL }, + { 0x2a70a1d9e773db7eL,0xe36d967a63c1c048L,0x51cba60d26d15862L, + 0xb633839fd5a6b746L,0xa6a756a2ec1fc364L,0x37fef8d24cfccb6fL } }, + /* 28 << 49 */ + { { 0xb4b7651f5be1d45bL,0x0425200a7f0cf680L,0x200d12b48960be95L, + 0x02fdd1a14945b193L,0xedd70e3e27d046d8L,0xc1cc086a83f14e12L }, + { 0x1580e72b2629396eL,0xc87439dbf9ed73c1L,0x5debdf30a90c5128L, + 0x0b6c020e9fbe14efL,0x168da56a0149a0b0L,0xc66a4dbd79c58ac6L } }, + /* 29 << 49 */ + { { 0x6ecd9c41596b8890L,0xd25172fe210d9613L,0x1ce8abf872b97aa5L, + 0x355899d610faa675L,0x003b69adf4ddf011L,0x6736cd40ec2d1af9L }, + { 0x8069a0ad4f85ac72L,0x5c31d68b5836cfd3L,0x8e9486eaa5ec1473L, + 0x8e175c4a1468cebdL,0x58b3d2b1ffaf2f77L,0x4fd21681a17a3e00L } }, + /* 30 << 49 */ + { { 0x800aec84330b8e2eL,0x1a2c033e335837bfL,0xf1a91551fe6f6dd9L, + 0x326c42b21de7360aL,0x300e740b7b66f9d5L,0x53bcc70068ce95d4L }, + { 0xc9e225ac3d80f228L,0x64b2ad4e6977dfdbL,0xac863b0801f23221L, + 0x0517a648df11e5f7L,0xbf7aedcb68d11050L,0x2607e33777b3029cL } }, + /* 31 << 49 */ + { { 0xcb1955e44f4706b2L,0x0821d4663acaed1fL,0xbe822db07f8b43deL, + 0x3d11573f9b1c83a1L,0x6c052118201eab83L,0x294c5060dfe340d7L }, + { 0x994a4bde0644005bL,0xf1519f3258fa0552L,0x9077bf5bd4d0d39bL, + 0xebde1ff0e6204ea0L,0x58a68e09829130a7L,0xda64eb8596961bb6L } }, + /* 32 << 49 */ + { { 0x1afa6aa6206add5dL,0x66cfbbae150ea4c9L,0x07fb920b5d36da4fL, + 0x144d51f9291e774fL,0x26c2c134f40d87a8L,0xc8cf3524a932f1a0L }, + { 0x35bb2a425aeb0bdeL,0x5cfcc1dac4be960aL,0x5c40cabfaa1838edL, + 0xea0c05ffe2855f1fL,0x931ebb02fd525934L,0x31a7b78f16246fd4L } }, + /* 33 << 49 */ + { { 0xbe055fead42b36aeL,0x733a05ed819ddf8eL,0xa00fa0a15c9a6102L, + 0x0ed363273c0af634L,0x5b5a62b4d5970a32L,0x9d7557dfca954cd8L }, + { 0x30314f0c6daf871bL,0xaa7c42a96267b2abL,0xc5d1f0d6132bc62dL, + 0x77ac94df7ed26084L,0x0d256fdada34e1f6L,0xf0259d1caa4b4dd6L } }, + /* 34 << 49 */ + { { 0xf576c69e86ccb00bL,0xc870c07f5781803eL,0x91d4c0c6b1869e56L, + 0x9c2729397d940416L,0xdad33f73c4d0269bL,0xe2baf5b8838c9198L }, + { 0xd8bb9613218414e4L,0x5e9f7b67c980ca07L,0x1e2d4e63165079fbL, + 0x6ae5b17f983b3fadL,0x1e66b8380c24e22dL,0x80cdaec2136e0be8L } }, + /* 35 << 49 */ + { { 0x98cb12d93fc277f4L,0x81def3ee160b8743L,0xa1f07ebb11711fb6L, + 0xba17dd15a95b3ba0L,0xb25f1c78bc158f33L,0x1bb83cf27841e8bcL }, + { 0x57ad928abf49233cL,0xc94fd746bdad3f2aL,0xf7c716ae4a4c6600L, + 0xdd0e3117060a78b4L,0x85e8851a860764b0L,0x3342d974bce0d787L } }, + /* 36 << 49 */ + { { 0x2bc4e37a719793feL,0x1543af2aa68ceea3L,0xc99cb391aabdea45L, + 0xc890e546f0b8eea7L,0x8b75b91feb4173d7L,0x9d52d04bef46f637L }, + { 0x0929f25d878ff734L,0x7377235fb6c43342L,0x657835cf6eca900cL, + 0x7b752665098bb5e2L,0x320d09b6b8a61442L,0xec4f8182cf5b8023L } }, + /* 37 << 49 */ + { { 0xfc5f8feffc788160L,0x7d552625f73f48a3L,0x4eea435145c02498L, + 0xb5f5de5bf8f8af26L,0x78f1c499067b1610L,0x6e0d1b14eac18a29L }, + { 0xf8be2f6c052af916L,0xd8cee5668876af81L,0x99a27ec31577bd90L, + 0x3ac529d242919f4fL,0x1215428c7fc05dd4L,0x99ef01e450f67e87L } }, + /* 38 << 49 */ + { { 0x145902629d671094L,0x7fef49c166ce858bL,0x2a7ea540c2f21eadL, + 0x1226b04fc1d5a636L,0x4fb54e4e535efb9bL,0x6c51cdb91d72bed3L }, + { 0x94162e44938efaf6L,0x166013cfaf6f5697L,0xfa9495bddf95f9c6L, + 0xc05441cb0d7f8406L,0x7e5c89763a233ca6L,0xbc75dc6493fe8e42L } }, + /* 39 << 49 */ + { { 0xe1885cf128ed669eL,0x6e9f40dfb428b3cdL,0x412388a61626f8d0L, + 0xb8201f047cbcd192L,0x642ecfad70ba644bL,0xd43be1cb43c76bb7L }, + { 0xafafffc388f4bd51L,0x8c40e2787052eea6L,0xc1a84e866a4c8776L, + 0xf0201f292fe7075dL,0x132f80e4576af421L,0xe0831b7f4731dddbL } }, + /* 40 << 49 */ + { { 0xecfabd2742dbb68aL,0xad43a2c43eb546d1L,0xcf4e64ccfe2691c9L, + 0xe3889e258347566aL,0x48da354885b8c733L,0xcb7fe0679d9c9f57L }, + { 0x8c26a8d668223280L,0xc1e8ff623065705aL,0x181ca70a3f8db9f8L, + 0x25aa6450e758213eL,0xa4898f9169b2653eL,0x5e5c9fb4ccd8303aL } }, + /* 41 << 49 */ + { { 0x640b6946b03aa213L,0x6b99e84d00c068f7L,0xed4f1d2d99c5c461L, + 0xcec88724b20eaffaL,0xdf2b79a95dbbc32cL,0x2f7397054f3a1c5bL }, + { 0x1594a54946eb52edL,0x55f11aad39c4c43eL,0x0fcdb331f46500f2L, + 0x0d66be885ceb8dbfL,0x4d977349886dbbf1L,0x238f4617797d1b41L } }, + /* 42 << 49 */ + { { 0xfc8c7320721034d4L,0x48b389db60264280L,0xac246988649cbd88L, + 0xb7f52891a50bb658L,0xc0a812e50a7f279dL,0x6593175967fb2cffL }, + { 0xd31a77c6661ab439L,0xabadcea00ceb4aceL,0x201d98f6a3702dddL, + 0xcec1e83e7c9463aeL,0xc64e44fbc55e6856L,0x421f3e3148aa0d81L } }, + /* 43 << 49 */ + { { 0x4f0b251871a07c6dL,0xbfe652edaf3a2fbdL,0x5f68dc667bc2053fL, + 0x445df84f6040a7cdL,0xbdda2132180dc0a9L,0xd8627401d6c7a92fL }, + { 0xba350cb190cd2c73L,0xaf4c1e5929886ab4L,0xee8fdff2d677399cL, + 0x3ce35c6edaecf83fL,0x44df0a300f114062L,0x1b633b4647f29868L } }, + /* 44 << 49 */ + { { 0x48483f6af58ae2c1L,0x70ba34635e1cce49L,0x5f7a1c6d33907532L, + 0xa0fab701875a5f3fL,0xf2e8b0ff85d387e1L,0x0076aa68ff349689L }, + { 0x6e392b02747e2fffL,0x5e1ea320e788d577L,0xba705bd7713a0b03L, + 0x04ef192f2dc2cbc5L,0xa5a14eed38aef8a2L,0xf9682bbe30a268faL } }, + /* 45 << 49 */ + { { 0xc04f2cf540244a00L,0x00c90c3bb8dc0ad2L,0xac5b1060601d76f6L, + 0xad97c5c1a7ff84ecL,0x7919a06dd2328101L,0x62d5b7a4ca8a69c5L }, + { 0x75607148de5a2cc9L,0x1afff7f79a75fd24L,0xe62efc8083a22367L, + 0xad08258a10e05e36L,0x22666e06c0e4b549L,0x15f62c613f4c48c2L } }, + /* 46 << 49 */ + { { 0x751affadc7b8da09L,0xc052109dbd8e45d5L,0x7d11aaad87c14560L, + 0xa0410b2a6b690121L,0xcabad9853e10a103L,0x4d19bd3e785f1bfeL }, + { 0x8f32c6b84b6167a4L,0xb21d4ec297b4f546L,0x2e26df99c008f7c7L, + 0x63825597eb347720L,0x6a05b375afe39fc8L,0x19790b92131201a3L } }, + /* 47 << 49 */ + { { 0x149347ff7780729eL,0x076b4edc62e2dd48L,0xbf0de9d7cdcec866L, + 0x9d75deab8fa1e18cL,0x10931716eecb1f4fL,0xa8765dd3a385eb7fL }, + { 0xfd26f39c4d70651cL,0xc501caf48834c723L,0x1d263a83a65e5093L, + 0x57ee2fb96f709deaL,0xdae3dcc645091321L,0xba0665a906a60a48L } }, + /* 48 << 49 */ + { { 0x517d13b1784d0621L,0x2db4ef27d77b84beL,0x6e2e26866d752aaaL, + 0x95da9fa1cab02667L,0xbe8d91ad423163c3L,0x8f3d59dba69953c9L }, + { 0xf728b1d2d6e635aeL,0x5c4c177deeea663eL,0x97a900a82e75d9c2L, + 0x136c6b1e3ad09defL,0x4bab14a6dd8a2be8L,0xa4ee903025cf1447L } }, + /* 49 << 49 */ + { { 0x05f93697a5235c12L,0x434f91026943a0d0L,0x92696b701a4d3169L, + 0x0a9da44b8c3b1ee5L,0x327f9f79d295521bL,0xf605cb83afd8aa40L }, + { 0xe3bd4ab5d365fb37L,0x6c6a470ce984ea2dL,0x7ad01e6b392af60dL, + 0xbef2dffd5ff8ee6bL,0x4e56deb722efc2ebL,0x1b90570ae14ff270L } }, + /* 50 << 49 */ + { { 0x70718d8e333cd9e2L,0x858c880c6b03a371L,0x5b7f69a5926a3dd4L, + 0xedbed135572f420fL,0x740a21e6332aaa09L,0x665aff63fecf1e3dL }, + { 0xd884a3c1214490e9L,0xed70c29a63cdab1fL,0xc92dfa58786e274bL, + 0xa5395591d7fd529dL,0xacdf81ac3b95b61fL,0x07f801df40cb45a0L } }, + /* 51 << 49 */ + { { 0x4f863ad59230d44fL,0xd176d2764a099825L,0x4a6868745a43a7d8L, + 0xbcab3548fff3e8dfL,0x15028cfccab2c7e6L,0xad077a8874a91fb2L }, + { 0x015700d39eee3e32L,0x524ef9c7386e489aL,0x3be1771b60285f8bL, + 0xe4a5353cf9c33beeL,0x0aa0f2ab244ad683L,0x04e846f98a4c0ed6L } }, + /* 52 << 49 */ + { { 0x326a204790f55f13L,0x194d24db53017b29L,0xa26db785cd4368c3L, + 0xd58943e8238d7518L,0x8e06f8cc3527387eL,0xebc6dc9e071846d4L }, + { 0xbfc08dccc541e098L,0x3dcf0713e4fbc9a4L,0x44e9ba7869fedb43L, + 0xd867cf784fa012a0L,0xc618b2b88733ddf2L,0x4149fd48a737fd5cL } }, + /* 53 << 49 */ + { { 0x5c4c2183179b1928L,0xc54d315d0439876cL,0x07d22792f7495bceL, + 0xd378185e3bc32c4aL,0x8539aab65b31c5c9L,0xc72b1ac640dffb35L }, + { 0x46bb918a2e8d6ae2L,0x102c49f9e8a1d7a1L,0x7c622793cd2764d3L, + 0x5bbc6f023c7aafcaL,0xa41f383bcff71b4dL,0xc8a0e1a9aa99bf83L } }, + /* 54 << 49 */ + { { 0x323aad4991d6b8f3L,0x91b678c0f3d9154eL,0xc141e2424ce74f67L, + 0xb7c38aef65659ca0L,0x5b5f89b174a937e1L,0x739fad71abc55012L }, + { 0x315ed44ccee5f4fbL,0xb0731455360a61eaL,0x39235ff0ee93ce5aL, + 0x6352556fd203baf9L,0x3c22dc6a0ea06b93L,0x195638cb591bbfa0L } }, + /* 55 << 49 */ + { { 0x8bd5a15359ad0688L,0x827e82d8a7323070L,0x9ea55b3af70686e5L, + 0x511c8c3f34c2d054L,0x9364d28aa14a3c61L,0xc4dff9c461374139L }, + { 0x947c3ec9a39c01c0L,0xead11d42108440bbL,0xcc6d893569677f79L, + 0xb1d632710b9b4823L,0x2cec325e63b154e0L,0x45e97c3814a85b9cL } }, + /* 56 << 49 */ + { { 0x11b59f3e92acd14cL,0x188c1bb1d7aea098L,0x5cadf0a19365958fL, + 0x8fef04fcca0b1b0eL,0xbcb4d9fb0c274a5eL,0xe97eb41cba78427eL }, + { 0xc49f0bc55cf06378L,0x2681f12a281b669dL,0x200e9e583f796b81L, + 0x5bbea92b17964262L,0x86b3c15756db0039L,0xe4477c5eead482baL } }, + /* 57 << 49 */ + { { 0x1340e22c050fc1faL,0xd5cc5445bd062615L,0x03ad31601f494b03L, + 0x612919142af1b95eL,0xdb31a06d53705ac5L,0xf590433ad07ae464L }, + { 0xed52363421bbbd72L,0x1f032ad2f1cc7842L,0x212b1d5536a7164aL, + 0xc2cedab7dd973183L,0x29aeeee05e74ada3L,0x579984d8bb666836L } }, + /* 58 << 49 */ + { { 0xbbe5db83e13d34d3L,0xbae5ae959a8a3344L,0x55d2f0ac797d6e35L, + 0x75e78c017cd0abb0L,0xb757f72cbad96294L,0xe52493895d556f25L }, + { 0xc02293538e7675dbL,0xc363c5255c8beec5L,0x7ac23c0b7c87ee00L, + 0x9c5f22b4a7de93f8L,0xc6f0ea64d9644b5fL,0x3fa718d4d161f87eL } }, + /* 59 << 49 */ + { { 0xe8496c463f356cf8L,0x25b5b8742da1b81cL,0xa35ec06330efa9c9L, + 0x7497d85ffdaeb348L,0x312ad677e83f49d7L,0xcb5c346cfe8aece3L }, + { 0x19d7332d61cd4ebcL,0xb03dece0d0967141L,0x47dcb81af5455addL, + 0xbef0e70389ca68d4L,0xf7abbeb9c987400fL,0xbda81c65a1521da1L } }, + /* 60 << 49 */ + { { 0x535f3e4b86882341L,0x5af1c6322e22600fL,0x0403b6e0584a13abL, + 0xa64de86661f59ce9L,0xd22106f738501b92L,0x2932f808ab6ffd04L }, + { 0x8da4cc6e232967f2L,0x4b8fdd9ef3644670L,0xe8cb6ef31e0c51bcL, + 0x20b7b734230c6897L,0x5009176453d9339aL,0x5f5c8c67ca637277L } }, + /* 61 << 49 */ + { { 0x23e333d467232358L,0x3c2807bdea037380L,0x9439cc4626f1dc2fL, + 0x8c87dde53ac29173L,0x601b7245766897a1L,0x9e0b1a4559350e3cL }, + { 0x0818b6cb301db407L,0xbdc4584676b6fbf3L,0xeeca553431bdd954L, + 0x1dfabc033f9be3bfL,0xdf0415dc68851bd8L,0x33be32a67aa9dfa8L } }, + /* 62 << 49 */ + { { 0x8c9017dd4b4e4b5eL,0x02f435dd7b892b2eL,0xe9af9efd292e0f2dL, + 0xa32124c75c4d315dL,0x5c6fde76b31a390dL,0xf1fdcefaa6e46d3eL }, + { 0x5f39dbfe9e9e84b6L,0x574d647d19aab6b7L,0xd5a234cdad1a2987L, + 0xeab841c7dab59c81L,0x5155898db3137b90L,0xc52e9ddd06db2fd0L } }, + /* 63 << 49 */ + { { 0x8617f0d490660ff7L,0x00d73d108b35743eL,0x433e42d68a6ca67eL, + 0x575ecb9beab5cff6L,0x4c64bcddf258960aL,0xb8ffb7f32c23405dL }, + { 0xa98c06691261b0c7L,0xf2701f4a6b9bf7c6L,0x3abe44c41c68efc3L, + 0xdb5ac9cbf12c7a25L,0xf5b4616651120981L,0xf8058f7074d518f3L } }, + /* 64 << 49 */ + { { 0xcd92906c6d6ae962L,0x628356159807d881L,0x0d6929781fdc1915L, + 0x45d01a8c269d611eL,0xe7bd1e709665b00aL,0x086385349bcaa388L }, + { 0x8f189e882dd24299L,0x5f643392b82fb270L,0xca65bf16c633b111L, + 0xc6adc9c9d6f1dac8L,0x0df2c293a3c3381dL,0xdd6ae97d8388cd12L } }, + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 56 */ + { { 0xffdbd0eb3863db02L,0x8b8256832f57e10fL,0xc11acead35e7a3a2L, + 0x4998cf8c67833028L,0x8f3a346b844c7976L,0x0a9d872cdb9b1a1cL }, + { 0x8735dabcb98d445dL,0x93790d80305fa0a9L,0x7c0add49d267a01aL, + 0x2b46c913ffa20d11L,0xf2acef26d8ab2d4aL,0x71b701b93d926080L } }, + /* 2 << 56 */ + { { 0xe9d2a98a5133de8eL,0x37083b60b81b8b00L,0xf399325dceaf86aeL, + 0x03b17c888f161525L,0xd8ac35c984211b9dL,0x220837849050ca48L }, + { 0xa818c44bc9fab832L,0x8882bccee5aea7daL,0x633aaf35f8715b04L, + 0x5463e1b99d8829a9L,0xb18df52d84a820f1L,0x9d5ef891d096675dL } }, + /* 3 << 56 */ + { { 0xd54e2c7cac60496dL,0xc06d5e5d04cd50a4L,0xcb4105e8e60f7f59L, + 0x705db308427483adL,0xf73ba98bf2bff383L,0xa945611a0220e6e9L }, + { 0xc01c46b8d957e12bL,0x458897b7acb1f371L,0xf738dc0bfa3403e6L, + 0x098bc687d2202896L,0xec0c217a5f882e5eL,0x8f25af77a1f4eb13L } }, + /* 4 << 56 */ + { { 0x2615c78259ee4124L,0x4dc2824c76532b4bL,0x9c3b1d771c84a04bL, + 0xb6fc203fcb9f9e34L,0xbed65464c64f7846L,0x04f520a2eb004248L }, + { 0x5c0177274a58fd22L,0x25958482c10d9472L,0xb78c6666aceb0e3aL, + 0x18d3c188fc046f0aL,0x7f3e2f301baa9595L,0xa574f8cd8a2844e8L } }, + /* 5 << 56 */ + { { 0xc899eba381c2d81fL,0xb27267d6f3f0a431L,0x607c8629da55568eL, + 0x6b5472282b1dc1d9L,0x23232311c9c001ffL,0x207a2eb2488f8b85L }, + { 0x3867ac9adac37a28L,0xa36d14d32584a5f0L,0x7398c647a74488ffL, + 0xf6ed920fbe087640L,0x72beddc76319a571L,0x55c2cd826a244aebL } }, + /* 6 << 56 */ + { { 0xb7da79c625f8a53bL,0x6b950bdfd331ad8eL,0x3481b7b54aa36d18L, + 0x6efeaf88ed0e3091L,0xeb017bddc993074cL,0x8431a6d6529dd654L }, + { 0xf5177231bd069585L,0x6d753b103ce85096L,0x194d82d34ca26741L, + 0xeaeffe15adcd1650L,0x4dcec3d9af7758b7L,0xf5fdf6664cc2c819L } }, + /* 7 << 56 */ + { { 0x94bdc7f4a9810744L,0x464195daf045d859L,0x27e2dab0d654cb57L, + 0x1d4e1e537a491956L,0xa1ef570c31d5d099L,0x01cd21ee295f3de7L }, + { 0x8681b00db8249038L,0x17c31bce93781b71L,0x4324e90c6a1b5748L, + 0x44f9324c1222e554L,0xe30ba10fffd53dd0L,0x2e5817a8b48eeef0L } }, + /* 8 << 56 */ + { { 0xa349bb66c8fccaa9L,0x7888755f31a53ee7L,0xa6e1d891c18d3750L, + 0x9985aa4dae8d2bfbL,0x8baec9ae31b33078L,0xee68295a98750e94L }, + { 0x0d834bf8d6ddf305L,0xab33dff39762126cL,0x0c22faaa0c51d098L, + 0x32404042b887a10fL,0x31f6a614248bed32L,0x311f86301ce0d662L } }, + /* 9 << 56 */ + { { 0x5c95cf080d844b0dL,0xe09a8352c98650c9L,0xc1b106c5d089058eL, + 0x2b3cf101eb0c6107L,0x1993fdba3ce6ee18L,0x7234eb6425fc4d24L }, + { 0x8345acfe05f46dfeL,0x07fccf68a2d87d38L,0x14494cea85da7852L, + 0x8737500acecdd9f1L,0x72b1490ca39068ffL,0xce28271acfa4469aL } }, + /* 10 << 56 */ + { { 0xc872326f55c6c00aL,0x6a5f0fa3f912decaL,0xf4ef0ca5a7d1bdb1L, + 0x1dee685b37dc6bebL,0xdad4cf52f1b09b88L,0xc7199f0277f1db84L }, + { 0x7099ef00a3f00491L,0xd8fbbbfa6d8804e3L,0x2a00b8e50ae1e360L, + 0x8a8c9d03fe9be5dfL,0x06e0585b8b1faf6fL,0x19542ee7ae29c502L } }, + /* 11 << 56 */ + { { 0x36cad867e2aa1c5eL,0x7ef21e51317f9078L,0x68efbb84c82e925fL, + 0x973b36769fe751e0L,0x09c4e0c1177d36a7L,0x9c0b7e048a753c5eL }, + { 0x8414cdab15ccad5cL,0xeea2134ed50c1678L,0xd9c1dae8f6585d5fL, + 0x82fd04ab4e5c3d96L,0x868cddf7da3812d3L,0x32a65aeafda07e68L } }, + /* 12 << 56 */ + { { 0x73292e6a60720858L,0xe046a79953160855L,0xf74d56c9ed3b94c1L, + 0x0e371167c67863e1L,0x19b3a9f43f6636cfL,0xe624798d898a25b0L }, + { 0x2ed1fc4dfde2cd6eL,0xd9a7ab519fd15ee5L,0xb6b8d551c487b1cdL, + 0x9fec705ae8936c54L,0x4b779dde1a50e094L,0xfb5100c2c3a4ef5bL } }, + /* 13 << 56 */ + { { 0xb35a7b102704c525L,0x8a77fa5b44276cbcL,0xb4a9cd235ff1a12cL, + 0xc74a017c88a37997L,0x84e26eea9af37476L,0x8a6b8c0e7bbf737bL }, + { 0x90ab7c948f05bd3eL,0x31749075464f3a2cL,0x32f7873c1dcfbd25L, + 0xc0af73d343bc2054L,0x556c4798171d825eL,0x2c84b5b6081542f8L } }, + /* 14 << 56 */ + { { 0xa5907e5c59ab2507L,0x12b86e04cf7df60eL,0x0a14bed18af4bc50L, + 0x462863b20c11bac5L,0x98dde284126958dcL,0x8877e7695625eb29L }, + { 0x869f7214f4fe19e5L,0x29867e51ec0f8c1aL,0xbf498bc078b85f03L, + 0x9dda400e8973a94eL,0x8d8b998ae6e51b1aL,0xedb0957c557ac00eL } }, + /* 15 << 56 */ + { { 0x84b6d5143b7d43f2L,0xcb84c823afb7a2b9L,0x892e8c4c56d2b161L, + 0x52ea7426214fdc0aL,0x07f3d57679763557L,0x9f95fd585a828bb3L }, + { 0x2c7f03d550e14019L,0xab723de7d7eae7b3L,0x4c08189317f4ea6eL, + 0x64cc5bc0ec367246L,0x73077b5ddf11c3b7L,0xfa34b540e08eb4bbL } }, + /* 16 << 56 */ + { { 0xac6dbdf6edc9ce62L,0xa58f5b440f9c006eL,0x16694de3dc28e1b0L, + 0x2d039cf2a6647711L,0xa13bbe6fc5b08b4bL,0xe44da93010ebd8ceL }, + { 0xcd47208719649a16L,0xe18f4e44683e5df1L,0xb3f66303929bfa28L, + 0x7c378e43818249bfL,0x76068c80847f7cd9L,0xee3db6d1987eba16L } }, + /* 17 << 56 */ + { { 0x254ed267050f46f1L,0x36786ff864daa83cL,0xb4a89efc802a3ae6L, + 0xe0027b3486b77d59L,0xb7147905f48d0de6L,0x00733ca710cf7c60L }, + { 0x87efbe387b3ab776L,0x3db10898de9730f4L,0x61f21e1386b7a40dL, + 0x5541873648455b6aL,0x0de378f9a88587deL,0x42dead7a766d18f1L } }, + /* 18 << 56 */ + { { 0x42b8ef51e15ad876L,0x498886e5082e110aL,0x3144e8c964edbd73L, + 0x4b08cf86f79e6724L,0x42d06d53ddfdb6a5L,0x4c9dce336d8b1f33L }, + { 0xbb8913ae4be29e97L,0xe944c922166fdcc4L,0x83913b963c494e9bL, + 0x529d57ac633a0018L,0x632a7cfd242e7d9cL,0xf0e2434dd9b51d08L } }, + /* 19 << 56 */ + { { 0x74768ab044ff52cdL,0xa590ac7eead09902L,0xdc408c53f52c0f5fL, + 0x614a22d6f853efbfL,0x61f391c425126427L,0xb61adcfcbf462fbbL }, + { 0x7b753aaaaffdbe78L,0xce12b2247bea939dL,0xca21f73e95baf09bL, + 0x2a82915e43ca9ebeL,0x67ba04f57936a38cL,0x1c1964f1616b0b87L } }, + /* 20 << 56 */ + { { 0x4dc628c67cb2ec48L,0xc896f99c0cb1e9d2L,0x399ac2e85cc6134bL, + 0x5ac36de184ba73d0L,0x66a334a3e1803832L,0x394af7ea59b770c1L }, + { 0x3df19e55b46f793eL,0x97aaec84bf770a95L,0xf52068b8f8c54408L, + 0xb6f7649f49e05f0fL,0x54d8db0583360826L,0x24748fdf71af722fL } }, + /* 21 << 56 */ + { { 0x68f4dd4956c29111L,0x391ac9910dac9352L,0xb0a8a54206dc9d58L, + 0xb5058ed8fbe70330L,0x8b5e9d4076b593bfL,0x769fb99cd7f2b261L }, + { 0xcdcbb60ec67cce8aL,0xe01a5d5d75da36dfL,0x7e831d0ef7c6e5cbL, + 0x0f6bf54bccdeef00L,0xed49ad3998ba4d8dL,0x8d512c83614d70c2L } }, + /* 22 << 56 */ + { { 0xc1910b2545b4f6e5L,0x54c6ee8489fb712dL,0x80b6fd47f5747ba2L, + 0x3d81e7efd6d4f856L,0x8b9e87418031f1bdL,0xc591d451f2327316L }, + { 0x4830d9971e0f1c1fL,0xeabe29bd86e92024L,0x2f2053a1b8c68d7eL, + 0xff4eb9e879d00ad6L,0xa0c93249f4b4cd89L,0xe127d9d3cb9e0761L } }, + /* 23 << 56 */ + { { 0xeb947df3492d73ebL,0x5474817b0d32c2ddL,0xeb01bef7a9440e93L, + 0xf604581d8085d1f8L,0xf69daa189f69ec8aL,0xc79ac48e71748716L }, + { 0x5141c75ad4beef28L,0xf7dfaf89901c44a6L,0x7bcbe4812e81ed85L, + 0x57ed0e6f0c5a4423L,0x7cf189651cec85a5L,0x8ddfe8a5beef12b0L } }, + /* 24 << 56 */ + { { 0x60ee08b46bc0b979L,0xa31cfd961aba7f4eL,0x66c05a6358bedf51L, + 0x2ae6ec3854df9266L,0xe7dbda332771b08aL,0x44455d312a09fb28L }, + { 0xaaba39171cec98a5L,0x9b2b12258cb543d0L,0xf47a9cd16af6495aL, + 0xe207f3aac6cd8a16L,0xf98952878ae828b6L,0x37e2475725844053L } }, + /* 25 << 56 */ + { { 0x7c8137d8f93723a2L,0x78fa2e03cf552846L,0x3becd2627d11977eL, + 0xdbc8e9b34e9a700eL,0xb2c7798d20decdccL,0xecae57179523bb6dL }, + { 0xc0fec0677fa2f633L,0xe270b10702aab6a8L,0xda280b374dcc797bL, + 0x50a163b86c42945dL,0x4a3fd6bd363e44ceL,0x0aa7e33d38bca4e6L } }, + /* 26 << 56 */ + { { 0x19c7f098a693d0aaL,0xb79d84244bd22a29L,0x19d91d12a9b3c2ebL, + 0x2ae96bfdde735665L,0x2f9c9a773d8a85bcL,0xa74bdd46cbab80f5L }, + { 0x25a2486cdd9f70f0L,0xada155c9754513d5L,0x8aecd7db4c3e9494L, + 0x9c3951ad2cf6665eL,0xd35780d44a9ec29eL,0x064983964cfd7821L } }, + /* 27 << 56 */ + { { 0x23407aac0834f890L,0xad7b7b5599bb065fL,0x3254aa7e4ba2b4ccL, + 0x37f37fd1663f9213L,0x0c72c3111c5a51d4L,0x6e6df84b9989820bL }, + { 0x576a320e1ae2f321L,0xa5fc617c3c62888eL,0xc4f1be4df6c40362L, + 0x01b21892dbfaa5b3L,0x6fc0442390b9a5e3L,0x22a70c8791495c30L } }, + /* 28 << 56 */ + { { 0x365e1382183aee81L,0xe9f2245275d289c8L,0x543cb5c7b70962e2L, + 0x853971711cea2e37L,0x8b31cf530adfc82cL,0xf9a458bf3b67c705L }, + { 0x13b1cb3334a9b3a8L,0xa4325b403732f6b5L,0x39e997ba04e9df8eL, + 0x24c0d6ebf1d542f8L,0x9cb3f1abd82901bbL,0xbbaef37a4cb34763L } }, + /* 29 << 56 */ + { { 0xc4881080b08dd648L,0x21869be8f1fe4e15L,0x63e158b112501ea3L, + 0x48a909ce32408693L,0x77fd2cf062b24495L,0xf7d1e134db9322a5L }, + { 0x4c02c8bcbdb19eedL,0xe03cd00e8a20b335L,0xe04271c530632562L, + 0x549e5dba603e1681L,0xf01b38f95503b61fL,0x244c81920b3fb785L } }, + /* 30 << 56 */ + { { 0xb423030c4b0c7247L,0x242d409f149f8cbcL,0x6094885e9c1f518eL, + 0x6d299dffe04d97ebL,0x152d05bb09903069L,0xf5656895fe235dddL }, + { 0x801e7f736b22ac0eL,0x73aa6df46ba6dc97L,0xba498bc0d66e5d8cL, + 0x8054e17d36b8c78eL,0x241bd2e21137fdf1L,0x8e79a943b97dec15L } }, + /* 31 << 56 */ + { { 0x94e617abeb64269eL,0x39aef936b410ae02L,0xdbb744c325fcc976L, + 0x5072bfab38a5b366L,0x3998aefea3f5d715L,0x0bdbf555a74e281dL }, + { 0x50d2feece24dd239L,0x835925ef46324c5cL,0x53c4eece7a4dad08L, + 0x340fef207c358d83L,0x9e2189da30f04396L,0x2bc748d727e322cfL } }, + /* 32 << 56 */ + { { 0x1238e097ae658422L,0xb4631ddb568df55fL,0x451254e7f74c5c50L, + 0x238b16d28805813bL,0x23987b28925e7a6eL,0x93b72e2d2a1a10bcL }, + { 0x944c784d05e44b7fL,0x7d70fd098c8e3120L,0x6bf1ab2aead45716L, + 0xd5f8f0e631c04205L,0xac062526a10b8881L,0xa1a83cf0fe5505a8L } }, + /* 33 << 56 */ + { { 0xe1e05ff89ea47326L,0x88219a1ffbfc7f61L,0x9cbd0b387dcd3008L, + 0x751d03847671a68eL,0xd73ed70d28e0387fL,0xf66f9cfea9485256L }, + { 0xac68aae1ae153e0cL,0x92eb6542e81b1282L,0x9617d45464541adfL, + 0x81b4d94a9d489e95L,0xafd5cd4620f31ba0L,0x35700392e5a38941L } }, + /* 34 << 56 */ + { { 0x52296be3b71ea9c4L,0x82b05a43424cadf9L,0xb6d329e8842699e3L, + 0x9dfb91bf9370f2c1L,0x0188b738994ecc71L,0xa9a7b03b5ce8b100L }, + { 0x99198b2a25c33035L,0x772795a7e21895d5L,0x37dafa4c42173e01L, + 0xd37f03933ab27d91L,0xf3500a7d2afad1f3L,0xa433b5fd87eac06eL } }, + /* 35 << 56 */ + { { 0xdc193cb5243a97bfL,0xe367f27ff5715184L,0xc4bb95c6fd9120c6L, + 0xd2bd176bbc5f7ba2L,0xf2c0f86de966c1deL,0xc69ab26e811e70cfL }, + { 0x95756460e87c55f0L,0x6b62ab136a59c832L,0x6e971c6c128448a0L, + 0xca72482e91ea44a3L,0x2602d4795dca0f8bL,0x8dadd3e25519433bL } }, + /* 36 << 56 */ + { { 0xfe0553be23246f68L,0xccc1d774d8ad4128L,0xbec668d8cc155edaL, + 0x7a80e9b44231506cL,0x579cb5f42aa1740aL,0x3a61b84fd8b35a2bL }, + { 0x0478c05ba3b519f8L,0xf518ac09acfe39aeL,0xabc15e9076c956e6L, + 0xff35db67dd55d268L,0xbe066679bdbba89fL,0xf7385df12062b845L } }, + /* 37 << 56 */ + { { 0x279d7ffdfc12078dL,0xeb14155eb8f302e9L,0x5f1b11e165b3c14dL, + 0x08510b461bd36b3fL,0xa7f5b2ffc9d73b4fL,0xe5e831557aa09e40L }, + { 0xbed67135cc3d88d8L,0x7b2775f7017a43d2L,0x9ce22ff24c58cb64L, + 0xab88d04849ede1eeL,0xcac13762da63daa8L,0x70662331b1dbfc4eL } }, + /* 38 << 56 */ + { { 0xe4f7022200a8a9adL,0x8d1bbab7d42fffcbL,0xe024970e368ad5edL, + 0x231ef631b4c0c9f8L,0xb47ca0386760b411L,0xe1f297ff179e6d44L }, + { 0x2e5ec77d3e071736L,0x90e20be915b29c93L,0x33961b6dbb7e7237L, + 0xa854df5b42176851L,0x67d223e4a8f4bac8L,0x5464a46f0dee39fcL } }, + /* 39 << 56 */ + { { 0x525a553b32230b65L,0x7bbde6b816bb6a4eL,0x2f5bc6d229f12292L, + 0x5d86858045fbcff9L,0x6ce4fb249f932964L,0xd7cd175098e05ef6L }, + { 0x794b0248e1366d8eL,0xa37afa66332098a0L,0x2dcc1888d9aac70cL, + 0xa01ba83ec15b9fb8L,0xd34ddf851df4b59cL,0x92289e954f829510L } }, + /* 40 << 56 */ + { { 0xdec879d51c9d09f1L,0xdfa9e7d61b371576L,0x8c705c7937fb3410L, + 0xd770153e1f2a02bfL,0x208fc8f18043ba69L,0x58aebe6e25aa3453L }, + { 0x191b69e512941f03L,0x27dbb050d7966e0eL,0xa5196bb7d16bc20bL, + 0x5b6bae47f22b30b2L,0xbddcabda8ce7b419L,0x6e3cfd373b9f5a39L } }, + /* 41 << 56 */ + { { 0x605d4b83330c07f8L,0x4dbe47646a0ed45fL,0x1e715823d7e4163dL, + 0xe337a67dcea3306dL,0x55abf0684f18a604L,0xaaf69d5ea9f57370L }, + { 0xddd09e8129784840L,0x17fd42b9a4fff5e9L,0xe99859e55acee616L, + 0x41d691203b927ed5L,0x35cc99675168f505L,0xfc311c24431d7d60L } }, + /* 42 << 56 */ + { { 0x415f7f0da581c54dL,0x67c678244509f31fL,0x36fb92eb988f449dL, + 0x22d41b1a94181fe4L,0xacc68410df896026L,0x4a10e46f9ccc4df6L }, + { 0xf805a1191969cf2dL,0x7230a26b32ad355cL,0x9d200562e9abd845L, + 0x2db90c3b5cb55349L,0x80b59daa29bcc42cL,0x81272ebc53d32149L } }, + /* 43 << 56 */ + { { 0x6aaf15f27756bcffL,0x5391bc009b645589L,0x46cc4480a6fc61a0L, + 0x6fde9d53293d676dL,0xd6c35628d7618399L,0xdda13a0853daac23L }, + { 0xb6e6c20c0fe7995dL,0x32eb3468d8d41d55L,0x8927d508c19c5995L, + 0x3907eeed3c229e66L,0x509af79f27972057L,0x8a7f44f750e2f170L } }, + /* 44 << 56 */ + { { 0xb91ffd21c87b3fe1L,0x0fe8389b34fe2825L,0xe22d45d74bf4c8cdL, + 0xb575ae4cd6d8308aL,0xa7fa552e82994ba8L,0xfb67a86fecb08870L }, + { 0xc3bebdf8e6dabcb1L,0xef18b357b5bcf114L,0xed518499a4b8eca5L, + 0x0fec83c5df16ed99L,0x5d353a5856b5649eL,0xc858c1d1cec900e0L } }, + /* 45 << 56 */ + { { 0x7a65d2660d85e627L,0x96170bb90bc010a3L,0xaa6e0055da030ad9L, + 0xa75ab280ff4e4a8fL,0xec14e68c0be864a3L,0x05424b9cc17723b6L }, + { 0x9ed54bb218ca85d6L,0x035edc14b78b34bbL,0xc116914929617416L, + 0x0a00e0086cb0d801L,0xba40f1207d4a638fL,0x54b1e8cc9d8bd0e9L } }, + /* 46 << 56 */ + { { 0xbbab4ab54c88db57L,0x68dbee6f9ee9558aL,0x31b988e140da802fL, + 0x9d117c37e90b2221L,0x443ae099025b66c7L,0x8568bd6f2538a654L }, + { 0xf806d8636720df01L,0xe390adf2b649ad8fL,0x7851f8e039d1c315L, + 0x8185ae1a5e650f1bL,0x3dccfc4c9b562532L,0xae99ae835f427c40L } }, + /* 47 << 56 */ + { { 0x99542ca7564c7ad5L,0x682eace49a96f25dL,0x2d01b2488d933a6cL, + 0xf96916ddb8604277L,0xad3259d12e4d7419L,0x9085251fc26981e5L }, + { 0x848219363d2ec970L,0x723ea6a5392351c7L,0x3fae69a55e5448c8L, + 0xf6eee650dfb03d49L,0xe2e1df1ef8c58715L,0xc603b61f1a369206L } }, + /* 48 << 56 */ + { { 0xcbbd8576c42a2f52L,0x9acc6f709d2b06bbL,0xe5cb56202e6b72a4L, + 0x5738ea0e7c024443L,0x8ed06170b55368f3L,0xe54c99bb1aeed44fL }, + { 0x3d90a6b2e2e0d8b2L,0x21718977cf7b2856L,0x089093dcc5612aecL, + 0xc272ef6f99c1baccL,0x47db3b43dc43eaadL,0x730f30e40832d891L } }, + /* 49 << 56 */ + { { 0x7f3a3e5f4447ed08L,0xa6302f7bf94d49d0L,0x94fd2ad33b2abc46L, + 0x98ffc01fe4249c1dL,0x6f3a53bf8db4549fL,0xfbae12df25566cceL }, + { 0x63fc92d3c2e84d15L,0xc355b46c4f5abdebL,0xb50b43a05678d0cfL, + 0xf4d4b0b15681d628L,0xc9f11d63fb3bac7dL,0x444b748cda461eb1L } }, + /* 50 << 56 */ + { { 0xafe9adafc9845a07L,0x484a9eb9df6a1305L,0xec32f0bdb0f111dbL, + 0x742b41cddc7b100cL,0x5a7ea89d23c5f849L,0x1ea8801fa298aa82L }, + { 0x183e1750cb001f26L,0x66ec5daa49da5bbbL,0x8071ff322d05ab57L, + 0xaea9e694e1944e0eL,0xc993754437b85438L,0x2c2467b4faaf4f22L } }, + /* 51 << 56 */ + { { 0x38f87acce602c278L,0x72c79590515854dfL,0x9d466a765e7e2f6dL, + 0xe5f6704772081935L,0xb4b56288ad958812L,0x7f4d9e1395b08242L }, + { 0xb38d0ddb962f0f6bL,0x969d4327e5f76463L,0xf7c7c799f6ac01f8L, + 0x494066673e6ff230L,0xa81fa10dc7e9c1b6L,0x2fcf26bf8093c2d3L } }, + /* 52 << 56 */ + { { 0xcca6e9cfa754256bL,0xfdd79280347723f7L,0x8179d6f52d69c6bdL, + 0x156a53fa94cc8567L,0xb819d70324655f28L,0xf86872e2ebfb198bL }, + { 0xb158e73939ccd668L,0x655db8248de67826L,0x54399a79c621cf3aL, + 0xc55900d498a09c9dL,0x5423edbf20278b3aL,0x06a625b280ba89cbL } }, + /* 53 << 56 */ + { { 0x0f152d69869c4f68L,0x0ed4205a9f0068fcL,0xda68af4f25d4490eL, + 0x715fcc60745c00afL,0x70ab559aad63dff1L,0x7d0a7b6a9b8a37ebL }, + { 0x82ab7a068bca8498L,0x4f012fb4297d954aL,0x8b139e6ed5f6a4b7L, + 0x597316e4b856ac26L,0xeb64b5894387367aL,0xcc92eeabbacb7e74L } }, + /* 54 << 56 */ + { { 0xb53560e968fdcf87L,0x4ed638bd3cbd0887L,0x57f3f38f6080d1cdL, + 0x50370e0c1e4e3ae8L,0x14c87fad184a1ecfL,0x3d06f78d0af7b2ceL }, + { 0xd9370e24fd595621L,0x1e462483c9fbb559L,0x1ee5d81ca0aa5c0aL, + 0xdb2524557419564dL,0x782ba91b57585be7L,0xb2d14bcc5c431c72L } }, + /* 55 << 56 */ + { { 0x9cb9de6fd62ebed6L,0xb7f23b1916c6d571L,0x69b4a8dfa8b307b5L, + 0x78a7f74e19dc7e39L,0x423405152f47c94bL,0xf1c2a5bc31ff2d82L }, + { 0x98c1c3f7b145387eL,0xdd9d24d885e635ccL,0xeaaececa07397bc4L, + 0x6bf6a8469b0cd4c6L,0x68052950680dbd05L,0x81a071b60ce07df9L } }, + /* 56 << 56 */ + { { 0xf3fa8bec0c61d5a5L,0x98f772fc0dedaa77L,0x45a382161146d42bL, + 0xebef5d4a58821ebdL,0x21498af30c1f0e6aL,0x3d8699144758014aL }, + { 0x6f2276ecb625c7e0L,0x68d6a144fb55d708L,0x0bc836e0ad56b494L, + 0x72b6d8850f58ef70L,0x0e0be2887bd7c1d1L,0x70549a879c277d39L } }, + /* 57 << 56 */ + { { 0x39a445d2dbb2bb75L,0xda2a211b1ac42cd1L,0x934bee9a8e4cf8f9L, + 0x5d0dde6a24801bc1L,0xb2d4261d23da4ea7L,0x5fa9059a7187cde8L }, + { 0x49298bb651f05f9aL,0xff0c4a0422a7bee4L,0xf466232da6a29be3L, + 0xff2e157a995c1904L,0x3a4ee4537b31bdffL,0xb4a736d7e41f6eeaL } }, + /* 58 << 56 */ + { { 0xaed55c123fa96c0eL,0x8f90803f6e08adf2L,0x349e5807015b7cb4L, + 0xdb3f05e314656b3cL,0x9289bbecde8b2d9aL,0x3cad12e0c7f28356L }, + { 0x7a68fa54959fe89aL,0x2e7135d0a77f956fL,0xa0285cbabbe35884L, + 0xc547ffe7131ab269L,0x82a902bebe33b425L,0x5a793a790c71b02aL } }, + /* 59 << 56 */ + { { 0x2bb2a929c645c6eeL,0xfc6cbd471e651728L,0x4ec3f630c07af98fL, + 0x118231588e4a8ad5L,0x99a2b5de1303f68aL,0xcc280b182ec9b8f7L }, + { 0x3d7b406ad7298d55L,0x63941bceb9f83957L,0xfeeb132c463a64c6L, + 0x243a2e2bf76a6c8bL,0xae72bf2fdad18d64L,0x774423431987a4caL } }, + /* 60 << 56 */ + { { 0x06de549d78dc1526L,0xa27fc0c1f52c5766L,0xee5ff3d8e9485b1eL, + 0x7af2fbc64bc530dbL,0xa266d6c810f9dc58L,0x866abeed8bfa4d74L }, + { 0x50356d7fcb7c7018L,0x4ae502e07c962af2L,0xb98b449cf011990cL, + 0xfcc8446b59e8535fL,0x25964ab0088776ebL,0x3848aba2ab6cfe8eL } }, + /* 61 << 56 */ + { { 0x9f2c62cbe14a2c5dL,0xcd182e386b113f03L,0x2275ad4f525a15aaL, + 0xd5b7d1d9eb373133L,0xd3c47b9b07929822L,0x60b043cd8fa8e8e0L }, + { 0x603a3403d3958f57L,0xefa36ad67b79c263L,0xfe33dd9f3742ac39L, + 0x30f40b3bb249f9bbL,0x9d2902d20a3b2e7fL,0x173f7d1a899684f0L } }, + /* 62 << 56 */ + { { 0xdcbeff5bf33bdff0L,0x963ae65ee9684a3bL,0xe03586882bcd272bL, + 0x756695068942f107L,0x14319d19262e422fL,0x5c0ef45a2265b294L }, + { 0xeb897bd8a9f64203L,0xa3b259d742b1640bL,0xdc34ee2dce66355cL, + 0x2fab125eb4e13438L,0x1b93a820443420b7L,0x79c46f97b4ba8382L } }, + /* 63 << 56 */ + { { 0xafd8cb2006e55b9cL,0xc88f38ea2530a11aL,0x628d10bfe4efe221L, + 0x00df0da42a8d983fL,0xed45860508a2fce0L,0xcd7882b86a01efecL }, + { 0x93ebd86c7efcbf7bL,0x578f9fe7e3db504aL,0x3c584008aa5e83e8L, + 0x5bf38b4ca8368754L,0xcb4a9cf905c05ca7L,0xf77ab684c634f28fL } }, + /* 64 << 56 */ + { { 0xac92ee1537d83369L,0xc968c187fecec65cL,0x29a7ca876e7a3265L, + 0x0f2b7e7a8456c9afL,0x7471824e9754326fL,0x498687bf364d2ec8L }, + { 0x86d8aacd3c6ee351L,0x01ee6823f6f41e85L,0x9805fc881d79f7ebL, + 0x377ac3a40040547dL,0xd39215d461b4e90bL,0x2547416e4c5fd81bL } }, + /* 0 << 63 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 63 */ + { { 0xa10292b907a6fbf8L,0x292c1a203fa6235bL,0x7a36f18f73ad7a1fL, + 0x8b2c7b0c5897b11fL,0xf7b9a272cb664c61L,0xb6d366af8f81e22cL }, + { 0x3b99b2118e342bbaL,0x03ce158bb06ced2bL,0x3af1175d001db74bL, + 0x526f08467159cb8aL,0x6a3c6e1febde4601L,0xfad5963b8c232eacL } }, + /* 2 << 63 */ + { { 0xa54768dab1b43eefL,0x13e41f47e14fda22L,0x774df203faef6863L, + 0xf795a034bd7471b3L,0xf0958718b47de2e9L,0xc92f7888e1160cffL }, + { 0x86ded97b0146c790L,0x015918f5480a4b7bL,0x05588920424e8459L, + 0x37455914eecf8b2bL,0xe7d3df1fb968a6faL,0x07a0ffd6bad0719fL } }, + /* 3 << 63 */ + { { 0xf13f55e619f6ebccL,0x63720df2a266b368L,0xdbcc937f3bf1a890L, + 0xd3faff625f326fa4L,0x8b33bae9019730d0L,0x7879782af9961795L }, + { 0xec7e75bc93735e44L,0xfbbf6d225d5702d0L,0x26b6e1d53bc2ddc5L, + 0x00345bf714941d10L,0xdd719676a745c77cL,0x2869b11881c523dbL } }, + /* 4 << 63 */ + { { 0x2566021f98d23f6fL,0xfb883e1234ca97caL,0x34e047a5d9f51b69L, + 0x0b50d91df8efa646L,0xc2bbcbb2971f584fL,0x4136f0e40907c91cL }, + { 0xa7ebeb0de735cc48L,0xa7d1bedce113c8faL,0xc04d9a073f5c962aL, + 0x95c155e53ff74a2fL,0x923c65a53df0749dL,0x10d5f81227ae35d0L } }, + /* 5 << 63 */ + { { 0xc08cf7a1a128747dL,0xeb34a1c02eca6776L,0xff6e7cdfb596491aL, + 0x17024305eddd8bbcL,0xab92b54cf3c46414L,0x2a995b7759134eb8L }, + { 0x97525904e48cb259L,0xeac065ed1e1da01aL,0x16cab74a14c5bf38L, + 0xcd3e2516c14eda8fL,0x3ff38094a8de7a9eL,0xb7340214359d653eL } }, + /* 6 << 63 */ + { { 0x4d37c2663e7a369aL,0x092dc32c3ae62c55L,0x566da2e928ca9d67L, + 0xa9771c1a79beb236L,0xaf6b97a976f801e7L,0x3afd62e771259358L }, + { 0xc23a5e32cd541e77L,0xae4c90a301660ff9L,0x3f3a233b1911ccf2L, + 0x93e4664cfa3b3aceL,0x4bdc14832d4c5f5cL,0xfe03d3c36abf13c0L } }, + /* 7 << 63 */ + { { 0x9649468631b26990L,0x55222e9fe3fd62f4L,0xc8eaba742ee74b8eL, + 0xfa43617834d198efL,0x475b688e892748f5L,0xc6eb426541b9822dL }, + { 0x535695bebdae951fL,0x45e69033e909cce4L,0x40354e72b1829154L, + 0x1005ee6d5c56c3cfL,0x61b36a754a3fec51L,0xae644f3872f2f56eL } }, + /* 8 << 63 */ + { { 0xd5469c7becee6e87L,0x056180bc33a4c917L,0xf881ca21a16caa7aL, + 0x221de182e6cc7f39L,0x10d61ab531378723L,0xfb763bd9520c9660L }, + { 0x145214cd0d6b1541L,0xd9f7ff2dd70223e7L,0x9fce59e30cb1fe69L, + 0x2e6e77fa3e299fe7L,0x3a0cf652d5af78cfL,0x50cc42c53e852159L } }, + /* 9 << 63 */ + { { 0xd2536452b8da85a2L,0x5c15dabe331197daL,0xf5a89366aecccec9L, + 0x8f998baf2d8352fdL,0xb10e6c80f56159d2L,0xf61ceff379eb9affL }, + { 0x05bcb93d1c4283a2L,0x4e1abc521d8cd941L,0x898c9a49b46b343dL, + 0xcf352f3c6e423ae6L,0xb1db207f6fd42c89L,0x08f36a1edab295b4L } }, + /* 10 << 63 */ + { { 0xebbe18b7ed31fabaL,0x046e248dd74971d3L,0x3ddf5a2a0b24f97bL, + 0xf9a400c262fc6124L,0x9ad9b0bc6b03b73aL,0x9fa97c56153c8fdeL }, + { 0x1b6477da00b73ea7L,0xec59f64a21b2f3f3L,0x4428712895306955L, + 0x4b5db01db9e77579L,0x237edf0bde05e0d1L,0xac904b01855332f5L } }, + /* 11 << 63 */ + { { 0x6a37fc505cf708c5L,0x8de4dd7c30497ceaL,0x6978648161b8bf39L, + 0x3cb303375d7362eeL,0x0e24d09237ed25e6L,0xd474f3dc2f69ce20L }, + { 0xe15d98a0edb40541L,0x5e4a87c91466f464L,0xc3cefc9eb68923cbL, + 0x66f10920f22c9de2L,0x3c18f9ea9a51b3f2L,0x706237bef40e6204L } }, + /* 12 << 63 */ + { { 0x0791dfa1df764716L,0x31bf68768c66da07L,0x49f25b77ccedf4f3L, + 0x05170ccd5d965c05L,0x37d9521bd49e6727L,0x1548251286a00176L }, + { 0xdab444936c00eb48L,0x102c6b95e00c5c5dL,0x43660c3e4c2506baL, + 0xb2fb26165ec6f132L,0xccc4221a99ac7691L,0x05b29758a576deb5L } }, + /* 13 << 63 */ + { { 0xee84fe05a5731e27L,0x3251ded005713149L,0xbfeeaf3c7c5e7260L, + 0x3db0b6b2f048907aL,0x38728debb4a6b923L,0x853997d9d1142e10L }, + { 0xc636e3874b641cd1L,0x69b10f43c629f4f7L,0x6f10a95c7deddd0fL, + 0x85b5a7a317f56374L,0x28cd59435c329333L,0xb37621f7d1e476a1L } }, + /* 14 << 63 */ + { { 0x3a17f86d48341ba2L,0x558ef6e8ba6375bcL,0xa86ea3f0927935e2L, + 0x2f43742ac04d4fb0L,0x32a30bce38769421L,0x5a6d6a62d8d3912fL }, + { 0x34154b19c20e3fd9L,0xe95d3843fc85f907L,0x26cfbe0f9f7a13c0L, + 0x50d50b3a531736e5L,0x81849773b2cfa2c2L,0xc81523e63ba8ae5fL } }, + /* 15 << 63 */ + { { 0xac9b0573c2f899caL,0xd9c4fc1ff747ef78L,0xbc205571c7714e62L, + 0x726bbf311919f8c8L,0xfff68adaaedc0450L,0x9f4bc0b9f4001089L }, + { 0x5d10a660fc5dcfeeL,0x1ea644fbaa9f25adL,0x4f5cf102e5a144d4L, + 0x4275b6021521f249L,0x9c62750522d8bcdeL,0x3ebbfc5bb7df57afL } }, + /* 16 << 63 */ + { { 0x4a873076ad8c49b7L,0x891598ce7146575fL,0xc1d3042f427ea198L, + 0xdc592111ed259219L,0x0abdbd16234850caL,0x26b9412643b6fe8dL }, + { 0xd3c79d1736a1cfe9L,0x576386219a2b3bafL,0xa736535d5a98bf65L, + 0xacb3b7ddab2cdb2bL,0x37d3743adaaf89eeL,0xf19d9aba0b348532L } }, + /* 17 << 63 */ + { { 0x013b49753e09dc4bL,0xe548f7bc2d034deaL,0x65ffcd710b861c72L, + 0x80f4d7a2e07dac01L,0xd1889dcf56c1a8b1L,0x14ad62d4789b133bL }, + { 0x082e3c082e80532bL,0x0562a7d80b9d17e2L,0x4f8613095d57e2a7L, + 0x79f21d7255f93514L,0x22c4f68c595c0f33L,0x91d9bd5ba22c0c33L } }, + /* 18 << 63 */ + { { 0x30539655b29eff74L,0x7ba206ebe723167cL,0xe20c3ce488110a02L, + 0x52b406b97c124481L,0x050111c68c74a728L,0x3d594a6bc57cd9feL }, + { 0xd4b2a271e5f952d9L,0x7e52d63b080da0c9L,0xa6463d65f53a6cffL, + 0x9ebcffcfcc678e26L,0xa657f27b2f2b9424L,0x850bd2b871da5c9aL } }, + /* 19 << 63 */ + { { 0x9f3c395b7d4e1a14L,0x2f99aa23bd7301efL,0x50eee34e3017f166L, + 0x88c951ff4c9cbb4dL,0x90c0422ad8dda2f4L,0xe8361775d49cae19L }, + { 0x654db0d250da6138L,0xe4ada30ee03c34a3L,0xde0d3787832ccf4bL, + 0xd1bf435641b94c86L,0x347531c37db87eb5L,0x6942e7e30fb51863L } }, + /* 20 << 63 */ + { { 0xafad01a0d93c54b2L,0x659bff9695536c49L,0x7b91aac2b9734c15L, + 0x55c7f08224e02f59L,0xebcb71e73a26e551L,0x5b7225f76c6343ebL }, + { 0x021c48fb17d5e775L,0x57536a42bd859c87L,0x24852cc0ae2b63e9L, + 0x21515020c0ce0ef1L,0x2ac7336c8fed825eL,0x4bc87feea0152819L } }, + /* 21 << 63 */ + { { 0x7f9813e94b82bbd5L,0xc01f14624e697d08L,0xf02d9eb293de010eL, + 0x290c503c50db5ea8L,0x339341f033edb639L,0x962abf5f7cd7f6c1L }, + { 0xbb1041ae95fb9e8cL,0xb8c9f9d6dbd8525fL,0x8658a54f0f5244b2L, + 0xe9326e455b84eea8L,0x9ebdfe4f54f11de8L,0x3c90b0cedc740440L } }, + /* 22 << 63 */ + { { 0xde6973e22683ad60L,0x35fe4650eebceb58L,0xbcdbbabf7c719a33L, + 0x8bce8111c076ca95L,0x8f7176deeb6bd711L,0xd04e9769d240a56fL }, + { 0xdef7d8fac8e218daL,0x04cff5976df28152L,0x2a1af6e24bd1cca2L, + 0x9397014edcb911e2L,0xa251339038677b96L,0x0dc48a8fb61b462dL } }, + /* 23 << 63 */ + { { 0x42eab6610197a8d2L,0xdc4a557ade082468L,0x4cf68d6090495f66L, + 0x6dba8de79032929eL,0x304b38cc827b5d7bL,0x8e57275cf32f5063L }, + { 0x4b555a0337280c95L,0x49c1e532ef8ddd18L,0xa2d8eed45459adc1L, + 0x2b353217bba3cf41L,0x11f3c90cefe8f005L,0xb3367fa0d55916c4L } }, + /* 24 << 63 */ + { { 0xe7c396d64654712cL,0x1fa5ea507a26e994L,0xaa98768709012b83L, + 0xf1ef9792e9b17e98L,0x2c22bcb06dc2db10L,0xae42ddf6ed4be80eL }, + { 0x672080f62e743405L,0xa15a7f975b7821d1L,0x0cd912f247adbf07L, + 0x6919c0dcb6c4ae8fL,0x62b13edd14c6253cL,0x66f35919f8032287L } }, + /* 25 << 63 */ + { { 0xc992f6fe05f3b31fL,0xcdcf59b56a3d4522L,0x69901b3815df24b8L, + 0x4b9874029f6153b3L,0xeb09cbc1bca86176L,0xbe78cd7d446289c4L }, + { 0xd4aced42b933fd58L,0xe0dc6f306a326de3L,0x4bef32960542a5f8L, + 0x3eb8d14106f537c3L,0xbb45a994b6f0d0a9L,0x340c025d3f4a01b8L } }, + /* 26 << 63 */ + { { 0xdfcb3255fa371ffbL,0x3fb4a22c92bb6b01L,0xd96efc1605396353L, + 0x2ce2228ce5d2bc25L,0x59483843212c7eecL,0xdca7173882996047L }, + { 0x44dad56d8de87b1dL,0x622f88910b6222d5L,0x1abbc501d5d3a9ccL, + 0xdbed73a5ebe52e80L,0xa7f785b1c98c56efL,0xa32471d3d343aeacL } }, + /* 27 << 63 */ + { { 0x65d39f8ae510cee9L,0xcc60cd118dc5e825L,0x3b6ac6627ed7198aL, + 0x5d7fc001f33edc87L,0x0218ffc453e978eaL,0xecb762e57bdfcf16L }, + { 0x8e7122047966b202L,0x1c502404e6b99602L,0x0acb73f1131cc36dL, + 0x81d1132ed4369a1eL,0xbca89fe8377271a4L,0x1353a883262a2e18L } }, + /* 28 << 63 */ + { { 0x2713b58c9d628e1dL,0x3729960afaa8ba1eL,0xc3438130ab53bc93L, + 0xcef9eda5e9c165e7L,0x9bacd1c3fd02650bL,0xbb300334540ece72L }, + { 0x21f5a5d3d9c4f0edL,0x1ba32e4ff7c19269L,0x8f073beb2cf320fbL, + 0xb49766c45599646fL,0x68180d6649e4f200L,0x8203d8aeeaeddb36L } }, + /* 29 << 63 */ + { { 0x7b19780fdbbbf57eL,0xc094d6d9c2207635L,0x241898ac6bb652d6L, + 0xb61b25724923ce29L,0x26ecd97508000048L,0xd08c54e5f5f96b8fL }, + { 0x19019968c1604cc5L,0xa9940e9edc3f31b9L,0xbad2d245c3614a9aL, + 0x7d3cdb2d411e63b3L,0x88d842c3223638ffL,0xbc5427d0cfba2b48L } }, + /* 30 << 63 */ + { { 0xe6d78b7f60085b20L,0x0aa1d62bf318d226L,0xaaa4391df6461e64L, + 0xb15ee4a7213c949bL,0x183f043be4bd3dbbL,0xa1a87996ca49f456L }, + { 0x6030ed2ef6ed22bbL,0xa2002784fab7f7a2L,0xfc40914dd850cdbaL, + 0xe63edc4c7df80ba3L,0x8fa35ab57b27ddfbL,0x3bdaec795096ea04L } }, + /* 31 << 63 */ + { { 0xf33cc5ee452881ddL,0x89c144a38966d47fL,0xbfa8395149156a93L, + 0x0069bff358707b05L,0x2caf814cca12a0b5L,0x1ea71ce71794450aL }, + { 0x08fd2b1c63d22a26L,0xdb08594eb3876737L,0xf459049a57b3669bL, + 0xf64ecaeefee0d4ccL,0x9da2177c63f233a4L,0x042fcca84e54f053L } }, + /* 32 << 63 */ + { { 0xa68295da2caf088bL,0x23d6439a5c8709feL,0x8deba0cffe0c3df0L, + 0x5b4d037b3cd00a1aL,0xe9edc429aa0f9088L,0x6f5827e35847def7L }, + { 0x9739d03d306ad966L,0x7c6b18afaed51d04L,0xdc3d34ff1759060aL, + 0x029e9aa9a7e94dbbL,0x2a3cdfa0f7e8b7f3L,0x42f87bf0bbd8f6f4L } }, + /* 33 << 63 */ + { { 0xe36941004ef8cf5dL,0xcb4dbddf4d8bb768L,0x0610858e828c717eL, + 0xb4cf22cb2bf53239L,0x938e49f16a3e7a71L,0x1dbbb837e73c7a10L }, + { 0x26ea3108db1b58d0L,0x1ca340abad2929faL,0x1d4601938ecb1f6aL, + 0x060543510424fd93L,0xdbfc403f0303dc50L,0x142ad48dfc0f4007L } }, + /* 34 << 63 */ + { { 0x8a8258eee6a52970L,0xf2d13a33a3882954L,0xd312768c38d48e32L, + 0x78a70e03e9369eb8L,0x02ba8d2b69228d48L,0x7f957a33b3bfeb28L }, + { 0xafb22cd20ab2d0bfL,0x335304ccf8cd44d9L,0x0587a6f256009a3dL, + 0xc0bc7278023b2530L,0xe85f2ec5f37c6727L,0x045f156003f5a081L } }, + /* 35 << 63 */ + { { 0x6d71a45274ec55c2L,0x0d064bdfed33da75L,0x1aa4d77ab503afc6L, + 0xec08340c5cb136e7L,0xf096fed6ed11d9faL,0xf232d1b82f81e148L }, + { 0x71cc9b78ae9b3374L,0xd80ce28668bcc1baL,0xe8f4bd170274926cL, + 0xa7ac120f100da329L,0x9f071c6352a482f2L,0x76d85a8e842d6ef1L } }, + /* 36 << 63 */ + { { 0x516f138bed210253L,0x5ec2fa324433461aL,0x0dbe2c66cdaf1280L, + 0x086b91e59fbf3318L,0xfb0223ee399a1ca6L,0xd6f86d9b0db5b20fL }, + { 0xec02bca25752d618L,0x952fafcaaf69f3f1L,0xf304cb7533c4d294L, + 0x78085727dac65608L,0x22f302ef840a4466L,0x33fb889dc371c31fL } }, + /* 37 << 63 */ + { { 0x4aa2f1c36abdcdf4L,0x80963f8251da8d8cL,0x5647a356ac008cf0L, + 0x40a78c45fc10452fL,0x2a3b9da1ca2d6a31L,0xa4d177760f0db94fL }, + { 0xcfd600d9939941acL,0x256e44c142c3fd25L,0x85bccd42ab3f9d41L, + 0x83e93e44d018298cL,0x569f54d474a5fb37L,0xad2c613af2ffcf8dL } }, + /* 38 << 63 */ + { { 0xc63e6f7c22d515abL,0x3fabfef42ad30174L,0xf13a0126b1c65411L, + 0xe269e956dce87183L,0x44136834a83e0249L,0x554e731831958850L }, + { 0xd287755696569aeeL,0x5af275e9274bf4dfL,0x7056f958197dbfdfL, + 0x699f5a672169811cL,0xd9a857d92c1c7c3aL,0x62cf7431843bdac1L } }, + /* 39 << 63 */ + { { 0x974fcf5529d0c948L,0x104d7df0693c5379L,0x4f851c397dadfb28L, + 0xcd5bc87c233c02c8L,0xf7fa16e82c8c1c04L,0xed42de484dc18a19L }, + { 0x213db3a5b4366736L,0xf6eb5c9517da3d1dL,0x4d04ef1213b304ecL, + 0xba7bd9afaf74e164L,0x956a5f7bab319f50L,0xe733891ce2a4932dL } }, + /* 40 << 63 */ + { { 0xaa4711f54f890542L,0x862421d9eba822c4L,0x2f667179848280fcL, + 0x4de16d87c201ed75L,0xd20e1399c5e61b5dL,0x3f7114b49ed67ec7L }, + { 0x561fd4979b5a88f9L,0xb202eb86d84db2c1L,0x67d8fb90c8637d3dL, + 0x3d1d78a1032b1853L,0xe07bf775ef1af9acL,0x691e1deea57d6adaL } }, + /* 41 << 63 */ + { { 0xe236e42b2a6045fcL,0x4a6b7be7613f1c5eL,0x14136ccbf57b1aefL, + 0xc3a8a6b9c7b34813L,0x63b0998c5f5cee69L,0x311bfe2c3481a229L }, + { 0x4dd2325ff0aba408L,0x1b8a3f739a2fdff6L,0x4845cde0dbafe0d2L, + 0xd092bb22cd37b02dL,0x35436f9d600fe0efL,0x63c580cb065f379eL } }, + /* 42 << 63 */ + { { 0x38f98360f48948b5L,0x1a1d67a97ae3ad67L,0x79966318ab91b44aL, + 0xb69a75b8dfea0b1eL,0xbb18e5fa05d4d71dL,0x80a14dfe03b1280aL }, + { 0xe549c8f14c17cf7fL,0x91da31098969b5c4L,0x1e3e8f08ccfc1732L, + 0xf1cfb3ad0c85444eL,0x6854b52a628bebbeL,0x8a5e2d85075f04d3L } }, + /* 43 << 63 */ + { { 0xd428f75c5aaa1da4L,0xf192162dd224691bL,0xc30f5ccfd3a50718L, + 0x82e2b585e9e0f738L,0xc7fb4dc15cf3fd23L,0x8a52eb37e4e2b37dL }, + { 0xd5bb892bf1702cd4L,0x64b8ccd056b92a51L,0x98ab053f8988e2e6L, + 0xd56b34022f104643L,0xf09017be073886d7L,0x0283e9eebf6eaea0L } }, + /* 44 << 63 */ + { { 0x834701da3801c65dL,0x5bb35c48955aa27dL,0x0ef0f375db7ad387L, + 0xd25e337f06cd1d53L,0x757a1f9d90cd91deL,0x1604f153d61bbd60L }, + { 0x6a01e8cf8bb95dc4L,0x34b7be6275bbdb13L,0x0a96b3a121e9b029L, + 0x25615c3b2946df44L,0x5eda7d1919d04842L,0x08317975fba84668L } }, + /* 45 << 63 */ + { { 0x4a4dd7bf2bb5fba0L,0x0ebc07f3c84c2304L,0x054f2e448daa5099L, + 0xbf8949da3ec362f1L,0x2e4a677c1d7d73f5L,0x405e3ad24dc70fbeL }, + { 0x2958e956c7e46fb3L,0x34e0d7f1b2522e5dL,0xc44b95e25e371e3dL, + 0x62e348a4d91baea4L,0x8d9e89e24c09e110L,0x8cb886f6b1c1e356L } }, + /* 46 << 63 */ + { { 0x66b16f6033e8683dL,0x3435ab2560b41c5eL,0xd5b89f51d452e049L, + 0x4b5253a73aac0092L,0x01cae436f9d2e2c2L,0x789de14637e8ce97L }, + { 0x8f50541701a1c2e8L,0x8c77dbdd798a8404L,0x5a264906b6e91e68L, + 0x36761ccc3c6aafe2L,0x5809baa37e50f9e7L,0x0b50904e28fac969L } }, + /* 47 << 63 */ + { { 0xb6360372308785eeL,0x0c9913a68cf10e55L,0xe82b0f470e67c99aL, + 0x0bf2d24825399082L,0x7aa3edfca86fe16eL,0xf534ec4e731a4956L }, + { 0xb71d5d4eff26e993L,0x320eb7ac7bd58ef3L,0xe5e4c5f30cafd658L, + 0xeb6b8e0a21a06cedL,0x037d0faf6f76acb1L,0x39c76a6ed6f13f81L } }, + /* 48 << 63 */ + { { 0x12474bd8a55a3a4dL,0xe326aaf19e471af4L,0xf201a9308caadaa6L, + 0x546821f835304341L,0x7fe452c3088353e1L,0x8f1ff628fc82566aL }, + { 0x49526f46d99f8967L,0xb19c80c0a4009690L,0xeccf97591cbc0716L, + 0x2e13ae2caf4cbc8bL,0x12b0df13f32e29adL,0xa2005d6e0b1565f0L } }, + /* 49 << 63 */ + { { 0x9260321bde788968L,0x4aaf1752886ccc74L,0xf94ae636c06b1d9bL, + 0xf0c858854954ae43L,0xaaa735866c42a104L,0xcab59d914e782db7L }, + { 0xfd12f9ee01ff3a1fL,0x35eb6104b546d3c5L,0x97d839e075ca1425L, + 0xa77712f452428003L,0xf5dda4e8bd9f30e2L,0x0c3ab97091d6f540L } }, + /* 50 << 63 */ + { { 0x58734b3ca68716ccL,0xacdcfdd2acfb5719L,0x97074bac7084cf23L, + 0xf8d4f285d0c81b66L,0x5ea926e2ef541e44L,0x65a8e25da2c04e0fL }, + { 0x67e2380f06258485L,0xdc00f2ed9691a57dL,0xd37b23fd6b80274eL, + 0x57f1604f2fe10aecL,0xcc21a4aeffb33ceaL,0xf33a344bf75eaa02L } }, + /* 51 << 63 */ + { { 0x24ca6fc56969f55cL,0x6fe18be29a7a9753L,0x5e9a7ed36af8da90L, + 0xf6c261b7ed493388L,0xbe9ac24beef2b77fL,0x0357ab559f244e49L }, + { 0x5f7953375f1b5b9bL,0x27dfdecaa9bc503dL,0x0b2091b55c0e3ee9L, + 0x1f4f7866d68cb87fL,0x336c2c127a442a9cL,0x88267fd1d3f2ab78L } }, + /* 52 << 63 */ + { { 0xdb891eedd06014e0L,0x69685d6103e9970aL,0x3a612db402838113L, + 0xc1cd7b3adcdef0b0L,0x612b299da41d6c1eL,0x982161ed0ed386a0L }, + { 0xb36bbe2f3ea1bf1eL,0x0d8c3752ceb2a5ecL,0xc02cd7f6ec03bdddL, + 0xa87977c152631d9eL,0x7b546cc37e398d7eL,0x5b1218a804845671L } }, + /* 53 << 63 */ + { { 0x52cd86c68a62f0a0L,0xc437c2af4d29c896L,0x722a337a45aebfe3L, + 0x03b13844d8a9de8bL,0x41a005bb8510aae9L,0xf42399ffc63af92cL }, + { 0x004d29cfcd93390eL,0x472de98741dcfa34L,0x2c71ae744e7cdcc4L, + 0x11a5c2f8409816ccL,0x320ca246a96cef60L,0x72de4287f3d57621L } }, + /* 54 << 63 */ + { { 0xe3e7a3eb3771a0aeL,0x781156e9b6dd5304L,0xbaee3a8323e31e6aL, + 0x66d1569a08985bf0L,0x56161e202d75cba3L,0xf9c23c102a944de4L }, + { 0x27ac8f454e129ea5L,0x8b991ba788050aaaL,0x600c96ffa5d052f6L, + 0x0fbe944df244984bL,0x3801026fa204c36aL,0xc4bfa1994d55a584L } }, + /* 55 << 63 */ + { { 0x11b200c6a32f5c81L,0xc4ab4cf43eabe341L,0xa21468f06f339f5aL, + 0xf20c2c5a729438aeL,0x3e68031e3a067c3dL,0x3962a92f062c8371L }, + { 0x389b22835b000f3dL,0x98f3b679250b8666L,0xe283c2b4eea91464L, + 0xd35b14de1e1f4c08L,0x9ae72567d79d8683L,0x2c37b162a3b2a840L } }, + /* 56 << 63 */ + { { 0xfa3e43e56cb173d1L,0x2502258d4591b5a5L,0xae8c4b558ca9682aL, + 0x8cb1ffb4ec81a288L,0xd11ae888bfc84fd1L,0xa3b083a0d774577cL }, + { 0x119b41c11da9afc5L,0x44bc77622934e22bL,0xa04694f37c639d6cL, + 0xd5e1ce5732c5b8eaL,0xd507c39b9749e8b6L,0x16cc0b5755255b63L } }, + /* 57 << 63 */ + { { 0x66fe7a39c4955e7aL,0x25b0b3e5bb11a1baL,0xb82c2cdefc573bf3L, + 0xed33c0e8281a3927L,0xd068c8901ad799d4L,0x052801ec9cbc73edL }, + { 0x614e4aba0faf5c5dL,0x50d7b0a89f66d391L,0x7bdfbf5fc18e88a8L, + 0x1fc93e1f4380d2a2L,0x8241dd5f27d952d0L,0x44944d9c3a3f79d5L } }, + /* 58 << 63 */ + { { 0x808e2693c0edcf36L,0x4725b5aa87c254c0L,0xd1e464644d317973L, + 0x3e59efc2393049d2L,0xa4c9f340d3e0d17dL,0x69b40727abdf3022L }, + { 0xa1d85395317058c8L,0x2cec2a040cfa7c13L,0xe3c16f7634236cd1L, + 0x566b403a3e52fe3eL,0xfd6065bdd6923cb6L,0xe769a89a5019f94eL } }, + /* 59 << 63 */ + { { 0x9b1f6e9042a1cce9L,0xc6c870270511f865L,0xc924caa72a3c29f6L, + 0xcb674fb068e604f8L,0xe997b0b8330c2dedL,0xf5b315a04ddab219L }, + { 0x6fa1dde6575d3ac3L,0x32ad27f735e65e56L,0xfe723ec2e81b1ce4L, + 0x149983f8985d7286L,0xa1d350a0492ecc9aL,0x12a51f8c36a0707aL } }, + /* 60 << 63 */ + { { 0x71e5df78614f6f37L,0x5cf0e08da0b80beeL,0x1f8dae171e32051fL, + 0x54ae365d83bc233bL,0x97ea005b1b84aaa6L,0xf4766d9264c75139L }, + { 0x9b93bbf241215701L,0xb18f042d8cf8a865L,0x5dfb96dd0867556fL, + 0xe9fafbb8597fd6a1L,0x729b2f50fe48bbc6L,0x2cf85f6b7f37ff9bL } }, + /* 61 << 63 */ + { { 0x3e7c871024d197f2L,0xb635595bafe9c29cL,0x302f4fff194e084cL, + 0xd497ce7c18edf332L,0x4081c7aa062672a4L,0xe886a5b28afa97daL }, + { 0xa7e922b5786e1bfeL,0xabd9a18bbd7ffb7aL,0x1f4f5b9356341b58L, + 0x1726484344969ab1L,0xc4a0b557e668a479L,0x5ad1c062bf4f3343L } }, + /* 62 << 63 */ + { { 0x4ff86eb693d2b958L,0x4513fe1b784f628bL,0x45f4712573b5bb80L, + 0x25aa3d36c987bb15L,0x12b1e65bb48163f0L,0x9d0cb4aa9801592bL }, + { 0x02c0c2aa3718bc98L,0x79b03df99c306353L,0x097d8d8daee5144cL, + 0xebed60774621d7abL,0xa8edf06e4b52e72cL,0x40c86f181dbca7d2L } }, + /* 63 << 63 */ + { { 0x65c7144a5e84482aL,0xba6f92644d4f7553L,0xf4dfe807d9c2524eL, + 0x1333dd7c054403b1L,0x44557e880156451fL,0x5dbda4d80824c813L }, + { 0x59e204959857fec6L,0x42f4068f1b1eeb99L,0x067c3aa21d59bde9L, + 0xa9c4c3eeef27419aL,0x99fc994b2ec87652L,0x4f1607581578a996L } }, + /* 64 << 63 */ + { { 0xcd8c2ec9378ef62bL,0x7f4a3c5491a7c4b9L,0xe12386d4db83e1abL, + 0x9a792032bb549bb5L,0xaf81cba62807c0f1L,0xd4ad7d87abf2008eL }, + { 0x9d7a72307e9ad6cdL,0xb30636b08b517b2aL,0x47c324daec900516L, + 0x408cd0d37193eb30L,0x8f0bcce2d315c655L,0x540ad4e0869d6c22L } }, + /* 0 << 70 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 70 */ + { { 0x4b5e753ddae0ff8bL,0xe55c83e4da3d97b5L,0x4034d75f42fa905bL, + 0x89b85edac33e462bL,0x31f413c3058de3bbL,0x66c01c806ba75391L }, + { 0x3f500202373e28deL,0x5090b33b4b9be739L,0x7297aa10efa2adddL, + 0x3e8ccdbe1a6566aaL,0x4dfda07fd7b4f214L,0xa659bd1e7cb1cae7L } }, + /* 2 << 70 */ + { { 0x31796c2387d11691L,0x02991ea2a9de506cL,0x4ff0cb716cb0c301L, + 0xdd0cdbd7d1702ca9L,0x470a26c8e1a02a90L,0xb705b7bad7054625L }, + { 0xfadc2e86d4a1a268L,0x0fd9764668e9f923L,0x042b5ebb2951a8feL, + 0xe4af9d0364197a76L,0xdd2c6bb3249c1b5dL,0x60af89bdf01932b1L } }, + /* 3 << 70 */ + { { 0x4374145d41afcd64L,0x98b72d6049d21198L,0xc0ff394bdfde8a41L, + 0xed1112e5ee1ff7a5L,0x87a920e8cb5036fcL,0x437123f62deb225eL }, + { 0x37e527afb9ad8c58L,0x3e3c9998abfaef38L,0xb656bcc550b2b4e2L, + 0xfacc8a193bf5699dL,0x98cec74fe616307aL,0x34af333dd3ef8babL } }, + /* 4 << 70 */ + { { 0x9ded9b0d744ec273L,0x5bdfe5472e79e4d5L,0x94f3aaf539393728L, + 0x22136862a438413eL,0x449286da373c7de3L,0xa709d85d29aa1540L }, + { 0x1bd13e410284a4f6L,0x37b54d69f0799c8bL,0xd43b558f6bcd0cb2L, + 0xf5757c0e9e610369L,0x15c80b23c16e0651L,0xacb2cf64001820aaL } }, + /* 5 << 70 */ + { { 0x0629e4ddeec37f48L,0x3f7556a2da7de716L,0xcacd8f27661662bcL, + 0x65d8bc2ceaf01690L,0x83ac66477c39c893L,0x353f60dbf59440e1L }, + { 0x2597b0d6852c575aL,0x410885f73a40c2b3L,0x953ab3472fcc2488L, + 0x9f753e5eef4cc6d8L,0xfc32bb4d97f69e63L,0x461c1b0c87e8c264L } }, + /* 6 << 70 */ + { { 0x2bea7e75ac4b62f5L,0xcf255dcdc6297871L,0xdd88db8781b25c72L, + 0x77ad90b3b617dc04L,0x65ee13820ed4a7d6L,0x4c08df9cd9644c8fL }, + { 0x072d3784525a023fL,0x1aef69cefce399fbL,0xb07fd78ed7f29044L, + 0xa3754e1443043fa7L,0x97bdae92ff9fe4d9L,0xad63ba6a700fe6b8L } }, + /* 7 << 70 */ + { { 0xa571929ba1ca17dbL,0xce7a12f545e146b8L,0x39df1446d9eb426dL, + 0x1e48b3f8dc27f268L,0xa2d7dfa1ff548455L,0x750068b86ef1cc82L }, + { 0x4d699306667fce62L,0x98540b9d131c5412L,0xf8a62cd347c580b0L, + 0x2b55460f73795005L,0x3206c0257b8db337L,0x2280934bd0dda5a2L } }, + /* 8 << 70 */ + { { 0x10a8aabd2352478cL,0x599d9dfa1364c40fL,0xa009df1a076945a2L, + 0xf869152c03861f02L,0xc405226e9f866a3cL,0x93bd737d8b41ecbbL }, + { 0xb5c9ed1033901eedL,0x90e4ce8f99312b80L,0x1a9ef22e57589279L, + 0x83ef607d7fe2d6aaL,0xf2da84543473dbfaL,0x14f36d3a57879066L } }, + /* 9 << 70 */ + { { 0x2c780f220ea3ce34L,0x240a211e4b8aac72L,0x7a266e5dc2625a99L, + 0x1cb15d3e3b30c878L,0x8cd8ccab0e1b21d3L,0x53c64279adc1a6b3L }, + { 0xe60d15b960bf708dL,0x6e431c1b0cb5ad4bL,0xec874c3e82033111L, + 0x88054a1d9141eae5L,0x98438a5addf53a28L,0x168f0b0ffa12c657L } }, + /* 10 << 70 */ + { { 0xd621ce26629d7a57L,0xbf571de7cc1f8af1L,0x2c5cfaf9304adaa3L, + 0x950addbd3f283b49L,0x622dc27cee6d1cd1L,0x26d920041f0863fbL }, + { 0xe243b2a2a41ec585L,0x0dbd9adf2bea6235L,0xcb083c4d6f0820f5L, + 0x809ecbafd5493931L,0x9647067414b7ffa8L,0x2cdfe22e53fc2224L } }, + /* 11 << 70 */ + { { 0xc8b1333c7cd74a06L,0x7d5ac4dc271006bfL,0xe9377d9fc14e0e56L, + 0xaa8651db7a92ab1fL,0x77cee8145fc11fb5L,0x1e7c5ca027870b14L }, + { 0xdeef4b3f6f959698L,0x7c59f26e5daa9bdaL,0x4d0d5aecfd312368L, + 0x5247a6f3b738de68L,0x1c4e8ba990c04807L,0x0554b41bcce126caL } }, + /* 12 << 70 */ + { { 0x3df98ea9a81cc26aL,0x982ed56883b2c6f3L,0xc9cbd1b5ea6d6976L, + 0x3f9f23197e25ffbcL,0xbca8e0567da6280eL,0x7abd316635cda713L }, + { 0x46ef321d740ae011L,0xb17f6c75db214a33L,0x37b73b4b51de4044L, + 0x5bccf3ccccd9ba8dL,0xa2ca080dd0f7045bL,0x79caf90668cf4dccL } }, + /* 13 << 70 */ + { { 0xcc3605a9a7b07d22L,0x4370eb18b4ebe4e7L,0xbe393039248867c1L, + 0xc8e4851ecb1a75ffL,0x215f3fbe39cb6da4L,0x6f2102eee41f9a34L }, + { 0x61d484abdfae7c27L,0xf5143bd26f1260fcL,0xa70b6c067514bcccL, + 0xe71ca833d23506f5L,0xe2f50ba8eae03a8eL,0x2ac3b50883c33359L } }, + /* 14 << 70 */ + { { 0xe94b930f3655cabdL,0x6ef6aac4a342443cL,0x2feb8005bae255daL, + 0x4625a15cac6e2095L,0x75c6311d0ec76c1eL,0x896a07409b81c6f2L }, + { 0xbad3e2f9073378bbL,0x2984a10629266ec0L,0xa68a5351a788010aL, + 0x321aa113017cd052L,0xecfb61752f34db5cL,0xfe080cedca2b51dfL } }, + /* 15 << 70 */ + { { 0xba29690803360c88L,0x3fb087c036311812L,0xec5fb10ad9ff6a48L, + 0x52f7077f207dd8e1L,0x8e65cfb844c02fbcL,0x4f4fcde2fbf4bfd5L }, + { 0xd1ff54156cc74320L,0xf989d544f68b036aL,0xafedc2db973bd9beL, + 0x7bdc35694785e26aL,0x0df36796751ae9baL,0xfebde691ccdabd95L } }, + /* 16 << 70 */ + { { 0x3499b44bc77488ccL,0xde000e01aa8f3c10L,0x30140406c1f517d7L, + 0xd4b3c8eb82a174e8L,0xc8835b13af2c9b3aL,0x2cd7626e443716f4L }, + { 0x336c4f4b9c22de71L,0x9dd2b277f2529f60L,0x6ffba2dc828c34d3L, + 0x257a345c34d0d1f7L,0xbc1eff056ca4fbceL,0x05b335620768349fL } }, + /* 17 << 70 */ + { { 0xb142febb692e076aL,0x10cfaa6b9a654721L,0x5b7ba30c8d4917c1L, + 0x44be3089dfe4056bL,0xb7530ae6ae6307f4L,0x47c519c45b5f381fL }, + { 0xa80648d8c3078009L,0xfde72e30dcb021b4L,0x8a89a51bdc2659e8L, + 0xb9e0efa6306adefcL,0xc671c060c754a7bfL,0x703c698e18f14248L } }, + /* 18 << 70 */ + { { 0x25c86ad43c47783aL,0xb1f94a9650f85a4dL,0xb9472e3ac023a02fL, + 0x91033d1b26f0fcdfL,0x95d775c1ab7b4ee3L,0xbe17daffdf3a5cb7L }, + { 0xaeaecd2ce78395f6L,0x0e3abb0953b5da8cL,0x5f729f858ee774afL, + 0x1acccfb3aeca7a6eL,0xd066fccb37e4af11L,0x24c832ab84fc3259L } }, + /* 19 << 70 */ + { { 0xca547b680ca4864eL,0xea40fe17c7d49f27L,0xb5e68bab87227475L, + 0x6ba2bfaf8ce485f7L,0x4d2747acb72684f4L,0x5fabffc670aa6087L }, + { 0x2d4ded5679c67c9dL,0xaf3b4eedc8a4f22fL,0xbef6128ebfa6ca86L, + 0x7ce412bbd4381632L,0x518e6ecfe670d99fL,0xaba6518dfa5f426bL } }, + /* 20 << 70 */ + { { 0x5ebdc79cd41b2401L,0xf0cd8598c498e0f1L,0x93f6efe79c8b7f7dL, + 0xb2f1e40ac469aa57L,0x882f0e943433c455L,0x0add72adaea0712aL }, + { 0xb13578c399af96d0L,0x43c28dc621177663L,0x83aca2d854e09133L, + 0xae03943cc6ad8532L,0xce0a61917104f75cL,0x7dec8786f9838c37L } }, + /* 21 << 70 */ + { { 0xb0b41b8ec5abaef9L,0x43f59aee8ff5d1f2L,0xe58f78c9234d3d34L, + 0x0e1948d029a7f49eL,0x722f8e54c6cd8941L,0x75a4ebcfbaf24424L }, + { 0xec8954982d7dc6d9L,0x8df2feee5261e4e2L,0xdf2820b825dfb96eL, + 0x4b89c4dcff651949L,0x27c871a527bacbe1L,0xfdc70cf7329a52bcL } }, + /* 22 << 70 */ + { { 0x37d58766fdb3f3fbL,0x49d9a762ad64fa66L,0xf80423918cfdbbc2L, + 0x22e60ca36400f7eeL,0xfab8ea7568210629L,0x91267753963e5b6fL }, + { 0x5988d7f56b8e7ec9L,0xe43e762a5899e718L,0x842dbdcc40ae8b99L, + 0xa7ced3f19869739fL,0x1ccc1e8a6d54b9f5L,0xaa3a91adbd32e710L } }, + /* 23 << 70 */ + { { 0x306d662c6d4c255fL,0xf32aa48101fa367cL,0x29a71e02f16b3197L, + 0x653f7d88513a6079L,0xde93d6e74541b4adL,0x4d284acd8c54d3b1L }, + { 0xfc9d462be106ed07L,0x6e3818d07e355468L,0x2ad523859400c515L, + 0x287af41d5ecd3b52L,0x1162162351e1fb02L,0xd696d01f17bd4584L } }, + /* 24 << 70 */ + { { 0x9db114e3715aa8daL,0x596c2dc25c2fee22L,0x04df016bd2f3080eL, + 0x0cb3f7cfb9b72037L,0xadb877c7814fe2abL,0xb2d5ec5c37761ec1L }, + { 0xb5d6068e55d45831L,0x5fab1dffb7c52c04L,0x39b4aa5457d36d41L, + 0xec1de467423cc8cbL,0x280e02dafda6566dL,0xc70c3c383ca55f55L } }, + /* 25 << 70 */ + { { 0x27a866e7c6b03391L,0x980b0a42bfa32fc0L,0xd27856910c105df7L, + 0xf3def8c77103a2b3L,0x6c4ff04bdffea913L,0x57b1003e121140ddL }, + { 0xf47bb2826d0e3170L,0xa44d6ab1e6abdfedL,0x67114b8a2a4b69d1L, + 0x7605714d52d7c65cL,0x3734795ef60b81deL,0x277f9816ebf91959L } }, + /* 26 << 70 */ + { { 0xe57c2ed902b3b70bL,0xcec67da99dbc076aL,0xcaf66725b0644881L, + 0xdea4f6608a3a3f96L,0x5215f097609df5ceL,0x6d828267010193e3L }, + { 0x5971ff31a156565bL,0x44f7e4037b64e465L,0x2145ea9ab5486d75L, + 0x47b04066758e7ec5L,0xc181833a9c93cbe9L,0xcac07a9fe8443292L } }, + /* 27 << 70 */ + { { 0xead7cd3d041326e8L,0x721785f26092e605L,0x760864024ba91a6fL, + 0xb7b9b9fa335e8522L,0x6ba9c85387bb3ea9L,0x9c9f1f6f89b2ae0fL }, + { 0x952bb995aae2014dL,0xf8e74d80c538cfa1L,0xb21ca840b55b7e72L, + 0x22565ec4ad982191L,0xf9547aa1f569c537L,0x8d3cb14648596bcaL } }, + /* 28 << 70 */ + { { 0x340d77c2f3b6cbc6L,0xe09ae22c80f4f690L,0x3e915b028b74d32cL, + 0xae7101ca3cc1117eL,0x3c36152b526c5939L,0xdad8aedbd3ec0caaL }, + { 0x34de058e351bde13L,0x2fa75fd4582726d1L,0x27c030efc214ac0eL, + 0x2a216d1cc7100acbL,0x3b730043309097b7L,0x162ada747afd8aafL } }, + /* 29 << 70 */ + { { 0x43893d328c216eacL,0x475a3466349d7334L,0xf9f259866114fbc4L, + 0x96a22d2f0410b54eL,0xc60b69a53f3d951aL,0x152416e7fb400ddeL }, + { 0x3904dd2e8f682dbfL,0x5459272368383eeaL,0x0092554ee8c998faL, + 0xc80f28512c602ce9L,0xab2f8533b197386fL,0x8c302dbc91094b32L } }, + /* 30 << 70 */ + { { 0x853d994eea2026d9L,0x18734b04a1b927d7L,0xd4815747ce88d009L, + 0x0265742f01b856bfL,0x05fd8b1e205d4e15L,0x0f4c8be0f1da4808L }, + { 0x2652b76c456d62abL,0x0d3d1a29cbb8d818L,0xf350487453048509L, + 0xe393ef54e89ae4a5L,0x19ed8f0cc4b1306cL,0xfd72388da1aabd6dL } }, + /* 31 << 70 */ + { { 0x8a7e1494289e6aa7L,0xc69223e65c955385L,0x2bcbad5c087b8c7aL, + 0xc08008a531fed020L,0x9d38f5b2dc117c3bL,0xd84158bee4ad6b36L }, + { 0x2c2583eb92fe5b21L,0xebc847bf557ce949L,0x4c1b54ff4fc0fd57L, + 0xe437eba325ff2f8cL,0x79a4c3cb383caa3dL,0x38a34856e08356edL } }, + /* 32 << 70 */ + { { 0x5d7afe9a10fa53ceL,0xe2415b501ff49021L,0xe39a067dc6523492L, + 0x3458527527557f5dL,0x756b8d86930e9f9dL,0x88df6219040d52d8L }, + { 0x606eb60b5362b045L,0xd179818c9e383cbeL,0xa6215748e068d293L, + 0x73fbdca22fce158dL,0x9cfee07dcb183c8fL,0xc0bf2beba5e03c98L } }, + /* 33 << 70 */ + { { 0x36702d091bf9acc2L,0x1efceaebc9c9dddfL,0x31f9f5599b9afc1aL, + 0x359d4ff33e61a0e4L,0x33b3a707f3772327L,0xd990af318ac1c7ceL }, + { 0x5ee060b7e736ad45L,0x83dbe8b2f653ac2aL,0x30a1e38b407f054bL, + 0x0ec6c70bd9326ac9L,0xeb37ad09d7358ab4L,0xaf36143030551ef3L } }, + /* 34 << 70 */ + { { 0x7b05d8e56edd5c74L,0x268edfac5443acbdL,0x73e0d693ce1ee52cL, + 0x67c67914120a1270L,0x54a897cb6f1c5007L,0xe817914a8d540dbaL }, + { 0x85c1fa1958fc091bL,0x4f4989f4cf2698feL,0xbb2d5091168c08b4L, + 0xa6143388768cdd46L,0x69ec7a265e62ddc5L,0xc08749ae2654f4b2L } }, + /* 35 << 70 */ + { { 0x0a9882b37409bdbeL,0xfad3899cf8b6543eL,0x01c183f9f7e9893fL, + 0xe6438cf708ac9a25L,0xec22dc81aa0f2794L,0x3b641c02aa277a09L }, + { 0x686b1fbd0975c891L,0x4f7e1b680070ce2bL,0xdc343dd7487e3f1dL, + 0x8825d9c230f35abaL,0xda5a77a413b91384L,0xf09d958459e405faL } }, + /* 36 << 70 */ + { { 0x76b242b31cf2ab8eL,0xceb190e697edb12bL,0xd39b41b7089fc439L, + 0x6ee54e750892be51L,0x128fbcfcde414849L,0x4462539007fce5faL }, + { 0x9d12e04513709b9bL,0xc2c49737d95b22a3L,0x0bcd670be4b34d6cL, + 0x78d7b8cd768d7c8aL,0x7cf9382e16a0f402L,0x9b84311d17238fa2L } }, + /* 37 << 70 */ + { { 0x6b7faaf8c19b849bL,0x24aa5d54a5bec317L,0x991aeb14e7c06172L, + 0x52dc7da883e65aebL,0xda8998497696dd56L,0x3844a54e94cea131L }, + { 0xc9fb72ac55f69169L,0xe2f7bfc821893ab6L,0x44220c2edc4057f9L, + 0x9f4f0c3812d5fedeL,0x5725b2b05c913be6L,0xfa08c56c02d8668fL } }, + /* 38 << 70 */ + { { 0x9aff9f0c009b3e1dL,0xed7936d97a3c8c8fL,0x0bc8e46fdefbd340L, + 0x7b508ef231540ba4L,0x9bcd9108005388f2L,0xa25cfa07c089f35dL }, + { 0x9ec7cf81733bccfcL,0xf8a1993a249006d6L,0x1e68981a96d81923L, + 0x27b6199adce834d6L,0x2ddccfcfacffb035L,0xf62d7a534fe0126cL } }, + /* 39 << 70 */ + { { 0xc800c1d5af76895bL,0xc86db45c43f2a94eL,0xf77322fbdbb144cbL, + 0xb2607dc8f7da8df6L,0xaf666055b6cc1047L,0xf1db6416375619d4L }, + { 0xf6103c8c4b0fbd9eL,0xea8e979fb4f5b85aL,0xb0307d41fd16f61eL, + 0x26bf96c58cadf61eL,0xb56c53a3bd348a61L,0xd1a5aa4f8a01388dL } }, + /* 40 << 70 */ + { { 0xa29d231edda802baL,0xde8d0d510ec3c1e2L,0x0ee56eae117033bdL, + 0x4dc9491998bf860cL,0xa08919cd775cd56fL,0x609a30dc1332bfc2L }, + { 0x2c337f181a41db0dL,0x27fb0072c974824bL,0x34292c1bfaf28976L, + 0x242fcd73ef8c4fccL,0x553723b27473c603L,0xb2191ee9a06a0bc1L } }, + /* 41 << 70 */ + { { 0xd10b7b7c10bf3427L,0x16f9ebc505321572L,0x057692f6db5fde44L, + 0xf45d4d268f047704L,0xe3f8784e25584db0L,0x753764cb9f548980L }, + { 0x4239bd4858f5360dL,0x9dc993da98296063L,0x0fbb0c419ffd05b9L, + 0xa6a87d50610c3493L,0x99f5669df10f18abL,0x5a03f02ba4224a18L } }, + /* 42 << 70 */ + { { 0x3c6839e5bf733207L,0xc2f380899c6d106bL,0x43155630e39a7559L, + 0x28d6cb546f2b8d34L,0x19738cdf09183c75L,0xa71ec595dcee5a08L }, + { 0x8e9c1cc3c70db659L,0x1333d7b38beff6a6L,0xb263d91e036a5aa8L, + 0x72728714ee4f858bL,0xd65fcffbb885ceecL,0x08193f585aaaac96L } }, + /* 43 << 70 */ + { { 0x264006e1b53b4c8dL,0xd3748c0bdea2f9ceL,0x019408d34e580011L, + 0x381bcc70b1342807L,0xb904a17191eb1a0aL,0x13ddf3af6151a1cdL }, + { 0x13827129bc228909L,0x3378b4834cdbebd9L,0x25806f7ed56635c1L, + 0xd1a3fb1c54327e55L,0xb2b8895c69d94817L,0x0779752d7150c16cL } }, + /* 44 << 70 */ + { { 0x228437506ce71a1fL,0x39c6fd9abf0956a5L,0xd34a4be8c8d29ce5L, + 0x41dc15356fbf8fb0L,0xdce277034c950de0L,0x1ad7192f90c75c28L }, + { 0x5b3df71e27766767L,0xba85ec629ca80b5fL,0xfadae6e5095938d8L, + 0x5ce3ffc24d286159L,0x60f771fdc7b977e5L,0x7a764991b38c0c70L } }, + /* 45 << 70 */ + { { 0x3e4440b7469f6406L,0xdba02dea247657bcL,0xa551a570a46227e5L, + 0x278bd5a06e58b15cL,0xbbc5f8edc53eb694L,0x50e6bf5b855a2c7cL }, + { 0xa80af271d231f3b9L,0x6c22008bc139b010L,0x04e9a337ba1e27e1L, + 0xcfb75909677a28ccL,0x95c59b55f967af35L,0x70d24fe88d3c6ddbL } }, + /* 46 << 70 */ + { { 0x0117cabbaedcb5a3L,0xb70a95d52e7bc67aL,0xdc2e07d1ad7e7cffL, + 0xf507941825b9a6b4L,0xf953a962bc8b2f61L,0x390a630d181fda94L }, + { 0xc833598d1fbdd233L,0x0213e633ac4763dfL,0xe822febbcabd2713L, + 0x522864e71d2a409eL,0x49d778a81f904f3aL,0x0dd980e15912be0aL } }, + /* 47 << 70 */ + { { 0x97f993f46621ff1cL,0x3bdcc1ea7d30ef87L,0x931c624585386384L, + 0xd17a7b6a8cb593e3L,0x1b25176da0912f55L,0x323cf7ac2faa4d72L }, + { 0xababa6c58683a7f8L,0xa99ebbda4a71606cL,0xb5375f6b0cd8fd0cL, + 0xce43e2e08ae372b7L,0x957af3cb9e69c105L,0x167c4fca772d0c74L } }, + /* 48 << 70 */ + { { 0x0934812574503f05L,0xcd6a64b217bf8ab4L,0x791e72fa1fd4057dL, + 0x033abed8f0697964L,0x1085ac930d58690cL,0x8acd49d69c8874cfL }, + { 0x929e4c39ff1a5286L,0x9704e80ff28395abL,0xfa69fce54c3d9f8dL, + 0xdeb56555fc83a6c4L,0xd375fa037dc04c5eL,0xab2f12f156a58cdcL } }, + /* 49 << 70 */ + { { 0x381d144f8119fa7dL,0xda3aa4a73c6cf64eL,0x3db4cf0a74cc1520L, + 0xe8148941c1cf3514L,0xbc6c7398a22977daL,0x75e26d4982bbdc63L }, + { 0x17a626a4c9594c3cL,0x766fc21a60d71273L,0x547331241c7653a3L, + 0xdbe3a9f1502617a8L,0xe41acd19a33d622dL,0x4d24cbd5e15d69d6L } }, + /* 50 << 70 */ + { { 0xdde0a062dbbb9d08L,0xb5676d14153211e7L,0x747247f6f97b1468L, + 0x93a6de79b2ada501L,0xf9d4e652518ce913L,0xefb0de76702b82fcL }, + { 0x2c54ffd9d68961fbL,0xa6a2d1a384f04f81L,0x88167488d74b91adL, + 0xf20bba56a7d73a78L,0x9af1df5ae1afc672L,0xd79ded4543c26afeL } }, + /* 51 << 70 */ + { { 0x24011535a223c19bL,0x38b55f0a19c719f3L,0x369f86b4d343ce98L, + 0x6516fca318288db7L,0xad32d4699e4aa0a4L,0xb6c80dd50480429cL }, + { 0x890d73f3b659b787L,0x2d1f888be15362aeL,0xd26a84bf7a9d8c3bL, + 0xd79b764460bc6435L,0xecd0272f07b0abadL,0x3ab2390382d7c63cL } }, + /* 52 << 70 */ + { { 0x3ec1874496d87afbL,0xb02425b5aeea74b1L,0x47cfacea954bb89eL, + 0xd8d6ff40cd26918aL,0xf2dbcbb19fd4dea6L,0xc481a4fe370fea30L }, + { 0x60df9f99a334a5a1L,0xeacebd61e6fbc823L,0x21932e6ba0140a5cL, + 0x6504deb051206cceL,0xaa4b43a350560eecL,0xaf965e7b6535123bL } }, + /* 53 << 70 */ + { { 0x25ce17e7be01690fL,0x82bd07fc216f7549L,0x26f98cddac6e021cL, + 0x815367ff3403972eL,0x01b1cf87cd89d71dL,0xe777db14ae24f544L }, + { 0x8081a692f628a076L,0x663adf4498b98423L,0x4a31e0bfbfb25b73L, + 0x5b42f193427be5b2L,0x24b1369118ae7408L,0xf13654a6e9998e84L } }, + /* 54 << 70 */ + { { 0xf8ec0a9e1b64a70aL,0xa1042bbb45fc54dcL,0x3ac4a936b7cbec0bL, + 0x0c2db54708eb7d93L,0x3f16e7c961ae36d2L,0xde25381b4611083aL }, + { 0xc1680ae3cf5edeb7L,0x7c86d74ce2b3398eL,0xa3ec4cde9945710dL, + 0x303d28ce864e3b4fL,0xd5b9730012956ac7L,0x9ad973be3c0763b2L } }, + /* 55 << 70 */ + { { 0x526c03ba1979515aL,0xe6492299cde06e58L,0x2215e3fb93ec91d0L, + 0xa086161bf783b7caL,0x89e39ff44ef0015eL,0x42c6ccc595e90587L }, + { 0x7577d689a81ec775L,0x272e4578daf4d896L,0x6d43c717cf01d7aaL, + 0x583814cffd5253d6L,0xee692f0666f7a3b9L,0x54048fe4e99bc633L } }, + /* 56 << 70 */ + { { 0x2afba531c0b9171aL,0x687dbe4cf2d75c55L,0x7c1c73f7fa17ba3dL, + 0x7886dd45063787eaL,0x14f59a18abd0a109L,0x1819df3c873bb66cL }, + { 0x76c969dfe01183f5L,0x486a120b1a78b6bcL,0xdfd702fac5686aa4L, + 0x2f74157bf3457569L,0x66c8c73e01964800L,0x0a2f6114def25ca0L } }, + /* 57 << 70 */ + { { 0x841838a8227220dfL,0x39eb77e2cd45ff3bL,0x7140aa47f5a060cdL, + 0x9fae5937b55bc3a6L,0x243390ea09b711c4L,0x69db2ace867a3eedL }, + { 0x14ee853a152860b0L,0xe3389c4edae0dae9L,0x4fa55ed1248a496aL, + 0xda6803e00ef304bbL,0xd19f48bcd04c2823L,0xe76b8d82a61773d1L } }, + /* 58 << 70 */ + { { 0x2e3a6332f7ae9a8aL,0x89f1576f78a12a00L,0x9597b2b245ab254dL, + 0x2017d6306309a625L,0x0385c02719adbe9fL,0x26c84f2014606336L }, + { 0x3808a31a3584dd47L,0x0fd2bd1b4e1da791L,0x70c2827fb894be27L, + 0xac97e84547d1faecL,0xa63c56fe9b01c835L,0x19c3b18067ca7507L } }, + /* 59 << 70 */ + { { 0x975dbe423a07930bL,0xf03fc9da8f7975f3L,0x94209a2522662e65L, + 0xf5b20e6b9619dcdbL,0xa95e2188ed5ee020L,0x2301e35abe7fb828L }, + { 0x4216b05b9caa0bceL,0x0534eef625cdec7bL,0x81f5c5f8613aa24bL, + 0x8705662951451a5fL,0xffafb623df15645dL,0xe19276fe79c497c5L } }, + /* 60 << 70 */ + { { 0x461bb6e1d118ef5cL,0x277e378d1f4bf653L,0x3b4138849ccaab1cL, + 0xa5979a3ecea9c61fL,0xdc2a23c09dbfe67dL,0x5f7e32f5335cb2d7L }, + { 0xeefe71a87accbd69L,0x65d961341df58e12L,0x17bafa56538145d8L, + 0x2a723472695df807L,0x132b5320394ec082L,0x96219e617d0ed426L } }, + /* 61 << 70 */ + { { 0xf08ee7071ec12e08L,0xb9a51fc40c4917aaL,0x1aa9b778aa085b77L, + 0x3b3e40d72e62193aL,0x3700217fdc211bb4L,0xed03eaf4fbea2fdcL }, + { 0x82e00364c55111e0L,0x3be15019e3cbc07cL,0xf142d230055b597bL, + 0xf68837b1a063deb9L,0xf1368df622e72e40L,0xfc712c67ab522f37L } }, + /* 62 << 70 */ + { { 0x02ca4c0dc3c8ee2fL,0x1962366a0d75f552L,0x6354ab90a43c43e7L, + 0x9f46429f7668d14eL,0x70ffaa6d0ca59472L,0x231fdb485a95ad7eL }, + { 0x82ae5f0acb2ebd5dL,0x2dc8417ce51b1d3bL,0x5052133a2fb456dfL, + 0xad3b4cf2bad61a16L,0x59f283a48d76344dL,0x5f15465772b18fdcL } }, + /* 63 << 70 */ + { { 0xe0ef0c3cc73a7131L,0x8a4e0cdd43ea81fdL,0xceb5fcb8d6d6ce6eL, + 0x941179893535781dL,0x20f5e952b37d4531L,0x5e77f33364c25699L }, + { 0xb6645e8fa6d3ff57L,0x6dac30cb5b9bfdc0L,0xb29648e73ebb655aL, + 0xe1bf3f4005ebc1d1L,0x1b12288514025fdcL,0xe15fab026c5adaabL } }, + /* 64 << 70 */ + { { 0x86230934f14a99d9L,0x1cf9c66e97c1c092L,0x01e186ba6f595ed3L, + 0xd3291c3de2284a58L,0x03dee2311b9e5e25L,0xf2e9b4ad15cc9f53L }, + { 0x4fba15679770c29dL,0xbf7d673650c4ae2fL,0x86901eb92532d015L, + 0x4396fd784e7455deL,0x2fbcea8fbcf811c9L,0x3981ad15ae952b37L } }, + /* 0 << 77 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 77 */ + { { 0x6bd2c54d4cb89afaL,0xe78c8bfa36527751L,0x27f52654e3eee747L, + 0x56f205839598d907L,0x5f91c2d027cb3712L,0xc501819fa3e33c5bL }, + { 0x248490aa4eded738L,0xde7ac94427789065L,0x20138b3d74f7d38bL, + 0xae791f602fb60214L,0x6b4fb300bd033d4eL,0xc69c25d9bdfd1f17L } }, + /* 2 << 77 */ + { { 0x0c3d2056be21a890L,0x1c1ffbfb8fcfba99L,0x1b68a98b1fbf56caL, + 0x56fd85ff396e31cdL,0xd2ca58444382c03bL,0xc442030a7d3ef917L }, + { 0x4129a731426afafaL,0xacff17ff5eaae9c6L,0x9e854180653f3b23L, + 0xe65a1a149ee066bdL,0x3420084e362ea5feL,0x6fe58801c7911e2eL } }, + /* 3 << 77 */ + { { 0x43f0ae676c4be6a0L,0xabc6a17a504bffebL,0xd5be6c25dbb4492eL, + 0x7efc9ee884bff97fL,0x54fbd9d7062da2e2L,0x1befeb61c6d2ac32L }, + { 0x14cf6dc0cbafef5bL,0x8e640e4771d12192L,0xd0566543d9a16800L, + 0x9cc2ade9beb1e28dL,0xcbfeb45038e65833L,0x3852eaacd0f5acb2L } }, + /* 4 << 77 */ + { { 0x5e930d65c4650b85L,0xbe96b2ae6350da54L,0xcfac4f7efa08bd49L, + 0x277e8456a6e10f64L,0x41be3067407ac162L,0xcfd1d03252a9b68bL }, + { 0x8d8d216a9c337e0bL,0xace044dc4e1b9cf5L,0xad9a4102c60d54c3L, + 0xb09420f028815187L,0x881179c60b3b8e59L,0x872685ed5b09aba1L } }, + /* 5 << 77 */ + { { 0x26d43085ee64924eL,0x5eb54d1c4bd6a77fL,0x69a69ccfd1ca022fL, + 0xaad92723a3342720L,0x51e27b54421d836cL,0x15e83917fc72a1adL }, + { 0x183e75d14ddea73eL,0x73fe3b9fbafcecfeL,0x0197e0925daefd64L, + 0x2fa89f60f85b8249L,0x95411aafd23cd465L,0xb7dbe7485d9a459eL } }, + /* 6 << 77 */ + { { 0xab146c207dfc66eeL,0xa7250dcebb6869efL,0xaeba44439d7ad5f8L, + 0x919f877ec48059f0L,0x780ecd232c6b5c11L,0x586daa8e38625f8dL }, + { 0x46a46c789911c031L,0xf56f74fc65303d34L,0x825bb06d4f384eabL, + 0xd147719ad6aa2bc2L,0x745fd7460750e1acL,0x2ef411494b3ec757L } }, + /* 7 << 77 */ + { { 0xdb24cd1af10ea702L,0xf393de57461f8ebdL,0xf56f414e5cfaefecL, + 0x758c8d854690230cL,0x6740c974433d2594L,0x69d92a620aa6bb20L }, + { 0x17be342e9b0bb191L,0xc1cd309fdbf5c97bL,0x089134df8998140aL, + 0x33809a7e82afcb85L,0x409d2a481db47b21L,0x1d54e86ccdb1bccfL } }, + /* 8 << 77 */ + { { 0x22313dee5852b59bL,0x6f56c8e8b6a0b37fL,0x43d6eeaea76ec380L, + 0xa16551360275ad36L,0xe5c1b65adf095bdaL,0xbd1ffa8d367c44b0L }, + { 0xe2b419c26b48af2bL,0x57bbbd973da194c8L,0xb5fbe51fa2baff05L, + 0xa0594d706269b5d0L,0x0b07b70523e8d667L,0xae1976b563e016e7L } }, + /* 9 << 77 */ + { { 0x47de66da62a200a6L,0x67b0ce0d65186fb7L,0x8e8f0248238d23a2L, + 0x5a44a886c1114a6eL,0x36383e5be8ec166bL,0xd36077d8ca7d2e43L }, + { 0x332f98267c45e8c6L,0xcec2ba1355d968faL,0xdca664a84a56f7abL, + 0x954652467b03621aL,0x471f66259b6e55d4L,0x401a6a5efb0714e4L } }, + /* 10 << 77 */ + { { 0x2fee0c6d6046896eL,0xde64c4e0466a90efL,0xb0c9755a55395f3aL, + 0xdfe2dfd6ae3879d6L,0x979853c2d656c53dL,0x58bb6121757f381fL }, + { 0xdfae5707980db8b8L,0x6d4c7cd7d7752f7fL,0xdfb77382c5dacfccL, + 0xd0fca93104177fbbL,0x9ef6d3e4b67891ffL,0xb599dfcb26024609L } }, + /* 11 << 77 */ + { { 0x79bf86761cc06935L,0x6bbc2d3fd44fe6bdL,0x092678c486f9f728L, + 0x05631aaf54c3fe18L,0x217adbbe95eec92fL,0xdcdbfdfb955bcba3L }, + { 0xf938779c01bafb04L,0x67f599e73ab755e0L,0x793b591fb00c1315L, + 0x7ea2dbae3f2d0909L,0x05436dce46614955L,0x02b988888060d145L } }, + /* 12 << 77 */ + { { 0x795df21ba1ebf7c0L,0xa98f2466681b5da4L,0xea18a2ab413b507dL, + 0x9243326688324aa8L,0x2b91dcc2f74d83edL,0x95054b471f411a13L }, + { 0x50869778e3c621f2L,0xb950f3a9427faf54L,0x8949bf7dae29f080L, + 0x7c16cd020ef3a3c8L,0x7883c719b122cd0aL,0xa2cad71fc03bd749L } }, + /* 13 << 77 */ + { { 0x60c794125b3ad53bL,0x91c62ac783981a98L,0xa6f30f473dcd7196L, + 0x55417e7598b4c589L,0x2ce067cb345b89bbL,0x4787f0db71936e38L }, + { 0x208cb360331d7de3L,0x4b0347aa15022254L,0xc66e58865e8af235L, + 0xdefed4c591a68080L,0x0b8dbd336eeb47a1L,0xb6d44d36f732c8d2L } }, + /* 14 << 77 */ + { { 0xce0b1700d3aa7741L,0x13cc58a90df0cefcL,0xa96149c7da3a1816L, + 0xd387d361561277fbL,0x2294f77cf2c363c6L,0xc8d19d51355a8a93L }, + { 0x926dd80092affccbL,0x70c59253686afd1eL,0xe4826f2370c4d8b5L, + 0x948d43dba2226c34L,0x6ffed99e2a097aaeL,0x80e7a99a2ce18037L } }, + /* 15 << 77 */ + { { 0x070c3f39b7f01551L,0x21b249434512844eL,0x46e33e16e2e2a68cL, + 0xd79daf0ca549dcb0L,0x634fa53966a7b9bfL,0xe856d0a8702990f4L }, + { 0x246e5858e466abdbL,0x3f3ad441edfc851eL,0x9ab3db2c2e397554L, + 0x6c5b1a39b5cabd32L,0x695649b2427c5cefL,0x6179fa0f82ab4f68L } }, + /* 16 << 77 */ + { { 0x022aa09d236b71dcL,0xb1ce6a0ea65a7640L,0x317344c5b38b417aL, + 0x29a74cdb436451ecL,0xd898eb6ca8b1c876L,0xf0134f99b74eeffdL }, + { 0x0d9eab64225d71f7L,0x9679b453ceb3cc2dL,0x37c894ce14dbff2fL, + 0x3704d34927065280L,0x9ee435d8ba29a0cdL,0x675bea1409c11c4fL } }, + /* 17 << 77 */ + { { 0xa8454e2b63263ee1L,0xf4c8a384cc42ffc3L,0xb260754916bf086cL, + 0x610d299cfa46a481L,0x21777897ce41a4d1L,0xdfc04bb321573cdeL }, + { 0xac7d9433ced06177L,0xfdce0356a281b9ceL,0x22abd67970d48fc7L, + 0x1e4ebf7750514178L,0x7f0869ef21a255c8L,0x80ae565c29bf477cL } }, + /* 18 << 77 */ + { { 0x607cfaa1a38a18a2L,0xb29ae9c760bd3f91L,0x4991432d76a4c22dL, + 0x4fe8dcd380e75452L,0x7aeea8150925ed79L,0xa0cc6823b7abca08L }, + { 0x647b164fb0a555dbL,0x60545cd3d6076f3bL,0x7e801133807a2045L, + 0x74b2200743ac7e22L,0xdfb58fd1716d3e5dL,0x369ad09947772c45L } }, + /* 19 << 77 */ + { { 0xb6c5dc0635ba2007L,0x6543c6307921115fL,0xa7e5a662eb6c493cL, + 0x728159f54a0b8d6dL,0x8cb07ef1b943fa72L,0x4a2c5cc923c46a98L }, + { 0xea078b478c26221eL,0x68ef5015ce2be601L,0x3048b5de5239f8d2L, + 0x00a98cd419bbe0e5L,0x0a34161caa94a375L,0x879a9a7aac8a411aL } }, + /* 20 << 77 */ + { { 0x2d968968e3f6217fL,0x60b781ad1fb91fc9L,0x44ce23514a84e6ecL, + 0xe8f5627d00a3d089L,0x45211a094a980480L,0x11029b7263274860L }, + { 0x44601cfcae0477aaL,0xa05a67df269ca043L,0x9dc3938fb758fbd0L, + 0x43d5d89abaa35f8cL,0xa38dfa1f2ab3436aL,0xa29653bc529b7061L } }, + /* 21 << 77 */ + { { 0x6ab2e32b982cd162L,0xdd690ed7794d6da0L,0x8fee0b461862f33eL, + 0xbf9aeee210d244fdL,0xe485aac27dbb57d7L,0x7f7ee4bc0ff23849L }, + { 0xfb3c6255171ba49eL,0x089b9986133e45deL,0xb6c033106d04b924L, + 0x216af9223ea88efcL,0xe646a49b5fd52347L,0xbb495d2ee404b86bL } }, + /* 22 << 77 */ + { { 0xe24934ba07fd5fcfL,0x4840e1a6a1027598L,0x4c2294d245eead89L, + 0x7717bb604fda652dL,0xe809c21878370655L,0x417853499151e578L }, + { 0x8bfe121cede554c7L,0x96037a33952c153cL,0x80458ed86a5b30f0L, + 0xba331cf9ca28472aL,0x31b5f463e6c177aaL,0x68c5dc9183ec14fcL } }, + /* 23 << 77 */ + { { 0x8b78d2bff13dc6a5L,0xacd7e0902285c2a2L,0x6aa7866cb47e9427L, + 0x7c2483474d9fa3f2L,0x2e668396f0661aafL,0xf491cd6d08cacae4L }, + { 0x772a131158f9a617L,0xf372dcd6b2011823L,0x790a5ae54e6bd2a9L, + 0x035ff238fee0c8c9L,0xcbbe828cb0b8c53dL,0x9edba1a40af83ca1L } }, + /* 24 << 77 */ + { { 0x2fde4893fbecaaaeL,0x444346de30332229L,0x157b8a5b09456ed5L, + 0x73606a7925797c6cL,0xa9d0f47c33c14c06L,0x7bc8962cfaf971caL }, + { 0x6e763c5165909dfdL,0x1bbbe41b14a9bf42L,0xd95b7ecbc49e9efcL, + 0x0c317927b38f2b59L,0x97912b53b3c397dbL,0xcb3879aa45c7abc7L } }, + /* 25 << 77 */ + { { 0x62ecc0cc429bdc1fL,0x6a8000add447c01bL,0xc2dd42354f23e5d2L, + 0xe6c1790a01b4a0dcL,0x2497e53c24393079L,0x0a113afeb2a00faaL }, + { 0x96c1bd5011151480L,0xded805425aad86dbL,0x639f24cb76720e92L, + 0xf17703b7d825eb92L,0x10f8924e82d2657eL,0x6edc843c627c5236L } }, + /* 26 << 77 */ + { { 0x472226adf80911c2L,0xfb50c3a5e087a3d8L,0xb194551441848a6fL, + 0x61f4fbba9f17504bL,0x8c59b2c48e33924bL,0xa7641127ac7a8608L }, + { 0x79feb7fc164a2330L,0x9e0fd67253a44e7aL,0x9c5c973081953c30L, + 0x25d6932c3f6342f8L,0x29e8b7664b574a69L,0x02f90a46a5de3639L } }, + /* 27 << 77 */ + { { 0xe2d1e2a3465ab77bL,0x2ca0f6a3cf45823cL,0xa1b12306dbdce9d8L, + 0x820470e7b4b39ca0L,0xe48956c76e847681L,0xc8ed8fc8fbf6970dL }, + { 0x52cb109419ba40aaL,0x08136d091efbaaa2L,0x99dd1ad27d71e1c4L, + 0x10001f97a3a59a3bL,0x79d229e460e4cad9L,0x6d443d8756732312L } }, + /* 28 << 77 */ + { { 0x8d6b28b4d7cfe9f0L,0x6ee5407a4dce4904L,0x7acee5e7ba0b67f6L, + 0xd4cf6bd2abf447aeL,0xc085e8e2e7330268L,0x23edbd5a145689d8L }, + { 0xd2ae9bd21d7b0e7bL,0x3196410ec4fe6ecbL,0x964bef26ec2cd59dL, + 0x09c6d07dd5e0bf03L,0x379f131ea65b646bL,0x0439c37964849830L } }, + /* 29 << 77 */ + { { 0x8afc9a5eae562537L,0xde81bbaab2d4172aL,0xa272c6d53db07247L, + 0x08b903ffd86ec6f8L,0x3373041f835aa84aL,0x02e8ecfdc8f18f48L }, + { 0xed6b2784ccc11e64L,0x03e45e15842a8292L,0xfcfcc54b653b86efL, + 0x9678fe7ed9ea2f91L,0xee5bf4584efceafdL,0x188e49d59fcc4be9L } }, + /* 30 << 77 */ + { { 0xeb0098cf67a224f8L,0x14e486c90991108dL,0x0dad68314b397687L, + 0xf2a4f6cb9d089000L,0x3fcc8803509f7376L,0xdbdf06dddb5d6f8fL }, + { 0x2cbf342806ef3e46L,0x4a4bd5eee432ca41L,0xdcb8bdb70e2d391dL, + 0x941b9a4ec1710ac3L,0x25cea4333d62c34aL,0x9136e5cd881a70b7L } }, + /* 31 << 77 */ + { { 0x9bfdb9b310c3ed1eL,0xc9a225ec0cd146c3L,0x1fec4316573c4414L, + 0xe11a408f2fa8323cL,0x198c760ac3e988bcL,0x3f8a5a1caf0fda3cL }, + { 0x91e89f11f6e78264L,0x3cee0165264eebfdL,0xf9412b049898eaa0L, + 0x3c67991a382e46e3L,0x8d833d7a80acd219L,0x746a696c9d233f20L } }, + /* 32 << 77 */ + { { 0x8b3269a2714a10e8L,0x64cef040a4a2727eL,0xbc5ac714e428865cL, + 0x531dd17ffdaba094L,0x86d2405718d657f2L,0xe807b0d92f99dbbfL }, + { 0xc428a80f6848ef88L,0xb3ef0709d0b73ce5L,0xa752691922a5d255L, + 0xbfe6392318a18586L,0x28a0c772fcf633b3L,0xad22b4ec3f3c5298L } }, + /* 33 << 77 */ + { { 0x8b6a2f1ae6c40f85L,0xf0f44c54f44cf3f0L,0xda635b687b25d4b6L, + 0xee59c00f8cdc9d5dL,0x36509f58cc4876afL,0xe37564484e2c550cL }, + { 0x20f965b565974809L,0x26481694e3fe3a63L,0x6778b20becd272eeL, + 0x9b6bbf39c9072853L,0x4f61f192b0436bdeL,0x98bf7dafd0221263L } }, + /* 34 << 77 */ + { { 0xa06a4b56e0442513L,0x6537e117dd513547L,0x89e38ccd2a654224L, + 0x2fe734bd005ee292L,0x54d6933498cfece0L,0x85de5c9d85a79bf2L }, + { 0x21e072bdcd3da6a9L,0x7a5d707b8c16b8a1L,0x43654d0142d04cd4L, + 0x07d589b94a88c151L,0x5bfe9ea2df726b52L,0x877c46ffcf728e4eL } }, + /* 35 << 77 */ + { { 0xe338f606fa009c33L,0xce596aafa351fe32L,0x8ae0e06123968387L, + 0xcdaaaa9465c98e2dL,0xec6b8a818acb9355L,0xc2c67e7facbee162L }, + { 0x7068df85517df4beL,0xc34a6ecb7c5c076aL,0xf4193aab6250f0baL, + 0xe0cd2f3fa6c9ea47L,0x23a57ccc6488135aL,0x044d73e6c12b842eL } }, + /* 36 << 77 */ + { { 0x9d8a78808078c8bdL,0x6ea07982076d44f1L,0xc58fc94eeb3bfda0L, + 0x0b9e72200dd11b13L,0x8bd58e3aa74a005dL,0x7a30aeda115b7d33L }, + { 0xeb0037e6ef2491ffL,0x0fa2d1a7fb39ecbcL,0xb75aac645ac598f7L, + 0x2c3c103341f61b42L,0x5a330bf01f7eb885L,0x1c96124d33d5e27bL } }, + /* 37 << 77 */ + { { 0x3f157ea1b28d1640L,0xa41c98f2c96806ecL,0xef261c3bb099566bL, + 0x11d88be30aa23f1eL,0x9a721a2c47ed1540L,0x214cb5b0e4431563L }, + { 0x36a95c20250f6b19L,0x6b44f01d30eb0249L,0x141777dc5c67e2beL, + 0x6926b32ebbe7bb63L,0xb72fd3bf756cbae7L,0x226661a279dfb835L } }, + /* 38 << 77 */ + { { 0xc25a44e3300b8f91L,0x08aa9d5691ad1a78L,0x130c561ffdd2a064L, + 0x36f0b4608c05f94eL,0x748166e158a351b3L,0xe408976147d40ed6L }, + { 0xa0ba5e5d1b2e3400L,0x94aea3b6687f6492L,0xf4975167ea262235L, + 0x8014e81143e800d6L,0x635a3c516e5df6dcL,0x71207caf2eb20366L } }, + /* 39 << 77 */ + { { 0xc00364013638e940L,0x24baf83bbb70e3cfL,0xc08a99b865dca079L, + 0xc070152e0d40622bL,0x44880b191697468aL,0xcf95519bfebc1644L }, + { 0x7bdc41d7911a74efL,0xb88180314ad83219L,0x53c523185ad49f95L, + 0x4e59a29f6d112b66L,0xb2707b9c7515de9eL,0x8322492c150c9bdbL } }, + /* 40 << 77 */ + { { 0xcd81bdcf24359b81L,0x6fd326e2db4c321cL,0x4cb0228bf8ebe39cL, + 0x496a9dceb2cdd852L,0x0f115a1ad0e9b3afL,0xaa08bf36d8eeef8aL }, + { 0x5232a51506e5e739L,0x21fae9d58407a551L,0x289d18b08994b4e8L, + 0xb4e346a809097a52L,0xc641510f324621d0L,0xc567fd4a95a41ab8L } }, + /* 41 << 77 */ + { { 0x966f961d46ff607bL,0x7e52ad9bb29278c3L,0x5b9b84b9bc6835b8L, + 0x00e4a35ad834701fL,0x53aa139866b8f484L,0xc397f087de063112L }, + { 0xb811a9a24e81b980L,0x8d9c38ef8d680c4eL,0x0a7e66ef1c8db33aL, + 0x1c7e636bf4e17483L,0x25c0a690ae9acf11L,0x5b0a435985966d63L } }, + /* 42 << 77 */ + { { 0x3d4a4ee0a3bb186fL,0x84de7765082c283bL,0x499bf10a8fc8baddL, + 0x85191faa2db59e7bL,0xc5964c20ccc587a2L,0xfa59313b9cf52cfeL }, + { 0xe614ce878da8cf4eL,0x7d8aa381d60e91b6L,0x054dfc4a0d5c0a8dL, + 0xbcd89aef28a15c79L,0x2af1121efecbc916L,0x6aa49bcb44f30755L } }, + /* 43 << 77 */ + { { 0x7953c7ec7b7dc4cdL,0xb709542edbdd99baL,0x7a2afc3eb30b5c70L, + 0x7669020fcd0cc804L,0xb57c1d949fade8f7L,0x5ae7d78cb2eef81bL }, + { 0xdd5457edca354c1bL,0xa531d85c8f5ac058L,0x5fdca829009e0aabL, + 0x8df732f6f2bced0fL,0x3ee658627faf57d5L,0xf7a265735c2f3bc2L } }, + /* 44 << 77 */ + { { 0xe1ce7f3725a64849L,0x760847744da790f0L,0x4638f287cf5f319fL, + 0xe36f3c5308c3786fL,0x07042ce1985513cbL,0xfb955cbf73d9cf3aL }, + { 0x3e68a2cacde0774bL,0x321f49b76dc2c816L,0x9bfed81fd76c4d3bL, + 0x985b34fefd49fa62L,0x2a3de945ebb8fa9fL,0xcaa616f0405da5afL } }, + /* 45 << 77 */ + { { 0xf3fa1924bc6d86f1L,0xbcf9d3cbb41dde67L,0xf96431168057ef19L, + 0x09315fc52177ef64L,0x1ae99958fcf594a7L,0x7c4baeefaa4dd788L }, + { 0xff1ed168a2bb1bf3L,0x9c697d19b4a651c5L,0x5fe29bcc0df8c999L, + 0x16446aa446c45428L,0x3a51398061700e83L,0xf34133593f034bc9L } }, + /* 46 << 77 */ + { { 0x9cc126b8cbf28cbfL,0xf3f8aa7c1e6d63ffL,0x533e48d2b7f80225L, + 0x8fea0d204749d781L,0xd8ea614b326f8185L,0x9cf3e07753c541abL }, + { 0x09040b60d95c9367L,0xc1b19940f5eabd9dL,0x80b0793cd8f8bd1eL, + 0x95fafd6fadff120cL,0x071b1841ce155f8bL,0xa85dfc8cd29d9d9aL } }, + /* 47 << 77 */ + { { 0xf38e0fdea761048aL,0xd9d5a22c88a93773L,0xbd58470841a99bddL, + 0xa31ef1edebb412e0L,0xd5c4fd5a0274ea16L,0xaaf215f380c1f0f8L }, + { 0xe842a4537d3dfd08L,0xb5c877ae5a904548L,0x3dadd2eb9c6ddbebL, + 0x7f97c541e84e54d9L,0x6183b6ce1b8d8829L,0x2a20c212f50534a5L } }, + /* 48 << 77 */ + { { 0xc8c9b0ae7176dd90L,0xa95604542917d487L,0xb03b7946e62c508eL, + 0x60425926e9fe2321L,0x73b10bba80c1d136L,0xc30a847d9d218c9cL }, + { 0x6ed0c8ef2073859fL,0xa176eabf432dd97fL,0x3078096ab9e96167L, + 0xb28f0e6cc473e377L,0xb44e4995683a3bc8L,0x483512eed3523796L } }, + /* 49 << 77 */ + { { 0x7ff5827f22adab31L,0xa7e859ad43ee005aL,0xfc2387f402c9629eL, + 0x6f39e84add12b107L,0xd1378037c097d3daL,0xc677b554d70d107fL }, + { 0xec15469fe4943084L,0x1f0b13b19d412b76L,0x3b3b49b48a265a31L, + 0x45f28cc7dbe97ff2L,0x33f0e31f4efa0f0aL,0x6b22b99e37a5591bL } }, + /* 50 << 77 */ + { { 0x0a751d3eae0538e1L,0xd51b039af14135e9L,0x92eae0f6e8bdf562L, + 0xf253bd5c66557b17L,0xc1ff9054ef26b81bL,0x9d586d39eafd711eL }, + { 0xd2b05d3d4f431502L,0x847d727f5823cfe5L,0x2c4e236a8e99840dL, + 0xa407e2d87c5981c6L,0x989dd28c69ca34b5L,0x2e8ec6b09fe586e7L } }, + /* 51 << 77 */ + { { 0x43161b5c40bda312L,0x8fd476b8a10fbb2fL,0x84cbf7579e5d9a4bL, + 0x19bb5926a9a31956L,0x66ed993aea9db48aL,0xd7897780ffb0361eL }, + { 0xb031e035adfa3661L,0x1be83caf2296b4d8L,0x8802c98b0024cc48L, + 0x73adb0c0bac1aa5eL,0x17df92e1bef75b41L,0xd753e99903d800bbL } }, + /* 52 << 77 */ + { { 0x24940b868733c1c1L,0xf5dd77ce2ac072e1L,0xc248ad6bf7bdb8d2L, + 0x423e0cc9d9a8b926L,0x4318d600e6da05dcL,0x3e557e08ca27dfc9L }, + { 0x8dc551cdc5dc822bL,0x160da94cbc8fb392L,0x4ffebd2aa6d4d363L, + 0x8190c17db1ce15a6L,0x1abcd1361e9dc500L,0xae3a477c9ee52a47L } }, + /* 53 << 77 */ + { { 0x67ab01575ed80bdfL,0xc77067b69aeb4a86L,0xe6e26abdf7880a93L, + 0x782248db1e43049cL,0xa902c41016d78616L,0xc6fa899fbf309f15L }, + { 0x81e1532d672d951bL,0x84280ba386556a0dL,0x83190bfb55199078L, + 0xbc11e8c25a1c4691L,0x8ac60c7f21152509L,0x4211923ec775dcd0L } }, + /* 54 << 77 */ + { { 0xa63b33f6746418acL,0x62085e0eb7359443L,0x3b43ea7b5fb598dbL, + 0xf4a0f4442b365528L,0x7f4d2ff3eb55a5ddL,0x012cd591f189eadeL }, + { 0x3fbdad99f58c8f84L,0x71dc1b0093bf34dfL,0xfb63f09ce062a588L, + 0xd5f0f0ad6f24b66fL,0x940e23c91813cd9dL,0xeff8580b55f241dcL } }, + /* 55 << 77 */ + { { 0xb30719d8b7fb5f3aL,0x8f74305b43275030L,0x2fdb613bf23628bbL, + 0x75d9868ad945ccdcL,0xbfae46f4f0b73348L,0x48ad8bafe26679b3L }, + { 0x3aeb4743d0b389bdL,0xd2463ca37916297eL,0x3a6f37c820f52fd1L, + 0x7bfade4495ffa348L,0x1e3f6282a25cb79cL,0xac3320d5229bd2a3L } }, + /* 56 << 77 */ + { { 0x261578c7d57c8de9L,0xb9bc491f3836c5c8L,0x993266b414c8038fL, + 0xbacad755faa7cc39L,0x418c4defd69b7e27L,0x53fdc5cdae751533L }, + { 0x6f3bd329c3eea63aL,0xa7a22091e53dd29eL,0xb7164f73dc4c54ecL, + 0xca66290d44d3d74eL,0xf77c62424c9ea511L,0x34337f551f714c49L } }, + /* 57 << 77 */ + { { 0xd1f879197700d61cL,0x21728fe49a89dc22L,0xdd3a475be6d93642L, + 0x3f8554d6e095363fL,0x4b8b712463e1bb11L,0x75db57e6c6da541dL }, + { 0xfdeb9e46ac8342fdL,0x8ab4875114905993L,0x48150a06b2efd023L, + 0x9f5f513df415bff5L,0x39b1234eee9d7915L,0x735570a7dda66da5L } }, + /* 58 << 77 */ + { { 0x3a79a1756e3d4ec1L,0xde0ee6c79936b689L,0x37a7d9ec7fb84ee0L, + 0xe82810d38fe1f44fL,0xbe433c7253049e9eL,0xe72ef4f5fb49e274L }, + { 0x525b72094b4ad28dL,0x37bfb857164f5f0cL,0x60327e31ac68d566L, + 0xdb027619bb71f137L,0x8abc8026abb6e829L,0x99702ff15e838117L } }, + /* 59 << 77 */ + { { 0x974be1d30696f1a5L,0xf884616dd3832430L,0x6997c37ce9dce1acL, + 0xf4bad00e2e5cfbc4L,0x7727adf8e327a9a4L,0x15315bf16aeeb305L }, + { 0xe697c0af09fbffceL,0xe4291f7589f86a5fL,0x765f1904487b12f9L, + 0x752c58a5b7f8ca88L,0x9f9563d473716bf7L,0x48803cdbfd032783L } }, + /* 60 << 77 */ + { { 0xa0d935ce9050c5cdL,0xc1e062d03e9b902aL,0x212d0e5dc3054c00L, + 0xdc9c3f2de70ad96bL,0xa2182ffbc2742144L,0x4680d472a716993fL }, + { 0x9852bb00677f3756L,0x2bb3d78435e6213fL,0xadfdbfe07377fdc7L, + 0x41db795d708afddfL,0x6848cef57727ed86L,0xb24e416aa6c1dd1aL } }, + /* 61 << 77 */ + { { 0x36d76f2f2edc95c2L,0xbdf2a67810b0670fL,0x49fc8c43b63877a1L, + 0x23182ed3a87c8615L,0x94c21da96c011a44L,0x3bc0b86860d3c162L }, + { 0xca6a158244815192L,0x4bd1ce04fd97b78bL,0x1d0074cddc750023L, + 0x40cf8233cdfb0c7cL,0xe4e28aa8bbbfbf3dL,0x72656155b6eec7d2L } }, + /* 62 << 77 */ + { { 0x5b1be65b912b364dL,0xe6369ca1e0335426L,0x249740d58420e7daL, + 0xff13a26f1ac1acf4L,0x0ecee744b9634fb2L,0xbaa77d57d664ceb1L }, + { 0xadfa7625914f3f7eL,0x17c75e99bbcffe16L,0xcf557911d64aedb0L, + 0x8a4b7b49c3644ba0L,0x115240401eb7bb97L,0xb823c21a70fc7b5eL } }, + /* 63 << 77 */ + { { 0x45db2c038727c0fcL,0xf5aeeb7bbae2c896L,0xfad1cc32eed15b82L, + 0x65d4440a8609b00eL,0x35698d956b4dbd25L,0x861615bd0f6cda68L }, + { 0x578efdaa8aec1e99L,0x87ddae76fcf67480L,0x5ff5a1304669ccb0L, + 0x5fd2f31a0b98ee60L,0xccad491a3cc4c003L,0x6dcf25bbccbc46e0L } }, + /* 64 << 77 */ + { { 0x93a62e7cfa43699cL,0xdad738901bc422d9L,0x265e3cbb10cc9544L, + 0x28cceb062f37154cL,0x6b79b0713bf2e08bL,0x88e025df3ab39091L }, + { 0x50a8d04d126522bdL,0xeabbc1b7b779bacfL,0x3db4336ac21cc62eL, + 0x4747f0a36fc00450L,0x067cbf1c544b2d95L,0x2480b7d8fd2be7a7L } }, + /* 0 << 84 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 84 */ + { { 0x0233e423d52eb122L,0xc28483521154b0c9L,0x2ca09cef6349e35bL, + 0x3b70afc3ded2ec54L,0xc813474d52dded3dL,0x2d3f21bf12f00ee0L }, + { 0xa0908f7692f215c6L,0xb97d60e94e9c0440L,0x84ad10c134b6a8e0L, + 0x6f37fd956e7c163eL,0x7caae8c8d057e0c3L,0x534f52c2553721a2L } }, + /* 2 << 84 */ + { { 0xa354c1de72a041b2L,0xe83df25929d1330aL,0x676610999d532bbdL, + 0xb7c2f4cf52011751L,0x6945d34ff659e35eL,0x6217d20ba1303b7bL }, + { 0xa200ddba25751badL,0xa74a729001d3566dL,0x3018445faa82b46fL, + 0xc3e6a3acfccedc1bL,0xe86ae8703353e29fL,0x1c8085bbfd7e8547L } }, + /* 3 << 84 */ + { { 0x728c8e145d1a678fL,0xf944da572ac89a2dL,0x3016c2da4796df72L, + 0xf6d79e4e00a55efcL,0x4fced269526b1cb8L,0x4a93e47791f165a9L }, + { 0x528b8572f84f90d3L,0x3b30376e5e725561L,0x4f903520e07bb990L, + 0x07ddb97f4ea8ae6bL,0x29c01e70b3b735bbL,0x825c7f6e5000dd4aL } }, + /* 4 << 84 */ + { { 0x306b63e3b4dcea78L,0x4b10209213636935L,0x36bb68898bdeddeaL, + 0x9331655d67a329acL,0x14c7fe26ba92ccceL,0x4e7d6929be0519b4L }, + { 0x0dc39dbd164d50e2L,0xd4c430a0b1679cc5L,0xc7f78818fa8682baL, + 0x43396eadb60aad97L,0x751784d7ff2c64ccL,0xd37928be866af43eL } }, + /* 5 << 84 */ + { { 0x3742b61e0475f547L,0x48b2a2c2477722acL,0xf52c6787abce3401L, + 0x4749711ea4cb41b4L,0x7ce0dfb03fca817eL,0x1c1e3bf996e85048L }, + { 0xcd65250e40faa8e9L,0xa8edce7017d9b93aL,0x73523cb2b4dd5619L, + 0x15ba773abb5379f5L,0xcc5e62d6c0a847baL,0x7efe5c7c04d852deL } }, + /* 6 << 84 */ + { { 0xf0a69e685a91c9aaL,0x0304d20105c13197L,0x773a3ab7cd14af1dL, + 0xc0b88edd558d555dL,0xeb12d197d2e63dd6L,0x4a8e849fbcd9cdb3L }, + { 0x06432985965eaa14L,0x453d93861a5a6f43L,0xbd28f6164171b9bcL, + 0x37781639bbfcf90aL,0x1f93898f3a36084dL,0x1fefd8b7dd00ca75L } }, + /* 7 << 84 */ + { { 0x3b8d8e495e456124L,0x967ed511967c17b7L,0x1d72430c2aad8c67L, + 0xe8c5d506b82c1673L,0x989978868a0fb41dL,0xa9d478f70f81234fL }, + { 0xa0c941cf44cc0614L,0xc033c99024ad30f5L,0xaa7de296101f89aeL, + 0x4cadd8e3ca6a3227L,0x3b4db51f2764ec0cL,0xcbfe70fc09256db4L } }, + /* 8 << 84 */ + { { 0xb9207dbc2b2f1bccL,0x6afd6871a3e83ef7L,0x49924e5534ba150bL, + 0x2935ebf1dfec9972L,0x34bf5e94b76f870dL,0x22d0f32b4c20385cL }, + { 0xc78ac1728ccc8e72L,0x7b45b8220ccecb0aL,0x76c67ee4cfb4b8baL, + 0xecfaefb2cd8724b6L,0xe9bc3d67340bc1efL,0xed40b2b9ca5541b5L } }, + /* 9 << 84 */ + { { 0x5d1bd16518f8e17dL,0x754986b7405f822bL,0x420b1b24d8753fafL, + 0xab038e0608ff680cL,0x33621a0fa3649f49L,0xe24b84db78918eb6L }, + { 0x0e669672c8bf4168L,0xcb7fab33171eab20L,0xa097d2cc4808be42L, + 0x4f4e395f5842b80bL,0xddcb1e51a579145cL,0xa635d0cdf330ae0cL } }, + /* 10 << 84 */ + { { 0x9b8a3eb3069e6432L,0x43aaa7fc721397f7L,0x46e23c6ca7e83a71L, + 0x71b261d593fa3c25L,0x4a47a1050f523a72L,0x31919e898dcad752L }, + { 0x4c8b06e70c5dd2adL,0x677ec5f38bdc55e7L,0x4372d55dcb1b5828L, + 0x7bf054c1f04dd321L,0x4e8c1a992e44584eL,0x6807803751d35d78L } }, + /* 11 << 84 */ + { { 0xa6d78a3d754377feL,0xcc17c26ac72ae5e6L,0x2f0ab93b1c05fc24L, + 0x1645c369d64c9d40L,0x7c37b12c563e7e9bL,0xb70d292d58b477cbL }, + { 0xc283aca993a2d5a6L,0x759e9118354c183fL,0x8a031f6fdd8f4125L, + 0xfa8b17ad56edbe3aL,0x6e0f96eb63c651ffL,0x40361942b5085541L } }, + /* 12 << 84 */ + { { 0x25ae349981d311b3L,0x8640f52a3b16037bL,0xac0839941d947065L, + 0x3723c75ee2e693d2L,0x65040a51b66f429eL,0x7f582b0b035a3a53L }, + { 0x20eca9e10a166da6L,0x45b37e202c4cc565L,0xeab882957a8a96e3L, + 0x99e771dab60a1a1bL,0x2cdd778c23b03965L,0x8d4d7a7291052478L } }, + /* 13 << 84 */ + { { 0xb57b345e4ff33506L,0xc1a3092a31d23fc3L,0xc16b501e905e1f58L, + 0xa36a3b1f29067b85L,0x7cfabd23c214dd5aL,0xbd5f7ab726ad949eL }, + { 0x8f64595987363816L,0x49c1a3e679d12d59L,0xcc8f3e2c32d771abL, + 0x008d900e6bde16d1L,0x60428a0f60165966L,0xd4f8d9eda7383ab9L } }, + /* 14 << 84 */ + { { 0xa52d3c2d7e8f73b5L,0x86d8063351842657L,0x58f01253b3949ebaL, + 0x97689f15e79367d0L,0x918bf9a30d820328L,0x2d4bc99441c959dfL }, + { 0x37392f6e8c16ee54L,0x9f726d58e6f0849bL,0x497de1e4b8208f08L, + 0x60c51233d51a29b3L,0x0f61fb03c9e1d465L,0x09494bd0fbe2613cL } }, + /* 15 << 84 */ + { { 0x100ef5d0a2bd7bd4L,0x89efecf5f45e2a66L,0x63bc210b653786bbL, + 0xc7748dba0a0e47c4L,0xaf8122ae110d1ba0L,0x6695bfbf797c78bfL }, + { 0x9b0e6fb1d7dbff69L,0x106799703f53040eL,0x22d9ed52fcaf4ed1L, + 0x1e27bafdcc1b2d4cL,0x839f9c019f1c88e6L,0x1112fe541321ad66L } }, + /* 16 << 84 */ + { { 0x4f293478154d0f99L,0x1b82320dd07a24b3L,0x1bf7c94f64d55f6fL, + 0x4489b57d725c5125L,0x3aa4d43ab1b6a091L,0x054842bdcf7a60faL }, + { 0xaa918a4d2aeb4cb6L,0xcbdaff99ac7d317bL,0xed0e00a16812a03cL, + 0xb09acf270b0a1e4bL,0xc73a41f7ac28386bL,0x43134dbdf4cd1321L } }, + /* 17 << 84 */ + { { 0xe5f746af6e001a20L,0xdc975b02d6a9925fL,0x6d13e266e57f9100L, + 0xe013661396a9c4c9L,0xb483162850a66d45L,0xe3b0f96d4ee8439aL }, + { 0xf2a2c08d3e074501L,0x987b2b6b2be498e4L,0x605aad24a15b815aL, + 0x5bf2186f8529ad68L,0x1413b3d7885ad25dL,0x3de23959807efaabL } }, + /* 18 << 84 */ + { { 0x08336ffed8c33924L,0x15b56cbf5140b253L,0x38dcd310306caedbL, + 0x04ecd49647944afdL,0x1280d23f68a48f95L,0xf414220434363c6eL }, + { 0xd0a397eacaa8717fL,0xb51a1669c3994b80L,0xa02eed916c56808bL, + 0xc3ab55c583545c3cL,0x8b835820fd26114aL,0xe0cfa4a6ffff324cL } }, + /* 19 << 84 */ + { { 0x4db4bfb788b45f19L,0x130252bbe0d5fd16L,0xe44c97b22808bff6L, + 0x885e4555b03405caL,0x3b7ce036be9af81eL,0xebe17cf58c552276L }, + { 0x6eb946c977f4158fL,0x36c23a9c74a5e642L,0x466ff55f2e70a453L, + 0x327fd5fd28ea7af7L,0xc96bfbec6e658256L,0xaf194fe8c0a3b932L } }, + /* 20 << 84 */ + { { 0xcf63d27951c0d95eL,0x3b170a0bac86a014L,0xc21eaaa9881095e1L, + 0xed2fda116069a3ebL,0x536264b9bd2f1c5aL,0x819e1cffde312c2cL }, + { 0x6c30f983dfd6ce38L,0x2f32cc4c980b439eL,0x9fab10b63b9c03b2L, + 0xdfebe34e011ab74aL,0x587360e3b80963f6L,0x3db1f6108692e352L } }, + /* 21 << 84 */ + { { 0xf262f2379765908aL,0x76f8d0017d03cdcbL,0xdbcadfb22f35de21L, + 0x88d5bf592a73815aL,0xc4f4e3b02b1bab82L,0xf5cce885b9635dcbL }, + { 0x110a785875a416dbL,0xfe7e6c360adb01feL,0xa02642c01374d779L, + 0x9010758753bb5898L,0x0c764ed2a363fcf2L,0x24a2a5541700e551L } }, + /* 22 << 84 */ + { { 0x63a094c5fe3d070bL,0xf769b91988515eb1L,0xafe86e1450d1131dL, + 0x6bf277886774d3d4L,0x7231d699ffd805d0L,0x05132e5b6304116eL }, + { 0x3d5e255be34ce5bcL,0xfd9c3bd0c95e3089L,0x22a24023b83cbac9L, + 0xfb6d2b6fb0b3b98aL,0x74af1115f7e36fcdL,0xcfe15eaff9da3bf0L } }, + /* 23 << 84 */ + { { 0xb242ffd61da39f60L,0xd0ed946320cac1b3L,0x9ebd5e46e25f809fL, + 0xc7df7e5a07f5aa4eL,0x5eea38d791a5f85dL,0x6240f01d6080442fL }, + { 0x72ec0a5e251d866fL,0xd3e4acbebf2c0037L,0x0d4f47c90fd962d7L, + 0xece7c047b8de2dfbL,0x841050b96df17f0fL,0x567c3df7e933a4d5L } }, + /* 24 << 84 */ + { { 0x266d2c1cbb2fcdaeL,0xb538d4a252be93f2L,0x774c88ba73bd0094L, + 0x65283a9b81a7e042L,0xe1438bbfd0381625L,0x450e1f644d0db206L }, + { 0xb38ae9ef4e60fc4aL,0x14ce87e112719817L,0x831d41ec570303f0L, + 0x7172917028850444L,0x2077ea32ccd609f5L,0x091d1166cd273fdcL } }, + /* 25 << 84 */ + { { 0xaf5916f49412edcbL,0x9ccc0dc08f01b2d9L,0xbed1fdd42dd737c8L, + 0x29d26cab95a21501L,0xff38bf18c70f1364L,0x0bdb055876879b06L }, + { 0x706031e2a14164d8L,0xe229fce1fc39648bL,0x5ebc640878e97c8bL, + 0x26039bda822de18fL,0xab992da4b9f090d7L,0xf409432d53eb438eL } }, + /* 26 << 84 */ + { { 0xdf216dd84b2ca517L,0xb3eec4b9c6b74c4dL,0xf564e6c81c14e77bL, + 0xcde25f1c2c2c9395L,0x7e31f7a5049fcc83L,0x6913707b9284c753L }, + { 0xb92a6f2458e6eb5fL,0x85b0cab595148292L,0xeaad036d7449be92L, + 0x2f6a2888eb94a702L,0xd7d8773d47d59fb0L,0x612d257303c0bf25L } }, + /* 27 << 84 */ + { { 0x805ece910ea742f6L,0x54486a6ffb5dba94L,0xaceb0eebbae52f76L, + 0x2200fd85e98794f0L,0x44bd993ef305af19L,0x28f256738eb8baceL }, + { 0x5d3fabbadc5f9c18L,0x4338f79c1b003ed1L,0xaf4b0566bc20c65aL, + 0xded9407c3045d1bbL,0xe8713d7506391eb2L,0x557d62c971307365L } }, + /* 28 << 84 */ + { { 0xb872a10584d2c3bbL,0x44bca57139196026L,0x857327d84e352e5dL, + 0xa6c6004ad925f99fL,0x48aaf266bab79eadL,0x213ad923adab2a3fL }, + { 0x3be29b6df371cc48L,0xe732b9062385c9f4L,0x562e0be123f0a84eL, + 0xbb6b017228c4b0dbL,0x71a93ae5f4c6d8beL,0x76b8bb16551f1fe9L } }, + /* 29 << 84 */ + { { 0xd028d9b5242002c2L,0xea105054823783caL,0x01cf8a491d45c34fL, + 0x1035835e42457869L,0x0a95049661cc1e05L,0x9dce5bd3b439afc2L }, + { 0x8552f02003b18e4fL,0x4973e3bde6144805L,0x29fb98d8d8514c4eL, + 0x0ce0e8d83ca27b39L,0x7aaf3f5284bbc6caL,0x0572bf40d78c7c5bL } }, + /* 30 << 84 */ + { { 0xbbfaaa94c39926a8L,0xb9a59fdb60a138aaL,0x217a1aa2947e30e9L, + 0xcac988c9c52c9fffL,0x5676473a3bae3c39L,0x7d84b353857f04c9L }, + { 0xdeded30cdd324e24L,0xf07c678a9c242899L,0x956d05538cb64f3bL, + 0x9d34e2f5502cb2b0L,0x99e1054a51dd03b3L,0x86b8bfa54d60a593L } }, + /* 31 << 84 */ + { { 0x3dcd2df9c8870c4eL,0x7cfdd05f1699cd0fL,0x19e9ccf027e79e0fL, + 0x56e997027b85d75eL,0x407b5b74ccadcf9cL,0xc961a336297dda7aL }, + { 0x350c34d56d12d17bL,0xe37de9a93bc6afe9L,0xd2c7339e0d641d3fL, + 0x2700f39cf7dfa063L,0x2916f9ad8ddef077L,0xffec6230547cdbebL } }, + /* 32 << 84 */ + { { 0x10a53b90754d15e9L,0x6cde9a0c5f4c7218L,0x740d513fabef2b96L, + 0xff6cc47cd3f802fdL,0x1be6825beb0627afL,0xdb21ede55886c2dcL }, + { 0xb6cfb2c6f5daaed7L,0x68b61aa8fae29a9cL,0x7a1e16f53a5a485bL, + 0x16b60b92e7b2223eL,0x332f33d836a13a9bL,0x4567c313876cd1a2L } }, + /* 33 << 84 */ + { { 0x7663402de62014a2L,0xbffe1e7fc4efd224L,0x2080eb02c38f766dL, + 0x6c95529ba9641db9L,0x24dc13a5c68de8e5L,0xca219b3fbbc3016bL }, + { 0xb83450e310b634e0L,0x8cd26d775b097a34L,0xb912c34564c9884fL, + 0x3d1f28be5bd75f1eL,0xdcba2b479466ea59L,0x4077e017ca9948e3L } }, + /* 34 << 84 */ + { { 0xb4b2c65df91c7972L,0xabe915496b689013L,0x4eb7afa8d506333bL, + 0xc2f2ac1d648e7c0aL,0xc6bc96b1213cc243L,0x0b827c2189e44025L }, + { 0x2e866601cadee87dL,0x8ee85356b4719ce3L,0xefda7427b4fc0081L, + 0x0d5c33c4c802c92dL,0x4c8635ab58515f01L,0x9d7ed87edd0ab04fL } }, + /* 35 << 84 */ + { { 0x9a660794cda4cadfL,0x70784fff2484a3b3L,0x8ed664ad2de7de13L, + 0xbaff5937030d906eL,0x884407034ab43a4fL,0x86dfdd53ee09795bL }, + { 0xcffa6852fb0e889cL,0xd94373e1e8c9fb95L,0xecc0ea249b0e3ac1L, + 0xe88eda6eaa89e492L,0xbb049803da19207cL,0xfbb0c3874bbb5be6L } }, + /* 36 << 84 */ + { { 0x3e2bdd9b5a5f6b4dL,0x30cf4762ab005a55L,0x8736f5188bacd78cL, + 0x8a5a647b09dc21fdL,0xfba40c38ca06c1fcL,0x63d53fb64a4e1524L }, + { 0xe77d07a19a2bd706L,0x54144ea7bbe30e86L,0x8eb606220bd955a4L, + 0xf689cc80b3c26cafL,0xc70fe95c9fefcbbfL,0x67f9e8e2495b5bdeL } }, + /* 37 << 84 */ + { { 0x04361e6b2e4d2cf9L,0xdbd3cc13ade11ba7L,0x93dc1d1df47d8ae0L, + 0x7d46bba6fbb2d65dL,0x797ea0df92e97abdL,0x09eb3975a712e8cdL }, + { 0x9ab3a54e0380cf8fL,0xcd1a9574c96710b1L,0x6abcd1a1dc13dbfaL, + 0x1be0db71c2ee67f9L,0xee8ec8d0c2ac89a5L,0xbc363f407da201f5L } }, + /* 38 << 84 */ + { { 0xc86c049bbbef377cL,0x43df6f3703de56a7L,0x01eced2b558e516fL, + 0x18fca0bdb43c1cc0L,0xd8c6f7ff62121c68L,0xb2f1f1ac36f90713L }, + { 0x5f876328ea1bbd95L,0x9f22dd535ac4ce8cL,0x7e052acc7df88002L, + 0xedf21fb7068d46a4L,0x349130a21d7d0220L,0xcccc79beaaa68eebL } }, + /* 39 << 84 */ + { { 0x9c955b5eb4100632L,0x8d6dd2d3ccd99a0eL,0x700f827c265dd397L, + 0x5540bc0cfc85a2c1L,0x6d4b8e7adfb81661L,0xfbfe1ebe1d5c1485L }, + { 0x322c2883c9dc1b6cL,0xc7c897cdfd7e0f34L,0xe70b0586030e41aeL, + 0x4263e06e26a728b7L,0x0ee2b93392387542L,0xae708ccaf6220511L } }, + /* 40 << 84 */ + { { 0x05ff8b9cbc15ae37L,0x94dc2e85d06d62edL,0xea1d1c8b4b02607dL, + 0x1fc202a224da757cL,0xbd5180bb35440e69L,0x0263dd51698ee7a5L }, + { 0xbe93f27654013d74L,0xa7c041c464e81695L,0xbb170ac13ba5336fL, + 0x1aadf302af84dfa1L,0xeda58747c960788fL,0xb456070e5eefc35eL } }, + /* 41 << 84 */ + { { 0xa905d421800ed69aL,0xdb8a643813622898L,0xd003affbdaab0769L, + 0x467bc051f0aed9d3L,0xed1e6951b11085d3L,0x7a1d1152d3f54fc5L }, + { 0x8cb243b6dc8dd008L,0xf9c690d1f409210dL,0x9a3195399461aee0L, + 0xf580724dbc2e4de0L,0x52f648e4e759556fL,0x235a79f2697885d6L } }, + /* 42 << 84 */ + { { 0xb293d3fe8220ceb2L,0xace20e7e049a33a9L,0xa584ad52af4198d6L, + 0x49c5cde64aa0a5c6L,0xc4f7877ecee2e664L,0xe1557968bb98ed87L }, + { 0x69b0cd713066000dL,0x1af188cbc7399f29L,0x5b88b85c306188a3L, + 0xcffa28eb4097182dL,0xdb01149ec80d0aa9L,0x9f8e6d59402bc397L } }, + /* 43 << 84 */ + { { 0xa646077bd5b97d37L,0x618df84461cfbd95L,0x3a9fe2f447c62894L, + 0x7f2760eb4e0f1612L,0x50c08fdb36e5acf1L,0xac799584675d2aabL }, + { 0x3eba6f54917dd606L,0xf585fa5075119ed9L,0xb047abfca32016bcL, + 0x61c03e51aca118f0L,0xef9fcc526dc13766L,0xd849eca5e8a3fb72L } }, + /* 44 << 84 */ + { { 0x11ac1ff4147faf46L,0x5dd8913882b818f4L,0xe439f66fb15fe5a2L, + 0xadf913a5fe8fb45aL,0x3dc708404a6bbdb0L,0xe8e1204da4af4ac5L }, + { 0x4be549318ba70502L,0x945d9a765883b39bL,0x99cb1c721a76198bL, + 0x96fbed479a7949e2L,0x30ee96ebf0299bc4L,0xb7dc5e76d3dd160cL } }, + /* 45 << 84 */ + { { 0x85eca39b0c88d5feL,0x96000863af9e0158L,0xbb13f99c4509590eL, + 0x50033c18034e2499L,0x1e9346f87b86cb33L,0x917d88b4aca548e0L }, + { 0x0c422c2e9e2a7e15L,0x6751c95c5e37fb06L,0x631361b8c40d21b7L, + 0xe231858ec9958deeL,0xae86abc54d9936e3L,0x60c78d1137bf9213L } }, + /* 46 << 84 */ + { { 0xa0bcb7c6283190a9L,0x36c884ffc53fe76eL,0x071d4acab23f0865L, + 0xd44e3c20e14a82f5L,0x704dadd8968d28bbL,0xb40d2b948e88ad61L }, + { 0x4a29142ff3de62f8L,0xdd071910bd7292a8L,0x5b12c32d5b3571c9L, + 0xe9886262943c6aecL,0xc49b7506cb1e0a33L,0x87f6c2d3de95886cL } }, + /* 47 << 84 */ + { { 0x44ba232e010f465cL,0xb82486c69ac91d38L,0xcd1a6bf75de743f5L, + 0xe050232838acbc4bL,0x8de9c29631fb87b5L,0x9c8029250450c4efL }, + { 0x19ee1607635e64a6L,0xeff5478c69ed7f8eL,0x311201a027001c21L, + 0xfc0382a78beb55ecL,0x494b623ce9dea7f8L,0x926a3f756767f769L } }, + /* 48 << 84 */ + { { 0x802f495cee46f99bL,0x0f3ad0ee43b91cbbL,0xeaf3b294e9b3f0f6L, + 0x82cc760033cbdcd1L,0x1a5642278e83fce5L,0xcf1b2edaffa0e4ccL }, + { 0x7d93e9769b1f5706L,0xe4eb843cf873d68eL,0xcb53dd79eafe5f35L, + 0xcbbed8f0fcaafabbL,0x570472705f053efeL,0x2c71a95f1ebfeb7aL } }, + /* 49 << 84 */ + { { 0x02d4717ddd7a5499L,0x3bc8bdcb9966236bL,0x13f08015fd27be15L, + 0xe05236f6baaff392L,0xf73bab3f7b4cc522L,0x8ad26d4552ccc027L }, + { 0x79f8e79e9e9ccd7fL,0x8011b92aab2f22d9L,0x6aef576e729662e5L, + 0x7d5194d05e568f55L,0x2947d63a1a40860bL,0xe9890f1440305b54L } }, + /* 50 << 84 */ + { { 0x8085614c0fa9602eL,0x9ee1b9b26651c4ffL,0x65dd9c94ec048f1bL, + 0x10b4a62f6d6c0fd7L,0x61469fb7d391dcd2L,0xdf751399edc3d431L }, + { 0xe3901315c913acbbL,0x31581d7a90976644L,0xf20809634aee5cecL, + 0xaa716eafe5408c5dL,0x9e356989b9a60ad7L,0x2d6e7733a6a3c977L } }, + /* 51 << 84 */ + { { 0xd6d99f54f19b8464L,0x3322a0b8a0be5c3bL,0x6cff730557e98725L, + 0x786709c7953a357dL,0x3864d278a1013652L,0xf7471f111738f6e6L }, + { 0x0377a923984c465aL,0x4a24b9e14ba970e2L,0xe53dd9f21c01d248L, + 0xf422b754fbffc0d5L,0xae25dc0ec6a956b0L,0x3c3fef96ce806445L } }, + /* 52 << 84 */ + { { 0x6a69d207b5906d71L,0xf3c757ed8964e1b1L,0xdae255af5f98821fL, + 0x6c801ed4db1af96aL,0xd12430343d109b86L,0x4b2aa65fa091f98dL }, + { 0xd9bb4c2132dcb5f9L,0xe5a5979bf190a1e0L,0x0861e5de40117a91L, + 0x8753c9adc39120e4L,0xfdcb09f4aeb4a18fL,0xdbda38746bd1fd08L } }, + /* 53 << 84 */ + { { 0x1bd8e8c0304f7045L,0x8ffcf24eedbd2dd0L,0x13c9441de6ae4dadL, + 0x5efb70aab418c02dL,0x9d0fede1b8cf6949L,0x613545cf41f5aec0L }, + { 0x4e3342244b98bddeL,0x7d0c11110fd8aaf9L,0x30c2bedcdfb8643cL, + 0x875d386aa83e493fL,0x85b32632d6cd0825L,0x9f1ef3a01445507dL } }, + /* 54 << 84 */ + { { 0x2b70440e54f6b8d9L,0x355e692430eddda5L,0x354e7cfbc9199910L, + 0x7e8933bfdc7de946L,0xc5692fa981b9eaabL,0x2eb58fff98cf5f21L }, + { 0xd0d8f9bb96b19d59L,0x779aad414d1a6285L,0x0cee1a9b5eb87c49L, + 0x676e36ff786c4c81L,0x6618c8f112d34964L,0x2061186dd03e9562L } }, + /* 55 << 84 */ + { { 0xa5ae40977da39b54L,0x98e4d1d9f1d40635L,0x40d97af126154fc6L, + 0xf18041d4e9ae28c3L,0xdca9487555978c61L,0x4aaddec43638b9b6L }, + { 0x1e615a2eab925f91L,0x5cfbbe9ded8a50faL,0x0f26d3ffb2034aa1L, + 0xb2f9cee2c4813646L,0x2195af47957b6709L,0xa55dac537e7fc45fL } }, + /* 56 << 84 */ + { { 0xe44a8ed7630816b2L,0x5fb9b643cca34310L,0x07826148a3b5d2e2L, + 0x0f890db16e65c2efL,0xe9feebe288283844L,0x8e56c6760368a9f4L }, + { 0x8f0cc9c93e4ce874L,0x646ede9b09f1beffL,0xe92d6bda014e3d19L, + 0x27e620c5520c921fL,0xfd9b2ae1eed78555L,0x68684615816a603eL } }, + /* 57 << 84 */ + { { 0xcf54e9e89ded00c7L,0x8dff0130abbf7765L,0xf12773fb10c5f8d0L, + 0x7435ac767382e4eaL,0x93092b16f61d443fL,0xc1554fa846eb45cdL }, + { 0x0896852c30957ca5L,0xc0d91e3effe60944L,0xce8aee57a1b7c75eL, + 0x4d24f07007cd1a9eL,0x3d8e381094456b11L,0xed6fba6b9dbc9d0dL } }, + /* 58 << 84 */ + { { 0x1b1de3ed8b5b8f82L,0xf542399d64252363L,0x23f34cccd206f26fL, + 0x54c48d9fbd941d6fL,0x3859eb56202e757bL,0xedcb4729ae0eaf7aL }, + { 0xf08753c512360fceL,0xf37ece765f697cd4L,0x073cae01c98a7c8bL, + 0x6e298559df664bdaL,0xe8cefd27194b103cL,0x56301e2a811f6a71L } }, + /* 59 << 84 */ + { { 0x8103c6053d3fe586L,0x472885b3999bb4caL,0x3759d2d492a2834aL, + 0xaa4eb3acd46cca1bL,0xcb99aaba633e579dL,0xf9369b033d6dc569L }, + { 0x55fdb1fe8398c067L,0xd7aab8b47e6826ceL,0x7f5497bd8b525561L, + 0x2e0e1e9c2cd0e3beL,0x3142a6e2c47caf5aL,0xe78cb1840f4b802fL } }, + /* 60 << 84 */ + { { 0x0a1577baf455f6bcL,0xaeeea79094df32b3L,0x1af3ba0f6bbb15ceL, + 0xaab92a74e8522659L,0x84087a8f7efa0a4fL,0x83c6991b84596065L }, + { 0x11f7829d29fbb626L,0x32b04b2f86031974L,0xf3a5b8722c1291deL, + 0x2ffcc97e8bd2be43L,0x575400d10a206f7cL,0xbb4583de0befbce6L } }, + /* 61 << 84 */ + { { 0xd448eafaab983fd7L,0x2622336c7a18a7e0L,0x36632e221c274b3cL, + 0xe64e8f89bf086fcfL,0x1dced08fef72ebd9L,0x61249c25ea295d31L }, + { 0x7433743d3755632aL,0x9d766243ff32ed08L,0xc36e816a977b1d9aL, + 0x1069fc0820ccec81L,0xbd4af7bef65a0cd8L,0xd04127fc92e31836L } }, + /* 62 << 84 */ + { { 0x39560937ea57ca46L,0xe1f2b7198229d346L,0x462b28d4dd02dcbfL, + 0x510fce98a333d609L,0x795fbd38fefa05beL,0xd6e34c231bcb029dL }, + { 0xf33291fc838f7ec3L,0x2a01a1f5f16e7247L,0xf9737722c0bcb3cdL, + 0xc53ef57ecc8a6c77L,0x219372afc750f1a7L,0x3e6a97c3d14e60bcL } }, + /* 63 << 84 */ + { { 0x87278f062db3d752L,0x64c65f5cd106b7a8L,0x04ccc14d41ee7aebL, + 0x72d1189e71952b60L,0x2e88f851080e9ea8L,0x625a6d32913e8df4L }, + { 0xd943de73900ee95dL,0x6c12b3b3ecb8b3a0L,0x6209daf2c9b141e8L, + 0x81c02f71412da959L,0x222d17b747278f65L,0xaa338805789138e1L } }, + /* 64 << 84 */ + { { 0xa896d28e4aea3fa2L,0xc6137a456db06ee9L,0x1bbafe8c06fb15ccL, + 0x2daab2961cdffdadL,0x984defc8e1119b3aL,0x9cd44c3cde2a25a3L }, + { 0xa7f54ece54ed6d73L,0xd283017f50907054L,0x69130efc6a3b9442L, + 0x5d17f1276785163bL,0xc019911b172b1d0aL,0xa19c745f7e3e093cL } }, + /* 0 << 91 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 91 */ + { { 0xe185bdc2ab83d932L,0x0a75845dd7c4e754L,0x1f6f3397c3fe5695L, + 0x6c9f3a5f61f6a04fL,0x3c0f9d4bb390a92bL,0x9e3336b74793b454L }, + { 0x91ad0c341472f06bL,0x4110047a892cbdd7L,0xfa24d90565d53c83L, + 0xd63e58334176007dL,0x741089fd2cd1623cL,0x6b3d92022685d345L } }, + /* 2 << 91 */ + { { 0x1d510157c9cb7f6dL,0x532a077346ab7372L,0x2ea07e2fc6dde9e2L, + 0xceed9ad937d5bb1fL,0x3121994b98cc6e28L,0x67d2fbb567ad8fc4L }, + { 0x34707fb3dc9f195dL,0x6a601f481fd5a013L,0xfe939b8d81ef6cb5L, + 0x5c51e8ab1223a9a1L,0x8f6d7993db74cf37L,0x0b81c5b7972808e1L } }, + /* 3 << 91 */ + { { 0xcb4e85123bf921afL,0x28fc6332532e81d3L,0x682d8637f69f907dL, + 0xbd9fa8f45f759a16L,0x091ea9fa51f03716L,0xd685a14132c630e9L }, + { 0x7600c9ac3d249cf4L,0x687e2022002cd2b5L,0x7ec205ab55334058L, + 0x9d0d86b13ecf1368L,0xb3fc17a7fc7baf6dL,0x57939961361c91cdL } }, + /* 4 << 91 */ + { { 0x0db33228010c0754L,0x10635ffa8eca7c59L,0x6efd85380e8a38faL, + 0xc1812ea5769360d8L,0x505723dc76f27ef5L,0xd0358e02f35af2e8L }, + { 0x9f7bb7fed99419eeL,0x87c66e83430a0e2dL,0x01187549773eaf7fL, + 0x05bbbba489d51bdaL,0x52cabb06640ccde6L,0x0d5cb557e7ff387dL } }, + /* 5 << 91 */ + { { 0x709d61ca10e06f1aL,0xaa1e9fc578eba75cL,0xf85d062f914b2cfcL, + 0xe73b3baf9089d85cL,0x4ac05feac4a284b9L,0x92c78a433acb7268L }, + { 0x7b5586f8ee45bb4dL,0xc39a0d0e6ac0a9e7L,0xe4bbe3d54d6f9ab8L, + 0x1489463f1fd46a08L,0x3ba3182529dba364L,0x94f000d68138511bL } }, + /* 6 << 91 */ + { { 0x70187dfbc39c1cefL,0xa785216e0c50c71eL,0x30188b816a6c0d60L, + 0xeaeda67d6a27e97bL,0x4a5192826ba389aaL,0xb96c7c7ea2bf1273L }, + { 0x8ff10657267fe714L,0xdff4a271996d91b7L,0xe34ba3e11dc7aed4L, + 0xc457048b38853d61L,0xe89825db1ccbf658L,0x68c7b4556b255eddL } }, + /* 7 << 91 */ + { { 0xdc14cb2a74871e18L,0x017b1340fcb8974aL,0xea5cb0546e93c20fL, + 0xa7c078ada9e2ad1fL,0xa37207d4beb26838L,0xcd8b3b25de7ee8eeL }, + { 0xdca6606a2801a7ffL,0xad2fedcf0f8af3faL,0xf27d30b49b530c05L, + 0x071fc1c36b2a4613L,0x363aaa99b72cea9fL,0x7a33ed8f3d350374L } }, + /* 8 << 91 */ + { { 0xc377b373bb20fabfL,0x68d3aa52f986b847L,0xd9c2f2adf39b6894L, + 0x1bbff106bd6da22eL,0x3f7e5b8e7e09678eL,0xad6a87897ed3ee78L }, + { 0x689e6b31af9807b9L,0xeca87778bd1f6ef2L,0x17d3277edda78c54L, + 0xe686caccefb65cb7L,0x758aa1ab19a30f0cL,0xb40df97fb11f071eL } }, + /* 9 << 91 */ + { { 0x43b379f71a54cd32L,0xd61fe6c948817fa8L,0x6d7b0acc49ab7a6cL, + 0xee23b4a0eb6bb45fL,0x340da1f1a2bda931L,0xfdff68411750ea8dL }, + { 0x890346b8a96c7df8L,0x551993aed4fafc31L,0x2830b98890de711fL, + 0x4d23863cfb5b5286L,0x327161a0d636d67cL,0xf99dded9733e1725L } }, + /* 10 << 91 */ + { { 0x0bef2d2517da64c9L,0xb94dfc85470bbc15L,0x2c2417cedd4af7aeL, + 0x52b5b3bbc8e88ca4L,0xc00328c44f20d154L,0x024290f730af5d4bL }, + { 0xe8bacbebeefc7350L,0x89eed6ebb72abd15L,0xb67d1da61d9e7030L, + 0x2ddefcbc0e70a331L,0x7d09bc6d61e32577L,0xc2073cc95b52e979L } }, + /* 11 << 91 */ + { { 0x585939298b806bfaL,0x608ddfbfbce6a08aL,0x674545a08eb27b54L, + 0x4b57a947c8fba762L,0xcf960113cbd8c683L,0x7b5a479a4fef1937L }, + { 0xe26eb960450e97f1L,0xf04b36b9d8605a37L,0xb208c832ee5af2b3L, + 0x3578d3a71fa337e3L,0x22547fca93509939L,0xd93dcb50e848508aL } }, + /* 12 << 91 */ + { { 0xd40f36e6276f2576L,0xd37455c46405cfe4L,0xe34094d7cc51dbaeL, + 0x20f93f0f0edf8bf9L,0x534b75aa23b5e165L,0x438e4dd1dc1b73a8L }, + { 0x9dd48c413bddb435L,0xc49867a0996b4932L,0x4212f8a2a9ffa0daL, + 0x8d5236c4d94ed9bdL,0x81bec489f169cb19L,0x71cc1d7e6104edfcL } }, + /* 13 << 91 */ + { { 0x31a94a7f22771941L,0xa277284b39867dc3L,0xc66bd88b1a52f0f1L, + 0xd2e2707b1aa21ee8L,0x78e4f280248d61e2L,0x33df48c7596a31f9L }, + { 0xb9bf2baab1bb1e89L,0xe1bbcdb4038f10e2L,0x81f674a877b89305L, + 0x8b2ec6ee16f08a86L,0xa07239c29db97ceaL,0x9f4ae6647ef8ecbcL } }, + /* 14 << 91 */ + { { 0x9cb21b57012eaba3L,0xcfce54821347a83aL,0xe3f3a67100d7b34bL, + 0xd4bcb3d1a6c1b0c3L,0x6ebd26fb9f3c3e31L,0xd01746532dc79be8L }, + { 0xe7cf9a0ad4156cfdL,0x2757cb0416face21L,0x8b0e320e69e1f08bL, + 0x2a8caf9b946f83d7L,0x6daff0ba98a399adL,0xb4dfea0938ed6086L } }, + /* 15 << 91 */ + { { 0x90ed8b41e2bcf8ceL,0xa464972be8dcc1a6L,0x5a3d0b80ba496081L, + 0xb636435569f85ac8L,0x0a2765b1a25bdd8aL,0x87a6c18f0d1516bcL }, + { 0x9344081ae3b01522L,0xcef8e12e608f0145L,0x6f3566a52155e7deL, + 0xcfc1be9c4d033a3eL,0xfc836eeaab97bf98L,0xbdf53718ba7dd059L } }, + /* 16 << 91 */ + { { 0x16f3708b953b9223L,0x0d3780f8770e7cf3L,0x97a615b227bb71a8L, + 0xa8b9a864162f8b55L,0x80ee8362d91e3fb9L,0xb2009a09f83a4ff6L }, + { 0x07a7873ac1696281L,0x17ff00c223095ddcL,0x427f683d860d60baL, + 0xea9959271f87d32aL,0xb2ac69faa050319dL,0x30c362b9d2d0b9ceL } }, + /* 17 << 91 */ + { { 0xe05c6a88783508b6L,0xa5569c8ee1779a78L,0xa1e0ca30cc1e84ceL, + 0x12ecb540337cca76L,0xafb5e2fb344d729fL,0x558db4e132c8f80bL }, + { 0x5aa3c39523128383L,0x9f04757cee1ee2fbL,0x41132bd215356deaL, + 0x4e9af313ae07ca78L,0xdfc14c0100c6b589L,0x54fdb4f3dc16a1f1L } }, + /* 18 << 91 */ + { { 0x71e663c234938279L,0x9a8f5ccdb05630f4L,0xd91ead12aad70096L, + 0x2b19b27e9e46cf72L,0x93348c7038e3932dL,0xeab6c03a5c7617b4L }, + { 0x57c13a97538eab27L,0x2624d17b2f5872f7L,0x77b63d9104b00f8eL, + 0x2e0582473c89db0fL,0x5d367277937d0d8aL,0x28c19068df60c252L } }, + /* 19 << 91 */ + { { 0x9867bc3d38cd6020L,0x5f341d8c5986f76cL,0x108a3c0d0dab2e32L, + 0xd127a7f989ab3654L,0x9d5018f468505cecL,0x51204da0a8fc94a4L }, + { 0x1751f30cf6da9840L,0xafe6a8d955ed1f74L,0x270a5d1180165ac5L, + 0x739f63e05de1e17bL,0xaa95f30735d2b566L,0xf20dd093650236a9L } }, + /* 20 << 91 */ + { { 0xd648dd79ee45d4b1L,0x0ceeaa64c2bc2f0aL,0x695f3a3f491a2862L, + 0x4c07e2e0ce497e3dL,0x5c53879969c766c2L,0x3f856a2e4c4a7c14L }, + { 0xbf8a6d81038032a9L,0xbeaadd7f45b7c960L,0x78b22e85d50b9d26L, + 0xac1c56fa7eaefe26L,0x21fbce54fc69f13dL,0x37be1b47512a3708L } }, + /* 21 << 91 */ + { { 0x12845d55689429afL,0x7e20f0f9082c8ac8L,0xe1615340249773b6L, + 0xf66c39638d0f35afL,0x4a20ce6d67d27093L,0x1d462f08e55802caL }, + { 0x66f209849ff4dd67L,0x6b86f8d8271c57b3L,0x8701a5cde766b85bL, + 0x50737ac2eea5fbfaL,0xb46ebb42a702f3d6L,0xf853091d999258bcL } }, + /* 22 << 91 */ + { { 0x0ce992198c9e7869L,0x653006be525c4adaL,0x783620e4330c402dL, + 0x185a6ac833b728b5L,0xa297c4a99d390886L,0x547d1db5db4b8123L }, + { 0xccf12f071acdb039L,0xe89c5866078ddc28L,0x3460cbb1e52c383fL, + 0x7a4d1beaad25b82cL,0x21e243fdb429be1bL,0x5aa85c25bdc0d798L } }, + /* 23 << 91 */ + { { 0x76cf73b9c0db9d16L,0x45e57cdc1970ace6L,0x3c6f5314c54a109aL, + 0xe32306f7da47cbfbL,0xb3787bdf93e76516L,0x68aa80084c6d4e22L }, + { 0xd9246ddcb3d37be7L,0x6de2bb4d7000f1abL,0xda02568b67e4751dL, + 0x3ed7a5615c7f88f4L,0x5f05c828ca5116caL,0x139cc5772a2ebb9aL } }, + /* 24 << 91 */ + { { 0xc983afb64cb8d897L,0x7f05e954b14cc152L,0x587fe71e0f4d02f5L, + 0xaaa43167531b0cd8L,0xf69452727a26def9L,0x7ecf1e563bab50e2L }, + { 0x04b6f5c94c6f20abL,0xbc6cec2b893b497bL,0x79e89567c9dc548aL, + 0xa39a0a567a40b749L,0xf1531e2644bd4efaL,0x14cdd759057c7c70L } }, + /* 25 << 91 */ + { { 0x30c49847d6d51bbbL,0x70b744feecdc6aeaL,0x38cdf36fe8671744L, + 0x5834286b8cf6461fL,0xf3414f7b2c09d632L,0x58425e4d5debb923L }, + { 0x8bd79117a6b96c6bL,0xecf9802680f56fa8L,0x5ae917d7e6dcbbf8L, + 0xf2d80fb169240a4bL,0x005ac47596e3aa3aL,0xe5196a3463536aa9L } }, + /* 26 << 91 */ + { { 0x5fb02929811d42bdL,0xd7d1b956289929b4L,0xfd3546947e531627L, + 0xa37c9b1e58c2b2e2L,0xf30ed0f902bf499bL,0x3fe80d240eb6df36L }, + { 0xf96270e57b148672L,0x47362483647f48d8L,0xc279ece6c29bc59cL, + 0xc05c1d9ffdd7e628L,0xef8fc92e17568a7eL,0xd65fe5a9ec0e7f00L } }, + /* 27 << 91 */ + { { 0x0ad31de68c93f010L,0x151b1405945ec54cL,0x325d132c3db6997cL, + 0xbed9cb3a335531e7L,0xa83932c34a578610L,0xd905abbf6f721147L }, + { 0x6dd45af086d1d919L,0x2b2ee3090195e91bL,0x3dc30d5edb70d257L, + 0xfb04b014481bde1aL,0xc2ac3ec82de2debeL,0xc9f161e090db691eL } }, + /* 28 << 91 */ + { { 0x8041f112afefdee1L,0x8cab3c86b891f668L,0x1f18774e2b61e754L, + 0xf0d81b2459df567cL,0x2cc25da41c95e1ecL,0x315b1b1ac735d39eL }, + { 0xd0a9b9fb010734cfL,0xeefc0398c79386daL,0x49ce859b11fb1917L, + 0x3d66fd6baf167239L,0x2522b0ef1fea6175L,0x1a27657d3ec4a52dL } }, + /* 29 << 91 */ + { { 0x89ec003abb2ca05dL,0x2290b5f403195ec6L,0x9989bd925f6b95b5L, + 0x1d6e6b2fad409cd9L,0x41f9b9ce3bfe7364L,0xb240f89570ec096cL }, + { 0xf8725a58b8d5a5d6L,0x3bfec6f1c581930dL,0xc93e290356235c98L, + 0x82af4269c7cdcb5cL,0xeb13fa40eea6fe91L,0x9247050097c80acdL } }, + /* 30 << 91 */ + { { 0x48dc23534ded5b58L,0x1b69590756e707caL,0xbbcb73927ec7794fL, + 0x3714dfa6e50dbcc8L,0x4f8083c8f27ec5d7L,0x6358d2273bc8c3e4L }, + { 0xe0c2a0e7656cf184L,0x3996e0a24244d801L,0xa46767b54e543c01L, + 0xbf55776d965f1e2fL,0xeb66845e6bc872eeL,0x6a73fef1b441895cL } }, + /* 31 << 91 */ + { { 0x21602e432b26bbf2L,0x6092d570d1bfd7e2L,0x2b48d74a30b38d1fL, + 0x4aab113c67c53791L,0xa6acbd3df57be611L,0x53b6509ebd3aae7eL }, + { 0x047e5ab4d8751f49L,0x978ed11b0cf25652L,0x763553d2153619c7L, + 0xc7e85e93d824d943L,0xb82cc9781048a7ebL,0x7beb9166e39cc777L } }, + /* 32 << 91 */ + { { 0x24480c57f26feef9L,0xc31a26943a0e1240L,0x735002c3273e2bc7L, + 0x8c42e9c53ef1ed4cL,0x028babf67f4948e8L,0x6a502f438a978632L }, + { 0xf5f13a46b74536feL,0x1d218babd8a9f0ebL,0x30f36bcc37232768L, + 0xc5317b31576e8c18L,0xef1d57a69bbcb766L,0x917c4930b3e3d4dcL } }, + /* 33 << 91 */ + { { 0xf6625ac0b9a038e8L,0x954056eb2a921e56L,0x7135295aeac07bc6L, + 0xedde9c39f1ba0ea8L,0x628324026b592655L,0x4603177aefb8aa66L }, + { 0x63e5ea16406a6c28L,0x5897fdee1c758382L,0x515e49fd415533c9L, + 0x0a0dd627d6701b21L,0xd7c06db1c93a312eL,0x4fe95e3da33d8df7L } }, + /* 34 << 91 */ + { { 0xf113d92c3336edc5L,0x0a201f3e8ce47278L,0x57492feb5c52562fL, + 0x18b73800f29da837L,0x2262089f649a1ee8L,0x076b07657c99bf48L }, + { 0xa95050bc09bfad20L,0x5aeaa9088c7e713cL,0x264283ed3cda06ccL, + 0x5d574b116079b43dL,0x0071495cced10a84L,0x97441fb0570d3063L } }, + /* 35 << 91 */ + { { 0x340831072b228335L,0x84ea0aba50fbd43dL,0xafde6098b3ec91e4L, + 0x4fd293ca1091ad93L,0xee085e23552a785bL,0x437d799ed7057200L }, + { 0x41f735628a611ff4L,0x707a7cb5d2ef6254L,0xa9a8f00092a30686L, + 0x901cc8e60cea8d1dL,0x1fbc9ca6d6da2ddcL,0x61bcee2176489604L } }, + /* 36 << 91 */ + { { 0x5f6ef134781a7f53L,0xbac4cf47b10a9d16L,0x48148ba110e69f4eL, + 0x40594360a9c615f0L,0x3141817ddfb3fc58L,0xb9579a9263c38d83L }, + { 0x0544b1bb6373b9aeL,0x718a5fb7007c8185L,0x48d4a4f77cfa392aL, + 0x9c16cb825d44ba38L,0xc83d2df42a8fa83fL,0x835aacccc08fef0cL } }, + /* 37 << 91 */ + { { 0x09ce1818af09fefdL,0xd1d2f95f5dd9d687L,0x94ed08b5495c4eaaL, + 0xd1afff464a0b95d2L,0xd51ba2b455347a75L,0x413126295e3866edL }, + { 0xeef2d7e3cdd37660L,0x50e6fbdfec2fe50dL,0x9d071e18a664e2eeL, + 0xe70e1d9ed6a8f467L,0x576d0cc4e13afc19L,0x67ced86da0efc220L } }, + /* 38 << 91 */ + { { 0xa26968cb26a963daL,0x461d1ab5cecbd96bL,0x8eaa1834b3e38516L, + 0x1e92730f05d2cd2bL,0x91112026b07cbf92L,0x26eb815062374314L }, + { 0xa904f1d08ab1b9d1L,0x52006594692b1905L,0xc9cc90ca6ba4717dL, + 0x4bd7300aaad1c74fL,0x67ba07a4c21c5832L,0xdebfd810fa56a1a8L } }, + /* 39 << 91 */ + { { 0x3bc5aaf484539b6bL,0x6ca9ac0c0d1249aeL,0xb59da22db4ee30c8L, + 0x6e62553e57149c9cL,0x46db0089786333cdL,0xe1e2ae523e4c12ceL }, + { 0xf828d2b537b3fd82L,0x31844a9d03af654cL,0x85dd8daaea5a4677L, + 0x0db99b8f3432e82fL,0x99383b874866e1b6L,0x52310054e325b0c2L } }, + /* 40 << 91 */ + { { 0x737cd387044854f9L,0x488b2fd667eb29c2L,0xe71d9bb7258c5a80L, + 0x21afb486ac71048eL,0x0252b540d4d39296L,0xe3e52cb87839d8fdL }, + { 0x5cb1100667ea0afbL,0x207637d1de82b12bL,0x77920933e93bcfcdL, + 0x65197f5df32f636dL,0x82179527b6c41411L,0x7696a479f410c989L } }, + /* 41 << 91 */ + { { 0x78307cd80e8d576cL,0x10d3b950fd9d6044L,0x2c2f9e2bf4b20445L, + 0x961343c72c5c7ea7L,0x931c52a0af640e61L,0x45557391470d420bL }, + { 0x4096a997317f4d26L,0x15210801cceb9be5L,0x228102195ff0759dL, + 0xc388a2d21d265932L,0xceb79d01e86dd99bL,0x23e8fc7b3311dcb3L } }, + /* 42 << 91 */ + { { 0x1a7d0e091d7743eeL,0x18720797d53e4a8dL,0x78465f1ea04dbaa1L, + 0xd4f064da9ce65723L,0xc0e7c035b496e8d4L,0x25657d2e6bb2f9ebL }, + { 0x45576ab49f4b6cb5L,0x83983c70ba33d6dfL,0xf699e84d1eca62a4L, + 0x35528636a13f5c31L,0x6a1b56b01f6b1739L,0x7906eccc6ea87942L } }, + /* 43 << 91 */ + { { 0x4e584a4fec1204a5L,0xd96b00e845a5b311L,0xea11fb03030badccL, + 0x9b2141b2a825a89aL,0x18bbc30bf8b2450dL,0x87bd93916513b2cdL }, + { 0xb3dbde552f0b304dL,0x762f3dd7c3c4817bL,0xe51e1733edd3fdd8L, + 0xddad4c515d8219a2L,0xf5a8c0b8796b6877L,0x34563a8989bf65c8L } }, + /* 44 << 91 */ + { { 0x93e2e3a2881c106eL,0xa227cc49fe82afd8L,0x6fee74a4748e81f3L, + 0xb212e8eaa5dd966cL,0x68d270efdc7d8883L,0xef2f3966fe757e9eL }, + { 0x0340098b7466881eL,0x7ab98a0575884bbfL,0x24783467a472f62fL, + 0xc73cb49f988637d9L,0x2b5e9d27dfb710c9L,0x503f9a2f788fcb18L } }, + /* 45 << 91 */ + { { 0xcba6f4631a52b729L,0x8874582cc8be34cfL,0x98a08e246a9a1eaaL, + 0x77094319d5693f71L,0x575a0938a8504e5cL,0x3f59910c226f888eL }, + { 0x5c3587990aeeb1f1L,0x7c32821d3613bbc5L,0x66f288e7cc17db95L, + 0x6f3221998724ac94L,0x4e3fa38981db3751L,0xa6e798c8420403baL } }, + /* 46 << 91 */ + { { 0x56672f2e2cbea2e8L,0xd1a02df9128bd636L,0xff6a3bc6d47a0025L, + 0x24124f30d38d0b42L,0x89ac3b8dda63df29L,0xf26d72994d0b6458L }, + { 0xfff0445f7d6880bcL,0xface90f52be76351L,0xbf10c6b8ebffb74fL, + 0x0e53c533a1fba003L,0x037baf09112f4980L,0xb8ae6312be960954L } }, + /* 47 << 91 */ + { { 0x8397b60917270d4aL,0xb4d0c38700e4caeaL,0x69c52bb3f4c58f86L, + 0x06e0e01157b1fd41L,0xc5dc2f25627873a2L,0x9af848ca0ae53974L }, + { 0xb5c957c06ad18335L,0x93b564154ef09e7bL,0xb5ba282450e2c5ccL, + 0x63f003a567d7b68bL,0x0bcb0dc820bcbca3L,0x8803b1ffe3d4296aL } }, + /* 48 << 91 */ + { { 0xff41d51faae4bfd4L,0xcf50b14117c44facL,0x078b808e657a1ea4L, + 0xc5aac1a893c00c55L,0xcb99cfd0cc4d1c0fL,0x1d1048933fa123a6L }, + { 0x49646059023ca92fL,0x5833e326f3982134L,0x2e0d4bc9c5781cddL, + 0x5f7f84ed8d5e75f5L,0xb6655f1fe1e8a383L,0xcc18514c296e4943L } }, + /* 49 << 91 */ + { { 0x5d3e5f8d8a407ff0L,0x9c713c8c7b42b11cL,0x7433a9921e387806L, + 0x5272b92a98cb43acL,0x6261dfc1b1018149L,0x229d2ba5d3b4adf4L }, + { 0x1f52e72989f0905fL,0x965e062925d4c79cL,0x42edaeeb33e6c016L, + 0x5ec492e8af1709adL,0xaad39616c5763619L,0x85a659098c666860L } }, + /* 50 << 91 */ + { { 0xec8fe7dc86009df6L,0x42dd3c37871b20a6L,0xe4388c920db643e4L, + 0xcc5dfdd481e06dbdL,0x3f1a3c6458ca7500L,0x987d7caa22c04e9dL }, + { 0xd0c91072bc5717e2L,0x3f605fd2e77e5509L,0xa1cc1404c0c3e95eL, + 0x4afaa9fdc6d0edd0L,0x2f3aba4e0d7d882dL,0x3f1f0349796c5ac0L } }, + /* 51 << 91 */ + { { 0x5dac93982eeb82e8L,0x2fe5ffb57536ce1eL,0x2bb120ac6926cfceL, + 0xe54ff20f2236dbf0L,0xaaf0d31edf8c5a87L,0x5262fb9fc8f5df7aL }, + { 0x0f833760467092bcL,0x50fa223d0a8dc0afL,0xd6a4847d35406966L, + 0xd17d6ce003b7f56bL,0x8067d8e2ee2d64bdL,0xe33e51bb9fa4fe9bL } }, + /* 52 << 91 */ + { { 0x52aa210770248e4eL,0x30cf7e773b6bf709L,0x36961c7b788e1836L, + 0xbe49de5f7595af2bL,0x86b49b619cbcba78L,0x1947db3790cf1117L }, + { 0x7d3f599de14b4287L,0x14546993f0ca62ebL,0x0f6c8872d0abde7aL, + 0x1531ceeaafe2260fL,0x36449624ae5ecf96L,0x6cfa12a5840bdc19L } }, + /* 53 << 91 */ + { { 0xb092ad68c1d612b5L,0x9f6052507af5c37dL,0xf48aa7c6c702b673L, + 0x380144215cd29c3bL,0x7b09e407121867ecL,0xf71443d391e59047L }, + { 0xea51e1a6b6d16a51L,0x041fa7650f33e2ccL,0x3a6d50c73750dce3L, + 0xeebf5c2e97cb7a7dL,0x2530de228f39e771L,0x9af217c18f37f863L } }, + /* 54 << 91 */ + { { 0x38793fd0c683085cL,0x49cc5934dc436d16L,0x94c708e4175e770eL, + 0x41bfb65d059c2682L,0xf6b83eb75f004ddeL,0xe1881929f6864410L }, + { 0xfaa77fe0b438f937L,0x97a856069997e90dL,0x78366a9108de889aL, + 0x6c28ef64553229cdL,0xfce82c2fe9381854L,0xae98117146f70bb1L } }, + /* 55 << 91 */ + { { 0x3f77410e9aacedd8L,0x0e34bd7d453813e4L,0xc5818436825d6b0dL, + 0x0e30f037b4d0ac73L,0x70f6bc9b69b559c5L,0x68d3d71eaed15484L }, + { 0xd0254e5414fbae1eL,0x6ddaad42ae0d3df6L,0xefb91a545a6e98d0L, + 0xde3fcefc854ee5fdL,0xb2f0f3a1dfa2a8a0L,0xb656f97ad00ded3aL } }, + /* 56 << 91 */ + { { 0x01acfa7e0a90e37fL,0xf47e5946366d0ba0L,0x8e37db7b54c11845L, + 0x5742d8bd50a62064L,0x27dc9a33ed6d096cL,0x2246d73016deb724L }, + { 0x203c08da2c8f1a85L,0x210cda3a56fea379L,0xea6b1bbf2bf9ed67L, + 0xe5a1e5552395cc4bL,0x458a7e19de2d6b2fL,0xa7199a86734942a3L } }, + /* 57 << 91 */ + { { 0x53684c23d44cad85L,0xd23613f8940779a5L,0xf485c7a3940bd34cL, + 0x64c66a1f3f673b5eL,0xec29c76f1d6dd63cL,0xe10f56272f191435L }, + { 0xc054f9a7325d5759L,0xe6740d3f974edaf5L,0x2723ac6103f3b640L, + 0x0a2315a4576e0bbeL,0xf8156e1e4a3ec903L,0xa307bc249bbc8c52L } }, + /* 58 << 91 */ + { { 0x78579ca212a1687aL,0x208b7494268a02a2L,0x61708a002c1c5243L, + 0xca366915a760461eL,0x0e9038fe3ca1e167L,0x2cfd6fe3a58e2c57L }, + { 0x97c16e34fe79a49cL,0x1575244ef08e4037L,0xc1407fa08e2283edL, + 0x38ae77621b057919L,0xcec574a5e68a366dL,0xafdfdce03eff00d4L } }, + /* 59 << 91 */ + { { 0xdad0dca9162d80c6L,0x554141f8b888ea0fL,0x1e471b24d4036218L, + 0xafca22cfb36102d0L,0x437c51bff280dfa8L,0xc2c8bc8b50c9c30cL }, + { 0xe7bacc372a9fdf6dL,0xd01dc65cf0472f2dL,0xaca59cf983d7be3eL, + 0xf7c935425d9ec484L,0xc22046c6015a08a1L,0xa71b3c64cecdf816L } }, + /* 60 << 91 */ + { { 0x4b7d0b277abe7856L,0xe566f4567acdb39cL,0x70c6cdf20047ae7dL, + 0xd27f831233ed0392L,0x498f0ad0358a429dL,0xed97c4668e6ee95dL }, + { 0x3d11cd69f3018515L,0xedd460344c1b367bL,0xd75660e3b3ac8ec6L, + 0xc80dfc0fa541e6e1L,0x80026f005c091a6eL,0x62b86784c426f2bbL } }, + /* 61 << 91 */ + { { 0x417408e529ee8eb4L,0xe92f18c2917f9951L,0x1f471f0eb38b6210L, + 0x53cb14264df240f3L,0xeaf7fc0067c29b25L,0xbbf46fd3d99cb613L }, + { 0x05cd552eb465b50dL,0x136b8e675e136733L,0xd7d50f61ccf61776L, + 0x90187ec5a32b01f4L,0x21548ec523ba232aL,0x6c8266c0748e558aL } }, + /* 62 << 91 */ + { { 0x762f413d7650470dL,0x9b4af5d018c9ad5dL,0x85fe90460ea625a0L, + 0x4af4511b2200cadbL,0x4c16980defec2921L,0x42ae5d5d60dbe1a0L }, + { 0x0785260bbb2ceb1bL,0xd181ea3242f1fb7bL,0xc34f02b13a47672bL, + 0xb0bc79f770e58634L,0x6e7967098a8509aaL,0x05870e6f3c3e6d44L } }, + /* 63 << 91 */ + { { 0x46d4fef752f7c595L,0x5f35083a8a07819cL,0xbba477ca591233ddL, + 0x4e66309358e307deL,0x65c3e2b9ef827537L,0xcf7b7adb09ee9adaL }, + { 0x00a82d4b5f5e1434L,0xd6aecb8032e50afcL,0xffdce7ce6b034271L, + 0xa95d96ae036d5058L,0x61582ae24cb7d60bL,0x6a10577474139c1bL } }, + /* 64 << 91 */ + { { 0x53ebbaaeb475d8f3L,0x3d6ea31cff76bedaL,0x3c15f25d340986b4L, + 0xc5925d2e3365312aL,0xc35d3ee251641f96L,0x11eb2f75984128e4L }, + { 0xb41a21a83d04bc99L,0xf2d286006436c3d0L,0x4ffcf4c0faf5663cL, + 0x889d285a0a62c9dcL,0x0908665acb2d60c5L,0xe2f19c590a131be5L } }, + /* 0 << 98 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 98 */ + { { 0xc0de60f5091354ffL,0xd7cc38bba1bd1975L,0xf4122aa8e734e2dfL, + 0x08f40f63ef773db6L,0x0a7e9484ce2d71c5L,0xcc79173378a3f825L }, + { 0x0cac7a5bb47beec9L,0x1cbea0e4a3f7b5b6L,0xecf19a90d3e18145L, + 0x0d1b062a0aadf689L,0x42299f1ff3f0acf7L,0x63a645395ac252b9L } }, + /* 2 << 98 */ + { { 0x44bfd1665c1d4586L,0x46434e198d1d86d6L,0xe50fcf81c3936683L, + 0xc9b4eb068b08680fL,0xf90882c52832aab0L,0x42823cefecbf5ddaL }, + { 0xfd4d51c744ae08f0L,0xb54a08f1bbd21c1cL,0xb72953dbfb187c34L, + 0x166f7f26f8ed037fL,0xd2b1077a097bad45L,0x47794cdc790dd808L } }, + /* 3 << 98 */ + { { 0xfadb2ac4bac8b691L,0xf0c5a0361579c4d1L,0xa192474f79019224L, + 0x8c7a64574117a323L,0xe58122dd84d970a9L,0xc475893c0bf77208L }, + { 0x9518412f1bd45c95L,0x75bd0a72283f7a3bL,0xa9e871605fb7e6f1L, + 0x14d3c944df67acedL,0xbceea947d0348c22L,0x5331c192d021aba4L } }, + /* 4 << 98 */ + { { 0xa05c751cd1d1b007L,0x016c213b0213e478L,0x9c56e26cf4c98feeL, + 0x6084f8b9e7b3a7c7L,0xa0b042f6decc1646L,0x4a6f3c1afbf3a0bcL }, + { 0x94524c2c51c9f909L,0xf3b3ad403a6d3748L,0x18792d6e7ce1f9f5L, + 0x8ebc2fd7fc0c34faL,0x032a9f41780a1693L,0x34f9801e56a60019L } }, + /* 5 << 98 */ + { { 0x35df68ae1a504405L,0xe41d69508fc755b9L,0x420dc1cda6297243L, + 0x3011646b913fb68fL,0xc4b630465e141a27L,0x943b3b3bbd91fe5fL }, + { 0x3ca17d6b50c31708L,0xce88b5e74ffa8c71L,0x8b60038f4dacd2bcL, + 0xdf654d723c13cf9bL,0xb5353e281d871b40L,0xc2d27919226663d3L } }, + /* 6 << 98 */ + { { 0xa028d2fa9b87715fL,0x7cdd9b4a453625bdL,0xc8afb1890be3dacfL, + 0x40289a3a274c4e2eL,0x7f5f9f7677c6bbadL,0x577c0935bdfeaccaL }, + { 0x5f838f0404281989L,0x8650a974ebfa410dL,0x414fab6dcd56dea6L, + 0x6995cae292eed440L,0x3b474d27ab146e15L,0xe24262b2e9938f84L } }, + /* 7 << 98 */ + { { 0x649e18fba34fb18bL,0xa4883af898cc69d3L,0xff46285f3fd56e37L, + 0x2e28ccc4557c0c04L,0x8388dee821a9b46bL,0x0fd4fb807ba3a6deL }, + { 0x1d8e9da7c62bb315L,0xfa7bd70d06e44230L,0x2840122063320438L, + 0xeefabd47d06c0654L,0xf4387b08d4c8c10fL,0x8f2694624ff2142cL } }, + /* 8 << 98 */ + { { 0xa4b957d262c36887L,0xaf15a485fc24cff8L,0x11575e80a271d9e0L, + 0x0fff68d44b9367e5L,0xf55ba6732279779fL,0x9d72cca6d4d68f68L }, + { 0x01474ab1590ffe4cL,0xd20f44e1074d634bL,0x63903a8336111d25L, + 0x37342a5fab531cefL,0xd3c93fe7702ed867L,0x05d143696279f7e1L } }, + /* 9 << 98 */ + { { 0xcddf64873e942b27L,0x9e29835a2bc21472L,0x924c2bfb2d2195e3L, + 0xdf4a3cd38eca6d9bL,0x7fe6acd1c5be60c3L,0xa3abee9cfc38025fL }, + { 0x014f0d992f449934L,0x8d72657a78860127L,0x92514cb948d84cfcL, + 0x8bd4ac503aadd70cL,0x3c96ee00136620d7L,0xa0caeeb54efc5e57L } }, + /* 10 << 98 */ + { { 0x7a65cdf5bd200ed6L,0x72dc1b5f0e4b1c68L,0x9c09576a6ddf540bL, + 0x358dcd122b169da2L,0x6466f0e81639b734L,0xa1429a6ef14c6eb6L }, + { 0x4b3d781943221168L,0xfe3d2fdaf3b74fceL,0xb22bcec2ae26014bL, + 0xa8900e7ace7e789cL,0x9db9af67220bce88L,0x1f86d2e4fb8ee34dL } }, + /* 11 << 98 */ + { { 0x6f8e1c0bf8c65293L,0x66f44ea04d7a5dfbL,0x2c3cacac741fdc1fL, + 0x72e58aae239f5f16L,0x50dbaf192f72d8c8L,0x24ee526628c97b95L }, + { 0xdb5f7827ab3ecb17L,0x2c567337669b05c5L,0x78c97eb8ff76ccdcL, + 0x1de1b4a3f8d2c990L,0x5b183974e6138df5L,0x61b74177aa1a1019L } }, + /* 12 << 98 */ + { { 0xb398290cf0db3751L,0x01170580ba42c976L,0x3e71aa2956560b89L, + 0x80817aac50e6647bL,0x35c833ada0be42daL,0xfa3c6148f1baba4eL }, + { 0xc57be645cd8f6253L,0x77cee46bc657ad0dL,0x830077310defd908L, + 0x92fe9bce899cba56L,0x48450ec4bceffb5aL,0xe615148df2f5f4bfL } }, + /* 13 << 98 */ + { { 0xcc14267f6be1860dL,0x3de7f48b4ffedea1L,0x8252694e5b776b87L, + 0x478c877890dd427fL,0x913e19a675a21357L,0x882f2d5ac078bd79L }, + { 0xf442752184c565dcL,0xd772147e3ac3ed26L,0xf21abc752fa216b6L, + 0xab1804ad305ff0dfL,0x10d89a07920c977bL,0x0a2240dc4fda6075L } }, + /* 14 << 98 */ + { { 0x7068e6b98653bfadL,0x16b0da9b8f4397e8L,0x77b953b4946bb9c6L, + 0x08366ad749b036f5L,0xd219117b26a3913dL,0xbe3607949a5460d2L }, + { 0x1a4acf6dfadd462eL,0x1f7de879c32f3550L,0x11117132669c9b2eL, + 0x1deea7d1c87ca216L,0xa88c90c748a058d2L,0x0d8e6afff403ef36L } }, + /* 15 << 98 */ + { { 0x21f6c96c1ad77f33L,0xb5da9d34992e7807L,0x17fc994ba7192adfL, + 0x59f204fcbcc3f8b2L,0x3f4a970f10bd22f5L,0x42936bfcbaa1188dL }, + { 0x6239fea5eb985837L,0x5fde15e0b33d1158L,0xe0bbe9b800cf90b2L, + 0xf2c6d8b16b2b68a8L,0x58c331cd0f3a2341L,0xe951c48910dab1a4L } }, + /* 16 << 98 */ + { { 0xdccf68bccbaf4685L,0xb333e464270a2bccL,0xe43ae199254dd3e3L, + 0xe8526e26ddce5c84L,0x52bad815ea0b4258L,0x67c12c1b094574c4L }, + { 0xa5362fcb861545b7L,0x3e904c35c2b2eb62L,0x0f9312b5eeffc2cdL, + 0x5475657b14de4e5bL,0x746e67d4f0233fa5L,0xb5157d7f35471ec2L } }, + /* 17 << 98 */ + { { 0xcbaf92265315e83aL,0xcc6e9a972f15ff37L,0xcac446dde8c87fb1L, + 0x5fa37a5c672d7f92L,0xe66efc07b1380425L,0x2d8ed2e32c8e59ebL }, + { 0x8e3ab80461743725L,0xe59a87f825493349L,0xf6995fe16062fe7eL, + 0x5d7f8a646e8de27cL,0x4a5ecbbbebe084f2L,0x99fc5ea93f863156L } }, + /* 18 << 98 */ + { { 0x1ddede1b495fdc2eL,0x3dfcf56b039d6339L,0x54c423806a56c492L, + 0xe6bfd184def6446fL,0xfaa2fa123ac841beL,0x503e319a4f9330a4L }, + { 0xd9305d4654ad427eL,0x68d23497d95dfcc8L,0x2d935aad1e9602f5L, + 0xd7e74bf2e33174a9L,0xc8e4a0b17225e2b5L,0x5db7187cbcda5221L } }, + /* 19 << 98 */ + { { 0x9a0e0908b0ec0b27L,0x28894b2edd759131L,0x0107bb592b9d6f02L, + 0x318921deeea022f7L,0xa1a00f5882c73390L,0x877833129551b381L }, + { 0xff866039a3a9dd22L,0xa59235ffdf0fc09eL,0x530c2fe61ca647f4L, + 0x77b1ea2860f9428bL,0xeef2a9e6bba4bbabL,0xdbdbe037204f5ea3L } }, + /* 20 << 98 */ + { { 0xf55edabb90b86166L,0x27f7d784075430a2L,0xf53e822b9bf17161L, + 0x4a5b3b93afe808dcL,0x590bbbded7272f55L,0x233d63faeaea79a1L }, + { 0xd7042beafe1eba07L,0xd2b9aea010750d7eL,0xd8d1e69031078aa5L, + 0x9e837f187e37bc8bL,0x9558ff4f85008975L,0x93edb837421fe867L } }, + /* 21 << 98 */ + { { 0xf87a92375b2e5fa6L,0x88571e4452a3a605L,0xf85e9a330c8f5f55L, + 0xf99886c599dc2c97L,0x5866329d065261daL,0x9011f13912dd434cL }, + { 0x0cc67d535284c555L,0xf8f715274a4032caL,0x4b002683a9524bcaL, + 0x3c3c12910f63a7baL,0xd19e173e9124eb8cL,0x3431c51c54b7d85aL } }, + /* 22 << 98 */ + { { 0x7103ab4ae11cc85bL,0x2064ca41789cf87eL,0x592850ead5f13a08L, + 0x56b9ff066212e096L,0xa106455d6efa7445L,0x3e62aac92343c5efL }, + { 0x7edbf70dcb8ddf7dL,0x27f00a4a5f2687e4L,0x7d4ce32e44a08d11L, + 0xe97f0910890a57f1L,0x792597fb912cb027L,0x1fa7a1d2ad3492dfL } }, + /* 23 << 98 */ + { { 0xbf4e161c3cfad317L,0xda4e6bffa1998bc8L,0x6534ef622e890b99L, + 0xd10a3b24d272cc42L,0x3f81b0e5f1194dabL,0x8919caefec549c5cL }, + { 0x847ef47f68f5633dL,0x01cd59975468f4afL,0xc38bce29b6727408L, + 0x56a1cd1ea4c84268L,0x31a493f406b81088L,0x4461ce8531b37e73L } }, + /* 24 << 98 */ + { { 0x3503d9371f23a0d8L,0x64c598a8c321dde0L,0x67f101ef5b52e0f0L, + 0xb6b5b4c2f955b5faL,0xb5f03d53880e0569L,0x121c3ac1c99393efL }, + { 0x90755bd657330666L,0x70ae5793d4d71d3dL,0x326ffd519e9ce792L, + 0x1b772d7396ccfa14L,0x652710f4874a22deL,0x72768469db210342L } }, + /* 25 << 98 */ + { { 0xb2d85722b3413d7fL,0x4e41362092e55ea5L,0xad1a20c7ff7b3409L, + 0x743b31c0c6f98cbeL,0x1b5b0b5adab3810aL,0x628d9b212cea0428L }, + { 0xa3e24294b0335ba0L,0xa9c0e139487530a7L,0x54199640072e70eeL, + 0x0977586e64c0d563L,0x393878451c5cce35L,0x57acd85631ce1eeeL } }, + /* 26 << 98 */ + { { 0x63081bcf9b8d9f3aL,0xb09fe52b6f94e3e9L,0xc232e5d1e39c092bL, + 0xd61ddcccf5f072e4L,0xcdb3b4189a26a93cL,0x0c010c048de6f5c9L }, + { 0xad2473a5d238e823L,0x4120ab3632029ca0L,0xd6632edb639bb8ddL, + 0x3383f077a8b32fe4L,0x8afcbce5eacfbe80L,0xe28236212d2fff74L } }, + /* 27 << 98 */ + { { 0xccf2a24a0eb3829bL,0xdd8fe4421eae0751L,0xb685b073c9598d91L, + 0x025214ce8b308785L,0x11c3fb11d6433acdL,0xe40cf39c81794024L }, + { 0xa167651b1c0b1f54L,0x350cf3eb0bbde983L,0x69c93dd0b2a88c48L, + 0xf13afc37bee80b26L,0x0be7d05d776345e2L,0x1ccbc8ba7645b02bL } }, + /* 28 << 98 */ + { { 0xaa6489df83d55b5aL,0xea092e4986bf27f7L,0x4d8943a95fa2efecL, + 0xc9baae53720e1a8cL,0xc055444b95a4f8a3L,0x93bd01e8a7c1206bL }, + { 0xd97765b6714a27dfL,0xd622d954193f1b16L,0x115cc35af1503b15L, + 0x1dd5359fa9fa21f8L,0x197c32996dfed1f1L,0xdee8b7c9f77f2679L } }, + /* 29 << 98 */ + { { 0x2aa349975442c668L,0x4c5137130cd74444L,0x4f87be0f449300ecL, + 0x13e07b552bae04fdL,0x6aa575d11f75acf6L,0x4502e9e9852848a9L }, + { 0x3c246d38889666fcL,0xb6c0292b7c100867L,0x618f234aa2a280e0L, + 0xf983c834669afe62L,0xc51a15105d900a1fL,0x7d7ce31bc952f419L } }, + /* 30 << 98 */ + { { 0xe3dbb7483c3388dfL,0xc26a7d042c32f139L,0xc1b48180ed938dcdL, + 0x785b964d42e4c01cL,0x507cd16aa1f75e28L,0xfaabff8d1f323caaL }, + { 0xc6bc47ceadd5b649L,0x997dc0ee3c0aed28L,0xcef0c89bf3666cfeL, + 0xd8d7dfb426482ea7L,0x5f00e432d2348484L,0x09549b5a1dc66aa6L } }, + /* 31 << 98 */ + { { 0x702e450ef8464b1eL,0x52d20765a061c4c6L,0xe1c930b26519bfc6L, + 0xa9c0c8c6d17ea02dL,0x52bfc60ddac62461L,0xc325568f7c5f9a55L }, + { 0xe7413df9eb44b9d7L,0x461682265837e0d1L,0xfcb9628c15aa0c89L, + 0x83d6d0eebb57c6a3L,0x17bb82a56829c9fbL,0x342fe91c496861e0L } }, + /* 32 << 98 */ + { { 0x58d6998e171c1439L,0xfd4a98f401feedecL,0x420b2a0165739fceL, + 0x5c5db30822f7a073L,0x016c547805042f00L,0x5fc73ce2a12413d9L }, + { 0x8ceb2d70e932aa17L,0xb4d66b670537afafL,0x2638d012339c146bL, + 0x02fbb7b628ac0555L,0x7fcb0c8162d46e63L,0xeaa9ff4f066d088eL } }, + /* 33 << 98 */ + { { 0x45f53090b8b22c29L,0x155b8f8111e70d5aL,0x5ec118b25d3a7d83L, + 0xfe4c7eb39c4ddd1aL,0x8cdfb753f226d869L,0x20bb870779fc646bL }, + { 0x3c8c1d7a25d1308cL,0x5a976ae47116f347L,0x6af949a60faf9690L, + 0x7e6718fc07f3472fL,0x16ec7b45267b17cbL,0x80744641cebe1bd7L } }, + /* 34 << 98 */ + { { 0x45eded7ab2a5c8e3L,0x4308485969a0681bL,0x89b7510d90910e8bL, + 0x1c622d04d2066d92L,0xdc3b434bcd2f0d7cL,0x98bcb83b476ea5a3L }, + { 0x9195431d3dbf2be5L,0xfec7efd969275ac5L,0x6a4364f556a7da4dL, + 0xaf701bc579c177ccL,0xb77ef33e9ffc2a47L,0x2bc59331cc23c4e4L } }, + /* 35 << 98 */ + { { 0xedf4a85b9d43c51fL,0xc0afbcb6b59a7244L,0x3ede2f25626e0ca8L, + 0x45836582270f674dL,0x83c47048bf06d267L,0xbb1e994f3c68314eL }, + { 0x50d79cb4f2fe6c8fL,0x1a1d8aecdf7600f5L,0x216f5d2bef4e4857L, + 0x41361a90bdffb9e9L,0x8040f5c173d2f9caL,0xe6665f0dd1e9be4dL } }, + /* 36 << 98 */ + { { 0x5405179f394fd855L,0xc9d6e24449fdfb33L,0x70ebcab4bd903393L, + 0x0d3a3899a2c56780L,0x012c7256683d1a0aL,0xc688fc8880a48f3bL }, + { 0x180957546f7df527L,0x9e339b4b71315d16L,0x90560c28a956bb12L, + 0x2becea60d42eee8dL,0x82aeb9a750632653L,0xed34353edfa5cd6aL } }, + /* 37 << 98 */ + { { 0xb112fd7b36386e2dL,0x358e974a6a634bd7L,0x509814737faf640aL, + 0x1036bdacef39b3aeL,0x410c6448db5aceb0L,0x914671305bbebe92L }, + { 0x83fabd54e9e009e4L,0xb2da8eea9994d16cL,0x9d73da6356997acdL, + 0xea9158b97ec1b844L,0x8e6a6e3129714795L,0x23e98f57131243f9L } }, + /* 38 << 98 */ + { { 0x7105f727552664dcL,0x97cbfb6c5c589c8cL,0x1a7b110a70fc59b3L, + 0x46c39f2cc754c69dL,0xcda0e2c067b1f17cL,0x35fe45fab7ede210L }, + { 0x6b3ecb7d82e78b40L,0xa90eed4fdbc07241L,0xa73797895aacd533L, + 0x28120ba5f4fa89a2L,0x9c1fc09ee3055006L,0x71e665efc51653a4L } }, + /* 39 << 98 */ + { { 0xcf782247d28b5059L,0x15bef4cb1b89eb06L,0xbc182ed6bcb4afeaL, + 0xcf5b6dfde0e32b77L,0xeb61aff9d9446052L,0x5846f171c4bfc0abL }, + { 0x61d5ae1c6fc68422L,0xa282c56846e870afL,0xdb4859d16bca8fbdL, + 0xd4cd416e97caf135L,0x11217fa9c3debd59L,0x27702da6370758ddL } }, + /* 40 << 98 */ + { { 0x8273db992d189057L,0x4d1b05fce1b5f8ccL,0x5fec7c830a7c32d1L, + 0x28ddaf28ea9b4d45L,0xb6bb62aca2fc58beL,0xfc65b7aa4a41852dL }, + { 0x6e7651941c9e6045L,0x3acabf28fc116257L,0xc9d5e8054b5a4ba8L, + 0x9a072259cbdcf1ebL,0xc67cf643439fc8fcL,0x917ef6f8b4333aa8L } }, + /* 41 << 98 */ + { { 0xee6123cca6411227L,0x91372d080ee882bcL,0x2c30a840a638a4faL, + 0x1867421321e83d4fL,0xc6afa4cfc3fb9925L,0x19aec276e4fdc73fL }, + { 0x1ffec4510cf4e610L,0xac57292ede22d429L,0x62844d78e6cacbc1L, + 0x0eafcc554d2e497cL,0x39f1acc8e780f600L,0xfcf8d914fcff8c6aL } }, + /* 42 << 98 */ + { { 0x0734ab43ff2152d0L,0xe52c5dee930fea54L,0x9cac7efe940bddbfL, + 0x30d2610ddbd43391L,0x4beeb865921c124dL,0xa19fe6a4fca219fcL }, + { 0x588395628755cc47L,0xa7f301241324f2d1L,0x4fe38ee3b1ec5aacL, + 0x3583542eb16413ceL,0xfa92e2191733b7eeL,0xc0f30ba32b2001a4L } }, + /* 43 << 98 */ + { { 0x706b02c3febc7968L,0x6e45dc90c96a6b64L,0x34e5f890f95aa4c7L, + 0x8ae64d487683b855L,0x0fbb9c4a62e03ebaL,0xb32a965ce2cab115L }, + { 0x4a7084a8b33102b4L,0xe7fd9db3ebd1bd6aL,0x2fcb233cc7f32b61L, + 0x365896d5f2549734L,0xa3f18bfd25c7a1c4L,0x382950ef212b8daeL } }, + /* 44 << 98 */ + { { 0x82154d2c91aecce4L,0x312c60705041887fL,0xecf589f3fb9fbd71L, + 0x67660a7db524bde4L,0xe99b029d724acf23L,0xdf06e4af6d1cd891L }, + { 0x07806cb580ee304dL,0x0c70bb9f7443a8f8L,0x01ec341408b0830aL, + 0xfd7b63c35a81510bL,0xe90a0a39453b5f93L,0xab700f8f9bc71725L } }, + /* 45 << 98 */ + { { 0xee2b773e4ed17990L,0x499e83623faab7feL,0xa3925e2f71abb9efL, + 0xfee50406ce3b4a69L,0x71a15070bc10f803L,0x5b01e4a2c7bab10aL }, + { 0x806c590d99e51e36L,0x34adbaf6a7f88d5aL,0xd4a93ce9f6b30ac3L, + 0x39d2cf40dc33fdfbL,0x13e676f1d5e4e7ddL,0xbaa72ab9199690fbL } }, + /* 46 << 98 */ + { { 0x85017690e51b47daL,0x25919b58a2b476ceL,0x6f692de103ec5d55L, + 0xd6cf8ee5d022dcebL,0xaf3225238ba7076eL,0x917b373728c902d5L }, + { 0xac75fddc3fdf8590L,0xe83d9bbb64fc304cL,0x13550de2971f659aL, + 0x70bee07ee12b7bebL,0x9989d2fa0a855646L,0x8b6043aca576b3a1L } }, + /* 47 << 98 */ + { { 0x1bfd4f92fadf9017L,0x1e4509aa737bc67cL,0x88278c3699af1ffaL, + 0xbc47536f4678e22bL,0x69914cdb1b07c823L,0x56fc28ab97277358L }, + { 0x092d28efe752d2f7L,0x6a8286a691da62c5L,0x86b702778033c632L, + 0x57ef284e7672f41fL,0x9101ed302e54007bL,0x53e94cfed25d8d19L } }, + /* 48 << 98 */ + { { 0x311ebba2fc37efedL,0x8a6a42d660cfd6bcL,0xb4051b3af2a4871eL, + 0x66ce77b8c2f0ebf0L,0x84abc9480ad28477L,0xc82e5c6263d9d11aL }, + { 0x99ffc70c007dcf93L,0x5e974edfd964c822L,0x0fee3572513085e3L, + 0xbe67a88046ce8444L,0x136ceeb806d17129L,0x0da512ae662d86fdL } }, + /* 49 << 98 */ + { { 0xeae827d989e687ddL,0xb025f0723bdbdd9dL,0xfbddcecec3a575aaL, + 0x3fab33c1f80d12cbL,0xd0232142b32f0381L,0xf00e74bd3b6c3132L }, + { 0xb7c1311e0e44deffL,0xf3d790ae29b04d6bL,0x3d3744b846f72957L, + 0xc0890fb6ab2f13e6L,0xa669a34324461f0cL,0x35c9677ddd72fcb7L } }, + /* 50 << 98 */ + { { 0xc257ed518060a28fL,0x3a9d7e1cc72fafebL,0xa304a5e8332f435aL, + 0x96969bc234ccf343L,0x2aae4d8e7702ba84L,0x37f15631f203a7eaL }, + { 0xc0000f24c9666405L,0xa98eb834a537fb89L,0x8c0564cf7e36dd1aL, + 0xb5ca507b4e89615cL,0x9bfa209a9d80ef92L,0xe2ec1879a83f02e8L } }, + /* 51 << 98 */ + { { 0x73b4573c11dfdea9L,0xe5f208ee5c8cc81fL,0x5c240d3c769adf12L, + 0xbd3f8f33550c53acL,0x98171d16bb4f43acL,0xaf19d5fe84db9e13L }, + { 0xc589be0d2e53345eL,0x3184b540f114f6f3L,0xa35ed77e4946090fL, + 0x427b860afd3108fcL,0x7d0848c3867df76bL,0x353539e2a32ec485L } }, + /* 52 << 98 */ + { { 0x9401aec2b9f00793L,0x064ec4f4b997f0bfL,0xdc0cc1fd849240c8L, + 0x39a75f37b6e92d72L,0xaa43ca5d0224a4abL,0x9c4d632554614c47L }, + { 0x1767366fc6709da3L,0xa6b482d123479232L,0x54dc6ddc84d63e85L, + 0x0accb5adc99d3b9eL,0x211716bbe8aa3abfL,0xd0fe25ad69ec6406L } }, + /* 53 << 98 */ + { { 0xee174af2df740edcL,0x1bd8382c09233f0aL,0x34a7450e7d343006L, + 0x92259ddd3d463e61L,0xcd0bfe6fedbc3af2L,0x39627c4cfc8770f4L }, + { 0x7b7c688ddbabdf2bL,0xf459f0e64bef3558L,0xfa0e87becc88f7c8L, + 0x67beabac5fcc80feL,0xbdae52bfadeba16fL,0x4751724c5af5c9bbL } }, + /* 54 << 98 */ + { { 0x5627e0d016332364L,0x33839376fc57f01bL,0xe7fc2c489528e434L, + 0xa0ee39acb52b3757L,0xe49e383ee42e4832L,0xabfefdbb31359afbL }, + { 0x5dedb6f3b99ee196L,0x38abe58bc16aac17L,0xa300a1333ec06a07L, + 0x00e68eadc90d4659L,0x60412e8a8000a773L,0x6099b6a6a5830c94L } }, + /* 55 << 98 */ + { { 0x85364bd10d340c80L,0x14b89462be64bc9fL,0x16429134b542faa0L, + 0x0d4cf3ce73683e2bL,0xf9a3e443cb73ab7bL,0xa4c2d0afbb156b0dL }, + { 0x826123921bc77675L,0xaf2aad4a5f26c238L,0x6f6f5d9aef4656bdL, + 0x0e20425f90901f3eL,0x0e30bfef9943a673L,0x6cefc62847415a28L } }, + /* 56 << 98 */ + { { 0xe7acaa8457e0105dL,0x3c06d3bd3851fd57L,0x23cf3c612a9c631bL, + 0x13888aaa33863bf8L,0xf2396355717783eeL,0xf21e1a4836b300e1L }, + { 0xa734cb3b9d27b4cbL,0x0a7effed796e34b6L,0xfc5864773615cc7aL, + 0x1f98ed7788844a21L,0xd6e289407ad4c7bdL,0xa00d64ebe9331c7eL } }, + /* 57 << 98 */ + { { 0xcc6ce7dee1c1e159L,0x77982e4f03df6b56L,0xbd8307d1b82b5ebfL, + 0x43e25358ed881b82L,0xddba4f418e0eb034L,0xbe326c36f919800cL }, + { 0x97d03da7af52dfaeL,0x153bb17af4bf81c5L,0x29bbb9bed7ff322cL, + 0x7a7bd8c7232cca47L,0x7474c199c2830f03L,0x9f464a06f0065fc4L } }, + /* 58 << 98 */ + { { 0xca505cb553b876bfL,0x6fc27f553662cb5fL,0x891cbef432cb1636L, + 0x339743f16e27e2d9L,0xde76538f21dc4837L,0x9cea05020efe241cL }, + { 0x97b8deb65888d9acL,0x4d3c28cba4b6cc56L,0x88ca828f840910b3L, + 0x2e5727cfbfde6793L,0x05a4138302bbae6cL,0x2e72fd653fa8e23bL } }, + /* 59 << 98 */ + { { 0x5b88c5ae6d17fe02L,0xc9b14810d6dbe104L,0x170b8659873be863L, + 0xdc5946a6ae9111b4L,0x4cfa5f022819a4cdL,0x7653d06ae213bb7dL }, + { 0x324c41baabd7ee74L,0x4219968cdd1608f1L,0xa5e104704adc1561L, + 0x964a53ea5e16d818L,0x00ebd1d4980f4bd2L,0x23cbb80d3518144dL } }, + /* 60 << 98 */ + { { 0x0d5c1769df85c705L,0x7086c93da409dcd1L,0x9710839d0e8d75d8L, + 0x17b7db75ebdd4177L,0xaf69eb58f649a809L,0x6ef19ea28a84e220L }, + { 0x36eb5c6665c278b2L,0xd2a1512881ea9d65L,0x4fcba840769300adL, + 0xc2052ccdc8e536e5L,0x9caee014ac263b8fL,0x56f7ed7af9239663L } }, + /* 61 << 98 */ + { { 0xe6ece4b5dae76820L,0xd428354e95feec03L,0x43517722f8871f7bL, + 0x313fde11e84d0b7cL,0x7f02824b1cae0a45L,0xf9f560c1d6646bc4L }, + { 0x124d88bc903a0608L,0x950e8320370c7ff2L,0x29e6da714090a72dL, + 0xbc5a108c54547d89L,0x809330cd3e484deaL,0x1b04a8088bb00f0cL } }, + /* 62 << 98 */ + { { 0x2425c59c03e0a528L,0x49de96f425c2be3aL,0x30b52686fff4b610L, + 0x2ce573b0f2e5f7b1L,0x4ec05f07b606f0e6L,0xf2040886366ecbf4L }, + { 0xc7fd993460d404d3L,0x8a064992fc12227dL,0x9c6d64ec215492b1L, + 0x2793bd0903463ec1L,0x49523ebab7376e80L,0xb138dfbd35b14fd6L } }, + /* 63 << 98 */ + { { 0x5ed097b0df7363adL,0x21319edba5696d91L,0x17c46519c5d5313dL, + 0x341d46576c6cccedL,0x60d80713692bc704L,0x9477b6e907fb8e13L }, + { 0x2965720b532e0c6dL,0x2767b4ee87831d79L,0x3e2e67abd4b5ef14L, + 0x45ee89b5d2598521L,0xfc8f1e3ee6441648L,0x75c4db57567ed090L } }, + /* 64 << 98 */ + { { 0x17e3d0b8713b8541L,0xf372b048c6b5e839L,0xf8ef0261d0bb1848L, + 0x9b804ceec71a3bbeL,0x00b7d171542a88aeL,0xf2b8ed10e9097b9eL }, + { 0xdbad9f122c0a009aL,0x245fc1e9205fb1bfL,0xa8a4834fb83debf5L, + 0xc3ee226d637e449bL,0xe3070d93cab82664L,0x24b8094db37320e8L } }, + /* 0 << 105 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 105 */ + { { 0xb506b7b925059699L,0x349fd83f01ab02e5L,0x64b729ad3789281eL, + 0x69ae8f81f9af4561L,0x007befe156f91860L,0xb578c566edc250fbL }, + { 0x1c16d75a67ae4801L,0x04c35a7ea1d3f592L,0x5dc97da936881f89L, + 0xaddb603103a5b1eaL,0x7eb515b13e153a0fL,0xdc3a92192b4a1ee2L } }, + /* 2 << 105 */ + { { 0xe7365f9e512cc92aL,0x9efdcf8b5172a654L,0xbfb389ac8e611fc3L, + 0xce778fd5699c227dL,0xdc1f47b63ff2ef17L,0x2ae0f68302672ed4L }, + { 0x51c63806a8e879cbL,0xd3dfecf03909f526L,0x375b3d13e00e12a2L, + 0x91f9f750bf8df325L,0xf1ea0e421df5f21aL,0xaed73e7f32c60584L } }, + /* 3 << 105 */ + { { 0x03b07fb5e0728e6dL,0x9e0469201012234eL,0x272e644935637644L, + 0x2b6ad1c2a55bcadfL,0x86c527765c71c6afL,0xa25bd60bc1678806L }, + { 0x0cae829476bb32f8L,0x389ce4e633e03cb2L,0x504df8337513dfb6L, + 0x4260ee8e1b351ddaL,0xa473c5d9dbaf7cd0L,0x22cb7cb471e390fdL } }, + /* 4 << 105 */ + { { 0x1d9aa9fa26caebd8L,0x6b64686926b7a673L,0x7ebed6a17f167b47L, + 0x324c13f85bd9153dL,0xe9ea5b734c682ba6L,0x2961da7d7e3ff6e2L }, + { 0x1ed2b05001a83dadL,0xb232951dc4a2f60aL,0xafcea5d3d68b8ec6L, + 0x21dc058d1c6ce0d2L,0x0043de75e719410cL,0x4edd792ce15cf534L } }, + /* 5 << 105 */ + { { 0x0f45245f3babe09eL,0x0959326fa9f2fac5L,0x7629e7fb5cc136e5L, + 0x208bd5a6e48b7eb0L,0x637891d6b75a85cbL,0xf0ad9d8d9f27b57eL }, + { 0x437b6944e0454b05L,0x022c51d702ed3592L,0x0f79e2bd0dc0a769L, + 0x54ace1fdd9b81f9bL,0x38611d66f95ea8dcL,0x52443ca8f0e6147bL } }, + /* 6 << 105 */ + { { 0x857d68558bc272d0L,0x4583eeeeb5be2485L,0xb83586dafe0152ecL, + 0x8b0eb223e830294aL,0x757582b6a5b0e880L,0x5140c0169cca7fffL }, + { 0x07a00782e9228f12L,0xb96e2b5dd4973080L,0x3cceb9a6e88efbe6L, + 0x9955b63073fcdd25L,0x04f26ab02805d470L,0x90b38299424da086L } }, + /* 7 << 105 */ + { { 0x73f1ae48f4f6c5b4L,0xee5af13d4a477f01L,0x274614a2ddb93d52L, + 0x90b0c563c320aaf5L,0xee2303c8ef990b0bL,0x00d028e73061f140L }, + { 0xff705011cb3d8eafL,0xae1d990862594f4cL,0x22a27cecdafea438L, + 0xa78e12d5c5962ea9L,0x5bbe9d878e65f9cfL,0xa222580cf47cefa6L } }, + /* 8 << 105 */ + { { 0xf7aaa732959abb9eL,0x1222ad0a2ebf80b9L,0xa1a417372e0c286eL, + 0x3b6685025da3472dL,0xbc0d116b7576f2a2L,0xfdbcad95a36a27d4L }, + { 0xcdb3f4749d54f7eeL,0xe2e0f5f98a5643a3L,0xc70d11b969d4f171L, + 0xdf96d1366cca4ef7L,0x570693db2fc6afdfL,0x5059e67b567504daL } }, + /* 9 << 105 */ + { { 0x2c8107d47fe632a2L,0xfc46c745ede7bff8L,0x2d3b12864650025bL, + 0x815ef3cbe74cd65fL,0x5431b01ba256f01cL,0xe832ff1139915cfaL }, + { 0x2c106de607d7af84L,0x67303b786d4753e7L,0x5f886ffa6d75c8deL, + 0x932a6c20967131cfL,0x5bc94a9170aebbb0L,0xa85b3044fd56e06dL } }, + /* 10 << 105 */ + { { 0xc904558ae7eba799L,0x46b6031bb2fa7331L,0x6620e2b50653675cL, + 0xd1373a357d2218f7L,0x0f4b3ca3af55a5e7L,0x50774160714e70c2L }, + { 0xacc63d1469188455L,0x89a795fe043b8b30L,0xac2fd66ce1e4b9cfL, + 0xac7927021bf67f26L,0xb9513f0d1143d437L,0x02198050811f2931L } }, + /* 11 << 105 */ + { { 0x6d4acdba7b480776L,0x8b518cd466dffeb5L,0x8826c99451918859L, + 0xd2b6a7a038fad835L,0xd315417a6929a870L,0x05d85252c5a769e1L }, + { 0x2fa06335ec0d091eL,0xb0cc337287768c88L,0xacbda5ba58a2eb9dL, + 0x2a404fc976b7b057L,0x073abb71838c6135L,0xbdf89b135cfc4f3cL } }, + /* 12 << 105 */ + { { 0xd00eb9c53508675fL,0x92ec76a4a117dc95L,0xf58d6f85334ca15cL, + 0xeeb522169cee0544L,0x3eb9847ff21457c2L,0x547908bc5524c60dL }, + { 0xb5b49d225198709bL,0x718abce6324abc67L,0xdab8ff2f4abd54baL, + 0x98be59e67184d444L,0x45b74b54babeb4b0L,0xd8d8bb30ff71a5acL } }, + /* 13 << 105 */ + { { 0x8aedf7e28ec13e6fL,0x8b952620d950792dL,0x36e9dac204918f59L, + 0x5e49a5a2d3dd47edL,0xb17455bee863c2bdL,0x8caac6a9326a0d66L }, + { 0xb6c3f5e427bb72e1L,0x17566c9dee5fe09bL,0xfd6bbcc25e3db64dL, + 0xd437d07a3189319cL,0xad00dfc4cd3166a5L,0xab75927b0bd63003L } }, + /* 14 << 105 */ + { { 0xa7672a39afc43be8L,0xefc49015c72f97aaL,0x81c63c050e48f2edL, + 0x62f39f32833a22ccL,0xf7a3480172c0c0c4L,0x4711cd41a4158538L }, + { 0xa3c99a4d1d15f2f3L,0x4b82c1c17bee1b47L,0xc7d60b489d199f10L, + 0xd1d1f03d5f16fa95L,0x96c780c932fbeaf2L,0x0662e250376ff106L } }, + /* 15 << 105 */ + { { 0x728e334678571c8fL,0xd0a886b56cb339d3L,0xf4ea33380a5671baL, + 0x43823401a64850a4L,0xa7729cd533117b9dL,0x4dd457602b78cffbL }, + { 0xbe0571115a67d812L,0x7ec6cf925105a3fcL,0x5dbcb4bc0ccafeecL, + 0xa7587f15803092f8L,0x67ee61d5a884efadL,0xd4ced554ca47d9caL } }, + /* 16 << 105 */ + { { 0x02c6b6083b03dcbcL,0x2b20149e3b9d868aL,0xaf5ab01d4f57eb0cL, + 0x59935b94d750e515L,0x32721b408f89ad68L,0x673bd755a7e3ceffL }, + { 0xbd462fd8ef3b3393L,0x991422640e59a120L,0x4162da619263fa61L, + 0x2ed1f2deb6488eb3L,0xb0bd37a8725680c4L,0x17218bf029ec27b0L } }, + /* 17 << 105 */ + { { 0x444071ff84ff1ebcL,0x4b4171e87f789cbdL,0x4a832cca2db4e8daL, + 0xe229ffb6dc209c05L,0x9efbfd7eb5f0b3f4L,0x65e07fe774fbbe6bL }, + { 0x2892c8ac627b9d41L,0x01a20eb94297e7a9L,0x2f54e88646f29860L, + 0xc425accc188798ecL,0x6137251c85c80580L,0x6cc0f9c4f386581eL } }, + /* 18 << 105 */ + { { 0xf677bdd11cb61a7bL,0xfca1faf8932d6113L,0x1d5bbf97a531bbe2L, + 0x3d5e4860c849fc47L,0x388943cd95fe4da2L,0xffb7d5e073add43fL }, + { 0xc3166ae828fcc058L,0x89dc7faae0d6f6e4L,0xe6daf1a6f527ca01L, + 0x500a703a56ef1d8dL,0x3573d0a3fc914df4L,0xd780e745ef8dc2a4L } }, + /* 19 << 105 */ + { { 0x90a8f3380500afbcL,0x8c303270838ccf6fL,0x82cbdc98458254c6L, + 0xc2f24d03b367ddbcL,0x5d3daa0d6c882354L,0x824d313d376599d0L }, + { 0x6e5075df7b9dd1b6L,0x6871a3d4d69c9828L,0x8b3762f59cffa148L, + 0xf2184f67eef8c656L,0x437630c296a1537eL,0x92a0667c4cbf8249L } }, + /* 20 << 105 */ + { { 0x6e929912ef619478L,0xe7ddaf255ffc5939L,0xb71133cf96dbbca5L, + 0xee8bd53f17da5104L,0x7601ce6adc49be68L,0xa1ca3b3cc63f2a87L }, + { 0xebf388c2a0de1668L,0xa0f6c38dd0ec6bd7L,0xc8e0875ddac451ddL, + 0x179fbbe5a5afce85L,0x0727095673bfb06bL,0x992afcd047622925L } }, + /* 21 << 105 */ + { { 0xe3b0122624f262c3L,0xaa7a0925dae30b22L,0x36104c95a96a18f9L, + 0xdc6090f5539b6740L,0xd70270ba11040a88L,0x53997b57ea3342feL }, + { 0xaaf1d47d63393e4fL,0x9db8aa3fe8a99625L,0xed571a32c3926e1cL, + 0xd6e898526e565346L,0xb3984bbd873b2589L,0xaeb7bf3f3f5f68e1L } }, + /* 22 << 105 */ + { { 0x75a4a19a79ded4a8L,0x1368e269f688177dL,0xa24d67118581e23aL, + 0xae63d5a6746b3830L,0x0c68d3e314017304L,0x521a5e7de4d45dc9L }, + { 0x69d9adfaf77ca616L,0x1f8d37f4bfda67f3L,0xa2833ba1027e771dL, + 0xae49b00367141a63L,0x04e6f282ed6f1968L,0x65d7d88f060f9157L } }, + /* 23 << 105 */ + { { 0x5dc3137b512e4026L,0x43e189595d6ac980L,0xdb7dfef39eac06a4L, + 0xa8f3e2aea09b0650L,0x80a8594c575e047aL,0x9eba41bcf0c58bf3L }, + { 0xdc04cc7679812341L,0x716050eaeed1be66L,0xe559782099b77be8L, + 0xe543aef055183ad5L,0xbbddfb814c08a959L,0x6e54d86eb5368e8bL } }, + /* 24 << 105 */ + { { 0x170f8a74e7aba263L,0x6b4e1d7b986b151aL,0x5f65bd224b08921aL, + 0x1017ae3de6caca3aL,0x613f36b626cb9d5bL,0x8a1e2f2ded19d99bL }, + { 0x52c915a5c3c519c2L,0x3c9a33305902fa08L,0x2cd7f7c206a51a12L, + 0xfed60db66e0197ceL,0x4e5b2bb7d971b04cL,0xebebeebf2f45ab13L } }, + /* 25 << 105 */ + { { 0x43b10a0673220e06L,0xdf93af67777cf022L,0x830195efbeea9ed4L, + 0x0a36b71812353c9bL,0x520e2e8d1ec8c488L,0xdc985ffaadac5e16L }, + { 0x0ebac566f3f58ed7L,0xc7747562a2cd13a2L,0x6a5b4cbce3901864L, + 0x66634acaa374b634L,0x45e000877f4680dcL,0xb783d01f9fdbe92aL } }, + /* 26 << 105 */ + { { 0xcf6d51be36e1c05bL,0xf59b6665e1da0ad8L,0xaa8bfb9d727a701bL, + 0xb1680942e26e268bL,0x09d41407e518661bL,0x8b0dfbfb3757a993L }, + { 0x34ecb09f6cb33380L,0xfcd77efede342bf6L,0x9f8fa6c6e476c5eaL, + 0xde30410fb6257416L,0x416ea101bbd47b91L,0x86ebd19e4aeede80L } }, + /* 27 << 105 */ + { { 0xfe7562e00818226bL,0x922d8fe662b46275L,0x6216698b491adc2eL, + 0x5bdf7a59f6a38f2eL,0xc0640bf937710dfcL,0x06ad30a9df687f48L }, + { 0xc561dc7d3eb66e6dL,0x7444ac83d08616c3L,0xebfcccee84984618L, + 0x35a03bafbb15eb51L,0x7c907f9fc17a5de2L,0x2e48ddb5814634dfL } }, + /* 28 << 105 */ + { { 0xe466d7a7ea51a37aL,0x5203e990cdf97186L,0xf700953096c84ba0L, + 0x4e32fbe65f89d1adL,0xe530349aa9be221eL,0x0f7f9c2e50b31508L }, + { 0xa6796f5c3af5a574L,0xe220f6daa2a2df89L,0x99ec4811d8b65510L, + 0x4dfdac69ed373b27L,0x663f46b1bb55114cL,0x44236350d167e032L } }, + /* 29 << 105 */ + { { 0x1382e90ba65f6a57L,0x3557ab88e5c903e1L,0xcc0cc77f032067beL, + 0xdd8da09f67797328L,0xeb2979d45114c09bL,0xaaca95bcc4eb598eL }, + { 0x651a7ce5a2b776fbL,0xc20fe9315312ffc1L,0x842957357dcf479fL, + 0x022ba6e2ee5cc0a7L,0x6d27e37185b0ba5cL,0xe6f212bdbcd5f2c1L } }, + /* 30 << 105 */ + { { 0xb0c2ce87a9088f95L,0x47ec07e0acb11d2fL,0xfe84fba0d30ad231L, + 0xaa98e35f18a08eb1L,0x36adc3f2f6a27510L,0x622d202751fac4fcL }, + { 0x4be765cabb9b6ffcL,0x934193571cbfcbeaL,0x83542d9cbef14402L, + 0xf27504954612b4b4L,0x91aff597bb988ba6L,0x229031e51d61f6f9L } }, + /* 31 << 105 */ + { { 0x6b04a446ea29e65cL,0x9b6247a696c48a99L,0x95aa162f60c83930L, + 0xe387f544e30821eaL,0xbe1cdab306c51b7eL,0x40175d151fc7b8f8L }, + { 0x89df5ff36384d331L,0x02eb9aa4fe1aaf5eL,0xf24155f789675704L, + 0xbd2e8cdd87f72f4cL,0x2856b3c46de30f01L,0x2356f0a3ecf8af25L } }, + /* 32 << 105 */ + { { 0xfb09e7564bd044efL,0xdbc9fcdfbb964fb3L,0x451c5b01cdb1f4f5L, + 0xb02f9068f1dd1cf0L,0xd4765e7c0c687e41L,0x89b64981d1967bd3L }, + { 0x06a0e4ecf0439d65L,0x564c387da5abbcecL,0xc1e9d01ac651d806L, + 0x5e6ebd830618a96cL,0x9ce1aacec54ad8ceL,0xe5248a089953f90fL } }, + /* 33 << 105 */ + { { 0xd65f3b909b6ab239L,0xbc259a6d9ea8bf80L,0xc10d5c235944f964L, + 0xbd6b3f6f61eeac6fL,0xc4ef2d8383e92858L,0xb80d5ab0a3736bfeL }, + { 0x27bebd1176695c40L,0x4de92348ea4f5720L,0xd70d93e6070b892aL, + 0xfce03d0be626d5abL,0x2525e8ea81014bedL,0x6fa3df16a70e2799L } }, + /* 34 << 105 */ + { { 0x42b8350a7bbc41caL,0xd7861ad49af59bc9L,0x2453d07c5644d328L, + 0x2b92643ad7c8ec43L,0x7c14d3c7cd5f1fd2L,0xcee050463d373c7fL }, + { 0x17ff60bd0ab2b35bL,0x473925e0dbb7f655L,0xdbaa015aff3ee023L, + 0xbc1ff6d6087ecfbfL,0xc44e1c8c5fc66ca2L,0xc60a193850d6b257L } }, + /* 35 << 105 */ + { { 0x5ff44f3ed8f0983cL,0x9de50da0bb82cc15L,0x504f82ec94757c44L, + 0x72a4fc9dc8a07028L,0xd4d6e4cec3d5e64cL,0xc6148fe780008568L }, + { 0x71ba3fc525ef66d6L,0x969cc8694f6589f6L,0x5016c8c2d934ab25L, + 0xa78382f6959e8881L,0x28bcb8bea20eee18L,0x055ba80b37edd7c8L } }, + /* 36 << 105 */ + { { 0xbe389fef9c98ca3cL,0xdc3ab23b910370e5L,0x866cb37d5e8eb20dL, + 0x2f951ca9c1e32fc8L,0x54ef6ab15fe24e6cL,0x6038b5efcfcb8cfbL }, + { 0x362e076b6eec196dL,0x47bb3aefd398b505L,0x9f3128eb343711ccL, + 0x8dda2fa8d28e3269L,0x908c52c7eda48846L,0x65fb3a05d53b0917L } }, + /* 37 << 105 */ + { { 0xeae35c02ed711239L,0x16ab943fa97db2d7L,0x9770bb578f3b0599L, + 0xa88ffb95956d04f3L,0x3b937af5f4dcf6ffL,0x311ef2cc0bc41f56L }, + { 0x00e9214a2860ea2aL,0x2a64b18a7bd12d8fL,0x20a5b9da6a2b9dbcL, + 0x5c16a412fe1b8edaL,0x6fc306af7b9db98bL,0x964c35de25dc9363L } }, + /* 38 << 105 */ + { { 0x81f4739e6df16589L,0x2ea2fff11f8b8ac4L,0x3baff03d33e02c36L, + 0x7f07526874d77660L,0xa442d7fa758eed7dL,0x584cbe9866625864L }, + { 0xeed35d579d167ff6L,0x56627c2e3c7bf84fL,0x908df5aedd011153L, + 0x2694e54d242fc055L,0x25beed9a2f2d60c3L,0x29d3f22fe2ee5293L } }, + /* 39 << 105 */ + { { 0x14940dbc178f9859L,0x6e6e35b7329ec4a2L,0xd1f198096707db4aL, + 0x6eb310b79fe4233aL,0x8f92556eb41e1d8cL,0x2ab28e231d7ce522L }, + { 0xc5d0f5dfdd5c4d68L,0x3f5146d825101083L,0x3a04aa53de9ee4cfL, + 0xcf36f1e3d9357f64L,0x05a1896444889f68L,0x1096c87aa96a4137L } }, + /* 40 << 105 */ + { { 0xfa4b6697a8352657L,0xf5696452cad6ec30L,0x10aaba60986c84ffL, + 0x49bdfff4dae014e1L,0xe2a810bd0abc0e46L,0x1dc5b81462d1dd5fL }, + { 0x15d2f2c723bb4561L,0x5ac7b6421818e30cL,0x40c6b6f94c545f5bL, + 0x5875b6b2f99241e8L,0xfa3e88a9d6708293L,0x1c936920ad6d9344L } }, + /* 41 << 105 */ + { { 0x6516f6210e18ec42L,0xb967eb43df8c26bdL,0x624ee27e69addc2aL, + 0x34019d6339063252L,0xb317fdd3dcd99d7aL,0xc3d566825d314caaL }, + { 0x04992df3367506b8L,0x13e4ab2e547262b7L,0x35f130352e287d3eL, + 0x92e0a276211304d9L,0x94e7129417133d22L,0xb35302275fd71a28L } }, + /* 42 << 105 */ + { { 0xe1d9273c9ae60111L,0xe86aeac3d01243ecL,0xc7257b27fa5989f5L, + 0x57737dc89807d3ccL,0xe1ef78526937551aL,0x74ab9edb15dd2d58L }, + { 0xbc47b23cc59962fbL,0x376ff30fd3bba76dL,0xaf0035872788ab98L, + 0x1e475c68619b472cL,0xd79984c89c6a9835L,0x5ceafba510219a94L } }, + /* 43 << 105 */ + { { 0xc25ae81155d238d9L,0xf2a21fce4ba4456fL,0x4ebe44d0bd1a440cL, + 0xe821687f83d958beL,0xb4ce63423ba09f9dL,0xf271435d139048bcL }, + { 0x2a3db37c99c6412eL,0x50cba09ccb36dbd0L,0x9e5231aef6e65cf8L, + 0x48e9105d90118a6bL,0x2d58d372368144cbL,0x48702d59928575baL } }, + /* 44 << 105 */ + { { 0xc71ce040d1c9204cL,0x8ad09d7373f7686eL,0xbcc6d88dc6fcf31dL, + 0x22a0b71aaf428ad3L,0x7767944847721255L,0x2b720c7e316b808fL }, + { 0x3128a7cc5ed45b8bL,0x9744c6c0f79fa1c7L,0x738e94efd22728d7L, + 0x8a652496fff8f874L,0x0e4a5ade566c9751L,0xfcde62db64e3199bL } }, + /* 45 << 105 */ + { { 0xb068ec91aa63f5fcL,0x547e7e471a29ddfbL,0xe3e5de42b17b8e5dL, + 0xb5c84f27264d1361L,0xa68d10a426432715L,0x4f31e81c23e48e1dL }, + { 0xe32bea6116dbe185L,0xfaeab7256d1d34feL,0x0ee437cef3a8ca7bL, + 0x2b8657a2f458446bL,0x8779a3d4c52e3dcaL,0x243d7d0e71654165L } }, + /* 46 << 105 */ + { { 0xc4a346b2de23afe2L,0xf8e00f790fac7ba4L,0x22393604ab76b7d8L, + 0x109233d7a06efba8L,0x5bf89334c7bf56a4L,0x27ed4a28135d4cabL }, + { 0x07851ad2e32ca02fL,0x41b7ffa630c97f29L,0x383b3716e4457ccdL, + 0x6ce8645b0b43a50fL,0x73c82018fc5b907bL,0x79a1467381bbcf0dL } }, + /* 47 << 105 */ + { { 0xcf5331d35e092e41L,0x7e0b9fdeb43e3c15L,0x842a971182841f82L, + 0x2d837c810cb9d1ecL,0x6aff6d6873095ddeL,0x2a7f6f40c9478ef3L }, + { 0xb6e8ac80a9976e39L,0x3853fa5474e40024L,0x664b159a6d87c1d9L, + 0xaaedf4b4b20b5d11L,0x8a1ac277c5819de1L,0xf10276dc6450b97eL } }, + /* 48 << 105 */ + { { 0xa8d7901c7c16c09bL,0x628ff3be42e1948bL,0xb905d7c504e4bce1L, + 0xdfbf9c4e5ab0696fL,0x0f4e6e2ab6db9cd5L,0x4857e570482e40feL }, + { 0x5ccd9b421c3beed4L,0x171b085fae51a947L,0xcebe0dbe59065754L, + 0x4d052d3a461c1620L,0x396bac422fe541a7L,0x8e714cdb70bf32d8L } }, + /* 49 << 105 */ + { { 0xed82f15e6ca1cdcbL,0xc5ae5cde51b9a9cbL,0x3b2f78cec70c475eL, + 0x0f22d10b4243c675L,0x1db96885facac4c6L,0x2fb7884817df2f2cL }, + { 0x25fb9f4e990f3104L,0x1416733ecefa14f7L,0x3a33828384a5dc24L, + 0x6d75d3d02564288cL,0xf7bea8b69b93e62aL,0xa5ea8695349f1740L } }, + /* 50 << 105 */ + { { 0x38feea7115e711b8L,0x129aea564accd3eaL,0xc53e54c412b23539L, + 0xb15bf11a2b280c59L,0x5ea76f5782d44df5L,0xea79f833d4ac1af8L }, + { 0xe547deba08330c6dL,0xbaa89422663ef402L,0x17263762d215a5f5L, + 0xb9509a19c02b5f9eL,0x9bb99fcb025caaccL,0x43f4494b25f24089L } }, + /* 51 << 105 */ + { { 0xe55e592c98563c70L,0x4e62ace5d013c82aL,0xb6025ac16fcf7380L, + 0xac4a8157cfdff8b9L,0x1fa181344497acf6L,0xdcdf05c0ef09d3e9L }, + { 0x7a65490d83d8e716L,0x2aee0b35e98c46feL,0xe62381dc7d6d4035L, + 0xc7162b78203975c0L,0x1079d8b6aad2c021L,0xe3e1cb4370c98838L } }, + /* 52 << 105 */ + { { 0x3ca01799f04dd97aL,0xd6d1d41d3f9e03f3L,0xac2713eda55fa375L, + 0x2bd440556a89a5e5L,0x8582d98458f5c269L,0x7f9b3527fb31fc27L }, + { 0x23f91951d810580dL,0x99303919360a3debL,0xfaf10326b5e1eea8L, + 0xf96feb4838ba5ac8L,0x1508b1002a639622L,0x0766a1019dc93c78L } }, + /* 53 << 105 */ + { { 0x0c79d40679a0290cL,0xc09bca0c57eb7a00L,0xf7274ffc163c1dcdL, + 0xd64ec461bb2c83c4L,0xff3b83efe9ee350bL,0xa490157d01882c72L }, + { 0x626e1f3d3312310bL,0xd2097e03cdd5d62cL,0x705c3fcadbf659c5L, + 0x2dc1d7cc810fa413L,0x6313192ad67d58a8L,0x6e1e5bc3597f63a6L } }, + /* 54 << 105 */ + { { 0x6100535ea0d42639L,0xb126e939d921369dL,0x2d4c826e4999e42cL, + 0x159063c6f62f77e7L,0x063c42914e632555L,0x8d3ee387b35d8220L }, + { 0xbd951cff9b2bac3eL,0xd9b943f1bc248755L,0xeee7017ad3a6074cL, + 0xbcb9e0e6b0872a21L,0x26d80e0949dff656L,0x2ad7d4e335fbf620L } }, + /* 55 << 105 */ + { { 0x6ce5840df7f9503fL,0xb96f82996abf4f6bL,0xf71f33853ab55fcdL, + 0xe347e891e83a8109L,0x12c5dcdeeb48f0faL,0xb0f02553cd7183a9L }, + { 0xa7d74862c414f01fL,0xbea40c5cae369360L,0xbe9785e5022d5192L, + 0x1a3224a50d318251L,0x4d7200093fcbceebL,0x1fd71167c2976f6dL } }, + /* 56 << 105 */ + { { 0x03c88a8566d2ee47L,0xee8e5c34455ee428L,0xd90a3d393870d90eL, + 0x2fd78d14f2fdb976L,0x9472a6066a312a30L,0xea68e2283484af2fL }, + { 0x7cf25951ac9e5cf2L,0x024f07ee37a28e95L,0x5d479379e563a2bdL, + 0xe87b50a4b46e93d8L,0x9128fc11f137285cL,0xe46efdf77c67d7e6L } }, + /* 57 << 105 */ + { { 0x4050036c7cb0b9a1L,0x8560750c1161d7fdL,0x4d293a521b247ba9L, + 0x4b25e54c8f1b9d31L,0x91c89139c5baa0aaL,0xa2f75f9f2202b7e2L }, + { 0x6c0915dd4d2d1388L,0x575d90f703717fd7L,0xd90c059b03e0626dL, + 0x7004305ba4239e8cL,0x39fb4e2e989775e6L,0x20c31fc8d8a239c6L } }, + /* 58 << 105 */ + { { 0x4de318054ab51b84L,0x4a68443c6aa00707L,0x2c3637f05b317f3bL, + 0xb8ea6f87c0fc14a7L,0xcd0cb4fca2cc6af8L,0x6b5fc899317083fbL }, + { 0x1b8f160956e6dfa1L,0x698299ed92b77d20L,0xdb84ab7f14fc3fc1L, + 0x944666a35d5fe625L,0xe9a3448d7e064ab0L,0x53f62fa01abe1440L } }, + /* 59 << 105 */ + { { 0x04bc8a2bc8c676b8L,0x502a73144a577562L,0x494d01f11ff01f9dL, + 0xfe648df164d98f70L,0x80bed0d849719dd3L,0xb77a8f09c231e190L }, + { 0xc8aa8daecc011818L,0xf313be4f5918814eL,0xf28fcb74488b5bfeL, + 0x71e23b19b3345c98L,0x1cfb7c0596eba9beL,0xa88e73b941c61971L } }, + /* 60 << 105 */ + { { 0xdc7050459cfd4295L,0x1cc9648eedeea59eL,0x88f4af1c0e9ca92dL, + 0x45d0b53f69689317L,0xa122a6dd41c04186L,0x9df54c3a277fba1aL }, + { 0x1efc55a5017eb9ccL,0xb253f7b661d1ecd4L,0xd03f8ec6acfb7854L, + 0xf641e5f49f338dbaL,0x6b6a680a3a3addbcL,0xe80babb5b5cd058eL } }, + /* 61 << 105 */ + { { 0xb48da67307873319L,0x53309cdf3bf5db9bL,0x1bc510e64ee9dd11L, + 0xbb8e529a7388950aL,0xc9c0ce3c7f6e6175L,0xd75753f88a290784L }, + { 0xfebdd94ba80acc08L,0x942cdfebdc846b30L,0xbb64799f6ca7099fL, + 0x40f03362d1326fa8L,0x95b2d9db97b62e9eL,0x5ad9ce165301d9aaL } }, + /* 62 << 105 */ + { { 0xaa5fead9dfc59ef1L,0xc1348e98b2cc1e9aL,0x83dd617e77bda968L, + 0x0fdcc0837c8997dfL,0x9206ae234cc62b01L,0x88aec92f417678dfL }, + { 0x9d399af791fb8920L,0x399eebd13e8a22a0L,0x32f3bba735bebdf3L, + 0x354c1c5004c2f32aL,0xc2d6b5514052c926L,0x16a1f71f656a7eebL } }, + /* 63 << 105 */ + { { 0xd7a755bc14a8c57bL,0xa97b901341ebec55L,0x88b88459143a1a9bL, + 0x7aa178cc7e19e3e0L,0xb8359634635dfb65L,0x63fd26c7c169e28aL }, + { 0x89d9090d953272f5L,0x63e571196383845aL,0x0e26c0cf886a1f1fL, + 0xda56332db7057a29L,0x6b5d303f7a459c6fL,0x3c351b771bb704c3L } }, + /* 64 << 105 */ + { { 0xda2b0725bb296c27L,0x1f22ffa4d341171bL,0xc721e35a5b132756L, + 0xe5695e84fadb6907L,0xbc5a3bf4c283f546L,0x9182cb3edde128aeL }, + { 0x179c7fa66592e05eL,0x1e604790f38e8586L,0xaf7e83bea16bad55L, + 0x6f41231e9137ecd8L,0xac87543d8f30d1abL,0x630a9d87b1ee0ee8L } }, + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 112 */ + { { 0x359cbfa05e4f1914L,0x6992cd48d922176aL,0x2fd5e90f630cbcb5L, + 0x2b0f61306ddbf238L,0x5070970a3af753e6L,0x433d009441727016L }, + { 0x2eb15b3b9dca97e2L,0x3a7379cd00d96875L,0x0d4374aee930a75cL, + 0x3cd36046849e7727L,0x9ac3117e336a19ffL,0x2d1373c9433ddc04L } }, + /* 2 << 112 */ + { { 0x985dcb43e4362d67L,0xecb860c2a939bea4L,0x40597f3055fbf1d5L, + 0xb6d166bf43fcd98aL,0x5932570915ec99caL,0xe05ae3b9c5bdd370L }, + { 0xc18f78270c7b943bL,0x84bde9c64dd572ccL,0x5d50a89df478e56bL, + 0x242c2f4864d29053L,0xcda12c6161cf7e0eL,0xf8b6890eac8d1d40L } }, + /* 3 << 112 */ + { { 0x7a9a9dd7b6b11af8L,0xac4c50dd16a42f8fL,0x1550267b6726c324L, + 0x12cfb2fd7f841afbL,0xa41b19052f046430L,0x8f5f5373b7d786cbL }, + { 0x7b61b39c729e09fbL,0x07a5415f2626da4cL,0x65d6efb84a348905L, + 0xf377862cf2e864b9L,0x3c94000dab96cdb2L,0x2176321a8efef0f6L } }, + /* 4 << 112 */ + { { 0x8c558000c1c1bc68L,0x9e48a67a83fd6ca6L,0xacf0d75ceb7a35cbL, + 0x0fbdce4cf0a93110L,0x82b2d13a9cc50c85L,0x696fd259cef70d6fL }, + { 0x1cc9be2e457b88c2L,0x0d58b34b1f04c0bcL,0x52bd479f195a532bL, + 0x769fe6ca1ab3605cL,0xba6a63e48a24c1e0L,0x86dea46299da5d7aL } }, + /* 5 << 112 */ + { { 0xdf2a6cecd24790f3L,0x37bfbba7b87ca06dL,0x7c8a7e4c0de8a6aaL, + 0x5c806b94be7b8f5dL,0xccca1c714fda3e7eL,0x3c1cbaf9cff788e5L }, + { 0x17a081a9565d0464L,0xc4eb995713ed1b82L,0x0d7c90549e4cfac7L, + 0x6fb74c629d53a200L,0x65b9ed6d5f977a8bL,0xe2279cec0ba2e7c4L } }, + /* 6 << 112 */ + { { 0x8435e2962d4412dcL,0xa36cbfef972350d8L,0xe2fe6e6fece5cb15L, + 0x6f249b095336f7ffL,0x5801feb9908ee267L,0x7649a837fc8f217bL }, + { 0xfc1adc3ea0ebc808L,0x1ef06bec94f08075L,0x4afb5404cc1d9b72L, + 0x75cabd61a1f2c5a4L,0x2bd797e1cd08f195L,0x4f1b5cdecbea0f49L } }, + /* 7 << 112 */ + { { 0xe9759aa9e7aa87e2L,0x2d54a5fbe5909f55L,0xe49a59aa2c80bb61L, + 0xdb89e21230c9b328L,0xf42b9adb004ebffcL,0x4471b983479678e4L }, + { 0x0dde5b0e97709e2dL,0x2f35c653a12bdb85L,0x9f8d7a5cd8c8285cL, + 0xd7cde5971d156206L,0xdbe765d7a8e126bcL,0x2e645b6de3f4e60bL } }, + /* 8 << 112 */ + { { 0x509abccb65682820L,0xfbfa1d094ff86137L,0x1ae371bd640bc2f6L, + 0xa155c2978f546c68L,0x8858cadcc08b8cbfL,0xafac5b0a1d96948bL }, + { 0x919cb22682e25016L,0xd147df4ab064ffc3L,0x25dd0f1ab4abe560L, + 0xc6bbe6369cb75bd1L,0xbb367cf947a778e4L,0x5714aa4dbde524b3L } }, + /* 9 << 112 */ + { { 0xce3c8218e61b1439L,0x8be5a9cb67f79d28L,0xb1bd1386d5164b35L, + 0x0bc24d96b9adbac7L,0xbcee4f0ec7482414L,0xac15b5b66ca5d49dL }, + { 0x79caa999f20f9a50L,0x89bfd652a911308cL,0x972fe26d15245a7dL, + 0xd44d0f6e1d0d2939L,0x6749beaedd439057L,0x02627a6ad4b6f416L } }, + /* 10 << 112 */ + { { 0x7e882e8cb437b791L,0x9afde25afbe334cfL,0x60184381da52f9fbL, + 0x935d33a1001df73cL,0x38f303df080682e5L,0xd9cf2c1f4e9a29b2L }, + { 0x889d265e00d9208eL,0xfc1cc2221fd8e817L,0xdd14f1a2ec71428aL, + 0xe81cc4f9d9e973aaL,0x26a154963696468cL,0x0620fe6409d546acL } }, + /* 11 << 112 */ + { { 0x06ed3e64166be92fL,0xe1da6e27c51ea53eL,0x784f2514acb2b245L, + 0xc544e50f8e24077fL,0xad449938c5c01787L,0x5d9ef8d527d41dd7L }, + { 0x37114064e15d4a96L,0x7f0c92aa1dd45321L,0xc1f11d56b9c72ee5L, + 0x91f3b3f7a78e6d3aL,0x0cf440b0c9488cf7L,0x14d3defd93df403aL } }, + /* 12 << 112 */ + { { 0x3fa4ea0225aa1d44L,0x22c68e17f74a6a3aL,0x351bcb80f489e72dL, + 0xdabdf118be0268edL,0xa3bf9e1984d2cd16L,0x318506a2d67393a4L }, + { 0xb0c6b2d8615ed517L,0x42ac507c3dcba0f9L,0x60570dfb51235e30L, + 0xc677628dedb033e4L,0x0290c22766e61f76L,0x1d8450d09888943fL } }, + /* 13 << 112 */ + { { 0x1b8f5ed7155a3daeL,0xc9d2433aa46ed72bL,0xe99c7fe38ca361fbL, + 0x606b08c19626fe7bL,0xe6447257c0ea792aL,0x5839e2c62e1156f3L }, + { 0xb73135dd5eab6d41L,0x200f2e488ef63584L,0x4c73885ddda1c49eL, + 0x8d606a75b5428ee9L,0x2a73cc7aa62699dcL,0x484a58941c6c8de5L } }, + /* 14 << 112 */ + { { 0x2365b4150decae0cL,0x9c8567ece8583741L,0x35d6cfae6d8842a7L, + 0x4e6c98e6dd0db8e4L,0x584524e767b34d02L,0x786ea52f554c6117L }, + { 0x8952ce169320725fL,0x8eb7f91854c4c8f2L,0xdd34f77afc799251L, + 0x76b8c3173e05d37fL,0x664cbddcebb4d365L,0x31ba98b90dfa1a98L } }, + /* 15 << 112 */ + { { 0xf113a7bd651c186fL,0x417bd7373737a50aL,0xddb40d201b858249L, + 0x62a60745345f5b45L,0xf0a03f5c2d4e221eL,0xcafde67cc64621a2L }, + { 0xbbbfaebcbc3c06c3L,0xadaf9a16b8383dc0L,0xcd21aa308f343ea2L, + 0x64cefec0d890128dL,0x2ed9b8f763b44054L,0xc0a49e2917c0ffcfL } }, + /* 16 << 112 */ + { { 0xc6307399166915dfL,0xb35545bc5da8a26eL,0x8e0126aae3a99321L, + 0x0fbfdf76da9308d1L,0x2163ed6b6168e505L,0x71f3d0087500d8bdL }, + { 0xf57159605ac13f65L,0xc1cd9a6755172d5bL,0x6b225f7e53d84c65L, + 0x9c031269025029daL,0x54c1edfa17d89aedL,0x5b0238786b435150L } }, + /* 17 << 112 */ + { { 0x96d69db1146abf28L,0xc924454924d221dbL,0x7881951c137bdfe1L, + 0xde2d490dda51f789L,0x6033c2c34b0a1e0aL,0xbe214d8c08dac13eL }, + { 0x3d5abfa9a5a1d055L,0x3433060f6fe02a62L,0x88608c7ba37f2833L, + 0xfd2da6f0e74dd6c1L,0x27c22c17fe000000L,0x04a1f15bcfbde005L } }, + /* 18 << 112 */ + { { 0x01204485f340b522L,0x588a9e1c9367a099L,0xb3d1a4b466005913L, + 0x522ac504d55cc36fL,0xa6c80e511b72eabaL,0x15025a7acaaa89b5L }, + { 0xc9166912bec1a986L,0xe78e9642f19044cfL,0x230d51ab4756908aL, + 0x6795942aac04cb90L,0xcd2cc9eca2a92818L,0xfccead967cf52961L } }, + /* 19 << 112 */ + { { 0x32fa291d52ccf481L,0xbb137ef901ac0eafL,0x13ce2183011746abL, + 0x7e64248677bfea0aL,0x67cbba0e5e7e5032L,0xc900998a1f2b69fbL }, + { 0x62ddd91aab3256afL,0x1f0f216911d7996fL,0xab2f2d540e4dd4feL, + 0x05b577a92ec64ec3L,0x8071e88708ef233aL,0x9be1f8d60e649a5cL } }, + /* 20 << 112 */ + { { 0x5f78334137732664L,0x625b85dc840b6f8eL,0x7dcb3d256cdf0959L, + 0x87a5ae19d4ce1845L,0x43bf0721b0dc016aL,0x6569ad52f6a5f6f3L }, + { 0xa2697f15560ab87aL,0x4c6fd1a0060dcd57L,0x652a7732c3167f56L, + 0xe355fef05294a5e0L,0xf7b3177dcc59c562L,0x511c96dddccf4b1fL } }, + /* 21 << 112 */ + { { 0xec768f587622c0b9L,0x7c9eb5490416afe7L,0x3c3d87f55795433eL, + 0x74eff3cba4611446L,0xb2c79249dc7037d3L,0x70062ebd8bb1fc42L }, + { 0xbd0d3532a4ad91c8L,0x42411c139f5ee0c3L,0x11c4ee91132470cbL, + 0x496438979fb2a135L,0x4c1df7e0ce2ec891L,0x689cda57e16f7413L } }, + /* 22 << 112 */ + { { 0x3b42838a2a0030a1L,0x3f37587ae05ba56eL,0x6382a86f44c16650L, + 0x6c1bc67da6f9f136L,0x7d152d907ada0f41L,0x9115319d5c40c0f5L }, + { 0x1143028632f58e3aL,0x5dcf7ec7eda5c5a2L,0xf04404a9f334a0b2L, + 0x75e0b4a84ec2cbd5L,0x86e89728d079dbf0L,0x796700799a99c605L } }, + /* 23 << 112 */ + { { 0x98456a79b1d2a3fdL,0x4e8ba91e6dd789e9L,0x8e0bfa33a435226eL, + 0x42bea2f48cfea5ccL,0x5ca5fb0321b14602L,0x73faac5826877b13L }, + { 0x0ddb6ea203905ebbL,0x67bc35f1698cd7abL,0x24da47d85d9af735L, + 0x1a2a7c1dd786000eL,0xb35fb29e23ccaceaL,0x1c063466bf1f51a7L } }, + /* 24 << 112 */ + { { 0x1e7ae1601e94d949L,0x177dc53ee78e6221L,0x8af29d8f7aeb9882L, + 0x2d9a60fd9e3f3906L,0x6979fcd6df962156L,0xdd2fe5887e1e54b8L }, + { 0x9cccf31076643453L,0x94ece1a84e0643d0L,0x745449cbc111d8cfL, + 0x872afa4ae6cfbd97L,0x5c27b7ca10dfb34eL,0x505e62bc533480feL } }, + /* 25 << 112 */ + { { 0x6dd2007363141676L,0xdb099810c5c4c657L,0x2bbbcbaf8c369f32L, + 0x339e3ded08794178L,0xcc362a32315c4cd7L,0x5d288ff37dbce794L }, + { 0xafd05d104d0cb6c6L,0x3a6dcee9d386c7dfL,0xa207dc17e311ee74L, + 0xc5794286abdc751cL,0xf45136e5d889b985L,0xb25e84638d8f32a3L } }, + /* 26 << 112 */ + { { 0x8711ebfd1dc32f77L,0xfc0e851f3933d758L,0x90b679fd64a859f3L, + 0x0914a975ef37a81eL,0xcef80495d675c502L,0x862d3b65be18c403L }, + { 0x0d53f957305b4aa2L,0xe404f2570e5bcb47L,0x833a8644854b6b63L, + 0x5709f53b99f8d3d9L,0xc400dc1f13893effL,0x75ca01714c65086eL } }, + /* 27 << 112 */ + { { 0xdaaf8e76eeceb904L,0xbce9ca54b9e31f92L,0x4442d0c88d06a58fL, + 0x5966e1e5eda0ee34L,0x043125f058edc555L,0x44d0311749cf0931L }, + { 0x292aea12a99ae5c2L,0x1e9be1702a2bade4L,0x003ec2826b21b444L, + 0xc158f3cffc41d601L,0x25a839f4c4b3f4c7L,0x4a36bec399e64264L } }, + /* 28 << 112 */ + { { 0x829bbe7e04e6bda7L,0xc52b64ded3e667dbL,0x98aa40ecaa2fc128L, + 0x2c6997d011fbef94L,0x70ca76aa97c8167eL,0x558f8ce7b1083886L }, + { 0x5c621e35d250f064L,0x757710f8f535b2c7L,0x5d118d8faa69ee95L, + 0x02ffe667b27cd9deL,0x65711ac7d13e51fcL,0xdbbf16278cb1a1c7L } }, + /* 29 << 112 */ + { { 0x3c2fcbceeab0bb77L,0x569d6c7e4e1b17adL,0x22e06899b0518730L, + 0xf8466d9d19f809e9L,0x372e254288359d10L,0x8074483532d5bb82L }, + { 0xc88727d566060945L,0x08e9246572a0d38fL,0x84ca145c9f84a861L, + 0x8363463c1c004212L,0x9debab72bd3ad87eL,0xce68c150a988e65dL } }, + /* 30 << 112 */ + { { 0x1c172e5ea71dbae0L,0xf7794eb19b80bf40L,0x3007c5705d7d2829L, + 0xa8d44d6fcc97cf00L,0x093a9784f6abea6bL,0x2ac4a67564cca46fL }, + { 0x14fcc56350d8fc8bL,0x53133983a11ccd07L,0x7cf09bf68e6b8f26L, + 0x49f864d57b06e3adL,0xd526a765c373fc6dL,0x7af297c6151305d5L } }, + /* 31 << 112 */ + { { 0x18f941bfcf7c1eb5L,0xda10720a130163b7L,0x3c4894f46bd9bb34L, + 0x7575087bc8ca64f1L,0x68c424852c8f3798L,0x986214eecf0e5839L }, + { 0x3723b713df2b0b90L,0xd81560d5d229bf8aL,0x0204ae5ff993078eL, + 0x55206d9186a14833L,0x8c7d09181557fc96L,0xe2cd5dcdddba9705L } }, + /* 32 << 112 */ + { { 0x009ef80aae238fa1L,0xb41d9b24486af6b5L,0xab4455ed685add95L, + 0x18f323f672c7dac8L,0xe7009790e372f168L,0x4d5bcba6067bea99L }, + { 0xf15bdbcc51a2a9a9L,0xde7e4f742fac9169L,0x2fd62c304bdbec36L, + 0x8b3ea93d1b3ac6c7L,0xce1c8e5c9c293889L,0x19664dda11564f8bL } }, + /* 33 << 112 */ + { { 0x207a738245406afaL,0x7c1c398d1675bc91L,0x2ae99d8ba1bb7a43L, + 0x63f134e8c5e176e5L,0x4a624a1c48364268L,0x471974f1de65c5deL }, + { 0x44932063ea90b0cfL,0x13ba5019d8fd7e30L,0x6281f71348510422L, + 0xdaba3f14bc1a523aL,0x333e5eff924cc5cdL,0x861ab150e9113d1dL } }, + /* 34 << 112 */ + { { 0x332d308dd9b9461cL,0x3e9b4a95b7014261L,0xc557f608c2beeb5cL, + 0x9ee927187c8531d6L,0x55ff3dfcc0002ff0L,0xed96119eccd9b325L }, + { 0xd779ba03fb92416bL,0x63b75d351416be79L,0x793cb1fbfc9ad27fL, + 0xcc762a5b87f1bc59L,0x6e7a23389bbb07d8L,0x99b6e278aa7bfa44L } }, + /* 35 << 112 */ + { { 0xeb142de02bcce03eL,0xcac04711577565e2L,0xa949c7350ab07328L, + 0x8f15874cd7d347ebL,0xade8c67a696dc9f3L,0x039e6b7c66a7bcadL }, + { 0x1260bd4acb8cb9d2L,0xdbf05496d4801bcfL,0x6b37a4d30ffb845eL, + 0xc3968fe150b50889L,0x261e82f4525c6a7dL,0x539f634912aad50bL } }, + /* 36 << 112 */ + { { 0xcb1a9d2ceae4d774L,0xfdec2ca998a0775cL,0xa538acbd0eab9e25L, + 0x6901ebfd04dd34b0L,0x998ab679ed4c6409L,0x69b1d7ee0235b865L }, + { 0x4f2e6e5723ac3be6L,0x2b2072aed4a00479L,0x5c12fcdc2ce2f059L, + 0xfc688c45ac329db8L,0x16d377a51f539427L,0xebe4e2cfa08ed9aeL } }, + /* 37 << 112 */ + { { 0xb394214715d60238L,0x60d8909bbe9d4febL,0x013827b78654e16cL, + 0x465b3078824fc55aL,0x361e6523e3fcd6c0L,0x2ef44d80ef88b307L }, + { 0xdca7809fbeb2db77L,0xe649d591da97468aL,0xad6079b77c28ff0aL, + 0x6a21ce1ac4897775L,0xde876f7b5a592fd5L,0xced421a585a1dd36L } }, + /* 38 << 112 */ + { { 0x9793bdf6a045a442L,0xdb3c60472713ed37L,0x9929d32261344a0bL, + 0xfb48c2dc831af45cL,0x730226df53a8a077L,0x3a5baf8a18876559L }, + { 0x99736e7d8e11f9edL,0x3e7663dd0c09dddfL,0x368a29ed89b8a23dL, + 0x5443d7f5d3a68663L,0x0b84b464c6302455L,0x235c6eb5cf088847L } }, + /* 39 << 112 */ + { { 0x13307013b8de0a3aL,0xfb10e919f592fd9eL,0xd09e5b2571401ec7L, + 0x6e8091c11d94cf0aL,0xb7d79fc74193b129L,0xb842a3695f2c05e5L }, + { 0xcf6fc6cbccdc7614L,0x77d6408180102a3aL,0xde4b9304f30c3488L, + 0x4fd9f8d89bd08e48L,0x58ac01245963b063L,0x1f11335c747fac66L } }, + /* 40 << 112 */ + { { 0x5f266f13175418b2L,0x6bd7a86903a626f9L,0xc7b532304a6f11caL, + 0xa216b056bfc8ccedL,0xa274d5d8b288cb7cL,0x6fc4a35d924897adL }, + { 0x1ea532eb81fc6940L,0x2fcd817e2acbbc45L,0x45eee93f67814fa3L, + 0x3b3da48c1229e035L,0xd049a976efd8e3d7L,0x8087dff7bf81f314L } }, + /* 41 << 112 */ + { { 0x9ccd802fbddea807L,0x08a64e86d93b97f6L,0x422c0f5602f04e3cL, + 0x25aecab133900990L,0xcdb2c5c15d4b4d2fL,0x849a6b1f5f43e42eL }, + { 0x4689b815446e7361L,0x49abaf6ca681fba0L,0x304d84b18289a564L, + 0xa6529d430b779df3L,0xca926da67b51b195L,0x3640dde5c829ae84L } }, + /* 42 << 112 */ + { { 0x747235495424e1d0L,0x3861ae65c85af64fL,0xc56ff12baab902c2L, + 0x9aeb9e154fbf264eL,0x14e3c13942ca40d2L,0x6c26da41c1ba0250L }, + { 0x97a6031df51a0967L,0x88fea7710e623393L,0xcafae4c778574eefL, + 0x2c4c281198119f28L,0xd190fc749276d971L,0x843f4baf9273f01cL } }, + /* 43 << 112 */ + { { 0x1b2d643de50ad79dL,0x1ceaee7ed3075486L,0x13a003f3ec287aabL, + 0x09a4a825e8c7aeddL,0x93babe5ad1d4c05cL,0x8115bfec95ab084cL }, + { 0x629e8e0a289ebb8aL,0x923167a9bd992f77L,0x440edf75ae16ce72L, + 0xa67dd37b0a0019d4L,0x174b341978b0df8dL,0x010746a5ad6e4c60L } }, + /* 44 << 112 */ + { { 0xed05e4bf8342da4aL,0x36d881f3b565f0f2L,0x3fbd04e1411e627fL, + 0x40ac13cb0411889aL,0x9f6006cab5b25fd6L,0x0e79d377e31404ccL }, + { 0x9fd6474a5af3ea01L,0x89d7ddcb2a27d905L,0x2c1beebada12e71dL, + 0x3ecb11e1833eb7deL,0xa348b2f6600eb1faL,0xc227192183f2657fL } }, + /* 45 << 112 */ + { { 0x2cfaf519e32ba792L,0xa99113d7f929b512L,0xd347f7d18f554e19L, + 0x18f0374f098a2ad8L,0x073855acc174e0b9L,0xf155c6c009324c23L }, + { 0x3388c39605d1e427L,0x144356a9d39221d1L,0xe3d4ffed492a84adL, + 0x519c65e6d1e53c29L,0x334f470a2813c717L,0x69aa0a1de0a400e7L } }, + /* 46 << 112 */ + { { 0xd8689c9c39e70b62L,0x2b87157e6cd86fe6L,0x53d55de887c0f35dL, + 0xb2d7141de09aa44bL,0x3499553084fe7c21L,0x4550096c16b19be0L }, + { 0xb0a8ce05b856dac0L,0x570223450e211887L,0x8d4a7431aca17401L, + 0x96bf439857400a0eL,0x1e849d365ffd5f34L,0x7e70f6253a6d23acL } }, + /* 47 << 112 */ + { { 0x511ad0024b4ecd64L,0xd2287a28f37bf796L,0x801d2c2dcbc1f22dL, + 0xf0d3a6944df568c8L,0xa7fec550af6836b0L,0xa27dd6e887a426c7L }, + { 0x2f730e5b59c6b695L,0x9df438ee93ee2b36L,0xc4def9eaf2cfc4c6L, + 0x82ddcca0a209814bL,0xb2e1de4f6dc916d3L,0xc6798e7453f81a55L } }, + /* 48 << 112 */ + { { 0x77faac22bd366155L,0x13cc4038282f11b5L,0x31ad1dd45fbd35abL, + 0x7e0de9da45d6d40eL,0xa16c5f1939749ef6L,0x761cd6cf85691cf2L }, + { 0x156536ad4d59b802L,0xee98dc4187c4b11dL,0x165a1eacd35088fcL, + 0xce8a733538fb995cL,0x34d0d3313293b3a5L,0xfcf548ca8b570e79L } }, + /* 49 << 112 */ + { { 0x4c4bddca99e8cb05L,0x2b900ed017c5be91L,0x0ba0201b40adbfc1L, + 0xb5098cf8534595ecL,0x356e23ff80f56f69L,0x8b3fa12e748555a0L }, + { 0x9063437677b8ebdbL,0xe3eb33fdf040b6a8L,0xcc5b699539b611ceL, + 0x20171523c693be7eL,0x5c4364d760849cf0L,0x30f3376372c4d303L } }, + /* 50 << 112 */ + { { 0x0757295022a8c8e0L,0x6e05715866ca81ecL,0x7e8e36890f804bc9L, + 0xcba813a191b99207L,0x3f11f7abe50ab65fL,0xaefe5479b6d05954L }, + { 0x48dd59a1eff5cf18L,0xa623b738bda11ecdL,0x586e755818870f08L, + 0xb2c471a50e38ba1aL,0x5b21c42c69ce8032L,0xaf040e6c7943d78eL } }, + /* 51 << 112 */ + { { 0x6364714c4852f979L,0x7ed7aa310700cd35L,0x9021e46d9376733cL, + 0xf2b65ed3b6de8d03L,0x0e3d00c16652346cL,0x6630fcb75d27e2d0L }, + { 0x69cc20ded79a1c20L,0xa6d77163be3745e6L,0xab36946379aacf14L, + 0x8bdffbf1b935a1daL,0xda8eb343b63096f6L,0xf61988f13c966345L } }, + /* 52 << 112 */ + { { 0x06f684ffd31f390eL,0xa1467be560ec98a8L,0x7cbdd03eaa80fddeL, + 0x0ae4d114e204ded1L,0xb8ebeb29a004c3e2L,0xd93cd70726009581L }, + { 0x3ff2ee49f1b9d3ccL,0x0e69e5ac753526ccL,0x8cb2243e8b13f47bL, + 0xe2c5ae8d7fbfc5aeL,0x8e9af723394a45d8L,0x0b1114dbd92ab8d0L } }, + /* 53 << 112 */ + { { 0x937d9d2a73f9ff5bL,0x07c8c147de0fd740L,0x3880ead73639b680L, + 0x879d6f836558cc89L,0xf32e14b975bc8c84L,0x278ea5e4bcf6f8cdL }, + { 0xd9f25ea94baca6cbL,0x676e4bdd44d0ceb2L,0x98042ac190868974L, + 0xdf227f370711b658L,0xcd6d29b46ef0e4f8L,0xd04f5bf88f817e92L } }, + /* 54 << 112 */ + { { 0xc7d62be78354f4ffL,0xd6fd9d590ac4d9b6L,0x13fbed772b50ab82L, + 0xc4c5be374362b766L,0x5d67bfdd6c59d059L,0x10c93cceac02f34cL }, + { 0x3bec1f3b72e35ca4L,0xb1cfade159f4820bL,0x679edbcf80fae051L, + 0x6762f5ba6671737cL,0x28b425db3fe77970L,0x4bd6d2ebe778aaaeL } }, + /* 55 << 112 */ + { { 0xdcbe0018aecd5ae8L,0x7f178b7aedb2a7b0L,0xedb5c805b427179cL, + 0x25fb6a084ba080fbL,0xeb6365165f1b263dL,0x814c520092acb04aL }, + { 0x936f97a988d94b88L,0x6d54f1768b45e4b7L,0x6321e3bdb0cc515cL, + 0x9118d0318eb5be13L,0x5be9188a8c574e96L,0xcdad43f3f281f19dL } }, + /* 56 << 112 */ + { { 0x7be5946ea85af34aL,0x420593c9da6fb0e0L,0x40b83c00987f9246L, + 0xac35f4e9a15d192bL,0x1979bd33776a678cL,0x0a7d973e8f6068d3L }, + { 0x71d322e87e6298feL,0xbb23a29936af9b65L,0x14e2b9706644c50cL, + 0x5f7f207373570bd3L,0x40215c569055538bL,0x91372e64365500c9L } }, + /* 57 << 112 */ + { { 0x2763961a303ef488L,0xc357c32fbf865ec3L,0x32ca1a943663e409L, + 0x9d9040217de506a9L,0x1f56e144249028bcL,0xd76402e61c5c7cecL }, + { 0x98dcac65b0dd9d4fL,0x887f6e97532facf6L,0xc0d5d2a123c2cfbeL, + 0x0566bd59d18d8b1aL,0x67404eb1297a071eL,0x10f24d9b26529285L } }, + /* 58 << 112 */ + { { 0x34808f5ca479ef4eL,0x60effdea9ff10abfL,0x471a077cdae34e0eL, + 0xf34df9562f9d1408L,0x4f8bbffbe46961b7L,0x6a80b0276336a6f4L }, + { 0x28e57309ca92e5dbL,0x27fbb139ce31cb10L,0xcea87ae28d24334bL, + 0x3781f438de6db765L,0x3328fc09edaf054bL,0xa8acdbcfa94396f8L } }, + /* 59 << 112 */ + { { 0xa05b72aa83a79820L,0x3210863ccdeeaedcL,0x192d5fdcb76fdabbL, + 0x25ec4568f10c17a7L,0xbd51e31fca556920L,0x8ab534f26a7e40f7L }, + { 0x2ecb28c041145d5bL,0x4e95843df9038557L,0x65605d17d783699cL, + 0xf728cb1178bddf7aL,0x2d823ae8bee2a60cL,0x02030edb8eb48325L } }, + /* 60 << 112 */ + { { 0xfe517758aa04facfL,0xa5216df44c421615L,0x4d87767d4f133b52L, + 0xdae81b7699757264L,0x53c1a0e3e3ad4323L,0x2c565bbd53b401bcL }, + { 0x94d2354fcd54a0e1L,0xf43d0f053f1a02a7L,0x52e7ee4af660b949L, + 0x563ec009bc208df4L,0x58c0b975bf21c4b1L,0x29a8e5adeb029e52L } }, + /* 61 << 112 */ + { { 0x4c07b3e4283bdd75L,0xcd94d2a385dd6177L,0xc1ab8a5cab097530L, + 0x90301468a5fd9ff7L,0x2a3e5b4064d0932dL,0x77e3b67e435e1c0fL }, + { 0x3b5d261c14f7bb4dL,0x1d67a760bab7bfc9L,0x507aad46d799621bL, + 0xf44567b5f4f3c3b9L,0xfaa97a3eae2bb6b2L,0x7d373b163594e2c9L } }, + /* 62 << 112 */ + { { 0x29ef2da9a15e6ea0L,0xf411e20dcd168689L,0x34944975049a4b24L, + 0x0effc2dfe035cd24L,0x5d77178b0a954cf7L,0x3504bc357ab2d8c0L }, + { 0xc3405000ec32219cL,0x00442630421a5a3cL,0x0548505c7f49819aL, + 0x6bdb281fc805d0e8L,0x03cb57ac97484e09L,0xcf0926da58a14cc1L } }, + /* 63 << 112 */ + { { 0x0715055cc85610a7L,0xd2642935fa6ca505L,0x87ef95128c361749L, + 0x89cd669a8c8156d2L,0x5cdcd266ed60d7ceL,0x99ccc96df59fb53fL }, + { 0x82400f4655df7f73L,0x2b6aa1d9af34f742L,0xa6cbca79c398aa8eL, + 0x7697bdea02b7325eL,0x1cb036b94fde4a79L,0xfe11ff96307fb964L } }, + /* 64 << 112 */ + { { 0x6a3a23279af0a75cL,0xf832a8159f1f250dL,0x17030c3322a82d3fL, + 0x24bf18ea14cbc835L,0x319dc4cab2da2727L,0x481df3606d020d4aL }, + { 0xaeebdd8a7fc22ba5L,0xbd0515c6a91e28abL,0xfc8a2978595f361dL, + 0xe60dd96c1ae8fa3cL,0x19c2109aa5341575L,0xfd6e92bb06a0ee48L } }, + /* 0 << 119 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 119 */ + { { 0x2e32f896cde5e785L,0xcd55ae7ab9db8f31L,0x278db1ad8f832885L, + 0x271d9078adcbd933L,0x2208fae34a64f863L,0x974046e039c89365L }, + { 0xcb46f272b3cd0cd3L,0x31f34e1a74e59edcL,0x3421d316edd50418L, + 0xb1d8a064cabe36edL,0xdb13e560362efcdaL,0x567c2b6cc71eb3eeL } }, + /* 2 << 119 */ + { { 0x2af8ed8170d4d7bcL,0xabc3e15fb632435cL,0x4c0e726f78219356L, + 0x8c1962a1b87254c4L,0x30796a71c9e7691aL,0xd453ef19a75a12eeL }, + { 0x535f42c213ae4964L,0x86831c3c0da9586aL,0xb7f1ef35e39a7a58L, + 0xa2789ae2d459b91aL,0xeadbca7f02fd429dL,0x94f215d465290f57L } }, + /* 3 << 119 */ + { { 0x94c3938b4c9324feL,0x0dea07003fe78a0eL,0x57ab9daa019e7dc6L, + 0xb0d7b14a9925b79fL,0x3c9a638b937a5daaL,0x3b14fd0de62943adL }, + { 0xbaafb635ed3ae4b5L,0x3060a090b2bcfaa2L,0x389d9e7f7aa8f217L, + 0xd7f987c6e9310a65L,0xec0927f993b69c0aL,0x9335e9102381a247L } }, + /* 4 << 119 */ + { { 0xc08550024b950889L,0xee99dbfe8ce24da0L,0xdda71d964318e860L, + 0x01d3d39604fe9b85L,0xda4bc065e25e7e20L,0xd3a50b87e076c81cL }, + { 0x5b9f821931e5f494L,0x6a140527a6a1b821L,0xf52683e4d8dd159bL, + 0xca9c888720b18043L,0x73c040fa08a0d8f5L,0x92e482e8179525c4L } }, + /* 5 << 119 */ + { { 0x8b9f650f3e776590L,0x41ba807f47703a5dL,0x8cc1a550fe907078L, + 0xd70cb76c8f00b84bL,0xcaee21566f3e6780L,0xfd6a51f595c2d03eL }, + { 0x2c897c5556ffa08fL,0x08589a6563d13d54L,0x6a1eed4287bbacf7L, + 0x66aed4f5ee709d78L,0x67c925bf1178ecabL,0x6870f4c8a29cf747L } }, + /* 6 << 119 */ + { { 0x37ed2be51cfb79acL,0x801946f3e7af84c3L,0xb061ad8ae77c2f00L, + 0xe87e1a9a44de16a8L,0xdf4f57c87ee490ffL,0x4e793b49005993edL }, + { 0xe1036387bccb593fL,0xf174941195e09b80L,0x59cb20d15ab42f91L, + 0xa738a18dac0ff033L,0xda501a2e2ac1e7f4L,0x1b67eda084d8a6e0L } }, + /* 7 << 119 */ + { { 0xe3a67b2d5e12e708L,0x3a4772e2ce48f234L,0x78f9dbc334794271L, + 0x9880053a3e6a61e7L,0x031c30b87c0f6e59L,0x8113df6cf7b972f8L }, + { 0x3625bdce18ee148cL,0x72c2b8efdb885158L,0x4c73c80c9a7f0df3L, + 0xbc2dd8a507b92470L,0x5a33e4dfdb005677L,0xc699cf5ea5ca9dd3L } }, + /* 8 << 119 */ + { { 0x3a828904a4d2313eL,0xbf4946b192e66888L,0xc574898ae5fa19d2L, + 0x0b13dbb65e1c5fa4L,0xf11343ba7c390fc2L,0x35b1418fd7d32187L }, + { 0xc92cb1bb83e7fe7bL,0x0b969455d78365c4L,0xda69dfe5672f2af7L, + 0x9c62d7b430932441L,0x165672ad94af02d6L,0xd2cc734dcde81c22L } }, + /* 9 << 119 */ + { { 0x6353420218d07dd6L,0xc7c0c8f128a3cb4eL,0xa41d4c55d7929131L, + 0xf1aaab3445d21f63L,0xd69a59545ec3e9feL,0x209732c1b8ddea2fL }, + { 0x368b9c59e1936916L,0xb011c662ab1f8585L,0xcce30a25474e57b4L, + 0xb79c76df7049c61dL,0x984739950ccf165bL,0x7c6f4ab40ce897baL } }, + /* 10 << 119 */ + { { 0x1d27efce1080e90bL,0xa28152463fd01dc6L,0x99a3fb83caa26d18L, + 0xd27e6133b82babbeL,0x61030dfdd783dd60L,0x295a291373c78cb8L }, + { 0x8707a2cf68be6a92L,0xc9c2fb98eeb3474aL,0x7c3fd412a2b176b8L, + 0xd5b52e2fc7202101L,0x24a63030f0a6d536L,0x05842de304648ec0L } }, + /* 11 << 119 */ + { { 0x907d88035a8432bdL,0x89232a5a2638fe30L,0xa120eecbe2089014L, + 0x3a5208cb5a2c9e97L,0xe163d29a3449eb4eL,0x3df984530eaba88fL }, + { 0x55d3b9afa1547443L,0x316aae18f2a60ceeL,0x64d0fd30d6e11a5aL, + 0x65de345808ef6002L,0xcede56fab4a3d1deL,0xa5bfa8d9a4bc1588L } }, + /* 12 << 119 */ + { { 0xd45e350133f4d416L,0xbb40233a4bf9131eL,0x1532a088e302483aL, + 0x3475e8b82c2485c0L,0x08f9ea56969cdbe6L,0x31928645253cd738L }, + { 0x1cf323a4ac9836beL,0xdf647ccf02b6e4deL,0x9a31e84fc06f3d09L, + 0xd326b86e39efe6d9L,0x77e3e1df14ac4decL,0xf2d5917af3e0c582L } }, + /* 13 << 119 */ + { { 0xf88238f1376216b2L,0x8c7522db7d15f653L,0x50aa7a74a21f74d8L, + 0xf7a964c8bc9e1a0cL,0x33ea64251387ca6bL,0xda84fe74e7be16a6L }, + { 0xdf0462d727867aaaL,0xeb7f0ab8ae6be1b3L,0x21abe5a5d9bdec8bL, + 0xdbb99199ac4bed1bL,0xf65c19d935d13c0dL,0xf966e22e4df74056L } }, + /* 14 << 119 */ + { { 0x67477cdc30577ac9L,0x51dd9775244f92a8L,0x31fd60b9917eec66L, + 0xacd95bd4d66c5c1dL,0x2e0551f3bf9508baL,0x121168e1688cb243L }, + { 0x8c0397404540d230L,0xc4ed3cf6009ecdf9L,0x191825e144db62afL, + 0x3ee8acabc4a030daL,0x8ab154a894081504L,0x1fe09e4b486c9cd0L } }, + /* 15 << 119 */ + { { 0x7b4e65ebae4219adL,0x2e424c441184a0d3L,0x10eeb898d32e179bL, + 0xadf05e2d8afa9a6dL,0xecd6c18bbeccd5f1L,0xe592115c39ac53e8L }, + { 0x9ccf231ac8c7b9b6L,0x1848b4fe678774bcL,0x2050856386782b91L, + 0xb7caf7cc74dc6018L,0xe80805485cf9273aL,0x9609897b246b4851L } }, + /* 16 << 119 */ + { { 0xe92b56c002cf37fdL,0xa75bbcb0f71b34deL,0x7754d0ef50f5c482L, + 0x850a9ef611fa89feL,0x97d74b1bba4ea7d8L,0xfc757c25aab7ba2eL }, + { 0x06f30ab0f2a67fddL,0xb10aba1412e72af8L,0x47580bca7a2e053dL, + 0x85795598dcf0e14cL,0xc3596781d6f55310L,0x8ab251b74c9b7e18L } }, + /* 17 << 119 */ + { { 0xdc56cff85279e5cfL,0xa33a6765fdbdf1adL,0xc122c0eee5077a4bL, + 0x44c3b190a98ab643L,0x334a6868b991d197L,0x598bbf185d6a0488L }, + { 0xd028bfdc5a0e6f96L,0xfd1a37f5e11c57b6L,0xe1240a3003f82183L, + 0x6afae98c390d8536L,0x554a42dcc244b181L,0xa3d422d75f4cb4b6L } }, + /* 18 << 119 */ + { { 0x512f82f9d113450bL,0x5878c9012dbc9197L,0xdb87412be13f355bL, + 0x0a0a4a9b935b8a5eL,0x818587bdf25a5351L,0xe807931031e3d9c7L }, + { 0x8b1d47c7611bc1b1L,0x51722b5872a823f2L,0x6f97ee8a53b36b3eL, + 0x6e085aac946dd453L,0x2ec5057de65e6533L,0xf82d9d714bb18801L } }, + /* 19 << 119 */ + { { 0xf113abe17d48bfe7L,0x51d77fa5213facecL,0x27bb373f21269089L, + 0x31e9850e7b188989L,0xd20a15f41d50a1c6L,0xb4887ed9d9746367L }, + { 0x8920a7e2325f19c5L,0x691352358ad74492L,0x713d1471d19a76a2L, + 0x952cb9e5873ab310L,0x5b359d1ffa8eb8cfL,0x55aab5ad8b9c9e7cL } }, + /* 20 << 119 */ + { { 0x4ab138504dbb8798L,0x0e7980d772d04cd2L,0x1755c5660b3271c6L, + 0x8414efb09d9d1468L,0x61a586301795ce66L,0xb6a8b393232924a1L }, + { 0xa992f0ceae031bd6L,0x6747fb5f2915acc1L,0x03daa26693e9c0d2L, + 0xc18fa3645400d554L,0xaf04ff8d9497e895L,0x86c3cfc250b6b339L } }, + /* 21 << 119 */ + { { 0xdf26f6605b26122cL,0xeb6c188c4d6b80ccL,0xae2efe59ccec172bL, + 0x5cdcd958f3f7d693L,0xa2ac2594c5f993f0L,0xb96ad8cf3f7cb591L }, + { 0x7e2f88f8446abbabL,0x3d1a5eb6f6051f2bL,0x7d882e82ad6f49daL, + 0xe32918e3c4e7bbffL,0x442a32789be81150L,0xa1d34da1bd14557eL } }, + /* 22 << 119 */ + { { 0xad81fa938ba5aa8eL,0x723e628e8f7aa69eL,0x0ba7c2deef35937cL, + 0x83a43ec56decfb40L,0xf520f849e60c4f2dL,0x8260e8ae457e3b5eL }, + { 0x7ce874f0bf1d9ed7L,0x5fde35537f1a5466L,0x5a63777c0c162dbbL, + 0x0fd04f8cdad87289L,0xca2d9e0e640761d5L,0x4615cff838501adbL } }, + /* 23 << 119 */ + { { 0x60c7e16cdf66a95cL,0x25b1078d5d0bd644L,0x77f8d872bd933e31L, + 0x5c4c382de2e1536cL,0x5b3b37c09295ee0dL,0xf94698d4ecce42b6L }, + { 0x947ef80c4db8f2c7L,0x34661f7dc70dd82fL,0x17b288a7f2311006L, + 0x1f1171a66815e1caL,0x0f71f66ce80d6235L,0x858c665a87fa5a59L } }, + /* 24 << 119 */ + { { 0x376b2a7f04e1e6e3L,0xea0dcb70a31774b4L,0xfc7fe4cc5cbdec2eL, + 0x8568499df03f459eL,0xe9fd8fb28b78900eL,0xd33c6e30e431bf97L }, + { 0xd904b8f5c896e766L,0xa8f577cf82748cefL,0x93dd921b87e044b3L, + 0x23d79837f76eebe9L,0x5e0a7493e569feebL,0xd0797549414dddb6L } }, + /* 25 << 119 */ + { { 0x9bf04f567781556aL,0x30be1e8953ebf7c6L,0x6f4899cf713fe432L, + 0x4f641fb7c9ef741fL,0x03560819002cc010L,0xfa51f8f7b4bbd339L }, + { 0xe09c5ef77f1dea5cL,0x39cb20d97255fec5L,0x407746862ea38859L, + 0x68ca598ecd7a29f3L,0xb8025dd67a9db4d9L,0x4feaeeaed9dfe491L } }, + /* 26 << 119 */ + { { 0x9422789b110b4a25L,0x5c26779f70ad8cc1L,0x4ee6a748ec4f1e14L, + 0xfb584a0d5c7ab5e0L,0xed1dcb0bfb21ee66L,0xdbed1f0011c6863cL }, + { 0xd2969269b1b1d187L,0xf7d0c3f2afe964e6L,0xe05ee93f12bb865eL, + 0x1afb7beeed79118eL,0x220af1380f0fe453L,0x1463aa1a52782ab9L } }, + /* 27 << 119 */ + { { 0x8cf42aa26b99ca6aL,0x696850242f091dbaL,0x9d887e6ad7d3270aL, + 0x627754fd5c9b735eL,0x3b8735a811d95df6L,0x74debd8b52443251L }, + { 0x1f8dd5b66181583eL,0xbd0ca92c8b570a9cL,0xc373a61a71ae3274L, + 0xf4b2c88d1c4c16cdL,0xd3e6ec3baf33efabL,0x8c54d2721bf6f0d0L } }, + /* 28 << 119 */ + { { 0xfd9e3542bfe5b1a7L,0xb42d2a4175938ceaL,0x74688a153befb760L, + 0x8daeeaa22e33dbe7L,0xc9c1ea083e677801L,0x68ecf4e434effe1eL }, + { 0x927700ccd294c321L,0x9e2e723de940afc5L,0xbcfac07a7cf6cd43L, + 0xa009ef94d1006bc3L,0xa02016b0373d13e3L,0x4e097adbabae5822L } }, + /* 29 << 119 */ + { { 0x7535175d48752720L,0xf51086ee850bdf07L,0xce322c33cb4c3f4dL, + 0xd863f7edb28965fbL,0xfe46a4e9885e4afaL,0x58b5c871136d7ddaL }, + { 0x126eddaf6ed07824L,0x084ce962844fcbb8L,0x9ac0787157dfb4c5L, + 0x97451fcc4d6b5910L,0x9f14b1ce0843c9c6L,0xf737f6c0a0e18596L } }, + /* 30 << 119 */ + { { 0x7c139d56d7dbe5f9L,0xfc16e6110b83685bL,0xfa723c029018463cL, + 0xc472458c840bf5d7L,0x4d8093590af07591L,0x418d88303308dfd9L }, + { 0x9b381e040c365ae3L,0x3780bf33f8190fd1L,0x45397418dd03e854L, + 0xa95d030f4e51e491L,0x87c8c686e3286ceaL,0x01c773bf900b5f83L } }, + /* 31 << 119 */ + { { 0x0028dcae855a0b90L,0x74c1e36026f0d718L,0x34f80e3ca059f144L, + 0x85b5d8e3f2bfe1b4L,0xe124601f453de099L,0x8b164ad6221b3efdL }, + { 0x636f45ebbe004ab0L,0xa23093e99f231a8aL,0x48e05e8e2287b992L, + 0xefec5e5b4477cb8bL,0x45a65afa8ba0231bL,0x92d38bd88b1af6baL } }, + /* 32 << 119 */ + { { 0x8db8b78cc898b8bcL,0x686896da502940cdL,0x67e50f022dde2e3cL, + 0x2e2461f38cbf406cL,0x32182781e1f7ff60L,0x26934b05e30e2688L }, + { 0x95adc204fc4494f6L,0x4c7f30c5161b7499L,0xd5caf060b7341737L, + 0xed93187fd128d46cL,0x3f2819cb20fc1e04L,0x48c4086f2b7f70a1L } }, + /* 33 << 119 */ + { { 0x45693c00a92ca9faL,0x046b218d63bd525dL,0x40f1d6cc6b1d6a68L, + 0xfc5807c5c54dc1f0L,0x2875d4d98b5690f6L,0x7a753543d0f72a83L }, + { 0x01f2c35ae28b5309L,0x38fb5f121bcef323L,0xd6ea6896256a9bffL, + 0x4380fb2c44d65badL,0xb587d641c3556fb6L,0x74c5ec1905167f32L } }, + /* 34 << 119 */ + { { 0xdabe347578673b02L,0x4f0f25cef6e7395eL,0x3117abb9d181ad45L, + 0x4b559f88aa13de0bL,0xfd8efe78ea7c9745L,0x080600475dd21682L }, + { 0xc0f5de4bd4c86ffcL,0x4bb14b1ef21ab6a2L,0xacb53a6cf50c1d12L, + 0x46aac4505cc9162eL,0x049c51e02de240b6L,0xbb2dc016e383c3b0L } }, + /* 35 << 119 */ + { { 0xa1e3cb2255b7f121L,0xc9183b13dd01db7dL,0xfe26aa801469dae6L, + 0x7318df7fd9ecfe2bL,0xade0a24d56dd4acfL,0x6e521c2222d1ba14L }, + { 0xa039800a40afa1deL,0x9c7da49d5c6af72aL,0xf7ae921cd3fcc7c6L, + 0x76af2407dcab63e2L,0xdc1618dbb6dd49ceL,0xebc65c4d362cc88bL } }, + /* 36 << 119 */ + { { 0xd847939132202bd3L,0x1dacde87d6631ac1L,0x99d2e71f905a94f4L, + 0xd3c21f5a7e67dd7fL,0x3605c28e3c43cf23L,0xb6cd5ac74d3b3070L }, + { 0x8bf748ba246298d7L,0x9e939fbd0f053664L,0x3bb3e7b8cc303783L, + 0x359bd3e56189c417L,0x299d0ce1f609ae34L,0xd7221cc7b9ca801dL } }, + /* 37 << 119 */ + { { 0xb7c823506b73c5a6L,0x7fea0d95fefee640L,0x6d5dd775f68b6be6L, + 0x4a5576147cbfa333L,0x6cad79c2fcd9b17dL,0x49aec3d405c4dd35L }, + { 0x3b1f3754c3792470L,0x351ef2ccbe00cffcL,0x44a248916a71f45eL, + 0x1e7a6013b8640d08L,0xf0f476154efcd556L,0xc82171444fe15dd3L } }, + /* 38 << 119 */ + { { 0xa3c56ad28e438c92L,0x7c43f98fb2ceaf1aL,0x397c44f7e2150778L, + 0x48d17ab771a24131L,0xcc5138631e2acda9L,0x2c76a55ef0c9bac9L }, + { 0x4d74cdce7ea4bb7bL,0x834bd5bfb1b3c2baL,0x46e2911eccc310a4L, + 0xd3de84aa0fc1bf13L,0x27f2892f80a03ad3L,0x85b476203bd2f08bL } }, + /* 39 << 119 */ + { { 0x85f9b301218642acL,0xb3f3b36f8728ef66L,0x4a833bea2ebb8181L, + 0x7d3bca9d8541a662L,0xd3be6d0ac5a0ecffL,0xaf52a2a9528da950L }, + { 0x4b431910131f72caL,0xe2708d36933d5550L,0x195340a469abf146L, + 0x84ca66e4e4e2e131L,0xd9402ca7e16c39bfL,0x5beedce343ca6041L } }, + /* 40 << 119 */ + { { 0x87c5915395523a22L,0x56686f525ac5146eL,0x9ec69ec718ccf766L, + 0x13f36d4ff6e21a4aL,0xa0841e94098691f4L,0xbd9d52d2bd91dd2eL }, + { 0xa8765981b3fa43eaL,0xb0cd17cd600b9761L,0x02dd9d71b5abe842L, + 0x63df33a63689a53bL,0xab4b85bb9d9baad7L,0xce2d31c1eb74e549L } }, + /* 41 << 119 */ + { { 0x8d69a654f2472426L,0x91a4b6a3ff7aeff0L,0x51dd8e76fdcc7cb4L, + 0x5f7d42a273731cd7L,0xc127401aa99c9d9aL,0x8ede9330c92561d7L }, + { 0x86057a56784c3cf2L,0x8afcf32cb5a7755eL,0xa0a5b561c71cd3d9L, + 0x0a5d805e36d3f5a4L,0x25a39acd7432a384L,0xd574a6b7b226e9ecL } }, + /* 42 << 119 */ + { { 0xab1cb818567af533L,0x273b4537bac2705aL,0x133066c422c84ab6L, + 0xc3590de64830bfc1L,0xea2978695e4742d0L,0xf6d8c6944f3164c0L }, + { 0x09e85f3dc1249588L,0x6c2bb05d4ec64df7L,0xd267115e8b78000fL, + 0x07c5d7aec7e4a316L,0xcb1187ba4619e5bdL,0x57b1d4efa43f7eeeL } }, + /* 43 << 119 */ + { { 0x886e3f30b29f5916L,0xa419d2c6625f29a0L,0xb4f89fc49bf07dc4L, + 0x86c137a1a165ed88L,0x6fa241a9e5d6280dL,0x08be9b0cd11576f2L }, + { 0x5735aeb7e376b03dL,0xf4639e6d182ce9b9L,0xb6948499cc688f57L, + 0xfde146636552009eL,0x3eeeae350a2e8553L,0x50447f1b659dfe2eL } }, + /* 44 << 119 */ + { { 0xefccd67ed15c33c0L,0x33393846146d5e96L,0x015e97da9ca7354eL, + 0x729b69bac143e795L,0xd4440ecfd4c5d0e2L,0x78c042bb697a80e7L }, + { 0x9361ad1d08602f75L,0xaa354166af489794L,0xe60e5a274966d3cdL, + 0x8346995e2394f9f3L,0x2de33256590f6a15L,0xb14427bb43298ac1L } }, + /* 45 << 119 */ + { { 0x38fee83a74680d2cL,0xd8019e5c0e700c8dL,0xcfaf5614475da1b8L, + 0x11893fc58f0159e3L,0x4c101127553813c2L,0xd273055208f82a6aL }, + { 0x8728834c74a3ce9aL,0x66b939a891906488L,0x42ac7c07b88d36bcL, + 0x663d7411d989bb72L,0x650e5d6eb284c066L,0x052b7f6710d8f124L } }, + /* 46 << 119 */ + { { 0x3618891fc8176a96L,0x62c4b084e5808b97L,0xde5585464dd95d6eL, + 0x27a8133e730b2ea4L,0xe07ceec36af318a0L,0x0acc1286ce24fd2cL }, + { 0x8a48fe4add4d307cL,0x71a9ba9c18cde0daL,0x655e2b66d5d79747L, + 0x409fe856a79aedc7L,0xc5a9f244d287e5cfL,0xcce103844e82ec39L } }, + /* 47 << 119 */ + { { 0x2a8cb0a56ad833c5L,0xe8fab8b844962dd6L,0x31166fd63ee1dfefL, + 0x3aba85a1e1230449L,0xf9f8da66bd1f502eL,0xe4a72d82e3c17ccaL }, + { 0xfa3d661d6070d587L,0x51d10b73c33ed08aL,0x3b0f515cb29f2d0bL, + 0xd82a11d7e1986e91L,0xcf24f81a2201f05bL,0xa94ec1e0d25f8417L } }, + /* 48 << 119 */ + { { 0xc7807daa081ed51dL,0xb7dfabf0e5d2d963L,0x3f78ae2e80d386d0L, + 0xd66275254bbfd04bL,0x238c8eb76d074f92L,0xfe51ec8a5bc5f9b5L }, + { 0x6ba47430cc03177bL,0xe72efda6400b29e0L,0xb905701becbffe88L, + 0x5c61bdb47cf89933L,0xf1eb3084c914aa6aL,0xa3ead71e8245998bL } }, + /* 49 << 119 */ + { { 0xc58ee3013c7eb5a9L,0x02c177220a1172baL,0x8620118394c7c5b3L, + 0x66292bc4e1668debL,0xf51b48f4caf39937L,0x9cca60f43eaea578L }, + { 0xf8e8004a5c2adccaL,0xce7ceeb1ebf49ac7L,0x36346357371d1c54L, + 0x8799e408d99ff07dL,0x3226181d8c3b2cbfL,0x3b4ff42ba437c2c6L } }, + /* 50 << 119 */ + { { 0x00675ba7f25d364cL,0x7a7f162968d36bdfL,0x35ec468aa9e23f29L, + 0xf797ac502d926e6cL,0x639ba4534b4f4376L,0xd71b430f51ff9519L }, + { 0xb8c439ec2cf5635cL,0x0ce4c8d181980393L,0x4c5362a964123b15L, + 0x6e0421e0ffdcf096L,0x624a855f10d1f914L,0x7d8f3ab7614dcd29L } }, + /* 51 << 119 */ + { { 0x235ba8b565868390L,0x853c9346ea936e81L,0x967ff132700bb25aL, + 0xb26d9778561a136cL,0x8b775c4fe3f7e41dL,0xae8f6b2ebd390b2cL }, + { 0x80959adc4fc7224dL,0xd9c913c12eaccf8cL,0xa9a278c79e96f769L, + 0xbc6be3038f26856dL,0xb039caf295d04cdeL,0x42ba0510a91bf5dcL } }, + /* 52 << 119 */ + { { 0x77870665cfbe0653L,0xab84c4b3523d814dL,0x72839d8897cd2bc0L, + 0xb966e521d25b1476L,0x4255d18451fd86a0L,0xadaf9b76dd54be7aL }, + { 0xada6ff627f285e0bL,0xb76e26f46d42400bL,0x1d9fe676958bee25L, + 0xfcd7be9edb59965cL,0x897a90834bcf6e75L,0x64b26f02aabd21e8L } }, + /* 53 << 119 */ + { { 0xee46626beb1a8ce6L,0x2de20371b672fc49L,0xa0fb11b8bd2d9256L, + 0x5b49f70ac2a8dcd4L,0x98935fc9e5dc0ee3L,0xaddbae423bc00993L }, + { 0xbd0bd9e19207f0e9L,0xe86c5365b393bcdcL,0x32184c832d0a9282L, + 0x8fe996d1df34532eL,0x3b33f151c6f45172L,0xd9def9a7b84545e4L } }, + /* 54 << 119 */ + { { 0xd9219adab3493ce0L,0x971b243a52f09ae5L,0xc16c9bf8e24e3674L, + 0x026d408dce68c7cdL,0xf9b33dd9358209e3L,0x02d0595df3b2a206L }, + { 0xbf99427160d15640L,0x6da7a04e15b5466aL,0x03aa4ed81cadb50dL, + 0x1548f029129a4253L,0x41741f7eb842865aL,0x859fe0a4a3f88c98L } }, + /* 55 << 119 */ + { { 0x66bb66f5f56b17ccL,0xdce0bf2cba8958f8L,0xd814318f9ff85781L, + 0x41dce823edd1ad96L,0x71bb754bb59c6580L,0x9c5efb70de594c3bL }, + { 0xf7b4ce5eb0053788L,0x9c26b0342770b6deL,0xe6967b1c8d131e8fL, + 0xfda0efdccf21bf28L,0x2366d47e09cbeeacL,0x62e9ee556629680eL } }, + /* 56 << 119 */ + { { 0xdaff980ff8e06359L,0xb4e0c9e2ead8a883L,0xe3e262023da6e94fL, + 0x37410ed03303c9d6L,0xc044d77b91fb5d82L,0x3559d9ac9ea34d26L }, + { 0xf51a120be21beda5L,0xdd2eef8a3f7befa4L,0x46a26ccd8c79fca1L, + 0x3fb21a682a046572L,0x3624a47adad7c7c9L,0xb9b77ffd4b4174f5L } }, + /* 57 << 119 */ + { { 0xae19a097c9f8c462L,0x477be49917a9d8a9L,0x4a0c41c9d2154c45L, + 0x39313aba1b0d985bL,0x3a70f65cc051b643L,0x0725dabf2d0be160L }, + { 0x29eefc94a69867d4L,0x6acc4cd49d02bce2L,0x0606ab725d4dca50L, + 0xcce81133bfecdcbaL,0x604df3def23b2239L,0xa644b430d20a7529L } }, + /* 58 << 119 */ + { { 0x80de085a05fd7553L,0x4a4ab91eb897566bL,0x33bcd4752f1c173fL, + 0x4e238896c100c013L,0x1c88500dd614b34bL,0x0401c5f6c3ba9e23L }, + { 0x8e8003c4d0af0de5L,0x19b1dfb59d0dcbb9L,0x4a3640a9ebef7ab6L, + 0xedafd65b959b15f6L,0x8092ef7f7fb95821L,0xab8dd52ece2e45d1L } }, + /* 59 << 119 */ + { { 0x43f9a415259ac609L,0xcd6c7aaa0ff5722cL,0xb4689e75b29973caL, + 0x78a43571b690c0acL,0x90dc4ac0a6d3ba1fL,0x38af00a2b773932aL }, + { 0xc13aebdda5e2c9edL,0xfab3a128cf3fed2dL,0xb3b7d29d32eb8ccfL, + 0x9ae1430b6986db5cL,0x35d18edf5365c21eL,0x88f8356e038471ccL } }, + /* 60 << 119 */ + { { 0x45587a7c0794dad2L,0x660833899e9c1cdcL,0x60e7ae4ad242a6b9L, + 0xb5f96b521009df3cL,0xc2d405092e30445aL,0xfa53ba4ec250a29eL }, + { 0xf6a247855d98c6ceL,0xf873653c207dd110L,0x2aebc3c6c634cbd0L, + 0x84b8016ce5cdbafeL,0xbda81fcace00b206L,0x837dc69484b55f2cL } }, + /* 61 << 119 */ + { { 0x61bdc5cab308f1f0L,0x7763c97d8898d3c2L,0xc02324e60434de23L, + 0x7f5c565e4ba696e9L,0x06f27a3e66914b66L,0x64a975ee05052cf5L }, + { 0x98b2f703bb38b14eL,0xbacbd113371e495cL,0xe54451acdd14cc9dL, + 0x8575cfdf87d141b3L,0xbd183a03d0996091L,0x947555579360264cL } }, + /* 62 << 119 */ + { { 0xd1f2d6b8b9cfe6bfL,0x6358810b00073f6fL,0x5fce5993d712106eL, + 0x5ee6b2711c024c91L,0xd0248ff5453db663L,0xd6d81cb2adb835e8L }, + { 0x8696cfecfdfcb4c7L,0x696b7fcb53bc9045L,0xab4d3807dda56981L, + 0x2f9980521e4b943bL,0x8aa76adb166b7f18L,0x6393430152a2d7edL } }, + /* 63 << 119 */ + { { 0xc89db4eb4595ca55L,0x48921c735f1a73a2L,0xfc513c904afe7cbaL, + 0x6d3f988bff8322eeL,0x17d0d4f0e59b7cdcL,0x292f4757f4bb5588L }, + { 0x3037e11151c14623L,0x3e113343dce98277L,0x0be229341e20dc8fL, + 0x0ebd1fbfcd6ff82aL,0x304bd69ed01fa90fL,0x402a457577f1862fL } }, + /* 64 << 119 */ + { { 0xd74d09c10ece13aeL,0x5e59d9e057a6bd95L,0xdb1ccfdce132b940L, + 0xa0e5309c843d3c66L,0x1fbd03a5f9cb3ef4L,0xcdc9ef0a00ea5177L }, + { 0x1ebf5a15cb784a6bL,0xa67382af8a0d109aL,0x3256c37aa0d34d15L, + 0xee40efa50fca43afL,0xc299bbd4b9841bdeL,0x6df68f603bef4a0bL } }, + /* 0 << 126 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 126 */ + { { 0xe01295fdd9d7c50aL,0xaf31b4ea67f8ef0dL,0x2ec9689f9eaf8eb7L, + 0x327b96c5c622acc5L,0xae918f81b2757f2aL,0x74927d684fd6606eL }, + { 0x09bb7fce18574215L,0xfea383bce8e68b72L,0xdf2a6f125fb47511L, + 0xbe88faa18e399520L,0x0166d57e3fb1c3a2L,0x5907ef2fe525f81fL } }, + /* 2 << 126 */ + { { 0xdefe3a7b8a37f660L,0x7898db8c858f5765L,0x7366c26a73d1f9b4L, + 0x35d5d718237ae8b7L,0x3efb20feb4478259L,0xccd0fed7aa545ee3L }, + { 0x750edd05ed22d152L,0x4f8020f9ee20d4c6L,0x16e60f370a9e29dcL, + 0x9cf0a136bfbec7f6L,0xb430a34b2e47e143L,0x2e2560bbc6cdd1a9L } }, + /* 3 << 126 */ + { { 0x799352dae4161a65L,0xe5cf7ad856253ce6L,0xf606bf796de32775L, + 0xddc0f3a357fce8dbL,0x1075fc2316cf4a47L,0x078f0e04b27c5ad8L }, + { 0x9fc477953f7100aaL,0x3ac489254673ffa2L,0xb8263f42f9cd8348L, + 0x5bdfde3068cc92d5L,0x2250927b1ac37f9cL,0x26ec8328b33da359L } }, + /* 4 << 126 */ + { { 0xf186d6bcc88d568aL,0x872bc4c7528535ddL,0xc9e7432edfe64dc3L, + 0xd9fc4832d795ea57L,0xf4ffdb81c845af2bL,0x66d7e7882b670517L }, + { 0xa7c1be04d7b7a1c6L,0xbed88479d5b2a249L,0x62ff8aba03f2ef6dL, + 0x60ecaac420dc701dL,0x9f4b559f4ff10119L,0x0582c9313cd54fd0L } }, + /* 5 << 126 */ + { { 0xea9da8f012bbaeb6L,0x3fba06b18c9f8360L,0xc11bd7abb28c0ac3L, + 0x1e05af2faa8a01bdL,0xae1e99c5f000b1c3L,0x93ee806453d79930L }, + { 0x5728089e4c4f5513L,0x755351f3b1f70b76L,0x187ac651675f77efL, + 0x5cf7bfb553067d84L,0x629290838174b5c0L,0x720e20798d5be74dL } }, + /* 6 << 126 */ + { { 0xab8cc09ff5eb9ad1L,0x97a4de76132edbfeL,0xa2e11c548baf6347L, + 0xcee54229683cfcf6L,0xe1e993b8dcfc6555L,0x333bf16abe9df066L }, + { 0x5207e093060d62dfL,0xfa32324d69b0f5faL,0xef16fbcfd3243d2dL, + 0x540a2e59f04f8e45L,0xb5e70f9c48317bbaL,0x00dbe9b25b35baa1L } }, + /* 7 << 126 */ + { { 0x0eaed675ebb512eeL,0x347e0756058efbd5L,0xadf792ca296d3d47L, + 0x57f00c0a4654d012L,0xa1e08a04bccc5803L,0x610677f05b2f11d1L }, + { 0x0d9393d7b81acfd2L,0xb258e1570587c219L,0x372a1857b4ceba47L, + 0xe1ce8bb53ecc1c5dL,0x7efdf301922cecd0L,0xcab8cb170d8aa653L } }, + /* 8 << 126 */ + { { 0x31954a5679d05497L,0xc12520b6fe76d4d8L,0x8c433ec5e37ef1d2L, + 0xcd0f203575bc3b66L,0x3723f145249cd98bL,0x1356e0d2ea3b42a3L }, + { 0xf607fee0f174c7b5L,0x318afc5e0127be39L,0xd47b5d74cea5417fL, + 0x6891940a10fca22bL,0x5cea41332b635e8bL,0x93db2ed6b5934fefL } }, + /* 9 << 126 */ + { { 0xf87cfaaac8972b7dL,0x2b8f9874e090800fL,0xdb88cd4f52efde36L, + 0x7b977f6e80776de8L,0xd047fc8ffb4b19c4L,0x33f3e43578b8135fL }, + { 0xb4cdb352da33eff8L,0x217f9e2deb89d325L,0x1bb5a004c99feec5L, + 0x98ce5a7fdb45c845L,0x458904681d87e964L,0xb9253873d151ad80L } }, + /* 10 << 126 */ + { { 0x5d7c767de39edca9L,0xe4a700e7a7f8de0cL,0x5816e1f93c9eec33L, + 0xa975c933d32fe465L,0x979beff968466a5eL,0xe308c135cc067721L }, + { 0xe0e733b41839b88dL,0xda3e3e6c298dc2ebL,0x414c3f0e8fb70e3eL, + 0x5ebaefa7ed7ca91cL,0x5c283310ae3b0f3eL,0x20353d5df3b1d44eL } }, + /* 11 << 126 */ + { { 0xd50767a9790325feL,0xe2ceddb9358c50eeL,0x60be64bdbbf03ae5L, + 0xe70c7e90f053328fL,0x6ba6af9e51543f0aL,0x470941f3b413e069L }, + { 0x0b569fd4ddf63d13L,0xf94b22634a2125d6L,0xaa45ab62a5c1acedL, + 0x2b797175defa5a30L,0x3eb30067ead1d440L,0xcadb54e90b691af2L } }, + /* 12 << 126 */ + { { 0x365a4a431630b133L,0x9ecef631068d7863L,0xa330c8b4b7205a6fL, + 0x4858eab357df815cL,0x6e522afaf1a92674L,0xa7cff3d9f41365d7L }, + { 0x00dd34615a0e4626L,0xa695feff48f9d094L,0xf427103f7c082301L, + 0x14a2a1876b092b71L,0x210f632130037a33L,0x21cca09639340e14L } }, + /* 13 << 126 */ + { { 0x58355ba0f60ad6c1L,0xc63fbcff56022afaL,0xa6a770d54e7ef19fL, + 0xf42b2024a09e9378L,0x153aa3200330f774L,0x268aaee55dc02c97L }, + { 0xa7e13b42828f7ab7L,0xc0ccce09c303bfcaL,0x23169daae3ccb6ddL, + 0xf7f763fd786774e9L,0xb15a5ef150021488L,0x52f408fd5f3ea885L } }, + /* 14 << 126 */ + { { 0x53e84021177346c2L,0x4ee451dde20af475L,0xd7642453c14f393eL, + 0x7eaa215331662516L,0x1217a1b4c1d486c9L,0x7d32427569860f20L }, + { 0x3813c95f14c2837eL,0xb8f0713d4e0c056aL,0x398c218cf6dec37bL, + 0x5bfa2eefa4ad1eedL,0x53cb0fd29f97a05dL,0x59fa132f6a9f492bL } }, + /* 15 << 126 */ + { { 0x6d5dff381fc2c16aL,0x5dec7ae2b1fe149eL,0xa9eed62c85088ceaL, + 0x5878fdf7996174baL,0x2cf65bb935517a73L,0x80844bcacff96d13L }, + { 0x0f55c8bfed53f49dL,0x35815fb0fbd8cec6L,0x23e7d5c53b6fa7d9L, + 0x3ee04c0146ce1733L,0x180e25553f5c4a27L,0x61263ea7280e6363L } }, + /* 16 << 126 */ + { { 0xb1f4fead41b959b5L,0x6edb53a9e71890c0L,0x48b47efe2e28aa2aL, + 0x70dad2e9b3151d67L,0x87a8178b436a3460L,0x0f86f9f5801f7af7L }, + { 0xfab462e3a982fc14L,0xe29126bacb03e978L,0xb4696b3fe6681282L, + 0x3bd9910a6a3fdc1dL,0x4409128449e37dacL,0x3b4bfabccf605fb3L } }, + /* 17 << 126 */ + { { 0x605fae7ece9d1372L,0xb2623a79f9b7e06eL,0xfab9b2742d37357eL, + 0xffdf9246461417f3L,0xc04b15d7bdd0e922L,0x767bcee54b2dbc0eL }, + { 0x74c4ea4ed45efc88L,0x32d3d85491a534a8L,0x88967078554b2691L, + 0xe8256015e336a410L,0x166469624b9f978bL,0xb433f06ca104f01fL } }, + /* 18 << 126 */ + { { 0x8906d815457e1e82L,0x96abb1aa4c8a2c68L,0x2e63f37927ab2fb1L, + 0xe092e15f5446dfaaL,0xa3a3f0926615c65cL,0x8b31116747c3f259L }, + { 0xfe2038782e5c658cL,0x38903cf526215773L,0x0039fca7237f1bd4L, + 0x75dbcc016058ff17L,0x67ee6226a65aeb9eL,0x96999fa75cedcba5L } }, + /* 19 << 126 */ + { { 0x04c6fd475ac4d191L,0x0067e474c825a897L,0x4a37c931404810c5L, + 0x072d30e5c4a56380L,0xbaf3428dc897ba23L,0x9899935b53724382L }, + { 0xda5cc13ff4d41a62L,0x063047a0c6271baaL,0x49790bdc5cf48302L, + 0xd8c34e5384c5a9abL,0x6cf28e83db5bc36aL,0x430dbb1497da9d42L } }, + /* 20 << 126 */ + { { 0x59470e49c37acc2eL,0xc9e0f73611b85596L,0x47613c1e0fb30eccL, + 0x1fbeffa3b62892f1L,0xddfeef49f8eefa16L,0x6f82acd9daeff719L }, + { 0xff1872cdacb41007L,0x06fe556c82d64c6dL,0x52a63a387695218aL, + 0xa0d413a720802b88L,0x233f1f3118f4a473L,0x22ef7d6fc9d7da4aL } }, + /* 21 << 126 */ + { { 0xeba1db6910dad9abL,0xddb62dacde3a5a42L,0x209c472cfdf5ad86L, + 0x14a7ee4b37214540L,0xcaf70ce08339c9dfL,0xa95744554eb9189bL }, + { 0x90d7f241e9b39189L,0xf5edfd09af7f3eddL,0xc9a3444deb7ed52aL, + 0x30d9e2f80085d9d1L,0xeb412daa4dc24fefL,0x55c0000b27786649L } }, + /* 22 << 126 */ + { { 0xa9f34fa9518118e5L,0x430db0a51a22e790L,0x64b443a5d5a16ca1L, + 0xaa3b64f4d8adbe45L,0xb49435fae0f0873aL,0xb8d67ce4a635d1e3L }, + { 0xad843f8a8a612b29L,0xa416ec7fd84a210aL,0x8b4dc6930984b23fL, + 0x29a1b71b24640dcfL,0x8f2d7507911892adL,0x0ce384105bd4d518L } }, + /* 23 << 126 */ + { { 0x1e1bef926c42e1bcL,0x91259dd60e04d449L,0xc029961e8875d346L, + 0xfde51012a9e38f43L,0xdeaa1dc18892643aL,0x67e3b913217e08d8L }, + { 0x889a28c269b92b7eL,0x004c0f87b7446c21L,0xea812f67a2f98e77L, + 0x42fc7bbe22c40b8cL,0x5e7f5f5a8722e381L,0xf8f209d932099e41L } }, + /* 24 << 126 */ + { { 0x867379134a2965f5L,0x34724dcde67b3546L,0x2efe185ee92c712dL, + 0x8b908f86c201e327L,0x3ab5528894f6b078L,0xb9b2b784ce0a5bf3L }, + { 0x5eab37ac879f6a41L,0x74271f672f2360f3L,0xf3a3edff304f1cf9L, + 0x8992ecd8f6fd3e90L,0xff24d7c69f16e5edL,0x0844ab25def9a5c4L } }, + /* 25 << 126 */ + { { 0x35cbf2191e14f235L,0x9ef33f3c4cdc1b46L,0xfd5cedd0299f7f13L, + 0xf57b9bbf99379e17L,0xae25d3e3cd3d59a8L,0x72f9fc84f58cb31eL }, + { 0x87950fd84c94b63bL,0x15b52b4f7a4560a8L,0x382d36ec943e44baL, + 0x567ce2e9337b0f11L,0x8136e9ce2fa44901L,0x7e43a7289b15eeaeL } }, + /* 26 << 126 */ + { { 0xd1c8ed8814fb95f4L,0xc302e0aa29602659L,0x67abcce005cd67baL, + 0x7a234cc022f8ae25L,0x7074face39f44e4fL,0x84a08afc7a9d3fb2L }, + { 0xfd149c88f56c1f32L,0x5b12cc15219e494aL,0x242fc50c9ea3c0e3L, + 0x196cdba555b23034L,0xfd8cfa5e87b75206L,0x915e706488d55f47L } }, + /* 27 << 126 */ + { { 0xb59480ba876145beL,0xd8f8fbbe8e1075ddL,0x0ba10292b5d9baf0L, + 0x3a4b7f65e39a8754L,0x1b3a044c0f3c6520L,0x6b8b3397b1dff4f8L }, + { 0x40cef2285c182eb3L,0xbef82aec1b1cb92fL,0x5c4d2bfc2a97c5dfL, + 0x41d2a046536ad077L,0x94ef34a8c497505dL,0x14e9aef48e0b35ffL } }, + /* 28 << 126 */ + { { 0x2edaaaaaacaf1f3fL,0x9e3af72c80ebcc10L,0x3542fc42bcb1618fL, + 0x6c04ec246709d851L,0x5fe9768ea9af4ce0L,0xe739d50eeb6ebe2eL }, + { 0x7b7da4ac876586e0L,0xb0869f1d64f5f956L,0x7f691c51fd563c80L, + 0xea990d6926c775e1L,0x2cd96f1321b58889L,0xbc8074720f1aac2cL } }, + /* 29 << 126 */ + { { 0x8e1fa5f8eb3283cdL,0x0107a3ba20e69342L,0xf99a511cb045b8dfL, + 0x172d0c8933b51876L,0xb11efc2b9636d0f9L,0x16b2197c41570483L }, + { 0x49df27edacfdfd1aL,0xd9d2cedc366b9b28L,0x0289a75cab028c0fL, + 0x522f567a4879464fL,0x3313728225f64030L,0xfa28cb1558d6753fL } }, + /* 30 << 126 */ + { { 0xe5252210c6cd33f0L,0x6ba7f51f3f085202L,0xd2a87fb38f52e312L, + 0xa5e082cff25f35efL,0x786a93c2b9df2f20L,0x68c7e1299a19bf27L }, + { 0x13a971ab8d710915L,0x3ca4f8c6939443c6L,0x8554699c70522446L, + 0xdf42b7768e14e6bcL,0xc7969fa5f7f3dadeL,0x135b6b77350ded88L } }, + /* 31 << 126 */ + { { 0x39e54aa472546076L,0xc0003f7f13e312beL,0x71106a4ffea91274L, + 0x3868f957819851cfL,0x713b96e75c85bbc6L,0xfda8c2df610403a8L }, + { 0x0ea806c3a008cf78L,0x0ef9708353c0d1bdL,0x536950211e592838L, + 0xea3773d5e9023982L,0x6eee3c0d4195754cL,0x95df7b568c4bead3L } }, + /* 32 << 126 */ + { { 0x57edf71edf9a9f18L,0xbf834240627a0b79L,0xb37aba1aa6934160L, + 0xd45b3d2c5e639a54L,0x62c6b9ad70bce957L,0x16bc35a75d7e87f3L }, + { 0xb021698266b4a982L,0xb56050dd0e51c9bcL,0x15aa692b478e4b91L, + 0xdd67cf29be3fe25aL,0xf1ef75b006bdd4a8L,0xf71a285b41df627aL } }, + /* 33 << 126 */ + { { 0xba6be58993032120L,0xea6dd691db99740eL,0xad8679463154648dL, + 0xd1a36f4c28c0668cL,0x09a28c234dd76e88L,0x93fef0c7dc665bb7L }, + { 0xa78dfeb4860a0016L,0x06d2f868e21a9e02L,0x333a25a38486ade7L, + 0x12aa13130e398a80L,0x04a44a5848d5b3e3L,0xe59293d47a7ec12eL } }, + /* 34 << 126 */ + { { 0x6cdfb5faea2c1632L,0x6799cfcd7865f931L,0x4e1e5d25bf420a7cL, + 0x7d4597db05d22ddaL,0x7548db12fceda1e1L,0xb4523ccdcb473578L }, + { 0x3d8dbad0ff889f03L,0xc591bb1118a9a222L,0xfac2b914a2cfcc57L, + 0xbb67601abec9d9bfL,0x18dff42ceb55218dL,0xb36ef9ba7d2b6320L } }, + /* 35 << 126 */ + { { 0x5b007ad1f3edf67dL,0xfaee9cada25fcfafL,0x18fc784a4d62e5c2L, + 0x98deda878acb5f8eL,0xe9cfd10a6f888d8fL,0xbb0d729b053db2efL }, + { 0x7b09fa4f2aecece4L,0x3f72187cd4c44cc3L,0xf646aba05b8175a5L, + 0xf213caeba5686ca7L,0xf5ce777badc5d40dL,0x15ff85d660eb9357L } }, + /* 36 << 126 */ + { { 0xcdd18aee24e6df19L,0xa08ab968bbb3303eL,0xd5eb039cbab4f1a3L, + 0x040d03a8fa7a48d1L,0x767c0ed23d66628bL,0x0c6bd388b1a6809aL }, + { 0x793aff3f029eeb91L,0x6db32d13bca798a8L,0x6aef5c1cc3816cf7L, + 0xcfb25ea45fd2cd2aL,0x0715a7899f8e3312L,0x4a9ad4782a6b1a6bL } }, + /* 37 << 126 */ + { { 0xa9f360a5d134c919L,0x10dba223dcfd0715L,0x7444b191dc9b4394L, + 0x9a16a971e2f288e0L,0x0d05c511f6a49999L,0xca34eae26b65e956L }, + { 0x692febc418a83b76L,0xf3468c7b0b5f3511L,0xd8d3ce48b8e1ed80L, + 0xbe8c5c302a6de231L,0x9c0468b74e680d8bL,0x773ebb63f57b88d3L } }, + /* 38 << 126 */ + { { 0x9c2c33a5b726729dL,0xa86ab4ea5db2af56L,0xe987c5e3b0a36ffeL, + 0xa6dba84da5fe8bdaL,0xe1fefa4b8ff617a5L,0x561cdb88a91ad714L }, + { 0xeb58f7fce145ddc0L,0x7b0e560a29c5ad50L,0xf8d6626593da0e76L, + 0x7769b479db39fb92L,0x9149f1e3a3c49033L,0xb706057f3ac49c35L } }, + /* 39 << 126 */ + { { 0xa678ba3fa527d157L,0x922aab268856a8b2L,0x936d3e85690b4771L, + 0xed78dccee114e472L,0x9694ccb1d315fbc1L,0x8b1cf4482822d968L }, + { 0x336e670c4aca5441L,0xece24fb58f0e2824L,0x28d1578d05b758adL, + 0x0a1be96a40c3f019L,0xed1586e30b659cd6L,0xdef180009f860dd6L } }, + /* 40 << 126 */ + { { 0xc2885af90fe0f372L,0x2c756bef5fa6b808L,0x52b7f7b6068926bfL, + 0xc9399c1ddb143b68L,0x0e77c689e4c61211L,0x7d01e37f15ad7fa0L }, + { 0x712fc61f188b2a01L,0x103685ec55a4100eL,0x721f9c02e5fdce96L, + 0x61c8a0c5e784397bL,0x34d478351c686ed2L,0xc697c89cd155bbe9L } }, + /* 41 << 126 */ + { { 0xc26dbc34f06a2cffL,0x4f10297631a80712L,0x758e33eda7c54effL, + 0x44b5e4ff3682d103L,0xef05034722a05e6cL,0x9170365c48ff372fL }, + { 0xee49b61d66a15a71L,0xb5fd487995c2045dL,0x5940487160ad67caL, + 0xdcd2d5f586388c40L,0x0b41a8e54cbd1f71L,0x8152c17040236ae0L } }, + /* 42 << 126 */ + { { 0xf05b99d0995e9809L,0x036248a70295fceaL,0x7b70cf8f558e6ec4L, + 0xe882639c7c48ce34L,0x4cc86feaf4f47d38L,0x976799cf6d81aef1L }, + { 0xdb202bfe8043cb43L,0x4c761cc5cef4f017L,0xe124bbc161f0c89eL, + 0x77d1cbf55b5a3d20L,0x26e549fcff346940L,0xc6040a4c2325466bL } }, + /* 43 << 126 */ + { { 0x1ed4d238e940e32aL,0x29d99c20139efcd6L,0x4cb7ef50c172b412L, + 0x8a9c438931957225L,0x5d8872af60be4612L,0x7bffbb1be7e79e0eL }, + { 0x75bd89c1fc7d4e66L,0x723f9ae86bcc0379L,0x88f673b599c1b827L, + 0x8d45d139ecf5148fL,0xf12e605ff97ad1e0L,0x567dec052f09c370L } }, + /* 44 << 126 */ + { { 0xfb33b987b0be5055L,0x9864f903bcce94dbL,0x99b8da36aea9d09bL, + 0x19e326113b622d3dL,0x6abde501dc38f903L,0xb1fe3f1867cb2161L }, + { 0xb053ec831e08cd7cL,0xba503b563298d32fL,0x220e98c8c2a79e86L, + 0x66ac99511e1cba68L,0xf9520e1e644ab527L,0x3f222b9b4eb8abf3L } }, + /* 45 << 126 */ + { { 0xae0cf2ff705cfc45L,0xf9d5dfb65a0449b1L,0xd0300b2cd4697fe0L, + 0x4ac80d7e4dc665b0L,0x84fbd38d72c1677cL,0xea8306f08e683a0cL }, + { 0xe2381e65a469e337L,0x36b565d0b3ec173fL,0xc67689c700f3007aL, + 0x9f0108992abcc81fL,0x867a5f8dbb9bf584L,0xef789cdd5a436b38L } }, + /* 46 << 126 */ + { { 0xf8cdc9ecee11fa1bL,0xa78c73ed4c90edb9L,0xf6703453bbbddb82L, + 0xd268b4e23020e294L,0x214cdd54958eb8cdL,0x2acbd31d4d7214e5L }, + { 0xf7c60c89cc733351L,0xb8c5cc642fa201fdL,0xaae1ca7f4c2acb10L, + 0xf7e33be56d7f598fL,0x982c012fd920c3c8L,0xaa98a69b86751ef1L } }, + /* 47 << 126 */ + { { 0xf5f548eb915ed5cdL,0x657ca09ce30f448bL,0x8750c4a44a30850dL, + 0x1b329c4108edb075L,0x8c261df8ccbcdaeeL,0xa81720bbedd44638L }, + { 0x602fc21f0b91ee05L,0x6241265db7e8bc28L,0x1daefe5b106ac444L, + 0x93fe5bd42c9deae2L,0xedc229e17f1ba35cL,0xd99244977e0da1f9L } }, + /* 48 << 126 */ + { { 0x3176a43ab7a3ce87L,0x9fa09e975f130e73L,0x971cc37b9368e156L, + 0x2cabf535b8981792L,0xaec2862e4d0f0bc0L,0xa1a48c183ce8c100L }, + { 0x288f4e694af2eae9L,0x778845f21f9339bdL,0x1ef5fdfd17dfaa6aL, + 0xc784117e3483a6fcL,0xe8c82f05f3c5c19eL,0xf39b3c1d1da87ab6L } }, + /* 49 << 126 */ + { { 0xa2539d4cc4ac73e9L,0x0308f91891488ba1L,0xa3e72f4459fae934L, + 0xb6bbcc37f8c9c402L,0x345a2debc6edee3eL,0x0352f023b0df87b5L }, + { 0x67c9e7b8818c4f8dL,0x3a8714cc70f44977L,0x37b96e1295066bfaL, + 0x617d9737c95d7f70L,0x60bb06ef759a360aL,0x97689b3f34f59fe1L } }, + /* 50 << 126 */ + { { 0x17d0667fb2dd1febL,0xbfb92fe48862b2ccL,0xcfa0c8e9d5438a69L, + 0x7bdbd4b1d9cf9ef5L,0x7616acddf373c87eL,0x0603d2b0cf8fd5b6L }, + { 0x6a80f25d46e31aacL,0xea8c0ad0fd424755L,0x9e2e5a5b3ffd5a2fL, + 0x8882d271f3b143caL,0xe6fc9ad7904e1740L,0x98d1620af428ad20L } }, + /* 51 << 126 */ + { { 0xc8c991a63292054aL,0xc90b11618ce93455L,0xdfa32238e200d1c6L, + 0xa9c578d5303004b3L,0x9dd2c3881609e5f8L,0x068ec35d24b69108L }, + { 0x47e8183b2d1a3b7fL,0x6200d70efe3db580L,0x76012f3fafc089b0L, + 0xba06dbf4bddea8a2L,0xd83b4af5da01a49bL,0xa3d4334ce16e87e6L } }, + /* 52 << 126 */ + { { 0xb2fff4035b43e58fL,0xe80bd5740727be41L,0x048a59cbf9b52541L, + 0xb79084e7f38d0b47L,0x763b0c95938935d7L,0x7cfc6180336b8735L }, + { 0x118d2a6f929b0200L,0x7e5789775a31948cL,0x9085999326009509L, + 0x330533a33ad633c6L,0x28bdb910733f4c3eL,0x82c88f148fdca27cL } }, + /* 53 << 126 */ + { { 0x1c346bb04ef444e7L,0x40a50060e6c22e57L,0x5eb02aa6c7a773b4L, + 0xd748a0a0d23b190eL,0xb6ff7f02cfedb7dfL,0x3f8fb35b30f8bb4aL }, + { 0x245b1c232dc31174L,0xa1e156579af25f59L,0x1ad1a2315e2393daL, + 0x9430ed2dfd7c7073L,0xc4161d4f580fbc0fL,0xa2bebd3fa0f1dadcL } }, + /* 54 << 126 */ + { { 0xace743b6baff35ebL,0x84ac3ce8ac6f38f8L,0x81d41297106b44f5L, + 0x33f6bbbbaed20aa3L,0xae4dd66ceb420ee5L,0x87553aac994f0777L }, + { 0x26275ebff1e3647dL,0x3b574c4fd9eeb474L,0x58fe2a16929721c5L, + 0x748480df932030d0L,0x3a30032641bb5f68L,0x0797fad92c06d1adL } }, + /* 55 << 126 */ + { { 0x65356242c7caa811L,0x780fe23f4506bbd7L,0xa741a51042407c02L, + 0xb8ccd27f5ef9eac3L,0x137f4a573ecf5766L,0xd495be0d15936fdbL }, + { 0x5a419656109c93f3L,0xd2f7b65dcb12affdL,0x2305a070ff830421L, + 0x6d00f1e9684d5a6fL,0x3de9d1de91aa391fL,0x0b5148c10acb6de9L } }, + /* 56 << 126 */ + { { 0x209fa6e68ca7ec95L,0x17808b0c107a1047L,0x99bbeb5edfd270cbL, + 0xe3d57c1dc25e2d6eL,0xb90b0c107ba1237aL,0xa7e1b8dc4a0d6856L }, + { 0x97d5b46136a9a07eL,0x931251e9125ea29cL,0x4177fd10fc8868a8L, + 0x1d3538b7b7cdcdf4L,0x889008c8ed3ff9dfL,0x30573ad2229b9413L } }, + /* 57 << 126 */ + { { 0x11596662924d413fL,0xe797d0a70e5d7bf1L,0xaa05dcd28452ee62L, + 0x6e10e77f5d5ddf1cL,0x46b72cda5fbd184aL,0x3adc1edb5b25c0c6L }, + { 0x640de5b05c732e3aL,0xa7d4f0f5c6739747L,0xbc11978d1426527cL, + 0x979276eccbee0053L,0xc44347a7304e8811L,0x016c01e11f5ececdL } }, + /* 58 << 126 */ + { { 0x78b2f1a15ee57666L,0x28060d1576a2c09eL,0xaf0cb38df632a5deL, + 0x93ce93eea284cd43L,0xe3670d0af35dc1f5L,0x3b8deea527971072L }, + { 0x3b88b1158eea4303L,0x43ff3b22aabde038L,0x8d69e180c813d623L, + 0x218f5b853aa7a08eL,0x6ee1544adf74f239L,0x0d7abf20fb8772f7L } }, + /* 59 << 126 */ + { { 0x1d881d4eb7716840L,0xdf83a03b86bdef07L,0xd534c4e4dc7ee69bL, + 0x1169f1cc6e264c79L,0x85c812d1b7690d17L,0xcc3164adec5f2ed1L }, + { 0xb91a14180674e87eL,0x5dfaa279969188fbL,0x434acad5e242b969L, + 0xa51b5c63751c4e51L,0xaa9089b7874f9aa2L,0x8758f9e51b8397e5L } }, + /* 60 << 126 */ + { { 0x422ad88e57fd35feL,0xd4564b96b99a11cbL,0x78939992238baebbL, + 0xe66ddcaf4b30a709L,0x00873d5f7812ea50L,0x7317f9dc6784aabcL }, + { 0xf94afbdbe0608ba4L,0xfff893618896d745L,0xa3348af5cad62808L, + 0x13ed4507f349f51bL,0xa73d4bec1186324eL,0xf0b48189a20022d2L } }, + /* 61 << 126 */ + { { 0x87d117858b8efa4cL,0x724439d6e9c2ee6aL,0x33ab2a03606fa0c8L, + 0x6ede5b55f9779d87L,0x858b7dd0759445cdL,0x33683c817a5ef23aL }, + { 0x0f093175221c3443L,0xedcf2aaf889195a5L,0x9f189ebc814abec7L, + 0x6a64999c40235b9eL,0xf98dc212984438ebL,0x97e2d102ba86e7caL } }, + /* 62 << 126 */ + { { 0x337b9cbce3db0718L,0x1f2f55833d1796feL,0xa522b76f68c2a69dL, + 0x4c1da7cf5375cb22L,0x690a2e7f50bb0d7fL,0xa734d4756689b6eaL }, + { 0x918592d5867ca0a3L,0x64d1c147c4d15e28L,0x4d8c3e22656f8219L, + 0x5e028bb2170f59c3L,0x41e8b84449875858L,0x1d928cc90c599178L } }, + /* 63 << 126 */ + { { 0x736dee2cf44db09cL,0xfb5035c07257b4e5L,0x3e3a7bf6bf0b702aL, + 0x4910a0165f257c0fL,0xd80b891d98437b4eL,0xf9e55d55076d8587L }, + { 0x4e4ed7a79b4fcf4cL,0xaaf417f5581acfe3L,0xb1ae2a7ca3b3f920L, + 0xa666bb6263ee4781L,0x2fba297e63684f04L,0xd6e662658d83bd6bL } }, + /* 64 << 126 */ + { { 0xa58a27c58a541be6L,0xaf66949954fd7683L,0x2431826600079a25L, + 0x113f6fcf2606caf5L,0xf6ff2be316cb28c8L,0x8f7fc60e3c17caa6L }, + { 0x8ea577e07d35e26cL,0xc3e744c0f0628903L,0x4b28eff4592a57eeL, + 0x76e1f87c5e3f67b2L,0x40d7a676fb008902L,0x68a9dc764b6e6b7eL } }, + /* 0 << 133 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 133 */ + { { 0x76e2751a12575913L,0x2c6059914a5f8c4aL,0x58322dfb71fba662L, + 0x228aec085e0886afL,0x8d83b6276aee544cL,0x338f5fb6e29f9639L }, + { 0x1ba4cfe0bf5e19faL,0x2eea84c5b9e4f8f6L,0x7e0eed58cee95d92L, + 0x2d29282abe535540L,0x866638b607a9a1f4L,0x915999776ab8dc82L } }, + /* 2 << 133 */ + { { 0xa16c79cfaf4d260bL,0xfe853f6cfab3c3c8L,0xb8bd6aa0c2f47e68L, + 0x277d590f2c9b4914L,0xb6d1c810097242a8L,0xcf2f3d8e45f75512L }, + { 0x2176162b74a20c3bL,0xeee8bcb82b2bcddaL,0xfcf8c0d1a503aee7L, + 0x5d1f94a57af4dd78L,0x8f0bc1a62ab43be4L,0xd22dbf16ba9e071bL } }, + /* 3 << 133 */ + { { 0xbf87f30e3790b47cL,0xd3d3f1e25ab52ae8L,0xd5fd32bd50ec0ba3L, + 0x7de8fe0ae60d1e72L,0x52d77fe0e14ff2d3L,0x9b6937db55ca47e4L }, + { 0x39e3d19f53e94fa3L,0x8d962a4fbd7827e4L,0x3bd70c7afe92c6cfL, + 0xa3fbc06869a82904L,0xe263f00ed96d1d9eL,0xe6c9781f75c0c24bL } }, + /* 4 << 133 */ + { { 0x705bfe37b4e814b3L,0x22f0de61702013c6L,0x811e77a9bc456797L, + 0x4f52c4e617081a2fL,0x87405d819fe1640eL,0x53fa82b7707711d7L }, + { 0xdc6fff830ee4aea6L,0x8413e22ffd60373dL,0x0ecb66bea9cf3eadL, + 0x7418372e87139b8bL,0x6aaccf295e42b4d7L,0xb6dc592531fc932eL } }, + /* 5 << 133 */ + { { 0xf1c8d00de460fe00L,0x5692bfee528da7c6L,0x9e4dd700ac8620dfL, + 0xcc43e73d9d6fe740L,0xc94060d3e76dcba2L,0xfcdf8ba6d398914fL }, + { 0x540942e7502f8587L,0x5def85040de058fbL,0x63e0c7855292b0c8L, + 0xe90405282e558983L,0xe25727a16baf4a31L,0xb9bf28f0acf64d7cL } }, + /* 6 << 133 */ + { { 0xc7c8364f09d26382L,0xe16988737bf32d9fL,0x97bac2feb726391cL, + 0x521426364a7c0b57L,0xe3e596482cdec222L,0x4ee7238cf44e0a98L }, + { 0xa6d05a21f61cfea8L,0xa1059fb7efe6a26fL,0x482a65b342416fa4L, + 0xdc5727e1c71e7a94L,0xe6b0fb6ec4767f1eL,0x3d0d626d6510599eL } }, + /* 7 << 133 */ + { { 0x59f5df1b2a8f9f78L,0x6bb161d992257e60L,0x2cf060beb7b2eb14L, + 0x98e72799aec169b0L,0xdde683927045fdb9L,0xee5e0aaf461b27e8L }, + { 0x80250c744c0ee047L,0xdd3881f597f0677bL,0x0ea56921a4459b6cL, + 0xf7793cee26df8d7dL,0x33bfa09be42d1913L,0x9f0636f74ccf5139L } }, + /* 8 << 133 */ + { { 0xfa3b4c8eb88ee8f9L,0x1f288e60b521ab57L,0x06aa39562e8c4d8cL, + 0x4981c3e5cf89935bL,0xbdbd0c4745fa071eL,0xa78f831c496073beL }, + { 0x09a72986a4e5c001L,0xac527731709cb728L,0x9a64b5b3988f2781L, + 0x6ac9440d73b1719dL,0x58ad54c7e3d2e807L,0x1c1574488f06742bL } }, + /* 9 << 133 */ + { { 0x3220a099a5e437e6L,0x11a1b1734dc5bdaeL,0x1ad9e736b64c9b8bL, + 0x82b6a3d4ce40acadL,0x54e1eef8915aaa8aL,0xff19be481f3a1f54L }, + { 0xadc4c5250b64a2b6L,0x6637bc8e12caf63dL,0x970d08b01206a661L, + 0x97c9b9bde57cf6c2L,0x228ee4712b89b7b7L,0xfeed19ca837cb79fL } }, + /* 10 << 133 */ + { { 0xcd36c981a816f4d4L,0xc99316c27712a72bL,0xd32cb20339e671aeL, + 0x79ff1889f67f6215L,0xf9fe7448cd08e91eL,0xdc9b277776f3e605L }, + { 0x8af30c2e7c1609a6L,0xed3224a3e54cdd0bL,0xe73f56ded1dea6acL, + 0xb836eb783e37a390L,0x9f0dcdb2c78a0510L,0xc37e67a39e6109f0L } }, + /* 11 << 133 */ + { { 0xab419eb852e0d552L,0x86c76ef8ae3d06ebL,0x219662b4f7c6342fL, + 0x2820299e548f6717L,0xc4d0d47a8a2aeebaL,0x4c98069895536593L }, + { 0x3644e55ff42cd505L,0xe109b64ae47e0b0bL,0x91f520a6c89788aeL, + 0x35f6dc577699087aL,0x3484f5b6b77deb8dL,0xc22a63a47f3c09e6L } }, + /* 12 << 133 */ + { { 0x6b5b7b2a75c953b2L,0x927ed77ca7f1cd5bL,0x2e8c53994cba0e5eL, + 0x03aeb14a3f4a941bL,0xedbad9a0a1385c8aL,0x925a49c167fd2258L }, + { 0xe7e368ee3365ffedL,0xcc4aad2dd106eb87L,0x4ce908daa980b53bL, + 0xd3f4954016929ac8L,0x613c804dd5c05c32L,0xa42290ccd7973344L } }, + /* 13 << 133 */ + { { 0xe7437974c464c24fL,0x70c04156d36bdfecL,0xd94c80fcb2d5d96fL, + 0x4a1fcf19d2cfea9cL,0x443478592f6df796L,0x0c908d0159743bd2L }, + { 0x78949087d165a62bL,0x6c3f9021632f4e1cL,0x3917b925a94bb004L, + 0xe153ef092b3f87e3L,0x6aee1027ea706338L,0x953ab2959733bd02L } }, + /* 14 << 133 */ + { { 0xad49cad49855d008L,0x23442cf94b273d85L,0x3a3c8752e3dd8f65L, + 0x0ca5d24bedf84ed0L,0x3d0580938b4f8f96L,0x1cea59acf9b9ae03L }, + { 0xf17cbbe23a06567eL,0x49cf5294f090338fL,0xcf8cbe0da93562c1L, + 0x66683f21b986b71cL,0x3c96750cc87c9e10L,0x38e62db63dcf2f32L } }, + /* 15 << 133 */ + { { 0x807a519047f99946L,0x49e03dcf01615a37L,0xe813287c99590bf6L, + 0xc9caf30ddb62835cL,0x0733c49d4df78781L,0x4fde30fd4815d3adL }, + { 0x2809b853f9a2610dL,0xf2b139b9dc050142L,0x52a40a413c23a4edL, + 0x9333086b0a104df2L,0x04a90c11e2a65950L,0x4c6a15c4dc24341aL } }, + /* 16 << 133 */ + { { 0x33952177a98cf218L,0x841d9e1f579ee53aL,0x1084d61e0a285bd5L, + 0x3935a84e71171b1cL,0x8ac2433cf29b29f9L,0x5dd868b56dd1e9bdL }, + { 0x88da04788d102390L,0x1140735a657400d1L,0xa792a25f9d5b19e1L, + 0x9ee015cb6a27fa79L,0xea3bf8b57ba16a8eL,0xc5f0cc26c15fde67L } }, + /* 17 << 133 */ + { { 0x033708d2e02e9feaL,0x2b588d1e222f437dL,0x998442d6c6b47013L, + 0x4033d62fb8ac1fc6L,0x9b8fd348877c726cL,0x1a2125fa5bea5a49L }, + { 0x04a2c1d680b8afd9L,0x3d52c9d2a40195c1L,0x56b204e6655c0b30L, + 0x55ee14ef520b3464L,0x23fc52e6b5bdd96bL,0x445cfd7a56f4b269L } }, + /* 18 << 133 */ + { { 0xc8985c2c5fee6426L,0x8be749496bb7bb8dL,0x12967576659363b4L, + 0xd1b6ded9b969b221L,0x586f28929819fc04L,0xec6b03e5addd6307L }, + { 0x3f0e96cad4da6627L,0xc866c95c14860d00L,0xb038867c9725f9a8L, + 0x60cd3afa1caf2547L,0x6f2cc04411dddfafL,0x49551f249d0af0faL } }, + /* 19 << 133 */ + { { 0x04a68337177e2e7cL,0xe20b21c0adb79464L,0x9b30d3437e42ae4dL, + 0xac7a01d7f86c5767L,0x3ea34e385381db5cL,0x3005a0c39235f5bcL }, + { 0x853eb43167b4a5c5L,0x92f26a35584e4b8aL,0xa3d25e5879bb470fL, + 0x7963d90a5eacbb13L,0x08ca7969212e3aefL,0xb5ec6582df92bfffL } }, + /* 20 << 133 */ + { { 0x2e152d95ee2c3290L,0x8437df2e4a9ceda4L,0x4151754e3c7ebfd1L, + 0x556c59a888f80aeaL,0x8d099c5d8de44dbcL,0x9ecce7fc77abeeccL }, + { 0x5e0a0f383aa311cfL,0x99ff1eecb8f2bff5L,0x5ae0b483b5dcf488L, + 0x11212c4591483a02L,0x99fe0738312134a1L,0x3b855db0a72745efL } }, + /* 21 << 133 */ + { { 0xb70bf73230261470L,0x8c9b7c4bc74a180fL,0x4c648aef88a9d9acL, + 0x3d9f7540a10f98bfL,0x8ec2a3a3120d55f5L,0x1707c1b0baa5a600L }, + { 0xacba8da9103f2f0bL,0x96926dc0c7194236L,0x00358df7584499dcL, + 0x74c27d0e538c0a15L,0xc675d079de960a77L,0x575b042e89f41f6bL } }, + /* 22 << 133 */ + { { 0xd17d99529703d919L,0xb25ecc411477faebL,0xa5c66a58a9aea2fcL, + 0x83754d683accb00cL,0x6a9ae76a25901044L,0xe437981b2565e035L }, + { 0x441ec0d96f45fa01L,0x35e40d126a697636L,0xba2fbab59bb3c2fcL, + 0xc038be03e94b245fL,0x366b4bcc0c1672eeL,0xa14a2c10f1ce6d55L } }, + /* 23 << 133 */ + { { 0xef32d94febe1dfe2L,0xdbf53d4271494ea6L,0x72dc5fad24cf0c2dL, + 0xa9247adc66dbc21bL,0xe31ff66ab130da59L,0x8cb97c09e86ab63aL }, + { 0x204020e2f59ebb80L,0x56f6d8b7cfd0f965L,0x7522a692b1518dadL, + 0x8e7c999f5f231e2eL,0x2eff5904b4406177L,0x8440cee87bfe2363L } }, + /* 24 << 133 */ + { { 0x37f50e43892c8eecL,0xf06a2f047d85a7e2L,0x3916af85e1d11150L, + 0xf56e852f6785ae1cL,0xbf8c72adae6ada8cL,0x1fcd53e3e13285b2L }, + { 0x5327920cbd56d348L,0x82a394fb445658a8L,0xa71328573caf3792L, + 0xb15ab34b550ffe1cL,0x818980666a5d4e4fL,0x0bda153b2f854f9dL } }, + /* 25 << 133 */ + { { 0xf664f44407aa3d00L,0xcf8901664704e2d6L,0x1802f662f8c2fc8dL, + 0xd52496b8a47f0da6L,0x37f71d8c75001c8eL,0x7ad8e8c29cad3ba7L }, + { 0x666afc25825515f7L,0x3a871c76a729e498L,0x5dc21f1108479e3eL, + 0x78ff145966c4331eL,0x8d01e2352dd3deb2L,0xc68445e9dbc91fc3L } }, + /* 26 << 133 */ + { { 0x8f2d9aae98ea13f6L,0x3e75ba40ab97bfb0L,0x14dd24e635e1fe35L, + 0x14abb0735f88d9b9L,0x74b2c6a801d4fcd6L,0x4905dfe7744a09bbL }, + { 0x349348c077cd538aL,0xdec247f5f7b6d035L,0x737e248dc455d417L, + 0x608a5529b6fe5d92L,0xce0ba0bccd7dca64L,0x022bcb18c21175c6L } }, + /* 27 << 133 */ + { { 0x79fe5372881b120aL,0x4878428aae98aeeaL,0x5c6a7f7d09511acbL, + 0xb7be08de3b046481L,0xfb91990b8b35f13bL,0xab734f604ebdd374L }, + { 0x3d4955f1197690e1L,0xfc82767c7b376dc4L,0x7cf3db85b8c659c7L, + 0x4cfb6f4b03202723L,0x8b79311746141d27L,0x94c6ee67867292c4L } }, + /* 28 << 133 */ + { { 0x77a31009722730feL,0x93707ac4d5cdd297L,0xa290be39d3811e8cL, + 0x831a9b9592a5cdb7L,0xc74cda84e7342270L,0x964661903f48affcL }, + { 0xb0496cca5520b0f0L,0xc8742cd9bae930ffL,0x3a30737aeaea703aL, + 0x0a8e6fb7fb758854L,0x9ab9523e6796f4d1L,0x36e6c05dfdf7140fL } }, + /* 29 << 133 */ + { { 0x4c8ec1a3ccedff1fL,0x8fc58987ca74bd5fL,0x70a6b71cf768abcdL, + 0xb9971cf5ed60a02dL,0xbb2aedc8af2f9a41L,0x4ebf90c76032c98aL }, + { 0x8e69b4c4d3752262L,0x350f201474ba8e8aL,0x7a164f6724d0052dL, + 0x5aeb80db61d7eee0L,0x626a6c9da63583bdL,0x6246637fc3f2196dL } }, + /* 30 << 133 */ + { { 0x2077dfa1817d444bL,0xdda9c7fcdf855b15L,0x577603be04b31d38L, + 0xc6beacae7a140cabL,0x8cd9dc019ecbed91L,0x6ea8591295ae114eL }, + { 0x6fb29a33fd47f1b5L,0x6203bca6223cb96aL,0x2459d85a7c1a3580L, + 0xbab5922d6410a3c0L,0x543be274cc7750f8L,0x1a653e1c42baea3aL } }, + /* 31 << 133 */ + { { 0x616abd271dbeeea7L,0x0684c14fe2189d8aL,0x0d2bf3687354d862L, + 0x8b0cfc06a8bdcb0bL,0x187147b49661e548L,0x07509bc358edde6dL }, + { 0x7b2a33bca78c2782L,0x5f41b8379ec5fa24L,0xa6df5de574539201L, + 0x3510f650093f8f7eL,0xe4d1c06ed14aaa71L,0x4d1b1ca2b0470581L } }, + /* 32 << 133 */ + { { 0x3b62315064ef6a95L,0x97645381aaa5b792L,0x4bc2c31c56471100L, + 0x4a0e73bb1bae8d2aL,0xbfc0770a8df1f76aL,0x5089916fa7bb16caL }, + { 0x2afe5b1cf31fe82eL,0x0b06831df0119977L,0x97caa333a1af2a82L, + 0x93cb92c5dafed6cdL,0x09553e7e92c3b2e3L,0x3d9c4b7d61af2956L } }, + /* 33 << 133 */ + { { 0xe56c89b06910185fL,0x1cd06d19ac47667cL,0xb35e6ae5fe41a4ffL, + 0xdc2fbaf959e8be08L,0xa9e6df08f8cec40bL,0xcab91f8ffe63ad2cL }, + { 0x1e3bd193ca2cc678L,0xe1830cae06bb40f2L,0x3b8b33d6d69985abL, + 0xb6b7e8433895d8a8L,0xec3882909fbf6b31L,0x012bec2ac37d64cfL } }, + /* 34 << 133 */ + { { 0xff2e88fd33941b4bL,0xa2d9730a8d85cccaL,0xa23f8cfa16f7d7a1L, + 0x82013193d39a250eL,0x3b119882ca0fd8a8L,0xcff642ac1a438706L }, + { 0xe4a3a95f65e5688cL,0xb2a6c836c31243d2L,0x1b7ec5d2194d1f42L, + 0x51ab34f814e4f7a2L,0xa3e3f135d3583ca0L,0xbca6ecbade9b91f2L } }, + /* 35 << 133 */ + { { 0xc85820c3002f07caL,0x090365320e00dca7L,0x0f3b3166f4e4d8c2L, + 0xe694eb4479460f00L,0x50d0ed14c15e04ecL,0x8c9998abcc86e3bcL }, + { 0xb82581624aefa561L,0x6351aca610050c0eL,0x4e60399acc8d2342L, + 0x96da3af7f633dc88L,0x1af763ec09202348L,0x76b0e49d3f0d5f76L } }, + /* 36 << 133 */ + { { 0xd83f574a08f84746L,0x48fc9715ca07f5f8L,0xb3d5d0d2dcc51638L, + 0xc2a5e3356153bdcdL,0x8242cd9a8aa4ef74L,0xe71ba25b0bdaa0d0L }, + { 0x4342d4bba4ff172dL,0x81db10dffc1341a2L,0xdd93dd877dacb140L, + 0x6f8a4e81d12d347fL,0x0d4e7e461bc369beL,0x3ce10a771fafd0c5L } }, + /* 37 << 133 */ + { { 0x2fdaa3bb8cb896a3L,0x2fb82dfd913bb303L,0x5d814a50ba9ca09aL, + 0xc3de6aa426112215L,0xd0d5c98b25a0c9fdL,0x54004b3e0eaae4a8L }, + { 0x410e2cc209358663L,0xf7e3d08a501c4ef5L,0x3d86434dd334aa19L, + 0xf70ea577772fc0cdL,0xa0eded5aa607c4f2L,0xba0bf1bc36222b2dL } }, + /* 38 << 133 */ + { { 0x8d901e759632c4d6L,0x0ed9a7ebbbd94698L,0xfd2169dbbf7bcbc1L, + 0x2b4d168d5b302c66L,0xd42f9dd73e65f24dL,0x73e0c22c0eed0022L }, + { 0xf9091588f5d2dcfbL,0x81c7c01eb8715b78L,0x2be06165dde6a9d6L, + 0x64b5902dcacd6ca2L,0xdcd510d70159d3bcL,0x5b71995b42b5e30aL } }, + /* 39 << 133 */ + { { 0xa9c474eae7a211edL,0xc7bcdd20d8170f76L,0xd9aa8d9734a15487L, + 0x26235292933c16b6L,0x289d47d5d8238fc0L,0x39f10fb3ae27ca16L }, + { 0x822e187f1c016ae1L,0x8e93b15f2be46859L,0xe2ba61a60b0a055bL, + 0xd8f33ddecb8de893L,0x016652d6379657efL,0xf4eb08f9e7d9eab8L } }, + /* 40 << 133 */ + { { 0x5559dd31e67145b6L,0xf2d905b45b2427e7L,0x0d840fabcaf57d0cL, + 0x9625866578742ab6L,0xc85482ad409c1c8eL,0xdca2a058adaa6167L }, + { 0xec26ad9a0c8885fdL,0x1b93b8a22a600cb2L,0x340aa7fc2539986bL, + 0xd7674876a23dee41L,0xa948a9292e1a9837L,0x9ae67d2a71438da9L } }, + /* 41 << 133 */ + { { 0xe753114a8d6a98f5L,0xb2d7d1e1f6ad93e4L,0xfbcfe0cf1935714dL, + 0x9dc2d293e859e729L,0x674c170889a703f2L,0x87744b0252063099L }, + { 0xa1721de04b25966bL,0x059292573a285fcaL,0x5b02ca39e8ce75e0L, + 0xbfdf0fb939e57da4L,0x554378cd6388a964L,0xc53fc5c8f853d7faL } }, + /* 42 << 133 */ + { { 0xcd3b60e352f51554L,0x6292fafab44ad7eeL,0x670561c79513741fL, + 0x95defdf3b9ba16a7L,0x6c0beac1adae36cdL,0xef05c24a3e8aabd6L }, + { 0x74208a02b23efc25L,0x71930e02c22172d1L,0xbdb1f1c6f5ccbffbL, + 0x358b483c504d9cb3L,0x48b5887a9a48a4baL,0x289256b4e48f09e7L } }, + /* 43 << 133 */ + { { 0x671bf1eebc2f256aL,0x530faa653984ca7eL,0x0a6d18955c05da6eL, + 0x219de918118fe96cL,0x289b9645bb7eded4L,0xe905c4729588f006L }, + { 0x56d0cd9ac9d61133L,0x8879550079a4f743L,0xd05e910199c2aff3L, + 0x7e91f7c985e52c8bL,0x7fd02f83b5c5d473L,0x4b43b6453c59330aL } }, + /* 44 << 133 */ + { { 0xeac6f447d56bdf1fL,0xb22e8425c2b502ffL,0xe1cc9d3dfca5a501L, + 0x8192bc29b64baf39L,0xeb2c901a52ce849eL,0x7f5f38b11dd506f1L }, + { 0xfb3684b10f0a1d68L,0x16c4aacde9240ff8L,0xffa682435a4d8995L, + 0x27264ab554e4c95dL,0x9aa40cdc4f34ffaaL,0xcb8a30a35fd818eeL } }, + /* 45 << 133 */ + { { 0x912f0a7dfa88792fL,0x2ad9249f5090716eL,0x4b828a6fb96e6e31L, + 0xe805f0588d7f2095L,0x72e95cb956e00978L,0xc95354667651815fL }, + { 0xc877181a08df5b53L,0xae055dd8779c3302L,0x3f9e6dd90b4e68d2L, + 0xdeb15f1308fbb2f8L,0x5f129c1cc5802a96L,0x7482e4af3cc51022L } }, + /* 46 << 133 */ + { { 0x98904777ab695f56L,0x6dc472c18989e518L,0x6749d25c82031d40L, + 0x5c465922c36202f1L,0xb3b5b9aff31fe542L,0x855263bdf98bc09dL }, + { 0x40ee01747eb4789fL,0xd64ae0d4de4e92bcL,0xbaea76a38995e69fL, + 0x3f22b2e3d972751eL,0x5a197daa2461f1b4L,0xbd15682a5097b93eL } }, + /* 47 << 133 */ + { { 0x7f251143534f8547L,0x213baf14222a161aL,0xae993737ad1e6005L, + 0xdc70867ff8b1cc7eL,0x41e880f3bb22e11bL,0xe36f54cbd2d6bc45L }, + { 0xa42e819d4d65ae97L,0xdc57be4de8592604L,0x8a89777fabe73b50L, + 0x435fedec72e26f5bL,0xe8d3cd8251ec79f0L,0x9574d6ea67f407b0L } }, + /* 48 << 133 */ + { { 0x39038863f7f35053L,0x421a17f3328787d2L,0x38aa682ef3d8310fL, + 0xb52d41e8f4123153L,0x4fbef3dd7026310bL,0x0c6bd7adf6ff5692L }, + { 0x3831c6b2a9be5d0cL,0xb5c9ae85e8d328b8L,0x76d26abc6516bba4L, + 0xc237f9a5446d35a8L,0xb2b16c0ff012a8d0L,0xddf2b7fe0ee0315bL } }, + /* 49 << 133 */ + { { 0xf401366a7dd4243fL,0x7db92881f434ba76L,0x5b5bacd737ffc502L, + 0xa53fe0e802cb994eL,0xf6db539ffb00cb96L,0x0bb288b379878966L }, + { 0x275c108c0c3d4b7fL,0xe57222d267236ba2L,0xc754d31890683aa1L, + 0x883a41ef2345460fL,0x8e6b7ce8b572fd14L,0x7649c29237d21925L } }, + /* 50 << 133 */ + { { 0x46302515c4af281fL,0xe2a9633c3513ea87L,0x1175276fb3e96864L, + 0xda377e32f4ed1228L,0xacf223a1fa6be904L,0xf442c41abc01057bL }, + { 0x83d766c38a69db33L,0x933dd0974cef397cL,0x094b21b575fe43cdL, + 0xf16ee57ab3141dd5L,0x4a8d0d6cb981d196L,0x6bd246c3730075deL } }, + /* 51 << 133 */ + { { 0xd9ae9faa91eab3f7L,0x8520bebba2bcdfc1L,0xc681d5a0ee94353aL, + 0x980871dd316ee7acL,0x7d70b82bcb401c4eL,0x150706c1bc6885efL }, + { 0x11709bbed3d8663aL,0xad69df943ace1806L,0xf889daef1a36f12cL, + 0x6ba376b2560bb749L,0x5342cd7a0d95f8b9L,0x5d14201273b4554aL } }, + /* 52 << 133 */ + { { 0xbb85b640056ad6c2L,0x7c51ef96ac074372L,0x1c7ce31cf10b43fcL, + 0x08e4101b26f4d3a4L,0xd18511c43968459fL,0x00e20c3fd6d07839L }, + { 0xd5bcd598e4fcdc11L,0x99e9a4d0c877f6a2L,0x9c5dd9d0bd491646L, + 0x83918f609bfd7a1aL,0x4bc130cd7e2b95a3L,0x668825fbfbc31c83L } }, + /* 53 << 133 */ + { { 0x7e8947bd5568b75cL,0x43419ecbdab8f822L,0xeb52a83a7b8fa996L, + 0xbc674ff32d1a32c6L,0xdc086f84ce405eeaL,0xebe3e087f8918ddfL }, + { 0x476099ecdb152bc4L,0x0cb491c52d3718c3L,0xa7c49cd69da8517fL, + 0xc736fcf51ab8fbadL,0xa00b403ba24fe115L,0x01f6e5bfd976f549L } }, + /* 54 << 133 */ + { { 0xef8e12edf15ad86eL,0x216be9828c20441dL,0x10ccd4f85c45e821L, + 0x8a12f6037c9745e9L,0x56212b09da6f1b2fL,0x5a81d69338115f05L }, + { 0x5aead3330a4405a8L,0x7024a76c03221eddL,0x9c101d0250e6a610L, + 0x6bcb22ffc1b6d54aL,0xf96cef62cf787e89L,0x9c9bde7b79341d83L } }, + /* 55 << 133 */ + { { 0xe9c61fa744058dc9L,0x59efcc8f1581d690L,0x1ea73467513aba4bL, + 0xf0fda8a69d03d72aL,0xcc1f3f22c6f30a01L,0xb632daa3ddf8dea8L }, + { 0x58563188fe8e2f89L,0xf053b9f67b45cf5eL,0x1ab51b07f9bda4b1L, + 0x37850e9789dc0050L,0x1bf5e41e8f6a1daaL,0x4abb4f82d94c0fd8L } }, + /* 56 << 133 */ + { { 0x817d77b106a9ad54L,0x3a999d7d89a25ecaL,0xd3ac4107da68b768L, + 0x6904bcddbebc4c4dL,0xb0d2103ca53d39e9L,0xdba86bd230a5e950L }, + { 0xb09256804f52208eL,0x37c3156a28495b2cL,0x2389ab34c15855aeL, + 0xc14dfd963017194fL,0x420e07191146b838L,0x1a9f909b8fb4b6fcL } }, + /* 57 << 133 */ + { { 0x73af3d1fa24985f4L,0x4fa27db444a1f9a8L,0x6deb02455cfbfa45L, + 0x4803e0342813c996L,0x24715fe80e4116ddL,0xa2e8258d38d8e902L }, + { 0x3321e112dd7d8ebfL,0xab8d5b2b272ee6a4L,0x2994fac34eb10fd9L, + 0xe007d0a4a9c611ccL,0x29db5aa974d194e3L,0x9e76e3ddcf7409b9L } }, + /* 58 << 133 */ + { { 0xf12a3eeab577f6b9L,0xe666e002b6db2206L,0x95aa0d03375229b4L, + 0xebd05140ef0772beL,0x9d5b5e9e48580b17L,0x960906b3a77ceceeL }, + { 0xca869663e50422f8L,0x150e844199d481b2L,0xadd97d7c3418b00dL, + 0x9908a23e68244f02L,0x5357ea61d3eac131L,0x0af5423d9778902dL } }, + /* 59 << 133 */ + { { 0x11aa3582d8e62251L,0x108ec170aa1560a5L,0x8423663e2b5b6ea9L, + 0x3f4ad292d8718329L,0xf8e3e7bd04f8daadL,0xed310c3a11b81211L }, + { 0x718db302edac9282L,0x7866f1c1e434544bL,0x1052133c568b195aL, + 0x8ca61965c0e37cbbL,0xdd28fbd32cfac1c2L,0xf4062b33dce29660L } }, + /* 60 << 133 */ + { { 0x2926ef17dd63404dL,0x0e89c4d41399cc68L,0x6507fedef7ec20b8L, + 0x1ac084ff88c751d6L,0x31bc08bedefe29e6L,0xd42199714f0692c5L }, + { 0x4d6ee74236069bc0L,0x3868ef6aff80f3d7L,0x6df02d7c5a9c6f4bL, + 0x2c3096bb101abf69L,0x0c2b01ec8eaacaebL,0x65914c20eb2e687aL } }, + /* 61 << 133 */ + { { 0x78d5ab7b34a8173eL,0xa34b72ac9230c3b2L,0x379453e13538b39dL, + 0x1764c4420f3789b0L,0x5b4bbe77a3f2ba4eL,0x3bd35b796f86338dL }, + { 0xf2fcdf04f02fa7e3L,0x6b4522f420d23feaL,0x966fb8fa01be16a5L, + 0xf2a56e96e0d705feL,0x494aa4553872e429L,0x68432d9181921587L } }, + /* 62 << 133 */ + { { 0x0ae47d1e3dba277aL,0x54607ac99832d90cL,0xd4cec32eecbcdeacL, + 0xe54b3033b9ccdfa9L,0x5b3a8a56fb920449L,0x831ec8f955eefd3aL }, + { 0x59ba32a3a02dca96L,0xb421e4b01decf837L,0x52e70a88a88636d2L, + 0x3b75ed073086667eL,0x7a4a46b3b877cd6bL,0x3825c80b59c99207L } }, + /* 63 << 133 */ + { { 0x3bc3f0e069bdc53fL,0x7e0bd730d9d7def4L,0x71a577e6844ede6bL, + 0x06d47f4981705712L,0x83bdb1a6ef108ea6L,0x853a3ce0c8a8ff41L }, + { 0xa6f114b8f408ec44L,0xe0ce4267e2d72d33L,0x405f6ddda2a0b613L, + 0x22ce3daa8d253ad3L,0x2fd738094aa1de25L,0x28a2001b27363597L } }, + /* 64 << 133 */ + { { 0x13722ab079ed523aL,0x33b29bec249d5624L,0xd3d0f467f76fdaf7L, + 0x7ce072f912ddfd9aL,0xce918a5747bdefd3L,0x14d38ab4750e5315L }, + { 0x08bbb20e3346f647L,0x428b917f05b26894L,0xc8fb5c21ca865ba6L, + 0xee6e41e02e6e8e6fL,0xd00ae6214c608b60L,0x659756396ff685cdL } }, + /* 0 << 140 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 140 */ + { { 0xbbccce39a368eff6L,0xd8caabdf8ceb5c43L,0x9eae35a5d2252fdaL, + 0xa8f4f20954e7dd49L,0xa56d72a6295100fdL,0x20fc1fe856767727L }, + { 0xbf60b2480bbaa5abL,0xa4f3ce5a313911f2L,0xc2a67ad4b93dab9cL, + 0x18cd0ed022d71f39L,0x04380c425f304db2L,0x26420cbb6729c821L } }, + /* 2 << 140 */ + { { 0xca07923c0eb008c8L,0xab79402d9985912eL,0x41e379e83cb02510L, + 0xfabac005beb383efL,0x24d12d9a1076dd0dL,0x95afd46fb208f127L }, + { 0x9cc38a60b1031e46L,0x93e21e977009f6bcL,0x6f6360d98ac219efL, + 0x1edaab3faf284c80L,0x9c3b5281019e366aL,0x6475c579bc9e9726L } }, + /* 3 << 140 */ + { { 0x26bd07d6bdfbcae8L,0x10b5173fdf01a80aL,0xd831c5466798b96cL, + 0x1d6b41081d3f3859L,0x501d38ec991b9ec7L,0x26319283d78431a9L }, + { 0x8b85baf7118b343cL,0x4696cddd58def7d0L,0xefc7c1107acdcf58L, + 0xd9af415c848d5842L,0x6b5a06bc0ac7fdacL,0x7d623e0da344319bL } }, + /* 4 << 140 */ + { { 0x8410d8298d85a25aL,0x48ee01354af81a14L,0xae460d0d18c25348L, + 0x5d0279a07eb035a3L,0x87e7c1289a114414L,0x17c08a8ec0744f79L }, + { 0xb7b2b4f1025cdbe3L,0x9a74f15d82d1af60L,0x124a7395b51ee685L, + 0xf2937c4bf6122422L,0xb4ec133207f1a7ffL,0xad801112f886032eL } }, + /* 5 << 140 */ + { { 0x4c0d78060c9d3547L,0x993f048dcf2aed47L,0x5217c453e4b57e22L, + 0xb4669e35f4172b28L,0x509a3cd049f999f8L,0xd19f863287c69d41L }, + { 0xe14d01e84c8fded0L,0x342880fdeafd9e1cL,0x0e17bff270dc2bf0L, + 0x46560b7bc0186400L,0xe28c7b9c49a4dd34L,0x182119160f325d06L } }, + /* 6 << 140 */ + { { 0xdd4eb3d07bb5346eL,0x9a46ad01382e7db7L,0x1200285ddc1973c7L, + 0xfd342beaa0046b98L,0xd19173491219a7fcL,0x5383d319b7caffe5L }, + { 0xea5a0c4e2e0fa118L,0x1cc2de3ca5457b28L,0x5b2a16dc6046eeeaL, + 0x1755e1fecc8e64b1L,0x51e4946e9e7faddaL,0xf805422ffcbf4ec2L } }, + /* 7 << 140 */ + { { 0x46d70888d7e02e18L,0x7c806954d9f11fd9L,0xe4948fca4fbea271L, + 0x7d6c7765bd80a9dfL,0x1b470ea6f3871c71L,0xd62de2448330a570L }, + { 0xdaecddc1c659c3a7L,0x8621e513077f7afcL,0x56c7cd84caeeef13L, + 0xc60c910fc685a356L,0xe68bc5c59dd93ddcL,0xd904e89ffeb64895L } }, + /* 8 << 140 */ + { { 0xf877e8c6bd08ffafL,0x24718fefaf23012fL,0x19ff269f2b004cfeL, + 0x8adc5d7795450f8bL,0x688ce8bce2a7d458L,0x74d7445b97bd7fdcL }, + { 0x1b9f4ad641e6abadL,0x6652ed05f00e4bf5L,0xabee1f7e71d83d86L, + 0xe693c76d25ffc219L,0x1c9a84afc873f553L,0x84d2718766d77a55L } }, + /* 9 << 140 */ + { { 0x75d874fb8ba7917aL,0x18fa7f53fd043bd4L,0x212a0ad71fc3979eL, + 0x5703a7d95d6eac0eL,0x222f7188017dead5L,0x1ec687b70f6c1817L }, + { 0x23412fc3238bacb6L,0xb85d70e954ced154L,0xd4e06722bda674d0L, + 0x3ea5f17836f5a0c2L,0x7e7d79cff5c6d2caL,0x1fff94643dbb3c73L } }, + /* 10 << 140 */ + { { 0xe566dc057e5f7121L,0xccac74e22ed07bc3L,0xaabfdfcdc70401b4L, + 0xac9fc4496254e0dbL,0x358d885f11c7de05L,0xb8e6a4a9d60772b4L }, + { 0x884272a5cfe917ceL,0xdfbe98689a3d347aL,0x06b90848c9d1baccL, + 0xc4ccedb6db8c6288L,0x892878b979e5683eL,0x1b521829243273e3L } }, + /* 11 << 140 */ + { { 0x916e19d0f163e4a8L,0x1e6740e71489df17L,0x1eaf9723339f3a47L, + 0x22f0ed1a124b8dadL,0x39c9166c49c3dd04L,0x628e7fd4ce1e9accL }, + { 0x124ddf2740031676L,0x002569391eddb9beL,0xd39e25e7d360b0daL, + 0x6e3015a84aa6c4c9L,0xc6a2f643623eda09L,0xbeff2d1250aa99fbL } }, + /* 12 << 140 */ + { { 0x099369c4bf0c6fbeL,0x976f78b2fe7d5727L,0x32feb503d18267a9L, + 0x162c41501a7dd0feL,0x3141e37726b8e969L,0x50497a643b53a94aL }, + { 0x96159f41607b4cfcL,0x1999b7042f111babL,0x3254987c760f2eaeL, + 0x5308075b841014faL,0xc634127e4e7adad8L,0x32a70a6059ffbfe6L } }, + /* 13 << 140 */ + { { 0x1feef7ce93ee8089L,0xc6b180bc252dd7bdL,0xa16fb20b1788f051L, + 0xd86fd392e046ed39L,0xda0a36119378ce1dL,0x121ef3e7a5f7a61dL }, + { 0x94d2206192d13caeL,0x5076046a77c72e08L,0xf18bc2337d2308b9L, + 0x004db3c517f977b1L,0xd05ae3990471c11dL,0x86a2a55785cd1726L } }, + /* 14 << 140 */ + { { 0x7279c369a1f857e6L,0x029d30ef27fb373aL,0xe82cbc806827358bL, + 0x2bfe09aaa18f57abL,0x63bf3145e5503492L,0x7ea15beafb28ee43L }, + { 0x8e6d428f5eec91b8L,0x215e03e9611b1799L,0xb995737161d476deL, + 0x2320c764e76726a5L,0xc5de88178e5e26f5L,0x24aae0699161e0b7L } }, + /* 15 << 140 */ + { { 0xb8d9b28672107804L,0xb5a7c4133303b79bL,0x927eef785fa37dedL, + 0xa1c5cf1ead67dabaL,0xaa5e3fb27360e7c7L,0x8354e61a0a0c0993L }, + { 0x2ec73af97f5458ccL,0xde4cb48848474325L,0x2dd134c77209bc69L, + 0xb70c5567451a2abeL,0x2cd1b2008e293018L,0x15f8da7ad33c0d72L } }, + /* 16 << 140 */ + { { 0x5584cbb3893b9a2dL,0x820c660b00850c5dL,0x4126d8267df2d43dL, + 0xdd5bbbf00109e801L,0x85b92ee338172f1cL,0x609d4f93f31430d9L }, + { 0x1e059a07eadaf9d6L,0x70e6536c0f125fb0L,0xd6220751560f20e7L, + 0xa59489ae7aaf3a9aL,0x7b70e2f664bae14eL,0x0dd0370176d08249L } }, + /* 17 << 140 */ + { { 0x5dc386d0a8790657L,0xa4fdf676bc4d88bbL,0x1b21f38f48bc6c49L, + 0xcdcc7faa543a7003L,0xea97e7aa8c9cf72cL,0xa6b883f450d938a8L }, + { 0x51936f3aa3a10f27L,0x0170785fdecc76bfL,0x7539ece1908c578aL, + 0x5d9c8a8e0f3e8c25L,0x8681b43b9e4717a7L,0x94f42507a9d83e39L } }, + /* 18 << 140 */ + { { 0xaeac64c96f089b59L,0xecfdc92b65f9d762L,0xddde5024f750daffL, + 0x82c01c1c0f707e73L,0xc70aa9d4ee20adb5L,0x27f6799dbeb0e60fL }, + { 0x918ad262520aa514L,0x2bb1362f8d13eae0L,0x21b60b46a9d1d43bL, + 0xf449e2d4767ab86eL,0xf42b09948a5a496eL,0x3b26006b853f2a3bL } }, + /* 19 << 140 */ + { { 0xbbe11ca8a55adde7L,0x39e6f5cf3bc0896bL,0x1447314e1d2d8d94L, + 0x45b481255b012f8aL,0x41ad23fa08ad5283L,0x837243e241d13774L }, + { 0x1fc0bd9dbadcaa46L,0x8df164ed26e84caeL,0x8ff70ec041017176L, + 0x23ad4bce5c848ba7L,0x89246fde97a19cbbL,0xa5ef987b78397991L } }, + /* 20 << 140 */ + { { 0x364d5dfda6140b89L,0x30e4a48efdc9105dL,0x13f6276018a47151L, + 0x18ad84cfa17a2853L,0x5f315c93988cb37bL,0x90f9cb701af64ce3L }, + { 0x020c67db029b6ffdL,0x8989ccc62ce3528dL,0x9bb4f9844d00ee63L, + 0x0b052413a70b4ca9L,0x7dee36dcc96b4a07L,0x226db70ea7888508L } }, + /* 21 << 140 */ + { { 0x111af1b74757964dL,0x1d25d351ddbbf258L,0x4161e7767d2b06d6L, + 0x6efd26911cac0c5bL,0x633b95db211bfaebL,0x9bedfa5ae2bdf701L }, + { 0xadac2b0b73e099c8L,0x436f0023bfb16bffL,0xb91b100230f55854L, + 0xaf6a2097f4c6c8b7L,0x3ff65ced3ad7b3d9L,0x6fa2626f330e56dfL } }, + /* 22 << 140 */ + { { 0xcd9b76b6a92f4e61L,0xa464f5225a00d902L,0xb64774e68a583f92L, + 0xc7dc2030bee842a8L,0x594743ea5d2f27ddL,0x4c0ed28ef3c54609L }, + { 0xd763346d4b1dfb93L,0x8ea291dde1bed2eeL,0xf26d4adbd6d34ae1L, + 0x74b8d24e54ea3529L,0xe20490e150062077L,0xf67b7a9092d6c19cL } }, + /* 23 << 140 */ + { { 0x3d28bf2dffccfd07L,0x0514f6ffd989603bL,0xb95196295514787aL, + 0xa1848121c3db4e9cL,0x47fe2e392a3d4595L,0x506f5d8211b73ed4L }, + { 0xa2257ae7a600d8bbL,0xd659dbd10f9f122cL,0xdb0fdc6764df160fL, + 0xff3793397cb19690L,0xdf4366b898e72ec1L,0x97e72becdf437eb8L } }, + /* 24 << 140 */ + { { 0x67bf4c98e11df408L,0x8e105c66d299b156L,0xfde3922e901b63c7L, + 0x7fd57218c184ac91L,0x6dd2ea5cebcdc105L,0x1c4956c0aef7653fL }, + { 0xd6fac6429c1c11a1L,0xeda44f663d230d5dL,0xecca2241e6902ccbL, + 0x85962a1f2700870fL,0xc5ca32c97864a291L,0xe55e974af6c8d3d9L } }, + /* 25 << 140 */ + { { 0x81dcea271c81e5d9L,0x7e1b6cda6717fc49L,0xaa36b3b511eae80dL, + 0x1306687c3cd7cbb3L,0xed670235c4e89064L,0x9d3b000958a94760L }, + { 0x5a64e158e6a6333cL,0x1a8b4a3649453203L,0xf1cad7241f77cc21L, + 0x693ebb4b70518ef7L,0xfb47bd810f39c91aL,0xcfe63da2fa4bc64bL } }, + /* 26 << 140 */ + { { 0x0af51a2025f7b355L,0x35fc45d58d8081bfL,0x0cf3036d0ab30d16L, + 0x2bd47f919109cf76L,0x8be09360ec7f12beL,0x99fc291be8dcdca9L }, + { 0x385b89868135b12fL,0x272ac288f4ec52dcL,0xe7ca370cce09b043L, + 0x94655816251f4c4eL,0x5c1dea972d40a755L,0xe8977234a4b10406L } }, + /* 27 << 140 */ + { { 0x82c1c684eaa66108L,0xe32262184cfe79fcL,0x3f28b72b849c720eL, + 0x137fb3558fee1ca8L,0x4d18a9cde4f90c4eL,0xc0344227cc3e46faL }, + { 0x4fd5c08e79cda392L,0x65db20db8adc87b5L,0x86f95d5b916c1b84L, + 0x7eda387117bb2b7cL,0x18ccf7e7669a533bL,0x5e92421cecad0e06L } }, + /* 28 << 140 */ + { { 0x240fde37b21b2632L,0x6b878ae68ca0f16fL,0x072d9ded0bc32ebeL, + 0x8c2552bc29840743L,0xb58327b003b34f8aL,0xa51598ea71dabbfdL }, + { 0x337361f7d4f461c6L,0xae88972dda1de4b2L,0x9ec86d7ade7e8c2eL, + 0x607de383f23f19e0L,0x0cb144c27d234103L,0x00878a228f0c3411L } }, + /* 29 << 140 */ + { { 0x26063e124174b08bL,0xe621d9be70de8e4dL,0xaea0fd0f5ecdf350L, + 0x0d9f69e49c20e5c9L,0xd3dadeb90bbe2918L,0xd7b9b5db58aa2f71L }, + { 0x7a971dd73364caf8L,0x702616a3c25d4be4L,0xa30f0fa1a9e30071L, + 0x98ab24385573bc69L,0xcbc63cdf6fec2e22L,0x965f90edcc901b9bL } }, + /* 30 << 140 */ + { { 0x265f7236e22b29caL,0xe36c3c3daa62691aL,0x73410e6ed2e1bad1L, + 0xa182a579a5743cecL,0x2ca67274c22b0453L,0xc698fe35546e52e6L }, + { 0x60b3a519890e9155L,0x24312c3c2b91dbc3L,0xa6d45050282911d9L, + 0x3781933efd249e1eL,0x2e0cbb93e26d023aL,0xfb479267bf27687aL } }, + /* 31 << 140 */ + { { 0xd53b592d71e15bb3L,0x1f03c0e98820e0d0L,0xce93947d3cccb726L, + 0x2790fee01d547590L,0x4401d847c59cdd7aL,0x72d69120a926dd9dL }, + { 0x38b8f21d4229f289L,0x9f412e407fe978afL,0xae07901bcdb59af1L, + 0x1e6be5ebd1d4715eL,0x3715bd8b18c96befL,0x4b71f6e6e11b3798L } }, + /* 32 << 140 */ + { { 0xaff4782231cb94c9L,0xf1b5a0b7803c1af4L,0xbeb85f8d2ef696a9L, + 0x8ce5baab4fa94fcaL,0x0a32f96200d41a43L,0x0f69ad5774f6e772L }, + { 0xbe0221af6ccb5157L,0xcb83969a2a4f91ffL,0x78ff85d6a7e49f39L, + 0x63006589cb5d3c63L,0xe8e4383596eb65f5L,0x79f59da9ff8adbdfL } }, + /* 33 << 140 */ + { { 0x3cc0df125df9b6ecL,0x3c18f44e286d6ef1L,0x55a3939e517d0f7dL, + 0x42626a32607e97bbL,0x6168e7b2e26ad78aL,0xdcf8e74b9145583aL }, + { 0xa7c541a52db84a71L,0x680532c7119210a6L,0x3252035d0a3315e5L, + 0x06dc2d5befe7c8b6L,0x940175894e720570L,0xb16e635f2f6a3ec6L } }, + /* 34 << 140 */ + { { 0x0bd0ed3803e13ce1L,0x44a148bb5868069cL,0x2a79ab57aa5095e6L, + 0x943416faffffcf22L,0x98434e8756a1365cL,0x2493315d196dc354L }, + { 0x1f89d911b79a3a1eL,0x937140a841dfdd23L,0x05ad36e43b220b8bL, + 0xff5e810333594e3aL,0x3119775f893edb80L,0x1fad811627eee584L } }, + /* 35 << 140 */ + { { 0x55c4377e204f30b9L,0x63550549a1ebd2bdL,0xdd86ee0c5e44f5f1L, + 0x8b9d1d9b5d84d999L,0x9ea95a58dda7a075L,0xa465b4a50977e81fL }, + { 0xcb491e5558421fadL,0x4617f31c280709d6L,0x5e2751c382e0195dL, + 0x698155856f8eefd1L,0x6702166cd16dc160L,0xfc14545c84c85b2fL } }, + /* 36 << 140 */ + { { 0x27c961f6e8fc35abL,0x1e0c26923a596fe7L,0xc75c7cb804351be8L, + 0xfb92bfeb1c425d80L,0xb01d1c909f0bde61L,0x273d1f0c512f7817L }, + { 0x4375000df0d71796L,0xc1655874cf53d529L,0xe157b358abddc21cL, + 0xb0f91e3e40cedc30L,0x48e26c7272260452L,0x9794a6bf0713f667L } }, + /* 37 << 140 */ + { { 0x78befaede72c6f0dL,0xc80584210bb2a3ceL,0xcee67a5d52748e21L, + 0x08d4a9e8de8ed124L,0xc0393271b5fb9514L,0x39b1df6b20942000L }, + { 0x831fd8cfc3d961afL,0x1bb097e3e752daceL,0x279b3924cf2c8143L, + 0xa9f8a939b8f5cad9L,0x2b566813bfb8009cL,0xab37ee1df58f0927L } }, + /* 38 << 140 */ + { { 0xc17f21f5134d8bd8L,0xc75fc638a90a9a1aL,0x032a6f382a22527bL, + 0x3c77a72bd20fefb2L,0x559d8a52196e2921L,0x760a3a2c9afcb6caL }, + { 0xa3bf5802f162d871L,0xb6b367a5c594d2adL,0x4d440c523daa48dbL, + 0xb2a8acafd5b2c18aL,0x50d85d6adc349ddaL,0x3c2e67718a707475L } }, + /* 39 << 140 */ + { { 0x8254a39d5e1656cdL,0xff457dcaa595e153L,0xf0ddc1936bf62398L, + 0x45e1f91a558f9337L,0x8a424d9d91480b33L,0x019f0a412bf61189L }, + { 0x66badaa6d49e7b98L,0xb0674512dad636faL,0xc767eceff4c49695L, + 0xbe16e6b5ddc80ea0L,0x2bd0bb87febd1ba6L,0x69c9f485fe60eb32L } }, + /* 40 << 140 */ + { { 0x08cf7d82bff4b684L,0x6abbf429ac4a9329L,0x2454c15ab0c8e0ffL, + 0x4782035a70bdb03dL,0x89ff6a41448199cdL,0x07969c9ffd0bf1e5L }, + { 0x19d1cc6a83406dc9L,0x4054cab9b4980267L,0xf0f5594e1887d258L, + 0x039249e4e09dd987L,0x2b0cd4f9857ddb1eL,0x54ceb29fd8418075L } }, + /* 41 << 140 */ + { { 0x562693d30843729fL,0xd703202122648488L,0xd7c40e82ec6d0799L, + 0x8eacb2496eb6fb6bL,0xddf7074885a5ec47L,0xd70524bf891d5de5L }, + { 0x4d17c237c4d01055L,0x4793c6e4b4203cc0L,0xf247d0df1d1bf37aL, + 0x406994fa93b007feL,0x4062c29902940092L,0xedc0d949f558c1e8L } }, + /* 42 << 140 */ + { { 0x9fb3630606ab1fc5L,0x2726c1acc0de4e26L,0x8b2fb5130ec7b070L, + 0xf3581a6907bacd4aL,0x97db622c164bf5a5L,0x8103517962327e3eL }, + { 0xad3637b0b1d635c2L,0xb894adf949832ec3L,0x0ab5381725685b12L, + 0x73ceb46069720ce8L,0xdbd1b68ef5e445dfL,0x57659059c8961eb8L } }, + /* 43 << 140 */ + { { 0xbd1272a5f73a7cfcL,0x30d3c078de0828e1L,0x5dc0244e1a8f36a1L, + 0x87c80cdf585ec2acL,0x46c88d277944584cL,0x588d14d8b2dbe1a9L }, + { 0xb42327a7afe7d55aL,0x58add8f98775409eL,0xa45db2fd10590c68L, + 0xb98e10bca972b84dL,0xbf5c0ee0a737aeb6L,0x26424f3def199fa1L } }, + /* 44 << 140 */ + { { 0xb7bb774603c4cd27L,0x5bfe638ad9723678L,0x47d8b4c24a04d064L, + 0xdba309383faa45d7L,0xb0fb4308b39dd043L,0x5eeaa33f23ebfa1dL }, + { 0xaa5a0ce0ba100837L,0xae025cf6d7667d17L,0x610baf5df480cf99L, + 0x8ba0039ead025771L,0x0ff4f75174785f24L,0x910736ef8b7c30b7L } }, + /* 45 << 140 */ + { { 0x0496b77ac04b7e7fL,0x6f7ea5bbdf8163a1L,0x87a8e8f18f415876L, + 0x6e5b6f2e3ee22085L,0x5ae860ca6f529471L,0xc54c8667eb624447L }, + { 0xdd06be3de1c7766aL,0x8a8e48ecd2189d23L,0xa4076d3564245444L, + 0xc4973a5deb651a4bL,0x3b3e2fd52c4f2747L,0xe9a16a24abde2ecbL } }, + /* 46 << 140 */ + { { 0xb7f146b890973714L,0x2277873f288ed67fL,0xe6da9d9ee5182317L, + 0xa446f9d3562475b3L,0xc5291f9756755d91L,0xe762c5f3c104c2b6L }, + { 0x542f90b3dde83d53L,0x758aaddddace5f42L,0x1c8b9775e673f002L, + 0x8899c11f74ec42bdL,0xfd9e300a2dbc0dedL,0x6de1c8e4d281f6adL } }, + /* 47 << 140 */ + { { 0x5ddafb1b2a2f98cbL,0x8dc2bdc429ec504fL,0x27c51b3cc9f43826L, + 0xcfd609fccacf5becL,0x642ff85c30dd9f71L,0xcab498e5b6b00ffdL }, + { 0x9c7ef286652ca743L,0xda291ae0ab95d7aeL,0xe6f4d2badfbff466L, + 0x34afffef9835d482L,0x41a2cfc050db295cL,0x51a08859e6ee400eL } }, + /* 48 << 140 */ + { { 0xf6fd26cc487925bdL,0xd9b751eef5ef44e9L,0x694a788be372817eL, + 0x85f3dc1ae8c90c31L,0x8c90c6bf15aa0ce5L,0xb52a5d83f01bb223L }, + { 0xbdae01dddf9c3315L,0x941fa6b663ddfc56L,0x50ddff4ec2548f24L, + 0x54a49868d12802a7L,0xcd922fb6404d9240L,0x88d7f41f957f6d1aL } }, + /* 49 << 140 */ + { { 0xbfd0a17e4c4c87cdL,0xc6c76ebb10b614bfL,0x721d8b4fd1c594a9L, + 0x1ff70b2daff65d09L,0x2698f57ce50ad026L,0xf4ac3f5627a92e38L }, + { 0x1114d3392c143ba0L,0x7fafa6b97f8e9b0bL,0x506f11edd82a2500L, + 0x4df1087fe0ad9ca2L,0x85509ad9fdfecaa2L,0x733c4f8293bd022dL } }, + /* 50 << 140 */ + { { 0x3b9de3494233d6cdL,0x9a360917a8f55d63L,0xbe79cdfd90662136L, + 0xbb3d8fd7cbf3f02aL,0x5d0d4eb81d61e485L,0x85b485215484cd65L }, + { 0x77580c810fc5cbb1L,0x4b36441bd8e70ff2L,0x50ccdec1b2107a8bL, + 0x6b7f97c945a45893L,0xb818859b9572a173L,0x864dc632d94bd9beL } }, + /* 51 << 140 */ + { { 0x13bb6b113fee0074L,0x4c02520ed1059617L,0x5beb793ccf71f07aL, + 0x15a8d28d46d4c54bL,0x9889a8948b89fab6L,0xd00fdcb492623b75L }, + { 0x1c7963572939a84cL,0x4b85d94d6221a244L,0xcc66b5bad1fd506dL, + 0x866271042a06ca91L,0x4295fc6a49bb18c1L,0x05a81eea341d93e4L } }, + /* 52 << 140 */ + { { 0x895dbf20df8111ccL,0xec8297be2906fb2aL,0x4ddd6f22b94c3f53L, + 0xec55cc738ecbd552L,0x549d3145ef343a0bL,0x9b19220c3b4858d8L }, + { 0xd5bbf954bd0c2f11L,0x9cacae0cce8c221fL,0x87e6cbc1f6a3dbc5L, + 0x7ce5c9b6e37ebcb2L,0x654339ef50eb3c8fL,0xeac7f343f3674f55L } }, + /* 53 << 140 */ + { { 0x723969a3dd8d5580L,0x4f6dd5c4a30edd79L,0x5b29f3f5a4d7ed53L, + 0xe17a12bd11869af9L,0x63d01e02dc4c4c1cL,0xb43b904466a691e9L }, + { 0xab58d45ad1bbbcbeL,0x1e9b166322e8a57bL,0x88b6d3bb6684cdd9L, + 0xb944dee1ddaf3976L,0x70a4a121c347c41fL,0x7e93fa26fd1c217fL } }, + /* 54 << 140 */ + { { 0x5df68a1b584da350L,0xf378c367d72cd093L,0x5908ac0033dc31a6L, + 0x89bb976b7ca65b9cL,0xefdadfe237dcf670L,0xce22b5ba0011f3e7L }, + { 0x94d2c115b7d27bc7L,0x2e6763498761afbfL,0x3c0477829eb8185fL, + 0x634c8c5531f7635fL,0xf8fb5494d4d0fc53L,0x5a905615530ee2c3L } }, + /* 55 << 140 */ + { { 0xd28e59a0940c9809L,0xc208ae4f01b9f39fL,0xae1cb420b3630002L, + 0x739950501289d72bL,0xec24392805fcbd8eL,0x5b592df51f843891L }, + { 0x0d7602303f59f374L,0x32b6e643cae9f3ecL,0x94a25696e3dcc436L, + 0x657ae6aa8a059dadL,0x0df91017edd1505eL,0xfb1ae06f7b518d81L } }, + /* 56 << 140 */ + { { 0xf5bd119ad84c8a53L,0x36c5410f26928a6dL,0xf340f2bc0eb42b83L, + 0x8d93a66cffeffe84L,0xff59141d64310b9eL,0x2d509d7aaf69e00fL }, + { 0xf0f034ae1390628dL,0xf9089c720c38b563L,0x7462988e4e8df0daL, + 0xe6041dcaa7985905L,0x86295326d3b7274cL,0x5c8bf249075aa31aL } }, + /* 57 << 140 */ + { { 0xb08d098b9e423b93L,0x8ae94622029d192bL,0x05335f68fd67f1c4L, + 0xf3cb831f6e8c1e57L,0xf84a7a54a50a776bL,0x99930a48dc49c28bL }, + { 0xdac2ef8f1b833418L,0x87a4ca7829fda2f2L,0xf47f23079c0e9e7bL, + 0xebc1c2de46aeb3c7L,0x544f76836408bfc4L,0xa01b094b86c6cd44L } }, + /* 58 << 140 */ + { { 0x8e81bd1c06841f10L,0x3fc24a346c045063L,0xbb2be2dc85bc7ebfL, + 0x32523efbc341fe12L,0x1ac9f6b116508a41L,0xb6b7fa1df6ac4426L }, + { 0x2614c995fb685157L,0xe452b94dace46bbcL,0xccda1adabc453b4aL, + 0x32d32574fb4fac48L,0x7e43920c9d7d90fdL,0x9d6e959417a08456L } }, + /* 59 << 140 */ + { { 0x2c90f95bdb1f005dL,0x801089a2e16444a3L,0x2f2944ed7a724ad8L, + 0x0dfdd065de135e95L,0x510ab3eaafed3817L,0xdba075380855fbb5L }, + { 0x905f78bda10dde49L,0x63786348956a4057L,0x3d420ff0441530aeL, + 0x7a9968bfd1488ff0L,0x97479bfbca4dce2eL,0xf371985356f76255L } }, + /* 60 << 140 */ + { { 0x8102fa85bbda55a7L,0x6cbafe0de96c5eb3L,0x517720eb26aa52c7L, + 0x0ee110a98c030e47L,0x5a058569d4afe2c1L,0x29965b44262bbc0dL }, + { 0xda017ec04996daf5L,0x1781e7b84dfb810cL,0xdbe148350c8a5cf6L, + 0xd151055dd92ff62eL,0x5e4f48ba2932a708L,0x77e163d95f28bb43L } }, + /* 61 << 140 */ + { { 0xf6c5998c48bc9bc9L,0xb25ae99e2db132d7L,0x17f29131fb934e7dL, + 0x31b96a79d7fb5430L,0x3fad00391971cabaL,0x7f809e56cf3d5e33L }, + { 0x1a4f705a9ede6055L,0x3cab6c6149c2d054L,0xb616adc47945b589L, + 0x842b8652f342ee03L,0xa22fc6a67bc36a4eL,0xffdfee262c89a4fbL } }, + /* 62 << 140 */ + { { 0xac6b2727dab13b10L,0x8b4fa7807351ac35L,0x48243c245692808aL, + 0x724897f01fbc5d24L,0xb635fe5e2c69bd93L,0xab26453338d5d5b2L }, + { 0x368b2c07bc578c97L,0x94e02c9226fecf25L,0x768de4d41f473908L, + 0x58feaadee445d405L,0x1f1380d6e42a2218L,0x2904b4542154dd5eL } }, + /* 63 << 140 */ + { { 0x4e28b938ca2ec0f3L,0xd4af48d795b1c113L,0x33ffb9c222f2275aL, + 0x2a734af97b57b2e0L,0x1555ba38d08a45d3L,0xd0cae6c57a05837cL }, + { 0xed04c869c4e78884L,0xa7ba74726f3d56d3L,0xdb7b831ef6d68485L, + 0x225798677e7d0a4dL,0xd2d702a94c3eef8cL,0xdaba503869a83e29L } }, + /* 64 << 140 */ + { { 0x082ea61d10eeed24L,0x7c9d5ade143fd59dL,0x7d33df962e54f5cfL, + 0x340b0d36e39dc6abL,0xd97a8b848d179b13L,0x88184bb0288d388cL }, + { 0x2237e507e116ae6dL,0x3e97b063211b2cf0L,0x645f8bcb42be7459L, + 0xce2b0f54de2176b6L,0xaf570a09d1e2f09cL,0x110adf5657fdc001L } }, + /* 0 << 147 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 147 */ + { { 0x158bfe27bcb6db29L,0x967212410054d963L,0xf07b153b8e71aca1L, + 0x5e67698171b11643L,0x77b7dd7dd04e2f90L,0x07814aa6f0dcf109L }, + { 0xd3bab2a4fe1d0b1eL,0x50abba31be69e691L,0x54fe99afc6f53cd9L, + 0x071f2a4f628039e4L,0xf1f44181b183aa16L,0xdf0138e05010f6f9L } }, + /* 2 << 147 */ + { { 0xb1e365019c77ca60L,0xfe084a2301018e14L,0xbf451d2ca4bfdcecL, + 0xd210892fb29cdcfeL,0x5b12bcd894514871L,0xd03ca18c1809b1e3L }, + { 0x09b243115858e4eaL,0x37b30d50e57524b4L,0xcef0a16b5de334b5L, + 0xfe0bd1e20b116076L,0x54e4b48289ae2bf4L,0xfbcc5e1a68c8a937L } }, + /* 3 << 147 */ + { { 0xa5023e1364be0f56L,0x6a7310e00046f45cL,0xe0af09aeec8700d3L, + 0xdea5fb7ceb2d38f0L,0xc038eae6859852e6L,0xd515fb4c8c34f04cL }, + { 0x546b778e1488c207L,0x8cf4f1146258d8baL,0x474e60d85182c96cL, + 0xcd0387303dbde757L,0x387232f876ab01ffL,0x277614f628231392L } }, + /* 4 << 147 */ + { { 0x309b1eb33ef5a413L,0xa7607981a81f43fbL,0x87c2b81ebf8a894cL, + 0x27a40bce0d293293L,0x7f4c315be4bf3714L,0x03fdc14e01236895L }, + { 0x319c88f8dff053feL,0x146bb448ea3fa121L,0xfcc2a05df0dd1380L, + 0xc8d55b024acba9faL,0x871358de5927313eL,0xfd1d81d317ce294aL } }, + /* 5 << 147 */ + { { 0xa135970c7361138aL,0xd67eddb5b7d50260L,0x313c6e9bc4d5311bL, + 0x4f503bf28423e5b4L,0x17dc4b6f44f3fe83L,0x15b7bdb9ccf1bbcdL }, + { 0x0ce4d64ea11b9896L,0x050b0edebbb6b0eaL,0x85531293bf5db990L, + 0x9db3b964520d095eL,0xb45ec235bd2d4e88L,0xf88a9e6215ee5ba1L } }, + /* 6 << 147 */ + { { 0x10777189c1a21254L,0x7d8d3966ca593a6cL,0x261ab515120380e6L, + 0x453c858fe13577d1L,0xb1f6bb58f3862db1L,0xf8ff48b8b9529e1cL }, + { 0x03f63a417b60b400L,0xdc248d96bba66b3bL,0x8423048b756e5af2L, + 0x4d978ed31c984befL,0xa06242995ba00f3eL,0x0bed7b454f4d19e7L } }, + /* 7 << 147 */ + { { 0x9ef52e3d6524f389L,0xc5b157c5f6ac19eeL,0xdca7a72ab5d42f7aL, + 0x2d2e8d72fa0051dbL,0x3a6ff9243f4a4f60L,0x0ae997af340e7977L }, + { 0x33dd395e269db4e9L,0xf95c3683616b9dc3L,0xb86a066122d516a7L, + 0xd50c582cad913df8L,0xac8b8efef550afbfL,0xf34fcab01d88728cL } }, + /* 8 << 147 */ + { { 0xd3797831ff63ae69L,0xa753de02ce4c7eafL,0x2ff7a6a611a4e339L, + 0x904f86f05328043aL,0xe29d31c012e9f7ddL,0x8825a639c0a51904L }, + { 0x070c2696ebfc2cc7L,0xc03ce643c5f7a943L,0x5b970d0c12c8a1f5L, + 0x572aaaa1ab352a83L,0x63df45a90c5eb0c7L,0x95c951e1d4977599L } }, + /* 9 << 147 */ + { { 0xf5aefd5572ba3741L,0x7ab81965f5fe816dL,0x597d15d546752cefL, + 0xaa79a0822a3c142bL,0x038ddfdd3af5dfe9L,0x9f4dc166755c9e07L }, + { 0xf34224dfb9165297L,0x96e7ff6e4e3fd907L,0x5d7f3c821727beb6L, + 0x7098493dd6af73ceL,0x6b9358fbe00dfa4dL,0xefb2634a96e74870L } }, + /* 10 << 147 */ + { { 0xe35daffe2e4c6299L,0x1f9e33935915cd16L,0x93f05a40f009a48aL, + 0xa4a801fd308a81c6L,0x75e5dc467e885426L,0xf0bc7d5d4629ff05L }, + { 0x356b879bdbd812c2L,0xdb5eb60001629849L,0x11c9856eec2dd55aL, + 0x20f0443880f0c804L,0xc0b5e3e21801b217L,0x7ceba67d6ea097b8L } }, + /* 11 << 147 */ + { { 0x7a1bc5d85d08d3f0L,0x9ecce2a8385ef3a8L,0xae93d42b3c1b2927L, + 0x81a3a60719ce9447L,0x8d6b2d3d0eda597cL,0x5baabad60eea6dc5L }, + { 0x2cb372642741608aL,0x3b1148d6f0202a01L,0x6e85272f52931f5dL, + 0x49bf47596a2e601aL,0x5ec0418443279ddcL,0x7d052cac6ec080ddL } }, + /* 12 << 147 */ + { { 0x01c2df8d3bb02d0eL,0x874e43afe26f388dL,0xe198341c8360fa6aL, + 0xe67f8092c52bb2d6L,0xf944dc63a02efba5L,0x9a9c02d92c12332aL }, + { 0x39684f6ca8cb6bd5L,0xbcc1828e26bc9535L,0xb7fb8eb646594725L, + 0xbb4f5f05793c32ddL,0x3ef3c33845f94b55L,0x228e0e7d09eac277L } }, + /* 13 << 147 */ + { { 0x80d9bd388aeae732L,0x2be676dccbeb6443L,0xef4d056bded9ad31L, + 0xc4fea44f349e5d0eL,0xb66c35d28d95db86L,0x210c3d4aae9f5d3aL }, + { 0x5c0c5b9c1582982bL,0x50a529be93aed9a4L,0x88f769a384c77818L, + 0xc0970b4269776a3eL,0xbf3e5ee022a1cad4L,0x705c0b29b80187eeL } }, + /* 14 << 147 */ + { { 0xefd26dca727cacdeL,0x6290fedb5fcdb147L,0x9f108a89e1830a96L, + 0x7e8e36813e039a02L,0x1747b3e9256fbb3bL,0x5aa0ebffabb3b2f1L }, + { 0xcac5818c9fbb9b49L,0x037d66114a94b74eL,0x4081fd4d7a548536L, + 0xfe2d8e79aa364507L,0xe86ce00ea81a5f81L,0x77b95e9477a9bdb4L } }, + /* 15 << 147 */ + { { 0x3eadfde5bf06a49eL,0xca88828b33787c62L,0xde6f765022070f63L, + 0xcb4e54dc438f649aL,0x24957c77169727d0L,0xa2e7781cdd2a92a3L }, + { 0x17a1d7ddc38885f4L,0xb75716717605c408L,0xfdbbcffc8a2323f5L, + 0x11666bd2c955456cL,0xf8b94fa2517f27f5L,0xe101927fee002499L } }, + /* 16 << 147 */ + { { 0x2c5b0e42bca07a42L,0xbe57f3597a0dffa1L,0xace485959aa90727L, + 0x32be886af658699bL,0xce75d6c6da3b18e6L,0x9d563e4f69caf667L }, + { 0xc17c66cf065eb772L,0xfbe123814df9f6efL,0xceb80041623db4efL, + 0xe75615b2c74762e1L,0xade8a5438671c52fL,0xb713c401cacaf2ecL } }, + /* 17 << 147 */ + { { 0xc740669ab01b20dcL,0xd873f3f1abecc3f3L,0x0d8290402db73d1cL, + 0x147aaafb99198d33L,0xca66e755d4e7d7e4L,0x8747298cb2cb752bL }, + { 0xd9d58d29c43762aaL,0xa3801a4a15e45d57L,0xa747fa3f454eaf2aL, + 0x26c79cdd0c067c77L,0xf15404cea24fe6b4L,0xe2add5ec77fec1c9L } }, + /* 18 << 147 */ + { { 0xc45064dbd71a7744L,0x1900bb8f04a6f3cbL,0xd592585a76c2dd6cL, + 0xabbbd6d862b95d26L,0xb0db482b1d2e180aL,0xf459430184c9dea5L }, + { 0xd30b162a6e5ec460L,0x90838e57e4b35476L,0xab4b7c80f9356687L, + 0x72c2c009719f347aL,0xd5d01fcf920d187dL,0x47426f1e0afe06abL } }, + /* 19 << 147 */ + { { 0xe6473aeaafb2f584L,0xd5395475c44ab7a2L,0xcba2c240bc27e864L, + 0x201735cc742c1c9bL,0x8cb4886951263febL,0xb52706ba4fd2cd5bL }, + { 0x028445755a2dec94L,0x978e79d6a4be7b6dL,0x5a68d8103c4742f8L, + 0x9c917f48b301ad64L,0xa6a7d5bd684a6ea6L,0x251d61327c978749L } }, + /* 20 << 147 */ + { { 0xdc7e39ee0ae2a7caL,0xcdd3c235e6b7dee9L,0xf9624c299368c8a3L, + 0x2086bc904b21951fL,0xf7990a1f57e0e6a3L,0xf170dd75e686da8cL }, + { 0x4a82719a06da9714L,0x3a78e35e24274685L,0x1c3965e1c67712f8L, + 0xc6c26eb62f164e3aL,0x1129a467381fb91fL,0x896022108443ffddL } }, + /* 21 << 147 */ + { { 0x25e561bd808c4ff9L,0x08c9f2758c0cf1c7L,0x9af6165b59599115L, + 0x59f06a4bb4b415f7L,0x3a9d8ca5236e2650L,0xc8fa3bc61b48ebdfL }, + { 0x5e1896193404846eL,0x6d1d803b378a5a46L,0x672fe2bab812d5dfL, + 0x3ec27a7f04c6ddc1L,0x9c5ff08c0cee3357L,0x9f465babae8d37d3L } }, + /* 22 << 147 */ + { { 0x0057f60756a0b6bbL,0x46a6e9949c1e24daL,0x1c283f859baaf618L, + 0xd75e731be878a354L,0xf9db13388bf2ca71L,0x0f14adeea9022f59L }, + { 0x309f04aa6c14666fL,0xe6cec2aa552d2da7L,0x9f27eaba218d8659L, + 0x9b3165d3c268561eL,0xc7e3afcb90ae19efL,0xb840170bcb329e68L } }, + /* 23 << 147 */ + { { 0xf6b9a32fab95aa95L,0x1a1e06c387e1c3c5L,0xcfb7ecc5317f1c2bL, + 0x12953ce7999d2bcdL,0xcaf5f0229e3c5a01L,0x0c9db571305ac94cL }, + { 0xa423d26cafbc860aL,0x82fbbd3dfe98409dL,0x455aa9926652ac17L, + 0x6916e7d6f9428029L,0xdcfbd65099822714L,0x5de152a13f3c72d2L } }, + /* 24 << 147 */ + { { 0xe6d039ef467eb167L,0xa7e0959d74696cf9L,0xf3a19b9d7078d8a0L, + 0x5d4ec99c07cdc6f6L,0x4842d0f98386eed8L,0x48f5ab80545fc0d5L }, + { 0x8906fc626d39c2f7L,0x1c050d691bf5366aL,0xac506c579f54d0d6L, + 0x9a356a6ef9e4b94cL,0x62632c5108a75e61L,0xfc1b9fa5c6951dc2L } }, + /* 25 << 147 */ + { { 0x84ba4069d034ec62L,0xd55b42f6f169349eL,0x78dce88d17de2b22L, + 0xdadae679204ec730L,0xfad5ec6b5357f5e5L,0x330bba18ccc0d0afL }, + { 0x8419755c4a566c71L,0x29c56c5fbfe57083L,0xe42a7c52598cad77L, + 0x9d81623f5fcf1dc0L,0x978eb12864615869L,0xc837262a9c2a6f35L } }, + /* 26 << 147 */ + { { 0x917747f99ee0628bL,0x5d711303566cf048L,0x206d53f15b77f58dL, + 0xe104bc12667a86ddL,0x158f8d253505380fL,0xf5b32ad4616e821eL }, + { 0xdb67191a3cdfe797L,0x61b58589147e1756L,0xb7927e12625d0efcL, + 0x48d999d008bca937L,0x335c6f5b7b02689bL,0x4f0994a9d8149b7eL } }, + /* 27 << 147 */ + { { 0xe7ba0870df6ae3beL,0x661373f0166cd7d9L,0x369d361d8627f3fcL, + 0xca06d544cf6ceb36L,0xc819e0ea34b5d425L,0x80c1ab716ffd2827L }, + { 0x3fb8c0b520b4161cL,0x3647e67b3734b87eL,0x9c3a14b203e6c9cbL, + 0x320ed1c1c3620486L,0x6d77d46b5286a22fL,0xbd6036c1bc74a266L } }, + /* 28 << 147 */ + { { 0x125951a52e6d5433L,0x7d672aee6a6013d4L,0x6ed23f2560831997L, + 0xb0e219ae438c75c3L,0x6851dd4bace91d00L,0x84704f7d30f19991L }, + { 0xd744cb32d0107170L,0x15f51a63b0cb6796L,0xe14712cf5a5807d8L, + 0xff89f0c5dbfd612cL,0x0c314718bd021483L,0xf9ccd3b11b4b76d5L } }, + /* 29 << 147 */ + { { 0x36121d0909b6398fL,0xd9ad591369069016L,0xd3a08c8469cdcfebL, + 0xd92ae9b2b03e1e4cL,0x1620c549e9b6284bL,0x5860431227ab9432L }, + { 0x4e1d3134aa314da8L,0x89207aad70910cbcL,0xacee236badff9190L, + 0xe6390f7cf6eb6df2L,0x0dfc5a5cffa91d75L,0x3474104aa0e7f48dL } }, + /* 30 << 147 */ + { { 0x00b75b851871749cL,0x063b748ea00faa20L,0xa516e09f90257503L, + 0x9ffc43981c800098L,0x49f011f871b00fa1L,0x6fc80517443268bfL }, + { 0x2802e2bf24a24acaL,0x96fdc71edde88ab9L,0xe3eff1f997e661a4L, + 0xae5c34e13cb321f8L,0xf863263e301c8ba0L,0x3c3eeb7b093e186cL } }, + /* 31 << 147 */ + { { 0xc0f51229e7aa3325L,0x3abde561fa93ec80L,0xd7e5317f4e6df2b2L, + 0x4eefcc76bc832652L,0x9dce52905d054a1dL,0xee2939da2a6f52e2L }, + { 0x8faa1d3e092b5422L,0x77f55f7f9ca6338cL,0x6dadad8f6546d37aL, + 0x0ef4922ef3bf7cb1L,0xfcf41c23200ccc57L,0x591e208362aa0372L } }, + /* 32 << 147 */ + { { 0xa933aaf7a4886619L,0x9ec1915f4af13c7fL,0x25a9dff8854de496L, + 0xa8b31d9b247bec15L,0x468a25c84661e58dL,0x8989c046786a0707L }, + { 0x282db8cabb66922eL,0x73bf240d45ca29ffL,0xa2c40faaeaeda06eL, + 0x69632929add94b47L,0xc72354f6b0069076L,0x8d197fbf7878e92cL } }, + /* 33 << 147 */ + { { 0x7bd8195662267b63L,0x9352be73894a4ed8L,0x62568211d0bfdfdbL, + 0x7974999285698b05L,0x897ccd584412ea21L,0xe4cc4ddcb2f25225L }, + { 0x808539bdb4a1d924L,0x619fee34bdebf750L,0x47ed5b3473aea42aL, + 0x91e07a9b94ba376aL,0x218f6885edb27e08L,0x4feb09e6c4214344L } }, + /* 34 << 147 */ + { { 0x24bf9fbbf3e4bc93L,0x8973b72471151bfcL,0x8e33b753a85eb707L, + 0x13eba76e50adc461L,0xe445e8e144dd9d2fL,0x8729ec22b1592a0fL }, + { 0x9a13bf315ec24808L,0xe6ae840c2e95cabbL,0x634f3416e28cdf4aL, + 0x34d3349b9278cd7bL,0xd74990c542b912b5L,0xaf94b104b2430c71L } }, + /* 35 << 147 */ + { { 0x6d26cd01580b15a5L,0x5af25c06dcd849aaL,0x05b00800ffef39f8L, + 0x8cc59e06f9e0208bL,0x920f69540bc19bf9L,0xc06c4df97faa5ddeL }, + { 0x9a26a3f4770351d4L,0xda015bd3443f40d9L,0x1afd829c740f1942L, + 0xb108a8a6566e6158L,0x118e50a9a35e5d37L,0x94cac90eab72a3b3L } }, + /* 36 << 147 */ + { { 0x01f7968e60cb465cL,0x4efeffb796e0af3aL,0x6f9016e7066ad6aaL, + 0xa8ae30e88743aa97L,0x7b77d3e0b7d55766L,0xe1773661c6b3fadeL }, + { 0xa52fa7bc88f5270bL,0x4de08cb39f7f811cL,0x6021536f9bc34254L, + 0x47bd18cf4068e3d2L,0xc91bc312ce16889dL,0x468659ea929b71f5L } }, + /* 37 << 147 */ + { { 0xa5a2a3b3225b532aL,0x5ed77864167f7874L,0x2b5d475037ae42d7L, + 0x9bd62f14433b243fL,0xe8dca1b2eea90992L,0x1ce44e53ef5e0624L }, + { 0xd92c7bf61d3d7173L,0x83c1e65424c19a94L,0x59dce036eafe8941L, + 0x23478c50d81014b0L,0xb89214bbe65a18e9L,0xf9fd325ea05d9fb6L } }, + /* 38 << 147 */ + { { 0x2c4bbee73965ed81L,0x58b6a8766c1a47beL,0x7c8d94f71a67dfabL, + 0x865c9e42ac6ae9e4L,0xa63a0e42a3114c18L,0x7432c6c92bcf8169L }, + { 0x1927723c7532bd7aL,0x20b75c7201e5781eL,0x1963e16919d57f9cL, + 0x05427a3cb10e3798L,0x31bbc661cebc82a9L,0xdd88383ac3862997L } }, + /* 39 << 147 */ + { { 0xa0ef513d4adce457L,0x942aea7df9f906d8L,0xe52a2bb5fe22c5a3L, + 0xfd9fff1f8dec9ca1L,0x19b0e7a27913f99aL,0x58c45dd205660e97L }, + { 0x6722c47ff06d3c2dL,0xe4927a002a4d127fL,0xdc647c1ef40f46a1L, + 0x538c8cda7ab7a21bL,0x90227d6cc8015ae8L,0xe62f52dc2d4ec8a5L } }, + /* 40 << 147 */ + { { 0x69a9ebd8a83bbb88L,0xcbab0b5a29f98875L,0x325e487e4e7611f0L, + 0x90aa24b1d955cc3bL,0x840e70a13c264d53L,0x15bcf88bad7f4f81L }, + { 0xe47552cc2cf0df0aL,0xcb99973379205ea9L,0x25dc58bd10d5ca45L, + 0x0947d7151228b978L,0x9a0204da4f2c7c4aL,0x4377ea4a4690052cL } }, + /* 41 << 147 */ + { { 0x35da16d16bc7d7afL,0x098c4b0271de4ac2L,0xdaa2407c3655dd94L, + 0x5136884c90380d70L,0x3f47052e762f61abL,0xf715107a8dcd6ddfL }, + { 0x862a4a6e5d76615aL,0x2b546e1b2128a6f9L,0x5297a3cf40490672L, + 0xef2cbdf1b9c765a6L,0x52e71cb4426562baL,0x34d0e3237a84f9b1L } }, + /* 42 << 147 */ + { { 0x6cd4098d74e7c67bL,0x3bf4193123d2b418L,0x598710ad682135ccL, + 0x26ccbfe0172d648cL,0x0c4918c5d84dc9afL,0x346e8b6385065417L }, + { 0xcbc7f2efd353219fL,0x93637eea3c4e4863L,0xb18fc69c2dbbd39bL, + 0x20614dd45a4b5b0cL,0xcdac0383547adce3L,0xedcdd64842ac8be3L } }, + /* 43 << 147 */ + { { 0x76ac6c94b4559439L,0x09090af620319667L,0xef433d73a742e3beL, + 0xb7ec99eb7cbd7090L,0xcde2579dcb782be1L,0x2a2fb807e75552fcL }, + { 0x083f9e982f1eee15L,0xe20f65c167779c98L,0x73c044ff5f23e998L, + 0x5fce594269488208L,0x3e4ca86ccace7ba3L,0x5e3f43b8f32c1acaL } }, + /* 44 << 147 */ + { { 0x3ab171a237b42b60L,0x6501afcc4f20e50dL,0x4f9e22413e3a4298L, + 0x3c5834d9be3b3d3cL,0x9607b8cb9be25af0L,0xcc5f6b6f81c723a5L }, + { 0x11b9b5d199227bacL,0x2bc5dd9f322cc499L,0x0c3884a0cdbc3a55L, + 0x018a8ebefd4f004aL,0xa858ee7ce08741d9L,0xb5bbfa2b5d69b3ffL } }, + /* 45 << 147 */ + { { 0x57069b4a1b0611b3L,0x24b5421c89da55d7L,0x6433c29dcf9b2fb2L, + 0xda9382c67869a1cdL,0x67fbb7a343514903L,0xb3429e35e8b224f8L }, + { 0x4058ef1e7ac51191L,0x56283b0cfd4e6114L,0x4eff0caca16fadd1L, + 0xe6088db7b6ee634eL,0x94e68bd0ca7bd1b7L,0x0e98796b965ff86eL } }, + /* 46 << 147 */ + { { 0xf3176014bbd74a95L,0x5dfe36b51bc6c763L,0x4c463aa27d3d0366L, + 0xcbd7106cff3b113bL,0x2d660f5a0b6edee3L,0x92d79c864db04c30L }, + { 0xfd1067cfd2236e55L,0x1ae21f2d90925a83L,0x8419072ca952c451L, + 0x2f268b473d946980L,0x04831991b709ab5aL,0x0d622a70bf72efd6L } }, + /* 47 << 147 */ + { { 0xec468aecf0440b85L,0xaae6041369cea78eL,0x5a88145d12a30f40L, + 0x438c6e3f37a52bfcL,0x41bf603894749b6eL,0x3d38b86267edc2d1L }, + { 0xe379125a020a32abL,0x68a6b13a198c3944L,0xed1fb3258be252d2L, + 0x76dc8df6e15c37cfL,0x5a6592cb6453b542L,0x372b1998b3347c65L } }, + /* 48 << 147 */ + { { 0x015c325eb8e79179L,0xf4fc61335b57dce6L,0x27a51e5d78d6858fL, + 0x13babcab4dd5f180L,0xfaa19cb1847e499eL,0xe2688ae608aaea61L }, + { 0xe20d7edce86100d5L,0xa9b0d46bed2fedacL,0x5e99cc0c1d357dedL, + 0x4c1263ab723cac89L,0xad5f3e6ff15e22f4L,0xf25f3950d77dae65L } }, + /* 49 << 147 */ + { { 0xf3814fdba1c6fb06L,0xbfde395d8d71559aL,0x6e4b2b1c07e00f72L, + 0xac0d1aef1e12b111L,0xa4041ea0387dc52cL,0x8004ef4893c80d7dL }, + { 0xb311b5c29a770d6eL,0xd4a340bbaf41a540L,0xe96d1dbd9a5391ccL, + 0xcd4b19fb45ebf6ffL,0x142556a5dcb6dbe8L,0xf68968ff092f898aL } }, + /* 50 << 147 */ + { { 0x540a2e35c854356eL,0x6d0eab45f5002153L,0xb8f542bd9a6c488cL, + 0xd572d282c6201f12L,0x260bc62781a3eedaL,0x508621af06eaa5beL }, + { 0x754eeb205eadc8d5L,0xfe33248f42d4b0dbL,0xf44a1c7ac5529222L, + 0x9079ccb574396eeeL,0x6c4bc87db9cbdc41L,0x1ee8982431ee3f18L } }, + /* 51 << 147 */ + { { 0xb64fc90ed811f25aL,0x310214a2c82c8f68L,0xee559209b5052420L, + 0x6055c5b45c1bf95eL,0x414f7c8dedce3bc7L,0xd3438b8a66d3cfb4L }, + { 0x687b9f70d3935eeeL,0x553b15ddd3e179f1L,0xccc9961e21ff232bL, + 0x3729ac207d322041L,0xf1537630094907c9L,0x3e87f4f903153dccL } }, + /* 52 << 147 */ + { { 0x2c21e48c7dae4b17L,0xe842930a07ca1575L,0x3a3d6d361cc47ab4L, + 0x749dba405fcd07bcL,0x55a538a6f306a498L,0xe85c60be633d42bcL }, + { 0x777595f2dafa94a7L,0x1c690529a0400ef6L,0x41485f886bfa23bbL, + 0xdead14a1256d9204L,0x74f1a820bbda2f9fL,0xc86554f65fe54284L } }, + /* 53 << 147 */ + { { 0x03ee764b978ad2dbL,0xec253b0f01c9282dL,0x028e7873fb26c425L, + 0x3e1da0436504ba10L,0x68369881531961f1L,0x0365ea56ee435146L }, + { 0xf5505ae80c00a6b4L,0xc1ac097403f34fe3L,0x7327b391b5922f68L, + 0xe561cedd1845ef9bL,0xaa82258c6a44b29dL,0x23e39cedc4d56159L } }, + /* 54 << 147 */ + { { 0xf5a07dedd14a3ce3L,0xeda454ec9c47615fL,0x01d6b1562775730fL, + 0x3ec02f95fe4d93f4L,0x335806e4dcbd0ceaL,0x3f498d1b51a19d96L }, + { 0x9949c853374b7210L,0xb255d34b25980320L,0x3b681db4307b513eL, + 0x4137053add10a78aL,0xd9c0f2728dcaae0cL,0xcbeb6b7216031955L } }, + /* 55 << 147 */ + { { 0xd1b13e72c709af4cL,0xb4b99796c12f27fcL,0x9e56569a05e2c06eL, + 0xd8c880631212ba12L,0x8da1a6704e7f8fe4L,0x3bbb314f875bb39eL }, + { 0xc56ef7088fbc8a3fL,0x39b3cef2300d21bbL,0x5e755398458e347eL, + 0x9f7b84b16c1b2162L,0x278ffd26b08d0c52L,0x7c8a442a9ec7febfL } }, + /* 56 << 147 */ + { { 0x3c0e2b9737e8e6b2L,0xa2037913575da8b7L,0xeedf0a75b925cbb2L, + 0x4f28ec1bc561b405L,0x368fb2742901931cL,0x52b54eee2f26221fL }, + { 0x381845b6247812a9L,0xf9bcc9619115a0dfL,0xef127dfecb84d25bL, + 0x4256afe5fa10e0a7L,0x0c08a532353a15ebL,0xbbd15b176a91e61eL } }, + /* 57 << 147 */ + { { 0x3c573b2655574ae4L,0xd3f12e8f2c0be823L,0x5954b69fde9ce60eL, + 0xc433991bcedfd1eaL,0x35696716718e950bL,0xce4318664e9cc107L }, + { 0xee16b6347359991cL,0x8f05851b1818a113L,0x257a228c3b494b59L, + 0x4239f98e156f91f6L,0x2382157c72efdcc4L,0xc82b652cff7b7ac1L } }, + /* 58 << 147 */ + { { 0x072eee036b7a9a38L,0x42a680cbaef9b327L,0x67311eb8b56fb35eL, + 0xf320acf3c7de3776L,0x09c89cc3ed15e895L,0x368501713232345cL }, + { 0x5a5fe1104822f90eL,0x64f7ef18c6077b89L,0xbbc5748c8bdfb971L, + 0xdf5488334b6209deL,0x02268bf676e7f595L,0x1c7971b447779e75L } }, + /* 59 << 147 */ + { { 0x90d308b495c9497fL,0x277535b782c903f6L,0x443cd37fc5d7b4c3L, + 0x48ebf0acfcaff8a7L,0x8ee8c79e579f25f6L,0xb825ccd8360ffd90L }, + { 0x6327be1599fe4be2L,0xc94c68cf59ec2909L,0x0dbf8d4456660ce7L, + 0xbb31989b5d510edaL,0x43c8c365c4a2e601L,0x100de78314dcf793L } }, + /* 60 << 147 */ + { { 0x635ee0f3d33ac52aL,0x609c328dd1970e1aL,0xf28ddf0a09426902L, + 0x2a94d4decbbcbbe8L,0x15890cf4ab7ecf5cL,0xb14a405df2dd4135L }, + { 0x64659a4fa6d01554L,0x1d1b2c43cc966f9bL,0xb02ee871df0e48b3L, + 0x0bd13e47f4dc3ebaL,0xb4763547bb4fc529L,0x868650044068ab72L } }, + /* 61 << 147 */ + { { 0xe3d60dfac22bda56L,0x021411ba6be2f502L,0xc1dd4d55b35e750fL, + 0x708b62cd4d5e1648L,0x234a80c6347b8b8dL,0x53b6fa80f3ba912dL }, + { 0x4041b8007b92c92bL,0x636c12524b6dbceaL,0x4ea250d08a1aa141L, + 0x9ffa7e35a2ae7be0L,0x765c809cd2844e61L,0x5bcabd922d56de12L } }, + /* 62 << 147 */ + { { 0x48d594e522205fbdL,0x79c78f1c0862eb11L,0x02a3becdf7798099L, + 0xbfe574a8b1ef2ae5L,0x1bfb7779c4781f34L,0x7211dfcf044da23cL }, + { 0xe4c3fd7dc3686ef9L,0x14c6e5b5e74210f7L,0xc40a0a0275ab746fL, + 0xd2033594621f6369L,0x6bdbbe3d66241d44L,0x014b089ee47f00e9L } }, + /* 63 << 147 */ + { { 0x93e3a89108e65849L,0xf90a376ba1a712fcL,0x6555d6dff1a48fcdL, + 0x984ec5c86a763e90L,0x7a7fe565e55d6b14L,0x12550fe809b2e8b7L }, + { 0x21736c048e41210eL,0x72ae44d448ce08f6L,0x02755a2871fecc50L, + 0x379da24beb485ee5L,0x394cb7ba66d7b659L,0x49fc9d60ab638c33L } }, + /* 64 << 147 */ + { { 0x854b05846150771aL,0x35fdd9b4d9ca9868L,0xec8293894c32fc71L, + 0x882fad4c9ec8f90dL,0x2d39990dc6c7b9c0L,0x7fbc201bd71a25e5L }, + { 0x6b852e655166da7dL,0xc6bde23a3d8c6e36L,0x370011545857f048L, + 0x746621fc1ccb9bc8L,0x97e44e63612bb853L,0xabc3b450758da4edL } }, + /* 0 << 154 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 154 */ + { { 0xd25f650804926a41L,0x7236b475514045daL,0x0b36031108b9b08bL, + 0x16477aff3fe92e91L,0x6e5f6cb103189ddcL,0x81ff008ec698a38fL }, + { 0x02a09218c93adb23L,0x71fcecd3445d8faeL,0x55a15eac8fd6b76cL, + 0x1e37ec3611ef96b4L,0xd1b3b3fc30e433b5L,0x4951873351d174c3L } }, + /* 2 << 154 */ + { { 0x7914213db8c9f82eL,0x7a3e4e38fc038e90L,0x6edae5a126a34238L, + 0xe566bf50701ce8c7L,0x3562e87555656e02L,0x48325ebfb4e8efbfL }, + { 0x5f10a50466505ec3L,0xd8b9834b8da78aecL,0x49d1fc25cc2f2e40L, + 0xe973bb1caf5718c1L,0x9b8825dad2d6b890L,0x7de7885ee2f00f12L } }, + /* 3 << 154 */ + { { 0xfb0fa0e6494fe64fL,0x4ea468b59a907f37L,0x9bb6d672cbabb7ccL, + 0x523c7c6ea5be2b38L,0x4065adbb361c2e41L,0xffa1299925c13172L }, + { 0x0eb29793f80d5e2dL,0x862fe1ae8e4efeffL,0xd485483e948895c4L, + 0x513977300d80d5bfL,0xb4731ffc348782f2L,0x42543c76e1a7f6aaL } }, + /* 4 << 154 */ + { { 0xe37211be7ef79898L,0xa810387721344d16L,0xfdcd7e26a1b9f8b4L, + 0x5641e45d7d7f72d5L,0x5377c1bec449c920L,0xd3edcb0cefc7b2a1L }, + { 0xc657a9ffe14b42fcL,0xc8f858c800831b07L,0x6bfcd1bcd020eaa8L, + 0x17534b0a3f6860c7L,0x8ce5722284c7c806L,0xa1d40eaf2bd7456bL } }, + /* 5 << 154 */ + { { 0x28b88cbb1a7093caL,0x09275152080a85ebL,0x0bee7d979c1dcc32L, + 0x43698f5f5ed033a5L,0x4f142867b0f0acc1L,0x6e6202ecf62960deL }, + { 0xe95a607ff005b671L,0xfeee8ea060cae478L,0x456bb6e90e8ec6e5L, + 0xc1c0319a9d088a59L,0x29c6898bbe3d2379L,0xd7049b2af8a8628fL } }, + /* 6 << 154 */ + { { 0xe0c93007c9aa57eeL,0xebb2d47b8895a604L,0xb8aebc49c4fd6ffeL, + 0x2c06e1e573f300b6L,0xa019070d81628b8bL,0x2db1690bbaf8c1eaL }, + { 0xb3fce6c8cc94ccd2L,0xf301463885bcdf4fL,0xb1e62616e2f82c32L, + 0x85581e2468295a54L,0x0f2e2ff5bf51f8faL,0x940716f1155c1f6fL } }, + /* 7 << 154 */ + { { 0x15b2dd270c6bd5f1L,0x07b5bd91eb086d0eL,0xe701742e97c5f5caL, + 0x3ce5f3f6eea06ea6L,0x51a81a6aa9cee784L,0x2bd404c1c7182fa7L }, + { 0x27deca74d5b8bde4L,0x2c1931c595385e4aL,0x04fcb34e3a79d65fL, + 0xdf3357edad1babceL,0x8bc628ffa31af476L,0x42ce1d91e5cc9e78L } }, + /* 8 << 154 */ + { { 0xaed02b6b4e623856L,0x7a6d2bef3e1d74cbL,0x82226ec4654e7c30L, + 0x008ac003e7034bfdL,0xe343c5407fd6b555L,0xca1b29071b429d44L }, + { 0xe0702a339c3ceea2L,0x48079aa9732694c3L,0x7e6d72f6d4652401L, + 0xd92655ed35f60043L,0xa0dbaac6273e8cc4L,0x0bb8f0f93c3ffb40L } }, + /* 9 << 154 */ + { { 0xc3134781a91940b2L,0x37579fc9e9b90620L,0xa506227a08acd6f1L, + 0x603ecce0270da73cL,0x8a53b67d7fdd70cfL,0xe29b7df299640bd6L }, + { 0x7bb4fa877569105dL,0x6ee80ae8567bb5e9L,0xf394bd02baccabefL, + 0xe854b3a6309c944fL,0x1271a131f06246e9L,0xbc1c205531580147L } }, + /* 10 << 154 */ + { { 0xb41b87b6c95cd23bL,0xb99714ba55e371a4L,0xb138ee8f6f571cebL, + 0x09c42be480146ec7L,0x275ee21eee9aa125L,0x0cef4d6f3a878b59L }, + { 0xd436eb1ca801068dL,0xe2c5448c762b8a80L,0x243beee1f3640ecaL, + 0xf979458b32bbba7aL,0x6bc26cfea63407d3L,0xd3b6e132392dd1d3L } }, + /* 11 << 154 */ + { { 0x123ae65005d0072fL,0x9f101624f0656bbeL,0x762bd4f4344e283fL, + 0xd1f70d5161b6863bL,0xcd99382592ef9a38L,0x53aaa0c3ac2bf9bbL }, + { 0x13904fb521ef9a43L,0x0470a8ba2beb8f44L,0xf3733943fcfe9ecdL, + 0x10b8881a79d776dcL,0x89b94c67b82b7139L,0x7af5147aeb962922L } }, + /* 12 << 154 */ + { { 0xbc06ecab3de4ba2eL,0xf51ca0639e491bcdL,0xa6fc6fa0453c94beL, + 0x5460f943ed1a6731L,0xeb11656a4ec3f1fbL,0x2fcb2cabff1e7d4eL }, + { 0x595264678fea2286L,0x838117a34e0bee38L,0x7bdf588824fd2ce5L, + 0x13df0c839f2c2925L,0x1bf621e6dee97f30L,0xb43b2558ebea6641L } }, + /* 13 << 154 */ + { { 0xf49a97d80a33b97cL,0x4e68d71512ab9bcaL,0xc0d361c04bdb65a3L, + 0x5fba9fb86cfb0cafL,0x222e12ca2a716589L,0xaea01502731f5099L }, + { 0xf322ddf7e97b37f1L,0x050e82a5e55c844dL,0x01ef972ba11d664bL, + 0xab30502882c737b6L,0x43aa811185e39769L,0x766a9350937c1456L } }, + /* 14 << 154 */ + { { 0x246c86608e729329L,0x39fcc41dd693dac8L,0x48a65b54c062a6c0L, + 0x368a57706a5a3101L,0xd143600f47ed1988L,0x48466d92a764ce3dL }, + { 0xb05006135a22cb6bL,0xf1d77247edea070cL,0xb1ddd151617f2464L, + 0x7905069828b83fd9L,0x021abb26d70bf93eL,0x590b3c42ab5a5e1eL } }, + /* 15 << 154 */ + { { 0xe86c737b728b8438L,0x21f45a22acf1dd66L,0x6f29f2d7abd4de3cL, + 0xa223154576d4435eL,0xad902927f5fcafadL,0x272cceeb04f30557L }, + { 0xc2e4e0017ebbb2d6L,0x73954580bb873ec3L,0xadf5ec7ac7fa9088L, + 0xc036da0464006dd7L,0x9c3545b5e8274f69L,0x6e153c2552325f50L } }, + /* 16 << 154 */ + { { 0x5906a35c1cfb991fL,0xb62a4f80740a7744L,0x65c8ac9136f84763L, + 0xf73b3debbe0f1dd3L,0x40358868a2d26c21L,0xd907e90a76792ae7L }, + { 0x3ecea167668c3d5fL,0x731068f26754b49cL,0x6db891090e006243L, + 0xd29106e6dd94681bL,0xb40b8694a85a3de2L,0xc80c7bf1936b86ccL } }, + /* 17 << 154 */ + { { 0xd735de6b91f7c76aL,0xd89aa1d4b054837aL,0x47c1a397271e94c4L, + 0x8d91f3f9dcb7c071L,0x4cf9be2db4cc209dL,0x4fb6842ec08190d4L }, + { 0x926423a1d7b2aaedL,0x5bbfc08957a1cb44L,0x44438c56021defb3L, + 0x8b9a2b1ba09863cfL,0xc9d5c170e37e339fL,0xa8994d5dabb18c7aL } }, + /* 18 << 154 */ + { { 0x003d45d011913575L,0x866cb2dd87e1186bL,0x692f630146b69a22L, + 0xd296a55c8174c1d1L,0x77ef6fbe9f17af00L,0x6b588be93aa922e1L }, + { 0x99ecb44f033e6dd7L,0x32edea2c1d22b7cdL,0x3122b027ba7006f3L, + 0x8950054bbb6ebc5cL,0x4f6d606182dab805L,0xc12055181bae5f1bL } }, + /* 19 << 154 */ + { { 0xeca71515ad7edd2dL,0x3f9c330e9bf56567L,0xd0b62d6749104bb1L, + 0xde92596410cc8d89L,0xc7a083f4287fc898L,0x8ba176e712d15d2bL }, + { 0x2cee62f7b4c8c4c1L,0xc15966c2ef79aeb2L,0x9b449522427c11a6L, + 0xcc850028eb49b2fcL,0x0966a06d3a22720dL,0xfd511944a1e78c8dL } }, + /* 20 << 154 */ + { { 0x28d33e79e08c180fL,0x768c7794f6aec9ceL,0x5a749f3bce683c5bL, + 0x717629d98371fe75L,0x5e828fc057712c1dL,0xb46c6ed17e4c61aaL }, + { 0x5d927bad5bccf95cL,0x55d6fc80d72f68ecL,0x560a99a398591dc2L, + 0xc885fe8a4836664cL,0xd18acd4226d79298L,0x05e4cd17185df1d7L } }, + /* 21 << 154 */ + { { 0x9c1e5db3ab34fbbeL,0x0d4b1e742f7eaa94L,0x106b0b5c86de1289L, + 0xd2c6c1aab691a830L,0x2e55cff9b9717593L,0x4522b37d075e5e95L }, + { 0xc6ee67ea3abfeb96L,0x35844bbd890b04eaL,0x0246545a55d6f65bL, + 0xc66bad2b13594e25L,0xaff4c6b35d6aa7d1L,0xebb7d2b5a3f42a84L } }, + /* 22 << 154 */ + { { 0xebc60e21fcc83355L,0xc94dbc02d9119b77L,0xceb05a312f18ae9aL, + 0xa8462962b8f69016L,0x58dde5a48f67b5f4L,0xb8bdf9c9af3c234dL }, + { 0xe95c069f80e85df8L,0x9d525e1bab3aa0e5L,0x73c8a92f76276d8bL, + 0x7feb4abd163530efL,0x8ca949b35ef5ad73L,0xe129431e2e3d057bL } }, + /* 23 << 154 */ + { { 0xa263d726c129d188L,0x89da948e9d526adbL,0xc7319a5a6b8a9149L, + 0xd85d382d8816f421L,0xfad69eb1844032eaL,0xf668901a4233122fL }, + { 0x246cc0de210ddea0L,0x26d8ccb70bc07dbaL,0xfc1b558470e6708cL, + 0x853802b775fa0b44L,0x215ccb88bb75a5b2L,0xff50f0cf24e60054L } }, + /* 24 << 154 */ + { { 0x9d8a925b60dec308L,0xb72e3efa6b3ea363L,0x4f53ca6ddfb534b8L, + 0x4e64874c6dd78a32L,0x336e5b46c2a146d5L,0x07c76d6398395201L }, + { 0xa4c095228fe3e815L,0x887e659d3221cc26L,0x0ff92f64c36286ecL, + 0x57b1b903c3ebb08cL,0xc6bdc9b665f00c30L,0x826242269a46d36eL } }, + /* 25 << 154 */ + { { 0xe054597768bbf4f6L,0x17bb77edb6e2cc19L,0x0cc551d89ae950f7L, + 0x3490778d761763a4L,0x1c36044a32647ceeL,0xa6e083223f9d2938L }, + { 0xea392a153a656a51L,0x4d51161ba083cb54L,0x15c01e792c690757L, + 0xc7bf5d7c5cc62636L,0x1b00cddab2ccd76aL,0x68f49fa995313f8cL } }, + /* 26 << 154 */ + { { 0xc782c16c1a0b619aL,0x8643d42bbe316086L,0x49d2966bc0daa421L, + 0x080b1cafb7b487e0L,0x1d33bb53144de273L,0x8bafce2d6faf7ed9L }, + { 0xdafbe3cf408d4636L,0xf10527df7ee8835bL,0xe1123f3ee2e75522L, + 0xb388c64bebe27d60L,0x2cb38dc1e3f1f55eL,0x57ff8e43e34524d8L } }, + /* 27 << 154 */ + { { 0x557dc1cbea28398bL,0x34d5709a208996b9L,0x94470993e97a3306L, + 0x0343320772b117f3L,0x66c4e442f056525fL,0x27753c526d11dd35L }, + { 0xf0aa7658b26a70d7L,0x95608b19543cd7ebL,0x618b2e17bac19156L, + 0xe7e42948cae64ba1L,0x2016a9d59657ec93L,0xa38f67e03d7ea46cL } }, + /* 28 << 154 */ + { { 0xd67dc92b85653dc8L,0x8e0970af0bc93ab9L,0xb6f09baa8b87c0afL, + 0x5a8a903052760ef4L,0x2e2ae7561047bf85L,0xd049078f85bd4e74L }, + { 0xced11ff83729f708L,0xdd21cbebd91068a6L,0x83d488ff24b3e911L, + 0x6e166fda1afd2196L,0x66a912114f0d2128L,0xd11078ed05c9f39cL } }, + /* 29 << 154 */ + { { 0x69aef6f919c64bddL,0xe7d4f909598ab592L,0x48952e280e55124fL, + 0x637693f6290b558bL,0x3afb2e7b421e60e9L,0x00d1dbac79aac8a9L }, + { 0x45156c5cc08563d5L,0x8cc201be4519c881L,0x2e36c0d7bd616581L, + 0x595fe0164ee16dffL,0xeebec40ae4889c65L,0x23b6dfd7d35b94e7L } }, + /* 30 << 154 */ + { { 0xd87003d3bdbdf0cfL,0xe9750b5b56c298f1L,0xc256c3a2b73ad05dL, + 0xe0779a192ee94279L,0x31d8b3c6279626a3L,0x469056bb90163bc8L }, + { 0xe6aeabc623755853L,0x9fffdfe2896a6f4cL,0x15c1ce78a36cf41bL, + 0xd4c8c025eee41941L,0xf7a917ee7653be9dL,0xfa3cba9659d52222L } }, + /* 31 << 154 */ + { { 0xa02f08586d8c610fL,0x9819c563ad4af3cfL,0x085d4439b95d17eaL, + 0x9df256ea616f532aL,0x5e9c5419cebd249cL,0xdd5ffbf451062a22L }, + { 0xb8910ea5c8b33577L,0x5e8b7ff7ff8e63d7L,0x5e4f3926b24e230dL, + 0x163eb51eacd851d7L,0x9bda95f2ea2aef8eL,0x3d6887755aefa290L } }, + /* 32 << 154 */ + { { 0x913f92075f8ab132L,0xd5b6792c5c14080fL,0xefab4e2c787c3594L, + 0xa55d465fe7b7b7ddL,0x921aaad834e28e6aL,0xc4f3a35e12d6a7bcL }, + { 0x109803c46115a5aeL,0xc023098ce709f9a1L,0x1a8c8bdb99c5bb66L, + 0x1cd1c2b6bc7c2da7L,0x50189c975f927eefL,0x493823d1229f9410L } }, + /* 33 << 154 */ + { { 0x34ec4dc840dedfb0L,0x1109ddb93aa89063L,0x93d9db278c218bb9L, + 0x07131b6e0b6007ddL,0xf90570ddcc4690f0L,0xa6a9a634afa26a59L }, + { 0xbd0c25194292e2b7L,0x92b99706a6d44b7eL,0x89481adf4942c03bL, + 0xff5e56b98a0c30d5L,0xdfd8939591c80fafL,0xed9d140840663594L } }, + /* 34 << 154 */ + { { 0xcc22db55c41e42fcL,0xc90ec77e4c9f2411L,0x419b9f46e4c02557L, + 0x156ed30ccee45c60L,0xf2c1340a72e4a938L,0x4a9cda8a204775a8L }, + { 0x900fd58713952b75L,0xa82ec2b812461145L,0x9f1875d41db68028L, + 0xaaa6af31308475acL,0xa11f379442d4b884L,0x1f1fcbe3d087882aL } }, + /* 35 << 154 */ + { { 0xa32d5a80a292fbecL,0xe0b10099d7091eabL,0xcb99bf7b4bfe6956L, + 0xfd806d4c61955461L,0x7124b1bf931066fdL,0x29fad019649ccbf7L }, + { 0xd1fe7911049609e7L,0xb568e167592f93c1L,0xabe7d10398ba066cL, + 0x0cd22c9668d7ac2cL,0x0ccd0c21427522d3L,0x97ba199ba503b4a4L } }, + /* 36 << 154 */ + { { 0xa0f2da0c78a2cbf7L,0xd1611acbd163d80dL,0x1af6ee1bf2cd3795L, + 0xc4993e08307d6105L,0x84c3b8f8560b5f12L,0x4f52c56347869733L }, + { 0x8fd9e3f728d28bc6L,0xdbf34576e5d44bd9L,0xf7e3a6da10d14cb5L, + 0xb93870990fe051ffL,0xf6363a48f15d43d5L,0x4bc358fcf434d1acL } }, + /* 37 << 154 */ + { { 0x35bac9471eae6dacL,0x4244697e39d6fe97L,0x16ec7f64fe017230L, + 0x393856d10493823cL,0x0782fbb55b7cbbfeL,0x4c399e3f5820f9f9L }, + { 0x86311cd9c08fe816L,0x057d4cbbc3ac958bL,0x63f09d484bdb0531L, + 0xab0b582b0b89ea02L,0x19c52243beb30331L,0xafa64f25ca87ff6dL } }, + /* 38 << 154 */ + { { 0x0d28a67859b1f4aaL,0x79b04589c52d40f4L,0x443b7fa5219303d9L, + 0x5be78d9663972eceL,0x0ccb969e7d984869L,0x7d8738077f81916fL }, + { 0x3502b3e426d9f292L,0xda1de7a82c90b612L,0x5605f5dc434f27c0L, + 0xa50d3328df89c616L,0x5a80cf84e7082731L,0x2c89e4b6f7ce953aL } }, + /* 39 << 154 */ + { { 0x7a46cd0d01fdf1e6L,0x86868e74e8690fbeL,0xf038771d8a8fc3b2L, + 0x30135b3084303d90L,0xa7ecb9ded562d20bL,0x7a6d1f37884cd233L }, + { 0xa30ca0bb07dfad3bL,0x1690d6018e09fa7fL,0xe582449f6c744551L, + 0x0b0030a21b935d17L,0x6b46681272bdb78cL,0xe40d4e5f56d4f328L } }, + /* 40 << 154 */ + { { 0xa29978fc62a8b8b4L,0x4cc216310fa130a9L,0xe4b51c6bf15e04c8L, + 0x453cf4d23f815420L,0x1257c751c6282b9dL,0xcd15b03c8af1af36L }, + { 0xe3596240514ef6e8L,0x72a6691708ab83d9L,0xca0a62d710e44b2dL, + 0xcde068128a9b8a8dL,0xd492b261ba470875L,0x5c7ea67cc6d7aeb8L } }, + /* 41 << 154 */ + { { 0x6acd945fc0995487L,0x06d5b2e47abac4fbL,0x42cddd75aaf3d12bL, + 0xca7d2363de1b9632L,0xbb1a1990dfbbb30fL,0xb0beb43139fd7bd4L }, + { 0x9ceb36884fa796e7L,0xb4d2bc4ba3266ab8L,0x79bda9d6e02df012L, + 0x414636bbf6faf7c4L,0x0a6603b9d1ab23f9L,0x2bc60c848db14f7bL } }, + /* 42 << 154 */ + { { 0x1b36ef27007ff90fL,0x394fe8095111399dL,0xaf4f246cb758e748L, + 0x794e4b151a7139a2L,0x40869a49eb527db3L,0xf2e15106f46d1b34L }, + { 0x46619f0352ac96e6L,0x40f556de49caf0c4L,0xa36b11d693072befL, + 0x871919b4ab2dad50L,0xf44b8084792dcefdL,0xe051823dbc31b021L } }, + /* 43 << 154 */ + { { 0x56293d8dcfd7432bL,0xdedf8dfd1d5f72c4L,0x743f4a71ae604fb4L, + 0xfb35ab43730caf7fL,0xcaacce6b20fc2167L,0x21ec3a0daa8ac71aL }, + { 0x4fdf5890c21ac9baL,0xbdc41ecfd6149328L,0xb1ac4d519b381c55L, + 0xc4cc08fd63f10a98L,0x2b9f0d3a4913a671L,0x9ce9949cbc36a952L } }, + /* 44 << 154 */ + { { 0x5049a7d3f758b1b2L,0x60beb74f14ab97b8L,0xdfc47828a9ff8ad3L, + 0x303a0cde8bb99766L,0x53f4b45a43b9a7a6L,0xe467aec8ca6e8c43L }, + { 0xb8e7db7b3f573855L,0x5fee5a5481e760f1L,0xe928b23385b0fed4L, + 0x72f02728ebae0b7cL,0xe32abf70bb5897d3L,0x103e8b859c572995L } }, + /* 45 << 154 */ + { { 0xf321278c2dc1a02cL,0x06ca03865dd09f91L,0x3c28640b7bac9e7aL, + 0xe3a7f9b527b1a011L,0x9137ad0407ccedd3L,0x3a2976a8cb6b447aL }, + { 0xab1c39248225c1ecL,0x30703f108f9022a8L,0x212f0f1bb0b2a64bL, + 0x76ad924b3e73862fL,0x47253a5c84842ac8L,0x33a03a17755af95eL } }, + /* 46 << 154 */ + { { 0x97c371fc5a274b61L,0xc7362cdbb14c680bL,0xa8cdd929efbd49afL, + 0xdfb2d5f075325f06L,0xf62d10e2b905531bL,0xbdfbfd8462ed0c3aL }, + { 0x252061599d07d2daL,0x1376775152491224L,0x165637057413313cL, + 0x642a7911a2b88eb1L,0x42d9dc6806ffe363L,0xe81d3403017bcc9fL } }, + /* 47 << 154 */ + { { 0xa68ce9db93d57f06L,0x4d1fa86a31dba07dL,0xf11603178c4822abL, + 0xc2243680633c26f5L,0x6b4e91cd10f1da80L,0x4358155734827d78L }, + { 0xbf54e87400c19817L,0xf52b94c4f2bad957L,0xcc85de8144e71756L, + 0x4f7d8ca365b7a8c2L,0xff76efa579d7c36eL,0x50a444025952932aL } }, + /* 48 << 154 */ + { { 0x87c0ef84172784bdL,0x023128267a5f2d07L,0xeae5c0cec9901fa3L, + 0x6ea74133a11144e5L,0x740c3d2ed8e89beeL,0x88e06131f9bb1801L }, + { 0x47f253754356fd51L,0x8e2ca6ce38e45ea1L,0xf0afe990c2ef8066L, + 0x91b7263d8ea03d0fL,0x37b01664880ca591L,0x61306f09790c8ed7L } }, + /* 49 << 154 */ + { { 0x084c4f92b24a5736L,0xf3d01da90a3c3859L,0xd37c47ed7468b812L, + 0xeb539a939567c798L,0xd852f502acfdc072L,0xd8e5454996245975L }, + { 0x42ec3948db5e323dL,0xdbebd1c7002d3fadL,0x9cc5db55d7c62d0aL, + 0x22af02388afa4c07L,0xbdcb68fc6979eb74L,0x33763dd544dc11baL } }, + /* 50 << 154 */ + { { 0x4734465f87c2e496L,0xbafe4fb4eb7d82c4L,0x940b168521837f17L, + 0x790d7041345a66c3L,0xe9973cfd65ea596cL,0x45fc95df058b3350L }, + { 0xc63bf91405d08638L,0x36e6af6476465a92L,0x7fe09193f1eb3701L, + 0x364f64f06468e2aaL,0x83108431f7129cc9L,0x3ac117205606bf94L } }, + /* 51 << 154 */ + { { 0xe6a85c7d34dcecd9L,0xc14437fe338cdc1aL,0xa5eeb471b3a9233eL, + 0xf230947c71349a62L,0xe704a95686308ebbL,0x0ef4d4da4a362a8dL }, + { 0xae9be4394b634c67L,0xf736c07c569f0039L,0x7356f3010f5f07d9L, + 0xc86c4000823c9cecL,0xc43b3489951ab5faL,0xa7a3b3a6b46bb659L } }, + /* 52 << 154 */ + { { 0xb1d6cb737337af87L,0x09a59a6908638c3cL,0x4ecc3fd25d94c727L, + 0xa7b57269e274ba87L,0x909cd824a61a0590L,0xcbe63cfe3c11751dL }, + { 0x9574de8347c46efaL,0xee334cda539b7e03L,0x245bc6a2e3ef3599L, + 0x13a570fee88d0da7L,0x88ede26d90ef4a21L,0xa0c5953b01fccebcL } }, + /* 53 << 154 */ + { { 0x855ff0f7657121c2L,0x18754814f94c7402L,0x720f1e3c32ce8340L, + 0x7ecd080ee8e49d3dL,0x2838e642f0bee412L,0x69cad618209f8e60L }, + { 0x5730f2dba983a4cbL,0x74957697f43896a1L,0x68de04373dc55d4aL, + 0xa2fbb915628698bbL,0xc8279c975cace19dL,0x7df557465fd52bc0L } }, + /* 54 << 154 */ + { { 0x1cb1c2f378c3f521L,0xa425f99b63116c7dL,0xc86b48c36f7c0e71L, + 0x9e92e82dc76a73ddL,0x8c0414657e7d6df8L,0x99e7884d38c02d8eL }, + { 0x6c53c0cfb78a7e50L,0xcbcb5114481d60ebL,0x1eed68ed035b4441L, + 0xdc95269f755f18efL,0x3ad7f32a3fe51f12L,0x981782d017296245L } }, + /* 55 << 154 */ + { { 0x7743ef2655fcd15eL,0xa73944a4d07f3cc0L,0x3161d6a32438cf14L, + 0xad193a9b14e8938aL,0xe1de190e872dac01L,0xb165da2fc4795b10L }, + { 0x1eb89d519e155bfeL,0xc8b97d94c9c552d5L,0xea7d3edb108c4c82L, + 0xafb60b29c10acbb5L,0x331b316b82c7b642L,0xa53c4b3d719fa342L } }, + /* 56 << 154 */ + { { 0xc8dc34f36b3bcbdfL,0x952d337b24d72806L,0x28b8ec817e56e8c8L, + 0x98e78abdbe861aebL,0x521773ddcf3bd040L,0x582ffcb2b7ca45d2L }, + { 0x70962c0a04202ac8L,0x31b6ac909f29381fL,0x3b4cd403355715a7L, + 0xffbbd1a7399a071cL,0xac669b08e50f02d7L,0x0f568c89b2cf0565L } }, + /* 57 << 154 */ + { { 0x2d2afc2daae7e637L,0x840e47c782a818efL,0xfe26a67c879f2451L, + 0xd41d289810f54247L,0x36040f4877119f14L,0x741859a983f240ccL }, + { 0x15f9607a8fa720c8L,0x8eb70f6df7b8e32dL,0x755394229b98d670L, + 0x80a4a127750c4e62L,0xbe88d03195ca3a50L,0xfadeb53dc6411eb6L } }, + /* 58 << 154 */ + { { 0x19f29da06b824028L,0xa5cfd12b7bd354a7L,0x1cb5d74caeb59b3aL, + 0xec9a8ccc47211999L,0xd7f2a1c17852f167L,0x134629209a1859cdL }, + { 0xdd65f7ac9e3a339fL,0xccaa968075437831L,0x25772f9b7f502bb0L, + 0xa64cd12f6fa0aa66L,0xd2f46ac62af2c3d4L,0x58433d963f262a2fL } }, + /* 59 << 154 */ + { { 0x747757c6715ba7e6L,0xc01b73c1f9cbefd2L,0xf1d96de501bbc017L, + 0xad554e91a1087f55L,0xd9b74be65a6cc716L,0xad2f2c0320317019L }, + { 0x42ef19c207893532L,0x7f3624c40858fdc1L,0xc104bde7078936c6L, + 0x99af706682b5f95eL,0xa40e02625a13a9a0L,0x6c0251c40a318574L } }, + /* 60 << 154 */ + { { 0xedb3abb1fe36eed2L,0xbb2cc1e6a038298aL,0xfa0ac06fe5adc3beL, + 0x7cbcef3eae73ebe1L,0x41596590cd676b87L,0x6cc8c0ae214391d7L }, + { 0x826e2e16fcb3f244L,0x1ed7837e1be22058L,0x83052d0d1a9912b3L, + 0xa2cb410c8ac3dbf5L,0x279d555a7faa6bc7L,0x870e7132f52b439cL } }, + /* 61 << 154 */ + { { 0x5957428e385308d3L,0x49ba20b3bfdae187L,0x4e1281c3adb44defL, + 0xebe93dc4e75c6cf9L,0x81d1d1cff675fc6eL,0xbe01bcecfe0e371cL }, + { 0x713f294d336bc7caL,0x1beb1508e26a1903L,0xbb5feab4b6819961L, + 0x28bede2741bfc7efL,0xb0a5108bb3365719L,0x81a8c9255ccd21a3L } }, + /* 62 << 154 */ + { { 0x4f3d90af2bea6870L,0xfebb0de2ca26ca46L,0x109d96e5d58bd9d2L, + 0x4b42928cd9882c8aL,0x5238cb7a8c73adcaL,0x9d79d72a4adfc913L }, + { 0xba58929d1f0bf201L,0x0b7790a505f52baeL,0x361949aae45fda0bL, + 0x21b2d006af3f732cL,0x1ed05dc33aa84bf8L,0x2322b7f72405980cL } }, + /* 63 << 154 */ + { { 0x4a38b5b2c7151e42L,0x1d5dd94894550168L,0xf2adeb5b7b3d1d93L, + 0xe15c42fa36661a89L,0x7d55a3f27a3aee90L,0xbe1b5c39d9d350a4L }, + { 0x9c4d6fa2610f16b8L,0x7b96051da60fb18eL,0x539762fa496c018bL, + 0x048ffa39168a8f22L,0x33486ccada1c0a58L,0xe216d6be9fd687a1L } }, + /* 64 << 154 */ + { { 0x11a8fde5f0ce2df4L,0xbc70ca3efa8d26dfL,0x6818c275c74dfe82L, + 0x2b0294ac38373a50L,0x584c4061e8e5f88fL,0x1c05c1ca7342383aL }, + { 0x263895b3911430ecL,0xef9b0032a5171453L,0x144359da84da7f0cL, + 0x76e3095a924a09f2L,0x612986e3d69ad835L,0x70e03ada392122afL } }, + /* 0 << 161 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 161 */ + { { 0x3ee0a31c6754f492L,0x02636c6b96769ff5L,0x90a64f4ff0fbfa96L, + 0x513f054efafea65aL,0x796ba7479cf4b9f9L,0x3198c068932a9590L }, + { 0x93af8a65549ee095L,0xb8b6f72ca212760fL,0x23bc71e9c1a46c8fL, + 0x000643af4c9bca72L,0xb6d967c7848cea30L,0xe06b6b4e73312ec2L } }, + /* 2 << 161 */ + { { 0x52ec99561d85a725L,0x0f9be000f3208012L,0xe881337c6dcc7816L, + 0xe4e7b6d9791f7cf1L,0xfaa717aa59885a42L,0xb1bbb5c7f9c01e41L }, + { 0xcf208d58a0361880L,0x24426e4020afa350L,0x7261871b264ce04aL, + 0x66be4a86cd42026aL,0xc5397b77829f99feL,0xffe4a6bc24578e2bL } }, + /* 3 << 161 */ + { { 0x0733667af822d5f9L,0xd7f81b9e18339700L,0x7ca29b27a7bc265fL, + 0x9fefa698eb4f0c7aL,0x7b6f351301f27630L,0x72f0f152fcfb1133L }, + { 0x9928d9d05c81eb14L,0xa16ac36bed8ff6cbL,0x7fbd1acbe041bef3L, + 0x7d25159af8d99854L,0x2ec3a7d8db5a0dc5L,0xd86fc4cc87e3e933L } }, + /* 4 << 161 */ + { { 0xba8418f34c20e15fL,0x7eed2494fb54404eL,0x4e6438d7bce1e82dL, + 0x9e489b3eb397915bL,0xa9baea9ffb4cf659L,0x8bc5b2ba42ef4affL }, + { 0xae3fb5337e62a188L,0xcd648493496e8e35L,0x89728e28defe047bL, + 0x63a8c679d24e60feL,0xadacbf92470f710cL,0xd470aeb95e198d3cL } }, + /* 5 << 161 */ + { { 0x8e3807dd7a3e874aL,0xc4edb45b89ac3a99L,0x9ba9cdaf4bfd77d2L, + 0x31d33f59b540fffcL,0x404c87790c60028bL,0x7f89da7189688c81L }, + { 0xdd3390e5504b862bL,0xdf1e721be937efe3L,0x5833d0df63e6036fL, + 0x7712527a385fbab4L,0x6347236bd210c0d4L,0x12d7733c8d238e2dL } }, + /* 6 << 161 */ + { { 0x0ecb0723302e943fL,0xd180ca1e4a443e78L,0x39e7891123dd2c9eL, + 0xfa2a440401fe50bbL,0x4678e7ed154d39d1L,0x64ddaee1af513e01L }, + { 0x6d4c615a634904daL,0x937c6326ba5c900cL,0x70658f5feb6c8582L, + 0x2a04fd51f3d65166L,0xcefe7472b676eb47L,0xd3565a71f597d887L } }, + /* 7 << 161 */ + { { 0x299520f4e5dcba80L,0x522ad4b52b758045L,0x54eabe27193b36d4L, + 0xda4d3bff45e9e442L,0x44cb9252637311f3L,0x4cd620a971338ebfL }, + { 0xec908157cc9524fbL,0x2731a11ba8c955d7L,0x72a5e0545cb94009L, + 0x7eee8f3b9126cfe8L,0xc71e29203dd5d5ceL,0xe886f91a22069494L } }, + /* 8 << 161 */ + { { 0x294d29550db962c0L,0xd6994ef46d523ab0L,0xfa1a7f9158f95037L, + 0xb137981164420c94L,0x2b686e1e093caea8L,0xdef10944f9e1c340L }, + { 0xcd1beecf611d9bf5L,0x34696c50a1b5267bL,0xcecbc7192dfc2b16L, + 0x2cdb955dcee7e854L,0x9fefc321f2635cc8L,0x276d2e4f2936f7d3L } }, + /* 9 << 161 */ + { { 0xa9de8b87d38e86b2L,0xe0c2f232780d2fb9L,0x742d7fe9449e78b1L, + 0xc6946b7ef29efe3bL,0xbd59bcf985de7456L,0xb070ebfadb492e64L }, + { 0x5cda7ac8a0ff7c15L,0x6e0c0062c4f435c9L,0x4d8e5395974d4be8L, + 0xa0a0c5984e6d1681L,0x5debadbea14cbda0L,0xe176a772ae30b167L } }, + /* 10 << 161 */ + { { 0x25df81bce7b19019L,0x3058081aa6f45519L,0xccafbccabb3de1d7L, + 0x2b794710c515b1b0L,0x74b81bf87168d9ddL,0x92d5e462ec00571eL }, + { 0x865e29efdc670943L,0x2350537c7f6299c0L,0x9fdf787ea947c6f8L, + 0x9601cb21cabe0f8bL,0x2899d5f49313b000L,0x4873bc9f66a9e8e2L } }, + /* 11 << 161 */ + { { 0x2829add72f163a26L,0xf96dd91156909488L,0xc16d185f769ccb59L, + 0x13c4b566e9c6da4fL,0xfd68110bc423ac34L,0x64911819cfaa9fb6L }, + { 0xad7c7d2b12dd07e5L,0xbf7eea90abc19a50L,0x1db70ed108d6c57aL, + 0x01da2b41446deeabL,0x163a5a5fa4f6a367L,0xca9f4bcca10c8a53L } }, + /* 12 << 161 */ + { { 0x2132c32e68206a00L,0x20bc1bb483bab6d9L,0x99fa3be2bc4ef156L, + 0xe515cd05ebbd6c33L,0x9c06d7670d2c8ebcL,0x2fa7f3b68a79c884L }, + { 0xa4dad16a9137df25L,0xc4da20f833598c21L,0x32f5d9e3867cb117L, + 0x8f00fb54da7cf533L,0x428cf9e3870ef3b4L,0xa8b6c754521b8428L } }, + /* 13 << 161 */ + { { 0xe9b297be7be5e610L,0xd09f63c304b49303L,0x9110a9b381ebb814L, + 0xc32af8986bf19586L,0x5c4939571da2280fL,0x89e85cb41becc5f5L }, + { 0x1068cb528f1a396eL,0x49dde483440a6144L,0x51280400b5d6aaf0L, + 0x0e8ac4a53e8ea21aL,0x32f4a91d92582420L,0x5eb09649bc35e408L } }, + /* 14 << 161 */ + { { 0xea3a2f0c32f235f8L,0x8281bfe5bf4a8256L,0xf44e1319577b9e1fL, + 0x31732d1bab2d9ac7L,0x6e7682eff375c5cdL,0x7069fbaf0913ed09L }, + { 0x693257dcf690cb94L,0x576a85b2dfa6e07bL,0x72e00515447fe4e4L, + 0x00af617509a2cd8bL,0x05a61365902ae75fL,0x8310b16db5ecb690L } }, + /* 15 << 161 */ + { { 0x4d22c79cb00fd8f5L,0x432b09844c9ed8b2L,0x43da93b2a85b3f0aL, + 0x0522df2ac4163655L,0x2ea7210b77214019L,0x8280099b7051a9a3L }, + { 0xcd0a829bb11b9e80L,0x9bda76c7246ee656L,0x1ece801bad70a0faL, + 0x4f8162f096721d79L,0x341faae58e7c3b0aL,0x6914420b12e57cf4L } }, + /* 16 << 161 */ + { { 0x4962c02167141724L,0x5f81eabeabe7762fL,0x78549a79dd189c3fL, + 0x47675cdd6ce517a7L,0x5102294e32d6bb97L,0xb19500c66ed1a029L }, + { 0x3efb54e8b16a206cL,0x7dbdcc250dc135b8L,0x955bc2948967fb04L, + 0x373615c9be04e909L,0xf1fcf820111efad6L,0x8530f97d6fd2e97aL } }, + /* 17 << 161 */ + { { 0xdfff3aceb3b513d3L,0x569f9d42fdaed4c5L,0x8615a9cf71cdec34L, + 0x2e700c34ceeedc56L,0x9047d770a48d0682L,0x3fc845780ee5893fL }, + { 0xaaaf3d90ab5b432bL,0xc846365184cb412cL,0xd215030d928ec9bdL, + 0x237a710045b97accL,0x0f533045ff791353L,0x093a0d21a1899bf6L } }, + /* 18 << 161 */ + { { 0x5da20568b4bcee44L,0x878025840f5bd27dL,0xc76b965c1c06dbccL, + 0x89ea2cceb1492616L,0xaefc8746b460c4bdL,0x679e6edb994d1756L }, + { 0x4ff93a4a271f3218L,0xae496faf3b970a74L,0x062df3a7ba6c44f2L, + 0x1ede93021990ede1L,0xa797899af9a1e2adL,0x9b1bcf6d82599120L } }, + /* 19 << 161 */ + { { 0x63a38a51bd04f6ffL,0x2ddc958bffafb91aL,0x198895cdb19b2b08L, + 0x1bb494246f65b797L,0xf75df140f157b79eL,0xa188dc873d599990L }, + { 0x8b926eecaeac83c2L,0x55fe56f03b82900fL,0x10eb6dd33b11d061L, + 0x8b44c14c3aec5877L,0x294b83e8b486e651L,0x469e552f79524b3fL } }, + /* 20 << 161 */ + { { 0x69386f451a746ed1L,0x4319649bcc14bac3L,0x006292b3b647cefcL, + 0xc771b7cda20e2a37L,0x838714d2396bf329L,0xf263e66759c0823dL }, + { 0x7ee258f0725e3ecbL,0x37638f9934218254L,0x4d57db246fc6d0f6L, + 0x8c85ad7322c2dd47L,0x2300a9129c59cf13L,0x63971b0bee08c1bcL } }, + /* 21 << 161 */ + { { 0x180032d98c2e7698L,0x07d4d364a851f2faL,0x0070bbdeb50b5986L, + 0xba05ee28274eee7dL,0x28843675b0f482e5L,0xdcc9c09ff82b2229L }, + { 0xae0273e7f061df73L,0xa3856b6644e3a740L,0x4b13b141527b80ceL, + 0xfd83b7f0e1b7dabdL,0xa3b5a2f1536c04c3L,0xfd09c77bb29e2bf3L } }, + /* 22 << 161 */ + { { 0x05fe64c5436e7c2dL,0x5b9f0b83ebb1ee26L,0x13dcbfed2977d6f5L, + 0xbd16c6b7db552375L,0xaaeacc2342da342dL,0xe427d2ee0cfec89dL }, + { 0x3097ac7b038b280cL,0xa2b79d623aab3c43L,0x9771fff4a40f585aL, + 0xf50974e0b15aa16cL,0x114e51137a847284L,0x574ba8efb4fbe083L } }, + /* 23 << 161 */ + { { 0x3c8dfa3b05e37e4aL,0xeaf691b47408352aL,0x2e1ce9863c9a8610L, + 0x8d024a814acfb35fL,0x3766aa2184ba6baaL,0xc336f82eb91f5a27L }, + { 0xe2d46985412ab7b4L,0x397f0411ded6de53L,0x067241c3544768fdL, + 0x9206d3839b71e023L,0x8571fe1e3f51c3c9L,0x0abdb52e3ba345abL } }, + /* 24 << 161 */ + { { 0x85e1e4abd5281f9bL,0xc7e517ddc653b0c8L,0xc0b84da1a717e034L, + 0xf1a63b280f1bf3dfL,0x47b74201aba6fd41L,0x9cf3da633518fcabL }, + { 0xe12511fb23bb6e77L,0x13b2cb4438679d79L,0x20e0fb10db5665c0L, + 0xb5448a33b99f4d5aL,0xcb1847ad46b7dbceL,0x41f156b8fdcadb87L } }, + /* 25 << 161 */ + { { 0xd09b746793c8b2a8L,0x36c760204357f251L,0xa965d1771ac04cf1L, + 0xca49d59427740f18L,0xbba973ed76c53b33L,0x7f8c2d264c17d867L }, + { 0x389afbbb00966b80L,0x92f2097a55988387L,0x316a85393a47c746L, + 0x259ae094ac3a3a30L,0x337f1d3f0d61ee3cL,0x02d5a60ca9d928ebL } }, + /* 26 << 161 */ + { { 0xd9f370e42af77d78L,0xf9cb8d588bfa692fL,0xdc8a4c24fc9203d5L, + 0x499b6fda3b8138f4L,0x051a61f19118d3b8L,0x89207fa2cb251fb6L }, + { 0x32247676bbb0e12dL,0xaa1c59822900bce2L,0xe7beff9c7df4f6c1L, + 0x595fd551757c1449L,0x2fe91299650e8961L,0x2db30033f480bf30L } }, + /* 27 << 161 */ + { { 0xe796c05d110c4d7fL,0x12f87395d4af6817L,0x849cd9e6b5512cb8L, + 0x23b8d0a4adb71290L,0x28cc808bee64339fL,0x3072d46fcc27fd1cL }, + { 0x8d9183af47f675d2L,0x9959aa9102c84561L,0xdff7591708216e03L, + 0x868c237abd01b2f0L,0x4c00c229a53e639fL,0x2c0667fb07d69862L } }, + /* 28 << 161 */ + { { 0xb4d2324f9470e571L,0x3af515979ca353e5L,0x479a3a796ae5778bL, + 0x387958a7fb1d9c91L,0x4e606558cf91edc6L,0x428384ca495a3b00L }, + { 0xa49f67da10f7146fL,0xbda553e08e25f80fL,0x21b034c4cb919bc6L, + 0x1fb454bfa7930462L,0x1fb2ac9b255d7fd8L,0x491cceff8b197e6aL } }, + /* 29 << 161 */ + { { 0x0a0e0cd91f5a179fL,0x699d872713841e78L,0xfa93f774fc47f9cfL, + 0x8fd0019c02933131L,0x128efed95aa46834L,0xe20226fdf080cb8dL }, + { 0xf7b05fc3000445dcL,0xcc818da1f52f5ddbL,0x0fa803d07299267aL, + 0x99cf0ab4f9f172a0L,0xb5dd3c36b08d03a3L,0xfafa550ea1c2f73dL } }, + /* 30 << 161 */ + { { 0xdda52c89d2da4e36L,0x0348948d5c333386L,0xe3a5be8b37917590L, + 0x42488ae238e4aaacL,0xa6ecb5be7a44eb6aL,0x3bfd640ea9b27b56L }, + { 0x23b8d107bd05946aL,0x01018c45bb8034bdL,0x1ffc958cd2e058fbL, + 0xeadc93953fd43516L,0x0659b83ea0491dbcL,0xc36115008cdee521L } }, + /* 31 << 161 */ + { { 0xc0f3761c034b0a6eL,0x2c4ce5481fb66b85L,0x7a5d3143410698abL, + 0x4bc07a795d59e8c5L,0x176a10eb4d19ba85L,0xa8a68c5526dae045L }, + { 0x7eed57fb21625985L,0x33ef04ae16c62e63L,0x78d0acd4562454bcL, + 0x5878d7f2a44a1608L,0xa51a423a0cf11971L,0x1934e3f2f21fd6ecL } }, + /* 32 << 161 */ + { { 0x3f2b5bd4b4805410L,0x201ca7a9f96c5ee7L,0x532ef2db94256fe1L, + 0xacbfc459318ddb03L,0x2375f9fd5f24c8e1L,0xd27c479b370783dbL }, + { 0x1bd461e856541ae6L,0x78f054a77f7ea49aL,0xc9f8777d8845f315L, + 0x81aed29697fc92c7L,0x9f2f8d7949929540L,0x7531e78bff5ebfe0L } }, + /* 33 << 161 */ + { { 0xd4710d5a16ba6a11L,0xb172d8a0e056d27aL,0x01879d2b8301e5c0L, + 0x100c3e706f6a3396L,0x4a33d4a4e4e1cab1L,0x48016f0f08017d74L }, + { 0xbde9e0f18cec4fb8L,0xd8604899eb15c26dL,0x17ac5d884a21f615L, + 0xb8f1e7060cb0cddfL,0x0ead85644a0d51c2L,0x7bff69bdfd6bafa5L } }, + /* 34 << 161 */ + { { 0x028acd1cb6b73820L,0xc931f4bc815047a8L,0x22c6159f1ede2c60L, + 0x571dd40c99a4820fL,0xbaf08be0b450f472L,0x6475536aeb5bb639L }, + { 0x033568e4d984d0c7L,0x2ab7dd4885e910d4L,0xb0d76698d0c632ebL, + 0x954d00f3e3c34a46L,0x53e8772de651bc5eL,0x4910b07b6e3564f6L } }, + /* 35 << 161 */ + { { 0xe1550b37e758fcf6L,0xfea2446f763120abL,0x5db50b38124f80e6L, + 0x5cc28a7830c3301aL,0xa935846fd950d5b9L,0xae3e87f2ce43ebe3L }, + { 0xf033b25b7d0776a5L,0x941d186e882c5916L,0x0430c4503d6d4f7dL, + 0x4e0641c0726f30ccL,0xdfcdbd1626c66c27L,0x43c4590ceb00e495L } }, + /* 36 << 161 */ + { { 0xd8cbdd8b70435ca2L,0xede7fb3675af3a63L,0x6c1fa971090b36bcL, + 0xdd2292eb85455ed2L,0xf9c3889c7fbe5041L,0x2ec87c15506d605fL }, + { 0x2691b0a28b099c25L,0x27961c8b89944e21L,0x8e9e18a5147f5304L, + 0x6a82e35baf7dce25L,0x6745339c32a4bbc4L,0xe0bf0e0ee026676aL } }, + /* 37 << 161 */ + { { 0x3c6fd1ab352a43fbL,0xe57e7f8cbd68dbffL,0xa4a5b74e9ea30f41L, + 0xacea695d2d5a3a34L,0x183be19adc8fe4d3L,0x22fce6281b9f9d1cL }, + { 0x8b1ae75da5d35bc9L,0x213face52c673f82L,0xa879851d6568d549L, + 0x327c59937f8d8112L,0x56b982e2a7869b71L,0xc77afa6110bb8086L } }, + /* 38 << 161 */ + { { 0x1dcd57541ccadbe8L,0xd2d8c36512b37773L,0xc1a7a5b7d50e8680L, + 0xab1a00b3e19d155eL,0x58f4bcce7a9776b8L,0x1c02df3320d9d7aaL }, + { 0x24f00d31db8cea6fL,0x2680b029d4aa0785L,0xf3db2889c48587f5L, + 0x1811dd2521a7fabaL,0x5836964bbf820746L,0x3b118bab97aca83eL } }, + /* 39 << 161 */ + { { 0x14babe6321d76845L,0xf7b4c662c60f5934L,0xbf212c4434de5b23L, + 0x57c478a35bdf0a35L,0xddecc21535dc8714L,0x1609b7401571e91aL }, + { 0x41998697ba45b40aL,0x6ef382d468cf383aL,0x77a24c1488c0ec9cL, + 0x0a5e245297b377a4L,0x2b9d72bf18f9804bL,0xa4c21326f51ddaacL } }, + /* 40 << 161 */ + { { 0x397049f4c785c7baL,0xa87db27da1decf9dL,0xce6d5ec1e7862c0cL, + 0x17a98db834350bf1L,0x6ceccd8030ec8d74L,0x4790cc07bcab4aa8L }, + { 0x4378b1feb4f771a8L,0x3c54588b404dfcbbL,0xbddf0faa8d60f86dL, + 0x987583da3573271aL,0xb0afe4ec4b8f8032L,0xb5c44605b69d03f6L } }, + /* 41 << 161 */ + { { 0x7f69e8bfed7d4230L,0xfe54dca7d8ee8cbeL,0x6ec2b75f71b72d99L, + 0x97e2b30f8dd8338fL,0x9916dcdbbc75bf05L,0x22f4291aad5c114cL }, + { 0xb6af2e86f9ba5c98L,0xdd7d738dfd6fc5d8L,0xce7af7d544649034L, + 0x2979be5cd163b098L,0x5acd51858db8d84cL,0x82b0e4a5ca64d1c0L } }, + /* 42 << 161 */ + { { 0xf27f5f4f480ef46dL,0x2f49f44fcba811f7L,0xef40508d43961b6cL, + 0x0f6778e8df9fb37fL,0x97aff7e8446864b5L,0x29aeb86d4d264e1eL }, + { 0x48baa1984901daacL,0x91ade9db02b483cdL,0x00952a61cdb6abc4L, + 0xa1a51250de7f22c9L,0xe6adfaacc19ec8d5L,0xa7d2f066fc39838dL } }, + /* 43 << 161 */ + { { 0xfbe20a8e270bcf2fL,0x9882e7a0c35c60f9L,0x74d8e63f560e716aL, + 0xdc689649bae281e2L,0xd454571036d9b680L,0x0a0f1c681740ca0bL }, + { 0x228dd692dadf3782L,0x6ab0bede632d6e56L,0xae2f5535e1b7add3L, + 0x2ce1c6fece308fa6L,0x7a11b255db881355L,0x903007107bee5bb7L } }, + /* 44 << 161 */ + { { 0xdd55c21a9f1a57d6L,0xc9e1dcf9f6043ee3L,0x0385e3f36747e2baL, + 0x6511555a932e55b5L,0x7f4053b3700e73f6L,0x23adf65d992916a2L }, + { 0x4664bf231bfc40a3L,0x8400e8f27974d63fL,0xb70f104dcff08198L, + 0x4c44382f4d1710afL,0x5593a751374ec807L,0x6af17e84462c6112L } }, + /* 45 << 161 */ + { { 0xc1ad3eb7b8f1f38dL,0x74bb37c88d462e67L,0xd127b6e6246b0388L, + 0x3054aaf0824defffL,0x4e981d2e487809aeL,0xba76b7b805ead528L }, + { 0x0a167834a7a32c6dL,0x3451ee930268c370L,0xab4da0971b625d09L, + 0xdb94f9aa304e60b4L,0xf3bea685ab50c663L,0x8d929a0142d4c11eL } }, + /* 46 << 161 */ + { { 0xfce03e6eaa911497L,0x32cba5cf546ab5ecL,0x631123d0b1a71e10L, + 0x49f3a80906bcdeafL,0x783373bcfc538ca5L,0x3590890ee4b47edaL }, + { 0xb5c84fff39ab2df0L,0xf681be9ac737b24fL,0xf37bbc68b2b0052cL, + 0xd9f03cf6fde04d93L,0x23171bc2e43803e3L,0xeda51460040de801L } }, + /* 47 << 161 */ + { { 0x0e09a74d0bccf0d7L,0xfb429a675b58037aL,0x1f2660d2200b89ccL, + 0x489b332e04efc617L,0xb53d4f65f38ceeb4L,0xeaaf759546c4aa4aL }, + { 0xc6cff1fa714b9f97L,0x6a647072ec0dd5b7L,0xcbf59eb1637384bcL, + 0x043003cd2240993cL,0x134cab640497f9afL,0xcdb44a4ca9fcc655L } }, + /* 48 << 161 */ + { { 0xbd9a66d6543b3e41L,0x2948c0a62ae73774L,0xa75151dfef38e9b3L, + 0xa3348ae5754fb3fbL,0x1218fa8f13069b72L,0x532bb0510835dfafL }, + { 0x2121a98edf2be3c6L,0x85980de69e5199bcL,0x1b23a4be1a1eb6eeL, + 0xb5c48b92adeb3ae5L,0xeebd305dedea2b45L,0x20543f04c37198eaL } }, + /* 49 << 161 */ + { { 0x9eb2d599fa727a5dL,0x27cce415105643ccL,0x2face9e8c06035deL, + 0x967f70e4c5d916cfL,0x477224ece7cdc451L,0x70a3de4ea9a34198L }, + { 0x84ebd23a62628f21L,0x517cbb6097f55e75L,0xa4dc8d8ccbfaa795L, + 0x821d53c1a9c17b12L,0x04e94aea5124d5a4L,0xc72432c083efbc58L } }, + /* 50 << 161 */ + { { 0xb7a2090999f73a42L,0x019bf3a630db0901L,0xcf0c2a7281cfde4fL, + 0xf656a2117b0b04f8L,0x88cedc1896043e90L,0x4482c3786ae4c551L }, + { 0x169f25d3dc70c774L,0x0f8cc86cb552fbe4L,0x17d0556b88d2f3eeL, + 0xf5af9d6ff864ba64L,0xcd509d82f93dbf7fL,0xf00c76f51b98df35L } }, + /* 51 << 161 */ + { { 0x19fbeb37856e35a3L,0x1788055c88f36390L,0x9da657f165361c9fL, + 0xc9f327b7e35a36b1L,0xdc388bcb04b9174fL,0xa79bf7d3349a87c8L }, + { 0x865958b202289b24L,0x4096845ecebc4686L,0x1127085b42ce096dL, + 0x56f31d12735241bfL,0xe2239ab543b89a15L,0x477cc5b3a6a1f0f2L } }, + /* 52 << 161 */ + { { 0xc44c81525d54607fL,0xe742a6f35c9ab491L,0x50df96d9be8c2ed5L, + 0x3aa8c9b4e7f5cc4fL,0x577d534c3f12e8b5L,0x03f9573da33a57b1L }, + { 0x9172e1aec5c0c895L,0x64fa9822a2e19442L,0x17db2388178a10d5L, + 0xe75a6bdc2755ed55L,0x6a6d9dc3f9188333L,0xdd93a3b83eda0c41L } }, + /* 53 << 161 */ + { { 0x353d1f4bad0d960fL,0x6fbf4355846e07dcL,0x2156ae3c3a1bb429L, + 0xfa95a260442e6e21L,0x659a856ac2b31d7dL,0x9b56cd6563ecb2d0L }, + { 0xac9ec96823a787b7L,0x4102d82e320742deL,0x470ee0ea50a422a2L, + 0xd3ca8414af386491L,0x28d8994b1a0d8192L,0xe601e4e2b3f117dfL } }, + /* 54 << 161 */ + { { 0x906c071c4e9ab844L,0xeb1a5806f085a058L,0x2f14c3ac176e2f59L, + 0xfc1a3020bd19f909L,0x5e67d789ac060e45L,0x75dd23a7b707084eL }, + { 0xb9dec51a07e89974L,0x50c9cd0b38f97f3dL,0x368b0f53e14cd6fcL, + 0xea4c7f8b81ab93b2L,0x774ca31d1b7aeb66L,0x94c14607288f51a9L } }, + /* 55 << 161 */ + { { 0x18c41b62fe32b90aL,0x2e11c7e6be96e1aaL,0x72832e8c428b9d81L, + 0x93f63cc0058ca451L,0x603f18af7cc827f1L,0x31c8b8fee038eb26L }, + { 0x21158b24411cb335L,0x48dbbed70d9e953dL,0x445e244e4d62615cL, + 0x2f5309ac28ef4922L,0x12ee44c60d4dc305L,0x7dc0363f56f7677aL } }, + /* 56 << 161 */ + { { 0xf73471b5ef349ec5L,0x014dae75565aa6c7L,0x57cb497dae082cefL, + 0xdfcbf2b5c3e563bcL,0x22149c0fd1125f95L,0x529f419b425bc019L }, + { 0x049476deaee2094cL,0x3490c0490cbbb583L,0x56c5c62d1256424fL, + 0x0a118ee541bc66faL,0x0d8e9ff8296ada14L,0x34356e8b0134f8c5L } }, + /* 57 << 161 */ + { { 0x5e41ebd6eb28f97cL,0xe054a055d6a393f8L,0xc0a19e38db6555e3L, + 0x1b40c80fbabf4f9bL,0xfca17ae2780d5107L,0x89ae096f379701feL }, + { 0xd79be295b53ebb0cL,0x3112d3a5942b2247L,0x6c1f44d30de10f30L, + 0x2a17fffb0041f800L,0x13082de044552d55L,0x319aa9c0cd11c85aL } }, + /* 58 << 161 */ + { { 0x63ea1a6ae760373bL,0x00f2addd11742d8cL,0x46b17c9cafdd38eaL, + 0xf4121c5a4c7e78d7L,0xbeb70ef90048e4f0L,0x0b60c2b6bf7f7348L }, + { 0x4bbadf7632969689L,0xcb6a8a20e12708e4L,0xc43ad55b5638eb7aL, + 0x4a72b02b3d27bf7aL,0xecc95d92e5a54c30L,0xae52514bacc45d53L } }, + /* 59 << 161 */ + { { 0xbf5a2b5132d1f651L,0x6a2a74116e438838L,0xfa6353dd6c067d61L, + 0xf6918622b96ba12fL,0xf0fa254d45f595f3L,0xa0f0cb4b92f680a0L }, + { 0xf13ba734463e3f27L,0x7e3d4eb1a32d7f9aL,0x348baaf26f6502dfL, + 0x8021a9977b830e5eL,0x503f38ca55caf601L,0x27dde9e8f4bb74b6L } }, + /* 60 << 161 */ + { { 0xfd5a49310eb63b3cL,0xdb9f1a1510175713L,0x044d42c23e11c321L, + 0x5561f2e9b7961e8fL,0x70b3f7557ec7c597L,0x5dd9671235aed561L }, + { 0xc6cdc78ee1bcc2b1L,0xebcf6f87f1117aa5L,0xef470e0ae3669f78L, + 0x87b13e0fd38e0fe8L,0x01bff01439c755c7L,0xa66f2521c37529f8L } }, + /* 61 << 161 */ + { { 0xac56a8b223f78e49L,0x908c4be58708f0b5L,0xa63aa4191536f6b0L, + 0x8c08578fe5a95771L,0x5d2d1d6b9c2ae8daL,0xf3e4ef12f1527cc4L }, + { 0x46c1ac13920a90bcL,0xc0bc661d28ba758fL,0x9114e016585ef450L, + 0x8ab6a1f6e899a032L,0x57d4089606b658baL,0x2ef87621eb83235fL } }, + /* 62 << 161 */ + { { 0x033a4d4c4ebdc925L,0xff239a3efe1b346cL,0xd7ab2fb388d03949L, + 0x56ce2e41bd6e8e4dL,0x3826aff0e55da68dL,0xc9c7ba7451267f98L }, + { 0x5264a48ae6710c7cL,0x3635f1d4e7605975L,0x53a1849a94be903cL, + 0xe4fc3617128d5859L,0x7686804d7e4dd785L,0x6f04942d2dbcfe4fL } }, + /* 63 << 161 */ + { { 0xe80b7f5562927d6eL,0x92b98c350c0cc89fL,0x9522896d15117facL, + 0x7a224db5fdd3ffcdL,0x9502ecd8fbfc8908L,0x4e1dc71ac593105eL }, + { 0x052aade62f0536dfL,0x0c7cc371f324268aL,0xe7c62f2ccd843bb4L, + 0x77d48fa36df2c231L,0xb2c29803cb8f68c4L,0xad7ccf519bb9fddeL } }, + /* 64 << 161 */ + { { 0xd0960bd80fab968cL,0x6899e4faae028db0L,0x975ccc77a9850916L, + 0xb41bd531e5f81554L,0xbdf8ab57c8cff2c8L,0xea306a01f5822be3L }, + { 0x1f0ac0e7befbdbbeL,0x72f4b0e960519f87L,0x22bd8b82e3cc86abL, + 0xc43bde8d2b2beaeeL,0x8168781e412617ffL,0xc5610627b7ee7096L } }, + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 168 */ + { { 0x0869457a01a8eb44L,0x522239857a7bedd7L,0x2c04b0c600057505L, + 0x468be6e80b09adebL,0x2f3bf32b6f81474fL,0xf54f949da712ccceL }, + { 0x292cee424cdd8f2aL,0x3d9fdf6b9c221be1L,0xe54da66156f47b2aL, + 0x2ca76835840b5d1bL,0xb52adb6a8a6e8cf6L,0x8b416a6bdade153eL } }, + /* 2 << 168 */ + { { 0x65f7d2c18565afc9L,0x764c897170fa7b82L,0xe268634c986436f2L, + 0x6334d8d133356165L,0xf17164269ec7957dL,0xae834331b8093983L }, + { 0xedb1fe5cd2dfcce7L,0x6195b86368463e5cL,0x746e5f4da691b665L, + 0x61171291e1e2727eL,0xbb4aa8f16f27b029L,0x1037657d7f42c197L } }, + /* 3 << 168 */ + { { 0x2af8bdfa970f96adL,0x19d09a6dd0c86e6dL,0xd57fd5ced7046d2eL, + 0x5ea025f7d545fd33L,0xe2ccb6f43161ffd7L,0x3ca5286209406242L }, + { 0xf3536d60b5c90905L,0xd086e3b9d5b290f6L,0xfd15b06a5cc55444L, + 0x61b0febf9a9e2a66L,0xdc3c0576653dfd02L,0x357774230a8ab51fL } }, + /* 4 << 168 */ + { { 0xfe19901b0d5b855aL,0x5facb9552f745022L,0x92fd012556c4ce5cL, + 0x23172d65938c89abL,0xa71f8a33aaa587b1L,0x511a3745b55c9c50L }, + { 0xec005f6a7185086eL,0x6dfc2761f894c6abL,0x98a4d67f9e26361fL, + 0x7f0a2b2321389c25L,0xd158820795ffbceeL,0x4d6b29ab9f36a888L } }, + /* 5 << 168 */ + { { 0x5ffec1d78c04bc6eL,0x35f052d16ca0dde2L,0xfbe3844c649c850bL, + 0x450263e610fa337dL,0x44f7c8f40280773dL,0x27de5d3ce896966cL }, + { 0x2587f47598d0378dL,0xbd49c97f4e4f6e49L,0x9e902f667071543aL, + 0x03398aae06577b74L,0x030926d6910bee13L,0x5576575bffa92cecL } }, + /* 6 << 168 */ + { { 0xe4ee33460562cd7eL,0xd1d385a3f01ba45eL,0xd817ca667ce11848L, + 0xda222cddcb69c7eaL,0x74ac74709d680afeL,0x3770357cd9596ca8L }, + { 0xdff57da7f7759bd6L,0x090426be20d5c726L,0x71c0ba28b7fbc1b0L, + 0x60faab1c13d4ed0fL,0x6fbe3567ea3a2ef2L,0x0dd3835c4e577dffL } }, + /* 7 << 168 */ + { { 0x9b758b512ce27e38L,0xe4148475a39855e3L,0x4669b3c39ee88a77L, + 0x3f36a671105e1ec0L,0xd0f30e5d9e88ea13L,0x6346df15baecbaadL }, + { 0xec65be65cf4c6510L,0x843efca194e1989fL,0xf7195d29942ce52bL, + 0x12201877d3ce28d4L,0x9c962aa1a97fc904L,0xc4fedb3465c5a55eL } }, + /* 8 << 168 */ + { { 0xeccb421ed0a701a5L,0xad4cb9a5b60cd286L,0xd344da9e05a53972L, + 0x3a8035e07bc99feaL,0xe0214485c0f77bf5L,0x50ada30ee54df78aL }, + { 0xdef45af64ec2d576L,0xa05d61845f9a8678L,0xa9b17db1c337e017L, + 0x026a4f66b84671d5L,0x606142343b7d696dL,0x71ed9aaf81cfd22aL } }, + /* 9 << 168 */ + { { 0x62805305695a3f30L,0x6ce27626e28e8fe0L,0x507386af6a54f410L, + 0xf8c5f738cd5c7effL,0x3ab2db9e347e85d7L,0xf5b635b0b2161b68L }, + { 0x99009791be2e80caL,0x6dff3030c13910ddL,0x2beeca057ee8700aL, + 0x12616fb11ac7e09dL,0x38c9ef9f9037c2e4L,0x39181fbf9c140344L } }, + /* 10 << 168 */ + { { 0xcdd6aee47aa54433L,0xf5ecb432b80336f5L,0x690bb949a1380829L, + 0x219d659ca9c9d720L,0x74abf2dd7e5a3260L,0x405ee136025c55d1L }, + { 0xc5c592cb1cc878a8L,0x119a38be88b31ecfL,0x4fb00f82e94e39e7L, + 0x66bf72e59412c068L,0x9337c8f30821142aL,0x477216340c24ab67L } }, + /* 11 << 168 */ + { { 0xa6c7953457fe953eL,0xd70d3d2f3c76ae58L,0xe1e047b52c531c84L, + 0xc71f3a9973735602L,0xd70bdb0f7ba0628eL,0x280fdd4e0e3e3c0cL }, + { 0xb5a3f5823e414e26L,0x55b2eda8f44dee7eL,0x8e1d024b2f5dd828L, + 0x21f054eb3b1bfdf9L,0x3d3ae74cc554e1cfL,0xa0a5863ffc42ec16L } }, + /* 12 << 168 */ + { { 0x1b76a3c5439ada39L,0x818829cf89236ae5L,0x2277cb7a750f8129L, + 0x44aa462a4d46502bL,0x7a12e1e164f06dc8L,0xb9a3300dba5630cfL }, + { 0xd2cc8d9c55b05f4bL,0x6d0b0b88a700be7aL,0xa7be99699617500cL, + 0x2b5b8deac03f8a50L,0x712f703e785b3dfdL,0x96a5a60accf93950L } }, + /* 13 << 168 */ + { { 0x9838155fbf9f72c6L,0x3ab3cb602c10e57dL,0x7ac228ef14bcd75eL, + 0x2c167e15027923fcL,0x678869d1267471c7L,0xeba35e857ec3582cL }, + { 0x22d290a9a3478eb3L,0x542092ca1309aa14L,0x8bb5c69be2e5d3acL, + 0xf83c5a0a81652736L,0x9cc576227280cd6dL,0x6653436f3b0f49a1L } }, + /* 14 << 168 */ + { { 0x7ad1f1bab497d900L,0x9d0512236c9dd5d7L,0x0ed27e5bffed3df8L, + 0x659028a775d2fa72L,0x69bd68154581f377L,0x142c2088e2faf671L }, + { 0xf9c1b8a499b000ffL,0xf31d01b18f408d3aL,0xa7aa142f42b9d35bL, + 0xeb8aa74ba0495da2L,0x824cc32a59a1da45L,0x3f1fbe0ff5173374L } }, + /* 15 << 168 */ + { { 0xec9071a634238c30L,0x6dd6c38b88a0f423L,0x3adace72992e7977L, + 0xc90b941b1ae5166eL,0x052aa3e9e3e43a68L,0xe9b1976da733a950L }, + { 0x0e1ca28e5ff6c9dbL,0xd1bd4350387409a2L,0x5943cc7089155117L, + 0x8e85794f5feae20cL,0x0d118fd669768ccbL,0xc647179d53120895L } }, + /* 16 << 168 */ + { { 0xfeb984b3ee828fbaL,0x8273f830e2bd188cL,0x177ef97e3ca0a99fL, + 0x76d4796dacc000acL,0xbad0fa6eb140f51aL,0xb275656706ebc810L }, + { 0xf89eb78fa18cb32fL,0xcfc37eaea65285b0L,0xe2b29cfbb25e9d1bL, + 0x9388ea8fb4e7aef3L,0xee606c12e267e845L,0x6b103c549f5806d7L } }, + /* 17 << 168 */ + { { 0xb9a40e78e31fd643L,0x648cc34a97950a34L,0x85c5ca405900be55L, + 0x2e519cf12abb843bL,0x6f9d0a7f27436edcL,0x2f569c9d6694f363L }, + { 0xf6d1b325f6f1bd24L,0x01103c0d4044b353L,0x2d3ce56f3138b549L, + 0x5379bcf71c28bc5bL,0x6768220d08ac00d1L,0x973f92ff0152746cL } }, + /* 18 << 168 */ + { { 0x5e992944b37b0486L,0x0a334b92001fa124L,0x6653cded9c9ab466L, + 0xd512612fabac4da9L,0x636bf431c502b860L,0xfca1c0c2c3d20db2L }, + { 0x7073f293f85c40c3L,0xfaabc77acfba9eddL,0x58842eb97f9b570dL, + 0xe8cd4f53702aec24L,0x8975f4e6e08113a1L,0xcc0d7f17767bedd6L } }, + /* 19 << 168 */ + { { 0x5163bb51ae315a65L,0xf82ec4cdbe405348L,0xffd381a46b1801a4L, + 0x33f9b8ad2f6ba570L,0xd88c58a58ecc0000L,0xc0b9a639cfdad25eL }, + { 0xc78cb70fe3bd808aL,0xf54b86e573ce5eadL,0x111208ed5610a761L, + 0xba3579b0e3c8e27aL,0xbadd918c63b85bb7L,0x9e10da0b71bcd972L } }, + /* 20 << 168 */ + { { 0xf418e3f63766f2aeL,0x4a3ad3c8053ef1c1L,0xd01e5b5b560db262L, + 0xa583edc7c02bf4c3L,0x7c9f706052f318d3L,0x0852556f1f5e1ffeL }, + { 0xe1c70aa7feb0e63cL,0x59f0a3f989a8c058L,0x4aa4cf021ffc0adeL, + 0xbb880e4138a78632L,0x35b0f7596f28f096L,0xf9c4fe17d5757d7dL } }, + /* 21 << 168 */ + { { 0x160303ded896adf7L,0x19a46b6c6beb8930L,0x33dfd962f010f74bL, + 0x03b699cc00e5610fL,0x17487b7595078dfeL,0x63bc614253f3479cL }, + { 0x43f3d994858d5b8bL,0x383349349483c0ffL,0x47c917a67977142bL, + 0xdc50fb80df7eead4L,0x4e3a1d3fb5b82be1L,0x091af8796d7317b7L } }, + /* 22 << 168 */ + { { 0x783e5066af151a9aL,0xec0a9c175466df17L,0xdecd12310174b0adL, + 0x654af66a3b2aaa45L,0x849d64e5b1fcdd11L,0x7e8e2ae6d05af56cL }, + { 0x12e887b7318a6184L,0x42d1445554ed59d8L,0x2eafeb48ee54ddc5L, + 0xd1f9e6b980c94a8eL,0x5ea691e3263696c0L,0x7f42f3796e03eed3L } }, + /* 23 << 168 */ + { { 0xeeb8accfd69b82b9L,0xb4c4988ae0b61d73L,0xb78becf19df9b59eL, + 0x13274f6236440c93L,0x33d287f5697d5a77L,0x391fe6129af4053eL }, + { 0x986c42b21c16e858L,0x23f5d1dffe04125aL,0x2f57ccb3af9541ffL, + 0xe5b4eec70f1a8bafL,0xaad23ce7646c1b6fL,0x69495ee5a6ff96abL } }, + /* 24 << 168 */ + { { 0x78b8879cfd6376ebL,0x22a76461c01e1edbL,0x6a44be39369cf0c4L, + 0x6653670d5ae54539L,0x257bd7516fb43ad0L,0xb3ac371512baffddL }, + { 0x48659d617548eabbL,0xd8f931f80cd468cbL,0x98f0241549e3b531L, + 0x90b0d71670df011fL,0x26d73c54ab98f066L,0x06591ec988475d5eL } }, + /* 25 << 168 */ + { { 0x6fa72e3518f18e71L,0x6c04fe2d8123ff14L,0xc48cb53a197481a9L, + 0xf059db349860e48cL,0x35e8341ace46ca7dL,0x880f4ea4b0400f7dL }, + { 0xb4c5ea9acc9cc40aL,0x6522c768e2555fa3L,0x95207f39ea2c32e6L, + 0x7b6fc09fa8be60e1L,0x772b829f29902652L,0xb7936b90af6a48dcL } }, + /* 26 << 168 */ + { { 0x409e3b1109758457L,0x59dd0a8c1dea73d9L,0x528906a58fb18a01L, + 0x6fa55967a17ffb33L,0x9523cc3d50edbcb2L,0x35600b3e44d43541L }, + { 0xc3a7d22c8f87dbc0L,0x5514c967c1b225abL,0x78e5701988304a74L, + 0xe9b417ba35f3b54dL,0xb72a243c48eea230L,0x4e173eaf291ee52dL } }, + /* 27 << 168 */ + { { 0x79b854ca2127c795L,0xd9457d8f86657844L,0xf8c9e6ef186668e8L, + 0x84c8855df913c2f6L,0xf207d36ad641cc12L,0x7be9b5736105ce0aL }, + { 0xe72cce1974ec078dL,0xc4f47413d09950c3L,0x640bf6eb3974554eL, + 0xf880dcfb844497baL,0x3744626999bbcfacL,0xcf1712f4316f4d64L } }, + /* 28 << 168 */ + { { 0x627f6328412b84c3L,0xd427e977a04545d2L,0x5b0145bc104f25c2L, + 0xa6931c4f2ac7ad62L,0x407611431f8d42f5L,0xfda5a76be7f8a0b3L }, + { 0x4f1ca5cffe0946b9L,0x6def7b9fbeb2d427L,0x984bd4bbc9a0d136L, + 0xb9a778235b3af1c1L,0x04ee66ae38ac2087L,0x63374ed926d9dbb9L } }, + /* 29 << 168 */ + { { 0x68088e9c3983deb9L,0x2c95ecaa2ed99988L,0x371af002917f200dL, + 0xff33aa5dbb4ff0dcL,0x1dd5fcf2e47bbd6eL,0x1624b973e75f73ecL }, + { 0xf6ce0e9db9722af3L,0x8bde5b8818226fcbL,0x243753fc5b5da478L, + 0x3b53e0e3bdf88daeL,0x59f8c86f325cedb2L,0xabd4076d70fb9681L } }, + /* 30 << 168 */ + { { 0x1996761db8759af1L,0xfb85cdd8e4a705f5L,0x2ea7aa0b35111725L, + 0x23245d4157a17f4bL,0xcbdb650e0d00eb9dL,0xb40823d9e23a4a3cL }, + { 0x041bfb67229163f8L,0x020ad3c16d47b83dL,0x3bc8975d344c8ebfL, + 0x287efd06d91ff408L,0x1ca5d75a2059106bL,0x4ff27af3b90c5d66L } }, + /* 31 << 168 */ + { { 0x416b7c61ded914e8L,0x1aeee7d007ad4237L,0x59d5852476c2b7a4L, + 0x427a102c98665f29L,0x8504aa8d2a1aefe4L,0xef2dbeadc183a736L }, + { 0x5cb5f222f533358cL,0xf2ebb47d36b0d678L,0x1de4a0e7f2c2cf99L, + 0x62613994ea95a161L,0x68a86f4012d66ed4L,0xeb12fe75b2af52f3L } }, + /* 32 << 168 */ + { { 0xcf947c0644ba39e6L,0xf5d5216cedfe78d7L,0xd00115c05f1835c9L, + 0xdf084152d8c79d90L,0xc0c3a6846db5f791L,0x40514451749b18cdL }, + { 0xd314b7d5734df3f1L,0xbccdd3f07f541415L,0x97ed5af06855a942L, + 0xea84ae9ee9d02ab9L,0xb87e90343238a5d0L,0xd12d25c3650a0eabL } }, + /* 33 << 168 */ + { { 0xc3747c584f9d2c34L,0x493a0adc95429c92L,0xf9b5916238a679ebL, + 0x04d500a16bac07f7L,0x8938f4f96a809676L,0x44ecbbf0c5b25a4dL }, + { 0x3b68705504768400L,0x6a432e14b4db3907L,0xff82fb56ad375d2bL, + 0x87f59f97944210c2L,0x2b680b2051445242L,0x1e0986466cd75962L } }, + /* 34 << 168 */ + { { 0xdd2eea82672e5a4cL,0xb05ef9ebccc68d94L,0x626ce368a3fa4215L, + 0x6e376f67fe46bd46L,0xaed7a0bc33c4f169L,0x4a92c6093af5c4fdL }, + { 0x6615245fa690fb49L,0x571d2d870d64f04dL,0x6a45df34641ce79bL, + 0x045ddbd02655d316L,0x2b6c574db4fbc42aL,0x41545fbc5b2dbbb8L } }, + /* 35 << 168 */ + { { 0x484996b97d8f1eb7L,0xf72f3a8110bd1585L,0x418e00e7b67eb27fL, + 0x354e56c97877c18fL,0x7f11f5040a8b37f9L,0x66591146ff58764dL }, + { 0x816ac849ed0bfc38L,0x85eaa6350a50a99eL,0x7fa62d9c5bf4995aL, + 0x77840d5003413385L,0xe4f023bde83f9fa1L,0x2c5f8e1d9cfa7578L } }, + /* 36 << 168 */ + { { 0x1473b55b86a515a9L,0xa9e3230a3b337c64L,0x7e8bf9049db668f1L, + 0x1db2c25ef27f9fc9L,0x0c1086072d9e467eL,0x4505579aa3f00d52L }, + { 0xe2ad661b240400a7L,0x8022294c11af4874L,0x29e9037078bba8e8L, + 0xbf0fbf08f6baca04L,0x2e46d2b74101fab0L,0x66065490c61089e6L } }, + /* 37 << 168 */ + { { 0x18b01aa935dde51dL,0xa7496997a7d044b8L,0xcd9c467f44c23d2dL, + 0x96211b86659e4a5bL,0xa2a9000f3e17b717L,0x7af9c312dd90459aL }, + { 0xf0d6c24394547203L,0xa76a23dbd77cc691L,0xe1b7fce10ef364deL, + 0xe08c1d0bb689c810L,0xb75bfacb0a43ca02L,0x1b7afea5408ac99aL } }, + /* 38 << 168 */ + { { 0x3b1abdb85a4a8a23L,0x8f52060c4d68bcf2L,0x7408306a00ab3146L, + 0x652ae3064b86b775L,0x276a14a0b0695b00L,0xcf8af11f1b771254L }, + { 0x3fafcc63b91118b3L,0x6c49000a73bacebcL,0x53852d084e3f3d6eL, + 0x78977e91fdfccca1L,0xe843cbca6ae9ea5eL,0xa99831896bb8271bL } }, + /* 39 << 168 */ + { { 0xf77b0a7387534a6cL,0xfff419f2f5b0c6dfL,0xde3c3b33357205eeL, + 0x867eb3a23c8ec9d6L,0xd28bed3263a99b18L,0xf5fc17e4c1573146L }, + { 0x30cf41e5821641feL,0x84b1970e225ab57fL,0x6bf707325a1e8ba0L, + 0x7bfb3bbce3cf38d6L,0x9f362787a661e876L,0x6d9137c86c0a16fdL } }, + /* 40 << 168 */ + { { 0x2131ce5b09f8a1cbL,0x7b373ed28ab129e2L,0x463cc8d677c1292aL, + 0xa9b7cf6594ffe9c5L,0x129125ceb99bfc4fL,0x819b42849820d323L }, + { 0x3f70976376541a41L,0xfd679ae5e32c7a7bL,0xc39a208df65b6b3cL, + 0x1c22ebc050002745L,0x268f19dde2bcd202L,0xfeac809c9c3d4266L } }, + /* 41 << 168 */ + { { 0xc5ad8903af14f8a1L,0xdfcd207c3993c99cL,0xf65f8260c7c1fd57L, + 0xa1573b3d41be66fdL,0xeeeb9ea476690f79L,0x6a6338437129849dL }, + { 0x22eeb38623a7bfcfL,0x258fc0743393e894L,0x008efb477ce9602aL, + 0x4bf127b699c7b279L,0x150da482fa1bfd7fL,0x7b84744d293754dbL } }, + /* 42 << 168 */ + { { 0x3af9919db2183277L,0x7f5990fb4f6182ccL,0x17603db034f716d2L, + 0x6b79f6538f135ad5L,0xad9189e68092d128L,0xa5f3ab8efc6628c1L }, + { 0xa36b978e84b6d30fL,0xf2a7e1c64c001f26L,0x2acbdfd676e79beeL, + 0x71b5faec86f6d6c6L,0x23d9b7c849b0e5d7L,0x36ea518212fd4cccL } }, + /* 43 << 168 */ + { { 0x14a4af0f59df1cf9L,0x37f8641dfd7cd2b4L,0xfb6aa5d0244434b2L, + 0xb85f8c8b5d5bbd63L,0x833e76baedb92f97L,0xbcd9d7b50d7a2dc2L }, + { 0xb233f07ff0e0f06cL,0x453f10c4fcc06efcL,0xa4e8f306128a167dL, + 0xbd6df4690d0c09cbL,0x2b5db66b7168ecc6L,0x7ec02c77f29bcecfL } }, + /* 44 << 168 */ + { { 0x0746783787dcdbdbL,0x4cce33be320493d8L,0x9ab08cbe713c7746L, + 0xd6f0c1de9c6dc5cbL,0x194005382ac03761L,0x3fc11f38d0547be5L }, + { 0x66b378ce819fe3fdL,0x6a590acc3700fe7eL,0x4c976a728924b396L, + 0xa5006d8d70b9b250L,0x2fdce1b212b85f9cL,0x5858f7ce495f8f1cL } }, + /* 45 << 168 */ + { { 0x3f2b5e295de2948eL,0x84554eaae1a4a962L,0xb4e55f1293db9addL, + 0x9260e3eb61b22484L,0x22a898997b1a6d10L,0x571bcd3af58d1ce3L }, + { 0xd62db0edecc88a76L,0x88352f634af2cf53L,0x8d279316b61c73adL, + 0x7f898e09ec74d6abL,0x39b2b0c05412a81bL,0x623a5ea30644b6a4L } }, + /* 46 << 168 */ + { { 0xe876b53bdb0f6565L,0xd0dc323c4650204bL,0x0e4af31b0201643fL, + 0x486173207e8a0e6cL,0xe09183d457643a1cL,0x3c55bcb5ae8359b1L }, + { 0xa06078cb7b467835L,0x4d3a35d901b6bb3cL,0xd4f1d8233963fd31L, + 0x9c1b06093d4cce05L,0x55e368d5da550340L,0x50c3feee12c4b7b3L } }, + /* 47 << 168 */ + { { 0x6de0fcdaf0f97e84L,0x1f225d818dfbc0ebL,0xe27a42efcd2c51d9L, + 0xeff56879c0cb033cL,0xe700cb87c82e38d4L,0xc89a02d589d244caL }, + { 0x0b464846ad9c718bL,0xf8d5ee1f8de96d61L,0x2cc33c3dfbfd0960L, + 0x3ef549f0e199b6fbL,0x29f83f686c1597b3L,0x54ca37a3731712ffL } }, + /* 48 << 168 */ + { { 0x357540ab903ff177L,0x225280b8276af514L,0x33d273ac14d7fed3L, + 0xfef6b9ffd186ee3dL,0xa94c207101a7b1d9L,0x4ea3627450bc8bc2L }, + { 0xc68959c9fa98a918L,0x8f5ecceec7bdc262L,0x7a73a4fce6861310L, + 0x19bcac90c828330fL,0x73e3b66f7ef74fdbL,0x60f7698352d8f2f4L } }, + /* 49 << 168 */ + { { 0xda57f1a65645cb9bL,0x3d5d3190f0840240L,0x6a0c6ab101bce275L, + 0x38993676ad23128aL,0x54f7b5d7ea0da248L,0xfee930b38b04ccb8L }, + { 0xadb9034e2cf3bf1aL,0x0488b71ae9b608daL,0xa3e51e303bd1172cL, + 0x56dffa5844993c1bL,0x6b3211fa4cdcaf10L,0x223b2a43834d4e17L } }, + /* 50 << 168 */ + { { 0xb31f934134e43ed1L,0x895c99973c6b7f58L,0x360021084c465126L, + 0x7eb0bf6b095df89fL,0xde3b2fa3ac534af6L,0xd9dd9f55c22477caL }, + { 0xf52cfffc2092e355L,0x4ba071ac8d8bffc6L,0xafb61137abefe750L, + 0x2887d0e4cb62210bL,0x0eb2be515f4fc157L,0x8c993039438fa2f7L } }, + /* 51 << 168 */ + { { 0xfd2a61093efae008L,0x60fa269552f57cafL,0x3591e64f481c36c1L, + 0xdc2b9993c908a87aL,0x76bd4dea5bffb50dL,0x913a0458f70fb0f5L }, + { 0x45ea6c4c097bbfc3L,0x3ebe29d3fa9e90c1L,0xc69532426479c087L, + 0xdd1d24509abc7a4eL,0xa497b072d0fc7791L,0x477d71f9388ab90cL } }, + /* 52 << 168 */ + { { 0xab3578047e03a14eL,0x0f4f28688caf673fL,0x919e661e66530425L, + 0x28da445c91ba47c5L,0xd6d0537566c394feL,0xfe1864a302e8ae91L }, + { 0xd34baca2a753aec4L,0x43b7ffe7a2c8d292L,0x496659eb04efb8f1L, + 0x310ec2a9e0252dfdL,0x98173d2f9168a80eL,0xa3e018d631497255L } }, + /* 53 << 168 */ + { { 0x39ee6439ddfa0ffcL,0xaea6f882c1d1d54dL,0x688feff654a65059L, + 0x17ee5aaa37f25ebaL,0x6c9b4f2932b345f2L,0xb883c0c75b4d62ebL }, + { 0xaf33e4ae3135aa7eL,0x28a7572c924146a2L,0x67dc5dd37e77ae8bL, + 0xe11cd9c5ff39b601L,0xa86f090b5e6f364aL,0x76f7517500b84247L } }, + /* 54 << 168 */ + { { 0x26d3a3e3fbae20ddL,0x5e9b73cee1dd2b25L,0x7008aefb0235d5b0L, + 0xa92af4ed2aaf208dL,0xab786c9bb1132040L,0x43250e6c9a91269dL }, + { 0x00a15294c9be00ceL,0x2d5782df1698dd42L,0x3f980bbe76e3d6e3L, + 0x5b602647496650fbL,0x461edc3271aca61bL,0x2516ab6c9805a01bL } }, + /* 55 << 168 */ + { { 0xb468fcf2967e2216L,0x97b840679ae47d05L,0xfcafaebc5cc15209L, + 0xaf7f6c8ccc83c3d4L,0xa74d4cd5cfa47e0fL,0xd8a51615474cb8b1L }, + { 0x4815ef52591462a6L,0x9c5b2cf74deb41ddL,0x39cb450b7e99d620L, + 0xfe8cacbaa7772019L,0x98b98210577dc69dL,0x5e02b90072423a96L } }, + /* 56 << 168 */ + { { 0x3266c887d9d9284aL,0x690f818b73646ab7L,0x67315ec6af7fc33bL, + 0x181e61abc30b1ccbL,0x1b81e6cd105a9e1cL,0x62a15daf5078b9bbL }, + { 0x74f9840f6fa8cc65L,0x356b777443388573L,0xba0f7d0506b3fd46L, + 0xb0ac864c92b4fdadL,0xcdeac253ef192cdeL,0x0c24810bc313b4a7L } }, + /* 57 << 168 */ + { { 0xfbcd4f77e748de9bL,0xb7d28cdfc25dcc94L,0x32f937a92e033c43L, + 0xb6289636d9da1f7aL,0xd774e97dd287865fL,0x8d013739e6243bf8L }, + { 0xee7ec1f856b9601dL,0x429017666afc90caL,0xc42d960ad2bef9afL, + 0x654ece7f5b430bf6L,0x02878c7f221440f4L,0xe575aa6474a4e1a5L } }, + /* 58 << 168 */ + { { 0xc96e763e71a449f9L,0xdeda66311a349fb0L,0x6f896aef3c4e8f44L, + 0x71ffe2d2e9eb36a3L,0xcbee21ab8f908a29L,0xaeb695f85be98708L }, + { 0xb6023803de61e1a9L,0x59f1ec96065ecca3L,0x2a1229f3637d0741L, + 0x5a9bca2c69441afeL,0xfc6daedbbbeaeed6L,0x950034954e2e31e0L } }, + /* 59 << 168 */ + { { 0xe59a827339859da4L,0x8720429fa7431a84L,0xfcab26e17ee3457cL, + 0xc13c1125da3b7833L,0x0bb1043fbc0b0da1L,0xdc2726ea84b526e8L }, + { 0x34049278a213a188L,0x400bb4a00a1a2553L,0x00e3eb25c92df398L, + 0xc0b7113f9c36a6ddL,0x719d185001e274bdL,0x86f08f2dcde338aaL } }, + /* 60 << 168 */ + { { 0xef8c40bf1adb09b7L,0x2efeb49c0b74992aL,0x3f0f8a412b79957fL, + 0x08927bfe87a06873L,0x1f63a4109288cb9aL,0x8c66fb70df2b373aL }, + { 0x98da4712980facaeL,0x15ce5b17d819d026L,0x097571a5749a671aL, + 0x85a40804894dd269L,0x3e89c13c34cb6797L,0x2d19d5e4d07119a4L } }, + /* 61 << 168 */ + { { 0x903eee85d90da9a7L,0x67723582de5ddbf9L,0xacf6898ad394eeeeL, + 0xa700fb8fabdb94f3L,0x1bcc4f947ac5624fL,0xee5cccff7e3b8ec5L }, + { 0x87d64d4d98e5a1baL,0x78727fc1ad9c4409L,0x55b4159b82310db7L, + 0xaff4eecea58d10efL,0x6d2ec94c11c958afL,0xf129bd1043db33faL } }, + /* 62 << 168 */ + { { 0xe1f6d71ed42eebf8L,0x46f825b9541ac0b2L,0xb01031b693ae2ab1L, + 0xfa4e1c357c589556L,0x65fb2504d273d1bbL,0x589d735447642bddL }, + { 0x7a5776adcf5e2d53L,0xab5c3544e5feda7eL,0x48e8442d32dea96cL, + 0x5f3e9c9e64d293daL,0x3f2df6a16b972a00L,0xfba58f5fa273832fL } }, + /* 63 << 168 */ + { { 0x5c9fe89240e9ce34L,0xfd9fb296633495d7L,0x0ae3c18a8c76cd7aL, + 0xb5ede1e3a6b77012L,0x5ac7a9d5a285822dL,0xe41de7da71ffe07bL }, + { 0x585f7e101b1bb4c5L,0x482794be74153077L,0x66f1c9d5a3e2a34bL, + 0x491d48f7c749830fL,0x3c0f3bcd5416d2bdL,0xaa3baada90b04986L } }, + /* 64 << 168 */ + { { 0x58225208ecbafb80L,0x4f212035aa73d6deL,0x1224e45562fe86dbL, + 0xa8c8a4782dc5b2f1L,0x8a957b8dc3096555L,0x6a3248b0b1591452L }, + { 0x1e563c58cb604c18L,0x32808cb59bf1045eL,0xf8f62de99462e7a2L, + 0x6b3dfe91c2489214L,0x6c1d8fc42174639cL,0xdfca11b8ef88d4b5L } }, + /* 0 << 175 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 175 */ + { { 0x5a4a5ce418690ad0L,0xd0f788e0fe27f51aL,0xd459388e4efe9a30L, + 0x3a45c11aef9d074bL,0xf68ab50b93ab9cb0L,0x62fbc397ecd9a566L }, + { 0xbfb79b7fcc587a7eL,0xfcf4d66f92870baeL,0x4f31aa21877390f0L, + 0x2de0c645e314cfb5L,0x56d904f6238eab12L,0x4d104a42ccb4d4f6L } }, + /* 2 << 175 */ + { { 0x3eb83a8729358cd3L,0xad741295b9c6d430L,0x57b8c77a53abe4e9L, + 0x0a14673ebb9feb82L,0xc0a6cbf7f26f922eL,0x213de299a32e526cL }, + { 0xca417e677b6ca858L,0x8d6ae0f7fc2e0900L,0x2bae0e7a62e135ddL, + 0x962bdcaea7ee82c7L,0x573d7f6ae5776c74L,0x9c4de6496ffbefebL } }, + /* 3 << 175 */ + { { 0x8c962fc809335d38L,0x26d1bc81eb38d176L,0xe1aeb295c47711edL, + 0x0812b9926cbe3e4eL,0xeecacaf90ab9805dL,0x82fefbaa3521a0adL }, + { 0x3a6948c0e2c31b9dL,0xb7d3905be82daf2bL,0xbd3ac90e25a34c37L, + 0x55afd99b61453063L,0x56d87cd190b99303L,0xc9bf82dd97ddb0a3L } }, + /* 4 << 175 */ + { { 0xcbc0bb1968916917L,0x0bbb9f921094bf88L,0xf62cb350d3806442L, + 0xe4d2f1cc397a7602L,0xa54bd48e43987d82L,0x77b6f8314f0a19faL }, + { 0xfa0c9a456e766443L,0x995ae0fff51ba70bL,0x8e242c5b9cbd8d33L, + 0x1671eb0813d97956L,0xccae388f40da55faL,0x97cc48faf376dce5L } }, + /* 5 << 175 */ + { { 0x1c2919bbe8c91718L,0x9dbb727a5097bde3L,0x23f87ae7f8ea2fb2L, + 0xe1bfffdcba310121L,0x5938c50c75329669L,0x716c63e00549855cL }, + { 0xe091b0c9654814f0L,0xa20535d10e43daeeL,0x16ce68b2593ddd04L, + 0x7813a49af59900bdL,0xef0d3eecd3e5d232L,0xe7d12cc40ee3fd4dL } }, + /* 6 << 175 */ + { { 0xe54d92cdef01fc5fL,0xc46c2ab8dda2e25aL,0x7c907fd2849f6142L, + 0xbb11dd2dacd0202dL,0xa4913a701d92d19aL,0xe9a26ae0cf610677L }, + { 0xfff1e1d5538943c5L,0x5943dcc4a47b2204L,0xcafcf33a92cabf71L, + 0xd571e13ce329d1adL,0x7626ad237a9a0e4cL,0xf0aa0d9f130d7f86L } }, + /* 7 << 175 */ + { { 0x09df3a4419e6aa7eL,0xe27ad0475841b1cdL,0x02d2a69fbde75934L, + 0xb0e05e53fd9ba435L,0x4732d88ae008c16eL,0xdebc4777ea72110dL }, + { 0xccb7d9932e3143adL,0x674f3753ea8cd06aL,0x56012a7a051562cfL, + 0x961df68425f74cd6L,0x26630e71214d8a95L,0x584e8d6365d92f84L } }, + /* 8 << 175 */ + { { 0x8a89daefebc5557cL,0x7ca71403275e1649L,0x48d923775b80bb4aL, + 0x0a587c52a45b3626L,0xdaff503cc75bfe91L,0xd845d3e6116d07d7L }, + { 0x6b5a4715a51eeca2L,0x34ac02bd74481991L,0x8f076cfc595abf8dL, + 0xc9de4ce9ed0391ceL,0xaaaad03ae1fcabd3L,0x8d48ec0087b199edL } }, + /* 9 << 175 */ + { { 0xbd0f2653ae5dd482L,0x59f968dd060032dcL,0x6bea33e067283310L, + 0xccce88cc012aa50cL,0xbb6d7f2f66838f46L,0xb764c95f05ec9bcbL }, + { 0xd097b60451477ccaL,0xc2fbda7b82b20a85L,0x75fe07a424e9ca8dL, + 0xfc4fa8240cc40d01L,0x0b17d5f90c0e95f7L,0x285e6e8a6e1e46dcL } }, + /* 10 << 175 */ + { { 0xb0641d09bc9b2654L,0xf9fcc2e68aa8fa35L,0xd12a5b4b00d5ec6eL, + 0x9be1a1115569d89aL,0x9c0566deffac7208L,0x7a9fd4ff7034edf1L }, + { 0x636aeb6b9571c375L,0x60d05aec55cdf187L,0xf4e2f898734e9d2fL, + 0xdaf742195ccdc6bcL,0x9d39249f608a4f28L,0xb5f1bb5e8820e2c3L } }, + /* 11 << 175 */ + { { 0xd02e9936d9589548L,0x8f1bf5755341402fL,0x1535a443057300aaL, + 0x3062478e65d29324L,0x4203351fc656a3f3L,0xbeb21b516569c4ffL }, + { 0x8113ce70e1f0f263L,0x59d1293903f9320cL,0x95061255d08f8936L, + 0x8be3c0f997d4b705L,0x0259742e827837c2L,0xf55ea28d95c65cdaL } }, + /* 12 << 175 */ + { { 0x62024812603dc3dcL,0x25dc5337efd67b57L,0x86b3eb38d7f033fdL, + 0xee3226b232646d6fL,0x8c4825f6f1dae596L,0xd2303055a5bcb8e5L }, + { 0x904a53493c0baa76L,0xe60f6125e08646a7L,0xaf6a329f21d45f89L, + 0xf20ad88a06605546L,0xcf7a0e9619a93d14L,0xf1eabcc891c97174L } }, + /* 13 << 175 */ + { { 0x72b76e9e8f02af51L,0xac94cbf1d580f95aL,0x2e9cd74801d854a4L, + 0x4ed4e9061f08a1bcL,0x0a2b28419d2bd936L,0xbf86350051c89ddaL }, + { 0x9407b0e7e3f00bf5L,0x6b1f71ff28b57ac1L,0xc1dfe03fcd28801fL, + 0xf3d83d64afa55309L,0x47aafba28af8f76fL,0x54eed45f6604b2e9L } }, + /* 14 << 175 */ + { { 0x59edd2640f3e541fL,0x318674b582b76ba8L,0xbf4a0d304e7f0716L, + 0x36fc0e4119b88200L,0x91db560240da801eL,0x638371ad2c72c2c7L }, + { 0xfe960c25d5822da7L,0x7a7571d14a7415e1L,0x5a6480febccc1576L, + 0x72f4e5e5c3c88f47L,0x224e7e749a7bd8ecL,0x3ebbf52c7631455eL } }, + /* 15 << 175 */ + { { 0xae3c2bc08608ab37L,0x35e3da8c39f336b6L,0x7413664281f44511L, + 0x21ce7c511d8506e7L,0x9b6718b3846165f1L,0x9e455007f5cabf6aL }, + { 0xec582a0e02611073L,0x269aa18d83bf042eL,0x7c54fb7c86306757L, + 0x453336021b948fafL,0xd3a5c508b7025d73L,0xcd6e555b428471e4L } }, + /* 16 << 175 */ + { { 0x42c9fad511a224e6L,0x6b6aeb8b69b2ac26L,0x0cf4c7fdb149854bL, + 0x4a7d90002fc359ebL,0x9ff0c3ea29ec8603L,0x157ae7859b24ee14L }, + { 0x638c809a8979e9bbL,0x347dfb2e7869d8c5L,0x2fb1e0f8a07ea547L, + 0x1e580d32aecdec3fL,0xbbf895730f74025bL,0xeb94d71bdd529164L } }, + /* 17 << 175 */ + { { 0x8670812a35d03250L,0x2f68343f1984cd59L,0x5fe890caf1ff97ecL, + 0xd47fff536f764b2aL,0x70fa44a4f8f7077bL,0x7b287efcb2c7fe02L }, + { 0x0718e70806dedcdeL,0x37193c827172c0f6L,0x47ad55f67b7f28a5L, + 0xaf83c4fe9c71a96fL,0x2d6075587c490626L,0xe647de1b933e9033L } }, + /* 18 << 175 */ + { { 0xdc5909e3f1687d4cL,0x4fe3be46d431c5a7L,0x28c41a035f9807beL, + 0x2c4203fd12f1f8daL,0x13f12da450a19620L,0xc32f881eae2e9835L }, + { 0x56328ef7622587d0L,0xcf785f038f209f66L,0xb562ea70a2697748L, + 0xa762289055598769L,0x9842bfa8fbf41fd3L,0x304c3057fa401ba0L } }, + /* 19 << 175 */ + { { 0xb8d685d1c56bc716L,0x1eceb18f1fccc358L,0xf94bedc82034cabdL, + 0xa9acaf11ad003472L,0x6fea0a55ad0786c6L,0x60f7f9a9581f6f52L }, + { 0xc4736494400bcca5L,0x221d8f8a3606b047L,0x533756fb6339c7fdL, + 0x1e068e987510c1a4L,0x9bf9abb6ededfa09L,0x96895ce548d54775L } }, + /* 20 << 175 */ + { { 0xc995b0171552c477L,0x6f92a95252351781L,0xa9d4bb6c4da25dafL, + 0x2b02828e3cf6aab7L,0x5f4febed11fa4d0bL,0x42f0e61ea12d9d37L }, + { 0x1ceef875d24610d0L,0xa7c85c485d4eeceeL,0x33fcfa3b79340a49L, + 0x3671e563b00b3491L,0x871f74e493eade0fL,0x1ed095182c546f3eL } }, + /* 21 << 175 */ + { { 0xc003b709a9a5c68eL,0x9441e7b26c84310aL,0x7ec3b652dd90f7c5L, + 0x17e601685b526324L,0xc5f77fee479573aeL,0xe89beed18453fe7eL }, + { 0x259a2b0364540cadL,0x8c2f13322b9a8053L,0x1db53ab7304940edL, + 0xcf780c5d1612763dL,0x2edd7285e19b62f9L,0x20ddc9874abdd7a5L } }, + /* 22 << 175 */ + { { 0xa70aa6781250954bL,0xe4a2f7cf2930f3edL,0x3e3dd26666fd719aL, + 0x500166cf792ff463L,0xeccd32cd75cf00a6L,0xb65f46a5c4526e56L }, + { 0xfc3a99c360aa8cd7L,0xe04a18b31290b20fL,0x957139a218cb9326L, + 0xf6b352ce11fc04a5L,0x9314b80778534e64L,0xd4a265c52d8f5015L } }, + /* 23 << 175 */ + { { 0x7078b4820dca1fd5L,0xec3192daeed504baL,0x144183332d06a63eL, + 0xaff9f7bd69c01ac1L,0xc5fb50475b74308fL,0x37846eeaa67e7ef4L }, + { 0x0fcea663976b931bL,0xd3407d42bb345b71L,0x925afc36a2deb11bL, + 0x12c271092207db49L,0x237500002e1c8fbeL,0x41427e0763f771cfL } }, + /* 24 << 175 */ + { { 0x9dafbe96491ddae9L,0x92c60b897741da5fL,0x1185b001b866ab14L, + 0x7a43b9cfca7f2f81L,0xaaeb5efc6ee8fdfcL,0x1f7cc70022beba9dL }, + { 0xa212724722e3e7cfL,0xb98dde1e9e723477L,0x87832183ac89706bL, + 0xdfb92ac1ff72f1d5L,0x5877fe6daade3804L,0x7ddde4a79170b9acL } }, + /* 25 << 175 */ + { { 0xdb147da0b7df600fL,0xbef5374660a8b100L,0xb4c7e404a1330d14L, + 0x152c6ae754f96693L,0x08884fecb25fd94dL,0x8ec186048ba59001L }, + { 0xdc245c0c9f8e77fcL,0x2be5aaebc0f0a83dL,0xd15bdecd1fd13525L, + 0x46b603f0821c9224L,0x6b335a7daf6dc128L,0x4cead4f94dc6b5bbL } }, + /* 26 << 175 */ + { { 0x239cccd8179fac91L,0xffa076063829d42eL,0x75b8589cbd42a0ecL, + 0x012f5e80d7f2292cL,0xdcee7efd99c14665L,0x4925256d23650737L }, + { 0x847c86ecf3cc64afL,0xdd34a75feabc04fcL,0xc2f73b3ac6a1f710L, + 0xe16e317565cbf6fcL,0x9cccffee351461d9L,0xe3d635543b4fe4b9L } }, + /* 27 << 175 */ + { { 0x6e27de1176ece8f1L,0x3ca873a79d5a3cb7L,0x7d65cdff7e424482L, + 0x023e5bcf69372216L,0xae601c2f2ffeb5a6L,0x8c8888cbde130b33L }, + { 0xcb8309485700ecc4L,0x5a1902ef9dfe1891L,0xe01f5fc558198380L, + 0x9d5d1c476c59f973L,0xacc64c98e34cc41fL,0x057d81f03065d870L } }, + /* 28 << 175 */ + { { 0xf3a1a9797aeefd73L,0x3fb166a09537abf7L,0x39e8c469d4c37607L, + 0x3efc85650e3f034eL,0xc955c2dff9c25655L,0xd6ce96ec260fa449L }, + { 0x5383a8b831d8e6d4L,0x3aed2e761a3595dbL,0xbd269c39e22a0f45L, + 0x4c82238694a7a83cL,0x362f08055731bd0cL,0x7dc1e7ee0527be95L } }, + /* 29 << 175 */ + { { 0x606ffedfd41ce228L,0xb87608d0ceb21740L,0x6fa23c0794a4354aL, + 0x587a7c54d5061d84L,0x75678bdb16b823ccL,0x2d2163c94ec818afL }, + { 0xa80b1e4e22c6fcaeL,0xc07cebee4d2a4b65L,0x64f303c7a895e2c9L, + 0x750079f5a768a2e6L,0x0665502c2d423133L,0xaf33176715135cdcL } }, + /* 30 << 175 */ + { { 0xda8f7878c715abf4L,0xc62292a5a5830c4dL,0xfcd30f7e4b46acb9L, + 0xb931f1ee39a73db2L,0xf838a5c84ee1afb0L,0x15609b57c202a921L }, + { 0x2e21871620bbba58L,0xe1d2fa14ae2615cdL,0x0a4dcf3543946185L, + 0x2e80d804730d2490L,0x5e43dc17794246b6L,0x7b3588c8dcb3be9bL } }, + /* 31 << 175 */ + { { 0x3e74f09c1bb8e6e2L,0xac587847584dba0dL,0x926415593f843324L, + 0x0033257729f3ed18L,0x4b7164e5d0089537L,0xc50542793e54c9a0L }, + { 0xbae7ff9808e58162L,0xc0707d03c1aa2fd9L,0x43524f717714dca8L, + 0xa202a0707255b169L,0x0a7867ab4249b2e0L,0x03f748656d6ec5e9L } }, + /* 32 << 175 */ + { { 0xfa2db51a8d688e31L,0x225b696ca09c88d4L,0x9f88af1d6059171fL, + 0x1c5fea5e782a0993L,0xe0fb15884ec710d3L,0xfaf372e5d32ce365L }, + { 0xd9f896ab26506f45L,0x8d3503388373c724L,0x1b76992dca6e7342L, + 0x76338fca6fd0c08bL,0xc3ea4c65a00f5c23L,0xdfab29b3b316b35bL } }, + /* 33 << 175 */ + { { 0xd2437a52eddd4b72L,0xe2cec2abf051b831L,0x845af98e482a4ea4L, + 0x75758ccfa43cae82L,0xa76733429260ea35L,0x77845b02b1dd602aL }, + { 0xb78bc4c047d5c450L,0xcb1f444550ad371bL,0x6bc01293d71cc417L, + 0x8538f638c1fcb367L,0x5d01d35919b313f3L,0xcd6b55bfcf67f6acL } }, + /* 34 << 175 */ + { { 0xc28000d6e3b03290L,0x4dd5064a5f2ddbcdL,0x4916f830338a1414L, + 0x3ffb8381aca74c22L,0xec073ee8e680f548L,0xa34e0693a0430cc3L }, + { 0xc6baf20dca03e6e7L,0x2a30df6e835fb88dL,0xbf3c9e9cc2092d6bL, + 0x391cb25c17bc2433L,0x9b7de7126c205c0aL,0xf25e1494cd2a5e62L } }, + /* 35 << 175 */ + { { 0x05ae44e9d21fdc9aL,0xc520657fce40ebbaL,0x6b8e25431270cb59L, + 0x24e6f9bff7f096d0L,0xc6ded76a3ed81f52L,0x729d05e75f7df798L }, + { 0x99e2636fe5468eb1L,0x6f3abd4c00419facL,0xfc61117a9cc41e09L, + 0xb16f106baa399a51L,0x05603bc845e52713L,0x612658aca5c36107L } }, + /* 36 << 175 */ + { { 0x107573b96defe8f4L,0x9a9edf0570545313L,0x5df43df0e54e8272L, + 0xac91bae8eeb4ae90L,0x241d54bd26006ab1L,0x0ba118a6c031de7dL }, + { 0x376214671f500d4fL,0xbbd6b318bc3596e4L,0x4b5532c85992277aL, + 0xb15165da16a4728bL,0xbd7986d45140abdfL,0xf4fe16df7386f38aL } }, + /* 37 << 175 */ + { { 0x8c5d305696aeee65L,0xe52e500ea79991dcL,0x3af4a3ef343fdde9L, + 0xc6d0389b248ad10cL,0xc3dbdb3f5014de53L,0x606b1352310a0cd8L }, + { 0x65af3f8479bde08fL,0xa6c7d968d82ab682L,0x7262c07d202a6508L, + 0xd0231bb64cd75fe0L,0x58a34ca5dcb1f7fbL,0xcc8b21b21b8cf7a1L } }, + /* 38 << 175 */ + { { 0x4cd6e61be824653dL,0xfa02c0c9f253dd65L,0xab198e41b1e84cedL, + 0x89ce6aff1928be7cL,0xf2a83f4895afb956L,0x5b5f195ddc73f3a5L }, + { 0x44220ff79328317bL,0x03d62cb7f5239616L,0x0e908d34b5d49415L, + 0x050b7651c1f7e665L,0x3610167089e1a98bL,0x564abb3418eb7644L } }, + /* 39 << 175 */ + { { 0x400b363b2eecacf6L,0xe2ae5bee1ed9fb9aL,0x23374b11831e99c6L, + 0x0a8382d82cb9de95L,0xf95b8e052dc02291L,0x63b05a0d2f752257L }, + { 0x9ec16f84b60d9df4L,0x6ed683ac3bda5171L,0x7206450813acca39L, + 0x6024af3cf8871ba1L,0xbf88040e2f9a4d56L,0x001054149fb100e5L } }, + /* 40 << 175 */ + { { 0xd52c606375ccd2e3L,0x4fa8e4df56ce654aL,0xcd905c9bce581d23L, + 0x51ce0eab24ff75eaL,0x1c1c0831432c6e5fL,0xb83307aec02f0e86L }, + { 0x0b7a0274fe2ee821L,0xae7dd7729c3d69faL,0x54745da5931ed75fL, + 0xc276d96f18caba13L,0x142571dd26dd9792L,0xc522dac16c0e3167L } }, + /* 41 << 175 */ + { { 0xa86fa630197b5b97L,0x749ea479fa21c176L,0x520c0e4871ce7101L, + 0x5c53d9ebe30a0b0aL,0xdc71b629ceb570feL,0xa30fc3d11fa3699eL }, + { 0x741321b579cbbfa4L,0x205ea0aae8d18119L,0x94556e92fc62e0eeL, + 0x5ba78d4e042b9c3cL,0x14de84103fa24a56L,0x6e57a9fbd6557bceL } }, + /* 42 << 175 */ + { { 0x2a5e716ff103d9c9L,0xda2f7e5cb9cd27ecL,0x317f74b8e047e5cbL, + 0xf1f496d33a4413feL,0x1a480a9cb8cc9fdeL,0x502b52d7575208d4L }, + { 0xf14fe00cd19c49a3L,0xf5c2367b269be5a9L,0x966a524f12d42690L, + 0x2786ff714dd03b95L,0x6fa1f891d69bf68dL,0x0f3d77579f67b3bfL } }, + /* 43 << 175 */ + { { 0x230c8d00c966c638L,0xde5c9e8e54673305L,0x618b0dd561bc99faL, + 0x669618048f3cb5c0L,0x7c653ca507141ba5L,0x454d54ff32ba155aL }, + { 0x82665a307df3e39fL,0x15eb1a65ca19cbb7L,0x4e7632a617330ab3L, + 0xc69235295a3221b4L,0xe23ee9382eb58e9dL,0xb320aa8e23bcf88cL } }, + /* 44 << 175 */ + { { 0x6ba15fe607a7ecf8L,0x93127926f831cc91L,0xfde2dbf41ff6264fL, + 0xdf7f22018413fdb2L,0xdd81d11487f66260L,0x87907f0e4a87133dL }, + { 0xeac1032cb1d47e23L,0xe2603119125a0918L,0xba680392f2259208L, + 0xb7c7f8ebf9bf06b7L,0x875a380fa56ba57cL,0x05a88a97460c939cL } }, + /* 45 << 175 */ + { { 0xfb2871b7d0dc771eL,0xd12b21fcbaf358c9L,0x30dbd412df616c16L, + 0x291bd90f9345e16bL,0x92f7534b8ee6bb6dL,0x7ebc5b0eb1c901a0L }, + { 0xc9e9c76151e1881aL,0x5ca52152756bfecbL,0xb0a9f5cb6affd506L, + 0x4c12f965669feb3eL,0x01d84b9ea6f1c529L,0x3870fa27e8433c92L } }, + /* 46 << 175 */ + { { 0xe4e9e72495bb5db0L,0x86babe3ffd616958L,0xc1520c280f93c1cbL, + 0xe393ded539cab777L,0x031a2af3e86a6ca3L,0xb26a19101e8466eeL }, + { 0xb16b746dbb64fd81L,0x4e96f0b65a97d50eL,0x7a12a611a793fac2L, + 0x8d729847db6482aeL,0xdd050ce812e72ce5L,0x915041366c54299aL } }, + /* 47 << 175 */ + { { 0x9e8018c06b63c4beL,0x49dde0c8fce47904L,0x1668de9c9bae36cdL, + 0x8dfb0d5f80ed18aeL,0xfd6739a791e1949dL,0x80353c9f8053d7d6L }, + { 0xa611699bdea54710L,0x5eacf16e6c6c1f5bL,0x5212fbd3c920323eL, + 0xaf75db75848d085fL,0xb58564b1babb45b8L,0xefa1958938bc491dL } }, + /* 48 << 175 */ + { { 0x0a43a76c2f95a081L,0x27eaf2bc38b1c395L,0x6ba3222c63da1d80L, + 0xd95ae17e6a78ce09L,0xa72d9812508f03b3L,0x9f36d02efa8ed359L }, + { 0x1716d1dcd5118f96L,0xd116339f489bbc53L,0x272153ef6f7e1d3dL, + 0xcb4a9e739e308d22L,0xcfa9d88b615a3646L,0x8b69bd6cde454569L } }, + /* 49 << 175 */ + { { 0x33ae0fec2b8f41feL,0xc45aac500762c46bL,0xa03bc6ddf228ec44L, + 0x82cb78cfea3d48c2L,0xbe7a02ed27126795L,0x1a44d1f830b3e3ddL }, + { 0xb414edc73be7b58cL,0xb3e6c7ce331bcbc9L,0x9f6fd0f2903b3508L, + 0x260c8b5736cc2930L,0x8581a05d0d59278dL,0xfac1817b189b3005L } }, + /* 50 << 175 */ + { { 0xbf4d4640cc9a69c3L,0x07b39b5d67d262dfL,0xcd4a6a4579526d6cL, + 0x4a04c430538143caL,0x6c3341b86639e3b0L,0xd490cab5ab7216d4L }, + { 0xedda2b64a2a93161L,0x04e309de644a06f3L,0x7cad728a8c4495fbL, + 0xe1744f3871dd61f4L,0x39cbd782e3201618L,0xbd66e1850ca18ab4L } }, + /* 51 << 175 */ + { { 0x69d8237f87dcb8beL,0x3f9a485b090e0237L,0x535371e1f117a1c5L, + 0x0d5ef52675430c29L,0xcb9c150898fdd18dL,0xc7c1a7b4108d9383L }, + { 0x6ba9fb4d98064eedL,0x07d205a9a3df31c8L,0x7a0be62e9be5da37L, + 0x03b21b1255a9e2c2L,0x3f4792263de80449L,0xb0160ee1ae3bf31cL } }, + /* 52 << 175 */ + { { 0xa22c084a7a3f8c5eL,0xeb7fe23f3ef30511L,0x161ca862819fa38aL, + 0xe5f014156d45762aL,0x37da6bb95718b789L,0xfcb682bbd837f453L }, + { 0xc49c7397275e5974L,0xbe908df5a1ed0925L,0x3dcd694615a13ea0L, + 0xdbe652e32596fa76L,0x6a3bcc93c55d376cL,0xa2f7611933a0f02bL } }, + /* 53 << 175 */ + { { 0xdfff9b9c6ed061ffL,0xa36aef2dec32b16cL,0x9f3b7ab6da61572dL, + 0x96e72a027ac2dac9L,0xb0e36e023aaf4fcdL,0x5f32a620503004cfL }, + { 0x6c91dacbadcd649aL,0xb25deea21ac02a32L,0x211a421ffb914c2cL, + 0x1ddbd60e149fde1dL,0x91c4cc0d7ce86ad3L,0x8be6f031b9ed909cL } }, + /* 54 << 175 */ + { { 0x62e773c4a0cb50ffL,0xe54fdbdd2e903681L,0xed2bce9e21c12ca9L, + 0x13aa4748c072bae6L,0xb290c0ad475f290eL,0xcbbc3f9b56698a85L }, + { 0xfb37611b1b7fff76L,0xe62a842260bc2e36L,0xb6a36c783bb20fd4L, + 0xdec045418dd69509L,0x67648b7798a1ad2aL,0x4fa2005d078fdea3L } }, + /* 55 << 175 */ + { { 0x757f249416307553L,0x865af9d0de6bcb49L,0x3943031a07b0104cL, + 0xe5fdb46168da2d33L,0x4937d614b5432b48L,0xb3fbbf2c0a29a5e5L }, + { 0xe7d3b12b8de89887L,0xc1a43c24e41258c3L,0x91ac7eabf7d9efe4L, + 0xfd90de0088385cb3L,0xead102e37674c39fL,0x7b9a2cc4fff118c5L } }, + /* 56 << 175 */ + { { 0x11f92678a1e598f5L,0xde8052491fbb882aL,0x3730b3261154d0aaL, + 0x0e279827da521670L,0xa03c8c702336f8c0L,0xae50e64ff0bd66d6L }, + { 0xfbfd665f7af4f681L,0x237a4f4e5c8d5680L,0x6527611ba409064fL, + 0x1f4eff6a99db9a94L,0x4a55d96ae53ba177L,0xd9dec234f002368aL } }, + /* 57 << 175 */ + { { 0xbb837d0ad193ebc0L,0xab1e3eccd09b24caL,0x229f36d81d848777L, + 0xee895edf0ab68c98L,0x67fc65f4dce31b92L,0x777ebe585db96c26L }, + { 0xca0893ae6047d0d6L,0x71a2ca0b550d6905L,0x35426866eac4c2e3L, + 0xb4d7e78e0c1b8eb0L,0x03cb0a9a84b384e4L,0xd8a99a5c7f7115b6L } }, + /* 58 << 175 */ + { { 0x07db8bfa5f25a74eL,0x97dd568a3dd8e706L,0xcf4c02a32fb59efaL, + 0xe2ae502616b291e4L,0x5499f3b20f9c10cfL,0x59abdcf5a7297ec7L }, + { 0xcec282671f4a3646L,0xc10ae0971e065cb1L,0x172f886319dbbaebL, + 0xb0c27f7d73dd068aL,0x764d185495086ceaL,0xb89923c732de9a97L } }, + /* 59 << 175 */ + { { 0xacd499ca093345e2L,0xfbdb3895f3c23800L,0x2584f8ca02f0fadbL, + 0x9f5dc96ec2f35eddL,0x4dd102ca1ba0266dL,0x13ee9c8aa9f26fabL }, + { 0x9e7467fa2a1e61daL,0x999764b6850191c5L,0xd053a575b70dd8dcL, + 0x697b856fd7065eb7L,0x9d5bb6aa695b4914L,0xc5cdd170e65001f1L } }, + /* 60 << 175 */ + { { 0xe87cf622e93495f0L,0x347b09c6bb43a802L,0x2a38f3b7a4e3ac34L, + 0x13353b959751c1c4L,0x753ec3ecb3947985L,0x3bf856dc12d3fa90L }, + { 0xbf4f6fa5ec35dbe0L,0xd099a15bf3b4fcf2L,0xb348462fbfe7245bL, + 0x508324b352a2d4f4L,0xec4bae05feee1315L,0x468fa9e404496618L } }, + /* 61 << 175 */ + { { 0xc57673257d5e7a94L,0x40c05da604cefc01L,0xba1fd6c6b921c681L, + 0x0d3e09f9c104cedfL,0x4b7cd83cc6586416L,0xb747d7f9adfa7bfaL }, + { 0x833f8e24a42be782L,0xd5f0421d06b2471fL,0xac87b17c22e4b84eL, + 0x85af6b063a10c7bbL,0x4e557cbf66e88e2aL,0xaff21b66d3751e40L } }, + /* 62 << 175 */ + { { 0xdbab25f4c4464538L,0x3c36560ba93d7f74L,0x8b9b15d39f86f410L, + 0x1237e35b0a1db237L,0xc9dad97994f49677L,0x390a3d8f15dff99eL }, + { 0x0a74dfaef82c19edL,0x3f8e958589c2dc55L,0x763448ce94a8e729L, + 0xc6349398625f0517L,0x1ca5f9e7523dd700L,0x45aa25317fe638dbL } }, + /* 63 << 175 */ + { { 0xe91af601aad04ed7L,0x6f86f323e897df2eL,0xf8c259564c7a0ab8L, + 0x6e793f3633845d15L,0x08937ef5e583d043L,0x92dafa5824d1fd96L }, + { 0x6458ae2a86c9aedbL,0x271823a026a4252fL,0xb119fe4c5a57ef16L, + 0xf41e13943a507289L,0x0cbf1da6bd1aa499L,0xa177ac9dc2465a51L } }, + /* 64 << 175 */ + { { 0x14f962e404a8313dL,0xc6e3e7c45f1f5a26L,0x2c0e11c079e777beL, + 0xa1705efb4657c31bL,0x02688fd23c494de3L,0x75664a84412a8718L }, + { 0x878fc7ad7a422f8aL,0xe5d581df7419bd0aL,0x7c813c4c704b70c0L, + 0x98553da87323c008L,0x4f63cec663089f1aL,0x9626d6fa9655d291L } }, + /* 0 << 182 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 182 */ + { { 0x10586ea7507f8b27L,0x1510deb9a261f7d7L,0xa42fc4d7dfbfa352L, + 0xbf38c3821e1c2291L,0x46e40ef60e11760aL,0xc24f6061dcb974d7L }, + { 0x755b105ba7619027L,0x8004bf09b8ffa759L,0xa630d0b00945db60L, + 0xa160ac9cf2809e1cL,0x38fc1113dc6c95c5L,0x01f540985d52574fL } }, + /* 2 << 182 */ + { { 0xcda68a7e698ee21cL,0xc7414d196a5e725eL,0x483be2dadce20b91L, + 0x7de1601cfc69dca6L,0x4bec17aaac4f9891L,0xe8741dd18d479a56L }, + { 0xc623cb8dac23a286L,0xe20a96b5166133f0L,0xda9bb7c030dcde61L, + 0xf84ea3273a1733fdL,0xd7afb6c3e82fac31L,0x37ea7d35d3897449L } }, + /* 3 << 182 */ + { { 0x120649b20370327bL,0x0e76555acd48cdc6L,0x4ed54decca01db03L, + 0x7be21319ac601d22L,0xf711661901b6576eL,0x7839fa064e73537fL }, + { 0x169d43ace46e860aL,0xde6d658c3078eed9L,0x8df731395032142bL, + 0x6be199b09b3c76c7L,0xc2f385f6f8bbffe5L,0x848df7f3d5ffd28cL } }, + /* 4 << 182 */ + { { 0xa189f30fc6a6d6d1L,0xdd674d3669665ab8L,0x307c9ec37d8da76dL, + 0xb3e1d006c1ea7c10L,0xc15e20b3b88c62d4L,0xb0000ec50bff3b3aL }, + { 0x9e330eb19ff9aa5cL,0x8663f9fddf578877L,0x157d3cb002e1eb2aL, + 0x638f297bf525e4d4L,0xa20f833234a3dff1L,0x748ea86b45a9c051L } }, + /* 5 << 182 */ + { { 0x978ed3abe664c066L,0x3f4a8e0d668361eaL,0x0ba610c753a25231L, + 0xa8b5b864189143c6L,0x0d7ccefca2841fc2L,0xa80dd8f3f8fea1e1L }, + { 0x2c24af232e19028cL,0x0e332b77919decaeL,0x44eae977f6089c76L, + 0x25e04dae53722e9aL,0xdd6f8b1f71ac4db0L,0x7c5b6ffd075e7bc4L } }, + /* 6 << 182 */ + { { 0x4c6299a7a1de1cc7L,0x362d293c02d9445bL,0x08f24df0399a9494L, + 0x33307792e37a1851L,0x1cc5e448760f680dL,0x70a6a8164a2efbefL }, + { 0xee939681246fc671L,0xfa7a26d1f70a9c14L,0xfae5ca89b826aab5L, + 0x6b8932c7e48176f9L,0x379f89bd9841c8e1L,0x46141d2fdb674190L } }, + /* 7 << 182 */ + { { 0xf4408485b4619d3aL,0x34b4f18160b4f44eL,0x369edc1b3532caf0L, + 0x2d0471ec6771abc2L,0xca4129311013266dL,0x02e636af617e2024L }, + { 0x1f93d60d3c69696cL,0x6aba7f2a1b99a172L,0x896873e1bf435ce6L, + 0x9649f08215b71e40L,0x730bedcfa02b024fL,0xb17e9cbd8df60bfbL } }, + /* 8 << 182 */ + { { 0xfe9fdde8bc266ee3L,0x91668688ba18e6c7L,0xa65349acddde6f6eL, + 0xc53c29c97e54356cL,0xee15ad945709f73cL,0x033b3940e5429277L }, + { 0xf52035cdd0c3475aL,0x9c5bef4d93f1f1f0L,0x26e0b0ceca319bd4L, + 0x4e7eb67b6951fd8dL,0xac3a6f4395c34d6fL,0x1f2769e600f60b59L } }, + /* 9 << 182 */ + { { 0x95188c136c4d0bedL,0x377a04901b5271e7L,0x60db30226a540165L, + 0x4be61fda3310c5b9L,0xbbb4fbe93f8bbf16L,0x5232fb46ac12f77fL }, + { 0x8d6f75ab255b569cL,0x09cc854d3bd39650L,0xec17a6e74b557c3eL, + 0xd6949f9d5c3d149fL,0x9a17a440494b18b2L,0xc10cb9d5d4a024acL } }, + /* 10 << 182 */ + { { 0x4520be6b8eddc97bL,0xeb8f2c317391f948L,0x18fcbbd772369418L, + 0xb8950ee217246882L,0x6b1e4b7a382e82c2L,0x9e2bb1eb7ea4c447L }, + { 0x5202d913c3c5bc54L,0x53ea78cd21352716L,0x7bd53ffb36e6b4ecL, + 0x8325bdf817387196L,0x33b2cd8af94d6a73L,0x206bdec5e13db4bcL } }, + /* 11 << 182 */ + { { 0x6e27ce2609c98c86L,0x8f87ec4c958002c2L,0x00b6897064ab26edL, + 0xd2b4037282e5e129L,0xbeae654c78c48327L,0xc0632b4341a54107L }, + { 0x7b1fc7f001562313L,0x01cd1b5c1fd6a56cL,0xa199a69835e71626L, + 0xb02b2692635fbcffL,0x1c0c4200a0632386L,0x637164f8d6c670e7L } }, + /* 12 << 182 */ + { { 0x2c47010d18e30ee3L,0xb7d4b1dbfdd5f040L,0x5c8abe509d930f6dL, + 0x6bcf875d5f56cf04L,0x1f6456c0062f1fc1L,0xc79597805304d710L }, + { 0xd76452e4db85dcecL,0xd531f73fa0cbf90cL,0xb5ae9fc89021bde6L, + 0x505c6b9f4babfae0L,0x99d943c17ea61fd6L,0x6ef4766159bf125aL } }, + /* 13 << 182 */ + { { 0x3a48020daa0b0a5dL,0x4a32d4d658bad0dfL,0xe013dbde2e4340ecL, + 0x99efac69a5fc51f3L,0x26acf7a669ee64c6L,0x36672d6566fdc9f2L }, + { 0x77426caedcb879feL,0x0166194676e3be96L,0xb6fe4709b2dac331L, + 0x1f3d8a63678ff3ebL,0x711c0ea447bd5865L,0x5fbe38e87c080adeL } }, + /* 14 << 182 */ + { { 0xd0891b2df4e61379L,0xea2c7ceb9941c391L,0x1441a2d099677e8aL, + 0xc29d88c8abcb3669L,0xecb1a21a06ce9bd9L,0x0663fa7cf5b11fc6L }, + { 0x440a5a1c0c44c2c8L,0x08d71bc39fdded3cL,0x62b53ca512d33d2eL, + 0x3fb8640e005e8adfL,0x2a9acaefaa2673a5L,0x356ae6f6695f8448L } }, + /* 15 << 182 */ + { { 0xcf3c9b318496d935L,0x7e849aff8ceefc78L,0xfc06a46e7a5d692dL, + 0x87248699e89463afL,0x4dc55e5e8e17af3cL,0x3378832fe41ec54cL }, + { 0x7578d6192816f87dL,0x505845612806d3cdL,0x7354f1022754c3d7L, + 0x61ca6cac08d64863L,0xecde4969eb9954ecL,0xe0c211b4a1a5dae0L } }, + /* 16 << 182 */ + { { 0xbd10b8bffb787270L,0x4f0b1566e43aaab6L,0x9a18be5ec0c90781L, + 0x3677f4c71ad167ceL,0xccb254e2a68c1c56L,0x392493e6e2c4d275L }, + { 0x44958cb1d5b63617L,0x178f141a4caa4e7cL,0x7445a767a2ffdbd5L, + 0x0e789c99b0b6c22dL,0x3ff8b6565dc92b2eL,0x1623e5c3eca98782L } }, + /* 17 << 182 */ + { { 0xcb013ff62c5c50daL,0x5e5550b70b256dd6L,0x38249ee1bfd47036L, + 0x984daee275379fbfL,0xfb35304588c6bc7fL,0x32379c955f9683aeL }, + { 0xbcb4ac531b5a8626L,0x1057d2a3bbaa0deaL,0x114ef8a7ffa8efb7L, + 0x553a34566da90cbaL,0xa2ced0b21a365fe6L,0xcec4d64bb1ccdb57L } }, + /* 18 << 182 */ + { { 0xe0312b66b81fe0eeL,0x11e0493b892c7b21L,0xb6a1d76e624ce73bL, + 0x38768ec0cd75cb6aL,0x425b091f2032c271L,0xa88d39f55b5d8338L }, + { 0x1496b9ed1916be43L,0x14468e3054549f3cL,0xd429c2c47248e206L, + 0x21a1c212fc9e892aL,0x0feb5822640c984dL,0x0cabfb472b7c0c66L } }, + /* 19 << 182 */ + { { 0xcda1c4cd1cc5a20fL,0x33d66a893f67814bL,0xbba50d5360ce82edL, + 0x9d34dc4d70553a53L,0xc926f498a8a1442fL,0x9dfe3cbccbb43feaL }, + { 0xd25887434fd3e4efL,0x7443a9a9a371d894L,0xb53e6afaa22bb4f9L, + 0xcef3fa347dfc9da4L,0xd079ded047403836L,0xc6c97c36d39aa93bL } }, + /* 20 << 182 */ + { { 0x6618fcae534f6370L,0x1635580da1a864a2L,0x90ad39947d7ce552L, + 0xbf8c45895257f24bL,0x5a9499202098768cL,0xec1eb621bb6d8830L }, + { 0xfae8f161f1f9ac16L,0xfc9184ca35704c99L,0xa72b1ea9139ea04fL, + 0x82229a912e39e1d8L,0x4153bf3e479c7bc2L,0x83325be4c5541825L } }, + /* 21 << 182 */ + { { 0x358a91badbea81d1L,0x4d1947d7c669c7a9L,0x4ca6d8f18eedbfcaL, + 0xf9eda237069b3b93L,0x9e1217e5a35ea963L,0xb7e16f08ab960c77L }, + { 0xf440d825fb313db7L,0x804c5262101c5424L,0xd236a0edab3c4f7aL, + 0xf8bdb2b1c2682459L,0xfaa7aacaf46c4d70L,0xcf6ce4adae83dd7cL } }, + /* 22 << 182 */ + { { 0x2c7756bcbd452842L,0x2c47593cd1783fd8L,0xa4f41583a7527697L, + 0x2fddafbbd1049934L,0xc087f3db6c71063fL,0x8f5a85c4c9b3ef6cL }, + { 0xbe178bc966a975d0L,0x2e2d825b94066514L,0x061dd919e0d42ba4L, + 0x964fdcfb227ca011L,0xcb915b2973d7ba7aL,0xaa7f2fa72af8338aL } }, + /* 23 << 182 */ + { { 0xbdbb3440734e8984L,0x8b9b7acb3d6f547aL,0xfc4f48ea0e76a07cL, + 0x49758a9f97da0c23L,0x13f4254a26958261L,0xdf1fdca2adb3ef57L }, + { 0xfafba40d699460e6L,0x71b2de39cd5c94c4L,0x52d76b76c21cdf0eL, + 0xbe75960760f3dfa3L,0x519d4fcb7078f5e0L,0x4bd8ca7f5191e1b3L } }, + /* 24 << 182 */ + { { 0xfadf9be978207cefL,0x97d5ba569cb5718eL,0xcbad24ec2f995393L, + 0x6236a26861203303L,0xe4bafc336589a4beL,0x6cba77185e23fa82L }, + { 0x8ccbc5774583e65aL,0xe5d88bca4bc2f415L,0xe6bc2d5841df8dd1L, + 0xec24e1d914d31fcdL,0xacaaf13efc26010bL,0x7e1da447e01b92f3L } }, + /* 25 << 182 */ + { { 0x2b3477ec1a29de39L,0x30a5c2190a8720eaL,0xf593ec729775bad0L, + 0xaaf607792af7dbbeL,0xaace90d4c7cc7b59L,0x6eadf21d40509cf4L }, + { 0xb9a5f138096d00fcL,0x3896d42625b206a0L,0x0f28f0f09dcaa5dcL, + 0x2ef6f9f9a8186106L,0xd212710fe25b4d04L,0x0cc6d2878b9847b2L } }, + /* 26 << 182 */ + { { 0xe7407327cdfb2baeL,0x06745198510c3039L,0x8a913ba74da758e9L, + 0xc882e7bb1a4797abL,0x0f0d8eb5dd7b375dL,0x90ac5223dcff3f3fL }, + { 0x8443b7cabbe341a3L,0xa7cba7f22f173bbcL,0x04669ff830e5c327L, + 0x0edd0eac09b777fcL,0x2a70898bd71e0cb2L,0x881c48929bd983bfL } }, + /* 27 << 182 */ + { { 0xe4847c654e7603f4L,0x826cd33c0bbea366L,0x95727caf2c4ced28L, + 0x580313dedb8ac1e8L,0x6745673701363cb0L,0x540c35ec0ff13cc9L }, + { 0x878c86fe3c4fc263L,0x4d81f8aed14e7c78L,0x6f7cf97e8355ef22L, + 0xa2aadbc848a0aef8L,0xe0200ecf4fc3c61bL,0x7e58e6e0c8094ab1L } }, + /* 28 << 182 */ + { { 0xc52789bbf2d3bdc6L,0xd38673fc3b23d7a0L,0x8b6df95aacafbbfaL, + 0x37afdcbdc7f6eb6dL,0x57775bdd6cb4c9d7L,0xc34e5a2711007453L }, + { 0x903e5ba1b5faf98eL,0x811e142a9d4a8a45L,0x046d18932d7ac9e4L, + 0xe2fe9d1543ce66a8L,0x44b5beb4d4956410L,0x7c5f1b9ebb147f72L } }, + /* 29 << 182 */ + { { 0xd51033f48312b074L,0xc98fe29456f898d7L,0xa8d6433be8eeebbaL, + 0x50bf170976fdbb84L,0xdd95f89d43c14baeL,0x13f9c7366307bca5L }, + { 0x3cd12e2855e7bc8fL,0xe2d7482c3a52581cL,0x12a2c6c7b59eeb8cL, + 0xf98f79124ae87ffcL,0x41eb808e80d7bf65L,0x589970f2015e20adL } }, + /* 30 << 182 */ + { { 0x200a764a6333b070L,0xa0acd8ecdf0d20d7L,0xbc1c589953269941L, + 0xed7c9192b439eca8L,0x057c50eeb789f0cdL,0x31dc2d36a9c794a3L }, + { 0xe3f2d38dd58ef984L,0xdb250da69235b084L,0xc2ff1b49da05b500L, + 0xf2ea6cc50387c539L,0x8250353a3d1004cfL,0x69103201aed0bf97L } }, + /* 31 << 182 */ + { { 0x495cd7fc878e97f8L,0x6397fa8b61120b1dL,0x20b9afddc8708907L, + 0x84f55bb97be2ee80L,0x996fcb9d8d075b5dL,0x2e94d95ead858627L }, + { 0xf786143e77113ebaL,0x6fec684f7b3fdb28L,0x4be44fb211d10d07L, + 0x4b3478e2372f16b6L,0xec8d61614697ca58L,0x097d241c3a45f335L } }, + /* 32 << 182 */ + { { 0x6f6a6104899ef333L,0x95496f6d39067165L,0x42fd9a6ab51989e5L, + 0x1b60ce0f68f5b168L,0x97324d8756f7fe67L,0x443812f7676815a8L }, + { 0x265ee994685a7260L,0x342c7b2f6c6515f0L,0xe909232334b4adb0L, + 0xddcd233e1e5a8d18L,0x3dc5b27c5f4f6456L,0x9664533a7f421d9bL } }, + /* 33 << 182 */ + { { 0xa55e8ab09a35f4aeL,0xf908fb35ebbadf5dL,0xf885d61b35fee31aL, + 0xb8047f4f82728fdbL,0xa6fe454d33c5bc34L,0xdc5266332ef52e54L }, + { 0xb2f524a931581251L,0xb9eeec91aba760f4L,0xa95d396624a9b423L, + 0xfd52f4d29d3d75acL,0x82719e78834d4c33L,0xeeca71fb3840ca62L } }, + /* 34 << 182 */ + { { 0x984658940f4c60e0L,0x3929d4c645ce7c0cL,0x7846d6c19c4f9b89L, + 0x2c38a9b20fbc695bL,0xeeb4799ad73d4bb2L,0x7c16e5ba4e3b5520L }, + { 0x11ce92e51cf310d2L,0x0910dcc91e037725L,0x159fcef85fc5af9fL, + 0x4944f8ee1dcb3ca5L,0xf5d9f8c0b9a4516fL,0x452f0fa2f1cfa6e0L } }, + /* 35 << 182 */ + { { 0x59b15b61c634aab2L,0xcca0742a620df0b6L,0x791d95720d345276L, + 0xb775b790cd3854baL,0x944e591a256c26fbL,0xc5fda2d0b8fe17d9L }, + { 0x7dba5830c0aff69dL,0x46f7164b0f7c6d60L,0xd767cd58549eeb83L, + 0x4498b4f51ff2da7cL,0xeef2caf8fc594b0eL,0x88dc39ec5f0a95b1L } }, + /* 36 << 182 */ + { { 0x1a57d3e1b3fe597eL,0x1a3ad06d18d1b6f0L,0xf70f27b32e4a4617L, + 0x55e8a0479a75b4adL,0x0b24d5beede15d86L,0x2b3c41d0fb2f56b5L }, + { 0xf6cf36aab1d36456L,0x418a72fe1d8ff434L,0x64149a0d156746bbL, + 0xae65897c4e3a26d6L,0xb75e87d21e68eefdL,0x5b81e0b01cb27c91L } }, + /* 37 << 182 */ + { { 0x2c3fa19b34b90671L,0x369c9e9aa7c9aae3L,0xd89dc03f3d236ad0L, + 0x280c47b9588ace95L,0x0ad071be57f25a96L,0x36ce641d8296279cL }, + { 0x321778128595511dL,0x51878842b52cb227L,0x720df7ab4156b413L, + 0xccc71e10fed25819L,0xc878554e3fde679bL,0x9c50ecbe3b565d48L } }, + /* 38 << 182 */ + { { 0xb2d66f1ffe23ba35L,0x82339e2914b273a4L,0x454a5f0b58c2be97L, + 0x0ebadaa68488ac1fL,0x3c635442517e9af1L,0xa87044c3a5b9fe2bL }, + { 0xb8214dbdb505ae0bL,0x05a9bfad60bf4393L,0xb7b64b42428a49ceL, + 0xcad71866bd2283f1L,0x5bcfe7fce33a3a22L,0x018a2121fd6c73c3L } }, + /* 39 << 182 */ + { { 0xc4471fb02510a1c7L,0x542e73bd2c1c35c1L,0x0bc8bcc4f028a46aL, + 0xdf87cd2bb5610f25L,0x0845e4d1df42b41fL,0xc0523e3593aba84dL }, + { 0xc9161e8ed14887b0L,0xa96f9b3aa68c235dL,0xba1427a46f94d5b5L, + 0x6a5fdbbc858e00f3L,0x8170bad6abfaf661L,0xb4b9dc0ec9f4abedL } }, + /* 40 << 182 */ + { { 0xc48bc829ff7543c0L,0xc0bda14c4d72bfaaL,0x2f470ec703be0af1L, + 0xc70f1e8e92d37eb4L,0x08abdd98418f410fL,0xe38c74ab35386176L }, + { 0x9c07cfdd8c00426cL,0xba74c310a998f1adL,0x76b45140b7d2dda8L, + 0xa52b5e584948330eL,0x9b7332348d8efb26L,0x5d1763735d19a312L } }, + /* 41 << 182 */ + { { 0x46950a441d38ade1L,0x377fdf593058c7a2L,0x5e2fa1681aa129f6L, + 0x2eae63dbc5fe1745L,0x9616fee275545475L,0x4073a79c8627b2cbL }, + { 0xf1ec69ea9a5198e4L,0xe9a906aebd2821d5L,0x193a9387bc22625bL, + 0xca468d717b6c67ccL,0xb4d11cb360f17a73L,0xcd801a0e3df1cabbL } }, + /* 42 << 182 */ + { { 0x1b80b9c386cf5a12L,0xa5bcd3a016349cfdL,0xcee36e8f00d1edb5L, + 0x9566e10a5b7bf29bL,0xd0db98cfd4ff0a0cL,0xb516605e7fe427d0L }, + { 0x099066c18e614e25L,0x63537fbbabe78647L,0x5601a8b420117e1aL, + 0xfd125e2f06df05acL,0xa7fcbd420948daeaL,0x55ad4ee28ff03220L } }, + /* 43 << 182 */ + { { 0x18d71671da2c6332L,0xb38bf94f98ee4e23L,0x9b90bf72ecc579e8L, + 0x5af93aab1bf6b8c5L,0xdad6e7909342613eL,0x5a1d49dc710ad0ccL }, + { 0x2013ed8801468036L,0xb8bd31cf2f0f6f9fL,0xf025eb2aaac961a6L, + 0x1e201f659e1adb43L,0x2755f3aeac7e5132L,0x72d8e1d0f5205d31L } }, + /* 44 << 182 */ + { { 0x80bba9170319fec4L,0x4ba44600aaef6debL,0x83285b613594f325L, + 0x8879183753b5765aL,0x651b4c6adaf1b02dL,0xccc17578825f609aL }, + { 0x0b4076b39fddc6ffL,0x286e2daddf2fa874L,0x46c45233c413b648L, + 0x4fa46969b7cfe0abL,0x835786f3e04f5e5bL,0x526292a90ce3f707L } }, + /* 45 << 182 */ + { { 0x9928e9eb83f17723L,0xc38d5de26c2306aaL,0x3dd3f371558b3989L, + 0xfa4b194877154d39L,0x89f437e4b89f5448L,0xd5531444a6437c9bL }, + { 0x65a6874092537cd4L,0x5f6d72281246fb09L,0x0db0b3be58539e37L, + 0x1f0dd43df50f4143L,0x1aa12daec215aab3L,0xf82820fb7fe7b225L } }, + /* 46 << 182 */ + { { 0x32c6bf5e56cb520dL,0x74dc46c41569fa1aL,0xcbee46391ba52541L, + 0x5e2f511a50ec4575L,0x90165e35032b6f53L,0x2b8f1f8a5544c780L }, + { 0x95baef65c6b50147L,0x4e9db41946b7fde6L,0xe2463226f7afa6feL, + 0x4d70932235409eb4L,0x8faad8937c20aa0aL,0xc8c95a85abc1ab65L } }, + /* 47 << 182 */ + { { 0xd5f54ce676d1f996L,0x55957500e595a0eaL,0x9b62e1fd92c72af4L, + 0xb4803bc3069bf052L,0xb7cdf59c686ebd16L,0x2d1fa780655ac6d2L }, + { 0x6c306d3edca404f5L,0x24e9d7a9a7b5fa9aL,0xe4c080ddc533c701L, + 0x71d16b63425e29e3L,0x81c00db32d993e49L,0xb59f87f577902ecaL } }, + /* 48 << 182 */ + { { 0x43b58def987cf64aL,0xc95b16c63d4bcd4eL,0x5d1b1373bcd9b923L, + 0xaf560542522e052bL,0xc2ff8f7583800352L,0x11723aa17fe2a4eaL }, + { 0x28de7668e94bd9bdL,0x0ce80e0f874018a5L,0x0fe3755d8d43e726L, + 0xa78296acf9b075c5L,0x76d58d9882207423L,0x5c5bc6971db99205L } }, + /* 49 << 182 */ + { { 0x9cbecc969e2aea70L,0x1a3fd38d7e4f2a84L,0xdc35e3c84b95e560L, + 0xd5e912a5aa21d2e2L,0x037866628d8cd601L,0x4b726855f2bb35e6L }, + { 0xa45a827a0d763ea2L,0x17d6e5ea057bceecL,0xdab2381d09a2a2a0L, + 0xf1880617e9aa76dbL,0xb86444dbb184c5ecL,0x23a0e4b767da7c23L } }, + /* 50 << 182 */ + { { 0x2d94a6f030df736bL,0xd1ce20050b3be2bdL,0x201352b55e288cc1L, + 0xdbd3dc57779644a7L,0x9f258b16d191db2bL,0xd83c827fd1c123efL }, + { 0x74c5126e17f04f0aL,0x06008f14966e620fL,0xa4406ba80aaa9e37L, + 0x27323f797faf87eeL,0x43380a672b1206a1L,0xab1ed1cfaf15ebedL } }, + /* 51 << 182 */ + { { 0xa3d2bad9bb22cc74L,0xfe6591a80e2b9221L,0x8c94c974d3cb4eefL, + 0x772694266beb6451L,0x2942737a010986e4L,0x920c9dda59c1ace3L }, + { 0xd31af336da61e1d3L,0x973997a118021018L,0x50a6c8425710575dL, + 0xd61d47c9ade9d8a0L,0x90abe8f8a85f458fL,0x23cc28a3ac4d474bL } }, + /* 52 << 182 */ + { { 0x283d5bb63e052e69L,0x149ac3d01bd300e4L,0xb4c7b96ce0582ccaL, + 0x66102883428cb7d7L,0xd3eea16b500958dfL,0xe1b6a74f74674893L }, + { 0xe3b284be3fb0522bL,0x74b0fe2dea983a60L,0xd4328e5c81e465d8L, + 0xecb534c7403173b3L,0x1721e22774144d34L,0xb7273c6aa88a5141L } }, + /* 53 << 182 */ + { { 0x0ea24ac64018877dL,0x265cbfe42acf249aL,0x811c17e61837d63aL, + 0xff453f5d6b3adf1aL,0x7add0621a3031529L,0x62105dc838af1d27L }, + { 0x2cd31a899b56ec62L,0x5f524be5ede7bbceL,0xc485b2ff66a044f5L, + 0xae28f5dc87a7b274L,0xd41989a93415b6c5L,0x3051ca44c9c43ad1L } }, + /* 54 << 182 */ + { { 0xc22046bcfb50bf2eL,0xee22fb7b78f7c548L,0x5c41c6bc2b5b4563L, + 0x56da674a8bf9259cL,0x3732f77433d8d4c7L,0xa90bf0472741046aL }, + { 0x5ee7f4396288c2e0L,0xa7a1fec99ae621c6L,0x523c0569b76e955cL, + 0xda0c2b378d1e8601L,0x9010bc349559b56dL,0x8d2fab0917b8d9b8L } }, + /* 55 << 182 */ + { { 0xb2caf938281b021cL,0xc61f3abf1404b0abL,0x24203e1cea26d902L, + 0xc84f07e10d34906fL,0x8ba3d589f0cf7520L,0x86b54f6d9a2a90caL }, + { 0x9f87234f3d77a667L,0x328941966e3fa8d0L,0x0921b4a6e994d49aL, + 0xe77e9f8b8b3495cbL,0x9e5b74798da1fe56L,0xcbc09ce7b070591eL } }, + /* 56 << 182 */ + { { 0x583ee7dfe3b7e746L,0x0b6659e4a4fab3a8L,0x34ee02751946db5dL, + 0x5ae3c0ba1a12eecaL,0x36756ed44ccb83e7L,0x973b0861a80eaf3aL }, + { 0x969e38f46982ca90L,0x9a9bcd10018d01fcL,0xb540e9533272476aL, + 0xcf91dd0a75ab7002L,0x2c7d363f39ceb983L,0x4369c221974747c7L } }, + /* 57 << 182 */ + { { 0x32c5b289642be172L,0xe5cc452e697e6a30L,0x344935e10aa6841fL, + 0x9eb2dc4faad907a7L,0xaf77d029e121d0c0L,0x2bcddeb08bb073b8L }, + { 0x3584dee5e40653fdL,0xe853b6337605f214L,0x4723f0add4bab900L, + 0x16dddd27fbf91322L,0x1f96d7e610c525b2L,0xdfba535200c998abL } }, + /* 58 << 182 */ + { { 0x701e8ab819df9ed7L,0x1a6d74c13e2159d1L,0xe82127e0fc61a470L, + 0xaa2e5f33dd15316fL,0x92b6ea927c42c081L,0xfd470a298522aef4L }, + { 0x0c54a067e5ccf152L,0x60c113eda1a079b5L,0xdd501a8389d6e6b9L, + 0x3dbf20d219792456L,0x633cd2b710bf70edL,0xace5327a0aa8e5e8L } }, + /* 59 << 182 */ + { { 0xed79a2de3b2a8a4aL,0x02851125cbf095c4L,0x6817ecd1880fd3bbL, + 0x72acb6ff066adfe0L,0x04fd696d66ce8257L,0xb644f098dc81958fL }, + { 0xcab55d1525218005L,0x1184b0a64de70465L,0x6248e1157aa96b53L, + 0xe30958630516ac32L,0x19f80cc0d07084ceL,0xfdf7ca2efde86c28L } }, + /* 60 << 182 */ + { { 0x9a8857568bc1783eL,0xb373e5a0a7cf2ee3L,0xdeb162fde46cc503L, + 0xd5d334601074ef35L,0x0030f98eea159a90L,0xc5ffbdde64e50d98L }, + { 0x85a6486a48195b26L,0xdbf56597b1b9f2d6L,0x5df2352ab8613aebL, + 0xc425807ebd0189a9L,0xcf5a34d4fa1f4f7bL,0x233e26c7628fd2ceL } }, + /* 61 << 182 */ + { { 0x6c4dd28313a1e482L,0x24bfc23bf803f1ceL,0xb8e795b2f426832fL, + 0x636d2d63b13fcb5fL,0x2dbca0b214a508ecL,0x1948c957c1ff2b70L }, + { 0xc9d7cd4ae3135c7aL,0x1bf41de75d7cfe18L,0xfff9428f2f6cd5fbL, + 0xa25d3e8294d640edL,0xecdea1583e4fec66L,0xff3b2b1555530798L } }, + /* 62 << 182 */ + { { 0x483565313178cbc6L,0x085a31143f3a1ff0L,0xee2a58b11dc7054eL, + 0xa9ce7c113287d5e6L,0xd283d22c8fa263a1L,0x9160bb8be77ff147L }, + { 0x21dabddf918caf34L,0x6921e987ad1a9f13L,0x47e45c7d3ba0ad41L, + 0xeaac63192bd18585L,0xb88881060818034aL,0x2d8e9c1b60be0a45L } }, + /* 63 << 182 */ + { { 0xad3e46af32f4625aL,0x5c2f95dd88371d5fL,0xfc7a9adef2415ac6L, + 0x77a23c424ad85440L,0xce7c63712f4dd730L,0xd65bdc45a5c9f380L }, + { 0x763d3990cf11ee6eL,0x7b2a927a9ffc522aL,0x65ccf351deead5c5L, + 0xef1fa99cce4d076bL,0xdb6f5cca6708ba8fL,0x361525a0f3bac7ffL } }, + /* 64 << 182 */ + { { 0xbfc40c30f893a2caL,0xdf96980e0623bad1L,0x4fd7b54dc027511cL, + 0xf4799284cf3484ceL,0x655ab811069beea5L,0x52588bc87392e280L }, + { 0x522e7b404f0c17cbL,0xc0d88acac705e9b2L,0x9cf1b95877f3913fL, + 0x3e06b9267dd52514L,0x992e920e2908cbcaL,0x13baced26d6ed529L } }, + /* 0 << 189 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 189 */ + { { 0x8a46c911bfc6c637L,0x8dc3d699e4fa4fe6L,0xd4ba64f15cf8e4c9L, + 0x01b3908a01cb3488L,0x69b1fa5d38bd7dedL,0x92ad483818b2eae1L }, + { 0x619324beb33955b6L,0xc7f373355c8a6df7L,0xa397f42e925b3f69L, + 0x32169a495f7e4d11L,0xc0fa9a548d0d9f01L,0xf52a1f2289d8f2e5L } }, + /* 2 << 189 */ + { { 0x9c0d5231ba8e0a52L,0x94d0509e93e465d7L,0x67df90dd98515454L, + 0x223e8b9c8dbfb46aL,0xf39529a36d757ce3L,0xffec9175b4648296L }, + { 0x330749e8f78aae7bL,0x19e5549645f93cc3L,0x8c320b3494083aa8L, + 0x1161f5a321e321c6L,0x0980deedde3e7892L,0x605aa9196ad76cccL } }, + /* 3 << 189 */ + { { 0x71191262062312e3L,0x84c82a94691f46faL,0xad4b344bdda57f44L, + 0x674b758ac4f0cfd2L,0x3bc058a077543efdL,0x3d7c765756618d06L }, + { 0x95107c744dba9e44L,0xe59c3180cfdf1923L,0x5dbeaf35e3f1d63cL, + 0x012029c643ab8726L,0x4f588a4ea256c6fdL,0x14a01b7a3e5d2e30L } }, + /* 4 << 189 */ + { { 0x73fa3508180660f7L,0x4cae013e2d24936fL,0xf64a549f58493d98L, + 0xd9ceae0adc79f602L,0x6569e37bd1512b84L,0x11e4c022151c9151L }, + { 0x075678c2b55c5813L,0xb26cdb5809d3cb16L,0x6334dca3a57fb969L, + 0x0ed90820223dc3ceL,0x74f9c3aebd11e277L,0xaeefed3679c0b8e2L } }, + /* 5 << 189 */ + { { 0x22195e48e57ac6a0L,0xba77c58214bd1913L,0x265f96b4323349b5L, + 0xc183196ea124d497L,0x99f1f78d2466d82eL,0x185a18bfc6263afcL }, + { 0x29a3d5b686cf8908L,0x81f3bc00f680511dL,0x5f6ffc81661d015aL, + 0x31c2ff64cd5eb082L,0xc3c37ad672776042L,0x49438769d9c6ac75L } }, + /* 6 << 189 */ + { { 0x0e2fc74c2a24c385L,0x836a474034679278L,0x25518f16817e2c41L, + 0x8b573a8eb4b7d3c1L,0x012797f94ab56adfL,0x9e0e56d0fa2ab690L }, + { 0x009ba1ee1c9f6f08L,0x8ebf4aac2f412e9eL,0xb143122a1cfb4e02L, + 0x988cf0eccbf2b783L,0x44a7ed9657f5be97L,0xbdcad87251804147L } }, + /* 7 << 189 */ + { { 0x969fcd982f60d1a0L,0xf0f4c9b2ef06b3ebL,0x8c6438cb49ec8f92L, + 0x746107773f1653daL,0xf7cbc899b574576aL,0x758de9008494795cL }, + { 0x73045065ab22cf9fL,0x9893653c9ff13e98L,0x6e8860264a58d64dL, + 0x387d6cc34e3bf554L,0x82a49da4a42b0008L,0xb28bd9b71b0b1c47L } }, + /* 8 << 189 */ + { { 0x378205de2f9fbe67L,0xc4afcb837f728e44L,0xdbcec06c682e00f1L, + 0xf2a145c3114d5423L,0xa01d98747a52463eL,0xfc0935b17d717b0aL }, + { 0x9653bc4fd4d01f95L,0x9aa83ea89560ad34L,0xf77943dcaf8e3f3fL, + 0x70774a10e86fe16eL,0x6b62e6f1bf9ffdcfL,0x8a72f39e588745c9L } }, + /* 9 << 189 */ + { { 0x97e6400574103b65L,0xdad518d6db50ac66L,0xaf96065961077d1bL, + 0x1335de0a5baab1f5L,0xd404db749e444a1cL,0xd3124c5027d5fe2fL }, + { 0x1f20c68a0bd49e9dL,0x44405e6aad6a1654L,0x287d565193c362a9L, + 0x301ec6a2e76661bfL,0x4900f9b54c6f9927L,0xca3dbc3464bf3909L } }, + /* 10 << 189 */ + { { 0xa96955b9b1bafbc4L,0x8dcb55a7646ece39L,0x2b62784feb00e541L, + 0x462f9d7d2693249bL,0x8b264697794c189dL,0xded6ff5563354e69L }, + { 0x7c8ea441eed1089fL,0xe355f75c1462f461L,0x87b691f61210fd5bL, + 0x7291bffb6983cb27L,0x9ed83afc92800095L,0x307a3dc81f24d923L } }, + /* 11 << 189 */ + { { 0x9f79814a45faaa0cL,0xc64a7ac93bb1b07eL,0xaad6ff897f2ad506L, + 0x43da948300b83699L,0x6a702b8d6617956dL,0xfcb1035a7981052bL }, + { 0x094acd48cb230926L,0x3c3249d05da96800L,0x934088079d7208c8L, + 0xe4f04014d738a48dL,0x49bc5f0bf18b06c2L,0xf854285f596b9befL } }, + /* 12 << 189 */ + { { 0x7cec60ead7804b2fL,0x0064464345c11441L,0x3c6de88b769cd685L, + 0x34709186c7f01232L,0xd9eef41eedd2bd0dL,0x3bafcccde427faa9L }, + { 0x33e5350ec07e701aL,0x9cb2eb47a87c1fd1L,0x9fa9a7790d5f5b28L, + 0xa2e7076b07ea2e53L,0x72f4da325c169cf4L,0xb7f192947e751588L } }, + /* 13 << 189 */ + { { 0x1a3b217d2f6d700dL,0xcbbe9349ed335d55L,0x428adbfb53ff169aL, + 0xbd74385214793b47L,0x2224e2569d9460a2L,0x8408600809982ac0L }, + { 0xae6c6f9934447242L,0x63c78b2b9b51fb67L,0x381c948a389593d4L, + 0xf4cdd09f6e79ee72L,0xc658428ba185a0b6L,0xcd7562a786fe4c6fL } }, + /* 14 << 189 */ + { { 0x47eb133532dd7a30L,0x9d058169a9db654dL,0x375c59df6e7a2b1aL, + 0x55d37c677a35f29fL,0xc78a3678493c4cdeL,0xe5f0e2d68d83e31bL }, + { 0xf7927002e9777bf9L,0xdd559324a5afdfc7L,0x077c6c48b81c08ccL, + 0xba1c98ccaa2ef694L,0x06c6c9544c02dd46L,0x211e50f37dd3145eL } }, + /* 15 << 189 */ + { { 0x7f985fa8a96aea53L,0x811f94dc480b38d4L,0x91fdd510f3d40c68L, + 0xc156312ccd763693L,0x24b544c3640057dbL,0xd7d5d4f5ad3b5a1bL }, + { 0x5e235a1e26cda8a4L,0x0cf7b7cd1d2c6f17L,0x17b1ccf0908d3107L, + 0xf32f2a06f555eb5cL,0x274f7c2cb3c278c6L,0xcf1eaf296af1b44dL } }, + /* 16 << 189 */ + { { 0x2a5f8ecf06616d0dL,0xca9b1cb8c7deb373L,0x9de31cedc59c4301L, + 0x1e0f40b10111d998L,0xd29d229f960d5b95L,0x10563249d1dabab8L }, + { 0x7b225cc9a05ecac9L,0xb02e689678f3b8a0L,0x009b52a1f5fb06b2L, + 0x8a575d3f842b9081L,0xfddb48afe9272512L,0xd39b8f1d0b452cb7L } }, + /* 17 << 189 */ + { { 0xb6efc7e167ba9cd3L,0x5a642c288e4f62a6L,0x214a63da364378edL, + 0x582c59944121c53cL,0x840277facc9a728fL,0xc6db3529f8f72d39L }, + { 0x9c5cc2760aca9955L,0x8558a58db8b6dcd6L,0x709226acf0701f24L, + 0x6ce95b21ed248b40L,0x32ea565b5487934aL,0xa75a688496f9ddd1L } }, + /* 18 << 189 */ + { { 0x0d6b9c7c67e09987L,0x261a564d0761ad52L,0xec4621749f60925bL, + 0x83ee0c1218529b03L,0x72972467fbcfff74L,0x37fc074c6abc4bfbL }, + { 0x8b6015bd54e65e89L,0xde8583eb991583cbL,0x379548e1b4d2c62aL, + 0x88024a9a9b24a5e5L,0x633aa869fc03abfcL,0xa27657b98fa35283L } }, + /* 19 << 189 */ + { { 0xb340993c5727e344L,0x2379f51d4f3295d5L,0xa5de3efce2929734L, + 0x7d2e2c82d8717e3eL,0x8f24abb67180db1fL,0xa5060d648a4ed876L }, + { 0x8d39e3a2761110d6L,0x38d30c93a3bb5b66L,0x07774ac3c12fb741L, + 0x7d4ae5a55f4425beL,0xb9848a2afa704922L,0xed9ab68c4cd00812L } }, + /* 20 << 189 */ + { { 0xde9703b461d9e770L,0x02d4091def4653efL,0xefd229aa576eb5e1L, + 0xc0b0b243f77eb987L,0xb11309b2eefe8f71L,0xfeeacf2f68478044L }, + { 0x8dfd8e8643ac3dd7L,0xc0a24181b07f95c3L,0x551ca09624be161cL, + 0x6cb2c1d4b098cdc3L,0xbfc74e9be74f84f8L,0xe58e14d9067e3388L } }, + /* 21 << 189 */ + { { 0xda121aae0ef98506L,0x435f28c6328e636eL,0x64b2170a720d40a3L, + 0x3ddb0e61cd24a844L,0x111442478797c7adL,0x624e7f73d589dd37L }, + { 0x3e7e0ed0a8efdd25L,0x8de031f116509a5aL,0x1330cff5873488c2L, + 0xa80c60b3342ecf75L,0x9d3742c8e62550ceL,0x8ec9b229e46475f9L } }, + /* 22 << 189 */ + { { 0x9eca6f94f025baa6L,0xb2db0741bcf9c741L,0xf8e2aab590bb8f56L, + 0x4772903208762829L,0x067a0c5ae2a266c8L,0x22b104c771b7d7d0L }, + { 0x4a48cd6953e406dbL,0xb85e44d524f0070bL,0x6168262fe10133ffL, + 0xdfc02315e4874e8fL,0x20dba2d7ca317e3bL,0x441c56d2e1d2c0c3L } }, + /* 23 << 189 */ + { { 0x9ebd10d6c444a2fcL,0xda7683e3f18ac11aL,0xdd42ed990fe8e59fL, + 0x9c867debee068909L,0x32df043fccc77aa3L,0x377423ce4aaa45acL }, + { 0x960940524a90c535L,0x48bfe83347d1799cL,0xe8cd1a55ccabd174L, + 0x2ee0a276682145c3L,0x4249297e8d606c00L,0x22021ce2fd7af6d3L } }, + /* 24 << 189 */ + { { 0xae10069e808dc4b1L,0x64df30e18fb3ba73L,0xbbe4caf27ebaad0bL, + 0x5907bf373dd6119cL,0x0a723dff9dfceefeL,0x59bff4ddf7cffc7eL }, + { 0x7bc95fa26a6f43c2L,0x9001d1d53ca0e2b3L,0x316a7ecd27b3335bL, + 0xbf08e6727b8d7d49L,0x4b209f93c619058fL,0x4c0ca01e59d8f9eaL } }, + /* 25 << 189 */ + { { 0x3c1e7f45bad772b1L,0x20f6f1732544af67L,0x14f491f9a7d6544dL, + 0x1451cc8e6acea162L,0x20c8ffa5d234ab89L,0x4b59bce1f5cd1002L }, + { 0x99da4c0ee63027acL,0x6290cb963fc1f75eL,0x3a51774524c4d85cL, + 0x3bf9929c1fd144e7L,0x9bcb97467068294bL,0xcb0b3e5d2e61a022L } }, + /* 26 << 189 */ + { { 0x18c452c4cae69c3bL,0xf45690acef0f00faL,0x3b363aa04f66a5ccL, + 0x9dd41c0a47718c52L,0xfa219d7e7e5cd370L,0x5d384db7b2196dfbL }, + { 0x5e14749b90b4d46bL,0x55796656d9db9481L,0x3bf13d0ac8cf353eL, + 0xb89a28a6a95c485aL,0x568fa3d05da29783L,0x4aa008eed182b1a4L } }, + /* 27 << 189 */ + { { 0x4f38667a179639e1L,0xca492d50ba7c7a16L,0x191e4a3478fe9dcdL, + 0xa3cddb2f03fc70b8L,0x57d90a90a751ec9fL,0xcf88357457a50cd6L }, + { 0x69abd86d7cc58687L,0xc73a00408466bc6cL,0xfbb99c755c495208L, + 0xdd5f1ab9c13347b8L,0x9ae6fb92060b93efL,0xd6bb56a3588e5369L } }, + /* 28 << 189 */ + { { 0xf7e1ed3bb09fa8f3L,0xbb4fe6f71da5be9eL,0xcbab0e01f4d1ba21L, + 0xb732741076a5f326L,0xd94d2349206092afL,0x739f3cd0728e0e4dL }, + { 0x568644aaf81fd823L,0x510cff6b6110e2f6L,0xef4cf1ac566c3598L, + 0x2c26f17162aae69bL,0x1e4360468964a2a5L,0x83c0bbf63e472c50L } }, + /* 29 << 189 */ + { { 0xc198c07064b2955aL,0xc32d41e1d8d43284L,0xfb6f0e2c9f4fc13eL, + 0xf4d5b60b41c61889L,0x5c79f500beb36946L,0x328b22408ca4beabL }, + { 0x64058e916697617eL,0x6bdf7409f43f7390L,0xf2afd208f5bd8512L, + 0xc0000aa0bd1ad6d6L,0x38b8e03bd9f6c1c2L,0x0a34680d665a2d06L } }, + /* 30 << 189 */ + { { 0x79c04804aabd965aL,0x9581aab443d0b660L,0x59bff0035ba71d23L, + 0x212ecd58b6a0cd80L,0x29bdcd33bf1ea5d6L,0x59fd2ff477a002e1L }, + { 0x3c9d21308d9cd247L,0x790e9dbcb1786da3L,0x967ee5e714464d04L, + 0xd6f7ebbd2b5373afL,0x1c0b22d539768d40L,0xdfb54983913f6cc3L } }, + /* 31 << 189 */ + { { 0x5c9808b78a42e002L,0x5cdb2b070f732854L,0xdc92b1676d6d4579L, + 0x789dbb8ebcc22c54L,0xd76b2d40716eb28fL,0x5cbaadea004affd8L }, + { 0x5d4d84dd08fcfe12L,0xd0f1d7ee20d4b893L,0xc98d77dfbbb90db6L, + 0xbce9a5a2b1e29a22L,0x71a6835d0b54e100L,0x0199594a55b1ac68L } }, + /* 32 << 189 */ + { { 0x167ec88a51b3f1ceL,0x19756ee0420024c8L,0x10f2e2443877e634L, + 0x6321bf2603462cb3L,0x1dbd10ee9d3afceeL,0x0726f5f22ca17dcdL }, + { 0x094652660bacf018L,0xc92a9f2de1feb969L,0x0043b0f95e1c5912L, + 0xa09b94d1757d3a63L,0x533956529fdef1e0L,0x9826886cd4fedd41L } }, + /* 33 << 189 */ + { { 0xd22bcbee51964ceeL,0x3ed80af3b0eea46eL,0x263cfa026b854aafL, + 0xfa4ad481b9ca3b51L,0xf8c569a0b4451297L,0xeafb78f8f48059a3L }, + { 0x86a9e3c037093acbL,0xcfb3bb63275ef52eL,0xc4672d3c7c924f03L, + 0xa87350871691be3bL,0xf124f3a52be289b7L,0xf45052dc6b80b6c1L } }, + /* 34 << 189 */ + { { 0x79c99f99a010db6dL,0xe83088a74ee93fc2L,0x76e8376d836b1a7dL, + 0x8cab091c4e24e127L,0x5c98a00f7283cd21L,0x1beaf4a084997647L }, + { 0x2cfb55b8d934088dL,0xca24052cee724d5fL,0x5d6e9db5bba84289L, + 0x133414b26fb26d72L,0x3e844eb9cb12a503L,0x5eac12dab53d6496L } }, + /* 35 << 189 */ + { { 0x79a098812cc6698bL,0x6d44e7577f383e02L,0x1969f93785b5f732L, + 0x3061f62792acecccL,0xa9428d60cc2a4752L,0x69a472af2cf58626L }, + { 0x63fde53cabd347d7L,0x138b5b6a1aed4fd3L,0xd93fce1f2bd48519L, + 0x957fe302e49cc436L,0x9b51657a2e21ad5fL,0x3b5c4cb6acbd3af6L } }, + /* 36 << 189 */ + { { 0xdcfa78b096dda000L,0x5b60dfe5be2303bdL,0x7a6bbd34c7c6ad6fL, + 0xd45c9cb57012b97dL,0x9a049e36812e1662L,0x723bc0b66a5483aeL }, + { 0x7fc03b6ad1c82e81L,0x02ddd6d2b23f6818L,0xe8914b2d30dae39aL, + 0xf4f0ae392f692056L,0x198a31bd45f1390eL,0x917ce4f4f542565eL } }, + /* 37 << 189 */ + { { 0xde39a4e6ca447864L,0x95a028f9f0b131ccL,0xba77ac314a39c4f7L, + 0x0c24d09614857939L,0xdeea56edfbfaa0fbL,0x79aa342f4c920bf1L }, + { 0x50228f48c7e9dc62L,0x0fd9d1dee0f0fba3L,0x3fc03993cd703f6bL, + 0x229a3bf4c5ff39fcL,0xa7456aa484f9cb20L,0xb01bb5a7d12fd7d9L } }, + /* 38 << 189 */ + { { 0xfb390be4539519d7L,0xbaa98a2a6ad44d22L,0xafd19a75ef89de1fL, + 0x1afaef2971e27781L,0x18b297d79887739fL,0x8fcff6048e6da42eL }, + { 0x17bfc1717e861a36L,0x1467800537a8843bL,0x2bc47afdeb16065dL, + 0xcc038e2fbab7b4fdL,0x9d8fc42a3eb9be7cL,0xfc2f0b295928da63L } }, + /* 39 << 189 */ + { { 0xa4e33ca261c14fbdL,0xebafe73fc0a87f99L,0x22fdf1d1f5abf7f4L, + 0xfc1da26549a6b956L,0xfd8c48e5be25dd72L,0x9fd6520ad31a25aaL }, + { 0xe0167d4ffd14dbbaL,0x8838d2ba7370153cL,0xe5f7d69b133fdda1L, + 0x31acbf8de1749b60L,0xc14ec9e2107558dbL,0xb06d0252b99553acL } }, + /* 40 << 189 */ + { { 0x34590975ed424438L,0x7c03ce744d11a200L,0xcc939a286ec406eeL, + 0x8d214276fee5454dL,0x66a0e1a56b257f70L,0x93761a8a006fb85eL }, + { 0xc44f9df2aa70b65aL,0x1dac524f91d9e2e8L,0x5894a8224fca1a81L, + 0x8586e418f3ed85bfL,0xd494dfb202899b5bL,0x7ea9f222ecb8e371L } }, + /* 41 << 189 */ + { { 0xd93ee716b0958516L,0xa91f39db3eb86888L,0xb472c1e2ac92105eL, + 0x4d88a307429ca094L,0xd3fd88027a8e87e1L,0x40c4cd50126a2cf2L }, + { 0x046ce3bf11cf2046L,0x412678ee05691999L,0xea0c78168d3a2921L, + 0xd24ae89924f3c66eL,0x2c4457f00bd144e9L,0x82005b4fd7a52270L } }, + /* 42 << 189 */ + { { 0xf1b3ec32924340e0L,0xe5430ea3b33a05abL,0xbf43b031807629b7L, + 0x53c9407d57014039L,0x6e67b52f2f195ce2L,0xc8cc645f1e48d8c1L }, + { 0xf2234275c08f2122L,0x9cfe3c74c2f233e0L,0x235e6b349c4e0af9L, + 0xb4e8ef5770de39d8L,0xba573a727f73d0a9L,0xe12c506a18587ed2L } }, + /* 43 << 189 */ + { { 0x6b9669c59cf3e4f6L,0xa472d5dbff677559L,0xde845b0c877e5590L, + 0x9f7ef5802d0e2350L,0x87ea99d4e78c1096L,0x213243e9abb68028L }, + { 0x0172c81595e71abaL,0xc2592a762ca34c65L,0x50749aee9dc286dcL, + 0xe37d10884055de3eL,0x3e5a93bb90d652baL,0x0cbb7a08c32aa3e6L } }, + /* 44 << 189 */ + { { 0xe0bf3d8a026c43cfL,0x091956cfeb702508L,0xfcd486c9a6b3203aL, + 0x94a6d52f365460ceL,0xefeb5400563bec77L,0xbe6baa9619b2659cL }, + { 0x116f71c34bf21a00L,0x83d1c99a86d21871L,0xff1ba96aca0bd547L, + 0x5eb0acf741b94afbL,0x1be5d66fb1aaad14L,0xb8ececc5e6cd6d4fL } }, + /* 45 << 189 */ + { { 0x65f6e29dec7d4de8L,0x082fa0560e938c79L,0x4cda3fc925a02f04L, + 0x77dbcf0d3bac5cadL,0x625f9bd859145bdbL,0x98b7fd64553a11f3L }, + { 0x621bfbe387dd8a45L,0x6519421d1c35176bL,0x89eabac6d5ead4c7L, + 0x45c68bfe54acfbd5L,0x87cd244a84f30b68L,0x83b5f6b27b39275cL } }, + /* 46 << 189 */ + { { 0xd43b1d3c0ed0ade8L,0xd60b1ae7640e7d37L,0x965489e6f88e06e5L, + 0x35398ac89653417dL,0xed1e89ac02cfcfc5L,0xd127f68dbb6f2bfeL }, + { 0xa569c59fe22bb079L,0x7933f14e4ca8e9deL,0x68b4964a30033c3eL, + 0xab438cf88f069045L,0xa64f3a1516163059L,0xf40499c14576fe42L } }, + /* 47 << 189 */ + { { 0x361c28da052567f7L,0x8a2c6aafe0db84b6L,0xa79eb10cabbc87d3L, + 0xeaf7bfff4141b3acL,0x90bba4a953aacaf8L,0xda577661c35f9564L }, + { 0xb2550d0dd4487a5fL,0x69d43c5199638269L,0x6d16973f7a1f8ac6L, + 0x3dfb2253c71e4a4aL,0xafd836aefa36168cL,0xba72fd1faae6dacdL } }, + /* 48 << 189 */ + { { 0x690c0cfeb449d1e2L,0x4a5e150b1b8e1577L,0x22508042204d98a6L, + 0xc87a97f5bad2eb08L,0xd307c59ed25823eeL,0x6ed083580df8b3f6L }, + { 0x280ae344314e7016L,0x6a55be876ef4e889L,0xea930e5a24d04e38L, + 0x0269d9a7309830fcL,0x41dc8f0ae4afeebcL,0xfd1bc660f14ee02dL } }, + /* 49 << 189 */ + { { 0xf81cc943631da366L,0x2e821eb85ab1a2caL,0x339e9e4765433883L, + 0x3dc14370e1f60c71L,0xbd6c79bebc25b506L,0x2bd3ad51a8a639f0L }, + { 0x7c168f13c700a293L,0x64fef4fc28b4ce88L,0x3ccdc3080c329c6aL, + 0xbfd78932b76a9452L,0xf0c123fbc684f4b5L,0x8bfad06432305ed6L } }, + /* 50 << 189 */ + { { 0x208a668feea1a9ddL,0x8af75caeab903f09L,0x356208b449265292L, + 0x57b24ebe53faced4L,0x9c8aaa7303694920L,0x1c06ef5ad2f90179L }, + { 0x794ead99df92de87L,0xad900c4e7a73fe9aL,0xdb66b9ae715d9f66L, + 0xd19dc46db1bc2950L,0xb0a5af5c24c82c0aL,0x7d83f950371d0ec7L } }, + /* 51 << 189 */ + { { 0x716071e3abd37656L,0xaa22858be6cab564L,0x6793a66f5aec00ccL, + 0xe2ea5401e025da6dL,0x3998ea5d2eb0059cL,0x4ff6f442e39abb77L }, + { 0x703eabdabdb6e0f9L,0xa33e6deb38522433L,0xe23c13f6ca83c2acL, + 0xcfb8e57c0cac836fL,0xd0f84bde7692714cL,0xb4fc3b01f3f41d29L } }, + /* 52 << 189 */ + { { 0x67842ab4d8f358a5L,0x70cab57540e2fb69L,0xdebc3046e5c458e4L, + 0xc3574cf47eb004d5L,0xbac261a1c86f20f9L,0xc1bcb661deccf7fcL }, + { 0x5b3b96dec5574e9dL,0x07b878b3e151fb0fL,0x2f2d126cd38bd5f2L, + 0x06c951e8319597c9L,0x5529be4424ed0027L,0x82dcacc2ba8d7acbL } }, + /* 53 << 189 */ + { { 0xc37eef0149311e82L,0x3d07aaad401d010cL,0x934e039e53417831L, + 0x70775653da895ec3L,0x206b80af625cbe49L,0x9e2a4ee1e53ccb36L }, + { 0xebeace45c8ca6ff7L,0xadb19bd9925302deL,0x951bfcc497dee154L, + 0xd09882da79b60e1fL,0xb1e9cf0cda5f2516L,0xc2b697295e4def97L } }, + /* 54 << 189 */ + { { 0x74ce542d04f860e6L,0xdc8adf8fa3c48075L,0xe19852232063f76fL, + 0xf651c9fd5cd9ff61L,0xd4cbea69bab39ea0L,0xb6d4749b28fe3443L }, + { 0xaa7747ec65e960ebL,0x1a1b7b65e132a213L,0xfa52901f402a50d4L, + 0x3e4d2da68d43700fL,0xbfc7322937d45181L,0x68a812f9008bb845L } }, + /* 55 << 189 */ + { { 0x226d4d233e4cbf5dL,0x36359f52576243e8L,0x032af38a39a1999eL, + 0x9b59120a687eb228L,0x85c56b78e68e1498L,0xa7a14bd4849d03d1L }, + { 0x9e7177b345c4c3f1L,0xad7e4975183bd846L,0x42418d9a42f69dc2L, + 0x218e8f8e4f52cac6L,0xafafa7649f1f3214L,0x32f6f72b747f7592L } }, + /* 56 << 189 */ + { { 0xefca7f7ba6c53c1bL,0xcb4bb33c524457a0L,0xc9eab87fe57d08dfL, + 0x48c01c2a7d9a1967L,0x11c97ed97dc27492L,0xd8c644861cf1f639L }, + { 0x541f8c0d8156576cL,0xdf5c8dff2384e299L,0x9806935ba6be190dL, + 0xec6c5de764494b4eL,0xf04e2d4cb83c00b6L,0x379af438c0b84f15L } }, + /* 57 << 189 */ + { { 0x64e6289d92bbc1f8L,0xe88b78c5a0620121L,0xd01bac79a0fbc373L, + 0xa2e7986af098f07cL,0xfcac4dbcc5911218L,0x2e2bf56db337ed26L }, + { 0x878d9819e89a73c6L,0xa7df4f5768df46d2L,0x74bf7e2f4b3c9568L, + 0x2f2b187aebcce535L,0x544f18139a4c2be3L,0x3a5fe300a5938f0eL } }, + /* 58 << 189 */ + { { 0x901a14cd70aa91aaL,0xf0b6e1ec7f0b0a70L,0x6fd1ee0156a8bf9cL, + 0xe7e53c6693fbdadbL,0x18ebae68e17de706L,0xf4107457ebecf636L }, + { 0x77a85ea4a9f6c696L,0x3ea193e17dd9e3adL,0x9497e0a9f151c8abL, + 0xcc9237497a1dbf14L,0x2e36740e8f9be59fL,0x1b1c7d7c4a249e51L } }, + /* 59 << 189 */ + { { 0x7a45af2242cdcc53L,0x3061d91b8682832dL,0x85e080f6c375030fL, + 0x3ea6dcd1418440c7L,0xe0559870d14b6537L,0x36619215d178b45eL }, + { 0x48a4b452dcb85a34L,0x79cf4529bd5504bdL,0x506215e9e9c34c8eL, + 0x961f74b6dbd00e2fL,0x473d1397cbc84ddbL,0x6c64f870a8d67cb5L } }, + /* 60 << 189 */ + { { 0x519a6edb91a9b99eL,0xc0ea29e0f19221eeL,0xde83e0f77dc193b2L, + 0xa7b33b6044be16f6L,0x7edcb49406c8e8d7L,0x9f9dbb86392c0ef6L }, + { 0x09aefe035726bd5eL,0x782d8350c4e80b7cL,0x14e41a49186b80e9L, + 0x9af13703499ef97fL,0x5752877f2cbcc336L,0xdd0f8583d2df624dL } }, + /* 61 << 189 */ + { { 0x1cd2be3f32f6b0a4L,0xfd5da4a90114bca5L,0xc322a6a198a39a66L, + 0xca411eeb10d64384L,0x7c5d3ed0c72d8b6eL,0xf20c76697481309fL }, + { 0xaa4e45dca155872dL,0x66e41d54b87c1e51L,0xbe2fe5e6a6bfe6b6L, + 0xf60ca33a08a4d3e7L,0x45c1ec8c7211b48cL,0xdf44d3b573b78f7bL } }, + /* 62 << 189 */ + { { 0x21eda67429a1e6acL,0x33118990422ce5aaL,0x236aa9ec27326810L, + 0xc42dff9e3be7b318L,0xbe4601281690755fL,0xa395509d8c1c60c6L }, + { 0xa36de79d05b991d2L,0x55f516a3632882d4L,0x4c8c5a4296d1d493L, + 0x56199648533cda6dL,0xf9c6897a603bbfeeL,0xae835160f9857cc4L } }, + /* 63 << 189 */ + { { 0x700bad58d6aa9618L,0x2ad7069c05d54c73L,0x7f3ff5992f6a8495L, + 0x39de751ee26e6720L,0x39126d97d4cecf54L,0x353e00e21523aca4L }, + { 0xee905af017a33178L,0xa30173d31daf2642L,0x24cbbcc728f9169dL, + 0x4e65bb13a7039e69L,0x004a11859121e44eL,0xd4efa5b91c1e60beL } }, + /* 64 << 189 */ + { { 0x2e75a26eec65b53eL,0xfeb630b270552fb3L,0x53dfd057ee7d8e4aL, + 0xb959110d8994f449L,0xb4a16596bb538367L,0xa70917bdef82f29cL }, + { 0x5a76430043bba6aeL,0xee207476cfbc194aL,0xc7eab23803a4184bL, + 0x60c67ef20f7fcd62L,0x41e05799dfa8a0c6L,0x5d7d05e604d352b0L } }, + /* 0 << 196 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 196 */ + { { 0xc97c01eb436b59f5L,0x1d15aca7ef1848abL,0xdba1ce807fa7d3c2L, + 0x69e6f96e81060874L,0x6e3e0df74d7eeeadL,0x8a3b5e85b0c87f3dL }, + { 0xc55ae3dbc8a23914L,0x5cdc2a92bf6d27d9L,0xa6008c591de7860aL, + 0x8202f8b66e546731L,0x652f2d07aa1e45d4L,0x146f214f6df5415aL } }, + /* 2 << 196 */ + { { 0x041c706cce5fb4d9L,0xddc78cb3b22a79a7L,0x7dc4cd27839e9d5aL, + 0xdfc9db83bf3c4c06L,0x85b8094138b7bd22L,0x1007dea2d0f4c2daL }, + { 0xd7b34006c633fba0L,0xa8880acf4476e55fL,0xa340b2c275236685L, + 0x5ddd05510113a85fL,0x7dfc7ab29cb32704L,0x9a334a33dabf22ffL } }, + /* 3 << 196 */ + { { 0x2fbce9bed7d1146bL,0xcec9e5d8b3980bd2L,0x48ea45939f4cbaf0L, + 0x56c540092574a3bdL,0x84a39630e792c39aL,0xe5c690f8eef81343L }, + { 0xf996760f17655bc9L,0x6009c2156c0c191cL,0xa0ca12e6966d7027L, + 0x92a6d5d52e6f7c63L,0x46809d269bd13eadL,0x3c11fa7967aac681L } }, + /* 4 << 196 */ + { { 0x3fc9b3cfabe2cc87L,0xfd8d64e3514e77feL,0x2003a58afe1ad535L, + 0xcec4be38cb39149fL,0x4d578c99bdedf470L,0xcd35d7a33a356519L }, + { 0x7a762f278b078d6bL,0x3b6891ed31ae2701L,0xdc0e817f270c508eL, + 0x5a7be2049fdb29c8L,0xfa1a0be3cb2711d3L,0x5865f55f3786a0c2L } }, + /* 5 << 196 */ + { { 0x1d0af6b52f641cffL,0xa932adeb3648c4a0L,0x67641951b1ea8fc4L, + 0xc0b90064b1fae482L,0x7012642f6623477bL,0x1cddc0245bf019ceL }, + { 0xca1f4675c2c32737L,0x11525a5e97d6b18cL,0x9c034ef2d3868de9L, + 0x0533d921044e0c18L,0xba6cf14ecb5e38c3L,0x438309f3509d7053L } }, + /* 6 << 196 */ + { { 0xe164268ec4ff9f0bL,0x6c8e9349e6c36e63L,0x734f979478ab17f3L, + 0x46d468de0179ed0eL,0x7e68f006dfa26867L,0xe4d4a85de3d0485dL }, + { 0x0913a1d7f84c0f8fL,0x4095c8c025a9c9cdL,0xeeb1a79e49eadd08L, + 0x433f5e417dd8f954L,0x70a6281430bb26d0L,0xad94d8f6ff5e8e29L } }, + /* 7 << 196 */ + { { 0x6a352b579e32c0a4L,0x5274a08277ec7a40L,0xee1f7c7a240e6dc5L, + 0x85d5be62d313b4a9L,0x1522c5d25c01a405L,0xcfa08aab960afd5aL }, + { 0xa3cb77f38e8a93dcL,0xaacb16766d1c98c7L,0x84090c7d3b93fa9dL, + 0xc77f1ee13c0383adL,0x461c93b776f7a220L,0x66d63a1d04ac0bfcL } }, + /* 8 << 196 */ + { { 0x3c7d6b644751207fL,0x65e1f96ae440c1a2L,0x8ed15d20aa0eaa1eL, + 0xe944ad2fc0eab490L,0x71525aa1f6d9f260L,0x5cd14c8816146ba3L }, + { 0xf940190814a41275L,0x3bb7ea742288618dL,0x6a4e1c37cab1060aL, + 0x357fe4d0c8cac96fL,0x97a8b8ab6a2466ecL,0xb6e83fdb9c01be70L } }, + /* 9 << 196 */ + { { 0xa55a7142cb09a69cL,0x0a39fa12896a9c24L,0xa7131a001f6c9c82L, + 0xdacbfae97509c912L,0x3793d4ef4232eb57L,0xb63d9fc0da02ac15L }, + { 0xf1ce48a09ab37492L,0xa388dbb5cf9ddedbL,0x7224ef47fd7b2aa4L, + 0xdfe18be82fd35ae0L,0x2286ae7b90a2e98dL,0xd06cfd71e0d3c2daL } }, + /* 10 << 196 */ + { { 0x7825df5c948663a4L,0xc8c093adeb4ec9ddL,0x677c51ebc1505989L, + 0x8c28421524041f43L,0x0f63f15ac9ef610bL,0xcb98841d257678c5L }, + { 0xc0560066c52c64acL,0xaf7417db954180e4L,0x935c08876fe1f0e7L, + 0x8fe556ba46d03a88L,0xec44271484a0c4a7L,0x431f8e8395be9544L } }, + /* 11 << 196 */ + { { 0xc1fc18cb3101ce6cL,0xff753902048e52fcL,0x768299554e58e21eL, + 0xac990acc32856d44L,0xaac4d5dc9f8a9da8L,0xca1740fdd4be9e8aL }, + { 0x59250846892d8bdaL,0x45f45cad19c97c71L,0xf29e2724e6ba5c87L, + 0xe441134473f6a778L,0x9f4f9027a0f278faL,0x11bb7ce02bdcef71L } }, + /* 12 << 196 */ + { { 0x0cc553bb9b3fd7ceL,0x2e0ff43ce103b562L,0x96c01f0328222a3fL, + 0x7dcc5593c10171c0L,0xc677366a4b3e5858L,0x872d4396bde4eebdL }, + { 0x5d0c5f3a7f83c0b6L,0xbf4274dcf7ba33d9L,0x1df6e4811a635f83L, + 0x24e2e8347d807292L,0x792203a8eee1e676L,0x20475f907ef4e8a4L } }, + /* 13 << 196 */ + { { 0x1b4db0579e37cd0dL,0x61b95bc9ebccdf79L,0x7d98d8537a57d7adL, + 0x58a3d639709b0194L,0x45fbd4417ce5bc31L,0x7684b71b5b3c856aL }, + { 0xb311f8f85bb6bd1aL,0xaeb8e44711eda59bL,0x1ad5b35fbf269cffL, + 0xc69651b4a0e2a640L,0x3713803bd83ad8b2L,0x613ca3af0e4b353cL } }, + /* 14 << 196 */ + { { 0x3ac59b1fff8cf495L,0x3f3726866b04c4dcL,0x2cdddf90da325f0cL, + 0x3ae79666444cabe5L,0x8222f6d6c7484b1fL,0x61fb08929ae328b9L }, + { 0x279aae392c575c0eL,0xac694019948508bfL,0x4931cc55b84056f1L, + 0x75927a688b50ad1dL,0x47ba72e945584371L,0xbea7e62ea79fe5e5L } }, + /* 15 << 196 */ + { { 0x990a6767faddc25dL,0xcd7650eb114eaf17L,0xf9d1d6409a44cda3L, + 0x70996b6871fb091aL,0x630ae9754ff80816L,0x59a9dc2f987b20e7L }, + { 0x9a39588ef65fbbc7L,0x71f4c8e598e7c78cL,0xad2f5a0138cd40acL, + 0x3c68fe575a837332L,0x7af44087155e6b4aL,0xd66f4cf8e99e31f2L } }, + /* 16 << 196 */ + { { 0x5b0b5d692a7aecedL,0x4c03450c01dc545fL,0x72ad0a4a404a3458L, + 0x1de8e2559f467b60L,0xa4b3570590634809L,0x76f30205706f0178L }, + { 0x588d21ab4454f0e5L,0xd22df54964134928L,0xf4e7e73d241bcd90L, + 0xb8d8a1d22facc7ccL,0x483c35a71d25d2a0L,0x7f8d25451ef9f608L } }, + /* 17 << 196 */ + { { 0x81e304c903b37e31L,0x21781e57925a6491L,0x4ecbad144b9250d9L, + 0xb395914345cae8feL,0xb894a39dbf775d4fL,0x8a2c1090d307e272L }, + { 0x49dfcee9408bf3cdL,0x08f0f33195b573dfL,0x23eb8a0b214bcd3bL, + 0x425e1cde7ccc4d82L,0x53f64095ac113d2bL,0x377a6cb3d88e0761L } }, + /* 18 << 196 */ + { { 0x9cd08431d360ae16L,0xbf5a73d211281e82L,0xfe25aadfcc34ff33L, + 0x8874984b84e3af16L,0x8dd38b596a65a2a7L,0x6c91112c68a26926L }, + { 0xb765168637554f46L,0x79558f04c78bf29bL,0x8bb14b1f03012b9dL, + 0xed7d03f9a0886ba3L,0x9a436ec3c2a93baaL,0x601babb740db0c78L } }, + /* 19 << 196 */ + { { 0xa7395eef391821d0L,0xb299378fc8b7b1e2L,0x53a37e3b7f3a58d4L, + 0x7d06fa4e3188c5adL,0xe65a94c063dd7462L,0x4daf74f39cfde2b0L }, + { 0x98f986b4fbe7198dL,0x8e96b1ee88176bffL,0x5f309f64eb91641eL, + 0x46bfe3352ffdca19L,0x1ea1bbe7ac8fbc08L,0xde8ca618b00f88eeL } }, + /* 20 << 196 */ + { { 0x0757ee852005631fL,0x60f484ea9d70cc3bL,0xaf131d246b011041L, + 0xe40711a1062e2e17L,0x05ccf1b94c27e2c2L,0x29e9910e43d43758L }, + { 0x54daa550ed000e45L,0xf00a312295d3674cL,0xdb006fe743ec424eL, + 0xbddf5473536162d2L,0x7b8a24b579d433bdL,0x3127a46f282297d3L } }, + /* 21 << 196 */ + { { 0xcd964573cd0585a7L,0x9c2fd35605b684aeL,0x7f600f4de4a47ec5L, + 0xcb4bcdf085fdd4feL,0x5b292292b4dcf5d1L,0x923c4331df33a2b8L }, + { 0x0fe13edfd6c1e73aL,0x0b35adc6c370821bL,0xa70061b08d405282L, + 0x98efb3fc6457af81L,0x8806ee7136e1041dL,0x8b56657faaaf0731L } }, + /* 22 << 196 */ + { { 0xe68b669189cb38d1L,0x250f59233456ed5dL,0x8928f1fe16188290L, + 0x8b24b1f734a837d4L,0x268c8c57d945d0b1L,0xa4190ceae002b3abL }, + { 0x4596e76e56dd74b1L,0x647c17871c307789L,0x0b945c7243b13a6cL, + 0x4904669552a58ee2L,0x7547a6b46e25b7e4L,0x8bc26f49e2b1b140L } }, + /* 23 << 196 */ + { { 0x95b3f4e75196d614L,0xc075bcfd5ea18aadL,0x15dc9dd41ae71f42L, + 0x75a769f289543f86L,0x06032d9ec392b4c4L,0xd6cc5c717d4df83bL }, + { 0x111fc63427ad6680L,0x770dfe7f781bda48L,0xabacb082fc0afb5cL, + 0xe3a463e771dca197L,0x390f21a89635b275L,0x3d3474b24ae094a6L } }, + /* 24 << 196 */ + { { 0x48f5588853666241L,0xb9fee3d39e6a068dL,0x8c50e3af0275e82dL, + 0xd490cf2dcab34005L,0x20b11f86bf0584c8L,0xd49714c18179e559L }, + { 0x89647b178ded6686L,0x6c4bac8cf16c93d4L,0x5401e4f8076ff71bL, + 0x577e73acb1ef9b0cL,0xa1b87e0ea46e7880L,0xab8d8bbb54fd28a7L } }, + /* 25 << 196 */ + { { 0x220161f0741396fcL,0xae14ce5817da16ecL,0x766e415bb828b19aL, + 0x1b3b239e610c7aabL,0xf1c7df4992d53419L,0x57e4cee59442c6cbL }, + { 0x546f73b5f85d33d3L,0x195116c74e041703L,0x5a71a96a5d668df5L, + 0x0adb7b16fe56c658L,0xf6be923deb563532L,0xa65ed113f2d45f4dL } }, + /* 26 << 196 */ + { { 0x8c6742e5bccd3be6L,0x5f0f7fdd378de702L,0x41236fec334aabb8L, + 0x4b15815b7e9d8aa9L,0xbb816e46e1c235bbL,0x8591cc45176c2fe0L }, + { 0xef00e3981d7104b1L,0x761d2c244012398bL,0xe4984f4ae81af247L, + 0xf923bb80c144dc64L,0xd51f27dd83988de3L,0x0ad5438d995dbbddL } }, + /* 27 << 196 */ + { { 0x0532790bd148314dL,0xb4862d9d5b6b4ad1L,0xab65bfc45beb3ac6L, + 0x72eac92d99331822L,0x2e09a69a6127632cL,0xaa1eaf0791ef9141L }, + { 0x79b923fe754ff12aL,0x19395a97f9a467ffL,0x7dcc91d49ef5cc4eL, + 0xb9019ff198a84090L,0x62616ed6d5bfd083L,0x95cbf9442b328615L } }, + /* 28 << 196 */ + { { 0x22ef6f606374afbeL,0x70e19fad26348f5cL,0x8bcd51a845f98ac6L, + 0xeeef7f7026b7ba04L,0x33aa0644544edcb9L,0x22d89a1244974c71L }, + { 0xecd08f5d0f8d90a5L,0x495a0403cf03513bL,0xe924feea27953ba9L, + 0xdfbe1f93eb5e7975L,0xd3c105a1285865dfL,0x87b8b6360886fc87L } }, + /* 29 << 196 */ + { { 0xc2da6d7a219d44f8L,0xe66364c555a9d970L,0xfb0936258611738aL, + 0x916fbfa844f7f35dL,0x7a4e0451774b1e2bL,0x7adaab9e80375e65L }, + { 0x2272b95c8ffdfda9L,0x41644b619ad42b25L,0x157026817f0c98fdL, + 0x25d4a00fffba1d85L,0x52e684c6c6c5545aL,0xba85bf2adabb7df5L } }, + /* 30 << 196 */ + { { 0x89a5b69dd282b12fL,0x63864e7ba7d28277L,0x36ac74d08c21f920L, + 0x7cfd291713a2f8d3L,0x50b63122c2ef5022L,0x23d454328ed33339L }, + { 0xf8696b2dc4880048L,0xb9605bd5792dcb6cL,0x4cdb5fc26fdeeb9bL, + 0x58ee2837f1a7f35eL,0x8956359ae2985ccfL,0x0cc6c4ab2c94cb32L } }, + /* 31 << 196 */ + { { 0x2fcac7d161a8254aL,0xc396583a05389aceL,0xc6f069cc3872ee52L, + 0x76f0e5b407180f5fL,0xc8b23b7a2dee0d6fL,0xc77b242613bf8fb2L }, + { 0xa8c625e66d5ae411L,0xc0c40a75b0723adfL,0xdee0ba8f380d9c67L, + 0x38b86a3b19920f24L,0xff2191b7d910e9cdL,0x8d01786734181894L } }, + /* 32 << 196 */ + { { 0xa704016022ec7eddL,0x19124972cc9c8ee8L,0x697f301f2ccb9417L, + 0x3ee877646f00d8aaL,0x2b5afaf88138a017L,0xf152b14c832d7543L }, + { 0x27c27ce2383052f9L,0x4746c5b5e1dae11bL,0x92dc5ac75b752008L, + 0xcf382e01e84fe5f1L,0x90e034197d5929ceL,0xafee3abb15ca3ffaL } }, + /* 33 << 196 */ + { { 0x299e0c5507f0e3a7L,0x75dac5c46cdebb44L,0x340b5479183c7e42L, + 0xfb1b03dd702672d4L,0x68f7222ec07cf89dL,0x67a471e422e7a8a4L }, + { 0x79dd4627b9ada93aL,0x774c53771c8ecca5L,0x95191e1a59db2e65L, + 0x3f6947f270abeeceL,0xb4934fe0885e4e00L,0xd082e49901728c2aL } }, + /* 34 << 196 */ + { { 0x86cd8083aaa82329L,0x74f0c5786e579dfcL,0xc2b68c4e3b436545L, + 0x8e66c648469d4a81L,0x4c5b05c5bef62bb0L,0xe558ff020bb6f865L }, + { 0x9f8ccb16f356a124L,0x1bb28d7c1279f8f4L,0x9b885f0ca8fc4e08L, + 0x2ec4cf69859d90eeL,0x9bef3c4d86d3b9d1L,0x5a98ce73eaad8d53L } }, + /* 35 << 196 */ + { { 0x6c716b179711b5d2L,0x396a4a4cb386c1d0L,0x5845f6861c157c12L, + 0xdcad516262c15d4eL,0xb6e0a6a02dadb218L,0xe4f6d5e5a342e785L }, + { 0x1eeea548c78980e9L,0x363c31be00a32adaL,0x01481fb7e660b445L, + 0xcbb61552999c1f5cL,0x20a73942f361d12aL,0x67fb89a11b8b4b3eL } }, + /* 36 << 196 */ + { { 0x1d57d639eb00e26fL,0xbeb198906985c10bL,0x38cd95a337b9b76aL, + 0x3b1d12e30304c87dL,0xdf42dc6f4734e191L,0x1ed1d9e397841989L }, + { 0xfb60e333859b577bL,0xfb026d16ed3db987L,0xa216b0e46f7855c8L, + 0x9501bae3539ebdf6L,0xd95a4a32dc8a1f6fL,0x76cb0b6b45307deaL } }, + /* 37 << 196 */ + { { 0x5607ab62a844b579L,0x8d3ed3db94f67d9fL,0x95390de8a9929b04L, + 0x4a6f6f7cc85397f3L,0xec5b73eff26eab04L,0x2543190b045699f9L }, + { 0x9a4896138cdbb723L,0x0e081e5b7a1c638bL,0x20f292c6596a7b1dL, + 0xa14d849794477dd3L,0xeeeca98064b0de1dL,0x75fdbae92c5135dcL } }, + /* 38 << 196 */ + { { 0x1202b5752b076f5bL,0x5ca1247edbd6c420L,0xb45ff9bfd8ccc5c6L, + 0x680fcfb28e061baaL,0x5a6e6342122a4212L,0x0ad12abc312fea8aL }, + { 0xd1dd8ae5665dc7b1L,0x30494dfdd9a22454L,0xc8aa9bc9da55ed09L, + 0x6ec643031b74b119L,0xf54574716b604639L,0xe2a214e59f8d83ceL } }, + /* 39 << 196 */ + { { 0xca698de5f5c96e8aL,0x352c89a3fd941919L,0x0e3de0a909812f23L, + 0xa74ba91667702fefL,0x6acfaa5a3863d479L,0x28d8932bb6bb15cbL }, + { 0xc62155704ba9718dL,0xc67a3eafa1edd692L,0xc86eeedaab31aa74L, + 0x2064ea632deb79c3L,0x813b84f51ff01adbL,0x994b9437458a1835L } }, + /* 40 << 196 */ + { { 0x1013c4f4fde3f7ccL,0xbad5415a838699b6L,0x2a8b4eac64cacc78L, + 0x3d10f949bf75d233L,0x5a9f7782fc84e55eL,0x209a18345ea7b274L }, + { 0xa66cb6d4f9e8d374L,0xf898d9479a20080eL,0xe7e4b91b1272df4cL, + 0x5b8507cc5dd136bbL,0xbe4b5262372a8e05L,0xa0cb170c2aa4a47bL } }, + /* 41 << 196 */ + { { 0x469180a38378217fL,0xd960bdde85ef6d61L,0xcc4e737d6654aa84L, + 0x28d440016ae51d69L,0xf13a0d9ac6187196L,0xe60851b392160f65L }, + { 0x41d98cf61cac48d1L,0xf37f003d1b57f2cbL,0x4829c60bce272603L, + 0x45991d4adcbdddc1L,0x17e591fe74601bf3L,0xf8a36b4fb3fe856cL } }, + /* 42 << 196 */ + { { 0x4410b773fe480323L,0x42ae32e3ea2f8b57L,0x6578a64b2886b9d9L, + 0xafcfa5fe4241ec91L,0xa7fa5afc16b4ef24L,0x4a6594bbbc16b610L }, + { 0xcb5845515e264fb6L,0x4b89955e2b9c3c70L,0x530426be21e11c1eL, + 0xb707abe9c9dab34dL,0xb5aab0bf5931cd78L,0xab6a2585f0ccfcdaL } }, + /* 43 << 196 */ + { { 0xe75761f716afd216L,0x8ff1cea3b8a4f008L,0x04b8b65e69889d77L, + 0x679bf7a586ad9fb5L,0xbe49be0b4c22b86bL,0xcc8905a16c026c1dL }, + { 0x17464e7e59ec1983L,0x50cb62832a03afe0L,0x8dadaf456ce4df91L, + 0x26cf59d1e0df6fddL,0x6ecc66119adaec45L,0x1be42e744ef67dacL } }, + /* 44 << 196 */ + { { 0xa01cb3bacb1957b9L,0x053693ccf50694c9L,0xf8a887ad527f3aedL, + 0x2f1a80ece9bf06f0L,0x74baeaa57d0eec9fL,0xce8e8b9ab0641cabL }, + { 0x91d1e84d128a1804L,0xbdcfcaec2d5fa43cL,0xfc5cff124106fa6dL, + 0x2ae3ffab01588ac1L,0xe9dcc9b44c067052L,0xd8e3d74bafa7d4c3L } }, + /* 45 << 196 */ + { { 0x64a134296d7b277bL,0x487080d8e9a50637L,0x02e5fe901c6c061bL, + 0x8fdaafc8ecabeb11L,0xb1e3960110720b13L,0xe7304bf77081f41eL }, + { 0x78a10af8c26f5cf8L,0xf52cbc155c032c15L,0x95a3c4558c0c2091L, + 0x1797b407abba6f79L,0x87c0cd05a96a3062L,0xdf75e2805f04a7e2L } }, + /* 46 << 196 */ + { { 0x47161e1f82779cd6L,0xa95afa08c8158458L,0x2cbefdbc40a80742L, + 0xd86e0bfaca420c9fL,0x08f5f8c29c79427eL,0xe8f88361da4d0d9eL }, + { 0x2195174d3eb78d14L,0x889b32c9ed6caecfL,0x1e679749c3c83ed3L, + 0xc27a8c84eddf8a29L,0x4a21af3af8e09f40L,0xf4b9797f1eb3b9b3L } }, + /* 47 << 196 */ + { { 0x58c2405baa44f11dL,0x86ffaa37ac0f7257L,0x373623cc4070f6e3L, + 0x142e62f9a36c73b3L,0x43bab2dd36a143fbL,0x4fbeb0b7aa50375cL }, + { 0xf9cc2e7b1f862294L,0x95a9be3c0abdcaa8L,0x70f050225cda074eL, + 0x152659db43e6bc89L,0x1790148727c6e01aL,0x544069354e083c21L } }, + /* 48 << 196 */ + { { 0xcb51f03954ebc926L,0xe235d356b8d4a7bbL,0x93c8fafab41fe1a6L, + 0x6297701da719f254L,0x6e9165bc644f5cdeL,0x6506329d0c11c542L }, + { 0xa2564809a92b4250L,0x0e9ac173889c2e3eL,0x286a592622b1d1beL, + 0x86a3d7526ecdd041L,0x4b867e0a649f9524L,0x1fe7d95a0629cb0fL } }, + /* 49 << 196 */ + { { 0x028bc25096c54946L,0xace5e7ad0f5fb7eeL,0xc820d7513350ab02L, + 0x4ae1f6d99c8d7635L,0x03d1f83a98e1ed80L,0xf014d45d5ad14550L }, + { 0xeb8f2c328cd6d0b6L,0x090a8f71770f586fL,0x1a8219f93eb7d3b7L, + 0x0d610d9febfc26dcL,0xfdb49980aa330297L,0x6396f218d81b3fbbL } }, + /* 50 << 196 */ + { { 0xb4ea3102eacb7b9bL,0x4aefb43d72af1d6eL,0x9a1a912d249a51d6L, + 0xddd0a5744d5e3a1fL,0xe252114708aa1f69L,0x4b235efe9de89d5dL }, + { 0x6fae47420d7f1aa7L,0x0434ae2ff200e13aL,0x75143dc192508b57L, + 0xc441a768055e177aL,0x84cd7adf2f142b2dL,0x56484f4161d9ad5aL } }, + /* 51 << 196 */ + { { 0xe3e9d0881beecd14L,0x4bd12b179093ab18L,0xa6908ddbc925d5dbL, + 0xfdc5f740832d1474L,0x1a35623696f831afL,0x0e39086808cde8c9L }, + { 0xab1c7cbda2206b32L,0x84d299c8b93ccf1fL,0x380fa432dabb6542L, + 0x59f01b5177c2cb3dL,0x9785c47b6e56c4bbL,0x047acc813a3f2b1aL } }, + /* 52 << 196 */ + { { 0x724210e61e42b4a7L,0xa8d536afe2dd968cL,0xc69936e683582c60L, + 0xd031f1abdd5d7f68L,0x7d31dcae8c4180d4L,0x117985f622bca188L }, + { 0x3b0a982537e38dc2L,0x1663fdc5896fe4b4L,0x55d18cc7fd707372L, + 0xfac2d7a40d2d8470L,0x994763391b04b1f6L,0x87cfbb5ee0bd72e4L } }, + /* 53 << 196 */ + { { 0xeac6a72ad5dd2841L,0xf1aa32524277e152L,0xe6c44e9b6ef7e947L, + 0xd03309fc54095378L,0x6fc5fb9ccdd06947L,0x10ed0e76d1e9a968L }, + { 0x42d5ab02dfb77b17L,0x4c54c381a53de8ccL,0x5fb4c256f2b1b5d8L, + 0x17d5ab28e12ed054L,0xd7c96ce1139da42aL,0xb32f63859919f459L } }, + /* 54 << 196 */ + { { 0x4bf5788312f4b0b3L,0xcd69d82ef46735faL,0xc397c8f9a1baa0efL, + 0xfce184c0fd1be398L,0x15021775fa54580eL,0x10bc85468f54397cL }, + { 0x6009a691eaa9d711L,0xc9c6a42fb7846417L,0xe9c305685627817dL, + 0xa1be66ff92abd5daL,0x9317838fcdea11c0L,0xace94ddcc85e7aa5L } }, + /* 55 << 196 */ + { { 0x3ef37821d4079bf4L,0xff78abebfcbdc3d0L,0x117414bc4733ea34L, + 0x7f181a3b9f50d0feL,0x9ea5f94eda897ea7L,0x01a996ceee8314ceL }, + { 0x0cac3c8b420e988dL,0x7ad66ac4bed3294aL,0x6bbf6dd800b62445L, + 0x590a57017a2fb4fdL,0xbf3b4e529ac11d81L,0x1bd453020d60c710L } }, + /* 56 << 196 */ + { { 0x8a43bba0902c32d8L,0xd8c69b74a3955e42L,0x413bf25d79c64afbL, + 0x3c39837584ac94cdL,0xfbfa9c53a08ccf5aL,0x9d8ac945e9d791d4L }, + { 0xfb9bb89e5e7a2553L,0x1442612bb039dd24L,0x8250ffe0a2e2344aL, + 0x5eae8b396426b985L,0xa1657768484741deL,0x05e52d4ac73cdf8cL } }, + /* 57 << 196 */ + { { 0x61c2417995c5e767L,0x7456380c3bdfef62L,0x62763f43d206cbb1L, + 0x1996e2c657871e44L,0xd0dbd290f220c06dL,0x6778e1e5d87743eaL }, + { 0x40e54caf16b8f046L,0xe834a1cb6bed77daL,0x7240befa3e9457c4L, + 0xd1b638dbac96cedcL,0xd1d7e814c9c0cd8cL,0xc73beaf14d38258eL } }, + /* 58 << 196 */ + { { 0xf1a6d776c05f40feL,0xb98c19b1c21ce471L,0x700b0bab7f9689eaL, + 0x861513a56f1d2e6eL,0xb7558b2292fe4456L,0x2d8f860704c66a25L }, + { 0x10ba7d6a7998347dL,0x72bf56093983b98dL,0x8d873c4f89238292L, + 0x5db0dca9a5e3c944L,0xf81fe37e0925aef0L,0xed6a13a4e4daae25L } }, + /* 59 << 196 */ + { { 0x49e2372711c3a930L,0xbf2ede34f5293b8eL,0x0abeeb3ca8e1cc9aL, + 0xb1db299440205cbcL,0x3252d29e52fb01d4L,0xa0b080c57dc91095L }, + { 0xb56fdae622a9ceb9L,0x6c3c3463b31f6f27L,0xcb510ec2ae3bd22aL, + 0x1efcd77b0b3db475L,0x1094bcc5ca766f9cL,0x688e940dfea48297L } }, + /* 60 << 196 */ + { { 0x3d95d26a99cde27aL,0xed608a89b99344f4L,0x7a70a8f09c0ab25cL, + 0x7740953c496552d8L,0x4da4ca0f4a366adcL,0xbf475c1b33274d4fL }, + { 0x5ac1d8288811b869L,0xed62e7b4d23446d4L,0x67d78571a0eab287L, + 0xa74ae3e98b0acc4dL,0xa63f91d64077c236L,0xe2c3f82a818a6889L } }, + /* 61 << 196 */ + { { 0x2bde7037b1d5fbeeL,0x477a4b51a80b92f2L,0x195ae0e06606b504L, + 0x7aaf3de57497785aL,0xb5581ee9290c5ef9L,0xcb303c30360c8ec2L }, + { 0xfb056f901b1fb602L,0xa38bc9f59931b7ceL,0xb0b74aeab2f453a8L, + 0x9a0e2ebf668cd68aL,0x8b7e0d73d7db7842L,0x21f29b74d1fa5433L } }, + /* 62 << 196 */ + { { 0x38321d7c4e11f824L,0x04dcd3a3e4a816e9L,0x382968ed07e09612L, + 0x6f7b2dbfa370e1d1L,0x5a8472348675d730L,0x88d974b0e59e984fL }, + { 0x89f7e2bce3f9e429L,0xd478eacfe3aebac2L,0x8df9f281ebef3488L, + 0xcbcb9fbeab5543b3L,0x2c8d19b0203f59e2L,0xbb98e4495287b0fcL } }, + /* 63 << 196 */ + { { 0x16c45f709aab81d7L,0x0f1310851795a4b7L,0x3c63d43af0ecd732L, + 0x22e2d1988628b683L,0x7d7482bab641d6d4L,0x6baef4a2ab69891aL }, + { 0x10989097e63c00d2L,0xbfd42ab0d93794ccL,0x9a1935f3e4165a41L, + 0x359701b35b600ca7L,0xbe7d69f983d1b54bL,0x99b0f35e3729bd4aL } }, + /* 64 << 196 */ + { { 0x11dd860e1c6d03b0L,0x30c1700809eec660L,0xd4f8aff635c0192fL, + 0x96a727b1e3a4a900L,0x1426daffde78c8baL,0xfacaa9bd8d1527c4L }, + { 0x0c0d5234cd072989L,0x1936c20d918550b5L,0x4828bee43d914fb3L, + 0x8324ea38f3ba26a6L,0x027590f3a94eb26fL,0xfd354295acd957bfL } }, + /* 0 << 203 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 203 */ + { { 0x3ede2484da756624L,0xb22da2ab73b13062L,0x56069e93962a667bL, + 0xc931266b130f2ceaL,0x4bd6a6fca7366a66L,0x23f30563aa5ac3b1L }, + { 0xa025d0efd7c2b26fL,0x597ce7d862129bc7L,0x4809927f2b3057f2L, + 0xb001c10a1499f884L,0x309d141c30b9a653L,0xadddce7dbf659d05L } }, + /* 2 << 203 */ + { { 0xa6c32900af2825c1L,0xb37c46c1d223a04eL,0x691e7d39063de7eaL, + 0x998df4e710daf9bdL,0xc7085b9e718b5d7aL,0xd41abcc816b3d4b8L }, + { 0x4dfce693f9bc4041L,0x383677ed659ec7a8L,0x2c1904bf4491fb34L, + 0x7c1bf1114552451cL,0x6562cc2c3c5e5e40L,0x1ecaa2a1fe0e4372L } }, + /* 3 << 203 */ + { { 0x9657d08ca9cb9ecbL,0xf69662363b75be69L,0x396a9344a31c2b8cL, + 0x1c50b1269767bc1fL,0x597223d0d1417e03L,0xe165ed5a12137153L }, + { 0x8bce29f926a24098L,0xc428a1fbe99e7bf8L,0x6fd4c906eea7f1d9L, + 0x94275713fceb2e05L,0x3555448b741dbd94L,0xc50e85459faffd4dL } }, + /* 4 << 203 */ + { { 0x84c3630bf3087bc8L,0x152691e674be6e26L,0x5abd125ff61af001L, + 0x69bca56fbfea3525L,0x384af19900e0cb6eL,0xb0b13cfed00475a6L }, + { 0xedafde495e394049L,0xd988b558daf2add6L,0xf14cf97a6c8ffcc9L, + 0x4d6cec23e5a9cc5cL,0xb0d678f88a104e05L,0x80a7fcba9fb527c1L } }, + /* 5 << 203 */ + { { 0x9ae12b902af1ffceL,0x082f30b95a30521dL,0x974099bdc304014bL, + 0xab1e27e444ccb6e5L,0x72db8f42290387a1L,0x3d1a461040f3ce18L }, + { 0xe939a3f2634ba10fL,0xe70a9cf517254c56L,0xd0f8692fa08ec3c5L, + 0x77edefcc7a7cbdf8L,0x04c4b18ebdf90f0bL,0xa890436a8aa36a59L } }, + /* 6 << 203 */ + { { 0x8618ffa79e30f8a0L,0x9961390cd12699bbL,0x5b1b0d744f61edfeL, + 0x33df67d9eb7a476fL,0x7f1a767ea92ee99bL,0xfab400e32223a2ccL }, + { 0x16f376f2f534dc3dL,0x6f36eaefcec17905L,0x8dc1516ca58765deL, + 0x893408262260ed6bL,0x060eb0afcf4b29baL,0x9cd0a9f11d252bbaL } }, + /* 7 << 203 */ + { { 0xd3c2a6a8ca413693L,0xcc56a8e932d5714cL,0xc72b73683c0da165L, + 0x5d236660db44e616L,0xa83b2ecce5c73667L,0x9d292f298aea900cL }, + { 0x67121215aaa2a7eaL,0x57dae96abf889191L,0x63bf7a81d296ae68L, + 0x9bf518758fd496c4L,0x5b4382fbc2f7308cL,0xf1215dfc9632aad7L } }, + /* 8 << 203 */ + { { 0x0d6cadbfc22137d2L,0xb5db59d3628a3298L,0x3b433c734ab19507L, + 0x4fc53405660086b3L,0x770ae903a1eb0f43L,0x31b5857ef6b5b58dL }, + { 0xe206e141d392868eL,0x8be6956f4b31de04L,0xcfbfca2f47449e07L, + 0xebaef25639fef8e1L,0x959e37b8c16fc80cL,0x8bb4bdd2e911d61bL } }, + /* 9 << 203 */ + { { 0xecfb851380fc41f3L,0xb0dc8823931843c4L,0x59decd6c1b93df03L, + 0x954103b72511e252L,0xe372f86a0f759de1L,0x04f5afd38f6f9ef3L }, + { 0xbd8e60affcba2e7cL,0x9b1cb1ed092315b0L,0x5f9e20a03fd05e36L, + 0xfcdcc44ded95f25eL,0x6baf401b6ac79cb5L,0xfe1a5a856894f651L } }, + /* 10 << 203 */ + { { 0x014a0907e51c6673L,0x28118ccd3e6e6a91L,0xdbbb7c4dc999acc0L, + 0x01b771075e7ab1e3L,0xa33fefbfcd8fb11eL,0x1df5b61fc0b8a5c2L }, + { 0x774dc2674478c5c6L,0xbfe1add422fb91a1L,0x5ac4dc694d9c8461L, + 0xbf6e002a1e772c5fL,0x4922120e0b83fe91L,0xa7747f4b3efbadceL } }, + /* 11 << 203 */ + { { 0x4b955beaddaf2e82L,0x3775ecde90fdc68aL,0x579c34f91713e763L, + 0x6c27f504fa509d74L,0xef6df04a3f8dbf4bL,0xc39f2e28b3ad7104L }, + { 0xe54042b3a5973cffL,0x4e594427f111f3d9L,0x53c7a2ba155fce57L, + 0x7b3c1c60e6e1d21fL,0x5e12db8d308ddf4dL,0x2c3c5e77a00e8976L } }, + /* 12 << 203 */ + { { 0xc483d4b24343bbf8L,0x42aca2e18a0fc95eL,0x5165df6fcbab1fb0L, + 0xeb284370f6cdfc0cL,0xab565c00994320fcL,0xc0d157fd62133e80L }, + { 0x7850cda55b69644aL,0xe37ae76a806ec8b8L,0xd14b805cc2c82eddL, + 0xcb5468b6cf244539L,0x97d43ee825dbe92dL,0x1442243689fb8f1eL } }, + /* 13 << 203 */ + { { 0xcfc8a945f361dc08L,0x383a5336491dc3abL,0x77580587c35cd376L, + 0x6604248ae2426904L,0x47c56025ffeb9d26L,0xc301edd8bae5d983L }, + { 0x7c6511a9e2e5cf33L,0xdc52c1dd221d41acL,0xdbdc8acada47503bL, + 0x01b406864bcedbbaL,0xca9cb9fd2d5496d5L,0x5768e0edb17e8400L } }, + /* 14 << 203 */ + { { 0x421afbe0431cb760L,0x9ae9ff985203e69bL,0x56cacf4db1a2705aL, + 0x6a3a4136d128bcd5L,0x2411c4b866191ad8L,0x39f26e1a15b45d24L }, + { 0x4cc82459c64ed153L,0x5c7a0dd58195b452L,0x9c88bb1c69f6298dL, + 0xfe567b031933fdb5L,0x8a6aea71881308c3L,0xc1268b55a2f0adfaL } }, + /* 15 << 203 */ + { { 0x312b777c1231c557L,0x3984f71be9971115L,0x0266b58294cc2d4bL, + 0xc3058419cdf5e5c1L,0xab3a1ae477bbf0d8L,0x7c2173a6d21603daL }, + { 0x61cca8cc747b092bL,0x70f77a53e376506aL,0x742c20692f1ccc85L, + 0xb1f2ceca2dc8844bL,0x5a73cff83a096c10L,0x28acb67d5c19cd11L } }, + /* 16 << 203 */ + { { 0xd7bf2ac6a0a85236L,0x2921b55c7194c46dL,0x162fabaa9afa9762L, + 0x7b7f1664b62b36abL,0x77b9f797296a84e9L,0xfcc1ad657dbd843dL }, + { 0xc6e9c1e1cd77b7f6L,0x9cf0e272917067c9L,0xfa7fa93d3bfa90bfL, + 0x55846fe9d050e46aL,0x473b9a0d35c56256L,0xadd29e332b656a65L } }, + /* 17 << 203 */ + { { 0x4698137f46fb8ae3L,0xb11a595f7b1c062dL,0x4a043b99ff023ef7L, + 0x2836d64d8ef0fa4dL,0x4067dbee8ea44a98L,0x9d1739c9f00ff4e1L }, + { 0xcbcf12fe133d2703L,0xd2923424016037cfL,0xda7543d68be5f666L, + 0x587d1920ac5e1847L,0x14662476f79e3462L,0x0120a1d8c810a1f3L } }, + /* 18 << 203 */ + { { 0xa4fc828ab18f9bb1L,0x06de4c9da27a787aL,0xfbb7c7d7b1b3a12bL, + 0xa7052b94b8583128L,0x173ec2d2e7b02fd8L,0x4b724682c776c664L }, + { 0x46ed9be5673183e5L,0x312191e83bd17c60L,0xe3ed6326efd56a9eL, + 0xb3ebc44c943a2278L,0x7ef62ba9ec9cf589L,0x754be6d389832cd7L } }, + /* 19 << 203 */ + { { 0xccb4b369dc992b32L,0x0ef84cc0922cee22L,0xda0058f1fc56e9e1L, + 0x208c57943f23632bL,0x3589a7338f77a82bL,0xee6cfa2c76ee99bdL }, + { 0x88cffafc418f7993L,0x0dde3f05f4be56d6L,0x5d088382a0472bf5L, + 0x872ca5aabd58d05dL,0x9c467c62e8f91f17L,0x38ab1b348c6b91ffL } }, + /* 20 << 203 */ + { { 0x926c2552ebc69b0bL,0x953a850fd4c7432eL,0x0ee85e14b9359035L, + 0x8b10b01abde090a5L,0xb2878dcaec423943L,0x2571a178f70bde20L }, + { 0x24ed159af5ebeee5L,0x60c202af043f6539L,0xdaaa76f4c8d4ffc3L, + 0x2fc1f1ba06eda10fL,0xddf159ee88ded556L,0xcfa71782e67b1ec4L } }, + /* 21 << 203 */ + { { 0x2596ee7409d3ed60L,0xd42551f474a46e37L,0x2e46a92e21061c90L, + 0x236299fa73ad22eaL,0xacdccd5214393ac2L,0x9a572130b56b4d5bL }, + { 0xddfc31781835e70bL,0x5dac0671d542048dL,0x2b0768d7a6dce17cL, + 0x6d447d4206c55342L,0x6b55b21525548478L,0x24e6483518d5310dL } }, + /* 22 << 203 */ + { { 0x3c58c5ea9b037c66L,0x08d0648e0d5c6ec5L,0x1bf90c53a4fa3f5aL, + 0x660cf61740381205L,0x63fd03081d44af3fL,0xe22b9c1a77175de7L }, + { 0x0b6044fc3556fc9dL,0xaefb6804fb55318eL,0x77045bce5c46e1ebL, + 0x29c4a3bc76e8f93aL,0xdf8aec699d697f5dL,0x5bd9552845a89080L } }, + /* 23 << 203 */ + { { 0x1bd61fbdc5756910L,0xcfcc6d5adeaca40dL,0x292867885dd80ac1L, + 0x7effe328d621c0a6L,0xc64ebb91ab22a2b5L,0x8954ab330c44a456L }, + { 0x7552a0b460e26218L,0x2e81d3a94136adbaL,0x96dc2451610d665eL, + 0x30859c62ab04e03fL,0xdb3726fd4c31fa3fL,0xbf4954d1d962a7c4L } }, + /* 24 << 203 */ + { { 0x31521f66d5d826b0L,0x0a63695240787844L,0xc0a3bd059c8f934eL, + 0x12c57dd42f0ce835L,0x847f6a9967064213L,0x1c9e1a7aa88bd71aL }, + { 0xc4060eb2171e8407L,0xdf78d8dfed106780L,0xa3d28ceb0d704729L, + 0x4f8e523246ca3912L,0x09e9f852017791f4L,0x594006631e6ea97dL } }, + /* 25 << 203 */ + { { 0xdd26fb79444827feL,0xbf78e076d3f5fa6bL,0x46d486e81a5475b5L, + 0x43e325a5faabc3f8L,0x1fef6b6ba6795d0cL,0x40e040666644d631L }, + { 0x16207bb9676c3322L,0x677c1c235811706bL,0xb686252e994e2a95L, + 0xa359e2a51b6f6a3eL,0x6d8f06cfb124f019L,0x3bcf778246266c42L } }, + /* 26 << 203 */ + { { 0xeaa3426b8eb929aaL,0x090924f2327bb35dL,0x4d23ba1276da394fL, + 0x05d98e56adecd43fL,0x83c7169f6b4af795L,0xc22560a7c8f26ae8L }, + { 0xb43aecc2d01ab5d8L,0xe7bcdc1f7257d7d1L,0x6f32d77650de3318L, + 0x6d736b279bf02c0aL,0x9534fa5865319235L,0x5a6a38493cfbeb3cL } }, + /* 27 << 203 */ + { { 0x3ddcb65828c50956L,0xb335f336bf1bdb4cL,0x7c18d2d0ac3b6194L, + 0x8748654bca324d11L,0x7c9c58dac2e85f94L,0xf1930a56d4f4f957L }, + { 0x9cacbdbbe410fee8L,0x0e292c2178e1312aL,0x6845b293906a6270L, + 0x842ded0f00c5401eL,0x747cd08f35e3ff9bL,0x8405540af48227feL } }, + /* 28 << 203 */ + { { 0x547b0d9583939224L,0x3a0823ff1e026769L,0x6016671525bd43acL, + 0xb6cf475e18ba5f64L,0xa22f9c92c8b6d09dL,0x730553683ccf50abL }, + { 0xa6de248eee6deefeL,0x32aaf8b2acc3ca20L,0x0e254c5bad44e674L, + 0x8aa73e6535f95f98L,0xe622600160a2dc1eL,0xdf9482109109020aL } }, + /* 29 << 203 */ + { { 0x7b24d7b056190aafL,0x0115cbdd0563b377L,0x5688526ca7ba4975L, + 0xd2971e28aee3100dL,0x57a6ff8a6fa24f61L,0x9cb571c4d8603be7L }, + { 0x09c01564a2cce6d5L,0x14f0902b89884939L,0xd71a5ff8a072ffecL, + 0xee7848b8fefeab69L,0x7b52a9577e40895aL,0xd1576be7e8c61be2L } }, + /* 30 << 203 */ + { { 0x4c4d454849d77b8eL,0x431f942f6a4c982dL,0xc8633d051cb39ce8L, + 0x23421f8caf516f9bL,0xc9db25d2aac876fbL,0x9f2669c5d882760eL }, + { 0x59dc4bf4c47d4bfaL,0x99ed0024c475f93cL,0x269d1ca4ebe07d37L, + 0x49ce3bdbbf88b1faL,0x515044053361e4ccL,0x207f0048735b3c96L } }, + /* 31 << 203 */ + { { 0x835fe90b5a516e82L,0x26f1f2a7abfcb383L,0x3dae65a8609c4ac0L, + 0x70b01d6e91f4054eL,0x22da015b581e3159L,0x2ad34f99329d1ebfL }, + { 0x7385aad60d09b845L,0x4cbafb0b0adf42f7L,0xd8727d26c02398cdL, + 0x58c261f590549db5L,0xd49b12e48ea70310L,0xb31eea047ef89773L } }, + /* 32 << 203 */ + { { 0x372798f02893f2f7L,0x4f62bfac9e5030caL,0x5e64f9a98a1e2567L, + 0x5870254ce70391c8L,0x2def81a341f02458L,0x25d4e4dc1d087bedL }, + { 0x3557d07d4fe24a13L,0x6da49186dc3112bcL,0x08c8c5675f73ba50L, + 0x5309050b9c7c6706L,0x2ab67da3bd985072L,0x9bafa8b1e5df4e96L } }, + /* 33 << 203 */ + { { 0x5acdcd216f77738eL,0x340710746cb67a3eL,0xd68c55cf4bf76bf7L, + 0x64c159200b4deda8L,0x1021d38ae242b1e0L,0x615f1f033bd3d95bL }, + { 0x2ae0245cc300c9c5L,0x3549605ba88d63e2L,0xfe0dd65ad5038849L, + 0xe67abfec63c6e4aeL,0xccd08ba528153bdfL,0x9be9f5bced4d76bbL } }, + /* 34 << 203 */ + { { 0x30fe00bb6e8423deL,0xe16ce94784e4d005L,0xaf0f8c283fed764cL, + 0x05ef9bf67d92b1efL,0xbf6570d4eb481da7L,0x39349e30468494ebL }, + { 0xe32b99a63fb36907L,0xd92386da2d35e71bL,0x74af8b79166a973dL, + 0xa0a177f94f72de6bL,0xfff3e19d5dd6c660L,0x15310d4d4b0d54f0L } }, + /* 35 << 203 */ + { { 0x692a561f15c15a11L,0x25abe85f26ca3ddbL,0x50fef4444caffa5fL, + 0x58472cfbed3f4aadL,0x7e9178f0092d2b83L,0x3afd364ff8dfaaa7L }, + { 0x4686ee5cbbf813a8L,0x6a62687d937cbae4L,0x56f22558a9b7b6c9L, + 0x9af1beae9c189e25L,0xfac4ad9f4d41f79eL,0xdecb57431f9c7a40L } }, + /* 36 << 203 */ + { { 0x3ac662895c02f173L,0x6a110e3876d566e5L,0xd9cc14e2b9577e26L, + 0x6f3d5df9fdfe617eL,0x8fac740f352bb2caL,0x50bc8a0cc28e6310L }, + { 0x6e572fc477ac93f7L,0x56277377605bb8e9L,0xad6d0637402b8c55L, + 0xdab377914509eda7L,0xae770abc0854e91bL,0x523bd278742b3de8L } }, + /* 37 << 203 */ + { { 0x8ede0eea2aa0da2eL,0x7015ee6e90cfeb90L,0xef33f3efd6b3227aL, + 0x6e332f1712ef9f4bL,0xcaa089898e7f9fe9L,0x001482ef8fa71529L }, + { 0x2522637907a5019aL,0x807faf01bed40fc9L,0x426002ab56710e12L, + 0xcdfffbc18d3949e6L,0xcc03f27861284379L,0xcd7dc2026d5edc82L } }, + /* 38 << 203 */ + { { 0x94f84d57cff31148L,0x9c567c7f6bf2a313L,0xc82e62353149ad8fL, + 0x81f69703c2a5d513L,0xb54e6fc756eea9acL,0x6799c7957c3aae62L }, + { 0x78e89c1edb280515L,0x3c5693066ac42925L,0xd984c86dab063cc4L, + 0x61754b5151d44ae3L,0x23af8ec0cebeef0fL,0xff67170bc618fe8aL } }, + /* 39 << 203 */ + { { 0x123b567195b58447L,0x7397316ad43aabd2L,0xcb65d69d9ddc7979L, + 0xf98be7bd91150e08L,0xa5388c79fc0ae5c7L,0xb115690215ed9074L }, + { 0xc2d01b9227e9afdeL,0x80d705ec2095a6ebL,0xbea901c7fab23079L, + 0xced8b2772346d712L,0xad5c45a92542a0ffL,0x87b2e4ac0455e90fL } }, + /* 40 << 203 */ + { { 0xc2cbd64417fecb90L,0x61616eb3b32dffdbL,0xdc4485a29f5d2095L, + 0xf78911246553371bL,0x4f06ba18bf9b20afL,0x136d4f291a2c4df1L }, + { 0xc04aca34fb8b685fL,0xeec83c20f2b657bbL,0x4da5d70a5925a36aL, + 0x8060874172ff2965L,0x2e0dd9ff9f352620L,0x5f0afa6746d1a7a8L } }, + /* 41 << 203 */ + { { 0xb76c722762c1e582L,0xbce1eb164ffefd05L,0xa574a9fe169e53fbL, + 0x77bf92b0c001628eL,0xd998172c04d60440L,0x62f35199ceae6bf7L }, + { 0xd81a563e93f1ff84L,0x5a7a0b4211598ad0L,0x884f2ca5ff11f3f8L, + 0x99f5aac2f3ac66cbL,0x58497c01f489c5afL,0x11277bc39566521cL } }, + /* 42 << 203 */ + { { 0xfb9670c26a770385L,0x5da887e1e9682174L,0x31fa9d6bedf922f3L, + 0x8de8814cf7a98d1eL,0x3935b9b27a019f08L,0x1f59d6f3ea6173caL }, + { 0x8732f39d5c638a66L,0x981a1b7a3d48d3e5L,0xea451b381ee0ab37L, + 0x31a8e9abf2708356L,0xa491944ee86cbfc1L,0xd747a885a97ddfcaL } }, + /* 43 << 203 */ + { { 0xa3460236aefd304aL,0xaac80f43c58719a0L,0x7d635c17d3ca5b1aL, + 0x986ac0a62119976aL,0x0d8a6e39f2538d36L,0x6a02af2f31849d5dL }, + { 0xecb6ef8f6719d4deL,0x6dd71ab674ff8880L,0x0d40ec0e9d225d93L, + 0x304cd88adf381d24L,0x2d6787380c5571fbL,0x03c23f547c03af94L } }, + /* 44 << 203 */ + { { 0xa995a95bf46aace5L,0x44ede5379eaa630aL,0x421f3b3500336e3bL, + 0xbf897478cf47c9edL,0xf360ae32259e0827L,0x04e0e3e82e6a9f6bL }, + { 0xb26eae5fa9136702L,0xd6cb15a1853674b4L,0xf81276e2748bcbc9L, + 0x7fc02e220a4ca1d7L,0xf650f48ecd82f330L,0xf4ea7c1dabaa8859L } }, + /* 45 << 203 */ + { { 0xe9f090b935caae35L,0xe04dff188dcf1e6bL,0x81b7de5eb8032e04L, + 0xba0d0b4e4b1e8070L,0xaa82dc8ad1a2aeb3L,0x5855ed1ded26f229L }, + { 0x8bce967ed1955233L,0xe6ed07f356ac7532L,0x4227c7fdbf0eff2dL, + 0xb1f4785fa5e213e4L,0xeedad0733ac30f4bL,0x503619889cf1e686L } }, + /* 46 << 203 */ + { { 0xeb252116ba5da79eL,0x51cc937edb691345L,0x1d5fec14077458c1L, + 0xaa304f7ba0808e6fL,0x4bed89f5abec4c09L,0xc67293cbd1a3b798L }, + { 0x0905f7d342122672L,0x83675b2da0d3a277L,0x7f422b7024bf5bcaL, + 0xe2144c6910495acfL,0xdac1c357a6a6ab5eL,0xd1a3b951c8b1d472L } }, + /* 47 << 203 */ + { { 0x0821017d60c0c248L,0xa17ce97a8540bdc8L,0xe0576ea986e6f45eL, + 0x1453268bf152c6eeL,0x1ea1937138edbed5L,0x970ad9c002343c23L }, + { 0x3a08a859af8a97afL,0x20caf7cab570d738L,0x6d82d863e2a89455L, + 0x30eb8d0724c76844L,0xb31d58c8d32b79f1L,0xe5df7cb9fe63e93cL } }, + /* 48 << 203 */ + { { 0x1ccd44ff95c746ecL,0xe18914b510405763L,0x50ed644321a3a927L, + 0x4f96a1b143ef8e8fL,0x7f5645e577952bf8L,0x4bc5c7ab66dbdf15L }, + { 0xacc1612623930a08L,0xbf5ed482504cf9b6L,0xdeb7a798d71ecbd7L, + 0xf62e63b14a4dd859L,0x668809a7daf714d9L,0xdd836382f3a4329eL } }, + /* 49 << 203 */ + { { 0xac0ef2cf383e038bL,0x848e3c1f91135098L,0x19e5a3ee3f15b241L, + 0x2d01f1a2dbea2ad2L,0x44ec32a799cb0bdfL,0x3e66fed4eab4d856L }, + { 0x3162a75af45c8656L,0x53ab74245a37ca4fL,0x1b81f1dc360bb395L, + 0xa7eb222e2b8a5267L,0x163bb0c804b0bcaaL,0x1cac5bc0ef5c417dL } }, + /* 50 << 203 */ + { { 0xb95e2d85e81d9e43L,0x8a92acdd1418f6d8L,0x5429140110ee43d7L, + 0x32a2933c625838dfL,0x801d57dd3d485868L,0x33bba67258af765dL }, + { 0x545fe2583f520eecL,0x900ed51a32d71974L,0xf21fefe6df3ed77cL, + 0x2f0df28c9deb2d81L,0x90898dd780856fb7L,0xeba82159bbba4771L } }, + /* 51 << 203 */ + { { 0x83ecc8f374df3780L,0x432e9807d3a89728L,0x3461c5297b5cb6e0L, + 0xee307c19030c25cbL,0xd72b60c7391ee616L,0x0c07bf462e9b4384L }, + { 0x9d791b0bd44acd49L,0xf3b3411c9f3b33caL,0x1bf55cb97f9b455fL, + 0x77e01607600f0a91L,0xdab95bf26bb7e977L,0x30d0f591fe4633e5L } }, + /* 52 << 203 */ + { { 0x894bdbd9c48f3ad5L,0x687ff8de09e167f6L,0xf06104a930371c43L, + 0x82fd34b7ce84dd10L,0xae122deb66ce5abdL,0x31f041d2fc4a90b2L }, + { 0x2589535c9a01c607L,0x231bcc85695bd7abL,0xc67c306262e3a31dL, + 0x31be44757af3e186L,0x1a2077a388efa7f1L,0xffe53e22815fad1aL } }, + /* 53 << 203 */ + { { 0x4ce41f69a3ee310bL,0x38fb07d09bf311ddL,0x5fd284d660985bd4L, + 0x2fe99a19e04d3dffL,0x21a352520b3ad853L,0xb0808a89012aa69cL }, + { 0x98219cf718c7c301L,0x429e08fc91254db8L,0xface2e53c41d54d0L, + 0x180651242decb2d7L,0xa9f65e3f26a9191cL,0x1dadd3deed42831cL } }, + /* 54 << 203 */ + { { 0x81ce91dd6327460aL,0x4cc880a0e2f22af0L,0x81aa9bb46a6d36f3L, + 0x8ad516741dd10657L,0x212267854253b30aL,0x530d1f6a8f161dd6L }, + { 0xe7eeb4c7e9ab63aeL,0x84f225bfb72d250eL,0xc81cb984458a8dc7L, + 0x39fbbe3bda68c1afL,0x8c6c99b3083cafd9L,0x4700ba37eb07d40bL } }, + /* 55 << 203 */ + { { 0x8980dd7cd8dcc7b4L,0x0179e9bc7ad18f8dL,0xa9e4fa6a08c60f0aL, + 0x4f0d76fa3cc7dd36L,0x53339e4c51a0e67eL,0x1acdaf24cebd80cbL }, + { 0x5aaebffcb5264b96L,0x3ebebb22858df87aL,0xb2f4c1cb092a95a1L, + 0x34932d51841b1a63L,0xe0631aab49074a2fL,0x71525c4fe3b7fd61L } }, + /* 56 << 203 */ + { { 0xdd15591366229776L,0x84093730f7882064L,0x6dddcb14e50ee337L, + 0xa8e6ec597a1f7e81L,0x8467f998f3738a6aL,0x70fcc6bcad3f1840L }, + { 0xf82eb4be723b3f4bL,0xf0f3935406beec1bL,0x1b181ea37ddcb539L, + 0x9c82c4faad6a81b9L,0xcc5ea5435c612c2bL,0x63ce7571bb258d6fL } }, + /* 57 << 203 */ + { { 0xc6c110ecd3b9416aL,0x254403ea024f63e5L,0x92d2965b68aa4a66L, + 0xa08bfaafbaed92aaL,0xe2194cd701ad3eb4L,0x7ba66e1da7552847L }, + { 0xf68c90ee44eb9bbbL,0xabe38c5c5f6438daL,0xe16d4aa68c38a6a1L, + 0xc2f8691bf6294db4L,0x9248492fba64da6fL,0x850c6a6865a3d6b7L } }, + /* 58 << 203 */ + { { 0xa794308d2599a1f7L,0x06bbefce3e72b328L,0x24f2c6f5420f6ae1L, + 0xedf67defaae894c0L,0xf66396eb2e8e9821L,0x21fbf5f7a701c8ceL }, + { 0x7fbb192401732f26L,0x3d0063a944f57696L,0xd6bcb1c3513dd8f7L, + 0x1fbb11b2c9f8c033L,0x122f94b17b57b3eaL,0x08edce19d24626c0L } }, + /* 59 << 203 */ + { { 0x06aa75398c3a1e9cL,0x3512ec3c1a08c7caL,0xfad0dddac5a92e6aL, + 0xa98059ee3b9022fdL,0xd67b6723103fbda5L,0xc1df32904762c170L }, + { 0xfd99ee58c734f81dL,0xa8de2a4b478b8a4fL,0x9e3ed58fb4b557c6L, + 0x14d353c571abd10cL,0x10ea798fe3fd4475L,0x157e16f97627f4d5L } }, + /* 60 << 203 */ + { { 0x1b5888550b96547fL,0x4539c9c065d1a59dL,0xd6c95fea26e15084L, + 0xf84ad9e286b96242L,0x92f57d6d451a5486L,0x0215cfcb06a9e87eL }, + { 0xe05b10eaf66e46f3L,0xe7b0e72f655a0642L,0x035032677b117f43L, + 0xf5b78105779ea4a1L,0x28ee00faa4adac77L,0x1ea67d716a93a2b1L } }, + /* 61 << 203 */ + { { 0x4b68a01cd6b3387eL,0xc79582a9e7c4c99aL,0xa4ad6429029fc3bcL, + 0xf260ad946b83c7adL,0x81360618b09c3b8eL,0xf66e00ccc661ba2bL }, + { 0xd064537de29a69e7L,0xe2764d389bb4095bL,0xa3f57eb0f2efdea7L, + 0x72c214f27ed3ac00L,0xf8cfa59de392e32bL,0xa5d995124ad99928L } }, + /* 62 << 203 */ + { { 0xd069a9971dec038dL,0x64401a3fd0b59bf0L,0x33eff74ce7ec5e85L, + 0xfef5a1c50d35b207L,0x731cfc17e766bc43L,0xf994c0d01328b6cbL }, + { 0x4f2a5eaa2d3cc024L,0x7f83c57036a6fa14L,0x915a126d65f71dbdL, + 0x588fdd68acfb54ebL,0x7de9d37b7f57b2afL,0xca52d27170e071ebL } }, + /* 63 << 203 */ + { { 0x9b9211ada283322cL,0x30c6fa27b7124c9fL,0xda8f88a7474cbf5fL, + 0xc2414ee338203749L,0xe5c65cc26b767731L,0x8bdb52952753781cL }, + { 0xc8fe770be051cd30L,0x6370ecc4f046aa97L,0x03c83c1cfa287e66L, + 0x935bd2052bccef4dL,0x87b2a49646012036L,0xbce6a91de3e6d6aeL } }, + /* 64 << 203 */ + { { 0x7be81fb126882c6cL,0xe2d5a251ecd25498L,0xbb3d40e27a8d1678L, + 0x1806c67ad520811eL,0xadd4bb6686f65d23L,0x3a62b1b3e20e23d7L }, + { 0x208b47006548b3ebL,0x0497f09ab7ec2809L,0xbd3964f8121c37e2L, + 0xd35ef301a598efbbL,0xbd76a276c5eef966L,0x64700a7f0af64e46L } }, + /* 0 << 210 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 210 */ + { { 0x169474a2d3812087L,0x9de300da6698ca7aL,0x8589de922ede425bL, + 0x50e03fea6df8a890L,0x0d8a5c1c4ba8b8e3L,0xf273aa673fffb91aL }, + { 0x21cf054475fc8236L,0x6ceafacf9799c242L,0xc3237eaed0962c81L, + 0x43d6ac34213f6004L,0x45e619b2d4148b6bL,0xfafa18b5ea5fb80aL } }, + /* 2 << 210 */ + { { 0x9a8580aa2f063b51L,0xa83c8ff71c216613L,0xb4da0970be07f781L, + 0x0ac2a260712f7b7cL,0xc9b8ee84436a7b97L,0xd758c20d11fb2f62L }, + { 0x5daabed9f170b799L,0x018d2fddc46bc387L,0x82d6b5b7d96cfb8eL, + 0x4d7d0d9344d9e843L,0xfa2a9ea991e7da3cL,0x8230c1a3d531b253L } }, + /* 3 << 210 */ + { { 0x82412f525ec31754L,0x42f462c89d32e890L,0x1e7b58cece897ff2L, + 0xcfef785241164628L,0x34ee0422d8bb22efL,0x6e0d44ac7d32f01bL }, + { 0x968251655a3cc196L,0xa26724dc99eb23d3L,0xdb575fafa75f7252L, + 0x778e333062a3e5b1L,0x8689884e84cccc80L,0x9883cd19b645502dL } }, + /* 4 << 210 */ + { { 0x4cc41f2834220e26L,0xb5937c6da49749c4L,0x705366640fa1ca24L, + 0xeeb40f3b91e5edafL,0xcdf98235f1d3de14L,0xa65e5b7eff018c43L }, + { 0xaa3228e7acee3a6eL,0xb63a6289e08f4ff1L,0x90e90425650b2daaL, + 0xe4a8cad26d875f17L,0xc212029c9ce8a46eL,0xce0512835ed7cfb5L } }, + /* 5 << 210 */ + { { 0xb0df226159b79436L,0x82bd0dafa195be26L,0xbc99a94b3398c317L, + 0xbeb44c903c96ee31L,0x3c39ad81664d2e46L,0x081787520a3e0585L }, + { 0x9a054b6b413e269aL,0xbe58891d98c3b62eL,0xe7fa4c4de5734974L, + 0x8ac535f4d0a846a8L,0xea0f95f1a651339cL,0xa255274fd96aa239L } }, + /* 6 << 210 */ + { { 0xe23b7b229534047eL,0xbd70aea83a3bd625L,0xf44b05fe238db60bL, + 0x9c46fb140293abcfL,0x12cab5d3bfd8875bL,0x1f38d4aa12dd0c65L }, + { 0x4bed41572adf9805L,0x3f87da928a56609dL,0x10b93363da02c903L, + 0x7ecc726621ce4786L,0x8ae366851e3da5bfL,0x196040ffd3edee12L } }, + /* 7 << 210 */ + { { 0x4805841fe81508e8L,0xe2a578d3a4808642L,0x6bbf10accd0b2555L, + 0xc5071effaf5cde28L,0x665e75439a7124a9L,0x157c11edc1437981L }, + { 0x2019367d7aeddd8bL,0x74a1e104386e3b8aL,0xe72d429bfbe09a42L, + 0xaca96fd9061b862eL,0xbb2d2bc8122595f8L,0xc90c6503c509d644L } }, + /* 8 << 210 */ + { { 0xadb5966fcff05adaL,0x8ed26c025c57284eL,0xa76e73e244693a95L, + 0x14da74355982bbd3L,0x46e982cd5d2ca132L,0x8f39074024938e76L }, + { 0x749206b30a89b09aL,0x429653c793b4a1e5L,0xbee3d1567025bb7cL, + 0xe23f0e1e19555c9eL,0x0dec3837751639baL,0xb36cb84405d43bd0L } }, + /* 9 << 210 */ + { { 0xae76a96e74f90b6eL,0x5fa8e94824c6789cL,0x2b3584bb03abbb81L, + 0xe19ce47c5c451f72L,0x35792fbad619ac7aL,0xfa0282a250059bf4L }, + { 0x562bfd14dabe692fL,0x1aaf542c47eeb6c2L,0x392d5bba045d0360L, + 0x4e7bb31bd80fe998L,0x08f62ef31111e14dL,0x4de917b04e9ee1b8L } }, + /* 10 << 210 */ + { { 0x8b9d2d5867166271L,0x658db4ea142bab7cL,0xdf84932fa4ad2849L, + 0x04b113355f6f86a7L,0x2de6b29c50cfcea7L,0x46d8f68a9be6a3a3L }, + { 0xfb88cda7af0204afL,0x3ece449126029d72L,0x69fef1e23f946dfdL, + 0x708532fb01ef7bb5L,0x78d5053deb3795a2L,0x819a63206b36d57bL } }, + /* 11 << 210 */ + { { 0xca07e0c1e509d19eL,0x6c7e42c39f6281b1L,0x0e2ff43977b66728L, + 0x1d740e7880e76251L,0x6bfae4c631a0eb23L,0xd78ca917aa9b0b3bL }, + { 0xe140c662991e1781L,0x6e396b5f0dd3cfeeL,0xf0a1d1976ce7f6c7L, + 0xbe10f8efd5b01564L,0x865cbd54101a5194L,0xf665885266861dedL } }, + /* 12 << 210 */ + { { 0xe4e52e865b28f7daL,0xeb43a6809a58683fL,0x73b951bfb49f2b38L, + 0x7b6cb7db3f8097cfL,0x9dfb8d0b328fbf05L,0x491635a5ebce6211L }, + { 0xa31a152390fdd577L,0x334120df1cd2f39cL,0x1d22834e6b563876L, + 0xfd91b30d10ee5a28L,0x3d7a282d59aee4eaL,0x36814c6b73300a76L } }, + /* 13 << 210 */ + { { 0x7b584add6621c251L,0x98da669d4233aba3L,0x4d652b7933aa2065L, + 0x901bcfb8df7b4ed4L,0xb2ce587948012f81L,0xc18e2cd63cb71b88L }, + { 0xadb0f2bdff86279dL,0x46d9e5d65bd15866L,0x11b1fb3ec635a4c0L, + 0x8bcd0ad201b1006aL,0x0f6f7502cbab210bL,0xd6cc3e560d6b3995L } }, + /* 14 << 210 */ + { { 0xa54a6420137264c5L,0xa6ef0e78f9c2e45eL,0xba8b5a73d58d850cL, + 0xc0209ed86ef6fc3eL,0xe39dd0f391f7518aL,0x74697b8942b3eda6L }, + { 0x2dccac36abfc9150L,0x80e4fba298b2f5a5L,0xe0e56fd2771018d5L, + 0xa31fd1684c22bb94L,0x8b0998f71a66ef21L,0xed483e55b5a53ddbL } }, + /* 15 << 210 */ + { { 0x95db1c0ef23978ebL,0x80ad1612f04011f4L,0xe76bd1824d7ae83dL, + 0x841d6e668fc3bd60L,0xb68e80796875e2d0L,0xe3965efcd5d9dee7L }, + { 0xc488bb7e58930931L,0x52f4de19a907aa24L,0x39aebbdd321cc197L, + 0xd2f5b1f967de5c66L,0x60f1a8c28efe3e76L,0xf40604a0af988831L } }, + /* 16 << 210 */ + { { 0x78b5c14c0acb5935L,0xd9ec715c4311d3beL,0xffa22ab209e1759eL, + 0x5a86263db4b2f68cL,0x71e77c516b5be7f4L,0xfb5bea3a19844f6dL }, + { 0x2519d0060890ffabL,0x426a03f0f0329ef0L,0x2c6d74a685b3c2a9L, + 0x9306f68fc294f449L,0x552e77c22c69fb46L,0x7c7337ad10bb9886L } }, + /* 17 << 210 */ + { { 0x61f8a505d2b9f25bL,0x1d33aafe4c8645ffL,0x26f3fab7bcd333e5L, + 0x8ff4fc51be95e40fL,0x11cd52c6b55bdd5aL,0xf2b4782a22d43de8L }, + { 0xfe66e399a4c0e1c4L,0x26c6d7fc17954032L,0x44c700f97f20d2caL, + 0xdf67c3927187cdc7L,0xe11a98f9da36414cL,0x0bc5763a04052276L } }, + /* 18 << 210 */ + { { 0xe75b564bcf95451bL,0xd5ed760cc01aac32L,0xccf14dc5980d2c06L, + 0x235b5034ce2a5c0cL,0x64dc86aa05fa6780L,0x1d2ea4877385590dL }, + { 0xb18696f636c3174eL,0xf530487b608215b4L,0xa073d0750a123172L, + 0x8ca24b5afde8666aL,0xd6dd589a9b716dc1L,0xcab7ea504a721d4aL } }, + /* 19 << 210 */ + { { 0x34dee42c1592ebceL,0x5b0eba2e417636d3L,0xba178703a97d7356L, + 0x16f6119f4123e8cfL,0xd2906a53ef179fa6L,0xac5530606b7ed572L }, + { 0x82a25857b600f5c8L,0xb1dc1309973d516aL,0x6d53a967245c6e34L, + 0x7ce90bf4f670b879L,0x727ad4129732b6ebL,0xf00fb0054411dfd5L } }, + /* 20 << 210 */ + { { 0xeba7daad2b14da6fL,0x8274d1a8cee90515L,0x985c18f885bdbc82L, + 0x86555ff094d43909L,0xb0b1b2b6539e108bL,0xa4f32c66c0bf1313L }, + { 0xbd4777c162080e0bL,0x73039da8dadfb23dL,0x85bc57374a27f1ddL, + 0x9a8ae24eeaaa58abL,0x161cb2f5e876fac2L,0x54d457e46636e377L } }, + /* 21 << 210 */ + { { 0x409b17487bece8c3L,0xee36a1d3b49f5c90L,0x8ed9eb2a619ecefcL, + 0xc50a917798ab7bb1L,0x1eb247cceee2ccffL,0x07a9566f084a0f69L }, + { 0x59bda805a7cbee61L,0xf588124ca4e7ecd7L,0x0f7d8c3dde5eed54L, + 0xd98894ddefcb791fL,0x2fd80439ab309d7dL,0x0c8bf15d3e6cf756L } }, + /* 22 << 210 */ + { { 0x076a19c70e68a69dL,0x4d01c94b24b3854fL,0x9f38c5eeea8a85b8L, + 0xea80422d9a56f9c3L,0x10d9ceec9ad36735L,0x42194df742261173L }, + { 0xc7332e70c285d22dL,0xf3a3d4be592ff9b0L,0x2fe712f7f59846abL, + 0xd6de5201e4362677L,0x16ce8f1d4f30006bL,0x1f3c324d11dba5edL } }, + /* 23 << 210 */ + { { 0xa5af9e1c0cb4335cL,0x00a46bc0f3d0dbe5L,0x852a18c99d734817L, + 0xc12d54a9986c0102L,0x184b407063ffe60dL,0xe05182437d99d723L }, + { 0x8d3886cb20ef7647L,0x7e9c618017b1ce8fL,0x194baf260f176141L, + 0x978015d3b4694945L,0x2603be2f1c135e8eL,0xbc0f5e72ba074e0aL } }, + /* 24 << 210 */ + { { 0x1674b959cfe7bcebL,0x62e1279fe7b66a28L,0x3962a32dc67c3648L, + 0x4949617368d720a6L,0x4e81df85a957a5b2L,0x28b5c45753123c0fL }, + { 0x5091dd347e239c67L,0x10b9c3f6160ef925L,0x5e7720f52c119dbeL, + 0xd584ae76c94d609aL,0x476c63ba86dccd1fL,0x70103a1a32508c6eL } }, + /* 25 << 210 */ + { { 0x64f4f4ee90a17a16L,0x31165bee7cb22fb7L,0x31da800b924825b0L, + 0xc2c169db0551e47cL,0xf9ca5e0e0d583789L,0x5e4fbdb53cd42f2cL }, + { 0x6ade1fce1d81000bL,0xa105df391d6603e5L,0xd659094da3139f95L, + 0x363a882851d01444L,0x13cd7cbb2dece086L,0xaeea2aa96ab9020aL } }, + /* 26 << 210 */ + { { 0xdcb31a931081405fL,0x200090dcf1326ecbL,0x773fe49cde99f0ddL, + 0xf6a7cb67fac2c511L,0x95c93429b40b014dL,0x967708d4198dd723L }, + { 0x74591cc184b90062L,0x2539ef20691d2550L,0x7d7290765a5d86c7L, + 0xa81f085475c6fdacL,0x103186d1c0f0d5cfL,0x5ae582e07eb3b8d9L } }, + /* 27 << 210 */ + { { 0x7df39eb2f9f3456cL,0x1e7ad4587be12020L,0xaee54df11fedfb79L, + 0x98f3a0879bf1dfe6L,0xdf958d371d13fb71L,0xa745249717dc809dL }, + { 0x9f2ec9dd02d4eb90L,0x9db5686e48b0c7a0L,0x7d064cbf72532eb0L, + 0xe204d56593a71a9cL,0x0c912346f1aecdecL,0x894224a3d25d243dL } }, + /* 28 << 210 */ + { { 0x6bbf77cb5a508291L,0x2af81442d35db82cL,0x357feb1a2b9febf8L, + 0x74240a81a25330ceL,0x7a9ab575b4917998L,0xa60288d5eda3ef5cL }, + { 0x360410d30aea9569L,0xef66acb5b9bf8c16L,0x7baeb466cc381b57L, + 0x024a98b8247a4904L,0x6e70b4c3e3c58130L,0x276e2420ae8a56d2L } }, + /* 29 << 210 */ + { { 0x3b4a25222c57f1f3L,0xf43d352ba8d1f53bL,0x169fb3cce198b03cL, + 0x92172ca923235a6eL,0x90b5953683f996e5L,0x32b1a34cb5ab11a0L }, + { 0xb944e4b7b9001351L,0x1084de3d28ab5cb2L,0x60f1dc93c70ec63dL, + 0x790e1d496cfa10f9L,0x79bcc2277c3cd865L,0x95007ac24fd31fd0L } }, + /* 30 << 210 */ + { { 0x6b5d8db5f75e17b5L,0xc5ab42961b45a230L,0x586f097b7486832aL, + 0x1ec456c14f289757L,0xd11773bb57b04a20L,0xc84dfacd0821d3dfL }, + { 0x580da8cd586e399cL,0x58c1355ae3bbec57L,0x0a476934d594a2e5L, + 0x0490ffd537e99427L,0xd41348386a4d8c4eL,0xd62cccb3c83d6e28L } }, + /* 31 << 210 */ + { { 0xe6071a3d57c9e219L,0x88728c47a93f38dbL,0x0426848b50eb1a01L, + 0x9df36972cada9a09L,0xf2ad4a2d4f494ec4L,0xae26577de1f34993L }, + { 0x72ec08cde3618d7aL,0xd1fb89013ea90c46L,0x915936173b94f996L, + 0x8703357705387745L,0xf1961ff818fd5199L,0x7f0b58d34c2aeed1L } }, + /* 32 << 210 */ + { { 0x3313a9d544b133d9L,0xdb85c25d2da910ddL,0xc0fdef915e4dd5cdL, + 0x902a2a93c565dd67L,0xd8eba4dc7fed05acL,0xd453995ce157dae9L }, + { 0xd655d0b3f250cb55L,0x4194a09e86119222L,0x5b7e525a0652872bL, + 0xaf7968efe68c0ddbL,0x2ec02930f51cb31cL,0x237f3ae4f2be071eL } }, + /* 33 << 210 */ + { { 0x696d84910dc943a1L,0x1f24fd7d9fe1d7d5L,0xea38c9e349413ad7L, + 0xe223996607c1cecaL,0x62094496ea7bd8dcL,0x9aba5bc7236dd525L }, + { 0xa138ed5851631b6fL,0xed724f20902f109aL,0x3ab594cccb28f1e8L, + 0x3424213b5916dae7L,0x07e5a6df18479651L,0x4c51f2e1c5b48e29L } }, + /* 34 << 210 */ + { { 0x6306564b6591a811L,0x734b2619fd463a13L,0xa795d0569d8019d8L, + 0x103d85004ffe5858L,0xe1962c31adab8484L,0x326b3351b2015dccL }, + { 0x2ad52b852ff36c73L,0x5874652308682fcaL,0xf544e162ea37824eL, + 0xd4a6b45ec208ce7cL,0x52d09045d2559ef2L,0xde1dfbbe57ebca65L } }, + /* 35 << 210 */ + { { 0x3a94aec3bb793f9aL,0xd0af44d4b5352511L,0x1d3f1c130b8930cdL, + 0x016cab225a729e0cL,0x092a7c11e31b549aL,0x80c462ed90ebfea4L }, + { 0x3dcb9606e5e4ae09L,0xad150903ab59a450L,0x1b58210c6c944727L, + 0x26599f6024572a80L,0xfce0ad40c0445075L,0xedca1ada54c4037dL } }, + /* 36 << 210 */ + { { 0x794593303801b021L,0xb19bb405c9a4cde4L,0xe20091667f9cdee9L, + 0x762c684f7636d30eL,0xbf2b29f20c215831L,0x4c0d1b651853fe90L }, + { 0x196ccb3157defc94L,0x9f3d66b7f6b9cc44L,0xb2328a0eea439deeL, + 0x82b3808d7b140e5bL,0x986210dd88e4a35cL,0x9b171fc838a2b7a7L } }, + /* 37 << 210 */ + { { 0xdc80e3ae91517233L,0xa219f65dc6f20d29L,0xd348a3d8be093f56L, + 0x63c233774d33113bL,0x587fd56257f2ce9bL,0x82cf3e3a4e9061c0L }, + { 0x0e41f59bee8dd928L,0x7a5641be8aaef52dL,0xa852a171984ff476L, + 0x3c37fd1c047457b6L,0x7f00d665972d4793L,0x29dab0fd97b27966L } }, + /* 38 << 210 */ + { { 0xb1d119c91e9d07c0L,0x2f973a09432c86afL,0x3505b6f05ded5546L, + 0x21814b958687f973L,0xc104d7fad3794ae9L,0x81614d707ea91311L }, + { 0xb7f3e6b600677961L,0x53fceb8bc0e6a90dL,0xa3a7485699ed4fb6L, + 0x07ad488421d4807bL,0x527b1ae6004e0c03L,0x437f306215146393L } }, + /* 39 << 210 */ + { { 0x917b4cf463e12603L,0x79e0b7363f838ecdL,0x57de4b3328b4f37eL, + 0x3085e4887f58fcfaL,0xb9301c4e958a3bc6L,0xef8d10578b044eddL }, + { 0x2123d284d6391459L,0xdfcc2be5e196d765L,0xb58216268184b993L, + 0x13e21d03937c6048L,0x39eb3d38460d11fdL,0xf8ef123e5bb23c30L } }, + /* 40 << 210 */ + { { 0xa6f8b354666eb2f0L,0x7fbf6d91f9c7b16eL,0x9b360814161b5e0bL, + 0x13726fbd921511a4L,0x37aa1b8013833a11L,0x53f01183407b9889L }, + { 0x8a83ea3fd147da9fL,0x25279241db0ad0b1L,0x78353bccd1a8d9aeL, + 0x1e33c10e271f7f0eL,0x136d9e7e9e67adc5L,0x11dcef95cc56ff8dL } }, + /* 41 << 210 */ + { { 0xae530580d84ba919L,0xac2e43ceb6d3ecd5L,0xf97b1afda4bc6a2dL, + 0x180d66d5bdfa96a0L,0x935b8a7d1ca12bf5L,0x1d4409a79e678225L }, + { 0xdd85bf4b19a2163cL,0xe34197bcddeeb22bL,0x1e33fc3e1210cde9L, + 0xc96212a98b9b5d0aL,0xa3ae81f303e4a12bL,0x531a7148ea262807L } }, + /* 42 << 210 */ + { { 0xf11ac5fd4ace8006L,0x898a388133c499a5L,0xcf27ab9f1d3368ffL, + 0xfb6019606cbd6e54L,0x5373c2a901fb58b6L,0x1489f5037cd1b888L }, + { 0xb3f0e0b85a238131L,0xd0e11e6e670858bdL,0x897f1584b65768f8L, + 0x9252aa72013b1f2dL,0x185842af0a1a5f8bL,0x49a978373d681a70L } }, + /* 43 << 210 */ + { { 0x8b65c6d23396eaf3L,0x2191764e50b9392fL,0x7a2363b72dcf6d0aL, + 0xa6a52402f0591553L,0xfaba81cd5ff7a071L,0xd6be926ae43e37aeL }, + { 0x7b34c578ccaacef2L,0x2bc5d248d5eec9b1L,0x9447aab3014c0048L, + 0x767309a3c02d54d0L,0x408c6eee1f92297dL,0xf7ad95f40072a2d4L } }, + /* 44 << 210 */ + { { 0xd0051ab940ee5098L,0x4861b2461d8311deL,0x6b7796e0f31e860fL, + 0xde8b243acfd543e3L,0xef9d0957a0161843L,0x70fd43ecefefcbaeL }, + { 0xd47392541931a5a6L,0x42e253300342623aL,0x90b33edd52ffbf5fL, + 0x0affda4ca015a550L,0x8716376b77e59672L,0x39d84b33fc0e9448L } }, + /* 45 << 210 */ + { { 0x71b55e7ea0415173L,0x5d0b5e01b10f3cd5L,0x0c35a1b63e3f9d84L, + 0x3c68cb5db794ba37L,0xa73356f0dfd6c999L,0xc59ed0650e5e221aL }, + { 0xc59443a90cd7d577L,0xa354296e283015a8L,0x202aee3ba7477107L, + 0x59f361392ee80330L,0xc52bdfaae875a886L,0x8ca39d9d07637e97L } }, + /* 46 << 210 */ + { { 0x95be10b8f3a1611dL,0x6db370f0d1f992c1L,0xb964029de8124b40L, + 0x618b26aadfc90473L,0xac65c9916f6d5553L,0x10d5b0f0a0a6fde8L }, + { 0x4bff23122d164911L,0x876db39d1f7293b1L,0xa2d3cd549de47789L, + 0xd8ca4f6eabc9a28eL,0x0bb3145fca7b5467L,0x4dce66338b37bf62L } }, + /* 47 << 210 */ + { { 0xcdd8ec4dec1b8d36L,0xf76258d888003e0cL,0x35a114e7262723f9L, + 0x12933142abb34bcaL,0xf55b84514c188a3bL,0xa0cfdb2c0ada78b6L }, + { 0xaf0b62f6ed36781cL,0x0c619486ea7e1ca1L,0x11fae38689162fc3L, + 0xe9bd7ae694828e92L,0x081c3acda84cedb9L,0xb34ceca8787a67e0L } }, + /* 48 << 210 */ + { { 0xd1b2af2f2bca651bL,0x2211e4f97404bc78L,0x787b1cc8fc5068f2L, + 0x73d6da299fcbb3f5L,0x6867fb7707d2142fL,0x36f277ae116ad6bdL }, + { 0x81c86073a7534943L,0x67188488c4033c7aL,0x13a8415ccc568123L, + 0xbc01db07f3f475deL,0x90b8af2e3aaeee1aL,0x320c4880175fa55bL } }, + /* 49 << 210 */ + { { 0x263afd7d2fcafc9aL,0x9b0c30ebcc9405d6L,0x713fdd27d6720896L, + 0xb07f8ec5f7df4a02L,0x05d62e5147ddd4e1L,0x6278227b8ae3b80aL }, + { 0x2ef5c81b0d4ab658L,0xe6ad5925016a434bL,0x6c0e30a2b85d8037L, + 0x254830037a9cd869L,0x78da543b2cc48c8aL,0x3a65b54e3edca4dbL } }, + /* 50 << 210 */ + { { 0xaf2a06c3d54b0072L,0x81621ebfaf0310c5L,0x6bd1fe41a8a7a9ecL, + 0x942cf6ba03e74289L,0x2a25f0f59f9822e8L,0x16654b13062edd3eL }, + { 0x2345a0b19de373cdL,0x425a59f80c0744acL,0xc6738fe96f0d620aL, + 0xaa479ef8ed67c1a9L,0x52540af87765b194L,0x17a3bd3bf2b96455L } }, + /* 51 << 210 */ + { { 0x5b1a1f075f01e608L,0x3c696f4e87b821c5L,0x4358a5243129700fL, + 0xfc9816a14be9d001L,0x905de48166744b96L,0x2ca5f8d8eeda3945L }, + { 0xb30eeb1aad207f4eL,0xbd113b2dbc66e6f7L,0x1b6c5c6cebaef81dL, + 0x6b3863998bfaf32bL,0x5f9f2a2432a83dffL,0xe8cc190e26ea39d1L } }, + /* 52 << 210 */ + { { 0x51e05f7d450535fbL,0xa5f5181effbe389fL,0xdf178fffaa2d5514L, + 0x89358810e51da035L,0x206e324f664d399cL,0xc148ae74c4477d4eL }, + { 0xe0c8d4377d6f38d5L,0x327aad6d8c8133e9L,0xa685a889d21cac4dL, + 0x1217c68d0ceb5770L,0xa4a09612d21f1d50L,0xab64b4dd889676afL } }, + /* 53 << 210 */ + { { 0xf263062aee202007L,0x95e90bbda2359019L,0x57740eb39f34e691L, + 0xa5f4fd0f355bef37L,0x484b97fb439f091dL,0x642776fe53ac871dL }, + { 0x5c8f9b1e494e0eddL,0xbc62c971ae25a6d7L,0x01981994a7d90290L, + 0x3cec43524602cdc1L,0x4bd29f5a14403ae2L,0xafaef08b921328d2L } }, + /* 54 << 210 */ + { { 0xd33e754a53ef149dL,0x82243def548034e6L,0x99c29a9b23ea2dcfL, + 0x724e4b5d214848afL,0xe43d4438dcf85b9aL,0xaf7241ea9d7b20dfL }, + { 0x60a10c30069edb1bL,0x1aaddd5e9874f484L,0xfc784ac073085538L, + 0xc998afe54d69703aL,0xb71f6fd7bf52139fL,0x28f994c46a45b089L } }, + /* 55 << 210 */ + { { 0x85084ec2eebd9e0bL,0x73e489c6cb9f1929L,0x91e47fd7ebe10e55L, + 0xeed6a3a1486a2704L,0xf63deae7e124d6e2L,0xca958204b48b3834L }, + { 0xe69cb5bb13185b44L,0x56be0e05868d97d0L,0xc48cb1e50181e64dL, + 0xfaa012ddfc7827cdL,0xf535b1c83488352fL,0xd1cce04e9fbf42d4L } }, + /* 56 << 210 */ + { { 0xa54436b6ba3403ffL,0x1fe4b1ecdcbc4822L,0xb3b351004c6846e2L, + 0x360278048d1cac7cL,0x9eff87327e86d5d1L,0x7f435326ba21993aL }, + { 0xb51a9da5adc24224L,0x111c19fcc8c14a71L,0x05aa2c86ab77e011L, + 0x81edc338ce72744dL,0x20fa8f528d882bc3L,0xc61c3e639d1696f3L } }, + /* 57 << 210 */ + { { 0xa66674ca0f41637cL,0xa01d08ac418487daL,0x2ce4258b6b593194L, + 0xd755220645024db4L,0xffb3366f626732ceL,0x802878f370ba2f1aL }, + { 0x80a3f41659b77372L,0xfbb411631a04b19cL,0x7d575112a346d265L, + 0x6c30421ffff87d4fL,0x1b62b93fdcb05f02L,0x98ba4397b72649e3L } }, + /* 58 << 210 */ + { { 0xcca45c1d135a7eb5L,0x2623e629b048126bL,0xada7326e926980f0L, + 0x64f334c276bf796eL,0xf0751596b4a562a8L,0x0baa14486f9d0079L }, + { 0x6c394aa32205ea70L,0x635b9d2d556172e9L,0xf418fe0cfd37b53bL, + 0xcf5fe2ac56b9791cL,0x9d855e67911c68ddL,0x9e40f75f734b57d8L } }, + /* 59 << 210 */ + { { 0x32c42482b5b8f846L,0xdefec599b61cc3cfL,0x4c3460996506a9b5L, + 0x0d9475a0263a6142L,0x1753cd92c80a6713L,0xc015412f420cf67eL }, + { 0x1c33f01b6a88d12bL,0xa49f038ef522f7d0L,0x232343decd25f260L, + 0x479bc742d6a833c3L,0x2f2ab294cee07b83L,0x02e69a143dec38b3L } }, + /* 60 << 210 */ + { { 0xbf7fea3aee1fee16L,0x31fb342ce0cde85bL,0x9a232ea51575924bL, + 0xc3132e6cbcc4cf26L,0xbc5b7a7102499a58L,0x3064a3b904d99836L }, + { 0x6f17475ff8b3bad1L,0xaeeb90c429271790L,0x7f442a13f8eca53dL, + 0x6d641eea08882274L,0x8dff43bf88ffaebaL,0xaa92827f5840b198L } }, + /* 61 << 210 */ + { { 0xf5ce3fca26d803acL,0x6927ddd9d4e1b6b5L,0xb509b5c609f48bc0L, + 0x2bc5d1749e35975aL,0xfba3024af570c98bL,0xeba15980aa27d6b0L }, + { 0x95abc07290abd2daL,0xd0e30e99232035cfL,0x3dc4e1bcd3f0ecb1L, + 0xa5a8c6e556de9d17L,0x878c7403ab73bd18L,0x5cce39260c474b0aL } }, + /* 62 << 210 */ + { { 0x86a3f001e93b6ee6L,0xa28984474fb3203aL,0xbca0d71e9b3550adL, + 0xc225759d0396d796L,0x208b9a02cbd949d8L,0x15b21ec9a550d2ddL }, + { 0x64aaed6a2a7dcffaL,0xb8cc7575ed5b6b47L,0x2b4a3aff022dbce3L, + 0xe85d690b86f51861L,0xe26a6c3d578f4d5fL,0x706d770a70e7ae76L } }, + /* 63 << 210 */ + { { 0x822467eb579c91a6L,0xe98a471531599272L,0x7baf0e9f1078d497L, + 0xd13f270e25fe439cL,0xae9d58adc0d95395L,0xc3beb60827693037L }, + { 0x4d9c4cf397f797e5L,0x4e26167db26d2e9dL,0x06092d5e86a167efL, + 0x9827a21128dceb29L,0x30423344552a55ccL,0xae07b37f3fa437afL } }, + /* 64 << 210 */ + { { 0x9b23ab4e94d0864fL,0x46356266009c9fc1L,0xdbe99e51e798edf9L, + 0x38547449307675c7L,0x23ffaf55628c0fb6L,0x56ccd2a31698c372L }, + { 0x39f45a578347ce95L,0xe0aaec744f2c6118L,0x2a89079e4af138fcL, + 0xb86371ea2ee4ecc0L,0x076d256a06bbf92fL,0x9073adb8ae3c4c51L } }, + /* 0 << 217 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 217 */ + { { 0xba2e9543743c15d9L,0x7d5812db1c99c984L,0xf94db95145bdc19eL, + 0x951d00ae382e77bdL,0x9940a5fbb220b29aL,0x6908d50e58fc91f1L }, + { 0x682e42eadd0940feL,0x2124e23aa1d32009L,0xbe15810016294d05L, + 0xaea13fe32e326d68L,0xc0dfe1ef15e64fceL,0x32dbc0b5b8237a8aL } }, + /* 2 << 217 */ + { { 0x6ee65a08c36d3f25L,0x7b6c811fe393e4d4L,0xc4a2cc382876e523L, + 0xab7aba26d3bf53aaL,0x5bf00871db7f290cL,0x3cb1cd131ee6d5bdL }, + { 0x4cafb218de998adaL,0xa1ecf36af6319101L,0xa1fe785520b281ccL, + 0xe457198e64d9c65eL,0xa3d1a6d0c5a0e67bL,0x69ddbc3290cc468aL } }, + /* 3 << 217 */ + { { 0xd4ee3f7f6dadc46fL,0xa1f3dc925d7febd6L,0x4c0bee1363ebab5bL, + 0x70e32d77005ec237L,0x302fc73dc52fb006L,0x1af84c0a8f159899L }, + { 0x42a5478f0686232aL,0xb4fc56348a308687L,0x042c4970c8378f0dL, + 0x70c195758e2c86c5L,0x61a95e6884c7c767L,0xd96a8216d6fb43a8L } }, + /* 4 << 217 */ + { { 0x0c62fd2d543c1255L,0x71ea9c6fef361a27L,0x76b0933dcef3f9e3L, + 0x51b1ec2d9889ffa2L,0x9e84b2ba9a3c88d2L,0xc8996b961913e52fL }, + { 0xbafc5e94cee43e36L,0xd9898d2470c658b7L,0x4e9bcc41bed17108L, + 0x0db5b7336c7a41c8L,0xd4be07a7795369cdL,0xb899f92f7bd3a934L } }, + /* 5 << 217 */ + { { 0x1fffcbc010e15fafL,0x8447bdb8910245acL,0x857d521e86476901L, + 0xcd1d5f87369ccfe9L,0x560b3277b3f1dbf1L,0x4ac02a1a47ea4266L }, + { 0x29ac98b6a8a929eeL,0x020ec6db5e5e70c0L,0xb0be38ba21291be6L, + 0xcbe9d362bdba40deL,0xc585450571535a89L,0xc21839de3d7a3235L } }, + /* 6 << 217 */ + { { 0x831541b39805497aL,0x2ceb5ac879c414cbL,0x86601fa616d2eb82L, + 0x373d19079338ce8eL,0x98151a90c1f5c87aL,0x966ebde6048a538cL }, + { 0x5c4a8c5ae180ff7cL,0x6d9065dff996d994L,0x4e0dd86e2460ab91L, + 0xfbe8b3ff309a8f5eL,0x33d7cb35856f7218L,0x62b2200a1ac59f2aL } }, + /* 7 << 217 */ + { { 0xb36ad750a460e53fL,0x727006d60df0f7b0L,0x6ca3ac348ee96a11L, + 0xb04f6ae930e75d1bL,0x9957738a3a24e9eeL,0xc0117a7d16521e18L }, + { 0x79fcea8872ad7e27L,0xcbe2c2d37281e3b5L,0x31915f1cc391fc60L, + 0x1c1c0082a13a92e1L,0x362663cc7ddca7acL,0x8021aad689689d35L } }, + /* 8 << 217 */ + { { 0x3f2eff53de1e4e55L,0x6b749943e4d3ecc4L,0xaf10b18a0dde190dL, + 0xf491b98da26b0409L,0x66080782a2b1d944L,0x59277dc697e8c541L }, + { 0xfdbfc5f6006f18aaL,0x435d165bfadd8be1L,0x8e5d263857645ef4L, + 0x31bcfda6a0258363L,0xf5330ab8d35d2503L,0xb71369f0c7cab285L } }, + /* 9 << 217 */ + { { 0xc19db6f05890e1cbL,0xc21587edfcac8d05L,0xa9e88798d86730edL, + 0xee3e6ee2c27441cfL,0xadb2c63ea23af57fL,0xb524b7da29ff5977L }, + { 0xab1ed847d3e4739dL,0x6592a0131cbfb581L,0x1f519c6ea1798195L, + 0xfe837a814c324a4dL,0x74fec4a85c813abcL,0x7b3b5351dce539b0L } }, + /* 10 << 217 */ + { { 0xb886a0c50c99e321L,0x4063d19576e924e9L,0xc03cca041a659dcbL, + 0x1e01abbc1bd3dab0L,0x9d7cf04fe9141cd8L,0x5f87dfa73ef58d85L }, + { 0xa579e76388d764b8L,0x381dec6a74b9e5b3L,0x354221f99a4c9a67L, + 0x8c2556d33f529346L,0xced3642bb4349eb7L,0x1527cec7fef5c92cL } }, + /* 11 << 217 */ + { { 0xf2e42ef7785ecd51L,0xca3438cf33d9c0d2L,0xeef9ec08c1c097f3L, + 0x9e438fa746682aa7L,0x53d0144531a7eefbL,0x04431241e6998a0bL }, + { 0x2c1bb2bd55bc7febL,0xed99e7afb44d4943L,0x7f37bc4a3c77d21eL, + 0x866c0978398e3997L,0xed7462305bde12b8L,0x24796f7c7194fd1fL } }, + /* 12 << 217 */ + { { 0x7e4450cd5e83d570L,0x0113cab242b394e7L,0xdf4062a08ee24413L, + 0xf8a0fd4931227510L,0x06b798f4b80f0d23L,0x33f17673b72bffa8L }, + { 0x4638602b5de9f490L,0xbe3a65834d905654L,0x446e0afaf406772cL, + 0xef68dfd7b4ec908aL,0xa6be004966ab5ebfL,0x56049360ff376531L } }, + /* 13 << 217 */ + { { 0xb47202b760b6ce82L,0x8129c1befe05e9faL,0xcb70cbdde861de07L, + 0xcf35fbc5af16b6d9L,0x60071beec9916116L,0x3aaa496ed057e63cL }, + { 0x1cb0bb12c356f065L,0x12dccccef4de0d26L,0xe3f59cf67ccc0d48L, + 0xd66f10b3d9569e26L,0x95f4d7e79d1853ccL,0x10313dfdbf651d5aL } }, + /* 14 << 217 */ + { { 0x779b55062a3d9774L,0x3785db08e0554291L,0x9b3a4eb8546c69dcL, + 0xfe36824dd22d8fc8L,0x037d9ac9471132a1L,0xc895e332a01e1c28L }, + { 0xe535ede71b5e2845L,0xdc90cd7c568743deL,0x3292b40b4691d367L, + 0x911fad21b4f16a4bL,0xb3c5f0eb455d018dL,0x2eb2def669033748L } }, + /* 15 << 217 */ + { { 0xfd1297a4307aa8fbL,0x021f242177952146L,0x17cc2d6f0ba72feeL, + 0xa265095d01a3a733L,0x2e12c2e7a07d5f8bL,0x27bb60341202224cL }, + { 0xb58b3fab8185dc12L,0x83467b977700f166L,0x98242e227ff9e1ccL, + 0x96b2a4d9f4b28f1dL,0x64113c3865ed82eaL,0x7dc9ab732ee160e8L } }, + /* 16 << 217 */ + { { 0xf16938f514c5969bL,0xde2e3cf0944b2271L,0x2d5095530b6490d6L, + 0x8432fef1a28a296aL,0x6f254dd08d26415cL,0x3780eeadd50c2865L }, + { 0x4f5bc455665b8794L,0xef31fb9e56cb7018L,0xbab8dd6e65e59340L, + 0x676baca2a56dc2eaL,0x38eea06beaa90e05L,0x26e64224174bada0L } }, + /* 17 << 217 */ + { { 0x309e9fbe109cdb79L,0xc2ed3566977d0e4eL,0x2891f30be6b944aeL, + 0x514bd4cf5022e070L,0xae9a22a98726a661L,0x1114a0c8c1916b06L }, + { 0xe1b4f8339795adecL,0xcc0f3824ed4dbf8cL,0x432c93c878096a66L, + 0xb9450e9da7d2ad83L,0x294b0c192c1e35ebL,0x791427038be5a953L } }, + /* 18 << 217 */ + { { 0x4d215132881faf35L,0x52171a5ceec736a8L,0x4788813e1ba561d5L, + 0x9ca022a7d35e399cL,0xbfcaab926c4b8d7eL,0xde62b2c007c7ec40L }, + { 0x7b46c2d96bb54e10L,0x2ce02e5a7d31e85aL,0xb757b699cd776c12L, + 0x08f122552c81b71bL,0xaca91e058aa6b02aL,0x35cf7bd37209279dL } }, + /* 19 << 217 */ + { { 0x24b5bc7086a04b9aL,0xd4d4c640612e0fbcL,0xb19ea7fcf732589aL, + 0xa18b6f4081fc63cbL,0xddd7211d84d88fe2L,0x7e8db6f72963130cL }, + { 0x8772908c500c491fL,0xa3bf747783fd8a41L,0xca54d0d34e3e9fe9L, + 0x9969471866b030d5L,0xc2f5fb98b1fd6736L,0x58d5a851d103fa45L } }, + /* 20 << 217 */ + { { 0xe4c16fcda97a5decL,0xcc4333092f1dd4b8L,0x8cac9da985d334dcL, + 0xb4deff204cda5a0cL,0x59eea4c9be70b1b9L,0x161e73a2ec5b7b58L }, + { 0x584c5e098b7fb4a6L,0x697fb795a3f7dd08L,0xc9e15f754bd4ba2cL, + 0x66d04f47c83df783L,0x0c03c2452efedf63L,0xa76a08c94a87dbb4L } }, + /* 21 << 217 */ + { { 0xde4e18c2da669a50L,0x0629350a480fb520L,0x84b3e68b7cac0748L, + 0xab718a12da3e1e9eL,0x3f5c5489cc26aed3L,0x81c6b6d42a57ab3bL }, + { 0xc4ded8ce15d23825L,0x2d753e6a20c6eb43L,0xbaa120ec555f3a83L, + 0xc72f9d3877e93abaL,0x4ce297d0373317cfL,0xf42b3e954845bc1fL } }, + /* 22 << 217 */ + { { 0xbf162c19d7480e46L,0xa7f45ea76403bf0fL,0x250e936c6c51cef8L, + 0x97ba086f1cd24b64L,0x271a22364cfb2889L,0x2685c98804dc4b48L }, + { 0x843bb75ac877f6a1L,0xe10cd5c799d5c7bcL,0xbe65eea1db60606aL, + 0x9019a9a7a10d0d74L,0x5614c0b987c62e5eL,0xaab2308d38240d05L } }, + /* 23 << 217 */ + { { 0xc908c6929a772e03L,0x73441df703928ce9L,0x36141b5bcf111c12L, + 0xf6b9e2f16c7c3e5dL,0x1f245a77722c5b57L,0x07e3f364635f65e0L }, + { 0x1aab7abf272597d8L,0x03954428d4fe8e71L,0x7dd58036ecae1b5cL, + 0x9b97c2f28c85b0f0L,0x68ed3dc6ace011e9L,0x8e4ab5ca1744a774L } }, + /* 24 << 217 */ + { { 0xe6a19dcc40acc5a8L,0x1c3a1ff1dbc6dbf8L,0xb4d89b9fc6455613L, + 0x6cb0fe44a7390d0eL,0xade197a459ea135aL,0xda6aa86520680982L }, + { 0x03db9be95a442c1bL,0x221a2d732bfb93f2L,0x44dee8d4753c196cL, + 0x59adcc700b7c6ff5L,0xc6260ec24ca1b142L,0x4c3cb5c646cbd4f2L } }, + /* 25 << 217 */ + { { 0x37daf7fd5a96d915L,0x1bba82e6d16a1332L,0x7558b642ce1135d0L, + 0xc9fcd6ce3abc5915L,0xc3762a20b93ad4d3L,0xef0cdb45e4e74f82L }, + { 0x809b91dcd26fbab6L,0x1264f72ea9b53697L,0x264699ffd7c827f1L, + 0x16d4f094d8c4976fL,0x244c90cd997df2caL,0x58eb3b1c76f77b3cL } }, + /* 26 << 217 */ + { { 0xb99e2dde1ed04268L,0x94247d202497b83fL,0x0c6c21d1fb833507L, + 0xa01e682fafab9c39L,0x4938108f4d84c3d5L,0x70b68c75347652d1L }, + { 0x458e814740e17747L,0xca752a14c3f8bb03L,0xaa537b4d8598d044L, + 0xeec3febb7ff102e0L,0x10ef3cad247fe4baL,0xe4de5b1b5673ac39L } }, + /* 27 << 217 */ + { { 0xbca2931378d0bb1aL,0xfcc237068e5c3fe4L,0x0f9d6b11dd0d67a3L, + 0x9aec22faae14bbd8L,0x75f8d86e5bda7184L,0x6bcad95759aeb4c1L }, + { 0xbb1224a5990a9309L,0x00edc04ef7193f45L,0x870c1647c17cbff7L, + 0x9855513c65031caeL,0xe5a2e2ded852b607L,0x540a4141e5671e25L } }, + /* 28 << 217 */ + { { 0xfb0e2f2e4d5efff4L,0xbf3b96e73a143fd6L,0xa18a037f18579946L, + 0xae02fd4ce48c8a51L,0x1cb139288745c177L,0x4991594a28c47832L }, + { 0xdce3b1d2fd51c1a2L,0x4e707213314cb09dL,0x5312de95ee323449L, + 0x4925c4e789389866L,0x2438fd9e28ca17acL,0x58fd2aad872dc0acL } }, + /* 29 << 217 */ + { { 0x75bcf0ef54ddedaeL,0x3cc75fc6f9077493L,0xc91b78df60f6b874L, + 0x7687a1d0622634c1L,0x57fdef4f82cabf32L,0x544819218e2671e5L }, + { 0x526cbb27a3c37afbL,0xe0db88340d1aec76L,0xa034badb73cdef1cL, + 0x165cdfad6281f26bL,0x5c90d4d1ce24a71aL,0xc404af1125f297a7L } }, + /* 30 << 217 */ + { { 0x6b21a0ea2fd5df44L,0x2da8dc6cb36e5b1dL,0xa683e08ac3688655L, + 0xfc5fbad3454bf878L,0x9d2fb9f12f73b749L,0x4612cf42f920b37dL }, + { 0x23da6b697035794dL,0x2763828adff7c198L,0xd320660522dd7eedL, + 0x6829994cd1316e68L,0xd732bc8f62831ed9L,0x69c6972c9303d789L } }, + /* 31 << 217 */ + { { 0xf5901854b0dcc28aL,0x81c92c1fcd18e579L,0x91a412ebc4b8e1cdL, + 0x35f00725891d6ab8L,0x10d6bad8ad7aa63dL,0x8cda809d09df2b47L }, + { 0xe856cfbfa489c233L,0x7ea921addf1ecf5aL,0x884cc717fd724c37L, + 0xe278f2457377136bL,0x240b142d9f3dc9ecL,0x80a384961139a645L } }, + /* 32 << 217 */ + { { 0xa35e411c2cb40964L,0xdd7d4f4cc331a3d6L,0x7c7c859e89a66f2bL, + 0x9908c37e0def8ecdL,0x8274124e344947b7L,0x0d279f7b568b0ce8L }, + { 0xe5291961866091ecL,0xb056e3bf3a08acc7L,0x60fb39e156bd3a7dL, + 0xe56a34d6268f8562L,0xb3a1fe1613fd8293L,0x6a41e1a967537fcbL } }, + /* 33 << 217 */ + { { 0x95c2bbfe021fc932L,0xc7e3399db2af7e0cL,0x1224bf06122670f7L, + 0xc9e4513ffcc1fe85L,0x8c82371ddb50fa7eL,0x017c5498bb76e4b5L }, + { 0x5467926c7fa89f61L,0xa4a65606f3a1204cL,0x22133acfa64b2e59L, + 0xab7896bce1247662L,0x75d35fb661780c9eL,0x99199644a91b33faL } }, + /* 34 << 217 */ + { { 0xf799c4638471104eL,0x43c122dd8b91c351L,0x9db6498616dc06f7L, + 0xf7e534410ebcf250L,0xa702c0f18373f9bbL,0x6ed8d39a1024e14eL }, + { 0x92913e436cabd9c4L,0xba906ef40dde6283L,0x06835e914a3972d8L, + 0xfbba3c7dfd99c4feL,0xf843e6f1b950909aL,0x7ec9866df5160b4eL } }, + /* 35 << 217 */ + { { 0x68f75bab06722bd4L,0xdeca718813066eeeL,0x4d658fa11152b8c6L, + 0xfae01e657257c9e2L,0x999445f923e4189cL,0x2cbe272cef6f0b1aL }, + { 0x5f60d9d735fff303L,0x4ca7a54696235360L,0xf506201598758f1fL, + 0xba81e7ad1dbaecbfL,0xd326e063c687425dL,0x8c46fa4b193484c5L } }, + /* 36 << 217 */ + { { 0xa97149cf3c1f5f12L,0x17b04a3d143d72b6L,0x174195ff17449a22L, + 0x851803960b136adfL,0x8d87d21f9a7adb22L,0xf9c9fc85a8f46d49L }, + { 0x7839f453a7ed1b7dL,0xe19d80ace9067ba5L,0xc387a6a0e41b8d6eL, + 0xd11611e1241d287aL,0x2561ed02636240beL,0x3bd8c57df0fba033L } }, + /* 37 << 217 */ + { { 0x7b5caacd3ea8ec1cL,0x221770e944624802L,0xafb1a4df5a32468aL, + 0xdec20eb62e295525L,0xe1cd4fb9e309c92dL,0x0331b9c0e7256005L }, + { 0x987d4c55246f2fddL,0xa392d27367f70f8fL,0xccba11994e214e5fL, + 0x789f0e4c9943562cL,0xf502ec237235c86bL,0x67403523987746d6L } }, + /* 38 << 217 */ + { { 0xdd02ced216c97e7cL,0x578d6912dc3347baL,0x760260da2134e993L, + 0xf96643dff34fb26aL,0xec214b767ea3285dL,0x19b135d4117733d1L }, + { 0x29a0e0636b037168L,0xb5df2bb95d1285eaL,0x5a2d3297796f0cc4L, + 0xfcee639f2090e0b9L,0xba11e8a4d93c091dL,0x5b6fc501492250e5L } }, + /* 39 << 217 */ + { { 0x6019d207263929d8L,0x9821d6e81f164aa2L,0x8f1b33f8d4924236L, + 0x389e482fb72de1b1L,0x398785a862554c10L,0xed31cf8408469265L }, + { 0xf9b99e158a09f334L,0x9ddfd4eba83df391L,0x28a5cdf4caa4f7d5L, + 0x32b9e3c68f68fd49L,0xbce64b93b6f52209L,0x72649c6fea7c4bdfL } }, + /* 40 << 217 */ + { { 0x8a15d6fea417111fL,0xfe4a16bd71d93fccL,0x7a7ee38c55bbe732L, + 0xeff146a51ff94a9dL,0xe572d13edd585ab5L,0xd879790e06491a5dL }, + { 0x9c84e1c52a58cb2eL,0xd79d13746c938630L,0xdb12cd9b385f06c7L, + 0x0c93eb977a7759c3L,0xf1f5b0fe683bd706L,0x541e4f7285ec3d50L } }, + /* 41 << 217 */ + { { 0x73bc200cfdd5504eL,0x73322fbf3825b0c3L,0xbf8bf1edd35c24d2L, + 0x54eba9f52e2bc29eL,0x80ffb5fff3aa841bL,0xbc676f62cc188be9L }, + { 0x2e2f79290383f0dcL,0x886c647e0d42059bL,0x673f0ea113eb7019L, + 0x630da63f3f9cd771L,0x2597592b3a0a42b2L,0xfd21fb21b83b8673L } }, + /* 42 << 217 */ + { { 0xd39ebb9fd2b34df5L,0x622bd0c3db873666L,0x546cc7f77b52738fL, + 0x0323cdd1c156c52eL,0x78b00818b5950f19L,0x8065a86a562bec17L }, + { 0x0b42eb1427ca5a49L,0x1791eaf1a457ac04L,0x3a2c93a6b2631402L, + 0x28b9cd6fcacec5dcL,0x6a0a8826d4535a3dL,0xeb08a884a83fcdcbL } }, + /* 43 << 217 */ + { { 0x16bae8925a940b6dL,0xfec394c1789562f0L,0x54349605ea412ea1L, + 0xccd57783cd18e2cbL,0x394bea1a1c813e61L,0xf11c566ff249dd67L }, + { 0x2cd679c112207f37L,0x7780918e83d16012L,0xe8bdbef4646c9987L, + 0x6e1882e5082dbbffL,0x811dd74777abe4acL,0x5bbbb740668380adL } }, + /* 44 << 217 */ + { { 0x0969263a7321c39dL,0xbd13b28bab7aefcaL,0x10e431f205377165L, + 0xbbb2a7d009442c57L,0xf935bc2d9cd156b7L,0x66c3d55e42406686L }, + { 0x4c529b76d20bdc50L,0x112e0f004d1c9f24L,0x414f1c65ed38dbc3L, + 0x63ade49c4eea65caL,0xbefd8af5fab697e8L,0x727bd3b45cc3b209L } }, + /* 45 << 217 */ + { { 0xb89d450a957925f4L,0xcb39b69c6e1e60f3L,0x55396e61ae3fffa3L, + 0xe89d97962986fdceL,0x5521d6b787fcd037L,0x6c20b2b0ec718024L }, + { 0xb1e0964bad6529c9L,0xe1bdaba3bc38493bL,0x6a9cf9d6f19b4690L, + 0xa2d035f7054466dcL,0x37df7fc07fa65c9fL,0x045b0b36106ef822L } }, + /* 46 << 217 */ + { { 0xe4fc833eda5c9577L,0x22afb5addfbbca7cL,0x215de02eb902e8d9L, + 0x215e4c900f1a6cb5L,0xf6d7e4a9d59e146cL,0xcd0c6c6e4912eb8cL }, + { 0xe0616976eae22897L,0xe2279d9f5d809d19L,0x2da1b7b3e282b2e5L, + 0x19327068ebf058b7L,0x9b23df0f5934492eL,0xabeb464fb1752d68L } }, + /* 47 << 217 */ + { { 0x6e754efc00d03f9bL,0x64aed0bd38b94393L,0x9d084ba16df2f6dfL, + 0xfe383a56c6abe8f3L,0xd23c6ca2bc7bac13L,0xde8ef161e326b691L }, + { 0xbb4e853342f96925L,0x1391974f6601dc73L,0x3a545ffb700480cdL, + 0x4d379c538884e214L,0x0fe40f66f713e900L,0xc7f202cbfff783ffL } }, + /* 48 << 217 */ + { { 0x89e48d8bc6bb5e5fL,0x0880ede01ea95a10L,0x60f033d7302c0daaL, + 0x15e4578a048eefe3L,0xfd6dec89b0a72244L,0x1f7cd75e309489cdL }, + { 0x7cdcc2a0e9aba7fdL,0xd18dc5c7f28ba00fL,0xa6300a455812b55fL, + 0x8fa5c4152ca31d8cL,0x36aa3c234f3a5b5aL,0xd128739ec86cf4e0L } }, + /* 49 << 217 */ + { { 0x7ac4712f660598aaL,0xe3f00c28aaba6261L,0xb71ac42e1a9b639bL, + 0x19674c28f69958d0L,0x3983abfec4e5c60fL,0x67f4583a5de58f9fL }, + { 0x83e0bbbaf7278c06L,0xd1883aaa19c5f96bL,0x8ec0f2848b3128afL, + 0xc88e07f49166e04cL,0xa515a9e44e3995c9L,0x0680a306b757ec2bL } }, + /* 50 << 217 */ + { { 0x5673b61e6d6f3aedL,0xcd1275e29524fd2dL,0xa8844f08cde12134L, + 0xeca3eb27b8366e0cL,0x5ce49d498bbe04b4L,0x0b7ab7a02882b056L }, + { 0x12fddcb840fee142L,0x99b7920b2895df5fL,0x35dd8d5a5829bb19L, + 0x271c6a4c46ee8dfbL,0xae09ba7536b594e4L,0x45502d0e1ae12c22L } }, + /* 51 << 217 */ + { { 0xa9e1b19ad95e0110L,0x6a419f8b2383280dL,0x6c35e8e16eb602a6L, + 0x966e0f44d71beeeeL,0xfc5cbdc0c8915585L,0xdce1c36583133b89L }, + { 0x3fbdd24289e6a35cL,0x8cd24d1760ff9dc3L,0xb9708c2729dd493fL, + 0xabbf39803cf807caL,0x62689ffe5410c80aL,0xf133928be8b31d13L } }, + /* 52 << 217 */ + { { 0x3645a1910d4bfc83L,0xa564ac85f2114b63L,0xf0647034cc6d9314L, + 0xb58e96d331d80285L,0x8b8222d9e269c964L,0xdee12adcd204b214L }, + { 0x82d2bfbae1d0a6e6L,0x4fd69d2e9da964eaL,0x1605d9e3200b3ac0L, + 0x5ab2886266d133eeL,0x938411c9f72f5353L,0x9fcdcb3a7d40dee7L } }, + /* 53 << 217 */ + { { 0xd65c1d6c501eb835L,0x37374dd14a0e5861L,0xa13f1070505f1fdeL, + 0xedd76943d1351805L,0x0f9501953673091dL,0x0dec24e308aa62f2L }, + { 0xec4962e7f50efefeL,0x0acccbdc9d227293L,0xc6c95d29d84fd828L, + 0xa4b214c540578ca4L,0x06963d3ba4d41991L,0xeb8c14c2fde0034cL } }, + /* 54 << 217 */ + { { 0x3d46a2317460e00fL,0xedce1c7dacce513cL,0x3d7b6f388cfdce74L, + 0x870082baacfa61deL,0xa86efef862ff847dL,0xc146218368c11d11L }, + { 0xb296eede9d21be2aL,0x9dc54e9e761451cfL,0xed1bb1fd53107f7bL, + 0x41f9efdb676bfbe4L,0xcdf43b904feb9a1eL,0xe81fcb6409d98782L } }, + /* 55 << 217 */ + { { 0x00639fa8642789c3L,0xf8e893a03c101e43L,0xc55439302730e33bL, + 0xe2967d30460970e2L,0xb33f1976ceacc128L,0x9bb0f896235e8c4cL }, + { 0x523f7bbb2fbbbc97L,0x127728a5dab215c1L,0x95dd23ca7ed6ab74L, + 0x69f1219feacf4ba8L,0x5ed12355e875dd6fL,0x7aa732dc95565bdeL } }, + /* 56 << 217 */ + { { 0x9a0e153581833608L,0x5cce871e6e2833acL,0xc17059eafb29777cL, + 0x7e40e5fae354cafdL,0x9cf594054d07c371L,0x64ce36b2a71c3945L }, + { 0x69309e9656caf487L,0x3d719e9f1ae3454bL,0xf2164070e25823b6L, + 0xead851bd0bc27359L,0x3d21bfe8b0925094L,0xa783b1e934a97f4eL } }, + /* 57 << 217 */ + { { 0x0a700190a5e41f7bL,0x2173e68dae9045b6L,0x28e9ac53f1669974L, + 0xcb00ff99d4b9fd98L,0x09c7b907ebe90d1bL,0xbf401f20385744c1L }, + { 0x0bb7ea7ae1292c18L,0x82aa43120b58f171L,0x5aa97bb2e3102d77L, + 0x1a71e7c570178b35L,0x9bbb9ade6ab76f59L,0x32da60c9dea7bcacL } }, + /* 58 << 217 */ + { { 0x3c3f113ab3726680L,0x27be1c406f5b5ab2L,0x5f51f684f6864a39L, + 0xfaf84229a60c4f39L,0xa788612d01df18c9L,0x65c9fd14951d5ea3L }, + { 0x4b2153cdaeeaf44fL,0x6b9e977ba567781fL,0x4dbca3609dbf3e39L, + 0x1ad43ad4fc65d7ddL,0x70a7a5e13d8dcf0cL,0xc11b1f4688b91e4dL } }, + /* 59 << 217 */ + { { 0x1ef5695b0868ad28L,0x09c9c06c2e3a9176L,0x2f2c19672c358e86L, + 0x4ff1af54da22d7e7L,0x5ea6716840fa2270L,0xd164b6874d31a3e9L }, + { 0xec036bb4345103d9L,0x6c6a130f26e17156L,0x2c491063d872b0d6L, + 0xa66be18c4123d04cL,0x8593de34a33fa919L,0x620d2970f025b880L } }, + /* 60 << 217 */ + { { 0xc194cc1664baf040L,0x8038f31fcc01f35cL,0xfcc82fa0ed2079c7L, + 0x1eb7571190d39b9cL,0xf1a89043c108e069L,0x10633334c020880fL }, + { 0x492a494086e262f8L,0xaa0208173383f1a7L,0xfbb4e5ba6d99cc07L, + 0xd6ccdc5cbde40478L,0x9e0b9d5867ee92c7L,0x5204bab7653eb14bL } }, + /* 61 << 217 */ + { { 0x721f44f0ef90c9bcL,0x6ebbecd8d55e653bL,0x9af325df6ccc5d5dL, + 0x265f0f6d827bd1aaL,0xb82453213487ea4bL,0x1642be42af6ba8d0L }, + { 0xb8c4168d4140e5f8L,0xdf5e32c13545d107L,0xf1301b9c2db68318L, + 0xb22e20472bf3c067L,0xf40af49ee56ba514L,0xf4090e795575f363L } }, + /* 62 << 217 */ + { { 0x980de58b1746f6bdL,0xa9e1f0089eb9511cL,0x8f53c6fd1bbdba34L, + 0xe6a867a6a1a41706L,0xd4cc48a5d2e48256L,0xd580559e05cb19d6L }, + { 0xc8983311e6466ae0L,0xeab62080174df01dL,0x710ebd184a0441d1L, + 0x0af69d9a9f653d0eL,0xef3a2510d789c932L,0xb5959cb992fbd39aL } }, + /* 63 << 217 */ + { { 0xdbbdd5fdccb1cc9bL,0x660110b98a26d874L,0xfa80d8b60fb9ff2cL, + 0xfeb5cd6b95040da7L,0xb526ae0c7366cf25L,0xf49d85fce3566146L }, + { 0x3b4107e699f505e5L,0x3c2d618f4302bbaeL,0xdaa09d150b199866L, + 0x3b65cb88c395abf5L,0xd2af1dedbd5ac4eaL,0x0586f5a5276533d1L } }, + /* 64 << 217 */ + { { 0xd927283013575004L,0x01a330d620b2275eL,0x58b9207f450db713L, + 0xae95338423e16d95L,0x4f10c6d4e60e349cL,0x541d03ecfeb122bcL }, + { 0x22548cd22c648211L,0x5c2dc84cd01354f5L,0xa1c6f912b6167b3cL, + 0x6967bab27902d2baL,0xebbe0b0836de34baL,0x6985b33a4b79625eL } }, + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 224 */ + { { 0x9e857f33771560abL,0x4ae1ba22250f109dL,0xf8538d68ff4f6566L, + 0x35380f15ac339148L,0xfef0bfdd5ddfc12fL,0xf706c6bf1387d93eL }, + { 0x618ce77d5357e131L,0xf0921744236478c4L,0x24eaf06e00dc0da5L, + 0x049113be07603cc7L,0x5cf489088f6963c7L,0xbe5eb9e6ede4a300L } }, + /* 2 << 224 */ + { { 0x77e486f85d066c15L,0x0c05b6c24ed5307dL,0x322b28ab7df36628L, + 0x2d14d1316704dcd6L,0xd359977af29a3567L,0xc29bb132ec96d3b6L }, + { 0xfd6e400ae6bfa701L,0x03db99244c7e5101L,0x62d81c7d9b8533afL, + 0xefa638c28de66eb8L,0x7405a9d7e86784eeL,0xafaa74efa6c22223L } }, + /* 3 << 224 */ + { { 0x6909994f0572e536L,0x9d22f9157fed8954L,0x1505ca05884aaca9L, + 0xe4b6530996995a98L,0x30e00a5ed02c000eL,0xb9032350236e7b09L }, + { 0xe696f09e14f6c7bfL,0x2126b6277dc18d06L,0xa9ada7b401e1e2a4L, + 0x9630acb69d2d025aL,0x9fab2c6ed84ffeb1L,0xc1d0db26ab7584f6L } }, + /* 4 << 224 */ + { { 0xf9b2dba4b9d36e91L,0x5fb4f6cefda9b2c4L,0x7692a4f33b8104eeL, + 0x5da885b0e4e1896eL,0xc2a30fec73d2aa36L,0x7d06e6af86f60bcaL }, + { 0xbc8bf16d87287887L,0x6c3dd86a3d701becL,0x8e79e2f37e35610aL, + 0x981139f482f9d71cL,0xf8997ec424e62733L,0x330d989aa3518061L } }, + /* 5 << 224 */ + { { 0x6cf0e6ef9b7e3cc9L,0xb465be6b0320acbdL,0x02777783856111dcL, + 0x3a1d36f0c0e9f2b0L,0xfcf4f6365e7fe507L,0x36bf41827fa7c8f1L }, + { 0x09a02de8b0f4ce56L,0xa0bbf65ca9cdb353L,0x7211a9654b7f4e35L, + 0xa6b2ba79805b58bdL,0x418302c20957860cL,0x3c17ec02f99f9d58L } }, + /* 6 << 224 */ + { { 0x4e6ef410ca89fbadL,0xe0fc53ba53933b78L,0xa4f03403fd41d143L, + 0x3a507177e0774c37L,0x078e8c568ec7484aL,0xfb73c6b6fbb3f66bL }, + { 0x169c94753bfbdff6L,0x44d286060a232243L,0x3e8e968508303114L, + 0x7a9797b8fad0def2L,0x0ad14404efc1c8daL,0x6daae4e921ced721L } }, + /* 7 << 224 */ + { { 0xfde0d1b4cbfd18abL,0xa3c9917595850f83L,0x16d3ad79c9eb9de3L, + 0x2707ec8b0ffbcdacL,0xd7e6750fa220287cL,0xe51baf059c2e155aL }, + { 0x3018c309871e10faL,0x074f08e3f23221c2L,0x1aa323aecf15a4afL, + 0xf085d69cc1b8cca0L,0x47a3eaccb143a969L,0x56a04522f3a98430L } }, + /* 8 << 224 */ + { { 0xc7e9ddef88dd2dc2L,0x2c21a99819a0c0b5L,0x6bc0746db239bb82L, + 0xc811a8eb28ea1341L,0x5f714ca71d1309b0L,0x79eabd20d4eb9b34L }, + { 0xe0e5afdcdf0fb30fL,0x1b01a16d8c0814c6L,0x670e1e7b84334366L, + 0xc8c38f9a0eed1116L,0xf914fae2619bbd50L,0x1ed062cb51c1995aL } }, + /* 9 << 224 */ + { { 0xce64d065b711b4e9L,0x32760c2eefc4d25eL,0x9e5916caa6292c7bL, + 0xa90d40bff2a47deeL,0x90dc6681604933d2L,0x707270c60115cf42L }, + { 0x55b601ff6fe583abL,0xdd2fe842a039dafeL,0x602d8de34c2d3357L, + 0x7cc979bca7ab9014L,0x4b8dcf7e60118797L,0x7f1f2a04cbfaad32L } }, + /* 10 << 224 */ + { { 0xd4e60e15cb583422L,0xc6b1ef90320f296fL,0x0714bad0d9bfc834L, + 0x5ee2ca8c9050e2c2L,0x074a8ca824f7cf1dL,0xb975024910df8516L }, + { 0xecee8ab7c2636d2cL,0x308e5af13b4b7bbdL,0xfed4f27eee2ae021L, + 0x7cd4bb192065253bL,0x6b21a3f84de525b4L,0x0f10e7bdac27fddbL } }, + /* 11 << 224 */ + { { 0xb4f02d9dbb3bf37aL,0x69590395978aacc1L,0xdf99b1309c3def3fL, + 0x5c66391e12be0bceL,0x30ab382cb5eaf100L,0x9b84b2b4e0352249L }, + { 0x0c22e4e1af14e85aL,0xc29d3c592286ea0cL,0x6c7f8b6a40758aebL, + 0x7a91adccde68fd0bL,0x4d8554fec8e8fd4aL,0x9fa863d5bb5621e5L } }, + /* 12 << 224 */ + { { 0xd5068487870e29cbL,0xf9420b85fc52d5cbL,0x50c3265a496d000dL, + 0xe605414a166bd6b4L,0x4de8d724c62b2a6cL,0x16af06f2a1a11048L }, + { 0x5406bde945f43c4cL,0x5e15bf6c751ad18eL,0xa846e665b6a59587L, + 0xcdb28a7d1816ac55L,0x899b3551819b73f8L,0x2d46297bbc848d08L } }, + /* 13 << 224 */ + { { 0x76f5aedd44af60a1L,0xf7bd3b4651d1efd8L,0xdfbf3c6439a9721eL, + 0xf927fbf0ee9d2ab3L,0x628e9258c7e0779dL,0x062cb2fe4cf1dccfL }, + { 0xb2ff57dde2278f00L,0x3f0e140a2d199ca3L,0xe7161304342c0a9cL, + 0xe7ca734f0bdbe131L,0x7d070270870057d8L,0xf6f1a65daaa55860L } }, + /* 14 << 224 */ + { { 0xdc4cc720299127beL,0x5b34e762faab8165L,0x2289b2f7b39c120dL, + 0x687a78d06e52b913L,0xd2a091dd2a3ea6a5L,0xc61eced638eab329L }, + { 0x652231ea7887ff2bL,0x77a568750479db4eL,0x1ef471c8d43c5722L, + 0xf82bf436f3764c34L,0x962af4050445cafeL,0xed8b227f5ff47259L } }, + /* 15 << 224 */ + { { 0x30e045f4a73c3da0L,0x13d2527df36c6346L,0x3dffe56d3836fb9bL, + 0x9518276617c5d2bfL,0xa0ef38724dd0b240L,0xb45e19ebc39c675aL }, + { 0x65202bc603e95445L,0x41e2f0d19a2ec9dcL,0x51c719cf2a0d762bL, + 0x3bfb9729ecc6b9f8L,0xda8271705a261640L,0x65c2bbbcaeee5f3fL } }, + /* 16 << 224 */ + { { 0xde849cd1d89594abL,0x00e2d2b10ec4fb3aL,0x3fbd9e3dabe92fbaL, + 0x785414d43324900aL,0xdaead1abde20904eL,0xb493e121aa5f1ba8L }, + { 0xd60a4f2d6eaea0dcL,0x394746b56fca8596L,0x163dc78934efa243L, + 0x3067dccf216a8d8cL,0x116b6534a901617bL,0x8c4bd099bbabe51eL } }, + /* 17 << 224 */ + { { 0xbb9eb22a97ebad53L,0x791d4f90666f1428L,0xa3a896e06c5d5569L, + 0x322d566fdefbc26cL,0xaa581a083c039c26L,0x82d899be62790f0bL }, + { 0xeff4bb9a43a0c2f7L,0x60515c10a01df2c4L,0xdd1455a849312160L, + 0xc8a15052c4292265L,0xdb2970f97f68d081L,0x29c825b892594c4dL } }, + /* 18 << 224 */ + { { 0xc8c2df45ac3a082cL,0xc353d074c8d4c40eL,0xb214f9c05a3c2de7L, + 0x504bc42cf86b0214L,0xc82df5cbd1922a58L,0x40887948a5bc3267L }, + { 0x04bcd21788ba8bb2L,0xe21b3e7f046fd401L,0x8419c338616af5cfL, + 0x7f24760baedfce9dL,0xded8035bddbd519aL,0x1f1fb0d71693faabL } }, + /* 19 << 224 */ + { { 0x7a88376766117f71L,0x8d4e37815d261599L,0xc900e6dff770b193L, + 0xb7d1c06b12e9dda7L,0xa86d173a717cb0faL,0xa138b7ba51dfbeacL }, + { 0xe84468c57360a27cL,0x4acf8b412e9b82a2L,0x85fa386cb121d6faL, + 0xc794d9f283e6169cL,0x7b4cd3fc8c9293acL,0x3096ad868d082719L } }, + /* 20 << 224 */ + { { 0xbb067b49d02ffcf6L,0x7cedf8f93e657299L,0xc3829961406bbfe3L, + 0xefe4b5aa37c12472L,0x7dc01cf9fec7dee8L,0x70a9db2389472f50L }, + { 0x29c269f8b31bf737L,0xa26deac3ae3fa7dbL,0x0046e91233caca41L, + 0x3bf4bc8ab6e78b55L,0xca83bc6cd9eb5ef1L,0x73f25c62c0c5deffL } }, + /* 21 << 224 */ + { { 0x117bb83d3ff7d803L,0xe91098c539c56c0aL,0x7bf72fe91e347fa0L, + 0xa66201a31e174941L,0x1d069d4d6846a06bL,0x721cdbbdcda59bcfL }, + { 0x17d6683a17652893L,0xee1b28f505be2530L,0x2e70558697a69062L, + 0xd4b5798682b56c36L,0x1ccc5be09082e781L,0x42e0e429d6b05e30L } }, + /* 22 << 224 */ + { { 0x697dc47d44b4aae8L,0xb3525cc0782c331cL,0xff71cca40bd7c78cL, + 0x5f3d776610c0ab69L,0xbdc10267e2ba07e3L,0xc656f75ce6373f6eL }, + { 0x9e2938b4b5607b62L,0xa65017d410b0a0f7L,0x8dad31195cc6ac25L, + 0x00f8f2d18ba5d1e6L,0x608137bc43305aefL,0xddad34bbdcb81cb1L } }, + /* 23 << 224 */ + { { 0x9e46b17c20c78a64L,0x28db365d5c48e678L,0xbe4c3b8eac6ba470L, + 0xee737236b6617b28L,0x81c5b94a4f3422bcL,0x4d44c33076faa922L }, + { 0xd7a09a719be38835L,0x99d024e1410b382dL,0x103b67c36b15012eL, + 0x02b6e094d9808da4L,0x4f5d938a0a7f2fcdL,0xa43058b7e4c5073bL } }, + /* 24 << 224 */ + { { 0xe133d941b1f82ca5L,0x2af8b98bfdf115bfL,0xdc6179c857aaa6f3L, + 0xabaa83e9130ade06L,0x7836b6fb0e8bffd1L,0xc479751ffa103703L }, + { 0x0ff3c1299c89963bL,0xe64072560b84c24fL,0xa92a4ea2f34f6bc9L, + 0xba45b3053197989bL,0xd12b5a0199243aabL,0x3015772c442af625L } }, + /* 25 << 224 */ + { { 0x5362ac737e0a5c36L,0xc731132a8c4fbc07L,0x0ef7468d7ca0d4d0L, + 0xc43afef835d25de0L,0x096bde6a3fa1209bL,0x21f57eb566846236L }, + { 0x878b585cf04d23d7L,0x737f7e527315ed56L,0xb716462c811afdd1L, + 0x4d223734a571a3cbL,0x56460e2fa7db2c60L,0x0684d72c61f97485L } }, + /* 26 << 224 */ + { { 0xd95fca81e6f065c5L,0x45e886d5fc8655deL,0x3580957727cff79eL, + 0x92a39a34625877d9L,0xdda02684dfee17eeL,0x6354f871986f635bL }, + { 0xb3a6e9edd409c182L,0xf0b1c8d9c4fbbb3aL,0x28721c019b77adedL, + 0x3c356df1bf94f028L,0xff221bd229a81f1aL,0x20edf2e856b20b0dL } }, + /* 27 << 224 */ + { { 0xb8c636db31ac60c2L,0xf3830e72bd987402L,0xfe63957c30e6b969L, + 0x3508e67989eb2bc4L,0xc0837f8c9a987e3bL,0xd1d0ce7b3f9b2ef4L }, + { 0x08d8f99441fe62baL,0xe73f79d7e17669d4L,0x8801fabaee6d68feL, + 0x4ef814891a508a88L,0xcc851bb71fbc4512L,0x69f728704680b88aL } }, + /* 28 << 224 */ + { { 0x97fff124835fda9eL,0xa79ceb2f0bc68512L,0x70ba93d1a2fc3995L, + 0x62bd28ab9e51c5eeL,0xb95fa624d5bbbaa9L,0x0654dc458c1f571eL }, + { 0xb9a4edc665a45ed6L,0xbf5ed1bc21ad0612L,0x74adc1a1b1a3551bL, + 0x3dfa3dc8dbbd6cefL,0xce5dd40b2fa3afd2L,0x14894e0f30a746caL } }, + /* 29 << 224 */ + { { 0xe4544006ada9bf7dL,0x9e123b709b75770dL,0x903628d557cea95aL, + 0x6429e00c9e8cef6bL,0xafa2cce77b1adaa2L,0xf2f5771e15e488daL }, + { 0xda44962269820874L,0x5b20ef1b6e0fef81L,0x3150a8699507b4faL, + 0x901897add191de20L,0xf459da31c41dbb2dL,0xc2516dd077146754L } }, + /* 30 << 224 */ + { { 0x7e729c58b8ca2a2cL,0x0f32ea1ecaac04afL,0x47267f13bdd549e3L, + 0x35b9440690be3b50L,0xad0f2bb14b27f670L,0xd7e5874e92341803L }, + { 0x7dc841cf1f9ec462L,0xebeff994512b2a42L,0x22998a7f320dc858L, + 0xf08eb5c719946f59L,0x228c8dcda68ea75eL,0x40dc6dc37b20dee5L } }, + /* 31 << 224 */ + { { 0x23f40e331dd722adL,0x0a441bf4c54fc48fL,0xed6c026548b75f84L, + 0xc2d3972f3e0fff2bL,0x889b44c4db09b7d9L,0xeb6ccc6541a6a562L }, + { 0x5ef1162e8f04e03aL,0x25e2ea895d8102c5L,0x37b71631154644d5L, + 0xa9a1a8320446b1bbL,0xe3f58daefb342b20L,0xc6d19decb6d292c3L } }, + /* 32 << 224 */ + { { 0x929454f6b3952db4L,0x412142ec4d3f69f5L,0xf5b0a7c5ee25c0b0L, + 0x7d3372ff2e752295L,0xd6dadc7d6eacac68L,0x5f0076cca96a8e3cL }, + { 0xea831db671725b3aL,0x4a286c89c29ab454L,0x5ff817e572e3c00cL, + 0xb022e25d2a5fb6baL,0xb611c5bcbb392476L,0x062c14dc190485a0L } }, + /* 33 << 224 */ + { { 0x44730047ffdc9a7eL,0x44949bdcf078d5bbL,0x8c1a3e4bc486e2b1L, + 0x53088ba20801402cL,0x6e20a7cfeac83daeL,0x4407ea8436ec5443L }, + { 0x564fb733853f79d8L,0x59ea819afe809670L,0x1ac62174f1ec7e91L, + 0x0d7e065566a0b8c9L,0x0c4d072482958221L,0x80db0297a60f984eL } }, + /* 34 << 224 */ + { { 0x380823e7f3359d47L,0x8a60fb05f5efd39cL,0x78a940669425487dL, + 0x1da6abc3f199c67cL,0x7df00b2165f0a6b1L,0xdc0dea58017b1231L }, + { 0x9c529db079f4f22fL,0xc7043be3e5dd92b5L,0x10153ffb43661331L, + 0x51c459bf6ff02e8fL,0x451483bfa43aa005L,0x3313f903199cd1baL } }, + /* 35 << 224 */ + { { 0x2f66587e62e1ef1bL,0x942d4c739e3ae33fL,0x4a27ead5c0ab9c1eL, + 0x368d8dd89ca91b06L,0xb3f0cf92c4b6ed34L,0x28cc332673e62557L }, + { 0x2649e5527910986bL,0x635dcf9cdda049abL,0xbbde12f625d3f201L, + 0x5200c3d0a9384443L,0xd996573d51eb3c10L,0xb093c1792b8cd7e5L } }, + /* 36 << 224 */ + { { 0x15cd1d1cc3fe6fa4L,0xf260a739e2c3c686L,0xf7c2270eb08c65dbL, + 0x9ada2cb6ff69d971L,0x65fbbcac212bff0cL,0x40157d075646a735L }, + { 0x101d2b7d55de9e45L,0x0db580e83118b763L,0x3203baca8322a9cdL, + 0x2a3137ef22cac14dL,0xcc9092e291a14128L,0xbb269f6d98cc368fL } }, + /* 37 << 224 */ + { { 0x7c8946002ad7f66fL,0x6a8328bb99b438a7L,0x86d06fbbdb440d86L, + 0xb74ffe2d20ac5a42L,0xc3a6f01d91b1c82bL,0x606f8ce71d5efbddL }, + { 0x8c49c43a6338c99fL,0x50657f7216da7cb7L,0x7f204c8b84f22d9bL, + 0xa2612d80ca76978dL,0x80080d868a3e8e96L,0xd8841a1ac0bff9afL } }, + /* 38 << 224 */ + { { 0xc2a734cb962fa060L,0x2baa26c580a17874L,0xe27b21110b44efe6L, + 0xdc1244e531d2154cL,0xfcd86d4116c7742bL,0xf45230df32503138L }, + { 0x94a790f4812cf0afL,0x0ab2df23da3f24d7L,0x0c764df181571d54L, + 0x989ff71c68d68f74L,0x9896fe62cda535b3L,0xfe0502e05f4fa41bL } }, + /* 39 << 224 */ + { { 0xf1ffe852c2f58cf6L,0x2ec46d2546d64576L,0x95bfec93d602c51aL, + 0x349c58bf3907b766L,0x59cb12bb9b94bdfbL,0xfa95da9515dfcd87L }, + { 0x731a8535e1543bfbL,0x14844aeeca14187cL,0x0d73e58aba1f4928L, + 0xbb71009fc6bb67f2L,0x5e7c0e988b4142b9L,0x4866b5095f08f58bL } }, + /* 40 << 224 */ + { { 0xc8295c2fa234de87L,0x1cd7f3fd878e77dbL,0x309c1fefa2155b6cL, + 0x2a9bcfd9484afddeL,0x87ef7a56cc999775L,0x34336cb1970aa188L }, + { 0xd45eb83cc3e16ba1L,0xf9d72c72b9c1695bL,0xff117458cb980742L, + 0x438a7fcb67af836aL,0x5ffad086eb9a6c40L,0xdbd3e518513922a3L } }, + /* 41 << 224 */ + { { 0xde241983e42021b7L,0xaa70e834542873c1L,0x99c9d35f9daf2b99L, + 0x0bf712d549b40780L,0x202d9969d9ab6e97L,0x7f3382dac4932106L }, + { 0x1eb5f5d40849e319L,0xc1bdd1179f659546L,0x628ddd3d2329f977L, + 0x5944611d363ee601L,0x7b7a631463d5bd4dL,0xaf6c51a5631d21ecL } }, + /* 42 << 224 */ + { { 0x2d8f9e1db4100182L,0xa08ae2fe4f3d2c03L,0x7548c430589e99f8L, + 0x0f5ccee2aede8af9L,0xa21ace3343b34b25L,0xb120c569dee102e6L }, + { 0x1cb103ed36f13699L,0xf71ff0dfc91e8cb4L,0x88f141079b22460dL, + 0x050af75af509366aL,0xeec8a310fb179bc6L,0x069e7331c26efef6L } }, + /* 43 << 224 */ + { { 0x3e2a9c713be9cdabL,0x8f235d6f73ac08e6L,0x3de28a6b28832dabL, + 0x7d08b9f31ee82d6dL,0x67c3b88f915ddda9L,0xba8f18cc0f7c81a3L }, + { 0x38cebc31ca3c0936L,0x745f71aa7816a6e3L,0x00cb85a91a95fcd3L, + 0xb92742c6577dc22cL,0x1afdaab592029cbeL,0x0bb43c91278d3f7cL } }, + /* 44 << 224 */ + { { 0x3d77059d3ba02d27L,0x58e28671440b2d3dL,0xe2d4235726636fbcL, + 0xcc448a52c54605d5L,0x73c2902efc0269a6L,0x28a15ed57ea8c26bL }, + { 0xf666587a0cfc1a34L,0x8374f2cc1ae0377cL,0x5dca6ae828417437L, + 0x15a6d54c94bc87ffL,0x5bf187bbb344796cL,0xc629c14889574b2dL } }, + /* 45 << 224 */ + { { 0x06d43c6d87748b63L,0x2489a957a7f232edL,0x7aa9174afa407c3fL, + 0x8c8b8fd933a762e0L,0xe2e8f1e7adbe94a3L,0xd1e0c8c2bb723045L }, + { 0xcafd8f483df092d8L,0xbc89caebb174025cL,0x97595c5649f20c98L, + 0x6e520a968a77acefL,0xc3dbd3107a52a4e6L,0xf51db5a91284ff27L } }, + /* 46 << 224 */ + { { 0x406465742c74cb2cL,0x44eeb9e546c33df0L,0xd2a9f16ecb4c50b2L, + 0x68f912a01906a6ccL,0x2b81296d95211e94L,0xddb2988ec8575839L }, + { 0xb74d990d33b180c0L,0x290185567d319c48L,0xd3d2e40dac8de56fL, + 0x9ad42a60461f30e6L,0x265e4715292a0faaL,0x56c2626c8ac3b2a5L } }, + /* 47 << 224 */ + { { 0xb7580f2fd468adb8L,0x8e1fbf0388a6a587L,0x1b8c40ed8f4f6cddL, + 0x337414f56817b2b1L,0xd877ebafb744d563L,0x59eed3c6df5e18b2L }, + { 0x365e148dd33afa01L,0x82e70adc665702cdL,0xccd77955a5e390ebL, + 0xd86c343accc90cb2L,0x23bd948d6cd8a33bL,0xb1fc140cdc43a8cbL } }, + /* 48 << 224 */ + { { 0xefda99d9ce11b02eL,0x9017bd4a3f820083L,0x8b9e6cd1ad14ac6fL, + 0x1239ee331f413880L,0xd98e93d993dd7fb9L,0xc280d252894fcb12L }, + { 0x33a9201a5230b5eeL,0xc6aeee256e41de26L,0x845051280d0a320aL, + 0xc20551db4b607b53L,0x6e63c766ea228c2eL,0x883321aeac48f25cL } }, + /* 49 << 224 */ + { { 0xa5173910e15a530aL,0xaa2c88b83ac38ab2L,0xcbfbd31ec6a6ba9eL, + 0x0fa126cb49ed182dL,0xd6b38897cfc53c85L,0x98d5f6bacb9c2f41L }, + { 0x6694e8e5cbd150e9L,0xd470ef226a1fc551L,0x57a63765d5ea1c0aL, + 0x95f5eb4318078139L,0xbeaba00585d3e0dbL,0x6bbf010fd314dec7L } }, + /* 50 << 224 */ + { { 0x5941229729ee46d3L,0x39e5aaa0e66bdfabL,0x9ff1575001c815e1L, + 0x709706211f2de195L,0xaac904a968aa571aL,0x9cbefacd8f7625f9L }, + { 0xadfd215dfce3a501L,0xc04d09ddf20651b4L,0x688c1421d17b25f2L, + 0x3efde5d40073247cL,0x999b7f3a7432c699L,0x33c76487703fea50L } }, + /* 51 << 224 */ + { { 0xc720aeb10af6e1faL,0x1564b8d8e8771dc6L,0x5983eb44673d8ef2L, + 0x5dabb2070679ac65L,0x51a854cdbcdb681eL,0xe2b186a9364a3cb1L }, + { 0xfa189eff7222208bL,0xf7161d86477666f9L,0x0ffcc3e6192d1df5L, + 0x1523508e39cf5a4cL,0xf5e98687c43ecce8L,0xbf17b63261450309L } }, + /* 52 << 224 */ + { { 0x63293cb8adfbde28L,0x5df78fb3c6b18ec4L,0xad10da4ffd27e50dL, + 0x60202b357ade5c9aL,0x67b9d253c6c8c8b5L,0xdbacffefbc2b30bdL }, + { 0x508ff8a67494b1edL,0x87ef48be3769728fL,0x74d4f180ef98d036L, + 0xc5d9ef531799e8a9L,0x726d22206e850162L,0xd86d3414239f6b38L } }, + /* 53 << 224 */ + { { 0xfdde327b3e1f1b96L,0xb6272e94bb58615dL,0x2881350cfc2d8a47L, + 0xfcbe87031142ab9bL,0xaa5fccd0f48c7f97L,0x606be6ed29a74ba0L }, + { 0x545409ba3afc598bL,0x4779f54aa7d23f5dL,0x2811c0829d68e38eL, + 0x5b4646bd3f9c5842L,0xbcd3aa492586219aL,0x7345799313642e3fL } }, + /* 54 << 224 */ + { { 0x9a61f240ab638788L,0x519742162b0a8449L,0x9a5ec31d43b2abfbL, + 0x6f3075740563c9c9L,0xe465f7793ffa198fL,0x8876c5772957418eL }, + { 0x10e3d09c976e5875L,0xd66d334e592c2409L,0x3f0d5727b39b7897L, + 0x17ca7ad1e37fd300L,0x221d8436da530871L,0x4df38e4179d6b350L } }, + /* 55 << 224 */ + { { 0xe805096338b7a2cdL,0x9874cc734b8f05cdL,0xfc0821791b74a790L, + 0xe18a92f3293049a6L,0xabd525694dfdc13aL,0xb928cc300d843466L }, + { 0x12750aec348dc7c0L,0x3c8e205d87f12dbcL,0xa2c71091e0bdbd81L, + 0x895b56a0c1c1871cL,0x68dd7414b4c850f9L,0x45a948ecbe806596L } }, + /* 56 << 224 */ + { { 0xa88dbfe0f4fe35f4L,0x32de3a1c84283011L,0x8a3777bc39caea33L, + 0x673630dee4d49959L,0xf3ef842c59070317L,0x33e4bb031fab88a9L }, + { 0x88e4538e98ce8bc2L,0x870c2eb81a235c6bL,0x71f62c5640df0e92L, + 0xdb43b853f9627486L,0xfde9fcaa95cc473bL,0xe4c5b4bb4b677b11L } }, + /* 57 << 224 */ + { { 0xa6ebd946dd4091f8L,0xf0e11886dcf0741bL,0xd6267674d9533601L, + 0x571926506f74e49cL,0x18269c2f891d6717L,0x350a7869b45ddb53L }, + { 0x79ea6a4ac8f62777L,0xbad33c4cae7edec9L,0x14bed149ad7e5578L, + 0xb2f4190ba91af4fcL,0xbbd6f68be71dfd3bL,0x23fd3dc8f2fb7a21L } }, + /* 58 << 224 */ + { { 0x5e0f89e598fd044dL,0xb77180d97cc30e97L,0x64fbfb747f82a12dL, + 0xbeebb9ca77629636L,0xe164549feba83845L,0xe65a964a7079519dL }, + { 0x8b1bcc08ca88157cL,0x466399c3f7483338L,0x6e2726414b9efdc6L, + 0xff8c7027be922e96L,0x9baebf7d48374f59L,0x2a84a23ac18ee18bL } }, + /* 59 << 224 */ + { { 0x337484e0dca4b3b3L,0x82137cb9f5b27d3fL,0x12ae1d11bbf4c806L, + 0xa1e2873f2880c078L,0x9e6bd909058b9a0fL,0xacc5656d2dba5fb9L }, + { 0x7fe5467853fd2ce3L,0x2aa4af35452439efL,0x329989a5904ffc67L, + 0x007ea4c8520fd31bL,0x58988e2551816b44L,0x644f2469d8f186eaL } }, + /* 60 << 224 */ + { { 0xcd4d1a9e8890722fL,0xfa0b826b74142916L,0xa494dfa817ba8041L, + 0x3fb73e736de2b6c2L,0x156a6cf4344b57a7L,0xb197c8621e205448L }, + { 0xf453e348c214acf7L,0x665d7083e9061a73L,0x5ed59ec5ce9868a3L, + 0x9bab305f6ad777faL,0x752c490b35315de8L,0xabcfa35b5d5aaf26L } }, + /* 61 << 224 */ + { { 0x4059fc2f914d618dL,0x88e55ce6108380fdL,0x0c22b21bee61a4c1L, + 0x435ecbdb04788627L,0x3f8a5ec7a9f72788L,0xa31eff8a732d5d97L }, + { 0x119b6bf9d48d0af9L,0xde6d1de5af70a043L,0xac075ffd3368db4aL, + 0x23a33ec94a58603dL,0xd43ad120fe181a89L,0x386b90ed42f0b006L } }, + /* 62 << 224 */ + { { 0x8096824bf9bf1a24L,0xcdf69abc8260ebd7L,0xaf93b34de9ab190bL, + 0x676351ff841cbba0L,0x3db704d3eb6d6c60L,0x3b1b893fc09aebfdL }, + { 0xc06b9bfdbfc69f15L,0x28b1ffb8e9c688c6L,0x1607bc68d3c16455L, + 0x07d56bcc6d16d937L,0xac28e69f318afd9aL,0x7f4afeb7e77263b6L } }, + /* 63 << 224 */ + { { 0x796a530ab935875aL,0xd6700ec89dd1e51cL,0xc30301df4d9320e4L, + 0xe23090f357157f87L,0xdd3f68a74029113eL,0x566afc6de2709936L }, + { 0x830f952edbff8926L,0xe207eae5c7a39d27L,0x9210b3dfd9494592L, + 0x3be25582d8460831L,0xec2496575d58edd9L,0xebe8426fefd24738L } }, + /* 64 << 224 */ + { { 0x0372678dc419b0aaL,0xf95031d8c13fdf17L,0xebaebca4b79594c3L, + 0xe587850baf3b75cfL,0x534183ac2c1e09c6L,0x3f5b0bfdc08204cdL }, + { 0xdac2cf06e297cc77L,0x5e47d9c6d0487084L,0xf6f509f490b0f6c2L, + 0x3ffc3cd6c2c62207L,0xbb21eb1132ff1887L,0x2116a023e62ccc6fL } }, + /* 0 << 231 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 231 */ + { { 0x406a7e2116960728L,0xd03923f85597d8c4L,0xd4402eff020748eeL, + 0x7827442af39b58dbL,0x77e3f2768d8cfb04L,0xf6eb49c8e45a978fL }, + { 0x9db0829949247f6aL,0xce71a74706669fe5L,0xe434ce47b82775f5L, + 0xe84995ef63910016L,0xa35e8b971e47792fL,0xc779cb3d7c6aaeb9L } }, + /* 2 << 231 */ + { { 0x1fa064cfaf31ea1dL,0x2a9547a848e8d974L,0xda8102a1fa9d9453L, + 0x786aecabdc6bd7eaL,0xcaf91e3bca2f6044L,0x67d86ea78573f208L }, + { 0xd309fce9c505ae24L,0x67ddc5b17f86eb8eL,0x57791ae0f3d53056L, + 0x26b053f00d1fd61eL,0x91c962c0045ebfa6L,0xe95246de076ed979L } }, + /* 3 << 231 */ + { { 0x156eaf570746d174L,0xa2d4a83dcda35250L,0x60a9f48c0290fa02L, + 0x9855d26d5c33b4acL,0x06e379c697eb1c30L,0x4f2e2dbe6e219664L }, + { 0x6b7448f829006065L,0x237a1f31115062a9L,0x5c635a90ad92cb24L, + 0x2e857f8c2eed977eL,0x3d512df7856dc88aL,0xbde85263e597a27bL } }, + /* 4 << 231 */ + { { 0x49f24994e7c03ce4L,0x274a8c132aed9ba3L,0x897b9103d5e91bc0L, + 0x63db1efbcb404f68L,0x70efd9d842f7fc02L,0xd6e02921c6a230afL }, + { 0x8d5b199f11ae0a56L,0xc98287dece33da6aL,0xde583d34504dd889L, + 0x03756001f823686fL,0xf19ab86f95fc73dcL,0x300406c693f12f42L } }, + /* 5 << 231 */ + { { 0x2f73595f7759701cL,0x8dc2069a6fe0e0d9L,0xb7de7114c286a65dL, + 0xfecc429e84c0e487L,0x51061a2c14344c07L,0x4d70972596869e37L }, + { 0x8b02781f2be9403bL,0x6cb6aa02de3ab5d9L,0xb013508eff6bdc9aL, + 0x568d2e84e5438c58L,0x7b35a979e4206c3bL,0x0bb793c0b17a8bc7L } }, + /* 6 << 231 */ + { { 0x3f896ca9fa4dd561L,0x4b9a98abd2de2ecbL,0xd0741632600e4e2aL, + 0x87c7db5f69e702d5L,0x1f5a3b8053e0df2bL,0xe1e24b49f443dfbaL }, + { 0xeb90e2305eef3a1dL,0x8f3fc8a6d38f73fcL,0xfb1e8299a5aa335aL, + 0xd78504cd4197b32aL,0x0e7a79cc6755918eL,0xc7c98ae2883b1c72L } }, + /* 7 << 231 */ + { { 0x1a12727c03d2beccL,0x810a37dfc6741372L,0x44ac483fb7049f39L, + 0xab73e5e7a36fc614L,0x298d453feeff8aebL,0x2127dd167e1b586bL }, + { 0xeadc5c54e07bd60cL,0x67cdae00f5e2d2e2L,0x03fe0446c9d2f10aL, + 0x0784098795e38ed2L,0x5d348a7ce1a6306eL,0x4903f1b6562f5463L } }, + /* 8 << 231 */ + { { 0xbf66baa5b44b1d0cL,0xbbed18eda44f8edaL,0x80bc32abeaaa466cL, + 0x605b7897e5f2733bL,0xe9e7e3a1a2531afaL,0x25d66db33deb8369L }, + { 0x36212ea3b2f25d10L,0x52d6b3f4a08d303eL,0xefa54b31444e9e9fL, + 0x9c2229a169530c1bL,0x68feb9854b79bdd1L,0xd570e84f8b984cc3L } }, + /* 9 << 231 */ + { { 0xe141b86bde0560a3L,0x858bf4cdb2264bd1L,0x526fb104fabe5359L, + 0x95f9c43f185b8a70L,0xf8e3a3eb2d1f75e9L,0x71826067d93bc6b9L }, + { 0xf360e01799692f49L,0x00f4fd16c2dc3dd5L,0xeb7f40498b9454d3L, + 0x5cb0f3c426c3b393L,0xe8ab4e4357bdc4d7L,0x9abe36b00c123d67L } }, + /* 10 << 231 */ + { { 0x1df8d98c57b168fdL,0x042fd731b45da94eL,0xa54d64f91703e143L, + 0xa12198be9de0ab4cL,0x160e06241ddc4e0fL,0x15cae64a6695891fL }, + { 0x808565e70c2b2081L,0x6de4a393cc65040cL,0x6682cd934bac1768L, + 0x62e7ac2ca5be965fL,0xd33f6f8ad7a38e90L,0x9cafc4635b8b516eL } }, + /* 11 << 231 */ + { { 0x0541a391b685c547L,0xe86d35e091765999L,0x65aa03c51db4a2ecL, + 0xba53470e6b1c4784L,0x4f848cc8cceca1faL,0x89d0db0b8b18e350L }, + { 0xd03e452a7840d734L,0x6cebfa790ca24215L,0x288b4569e8f1d9e8L, + 0x18e405af8927ce0cL,0x5aad57e51abfb4c8L,0xbbd99091a197ed1eL } }, + /* 12 << 231 */ + { { 0xf041e421aa44f3e2L,0x47ed9e8eae6fd2b7L,0x4fea93751128ed62L, + 0x041a1c1acec6eae6L,0x1f32359415a65daeL,0x741fea0a0154e8e8L }, + { 0x309e9f289c32e224L,0x457d4ffa902ce57bL,0x7bb54dd5692420c2L, + 0x193a41aec4fa1a6aL,0x35f5f3b43d779e77L,0x31e84371046ebb8cL } }, + /* 13 << 231 */ + { { 0xe75a7c1d9d7e5551L,0xb73c987611635e3bL,0x3b07a071e09d29b3L, + 0x0a3cc0acc623023cL,0x15ec4a7a1e2ceb33L,0x09a01968c70eb27fL }, + { 0x2e5bb53c369d145aL,0x4c93330d9b7fb506L,0xbb10a2f358013308L, + 0x3d9da0c4e0b85fd4L,0x8b39c992ce0dc79bL,0x7e6d18b0bec905faL } }, + /* 14 << 231 */ + { { 0x3a5a366ea1554376L,0x0e1687c052a6ed9dL,0x3e16e4aafe5355beL, + 0x6d8bac03ced67666L,0x403eb33ed9344003L,0xd7b9ec0d333ab20cL }, + { 0x9fce1986d64c272cL,0x9d52d64bb1e23843L,0x8e689611921a58e5L, + 0x8f5f115620d5c61aL,0xb17f612fadc81b4eL,0x36e2db30e562f779L } }, + /* 15 << 231 */ + { { 0x98d0bcead01f8634L,0x6e9ba675bc5f825eL,0xfac2d3aa05e938c1L, + 0x434b712fb9c66adfL,0x81c29163a9a61d36L,0x80eade933be8eea9L }, + { 0x10fc6d75c04c45a8L,0xa2c9aa58fb9e8702L,0x9142afaeb200428bL, + 0x4fa28c8520eccf38L,0x3b5f63308209b3e7L,0xf74206ca8cd74accL } }, + /* 16 << 231 */ + { { 0xd6a4d25c845f26e4L,0x71e554ce1b039dffL,0x942059731cdedfc0L, + 0x0c4e385603d6502fL,0x981a4fc5e15ce8c8L,0x85d1b0f17aca30b7L }, + { 0xf2037ef777bb9e43L,0xc52804f4e87ae187L,0x9c98a23c71f3e4e3L, + 0xa73c8b89f47b504bL,0xb9e33f54023233aaL,0xf2bcfc17f92c9f68L } }, + /* 17 << 231 */ + { { 0xb3c1bc26707fc6ebL,0x0bb585b75ef6dac6L,0x70af297f5f707063L, + 0x3d86a8fa967a0ad8L,0x510dae4d4f956cc6L,0x1dbcb2e883c01ad0L }, + { 0x0e480cd28bfbb5edL,0x76498f813025fca2L,0xc015064ec5446cadL, + 0x4ddfe2af3616f51aL,0x76b0d690e6750b31L,0xc4502c050073f263L } }, + /* 18 << 231 */ + { { 0x9120912bb3081e59L,0x6c73c4a2f908b364L,0x408af8c94de763d6L, + 0x3d9e83084000add2L,0x65d197fddcb5a5a2L,0xbfd29f0b2bd82bb0L }, + { 0xa1243e63bdfe09e7L,0x91d90b54d556188cL,0x977dd4a18bc872fcL, + 0xa8e6e7bef4ea7805L,0x12c53bd80a467365L,0x9d7abca493b7f0a4L } }, + /* 19 << 231 */ + { { 0x5faf453a40eeb93eL,0x6801e0d1f1fe9307L,0xe92505d39ea9b800L, + 0x7e911f8108eb58c8L,0x5da7ffcc098143eeL,0xe023262056876057L }, + { 0x5354045bbfa99a91L,0xee660bbebb346841L,0x1dbf5c7cecb3099fL, + 0xe79c78d6a125d753L,0x2a356f10706fc013L,0xe50c50b725f88ebdL } }, + /* 20 << 231 */ + { { 0x663ca92723ca903aL,0x8a64a4dec7681937L,0xe3ec0966a2baa42fL, + 0x688328d7a2906226L,0xc2821e9c94790fd8L,0x7a295b62157501cdL }, + { 0x032cd57d3675c2f3L,0x91d66a57f42e6f95L,0xd75056961e97dcd0L, + 0x7e8ba3ed7d8b6f52L,0x8ddb72c420b0dccaL,0xe09e53bb6aea2d55L } }, + /* 21 << 231 */ + { { 0x3815b1028a009f19L,0x4f76d609f5418c34L,0x7a35cb332a9eabd9L, + 0x018d6c54ce89e886L,0xe00b99e859c9fab6L,0x4f10a0d9aaf6e7b8L }, + { 0xee51f8f0e722fce1L,0x03e8b63179bccac0L,0x66e540c26f327d2fL, + 0x31df4a35d22377e4L,0xba5b0029d5c71cedL,0x6a3e20553ed6aeeaL } }, + /* 22 << 231 */ + { { 0xe932d1aaaffc47ebL,0x75c9d4d8513f85a3L,0x50886fcdf9419cb0L, + 0x756a7d7d49081e9eL,0xe45fff1fe14aff77L,0x022b4ac339846230L }, + { 0xefc3e8dbe89adc78L,0x921bb1538c09ccecL,0xe4dc6aa17826d461L, + 0xa53aa6cefac8f0f4L,0x5d4e4d53954192c5L,0xda721828c722780fL } }, + /* 23 << 231 */ + { { 0x978609c67e4933daL,0x49fd5c5d2539c807L,0x072a911c6330373fL, + 0x40cfa61838177579L,0xf9a7aa4c81c51596L,0x7ba8e7a5b346724dL }, + { 0x79298c06d26ee66dL,0x243323702a9c2792L,0x585e8b9eb6aab53eL, + 0xa39596c6e14bee4eL,0x89b2758828a76dbfL,0x889fba0aa00dc1adL } }, + /* 24 << 231 */ + { { 0xd55a3eaf0a9a8ba4L,0x13b1406b2a8cd215L,0xcb44589a93943e1aL, + 0x91b5e3493a671a47L,0x488654f8efbe0256L,0x448bee4b392ba5e8L }, + { 0x228f478137e762caL,0xe21a2ca7e71b6c47L,0x0e809fe94900fcefL, + 0xb05e1db2815f6c76L,0x8cdf28815fa6fa0cL,0x2ed55c1c586fec8fL } }, + /* 25 << 231 */ + { { 0x7c3842eba210d4d9L,0xd656154e5f69a69bL,0x9e11c6db1f3a0483L, + 0xb0314a5e5a217444L,0xe17a274e34f4e54fL,0x6e41c20a9f79d6abL }, + { 0xd010d789dffef6dfL,0x704937f17e8915f0L,0x5072bf063d3460fbL, + 0xa30814ed5f08429dL,0xe5faf476207d2708L,0x46e56e14af448339L } }, + /* 26 << 231 */ + { { 0x5a049c8f94af3a35L,0x9ae89160d8b75bbcL,0x8b026d867ff40c5eL, + 0x90e54aa4fbddfd06L,0xc85349e7ee418640L,0xbf71e454beb7801bL }, + { 0x63f5e068ad912e83L,0x6252a4a4ada5341bL,0x25114b87b44529abL, + 0x9b80bea9eadb4f13L,0x7f071c0cfe050052L,0x4c9cd33418612061L } }, + /* 27 << 231 */ + { { 0xc6f50ed03c768ff6L,0x5b994b58b6de126aL,0x807ad19e2a1ac05aL, + 0x012fcb9ddfc66ad7L,0xf8706d5fefeb7d07L,0x132aa6697bfc5337L }, + { 0x56bd874310e28d18L,0x33bc53d96e9f8e26L,0x5885b63b152758edL, + 0xb8b1bd5e757e1471L,0xdbc689458c0d406cL,0xa664de3bfc605a11L } }, + /* 28 << 231 */ + { { 0x04df415ea6d4b6c2L,0xb8e33e71d254d2d4L,0x179df4f48b84c588L, + 0x8a2a0683d435793aL,0x6147a5a911eecec0L,0x0b8389793a0196ccL }, + { 0x855059ce81805693L,0x37babf9f3b27872fL,0xa2ac78b1769be5c3L, + 0x16260f0c0a8d267bL,0x31f48c42388266c1L,0x58fee495ead1f238L } }, + /* 29 << 231 */ + { { 0x5753ee0fc048300dL,0x307dfd57e048abc4L,0xc18bdfeca3ba6c56L, + 0xfb2d8daf10495489L,0xd93aebd4e0fd2d13L,0x4736efaf0518a5faL }, + { 0xa8ee4995eaa9fc77L,0x2620f08e008adc03L,0xf03981839f06991aL, + 0xd47b1eabe25a4f4cL,0x669cf09c79f95484L,0xf30191584a0f8b96L } }, + /* 30 << 231 */ + { { 0x047b0f0124b240a1L,0x959915dd46cecf58L,0xedf2e74b72980ca1L, + 0x6b7b7b4ef2cad32aL,0xf9f01c9d0b9ded1cL,0x009d3a5825e77e0aL }, + { 0x62314ab411a39c1cL,0xb3b0c5b2ad557b74L,0x6dbb75dd961619fcL, + 0xb8f2d198c934e1e0L,0x4401507542eb7fd5L,0x3a8552efea1be435L } }, + /* 31 << 231 */ + { { 0x08e3f0e2217de9abL,0x6bdec27bb6b4f789L,0x5b160334685af8e0L, + 0x31e651cc61738f6fL,0x37224bc4631989c0L,0x2dc8006ad39f9c4dL }, + { 0x2a5d585056c3d84eL,0xb2ef06cc5cc79193L,0x246d92869eaa50e7L, + 0x8cacbf7cea6a7cadL,0x109bddc629465ce6L,0xad2f492fb5744947L } }, + /* 32 << 231 */ + { { 0xba03ba3b7b3b336dL,0xe57ce50928c9c55dL,0xf96b8cfe4f0f60b2L, + 0xb908d77e6fcccd96L,0x7208ef7de79dd17aL,0x739095333ec3d048L }, + { 0x9c5ad2da1163fe78L,0x4e2a8685cd4a15c2L,0xac999449470eb938L, + 0xfaaf27fbee7d772fL,0xfbe402abd0b7ad09L,0x704d4f0e57db00a9L } }, + /* 33 << 231 */ + { { 0x8f2f736c6330607fL,0xaf4acf66c975432bL,0x838fd8cabd1dec99L, + 0x347088aa7c3d0499L,0x28008757e835ea86L,0x43e2fb30c03e1aa1L }, + { 0x06c66dabf0d10da1L,0x25d7aa1867321158L,0x215e483811dc063fL, + 0xd52dee1e288362f2L,0x790989a1fe300a0aL,0xe0452fa5f163e1ccL } }, + /* 34 << 231 */ + { { 0xd3eab3ae25e7c044L,0xa3712d11b6d22325L,0x5e3835999e8237ddL, + 0x2549047c9dc93a5fL,0x24b07617b546a113L,0xa50359ed2e7b82fdL }, + { 0xbbc3eb5889964effL,0x93d490b60d7ae172L,0x68cd6b3f774ac0e6L, + 0xf98f1df035e02fc6L,0xfd2625c560857c16L,0xd68f25e845dd06f6L } }, + /* 35 << 231 */ + { { 0x40dcb41018c1b3d8L,0x8af9a0bf954cc170L,0x9c40a17d5af27d6dL, + 0x6b20fa7d7137d35aL,0x7c46f6aaf07f5adfL,0x7caa6e3cafc2f780L }, + { 0xef03332694dfb637L,0xd8f330b38d0ac73cL,0xacbf571255d40a9fL, + 0x1b4ffafa3f4fde0eL,0xa17488e09fe6b04fL,0xd27808a103957cfcL } }, + /* 36 << 231 */ + { { 0x85e1de1e96569e6dL,0xc9545920d7ae52f9L,0x04ebc797bcd62008L, + 0xe142d0bc04a24db0L,0x5ed44b0d40e9fa80L,0x39fd679a48ddaba3L }, + { 0x91aba967ce7ee095L,0x76de8d3a0e97d0f4L,0x92e7a107a221785fL, + 0xb028f67e734283ffL,0x987f644168af2f42L,0x0ad882369d7f7102L } }, + /* 37 << 231 */ + { { 0xc5289301642f7d3cL,0x53ea584de508c45aL,0x86eb66e949337336L, + 0xa56d59d668fbc13aL,0x44c464ffe9e51562L,0xe5280ecd8200a27fL }, + { 0x92e2a9334cc73f23L,0xf59780325e7b858cL,0x399bd41e90d4b2efL, + 0x4faecb8bd0ead86aL,0x6ead9c530ce48b14L,0x941b4807ef74700cL } }, + /* 38 << 231 */ + { { 0xea281be94d522b69L,0xb6855d45694a08bcL,0x7c47ddc7aa7f4d28L, + 0x2028e22b6c36bba5L,0x206b63430c2dee0aL,0xfeb0b3dae68fdcd8L }, + { 0x6dda02a44603db5cL,0xa705d0defd786a39L,0xd356f6a426aadd38L, + 0xd34acb7d95ef6a00L,0x073ea16e14846402L,0x2cf7a82ab2df8bc5L } }, + /* 39 << 231 */ + { { 0x8fdcd309bffd7240L,0x6843dd76386e459bL,0x222fa67c0dee5740L, + 0xa3801343620d7d83L,0x96dfdbffe21b4af3L,0x017bd3d3dadd04beL }, + { 0x1b6adba2bca18337L,0x191b86f1300ed35aL,0x103a380cd73bbadaL, + 0xc2f3172f36f95dacL,0xa01a10e220767bf4L,0xda882ca6989ad766L } }, + /* 40 << 231 */ + { { 0x5bbc748b9cc47708L,0x16d796054026c772L,0xefc3ce3ea053df6bL, + 0x30ea7eab0713752fL,0x15b491b9dfd524b7L,0xa751d82010bcd34cL }, + { 0xf30c708abbd5da72L,0xf0c55aa86d16bd51L,0x1754060ba6215d84L, + 0x3a48d2cbb863542bL,0x992e8340261d8c45L,0x4096f65be8fd2113L } }, + /* 41 << 231 */ + { { 0x5532411e1045d8cfL,0x2d2f8d6b52bea60fL,0xa850b61825c556c2L, + 0x6547892fe8965d13L,0xa7bd4527184d0cffL,0x0e7f7daec25ba558L }, + { 0xfcfaf7b234343889L,0x9d6a23aeb82ba1d7L,0x2859023b60514faeL, + 0x4d51aeddc82da6b7L,0x6a060dc38273cd00L,0xf2f8923d78478c29L } }, + /* 42 << 231 */ + { { 0x0baa35154f08b278L,0x26baf331e57297c8L,0x3fef65cc04e27c13L, + 0x0f910ee0ca8430b6L,0xa27c5f5c2c445251L,0xc780142dccf3c637L }, + { 0x47dc4192e0f3fbbbL,0xf4d12bd6f2a91a33L,0xc1eb18b206352685L, + 0x111cc07f5b3db096L,0xbce0cddbcb95c815L,0x6b0bae7e14d28563L } }, + /* 43 << 231 */ + { { 0x40d16b7705897177L,0x4772a643953915adL,0xc6cfc1d23cabc7a9L, + 0x0641e96df80536c3L,0x6c297cd6be4c5454L,0x509a837c9c00216aL }, + { 0x17455153c01ce9a5L,0xee76da8a40b825e8L,0x1757a59cd23a37acL, + 0x5adcfbd10958248aL,0x043314525d01549bL,0x831f725ab0c42176L } }, + /* 44 << 231 */ + { { 0x28704bdcdf7d537bL,0xbcae2c15fa88f42cL,0xab32eecd3866ac4fL, + 0x446754a2128c4a7fL,0xc69309c1739ef781L,0x216e9f43bd160d81L }, + { 0xe0efa3ec6fefc0aeL,0xd179225086a604f5L,0xe43e13e260418c0fL, + 0x6f605146f100b9b7L,0x6c39828a6e994093L,0x99558f4706c019e9L } }, + /* 45 << 231 */ + { { 0xf541b3cd28df49eeL,0x0be75ef5cec2660fL,0xe73d18bb620c81f1L, + 0x42e81fef3c775c53L,0xd0a9dcdcbc012ed7L,0x570f5a1b8f292a58L }, + { 0x51f302e74c030819L,0x42e1903f50bb8a5bL,0x6d8105a98536e7d0L, + 0x66e2fdf1c1ca766dL,0xecaf4a316c5927fdL,0x347803cf96a14565L } }, + /* 46 << 231 */ + { { 0x794d90ab425d3a7fL,0xcae9008d93ecbe48L,0x211e38c3bd5f11b3L, + 0x6020ed2a6db1c1d7L,0xaa5695064437f020L,0xb2b93424235f4d6fL }, + { 0xa84a3c1d66ab2a3eL,0x171f9325712a14e0L,0x4a43cd6744d958d0L, + 0x53bea85ee95dc3cbL,0x1fba008769f2009dL,0xf0fbc48f31c13eb4L } }, + /* 47 << 231 */ + { { 0xefa3dea85fb2227aL,0x0160b031e098a97bL,0x92a554e3553377b1L, + 0x7b58c26258ccaac8L,0x666400171c3e0a47L,0x40e45f90ae2d7d8aL }, + { 0x660df3441ee18103L,0x5515cd66e9b64e55L,0xede93c59de059b3aL, + 0x874a0c90ca0e7acaL,0x840188abc8b1daa0L,0x9d49a02601e148a7L } }, + /* 48 << 231 */ + { { 0xe93ee31ae12b4e64L,0x2ab8e378662d17f4L,0x2544bd9969516582L, + 0x7bf80e4b2e1e5485L,0xf30f0b14729d9361L,0xb3ffb5d18268d40fL }, + { 0x34605055ac193a63L,0x9e5ca9a9f8e04d69L,0xcbbeebc1085ecbb2L, + 0xda03b75bf340eac4L,0x3bf9468a84436462L,0xdfa8b4c80f26f20cL } }, + /* 49 << 231 */ + { { 0x2e6520714aa497e2L,0x2b9358fd7ecd223cL,0x96efcbdc4f828e86L, + 0xa0f76679d2f096c9L,0x3887bef70690b78aL,0x2e7d9cae1a01b10dL }, + { 0x8b0cdf0e5656e5d0L,0x0a6ca92d48d3ec2cL,0xdcacbdd3b49e2ab8L, + 0x4d087ee0d7485e87L,0x4987078292cc57a7L,0xa1776bd47bb38b8aL } }, + /* 50 << 231 */ + { { 0x60c113bdb711e087L,0x28694ff4e257e115L,0xf81d5e054c18d716L, + 0xd1c04b67eb0af843L,0x16e6e46e40d8907dL,0xb73c3de91dd34d22L }, + { 0x9d7f282519825f92L,0xdf5d33edba486ce6L,0x288fafac21c223d3L, + 0x21c4df016d05007fL,0xccd9626b197c5badL,0x3a91743902c91b36L } }, + /* 51 << 231 */ + { { 0x6f950922340ebed2L,0x9e796894beddf06bL,0x5a8ea337cd9d7a07L, + 0x1c5dee115bd182ddL,0xba87dd1ae0c79b9dL,0xb16169f3b9002931L }, + { 0x68098da138c62518L,0xea7bf413417fdc6fL,0xa500a320b6fdf768L, + 0x7870c71c4550c202L,0x0874fd9f6121afb2L,0x49f0fd0cab7d0b6fL } }, + /* 52 << 231 */ + { { 0x7af3de47f6b7fedaL,0x19b8a51ba30b2296L,0x16886446150a0af8L, + 0xdada5aeeb2a4ecbbL,0x77105de8e8de3888L,0xc54d352c7d763f77L }, + { 0x754984ae72ff499aL,0x3de4b2785a5a25f4L,0x5df75ece818512a4L, + 0xd4fc8093ca7ccf3dL,0xff9bdf544a49f4fdL,0x45d23e77de0a5840L } }, + /* 53 << 231 */ + { { 0x8ef88682ca85a586L,0x12038785bff64885L,0x99670d8ac98cf695L, + 0xf7dc3dca6c3d5832L,0x1e836a59fd3e64d1L,0x8dbb13addd426c1aL }, + { 0x21867f0690f59314L,0x7adb6f707da5ce5dL,0x662422ae0da28987L, + 0x75a1486466766a41L,0x2d42bede6c8937b6L,0x559e168dff0c474cL } }, + /* 54 << 231 */ + { { 0xa07fdaa25af635feL,0x01d67fb36a0c8fd9L,0xa226f8dac9eb8d8aL, + 0x0795c27ce7fcfd0dL,0x84556c0553578294L,0x92b30a84b3e57574L }, + { 0xc8eb6ac0ca5dc890L,0x061a0a195c8b7d8aL,0x60f3351923177c06L, + 0x780755917d01bf6cL,0x63ec8a4421f48422L,0xddfcb2c0d804c7b0L } }, + /* 55 << 231 */ + { { 0xb186daffdb2e385aL,0x7589c9cd43aac848L,0x9b474a411fb053d7L, + 0x2f79556be1ada6c8L,0x694badc54d7d9ce8L,0x31ac06a84921f546L }, + { 0xacaf91c165666233L,0x6ea97c8ee45b62b3L,0x9c8f3fa66f0096c6L, + 0x2db7da39ac68f8baL,0x0ad2da0f19a3d1b2L,0x08c96b0ff80d426eL } }, + /* 56 << 231 */ + { { 0x07d63f07257d20b5L,0x25475a304e8c62caL,0x2469d661789ac15cL, + 0xd0d2ba1b3aae86a4L,0xc716202a4458dab6L,0xa011ca5ec4d5f90cL }, + { 0x53ce0273ca2430c9L,0x61040ecf96da6946L,0x6847dd034247c99cL, + 0x0c500b4519defda5L,0x263316db365796d4L,0xff9b99e7b982d89cL } }, + /* 57 << 231 */ + { { 0x725fc8f911591738L,0xe6c16db3f4030f65L,0x66c7622d441b6b17L, + 0xad8e4b9c69d93786L,0x732d597473093a4dL,0xa2136d85228f103bL }, + { 0x84f1d9397bcf76e0L,0x971a4c55e2531411L,0x9816371d15920fa7L, + 0x5515cbc594bbc17cL,0x8b8c76e859d52722L,0x3bfe618e9a240652L } }, + /* 58 << 231 */ + { { 0x18981da25cd1f7c3L,0x198a91bb09b22c3eL,0x48d11aafb23d71ebL, + 0xddaa6e071d31782aL,0xca7b812a39125babL,0xd89dcd825d963539L }, + { 0xc7012ed9e5a89eafL,0xbcf0d4c4af0ce61fL,0x6f65a246e6a9f404L, + 0xae6a489d51c1302bL,0xab43a2bcfc5ea651L,0xfdb73470293b1e58L } }, + /* 59 << 231 */ + { { 0x8e860629f5c9d835L,0xf91a0b5d04efe37dL,0xaa2acb55b1956d3dL, + 0xe295b30fb5bb48ddL,0xdfad64a7e8275e6fL,0x1e203bb7d41beeaaL }, + { 0x4aa2fd5836e64f60L,0xfb0b92a706e01818L,0x68e386d60d29ff89L, + 0x617981bc1802840aL,0x6d68ccf7ceb124f5L,0x19193c483b120ddaL } }, + /* 60 << 231 */ + { { 0x4d02098b8b5d9d67L,0xecb580503148dc75L,0x561545107d898600L, + 0x0213ef782d8be728L,0x4123671b1f11d90bL,0x8b9ff1b654c291beL }, + { 0x139ba95e52db185bL,0x83be41d0997b3eb4L,0x4a950c9a41e2e288L, + 0xdca0290c48916145L,0xf1eb9327cd073e77L,0x384ec5ddbd4f4ccbL } }, + /* 61 << 231 */ + { { 0x7e538f9036f4b7b0L,0xeb54e9e4ca25008eL,0x0054a07bf8af6eb2L, + 0xd96b712f5e3f61e9L,0xf01da03e29aa496dL,0xedbbc2d7d00faf95L }, + { 0x178c5bbd104f4dd3L,0x5cbd4783aa11b0d0L,0x4433fe6156eecea2L, + 0xdcc01bdcada7991aL,0x89ca41ba1addfa5bL,0xad64ee097a65ee64L } }, + /* 62 << 231 */ + { { 0x05a8a58d7e276915L,0xee28f77bf1582bf6L,0x6f308349285bd210L, + 0xb8b8ec47ab877186L,0x0436930e0ddb857fL,0x20a9973e5346b800L }, + { 0x756ab9b5848dd5b9L,0x33a220cfa12370ebL,0xdbd87c391f3d0386L, + 0x90c6879075429844L,0x5cc1a9736193f021L,0xf0b80f6543d46e24L } }, + /* 63 << 231 */ + { { 0x45e5f57bf79f5116L,0x14f02b229bcd30ecL,0xd989ee5426a39a1dL, + 0x497ad3c3d5854b85L,0xb61c15e50154364fL,0x5979941f502107d5L }, + { 0x0b99f087195934f6L,0x1f852baa605fbf71L,0x68ec80e47206f65bL, + 0x0392af1cea5bc3c0L,0xcebe56f81cb1d6bdL,0xdc6279d90f80b6b9L } }, + /* 64 << 231 */ + { { 0x10c082a63fc14a85L,0x59389ebc1c0b14c4L,0x785d935b4cb291a7L, + 0xfc2ae15313e9ce08L,0x3146fabf4df6f1c4L,0xa2a4a457c87dd24cL }, + { 0x85fdd8771deb49bbL,0x2b7843709b055934L,0xc81d05013e7e0297L, + 0xb56ddd1fb92df904L,0x4612df9f295ddccbL,0xc24bd4cf0e27cf1dL } }, + /* 0 << 238 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 238 */ + { { 0x7830460fd1944d1bL,0xc56f08e784350af2L,0x73bee2aa307d9c78L, + 0x1b02af1b5aad8b6cL,0x5e31882703848db5L,0x4785958bf230f476L }, + { 0x4ea6535d4f80e25dL,0x9958c9c7d23c7f72L,0x4c197b332fd33cabL, + 0x24c7b0b1c566914fL,0x956ce3c371952d3bL,0x8735694bfabae5f2L } }, + /* 2 << 238 */ + { { 0xca9872e1597bd10eL,0x6725cc9a4aed951fL,0x96b17cb84e05b280L, + 0x97987146fa234d45L,0xba78949ebb35a7d8L,0xb82e9b9f6fc59384L }, + { 0xa303e54a70f165c7L,0xfd6bb0dcb9c2cad9L,0xe57e2de8ee722045L, + 0xa05c106563e27035L,0xaa38e86602d2fe6fL,0x78e02fa8ee2f6aadL } }, + /* 3 << 238 */ + { { 0xd6256e7c62c627c2L,0x5571edfc3cbb10dfL,0xfedec45771cca8f4L, + 0x2e26ac5f8483eed6L,0x8e8c0671173508c2L,0xfd9f25d50f39bf76L }, + { 0x1cb080c3094cc1b1L,0xd367ca8c113e6552L,0x4ae2ca36bedb511cL, + 0x0de0c3e34707eeb6L,0x204cc610239d3097L,0xb235dbf0adb00383L } }, + /* 4 << 238 */ + { { 0xc0426b775e3c647bL,0xbfcbd9398cf05348L,0x31d312e3172c0d3dL, + 0x5f49fde6ee754737L,0x895530f06da7ee61L,0xcf281b0ae8b3a5fbL }, + { 0xfd14973541b8a543L,0x41a625a73080dd30L,0xe2baae07653908cfL, + 0xc3d01436ba02a278L,0xa0d0222e7b21b8f8L,0xfdc270e9d7ec1297L } }, + /* 5 << 238 */ + { { 0x9704cdc6a9c26f4fL,0x96808107908a6756L,0x73be47d40f1def2bL, + 0xd32c11d619215394L,0x1a59b9541842c2f2L,0xd64a70bb52c94807L }, + { 0x32b08c3e9dd262b3L,0x54d2cdc4440315a0L,0x671b3139425ace14L, + 0xd418542f2c7518e4L,0xce5e1712cc1bbdaaL,0xb3268403131f98adL } }, + /* 6 << 238 */ + { { 0xce4b39874e39e87dL,0x8e60a901966f4603L,0x1b95e4fd73c4a679L, + 0xae87f845b004310eL,0xcd50aedf815684c5L,0xa56805d343c77e38L }, + { 0x9a429abcf0588403L,0x77dd1a02009e699dL,0x27ad38fb52a417d6L, + 0x62591579fd8f6d00L,0xccb12126ea58f822L,0x3a009e76760a3ccfL } }, + /* 7 << 238 */ + { { 0x17688d3410023b42L,0x9bc8bd6f7cfadb6eL,0xe4cdf89f460aa255L, + 0xf709740a99eb21f8L,0x1ea8115cbd460bacL,0xbf7bafe8ac7e6629L }, + { 0xf8dc02bb096de741L,0x982f7becd2f6a583L,0xd971589a0f92bfeaL, + 0x662793afc02acbaaL,0x1b0f7d5eb771574eL,0xd9f71c4c66985cdaL } }, + /* 8 << 238 */ + { { 0x4f120aa7e2a07891L,0x9158bab3a25d3225L,0xc96bac5ecfe5f7a8L, + 0xd4e73d59bbf3cec6L,0xed8d233560361cd5L,0x9b1a252c562f444cL }, + { 0xbd37d3cfc70f23c2L,0xf13b3b6ea52ea19eL,0x7e35535a3d2f41edL, + 0x0353b52ee8b1743eL,0x31d89dfd7b5a2765L,0x2b7ac6848d9ea8b8L } }, + /* 9 << 238 */ + { { 0x3613afb361bd36b3L,0x85171aef3e0339eaL,0xdaf0c280c833abe6L, + 0xde566372e4500f09L,0x487dbef84a5bda73L,0x5cc00564e6e3f324L }, + { 0xbdf148cfb96abd01L,0xf8dbeda5ba9306ffL,0x05774d1a5ac0b828L, + 0x73ddc3248cf4a56dL,0xabc5af5232dc6125L,0x15ad6d2573294d7bL } }, + /* 10 << 238 */ + { { 0x7b5bbe51bd6086deL,0x7fbc95303816cee6L,0x60ac14fab3354bf6L, + 0x2b2abe43c9a6e793L,0x6ffae7342e19664bL,0x1d0e38b90064bd95L }, + { 0xc1303ba3fa9f23beL,0x6d5f4ea5d8f0a46cL,0xf8f472517a270649L, + 0x126c13ae723a5a0dL,0xe4d0a19e5e21273eL,0x18076170e83abb8cL } }, + /* 11 << 238 */ + { { 0xc21dc6946b771809L,0x2501f25600f85b8aL,0xb3a21dc347382df8L, + 0x25ede3c239dee18dL,0x39709b9db29b770cL,0x6eb314d510fa9c5aL }, + { 0x79140b1f508f5e59L,0xcce9f7cedeff2816L,0xa153c050400bc8a1L, + 0x052e03c4ff2c127fL,0xf8ffff1f841a03adL,0xc0c2626345896fb5L } }, + /* 12 << 238 */ + { { 0x06a67bd29f101e64L,0xcb6e0ac7e1733a4aL,0xee0b5d5197bc62d2L, + 0x52b1703924c51874L,0xfed1f42382a1a0d5L,0x55d90569db6270acL }, + { 0x36be4a9c5d73d533L,0xbe9266d6976ed4d5L,0xc17436d3b8f8074bL, + 0x3bb4d399718545c6L,0x8e1ea3555c757d21L,0xf7edbc978c474366L } }, + /* 13 << 238 */ + { { 0x905ad4bf3023ec1eL,0x8cc101ca16081c1eL,0xe0d47ec79cb74127L, + 0x1be5f86725da2dd4L,0xcba2ee4507ebac2eL,0xcee26667e22d87d1L }, + { 0xfc339af1c7c409ecL,0x112af9b47b7ef32fL,0xcc3e07898b821999L, + 0x4234433c222b3478L,0x55bcc87ddbce50c0L,0xcb6141cd7816f642L } }, + /* 14 << 238 */ + { { 0x8ae24e6b67f38eecL,0x61adae20ea14bc0dL,0x32737584c480c3fcL, + 0x44f61b79812ee744L,0xc8f607d5fe06d5d2L,0xfeaeb2bcea45267eL }, + { 0xe004522bb92c909eL,0x5171fe360ab3e854L,0x659936fe63ebc481L, + 0xdde6dbbff76649d4L,0xb38c160fe2295d0eL,0xba608b7e1e8f5c1bL } }, + /* 15 << 238 */ + { { 0x55616c4c86c2cb9cL,0xcfa8b484173526faL,0x096a09d90039a4c9L, + 0x6ccb4964f300a73bL,0x42dd78ac66819855L,0xa7c532c10941599cL }, + { 0xd15905f0b630220bL,0x9f4893ca5637e103L,0x768c09bf8a2115abL, + 0x5091f4399c52755bL,0x4ad1c0f6d38e7c50L,0xf6e6b2d054eb4439L } }, + /* 16 << 238 */ + { { 0x73457010c46db855L,0xccb68c43dd579fb8L,0x705b0e8c9c25fe5bL, + 0x40f36ea182dd0485L,0x3d55bc8527ac2805L,0x15177c6fad921b92L }, + { 0x51586cd55ab18cabL,0xf51b5296cbb4488cL,0xbb4e605e84f0abcaL, + 0x354ef8e3772dd0daL,0x7f1a8f795e4e1d41L,0x93461f09de5d8491L } }, + /* 17 << 238 */ + { { 0xe186b0b09cd7d54aL,0x0451cb0dd4303760L,0x90a8b0f84b38f082L, + 0x2357f03700b04fffL,0x8a4669f86d81dbd3L,0x2a5cb6f6bd94842aL }, + { 0xa13d19c4c498a572L,0xb7b8fe10cd937a76L,0xf8df355ed9842244L, + 0x64fc9d62b077c8feL,0xd4b2c3cce9dd337eL,0x7c63799ad3784edaL } }, + /* 18 << 238 */ + { { 0x39fe6673a780fd38L,0x8bc8d026a4b4cfa8L,0xcc339850801c44bcL, + 0xb5d80c4bc2dca07dL,0x745ffb5d91f1408bL,0xb55588f89017d1e7L }, + { 0xafef3cf1c3d76a1eL,0xe3a6e8058e1367ebL,0xd09ea1e2a642d2bbL, + 0xf303c613216e63e5L,0xe699e51cc98908e6L,0x835d4cefafeac3c2L } }, + /* 19 << 238 */ + { { 0xd1cbe55ee5000eceL,0xc1a074b01ff0f474L,0xc6681f48d7ffb89bL, + 0x7c68011d48d0bb4dL,0xf305627bdcef5e07L,0x0f0e0c36323ee3fbL }, + { 0xc5c6b61355f5f185L,0x6e4de5af52d6cc84L,0xa64ea548889fe8bfL, + 0xc4c5e4104d28350eL,0xef944a8f7dd3072dL,0x7ed579fa13356185L } }, + /* 20 << 238 */ + { { 0xec72c6506ea83242L,0xf7de7be51b2d237fL,0x3c5e22001819efb0L, + 0xdf5ab6d68cdde870L,0x75a44e9d92a87aeeL,0xbddc46f4bcf77f19L }, + { 0x8191efbd669b674dL,0x52884df9ed71768fL,0xe62be58265cf242cL, + 0xae99a3b180b1d17bL,0x48cbb44692de59a9L,0xd3c226cf2dcb3ce2L } }, + /* 21 << 238 */ + { { 0xe646281876ba99afL,0x1d53bd27818b5992L,0xc55e135d67e1d81bL, + 0x32b9e37023e211feL,0x91ea63dc130b1176L,0xd7e1cc51a34fbb3cL }, + { 0x5363fd962fee934dL,0xd19c50ba0b8fd289L,0x21257825a11c27b6L, + 0x19159a966792c1ccL,0x0ccc3cac39a08fbaL,0x841cb58a45512d8eL } }, + /* 22 << 238 */ + { { 0xae8532c3224ab492L,0x8bc92c85f6acd0ddL,0xc071ba92b796d21dL, + 0x1290162943797a3bL,0x8f4c5fb5ec950329L,0xfab6f950cf0578e3L }, + { 0xb7b8d211bb6aa75cL,0xb06279dc3d1147f9L,0x060db1a7591820cdL, + 0x0e691a412830f356L,0xac00664224b8bc33L,0x579f9c052f17441eL } }, + /* 23 << 238 */ + { { 0xd8b9dcd50c4cb7edL,0x2f59d64c7619cdf4L,0x7e83d18e284bc6f9L, + 0x49af25123e415166L,0x90388976ccd64d11L,0x4708fffdfe2580b6L }, + { 0x7a8d25ff17dd4d8bL,0xba7785fefd71355bL,0x7cceb111b9789cc6L, + 0xa8fd782ee98d6b78L,0x8d1b7fb66135d4a2L,0x78c2267d35e382beL } }, + /* 24 << 238 */ + { { 0xf38995589311182cL,0x1bee4c4bb657a7b7L,0x0b1c4fd32df8d1a7L, + 0xf16bcc2376d3fbbfL,0xd5888916f4fd52bcL,0x3de6cfb4d5cde1f0L }, + { 0x764ffffdd4a07dfdL,0x5e674426e2642182L,0x34f64762ccd57b85L, + 0x2233a4c329351062L,0xdf076095d9c642f3L,0xac917a2c59f0df34L } }, + /* 25 << 238 */ + { { 0xe588d5a8cf2f7d4dL,0xb45923ee86798c14L,0xffefd323f0623572L, + 0x24dd7019005f605aL,0xb9e833053a6edaecL,0x039ed04949923a44L }, + { 0x0f83a74360789fd2L,0xb4f91a8e9b001515L,0x37b856664261ad9eL, + 0xc291caa68b92b7afL,0xfa0f8a5e67ba28e0L,0x362a6808c5eefb98L } }, + /* 26 << 238 */ + { { 0x8aee939cc64e4ab3L,0x3baac0a844621bb2L,0x9094a09629da9bc3L, + 0xa92dc70806d2314fL,0x45c1cd0e34235918L,0x51aeb007c34021a4L }, + { 0x58267735a3492237L,0xe8d494bd375eb21bL,0x664dacf5a395bf8bL, + 0x2ef1feb612cec40eL,0x90c5f43fa7141e5bL,0x93e80dd03855169fL } }, + /* 27 << 238 */ + { { 0x2e550006211b2fb3L,0x8c82e59d6cab73baL,0x011bb2fb2bd326b9L, + 0xfbd519ff1e0efd69L,0x0fb2f266320cec7fL,0x879e28c03518fac3L }, + { 0xd0887775e01294eaL,0xf6e60efd1df5bb0aL,0xb2a5d3a404d04a96L, + 0x915eaa29a4f3500fL,0xcb6c03f70db6bde4L,0xfee081a405f30cc1L } }, + /* 28 << 238 */ + { { 0x9580cdfb9fd94ec4L,0xed273a6c28631ad9L,0x5d3d5f77c327f3e7L, + 0x05d5339c35353c5fL,0xc56fb5fe5c258eb1L,0xeff8425eedce1f79L }, + { 0xab7aa141cf83cf9cL,0xbd2a690a207d6d4fL,0xe1241491458d9e52L, + 0xdd2448ccaa7f0f31L,0xec58d3c7f0fda7abL,0x7b6e122dc91bba4dL } }, + /* 29 << 238 */ + { { 0x24e2801364ca563dL,0x6f06fde270f8f91eL,0x9abcca1bd2a65c0fL, + 0xc5728ffca5aa1e40L,0x654f0f56eb9d3e45L,0xe04ada2394161a0cL }, + { 0x001b25626ddbc960L,0x253b447aef93504dL,0x895ce21e2d6dc894L, + 0xefb987381c1b63deL,0x6adb6eecde8b806aL,0x9ea3884e0240e7bfL } }, + /* 30 << 238 */ + { { 0xe8387f68411ad563L,0x98a962eacc5f157bL,0x8093a8d296090321L, + 0x240a73083790052dL,0x6cb4a7382e7dcedfL,0xda65bf8481a60e8cL }, + { 0x420ce478c66c70aaL,0x0e7959ec42da3021L,0x44bc9d3c7e35aa20L, + 0x36e49d764e9df39bL,0x7281073a9b286287L,0xd9a068422524b62dL } }, + /* 31 << 238 */ + { { 0x00d6e0312546247eL,0xcc2851020fdaebdaL,0xb8a453f15601006fL, + 0x0afaa3f138be7068L,0xc87acb442c6cd9f1L,0x10dd5d031ffd5fbcL }, + { 0xbae0b62fddacbbd0L,0x1daadc18446bf2e2L,0xaeaf15317ef0facdL, + 0xe7b92b76c941808fL,0xda59af2ae6d0dffeL,0x1c09b783e612b888L } }, + /* 32 << 238 */ + { { 0x3bd258d8775f516fL,0x4bedebd5c715927fL,0x5b432512e3f966a0L, + 0x338bfca7709d0c2dL,0xd142cc1049658259L,0xfabc6138636b8023L }, + { 0xa9ef94014d4ef14dL,0xd5917ac1c54c570cL,0xfd2f63c55cb64487L, + 0xbae949b11cea475bL,0xa45446031e67a25fL,0xa547abc1dc6a7a6aL } }, + /* 33 << 238 */ + { { 0x6c7b4cf344b880b0L,0x29da87760a388eaeL,0xf434d173fe9617c9L, + 0xaf67cc2ea47abf28L,0xe211ad37249d0eb4L,0x88d156e538bce76fL }, + { 0x60320c6dd58fa585L,0x7b352c39ebf09a7bL,0x9305dae8a31ce734L, + 0x70c35be89361cc3bL,0x6b8b71f8bcd14255L,0xd1b7963572a457a7L } }, + /* 34 << 238 */ + { { 0xd8d04787ef8849e1L,0x58adf044148375e5L,0x5b613ac476623232L, + 0xbd274d2f95d7e359L,0xd97acbd271576bb6L,0xd20bb2c34c7fc4b7L }, + { 0xe15465315f837664L,0xddac59b5fb4ce79aL,0x33fef5214fb36e08L, + 0x0467811045108b22L,0x0de6c7766dbe57bfL,0x456d765a25fea77bL } }, + /* 35 << 238 */ + { { 0x4d9838a32922b715L,0x3cd9fc0a6a7bb3a7L,0xb1bf28fc2247e916L, + 0x92dd22006f206a16L,0x8ea87d67b51256caL,0x2c535730b5a4bf17L }, + { 0x34da42505f584954L,0x72326fb8fefca748L,0x40fd9d09da2844a2L, + 0xaadaf71c412da037L,0xa62329a9aa6f884aL,0x1b6165e6726a8f8cL } }, + /* 36 << 238 */ + { { 0x2a2dedafb1b48156L,0xa0a2c63abb93db87L,0xc655907808acd99eL, + 0x03ea42affe4ac331L,0x43d2c14aeb180ed6L,0xc2f293ddb1156a1aL }, + { 0x1fafabf5a9d81249L,0x39addead9a8eee87L,0x21e206f2119e2e92L, + 0xbc5dcc2ed74dceb6L,0x86647fa30a73a358L,0xead8bea42f53f642L } }, + /* 37 << 238 */ + { { 0x39de72e225e62213L,0xd885c406a03a58adL,0xa63964b527e76458L, + 0x93f83239637c0becL,0x8c9e29b4ba556e65L,0x7d746448a6183182L }, + { 0x6dee01aa09a8eb37L,0x97289f2e757ffa96L,0x367ec50fb4785102L, + 0x200f77cdb3d07cd8L,0xadc7c000a581946eL,0xa2dba5e52c0b32aeL } }, + /* 38 << 238 */ + { { 0x95a5a7f0b203f75fL,0x9b574cfcb5df11f0L,0xbf5fe3f2dba4b4e6L, + 0x347a7bd7d0987125L,0x858dea6b09377a2aL,0x87cb1e66eea85d5fL }, + { 0xe7619b666146a0c6L,0x0012585a8a0bc101L,0x738e6589ea0ce92aL, + 0xf23547979a39b3f0L,0x666f3f5d6dc81167L,0xe569cc82fb06b0b3L } }, + /* 39 << 238 */ + { { 0xef0e64399c7677d5L,0x052bf027efc398c2L,0xa5d253cc515e4198L, + 0x7b915f07a71ce047L,0x56880ea2e177dbf6L,0x735dc74f0b5741d9L }, + { 0xa108632f0161a0acL,0x0c68765705e7e09eL,0x694e651e211709e0L, + 0x334e15e51d879a41L,0x6191d34260c2a603L,0x3a8ce0e6224234d7L } }, + /* 40 << 238 */ + { { 0x158d814db12c4bb1L,0xe52f75d22f0cf4faL,0xf106023e6141b59cL, + 0x5eb8b8ebbeb9d941L,0x1dd3972990cf579cL,0xb273252e69ee6efaL }, + { 0xe43a3c593e9947a0L,0xd605124f6c19dd01L,0x8090fdbd05c578b0L, + 0x8e6c535a622ff18cL,0x3600b0c257d12071L,0x6d026e5c78d001d7L } }, + /* 41 << 238 */ + { { 0x6e515f3608e33ad5L,0x3e320c5283512d9bL,0x171ab26a5ca1c452L, + 0xfb3061e874c97139L,0x7944644c9cacf3aaL,0xedc724f03687cfceL }, + { 0x7252d7590db9b5beL,0x625f17ed0eeaf1d4L,0x6b0b4e5e82e3c58bL, + 0xf03d7bcef0f2ecc3L,0x4cbaa878139a7580L,0x982e471672203e07L } }, + /* 42 << 238 */ + { { 0xa533f574e335d60dL,0x102b66fb2aa6855fL,0x7a57420c49946287L, + 0xe3bb702286f393c2L,0x1892642d04a41c49L,0x2c47ba38d44969feL }, + { 0x9068650444388ef1L,0xd94f6f131eaf6b54L,0xf81d8782f0b872e8L, + 0x7ced5924d013f6eaL,0x76ef63d307cd721cL,0x888646b36cba783fL } }, + /* 43 << 238 */ + { { 0xd2c858157ec1660cL,0x6c8988a3ee73763cL,0xd6cc562d5e80aaeaL, + 0x48f399d975768c58L,0x3189bf68af50c1c3L,0xa3f8d2df27dc372fL }, + { 0x99d6b416b8c7c529L,0x531707944406b1e6L,0xafb57933e3ac044fL, + 0x530ad3bab2548505L,0x791a290a977590caL,0xb0d07228646fd1fbL } }, + /* 44 << 238 */ + { { 0x636225f591c09091L,0xccf5070a71bdcfdfL,0x0ef8d625b9668ee2L, + 0x57bdf6cdb5e04e4fL,0xfc6ab0a67c75ea43L,0xeb6b8afbf7fd6ef3L }, + { 0x5b2aeef02a3df404L,0x31fd3b48b9823197L,0x56226db683a7eb23L, + 0x3772c21e5bb1ed2fL,0x3e833624cd1aba6aL,0xbae58ffaac672dadL } }, + /* 45 << 238 */ + { { 0x86d2f71530cf85afL,0x8e1b053cf7e634e0L,0xe79592f43a4e466dL, + 0x26752e8506985331L,0xfd098e83dff73363L,0xaa158e2c505ffbc0L }, + { 0xe45fa1cba0fe759cL,0x6e2f5989bc0d1491L,0x4a804eacae7210a9L, + 0x0e252f758a63f67bL,0x0d7600cf362a7df7L,0x795069bf6d5b2b18L } }, + /* 46 << 238 */ + { { 0x25f9f0fc0649613bL,0x109521f05d3005d9L,0xcce1c5b41feba4c2L, + 0x6a27cfafacda6021L,0x37ff83303ab6382eL,0x53c7ccb715ca79f3L }, + { 0xdffa6c9633611dd4L,0x7555cfd4352d3916L,0x2354bec62cbd44f7L, + 0xaf0044c54b0b500cL,0xe4835df7ce9aade1L,0x14e57f6bcb218644L } }, + /* 47 << 238 */ + { { 0xb5e26899b1c22bd8L,0xde12b0b51aaf3460L,0xc269595c31ee049fL, + 0x8c7513c88a73ed74L,0x8273018450cd009eL,0xb2cd2dec4d130b5fL }, + { 0x1a9015521971a189L,0x6ce23544c6f39bc3L,0xd76133aa9467badeL, + 0xf91173cc071ee7a4L,0xe54d8f44b8267c73L,0x5725e0676dc9aee6L } }, + /* 48 << 238 */ + { { 0x00e0a003daff1807L,0xcb9d155992c94fd0L,0x3c2b5c3dcebbf905L, + 0x9c799ec7d338afa9L,0x60b9908c4e2cfcccL,0x4bfe1a57ae3c6f92L }, + { 0x480d310efb116150L,0xa1ed6c31e3e7888eL,0x841a11d9720b5196L, + 0xcc337d178adff37dL,0x08c668265faa86c5L,0x945c90d49dfcc7adL } }, + /* 49 << 238 */ + { { 0x0fcc0854f2b3622fL,0x3a9e218ab6833f04L,0x209125d4ee8fc062L, + 0x98b2c628a3c3bf2eL,0x7e051fda83ca6a6eL,0x81afd3933d87981cL }, + { 0x8f3beaff4baf556eL,0x0f1b27fdcc7e66c7L,0xbf0b08f59f4a4461L, + 0x8eb739fa141985e5L,0xdb5b46112da43947L,0x63bf81cbe5cabfddL } }, + /* 50 << 238 */ + { { 0x355e40d398ff85afL,0x19f2f3c2b08f836bL,0x0a62d254737cb5f7L, + 0x5d0ef7d9f8c50d82L,0x773a399ebbd70eb7L,0xac357974a70bea8bL }, + { 0x1de5a45cb3b5d794L,0x67c58b52a48b55b7L,0x724f56f4b02ebc8bL, + 0x03dc71e3154ad508L,0x9bcd3939cc84428aL,0x7fdba978158c4a0eL } }, + /* 51 << 238 */ + { { 0xac08e06e65b93d44L,0x2397625a5358c691L,0xfbc9285a8516e31aL, + 0x38ce0d3544ffe25eL,0x13381dd16414072bL,0xf782fddc170ecb4eL }, + { 0x78c71a716f815259L,0xb725870573659a85L,0xd37678008712d968L, + 0x153d8aee3eda5006L,0xda4fd94818f1439eL,0x6384135352dbfdf8L } }, + /* 52 << 238 */ + { { 0xce92224d31ba1705L,0x022c6ed2f0197f63L,0x21f18d99a4dc1113L, + 0x5cd04de803616bf1L,0x6f9006799ff12e08L,0xf59a331548e61ddfL }, + { 0x9474d42cb51bd024L,0x11a0a4139051e49dL,0x79c92705dce70edbL, + 0x113ce27834198426L,0x8978396fea8616d2L,0x9a2a14d0ea894c36L } }, + /* 53 << 238 */ + { { 0x06d57f2920514206L,0x61394b863a2cc1ebL,0x0ffdf49a86c7b2c1L, + 0x65334e9349f58f13L,0x180b10b8c08dfb05L,0xec352adef6c95b7aL }, + { 0xf9801dc0c4bde0faL,0x428c77f0dabf0c66L,0x2a7d1bb0c2eb80d4L, + 0x81774172fdb56fabL,0x7507481f1d965515L,0xee0693bb8ebfadebL } }, + /* 54 << 238 */ + { { 0xf4589418ac56a031L,0x21f3dec6f2718a10L,0x0ed08d9690f28b6fL, + 0x2624bd7a35c3a6a3L,0x1b3f02e8bba795f2L,0xe629b5aa3977fd17L }, + { 0x66c8cd7691e8df1aL,0xf36c4e2c1b2b5542L,0x7f6b742f7dff66a7L, + 0x00bc68b8242e0fc2L,0xdff5c73360119d9bL,0xe726260fb5c4dddfL } }, + /* 55 << 238 */ + { { 0x0242fa358eeaa549L,0x2d081bcf8abc93c6L,0xaa31813c55551d40L, + 0x1cf21c1271db3aecL,0x5a6dede7203880d9L,0x389c63cabe4aaa9aL }, + { 0xff4db7d4bf28086fL,0xd89c039b33146844L,0xc2b32bf06df6f790L, + 0x7f4e836b9f22fecaL,0x3f64d0fa0af51572L,0x681a1f5bc67aa565L } }, + /* 56 << 238 */ + { { 0x9f9ac9608e2941a6L,0x43e7ff902fc4fe1eL,0x5ec413596033e041L, + 0x5ce791c46f6ff0f3L,0x8d134b899d907343L,0x7bd15c7786304df2L }, + { 0x2cd2ebc777c4a913L,0xcd86a39d45f07153L,0xe7e12d2e88bc423bL, + 0x478e814b0b3163f4L,0x78bd9c8abe8ec766L,0x6a5763e87709ce48L } }, + /* 57 << 238 */ + { { 0xb503ac624329d7f4L,0x3a900374488e3ce4L,0x8a11addab0d8dc97L, + 0xbea3ea2c0873bdf8L,0x0f57130115bc7adeL,0xbc98d2070b2b69a0L }, + { 0xaefc4047639d182dL,0x0e6db26feb3c44eeL,0xaf0f8b392a68a48dL, + 0xde65a6b36bf1e593L,0xe48f8fc989dbd38aL,0xad18a43bd8d285b3L } }, + /* 58 << 238 */ + { { 0x249d86007e9d48c8L,0xec6109ba109a54bbL,0x64f688af5ac65ad4L, + 0xb12c85b4be1796baL,0xcc258d31c9940da0L,0x59590853ff2f151bL }, + { 0x9e9edc4d401c5d1dL,0xdd9ad117f230b458L,0xc2c752ac962334b6L, + 0x3fab66ce27327e6cL,0xa363d3643816a47eL,0xa6fc57bec180bbdeL } }, + /* 59 << 238 */ + { { 0xd72dd5893ff345d5L,0xf87c17ae41e1d287L,0xadadbf525964d55fL, + 0xecc7f27af8b07db1L,0xa2dacfce6f2aa320L,0xc7936da72aa3f228L }, + { 0x2e9e6058fa504b87L,0xf2df43279d0f0634L,0x90d5ee22a4b768c5L, + 0x1ea9bf0b5b46ea84L,0x792370f45cc41770L,0xfd17823176c1a3f5L } }, + /* 60 << 238 */ + { { 0x4f1e1254604f6e4aL,0x4513b0880187d585L,0x9022f25719e0f482L, + 0x51fb2a80e2239dbfL,0x49940d9e998ed9d5L,0x0583d2416c932c5dL }, + { 0x1188cec8f25b73f7L,0xa28788cb3b3d06cdL,0xdea194eca083db5aL, + 0xd93a4f7e22df4272L,0x8d84e4bf6a009c49L,0x893d8dd93e3e4a9eL } }, + /* 61 << 238 */ + { { 0x4c124a904190257aL,0x09002f52347e517bL,0x2e9b69a1e5760993L, + 0xbaa49e53e26672bcL,0x9468fc3bf7820190L,0x637bccfe1f955328L }, + { 0x16fd33f26e0aa088L,0x9391550757b2b2adL,0x85e98842e9a0ace2L, + 0x8e2bd52b4fa787afL,0x8a86bd85644aeeacL,0x63490956c2814734L } }, + /* 62 << 238 */ + { { 0x5e902fb3063b3517L,0x0cd006cae5a65212L,0x597bd7804591c4bcL, + 0xd853d81be17c1d3dL,0xbc4bf68156e5d24fL,0xbc801615d26b5ce5L }, + { 0x1ffa5cd5caeecbe7L,0x16ec32a4b0203156L,0xaaad43269a857672L, + 0x0606ebf9189c6f6dL,0xb90730bd57e476f2L,0xed8d82b1d492fb05L } }, + /* 63 << 238 */ + { { 0x69a2a9b6ff824814L,0xe7b716e7c35c5da3L,0xb6781a5e9a5fde1aL, + 0x08bf695dc072e1b5L,0xaadf71462590a817L,0x490297f9c755c83aL }, + { 0xbd9fad6191c29990L,0x87b3abc226b6cb9dL,0x6975d59865fd0b64L, + 0x0fdc5267f4257158L,0x9f3e10585877bbdeL,0xb7f4cfb04297a2d1L } }, + /* 64 << 238 */ + { { 0xd699ea2d8d095606L,0x3cd080c51e0ddd3aL,0x46604bad66a8b35bL, + 0x0c779b624233fccbL,0x578458acbfd3cf0cL,0x6820f66596bf57afL }, + { 0xa9724245bf1f302cL,0xbbde24da277a6c3eL,0x0980a5b8c6be8c14L, + 0x6230e3ec774d62c4L,0xda1467d84fbde24bL,0xd9d68d07cc862204L } }, + /* 0 << 245 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 245 */ + { { 0x67c516347378f90dL,0xbc201a7966647082L,0x77fcc8dc9ee450cfL, + 0x8dd2b318b41a3e2fL,0xdf6a935e93bf0689L,0x75edabf3a92e5464L }, + { 0x49afcd9f604d208aL,0x372f0ea7d465ca48L,0xcdbd8ad2c7ea7810L, + 0xfe61571e550822b2L,0x744a4f9386606adcL,0x6beb3c9cd9d4e110L } }, + /* 2 << 245 */ + { { 0x1fef389ce700b9f2L,0x63029466425bc8abL,0xbd770a1437f04a33L, + 0xc7438e29d0169369L,0x6b265742e2377cc3L,0xdf24bf96c369fa4fL }, + { 0xdfdbcf470ad94e08L,0xd101b8617f75a7dcL,0x5574a0b82a9c483cL, + 0x0563fe942de43228L,0x58ca0e8aead1fabeL,0xdc3d9a8466023966L } }, + /* 3 << 245 */ + { { 0x383bda07c3fd20e5L,0x9619b1df5c29449bL,0x6f3c717d369f39bfL, + 0x1bb593d11a5a3900L,0xd0f07ecc2aec6c2bL,0x9d72eb2a4240b202L }, + { 0x35342f6cc50e4a0cL,0x701b46626b93bf61L,0xfcd6eb09ccb6a888L, + 0xabb7a6f785aa42c5L,0x952f8824aa4e5895L,0x49860db85c406582L } }, + /* 4 << 245 */ + { { 0x3667a7203955812bL,0x0d73483b284d1dacL,0xe084535efc62f791L, + 0x5bc1652b389faf7fL,0x40cf51683a71b7f6L,0x8a4b19fad4f39703L }, + { 0x823e754a2a8eff13L,0xf01b2021bffa5afcL,0x5639ee027225b319L, + 0x7533bc86fc282f16L,0x710009d2c69f61aeL,0xe30c499dbf65e803L } }, + /* 5 << 245 */ + { { 0x0da7ac1b734b4ec3L,0xf47fc1d012a2afbeL,0xbbbc99be87dce4a2L, + 0xf7264b4edd5c6378L,0xe9409305f618ffdcL,0xafadda9bd1846ac1L }, + { 0xe734f9d0a21850d4L,0x199cb44f8722a316L,0xcfe8704b38cae89fL, + 0x2db1e56b6b151b57L,0x116ca5cf69ce7b2cL,0xe9b8625f57de97c8L } }, + /* 6 << 245 */ + { { 0x18811bd5af247c49L,0xbc180793e124dbdaL,0xed978d3a21234fc4L, + 0x516dd9a70616ae15L,0x8f80677774e430b8L,0x9094256906e8fc49L }, + { 0x4ca03fb5a4e61235L,0xb91de709b617f361L,0x0898d82d0ed08bc3L, + 0x2bd712368cb08146L,0x45b92d45e213176dL,0x05894791f2bf5b9cL } }, + /* 7 << 245 */ + { { 0x0d79cb892695ea2bL,0x2cb0f8dfc88e538aL,0xc1b8dc3da80f36feL, + 0xd756fa6684f00cc2L,0xa6f1cdec9cb9efb2L,0x5c3f15a8a6a21818L }, + { 0x9a7ee3516995d09fL,0x88885463d70434bfL,0x18cecc6d4f7d5d33L, + 0x3f0138866b353bd1L,0x53bf798b0d9ad368L,0xeffd465a28dbc3eeL } }, + /* 8 << 245 */ + { { 0xeb29e44cb5d98ac1L,0xe47e57f80e227a4fL,0xd09c04943d2bf688L, + 0x3ab7799a47428dd2L,0xdc558d6be9aafac8L,0xc042c4cd87f9f6e0L }, + { 0x93842bcd89fb4693L,0x62dbc82f7068fbf7L,0x164552687e6d47b5L, + 0xab304b7a4c37eeeeL,0xdbb3d4e13fc412ceL,0x4f65dad0a726a2c8L } }, + /* 9 << 245 */ + { { 0xb25e01b2605cdaeeL,0x74abec55bc57969dL,0x9c57bfabcdd9d41aL, + 0xa3330e3f4a9e32a3L,0x5929a0d8e5792fd8L,0x830b4ea271ea2cdeL }, + { 0x80065ac1fd06d246L,0xa2b416e632e64a25L,0x3950bde7c0c927a9L, + 0x9951f3bd679d9b8cL,0xc235a274651b6855L,0xbfe5e08e5ad97bc1L } }, + /* 10 << 245 */ + { { 0x4409a5b6744ae145L,0x5e83fa0b7f620908L,0xfc489bec2e140aa0L, + 0x5805a462e3cae337L,0xe56e9ff7c2211c21L,0xb722f2b40c955362L }, + { 0xb098a32f41371f33L,0xe6cceceabb4923d6L,0x1cfbe2b3d82a311cL, + 0xcf9428936b98f917L,0xd60dc62492ef848cL,0x34af446e5adb5228L } }, + /* 11 << 245 */ + { { 0x0eb7e743796ce1caL,0x138653e5d851377cL,0x69c7c86f2b11c8e0L, + 0x878ec1decdf2b205L,0x03e6688aae0e8562L,0x20810666935a36a8L }, + { 0xc8ab7c7f26635c50L,0xe75cdb06744a21dbL,0x4e26f32fd720e198L, + 0xa1c6395ad8cded81L,0xb75dc6ea6ce4fc04L,0x71750b33004623b5L } }, + /* 12 << 245 */ + { { 0xbdef84077e60c447L,0x88570f712a65accaL,0xef3d4a400bb6aa79L, + 0x5c9d189060212976L,0x80179ea21d96c43cL,0x3f002e6d53d2948eL }, + { 0x14b2cc9149d78183L,0x7a549c71b496c279L,0xf4beac3f44995f6dL, + 0x5a34239800bc78feL,0xa874dc1b60e42da0L,0x3a984010cf5824d5L } }, + /* 13 << 245 */ + { { 0xe514ee06dfb9760cL,0xb8862d7577b8951fL,0x0144676ef8ee1141L, + 0x49561a3002eb3e82L,0xb3541c154ff9f897L,0x1670edf0a7a99791L }, + { 0xd41d603564aea7f9L,0xf66ffd092b3463b4L,0x0784e015c3b26fb6L, + 0x88edce33ec46f8c8L,0x1b1e25a3b6381011L,0xbfaadc03ff95ab97L } }, + /* 14 << 245 */ + { { 0x727a59fe0c7be4e1L,0x75a7d5e3f58ced15L,0x146fc0d990f569e7L, + 0x94dbccd2b7f1dc54L,0x0df1ef90b75bf232L,0x2943a082a2568190L }, + { 0x75f2f80d67837b06L,0x07e3506f24b44b6eL,0x7c30829ad0d2231bL, + 0x9ce577ca93277abfL,0xa19d1868b17549ecL,0x0ad6ff5525e8c4d7L } }, + /* 15 << 245 */ + { { 0x16b38dfe1c24d075L,0x3acd4c36992959f6L,0xdaf2fe88ac2da7abL, + 0x76e8ff0e89644935L,0xb8547c26e85f7076L,0x9f149faa1cdea7ceL }, + { 0x181a60729e125d84L,0xc4aef9fa18751ce6L,0x451c84660e00f00aL, + 0x662b3e7ac4e3e6b8L,0x57b7114ec6b64507L,0x07aeb1980b37fb70L } }, + /* 16 << 245 */ + { { 0x79d88e004516234aL,0x98dd3cb931f9cedaL,0xb528000fce7d606eL, + 0xc773557e2fa27fd3L,0x55b53dd3e19436afL,0x675084b3e10b64c7L }, + { 0xe583266556d56374L,0xf8f7fd2a307e2e60L,0x7b93bf537af3e3dcL, + 0x94fafa2cf47d298cL,0x94c2ff9a21121369L,0xa41de95f33468ff6L } }, + /* 17 << 245 */ + { { 0xebbafd4720f25aa7L,0xe2becad71ac444bfL,0x323356a092a944b8L, + 0x32feccc0c9a3cec9L,0x15ec3aaf5f9e96c1L,0x852142b5c12c8e62L }, + { 0x098ffcbf2b6865f1L,0xcca470e8733d7741L,0x0f8c0f5271945bf5L, + 0xfb654f6a08068827L,0x3a9e7d742a0e2829L,0xb90742b04b687763L } }, + /* 18 << 245 */ + { { 0x145afb651fdb2a7bL,0x93315b684eff5eadL,0x0cad1d20e40ca999L, + 0xda9b517a379a8173L,0xacb665780ca018cdL,0x1e9d919f481969b4L }, + { 0x5c9a058d68130364L,0x872e26620a62ce5dL,0xca598848acaabe54L, + 0xdabfcee18aa048a0L,0x16198d034ac52a57L,0x72eb5ec632b6d102L } }, + /* 19 << 245 */ + { { 0x13f2e1726a0c96e0L,0x55aed9e02d6b6f05L,0x3c919ba3bdce76c0L, + 0x647a525ffdda39aaL,0x5c0dbecc01a9011fL,0xa537ba8d9fd9dcefL }, + { 0x8472e375cff62467L,0x57672311ed5adf05L,0xd1e178dc6a423de3L, + 0x3ebcfe18d3ad3ca4L,0xb8f341d7ae802c11L,0x3f14c424ecdfdb7bL } }, + /* 20 << 245 */ + { { 0x381e0a136e4d2e42L,0x2f2a4ee183c0d752L,0x50d4647fc8e6532eL, + 0x7e210aeeb4e7495dL,0xfd147710bcd142a6L,0xddddb07b06429213L }, + { 0x63e06fc64548a6b8L,0x05d9b825904f92a6L,0x4b63fdbf9988ee79L, + 0x6cfa412f9b3366bdL,0x0dd5fe3dc8c61f51L,0x3ec77027be8e047eL } }, + /* 21 << 245 */ + { { 0xea7d01cfc7d81791L,0xfa6c0fe6e2264afdL,0x53c7eea363651291L, + 0xe58f8411f2d90f92L,0x4919b4c61faf0e14L,0x0c7dcd07148e98a0L }, + { 0xf9ef44cebc8bd43dL,0x3acfb6686f83cfb4L,0x34130e18f883693cL, + 0xda9ed2ae2d236c3eL,0xf54da64cc75cabdfL,0x1c3df906cc01722bL } }, + /* 22 << 245 */ + { { 0x686796c68d8f2286L,0xe0efaf9334d7cd1aL,0x84f9237c93b23708L, + 0xcb50cc8ee47f5161L,0x498b81e71f597821L,0x3c3f33e1a491079fL }, + { 0xee300c6dc69d1bc8L,0x279760e734778389L,0xe00ac0eb2bb8ed78L, + 0x9bf9a10e765c8b5dL,0xc7e95c0cf8c1e909L,0x3721300ae6e63ea5L } }, + /* 23 << 245 */ + { { 0xc03ad784d8dfd7aaL,0x671384a64b065a2eL,0x9b21e9e7bed74e87L, + 0x153b606cf889f75bL,0x7345c62a2aab6562L,0x270e4f445960cb4cL }, + { 0x515909fb885f0f88L,0xe43ee4f7067a7928L,0x5f906fc8fc182e56L, + 0x297ad5770641d0d1L,0xdcc45aa1d1b188b4L,0x8c817fb2ef062a39L } }, + /* 24 << 245 */ + { { 0x91e8c992044637f0L,0x01f7838827ee8e8fL,0x7c5e3f6dd095f5b9L, + 0xed7522fcddf3cad2L,0x80bb87056c57aacfL,0x495480b00cc5ff51L }, + { 0x964def7f04da2565L,0x8b0d0fe3afa72140L,0xcc75192584de66a1L, + 0x9acaf7fe075f07c5L,0x6505c2f81eeade93L,0xa2f35aa00e3cf58fL } }, + /* 25 << 245 */ + { { 0x1ad38a2d80548b22L,0x4d6120df47a37b3aL,0x6d64ef8c23e33cb7L, + 0xa1b5f51723c14ca6L,0xd2cdd425039a8e83L,0xa0a359ae229dd2dbL }, + { 0xde0788166c2779afL,0xd960453362d2abc2L,0xc5c48b20707c0e4dL, + 0xe452debd691c5407L,0x35c37ca882b0a299L,0x5b263014da3cde7bL } }, + /* 26 << 245 */ + { { 0xde34fa4586330487L,0x8391248153f61e6bL,0xd3f8fe742d04958dL, + 0xdade250f6df77d09L,0x3a3a16175649d9ebL,0xf9b77847a23abc74L }, + { 0x31d45db63b2e2c8aL,0x311ecc24f61a7bf4L,0x206029f9c56eab17L, + 0xb9d9ff35878c672eL,0x0d268c160fbf2d91L,0x2474b527a45f58d0L } }, + /* 27 << 245 */ + { { 0xad8e84be8436beaaL,0x8f07eee4209eb5d3L,0x47cba1d83ee61bddL, + 0xa081f21f72018544L,0x5dffddf493d88d16L,0x539a79efcac3952aL }, + { 0x990af57791bc452eL,0xb139d7d5012f5c6aL,0xf818c9f3fb180417L, + 0xeeb2d08475566152L,0x287571253f5d4ec9L,0x5a26505daa959798L } }, + /* 28 << 245 */ + { { 0x6536834e11b0f7b6L,0xcaa5271aad46c10cL,0xb5b6ead1fab43763L, + 0x25bf402ff7f7d8fdL,0xf33fb223e19374b4L,0x183ae9b75f348172L }, + { 0x1783c235078862a0L,0x9981a6c33cd368fcL,0xf58d2274fd627f9fL, + 0x37ac9c265c5e71cfL,0x167c8d047b0f157eL,0x24f522f8eefc7d85L } }, + /* 29 << 245 */ + { { 0xd25aeab3926cc973L,0xb3e2cffbdfc2cfbeL,0xdd259ed1de742b6cL, + 0x9d77c94e7b98bf81L,0x90f9067cb0ead3d1L,0x148f2a192a93fec1L }, + { 0xbae3c543c2850153L,0x0d330d758910422eL,0x06f80a9efa670474L, + 0xac6cee9f038431a3L,0x4900d17f5c22ee99L,0x62de04aa275a9774L } }, + /* 30 << 245 */ + { { 0xb6eefcc55f87fb35L,0x9766873b4371415aL,0x308337bd16b058bbL, + 0x6d5b1ddae1ac3884L,0x9307aa0835c4630aL,0x22cfcc0c23e91988L }, + { 0xbeb3814c37db0207L,0x19ab212fc4bbaf5bL,0x0801a1cf21abf22dL, + 0x9e6862cb3bd07332L,0xaa12ba0e4319929aL,0x0da45831f540f97dL } }, + /* 31 << 245 */ + { { 0x67d8ac9484bbf927L,0x7dd04e4e4ea01d33L,0x24ea6386f13def66L, + 0xa8a1acbe28f7f5f0L,0x5f578ffecc84c93bL,0xda8fe295f4ad116aL }, + { 0x4b610ae48483347dL,0xcac5c5596255f9e4L,0x19a0e043abcfe47bL, + 0xcd0cc9493966784eL,0xcc59a36743279291L,0xaa504087802961b6L } }, + /* 32 << 245 */ + { { 0xbe45d81a1b270599L,0x50696e7d97d6c603L,0x63c5a516b078ea89L, + 0x9f3efe41b4464764L,0x84580e24101e5232L,0x00850a1ac8ae8220L }, + { 0xbff4077ded55c404L,0xd74de734f2e7bf50L,0x4df4eef207e1c03dL, + 0x4ab3d0396e654d58L,0xb20056cd086f1596L,0xe4d08a278acd7cd5L } }, + /* 33 << 245 */ + { { 0x5510cebfe354510aL,0x48925b9349998c9bL,0xa05fc961e6d707a0L, + 0x85bf38f866ebc93bL,0xea637045254e615dL,0xae25e2e740d8459aL }, + { 0xa98583176efafd1dL,0x863931fd5a51c4b6L,0x3810d732d4221708L, + 0x959a2f70762a30f3L,0x7bdbaff9420ad3acL,0xba41b20bebdfe90eL } }, + /* 34 << 245 */ + { { 0x5e4d3280d3171eb9L,0x3fb715851bc65c5bL,0x6558962a901a899cL, + 0x78b7cd3e7851462bL,0x21228419ca8f6495L,0xfd8d8f9b2d8be765L }, + { 0xe5e90b92bc562144L,0x4f1f7ca1ae3243edL,0xd20178cd0985f4e4L, + 0xe5be263304253cbdL,0x1e34141c0d348fadL,0x0073fa0dad0eef45L } }, + /* 35 << 245 */ + { { 0x922ddb84d403f20fL,0xf7bccbb54681def7L,0x81a1200f6b580442L, + 0x64901025dc2f9884L,0x3746675aabe78edaL,0x3e750369aa6f005aL }, + { 0x140477ceeb00658fL,0xc76a320ccf89be62L,0x00761f21658c127fL, + 0x669186dfb8b6b03cL,0xbcdf1c36dcb26a2aL,0x94a7aba5da876a56L } }, + /* 36 << 245 */ + { { 0x1872f65c26163265L,0x9fbaf44fda52ad9cL,0xbec7addeeda47d38L, + 0x6a04dc3078094f9cL,0x2c73b8f15f4498e1L,0x504909efd4fcfcb4L }, + { 0x747efbc6b6b3a63bL,0x856e276de0dadd96L,0xa22459aaae3be3a4L, + 0x9ef59e732294a854L,0x0717d4e5d0e36205L,0x5a6afa3eb734cdf4L } }, + /* 37 << 245 */ + { { 0x6bd8fd330e938950L,0x8b26d7fa0f20c4f3L,0xd29a1121e0604d4eL, + 0x23d1cae60711c191L,0x460af39d51914cb2L,0x9cd04208547463c1L }, + { 0xeb80d70e493b7a0bL,0x182568869171652bL,0x9f3007ad76ca8b21L, + 0xf9bdeb4664ac10c4L,0xdaddd584284ae80cL,0x5c7ea28a0022abfbL } }, + /* 38 << 245 */ + { { 0xaef75aa7dc3c897eL,0x98bab5852e6432a8L,0x522b383d83fb0ee5L, + 0xe0d8620f056a8589L,0xd63525dd39352633L,0x74362bbfaeb985dbL }, + { 0x11419f4e8c0f17feL,0x3ca918b0494ba972L,0x39f2bc3c6e074e25L, + 0x3bb66618fbbf0d60L,0xee60c8f88579fecbL,0x916f3fe92a9b905fL } }, + /* 39 << 245 */ + { { 0x14ed31b6482b668dL,0x8e3e10db5b65978bL,0x72ff92eee8011bafL, + 0x5183d0bde1143531L,0xdb628188f9c740d1L,0xd23cb9c57570e3d2L }, + { 0x9e893cacd2745832L,0x49762940ef4a2b31L,0x02f6f892324361bfL, + 0x332e089dd7a881bfL,0xe9303153f788f52dL,0xcd6d15564e7f1bd7L } }, + /* 40 << 245 */ + { { 0x8caa623d408b62b7L,0xa58aa0b0c0272b41L,0x089af856ee285bfdL, + 0x77b461f6d0674ecdL,0xbaa9d9b38d6f6612L,0xa8f26e12590669f8L }, + { 0xb164340c5ebb5e28L,0xfdc11f7401ea89a8L,0x73c03b9176e4346eL, + 0x6a678eb17caad5fcL,0x103ff0790a87803dL,0x25d6fd2af7430a94L } }, + /* 41 << 245 */ + { { 0x72cc0aba66116d84L,0x642c88681039c0fcL,0xaeded9e6d96a7423L, + 0x4ff4163ccc5fea03L,0x180e4d3616483ec5L,0xefde910a7f6332c1L }, + { 0x8042696283367060L,0x4edce3e8c28af356L,0x2452e4de965139daL, + 0x15129fd9547477a1L,0x7f628b5ed80998cdL,0x7c56d44541054b54L } }, + /* 42 << 245 */ + { { 0x4c3f81184d3d9da9L,0x332072f9e1e71487L,0x8cbf7284759ef371L, + 0x3d13d85cb98ce007L,0x507b467f980f4fd5L,0x9853b98bc74fdfdaL }, + { 0x94b81534993f5e19L,0x316b761beeca71adL,0x09820a2331c04080L, + 0xc71a9bd4420e3114L,0x569f813822ea67ddL,0xe3ec5d2b3a41b079L } }, + /* 43 << 245 */ + { { 0x6085b24a19bb6f27L,0xc2f18e8f64dcb82dL,0x8ff89ed91fd3888dL, + 0x9fbe31db0e525a5bL,0xd52dfb5df0527573L,0x90288a3f703193c3L }, + { 0x87bb5d30bb1ce380L,0xb6c9a4c9f0dcf59aL,0xcbc52966aeb86e7aL, + 0xd151178a9a1636eeL,0x48342994e4b48c74L,0xe5bced925af80bc2L } }, + /* 44 << 245 */ + { { 0x106882534918179cL,0xdeb69dde08143b36L,0xfb3c527b992363faL, + 0x11d05e93e9393832L,0xe3249558383a0f59L,0x2d0f3e11c234ab5dL }, + { 0xd50a30d95c599ae7L,0x6d7abc6ce9f98316L,0x3d190629060ab6ddL, + 0xfd58473c81d69afcL,0x841193d24b782d62L,0x4f72696da771226bL } }, + /* 45 << 245 */ + { { 0x288895d056e467a5L,0x78166a95e025a5b3L,0x89df640e895835dfL, + 0xdc2b61f483dcbc50L,0xbeaa7363110dd6a0L,0x2346a2a5e7fdbe3fL }, + { 0x379ae5fb6947a9c4L,0x9dcf01956370a372L,0x34c3c6c3d70d9a24L, + 0x98ee14b7fe6a3d0aL,0xdd37708bba8ce5baL,0x785adb86a15c3672L } }, + /* 46 << 245 */ + { { 0x4c93de89c5ff194aL,0x56aef366fdc94109L,0xc8cb2a0c5b0b23d4L, + 0xd73f1cef587ada16L,0x7138315a364b1463L,0x43940ef59f6bd411L }, + { 0xad068e490f4a533fL,0xe8a772a33c7dac91L,0x74b815fc107998b8L, + 0x4b8fa9db92699ee7L,0xfb2de4bf4cbb023dL,0xe5833a390f67c29cL } }, + /* 47 << 245 */ + { { 0xe985acae7fc4fa91L,0x7730e38ec66c4282L,0x4b971449f4bda67dL, + 0x55261be02b001f47L,0xccde0c7126d0d8e6L,0xa7ac56fd701f6febL }, + { 0x2488b28552642a53L,0xeada397c58fcfabbL,0xa3fc0452b679b0e3L, + 0xd0ef09ffec2e921aL,0x9fcfd991575fb70aL,0xf4adcbbb366cb10dL } }, + /* 48 << 245 */ + { { 0x517075af5faa0cb7L,0x400a22c1efaf68f4L,0x320ce9493b86f639L, + 0x511565717f296bf4L,0x0919607a96108276L,0x4fcc39a02f035900L }, + { 0x5d13de7cefb73f3fL,0x19d725c5081c38e3L,0xf1b28089c0f58697L, + 0x2adcd1a30ca7ca20L,0x96c07f42c21e1be5L,0x94d28cacbaa0aba0L } }, + /* 49 << 245 */ + { { 0x0ff4983fd64cfa4bL,0x2c49c4918c55942cL,0x6093eb7f98eb20baL, + 0x1b33296a060497baL,0x32776a53c92d7b47L,0xf367e6b25241de3dL }, + { 0x711119813b65228eL,0x2e5dc541e1394451L,0x940a4a0f98ef33e5L, + 0x1a395be32cd4315dL,0x4d49469f3c2e20e1L,0x5384f4b95c314f95L } }, + /* 50 << 245 */ + { { 0xdda2f3a0a256813fL,0x4363d190ee6cbae0L,0x61f4d607930d0094L, + 0x6767ff4817021739L,0x8450091bd2c5fadbL,0x144d02fe870710a8L }, + { 0x73f45d9035524b7bL,0xccc7856b04615373L,0x0eb5cd436f081dfcL, + 0x9c433cbfe3a70d59L,0x9ee70f509818349aL,0x16de27347241c634L } }, + /* 51 << 245 */ + { { 0x02a24c5cc47f7db6L,0x519242cd33d60e1cL,0x543f39cf7244a636L, + 0x4ae15d698deb181eL,0xbaec81ef44261806L,0xe5cb18bb5fbf13abL }, + { 0x7534787a032158e7L,0x770e1e34da0d9a6aL,0x251bfa7158f9baccL, + 0x12663214c8d39905L,0xb7bfa81b39c3d64aL,0xd6d439ffe3ee296cL } }, + /* 52 << 245 */ + { { 0x192ecf72d0aa048fL,0x23af774063e40c0fL,0xe4d98e41d804d367L, + 0xd868cc885405bfc3L,0x96909a5b6f6ece88L,0x16b05ad2bae60dabL }, + { 0x7382a1dbde621949L,0x569bb6c9c47cf6dcL,0x892da43e1f2d098bL, + 0x6bd959b9bfa25649L,0x90617c419cb48f9eL,0x36059b73f110b22dL } }, + /* 53 << 245 */ + { { 0x1817b140791af82aL,0xf4a44cde042870c5L,0x60b8414ab5c0405aL, + 0x3b00f5ddf4dc4a9cL,0xa61aa0cfea81dd5bL,0xd43c37422554907dL }, + { 0x3fa264a620569ecdL,0x2cc69c2ba5a46190L,0xecd4f6d3dddd072eL, + 0x41083b72dda8de01L,0x4bc047f110d6f156L,0x7164b432cac3203aL } }, + /* 54 << 245 */ + { { 0x7e7e08f401d45bfeL,0x04f9c9ed0e2d17e2L,0x3213556fa55bc148L, + 0xc58983c734449f0eL,0x463217afaf2bb219L,0xe08a51a2f8fba72dL }, + { 0x2f44991e974d51f0L,0x15f2171f3f12af56L,0xbcc919de24cf01f3L, + 0x9ea371f269399bd0L,0xae8a8eca3ccf4574L,0xf0535b83ae499429L } }, + /* 55 << 245 */ + { { 0xe9ad8928f72305e3L,0x4144b6b9fce1295cL,0x672732a0c3487eb9L, + 0xf19d09a6147f70b8L,0xf45f6a11362a7684L,0x84ce4f25adfbbdadL }, + { 0x31e4bb0ac3403b48L,0xefc861b9b478ab38L,0x3323df44a8320c49L, + 0xa2838aa1ed4f14abL,0xc80e30cc63bf7df7L,0xdd2d5ef9f15ec5ffL } }, + /* 56 << 245 */ + { { 0x3027c1698d6f8572L,0x89326850111e64d7L,0xe6eb6cd31b8b0179L, + 0x0d2d27ea6dd5a4a7L,0x41682c0007c82f11L,0x5a01c54c81075022L }, + { 0xf3903f51fe7220d0L,0x75daeaba1f8e66b2L,0x1b625eed470bd3b2L, + 0xa46398a7e85a6293L,0x8ff6ef8c805ad640L,0xb3430f6795bfa3a5L } }, + /* 57 << 245 */ + { { 0x55d31765bc9341b7L,0x6530526ba312d125L,0x57ad29c02e9eb238L, + 0x31658a8282292155L,0x4d3417b169301639L,0xb38d6199e48c3d1bL }, + { 0x4399d5ddcc5202eeL,0x4b1c293a5076cc08L,0xa46e87f5824171b0L, + 0x16f75919e4cb40e9L,0xd086562dac35d85bL,0xc2b41ad532713f5dL } }, + /* 58 << 245 */ + { { 0x2da6d2ca3248f02aL,0xae49d2fc675de73dL,0x4abb1a65cfbfee63L, + 0xc6cea22cf1246350L,0xdd510cf82d3faec5L,0x8b7d1b0865e7460bL }, + { 0xc5b39c802737b182L,0xeee61e0d8963c709L,0x9cf9da61793e7179L, + 0x630637e52a295ba6L,0x18b85c9fa3881ba2L,0xca091a9464a94fe2L } }, + /* 59 << 245 */ + { { 0xcb68739f0bdec121L,0xf4907b3cd3811dabL,0xcf1b079b8c5d7707L, + 0x9ef9002d2fc6a56bL,0xc4c9d069809e8b64L,0xaf86a3db90d0eef4L }, + { 0x30a52f994b24a04aL,0x03bcd7a958574ed0L,0x330ce8a1a5b52b8bL, + 0x632b3c2d5e6a8ed9L,0x7b080a2c18369382L,0x12173e5f65187ce1L } }, + /* 60 << 245 */ + { { 0x027f654feabe8ef1L,0xd9d327e481a51834L,0x9215df61980faa43L, + 0x76b4f8003ba045c1L,0x8f3ce587f400732cL,0x0abe1f34f133a3caL }, + { 0x2ec690526de4f504L,0xa297cee4cb7ff026L,0xa31a76e3cadaefe1L, + 0xb701391e1173a958L,0x0a4279b08c8768f1L,0xd58927c12f8ede03L } }, + /* 61 << 245 */ + { { 0x71ea38454e630b0aL,0x4f696b59119263abL,0x9e7cb293f9cbab69L, + 0xa448d591c60ea8d2L,0x5021d4ef7d89eb52L,0x1a1ea5e3787663b1L }, + { 0xa95af4eb05bedc8eL,0xfe72effcc2fba411L,0xa88b79bb19a2c6bdL, + 0xbed948fac84c78eeL,0x022dcf3d5ee7455eL,0x0c39c3689f56accbL } }, + /* 62 << 245 */ + { { 0xe0e818a8b77c9de2L,0x0dbaea885e07f77fL,0x6ece83b97b1f96f0L, + 0x3c02e59631733a5dL,0x44bcdfcdd14828ffL,0x2791ca54b66f6107L }, + { 0x1a051c5a6198f24dL,0x9cd5f09a17627301L,0x64323392004a0cb1L, + 0x75d6819b3cc13e05L,0xf5cab2874a58768cL,0xbe090e83e3ca9332L } }, + /* 63 << 245 */ + { { 0xd639e0f3ab9b278dL,0x57f3f8cafa2407b4L,0x6720549f6c11f6abL, + 0x6ad1c608e784308bL,0x62c31e4a196babbbL,0x764b4deed1d36447L }, + { 0xf44efcefaf4407bcL,0x7c1f45dbb3ca82a3L,0xf43e4a8773b952b3L, + 0x145cd2d6ff478bbeL,0x11ef2df450c8e708L,0xa2af06f044491734L } }, + /* 64 << 245 */ + { { 0x8cd6c9f7c90b13f5L,0xec0c187d52a9d469L,0x9c0db0f589b8ad2bL, + 0x692a8db70d9c999dL,0xa407fd03c9f84ab4L,0xa5742fd1cc9a906cL }, + { 0x4813a765c8e72867L,0x9c65943de2e9a10fL,0xca6bf2934fa0a23eL, + 0x1dfa3af7cb1f8d7aL,0x28036f5498d10c53L,0x7bfbcaf20e012c13L } }, + /* 0 << 252 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 252 */ + { { 0xa53f1a104ec177f6L,0x4a2ef9aa3faa5ca8L,0x30efed8532976d13L, + 0xcf5ada165ee692d1L,0x3ceda69d259e7cc1L,0x2aae29e99baab472L }, + { 0x7ee5baef737cc8bcL,0x1717af747fe68dedL,0x9e5c8ddacfdaff63L, + 0x575c8db9cec07693L,0x9afc8ae0fdfb509dL,0x27836d3685651697L } }, + /* 2 << 252 */ + { { 0xa7342f9517eb9264L,0x9264a6a00a8a6eefL,0x50e48bf07471c384L, + 0x729e5ab130827f34L,0x17199191ea779c23L,0xd13ab8539fa9fd58L }, + { 0x7d5799373b1d773eL,0x65f8e7c6d196c3dfL,0x253f7d51e8541725L, + 0x107a793dec720355L,0x1c14d0566aa16268L,0x9dc5fca38bbb231bL } }, + /* 3 << 252 */ + { { 0xf5689c5e12b09f53L,0xc1da32e19e87ff7dL,0x1af879d012eaa533L, + 0xdba775e6d9271e94L,0x60f8507310e63c34L,0x445f3e21a686a24bL }, + { 0xed5ca8fa15bc277eL,0x9839198a364ab7abL,0xe2ee39426d90a7d4L, + 0xe5b3e4cbccd37e76L,0x9013bd08f1412e0fL,0x82f5c532ce999048L } }, + /* 4 << 252 */ + { { 0x61d0e01bf3fe3441L,0x674e52332af47609L,0xd4a4e224b362902dL, + 0x45923c129e0a5d16L,0x4fc2bdd495e580e9L,0x6d1d974ca8c3d954L }, + { 0xaeff1135d0bbeaaaL,0x013ab5b31baafc9eL,0x80907d3eab8f9f31L, + 0xaf2c12166d566c15L,0x0082daba952e6fa7L,0xa46710032df9e03aL } }, + /* 5 << 252 */ + { { 0x91b379c63223d561L,0x8cb7b8cce203417cL,0xd0f44208176b3b81L, + 0xd18c2118aaba5cd3L,0x4aed5c9770794f9fL,0xfc540dc4f4c33894L }, + { 0xb8e6798a0153a8a8L,0x6537dcdf43c4b0c0L,0x1b7eef39ab557397L, + 0x175e3934b7103105L,0x943abf4a82ac89e4L,0xeb1a61f957ffcdb8L } }, + /* 6 << 252 */ + { { 0x99c2b4cd66476227L,0x576a4b0662850cd3L,0x067bb66b5a352b7aL, + 0x3c7d6fc43ec757edL,0x2f69291cb9d36adcL,0xc7c0f3257c9143a4L }, + { 0x768c3c400627fee2L,0xc214d81da8fde577L,0xd86e4b025299ea1aL, + 0xbe46b7e91a2d4005L,0xaf865a169317fa60L,0xfbc3268fcdce2fbeL } }, + /* 7 << 252 */ + { { 0x66fcba52d8fbe900L,0x9f16434c861b3e33L,0xa371b97241b4305fL, + 0xb2d858ce25b6af89L,0xbab07d53275f9e8cL,0x3b5951f8d525bef8L }, + { 0xebf79e3ca1755b0aL,0x4e6256e7b467b1c2L,0x7dbd8b66cba1a659L, + 0x88ea40138b1eb8b6L,0x210ac1b38fa6436aL,0xe93e22c23df40e33L } }, + /* 8 << 252 */ + { { 0x5f79f0df1fd64063L,0xd2d39dd381e118ecL,0xd631a68e11571c5bL, + 0x6d072b4e2474faf7L,0x5e043a6d862a924aL,0xcae58bd8b0fc8d7aL }, + { 0xf54bb7f3b1351f28L,0x4588b6280413275eL,0x81459f4c5909ec04L, + 0xd28cda25abd16460L,0xbb676d018db1c69eL,0xc0056e2dac5036f4L } }, + /* 9 << 252 */ + { { 0x1ce187bf323169baL,0x1dfaef8661ab5073L,0x1893dc7b2ae468b5L, + 0x0748ec86123848d4L,0x0d2877b46a96eb12L,0xb6063e75e9322495L }, + { 0x1cb17189d7d1828fL,0xde41f11944d1b318L,0x7ce0f87610f0b74dL, + 0x2c7c91ee7a98f86bL,0xb641418e750f3ea1L,0xae2cd2e280094054L } }, + /* 10 << 252 */ + { { 0x9f6c6ed598d8e086L,0xa9ad63ca2d3fad85L,0x055b8323fe016926L, + 0x039fbe287b3a8d68L,0x544a8bf5fb6b315aL,0x04b122fb647fed85L }, + { 0x1e9807fa98085b1aL,0xb78a36a771c12696L,0x4ccc1a2cdc22f95bL, + 0x6ff4997d54d1e818L,0xecb5bdc2f08c22dcL,0x6e07e2c146a27762L } }, + /* 11 << 252 */ + { { 0x602077aceaaec565L,0x9dacf68224568aeeL,0xa490fc1e9cfcce26L, + 0xb2ac94b3303218baL,0xc0208604ab33f9aeL,0x801663b6e39a6668L }, + { 0x1defbb42961b0927L,0x688b445e83e318b3L,0x34fe2830c11648e8L, + 0xed56e99360066dfaL,0xa5f30f9a07671eccL,0x02c40260a3222e8dL } }, + /* 12 << 252 */ + { { 0xfb2a11b4ea347db9L,0x2360667e03350681L,0x1aa6e720a02a1261L, + 0xac2bd2eba110bb21L,0x8ab2f9063c9b4568L,0x5f46263d5ace1f17L }, + { 0x97067801eae704c8L,0x35d2637ea715d313L,0x24cdc3d0c77573daL, + 0x6f97cd07e2562b2aL,0x27bcd62d5afb29e4L,0xc38ac1c55d29f5d3L } }, + /* 13 << 252 */ + { { 0xd9c38ba47c88f46aL,0xdd07c4d79946ebe4L,0x908731dcce0e5417L, + 0x43088d11e145839bL,0x9d37419d07b61543L,0x440cdbcd2c3c7c4cL }, + { 0xa6a6fed673216db4L,0x15ce171a198cd32bL,0x198c256974e6a085L, + 0x5fec853f3dc2a714L,0x329250bdd5923068L,0x1d82373c9f6195caL } }, + /* 14 << 252 */ + { { 0xa8e17be53777b2aeL,0x534e3a3bcc284224L,0x7f34ce458192cfa1L, + 0x0009a72966d0e03aL,0xc42053ba524ce1fcL,0x834e98fe6d092e58L }, + { 0x400c65a1c8b0f751L,0x268bfe6f107965ebL,0x0f141c0332e0bc69L, + 0x33bc6e64597a2264L,0x039a4ae9454a0d6bL,0x2cb0bf550b07ddaaL } }, + /* 15 << 252 */ + { { 0x69056cbe63769bb3L,0x710a67d385044d35L,0x971ccbdeea855332L, + 0xd655163a0fd0d210L,0x619c3f9adbb8a8b9L,0xd156f73d49a014e2L }, + { 0xd04ea0a5a129a598L,0xc9c04da6fa2f12eaL,0xc0ed654ae98b3187L, + 0xa254eef6a82f9ec4L,0xe537695fa386a72fL,0x170f1ed4a74eb453L } }, + /* 16 << 252 */ + { { 0xdbe04c3044ce3ad8L,0x995fbb1b4ce8aad5L,0xdbf8b54670911457L, + 0x9e683b5b3f7a1757L,0x7b89a08a9c7bd62cL,0x448865a40b3fc97eL }, + { 0x0ac9abfc3bb01e94L,0xa07760421e756124L,0x0aa6c335d9deed97L, + 0xe270580f72603e08L,0x70857a946c783bb2L,0xa0047774caa929aeL } }, + /* 17 << 252 */ + { { 0xf99a63c5e8c4a440L,0xc7fd1d1419d65168L,0xfb6c21d696d5e80bL, + 0xa4a7304944b833beL,0x093728d5127b1599L,0x9046cbe2c89e7195L }, + { 0x21e2863c146a80d3L,0xb1ac7e1bdd559c13L,0xbe5ba65c72c39063L, + 0x7da5feb87722cbc7L,0x122615d0f17c02c5L,0xd44f477179e5fcb6L } }, + /* 18 << 252 */ + { { 0x0d913830e2d28da9L,0x0465920a8a164385L,0x79959ce1b0ad65d5L, + 0x6c94690759a966d6L,0x4ccb0e5e832c24feL,0xa8c5bee5d6af2a10L }, + { 0x264dcc118c5791fdL,0x719f23ac5b58ce85L,0xfbff8a2f8e54b029L, + 0x0c9240be864e959cL,0x8f7c21733c37c665L,0xfda848d9f164d354L } }, + /* 19 << 252 */ + { { 0x203ea731f35d11f6L,0x90610383f9f9001bL,0xb9d3c302ed97e6f2L, + 0x4c529736c9a67e6cL,0x2e440b1781f6597dL,0xcc798f5616aabf20L }, + { 0x490f50642832ffc5L,0x585e462a7a19b125L,0x99d73e391b06d98bL, + 0xb817e97aab696d7bL,0x9df2f65ac28dffeaL,0xa48dad47045fddd7L } }, + /* 20 << 252 */ + { { 0x2878c20d62e5fc09L,0x419ed2ece7f012abL,0x3bbc853fbaa21e7eL, + 0x412bc3c54844c009L,0xc4b150508b012199L,0x9d160f4c310d5fbfL }, + { 0xcb61b69214f60becL,0x436348c064092943L,0xce8c136e3185cde0L, + 0x97b034f68be5dd85L,0x7697adf92701631aL,0x2ddd86361fa6e8a0L } }, + /* 21 << 252 */ + { { 0xde8c2c963e9ff7faL,0xfdf1e25d8b75bbeaL,0x28ba3be59c146264L, + 0xfc1df52e81fcb0c9L,0xf9341c43af3ba66aL,0xe81c22470d72188eL }, + { 0x2ff00f1069c62b9dL,0x1077962e71498d24L,0xdf35b17ecc34ece7L, + 0x3516c33687eab2daL,0xe71cf7ddc72b7911L,0x6c9233d92c286c56L } }, + /* 22 << 252 */ + { { 0x7ce6389d162754d7L,0x8f03eff514e0d8e5L,0x9fd2c896ef402e31L, + 0x4a4bf70a2195b0e6L,0xe6043a383c8d82dcL,0xd86b647e8bed7c65L }, + { 0x21bc56f4a4c87660L,0x8c99d6270c05564cL,0xd6b82e9014050ee2L, + 0x09bf6a3eb6b11f0bL,0x9704b36731dcd6b1L,0x871c85c85e3d44caL } }, + /* 23 << 252 */ + { { 0x93024430e5236badL,0x4c5872728b883d1aL,0xc265b94bba68d3bbL, + 0x7d8fc82a648d9b7eL,0x57086e6e75ac264cL,0x4b8a157102fc9ec8L }, + { 0x83ae238e86849a9bL,0x2eaad9b8a69acccfL,0x2d82c029d44eaa39L, + 0x8f5b9ed833d7a556L,0x05c83328eea8b609L,0x537069efc3c96005L } }, + /* 24 << 252 */ + { { 0x292f8874b25c4d4aL,0x54961fd87e79f526L,0x949a1fae008c6ec9L, + 0x6ae82f0d525524fdL,0xd1f6f4ef2edbcb1aL,0x41617a6d977ddffbL }, + { 0x6ae38fb71baf0668L,0xa79ea228d538ab3cL,0x70babb05fc44e273L, + 0x247384fbbca85910L,0xdc0e069b6a564959L,0x37a9c5521a7438adL } }, + /* 25 << 252 */ + { { 0xaf2c87828a4b7251L,0xcb5ebfd3c1bc7f72L,0x160b77e560579615L, + 0x297412e3c10f067cL,0x5ad0681ef7df86c8L,0x2e8c63529b3e3afbL }, + { 0x32372cc74cfd3266L,0xb7abc8baa820f8b5L,0x857d545519f34baeL, + 0x5c055ce920ed65beL,0x1d8a59ca537ad6b7L,0x1135adcf7ad88633L } }, + /* 26 << 252 */ + { { 0x47e6ed9530034df1L,0x1839f488321bed8dL,0xb6b67d452ac8a9f9L, + 0x2fe1efc6182e4a63L,0x2da34bde0c1185c7L,0x6e5d1621edfdf9aeL }, + { 0x3bae9db77120804cL,0xf094b0676d986ef3L,0x029c9246853e24ceL, + 0x3abacb1b25a82463L,0x58777e1389c5616aL,0xaedd003b5aeed714L } }, + /* 27 << 252 */ + { { 0x7494e4319da5fb0dL,0xc684d74bee3fd6f3L,0x12fc899403a87d91L, + 0xc4c55e692d6e3931L,0x63e1255896336788L,0x36c297a5f78371fdL }, + { 0x4cd3f9c4a63b313eL,0xd2825e17c543e507L,0xd37e36d06a4e64d0L, + 0xab9559ec11872774L,0xaf168b34880a5d00L,0xb0c916a10c0c3f42L } }, + /* 28 << 252 */ + { { 0xd389397c834eaa9fL,0x2271ea0d2a5532aeL,0x5e59a23ae1f92e9eL, + 0x9f179b8c1f7b91f5L,0x2a1c10028de2dc8bL,0x6ac83e58787a276dL }, + { 0x0facd4756d9d1571L,0xcceaae5e4bf118e2L,0x4e8008b7620fbecbL, + 0xff633fef7a1474cbL,0xfbefea80ce377357L,0xebb9a9460feb7724L } }, + /* 29 << 252 */ + { { 0x0bab441ae9803b71L,0x309ef14684e2e21eL,0x17ccd5b6851b6519L, + 0x8b5e7e300126f470L,0x0560cb9d847eca03L,0xc45850bf11ade256L }, + { 0x08603f5c3c33dbbdL,0x21887bc9708ae545L,0x3bd25ad480014ffcL, + 0x5eb0f89fd3a64409L,0xbca2726b4c3dd83dL,0x611afd2fe4259797L } }, + /* 30 << 252 */ + { { 0xd9cb4233c4f4e0e5L,0xcfc0576818e49029L,0x8e9c8360526f05a1L, + 0x8e83037aa56d6c3dL,0x33507065c47e6742L,0x5ca2c8d8788b5da3L }, + { 0xf355cee9cfb0b6feL,0x0e86fd73973ddafdL,0x27fc6c56d44fd889L, + 0xc9ab416ff7d93f3cL,0x778c3f160d063d62L,0x175e5d920b5085ddL } }, + /* 31 << 252 */ + { { 0xd62406873be63d8cL,0xe8c93b93b80059a6L,0x33bba7dfe065854fL, + 0xcb26543f36b34e45L,0xc17ee58dd2d0c3d5L,0x69752f49bae1bcadL }, + { 0x87e31b429b20106aL,0xc520424b06734eb5L,0x993240afa896d17eL, + 0x5238851bc2762a62L,0xce399f9d506d7dbfL,0xa4822d23040cc7d4L } }, + /* 32 << 252 */ + { { 0xf071c9878fa06859L,0x0083e5311a52390bL,0x845eb12a61483bc2L, + 0x17471d801caf6dd6L,0x7b603616ddc21b92L,0xd38fe0f6b992536dL }, + { 0x433f0652297c25a4L,0x03d4d8fcb1c4bf41L,0xdf617386a9adf49bL, + 0x4bfeb3992cb2944fL,0xbf288427b3d9c076L,0x17818c3e965b4576L } }, + /* 33 << 252 */ + { { 0xfbcff79f6df360c9L,0x342f9ded2bd94c22L,0x2dc5f999283f2300L, + 0xbea18d9893cc3330L,0xc197176269a7da4eL,0x72de17ee93ce69a3L }, + { 0x6c354a6184170a91L,0x031ce0debe47ef92L,0xbf256fd418658739L, + 0x0395088a0d037d9aL,0x61179c42c5a05970L,0x0d5a9f7db8b6ab64L } }, + /* 34 << 252 */ + { { 0x18be1d605a44a8dcL,0xb512d945f1d18ee0L,0xd2e1f6623af39ec0L, + 0x440469136c223676L,0xe7a860836a60a4d8L,0xaefcfc2dc7e09d3bL }, + { 0x175817fad685c9b7L,0xe20b6c9e4b9d0557L,0x9212e7bb51fe560dL, + 0x748aafb7608b53c4L,0x86186d4fd9b06850L,0x4cc6041376512c08L } }, + /* 35 << 252 */ + { { 0x2d5be3b00c127e46L,0x8c6f38fad9b04e47L,0x49c444098736f31bL, + 0x5469ae47f53aa908L,0xd84856f3492fd120L,0xd04b1fa20725e199L }, + { 0x50c2e80a8e7056f2L,0x415db04c9ba2e259L,0x8e4c56ae2eb201e0L, + 0x449e4d9e5082ce94L,0xb5ff077a7345459dL,0x96d10f1e07330e72L } }, + /* 36 << 252 */ + { { 0xac77126e3b3094b7L,0x7c1e7673bdcb616fL,0x90491f8176993114L, + 0xf17c08a8cc8da63bL,0x972a3bffaa050364L,0xdef45b7f65a9cd57L }, + { 0x105ec5ba2b9b889eL,0x7066821150f7a61eL,0x11daa9dbb1d63a40L, + 0x6065451007790568L,0xfaa219cebc2b6d2aL,0xb1b8ace93e5163dcL } }, + /* 37 << 252 */ + { { 0xf8042ae2859b0f22L,0xd8a5d3a200d8bb8cL,0xe85c596189faae14L, + 0xb7d636f906611c0aL,0x35b68bbdd2bc8957L,0xc86f5be5b7cf558cL }, + { 0xb602a00369c17e74L,0xc39479cfd8a1fc01L,0x6dca5c81f733237eL, + 0x9c8cefd41b2e2cccL,0x2e32a323caacb4b8L,0xf7406874ad639090L } }, + /* 38 << 252 */ + { { 0xea3a358e24c1bbfdL,0xfd32af33571400aaL,0x2ec3d44da413949aL, + 0xa0d8594a7bd121f8L,0xb32997a1d6b6153fL,0xa0f48d98b9469c6eL }, + { 0x236b7a18fba15481L,0x49dee3bd98ff970fL,0xbc27ac7a7ee97875L, + 0xd1acf2be28ac6279L,0x92e7ef02514c8328L,0xb2d7a8304f48b497L } }, + /* 39 << 252 */ + { { 0xcaad0554d95946a9L,0x992268c973ed1281L,0x6c0b1edf7b1b25e1L, + 0x4de2d9f81d6e73dbL,0xe12a4f1c5a2950a9L,0xe0cdf7af36ac18fdL }, + { 0x16e7332d1abcc9f5L,0x4dccc1505bac1c75L,0x1b48bbc141f8c231L, + 0x3702cc2693692a4aL,0x9e9e53dd311c5dabL,0x27bc006cfe5d9fd3L } }, + /* 40 << 252 */ + { { 0x2bb798ff689f43efL,0x5813e4415f26ec54L,0x51f64c495005c929L, + 0x60e213a54b42e417L,0xc152844262cc3734L,0x6ecd6c3b09d994e1L }, + { 0xa6e72f7183dd047fL,0x3836f663b0019803L,0xbcf1265b257493cbL, + 0x59b15ff09e62d78bL,0xaac5ed5b6cb92ecfL,0x37e6ad7d9662651cL } }, + /* 41 << 252 */ + { { 0x04743bf8b224f6c9L,0xec04b641ae33b1caL,0x6301f51623a76fccL, + 0xf1aa954675e15fe9L,0x878c64ecd95c1972L,0x033df5ee3ba7578aL }, + { 0xe5e9ff7c47f4721fL,0x9b3d93fa03eef7e9L,0xcd0be6ad573deaa6L, + 0xf377570f3bbc8a16L,0xffdc04c161c37393L,0xd9eee46dd26d659dL } }, + /* 42 << 252 */ + { { 0x33f933604d4b7317L,0xee44b3e02fe482ebL,0x5a96870480f1fde5L, + 0xdfd6293b5510952fL,0x2abdc1989cc0af6aL,0xe608e2769ff45aedL }, + { 0xf408670e3247e796L,0x3144153535fe07c4L,0xa941f96e2870053dL, + 0xbe908795ef6383adL,0x82b620a63560fdf0L,0x2c1cc1ae135de5c8L } }, + /* 43 << 252 */ + { { 0xa829397c727e5988L,0x305659bac6239b1bL,0x9b13701200392cb0L, + 0x4eb1ddf376091862L,0x68b64b19202bdd8aL,0x56c427c5228071e4L }, + { 0x354b1beac3375accL,0x94a45b4e54e1194bL,0xf528df0178095edbL, + 0x6fb0867146fb9ec8L,0x977efc84c555bd48L,0x8230d6f7c268a20dL } }, + /* 44 << 252 */ + { { 0x003d4004b8d81c0bL,0xd3d5048f4168a407L,0x7748ecacc6675bd9L, + 0x9dba4539e2612cf4L,0xa5ebbccfd8770b8fL,0x206b4a9aadd90558L }, + { 0xe446ed9c81b5c103L,0xcd2434184d2199dcL,0x0840f6eacb0d70d5L, + 0x6fbbf1b43107367bL,0xde9444f7d29335c8L,0x33ef004c66252eb6L } }, + /* 45 << 252 */ + { { 0x10eac97aa5a6546aL,0x6129392fe231f95cL,0xfd41bda100e2aae3L, + 0x5b1f93299d8c6288L,0xf1d2fc9246b7df40L,0xbc6fbacfc5df62bbL }, + { 0x64885d924b5af011L,0xe4f3ade883461896L,0x644ce7a7a4a62e43L, + 0x74c9d145337b2730L,0x69d714840f83222aL,0xbfbc594ec27c0fdbL } }, + /* 46 << 252 */ + { { 0x3263c0517ed92916L,0xc039b94884e3f519L,0x54aa433ede89de6dL, + 0x92f76292c0971a03L,0x8457b2312550a2e8L,0x46ab1f0f11cfcd9aL }, + { 0xd97b95c1c6d53077L,0xe8db11d159550599L,0x2092c81385ea4b32L, + 0x149b6b2cb7ced408L,0x2ada6fa482b9b22fL,0x53a5576a25877963L } }, + /* 47 << 252 */ + { { 0xa1e2c2a8195ad455L,0x65e90a3de7f61038L,0xb01eaa52ec623680L, + 0xfad0f9f110302efaL,0x9e544b5449274409L,0xfc9037de8c3a0925L }, + { 0xbcf196fcfd139cdaL,0x0a1f747c4f6a2cdcL,0x580a9abab879fe3eL, + 0x08a20f1c5ee74778L,0x7c9be7de464c5271L,0xa4a1972918e85a09L } }, + /* 48 << 252 */ + { { 0xce23a19aa17e560cL,0x6491b95f62550e2bL,0xc72000121d15a005L, + 0x15fde735f4355a1fL,0x3849761f607f7807L,0xcbe322d018204691L }, + { 0x75756e4ea95e8e91L,0x365959fe817a9b8eL,0x631232763d4ce3dcL, + 0xa769d2fef1d66e00L,0x8624ddbac28829e6L,0x03274297d2df06efL } }, + /* 49 << 252 */ + { { 0x2ad21bdadf3b1368L,0xf4f9d5270b3001abL,0x10182c5557ecb528L, + 0xe00db71565372a5bL,0x2018e0ed74f2bd83L,0xa11b47066175efb4L }, + { 0x3172264722d565cfL,0xb20c27ab2f0faac9L,0x4ca2982a6260f995L, + 0x3850ef89b7085c6fL,0x5b4a6e235f0d45a3L,0xde562df9b7523682L } }, + /* 50 << 252 */ + { { 0xb34ecab233bb63f6L,0xe6cd56a202944c4cL,0x2690cc39489a8d88L, + 0xcdfe368a4fe612dbL,0x23069ca5e9e9f7adL,0x7b87105cc07d742bL }, + { 0x5114645a8b58ea8eL,0xd31fb4821829e8aeL,0x5e235d95c4b28520L, + 0x2a1cda885c2292d2L,0x95d77447ee925b6aL,0xeec419a3df18845dL } }, + /* 51 << 252 */ + { { 0xb8903f10be9ffa75L,0x8bf7fc786432dcc3L,0xcf3f7cf15d028549L, + 0x7684baf29846f2d9L,0x4c580edbe9e063deL,0x0ac5c3edf2d70321L }, + { 0xb9ba10e184c5d96dL,0xbb854b39d7aaabafL,0xe29d66964793c87aL, + 0x7b0fe1d448285ae5L,0xa143454df0121733L,0xa286eb043aa5ddc8L } }, + /* 52 << 252 */ + { { 0x8e4dcfc88c93bc5fL,0x9f96d60a1b233295L,0xae5262e91d447dcbL, + 0xafe58396541d46c4L,0x3e733c2636ff8f80L,0xcb36a37748b81037L }, + { 0x9bcbfa9fc406ef17L,0x57a6e28006fb128aL,0xd86b44db9a771eb1L, + 0xc7ce106e62545a4dL,0xec6818a6b254c908L,0x4b8d3fc550feb342L } }, + /* 53 << 252 */ + { { 0x8faa39c8b609ef4cL,0x0209b3a7d8225cceL,0x11254c211feffc0fL, + 0x64930dcdc1e42ad3L,0xf5b058eb1cbb39fcL,0x2f870e3341cb5065L }, + { 0x61b3611cf7663f95L,0x981890b637941996L,0x00c42b0908dd6854L, + 0xac42af5de17da075L,0xaf3a394c282b8d53L,0xb53b3b245d8bab96L } }, + /* 54 << 252 */ + { { 0xe17c9d98d90f0c83L,0xdd4aa8ac6d984408L,0x94b6fc50f71aef46L, + 0x2e6b5d24f0a2009eL,0xcb9d9cd17d8d75e4L,0x5e732a5b962a1708L }, + { 0x9d774f1c7fd01089L,0x56bc35aded95094bL,0x6844220bb9c797d4L, + 0x40021d8e90ace48fL,0xddc769c5701baad0L,0xe23e8f9e333ac2deL } }, + /* 55 << 252 */ + { { 0x6cf6faf6e92e42bdL,0x759dc78b0d1e6a0eL,0x18fd55ff11532759L, + 0x04a306d7e9af0c07L,0xd7febf615ef7f82eL,0xaa04f1dca65cae01L }, + { 0xb084407c16442bc2L,0x17ab4f74f874f10aL,0x236368d40fb6cea7L, + 0x451ea8206f66813dL,0x4a61097b1760e6ecL,0xa8655cfba01bdd2aL } }, + /* 56 << 252 */ + { { 0x52fced3116f01d7bL,0x88c6b172daf046aaL,0x1a189403fe7a338eL, + 0x39741ecd61798b1eL,0x6a47b0712934b879L,0x3b1a5dd1828d1e9dL }, + { 0xd4bd48487f35a7efL,0x71774b5bc1eebaf8L,0xa86471e5d55344baL, + 0xfbf145f17b8a483aL,0x70f9b214aa53802cL,0x995af93010b066e1L } }, + /* 57 << 252 */ + { { 0xd2714b97aadf25ceL,0xb95c54162a7643f1L,0xae7dc619ba2f1939L, + 0x30e5d013b0db537eL,0xfcd1a456753f0813L,0x19f7117cef62925cL }, + { 0x40a22e35423d3c56L,0xb0271e9926a5534dL,0xc19f703cc76c9a1eL, + 0x9b8fe585560bee08L,0x48c7797d3cc772aeL,0xabd2148e10bd6393L } }, + /* 58 << 252 */ + { { 0x046fb36cc34a7ba2L,0xd42e56d42a61a8a6L,0x16b8fd2d3d4b1184L, + 0x6f9e85a26da29888L,0x1ff7324bdd683c49L,0xdb3746db27bb8e2aL }, + { 0xa7e586e684be7f99L,0xfbd0c0ee61740d6bL,0xb80509bab2071320L, + 0xb5bf09fea3f03641L,0xe872cd854971e39fL,0x9bed91c0ce2b2db2L } }, + /* 59 << 252 */ + { { 0x85177e7ca6bad7b2L,0xd5b1f0901425b611L,0x6b5f16223c4bfa24L, + 0xde34a692def66d8aL,0x96c0663ee8a1b7a0L,0x43eb91ed459c8bbbL }, + { 0x6cc7e78b7d3d8b92L,0x3c9da7efe0338ba8L,0x18d7ab00e21360b4L, + 0x0785ca897f9df01aL,0x5bcfb8302220f1efL,0x8c61a3bfa52bbf42L } }, + /* 60 << 252 */ + { { 0x4dcc3b82196c21d2L,0xef0e0e1e61071fd8L,0xa2a28c3b35a013f7L, + 0x7550d3d7f6b58f80L,0x0f1fc9d58101742bL,0x027874f055982d5dL }, + { 0x5a10b98c629bc409L,0xa28a1b2baf494679L,0x84afdbe1b96578d8L, + 0x201a8062d427238bL,0xe321ee2d89fffdb0L,0x0b304de4fb89f171L } }, + /* 61 << 252 */ + { { 0x5d8e16c0d7700dfdL,0x336e30fa24260211L,0x7ba72067ad557ce2L, + 0xcb388c3169621e0dL,0xcf6b7d813dbf7ba3L,0x7bfe43a91cbd216aL }, + { 0x6c40516adcffe0b5L,0xe77507f083b7ea33L,0x5b5cda074ba1fc8eL, + 0x46860dd296c6d2c6L,0x4716114f0eb5013cL,0x05bd136898c3642cL } }, + /* 62 << 252 */ + { { 0x7fac263852ca5d3bL,0x35e5d8d0f5a2a596L,0x4c7129210011a394L, + 0x400168f7a9c417e0L,0x220994b447b77b44L,0x01a7580af548c0adL }, + { 0x59870c2afe292ad7L,0xdda35a1a2abf8e7cL,0xa3082dc4f16d0c7cL, + 0xd4dcd5f38557c9e8L,0x38d45cc6ba7f0f99L,0xdefc0b1da7c18157L } }, + /* 63 << 252 */ + { { 0x5db2ed891c43e426L,0xeed247709adf4a50L,0x0b5e19765c8b90e1L, + 0xe9db695ffa18542dL,0xc16d3bfb8d043dc5L,0x5c5feb44f11d3430L }, + { 0xd44e3d57365593c0L,0x1338f26c8796edb5L,0x789b325e051ca644L, + 0xaa93b75d1579c2bbL,0xa39a8ec57842c0b2L,0x84225134550ddf11L } }, + /* 64 << 252 */ + { { 0x9ec1159727a28f9dL,0x96f2c44bb847cd83L,0xacf794e131fca111L, + 0x438b917896076f45L,0xad71035b51732588L,0x2db32f32a5d910daL }, + { 0xefaad0e8fe1cc184L,0x6f0360b52e00bbedL,0x99402426474ce326L, + 0xd53b687a2aa270daL,0x96c8bb78d78fa6ebL,0xd07f3bba6e699411L } }, + /* 0 << 259 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 259 */ + { { 0xfe1f11ad389283baL,0xc87e20b60cd91b22L,0x99d0015a3c5babf8L, + 0x7e795b4d5929ea0aL,0xc9cf68331dfb7b7eL,0xc1c07346a64992e8L }, + { 0x0b7e0dd89889746dL,0xa89d7b461c43ea4aL,0x64023cf034f02b96L, + 0xf7dd410a5662f0c8L,0xa3bb6088a1058ccaL,0xedb25dc34e7801edL } }, + /* 2 << 259 */ + { { 0x140a0f9fdd93d50aL,0x4799ffde83b7abacL,0x78ff7c2304a1f742L, + 0xc0568f51195ba34eL,0xe97183603b7f78b4L,0x9cfd1ff1f9efaa53L }, + { 0xe924d2c5bb06022eL,0x9987fa86faa2af6dL,0x4b12e73f6ee37e0fL, + 0x1836fdfa5e5a1ddeL,0x7f1b92259dcd6416L,0xcb2c1b4d677544d8L } }, + /* 3 << 259 */ + { { 0xb6f8d615a033cccdL,0x6aabb87cad75e31fL,0x30a03029a4646d1bL, + 0xfad497e6e6547805L,0x4b9d45c3ba291f12L,0x0f74909bca059918L }, + { 0xdece1fb0b5a181b7L,0x973f74413be1f21bL,0xcc919af36b06839aL, + 0x14427886ad57101fL,0xc63a79882bbc8022L,0x04cf807426742ccaL } }, + /* 4 << 259 */ + { { 0x279fd119da1c29abL,0xbd0688022b30d40cL,0xd8f57da4da44105dL, + 0xb1814b7a28223fe1L,0xcf2fd241e06f2d2eL,0x99003a0201dfde06L }, + { 0x876a31affded7e4bL,0x1efaf8272f725094L,0x5117d608493a6a0aL, + 0xdcec8088a88c03e7L,0xeae1d352ea916897L,0x8cdc28106e8b2c57L } }, + /* 5 << 259 */ + { { 0x52fb8e6f7041b903L,0xd7fc4b5b2ad368a3L,0xf16c61d2f890136fL, + 0xeee859dfbb52a90bL,0x1651b16b3f8396cdL,0xfbced93eb6462918L }, + { 0x1cb3126c4b6bfaa0L,0x65dfc76cc7c8fd16L,0x225b9c21bb46a3c9L, + 0x6c3457577f64f9ffL,0x6f65fadd57c297ecL,0x72a630eae5c5bbbdL } }, + /* 6 << 259 */ + { { 0x0254486d9c213d95L,0x68a9db56cb2f6e94L,0xfb5858ba000f5491L, + 0x1315bdd934009fb6L,0xb18a8e0ac42bde30L,0xfdcf93d1f1070358L }, + { 0xbeb1db753022937eL,0x9b9eca7acac20db4L,0x152214d4e4122b20L, + 0xd3e673f2aabccc7bL,0x94c50f64aed07571L,0xd767059ae66b4f17L } }, + /* 7 << 259 */ + { { 0x25cb1f44f4fefeeeL,0xe1a6b6c8bce660c7L,0xd25459a00d2118e4L, + 0x716532dafedf8f98L,0xaeff37d492cfb480L,0x45919f7da1453c41L }, + { 0x5100afe08d8836a6L,0x2ec20fd7b35d4fe0L,0xce8eefd1c00b7d66L, + 0x922d535d6b82c7ccL,0x5eb38f3fddd8d80aL,0x7eae5305213ae465L } }, + /* 8 << 259 */ + { { 0x09f8bb0654e93c1eL,0xb0045884ad81e27cL,0x26ebc7b6076e13ebL, + 0xbda0b5535d5ac07fL,0xbcb8132248ab69e6L,0xd3847d2e1c0f21faL }, + { 0x7a466528c834d740L,0x6c67a79ae0823ff2L,0x85dd11864c1d7cb8L, + 0x096f849f2d081301L,0xb4f503dd8a5ea0f0L,0x71ee0889d1bf69b2L } }, + /* 9 << 259 */ + { { 0xd7a5f9feaa074b9eL,0xbeda44032fd2468bL,0xca3956309c35ffcaL, + 0xb02a1f592de68348L,0x946b0250903b35c7L,0xe9984f24634e9c91L }, + { 0x4f70d22fe7303041L,0xf8a05d7fb68b0051L,0x0ce7af4fab5006afL, + 0x1011d1644a6bb502L,0xdf959199da4ad1a6L,0xc468cddf1e146f24L } }, + /* 10 << 259 */ + { { 0x40336b12dcd6d14bL,0xf6bcff5de3b4919cL,0xc337048d9c841f0cL, + 0x4ce6d0251d617f50L,0x00fef2198117d379L,0x18b7c4e9f95be243L }, + { 0x98de119e38df08ffL,0xdfd803bd8d772d20L,0x94125b720f9678bdL, + 0xfc5b57cd334ace30L,0x09486527b7e86e04L,0xfe9f8bcc6e552039L } }, + /* 11 << 259 */ + { { 0xffd4fd775b5c7501L,0xc43e409ee0600e93L,0xd2a18cba7d522993L, + 0xbc2e14dc17c84d1cL,0xe84deb43c1eee29dL,0xe65326f08d691cbfL }, + { 0x89760cdd77b726afL,0xb91c302a577b30acL,0xc6a742906e145891L, + 0x95bf3e913be85cc7L,0x2ec0285b9815e0edL,0x5b4be6da8aa3ec95L } }, + /* 12 << 259 */ + { { 0x4ab7a22c02a2d1e6L,0x967e19a31371d5a4L,0x20f59f95078de336L, + 0xfd28fa36f7869245L,0x1de42581cbf1d96fL,0x2e0127d7366e1f0fL }, + { 0xbc65fa9d2258c741L,0x1f2f3356dd6d65f8L,0x06384f3a4a0822a9L, + 0x1c81332bfd05a0aaL,0xbfb12361d95ee3ceL,0x180aaf0642016d00L } }, + /* 13 << 259 */ + { { 0x329ff57bf08c171eL,0x6cd8122a543af2a9L,0x5209a3d65b2f8d96L, + 0x0285b128ba90c881L,0xeb5971ef61b43c8fL,0xf1ec473ccfd759b8L }, + { 0xd2a79fb712d58e1eL,0x695f4877fdb6497bL,0x8bf5a4251f1a0f24L, + 0x3e79a0dea5c8a189L,0x9c8ada35908b7ae3L,0xd8b8622c5000f772L } }, + /* 14 << 259 */ + { { 0x3b75c45bd6f5a10eL,0xfd4680f4c1c35f38L,0x5450227df8e0a113L, + 0x5e69f1ae73ddba24L,0x2007b80e57f24645L,0xc63695dc3d159741L }, + { 0xcbe54d294530f623L,0x986ad5732869586bL,0xe19f70594cc39f73L, + 0x80f00ab32b1b8da9L,0xb765aaf973f68d26L,0xbc79a394e993f829L } }, + /* 15 << 259 */ + { { 0xdd01a72b6024f09fL,0x192c8254378d12e1L,0x03ec536bf5d8b8d0L, + 0xb0c4c01873806514L,0x7d3c5f5614d202b6L,0x7c2a7c5c6febb3e2L }, + { 0xf2fa07d4f9f2b562L,0x6f717b003ba2a4faL,0x1ff95d598f452226L, + 0xe4b3f6ba867c1cf1L,0x907a648a5d0944ecL,0x1ed480007f64f9b9L } }, + /* 16 << 259 */ + { { 0x0a159f6295b3287dL,0xb18f875948cecad0L,0x6d1ab8ee1661a23fL, + 0xcae7f40ec95c41b3L,0xbc3d20407c51eb56L,0xa7527283e8754250L }, + { 0x815610561f9e668aL,0xb8aa7296900f5912L,0xabdbc1bf6af2a00cL, + 0xe9a942542d0a56c0L,0x4774a7b77bc8959eL,0x0a837ff019cef2f3L } }, + /* 17 << 259 */ + { { 0xd9c3f4ea3c696c76L,0x3aff88caea5878bbL,0x2b01171b09dda122L, + 0xa61d5ca0f599cad4L,0xba0c19bef49772c7L,0x8ee9acc25001f977L }, + { 0x15fd3a172549a25aL,0x8f1a25d82263bc97L,0x372b88434db4af00L, + 0xa613b31f4f912925L,0x7d83041a0b64efd9L,0x897c521ca7d5f6a8L } }, + /* 18 << 259 */ + { { 0x9c441043f310d2a0L,0x2865ee58dc5eb106L,0x71a959229cb8065cL, + 0x8eb3a733a052af0fL,0x56009f42b09d716eL,0xa7f923c5abcbe6adL }, + { 0x263b7669fa375c01L,0x641c47e521ef27a2L,0xa89b474eb08ffd25L, + 0x5be8ec3ff0a239f3L,0x0e79957a242a6c5aL,0x1dfb26d00c6c75f5L } }, + /* 19 << 259 */ + { { 0x04c6a90ae75c82afL,0xe9183100f2488abdL,0xef4b378b111a46baL, + 0x77ad9ef502eaa62eL,0x61229a6205e81570L,0x06e26a2db474c367L }, + { 0x0bb2ea7e7113f2d4L,0x8ddc6f887f101386L,0x93fe2d7ef4de63abL, + 0xc3d038278f44e271L,0xe9f9f48ea94e641aL,0xb84b817b4962467dL } }, + /* 20 << 259 */ + { { 0x36f3a3d8a084fae6L,0x759835899a9b0d95L,0x70722186cc80fcb6L, + 0xf28ed0c796d84c04L,0x95a32263ffb63f90L,0xdd7d60a098766034L }, + { 0xe193a31f1d5c387cL,0x6c5eca7eb8310f8bL,0xfe61d523c083ff47L, + 0x90c832dbcb2944e9L,0xa9f3f293593334b7L,0xe6cde2e12d7d1c33L } }, + /* 21 << 259 */ + { { 0x5637d16b065096b9L,0xee3a2ad04770d39eL,0xae605cb56aa94587L, + 0xc2d71dae9b600c6eL,0x672ef30d76a87e0aL,0x74d5bebe567e0817L }, + { 0x38f591310eb8ca48L,0x92b74866031e099fL,0x654858ca785f77eeL, + 0x264b6b7b830be443L,0xb167203d57103903L,0xa73d5d545ce2b21aL } }, + /* 22 << 259 */ + { { 0x2fd97b9b9dfbf22aL,0xdec16cc85643532dL,0xdf0e6e3960fee7c3L, + 0xd09ad7b6545860c8L,0xcc16e98473fc3b7cL,0x6ce734c10d4e1555L }, + { 0xc6efe68b4b5f6032L,0x3a64f34c14f54073L,0x25da689cac44dc95L, + 0x990c477e5358ad8aL,0x00e958a5f36da7deL,0x902b7360c9b6f161L } }, + /* 23 << 259 */ + { { 0x5e8eb8f0636a77efL,0xe14290f8970c3a7fL,0xfe6f6acdfa1784c0L, + 0x98671d33de6a46b3L,0xe7fd88722ae5a76eL,0xed971ecbae4f7d60L }, + { 0x1d90dbd88461b895L,0x3f979ab4bfaaac13L,0xe06ccba1dbd3379aL, + 0xb53b04ba108c4487L,0xe42609dd38d2730dL,0x0638fe82e81c4594L } }, + /* 24 << 259 */ + { { 0xbd079cf1f144b6ccL,0x7f86e29bb4f4a764L,0x5b08b290f21f9cbfL, + 0xada0c85b75e3aeb9L,0xd0789f8b6666c2dfL,0xcf5d8a8cd71ec2ecL }, + { 0x6f7780c3e7e4364bL,0xdd9a652985d2eb75L,0x8222f66bd952a38eL, + 0x9dd5f7eb27260a29L,0xce49b34457947178L,0xaa215f82cdda7e39L } }, + /* 25 << 259 */ + { { 0xcb91619d1419a50fL,0x44a22eac65dc4c84L,0xc199f93701a92405L, + 0x3749a33198045324L,0xf1676e8abc57764dL,0x922f9460a00c33eeL }, + { 0xfde98e63d3766db4L,0xae08a82efd5ffb6aL,0x6a9834537c0c6ae7L, + 0x0e9a919a54f34cdbL,0xf37a95e8fd88d765L,0x927427d4228a1affL } }, + /* 26 << 259 */ + { { 0x454ab42c9347b90aL,0xcaebe64aa698b02bL,0x119cdc69fb86fa40L, + 0x2e5cb7adc3109281L,0x67bb1ec5cd0c3d00L,0x5d430bc783f25bbfL }, + { 0x69fd84a85cde0abbL,0x69da263e9816b688L,0xe52d93df0e53cbb8L, + 0x42cf6f25add2d5a7L,0x227ba59dc87ca88fL,0x7a1ca876da738554L } }, + /* 27 << 259 */ + { { 0x277c833f57c7bf99L,0xbbb84d1d0b301f02L,0x11435cb20713a92bL, + 0x8ae509702d02862bL,0x4edc66bdaa7b0660L,0x5bc0d893d6382c91L }, + { 0x7992c5d3b94a6343L,0x1cfee04147b19345L,0x57963034964ed646L, + 0xd7af0cac3de7b0e9L,0x5123dd8d481b940aL,0xe1d23ad8ad7d3567L } }, + /* 28 << 259 */ + { { 0xaa44b2863004db31L,0x86f43d7ad43e4430L,0xdc4874cdb0b0240dL, + 0x79986a23adc45a06L,0xbb275b443cee4631L,0x21daee8a63a217aaL }, + { 0x1e7c5397d7b25c02L,0xe677d3cbc5e668faL,0xc7c84e28ed51b4bfL, + 0x7ca19e99923e5408L,0xc6f8a595c3f832e7L,0x2d0a789c5fb049a3L } }, + /* 29 << 259 */ + { { 0x49702e622b82b466L,0x365d4f6afb8fe508L,0x2f5234e044884733L, + 0xcd527f345dd0a3d5L,0x371b02544bf4033eL,0x7d84ad677e3212e0L }, + { 0xaf48fd79e69d6b81L,0xd126f83a7a44bfc6L,0xbb8d2b57b2cc4e93L, + 0x5f62a3d5eb60ec5fL,0x7b37da33aa76c824L,0x7593d06b89a682dbL } }, + /* 30 << 259 */ + { { 0x3fa5c1051cac82c4L,0x23c760878a78c9beL,0xe98cdad61c5cfa42L, + 0x09c302520a6c0421L,0x149bac7c42fc61b9L,0x3a1c22ac3004a3e2L }, + { 0xde6b0d6e202c7fedL,0xb2457377e7e63052L,0x31725fd43706b3efL, + 0xe16a347d2b1afdbfL,0xbe4850c48c29cf66L,0x8f51cc4d2939f23cL } }, + /* 31 << 259 */ + { { 0xc342ed50dd305573L,0xe3055013de86c6c8L,0x0ae84d9776deedc4L, + 0xe8e70cbfd1274b52L,0x4bb51dce32e87f7fL,0x32de3672f3748177L }, + { 0x528af91681722d55L,0x459af071a5f2ce91L,0xf6883bbdc685a670L, + 0x398657f9eeb836b8L,0xa08a793eb9278bd7L,0xe786426bcc09e408L } }, + /* 32 << 259 */ + { { 0x114a25c844922386L,0xdd084d446d4e8b57L,0xc49b68411e7bd7deL, + 0x5b0359fad6da54dbL,0xa6e6e5f93f0da321L,0xb65ec55cd640a87eL }, + { 0xc1a4f6ceae64020eL,0x91e29cd2088e1337L,0xf44ceb8e3c0a631cL, + 0x0205b11db756445fL,0x04844e845bc8880eL,0xb630ddc0b85e00d3L } }, + /* 33 << 259 */ + { { 0xac512659c6ee46b6L,0x0c92e402ca82b384L,0x81d79049194fba3aL, + 0x9b68376c36b42b32L,0x6dc1c80cf6b410b0L,0x509fbe9196b2b328L }, + { 0x988fedd6fdc783b1L,0x9f34cd87436ed055L,0x29f243648bb8809fL, + 0x6962ca24b8dc8b68L,0x076cb7b931963ff9L,0xb609ad792b915093L } }, + /* 34 << 259 */ + { { 0x169e025b219ae6c1L,0x55ff526f116e1ca1L,0x01b810a3b191f55dL, + 0x2d98127229588a69L,0x53c9377048b92199L,0x8c7dd84e8a85236fL }, + { 0x293d48b6caacf958L,0x1f084acb43572b30L,0x628bfa2dfad91f28L, + 0x8d627b11829386afL,0x3ec1dd00d44a77beL,0x8d3b0d08649ac7f0L } }, + /* 35 << 259 */ + { { 0x4aeb3f870af947c6L,0x9ac9ff2791d090c1L,0xeaaa7e0fcf698277L, + 0x737ccc2ff09d6155L,0xd5d4bde86753cc31L,0x3b9063477146d4a3L }, + { 0x75106d8959e32369L,0x7a8ee281645999b3L,0x9184fb5cfc3f675aL, + 0xaeebd0423ad4e239L,0xcff8f73e12f449d1L,0x2771bec17339eb4bL } }, + /* 36 << 259 */ + { { 0xf783db44e6674091L,0x57d0eed31e12a3b7L,0x62d2762af3474f91L, + 0x3d122edf0562af71L,0xaf78dbf77f4bbcbbL,0x8fbbbd97e55f0654L }, + { 0x77e117b004bac36eL,0xbbf6bd463ec582aeL,0x553acd10017eb463L, + 0xfc521187fdfd820bL,0x73211103089b6829L,0x9d3fe7ad7e01e5c0L } }, + /* 37 << 259 */ + { { 0x12a8b7ac04c6babfL,0x7b23210557d2cf63L,0xe03831868f21ad0dL, + 0xd14c2b95acdc2184L,0xe7bd19fcadc9bae1L,0xe2dbabf2edea5c71L }, + { 0x009a3ab78f3f4266L,0x159691e17f8ff74fL,0x5ae666aa22f40f41L, + 0x72fcdc88512387bbL,0xa74e8fb841516c92L,0xd9cee7833b15bf07L } }, + /* 38 << 259 */ + { { 0x00a93daa177513bfL,0x2ef0b96f42ad79e1L,0x81f5aaf1a07129d9L, + 0xfc04b7ef923f2449L,0x855da79560cdb1b7L,0xb1eb5dabad5d61d4L }, + { 0xd2cef1ae353fd028L,0xc21d54399ee94847L,0x9ed552bb0380c1a8L, + 0xb156fe7a2bac328fL,0xbb7e01967213c6a4L,0x36002a331701ed5bL } }, + /* 39 << 259 */ + { { 0xd76b43661c8bd222L,0x041c2b87b97e5b19L,0x7b80f8d7b47c4282L, + 0xfec3d476d0dbc7d3L,0x84aa69712753a830L,0xe5f336079ec85e26L }, + { 0xa425d60cfe2374b3L,0xf88b90f14d953af2L,0x80370e7857ca6c43L, + 0xe07d07176f4d6d7eL,0xe60639401e61ab85L,0x171a2bf632a4c829L } }, + /* 40 << 259 */ + { { 0x38e4168d4f8b5073L,0xf1ddc53fc521849cL,0xd2bf515bab917df1L, + 0xab76b71a697d45c1L,0x20fdc6c7cb566a9dL,0x3843bf838a031cf4L }, + { 0x9a2d89a58a028b04L,0x52f3cb1922a908cdL,0xb5df9c2b7b8723baL, + 0x5142f51060374a3dL,0x949b719800bd9f30L,0x4b7cda16c9b86959L } }, + /* 41 << 259 */ + { { 0x22a32c50d154fc49L,0xe12242de66357eb7L,0x67571eb89f19ef9fL, + 0x2ed01f28b92b20e1L,0xd4fd6efb6cd439c0L,0xc4036cfc03b057fbL }, + { 0x605fab271cc48da5L,0x3cbd7a071416a3e7L,0x9cfe7161714bf173L, + 0xbd03d786a77eb0f8L,0x1423516678b8f5ccL,0xecc56e02f0523f3fL } }, + /* 42 << 259 */ + { { 0x20b1632addc9ef4dL,0x2a35ff4c272d082bL,0x30d39923f6cc9bd3L, + 0x6d879bc2e65c9d08L,0xce8274e16fa9983cL,0x652371e80eb7424fL }, + { 0x32b77503c5c35282L,0xd7306333c885a931L,0x8a16d71972955aa8L, + 0x5548f1637d51f882L,0xb311dc66baba59efL,0x773d54480db8f627L } }, + /* 43 << 259 */ + { { 0x2be2f1d67d64ddbbL,0x3afc2fad6edd7e04L,0x9a57c16d9e797442L, + 0x1efecfde9c16769bL,0x86523c3571b2940aL,0x1a9b30035825d17cL }, + { 0xa25e99beeefc4d7cL,0x8521b49fb50df9eaL,0x10bd2309bd8f3b06L, + 0x1f892e95ea82e80cL,0xf741621c93585741L,0x95687594f5e5087aL } }, + /* 44 << 259 */ + { { 0xbcdd3a3146f684c5L,0xbc8be436f700b0cdL,0x33005e370de75b7dL, + 0x527a8a2c3bd820caL,0x5e44854446997e4cL,0x40921fd93c3dafb0L }, + { 0xf3873a8ab7390d9bL,0x30999855495ba2fbL,0x005164f0813c8c76L, + 0x05bb04d7fe8da60cL,0xee7c38d503224ad1L,0x172018d615785ce5L } }, + /* 45 << 259 */ + { { 0xaaf786c0f6442534L,0x3f1344c1e56b44a5L,0x31199702ed073a36L, + 0x1f8ba0ec3df17e33L,0xf3e7b63493ceee0aL,0x568bdf39490fc4beL }, + { 0x364bdd11b1e1c439L,0xa1aa317ae5a63c82L,0xb12697034c02ee46L, + 0x0bc6d92e7eb64374L,0x87538fe740ed83f1L,0x862450abda74892aL } }, + /* 46 << 259 */ + { { 0x59b1b1347a62eb3bL,0x0f8ce157cceefb34L,0x3fe842a8a798cb2bL, + 0xd01bc6260bf4161dL,0x55ef6e554d016fdbL,0xcb561503b242b201L }, + { 0x076ebc73af4199c1L,0x39dedcbb697244f7L,0x9d184733040162bcL, + 0x902992c17f6b5fa6L,0xad1de754bb4952b5L,0x7acf1b93a121f6c8L } }, + /* 47 << 259 */ + { { 0x293ff71acc51318fL,0x69437a2e614149cfL,0xb12ea4613b48b348L, + 0x2f58020321f6cf90L,0x2e865f77178b53fbL,0xf4774d29231909a8L }, + { 0x0433e66bc4d8b703L,0x4fb6256b907097cfL,0x44a2a7fe004470f7L, + 0x7d3ebbb46dc5f10aL,0xe9b3af288f5526b4L,0x4bc0d9db1107bd75L } }, + /* 48 << 259 */ + { { 0x4865c0ffc0391d0bL,0x70d31470176740ffL,0xf44ca9a1ed506d00L, + 0xfaac86f6c981153aL,0x713ddaf4e3f86940L,0x64ec27093fc39de9L }, + { 0x04d413acac9a26b5L,0xde2052eebb21664bL,0xa6e04de8957b4f20L, + 0xd185b640d5487618L,0x1668b6a46fed1707L,0xeed37894c435ac3dL } }, + /* 49 << 259 */ + { { 0x1fa08a16f69cdfbbL,0xabba54dd0bf735a1L,0x37848c6a68a5cc20L, + 0x08e23c52a969298bL,0x48240306f965bddeL,0x48492deaf90bcff5L }, + { 0x416b9005bd994e22L,0xa6ce214ce6429f16L,0x5aaeec21f43f86d4L, + 0x202db9b7a0b1979fL,0xb2d97b4fdd7ae6d5L,0x4fedb6b9e12f04a1L } }, + /* 50 << 259 */ + { { 0x7a56867c325c9b9aL,0x1a143999f3dc3d6aL,0xce10959003f5bcb8L, + 0x034e9035d6eee5b7L,0x2afa81c8495df1bcL,0x5eab52dc08924d02L }, + { 0xee6aa014aa181904L,0xe62def09310ad621L,0x6c9792fcc7538a03L, + 0xa89d3e883e41d789L,0xd60fa11c9f94ae83L,0x5e16a8c2e0d6234aL } }, + /* 51 << 259 */ + { { 0x9c8e64869c85df60L,0xa84692a681e26100L,0x0350e1209c739462L, + 0xb6da4ebf99fa1f63L,0x857b534055e2bcd4L,0x7f4001dbdb209cf7L }, + { 0xbfa320378757800cL,0x2d56821fa6a562b5L,0xe56d810b6c3e775cL, + 0xeba244a6ba757f86L,0xb7ca8dbf80a17cb3L,0x8cbff4a22b7db57cL } }, + /* 52 << 259 */ + { { 0x650c31da9dff967dL,0xecd1e0f77ed949dbL,0xa7ff9becb20196fdL, + 0x5085c68d1e6259aaL,0x5759a166871a71e9L,0xba15e24c2b4d3bd2L }, + { 0x22c4f75912c51998L,0x6038fb0a7c8a9400L,0x64827d9c09625dacL, + 0xd8ce10c96ec4fb64L,0xe417ac30095686ccL,0x1e624aa88c723f44L } }, + /* 53 << 259 */ + { { 0x872d3dc953387fbaL,0xaaa0e1b4317ec17bL,0xa12b45519efb728cL, + 0x0b43907d45a3491eL,0xb7fa83befa4a239dL,0xbecdae00b59a4f3cL }, + { 0xe4e4c7c393407d23L,0x8278f336cf1d3cd8L,0x73dc9356610570a3L, + 0x5579653d688d933fL,0x208b96be5881d760L,0x4752a645d12f57bbL } }, + /* 54 << 259 */ + { { 0x87ec053da9242f3bL,0x99544637f0e03545L,0xea0633ff6b7019e9L, + 0x8cb8ae0768dddb5bL,0x892e7c841a811ac7L,0xc7ef19eb73664249L }, + { 0xd1b5819acd1489e3L,0xf9c80fb0de45d24aL,0x045c21a683bb7491L, + 0xa65325be73f7a47dL,0x08d09f0e9c394f0cL,0xe7fb21c6268d4f08L } }, + /* 55 << 259 */ + { { 0xe02aca87d4bba3cbL,0xd40ac486652fb181L,0xa1dcfe7ffaa3f999L, + 0x116323e0e9eded09L,0xaa3a0f0f07629d4fL,0x9f8e49f5e0dc53adL }, + { 0xbae96096742af22bL,0x6d7e24dd518862dbL,0x5c91ba30bb333cd7L, + 0xda8df051e65319b0L,0x2b9305ce9b3e43dbL,0xbf1d0e98fe783571L } }, + /* 56 << 259 */ + { { 0xf629fb233809aa31L,0xb3b66d77650bd2b8L,0xcb643126bd325d57L, + 0x29f46272ed41fa03L,0x374e734f406ef56cL,0xbb9ecd36da7428eeL }, + { 0x069694a61c06325aL,0x852b2912e40b9e8cL,0x6504bc90cc3d9695L, + 0xf1af43587e38707aL,0x552127dc239a0781L,0x0d1b3a6e8fe76173L } }, + /* 57 << 259 */ + { { 0x207e41f31d681018L,0x8883a6e417a7d540L,0xffc48332bc983c31L, + 0x729c4110c6b3de67L,0x5ef4680ad69a2499L,0x4544b58fe7afb2e7L }, + { 0xf5a2fb13480e063dL,0x8797357382054197L,0x5dd38cf7131d2df7L, + 0x635e91b8a9366742L,0xbd87a407e0d703c5L,0x6cc37be247251f16L } }, + /* 58 << 259 */ + { { 0xc4ccab956ca95c18L,0x563ffd56bc42e040L,0xfa3c64d8e701c604L, + 0xc88d4426b0abafeeL,0x1a353e5e8542e4c3L,0x9a2d8b7ced726186L }, + { 0xd61ce19042d097faL,0x6a63e280799a748bL,0x0f48d0633225486bL, + 0x848f8fe142a3c443L,0x2ccde2508493cef4L,0x5450a50845e77e7cL } }, + /* 59 << 259 */ + { { 0xaa129c0ddc428c57L,0xfe619b75aea19047L,0xd6287ecf12ea77aeL, + 0x4e6d070fdf7ce104L,0xd0df6788f097c79cL,0xd1c1f8a6ad8b1d07L }, + { 0x53eceba296519e66L,0x71670de3d6274109L,0xd2f21ea03f7a82b8L, + 0x41efbe939c8e45a5L,0xb5b153436ada3edfL,0x32ba22aca90038f8L } }, + /* 60 << 259 */ + { { 0xe1d195fad0cbe947L,0xd1fe0c4ef2ef1b72L,0x1451a0b206003fffL, + 0xda653fa08239341cL,0x5f834372f2508d75L,0xaeb245f507faeac3L }, + { 0x3eb3285b65fdf4ddL,0xfb335c0e84085970L,0x600ad6cae5efc0deL, + 0xc9c9f8910cf83e82L,0xf880ff84ad8cc14cL,0x54816725a016aae6L } }, + /* 61 << 259 */ + { { 0x22ce565ce1124375L,0x30ff1dc5edd968c9L,0x62d74c54e9148534L, + 0xf003f0d35de42774L,0xaf9448e6e57f8842L,0x55d5c9a3c5ff761bL }, + { 0x7da9398cc4c5edd8L,0x9643424e4ea0e099L,0x497eed480634fcb4L, + 0x09ffe2d07dea57cfL,0x30673ba73530a094L,0xfdbf8f24a251cff3L } }, + /* 62 << 259 */ + { { 0xd0f4e24803112816L,0xfcad9ddbccbe9e16L,0x177999bf5ae01ea0L, + 0xd20c78b9ce832dceL,0x3cc694fb50c8c646L,0x24d75968c93d4887L }, + { 0x9f06366a87bc08afL,0x59fab50e7fd0df2aL,0x5ffcc7f76c4cc234L, + 0x87198dd765f52d86L,0x5b9c94b0a855df04L,0xd8ba6c738a067ad7L } }, + /* 63 << 259 */ + { { 0xf9ae5fcedb877020L,0xd84ad42f703e5d09L,0xa6a5cc1fbfaed17eL, + 0x2099409829362fe9L,0x9f863bb0dd299c2dL,0x82bd3f61fa632197L }, + { 0xd3b14097ebe7ff51L,0x7c9e6ec4c719a6bcL,0xd3b46f3d70a51db6L, + 0xc8fa2f0692eb8243L,0x68e1f56e02155139L,0x0c35d135fd3b893dL } }, + /* 64 << 259 */ + { { 0xe76894c3ae7ce296L,0x87737ee2a6cafc34L,0x566dfcfbe55cd1e6L, + 0x5421a9f23a7ad5b9L,0xa005838a4687a4efL,0x3837219a23a2c423L }, + { 0x4b7800128a82cd1bL,0x401c07bec728b588L,0x2b5f69e937ced8f3L, + 0x306b621d8c1e1eaaL,0x8acbbe71d389cc4dL,0x922fa665f4ab7774L } }, + /* 0 << 266 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 266 */ + { { 0x2df6f242d35c2d80L,0xf65a99a93493ce97L,0x9e80232b372bcc87L, + 0x26ba13b86e428cc5L,0x2526ef1f13a1b763L,0xcef3edcddc97c5f3L }, + { 0x4954867fbde16b73L,0x9817813d368ff6cbL,0x7e39fa69be143027L, + 0x12329463cf54f28bL,0xcf0991dc7597c2daL,0x0cda396952e07099L } }, + /* 2 << 266 */ + { { 0x412f64a3f303955dL,0xe92bdca9bd692593L,0xfbe6cdc2c2e964e0L, + 0xe9a3b1fd0011cb01L,0x6c30762dcf228f23L,0x1270b84abe9199a1L }, + { 0x732711dfe3c9cbb1L,0xa3aabe37d91d9513L,0x8ee08ba0c6eceba7L, + 0xb1711531f3c3d31dL,0x65060b633c716948L,0x046b4ea12ff2caddL } }, + /* 3 << 266 */ + { { 0x25d1124fbab220c6L,0xcd1423c861524e3eL,0x75e4f45f0434fb51L, + 0xb5180a8f5180ab2bL,0x144e214e5b22e388L,0x6b16dad192263054L }, + { 0x3ea7590740863566L,0x372d5abddada3b46L,0xb3ff5a3a893d210fL, + 0x39f8d1ce5e29f3dcL,0x559186ce68200e82L,0xf48764541202cb66L } }, + /* 4 << 266 */ + { { 0x6f178dbf8b540904L,0x0264bccd8720472aL,0xa6e8b4b459b46611L, + 0xafce8267c72b4a58L,0x21142175a45985adL,0xd23401dfe649d733L }, + { 0x6bf42fe085dc7720L,0xc5c8ab9440e3f2f5L,0xb0c8a58acd029197L, + 0xa73ff329215492e1L,0x895c545eb1b5a5f0L,0x6dbc24456fcaf49bL } }, + /* 5 << 266 */ + { { 0x25ef32d60f2d76a3L,0x540650b9af4a7d46L,0x8979a4b8d991d7f4L, + 0xdaa706c299202400L,0x8a729680f19d281dL,0xde25bdc44ec44de2L }, + { 0x0fc50832c2054496L,0xfee72fb60aaf2941L,0xc8263e64b82ed4f0L, + 0x91a8cb736f49055cL,0xb7585458f2bb515cL,0x03d2b23ab855e6c6L } }, + /* 6 << 266 */ + { { 0x09ec1e3dcfd3f182L,0x1f1c30b5adae7af9L,0xf3a33f7c6b454164L, + 0x0318926f94647c4fL,0x8e37bdd787db14ecL,0x811cbd342ab364d3L }, + { 0x1dd1e5077c2b369dL,0x7a57bc46a28056bdL,0xfca5be4b089efe44L, + 0xb3bd84d76dc1290eL,0x40d7af098793e6aeL,0x4e08e11fa3723942L } }, + /* 7 << 266 */ + { { 0xca3709ad899ffebbL,0x1a87377877c00602L,0x5ff40c2aa99b4af0L, + 0x680464e5a80e870cL,0xd2f7f04494e10b1dL,0xee9b206c4e9aa1a7L }, + { 0xb536d67596cbe950L,0x841856899e8305f3L,0xae1b669c369fa255L, + 0x62e260267233e1eaL,0xac05c5136aa60c24L,0xdfc6814fd2691677L } }, + /* 8 << 266 */ + { { 0x8baef5df0a02b0fbL,0x58a2b06bc2b92b02L,0x268558d754c8267aL, + 0xf924f795ccf70393L,0xe3763f30f68ee021L,0xc1e856f05c01ba4bL }, + { 0xcc01a3e9722b6bffL,0xd2be4623ed5b3b02L,0x1ab3512e6c45e33fL, + 0xa978fe484ef433f6L,0x23e2ea018e21f5afL,0x49647d8811524a40L } }, + /* 9 << 266 */ + { { 0xd50abc94f5d3f437L,0xbf2ffcc546b7b738L,0x0bf53571f80edda5L, + 0x167908d4ab90ba5fL,0xad445b102303cf00L,0x9b537d4fb9e59406L }, + { 0xfac5e27cf43049a8L,0x05ccb32ebf9db100L,0xe662eeac4d1b535fL, + 0xbf21d6d78d27ca90L,0xb960bf652a684981L,0xe16bdaee49236475L } }, + /* 10 << 266 */ + { { 0x47a5958f92ad4720L,0x12c33193da3bf809L,0xf16493147da6d32cL, + 0x42eb4e687102deebL,0x0f8c4ce283088c86L,0xedf91c3bd693c9a2L }, + { 0x8a18a4761e8c310cL,0x5e8757c5dc3db0e8L,0xc48b820ef76a0affL, + 0x690d788d5c71e596L,0x2b0a00857cfe770dL,0x440ba06bd46505f0L } }, + /* 11 << 266 */ + { { 0x503f77906087d4d0L,0xc7243aeda1ebfb04L,0x203f0563ad8f14bdL, + 0xc20013b7cad73fcaL,0xbace8b323741a708L,0x0b376ff731bdeb56L }, + { 0x820b7f1282c22e57L,0x0c08133117830562L,0x306d178a8d0d30c2L, + 0x36a6efd1467a1510L,0x558fea1af55b7b97L,0x1e9152b784e546eeL } }, + /* 12 << 266 */ + { { 0x92a7fbcdac3ce531L,0xeb85f7f059498d99L,0x8e45db2d02a8feb5L, + 0x176c0cb2728cecbeL,0x33fcfbb0d1837662L,0x426e192dd6f2882cL }, + { 0x75a0f3450a2c9899L,0xd815dc6066148f9dL,0xf4ea90cefa0453afL, + 0x5108858ff54c96fbL,0x86b46b5731f77afcL,0x59df021f6bf7e2fcL } }, + /* 13 << 266 */ + { { 0x48d67f73dab6c0f4L,0x70cfc26cf0d49ef3L,0x25c95a68a65cce7bL, + 0x29a05632cf6ad228L,0xbcc2fb5a1a8128f5L,0x360d82a48c9defe0L }, + { 0x1c5c5d628d1531d8L,0x58fc4b9a149f6b4cL,0x8097cf56a3b625adL, + 0x8821ead7fd8e0e35L,0xb96c2b880d9e1df0L,0xfbf55ba72a243accL } }, + /* 14 << 266 */ + { { 0xef32e94d70e0d8fcL,0x33ec93dc6d63e65fL,0x134532fb1dc7156fL, + 0x98fb5b0c0e8d85b4L,0x05c28df9b64f7861L,0xa7e73afa4160e1a2L }, + { 0xbfe60a9b785f6e4bL,0xfcf998f12fec9ec5L,0xf673b8d15c12a44aL, + 0x85df3bc736d189a5L,0x4480a189dd83f6e0L,0x3216317ef3d3ab44L } }, + /* 15 << 266 */ + { { 0x221c1b7ffd3d7532L,0x40939c318bb4e719L,0x75182ce602f8f74eL, + 0xf508d6415395f9d8L,0x88fc89ea1fc81977L,0x861d8d0bcc8dc7d3L }, + { 0xd76e4f0cec07b0e2L,0xb0a4e2aa5819b99bL,0xa67bed0366a9c935L, + 0xce7c8241d2781f91L,0xe7c5c22512af0abdL,0xd1067dbcfde7de16L } }, + /* 16 << 266 */ + { { 0xe1d42d94d087b788L,0xfbfb221aba0e176aL,0x5f6698e783686966L, + 0xbb5e159474a30dbfL,0xef86bb5bcfd20230L,0xf055a1c5403b8f8bL }, + { 0xf249aac8d9d85ea7L,0x7318f7bc3d200198L,0x3b80960cefca9a90L, + 0xf28e33888f449c4bL,0x0cdfc61bf0cfe09eL,0x3b169c638b22cd26L } }, + /* 17 << 266 */ + { { 0xf4f13a49b81b45b0L,0xb77a67be3003fe1bL,0x70e648a318d52c97L, + 0x701ba8a1ee17ce93L,0x58a0ce0cf672226aL,0x2fcad147cebc3294L }, + { 0xf5cd118a104e8f68L,0x0015bc0bd15358e6L,0x75f0d28f1c662df4L, + 0xcd54f443a3e038f4L,0xa83507610804c717L,0x5fce0ce3f03bad08L } }, + /* 18 << 266 */ + { { 0x4c2e2bffa180a71cL,0x067f3e3baff551b9L,0x007610f1afa43e12L, + 0xe8a9ae79ef7b9a1cL,0xa558ef6cf9d3b397L,0x8d5229884f172f34L }, + { 0xafa906332d425e05L,0xc62c3914207b0bd8L,0xc84d197c059f7d66L, + 0x6cc1d8ce421a9172L,0x1d44a46929a7ebe3L,0x96ca4d0171c3c8b1L } }, + /* 19 << 266 */ + { { 0x31302e094d369fd6L,0x62fe210cf1b62d27L,0x496ac173bb37578cL, + 0xb4d3d065aa0907e0L,0x02317db27c822875L,0x60a01580f241ebc7L }, + { 0x81a5d5244e4f37d0L,0x5286f7289c3f2555L,0x14c8c7549a73ff08L, + 0xd8236689ff478877L,0xf62d426b08e09f00L,0x2ba1833c67a96517L } }, + /* 20 << 266 */ + { { 0x7013d596831f464aL,0xe57185fdd3cf6ca2L,0xbba7898e35915f51L, + 0x9fbe5f139fd967d4L,0x0aba8344d173558fL,0x4c0dd30dffeb6beaL }, + { 0x928f68cc5110e40fL,0x1589a327a58b6d60L,0x09b5c4e06abb0ac9L, + 0x01ef3f8a68957627L,0x55dbe9f79f4045a4L,0x91976aeeef178ac3L } }, + /* 21 << 266 */ + { { 0xd9c20a69b85e46d9L,0x1bda1163cdbda686L,0x5c0717f6c02427a9L, + 0x2a976c104d2a48afL,0xea276b15921a02e5L,0xf055b980ddb6315cL }, + { 0x0ab85663825f00efL,0x95377fd42053a392L,0xc51c245e23f463e8L, + 0xe1ae1e5da24c981fL,0xd6a0b44d9f5cfdbaL,0x1205754023c16002L } }, + /* 22 << 266 */ + { { 0xfe464ce116ac9150L,0xfd629551173ee9e8L,0xd0623ab1781696cfL, + 0x7a07cedd58529fa9L,0x831b4a9d449c33a0L,0xb7b7b72417b171a8L }, + { 0x0e1ff931f5a9aa41L,0xd43f33dfe356ba47L,0xd2abfc77f003b5d2L, + 0xc2909150882c0313L,0x83823f6c7ee111a6L,0x9d7a2d82f59cb72dL } }, + /* 23 << 266 */ + { { 0x52e712549b33f6fdL,0xd4d9b73f5c414babL,0x9834943177e93a9bL, + 0x848b53c99f283fc9L,0x86e48b6234c787efL,0x8b498e1cb3166045L }, + { 0xb2259559e5e456ddL,0x0316069fa2c2ca8cL,0x9a70e29ef6524ecfL, + 0x2477ffc9bfff600dL,0x80a9a5e081869e1cL,0x84f887e70a78f6a0L } }, + /* 24 << 266 */ + { { 0x7f89c2c40c9f23eaL,0x8fb025d4d6ec2b2aL,0xbe70e48b12d9f811L, + 0x703ac1bdc7a43dd0L,0xa4309a2c2118ca3aL,0x5a95d7b301943012L }, + { 0xd9597d87811f6c73L,0xf82e801596079992L,0xfcf8760df1561aa9L, + 0xe1e0306e2d91ee39L,0x99979031e0bbcb6dL,0x49259e54cfcc8746L } }, + /* 25 << 266 */ + { { 0x0de49373a38fb6dbL,0xda9e9036d6bf0a7dL,0xc99fe05fcba221c4L, + 0x45b51edd4cb730f8L,0x312670a3b064e142L,0x60dd1edecddb9ddeL }, + { 0x94be613b9291d75dL,0xbc49861ca00b9831L,0xccec7a08230320bdL, + 0xd1de7bd80ff967b1L,0x5a1164f105fda7e3L,0x864cfc4ce3004538L } }, + /* 26 << 266 */ + { { 0x06f76165385095a7L,0x3c73ac918514b2e0L,0x8ac1120a04b2dac0L, + 0xed6a74174382d5b3L,0x852a5a7864a32d50L,0x7ef5b84bbdc721acL }, + { 0x73dd18980480d271L,0x755b23e04ab0b11dL,0x2e78238982391e5aL, + 0x4957b5c948923446L,0x4ab9318f6921c1fdL,0x8e455abd3e46607bL } }, + /* 27 << 266 */ + { { 0x5c41aafbaf25d6b6L,0xe351f1df916b63f6L,0xe28e9ba98a6efd65L, + 0xcbca736356afe7b0L,0xa77d6077f7384e6aL,0xcc9ad74a738a90abL }, + { 0xe1071caa2333dc2cL,0x4415691000dfc2cbL,0x0ce43c16afd89eefL, + 0x0cfbb8767b812045L,0xe6da40fa6d916fc7L,0xe404b3436302af21L } }, + /* 28 << 266 */ + { { 0x4073f246d9915433L,0xc0149d5672e06203L,0x0abb06c18fcec6a1L, + 0x3a7d1295d75a73f1L,0x65fd8700f18c9488L,0xc3cc0b27732f7741L }, + { 0xd15d8c8025a261caL,0x518233510dc1fee5L,0x981607c7120e1266L, + 0x0e486b11f42cc9fdL,0xe606c16c01a888cfL,0x079dd0b31ea23249L } }, + /* 29 << 266 */ + { { 0x19c62d3c58624305L,0x44974c41b73eae15L,0x2df48b6dd023231aL, + 0x6a82c197c6fad2d0L,0x55758764c623fdceL,0x29f533fbadcebd90L }, + { 0xcfbe4155cfff7336L,0xb18415c7bfb609fcL,0xc23395ad8d411a6cL, + 0x25aebbcf0c92de60L,0xf4d3b1ebc5ccf268L,0x9646b4a79ac85de3L } }, + /* 30 << 266 */ + { { 0x0f423f3013d6cb61L,0x239b2baa66674aceL,0xa6f2ba39eda69340L, + 0xdbbd20eb43e6918cL,0xe6ce84a3e5e7248cL,0xd9184bb5e04c580cL }, + { 0xe4b76d96a0738aedL,0x98662b6090d480a8L,0xfb14bec72610b6c5L, + 0xdfcb01f6bb65837cL,0xd7f0b6ad4a97fb21L,0xe6d84f4bad59b2ceL } }, + /* 31 << 266 */ + { { 0xa79085eb1f7e921aL,0xe2737a08d0aeb41fL,0xa96d7e8169ead959L, + 0xbed1731b733b7c6aL,0x7768e32df508a48aL,0x6f73a08651ccc97aL }, + { 0xb7f94a4b9122db73L,0x1cd17ca257ec947eL,0x7c83fe278f8445f1L, + 0x661f5d82b520fe34L,0x495354942233d364L,0x0bf7abe663925ca2L } }, + /* 32 << 266 */ + { { 0x923e948c203bb368L,0x58e37a2b231a80e0L,0x345a011a6df27debL, + 0xba6784c1d57f4ca2L,0xf01b3703114196e9L,0x981a63eb1aab426dL }, + { 0x2ffdc97851770c1cL,0xddd19da6efa722fcL,0x5ca1c01216f09c1eL, + 0x612021de5b9cc0b6L,0x910e10e95e150569L,0xacace9dce2ab93eaL } }, + /* 33 << 266 */ + { { 0xf66601a7aae13423L,0x940bcd2882cf3308L,0x55de590974f632bdL, + 0xf677d9d4f183faeaL,0x54026b2828ab364cL,0x2a5353dc743469edL }, + { 0x15f02aadd46871d5L,0x4b3ec89b5a2100d1L,0xca85c3681eb9c381L, + 0x145cc7fd50e78466L,0x75fdac98c4b4cdf3L,0xb7cb9170796136f4L } }, + /* 34 << 266 */ + { { 0x6e89c0df54827957L,0xafb26b6d05805250L,0x0c0dc4ea37343465L, + 0x2d3c8b873daca876L,0x733b23d9554a2cd8L,0xd4f2936a6a04d38dL }, + { 0x0937611686f90d9aL,0xcd854d3211425591L,0xbaf9d4cab55b4bf3L, + 0x47259b95144676c2L,0x765cc4b55d7d2835L,0x36e47a8882b2cbafL } }, + /* 35 << 266 */ + { { 0x2070db373af8c96dL,0x4c2db2623b70e976L,0x7ed4d1e9c01f404aL, + 0x04a52764b39d2e07L,0x06e4a7984ebe3ac3L,0x35c9c1f68d7645a7L }, + { 0x2e0b48c75e9c295dL,0x5d44fafaf78e0717L,0x2fc27eba04213067L, + 0x9f3fb2ff2ab0f0e6L,0x374b32fd0c730af6L,0x06ec846129583945L } }, + /* 36 << 266 */ + { { 0x583a3272230be37eL,0x4d3298951c55f593L,0x3b3a2d8a350f0334L, + 0xec830170b25498abL,0xd65847d9b3a01571L,0x4605e739663f86fcL }, + { 0x971b8e115c4bf502L,0x651d179571a892b0L,0x57930832d2d1a4f9L, + 0xf97010745b09a4c4L,0x76b023e55ec2d1a6L,0x8648b8bcf49e1329L } }, + /* 37 << 266 */ + { { 0xc5a8884d6d5c7411L,0xad32aa97d098e2f2L,0xf99569e945d8ad00L, + 0x35801c1c0a232776L,0xe426fd65fb1a2cb2L,0x874b559ecb26ae10L }, + { 0xfa67c2ddf44461b8L,0xc58f8d229418e17cL,0x5998197169908eddL, + 0x8a4a14b8a1f78300L,0x4814c36e61f7fbc5L,0x0389dcc716a1c7adL } }, + /* 38 << 266 */ + { { 0x777e308fc072cf71L,0x4a2d66928c807ed5L,0xa4fe074124842689L, + 0xa3c2a867151ed7b1L,0x52ef24f24d22ee35L,0xe684ac76499053ddL }, + { 0x0b7c223b0582cb86L,0xa6c18539bb81f713L,0xb472da7f66d2aab9L, + 0x3592ab7b7916d4e5L,0xed651a05770c49a1L,0x7b879da1c0256420L } }, + /* 39 << 266 */ + { { 0x82eeaa1496f83e29L,0x586f3e8de5cae8eaL,0xb671eddbb298eb5aL, + 0x41efea86dd0da080L,0xfe9af019564a382eL,0xb2f370463027693bL }, + { 0x65466e5018789c0fL,0x5b0870ac2ebfe89eL,0x9093f416a59f3a53L, + 0xab0cd17251864c77L,0x8e3aa9864481457bL,0x46cfd207896346a5L } }, + /* 40 << 266 */ + { { 0x473bdac887cb6ae0L,0xbd3001b3f155c32bL,0x109643c20026e8a5L, + 0xc4f5f6cc188a568eL,0x630aecf64d2758e0L,0x4549949955b91872L }, + { 0xb10f19d4b6a09df6L,0xc537a4bb37f26d01L,0xd29f505c4d19a293L, + 0xf388a5d2cbb09b17L,0x462efffc6811a49bL,0x8a1cbc40b2f3aef2L } }, + /* 41 << 266 */ + { { 0xf7d94342b7b42998L,0xcdfd6e43629089abL,0x622e8d3cf7932661L, + 0x4818adca0b14b257L,0xcc1dcd1ccdb486bbL,0x58b6cb7ecce8b358L }, + { 0xca36c0b4e640cebeL,0xcc5598942d25f742L,0xdf4f2a9ed754d3eaL, + 0x072eb5e5f44a8604L,0xfa7b1a03cd5ca1c5L,0x6b6b4967d4779eceL } }, + /* 42 << 266 */ + { { 0x0f0233df8665f6f2L,0x8cd887463bd40f39L,0x23a41596eedf8d3aL, + 0x3f50e3f0b5ef5455L,0x935b24e0a50cd358L,0xfdd0e940d362a9a7L }, + { 0x6b00a6d154371aabL,0x2e707c4e1204bcf8L,0xb4d2d2dc30233f88L, + 0x470c3201783e58efL,0xf53987865ac21a16L,0x278487d626c3513eL } }, + /* 43 << 266 */ + { { 0xab5ac4df7d40427aL,0x0c4fb23b66ebdcedL,0xb02f8632b87df612L, + 0xebbd2e7f1801700cL,0xdd11de725b675e5bL,0x2adfb20662d7210fL }, + { 0xe3ba7c0e28667b70L,0x3e190a438fe31c22L,0x57908f2bc3390733L, + 0xe9e8714ccb6fefbbL,0xabba506dfd51c513L,0xd50f979f6b798860L } }, + /* 44 << 266 */ + { { 0xdf224cea1eed2b0bL,0x10205f438814572bL,0x8b99d85c02eb9b6cL, + 0x7a8a3d146c63a672L,0xc8822c6c96f45695L,0x0530f619c7f532f5L }, + { 0xb981e182310f8355L,0x49318290f201444cL,0xeaa4c406f9b76d19L, + 0x960fa2c7534a91c1L,0xf98966d1522b7d9dL,0x66912542c757dbd6L } }, + /* 45 << 266 */ + { { 0xe265972e1fe73a1aL,0x77e234c2987a1a34L,0x1814bdfe8c5789c0L, + 0x908f55c7df2ca0d7L,0xec207eb2a6a50ceeL,0x63cfeaffee916760L }, + { 0x808a758bf466a1b8L,0x2a48112d8383b0afL,0x5238922ef1a4ca6aL, + 0x5c422786778de666L,0xf5a8c6b5d2f549ecL,0xcac5d0c5242bbc9bL } }, + /* 46 << 266 */ + { { 0x33e0e005b34dbf06L,0x7bbdbe1e1fb341dbL,0x443fde882bab5425L, + 0x9db5bf1a86b57cdfL,0x72c535c309a93848L,0xf7aa9432b5f216ceL }, + { 0xc17dc7ae0242308dL,0xf1cb5dc5db0e4c0cL,0xb9d16d58a2b7112eL, + 0x486cda07ee4494b5L,0xeb46ab545d431adbL,0x3261dc5181ab565aL } }, + /* 47 << 266 */ + { { 0x476a4bfaa2a8a081L,0x43c5f841394f851bL,0x659baa591f5b22ddL, + 0x49a786aa65f680efL,0x091bd21608fcb9d8L,0x13f6953d984fe1f1L }, + { 0x7b5d9f4b6d6d40a3L,0x2f135dcf0d458d54L,0x2da18c3d3a71204aL, + 0x3d93edb97a3486d6L,0x026fec7261846af9L,0xa62197bcd5200dcdL } }, + /* 48 << 266 */ + { { 0x0cdd83725070e0a9L,0x7c5ad562ec550783L,0x9652b8474f3b8d2bL, + 0xfdd60d93e6e98d73L,0xd51cae2ca3479d0bL,0x11b93b6dee05c006L }, + { 0x9d72b82d8a3b40d5L,0xc6e996fea7d24855L,0x420672f7398603deL, + 0xd551b34a9a1af2ceL,0xdeb8c1d913bdce0cL,0x56ca926debbeba7aL } }, + /* 49 << 266 */ + { { 0xf63ec096bb85ca8aL,0xc149664173bc52f2L,0xba792560c02fc808L, + 0x9a6043e3533c6523L,0xa9d78f0aa8564390L,0x7fef67e494614bc7L }, + { 0xb4091b8fd389234dL,0x5913368e82db1d08L,0x178f7df0981cc6caL, + 0x19b1f2be725ec048L,0x852aad85012f9c44L,0xb07cac0dc894e777L } }, + /* 50 << 266 */ + { { 0x1c1709d02c7e0767L,0xec1013234d70b117L,0x95c57e678beb8e05L, + 0xdbf29e2e1133fa4aL,0x917f4a6c5139e020L,0xcf0be5098399735dL }, + { 0x83014c169c878b4aL,0xe0c14d2cf789b84fL,0x222aba39165a4aafL, + 0xe135f2b384441391L,0xb6f1cf7e19c3ee07L,0x2f918da9f810499eL } }, + /* 51 << 266 */ + { { 0x026ee35816bb2bddL,0x8c8953f8566d8470L,0xf0cd746d0fc63932L, + 0xddf3e54f060a07a3L,0x8da877a643b4e92dL,0x7ffd839dfdc9e34aL }, + { 0x5c3527445df04d9aL,0x3c5eb576b69f84e0L,0xf73cae300848d993L, + 0x3438f2bea0fe7fdbL,0xd4e7511f0eaf0168L,0xa7ffd167c768386aL } }, + /* 52 << 266 */ + { { 0xbb91877acfc74bb0L,0xbe742182a060a71eL,0x116e5a626ed7786cL, + 0x0a496b1bea669e56L,0x3a012174b8f02e6eL,0x6add760c106174f4L }, + { 0xaf2606e05e0292cbL,0x7800a495c7b7bad0L,0xca02c9320a1c5954L, + 0x904f23c6b245ad57L,0x28d6cc2172934de5L,0xbb7ed903283752cdL } }, + /* 53 << 266 */ + { { 0xc80288125e58122dL,0x7a5c65f1c4b089caL,0x4ddfd3663b980faaL, + 0xe8129f7f96a909a0L,0xc177aa042221ffacL,0xaf444ef78ff46e81L }, + { 0xa627f3d76b154996L,0x0f06fa7b115e2a5dL,0x2532b85d43fdb775L, + 0xb6d96b32eaacfb58L,0x898766304f834382L,0xfd2ffde9d5636b92L } }, + /* 54 << 266 */ + { { 0x318cf974973757d0L,0x12882d0a94ac73a2L,0x1fb74a53bc250843L, + 0xc612569eccd8d47dL,0x74cff8789d5f7c8cL,0x54e0e475375a7366L }, + { 0xe8322d23d0f57cd4L,0xb6ec5666d95a6e0fL,0xc8374b254a4bd084L, + 0x9459181b349d93ebL,0x7011f0a61368b9a8L,0xed57a19137eb2833L } }, + /* 55 << 266 */ + { { 0xd245d180fa5f79acL,0x44c331f35b41fcb3L,0x13188b6e27ee6c0eL, + 0x54ce984b23fdc742L,0x66d4e1303c81c213L,0x432174030ecb6fd8L }, + { 0xbbeb09fe111ae08bL,0xb22ca6b42e2df05cL,0x0e9d01dd0fec9be9L, + 0x9ac4523dfd2fc4abL,0x3d9e98c8fdc059f5L,0xd52e6dfb2d2cbde7L } }, + /* 56 << 266 */ + { { 0x80d7ef8598100f17L,0xb9795c7112db3f3aL,0x44473659296a7c44L, + 0xa46810f21e5bf539L,0x5621241814ee1e3bL,0xea8284e209931822L }, + { 0x424c613e42ac1e42L,0xe84a80afbccf9466L,0x21a8cdcc45132204L, + 0x9505a4148d58da62L,0x773e09837b3f47aaL,0x0ad0cc91e109bc6dL } }, + /* 57 << 266 */ + { { 0x98e2509bb527b250L,0x2dd30c824a9c762bL,0x54025da4cb2a00a2L, + 0x88ed00ff04d8e0e9L,0x5699890219ab1fadL,0x92fffc41697b0226L }, + { 0xb481d1ee7d08a39bL,0xea773f7f82be0803L,0x967e848a6de8ec6dL, + 0x6ea1e46380293472L,0x941cded72e988de3L,0x85f96b23399da6b5L } }, + /* 58 << 266 */ + { { 0xabd86572f1a62473L,0x9ec25d0bec274738L,0xd27d1a8c2052d4ccL, + 0x1f2a2a9ba95de3f0L,0xe3b8652ea2c91bcaL,0x1a4f6900822175deL }, + { 0xd9405d4662475a44L,0x4ecbe06cfe55c587L,0x30f8d199a4ac2f35L, + 0x2a5defd8d3c12844L,0x6d0fd9d673fe9b7eL,0xb0ae1019adf1a196L } }, + /* 59 << 266 */ + { { 0x6c9a378c30734f5eL,0xdf04359f6aaf7b42L,0x244422fc16f87409L, + 0x81dfb15b08bcd67cL,0x24b7d083a5e4a8e0L,0x557183410431786fL }, + { 0xc8feeb8c33f3ec2eL,0x360098cb2be371a0L,0xf4f3d992bdb874ceL, + 0x47b432ed87af8471L,0x5c4b1dbdf87535deL,0x6bb6d6dd8301f660L } }, + /* 60 << 266 */ + { { 0xafa9338759769f77L,0xe6c710cb49e502b3L,0xe6fd7b8d1514da98L, + 0xb5924c63aedf93caL,0x4cc36795c112b37bL,0x0ee30ce3231def42L }, + { 0xe1f436e7daf8a37eL,0xed54b7f56efa184aL,0x09ad65752c0dfe63L, + 0x5ed9da43ca530b38L,0xea2fa192ae156274L,0xbf096c54a4429edaL } }, + /* 61 << 266 */ + { { 0x41401b98f54490cfL,0x361a24a143b21183L,0xf0176431b6570f0cL, + 0x851bfe9d05c8bd3aL,0xe44f4ba74611e1b9L,0x587677dc28bf2c27L }, + { 0x3e3b67886d85341fL,0xad65a69468aa381bL,0xd269dc711aecf19bL, + 0xb94b64a2d98e6a2cL,0x6004b569a94661a0L,0x81713a8e689181d5L } }, + /* 62 << 266 */ + { { 0x55b1901d3649638eL,0x2e9929c416abaf64L,0x2d2b160ee9cd0090L, + 0xb5ef6525f55f13ccL,0x447aacbe11c3e8a5L,0x2c54e602630cf4c4L }, + { 0x3f6d99fc641d8eb3L,0x35386c1384877912L,0x7195db8973f31b6fL, + 0x63297cb2d3a22085L,0xa627593833fe97cbL,0x2f9a6f0da1eaef0aL } }, + /* 63 << 266 */ + { { 0xb70d7683c63d6dd3L,0x60ea781084acedf1L,0x7646260c40d62cd0L, + 0x687000b456142a6aL,0xce3c4728ccb9177bL,0x45377d059928c509L }, + { 0x75cc40bb1a78af0dL,0x43a1661cc69e59fdL,0xf9bbcbf8044a943cL, + 0x934fd40d7c372080L,0xb6edae96cb2eb940L,0xa02bb5fd6e063cc9L } }, + /* 64 << 266 */ + { { 0xac58c9e09db9ca19L,0xd308ea5d390054d0L,0x32ef4afc2cc42529L, + 0x08bd48b397c2bdf9L,0xac8a7803a849e19aL,0xcd51c0da75c31496L }, + { 0x733dc7def0e2d49fL,0x7c9caad1b44b8cc5L,0x6d9c5b0847be21a8L, + 0xfab0fdc55ebf426fL,0xd60748caf94e9e5bL,0x3072e59269366089L } }, + /* 0 << 273 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 273 */ + { { 0xb06c17a3f0ef77c5L,0xc144e7846df6bf59L,0x2440ae990038aeb2L, + 0x83bf711b58b402caL,0xb8763e00b577732aL,0x509e91eff651a932L }, + { 0xbe02ab9d00ac109eL,0xfbcb426c8dfd78f1L,0x7ed272f64283f80fL, + 0x098cf0572365da5eL,0xd90e6f1805dc6bebL,0x09ef177fcf7b9d72L } }, + /* 2 << 273 */ + { { 0x6f101762eeb791c4L,0x0d942184df261effL,0x2c58e2aaac1dc827L, + 0x51410e89f835a1b6L,0x981333a7629915a4L,0x371891b60c14148dL }, + { 0x4d20b3d3c0904446L,0xdda7ecc8949776d8L,0xa664b68c2a2645f7L, + 0x7a6bc857add082eaL,0xe7467dc63e5ff206L,0x40a6c34004e2dfccL } }, + /* 3 << 273 */ + { { 0x3d0efae3106ba1a1L,0x9c717ca192d7be5aL,0xa5cb5a253f00eeeeL, + 0xc2f9258cd86161ceL,0xd2b0865f5c4a389aL,0x8c06d7689b1f2159L }, + { 0x5a758a612753107fL,0x5ab6449d0a539c19L,0x88655a4949d301c8L, + 0x129647e61c4bb89bL,0x06f0665ec360259cL,0xcdba2f0b066197d1L } }, + /* 4 << 273 */ + { { 0xa235456903744726L,0xd2169e6dd8d275acL,0xab0c247b132c5689L, + 0x129a5c9dcc4760bbL,0x03eba46726ae821bL,0x67a33fda3df1cf83L }, + { 0x010813cfb8421b7aL,0x7b0f507098cd6d76L,0x907320b31fe4b600L, + 0xda3bfeb398dd3239L,0x23f1ed1641abb34cL,0x01b30f29946f85f1L } }, + /* 5 << 273 */ + { { 0x97c5f1c7d3970d9fL,0xd051c518ac8e6227L,0x3f67b3958e87edacL, + 0x3a5cbd287b9e4c17L,0x58c009e65671841dL,0x7bc5bddb518b3b39L }, + { 0xe7a8a6335e74a614L,0xf92e4c226ed89a92L,0xd0d6e80a118e663dL, + 0x33dba4f9dcbb4aecL,0x1d4cb3141f917417L,0xd8b17bfa3b0c5859L } }, + /* 6 << 273 */ + { { 0xc0fa0d21a093c3e0L,0xad34c41439e902a2L,0x81c8cd7599bc928bL, + 0xf7f8be14cdbbe4d8L,0xe46268b5c2339529L,0xcdc54e348283ba7dL }, + { 0x4c5cf62778904fe1L,0x056678c11b45e4d2L,0xb555ad6ad265abc2L, + 0xb8f8ca3f830306efL,0x48c8764681c20e1dL,0x5bb0a529737a7944L } }, + /* 7 << 273 */ + { { 0xbd4c2bfc9cf6fc5fL,0x888885140577af66L,0xb5aa2f05f9e3f7c5L, + 0xbd477bae64de6007L,0x1da5dcc9747e1224L,0xc2293d1732a15f5dL }, + { 0x4dd9daed029d6cbaL,0xf51362d62cf299c7L,0xe1a4b5c4279cd1e1L, + 0x4b129a5ea89acfffL,0x8292228ece1c8744L,0x5a440fa04fd12c86L } }, + /* 8 << 273 */ + { { 0x285248309666f8eaL,0xd579b3dfeff6502bL,0x3a66fa9900e4f78aL, + 0xfd8a65bb54a3f7a3L,0x505d3f631965a79aL,0x9524972c1891469aL }, + { 0x78367cbc3354da3aL,0xbfe1fe3de4941c6eL,0xe41bb3f6f5af173eL, + 0x57cb03ca5ca36597L,0x27f86cb87b99f795L,0x5cae6514ad4dcef1L } }, + /* 9 << 273 */ + { { 0x4b43f0aef1743346L,0x1700581944324c46L,0x86c77197e3603fcaL, + 0x230d516f4a6858aaL,0xee965b4ee7c56f7fL,0x4f4ed301dcefb75aL }, + { 0x610b138c4a740b23L,0xda3996a83ffc3599L,0x930698fcb2d1c304L, + 0xd55bdcd3702bf80dL,0xdf767c419e334726L,0x975352a9d0e819b6L } }, + /* 10 << 273 */ + { { 0xc117353b5e816653L,0x0c87bebe820641d5L,0xee588c6d9ecd29a1L, + 0xacdfe622c70edf9bL,0xe8b8024cebae414bL,0xd0c426dc9bd7ceccL }, + { 0x715cbc2efe735ce7L,0x8376edebc5e7017aL,0xe9b37efc07990dd5L, + 0xc89e384ed8d75238L,0xbc594d218438ffb3L,0xbe77e4d4d3628473L } }, + /* 11 << 273 */ + { { 0xc53720cdd1b4f3baL,0xb8ac3b4fadf2a330L,0xcef037f5fe179e70L, + 0x2743b382589d9147L,0x77a094d624423d58L,0x9e34c2e62a23d372L }, + { 0x641ea760983a5893L,0x2211e6a49a81548eL,0x56578a1a48735310L, + 0xedb91e03a57faa83L,0x4e14d5649b133629L,0x341f3ef957e82ff7L } }, + /* 12 << 273 */ + { { 0x4952a350d87a86c9L,0x08ed7da7034f45f9L,0x1e9ff8272bd716d0L, + 0x2471fd15f1d9331fL,0x0c708362d7370b75L,0xaddedde6fc1a1051L }, + { 0xf4475288db27b186L,0x5be4d46b3760bc11L,0xe44435d906d47ee1L, + 0x865cf7c8d0b7c8a2L,0xdb412be08d31a252L,0x4b90a9322f24d71cL } }, + /* 13 << 273 */ + { { 0x71b84eed8f7a3ab9L,0xf41d7edb2dc18004L,0xe408156dcc4a02cfL, + 0x0be155a25cd906caL,0xbf4b0f6991516399L,0x2ea85d434a7ff94dL }, + { 0xf199b31da26e9974L,0xc584df250b805ae3L,0xd4e7e8597a3634daL, + 0xf553f07770db4be9L,0x1cb1056fbf0dafa3L,0x235281b2a817d6edL } }, + /* 14 << 273 */ + { { 0xc3304e9260d2b80bL,0xab24dac9a38753bdL,0x40373d04cc1ebbf8L, + 0xa5a162d3437e68d2L,0xc8018b1257e8db12L,0x0c99c6de9bb52643L }, + { 0xafef0ff6ee24e63bL,0x329c46264bea9a14L,0x1b17d2e6effae4f9L, + 0xd25b93aaee300afdL,0xe83bfdcba0d62da4L,0x5e919538fd787740L } }, + /* 15 << 273 */ + { { 0xf5bbb4fe196c38e7L,0xe0011deca5c75baaL,0x2e29fe59b835aa49L, + 0xee22e2864230f17fL,0x8774214ff94c1060L,0x35bcca38e6d4c126L }, + { 0x18d984dbb7c9d255L,0xb1d5515c9b63dc4fL,0x425360f12a0cb854L, + 0x038c7f2317a1e286L,0x5e6b12ce951f18b2L,0xabfbde5ea65b1de3L } }, + /* 16 << 273 */ + { { 0x38a49bf555f0ad9fL,0x1a84c6b8f3618639L,0x5f709eca01b2f7c2L, + 0xc479a6505be8359fL,0x6b6a22bfd6646b3fL,0xcce78878cc5b711bL }, + { 0x8e7dbc63b446cc63L,0x231bd027218f800fL,0x2d3a7e04030271ebL, + 0xb08b5978e22fb3c7L,0x860d62789be0d46cL,0x253a31c21d49a915L } }, + /* 17 << 273 */ + { { 0xab4dbdf36ebc28e5L,0x56d5fec527be58b5L,0x6e9375d3cf3fd509L, + 0xfffea897ca4ddf48L,0x0a9542ae6a3757c5L,0xb9069a2e7d93911dL }, + { 0x3e74ac5f3dc967b8L,0x99c38796ea8f5a21L,0x27797b97a6ddea53L, + 0x9501e1c561dfcc1bL,0x568d3abe448e95c5L,0x021f8f4c0e7c186bL } }, + /* 18 << 273 */ + { { 0x98aa1f7a6e44f63dL,0x6451b170cb597ec9L,0xc0f6ee8721e13b78L, + 0x36c3b9c751cfd003L,0xc31718ed2f610040L,0xdddabc6688c48009L }, + { 0x5626f090a8369e4fL,0x0eccb1c06004a968L,0x2f0448035da2f1a4L, + 0x5390b6dd3846a726L,0x5c4caffea24f3083L,0x3c9baac8c4842995L } }, + /* 19 << 273 */ + { { 0x58c5fd1205c7a75dL,0xa98007fd10866935L,0x91369e874acd567eL, + 0xb7e05dc322c6145aL,0x24c949b4d949d8b2L,0xc5c574a590a6a437L }, + { 0x4306f0334798d1d5L,0x82af09f4520e01b3L,0x53fab41b81247f00L, + 0x3096ccf44ea93cbfL,0x9665e039f13ff09eL,0xb623f8b158e036d9L } }, + /* 20 << 273 */ + { { 0xbad6b669376bdc3fL,0xc4a8e7bc23a9ff38L,0x3f54d8c4555fb0a3L, + 0xfb3d5e1d2b23db1bL,0x6379f78af0d7eba9L,0x36004febfa0beffaL }, + { 0xdf0a373c334ff01aL,0x10314749dff12a1cL,0x1d52ddc7f184c1b3L, + 0x79431663ab02d404L,0x1a6488c17f4d3795L,0x3363660f7cca9102L } }, + /* 21 << 273 */ + { { 0x1e4595c6db3e57d9L,0x49e3d3d9bfb94ec5L,0x4c720de1a4f12881L, + 0x91a08340b06c64e6L,0x8e5c72f0ef0857deL,0x2c9b4cbc09bb76fcL }, + { 0xd4262fe4b0bba8bfL,0x64c5fa1439fcd07bL,0x518da4de62904ceeL, + 0x626182ebae4c9717L,0x900fe9f806351622L,0xf74aaa2241f9e4d7L } }, + /* 22 << 273 */ + { { 0x9d2c02839fabb29bL,0xb27ac46e172348cfL,0xddc6fb63de1f64b2L, + 0x532dc953bb097c87L,0xc7f5180cdaa34e27L,0xf96e4ad755438893L }, + { 0xc0b2eba324f54a0bL,0xeba396ce5b50d12eL,0x80b3a7f699772783L, + 0xe2fa82ff3ff7df4aL,0x55375369a2359baaL,0xa28388ed856c05bbL } }, + /* 23 << 273 */ + { { 0x4432fe8495a2d064L,0x4c6380747fec6057L,0xc33705bb33cfb533L, + 0x5e7fb7c976991cfeL,0x73d249bdb3ac1b6eL,0x963964c896aeddccL }, + { 0x8c1abe0e56b71636L,0x6ebb841f38693cd1L,0x00ef6a7b60e7cf67L, + 0x29ecded2c258bcb9L,0xb2d566a5e40fd26aL,0xa2910f4ed512abffL } }, + /* 24 << 273 */ + { { 0x56d6515604dc109cL,0xcd740cc809c1d307L,0xef9e049f10dfaeadL, + 0x19750b3ae30b70b8L,0x11ed860015c6a562L,0x53bdf97e12097026L }, + { 0x79559d056c0d908fL,0x8f1d75bab506d527L,0xd6fd7323ae8fb3c4L, + 0x834639c9a4111f88L,0xfc69a029a310a683L,0xa4467bbb255f2e9aL } }, + /* 25 << 273 */ + { { 0xa809a063e9e3953fL,0x09242dc960dc53fdL,0xa48f52d00080c436L, + 0x762a585dad2eb70dL,0xc6d52f047a3c6aa2L,0x1b6979dcbe60899cL }, + { 0x7a07af246d760794L,0xa5b1f912ef5c1118L,0x36367e4375bb329eL, + 0x594f349029e6bddbL,0x13cdc4aaa4a4f1edL,0xa7c3ff97b687a69dL } }, + /* 26 << 273 */ + { { 0x1e79881146f7c4c0L,0x25730855946abf8eL,0x1741fdeeaac2031eL, + 0xef34715b72ea60b6L,0x378eb680350ddcfbL,0xe72ac880ec237141L }, + { 0xb173251fff125bf8L,0x37ffb0cf4999b6daL,0x9eeb91a8817779f6L, + 0xa9edff0ae93ed1f3L,0x31f2ca241d7772d6L,0xd25c3f3b97f67b92L } }, + /* 27 << 273 */ + { { 0xb6c4144381478e46L,0x7b53d46350cf8795L,0xe96e7cb9ca5bf2d2L, + 0xc8fa39c695ac9ba6L,0x8ab037d12efc83d1L,0x0ccacbcc94bc2536L }, + { 0x45e7c7c774038e13L,0x47d5b7292f5e344eL,0x2e0ffb2cb1eed282L, + 0xfe88d3a88d5d0b37L,0x804b612e2487d971L,0x6f316d66c95d08faL } }, + /* 28 << 273 */ + { { 0x5f0a58a8a3526fecL,0x849c171b02f028c1L,0x34d77ce856a5d3b5L, + 0x9701621754d5a92bL,0x0cce35c12cc5b70bL,0xd9d5a00ae83f1f4aL }, + { 0x064223f826a0368bL,0x328a9f6940e16452L,0x3a6ac093d305ad2cL, + 0x759d9a16beba7c44L,0x86021de7637ce7c8L,0x276bed61cc80c1ccL } }, + /* 29 << 273 */ + { { 0x5d4a529ef9822e60L,0xc6f2702006edd801L,0xb2511d84efa3d8d6L, + 0x38cfba656a4c6598L,0x31a5779765c067a9L,0xcee558f387d2ca0aL }, + { 0xf22345cff844260aL,0x29b6352a63d2ae75L,0x59dad0ab6cc9f2bdL, + 0x615ad3599ae1bcb3L,0x3a29a237f692f42bL,0x543771c40f26163aL } }, + /* 30 << 273 */ + { { 0x427437e7d722576cL,0xc9d7ac7abb548ef5L,0x72f00f28c331a9e0L, + 0x5d9327b564949b48L,0xea75f3b54e2bb808L,0x28acdea068678f8bL }, + { 0xe9e787b20878223fL,0x213f47ff7e7b0a11L,0x5e967d39f277a3f7L, + 0xe6651015d2006de4L,0x49b87e4bc44eb1e0L,0xf461bb76222cd3a2L } }, + /* 31 << 273 */ + { { 0xd6b9341fde60d963L,0xb1a8dd0d5319a930L,0xc4f18dc0aa6b20b5L, + 0x787de2e7f23f4401L,0xc15b38eb28047029L,0x0bffc0b55c99d51aL }, + { 0xf0310f39740b5798L,0xf69ea1064ed8d3bfL,0x545a54d79f6722aaL, + 0xe5a9dee3af4017c2L,0x45efa2ec4a659592L,0xc5d64bedbed4e245L } }, + /* 32 << 273 */ + { { 0x66797f56bbe4bddaL,0xb92a369eda51b1a2L,0x18eef4a531adb034L, + 0xcf1cb5ee5d185cfcL,0xf596a59bbd53c27bL,0x1e1dd6f569002569L }, + { 0xd9433e797687e48aL,0x7d8d24c20cbcb9ceL,0x233cd7ed65d68ecdL, + 0x201bbe09fb2aded8L,0x987f4975ac9b750eL,0x949da385337f7f25L } }, + /* 33 << 273 */ + { { 0x31439e35b95fd11dL,0xf97e8fa4b691fb77L,0xcfdc02956d4ac378L, + 0xd31bc3b0d1a617c8L,0xd857098204bd015bL,0x30cca6efd6198f0dL }, + { 0x6a52650a805964edL,0xb656d7abd060eeb3L,0x5267f37ed38a9218L, + 0x5f28a2ecd3d6a193L,0xb7dc6e916d0d9c9eL,0xa7f84e4b219d45c6L } }, + /* 34 << 273 */ + { { 0x550ef2713398c3dfL,0xfe184954307631a8L,0x02cef50606e5cde4L, + 0x9687a39c10f11703L,0x02c35937acb10b97L,0x835b00fd13e3d219L }, + { 0x5828678b584d1abaL,0xbe55fb9cc9b40568L,0xe5a4a90e8fe19e84L, + 0x91e24c9248989b77L,0x094f9e7ae3d5f4fcL,0xfe9bdfb9759029b5L } }, + /* 35 << 273 */ + { { 0x43b1f8b9c1de72e9L,0xcbc8e0d4a3bdb164L,0x5c45d3dfbcc2e5bdL, + 0xb5137b69247bef53L,0x6d889f5673794e3cL,0x43e2fc9b1e2dfdc1L }, + { 0xda15dc5da995d3adL,0xa0db9f5ec43d86e0L,0xc42a144bcaac3bbfL, + 0x3c855fb174c43eddL,0x0731f33152688272L,0xc1f23e5643d7762aL } }, + /* 36 << 273 */ + { { 0x00c2ee1c9c7de99fL,0x28a7461d15e50391L,0x1bdc0e32a1c77952L, + 0xe98242c4d53d640dL,0x1a4724d2cf153c7dL,0x194e5dccba477d46L }, + { 0x871c8cfe3a0d4ccdL,0x62010af09af451fbL,0x9b354f9e6ddec75cL, + 0xe5db0a5d680e3511L,0x183d1270d247745bL,0x9910867aeecf52dcL } }, + /* 37 << 273 */ + { { 0xa970903e8bc2003aL,0x0f8bcfa4a3cf29bcL,0x7054f69e683a7ddaL, + 0x53928bf1ece30167L,0x2588bdf1ffffea87L,0x01683b5ed7172ad4L }, + { 0xa0ac85379de7e713L,0x217bcdfe9b0442bcL,0xba46b8f64d4adb3eL, + 0x320580990a9f8ecdL,0x0173b7bea504bdc5L,0x15321aeb82b1606fL } }, + /* 38 << 273 */ + { { 0x4f349e5f6e39d625L,0x37cbd935b80760d6L,0xb8657ee14b1e84c2L, + 0x502954064cb84bdeL,0x66d678cce8d23ef5L,0xcba173713ec3b79cL }, + { 0xed7ab3e526e3cee5L,0x34c68c516c44ef0cL,0xd704e724f8fdd226L, + 0x2fa0d2dd3a9b40a7L,0x373c5c70a23be590L,0x0beb611bda9f7f7dL } }, + /* 39 << 273 */ + { { 0xef506531913bc31bL,0x31210c5f8c320074L,0xb42faf19b861acc1L, + 0x26f09b89e041e774L,0x23fec89822f84c93L,0x9f8b9d708ec590bfL }, + { 0x604d7d2952644790L,0xb77e3136a2339c53L,0x17f1d7a920f2fc09L, + 0x8c6435d9e6bb96eaL,0x5cafeb5f3711b8a7L,0x1ec6c4edfa23ca24L } }, + /* 40 << 273 */ + { { 0x6fb6b7bc0410ca0bL,0x0e16eed2b3c13935L,0x98ad89d8316ff531L, + 0x4800ee179894d65fL,0x034ea3c448280170L,0x8126d12dc30be537L }, + { 0x43c2d27e5120e525L,0x96a5d498ee65df90L,0x654540105eaef29aL, + 0x1d8f07a17b678fc7L,0x54bc6f737b301270L,0xe58a8102e9473365L } }, + /* 41 << 273 */ + { { 0x1fa3a458aaaf79f6L,0x1d14ff613a1b7c64L,0x32c7da68f22ddb3cL, + 0x7b2345ac58cff63fL,0x214e6d9dce3c3af9L,0x36fba0b78b6691deL }, + { 0x69fd813cee1a30abL,0x50daffe91adf6215L,0x55b34de692871a84L, + 0x437f1b4b7ff3ea1aL,0xc3258ca580ff1c23L,0xdc220ffbc6d0b822L } }, + /* 42 << 273 */ + { { 0x93e56b47ad910b37L,0x8cbce4815d20d236L,0x25b50cac5872d763L, + 0xb50aa752d8505696L,0x02075e6d6f42b533L,0xf0b34a178f8d8352L }, + { 0x59f2feda5234531bL,0xb23e1da1751127c8L,0xe1f65e08b6759ccdL, + 0x47d8631c352e9500L,0xab10d299c13feb16L,0xf9e916a3e5c6a220L } }, + /* 43 << 273 */ + { { 0x55899ffdc06f1b65L,0x4f9ec6e011899630L,0x0df97edc50a29319L, + 0x5c4a10ea5e66f0adL,0xea7b4497aa3d14e9L,0x484d8f64d22cc470L }, + { 0xd7fd252240a61a0bL,0xebd9f49d42d04a79L,0xf18ba2ec312ddb99L, + 0x687273ec2dce1351L,0x68d8b052d0220e57L,0x2c0ecd6b05a7e3dcL } }, + /* 44 << 273 */ + { { 0x460c29904ac6cf02L,0x01482cfa420a35b7L,0xf793933a34680972L, + 0x2cd1f50017e2367bL,0x2411c3523944f060L,0x3d58b97411c06b05L }, + { 0x4552e369cddebb3bL,0xe1c38aec009aeab9L,0x9d34737c353b6e4fL, + 0xf2c99e2cb16d7b0cL,0x57029fa47bbba6a2L,0x0565d1bcd13ef64dL } }, + /* 45 << 273 */ + { { 0x93a50cc7eb0112a9L,0xa0d4419984a59bdbL,0x04b9538c82d01160L, + 0xdb1d33e163a8d5a3L,0xa710beff08d3effeL,0xc2f37326f9bf02f4L }, + { 0x606b6b5555d26856L,0xf528d22a427fe3d7L,0x31b20fac84fb5086L, + 0x27129aa592f7e7bcL,0xd88f0d4f44171b33L,0x9b045c897915ede1L } }, + /* 46 << 273 */ + { { 0x0b15ebebcbe014d6L,0xa4f1504e68d24086L,0xbcf475c979d7c8b6L, + 0xd61b92a8d00a6890L,0x78e096742ee24533L,0x6fe9fe6099656101L }, + { 0xc9542f53e5e63e28L,0x59ec39e12edf3a80L,0x8fe57ffe24ad9280L, + 0xbae0671bf4b9b024L,0x76e36c14d5816ae9L,0xe53256d4805f8688L } }, + /* 47 << 273 */ + { { 0x006956bfcf9e545bL,0x7829ed13e8fa2ee4L,0x1b108d77d4dd6f85L, + 0xf51217bb17045f1aL,0x48c4802986141bd6L,0x8d59b995f8820213L }, + { 0x8439949ffc298a9eL,0x967fdcb278188d77L,0x5bbdfd296f35c711L, + 0x25b37e5df8e62607L,0x18f5c4251795cccaL,0x260f075af0e35ff5L } }, + /* 48 << 273 */ + { { 0x3561b3fea329deb1L,0xfdca0e34f1c3c3e4L,0x4374831347fb79d6L, + 0xa7f497e1c48002edL,0x86221cce2c44dcb0L,0x65e3f04643785e06L }, + { 0x9ee9061fdf4cf461L,0xc7479e8cf022d27aL,0x1d8de85b76f7f52bL, + 0x39a713c90fd6c65fL,0xf74ca067711f8a39L,0xad1119ad8ebc640aL } }, + /* 49 << 273 */ + { { 0x43d9bcba57ec124eL,0xbce6aed98cc29801L,0x1dbb88c72632e757L, + 0xe88f49e891f550e5L,0x056f67da7b6e1b05L,0xa503271082a027bbL }, + { 0x8471fa55c91844a9L,0x882f25b628479daaL,0x96f606dfa9c23504L, + 0x6a42d307fb7fa83dL,0x531c8a5cea310e34L,0x7e2d20565b2e42f0L } }, + /* 50 << 273 */ + { { 0x547047862e8c467eL,0x26f5efc690e52377L,0x762d8f767f6e71afL, + 0x5fc1bd13917ff587L,0x487f6c63fb696a60L,0x889a1dcc3afd2aebL }, + { 0x7407d0a0adcf4b35L,0x8f6c9aef91024ecfL,0x3384f1c03e5d9da0L, + 0xf87acb00b846d122L,0x6d86aebddceb383aL,0x6a5a90cda8f2d076L } }, + /* 51 << 273 */ + { { 0xddff7aa3feb71de1L,0x431e106be44644a9L,0xafe96f8ed5190b4bL, + 0x31a4dfe40ab42a27L,0x0e2d0cc435762eccL,0x7c928cd91fefb256L }, + { 0x5f33c775daeb94f9L,0xa7a91f8894c239b7L,0x6bf418fb4deda3c9L, + 0x91ad6e99eefd4f99L,0x7aae05559c25448fL,0xfb7ed9df487b4deaL } }, + /* 52 << 273 */ + { { 0x59753bf68ba85dffL,0xec8b82efd1c89bceL,0xd7f1a651b8b6a683L, + 0x9c329bf36f84416dL,0xaecbf4b9e68db225L,0x94ec3b0f5a614d23L }, + { 0xbcb6672593a9543dL,0x90c46c46f19132edL,0x4767c73c950b080fL, + 0x0b9b143e971fd9e5L,0xbce6886f8ec8c68dL,0x167b0f8ad47f512eL } }, + /* 53 << 273 */ + { { 0x51517f9481819dd9L,0x2c2640a0fdd7cef9L,0x59283faabf98b8ffL, + 0x39713768a46ad877L,0x13d9c0e6834dcf0cL,0x38c85473cc7acaddL }, + { 0x7b58c7666971a512L,0xbe46a58c2a38e57eL,0x3d26d0a06972e213L, + 0x2341769b63cd0aabL,0x4a293dd0e86307eeL,0x8d1e338d264c81a1L } }, + /* 54 << 273 */ + { { 0x66eb8beab2d5b430L,0x50b4af4382136220L,0x6644e673e79d0b5bL, + 0xe64cdf10f9fa7610L,0xf1dea591132ff33dL,0x07791ab6b926c725L }, + { 0x6c41b4f383f60e02L,0x54bc9049977519c3L,0x618a6f3c2aef73a4L, + 0x42cfc9d26fa4ca2bL,0x2784db71a39a215dL,0x378071655cc85253L } }, + /* 55 << 273 */ + { { 0x9cc3ada3554a7f23L,0xa822f9f21c3d0003L,0xb1654da7303123f7L, + 0xbe33e388f0d8c4a1L,0xd8919c79be4366e8L,0x5a41c92cfe292117L }, + { 0xc4b02d0678c325c2L,0x89eaf4356d511c4aL,0x726fb6d65fda70a0L, + 0xaf7949a0183abdf1L,0x3410915d26f8f929L,0x36b3aeb281f0f83dL } }, + /* 56 << 273 */ + { { 0x1942c2ffcd74009dL,0x71c4d5f5e9c286a4L,0xf3c152b5771a5972L, + 0x4cfb1e74363c2048L,0xcd2ce8249ddb8da2L,0x5d97c8e0a5ee443dL }, + { 0x6fa84b3d68d7b3d5L,0x97eaa76d9ce14ec3L,0x2e4571368e13869dL, + 0x39ac6a0c96f0f8a1L,0xe24458ac42d93dc0L,0x7eb3689d5f60bec9L } }, + /* 57 << 273 */ + { { 0x75592736bce6ebe3L,0x84001a886777bd90L,0xe82739774a31ca6bL, + 0x6906baf0a8e0dd38L,0x92af56d0848d0c92L,0x7ae700c6501326d0L }, + { 0xce418817470339a9L,0x4354d7928e448dfeL,0xc8f593afa48e3148L, + 0xdd5fee34db1a96b2L,0x5974e81e357960c2L,0x7326bf016306fdabL } }, + /* 58 << 273 */ + { { 0x74183618de017cd9L,0x939c7975dcfe6dbfL,0xcad9f8a108ec41e5L, + 0xd9edb91d391afcddL,0xadf1f18c7c4a3f03L,0x0566d3e8ab477304L }, + { 0x32ae20464c19c62cL,0xfa15fdcb252c8c4eL,0x2ed4767e91de2794L, + 0x622e4f38507f8067L,0xd647242bc68ac330L,0x0650e0a9fc1ccf29L } }, + /* 59 << 273 */ + { { 0x6ecd68a086085cc3L,0xb463f4c165c0cc54L,0x3182cc5c480bc57dL, + 0x8f16f2038e6d9267L,0x8c92e446df0d0ee9L,0x7da6001ba4d09789L }, + { 0x596390ff976ee9d0L,0x12b8f9dee4c0fd5fL,0xad08673f297b10f2L, + 0xc8e9097c7b524a51L,0xd494f0d3009cf47cL,0xf535c07abcdd1b68L } }, + /* 60 << 273 */ + { { 0x29544fe8588360ecL,0xa1aa9b9fffb550eaL,0xe1f6cf994af4d28dL, + 0x723d48b00c6fd477L,0xf51f1b2f5c81b252L,0x88ec11c04f5a33eeL }, + { 0x7747f0432cd72de4L,0xcca69b0ad71c92c1L,0x9455d86e4e8cc763L, + 0xc9e0aa1bc08444e0L,0x93803b68e8fffa63L,0xc296af292d781b7dL } }, + /* 61 << 273 */ + { { 0xb1891a2b17329e31L,0x87c2a49056e36717L,0x8c2a50fafd26d8b3L, + 0x017e4e417e3c5a5fL,0xbeb4fad0506c382eL,0x5d3e8b16fc281ec9L }, + { 0x407f7598890e57a0L,0xda855e8b340cd6d6L,0xb9393129ff388d54L, + 0x41113ffdcf355d9eL,0x31d3bb09b357c28dL,0x975bdf00fd39e481L } }, + /* 62 << 273 */ + { { 0xbfb0c87e10a1b4f2L,0xfaf51153dc2fcc04L,0xd2588e39d6b98d81L, + 0x5de5b0eb4953133dL,0x6b65d8135b959ed6L,0x864511dc02eb45bdL }, + { 0xb1dcb4d3d7ce20bdL,0x917bcd0987587230L,0x0935790f83a79453L, + 0xdc65862e54b35d76L,0x4cd2332ba6d1eeeaL,0x0706fcd030d315b5L } }, + /* 63 << 273 */ + { { 0x7c91adb3adf2d8d1L,0xfe1549c24a212fd3L,0x8a7cc285c33213b3L, + 0x26643cfd3e56d17bL,0xcc007c15684c872fL,0x485643e009e554f3L }, + { 0x7f5e9a6ec6569206L,0x252b5393c2f596d6L,0xf7eef1dbbf9cdea5L, + 0x611ee7334dffab46L,0x8d93802a805e976cL,0xd07c0ac6f85c939cL } }, + /* 64 << 273 */ + { { 0x514cc1dcb08d2d0eL,0x4e6b379e30e93536L,0xf0e422ac2fc9230fL, + 0xaa50a1ad92e23e21L,0x70ac46d8676d1ac0L,0x698b9991f9f54493L }, + { 0x59a6b86a8649519fL,0xc1f11ad6e3511da4L,0xd3d9cff13192968cL, + 0x13e700b40b342dd8L,0xfd5dc7bb3b1da441L,0x02426e7c2c883760L } }, + /* 0 << 280 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 280 */ + { { 0x9e9af3151c4c9d90L,0x8665c5a9d12e0a89L,0x204abd9258286493L, + 0x79959889b2e09205L,0x0c727a3dfe56b101L,0xf366244c8b657f26L }, + { 0xde35d954cca65be2L,0x52ee1230b0fd41ceL,0xfa03261f36019feeL, + 0xafda42d966511d8fL,0xf63211dd821148b9L,0x7b56af7e6f13a3e1L } }, + /* 2 << 280 */ + { { 0x3997900ecc8998d6L,0x8fa564b7baa60da1L,0x71bf5b0a661f3c57L, + 0x44b13388aab1292bL,0xcbe80cb9d4d993f2L,0x0b19b4c92203f966L }, + { 0xbc82a6520080f259L,0x870ebc08ad96dea3L,0xa388c7e7502f0003L, + 0x9c704ef056a38f73L,0x93cde8a73487d9b0L,0x5e9148b0ec11a1f3L } }, + /* 3 << 280 */ + { { 0x47fe47995913e184L,0x5bbe584c82145900L,0xb76cfa8b9a867173L, + 0x9bc87bf0514bf471L,0x37392dce71dcf1fcL,0xec3efae03ad1efa8L }, + { 0xbbea5a3414876451L,0x96e5f5436217090fL,0x5b3d4ecd9b1665a9L, + 0xe7b0df26e329df22L,0x18fb438e0baa808dL,0x90757ebfdd516fafL } }, + /* 4 << 280 */ + { { 0x63f27a25a748b8f5L,0x68c8f3ec2cd246c4L,0x5d317cd965f9ce38L, + 0x162c92e0635ba300L,0x5259f64ffe343662L,0x4a6b2b668e614ac8L }, + { 0x97fb55bb01177c3bL,0xfb586c21a705cb01L,0xa57e732578061824L, + 0x892f6b386c1e6306L,0xf12e4c072367b14cL,0x580d5fe2c83a48c5L } }, + /* 5 << 280 */ + { { 0x1e6f9a95d5a98d68L,0x759ea7df849da828L,0x365d56256e8b4198L, + 0xe1b9c53b7a4a53f9L,0x55dc1d50e32b9b16L,0xa4657ebbbb6d5701L }, + { 0x4c270249eacc76e2L,0xbe49ec75162b1cc7L,0x19a95b610689902bL, + 0xdd5706bfa4cfc5a8L,0xd33bdb7314e5b424L,0x21311bd1e69eba87L } }, + /* 6 << 280 */ + { { 0x6897401cea2bafb3L,0x7b96ecc215c56fe4L,0xe511b32939e2b43bL, + 0x39522861bf809331L,0x815f6c1dc958f8f4L,0x2abbdf6bc213e727L }, + { 0xeb09ae59c39bc01fL,0xffe3b831676b56a5L,0x8f4815a2a20f86c6L, + 0x748a17669aa30807L,0xf1f46a211b758878L,0xbd421fe76f6fc3d7L } }, + /* 7 << 280 */ + { { 0x75ba2f9b72a21accL,0x356688d4a28edb4cL,0x3c339e0b610d080fL, + 0x614ac29333a99c2fL,0xa5e23af2aa580affL,0xa6bcb860e1fdba3aL }, + { 0xaa603365b43f9425L,0xae8d7126f7ee4635L,0xa2b2524456330a32L, + 0xc396b5bb9e025aa3L,0xabbf77faf8a0d5cfL,0xb322ee30ea31c83bL } }, + /* 8 << 280 */ + { { 0x300b04840d6ded89L,0x0b1092cbc3ab55edL,0x17d9c5420cc10a74L, + 0x7f637e84eff9d010L,0xd732aa1e27aa1285L,0xedb97340e2a77114L }, + { 0x62acf1585ef4dfb0L,0x1e94fc6eba1d7b81L,0x88bec5d22e6eb2dbL, + 0xaec272028d18263dL,0x4b687353e4bbd6acL,0x031be3510ff7e4c0L } }, + /* 9 << 280 */ + { { 0x048813847890e234L,0x387f1159672e70c6L,0x1468a6147b307f75L, + 0x56335b52ed85ec96L,0xda1bb60fd45bcae9L,0x4d94f3f0f9faeaddL }, + { 0x6c6a7183fc78d86bL,0xa425b5c73018dec6L,0xb1549c332d877399L, + 0x6c41c50c92b2bc37L,0x3a9f380c83ee0ddbL,0xded5feb6c4599e73L } }, + /* 10 << 280 */ + { { 0x6c00f388f086d06cL,0x17ee45035add0cf4L,0xf96984c707caf89cL, + 0x9d49d667648ed5e9L,0x3ef95015a0164881L,0x39e28e447d9c651fL }, + { 0xb13ad24059f37780L,0x08cee349b9522225L,0x9245ee6f2ba1b214L, + 0x12bedaa9a886d8d2L,0xe139ae08fcb8186fL,0x99203fb6fc2ef864L } }, + /* 11 << 280 */ + { { 0x14d34c210b7f8354L,0x1475a1cd9177ce45L,0x9f5f764a9b926e4bL, + 0x77260d1e05dd21feL,0x3c882480c4b937f7L,0xc92dcd39722372f2L }, + { 0xf636a1beec6f657eL,0xb0e6c3121d30dd35L,0xfe4b0528e4654efeL, + 0x1c4a682021d230d2L,0x615d2e4898fa45abL,0x1f35d6d801fdbabfL } }, + /* 12 << 280 */ + { { 0x3c29284764c9323dL,0x40115a890491f77dL,0xec141ade2d7a05f5L, + 0x0c35e4d9222a5f9fL,0x5ea51791442a3e9bL,0x17e68ecee51b841eL }, + { 0x415c0f6cd6ae9174L,0xe6df85f89ffd7595L,0x65fc694f8dedf59cL, + 0xc609503efee92718L,0x57d2592e97d565aeL,0xb761bf157e20862bL } }, + /* 13 << 280 */ + { { 0xa636eeb83a7b10d1L,0x4e1ae352f4a29e73L,0x01704f5fe6bb1ec7L, + 0x75c04f720ef020aeL,0x448d8cee5a31e6a6L,0xe40a9c29208f994bL }, + { 0x69e09a30fd8f9d5dL,0xe6a5f7eb449bab7eL,0xf25bc18a2aa1768bL, + 0x9449e4043c841234L,0x7a3bf43e016a7befL,0xf25803e82a150b60L } }, + /* 14 << 280 */ + { { 0xd443b26582376117L,0xb91087c11a1beb0dL,0x3fe62a6545cc5951L, + 0x49c754bce6e472d5L,0x7e60bb8177c424ebL,0xbcd4088e830cbb97L }, + { 0x3da5c94eba26df7bL,0x508b4f55f72b4338L,0x409c5c7469ad7784L, + 0x82e5f1b0fdf44d6aL,0x10654a1ceed2766fL,0xef1e65faa6e83f4aL } }, + /* 15 << 280 */ + { { 0xe44a2a57b215f9e0L,0x38b34dce19066f0aL,0x8bb91dad40bb1bfbL, + 0x64c9f775e67735fcL,0xde14241788d613cdL,0xc5014ff51901d88dL }, + { 0xa250341df38116b0L,0xf96b9dd49d6cbcb2L,0x15ec6c7276b3fac2L, + 0x88f1952f8124c1e9L,0x6b72f8ea975be4f5L,0x23d288ff061f7530L } }, + /* 16 << 280 */ + { { 0xa6e19d0a5f56dc3cL,0xe387e2690b88326aL,0xef7380950ee527a4L, + 0x78b7174b7c4278a6L,0xc133d867e70798ffL,0x9d0fef759e9230caL }, + { 0x7431eef01a955ab9L,0x3772e7038868d922L,0xf7a4306a8d6af3f7L, + 0x633bb5a0bbec076aL,0x6d07623e7a257ca3L,0xffb5e16521c00663L } }, + /* 17 << 280 */ + { { 0xebfe3e5fafb96ce3L,0x2275edfbb1979537L,0xc37ab9e8c97ba741L, + 0x446e4b1063d7c626L,0xb73e2dced025eb02L,0x1f952b517669eea7L }, + { 0xabdd00f66069a424L,0x1c0f9d9bdc298bfbL,0x831b1fd3eb757b33L, + 0xd7dbe18359d60b32L,0x663d1f369ef094b3L,0x1bd5732e67f7f11aL } }, + /* 18 << 280 */ + { { 0xfab0ce2bee1ae33dL,0x7bf9f90b4c5692e3L,0x131a4374d776d6caL, + 0x6ba40908a2b135afL,0x5c4ab997e1334bf8L,0x9eb442d07af584e9L }, + { 0xd764c506786391c1L,0x07f24c6bbcf6ab3aL,0xf73c7924fad8e1bbL, + 0x79f624acb7583623L,0x2b032021b44c14d3L,0x7cc0ae8dbf58ff99L } }, + /* 19 << 280 */ + { { 0x3c7fb3f5c75d8892L,0x2cff9a0cba68da69L,0x76455e8b60ec740bL, + 0x4b8d67ff167b88f0L,0xedec0c025a4186b1L,0x127c462dbebf35abL }, + { 0x9159c67e049430fcL,0x86b21dd2e7747320L,0x0e0e01520cf27b89L, + 0x705f28f5cd1316b6L,0x76751691beaea8a8L,0x4c73e282360c5b69L } }, + /* 20 << 280 */ + { { 0xe4d7c8b88929c133L,0xe5f96bef92a813c7L,0xdb8ab0af71c18e09L, + 0x0db6ff287dae63b4L,0x54d1fac49a1eaa73L,0xadbcfdf59180c980L }, + { 0xd3220f300b584314L,0xa24e4d1cca3697c7L,0x4ade8c7fa44f8067L, + 0xbd8bc81aca21ac17L,0x303a2f9fc1d361cfL,0x55648b65c71cf031L } }, + /* 21 << 280 */ + { { 0x46bcc0d5fd7b3d74L,0x6f13c20e0dc4f410L,0x98a1af7d72f11cdfL, + 0x6099fd837928881cL,0x66976356371bb94bL,0x673fba7219b945abL }, + { 0xe4d8fa6eaed00700L,0xea2313ec5c71a9f7L,0xf9ed8268f99d4aeaL, + 0xadd8916442ab59c7L,0xb37eb26f3f3a2d45L,0x0b39bd7aa924841eL } }, + /* 22 << 280 */ + { { 0x6f8135c7ce89e8daL,0x21ac20d9d6b5948eL,0x1dc4d48b31cefd7eL, + 0x3d34bc2a4a347926L,0xadcd11be8f614fd6L,0x77148b08a8ea116aL }, + { 0x7afc75fcfce1d3f5L,0xa9e0557d7d9a8ea3L,0x640cb5850cc864ecL, + 0x5811ba842eb332c7L,0xb6c10b6efdb668c4L,0x24d8b10f99f5f6c7L } }, + /* 23 << 280 */ + { { 0xd811eb32e03cdbbbL,0x12055f1d7cc3610eL,0x6b23a1a0a9046e3fL, + 0x4d7121229dd4a749L,0xb0c2aca1b1bf0ac3L,0x71eff575c1b0432fL }, + { 0x6cd814922b44e285L,0x3088bd9cd87e8d20L,0xace218e5f567e8faL, + 0xb3fa0424cf90cbbbL,0xadbda751770734d3L,0xbcd78bad5ad6569aL } }, + /* 24 << 280 */ + { { 0x391fa3cd8d075ec5L,0x54d45020c84c81e5L,0xdead561a79fad87cL, + 0x0ab3c8544e7ffc48L,0x5967f8ebff02706cL,0x8860de795d31ec98L }, + { 0x7476459c6c8a1c25L,0x8d9c484082f16117L,0x5c1b13b33b413429L, + 0x1962a435601b5906L,0x78b9d382e006929dL,0x1924e979e5897b16L } }, + /* 25 << 280 */ + { { 0xcadb31fa7f39641fL,0x3ef3e295825e5562L,0x4893c633f4094c64L, + 0x52f685f18addf432L,0x9fd887ab7fdc9373L,0x47a9ada0e8680e8bL }, + { 0x579313b7f0cd44f6L,0xac4b8668e188ae2eL,0x648f43698fb145bdL, + 0xe0460ab374629e31L,0xc25f28758ff2b05fL,0x4720c2b62d31eaeaL } }, + /* 26 << 280 */ + { { 0xef1001dfbdb22e61L,0x1626bd9af384bbf5L,0x33f42d385fe8ae07L, + 0x59646c42b7218d21L,0x5e27210e6a016f5dL,0x3e9ecf07094481c3L }, + { 0xf91609c1f50cc2dcL,0x8bf8c05ad0d43633L,0x9d508972e74ab746L, + 0xb625887a33f628b7L,0x557bd493e733952fL,0xd35f450b8981dcfbL } }, + /* 27 << 280 */ + { { 0x4603cdf413d48f80L,0x9adb50e2a49725daL,0x8cd3305065df63f0L, + 0x58d8b3bbcd643003L,0x170a4f4ab739826bL,0x857772b51ead0e17L }, + { 0x01b78152e65320f1L,0xa6b4d845b7503fc0L,0x0f5089b93dd50798L, + 0x488f200f5690b6beL,0x220b4adf9e096f36L,0x474d7c9f8ce5bc7cL } }, + /* 28 << 280 */ + { { 0x531c43cdb63f3d28L,0x01289772429708dfL,0xb0ee772ccdb60078L, + 0x4131f5cd5f1a6e72L,0xd9d0f8c6a0da0112L,0x58efddd204e957b1L }, + { 0x18857c0c32840c31L,0x00825340c4068b2cL,0x0a9217a771ff8800L, + 0x69b19e6415530b80L,0xa28e274ee125e3f2L,0xb471a91bc9bfc846L } }, + /* 29 << 280 */ + { { 0xfed8c058c745f8c9L,0xb683179e291262d1L,0x26abd367d15ee88cL, + 0x29e8eed3f60a6249L,0xed6008bb1e02d6e1L,0xd82ecf4ca6b12b8dL }, + { 0x9929d021aae4fa22L,0xbe4def14336a1ab3L,0x529b7e098c80a312L, + 0xb059188dee0eb0ceL,0x1e42979a16deab7fL,0x2411034984ee9477L } }, + /* 30 << 280 */ + { { 0x01d04fe04ce2d199L,0xf434bcfd0517c7ebL,0x82f3aca4a7659a94L, + 0xf436a7781ff015c9L,0xf5143391d6223e5cL,0xba66c6a2ecb5c340L }, + { 0x080f158a4b23a041L,0xb401094cb699acafL,0x1c57626c677491dbL, + 0xfb39e317d42d86dbL,0x19e2ca804f6b3354L,0xe919c4c3c1d41ef3L } }, + /* 31 << 280 */ + { { 0xd65246852be579ccL,0x849316f1c456fdedL,0xc51b7da42d1b67daL, + 0xc25b539e41bc6d6aL,0xe3b7cca3a9bf8bedL,0x813ef18c045c15e4L }, + { 0x5f3789a1697982c4L,0x4c1253698c435566L,0x00a7ae6edc0a92c6L, + 0x1abc929b2f64a053L,0xf4925c4c38666b44L,0xa81044b00f3de7f6L } }, + /* 32 << 280 */ + { { 0x35ae891bbb71e9b0L,0x1f6ce6ca522b77f0L,0xc2dab3cae63745c4L, + 0x55b8c185f218d139L,0x6ab039c889f3b0e2L,0xd9e25bfdc644c3faL }, + { 0xc8496f203e2ed47bL,0xc395ec028d67e17cL,0x5c67839292114918L, + 0xe962e52fef73f345L,0x3818baf354fcfb22L,0x4d75d65d9d4bc911L } }, + /* 33 << 280 */ + { { 0x10078824eb7ff5fdL,0x50c65328735ef75fL,0xdfc04d53ec980ba2L, + 0x4bfb260f2d519cf5L,0x1f03dff15c854667L,0xd1ad2231badb625cL }, + { 0x986064d0be9f7f03L,0xe5ff93e5c13f7d0dL,0x02682a1896e26a17L, + 0xc421567c817ec3cdL,0xb740652352615c25L,0x6800a8335d135eebL } }, + /* 34 << 280 */ + { { 0xde57575b17d8ec5cL,0x72e2257578aeb9bbL,0xce73fa7731605c27L, + 0x2f286b79ae77436cL,0x5e78fbb77f4e6997L,0xb03c888e474f23a7L }, + { 0x4bb302a3e38927ceL,0x39c6de5f6e1514ceL,0x9daa0ad349b2ddbdL, + 0x98fd2377d683dffdL,0xbefa4ae5933476edL,0x4ad53d01173f49edL } }, + /* 35 << 280 */ + { { 0xdfafc70e44b89837L,0xe0104b9c4935fa88L,0x7625d9d92fd702e2L, + 0x27461e6549af2219L,0x4a279383ad3f36edL,0xd87e246b9204e857L }, + { 0x8d832190ab1727d9L,0x59205cd82182e291L,0xb96a1d15a6513613L, + 0x1c7de3cc49cc8ddcL,0x637ea26af17ab785L,0xc098bb7a09a3ba58L } }, + /* 36 << 280 */ + { { 0xfb5383cc31bd4f68L,0x6fd5aee3d96a1899L,0x4e39d6eb01d5430eL, + 0x12679565ca5a2848L,0xa399e83f062b44fbL,0x3ee2432f3c166682L }, + { 0x57229c841de47708L,0x40a5d0cbba528a61L,0x4bae36be8239e7baL, + 0xddac65a2f8087427L,0xfd516d1a3cc61266L,0xc89542b5bcef98b1L } }, + /* 37 << 280 */ + { { 0x3fc8d1b2d49cc0eaL,0xfc591f7f7bca4d23L,0x5f48e27c41fefdf3L, + 0x5ca1d08a1039419dL,0xd450c1bddc8042ceL,0x6760e23fb436fc4bL }, + { 0xc5642797c06bb34bL,0xb787cd53fde06d4dL,0x2926360ccbf144b0L, + 0xb63756f4dce32421L,0x0878deab774abc4aL,0x2d97c7919a4e142aL } }, + /* 38 << 280 */ + { { 0xf58389ff105c818eL,0xfa29f1eb585fa7f0L,0xb6da09b5917e8924L, + 0x1375c3047e7a3f49L,0x9b4792b289cfa1c0L,0x92094a8535571cc7L }, + { 0xf986ccf6051e5e50L,0x55ea34d601df6babL,0xe65989eed1363333L, + 0xd94bbd918c84e20aL,0x9a4f71dc49e39b8aL,0x6d9fe495927d633eL } }, + /* 39 << 280 */ + { { 0x30b295f01fdc29e2L,0x71415daae2c2fab4L,0x205e957683c312beL, + 0x893c69fefab48afcL,0x8108f3f994ca2fdbL,0x37c860c314f99296L }, + { 0x1009a6d2e990ed34L,0xd5350c36ac26b611L,0xd03161102ce23d91L, + 0x82bb476e62189343L,0xe255965160ef0cbdL,0x6bab3f53cf5d2311L } }, + /* 40 << 280 */ + { { 0xcaa3b7a592fa460fL,0x92bb46b804dff174L,0xcd6949b3cf926a1fL, + 0x01f95e5559d1bb18L,0x21f90c08d4518f3cL,0x325dbfe920ee8bf5L }, + { 0xd0136f3feafb919eL,0x941190cc8e0ebcabL,0x599e91a287b557aaL, + 0x7fac4887dcbde1c7L,0x1dad481905a07040L,0x640493978b03d593L } }, + /* 41 << 280 */ + { { 0x65521bb85ebd3685L,0x16c68e79665d1619L,0xd6ab56bbc52b14c8L, + 0x312f1fb4c6d3067dL,0x5afef4f3d50587c0L,0xa3e79e94ace6e2feL }, + { 0x52c7fa0825f12a1eL,0x9c1c1ea20dec9f3dL,0xc418d4232e87a036L, + 0xa0a19fbb0283752fL,0x52e0a8830b804506L,0xc67fc71b3f7de2a1L } }, + /* 42 << 280 */ + { { 0x4d062d3d7dad8ca9L,0xb78c81581cf59756L,0xaccb38f8c6b5d9fcL, + 0x83436d3f7ddc66eaL,0x37115b6033adcb87L,0x49b74bd45a8b09abL }, + { 0x7b8bdb81675ae43bL,0x5284f5b3f0476428L,0x8f1521e7db38b0c7L, + 0x792ef9dea0c4b2f6L,0xa15880a162159fc6L,0x70b999e372b09b63L } }, + /* 43 << 280 */ + { { 0x6f47787d4e8ffde7L,0x19e9434574495a10L,0x8da6d55784f5be33L, + 0x110844811884e325L,0x621734c5a9f030baL,0x25cd0544d0e63f63L }, + { 0xea6729687e936833L,0x08297af784a34442L,0xb77dc3a342f9ed3eL, + 0x9f8908c8258e8d4fL,0xb8281bfc3299ba4bL,0x1f6412920a09849cL } }, + /* 44 << 280 */ + { { 0xd5d51e60ee9a7708L,0x2e8ab3effd2cfe78L,0x0af5c3bac8e71273L, + 0xbfd1b94091041652L,0x4c7c86ab52ce4582L,0x3ab72feff1d9bc29L }, + { 0xae89c3d51e1974b3L,0xd859c7ef70433caeL,0x762064c77edd1398L, + 0xc0b6a6b6072064a4L,0x3ba43b059bb1b3d0L,0x20f9aa85e47d79bbL } }, + /* 45 << 280 */ + { { 0xd1a45415c2d001cfL,0x40f3f05d848a480fL,0x03708da0ce554d5bL, + 0xd7090557c80f4254L,0x7e57d29907743393L,0x7db8a5e10f2f5903L }, + { 0xd0466a0b14e8ff8bL,0xa3c38f49e0cf88b0L,0xde47262e329f71adL, + 0x56b2a7935da6d0a1L,0x22e1f9b880ef44b0L,0xb9b96c617b2b6d4bL } }, + /* 46 << 280 */ + { { 0x3235bc494c500ee1L,0xce0f0b54da4a4f35L,0x628cb91c337ac7b7L, + 0xd8a6d4cd88a26e9dL,0xdcf40cba96e44349L,0x073a0f75b54e3fa9L }, + { 0xc9b95d29ca44e6e8L,0x42ad9afa2315f4beL,0xdf13a5ddf78617c7L, + 0x40aeb346d196504bL,0x9317d6f33d1fef90L,0xf94d308fe1708a79L } }, + /* 47 << 280 */ + { { 0x45bc768608835815L,0x700d93bc5798c507L,0xae3415b85362a822L, + 0xdbce01b33883d21dL,0xb9df7efbe56fb2aeL,0x5ed57d9427d341c0L }, + { 0xdc26916e7ee4dfa0L,0xcdb06a17147c075fL,0x0198b6a7fa9e7a63L, + 0xc9876c786355b62bL,0x9f4b8f12f565279dL,0xa03aeb619cb6ddb6L } }, + /* 48 << 280 */ + { { 0x3a35938779493f3dL,0x128301a91f06a9c0L,0xfcce0f82899d204cL, + 0x4ca41589158780b5L,0xc28f1bb73c4edd4fL,0xe08e48a87a6aec34L }, + { 0x6d4783dfd447c55eL,0xe7c2ecc857803027L,0xb7b8c2bcdf6d7f91L, + 0xf0a8d4700f356ca3L,0x229894bfdeb8e964L,0x555c9d40d3aa70e1L } }, + /* 49 << 280 */ + { { 0xa899a252e0ace851L,0x74b716c9bb9d8476L,0x2ba0bb00571bb175L, + 0xee01a9bf7ac2b619L,0x74f0b6d3502ee575L,0x7fdd7856cc45f810L }, + { 0x68c0beb1c0ae384dL,0x21955de8fe63d58fL,0x1b98e3951c08bbd2L, + 0x5ddaf7e9638701b3L,0xefc264f1b1242d62L,0xa9b8de5c81292443L } }, + /* 50 << 280 */ + { { 0xf0d713b7131a3bf1L,0x690ae8c147e9f09fL,0x1dc92a5f8cd8bf1eL, + 0xdf98927ad61f5445L,0x729b5469ae795eabL,0x939b391c5265675aL }, + { 0x5d916c6c7bd7e97aL,0x7c2a3de5d514e72bL,0x0660758379e9915fL, + 0x0554d5e543a4d2c7L,0x37eb7f82ca5bca41L,0x90e41b71b640109dL } }, + /* 51 << 280 */ + { { 0xfdd403b0e6f769aeL,0xa67f97f6906a7981L,0xc86c49be6aa83c6dL, + 0x6177820677ab6d8fL,0x60f77c49916933b2L,0xfa33c528fcb3fe39L }, + { 0x102ffca0783cb589L,0x6a37a394a96ce10eL,0xd17bf1f89eb4695fL, + 0x2a7623af2a53116eL,0x10601afe83af2e60L,0xceebada2582a1704L } }, + /* 52 << 280 */ + { { 0xcbfb50fa57004c05L,0x0d545f0ea7bea436L,0xb7e30eb77071e269L, + 0x435b3df73b845896L,0x48ba27f0b246365eL,0x9fbe883341344f12L }, + { 0xb763df280a87ef33L,0x4f9339d70b5288beL,0xc02770d6e722e3beL, + 0x6c69bfd918e32f03L,0x20c5c05e74c2845cL,0x09fa0928d6f9279dL } }, + /* 53 << 280 */ + { { 0x82f43866962fccc1L,0x92bc5f82278c9762L,0xc979a68b39a39a08L, + 0xfcae204b97c5a298L,0x78f55c7908676082L,0x210e036447c7b09dL }, + { 0x24512cef47d87769L,0xb4b0fdd7e4b53f4fL,0xc2a263fff6818efdL, + 0xfa160dc1985bc93fL,0x7b7f82961bf44affL,0xd6c75fb2a6407cdfL } }, + /* 54 << 280 */ + { { 0xea0b6ec35741c57bL,0x9b148c2668ba5fd0L,0x6206025166461969L, + 0x0726919f8cfc618eL,0xf66ac684c1954bcbL,0x160ad0260273adb4L }, + { 0x0ec10cffe6f6aac3L,0x232fc7adb4f64d98L,0x0707cb6e73564063L, + 0x76daa2c5487a29acL,0xe4ffd6e335768176L,0x4ab87262464d126eL } }, + /* 55 << 280 */ + { { 0xdbc1d21c553f05efL,0x16e950d0dc115e4cL,0xa727059a354480a5L, + 0x32df221efd6711f1L,0x06f9bc2e5c8aa9fcL,0x9f2449a67b15522cL }, + { 0xac14774bf498ee00L,0x02b5979f3ec7e0a2L,0xdce96e06e1e00abdL, + 0xd7a1bf5a1e00e8a9L,0x19b30fd3a8f42042L,0x29b08eb7e7c507ebL } }, + /* 56 << 280 */ + { { 0xe91477d3a66b2f3aL,0xf50d3bdfc4deb7f5L,0x19bf2857a1e45e44L, + 0x1c104e3270a2126aL,0x4636b4894357b9f5L,0xf65e5aa0962d684aL }, + { 0xfcc83a5fb7b52893L,0x8451d02b08adbd4dL,0xf0fb410c19f7a896L, + 0x6b90b0faff36caeeL,0x111710d0f5af8966L,0x00a4cfafbd2b8c59L } }, + /* 57 << 280 */ + { { 0xad9f11cb817bd227L,0xe4733a1465d27b5fL,0xeda46e8dbcf76526L, + 0x8db309ecad57a5a9L,0x4a863ec07f1487a8L,0xb0453ed210f1c4c1L }, + { 0x9b4df78af2dbfd76L,0x62af38b21525e18cL,0xe6bd0b0ade2c7f65L, + 0xad62bfb70b27fad4L,0xd21fd4346d6a8a5fL,0x07b606703e401a5eL } }, + /* 58 << 280 */ + { { 0xdd14c891e34b192cL,0x6ddfcc793aed3e36L,0xc89c3e6dc49a92e2L, + 0xa61954fd6fcf1ce9L,0x420c39a9bd297157L,0x57c20a8a406d3f2fL }, + { 0x7ccda02263faf545L,0xb01814a96cca4388L,0x88baf1dce5fb1fd0L, + 0x9e1183cfa0bae755L,0x3fe540badbc243c2L,0xe50d52305aeb26a3L } }, + /* 59 << 280 */ + { { 0x10145b3d52726a98L,0x7236036869e333fcL,0xce9a409323a6f608L, + 0x61c121dcddd11095L,0x3349b30a0d39f1daL,0xd07df9d4e3485e93L }, + { 0xb4c500a561159e84L,0xbc74918100561c03L,0x8f27e9f3904ad807L, + 0x7272786a0108ed01L,0xcf36a5d9c9365dd8L,0xe052fc9d7f859d87L } }, + /* 60 << 280 */ + { { 0x0e6cd863da97e11eL,0x5b058c6852a818a1L,0x7768c5e73de760b3L, + 0x898b7f608dfb4142L,0xd48130977efec180L,0xd7196cd758279538L }, + { 0x67c451fb816858a1L,0xbf0e88912ac699b2L,0x21fa74effcb126a5L, + 0x1f9dc10123b8df5aL,0x38aefff921136ffcL,0x3408874c47cb395aL } }, + /* 61 << 280 */ + { { 0xded9035213054567L,0xc61d0628c58c633dL,0x73ff2589f31143c3L, + 0xc43594ff0871b05cL,0xcf662dd64db0edf2L,0x6bac019d8d1f33b0L }, + { 0xcaa37cd8bb379461L,0x9b077a6934fc0269L,0x421e716788ecedf2L, + 0x2d422f95073284cdL,0x9a353114bbb2409cL,0x99e8c7a0dcbb79e7L } }, + /* 62 << 280 */ + { { 0xfca254cba21c40f0L,0x4945c838e0f4a032L,0x99318ff3fd6cb7fdL, + 0xc631e0644a85e726L,0x2e3ca11d9359e8cfL,0x433a0e5c06acf935L }, + { 0x665c54c996b37ea9L,0xe78865c4c2d52b81L,0x68596f6ffb27850aL, + 0x7e7272221277995eL,0x602b0f5c197344c2L,0x81ff2ad620a9ec11L } }, + /* 63 << 280 */ + { { 0xb2ce6cbe7c4c464fL,0xd7c11ef5741a4b1fL,0xf3f987f621a7eb17L, + 0x6b2812ef79f4e274L,0x3a0117ae38a7d5ddL,0x5d8c75a9cfab6bb5L }, + { 0x3827c04052394166L,0x897eb181e00e621dL,0x6693817f8aa19361L, + 0x67cac329959d81a8L,0x21e7133869a7ca51L,0xa02fd11269a46a87L } }, + /* 64 << 280 */ + { { 0x7f1f985c022ea83aL,0x90a22662a7584e7fL,0xb40a930a5188fcf6L, + 0x3fad79aba3a82904L,0x7bee8d22f3151027L,0x79a1a838c2c3e17bL }, + { 0x1fbe06e933cc3509L,0x629c56aa9abd5ccaL,0xfff290ec2d9cf7a5L, + 0x5d0dedaa9bd062c5L,0x080344abd7d35381L,0x0848373af5cf9edaL } }, + /* 0 << 287 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 287 */ + { { 0x31d31f7a7a0c0bc0L,0x7a37a84ab251d2bfL,0x1793362e52f04d67L, + 0x5808e70921c7b651L,0x33fe9123ed6f47f6L,0xdeb1dde958f71405L }, + { 0x821d3045ae56b472L,0x9f61f761e02043adL,0x932ddb145b2048a9L, + 0x17d989fed7811330L,0x032ae4cb128fd85fL,0x8f1956b47d1ef434L } }, + /* 2 << 287 */ + { { 0x070d34e116973cf4L,0x20aee08b7e4f34f7L,0x269af9b95eb8ad29L, + 0xdde0a036a6a45ddaL,0xa18b528e63df41e0L,0x03cc71b2a260df2aL }, + { 0x24a6770aa06b1dd7L,0x5bfa9c119d2675d3L,0x73c1e2a196844432L, + 0x3660558d131a6cf0L,0xb0289c832ee79454L,0xa6aefb01c6d8ddcdL } }, + /* 3 << 287 */ + { { 0xe5d473dc7521f457L,0xe9ef09bda00be577L,0xf6d0965fb6eaa640L, + 0xeb49486875726560L,0x452116d528817302L,0xf0424fdbfbde3597L }, + { 0xd6096da3bb454915L,0xde48280841422141L,0x7a1351972d19fac0L, + 0xdc9a5ec421393f6fL,0xcabcc1e3eb2c8adaL,0xd436643142d8c4f2L } }, + /* 4 << 287 */ + { { 0x0ed1082f89e4e449L,0xdb1fb471833f2378L,0xa35fef0eece77352L, + 0x76adaa464bf0c426L,0xfbab929aa011b2fbL,0x6f475d5b9d8cc4d3L }, + { 0xbe6d7f2174351480L,0x2d1362d193e4a7aeL,0xc7e2cba5106ceaabL, + 0xfe94528a45258697L,0x7109b17d075945b0L,0xfd395b2ccae17f7aL } }, + /* 5 << 287 */ + { { 0xdf534b80dece6d4dL,0xcfaa60a28737af46L,0x7d76a921b9ba3d56L, + 0x61490bd199338721L,0xc514e950ed25cfbdL,0x5041fbb2dc09b8b1L }, + { 0x2410310d46fbcbf0L,0x2c46bcd14f7e8aa4L,0x08ce31f5d0d5fe1dL, + 0xb11efdbebeac3c97L,0x406e1d05b01633e9L,0xde48cdba766391adL } }, + /* 6 << 287 */ + { { 0x68550299845e12c9L,0x979b5406361d027fL,0xf601d2b4a8e92e70L, + 0xfd02799f0cc9fca9L,0x89f99ca013bc2e96L,0x22a12c0bff9db9b8L }, + { 0x6ae7084a32efcea8L,0x5ddd3ee9a24b9376L,0x394d92a4e0945e8fL, + 0xddab6752ecea36f6L,0x650b74d60d18a069L,0x37f91cebad650860L } }, + /* 7 << 287 */ + { { 0xe3e559bd9d839b3aL,0x50e8d4e9719de3c7L,0xf7bb377cea70b986L, + 0x63753cace1b2707dL,0xeb239a870e585c4aL,0xec40a379b0e32380L }, + { 0x836ebcefc86d6685L,0x703c296a70d18b76L,0x47e2c004b94aa268L, + 0x33ef7d0cbaf14d61L,0x74aa00fcd315c72cL,0xf23c789eccf5d75aL } }, + /* 8 << 287 */ + { { 0xfc1faedc310404a8L,0xea339148d3bcb128L,0xf00485456416defdL, + 0x75de7770c58653e7L,0xdd2dcbebe2f6f99eL,0xa4380ef4d159ac07L }, + { 0x45dd713ce4173608L,0x44919b61446a6789L,0x3f73756b6b962b38L, + 0x3cb9f53bbffd3f0cL,0xd723c40b7f08ebaeL,0x998a9b170c3cddbaL } }, + /* 9 << 287 */ + { { 0x261c9fe6f21ae889L,0xa589147edf3cb243L,0xd09452f71976deecL, + 0xf80ee8bf2497f6b2L,0x0b5f1b19eee697d4L,0xce9b6b680de48ab7L }, + { 0x3ad3bbc4bbf29546L,0x544406a697f51becL,0x51d44dfac2e2e75cL, + 0xcfc8625d3da3f634L,0x0845ace6a1f5995dL,0x11850d8bf3b65c55L } }, + /* 10 << 287 */ + { { 0xa804b2f089ef2489L,0x06a2a805fb22f7d6L,0x31baf4fd353970beL, + 0x3481c8b712854a91L,0xb0424eecf3971398L,0x748ef3820f4ed94aL }, + { 0x92b74ad026722164L,0x23f71d5831b1302fL,0x6741b28070a5f0c9L, + 0x46c12cfb9f5101caL,0xe7014d7901d0f81eL,0x129bd87ad758c288L } }, + /* 11 << 287 */ + { { 0x6c43d8307b00cd09L,0xb794cb012141eb00L,0x95fe13a75cf23ec5L, + 0x3de5ad7b8f2c799eL,0xa378434a025de83bL,0x07f681bba3a14a3cL }, + { 0x8fa0b5d2983ba419L,0xe477bf361781bf08L,0x5b8162845e8ce6bdL, + 0xb36a78ee199ec8eeL,0x444fc01a6062d5d1L,0xc026ab4586ee9ac2L } }, + /* 12 << 287 */ + { { 0x6a565269a3e0c5b3L,0xaab7ec7104c6ae54L,0x0bda11a7d8c6ddb8L, + 0xb7ebfafb2332347bL,0xcf791881e99dff48L,0x81600214dc357c83L }, + { 0x2a264f8931d7495bL,0x8ca430004ec885a7L,0x6d478260bb47d417L, + 0x544de4ec3d817032L,0xac7150a9dc05f901L,0xffef225775c0963cL } }, + /* 13 << 287 */ + { { 0xacb83aadb65296f8L,0x04c96c3e18151422L,0x8913311e7a9f126aL, + 0x3baeaf8010b74e8aL,0x253c9dcbb7410105L,0x30a13e42da2d5437L }, + { 0xde31fd5533a2065eL,0xde2caf1ffe099595L,0x54c762fe795076b5L, + 0x8beb51fe635ed402L,0x369603c1e5c3d2a6L,0xc5083f0700a472b5L } }, + /* 14 << 287 */ + { { 0x58805ca8d2eaf294L,0x910d085ed7d5abb8L,0xf9cbc9a1349cfecfL, + 0x67bc7b417800a980L,0xe7e6dbc0f6847e9dL,0x7a0f22c4af379c48L }, + { 0x80b6fc04b1d2822fL,0xa1cae656d8517a70L,0xd2d11ed14e9dc24bL, + 0x48d74f173fab87e6L,0x1feca5af50c630aeL,0x263e04cc62d0620aL } }, + /* 15 << 287 */ + { { 0x7dd330ca16b2a52aL,0x25133c614157ae5bL,0xe6ee0e4edd606b2fL, + 0x700840423f2b59a7L,0x58d27587d03f54eaL,0x62ebc668d34605e9L }, + { 0xa764392ab3155e07L,0xf0810f3e3c6ae6c8L,0x1b32e5ae94614cd4L, + 0x45b49262b9cbf481L,0x0034db795b3d1184L,0x463237825b1b9ab9L } }, + /* 16 << 287 */ + { { 0xf6377e3bf6ba1469L,0xc334fb6c09c832d3L,0x7f85ac42c21c0cf1L, + 0x7a3e31c9857d8edbL,0x2eb1076327b77ed6L,0x2bfbbdbc38dae10bL }, + { 0xed7c6fb17bae3b4fL,0xc5911d9f36d04e6fL,0x4dc435504569e72fL, + 0xaa82fb97bedae3abL,0x06d37bef4f27e463L,0xd0dbce6df0c35a11L } }, + /* 17 << 287 */ + { { 0x4482c7b704414726L,0x72c9cb5b26d23eabL,0x3747b8cefd5cb171L, + 0xe4ecabc300312ffaL,0x5909f29b9cf10a38L,0x209bc3f4b8d0e5acL }, + { 0xd34c84db60fac147L,0xd64dea89f8938c89L,0xb18285f8b815267cL, + 0x719a7e355a2437d1L,0x45f8d9dab769c5a2L,0x2d0e4281a412cfccL } }, + /* 18 << 287 */ + { { 0x23c14c43d8f6e236L,0xb14be0d28ee39386L,0xd3c55814262dd390L, + 0xa1b40401e1f23d0bL,0x1377b07c61534375L,0xfe4e3eb116f6d95eL }, + { 0x17b1af0040b4386cL,0x2dc657a837ca3851L,0x6862ca92ef976731L, + 0x9f0c380ba4118d3bL,0x23bf793977c1aa94L,0xaadee0612bc27d4bL } }, + /* 19 << 287 */ + { { 0xfa5e4cb6f1847a9aL,0x0e13a60cba6f07f1L,0x68d9db450ac86498L, + 0x44b02de3920ff013L,0x43724c2d84b46078L,0xb3686ee81f951b93L }, + { 0x019b3e77d712fe85L,0x313e7b7497dfb295L,0x7d883ed826d50e37L, + 0x64815565d32562ddL,0x2f9e48bed7b3e2f2L,0xc97cf156dcb93450L } }, + /* 20 << 287 */ + { { 0x0573d9963ab4c707L,0xee5d87691420fdf1L,0x41873aa55e2b9c12L, + 0xe09290456810bf08L,0x4ff4143fccbe4bbfL,0xd0e5a74969328301L }, + { 0xab5912621c4b73beL,0x550ea0633f3edf99L,0x8a77633734c93db1L, + 0x5c51d3f832b21521L,0xcee9f604713feea0L,0x0d6f8a5a7bf4268eL } }, + /* 21 << 287 */ + { { 0xc415d467009a0cffL,0x32dd46ef55960242L,0x4ccc6f676d6a81b0L, + 0xa860bcb6b2571d81L,0x7e74150991f9b6c9L,0x9a96b2f9d3a0592aL }, + { 0xcc3d821071248929L,0x586062daf1cb0f52L,0x18d993483d48b6c1L, + 0x667f17949f4e612aL,0xf1d7a77ffb3a12e9L,0xf7586397f5753220L } }, + /* 22 << 287 */ + { { 0xb87d5ce2722f405fL,0x24d1f993d7c6a322L,0x09d837291e0d8113L, + 0x70b5cdbf89a6cbc3L,0xdfb3ee16fb2c9607L,0xf0acc1163465c7c6L }, + { 0x10cef4b707e6659bL,0xc280c4331fde9940L,0xc8b5e9819a2d3f25L, + 0xc36faa763f7f68c1L,0x17878bfa8d54e281L,0x8fda8b359c42c5a2L } }, + /* 23 << 287 */ + { { 0x2aa1366305d22d7dL,0xee77da6eb0c62a12L,0xff8f99c5bacad876L, + 0xcbe33479f8a0f0baL,0x4c69bd7f4a232c8aL,0x760ce3fd485d3f48L }, + { 0x0b286a59268d7411L,0x2dd746b6589819b9L,0xe017a53060ce76f2L, + 0xe4407828d642a7f0L,0x12761e51b6badaecL,0x4f4f286b78d07257L } }, + /* 24 << 287 */ + { { 0x43c78835661019ecL,0x68e916b124e66d29L,0x02c0f3a224094671L, + 0xab6f1c05d0f17d86L,0x6d3bac72a22d4264L,0xd7b8f152f6e5fafeL }, + { 0x95627c6339447eb3L,0xfd15901879e1ff93L,0x39277c835ad80806L, + 0x758aafc90d7c7b74L,0x605ad8ca4cb8bec9L,0x6a90085c5741828aL } }, + /* 25 << 287 */ + { { 0xbc11d3d559cdebfeL,0x75c31b4531b2796eL,0x8d11e18a07b1055eL, + 0xcf522c1fb2d2986dL,0xc994c377eafcbec6L,0x840d27ebc0c0e2f0L }, + { 0xd4124d17859550d3L,0xeea6047aba21b2b6L,0xbd2a036e335a2854L, + 0xd8703d6b207ac2e5L,0x09d2244a94a34bbbL,0xd6b9481417ec6f44L } }, + /* 26 << 287 */ + { { 0x7d8ddca252aa7ff2L,0x0985e47d6953b9a2L,0xed328993dfff63ccL, + 0xbfeca5327cfa6ee5L,0x7535a871b1e6a010L,0xb0052764303c2ec5L }, + { 0xd39c72102fedb0daL,0x7ee2b384e1001505L,0xb638a1b1c82a7e1cL, + 0x1b94a47b4573fd7dL,0xef2bca7792cb2b88L,0x49ad6e97a75b21efL } }, + /* 27 << 287 */ + { { 0x591bdd0d8f4093abL,0xa2c63f1ba1322343L,0x5e548f71b32a4331L, + 0x9930891c5e7f3c14L,0xb2b2406e54c27043L,0x7ffe3e5ef1281af8L }, + { 0xc31ba363900742d1L,0xf24c8ae1e61ee209L,0x687c56b7beed46f4L, + 0x0b63e47895682562L,0x9117cf4c0c8a45a8L,0x0744a86824c20748L } }, + /* 28 << 287 */ + { { 0x9ac777993acb39ddL,0xd1d3ecddbb7c6a8aL,0xa5271c9e7a75159cL, + 0xa6ffb41f2c276e4dL,0xc526556e0bb9a955L,0xa32e1352233b7774L }, + { 0x103f124bc2cf09aaL,0x1816d1eff10bae5aL,0xc5f9197ee8837629L, + 0x064d5dcb13b1b76bL,0x109c70748d0fe0b1L,0xbb4e9743fce5f6e1L } }, + /* 29 << 287 */ + { { 0x4636f36d3ef05af6L,0x3695267b3e498920L,0xd59830285d773fc8L, + 0x939591245d3cc515L,0xc3f52a9569134370L,0xc9d0db7af8848992L }, + { 0xcd1be9bf15906eeeL,0xa95d25fb916d576fL,0x08de893be152fb62L, + 0x65d743658ab1e35cL,0xd6d97057fef14ac1L,0x67ad47b9574508c7L } }, + /* 30 << 287 */ + { { 0x1b403c4f1470433eL,0x6f8cb19257e53eecL,0x87b5b93df0cce4f5L, + 0xfefaa5008c566f77L,0xf6aa8066db71517bL,0x9f01b036d67f5952L }, + { 0x9524306faaeb40dfL,0x5cb2e8e1421350a6L,0xa57d05ea3d69040cL, + 0xd0ff12a1b9bbdcd8L,0xed64d3259e3e19bbL,0x29509c0fed0a490dL } }, + /* 31 << 287 */ + { { 0xc94191e7a607c050L,0xb918a096b98d3d4eL,0x97413dbce3f253f3L, + 0x8476c03cdc6d8418L,0x50247d1d2402202dL,0x077476225f8097c5L }, + { 0x1457ab609b71c6d6L,0x9ff312c447cf0c94L,0x954dce23ee79d2bcL, + 0x3ba2b1a4a0da6e48L,0x363df36f532be9f6L,0x816642ddc742c7d4L } }, + /* 32 << 287 */ + { { 0x6edf5561ff8b1fbeL,0x614b788ef6eac0c0L,0x7699ae56d8d66d29L, + 0x5f81602ae9d58eb2L,0xd0c04874faf9176dL,0x4b3a0046523153b1L }, + { 0x9690930ff6315883L,0xa81c0b44a60ca92dL,0x2d0e725873bcba90L, + 0x57efe72de902e329L,0x3fcd598676bc27b9L,0x492adf0393940c09L } }, + /* 33 << 287 */ + { { 0xf2ab8e22973a4b6bL,0x6a96f2ef6ad73ce7L,0xad5e22547235e929L, + 0xfab3e4a9bc6c3b76L,0xf69fb2062dc950d0L,0xd863ca9049478ff2L }, + { 0xec669f122749fabbL,0xe1d28bdc71a6d279L,0x766ee6458372942dL, + 0xd118b90480ade5ccL,0xedcfb0a72293740bL,0xa3ee3a67f16b29cbL } }, + /* 34 << 287 */ + { { 0xc29fb53e118a0c7dL,0xea7a1017193b834cL,0x678072a2cec93ecbL, + 0x9054d6b72475dedfL,0x4a7d477342ee616cL,0x05cec7f8680f8a43L }, + { 0x39c491d496915870L,0xe07a2b1d8746edeeL,0x1d8ed3c83566e7fcL, + 0xc7d744e5e002298bL,0x8a0acec99c0e6388L,0xb2daac39ebf48fe3L } }, + /* 35 << 287 */ + { { 0x773ad1cb8e133d97L,0x1e29f5a2872523d3L,0xa2a742293a09c1ffL, + 0x809e6d284369ca06L,0xf22e521a7fe148caL,0xbaaf90c383ef9578L }, + { 0x65aa9b54d633b2d5L,0xe55f2ce29a2994a8L,0x8a0af446e67e0b85L, + 0xb9714de9c1f062c8L,0x1f4047dd2a3aa1d7L,0x39658ea965179222L } }, + /* 36 << 287 */ + { { 0x0322b29a57fbc5cfL,0xf55af7863078be9cL,0xd4b186e6ecb59f79L, + 0x50f5fe746d950733L,0xaf8a1898a9f90d02L,0x483801a742d6d9bfL }, + { 0xf0a0af145ec09c0eL,0x85af0e6188383360L,0x404b295e42592235L, + 0xb3199d63c596493cL,0x7aadacdb194abb80L,0xac84563ec1c845c6L } }, + /* 37 << 287 */ + { { 0xd78d1dae5336e58dL,0xa3f36e0bc5ff354fL,0x8421f95e5d1ed78cL, + 0xff4c16019f360c43L,0xd5efa09f8bb582a1L,0x0ece005aefb39652L }, + { 0xce8bb58036c2c940L,0x11f8f74bcd1ae8ccL,0x923c350b57a2f2b3L, + 0x2438e3213c86faacL,0xe76129503e230776L,0x35c73d415e6158e2L } }, + /* 38 << 287 */ + { { 0x8ffda4643672507aL,0x76301be7dd91327aL,0x42720bb0958860bfL, + 0xedc0b8945ad4f455L,0x2fb553201bfbeb4dL,0x22a425bda1c6494dL }, + { 0xfb927a85de0e7f52L,0xb84a82cf49a4b6a1L,0x8afd0546b640fe0fL, + 0x23b78fbed2fc15cbL,0xeab469c26742a49fL,0x308e453fe277c7cdL } }, + /* 39 << 287 */ + { { 0x60ce0f55af7b14aaL,0xf2577fbe5cf5a2caL,0x7bb9521fabf3bb41L, + 0x68b6409def00287aL,0x700bf423bfaf9391L,0x98e6c3017d637300L }, + { 0x342ed4870ce28aeeL,0xad8b8dc383b059dbL,0x1b8a892b85d0a485L, + 0x553c4fad6b7a7d3aL,0xf5692acc198d0379L,0x6004ebb3ce932f00L } }, + /* 40 << 287 */ + { { 0x6895dbe2f820c195L,0x3787a5003f6c7b40L,0xdc718243ac1e90f3L, + 0x352f8c91ba5d0870L,0xf3d1c53eec0112b5L,0x08a0782f6b84f64aL }, + { 0xd659e6358eedd5d4L,0xfc30df6c29537276L,0xbfb09978a1755ce0L, + 0x227f7b12aa2b4187L,0x828730b9226539d2L,0x9051a37cb2472c95L } }, + /* 41 << 287 */ + { { 0x430c2a45d0a0ddabL,0x916aa68926a6291fL,0x9db5510268dff24fL, + 0xa22121c1850a7aabL,0xd43416194e2d9670L,0x7ef2cb9415cf7636L }, + { 0x2cd6ddf6bf97b27dL,0xac5676b625aba9c0L,0x3ca96f7ec4ee110fL, + 0xc6900abd08e7ebb4L,0xcd3942fbdcb91135L,0x62d6b6f6a8ad56e2L } }, + /* 42 << 287 */ + { { 0x1ec7f2410828d35fL,0xd94c2a926ccae554L,0xdf4227273c36ecedL, + 0x2facd6d89fa6582bL,0xed43247ed349d3beL,0x1d59d55d1db6fcc6L }, + { 0x2b5074b1ee1bea38L,0x025496aac9c21a8fL,0x57dd7fa1d1d817edL, + 0x57b5572aead03124L,0xdc024be87314616dL,0x5bb5b23c10f6e38eL } }, + /* 43 << 287 */ + { { 0x643cb9cd53812134L,0x016a11e8092ff9b5L,0x227f3dfbfcde37bfL, + 0x01b9bcebe8a8fc6dL,0x7009ae45e1da0dd6L,0x193b6f519e2908f3L }, + { 0x28656302230db5feL,0xb0a730c41aaeee73L,0x028320ab387addc8L, + 0x92165d909a92488cL,0xb0b2f8f09066c95cL,0x0fa55db564007634L } }, + /* 44 << 287 */ + { { 0xbff4fe0844284b10L,0xc7e3f8da19c2f775L,0xdcd97e54a45ab746L, + 0xf53158a9540ee8a5L,0xfd19068728c4aa74L,0xa3447e30648fa2e1L }, + { 0xa6794670c374cedcL,0x605629c258204248L,0x1b86f8e6f7d8db3dL, + 0x1e8ffe8bff0f38c9L,0xe4a556b8e274c82bL,0xb31406c94c0076d6L } }, + /* 45 << 287 */ + { { 0x198999821e555a0cL,0x831e923fbc196442L,0x8b294623f682e135L, + 0x79ba90c01743c6e1L,0x74f8dbafeff5ed22L,0xe4c3257d5c010835L }, + { 0x9cf94a208f9ec66bL,0x9fe9da3ddc303c43L,0xa53870be0cb716daL, + 0xc322ffaa2aef881dL,0xb9ff76ff0fcd5580L,0xdcc125d49ebb1d7dL } }, + /* 46 << 287 */ + { { 0x747b6b6ddecaf88eL,0x1a32f8ba368cc7caL,0x52a3a00f60d84fd7L, + 0x60052af507adacf7L,0x8b7bf25650b8de16L,0xb8b2acf8194926baL }, + { 0x4bda72c81d1ef524L,0xe350f73288993f96L,0x63fee4e2e08c5d39L, + 0x1f2cd9cd5db46904L,0xbf11ac311668d3bcL,0x8eaa064371d721aeL } }, + /* 47 << 287 */ + { { 0x33cfdcb3e14210feL,0x4abad5ec4946aa01L,0x14b42417a8cb53b3L, + 0xeebb0d70238d4edfL,0x8c9d87fdb5bdb30bL,0x3cc680f17c928b33L }, + { 0x4b2b2358757c2607L,0x51a70a33c1c8dedfL,0x62a26d776b22d113L, + 0x2f4acd62ef3b4f5eL,0x403e91bf6ed00636L,0x219ba3577bf74d3cL } }, + /* 48 << 287 */ + { { 0x7de743e2b39317b8L,0x9205d4472d372acfL,0x8226fc303eeb0012L, + 0xab2a3e052af74be6L,0xbe4767804af91ac0L,0x98497c710ca36bf4L }, + { 0x74fdf7cd8d6dedb4L,0xb50778eea0fc5919L,0x5d5ec33f2fcd7c63L, + 0x667b81937f33cde0L,0xce48ae4b38364d44L,0xb8578963223ed67eL } }, + /* 49 << 287 */ + { { 0x3e5688e46bfd7adeL,0xb3f1eb051b80bd4bL,0x8626c4cafe3de456L, + 0x8846bc714b7e5444L,0xa54c7cff689e8a67L,0x8c3ea61f43eadcf6L }, + { 0x924f17d6fde15178L,0x45319eb705c08d2dL,0x6d55775d9f85dcbcL, + 0x2aaf9f7405278280L,0x574a13e77b617153L,0xe7fa921ae8b15bebL } }, + /* 50 << 287 */ + { { 0x9dd54056514e343aL,0x8d9116dff12aa25fL,0x5322ec38e3397844L, + 0xe1843921571036a1L,0x2cde0a48650beb19L,0x41ad4a7e4f259728L }, + { 0xf314fceeee6448b2L,0x80006b2aff0e81f5L,0xb5ee5524d51d229aL, + 0xeba6d733128e900bL,0x79278cb8030f391aL,0xb24bcd63a9a5f9fbL } }, + /* 51 << 287 */ + { { 0xed867a7b37d10743L,0xd57d2d8df510023eL,0x4d500e4c737e0a50L, + 0xcfa119900ecbf795L,0x3ac126b89373bdaaL,0xb06324fb735449a1L }, + { 0xfe321df5cd79de70L,0x52d625dbfd07c6d4L,0x88ff505a3d628e51L, + 0x120350fab044d725L,0xf718b20ad02f9515L,0x766698630bbea1b2L } }, + /* 52 << 287 */ + { { 0x6293e0ff50d9bda1L,0xe7259ada433b4dd3L,0x39aee63e821cee67L, + 0x4d707c7144b10739L,0x42b9e0f69bd6efc3L,0x7d71edcc0717a61dL }, + { 0xe7df9e56d1e5a5bcL,0x7895b638ddde509bL,0x6fc597b3d2a6a822L, + 0x022da65d96d2a8abL,0x95541ce7cff45c72L,0xa5bb7799e649800fL } }, + /* 53 << 287 */ + { { 0x7472e4c963676cd5L,0x2836b1d52687f376L,0x1460b664f732a51aL, + 0x7c4541f22a214ae1L,0x743a524d107d6622L,0x9c64e3ff082fc015L }, + { 0x9341f3fc8e0d13bdL,0x9946043e529554edL,0x6fbbbcda5798d6ccL, + 0x3bfad5fb242115c5L,0x1f46bd1945ab793cL,0xd9383bcf3b42f81aL } }, + /* 54 << 287 */ + { { 0xe4ff888f820a13b5L,0x7cd18b3eaf1bfbbbL,0x3fb7f681bd4e4dd5L, + 0xaba364c287d46c40L,0x44e209ab659b3498L,0x5e071a272dde85c1L }, + { 0x8a029b1fb969c790L,0x51bab9f0c6fd1c22L,0x9ee9b047b83eb0c1L, + 0xda0b39439e5b2c35L,0x0cb30625f20ca425L,0x8e4dbd013d25c2c9L } }, + /* 55 << 287 */ + { { 0xe7aa41a96b8f7599L,0xe97ff24a3f556ad5L,0x10e07713dd6a9329L, + 0xaf464b18c4d06a93L,0x9b8e5145a1ccc85fL,0xa256680bd0487ca6L }, + { 0x420b60bf815652f1L,0xeaf09eff5bb45b6fL,0xa31e875f8845a557L, + 0xb035ee09eebe0911L,0x1402d1d86531c356L,0x24aeeaf0b630f75aL } }, + /* 56 << 287 */ + { { 0x4b20d1829567f5f4L,0xde7e814918f02b34L,0xc9a4be7becff9dd7L, + 0xe2f70bbe9812fd3fL,0x471bf90c9c889263L,0xb60d01b53e61f5bfL }, + { 0x258c7f89d22d855bL,0x35ef5c15b75a7d4fL,0x26d8e1dab247f27dL, + 0xcf1361998d0f7757L,0x312447803f8e894dL,0x8d2a20bae1a3d47dL } }, + /* 57 << 287 */ + { { 0x6447cc97f08a0417L,0xd98ea6837afee809L,0x81426d20bf7990aaL, + 0x848bd6223526ad26L,0xb6cdc5b4fe1f3381L,0xe7e10bc7a26189ecL }, + { 0x25a9f7cf57464e6bL,0xf90c1aa12c86ddf0L,0x2126ed530124705fL, + 0xf384e7e5b58e6341L,0xb2dfeb0a12207e57L,0x72875c55e0e23287L } }, + /* 58 << 287 */ + { { 0x37579c3eb954b7a4L,0xf0291f8f3f2ea608L,0xde68104f90a85ed2L, + 0x6a35fea9e1088788L,0xe8d5517470d15d00L,0x0bc72de552467f90L }, + { 0x2ded3293297be2b8L,0x76c53e5761ddc65bL,0xae4b2b5015562d6aL, + 0xfe7cdd329e0aeb79L,0x98ef4c518dd474ecL,0xfca56ffb0076b23aL } }, + /* 59 << 287 */ + { { 0x120adcba6f60309aL,0x41e46edeca8ab2c7L,0xd68aa4c529b79ce0L, + 0x21a21f8d7a3b11fdL,0xea68dc4739d0809fL,0xd4faa71a27973044L }, + { 0x65b42172810be134L,0xb2dafa6c793aee92L,0x951e9f6f1f78f7dcL, + 0x2affc70a17fdba97L,0x4f0f4c51dcaa2789L,0xfde1951c9e703980L } }, + /* 60 << 287 */ + { { 0x80826a196488d9d8L,0xfa452795f3ad867aL,0xdd9bf8f5bd4e6674L, + 0x324386227e8e3ee5L,0x7af4c605dff05c96L,0x79efb6f9541cbbd2L }, + { 0xeb5ff62675e78961L,0x5318c4c30be43d7aL,0x02df456daa4a0562L, + 0x4d6002d88a916a81L,0xf0dbc349f68eced2L,0xfd75d4d5ec8c3fddL } }, + /* 61 << 287 */ + { { 0x6c15d903544378f3L,0x0a9bc9d735ea3c77L,0x9d9066408caa4acbL, + 0x9ba27502402be833L,0x1ed4123f8773fd7bL,0x236364ba190eac92L }, + { 0xd6287f17f8383ee1L,0x75b7b0b5d9739582L,0xeb6cd50d0292806eL, + 0x216f36dc43448409L,0xec136f8cb6c4958aL,0xfa805ab49ef7810eL } }, + /* 62 << 287 */ + { { 0x5c6448f70d00b29aL,0xaa134b87124cd55dL,0xc2c6b269d94b72d9L, + 0x0f0dd472412f76d8L,0xb4cf3c1873f6571aL,0x6aed00218b9218ffL }, + { 0xa55b74eaa0c9dde9L,0x59b952125b4c8fccL,0xbc9873ea4ddc367bL, + 0x26b369ba0fd30421L,0x71763a45e446f4fcL,0x67e800edaff54707L } }, + /* 63 << 287 */ + { { 0x4de97de1126b4919L,0xd631d908883ea109L,0x37c77d729f6ec50cL, + 0x910932e6df718c7dL,0xa798406855028d0fL,0x21b09540a6119a26L }, + { 0xb837cceced4b4962L,0x3c83f4bdba66002aL,0xa067aa3d2ac41124L, + 0xa64bff30d08dc360L,0xa22778a5c108d3abL,0x7f732064aac4dee4L } }, + /* 64 << 287 */ + { { 0xc68b641ec795a2c7L,0x4fe559b15a4d6647L,0xeda98cbad89ce668L, + 0x15f84dc06c269d8eL,0xf0eb685ecbf34023L,0x3668c530c032634aL }, + { 0x2e3d7fffe4531f59L,0xe627030685494d06L,0xf02cabcfa3e050dfL, + 0xccd2da67c001dcd9L,0x50aa3723066d2d52L,0xdb0756507224a41fL } }, + /* 0 << 294 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 294 */ + { { 0x04418b5965b55050L,0xa8a797c3d324aa67L,0x5f87e22c7c65a6d9L, + 0xaac710651dbeffe4L,0xff619d64bd3cc05cL,0x9a29c966e65c92c4L }, + { 0x23af2b21dad7fcbdL,0x4950a767153b817fL,0xc34a7efac6478c55L, + 0x57cde95af6cd140eL,0x64b74575f5a0db2eL,0xd4b5ea5275d7fb76L } }, + /* 2 << 294 */ + { { 0x284050628e72aafbL,0x655bf3538ea8bf00L,0x789d944405547f7bL, + 0x7fa445ed3441e472L,0xfeb198254a44ce87L,0xccb5f12c129aed14L }, + { 0x22b05de3af94fb34L,0x7422a040d3f03199L,0xfba252caa83f7f08L, + 0x0f6ad6e6cefaa757L,0xe1ad18716517d806L,0xd16dc8ed8e9d97adL } }, + /* 3 << 294 */ + { { 0x0208092a0e3dca68L,0x9a49bdccd1a09971L,0xe5194181aefab9c1L, + 0xc1c9690a0076f47cL,0xd7499e95b486c2fbL,0x83a69e43d4b72e00L }, + { 0x75f2838a2d1a6c2bL,0x57a24c69751f6366L,0xd956ee08626cc684L, + 0x434cadd7e6ce3249L,0x3d4eaececfe289bfL,0xbbd53b961b8aafddL } }, + /* 4 << 294 */ + { { 0xcbb99194a3736eb6L,0xdd5161cd36dcf470L,0xd50b24aab6ab6c03L, + 0x419d2810bc41f4b7L,0xe2e88d7a295496cfL,0x350713f2f2457ac0L }, + { 0x838e4a360427e2aeL,0x7631472a4d974e5aL,0x9fa3ab1c7a5c5fdcL, + 0x324798cdde34cb8dL,0xbfa5a9d0889105feL,0xd05dad34fd0df249L } }, + /* 5 << 294 */ + { { 0xb47c1d47d6a3a1baL,0x99bb7e6572f65bd5L,0xf251794578abfda2L, + 0x827f2aba3e3e3420L,0x436ee73250e2de70L,0x5c9ac6dc10eca926L }, + { 0x2ec67465181f5e18L,0x1e8f32fcc6c83d02L,0x9dd3aeaf3953bd81L, + 0xca955f4b07086daaL,0x7b4b6f3fd14eaa88L,0x562e75f1148d826fL } }, + /* 6 << 294 */ + { { 0x536e5657cb419fc3L,0xe8c208bc1d271dd1L,0x6a3713bd22d2b9adL, + 0xa4c761a7471d808dL,0xd93aafb67e6dca35L,0xc46c0ae38f55ca32L }, + { 0x55dc0de7a78bfca0L,0xe9cfb3013407d0caL,0x777e2a60b3256c14L, + 0x32b2238c6d8fee02L,0xe8b3539646e43ee8L,0x310bc1ba247985ddL } }, + /* 7 << 294 */ + { { 0xbb9bce6810168f49L,0x32edc368717445e3L,0xb0b5a04426aa3ff2L, + 0xc671f1fcd166542bL,0x3142864df61d2523L,0x11b2dfc7b0c67410L }, + { 0x2e031a05c99690a5L,0x4782fb749fb7bae8L,0xeac2cd506b7175acL, + 0x2e116782bef2313aL,0x67992027241c4d2dL,0xf8aa0e09a6952d9fL } }, + /* 8 << 294 */ + { { 0x9974759c581f9d3cL,0x9e76a970e5cb1973L,0x8afec58ec64941caL, + 0x2d7c57fa01d05575L,0xc07c74cc5c448db5L,0xa52474ce01bb1440L }, + { 0x93162d9700115bbbL,0x483b6147fd7480f9L,0x4f28c57e6af18dedL, + 0x36faed8f174a3089L,0x702dbd64a3dd6265L,0x86a9c43f6adc0d7bL } }, + /* 9 << 294 */ + { { 0x9d4d4b3c795eb646L,0x727e2aa17485839cL,0xb50018a5aa9250baL, + 0x5a15808d1ba716adL,0xb1748d580ff91cebL,0x0131bcff76144b6dL }, + { 0x23fea4a58dcccffaL,0xe8eddb5ceb64caaeL,0x011a65971c3c5e66L, + 0x7723dfba377a8f6cL,0x00167c71dee2f651L,0x3e89ddf5ee0e4325L } }, + /* 10 << 294 */ + { { 0xa3510710b9de7b63L,0x9f364ad14019c9dfL,0x5b66a5d79b5bdce3L, + 0x2b2f695178b1b385L,0x3e4783d33cfa9f99L,0x1af517506bd6bcf4L }, + { 0xf9c0686a81d8d7efL,0xdc0f22ec37c068d3L,0xe1b8665393545fafL, + 0x37ca8501a8a52881L,0x07ac5c8a5603e359L,0x98fb2bab542cc937L } }, + /* 11 << 294 */ + { { 0x96326ec323da6b81L,0xdb48a5e1f90a6f83L,0xbb141660f640a0fdL, + 0xb51609375b92f5c2L,0xaaabd54c997244e4L,0xbeb8ab2f859bb92cL }, + { 0xcac7c5dda4be476bL,0x7093faea7f58c1b2L,0x3167a2c45c6ad412L, + 0xabd86bc9544fb9a7L,0x571296a72448c363L,0x4da64cd9c6cd4621L } }, + /* 12 << 294 */ + { { 0x4981be690c5bbd3eL,0xb047df0a185fdb55L,0x3168e05074cff00cL, + 0x111150a1b52c7f9cL,0x0db2ed84a51c7986L,0x7d991630e61272adL }, + { 0x7443d93628de14ddL,0xfdf31f41a5daed5fL,0x71e0ef4e866b5e40L, + 0x05c57a45b965a670L,0x85bdb58c70e1aa77L,0xe4d1fe2a9df3ce32L } }, + /* 13 << 294 */ + { { 0x6ff2b1a1772c3796L,0x9b88c1178e186fe8L,0x342ba11f4312af31L, + 0x9a93a4d1a86ae2b6L,0x496d5f219d59e3feL,0xce519a7d6924acdcL }, + { 0x6fdef82327c46e44L,0xab5504c34d31c9bdL,0x6fa52bca71693677L, + 0x31221119033c80f7L,0xdb2cb49dc0a22f91L,0x4962d58f9b4aeb5eL } }, + /* 14 << 294 */ + { { 0x5d4618982f722563L,0x11d22b39567db14cL,0x9a8f004e6779cd40L, + 0x0812ae3d5473ecd5L,0x4ed828624e6c296aL,0x2d9ce40c064ee61fL }, + { 0x4856d586d8a9eb1eL,0x2ddd6b125d1b5e3aL,0x0ab5eec0382fba3cL, + 0x302018dffcf4a9c8L,0x7b4e6fd2ab3cdedbL,0x266c246a8f64cb1dL } }, + /* 15 << 294 */ + { { 0x55bad54bd6dc35e8L,0xa43d72ff38642612L,0xe39a191609bc85ddL, + 0xc9d4bc9b0f85d3baL,0x84cd12b61367a70cL,0xf4ebc0e04937bb2dL }, + { 0xd083145949dc027bL,0x110751601cf29970L,0xa443a29c0b76b4c0L, + 0xee5b8d0ca0de3249L,0x368aa3259002e7d6L,0xeb48afdc6182e2e4L } }, + /* 16 << 294 */ + { { 0xc41e4aedf5c3af59L,0xa0284ad06de9a78aL,0xf5eaab7b8ed812d2L, + 0x7801fbb81afb58b8L,0xbe5cdba671efcc3aL,0xe31a0e3ccd10cb91L }, + { 0x882e821e85dc0bc6L,0xd3ad070fbb32e506L,0x3afede2bd8a0f038L, + 0xe20a117c857fd3a0L,0xebaa2aa43060f767L,0x6524aa0d2b9d1da1L } }, + /* 17 << 294 */ + { { 0x86aeca0ffd81174dL,0x19bc6ee60c6eefc8L,0xc85f7f2ea91f0e19L, + 0x09b9276ad2354dc8L,0xb62adee0542a669aL,0x8354ad1a88097445L }, + { 0xe67d2834df9984a1L,0x2330c8cfa64b2864L,0x309dcdeb39e7b54aL, + 0xbbba4737a18cf5eaL,0x47511b1d92861a8eL,0x99d4bd673286d404L } }, + /* 18 << 294 */ + { { 0x9cc5847c88cffe33L,0xff726b0f6e8eb6c1L,0x9bb2ca161bc45d8eL, + 0xe7903009a6d8a5a6L,0x4f089cc047db2201L,0x4135884de6b5928aL }, + { 0xb1a86a0ae5c017cfL,0xb1d9bf6db0a393dfL,0x33d9c1c628bb3277L, + 0xcb05b67b45b582ceL,0xa72585fcf33792c5L,0x78b7c5e8a7d1ed84L } }, + /* 19 << 294 */ + { { 0xbb83b446b1b4a091L,0x66440b3d9603d875L,0xd1931f33c2b45d1aL, + 0xb8b67f20098d4cccL,0xa3583818790f208aL,0xe01194bec4a3e88fL }, + { 0x29301bb192e8b150L,0x1795cabe9448ee60L,0x377d8f9752500c48L, + 0x474e73d65a457e79L,0xce0a50ef30159027L,0xfe69abaafbb2c214L } }, + /* 20 << 294 */ + { { 0x70e478fb9346df25L,0x01dc0c2eb4a4ada5L,0xaec82b005be36ea7L, + 0x82618b8f6717e06aL,0x2db1f6d4008f1977L,0x4e493f3b16b390d1L }, + { 0xfe86fd4d990a75ebL,0xa1cf7f99783f6076L,0x6cbb23e70c049158L, + 0xd05be7e5ed456235L,0x601374069bd836efL,0x94ec964432e5f604L } }, + /* 21 << 294 */ + { { 0xd96e4d920fc48c7bL,0xa2e29660f66e491cL,0xb92d850601146906L, + 0xa43f4803afe346d6L,0x27885d98700b6bccL,0x90662e9f595d8de2L }, + { 0xefa7f261f70d1007L,0xfe8a8be3fc72531aL,0x3b3f7541f1aa8d93L, + 0xb31bea258215966bL,0x15faa4acf35d2be8L,0x0a5f95e786c9a45fL } }, + /* 22 << 294 */ + { { 0x3361e1ce3d87bfa8L,0x92f235e78dcca4f0L,0xc8084cb4be323fd1L, + 0x3fd481a5c24c6d16L,0x9b1bd9402cea81baL,0xf50911910c5aa59fL }, + { 0x4cd8c9eff81d5e2aL,0x5ad000131550bff4L,0x29d47b9f8cc32e55L, + 0x66e3e6f111694eceL,0xd5edf7017950dd7eL,0x9ccb10960f6350c6L } }, + /* 23 << 294 */ + { { 0xc31e47ff95e784e4L,0x7ad0dfd63fa14241L,0xc91482092dab896eL, + 0xe9a114cccb9bb463L,0xedce9e6f16cb16afL,0x0ee2ce0607508893L }, + { 0x1aedb80ce31c0f54L,0x235d4591512658ccL,0x9029fad2a38583f1L, + 0x95b1e1ddebef898eL,0xeb2f21809efabef3L,0x458c4338b10e9cbbL } }, + /* 24 << 294 */ + { { 0x09db138d18f2470cL,0x63bd2290f613658fL,0x0bb647794feebab9L, + 0xfce4aee17fdb1e71L,0x7d5c0c61a7f1f65dL,0x46405b618d02d6cdL }, + { 0x7cac04856fdcb0d0L,0x85224c4b2f8ec5afL,0xb5879a59db0aa864L, + 0x75f391b8ff94f8b5L,0xa6c994ae49c97f8eL,0x4d968fadd690b232L } }, + /* 25 << 294 */ + { { 0x1e436df6e11a616aL,0x9eb49c76bdb932a8L,0x207d2fe90e6591aeL, + 0x6e05acc8233ac034L,0x464dd321f3d04d32L,0xd4ba4889af43c171L }, + { 0x0808e5207120fab9L,0xb9e4726c3fbac672L,0x5dd1c13b9d7d883bL, + 0x1c091808771f1edbL,0x76988d1c75eac1a5L,0xb0fcd3a893a67be8L } }, + /* 26 << 294 */ + { { 0xf5cd290a67e0b4e7L,0xaa6fa6807c1594b6L,0xebedfbd7b63270beL, + 0x574b410ba369bfeeL,0x431cba5a020ea888L,0xd3a3102f56c71d47L }, + { 0x4894bfe0a90a853aL,0xd78bd98b5f9c4b6bL,0x9b1324f6d900c5c1L, + 0xc65c944d718c2147L,0xf661de6ba987f634L,0x0315e69f172628d8L } }, + /* 27 << 294 */ + { { 0xb12e0ab8aac7ab64L,0x8ce877abb06cf9cfL,0x39b694b40bb11fb4L, + 0x0c2428369b0d8850L,0x6bc9a033ccd50c6eL,0xaa2e77739a1e8fb3L }, + { 0xa7d8be09608e2e9cL,0xeb4cef0542b9f458L,0xa7268c9b985f66fdL, + 0xd60eeab27acf4968L,0x02eb2db3b6e5621eL,0x82fb4abfad8236c4L } }, + /* 28 << 294 */ + { { 0x07c60c7522ea5f1cL,0x35beae34a36bee4fL,0xa8b00a09dcba8997L, + 0xa77f1f3a802ce50cL,0x6c4050df2a2144b0L,0xf79bfa96ab1b10dbL }, + { 0x9025d470433a9b1cL,0xaf3e391790d9eec8L,0xbcad2d629ae2d535L, + 0x7a152829eff0f6a9L,0xe87345cd925fa5a0L,0x6ce007200e84039cL } }, + /* 29 << 294 */ + { { 0xc65acf36c3d095d2L,0x9192c5fe72427e6cL,0xcb84c43c3fa8b90dL, + 0x2f458fe965e15b23L,0xd8bf193731469f11L,0x1ccd8bb93638cc3eL }, + { 0xa067022f78e35577L,0x382e6af730ee676dL,0xf197adc2f6d135bfL, + 0x06360834c9a1cf58L,0x413813f7930371beL,0xf7461d04f5dcaccaL } }, + /* 30 << 294 */ + { { 0xdae449c007f6a05aL,0xbc1b84f55bf26c9eL,0xe3b3f9edb1c13820L, + 0x5442ad5b4090598bL,0x794ef65613749e4dL,0xde809180948b71c5L }, + { 0x4c72dc7de203c5b5L,0x8902b0971b349fc4L,0xa899bedb225a1569L, + 0xeb7da73de6ff3f53L,0x6ee8e1607c0be37bL,0x9ee667d2a31bf943L } }, + /* 31 << 294 */ + { { 0xbc91031108b6fb2bL,0xa5e0ab3e25e06a55L,0x16ff0705360f1698L, + 0x71c0aa7487e72a67L,0xa1f1497b355c75e8L,0x179b67bffa6bbcd7L }, + { 0xc9db6590b6738583L,0xf77660c4d87e72bdL,0x0ee2e7b3f13abc2dL, + 0x0cdf5a37a4d922b6L,0xaa8af2d596c853a4L,0xdc452af4e0092356L } }, + /* 32 << 294 */ + { { 0x5017e145db81146dL,0xc7d2086d45c54db8L,0x2541059dfa98234aL, + 0x4bf344d99985af98L,0x39737ed67b5b7b1cL,0x8e24691987c411adL }, + { 0x2fad8cedb877a75fL,0xe42352df17e60ee2L,0x1a53d856404043f7L, + 0x6c1f07a5863927a1L,0x38d3a4f4b6892121L,0xf4c1092001976c8fL } }, + /* 33 << 294 */ + { { 0x541732a70224214aL,0x61617b515cb2d019L,0xc560c24bcb4fc6b2L, + 0xd0ad737943670d99L,0x08cdd32eb83112a8L,0xbe57493d7e29810fL }, + { 0x7834124899d4523fL,0xae1a5857cc8e5fb7L,0xf8b62a59b8454efaL, + 0x7c63c900ab0f4729L,0xeef9243d72dd0f5fL,0x6b865dfbad766386L } }, + /* 34 << 294 */ + { { 0xd11536eefee626b8L,0x1d2471dd8077b5d4L,0x7db062debdb9a4dbL, + 0xfcc62c0ab9f808ebL,0x619b54c6ef392bc7L,0x81e146fc51b9f5c9L }, + { 0x0343807c7bbd52b3L,0xe024a9f1572125c5L,0xf8b886d86c57cb31L, + 0xcb92aa7d5398a318L,0x4ce0870d2410ef34L,0x1a40c103f8366683L } }, + /* 35 << 294 */ + { { 0x46485baa7bb78552L,0xc0f685f23e6a3f0fL,0xd24970b5fb3cc0ecL, + 0x0d1f380e7bf91feeL,0xf0f7fcafe7624351L,0x27cb99bc697a8055L }, + { 0x55be14685cdc7560L,0xf006927927ba7f93L,0xb0c25c759fdd0e70L, + 0xda82e73785818253L,0x7d40d86946304c51L,0xe06ea6fdcc18ba58L } }, + /* 36 << 294 */ + { { 0x99d37ade6b65e17aL,0x61ca538e38ce217cL,0xd3ea83f68ebb89edL, + 0xce6611eb4b02964eL,0x0ec7cc2f5c0a8e44L,0xa985b0c2974240a4L }, + { 0x7a3abb6c42ee5b0fL,0x55f049a0cb2eddadL,0x69348b027c44a60cL, + 0xcabc65191974a8c7L,0xd9def4bc07b91a35L,0x684a2d71b93b34c3L } }, + /* 37 << 294 */ + { { 0x21c37d21f48f274cL,0x2de96b4da082a098L,0x82520e0ca606b6a6L, + 0xf76c9ec6e1050b81L,0x248c5efbd1ce149dL,0x5a36ae1e9a909790L }, + { 0x8790b09bec8b43afL,0xd592dce560ff709cL,0x726d699724cc8e21L, + 0x61e37bef5e2cb745L,0xd55a68c26eff3ba0L,0xd47f02659ad265c0L } }, + /* 38 << 294 */ + { { 0x3e6351ef3932ef94L,0x65625878db5d64e6L,0x118a688e091ec7b7L, + 0x2a95072abdf60b88L,0x5200703540dc0afeL,0x59c3d90b6fc1cbffL }, + { 0x5622b1b21dfb1a7fL,0xdcb0344834d92243L,0x18fccfa86d7d36c4L, + 0x5d43a14181341761L,0xef375542eaaee79dL,0x4e4667216999d399L } }, + /* 39 << 294 */ + { { 0x1bca97aa9d3c6b9eL,0xb4bb4f95095cb250L,0x4f2c216a996fb52aL, + 0xc4d01916f379790cL,0x510882a4359df53dL,0x6457d76a671d6a8fL }, + { 0x0ded2623061f7d64L,0x3cb4f38f1ce7dcf2L,0x0d86313a224ffa88L, + 0xba8a15012b99aeb3L,0x2fb92183d69f72b5L,0xd3b9d6daf1fdb8f0L } }, + /* 40 << 294 */ + { { 0x5d573a3a0b6320aaL,0xf9ac8ccf289b6700L,0x8bad05cd8f28dd72L, + 0xe2eabd446b62c306L,0x60f70353906ef302L,0x147cdd0c367a768eL }, + { 0xea9d871635a9e846L,0xdd71e80aa8684430L,0xa56a5ccd530768a8L, + 0x59d241270a3e42f6L,0x707cbaf0faa367d1L,0x5419b14f52a0cbd0L } }, + /* 41 << 294 */ + { { 0x625bf4e6d991d842L,0x56b95a56a81daaaeL,0x2101137c9911bdadL, + 0x1141b0a1bbded1c2L,0x85deb889d1df8d43L,0x51e3e17edac3e376L }, + { 0x5d31639381fb19f8L,0xd1cb634b92eed2c4L,0x72a6ed7b943746dfL, + 0xd55f55fb22b85e00L,0x255b025804193aabL,0xd0b94c5d86a78c96L } }, + /* 42 << 294 */ + { { 0x121c15d859c3556aL,0xabe25c21864380dfL,0x2de101832627f78cL, + 0x19988e4b4bcf4a0cL,0x4ed3aad8a2f9cb52L,0x50f8cef5b2b257e1L }, + { 0xab0b000c49f7f596L,0x6cb997471fb9c471L,0x331974b95fefb8f4L, + 0x57cf97578e2e0e5cL,0xa82a8d06174a626cL,0x40ef371b03e80567L } }, + /* 43 << 294 */ + { { 0xfea713e1324cbab8L,0x738885e61897e7baL,0x8234ed08126aaa13L, + 0x4f66467661ed1548L,0x61fdc2aa172c432bL,0x78eade7c9ebf0a29L }, + { 0xd50ae7156aa104a9L,0x977d7a605536df98L,0x024014bdc9eb983cL, + 0x75d53c0585e21649L,0xc181d67098404cffL,0xe00f5f5dfdb3f05aL } }, + /* 44 << 294 */ + { { 0x3cfe2987d10542b1L,0x5935e0dc29f5b006L,0xce5932d6d83344f2L, + 0x67aab7ad9800a6d5L,0x3ef2b0e765073619L,0xc381a99454aa9ccaL }, + { 0xbf069577d4011571L,0x33b70c5d4d1ce997L,0x801ba41c758c9b1bL, + 0x6c2dd5ec36968958L,0x31820ca087921665L,0x0b7f0d337ca55668L } }, + /* 45 << 294 */ + { { 0x0b099a5afce6c55fL,0x91d1caca408dd628L,0x42a5181165449db1L, + 0x540935b040715d49L,0x8feabc5433b00823L,0x7107c06240c2485fL }, + { 0x13f307ac4fea64e4L,0xae4ec4a713a04327L,0x8297be380eff71f5L, + 0x3434286f1ecd0b2eL,0x4d7a5456a3e9d625L,0x657f950b6a0d04e2L } }, + /* 46 << 294 */ + { { 0x2237f78ecebadb15L,0xa1184339da01f9e2L,0x542c3354ef37abd1L, + 0xbec90883de982d70L,0xbacdbb9c457d3024L,0xf1d167c19840ea52L }, + { 0x9ed827d8433bd3cdL,0xf4e5b4231102fdf3L,0x2038c92fb63d6056L, + 0x490cb0188eb9ae35L,0x776331b87c75ffc8L,0xafbe7c6a3fe2e400L } }, + /* 47 << 294 */ + { { 0xf668460c9176a02dL,0xa843a70011d322a2L,0x6424f0e8a8c5d1c8L, + 0x0b45a1ab1bc440e5L,0x3b740cb11c3e391cL,0x5aaa89c4d5850e1bL }, + { 0x77739ee6d632c592L,0x171fd350fffe373cL,0x6a648fcdbd7e83beL, + 0xd98650c6b619f4d5L,0xa4e4ae5438dea07cL,0x10001f5afe0bf5c1L } }, + /* 48 << 294 */ + { { 0x31cb896b57dfc732L,0xc6b74a1edc323e91L,0xd24a41d0f11b04f6L, + 0xb609a26dab8f7159L,0x96d84b372adbec34L,0x154f5307d24ae7f6L }, + { 0x36dd3243e10eb34cL,0x055d3b714f6dbbd3L,0x30b1efde36d0c561L, + 0x3846925ce9bffd15L,0xaf401286aa99ba07L,0x3a191267fd48b839L } }, + /* 49 << 294 */ + { { 0x67145f18e42a26cfL,0x580857fa491122d7L,0xa4e2db8dd03b5071L, + 0x47a39a0d3e379882L,0xb6bfe4b35970766dL,0xe40f4daea8bce767L }, + { 0x38f199a7e812a217L,0x1407f98d97eec7caL,0x25d6f750236a41a0L, + 0x644327340e811ee6L,0x84d5d9c9dddd6e5cL,0xc1b6ef13c44cae4eL } }, + /* 50 << 294 */ + { { 0x79879d4f6714e8daL,0xce409617a17abd07L,0x6f2b14d008a6e685L, + 0x817d467409b5e150L,0xa1181873eb51b966L,0x573ba855da6b9544L }, + { 0x836ec3e5c4a37013L,0xb8da1bbe93fded69L,0xdb5bb6f16edff4c1L, + 0xff30b837f1657d36L,0xa20cf000223270b9L,0x29d60562d44a57cfL } }, + /* 51 << 294 */ + { { 0x0d6f36b9b98b029dL,0xc4cd72d07a371233L,0x23bd419e4f95cd4cL, + 0x2c95b0a2b80d1e13L,0x0f76e62f7edfbef1L,0xd077194dd303a470L }, + { 0xd6e20e7cd1b50934L,0xf4201fca2dfeb806L,0xa57dc150bced28faL, + 0xa84d621be3172301L,0x119768fe9aa14d6dL,0x34f1ae864b363253L } }, + /* 52 << 294 */ + { { 0x2fc83aa3afabd13dL,0x521b745f53c45a27L,0xc6f345a660c18225L, + 0x9609076eb5faa47aL,0x8bdd97fd535388fbL,0x8f5f3bd6e7fd7e87L }, + { 0x6de4454c1c8e1d5aL,0x8d61ca3b2b35e823L,0x93b66fce4672d30eL, + 0xcb9d601721d09ec5L,0xef98137fb1de06eaL,0x45e212758b051877L } }, + /* 53 << 294 */ + { { 0x117b89e9ee6e35f7L,0x2ad205aadd203ed9L,0x3f6c950c0689bd4dL, + 0xaba1e4b342f20742L,0x67464b793e22f0d1L,0x74436dfdbe0ad6c1L }, + { 0xc4a6e964c1470ac7L,0x853ad39b361da35bL,0x261c6fd6a187a6abL, + 0x08d7e89d59fb860eL,0x158e2697e8f88299L,0xf3f1f6f34b04a8ecL } }, + /* 54 << 294 */ + { { 0xbdfb8d006b562705L,0x76dbc217ed9f2aaeL,0x62f713778cfd02ddL, + 0xa05eed177a5d27e1L,0x60082379a006983aL,0x312af914bf7c2c05L }, + { 0x7d163fe76c8500fdL,0x722a35299d4d0dbcL,0x9b4c5c3539f93a78L, + 0xb193734c34c7ec06L,0x457db178cda87a84L,0x088dae087f816e0cL } }, + /* 55 << 294 */ + { { 0x746e73055896ac5dL,0x1d8326c21a7b69f1L,0x695197743132a40dL, + 0x3899f8a03f58720fL,0x2c3070a5df0b7fb2L,0x49bc59f2acb839e3L }, + { 0xf7d5d3f66b8f5a9aL,0x704ed893a4c3b570L,0xbafde26cab591c03L, + 0xc447dac83388a62bL,0xda80991d4416acfeL,0x1625c9151e729d69L } }, + /* 56 << 294 */ + { { 0x3104e59e6b843647L,0x4eccb42720bad138L,0xa575b8e150efd6a9L, + 0x68a6b7055a6e4729L,0x670306798f5b2a22L,0xb2cfcf81df9253bfL }, + { 0x9c3eeb19b8f81c39L,0x082ca86c986b4dfeL,0x1f64eca250250d8eL, + 0xbf26bcfb67f0c713L,0xbc5d0e2a49b609cdL,0x175acb34e6aa3c76L } }, + /* 57 << 294 */ + { { 0x5237d7368c53aae2L,0x2a88098bbdbc0b10L,0x18f1af11cec6db6bL, + 0x12c23392c4e08b3bL,0x23b652bf3eab43f3L,0xb79feb949f3dca0dL }, + { 0xb71e311d2b24e0d9L,0x85e48aede37a0f90L,0x93e8a0e753200b6dL, + 0x5d44b87226bf3a30L,0x466c31d1d0496b98L,0xabec12f7dd39874fL } }, + /* 58 << 294 */ + { { 0x58bc23928ca41326L,0x0744ba8524aa5067L,0x900e7e9baaf80bb2L, + 0x510bd122aff38fe1L,0xf90dd6a1002b277bL,0x829379dc81bf7df2L }, + { 0x5443b8736372d502L,0x124c2abab5b6f9a2L,0x88b237a4d6020c14L, + 0x3542215108f7a498L,0x39e84240e6234eb1L,0x43d721dfcc5827eaL } }, + /* 59 << 294 */ + { { 0x43e7597234658dcbL,0xed936b96bdf3a7caL,0x74acb7f60f1923abL, + 0x6a52b28cc007995bL,0x5abf2909a560fbf4L,0x79d571dd256bf1a8L }, + { 0xa8d51082e4c3281dL,0xc0d6f8aa0b9fdd38L,0xd589f2c57ac30640L, + 0x6abb8faf07635c58L,0x2af1b083d7520b0dL,0x18b9f6c893b951fdL } }, + /* 60 << 294 */ + { { 0x32e678b4c1ba956bL,0x9e8b137248f32982L,0x9b380a118a8f262aL, + 0x5c2d6ce0807f6d1aL,0xe99c2e909f1b3fa2L,0x6a0c9e4a7c4bb836L }, + { 0x30d80329ee8dac83L,0xabcf7b76b60bd5fbL,0xc589a0c8c14d56d4L, + 0x9e40af665de24d43L,0x932f4070230f8331L,0x96bba1c19b87948dL } }, + /* 61 << 294 */ + { { 0x8b83af0c4efaae9aL,0x25e55686770c85cdL,0x0beda54fede0c999L, + 0x6c5749398d249a2eL,0x520ac2ba2f476146L,0x162e482de95b05acL }, + { 0x2d3d19b6c73a32daL,0x945e5e3c33fd2c48L,0x361d9770a36b4ee8L, + 0x8aed760d014cacb3L,0xae66e5de5ae302c7L,0xb5fd5959b5d4d6a4L } }, + /* 62 << 294 */ + { { 0x25df58ff147da470L,0x1b3941ec3f4e3e98L,0x7543b1227aee3587L, + 0xb7bc2b31b4a28218L,0x8628b5400bb3224fL,0xe3e7644d373222e6L }, + { 0xb4e3269299244dc9L,0xe72c679d49781bcdL,0x894d9eb0bb6f0700L, + 0x4a08cdbc443c3639L,0x52c4d04e5baeb02cL,0x53f550ffb5f93552L } }, + /* 63 << 294 */ + { { 0x2b908f693c1f524fL,0x59fd6ae7090970ceL,0x595e15721eb9ec29L, + 0xa55adbd6fbc4f04cL,0x575a2344bcc38bf8L,0x89397944f2b659b7L }, + { 0xc77532a18c87fe8bL,0xa5a75677de4c9eefL,0x2e3d873a0e4a1704L, + 0xe18ff4fcc4d02aa1L,0xd842074275573a79L,0x0fcb532115296dcbL } }, + /* 64 << 294 */ + { { 0xbcc88422c2ec3731L,0x78a3e4d410dc4ec2L,0x745da1ef2571d6b1L, + 0xf01c2921739a956eL,0xeffd8065e4bffc16L,0x6efe62a1f36fe72cL }, + { 0xf49e90d20f4629a4L,0xadd1dcc78ce646f4L,0xcb78b583b7240d91L, + 0x2e1a7c3c03f8387fL,0x16566c223200f2d9L,0x2361b14baaf80a84L } }, + /* 0 << 301 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 301 */ + { { 0x7a1a522b246dc690L,0xb563cbe14b61ab70L,0x41bb4abe3d4ac4abL, + 0xc52950b337f996e8L,0x01d991e679727761L,0x35de93bd978fd7d2L }, + { 0x86bad5e65706d336L,0x10844155e7f26c20L,0x58ffeb7705757453L, + 0xbb1861293939df77L,0xbfdd394a6a78ea0fL,0x907ff0546e33e1d3L } }, + /* 2 << 301 */ + { { 0xa7f295320df93b34L,0x855934f25c14df30L,0xd2f54ce9efae348cL, + 0x5acb931cac52758dL,0x287b3e18d22961a4L,0x42a5516d748f8fe1L }, + { 0x1b62b341877224caL,0xaff58db3d30a4aa7L,0xbad78dadbe8da847L, + 0x85fa710954f18276L,0xe2cc9d287c4bfdadL,0xbb131f762c75f237L } }, + /* 3 << 301 */ + { { 0xcdcdd7d703844670L,0x79ec59afb4a23f91L,0x5923c569c00ce5c3L, + 0x099c17ffc589d0c7L,0x0335eeea89fa6fe6L,0x916bcacaa4e868c4L }, + { 0xb7037325fb687bd5L,0x57d6bca79853b564L,0xdf3132efd5e26d28L, + 0x7ed994b8de919cbeL,0x12df67cd6fbbb18dL,0x516e07c06baff508L } }, + /* 4 << 301 */ + { { 0xf2ec9ef597e833e4L,0x97bdef9734ec7e41L,0x90e2b2387d2ac6e3L, + 0xcf682b120318a3b7L,0x7fe76089ea84a7a0L,0x85c489f916546d05L }, + { 0xf987118f6abdda05L,0x675cf998aa4b95fcL,0x544c7774888a7e8cL, + 0xbd2647ba63ec5831L,0xb479cea3fd2fe985L,0xa042134528d163e8L } }, + /* 5 << 301 */ + { { 0xd93506a4e5947c6fL,0x4340d76a39b81d08L,0x741aee5917930d30L, + 0xfea3d99a18fdb81cL,0x1088ff6b289bcb07L,0xc6b45602b7c082c6L }, + { 0x50e2baab453d8d69L,0xda9bf561e893e183L,0x0af25f86b29a284dL, + 0x0e92e67473e01380L,0xe173a0e32be00e59L,0x402d2f3dada8954aL } }, + /* 6 << 301 */ + { { 0xca9cb3890399721dL,0x03ad9f4aa3291479L,0xd85b5df56dee003dL, + 0xe1fa7b0264a4f83aL,0x01c4cbfdb73f7324L,0x707010d45cf2ddf4L }, + { 0x3c6df430b12e02f8L,0x921a290185531489L,0x302fc77c91d1022cL, + 0xc3733ec0342d8f3fL,0xb83bc75f6195a665L,0x4a14b9e7a79f8027L } }, + /* 7 << 301 */ + { { 0x9f0e5428e2a57359L,0xc690a3c714998c16L,0xd73c3ca2de37e07eL, + 0x2ddf91b8dba0bc0dL,0x69d834b27570ae71L,0x2ac8bed4735195a6L }, + { 0xcd8c51ff3b1fcc5cL,0x7aa8cf4e1ba6863fL,0xebb69e72ae70f428L, + 0xa29409dfaa9e936dL,0x43f6ee805a332b9bL,0x0de49efac2eab0a9L } }, + /* 8 << 301 */ + { { 0x04baa1762310333eL,0xdc75e35f7b9bad46L,0xc4a6031dc6cd6108L, + 0xba2534d030bf87a5L,0x7ebc6e2131e497ccL,0x8a2a82b4851fd665L }, + { 0x9ecae0116d5faf40L,0xfa3a6d7f96956ecbL,0x39e8a9c22fa52782L, + 0x74c93801236d442eL,0x8b21ba23b1c289ceL,0x7f3e221b25c769cfL } }, + /* 9 << 301 */ + { { 0xed800e4d08aa4dfdL,0xf524b107d8105bc7L,0x8c4addc9ab07fc03L, + 0x2b0f038d26a71b4cL,0x5055c471a83d19a7L,0xc6c5ecba27e20a5bL }, + { 0xdbad26b7aaeaa017L,0x4e3abc20d2493554L,0x626310143a0c15bfL, + 0xbafcc06798cec55cL,0x9204e17ce6f87607L,0x8f1c10eed9302c05L } }, + /* 10 << 301 */ + { { 0x53680ce08afe59b9L,0x36a3cec75665022dL,0xb3a5091654490b50L, + 0x803d383f0838f0aeL,0x65531a008005ba2eL,0xb7fa6b4a1241a17dL }, + { 0x9aaec449b17e07bcL,0x19b7d9113d190dd0L,0x79da42457fa5e7feL, + 0x725bd045598ad850L,0x49f96cc45f94ee82L,0x114bbcbf03850eefL } }, + /* 11 << 301 */ + { { 0xf566a287d43a6db8L,0xffb8944b2aeb120cL,0x3e7099427e294c1aL, + 0xce122b126c31214eL,0xe59b280c2a21282dL,0x03916e2ba01a4fc6L }, + { 0x56e65da29f5e409cL,0x374d3dfe7f5c3e11L,0x150684fc13967e2cL, + 0xfbed4f5bdf4bc38eL,0x5973c67182e54b82L,0xcd36c873363f307bL } }, + /* 12 << 301 */ + { { 0xcb42c5617c3805d4L,0x0e74e75c3b43a8b3L,0xfd58f864369f579dL, + 0xf471aa774a3dfe97L,0x2e0dbb51ab37bd2fL,0xc4704487729c887bL }, + { 0xcb7958a9cff32948L,0x3e36de368505e71fL,0x2232fd2dd38ccfbfL, + 0x6f3c502042005175L,0xd1280a3e306fb63bL,0xef7abd792e368ee9L } }, + /* 13 << 301 */ + { { 0x29c5712d56ffcac3L,0x20307670e1a8e0eeL,0x676a23c26356aea0L, + 0xb9c17e3f432f15d5L,0x0008512e287c5705L,0x6ae2704bc5f7ccfeL }, + { 0x6a200db709a13b60L,0x24fb1e9241043271L,0x2e455e9741b766a2L, + 0xa11ff26fbe056684L,0x3cfb8a64ad9178ceL,0x5786978d5d675b79L } }, + /* 14 << 301 */ + { { 0xf4cf2c8e6070a72cL,0x0bd73aecabc3251cL,0x1af44eff17539f67L, + 0xec3ee99e44e8d8f7L,0xba698f6a279afdf7L,0xe871accfb771d4a1L }, + { 0xbf92963d8bb0f264L,0x817b1fcfb10716bdL,0xf57580786b23076dL, + 0x994ff3c535a994cdL,0x05d984e82604847eL,0xd728e292fc9f2e43L } }, + /* 15 << 301 */ + { { 0xa44bf023b900b696L,0x1f82fe54037bb770L,0xa6d12f820717e747L, + 0xf154ac51e3b83029L,0xfbd343128cf3984dL,0x7f734beaa76c72c2L }, + { 0x05c5b443114548b9L,0x4ce414f396af4132L,0x1474c0b79d080a7aL, + 0x865827c6497366a3L,0x34760c457816a0a8L,0x6da2474c15d2a176L } }, + /* 16 << 301 */ + { { 0x761e10e2ca114c4aL,0xe39d121d894301b3L,0xa0870ff43dbc6fcaL, + 0x97651286cbe0ba8aL,0x47d46075c0f1ff6aL,0x18669c843abeb5b6L }, + { 0x1234c80ead8d9309L,0x1ccbe4d51f6f97ffL,0x399a2d41d82ab780L, + 0x8a03afafde426e50L,0xa2bcb109ca6dde77L,0x840e13b00618f5ecL } }, + /* 17 << 301 */ + { { 0x9552a8184929f7eaL,0x514e9ce9acc61766L,0x03159a525a219015L, + 0x5efeebfa14eace54L,0xe8a3736f853da94dL,0x3a0f334ff45e8a32L }, + { 0x71ebab39c9dc65c9L,0x6ef37f49d7c24f39L,0xde3d45f8b24a9383L, + 0x7193bbb80c218869L,0xa1bdfd30c0f7b6beL,0x82b2c4c5c1d9206aL } }, + /* 18 << 301 */ + { { 0xf9d9b678b197099fL,0xfa8548c4c15b2bbeL,0xa36f17fbdd2817beL, + 0xb35597021732d1edL,0xba145100744f3955L,0x7c274633344b43a3L }, + { 0x9b0ee7c8686b65a5L,0x438eaf4823f0e973L,0x79a658a7288c5019L, + 0xf6d938c546d04413L,0xe39bf9a6a6cb9853L,0x880d5b83801b70ddL } }, + /* 19 << 301 */ + { { 0x8f23f00303825482L,0xc4a9f214a6b35023L,0xf0905573794e7de0L, + 0x7ff790144dd68979L,0x8d9c14942959beffL,0xdb34474f82282e48L }, + { 0x423bdfa281fde794L,0xfc31e3e792a8810bL,0x19d316ba8bae4eceL, + 0xddcf30b7159c1386L,0x997968a38e7d69dfL,0xcf67ae9aa6b21be0L } }, + /* 20 << 301 */ + { { 0x877866a3697b4dd0L,0x32a872f4e76481aeL,0x300387bad609cc04L, + 0xc761ae79d74566d4L,0x9fd3e5bff22e2d24L,0x363ef5bf1c46bc0dL }, + { 0x121b25bce299a690L,0x7932471dc2d32b7eL,0x7f89692e94bb4272L, + 0xaf9cc4111a3ce076L,0xaf02ea22ea02e452L,0x43154e581d19dc60L } }, + /* 21 << 301 */ + { { 0xd9389e05e25dbe97L,0x3a8689b162b3afe3L,0x4d5556467014953bL, + 0xd6894c42af5ba9bcL,0x4b233690b3bacaa6L,0x0fc8ad07fc191181L }, + { 0xcd3a1e4df0764f39L,0x18a47233d79567f1L,0xf0f9eb765f921f79L, + 0x7f3d814d19d12a7fL,0x5e48cc36ff33a995L,0x9589679b8960331eL } }, + /* 22 << 301 */ + { { 0xa2ff78bb477d7226L,0x3216fcc085e04a8bL,0x7c594f81e4c3c24aL, + 0x075eefaa029d6ef6L,0x5ae51000493ab006L,0xcdfcc6939ab165efL }, + { 0x50b7eee276073bfaL,0xee52d55b3b60cdb4L,0xc7f7b3af45027275L, + 0x01d5444ac15b2ecbL,0xdf56f8c12a61d1e1L,0xcf032e7e4992e1bcL } }, + /* 23 << 301 */ + { { 0xc8a4dfbf15b6d8d5L,0xcb34e0e4e87ff88dL,0x6dc95befa6ebbff6L, + 0x2a55ca1372ff2cc0L,0x3c4c0f3c6a62588fL,0xa8de444ece156917L }, + { 0xced7c4523e55eba1L,0xa109b7949f05820eL,0xa021717e0e6c318dL, + 0xa0156b8d0b308f5bL,0x3c65ab9daa6634baL,0x1666e650e2839e0eL } }, + /* 24 << 301 */ + { { 0x0d27500f9ebe3c40L,0xeb9ac1022b700fcfL,0xee7578f8610763e3L, + 0x6e56078f47ef08feL,0xa8d03a7f047d04c0L,0x2143606f27cc8aa3L }, + { 0x6b08eb383b004721L,0x1f505c0dc4e36bb6L,0x6f9b869ae3f10ba9L, + 0x3bfb9833e500e846L,0x6d975557b9171b1aL,0x7af9cf4f18fa0045L } }, + /* 25 << 301 */ + { { 0x35bfb51b3b35836dL,0xc834e59003b0fba6L,0xbe6e17d378937ce0L, + 0x2f796f7c4daa9aa8L,0xd7896a0ad310eba9L,0xda258ab05ea4056aL }, + { 0x2d872d2170626628L,0xc9b26d7c2ee433f0L,0xb176220ee72f7491L, + 0x4869adcd895e9b52L,0xd37540e4d3a6d786L,0x024aff303a86b44bL } }, + /* 26 << 301 */ + { { 0x5e78606bd8424b90L,0xc83a5af9ebc9c9fdL,0x8d5b63740b65ada7L, + 0x4d01d6a221fca70fL,0x8ed7787ba1838061L,0x29901318f4a1716eL }, + { 0xc4d260527f25fd2dL,0xa66dc0a98b5147e0L,0x4355e26c269d726fL, + 0x1284fecce3a27644L,0xc9aa6cf7f98e1d0aL,0xa25ac1be3ff560c9L } }, + /* 27 << 301 */ + { { 0x5bbb87ded64d103eL,0xcb53a2f24d20fb37L,0xf8a9c2993a46b892L, + 0xb552910ca793aa9dL,0xd09e5bea51ef0806L,0xb57a0568e0c3817fL }, + { 0x9ca67c5f4e85598fL,0x04f6361fb0336008L,0xf028231b580afa5aL, + 0x8d938c0ef2bba03cL,0xa5984c1f894f37d3L,0x62ead7f4af695ac5L } }, + /* 28 << 301 */ + { { 0xf897de9213a48775L,0x505e21681b0041bbL,0x9f5533aad598ebb7L, + 0xd552ae1e1e87b2fbL,0xbb35a6319b736f5aL,0x391ce7dcc3a4c54aL }, + { 0x4c677d87f90124d6L,0x2ceebe51a9292210L,0x8882ae3133c63951L, + 0x8222c6482d44c9d0L,0xb97511420d607658L,0x3a999028b85f5997L } }, + /* 29 << 301 */ + { { 0x7b23f424eabb3f68L,0xa622a3ba4294750eL,0xb382b118e535b446L, + 0x7dbab9ee5fab292cL,0xcfabbfb037fe2f8eL,0x2283d7606670925bL }, + { 0xd18e90715be9d07fL,0xe191daa7d257745dL,0x86d59808df915e35L, + 0x87f68d5987370b6bL,0x76b9d255f945ac1eL,0xdcf9e8f2dc94ddbdL } }, + /* 30 << 301 */ + { { 0x004f1db65b986506L,0x5da683c32b0d22acL,0xf2afd1d85ee0c71aL, + 0x3b99a78a8f2ad25bL,0x8145d2ffd1c0cb69L,0x4511dc4e4009a536L }, + { 0x5539e8b8a5cb0c13L,0x4f8fd0186aae4603L,0x15dde4476d2365f3L, + 0x7cb887f7380df270L,0x815343a6a741b88aL,0x81a085e4bf99e7e1L } }, + /* 31 << 301 */ + { { 0x37d0460fd647fbd6L,0x2ccc7b01b9541f89L,0xec0e8826877a1b2fL, + 0x54d9e611cd462979L,0x016e8458453dcce6L,0x99b5dbed20ea6a24L }, + { 0x64072ec778550386L,0x279fbd9959d02307L,0x7f2ca27e9183bfebL, + 0xa191d6e8bb5132f5L,0x2b9f6163ba49ee68L,0x5a58a11fa3ee1672L } }, + /* 32 << 301 */ + { { 0x15d47e52ec645a62L,0xabe0ddb38d6d4423L,0x51226a3070cddb11L, + 0x63a253d32b5a8db7L,0xe8be4d1fbef37d65L,0x41e625d9c0920b91L }, + { 0x08b713a8d9d040ecL,0x467fb08dc450cdbaL,0xa8975877917ee393L, + 0x294792e91528cd12L,0x4512dc8c37daf6aaL,0xa83becc9197a99b9L } }, + /* 33 << 301 */ + { { 0x1b7bfdb118815b20L,0x1aa602e8629b81b9L,0x11e6df9d199aa5abL, + 0x1a521728bef9296aL,0xeba3e03b89e127e7L,0x6e69893553dffcf2L }, + { 0x24355785101615e1L,0x126b4c5282e42593L,0xe344ddd85c23144bL, + 0xc73a49b3746c0ca2L,0x1ec2432be6f63f9bL,0x6080ba870243120bL } }, + /* 34 << 301 */ + { { 0x6ab2936a4c3e946aL,0x8de2e0ae3ab052f0L,0xcaf8c35eea109739L, + 0x21d69383032418c8L,0xefab535ae7ee60faL,0x1a3a1be794b44fabL }, + { 0x0842aaa5eb911cbbL,0x789c2b7e0286862dL,0x8bff708715c0b148L, + 0x71100d79d8d7faf7L,0x47caa89a6dfa0c8fL,0x82385cf44b546332L } }, + /* 35 << 301 */ + { { 0x4f5d8c35e4b814fbL,0xe534b7be6a427f92L,0x468fb2819ca1d37aL, + 0x8c1c86347949961cL,0xf9d00305db0f7f19L,0x77534b3a976f7102L }, + { 0x94ecb7933f530710L,0x072f6fc7a916827aL,0x9247acdecc926f8eL, + 0x0d4a8997281d0a50L,0x659712669f353507L,0xd4730a15fde80a6bL } }, + /* 36 << 301 */ + { { 0xde68ca25bd37b630L,0xcfa9d32ca899d623L,0xaaeab905937c9ba8L, + 0xcb261334348ed39dL,0x8d12531fc77e1512L,0xfb7934b6213b63d1L }, + { 0xc6a6fb0096a13f19L,0xe940f3aac8f88d6aL,0x014c7f95c3d2829dL, + 0xc33d87e9fff01f41L,0xbf9c3c23c5cdcb4bL,0x8b8c0afe5d5be5c1L } }, + /* 37 << 301 */ + { { 0xe4f84bf12aac2c23L,0x5bde1744f823f90fL,0x65ffefbc02d5bbe2L, + 0x385aff9332a3b756L,0x3813f2b362abfdacL,0xbbb444cb0a144325L }, + { 0x0cf9d137ec625be1L,0x86b8fcd4c143816bL,0x03f7a9d060ac32d8L, + 0x0428daf9366165b6L,0x6ef94260d2a806d0L,0x94a100a598134bb5L } }, + /* 38 << 301 */ + { { 0x4b68325ca4a34cb5L,0x74f41f7639fada89L,0x34bf397236e593e7L, + 0x0cc75d461c6179c4L,0xe62d5ba577d711e5L,0x7bec1be7876964c7L }, + { 0x768f35d13809fc73L,0xfe55a9a57dcf1703L,0x86405336e69d3390L, + 0x68f5ea2d00bfc544L,0xd4cf822b4834b2d8L,0x77dc1ac22b0d3ad6L } }, + /* 39 << 301 */ + { { 0x45603dfa0337f57aL,0x50623184344b6968L,0x3fb9957ef160d9aaL, + 0x40eef1697c8db44fL,0xa8f394e98bf71121L,0xa55ecf3b86a920f5L }, + { 0x1f3c1f22bb0822e6L,0xb3c2f21357747a3eL,0xfbdb4465bef56f08L, + 0xa9844890a46ac73fL,0x3fd564a5bde3652aL,0x008cc1a97c653c82L } }, + /* 40 << 301 */ + { { 0xcfebe027ca0a98d5L,0x946b0d9aa8914697L,0x00f89d16725ebd08L, + 0x94c6f2b07a584e8dL,0x095ac9cc911cab58L,0xfc9c3b499c4073c8L }, + { 0x265919b0c7233aa8L,0xe6c0c7f474be5217L,0x6db597f1815a70a9L, + 0xdd9e4a101c5fd35aL,0x38b8e35112d52a8bL,0x5d0ed83f2ef20fabL } }, + /* 41 << 301 */ + { { 0x4f47e10a6c96b43eL,0xe406ab39f3d744deL,0x1caf45d83c893b01L, + 0x4f089452a7582ea6L,0xc02f58cd62b5a868L,0xf6532017c2a9aa7bL }, + { 0xf0d8bf6f32b01bf2L,0xfeec5f68a97246f3L,0xb2ead70a1aa7c238L, + 0x1a1d6f77ad83e05aL,0x4b7110533dca7e9aL,0x44a89fb85f96e5adL } }, + /* 42 << 301 */ + { { 0x86a7ebe0f02461f3L,0x6a7a9cc6862282c9L,0x7f8857944a97e48bL, + 0x191244cd20662db2L,0x8d85175183489311L,0xfbcb17b0f934c1fdL }, + { 0x33b4d86e032a7bb3L,0xa99864cb573f5c28L,0x49fe8e799c4f12cbL, + 0xe34c32e32c8bb49cL,0x5888421e962d6d9bL,0xa317c2d1bf1be44dL } }, + /* 43 << 301 */ + { { 0x3454c424cc1dcbbfL,0x67e61434aac98717L,0xfecd8125cc2d3044L, + 0x2032be70df7f8891L,0x04c5a0c81028059cL,0x6563dc8c76ade6b7L }, + { 0x9ff3815192f460aeL,0x8c2c3c632d54785dL,0x1fa99d8e43eabf60L, + 0xd75d9559383be317L,0xc9ef068e3dfc908eL,0x2217c8c1959d3e6cL } }, + /* 44 << 301 */ + { { 0x5828d71bf2e5f345L,0x8b756075929fe375L,0xca625ec12c43a6d1L, + 0x08cd01f53b31e127L,0x56c622619cfc1be2L,0x093ea207b3a6caeaL }, + { 0xdf53b20970b42dc9L,0x2d2dfdf2235f4aa0L,0xcaac3b3598786c94L, + 0x1ce1f893b4998150L,0x40341c41526a98bdL,0xef39e97eedce5288L } }, + /* 45 << 301 */ + { { 0x08cd60d461ea4256L,0x8031748b9461f861L,0x9c96e1f9019c7908L, + 0x7e6e08f4e46bcf7dL,0x8e8408f123ffa986L,0x0bee857ed467288bL }, + { 0x702fa8536e36fcceL,0x3bb25fa905a89edeL,0x642105f4e96866ceL, + 0x6a5207cc16e37536L,0xcb6a96d1372a3e06L,0xb1c7c85a1da6bc6dL } }, + /* 46 << 301 */ + { { 0x0bb97497a97a3316L,0x9416659ce402a800L,0x79656970503a2314L, + 0x0070a7eef8007c50L,0x8093cd4372624892L,0x4c0ee444f9b96830L }, + { 0xc7c10b9fe300c49bL,0x97f5f90a5f7baf99L,0xf04a5a7cfaa064deL, + 0xd5b01fa6b0c111fcL,0x4d12d6fb65d8a2b7L,0x807a381c27770e2fL } }, + /* 47 << 301 */ + { { 0xcd1aeeb43b6a9c22L,0x7fbdc6c19d71dcd0L,0x9bb43b6e6221669eL, + 0x1b76f2bf526f8a00L,0xaeba54302efdf661L,0xe1f623e745537bbdL }, + { 0x340966ae067c5f4aL,0xe2cdb27e4799b2aeL,0x9aeec5989b8458e0L, + 0x1d0588487655b632L,0xa5ffe5897abd70b1L,0x84db43db6721054eL } }, + /* 48 << 301 */ + { { 0x3b21dc1f538d92d8L,0xc80b22b3c005aa86L,0xf536e5d30da87d65L, + 0x4ce10edf0cd999a0L,0x8949181450e08f5dL,0x77fd8f2e526647e6L }, + { 0xcb207ee9250099fdL,0x03c7d1abfd6aa078L,0x7d4940d225e0cf15L, + 0xb688b311067fa052L,0x89308326a98b2e21L,0x3ee4cc2b72311eabL } }, + /* 49 << 301 */ + { { 0xec49fc4e06d255b2L,0xabd0c002fb309d28L,0x97490ff08c601c3cL, + 0xe17102fd58042cd6L,0x861411f11416ebc3L,0xfb31ce455c6c630cL }, + { 0x0a24d561c6cc5e9bL,0x80bec25c9a7c1524L,0x8003494fbe53e50dL, + 0xe89b75e28633c559L,0xafb1f6d6763b3360L,0x0e7e58c52bf70cd3L } }, + /* 50 << 301 */ + { { 0x72322d26aab6c9b5L,0x953e43d0070d7d08L,0xe2dd5444954645c3L, + 0xc5de051cb276ca86L,0x195d454439158c74L,0x26e2cf9fb90a8f97L }, + { 0x774baec15b217a76L,0xdba4bc63f94172baL,0x96ddaa4022e20037L, + 0xfe1ce4aac111af69L,0x6f6d3c428ad6dacaL,0xe59257d8376cdefeL } }, + /* 51 << 301 */ + { { 0xf2cabe73184d44ecL,0x4bf744d60bb08687L,0x10cb9e9209865d58L, + 0x3a63fe414ea221e0L,0x8f595e5892961becL,0x1b8ad036855d186cL }, + { 0x75dd5f70086542abL,0x8b357e087bddbb6bL,0x22de89f06e829a06L, + 0x44ca8b64ecc6cc26L,0xd02fa871a5ddebb6L,0x6adf1d0c6a60a0e3L } }, + /* 52 << 301 */ + { { 0x0102775982e4f5c3L,0xac8eac172c014fc4L,0xa0cd26e85bd843eaL, + 0x9b0431ec056d4b1fL,0x89df7db58eb9c55bL,0xf17f917298fc9b9eL }, + { 0x2cf1e4a78e6b770fL,0x0d6ef9e2b842fe52L,0x40b4ddb76c578172L, + 0x6630657627533b9eL,0xf8d8661eb50ce390L,0x6ceba0aa16577df7L } }, + /* 53 << 301 */ + { { 0x6dff66c19ec8ac93L,0x6261295bfdf6fe7dL,0x9ad1536fcf9fbbb2L, + 0x5cfa30a92a6d6d31L,0xb3bcf1b0296224dcL,0x42e4b410608371daL }, + { 0xd6bad6dac32945fdL,0x0fab7d1dc0c031a1L,0x054df9599b192d32L, + 0x29830094ea78052fL,0x8d73ffce03f2ce45L,0xc14c7012f9d840ebL } }, + /* 54 << 301 */ + { { 0xdf74522e74ce5c21L,0xf864cbac930c4b92L,0xfe0d2358eb0fbe9cL, + 0x10b31736a5cf765aL,0x185bbbe96a9c95c6L,0xcb14d694e5362993L }, + { 0x3f5c921da5332e61L,0x0820b32bd244cc98L,0xdaf09f24d7c32062L, + 0xb2241c9ad5959a1cL,0x16bb89a3226127ddL,0x0b46e3f03723d04dL } }, + /* 55 << 301 */ + { { 0xa38b1a796975230aL,0x25c6db8c3991b5ceL,0x0d89c3fe9c1bf52aL, + 0xe186e293cd8f9f8cL,0x777bb327e6ec37afL,0xa974132a0ae31c7eL }, + { 0xfb9918305c50f089L,0x4a653d6999497954L,0x5055c690774e8a26L, + 0xf94ffbae3815d67aL,0x99d74f5e74ea4481L,0x3b352a327d477151L } }, + /* 56 << 301 */ + { { 0x2a62804172fb61e9L,0xa9bfa73ab13d053fL,0x4a2cdaa3c647fcb9L, + 0xe1a9e91f4952d3a4L,0xbc1b3d8011e2e2c3L,0xe58ef59c18e4340eL }, + { 0xeb8696ff1cf859b8L,0x5b0f5cc4ee918cf4L,0xa471d6ce6c1e905cL, + 0x4e13d6091ed2e8cbL,0x52951509c77c8c91L,0x0926dad8e234884eL } }, + /* 57 << 301 */ + { { 0xb168a6c36e3aa3d7L,0xbd0086ea5ad9142fL,0xbc4da0293c24fe23L, + 0x7ed3b34808b90de6L,0x7a7a2259e33b0df9L,0x483b389c9c3a173dL }, + { 0x02080c626334a061L,0x61944965b020cfbeL,0xece528e9ede88ecfL, + 0xcdf3e2fc99389758L,0xb21470cb7a3fb92fL,0x717cfbe083937e21L } }, + /* 58 << 301 */ + { { 0xfac97f2910e3e93fL,0x1505c7d2f1101b88L,0x7cea978823bc0d11L, + 0x27ead95d45045667L,0x711bc4dcd17ea199L,0xe3f93fb522f3142dL }, + { 0x31b05e6ad7233d64L,0xac28e6c154e7c9d5L,0x892b6366716d273cL, + 0x1622230470da8a48L,0xc85bbe6070d560b3L,0x555e6de987fd38a0L } }, + /* 59 << 301 */ + { { 0xac593f746ed50680L,0x89bdeabbcb01cfd3L,0xfa43158ead35524dL, + 0xb2393726e8d66ca0L,0x248c67c2c36bb495L,0x27d4b0b85c933625L }, + { 0xdbb1364a78c8bb4bL,0xdcf4b1e13486ef0eL,0x554f95cec498b2c9L, + 0x2b76da29811a2329L,0x750c10271a10d941L,0x07045eae375b01b6L } }, + /* 60 << 301 */ + { { 0xd3fb9bef82621500L,0x09b18748f0f647a6L,0x186bed054c357e73L, + 0xd58281f0a85f3174L,0xdcf2e0bb91ded0e9L,0xe77faad126894faaL }, + { 0x6843c160bc3a3c4bL,0x7f8058944c76592dL,0xc53be0883ec05e95L, + 0x318d8ce7cce0c822L,0x6d615f1b4c761dbaL,0x0115824c46ff47e0L } }, + /* 61 << 301 */ + { { 0x1815391cf8d0b74bL,0x903ad8fd797625dfL,0xad1ca24d3983100eL, + 0x0883fd415572ff15L,0x0e9e572cadeb4e56L,0x800bad6f7d0e25c4L }, + { 0x52a394b44c7e2f03L,0x5150c01398f2c416L,0xf4ab35c68ce503c4L, + 0xa0ad209a41b4beeeL,0x050c52c80189706fL,0x86780a924049e913L } }, + /* 62 << 301 */ + { { 0xa398529c74ded2a1L,0x5e7248f52d7ea6e5L,0xbeb250bc28c2225aL, + 0xf7068fc0b40f4843L,0x62098aed839b7290L,0x947087e293ddfec4L }, + { 0x81ba8c8824d71004L,0xa877f443bf4813c2L,0x3cf5f473ca4751bcL, + 0x2533890e633cc635L,0xb358f7781e6d9465L,0x50693deaa7801dc7L } }, + /* 63 << 301 */ + { { 0xaf306f56cbebedf6L,0xdd733be7837acb84L,0xc767237afcff0b9bL, + 0xdf948f12e555bee9L,0x86b85657826dc76dL,0xa4bac032e702b1c0L }, + { 0xdf3544bba81bb117L,0x69c20dff34f4f0aaL,0x846b78577050d98dL, + 0xde0ef0403c70120cL,0x4483872c12c3bd64L,0x870b758550acebacL } }, + /* 64 << 301 */ + { { 0x37be5d3f68d7dfcfL,0x97bdbd49b945e6f2L,0x165a24b59d1569e7L, + 0x254aaf59b4e293abL,0x3c751fbd6fb7c0a4L,0x14eda4ba5018cb18L }, + { 0xacb3b8971b5f6aedL,0x6d10be441e4b6b78L,0x245d7258621df6d7L, + 0x2af0e283185f0e2aL,0x1e7edc818fddbd81L,0xbd1e6c72c538d02aL } }, + /* 0 << 308 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 308 */ + { { 0x6858b674844626a2L,0x610cd40f0cbba6a6L,0x324e674e29d9194dL, + 0x2dc6fdf6dcb30a51L,0x3f3ecb77528aa549L,0x0721f8f923ffaa92L }, + { 0xd8efcbd627a77538L,0xf4e642bfd6162c9cL,0x04f2b0b74cf4a16fL, + 0xbc0bb49fbbf335fdL,0xc6b6e5bd5a928c36L,0x981b01f4d893dd45L } }, + /* 2 << 308 */ + { { 0xfb083c2af810465bL,0xb66a8de902ce0deeL,0x6e4130e747a81b95L, + 0xcd704dc658a98737L,0x842ae329592829c9L,0x99bedc34be20dd63L }, + { 0xabee8e55d53b2df4L,0x6ce657586010b37cL,0x781f39b2467112b9L, + 0x6f06058fbe341038L,0x5effdca512a2f8beL,0xaa9bdad7af34466eL } }, + /* 3 << 308 */ + { { 0x3933b4c1575782aaL,0x610d3ba25c66e501L,0x52fd3c0f0b7e019dL, + 0x7f8e5ddfa48715d6L,0x0879c5defa39be53L,0xe32c886c56f01cdcL }, + { 0x71b2dcbb1726779cL,0x6caaff052c6aa84cL,0x6af94846640b2d74L, + 0x78a10710049a2cbeL,0x41a1ce67ac2ab0f1L,0xd160b7faa76d8438L } }, + /* 4 << 308 */ + { { 0xab86639e9c216137L,0x45a12fb882b18d64L,0xb5734418d763f0bbL, + 0xd2cc332211a9802cL,0xe41d7db881269b8aL,0x91072fc12ecfa355L }, + { 0x59d6912504ce306fL,0x916d9d4da131b86dL,0x84478b6b8a739738L, + 0xe86ad7d91cc83ae3L,0xbc9b2084797ccd97L,0xc1e94af4694944c6L } }, + /* 5 << 308 */ + { { 0xbbb6725b5c82c857L,0x72c66c3f140b561eL,0xab65dd0664bcb2d5L, + 0x755e848a780d5c1bL,0x84e6f686a3a61e6eL,0xd84bf486bd100b4bL }, + { 0xb34fdf846354e899L,0xcbc312da55ec5654L,0x3c2cc881f9a125f0L, + 0xb1fcce564aeadf8eL,0xbdfc54c0c46bf0c2L,0x11d7ea4f09d281beL } }, + /* 6 << 308 */ + { { 0xe1aa844b1601940eL,0xd22221821797e84fL,0x3025aba65ddcb5d1L, + 0xac8cdaba38009c6aL,0xb9ee07b46e261ee5L,0x84069bc106ab8430L }, + { 0x7a36b46278b9b112L,0x2d91ed2c08e77879L,0xae4ef469341275a1L, + 0xf7cb393f1c7cf858L,0x83c00eafd192af3dL,0xa81697a7a1e15176L } }, + /* 7 << 308 */ + { { 0x687d0980f9bfd795L,0x9a7539377ad882bcL,0x641407fabbcde5b3L, + 0x12ec9d216ed103a5L,0xf858c7851fa6ee22L,0x329b61bc818f2c11L }, + { 0x4720d42ad9d48b30L,0x3f61c66082a66766L,0x99aff25533723e4eL, + 0xd6c67ce3d3260b62L,0x63a6fc9d86391c33L,0xc002433a31de2381L } }, + /* 8 << 308 */ + { { 0x585edee3895c0318L,0x775e142f45e8205bL,0x3bd7924fd85ad31fL, + 0x2e7d8f919124bffaL,0x885397c044c62868L,0xc0c2dff47fda9f5dL }, + { 0xd302582ec14e693dL,0x53d6e33a6cec31baL,0xb0216b5b63653c06L, + 0x8f08a1ad9c70dad4L,0xccf014aaffbba93dL,0x900b0d2ca33f12b7L } }, + /* 9 << 308 */ + { { 0x4960ccb6e9824c45L,0x3c5a9b74c7e4cd06L,0x1e78cdfe37cfec62L, + 0x8cd49ca80da56a05L,0x5ba51217dca05707L,0x0d1f6e459d66c960L }, + { 0x7178089467f9c82bL,0x342e4a5b18974c55L,0x16263f18f9b32fdaL, + 0x844b5a02935b3636L,0x9c5abd51c139ea58L,0xf54c69428beef953L } }, + /* 10 << 308 */ + { { 0xbe51552d6d2dedd1L,0x6bc86dc1cd997093L,0xc9b600c4418f03b8L, + 0x4ea4e857e7a9208aL,0x7aac3d96883b639bL,0x4127ed0735d2f4bfL }, + { 0xf5f6310d76bd792aL,0x3da9b6a5fa223d0cL,0xd75f88075a041b79L, + 0xf3261457e4dd58f6L,0x4f0f5b18b0d9a51bL,0xf5aeedc1b8c84f9fL } }, + /* 11 << 308 */ + { { 0x1e08d6a81375620eL,0xed9a4fbae1f62c24L,0x0d3bb90381ab5de2L, + 0x885781f0df1b6a13L,0xc3fb9f97e1c7de7eL,0xf12e4bcf9372b033L }, + { 0x9bc3cf4dd5868448L,0x89465649552016adL,0xeea40cf92a8b2c23L, + 0x57d720ee3af98886L,0x97b14c0b72db853dL,0x65d10f42f23504deL } }, + /* 12 << 308 */ + { { 0x0dd2395e9b8cfa41L,0x50e203abd4f92a44L,0x7280aff16630023bL, + 0xfcce59dc07de820eL,0xa686be05bc8189adL,0xac4b59bfaac70b7eL }, + { 0xd2c0070e7a3c71acL,0x1d550add35ac1c47L,0xd42b6389fb881c1bL, + 0x57ca3fccd0dafd42L,0x909e8284be26ccc9L,0x1abe7595a002235cL } }, + /* 13 << 308 */ + { { 0x02562f1c6b1878daL,0x52a2cd069fce0ee6L,0xf25b35bdeb16199aL, + 0x0320c326a75fb01eL,0x2006d7587de2d46aL,0x6f9d0e256842b459L }, + { 0x70a89562a68b5482L,0x9653726e1ab35865L,0xbda3cebbd8f849adL, + 0xe2f8d9e60b6fc51dL,0x9c3fd51246104400L,0xbbd260c9bab5d34eL } }, + /* 14 << 308 */ + { { 0x1f5094703cbc1df1L,0x9f752a663f962634L,0x98089d2ca2435048L, + 0x05256acb0e755318L,0x91a21f707f3845f4L,0x473ac1e0d68c8fcfL }, + { 0x57ee51417f2ff0c9L,0x959a84f32013c48bL,0xe701f13c4c111ee5L, + 0x70219eee86db5763L,0x385f890cdb0782e5L,0x81fb64b2fea04d2eL } }, + /* 15 << 308 */ + { { 0x61b4bf7eeaa07bd9L,0x49832879afe544c0L,0xf788e97f54eb4d80L, + 0x78351b41338af327L,0x3a631bba77cb8057L,0xeb9a6f23f218e4ceL }, + { 0xbd4a0dcf025b6453L,0x2aad6a467b876222L,0xaee94361215c42cfL, + 0xf8d1fd5de496cddeL,0x3c3af08022d0fe06L,0xb3d5dde0d09cc3f7L } }, + /* 16 << 308 */ + { { 0x1e34781aa6a1913dL,0x9a8f32287d0adc38L,0xfc185ccc28af85baL, + 0xc923d78b3ae9ba11L,0x7d494d7ea7bdb313L,0xf774dfa5af8f8b87L }, + { 0xc178ccc116e863b8L,0x2d472f2aa8899691L,0x608747cc80a50372L, + 0x8147aa90e6f90197L,0x4683d4c978c2f216L,0x8323652c552f3b51L } }, + /* 17 << 308 */ + { { 0x7d6bff984dc9149fL,0x79879e1f499b443dL,0xf4ec65232aff2a1dL, + 0x6cf3c97f27253aa1L,0x95b9471eefe6f72cL,0x3959bd816c8457daL }, + { 0xe2870635cf112073L,0x84e44933ec12174fL,0x67a592deedf434edL, + 0x0c93cdae2897d0e0L,0xe344ecf463c89730L,0x28098b7567a1133fL } }, + /* 18 << 308 */ + { { 0x62e96dc7a12a0cd8L,0x09d7c6f0f02a3d87L,0x9d9fd51233f8929dL, + 0x1231952dab376555L,0x6ef6823c8e3d2d63L,0x7ad2e5405a01c12fL }, + { 0xd1bfaec479af6fc8L,0x4555fedfdad97daeL,0x0e6d3f0155750bdeL, + 0xd37ed9f0056f6128L,0xf1fdf91c65fe6ff7L,0x3ece19ae92d05e43L } }, + /* 19 << 308 */ + { { 0x07d2075e750fc5d0L,0xdc2b03f6a07ca45cL,0x0248d87552efef7fL, + 0x2dfdaf3f744e727eL,0xbef861b8d9b2bcacL,0x5e6363f0baf394c7L }, + { 0xe8f23bbec973934cL,0xb43d619a50ea324dL,0x2bd5e0075842d6cfL, + 0x5c5af62217646e90L,0x5d95d8fd222ec05eL,0xc9adabb45bd67c31L } }, + /* 20 << 308 */ + { { 0xa5c08e8bcc2c9a2aL,0x70e1b4058baaf0fcL,0xf29e1e5c9e36e50cL, + 0xa3d9080080f258c5L,0xc9ceac25ecad4498L,0xcb73130fca32f3feL }, + { 0x2dbe620c48b3863dL,0x8c52727f14ff53bfL,0xb60b22a86b45e9b8L, + 0x81e05bc0f6483c5dL,0x217caa6bcd542972L,0xffab716afa780778L } }, + /* 21 << 308 */ + { { 0xaef1278b0ba5a344L,0x253be7ad2d0c3947L,0xce58bf0fe5408f09L, + 0x867b0d6fe21228f4L,0x815abb5dca61e691L,0x0da28f58f3e94434L }, + { 0x5b0fd178ca4cee2bL,0x8989604240b13224L,0x8e2fe19616c251a7L, + 0x7b3381cb11b17162L,0xc73d96a427ef2c0dL,0x76b7fcf36899c135L } }, + /* 22 << 308 */ + { { 0xcaee3387cad8b585L,0x58446c1ad59d8777L,0xb8755fa540888d8cL, + 0x7868510654428813L,0x7bd21629136e2b59L,0x249903a6998254a3L }, + { 0x2cc73a751f8fd813L,0x4b1a64576d4f3a70L,0xea2aa620b2e7a0fbL, + 0x77c8cb98202f6ddcL,0x68ba9d261e3851cfL,0x936fe8cbfe02e6efL } }, + /* 23 << 308 */ + { { 0x8b84121bda75aba3L,0x4440272d74602c33L,0xb8110b2a1e8a8ab0L, + 0x4de462e9391cf47dL,0x9173d756519b9ab4L,0x3df52d13ba8d5dc7L }, + { 0xd7a822eaa418b01fL,0x58be2b076585f7d8L,0xaa814fde00fb449fL, + 0x6b8260fc7da43c5dL,0xaecbfb442351ba9cL,0x9cbe3d199f8db60aL } }, + /* 24 << 308 */ + { { 0xe5d3e0d80d7410d6L,0xcfa9ed742be432c9L,0x60044434a85a0686L, + 0x93b357166ad6918aL,0x1a3c3e6d051762beL,0x80813589b0ab32d6L }, + { 0x64214b92aad403fdL,0x684befc14d3fb746L,0xaca5a51479515046L, + 0xacdba03472e84485L,0x61aa2834287d9e97L,0x07a515a5cad222e7L } }, + /* 25 << 308 */ + { { 0x8f631b17bc04e9c5L,0x017527212c515161L,0x4358d8e9ee7769a5L, + 0x18f0aed0b59dba1bL,0x035c6bb644973218L,0xa49a4cbcfb3897e6L }, + { 0xd2a0b7505841ab18L,0x8fe952dca6d2d43dL,0x2d30add69a71d0ecL, + 0x0cb84c402c5d440aL,0x33f3cf7c7c47846bL,0x88703c65bc8e8b3dL } }, + /* 26 << 308 */ + { { 0x3c3db9419474059cL,0xcfbf13ad72820ae8L,0x3f84300c51c37d62L, + 0x0f78adc45529d333L,0xa19be46482e34cfcL,0x9ed07ee011c98376L }, + { 0x5113e660b5b6f6beL,0x56f2d2b37a5bc818L,0xd99290c61c2c822cL, + 0x39c026b8b27aafceL,0x8692150b12ef7c76L,0xa55426d1c6de9e16L } }, + /* 27 << 308 */ + { { 0x889aa8ee3465358fL,0x5885ee29afbefa70L,0x05f9dbd290b6ff58L, + 0xc74be0d09b5e02afL,0x4b7da27ea6b29d44L,0x2ad60aefcf68eeddL }, + { 0x2ba942b3388c81c5L,0xda8badcc368e2e62L,0x33e95ac87a9e8511L, + 0x37453bbae72008b3L,0x3e1f181195eceea0L,0x719f550c7b19a417L } }, + /* 28 << 308 */ + { { 0xb03093068af19670L,0xd784125a34c6bf0fL,0x0b425ee0255a8396L, + 0x91076433fb541162L,0xc4d8188586f47a0eL,0x3b767d54fd7bc7c1L }, + { 0x98b405d3bee196e9L,0x4ef9c511edaccf4aL,0x5a6deb6503f4f1a6L, + 0x4a22ca641b4c5104L,0x2cce36679145ce41L,0xd05187523206810dL } }, + /* 29 << 308 */ + { { 0xa5746e07f7e11342L,0xb50e390f2e2ddca0L,0x3847749bcb288bc2L, + 0x6ff43ec646ee679bL,0x343b3fe2c5257b02L,0xc0f57f509b823eb7L }, + { 0x5ce3d2c8aff42c7dL,0x984c9b99c3c76f3fL,0xc8559f58b8823b92L, + 0x883ac8064ce4338cL,0xecf8aac3389d8ebbL,0x9edaec10b40bfb16L } }, + /* 30 << 308 */ + { { 0x0ed8a07cafb04e5eL,0x7e95ed898f6bc911L,0x6a4ed37113dcc222L, + 0x9aa3a43296f07c7dL,0xe819a80b9b338e4dL,0x65fc2778278f53b5L }, + { 0x788408e9024163b3L,0x159de8bb7de54f06L,0xc953e21281239dccL, + 0xacb5ea2c6dd62ce9L,0xf56ac93b753f4ab3L,0x2a1a09b5eacc39a6L } }, + /* 31 << 308 */ + { { 0x89dcbf021c5f4cb9L,0xc0fbe7ce210f98ffL,0x3dc3c743b897cdf2L, + 0x931f9dbb5d02c43fL,0x0ea9f164f74db981L,0x504938874af9f53aL }, + { 0x86bd3ed62531b8aaL,0xcc1fb6dddcfca2a3L,0x24b0cbf2b97abaa9L, + 0xd81ad35c9073f19eL,0x4dde5dc05db7fd5cL,0xce410880e3ac9b63L } }, + /* 32 << 308 */ + { { 0x29d81538037bebadL,0x76e52c73d9e0b78cL,0xaa4ace6e8783d1fdL, + 0x9c14ebddf0e3c126L,0x0eb1c08d6eca4b71L,0xd10c6b961c91df35L }, + { 0xdb8119bbe81bb84aL,0xf784d3c117e3ceefL,0x053c916835436f81L, + 0xeb41ccbb9b18d212L,0x93b3fb43b1bc3497L,0xd85a7c758c1ced81L } }, + /* 33 << 308 */ + { { 0x90b606b2fc9958e6L,0xd39965b6f94234b9L,0xf4a86f1676f4dd03L, + 0xd6a7ba54470f0f7aL,0xa1b85c0ca86fce7fL,0x2b50f14e574c4cfdL }, + { 0x4aff867d80e783bcL,0x031092eb61f78fc4L,0x8ad0d7486fe0af1fL, + 0xb56b1a1a0cdfa574L,0x586c916a56466e12L,0x427e5946d09a9d1bL } }, + /* 34 << 308 */ + { { 0xdd0e3ca276d1b2e5L,0x07dea7e48b4cb3a6L,0x62a63cc7fc4a0f0aL, + 0x048478ef5ea2eccfL,0xa77eae472e34c1a9L,0x7a2120751bfa5dc6L }, + { 0x0c1fbbecabc233ffL,0x6255fd91dee18d7fL,0xd6da39aec38462ebL, + 0xd86bc3194be435f9L,0x23567d64291c606fL,0x6b85038af67051adL } }, + /* 35 << 308 */ + { { 0xbe79e1b1eef4ae7cL,0xa45668dc42fb7357L,0xcdb3b3ee2d497a36L, + 0x6ef724e6c5f8d861L,0x7e8834523802a324L,0x641b3a81aba90442L }, + { 0x13bec555ae4c2544L,0x340d34f927d172ceL,0xfcfd933bd92f558cL, + 0x57d8e300d5a669bdL,0x9f745ce71883049bL,0x19690a31e261f9ceL } }, + /* 36 << 308 */ + { { 0x004105c3811af84aL,0x01307934a7934a0fL,0x179fd49b9b3226a1L, + 0x195d9e5cde6834b4L,0xfbb79dc00e6051bdL,0x354273ed367f4487L }, + { 0x4afa9d4574fb892dL,0x03ae905ea1b7f3bbL,0xea32cd5d592f6122L, + 0xa758eed2f1103301L,0x9dde4238c59d1cc8L,0xe2760bcc51022a42L } }, + /* 37 << 308 */ + { { 0xfed7077b7a7134a8L,0xe65b4eaefe0cf05aL,0x130de76be626841bL, + 0x499934ca300117fcL,0xce74885d4e186b5cL,0xd352d0d2029bee7bL }, + { 0xd86c448c857a38ecL,0x8139eb50a956da9eL,0xa036de4a93ce7131L, + 0x3f9eba375041c9d4L,0x8c24408e548f74fbL,0xa74053fde942bf8fL } }, + /* 38 << 308 */ + { { 0x64cb00f586ff10acL,0xd1eebc4c9cbba8d8L,0x427fad8af3157125L, + 0x9f8eb84cf7523b0bL,0xbdd082bf2e6dc29cL,0xfe40623823d3c315L }, + { 0xad5df7fb546d9dd4L,0x83cadc4b8e42f3c7L,0x7c90502c36876485L, + 0x4f33eccda35bb6d2L,0xdf7571383a79b9baL,0xd250b7d2e6ddafaaL } }, + /* 39 << 308 */ + { { 0xa52a7595504417a1L,0x540f70b014683af9L,0x5f0d1560f27a9620L, + 0xccad06444b2147c9L,0x92223275e52c8eccL,0x30d6b52b7cfedb7bL }, + { 0x2161f8bb9bb5b844L,0x075b9db87033586cL,0x5748d512c8c5189aL, + 0x95d76a950f0aab91L,0x91f85aaed0ce9c56L,0xeab8cd9b8434e695L } }, + /* 40 << 308 */ + { { 0x54f84d70d377d7b0L,0xb745d1903344bc4eL,0x1c693ed08f33aa53L, + 0x990ed45f8bfbee7fL,0xad620c9fe9b258fbL,0x465ccb101a54bf46L }, + { 0x5330a0d3ebc40951L,0x34423e8ca405da61L,0xeef1ce78b83043b6L, + 0x99678f22ac06d182L,0x9213f57d1802f14cL,0xf8549616adf11fdaL } }, + /* 41 << 308 */ + { { 0xc6ca95476c66fa6eL,0xcae41345bdd5b16dL,0xd72a41a4ef022783L, + 0x810f4615b2d5154aL,0xfddc469e6d333af9L,0x3154ccbb02d2bf38L }, + { 0xb33d5c59fc1a0bdfL,0xd8c3f8743c971fb3L,0x5e47ec01114e68b2L, + 0xa440a83fe9baa164L,0x353d01c397c26b35L,0xfaabf5dff03b7672L } }, + /* 42 << 308 */ + { { 0xdc2a97651e22de2eL,0x91eef436b6cd3b6dL,0xff099200f99ac721L, + 0x20faacfed4f89e8aL,0x91bb24373fcfe45cL,0xb7a152897b6d3ff6L }, + { 0xfee966c0ef94332aL,0x944728473c81b942L,0x831d36dfab1a553fL, + 0x244bc8393023cca1L,0x3f4a49d57e7be940L,0x4159aa9d7b71c0e0L } }, + /* 43 << 308 */ + { { 0xfc25fcab5b16ee64L,0x44f807e06841acd2L,0x5f43cfedf59c3f06L, + 0x9279c8110c5b59a7L,0x825df117194b80beL,0xe2c18880d27d6fa7L }, + { 0xc9aab2e66a333721L,0x1665b6f55b034c1cL,0xf28fffd13df9796cL, + 0x23caca87bbefb8a2L,0xfc556d575f7510f0L,0x41990ce8552dafd0L } }, + /* 44 << 308 */ + { { 0xf31796d2b6e392e1L,0x199d624893b3395eL,0xef14c7c212f9b763L, + 0x721ebf2143edb7a5L,0xa40b88945e96f3baL,0x8770608c4cff8394L }, + { 0x990c99ae8d0def0eL,0x292b26dfa15a5649L,0xa98fda2c91ca89d7L, + 0x916cb1b4973e5f5fL,0xa2823f13a72de0bbL,0x415f7bd28cd3219dL } }, + /* 45 << 308 */ + { { 0x5cfde16a9fc0e90fL,0x61bda4caac6c15d3L,0x5935e48e2a79d928L, + 0x31213c7c82f986eaL,0x170dc539bcc4c0dfL,0x2e0d29406f11823cL }, + { 0xd2dbecac80fe659eL,0x98b7f46b8399d8b8L,0x259f975abb204589L, + 0x65f3073cd5c52a46L,0x0f4c007805dc7fc4L,0x16c49d403031a8ffL } }, + /* 46 << 308 */ + { { 0x95705b15359816d5L,0xce0c4379d0641ed7L,0xb3f0d8321e8a448eL, + 0x8bea060873e2d711L,0x5a85fb2f6a040c03L,0x7c19a2185bcebd4aL }, + { 0x2b10a87aa31cffddL,0x4fc728fa9a5814a2L,0xedabb0dc63bdd2ceL, + 0xdb90173f96bdaa40L,0x543c4f01527ff659L,0x5dbff7ad0a33b251L } }, + /* 47 << 308 */ + { { 0xeef30ea55e636f5dL,0x8df2d4040bccc4ddL,0x8b0d6f35ef1afe9fL, + 0xbd288e6ef8f86f6aL,0xbc68817ebda45411L,0x8a6f50070faf9e7bL }, + { 0x6158c57a53d4050cL,0x6d5a3af165b2252cL,0x10f62839f450886aL, + 0x8b9ac19b1df85080L,0xc160c1567553ed58L,0x2195ab29cb449cd9L } }, + /* 48 << 308 */ + { { 0x521f4af73ed03d5fL,0xe3461f66eaf9064cL,0xad099ab7ae03777fL, + 0x541cadcdb65f73ffL,0x53430463a86059b9L,0x8ff88fe5043e9f82L }, + { 0xd515f4c7e42cde45L,0xf7f3dec3f41c3269L,0x7bed53567ef1b8ffL, + 0x8782b45f1295b5feL,0xab54ebaa03917627L,0x8516beb28787ed9fL } }, + /* 49 << 308 */ + { { 0x24b2b95b113940daL,0x8c24d8d3f9c6e6d1L,0x7c584170eddaaf29L, + 0x249267171efd01aeL,0x692cf8f40cd0f2d5L,0x0bf82e142f960244L }, + { 0x6dbcb6162dabe927L,0x76d826d20aa1eed3L,0xe4492fb3be98af99L, + 0xd4f27cbea50dd711L,0xb7796efe2d8085daL,0xf2d42519ec4e8ec2L } }, + /* 50 << 308 */ + { { 0x3fbaf46dccc3c261L,0x773c240c1b646e80L,0x151a711f363b6a5bL, + 0x3c8680b1c53b5b59L,0x8ee6795f9fb234b6L,0xab7840aa2f673211L }, + { 0x0a1a0ff3224a8184L,0xcab87319c71bb575L,0x7a9e9daa8125668fL, + 0xdc607b016c4cff5bL,0xa54cb4c792e5c760L,0x977e4c93d99e4655L } }, + /* 51 << 308 */ + { { 0x87d4ff71ebe95680L,0xa2093915e5adaac7L,0xd5bbbdade32f5d9aL, + 0x5d61056cf328a4e1L,0x61fcdb0f353f565bL,0xb7b8ba004efab5caL }, + { 0xb5bbcfa410f05eabL,0x483ae9221f09a105L,0x17d94ca44bbf4753L, + 0xf734a8cdbbdc9a94L,0xc7f01a4244e81e2dL,0x60c3e777b3ba8033L } }, + /* 52 << 308 */ + { { 0xba7df5a965b68624L,0x30b4d6ed6e7d58bbL,0x67e52341dbb81762L, + 0xd697ab1b0deeac1dL,0x01d15e8e5577ea92L,0xbb12d72498fb38daL }, + { 0x302faa6d4e04908dL,0x66cf6cb909b90a9cL,0xcd665dbd98d96736L, + 0xf7d3c528b86f3af4L,0x4844c7541d8b07f4L,0x2a77d7b91eaf7dc0L } }, + /* 53 << 308 */ + { { 0x8a36c9b57fceaa87L,0x5110912b553c7ad3L,0x4aa51166d5eca67cL, + 0x05740dcf07a5eb58L,0xeaafb3e3396857a4L,0x1ae9571bba8d62d9L }, + { 0x2736975500272434L,0x2c74325c59872fbbL,0xd1d8291709dda11aL, + 0x2a5334eb4683e8a1L,0x22cdd088e3481df0L,0xab1c5f5b4fddc546L } }, + /* 54 << 308 */ + { { 0x1966aa0515f46174L,0x495901bd2a074050L,0xda5b0cdebba902baL, + 0xc47c518a684325bfL,0xa5df133ec4d9d6d9L,0x3771f465fbf7d31aL }, + { 0x0a73718c02b05d1aL,0x1107cd45534237a2L,0x582cfd2980f5d897L, + 0xf51a0a88dab0269eL,0xfdea51cfea1a22faL,0x3c9a0d247a13a324L } }, + /* 55 << 308 */ + { { 0xcc330f58c42f1ce6L,0x8e1fb7df534efc38L,0x2a37208f5fa5a01fL, + 0xc06d8447369bdbb6L,0x0b1ea5161a3e36e7L,0xfb4a48366ff9abbeL }, + { 0x5989c2d524419909L,0xdeaa6136f1d5b1caL,0xac6003b04ba760f1L, + 0x3a6d5422059081beL,0x96c7fa9df797e22dL,0x67c2f77fa9f3addcL } }, + /* 56 << 308 */ + { { 0x53e59f251d70eb73L,0x8aed17afe69d0525L,0x26ddc17864413768L, + 0xa7c8d40f5e48c349L,0x29ad92d187ff01fbL,0x8f4e1b3b965b2de1L }, + { 0xb83cfadf1446eca2L,0x7432bda4e609d416L,0xcf97e8a3f1c7de69L, + 0x45899bd832f55f07L,0x41a6811751175738L,0x89eeb115b8efff21L } }, + /* 57 << 308 */ + { { 0x9dcda4f3723fc25eL,0x710de79fb5d954deL,0x095ffbf1f0b7d129L, + 0x419a2a5e32651179L,0x7b249135827d4268L,0x9dccc98d909fbfb4L }, + { 0xcb4b0cb016554ab5L,0xb2fc635f6d84b255L,0xa7f8f3f553512b87L, + 0xc72633f300ec778bL,0x4e07d91a4f1841a9L,0x2a1adbbdcb4f478cL } }, + /* 58 << 308 */ + { { 0xe31333093bb794fdL,0x34c68bac33b3be44L,0x953fa2c412172b7aL, + 0xa9afc12d4fdde6ffL,0x30b5302ae9c7804cL,0x4a1746c702119e68L }, + { 0xc4d0c7d323e2ec51L,0xbc821f217143d613L,0x8f41251a673e203dL, + 0xfa32c06aac2ca4c3L,0xf4343f2799a7c431L,0x8f7d489e6b96d959L } }, + /* 59 << 308 */ + { { 0x183311763f6278f9L,0x4fcc5b653593cdd5L,0xb09b5880e643f83dL, + 0x0f130a3d2c78466eL,0x926d7c3d2b1c1ebcL,0x7217f875662ed4ecL }, + { 0x2d3be028d81cdad3L,0xb2a04e3507a38019L,0x8da8cddfc9a3097eL, + 0xbaa67f60ddb20228L,0x698fc1c407f04de8L,0x6f0e1d6d7e86db6dL } }, + /* 60 << 308 */ + { { 0x54a01e60936c3ebaL,0xf326fe96ec01b12cL,0xcdfaf00366e4de2eL, + 0xc53dba07392fd0a8L,0x00d9b80f6ec46004L,0x84d59be83ba63f8dL }, + { 0xbac4ea439dea6062L,0xb4b4845badd568caL,0xa6ca3d34d225e2d0L, + 0xce72955db50070a2L,0x56e5c91321c78b68L,0x888eb198999488a3L } }, + /* 61 << 308 */ + { { 0x65bead3c1c2de335L,0x0ecdc057b18a6778L,0x821b836983e57ea8L, + 0x84c80b574a5c11dcL,0x0b6432822ac9ad27L,0x8e09a7f344fe943fL }, + { 0xe510f47daa92dc94L,0x8bb0b5cc6a1666a3L,0x55315bcc24645380L, + 0xe3acbed113dcf7a1L,0xff99c90e3c9a1610L,0xfbe9aa1bc326e1f5L } }, + /* 62 << 308 */ + { { 0x5040bea56827b6e3L,0x1049e004d935eb24L,0xa15f9a07ba9bde68L, + 0xda430c55e6087e70L,0x30ed69af8e84b7c8L,0x8498514eac9d6a72L }, + { 0x69c783d64cb27e79L,0xe55d31a09647a572L,0x0479e8b2fbfb82e8L, + 0x3e845922b52f08c0L,0x252f755f0dbca622L,0x6219778389ddfee8L } }, + /* 63 << 308 */ + { { 0x175264893ca1461fL,0x54c432f92b6476bfL,0x0e0be36a530795f9L, + 0xb9896dacca583429L,0xe4af98239d4e6085L,0xa38b7c4b4a7422ddL }, + { 0x74643ef47163e421L,0x74c28314895ee61aL,0x637c79c20d62b657L, + 0xb232ec619bf2b3afL,0x27bdbfb4b2d5992eL,0xcc6e424c49afb181L } }, + /* 64 << 308 */ + { { 0x5255508c11c92f34L,0x9a346cf3a294d382L,0xd9765eea3095205bL, + 0xfea2ed702c470ef7L,0xf5e8a0fc9c40bf0aL,0xb572390ee4137a16L }, + { 0xb91753712bf2f545L,0x2c2d0f4c58cd9cc7L,0xbea6bce902385486L, + 0x46208408a8bc3a94L,0x64a87a2a3ac45044L,0xe40da33c7df70151L } }, + /* 0 << 315 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 315 */ + { { 0xee9e25d939161b8aL,0x8763f2a2e2eead91L,0xd2fc1157d2d91300L, + 0xe7597e2fffcbe50fL,0x4be3814fe11d376eL,0x1eab3d7edbf14562L }, + { 0x38a107c0c0ad183aL,0x829766267c753bbfL,0x18014e09caebd481L, + 0xb28c331bf9ace60dL,0xe8fba04f211cb8e7L,0x41c4b797e42dc65eL } }, + /* 2 << 315 */ + { { 0x009dc2f4c3e88580L,0x4a405be899db1fb5L,0xc89bfaa2ec5d91feL, + 0x461be9a0f160afcbL,0xfdd084bb7d7566b5L,0x795275e8e48099a2L }, + { 0x1b461fc9fe9815dbL,0x576214cd73627bbcL,0x3246332d9f09a206L, + 0xbde4c0c36941d6efL,0x44ef03fdf387f5f6L,0x99c8ac0157b63400L } }, + /* 3 << 315 */ + { { 0xaa512f202f6e4301L,0xef668a5fbf94a1ccL,0x08713c3015861b88L, + 0x49d47551c99bb2b6L,0x6db5f812e2f0258eL,0x70c9b299998d7435L }, + { 0x46168e1c5d176ae0L,0xec3306e4f730ec30L,0x49439df3ab69c15dL, + 0x1040408bea0143e4L,0xb48ab8eabc549b0aL,0x4aa38bbf10f89223L } }, + /* 4 << 315 */ + { { 0x7e4851599598f49aL,0xbdac3d5e9629305bL,0x20de0dafa6fbabfbL, + 0x04f015838f09fff7L,0x5a0562976a06994fL,0xf51dac8f6e3ccd33L }, + { 0xc087ef9c3af507b8L,0x525ab76e6a5c6663L,0x4fc04814d916ee93L, + 0x3369c978d23d140bL,0xb0fcd70f1662028fL,0x2ca77de2e1e28adbL } }, + /* 5 << 315 */ + { { 0x838acd1bc512bc71L,0xac06d6bddc18afd0L,0xc991c1e39ec45f4bL, + 0x667c5e89cc27c68eL,0x0e059b04ed07f829L,0xceccf1d4cec4b3a7L }, + { 0x3d9c2dc9b953f9a1L,0x4be2f7e72d599b16L,0x1a2054b197256c26L, + 0xcf66fa478b4fdfebL,0x896cc1b38134d7efL,0xa17264cad41dadbcL } }, + /* 6 << 315 */ + { { 0xe3ccfe8e37627e56L,0x00733a867b6b21a6L,0x3f13e2cbb605c427L, + 0x5ee12395b0d80992L,0x4dcaea94b9991381L,0x4cfed7ee8c4c4b6eL }, + { 0xd7aad54b7f7f45dfL,0x2229407fb3809bf8L,0x6eb31eee68048fd9L, + 0x693842dfd57225fcL,0x3e62cd85a88dfd3fL,0xc6307d53d5462cf1L } }, + /* 7 << 315 */ + { { 0x2d15615ef344f5fdL,0xe0ba6a8aa7f23989L,0xbbfc58041c84e3f2L, + 0x22ffeaae6f4ba826L,0x1e9bf27494292682L,0xc768f89146c02af9L }, + { 0x894127d6177cdafaL,0x8d0523da2acdc791L,0x71ada9aedc78c3c4L, + 0xf21dbbb92c532a01L,0x0c797d5eacb20fdaL,0x1ff99d7616cf57b0L } }, + /* 8 << 315 */ + { { 0x99b5f150493c1d64L,0x3422b656fb74075eL,0xe7493900ff19bf24L, + 0xc82e5b80260925edL,0x3398d340c0ea1eafL,0xe7de2ba11287121eL }, + { 0xea6dfb0b87847031L,0x73bed0a1566af2f2L,0xe26678bf12012999L, + 0xb5369e4d32e5cebcL,0x2304eac86d181e32L,0xafdbd9543d364addL } }, + /* 9 << 315 */ + { { 0x5b1a53ca75da4189L,0xa90485802eb4862bL,0x319424092783ad6aL, + 0x15a4c5e11a9e025eL,0x841bc53313837199L,0x6e9d3e14e642954aL }, + { 0xf4a02bbdd436ec5cL,0x62fe177bc6d6ad53L,0xedbf1e4eac86425aL, + 0xff9359c8d9f752f5L,0x79c685d92d7ad656L,0x8d82c0c4fdde9052L } }, + /* 10 << 315 */ + { { 0xf55f868e702f640dL,0xe459aa9b1dedda11L,0xbec0ff9bbb5ba193L, + 0xf7325c4957724703L,0x5ab8f06323e0e4fbL,0xfbf02e91ecb0fd7cL }, + { 0xcc72e8daa2e5fa31L,0x47de252832cb53cfL,0xbfa646e64252763cL, + 0x7a769efeb8d81de3L,0xf5ec70031e772f00L,0x049bea9a2729aa5eL } }, + /* 11 << 315 */ + { { 0xe987ba54759090d6L,0x904d6901619ef08bL,0x9e16d1382024a6fcL, + 0xb6f0459ba9f3b7e4L,0x1f2a530817ee069aL,0x99403b2e2be31049L }, + { 0xba1663c6bfb2f288L,0xf829195cc7a92b41L,0x89b915ee8ae621b1L, + 0x3fbbb1e150f8ea92L,0xb1fe7f978c901ddcL,0x16d1f62cbbc69ca4L } }, + /* 12 << 315 */ + { { 0x51f19bb3fda072dbL,0xa815459fe3f7e0a2L,0x5f7cde2f987112caL, + 0xdc51d948759de2cbL,0x9d05c410ed49bd98L,0xf063ab99364341fdL }, + { 0xd7869d68d1aa0a11L,0xc20291065d862d01L,0x7f258180c2591073L, + 0x7b90fc7a6ebc4ebcL,0x5565390f3dda1d68L,0xae77fca8a44e4493L } }, + /* 13 << 315 */ + { { 0x97564e4847c49ee8L,0xc56bb5a9ab4ebef5L,0x80d969417b4f86bcL, + 0xa594b4e541026cf0L,0xd56c89965a89ece9L,0xbcf609316a0f922bL }, + { 0x702596161103475cL,0xb1224fb58a2a2abbL,0x0a437a03715cd61bL, + 0xcbe2d2b2739921edL,0xf3b1b5e9385541c4L,0x5d0984f4ae010520L } }, + /* 14 << 315 */ + { { 0xb4a2742dcfd9295eL,0x9cd36774ae929cd0L,0xb15fadccdd7fcf4fL, + 0x0b1fa2b337d4fcc6L,0x242c7b26f01c7ab7L,0x2be8131b50574cc9L }, + { 0x6ee50f42bd89a03cL,0xc7f6ff8f005e7765L,0x04d13af18420501bL, + 0xc22e092b1b6e7d2aL,0xa393be7ee9516f80L,0xa2593652b80bb5b5L } }, + /* 15 << 315 */ + { { 0x5caa5da68b23bebbL,0xa1ad33e81fdbbdf4L,0x18dc93cf4e5c1de0L, + 0xc3e6addb5bd9e178L,0xf30d517e7cb8cd03L,0xbb84ce54f1abc417L }, + { 0x0774b64c67699659L,0x228005b9b7d4a401L,0xd8c2ec5b80b2d3d2L, + 0x419c4cd93450ba7fL,0x520ae681789286a6L,0x24b67ea9aa8bcfbbL } }, + /* 16 << 315 */ + { { 0x9e41b9b70f74808fL,0x2d835dae0c061bdbL,0x67e50c8cf272346cL, + 0xc98a5ef5def57493L,0xc2dea8afa02676fcL,0x59508de26ace4659L }, + { 0xc2b707aada6cd733L,0x6c1f226a4be7bfb9L,0x5b580fa2a778c20bL, + 0x272c3a1d57af166bL,0xe47a64a9ca78ce62L,0xd12db7d771d35087L } }, + /* 17 << 315 */ + { { 0x6a37ac5a2ada7e64L,0x664594de04e35dbdL,0x3a82f748ffdbf300L, + 0x4525ddf155975f5dL,0xcfe5a76bbdf2035fL,0x1693a99f0fcbda84L }, + { 0x5bdb76856a297cdeL,0xdb9ad0cef1d1009aL,0x9e9dae1caf902a00L, + 0x7e36f79f271a0a50L,0x688a0f41a2a2f652L,0x33d2178613722e40L } }, + /* 18 << 315 */ + { { 0x2f4abaff356f4ca1L,0xa2e419422d13be2bL,0x58d72e2f3d7db731L, + 0xafc2f505cd455649L,0x8a0794cd1583705cL,0x4a43066288ffe8e7L }, + { 0x2c0c031d135c8e7cL,0x8ecd9ed76b371b41L,0x17cc1ad9563843eaL, + 0x9603987cfc6b810fL,0x6e291ed7f0d9498dL,0x8c69ae62e1a4058dL } }, + /* 19 << 315 */ + { { 0x934666dd40680b5aL,0x37a9c6ac91e762f6L,0xa0a10533e4d26e7eL, + 0xd811d558ade18237L,0x6e2918ed411b121fL,0xbd9352b93c24a52eL }, + { 0xe31569ccb811ec4fL,0x3b5b977553f7d097L,0xa0d9ebfd7198e959L, + 0x63e10ab13f0a942cL,0x65b8b87f8ea55897L,0x935ea3c129aa0212L } }, + /* 20 << 315 */ + { { 0xe14dd3708ba8a3dfL,0x49c1fc3750a645b6L,0x3f0db6a32252ff87L, + 0xea2ac3c4a34ad040L,0x97a37936decf9f0fL,0x810f02326f7f92ffL }, + { 0xd96c2641184e9c88L,0x08c4cd333d5ab12eL,0xa938d8c3eda80fdfL, + 0xf2dded68bfccc054L,0x4b3da61ede36ac9cL,0x2c266df8347ef904L } }, + /* 21 << 315 */ + { { 0x4653cbfbe3443739L,0x53ea14dd8dd85382L,0x2f6d0513f26ba2fbL, + 0x374d9bee51269be1L,0xf976cdb243f1f612L,0x68b47bf7b5f171b8L }, + { 0x726e93dc7095f377L,0xe6f18c57b59fcfb8L,0xffb56a4023d9eb60L, + 0x678c9508447caf79L,0x4cec83e459740ce0L,0x820ab7eff4d7d58cL } }, + /* 22 << 315 */ + { { 0x88eac51c8e376fe4L,0x096e70c49ef465b6L,0xb35265852004969eL, + 0xbd581669d29cc63dL,0x88094298745b6919L,0x317e386c12e7d67fL }, + { 0x33848bb2e3d6f4daL,0xbace887f2a0ca785L,0x83b32feb197e67a7L, + 0x2b58535ade9c851bL,0x3e428b19c38beaa9L,0x784aa3d174f26de1L } }, + /* 23 << 315 */ + { { 0x10c5f1e5b292efd6L,0x47d92b88ddc96103L,0xc8743717e5e802e0L, + 0x47781ba8008dbb2dL,0x7abcd3acf02360fdL,0x673e2b05e9142308L }, + { 0x501db7c76db93818L,0x285ced71f33dbda3L,0x30aa5fb5cdba4b44L, + 0x93d536c2df0445b0L,0x28a77bfa10196091L,0x26b9f668e38c4c7fL } }, + /* 24 << 315 */ + { { 0x98c3a697c0909659L,0x35c3b0f297d847aeL,0x67d9f71273a7a5a8L, + 0x28e83651b47bed08L,0xfca9e849567b3410L,0x5fa9a6ded291fe1fL }, + { 0xd79682421976a995L,0xcff5bb36a0261383L,0x34166ef962e9922bL, + 0xd816b0342d433139L,0x3b62d3589c4b99c3L,0x8521f917104f7cc4L } }, + /* 25 << 315 */ + { { 0xc35a5c7874e09962L,0x1c340269e1690418L,0x2ed61ab4dca0de49L, + 0x2570d29ede2534ffL,0x9077691bc5143c88L,0xaa249a4a346f3ec1L }, + { 0x57e4f1e104de76b3L,0x206859c3f415b99dL,0xdac6f415f9a15eb1L, + 0x2bf456d00a9501bcL,0x1ceb7dc41ef91323L,0x19c1fa8c3cb8afb0L } }, + /* 26 << 315 */ + { { 0x7761d8fc6f7b6eafL,0xdc439bfdcc0575e5L,0x33853d91f1ff4383L, + 0x6da20e4b75dc1254L,0x25a53b581969a1d3L,0xb40df56723311968L }, + { 0xac150a297dd6aaebL,0xfe6865ce2a3ba337L,0xea05d97cf71013feL, + 0x0ab3cf008053c65aL,0x7cd38b647bab4869L,0x788cb867204cc6a5L } }, + /* 27 << 315 */ + { { 0x253a041e36e88e48L,0x1610f836b86297fdL,0x379d3da109334bb9L, + 0x62de4308777fa7a9L,0x604a46bd6dfefd1dL,0x9e4740ae314eed76L }, + { 0x40ec32e12efde5ccL,0xa5b841bdd92c1faeL,0x01852e23dec68e16L, + 0xc76173b88b55b2c2L,0x4609f350377d5e77L,0xe9c4167ffd67c6b2L } }, + /* 28 << 315 */ + { { 0x52732a0a4b0fc112L,0xe654744e9d125dddL,0x9f76cf7e269beee7L, + 0x2fb8bf32ff80a2f0L,0x1bcef16262b7153bL,0xdedc255a43a4201eL }, + { 0xb1b30b91acbd8a37L,0x147fae6f240adc8fL,0x5558702cb39bf39bL, + 0x171e58803e1eb997L,0x095bf301ed7c79b4L,0x29f1dbffeef752f4L } }, + /* 29 << 315 */ + { { 0xcbb2506e7535c370L,0x40ee37ec7ab20106L,0x74f502d4caca3675L, + 0x167e778db57c0364L,0x7726715b13fa3dccL,0x76097791f42e0c3aL }, + { 0xe1d990c3379dd41aL,0x432454d785c8f5e2L,0x1f90c59562ac45e4L, + 0x63e156998ffe0c09L,0xc3bb8c29d42bf0a6L,0x027d5a86ecca4cfcL } }, + /* 30 << 315 */ + { { 0xaf8ca08b20492da0L,0x37b1fa1547508667L,0xc9fc925b96077958L, + 0xb78c83c19ecac8b4L,0xd9d953a17c05a67fL,0x970ee229b9ebcaaaL }, + { 0x689cad7f55dc989eL,0xf02f05bc66c941fcL,0x8d00516281e23d8bL, + 0xfe603ffc8caebcc3L,0x592860bff303153bL,0x9ec1d5ab3344e524L } }, + /* 31 << 315 */ + { { 0x7e374b7b0f922941L,0x44b3f00174466c92L,0xcb3eb28c3c2fe678L, + 0x91079467bb9bf05bL,0x0d268749de2dcbe3L,0xb6383ba4c5204680L }, + { 0xd50269f4951d3c71L,0x9209a2d53ffbf2e0L,0x2f6496258110f811L, + 0x08fc9fbb0b31e275L,0x697960ea1faec287L,0xae95e4a8c5420ad4L } }, + /* 32 << 315 */ + { { 0xc20fb9111a42e5e7L,0x075a678b81d12863L,0x12bcbc6a5cc0aa89L, + 0x5279c6ab4fb9f01eL,0xbc8e178911ae1b89L,0xae74a706c290003cL }, + { 0x9949d6ec79df3f45L,0xba18e26296c8d37fL,0x68de6ee2dd2275bfL, + 0xa9e4fff8c419f1d5L,0xbc759ca4a52b5a40L,0xff18cbd863b0996dL } }, + /* 33 << 315 */ + { { 0x1304bd65ff0e8fbfL,0xa249adb53343deecL,0x20635fa9826e1293L, + 0x6283f098b7bddaadL,0x0d0a7820bc96fed6L,0xcd7605d47de0b9bdL }, + { 0x4f0a9751586f9eb6L,0x2f6dde5556b2521bL,0xb7efccbd76264c6fL, + 0x7df9cd35b2613621L,0xc334c8f924a2ff4fL,0x914f472a0b13b604L } }, + /* 34 << 315 */ + { { 0x89092cbc5f6bb241L,0x8b4dadacca123b83L,0x9ba420eecd2dbaa2L, + 0xf269d1982dd6ef2fL,0x29f68d03809b338dL,0x18cf8675958ae927L }, + { 0xc179d4b2bffac33aL,0x5356ffc1522695e1L,0x453474986d039c90L, + 0xcba0e0fc5a675530L,0xf369b7ab98a0c70cL,0x51f82173d508c254L } }, + /* 35 << 315 */ + { { 0x5f98e5aae8490374L,0xdd84a7506ca52a68L,0xb6904ff8a9244f56L, + 0x4c908c0362a5502fL,0x70ff1e01a8df73b3L,0x573a37f20df382caL }, + { 0x5df73cf8c7dd1209L,0x965ad402abfbcd79L,0x61a633a59e67af24L, + 0x0953c83cc64203f7L,0xe14f58f9a1fd8dcdL,0xb5ea722887a5fadeL } }, + /* 36 << 315 */ + { { 0x55466aa1d896c2f9L,0xd03ade059831fb31L,0xc46711547d968dfbL, + 0x8ade0c97bce2fdb9L,0xb408c7457f6d843eL,0xb1bbe028a709cf63L }, + { 0x1dbd25383ba4fe36L,0x1438d322dc1f2720L,0x1c3c46b9c37694deL, + 0xe57133dc3997e650L,0x754c171e422b95bcL,0x29c47f0da209c7bbL } }, + /* 37 << 315 */ + { { 0xe520480823822d0dL,0x745fe7aae3eab177L,0x6f0f4a7e808500edL, + 0x9383c632200c2bf0L,0x6f3130d7be22d432L,0xed7713d465511061L }, + { 0xff84bc04049067acL,0x33c2be61d56210e1L,0x57d63f885ac04f01L, + 0xc2fbb773284fb49dL,0x46422426e1f349adL,0x3cb627c465863455L } }, + /* 38 << 315 */ + { { 0xea06cbe9a1edcfccL,0xb0438e198aff46ecL,0xa93fb88ba450240dL, + 0xfc4a370021b6b45dL,0x2503aa5d82a21241L,0x7533f1d7f540d3b7L }, + { 0xd7a58a679277538aL,0x466d981a539c347dL,0x46f1682bf26488c2L, + 0xee2b4976318282e4L,0x8fe5e5b85a94409dL,0x40ca43a7b1a4fc28L } }, + /* 39 << 315 */ + { { 0x0ed4414c901e48d7L,0xdcabb46418340890L,0xd50bf12f20998781L, + 0x498a90232a596ffdL,0xcc877212b43f456cL,0x98d9d531f796c4fcL }, + { 0x061e3b31977c11b9L,0xe56bc6f00a00c822L,0x756e62c96887ea43L, + 0x29129d53859ec944L,0x42342589146c1fbeL,0x2f2cd4bdd1884196L } }, + /* 40 << 315 */ + { { 0x3d3815d645d94a24L,0x4cd9fe1139f3e6e2L,0x8c7b8dae8e7eb572L, + 0x7e69faf40f7deecdL,0x0e54b3c0387e97ddL,0xd12e473175a1b6b1L }, + { 0xb7163632c664f92aL,0x86ab4ea88d94e55bL,0x37212aef1133dcbdL, + 0x0c6c7fc6dfc0d47aL,0xacbcb077aa9e1ccaL,0x43cf50a726ef7fb6L } }, + /* 41 << 315 */ + { { 0xc0eb003c54d7bac5L,0x89780aea2b770baeL,0x13a194e8076bb29cL, + 0xb863585046f8aa90L,0x79ebc6066df515f0L,0x25ea422dd1ead000L }, + { 0x16b03b8106c89b71L,0xa964da878ad9fff7L,0x2c96dc6b2e7b9072L, + 0xf71788978c93f6bfL,0x4c7ecef912688648L,0xed7b4a577c663be0L } }, + /* 42 << 315 */ + { { 0x5b7cdd0ad74a20d2L,0x273184f48bcdd2f5L,0x4d8d3b4ce3ac03f7L, + 0x0e2ff518a02cc60cL,0x9c006ad8b6fa606fL,0x401606caccf627a0L }, + { 0xe7429a6f7b967844L,0xe4e5d1c1bc8ac8beL,0xc050f89ff4f46638L, + 0xd23a3eb452f918c9L,0x4528e4e202944b49L,0xeb345a689268719dL } }, + /* 43 << 315 */ + { { 0xf4fbd190ccec4c27L,0x7e042c8722674e8fL,0xbc79835ae8b33439L, + 0xc7923b8fad2124d1L,0x0ece42272c72542aL,0x02d638e2b9264875L }, + { 0xbdf9fba1904e7683L,0xcbbc0e0aac934377L,0xea154d99459ec213L, + 0x87db3f66c3023e2eL,0x7f9262d518de83a8L,0x432fef4f3524400aL } }, + /* 44 << 315 */ + { { 0x3b5566d7938a395bL,0x920dc1111f256c82L,0xcee7f231a059c8f8L, + 0xdc3da434d48b3179L,0xb1e819e913f78de6L,0x94a21bb01f9819deL }, + { 0x8ef14a96f302a94dL,0x9f897e1a079fff9eL,0xff9a4e0e54122af0L, + 0xac6a6cbef0b7f1c7L,0xfd15d9756401df3dL,0x500531a323a0b7b6L } }, + /* 45 << 315 */ + { { 0x12e22a012da0c724L,0xa0a837f3b80cba90L,0x89df9a3e2a9b5434L, + 0xf3299f64925840acL,0x0cc78a3a125b3dc1L,0xa4ea6203c723d647L }, + { 0x5cee8068d369522cL,0x3e479803432d5e87L,0x86e809363ad8126bL, + 0x93e871c9cf89d85dL,0x892e4710286c9010L,0xa075a6d3ec3a1792L } }, + /* 46 << 315 */ + { { 0x095768bc7dfddf6eL,0xc4e331b4e63c4e60L,0x1179808104f28a2aL, + 0x415e33e1bee48983L,0x7fe8050144af7eb7L,0xdf6c423b2f28fbfdL }, + { 0xd10886db007a2b56L,0xea578b286613f26dL,0xd18a9d1c2b90a815L, + 0xd4c6e8b2675c2c8dL,0xff973df5788bf2d6L,0x4fbeb6210d7e611bL } }, + /* 47 << 315 */ + { { 0xcfab317671674fa8L,0x78038a1afef7089eL,0x3109736aa27b5b55L, + 0x1b31325fc0193518L,0x3afd21a8be19b5f0L,0x548196a2d8028eabL }, + { 0x15b0d6d2a94e6be0L,0x1552ffb67afd5dd6L,0x49b1150d89bed9eeL, + 0x2c59b0bfb0d1444cL,0xab265d7eb695a900L,0xa24d0788a1dd1ef4L } }, + /* 48 << 315 */ + { { 0x4e913e1131e325ccL,0xe92f7c8f2a65fe01L,0x8e61a80d5857aae9L, + 0x2c36923d53104397L,0x5b0911d6b36d5379L,0x76eb9b56b1207ae0L }, + { 0xb5cd11646723c4aaL,0xa6bec13b98891a11L,0x09af8be29d806056L, + 0x7da8d29ecc1fc0e6L,0x231cc00e2aa8791dL,0x2ded362c042171c2L } }, + /* 49 << 315 */ + { { 0x26eb2ac96afa51d2L,0x83485eff13c04ce8L,0xdedb48718072d8dcL, + 0x4da1771d8ac3d411L,0x2d8f99ef849c6c0bL,0xea65f6bc2b5882e4L }, + { 0x60a90f58fd671216L,0xb9f3e2058af33bedL,0x29c41ec92bf02916L, + 0xcdf15b1de5ddeae8L,0x67f9ad163109e99dL,0xb9b5585f517d25e1L } }, + /* 50 << 315 */ + { { 0xae016b4811b3e20bL,0x5ccf3cf1e5164179L,0x1281ff8efe9fd47cL, + 0xb85438038e61bdf2L,0x694e42feba5856a0L,0x53f7e09759b32aa1L }, + { 0x5b9848e9c341a531L,0x9a5fb85025952b73L,0x9d5fe0dea6f82c5eL, + 0x9216a8ca44090933L,0x3e986d4bc3272875L,0xc20534f8f3512e42L } }, + /* 51 << 315 */ + { { 0x718124a1033495a6L,0xc4f28a746834851fL,0x91186d80e1baaa77L, + 0xca4e13222a761e95L,0x7b6b8322582ddee2L,0x75d396c6c3c70c6bL }, + { 0x075dcd6b54c75102L,0x3669b97c0b92622cL,0x621154e6f0cd45adL, + 0x7ff0029ff381a6d3L,0x3d37e750a726f84bL,0xc4f79202874de604L } }, + /* 52 << 315 */ + { { 0x215018fdec26297dL,0xaa06fd0bbf35d225L,0xe5fb438cab40bc17L, + 0x6a0ab335acb7f4c5L,0xbe1f4de4187a8e6cL,0x651deba961f7e842L }, + { 0x2b30b0046f629aedL,0x63bdbf8e2218f107L,0x21a21aa5f9ca8bbdL, + 0xa88cd9138304f7e1L,0x23594fc6c5e6f9d4L,0x4d4db41a6682fc06L } }, + /* 53 << 315 */ + { { 0xca2317b0428dcb40L,0x9a7bd387288b5eeeL,0xd62da6d0a060584bL, + 0x601a3d6ce8f10251L,0x65718f0584885319L,0x5a87b1c2a1bc252dL }, + { 0x27ae8015a37b05d5L,0xa624af9c98394605L,0x988220050ba4565dL, + 0xb93395c9da2613deL,0xcef9a880edcaa74eL,0x7b2ef0fe0976687eL } }, + /* 54 << 315 */ + { { 0x094f20588e5c6b80L,0x6e5a5f52846eabebL,0x9eaef2d7370a9345L, + 0x12d6f20687c19719L,0x0d2494ab9c44076cL,0x15ccc737de9309a6L }, + { 0x8eeb8faf94ca6587L,0x7dc9a4fe3fe363f5L,0xf02f6e03b3b08270L, + 0x31adbe77daf15507L,0xc0fb2814343bb4efL,0x724007519bdc1d91L } }, + /* 55 << 315 */ + { { 0xd301525c1677fcb7L,0x11b7141bfb6b0dc1L,0x01f4950eb2163b70L, + 0x34c758c6ed3c0025L,0xd1b1c7573a5196cbL,0x7926f0a42fa19c66L }, + { 0x107e5d32b1c47233L,0x0fe50b00cacbdaa0L,0xf45dd7e8e213397aL, + 0xca6b2de9eaa1db7dL,0xbf234b55dd09c2eeL,0x10db87d1a1db37f3L } }, + /* 56 << 315 */ + { { 0xaff57c87de0572ecL,0xc0745250826246c4L,0x523910fc700ef250L, + 0x8c23aa5793faa067L,0x87f7c7198e7dcf75L,0x45ef4adb46695227L }, + { 0x0ffe09d196ceb1e0L,0xfb72a05790f3383aL,0x62d26e5e07c220d9L, + 0x03e19605766b1e64L,0xa774669458c17fb7L,0x9a851d828e7acfa9L } }, + /* 57 << 315 */ + { { 0x150e936f4baea8efL,0xeb5328d68239dfe4L,0xe064fd95b5f987adL, + 0x13d3803d52e7313dL,0x0e9738f5b215317dL,0xb6dd60a7974be106L }, + { 0x00fa92bd6bac81d0L,0xdee050f9e7cb2338L,0xd7943d4f9075745eL, + 0x07cc4170819cfd9aL,0x21b7e0b04aef1468L,0xd7520b77aef07b1dL } }, + /* 58 << 315 */ + { { 0x126c012681097c49L,0x95339f9475c02669L,0xec3fc15b100115ecL, + 0xea5c8e9c49fb787eL,0x63168108bd3fbc19L,0xdbf2430541573590L }, + { 0xcaa3a69686dbc847L,0x2c464fcb70d76739L,0xdd9e0bcd69e2fd74L, + 0x4ae92cc01652728dL,0xafe3e24812b060cdL,0xf3776c6ff951a38dL } }, + /* 59 << 315 */ + { { 0xe4ab1c417af22e76L,0x35a8addf038840dbL,0x95ba3e3dafd0d7b2L, + 0x2a7bf827f84417a3L,0x0bc177c729bf5a83L,0x29ef7f8bd09905a3L }, + { 0x1df34fb1385e6c69L,0x079bc0fcf99e0d19L,0xcd2dbbc4f30eb5c7L, + 0x2d364701afa7447bL,0x3c7bfa087a791ef9L,0xe21508c8e71166d0L } }, + /* 60 << 315 */ + { { 0x0b204c9ac746ec60L,0xdd5efe2718b93b24L,0x484474e0ce15332eL, + 0x690be23d05a308b7L,0xeea3abfcb0f7081aL,0xaff69f36cd8e8720L }, + { 0x5dadd080d951329cL,0x060c379c8cae67c2L,0x8e284705b20851baL, + 0xacc8d8a0e5df0e85L,0x8c024e789463544dL,0x15a9a3f08003076cL } }, + /* 61 << 315 */ + { { 0x095e284899e0ecb5L,0x61e9d5893415c1bfL,0xb1207d3017f5c585L, + 0x75f73f1d04e97243L,0x868551aa77bd50d8L,0xd530e0cc197f7d84L }, + { 0xdd6ab731ea9fb71bL,0x26e5b52e2cf9510cL,0x4fba03ff11a88911L, + 0x6608b634e921e323L,0x4baf22f836d46a1fL,0xb8bced501bc7ace0L } }, + /* 62 << 315 */ + { { 0xaee397fa327d9bbaL,0x9a45e7a2d832e3dbL,0xccb43a730582ae33L, + 0x457b3271d4093b12L,0x409caea6370bd663L,0xa5019f25657f693aL }, + { 0x5851c78a16478fe7L,0x5e09ace7ddf17dd5L,0x89ca68da0763656cL, + 0xb92d3321e2bad2d0L,0xdd5642098422f6bcL,0x4a6ea69946c04923L } }, + /* 63 << 315 */ + { { 0x7ba1f48579120405L,0x6c136597898be69cL,0x1e75e1586dcacc38L, + 0x3d3cb58b65ee4cbeL,0xbccee7a308db0caeL,0xee8bff34e77edfb7L }, + { 0x123bc3f036f60cf7L,0x3b1dc9e779bb4c78L,0x036a8049fe5f0d85L, + 0xc4de23d318f66f39L,0x593cf51e3c436c16L,0xd4d40e906769584eL } }, + /* 64 << 315 */ + { { 0xf6827150844eefc5L,0x002e82c44515ef68L,0xa46c8f55c51916c4L, + 0x98c3524b61ee081fL,0x5ab7f2c2ad64872aL,0x0b503ff07e555faaL }, + { 0x802e0d23b4c58d29L,0x122890402fd917feL,0xb56d19087af20d26L, + 0x8d619e216be50784L,0x10fdbb721372b851L,0xf2c1673e4935576eL } }, + /* 0 << 322 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 322 */ + { { 0xd97a9b1451a135f6L,0x6d16aaf597b4df14L,0xc57160c254818818L, + 0x4dbdeab61d59be44L,0xb93a9dad81f2b247L,0xe2868cf5ecbcab33L }, + { 0x5e1ce82883a86711L,0x29a9ca2f29c55428L,0xe716273a2d82b0dfL, + 0xb017f5f6ac8ff52fL,0x7563e79970ea7ccdL,0x5fedf0a63f0e674bL } }, + /* 2 << 322 */ + { { 0xa7f8501488d7b3fbL,0x3b5ec513ec78386eL,0xc6586b8a2ad5053dL, + 0x88c09a43fbcebe43L,0xde7f2a4a20054f16L,0x63daba80bbbb147fL }, + { 0x087e48f37d352b55L,0x997e32a08317ab79L,0x8ae802ff7f27cac7L, + 0xb01a131c37b1f6e1L,0x3f0d4c2e9a6d1deaL,0xe06114fce7ceef80L } }, + /* 3 << 322 */ + { { 0x311df84c359590bfL,0xf907d69ddf6ca4b4L,0x876fd36782f22c64L, + 0x64c4d14d9713e68cL,0xd431858d6b07f539L,0x39dfea3384990283L }, + { 0x6afb8cf080cf6498L,0x327056bcde060e9eL,0x5103ce4a49a71086L, + 0xfc94be75cdf853abL,0x2bfb105f8ca579cdL,0x02d19c3a50454b41L } }, + /* 4 << 322 */ + { { 0xaa03b474cde121c7L,0x74a648cb55e52c76L,0xb286ef86f37b57bcL, + 0x95b797eb2a6371d2L,0xa489ef894077ccbdL,0xf46ade048e99ca6dL }, + { 0x5cf9e23723242d03L,0x33c7d32acb708390L,0x329523b6ba7ba477L, + 0xd406ab8757de30bfL,0xaa10e4a21536ca01L,0xdcec94f4dfa7aac5L } }, + /* 5 << 322 */ + { { 0xb5839fa424700097L,0x82fe2251759eb8beL,0xec5f34bd5f104a39L, + 0x7f3da509ed1cf49eL,0x62fe425244621c76L,0x2118b68dc7bba926L }, + { 0xb0ac18009ea4b7e7L,0x33b21ca1fcc83f56L,0x1856161208458096L, + 0xba0e6aa95650f3feL,0x918d427231006f05L,0x955f3951b1066473L } }, + /* 6 << 322 */ + { { 0x0cb41ada3c59ee1fL,0x38b2465861d1633dL,0xde863b47d03e9452L, + 0x2bfab5b41548d45bL,0x580af6272ccb7528L,0x6744c7cb13c04327L }, + { 0x5eca3ab339cc5075L,0x51dbfc7b6d243f62L,0xd64d84b7981ee3ceL, + 0xf639a03db4f2bc63L,0x8a411c36a317a1b6L,0x51edc4c0ed34eb3aL } }, + /* 7 << 322 */ + { { 0x01511b8a9d6fce5eL,0xb5c7b33f89a2875cL,0xa88e720e2fd79b67L, + 0x5337034404229e94L,0x40bb7e7ec94af25cL,0xc11501b99183a7b3L }, + { 0x29a4d81fcec3cc7bL,0x143976fdd75b8febL,0xac8dad2cfa261ad0L, + 0xb14793006a2db8a8L,0xd4981293929c4a12L,0x5703506fb6eef856L } }, + /* 8 << 322 */ + { { 0x762a5eec1f5a9609L,0xfe4f5f6a765b337fL,0x0fd534aeaa4f964aL, + 0xcf46648ed6526f01L,0xbc62a54a18d71d72L,0x48d94f2a4f8488eaL }, + { 0x62c40de7a0c72a86L,0xd73ac51a725dd2efL,0x3a51d7466ab19096L, + 0xf07bea4b2dd1ad3dL,0x2a0ec4672ef88078L,0x92598cb3664e435dL } }, + /* 9 << 322 */ + { { 0xd49f753012fbc44aL,0x769a4fc941c51d91L,0xeb1ed485981fd6a9L, + 0x90a4b3cad7daf430L,0x4bbffd5c75d07405L,0xd998a096da671888L }, + { 0x0514ad4b6e10976cL,0x5d40328aab11d9ecL,0x86de976bfa180702L, + 0x259ca429f6f8a4b7L,0xe08970f05772eb4fL,0xca428fa1b5feb7a7L } }, + /* 10 << 322 */ + { { 0x9f3d76ae35af4a88L,0x0b92f48a242af3e6L,0xd4f8a37b7165d261L, + 0x30e1fa8b2b917832L,0xd26f821f8fdfc06aL,0x75359bcf3669d1a2L }, + { 0x0ba3bcebb638331aL,0x8d02c0996c73b62bL,0x2a8c078d8c4f63a5L, + 0x55458ccaa312c282L,0x901ea0ea5eaaad9dL,0x03665da20e39eba1L } }, + /* 11 << 322 */ + { { 0x79a30b82da9affceL,0xafb188567204a29dL,0x2e64e6105a8ed24aL, + 0x6bf3695a9e44aa24L,0xc22320690c77fa6cL,0x20b3c69531524429L }, + { 0x91e60caad6e0f847L,0xf0fa30c4542d6b57L,0x56a3a66bff98ceffL, + 0xec44f0b72c9507a2L,0x4ef13008c37e17e4L,0xc819ae81cda21355L } }, + /* 12 << 322 */ + { { 0x17c563be1cac0b58L,0x889cfcecb8491347L,0x591d49ac4cd1bfc0L, + 0xd4465510d4e53d3bL,0xca95ccf6ad079a6eL,0xce391389b5ea6eb4L }, + { 0x600ccc9ca48b6447L,0x20d0c7dbc20d56a8L,0x5f27edc569c6c6e7L, + 0xb3fc0f4a586abcdcL,0xdbfdf3f985dbc5b6L,0xfba1cf254ea80fe0L } }, + /* 13 << 322 */ + { { 0x38d6267e427a9075L,0xd1df12006d63ea4cL,0x9887a99881407b57L, + 0x41accae4688e9f0eL,0x33c63c9e10886dc3L,0xf8332ac57574a033L }, + { 0x7d77d41f4c636d00L,0xf6f4ca28add70d4bL,0xbe496330c0ee111dL, + 0xa4de7670b74bc69dL,0x683a93d369e5eabdL,0x4c5461c710963bd5L } }, + /* 14 << 322 */ + { { 0x9bbc99b59310424cL,0x6f4bce534568e290L,0x21373f5bc1572fd6L, + 0xe5ecd5b6a28b4394L,0xd56968f646ef7bacL,0xcbce8614726cc043L }, + { 0xb2fa6101d0a49bd8L,0x65eaa7725a7b41c3L,0x10d7515296e5ae18L, + 0xec8f4639af389838L,0xac660d81bccaff25L,0x3c546ba931734025L } }, + /* 15 << 322 */ + { { 0x81b13d3ee098c584L,0xf8eb4e41fa3460caL,0x1bb889d1f0b905e3L, + 0xd158ebe939a3faafL,0x7ad0f829cf09735eL,0xc89611963aa8b3beL }, + { 0x522327781be516cbL,0x9118d851ee88d911L,0x35ad130f0bf2a62cL, + 0xf35bcf1b39c05087L,0x73b992c3bce42949L,0x93ce50b95b42744dL } }, + /* 16 << 322 */ + { { 0xee6e7006b515fff5L,0xaedf6e3913258ed5L,0x373adf7dfc45111bL, + 0x0c7535b1875c23c8L,0x2a7e04f897039d49L,0xd76787ae9afd1a06L }, + { 0x049dd38591b6dc89L,0x8f0c8ad0932dab78L,0xdce057b9925498c2L, + 0x7b9c9bd2da25daa3L,0x6d0b70a3d4decb7dL,0x099a218303df76efL } }, + /* 17 << 322 */ + { { 0xbfaf4b848c5520a2L,0x36fa343fc6741e50L,0xadcc36dcbd5211c4L, + 0x2cae5a8514bf0578L,0x8fee4d403fe4171eL,0x2acd2756624d0daeL }, + { 0xaf99a323623aa9cbL,0x120cd2038c8191e2L,0x2073e8884068d993L, + 0x144851ac579bbf88L,0x54d458a4ee29fa34L,0xb7704255e5e5d676L } }, + /* 18 << 322 */ + { { 0x02f6e396617dc4bdL,0xbc48c42961497feeL,0xb27487fe0b4d22d7L, + 0x33d6b1161d0b0aabL,0x5e21cebad31278e5L,0xf7119a50dacd8f27L }, + { 0xe47eff2cc8ab54acL,0x7c7ccd3bbbe16c9cL,0xc056d817c584bafcL, + 0x868ead2b97790d9cL,0x8fea6eea1a58126aL,0x67d323640fab2640L } }, + /* 19 << 322 */ + { { 0xee1a958ffa14b58eL,0x900644f9760b54e3L,0x97fa6fa451579d09L, + 0xa7351c3b26e7f95aL,0xc3546595aadfd139L,0x07b7ef48f14f1e6dL }, + { 0xc8d100ec4d139608L,0xf98609b2d8741228L,0xf0890d9d33030d3eL, + 0x893b874fe28ed106L,0x5439b7aff7bb558aL,0xe68a3adba71a2261L } }, + /* 20 << 322 */ + { { 0xff54e8bc8acd597bL,0xdae781e94682b8c6L,0xb2265bc4ed1fae2dL, + 0xa5e23c29ea983db1L,0x4af5f55909851454L,0xffe9538836eb4506L }, + { 0x4c72b2d1c2247b8fL,0xb179573331a67505L,0xb1aa8ad4e19c9c25L, + 0xb9cfea953e8b8004L,0x07782d788ac747fdL,0xe23e547fce9d9e41L } }, + /* 21 << 322 */ + { { 0xbc6b0088fd9e8e72L,0x7e51aa5dc6453462L,0xe8615fb9c8b1725bL, + 0x031f0d2a5a371c9bL,0xb9db0a647441d8aeL,0x0dd0446e9d5783c5L }, + { 0xb3b7be2381720779L,0x49a8ecbb6cc5a610L,0x165c626152cd016cL, + 0x5fcd657da3f6ae6aL,0x30497fbc9f6988dbL,0xd734927936a73fe7L } }, + /* 22 << 322 */ + { { 0xb30ddd0e388562b4L,0xc485506b1f61067fL,0xf0da517684947c84L, + 0x04830cedeb067f33L,0x05084c8262404b76L,0xe7e7efad7996707cL }, + { 0xc2a6a57fc78b9a7eL,0x4e55fd8c7bfbf308L,0x204e7c44d1386117L, + 0x979ecd5a4e56595eL,0x3bfc790853707b85L,0x2c3a41c59fcc5b7aL } }, + /* 23 << 322 */ + { { 0xcdbfd951ed6e2671L,0xb72c42ee135f6b96L,0x38c8d1ca40bbb789L, + 0xf6fa984cda03f270L,0x76dc5a19ed88deb9L,0xa8c88f2a9985bcd7L }, + { 0x2b0d3b66c6628a44L,0xdf679b6a2b311954L,0x30a363c25f851b07L, + 0x78a5d242aecdb9cdL,0x42d7ca82a968b4e6L,0xb188e99af2efb94fL } }, + /* 24 << 322 */ + { { 0x779905b6d8948f95L,0x3c7085b591cd0206L,0xce9af0aa679096dbL, + 0xfdf04f10f558913cL,0x05300cb06f24a2e2L,0xf9d9a2f25d581b35L }, + { 0x855c8de96a713751L,0xc9ac24bc0e0c0dfbL,0x67612a4197740d65L, + 0x7588a52744c9360dL,0x928ac910325cc880L,0xa74abdafacdd3188L } }, + /* 25 << 322 */ + { { 0x98d80359e7c5fbc7L,0x6abc82b7047c61d5L,0x8d8f5fbd58f2fd49L, + 0x321f2426ccb0a4dfL,0x379f10e2e96cac24L,0x34c0444130666763L }, + { 0x8dd3972043632c61L,0xb2bbe2eec19f98eeL,0x00d5a467c464dfa3L, + 0xa44ceb19a85b6fecL,0x88bf80ddc9b1fa77L,0x7e5123c8e6dda98fL } }, + /* 26 << 322 */ + { { 0xf73ad540b75a6b88L,0x57bcf1cc08487cc1L,0x00358de735cd0c27L, + 0x86d469a2573df808L,0x4884cd5684716abfL,0x0157687fa7da61d7L }, + { 0x8efd8acda732c2cfL,0xb6c9bf7198677236L,0x3d1f01826d46c473L, + 0xafa65fd82f497476L,0x535ee757e54f17daL,0x432b5878fe7aaef6L } }, + /* 27 << 322 */ + { { 0xf091c4ff3370e118L,0xabf011ee118d4b8eL,0xb489c4b7a13c7279L, + 0xc2dd44e93bfb19feL,0x10b68e92c5d859dcL,0x57935fc39249205eL }, + { 0xb97e63b06c929bf4L,0x98cb08a739a25097L,0xb13f17c15eeedf15L, + 0x1e27a85c240884feL,0xda1515ad9b601298L,0xe01251fd4ce36c3eL } }, + /* 28 << 322 */ + { { 0x3774af36ba6aca8aL,0x562fcfb1340e6a03L,0xde45205ec1187539L, + 0xf3b114418799c22eL,0xfd53f681e8b0842eL,0x45a0039066d36d64L }, + { 0xa2c3391d353eb1e7L,0xf9d9fcc55840eddaL,0x4df1fa4a6ab8ab4aL, + 0x2b0cd34bd841a623L,0x52441d79b10b189aL,0xfd86d3c2fa025da7L } }, + /* 29 << 322 */ + { { 0xe28f3bab5872204bL,0x6f87cbaf0ba35c66L,0x783e85c03d877c60L, + 0x376e5e2df132df52L,0x213d53a9bc2cd6faL,0x2e2a573008a13174L }, + { 0xc0988fa9ba15290fL,0x51d81b9485456f81L,0xfe371f32a0ef5b80L, + 0x9aca060ff129171bL,0x0b02b39e0e402e65L,0x8e6bce1eae9c209cL } }, + /* 30 << 322 */ + { { 0xb0cb0f0c532f78c8L,0x83113e752d133635L,0x3f64aad5123dc64bL, + 0x4d3201c85aee8c59L,0x265905dbe75e8642L,0x9d1d277805f9a759L }, + { 0x84778aead9e2a07eL,0xc747cc3a9c0aed31L,0x10d1b4e87af2dc61L, + 0xf58a6bd8af0bf23cL,0x83836c2352e1ee75L,0x88c4d1c6d899062dL } }, + /* 31 << 322 */ + { { 0x27eb26a3f3842d98L,0x90f712b69da68159L,0xd11177052676f05bL, + 0xdf603446073bf994L,0x28ad2b498bfcbb7cL,0x6916c6e2e5e1266cL }, + { 0x37d516996e98d62bL,0x155d8ef749634968L,0x0676ea286a1b2222L, + 0x1dc3f8d71566cb3bL,0x95fb3f177dc6aecbL,0x092f4c8120807b13L } }, + /* 32 << 322 */ + { { 0x3c6c5618b9d926c2L,0x7e14c3ae4a9099f9L,0xb3259c90ae2fb830L, + 0xf7cc6e43ec31a504L,0x83bb13c6126230bdL,0x5a1f4313ff1dae3aL }, + { 0x0cc6c1a549b0b65bL,0x67fa836a274a84c2L,0xd454c75fe604a58dL, + 0xceadfd912491f872L,0x6c5575da9ce116a5L,0xfaa4903fb24a4481L } }, + /* 33 << 322 */ + { { 0xc9ade1497c4579f8L,0xdad7eff3be316db0L,0x4ff3abc613fce23dL, + 0x09103a75da708e56L,0x4cf139fa8ab52827L,0x0f82219b8f251a68L }, + { 0xd19719c7dea33388L,0xa482548423085413L,0xbb63cb43f8eb4b18L, + 0xeec33735f3b88079L,0xee79d331de3ddb97L,0x56fc93090e5acf8aL } }, + /* 34 << 322 */ + { { 0x951a780bcef9c5bbL,0xc37d442ddb35bf11L,0x8e2a0e7d64a776b0L, + 0xbf461becc652cf34L,0x3970eb603194f918L,0x2768daedb3bda869L }, + { 0x8e81257557b24bf2L,0xae05e2db38dd69cbL,0x0adab288cee2f522L, + 0xc7a0e1f148234f13L,0x285f6ee36728c9e9L,0xb9ae7b9fc4541e19L } }, + /* 35 << 322 */ + { { 0xfd90c5c1f6422b56L,0xd9fc8cce4dfdb947L,0xf3566dc4d088588eL, + 0x25dd9e27f22682e6L,0xb077392119b0a532L,0x54da228c0d05a9f9L }, + { 0x0f7fda40986f60d4L,0xb6dafff6c9b112feL,0x7eb99e1a4abfdfcaL, + 0xed499eb9389611caL,0xf230d6d6f251477bL,0xc09d328c227ecc92L } }, + /* 36 << 322 */ + { { 0x9b21ef6c16cdcfeaL,0x233be0c3694edecfL,0x110243df7c49c931L, + 0x03a59a2ea3113ed1L,0x6470f721023c9a77L,0x7d1640c88e9ff099L }, + { 0xc21488316f2c7b37L,0x9e1c9e1dac6eebc7L,0x6af65a671109ca9cL, + 0x8379fdd9cc6f80d9L,0x33f74ade7e666a4fL,0x07ac728b7be081a5L } }, + /* 37 << 322 */ + { { 0xa3df31a312354705L,0xffc8fdfc1aec1bd7L,0xd9dd39c112cc342cL, + 0x8077a57e37bf43fcL,0x0f037ce49cb8751eL,0x5740f6b5b805b530L }, + { 0xd26422704e2b5b93L,0x114bb1f02dc158efL,0x71881767a9bec3d1L, + 0x1174386d266d95cfL,0xa373d7ea7cdd4461L,0xaf4f7b40d814a33eL } }, + /* 38 << 322 */ + { { 0x0db94a18f79761beL,0x263e2acb5717b98cL,0x78c28d8182567b0eL, + 0xce1b366b893c35b4L,0x1e20b1bc0d6907a7L,0xd6f123474b973588L }, + { 0xfb945471f717e91bL,0xef85653cb027bd4dL,0x048e9e1df07dc0e1L, + 0xc494aa9cc163b83dL,0xfaec72d3021b4fa5L,0x5c63c30fc9869fe6L } }, + /* 39 << 322 */ + { { 0x2dfa058d510d8d86L,0x772fad416a89aa0cL,0xdf55d15cd586f23dL, + 0x7d96b7a989b604f6L,0x352fe049a38d821bL,0xfc56b8df4fbb5795L }, + { 0x264122b4b3d5dd0bL,0x89317f4a980177d9L,0xc060ab4a13e2aeecL, + 0xc2676725e2cafc87L,0x78863cf45eb1df3cL,0x2e1572dc0ab1a715L } }, + /* 40 << 322 */ + { { 0x7a8a898d5a4703aaL,0xc59933ea1cd6f9d6L,0x703265f5d28124cdL, + 0xe1c1bee10178d1feL,0x9ff31cd4241262e9L,0x9174a939a3c9f80fL }, + { 0x0f7a3d2dbc2a62eeL,0x0454051c62f1b3acL,0x83502c9ea2421254L, + 0xb4fa51fcb684199bL,0x257e9e2bc5e36a44L,0x14efeed597d8647fL } }, + /* 41 << 322 */ + { { 0x09bddbc28f2b12baL,0x8af83a779b7f1c14L,0x88f9b4d3bcc934bbL, + 0x8d8312df8d072340L,0x2ee105bc615989dcL,0x6044fa00de3bab08L }, + { 0x98c499d603cc86ffL,0xf0b48aa7c5068033L,0xdaa536d2c96606d8L, + 0xef905aa2bc6a843eL,0xb6f108ee8ac620ecL,0x0dec7dfbb6dd66f9L } }, + /* 42 << 322 */ + { { 0xb9157d4ab0fe18a8L,0x139bbcbc68cc7a70L,0xd546a06d7dea2914L, + 0x8db142d4a01cc59aL,0x127ce2d9aa09fcdfL,0x3950a5a63bfef8deL }, + { 0xf41ef6d42527522aL,0x4b4e6f107e6fb19cL,0x2a2735d1345788c5L, + 0x87963e1ee72a7ae3L,0xb58d8934fc443360L,0x93552692b16b6f2eL } }, + /* 43 << 322 */ + { { 0x70591a849518f0c7L,0x5c282b6fc67c438fL,0xdbf61b6b100facc1L, + 0x3c5d969f2bf2a5beL,0xe1a0c6cbab980c70L,0x70f4981c680619fdL }, + { 0xc6905d7cc65be256L,0xde3340fbb5c27acdL,0x17be9d182c1b3fbcL, + 0xd584e4f96fb00b1dL,0xac5dc14eb819646fL,0xf5c3279a3242935bL } }, + /* 44 << 322 */ + { { 0xfdb13b31be970ebaL,0x119b1c08b0bfadc2L,0xed62f35e21875542L, + 0x73c8f9b0349a6d12L,0x8c35d8f8bd1622c0L,0x501b9d288b6521a0L }, + { 0x377f8fa1c918b2d5L,0xe2a9580cd0239ef9L,0xee24f4f0371d7bebL, + 0x4cc697a669231b47L,0xa55193c8dc4c5a07L,0xd4e51e1db0ab8507L } }, + /* 45 << 322 */ + { { 0xcb811c27265f267fL,0xb85593aa9e2688f4L,0x57a1969dd76bf364L, + 0xc29946c9014483a2L,0x5bdd72490915bddeL,0xba6d13ff22746ae4L }, + { 0x524121e0d25f6b7bL,0x9011309e0d68a3f9L,0xf25e89ccdb91c66cL, + 0xae79cad781df593aL,0xef8c6bec4f103231L,0x832659c3e038f02eL } }, + /* 46 << 322 */ + { { 0xd58eeece37761959L,0xba6d8ab5b328f084L,0x3911e6ae324a6706L, + 0x299921c8ad139296L,0xb81a3fe4f6b8d9e1L,0x2680c46f5ef06a6cL }, + { 0xab9cdf368611d63cL,0x6c9fa5b3cc0a5da8L,0x712356a3da4d4412L, + 0xc1707a10cd3f550dL,0x5c25b2f3ce468303L,0xe4be20bffa546b6aL } }, + /* 47 << 322 */ + { { 0x797a2919515ee1dfL,0x65dd5991119dc9d3L,0x82e8201b41e4c5ffL, + 0xd27b35130d3dd45aL,0x9ba590c5b13b2dd7L,0x0f15b35282992935L }, + { 0xef39971e227e4e46L,0xb74c524b2786fd6dL,0xe09c28ec71b1579eL, + 0x0d1418e285f6a935L,0x173265448719fbe7L,0xfe3b1d831200b35dL } }, + /* 48 << 322 */ + { { 0x6e96a8195cecb21fL,0x3a58d8b2d8beecaeL,0x93c3cbb0c0c715a8L, + 0xfb06f977541759b7L,0xf25ba095771c3d2cL,0x7560446ea3bfd322L }, + { 0x7cd99f35a015cb4fL,0xa0e541960786f235L,0x0f868f768b8e291aL, + 0xc8260b0b2f95050bL,0xaf38376ef4c0a462L,0x2b3c0f3b98a3395dL } }, + /* 49 << 322 */ + { { 0x99d4529efed6a724L,0xc6f1b084071d8d31L,0x6c48062ba097da1fL, + 0x1dd10493301c1d74L,0x5288f194f554cbccL,0x77b1b81f39dd42c7L }, + { 0xeb1f2d53a007a6d8L,0x43bed54e05648d75L,0x1a85326f29801a1eL, + 0xcb9a91a4f564d78aL,0x4f38fc7893f071deL,0x920117d8aeeeb5adL } }, + /* 50 << 322 */ + { { 0x709b5904b35cba78L,0xef0c321021b11d3dL,0x38f07eec46844b18L, + 0x2e79f99934870a55L,0x9e9df80400d7b924L,0x857a95625cafba4bL }, + { 0xef8ab68f4adfea6fL,0x4a83bfc16ea764e1L,0x21f4c75475e8d874L, + 0xa3597f526ecdf5d1L,0x9d3a4766eff2e1e6L,0x9872db39e5e6ae81L } }, + /* 51 << 322 */ + { { 0x42d9f39e99bb9a10L,0xe617263ce35e4852L,0xb3f8ace1a06b71d0L, + 0x861520de6419d9d1L,0xc2c521cf37b1fe38L,0xd537001b9edf9936L }, + { 0x92614b9f39af94e7L,0xd2003f2e25286664L,0x249d04aeb836d4b1L, + 0x3c6c192ab26df88cL,0x6e0b25442c72ec0eL,0x69d7f6d7497f03dcL } }, + /* 52 << 322 */ + { { 0xbb5a95f6293cc00fL,0xb202a82a65fb729eL,0x819c26aa12e35774L, + 0x70cd5237c2b3f0b2L,0xa752224a89b2c5ccL,0x71c09cbd0ec89df5L }, + { 0xb849e352bab45d24L,0x290f0307d313f461L,0xf083031cee885e9dL, + 0xdf42a973a60bf2faL,0xe39f2118d4842999L,0x8b54cf1d0508febeL } }, + /* 53 << 322 */ + { { 0x8942b4df0d846a3cL,0x18db708662b6605cL,0x6549e019fafa6508L, + 0x85d97fce43ef9443L,0xe9f13da373485de4L,0x5743297bb0f46e8dL }, + { 0xc52781bb70908255L,0xcd88a48a6bc6e666L,0xf857caa5eb4f54d1L, + 0x32dc925320974dfaL,0x6dc79fad965146e6L,0x24e3a8d2edc1f747L } }, + /* 54 << 322 */ + { { 0x1993fa650e81671fL,0xc6acd9f3dd1a1e4fL,0x227edd1a7bf36f1cL, + 0x4ad2478370867ca3L,0xed0254f758b9a7c2L,0x63fe279a7013a5a4L }, + { 0xa65787ee232e6a88L,0x5faceda487161d5cL,0x36e351b603d64c37L, + 0xaa265f1de9e30871L,0xbf3432f521e6f66bL,0x69d68c068621289dL } }, + /* 55 << 322 */ + { { 0xd2bd143ea0807eeaL,0x474ad99582568efeL,0x0fcd6bba7d482c5fL, + 0xf83e6f15e2628f4eL,0x314508252210e41cL,0x8f0a9402f47de776L }, + { 0x7f20bc562ee4d1e0L,0xed4157de791aa7a7L,0xbe443399be2dee9aL, + 0xb461643371625f13L,0x1be21ba8771f55c6L,0x04b3035a300fc187L } }, + /* 56 << 322 */ + { { 0x0952b888b9d0bdf0L,0x3973763c8ce32fb7L,0x221f0ba56dd860c7L, + 0xbb7a27feb16ac501L,0xf113b194bc8fe58fL,0x18f3297a65839ffbL }, + { 0xa2d4eb7c8dc30003L,0x3fb4b4878e334479L,0xa4f32c651a8310e3L, + 0x944cd644f78f46acL,0x14e40c4af96fb91fL,0xc31402bd4ddf6e72L } }, + /* 57 << 322 */ + { { 0x9eb2c9e51ff0ab88L,0x0a29fc0695cc3436L,0x3f4b4ebdbd298127L, + 0xeb8ad8b52ef56848L,0x6159700f5b211ff6L,0x8fb98f2fc3a67bc0L }, + { 0x5c5998ffbd195b66L,0xea99d6767e44a64bL,0x314316e4bafd1471L, + 0xb5f48757cc8c0e77L,0x922a91d15b259ac8L,0x2458279cf9fc4e4eL } }, + /* 58 << 322 */ + { { 0x945c5a3c6aac3e97L,0x5cbdfad9a266ad50L,0xa3e38114fe59f5ceL, + 0x1ca1cfdace3ae206L,0xbe1f15e12a84cfdcL,0x682514726a12ec3fL }, + { 0x48409f871f57341aL,0x632c369e8461bf7fL,0x1c96fc87d8865ed4L, + 0x1727934ae1ffc51aL,0xa60f0ebb6d71f51dL,0xb6c354052e411888L } }, + /* 59 << 322 */ + { { 0xc7b3d3bb72a77726L,0x04b9bdfbbdb03d78L,0xdbdbaa7e2fe88db4L, + 0xc5848e58564710b6L,0x7bbd84863ec55713L,0x1b5aea5670183191L }, + { 0x95d91bb25340d9b7L,0x9a1462e4187a3252L,0x5cee9b8cec352fedL, + 0x7db8350137049284L,0xa1d2822cd3b714f3L,0xe4cf6d53c2e51da6L } }, + /* 60 << 322 */ + { { 0xdb2a2ac9a63f6f62L,0x4c0d2da695f20639L,0xa485a6adb475e177L, + 0xf6dad8b5aa93055fL,0xafcc1e954974bc52L,0x6686940224fcf32fL }, + { 0x10c138bfc103b013L,0xe74ea82bc6faba1bL,0xddb399c581824de5L, + 0xae797b70cdaad079L,0xc648e7ad6ea955e2L,0xd07c5c919be79db6L } }, + /* 61 << 322 */ + { { 0xf4b7a33b39d93befL,0x4be176f9659da9f0L,0xbf57d975f36642cdL, + 0xe10b452d16d5528cL,0x7c062421a6bdd74bL,0xc093e346e7aa1d9eL }, + { 0xb7cc38cc2f5c19ddL,0x9fc7f69b230c8790L,0x9b667acd5e3c5282L, + 0x1cade31144cd22ebL,0x53a0d702bb43a1e4L,0xb25868777906519eL } }, + /* 62 << 322 */ + { { 0x46e2415deb5003acL,0x05aee8855e8a6a0aL,0xbda9f162bbaf343dL, + 0x658b350b21853341L,0xaf6b4948ced47246L,0x1d454740723cd3bfL }, + { 0xc4b7ce3fe1aaef54L,0x619420daa35c9e24L,0x65d455b14eb7a52cL, + 0x2f9b700a4c961515L,0xa5b7b962d3aed448L,0x4e32a6d937851d3fL } }, + /* 63 << 322 */ + { { 0x2c4c1b2ed00f8cb9L,0xbf83ba500fd305aeL,0xb75bcf9f801a8e64L, + 0xd8ab465ccba76b29L,0xf5a2bcd74ea718f4L,0x81501d563b592ae0L }, + { 0x9734e4e26ae6bac5L,0xc4860b0eee304e5eL,0x8bd59b7b1d59f1acL, + 0x7c9497e8e799594dL,0x4bc6634c08292918L,0xc45583aa92619229L } }, + /* 64 << 322 */ + { { 0xc5ad791eb45a8002L,0x4a23fd68ba2d7a40L,0x673b9e4998544bc4L, + 0x934d8f55d273c360L,0x7fb48d0768a75a8cL,0x2e6201055e0fac97L }, + { 0xbe01655ff10ed580L,0xd21d52ae9e96731fL,0x74f830de53325138L, + 0xa7240331de9f3fc5L,0x96b25206a7e01fa5L,0x3fcfedee07eda4b4L } }, + /* 0 << 329 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 329 */ + { { 0x3e6e93818d5c039fL,0x809494228a8d2cc9L,0xf2d7c8b4b843ec06L, + 0x0055d882af8a23f1L,0xe848010ed3792335L,0x9b41a55f55e08e74L }, + { 0x956ea8e95de83059L,0xf159a9973263678eL,0x5f7b9271cca1b548L, + 0xd41d2281f1d0b7f1L,0xb187047b5c9963fbL,0x213ff6af02536cd8L } }, + /* 2 << 329 */ + { { 0xe51a95700d0fa76cL,0x67c7890e4d2e9c8eL,0xc6160fa2f974d2cbL, + 0xe00474f74c6a78deL,0xee916e510ac89d11L,0x1adad97af826f133L }, + { 0x3fc65d3f8d2d77f3L,0xda9420750ba6c300L,0x5237a82e0b9196b1L, + 0x4975e680a572b6f5L,0x41ea8b92b9bed2bcL,0xbe0ad7109826825eL } }, + /* 3 << 329 */ + { { 0x06f721d30a9ec81fL,0xf0359222034f3e78L,0xc5ca6b7a5a44ffd9L, + 0xc53e328915764390L,0x7f16917459747d7dL,0xc3a9981461f79122L }, + { 0x099f4e3a97aa46f7L,0xcb0570c9d70458a6L,0x270a43576b72f327L, + 0x9d6bb26cc33695bdL,0x60f9202126224902L,0x8eb0e108e1b0a51fL } }, + /* 4 << 329 */ + { { 0x8a390dca9fcaba39L,0x3879f0b4278d22b3L,0x77bbea69bc5e82f1L, + 0x71f02e2d4628d6f1L,0x6260790cf968e240L,0x1c7f3df5665270eeL }, + { 0x336395451a87b1c8L,0x2011fd214ffd9fb8L,0x69060f867807ed55L, + 0x1b0ac0119dfa452cL,0xbbdb25fe06d27c0dL,0x5c25d23aa60ef90cL } }, + /* 5 << 329 */ + { { 0xc08dc153d9f75d6bL,0x5c1f07e7a0330237L,0xb3e6fb677d67a5c9L, + 0xca949ed098f9faddL,0x48b16b2dd7720835L,0xfdb1b735fee4d341L }, + { 0x1a6b37b1debf3207L,0x5b3eeb1e3218c63aL,0xc19b57b504c23b30L, + 0x178bd3bb40669e2dL,0x74e57b26fb6b162cL,0xc3626931a0932b58L } }, + /* 6 << 329 */ + { { 0xd3eb69e4734b2e9cL,0x1c2754e2c35ff1b3L,0xa26681e69f3e8c51L, + 0x7892ad11a2cae737L,0x88b1da43cbd8bda6L,0x8a576942419d21c4L }, + { 0x7c124343c90f4545L,0xa5a8d93b26453baeL,0x9a4c08fd76ae72e8L, + 0xa08b82d97b064e94L,0x4f803ba083725330L,0x33672455865235f3L } }, + /* 7 << 329 */ + { { 0xf7a5e2f0a51e695fL,0x3099bf9484adf10bL,0xb2a03c0f22a3ff04L, + 0x30303a910acec674L,0xaccb2f3ca59522f8L,0x00ff4d88f273ba94L }, + { 0xf0056b4210e735ebL,0x3337279a7786e93bL,0xfecc77c44bb3c31dL, + 0x3385bf5be0e26a05L,0xa9454ab85f45fcbfL,0x41a4158346edb553L } }, + /* 8 << 329 */ + { { 0x1877dfd0c8110f1fL,0xea88f59d18db27c2L,0x9d089536c78e295eL, + 0xcbb5d55374a04cc5L,0xe3666006827f75edL,0x8557b81a61e7378cL }, + { 0x74170170ed223f48L,0x84197a6ed86ee829L,0xd75a30f8ac1c4a0fL, + 0xd7e7be0d3cd92824L,0x5ea0abdb1b5e86d4L,0x41146ae1b3b615efL } }, + /* 9 << 329 */ + { { 0x6d340fd3fabd376bL,0xb5066b1ccc169cb3L,0xa4148142d20ef8f1L, + 0x0c5d66fb461544d0L,0x84c7a232d67043d2L,0x4c0e77867e609af4L }, + { 0xb1e83f1af4619e4eL,0x40fca1a0b225d174L,0x39bb3a882e42fa4dL, + 0x04dfe833d2682205L,0x49016d9d685296f8L,0x2da587198b735155L } }, + /* 10 << 329 */ + { { 0x570deceb1ae5e9daL,0x5c079c70b73ead01L,0x522a30a6d2ce6639L, + 0x71dc5c3ff4056ac9L,0xd93c7a2dbaac149fL,0x5c3298b8f1844cebL }, + { 0x282adf408c23c0dcL,0xbe4981899b646f86L,0xe77c1950628da9e5L, + 0x38cc27baa1fd5a18L,0xb5579728aacdca52L,0x8d34fdb4c8e1ecbdL } }, + /* 11 << 329 */ + { { 0x563e0b8a7a7fa597L,0x6697c375bb7dd079L,0x95758ff6c6233951L, + 0xca07993fa2059c40L,0xc3065507ce2aaefcL,0x9faed33c6ea927d5L }, + { 0x0f8b48241207247eL,0x0044f6115eb2263aL,0xd7c9ce7c851596fcL, + 0x54729d523c69d424L,0x42cbdcca45876770L,0xc1e0e6ceeff2adcbL } }, + /* 12 << 329 */ + { { 0x323f2102adea7d6aL,0x035b354eb694b253L,0x66dc4e4a5b8a36c2L, + 0xb609222471795ca4L,0xd8c6d7eed300d80fL,0xf31f258db3b94954L }, + { 0x0f2eb679277ced5bL,0x0b16efa3eba40e3fL,0x400035070dca4f36L, + 0xd34c91cb59a9a3a1L,0x5e8fea3286da6408L,0xf237959f03f31728L } }, + /* 13 << 329 */ + { { 0x1d3173653412e8d3L,0x1d14cd1b09695abbL,0x9044adf2a2cda00cL, + 0x60a6ccd60b7ba011L,0x614b100417284b46L,0xfb3d84b9cf840203L }, + { 0xd65b3566532b068dL,0xc8c03996c2465150L,0xc9035c2df71c35f4L, + 0x350231a752222e21L,0x59440020451935b1L,0xd723a55cccfdd206L } }, + /* 14 << 329 */ + { { 0x1b5bc630bbaaedc6L,0xe7d25088b49cbb3bL,0x5622cbf70deb8cf0L, + 0x3b20803cd309c3baL,0x64c2e7deff45e2fcL,0xfa730ffb9aab84a5L }, + { 0xba83cc514edfb52eL,0xe05c0140748bbd69L,0x27bbb5f52254ec43L, + 0xca740989324c8c40L,0xa21488b1d26491b4L,0xe2753a1f69d8626bL } }, + /* 15 << 329 */ + { { 0xea04908f64dab001L,0x8ea1f127b4debb2eL,0x87adb69534f155a0L, + 0x41595cfcca8afe0bL,0xffef042f8763ba08L,0xb7b4865decd3e667L }, + { 0x2c46c97070c4c8a3L,0x1ab18c080403d206L,0x08b2d3c94b3df379L, + 0xc6a4c268a87a7166L,0x449bc61f5323b1f0L,0x8d4b7ced489ada74L } }, + /* 16 << 329 */ + { { 0x618ca06b8956146cL,0xd51f1e6f552cdecfL,0x981372cca3b6ce7dL, + 0xb44a68ee5f14bb57L,0xfc1167e96373abbbL,0x3d621f8b767d4c0aL }, + { 0xc6dcdfebf6ecc778L,0xddda926282d1fbddL,0x477501aabfcbf2f7L, + 0x0be7228a67aa8277L,0x5de7b8331daab9cdL,0xb88a4f9a262feb4aL } }, + /* 17 << 329 */ + { { 0x203a666c608fea53L,0xbf71f8fde8979c08L,0x3bd58feba22a3d2cL, + 0x596bfcf521f178a1L,0x6f207d89f84beffcL,0x8a7c6dbb18097607L }, + { 0x208f5e64a1c5c927L,0xd7d0e33478dc83c3L,0x5e9397261d4e30f5L, + 0xf3877242fa09a36cL,0x68e4338ae6a7b0feL,0xcf8cd131ac47b369L } }, + /* 18 << 329 */ + { { 0x28f18586936fb33fL,0x9809b2ab381bf7bbL,0xf6e16931eac3c252L, + 0x366d18335e151187L,0xe5b4c2357a3b6460L,0x693a9fa50a68bc91L }, + { 0xa35f104a6a7f8b6eL,0x3e5d6981688676c4L,0xc0c081b10651a609L, + 0x6df5da2dd77057c9L,0x8bb271bbc4602847L,0x322547b3c4bd07d8L } }, + /* 19 << 329 */ + { { 0x9b56b9444deb8158L,0x5f4b15a6da5eb70fL,0x120afa9514cb0126L, + 0x01f6d00d6bdd0d78L,0x73dd7c5c463b1ce6L,0xc770cf35df00a133L }, + { 0xb5db93a1247ff879L,0x1c12f3f0c70ecea1L,0x10168c4e5b59cc9cL, + 0x1e9e0f8a0e19efe5L,0x43987dc1cfd44b62L,0xb1d265c204814e2dL } }, + /* 20 << 329 */ + { { 0x8c283529233d39e4L,0x96300796c6092096L,0x2c549de55dde766cL, + 0x27e0b444b4151002L,0x802e5fc3f2f88f1bL,0x2af579c28ba1956dL }, + { 0x52edd04ed68196c7L,0x2e22e71474a202b0L,0x338948248bf66459L, + 0x8f0d8c259e39df55L,0xee4f109e6c5276d9L,0xc0c893f0c5dc0bf0L } }, + /* 21 << 329 */ + { { 0xa3081bc75b3f17e5L,0x299e7a0222e46b9dL,0x36184c98a9afa278L, + 0xee2043319095a8a1L,0xf5e54622cd5ac080L,0x08d649013fa844a4L }, + { 0xb20ddfc6d7fbb42bL,0x15130bdbd868a81eL,0x25e5fd2f32ff1a03L, + 0x907e3c01ca5288d3L,0x2f2f7496a1f6f96cL,0x831feefd38ab83d9L } }, + /* 22 << 329 */ + { { 0x06054c76f8482849L,0xc24b4a6a5fcca65dL,0x71c27e01a17ebda3L, + 0x1ffce0281be9dfb8L,0x3784c950ebc43854L,0xcf0ecc2dd5086510L }, + { 0x86d0fc3cbe24d8ebL,0x5bad01911f21788eL,0xe2c3bcb9c49b3a12L, + 0x66f82433f7d5992dL,0xf7cc5eb913969246L,0xe52defd48660a6daL } }, + /* 23 << 329 */ + { { 0xd6d6a42b102490deL,0x9e6532acf40d27d7L,0xcd1591cdf2a08bbeL, + 0x973e09f234eb47ccL,0xb3a5915add4fa316L,0xb36ca6ceac38218dL }, + { 0x73d370b3e58a0cafL,0xbc8fd39f07766be2L,0x3d5d9ef7c2ea7997L, + 0x22877500bbfcc1a7L,0xc54d0c6406e0547aL,0xf7bc1d2d564e9ef1L } }, + /* 24 << 329 */ + { { 0x7a9623b653fd1a04L,0x13bd35bf3a3b8500L,0xf8a5dec9e0f8e530L, + 0x88bcbe291d65dcd4L,0x09fe38036739541cL,0xebd04b7fe716a97aL }, + { 0xbd8e34df1e5ef7cbL,0xddfc4243d7c4fd6cL,0x0183d9053519411fL, + 0x63450996f7a3c483L,0x18283cea01355739L,0x8c1d72cf9aaa72f7L } }, + /* 25 << 329 */ + { { 0xffcd4b6f9be9ff57L,0x0bff01bb939327efL,0xde596626b5ed90e3L, + 0xc07464ff4379e17cL,0xefd3e2c470d31340L,0x78b2192f4e7df61bL }, + { 0x7cfe28def3faf2fcL,0xd2d1a994dd642f87L,0xa5d4fb1410b3377eL, + 0x2cb4978ead6fa00aL,0x5b6fe7a765fb3688L,0xc26c1b3336d5acdeL } }, + /* 26 << 329 */ + { { 0x551e1b4e8dc72468L,0x8a926cb2a7b2f1acL,0xb873e83b0fd12fadL, + 0xb6cde14fa4e7fb13L,0x81ae41415befc256L,0xffb0c636b4c7631cL }, + { 0x80f1408f8a2478feL,0xde6d051d44fa7605L,0x5a15b1f84d44a1e4L, + 0x1a0031c5a0daafe3L,0x304338dd597652a7L,0x6830dcc7f257f17aL } }, + /* 27 << 329 */ + { { 0x62fae4072fdc8ea4L,0xff77522fcbe76ee3L,0x5fa03a454fd2bae6L, + 0x774c635e8dc90431L,0x718081b62ddc4376L,0xf4901a2c03e7aec7L }, + { 0x5339a3109eb023d7L,0x15dd4f96366e35f7L,0x1f802d4a0e2d2e95L, + 0x8e5e9cb2fe1b1226L,0x175806f623a0de5cL,0x115a97db068c7bbdL } }, + /* 28 << 329 */ + { { 0x4a67ec76193aabbcL,0x3da6dec6d74761f9L,0x751720c90b35bb70L, + 0xe5e049058d9e0f8bL,0x3cd37c840858f29cL,0x7ff1abfbb881733eL }, + { 0xa0c2698b0c4f7694L,0xc736419296b95e4eL,0xcfa55c5537ece651L, + 0xa2bbd6ae7cb1e9e1L,0xcd2292b9a0eb0e8aL,0x8aba99e18d5030d0L } }, + /* 29 << 329 */ + { { 0xa3f508a498fa3d8cL,0x4d894cbf45bcff40L,0xbcdac17d0c095cc4L, + 0x397caa6f407c2ed8L,0x2195056b5f97b4a9L,0x41eb6e0e97434508L }, + { 0xbb5e4e4a73f211f8L,0x5e8e638f720a451cL,0x8470bc9e4974252dL, + 0xc487aae29f6a9a96L,0xaa66417101165deaL,0xc8af7172b603771bL } }, + /* 30 << 329 */ + { { 0xb7c74c58dc4a1d3eL,0xe3ec30160331ea39L,0x83afb271023c8712L, + 0xc2670d56c9c82680L,0xd426f350feca1061L,0xe8aee692ba6edc01L }, + { 0xc916fbe546e801d9L,0xcb001c377097286eL,0xfcf79d2678ee1328L, + 0xb05b0634b6a4afb3L,0x2ab327bb306da14fL,0xc11a0294ba5ff534L } }, + /* 31 << 329 */ + { { 0xcaa287c30f00dfcaL,0x9ca672930601cc7eL,0x435e883fb105d00fL, + 0xf9cddbf91238536aL,0xda604ccb45f558c3L,0x7e51d9d182f48366L }, + { 0xc1e8d50d7e8396c3L,0x58638b85edbb75e3L,0xe926aabe9b088d2eL, + 0x8103a34a428c41e3L,0x03e5e35d089deeedL,0x64969c6d93bb0b99L } }, + /* 32 << 329 */ + { { 0x7b7da028e19763ddL,0x662f54df8b98ff78L,0xc056d83c51f3dbd9L, + 0xe2f4d46fa91d085aL,0x31759c9ceb35262dL,0x624d0cf20c9dd29eL }, + { 0x108cf9bb1624b02dL,0xa241444e345531d6L,0xf69816b273d372b2L, + 0x126575a7d5415e53L,0x546bb4c1306b8b0eL,0x82bb0c124d54ea5eL } }, + /* 33 << 329 */ + { { 0x85b355304c397362L,0x218a3b0eeda72e19L,0xd8eae54461729c56L, + 0x3d9b4a62735b571dL,0x12f3ee775629e437L,0xa72f9809095e5378L }, + { 0x5420a641bbe6dd1eL,0x8121eb3d02f41fe9L,0x5698eaf945e7acbaL, + 0x8a5e1a89469c2f12L,0x801740e25b434e0fL,0xa4dbe1cc670f58bcL } }, + /* 34 << 329 */ + { { 0x2f1919df5819e9f2L,0x156489e7a62287a9L,0xed038deb20a0c2caL, + 0xf63ac2d5c5ab4fdcL,0xca2b648ce391ec06L,0x8258e3f45b047d2eL }, + { 0xb7dcff56fd17b40aL,0xa8ace11f4bed747eL,0x542d70d175018429L, + 0x6c568967951bb2e2L,0xce420f73bb0e089cL,0xdae9623ed13f8eb5L } }, + /* 35 << 329 */ + { { 0x2d561034009a41d3L,0xf078204f5734d3a1L,0x2b8973ff7408e71fL, + 0x07cb9f95aab9c533L,0x376c1f59d0b35fffL,0x4a756c7fe851b313L }, + { 0xdc690e9874dedeaaL,0x625b082f70cf3f5cL,0x44839b5803dfc301L, + 0x5835a6c3c520f618L,0x695425e3afdb68d5L,0xc04ce4c62db97ee7L } }, + /* 36 << 329 */ + { { 0xc1d9b27ecb5833e7L,0x9911909567a8a669L,0x9317f8c30ab9ee27L, + 0xfad65eb9f34551e6L,0x7725ec2e016504f6L,0xca492cb47ebbdfc1L }, + { 0x6d2a3c962706aa66L,0x53e6d650836d8ee2L,0x109496434bc84bf3L, + 0x8442ee826df7c0f1L,0x7ab2eb9918fe80c5L,0x6a8579b35cd2ea35L } }, + /* 37 << 329 */ + { { 0x96adba7706e80e68L,0xa8839d6a0fe580e1L,0x755227e337a31a9bL, + 0x40b5fc70e27ec051L,0xb900a11b29af222aL,0x8fea2e509dd84811L }, + { 0x4f844c8861b59ab3L,0x26739874560c0948L,0xb39f85ba0cc08828L, + 0xcdce2fca829082edL,0xbd17998eb4555dceL,0x827eae97a3608a9fL } }, + /* 38 << 329 */ + { { 0xa77087f4c98e17c4L,0x9fa12dadbe2985a5L,0xa68cabc94bdce4e2L, + 0x222a6fb6d3500913L,0x15e28fd5a9c0904eL,0xed31c63f7a91f825L }, + { 0x9cd9f3e56f2f35b0L,0xa2b14261923cab8dL,0x71a780516d8ccbeaL, + 0xf1fe532bdfa937b4L,0x6e3d7252539d0a74L,0x27ef2720814cd797L } }, + /* 39 << 329 */ + { { 0x8bd8341e6899b9bfL,0xc2ea111680865aedL,0x0cabb5cf13fed0e6L, + 0xa11e82c1e4ce70c0L,0xefe3d4eb99aba16aL,0xd774db4dd8df10c3L }, + { 0x72ee5c98bae14dbaL,0x9161d0b179b86e02L,0x1ba8b84585e5ba90L, + 0x3830148f17228bdfL,0x222499e2ba89b2a5L,0x5d50922cccd4f87eL } }, + /* 40 << 329 */ + { { 0x81dd074e4398751eL,0x87b11b480a3f3ebcL,0xb5afe1f0352b58f5L, + 0x6d2d94829c390eefL,0xd073f9a0f36a8d23L,0xa7c5abec466ebbe5L }, + { 0x968c04a60539f145L,0x52a3ad0c93f4d3d3L,0x98e196bb15c0970bL, + 0x2af28ea370ab8ddaL,0xb912fbda7a039fa9L,0x3dd8d87acbd02ff6L } }, + /* 41 << 329 */ + { { 0x849b2f0b4ee5ebb7L,0xfd1b015158bea2f9L,0x260a6b5bfbc530f9L, + 0x2b6c198d06776366L,0x6540793f8074c6d2L,0x1c722c259871be11L }, + { 0x8ce5241ce0560ce9L,0x3574db548096df0cL,0x1d9dd078b0fb8c98L, + 0x6049c7f25625a023L,0xd2c0853cb18d0dd0L,0x5e57bd71cd645f78L } }, + /* 42 << 329 */ + { { 0x8da9b831361ce377L,0x6496515b7dc06076L,0x870e7df3b8cba83eL, + 0x315ac0049f8f495bL,0x1a09dee576fe0978L,0xae7af621c18059a2L }, + { 0x2bc9dea404fac2afL,0xc630bd5021b90a79L,0xbded6b8628c0f9a1L, + 0x709d72c7be4fe93cL,0x3d1e2eed74b22303L,0xcdaf6b1d0e81dfcaL } }, + /* 43 << 329 */ + { { 0x42d004f3be8ec138L,0x5379a3063d617cfeL,0xcbbd274ec1a87d06L, + 0xb9967c5284c9df0dL,0x0238d715c421e288L,0x787ee6abd239639fL }, + { 0x746e4071adace009L,0x2e2545db61377666L,0x47cc241cf07deb1fL, + 0x0a0742f1847dee19L,0x50175dd06e59b0acL,0x95ce3065d2333a87L } }, + /* 44 << 329 */ + { { 0x65c33cf4ca5eba6eL,0xbc48b22e12c2f19aL,0x6c5bbde461fbdcb0L, + 0xe086202bbc503a00L,0xa9483799deecbb11L,0x9b2c0216279aff50L }, + { 0xc10fce1069f99456L,0x2b0051d5b7820d55L,0xd2de9cc32129b5a4L, + 0x711166d9e4f565d6L,0x7a8c3dfb88075f30L,0x6914edda224ac45fL } }, + /* 45 << 329 */ + { { 0xca481b6e4e1e3cabL,0xf390ed5f7e12d8b5L,0xcda82616dcd06247L, + 0xf7d791422cec8917L,0x0c2ea9fe2364e5deL,0x471b71ed21f98e3fL }, + { 0xbebd6a753b9aae94L,0xf9914c0b45f5d5a5L,0x07c823ca4b3dd18fL, + 0x0b8c09ab74ad2bafL,0x21048cf7c7376302L,0x080e4a00efb16ac2L } }, + /* 46 << 329 */ + { { 0x1699d711379e6c77L,0x9126d88c7427418eL,0xbb05797d825210acL, + 0xc0b611df315cb277L,0x90f82a9d61f69206L,0x39a79014f517228fL }, + { 0xd9f2def450e8a693L,0x88c1104381e9d71aL,0x28e20b56451f8a9dL, + 0xeaa794763e101231L,0x3f1ba0c56423e8c3L,0x2fe7ce4e3c6c558dL } }, + /* 47 << 329 */ + { { 0xd706ab9cc55b1a3cL,0x99c453663aa386f6L,0x348c8f743617676aL, + 0x5f3c49092b9ef7bcL,0x26969963ff5d4864L,0x1f952e03f5b490ffL }, + { 0x4007914e30cd5518L,0x3b38fd1e0b0e6513L,0xb25e0a81decbba43L, + 0xb7e77345a7d78431L,0xbb7bc23062467d4aL,0x616c1724598ad852L } }, + /* 48 << 329 */ + { { 0x5bcf287864e60ac2L,0xf70e78a455d53345L,0x88685de6707a7138L, + 0xa77646dcfb2041a4L,0x8608695289db3060L,0x08b7c4d8e27a1690L }, + { 0x4148d9373ca7fd81L,0x58c7440bff7698a8L,0x9d722d4db0391d14L, + 0x5683112462b0373fL,0x87b0363be9a9992cL,0x51870cd18853db84L } }, + /* 49 << 329 */ + { { 0x775086f481eb73b1L,0xddf02d0e4db4d236L,0xab3d637445b09e54L, + 0xb7ef92657e883a2eL,0x20e6ae8f7f42b4b3L,0x26a14629bc49d85cL }, + { 0xf0ee4e5ca4ed9ba3L,0x288c5b0793b0b721L,0x9c767a59e9917114L, + 0x3dde322015085ec5L,0x3176507f7ece24dbL,0x71e1995686cc47fcL } }, + /* 50 << 329 */ + { { 0x86dedf2e9b1ab85eL,0xf3330387c2d0593eL,0xf5e6143997e907a5L, + 0x1992569d8cd66e4aL,0x836b215e0869329eL,0x8b5c4891153ff215L }, + { 0xf6c52f1b609dcc15L,0xa3a5258c085722c3L,0x0a4e81501c378dfcL, + 0xa8997ddc739040aeL,0xb1c4417a7180a073L,0x618009bff1dbab34L } }, + /* 51 << 329 */ + { { 0xc276e23733ec753fL,0x196a1ccee112da60L,0xcc049e2b953211efL, + 0xa60e1aa711dcc43cL,0x091ceb49cdfed2ddL,0x8fe1c52e72c69037L }, + { 0xf66eac87a986ba11L,0x4917f822b273d90dL,0xf7ef04cc957befacL, + 0xf8a7ac1320b8aeebL,0x71f0db3dbe6af428L,0xcb0bf8ba566429c8L } }, + /* 52 << 329 */ + { { 0xf617674d2cbb40a8L,0x446ad46b4d11399aL,0x4d4246943076b6b3L, + 0x1b9e7d881c33ea9eL,0x8e1aa6716954589cL,0xf1099b26e221722cL }, + { 0xb18904f94917576eL,0x0512b21bb549058bL,0x12c89a64a209ad3cL, + 0x421f5e575557cc67L,0xb42e17371b5a17edL,0x427c6a621ff3230cL } }, + /* 53 << 329 */ + { { 0x74e75db02bfb49e4L,0x7685588d58cf18dfL,0xfbfe8f56398e27a9L, + 0xd2711ec365666b9fL,0x1df7714d2c59b787L,0x0f2c4b4c486f8fc0L }, + { 0x098ed315f847b688L,0x60c367e332a20ae2L,0x58f48cd6bba6dd13L, + 0xc41e31960616128aL,0x7f90dd69a3205005L,0x8e6ce9d23581c177L } }, + /* 54 << 329 */ + { { 0xcf2da6044a3b3618L,0xcfd27cc6b83f1814L,0x8cb45c0a6b9369a6L, + 0x1f11501633976ef1L,0x2654a1574afc708cL,0xb47f423860970498L }, + { 0x548be9389fd8536bL,0x454fde1673ff1ecfL,0x44657efae96be82dL, + 0xc8e7e96b555df813L,0x2a0b3f4a4fccb822L,0x2e0f36b114b6dfdaL } }, + /* 55 << 329 */ + { { 0x227ba88551cefcb8L,0x81e8f52e00071a19L,0x4afd5a5d170fee3eL, + 0xc8864e274e17ff05L,0x1d8c2083710ffa4dL,0x22529baa9839c46fL }, + { 0xad771341825a0a87L,0x34a3049edad7c56cL,0xf1f14e1712f3625fL, + 0x6103d1fabcd36dfbL,0x9f5ce7a949a7cf78L,0xa5a4e38a333cf634L } }, + /* 56 << 329 */ + { { 0x6c8e5a261d99492cL,0x6e5bab8e77f916a3L,0x9b014aad50ad6f39L, + 0x2a3933c51f107e26L,0x4b04395cc951bf73L,0xf8f683b4b0ef56dfL }, + { 0x28c9fcdd1905c84fL,0xb03604f14141feacL,0xb546f58e53ace23dL, + 0xee5fec4efe688f02L,0xd8b43f6d2e91406dL,0x75e44b21261764d9L } }, + /* 57 << 329 */ + { { 0x56905026e84e6549L,0x1dc1958c5b84b0b7L,0xcb477afba55d3c52L, + 0x6c67cf7bc1434094L,0x739da94d2ecb03edL,0x8c45e5ee778ca2fdL }, + { 0x66084f9712e2fe43L,0xee6a89e66c3289d1L,0x623b73abc5d1a215L, + 0xb0edfa31cbf45830L,0x8024dffbd7de3b1fL,0x2ddf805a27f25caaL } }, + /* 58 << 329 */ + { { 0xb4e5a5d5605d7341L,0xe7a7a4069a1d3465L,0x234783d66c60b1b0L, + 0xdd7ee2fb3b480129L,0xfd183240dbb7032fL,0xba2a97accaedc8c1L }, + { 0x1a1824d3b0185c9bL,0xddc0f82cd36edae3L,0xaf7bbcc03116b17dL, + 0xefc9095985f6e8e4L,0xc6bde428acb9c328L,0x69d80732cbf991a7L } }, + /* 59 << 329 */ + { { 0x455a23a465ecec1dL,0xcf0b2a221d9e9887L,0x0b43131e3fbb1cc9L, + 0xd4ece789bdad49b9L,0x370c2f9aedfa4d17L,0x7f6855be15163f17L }, + { 0x868a16f3735ecbd1L,0xd84527db08897c01L,0xcdbf5b18f2df294aL, + 0x8c500b1f12b99a2fL,0x929c58df2591e3b9L,0x314cb13714eae6cbL } }, + /* 60 << 329 */ + { { 0xd014cc6deda2479bL,0xd2586003f1a85fb5L,0xceb0611153cd207cL, + 0xe8c9fbfa647b3c16L,0x1f53e8e6ab7d6738L,0x06dcceabb060b5f3L }, + { 0x80e023b2ab770ccbL,0x83ca0a5f4cda70d2L,0x19f7f5dfea1caa2cL, + 0x769041414ffe884eL,0xfa4d93a3fca3c05bL,0xd381f527e88e1169L } }, + /* 61 << 329 */ + { { 0xa4553b3534914b85L,0x03968ddddc176f80L,0x095fb9531f258fa3L, + 0xda9d2df7a554bb6dL,0x012a30ed84926864L,0x3fea37b12aa219d2L }, + { 0x730d2c6d81cc6036L,0x96ea83c9ddd81991L,0xfab080dcef1678dfL, + 0x16e25c6bfb2fe230L,0xf083a2b298ef2fb5L,0x0c0d0767581feac0L } }, + /* 62 << 329 */ + { { 0xd464a6525bc81cc8L,0x513353adebfa99d0L,0xd1aa97c0be51245bL, + 0x0d37e590e4d20201L,0x7afc95cbb45c5c19L,0xdbd640cfb6a4ea8cL }, + { 0xffcc3ff2be9c5b78L,0x61cb76ac1b2865d1L,0xb145bb0011352d21L, + 0x69568e5ce550ac6dL,0x454a33043bf7ee0bL,0xa2fcf9b45dad3642L } }, + /* 63 << 329 */ + { { 0x2e2c8fb3f33eaca6L,0xae1c78b265f75366L,0xbdc601092280d2b4L, + 0xed8409b7b6f472f0L,0x69eafa4f439e09afL,0x3b9ca2ecaa2b1531L }, + { 0x59b2e8eb336e484bL,0x93ec3ecac5f0481aL,0xb01e690ad575157bL, + 0x811aebc262e9d767L,0x1b26c0e49a9065eaL,0x5712d2c969a18827L } }, + /* 64 << 329 */ + { { 0xdaa7fcc9f9474bb7L,0x3c82e74bafa5db2aL,0xfbf918c59894edceL, + 0x470c45eda9ac29a7L,0xdfd44f6fbc372f2cL,0x73a4790aa1e38d3fL }, + { 0x23d2400ba9674837L,0x3dad71bc136a92daL,0xc76a488148baa4abL, + 0x73227e4ebc26e6b0L,0xe732edcfe8ef5662L,0xfe96aa5f0c5662bbL } }, + /* 0 << 336 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 336 */ + { { 0x87c7dd7d139b3239L,0x8b57824e4d833baeL,0xbcbc48789fff0015L, + 0x8ffcef8b909eaf1aL,0x9905f4eef1443a78L,0x020dd4a2e15cbfedL }, + { 0xca2969eca306d695L,0xdf940cadb93caf60L,0x67f7fab787ea6e39L, + 0x0d0ee10ff98c4fe5L,0xc646879ac19cb91eL,0x4b4ea50c7d1d7ab4L } }, + /* 2 << 336 */ + { { 0xcfbcbc4a7db62b5aL,0x2919bf514ab45ddeL,0x735de05622322f91L, + 0xd2590bda7662ae23L,0x63d468fed82be7a6L,0xc84d0435695ea172L }, + { 0xc50f494120a6fccdL,0x2d613990620f44f1L,0x680ccd041fd25778L, + 0x25ddac444a3d0808L,0x41d8b738c4684cbaL,0x2611645f53963888L } }, + /* 3 << 336 */ + { { 0xb05cb834b0279be5L,0x2de7d0ebf08c5f93L,0xf023b5aaefa9e4f0L, + 0xb8061e5d9bd075ecL,0x7d2ba50f1aa41bfbL,0x8963f3e390865d96L }, + { 0x7f221a794713ec7aL,0xc83bc5178500b4c3L,0x085feb6af6ab1540L, + 0xfd141024dc87cd93L,0x3e196fdb3239dbf6L,0xb7cf3e16dbcd5364L } }, + /* 4 << 336 */ + { { 0x1466c9f5e03a2fb4L,0xb866c006862a58a2L,0x291e8c75b5865550L, + 0x1ddb7154e65862ccL,0x285153bc2b997167L,0xe2fce0e7954b6c19L }, + { 0x985d450616dc2937L,0xf7f14216ee41d9c3L,0x39e098dafa5fe5e5L, + 0x3fc26046f90f231dL,0xde5d5ced32afd0b5L,0xad688b1d60c09c18L } }, + /* 5 << 336 */ + { { 0x3720b1720f806b59L,0x1f696d47f224597bL,0x03c46e315b54eefcL, + 0x387e466472b0edaaL,0xfc59b03dee77476eL,0x86854e54607a7259L }, + { 0x1478bcee3e9320dcL,0x4aa825a88c9d87e4L,0x71272f72cf272ee0L, + 0x19e3a4a38bd885cdL,0x9af6415b376ba31cL,0x6394b5a7807b2b36L } }, + /* 6 << 336 */ + { { 0xdbfcfa75e572e06dL,0xafa019d08b7d5653L,0xcc6c851d67a19b60L, + 0xace88bf431ae1a67L,0x74554a6193d1e135L,0x51ba2cdd4211890aL }, + { 0x7cb326899e8d1f02L,0x29a6b8258b66ab99L,0x0a672c21766e72f3L, + 0x24bb718a880642e3L,0x425dc41d184d2b36L,0x96a1468e891024abL } }, + /* 7 << 336 */ + { { 0x3180789c26df7050L,0xe375a43e96cdfd31L,0x7951b895e99e922dL, + 0x987ea2503d0bbe80L,0x6d2f49f0e2fe79c0L,0xc9c2c636c2b18d2aL }, + { 0x707798f3d8c8620cL,0xc2d603dad5c6a0eeL,0x46cf1e32bc447940L, + 0x4dfc145938a845f3L,0x210083fe455e5d92L,0x6be989eaa1fedc3fL } }, + /* 8 << 336 */ + { { 0x72fc8198dacc038cL,0x5fdae1d9f1077bbdL,0x369198bbd99e3036L, + 0x6b68390a0efddfcaL,0x8c35f3e4f0914741L,0xd2bc54ecca7d7807L }, + { 0x564d991e3a8695d1L,0x5e1e14c81b0d937dL,0x51f30dab5d635893L, + 0x0427e346f944e49aL,0x1e0bf1b56a233bc0L,0x75b0ee6c617bf93eL } }, + /* 9 << 336 */ + { { 0xcd2db6797b1bbd75L,0x1ce5acecaac388b1L,0x715ab9f634c1fa9cL, + 0xa531e1b8e0815643L,0xa64511c692de769bL,0x8425126b785b8bc0L }, + { 0xc8d9320de72e155bL,0x9cf36dcd5600a04bL,0xbea8b0f4c6e1f7fdL, + 0x6f9af6349767d85bL,0xc3ea9fa4c403ecb8L,0x0af7be1ed60a0e70L } }, + /* 10 << 336 */ + { { 0x180afdcc20928729L,0xec2e90f436bce72bL,0xa8a8c54d8f48e48cL, + 0x9d0c6a355248109bL,0x8bdd819baa6c3ae3L,0x95e221a6dc0bebc1L }, + { 0x83e568eceb113737L,0xaa6d29c8a1a3a0a8L,0x0ebd5015c54fbda4L, + 0x692a84832a5c8b17L,0xa08e384b51836490L,0xf1904bfc37ded786L } }, + /* 11 << 336 */ + { { 0x2093335463919940L,0x34e4f27397ea3359L,0xbe64c5584d4156a5L, + 0x368a6c980497cf92L,0x59931a502288b8cfL,0x67d70ff8c36cf906L }, + { 0x4175562a8886126fL,0x46ecdd1d55114ffeL,0xd12876f94efde702L, + 0xb0c9333fc046d908L,0x8358b04a2cd6c180L,0xcbaf4612336d3c84L } }, + /* 12 << 336 */ + { { 0xd77d9cd4fe8dee55L,0x7a0f60c12e43fc84L,0xecc5cd746d5da126L, + 0xb5ac6fee2382a984L,0xd9db83e26ccd0feeL,0xaa4dbcba350717d4L }, + { 0xb3c0562c812ead77L,0xf7a995eea96cdd07L,0xd5419bf1ffeb4e67L, + 0xba0aa22e1226df29L,0xb8d0d7f4c1e333d1L,0x86fecca60a27388cL } }, + /* 13 << 336 */ + { { 0x9ea1d715dc579084L,0xc1e715dd0b1cf2a4L,0x624fa6e4926bf7d5L, + 0x5034c9d34f7b4e51L,0xc1b0ed7aba3a42a6L,0xd1847c28b73cdb77L }, + { 0xa4794bc36ae49ff0L,0x50b2d908b9144fa5L,0xad112c778f073479L, + 0x040499dd4b98f590L,0xd415d273152b5e30L,0xd3f4ff3f39054cabL } }, + /* 14 << 336 */ + { { 0x1e0318d5fff93451L,0x40b91fa9283e197eL,0xdebc5a28089ac579L, + 0xcf25f527e9d98537L,0x73f7818d4ae08f51L,0x397f2cb6a956c875L }, + { 0xb7d74ac57515436dL,0xc29a2ffd830664abL,0x02e273563cabe01bL, + 0x418417c103c78924L,0xd12994116535005eL,0x53fc391258f66295L } }, + /* 15 << 336 */ + { { 0x6b1fceac4d87dff4L,0xd31aef70f262f722L,0x894361782612da01L, + 0x1d3bdfa9963bc230L,0x9a46505ba7afa565L,0x662c2fc7a31db4ffL }, + { 0x33983a9ae5ef30c0L,0xb8c874ee723f085aL,0xfb5fbc860f279c05L, + 0xcd9cc376ad0a380cL,0xcb19d881fdfad736L,0x1c3d9734585167ddL } }, + /* 16 << 336 */ + { { 0xd23658c8d2e15a8cL,0x23f93df716ba28caL,0x6dab10ec082210f1L, + 0xfb1add91bfc36490L,0xeda8b02f9a4f2d14L,0x9060318c56560443L }, + { 0x6c01479e64711ab2L,0x41446fc7e337eb85L,0x4dcf3c1d71888397L, + 0x87a9c04e13c34fd2L,0xfe0e08ec510c15acL,0xfc0d0413c0f495d2L } }, + /* 17 << 336 */ + { { 0xf791c8196726ae9cL,0xc95c53f13cee0ca7L,0x816b37ae601b0802L, + 0xcf28a2371b854925L,0xdc4f6bc111d5d9f2L,0x222d6102df6862aaL }, + { 0x93d3fcc5c0053ee2L,0x1d30937fdf873eb7L,0x925a2c2527d098b9L, + 0x8564c199001cf28aL,0x87cb85ed748b8479L,0xd12d6b2b184c1020L } }, + /* 18 << 336 */ + { { 0xeaf36b865bddb3c8L,0xa4bab6e0099f18ecL,0xe22839208addee4cL, + 0x485307e053bb454eL,0xf981c80d362db12aL,0x012190355cb4b460L }, + { 0x62824680c78bd110L,0xf3e0b963d87df5f5L,0xd96de5e2758da525L, + 0xc6a810faa60956abL,0x913d5a7b8e3eb6dbL,0x27c581fbbc9e8c3cL } }, + /* 19 << 336 */ + { { 0x5edcd7dcb0c55d75L,0xaeb0b5c727838c23L,0x13d65db758c3fea0L, + 0xe821d853b36f1f15L,0x3435a4bc365e7703L,0xb890e52f3a04d292L }, + { 0x6a96ae92e7a823f3L,0x3960ecb0ca611036L,0x81638aff210cb460L, + 0x5f95793ce6b983d1L,0x0d5029ffa3ae1a8dL,0x54f749b492ca1229L } }, + /* 20 << 336 */ + { { 0xefe0a702537c4a5fL,0x322ff89c151d0e69L,0xcee88b48491b757cL, + 0x8e92cc15b5da77c0L,0x3138b90bf6af039dL,0xeb73edd2f3748d35L }, + { 0xf29f06435b8bb06cL,0x91ea9643560e4966L,0x013c274875acbcc8L, + 0xdb2d1d9703f1d40dL,0xed7aeef1fcac606eL,0x91395dcabff4b849L } }, + /* 21 << 336 */ + { { 0x952e4e21c8967f37L,0xdc9f71994bf85ec3L,0x6b01f3d00c141bd4L, + 0xc6601dec06c9ba55L,0x7d884fc0c4a5945eL,0xcab1de947e19d3baL }, + { 0x9ca6aff02e3c9c5eL,0x01e828a1445e4a8bL,0xf97165ae80d065c1L, + 0xe2195895881978a2L,0x4834501fc6b77acbL,0xbcf7545445d99f5fL } }, + /* 22 << 336 */ + { { 0xbfc9c5071e434ba6L,0x30768f646f2634adL,0xee3a7cec1caf9c0bL, + 0x27c4fd0bc232910fL,0x5c5813ee24ff4510L,0xe5e731af901f2ce6L }, + { 0x440ca2cf68f9aef3L,0x54ff9e837fa17587L,0x4d792db7982acc0bL, + 0x73c3863834846c98L,0x76cff95f8d6243d9L,0x5fa573399d015583L } }, + /* 23 << 336 */ + { { 0xe0419a6fb007e4cdL,0xc44ac4961f613529L,0x3408e15af18f82eaL, + 0x66bebd87d92d3b39L,0x1c563ee4f85d0c1eL,0xb31a8c891f7eb37dL }, + { 0x65c7bf8c458a056dL,0x9d2ba592f25b6f73L,0x1ac4f0bc94eeb39dL, + 0xa008b562d9a9ac29L,0xe7de714589d1c354L,0x420f5cf04c2e45d2L } }, + /* 24 << 336 */ + { { 0xe11cc2e117cc0d20L,0x9b4cc698d406fabfL,0x6f6e9b0cb8567c18L, + 0xa0dcda9c61b22b83L,0x4c8683fa79ee53abL,0x7d46b3f82f11f0c4L }, + { 0x91e74e482740aed8L,0x75afb62a056466e3L,0xc60bb430e8d0c16fL, + 0x36cf252522b4aae9L,0x3713f254aceb6dd2L,0xc2906379eb8c6fd9L } }, + /* 25 << 336 */ + { { 0x440da0369eb8b2deL,0x6c4d1a38462fbb19L,0xfd86930fb050f995L, + 0x2e5f1a8c954823a0L,0xe9122aefcb9f8e9aL,0xc9e923f2794be14eL }, + { 0xdaa5663dbf740c2aL,0xf3a7ecd6df75c915L,0xa047a07efa80015aL, + 0x846b4d27ea4a720bL,0x2389717e295845f4L,0xf56f77f6cbf2eabaL } }, + /* 26 << 336 */ + { { 0xaac4f6a7e67b6dcbL,0x59ccb836d51c5183L,0x78d19f452b7ccb20L, + 0xb32d4ffd5a619a1dL,0x86b11dbe5c4bd17eL,0xd983e839a9b52073L }, + { 0xfe9c0b92993455c1L,0x3a156676ea36006eL,0x578217fea907ca7aL, + 0xaa3c5489440a251fL,0x6760a166d7fdf3fbL,0x4a2fc54b4415c6fbL } }, + /* 27 << 336 */ + { { 0xaedf171dbe18bc16L,0x00febab2b2d026ffL,0x82b6d8890cdcca4aL, + 0x1b1e4c53445bc877L,0xc2174e10ed74285eL,0xced66cc02b243f6bL }, + { 0x73e9ff69c7b9a66eL,0xc4fe5caad5e4d121L,0xaef80d67402c5d1fL, + 0xd3b95a0f2f3dcaf9L,0x00cb6e798ceeea00L,0x1ee2ca8c436f35e1L } }, + /* 28 << 336 */ + { { 0x0b21c764a6db111fL,0x7c36dfde24c5721eL,0x53a0b6db66e2d428L, + 0x6f37bf728169d776L,0x9baf6385a68511c8L,0xeaef9c919b218151L }, + { 0x712cdd5bdd58d201L,0x50bcd0988d3f78c3L,0xfb6427b571fcb05eL, + 0x6245fe7cc4675aebL,0xb5b75b50fb767bdaL,0xc1d8b76ddd7a18fdL } }, + /* 29 << 336 */ + { { 0x6392686cbb52f636L,0xf10df7c41c46a5c1L,0xab7f88acc504a122L, + 0x2a179193fdb6a9d5L,0x2a7c7e4e2901f29cL,0x3ab41b80a2cc726eL }, + { 0x8f577fc31fb5e412L,0x65cba0aeff7c47faL,0xa79191697f45c04dL, + 0x2712fcaeb29a4c06L,0xf2a879e4099f76e3L,0xd333fabd98a22a04L } }, + /* 30 << 336 */ + { { 0x87a905e056ddf14cL,0xd36289cb95a1c633L,0x2fb251aa57f8f0f2L, + 0xbf9c72a9fb7907a4L,0xb4f9b6f3f771333dL,0x7b5ed437469ea10bL }, + { 0xe8cfa847fa5a8f93L,0x456395c945a4c9a9L,0xe20ffc39f7fac5a6L, + 0x8b07c9ff287a3c78L,0x117f306f67e66d0eL,0x97c8a6388b331e09L } }, + /* 31 << 336 */ + { { 0x1b3e04c26a98318fL,0x04d5ed5dd5a63b2bL,0x4098d09f3cebabecL, + 0x226bb70565a14306L,0x5bdce76fd962a94fL,0x47a66e96c40dedbcL }, + { 0xd514ae5bbedcfbb0L,0xa8c0fe40892f07e7L,0xcf78e224c9186f1cL, + 0x2499f68fe94329e0L,0x3ea3fae5ebbe3d2fL,0x681fca8bbc631de3L } }, + /* 32 << 336 */ + { { 0xb097b2c5c4e81268L,0x7ef175521d50ca8cL,0x638266e942099644L, + 0x43d059deff729073L,0xeebb5fe1148c3940L,0xb82e73d1daa8e925L }, + { 0xf43c78d8254380fdL,0x2beabc58fce37fa0L,0xcdd5a7d66b636357L, + 0x8b70a2ebe096a954L,0x011d5419d0afa2fcL,0x3e49eb6704fb095aL } }, + /* 33 << 336 */ + { { 0x5c73f69fb99abd8eL,0x0a7c36aacc1ed636L,0x9d2fe67e7f69a6cdL, + 0x04d015fd48c34b1fL,0xc50f88c17f84915fL,0xeee3e105a706fb24L }, + { 0xbd42861c734d0513L,0x544b6ef495408b60L,0x4526e680d40179beL, + 0x9f984c4140ab740bL,0xbed7baee67a02ab3L,0x09e3446862a9fb2eL } }, + /* 34 << 336 */ + { { 0xdf64ebcf28eedf59L,0x435531be73b5d9f4L,0x1990df01cf35d981L, + 0xa34d4fa9a2cc41b0L,0x9f643bd6b5a10b37L,0x90cae11158a6cd14L }, + { 0x2b0490701943d2f3L,0x2c9f8af4eda3fc20L,0x48c245c5f96e72f3L, + 0xb4505a3a861355deL,0x4dfab1b9be032112L,0x69c1a9195942de24L } }, + /* 35 << 336 */ + { { 0x761c2c356efcc891L,0xd06710d1fa376241L,0xc83a491c8a78b0fcL, + 0x0c0ee8d8af75b3eaL,0xe6d9d92e4532b587L,0xcb3b652d64eba138L }, + { 0x1cc504ca34ff5d2aL,0x207e7443d0eae0baL,0x94ad1676428382b1L, + 0xfcb5909992ec17c5L,0x7f99e1b5ce3b2e48L,0xa8c38c0fac9bc921L } }, + /* 36 << 336 */ + { { 0x5763ff1af4ba4711L,0x6aac1315bfaae662L,0x51b9c30ede4b5505L, + 0x50e63d1891b25d3eL,0x41938349e65ea695L,0x11260360f514dd15L }, + { 0x231f7f574a086eecL,0xa2c3237f55bd9ee1L,0x8afafa043e0705bbL, + 0x44607900e9fc754fL,0x7250929678519ce3L,0xe751c3a74d17708eL } }, + /* 37 << 336 */ + { { 0x0098a3254611d3dbL,0xbee52036dde82f67L,0xec432a62cdd50282L, + 0xae8a144e52f994f2L,0x027e9e60aa5c03fdL,0x1a49ce47821f55f7L }, + { 0x46fbbd6c4d10c0ffL,0xe14c82ff8c461df3L,0x95570f44aef902b8L, + 0xacaa04ec0eb7eb26L,0x3c8c86a8e738570fL,0xb87d47ccb77cc59cL } }, + /* 38 << 336 */ + { { 0x2f4f68377bbf7168L,0xd5b67947f03f7145L,0x2c6ca74d4cecfe22L, + 0x0e559b9f0a7d6fadL,0xdbcd039ff6b37f98L,0xaaf1f6edfa7a3877L }, + { 0x97b779f0f607316fL,0xe2185ccc72b99fd4L,0xd3f696bf2bdfe399L, + 0x20d9baf15e6c403cL,0xe5bbc1cb4c4f1216L,0xd1c0761a428838fcL } }, + /* 39 << 336 */ + { { 0x4f433b8abd08dd65L,0x27849a72773bd3c0L,0x62351b911854502eL, + 0x836580ffca24ce7dL,0xa5c224a39355258aL,0x8d33fb43e65db7f0L }, + { 0xe44d391edf49a825L,0xc28e0d9bd2f5d4bbL,0xf7208342efb61ae9L, + 0x43686b414dbce055L,0x7f7562d01800c062L,0x5031bd7c8b8ace99L } }, + /* 40 << 336 */ + { { 0xc183199375476a4fL,0xa6383a0055fc4367L,0x23a72dea98bf90c4L, + 0x67ee6f451045a947L,0x4e6518836920d0a2L,0x49132c9ac8042a04L }, + { 0xe249e46d5dfa9fc8L,0x6ff9eba1c60d1a11L,0xa4d9362d43490335L, + 0xe8fad79ade504480L,0x519e8d1bac43c951L,0x7e688047952d6f54L } }, + /* 41 << 336 */ + { { 0x135d677342e27f9eL,0xd58b98fb8fcc77e0L,0xf3bb847d7f64928bL, + 0x15ec841663176905L,0x83e75b6a0f755173L,0x4c3eff5c7a24de69L }, + { 0x289e9a45313bf61eL,0x01b15aadeafa2733L,0xae7fafe1d2cf501dL, + 0xd6fba525d5ac0b3eL,0x4bf48be0689bb20aL,0xa591843255bf610eL } }, + /* 42 << 336 */ + { { 0x0f019b64c5f8df0bL,0x112f06a979307310L,0x91dc57276d16102eL, + 0x34070a5be2651248L,0x0b9f35dbd3423044L,0xf29bb4a072b10ed1L }, + { 0x87071a9a07fb6388L,0x4246d532b7dbdb1eL,0x87db3d2285a039c9L, + 0x76620a5d42b030cdL,0xc798e3816a42d8ebL,0xdd97441ac441ef9bL } }, + /* 43 << 336 */ + { { 0xa9b004a0f08592c3L,0x984d17e5d069c54dL,0xc96f2132ccb87e81L, + 0x67fd082f3b1f9eccL,0xcdd0827ac4ff9feeL,0x9d1025070e04b7a6L }, + { 0x4ff3424177c67935L,0x4f2246f58efea5b9L,0x128085b12fbf7615L, + 0x9f111f65174b0575L,0x0b27d8e2f455cba5L,0xda20626b536054eaL } }, + /* 44 << 336 */ + { { 0x4a3df6de3761fa82L,0xb839d6babc56eb6cL,0xe41afc5e13977a26L, + 0x64022937fc0686d5L,0xa5d6dc19e2d681a2L,0x81afab3128f411b0L }, + { 0xc089aff74321a117L,0x32b0ae2657d18f89L,0x650aacd5f66aacd0L, + 0x7b317bf6b8d3f677L,0x2cd5789777ea82dfL,0x935be0f3c74e7509L } }, + /* 45 << 336 */ + { { 0x4387f8f602de9e59L,0x529c06f337589811L,0x6dbaab60bc9f06b4L, + 0x0063bc3db5f181faL,0x7bcb289969b906b3L,0xdca70d1331d1ea3eL }, + { 0xca65e546ee373e94L,0x13cd365c779f415fL,0x4183460e9d71cb08L, + 0x60f312726e35eaf7L,0x3d0c265f14bc5e0eL,0xe7a1b9af39ce618bL } }, + /* 46 << 336 */ + { { 0xc234c892f46aac36L,0x213076ada55983a9L,0x81f96142dcf335a1L, + 0xf21ceb724b22e311L,0xa12d6333dc053e1dL,0xe7808925a930732bL }, + { 0xb5a9eb81b1f1075aL,0xd13739c0f0a3e623L,0xbcd842e9ff2f24d5L, + 0x200cda381b16ff0fL,0x0a85ea521d6a6c54L,0xe1c0dc8756785463L } }, + /* 47 << 336 */ + { { 0x3287c8d39100f769L,0xb349ce8c052e8bcfL,0x5fdb952dd0d3e44bL, + 0x68715110d0639cc4L,0xc9a5fbaac8efc67eL,0x14ebb97da009aec5L }, + { 0xf0684e1ca1423e1eL,0xb282f2f56357fa17L,0xc2e79d3c5af78041L, + 0xe0ca9f4bd7d2ba8bL,0x20629f1e04dd84bfL,0x274ebccc3ee73228L } }, + /* 48 << 336 */ + { { 0xeb05c516156636c2L,0x2f613aba090e93fcL,0xcfd573cd489576f5L, + 0xe6535380535a8d57L,0x13947314671436c4L,0x1172fb0c5f0a122dL }, + { 0xaecc7ec1c12f58f6L,0xfe42f9578e41afd2L,0xdf96f6523d4221aaL, + 0xfef5649f2851996bL,0x46fb9f26d5cfb67eL,0xb047bfc7ef5c4052L } }, + /* 49 << 336 */ + { { 0xeadd123d385f2b36L,0xe3b14829ddf58569L,0xa4fdf0ec47c7e485L, + 0x93c0d8380623ea5fL,0xeb9c0a2c9e2661deL,0x8046fc69e72e0ca6L }, + { 0x6f439e5c7be1c918L,0xcd8fd2f92a9ffcdcL,0x7f134747420e939cL, + 0x8e880ef05ae283f9L,0x502c5c99f780a249L,0x68a529ab94bf9d68L } }, + /* 50 << 336 */ + { { 0x3cf994ed88c9d290L,0x9209f5610bb34d46L,0x8170b567b2bfa21eL, + 0xae87b6f7c62f86d4L,0xac6fc431d71bccebL,0x5f3a62ba83cf2970L }, + { 0x390262d1d943b10aL,0x8fc9a27f28aec573L,0xe59beb203e3069f9L, + 0xf3e7bd365e0812a7L,0xc29c8a433aceffa4L,0x015feecb41c25e2dL } }, + /* 51 << 336 */ + { { 0x5b6a4d6ca8e61f40L,0x35825d762f9a6e70L,0xd48f6d8d346a8b94L, + 0x12bea60889801a40L,0x5182192ad57115f6L,0xb5a8dc6b954c1b47L }, + { 0x084a5c71793b427eL,0xeb66d699f8de2a03L,0x9835b2fb8eb6d905L, + 0xb4229923c79dfe40L,0xa7c8aedddee34c0aL,0x12a00675337b0658L } }, + /* 52 << 336 */ + { { 0x38ca9f61d44aee32L,0xb2cd0f505484905aL,0x23ecb3a4d812e727L, + 0x9be645b874a3ac5dL,0xaa4a1d114bfa93b9L,0x5be5277d147072caL }, + { 0x623a4bd9ba0a6d93L,0x03419661dcf3d9b1L,0x9bffbe8231de1cf4L, + 0xbadfa2ab56a6af06L,0x9103f7256746f09cL,0x0cd5e956344a2688L } }, + /* 53 << 336 */ + { { 0x50a18ab1f40b0edeL,0xf963b76736e01032L,0xba2029b4d4f9a6deL, + 0x8baec9b85a8446b9L,0x7a4107e766fa8a92L,0x06e78bf99f6543d9L }, + { 0xdaa894b3a5043e86L,0x172858a8f4e6fe37L,0xff0265cc0844608dL, + 0x5db1a8f1d5def174L,0xdf9f8a698874fbedL,0xdd2292a977a274d6L } }, + /* 54 << 336 */ + { { 0x46f522196ad8d03dL,0xb63e0eaadaf8b0d3L,0xd667f0a66e29df38L, + 0x6e77432f96ef3b57L,0x78fe0872139ca180L,0x300a0c78d1e4af21L }, + { 0x650f32462148816aL,0x31ef1e883b4301a2L,0xa2222b25f18442fdL, + 0xb26b63066884291fL,0x977b6f7d713d88daL,0x3e8173248cd5f7f7L } }, + /* 55 << 336 */ + { { 0xd5687c9a9684771aL,0x797808e396cf65d4L,0x793d4eb6ea9ee562L, + 0x2359b991fd94defcL,0x4e75cdf03a8959adL,0x7a08566900ce7815L }, + { 0x5c61df5da699fc46L,0x02b62d4868da56d5L,0x8a6972d1eaea27d5L, + 0x727582b3c8e5d04fL,0x0ab2e6c2de87c408L,0xaa9a62e47b9ed157L } }, + /* 56 << 336 */ + { { 0x9c6247d631af03e4L,0xe5a59ad075f9ee90L,0x1da1d64f6ac4b5a6L, + 0xd2fbd169c521ec7dL,0x6d168015dfaa39f7L,0xe9bcf5b59c69d9d7L }, + { 0x3d1d3e6693ae2925L,0xcda60beae4bc73a3L,0xb2456adc954e2f3bL, + 0x5d312fdc02a8fe08L,0x7b37c00e0e497a0cL,0xbd1f3aafc2f8b148L } }, + /* 57 << 336 */ + { { 0x60f3bb27bc00d150L,0x159c5af42448affbL,0x4492b6bd2cfa563dL, + 0x7e58219683c833b8L,0x9f9ebdb20edfafa2L,0x93a7048f31a39a8aL }, + { 0x4172f74d50149d01L,0xff38fceec58b7588L,0x2e71ba9099f25353L, + 0xdf50fb440604e555L,0x7effa7ca8f3b5969L,0x3bbe8d49b836b8bfL } }, + /* 58 << 336 */ + { { 0xc18c375c29d08d49L,0xb04c0c29c1a681bbL,0x0c4acce9e74dd458L, + 0x1d6da95c85c920a1L,0xc67280d285387462L,0xeba99725e7e804adL }, + { 0x08f80e5a8811a138L,0x26f442138f2136e3L,0xf67f157c2d028cc9L, + 0xb436356d14cd7cbaL,0x1c9c610290281895L,0xf67f16ea48598bdbL } }, + /* 59 << 336 */ + { { 0xbf926a077a326266L,0x4045c18bef43cfc6L,0x6fad4cf56ce45553L, + 0x613ad2dc45a9abc8L,0x7b086ace8836eed8L,0x855857c213ad51d7L }, + { 0xa3b19c2d167664adL,0x422c548abbd2c452L,0x8cd3681f85928ef0L, + 0xe969e45c3ed435ecL,0xf76f2cce746c9aacL,0x514df58d1dd90e35L } }, + /* 60 << 336 */ + { { 0x9b66219c4d09cd36L,0x6c6fa570b54f0853L,0x95c268bcf29a8fffL, + 0xc8cf84bf5420c324L,0x5bfc975ebb61617aL,0x935cfe24e78f1bbaL }, + { 0xa6e2afe919d71ea1L,0x8a321e568c9b950eL,0x42dd9e28ec097826L, + 0xf06e600ef391633aL,0x94e5512b46acbe2eL,0xb0bca2cc61cc7a08L } }, + /* 61 << 336 */ + { { 0xcd361103e8b2d41dL,0x2d0d982cab0b5f13L,0x8158129618d55aecL, + 0xf1c28a71579caa03L,0x5ddedfd7e50b83faL,0x932d2c03222105d0L }, + { 0x48fd0ead75ada3f4L,0x29209d988c533a40L,0xc2acc587f2acf0c8L, + 0x05a8703ef689912fL,0x8f28953b9182995aL,0x1cbba2f20fb3eeeaL } }, + /* 62 << 336 */ + { { 0xa1472574180e5eb2L,0xde27569b93fc7b21L,0x3bb956816b9af8aeL, + 0x8a25fc0ee155f89bL,0x8aff018d825126b2L,0x6eda2f31906f0bdcL }, + { 0x19cbbecc4e8fbe4eL,0x04e0a4a40568d248L,0x6de2c002ff07b863L, + 0x6d388447e8d1595dL,0x6a193b70c2cfd10fL,0x00bd826ee6f6bf96L } }, + /* 63 << 336 */ + { { 0x2a0165a40a5b4d1dL,0x49c85ee904f12309L,0xc2d221031ded788dL, + 0x510ccbb3735bd89fL,0x92d2eaebd8eb0e1dL,0x6bda8e346e428c11L }, + { 0x44c01a1d361f7495L,0xddda8e97cc7a95bdL,0x95cbae30524a53baL, + 0x266d7192dacad45bL,0x8a42793f22fa4b99L,0xbb393cb5ed204904L } }, + /* 64 << 336 */ + { { 0x88e7ac8e168d5e60L,0x53abd5696188a98fL,0x3b96d52918be419aL, + 0x7e75e354c057621cL,0xcb1b709f5ce57e59L,0xe78befa2844f2463L }, + { 0x536081993276d4a0L,0x92636ade157f2024L,0x6dd0d348e0411414L, + 0x5b28e9504d73eeaeL,0x08439232690ed85eL,0xdde1a3496da14b58L } }, + /* 0 << 343 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 343 */ + { { 0x6cbd275739ed9ec9L,0x5db68a68fe5d4aa8L,0x177eaa0be4c58c7bL, + 0x603551ef0e488784L,0xc8eba131df916b0fL,0xd0dbceda159732e2L }, + { 0x55acca84b0834afaL,0xdbe98440b59ffbf5L,0x162a2c703bd3b202L, + 0x4c5e5d256ddd8ebaL,0x66e7844a77b1d93dL,0x1292bc0e110b9dcfL } }, + /* 2 << 343 */ + { { 0x1b66faabf9e89beaL,0xc81c5ddc3a441284L,0x1a82f3a0a675f7c8L, + 0x82884a2f30313a71L,0x7ac5d7b058aea9e6L,0x1954f075cd5ff05dL }, + { 0x7c29638d6178d270L,0x6af7f8ba19381929L,0xe85e3c47a17ae3a7L, + 0x91b107c77009e38aL,0xf3b777d8f1f9c52eL,0x5b7b74ff11b688a0L } }, + /* 3 << 343 */ + { { 0xe1e5b76914b87b2aL,0xee187f5d143a4ae1L,0xa9a38728908cb988L, + 0x2027b2ed4443d8daL,0x1c6b4813c0c98675L,0x509ea7d1323bd978L }, + { 0x43b16a587f4dc19eL,0x385f8be812940ae9L,0xa4ed64e57d59acadL, + 0x47e7abed51ca7f14L,0xead594b82bcce6b8L,0xa2bff60cfc03cf06L } }, + /* 4 << 343 */ + { { 0x4ae3d232c0385874L,0x83bda9e6cbf96d2aL,0xba73c769ec62fd6aL, + 0xd586ba7f62a4720cL,0x6497cd140cc1f491L,0x8b012b707b2ac571L }, + { 0xa65eabb6268fd705L,0x8caf100a1431873dL,0x25b31b84231457d7L, + 0xcab62f75901645c5L,0x2377d74db2f7b656L,0x4008277c2d33c95cL } }, + /* 5 << 343 */ + { { 0xa7be70c04bfeb784L,0x4633ddadc222ab44L,0x00e397d30f5924bdL, + 0x5446db3ae25b7b9eL,0x433ea2c4fa1dd048L,0xbb9ae36a1421321aL }, + { 0xf879069dc59fe8f6L,0xe0f2b8b4820bfee2L,0xcc6cf7c49cf239e4L, + 0x0e3545c207dc3122L,0x23b0f48b1d2c737bL,0x1c6b6d9cfc1137d4L } }, + /* 6 << 343 */ + { { 0x10105dfd101d2433L,0x64e009b58ab6d664L,0x122e68324e80fc07L, + 0x3b26e76287dc7da6L,0x7bc183de6d4728cfL,0xebfecf4f8bcdc129L }, + { 0x8b995cec265c66f5L,0x080572d7c4b0e942L,0x612e9e6b4da5b77dL, + 0x8ec048a96caf9161L,0xe3628ee2c7f45eb6L,0x0190b71bd85650e9L } }, + /* 7 << 343 */ + { { 0xccf79a81017fbd3fL,0xa852ca29c875bc66L,0xbb4cd90c0592f8e2L, + 0x2ee786f455b05c79L,0xe1a2b6baf382e6e7L,0xf2d6cf6e6d2e952eL }, + { 0x2f0b534abc9304fcL,0x1d63fd80795629a3L,0x42e70cd9322d8e03L, + 0x8a282cdfb057e36cL,0xd18a0c313ceb177bL,0x270e31569c58b890L } }, + /* 8 << 343 */ + { { 0xaae2f448ed001c43L,0x08ad1d9bcf4be493L,0x3262b2f482c1f372L, + 0x5521febd351a5f7fL,0xf8ec9190916c75a8L,0xf3c258c72728dfb8L }, + { 0x5dd4ff4f8af19574L,0xefddf5795d076b1cL,0x318b5b98ba8b777aL, + 0xd971d426fb7f8409L,0xed1465e8b0fd31dbL,0x80d24d4300f66347L } }, + /* 9 << 343 */ + { { 0xe8263e8012eb6baaL,0xc452c7581dde8c37L,0x5112af2840baa45dL, + 0x949b8a740793703aL,0x8ba78382e60e007eL,0x38cd110412823c99L }, + { 0xdeb0d555f86cf04bL,0xb2f20bfdfd9f6320L,0xff1d399d17c39502L, + 0x1340aedd1bdf0760L,0x36b2b43c88cc0c09L,0x5f3dba7e9ce285edL } }, + /* 10 << 343 */ + { { 0xcea0374a69ca5051L,0x19e060ad5294ae7aL,0xf6ce02361bb01f47L, + 0x2a5b28ba8c328b8bL,0x6991b1d8b253d630L,0x360afd40859455d8L }, + { 0xf5c6e1427c1f5946L,0x1eab83084cc8c391L,0x4eb4032f67e76ecdL, + 0x5bf14aa233898059L,0x0804a7c00e001b76L,0xe3866a93734cd134L } }, + /* 11 << 343 */ + { { 0xbe85177db72e5eadL,0x47c15fad59fd2463L,0x2cf5f07f4bd51f8eL, + 0x82f48288c2898713L,0xdb08aab4c8f753e8L,0x18a1f5c510f58eddL }, + { 0xaeb7bde366d0b94cL,0x04539620079fb6dfL,0x64d1aff2ebe8c4b9L, + 0x08d9ef431a10a101L,0xe326c7ec6c602789L,0xd8b1b3e7f6efc3d1L } }, + /* 12 << 343 */ + { { 0x5ba5288c1ae586a2L,0x044f1fc61b715821L,0xc1a9a997602f3c65L, + 0xc5c7512fe08c0223L,0x48a19c3c367e6f1dL,0xa9f2195dfb241597L }, + { 0x9f674a5fb5ba32a6L,0x275a060f0a312742L,0x5aeb8c4303d6f13eL, + 0x0fed575d917433fbL,0xe4a5ef9a59f53490L,0xa9f86145f315e616L } }, + /* 13 << 343 */ + { { 0x770d01ab2c1deef8L,0xca72f761f61b2a4eL,0xff686a4ceff9ee49L, + 0xd6b338d30d07000aL,0x885b4e8ce1050b10L,0xd6326179b2364b01L }, + { 0xceb2bafc672b298aL,0x7df8941aba628946L,0x9c94004ebc56b115L, + 0xde09cc2d7b12cdd2L,0x9c2dda163833ce43L,0x88da691a6265b59eL } }, + /* 14 << 343 */ + { { 0x7059c58669a03980L,0x91f2dfe4e88e1287L,0x96dcd9318d9633ccL, + 0xb2abc44f37bda148L,0xe31adb3feb8964dcL,0x7b07e015e316876cL }, + { 0x31732880ababd240L,0x5c37a667e95854a1L,0xb5b334c91d6f69adL, + 0xe613e5622c34e118L,0x8bbdbf5c5f5984edL,0x82ecfd95cf4f63a1L } }, + /* 15 << 343 */ + { { 0x813caa72ade4e3bfL,0x29055be8600c93c4L,0xcb346967e6e4ec1bL, + 0x39c1152d50ce992fL,0x4682c20e5ce62852L,0x04e9dcb7f4e45ed4L }, + { 0xda75355d7c0fa5bdL,0xe80f29b078949d91L,0x6214610130fb9e33L, + 0xe70cda8f325eececL,0x49217f74efca3e14L,0xd3c890b36bd7246aL } }, + /* 16 << 343 */ + { { 0x315ad7a47e5a59f4L,0x1c615bfc543c8b00L,0xe12f97a8baa56473L, + 0xf263db4446edcfcbL,0x47cf91d53c1a968eL,0x1a1165b4c15db875L }, + { 0x5d35e53a3479616aL,0x649f87b45c59958fL,0x5d3d11ea246da3d3L, + 0xc1ddfcc653f06820L,0x8169d7116610c00fL,0x15f16ba54bddc8c7L } }, + /* 17 << 343 */ + { { 0x307b040d9977713eL,0xc03f7787dee9e016L,0x761a5d03e12c354fL, + 0x8fa1a4141cc88904L,0x2e079008b7675e71L,0x649c789591d68d60L }, + { 0x63467e93c98f1c9eL,0x81931ac7fcc52703L,0x2060c89538e59af3L, + 0x8c12e002a87024c4L,0xfc881e69b3b8496aL,0x2b4e482e1e827081L } }, + /* 18 << 343 */ + { { 0xf80ed61a30fa7e86L,0xf2e5f324a15ec5d9L,0x139ca085ecba2d64L, + 0xd164ee5ff3f5cfd1L,0x758c0008e5cc3cc5L,0xd180c463ce8fa1f9L }, + { 0xe5dd27054adc6e61L,0x061e0c3c592c39e5L,0xec5a8d4a4e437781L, + 0x9e4c6f461e6d4540L,0x33ab232e2526e6eeL,0x3c551685ea282d9cL } }, + /* 19 << 343 */ + { { 0x59507a2162ce1459L,0x88b465d1c6a2cb30L,0xa5ef8b2b5c8ef7d4L, + 0x73145f4c4dc9a457L,0xabad3390d19186f2L,0x7036b424f9b78a7aL }, + { 0xf76f51bb16e04046L,0xecd1ece92b2b71efL,0xda8d82011900f2b9L, + 0xc2d3291b268d1bfbL,0xa6c1c79a2d176459L,0xb27e5d5885ee1b7bL } }, + /* 20 << 343 */ + { { 0xcf19fb2a1e548ef0L,0x8bb6dfa0cc694171L,0xeb1668ca5c5e390fL, + 0xf5a3485be1975263L,0x4edfc596442cc850L,0x9901f447f9627d74L }, + { 0x3a6b85c984d0413aL,0x1466366167de639cL,0x9fc9fdcf11705bbbL, + 0x6d066e2bbff2cf80L,0x38dedc2fdc3026fdL,0xad533a981b828538L } }, + /* 21 << 343 */ + { { 0xa7d51d862222dcb3L,0x52e2531cd1a6c525L,0x742b1234532126d8L, + 0x226043f24e9e77acL,0x02f270afb3a75b2bL,0x7ede5714d4a8dc0aL }, + { 0x24699e16b34fd97dL,0x4e5d785e8d417ad1L,0x273f5dd1ec307ecdL, + 0x742373863186955aL,0xf46805fde6afd38dL,0xae100ba424562906L } }, + /* 22 << 343 */ + { { 0xed9f434e5216636cL,0x242bd09bc5c1668fL,0x8bb747bd804f3d6eL, + 0xd66d8753c7c83dd2L,0xa71016c2584540b8L,0xd8b16210fdd41a90L }, + { 0x5eb5947e1b65be60L,0x1bf995e7616dbdc2L,0x71b7099abb7dbdd8L, + 0x53650d29079eec24L,0x6bdd1b0e8ebd86c8L,0x0a9658ed9a31624aL } }, + /* 23 << 343 */ + { { 0x3be2ce89b8cf4d55L,0xf9b3c501822cdcd9L,0x0cc8423010e12f3aL, + 0xee09031a3c580ec7L,0xf4c256a812f4b48bL,0x71a8323104018d0cL }, + { 0x69ad6d7babfcf13fL,0xfa79b457af658743L,0x249f32816001af58L, + 0x158430fcea127a64L,0x25a3e4549a9be713L,0x68ba3f0fcc6b5bb5L } }, + /* 24 << 343 */ + { { 0x6c75bc93b7bfa29eL,0xf86f22b218ef6d69L,0x90ce6a1536dcadf2L, + 0xf11f711c7ce50921L,0x0739ceda38a479e3L,0x840b825e6ec3dbc6L }, + { 0x7c36c0a59fa23481L,0xceb61fd170cb186dL,0xac6f7d3c26e4754dL, + 0x4076d3b5f317b385L,0x52f1bd723fd9e9c7L,0x6649d8b6bf316043L } }, + /* 25 << 343 */ + { { 0x5f03dcdcceb1e25cL,0xafff6561d50ff864L,0x17208b6f3a6bb787L, + 0x61d96c978e15abf2L,0xb1beb427991107b1L,0x436328475008aa3fL }, + { 0x8a326eeb3595febdL,0xa8e5a037ec60dc0dL,0x762ebd2a3159f062L, + 0x8ea005adbd1b0bd5L,0xd4d863cf696d4121L,0x2a07a637eacc9b9eL } }, + /* 26 << 343 */ + { { 0xf352e28b54a8ffaaL,0xa8317f089ce68b6eL,0x7deb148770cad820L, + 0x2411b382b2c3579dL,0x20b21ed214d36e66L,0xe7331bec353b9ff5L }, + { 0x5692636840dff0b3L,0x13356f7b646eff07L,0x1e6e6e4508c64091L, + 0x913b83f2ea0b920eL,0xb69e5f839f713aa1L,0x8e59d3794632a60dL } }, + /* 27 << 343 */ + { { 0x3594c0d3cdefc3dfL,0x9d850e2fd21cf9e7L,0x245322944e38263bL, + 0x597964610e43acb7L,0x13fad563bca9408aL,0xe52983dba985390cL }, + { 0x9c5e71e08c000a9dL,0xde6b0b2f800949e2L,0xc58032d131d94108L, + 0x36cd4099b31811e6L,0xa8d9bdeb3981d619L,0x06f644e03d4760c2L } }, + /* 28 << 343 */ + { { 0xdc2870f8243cfbd5L,0x000b71b31ab496f3L,0x53511a3f708f4507L, + 0xbd7bd0381949d835L,0x723a007d938f4db6L,0x5bc8679e2d04e9fdL }, + { 0x51ca5fd176ec7fc4L,0x86c4205c988f354eL,0x9042e76b2a0a4a90L, + 0x368f52a84ad44d2dL,0xddc2cab8912edfb7L,0xde74ccf5cde80199L } }, + /* 29 << 343 */ + { { 0x91b31fcbcaa3f1d2L,0xb8a29af1bcc99f53L,0xc5842b2695662f80L, + 0x13954262a4b4b396L,0xc1fac956a6acfdffL,0xbe37fa4dcf60b88bL }, + { 0xc7715493dffff3deL,0x06dfaceda1274350L,0x9dfcaffd7460fa94L, + 0x5f1d3a351e9c317dL,0x2fbf393d377b84ceL,0xb4d9bc8404b83635L } }, + /* 30 << 343 */ + { { 0x29871ce22855a74eL,0x5418f0dc98696474L,0xd8bc07d6b90d0498L, + 0x391012a79fdc0ea2L,0x271396949b09f60aL,0xa0a43dbf3371f0d7L }, + { 0xab5849422af8d992L,0x64cbd121409eb3faL,0xd36faf01766864fcL, + 0x69189faea2a83417L,0x3c24d85e3733b772L,0x125a915d2ee497adL } }, + /* 31 << 343 */ + { { 0xa8f9eb2abab3fa8cL,0x484584f654ab1e16L,0xee74e5aab21b34edL, + 0x3ce626ff4eb689f0L,0xd757f22b0006e5bcL,0x611505d024a25e65L }, + { 0x212df14c46382659L,0xd17898d78c73da0aL,0x5604a93e51421c2cL, + 0x76147f7603a580a1L,0x325b5c8ae5c34d09L,0x6ff28848db857152L } }, + /* 32 << 343 */ + { { 0x8002f4583e455a61L,0xafbafd375bea205aL,0xa8ced112fb93f735L, + 0x27cb6292196e3084L,0x72395bdd77e8c744L,0x02e018d8ee71f5ffL }, + { 0x7cfc14d9c1337a1dL,0x94e14c0ad7b4d86eL,0x66e50129d213738eL, + 0x7a905d91bc0b5ea3L,0x92cb630afca06700L,0x65e06d5cbf3a0821L } }, + /* 33 << 343 */ + { { 0x769ff9191e1cde66L,0x6ef257d1944a8786L,0x881437da4f75233eL, + 0x15266f3768665eafL,0x21fcccafc1777505L,0xe9513e1ab7fea0ddL }, + { 0x67806e9c53c8a735L,0x24be9a769b11ae2eL,0x928c1455045d2065L, + 0xea0395b53557f62eL,0x910d7cb4c7d3a450L,0xe849c853c634443dL } }, + /* 34 << 343 */ + { { 0x76c6e48d3b476f69L,0x28195cdffe694ee4L,0xa3a9a99e2d3aacc9L, + 0x0f68fe36b7f320d8L,0xca84a6c9889ce762L,0xc1eafac94901907dL }, + { 0xa28b9916208c9770L,0x6846e639f8403e57L,0x12fdf9fa1d179e3eL, + 0xb81e47c843d046dbL,0x700ad19468c14491L,0x136395cebbac51d7L } }, + /* 35 << 343 */ + { { 0x7452dfd4f775003bL,0xb38a2031f1a4765dL,0xef36c513a2888c68L, + 0x2039b168a2339fd3L,0xf74c24be2cc498e9L,0xbeeaca157b622e31L }, + { 0xda72e5a005f2fb8fL,0xab4a98f0568d5811L,0x231aa495fcb15e1eL, + 0xf981bd7f537023f1L,0x29d6eb2db367e5fbL,0x15247194b8cd452dL } }, + /* 36 << 343 */ + { { 0xa81e4a4e55c2369dL,0x394de01b60a0f544L,0x22acfd07a8906e17L, + 0xf59b37a6cc9bc4d0L,0xdd16a22c7ffec12fL,0x07decc2ad5976455L }, + { 0xc5019463abe1d122L,0x2bf0ac0ce318c92cL,0xfa50280ab2bfc47bL, + 0x53354fc5c7cf8bffL,0xaea1d293e20ca341L,0xec25ecda8b626244L } }, + /* 37 << 343 */ + { { 0x05c6f1c99a2f572bL,0xf13f8c7747987918L,0xccb406d74101fdffL, + 0x93cea27bee1abcf4L,0x32703ada8f5adca8L,0xceaecb5f76313a1eL }, + { 0xf1c558980b9620cfL,0x942c28b51046c388L,0xbed4e9dc5a07cf8cL, + 0x423b695a6c734b85L,0x1ce0a2392ac87737L,0x40f126ac4d1cc7d8L } }, + /* 38 << 343 */ + { { 0x63e3bb09ad9e132dL,0xaa2880c5c9e84778L,0x23de89ea06049834L, + 0x442d1df3554e23bbL,0x87214f9f08c5f124L,0x305d967a6beb4996L }, + { 0x01676f804409f827L,0x16992f73a50147f9L,0x77ee56796081b38aL, + 0x8c75d293290afd9bL,0xf9578bca813f0aceL,0x395212dd0e786ed6L } }, + /* 39 << 343 */ + { { 0x63475e65c21b0f48L,0x114f9af5326c2c63L,0xa897bc01310f768aL, + 0xcaf47a8fc1bf3f5aL,0xc023bb3718cb887aL,0x3572f633685652a2L }, + { 0x2dc4ea0d7523287cL,0xafd60b92a121a141L,0xb6b4bf6e085ca490L, + 0xf599f8f2e5351ecbL,0xe38c8eacddba3d60L,0x2540585f5be9e748L } }, + /* 40 << 343 */ + { { 0x313b66cafd8ba33eL,0x10bdb130fabe27ddL,0x1181334c125e2b8cL, + 0x0f4f198fdb6f94baL,0xf7000076ac3f5de9L,0x1a78813d9d6402aeL }, + { 0x3427f75dc8a9e758L,0xcdac8b34b01f791fL,0x922c36d12a9ebaf5L, + 0x195ea05fb0487cc4L,0xe33de901a808baecL,0x15e1d5ac57291d89L } }, + /* 41 << 343 */ + { { 0xfe52cd9cfdc7e2deL,0x3947e578da6dccf1L,0x0548d4b5738751e7L, + 0xc73fc23f4b52a5ffL,0xf38eb8ff1b066accL,0xe9a40d37a27b40f5L }, + { 0x723b0752a264ad77L,0xe5d0c4efdea83bf8L,0xf7301e3fafad27a0L, + 0x336b0d86298d09b3L,0x462766bdb2ef2fb7L,0xa5311241141a7607L } }, + /* 42 << 343 */ + { { 0x10adb987ee1f44a1L,0xd6ebd1c3e51c0152L,0x0cf1303f4dd3b9eaL, + 0xd06351b837a33a3aL,0xb5ce1d941cff1f0fL,0x326b3e055476e2bcL }, + { 0x90f76b5d3426b8ddL,0x77497380648042f1L,0x48684604f9f83902L, + 0x00275191180f197aL,0x36fd84ecde7ce932L,0x52b428e65391a268L } }, + /* 43 << 343 */ + { { 0xd2c1ccb0695c2851L,0xd722b84ff1c78f17L,0xaaa53d26fe52f2a4L, + 0x3057f4ed24742143L,0x951332a4a2aea258L,0xe5e4db6091096878L }, + { 0x71db9e48f0b9ef38L,0x7e4b25c1ac542c26L,0xb7250394dd021df5L, + 0xcdcc6118ee48e711L,0xbc324af1fcdd5db9L,0x71a664ef3e6de57fL } }, + /* 44 << 343 */ + { { 0x4e2a05c1c21cdd1fL,0x8a232097dd46e76aL,0x8b55313cd871b1d6L, + 0x976ce5f6af396bc4L,0xeb91527dafd381b1L,0x6cfd449014455ee2L }, + { 0x8723be9e1f274d1eL,0x1c63fd011999fa9fL,0x5f1726258049b6f8L, + 0xe18a3ecd99a51b4dL,0x329fc2c1b13d4e65L,0x94da252b0f18f300L } }, + /* 45 << 343 */ + { { 0x583adeb8b893316aL,0x69dce1efee5122deL,0xc5cacdf319b77627L, + 0x061fedee5e8aedd8L,0xd53fce220257dce1L,0x0e4124bdc781e069L }, + { 0xf097c697d44ed517L,0x7704e33e9a4e9019L,0xac245dc23e0088dfL, + 0x70e1176bb76102a3L,0x55261ab235e4dcaeL,0xc2ba59230ede3501L } }, + /* 46 << 343 */ + { { 0x6edf35f3af073b6dL,0x7ab4118107376eb0L,0x4ef3e65be7ff1c9aL, + 0x654ea359d2ac6d70L,0x2b41a7f67ffcd91fL,0xe5da0511e0a60e8cL }, + { 0x97fefd9756701b93L,0x7a4a827dd34afe15L,0x8bd6c2299090536cL, + 0x110156f217e510a0L,0xce62a26ec801ca6aL,0xa786e9b05522b64aL } }, + /* 47 << 343 */ + { { 0x3c73c2868f02f70bL,0x744a580d0eeca325L,0x58b7ca1733534669L, + 0xd7d17d77800b0270L,0x864e3509538b116aL,0xc7eda5dce4797818L }, + { 0xd6c00fbaf741f023L,0x718ed11131d022bcL,0x4586baf2f2ce39efL, + 0x1095729dcd9a09f8L,0xf5ff3f2d7652f5ddL,0x29d95a09dbb72722L } }, + /* 48 << 343 */ + { { 0x7b151b98e28fd10dL,0x8fc01ce81dd884cfL,0x1f0ffb5098d56c2cL, + 0xf9df1fa2b084606dL,0xf86232bfdc7d2008L,0xeae5cb8fd8751699L }, + { 0x70f0229883ed54fdL,0xb575283a86087697L,0xad2191350302e2c3L, + 0x1c09a0d6c4b57e01L,0x0f65e1e1c541b9fbL,0x85493d9bf4fe76c0L } }, + /* 49 << 343 */ + { { 0xecf595d6bc19db89L,0x32cdf31bd607e09bL,0xfaf93c636217e9faL, + 0xa9a1619884d37c72L,0xa2688a33bd929e8eL,0x2ce3442e2842b31bL }, + { 0x906ac09ab37184daL,0x93a1a54492587ea0L,0x1acfab1ec5b4ce7eL, + 0xd4788cac7131e80bL,0xb463d67bc8cf0e18L,0xa754ffb81f24067fL } }, + /* 50 << 343 */ + { { 0x634f8d6db04ea518L,0xe8c424b4c60108a7L,0x3553b6d11ef6f4bdL, + 0x1fe850dfbc0a8e1cL,0xa077055473a66e4aL,0x5417bd50da985b55L }, + { 0x3f99edcaed53259aL,0xd243f2d1b3d5ae6cL,0x70f404b8cb49e74eL, + 0xf6893edc51fec8f0L,0x3f3ac23871521335L,0x127c055436e39048L } }, + /* 51 << 343 */ + { { 0x459a96595ab6a5b5L,0x14ec172bb5ac2238L,0xe556f7061642ba57L, + 0xe18d92d2da35bad6L,0xe64f9bcdd5805c1fL,0xabb4e0243b297094L }, + { 0x95429e14b8b876f3L,0x27961a7d9c04bad0L,0x81c74cf57fa32b6aL, + 0xb035259ebb0f1f24L,0x828c42da2e773f8bL,0x06c996366ea73c24L } }, + /* 52 << 343 */ + { { 0x353718ce191c21ccL,0x08e6edf64ad6bd18L,0xc2bb0d6e4dc5b572L, + 0x328e19df88193daaL,0xccc9f6ab7211c958L,0x377d99ef58aae5c5L }, + { 0x40e2ecc91c823442L,0x036d6d528b0d36abL,0x2fe0cd7eda4d0ad3L, + 0xb8fc3c7ffc8af791L,0xdb7e44a42b201b20L,0xa5176004ebcf527dL } }, + /* 53 << 343 */ + { { 0x24d19ca6fed20bb6L,0x0c02db9841d634aeL,0xfb55998930310b8fL, + 0xf9d0818506c00c8bL,0x2b9983fb4742362cL,0x16ae9bfbdce1b6f3L }, + { 0x679057e6a161a419L,0xe1e80fe04db28bbaL,0x2ca0c869f06c9a98L, + 0x7b80c43bc448ffa4L,0x100f205cb7ef73f7L,0x29565a93a938bea7L } }, + /* 54 << 343 */ + { { 0x4d00c613e1e7a831L,0xc90021dc56d9ddf2L,0xbb80b8385286ccccL, + 0x156b05b771f5f09dL,0x120f47f47bc921f7L,0x6ea1715f8a65c50aL }, + { 0xa070c9f695aa8348L,0x96120fe273171f56L,0x10c7d592ebc69e4eL, + 0x73f6ba27c1c7ef52L,0x10f5b9cef8bb536dL,0x8bc82b225ce0220eL } }, + /* 55 << 343 */ + { { 0xac25749af4f3fa3bL,0x2376bcd76f50e4a0L,0x9c68fd1028b2332dL, + 0x130ed4d12130b66bL,0x91842d58038dfc9fL,0x4111e4cbc401a53dL }, + { 0x85532deafb5d9b16L,0x0c5657503025e3b1L,0x1340aa49b6cc0c31L, + 0x1cfdd7d68b7f71a0L,0xee911d7e8b6e548fL,0xcddf07f021456ebdL } }, + /* 56 << 343 */ + { { 0xe19b7576fa5256d2L,0x418d5425db3f8bfdL,0x00424869951a1719L, + 0x2383c7a8533b69b0L,0x166a38e2e67a86fdL,0xa6baa01c5876c435L }, + { 0x574ddc4584a208f5L,0x8cee30b826b18dbbL,0xeced99c1e9f6b30dL, + 0xb638d88da7d34beaL,0xa4836806069adedfL,0x62beb7ee7a07c593L } }, + /* 57 << 343 */ + { { 0xffc89d6de16d63b2L,0x4da3b04f5df40d2fL,0x3437da2ab48706d8L, + 0xc35290a1d677df03L,0xe54fc6567c5b6c8aL,0x84f052ff2c77314eL }, + { 0x59c33a99d968b4eeL,0x2424c5d0facce444L,0x022d7bfbf505307dL, + 0x5372518d00c142ffL,0xcc82d21aeefa787aL,0x3517f3c0473ef630L } }, + /* 58 << 343 */ + { { 0xaf576c307a8a437cL,0x15852131de3f2cc9L,0x96bbff4371759da5L, + 0x106934ec66f5257dL,0x712e7d0ba9cedae6L,0x5b0b876ddabf131bL }, + { 0x1605f3a8b741f94fL,0xe5d961c109305b04L,0x3fb97996346266c6L, + 0xaf4eafc0b3ec7458L,0x0aefa01abcd90b0cL,0x2b7723e3505ea305L } }, + /* 59 << 343 */ + { { 0xe5c6f37b43d12de3L,0xdc34fdad642baf26L,0x89d716d647268e1bL, + 0x50047b391df8d657L,0x40da6352c64470a7L,0x406e3bc97879824eL }, + { 0x9677b4c38b9ecc36L,0xc82bf16fd246788cL,0xbc9fa99cef5dda3dL, + 0x3050febf0e7b676aL,0xfbb1301a53e448afL,0x3239f20267c84d67L } }, + /* 60 << 343 */ + { { 0x5093950b724fb94dL,0x107822718117ff50L,0xdc9e34b59f5961d7L, + 0xfaa2fc012351a33eL,0xb9e0f1d9d5fc462eL,0x276a5b3bdd9c6914L }, + { 0xe6136d1775365ca5L,0x228b77e2a91eed68L,0x5cd6a269411e4770L, + 0xd8857b0e17590390L,0xe7094f3aa0d45fafL,0xe52d11dcf40693e4L } }, + /* 61 << 343 */ + { { 0xc873fdf565a0d2bbL,0x848244dbaa42c6cbL,0xa5d2d766ac50ba78L, + 0xc650cf4343f38ad7L,0x901cf122ea895d06L,0x3ec1b583cbf46321L }, + { 0x863dce6193c3db94L,0x902459202445bb4fL,0xae716052673385dbL, + 0x9266b0bfff830253L,0xd201095844375610L,0x9e008b9712cf8d71L } }, + /* 62 << 343 */ + { { 0x2b1b2a551448e73bL,0xa8486146b5f97da2L,0xcf24d8636c848202L, + 0xa3d6431c5e483407L,0x47a33db852edb78bL,0xb09256a37dad3826L }, + { 0x740222a74dfa2b26L,0x23f43bec2a8ebe04L,0x4081e512a8072f18L, + 0xe53f0d05751ad7e8L,0x100d0a17332361ecL,0x8a2122e9e0c3a152L } }, + /* 63 << 343 */ + { { 0x28be8affe7e6417aL,0x4e18b452d6a30763L,0x73ae410310d0d5f2L, + 0x5151fe80003625caL,0x45ebb636ba7a91ccL,0x50f4b49d994e7e31L }, + { 0x02eaeaa93ebac455L,0x7632c7dac830fb1cL,0x06fe1dde3bb0d765L, + 0x0d2f7623a6789d20L,0xabba46de01a43e9dL,0x2e822e08f27917f9L } }, + /* 64 << 343 */ + { { 0xe96c4aebe5f5b545L,0x10a85a002d4c43b0L,0xf86ad2f632f9151dL, + 0x05daf874302b99e2L,0x4299dbfa14fd3171L,0x27cbedd6812cfc62L }, + { 0x42e61536b8772164L,0x52eecef76a5423efL,0xc34c6c70548fffa3L, + 0x1fbed7777b6db825L,0x850bded44ef2989eL,0x3b8a542c815463eeL } }, + /* 0 << 350 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 350 */ + { { 0x9decf2173079fe2fL,0xc32ec5707c817f6dL,0xd5649ce8aeb36b92L, + 0xab9f77d158fb4dc8L,0x66b11fb6b52d60cfL,0xe217941deaaa4619L }, + { 0xf3522a9a1607c412L,0xea2eba4fc2a3d8c9L,0x267997c625e38722L, + 0xed5047b72d4595eeL,0xaaa41e5f55e5456cL,0x891e3d1278cfc6feL } }, + /* 2 << 350 */ + { { 0xa438634ed7357a51L,0x918f14cd18c04d59L,0x2ab4dedfac40dd56L, + 0x758e95ee4956a5deL,0xfc11e3945113f84dL,0x6d71b6736059f16cL }, + { 0xfd8e2236fb357c3fL,0xd7c8681232dca873L,0x02aeb1538ea13b44L, + 0xde1275d3013d3827L,0x470a7b7e659ca201L,0x862c83c55c77b351L } }, + /* 3 << 350 */ + { { 0xfc9b800f05084cfbL,0x1c4d4510496f23fcL,0xfea0003cc1d08465L, + 0xf0281da09af48a41L,0xa5c0d97144d32eedL,0x2613b73e023a2e31L }, + { 0x455013c87dc8ac1aL,0x581b13195958b3daL,0xd293f2f22290aaeaL, + 0xa068256496f6223bL,0x38fd18fa69410ef6L,0x74eaf35f2b2cf629L } }, + /* 4 << 350 */ + { { 0x281f6e58c7ff5b50L,0xbc67791ecf9cd114L,0xe29fa41afd89abd8L, + 0xfcb0b0b07984feefL,0x0b0928a6d9d20a64L,0x2fd385c46979ccd5L }, + { 0xce9c34c81fbe72e4L,0x69364344aad0135fL,0xd464635250946a5bL, + 0xb09a97c6f39f53b9L,0x1d47bc20dcbc8b64L,0xcda5c7bdd458b0d6L } }, + /* 5 << 350 */ + { { 0xad5b8c2887eff3b3L,0xa8a3917d9937833aL,0xbafdc493200c3b49L, + 0x9e27aac5972c6fbfL,0xfd292bb20518c97dL,0xa62126db33515a63L }, + { 0x9892a8bb1bcfc875L,0x93b066b7e0b674d1L,0xcde9b0087fd3d080L, + 0x1e285a8859401ae8L,0x4679e32982cfea96L,0x52406ea023e615d3L } }, + /* 6 << 350 */ + { { 0x27de61138b6e9462L,0xb8ade1dc473464bfL,0x911ad49394dacc08L, + 0xd036f28e44252cb1L,0x3865abf6d13dc20dL,0xcea487cdd528f0baL }, + { 0x14d77eaf4fc290feL,0x5106533bc5084101L,0x11001dc7cda9eccdL, + 0xb79ad4bc49fc4a78L,0x4f6369f54567f8a9L,0x64050aa2df7ab817L } }, + /* 7 << 350 */ + { { 0xffe057aade07f615L,0xf3f91b55342700bdL,0x294761e127a839f9L, + 0x6411a2b480eafe1cL,0x4900eb120737b80aL,0xa1134d10bb73264cL }, + { 0x0ebfad730ddbf7f1L,0x57bbe692cd1f73ecL,0x675931fca20f8944L, + 0x1950eefffad2ad19L,0x60d304029cdf88a0L,0x121af89e33fd2c6eL } }, + /* 8 << 350 */ + { { 0x763e3664295c4db2L,0x632fd676dbbaa92dL,0x62ab11a8c66b40e9L, + 0x06244698f384b708L,0xe7cdf3bd69197876L,0x9cc79c48064f8837L }, + { 0x95900a229486589eL,0x7953f6e72ff01639L,0x3f65fbbddd3e6e46L, + 0x84f52e06baa2e2a0L,0x1dc462a8e3852824L,0x9be69c3f7e4c032cL } }, + /* 9 << 350 */ + { { 0xa40afc3670977e01L,0x965f110da6c3b289L,0xc4952f87805a8491L, + 0xb36804b80b65e2d3L,0xd3f6f5ace8cf2b2bL,0x0f37a79da4b71938L }, + { 0xb2f810d9489ef671L,0x1feae0262df23cd8L,0x7412eee321a14e4fL, + 0x1458b8ad179d51faL,0x2156a90ee201509cL,0x39f29fca72605867L } }, + /* 10 << 350 */ + { { 0x231f70adb2e066e3L,0xf09db880bb477a19L,0xdfa0e503907e5c63L, + 0x12fe09f4f97022adL,0xdbf06f3620bce7ddL,0x0140e197f1371cbaL }, + { 0x917b6da464b0b4b0L,0x9a6f4d9b20fe3320L,0x0981d60ed66bdf87L, + 0xb430e4e062d3487cL,0xc3440fb934dc4a94L,0xe7972dda09a5e3c9L } }, + /* 11 << 350 */ + { { 0x29d6394093f47052L,0xadf04e70847e5937L,0xa0ef4fee731bab6fL, + 0x21de31956ee7d7bdL,0x99af4a8dbd716777L,0x9e15c983df4c569eL }, + { 0x2ec7bc0ce94401eaL,0xda1835ad85727722L,0x2b5862ce5dad81daL, + 0xb2be508188dddc2eL,0xa02482101414286bL,0xc52c436d8ea33f3fL } }, + /* 12 << 350 */ + { { 0xcc580ea73b24e776L,0x0f3a8b189d721d6eL,0x8665604fb23480cfL, + 0x95787cba34414689L,0x425d7c6f4d10a945L,0xb5ec2626b2f1cc78L }, + { 0x55da88858658de6bL,0xb50919d1e9aba03eL,0xc64881d7d99e417eL, + 0x1eeba5aabf28fba2L,0x20feb7b3504eff80L,0x9f5f9db650debfb7L } }, + /* 13 << 350 */ + { { 0x4eb94584230923dbL,0xba8611287b3a6929L,0x5aa7faa3ab1d6b31L, + 0x95c1e23916ae0966L,0x98674fd3a2fe2297L,0xa8da0ee53c42d488L }, + { 0x103cabace0740db0L,0xf0b860d45bf16882L,0x03cb0cdc289e48ceL, + 0x3c15d3759e52c7d5L,0x524f731998103ca2L,0x828ed65cc609ffebL } }, + /* 14 << 350 */ + { { 0x518f231b83dfb993L,0x4b0987db37c0826cL,0x0c34961cd5177eadL, + 0x9d882d3e452c92daL,0xbfeaf5588765bcedL,0x83957b62b9962295L }, + { 0x2d1d01757bb084cfL,0x04c4cfcde8cffcfcL,0x2f35e33d8d4536c1L, + 0xbebb31cbd83124cfL,0xe342bed2abb29019L,0x2af0fcde2692a0d3L } }, + /* 15 << 350 */ + { { 0xece5d865c7e3b29fL,0xe58106a4622839ddL,0xf5272d43f2969d76L, + 0x90c72c1b2a1a240fL,0x1e2aa0acaf15e14fL,0xfa2f1c7bf1b6b5a0L }, + { 0xfb5d343d880224a5L,0x47b88a84f91881c5L,0x140f5ee9dd142fe7L, + 0x4e76982e24b37c44L,0x6aaf61e9578b482bL,0x01950e22765bc4e2L } }, + /* 16 << 350 */ + { { 0x20ebf79ce8a2e8f0L,0xec040d0daca418a2L,0x016c07e78d630d2aL, + 0x20021d57fa605dcbL,0x6190f3e942d04705L,0x4e000df58974b7e6L }, + { 0x6710da6c5abcedacL,0xf31aa4965f95d37cL,0x192c4b8ba5830899L, + 0x171ab8c4ea7dbcddL,0x715f60818cdf1097L,0x0e0135bf205d10edL } }, + /* 17 << 350 */ + { { 0x070fbbe1687645c4L,0x4dd859c8c7e0261eL,0x749fa1e9fad54b60L, + 0xb35942f483cdc91fL,0xcef26d0018eeb83cL,0x4dddd5787462064fL }, + { 0x0420ed6e703e8740L,0x9087d805c180c7d3L,0x93807412828424f2L, + 0x8bcea69a6dcae236L,0x22aed9a2d1973c78L,0xe3d0f6f83328d690L } }, + /* 18 << 350 */ + { { 0x5ce5bc6da85a13acL,0x868f385c7f1dd71bL,0x15aa63a420c376c6L, + 0x7802fc9e749127dcL,0xfad59f8e67a98935L,0x6bc97b1d60c0fdf3L }, + { 0xd24caa7ebce87ee6L,0x8aa08bc27ba511f8L,0xe5ba94f47ba61c1cL, + 0x9fe9c343364d2d75L,0x8ee0468161273932L,0xab2f0dbe5e8c4861L } }, + /* 19 << 350 */ + { { 0x13239c0a8254ded6L,0x594182e61762f9cdL,0x6326369d480efa21L, + 0x7fee5afd33101382L,0x9e1ea59c4688bc0bL,0x7a3b1b8eae19c17aL }, + { 0xa8f8f8e5777aedf3L,0xe2d018bfc6bbdeacL,0x3625b03b54328db4L, + 0xda7540c8711ab8caL,0x7faa19fc46930a99L,0x61a5d1845b59a973L } }, + /* 20 << 350 */ + { { 0x4a6226f9f7092423L,0xfe6b7a6dec945231L,0xb44e2e60a1193cabL, + 0x2ce6393543dda270L,0x1a9e8a2138d64738L,0x863d151a9d843675L }, + { 0x98a1222ee2b14443L,0xbf8b32712826846fL,0x80475be555508801L, + 0xc39ccd917b38f064L,0xea31304de8e249f5L,0xa3b6891b4d42db74L } }, + /* 21 << 350 */ + { { 0xc0f1627a147e0f32L,0x59fb7f2f5e8822d8L,0x21d8be6371097441L, + 0xa6169f1b855543f5L,0x188c420645102ae3L,0x4c20a136131b674fL }, + { 0x05487c4d15999699L,0x8a82a130e6ba5542L,0x93a2119519ec0de9L, + 0x634d644cc8d0538aL,0xa90c5eeb3b6bbd60L,0xd59105125e4db926L } }, + /* 22 << 350 */ + { { 0x5140a7172119e821L,0xe5a2ca8cbc370a14L,0x0c17ad48a6db3398L, + 0xd7094545ed6fc82aL,0xcf32984dedb976d1L,0xcf04ac16cdf83a9bL }, + { 0x9bbea16b49775502L,0xb4855286452a6f35L,0x45cbc3b7a86f445dL, + 0x5972ec64763f5990L,0x14d0b9c0b780b2f0L,0xb120273456e707feL } }, + /* 23 << 350 */ + { { 0xbf6b76e1e41c43c6L,0x64ea1824db033acdL,0x7fc0399987c9406cL, + 0x9427585a51b371d3L,0x464f3559c9705e0aL,0x6639797ac8cb6ff6L }, + { 0x5104a72e842fbf01L,0x7cabb009fea7af74L,0xe42aa69b19a1db1cL, + 0xca9599a3a6a7ab69L,0xf31e4aaa1a70d770L,0x0fcc7f1b8a5ef098L } }, + /* 24 << 350 */ + { { 0x39a689bc281548baL,0x11aacfca138eabbeL,0xcf33108a8d29457bL, + 0x312612e014ed4b4dL,0xcbb21f345115625fL,0x4e7217de303a363bL }, + { 0xaeb0c8c0d137f67bL,0x4ff84a937bf78dfeL,0x7a022604683b37dcL, + 0xfa4ced77862b0847L,0x5a49bdc136d69390L,0x6d9dff06c0215314L } }, + /* 25 << 350 */ + { { 0xcb116e787b1320bbL,0x6310206258ed15fcL,0x1a7891a082c13108L, + 0x203d73d939eb4c93L,0x0485b8493c78c65aL,0x663897e93c935525L }, + { 0x9b79708088b41afbL,0xbd34d5134f2b649dL,0x0b4c156f62f6b652L, + 0x24125d1d6863dca7L,0x726a8bb2edb6638bL,0x2ec5deaf82aea7a2L } }, + /* 26 << 350 */ + { { 0x9fb22ca52a3706f1L,0x5a265b5279f5203eL,0xc8844f096fcbd426L, + 0x52a165f0ed8a3267L,0xff0b3a00dfdfcac5L,0x80167cf52de9e1c6L }, + { 0x9e9c4391b0b969c7L,0x279440c41e0dabf6L,0xaa535b8f85133e39L, + 0xef61e22234660228L,0x8ea81a41c386528bL,0xd0bb1f6e71a8c66aL } }, + /* 27 << 350 */ + { { 0x75a689bfa67ab0ecL,0x53eaad3e54843363L,0xdb71f81619a3ba98L, + 0x817257fdc244f33dL,0x8181c028c0fb3720L,0xc813c4651cb7bb39L }, + { 0xbc44c1e71b189585L,0xaedef8701eea3a29L,0xcdd828d7ccb5dc90L, + 0xd224f1774fd2e0f1L,0x2a4723b0e78883e6L,0x33bb05473128e260L } }, + /* 28 << 350 */ + { { 0x544874b71477473cL,0x253a455a3907385fL,0xb303afd631411ba1L, + 0x30047aa0466d6415L,0x3a1b676594d4c2deL,0xc265f1912860c7b1L }, + { 0xfe140a73688e7975L,0xf08a652bf37ce7deL,0x6c9f6df9f46f144eL, + 0xf7e7b95bc0defbc4L,0xfbc9a9697824c075L,0x9745d768d7773c39L } }, + /* 29 << 350 */ + { { 0x7170ab4699873dabL,0x765eb89b8952bc0fL,0xbe3fe2c4f78fd020L, + 0xde51f8579f194b70L,0xa625839e7cc68fbbL,0x50e59b49f7105097L }, + { 0x625294f3b82e287dL,0x98daa85288ca9d10L,0xfa0eb790b499d9bfL, + 0xe280de610382dba8L,0x3fd350e0e76a7d70L,0x1e5c2bebece5ba7aL } }, + /* 30 << 350 */ + { { 0x73e187e000ce469bL,0x21dc6268dbd717ceL,0xe9d63224ee564ef2L, + 0xa7553c854c4c444bL,0xdd409398f6a9b713L,0x902c9cff72f94d6fL }, + { 0x944edb33f50a36eaL,0xa48a5ae4cfb65a8aL,0xcb9a83b9ed82fddfL, + 0x9476090c209aa829L,0x66cd0cb1c7e2347bL,0x0f1fe07c86fa005bL } }, + /* 31 << 350 */ + { { 0x7c17a2e0c65e52b9L,0xa987f030615b8325L,0xa39b78aaa3d4dba8L, + 0x738ce26396e96e82L,0x313f7bb7f08f99cdL,0x29571b3cd1a1b7c1L }, + { 0x00c0e66c89ead6e5L,0x231de4ff19b9874dL,0xc9445296a4137755L, + 0x7b95f3ea336ea724L,0x7c0a222c49bfe5a0L,0xa265c41d782f8d4fL } }, + /* 32 << 350 */ + { { 0xd2db4d35c8d2bf7bL,0x52105d0981571d06L,0x447565cc723a57bfL, + 0xd98c3597d8ded62cL,0x0aeac6d9de2f1a9eL,0xd363b0b70a98d3b2L }, + { 0xd9708f0702ad9933L,0x9334677564f5809dL,0x499332cf49cda010L, + 0x546df74a858467e2L,0x8b84a55093748e8eL,0x9e88ef9706f09073L } }, + /* 33 << 350 */ + { { 0x1cdc6b4f673d9c55L,0x4300148a0c11743eL,0x2f924ce4c38b8c99L, + 0x5300ecc925f32459L,0xb9cd815004473c2cL,0xffee15498eebdcabL }, + { 0x42c292d54c537dbcL,0x32f6d8a293a133d0L,0x4da3a50c35dc41a6L, + 0xc16dee6a102f9ea4L,0x69a017a1f00d0bd6L,0x6a95ee1527acbc5eL } }, + /* 34 << 350 */ + { { 0x6c02c17adcb73b47L,0x10073a3454b70b07L,0x417ca218a7fe7a73L, + 0x6f81a38e4ab64b0aL,0x4e25301f8fa7fc44L,0x180f3e1b27d41e1eL }, + { 0x88925649ce1cfbf5L,0xae279fff2eedaeb9L,0xeac9b033eed426cfL, + 0xa8488f8aa1740d49L,0x6f748bc3711b5da7L,0xbb1c46fd23bbe135L } }, + /* 35 << 350 */ + { { 0x6b2f317b9da70c21L,0xebddc2b5c99dc82dL,0xf4a85d4c5c807d1eL, + 0x47a79b298a15ad6eL,0x02afb05befbda553L,0x34f3998e6941a669L }, + { 0xa4a413fb72deac14L,0x2bd9306c1941b899L,0xae023fa5788c1db8L, + 0x38cd6c42e1012bb6L,0x77ae298c13bd860bL,0x6312af9d63bb40cbL } }, + /* 36 << 350 */ + { { 0xbb7742f370fcad48L,0x6dcce7ff57d444acL,0xfc338485b6abc122L, + 0x03c1118caaf9060bL,0x095dc123cb997905L,0x2dfe24453dd9bee4L }, + { 0x9bffbbf9d45cdcdfL,0xc5b50babb4b26fe5L,0xe985754e87d31873L, + 0xb5b007f5a503d2e0L,0xe25c4eb620bb8357L,0xb6f00e50803fa8ddL } }, + /* 37 << 350 */ + { { 0x21cab682b8035f01L,0xec82f6ae301c96c1L,0xf25d6a0c1539a503L, + 0x94180ece1e35b449L,0x13fbc96f1ede3c57L,0xe4a63eac01d8e678L }, + { 0x3d1a745c068c6886L,0x0659d6ff233be378L,0x493d7a6f3244a214L, + 0xfa852b1b772bd953L,0xbf05cc0ce87db547L,0x28f497ccb30aacf9L } }, + /* 38 << 350 */ + { { 0xa92f28b88ea312ecL,0x9c702e953a3b5f1eL,0xf0a2f787583053edL, + 0xf99506f29cb41eceL,0x4c3b00b5c2b5c214L,0x59bb943717b8d5caL }, + { 0x9ccc7869af5e6b94L,0x6eb795a7f340d02cL,0x7fc613c80a09eca5L, + 0xdac14e61d155f16eL,0xda25c7fcccadb39eL,0x160fda8c9c7fe2b3L } }, + /* 39 << 350 */ + { { 0x8aa83310312ee9dcL,0x702ad7bc2af291bfL,0x3940f883ec915c5dL, + 0xdfb7e44f6fe07c64L,0xa7af875c72d09357L,0xb5df04f4f70b766fL }, + { 0x738af1bb96f8b10bL,0xab27b86735563f8eL,0x18fccbec2ebaf570L, + 0x94e9066dc1d7d59dL,0xa1e3518dc63373e4L,0x0722fd0f22d8306fL } }, + /* 40 << 350 */ + { { 0xcd42d2391be93e28L,0x93c11fcae2ea0d1cL,0x8acd0b17345984efL, + 0x3e3feaf350905d0dL,0x4124e89a6f35b49cL,0xafdd8d27a2bae979L }, + { 0xce1e814015ad5661L,0xb0f9296dde281bc6L,0x11e93935c31ea529L, + 0x1c4c3bd7ebb898ffL,0x7cb73fc76ccc32c2L,0x69e5307da3ac9b8bL } }, + /* 41 << 350 */ + { { 0x37bec50c8e5a9a8fL,0x7f0daba5055a1aa3L,0xa56bc577a1c00a74L, + 0x0656b6aeab88258eL,0x2959237fb88f0f0fL,0xffff63bb9ef15ca9L }, + { 0xd9a2909eb94ae6c0L,0x2506a1779b304c76L,0x5658fed3abdf17c8L, + 0x9c95765e0f90cc53L,0x80ffd7b38e74dc97L,0x97e032e6b8c73479L } }, + /* 42 << 350 */ + { { 0x7073ada11780b0c7L,0x6d4ce321f35f07d8L,0x27b26ee589f35e5fL, + 0x5af10ecd324349d4L,0xf9a0a9071b9bd956L,0x5dde968571350ba0L }, + { 0x678158f5b6400a5eL,0x93764a022842e0deL,0x71a17724057c9ff8L, + 0x04c4313c72f58c63L,0x07fdf15cc4e81260L,0xd6c25e82a509f1acL } }, + /* 43 << 350 */ + { { 0x4f8a719ae3cf3138L,0x7aac7f0d9b1a2e30L,0x3fe8dcb88c0c76d0L, + 0x34afed4ade0b5be0L,0x824e043cfdf7c28eL,0x5b700afce708e71bL }, + { 0x6c7fa728eeffc50dL,0x2488eee97ca62450L,0x25490cb59d969f4eL, + 0x8bbbac3d8bd629aeL,0x7e5213b56e75e171L,0x1385bff25324b23bL } }, + /* 44 << 350 */ + { { 0x364e7371c7d996d5L,0x053390bf8cc483aaL,0x69c23cf281e948d1L, + 0x65e45d618e822ec6L,0x9240ee412ed94568L,0xe0f33912510a84cbL }, + { 0xad42eb0f6ecabdadL,0xb35afdb4bc7e39f6L,0x4ee63cb10cb50316L, + 0x7ccfa14a2a27dc3fL,0x584328f0b4141347L,0x361b2614a23cd89fL } }, + /* 45 << 350 */ + { { 0xe70edc42ee93ec36L,0xec773e52bccc99efL,0x9b0367a0ce0816e2L, + 0x43baad458c6757e4L,0x5d25fa821fb7b01aL,0x65913e86bb6bc3fbL }, + { 0xb1f1fcab67fafef2L,0xe5ffd89c9e9261cbL,0x86f7b89ff29bb205L, + 0xa76ed6722db408b5L,0xd6f1ce5cf83f53a5L,0x9cb5cd26c2882d51L } }, + /* 46 << 350 */ + { { 0x03f6ca364b2582d0L,0x70345ae80f8116e4L,0xc2612cbfc562aba3L, + 0x9cdd127789898142L,0xea7f202c02d762ccL,0xa00c15da33662a74L }, + { 0xcb5cc621aa430b63L,0x6dd1482fb1550d67L,0xb27e7df46216f063L, + 0xfffe57408f49403aL,0x9403206cfc2bc9f9L,0x132504014593a578L } }, + /* 47 << 350 */ + { { 0x6b9c67e6076b2d5bL,0x54509f61883d31d1L,0x25905831fe051be5L, + 0xe6633c1be93608f5L,0x284afa7697480e6aL,0xb124e6063a06cc65L }, + { 0xcbcb2c2e2c608edaL,0x07a39d8f813795a2L,0xf27742a8bd108bbeL, + 0x7425519005b4e5b6L,0xa27620b2b0145a3bL,0x6e3d1210c0f42782L } }, + /* 48 << 350 */ + { { 0x0eeb9dc702ed3c24L,0xe7cb624dfb39fc44L,0xded105f581d4cceeL, + 0xaa675d0c46465cc3L,0x313f4fc99af0a81bL,0xd129819f227e6a72L }, + { 0xaa6b690340b16103L,0x3dba75b2fb4c2fdfL,0xc9feeea1e7c79c2aL, + 0x14f503104e024e75L,0x3704aaa8b5729449L,0x39ac6b0c24b86accL } }, + /* 49 << 350 */ + { { 0x7e25860735214575L,0x3baa75cb068c68c2L,0x93b6a33f10be8d33L, + 0xa88f3cc11ba06b10L,0xe70e7ec2a4f8fe72L,0x32fed39fd4835710L }, + { 0x16137edf3e6059b5L,0x57b1bb9fbb064775L,0x68d3f26dac98cfccL, + 0x89339bce7f9fd53fL,0x15b32212825e946fL,0x55b0a89bf92a0ef1L } }, + /* 50 << 350 */ + { { 0xf419d9becd3eed01L,0x851b31659851492fL,0xa9ac81a9c9b0a402L, + 0xf67bdf20122c09acL,0x9b26b131f442a030L,0xf7a548f517e72d1bL }, + { 0x9e0dbf852a7f505eL,0xaa8e7348c7e93ff2L,0x4efa7877134d8017L, + 0x48f476fc13e5fb0eL,0x552d0447154f4040L,0x8d5b166569b18f6aL } }, + /* 51 << 350 */ + { { 0x65ef443e63c90cfcL,0x3a0dfb8194ed3ad4L,0x75570ba710b5547dL, + 0x5e161fa498e84064L,0xf55dc5003c576f89L,0xe46bd28c7f530eabL }, + { 0x367607400109f9c1L,0xde7a997bb15e9598L,0x25386f307593c3d7L, + 0x680e3639def120b7L,0x43fab687aa6e213eL,0xce48861daa99cf3bL } }, + /* 52 << 350 */ + { { 0x93c2cf3e53ead820L,0xfca3b3564f4444e1L,0xeb6d82bfaac7a37dL, + 0x9c0915d4cf49947cL,0x771f9f7cc7edadaaL,0x51418e487b2df679L }, + { 0xad1b249173f28cf8L,0x8fe4fb7baecacd2aL,0x539764bdb20d0b77L, + 0xb0073685a6a4f808L,0x4c6f5602cf909196L,0x1ae89342d45e9e7dL } }, + /* 53 << 350 */ + { { 0xcf8aa4e5f007985eL,0x833ea882c325d2dfL,0xc1cbaaf5f9f326e8L, + 0xe779a4a9bf906c20L,0x29f475bbc923cf15L,0x6598d52a54055b74L }, + { 0x1001a5f1e4fbd4f9L,0xb4933d56cc74cc71L,0x45c04a50fed802baL, + 0xda140558052bd04cL,0x71c127d63dfbd563L,0xef2b85ba42ebaafcL } }, + /* 54 << 350 */ + { { 0x76569e44bc325891L,0x8f8a1487fa2604afL,0x07a8bacdbc90be04L, + 0xeb53b1087b2c9bb7L,0xcfdc78aaad3c7943L,0xd74807da3bfcd779L }, + { 0x642552417189257eL,0x28138e8d23cb9584L,0x0ce0b331476b888dL, + 0x6d9ceaa0f2a9bbe5L,0xb4f1185653b872efL,0xfa9e6fb222d06df6L } }, + /* 55 << 350 */ + { { 0x0d45565ce6eabd52L,0xaca75463f41a4559L,0xc3e4064a846eb291L, + 0x22ac04bc8613d2f2L,0x74cf6fac2364ce2cL,0x61bbaca8be4fce3cL }, + { 0x302e8117b24dc7b4L,0xa72ae24dd89a053fL,0x75b2023967de96e1L, + 0xbe51cfd2a9e6d1bdL,0x807a8e3d07c9259dL,0xcf3cd92e43cf6384L } }, + /* 56 << 350 */ + { { 0xc040412c754b8669L,0xbda7e0cde2c1d3b4L,0x2ac3b3d5ba29b9beL, + 0x98a415e3f63bf3abL,0x25aee93ed1776a16L,0x46db7347ec3bc968L }, + { 0x8e44180a02612d2bL,0x4e3dc4e82db990ffL,0x2050f58f5f7705dfL, + 0x7b41f5892672d845L,0xeb301603c96e4fecL,0x66ecd24e6cb16a6eL } }, + /* 57 << 350 */ + { { 0xd428e7e3d01edc1fL,0xef608062873fadf8L,0x05e7c80d5606965eL, + 0xb818d0c6a979f826L,0xe9b4c5c7c4793537L,0x7ef637225e83bb66L }, + { 0x825d89499fbb3a85L,0x557abf0396e34cabL,0xfc3db05b8040ad0cL, + 0xbdc8e907e305204eL,0xdfc1628d1c1637e1L,0x10841d2a947a78deL } }, + /* 58 << 350 */ + { { 0x99432df309c7b138L,0x288eef14593b1fc1L,0xf47f9fb21b55f0b4L, + 0x5cc20dd46788b9a5L,0x2e87fb4605e43a77L,0x08cf86be849c700aL }, + { 0x467ec61374680ce7L,0x44e5c8d45884aff8L,0x549f2ea86b33a1a9L, + 0x2ebf696a8b4a815dL,0xc1705b152a74323aL,0x930a9fde69745934L } }, + /* 59 << 350 */ + { { 0xbb11fe102d168ee9L,0xba4aea667f39e124L,0x139364b6fca2841fL, + 0x6feef5b13d359df1L,0x4fe89fe19787be92L,0xd4cea92e0f6b6aa9L }, + { 0x794006c0039bd8f5L,0xdce0eb5b0be647abL,0xf4a97f7d4e40c1d3L, + 0x78d19059d5f7254eL,0x464ddc1d0df22d8bL,0x990b0a39e0fc7628L } }, + /* 60 << 350 */ + { { 0x72f5a0f70ad3bb67L,0xabb15e3dce6396d8L,0x2ae94788463efba7L, + 0xe77b53b41fd4c512L,0x09921a1ca88606cdL,0x1b86b75608e980eaL }, + { 0x2def667af3d22731L,0xadebd3a39641b175L,0xc0f35509045da920L, + 0x8fbf85e4952b7ca9L,0x4ee7565023517a65L,0xd31eeea30e75a4a4L } }, + /* 61 << 350 */ + { { 0x6d9a5d3cc4508650L,0xe71fcf32d1a2ac1bL,0x784b9148d62ec2dbL, + 0x9a3d5d572088946aL,0xc488178757848c00L,0x2f50a62e0875c1e9L }, + { 0xbd23d4aedec0f2dfL,0xc9c28dd5188dad0eL,0xf87ef6460977ba29L, + 0x89ce8330ab03e4d7L,0x7dbec90dbcf1a5a9L,0x3ddc39c1f6c2a4d4L } }, + /* 62 << 350 */ + { { 0x8c0518c7618b787eL,0x6f226212b95734feL,0x3e6cab90c66e138bL, + 0x6e56d68037a7c0b8L,0x67a3c7df16f6acbbL,0x43df95107921bb92L }, + { 0x967846f6a0887d25L,0xf717017766908fcbL,0x1a8ec350267430d8L, + 0xebb46f1a25855c90L,0x73eb78cb396c1714L,0xf766957cdc081e43L } }, + /* 63 << 350 */ + { { 0x0700da846de27e73L,0xfac9dcfd78c35563L,0x01af330ccd073b09L, + 0x0bf5c3b1bb784ceeL,0xd3d9a9ff5d465498L,0x4836b065bde8bafbL }, + { 0xf5bf3316329b4cf5L,0x387388fc54a5275fL,0x73e880d8254af26eL, + 0x07ebcddc8d05311dL,0xe8b9965a4f46cec2L,0x4f07a4fa01b06069L } }, + /* 64 << 350 */ + { { 0xc0a40cac52133095L,0xfe1b22fd93c162bbL,0x8625898c34018741L, + 0x69c9f3f636d9e57aL,0x69d9d7f3378aa211L,0x6b03f897e7dca168L }, + { 0x24d49aebf997a48fL,0x1d984c67c149ac40L,0x667c1d01576f533fL, + 0x372eee199ef82eceL,0x577723c0c207c14dL,0x4225907a0eed37f6L } }, + /* 0 << 357 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 357 */ + { { 0xc61db977bc0e0903L,0xbaf6e4da645c32fbL,0xce89b8ca060b1adbL, + 0x41db448188e2c178L,0xba6339f3923bdd3cL,0xff25b818d29db42cL }, + { 0x3521116ee6d6b35dL,0x4e1bd283b22f16acL,0x9357c984bd79fe5dL, + 0x2eda73be9d45eee4L,0x1a50c59f6288e01fL,0x37baf64975018873L } }, + /* 2 << 357 */ + { { 0xc552c6c6097f322fL,0xdf59a3028bc06287L,0xc9ed375c19610b0cL, + 0xf0e7b4ebb051dad5L,0x7267a304c6556643L,0x0044f6d8c96dc1d8L }, + { 0xf0ed5f9af4fc3725L,0xbbaf9f2c9de8e1ffL,0xef5d66f4af5a4b4bL, + 0x0b5bed3d20644cf2L,0xf7e4543a75ae23c0L,0x696f60dc41325b66L } }, + /* 3 << 357 */ + { { 0x9949b33d2c20f868L,0xdb3aa790b5706250L,0x88ce71e788e17f2bL, + 0xd851baf2da9c0881L,0xe869c5ba86d8c9e9L,0x1af68d65a01425b6L }, + { 0xeae8b1c69bbd3963L,0xf34900b1ec087425L,0x14942910c374bb96L, + 0x3e13c45705487483L,0xe0e6fad435bc6ee1L,0xc7c38dc7b54d247bL } }, + /* 4 << 357 */ + { { 0x6d34bdf6ab463fa6L,0x7bb127b60093b9cbL,0x61d051135a3bfdd0L, + 0x4abab575f1296bddL,0x72da68494d2e9a7cL,0x90267bca8d11f03dL }, + { 0x478111223e9b310bL,0x8ffe91d31b1920cdL,0xec293ec67521898eL, + 0xf0cf026996c1da75L,0xb0dbd4c380f2c7b3L,0xe528175534e4baf8L } }, + /* 5 << 357 */ + { { 0x7ce1ce36189e2f1bL,0x36ca8fe3fa84ca41L,0x54cc2c13a6a568e4L, + 0x1967d9ed25a6d223L,0xf8d20c88537252afL,0x5a58936cac3d697cL }, + { 0xa2659671b0084ffeL,0x08a9e041ec25bb0eL,0x6bd405ed4074ccedL, + 0xaeebb470dacb5503L,0x6f18e32bd5448d3eL,0x0412973ba94cd45dL } }, + /* 6 << 357 */ + { { 0xd72fcc3742fb1cd7L,0xadfb8967c49c359dL,0x6dc988a55935bb0dL, + 0x3fb10981e3080802L,0x12c4494f3be161ceL,0x5a0e22d44b649dd0L }, + { 0x5c57cbfd62a85259L,0x7ad55b3c0e5ab7a2L,0xcd53564928de30e7L, + 0xce35e6e76867e6a7L,0x626810562f6716fbL,0xd8b4ff26a88d3bf8L } }, + /* 7 << 357 */ + { { 0x5949ddfa53abe7a9L,0x944a2ae0716f63a6L,0x90961922675d1f43L, + 0x36c41c12f5b55722L,0x85b8250f7782775eL,0x89a3a733748663beL }, + { 0xd4358450475d2d88L,0x4183f45e1beef8adL,0xee3bfe8b06ec8d58L, + 0x2e462b1609cc4d82L,0xf9cc307ec6148e1dL,0x70d3b2f77b1281a3L } }, + /* 8 << 357 */ + { { 0xc32730e8dd14d47eL,0xcdc1fd42c0f01e0fL,0x2bacfdbf3f5cd846L, + 0x45f364167272d4ddL,0xdd813a795eb75776L,0xb57885e450997be2L }, + { 0xda054e2bdb8c9829L,0x4161d820aab5a594L,0x4c428f31026116a3L, + 0x372af9a0dcd85e91L,0xfda6e903673adc2dL,0x4526b8aca8db59e6L } }, + /* 9 << 357 */ + { { 0xf0467111e854f886L,0xe228021d8dc6117fL,0x07ff954cac432e28L, + 0x373be2ef31d9b69bL,0xaa214d016fd61f0aL,0x27bb7932f950b029L }, + { 0x1caa914f967c97f0L,0xfb133ec0d548897dL,0x598514173cfad251L, + 0xd41d1da432d14208L,0x446c79f2cee424ceL,0x8b5272a175e839a5L } }, + /* 10 << 357 */ + { { 0x26b5e85d62f50c12L,0x8418cecf5ff562d5L,0x0d35b4d459be698eL, + 0xd79ca9ee93730d2eL,0x2414d99325627fe5L,0xe31dc5293fc64803L }, + { 0x5c9100d60d027a12L,0x9004ee36f2208db5L,0xe734b13b135d02bdL, + 0xf905c01a7bc09b60L,0x4eb51557b21b68fdL,0xe6e98bea8c583359L } }, + /* 11 << 357 */ + { { 0x14dbcf1a61dae7e6L,0x559a7b52ea0da075L,0x7391545d439d10d6L, + 0x187e00e675e617abL,0x453b546b5142355dL,0x9bdbddbc84bca97aL }, + { 0x742a699591e5035dL,0xcf86d3e1831209ddL,0x6fb66757f5f2a999L, + 0x2e360aeff0e71f2dL,0x6c6f71f2dc97114aL,0xef686b8b17c3a3dcL } }, + /* 12 << 357 */ + { { 0x7d07a61d13b5ea74L,0x7f4b7157c8afecd9L,0xefce9c89820b0298L, + 0xe85c4510e3888d59L,0x9cd3352001234b9cL,0xba2692c0fef767e8L }, + { 0xd2bea3d45b3ca353L,0x9ad478e5b51a704aL,0x1fc9bd0d9426f25bL, + 0x52f930bf864a1ba4L,0x559f36353765ff27L,0x548c7f0dae28479fL } }, + /* 13 << 357 */ + { { 0x6296d54f68b0df62L,0xace420ee9e6afdd4L,0xa20a510dfcd1812fL, + 0x488f113a8cd04a29L,0x1bee07640765cb70L,0x50bb5c446d0f44e5L }, + { 0x5ea842cb7e320ebfL,0xa6e0c1e6e795a7fbL,0x89cd1f765e7e79c9L, + 0x7436ec1e87ce6c5dL,0x1376222de28309f9L,0x9ed7d6fb7f01548aL } }, + /* 14 << 357 */ + { { 0x32e9740ae2fb0467L,0x3a7a32b3ec039d67L,0x630d8d346a425a7cL, + 0xc9af74ae418a7dd0L,0xc903576daf502870L,0x7e02b3b7e98cce5dL }, + { 0x0bfdee7a158f005bL,0x88eff4a363b91d59L,0xf23079728bfe3ed3L, + 0xc75536bce6b1fb4cL,0xf61a82e1a04d46fbL,0x771a8fedfddd52a5L } }, + /* 15 << 357 */ + { { 0xf5efc82065af5b94L,0xd618a9e8ce5535a2L,0x70cfb112cda6249cL, + 0x6986f00f9f217280L,0x41e46ce605faa951L,0x2abb39f3a3ad613cL }, + { 0x3e04b28b07671c94L,0x61d323ac53cdaf80L,0x2389875cbb9580f8L, + 0x64800835febb0b34L,0xdaebba99d0d21027L,0x0f1cebfc23288a7fL } }, + /* 16 << 357 */ + { { 0x51a033a5cecb916fL,0x2ac62f638d7de61cL,0x92eece49a42a266eL, + 0x87e037db82c4d11eL,0x875be1416fbae08aL,0xf348fe26c539478cL }, + { 0x51f8b907ff94c01eL,0xc46cc0e019695a9dL,0x2c74bd666c51b9c2L, + 0x635d3d24ee565de8L,0x6bd656638982c8c3L,0x5c345b79daf6a93cL } }, + /* 17 << 357 */ + { { 0xee7265ee93f081dcL,0xe8f90a6be03493f4L,0x4e8d10275328b0b8L, + 0x13bb82bb96fa0930L,0x764c2915d1f7d5a7L,0x1896c78f73476481L }, + { 0xe9a34ff267873b76L,0x8a9a719cfa0afda4L,0xce93d4cc9ccb715aL, + 0x9ba00f011495d1ffL,0x3131e6666df0e119L,0xe68e1815c902ac6bL } }, + /* 18 << 357 */ + { { 0x0ce4ae1044f4a2dbL,0xa8645e2310bcc5c6L,0x6d9728b5e489762fL, + 0xd365c12a9d46ad88L,0xedf484fee1a527aeL,0xfdf5c519e5be2bb1L }, + { 0x4706cc2870a3d4e3L,0x07c60129065f1506L,0x42e2e16478298553L, + 0xa56a2bd5bae646dbL,0x893bf45c61437e62L,0x97dbf9266c525900L } }, + /* 19 << 357 */ + { { 0x65c56764b52213c3L,0xa171ba9d97aefe9aL,0x5904e8c934336916L, + 0x727209b6ff187f05L,0xaf4e50525cb68a5bL,0xb46a6abadc4319feL }, + { 0xfd48d0d57890cd90L,0x5b0b68c7252942daL,0xc41023352b01887bL, + 0x582251eb5ad09a7dL,0xbd79b557e1312726L,0x9f5ee3788057db5cL } }, + /* 20 << 357 */ + { { 0xa30486a6666fdcc5L,0x5cb7f7ce84056f89L,0x0f8a6b96505636a5L, + 0xfeafdf97c6624ce2L,0x9dade91c55b8a7d6L,0x3d009219ca2b459fL }, + { 0x483549845a969337L,0x37d57cbd323c09adL,0x32a91e91e74b9e74L, + 0xdb4f18ff1c317c24L,0xf9f0daf342418667L,0x735a1eb946946667L } }, + /* 21 << 357 */ + { { 0xb395bfd1c8eaa54bL,0x8181d6262ee25219L,0xf4bf437b38d912f1L, + 0xf9f1161228a8b32eL,0xe359adacc2be5c61L,0x71557ea2971b60c9L }, + { 0xf071404b1b00cf1eL,0xb163c3608da3141fL,0xd9dedc07a8d51d98L, + 0x29e89ac5ac827b74L,0xc38cef633ef35dfbL,0x9abd281097d477f1L } }, + /* 22 << 357 */ + { { 0xb34e560f0e6d9646L,0x4fc05a0dc0ba033fL,0xc9f5e040ddc1bcc8L, + 0xf723b78ab92068cbL,0xd558f5912b5c7030L,0xb16bdec774ed778bL }, + { 0xc12aacc3b32980e0L,0x856e90411daaa32cL,0x34f7a28596429db4L, + 0xcc2c61ea415dcd04L,0xa0e192cb46b7d996L,0x5b7c845d55d87ce9L } }, + /* 23 << 357 */ + { { 0x9ba0a26fc0ee684eL,0x1b871ac353573254L,0x76a094bc5783e706L, + 0xe78bea66dcc01e8fL,0x7e20c5aedfb74e56L,0xbdc5314a8710f0e6L }, + { 0x2bcc7a0085f2233aL,0xc58dd45b8aba1575L,0xdd1c6b78e411b6d8L, + 0xbb8d19529d23d2eaL,0x5293f3cc0066c9cbL,0xb7d0d7b0249c6d93L } }, + /* 24 << 357 */ + { { 0x68fe359de23a8472L,0x43eb12bd4ce3c101L,0x0ec652c3fc704935L, + 0x1eeff1f952e4e22dL,0xba6777cb083e3adaL,0xab52d7dc8befc871L }, + { 0x4ede689f497cbd59L,0xc8ae42b927577dd9L,0xe0f080517ab83c27L, + 0x1f3d5f252c8c1f48L,0x57991607af241aacL,0xc4458b0ab8a337e0L } }, + /* 25 << 357 */ + { { 0x614c4bc273041ddfL,0x4fef1cf6364135aaL,0x2c9ac204ecf0e610L, + 0x75a302a991a6dce1L,0xa5899c96651ec9f9L,0x6c5384f64bcad1a6L }, + { 0xa41012e560f705ebL,0xfcf6512235e85d67L,0x2fdcfc235ced3638L, + 0xf834fac02deac34aL,0xf5a64ec510a8ad80L,0x843855e1a412c4feL } }, + /* 26 << 357 */ + { { 0x440dfebd76ca517aL,0x79924057c577eb59L,0xf1aea290d038a921L, + 0x77afb37fb0c95974L,0x48a5b9a715763d44L,0x713de85155c8683eL }, + { 0x250e8f8239d7e1deL,0xc5f1f61c8a2c846bL,0xf26ea6f9faafd017L, + 0x8ad26055f9d7cd35L,0xc980ba773b2df598L,0xe23b7eabd5e299a3L } }, + /* 27 << 357 */ + { { 0x5d37811464744605L,0xfab096990278c1f0L,0xc4d32b208448c344L, + 0x767a24d2d7d1df17L,0x842de148773ea0fdL,0x73d7dfbdff6e40b4L }, + { 0x3d61439283576d1cL,0x4820c435ec865519L,0xf99e84dd6bfa5e48L, + 0xeb18687a9d0d2adcL,0xc3b7369da7fd75d2L,0x7e332b5739f5f093L } }, + /* 28 << 357 */ + { { 0x0796a8b6ec13d2acL,0x19036c255677347dL,0x2f0d36eef527c827L, + 0x7c8a3d17ca61ed60L,0x3920bc68748cf7c2L,0x61835bdf9018b300L }, + { 0x9cf595c1689d5826L,0xdc547999fb51aea5L,0x11bb04120fc297c6L, + 0x88770df2b2f9fe0eL,0x99e031f5f6856a85L,0xbb59e8c7afe29c50L } }, + /* 29 << 357 */ + { { 0x714e784820dfc5f8L,0x35cde8ae2a2265bcL,0xf6b29ce4bfc32fecL, + 0xbd5e91f1918043a5L,0xd3766f8b60f8c218L,0x273c41935298904cL }, + { 0x0a76492d5d441fb5L,0x99cb3b1d164d9275L,0xb2be87c80ac7935eL, + 0xbd1a1b3f0962981bL,0x8a0c207b96d0df2dL,0x1bb1e505929752d9L } }, + /* 30 << 357 */ + { { 0xa574de94621b2705L,0x0d0ca1b73e3f2227L,0xbdc9ddf2e49bc2d8L, + 0xfbc7254309d314f0L,0xf5900cbb827e0b1dL,0x3994eadd8a7e8164L }, + { 0x2e7949793046f170L,0xde21ddc3c6883cc6L,0x9ea19d34bcd40da7L, + 0xb4334df8f01a9ae5L,0x801496ebce8c53c7L,0xc2a5e8527a4b0601L } }, + /* 31 << 357 */ + { { 0x435a6c512ecf62d2L,0x757cd8f6559a6a0cL,0x47833f815e4c0d40L, + 0x2d0b48047d960c6aL,0xf5474833473d5eb3L,0x70264154bf756b52L }, + { 0xcc46e58d940bfb7cL,0x2e0dd3a69c89d48aL,0x483f3ee19387df66L, + 0xb3097da4585d3600L,0x82d64b4d76411ef9L,0x0df7d95719682e87L } }, + /* 32 << 357 */ + { { 0x179c59cf210c3144L,0xfb613c5733eebbc4L,0xdda75cfdba0cf384L, + 0x94081a5b3a8fbafaL,0xb91de90a33384e0bL,0x7d1f8f4027aa2a45L }, + { 0x0747bcc162031148L,0xd2db8e39f324160bL,0x9c1ce3e9722484f0L, + 0x13a7ee5da62d1ddaL,0x77fd79343a963bceL,0xcd3d871783d2f21bL } }, + /* 33 << 357 */ + { { 0xc7c8eedc93a27196L,0x0832b0dfa8abe585L,0x31fe11e8d8adfb86L, + 0x1091601e9d50e4c7L,0x7931a284ac3d2ca4L,0x0f1464b6f3fc6641L }, + { 0x2ead94f3260f29a7L,0x914b8396d88a7696L,0x950be4bbe73d807dL, + 0x26d0115e5b3ad83dL,0x3de8a73146c22525L,0xe50825dac5fffff1L } }, + /* 34 << 357 */ + { { 0x716378cae4b98aa8L,0xacf8d67b59b746a9L,0x78f0b5eca65ce8ebL, + 0xe5997983523cfa35L,0x85bf5badbeba89e3L,0xc8052bbfcfd73b41L }, + { 0x0b3d77139fb311a3L,0x821a20e2d96f696fL,0x0f087e5744657c9aL, + 0x72031f281ecfea36L,0xd0765f333f32b010L,0x0412c69929c48643L } }, + /* 35 << 357 */ + { { 0x53d361b89f501481L,0x8970937717153c6fL,0xb52280b916bb8d8cL, + 0x5985cdc0b33dabd6L,0x35ba0cd9dca8ae72L,0xf55c6e7301bc4efdL }, + { 0x2106ed2f269577c4L,0x4cc34291bfe765b4L,0x9f4168ea812eb958L, + 0x02869228999ba5cdL,0xff91540d3ab27498L,0x9020e6e158e55a79L } }, + /* 36 << 357 */ + { { 0x1a5b15377f1c7cbdL,0x5b31930b7cc17c56L,0x5b91e1a492cc8cf5L, + 0x970e43deeca08bdeL,0x36424bfe0e2e963bL,0x2e49534968b1a489L }, + { 0xe350ca52d8e85a9aL,0x3cb9f599ae2cdd7cL,0x0ff35a0aa83215ecL, + 0x64cf57b81973a966L,0x128be6cd36b26702L,0x8067afbd5f65f7bdL } }, + /* 37 << 357 */ + { { 0x23d1f49215876c71L,0xafb21c1d41e7495bL,0xdb3ab62c2705885dL, + 0x20ff803f7ba216cdL,0x26cb190699c9ee55L,0x8280dc9c0fb05389L }, + { 0xadf55171df1020dfL,0xc044e9bcbd011b5cL,0xe21aaa60cbed2430L, + 0x5939fe583336df4dL,0xfa306816ff78c665L,0xba92ca8243eb18f2L } }, + /* 38 << 357 */ + { { 0x6f05e6241b7edb64L,0xc280105b6681f48fL,0xd1b94413f993dc9eL, + 0x84f24c01e46de412L,0x092017d54abbf7dbL,0xb73193a56f7b1b08L }, + { 0x22a7c5765195ae46L,0x81dd6b12610c28efL,0x61959874ad7bfcc1L, + 0x3ade0a77d15f8cf9L,0x124cef4d954db624L,0x0733bd7a5c247650L } }, + /* 39 << 357 */ + { { 0x52d7f9ddf1cee098L,0x538b7fa17a6a2ad1L,0x5f2294312911e75aL, + 0x71c337b7e6ef0271L,0x5e278a1267ee72d1L,0x7b348c756f33fea9L }, + { 0x7bb59f1a694bb928L,0x5783e43f292b258aL,0xe3b53ca77181f1d2L, + 0x028ba90e051c7d2eL,0x4bb06f9364789d76L,0xcf97fc4da228a7a7L } }, + /* 40 << 357 */ + { { 0x3dbb3fa651dd1ba9L,0xe53c1c4d545e960bL,0x35ac6574793ce803L, + 0xb2697dc783dbce4fL,0xe35c5bf2e13cf6b0L,0x35034280b0c4a164L }, + { 0xaa490908d9c0d3c1L,0x2cce614dcb4d2e90L,0xf646e96c54d504e4L, + 0xd74e7541b73310a3L,0xead7159618bde5daL,0x96e7f4a8aa09aef7L } }, + /* 41 << 357 */ + { { 0xdf5c2fa79111caacL,0x493ada25b04d2b3aL,0x5c4850bfa39a7872L, + 0xbeae16c067e07e93L,0x63bd7d390178358dL,0x7a7e56a1cfe0bcd0L }, + { 0x9ba7a4500816b666L,0xea6c70c8dae070dfL,0x84013756832c2b35L, + 0xa28e5dd08d3e9fc3L,0xd67665aac653c08fL,0xee54d7b6aa6bdff8L } }, + /* 42 << 357 */ + { { 0x99b870afadbd24baL,0xb34fa9083bee289fL,0x4a20f29bae836fa4L, + 0x4188ed5024b464c3L,0xfb93f48fc6c00297L,0x334b8689736186ecL }, + { 0xbf7f1c424e1016f1L,0xf95e6e59413ca088L,0x5878156c288912d8L, + 0x9e99199704c7ce69L,0x0f0c185d5d6520d1L,0x1ed2ece33fe6f498L } }, + /* 43 << 357 */ + { { 0x319fb249607cfd40L,0x5920056f62b40e28L,0x9ab4528058631ab5L, + 0xb527738f413452d2L,0xb2885e46b296e602L,0xb1dcf41a74824807L }, + { 0xca9d2b06b2ad2fc6L,0x500c5f11ad05eeceL,0xca94160f21f3db6aL, + 0x693adf4e262470d6L,0x1f4c62c5480b0cffL,0xb3ebf11f54c748e4L } }, + /* 44 << 357 */ + { { 0xc8ae4d2bb4ef93b3L,0x4967da7b99758d99L,0xd1483a1fe04db9baL, + 0xf5e657df3033474dL,0xdd9371c89db4b96fL,0xb5f288956044b259L }, + { 0xe8987a43b2ec27bdL,0xaabb1ae68fce67bcL,0x4518fa3eb2b97680L, + 0xa0142a13748591e1L,0xf9148ab96c2db557L,0x65592253e0e4f9e7L } }, + /* 45 << 357 */ + { { 0x21163809bccf41d8L,0x0eafed515b3f09d1L,0x3b5360d9d84b27f6L, + 0xee752fd04411d37aL,0x1cea3b5c6a3f5027L,0xb206e74d9454d9f6L }, + { 0x710715dab52af43dL,0x8175ca136e6c6463L,0xbdb123d39689144dL, + 0x569e6edd4d9c459fL,0x070f09a4f02e5b25L,0x691c23ef3d79a7b9L } }, + /* 46 << 357 */ + { { 0xc0c94165781356cbL,0xcb9fb705876a839bL,0xfe23f07e89db25feL, + 0x710f0fa3a52cec3bL,0xb0ab363073e0f037L,0x3b79a8167c9aa037L }, + { 0xdbc7f83ca1f13fe1L,0x8bd910c63d653a81L,0x2e54ad408c78d003L, + 0x0de02157a3e9ccf0L,0xe9081e8bf7670dfbL,0x6a2ad476c8647bc8L } }, + /* 47 << 357 */ + { { 0xaf58106ebf047836L,0xadc3245e195e5675L,0x75612e175290e051L, + 0x27b81bd869d46bb9L,0x9d4dad5b5417b5faL,0x19850d70fd024259L }, + { 0x987daa604b0a86b5L,0x5d5a5f9c0358a944L,0x9008682f48d2ff67L, + 0xc9db4d4b89e81cf9L,0x133516bc850eaae4L,0x0b5bfdc81da8bd19L } }, + /* 48 << 357 */ + { { 0x609deb162d8bcd6eL,0xe42f23a92591750dL,0x4a9f3132b378305cL, + 0xf101799869275f5eL,0x14be746761b089b5L,0x05f620d20c81b0c5L }, + { 0xca90a9c06cb8412eL,0xfe0f6a8915b1b0d5L,0x1b25ac9620c71988L, + 0xb971b61a390aedd0L,0x995214d779d8cd39L,0xd7fa135b65c6e11aL } }, + /* 49 << 357 */ + { { 0x5aaa98f875330325L,0xc900a7781f3541a6L,0x69bcf864174a3200L, + 0x3abc5ef71c46b3e2L,0xa53c9e4e47851b97L,0xc166a4e22acdc42eL }, + { 0x49e4e6fdb19b4678L,0x4fe02cb162b7da19L,0x575c61a6633153feL, + 0x49578b28a4f83b70L,0xc6840d063737532cL,0x93047d40480f55b9L } }, + /* 50 << 357 */ + { { 0x835be7417d930332L,0xa4d001bb2cd86fc4L,0xef141e30a6e3a24dL, + 0x4047620adc328d2eL,0x5c80a3bc9a5f1f12L,0x6cde5e4ca19b423cL }, + { 0xcdd5d7773ba0fa5cL,0xb96dbe62ea85c28eL,0x963c02245c804896L, + 0xb2a581abe5dd6b98L,0x28a908a2abc8dac4L,0x5834b212985fd18fL } }, + /* 51 << 357 */ + { { 0x02757b1f0fbe0c5dL,0x2d0d05a854ef99e2L,0x2bda526d0377ffa0L, + 0x58ca8b08925985afL,0x1fb7dbe727b69722L,0x322d7db5f1c57fe5L }, + { 0x4049c8bcfdf111f3L,0x0b4712974148b027L,0x34fcb1e58782dab0L, + 0x697dc9431665557cL,0x3ae30e2844659ba2L,0x479dbc2f118e7417L } }, + /* 52 << 357 */ + { { 0x10b10d86227e8607L,0xe83536281d1be36aL,0xe34068f9d952b0e9L, + 0x148eeb38fdb6ea99L,0x82657d605547e7ebL,0x9c35dc82a86155eeL }, + { 0x408f79262060a81aL,0xf2a79205a6282e8aL,0x10dbb58526e70e7cL, + 0xd636f8225df85d6cL,0x03202c027682b922L,0x31323940baf18500L } }, + /* 53 << 357 */ + { { 0x5882374401879796L,0x068943ccd1249281L,0x20dec1c12e1d6effL, + 0x5f4c2c070bdddecdL,0xc56d52b37ee724c3L,0x93bc2c7a559e25ddL }, + { 0x0c95d2e5f98a9940L,0xc570e96ada60a809L,0x94c4a964076233eeL, + 0x843c99627dbbc526L,0xe4075129d4cdc652L,0x0afff70561cb2698L } }, + /* 54 << 357 */ + { { 0x3ec1e3a5f607f893L,0xd476dd24054aaa8cL,0x2cb92280a93488abL, + 0xc8d1207710d1dc68L,0x564839b9bfb494e6L,0x7a13930ceabdfe56L }, + { 0x52f72a9724f9b183L,0x30ae4bc87e9c6fc3L,0x3d7d2765f35b8e6cL, + 0x701f3d89a665ba55L,0x98f2fe85c466111bL,0x338073600c1c0dadL } }, + /* 55 << 357 */ + { { 0x7dd106bab3a48d42L,0x7eac4690ebfc75aeL,0xdbf3547e68ef4ea3L, + 0x3629c438a1a5faa2L,0xac2aa55e653bfd97L,0xae5cc39752c3b8f9L }, + { 0x117380552853b626L,0xd5a955f224a0dfe2L,0xc4356ca25940233eL, + 0x73f7eda97994aedfL,0x2bfa76c693b185d9L,0x091cef91a0327108L } }, + /* 56 << 357 */ + { { 0xa8393a245d6e5f48L,0x2c8d7ea2f9175ce8L,0xd8824e0255a20268L, + 0x9dd9a272a446bcc6L,0xc929cded5351499bL,0xea5ad9eccfe76535L }, + { 0x26f3d7d9dc32d001L,0x51c3be8343eb9689L,0x91fdcc06759e6ddbL, + 0xac2e1904e302b891L,0xad25c645c207e1f7L,0x28a70f0dab3deb4aL } }, + /* 57 << 357 */ + { { 0xf5dafec85f102704L,0x2f3b6b6929f5b946L,0x84472c029d4c9979L, + 0xed49f3e6341f0150L,0x3ee3432eb3bb085fL,0x84c553183cbac42eL }, + { 0xbb358bd9dc4c7ffaL,0x0713917d2db356ccL,0xc73e9fd0670c7139L, + 0x87600c4c3581108eL,0x2ae731d7586af51dL,0x30630ad6614c126eL } }, + /* 58 << 357 */ + { { 0x15f8fba7712c0edfL,0x4a1f93baa2c363ceL,0xfabca37e8f2948a4L, + 0x652922e4dd765560L,0x2da78559220cb98bL,0xb797746a54b940c4L }, + { 0x8535fcfc591bb7faL,0x58857815c25376e3L,0xcd8db789da627557L, + 0x718072ca318512b7L,0x92266469813efd94L,0x3217649aafa85382L } }, + /* 59 << 357 */ + { { 0xd517b39e51c4bf28L,0x6614c16261f583a3L,0x79c72f414739ea59L, + 0x597e1c2ff76e80f8L,0x3a72b05e7b846f3aL,0x1849e5126c0a45a2L }, + { 0x79a6ea5b9d506d83L,0xc48e570219b7f46eL,0xc89c5047c524bb48L, + 0xafc1fdd99cb88cfdL,0xb07eaaa0b82056e6L,0x60f6544f05885df8L } }, + /* 60 << 357 */ + { { 0x9894ef75f39e2738L,0xac585d07b40db6ecL,0x07d9e938c4cfdb92L, + 0xda174933737f1a7fL,0xa4f1fb65484031a6L,0xa96d9f612c21b546L }, + { 0xaf981519d24ccee0L,0x238de6de9d53b571L,0x09afc481fd78c3ffL, + 0x4351715d9ea7f6fbL,0x91a02325b14a7320L,0xcd8958d8bbb6346aL } }, + /* 61 << 357 */ + { { 0x22ef4217452ae6a0L,0x3192309d9ced837aL,0x773585ed2ba43ee9L, + 0xa9b29d94f3379e81L,0x43838b3aa6835e44L,0x1afe27ab0c7b2336L }, + { 0xca1dc61683ecd230L,0xc9e8b95e6d235df5L,0x9667829b2af11adeL, + 0x27254b0fbe532148L,0xb50bc3c86d233f14L,0x30e0e450bb35d985L } }, + /* 62 << 357 */ + { { 0x8b3f79087b95cf32L,0x67c654b06272c619L,0x61160a9d22c0f46eL, + 0x1cce95721d2e36ccL,0x62bd951d3990db3cL,0xcf0005c8d9700d14L }, + { 0x304aff9c70116120L,0x1c919dd2b08d57ceL,0x841b058ec0c0c0b0L, + 0x7cfd4deb7af05aa2L,0x4fbd13c57b11ce5bL,0x03e07dc9f8259bebL } }, + /* 63 << 357 */ + { { 0xe9b37f569d0703e0L,0x7b5e0df5f83c215bL,0x7fbb40f0d3c21efcL, + 0x87a2ff119fb33620L,0x208b062bd1176635L,0x806bc549950d30efL }, + { 0x862de3a4ae2bf355L,0x917b06bacf9ef6e8L,0x55f1ec4cadacc178L, + 0xbcd679fc81d752fbL,0x9404d6ce65a00270L,0x25ce99e6000c6e1fL } }, + /* 64 << 357 */ + { { 0xa13f19b40f3ff12dL,0x57ee08b1019564aaL,0x00ec0c997044a6f4L, + 0xaf5665f8dca1075cL,0xded5ca3f0620ab0cL,0x9b2cb8c7a896deffL }, + { 0x032ab2b307df2345L,0x964d109ef1da3f88L,0x2286b6f725133304L, + 0x0d16d531977a4567L,0x00a66036f1abae4fL,0x5debab1d95f0103bL } }, + /* 0 << 364 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 364 */ + { { 0xf2cdae3196230a58L,0x47cf36b4f304e1eaL,0x9d14f25ad750b29bL, + 0x931b9c65dba15f3eL,0x34db169ebf9fe2ddL,0x8a89e47c52663433L }, + { 0x8859a4f8026ec31fL,0xeeb703eaa913ceeaL,0x74638d6a67ac4db7L, + 0x5c8ea7b2be25d755L,0x8a0f0a8738db10eeL,0x96a26bace890bcd3L } }, + /* 2 << 364 */ + { { 0x883533af64a5e869L,0xaaa778c26973ec23L,0x8f0b5fb546d0fcf3L, + 0x7e6b0a0a4ab05da7L,0xcd91a869c67b6614L,0x7de9f2ff6c6f7cf2L }, + { 0xc072a106d1ec14c3L,0x3f4b960642a128eeL,0x7378192c8f0ce946L, + 0xdf2e7b9fd1149441L,0x4fa17cb614ccf45aL,0x575680e945f03568L } }, + /* 3 << 364 */ + { { 0x0f4ca7803374f910L,0x5948ae98fedc5b5bL,0x4873625b4ef805afL, + 0xbddba22fc015c586L,0x7091b50aa41a8c93L,0x721dd3384c005f42L }, + { 0xf43d37462065f41dL,0xd16bae3e172512b3L,0x3efca10c8277068fL, + 0xd0c25d7b77513f00L,0xc0015cc12dc3af9bL,0xdf11a4ec94c6cadaL } }, + /* 4 << 364 */ + { { 0x8b70e94f8f458c68L,0x292726544160ecc7L,0xe22219ba4d3ef22fL, + 0x7f8a712a1999f948L,0x25575e96abfe7302L,0x21c6ffc6564a1af0L }, + { 0x045e9c667e8500daL,0xef7c3cf704ef8ea6L,0xdd23b825c3db161aL, + 0x05fb173aba33a906L,0x9a8b5ecb870e41f2L,0xf3d9db0bccc30d1dL } }, + /* 5 << 364 */ + { { 0xbed7d94ca1bf2c8cL,0xbb7f437cb8b719ddL,0x65416af6106834bfL, + 0xdade8a144c4f7448L,0x62227a1d881dfc06L,0x37bc7de58dc2b7bcL }, + { 0x4f11541712ce030bL,0x72439d8ac2a9e0d6L,0x98cc53aba0f1b961L, + 0x2f68011d48b0ec8eL,0x4bbc34679c72d034L,0x0320c1469c576e38L } }, + /* 6 << 364 */ + { { 0xd9243926e873ff0fL,0x2e2a5ab6f20b0e49L,0xa1bcfeee0e35f201L, + 0xd25be5f3196f23f3L,0x298c67f2ffc1d068L,0x77dae55c0c3d950bL }, + { 0x5e15ab998822c996L,0x52de2e6d83f60a98L,0xa9f82ec947a7e269L, + 0xf02af9a22ac22e49L,0xdfb3103fa706f090L,0x125599623cf8dcb0L } }, + /* 7 << 364 */ + { { 0x9f5f44fa666e278fL,0x53c88803f5582c78L,0xd7e8f258f9627f9cL, + 0x22499dc938fd51bdL,0xa9d7497c846a4a79L,0x791b8ead026ae250L }, + { 0x84d47d19db15ff63L,0xb58a82c0267b44b5L,0x9b2f138806a52e30L, + 0x3fc8da027f08953fL,0x22d074d292fcac08L,0xb9c7c3db701d73fcL } }, + /* 8 << 364 */ + { { 0xb7b8562588ad12b2L,0x81f5958b1e44b254L,0xb4ebddd5c91b8ffdL, + 0xef815ae155d38511L,0x98587d551b0da525L,0x1d41817734a9ebbdL }, + { 0x844811fb1e6057d7L,0x0c16977176e5976dL,0x4b268bb4f623789bL, + 0xb26ae5be40498058L,0xb47a5ded3c2b435aL,0xe15a684b8fceceb3L } }, + /* 9 << 364 */ + { { 0xd55407583353db48L,0x0e334ccac0c0b5e9L,0x679a935f270c48d3L, + 0x170693e436ef0e90L,0xc72fb12f9de59023L,0xaae13a0e9371697cL }, + { 0xe98ed704d8d56e4dL,0xc6de5384eb71f091L,0xba63adccc6d905a8L, + 0xc84e614d66e40dd4L,0x15dcf1a3fa0f55e3L,0x4e26ee3af157c7a1L } }, + /* 10 << 364 */ + { { 0x122a3eedd09dc3c8L,0x6a19907faefe0819L,0x057aafa1da325339L, + 0x138033bdd42a5345L,0x8ac206af1a065ebeL,0x0a46f5ae25c31ed6L }, + { 0x7fc577a9d7e379dbL,0xc6df694369dcee54L,0x4c167ba2a8336bc1L, + 0x0fbd9708f3a1339cL,0xc6b8c01f226f612fL,0x5d4ed789d51332e1L } }, + /* 11 << 364 */ + { { 0x67ead4e0f6a40814L,0x42fe051ca2ec9ae1L,0xc09f84395eba62cdL, + 0x7bb5ba0c9d8e7305L,0x85962d0db46f81abL,0xc7183752628b18ebL }, + { 0x7a1f023edf58ec0cL,0xf21bfdbaab6535dfL,0x12add590801d2481L, + 0x1fccd1e37a11520aL,0xf83caddd6fa8f8e2L,0x99e7256c24e58433L } }, + /* 12 << 364 */ + { { 0x26aa2c2e5a1abcd8L,0x2b16a12e9609d9d8L,0xe485a551a2bee00cL, + 0xfa28c30bf4f2292eL,0x99abef78b7358f1bL,0xda6b3cdf10a276a1L }, + { 0xbd3858b747c03f71L,0x4f0bf5f0b22d05d1L,0x2d80f5d28250f760L, + 0x060f9b278cd9666cL,0x6a6c40b0b1b014a9L,0x44537af38c440a9eL } }, + /* 13 << 364 */ + { { 0xce1c070a2275263dL,0x2723b3d149cea971L,0xedca02f5817001b6L, + 0x5c160e9349c946e4L,0x273b4952458a5265L,0xc7bcd7c610385173L }, + { 0x22cddfd17fb08b14L,0x959d5dfe10f73d01L,0x900f5f348e387351L, + 0x6d7381dfdadb8695L,0x8dff2b193aeafba6L,0xe4a8d6bd8adadc36L } }, + /* 14 << 364 */ + { { 0xb564cfd676faaca5L,0x8a6e3925920dd223L,0xee59a140a590a383L, + 0x9e29b552a1922ad9L,0x604367de60a0da63L,0xc498aca592c35fd0L }, + { 0x74135082250ed8a0L,0x5d109d1a6c7c3e77L,0xf9e2d84dc63dff94L, + 0xca50f5e4f7aa2b0eL,0x7cba9e87d543d389L,0xaf5fbbefd8fd1292L } }, + /* 15 << 364 */ + { { 0x3163e2e895bcc345L,0x4ceaaf2d80d9a931L,0x4d2dc44b2f621612L, + 0x2a5f60b86cc8ffd0L,0xf49038cf7e8c9434L,0xb580b8c508015b8fL }, + { 0x4283ec01d52af80bL,0xac9dc35f99076245L,0x38785f7bd64c3dd8L, + 0xca19c17623bf8915L,0xd778291370478260L,0xc1e48e6816e34149L } }, + /* 16 << 364 */ + { { 0x707656834fc11c3aL,0x53a9403166aac4d1L,0x2a935ef0a6db6169L, + 0x002927612032d599L,0xb5babb2d3a6f1316L,0x601a7dfadb26af51L }, + { 0x00c340131322d983L,0x45b062ec2bb507c5L,0xa1bbe2ed0f9b3656L, + 0xe17a5d4934031d18L,0xe3661047f8fe1224L,0x0e4f3b3d623c6cf5L } }, + /* 17 << 364 */ + { { 0xb335d83c7c3b8c3cL,0x01eb94f059359a67L,0x3a8359a6aef3ffa0L, + 0xb0270076ecd2d862L,0xc946b1610377e30eL,0x9a5506c282bd6ae1L }, + { 0x737bdad0218512dbL,0x449238633487fb13L,0x36026dd12a8e7907L, + 0xb67bdc80784811eeL,0x9f92cc2405c90646L,0x02c551554c370746L } }, + /* 18 << 364 */ + { { 0xffaac084ca45cccfL,0xaea5cc3d061ffe3cL,0x7c5d7c60b355f387L, + 0x4bbb2a0c99cba92dL,0x6b4ba3ef2f7768d6L,0xc7484ed2cc5f9c40L }, + { 0x5d4e92fc52b57a7eL,0xba9f16c4ca2c200bL,0xebe02a8a3797ccbaL, + 0xb6b3f42138c4133aL,0xad5d85b68153d033L,0x782d6ee85714f269L } }, + /* 19 << 364 */ + { { 0x4654991087f226ccL,0x97894d5fc7bfffcbL,0x94f67786b3cabb83L, + 0xa6abaa960d788dc4L,0x08ae72d61723738dL,0x5003f41d86704dfeL }, + { 0x67687c3d40fb0a3cL,0x6fdc98c9b43320aeL,0x0f22572fdeb08964L, + 0x05bb02a4c8002624L,0x4c5adb7f987c2991L,0x3f1c6dddef4e60cdL } }, + /* 20 << 364 */ + { { 0x7845b6969c0cf752L,0xb82d052b5a732acfL,0x7760564c1262877bL, + 0x29b3c57a8ecc7aa5L,0xb58eccb0df1ebbedL,0x86fc15443c3a3303L }, + { 0x44761ddf13060f0eL,0x5a3dacfd7371a5a8L,0x846f6faaf7cbc2bcL, + 0xf5e098b0368caabfL,0xe23ea10710c08769L,0xbc5df1db1563fcdaL } }, + /* 21 << 364 */ + { { 0x75647f6476638edbL,0xb76ceb04aad6e25bL,0x33c73367d9393a41L, + 0x8396726dc55f0feeL,0xe1cbd48e751b3d43L,0xb779c5bdf47141a3L }, + { 0x122b85434eab6097L,0xeabacf45e08c6fa4L,0xdb32eab7769f49cfL, + 0xf956976a04ac2cb4L,0xf55c6fcb5ea8e71aL,0xd72940dfbad47ea9L } }, + /* 22 << 364 */ + { { 0x65c3a54e142d8955L,0x5c6583cce7814f25L,0xbd5a07d8d924dc7dL, + 0x9f717bd9c28f6e8eL,0xa0c4ec4e3b6540a7L,0x3153bb2b142b3283L }, + { 0x53bf403c9b296946L,0x659a828ab1cdb6d2L,0xe9517d811369af19L, + 0xd8c7a0998990e7a0L,0xbaa9f59de535cd04L,0xbb0cc68e0f269551L } }, + /* 23 << 364 */ + { { 0x2b4a0e69d0cd5fc2L,0xeb8dd25981167a94L,0x356198ae61b73503L, + 0xb159ca12e5289d45L,0x99d71c97991765b5L,0xce3a3b6c198e10b0L }, + { 0xcf6ee0bcafbb512eL,0x4aadd1381e19b49aL,0xcf6a9cf3b4806f0aL, + 0x6aff0386ad688bb4L,0xea487c6e4f2e5065L,0xec200f4b56573b51L } }, + /* 24 << 364 */ + { { 0x3c00ac526a78c6e5L,0x9c61aca6defaa52cL,0x0034128939794a09L, + 0xe08910d141cd7c0aL,0xa58ffbb6a732e3bcL,0x87bf51ab91fe8fd8L }, + { 0xc4f4f2674a59e2beL,0xdeb512c7438071c8L,0xddf82842e9cd290bL, + 0x3e17311d6ae85fe0L,0x6e9236a9b41be881L,0xbb9ddf9853555ebfL } }, + /* 25 << 364 */ + { { 0x07d2df1162bb0e3aL,0xe74ce211ce469affL,0x9629d7d4756b5a83L, + 0x61d2a633aefd449eL,0xd39a6afe491e503bL,0x0f1568d14d2b2ed7L }, + { 0x8216304cd19611bbL,0x6df99bbeb27388daL,0x2b0f60c0b7a3b4beL, + 0xcff84c1c7dadf840L,0x470201e28a9f8a49L,0xcda3693c21afc717L } }, + /* 26 << 364 */ + { { 0xccc163ea09f3f0beL,0x9932b56f6a5b0a63L,0xf89fae919c69668eL, + 0x555f98215ce13021L,0x4b02693f37037aa9L,0xc4afee79bde50f35L }, + { 0x4b0919c202aa6c7aL,0x3166de2a991e15e9L,0x284baa3e7077fb38L, + 0xbb7a6416a116ddecL,0xe8c89547b7636772L,0xff9403620ef92c54L } }, + /* 27 << 364 */ + { { 0xcd183e8bd3ea4c3cL,0xc8ce2f2154b7ac32L,0x75387e04be960826L, + 0xaf878400f2e39f5dL,0x7fcefcd94fa628f7L,0x76eb621c34582cbbL }, + { 0x44e1f848f29d2496L,0x42aa36174ab4eb21L,0x43cead840c08b50aL, + 0xfa4ecf60dd44f7c2L,0x5ac9ffd59f817546L,0xec11567eabcc594dL } }, + /* 28 << 364 */ + { { 0xd5d81275e2ce6008L,0xc45bdf250b3b9d10L,0x15ab5da36cbc83e2L, + 0x85a18cf8c52a66cbL,0x77e202b8b042c047L,0xc4dc3de2e7e7997eL }, + { 0xfe9335b1995fa67aL,0x809e161d75b96a00L,0xfb03c2a5a0c3baeaL, + 0x5c7e0523888c2f77L,0xa8fda1c887ad10e2L,0x90484f78858a3577L } }, + /* 29 << 364 */ + { { 0xefc5aa2681bf26c9L,0xdbe91f606bf105bcL,0x0d70c4d4369dd3aaL, + 0x2b357b847af9bf66L,0x4293e9a01f27f163L,0xc846f67cb3eaeddeL }, + { 0x4556bb787da305dfL,0x4ecebf83a5a26bf9L,0x8e05af924c1bc430L, + 0x4f3bdaba70f80402L,0xccaccfd3cf204577L,0x8fdee135a0c42d1aL } }, + /* 30 << 364 */ + { { 0x49e41f0af9fde126L,0xec9600443613d3c2L,0x2c62a49d10421d3bL, + 0xe24024648131a0d8L,0x8a7ce188bdf794fcL,0x704dea7d4665b1b6L }, + { 0xbdb9c18e4d57c6baL,0x5288a053f669b3c0L,0xbf7d01b878a5e252L, + 0xb26cccf926b9cb7dL,0x14191a3284326c47L,0x460ff74791f8425bL } }, + /* 31 << 364 */ + { { 0xb9958c5397698b9bL,0xe1f74292c27f96ffL,0x172b0d50806da6bfL, + 0xaf3d889ddd38b97eL,0xe7a75ea409c688daL,0x1f0951b85c631b2aL }, + { 0xdad8b2adda1c111eL,0xbacb9cc832813338L,0x30b8336b10582abaL, + 0x0ff3d7549494e71cL,0x8d99be5cd663ed6dL,0x8eb412cf7073a941L } }, + /* 32 << 364 */ + { { 0x59367582bd27be7bL,0x92bf5bbc1ab2c596L,0x5d96351af6a27741L, + 0xeab94db87f929e0dL,0x865ba011043f1afbL,0x43acea125fb631ddL }, + { 0x192e0652b2fd1436L,0x44f22ff17b38d121L,0x7bcc228db7cae5f6L, + 0x02eaeccd6a828b03L,0x7c48a2ea91f301aaL,0x1e090717f5eb1a07L } }, + /* 33 << 364 */ + { { 0x4c7f41b4609c6818L,0x978c2a561c82b3c4L,0x68404f1d7f6ba836L, + 0x91e056d0c863aa7cL,0x0b24599ba2261804L,0x16e9060dcdd7596fL }, + { 0x42aa49434eff004eL,0xb99408690438f1e4L,0x28299e8581775712L, + 0x498998eb83be6877L,0x84273d9e91328a67L,0xb7e9076e9a87bc8cL } }, + /* 34 << 364 */ + { { 0xe8d204865e5aea08L,0xaa946076addc7ba0L,0xc0153a9bb6a5cabdL, + 0x622271bd4fbe43e0L,0x44de159cbd62e5cfL,0xefca41112b9b63f8L }, + { 0x30774d3cf5269928L,0x4fbb7ff84ac0c8b6L,0xe0611f1f8839106aL, + 0x5d4121204ffa4a64L,0x9552c123e86251c0L,0x57d029680efbdb14L } }, + /* 35 << 364 */ + { { 0xdf3f8e06d7aeacd2L,0x725b25fe4d0e7af3L,0x1794f0da5c17392dL, + 0xabc807dac977ff46L,0xd90e6c8f0d5ca66fL,0xaf8eb526c2d26d49L }, + { 0x4661962e8a8efa37L,0x2a2cbeade87ad53aL,0xa57d34b1ce3ff40fL, + 0x1190437dc6aa3067L,0x92c31e779db66b47L,0x86a8ee0f8e8a70d4L } }, + /* 36 << 364 */ + { { 0x7b65bb14de97229eL,0xad6e3fee4c6d35b8L,0xfcbbf6afbee3f5d8L, + 0xb51549ca4a438fe3L,0xe66e615d437d531dL,0x9ee793eabf168624L }, + { 0x796789b0f8878a84L,0x3d38950dd32ec2ecL,0x74c37196a638d45bL, + 0x35d318327aeedaf0L,0x082c44f046a001e5L,0x93fae5cf89886220L } }, + /* 37 << 364 */ + { { 0x8e585fea499b635cL,0x60afcb3566781e83L,0x06594d9267482257L, + 0xb9f6101128773448L,0xba9ef7102817fd2aL,0x494e05b2aad046c8L }, + { 0x65d804fc1614e265L,0x1b0884c6d97fe002L,0xd7d34f60875bcc2dL, + 0xf34725444b440852L,0x49386bfb95591325L,0xe3966f4ccf68a142L } }, + /* 38 << 364 */ + { { 0xa5f3bc6cea06320dL,0x1bf855c637ad6e7eL,0xce7ff06ec58befadL, + 0xcf0d22cf1c2c0478L,0xf53e473e75616621L,0x00539f8700829986L }, + { 0x45398355844866d3L,0xbade46a2d710bc63L,0x6b3da567d4e2641fL, + 0xff70185978fd963cL,0x2eefaabaa5bc18a6L,0x61eeca92eb64cd49L } }, + /* 39 << 364 */ + { { 0xdf7c7c0b4cd4c82fL,0x67a26a97188ab9dcL,0x58c5bd74dd189cebL, + 0x3e1e93a9bb6409f2L,0x0d18a8bca6bb744bL,0xad3eafb45328dcf0L }, + { 0xacd15db5e311dfe8L,0x13a1c10ac1e849bdL,0xfaaa7227e1e73aa5L, + 0xa4cd2400e33d4665L,0xb9be68d9d6d527b4L,0xfe282bc05efbfc40L } }, + /* 40 << 364 */ + { { 0x159b38e17f8fd522L,0xf3ea27b5755e2bd8L,0xfaa52efebf11ac90L, + 0xc2014b892cb9f6dfL,0xa711c179d8baa5d6L,0x5474c1ceb22c2f27L }, + { 0x3cbc74cb031d05d9L,0xddd97ca6c44e469aL,0x21b386a647db83e5L, + 0xd1431c7b7abc0595L,0xbc05d009a416a325L,0x1c29eb709da53e92L } }, + /* 41 << 364 */ + { { 0x7f1aaf98181ce8a0L,0xa890cd3b6caa5b6cL,0x5d78dfaa5fbeac66L, + 0x36c63cef3d3d4594L,0x6f89ac3ec36d117aL,0xce9095640fc90e27L }, + { 0xaa356b1ac127aa76L,0xfa42cc119d181455L,0xbe4622fcd27f5ab7L, + 0x58d924542c3d54f7L,0x78a84f6b07e93c24L,0x5bf7cd278bce9a46L } }, + /* 42 << 364 */ + { { 0x4bde9ce5f810db3bL,0xec4a74b7281552edL,0xf5b4fa5fee085bb0L, + 0xb07a62936192c8b2L,0x163ff0d1fb18d219L,0x8d4b5e1d8e0ce753L }, + { 0xbfa6211baebcbf50L,0x1ed6d4b4fecc19eeL,0xbf6d514b82393e94L, + 0x90b356c1711e7d6fL,0x87b28dc2f975139bL,0xc41900648d8bebe9L } }, + /* 43 << 364 */ + { { 0x3468af53e8d49368L,0xa0a07369ff825262L,0xfad134fd662958f7L, + 0x5be79c00ce900822L,0x4909a56c44bde5abL,0xc2e8c4df4862e335L }, + { 0xd5e9b9386e7e41f5L,0xd3828d424fe474afL,0x058b2723cef44adaL, + 0xc74ac74617eebe66L,0xc3e6e014bca4416cL,0x2e30bc88167c2e86L } }, + /* 44 << 364 */ + { { 0x68211ba4969c2c58L,0x7a34733977f218e4L,0x0237eb3696ea1d64L, + 0xdc97f94b7416f3caL,0x63aa82e476bf9e52L,0x4b88a32d388465baL }, + { 0x7322d9f44adc7579L,0x70c01c7fb24d28f6L,0xdf7f4213c7517ecaL, + 0x42c027f0a8db6d56L,0x2708360eb6c2f8baL,0xf20690d1c2dde09eL } }, + /* 45 << 364 */ + { { 0xf139c3e3bc6158ceL,0x19207b6a4c86b780L,0x55af3eb977c036b1L, + 0xd192686abd563ebdL,0x8bd0afb05550266dL,0xaaa7376d83bf81bfL }, + { 0x26aa74ae4a114541L,0xd92549dfbb6745ecL,0x6ad6a14ec6bbfbd0L, + 0x63fee75b411771f3L,0x111ae3101938e8b5L,0xce3e5e346c363756L } }, + /* 46 << 364 */ + { { 0x2a53c88ae0a45b56L,0x26367466da72228fL,0xdd65516edfdbb135L, + 0x5fe254e82d7e37bfL,0xc0f5cbe433ef39e3L,0x249b7e3ece85effeL }, + { 0x85951a5391ffba8aL,0x41117672c8dd5ec6L,0x7a74538d9dbb0761L, + 0x0b35fba0cfb06ddcL,0x8c36be4d1a0aca2aL,0xbf884a8e45848e1dL } }, + /* 47 << 364 */ + { { 0x191eef31788596c8L,0xa7413be65a2d0ef8L,0x30894fcc5c3c09e1L, + 0x6b0e429b2f72a333L,0xceea52a1e70470e2L,0xfc638b316b682db2L }, + { 0x31af73cd615f7f21L,0xb31663760094996eL,0x7ec37e33dfff756dL, + 0x38c50101d9b63a4cL,0xa517c6df192f18e4L,0xd674c53a841fb337L } }, + /* 48 << 364 */ + { { 0x4dd3bd842446fc6aL,0x4654b82ef25ab510L,0x1ad46998ba066896L, + 0xb7c679acad713bbdL,0xef9389aff7ca4fa5L,0x1b864105d68b6a1cL }, + { 0x3acfff604b6f5ea4L,0x81ef58f7b9e5a475L,0x5e2f6441c66ad734L, + 0x49f144c42fd3eb16L,0xbd7f22082e4e2117L,0x30865994417911a3L } }, + /* 49 << 364 */ + { { 0xc2f25d9e80d2adb5L,0xa0e77dc5242430feL,0x7f30e54b4f504e97L, + 0xdc114db4680ca2cbL,0xf76fae57adec4d89L,0x06f892eff313535fL }, + { 0x50af729a9a266407L,0xb0cbc4f0764dffd1L,0x153ff8f8d20c2e19L, + 0x27fa845a7388d22fL,0x26e08ef5d784e057L,0xccbe49ee53b5dfc0L } }, + /* 50 << 364 */ + { { 0x6fa8e5ff3082ceb5L,0x81f4dd02ef4850ccL,0x626b324456483f9aL, + 0xc0acbd8782e65652L,0xf9bef3117e23f93eL,0xc2474777c2310f6fL }, + { 0x6b4617704379fd64L,0x2f8fc599f18c3b14L,0x2287f1d0bd076aedL, + 0x9f8eac0fef366016L,0x517cd2e371fd845dL,0x0fc2f219a30c371dL } }, + /* 51 << 364 */ + { { 0xfea0464721c56ce8L,0x4f7b055b6a32a26bL,0xf8c8d93e487ed396L, + 0xe620b440855f4df9L,0xa3f6f21dea870c14L,0x0518225207dad127L }, + { 0xbdfb7b12c68ab5f6L,0x5f58bdd7fc68f296L,0x2df9cfc505e4fdc2L, + 0xed12a102379c282cL,0xd388362654d8de77L,0xaefb0f7fb01065afL } }, + /* 52 << 364 */ + { { 0xdc64f8d23d80d738L,0x7ae74ab1d95a1c6dL,0x4dba93a8dd46de0dL, + 0x271aeb870fddbd1dL,0x1bab6546e9e7ed31L,0xe6445d22efec8f37L }, + { 0xd927df1797a718a7L,0x738c2450351b1ceaL,0x3809e595d51a7422L, + 0x4f8d5ea58969456cL,0x74d9168421c9ad95L,0x59a69f8f4f796a11L } }, + /* 53 << 364 */ + { { 0x2542fcf1f07717aaL,0x032abb3f405a7717L,0xc757e6e294cade8cL, + 0xad4776adf2e84dd1L,0xb7e277243d5e397bL,0x173894a605f8921cL }, + { 0x0e3a78531f6afc3fL,0xf33732b8ad62482fL,0xa6b4e0f03e4cb6e9L, + 0x51ba565eda02264aL,0xd0afaa4600f3f376L,0xf5506a1e35252e93L } }, + /* 54 << 364 */ + { { 0x3574783b5ea1c662L,0x675894e514fadc8dL,0x64dd63935ac6ea7fL, + 0xa76c00dc77f16c96L,0xf73ef2c62eb9574cL,0xdd39a89a2e408008L }, + { 0xbef8c8c72bafa10bL,0xa31f030a074733f8L,0x5620dda5445b4b6dL, + 0x4e08fb0173040ab8L,0x0a279f38598ad48aL,0x03e8b55e2d40d775L } }, + /* 55 << 364 */ + { { 0xf49d4d54c20c8610L,0x1b1d70bbc0d62b65L,0x524d3a0c16285ce2L, + 0x0be553b08a0785b4L,0x9b93e5093c84975aL,0xbeac761160769465L }, + { 0xffaaffcb3331dd0aL,0xad0f01542d70fcf1L,0x65aaabab66fe24bcL, + 0x283edb562cab253eL,0x1659deca80383c87L,0x06de45fd83fc6d7cL } }, + /* 56 << 364 */ + { { 0x7bcb055d5f76c311L,0xdb2d05878e293aaaL,0xb15036e7207360b4L, + 0xbc38cc9f163f0ae4L,0x5a942f85a44d0a0eL,0xee8633a23f553a88L }, + { 0xf66b65c5c9bd4ee7L,0x7a4ca96a80b8ceefL,0x7b71cc55f6f08036L, + 0xc0408b198c41be7cL,0x885fd72f80860d93L,0x338a567be7f68b7bL } }, + /* 57 << 364 */ + { { 0xcba302e939d99b60L,0x2557b3d903b8faa0L,0x2a99cd6e9efc4461L, + 0x03ce3e08268f14a3L,0x59226a83b1c68a01L,0x81a18c69fe379976L }, + { 0xfdfc9f148af62557L,0x0cdf327140b2d4ebL,0xf99ff3ded26c6085L, + 0x2c138ffdf9b0273cL,0x393d6de6888dfbd3L,0x75903c68e5cc102bL } }, + /* 58 << 364 */ + { { 0x0c56d477b78a7b91L,0xbedff933c7c3ecf4L,0xe02da64223ead65aL, + 0xf7e7cc19a8162300L,0x3719fb8f2f3dbd03L,0x4f150cb8cff88c59L }, + { 0xa564c5eda7fcb233L,0x9b042870b6a41ca7L,0xf253b65ac1615f1aL, + 0x9ccb49a7b8aaff46L,0x38bbc5f7af0086fdL,0x688f7c2054a6d8a9L } }, + /* 59 << 364 */ + { { 0x3702c5e5d22a0892L,0xf17510a28d510809L,0x5c36dc68bfdab4e7L, + 0xf72c9357623a98e4L,0xc660fc5146624a0cL,0xf0b4983d3e64dd4cL }, + { 0x5cb98cc9a5ecf45eL,0x79759acdf5082a78L,0xfd0daf366e7321dfL, + 0xf61c54f7f1ebcacaL,0x782e5e74b8f665c4L,0xb1d54c2145d78c08L } }, + /* 60 << 364 */ + { { 0xb64f3b9bef1af123L,0xc86dc5ffe1b75401L,0xc3a76d81d928e989L, + 0x075005abff8ca002L,0xca6226325c3cd8b1L,0x017a97b2bd8f772aL }, + { 0x187eb635039c4757L,0x9eb7a9d1e905c6e5L,0xdacb98bfbc251cceL, + 0xe357c60e8704c639L,0x50563b8558fd987aL,0xb2f89c864cea5d4bL } }, + /* 61 << 364 */ + { { 0x3d13c0bfd32233faL,0x997c424145aceb7cL,0x77ff5a75ed2e9df0L, + 0xc4279aa23c91d085L,0x5a11a276ca0392c7L,0x928e06032daae653L }, + { 0x21fe225fc4046f85L,0x591fa82f512dbfb4L,0xb5b01a3f51aa53feL, + 0x900012ef7133befbL,0x24609da17130c15dL,0x3c4a09b33d2549faL } }, + /* 62 << 364 */ + { { 0xcdd3073d3ceabe32L,0x56e155bc5a848977L,0x07f4c7c6da48eef6L, + 0x00a2f9f79e021b38L,0xeb683e17ffc4bd6bL,0xa7d6b87592b7e240L }, + { 0x651d21de7e48836eL,0xf9c9ede775de3c75L,0x72cea748d90f2634L, + 0x29d8022283fc524aL,0x1e412b510dd044faL,0x1b9b332a76a04fdfL } }, + /* 63 << 364 */ + { { 0x4dc8421f06f49d8cL,0x6a3fd9a83f979e4cL,0x50b0e3760b51bd69L, + 0xec22f486a592313eL,0x5e4663ff8e8904d4L,0xde7b9e23f3362548L }, + { 0xa1ad270d1ab757abL,0xb91fd935a3089f6aL,0x1d6b1524a635f996L, + 0x8673f8e29c718c6dL,0x0e04360725932b9fL,0xb5d0447222ac239fL } }, + /* 64 << 364 */ + { { 0xdf0ae8df941948e3L,0x123fee901d010bcdL,0xde3717ca1dd28691L, + 0x0c1db879709b678eL,0x0288959a400acdc6L,0x66c691815ca2d03aL }, + { 0xe52534b3dbbb75deL,0xe914938c3de927cfL,0x1a9a34f873eece30L, + 0x0fb0c7bd642a6799L,0x375cc0cfeaa7e8a8L,0x75fb9eb5d00ec238L } }, + /* 0 << 371 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 371 */ + { { 0x9ca8cc9db72958ebL,0x3c8cd0db1014f562L,0x72115d53059b2bbaL, + 0x8fe7ac30730e5dc3L,0x4e67ef69841d8998L,0xfb6439ffc8ed37a5L }, + { 0x48164b3e26df84c4L,0x37d492ad365bc99eL,0xb7fd4643beed38ceL, + 0x993cfa9fa3e30b3dL,0xdcc5e7af01ddd484L,0x5edf3ac06840175dL } }, + /* 2 << 371 */ + { { 0x79768e9f51d33c11L,0xeec34505a4b24889L,0xc194821bbe0c67d7L, + 0x537a6a4a6909fdfcL,0xae6d705195ccdda7L,0xed4b722292b3926cL }, + { 0x2c5dd6af6b24a3d4L,0x9282ec39e4386095L,0xdd3c7388397a3bd3L, + 0x9d176c6a8baf59c2L,0xd5c6219e380ec958L,0x194fc11654e8e315L } }, + /* 3 << 371 */ + { { 0x0b7576f901ec1432L,0x84b30eecabc5f603L,0xdaaf7ba9f4a84b7aL, + 0x9e3a5daa3bb37a99L,0x56bd964880378cffL,0x2fdeeeb78e6ed856L }, + { 0x079014a73c81ac34L,0xf8de4004b4211c27L,0x0cee3df97fe4391eL, + 0x441aa7fb2fd2fc38L,0xeba7be864d1b575aL,0xca2fb5b7231c2d01L } }, + /* 4 << 371 */ + { { 0x0683349e463a8251L,0x97dc4f475103e72cL,0x47c7181050663b9eL, + 0xf327d1499733dac6L,0x03f55e4a292137c5L,0xccc6232ada59e1c7L }, + { 0xbaa8b4ddadc59cb8L,0x45370d35fe7486e4L,0x99a88c1db0322df9L, + 0x394440a7fd69954fL,0x9060473da5a29889L,0xc8ca43e32f04864aL } }, + /* 5 << 371 */ + { { 0xd5c7241add8b9644L,0x45a5f2d1993116d2L,0xbacacd4a823048dfL, + 0xa278fa042568547aL,0x3a4f2482bff72820L,0x1305d1a713e4314aL }, + { 0x9d84c33334ba28e3L,0x9995b5bb6a32fb41L,0xb0f75f3c520946d8L, + 0xd7c4b8b7de98aa63L,0xee5efcf3ba856b6bL,0x36af33683324ed66L } }, + /* 6 << 371 */ + { { 0x90762c1f5827fe2cL,0x20160f7aeaffda88L,0x7420849f5c47c645L, + 0xb08231956d72e748L,0xaeac683b8ee11773L,0x8c2a0a79fb5c550eL }, + { 0x6d986d696c07cc1eL,0x57269140ba8398b9L,0xd13e136fd94d5223L, + 0x1aa75419ed5b01c6L,0x7c2014b1408fcdccL,0x0680a985cffde5eeL } }, + /* 7 << 371 */ + { { 0x92fc9a3342c5a7eeL,0x8768614af9f0ed71L,0x1ea5f7ed87ebfb66L, + 0x296852ded361069cL,0x1cec6f1a0192498eL,0xbfd4858fa9cca3aaL }, + { 0xfba98c242ef240e8L,0xc8b500e4ab635d9fL,0x9f49c572913a3eddL, + 0xe6181f93d42b2d4dL,0xf96b5db26aa77fa3L,0xdfb2241fe43558d8L } }, + /* 8 << 371 */ + { { 0xc7d0abb2edee15a5L,0x72dc0105228cc4a1L,0xeb67defca80767deL, + 0x6fa174d871820908L,0x3215df485674d19aL,0xf944531a960a081aL }, + { 0x93ed7180ef2cce62L,0xb318edbfc8bcfc0dL,0x0909d56efe787e58L, + 0x5ae74fc98fe8b96fL,0x8fc342c435ab6811L,0x6fc6cc5c0b991e0cL } }, + /* 9 << 371 */ + { { 0xa8eaba6e291f689dL,0xfbfa9a2cdea0cba9L,0x5b1b4a21727bfa11L, + 0x3b69505fac59c8c4L,0xb06290c89368ddb2L,0x4181abc294bcc14aL }, + { 0xa19f65813e29d997L,0xab1ae8408864aac2L,0xb04a24300fcc9ae8L, + 0x3ca2428e1059e4dbL,0xe288731117e1e01dL,0x1f5d4164be56238fL } }, + /* 10 << 371 */ + { { 0xc600dd57354416d9L,0x6f5840991f829d6bL,0x2d7b0a27de43c1d6L, + 0x21bf3a9e616bdb16L,0x33ce767c96297953L,0x99bf97b69e4398b2L }, + { 0x4069cced8d441287L,0x52e0edd6bf01017dL,0x9981bf89c5394236L, + 0x07d9c079acb24e38L,0xd2e5e904a2da4735L,0x4c3c12162f1b6cd9L } }, + /* 11 << 371 */ + { { 0x1f28bd0de6f1c85cL,0x4a49d0864e6f3db6L,0xc9a8e70c4ef7d981L, + 0xde8abcf2682bc68eL,0xd0ef89a4a66cbee3L,0xfa03108432df7f0fL }, + { 0xe361e0f803594856L,0x1f423bafc985c77fL,0x50397b67010ee4acL, + 0x502f4a20c0a48e96L,0x260bed875435539eL,0xdae03cefa0391250L } }, + /* 12 << 371 */ + { { 0xfeecc6e83be5ba68L,0x3293dbda40445158L,0x48454e20e81879caL, + 0xd0ea9cb89c4a2712L,0xba8b6f33540749c3L,0x95e6d6e3e971df93L }, + { 0x4c2a1b13478a2eb5L,0x8b5f9af330b92170L,0xe6c60b5343573986L, + 0xb9f56a6a57040c00L,0x6de6489f6291a7b4L,0xa9a7784653bc3246L } }, + /* 13 << 371 */ + { { 0x0dd4172f9025411fL,0x978e952ac6129de8L,0x9afa974bc7ab7609L, + 0x7bd29a644e42f223L,0xc0232f5f3deb639bL,0xacce69d05f39a264L }, + { 0xdaee07cb3070b24cL,0xe3adc8556b532246L,0xae5935ce1e6ee4f6L, + 0xba9c4329ea018a45L,0xa1a4002e6b97ee9dL,0x98390aab8a9460cbL } }, + /* 14 << 371 */ + { { 0x828a9dbe67154a02L,0x57a3af981866aadfL,0x1558428089faa581L, + 0x2da092202dba2a1dL,0xa225f631df197ae6L,0x0abff5cf8f4ebabbL }, + { 0xbbadc9b3b98e5e4eL,0x7c7cc36e4509f98fL,0x072a6cc2759413f6L, + 0x7b39ea4121dd1222L,0xd6baf9e196ac2c73L,0xee38818c75d46296L } }, + /* 15 << 371 */ + { { 0x19befeacfa37c53fL,0x32c29b361f95c29aL,0x1d282db40d5aeafdL, + 0x8812b6c8f102a97eL,0x1cd4a23c8402f481L,0xbfdf7b6b8eddec81L }, + { 0xc8039ae0616b2654L,0xdc6f38acabd23a57L,0x2431c763f147dd44L, + 0x7c45ed50d795bc37L,0xdbc30ab9842022aeL,0x568f7d4ba1f05a43L } }, + /* 16 << 371 */ + { { 0x55671129542f4e90L,0x43bedccf0623d4cdL,0x7e21207ce99ca16bL, + 0x785fa1057c7a26b9L,0x33c28658c2c3ab00L,0xcce42a48d79cd59fL }, + { 0x9a674db4b8c3bc75L,0xea701d156904e3feL,0x990e722166bf2c6cL, + 0xba29affabd4c3791L,0xd98510cf20696ee1L,0x722ed471f93d26a5L } }, + /* 17 << 371 */ + { { 0x74e6c2624ba40f04L,0xf7ad1f159a63b3c2L,0xa89e8490ef75d482L, + 0xaf8e79b83bb5f5c4L,0xb094f8660c624d8aL,0xb571ce6613c69a60L }, + { 0xcbf9722d53787457L,0x97e24cf5c15d097fL,0xdba98bede99e034bL, + 0x8b6c171a57773590L,0x5d2b441cfe822efbL,0xb8c6dc57fc74ef1aL } }, + /* 18 << 371 */ + { { 0x37c70bdf7db1c03fL,0xd9368612964632abL,0xcf6368d742530338L, + 0xe56beecbb1d9522eL,0xb1caaf16bb6fba3aL,0xb7bd485ac8384d26L }, + { 0x4ba13818528d4372L,0x95c469bab9c5e8f6L,0x4e5cef0c4a370695L, + 0xb87c97ca663f9b07L,0xa9e1b388e5f3b79aL,0xc0416bb84c845a1bL } }, + /* 19 << 371 */ + { { 0x4483db00e4634d8dL,0x4d8d623d0a268bd8L,0x296f179c64e6d10aL, + 0x048f3a1cb6c7ff95L,0x60f8ad62c60c76d1L,0xa0a497610d028845L }, + { 0x10128387aea1b714L,0x81e5c75ca18bd98cL,0xac30d7361dac4200L, + 0xb83c1c12821380f1L,0xc8ca7c6afaaeb726L,0x13fb870dfead4cfbL } }, + /* 20 << 371 */ + { { 0x3921332a6b393648L,0x49ec6df649584f38L,0xa0fc013dce243a6cL, + 0xde5b16b5f8da8a00L,0xabcd0c0471ab1c9aL,0xff6594bc78b83305L }, + { 0x3546004b76c1900bL,0x87428fa236fb3186L,0xd2e464ce59cdeb49L, + 0x1260bd28faf6ec08L,0x1ada2f08d0c9d098L,0xe0b66299dea06396L } }, + /* 21 << 371 */ + { { 0x603d58167c1212e8L,0x95bb823fa4590144L,0xf239058a4bc3ba48L, + 0x21f2aa610db724b3L,0x29c706e8cd6792a2L,0xb143a84a634f01e6L }, + { 0x68f37382626ee80eL,0x56daa0e51fcd8c4aL,0xe01b52b39e5299a5L, + 0x2224513c3accdac7L,0xbb21c7d74acd435fL,0x039bc010bbcb948aL } }, + /* 22 << 371 */ + { { 0x5006c3a00848d6b7L,0x726b8648b28285aeL,0x7162e3c0277c5a87L, + 0x567f7ab02019c20aL,0x490c858fa551d5efL,0x0029a108d134a2bbL }, + { 0xa9e19284ef0aca3cL,0xbc399dc16e414f83L,0x5bdf85f86efa5a8eL, + 0x5291e1a674fe7c5fL,0x249ddf2acd7091dfL,0x71d4cb4c2e29fcf6L } }, + /* 23 << 371 */ + { { 0xc374acf4c1ded13cL,0x300d96132b69132cL,0x909ce34b055622d2L, + 0x26f033f6bad97809L,0x30987ebed1f7a220L,0x23147226db775b8cL }, + { 0x8d45c2c28d05ecfdL,0xeee0c679f0c1b419L,0x9f7df70d8c380da2L, + 0x4d49f3d130212a25L,0xa9602e8c64491ff3L,0x5ab91d223a254c49L } }, + /* 24 << 371 */ + { { 0xedd3291c9dac47a9L,0x02d64634fb5d396dL,0x2ce21bf163264c51L, + 0x0fdcc68e092c4724L,0x653acb286e3e4c2fL,0x2f9c77f12f1fa1edL }, + { 0xd91d4c3aa58afea2L,0x5a91b2ba7b0d8092L,0xd47e0f61f10a15fdL, + 0x01652d86f9c86edeL,0x1cc1b668d6006daeL,0x2763e36d24af68beL } }, + /* 25 << 371 */ + { { 0xaa5f387c2314a1adL,0xb8c00105e2647c74L,0x1f950dd8d6719178L, + 0xb7dae31de79881efL,0xf2d49aa2e45a615eL,0xb22dc098f17352afL }, + { 0xa4c438728ac23ba4L,0xedd6e4092c55e588L,0x1956b199022f5632L, + 0x18adcaa58c11bc50L,0xa0c11f6458b1cbf5L,0xd1204377f961ce1fL } }, + /* 26 << 371 */ + { { 0x35a2685bbb77f5dcL,0x1b5b79bbc08efa67L,0x4ebec6e6ea5f411eL, + 0x1800a21988c57793L,0x8d7397f2cbb13c96L,0xbc13ac35dc0327f4L }, + { 0x53ac05a6fd94b150L,0xd898fa600423e787L,0x802aad2c2a66b97fL, + 0xb604ac0692c62b03L,0x9f395d3a45911e7dL,0x5d38164128ae56b6L } }, + /* 27 << 371 */ + { { 0xa7d5a3afa5fb0decL,0x0d11c0cd5b27e02dL,0x8d854b53366c6cc9L, + 0x87ef4c140ad9a5f5L,0xaf7c2e6b0c5f8acfL,0x81fc22b69f010f1aL }, + { 0xe49e0c7e4e25ddb3L,0xd30bc860ef233d23L,0x0b63afb89fa41205L, + 0xd14b326c702fea93L,0x10ab93662c2a5fc8L,0xab35bab356cfff28L } }, + /* 28 << 371 */ + { { 0xdf0f79524130138bL,0x117e4628934c58afL,0x227be6867b6a4087L, + 0xe73fb2f3b8d298a3L,0xe32e89fda9bacb9dL,0xdd3be6130e9ea7e3L }, + { 0xd3d655ead4da2d1eL,0x153cce647833bb3dL,0x4a32a9f0b36da20cL, + 0x025768e5a69c4b27L,0xb0b5da379cf1fcecL,0xd0ecaba23aa3b99eL } }, + /* 29 << 371 */ + { { 0x9ab6dae0aaf6b398L,0x2d50f46b4f8e270cL,0x46c1e676fd7b7005L, + 0x4b8b203e32cf8be9L,0x0253ec899451bca9L,0xc3a7eab7f512b7a5L }, + { 0xf3bed3fdc5bd61a6L,0x5c0eb52f0a37ef8aL,0xb61aee11140894dfL, + 0x690607f9bec928f6L,0xba2b1db65148b45cL,0xbd309bf56619b652L } }, + /* 30 << 371 */ + { { 0x79d624c7a7b92932L,0xcd086bd7cc75e7a8L,0x3cddc1bbb48eab26L, + 0x10282df1f6791cfdL,0xffedb4fb1048f114L,0x937ed0e7c092d899L }, + { 0x045e4f60b84b6d20L,0xdd67bd36877ed915L,0x9bf8fede97617aa9L, + 0xa7ff9b0789cb8e1aL,0xc49e310e74f4e7d6L,0x12dde0fb3f62eafeL } }, + /* 31 << 371 */ + { { 0xe2e3dc4d50ba6e73L,0x31c19ebce6114f87L,0x8df0ffb01ffa99b5L, + 0x305142f1bfcf7fbdL,0x39931954ab88b782L,0x1952bbab43de3650L }, + { 0xb32ed678aa09e528L,0xa5150011acee68ffL,0x0307716a97b98b23L, + 0xb60c3edd4fc8d2b7L,0x91c81725b2b2f887L,0xf1dfc70ab9fb0288L } }, + /* 32 << 371 */ + { { 0xe7cf5bacbc579793L,0x11db7ddfd73f881cL,0x9c1a531d04fa8473L, + 0x399e84845780efdaL,0x6e9c12be4f62cb5aL,0xf21bdc4994a5df3bL }, + { 0x3c15fe1211da2a4fL,0xdea123bb23e631d1L,0x3ef76da4be294c90L, + 0x5cf21d5aa99b8398L,0x50679cf8751b9f6aL,0x4b3f3b9c54d0b7bfL } }, + /* 33 << 371 */ + { { 0x442dc0fd27174604L,0x5aa056efebc95895L,0xbb8cf9b54c96a2dfL, + 0xf43342d440f8618bL,0x58b0d00a8f89a8bcL,0x74d32dbc81f69f20L }, + { 0x5caf0910ab22a49eL,0xa0e9a677ff372f3cL,0xec90b5aef5c05066L, + 0xe2d98821b663f0e1L,0x388804bf50c7abc2L,0x2fbab16e97ba64d3L } }, + /* 34 << 371 */ + { { 0x09138c6071ed8d4eL,0x994d0fa991ef82b1L,0xe6089dbb931f3193L, + 0xb3b229d0aac23611L,0x52cf03fdacb8affeL,0xf64f9872bd99d6e2L }, + { 0x52ebb8b40186279dL,0x36a2349fb09efd7aL,0xa85b5d802225772aL, + 0xd2dc3c1547522562L,0x659297a666471319L,0x65913b608c8e7b68L } }, + /* 35 << 371 */ + { { 0xd54591f9a713f82eL,0x0ecfcffc6fae64b7L,0x7df9d7ea7287e218L, + 0x8b260162abe71460L,0xf75097efb12d48beL,0x82d5902482581904L }, + { 0xc5c0b5dc400d4288L,0xf6493c78190f768cL,0x1844b5f895bc9fccL, + 0x24afb04ba615bff9L,0x6c9638ee8bf51197L,0x38bce012b9ab9fcaL } }, + /* 36 << 371 */ + { { 0x087a2790494efdc0L,0x0b5f23c9e1645cb8L,0xa6e1d1e8193a99baL, + 0x0d324e67c0e0c026L,0xa86d993820d608b5L,0x48ddfbfd8d6944dfL }, + { 0x6aa07f90d371864eL,0x5cf727eef2060df5L,0x7694e02c9a7cf2d0L, + 0xe091982f6260f63cL,0xd2d481a72cae5da6L,0x045e3685ebcb4172L } }, + /* 37 << 371 */ + { { 0x1765632323c82633L,0x5de90578d590cdd3L,0x5cc5e7b9525caf0aL, + 0xdd9be80dd53e825aL,0x9ed28b29949073f3L,0xd15024156a6ce0bcL }, + { 0xbc34beeabf355f49L,0x73724878d2b210ccL,0xe47b7af911e8122dL, + 0x381a4cccdf53a9eaL,0xaa22c9b229e8a466L,0x7a05e2081a4fa093L } }, + /* 38 << 371 */ + { { 0x3dfb53521830d848L,0xea183d5cd2820590L,0xc83a65bcabbeb376L, + 0x5d9ca4d189bb9ac9L,0xb32217be137c900aL,0xcc40daebb0827afdL }, + { 0xc76130060c58b0afL,0x39f4ed8adf32389dL,0x04a586e2bc1fe9f6L, + 0xcf018c2abb50450eL,0x5072b8f016d55d0dL,0xc3c72e90d59e1dbdL } }, + /* 39 << 371 */ + { { 0xb3291b4e50b4e9f4L,0x79a2e8121b7b9e08L,0x81855db1ddd5f0adL, + 0x91fa12fc884392e5L,0x6373de02291c5694L,0x15c77432a7171428L }, + { 0x6016a06c1132df9eL,0xa4286939a0c21c8fL,0x70c5ebe26dca3f37L, + 0xc5278c510f115497L,0x8f5b07a35ce1953cL,0x4d75c1dc41f6ac0dL } }, + /* 40 << 371 */ + { { 0xfeac8e8ac24002e7L,0xa43892076643fa6aL,0x06e7ed63daa68b52L, + 0x8580bbd5d8c7b952L,0xb17ce22410c8fe9dL,0x40266bd379b88ceaL }, + { 0x32afc840dd63ffa5L,0xb4a3eb27a2280b83L,0x90528bf685897e28L, + 0xe4612391d231f941L,0xa7b3a2ccacb5c909L,0x2606844e5558d57aL } }, + /* 41 << 371 */ + { { 0x49ad52380519dd66L,0xe1b0b03b3c1470f4L,0x15e42792cd3a4852L, + 0x91c954b7388ba040L,0xe9fd8c7f857711f1L,0x8552d3d44b63a36dL }, + { 0xbf867fde230ffab0L,0x362a32a0793f885dL,0x687802cba11e0225L, + 0xd95b073b308c1972L,0x13b104aa6b3e5120L,0x60bef12333673f57L } }, + /* 42 << 371 */ + { { 0x4c4cc5561c8a5d9fL,0x5c6e1fd52b8a42c9L,0x73fd66c44ccfa024L, + 0x73c777563c50d038L,0x26964a68a5076758L,0xb14cdbfa7484d080L }, + { 0x24c499cf3f4b92ccL,0x40c8c0d84682daa1L,0xaa156edf785561beL, + 0x36718fb6de75af0aL,0x4d391cee03f5b180L,0xcf28d08a3100efc8L } }, + /* 43 << 371 */ + { { 0xbf1fc9fdd113a97bL,0x19cee87f5ff5ff3cL,0xfc140acf8f8213a3L, + 0xe70d50d546127d5cL,0x78cd24032faa7ac9L,0x409675f1c1808096L }, + { 0xaa7b6cd91765da93L,0xc0755b924f508d86L,0x09b8fb7640169a6eL, + 0x9ca977e52e7da664L,0xee1aab6c9a9616daL,0x54d740391ca0f4fdL } }, + /* 44 << 371 */ + { { 0xfe011830c37c7fc5L,0x0b2b965b2ee958c7L,0x99fd253588a43cf6L, + 0x6a73d62dbf8dc33aL,0xd53c0241a99247deL,0xb8186dccb4127f94L }, + { 0x86c4c274964cc3d3L,0x2f3f2742cbfa9429L,0x5b4bd23c5391abd3L, + 0x030b211bc5838fe2L,0xd2263dc4ae2e36fbL,0x45583a3ca0bf7280L } }, + /* 45 << 371 */ + { { 0x9ce7f43f1ed3f49aL,0xd8094c4afcdce20cL,0xd8b423d12b37b162L, + 0x332ce47c53d90a7dL,0xc686fc0c94a38ff2L,0xb44938d6c33d842eL }, + { 0x5ed14772cd9b0002L,0xffa5d063e800c655L,0x4511ec79ffcb6120L, + 0xb8c9de3f9da8e70dL,0x4d0759ca952b0ef7L,0x685f7005dfd88f4cL } }, + /* 46 << 371 */ + { { 0xcbdb755f1dbdc85dL,0x63d0d7047961be6aL,0xf65af35d8220a1b3L, + 0x8dcea7df77db51b3L,0x8cb2c5d14bfe8fbeL,0x740579bdee2f03e0L }, + { 0xa7eeea4ed3f0181fL,0xedbdfaa3c12ef399L,0xee3cc40f1c332118L, + 0xdae0995e731ef93fL,0x05165c6c0f24d954L,0xcbcc014219fca63aL } }, + /* 47 << 371 */ + { { 0xff24bcd842c7c110L,0xa5ddfffc56dc10c6L,0xb9937fcdaa1a09c5L, + 0x8e18ed5b852dd22fL,0xf24e43c7826fb5a7L,0x13989a43415c2c63L }, + { 0x71ad7c21d36ffe0bL,0x68b77701129df418L,0x1c5324cd9a8d424aL, + 0x2e2a2b1ba9bf46abL,0x7d0c04d19cd0ea12L,0x8b4186bf2f9869e8L } }, + /* 48 << 371 */ + { { 0x6c8d97e075a46271L,0x0fa0c4cd9dbed39fL,0xfb6da5e2de74ac6cL, + 0x041ce886c17c1ec5L,0xb42941a8d7419105L,0x79768eee002fdfd5L }, + { 0x64849afd88c8111fL,0xf425fe14814192d6L,0xe916e8640448fd7eL, + 0x31e224ad72ed351fL,0x73e6e6ac7c0183c1L,0x375657c621bf7cebL } }, + /* 49 << 371 */ + { { 0x093d8039114fd7b9L,0xb6bed3eb45c5e1c7L,0xb73ab7fe50fdbf14L, + 0x68d95e57af0cd23dL,0x5c260eacc7b750fbL,0x79bb142bb5358c26L }, + { 0x5aa9845158ace251L,0x04b2388637dbfef5L,0x1051172dc0532263L, + 0x686ee9e6294890d9L,0x092617b3bffd1609L,0xb4a50e50ea3836a4L } }, + /* 50 << 371 */ + { { 0x8bdb3886cdf950abL,0xe2bdc8d3d595dbd5L,0xd28211254ecc49f1L, + 0x946566081d3c2f24L,0x8124ad390c87df6dL,0x6020c322d16272baL }, + { 0x2150f7e694af134bL,0x38512401a1a14e33L,0x39a54386b1ff7304L, + 0xfaf1ffea078d8f0fL,0x7739ea99dea995bfL,0x3252e815c020816eL } }, + /* 51 << 371 */ + { { 0x1609832322f1bd8dL,0x6b02533cd4df163fL,0x25108619a8296363L, + 0x373bf9988f8c755cL,0xebfbc5b23b32542dL,0x7ada597688b9d360L }, + { 0x3914406ebd605f01L,0xe245ba48cb3a40b2L,0x11a1dc4ed3171f32L, + 0x4a10d5d26ffb5915L,0x9326b23e997460b6L,0x53ddfee92aa0c77cL } }, + /* 52 << 371 */ + { { 0x44f51dd51104ed7fL,0xfca4773e270f6135L,0xe36c8b266bc757f4L, + 0x2cf0515d6941c7a0L,0xdeab655d5fb16e2aL,0x75c28116cff7be07L }, + { 0xb24ca428abbbca02L,0x6aaeca9b1e7f8116L,0x4252f4c3510f0c81L, + 0x01462d856f3ff7fcL,0x4df702879d1c25e3L,0xddd47a1dbebd1559L } }, + /* 53 << 371 */ + { { 0xdffaef2c6f2e2611L,0xc2c2e6a41f29efa2L,0xa29bc3b75ebb40c9L, + 0x8473594bac31a2c4L,0x100d7d6a8604447aL,0x80318670794bbab9L }, + { 0x78979f72054dfc75L,0x94b4c17e55232511L,0xac44836b78b883c3L, + 0xc1f7e98168422328L,0x34fcdee68266747cL,0x18533b3f0475c011L } }, + /* 54 << 371 */ + { { 0xede6728e3bab17f0L,0xfcd9c96879b94302L,0x6410ae37544a677bL, + 0xeacbf6de1dcd0fdeL,0xdae70841e2f3ac0fL,0xeea2a9b6e41ba13bL }, + { 0x1b06aeae9349cdf0L,0x28571e3d33c0ea87L,0xceaf9dd46043e874L, + 0x32cbcc69fa6fea15L,0x7db75664e135aa11L,0x588d4458f816929aL } }, + /* 55 << 371 */ + { { 0xf70797d02b014160L,0x1ddf312d8d7c3263L,0x3bdd58f3c78beacbL, + 0x8bccd90101c71f77L,0x3c637f58166c1486L,0xb62c0aa45fd1a307L }, + { 0xa68db7b05f2544d4L,0xb9727946f860585aL,0x91565060a068412eL, + 0x1283d6d1ab536c42L,0x86c2a11c79caa387L,0x2687309b62bd7797L } }, + /* 56 << 371 */ + { { 0x525cd8849b711a38L,0xd413d82b8c95bf61L,0x19ecc14a36b82970L, + 0x65190ee6e3416342L,0xde9834c93066fcf7L,0x3b87b15e8302cd85L }, + { 0xec6f67a785268eb2L,0x5ab08b5af95aef07L,0xb5257f70adda86a5L, + 0x53e95ec4b934400aL,0x9611a632c33b870bL,0xd27929522723a3d5L } }, + /* 57 << 371 */ + { { 0xcd203b542c95b469L,0x89b140e768713ca6L,0x451646a165701050L, + 0xb97a582575e54715L,0x070fabaa93bb6a91L,0xe517e07a196421b3L }, + { 0xc8d741235f46e495L,0x920ee94fdf60eb8dL,0x885b86dd19564c3eL, + 0x6c9e973231670005L,0xb52eed1fe4893763L,0xa8f9fbd759157417L } }, + /* 58 << 371 */ + { { 0x0c41f2eb56517cafL,0x47778a92798cf8b0L,0x4232ab390dc60cecL, + 0x5de0b7e39e3eb6f1L,0xa2569d8571562511L,0x37b3c62a1ce1cec9L }, + { 0x312caccd8b3391aeL,0x6b22c9447dcbe533L,0xc890d22f4fefd4edL, + 0xd1504f7df007a64eL,0x117e4e595845d5bcL,0x999386c7723584e1L } }, + /* 59 << 371 */ + { { 0x02c396533bdadbd5L,0xc07325fda1fe704aL,0xf78d7e23350aa0c4L, + 0x9f09cf22ce50784cL,0xcdea9a6a1a6e8abcL,0x245fba06ee5a5e06L }, + { 0xf1fd3b9b4a3d0d7cL,0x24c65a131a4952c4L,0x40ea3ef37236b6f4L, + 0x60aa573d8f7addcfL,0xdd5ec47b0305577dL,0xd92dc5035deacea5L } }, + /* 60 << 371 */ + { { 0xc666f8f3fac2de80L,0xabb2b8aba8fa36a6L,0x1bd0ec8f12202b09L, + 0x88b184be6d17a3c5L,0x00d501fc670a77c1L,0xe1f94f1db3de1c7eL }, + { 0x953179cd2d6de8caL,0xa8873a5bb9263791L,0xd76433098d7ac5d1L, + 0x3d751cab4d2f8224L,0x7417b8262e5458eaL,0xf4eb3c669e454a8cL } }, + /* 61 << 371 */ + { { 0x65b0d7e9ae3284a2L,0x3d4770bb1e3cbb18L,0x217a0cdb808ea164L, + 0x9ed6d0f689810270L,0x62d9cc95f14139e1L,0x4d39eeef6a2c82a0L }, + { 0xecf319f40dcf14afL,0x62c95df6ab0fd145L,0xfe85014d22db0105L, + 0xc37756e6a652168cL,0x6ba9f6b370a67e9dL,0xe453fd0af18d8058L } }, + /* 62 << 371 */ + { { 0x265798acfe3bf4f8L,0xc1603abdc1183f63L,0x14e3952f1063e086L, + 0xdcb106d2910f0a78L,0x27c2aee2f454f625L,0xf16d83e60f463fe9L }, + { 0xaa5547207f5ae172L,0x42ea8fea9a2133eaL,0x9f3b33f6e9253e7eL, + 0x6224ef75d67af0afL,0x06f0ddfbb92d6cc9L,0x12e66e32656e9e9aL } }, + /* 63 << 371 */ + { { 0x1a93be3424ace7f0L,0xb993bcb9a56be2eaL,0x3b054afac33608d7L, + 0x36e782c3aea3d7e9L,0x54f1dda950e9b3adL,0x04dd021f55f51bb4L }, + { 0x9c76f7c0347bb352L,0x3d9a04ee2f1dc5fbL,0xea5e582ae80e06f0L, + 0xe523aab927e1e818L,0xe2f1960252d4904cL,0x1bfa8b03adecc51fL } }, + /* 64 << 371 */ + { { 0xc84f917203bdf6d6L,0xcfc4718769f60e03L,0xcdc4753ba05068eaL, + 0xa177ad14077777efL,0x0b7f54eb7e4cf44aL,0x4ee443f91860144eL }, + { 0x1279ed4d42bb6a93L,0x511137d7436c1b54L,0xebc958fab8cdb6ceL, + 0xbc4f93f4a0c7614aL,0xc5bd6cde7b2c6d8eL,0xecff7dd78d65f38aL } }, + /* 0 << 378 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 378 */ + { { 0xffec6674f65de0f5L,0x4043079cd23ad193L,0x31811365ee61bc95L, + 0x358bbd6e8948b6e2L,0x1cd9c342e31644beL,0xbab3aa8c60a8a7a7L }, + { 0xe065519fa375beb6L,0xf7d0b0414439990cL,0x8957c03b8517ae8aL, + 0xc96a040173750d6eL,0x4eb2e364b2aee6d7L,0x813054feed099114L } }, + /* 2 << 378 */ + { { 0xbb39a17a7c34f095L,0x7be330a822fbbe61L,0x6be6abe3b91f1482L, + 0xf972804fbd39a2bcL,0x06737e54f91d813eL,0xbd6066681a87cd4aL }, + { 0xbf88b2e5f538d56eL,0xb8206a8134afd68fL,0x7a93aedfa58af042L, + 0x8853cdf6ac0511b0L,0x9d7f416d067e2c19L,0x5d0bc923f9671d8aL } }, + /* 3 << 378 */ + { { 0xf3b6fd79dd3532a7L,0xf60262b5dbbb9e4cL,0xbf75bb57da4d6ac4L, + 0xf016adf1c094b38cL,0x9114cdd012def474L,0xdc74d638c785f143L }, + { 0xdea060d6a8d90bbbL,0x1f141878cbcd0d4cL,0x552685b79ddee1f5L, + 0x381dfc0c636ea6b6L,0x8c601615cb08f34fL,0x5b843830271041eeL } }, + /* 4 << 378 */ + { { 0x2e7d0a16204be028L,0x4f1d082ed0e41851L,0x15f1ddc63eb317f9L, + 0xf02750715adf71d7L,0x2ce33c2eee858bc3L,0xa24c76d1da73b71aL }, + { 0x9ef6a70a6c70c483L,0xefcf170505cf9612L,0x9f5bf5a67502de64L, + 0xd11122a1a4701973L,0x82cfaac2a2ea7b24L,0x6cad67cc0a4582e1L } }, + /* 5 << 378 */ + { { 0x139d9fef6bfc08e4L,0x4399615939ffcb3bL,0xaa299008a84ace07L, + 0xfce43e873cbb2b3fL,0x07b3e8b9191a320eL,0x3ec851d706c4d485L }, + { 0x03d8a672a4bb8477L,0xb6a5dcb213c31d5cL,0x58b79d01c439ab23L, + 0xdd6f8b5134f66137L,0xccb178a0b29be48cL,0x4c71b7aa4df8a1b2L } }, + /* 6 << 378 */ + { { 0x92bf8c4508359896L,0x77253434ae2c30f2L,0xf05086ec827e6cf8L, + 0x46d4729f1771c5d3L,0x92587306f37f0bedL,0xb82c99d2e7c30180L }, + { 0xee0141dcb1684841L,0x7fa984be994ddaf5L,0x5c583347165c238cL, + 0x1a1ad3eea5d78204L,0xcfed795f2736bce6L,0xa7a413318961204eL } }, + /* 7 << 378 */ + { { 0x87451ca71400851dL,0x3aace28e3573ecf6L,0x3a5902cee85717c5L, + 0xe4b51dd0c9f57944L,0x33cf684789a9d8aeL,0x2f6fb08031e6e769L }, + { 0x4bf3da323b78dad1L,0x2d73fef4e7809638L,0x84d76151965109abL, + 0xa2c932c9a2098f46L,0xb8c457c3bc17d1fcL,0x5ef2562d0c8012a4L } }, + /* 8 << 378 */ + { { 0x96a1e74f51e4de5eL,0x72913696e37f5006L,0x12449c4fbe35109cL, + 0x1fad8b304521d7e6L,0xc85eb23d57d00293L,0x4ebd334b35f68229L }, + { 0x7c5b86682df5acf1L,0xc2b4da6e5463de2eL,0x067b0456757cd570L, + 0xeaab81be3a1c866bL,0x72a6af75bbba88c0L,0xaed4dbde0ef567dcL } }, + /* 9 << 378 */ + { { 0x085e33cd9273818aL,0x8fb9294a8cf4e306L,0xaed46bbc35052bd1L, + 0x031febb3374661eaL,0x9386a35d4868dbb2L,0x381e5b521d3f2dddL }, + { 0xa938a3a5179617edL,0xb0fc99f49dc95af1L,0xf446dfa92b9dacbcL, + 0xbae262ae490c1969L,0x042707ffa7443354L,0x8dc0511f267d5c14L } }, + /* 10 << 378 */ + { { 0x8f0e1908fac2674dL,0xd86e85a483e43c26L,0x1f719f7036fb5a4eL, + 0x7ad61b8ca57dbcbcL,0xcf6ba7db0f63dc79L,0xb4315ab11afe8540L }, + { 0x0448e852425c4df3L,0xf51969ef8838a51dL,0xce98589b9eab87deL, + 0x55867b5645149689L,0x9b70bc8c60d2a624L,0xc158a2710b6dbd45L } }, + /* 11 << 378 */ + { { 0x0b262f808f1915f2L,0x64ba3bc73d501e01L,0x8ce2db1f4645152cL, + 0xf4a4f3afab047cdbL,0x1a7c4af600d31e7fL,0x0005bca678d1c0ecL }, + { 0xf5ed135f6fe5ebb0L,0xa299b1002ea9abdfL,0x4fa387e5fccb58f5L, + 0x105b9dd2fc657b72L,0x1494c6050dc3c22cL,0xf7468e8a92d281c7L } }, + /* 12 << 378 */ + { { 0x597a26ffb4dc8600L,0x264a09f3f9288555L,0x0b06aff65c27f5f6L, + 0xce5ab665d8d544e6L,0x92f031be99275c32L,0xaf51c5bbf42e0e7cL }, + { 0x5bb28b061e37b36dL,0x583fba6a8473543aL,0xe73fd299f93fb7dcL, + 0xfcd999a86e2ccad9L,0xb8c8a6df334d4f57L,0x5adb28dd9a2acc9bL } }, + /* 13 << 378 */ + { { 0xc760823646dd14f3L,0xc6d97d37e7a97f33L,0x05037f26de2f444aL, + 0x5267ded09aa9a5c0L,0xd1ef46340be2d841L,0x308b37a8d48b9574L }, + { 0x102f7878487bad5bL,0x1d5169d938b7c1efL,0x2d8adde62c39c75aL, + 0x71bfb8bc0b80f3bbL,0x126505999bff252fL,0xf99e952f24f8bd3bL } }, + /* 14 << 378 */ + { { 0x24496a8b7a8a6d47L,0x9fc75c0aec6afe43L,0x4200e00670744f15L, + 0xe2f87d5e2973be1dL,0x0f6c5993c82e2013L,0xe9ecf6ce198c99f0L }, + { 0xcbdf72058b37d828L,0xbef4b8c8325d1d93L,0x8e962ffbd0fbb134L, + 0xe4273a124bcffc61L,0x4f24ba23f3d93d73L,0x8f02df83bcfcb930L } }, + /* 15 << 378 */ + { { 0x985c8f4b0614348aL,0xca4ca7cd5a03c014L,0x5bdd4382a7b62effL, + 0x623d44b9e4a0bb42L,0x1f28862ef23931d5L,0x30568303868326beL }, + { 0x850d2a0d82e76f04L,0xf4dc02330ac4a153L,0x62b74879b1e70a9aL, + 0x7b32249baf3f0dbbL,0x2f50395d155eae92L,0x6d990c16f6f5c9a4L } }, + /* 16 << 378 */ + { { 0x3afdee277d221ab6L,0xecf10abc47bb619eL,0x340c8ee3ba4a3301L, + 0x1a6ea51a2a883b7fL,0x64f27976d5d7412bL,0x7fcf0ecc91251b6eL }, + { 0x5f3f8f41365b18b7L,0x38e48b96e2e13e58L,0xde3b73d6ad61b2cbL, + 0xf08398d5d542676dL,0xd373931e8e7d712bL,0x89325d7a7f96e023L } }, + /* 17 << 378 */ + { { 0xeb2e48c10bf4e94dL,0x00614bf206b7e166L,0x536c999ce295c451L, + 0x951f92186359cf06L,0xe2a938890afc827fL,0x63102e93ff029787L }, + { 0xab297c7d2ac89645L,0x7354df74928742bfL,0xc0934ca6c8604304L, + 0x36b7e9711cc2f3b4L,0x487ce890e10ee837L,0xe6aa9eabae2ae9e3L } }, + /* 18 << 378 */ + { { 0x6e7a578340517347L,0x7db868f3a950dfa2L,0x7fd7fd8eb3c2eff7L, + 0xae7b59c5fbe10a47L,0x5239b5c4109797d6L,0x3838356a53264b8aL }, + { 0x8df8454c320a8c5aL,0x67c86ef46958fa2cL,0xfe1aad846241a50aL, + 0x3df64ef5a06f3cf3L,0xde6af0ff83282fbdL,0x25ca45046cdbe5feL } }, + /* 19 << 378 */ + { { 0xa319340d6e6c0debL,0x101f055acb1b1cd5L,0x4bea31ad623e7e55L, + 0xc0c88af6aec23cd2L,0xca98c4364aaf2f73L,0x1969eca437dd1341L }, + { 0x6b03989f97866dc3L,0xafdc99532eaf5b08L,0x199ec0e93d6ea9c4L, + 0xc3d1069474f262e9L,0xa7e5670079911cf9L,0xc0213ec56844da05L } }, + /* 20 << 378 */ + { { 0x5adf3d9a111792b9L,0x1c77a3054f1e0d09L,0xf9fbce33a82d3736L, + 0xf307823e718c8aa3L,0x860578cf416ccf69L,0xb942add81ef8465bL }, + { 0x9ee0cf97cd9472e1L,0xe6792eefb01528a8L,0xf99b9a8dc09da90bL, + 0x1f521c2dcbf3ccb8L,0x6bf6694891a62632L,0xcc7a9ceb854fe9daL } }, + /* 21 << 378 */ + { { 0xfc9660a3c8808373L,0x84c5d6a71a50c560L,0x13fe0588ba057fe2L, + 0x29b0341dafb73ad1L,0x37b11137f15f0cd2L,0x84422ba89c2d7eb0L }, + { 0x0b595ac52554ef7fL,0xd7a8303f08b37a84L,0x908895a9e02d77fcL, + 0x70cdeb0c9f242a42L,0x535e8540116e2db8L,0xc88f0cf685c54d31L } }, + /* 22 << 378 */ + { { 0xf534f145e2290ebaL,0x3d081c0d7f15c9e3L,0x716574c5e9ae3da0L, + 0xbe6bd7b92c078aa8L,0xab8802bab8da8e68L,0x0c5be4a1ab204fb0L }, + { 0xad25c5ee0d3f12b3L,0x3929d0d78fc9b7a5L,0x9c6e2ce0bb5cd2fdL, + 0x855367c4924ec2d2L,0x6b532891e6550d3cL,0xab2bc89575ba5c99L } }, + /* 23 << 378 */ + { { 0xb56b035e2a0349adL,0xcfa41da6f89ce836L,0x9d86bcac8b5c43fcL, + 0xc77375da47644b07L,0x9e9c222607f4b670L,0x71d663c80482a61bL }, + { 0xb423e739ef237431L,0xf1cedf7e48832b5bL,0x09e0cb2a7ca7548bL, + 0x9b463559631b9850L,0x8a2bd7fed4dd03deL,0x46115292ae0c97d3L } }, + /* 24 << 378 */ + { { 0xe44e3f864b3759cfL,0x90cab0eb9d74e3f6L,0x1004254501c4e171L, + 0xc12df68cce52defbL,0xb1fae2fbf363100aL,0x5016c8533573235fL }, + { 0x8d4deb661d922e9bL,0x8a20d42317f84ef2L,0x324985835a4e118eL, + 0x5abfa961308772e9L,0x41c7611ff54e4876L,0xc1da40d31f5867b2L } }, + /* 25 << 378 */ + { { 0x4df02a7d3088aebcL,0x7dea27ea12487485L,0x2a773270df98069eL, + 0xea435fa0e9ceaf44L,0x08e952e365e5ebabL,0x972877d5c3511480L }, + { 0xef5685f859a04cd0L,0xe50abe68b8c7c796L,0xbbb792e2c3225f20L, + 0x7d9878e811c89153L,0x4b72a1e619354751L,0x7d5f05a3faa1be22L } }, + /* 26 << 378 */ + { { 0x61dd7692f27eed54L,0x8540213ea7a3f2f7L,0xe659cbd6ace07e13L, + 0x3a998cdcc8995cacL,0x0accb4a7922d3b25L,0x762b3406c6577d81L }, + { 0xa09db4f57e043740L,0x7f78e02d8cc9bc5fL,0x080a522673b98cd3L, + 0xb6d72f7ce6490808L,0x36815de2c724284aL,0xc27d13df98b867b5L } }, + /* 27 << 378 */ + { { 0xbfeffd5356adb6e4L,0xb5e8876c499a1455L,0x4771281390833f18L, + 0x5f49ef880115b9a5L,0xb041ec67cf575de5L,0x490753350b7e4afcL }, + { 0xad4dc4a15f0b9f24L,0x9dbb181edafad9a5L,0xa84431a6e6ed5198L, + 0x33ee16e27993eed6L,0xfdf76899c1e4f8b4L,0x868d06baff60e943L } }, + /* 28 << 378 */ + { { 0x46303171491ccb92L,0xa80a8c0d2771235bL,0xd8e497fff172c7cfL, + 0x7f7009d735b193cfL,0x6b9fd3f7f19df4bcL,0xada548c3b46f1e37L }, + { 0x87c6eaa9c7a20270L,0xef2245d6ae78ef99L,0x2a121042539eab95L, + 0x29a6d5d779b8f5ccL,0x33803a10b77840dcL,0xfedd3a7011a6a30fL } }, + /* 29 << 378 */ + { { 0x5d782a0778664144L,0xc1413da46682c779L,0x937a15f52a67b12bL, + 0x8ec00d9fc04d8cd5L,0x3f16d1ed3b5fe8d6L,0x24ad6b0ca28c8067L }, + { 0xdd1eecc532732b19L,0x62c4c2beab2fa785L,0x7d863f5b2ac0c238L, + 0xd686eb7239384e15L,0x3770e54d16bd75b2L,0xdcd9e4e8120b3881L } }, + /* 30 << 378 */ + { { 0xe3052838df5147e1L,0x87bc4d75b1baaa7cL,0x49b13eb95acc5572L, + 0x919081881990c13cL,0x5d43a4a6191cc808L,0x20b358444182aa55L }, + { 0x70d49a4a670b1fd1L,0xc6e6e061722e91e7L,0x8d130b3900c5ae9eL, + 0x5db7d06920f68ec5L,0x85b6c505470fbe13L,0x14101ec7326c4d38L } }, + /* 31 << 378 */ + { { 0xeef03450e10e8018L,0x75921e487576c3ddL,0x6c8e22676e97f5afL, + 0xd7323e01a856ae6bL,0x43a195425fed884fL,0x010865380377ba8fL }, + { 0x7cdbd06ac82a8f67L,0xc6fce58bf0fd4281L,0xae098b7f9e67bed0L, + 0x0c8d328bdd918524L,0xddf723ec0a11fb83L,0x210d6016e25a2073L } }, + /* 32 << 378 */ + { { 0x3c90a59f85adde98L,0x35414174e5269140L,0x9aca885c1a0d58e2L, + 0x77b9b6dd6816b009L,0x8e5c12139ee4718fL,0x60ad991e4e4eac45L }, + { 0xc00c35694d71f624L,0xacbf4eb25bc5fd2aL,0xcba1ffc75eaf3eaaL, + 0x5f99092d42a87e32L,0x2e7b49c76f7a882fL,0x5e9bfc5c29040512L } }, + /* 33 << 378 */ + { { 0xa31d3524b295958dL,0x9713a5e04894f486L,0xe8804ab3329a0b9aL, + 0xd4447c1b20eefa54L,0xf5b944c9040b7ad4L,0x9db0ee0b907f2cfdL }, + { 0x0b1a1f3a5384a999L,0x3137241ea8351764L,0xe0663b5ab29c3cffL, + 0x2b47ca0622d4deefL,0x4f952109f1172bcdL,0x1e7a7fca9b447bd4L } }, + /* 34 << 378 */ + { { 0xc9898355ecf2a473L,0x20d0c4740dcd66f6L,0x6459720f8eeefff5L, + 0xd9b625dcf9ce0cdeL,0xed3a6508ea56be90L,0x6847c20de211c90eL }, + { 0x36d86bed71a73ceeL,0x9222eab23023d16eL,0x3155874750209b4dL, + 0xcac8f277d145b831L,0x49cedc634470e754L,0x6c7c065add370f77L } }, + /* 35 << 378 */ + { { 0x46a95735f8171804L,0x1ff2549ec4c93476L,0xfb8a08285bb5202dL, + 0xaff5505f1070737aL,0x162aaad842f412c5L,0x02a37213fac8a477L }, + { 0x05ff9238932f08e2L,0x9be6a0b29fc66787L,0x373a9039db1e5a40L, + 0xe657e8c782d04913L,0xa2006f207e6ee867L,0xd7aa1d2378d82f9aL } }, + /* 36 << 378 */ + { { 0xfa070e22142403d1L,0x68ff316015c6f7f5L,0xe09f04e6223a0ce8L, + 0x22bbd01853e14183L,0x35d9fafccf45b75bL,0x3a34819d7eceec88L }, + { 0xd9cf7568d33262d2L,0x431036d5841d1505L,0x0c8005659eb2a79aL, + 0x8e77d9f05f7edc6aL,0x19e12d0565e800aaL,0x335c8d36b7784e7cL } }, + /* 37 << 378 */ + { { 0xdcac39d87c1d9f4dL,0x88322d8bc225ce6eL,0x5c240cefa3ef5202L, + 0xf60ce5d991f1d487L,0x8e857069e462cfa8L,0xa6e5585e996d2033L }, + { 0x709675a556281e6aL,0xcd90c140f907ebf0L,0x5343a0a2a3231eecL, + 0x74b1443214892291L,0xf8cb9c26a5325b8cL,0x1bb28be140089be5L } }, + /* 38 << 378 */ + { { 0x2bb6e7ec3092d0b2L,0xc7c9e5f1d27d1f31L,0xbac785aeac0939e3L, + 0x186d3d934f810d8fL,0xda296dacfe7d778fL,0x6189f5e41a991ea2L }, + { 0x098f794e9634363eL,0x04aaf59a88a4dccaL,0x09d718487196dfa8L, + 0xa447a31ed83044a6L,0x720cd3908d1363fdL,0x6f670479e22efa03L } }, + /* 39 << 378 */ + { { 0xaa452e81cdf60f9aL,0xf3dc472a8e2c58e9L,0x16ddefa50589fd01L, + 0xd56ec8f223a1656eL,0xcccb784f77921ca4L,0x9bace7adf8a7c0baL }, + { 0xc94ef3ef51f052e2L,0xa70c0579c34e7cb5L,0x3599817883ce8674L, + 0x033647c392a20951L,0xc828fcc77a21add6L,0x5a446de871ba27a5L } }, + /* 40 << 378 */ + { { 0x75cba9d530a3ada1L,0xb69e308bf8ae9565L,0x990e3425ca7b8369L, + 0x9f67567fe0a7ad0bL,0x76ed6fe718bd01b7L,0x282358aa2ff95cfeL }, + { 0x28d2ea41410f8841L,0x89d1533fccd67c81L,0x969bb272b6a7b8f9L, + 0x54f8664c26330782L,0xb89f3ae81dcd9164L,0x54d845b93d962c14L } }, + /* 41 << 378 */ + { { 0x08ba5b61fde4ca03L,0x39b1a9c697b17ee6L,0x885253779336b2b9L, + 0xe964dc9c9aabc3fcL,0x6aed101a5295e728L,0x30369ea0ee12356aL }, + { 0xe081e022c8e80e5eL,0x3a769ef0df9f47c0L,0x3b2f7aab5590750cL, + 0xd16c7a85a1a5e504L,0x9e528623e854d7cfL,0xaca079354468e419L } }, + /* 42 << 378 */ + { { 0xee521c0af93098bfL,0xf517c925b79aa0ebL,0x17779f5e7bbc58feL, + 0x093c3dc2769de891L,0xafbf32372a69ad0dL,0x33a95de702001e8cL }, + { 0x3b30afc73410a2b0L,0xb379a3f425bc7d9aL,0xf1c069251604a646L, + 0x04f0bb334fca052fL,0xe5cd9c39cab33871L,0xf259795816fa1b16L } }, + /* 43 << 378 */ + { { 0x291d65c801189d9aL,0xb16ca18bd8e94e49L,0x55f7680599440d4bL, + 0x55d40c1b2eb7f0fdL,0x752d98f6018d7c64L,0xa1cae78c7b491c4dL }, + { 0x898fc8c78f66b8d3L,0xbb48956a3ceecd27L,0xb8f9498dfaa9451fL, + 0x583b336aa5683ef8L,0x0deaa373e92656f4L,0x7f87b4412a9a0272L } }, + /* 44 << 378 */ + { { 0x8b2fc4e96484fd40L,0xee702764a35d24eaL,0x15b28ac7b871c3f3L, + 0x805b4048e097047fL,0xd6f1b8df647cad2fL,0xf1d5b458dc7dd67fL }, + { 0x324c529c25148803L,0xf6185ebe21274fafL,0xaf14751e95148b55L, + 0x283ed89d28f284f4L,0x93ad20e74cbebf1aL,0x5f6ec65d882935e1L } }, + /* 45 << 378 */ + { { 0x4b0c7d0c69c284cbL,0x907e4f38199c5176L,0x4ebfbda7cf3dab12L, + 0x675f12cca4fa74a9L,0x86628102bdf579e6L,0xf08cbfe771c4d061L }, + { 0x9dde390e03bc1cb9L,0xb6d0d48b4c727915L,0x7cad28c370c0b7bfL, + 0x8d978a8110d1e881L,0x1c071597924baeb1L,0x83c09192eb103fe0L } }, + /* 46 << 378 */ + { { 0x494dbd2665925506L,0xe239b1d404b6fc45L,0x38a1ec5ce16b874dL, + 0x1588c4712a3f012dL,0x5bd45adcdc6938b9L,0xe4c35c2244ab2fccL }, + { 0x87cbd9ff887108a2L,0x92a9c3b2144fd3eeL,0x3a0e55c7982a4928L, + 0xcaf679765bb0fddfL,0x04616318263ea256L,0x56eb022838caa901L } }, + /* 47 << 378 */ + { { 0x2f7de141a48da000L,0x323bd638835a4edfL,0xd2d9da967e155bd5L, + 0x717c302a766b69daL,0x5927968beb0f6ca5L,0xfd96bd168940c766L }, + { 0xf89f7539a334fd71L,0x4ba9cd8bd870954fL,0x7e639523a3d57aa8L, + 0x88f31e162314c0ceL,0xa836a6ad53b7e6e9L,0xd35a825190e43169L } }, + /* 48 << 378 */ + { { 0xb3984b176c0f3509L,0xf9fa4483d8b4d6bcL,0xf4ac2b677dec20d2L, + 0x67ef024eb3dbe034L,0x2dcc51180f94f4d7L,0x024cdcfd74a51393L }, + { 0xf1c0fead20e7abcbL,0xffc18f81d3a7414fL,0xb00ce5567062cb0bL, + 0xeccb0521817bc8d1L,0xa0c0fe6040411c15L,0x053113221defbe00L } }, + /* 49 << 378 */ + { { 0x74faca8a6af7e742L,0x6f206002d878a97aL,0xd69b7c83177305ffL, + 0x605e7a32d2e2bcf1L,0x65bd03584590bf03L,0xab3ae700d1a378c5L }, + { 0x037e79028a929b0dL,0x83625ae0a7c451c6L,0x82a18f03492b01d4L, + 0x12c6d168e67756b1L,0x1e704c3bd7924df1L,0x7708617f1989244eL } }, + /* 50 << 378 */ + { { 0x4c98c61d097bde48L,0x6a55edf1c354f433L,0x1ceee947c3f39212L, + 0x162cf27f36ba3cebL,0xd9f3982e3ec5f7ffL,0xd363e435d58d42d2L }, + { 0x2ee90d7bad36681dL,0xd916df56ebfbf51cL,0x61d94ed8d7c27fe7L, + 0x5010582e923c1acdL,0x89d23e8b6de52994L,0x0a4f9c10525dbccfL } }, + /* 51 << 378 */ + { { 0x7778fad7e65573e2L,0xa4af7a2d74986210L,0xd78ecebfec57d967L, + 0x9be8a33f67d61b2eL,0x6888444f98a9add7L,0x218e7fb1b71a25a4L }, + { 0xf75a6b795f46323bL,0x2f8610ad11a52cd9L,0x23692f85fc6837caL, + 0x3a37965f71fe847bL,0x29c25cc3fe3bdeeeL,0x68fefc83f624665aL } }, + /* 52 << 378 */ + { { 0xe222eba4a4dcefe9L,0x63ad235fec1ceb74L,0x2e0bf749e05b18e7L, + 0x547bd050b48bdd87L,0x0490c970f5aa2fc4L,0xced5e4cf2b431390L }, + { 0x07d8270451d2898eL,0x44b72442083b57d4L,0xa4ada2305037fce8L, + 0x55f7905e50510da6L,0xd8ee724f8d890a98L,0x925a8e7c11b85640L } }, + /* 53 << 378 */ + { { 0x8357d8bb460e77b2L,0xc749a6a77709a52bL,0x94035a1f0c82ab81L, + 0x15245ac616c11ef4L,0xbf3cd96c034d021bL,0xf79e2d39b2e8fac1L }, + { 0x387015194b6cf1bdL,0x341f9b53b3143bf7L,0xb2584aabdda9acf2L, + 0x16f34bdd553a8e68L,0x89d0c4c5da7830b3L,0x6cfe44c63f488c2eL } }, + /* 54 << 378 */ + { { 0xee536a26d4bcaa59L,0x5ea6a57c699397bfL,0xb28f476b59a7eb99L, + 0xa901f2551406ec90L,0x7b6e3e4d1f54ef38L,0x058ff1904c89c9a8L }, + { 0x5690fa10fca546ccL,0xfe98793145e14268L,0x6181fa1675362f5dL, + 0x3ebe84466964b9aeL,0x3e1957812ce0f969L,0xb33ea619b0195852L } }, + /* 55 << 378 */ + { { 0xeef402410ec537acL,0x1f72c1f8911316f6L,0xab4bb08268cc6678L, + 0x031fc087255e8c5eL,0x99c2ff0b948ac53bL,0x13db3201919c1870L }, + { 0xdec81fd312057a3cL,0xbdffa226ff7a44cbL,0x748d2e93d97167e2L, + 0x33a9fe40bd21effeL,0xe08e4213817ea560L,0x2221798b9f4337d5L } }, + /* 56 << 378 */ + { { 0xda828fe556467257L,0x5e9abf67d640c2a1L,0x0eed233cc25c696aL, + 0x72483dc5b3e1d84fL,0x30bf1ee34f114abcL,0xf58b321ed1f9bce8L }, + { 0xcb26564c97524f33L,0xdc2f105e1e453229L,0x9da43ceb72a982ddL, + 0xecf5649dfeef8862L,0xd8afda341fa2f06dL,0xf0d0ced355035432L } }, + /* 57 << 378 */ + { { 0xec22bb32205a5301L,0xe4d168e75b0b727bL,0x91217a6be34fe2e0L, + 0x03c6831675f0f139L,0xb21e275d8b991b29L,0x7f517c9c01f3f401L }, + { 0xbbe95d19e55e49faL,0xc5470808504514b1L,0xb88be15c7cc1367dL, + 0x242cb06bbfd24bacL,0x08647a158d2ab0baL,0x8f1fd1bd5716ed9bL } }, + /* 58 << 378 */ + { { 0xe787054518ba5236L,0x243622f9e8a47507L,0xe7d94f4697b97d7cL, + 0xb120589021649255L,0x8b5101310dd4e1d4L,0x1690687e164c44baL }, + { 0x65bb4d8cf100fef5L,0xfffffee70a684c3dL,0x2aa11707c463a975L, + 0xccaddeaf391ad03dL,0x4d2cda1c81cca7deL,0x9d3eaa58c5b0f8e7L } }, + /* 59 << 378 */ + { { 0x3d92ecc18f8802dfL,0x3024ce311a719461L,0x6bdf53fc46c1f31bL, + 0x4f4576a12c9c7744L,0xe1ee7508c3ff7356L,0xd4b25ed3883ebf03L }, + { 0x1dc46052420c3ac9L,0x376ebbfa11ecefa9L,0x36e175265e9693f5L, + 0xeb82b33740ed3143L,0x6960312ff19fa66aL,0xc7edb5db6c742e1bL } }, + /* 60 << 378 */ + { { 0x5bfa10cd1ca459edL,0x593f085a6dcf56bfL,0xe6f0ad9bc0579c3eL, + 0xc11c95a22527c1adL,0x7cfa71e1cf1cb8b3L,0xedcff8331d6dc79dL }, + { 0x581c4bbe432521c9L,0xbf620096144e11a0L,0x54c38b71be3a107bL, + 0xed555e37e2606ec0L,0x3fb148b8d721d034L,0x79d53dad0091bc90L } }, + /* 61 << 378 */ + { { 0x4b98cb69c5c8a182L,0x887071bbcac96dabL,0x03d42e96afc190c3L, + 0xbc2c3b8d7a813820L,0x1ee7797f6590d0ecL,0x4a95f7f3ad4777a4L }, + { 0x7a36de4e2a8d2736L,0x7f8c6751ad78dab6L,0xf9874bf6974c0a8eL, + 0x759fee1c8b53025aL,0x1b00fb28a2171c8bL,0xdf206f19be8f2e7eL } }, + /* 62 << 378 */ + { { 0xe6bbcf0bf8ed6302L,0x7734dc91f8fe7a42L,0x840210ee61ff9d1eL, + 0xbbf2d5477007f2e9L,0x0f17d421a6542ac0L,0x0b2d3d2ee01df4e9L }, + { 0x520e4fbb84f3703fL,0x8362f7b1431106b7L,0xdcfc96ae6e50d836L, + 0x2dfa176cc44153bbL,0xeef1c6710b09ffe2L,0x633a2ac888531d81L } }, + /* 63 << 378 */ + { { 0x29262b6d7636a78dL,0xdc504f01d3ce2967L,0xa441e5035bcf0e19L, + 0x8025224f7ad39d9aL,0x780ec65de871b792L,0x977b4bce597694b4L }, + { 0xe05eaeb87fe3ef11L,0x1cff87ac9748b10eL,0xb669c1d60c34153aL, + 0xf5da63e0f8f90368L,0x6f7f2fc47d31bf61L,0x37e9158235c16a0fL } }, + /* 64 << 378 */ + { { 0xcf17f9dc08d1be5dL,0xb55de4c8afdfeb23L,0xa69454ffe437b29cL, + 0x6628d789e27ee9e2L,0x56e3b975ee3af03bL,0x0083fe9c2f532d62L }, + { 0xcae15213e63e7511L,0xdb5384f386ed849cL,0x902ba959fa4d825fL, + 0xbad700d55ae17566L,0x16b2c5dc14c82eb4L,0xa4b057a736708ea7L } }, +}; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Pre-computed table containing multiples of g times powers of 2. + * Width between powers is 7 bits. + * Accumulate into the result. + * + * r Resulting point. + * g Point to scalar multiply. + * k Scalar to multiply by. + * table Pre-computed table of points. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_add_only_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 rt[2]; + sp_digit tmp[2 * 6 * 6]; +#endif + sp_point_384* p = NULL; + sp_digit* negy = NULL; + int i; + ecc_recode_384 v[55]; + int err = MP_OKAY; + + (void)g; + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + negy = tmp; + p = rt + 1; + } + + if (err == MP_OKAY) { + sp_384_ecc_recode_7_6(k, v); + + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + i = 54; + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_65_6(rt, &table[i * 65], v[i].i); + } + else + #endif + { + XMEMCPY(rt->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(rt->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + } + rt->infinity = !v[i].i; + for (--i; i>=0; i--) { + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_65_6(p, &table[i * 65], v[i].i); + } + else + #endif + { + XMEMCPY(p->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(p->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + } + p->infinity = !v[i].i; + sp_384_sub_6(negy, p384_mod, p->y); + sp_384_norm_6(negy); + sp_384_cond_copy_6(p->y, negy, 0 - v[i].neg); + sp_384_proj_point_add_qz1_6(rt, rt, p, tmp); + } + if (map != 0) { + sp_384_map_6(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 6 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return MP_OKAY; +} + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_384_ecc_mulmod_add_only_6(r, NULL, p384_table, + k, map, ct, heap); +} + +#endif /* WOLFSSL_SP_SMALL */ /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * @@ -43032,28 +62738,30 @@ static int sp_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[6]; +#endif int err = MP_OKAY; - err = sp_384_point_new_6(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 6, km); @@ -43063,12 +62771,90 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_6(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[6 + 6 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (6 + 6 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_6(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 6; + + sp_384_from_mp(k, 6, km); + sp_384_point_from_ecc_point_6(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_6(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_6(point, point, addP, tmp); + + if (map) { + sp_384_map_6(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -43086,7 +62872,7 @@ static int sp_384_iszero_6(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -43122,7 +62908,8 @@ static void sp_384_add_one_6(sp_digit* a) */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j; + int i; + int j; byte* d; for (i = n - 1,j = 0; i >= 7; i -= 8) { @@ -43196,41 +62983,46 @@ static int sp_384_ecc_gen_k_6(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[6]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_384_point_new_6(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_6(rng, k); } if (err == MP_OKAY) { @@ -43255,15 +63047,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_6(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_6(infinity, 1, heap); -#endif - sp_384_point_free_6(point, 1, heap); return err; } @@ -43277,7 +63068,8 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_384_to_bin(sp_digit* r, byte* a) { - int i, j; + int i; + int j; for (i = 5, j = 0; i >= 0; i--) { a[j++] = r[i] >> 56; @@ -43303,33 +63095,35 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[6]; +#endif int err = MP_OKAY; if (*outLen < 48U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -43342,12 +63136,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(point, 0, heap); return err; } @@ -43630,7 +63424,6 @@ static const uint64_t p384_order_minus_2[6] = { /* The low half of the order-2 of the P384 curve. */ static const uint64_t p384_order_low[3] = { 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU - }; #endif /* WOLFSSL_SP_SMALL */ @@ -43778,7 +63571,7 @@ static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_6(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_6(t2, t2); - if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_384_mont_mul_order_6(t2, t2, a); } } @@ -43787,12 +63580,63 @@ static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_6(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int64_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_6(k, k, p384_norm_order); + err = sp_384_mod_6(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(k); + + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_6(kInv, k, tmp); + sp_384_norm_6(kInv); + + /* s = r * x + e */ + sp_384_mul_6(x, x, r); + err = sp_384_mod_6(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(x); + carry = sp_384_add_6(s, e, x); + sp_384_cond_sub_6(s, s, p384_order, 0 - carry); + sp_384_norm_6(s); + c = sp_384_cmp_6(s, p384_order); + sp_384_cond_sub_6(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_6(s, s, kInv); + sp_384_norm_6(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -43827,8 +63671,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -43846,13 +63690,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 6, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_6(rng, ctx->k); @@ -43880,6 +63721,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_6(ctx->r, p384_order); sp_384_cond_sub_6(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_6(ctx->r); + + sp_384_from_mp(ctx->x, 6, priv); + sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); ctx->state = 4; break; } @@ -43936,6 +63780,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -43968,72 +63815,55 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*6]; - sp_digit xd[2*6]; - sp_digit kd[2*6]; - sp_digit rd[2*6]; - sp_digit td[3 * 2*6]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 6]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int64_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_384_point_new_6(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 6; - x = d + 2 * 6; - k = d + 4 * 6; - r = d + 6 * 6; - tmp = d + 8 * 6; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 6; + k = e + 4 * 6; + r = e + 6 * 6; + tmp = e + 8 * 6; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 6, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 6, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_6(rng, k); @@ -44043,7 +63873,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -44054,38 +63884,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_6(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_6(r); - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_6(k, k, p384_norm_order); - err = sp_384_mod_6(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_6(k); - /* kInv = 1/k mod order */ - sp_384_mont_inv_order_6(kInv, k, tmp); - sp_384_norm_6(kInv); + sp_384_from_mp(x, 6, priv); + sp_384_from_bin(e, 6, hash, (int)hashLen); - /* s = r * x + e */ - sp_384_mul_6(x, x, r); - err = sp_384_mod_6(x, x, p384_order); + err = sp_384_calc_s_6(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_6(x); - carry = sp_384_add_6(s, e, x); - sp_384_cond_sub_6(s, s, p384_order, 0 - carry); - sp_384_norm_6(s); - c = sp_384_cmp_6(s, p384_order); - sp_384_cond_sub_6(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_6(s); - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_6(s, s, kInv); - sp_384_norm_6(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_6(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_6(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -44099,20 +63910,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 6); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_6(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -44288,6 +64103,94 @@ static int sp_384_mod_inv_6(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_6(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ + + sp_384_proj_point_add_6(p1, p1, p2, tmp); + if (sp_384_iszero_6(p1->z)) { + if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { + sp_384_proj_point_dbl_6(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_6(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_6(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_384_mul_6(s, s, p384_norm_order); + } + err = sp_384_mod_6(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_384_mont_inv_order_6(s, s, tmp); + sp_384_mont_mul_order_6(u1, u1, s); + sp_384_mont_mul_order_6(u2, u2, s); + } + +#else + { + sp_384_mont_mul_order_6(u1, u1, s); + sp_384_mont_mul_order_6(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_384_ecc_mulmod_base_6(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_6(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_6(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_6(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_6(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -44306,8 +64209,7 @@ static int sp_384_mod_inv_6(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -44326,8 +64228,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -44342,7 +64245,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 6, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->u2, 6, rm); sp_384_from_mp(ctx->s, 6, sm); sp_384_from_mp(ctx->p2.x, 6, pX); sp_384_from_mp(ctx->p2.y, 6, pY); @@ -44400,57 +64303,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_6(ctx->p1.z)) { - if (sp_384_iszero_6(ctx->p1.x) && sp_384_iszero_6(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<6; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->u2, 6, rm); err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_6(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int64_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int64_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->u2, 6, rm); carry = sp_384_add_6(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -44458,22 +64337,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_6(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -44481,128 +64361,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*6]; - sp_digit u2d[2*6]; - sp_digit sd[2*6]; - sp_digit tmpd[2*6 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 6]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int64_t c; - int err; + int64_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_6(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 6, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 6, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 6; - u2 = d + 2 * 6; - s = d + 4 * 6; - tmp = d + 6 * 6; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 6; + s = u1 + 4 * 6; + tmp = u1 + 6 * 6; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 6, hash, (int)hashLen); - sp_384_from_mp(u2, 6, r); + sp_384_from_mp(u2, 6, rm); sp_384_from_mp(s, 6, sm); sp_384_from_mp(p2->x, 6, pX); sp_384_from_mp(p2->y, 6, pY); sp_384_from_mp(p2->z, 6, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_6(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_384_mul_6(s, s, p384_norm_order); - } - err = sp_384_mod_6(s, s, p384_order); + err = sp_384_calc_vfy_point_6(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_6(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_384_mont_inv_order_6(s, s, tmp); - sp_384_mont_mul_order_6(u1, u1, s); - sp_384_mont_mul_order_6(u2, u2, s); - } - -#else - { - sp_384_mont_mul_order_6(u1, u1, s); - sp_384_mont_mul_order_6(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_384_ecc_mulmod_base_6(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_6(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_6(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_6(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_384_proj_point_add_6(p1, p1, p2, tmp); - if (sp_384_iszero_6(p1->z)) { - if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { - sp_384_proj_point_dbl_6(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 6, r); + sp_384_from_mp(u2, 6, rm); err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); } @@ -44613,7 +64428,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 6, r); + sp_384_from_mp(u2, 6, rm); carry = sp_384_add_6(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -44621,26 +64436,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_6(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_6(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p1, 0, heap); - sp_384_point_free_6(p2, 0, heap); return err; } @@ -44654,34 +64469,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_6(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*6]; - sp_digit t2d[2*6]; + sp_digit t1[6 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 6; - t2 = d + 2 * 6; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 6; sp_384_sqr_6(t1, point->y); (void)sp_384_mod_6(t1, t1, p384_mod); @@ -44701,10 +64508,9 @@ static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -44717,16 +64523,23 @@ static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_6(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 6, pX); sp_384_from_mp(pub->y, 6, pY); @@ -44735,7 +64548,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_6(pub, NULL); } - sp_384_point_free_6(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -44751,47 +64567,48 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[6]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; - sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_384_point_new_6(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_384* pub = NULL; +#else + sp_digit priv[6]; + sp_point_384 pub[2]; #endif + sp_point_384* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 6, pX); sp_384_from_mp(pub->y, 6, pY); sp_384_from_bin(pub->z, 6, one, (int)sizeof(one)); @@ -44805,12 +64622,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_6(pub->x, p384_mod) >= 0 || - sp_384_cmp_6(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_6(pub->x, p384_mod) >= 0) || + (sp_384_cmp_6(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -44822,12 +64638,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_384_ecc_mulmod_6(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_6(p->x) == 0) || - (sp_384_iszero_6(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_6(p->x) == 0) || + (sp_384_iszero_6(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -44835,22 +64649,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_384_ecc_mulmod_base_6(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_6(p->x, pub->x) != 0 || - sp_384_cmp_6(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_6(p->x, pub->x) != 0) || + (sp_384_cmp_6(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(pub, 0, heap); return err; } @@ -44874,33 +64686,35 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 6 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 6 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; - err = sp_384_point_new_6(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_6(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 6, pX); sp_384_from_mp(p->y, 6, pY); sp_384_from_mp(p->z, 6, pZ); @@ -44921,13 +64735,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(q, 0, NULL); - sp_384_point_free_6(p, 0, NULL); return err; } @@ -44946,25 +64759,28 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 6 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 6 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_6(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -44985,12 +64801,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, NULL); return err; } @@ -45005,32 +64821,36 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 6 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 6 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_6(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 6, pX); sp_384_from_mp(p->y, 6, pY); sp_384_from_mp(p->z, 6, pZ); - sp_384_map_6(p, p, tmp); + sp_384_map_6(p, p, tmp); } if (err == MP_OKAY) { @@ -45043,12 +64863,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, NULL); return err; } @@ -45061,43 +64881,28 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_6(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 6]; - sp_digit t2d[2 * 6]; - sp_digit t3d[2 * 6]; - sp_digit t4d[2 * 6]; - sp_digit t5d[2 * 6]; + sp_digit t1[5 * 2 * 6]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 6; - t2 = d + 2 * 6; - t3 = d + 4 * 6; - t4 = d + 6 * 6; - t5 = d + 8 * 6; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 6; + t3 = t1 + 4 * 6; + t4 = t1 + 6 * 6; + t5 = t1 + 8 * 6; { /* t2 = y ^ 0x2 */ @@ -45157,10 +64962,9 @@ static int sp_384_mont_sqrt_6(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -45176,31 +64980,22 @@ static int sp_384_mont_sqrt_6(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 6]; - sp_digit yd[2 * 6]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 6]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 6, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 6, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 6; - y = d + 2 * 6; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 6; sp_384_from_mp(x, 6, xm); err = sp_384_mod_mul_norm_6(x, x, p384_mod); @@ -45233,16 +65028,11858 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 16]; + /* Y ordinate of point. */ + sp_digit y[2 * 16]; + /* Z ordinate of point. */ + sp_digit z[2 * 16]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_1024_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x8, x9, [%[a], 0]\n\t" + "ldp x10, x11, [%[a], 16]\n\t" + "ldp x12, x13, [%[a], 32]\n\t" + "ldp x14, x15, [%[a], 48]\n\t" + "ldp x16, x17, [%[b], 0]\n\t" + "ldp x19, x20, [%[b], 16]\n\t" + "ldp x21, x22, [%[b], 32]\n\t" + "ldp x23, x24, [%[b], 48]\n\t" + "# A[0] * B[0]\n\t" + "mul x3, x8, x16\n\t" + "umulh x4, x8, x16\n\t" + "str x3, [%[r]]\n\t" + "# A[0] * B[1]\n\t" + "mul x6, x8, x17\n\t" + "umulh x7, x8, x17\n\t" + "adds x4, x4, x6\n\t" + "# A[1] * B[0]\n\t" + "mul x6, x9, x16\n\t" + "adc x5, xzr, x7\n\t" + "umulh x7, x9, x16\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 8]\n\t" + "adc x3, xzr, xzr\n\t" + "# A[0] * B[2]\n\t" + "mul x6, x8, x19\n\t" + "umulh x7, x8, x19\n\t" + "adds x5, x5, x6\n\t" + "# A[1] * B[1]\n\t" + "mul x6, x9, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x9, x17\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[2] * B[0]\n\t" + "mul x6, x10, x16\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x16\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 16]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[3]\n\t" + "mul x6, x8, x20\n\t" + "umulh x7, x8, x20\n\t" + "adds x3, x3, x6\n\t" + "# A[1] * B[2]\n\t" + "mul x6, x9, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x9, x19\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[2] * B[1]\n\t" + "mul x6, x10, x17\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x10, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[3] * B[0]\n\t" + "mul x6, x11, x16\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x16\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 24]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[4]\n\t" + "mul x6, x8, x21\n\t" + "umulh x7, x8, x21\n\t" + "adds x4, x4, x6\n\t" + "# A[1] * B[3]\n\t" + "mul x6, x9, x20\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x9, x20\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B[2]\n\t" + "mul x6, x10, x19\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x10, x19\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[3] * B[1]\n\t" + "mul x6, x11, x17\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x11, x17\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[4] * B[0]\n\t" + "mul x6, x12, x16\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x16\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 32]\n\t" + "adc x3, x3, xzr\n\t" + "# A[0] * B[5]\n\t" + "mul x6, x8, x22\n\t" + "umulh x7, x8, x22\n\t" + "adds x5, x5, x6\n\t" + "# A[1] * B[4]\n\t" + "mul x6, x9, x21\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x9, x21\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[2] * B[3]\n\t" + "mul x6, x10, x20\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B[2]\n\t" + "mul x6, x11, x19\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x11, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[4] * B[1]\n\t" + "mul x6, x12, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x12, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[5] * B[0]\n\t" + "mul x6, x13, x16\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x16\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 40]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[6]\n\t" + "mul x6, x8, x23\n\t" + "umulh x7, x8, x23\n\t" + "adds x3, x3, x6\n\t" + "# A[1] * B[5]\n\t" + "mul x6, x9, x22\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x9, x22\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[2] * B[4]\n\t" + "mul x6, x10, x21\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x10, x21\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[3] * B[3]\n\t" + "mul x6, x11, x20\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x20\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B[2]\n\t" + "mul x6, x12, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x12, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[5] * B[1]\n\t" + "mul x6, x13, x17\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x13, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[6] * B[0]\n\t" + "mul x6, x14, x16\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x14, x16\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 48]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[7]\n\t" + "mul x6, x8, x24\n\t" + "umulh x7, x8, x24\n\t" + "adds x4, x4, x6\n\t" + "# A[1] * B[6]\n\t" + "mul x6, x9, x23\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x9, x23\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B[5]\n\t" + "mul x6, x10, x22\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x10, x22\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[3] * B[4]\n\t" + "mul x6, x11, x21\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x11, x21\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[4] * B[3]\n\t" + "mul x6, x12, x20\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x20\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B[2]\n\t" + "mul x6, x13, x19\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x13, x19\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[6] * B[1]\n\t" + "mul x6, x14, x17\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x14, x17\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[7] * B[0]\n\t" + "mul x6, x15, x16\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x15, x16\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 56]\n\t" + "adc x3, x3, xzr\n\t" + "# A[1] * B[7]\n\t" + "mul x6, x9, x24\n\t" + "umulh x7, x9, x24\n\t" + "adds x5, x5, x6\n\t" + "# A[2] * B[6]\n\t" + "mul x6, x10, x23\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x10, x23\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B[5]\n\t" + "mul x6, x11, x22\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x11, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[4] * B[4]\n\t" + "mul x6, x12, x21\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x12, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[5] * B[3]\n\t" + "mul x6, x13, x20\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B[2]\n\t" + "mul x6, x14, x19\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x14, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[7] * B[1]\n\t" + "mul x6, x15, x17\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x15, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 64]\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[7]\n\t" + "mul x6, x10, x24\n\t" + "umulh x7, x10, x24\n\t" + "adds x3, x3, x6\n\t" + "# A[3] * B[6]\n\t" + "mul x6, x11, x23\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x11, x23\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B[5]\n\t" + "mul x6, x12, x22\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x12, x22\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[5] * B[4]\n\t" + "mul x6, x13, x21\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x13, x21\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[6] * B[3]\n\t" + "mul x6, x14, x20\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x14, x20\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B[2]\n\t" + "mul x6, x15, x19\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x15, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 72]\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[7]\n\t" + "mul x6, x11, x24\n\t" + "umulh x7, x11, x24\n\t" + "adds x4, x4, x6\n\t" + "# A[4] * B[6]\n\t" + "mul x6, x12, x23\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x12, x23\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B[5]\n\t" + "mul x6, x13, x22\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x13, x22\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[6] * B[4]\n\t" + "mul x6, x14, x21\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x14, x21\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[7] * B[3]\n\t" + "mul x6, x15, x20\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x15, x20\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 80]\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[7]\n\t" + "mul x6, x12, x24\n\t" + "umulh x7, x12, x24\n\t" + "adds x5, x5, x6\n\t" + "# A[5] * B[6]\n\t" + "mul x6, x13, x23\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x13, x23\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B[5]\n\t" + "mul x6, x14, x22\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x14, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[7] * B[4]\n\t" + "mul x6, x15, x21\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, x15, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "str x5, [%[r], 88]\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[7]\n\t" + "mul x6, x13, x24\n\t" + "umulh x7, x13, x24\n\t" + "adds x3, x3, x6\n\t" + "# A[6] * B[6]\n\t" + "mul x6, x14, x23\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x14, x23\n\t" + "adc x5, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B[5]\n\t" + "mul x6, x15, x22\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, x15, x22\n\t" + "adc x5, x5, xzr\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "str x3, [%[r], 96]\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[7]\n\t" + "mul x6, x14, x24\n\t" + "umulh x7, x14, x24\n\t" + "adds x4, x4, x6\n\t" + "# A[7] * B[6]\n\t" + "mul x6, x15, x23\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, x15, x23\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "str x4, [%[r], 104]\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[7]\n\t" + "mul x6, x15, x24\n\t" + "umulh x7, x15, x24\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "stp x5, x3, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * All registers version. + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_1024_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x21, x22, [%[a], 0]\n\t" + "ldp x23, x24, [%[a], 16]\n\t" + "ldp x25, x26, [%[a], 32]\n\t" + "ldp x27, x28, [%[a], 48]\n\t" + "# A[0] * A[1]\n\t" + "mul x6, x21, x22\n\t" + "umulh x7, x21, x22\n\t" + "# A[0] * A[2]\n\t" + "mul x4, x21, x23\n\t" + "umulh x5, x21, x23\n\t" + "adds x7, x7, x4\n\t" + "# A[0] * A[3]\n\t" + "mul x4, x21, x24\n\t" + "adc x8, xzr, x5\n\t" + "umulh x5, x21, x24\n\t" + "adds x8, x8, x4\n\t" + "# A[1] * A[2]\n\t" + "mul x4, x22, x23\n\t" + "adc x9, xzr, x5\n\t" + "umulh x5, x22, x23\n\t" + "adds x8, x8, x4\n\t" + "# A[0] * A[4]\n\t" + "mul x4, x21, x25\n\t" + "adcs x9, x9, x5\n\t" + "umulh x5, x21, x25\n\t" + "adc x10, xzr, xzr\n\t" + "adds x9, x9, x4\n\t" + "# A[1] * A[3]\n\t" + "mul x4, x22, x24\n\t" + "adc x10, x10, x5\n\t" + "umulh x5, x22, x24\n\t" + "adds x9, x9, x4\n\t" + "# A[0] * A[5]\n\t" + "mul x4, x21, x26\n\t" + "adcs x10, x10, x5\n\t" + "umulh x5, x21, x26\n\t" + "adc x11, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * A[4]\n\t" + "mul x4, x22, x25\n\t" + "adc x11, x11, x5\n\t" + "umulh x5, x22, x25\n\t" + "adds x10, x10, x4\n\t" + "# A[2] * A[3]\n\t" + "mul x4, x23, x24\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x23, x24\n\t" + "adc x12, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * A[6]\n\t" + "mul x4, x21, x27\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x21, x27\n\t" + "adc x12, x12, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[5]\n\t" + "mul x4, x22, x26\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x22, x26\n\t" + "adc x13, xzr, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * A[4]\n\t" + "mul x4, x23, x25\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x23, x25\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[0] * A[7]\n\t" + "mul x4, x21, x28\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x21, x28\n\t" + "adc x13, x13, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[1] * A[6]\n\t" + "mul x4, x22, x27\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x22, x27\n\t" + "adc x14, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * A[5]\n\t" + "mul x4, x23, x26\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x23, x26\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * A[4]\n\t" + "mul x4, x24, x25\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x24, x25\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[1] * A[7]\n\t" + "mul x4, x22, x28\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x22, x28\n\t" + "adc x14, x14, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[2] * A[6]\n\t" + "mul x4, x23, x27\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x23, x27\n\t" + "adc x15, xzr, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * A[5]\n\t" + "mul x4, x24, x26\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x24, x26\n\t" + "adc x15, x15, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[2] * A[7]\n\t" + "mul x4, x23, x28\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x23, x28\n\t" + "adc x15, x15, xzr\n\t" + "adds x14, x14, x4\n\t" + "# A[3] * A[6]\n\t" + "mul x4, x24, x27\n\t" + "adcs x15, x15, x5\n\t" + "umulh x5, x24, x27\n\t" + "adc x16, xzr, xzr\n\t" + "adds x14, x14, x4\n\t" + "# A[4] * A[5]\n\t" + "mul x4, x25, x26\n\t" + "adcs x15, x15, x5\n\t" + "umulh x5, x25, x26\n\t" + "adc x16, x16, xzr\n\t" + "adds x14, x14, x4\n\t" + "# A[3] * A[7]\n\t" + "mul x4, x24, x28\n\t" + "adcs x15, x15, x5\n\t" + "umulh x5, x24, x28\n\t" + "adc x16, x16, xzr\n\t" + "adds x15, x15, x4\n\t" + "# A[4] * A[6]\n\t" + "mul x4, x25, x27\n\t" + "adcs x16, x16, x5\n\t" + "umulh x5, x25, x27\n\t" + "adc x17, xzr, xzr\n\t" + "adds x15, x15, x4\n\t" + "# A[4] * A[7]\n\t" + "mul x4, x25, x28\n\t" + "adcs x16, x16, x5\n\t" + "umulh x5, x25, x28\n\t" + "adc x17, x17, xzr\n\t" + "adds x16, x16, x4\n\t" + "# A[5] * A[6]\n\t" + "mul x4, x26, x27\n\t" + "adcs x17, x17, x5\n\t" + "umulh x5, x26, x27\n\t" + "adc x19, xzr, xzr\n\t" + "adds x16, x16, x4\n\t" + "# A[5] * A[7]\n\t" + "mul x4, x26, x28\n\t" + "adcs x17, x17, x5\n\t" + "umulh x5, x26, x28\n\t" + "adc x19, x19, xzr\n\t" + "adds x17, x17, x4\n\t" + "# A[6] * A[7]\n\t" + "mul x4, x27, x28\n\t" + "adcs x19, x19, x5\n\t" + "umulh x5, x27, x28\n\t" + "adc x20, xzr, xzr\n\t" + "adds x19, x19, x4\n\t" + "adc x20, x20, x5\n\t" + "# Double\n\t" + "adds x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "adcs x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "adcs x17, x17, x17\n\t" + "adcs x19, x19, x19\n\t" + "# A[0] * A[0]\n\t" + "mul x5, x21, x21\n\t" + "adcs x20, x20, x20\n\t" + "umulh x2, x21, x21\n\t" + "cset x21, cs\n\t" + "# A[1] * A[1]\n\t" + "mul x3, x22, x22\n\t" + "adds x6, x6, x2\n\t" + "umulh x4, x22, x22\n\t" + "adcs x7, x7, x3\n\t" + "# A[2] * A[2]\n\t" + "mul x2, x23, x23\n\t" + "adcs x8, x8, x4\n\t" + "umulh x3, x23, x23\n\t" + "adcs x9, x9, x2\n\t" + "# A[3] * A[3]\n\t" + "mul x4, x24, x24\n\t" + "adcs x10, x10, x3\n\t" + "umulh x2, x24, x24\n\t" + "adcs x11, x11, x4\n\t" + "# A[4] * A[4]\n\t" + "mul x3, x25, x25\n\t" + "adcs x12, x12, x2\n\t" + "umulh x4, x25, x25\n\t" + "adcs x13, x13, x3\n\t" + "# A[5] * A[5]\n\t" + "mul x2, x26, x26\n\t" + "adcs x14, x14, x4\n\t" + "umulh x3, x26, x26\n\t" + "adcs x15, x15, x2\n\t" + "# A[6] * A[6]\n\t" + "mul x4, x27, x27\n\t" + "adcs x16, x16, x3\n\t" + "umulh x2, x27, x27\n\t" + "adcs x17, x17, x4\n\t" + "# A[7] * A[7]\n\t" + "mul x3, x28, x28\n\t" + "adcs x19, x19, x2\n\t" + "umulh x4, x28, x28\n\t" + "adcs x20, x20, x3\n\t" + "stp x5, x6, [%[r], 0]\n\t" + "adc x21, x21, x4\n\t" + "stp x7, x8, [%[r], 16]\n\t" + "stp x9, x10, [%[r], 32]\n\t" + "stp x11, x12, [%[r], 48]\n\t" + "stp x13, x14, [%[r], 64]\n\t" + "stp x15, x16, [%[r], 80]\n\t" + "stp x17, x19, [%[r], 96]\n\t" + "stp x20, x21, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) { + r[i] = a[i] & m; + } +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Add digit to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_1024_add_zero_8(sp_digit* r, const sp_digit* a, + const sp_digit d) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adds x3, x3, %[d]\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [d] "r" (d) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_1024_add_8(a1, a, &a[8]); + cb = sp_1024_add_8(b1, b, &b[8]); + u = ca & cb; + sp_1024_mul_8(z1, a1, b1); + sp_1024_mul_8(z2, &a[8], &b[8]); + sp_1024_mul_8(z0, a, b); + sp_1024_mask_8(r + 16, a1, 0 - cb); + sp_1024_mask_8(b1, b1, 0 - ca); + u += sp_1024_add_8(r + 16, r + 16, b1); + u += sp_1024_sub_in_place_16(z1, z2); + u += sp_1024_sub_in_place_16(z1, z0); + u += sp_1024_add_16(r + 8, r + 8, z1); + u += sp_1024_add_8(r + 16, r + 16, z2); + sp_1024_add_zero_8(r + 24, z2 + 8, u); +} + +#ifdef WOLFSSL_SP_SMALL +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_1024_dbl_8(sp_digit* r, const sp_digit* a) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 64\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "adcs x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x11" + ); + + return c; +} + +#else +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_1024_dbl_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "adds x3, x3, x3\n\t" + "ldr x5, [%[a], 16]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 24]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 48]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 56]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_1024_add_8(a1, a, &a[8]); + sp_1024_sqr_8(z1, a1); + sp_1024_sqr_8(z2, &a[8]); + sp_1024_sqr_8(z0, a); + sp_1024_mask_8(r + 16, a1, 0 - u); + u += sp_1024_dbl_8(r + 16, r + 16); + u += sp_1024_sub_in_place_16(z1, z2); + u += sp_1024_sub_in_place_16(z1, z0); + u += sp_1024_add_16(r + 8, r + 8, z1); + u += sp_1024_add_8(r + 16, r + 16, z2); + sp_1024_add_zero_8(r + 24, z2 + 8, u); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[32]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 120\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 128\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 240\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[32]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 120\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 128\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 240\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* !WOLFSSL_SP_SMALL */ +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[16] = { + 0x666d807afea85febL,0x80c5df10ac7ace87L,0xfce3e82389857db0L, + 0x9f94d6af56971f1fL,0xa7cf3c521c3c09aaL,0xb6aff4a831852a82L, + 0x512ac5cd65681ce1L,0xe26c6487326b4cd4L,0x356d27f4a666a6d0L, + 0xe791b39ff7c88a19L,0x228730d531a59cb0L,0xf40aab27e2fc0f1bL, + 0xbe9ae358b3e01a2eL,0x416c0ce19cb48261L,0x65c61198dad0657aL, + 0x997abb1f0a563fdaL +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[16] = { + 0x99927f850157a015L,0x7f3a20ef53853178L,0x031c17dc767a824fL, + 0x606b2950a968e0e0L,0x5830c3ade3c3f655L,0x49500b57ce7ad57dL, + 0xaed53a329a97e31eL,0x1d939b78cd94b32bL,0xca92d80b5999592fL, + 0x186e4c60083775e6L,0xdd78cf2ace5a634fL,0x0bf554d81d03f0e4L, + 0x41651ca74c1fe5d1L,0xbe93f31e634b7d9eL,0x9a39ee67252f9a85L, + 0x668544e0f5a9c025L +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x290420077c8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[16] = { + 0xd99b601ebfaa17fbL,0x203177c42b1eb3a1L,0xff38fa08e2615f6cL, + 0xa7e535abd5a5c7c7L,0xa9f3cf14870f026aL,0x6dabfd2a0c614aa0L, + 0x144ab173595a0738L,0x389b1921cc9ad335L,0x4d5b49fd2999a9b4L, + 0x39e46ce7fdf22286L,0xc8a1cc354c69672cL,0xbd02aac9f8bf03c6L, + 0x6fa6b8d62cf8068bL,0x905b0338672d2098L,0x9971846636b4195eL, + 0x265eaec7c2958ff6L +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0x880dc8abeae63895L,0x80ec46c4967e0979L,0xee9163a5b63f73ecL, + 0xd5cfb4cc80728d87L,0xa7c1514dba66910dL,0xa702c3397a60de74L, + 0x337c86548b72f2e1L,0x9760af765dd5bccbL,0x718bd9e7406ce890L, + 0x43d5f22cdb9dfa55L,0xab10db9030b09e10L,0xb5edb6c0f6ce2308L, + 0x98b2f204b6ff7cbfL,0x2b1a2fd60aec69c6L,0x0a7990053ed9b52aL, + 0x53fc09ee332c29adL, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x75573fd71bef16d7L,0xadb9b5706a67dcdeL,0x80bdad5ad5bb4636L, + 0x13515ad7e9cb99a9L,0x492d979fc5a4d5f2L,0xac6f1e80164aa989L, + 0xcad696b5b7652fe0L,0x70dae117ad547c6cL,0x416cff0ca9e032b9L, + 0x6b598ccf9a140b2eL,0xe7f7f5e5f0de55f6L,0xf5ea69f4654ec2b9L, + 0x3d778d821e141178L,0xd3e8201602990696L,0xf9f1f0533634a135L, + 0x0a8249063f6009f1L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000000001L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x10, %[a], 128\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_1024_cond_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 128\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_1024_mul_d_16(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 128\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B\n\t" + "ldp x8, x9, [%[a], 48]\n\t" + "str x5, [%[r], 40]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B\n\t" + "str x3, [%[r], 48]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[8] * B\n\t" + "ldp x8, x9, [%[a], 64]\n\t" + "str x4, [%[r], 56]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[9] * B\n\t" + "str x5, [%[r], 64]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[10] * B\n\t" + "ldp x8, x9, [%[a], 80]\n\t" + "str x3, [%[r], 72]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[11] * B\n\t" + "str x4, [%[r], 80]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[12] * B\n\t" + "ldp x8, x9, [%[a], 96]\n\t" + "str x5, [%[r], 88]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[13] * B\n\t" + "str x3, [%[r], 96]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[14] * B\n\t" + "ldp x8, x9, [%[a], 112]\n\t" + "str x4, [%[r], 104]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[15] * B\n\t" + "str x5, [%[r], 112]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "stp x3, x4, [%[r], 120]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_1024_word_16(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_1024_cmp_16(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 120\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 112]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 80]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 48]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 16]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif + + return (int64_t)a; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_div_16(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[32], t2[17]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[15]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 16); + for (i=15; i>=0; i--) { + sp_digit hi = t1[16 + i] - (t1[16 + i] == div); + r1 = div_1024_word_16(hi, t1[16 + i - 1], div); + + sp_1024_mul_d_16(t2, d, r1); + t1[16 + i] += sp_1024_sub_in_place_16(&t1[i], t2); + t1[16 + i] -= t2[16]; + sp_1024_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_1024_add_16(&t1[i], &t1[i], t2); + sp_1024_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_1024_add_16(&t1[i], &t1[i], t2); + } + + r1 = sp_1024_cmp_16(t1, d) >= 0; + sp_1024_cond_sub_16(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_mod_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_1024_div_16(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_16(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + sp_1024_mul_16(r, a, p1024_norm_mod); + return sp_1024_mod_16(r, r, m); +} + + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_16(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_16(heap, sp, p) sp_1024_point_new_ex_16((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_16(heap, sp, p) sp_1024_point_new_ex_16((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_16(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_16(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 16, pm->x); + sp_1024_from_mp(p->y, 16, pm->y); + sp_1024_from_mp(p->z, 16, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 16); + r->used = 16; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 16; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 16; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else { + s += 64; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_16(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +static void sp_1024_cond_copy_16(sp_digit* r, const sp_digit* a, sp_digit m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[r], 0]\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "ldp x3, x4, [%[r], 16]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 16]\n\t" + "ldp x3, x4, [%[r], 32]\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "ldp x3, x4, [%[r], 48]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 48]\n\t" + "ldp x3, x4, [%[r], 64]\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "ldp x3, x4, [%[r], 80]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 80]\n\t" + "ldp x3, x4, [%[r], 96]\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "ldp x3, x4, [%[r], 112]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "eor x5, x5, x3\n\t" + "eor x6, x6, x4\n\t" + "and x5, x5, %[m]\n\t" + "and x6, x6, %[m]\n\t" + "eor x3, x3, x5\n\t" + "eor x4, x4, x6\n\t" + "stp x3, x4, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_1024_mont_reduce_16(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "ldp x21, x22, [%[m], 48]\n\t" + "ldp x23, x24, [%[m], 64]\n\t" + "ldp x25, x26, [%[m], 80]\n\t" + "ldp x27, x28, [%[m], 96]\n\t" + "mov x3, xzr\n\t" + "# i = 16\n\t" + "mov x4, 16\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "str x11, [%[a], 32]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x11, [%[a], 48]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "str x10, [%[a], 40]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x10, [%[a], 56]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "str x11, [%[a], 48]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x11, [%[a], 64]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x23, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x23, x9\n\t" + "str x10, [%[a], 56]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x10, [%[a], 72]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x24, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x24, x9\n\t" + "str x11, [%[a], 64]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x11, [%[a], 80]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x25, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x25, x9\n\t" + "str x10, [%[a], 72]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x10, [%[a], 88]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x26, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x26, x9\n\t" + "str x11, [%[a], 80]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x11, [%[a], 96]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x27, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x27, x9\n\t" + "str x10, [%[a], 88]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x10, [%[a], 104]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x28, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x28, x9\n\t" + "str x11, [%[a], 96]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x11, [%[a], 112]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 112]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 104]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x10, [%[a], 120]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 120]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, x3\n\t" + "str x11, [%[a], 112]\n\t" + "cset x3, cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 128]\n\t" + "str x10, [%[a], 120]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 128]\n\t" + "adc x3, x3, xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "# Create mask\n\t" + "ldr x9, [%[m], 120]\n\t" + "subs x11, x9, x11\n\t" + "neg x3, x3\n\t" + "sbc x11, x11, x11\n\t" + "orr x3, x3, x11\n\t" + "mov x9, %[a]\n\t" + "sub %[a], %[a], 128\n\t" + "# Subtract masked modulus\n\t" + "# x12 and x13 hold a[0] and a[1]\n\t" + "and x14, x14, x3\n\t" + "ldp x11, x10, [x9, 16]\n\t" + "and x15, x15, x3\n\t" + "subs x12, x12, x14\n\t" + "and x16, x16, x3\n\t" + "sbcs x13, x13, x15\n\t" + "and x17, x17, x3\n\t" + "sbcs x11, x11, x16\n\t" + "stp x12, x13, [%[a], 0]\n\t" + "sbcs x10, x10, x17\n\t" + "stp x11, x10, [%[a], 16]\n\t" + "ldp x12, x13, [x9, 32]\n\t" + "and x19, x19, x3\n\t" + "ldp x11, x10, [x9, 48]\n\t" + "and x20, x20, x3\n\t" + "sbcs x12, x12, x19\n\t" + "and x21, x21, x3\n\t" + "sbcs x13, x13, x20\n\t" + "and x22, x22, x3\n\t" + "sbcs x11, x11, x21\n\t" + "stp x12, x13, [%[a], 32]\n\t" + "sbcs x10, x10, x22\n\t" + "stp x11, x10, [%[a], 48]\n\t" + "ldp x12, x13, [x9, 64]\n\t" + "and x23, x23, x3\n\t" + "ldp x11, x10, [x9, 80]\n\t" + "and x24, x24, x3\n\t" + "sbcs x12, x12, x23\n\t" + "and x25, x25, x3\n\t" + "sbcs x13, x13, x24\n\t" + "and x26, x26, x3\n\t" + "sbcs x11, x11, x25\n\t" + "stp x12, x13, [%[a], 64]\n\t" + "sbcs x10, x10, x26\n\t" + "stp x11, x10, [%[a], 80]\n\t" + "ldp x7, x8, [%[m], 112]\n\t" + "ldp x12, x13, [x9, 96]\n\t" + "and x27, x27, x3\n\t" + "ldp x11, x10, [x9, 112]\n\t" + "and x28, x28, x3\n\t" + "sbcs x12, x12, x27\n\t" + "and x7, x7, x3\n\t" + "sbcs x13, x13, x28\n\t" + "and x8, x8, x3\n\t" + "sbcs x11, x11, x7\n\t" + "stp x12, x13, [%[a], 96]\n\t" + "sbcs x10, x10, x8\n\t" + "stp x11, x10, [%[a], 112]\n\t" + : [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_16(r, a, b); + sp_1024_mont_reduce_16(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_16(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_16(r, a); + sp_1024_mont_reduce_16(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_16(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 16]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 16); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_16(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_16(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 16); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_16(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_16(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_16(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_1024_norm_16(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_16(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + int64_t n; + + sp_1024_mont_inv_16(t1, p->z, t + 2*16); + + sp_1024_mont_sqr_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_16(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 16, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_16(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_16(r->x, p1024_mod); + sp_1024_cond_sub_16(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_16(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 16, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_16(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_16(r->y, p1024_mod); + sp_1024_cond_sub_16(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a], 0]\n\t" + "ldp x6, x7, [%[a], 16]\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "ldp x10, x11, [%[a], 48]\n\t" + "ldp x12, x13, [%[a], 64]\n\t" + "ldp x14, x15, [%[a], 80]\n\t" + "ldp x16, x17, [%[a], 96]\n\t" + "ldp x19, x20, [%[a], 112]\n\t" + "ldp x21, x22, [%[b], 0]\n\t" + "ldp x23, x24, [%[b], 16]\n\t" + "adds x4, x4, x21\n\t" + "adcs x5, x5, x22\n\t" + "adcs x6, x6, x23\n\t" + "adcs x7, x7, x24\n\t" + "ldp x21, x22, [%[b], 32]\n\t" + "ldp x23, x24, [%[b], 48]\n\t" + "adcs x8, x8, x21\n\t" + "adcs x9, x9, x22\n\t" + "adcs x10, x10, x23\n\t" + "adcs x11, x11, x24\n\t" + "ldp x21, x22, [%[b], 64]\n\t" + "ldp x23, x24, [%[b], 80]\n\t" + "adcs x12, x12, x21\n\t" + "adcs x13, x13, x22\n\t" + "adcs x14, x14, x23\n\t" + "adcs x15, x15, x24\n\t" + "ldp x21, x22, [%[b], 96]\n\t" + "ldp x23, x24, [%[b], 112]\n\t" + "adcs x16, x16, x21\n\t" + "adcs x17, x17, x22\n\t" + "adcs x19, x19, x23\n\t" + "adcs x20, x20, x24\n\t" + "csetm x25, cs\n\t" + "ldr x21, [%[m], 120]\n\t" + "subs x21, x21, x20\n\t" + "csetm x21, cc\n\t" + "orr x25, x25, x21\n\t" + "ldp x21, x22, [%[m], 0]\n\t" + "ldp x23, x24, [%[m], 16]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "subs x4, x4, x21\n\t" + "sbcs x5, x5, x22\n\t" + "sbcs x6, x6, x23\n\t" + "sbcs x7, x7, x24\n\t" + "ldp x21, x22, [%[m], 32]\n\t" + "ldp x23, x24, [%[m], 48]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x8, x8, x21\n\t" + "sbcs x9, x9, x22\n\t" + "sbcs x10, x10, x23\n\t" + "sbcs x11, x11, x24\n\t" + "ldp x21, x22, [%[m], 64]\n\t" + "ldp x23, x24, [%[m], 80]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x12, x12, x21\n\t" + "sbcs x13, x13, x22\n\t" + "sbcs x14, x14, x23\n\t" + "sbcs x15, x15, x24\n\t" + "ldp x21, x22, [%[m], 96]\n\t" + "ldp x23, x24, [%[m], 112]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x16, x16, x21\n\t" + "sbcs x17, x17, x22\n\t" + "sbcs x19, x19, x23\n\t" + "sbc x20, x20, x24\n\t" + "stp x4, x5, [%[r], 0]\n\t" + "stp x6, x7, [%[r], 16]\n\t" + "stp x8, x9, [%[r], 32]\n\t" + "stp x10, x11, [%[r], 48]\n\t" + "stp x12, x13, [%[r], 64]\n\t" + "stp x14, x15, [%[r], 80]\n\t" + "stp x16, x17, [%[r], 96]\n\t" + "stp x19, x20, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_dbl_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a], 0]\n\t" + "ldp x6, x7, [%[a], 16]\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "ldp x10, x11, [%[a], 48]\n\t" + "ldp x12, x13, [%[a], 64]\n\t" + "ldp x14, x15, [%[a], 80]\n\t" + "ldp x16, x17, [%[a], 96]\n\t" + "ldp x19, x20, [%[a], 112]\n\t" + "adds x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "adcs x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "adcs x17, x17, x17\n\t" + "adcs x19, x19, x19\n\t" + "adcs x20, x20, x20\n\t" + "csetm x25, cs\n\t" + "ldr x21, [%[m], 120]\n\t" + "subs x21, x21, x20\n\t" + "csetm x21, cc\n\t" + "orr x25, x25, x21\n\t" + "ldp x21, x22, [%[m], 0]\n\t" + "ldp x23, x24, [%[m], 16]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "subs x4, x4, x21\n\t" + "sbcs x5, x5, x22\n\t" + "sbcs x6, x6, x23\n\t" + "sbcs x7, x7, x24\n\t" + "ldp x21, x22, [%[m], 32]\n\t" + "ldp x23, x24, [%[m], 48]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x8, x8, x21\n\t" + "sbcs x9, x9, x22\n\t" + "sbcs x10, x10, x23\n\t" + "sbcs x11, x11, x24\n\t" + "ldp x21, x22, [%[m], 64]\n\t" + "ldp x23, x24, [%[m], 80]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x12, x12, x21\n\t" + "sbcs x13, x13, x22\n\t" + "sbcs x14, x14, x23\n\t" + "sbcs x15, x15, x24\n\t" + "ldp x21, x22, [%[m], 96]\n\t" + "ldp x23, x24, [%[m], 112]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x16, x16, x21\n\t" + "sbcs x17, x17, x22\n\t" + "sbcs x19, x19, x23\n\t" + "sbc x20, x20, x24\n\t" + "stp x4, x5, [%[r], 0]\n\t" + "stp x6, x7, [%[r], 16]\n\t" + "stp x8, x9, [%[r], 32]\n\t" + "stp x10, x11, [%[r], 48]\n\t" + "stp x12, x13, [%[r], 64]\n\t" + "stp x14, x15, [%[r], 80]\n\t" + "stp x16, x17, [%[r], 96]\n\t" + "stp x19, x20, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_tpl_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a], 0]\n\t" + "ldp x6, x7, [%[a], 16]\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "ldp x10, x11, [%[a], 48]\n\t" + "ldp x12, x13, [%[a], 64]\n\t" + "ldp x14, x15, [%[a], 80]\n\t" + "ldp x16, x17, [%[a], 96]\n\t" + "ldp x19, x20, [%[a], 112]\n\t" + "adds x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "adcs x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "adcs x17, x17, x17\n\t" + "adcs x19, x19, x19\n\t" + "adcs x20, x20, x20\n\t" + "csetm x25, cs\n\t" + "ldr x21, [%[m], 120]\n\t" + "subs x21, x21, x20\n\t" + "csetm x21, cc\n\t" + "orr x25, x25, x21\n\t" + "ldp x21, x22, [%[m], 0]\n\t" + "ldp x23, x24, [%[m], 16]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "subs x4, x4, x21\n\t" + "sbcs x5, x5, x22\n\t" + "sbcs x6, x6, x23\n\t" + "sbcs x7, x7, x24\n\t" + "ldp x21, x22, [%[m], 32]\n\t" + "ldp x23, x24, [%[m], 48]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x8, x8, x21\n\t" + "sbcs x9, x9, x22\n\t" + "sbcs x10, x10, x23\n\t" + "sbcs x11, x11, x24\n\t" + "ldp x21, x22, [%[m], 64]\n\t" + "ldp x23, x24, [%[m], 80]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x12, x12, x21\n\t" + "sbcs x13, x13, x22\n\t" + "sbcs x14, x14, x23\n\t" + "sbcs x15, x15, x24\n\t" + "ldp x21, x22, [%[m], 96]\n\t" + "ldp x23, x24, [%[m], 112]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x16, x16, x21\n\t" + "sbcs x17, x17, x22\n\t" + "sbcs x19, x19, x23\n\t" + "sbc x20, x20, x24\n\t" + "ldp x21, x22, [%[a], 0]\n\t" + "ldp x23, x24, [%[a], 16]\n\t" + "adds x4, x4, x21\n\t" + "adcs x5, x5, x22\n\t" + "adcs x6, x6, x23\n\t" + "adcs x7, x7, x24\n\t" + "ldp x21, x22, [%[a], 32]\n\t" + "ldp x23, x24, [%[a], 48]\n\t" + "adcs x8, x8, x21\n\t" + "adcs x9, x9, x22\n\t" + "adcs x10, x10, x23\n\t" + "adcs x11, x11, x24\n\t" + "ldp x21, x22, [%[a], 64]\n\t" + "ldp x23, x24, [%[a], 80]\n\t" + "adcs x12, x12, x21\n\t" + "adcs x13, x13, x22\n\t" + "adcs x14, x14, x23\n\t" + "adcs x15, x15, x24\n\t" + "ldp x21, x22, [%[a], 96]\n\t" + "ldp x23, x24, [%[a], 112]\n\t" + "adcs x16, x16, x21\n\t" + "adcs x17, x17, x22\n\t" + "adcs x19, x19, x23\n\t" + "adcs x20, x20, x24\n\t" + "csetm x25, cs\n\t" + "ldr x21, [%[m], 120]\n\t" + "subs x21, x21, x20\n\t" + "csetm x21, cc\n\t" + "orr x25, x25, x21\n\t" + "ldp x21, x22, [%[m], 0]\n\t" + "ldp x23, x24, [%[m], 16]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "subs x4, x4, x21\n\t" + "sbcs x5, x5, x22\n\t" + "sbcs x6, x6, x23\n\t" + "sbcs x7, x7, x24\n\t" + "ldp x21, x22, [%[m], 32]\n\t" + "ldp x23, x24, [%[m], 48]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x8, x8, x21\n\t" + "sbcs x9, x9, x22\n\t" + "sbcs x10, x10, x23\n\t" + "sbcs x11, x11, x24\n\t" + "ldp x21, x22, [%[m], 64]\n\t" + "ldp x23, x24, [%[m], 80]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x12, x12, x21\n\t" + "sbcs x13, x13, x22\n\t" + "sbcs x14, x14, x23\n\t" + "sbcs x15, x15, x24\n\t" + "ldp x21, x22, [%[m], 96]\n\t" + "ldp x23, x24, [%[m], 112]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "sbcs x16, x16, x21\n\t" + "sbcs x17, x17, x22\n\t" + "sbcs x19, x19, x23\n\t" + "sbc x20, x20, x24\n\t" + "stp x4, x5, [%[r], 0]\n\t" + "stp x6, x7, [%[r], 16]\n\t" + "stp x8, x9, [%[r], 32]\n\t" + "stp x10, x11, [%[r], 48]\n\t" + "stp x12, x13, [%[r], 64]\n\t" + "stp x14, x15, [%[r], 80]\n\t" + "stp x16, x17, [%[r], 96]\n\t" + "stp x19, x20, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a], 0]\n\t" + "ldp x6, x7, [%[a], 16]\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "ldp x10, x11, [%[a], 48]\n\t" + "ldp x12, x13, [%[a], 64]\n\t" + "ldp x14, x15, [%[a], 80]\n\t" + "ldp x16, x17, [%[a], 96]\n\t" + "ldp x19, x20, [%[a], 112]\n\t" + "ldp x21, x22, [%[b], 0]\n\t" + "ldp x23, x24, [%[b], 16]\n\t" + "subs x4, x4, x21\n\t" + "sbcs x5, x5, x22\n\t" + "sbcs x6, x6, x23\n\t" + "sbcs x7, x7, x24\n\t" + "ldp x21, x22, [%[b], 32]\n\t" + "ldp x23, x24, [%[b], 48]\n\t" + "sbcs x8, x8, x21\n\t" + "sbcs x9, x9, x22\n\t" + "sbcs x10, x10, x23\n\t" + "sbcs x11, x11, x24\n\t" + "ldp x21, x22, [%[b], 64]\n\t" + "ldp x23, x24, [%[b], 80]\n\t" + "sbcs x12, x12, x21\n\t" + "sbcs x13, x13, x22\n\t" + "sbcs x14, x14, x23\n\t" + "sbcs x15, x15, x24\n\t" + "ldp x21, x22, [%[b], 96]\n\t" + "ldp x23, x24, [%[b], 112]\n\t" + "sbcs x16, x16, x21\n\t" + "sbcs x17, x17, x22\n\t" + "sbcs x19, x19, x23\n\t" + "sbcs x20, x20, x24\n\t" + "csetm x25, cc\n\t" + "ldp x21, x22, [%[m], 0]\n\t" + "ldp x23, x24, [%[m], 16]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "adds x4, x4, x21\n\t" + "adcs x5, x5, x22\n\t" + "adcs x6, x6, x23\n\t" + "adcs x7, x7, x24\n\t" + "ldp x21, x22, [%[m], 32]\n\t" + "ldp x23, x24, [%[m], 48]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "adcs x8, x8, x21\n\t" + "adcs x9, x9, x22\n\t" + "adcs x10, x10, x23\n\t" + "adcs x11, x11, x24\n\t" + "ldp x21, x22, [%[m], 64]\n\t" + "ldp x23, x24, [%[m], 80]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "adcs x12, x12, x21\n\t" + "adcs x13, x13, x22\n\t" + "adcs x14, x14, x23\n\t" + "adcs x15, x15, x24\n\t" + "ldp x21, x22, [%[m], 96]\n\t" + "ldp x23, x24, [%[m], 112]\n\t" + "and x21, x21, x25\n\t" + "and x22, x22, x25\n\t" + "and x23, x23, x25\n\t" + "and x24, x24, x25\n\t" + "adcs x16, x16, x21\n\t" + "adcs x17, x17, x22\n\t" + "adcs x19, x19, x23\n\t" + "adc x20, x20, x24\n\t" + "stp x4, x5, [%[r], 0]\n\t" + "stp x6, x7, [%[r], 16]\n\t" + "stp x8, x9, [%[r], 32]\n\t" + "stp x10, x11, [%[r], 48]\n\t" + "stp x12, x13, [%[r], 64]\n\t" + "stp x14, x15, [%[r], 80]\n\t" + "stp x16, x17, [%[r], 96]\n\t" + "stp x19, x20, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25" + ); +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static sp_digit sp_1024_cond_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "cset %[c], cs\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 128\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "adds x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +static void sp_1024_rshift1_16(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr x2, [%[a]]\n\t" + "ldr x3, [%[a], 8]\n\t" + "lsr x2, x2, 1\n\t" + "orr x2, x2, x3, lsl 63\n\t" + "lsr x3, x3, 1\n\t" + "ldr x4, [%[a], 16]\n\t" + "str x2, [%[r], 0]\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "lsr x4, x4, 1\n\t" + "ldr x2, [%[a], 24]\n\t" + "str x3, [%[r], 8]\n\t" + "orr x4, x4, x2, lsl 63\n\t" + "lsr x2, x2, 1\n\t" + "ldr x3, [%[a], 32]\n\t" + "str x4, [%[r], 16]\n\t" + "orr x2, x2, x3, lsl 63\n\t" + "lsr x3, x3, 1\n\t" + "ldr x4, [%[a], 40]\n\t" + "str x2, [%[r], 24]\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "lsr x4, x4, 1\n\t" + "ldr x2, [%[a], 48]\n\t" + "str x3, [%[r], 32]\n\t" + "orr x4, x4, x2, lsl 63\n\t" + "lsr x2, x2, 1\n\t" + "ldr x3, [%[a], 56]\n\t" + "str x4, [%[r], 40]\n\t" + "orr x2, x2, x3, lsl 63\n\t" + "lsr x3, x3, 1\n\t" + "ldr x4, [%[a], 64]\n\t" + "str x2, [%[r], 48]\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "lsr x4, x4, 1\n\t" + "ldr x2, [%[a], 72]\n\t" + "str x3, [%[r], 56]\n\t" + "orr x4, x4, x2, lsl 63\n\t" + "lsr x2, x2, 1\n\t" + "ldr x3, [%[a], 80]\n\t" + "str x4, [%[r], 64]\n\t" + "orr x2, x2, x3, lsl 63\n\t" + "lsr x3, x3, 1\n\t" + "ldr x4, [%[a], 88]\n\t" + "str x2, [%[r], 72]\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "lsr x4, x4, 1\n\t" + "ldr x2, [%[a], 96]\n\t" + "str x3, [%[r], 80]\n\t" + "orr x4, x4, x2, lsl 63\n\t" + "lsr x2, x2, 1\n\t" + "ldr x3, [%[a], 104]\n\t" + "str x4, [%[r], 88]\n\t" + "orr x2, x2, x3, lsl 63\n\t" + "lsr x3, x3, 1\n\t" + "ldr x4, [%[a], 112]\n\t" + "str x2, [%[r], 96]\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "lsr x4, x4, 1\n\t" + "ldr x2, [%[a], 120]\n\t" + "str x3, [%[r], 104]\n\t" + "orr x4, x4, x2, lsl 63\n\t" + "lsr x2, x2, 1\n\t" + "str x4, [%[r], 112]\n\t" + "str x2, [%[r], 120]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x2", "x3", "x4" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_1024_div2_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_1024_cond_add_16(r, a, m, 0 - (a[0] & 1)); + sp_1024_rshift1_16(r, r); + r[15] |= o << 63; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_16_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_16_ctx; + +static int sp_1024_proj_point_dbl_16_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_16_ctx* ctx = (sp_1024_proj_point_dbl_16_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_16_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*16; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_16(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_16(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_16(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_16(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_16(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_16(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_16(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_16(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_16(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_16(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_16(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_16(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_16(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_16(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_16(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_16(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_16(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_16(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_16(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_16(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_16(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_16(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_16(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_16(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_16(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_16(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_16(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_16(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_16(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_16(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_16(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_16(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_16(y, y, t2, p1024_mod); +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_16(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*16; + sp_digit* b = t + 4*16; + sp_digit* t1 = t + 6*16; + sp_digit* t2 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_16(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_16(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_16(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(t2, b, p1024_mod); + sp_1024_mont_sub_16(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_16(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_16(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_16(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_16(y, b, x, p1024_mod); + sp_1024_mont_mul_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(y, y, p1024_mod); + sp_1024_mont_sub_16(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_16(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(t2, b, p1024_mod); + sp_1024_mont_sub_16(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_16(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_16(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_16(y, b, x, p1024_mod); + sp_1024_mont_mul_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(y, y, p1024_mod); + sp_1024_mont_sub_16(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_16(y, y, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 128\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_1024_sub_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_16(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_16_ctx { + int state; + sp_1024_proj_point_dbl_16_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_16_ctx; + +static int sp_1024_proj_point_add_16_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_16_ctx* ctx = (sp_1024_proj_point_add_16_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_16_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*16; + ctx->t3 = t + 4*16; + ctx->t4 = t + 6*16; + ctx->t5 = t + 8*16; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_16(ctx->t1, p1024_mod, q->y); + sp_1024_norm_16(ctx->t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_16_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_16(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_16(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_16(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_16(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_16(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_16(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_16(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_16(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_16(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_16(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_16(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_16(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_16(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_16(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_16(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_16(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_16(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_16(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_16(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_16(t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_16(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_16(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_16(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_16(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_16(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_16(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_16(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(x, x, t5, p1024_mod); + sp_1024_mont_dbl_16(t1, y, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_16(y, y, x, p1024_mod); + sp_1024_mont_mul_16(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(y, y, t5, p1024_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_store_16(sp_point_1024* r, + const sp_point_1024* p, int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*16; + sp_digit* b = t + 4*16; + sp_digit* t1 = t + 6*16; + sp_digit* t2 = t + 8*16; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<16; i++) { + y[i] = p->y[i]; + } + for (i=0; i<16; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_1024_mont_dbl_16(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_16(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(w, w, p1024_mod, p1024_mp_mod); + j = m; + for (i=1; i<=n; i++) { + j *= 2; + + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_16(t2, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(b, t2, x, p1024_mod, p1024_mp_mod); + x = r[j].x; + /* X = A^2 - 2B */ + sp_1024_mont_sqr_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(t1, b, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_16(r[j].z, z, y, p1024_mod, p1024_mp_mod); + z = r[j].z; + /* t2 = Y^4 */ + sp_1024_mont_sqr_16(t2, t2, p1024_mod, p1024_mp_mod); + if (i != n) { + /* W = W*Y^4 */ + sp_1024_mont_mul_16(w, w, t2, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_16(y, b, x, p1024_mod); + sp_1024_mont_mul_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(y, y, p1024_mod); + sp_1024_mont_sub_16(y, y, t2, p1024_mod); + + /* Y = Y/2 */ + sp_1024_div2_16(r[j].y, y, p1024_mod); + r[j].infinity = 0; + } +} + +/* Add two Montgomery form projective points. + * + * ra Result of addition. + * rs Result of subtraction. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_sub_16(sp_point_1024* ra, + sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* t6 = t + 10*16; + sp_digit* x = ra->x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_16(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_16(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_16(t2, t2, t1, p1024_mod); + /* RS = S2 + S1 */ + sp_1024_mont_add_16(t6, t4, t3, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_16(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_1024_mont_mul_16(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(z, z, t2, p1024_mod, p1024_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_16(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(xs, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(x, x, t5, p1024_mod); + sp_1024_mont_sub_16(xs, xs, t5, p1024_mod); + sp_1024_mont_dbl_16(t1, y, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + sp_1024_mont_sub_16(xs, xs, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_1024_mont_sub_16(ys, y, xs, p1024_mod); + sp_1024_mont_sub_16(y, y, x, p1024_mod); + sp_1024_mont_mul_16(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t6, p1024_mod, t6, p1024_mod); + sp_1024_mont_mul_16(ys, ys, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(y, y, t5, p1024_mod); + sp_1024_mont_sub_16(ys, ys, t5, p1024_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_1024 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_1024; + +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_16_7[130] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static const uint8_t recode_neg_16_7[130] = { + 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, 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, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to perform. + */ +static void sp_1024_ecc_recode_7_16(const sp_digit* k, ecc_recode_1024* v) +{ + int i; + int j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<147; i++) { + y = (int8_t)n; + if (o + 7 < 64) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 64) { + n >>= 7; + if (++j < 16) + n = k[j]; + o = 0; + } + else if (++j < 16) { + n = k[j]; + y |= (uint8_t)((n << (64 - o)) & 0x7f); + o -= 57; + n >>= o; + } + + y += (uint8_t)carry; + v[i].i = recode_index_16_7[y]; + v[i].neg = recode_neg_16_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Window technique of 7 bits. (Add-Sub variation.) + * Calculate 0..64 times the point. Use function that adds and + * subtracts the same two points. + * Recode to add or subtract one of the computed points. + * Double to push up. + * NOT a sliding window. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_win_add_sub_16(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[65+2]; + sp_digit tmp[2 * 16 * 6]; +#endif + sp_point_1024* rt = NULL; + sp_point_1024* p = NULL; + sp_digit* negy; + int i; + ecc_recode_1024 v[147]; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * + (65+2), heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 16 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 65; + p = t + 65+1; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_16(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t[1].y, g->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t[1].z, g->z, p1024_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[64] */ + sp_1024_proj_point_dbl_n_store_16(t, &t[ 1], 6, 1, tmp); + sp_1024_proj_point_add_16(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[ 6], &t[ 3], tmp); + sp_1024_proj_point_add_sub_16(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[10], &t[ 5], tmp); + sp_1024_proj_point_add_sub_16(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[12], &t[ 6], tmp); + sp_1024_proj_point_dbl_16(&t[14], &t[ 7], tmp); + sp_1024_proj_point_add_sub_16(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[18], &t[ 9], tmp); + sp_1024_proj_point_add_sub_16(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[20], &t[10], tmp); + sp_1024_proj_point_dbl_16(&t[22], &t[11], tmp); + sp_1024_proj_point_add_sub_16(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[24], &t[12], tmp); + sp_1024_proj_point_dbl_16(&t[26], &t[13], tmp); + sp_1024_proj_point_add_sub_16(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[28], &t[14], tmp); + sp_1024_proj_point_dbl_16(&t[30], &t[15], tmp); + sp_1024_proj_point_add_sub_16(&t[31], &t[29], &t[30], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[34], &t[17], tmp); + sp_1024_proj_point_add_sub_16(&t[35], &t[33], &t[34], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[36], &t[18], tmp); + sp_1024_proj_point_dbl_16(&t[38], &t[19], tmp); + sp_1024_proj_point_add_sub_16(&t[39], &t[37], &t[38], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[40], &t[20], tmp); + sp_1024_proj_point_dbl_16(&t[42], &t[21], tmp); + sp_1024_proj_point_add_sub_16(&t[43], &t[41], &t[42], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[44], &t[22], tmp); + sp_1024_proj_point_dbl_16(&t[46], &t[23], tmp); + sp_1024_proj_point_add_sub_16(&t[47], &t[45], &t[46], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[48], &t[24], tmp); + sp_1024_proj_point_dbl_16(&t[50], &t[25], tmp); + sp_1024_proj_point_add_sub_16(&t[51], &t[49], &t[50], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[52], &t[26], tmp); + sp_1024_proj_point_dbl_16(&t[54], &t[27], tmp); + sp_1024_proj_point_add_sub_16(&t[55], &t[53], &t[54], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[56], &t[28], tmp); + sp_1024_proj_point_dbl_16(&t[58], &t[29], tmp); + sp_1024_proj_point_add_sub_16(&t[59], &t[57], &t[58], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[60], &t[30], tmp); + sp_1024_proj_point_dbl_16(&t[62], &t[31], tmp); + sp_1024_proj_point_add_sub_16(&t[63], &t[61], &t[62], &t[ 1], tmp); + + negy = t[0].y; + + sp_1024_ecc_recode_7_16(k, v); + + i = 146; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024)); + for (--i; i>=0; i--) { + sp_1024_proj_point_dbl_n_16(rt, 7, tmp); + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024)); + sp_1024_mont_sub_16(negy, p1024_mod, p->y, p1024_mod); + sp_1024_norm_16(negy); + sp_1024_cond_copy_16(p->y, negy, (sp_digit)0 - v[i].neg); + sp_1024_proj_point_add_16(rt, rt, p, tmp); + } + + if (map != 0) { + sp_1024_map_16(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[16]; + sp_digit y[16]; +} sp_table_entry_1024; + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_16(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_16(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_16(t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_16(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_16(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_16(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_16(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_16(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_16(t1, t3, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_16(t3, t3, x, p1024_mod); + sp_1024_mont_mul_16(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(y, t3, t5, p1024_mod); + } +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_16(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* tmp = t + 4 * 16; + + sp_1024_mont_inv_16(t1, a->z, tmp); + + sp_1024_mont_sqr_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_16(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_16(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_16(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_16(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_16(t, 128, tmp); + sp_1024_proj_to_affine_16(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_16(t, s1, s2, tmp); + sp_1024_proj_to_affine_16(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC | !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_16(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 16 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 16 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_16(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_16(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_16(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[16]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[16]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_16(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_16(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_win_add_sub_16(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 16 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_16(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_win_add_sub_16(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_16(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[16]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 16, km); + sp_1024_point_from_ecc_point_16(point, gm); + + err = sp_1024_ecc_mulmod_16(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xbf9c7ec6e0162bc2L,0xddecc6e310a89289L,0x5d599df09e499d81L, + 0x9a96ea286d358218L,0x01aec7d370c5f8dbL,0xe72e49958cf5d066L, + 0xc2e7297d3e91d7f8L,0x8621db92da9f2f5aL,0x4b26c8675a5679edL, + 0x233385df2c56aac1L,0xb88e74d4c6a13f99L,0x1214b173ffa8ec11L, + 0xa0386a271f3f9fefL,0xbd9b1b4ec0e7b44eL,0xafe528dceecd3496L, + 0x8dfff96a1c49f80bL }, + { 0xb4a4753ac03c0c83L,0x68e69d18abcdcd75L,0xe3839b88f775b649L, + 0x803f949abf58f352L,0x5f702679bd0bc15cL,0x85bf5d168ff298c2L, + 0x3f6ebd98c6c7976eL,0x20618af445e3e1b4L,0x67d5598e54e64093L, + 0xb047283b504fed9eL,0x450cabfd70d87517L,0x47d628bf3f5addbeL, + 0x0037ef3078cb4ccaL,0x4e148d3c6b1c4908L,0xe256d3294fcfd837L, + 0x2aa1207bde3c01f3L } }, + /* 2 */ + { { 0xa95b6dae01900955L,0xa5dc9cc1ceb4656dL,0x50c78907e72fe95bL, + 0xa1ae5447a040c334L,0x911913707952ea6eL,0x54ff73436d097305L, + 0xa4db0074bda4d10fL,0xfd5306f191644070L,0x14b9fe738b24522cL, + 0x1468dad67849f762L,0x87b29a18b0dcd2e4L,0xadd7f1a15e1ad492L, + 0x9ac63a81dbba2a1aL,0x01379c5b81223379L,0xf402b2f0b0e53bc8L, + 0x8c3eb27f0bf13b61L }, + { 0x9a4ad3e1e513696fL,0x0350ba5c18c81ffaL,0x1e2fc1363c033d13L, + 0x53da6e7117a531bcL,0x42ec64901aed610dL,0xd33e8df7e99ff567L, + 0xe4aad73e3deed12aL,0xd983b465180f4debL,0x99365269502f30b4L, + 0x7e2799aba8918d7fL,0x0ffe84b6700fc79aL,0x7b4400d640bfd8c2L, + 0xc3a21d215d2641bdL,0x79839442c32621cbL,0xace6500bb1401e83L, + 0x7bf4163e251c4310L } }, + /* 3 */ + { { 0x1c174f88e3fd589eL,0xdb501790df974a03L,0xd09623e33e70549fL, + 0x8d091eff15924f34L,0xeef79cadf9b65ac5L,0xd2cc42623f69c2cfL, + 0x817d903252cd82bcL,0xacf4f4d9a5f1ddddL,0xd06126355011b6bdL, + 0x9f74490d2ed140c9L,0x64092e8c4db686d2L,0x225eef16776b0fccL, + 0x0e8c01e9df16aeb6L,0x6283674184bbd82aL,0x757574e28956e337L, + 0x9871edc6705a7f07L }, + { 0xbd0b76d5776535f7L,0x5214d6022635b3b8L,0xc0c25ad99d216f64L, + 0xfd4df3a75515bf75L,0x24a625bc5e9f1675L,0x3c35efb7406873e7L, + 0xef5c9a33bb2e5c4aL,0xa971b35e806b198aL,0x9f5c0ca5a3c690edL, + 0xa8d5dd898e1e2341L,0x4cecbcce955ad9e4L,0x2ecf4407248d3416L, + 0x1abb381145c0af6eL,0x3f4bee821c780fffL,0xd14df768c272ed57L, + 0x397ed10a371637adL } }, + /* 4 */ + { { 0xcf3e0bb2755c2a27L,0xd38e42f959585c44L,0x46b13e0f19285e60L, + 0xc3ecd0c076273d0fL,0x7800f085193c569aL,0xf04e74ab4351818aL, + 0x9258aa388496363bL,0x8456617cb8c894feL,0x8bc62aaa2af969a0L, + 0x66c2280b5a4668d9L,0xbc9df58ea992f4faL,0x5db0b7d93f401e99L, + 0xe0614fe1c4c38c0eL,0xd531151c2ccdf6b3L,0x1c7575ece143b618L, + 0x40247985df9398a4L }, + { 0xfba251788f055746L,0xc5ba00400ab1e6e0L,0xe1b194fbac292697L, + 0x771521195b4f4740L,0x250091d09bb7ba54L,0x7a674861b9a139a4L, + 0xba8413b3f353aa7eL,0xafe771922443ceeeL,0x14468d363847bbd0L, + 0x61f79ff63da4942dL,0x1563a1c1d425b456L,0x3c270fcd75ff4630L, + 0x42072090eb2802c9L,0x68f0cdcbc85c7004L,0xca4372fbfa032e74L, + 0x1a6fd1e6c8b79d80L } }, + /* 5 */ + { { 0x967a901a8d5116a3L,0x0b844394b2f5f47fL,0xe39ad45260ebaf3bL, + 0x1e1be61760ccfc0cL,0xac07e3d2cc3f53f2L,0xdd838e0e1ed11bb6L, + 0x454753071c15b0c2L,0x70dd4748920fe5b8L,0x1a20be2de471896dL, + 0x3c3fad8a59276c7cL,0x026a1cc3c886ee07L,0x9fdb6f376e831ac4L, + 0x26a35d1aac501d65L,0x0ae9890540da8574L,0x65dde0a4abd734e5L, + 0x29b7d4dc15614750L }, + { 0x44b3c2cbcbf4e20bL,0x1c3f548f58cc44c5L,0x39809b545b0cac1fL, + 0x0c0f02b500f80621L,0xe612b890066905e0L,0x8f158ed78350188cL, + 0xc01dc4583f5576b2L,0x29803272a45492e0L,0x77a5623a0ff92443L, + 0xd12a2b0029d0dc41L,0xb41254592780e87aL,0x1ebcf9030d53f272L, + 0xbae6ea4024301e8dL,0x1e5f3f2fa37d0798L,0x9342c31022b4126cL, + 0x5d0928025382497eL } }, + /* 6 */ + { { 0x583a2b7eff2f780dL,0x34d26820d7d76b1dL,0xe3c3284786f74aecL, + 0x0fd4221210823febL,0x227e417efb5e7bf4L,0x510d49b6a568f8cdL, + 0x53bce7d61781bbecL,0x9cfe3f222f3718b7L,0x7f44e89fd9de6c1fL, + 0xf1cc553f3fac9b55L,0x9d2d0846e6f300bcL,0x976c82a29f0ae6b1L, + 0xe63dbf5e24b8bbe0L,0x4cac7f45973a5aa7L,0xc6eb623784dd33c7L, + 0x0a26e434142fee5dL }, + { 0x8081339facaa9a08L,0x40f311055246ece1L,0x892c817061393747L, + 0x8d8d4103242f02e1L,0x482bfd203b5de98aL,0x89ef946b5abbe952L, + 0xb8d218b937698249L,0xd5268e8966617c7aL,0x962e75518b7d2b91L, + 0x2c5c7973fe8d67c3L,0x42e3150a2b017c51L,0x6f4e5ebcc1a29469L, + 0xa39910ce531c7083L,0xaf4f6eb4b77b9e50L,0x68cbb175da120ad0L, + 0x19497c61b92636ecL } }, + /* 7 */ + { { 0x6920b0c6417659a8L,0xc77ab9c792cb28ffL,0x55b67180b687797fL, + 0x4caf58c1e7759363L,0x5155bdb65561b186L,0x2e64e355780f4946L, + 0xeb0ac9b7229a8b20L,0x88594d782571bd60L,0x5dcc0939e3fa78f9L, + 0x7b8b48302ac2d379L,0x505fbf60b90f1444L,0xac610e813ce4b3c1L, + 0x39a4f27ad59b5c18L,0x5fa339737cea0222L,0xe578730b8dff1c7bL, + 0x96b91b8b517bf7a6L }, + { 0xc1a991f49aac087cL,0xce62f74e6cfdb28dL,0x08d6ff9a5f7600d6L, + 0xd781cd04f917f9c9L,0x7796f5f63de52dbfL,0xe7db64e02ed72180L, + 0x0f0876f66fa4137dL,0x3271ee643ca1f716L,0xcb9b20587c4ab8a3L, + 0xcba1710739481047L,0xdf9a190d598c5c37L,0x0cb6e72a6f20e125L, + 0xa3142204f4f2902dL,0x42d28cb97ce2dcfbL,0xdf261b8aa3d3c351L, + 0x73f3d315cffc249dL } }, + /* 8 */ + { { 0x5d86855be6fd3673L,0x309b70af9d214b7bL,0x8d332f90dcc46cd3L, + 0xe553c015595510deL,0x5746a09638c1251cL,0xcd7cea5b85cc1bc9L, + 0x4ffa1468002eba8fL,0x10a3cb7022fcd77cL,0xb6999dfbc4ea05e3L, + 0x3375a0d04efa756eL,0x4d90279edced5fd8L,0x48192403251fd56eL, + 0xe87633a482a4c5f1L,0x3170d1301b34105bL,0x93998b0f7247e578L, + 0x88934f64436ba1faL }, + { 0xf09f43b04713eabcL,0x4ca7dd91accdc517L,0x27daa63bef13ca7cL, + 0x8b2e5a7a2588184bL,0x0a8cb612d95dc269L,0x346975a2e1f2f14cL, + 0x1f29b8ede172935cL,0xc3cbfd6ed40bc1e3L,0xd3f46b3f132623daL, + 0xc115be6dfb0b7681L,0x5e31c34556da4344L,0xa7c63f18a8e43d98L, + 0x55cb20834bddb4eaL,0xb16a0c384a54f58cL,0x74eacca246fd69d9L, + 0x0d1898bb153548e1L } }, + /* 9 */ + { { 0x4ea73461e35ef043L,0x107b67d93496b564L,0xd62c173bd0f83a3cL, + 0xfad4b03851d29c35L,0x3f42882a71b1c1a4L,0x5d2bcf6654b43b9eL, + 0xc77b15aa2abdf543L,0x5cb38a80dabe3dc1L,0x15fda0aea481673bL, + 0x86996b4de7b90ebeL,0x84f87e252bc8f3d8L,0xaded03d637c4e424L, + 0xe5ede666d7a7afd8L,0x80dd95a2a1ccb93aL,0xa55cfd2546fba391L, + 0x2bdab1dc46f82e60L }, + { 0x7a4de22bfa6fed61L,0xca458aa5cc8dd94eL,0x3e372df1071222f5L, + 0x06a4b44fe5aff377L,0xbc2d0ba74a738e6dL,0x1a470e1d5f31f136L, + 0x77ff933ae102a911L,0x8b380a50310c7885L,0x9f3c0228783fc5acL, + 0xec66892544725d06L,0x878f0e165ac84221L,0x9a3af1afcfda6e8aL, + 0x0183ed3778cd2abaL,0x32cdbd60826d0eaeL,0xb3234661cbee6415L, + 0x353eb892b9c10120L } }, + /* 10 */ + { { 0xc8fdcad610b5521eL,0x1a11b44052e702f0L,0x6302680d8ffda49cL, + 0xcdb9654acbf36badL,0x7b58ce114c10a2d7L,0x1e5d1f7de630e7e0L, + 0x8cbe3d7d6760a813L,0xeb35866b6480d77fL,0x58728cf37f036219L, + 0xdd5865ed42a8a757L,0x283f1f1d906a2870L,0x79e23fa4a51f906bL, + 0xf2ac6e83543b20a8L,0x4f0b6379b81e7754L,0x57fbc0d4840016eeL, + 0x8da20771e621b67dL }, + { 0x3c855004ecce65ecL,0x76d10d1fb748185eL,0x64be7bca78797ad2L, + 0x43444db077e54aadL,0x17b6b0c9be0df0ffL,0x8fc4256c055086a4L, + 0xf952c43bfd74d5a3L,0x501e005a01c4edb8L,0xd5172dfc4a57e328L, + 0xdb40ce4e535d6ee3L,0xbaef1e5c0c650918L,0xe85145e7857561fcL, + 0xe468536a34a224c6L,0x69a8e2270ec0e0a2L,0xb3f52247242b03fcL, + 0x862f55e2c3bebd5fL } }, + /* 11 */ + { { 0x2d6a390f226049feL,0xcc92a578dcbbc9fbL,0xa52feca497634fb7L, + 0x2b340cb63dea5893L,0xa39f338a2a49e916L,0x26b2df3d949e41f3L, + 0xc71c7cdb065a7e40L,0x4a9b84a0468281a2L,0x63eeb503731eeecaL, + 0xe6d0913476cbb725L,0x0cf979a9b94a678cL,0xb44d8c3b808fd9f1L, + 0xe60da613e0afc5b9L,0x52dce7de3ea5be69L,0x3a5d6864dc1ee74fL, + 0x71ab28913bc80790L }, + { 0xcf618fc43b5b60adL,0x0afb5e304a0c3184L,0xd22381ccbc403302L, + 0x33cf8953db1c0c66L,0x9c994e4da6112a8dL,0xd7aae2c3d1967a86L, + 0xc28d54935b7acd29L,0x8075bd136c9a57fbL,0xc9c0373e9c8427f9L, + 0x2cbca18d193225f5L,0x73777d13442c018cL,0xebe5ed47fbb3a727L, + 0x70437d491962dc18L,0xf39c1e092dc08806L,0x03e9c6f715fff35cL, + 0x8d087bb65e360a65L } }, + /* 12 */ + { { 0xbe2123023fdc1844L,0x6eca27ef105eac56L,0x2183a606f168a348L, + 0x295f807de1d7a4cbL,0x7246a6327ef5d43eL,0xae143205c77025c7L, + 0x4bdfc7caf3484e3eL,0xec939895df52c075L,0x82e655f6d7a9cac0L, + 0x985dfe208baeddb0L,0x79c817e4527de731L,0x30ce0fbc313de1eaL, + 0x9df95b89cc4f6cbbL,0xf2aedf1ef5bb20cdL,0xfc1e0a891a8cfb01L, + 0x225ed34a63edb7ecL }, + { 0x3e13154dbabb1a85L,0xd3d8dae71e6a565aL,0xd3217d56ab4b100fL, + 0xd44d934eebc78e1aL,0x0215321b48e73d37L,0xbbc90bfa201e43cbL, + 0x3c23f1d027500905L,0x2a2e5000c86691a1L,0x08b2bad26065841cL, + 0x15d41caf30026b60L,0x1712c2f45276ce61L,0x01c4c3e715932ffbL, + 0x7894e13d6a74caf2L,0x02d6f5df0c0537a4L,0xa8fb7602c2b1c97eL, + 0x612b60e5d0887c7bL } }, + /* 13 */ + { { 0xefd495cfba245d6bL,0x5cf0cbb7a2ce3ff6L,0x24da2ac0dff5feeeL, + 0x90c914f8cf28c6a3L,0x72fdb50d4308a56bL,0x03dbf77913d72034L, + 0xcfa5ec91822ac9e9L,0x0dde73c83aea3e81L,0x545ba96266289139L, + 0xa52f648bca6acbd3L,0xff6f276e98a0683aL,0x2536d3aca378ed52L, + 0x353c2c54885ac1d9L,0xcaff52da00bc84a7L,0x3971f81c37684167L, + 0x0f7334e1d2d7986eL }, + { 0xafbb5c836596067eL,0x33e54e1938c19806L,0x8285d96739cb0dccL, + 0x2b53f43d424035f9L,0x38c531f8dfef9095L,0x90fbe8e4db0f571aL, + 0x9a0c1ed2a39ca787L,0x2fecc1d6606f2620L,0x9dc890b172b7cb4aL, + 0xc33ca6fbccbb7868L,0xd1b11082fe73ee49L,0x590b7d17fcb66c48L, + 0x9356b0a686e14573L,0x75d682c4053ead85L,0xb2ae55fac54d30fbL, + 0x67636a72f8aee949L } }, + /* 14 */ + { { 0x638063bcb91d6beaL,0xae263a2e923ecb96L,0x9d7b0992c627aca6L, + 0xc6ed001a77af9e7eL,0x9214accf24aafebbL,0xa3564b9678055a90L, + 0x00999b1ce027499dL,0xe413a4e1e46a06a5L,0xa05d13f62e51efe7L, + 0x35e87d349ba843beL,0x0a6338253183159eL,0x6023e8ba54601923L, + 0x9b107721b7fd1cf2L,0x46b5542bfdf2fd53L,0xb314f4f81c18af38L, + 0x086f987660ac8965L }, + { 0x767019548cbb9850L,0x6210b730a20d2c8cL,0x4084d0575335670cL, + 0x3ecdc5950324baeaL,0x607fc5f2c76ee9b4L,0xf393d00f440ffa64L, + 0xe01117962dc1463cL,0xf00b82519c7725e7L,0x35e607365bd1d186L, + 0xf3d8554c2cf72aacL,0xb4dd0fdeefa3497dL,0xd712268cf646ad11L, + 0x07c20afb9f7b8eadL,0x630969d4fc06dfe5L,0x76b7df1c7245549aL, + 0x681f9403e61ae810L } }, + /* 15 */ + { { 0x7cad5163c9a0623bL,0xdbf8295767fab8d4L,0x2ccab0ec81af7c7cL, + 0x469e38c8e966d5c2L,0x34430d52f0d4e41cL,0x426075a2a52b359cL, + 0x242dd3e333bd0127L,0xcda3f6359fed2341L,0x4df33730d7d52ffaL, + 0x5fff56f07640c3efL,0x4783c21c1bbde57cL,0xd8784a2aeb8bb336L, + 0x1ec7c533ead08405L,0x4b7f1423f9b62bd4L,0x5543145c7075d4afL, + 0x0c9de94aba60590aL }, + { 0x8ed7273595d5682bL,0x711c42832ec276edL,0xd1f4aed58b36a0d2L, + 0x62ab40c48498a88fL,0x58c8fc624480f451L,0x8bc8ca4bb79cffe2L, + 0x90ab583c701a359dL,0xaee31a733fd5d15dL,0x02a5597bc912333cL, + 0x1019cae4b6c3e3c2L,0xe513042c29938088L,0x0e00283df47c8199L, + 0x90d68e58f2a00e92L,0x69e2df41a775ae3bL,0xb8d2eca5871c30b2L, + 0x733dca0ebb1de396L } }, + /* 16 */ + { { 0xf5b495d04b59213aL,0xca6720398d70200eL,0x4bcb09a62b6771c1L, + 0x26adeed42b9eb0cbL,0xeb5447548cdba212L,0x0e1abfcdf08890d1L, + 0x52509963698e46b4L,0xe1bff0b082e9c138L,0xa189e4cd51099a71L, + 0x2360c9bcc9b91cc7L,0x9bd4d7dc137ec4beL,0xd0356521d1519f6eL, + 0xbf5f6d78cf832503L,0xe43010318deea2b4L,0xc3132494ef4c319cL, + 0x2ab3bd470f1fa7d7L }, + { 0x5753b680922c9fbbL,0x869e7dc80f16c6d1L,0x83445135bac16efcL, + 0x4326a3b4846d1d9bL,0xb517fee3b2d62c21L,0x6905afa20b292ad5L, + 0x2a57131a2cadac13L,0xcd904d8febdbca8dL,0xdfeda86f3f365fb2L, + 0x7097b208dc7eaa1cL,0x89a35a84a45e77c0L,0x417a062ccf5d118eL, + 0x3c0c04a81f6e99e8L,0xc44704b0ba7a087dL,0x6f8a27d13ea22ad2L, + 0x93a4b4164c27d229L } }, + /* 17 */ + { { 0xd4271bc11f1efb7aL,0xae4e68e633fccc0dL,0x9d9bc8f1b11f50a8L, + 0x5430398faf076089L,0x45e242fb443d0e03L,0x73ec2519f6e3d4c1L, + 0xab70f790ba9bad09L,0xde612ad5f9add10fL,0xb837e54e14e942b4L, + 0x175a56d3ddb8b68aL,0xe85b233c1ac2a408L,0xf8ff6c30f0c80f94L, + 0x4b7f3fb7898db4f9L,0xa2c6044f45a7dcddL,0xf3abb2f6fe3d3895L, + 0x342ce0d732ee7763L }, + { 0xeb261394cf491b1fL,0xdcaaeed71909e395L,0xdcc4055a9fe4dbeaL, + 0x17a6611d493d604dL,0xba445a3a1ce5ebefL,0xe82e2858e3989cb5L, + 0xb96f428283f58406L,0x99877b99a156cf55L,0xaf906a664e166a0eL, + 0xcea1d353b2976d13L,0xefc16f2736c61a01L,0xdb04c433b0f55d86L, + 0x3cb4b2698eb34c01L,0x38d07f782ae60280L,0x43ac3bcb43be3ec5L, + 0x455f4af3e156fd20L } }, + /* 18 */ + { { 0xc057f262754ec21cL,0x3eacd4c9e3a1ba38L,0x3a0210d1116c1fe9L, + 0xe4ea4e94eacc8ab6L,0x31c00c9aea6f32caL,0x5cb6239d86b975ceL, + 0x654d5d8ca14ea1e9L,0x230d31f45067fc8bL,0x48bb90cb6355fecbL, + 0x78f81ecedc172e8eL,0x288380a8cb006737L,0x19b02e01e162d012L, + 0x0e087a06c5af145cL,0xf04dc8b7b72dc354L,0xf70ef2148de3c066L, + 0x4f14824313009fb7L }, + { 0x5e004fce6e2055e2L,0x89e247ea86c32067L,0x4ebcbd955f9daaa2L, + 0xd15f212fceb7f63bL,0x5ecc5c1f863784a0L,0x53b3800b75760251L, + 0xeb9301c38a6a2954L,0x0f16ba18a13cdd19L,0x8313d251887c2d24L, + 0xf99235859a9413f6L,0x423405e6fe3fd7c5L,0x678aeb3416e0ee05L, + 0x1f3be7bb3fadaab0L,0x7901fa2c82884471L,0xc950db304d662ff6L, + 0x74d5d2d43c01170bL } }, + /* 19 */ + { { 0xa3002dc02b5bfe11L,0x0733410d52d321e7L,0x15920f659679ba89L, + 0x0e248c14685b236eL,0x8cfab594346f6040L,0x9f57afb740c717f0L, + 0x0dbab28c66044576L,0x0fa099689cdc3247L,0x41e02ae2c230ed05L, + 0x0d961554e45bef74L,0x9688a982ce4d7b6fL,0xfadefac75e62d22eL, + 0xaf1512a6bd2cba28L,0x78868e62be7c749fL,0x88048d81ae9f5a6bL, + 0x6b1a5442c5857a29L }, + { 0x9f5ab9ad43242066L,0x0afef1b52ccca2aeL,0xb1b43ec7988edc4eL, + 0x0d0c00f10341b0d5L,0x4d68b8f7b50aab37L,0x9a8e4e6ff3a64a99L, + 0x198338fb7f1a684eL,0x8bc0e748351a0f5cL,0x2cacf2cddac44515L, + 0xc14d39995e9ff76bL,0x54a01b3f16393055L,0x6ac3eea5888d8376L, + 0xb84d9a9a723277b1L,0x99132691e11dbbbfL,0x597717aeabb67178L, + 0x4c2135268bb14ac8L } }, + /* 20 */ + { { 0x2e6fe0a695532833L,0xabca228ed626d067L,0x22aef3d9649e73bdL, + 0x2083a87af03c4c0cL,0xe954e75d35169b45L,0x577509ee74506a89L, + 0x49cb276e2aeacf90L,0x08275d77fa409f91L,0x61eb6f3df0bbd6b9L, + 0x948202cbe4132704L,0x35f3fc21b1c498b1L,0x76c68ba8361fee59L, + 0xa18cbbd950e051f3L,0x2384a879318e7042L,0x292abead80dd1e8bL, + 0x65713c295c37c334L }, + { 0xdccca8e9ceb77b9aL,0x2f97e72723b69469L,0xc76abee6a01d6b28L, + 0x3925203d5abecdfeL,0x8944808229290d70L,0xf9931424b0314438L, + 0x04209df17cd447c3L,0x7c6f2059c855c827L,0xd97d786256c0e069L, + 0x5a9db6fe412d94c4L,0x19a64591994c41ddL,0x12348aa1c89e21a3L, + 0xd6904b50c6a03f0eL,0x55c15156a616feacL,0x4e36d1b57cc7693bL, + 0x6b0e996c3bae3c38L } }, + /* 21 */ + { { 0x32789fabcceced00L,0x3237e71ae5b7aa66L,0x87b2e2692ddebcdfL, + 0xb7245120b61dad8fL,0xe11e5e48d35f803cL,0xfb4df5d798e50f0dL, + 0x60ee68b4bcd2ab92L,0x98ab2f5c1ce3363dL,0x15ba39da7cd42647L, + 0x1a6572eb83f4fb3fL,0x0f77de88e56f08dbL,0x1743761e172562c2L, + 0xbe349ff88a58f0f4L,0xe04da71b84d1d6e2L,0x368f03429e9ff3b4L, + 0x4022a205678223f8L }, + { 0x527bbd0583847375L,0x3ae56b623f451af0L,0x6198f24d4b2c7f18L, + 0xee323f5b4525b98dL,0xa9d8d39a0e0884b5L,0xd005d7f6fb12c776L, + 0xd71c483e708bc154L,0x8ca6fd28742541bcL,0x0af3dccdf8397ddbL, + 0xb80d31253eccf243L,0xc743a10858d81b8dL,0x3f48eb2171391f68L, + 0x493aff8833bb657fL,0x1d15ed6607e47e31L,0x10159b11e08279f6L, + 0x312179cb24a6a956L } }, + /* 22 */ + { { 0xa94cc3ca07615ac2L,0x85865e64121ad581L,0xae47616fa7986b79L, + 0x395a40eb9d5e0f1dL,0xa91432643d9457eaL,0x8de6d6a3fa2865d9L, + 0x0771db961014ae8cL,0x77a7cce6976a87cbL,0xa7de42e1143a0f60L, + 0xe203cc09d993d934L,0x9201869398ec4c3dL,0xd77546d83a25df4bL, + 0x0ad9eb4762b02d6bL,0xfaaaf208d05a7189L,0x5238181f431221bbL, + 0x417d6c78733511eaL }, + { 0x3cbd81b70e91e9a8L,0x73340418c370d6b3L,0x825db10a8eaa2373L, + 0x8f2b09e46c7d6756L,0xe288ee9b94c33dedL,0xcd8426bb1695e3fbL, + 0xa6176c86dce9e888L,0x3f4c89226165e362L,0x514e411f6063fb09L, + 0x6907ac20c8f9e04cL,0xcef7469cdfd2ad61L,0xba30bae48452199aL, + 0x3068129312ac3462L,0x011be873c92d482dL,0xff4cbf89e8330995L, + 0x02189d52d1470a0aL } }, + /* 23 */ + { { 0x73e419dd92599c69L,0x5b94221b7fec32caL,0xb2bf9bd209bbfbfdL, + 0x61ea97a463ed895bL,0x6609146b3f486f79L,0xbd1c7a05fd141a39L, + 0xc79ec8cf83d64135L,0x7f8fd42f9883507bL,0xafcb53b717b3d027L, + 0x86658dcd67ca5a21L,0xa6a6c0accd149786L,0x16f3d70e34b95067L, + 0x371208e3df44958cL,0xd2dd64e6ec280212L,0x33b2c4ab30782c71L, + 0x7bbf8abd521176faL }, + { 0xbe9e4aafa78b981aL,0x788b4e36304ec828L,0x0c45cf393959dea3L, + 0x70a9bdd3240b39c7L,0x499cd7dd28383b7dL,0x30690b2e307a1026L, + 0x2262d598ee92f1b3L,0xc62d77deb4725a48L,0xa16f25bc7bc3aa0eL, + 0x62dd8b65d15ef7faL,0xd979221d0b96d68fL,0xb92885c3a00f1906L, + 0xfa476b9beb74c740L,0x217ddbb5c7576222L,0xc2782c305788504fL, + 0x860d096cf812716bL } }, + /* 24 */ + { { 0xfebc337d4d79bbf9L,0x5d53eab869f74f80L,0xff36a09533104d53L, + 0x2ab820da196f8b97L,0x961d3d1f75ce6909L,0xb197ec0404683754L, + 0xa68ce1bf93a6cb9bL,0x503456ffc5f021a3L,0xb50a2db18940ffdbL, + 0x77c50f8fef004209L,0xd635d17704965875L,0x725766d98bb8770aL, + 0x8e19b028a078e53eL,0x364d4ccaf9fc8378L,0x1a3df411f0dd39a0L, + 0x7e80e44203adf920L }, + { 0x4b5f8a57539a1ddfL,0xd248e7aeee486562L,0x1c7b491d816021e1L, + 0x2e7b871bfd36d2c4L,0xda38b5040aec00d9L,0xf28276126193f1b3L, + 0x69c3fe86fb1f78d6L,0x56c8b786e827ac33L,0x1687f6c73487c8f7L, + 0xab8f221719dee5bcL,0x04e8473fff399418L,0xf384c014a9027c80L, + 0x9967be9aaa1d2e28L,0x869686d3e065eef1L,0x737c6b08c7bd837cL, + 0x5dcab5d19e8bd863L } }, + /* 25 */ + { { 0x0784283a9a7d772bL,0x6b49e525e540959bL,0x546bb00886414ab5L, + 0xd44481629d74b2a9L,0x267890ad203b0b1bL,0x1e7a82bcc8d3f86bL, + 0x1352bfb5d85a83c7L,0xf29f16e3fad07ccfL,0xc02a63b841e0c43fL, + 0x904f22c56b379fefL,0x19d8a653b1244f26L,0x6635b6df3a28bdeaL, + 0x18b68851f6d455ceL,0x74ac28189cff3735L,0xad40f9df8b2cbdabL, + 0x08cc2d9eadc9d498L }, + { 0x2e6a6866c170c84bL,0xbb989e8b5a49a484L,0x7b0e00e0d04c8992L, + 0x55ad347861b3a423L,0x3c952450b0d01899L,0xe3922155e3100cb3L, + 0x19265b6ef03276d0L,0x0fe8595a76d42b53L,0x0a96dee0fc6353b6L, + 0x761e0dc8246f893eL,0x4ec902bef0a74cbaL,0x610086843fdfad9bL, + 0x5d6a60e44fdb6975L,0x3f53aac87ef7590aL,0xd29e6be012870a37L, + 0x991fadc155aa55b0L } }, + /* 26 */ + { { 0x82bc4b0fb4844ffeL,0x7392271460f8b871L,0x8ac000e24ce3f1f3L, + 0xf0d548b4163519ecL,0x7aaf842b88288b5fL,0x9e8b0c4c2bdc9a70L, + 0xa06d51524ba5fd67L,0xd0b1afa0f93cdec3L,0x280955badf89f8f0L, + 0x86cbe92deea32c92L,0x0cae3f993fe05be4L,0xf2607095fa6919aaL, + 0x0f54741e6e0f1b8bL,0x2aed1f7430ecf988L,0x9296f76b734991d7L, + 0x66cf8d28259f0fe9L }, + { 0x9b01905b226f5868L,0xc102e88c16909e9eL,0x2bd089164a37eb54L, + 0xf72253e8c9816323L,0x37f84e9d86bac53cL,0x2e352454afeaaaf7L, + 0x67c86f772ca0046eL,0x86bce50e6663372eL,0xf6a3a960b6950a04L, + 0x61f994d7fc1aba93L,0x1957c12bc1326e6eL,0x9b658fe42e56b005L, + 0x9cd297fc8592740cL,0x7654ce9b177f26a5L,0xaaa699dba79d2ebbL, + 0x5fca0c5a0ecb6448L } }, + /* 27 */ + { { 0xe26e25f3569a6663L,0x09597ee7e6aa4ca7L,0x25a4cda68d18b80cL, + 0x450602b522926730L,0x9af5f65007387209L,0xfeeedb3426733a53L, + 0x0f5ce76886572951L,0x872a360b8398ae9aL,0x60347a802b30f6c3L, + 0xd2113b231a162158L,0x6fd9cf92ee6c6decL,0x85f0a5a85cbcf9e6L, + 0xd7a5a6e42ba3fe84L,0xaafe672051ecd727L,0xe09c6bb2a2081a10L, + 0x657acbf0b973b0b4L }, + { 0x3130466fc274c8d4L,0x4276517630a994d1L,0x217258ca7079435fL, + 0x44850406eb897a06L,0xf38dfeee561ee130L,0x11f4facfaa1778bbL, + 0x765c6617b9abb9e9L,0xb135499bd8f10932L,0xc0eb6337a73b9159L, + 0xf2c1ccf16f7e8b6aL,0x5b32c03a187def53L,0x89ad1d49830b9c62L, + 0x1735eae32f10e538L,0xb1cbd9c29d5f55bcL,0x42428c47e539db0dL, + 0x3d2da412c852b3bbL } }, + /* 28 */ + { { 0x97702b6e871f2865L,0x56cb639f142920d6L,0x328522a045b58611L, + 0xf3943ad1f3b13812L,0xe6c2200a712206e8L,0xc2890e5aa34d59eaL, + 0xab52fd40f6b7f759L,0xf522c8de180bf567L,0x181e97b2accee396L, + 0xe0375819c4ea5cbbL,0x0d9985e8ab51d3efL,0xe26c96cabcb50fd8L, + 0xfb9d6b1397e1c80dL,0x582b1814f796357dL,0x89a7822107f4c7fbL, + 0x02aeef2dc0357e61L }, + { 0x2ba7926f2c7ec9beL,0x292f307e7258b201L,0x74e62a10c6fa6b4aL, + 0x80c08549e2bcc5abL,0xb4160db87bb8c073L,0xd5ef0529329f194dL, + 0x0eb8da146dda4a9cL,0x0b5d43d215ea23d1L,0x6cebef02fc34bfaeL, + 0xacd364d0848757a7L,0xc14013682d34cca3L,0x09ca67421d2d95e2L, + 0xc3fd1d6e786eaa28L,0x9eb1136da2965fecL,0x48871baac0779203L, + 0x6b446c014b15aeb0L } }, + /* 29 */ + { { 0xc819eb2e25e8fe80L,0x2b5f790698238a17L,0xd6f1e99681e41849L, + 0x58ad8ad698ea6d45L,0x5bae5ad4bfd02e40L,0x016dc327a812416dL, + 0x8b31a985a3347ca1L,0x0b4da61082a65391L,0x1cb91b2db48c35fbL, + 0x9e96817cd2aaf8c4L,0x1a630483cdfdcdc0L,0x7055936112b69254L, + 0x5fdcd712f8a2a097L,0x59ab623a35cc5281L,0x30c8ebe0932b6095L, + 0x8613424bb08e052fL }, + { 0x28902063b2231d8aL,0xb0f62329d9a61667L,0xaafa0fe7071a9f27L, + 0x6bcd8960603f047eL,0x118cca76fd92a1c3L,0x3414e62b71d483b6L, + 0xa123ccddba705262L,0x1a576437fd9b5c5aL,0xa5301bc24c8d0fa3L, + 0x96f0ad44102427cdL,0x0e6fb5e0d3aa6c02L,0xcd8c4880072a3996L, + 0x4dafca12840d3fadL,0x29f4ca3dde91d541L,0x0037c5988441734dL, + 0x86333a999ccfe57cL } }, + /* 30 */ + { { 0xd213a751ecf53b40L,0xcff2c6f22f78a542L,0x0f59f0e2f13ae56dL, + 0x91f8ccbf0e61748eL,0x0aadecb9d72c4145L,0x6b2ed8524c9cdcb7L, + 0x8e00b72c1eaffc70L,0x89b24285aa728102L,0xaa7ea7e0b679cafaL, + 0x5d2b8c264f0a6f6fL,0x7ed7b1730e804397L,0x5a93eb45c8573049L, + 0xc92bf5d40986e93eL,0x526b5a9c6a20c0afL,0x0adf47c9b99dc3afL, + 0x12b25fe2ba202cc9L }, + { 0x09b8d78a33eea395L,0xc7a93618f633fc5cL,0x7e821629270eceefL, + 0x524779b8c628ed0cL,0x91db5ca1a1d68939L,0x8626e18e586edc90L, + 0xfe023e8bfeb3f3bfL,0x6279fde10250171cL,0xe52ec7dc55e172deL, + 0x445e8695c6d4ca45L,0x42de3878bdbc10f1L,0x2b114de86fc3835eL, + 0x9faba4567e10b652L,0x4111d82a390e78feL,0x576b61c2aedf0acaL, + 0x216279a974accb74L } }, + /* 31 */ + { { 0xc14cdabf4047f747L,0x03ca233dc1315a1eL,0x59e7cbd340e5d0a7L, + 0x1fd0c4e9bb413869L,0x189d08b10f01fbd8L,0x50449c42a76b823dL, + 0x81c224a1398b00a1L,0x08084e4f8e8179e4L,0xfd8af994698e41e9L, + 0x1e30e37c5610bf2eL,0x4e6a043fa7d2790fL,0x9d96e60cb3195388L, + 0xe75f986d03799dfdL,0x3b4a8f11f8ff902fL,0xfa9453787588416eL, + 0x20683e3f9827535eL }, + { 0xcb582e26d0378878L,0x9e214c23a7945787L,0x13d000bf8f6688b3L, + 0x7548d4f540515270L,0x7113c15d40111f5dL,0x3bf5a526a8bff902L, + 0xbda6b0109b4945ccL,0x83dcc74ebc2f3a05L,0x2aef628443efdfa1L, + 0xd2e60ee9565c5bf4L,0x4f0fa10d592f243aL,0x6ae58b321bc3bf51L, + 0x813b086860576a74L,0x0bc023f84d73081aL,0x9fd03aa032dcee59L, + 0x5e416bf527d6c795L } }, + /* 32 */ + { { 0x24313760026cc23cL,0xf819aaeeb5b29058L,0xa92272f8c5d2ee17L, + 0x8048e7cbee5cc402L,0xdbc7d6ee77def07dL,0x61d69244f6af821eL, + 0x5f7966ed996cbb89L,0xf81b17ea96a155a4L,0xb2d9ef7003f3ed56L, + 0x5e6e5906e882a5b2L,0x86fa1072ae947180L,0x34d9fc51658c76f4L, + 0x9f603dc0cb035aa0L,0xb7b39feb75be6481L,0xca87554acf04a9efL, + 0x4ff682ec87b4fde3L }, + { 0x3125627fd0a10ad5L,0x7fd45c72968e6f45L,0x2981bd6b806a1163L, + 0xb92de1cdde5033e3L,0x3b44b45ebf4f8988L,0xca1b9896dae7e1dcL, + 0x52166e5a0778d878L,0x82d472bea5116847L,0xfbdd382af2895445L, + 0x22ed16025d6ec4c9L,0x3614eb1cb6552b02L,0x63c5df73a1e6210fL, + 0xe9160285021a74a7L,0xa44ca400c65cbd4dL,0x48cb187e0f15e299L, + 0x51eb818e3402507cL } }, + /* 33 */ + { { 0x1fc1d178b92100abL,0xdf2e3d609605b839L,0x12a7c255b71e59d0L, + 0x3f8b667514fcbe04L,0x0e8a393559fd06afL,0x5632650212020d07L, + 0x6696fcd1528e7be5L,0x6588514b0c7b7654L,0x0cd80f8c5912a5b5L, + 0x8bafef04f324cb7fL,0x6b53eecfc6da3d75L,0xedef48d831d1df2fL, + 0xf336b96573812b6dL,0xc82eae4aee626031L,0x300abd32d244f09bL, + 0x8b0af95531d9647fL }, + { 0xb770180a2e603544L,0x2b573ac3221acd9eL,0x3a17f66562407032L, + 0xad3e74adb89abc3dL,0x8a3d2e3ad793225aL,0x457bba04ef02564bL, + 0x8875652ffc2dd2b5L,0xd2905d15e67143e8L,0x6d884b4202e48d70L, + 0x06f99219c7636a57L,0xa8dc342135e378dfL,0x95c1d73d10c64a02L, + 0xcd6a4ececc157a66L,0xbadcc1c88e24a354L,0x8024f1b29839329dL, + 0x5363e5494da48ad0L } }, + /* 34 */ + { { 0x1f5523b7e23fc641L,0xfe54e72f86667063L,0x294a15f58e009d2fL, + 0xf203997f8c57f5e1L,0xa229724cb16d64dcL,0x697be4fd4baa2ffbL, + 0x3f507e460a6e8ed6L,0x0afe3a5d78508536L,0xeeef6cdd95408208L, + 0x701fd889f2c4237cL,0x496d883a5c385253L,0xe25c67ed72a212f1L, + 0x4b4167831ff78fcdL,0xe9967004c16f4146L,0xfa45c3a1c45b0697L, + 0x633340183fbd30c3L }, + { 0x39c9a0cca2fbbbceL,0x876f6e5caa0cb744L,0x9ce6010e3438ece3L, + 0x0aad148e13802d82L,0x9c3e5c609cd45a1bL,0x875cb8597bcfc1e0L, + 0xb19ff790d8584dd0L,0x2598b81ed81c2a2bL,0x118bdf2f02be07e3L, + 0x074fc8eeb9765ce9L,0x125e9d88b24f95aeL,0x3bb12cdc0c98f09dL, + 0x4a6aee07a0b74b27L,0x4723d2f9c08077ceL,0x959447d6bea8026fL, + 0x93a7075c16280b73L } }, + /* 35 */ + { { 0x26bbefe2715b27f9L,0xa935a5e22a280923L,0x5ddf23affd58a26aL, + 0x54c83e167c138694L,0x44799bc9892a2153L,0x4e6e47109b8d09f5L, + 0xc63af616d588ea68L,0x5e896706883ab1b6L,0x3c1393a03d209336L, + 0xd02f292192c23ddaL,0xab70cb7adcf6ea43L,0x12434ea8791559e1L, + 0x040680db6d70ff0bL,0x1a10fe522832ba45L,0xd69f9c08e5f0cb8fL, + 0x1a7422ac44b141fdL }, + { 0xc3a9dd2e9f40b675L,0x2a7c6603fcc71f39L,0x18939a611948e342L, + 0x8f3b6158ed0ab484L,0xa3aa7d97ee31ca6bL,0xbc1e865ef7a8db63L, + 0x315f8c092c7c62e4L,0xa260788f9f5c6d0fL,0xb18331294b6f3ec5L, + 0x73adbcd636b4d849L,0x66e14890bc699a9bL,0xbf3790d82a1175e7L, + 0x7f43605afc53ca4fL,0x577f6c4787ff6091L,0x827c7552600c82b6L, + 0x0944d6309d25599cL } }, + /* 36 */ + { { 0xcfdeb63ee6ab9620L,0xdff4fa6d786cd808L,0x145edd82456320b3L, + 0x2ae5f862c4943915L,0x9508e813b73b3f87L,0x3bd805f3e52f97a9L, + 0xf71b5c28c9829b62L,0xb394c70e86e0cefcL,0x534fb1a923bdb36eL, + 0xd64f5862dbe27e5aL,0xbae23df383ab6169L,0xdd6df1b127c828cbL, + 0x1901899f3a307a8aL,0x36cc8659811ddf66L,0xa3cb777479943b77L, + 0x7d89f3836fd86576L }, + { 0xf8564242c9f92b2bL,0x700c6a75c46e32bdL,0x93e768b77f99a5c5L, + 0xb6efe85803149568L,0xbbfe8a19c2ce6709L,0x721a3b1bee6ec493L, + 0x26eeeea9c371c28dL,0xd798115e15177e1dL,0xd7bf3bceb068a5a5L, + 0xdf8da22046d2b4b2L,0x3df0995b59be9dfcL,0xc96897bc77640b79L, + 0xce0cf4c25a2bd3c5L,0x16f45d6e89afe744L,0xb53f3acb3a8509bbL, + 0x449af81f63f2a6e6L } }, + /* 37 */ + { { 0xc2fcf132a16d9377L,0x9ab377b37e1a2f9eL,0x72e1a12e86d19ae5L, + 0xd2b12e66d013bbb1L,0x0972e055cb5f66baL,0xd11de1c0399eab50L, + 0xc1f314fdc65f5ec2L,0xfc3118418a9ff593L,0xdf73c1ece05246e6L, + 0xc28d13631625056dL,0x30a9dbd76fb25e19L,0x049ed244845cd2d7L, + 0xc779b83fd36e852dL,0x85a35fc7f68c8a83L,0x299bf1e1c95e8033L, + 0x0e8617c320891af5L }, + { 0x5372060267c81b5cL,0x2fa89dcde737873cL,0x2a7430b0a8144fd0L, + 0x3006c5a726208c83L,0x4e066660d8ea40f5L,0x9dd025f9896413a4L, + 0xbdf380cc46b9149fL,0x801566190a125cc2L,0x04d6a3b752793c37L, + 0xb60013746b7a62f2L,0xa9cfe268585d5978L,0xdcad0cb88395fe66L, + 0xbab468fc46b261f6L,0xca0ef5ef9d9d9218L,0xc507d4a85e452402L, + 0x6f4404f1326cf687L } }, + /* 38 */ + { { 0xa3e1920b4febd3ffL,0xca6234d8fdfd2bbaL,0xb7d1af2ae19a9829L, + 0x23de1610c6f5bc20L,0xe204dbf3daa39ca9L,0x2a2de9b86d8c70abL, + 0x272e0c377c9d370bL,0x80914c06e565510eL,0xb611e7a857cbb6b0L, + 0x076fc6efd8266a6eL,0xdfac34ee3095801cL,0x69ff40a2b9e24063L, + 0xa7ba31a9787aa5c5L,0x0e4d1fdf33c70cd2L,0x903e31326895f074L, + 0x905771f87fb671e2L }, + { 0x5199ba0da4062beeL,0x18e7238c94d7d9f9L,0xf53f29bc1e0922c0L, + 0xde9b2a81b12d855fL,0x649f3eed6d68ca29L,0x64adfc34c50c097fL, + 0x81964ab99db398a0L,0x00d59c477a587224L,0x09fea39674c5903aL, + 0x6aafd8ee15043dd0L,0xc5721a6e5f1ecc20L,0xb6d6a4830db9b7b4L, + 0x06ffc61766c8d52aL,0x3de241d6acc82a27L,0x0605f05227f2f7a8L, + 0x6a22953b6404deccL } }, + /* 39 */ + { { 0x92452d8f74fce389L,0x059634c02afa5564L,0x9377ccbbf0ed7825L, + 0x89f4045b37718e0dL,0x11074e7d9fa69a4dL,0x5d70bb077295b0baL, + 0xb22d54adf107ede6L,0x5c39a3d8a1a29c7bL,0x37236c02d795e3abL, + 0xf7282d002b589951L,0x5e2265be5790bee2L,0x91e0ea11a8e65ea2L, + 0x0e71a7086001cebdL,0x16900f5a2c1c5402L,0xc3b2d5c0357f6981L, + 0x528c9ea0619e3427L }, + { 0x1edc86b45f26c577L,0xf80747089438bd45L,0x2dfe1013792582a7L, + 0xe08eaca0de1e569fL,0x5f952efa9a55a356L,0xa4d80b53e4976216L, + 0xd2b65855cd5d71f2L,0x246704bf66cea3f0L,0x193f641f492323caL, + 0xa681855c9adb1325L,0x86d522ce2d19d652L,0x53609f105b82ed7bL, + 0x3b0f00948e150d29L,0x23ad8bfb0b13e891L,0xcbb1556cf794b449L, + 0x200f9093738bcf57L } }, + /* 40 */ + { { 0xf9b22fc58388387fL,0xcf26f17028e883c5L,0x447cab90d1b7973cL, + 0x8d5d4ea2f6ec9171L,0x2e16f498c30cdbc0L,0xdc92910c48623c2bL, + 0xeb1491b030dbc545L,0x631deb2e14de21b0L,0x04a210662fe830f4L, + 0xa4c6979c379c1f3fL,0x8a732b68fb06a795L,0x3a44327a1619dfa9L, + 0x91a307d38dbe2c9bL,0x939bc8d203989feaL,0x3daabaf20f4a331fL, + 0x5c307e98dd0f55dcL }, + { 0xbbc4e0c435b233daL,0xe3d2908522f6f985L,0x99dd2d21a8b02468L, + 0x978f40e9a96916e7L,0x0327d86c614bccedL,0x95e95502b290762cL, + 0x0ffd2197a879f2edL,0xc436513750e0bd33L,0x26c3148a0827c4c4L, + 0xc79812a83fcfc0b2L,0xc3d8d17e31928589L,0x8b572cfe8830f42dL, + 0x7cd9ff924b07f83fL,0x331ca9500a51148fL,0xd0c539684c59f9acL, + 0x1df16dfac1434785L } }, + /* 41 */ + { { 0xcc7bb4ac68bcacc3L,0x06ded34f430f58cfL,0xc59f9f4fd461855aL, + 0xf549199445c9f0bcL,0xdc5f7ec64375c892L,0x1b8708f13c85983aL, + 0xb32a5cc482fcd087L,0xefdcdc352d6b4c0fL,0x4bb24f048ac6fb2dL, + 0x5982d4f533906471L,0x162eb52fb83a3ac4L,0x7130df282337a223L, + 0xdce7b802cbc3dbd3L,0x8b3959592467ac0eL,0x21d3d2e81b56717eL, + 0x729a7f5046512617L }, + { 0x874ed1aa8420f90aL,0x6368e19e0fe4c855L,0xb62d4aaab0be74afL, + 0x76fcc4808ca60ca9L,0xf310b5a57645a867L,0x131bac9bddb1b24cL, + 0xef77d71d2dea5b44L,0x4706d21072fcc64eL,0x29b92691673d77f0L, + 0x22e00bf3e89e0663L,0x472d0cd374077d40L,0x3e21040d829232e2L, + 0x2f916dfb38dc8533L,0x48bbb59b14b8f667L,0x19de9f4ad44be19dL, + 0x7f6d3649232d9d5cL } }, + /* 42 */ + { { 0x3bd064de6e794819L,0x5a6b694ef82ebda1L,0x1f017fe0b91e2804L, + 0x190d31f307a43cd2L,0x6c26f226630433e9L,0xba488aa70abfdcb4L, + 0x418d9085a46411c0L,0x1b934fe6bffb5880L,0x75d1e237e200f849L, + 0xdf04d63fa55413dbL,0xe216ed75e23b3f77L,0xa05866cb0f91bd30L, + 0x84c395d97729c509L,0xec97e188452ab2d7L,0x8cb7c1f90093d686L, + 0x2d032395628f086cL }, + { 0xa81c94074a44b4c5L,0xb9846879cc702c98L,0xcb502287ceb0dc97L, + 0x303011266e3aa321L,0xc0ac8763e4c256c2L,0x65034d20e55b4845L, + 0xaa96a040f240f35bL,0x046d26d37cf7eedcL,0x62a5a8e13b810656L, + 0x86044b9783d70c2bL,0x2fbaff8859e4da8fL,0x929d901a5457f5d1L, + 0xd29e1eb2b531b757L,0x214dabdc9e4e9739L,0x5bd724fc4eaa9bd9L, + 0x734c12b31ef9bb9bL } }, + /* 43 */ + { { 0x98fe3c2e92f9b086L,0x4641b93eb3fd4544L,0x47ce208b5c02c65cL, + 0x8a52dca1c4f03242L,0xb5ec17d9679d29f6L,0x11d2fed09406f5f4L, + 0x260f63dc0d9ba811L,0xde2b056f15472a3fL,0x1b170d9f007290e6L, + 0xa2e23e8db6b5c8f9L,0x345a2839cf34c3eeL,0x9bdc54611b973ee2L, + 0x65bda6c2bb24d1c5L,0x97d52ba33c6141a1L,0x47bb16129d2eb201L, + 0x7c558a8721fbe49fL }, + { 0xb9485a523f350fecL,0x016678c56a38d4c0L,0x8ef346a20d5aa64dL, + 0xb85daa02d96da2e4L,0x845ec4ea4f647b3cL,0xc0d1a6ca0d5e946cL, + 0x41d8d1c14fa9f4abL,0x43972cc59c8b1303L,0x67e1f48d434ffbfbL, + 0x350ce93a819d2318L,0x49f530906ddef23fL,0x3c2e6cf9200cf12cL, + 0x42691cc1640432fcL,0xbfff74b472496b52L,0x44527c9f020a97beL, + 0x34cd7dca7b3c4348L } }, + /* 44 */ + { { 0xf031761a59e7fe87L,0xb1eae31a0047cd72L,0x27902e68fae30f62L, + 0xa666f48db71db143L,0x75ee66780e0038f4L,0x3b45ac6702bdd76dL, + 0x0d2fb828a0d6cd5cL,0x27ce7f1d9d8c5b11L,0x141fe0e4120b5e96L, + 0x95a1b984b9267c37L,0x5206e589d60312cdL,0x1867342eda549356L, + 0x374520b9070c74acL,0x2703cbb59557b0b3L,0xf621f59ca6ed8c14L, + 0x7ceb1cc2abf7b887L }, + { 0x0647a5bbdb7fd65bL,0xd8d45cc036c9457cL,0xc6da99db9e12718aL, + 0xed1dbbf4e93a7fb1L,0x4512c95cbd1566a1L,0x4861ba00dbc0c919L, + 0x3c6cc2989e7f5269L,0x671961500941aaaeL,0xbfcf5d0fc8c538e3L, + 0xad6e9929a25a551fL,0x9071098517ca0f26L,0x743b78eafa89ef7eL, + 0x39d5ea3171ab4549L,0x7442f3f3e6d1c36dL,0x25a683e0059d568dL, + 0x1f629a99227ced5cL } }, + /* 45 */ + { { 0x8925ddace45a1c3eL,0x72d2936541f7545fL,0x45622fcb37e7f828L, + 0x882345133e4c79d2L,0x5dffaf849c2645d6L,0x3078f4dd994802b9L, + 0x566927f09d339fa0L,0x9a500a1e9fd91dccL,0xce0081800ab0abd7L, + 0xd97135a38194e5dfL,0x9e87630798adf088L,0x3baf01b89a45a2a7L, + 0x6fed6154788b4399L,0x980e5722e77a997dL,0xaac90ffa2a378eedL, + 0x4a75fda28bd805a2L }, + { 0xd09a8fbb55e74cbcL,0x737738cefab18f25L,0x0fc23ad69764ec3aL, + 0xc5a7d35be7e0ad31L,0xe75e068ee481cc9bL,0xf0c2ea993d4aec34L, + 0xf1324fe80d4a63c4L,0x5dbb7c1699b0592cL,0x442d674da7e0f46bL, + 0x5a5d66c7a300faeaL,0xe83dc8213333ac83L,0x70ef812e8c408496L, + 0x96e1dcb699ef5fc1L,0x6e2b771b1734e862L,0x04629cdc583507d8L, + 0x5819f9ae23d8179aL } }, + /* 46 */ + { { 0xd99691216aa78811L,0xf64ee8f42103e7c3L,0xddf0107022b9e698L, + 0xe6001f9e4f582cdeL,0x24a608af2ecfac1aL,0x6ef4c78406393009L, + 0x5262eae6ebf72911L,0xddbd0af58c4ee5a0L,0x875aff90ecd87bc7L, + 0x2fddb34c6f24f114L,0x48104281e865f172L,0x95692426886c1b9aL, + 0x6f5f32089ef4231fL,0xaf587acfd0a7e82eL,0xd65719179ac395c8L, + 0x7459603c1364a750L }, + { 0x1c2475bff41ae519L,0x34401fb14af8f251L,0x70ddfcd2aefb2c3dL, + 0x9b2d385b51cdaf08L,0x8531c2568208bb19L,0x16c89df64c33f3f6L, + 0xc23cfa9924571769L,0x2339b51e86d010baL,0x08db0e8d22638313L, + 0xf769e17900fedeb7L,0x3fd96dcba3687ef1L,0xcd046b2391476475L, + 0xf3ff20640c45c8ddL,0xefd167bdb8343d78L,0x493ccb6d4b77ee90L, + 0x33025513b3cf7b45L } }, + /* 47 */ + { { 0x36f0046935eaaca1L,0x0c384b7589119102L,0xcb375665e6d2954cL, + 0xcb9199b9b1e9d6d7L,0x75852349c29c2757L,0x89cbd1bab8e738d0L, + 0x9b8dbe905923a427L,0xa237793e18fe1889L,0xa4271757a742e083L, + 0x8c4979d24eebd613L,0x40325054d4f2cf77L,0xa3b8a091958705deL, + 0x1b191bd933d999baL,0xbafefba43b0fee1eL,0xb3bad1843facdf14L, + 0x9328adb04387561cL }, + { 0xabe84e80f906b872L,0x705523a078262665L,0xd89c6a7e3398ccf7L, + 0x2fab551df55b5323L,0xa0578eca0554dea8L,0xef26523d375589cdL, + 0xd8fd6242864ad750L,0x93f27fc5178fe1feL,0x7b3e6f309df87422L, + 0x2862e49e3750d054L,0x7d90c6b25dc038a1L,0xc1a1ae2284db682bL, + 0x47f3dab79881930aL,0x30e6bd52baf3e0a4L,0x0680025bf62d25c5L, + 0x0aa1f3cfadd0d5e7L } }, + /* 48 */ + { { 0xa982219022a10453L,0xdd1eb91c2a03a10bL,0xafbb5d9596646f3bL, + 0xa58de344f38b6fc6L,0xce47c3e5b8cfca1dL,0xfcd8e16d0f70da04L, + 0xac44349bda262ed6L,0x9320d87bc56e2f8eL,0x9ce3ea0819138e58L, + 0xa5862dffa2b236c0L,0x6b0f9a5c8e7efb0dL,0x4b53432b16ac78ebL, + 0x6ff43105709b51afL,0x08e236f88f519628L,0x1f93f176eed403adL, + 0x559337e09636545eL }, + { 0x30ddf738d8fd807aL,0xf4e0ec9dab131222L,0x14a2f4db625afbc3L, + 0xd5b706049f12f895L,0xb46f3c23ac3044fdL,0x1b232d1ff540148fL, + 0x61b458f539b4e554L,0xf694b24a0dd70b75L,0x0fc64299289581d9L, + 0xc05d49beee5fe22dL,0x7af3447f6a18bf63L,0xe96a1dc27f1929d6L, + 0x6afe6028c1551e8cL,0x27dacaf32b5d4fa2L,0x4a1631bc545c2cb4L, + 0x930070f9b0c914d3L } }, + /* 49 */ + { { 0xd2f32c5e69a9bc05L,0x0a5c19c6589c4b73L,0x095c9e5e94665f9cL, + 0x8ab0f293bcfb4c39L,0xb90708771ddb7c31L,0x894e965866b38048L, + 0xf19a90cf606bd9bdL,0xcc1d58dfb6fd2d69L,0x886dcc4e461d8a69L, + 0xc455c277f9ce4831L,0x749a5996765f8a82L,0x2ffc668cc3badc8dL, + 0x380183969112cdabL,0xa98795c3b243c7cbL,0x8775f310010a2224L, + 0x043a2141587b5e14L }, + { 0x7bbe9dbc3a873752L,0xee1493f42f442feeL,0x981ca2c8c18c2181L, + 0x00ce3090e29769e7L,0xb4626ac8de768c5fL,0x33e9ce4634d7677eL, + 0xf89c2cade0fa94e6L,0x04f5cc1141f5b5bfL,0x2565f7362228c12cL, + 0xf1bf706a0c05cce5L,0x5d07ffffbe487c4fL,0x3ec43c09a499f1a4L, + 0x4f4e79bb98d94800L,0x8a335a16073f12f8L,0x4bb5eaf70f970d6dL, + 0x18d0747bf24d0ae8L } }, + /* 50 */ + { { 0x58d3c77c84601fafL,0xc9465be2af1c1f72L,0xff626798d116d806L, + 0x3996c0c6d5b0d93cL,0x2fa1ad755ec6723aL,0x966a814403ba5349L, + 0xdc4c94222ac34d8aL,0xddf471deed675865L,0xd8aca597953d528fL, + 0xb2e463b524ebf67dL,0x258248717e25b4d3L,0x23c5adba43159daaL, + 0x5458f9c683357540L,0xcf685da7f938b1a6L,0x981a4fdacefed231L, + 0x711093ed08bb5e59L }, + { 0x12aa3fc6401f161aL,0xf7358560974c5e87L,0x4aa252fb17b5df82L, + 0xb0b82b07a48e6299L,0x0023415729dd847dL,0xf1e54d004529c5a6L, + 0xcc1c539e6d98f538L,0x36162b5328d3abcbL,0x75a379382a84f0cdL, + 0xf717a81b4dee7484L,0x16cf35fb4c23bf1bL,0x7fd1c29f787e8b3eL, + 0xb7da7e6859b79ab0L,0x072100a085f6c60bL,0x31840159e7ed48b5L, + 0x17898bda4d9c97d4L } }, + /* 51 */ + { { 0xcd8483d8ae1b8cf8L,0x323d4b42e9a28856L,0x7633584f204a4bc2L, + 0x4e0b2228ca7a69faL,0x8afbda8bf757bab2L,0x85b240886cc5f9caL, + 0x47fb4813d41a95c3L,0x3f1bc53cc2aabe6bL,0xf22cda3f1ad1599dL, + 0x1b2ec081c31ea9b1L,0x048f304b01614ac1L,0xce31cee9c6afa7abL, + 0x55af76334140dc3dL,0x84b7ab37dce8abbaL,0x50de7648c7cf3efeL, + 0x73a88dcf15356ab2L }, + { 0x3f86828806e83b39L,0x477a44139f44037dL,0xf9058b0f17dbc841L, + 0x2db64f4f54d17549L,0xa23cea6af2307ffeL,0x393efd554f126261L, + 0x2f4e658a10f37f26L,0xa4437ce3f4ee1e35L,0x64ef42a7a93cde8bL, + 0x1debc9f4939aa901L,0x44223d6a3d7b5cd4L,0x789a6a11f88a3accL, + 0x56fb9df82c608a2dL,0xe79db8e3bbf56c06L,0x73c56af2668fa300L, + 0x52f32b17ae396a1eL } }, + /* 52 */ + { { 0x56f524c1e714f71aL,0xc1be12629add8519L,0xad9189d865cadbe3L, + 0xd88bf5c85a0fb649L,0x9efa6a9221d192d9L,0xe3fe83896f724b6fL, + 0xec3fae24b250119cL,0x4b6af9f62ae0d3c0L,0x8fceba0bd619624dL, + 0x7dc3092b2fdb6e3aL,0xc91da3763263cd29L,0x30c0761ef95c43bdL, + 0x89136400cdeb44d9L,0xfd7dce8443c0d31dL,0x78fec3b19871899fL, + 0x79e14d28efdf58c1L }, + { 0xe38222359bb40c55L,0x0a27202d0ed07a42L,0x48e6c1a94838c1f4L, + 0x2b5f24a7d864a78eL,0x7e7f140a0c6c55c9L,0xe62c104ace12d508L, + 0x9b0a1a7ec11b1e10L,0xfd8a275fafbb3dd5L,0xdff354fe9a3b6b30L, + 0x5a105d9e46602a01L,0x3d371b4d93bb65f7L,0xda5cbf0b0f82fdebL, + 0x4601229bde468545L,0x505e10b9c73d517eL,0x77cfa541672ff492L, + 0x0d8ec28a99566ce2L } }, + /* 53 */ + { { 0x014cf73ecbeee995L,0xb2eb88bcd491e80cL,0x615a6cadd9aba5d4L, + 0x2f7d46339304c84dL,0xba0501d28ab03c9aL,0xc8f723de91babb94L, + 0xc885f97750405772L,0xb5e1d2b3c7fcb094L,0x61ee7995df96c71aL, + 0xb8c8daab3464499eL,0xdb425ddd5f607932L,0x70251ca1b1243587L, + 0x26d7d3be9fc74340L,0x8c179310c902ac89L,0x72522c154559a74fL, + 0x86001e27c3734afcL }, + { 0x13b00ba5e7693947L,0x6478641e012c062bL,0xe1a438e0e85490a8L, + 0x5173dbbfd9574d5eL,0x9532eb8c9bd3ba61L,0x1f41bcb85f3ea075L, + 0xac1cc2478cbb92b9L,0x0f34648e1ef901b4L,0xdd929d1ed2b3b2eeL, + 0x470f1eabc3d75bfcL,0x5cdbc6f7139cf4d2L,0xcd86454df0424953L, + 0x1e07981247fcb383L,0xb9f209b417df930cL,0x4225fc31114ebc00L, + 0x020591cb347946c1L } }, + /* 54 */ + { { 0xe3003721275e0af4L,0x721141efe78a4a4bL,0x666cfcf6d1757485L, + 0x5fa1d737168e659eL,0x263e3e540e2842eeL,0xadecc3d4948bd5f6L, + 0x019de03d246b104aL,0xf8a9e903f343d818L,0xcb57ba4a5b0c0d31L, + 0x8246c50651e2765fL,0x80c5751f6519bf67L,0x5f05c200f2119a01L, + 0x7e6487b87821d4f4L,0x262f94aa261c3a06L,0x56cfe48972146052L, + 0x5119985fa1df05efL }, + { 0x5819497db18586c0L,0x004415d6c6eeaa62L,0x7c6a46b697cda28bL, + 0x9a149b287c194594L,0xb56369fa4ed3a506L,0x7092aa6643c94cb4L, + 0x55bce73aa9e9eee2L,0x34bb287077893509L,0x8af95fb006eb5326L, + 0x87cd03239638f485L,0x293762685ba75bf8L,0xf32d6f3d9d42d581L, + 0xa4cad57465c6d64dL,0x985f50fbb2cded41L,0xcf34ce0e9006a067L, + 0x59eaf26558a57f9aL } }, + /* 55 */ + { { 0x7b407efb6ec3876fL,0x780c6123f0f48648L,0x2abb56ffbf893039L, + 0x9592eaa045a91ab0L,0xce5b84d778811b82L,0x86a71a341f9f3fc9L, + 0xc17fdd86f0e7e13bL,0x88ed8297655a0880L,0x75d6dc7481d5e666L, + 0xeffc9df61d171797L,0x36ad4c8de3f79e1fL,0xdb15317d2046192eL, + 0x78c9fa7a274fda62L,0x04ec924f82dd9914L,0x059d1e383a64971cL, + 0x3b4450ea2620bbfbL }, + { 0x3db7a955c776dcdbL,0x35c4a57c81c8ba47L,0xae285003505760fbL, + 0xe3e80691b3aec353L,0x380335be47117be5L,0xe1c47e3a056ccf61L, + 0x253cfdeb33977916L,0x3decdfbaf5cb7ee1L,0xf3c9794f7cf4b704L, + 0x2401680c9ff81462L,0x4e440e11be3daa9fL,0xc5d0437769f91d8aL, + 0x4106c7a8cb5e9c5dL,0x191909a133b7d24dL,0xe893c8383764b4a2L, + 0x4a7fe30cc429b614L } }, + /* 56 */ + { { 0xe78f3a702455c7c5L,0x5b7636e870157754L,0xf32c45247623262cL, + 0x2c98b11e1bc780c7L,0xd48eaeac915ed877L,0xbb04d3c0199265f4L, + 0x6b52b19bcfa5200fL,0xc46a098193ea3fe8L,0xd82c733dba758059L, + 0xd324bbd61896aaccL,0xac09a2fcce8ecd51L,0x529918fd02fc44b3L, + 0xf0c45e4aaaa1784bL,0x35626340fe22085cL,0x53cbb676c50c7d61L, + 0x83fa1ea365126b23L }, + { 0x60ac86da10ccc646L,0x2ce0637f7b0451e9L,0xbbbcf6308a088610L, + 0x23c1901920349982L,0x707fc39cfc0bcda0L,0x7f4d1f151bd4fd7dL, + 0xd6a64e7444713bbbL,0x57bdc676c5ac9e60L,0x456c530337b61169L, + 0xd3451396dcf40a1dL,0xf3edec254997d2c7L,0x534ae9a4c2c4a739L, + 0x1401397e6a6ad2e2L,0x20769d4d23e95f81L,0xcee007c6de98fabfL, + 0x61409779931c51e0L } }, + /* 57 */ + { { 0x3ddb32db15156623L,0x68137fbcab7a67c2L,0x26011f506f19e3c2L, + 0x34218b0289924c61L,0x492a0b0fc6804c1cL,0xd65be706afaae6a7L, + 0x3b13d23e0d01be61L,0x44545b47f87f4c69L,0xd42236e204dc1aa3L, + 0x6135261d3c5161ecL,0x1eb46a63bd88bc07L,0x78c6d8361599d720L, + 0xf6955fe169baf0f3L,0x467eebd617072820L,0x2f1b8a2a3e3a340aL, + 0x636dac762d0b5f88L }, + { 0x94280db9b4c80af3L,0x9a189cd14e3892abL,0x26e702e0d1477ddcL, + 0xe91aee3868f9f14fL,0x2864f63a80baa0b2L,0xacd81f738b714a29L, + 0x30e1b870c5fe7cb6L,0x883ea1c3b10837fdL,0x2da279536b20489fL, + 0x3aeb2a6858a2da5fL,0xe2330bf203a8fa14L,0xb5c488b5dc70b1c4L, + 0x0a78c4d9299678f4L,0x233bd09825df675cL,0x37b5c0767b67d368L, + 0x2f6dbdfe4d0bef3fL } }, + /* 58 */ + { { 0x2f8472fd2e4da7c7L,0x708cfc91ae677932L,0x364af08a3dc268e2L, + 0x0f10dfe0799a2424L,0xef912d5871d58bffL,0x6bf35dfc988962e6L, + 0x28b96fa95f47ea0aL,0x734a79eaaad308c1L,0x957303379f437bbaL, + 0x002cbd8e6cf54f75L,0x47606dcfe7632eecL,0x404b5ecb53193104L, + 0x0ae0897c0acf729dL,0x89628b863bddf1deL,0xeced154ef87d7448L, + 0x5cb6e197458d5d4eL }, + { 0x98cef197008c75edL,0x7cf49d3ef6eeaaf8L,0x1d6f9e021875e96dL, + 0xfcec2cfedd9b0d8aL,0x38a61cfeb9576daaL,0x10003f3936a7dbb8L, + 0xb37c386823b814f4L,0x9fb66dcbb80e3153L,0x9e7e2eba059847a8L, + 0xa4ec63fd35a72770L,0x311f3d91fc9e0ed0L,0x3c1dc094d515baa4L, + 0x75a06ebca08cd4e3L,0xab6172382ed5eeaaL,0x2e82bbb0e1f52c1fL, + 0x2149d6305175d6e5L } }, + /* 59 */ + { { 0xee1a8e6f5f9311f6L,0xc97e3c9fbabc1f85L,0x4fa7c52eb494209aL, + 0x04c2f51c19774fe1L,0x5cefd1228555844fL,0xb53862a3b5873ab3L, + 0x768efdd6cbed19fcL,0xcdc12479ee58469aL,0x11237e313d80c09cL, + 0xdd74a290c044c28cL,0x9ee6517abd47e287L,0xc2421228ad0ffeefL, + 0x4273088f818d281fL,0xebc744bc43ec0de1L,0x5b26eccfb415bd73L, + 0x14e2f350cb07c26cL }, + { 0x548d2a104216946bL,0x6e801f077a4bd92dL,0x5996d0a343695160L, + 0x0f1b5c2f63a197c9L,0x79da3c4f061f77c9L,0x1c1cd63493ff7b22L, + 0x5e61b650a234123fL,0x826b34c5f284033cL,0x718b90e8c2f34214L, + 0xa5f35620ae806ec5L,0xa2fae345e324a9b4L,0x8c0bb95e8b53cb51L, + 0xc94f6ac2f9965778L,0x07ec607d6b9def32L,0x63bf1dbad0ed8f27L, + 0x58537e02dcb61e4fL } }, + /* 60 */ + { { 0x1f64b06464f80ba2L,0xe8e055e70559a45bL,0xc3262b34f1f4b634L, + 0xef4f7d5fde8c8482L,0x9d55dea0c30c780aL,0x1740afb9cfa1e693L, + 0x2cfe6a667460c34bL,0xf66959411187c1eeL,0x1382f2775f974d94L, + 0x1ca0ace4004549ebL,0xf8244b3fbabded02L,0xc36f4d064e3653eaL, + 0xeab9f0dcc55c5f83L,0xd93b9cefacebce90L,0x16658e7219061425L, + 0x4857835f82d7970dL }, + { 0xdcd525bcd2576210L,0x9f378aa7d51b5443L,0xfe97bf171bd83994L, + 0x930d0f63f38ac621L,0xaf8f2c17818408ccL,0x2692c87e260f53f6L, + 0x0ee45407db0a75e4L,0x0ec47ae5ffdb1b37L,0x769129dc7aa6a44bL, + 0xb6f932b22e40b75dL,0xe06764d095ef3b77L,0x28fd47f568bc63e8L, + 0xd18104949c0014c0L,0x90e2d3fdd7995d8eL,0xeb39a05d6c2a85afL, + 0x6c0277bda21f3128L } }, + /* 61 */ + { { 0xe41b7086b509e7efL,0x8842ec7b3d7f9f91L,0xcd285f945526b88bL, + 0x6e44e064051dd0abL,0x90198c10774f1cebL,0x6ecabe98123e661bL, + 0x4481113632f647d9L,0x1dd82b4526c52aeeL,0xd650907f939dc9d5L, + 0xbd5eeef2fcd455bfL,0x7815a4dd8d2e5d7cL,0x5ad4ec9288bc9f2aL, + 0xc6f10d0b57a3b322L,0xe8d0c1e720b9cbdbL,0x5a0b071a9b774ee8L, + 0x3067bc9af22fcf8fL }, + { 0xe0e589f2b7ca9326L,0x17a106fdb1224f63L,0xb2354521747a57bdL, + 0x2614982d62b0882eL,0x7f3af5444391ffcfL,0x1aaa337ba84e440dL, + 0x28ea37b0941bb071L,0xa957dcb42e4a7f54L,0xe7ab662c1a6ad5fbL, + 0xd135e381f7c36a20L,0x42e7980c9baa0b6bL,0x4237030c94e4671fL, + 0x24cc63ff8b0922e3L,0xd10d5279445a589fL,0xbb99d316a870ff6cL, + 0x390c83caa996c195L } }, + /* 62 */ + { { 0x50d3fa82ffc4a73fL,0x2665d6353bd53303L,0x80a06f8a264bb77dL, + 0x81c04a6e22d73d84L,0x2409cff50323b8aaL,0x31dce2178c4c4d5aL, + 0x374aa80e0c0f9c19L,0x0b25a38700186bb8L,0xd0b77a10aaf1487fL, + 0x15f39ad5ab498de1L,0x92e32da61aa0c116L,0x228e3dbd96e25ce8L, + 0xb57c88dc5e8646d1L,0x672b1164267b1c68L,0x5d0d807f600bdec5L, + 0x3ea4007d223e573aL }, + { 0xd76debd0a595d0a3L,0xa6bd76cbaff0b3b4L,0xbf2c154f9b1bdb97L, + 0x62b19ab44c714c71L,0xc9bf33b9221af663L,0x23d87c498c941ef6L, + 0x255804c3d79f0f6dL,0x6f1a10052a7acbc1L,0x5dab79d9550528afL, + 0xfd77a6f0c8d16213L,0x40508b6dde5e1029L,0xd95ac0f2f95da12bL, + 0x8860af71758a8ba1L,0x0b194c837160c8fbL,0xa40e6c80ce004d34L, + 0x09f82a176b14aaa0L } }, + /* 63 */ + { { 0x60abe588c21366dcL,0x729c0a4faf75daf9L,0x70501fd9acb93ed4L, + 0xb97e744e87a16d70L,0xa42e0a7a98e7361bL,0x1acdaff228b54cf3L, + 0xf087ccbbb7bd9078L,0xda6f3983663250e7L,0x66d693eebaf07c09L, + 0x79baf4c38cbaf157L,0x5a984e07dfca99d0L,0xab4d3247f26d8dabL, + 0x4d0be7017eba36f9L,0x37bb9e650e8dd216L,0x72aa4e24531c4f03L, + 0x77d1e984b753d85aL }, + { 0xd9373239d8e62367L,0x3361848bb9820cf1L,0x00c7e3445a9c97c4L, + 0x9a0ec9ae14f960fcL,0xcf41f0cf740474b5L,0xa5eede8fece065d5L, + 0xb1de5a4e9e808610L,0x17c44ae4ae0cf75dL,0x2fa563236b148d0bL, + 0x64fa740fd29ff2dcL,0xc605eb8a88cb212eL,0xf2c771ad6a863016L, + 0x6d6112e7607b4c17L,0xfe90ec0740d49785L,0x599be18be256e0e5L, + 0x4e6eabecca54adb0L } }, + /* 64 */ + { { 0x950323d3fb99cfe6L,0x7b09bc26c9334178L,0x64111e417cbdfb6fL, + 0x9114174489a75760L,0x4c633df910919cb0L,0x715fc7c7396bfd2fL, + 0x8ca195128cab62dbL,0x306724734db81aacL,0xe67a246bb4c4c54aL, + 0xd77ea0fabf229646L,0x5bed15f1fa5b5d70L,0xa5686da5c2f192f3L, + 0xdecac72a7f6690adL,0x0c4af2a2caa50b7dL,0xf44631c16049ad2fL, + 0x325d279604ecf056L }, + { 0xee11fb554848c144L,0x4e062925b6a7af32L,0x125b68e1369e0f9aL, + 0xad9bdae6ca53b21eL,0xf50d605c2e98ea1bL,0xbdb9e1539f2fa395L, + 0x4570e32de91532f5L,0x810698ae46a250d7L,0x7fd9546cad9d9145L, + 0xabf6772111e97a5eL,0xca29f7d5249f82e9L,0xa9c539a99851df63L, + 0xfd84d54b71d0e3e5L,0xd1e0459c041d2b56L,0xceb3eb6efd80096aL, + 0x19d48546e32a79d3L } }, + /* 65 */ + { { 0xfe19ee8fb540f5e5L,0x86d2a52f04e68d17L,0xd2320db0adbdc871L, + 0xa83ad5a8d03a7fc8L,0x54bf83c708bcb916L,0x092133ea2e51e840L, + 0xbce38424cb52dddfL,0xd5c7be4031063583L,0xc1ebb9df458e3176L, + 0xafb19639bc4dabbfL,0x36350fe4c05725a8L,0xac4a063484e1cd24L, + 0xadf73154c145b8deL,0x0aa6dd9eb3483237L,0xa3345c3dcbff2720L, + 0x1b3ace6cb4e453b0L }, + { 0x0343e5e990a8bdc5L,0xa203bf9d6306a089L,0x98489a358e48520eL, + 0xbd17debede7d1d06L,0x8fafa6d75f795d3fL,0xa4ceb630387b0a3fL, + 0xe0166b32ffddeafaL,0xa2fe20547e764e02L,0x55ab9824e871f304L, + 0xa2bd36bb952ec45eL,0x7b4c1484a90d20caL,0x5319f38775bcfb53L, + 0x34238a4a6982c4e5L,0xa2bb61c7a102921dL,0x1e061b64db3ab17eL, + 0x538ec33e192f0a14L } }, + /* 66 */ + { { 0x193496fea19b56cfL,0x663d77f47bb99acdL,0x8f04afa857d0a881L, + 0xcced3da2082835fdL,0x7e21faed5d82cec7L,0x6e175b99f8009c85L, + 0xd9c6e31b2d05a307L,0x96948d4a81487d82L,0x86ebd3f2d46f6655L, + 0x86851aa8773ccc49L,0x3e220f228b1640a6L,0x9f06e3a841a20b75L, + 0x2cfffe5e90ac0a6fL,0xf5a9b1da8ebeb3fbL,0x2587d9976e08e2c9L, + 0x6fd6029803e9f401L }, + { 0x54709f8d8eb7516aL,0x83058a74bdc598abL,0xd234dd9887e801ceL, + 0xfd0f9d90d17b8a96L,0xaa1e549f6e90f6abL,0x2496ff805a7ed55bL, + 0x0d9f657a6c254c19L,0x3cdea49cb8962575L,0xb685a3f02dff27deL, + 0x3c50e7fddb8bc04bL,0x904ff0ff987236b0L,0x494298fdbb0d5055L, + 0x34b3386de14be8d0L,0x7ad34e9c7c3d30d6L,0x1f2b32bde159fdd9L, + 0x84cfa23cc761e5c0L } }, + /* 67 */ + { { 0x13bc11eb8b99b964L,0x8e280c0a58e2fc47L,0x870fbc49d4c9a54bL, + 0x37a334a2bf6e20faL,0xee583d0dd7c88cfaL,0x05e029a8ef4af1daL, + 0x6d55e2340c2ef8a6L,0x61b6fdfe209e9b62L,0x3b1dad26bb8e080fL, + 0x5adbc1629392fc1aL,0x02ac0fe60aae3f4eL,0x8d99801ac2bf4d5bL, + 0x2333f93fc282fed2L,0x16dcb10cb52db33fL,0x09f90f84c55752e7L, + 0x287d4c51c84a0d8eL }, + { 0x5fa582010e9867daL,0x614589b31a874cdaL,0x005e27c5fbdee22eL, + 0xe357fef5e612bda8L,0x4e0dbedf2d3635f9L,0x62be70e46f125a86L, + 0xa09b98840d94a2e5L,0x7eb99a1528b5e5d1L,0x21b9416e751028b5L, + 0x1b137fd7e06d2cc4L,0x6fa1f517fea09845L,0x3ba1e966ffcecbd7L, + 0xd4c89a4a832f453eL,0x07b1e2afeca68fa1L,0xd0fb44534bd395a3L, + 0x0132a3dcd8ef9e13L } }, + /* 68 */ + { { 0xe53c7785576374c2L,0xe60526d184727040L,0x8a066dc8228ca044L, + 0x1fe1c1b2f1ce1313L,0x2aeec832cdeb0c5dL,0xa75966999cbf826fL, + 0xcd188e81de77a589L,0xe5ce0fe0118d1254L,0xa142a9840790b86aL, + 0xe28f043f39ac28ceL,0x4eef829087de5804L,0x83c31b32f639a8c5L, + 0xd70454a75887794fL,0xca635d5018b1b391L,0xcefea07631d9c795L, + 0x13cbee76b6f8aa25L }, + { 0x79cabe0f8d3f34f3L,0xbda9c31ca3617fe3L,0xb26dee23dd9426a1L, + 0xe9dd9627f29c9104L,0x033eb169e2c6cd3bL,0x8a73f492fcba2196L, + 0x92e37e0bb858c83cL,0xe4f2aca623b3fbb7L,0x8101fb1e64be00a2L, + 0x91a7826a948f6448L,0x414067b4907260e7L,0xf774aa50e30bb835L, + 0xf922ca80c999c06eL,0x6b8635b90ba08511L,0xbf936b5c25fa04f0L, + 0x4e0a1adae02e8967L } }, + /* 69 */ + { { 0x00ca66708ba29c4dL,0xc08240ce22988094L,0x21c5ca6716dda752L, + 0x689c0e45abbbfa34L,0x1d7545fd3ed28b72L,0x5f221198d7c56ab4L, + 0x4b3d8f7438759d65L,0x93490dfb8fe50b89L,0xb641f5d7e80eba16L, + 0x7b0da5eb79acb537L,0xab6b14970c1d5e5eL,0x2338e68da5da429aL, + 0xe010c4372f6d2f25L,0x226f16d26530f3a7L,0xefb0f7b6cbef08bcL, + 0x733e30d99f99c999L }, + { 0xecfe1582a42a38f9L,0xaec2d58e4730b500L,0x2ee2f2a7de976b2cL, + 0xf0539db5a969c1bbL,0x31954168fcecdb4aL,0xf2f7348ae7a8e902L, + 0x1d58d7cc3121541fL,0x5d25b75c2202ae52L,0xdea9965af40835a7L, + 0x3feb6a41529b4e46L,0x5c97fb6fbd27ad9bL,0xd87554c0261f900bL, + 0xb43031d904d5b19eL,0x33d5e9b8cb219b9cL,0x7a43d4923ee00bcfL, + 0x56facb39b79a5c0cL } }, + /* 70 */ + { { 0x019165a2a3018bfaL,0x100c6b249ffad984L,0xbbf1b1f655341a9bL, + 0xe6bd1d9725dc4cc9L,0x52850ed52bfffe60L,0x24e992cc7e5509abL, + 0xff6c502e4ceb59f1L,0x2f0b35731aa7d148L,0xe90c1ddde7e3aa46L, + 0xbaec9f45d1142880L,0x475cfd2665be5dd5L,0x83abb14e1febce13L, + 0x6aba482980942d30L,0x1e1b235d297e82c8L,0xb771cdbe50d8218dL, + 0x88599266d94d6cbbL }, + { 0x08847290155ccaf2L,0x8679ebc77c5b773eL,0xa88b2dd1b2dd08edL, + 0x960a180e87d475dbL,0x80fdb6b76694d02aL,0x3e8758c93f3f9e96L, + 0xbda3f6fa4ad836c4L,0x9400c58132fb387dL,0x25a785422550200fL, + 0x2a97c351776ecf18L,0x03ebf46e566db59aL,0x4743a28026545edaL, + 0xed169d84cf74ab44L,0xbaab931d88cb3f69L,0x70ae932cd8257196L, + 0x797224a6a0c09719L } }, + /* 71 */ + { { 0x632923f8441f3567L,0xc11c31682e24bf1dL,0x4b97726bb7671fffL, + 0x601746a77a5e1a22L,0x53dddea03addb417L,0x57867a3c7f59b846L, + 0xb012a98756cd7ff7L,0x1bd5fec9f19ba9a8L,0x750379a2f8306748L, + 0x7763445dab8c05d1L,0x5d7f441b7903f42aL,0xc011674da903e46dL, + 0x1b1d3c4dadd126c1L,0xa2752aac61455b40L,0x4da42a68555c356eL, + 0x3ff09c15d820852cL }, + { 0x4c0a1bcef9cb7784L,0xaec539bc2422f305L,0x5f40f9fd0c414aa7L, + 0xd3aa316cffd42bc4L,0x42f5a4c32f358e15L,0x00bdcd9ed6e27682L, + 0x069f789ff8a5eceeL,0x8078018e05e14f5dL,0x2bb3e4938b40c741L, + 0x5dbc8c1d7917f72dL,0xe0eea664cc57150cL,0xa25ecc5ac3fa8920L, + 0x3c21b0f51c797164L,0x8f09a2f2634ad16bL,0x8e730fc558391d9aL, + 0x47ef18054fdfae4cL } }, + /* 72 */ + { { 0x9965f3d13da285e4L,0xba7d4dba3a01e3f4L,0x4738413a61214ad0L, + 0xd3b7d53522397549L,0xa53dbdcf5a730b92L,0x3130d92b332d165dL, + 0x44a2854182f97ef4L,0xbf62221c44dce1b6L,0xbba138587e2a0ec9L, + 0x33f32c8dcbfad998L,0x409e5f3fb5fed44bL,0x5c328c65c66217bbL, + 0xb00db69ffcdf71a9L,0xa23c2a21b8920788L,0xf8ab28e63ae6464bL, + 0x1a6b6e9cb8de0861L }, + { 0xaf6ec2b606af77aaL,0x2e60f5cda887f065L,0x87d214009f498c56L, + 0xdb595b59fcbaaf4bL,0x0fb592a1271ab855L,0xa0ce10e5d4349b0cL, + 0x9d6187d8887d8c9cL,0x03ee95f9154bd6dbL,0x8fe532135d06c999L, + 0xf4a7bc30fb6a64d0L,0x3d22af0d66a4cb60L,0x16952cef5d37367cL, + 0x6f0ea734997d8e55L,0xb447c70f731732d0L,0x00ab3034a9cb3942L, + 0x79dd018028510fd0L } }, + /* 73 */ + { { 0x04e0033a3ac7424eL,0xdb06b68860fda4d0L,0x236a9766bcb772fbL, + 0x294a8e2bf297cda4L,0x4b0aab85db013c6eL,0x3d2aec988723a3adL, + 0x0cae32cd13c84a6bL,0x21888f5e70ec169eL,0x739633bd42a88262L, + 0x68ac792e7b60d9b8L,0x89f2b72210769fe1L,0x8f3fcfe6d24bed34L, + 0xd35efb88a3eb24aaL,0xddecfa3f484c706bL,0x7cc119a9929ece0dL, + 0x87e5ad458d405436L }, + { 0xba99aa9d7d1000a7L,0x8b94affcae823833L,0xc8229628dfb83dc5L, + 0x2f59fe11845a418dL,0xa8b970f85d417054L,0x8918c26572b71581L, + 0xe4ef477dc0d1dd17L,0xb50b4cf33afad7c0L,0x21baea7901870a5bL, + 0xc77087f9bb3a2868L,0x7857531e124a59cdL,0xed74c26f57f43239L, + 0xd5f5ae250164c94aL,0x6608b7e2f094bf74L,0xf4cdb5bafdceea32L, + 0x0b712519990cc045L } }, + /* 74 */ + { { 0x5a290ca188d5c64dL,0x0596d749a7492534L,0xa04b0d3d2a00e925L, + 0x082cd02ccaf7b66bL,0x912b50c2ecdded83L,0x813ce9deff31646eL, + 0x62ae70c7c75fff95L,0x6f6852e07e2a4615L,0x320fd7d003804fd1L, + 0xb1a2a4dd8218e8d9L,0x4918a6fbafc645d7L,0xfb080fa1e8d9fdbeL, + 0x33d4d08a4470b6eeL,0xd2ba20776d974ef7L,0x8ecb95a769dae5d2L, + 0x7a3f423a7d69596dL }, + { 0x362d2ca69a929387L,0xabdb7581cb1c1fffL,0xd892ec9f7e51b6cbL, + 0xee8d86323a4e131fL,0x4680e3f15bd87561L,0xe3a597e1d4e7e732L, + 0x3cc72b7c5581fefeL,0xf3e77f8aca8cae0bL,0xfcc7d7dc5e2fd4afL, + 0xdd3a455221355b79L,0x546b24f2a2c07177L,0x415b532d0689621fL, + 0x2be9af513f78163eL,0x27d63b9b33d7ed21L,0xab019ef296802943L, + 0x2da5fc551623faf4L } }, + /* 75 */ + { { 0x62429cf3c8a5c600L,0xa7a80c223fe33e7cL,0x9ffda7400a57ddcbL, + 0xd1ae156d925b0c74L,0x097a43f96b100eb0L,0x169e945cef943c81L, + 0xa1f734e51128cf24L,0x04387c4a419f0133L,0xc007868b01044024L, + 0xe5416abf90359cf2L,0xf9c76fee478d54e3L,0x66219da642a2173eL, + 0x61e031569fe30141L,0xa0ff5ce393ef247eL,0x811792ba072b6592L, + 0x855f021970c854d3L }, + { 0x61fbfb6c847314c4L,0x97906155eb45b96aL,0x7102e1466ba2afacL, + 0xed51f975ab949781L,0x9d2f5b17c110c4feL,0x7ac8ce70aff57667L, + 0xe7366a216eb244e7L,0xdd1bbcec551c65c7L,0xb525060ae1a859deL, + 0x7a0481748ba7d2e7L,0xe1a2c541ab8ea8c4L,0x6e7824c36fdff078L, + 0x79b49fc714874b04L,0x22ae337f06b1f733L,0x1c3521926f8fe6cfL, + 0x292236cf525d0797L } }, + /* 76 */ + { { 0xcdb8d80a7d8b29dcL,0xd17a202408ea648aL,0x7db12c5eae92be91L, + 0x1f347d18fda72fbcL,0x11374b409e760c6fL,0x7361e8f1d8e38d91L, + 0x7714be9d739ac1f4L,0xc1f9701cb4df5c4eL,0xd9138ed86f72cae1L, + 0x1c7fe1f76ad180c4L,0xf8c185be9e2dbf9cL,0x835db2697c70c44dL, + 0xf997cfeab0d15b5fL,0x5101445a61e6545eL,0x16b0688425184e5eL, + 0x7cfac3597521e7aaL }, + { 0x811821673c0bc53aL,0x84b5ede37e751367L,0x3ca255fda3657a18L, + 0x096abbf4ba1fdd98L,0x9ce8369fc5da77d8L,0xf27b9ae7aab342c5L, + 0x06c91bd6972059f1L,0xee0dab30914ecfe9L,0xbb647fbb93f53f12L, + 0x30c38a7affa57e0eL,0x517d06ef9f2ad607L,0x49728d87bb99dcc9L, + 0xb0034af1446080a1L,0xcc810c3f12b9c17dL,0x7225f14f772a22a0L, + 0x6ce3dc7f1ddf82bdL } }, + /* 77 */ + { { 0xc07cd835a4397830L,0x4dd9290cf4733306L,0xdd35d3a829989e8cL, + 0x79902559563d8152L,0xf278d911e87de61bL,0x9c7340c71024e35cL, + 0x2d4444614a0d0e59L,0x63e7608ff32626a1L,0x627a37e9c4c9baa9L, + 0x0c56dc5176fffd25L,0xcb6defc8cef2a1cdL,0xcbcc0d56efc559d9L, + 0xe45f3fc5041cb692L,0xcd05c239e5161e09L,0x2a731ee95c3b559cL, + 0x85151122a3d0a16dL }, + { 0x782d033586ff19e2L,0xc2c60daa1da28603L,0xb2e78cfe557c7eedL, + 0xa8f6f9841bc4e8b0L,0xcc1f9b4b3df35c67L,0x96e136034764462aL, + 0xbf910b977c7ae0b0L,0x27c7f30551435956L,0xc14db15cf631eae5L, + 0xa51d61427e69b34cL,0xdec828515fc12ff2L,0xfcceae13fb887162L, + 0xda332ac1de1488bdL,0xa20374e22ee3e74cL,0x597ea1a1f0ae069cL, + 0x8b1159f277bdec04L } }, + /* 78 */ + { { 0x4af71a442f961d30L,0xbdf968a87ac7248fL,0xd32df87cb1a906cdL, + 0x00c10e2604abf925L,0xb8711759b9f04d4cL,0x00d54e60939705daL, + 0xf7587433c9f80849L,0x2e9abade6a7a2375L,0x5676d47894ac17acL, + 0x4ca0525bc202d99cL,0x95b8bcadabfae73dL,0x2371ed383405991bL, + 0x2b69e47a458a99c3L,0x7cac0b182b78c866L,0x6ceaa79be0232c7cL, + 0x0bd86433588f7459L }, + { 0xdea1a8b47e734189L,0x52c5ac88cfe5fa17L,0x444a4d4e11437664L, + 0xc2522308af9e9750L,0x78b1d0c3d30c6b3bL,0x2edae5f04c6df477L, + 0x53131d9a2ee88dd7L,0xc4e380eeacc93e34L,0xd499b1aca8db0e8eL, + 0x77348c167f5d49d7L,0xc96632571556ccd7L,0x65ce0e8c2611d13dL, + 0x2c95fe66b5a2fdccL,0x266988328658faa1L,0xda87d1f431c32c98L, + 0x46650598fcd91907L } }, + /* 79 */ + { { 0x4c6c13cc6b4a5efaL,0xc481989b1d07b265L,0x10b966ce8bdc69c0L, + 0xf54cfaa22c2531d4L,0xcb5f1808cad0a100L,0xbeb52538ee5da449L, + 0xa6240085bedd83ccL,0xe792dacfd6255c78L,0x883719062062058fL, + 0x96615e83ed1658c1L,0x4b549b277d28d542L,0xeaf127db83b75df3L, + 0x4f60df6d17fbb942L,0xd08631dbf6f7c930L,0x17c38f986018789fL, + 0x0c43574ab9a9280cL }, + { 0x76eb324c1d20cad0L,0x90decb098c61108aL,0xa6e9d39c6f06d36dL, + 0x6cd978babc0da197L,0x5948b1c0507ac5ceL,0x2bd47164c5497eb5L, + 0x2a9c4c0f4d5914e3L,0x772c5046a759f03cL,0xe7d7328a69ac847eL, + 0xa8d57d0c3048b330L,0xe60034e040f7baceL,0x823d9193a85f1790L, + 0xa6e9b66c5c859736L,0x22ca2c7a679e1022L,0x00e7a19c09023fa4L, + 0x324999f12726d5b9L } }, + /* 80 */ + { { 0x667eaed67c834915L,0x9f77aa6abc5eb64dL,0x729ebcb625d62011L, + 0x0aee24f2699fd9c2L,0xe1eb58742b8d4f6cL,0x7f12710c14c976d6L, + 0x91390335f6d9ea65L,0x668b704906b50064L,0x65969a0e0876ee4fL, + 0xf901bf3f2f9d9360L,0xfb1a8651b499e3ceL,0x80b953fbf2dbcaaaL, + 0x312cc566973b06b6L,0x3534d9c33af36c64L,0xe4463a5210ffd815L, + 0x57ea2b4bf18c2b91L }, + { 0x00f5e1628aa0f2f2L,0x8c7e75c50e46bcaaL,0x97ab479aa4a2c42dL, + 0xb4f308ea14baa202L,0xa901bd146943cc2eL,0xbb125feeeed58804L, + 0x6502c8f99d180f7cL,0xe53539191580c61cL,0x7e27806927101ee3L, + 0x7a0a40a1faa72717L,0x32edce024c75b153L,0xda23660b538f1c22L, + 0x4d511e98be307d2eL,0x24276e409baee0b4L,0xa78c39277ff1f307L, + 0x60480b46ea7935c9L } }, + /* 81 */ + { { 0x31087d663872ece3L,0x5f29be7d955b70f8L,0xb50b4fc79cf95bb8L, + 0xbae3b58ddbffa621L,0x0e61d280e022ba5dL,0x78ae51174181449cL, + 0x0b132840cf555485L,0x800ed1b6b8ce0b0eL,0x35dffdd578d5de3dL, + 0xf7e4237469a56b47L,0xd5e323698d910ae7L,0xb6ff52a06313c7c7L, + 0x5a2fe20da92de9e5L,0x41b347d3d12110bbL,0xc5905edb40c16f23L, + 0x0774a0d39a8f88ccL }, + { 0x3ae181abe3b6c106L,0x4ebe163f8de150b7L,0xcf75b82f6f354836L, + 0xaa0d20633ac7ac16L,0x5c680668291722afL,0x73941e6111545553L, + 0x17127e38bf5de3f7L,0x32cfdf031afb41daL,0xc6893c9187bc8663L, + 0x75046744a62c9c99L,0x96866e2d962c1947L,0x489ec8df378cdf4cL, + 0x3a60709b3407fa32L,0xd37d2159551290d1L,0x9623d303bab92273L, + 0x081519542432014bL } }, + /* 82 */ + { { 0xf9236d89fb7b2108L,0x3ecc83ccad75f9aaL,0xf7c72b15b4e1da11L, + 0x552aeaef0315c362L,0x11e140edf272fe3fL,0x99d79bf687843ee8L, + 0xce6b54fd1d9bb25bL,0xb20b0e215b1bad74L,0x54a0214f5b84c90dL, + 0x459bbf52fca6cec9L,0xe363c48d9e4df76fL,0x3045f84ed64cf17eL, + 0x8402a167f62ada48L,0x2c9e1bf36a74ca01L,0xe8cf9d41f691c42dL, + 0x5abf2178c2c4b874L }, + { 0x4777966bf3b3bccdL,0x0047e0f0be3e0caaL,0xcb8383b38c7d5043L, + 0xe77e3baf946fd5fcL,0x79baa785e9ec0e87L,0xd83c557cc8a18d25L, + 0x9b96e5af25befcfeL,0x4f05d15e98c71b61L,0x081f991a77e62da1L, + 0x1c6ec781cbaa3821L,0x7522f65de54d9bfbL,0xf5d0557344ed1430L, + 0x3035b31f95cafddaL,0x47e67f436378f5bfL,0x029f7cad5270b9d9L, + 0x15ad15874d916a48L } }, + /* 83 */ + { { 0x00de2eceaa588ae4L,0x552ebc58a371a232L,0xd00ea93471230444L, + 0xafbfa67de4b1832dL,0x29216341b689e843L,0x1f96bbbd61f4e2e8L, + 0x9542068404c29dc5L,0xc7fe382742317fd1L,0xe0a0aec663483162L, + 0xfc2b94d10700184fL,0x07219973fe1fbd85L,0x648b6ab1fb074352L, + 0x23bbdaadc46e5392L,0x0db8dd1f00fa56ffL,0x104815eb866725f6L, + 0x3f9c4cca52e81963L }, + { 0xff36b29732ce637eL,0x81a15f2df5d25cddL,0x1a1d052d8b02ad97L, + 0x2e5f3bbccfbab3e9L,0x60d2cbd7614eeb75L,0xd4491843cd5a793aL, + 0x2242cf75cdba2144L,0xa20705e788b99766L,0x64e12cc0ec77e132L, + 0xb1c14df6b61a9b05L,0x8fd97f0474825b5aL,0x956048213da31223L, + 0xde4867274d30c70dL,0xbcab8f151c12ee69L,0x5dc638b4668d893dL, + 0x6479dad6223f574bL } }, + /* 84 */ + { { 0x569044f3b05f2b26L,0xb35a294a80b9f76cL,0x8839fe284290f6aeL, + 0x761cfb23026a5877L,0x768926b62e5ff9c3L,0xbae6cd200b11c576L, + 0xdc85775672a03efeL,0x0cae074ae1bad63aL,0x3fe491a1d709d99cL, + 0x76c5ded66501d9c1L,0x1da6eca1c32aeff7L,0x50849d55c57683e8L, + 0x9e392e9cdf98d847L,0xfad7982f64d9a564L,0xf7c3bdb7a37b98b2L, + 0x1fe09f94f0860497L }, + { 0x49a7eaae7648cc63L,0x13ea251167cfa714L,0xfc8b923c653f4559L, + 0xd957619b81a16e86L,0x0c7e804b3c864674L,0xfc88134a1616599aL, + 0x366ea9690a652328L,0x415329604bc9029eL,0xef9e1994ae2aad2bL, + 0x9e2a8c527f10bef5L,0x73dcb586c67bf860L,0xf61a43fa844cc25dL, + 0xd74e7eea74eb3653L,0xf3356706dd240f02L,0xeec7694cfd83bcb4L, + 0x4de95786db62526aL } }, + /* 85 */ + { { 0x4867d3153deac2f7L,0xa084778ab61d9a8eL,0xf3b76f960ab7b2d5L, + 0x00b30056cfdf4f79L,0xd0701e1531ab8f4bL,0x07f948d59c779d01L, + 0x7c994ebc82675371L,0x1104d4ee48bad4c0L,0x798ce0b5bfc9d058L, + 0xc7ca898d309fa80bL,0x0244f225acb33eafL,0xd51e8dfc5b2f3175L, + 0x3e49ba6ba4d7be34L,0x1760f4c7bda02b43L,0x37e36a7e4435275aL, + 0x1c94418be636980cL }, + { 0x43a2131309dc1414L,0x060765fc43c93537L,0x6ff3207adf5f79ceL, + 0x6f18b1fa85d4cfcaL,0xf5c4272e63e995abL,0x121a09e4a82b3002L, + 0x82b65d1b97147f16L,0x4993c20c20a7fe26L,0x99c9cb98e6716726L, + 0x5a02d673feb440a0L,0x3f3fa9e1251b4bc5L,0x75dbc474a05338eaL, + 0x3cb4044b7b09f6cbL,0x6767da1880434609L,0x97851422098ceac2L, + 0x611bfbb2b55235baL } }, + /* 86 */ + { { 0xbdbaa55ef00ad2a1L,0x29efa85e14a290d7L,0x3b4a4768e92b1694L, + 0x67111bcd11ec8130L,0x0e42570288bd27b2L,0xf28cf2a3d9a03c06L, + 0xbb7c8d2df318884aL,0xe2ea1462e3aaeb20L,0x3353580443b85d77L, + 0x81ee4482554ee9bdL,0xeb2eee9ee6aa198fL,0x7a5aa804c26c5944L, + 0xa0ef2da582ab167cL,0x5a2ab47602fe21a5L,0x169cb3b83370298eL, + 0x86e6c5440eb3aa8dL }, + { 0xede033210b793d9bL,0xf79fade11ddb5eceL,0xf73fda9268930b64L, + 0x06aad97dfe4fd1b2L,0x073a5b1d92a4dc88L,0x8af8cbd8bc976d75L, + 0x60b4abb163ce26c0L,0x9c8300a9dcb1fb06L,0x335a594cda95b3d3L, + 0x1f97d7d4b37eac87L,0xa3d2eba220eefaabL,0x3258c906f3e828c8L, + 0xc832616f85ab7781L,0x725971928c28b617L,0xcd7196bc3233b82dL, + 0x83867eb919fa126dL } }, + /* 87 */ + { { 0x774fe73e22474edbL,0x2a7663941a84e1aeL,0x270329ad9c6dd6e3L, + 0x00c4a41514f8bf5dL,0x3ce2ea37d2267b90L,0x1275301511d24faeL, + 0x7c14d854263a1b78L,0x20c8401b1ae0b206L,0xf32a011b081f49fcL, + 0x1e8123fb959c6df8L,0xa328dc7c800e1d06L,0x5876a37824259a9aL, + 0x23ada8b5b7ef6c37L,0x023f6b6ea93d4c9fL,0x89f5414dffb6389fL, + 0x4b26bba2e628b39eL }, + { 0xd30b1cb45d318454L,0x123b749fd7436cb6L,0x3110c726568a7461L, + 0xc85de1231c84fd1eL,0xa5f8d6e608403d55L,0x395b6e139b1fabf8L, + 0xfe6d68c33cfedce0L,0x1d90381f94b91110L,0xf0a8ea812dcc6eb7L, + 0x59e804137e90ca2bL,0xbeb5fc07c8a25c5aL,0x009c253a5d84663cL, + 0x00b15073910b6a7cL,0x8607da4c4108f8d5L,0x02c3d9c3cb901e65L, + 0x4d697bc52c9615c6L } }, + /* 88 */ + { { 0xe0db1ef0efa8fb40L,0x29021c5b5ba3989cL,0xa8d6fb15809d19dfL, + 0x6b787b734c1219e1L,0x6417e16814ef05e2L,0x449342db8f9796e2L, + 0x2f878a5ebf84421bL,0xe71916d7e94a4536L,0x9818bba3ae119693L, + 0xec674be95768804eL,0x0a26074cf8424f8aL,0xdbc93b9d466ce6abL, + 0xb3f15a98c920078bL,0x9d10fd0d3870f1a3L,0xa61241d9e4e785a7L, + 0x76ca87a1e6c8cd80L }, + { 0x4357fb56e02e48b7L,0xfbd14b13cc09e9c6L,0xdb5f243524069cf0L, + 0xf878165c2c3b01a9L,0xe549e7c4e6956dadL,0xf2fe9538bbd60b68L, + 0x952f856b059dc653L,0xd3f60225b377fe9bL,0x6a0c7328bfe908c4L, + 0xce6aa2d3bc8f5f2dL,0xf721344324425050L,0x17e1266a3d3b3ce5L, + 0x75b5e43fc1677512L,0x1592706237fb894aL,0x152607532be3e375L, + 0x27e7f2c66da3b7beL } }, + /* 89 */ + { { 0x638f65ade6a15883L,0xd4a7e68c66afdb33L,0x6207b6abd3f12de5L, + 0x1c6ff95037b87810L,0xc0d44cb264acf6d3L,0x163ac601f2be78c2L, + 0x1c63cc5a1636980eL,0x3e92cfe895c9349bL,0x7738e0d841ec7220L, + 0x6169d7642d5fa961L,0x2aa776c1c3e028e9L,0x93dc5646b16d5409L, + 0xa0b27fb5706df4d9L,0x9e991170ce9c6b97L,0xea8e42be53c85f40L, + 0x02e9643783246528L }, + { 0x91540addae78ea1fL,0x51a1b74d7b670e96L,0xf9936441f7006826L, + 0x8f97d6ea7d7520c7L,0x0faa6a0269ce12e1L,0x2590aca879208342L, + 0x7a48386375614436L,0x07c6149ef381408fL,0x733bf584d7853406L, + 0x8761b0109abbb6f7L,0xe4eb249ff528a09aL,0x08781ed82e00ae3cL, + 0x864c1b252178effaL,0xcc1e62a29d513a7eL,0xedb8b94e1919062fL, + 0x739f53da4f16527dL } }, + /* 90 */ + { { 0x7a5f4a88924adc5fL,0x95646c16a818f56dL,0x0ec491297795f954L, + 0x2b48753dd19c5400L,0x16fa236b205912b4L,0x6b3d65f3e87a4946L, + 0xa7174a01045fd066L,0xb635031312a5e140L,0xa79c4b44a96b8623L, + 0x7a339d659ab003d5L,0xc72f30c63826f31aL,0xb4e7390c6f7090cdL, + 0x59ac6c36906ebe24L,0x39a7f06dbba4505aL,0x839991e1c58c413aL, + 0x020c23ffa20e0e84L }, + { 0x120e4adaafc74661L,0x37bbcf63277fc065L,0x41049cf6b6dce799L, + 0x5b8d6b537b161ba1L,0x22218431a9610fb2L,0xde9ec9d1dfdde769L, + 0xd32bfa4d42d80630L,0x3885702a6244df4bL,0xcdedd1ed45592dfbL, + 0x0e1df45bfb4e01b8L,0x8f4bded286e215b0L,0x809354876a937e6aL, + 0x415278ba8130f723L,0xc6dc469238a821f8L,0x2207b119fd8b4f8aL, + 0x76e7bf53f9269cefL } }, + /* 91 */ + { { 0x5f12842827ebd187L,0x8d3320abb65aadbbL,0xb042765a72258695L, + 0xda3f33f98f0986abL,0x411807a7aebff503L,0x25c776ca825f71a5L, + 0xc0de7bedff7df24bL,0xda8b0f42165f1fb4L,0x5f3ff737731f3ae3L, + 0x4cd1d7e7193e0a52L,0x8df84aa3b6b3ba46L,0xba84b897aa1f3782L, + 0x6e7960cce7733ac7L,0x4d46d6ab50981a21L,0x1ec12c257cbb80edL, + 0x79e7ad272b96ef09L }, + { 0x3cd970dc8f30caaeL,0x85cabcf10a6ebef4L,0x63c1863ec714616dL, + 0x1c50db0b519e3a98L,0xf39b896364cb13d6L,0xdf67d81f22547b69L, + 0x7157abb9d67db0ccL,0xccca25ba889491b7L,0xf689207c7a27e0dcL, + 0x34ae8fbe0fd43281L,0xa5d91f735720ec09L,0xb2f61909cdfd7bedL, + 0x1ec102324a039e32L,0xd3c3d65edb0d8fdcL,0x32c916c84fe5005dL, + 0x7f8c37ac4c0bea94L } }, + /* 92 */ + { { 0x33ec1e5443ac05e5L,0xda4a4da4cd8d3825L,0x86d88c0b88bf9e2bL, + 0x34d71dd0b53811dcL,0x655040d2a3c3aba4L,0x2bc40949b61611beL, + 0x1c2d426e279a4fa0L,0x535a5aa23b065ac3L,0xdaa8a32fc52ea890L, + 0x5a5deca79fddad22L,0x911f05fd2ab3b26fL,0x5dace7dbf37cd81eL, + 0x0e0e44e790d16b8cL,0x15e68aede4f5894eL,0xafe04999fc92a74fL, + 0x1d7703aa970e7c2fL }, + { 0xa8a4c81d3f0062a9L,0xe31eb2b8d96a20baL,0x66dd98df864bd101L, + 0xba05f5924413b614L,0x51a67a0de9a555f8L,0xacc2f0972e4b52d1L, + 0xab5daaec7184ab23L,0xce08b43e7c7f691bL,0x520e530b76c427f4L, + 0x7d352069e423ebdcL,0x6b5e39e834df14ceL,0x3dcbf295446305acL, + 0x682cb2e1fe34cdc1L,0xd4ac45d1111f5afbL,0xc5ef63cd47f296f9L, + 0x0a2c40ec93c20871L } }, + /* 93 */ + { { 0x09bc384faf5747dbL,0x3bad6086c06ab86bL,0xa406882e9e7c1547L, + 0x2d5326d155977abfL,0x063a9a05da81deb0L,0x9a86e4a7524b6111L, + 0x1402f87a4ab2eb90L,0x7d0721d4d5c600baL,0x1a2fd9a9f289fdbfL, + 0xf5dce66decde6f07L,0x62171277dab9fa73L,0x6d2dc49f6c474babL, + 0xdc017e1f76eed033L,0xb97175c04da825d3L,0x6c297e3d54b05e43L, + 0x2efb454656c9c87eL }, + { 0xa4712b008b21c064L,0xd186fe424a70629eL,0x6435b3409b74f0afL, + 0x6965aa437ec9e629L,0xdda14673c4c60d08L,0x0b656670bf3057aaL, + 0x7f05e8403ce86f60L,0xc05073a904401a16L,0x16b1e638294e607eL, + 0x2078325269cf7046L,0x2941141be8ce7d3aL,0xd38ad8d37577053dL, + 0xdba68fb3caa6630dL,0xecbeaff1e9504350L,0x9f5166d51d2d760bL, + 0x337532ce462891e4L } }, + /* 94 */ + { { 0x3f1118533a00bb9bL,0x2d2ffbae45f66685L,0x9ae11a85d4aee24dL, + 0x18ba1e1b0341856eL,0xa9ac81782731349fL,0xc13dfd4a545715b5L, + 0xa5f7423c5daad2eaL,0x30a483b9535b76a7L,0x92e9ada4ff873e9bL, + 0x15662d84723a1055L,0xb935497b8edac4e0L,0x61b6441a39d8fa70L, + 0x1541d75640d1589fL,0x62994237f0a05f0aL,0xfd8b00346bb28908L, + 0x192a2b5dd4cd32bfL }, + { 0x63576628365ced07L,0x029f32fb05de1d1fL,0x6d17b9bcbf40a7aaL, + 0x1b1b2a089bb50a47L,0x9389abbb795a6278L,0x52cff60fb34fc19bL, + 0xf3ab9492387d8739L,0xa8f053e66920ccd6L,0x3ef2dd4b63a9b4f0L, + 0x9ab0ede151e82129L,0xafba0c0b0838bfa1L,0x2bd5a7ac9ffc11beL, + 0x058bfd9595cc0878L,0x686d48a3f8c2f0c6L,0xc33abaaf1d9b31baL, + 0x632e22893bc0c268L } }, + /* 95 */ + { { 0x1c851d2015a1cccaL,0x4efe290c7e522bc3L,0x0b741d5518eab053L, + 0xae656197bc85e217L,0xae13141e01cf8b29L,0x2e2cb59366948478L, + 0xeb57bb0fc31bd8aeL,0xdecef5d6c264e788L,0x6fa856cc9cb96d86L, + 0x2db16813279183daL,0xf03f3820383d796aL,0x58a456ff1d0c6fedL, + 0x255898058a6abd9bL,0x339f52c583f96f19L,0xcf6ded8fda7e9ea7L, + 0x68c3d9c15d1ccd45L }, + { 0x67e26265e6b392b7L,0xcec1d9bf775d9509L,0xe16abcd4d76514f7L, + 0xd86f59b20de72e1cL,0xa66e43cd1adfb033L,0xdb34434005e457ccL, + 0xb67a79165681daa2L,0xc32e7babf0114731L,0x066fe16ed3b1e961L, + 0x924e298ef63d26e6L,0x9bea0dd8541add6dL,0xef9500df9982f971L, + 0x5c876e63c5f076acL,0x55e12ae5b23d396bL,0x09efbb362ec6747aL, + 0x8f2055ee233286a5L } }, + /* 96 */ + { { 0x4a4ab9e3b82c1af0L,0xfc65e9e7f2cae264L,0x4feaac0a60187d46L, + 0x27d3f335e393b363L,0x9c9f7c00819bacceL,0x3f7418b5b8aa6611L, + 0xffa94557372aae95L,0x937d78048db38589L,0xd10c86df6f1fbc1cL, + 0x48aebd89a2f0a0ceL,0xae5d5fa2367439ebL,0x103a6a0b3f17d2d8L, + 0xf233f68a411d9894L,0x7fece8b3218b67a2L,0x0422540f2319bf06L, + 0x1292c8c9340d322eL }, + { 0xf5eb55870386463dL,0xd4bbc2b20371d97fL,0x1b3645710b819c5aL, + 0x0cbb42d6cf04ad41L,0x5d819c7666939ec1L,0x8745ac13a01847e7L, + 0x4f704b021c7232e4L,0x2c9e58a0acb05780L,0x9523b8b3b561e295L, + 0x3384df0079f9ba35L,0x78231fc21eaa9628L,0xa2eac54f8aea2b90L, + 0x8075ed7730d1c263L,0xacb44ed5fb339000L,0x92546ac2f011293aL, + 0x7c78762beb821764L } }, + /* 97 */ + { { 0xb8f7d6fb067902b6L,0xb2823a43d1735980L,0x062cfb1259741dddL, + 0x6e391b074033f95cL,0x3831d0a368589b8cL,0xe3474d49522290f2L, + 0x4dab14d6222e1f3aL,0x8f00fcde53f08d39L,0x559917ae707f28f5L, + 0x166aa0ba068e607cL,0x602713e7d7e1f824L,0x7c2555404d6a328fL, + 0x0d2e32649890cd2aL,0xf2207944eca0b20aL,0x5c98dc0752f4e09cL, + 0x69403504d84de81dL }, + { 0xf8b7b366e5407206L,0x1ecf54cf0d88fa8cL,0x6fefe548f7272e6fL, + 0xd653137281ab4468L,0x52cb5f0e4e474408L,0x9e426b3a6490737fL, + 0x2576c19b4980d071L,0x91f346280f272cafL,0x78e60a4f468f31c9L, + 0x8776a32990844d89L,0x8a55700cb951582bL,0xab1af36514b1adbfL, + 0x22ebff92fbd343efL,0x32f9fb01b7d81f34L,0xad850e06ba6b30e1L, + 0x6da9e027bc5f9546L } }, + /* 98 */ + { { 0x21eee4c25c9490ceL,0xa96ec4a30df68381L,0xe6c607e0a4a9368eL, + 0xd8b0492a4bc262f3L,0x0846a210460c34ffL,0xf7ff7a6428df33cdL, + 0x10c5504421827612L,0x9d25fce9149bcd01L,0x725611cdcfc613dcL, + 0x159f7e8897f51ce5L,0x3fa3bf314e8c08b5L,0xea15611575e7538fL, + 0xd1e0a95191c84020L,0x0d2268bacf02ad0aL,0xa04c6ac4058b8e5fL, + 0x773b40b9b3515912L }, + { 0x00ff2cdc3631cfd2L,0x14c4c2d3807737bcL,0xd600616a338a5270L, + 0xd0e3306db32cabdeL,0x336738eaa70b17caL,0xf2f4aa8d79f353eeL, + 0x712f6ad9576f3ad3L,0xe427985289b2bce0L,0x05d8f94dda92ca30L, + 0x9891d475d8492dd9L,0x3e06a5ca4d15e4bdL,0x4725d4eb254eabbdL, + 0x31394acec0ed513cL,0x7e0f9859bbfaae6cL,0xdc125546833fd137L, + 0x12b46385c56c4f75L } }, + /* 99 */ + { { 0x810dbebd932951deL,0x96959d425aa69c94L,0x5fc49c04ecb2f08dL, + 0xac74f0cc2250b82cL,0x96a439a53aec4e1dL,0xc33cab9a90499acdL, + 0x2fccde6654d9b3afL,0xf4af285c3863ae8bL,0x2373373e46febf88L, + 0x751d672c3c9ab7edL,0xc1c51130fe12020cL,0xad82402f52f3e56eL, + 0x3489ab7aa4a64a81L,0x0a1fb661d9f163f2L,0x17c69be10e553317L, + 0x61c1935e7d88d417L }, + { 0x2e722d9b3492ae43L,0x1ef89d950538f05aL,0xae77e588200aab63L, + 0x2872c120eba4b117L,0x5c2432c83a461cb8L,0x315b3434cb938f26L, + 0x05bf2ac58c4c7dc0L,0xd2e501dd596b378dL,0xa8506c9fcb890c30L, + 0x3d0af4617c361f0cL,0x21f7b7185a35cbaeL,0xbd1035f1f3fc0138L, + 0x74628af58b248edfL,0x8d6421d048c9cae0L,0x75e3da392ca18773L, + 0x27ad0df271d3db94L } }, + /* 100 */ + { { 0x9e3bda79305b5aedL,0x2c67d4a45998d6a7L,0xc855e1d30f7eb700L, + 0xc18a7e9e147d1c44L,0x3ea99618c89540edL,0xa53be20a7e6bfd20L, + 0xc9487e64ecc14437L,0x7297920734ef85c6L,0xfa0d4e71d5e1ebd5L, + 0xfda2b1e64d48d6b6L,0x782a1e0566e200d4L,0x2a3c70da5a5366a1L, + 0xfe3fbd2b1a473738L,0xd7ef8c067fe020e8L,0xec686fdeeacfb665L, + 0x5d9b5e276dd1542fL }, + { 0x3637c5a5cb3e472eL,0x2153d92730a1405eL,0x009992e5b4498558L, + 0x18f00ccdf39a0851L,0x26237c11b5c6c560L,0x418ed4081343540eL, + 0xfef7cbf07e7f3184L,0xecd92366bf48576bL,0x1b75be1abc94c91aL, + 0x8e1778de4a162276L,0xc52e57d3c5c6bcb8L,0x5cc382c75ab71858L, + 0xe12c2c283f6e39f9L,0x4c7e0ef2d62735fcL,0xe071deb1835a5996L, + 0x24f891cdcbb8c766L } }, + /* 101 */ + { { 0x24ef60bf6778c1e2L,0xff49c03d00d5be5cL,0xec11986e2f01a09fL, + 0x59a728a4ae096e58L,0xaabbcedb7077984cL,0xfb473bd2870ca5a5L, + 0x8c928c614de30e3dL,0x3fae7f9a4f67abcaL,0x83c2b2ebec21a9cfL, + 0xafa70d629cd9b5deL,0xadeaea59c60b18dfL,0xd5fef7be4049b54cL, + 0xfceebc766dd310e3L,0x7748efe38f6321ccL,0xfe9c32b118ee8af5L, + 0x863ac3cfd42df612L }, + { 0x0a36fca7b85a2fe2L,0xf3e70d08ee429dc6L,0x8c9ba209141c3944L, + 0x306a810667272a0aL,0xe69a1555f968bd06L,0xb86f7e47153c603dL, + 0x9706614aef56e4faL,0xc0dc36b898780b4cL,0x43657fe23a1d3263L, + 0x01f97a86435522c9L,0xd91897f6edfef679L,0xebbe31d46daa17a0L, + 0x6f17910085accfbdL,0xe0da6e328f9fc1deL,0x1c9d53dbe1e7142cL, + 0x3e3f1b1e8b86725aL } }, + /* 102 */ + { { 0xb7ea15c07b7fbf05L,0x992f11b61f1a3882L,0xc9ddd95ad1dcd1bcL, + 0x31f5b7faad0f7e8bL,0x2936e5ebfca7ab79L,0x30f417dc19a55be6L, + 0x1f6f4e4343cde554L,0x971f5e6582f044bfL,0x73c3b8e44288c408L, + 0x61aac59fb807f575L,0xa64ee2dd818b58f0L,0x6f7a0a6097a3b0d3L, + 0x8b85ecc80394b058L,0x9a059474bfb3517dL,0x89ad5977a79c3f06L, + 0x81208ed8700a8025L }, + { 0x1093509914c4ce37L,0xf34bb843a1aa48a6L,0x86007024580d58e8L, + 0x6db42c49b375b8baL,0xac365524ed3bde83L,0x5521e1b4649233b6L, + 0xbc7cc5d564dd946fL,0x9c14b035bfb5b6aeL,0x7f22ba180146c1a3L, + 0x0b62fbbc872214f5L,0x3acfd7f7b4921764L,0x5ff10da1cb4d6df1L, + 0x660e262062600a91L,0x7ac7da9d81d9167fL,0x6e8e260cb6e7a199L, + 0x44383fb880deb3c2L } }, + /* 103 */ + { { 0xe107f01de44f9af6L,0x36381a4d8cb1fa1cL,0xe65be3ecfb7dd493L, + 0xd0b8435a26a8839fL,0xee60f9153ec789d8L,0xe25fea502bcc5e1fL, + 0x0477c0c57e44a81cL,0x349e9f83230ba5b8L,0xdd42f32fde180dd9L, + 0x8b039eaf64a3d11cL,0x80ef884ebeb7083aL,0x288e60c4f12742cbL, + 0x44156cc5720a0262L,0xcd547de67253b77fL,0x9829a6eca6013a59L, + 0x8aee708f0d548445L }, + { 0x18f22d9c32c54409L,0xa9ebfa4675ebaac4L,0x90e2e92886284981L, + 0xd0201f6f6b3a8e0cL,0xc973016cbd77641eL,0xf926f2f070170575L, + 0x4984048ffec0ce01L,0xbf696211f319d304L,0x74b5c844c91a88c4L, + 0x4c40fbcee0030a82L,0xbed67525e4f6d521L,0xaf7e47cc29d67d1eL, + 0xfa307db8c21d3536L,0x56b6c46abbb29405L,0xf059a7e3033e805fL, + 0x970f61fe6096a5a0L } }, + /* 104 */ + { { 0x1bc53d231bec8e4aL,0x8809ac1435a6034cL,0x4ee081da509e464dL, + 0x496ae1fd8a488235L,0xa1ae9863325864b6L,0xbaca13e974cd069fL, + 0x3738cc58b1d8a6b4L,0x5fa71f58e76b9da4L,0xc919be88c7eb16fbL, + 0xf5c8f13fad4e429dL,0x4583b6712499f9edL,0xbce20115a10d8bd7L, + 0xf66d76055790bb7eL,0x9316aede482b78ddL,0xe0d8fb2d75f855faL, + 0x404b5b945a7dcca7L }, + { 0xf9ee682a517a15c7L,0xaae4cfbcef880202L,0xcee2c1395106a354L, + 0x5de60192170febe7L,0x589e39fd73d0c54bL,0x195c71358c9092b7L, + 0xcb7ed53f0a7bfe5fL,0x2bd9242af61cc979L,0x8d2ef16c5395f7d9L, + 0x0d4ac1ca70b32f09L,0xa587526d52d185c1L,0x2932b04a942d6195L, + 0xfe25a979a500b0acL,0x5fa1f4ae562fd230L,0x60f55af220da253cL, + 0x7faa11b583146002L } }, + /* 105 */ + { { 0xb0ba4f0c6e402149L,0x3584cc1d963cc119L,0x7740dc1aa6527476L, + 0x3f77ff75c95715f2L,0xb2f234ad3f89fb0eL,0x55159032ef9be3ffL, + 0xfc9fb21d04237e82L,0xeb2eff38a153ed93L,0x89d53ae010041d13L, + 0xcf2e545b7f1bd828L,0xdd4a27ce43953ea5L,0x00d2e5d4d85e75c8L, + 0xeb93ed62241be1c3L,0x1e53f25f0242032dL,0xb9957636c3a4e701L, + 0x14b63a52ed98febfL }, + { 0x7610b55371c43336L,0x19dfd4a623a4824bL,0x7b97a2e00286051bL, + 0x86abbb9c8f5f1edbL,0x67a57d779b67daadL,0x8ace506dcd5ffafbL, + 0x85da9f9589ac3c63L,0x081cbaa875a3d150L,0x03353d8fe9346ed2L, + 0xb2ab61f1a1f9a02dL,0xb0cb09373a659c71L,0xb7e0e30b4f5df8a1L, + 0x77c4c741eb7d5a1dL,0x8f046c9c728e5cf0L,0x32dd0bc7f7c171acL, + 0x02485873836d2655L } }, + /* 106 */ + { { 0xcd40dd2375a4cd8dL,0x132ca43397bcba78L,0x30c5cd84258d61f5L, + 0x0a7ec059da1e8e68L,0x07a8f1711d65d40aL,0x869e655ef4350d76L, + 0xb98ce6f05983ae42L,0x7b61391d9d8bebd0L,0x3a529e25b1ba5d49L, + 0x46f732e91f6b2cf6L,0xbd66ec6a3fa3b629L,0x397950ecc3ef0ed2L, + 0xee9008cb5f08b476L,0xfd6be425965a0e2eL,0x78ed513c1177bc87L, + 0x6798cedffe512daeL }, + { 0x49e3f8fd1b97c5c6L,0x39fbab3e78c3b33fL,0x4427441240f595baL, + 0x174225b95d7d4376L,0x880b3fcc79c44777L,0xdc3aca833296b245L, + 0x55913df71734e184L,0xa4db23d39c934472L,0xcebb3733d1420a11L, + 0xb9d20cf9f3608bdcL,0xa618acf630cfe13fL,0x75f06b315f30874cL, + 0x506efe7f9f0005a5L,0x8aaea78c01bfc9dbL,0xf9179255f78e7c41L, + 0x3ea7aed252e96395L } }, + /* 107 */ + { { 0x98617e045b06ae25L,0xbcac148dcb5750efL,0x91ea2f0e604c2ba2L, + 0x00c19f6b76b78975L,0x79b9b6d0651da181L,0xf3225bebc945705bL, + 0x30b435f35c005bf1L,0x440b4482bc24d86dL,0x2b8f0996d6373777L, + 0x65fd6c561c44b4dcL,0xe9405ee630906999L,0x19ff092408aa1ec1L, + 0xeef3246a3d2f2895L,0x016c3765bc746797L,0x62d2569fd0705f7eL, + 0x6a8ad39c05250044L }, + { 0xe45f020d46be7282L,0x9405afed21380f12L,0x4cdca5bdd5da6ad0L, + 0xc2d6f1847f8be61eL,0x20132953596b8178L,0x8d3b1e7b7a8df954L, + 0x757c61bb39572b4dL,0xd749b57b80cc3b56L,0x9590ff9337b3ffecL, + 0x39bbb653145dc94dL,0x70c1c6062335e573L,0x9c2e72d7f763febaL, + 0x4768e424cc61b732L,0x777d2fa6aa73f2caL,0xdee4dbaac5cb58cdL, + 0x1a1811799cfae1aaL } }, + /* 108 */ + { { 0x6f6ff62f77575ed0L,0x18f14fa97d1da99bL,0x2e72aefb69efd7f6L, + 0xc45ab4cbddc28633L,0xb0e20d48586c5834L,0xd397011a39775dd8L, + 0x0130c808f4134498L,0x2d408ebaf5115ed8L,0xc506a05c0260ded9L, + 0x9e5b736219cab911L,0x4cf508c6e8693a86L,0x4e71245fcc773617L, + 0x2f71aa1f95d89ca3L,0x4bba7c6a607bbc98L,0xf3a515e7212b7fd2L, + 0x7d2ddc759230f5a8L }, + { 0x3d05816d4ed2cae8L,0x4cf6bc7db9c00377L,0xc23e98e6646b08d4L, + 0xf9ee6c614b9c0180L,0xe11c9a13ef9179c1L,0xa5b6147e8ed9688aL, + 0x7afeb648d06670a7L,0xd670333c17685275L,0xa89dd96975f9e8f2L, + 0xbb57228d37a68adeL,0x21a05d5e454cb186L,0x4810158f063dd550L, + 0x92dd4f084cb6caf3L,0x70c4d8527854abe7L,0x845969dc6e729d76L, + 0x5a52f87ab1bf40baL } }, + /* 109 */ + { { 0xed019e9109ecacbdL,0x6544023d7b89bdeaL,0x7cc51f0b5707371eL, + 0x14832b0416c8e217L,0xb1aa668281259ab5L,0x6e100f9223e361d4L, + 0xe593eee9e3a95c2aL,0x699b6bbd16c10e26L,0xad4878739473a13fL, + 0xf1c14dc5b274987cL,0x57dc00752559e2e9L,0x8449849dc3d47ad2L, + 0x83df278add527793L,0x770e3ec8eefd5b99L,0x2ae5844676bd02a0L, + 0x17f027643e705ffeL }, + { 0xdda4010d29abea1fL,0x636b96952407ac4cL,0x96a601290433218bL, + 0xf221fc3b163d534aL,0x05ba15beccc20565L,0x1238e54d96285577L, + 0x1b144257878804d3L,0x96fbf304a89a9fe4L,0xc8a7f06c4be642b1L, + 0xdd1a20e86e2b085eL,0x8f7f27c2ff4a591dL,0xc17b0753a4a343b8L, + 0x684b1e88bb173d4dL,0x3accea443dc07bbeL,0xdb15c88d4c441d77L, + 0x0ef0309a53e5957eL } }, + /* 110 */ + { { 0x4fc25721fa8e5b60L,0x646938ad691c0bb2L,0xe46d4b760b0a2248L, + 0x863f9ac27de16877L,0x503bb6ef2721c630L,0xf8c199df0b67fb02L, + 0x78c1ed72e07abd39L,0xcf9deb7bb32f0ddaL,0xaff726f06c3c89f3L, + 0xb7008b2d1972225aL,0x8f5a61174f145f5cL,0x4e0e6f8c457c4f37L, + 0x8bbdaa441c453c64L,0x57be326da6e92c80L,0xa9bc3fd95d773561L, + 0x3d3b6cc6bb37b72aL }, + { 0x6e6f12cc9722c880L,0x3a1b6ae7286b6889L,0xba1cc09bad2fafecL, + 0xad64ad7a43bb8befL,0xa5af6a0097c3f4c3L,0x2afcb0d9c353a91bL, + 0xca13fcab69ccbf6bL,0x699a1391f2abc190L,0x2dbd554223a247e5L, + 0xe206180f95488d9aL,0xba9e7bff1244cc3cL,0x29297abe87d3a365L, + 0x4054fa38fa4ca5e2L,0xb390623d67be1b6cL,0x1fa67c5778f41a44L, + 0x2e946e43c7b544e7L } }, + /* 111 */ + { { 0x2980fddfc60934aeL,0x2c3e7eff164206d1L,0xf75e7f96416ed75aL, + 0xfac60cf35cd0b2dcL,0xddc4bece1faad87bL,0x753fa87c9849e5ddL, + 0xc5d516a32c1bf1aeL,0x565dbea814732b4bL,0x007ebe3ace48696bL, + 0x40ca74d6cdb97694L,0x3f5cd27065e4e7beL,0x74847c013aac4ebcL, + 0x6762e03443d6c3a1L,0x690d8c95467a076aL,0x768d78d61eda677dL, + 0x0997ce550181d8c2L }, + { 0x9297746c965a0b81L,0x48b58be6e5e12dfaL,0x5573b3c4715f437fL, + 0xe425e907b565c459L,0x4f43f5121582797cL,0xe5dafa6f8ea5474fL, + 0x2aeb8fbe13de04acL,0xed7f95f0e8a07c83L,0x3e012a6e662c09feL, + 0xbf96e9b8c742cf17L,0x8ea5759ae28a1c45L,0x475941b45cf4e2f3L, + 0x7dd3c02df901a019L,0xe7a4deea70916b2eL,0x50b272b52fa9b988L, + 0x96f9f09fd0917fe6L } }, + /* 112 */ + { { 0x78e8aac42c310a96L,0x32a98303f7a2a734L,0xc46ca83d23962207L, + 0xad131e6ed9541280L,0x5791fc5e2cabe911L,0x50cb77eb841b6c68L, + 0xaff93dea3d3c8878L,0x06541f1df1007bceL,0x4ee729c255cdf1fdL, + 0xe0f71317323e3972L,0xa2de7a41ad4d08c1L,0xa9912abfa35e22bfL, + 0xa050122b89b03325L,0x8b9e51f406514d4eL,0x423c7aad79d3e0abL, + 0x71998e2640b8fea5L }, + { 0x40140fcdceb6ed78L,0x653cf37718534516L,0x0450b65ae8d60dccL, + 0xce6c1a769dac55f8L,0x8a96a92dae05686cL,0x2fe4476212712562L, + 0x747bcb50a4f39425L,0xf0ec6ff2fc531fc2L,0xc97c344710fe9ff0L, + 0xfb4887839c792cffL,0x552c5248026fb019L,0x4001a29cd804c290L, + 0x742b5ad835c8ca73L,0xc3781f176ee5dfa0L,0xca6b85f03dfa4ab1L, + 0x8389941a0b0d32acL } }, + /* 113 */ + { { 0xc0f062a2de067dffL,0xd4f32690bcb80162L,0x98cd990d0707a2bdL, + 0x5afc63b8fae4a391L,0x684f1b7bb32ad814L,0xb0a2dce2f199dfb1L, + 0x2260e17f48f25848L,0x7393db00c2d5e862L,0x9e88f854338cf171L, + 0x0067942902acf522L,0x19157cb86835af3dL,0x2faa6f92b8a2614cL, + 0x04ff95f5134ec46cL,0xcf00626efb7a8135L,0x454b3d05b37a4704L, + 0x1fbfda312694ec25L }, + { 0xfdebb657c8f69c77L,0x92a8278ba3df88faL,0x463b5571c1fb78b4L, + 0xd2066a1a11c71a33L,0x10c88143089958b0L,0xb975c7e0cf9d67a6L, + 0xdaa5d20873037b8fL,0x5ee5005d40bf5861L,0x300e6ce77dba69a9L, + 0x893c3cb3c962cc74L,0x0ac986294cf84055L,0x0a7ef63a225c9d70L, + 0xfe184869b91e47e8L,0x1b9d7deb8c2f84beL,0x67788915c0e278bfL, + 0x4f9488cac426f19eL } }, + /* 114 */ + { { 0x610dfcd4dd51b8ceL,0x0857927836230e80L,0xedc7ff1c36599562L, + 0x905ead4be2cae877L,0xa1c325d9e7967608L,0x3e39edddbd38926cL, + 0xda92c8685f6f0a4eL,0xe16f800af47a0fa4L,0x50b4db5be5f60aabL, + 0x3665412f983853d3L,0x64b622509b79789cL,0xea5600584e0e72b2L, + 0xabbd4901e555c2bbL,0x378419a717292e11L,0x6e0b5aaae174218fL, + 0x688e06848f796b92L }, + { 0xcdfef641313b8f64L,0xaef11b7b942c7462L,0x067cfb775c0d8abdL, + 0x608ea5f0af4041a9L,0x23d5bd826935210fL,0x5ab904fc27917a08L, + 0x85dbb1fe45d22d21L,0xc3d5e5094d36159fL,0xaebb528e1d39b8f2L, + 0xdd5ca828f44acef0L,0x24209adf20c57a54L,0x5742b43378f95f44L, + 0xd11fa7d9a9337d37L,0xd66a0c09c64cfdb7L,0x56e55b8f9bb817ecL, + 0x1723c7e3e4c41265L } }, + /* 115 */ + { { 0x9a6486d8dc8b43f3L,0xfc3e0e6126409e68L,0x1889c437d9b46003L, + 0x3a8503356284ec7bL,0x5a3665c46a9dbaeaL,0x7bf6941de978933cL, + 0x1ed5a51069341490L,0x664a7b7a8cb8002dL,0x603f76e460ed0a59L, + 0xc3e06ba31f4ebf27L,0x296ced41f2c38a7fL,0x2ac18f79cf1db08aL, + 0xc919e882cde7a3b6L,0x15e77d29dbf68b06L,0x21978baa4e947cb5L, + 0x84bf542b7630993aL }, + { 0xc1decda9e364f21eL,0x0d6cf345012e557eL,0xba246848588f90e1L, + 0x9f6dda4be3b104b8L,0x6bf7a346e3aef57aL,0x210299fee8327ea9L, + 0xaa99f487da95e6c7L,0x24ff813ed2cdf645L,0xd1dbb2d28bd414b8L, + 0x065101afcafa1a61L,0x7d9f4b9a9cdebda4L,0xaf41b395e41039e4L, + 0xe3e9e6bac50adf42L,0x4f2133ae341e9e49L,0x4968c0f3cb157f23L, + 0x383f827bda068153L } }, + /* 116 */ + { { 0x2ec46a216583ff4cL,0x4e645a294ad709e7L,0xdc66e9cfc04ca12aL, + 0x82f128f49160a7e5L,0xbfb227b1569c762eL,0xf80c7963c2edb8e7L, + 0xa7dafe0649a0f688L,0xb7e417542d14b8ccL,0x3a0c5c5386de40beL, + 0xf0d052861db79331L,0xb902ce69fbfe071bL,0x61e46956210e9903L, + 0xfaef874ef703ebb8L,0xf668947edd5f78b6L,0x6fe865475af5ea3aL, + 0x3b121f1543f94625L }, + { 0x5b26e847659275e9L,0x47581cfd6d0fce50L,0x55f5cbfd8aa3f1efL, + 0x1e7be315e484e60eL,0xd8f1a20ffe9698e4L,0x25d46da97ab04784L, + 0xa526db75834cdb3eL,0x1fd408d98d08a009L,0xfc004b205b5ca816L, + 0x5b3e3bb365e4bbe8L,0xf50cc125759bb6efL,0xf05fa817c2fac737L, + 0x9ee102d2d273951aL,0x2a8e540bfecb3367L,0x673446fb2a6a515fL, + 0x5505e1d137290c83L } }, + /* 117 */ + { { 0x0c3014a1d15e68a6L,0x6f9f0b2664dd35e5L,0x18c3742d03ad67f9L, + 0x74818c0ed2c14484L,0xc51811690d41a3cbL,0x65c8c83fc49f3e9eL, + 0x9b260c612c279386L,0xf6086faeced04e9cL,0xa7b2ccebfd7c4758L, + 0x4b3c313390297fd8L,0xca8264e809701ac8L,0x9f976a87508b3762L, + 0x5d582714983a8dfeL,0x350d2669d9d598e9L,0x85cb89cb0f6fd348L, + 0x617d80d4a574317cL }, + { 0x4cef267e70022b67L,0x80536bb53768b94aL,0x3153a566d2784462L, + 0x49054d4438243919L,0x8d11e1725df78c4aL,0x9b252a71d5a1e35aL, + 0x07866c808171e31dL,0x0a8501db1b38a00eL,0x2ed932b8ce770236L, + 0xa2d776098edaf7d0L,0x3aee5dabb93006e9L,0xfaffc8c4bbfeb036L, + 0x077b96784e21b38bL,0x491fc59fdca8e069L,0x3f624f550e938471L, + 0x5156f5087cd1780bL } }, + /* 118 */ + { { 0x58234e220206e8d0L,0xf5f6f5d47f15af32L,0xafab7289d638950fL, + 0x66ec4d097d4495f4L,0xad890c5d68da80a9L,0xe4aa092064f8a36bL, + 0x799e257e0f4d5c5fL,0x44c677ae24495e31L,0x720387b3a5b8e352L, + 0x703790f475a287b9L,0x54895cc5c3c1f2f7L,0xb8680f9b41a7fa41L, + 0xfcd47458b00b008bL,0x149cc838ba6473cbL,0x78ed5f7aac9be19aL, + 0x5254599cb33765baL }, + { 0x08739679a21b54c4L,0x029ece2ab6497d9dL,0xf14f1a92c8488640L, + 0xae48dcffe9fa79d9L,0x14b911c246c208dbL,0x5ab0fbf2dae3f69eL, + 0x180ac87ed1edb838L,0x146fd718188586bbL,0x210eb6545467cbd0L, + 0xaa2394081667cfeeL,0xdb125c1ab73d1a60L,0xde685300881c1cbeL, + 0xfe34c71337c30232L,0xc6c6070e6f3c8d18L,0x07e365bab4af4e83L, + 0x22f0a7eddcf82b45L } }, + /* 119 */ + { { 0xe262791fea7f1b7fL,0x9c3d8c5ddcff09d4L,0x86c2a9c339c7dc58L, + 0x4dad40174276e8c0L,0x0a918f59e9fe1d56L,0xb8d796702aa810c9L, + 0xeb7a88364aa5cdc4L,0xfc4c23bbe7afa72eL,0x4dbb5c9e4ac86908L, + 0x37e390136a0c7e6fL,0x855d700149c218d2L,0xe475bc6794b324a2L, + 0xc98a8dc66287a071L,0x395a299b5fb4323cL,0xe186c3ee0c0389e9L, + 0x79f81e6f16734c46L }, + { 0x83f2c1f3364f3c4eL,0x536b2ac51367e14bL,0x44a6dcfc5933e43dL, + 0x34e5947510d961feL,0x08234ece7e3f2aaeL,0xcb92e00abdea7f25L, + 0x1efba4f0a791a124L,0xc2086fd21192d53aL,0xfec0d0fcb51c8af6L, + 0x48d1b2cadc0f1b5fL,0xb07a388f812dbe19L,0x40873a6adedbdd45L, + 0xbc2a1268d702589aL,0xbbf6e3a817e27b64L,0x73ee56636d386e85L, + 0x442ecd379de7c000L } }, + /* 120 */ + { { 0xb4cd1ae68a2f90a6L,0xf277d41d6f5ad0ccL,0x6a3828c4401d4b8eL, + 0xe817a134d8376631L,0x142b758df5e1124bL,0x25fbc69dfd6b95e4L, + 0xa30c9f5fd74a9e3eL,0x5ac0f163d89663ceL,0x32a9eef70ce6386dL, + 0x7a690ea5d8ed5544L,0x5de23ff09889427aL,0x75ad36a5eaaced58L, + 0x3514a6c1d3e18465L,0x3d9162c37f093910L,0x5c10add9e33d56e8L, + 0x85176b7306aa691eL }, + { 0xa32110fa28a21e38L,0x97b6379d5773d538L,0xd3697bbf2d020dc4L, + 0x59177593961833cdL,0x6d7045fae5fa8516L,0x3390f29a786ab5d2L, + 0xac0bda30dc4f5b70L,0xcca0240adcc615c6L,0x8e1f1702c5146d91L, + 0xceb472d0a72cef87L,0x848407080b669ba1L,0x79b08f9d7e61aa0aL, + 0x388160be4669560bL,0x23935c2d948eb71eL,0xd7fd83c09431590cL, + 0x8ab154bb6e5768b3L } }, + /* 121 */ + { { 0x28686003353c4a96L,0x4e5c60e8905cd835L,0xbd5913648f66f8ccL, + 0xb6b80b989faccf9eL,0xbc1c1faee32639e5L,0x2f6396d2278aadebL, + 0x00a796d01898202dL,0x18ab548f3a474835L,0xacd056c3b31b0e3eL, + 0x15ba68dd0164512dL,0x203836d94b03f3bcL,0xd64eca6bd8f206c5L, + 0x931a361e9f1779b6L,0xd82690fc52ab34a8L,0x342bb8e092922e22L, + 0x1bfcdd84e00b02a9L }, + { 0x310b9a4375a365d9L,0xd4ade15e08d8fb03L,0x9c9753d7d742df83L, + 0xcf7309d4de318742L,0x1228e2123360ace0L,0x1043d238f7669643L, + 0xfc2adbedf90f5a53L,0x41d64cb77b5f9397L,0x5200b30ac446d010L, + 0xc3c8642d231720feL,0xfcc0122db9aa2075L,0x856e3b12041eae47L, + 0x4586445568c876a4L,0x1a1c7842233606b1L,0x9b766d1f227757bfL, + 0x25b78a3bf7b9d4f1L } }, + /* 122 */ + { { 0x90835718156707ceL,0x9bdc23984314f90aL,0x017c885a8be57dbdL, + 0xd4bba225ad63a4b8L,0x5ce71b8615aacffdL,0x5f26647572954722L, + 0x0a80f1f74f0ad3ddL,0x010538a3fc352ed7L,0xf8a640454203c6caL, + 0x2b2c7a88330c73b4L,0xb3433ee602dcac1bL,0x2e0499cfed2b17c7L, + 0x9f8681a4bd6329c7L,0x3897994636fadc37L,0xdc5650c892b7895bL, + 0x70ab957065a51cf0L }, + { 0x46778ec47b585d93L,0xca6d3610a633fe4eL,0x21da154e4ea0311aL, + 0xaf22190bbd64002fL,0x9e633ac7d91cb7a9L,0xed13c31fee6837d7L, + 0xda4a07d71616ee8aL,0xd78a27323afcd616L,0xc06696e5ba14d694L, + 0x733754d74df58420L,0xe85e504e2778e3c9L,0x3055aa0c55b5a5c2L, + 0x313df5388a3acb5cL,0x5896acb52a088edaL,0xfc8842a084c85ddeL, + 0x5fec9f7951dde6beL } }, + /* 123 */ + { { 0x5ebc2c7cfe519f99L,0xe396bd80e5410353L,0xaded94028a3988f3L, + 0x1c03b735d601bda1L,0xfd30203614ce64acL,0x5837ebe901240290L, + 0xcaaea1a3a554097dL,0xdce73d25b0b88139L,0x35ed412becb090b9L, + 0x99029ff7d63dab3cL,0x555437d9062db071L,0x277d2f5642a4c11dL, + 0x477fa64524fc9109L,0x7b12e9b72799254dL,0x7ad2ae22d84c618cL, + 0x0a8d5663ce8ed195L }, + { 0x43ac51630a21fde1L,0xcfcf5dd66903d849L,0x6d2499ee5fdd6281L, + 0x4dedc6f077a49a34L,0x46bda2c02875c06fL,0xd0e0e0f6347b8046L, + 0x1058169b5e67836fL,0xc961912ade8a8042L,0xdf3fea0aa93b3d32L, + 0x9f138edb0c576bc5L,0x7971ad6ed8d37e47L,0xeab85739cce5e7cbL, + 0x88a4b4341d202b40L,0x5d842557e3a1fd26L,0x872fabd5b3a86f91L, + 0x95b934936aa4629fL } }, + /* 124 */ + { { 0x9998a70199f951deL,0x8fade596f058db45L,0x4d479c1ef3d03dd3L, + 0x6e928d5d33b141d3L,0x9a465800acfe8a40L,0xd108ad2fc1cefa3dL, + 0x64b96921e013726eL,0xb9b6a6b68e83bb9fL,0x29f1e6dc1242e544L, + 0xd3f8f6762f65966bL,0xa34dd0965e105b41L,0xd4e9139a16011e1cL, + 0xeea4dc682515541bL,0x6f8030acc822166dL,0xbdc7ae1d31d16124L, + 0x2e25ef51621afa7dL }, + { 0x2533cf8fdd8e7357L,0x333ba218eaceddb8L,0x68e3e31d0784d2acL, + 0x1c927f36f2804ae2L,0x01433d2277e7ad7eL,0x0b401cf0587f78a0L, + 0x9dfcf036aa0027aeL,0xc9e46c8b1d9a46b5L,0xaa6de4861f288d32L, + 0xdd56da2f1b8a043dL,0x346230e5f2d0bb56L,0x19f0b6e419defb56L, + 0x55ec37cd21d2c874L,0x3dbf0397b70e45b3L,0xf0862a8dac7ce852L, + 0x87979ea7e141f3d6L } }, + /* 125 */ + { { 0x9b7e7b3f7f1c747fL,0x151a4c1dc6e63369L,0x4273ff70b372dba0L, + 0xca6d2234d3ee54feL,0x12fc8e0cd33cae0fL,0x273285385dd6f10cL, + 0xc86f3fbdf01a9cf9L,0x5322677fe36cae91L,0x39a700332fefea44L, + 0x2c9ca328ce8af217L,0xc0256776f6a731f4L,0xc687b3df66a96813L, + 0x194aab128db2eda8L,0xde30dc5aeec4febdL,0xc052236a979241b2L, + 0x3ec98802c23d4c16L }, + { 0x0f9e760c4072f74dL,0xe78eb0deab594059L,0xdb3dea40c9b009c2L, + 0x47e875f038b59ae5L,0xf40eb4362b4daa06L,0x9a6a4f92090f3788L, + 0xefebe9afedbfaf8bL,0xf87f96a59867e256L,0x1e6fed2375ab6aebL, + 0x17f2782a3fdb13cbL,0x5102c71e70fa2621L,0x5d2b06ecfd4c0dbeL, + 0x537cc26830347297L,0x8dbf5e2b2b67e780L,0x2f633f3aba25da32L, + 0x3e9315e8efaec914L } }, + /* 126 */ + { { 0x9255cfa5239a9ea9L,0x20f3c6900be33a62L,0x759eeb4b9cb642bdL, + 0x3316c54600bae718L,0x874a76d5f3410f84L,0x123b502e90f129b6L, + 0xadc8f9a812851f1cL,0xf57b764a1b62408cL,0x116ec01f1a80777bL, + 0x746ecef21f0ddc5cL,0x3c49d47ce5a6a5a7L,0x1e15dbe706e955baL, + 0x629c0c79b45d79b0L,0x11278308778d1087L,0x22585dc78c6a22d7L, + 0x2ed02a0d0a682791L }, + { 0x530434164daa2682L,0x0e26d32b01359625L,0x449c834abd867097L, + 0x11a19d2bee77ae2eL,0x39bd529a3af6c169L,0x36cca5c05cd61054L, + 0x6370a59bdc6c0fe1L,0xca420d27b93d5135L,0xd8730d45554c451aL, + 0xebd258c996cdebf2L,0x0cb1b990a50f9a05L,0x69a8c97a7b0f0151L, + 0x2cc36d3411d217e1L,0xf117688a752f75e8L,0x1db01394a09b2a61L, + 0x14627844a9efd7ddL } }, + /* 127 */ + { { 0x6bca3aed232803cfL,0xc1e4398b9a96ff34L,0xcaf6757f74ab788bL, + 0xc3a53e007e68c04dL,0x5f969c195cb7cd20L,0xf28b65a6dc068bcaL, + 0xe3ca01d31d863032L,0x9b733b8187808e14L,0xb5d704d9efe618beL, + 0x276f3542b01b946dL,0xe057e19efbedddbfL,0x7d182f2b903275ceL, + 0x3cdc5f77880f7bc6L,0xd6f03d3f78476c14L,0x035f5557a9ba5072L, + 0x7acb57b6b4029628L }, + { 0xd241356944e6b07cL,0x451c4cc9e1c7345dL,0x407444d8e273b9fbL, + 0xfe496079b88e34fcL,0x77d184cff152776dL,0x6d1033b9c742299cL, + 0x29a0a68477bf2897L,0x59ffdf10ee8f0420L,0x4e17146c44bb56d6L, + 0x831d06c2fb9ae855L,0xb2cb82dbd93e7cd5L,0x83381c463c96b607L, + 0x06aed2517549e2a8L,0xef97891c774a21d4L,0xae9807c78675fbddL, + 0x6a5a05b96363516cL } }, + /* 128 */ + { { 0x92e71ea66a8f4f33L,0xf2fc6fc64dea8f4aL,0xd356252cfee88461L, + 0x59b0a83e08954d08L,0x5bd68c23468ab766L,0x40281357900f8d04L, + 0x181c19c052b867aeL,0x986a516918764c41L,0xcb01dfae13575d24L, + 0x17269ae5593677b7L,0xf6d1702546dc9b19L,0x8de68499c40097c8L, + 0x76df0032259c407bL,0x4091aad917d29d8bL,0xa7f46d214a7ab5f6L, + 0x688054b470ece48cL }, + { 0xf0d168aa51a5b86cL,0x2437e4d895777247L,0xae844076f1720329L, + 0x0a7ac87d9647a54eL,0x1e597a4b0405622cL,0xedefe5c6f0a79f2fL, + 0xaf3ef0c24d55156dL,0x917fb04eef047cf6L,0x3792799f54b62137L, + 0x875ea32f314be0b8L,0xe157c65b0c466b0cL,0xd28c90ce7e218978L, + 0xb90fc3bacde587afL,0xdd32d71c8b877bedL,0x3b432200ca8e10cdL, + 0x0021f419d94f6e53L } }, + /* 129 */ + { { 0x2191122c43519d26L,0xbdafac1d40a51845L,0xcc6f71e9548bb89fL, + 0x9ef3375c16844bf9L,0xe7789f79178e8d55L,0x04f599b61f8be1c5L, + 0x8088c99a2cbbde40L,0x8939a260893206c9L,0xa1ae4bfffcd30851L, + 0x664cb3fee08feafeL,0x61f38099ff14aabcL,0x0d8394cc2a841ef9L, + 0x75fad8ad17f01db6L,0x6fc345766debb773L,0x1e716b05a4252512L, + 0x7985588029e1ed9fL }, + { 0xa2cb3aaa95106473L,0x95fafa415a61da04L,0xfd3c9362539563c0L, + 0xbaa4809195312b87L,0x6c7e7582bf885c76L,0x70f6dab6230c78d5L, + 0x8ce3051c7747440dL,0x6dbebd14ffdb6186L,0xb0e041fa190e4096L, + 0xba10c4666ee62e2aL,0x93d57e2a74f333d6L,0x006aadc4fe7b9b66L, + 0xfaf72f6c06d2837dL,0x318cc5e6910741eaL,0x9c50260965692477L, + 0x95d823c31d0fb08dL } }, + /* 130 */ + { { 0x6aeebd86140528a5L,0xf268c2ba53979bc8L,0xb1bc9b8a4ec144abL, + 0x1efabb0d82a7d7edL,0xf12c70d14e0118d8L,0x31607168a1c1558eL, + 0x33e428b7e4b7e73eL,0x6317663783aec9ddL,0x5172ffbee12ac35cL, + 0x37df0bfbbc17b2a4L,0x4212f870741f812aL,0x3dcecbdbe2888f9cL, + 0xa9dc15aa756ca55dL,0xf31918ecb9028e41L,0x7ede02856aeadb03L, + 0x0e2708d578654f54L }, + { 0x2270cc53cde20f88L,0x9338272c5f5b1039L,0x5042e19e5dcb1dbfL, + 0x4b3de219b72d74c1L,0x16c49a8b2aaaaa55L,0x008443e5bba86ba6L, + 0xee6bcd7220cf1695L,0x59ffac6ba89abd11L,0x2831217bf115639dL, + 0xe4d28af2f34cba52L,0xf27f03e70727a906L,0x6842c79f69017766L, + 0xcb3469bd7a81123eL,0x48c0f346a42973b8L,0xfc5784a623990dbdL, + 0x0d3dab3bfb299678L } }, + /* 131 */ + { { 0x8f8376e6ce29c3ccL,0xcb0507ecf016cbc6L,0xdebff9965e394ce1L, + 0x24fc526f73c50d41L,0x4edd5a542d16ce3dL,0xbb37bdd991c13141L, + 0xe3442ef2e33a8606L,0x2ae90337c0629da8L,0x57faec64592ab331L, + 0x1a938997d82b857bL,0xad6c8cb9a3373176L,0x82595de29086751fL, + 0xa81e97fb18c17196L,0xe4f48a13bf697357L,0xa1387c2e5cb89f69L, + 0x530b4eeb5874b426L }, + { 0xe9f275a1bab7b5aeL,0xbb69dc4d03a57bf4L,0xc974dc4aa45c505bL, + 0x726369f3416ac402L,0x735e4e78aed985dcL,0x0548d879cdd446a1L, + 0x84ceb0699e16b02aL,0xf73f6fa4789b11a6L,0x6aa0c41fb2a4e784L, + 0xb1f7690293a9b697L,0x814cce00f03a8ab2L,0x64cb255b844d66c1L, + 0xb794e7d630952201L,0xe052d4e43da32271L,0x5278b2e708b6a4d9L, + 0x9094255280c6577fL } }, + /* 132 */ + { { 0xd269a14d0d5b4c2fL,0x2b8fc59b5c8a649cL,0x95becb3ab0e37d4aL, + 0xfda1a7689111037eL,0x5810e05a94e35322L,0xa24dcc12a178fafcL, + 0x5c2c63b28e3dce62L,0x995c3f179452c444L,0x35330ec342d45161L, + 0xa025a60ab4ef8129L,0x854932528bae9c13L,0x25d1a606e2e3caf8L, + 0xd44091ab3649bf47L,0xc7d0afbf704ec5f1L,0x27bd1d62bd8b3333L, + 0x50570111cfe616f5L }, + { 0xd0084acef534356bL,0x9df1de054b4b0fbcL,0x021afe05cee04dc1L, + 0x64bde688361b78e1L,0xa324fcc7ef78d38bL,0xfeb372ceeb0a5e4eL, + 0xef04fcb365811996L,0x7dce5d505eb0ab4eL,0x1e29b588238c586eL, + 0xde5e3197bcd80037L,0x8bf5e4514806b9cfL,0x4330968bd18e67abL, + 0x26a7d04ef9f63fadL,0xa1c7f123b5c18bb4L,0x485b848225dce22cL, + 0x8ff0b36fd540e79fL } }, + /* 133 */ + { { 0x99f2e2f43ff42cffL,0xa3c19f9d1c35317cL,0xdb749392aba1b545L, + 0x84232b054afa9a32L,0x0b855d46d7dcd436L,0x8ac35e2045cf9915L, + 0xd7cf22c7f001a218L,0x057d35aeed408305L,0x25a4a519553ccfcdL, + 0x5e56579393e2b939L,0xa20332b03422ec27L,0x9b09005e3ac53958L, + 0x628051a379e9b163L,0xb4a0dc09fc6618d6L,0x9e0e857f6748e7afL, + 0x71b28eeec577d63eL }, + { 0x4942b0cd99726bf8L,0x1290a3b91c208f3cL,0xfd7290e7b0598eaaL, + 0xc6a7791fa25a9128L,0x2d33db24c037d7daL,0xc21efeb070e2837bL, + 0xbf70d96ee3dae2a0L,0x43ed819185076027L,0x4aeb0aa84d4ad7e3L, + 0xbc75101fe8c5b74cL,0xdbfb2a6ead26ebddL,0xba8120686b78aa4eL, + 0xc94aa8f2e1159848L,0x0d10d9db3eba5c4eL,0xce7fec476318295aL, + 0x7294711a330d925aL } }, + /* 134 */ + { { 0xfce4590432bbd495L,0x330f4dd1be54973fL,0x006bee1d5d9c3f4eL, + 0x40ee607859ba7204L,0xc194fd3f42c2c768L,0xa0e76b12e9fe88beL, + 0x17cddddbec2b0210L,0x689d436b00811ec7L,0xa6a6ba37284be9e4L, + 0xabc395b2007d4114L,0xf8cdf9f30f11e744L,0xc5febec8e9396402L, + 0x8a751743eeb46285L,0x99bf8782c6e0d137L,0x3965e170beb292e3L, + 0x001c39d85801fd5fL }, + { 0xf4805cb9da4a0912L,0xd27cb76a4410bca4L,0xef3dcb8eec71d65bL, + 0x780fbb2b4816849aL,0xef6a7026a8b24635L,0x15625c8812c44e68L, + 0x624c232c4d7a74a8L,0x81a770374b1631e4L,0x04e4f7f1db917c2eL, + 0x1d0465fd1f61ed95L,0xb1048049cbde6e3dL,0x637ce0c1d7131fcfL, + 0x22e4dbc28ada4715L,0xf7530c5cace99726L,0xa0160dccee287450L, + 0x9132e670bb91af13L } }, + /* 135 */ + { { 0x8057efe27996099dL,0xb72344dba06e608cL,0xeb4a8740d0958588L, + 0xe53daf0679e5aee9L,0xc9560a9a908a2fadL,0x7f4be131107e706aL, + 0x6d5f3d9b2830246aL,0xa5f8e8da27cca3e6L,0xeb51dca64c28f292L, + 0x4cfa310ef31dfd78L,0x92e0c7c22ca073e5L,0x102f1694a40da683L, + 0x16bb07cc750d38fcL,0x703e83e2badae035L,0xea93c066b4d3c9ddL, + 0x7d0b03e579940ed1L }, + { 0x5fe7ea304dd94c63L,0x57ef01c5738b0b3aL,0x9534a78ca14e6b4bL, + 0x07622cdea5353276L,0xaf696a077c22d006L,0x733c18867d46b209L, + 0x9654ccbb626c2b4aL,0xa098d3a1a84f3c4cL,0x3596f9ed2d734b74L, + 0xdfd3021a5d551c90L,0xe2ba7d2f1ec5123fL,0xf9726925b2c1aa39L, + 0xd2e75d0ef8eb2927L,0xfaba712e19192a6fL,0xa606b43a9b83e50eL, + 0x31b1782fdab5de60L } }, + /* 136 */ + { { 0x878dba454034db92L,0xa39779018f34dc4dL,0x8d004f2edf754c33L, + 0xeaa5954acd563a88L,0xa29d6c89bb5ffad1L,0xa8adf655b0d8bdb8L, + 0xf7fb842d8cdbdb47L,0xb72e3a0380d3205bL,0xc335b0b27cac7ca9L, + 0xffc60bcbd8a5475dL,0x736f7719eba4d25fL,0x3d901c380c50fca6L, + 0x1fdacf7b80c01900L,0x75cf658f5681f84dL,0x57a7e6345cefbbc1L, + 0x6fc0fbe53e07ed1fL }, + { 0x496d116bb81b0e5fL,0xd82dd2a52ac853b8L,0x357e22d4327387f0L, + 0x3e332a84ba912c59L,0x8b71c64349d5dcc1L,0x0c982ee9438d85d3L, + 0x90b9553cbf7fcd4eL,0x2cb39bbc38fed5e3L,0xa2c67c9c5ac42903L, + 0xebf21217bf07da55L,0x55ac05ada0b9e4eeL,0x10bb12c28ee9e0c6L, + 0x5cf3aee548bb6e3fL,0x4ae7269c8b046e91L,0xcb266012aa0e553fL, + 0x701935a1a94c8fc8L } }, + /* 137 */ + { { 0xde58d41da4626deaL,0x25ef66ca15b9039fL,0x99a810a43164e65bL, + 0x9fe6daad748cfccfL,0x7ab9a6bd2f142fa9L,0xa4cba1685d471796L, + 0x12d30b366bc3a39bL,0x1f46a5dc8bf45076L,0xb868e5291421ac0eL, + 0x7a68620659bba1c4L,0x2b4b552eda698b90L,0x5039dcd4e5453707L, + 0x42a07a9e9e90165fL,0xa838fff3d7d45dfcL,0x41991e5a3b5ceb30L, + 0x6c961ec8969ca600L }, + { 0x703bdc1bc4e7eb46L,0xd6bac557596c7b48L,0x4f9917cd66afd74dL, + 0x56355105656ce6f3L,0x3d1fb50c32497175L,0xfda6783e63effb2dL, + 0xbd79f1f3eefaa2bdL,0xa4efbe5417af9ef7L,0x6cef64625a55b7a4L, + 0x116f32381a713304L,0xdb2a2a7fb95625a3L,0x6a0aa43a0b027e96L, + 0x458fe5d24832b3bcL,0x523418df5adfaac0L,0xc05a89cbc49e7f9aL, + 0x830883d869e24b53L } }, + /* 138 */ + { { 0x959b1c6202557389L,0x5fe5ce97adefc0bcL,0x893bbe7f8330f383L, + 0x27e0c6af16cfb81eL,0x6f64e65bd04428fdL,0x53de9245b79e6182L, + 0x08a313c1487e11caL,0x65cec3b9445bce93L,0x33bc0314d67ed49eL, + 0x69f36b2430782352L,0xd78e5daf93ad31d2L,0xf2682b70c780890cL, + 0x7015c34f9e45efe9L,0x135d4ba4e6cbafeaL,0x43a378a47e3fcc6cL, + 0x2376f97f96638f8cL }, + { 0x0a6e1ec0ae575b99L,0x7e14cb4f81b970dcL,0xf00a3824d3a73947L, + 0x0b4b9c81fb235a9dL,0x8d15115f5bf62944L,0xcfd35b431e165d7aL, + 0x5d12fea2b2ee3e3bL,0x629984a6f5182e7bL,0x4e43e2f3c365d08eL, + 0x9932709130f36e72L,0x698b4a00fd345401L,0x23c4fd0ebaf96dceL, + 0xa60ba0ae23675554L,0x51bdac2db0325784L,0x8ab4190a215464a1L, + 0x8c4616616bf10296L } }, + /* 139 */ + { { 0xeffca2582d1f36a5L,0x0eded2b2894c5f2dL,0x35a5cdb843ced84fL, + 0x290f8982db0e3b9bL,0xcce0eaf00719a112L,0xd0e657e439a362d6L, + 0x5516a55d62697e47L,0x269e1f778e636514L,0x5e3dedcbd50269bcL, + 0xecec2300441c57c5L,0xdb83f31cc705578dL,0x1bdefb731e489eabL, + 0x20b678cf395fcdb4L,0x908cf91cff9db001L,0xcbebc6f455f52cc8L, + 0x155ea622b4c61162L }, + { 0x94be2f1f876fa42eL,0xab5e87497fadeee7L,0x692e70f538c865afL, + 0x16e99b84df8059b0L,0x0ceb606e8b5a7ac9L,0xced233572d463d2bL, + 0x2d0f26232a9a09a0L,0x2529998c3861fbdfL,0x711888a7c1be310bL, + 0x9b1229c50d8aade3L,0xdbcf9b783b13533dL,0x3ca746f8ff029708L, + 0xa5a013a1da83ef88L,0x8e904d184ab28444L,0x2fe84b3dbcbd4abaL, + 0x8f570f24259058c3L } }, + /* 140 */ + { { 0xdeb66c8a2ca9c508L,0x2dc5bec269d6b780L,0x16d6126688ead600L, + 0x61841b9749d72614L,0x41e40e6cce472e6fL,0xada242641fa7a876L, + 0x45b9fd33cc3997a0L,0xb25e8fa97c15dcf4L,0x0124ceb212e9629dL, + 0x3a8c72c67db3d956L,0x8e2ded2b7c1a7844L,0x94ab09c66dd027ffL, + 0xf89a057d7e7a2bc6L,0xad8bf226cf70c763L,0x4cb268e7c8a26212L, + 0x3d171e87b2c44c1dL }, + { 0x382ac16e8ce49820L,0x24ee45e2c0c44dc9L,0x0ec6791273e858c4L, + 0x918cb25c46327cf9L,0x43e3876bc6159c1fL,0xb6b6e0e037545cb3L, + 0x64b839ab5d12347eL,0x72e09274a300d541L,0x26ab28e6881c1169L, + 0x4a580fffeb75a843L,0x0a5802ca359120dfL,0x7fee82d03209f4a3L, + 0xb518016b8e6a9380L,0xb99c6c70c2ee11caL,0x16105af1ab9d4ec7L, + 0x234e98f834cd9004L } }, + /* 141 */ + { { 0xff43520814db9cdaL,0x99cfdc4796adec90L,0x843aaa6faf458b6dL, + 0x3f1f7415743eaa31L,0x915e192e61735d81L,0x3441a22d0ac595d5L, + 0x704bbf67c044bc8dL,0x2f960471be23a236L,0xcc32638815d1d557L, + 0x9410230b76b1dd94L,0xf2e5439f0c1c8a67L,0x56b141ac833c910dL, + 0x467c999f865b84dfL,0x1b0251fa21f02b7bL,0xde5b526096216950L, + 0x6a2130e3ce3a1e93L }, + { 0xd21b67a04b3ca1a7L,0xaf42ed5300c0ce80L,0x22ccd368932cf07aL, + 0x36523a815c25c35aL,0xecdd39588dd04d06L,0x73da3502b2f93a3bL, + 0x4c5e0c3cd5e5b530L,0xef9f548613268777L,0xed87fefc1e742292L, + 0x6d9ac29ea24e5edeL,0x08abc9f033849f1aL,0xb09b229240f23905L, + 0x6791072c7f934353L,0x102a6381e6aeb550L,0x3ee0740996feb870L, + 0x34f06faa9c4d2830L } }, + /* 142 */ + { { 0x869dc79f2348f005L,0x9b5c5d71df4920b1L,0xfd1b57ca6dee64a4L, + 0x21b7f734e82a4fb4L,0x637cb834b9578366L,0xc934101b7d287d96L, + 0x1590f8ac0392ecabL,0x280dc3737f75f4e3L,0x8b36f50f6a61ac62L, + 0x74f58304a65568daL,0x80d792a9d930870aL,0x6d17b192fc8895ccL, + 0x498392fa4914939fL,0xaf36027dd41d5b9eL,0x452d79e25caa82b5L, + 0x764d47b1f4115d1aL }, + { 0x5df22303a2ee8b9cL,0x1b9f72d385dfcd48L,0x6b42b98310813a37L, + 0xe28c523b3de741f5L,0x0857625af303bb5bL,0x926f299aac9bf9afL, + 0x21beac080d445b34L,0x6a523a02d6ba2c0eL,0xe302a1b17fce2864L, + 0x4516a235e300c1eaL,0x4543736a7b4a9311L,0xd3c0b9e8c0cc89f7L, + 0x0481904f40ed88deL,0x4f269b563cb7fc70L,0x09a1d53a321b9738L, + 0x1c0dd9c3230a3810L } }, + /* 143 */ + { { 0xffaa1f67c46a7d9aL,0x64743334bedf91ccL,0x45833a7447a42f2eL, + 0x67980051241ffaa9L,0x70979a84335efe6bL,0x5f0613f5f08b2403L, + 0x6bb22fcd64f211dcL,0xe1b8b2a3a0572cfcL,0x19e0eb417950a14aL, + 0xe634bb293eb6cd4cL,0x31a04b25470a25ffL,0xa41f7ac9a3d15a0aL, + 0xefed85ecbf2fede9L,0x1f581f5f81b94a00L,0xaa3996b09ef4a15cL, + 0x52d8be39b06041bcL }, + { 0xbd1536f6fd631a2fL,0x91fae7f0b351a8dcL,0xd1a590c79b126212L, + 0x52d4875f2bd0f435L,0x9aedb6d392b0ea70L,0x0bd0abdcb83ab89eL, + 0x827a106289fe192cL,0x6566a960102a0bdaL,0xda083037ce036814L, + 0x30bed79f58639405L,0x972019b6dbca8df9L,0x89201286efdaa3f5L, + 0xb337b9965236b892L,0x11d3e38e28fc2e73L,0x70787f41880e8da3L, + 0x6cff6367dae4a45dL } }, + /* 144 */ + { { 0xbd3d0433f89a8bb4L,0x42144c3393b98f71L,0x82b616c803470a2dL, + 0x98fcc757e5da089eL,0x542354ef7bf5fda6L,0x1885c2539ebd34ccL, + 0x2e20b285bec5dd0dL,0xe71bbbe1782a1bcaL,0x959ded309b854ef0L, + 0x172499798997fa6aL,0x50cf8fa8d81f3c45L,0xa9a3b51760c11152L, + 0xc9b0ef7decf845eaL,0xc9339e23b9fed11bL,0xc93e9c5c28256080L, + 0x1d2c8217613ec1e7L }, + { 0x7381347d987cfc93L,0x047603bbf187f810L,0x3fa6bc9d1250ca31L, + 0x480091e0bb055bf3L,0xbdf95f1a3a3af87cL,0xe2687770140540abL, + 0x998df730d7fe045bL,0xb398135fb723bc2dL,0xac230f8c15ebec46L, + 0xe08e18305f5561c0L,0x7c0fbf4cda60a47fL,0x06e95c24e16d4bfcL, + 0x7416349574617e92L,0x397198694ae0c20eL,0xfe2693122131e2b6L, + 0x25486e360a537722L } }, + /* 145 */ + { { 0x618795ca53572806L,0xb2c89449656968e1L,0x149c2c973fb323aeL, + 0xfb15de26409bc7d6L,0xa90cda72c79121b3L,0x6d2fa14e204cabbbL, + 0xcbcda6f791604125L,0x25086261b435f947L,0xdb686c38c282eb10L, + 0x51016d62f1a791cbL,0x6b1c7ed161a2266cL,0x26780666271d74a6L, + 0xb5ffeda1824287a4L,0xcbe503ffbbe4f0f3L,0xd7f7f0beb9482a74L, + 0x751b2358088493f1L }, + { 0xd597b9d6e9c9be68L,0x1794b5c467d10c6cL,0xa88cdc3d7762b2f4L, + 0x6d94a63aa1b44e11L,0xfb0bbbb9aaa8eca8L,0xf4b0f2d0c963d87fL, + 0xb753062c5dc7075dL,0xfed726ac49933989L,0x5da6063857f9ccdeL, + 0x221c392a75f8c766L,0xcd264d955dc672caL,0x7004ff22b66ecc8dL, + 0xfb1aa9ae18a458baL,0xea9644df8babd653L,0xa9378e802ba0de7cL, + 0x144cc12dca2c6c75L } }, + /* 146 */ + { { 0x593a0a1d2989aa3aL,0xd83f228359e6e64dL,0xe938b0cbd32e732eL, + 0xf4c464c53c3cb249L,0x9750a5f8f89ea6acL,0x467e5bbf346cfc32L, + 0xc9bfab9d37b2b809L,0xf8eb74533b339c6dL,0x3fe01fbe3b766deeL, + 0xb3154254ef6aea27L,0x555c3df27be61b10L,0x70fb6d81dd818488L, + 0xda1af3a4bbe714f9L,0x575f20179d18f693L,0xdc08fc6b2465b839L, + 0x874ecf336b84a951L }, + { 0x624af83ebbb3f6beL,0xf578fbb908bb423dL,0x5623b0bad7873527L, + 0xc3659bd8a62e0442L,0x2903b167fe236f79L,0x55a430c6e53f26a6L, + 0x222547ae3ad712cfL,0xb73890d776eb272bL,0x95b4f70b3d628df9L, + 0x9f0e13b053eae4acL,0x5b4f5138e7f2174eL,0x75482cf998dbae17L, + 0x2b69bbde44518480L,0x4f279652cafef15cL,0xa0a3ef2bb6bcaf19L, + 0x31fb8581ce4c634fL } }, + /* 147 */ + { { 0x398306d1615cd607L,0x680c9faaaa32c3a6L,0xe87a705b7779131dL, + 0x1031013a36708b00L,0x814fa0e19445297fL,0x70c5583aa6a79b56L, + 0x03039cbf4b16bed4L,0x18a7ca8daaaaf8d3L,0xf33159e75cdb68a5L, + 0xdea0e738d23814faL,0xeb3527188d0f4f9fL,0xb0b76609dcdff032L, + 0x65ba8ea93d48338bL,0x18044d8255dd507aL,0x844a223e4a4a50b4L, + 0x9832300018e19e54L }, + { 0x28a2102757f3d5a6L,0xffce56486e8cadcdL,0x9590381b02551f3bL, + 0xb26cc64f935ebdf1L,0x60611291c083aa6eL,0xcd988a6688e4cf41L, + 0x581c3f73dd53b1b5L,0x78c804a977fc621dL,0x31874330fadca2faL, + 0xf7008da4c83ccf02L,0xc4122a1da79a4707L,0x9a8e0d3f4a915eb5L, + 0xa2de157dd0123660L,0x45ef43b265ead2a0L,0xd0a22ade188db285L, + 0x8abbe39e922e0caaL } }, + /* 148 */ + { { 0xb44469053a2d2f01L,0xd27c31935dc6685cL,0x6a908bbf1d74a027L, + 0x01da350f5b50ec1dL,0x1d3dd45e3f3c2e26L,0xf66e11d0b836ee92L, + 0x7e03908f474b979cL,0x19e7c5b998b87834L,0xa741d3febd3d1de9L, + 0x63c68e8d1ef6059bL,0x9b9ff9393674e247L,0x1d7d53e73e7e67f6L, + 0x698dc326aee9e248L,0x52f23edab3bd984cL,0xf95e31b06f8fe8a7L, + 0x0f15b4d0c3d0ba95L }, + { 0x8f2f6635790a8d85L,0x51bffbaee2595af1L,0xd15b7ec624b51287L, + 0x7639b6ab3234715dL,0x0cdd52992bc5441dL,0x54800ea4f6d05833L, + 0x21efd752f6d6e360L,0xc0b7ffe519290613L,0xb68a5825eea898cdL, + 0xecedba9222982266L,0x678a91b0bbd06bb2L,0xb2436dc04bb6b0cbL, + 0xcf7a99e7caf8ea98L,0xb92d0e6e71aa05bbL,0xbf8d0471f5993eb1L, + 0x515db37820385ddbL } }, + /* 149 */ + { { 0xee43eaaa6f5bef22L,0x952d269820348712L,0x1e4c484e7a3af6c6L, + 0x18d434c69a8c9403L,0x63e5d7415001899aL,0x5238dbbcfe8ea40cL, + 0xca6cc8d296798721L,0x73db6aee04acbde8L,0xbf69328db7f993ceL, + 0xa3f79bbfad45e334L,0x8c51ec937c1f1630L,0x4907325f9b00a6deL, + 0x49e6acb412d82bc3L,0x5901b36d0ec59fc9L,0xcb09b7109cf34e3bL, + 0x2de0487e1abf4c02L }, + { 0x18b722f38dd9d484L,0x833493937c77baccL,0x58dbb8f193d92b8aL, + 0x80d78d508e3fac25L,0xf0500981745f4a7dL,0xd072bfed877cc29dL, + 0x67abf8f2c30a89f8L,0x92c567ea9a0820d7L,0x425ab12e8a3a5738L, + 0xc162faebf055521bL,0xee1c4f26b94ea5e9L,0x1e4149943d71e546L, + 0x258183b843e8be1dL,0x44917c82ef9eae0bL,0x6813a45773874a30L, + 0x6f6ac071cc42f86eL } }, + /* 150 */ + { { 0xd38822ad4dd6e3b1L,0xfc78e1ccad620869L,0xe78438452cacde80L, + 0x121cc14aa8469fe3L,0x8e8f3da7e67e8ef2L,0xdb83d16e4d347448L, + 0x3ba1dd98798631f4L,0xdfab59770a4c4c17L,0x1f0a13063edc701fL, + 0x4649d6016cd8ff28L,0x2267230bbcc55bc9L,0x02a19c605760412aL, + 0xc719d5f1328faef6L,0x27cb969ef67eaad9L,0xf342530e719bafb5L, + 0x6e2c24ccff5a82cbL }, + { 0x6313024badaf8793L,0x944bccf1035c948eL,0xe9a066b7953500bfL, + 0x7991a9461d116765L,0x95addb2e9fd93c78L,0x05d2c037e92e5495L, + 0xcb145b189f03e5cfL,0x81ae48ca95aa1f72L,0x203f2702135a6e4fL, + 0x2bcef5a249b2a7d5L,0x0687a90002d7f2a3L,0x2f7d32286c6745b0L, + 0x3da8a87586507305L,0xbe38b8842e8dc58fL,0x6b48bf34dbf11185L, + 0x5af7fd0d97c08f91L } }, + /* 151 */ + { { 0x55f9b950f4a224a5L,0x41904574cc50273aL,0x34f81330643f1fd5L, + 0x996801bb0e50f783L,0x866d740389581712L,0xdb9a405da4091d36L, + 0xf1e379df16a46fe7L,0x8d04a93f83bf9168L,0xae4c833532b20bcaL, + 0x99d334b1f72a1c10L,0x8fbc9977d8195db4L,0xcaeb3dfffba14b5dL, + 0x60fef02276daf476L,0x4b948dfedb5b72f4L,0x5185c925b6dfb062L, + 0x27a9c3819609d4aeL }, + { 0x73c37346f12a93afL,0x028b707c5536634dL,0x8efa58d5498193d1L, + 0x4f83a5ccef21b69dL,0x05cbb0a3a788a0e2L,0x0103178165b13c98L, + 0xfea20e582b73784cL,0xdf9713a0e50361f2L,0x31449a0fd0cc22d9L, + 0x183752e77c5e2e1bL,0x6e44d6bdb67044cfL,0x012dde95733e177aL, + 0x68b4966908ee2c23L,0xd9bb05411f5f1949L,0x95182c716acd886fL, + 0x1c690694fbde9244L } }, + /* 152 */ + { { 0x5db67d173a880026L,0x89c4f0a0125d95f2L,0x290505513f6cb7a4L, + 0x3eb231d15cbbdca5L,0xf8cffc99972bcbd3L,0xcb4ef4d4ad55a03aL, + 0x944d47ca22867c2fL,0x96d885480ead1aa5L,0x76a57cf8cbc8b045L, + 0xdfe5844b005e55a0L,0x5e9e7e191d18a097L,0x957a26e852923c74L, + 0xd0867b797f5db339L,0x2553408e63bed0c8L,0x1596e5d5689ad23cL, + 0x7b8c13d6a504c339L }, + { 0x2fc43aad52fb6901L,0x1c0313f916ca253bL,0x1475830a515aadc6L, + 0xc93d19267f577dc2L,0x26e52e8ef723c0ddL,0x2f1e0eb83eb9f6daL, + 0x9979de82f180376dL,0x43e28ecbb0834939L,0x9a2d51dca39c38e7L, + 0x6e6063a9a8e3f6b5L,0x4cf1da3a4b9b3270L,0x6e5348a2d2f8915dL, + 0x5e75e3e050507912L,0xaeffce5720d383faL,0x1d6d53cc8fd2fb29L, + 0x0e3c3ef6696f4cd0L } }, + /* 153 */ + { { 0x3bc337c121ee1d83L,0x97e08f6d787b7788L,0xbf709fcc138fa4ceL, + 0xbaf77647a0348e58L,0x04f8babca55e672dL,0x0ed2919d7d5ec5ddL, + 0x8ce64bff33e99218L,0xac09fc5724b059afL,0x506831f9dc5e32baL, + 0x26a22677465af6a9L,0x3c5efe66c97f1ff8L,0x1515e0d6bc6087fdL, + 0xb1a39c5eaa8edc6bL,0x3dd816bb0e79ed29L,0x6cc13769bc3788b8L, + 0x463098e3c092a51cL }, + { 0x3a6408c7c8bd0fa7L,0xd1764311ce6bde49L,0xe315e108283ef7beL, + 0x8213cc7799b5d938L,0xaf7f158145a49a6bL,0xd00fdb0fe529e4d1L, + 0x55d38f77ce66c9d6L,0xb4f7ccc01bd4b952L,0x8d975b49af71f986L, + 0x12b59fcbcd64d00aL,0x1860e504a5a3bad7L,0x6d9760442b5c89f1L, + 0xfed0c6597a3e231fL,0x58114c33178cba92L,0xe2e74c066698e11eL, + 0x7f8fd093a348b85aL } }, + /* 154 */ + { { 0xf24592cac19428afL,0x192a1c813a308665L,0x42589812e30bbd7fL, + 0x10db0723836c6bb9L,0x9c7a41e9598e4987L,0x8aff179e6ead6f4bL, + 0x70f8f9b975862c44L,0x6b3b02376f21983eL,0x25d83e9b98e65152L, + 0x3b2d26a8d751218aL,0x9508281a9d6f1da6L,0x8df78d05a5a81f74L, + 0xd79ee559e4687471L,0x2060ca576787d8ccL,0x427a84ffa8476c95L, + 0x87b64c51e6435131L }, + { 0x87f46f654b30d3c4L,0xcdec4c5c23b4ef14L,0xb3b7476663ca4d68L, + 0x1df34269cf3fb56dL,0xd4f139c40fd7d46aL,0xa3b7c7c76a69a8bdL, + 0xee56b4c9cbadd7d2L,0xb28ff342ac942334L,0x0046fdfa786f1da3L, + 0xce5d149cb700c82eL,0xca30ef8150966597L,0x44a20609fcff4bddL, + 0x0f2f65e744925268L,0xe5b6552cd4021f38L,0x77ea9c2a042dbbd0L, + 0x8c95267cd9c062f5L } }, + /* 155 */ + { { 0x6655032e5fc1abb1L,0x2215af5412fe4743L,0xfd65756029f05ef5L, + 0xb0e73325dc191be9L,0x7ab3c65ec08639b0L,0x67507f511c3e6673L, + 0x638befc3c8615555L,0x5d0188cf42f0c4adL,0x843a301cd896186dL, + 0x045603f7b2c6741eL,0xf7545c0cfa3cd1d0L,0xf612affd4a40672eL, + 0x56197c9f45b9e8ddL,0xb453237d87922d74L,0xbf132e3a4b2d59bfL, + 0x8afa1b73b84a6a16L }, + { 0x6b3596eae793ac70L,0x4c94ef8eeef6dd10L,0x926b4fa270422e40L, + 0xc8c71dcee9e5d763L,0x352fcb70f512aadfL,0x1b7ba138a883975fL, + 0x57991390058c3b13L,0x9692092a97740fd1L,0x19ad945b160b0697L, + 0xbc63438810837ab2L,0x76ee11c4f174bb71L,0x6111bfc1ab1b80ebL, + 0xbc82bac870ec458aL,0xeee60127312d3325L,0xb4118b1ab240adc8L, + 0x672111912b5a093cL } }, + /* 156 */ + { { 0x91e99306f55cf9bfL,0x9b045308a46b96d9L,0xae3c1e1d9e7a65dfL, + 0x453cb151c731bcbbL,0x14be5227a4d58a61L,0x39dac92297c74cc2L, + 0x4d0f7a45822e00d6L,0xafeb1d51c62b03dfL,0xbb1dc3a4baa18b2dL, + 0x7f3c7178df2b74f0L,0xfcd328a6896b6a33L,0xe95ed4541dce055fL, + 0x97fbc76b6a4e2b87L,0xe5ec67f1fa59dce9L,0x052368accc0367c1L, + 0x7c86391654e4a3feL }, + { 0x55e94b5eca7388cfL,0x17cc0a60c0335d38L,0x9b69b78b616f85baL, + 0x705d02ef10122980L,0x565a6e801cfd0a79L,0xeb74a96d7d1ee352L, + 0x5c8832ed427b9dadL,0x96ea8528e6d5330fL,0x30d8862b18d24ee8L, + 0x9cd38ed59ff939f7L,0x690fc9a201060252L,0xc62d88b82303b3ffL, + 0xfc42d7a4dd52b469L,0x06f8dfa28cad2d93L,0x5023609060920438L, + 0x32582758fce855adL } }, + /* 157 */ + { { 0xeb20e45f359e8c60L,0xc71bb8a5364ca186L,0x02b15071dff8e110L, + 0x074e91d34c93e578L,0xc0326e00b829d0d8L,0x3c192258626a83faL, + 0x387a64d5fb29a09eL,0xcaaa3d34e5ac5c82L,0x8ed685e5ada2da29L, + 0x92720267eb29650eL,0xf7184b19763802f3L,0x23f5dd0edf6b1aeaL, + 0xbe1fa34725e6125dL,0xd6287f9d0c872a1aL,0x49aa93d2ac57c3afL, + 0x1a4e6a715bda7656L }, + { 0x1a126ede554d1267L,0x37f945331cd02b48L,0xd70af04cce31fb1dL, + 0xcf410b0b097dc012L,0x930e1d1736c7b6c5L,0x902fee41c6891085L, + 0x349ba4a779fb638fL,0xa16c5821acd6f8dfL,0xfb3b83c12e076aceL, + 0x6b8d033be501d14dL,0x0593d45220f2d2daL,0x3752526d99df1880L, + 0xca32351c9feb33a6L,0xd91343bc1f6ef456L,0xc74857db35b9dc8aL, + 0x856a7c9385b4e832L } }, + /* 158 */ + { { 0xa007d0020d0a5583L,0x2f1301ddeda4658aL,0x91c0796434d939beL, + 0xa0cb6780a70c0836L,0xc0b4df95be81e540L,0x6cbbcd345d4ac8b8L, + 0x57c52ed054756239L,0xcac2dca41805ceb6L,0x915ee6ab79344255L, + 0x366def3124c9a2a6L,0xbd3b962f8c12c674L,0xaab64f1b7dbb7c3bL, + 0x3c0e4553e22bb95bL,0x2408febac4c63b74L,0x3ca773122a4da631L, + 0x62889084c636da40L }, + { 0xa457fd538cb8d208L,0x7a8f8009543f06d4L,0xb66de154f2eff2abL, + 0xfddb28ebf72517e7L,0x0149fe66f9389d2cL,0x79e8773fd85b88ceL, + 0x452e090b0ba543f7L,0xdeb9b5cfb0b03fc0L,0x3113448a6c5ed77bL, + 0x3609f3cf8ffc0372L,0x2bc9c46d5c1b4c4aL,0xe66f3bf38fa59be9L, + 0x1396bf5fcdb02691L,0xf1ec59d4009f88f9L,0xc29034562ad9dfe3L, + 0x79d8122c5ada4d58L } }, + /* 159 */ + { { 0x14d4e4ceaa529507L,0x056a081474655d00L,0xc0d30a384f0fc474L, + 0x8a8203ea3443cb8eL,0x33c62fb097f1728dL,0x8a38dcfdb520ef52L, + 0xa0f90d5d7cac9d3eL,0x28a7b0bf873cea50L,0xd115ae3a6c6c41cbL, + 0xa35171daa13812c1L,0x25d4bba5624d507eL,0x91dad2897e98f42fL, + 0xffd6b1e996a41371L,0xd46c2125b69e5b77L,0xc7d2b42420c4f707L, + 0x2ab3af958142557aL }, + { 0x86ca074c6a5372a6L,0x728fb83e56292ba7L,0x745596dc77741cf5L, + 0x70b4cea1520ef49dL,0x1472fe3461e46472L,0xf4d6bd663fb8ac5dL, + 0x46e52cc9c10bc071L,0x28794efe371a3461L,0xa4850718276fe877L, + 0xedad57739bef5ab4L,0x24c2d9ff3f15c815L,0x188950e58f8395c3L, + 0xbae4099680b6a855L,0x4f53e22c8a8803e1L,0xaf233f61039d25eeL, + 0x07db2c35250409caL } }, + /* 160 */ + { { 0xc7f3b8db037d4703L,0xe83708dfc5f488b9L,0x1fba830f8471d402L, + 0xa55ee8d25a2faae9L,0xc2e5bf105404fc1eL,0x647d5027aa2d5651L, + 0x37a53c0c7ebaf5f9L,0x7adf0bb295b30abfL,0x5a62e1fed64c93baL, + 0x7ffc18c0e2ef4a78L,0x139dd9d94d2cd04fL,0x253fbab75ea0af02L, + 0x7c8100ea0fef9acfL,0x74c5384dc8615aa7L,0xcb28682d9fe52069L, + 0x08b6ca8fcf7dd759L }, + { 0xe04e5bea036c3b5aL,0x387261027f9f2b4bL,0xa9fca57029797c0fL, + 0x1656180b82879ea3L,0x153389bb607f0ddfL,0x99a1223c67b0e087L, + 0x0d1808ec9d897fc7L,0x9470711a916edf19L,0xf8f52f2b07217118L, + 0x5d8b29ffd18888b6L,0xef1e22c54cc6f900L,0xc4036165eb24877fL, + 0xfda9523335479525L,0xd622a4216861468aL,0x5d043b0774faba08L, + 0x2c337b020d31a7d2L } }, + /* 161 */ + { { 0x7b2305bcea22fa65L,0xbe183ef4d159f63aL,0x3473d87d3f35923fL, + 0xb27fb306c11d7753L,0x702e7e6b2a054cffL,0x3ce9f97caf185619L, + 0x835502434e7d51c5L,0xa63e3d82f356ac5bL,0x867b7caad7645131L, + 0xee85e6afa671fc9dL,0x3b985ede2b07cd77L,0x07d598b0ffda5193L, + 0xb10eca39a942dc36L,0x17f3dcee506218a9L,0x3d94e8d106b7d5caL, + 0x509b2634ed8831c9L }, + { 0xb1b9414e48caed54L,0x77a78c6ccbf51e97L,0xa4688c8d4de9b258L, + 0x0024137c91ee3d78L,0xa68f9234e30ee64cL,0x573255bc88190d78L, + 0x41e8e05fba80690bL,0x50038d84ec354f4cL,0xb18f02d6dfa52816L, + 0xc47f9007ccb63fdaL,0x29d480fbe98ae455L,0x4ac45d225d0e319dL, + 0xd06f3575026db719L,0x733b9e202c3587b9L,0x224839922c317727L, + 0x1592d5a754bb8752L } }, + /* 162 */ + { { 0x5778d9a2cf7453f0L,0xaffb899aed83c1f0L,0xae6506d3e0a82ba7L, + 0x32c84e1aea3d5081L,0x9ad528c0810aa38bL,0xb1fdb020bd37d041L, + 0x78d6cbe1d06ce41fL,0xd287f0f02e74b7f6L,0xf5cd2575c43bb022L, + 0x6d28f2f3f81a71b3L,0xe65bb1f5c633e7f4L,0x32e5fc1cc4fc580eL, + 0xcd55539fbb7b07a5L,0xb5a94471c3caaf3aL,0xb958bdf44cc22d2dL, + 0x1614bdbd77a2777cL }, + { 0x4c1f0230ed0ab04dL,0xae347b006e2082eaL,0x9f10bc63c42c5b5fL, + 0xb0539e6fde019935L,0xd89bd4e765dd0825L,0x92260fefbbceda16L, + 0x8aaa755ce62aca32L,0xed762fa95ec82c5fL,0x99e64c0118650768L, + 0x57dd6245c92e348cL,0x0db88a7731ea6d68L,0xef0012ab07b44736L, + 0xb9356b94171d70feL,0xe68b062803f891b0L,0x3a54a53ab79c20a2L, + 0x489656c7b00b0728L } }, + /* 163 */ + { { 0xe43649ba71353c25L,0x517f27a113f67e24L,0x10bd333a1c1eb9e3L, + 0x94e1c05c78e29bf9L,0x84fe7d974743f15dL,0x9c87490890da2df0L, + 0x82403fa753673be1L,0x7ebf5db41baea1b1L,0xcfe0ae3524180eadL, + 0x1d15873fc2f50c3fL,0x16851ad670661cd9L,0x802968d9a51e8c2cL, + 0xe7d1a9cde0161099L,0x2b153c89a8a7ea56L,0x6d41b78906e3c498L, + 0x082bb2e9d6769dcbL }, + { 0x6180ef46c4d6615fL,0xfc629dc101b9829cL,0xde222ec00fb264caL, + 0xc5457e0610ecc2c4L,0x95ce599f1eea2c4dL,0x0433fa728f9c5b2cL, + 0xee035462cd6310f9L,0x84c57c3bce2e2253L,0x6c8ec31a96d87e44L, + 0x30bfe393a452c5a7L,0xc592b140a047b235L,0x7bd8be18c018545eL, + 0x794e01075c178c46L,0x484719462e23005bL,0x2665e237622a54f3L, + 0x36451a46901c9042L } }, + /* 164 */ + { { 0x17802d1819893e71L,0xa1765d8b539a2082L,0xfc6aea012302ecfcL, + 0x8d4cf51b365bf59dL,0x87741d720d232a80L,0xac343eb318e80427L, + 0x553ecb2fe74739ecL,0xaeca79a81a8b07caL,0x089ff32256f4ab3aL, + 0x5e95d7293fa1d1f7L,0x260569aef62a9a16L,0x5e776232aa08ddc2L, + 0x93fabec31b7bb54aL,0x48a20956743d56e7L,0x749cdb12eb0ebeffL, + 0x705307a469b8fcf1L }, + { 0x7a8e4c04e488310bL,0x12726e325325cd7bL,0x5d0fd8b04983efacL, + 0x796e552c02ddb913L,0x0eeca3f777b9685cL,0x9b766e89b15f24a3L, + 0x7c2736d648efc979L,0x3d619685a8021c6cL,0xfe33e278a0b2f1eaL, + 0x95c69879b676d6b0L,0xa07473191af4e0beL,0xa2fab5f136c4ee55L, + 0x6938b8ff59e5f3b9L,0x1e114da439cafe6eL,0xc9595ec36a6ad120L, + 0x80f79bd057e62aecL } }, + /* 165 */ + { { 0x3cef42a760af09b3L,0x3c016ebd933dfe14L,0x720cf1e0ed85eaa8L, + 0xd4f5e99fceaa3bc9L,0x7216b9d2b7106f97L,0x65f34c36c9668ad2L, + 0xa8fb82bc5b0c651fL,0x20f42f1cf2fda4deL,0xeb31ab2cd21f659eL, + 0xb7a776c7a13d1618L,0xec44102238662be5L,0xc825da70cad08e0bL, + 0x99299079022c0180L,0x7623bda02aef9ffdL,0xde84f4f3f5c58b50L, + 0x5f5a5da4d824ff19L }, + { 0x5737257e7e8311dcL,0xdef94f51466cf136L,0xa73e1645b05ca21aL, + 0x38ea9b3c02e4ab37L,0x7760eac98579165bL,0xdffdd047c24b01a4L, + 0x188d4fd13fb95584L,0xfaac38b825548bdaL,0x1a79a6f059e9dcacL, + 0x983f720f09a2700fL,0x8cbba554fb8a7e48L,0x38a1996847a1fad5L, + 0x118565475abd6b5eL,0x75113d31f3716ec2L,0x1391e7814212907bL, + 0x5319c8010dc15889L } }, + /* 166 */ + { { 0x2320136e6b61c3afL,0x1d40f2de07b4bb68L,0x651dee7f380c97f0L, + 0xa978ba706a8c313aL,0x22c587d62011ca10L,0x48bba218ab1f445bL, + 0x8c5eaf07e50444e6L,0x5549f02a442fccf9L,0x2564746f3d80493dL, + 0x42d24f6179c04591L,0x1600fa18abdc8887L,0x5cb8600aded38f8fL, + 0xa4bf9b90923aeb46L,0xd63fee351e1c578aL,0xf3c9c5acebb9ea14L, + 0x3d13314df11a4ff0L }, + { 0xe5cc662db4513d1eL,0xde78a8c5d55952bdL,0xe8a37a3fe7f86d0aL, + 0xca2d12a47a04f0c5L,0x4c6696e42e25d06cL,0x52614698b2136071L, + 0xf4d2701b89f6e1cbL,0xaafd617780efd95eL,0xe6d73ac4c5bb6907L, + 0x49e874ac420db35aL,0x11631de4f2751fa0L,0xb29f7336a1fa2eddL, + 0x4c406864b7fd794dL,0x73cb21d3e22f92a6L,0xeae904e62043cc76L, + 0x67f28a9fb322c6adL } }, + /* 167 */ + { { 0x7c17b258ca148ab5L,0xb9a1976fb3c60051L,0xea260698c8f28df9L, + 0x87b2cc74e8d45017L,0x372573290578a422L,0x81d5ee2517bec732L, + 0xd7411fcf1d48bbc4L,0x46217e6b487f5cfeL,0xcb007ac541eb8e1bL, + 0xc41c57a6e05a00c8L,0x1f954d2bd2f9fa99L,0x370bd5db40941cadL, + 0xe487879c3829509dL,0x4c1375525ceca5eeL,0xe8ef7fa4fd3efb9eL, + 0x5ff091741bd1bdb2L }, + { 0x791912a4579c6632L,0xbb19a44fb8a20815L,0xf4f97b84535639d3L, + 0xe57e2bcbbc3c9bceL,0x122b3f2bf19e6410L,0x1f0189da1357d9adL, + 0x675573bb79e5ff66L,0x444e5c98ef2f3c4cL,0xd6f61e2004d10731L, + 0x0dfa366fac75d635L,0x9fc47c862c854f23L,0xc04ae43e0ad0850bL, + 0x5ce94f642f720c32L,0x67efae65a753bc9dL,0xc27d30d3b0373a63L, + 0x6681013a29721646L } }, + /* 168 */ + { { 0x1385d913e84509dfL,0xe978beddcf339376L,0x2df425d33423a148L, + 0x43fa0ae3ee8cb579L,0xf015369d31c4553cL,0x05cf08bbdfbf1d48L, + 0xadff4be69444244aL,0x01635f81a35dda33L,0x085c8949e76fab7cL, + 0x4bd7fcde16737783L,0xfd8cb52ca254f8d2L,0x62168a66413ec985L, + 0xf2db97417a9026ccL,0x3962ee5650e1e1b7L,0xbee0a346d3beffdeL, + 0x3b35b72f0bdfab1fL }, + { 0xbff8de9f535c3749L,0x23c1f20f8add9c48L,0xa975b37bc8f8f663L, + 0x2529e475e8f3ae49L,0xc32f10d51d5e2628L,0x5ac0d29767862f1dL, + 0x13c79338854cbe36L,0x48f004ef4b67e462L,0xfa37a150e5d10ee1L, + 0x4974778dd28288a0L,0x96830a66cfb73f4dL,0x9f44401307804952L, + 0x8233c7099760b694L,0x8340cca525b75c99L,0x3f62e40bc771f99cL, + 0x47d0a1ebcd95c685L } }, + /* 169 */ + { { 0x266f4fff652811f1L,0xeaacaa9362ef3002L,0x6c387a5550cba0caL, + 0xa350142a007f5467L,0xc7fd102a202f2673L,0x5daee57033dc6e65L, + 0x60682ec3064a63d9L,0x46cf0bb0462b251eL,0x0e030ca55da936e7L, + 0xc87a60f2434265b5L,0x9637b2bb69b4e8f5L,0x601fb58c7ad7770aL, + 0x1f2147f6ed3a15a6L,0x05b47d5e2995e961L,0xcb0ca9b383213a16L, + 0x8f4b614a4995a85cL }, + { 0x5aa8ec194b4eb3c1L,0x8c549ac420323a70L,0x00d493224f6cc6aaL, + 0x0e53b9bb45f9a5a3L,0xe46ef1100897abbbL,0xfe873e57d7acd7d0L, + 0x7cfccfe50f7cb588L,0x0ea53d65c85557d1L,0xfdd9eb447288f2e2L, + 0xab2dedfac0eb68a8L,0x5822147008603a0cL,0x6946468900feb06cL, + 0x804cf5bf25e5caacL,0xd85598589fc91ae9L,0xed9378b173c45eaeL, + 0x8f942d02524c9801L } }, + /* 170 */ + { { 0x1f1ec3028e845808L,0xc302bffab77abfc5L,0x26afd4b9f8d97dc7L, + 0x3d3a83c43aac594bL,0xe3b74bd1674d94dcL,0x4464b737caa5911cL, + 0x62925773871c2cd2L,0x419f24853b4440feL,0xdda6a0f3e052ad7dL, + 0x645280d6846c86c0L,0xa25689faf8324f42L,0xc74ad1e807cf117aL, + 0x5626dea08ddc9db7L,0x52620373966fc85dL,0xe0ad57c3f3b1eb53L, + 0x38300252949c1acbL }, + { 0xa0ef5a405e744723L,0xdb5bcf751ae08481L,0xabfad8ccfec1f76fL, + 0xfba5d831fab37fc6L,0xbe39e248c8fedb78L,0xa5cfad5fad93f310L, + 0x747fdb1e913d5c24L,0x052a47c94518b7f5L,0x9e208d6c7cfb4327L, + 0xb135cb9c70e538beL,0x363527595bb17916L,0xa2c078805b3106c7L, + 0xd2d42a06c209bb06L,0xb525b471d3c504adL,0xc9f4b368822ce034L, + 0x15f18796eb4185a5L } }, + /* 171 */ + { { 0x094dea060aee4684L,0x42b21f067cdbdbc8L,0xa439e149b1931319L, + 0xea4bdd4181a7dba6L,0xc62137063c2ae80fL,0xb58b096712823dc2L, + 0x7443d515832611b1L,0x2e16f83113c20384L,0x0ce204d62bd992d2L, + 0x499dbcd6f419388bL,0x492ded1d1d3778c7L,0x9d5bd74fc5ddae73L, + 0xd4813d52994b6259L,0x191d9cf60e86ca68L,0x562179eaf3e9c2acL, + 0x6146f1f39fee1238L }, + { 0xbd06d33e078e2aa6L,0x693af7f79dee9265L,0xd56e0f81daa40e84L, + 0x05fbbb889b9a407eL,0xdcf44adcede99519L,0x7f71f8d3092dba39L, + 0x675b5da54231774bL,0x7456a251a5f605ebL,0x9031d4af87a39a9eL, + 0xdb43000605b474bdL,0xbda5dbf2b665aa91L,0x5d1a3df56631eeb4L, + 0x028149ef62377c58L,0x2e1af4e9685d0bffL,0xe0ea087582a465deL, + 0x95543f9e06bd0050L } }, + /* 172 */ + { { 0xf7cbc6f485d7c6efL,0xcad8084d63b1bc24L,0xdf90ce88bf8cba62L, + 0x98e4b686b455c192L,0x6146b8d5774fc6edL,0x70e2389e7ae20077L, + 0x5241c47961c22529L,0x7d2215103884e5f5L,0xd6d20ce217e28273L, + 0xe3119f514f2674f8L,0x8545905570c011dbL,0xdfab75d9fcfb760eL, + 0x9546362a9e8c2a19L,0x4b6d3f8a4a7d4b27L,0xa5c87104ee5d698cL, + 0x6db434782ba296ffL }, + { 0x064864935c3f0d95L,0x8917db824e748895L,0xf73fdf626b2f3e44L, + 0xc60edc542b7f574bL,0xbe1c09a2af732723L,0x7d34669d7cad114cL, + 0x9646600a321aaff9L,0xb94e2bbaed0cd61cL,0x866e1a41dec4750eL, + 0xa1be990db1a89f58L,0xc39e4d6cf2759693L,0x11cfb780c0e0dddfL, + 0xf0afcd7fd99c8a41L,0xcebffadb6e1c3050L,0x4f3981b096d2c6e4L, + 0x07a791e72ae27a94L } }, + /* 173 */ + { { 0xe70e90471e9f0300L,0xe0253ad9bccdf904L,0x51c0289dff053078L, + 0xf1ef092eae893462L,0x2c90a91aa4846845L,0x1946eda0f1dad4b4L, + 0xf07650f333df67b2L,0xc6e988db0b15a014L,0x72e0c66eb542f0f9L, + 0x5d4b6311e0c0378fL,0x548badaaae86950dL,0x6801638db35f1c8fL, + 0x129e3216944d1ad4L,0x9951bac840471d32L,0x03cc29f385e94ddeL, + 0x6d6acc2e4543ecacL }, + { 0xeb999e9557b2d299L,0x3a2bcd9be3d721cdL,0x2e60384fbb4cb444L, + 0xae177709dc060faaL,0x74f0e6d38c987cdeL,0x9a237cf81076fbedL, + 0x69af15137983fbffL,0x6c3f7a1d323f9584L,0x3e21cacf6db64398L, + 0x7cd8134f96703d92L,0x0755898fb8393f76L,0x1b5b28bc2e825222L, + 0xb78799c17924aa7cL,0x1db378f281427a8aL,0xd5a451b1ff289492L, + 0x79d182123d3c46eeL } }, + /* 174 */ + { { 0x1a3edff9109d5589L,0xded52eb4029b4499L,0x13eb9d30b4b54adfL, + 0x4f9214c1a27bff67L,0x4c817ee767f0f460L,0xbadf8d83c3a50e28L, + 0xc5dc03c994026237L,0x5f29581b966647c1L,0x10b6a0898a0687f3L, + 0xae787cec31634517L,0x2001dba562e75188L,0x55d4e1a745e2c3fbL, + 0xbfcacdebb67d3395L,0xa1a0af9cbc6842eeL,0x50590a2b3e88580bL, + 0x73104491a784cdc8L }, + { 0x44ca2cdf2648d676L,0x9a85eca54f1b12b1L,0x1b9dac942980e1ebL, + 0xf30d37091ac8aa89L,0x73072ab7c719e195L,0xba518c822f703797L, + 0xac090e14ac0067f6L,0x0e6cfc708dcd2927L,0x4f5889e221e7da63L, + 0xb4aaa40b8371c7c6L,0x1f9dabe28f7878c9L,0xf78aed6bd84caf3fL, + 0x3c39dd079e0e1d92L,0x680be5fb122424dcL,0xf41b214d0bdc0099L, + 0x6a8f8fc95180c54fL } }, + /* 175 */ + { { 0x62a1ed6353235132L,0x1db233f159dba88bL,0x85625452291efdd8L, + 0xc7505297b25111aeL,0xb5921af91d701bd8L,0xb4d05d729774f45dL, + 0x6e3d4c5ef18e73ffL,0x897d985f899b3038L,0x8a9c30fbc89b1558L, + 0x3c92d1a34d13181cL,0x292e86ba2223320eL,0xcf2454c201ceed02L, + 0x27a45f74583f309fL,0x75a6102cad0fd1a3L,0xdb4f45d2cb9c7538L, + 0x4752d8c1db283fd7L }, + { 0x514d6cead5dff4d5L,0x74cd5fdb45a827f4L,0x1070a60c4fc7135eL, + 0xdec0bb781be5778eL,0x271e12cd58dc6b08L,0xb765089b54bc2496L, + 0x6ddf2c63619098acL,0xfd6ebac667528832L,0xeaa2d025c2508af1L, + 0x13c2cda84dcfc1f0L,0x1c7836a845510be0L,0x3904688d1a886801L, + 0x643132aaafaf2545L,0x496855772830a88dL,0x569491ca8744b470L, + 0x3a6518f375fb8552L } }, + /* 176 */ + { { 0xaaa8ed50224042a0L,0x6cb4e3b02452f1e6L,0xedca5f4c768211d8L, + 0x4e0fe3f9ef4d5d3fL,0x33a8e2a4522d46e5L,0x5998e21ff1446775L, + 0x1496c50ef592d01bL,0x69104c2f83a67739L,0x28670bcb472bbf00L, + 0x8ea883b2503177bdL,0xc5d8bc057d2712a2L,0x41ef9317b439c994L, + 0x9801d3a8dcda1affL,0xd686eeb57038f6fbL,0xe80c5cd0fbfbf820L, + 0x540ac363edc25817L }, + { 0xa71969a9fe7f43dfL,0xe66538082c1b9e4cL,0xad9677d8859c2917L, + 0xbaca954596aa4404L,0x0e9d855fff1297daL,0x1f61897b22aea7deL, + 0x96edccfd36f13f8eL,0x627d307016e200dfL,0x729f0736c98988a4L, + 0x95e25e6097f231d2L,0xaf7f221bf6048752L,0xd66826094019b299L, + 0x1d99de0926b4b1d9L,0xec47cf661acdd7a3L,0x4de9f2b36ebe15e9L, + 0x17db32ecfa16974fL } }, + /* 177 */ + { { 0x75ef69196cf40599L,0x7ea10dfb00c020eaL,0x3da5ae7bfcaaf679L, + 0x0d663ca388ddd678L,0x5a21f8fe255bcfcdL,0xe9c3f538e344bc7eL, + 0x35f62b1d548e0632L,0x654f242543c6e64dL,0xc755a7a626993627L, + 0xa3b7c5f7b0f41324L,0x05697f793a2180f3L,0x6cf85fb11e81675bL, + 0x6d3cdb35e53428f5L,0xe3aa159152d28b02L,0xa8470255f7a3fb78L, + 0x460bd01ba194445dL }, + { 0xbc34dc23c24d8077L,0x82f4b5804c720d2cL,0xa29da9116f5d1ffeL, + 0x578af52092783ce2L,0xe29f51abb5904af3L,0x46c570d7f7aa1190L, + 0x4a522fba571bddf0L,0xbf4e2a06ae89bb51L,0x799b35cc59f3444dL, + 0xc302836726cc2557L,0x94a4e985afcec177L,0xadaf7dcb7c36cbd0L, + 0xed31b78775d39077L,0x52d6904f2d3e24bcL,0xc5ca26691f95421bL, + 0x7d342c3c1734878dL } }, + /* 178 */ + { { 0xe5cf2c0a11fd127fL,0x66d36bb8119e4c5eL,0x621ab2526ef56ac3L, + 0x30cfeaeee5430675L,0x2ede27d2ac3e9619L,0x6413513af8fce671L, + 0x6159c61b075f4c3dL,0xd447efe959069d98L,0xaf8d6f68ea76aea9L, + 0xac5dc61b0f5bd164L,0xdbab446e1e88bb98L,0x618b8b161ba92320L, + 0xa0eafb3c78989865L,0x0c7abcc2c08b7e82L,0x10f09b6e20d160bbL, + 0x5be0afa68e4c63a7L }, + { 0x82ab6d381bbbf49cL,0x3e09ce498c0703feL,0xeca58b5de10f4263L, + 0xd9cc6581da5a4532L,0x07e18876f618f7b7L,0x0419a5e3250f7fe7L, + 0xbb1a9e90de6b86beL,0x584a7deb37359169L,0x38eb34895149db2cL, + 0x14546a33b0ebabb8L,0x0067f0b0c2f88a92L,0xbde0dfe70a2db019L, + 0xba51b06cc63e6f3eL,0xa19127b9e9206fadL,0xe4eb5e87fe80dc0aL, + 0x1e6fccf5d4de30aeL } }, + /* 179 */ + { { 0xb57dff66aa8ac924L,0x06e9ad31c298b3e8L,0xd140e32965fb080cL, + 0x7dab211d1d95c93fL,0x6d68d8428a180caaL,0x1a929408a20ded69L, + 0xa815175338df461fL,0xff5604ae60eae932L,0x901b9e497dae4c0bL, + 0x4573a97fde262e89L,0xed69d9a4f1084983L,0x8ffa022f64724f1dL, + 0xd5f1c2e4ea85a15fL,0x4c626ce901453794L,0x80440cd6bf0907ddL, + 0x4522d4615ddaa837L }, + { 0x8895f079ebfbe7c5L,0x30ea1ded84ef3446L,0x716a9eb6d4a1ab96L, + 0x1a4a5d2250a30c68L,0x5a16631c0043bbaaL,0xbd1075025010e5f5L, + 0xbffe3e9d3d8c0556L,0x31b30b1807772419L,0x90ff7ef084b82297L, + 0x00c37d75f21a18c3L,0x18d0a635565bb8f8L,0xbac1da2a45e3bcebL, + 0x1c38e90c23f0b08dL,0xf1ba1aa25fbc5ac5L,0x09d5256bdda71fc6L, + 0x346501a96d7e40baL } }, + /* 180 */ + { { 0x86be448ccc2b0f1dL,0xe3eb45c9ac4c3703L,0x5387f65d9fc96bbfL, + 0xcef3c4e95ae27fdaL,0xa008f7761bc18089L,0xf374a08422ca18a1L, + 0xee88284253b73371L,0xcb6fc6d87cc09354L,0x8489ec1b61496d6bL, + 0xa92c29b949e325c4L,0x15c6ca527bdec166L,0x95444eeedcea2813L, + 0x34683eb33a21154fL,0x8fb26f98d39061cfL,0xc3b08aa806c940bbL, + 0x7c1d42cfe554c96dL }, + { 0x766e703fdc110aa7L,0xab7b79d7f362e378L,0xd259c75d5aadca3cL, + 0x2a6eca7960be3373L,0xf4744a4b06c4e8ffL,0xb2842ccef3b705bfL, + 0x1a3af5aaae304b53L,0x7bbfa2011b2d31b8L,0xc4ba6eba4bee88d9L, + 0x2d3565ce565cb839L,0x24808696daf7ece8L,0x2c7ccce7e6959745L, + 0xefd6eb3ce94f9837L,0x0a33b4cf3811a326L,0x14203f43fffa93a6L, + 0x031e982873c31d90L } }, + /* 181 */ + { { 0x4fefecfc765a17ffL,0xa09f3888d1290a65L,0xbf265c46938da038L, + 0x4bb6145da169ad46L,0x33cf821423a62fe8L,0x562df571abc860a5L, + 0xbf2a90fa815c38c4L,0x45ba1d6e17eda875L,0x799d881a946fa5e1L, + 0x6c1be784b90f5a3bL,0x0910a37cb10ff52aL,0xc38c1fe4a4f4fd36L, + 0xc3180fc58e2d3ba0L,0x3e2ff050b17a6187L,0x3a00059b943a35c2L, + 0x494d3645a28cc51cL }, + { 0x398426b64ba021f8L,0xd14c9083796deb6cL,0x6d2e53957e36c762L, + 0x8f556eca751cf216L,0xdaca1e0019b24a19L,0x47887da44b20c2aeL, + 0x93ed4ccdff41a733L,0x8d717c445c7c0cd7L,0xcc48634a91bf7009L, + 0xa1f146f93b59bbafL,0xdd38bb39e5624f15L,0x96d41aad303f8443L, + 0x6b670f034bf104fcL,0x0503f9ed29706582L,0x768e1f47b34200f5L, + 0x3cfdcc5ebbd4c6f3L } }, + /* 182 */ + { { 0x536c2a86b523e13dL,0x1014a4582920d0a0L,0x3d52b478e7571296L, + 0x057460667eb51beaL,0x709f786187b0e919L,0x028aed88686888e8L, + 0x79a809d7d94afcd4L,0x50c6032fe2129af3L,0x75e4be72983c4082L, + 0x98331bbb7ab3be8eL,0xd31a032cb618c728L,0x36dd85a13f59c4a4L, + 0xdbece345ed4f61e2L,0xba7aaccd1e571715L,0x138c58da64a1ebd7L, + 0x89296d0f3d1aeea1L }, + { 0xb165288fcca82c97L,0x26c6c12d1427e8dcL,0x66a94f074c3edda9L, + 0x94600e1eeaa01ebeL,0x14abce7c30f5e86dL,0x741d7020cb456a31L, + 0xab05aa13279f42c2L,0x70b60fafd4238468L,0xa18efec1318d39e6L, + 0xeb07f1ac8920b318L,0x01e3cba8d8399e03L,0x65f8932e3c81a301L, + 0xae8bca7dccc667d8L,0xcee1ae79a268607cL,0x3182e64ccac0a12cL, + 0x9233a2f72b1a4c54L } }, + /* 183 */ + { { 0x717e8df60acbee17L,0x0f0959c25c24fcdcL,0x46f09887e54ffcb0L, + 0xb993decad285116bL,0x0bfaa4f8bba1fa51L,0x9c9249efd0f2183eL, + 0xf93cb35896847779L,0x284bfb7f2322d421L,0x40cc709ad42af009L, + 0xc69f22749bb1d615L,0x76f50b3a717c3c6aL,0x8b21e985bb9c5eebL, + 0x58fb19aea4783b5fL,0x04c86b9b52e1c3e7L,0xaca59092f2971ac8L, + 0x2bb26a6921ed8291L }, + { 0x98a3443515f81416L,0x086e72e7aaff5bb4L,0x3d1f64de0317261cL, + 0x31c0786c5c0a1cfeL,0x542ea4d8b3683401L,0x2f77273a1a39b4cdL, + 0x14fe7ee1cbef27f1L,0xee7fc09e16bb27dcL,0xc0dccc17410e5dc7L, + 0xa34667421943b3ddL,0x92934b603f31c1b7L,0x0186ded9c22c1070L, + 0xa37ee8ba799f966bL,0x0f3bfcb4249b0893L,0xbae614472e92d4deL, + 0x937cb3f8e196eb08L } }, + /* 184 */ + { { 0x57c0e77c16fbfdceL,0xea034cc9c98d4cc0L,0xe7606d7242572d20L, + 0x9861b55c0019a83cL,0x80ba2803f1597162L,0x0f4141dd05a0fd7bL, + 0x8865913b4b0daaa2L,0xe6685746aa3848ecL,0x16d15a5a3e0485d2L, + 0x81c0c7743b6905ddL,0xcec31b7d818af2baL,0x80d8f194d2b74b78L, + 0xca659db2543e2f28L,0x31b83a7d9fb07c1cL,0x86537fdc1f1048c0L, + 0x4d57bb0778586a11L }, + { 0xbc4b768a53b396b6L,0xbc8b24c493b51dacL,0x33e511eba30ae1b3L, + 0x893bbd95945147c5L,0x6cc86031179fe3ceL,0x34b0a1673f920bd4L, + 0xb32912eb6b256160L,0xbc69a2a49d168d83L,0xb4949e7aef0dd128L, + 0x2613419a872699e1L,0x06c58477bf21376bL,0xe55b1909a4f97147L, + 0x63d6eb757b9b745fL,0xb5365b2908df3c85L,0x0e257e4355fcfae3L, + 0x1067c118979f2aa8L } }, + /* 185 */ + { { 0xc845508432bf8883L,0x4755286a6fd06667L,0xd70b0f8f77c2335dL, + 0x678e60da2f4a2c94L,0xa468d8acd118acf5L,0xce93830bbf5b90d9L, + 0xea4b1c74ed4e9104L,0xac67316d27776ea4L,0xb98ad75c361bab12L, + 0xc323d48299122451L,0x26440220530a43aeL,0x3a44532e3292d5a5L, + 0xdb48694b5fecf1bcL,0xe4e0516ec667b8b8L,0xb3aa595fa4306adeL, + 0x7e4f7091f34e9725L }, + { 0x3f3816e9b7f70919L,0x765216ed16b003f5L,0x46c6cff4778c99e5L, + 0xe6a5abe830a51810L,0xef6f49e645e728dbL,0x6fdd73eacaccefd6L, + 0xec394e6f8c37f3f7L,0x73320802b6407fc3L,0x988e8f7a96625cbdL, + 0x832923637cabfb00L,0x258ba9df407f359aL,0xff01aee5ccbfae50L, + 0xfbeaeacefe251813L,0x9c69f16183f1cba1L,0x512c58ad9eadcdb5L, + 0x2ae49cd46ccce8bdL } }, + /* 186 */ + { { 0x1239b0e3c40849f2L,0x5136a4cda441098cL,0x61535a99e547f649L, + 0x92e4bdc47a9bbac6L,0x195a164653547af6L,0x85ecb3198b47a74aL, + 0x278553fc9de6a2b2L,0x471c038a0e2ba52dL,0x12ba1b8835bcba93L, + 0xd4bf50da6f31eca2L,0xd146e3f6802b32c6L,0x0c9c01313c64c8c4L, + 0xad30f12deed21297L,0x9b75bffb9c68530fL,0x23c0ad3e8918de51L, + 0x180e9d52a73771b7L }, + { 0xc316542f29ab77b0L,0xdd411d9cf7aee628L,0x044c0685353c2f40L, + 0x638dc7e44b0ae4cfL,0xa092418595fc266fL,0x639da671fd2feb7dL, + 0x56858ed55ea39798L,0x7a694f3158f3832aL,0xa94233c6d316d831L, + 0x2fcacb2630a35a7bL,0xfef8f7ddf1ff713bL,0x8b9b452559eee2f3L, + 0xd1b4f91b156d064aL,0x177866c22f5cfcfcL,0x12bc25663777eb41L, + 0x21ca6f3cd8ab85b4L } }, + /* 187 */ + { { 0x0e162b13a3e66635L,0x1ef20a2b2a9f76afL,0xab473a3046db3356L, + 0x0840bd777802bb8dL,0x5b6baf5ea699b44cL,0xc6e119001b2207f1L, + 0xe5de16a9790b0105L,0x22b12f15db67f004L,0x185fad458a025d25L, + 0xbccf6953df0a1142L,0x4c42129bf45034c0L,0x0f7404001c277bffL, + 0x6e440b4c280a9e18L,0x767de8f5842aa2b4L,0x3de20ab805e8d94fL, + 0x5aff585920227635L }, + { 0x805acd20a8458e40L,0x5a5557d8149732bdL,0xc70741315f1ca72dL, + 0x7f2e269c952b5323L,0x5c5925566494fadfL,0x153b7acd1a7d2666L, + 0xa6df063d86fe2865L,0x1e91db1357d53b6bL,0x9195bb89e93ead01L, + 0x3d71e1af2963bfe6L,0xfab2b9c288278886L,0x778366923b859b6fL, + 0x6e695174f7029dd1L,0xc79878767b984561L,0x64fb4f1d5907d849L, + 0x3eab7e1c88d8a977L } }, + /* 188 */ + { { 0xc73a94b652e5718bL,0xe3aefa54f4cee1e9L,0x654e9e63553eedeaL, + 0xf2541e1b5f3aca1aL,0xd71294890d083316L,0x7965af63fb7f950eL, + 0xd8fc9e0dc74e3e4aL,0xb4ee48d2eaf79ebcL,0xa458a86a8b7787e6L, + 0xd8c7621ff7cceaf0L,0x8228eeffdf67980dL,0x210d4742f9106727L, + 0x91f63501b07e3629L,0x441761c67971e29dL,0xc0ccc65f03a3b8a5L, + 0x3491da4f38e09544L }, + { 0x6706d046cb062eaeL,0xee7db7355d08776dL,0x80de8052292315d2L, + 0x40785662c402bbdbL,0x5f93525c26ed3337L,0x6cea14d67d568ed3L, + 0x916a118966888b1eL,0x0fbd52055dc71675L,0x833d1077e4575df2L, + 0x4e93100aec092335L,0x2f9e1d016cd85389L,0xeebd372543226368L, + 0x401d172b1ba4cfd7L,0x377dab9d574c5838L,0xaeaa695880d517deL, + 0x0c843dfd6ad15a18L } }, + /* 189 */ + { { 0x455811ffc9373300L,0x1c39332a99fdc300L,0xe19bb81c353cb655L, + 0x774b924a96a83d27L,0xcbfc8fcbb2ee3f1aL,0xaf278ec4010d56c7L, + 0x6fde682fe0abaf79L,0x7566d0727339aebfL,0xbd35ad5d71205db6L, + 0xb5bbe6947051c9d0L,0x577db480d3a3067cL,0x2c70ff54572d7530L, + 0xe8615aece06d853dL,0x71999ccb05abfb5dL,0xeeefc96bea0a8ed7L, + 0x2dcc469d35f6df69L }, + { 0xcca6cd06c65f0e77L,0xddcc7980bd71b14aL,0xb6221f8b3c93cc00L, + 0xddfcd5b3ae8cbf57L,0xbc92973f76f8e63fL,0xe9848a3406e132b7L, + 0x4cc59a03d51ec9e2L,0x9c9d32bb3a33081aL,0x0012105280e8466bL, + 0xc2b0032a1bbe7295L,0xdbfc657224938448L,0xe972a0ceb6bba0ffL, + 0xf60c0a4fc0a94802L,0xf62c41cc599d8bc7L,0x820c96ee312da0b8L, + 0x5a1a65dbcdbdf9fcL } }, + /* 190 */ + { { 0xbfba691a42485684L,0x613116b929c470c9L,0xb4b01971e62a0519L, + 0xf3245aa65ff499daL,0xc2ef87f4a5238effL,0xc16dc6bacc9d5515L, + 0x5a7f227e2dbdacacL,0x8dedaac4a9bbaecbL,0xff308a6d2e7c9885L, + 0x4c6f2fc2e6895593L,0x3655f285177e0611L,0xa63e8d06300b1beeL, + 0xbed0ce7913c17b54L,0xca4abe35c4974262L,0xf4b44a17bc4e4037L, + 0x5ae95099efe5fbd9L }, + { 0x122e5ee7804f7455L,0x341a499722066682L,0x97d24c317795e333L, + 0x12f4123ce48efcedL,0xe8738d9219fbc21cL,0xbb3bdc610663a3aeL, + 0x3603d8c28593a6dbL,0x926227f2e3c1ac75L,0xfea92ac05eaae519L, + 0x5b596f0bfd6812acL,0x3ce7e844fc2a82dcL,0x3840481a63522b27L, + 0x836088b152867895L,0x21ffb7cc26588688L,0x0ca331612f4a7cacL, + 0x4110667ea3edd298L } }, + /* 191 */ + { { 0x81830357c2d04b63L,0x3fc5a34df4929a18L,0xc73bf6da22d195dfL, + 0x14df2f89cb432473L,0x345afe5ce997f138L,0xd8e3f5f98b9604f4L, + 0xad7942e950c10ae5L,0xcefd5447eed25ff3L,0xbf68e51e0e73c0ccL, + 0x5b1ad591ab54fa4cL,0x8bbc110512b61c8cL,0xbb932913b5abf760L, + 0xdb1231be01e79649L,0xd0a83e91040ccbe7L,0x3dde426f90a96db9L, + 0x1cceb64534df11eaL }, + { 0x2d210c4f0c6d0f55L,0x6cadf61b9c673c9dL,0xdd7f9919a9ce3fbbL, + 0x135f494c93b063e4L,0x580bdb3c145a93beL,0x4d8723320f52ef7cL, + 0x74d876e88814bb6aL,0x4f6f723ac7a97deeL,0x7de2b8f03e3cd833L, + 0x6162f082ae720270L,0xe88ec2d4ddfa486eL,0xd965c8598d3a17c6L, + 0x62e59e543980171aL,0x0ab6285dbbef6b22L,0x3cf451954d48b203L, + 0x1f1752334ea25ea3L } }, + /* 192 */ + { { 0x808a765b3467ea91L,0x3f4632eefd2d9c45L,0x7b75dc6d9cf2bc6fL, + 0xefc8d240359813aeL,0x23ecb209e44cbd8dL,0x59ba10e321525622L, + 0xfa14d9343f1ee19aL,0xdf97c21bfb0c48f7L,0xc4e62890ea30d437L, + 0xb286e2a4651475c2L,0x291f01e4126672a5L,0x9c6fda5c31aab3b8L, + 0xb7277a5ae17d22ecL,0xbd88ed83914f0badL,0xd0b05d1b6a2392e1L, + 0x4cb8af9065893c2bL }, + { 0xa2b02057bb4b1953L,0x4ce08b44f597f6eeL,0x854f5d9b5e6412c8L, + 0x1913262db3cd4919L,0x902762e46e42bb5dL,0x8355c8e6d78e7f60L, + 0x8efaa82438b6c16cL,0xd0173790e550f618L,0x118af462e57d778eL, + 0xa16ad5e8715b4714L,0x900596c341dea4f9L,0x2a957c32280ca610L, + 0x2faee800374c65a1L,0xdb10512750080414L,0x8c1db931ff080fa1L, + 0x486a5c25d79878fcL } }, + /* 193 */ + { { 0x0521e213941b4f36L,0xbaacfb14f803b4f9L,0xfdf1e22e52a54ba8L, + 0xacfabbba8fe4796cL,0xae0788db58dbacb6L,0xdf98d736c19dfa51L, + 0x155c286a35a716eeL,0xbe7d46769c86461bL,0x50b6380f63a64a5eL, + 0x14b419149f609262L,0x0919a7d0a2dfc5b3L,0xc454da55cef466acL, + 0x93fa4a246986aaecL,0x5090b17171a49cedL,0x602f1d6cc1fa75adL, + 0x5d269f8978e4c054L }, + { 0x3a74030c14920419L,0x0845d86890968739L,0x81b994c4eeb70fa6L, + 0xabcaa06dd9fc5bcbL,0x06539427f58f8f2dL,0x35c85f67b1dc52aaL, + 0x5a7d8d722c911baaL,0x4041005caec2d834L,0xb5868a447a8e5347L, + 0x04ee180b8de512c3L,0x4daa66e5211168ebL,0xc0bd5dab2317cd8aL, + 0xa1d4185d61164df6L,0xacedca261dbad7c9L,0x0fe4b5ac09b02683L, + 0x8ac9995a26d9550fL } }, + /* 194 */ + { { 0xb2c8dc9b2640a39dL,0x21ff0b38ede0c9f9L,0x74f469bda1ecba0aL, + 0x8a902ccd080d0417L,0xe956fa32f4994604L,0x348f85cf9776ab15L, + 0xc21fc6ee0066f492L,0x35b1ebfefeeef367L,0x7804581c4613e5edL, + 0xcbdfe8e6ea6ba071L,0xddfcaa32950d73edL,0xc97479361da48889L, + 0xce867c8cdbaffbd1L,0xd267431f1cbaeae7L,0x68255045897912c8L, + 0x0c7c1ddcd7ea1e4dL }, + { 0x53aa30cc1ce963a7L,0x7352f64cc4c5fadeL,0x2b9aa2f82828afbfL, + 0x64273c56ca212107L,0xaadd765485a576dcL,0x6196ac3e90b5c77cL, + 0x20d43e9fd1aaf39bL,0xfc392062cd05cbc4L,0x141638724c0ff2fdL, + 0xcf32b8d82ae821e6L,0x5f58f9433fa7a3f0L,0xaebf1d2df644ca92L, + 0x0c0615631918a75fL,0x7989b5ed6b876118L,0xbf342445ad412441L, + 0x24ffc9ae1df633abL } }, + /* 195 */ + { { 0x89fcdc0593c7cb2bL,0xc1243b95590053fbL,0x601debcf6182343cL, + 0x364546ef66c18a63L,0xa5290701ec913287L,0xc35b8026f9788c31L, + 0x852b862a92d1f7d7L,0x1809cb050aa79728L,0x897d467ca3cb2005L, + 0xf20c77c09ef5b946L,0xc3372c42f2241984L,0xda053e0df35bb206L, + 0xbc26c6d0a9c140b5L,0x61cfcc0ccb56fb33L,0x1c3cf9ef299b3968L, + 0x89e4d3d140621ba4L }, + { 0xd35e80e7a45a9be3L,0xc4daa57807356fbdL,0x0186d62eb967bc2fL, + 0xa702679e47cd16e3L,0xca2f1c025f30ce9bL,0xf1205b461f864f50L, + 0x7fd6d79785061d66L,0x47edc4f68a08809eL,0x5dac04499a4d3ae2L, + 0xf844664a6d1f9da8L,0x9f30ce84d7a83a71L,0xe9382baceaac33f1L, + 0x1f033831948622abL,0xb037a4baf7681eb2L,0xd156a90899a1b5c7L, + 0x675d3e6fe6f1d0fbL } }, + /* 196 */ + { { 0xd9767ffd707193e5L,0xe478aa91810358e5L,0x5634f9ff328d8ef7L, + 0x913a0ee86dbbd9a7L,0x379b29687e215686L,0x903f410a89d9da38L, + 0xd9f8d7b91b1334d2L,0x9fe74229bd82efb5L,0xdb568b623803c778L, + 0x93e9a350d3d25344L,0x559c35b0724497e8L,0xc472d436a169e23bL, + 0x09864632cc5b4c69L,0x9f6d759d83c7f531L,0xa91cf1db1e497888L, + 0x5f7f92fe60af1a4bL }, + { 0xf18a1cc60545167eL,0x55ee2e02affa88e0L,0x24cdff51432a7bcfL, + 0x7382da42a7510866L,0xe894c11f40511af7L,0xaa4e4e312aaf1423L, + 0x8c3d36f0f63dd2aeL,0xfc5c9550d7660635L,0x0125373137ea7eabL, + 0x2a5cd59839b950f6L,0x95a0f60140e63442L,0x905e238ef2ac7045L, + 0x44bacc0e446b0f73L,0x4cd4206ec448578aL,0x367b1aaaa5bd7803L, + 0x25beced90a2b458dL } }, + /* 197 */ + { { 0x079a73820c33a8fbL,0xcfbf6cd10f25dc1dL,0x4ffc73f8c6d482b6L, + 0x3e51f18c07bf844aL,0xa7651236599162f0L,0xac59a74e14013811L, + 0x957a6865e55018a0L,0xe1ec51bde3ca09b1L,0xbc0c7eb3a960253fL, + 0xe83bfd147de03f84L,0xc0540ed152fbdb09L,0x6ba52eddcea15ec1L, + 0xf3d30ed54b261307L,0x9bd7bae8e8397206L,0xf20d8692096373aaL, + 0x0a616a4bc3b0bf63L }, + { 0x2075f3ed6e1339c9L,0x7afaa072bf8b00a6L,0xdfafec82bccd9b47L, + 0x4713158f00ca54c7L,0x449102f138bc31aeL,0xaf98f158310dfc8aL, + 0xc9ef207559e954d4L,0xe8021af9c527a0c4L,0x6e8012777a192023L, + 0x635f538c7fb02377L,0x5df1974fe8c9e951L,0x0287faed15cc9097L, + 0xfa0728f0f7a5115cL,0x90dbfbe60fac623dL,0xa8d40fd40311ba09L, + 0x876d154e07c6464cL } }, + /* 198 */ + { { 0xd3a4d6d2c2d3ea8aL,0x36be681ba842600eL,0xc53f100de4070672L, + 0xe3e5b6fe6a7d7a7bL,0x6e6994f95d5e1a83L,0x07cacd2276097c2aL, + 0x12d98dbaa6791011L,0xddfc4461102e0e24L,0x4815dbc2d493272aL, + 0x7e38e64ba9436696L,0x4960eb1a32b2bf90L,0xda457525d928e28bL, + 0x72f75b392a077c9eL,0x27760cbb7fd61d00L,0xaf235d1b0f4b1456L, + 0x3040c23be76d1700L }, + { 0xb10dc55b4efa9a70L,0xd4de414f53e86610L,0x3d95c11309f8a27fL, + 0x505109a506661d3cL,0xcaa2994a60eb513eL,0x3ee415371e7d338bL, + 0x4fd145fc4651e71fL,0x51bbf838cbc313b4L,0xb039e0781eb92150L, + 0xe8696b4414bf5ac7L,0x2d6671888be0d48cL,0xbe93b2f5dd8f2b6fL, + 0xc1dfd1e7eb8a7f8aL,0x862b3dd990f751c5L,0x1eb1ad58a32a74beL, + 0x5486d79a1ebbc9a2L } }, + /* 199 */ + { { 0xcb2e34ffa1359e13L,0x202d8dbf28196051L,0xe95e023d23564b5eL, + 0xfb1340b642f6ac12L,0x543ba852b653725dL,0x81aedcd68d2466adL, + 0xbf780224547c728bL,0x559f8a119569fb65L,0x505b7a62dfb22ec9L, + 0x071075409eed5e52L,0x9c899288299f6f11L,0xa7d692613db6f8c7L, + 0x30eb7fb3b3ca79a9L,0xcab99bb8fb2160b0L,0xd2012568d28b409aL, + 0x380f1b0f5ac45f8bL }, + { 0xc0b99e6be6a0068fL,0x4b67cf2ac8a73753L,0xa6c9a548b2faeb7cL, + 0x7f417f99340260c3L,0x8ee56855cc0f739eL,0xf08b510f780949daL, + 0xb1770fc28d5c6effL,0xb4f5abeefd96a7bbL,0xa07b1136f2665a2aL, + 0x2fb380a4b601dcf9L,0xcc803614162becc6L,0x3498fb96ee6b83b3L, + 0xea9b0fd6a8c17eebL,0x5834b5baa177efc2L,0x929044f55b110b3eL, + 0x4abeddedebd7285eL } }, + /* 200 */ + { { 0x3355e1b9700ef376L,0xd56e5d9a66cdabffL,0xb3dc257547e87646L, + 0x28f44b8a00f79369L,0x08c32b1ea0c52e29L,0x5a78de123729b392L, + 0x4184519ab26d239dL,0x23f6b4b7e0ce4a6bL,0x235f6f8aacb2a9f9L, + 0xbb8bc454e2064a59L,0x37efd0341bf3062eL,0x6bac683b94dff6f9L, + 0xc3364b1e8aa7fa06L,0x0616772ace0b3745L,0x46f08d08d1e3fb0fL, + 0x6a20abb318e132d3L }, + { 0xea8310166a85cbc7L,0xd0990946934f9aa7L,0xc2211088e778f1b3L, + 0x7ea4ff8f2247b799L,0xb3171d71454484ceL,0x294039494f98c364L, + 0x5da911f397df1458L,0xa6b5809309439116L,0x75f9509a174238bcL, + 0xfeb518218209758dL,0xae0c6021a47925d0L,0x0e946694af8a315eL, + 0xae7af8a36bad04b7L,0x44c15e7ff072447dL,0x5184668aa5456ffeL, + 0x45e353a7bf36b977L } }, + /* 201 */ + { { 0x7605676493092f71L,0xeb66b6c2f5b92d71L,0x9db3149be2c8b6c5L, + 0xf62f583a20c0363eL,0x688acd3303cd7097L,0x85d0c0f8ebb916acL, + 0x1bf7462c84c19b0eL,0xc76ed5f97c4a6ad1L,0xec8b88bad119f369L, + 0x59b8371bebe50b83L,0x0cc69508866706a6L,0x531c75a3f8373d2cL, + 0x4e1cd3a32a5a02fbL,0xe8274778da39a1d0L,0xedfc5bbb75da333eL, + 0x15941f24ca79bd36L }, + { 0x42e8c0f8a77dd512L,0xa91b59a71dc365f6L,0xe80d14cd08753862L, + 0x1624230dd272facaL,0xeea3ec164027cb5aL,0xc1700b59c1ef9f03L, + 0xd411c1270da3148dL,0x801ee448c4181af1L,0xedf285599e3a900bL, + 0x5d67b0bd0d09affdL,0xd839df968b370024L,0x3b6307e0e6f836b8L, + 0x5382e588bd3201c9L,0x636d8a6b7a1d02bbL,0x70b7db76968641e9L, + 0x6d17c34a118fad03L } }, + /* 202 */ + { { 0xcf608841c181c99bL,0xb65dc901c87bdcafL,0xb460b4473720dabeL, + 0x4c79c3965377515bL,0xd447f22e0a96c277L,0x0d9521302ac0f440L, + 0x8330b26bc90583adL,0xe25e977a928904a0L,0x1deaffd985c50b18L, + 0xcf4dbcb7a5ad5f6aL,0xcbcd0019c8a37ed5L,0x7846dd901e9850b6L, + 0x1ac8194ab0b8e605L,0xb972857134132f90L,0x4ce9f149f56ee28bL, + 0x1ab9b5a43e9e1d4eL }, + { 0x206dab92314fa7a3L,0xcc4af0f0478ff963L,0x4cce1713904d9fdbL, + 0xac20a2eb12c045feL,0x44fc5478fd8f6d7dL,0x886e72c5ca7b6ffaL, + 0x7fa4529b6fd6f758L,0x4df1d1b192a820d5L,0x3d812f9f2789f149L, + 0x9842f083aabb53d2L,0x2648539b2a03ab32L,0x631ce090b1512502L, + 0xe1294d15731f6bd5L,0xb229361d9436e634L,0x8c4281c43ca966afL, + 0x24b34956c21ab3edL } }, + /* 203 */ + { { 0x49bdcb86659824e2L,0x6dc4ce484e13e74cL,0xa4c01a266bbe1eeaL, + 0x47b2b8e71e3ec457L,0x7e8b15e02f5a8e4bL,0xe81eb6e6e333530dL, + 0xacba369e17a45202L,0x81241431d70e4c9fL,0xc190af4b3e12beb8L, + 0x5327052311f486fdL,0x9f6c41e129fb2bceL,0xbe6287ebb70f6c08L, + 0x1479850a3feb4477L,0xfcfdfb119bcf18bbL,0x925c292fda80d040L, + 0x212d65e57e3c5bf9L }, + { 0x23adb386ca15cf08L,0x4dfa4ac481e172ebL,0x9d1dbf934d42d0c0L, + 0xd9cf607374404dc7L,0x60508441e932bfcdL,0x9ae910ca1c682a98L, + 0x9528fc1841ac1cc0L,0xe6a120aedbbed630L,0x94e0e1ec30ccf250L, + 0xfe84ba54e58bbf2fL,0xc66d0b4f9faa4415L,0x0c58f1e7ecee7ce5L, + 0x7a1d43eb6fa6873aL,0x96c6c5a0399f1348L,0xe6ef9aaae6727ab7L, + 0x66afa5549a5c2447L } }, + /* 204 */ + { { 0xda5aaba8c980e91dL,0xa93cf5096ac98efaL,0xb0990e0a8da32662L, + 0x01d215300081453eL,0x2bb0d33e3d71de84L,0x465f6d803e19a012L, + 0x5902ff4c78a838e7L,0x74e2afb71931348cL,0xa49327579cfb057bL, + 0x761ea6423ad03f8fL,0xb7d4c24558ffa40aL,0xb5e9c0d977a87e30L, + 0xd1c5edbac9c84d26L,0xeca8839a3d1963a0L,0xbc6f2f35ebf6bf0dL, + 0x01ef06310d58abdfL }, + { 0x2bf903163ecdcbb0L,0x19e2d72827c1c955L,0x9e5270309575c930L, + 0x0dc1c5a996983930L,0xef9f80ff7cd082dfL,0xcd915075df97e051L, + 0xf286fffe9cc61b55L,0x352db38f80f24cc4L,0xed9b99ec36523ae3L, + 0x109a8ca810b104a9L,0xc2700fe7305203adL,0x2a2ee24e769400f5L, + 0xd595d399ee0c452cL,0x0ab75d6af7f02a41L,0x341080990db730b7L, + 0x0e4f5ffd5e8d1202L } }, + /* 205 */ + { { 0xbd1c64440ff14c38L,0x9a5b59faaece11f2L,0xaa4605a722af6330L, + 0xddc9f65a82af24eeL,0xf4ee4bfeeb9a1159L,0x2463d07674e84eafL, + 0x88cbe1e00e0baaceL,0x7ca568ead5fabdcbL,0xbd80d524c57eb99dL, + 0x9c46572ce9be9873L,0x918a1dcd7300b85eL,0x4922131240f54176L, + 0xf7e324ffb5b14236L,0x40dda5012434f16aL,0x08833421a133d97cL, + 0x33d411610876f020L }, + { 0x7531a36b9878e5ecL,0x5de3e32146918232L,0xd15f9a33d0a30464L, + 0x734c1b87aa173659L,0xac2094a2f925d4feL,0x43c965a1c262b0f4L, + 0x759c903e447d5cbcL,0x92af215e05239300L,0xfffb6d5f1f593f34L, + 0x65943b4bc3cddb5fL,0x9d03a29cbfdd5408L,0x8f7cda6b198d76c0L, + 0xc0790a22c0f27b59L,0xba557a848cb58ccfL,0x5922052d76c54fdcL, + 0x2d3de7aa47b6b466L } }, + /* 206 */ + { { 0xaade746265add3b7L,0xe5888f35abf24c2aL,0xd41549cae1a57d93L, + 0x0e22e18e2c76f7bfL,0x67f288eabe3202b3L,0xb79a66ba1d1d0f0aL, + 0x0e0ab7492881ad18L,0x7d424086c7adb0e9L,0x870c32c52842132fL, + 0x858477f158f9a09eL,0x422a9372ec025589L,0xbe428c5ca5098777L, + 0x45b7956457660058L,0x6c7fc631957f37cfL,0x8b7023ddd6316289L, + 0x47003bb65b1c12a6L }, + { 0xd99401c1c91c1c96L,0xaa5dcdf927a12970L,0x3ab92e17c3c29107L, + 0x26fce8f7a3fe4710L,0xb0d09d5e4ee998eeL,0xafa622048e3a41f8L, + 0xb1c012a5a26ca506L,0x2c6f734c99b57252L,0x1093d79f512f7fe1L, + 0x2f30906eacee19a6L,0x6bff8381056d1ea6L,0x61c75856eff35f21L, + 0x6e07e978c1ad2224L,0x2cca6ca16b20fde8L,0xab4d6d2d633fe81bL, + 0x73dff504b06a2ce6L } }, + /* 207 */ + { { 0x8b615805d8e20fb8L,0x7c6873e482b533f0L,0x5205f00156a854caL, + 0x87fec6accb369211L,0x1fa3c0ecc7f092b7L,0x5b36647ee845fe4cL, + 0xd4781e85f8b1f112L,0xc65268398b0f1a6fL,0xceeb8c6cdcb8eb92L, + 0x133f0ead8e5f6d52L,0x31883e23c8d934dcL,0x214ed5bd428ac45aL, + 0xf77ca492dbbfca85L,0xdf4113fe07e5ae13L,0x63e4a0d272ab05fbL, + 0x7544d0b77148f535L }, + { 0x4fe8d13480797aceL,0x216d6aa0af86d97eL,0xdbf0a688ef5a68fcL, + 0x18b26f459f9b2684L,0x52fefcfa8999d2fcL,0xd5af8d8262423955L, + 0x8f123469f63a3780L,0x2933454fdcd4feafL,0xba8018b7a73b5d09L, + 0x9af1f276e5552c18L,0xc5d4773dff26bb1cL,0x9ef4941006dd4f44L, + 0xad8f12f95f39ba49L,0x5767f6dcf66ca4f2L,0xba8773f17922f59aL, + 0x220081eac1e42d49L } }, + /* 208 */ + { { 0x3043d573ba37a0baL,0x05a431bcdd176df6L,0x03322cfcc42070f7L, + 0x5cabd30e67c2d109L,0x362c95decbf8bcfaL,0xd767d2777787b10bL, + 0x612c915e6ec05e64L,0x9e669631ce69c30eL,0x27c9dd8f682e2635L, + 0x79021f1295ffcc38L,0x06a8ee798a2adca2L,0x8e00e7844b5d500aL, + 0x87746fc78d80d6c5L,0x246053be915f10ccL,0x844e328b219f6fd8L, + 0x620541ac11bd3733L }, + { 0x0f7fd382509e5a29L,0x8748d7d0b432531eL,0x8f749354cd3883b9L, + 0xc6b8ac748bfbb17aL,0xa4616a6605f2d2c5L,0xb3d966251bcb1b83L, + 0xcf7531042fee265aL,0xc70d73fbdb225058L,0x1211d434f0c2d556L, + 0x862061d854b259b3L,0xffe4606dc42b3f7dL,0x4c5c8585e86a4949L, + 0x04ddcc8b160eedacL,0x1804ce67568e2420L,0x91f3855a42141656L, + 0x7f378198f932be97L } }, + /* 209 */ + { { 0x9a374bdadfa6639aL,0x0cbd48d402ab7391L,0x5c5ef23647031e2dL, + 0xb49ee2bcd0599d1fL,0xd285eb60e0d38443L,0xdbbea92f269392e8L, + 0x91455fbfb8bc538fL,0xae259ff1e469b768L,0xc1cecb1f41de5682L, + 0xc876f0719952d1aeL,0x1ce25181e7bf7446L,0xcb93ad86282ad2f1L, + 0x8fa3cd316ba4ef67L,0xfce68a04e507aa3eL,0xced74170a61bb608L, + 0x6de716b3f6ac10d0L }, + { 0xd4e58d04172d6dc5L,0xbed2cde66397c65cL,0x7ae77e180c9eb4e8L, + 0x5627546875fa2edbL,0x4b30324ea91e6738L,0x6023a856235c8b2eL, + 0x9df6d6c2a8f92887L,0xec2c185ff6f5e8b5L,0x7892e12b3ad5748aL, + 0x7aebb4f2d54aefbcL,0x14915448ee868821L,0xa26c5f71b1d9bd5bL, + 0xe5ccd1662ff00df7L,0xebc99f17b95b1deeL,0x909836163fe1f774L, + 0x51f90830bb3d25b0L } }, + /* 210 */ + { { 0x49376fa1f2922461L,0xdbb1b1c31650d0d1L,0x92b91c330dd8608dL, + 0x3e612c4b36b89906L,0xe1977b0bdf560052L,0xf8afff70636a2545L, + 0xcda7d27811723d8eL,0x0b0bc4bb81bde7baL,0x3cb080b2ed2a578eL, + 0x5bda0d0d171b2e02L,0xf6df38cf941bb9aeL,0x85dd81dbc14a65c5L, + 0x7f98c82dc19dd98eL,0xc613747f52206f93L,0x9e13a2c25f5bbe78L, + 0x5eed218e0aa34be7L }, + { 0xe156575401d4dc0bL,0xa1ae5f27f566bb07L,0xe985ebebb82225d5L, + 0x5f3ad21c1189ec6bL,0x17da518cecce4d9dL,0xc84a2d3ed6b65b59L, + 0x7f9881758ffa771cL,0x50d6ae122ac69a7aL,0xcb7f30b1c6e6846dL, + 0x8c023a605bd0bb13L,0x9a10fecdd73f2407L,0x8c5158cce5f0a996L, + 0xd26bf615bd8f5806L,0xaf32ea87915a46e1L,0xeaf74e810287d308L, + 0x8c14ba06a6264254L } }, + /* 211 */ + { { 0x0c877895b17ee201L,0xc05aa47188e57a77L,0x19c3e76397822456L, + 0x0be6f8c0c9c3ba1dL,0xfe85f4ffb4389ebeL,0x538bccce0ce7fbb6L, + 0x876eab2a65266c64L,0x5c9ac690cf9a3842L,0x9f5cf3b1ccc8f981L, + 0xfa17be6a9cf687deL,0xfcfc10fc83835c15L,0x086b0fdb150ef2ebL, + 0x9f97ecd9884a52e6L,0x416e6fa2b0cd1eb8L,0xe2bd15993ecc03baL, + 0x645c0a5deabb165eL }, + { 0xd94c420550aa7e31L,0xaec8df0c2f851da5L,0x996469093c726e6aL, + 0x72dbdc362619bf9aL,0x1b4260e0e253fbd5L,0x97c259fb8c709e06L, + 0xfabf7cbbcddaec5bL,0xb4d5e8b1e4b703e9L,0x1b06e56e0734efddL, + 0x02d4a4f91f55f8a5L,0x7f8608ba3f565c8dL,0x822f47d2816d1d94L, + 0x0cc361565ce7b136L,0xe46ee5ef31d04242L,0xb2a65f70683567f6L, + 0x27e9ff40d2fa6c91L } }, + /* 212 */ + { { 0x75251893d7e952e7L,0x15b30583c735bf18L,0x732b599296fe0491L, + 0x27451858806d2fcaL,0x71ab76a01b885ed9L,0xbdce9d976d9f55ecL, + 0x3da60b2048f2ba9cL,0x6977c086592b132bL,0xb6dca9cb099051d7L, + 0xd9c2ab23d188ae25L,0x9f469f3fe20aaf3dL,0xdbd1f7cf5aad74d0L, + 0x3d5efe5c22a9eb3bL,0x8c5edfa2137010c4L,0xada2217b57870260L, + 0x4feee5673dac9776L }, + { 0x30e18d52b5d3d780L,0x4dadb5d307166744L,0x320d386e5a742156L, + 0x5d8c290e8d6bbb86L,0x981a43232d263dd1L,0x33d0e7ca98984636L, + 0x5138784da519acb1L,0x832e3fabdddc81ffL,0xfc2785943199a43aL, + 0x5b4cabcf32743163L,0x9fa010bd74f94fa7L,0xc28a743d5694a627L, + 0xc1d2a888cb657a24L,0x7eef2503e86a25eaL,0xed11a5d304c561ffL, + 0x4fe818e79c9ede0eL } }, + /* 213 */ + { { 0x00252c9d7fc1c7ffL,0xa9bd419d9fa89ad1L,0xc93a124a4064e9ccL, + 0x384cbcb843942eccL,0x004c21fd8749695bL,0x69c81d9f421165bfL, + 0xe2325628dde01102L,0xec9374575a9b004dL,0xfb3346bff6dcfc21L, + 0xac4da64b4d372c7dL,0xcecb7ad3f20494e2L,0x562c41b5e867c150L, + 0x299395cec2b723d8L,0xc91adfc57ee53231L,0xe06f1161f10b6597L, + 0x81915529b74d3ffcL }, + { 0x8ec124316ed9d4eeL,0x3dffa154689aff01L,0x4aba349f2a89a3f4L, + 0x2db1e8e2d467efb2L,0x18dea354039102e2L,0x422ab853e52f082bL, + 0x7130a2c1ed36dd47L,0xca60e86d0295d1eeL,0xe6ac68087c7f5ad3L, + 0x0f83cecfde864658L,0x72e66c21461d1265L,0xfeef4150bd385099L, + 0x0f183f3aa6632289L,0x275454be792dc795L,0x2744c11b11367702L, + 0x7d06bcc7e8ea6ef3L } }, + /* 214 */ + { { 0x892859427090212fL,0x691b7d4c5521e844L,0x4c038422be2dbb92L, + 0x317721edbd81f880L,0xc136cbeeac89bc36L,0x4f71b60b7b8f004dL, + 0x269132d04e218ab8L,0xb0e2496ee6cc814dL,0x0b2ce31775fadc15L, + 0x82e3c08466d223c5L,0x9721caa64c612f8bL,0x59a751eba4b65355L, + 0x3433aad5c7d3d9d1L,0x1e61b9d2e80d4246L,0x149f655ffc673caaL, + 0x48b52b99d0f9cb92L }, + { 0xa3915399efdc05beL,0xde70db1813e095e9L,0x447862e9cddb3fdaL, + 0xa2b031621a009451L,0x4b27980c23920ea3L,0xac5394f1a23b8febL, + 0x163f72563e5616d4L,0xaa0ff93fb714219aL,0xd26f96d293d62474L, + 0xdd212ea87dcfe276L,0xab27bf2f47038d15L,0xe58c8325f418168eL, + 0xe3704222b32a989aL,0xa3694390bfc9f13bL,0xf16e26060d0684adL, + 0x17c0de879d8c76ecL } }, + /* 215 */ + { { 0xbca5f453dcc01958L,0x7d9459541ce88393L,0x5e6350a1561f5b6dL, + 0x291c3c867e2d36bcL,0xf6c7ed84a5ac3a6cL,0x7913c40bd98006cdL, + 0xf78bb0875671ec3bL,0x1c928f6eb43e89a9L,0xfdf28df3ae1ea1edL, + 0x62bba5b1b924b2b5L,0x491d27051a116e05L,0x08ec02b7167ed3e3L, + 0xe291cf7b5bc0b046L,0x30e501698c5d7f59L,0x0c7c350df5c799b7L, + 0x6862b9e20ac6e1d7L }, + { 0x56c6f4e79ffa1f64L,0xfed6a91aa1e24349L,0xe9a0ee0ccdb75232L, + 0xbfc90b370322d607L,0x29480ad2462fef87L,0xfc214969c2bfcf34L, + 0x6e5211e0a539e38fL,0x2a59ec2612a5149cL,0x195fe212d706b532L, + 0xf77fb108e99c8429L,0x74ceaea35dc80482L,0xa5a6030bbd92d298L, + 0xad42dca5aaea15eeL,0xd6ac3bc74987109cL,0xc64e1c40290af649L, + 0x5093fa2d51f8de6cL } }, + /* 216 */ + { { 0xc4cf32804c2d553bL,0xdc1abe223b966c29L,0x556a549c2296914aL, + 0xd8c9f8b5999976c9L,0xc22c57bd776e83f3L,0x4f2942ab7c85ec57L, + 0xef3407e56e2c61f5L,0xf005e8caf213db48L,0x470c853df32698c7L, + 0xe6f488d7cac0a54bL,0xb6bd6bed60b7501eL,0xf0103106714a4bd9L, + 0x5285bc3b6e098894L,0xec06741af5f92a00L,0x32f16426ef7ef24aL, + 0x12f9c44d6c77a438L }, + { 0x1951e96483313a1cL,0x98edd3da33c58b37L,0x4edbbf52c7ac4044L, + 0x866ca6f70dcb5ee8L,0xec0ae8f56dd422f8L,0x1077bc540661ec2eL, + 0x6d39913ad422523cL,0xd105e1e858e7cb3eL,0x47c9397fc979bb45L, + 0x3221d4a90997b592L,0x0ef628a3e8952fe7L,0xd08d58274e946241L, + 0x64cbed0f59780f40L,0x13d7c22708e110ecL,0xd186d8667679b1a3L, + 0x02f75e4e26ae1d18L } }, + /* 217 */ + { { 0x1b637ebf47f307d7L,0x6b644a6ad0141477L,0x82a33d652e05a80cL, + 0xc8f1a0f3fed07b31L,0xc09ee7f93696e597L,0xcdaa7ec3c7ffc01eL, + 0x549f88fef8f373b9L,0xc88d1961c3bb8989L,0xd92a4fe9dfcaa7b7L, + 0x12ff9ee23ae4ab20L,0xf5aea641f5ecb1a5L,0xe769237fe32fb47dL, + 0x96a5c42025d085c0L,0xdc91255826c755a2L,0x580b985f9bce9723L, + 0x72b1b56663961941L }, + { 0x9d708a08790e5558L,0x985360410689af80L,0xe85e7b8a42313b5fL, + 0xe6ba129255a49d1aL,0x5e76c4b0ac371b0bL,0x58504f39938e6e19L, + 0x8dd4142260ae9a21L,0xd8b04e9b968485ceL,0xf94c4ba5887efe43L, + 0x11268e67f11c5e73L,0x92623e28cf6b99c4L,0xf2d0aaa87a0a9662L, + 0xb266772a4ca02ed3L,0x68ee8e4e2d63b551L,0xcdebb2992e78b5b5L, + 0x5df19216e17225adL } }, + /* 218 */ + { { 0x20027e1e8df2e7e3L,0xb183cc68d8da07deL,0xce35ba694b4ae694L, + 0x896d97df3ca62e88L,0x3de4713b52efed2cL,0xd006c40e26bd084fL, + 0x1e9b71bbfc81923bL,0x9991c7b61aacc6b0L,0x650c93648f656840L, + 0x138561d187f47524L,0x610f2b11bffd3ca2L,0x96915faffa191418L, + 0x8f1236de955e5309L,0x613cbeeaa1872d79L,0x7f7b44ea66a2a48bL, + 0x452265c2e0a89c32L }, + { 0x4ad5ec7925430010L,0xcac786ffebd090c0L,0xa5f9f4ff20a9d3f5L, + 0xfcbf4112a3edc65fL,0x8824839c0cf3eb11L,0xb8dd6d4e8aa5b700L, + 0xe2271dfdb7568ab8L,0xe43ec373b744560eL,0x78eaf9261cf75296L, + 0x1809ae0e3fa96d9bL,0x0b312d2ddc25dfd5L,0x6b8f78b46bab7711L, + 0x069efc8db5ecf1e4L,0xc1952bae609fecaaL,0x43e302ed5f4dbde1L, + 0x14b02bf91e078555L } }, + /* 219 */ + { { 0x2c71c768b87e5b57L,0x0bcc78f7f531a557L,0x4ff93f8bf7597dc8L, + 0xb28e026d139e175fL,0x6b83b727cb94ca6cL,0x2eafe3b20079f7fcL, + 0x2aca54decf3bd170L,0x17c4133c6af0dc6cL,0xbea1e665ccf5e35eL, + 0xa6691a48345505c6L,0x2633abd0e6100b89L,0x966c6706c17d0388L, + 0x7aefffbe1a0cf90cL,0x4d847be7d0add64cL,0xd49bcdfbaea2aa46L, + 0x85e07e742cc7d0a5L }, + { 0x23aae0a60bc25bcaL,0x6e8e55f1e44f64ecL,0xe1e696d8b607b773L, + 0xaa90a746d3005909L,0x072b1ccd2cbc4990L,0x0d0fe6c6c68e2f5dL, + 0x920ec5f053e28ec9L,0x79b21fb4f0040cc1L,0xa7375bd3fcc4a2c7L, + 0xf5f5def9e1bac7ddL,0xdc315d7935c0f8d3L,0x7117c1702cacd318L, + 0x6f2823c4e926f71cL,0x38db58bbed02f39aL,0xe5b492317db69323L, + 0x0964039f8d49f430L } }, + /* 220 */ + { { 0x21774f1656999ebaL,0x3d8ee287b1de6305L,0xd81af726de0b2669L, + 0x374469393f8942a1L,0xbcf6b615ea03e13cL,0xd30c0c3594e273cfL, + 0x4fd33a56c6725c56L,0xa57534ada8be97a2L,0x799242a67c22a251L, + 0x4e51bdb59d0c5c49L,0xd7cd76ccc6a42768L,0x914097acd426bf59L, + 0x59404a2c66e9beb2L,0x4738fe985c96e3e9L,0xbcbb3e0eaad666d0L, + 0x626b0fd263bc5e56L }, + { 0x47217dbae1a1ec42L,0xaa6ae7dbab5acc50L,0xb7e1ab1e865331d1L, + 0xb84530703d30126fL,0x280649e0dee61851L,0x8806f4a3ea689544L, + 0x4bbe43adcb56f632L,0x036b9bdabcaff94fL,0x0d941e65bd0637beL, + 0x82179d44686f3abbL,0x1486912caad6afd6L,0x9a3b891eff7e1534L, + 0x88c426ceeb86fd96L,0xb56e6a81117928c3L,0x933e713596399e00L, + 0x09bbddd9a17b6ac1L } }, + /* 221 */ + { { 0x75e39c1de4fd3673L,0xf880d9d1a65c8e07L,0x4725c1dc7289c7feL, + 0x5b6735ee3529d200L,0xc1f8f2ed3c747af3L,0x5cf3998f912efdf5L, + 0xed72261849859c39L,0x23793a2f0e69795dL,0x8a6ab8d686b1d2a7L, + 0x00c815de22a882e4L,0xbe77d6fcf9db8d7eL,0x0886fb3202267547L, + 0xb62687d449c10edcL,0x9f1c3e177c83ed4cL,0xe6d5d7f05af366eaL, + 0x2eaa01b8d1efad24L }, + { 0x5e47fb701f357c74L,0x93085c4aa9e3b794L,0x4f0987336e85a905L, + 0xf53808ffbe0244c9L,0x91dddf93a3b5660dL,0x8b76377bf3b95ed6L, + 0x91b911b7bb3920d4L,0x7ccf08bf86a13cf3L,0x53ed8f97ea018e58L, + 0xb1ea434378c55194L,0x8e6adde9e0d2d5a6L,0xfc2b248f9b96259aL, + 0x96ebceaeeef17dddL,0xf694b443557f9c85L,0x48cd150f07d5bba8L, + 0x02d31de9b4c1986bL } }, + /* 222 */ + { { 0xa6bb9e1ede79499dL,0xf6ca8ff8fd0fc2adL,0xbec0f8e81a7d9356L, + 0xbc3d1c9fe8f06327L,0x805c72173b300bebL,0x00420a08413c181bL, + 0x9e9a167ef0ca9d01L,0x076c909d1aeeddd6L,0x64a1997f8e3a8a72L, + 0x3ce7f7a7a77b429eL,0xaac0fbf45c94d3e9L,0xf37694a7e6d48407L, + 0xf56679e2a91921e7L,0xf23fe0f3ee1dbbd6L,0xc7917566cbf9fa99L, + 0x965860f2e0f4d765L }, + { 0xe734702b7fa5f79cL,0x930bd4265af2d26dL,0x45bd8b986c73e0ceL, + 0x7dbe7bed4ee44a2dL,0xc129e024956c8a1aL,0x6fdc05ac77cdf80eL, + 0x70a6ba2b589ca59bL,0xfc484021999825afL,0x1d284b547a23f0b6L, + 0xb1da10a428a0a8afL,0xb1eb1b312b2af6d8L,0xf051443a33935ee3L, + 0x7a07eb268effa6ecL,0x16ee4086d662654cL,0x7a7bc5014549ee4cL, + 0x650810321fa98a52L } }, + /* 223 */ + { { 0x49f0e460b67ed9b2L,0x0cda0fd0c36d93d2L,0xbb5963e988c75e1cL, + 0x757bbe93614bc0c9L,0x9a9b88019a768605L,0xa8b7e2af48edc544L, + 0x9e77ed9eb51a5985L,0xdd025274ebbf024cL,0x598b62881545c636L, + 0x39bdaed04800dba0L,0x7fc2013981e2a23aL,0xdc66fd5c550cb4f2L, + 0xad27032fb52068c7L,0xc9a0bcae8169fa15L,0x60606f213a7ca8a2L, + 0x982950469862652fL }, + { 0x3e3746002e11c128L,0x80dfae5d0e6dca7eL,0xe44016e2d9552264L, + 0xf65f88f2880b7143L,0xca3d28d4526b881cL,0xf9c59dd1dfb86afeL, + 0x548860c24c74f958L,0xd06ea43c9cb69f4fL,0x5343c9ae7334ececL, + 0x5cc2ccd635329713L,0xa95ff4035f3a6c0cL,0x2e01a1ccb372653bL, + 0x31510fdfa250523dL,0xeee538e2a6227eb2L,0xeadfc8a0ca23cd10L, + 0x4b7e6e1b3e78f54bL } }, + /* 224 */ + { { 0x79c9076fdb5f928bL,0xe6250bb6b7347cecL,0x54b67798ac00ec41L, + 0x900d20ba9d9619c7L,0xed42c0d059e4343fL,0x3df39e85451935d7L, + 0x2639118264f701ceL,0xce8f2554e1f87aacL,0xfddd678965f91aaaL, + 0x96cd163fa324539fL,0x5c815f2c4bace995L,0xd78c8c2aa94f9ea5L, + 0x7ab2aff4ef24e455L,0xf0ed64091cddc26aL,0x954a420b00ca2822L, + 0x0611c4c5d3297658L }, + { 0xf192001ca9e81829L,0xded3332008a282ccL,0x0bfd7de18f9ded9bL, + 0x6793ac0db7889003L,0xbb00d91d3577a5ddL,0xe17a23a7802d3c2bL, + 0xff95f88cfb549014L,0x7cd1bf4bc71b6e07L,0x2e3b24a023588c8bL, + 0x9b5335b8a4112076L,0x2481c05ec4056d30L,0x55c7410ce916a1b5L, + 0xbbe03271850179f4L,0x15e6c177b3cd1208L,0x509a24c090cbfe50L, + 0x820795291c108566L } }, + /* 225 */ + { { 0x5d2d3cff1c7d353eL,0xd5e7eccd7de0ce3bL,0xb4b1075f6ca87635L, + 0xda8404e025f9ad3eL,0x6b963e89205cb5aeL,0x9e5ee0d809f221a1L, + 0xd64c85d9ea41aca4L,0x6a46c4e934442a34L,0xac6ff97e3cf655a4L, + 0x76565c1ee5417d7cL,0x681009a9eebf9c4cL,0x95b61d3988da6388L, + 0x6402b46af6b472c6L,0x1fde51650b7f1171L,0x94f8f273be0c05e3L, + 0x7487b036a88344a7L }, + { 0xa860e5759c3e2370L,0x19d58193f8048719L,0x3a0dbf3ca6e2f9aaL, + 0xb6c7e9596144719bL,0xa9049c74deffec21L,0x8ba064b23f50cebfL, + 0xb12822c049a1de15L,0xb654b7d9b1d527f2L,0xc470859d0ffd0430L, + 0x37c74a674f05446bL,0xe553251ba3add995L,0x4a3ed6cbe33533b5L, + 0x2f2f44d027e419ceL,0x2d84ee82a5d1b979L,0xcc76b123db6fa69fL, + 0x834f85c521fa3bddL } }, + /* 226 */ + { { 0x329347c12ce9b31aL,0x1d88522afe3fb3b7L,0x4bcefb4d52ff90fdL, + 0x53b173862b1a081dL,0x538c11ba2a411f08L,0x7895b93c141b603aL, + 0x2993b9aab10bd741L,0xccbbd04609912986L,0x669fafb0eea0aba5L, + 0xd484462235661897L,0x4a63b89c367ffa54L,0xcbad5d1d1c3478daL, + 0xc5339227aa6034f7L,0x0e6d705fe61b1391L,0xdd14b660f74ff515L, + 0x639d8b0a5332b54cL }, + { 0xfa423162162217cdL,0x2e0e4a2a811c28e6L,0x68d9ce1821766dc0L, + 0x51263739046a06efL,0x44eea231dde92101L,0x0607c8f2114298d3L, + 0x27f272ba63d957e9L,0xe7ce80cca5e8cae1L,0x5816ebe224f7a63fL, + 0x4dece5a789673e34L,0x13756a22536babd4L,0x644d61aee3bf77afL, + 0x60b2bf6e2bcf98bcL,0x3b0b59f329fa962cL,0xb0769a1aabb50023L, + 0x409031360c75402cL } }, + /* 227 */ + { { 0x84d2873a1670433fL,0xc9394df625493dfcL,0xeb05a19a80fcf89eL, + 0xe39e4310db297616L,0x50742dc9d9e63046L,0xf31ad8c81de9ca9eL, + 0x86aabf94fb7b1d0dL,0x36cda27a1b3c82d1L,0xfb1a2ef439702d84L, + 0x280bfddc46081299L,0xe4b2b48dd2396238L,0x2db2c2f37b3c9353L, + 0xd5b5b31712fb8a69L,0xf9b87a3b08180474L,0xd85909861e952578L, + 0x80668eedf37a2bc8L }, + { 0xe2edcd35b39a0249L,0xaf230cd4b2f8aeaeL,0x295b15e47223df05L, + 0xbb66982ae0e937f4L,0x019d2b728cbc9162L,0x5c512ae9cf49dca1L, + 0x11b491a7630f07b4L,0x48d4f34ca03874e9L,0xc1fd0ea644cb7433L, + 0x13f79ae1f95b30c3L,0x40362d4ded8b60acL,0x9e8314ff61ead81cL, + 0xed600dd4498c3d28L,0x5fcb1c19c2521702L,0x592329fc3a9c1f33L, + 0x046775481bde6ce9L } }, + /* 228 */ + { { 0xee3de56e39233c96L,0x868c409c80737eafL,0xacae11bd201abc68L, + 0x0f2cea9b2b486205L,0xe32387e16f19056cL,0xea75365aa5dc2a41L, + 0x76c29acc12b4be86L,0xa01fcab78d63294dL,0x81dbe88b0cab9f24L, + 0x76646e5bf414c054L,0xfe111893cb96b7aaL,0xb649f5b17664e097L, + 0xa196422e53fcf5a9L,0x5978c9bd0b7ff634L,0xb5feb38e3c229895L, + 0x038a49fb0833c456L }, + { 0x35e3818c13e93257L,0x14cebc9da612741bL,0x4f6e92497caac06bL, + 0x82278e333daa1116L,0xe7cc565e4de2034aL,0xbb7dc95f0a1ba630L, + 0x81dd9f2366956fbdL,0xc63e6319bb132dd6L,0x6e22b022fc241337L, + 0x238481937e8beb1cL,0x83b1994dd8c938acL,0xb54cfacaa6bb5644L, + 0x1a7cd44e06f91807L,0x1dd439bba8f8d9f3L,0x660c2a787f74a8e6L, + 0x4bb76e22121b5660L } }, + /* 229 */ + { { 0x7a151e8ae6354817L,0x33d494eaf038b438L,0x4c86c68885958986L, + 0x721538271dcbac12L,0xf487af8cc0edad06L,0xad33051fe500e5d6L, + 0x0a711b1bd6e47f55L,0xa68709a78c746ad5L,0x27f172626402f35eL, + 0xc6d08efafb30c130L,0x9ef1c041c06c7497L,0xd0c74ecedcc3e2daL, + 0x30c5f96e092e1073L,0x0f1393cf2aa12b74L,0x245840162107eb02L, + 0x8843d25f7b76f98bL }, + { 0x4e1501dcedb2a83eL,0xbcfe8fb02bb8d724L,0x09020659d925df62L, + 0x3c715dcf42ab6fc3L,0x73c05055a0f09dfdL,0x126745d8e3590aeaL, + 0x5382f4d876ff749eL,0xfc69feefa920c663L,0xde1602119fd711caL, + 0x4219c3bd9075c4d5L,0x3800cbd13ded6bf2L,0x8c7ea0eb6263a116L, + 0x35bd79587d264c37L,0x56e22e457159c98cL,0x71bf2a2dfa7373b5L, + 0x0503f9398935c949L } }, + /* 230 */ + { { 0x65addc6671dad4f6L,0x238e4889024bea1bL,0xfb76c8e2f605d3ddL, + 0x13d5f5deb0d96b89L,0xe0b5ba356601b2cbL,0xe37d491d83e3d254L, + 0xe8860423240c8ea7L,0x374182f3e91c99baL,0x26c2caf9a87ad919L, + 0x4b13040af574f295L,0x5b9bced1944000a3L,0x4ccc57be06df42e7L, + 0x22e8ec504bd1089dL,0x0c53177adddbb500L,0x690d31d29ecfeadbL, + 0x735778fe176668f9L }, + { 0x0f86ee3e843c1137L,0x3c1c42fa3f0b73cdL,0x0e75679d8ab20e3aL, + 0x6f95f1f416242faeL,0x7b88e11c39b092e4L,0x1629403e4c236ac0L, + 0x66105f412dac02e6L,0x74dc28a7862e0632L,0x2118ffb2f3b23c8dL, + 0x1182417c0745ffbfL,0x49b55a044c05711eL,0x2c665b74cefbe4deL, + 0x1cc4c01d97bf7107L,0xb2ca06dac54f0676L,0xfc599daa7450d0f8L, + 0x52e637a61a3182a1L } }, + /* 231 */ + { { 0x481700f16bebc6dbL,0x4a6b45dbf9503d92L,0xc715cd3c5d153919L, + 0x942a1c05e5ad2abcL,0x36a82433ab7b466fL,0xba413bedba13918bL, + 0x698a562490f4e6ceL,0xbb720da6f3f1f3caL,0x2116d41d63471ab3L, + 0xe00d2227303d3609L,0x7fd4cc00463ba69eL,0xac609e4d62845fd1L, + 0x63603b2c80adc9c7L,0xbf16fc9a45fafbcaL,0x41007f7fc4bc94abL, + 0x7c916b4fa74b1698L }, + { 0xc1026f9178bac2d4L,0x8a2e80982601a875L,0xad2f276e0073d640L, + 0x443610c4fcc1fb88L,0x5727b822ca6b291fL,0x0645532c88ec60fcL, + 0x51e48899ed9ad48bL,0x841b48b5f543f103L,0xa6ccb1bed591ceebL, + 0xfc4adf0f9dcf5a8bL,0x3a7ca020b347ddb4L,0xaa1accc2cb44c521L, + 0x773b68280527c0c4L,0xaa374c107023cf50L,0x733d10006b74c926L, + 0x1ff3916f77a8d07cL } }, + /* 232 */ + { { 0xaa218fe4f997939dL,0x3d4dfbbb791583b3L,0xb3a7b5da87f7560bL, + 0xa9c028015da92c98L,0xe1eb4aad46666f4aL,0x2eb17a5114ce9dd7L, + 0xf46a66a4ef8f3076L,0x900b45c6810e546eL,0xf7af22584baf04ddL, + 0x3cc1c8725c84d42fL,0x3093f2258e4c83deL,0x62fade41170d88b2L, + 0xe19612e4ac076e44L,0xf48d734632dd141bL,0xc1b1f759925e34daL, + 0x19ed1a56072b90c9L }, + { 0x9cf7fcde6c735473L,0xaab88e676003bc3eL,0x12187cbcfb199bb8L, + 0xbb7304419accccbdL,0x214aff3cb0f65459L,0x6aec81a36f926282L, + 0xaa82cb329f9d20b8L,0x82f3f90f5773cc90L,0x4af60e6bf62257e1L, + 0xf18b44bfbd4762dfL,0x3948b129db970753L,0xc6e920e97c22c18eL, + 0x393d620857be97adL,0xe8d7382c46b637f9L,0xf6625ccbf1fed1d5L, + 0x6f31e0f968681599L } }, + /* 233 */ + { { 0xc45afe5582b8f204L,0xac0441b6d358b54aL,0x7213e7bfacd5f5edL, + 0x1914c70b139bcd93L,0x714b458196dbcbb0L,0xe9297d351ed35d21L, + 0x8f6408376a3e1f20L,0x150a8a9d2f3cd705L,0xfb36e801dcdd9f6dL, + 0x5a54eb655cf56d82L,0x7610500c92aa5a21L,0xd10d0ae23b089f03L, + 0x491b2079c42b66e8L,0x4af1ae3d0eee8d48L,0x137e4c2841556f45L, + 0x875e330863d8a7e6L }, + { 0xdc80fddcaf6c0accL,0xd5ad1e66bb1e7c08L,0xdc717ae1828585adL, + 0xbdc54340275c7da6L,0xf4b4c852d26b9e15L,0x5f0a1fbf6a05fa50L, + 0xc6f81e47817bcb32L,0x2cbd432870ff2e1dL,0x8a24901667c7f7fcL, + 0xd045acb7b585a6c4L,0x2e972ad44666c057L,0xc74d87cfe6d7d63dL, + 0xf7067d870e274144L,0xb2ca157a8b2584aeL,0x495c5bfb75f0fdebL, + 0x5abb0581f386e009L } }, + /* 234 */ + { { 0x8be62d2bf0c97f57L,0x0fe04871962f28c7L,0xc548a46747b50abbL, + 0xf6b26e0344fa09edL,0xfd44c6e3ab05a96eL,0xedb0032c70e6ae82L, + 0x28bd402bd7e4899dL,0x43f2e9639b7c11c2L,0x0ec3fc0ece913716L, + 0x769b8bc902fd0f8cL,0x9d9cb3aa7cabc3acL,0xe88a889206924cc9L, + 0xa51461aa42609014L,0xc7f4aa8b962e79e0L,0x4ef0210a8b1b3e80L, + 0x705446801bfee4bcL }, + { 0xfab3d713121901c1L,0xe90a2627fead54aaL,0x64f6d285bc08ba23L, + 0x8d99301536ec227eL,0x99a16ab906c191abL,0x86b1cf5bf649ce2cL, + 0x5920675966be3a80L,0x18836279ccba2cf0L,0x2c157b87eff53486L, + 0xbfac98964b223af2L,0xcd0fd4f00aae7a57L,0xdaddb94063218a80L, + 0x3844bb79df88f14eL,0xc1b3e3d4b71ed9fdL,0x6c634a13d6205036L, + 0x6f56aecfb8680a6bL } }, + /* 235 */ + { { 0xb01dc803d9205c5dL,0x68955f7d67123929L,0x3debbffd9d9b6565L, + 0xb844395ed3b1acfeL,0x04328b216094eeffL,0x6631ffa822991febL, + 0x0dde66e6190dd075L,0x75b03c55e8577c05L,0x6c91ce5f91722407L, + 0x9a288a408ebb3a3fL,0x1d376f8a058a1396L,0xf3a594579a6e0676L, + 0x103029c57b71d288L,0x0843f428b44c30c0L,0xd8e6aff8730e0b9cL, + 0x7b6be8114ed644adL }, + { 0x3ec38e4a3d3aa54eL,0x10233943d83d509aL,0xf84aa621243955e2L, + 0x29104717f51d3d44L,0x62d2442c7eca4e37L,0x8c5a523d85fa55deL, + 0xc6f5ccda851da1b5L,0x044bcaa820001468L,0xf7501e68e01702e0L, + 0xf0819359e6a0acecL,0x33dda6adac0ef0b2L,0x97aeedc8fd964f01L, + 0x48dacd0e530b90d8L,0x4c5fad6fb84122ebL,0x2284ec1ed700a1deL, + 0x86f9a835dbca5474L } }, + /* 236 */ + { { 0x0e1d9055450cc69fL,0x50eb14bcc9edf98fL,0x1bb94e77ee7eba01L, + 0x5f7a6737998f8e53L,0x588384e31b16eef0L,0xbb928723d85c5e15L, + 0xfe51e345cbd952aaL,0xc5d0ee287e241674L,0xfdc146ef100182f0L, + 0x0f739e92e7f5be2cL,0x501ab3afb656bd3eL,0xb1552dde5168e289L, + 0x940dfe31b8ee104aL,0x42923603c4304475L,0x9306f114c460a913L, + 0x5bfa9faf03b51f86L }, + { 0x2a23f52c107b258eL,0x989e82bbd66341dcL,0x54a3ced8823cff1aL, + 0xf45b7794719b491fL,0x898c22182433dfb8L,0x0f9dd91cc49250eeL, + 0x50c2a2ae4fa17655L,0xf7aa1ce42c327f45L,0x13a15ad6583b1e41L, + 0x9aa0d5a5a1bfad9eL,0x9b1caa288e1fbdcdL,0xaf9283b6915f7f87L, + 0xc10e4e0c87e81a1eL,0x04fdca561080d296L,0x6acc961612755bd8L, + 0x1b1266aa828feedaL } }, + /* 237 */ + { { 0x4ebc0a00774ee49cL,0x776f6852cb6237d7L,0xfc0544ac5df938a3L, + 0xc3388ec8b6fbfbbdL,0x84ac8bcd745f2eaeL,0xa9c56609b1ece937L, + 0x656fb6ac7de8fa13L,0x5f8ded74a532b871L,0xab0d428baa889f09L, + 0x43b27f2810b7aec2L,0x26426e1efeecb34cL,0x44431b6b9e89c2dbL, + 0xaac4bc5d39211090L,0x926f73684fd81058L,0x452fa691471ef60eL, + 0x33517fdb218d7a23L }, + { 0xa9c33f46593c4a36L,0xac69d71836b1a9eeL,0x55a20c1d4277beecL, + 0x3e8ca24e7e4f179cL,0x57373369d46d88a2L,0x71ceb1cc730702f8L, + 0x8b184d9735eed574L,0x7f4517a20704cec2L,0x7f129d18d7062a53L, + 0x07a4571bb1d77e1cL,0x774ac3098350d8b2L,0x27b2919f61fab8efL, + 0xa7c4cc13b5dd801bL,0xe7e6255b1434591fL,0x349937b85a3592b3L, + 0x31fac63d30c77549L } }, + /* 238 */ + { { 0x2ee8cf1b04913fb6L,0x7e4013501769a6b3L,0x790ebb71783e61f0L, + 0x1e5107f9e27f2ffeL,0x124ba67fedaf89bfL,0x189200e1e58de68dL, + 0x962732a36df5abeeL,0x72cc37cfacbeb4aaL,0xb0c5fa96e93c5a76L, + 0x4c2a317cde63393bL,0x97f65e67830b2d6cL,0x4afc35041be5b96aL, + 0x0bf40a60730ce66dL,0x96a1ba799340d84fL,0x3ee1825407626b08L, + 0x01db35db7ab0cbf5L }, + { 0x6e0fbc2dac0efee2L,0x8406ebcdd71dbb45L,0xe72bde3e19b69abeL, + 0x49cb7e6137e01822L,0xcbb8c01c11458b4cL,0x420b4847687c5d63L, + 0x1847dfa1454c6776L,0xbede911dd1839d18L,0x1b9dc9c9278df046L, + 0x294bd62b881a336cL,0x7f09687993e77adcL,0x7ac9066543ce3ba7L, + 0x148695fd7764eefcL,0xe0c20f0b9ac465cfL,0x636e8d28a6e2cdb1L, + 0x7b6ba98cd755341dL } }, + /* 239 */ + { { 0xcb1d9e03c1881ab4L,0x19c25d55b3168c88L,0xa82d3d47282364ceL, + 0x95994390f161aa24L,0x7838bc00e1ebb2c9L,0x8fd5dfccbdec7a75L, + 0x4dd203c24ff7220aL,0x5ec173b30efeff48L,0x99f1d2b316428b35L, + 0xc06bd9e5056e813fL,0x929172bac0b319f1L,0x6ae0e384fd223b15L, + 0xbd01059e98d091edL,0x6b3168e4a654648eL,0x2211447f3375e798L, + 0x47e8101971eb4508L }, + { 0x7045d45abc8c290dL,0xa33d1355810fb33aL,0x2baf009246fbbf2fL, + 0xacff3f1b385c7cd9L,0xc5b150ece161985cL,0xc6ee0a7f2a888748L, + 0x9d888c8e5e88dcc8L,0x4dd735f2ccb86443L,0xcc1e13b73c40f6f2L, + 0xfc3a25fff3fed691L,0x4cb43b17257ee5c7L,0xaa654f93f32db135L, + 0x44f58d0a02dff2d3L,0x78e3f188a8ca6394L,0x39646ccef3e86697L, + 0x785b1902e0dce87bL } }, + /* 240 */ + { { 0xfcce2361a92f9a20L,0xb7bdca879d64540eL,0xd4739a851d00d7c5L, + 0x067ac8dc2e97c926L,0x2aea3ffe78da6a8bL,0x6828bf5463c51b69L, + 0x76f1c4797155141aL,0xf4bcbef63977d810L,0x75bc4949541bce7aL, + 0xe01f4066d17041a5L,0xd282d5bd87755eafL,0x6e2107dd59e7ae80L, + 0xaa56e166382ab36fL,0x65ee8ef6b9d1d634L,0x99a2160ace4ed844L, + 0x6557c367b7712c27L }, + { 0x561b0268d75b6e52L,0xb0813640118d0e89L,0xcff533306a2eb1aeL, + 0x4e4622266d090894L,0xbb351227b5fc1d48L,0x9365ea0757a3062dL, + 0x4caca37bd66e2dc5L,0x220d7d23b9095887L,0x9c0fd3938c4473bfL, + 0xadff370a6787da4fL,0xef0aebccd057f4b8L,0x205e744c1173f33aL, + 0xb8d1f0a5925a26b4L,0xa9364f49722fbbfdL,0xc891ae778227d284L, + 0x15c40d04a0e08ab4L } }, + /* 241 */ + { { 0x9baf169a2a0e18d1L,0x9971c0174c0327c2L,0xd81a323f7bc262ceL, + 0x2099db8d818ff379L,0x663f663d4cd3c330L,0xef5325c3011a0553L, + 0x9cd70bdcf980a470L,0xe64452d11c9ed070L,0xafbf43f4ac676e13L, + 0x97bec0a6ae85c2a5L,0x2faae550470490c4L,0x0ab97a87491e6ba9L, + 0x4055f537aafa9914L,0xfc95adbb36726557L,0x646343b9d119d6bfL, + 0x788e94a09d341e37L }, + { 0x053a6fe59c53461aL,0x75ec897e08e3b6edL,0xa8f5d2f30768d939L, + 0x9bd6bff6cc213d4fL,0x590c7b4105b0147cL,0x20a3628b7c7b8169L, + 0xc66a086e5bce78e9L,0x3dd4d2824dec1d8fL,0x890acf44c19dcce9L, + 0x6632d875d8435a7eL,0x590167c1ea6381b2L,0xb2259797f0dcc128L, + 0x91a612b446f8d463L,0x42185d78c15efa39L,0xdf55ec37119f6788L, + 0x91b19cc6780dea93L } }, + /* 242 */ + { { 0xebf2709dcb5d8b80L,0x03b96182fc35660eL,0xb873d991055ef969L, + 0xd1ea4b4de47c4342L,0xcc4b9244d54f8867L,0x93b1a2cafd8d77efL, + 0x068d24e7e8c1f563L,0x5f5fabb649973056L,0x83248c500542374fL, + 0xc36de2b53f38e913L,0xed07e8eb7bb680beL,0x964813d7d8f313b5L, + 0x7bb6a069afd2d392L,0xc06d848e0848a31aL,0x6867fb2fe4f0c325L, + 0x3c2ba834067343afL }, + { 0xab62d7759d3ad63bL,0x3f9cab9759e0eb1fL,0x70332a633885e117L, + 0xf22cafcee20b2f9eL,0xb529ba7e49eca947L,0x249542166228d88dL, + 0x80ea23ec39239561L,0x1b8907e7d4370644L,0x4b7fa455563e4e44L, + 0xcca9829eb2a4b0faL,0xd0a720a448060792L,0x8ccdda0c246991ceL, + 0x37a2325b348d086bL,0x566ed509f60aee13L,0x3d30e091147f253fL, + 0x1fa627a5c1073bd8L } }, + /* 243 */ + { { 0xa11222a242478fd4L,0xacf4c6f1670b2000L,0xf71bb04f8359c6deL, + 0x618e28297b93cdbcL,0x96e1bae3230db60bL,0xf17fd3b4965b3b29L, + 0xa58639c6bc7055ddL,0xc3ea92ed4b817d7fL,0x9082b2a6d23b08a4L, + 0x8471228adc17010eL,0x753b9e4620e89d97L,0xcf7e4f9703ff77c9L, + 0x6c3f82452bbe60e5L,0x9e432cbcb80e017dL,0x150a5acdc0a45edbL, + 0x67b8bd054798743eL }, + { 0xe66079b4f4797cf7L,0xe31c998ad03fde02L,0x5aa3763a54caaef1L, + 0x64d9a1fef7649711L,0x7ce0dc73af29b1a7L,0x6661b083fb66ca93L, + 0xbf4d74fe32fb6a78L,0x25f6ef09df00a561L,0x2bc4383f831d1159L, + 0x6d5cc10c536bde37L,0xd4945f9f882cc65bL,0x81f48f13451a99b8L, + 0x140161cd6bac11a4L,0x9d94d4edf18a4a0aL,0x65363165a467a824L, + 0x74297aa9a4c9aedfL } }, + /* 244 */ + { { 0xc49758a4e21124baL,0x99bd8198a87ffbd2L,0x45fbcdd13d6638a8L, + 0x94645ff815f7bf76L,0x5fa6736fc4e6d57eL,0x1eae647592e61db9L, + 0x79575c0ccbdf944aL,0xa3d1304725b31d74L,0x7881df224cab5ae6L, + 0x8dbfd2991a2887f2L,0x23d07590a26ac459L,0x2e589852d8661d4aL, + 0x37b5c13b8a0140f7L,0x0f94199e3fb3782aL,0x722aa0591bc14e90L, + 0x89aab7bad55bbb12L }, + { 0x8b345a96d656bdc7L,0x43bdc8afe176cd3bL,0xd69518b632d64c43L, + 0xfcf364a779b82b41L,0x907b344effb0cf82L,0xf3d0c83c5101287bL, + 0xe9f26a5934cd90efL,0xe5f5aaf207082b5cL,0x4eb72c75ece7c165L, + 0xe9590a81be986cd6L,0xfeef498fff1536aaL,0x04560243a8263d5eL, + 0x940be14f54ae872bL,0xbee7bcc9e3207686L,0xd496a27dc1bc4d7aL, + 0x002dc2975940ab46L } }, + /* 245 */ + { { 0xee533937b69d60c3L,0x260be552fe972755L,0xb11fb78dc0c725a6L, + 0x6982c27ecab2e7c2L,0x4bceedd9ee2322cbL,0x952b19ed122704f7L, + 0x2df4c285854a6165L,0xba40b5bf7b192485L,0xfcbca9500119f52aL, + 0x7467d1cbe5add86fL,0x9bf536fbd9d0f2c1L,0x3c296e34b8d4ebc9L, + 0x0495f8f405a81317L,0x8c59e8d673335f76L,0x0b53d324e0542122L, + 0x4d5645353c3bda73L }, + { 0x7322f8007e5c0877L,0x481b43e60ca9a764L,0x231f4f4ba2c12716L, + 0x09596857ed3136c2L,0xae82632238db30deL,0x652fad4099908ebcL, + 0x0b8d1814af0d231eL,0x2680c54b09cbc349L,0xfd4562f34bf3bf8eL, + 0x2985090b092b595fL,0xe6f39ca45e15fc34L,0x70175191bc378168L, + 0x906944b3845a4a87L,0xacc6d74a82a1541aL,0xadc9bab3b155c8b4L, + 0x1f2f89ce77306c62L } }, + /* 246 */ + { { 0x8253ef419affefdfL,0x05d7ece54cf9256bL,0x377002f2b444e483L, + 0xb189755fcba5471fL,0xc88483cbd5cbe015L,0x254f7c696a0b8429L, + 0x18850bd461f3f61dL,0x7ba210890a247157L,0x35abbc2ed92eeb0dL, + 0xfb56cabe965dec89L,0x9da23724bc55684aL,0xd8ba396f6a7a7492L, + 0xfcb90db72ef4ba46L,0xdd234fe09909b27aL,0xbdf3c16476f4366eL, + 0x09c8097f17e50d47L }, + { 0x6a04b14060050c07L,0xc29e831843a8e37eL,0xcb9429b2bb55e41fL, + 0xed2fea5a2ce60e3aL,0xdc7b1ff3db9d82f4L,0x48ebecc3687d37faL, + 0x79153e32ecb07539L,0x6a60054f57075692L,0x3871cd0c800759baL, + 0x17a7386f30922df1L,0x4e9fc59e83357b7cL,0x1d26b3a939415186L, + 0x912a0222d34db889L,0x6672fcf459fcdb71L,0x5a3f268d44ff3036L, + 0x6f113ed36911e16cL } }, + /* 247 */ + { { 0x52a9df591836f1c9L,0xfa6519f54232307dL,0x8406c7015ded285aL, + 0x0a1545caaf627f75L,0xae1111eeace0417dL,0xfb28bdf6a6113443L, + 0xde9ef0ab52dbcbcbL,0xe9dc181b7813e658L,0x0b1dabdb99127225L, + 0x5f0598e322814c59L,0x5c3b966ed934ee7eL,0x4eb84edab99ba4bfL, + 0xb2919a343c1b55e7L,0xa9addb4994aa860fL,0x1b7220dff6811ff6L, + 0x6636a23bd1a183e2L }, + { 0xdf5d5a2d20587283L,0x0b3822c9ef07fc5dL,0x1786bd550ef6de38L, + 0x163cf90725d1671dL,0x74bf971f1cdb1defL,0x5749e8300842fc4aL, + 0x0e2edbc727f854f7L,0xbb27bbdabce24acbL,0xc1b19cec05bed08dL, + 0xaada123ef7c904bcL,0x02429f1bd89982dbL,0x49d3616e65f6e632L, + 0xa3789fa8ee59fd32L,0x160ba3bafe9f29f5L,0x0f2d3b61af5378a0L, + 0x7aeecc7673c2a6f8L } }, + /* 248 */ + { { 0xf3a4757cdc43b0dbL,0x3d8a4e8598119cadL,0xf8095bf64616c156L, + 0x3e2a07bc4f533e97L,0xa982436739cfc5adL,0x18a6ba3acd68052cL, + 0xbd60e5908a1cec66L,0xae3841a502b1b695L,0x986dff12190a195bL, + 0x2df2beacad31fd9bL,0x7d893224cc728f7bL,0xc38ea7380cf0a992L, + 0xa8439a80586a44eaL,0xede7f7f01615f03cL,0x4824990827a1f885L, + 0x28ec4006b78a7645L }, + { 0xe1820c2ea2fe0009L,0xe11ba5d2f13874e9L,0x97522454c524db52L, + 0x4d4774267fede529L,0x01d3419a9b2500d4L,0xce08a4921869244bL, + 0xba169023dd1be1b9L,0x242c3e5432a301e0L,0x9b56f7ba70906788L, + 0xf0ad2a09c74a8cc4L,0x99cd1841d76f9439L,0xeddafe0b621fb60eL, + 0x056bee54bc397634L,0x4653f860ff7f0a84L,0x6bd4876f2011c0afL, + 0x134f4cc70c9525c3L } }, + /* 249 */ + { { 0x9621a3ece938dff4L,0x7d101a7b486a79a3L,0xf2c4ef97de950537L, + 0xf3184099e65d87dbL,0xb89c7ffb373b8cfaL,0x68baa505e842916eL, + 0xa790fd094ebea764L,0x679df6d4e592892bL,0x2023331cfcfed741L, + 0x0bf4efd29880ff21L,0x7ca78dddd0344501L,0x2cb09ecb342858c8L, + 0x9e5eb6dc2575487aL,0x50675a15ebcb0491L,0x09d2e74f7381d471L, + 0x6ea3782983d3d6f4L }, + { 0xc65c094b4e5cc40aL,0x7a2e3f6a1af37dfbL,0xef677e9df9026e44L, + 0xb7878c9593880f53L,0x4aa30b077f644aa9L,0xa0c516832f208c3cL, + 0x7c0277ae658d663bL,0xef0b3c38ae1d9130L,0x302f37a7695c3ea4L, + 0xe004c1c56a0c5e0dL,0x9fd495c420cbcf9fL,0x706d5b9d568a0e7cL, + 0x8b225dff59286454L,0x527d44658d9a709cL,0x47c558da87c08d68L, + 0x606ee6e6bb4ef07dL } }, + /* 250 */ + { { 0x02d99fc757c621f6L,0x292e40c17fe83d48L,0x1bdfc7a19ef199b0L, + 0x78a04102e62c7666L,0x16cda370e6738753L,0xbc81974d1e3a65afL, + 0x19742048f78fe209L,0xc83a058abf5981c6L,0xf26b24349c89702dL, + 0x988b2f1e9d1a678aL,0x472bf9b0ff29ae29L,0xa143e3981d7cf5ecL, + 0x9c9d7e45b268ddd8L,0x166cda555fc4ff76L,0x6044cdf0a4aa7673L, + 0x49dba6f7e9148707L }, + { 0x20e47fb2a758e37aL,0xaf6b31d72d8eaf66L,0x352ad5f96f9c2210L, + 0x0093f72790efc32bL,0x435c99dc41e4b264L,0xbfa878e005b15795L, + 0x99c520a40e673575L,0xca68259487eea759L,0x029f7b81f12a348bL, + 0xa547cc182aa2ce35L,0xa11d874bead5e2c5L,0x9af0349b55682cdfL, + 0xf86ebfea8bbe8e66L,0x3dab8782f55394abL,0x458bf797ebc8eb8fL, + 0x4890a7a49b7de78cL } }, + /* 251 */ + { { 0xd72996898da995f6L,0xd39eaae7ec6156efL,0x6959040c356a82d5L, + 0xb2046b21c135bcfeL,0xea720b640f595c78L,0x02824efae7c5fb40L, + 0x97d8fd4c0edb3bfcL,0x12f0290579f24ebeL,0x16fc47cf187ea6b9L, + 0xc219fd27789d5c23L,0x233a6b6c89263eccL,0x823634b28b6d30a6L, + 0xca352e25c9b33680L,0x9388d6ca40c77456L,0xf8e55b0b3c92065bL, + 0x5c17474b02439a76L }, + { 0xd888e7c28aaccab5L,0x18027836aaced05bL,0x185b877dccec0f65L, + 0x93cadc1c125c2882L,0x45df540a67fdc54cL,0x4f3c86e2c2788a33L, + 0x3e874469e3a0fa2cL,0xc59daa47273983cfL,0x3063c48b4a96d8a5L, + 0xc38d2bcfc2e58915L,0x90e78b8784e428c3L,0x900a292cf0c4fd53L, + 0xb7f92db7941e6005L,0x956792416ca53a1cL,0x35f6f31db1ab0fa7L, + 0x5d675eb47b58408cL } }, + /* 252 */ + { { 0xaeee1a77870c6025L,0xfc4a23b791a2dfcaL,0x7b0e60c4386b64c4L, + 0xd5d5b17de5ae72b1L,0x6dfc88ac9eefa212L,0x4feaefbed4038b96L, + 0x099ac3568e2d2eccL,0x548ea612012af207L,0x4ffed9db89c31218L, + 0x1c1e91c4e0e67331L,0x009bb64faf8300e0L,0x8780501c6773c3beL, + 0xe0cd6edec08219faL,0x7c055e07f81b06ffL,0x82b63f9ce080b36fL, + 0x02fccbaf0a9feca3L }, + { 0x9991d4d1b47cac61L,0x2e9d1687ab86e12cL,0x8c6855ec2b94f042L, + 0xca40051948e648e5L,0x9ba91fb2ef89ac57L,0x4f4192061be792cdL, + 0x82d221cbbd0f1e15L,0x062eb13bfc444019L,0xf3a97c3299790fdcL, + 0x4e796d946067a64bL,0xc46dd3006d23775aL,0x8672c4d5ed7f0f23L, + 0x821851dc3b4f63d7L,0x50a3ae0cd26273f2L,0x800e58fceac60f6fL, + 0x56f1e45613845545L } }, + /* 253 */ + { { 0x01ccb3f632c24f3bL,0x99eb1c7f06d817e6L,0x8dc640bb6aa26776L, + 0x7838affe0845d5e0L,0xf34fecb1f81a79a8L,0x6a2e282d3e6819b0L, + 0xc4b977ce8237a4b8L,0x0f46b3db87636439L,0xa465f54097970497L, + 0xd7e087628791be43L,0x00220b6c34198ec6L,0x57b38637093d94bbL, + 0x84012e1629d690b2L,0x02ec9db520aad1a4L,0xafee2fc685dc34e3L, + 0x911d193625500cf8L }, + { 0x13b1bd58f5e5af5bL,0xa7ca263b7b6a22a7L,0xab6bec4df3af2adcL, + 0x16651e59a04420bdL,0x3b448b3b4ba36c11L,0x3c62bfcdff424310L, + 0xde15c4a5f1a96cbbL,0xbe0ad8a1e4d1f980L,0x812bd14e36673a3aL, + 0x40303af69212acddL,0x8f6dab9c576095ceL,0x7df1882a107f5ca5L, + 0xb903e63c8896a3b0L,0xf5048544d863b3f0L,0x5e5019b9c09887deL, + 0x2be744fea0f53865L } }, + /* 254 */ + { { 0x054cd05f5b50f324L,0xb9b1eb241ea3c7a2L,0x4a858a5c7ff8e6b7L, + 0xd83902feec040882L,0x72b26494d0cba9bdL,0xd0176f90b29c9e1eL, + 0x05d4eb02cebadb81L,0x874405b1372b8bfcL,0x5c41288179ead190L, + 0xd44a3dd3ec2b48cdL,0x84499a773f4d5033L,0xb37b38cd564c3a09L, + 0x80e99497f42e803bL,0xc07b47a0b8f518b2L,0xc710e3c53568fde4L, + 0x735f542fcead0e7aL }, + { 0xcaa9a17138380039L,0xadfafe17f74d19c8L,0x92d4393eccbc1a8bL, + 0x3c5dbf39fe029705L,0x4552b5ab930e9b36L,0x7ee630322afd494aL, + 0x826a9ad73f02ac43L,0x98c5356299356298L,0x0c869f877342bb39L, + 0xd7510020e4f9b79aL,0x6361d1a4d34789a9L,0xf0ded5bacfa85637L, + 0x407ee73f88ac07e4L,0xfac7d03f09ef1cbdL,0x25d697cb4d475badL, + 0x1e984c9d14bd399eL } }, + /* 255 */ + { { 0xc76d05614850c817L,0xb08a5b193489812dL,0x7273d1545e58cbbeL, + 0x8900b5fa4be61e5aL,0xaa088691d7aeb8e1L,0xe66666afd35a3d4bL, + 0x38a2c19957ec7d3dL,0xa0648e8f668d6f5cL,0x1f9fc92c7adc1746L, + 0x23a116c0843065c3L,0x36370a2061e6ae69L,0x626c37362aa47e73L, + 0x540c25f2deff6d84L,0x9804824ccdbed2d4L,0x4b5bfce0039a9492L, + 0x6c474a5676942e01L }, + { 0x3aeb9a417d88e3a1L,0x105d3c88c484742aL,0xe59de8d13fe61131L, + 0x148f5b6b1a869e8bL,0x7a8abc59aa75d90aL,0x2f0c9bc762146013L, + 0x43faa747c3824cd9L,0x81763a186a5d0b92L,0xbbc341bc9bcbaebcL, + 0xe1813160f745d1ddL,0xa53ce52db75ce5f4L,0x15eae66cd50de4c2L, + 0x5ed8996c75d7656dL,0xe4ff5711c4ca552aL,0x215e985a3c5305b4L, + 0x6b258954fa1ba2ceL } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_16(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_16(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[16]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 16, km); + + err = sp_1024_ecc_mulmod_base_16(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[16 + 16 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (16 + 16 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 16; + + sp_1024_from_mp(k, 16, km); + sp_1024_point_from_ecc_point_16(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_16(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_16(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_16(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_ecc_mulmod_base_16(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_1024_proj_point_add_16(point, point, addP, tmp); + + if (map) { + sp_1024_map_16(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 16]; +#endif + int err = MP_OKAY; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 16, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_16(point, gm); + err = sp_1024_gen_stripe_table_16(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[16]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 16, km); + sp_1024_point_from_ecc_point_16(point, gm); + +#ifndef WOLFSSL_SP_SMALL + err = sp_1024_ecc_mulmod_stripe_16(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_16(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_16(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_16(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_16(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_16(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_16(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_16(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_16(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_16(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_16(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_16(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_16(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 16]; + sp_digit tx[2 * 16]; + sp_digit ty[2 * 16]; + sp_digit b[2 * 16]; + sp_digit e[2 * 16]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 16 * 2; + ty = td + 5 * 16 * 2; + b = td + 6 * 16 * 2; + e = td + 7 * 16 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 16, base); + sp_1024_from_mp(e, 16, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 16); + sp_1024_mul_16(b, b, p1024_norm_mod); + err = sp_1024_mod_16(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 16); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_16(tx, ty, t); + if ((e[i / 64] >> (i % 64)) & 1) { + sp_1024_proj_mul_qx1_16(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_16(tx, tx, t); + + XMEMSET(tx + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_16(r, tx, ty); + err = sp_1024_mod_16(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][16] = { + { 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L }, + { 0x170a46d2335c1685L, 0xeac9e971e1007a58L, 0x40e8f3df43ca4a73L, + 0x2646f81582642475L, 0x3af49bb4b36576d1L, 0xd89e2d1472bf1afbL, + 0x27be882c2fd151e6L, 0xaddedc858f88717cL, 0xd6d859bf16ac6c6fL, + 0x0e741a1b2d8eae58L, 0x6faf7a0061c1f30dL, 0x66dbd09a9b67e096L, + 0x21f11c067d3b4f7dL, 0x6152ba02c727c98eL, 0xafd58891e86cb221L, + 0x59e93c6a6bd3baf4L }, + { 0xe54dd36f71dd4594L, 0xbbc9cc9f00aef1e6L, 0x9ea5a44ea19f6530L, + 0x8588aa993f520928L, 0x9753794c8f5c1418L, 0x118bd792c11399faL, + 0xb9bd3afdf5cb6ab5L, 0x813d1cb22ecb9652L, 0xfd45626740389813L, + 0x51f7119b4ac8431cL, 0xdd9f6a910a180eb6L, 0x13946d179f7bfa2eL, + 0x16f1863150a9d0d9L, 0x5f19c20d6f8373d3L, 0xbe85ac6a9b6a52b9L, + 0x63ef187b74f62e03L }, + { 0x7c376b7f016f45e7L, 0x1c1bdb572bec82f8L, 0x7392f741ce429b60L, + 0x6fdbf0a2c7afd81dL, 0xbda41b1f7241098bL, 0x5b407474bb60f8cfL, + 0x933e0d41b330bc4dL, 0xae182830733fa3beL, 0xa0ed299b0f5c6cd1L, + 0x7ff3354e3f9860c8L, 0xb136098615559c41L, 0xab0cb63c129f85cbL, + 0x682ecc4947685fbeL, 0x505e8ec2eb199633L, 0x90dcc794ddac2cdaL, + 0x4fe6791cf192da23L }, + { 0x94a423d505e8733cL, 0xcc845e651d5717c1L, 0x237c7e88e961b322L, + 0x0c4471c6db4181ccL, 0x00c875e2713bd721L, 0x9dfde9edb2c17b09L, + 0x430a6de5e88ceaf6L, 0xaaa7a61a7b81cea6L, 0xea52d026233f98d5L, + 0xb55efdd060689a9aL, 0x30cfa7ce5cac4aabL, 0xfa4db1148e950761L, + 0x309570c44e9a1e52L, 0x18c21f611a040170L, 0x555d1ffebe78d9d2L, + 0x04482a18561db297L }, + { 0xe7758ac273d486d8L, 0x8169f94661cdc1e7L, 0x723c99fc2188ab4fL, + 0xa0e54f02f3373630L, 0x560bee25bd8c2260L, 0x28fc307c4531bc60L, + 0xd6f21f1a7e44feb5L, 0xc8e4499c57128d37L, 0x963b053ed7b2ea45L, + 0x40c27a0432a3d222L, 0x5b51854d35459668L, 0x66e1a49fd73557e9L, + 0x0d267fd98692077aL, 0xfa1350d3e7342702L, 0x1a9c3f2568ccdb44L, + 0x833a0ff8dedbf89fL }, + { 0xa8c419c7ab376b76L, 0x3b7294f327d0f0ccL, 0xe56bb9e2a90c514dL, + 0x931ba51ea62575a6L, 0x56fee07b098c0a88L, 0x04be5aeeb4c16a2aL, + 0xe513350be6eb260bL, 0x339edad6a1d5c270L, 0xf366ed59e9dbadd1L, + 0x4213be882dd06ec0L, 0x22d639c8cb1187dbL, 0x1fec95e1d8a1058aL, + 0x03f73ea6a2b744f1L, 0x741fd51af4f05c0cL, 0x2e2df95a85f811a0L, + 0x692b3ce3eb24965fL }, + { 0x0ce6cb72d2a127b4L, 0x66a46ea58f92816fL, 0x43ecf46347a37616L, + 0x163d9a01e0ab96eeL, 0xc8145c6db2edbe8cL, 0x2f426cae4de4e665L, + 0x174d0b4074e252f9L, 0x54c240d77d2af831L, 0x581fa3973d652936L, + 0x05b9491ca09d4695L, 0x8c4e85335452643cL, 0x32d64331d4128327L, + 0x6447903870361f25L, 0x774191b189ef09f2L, 0xc0cf0aaf81de5fe0L, + 0x333e430af40042d6L }, + { 0x5df04de4cf26d3b7L, 0x57a77306b53f79beL, 0xa4013c5f1808b664L, + 0xef291ea485037360L, 0x1ffc9d7d0b061037L, 0xd9d04dd965c913bbL, + 0x948a37aff13b8587L, 0xb5443483fe3ee755L, 0x3fc21e7404631386L, + 0xb3a104e5cddeb58cL, 0x94fe18626572cd52L, 0xeb9a71a115aaa408L, + 0x8adc6fe5459ea462L, 0xbb18d1754aeb02a3L, 0xae1276362f7791d1L, + 0x10e8b31dd6bbd708L }, + { 0xb87f03e53ed9f1afL, 0x03ad247756676166L, 0x38dcd63074ce15b8L, + 0x1877e2b026b1e85bL, 0xb1654d171af99c15L, 0x9782e9e49382547aL, + 0x6dc7fc7c26d55ef5L, 0x9038f95d2fbeb54cL, 0xfe590dfe036c0357L, + 0xcfcb6eae4fdc3f7fL, 0xcb1fbc54f35e1a88L, 0x3c8e1db2da0a5568L, + 0x9a87393f5b6f5557L, 0x38646b32e7ac0a06L, 0xfd261c832a8495abL, + 0x6485524c0cdcc4bcL }, + { 0x1abfb3e2c4a6ff2aL, 0x2aa03fba35a6428aL, 0x884227f089aff742L, + 0x2337883aba5dbd93L, 0x38186ae9d2a182cbL, 0xb9f0764d49a01f05L, + 0x92411feb917b1e7aL, 0x700b1903570cbb5bL, 0x5d5181d5b914be7cL, + 0x135c44371981182dL, 0x32758d24574b9997L, 0xa650a8f5632d28b2L, + 0x24078bacfa383f09L, 0x6546a60c00a33d80L, 0xa4061c7a2df8b449L, + 0x1f76f3f2f234563cL }, + { 0x9aa2c14344c436b0L, 0x790705561f69c87aL, 0x35f3117b5f6db2dfL, + 0x85761f41ed56ba82L, 0xf831464f7d0afa48L, 0xa99f29153adce71eL, + 0xb27bf693116b7488L, 0xa98a5a8c9bb9443aL, 0x7f8780262ee5fde8L, + 0x3a6f93dd1812acb7L, 0xaf92a4ccdc84bc92L, 0x3c2562aff1d4995aL, + 0xfd9fc33c04ed899dL, 0xc028ca944ed2a538L, 0xd0f367bb049ea726L, + 0x04924ffb3d108e05L }, + { 0x06548e3dc673562fL, 0xd3b33025e2eae48cL, 0xe61fd32b5e1c6977L, + 0x424e20646ebe557bL, 0x767391c041d6e18eL, 0x4b8ebb8e14d7e95bL, + 0x4ae8b7d420991b8cL, 0xf8a0df66e01290d3L, 0xc97e24a3925e5f4eL, + 0x79a7b2cb1508272aL, 0xb40b072e25072661L, 0xdad9e1829062fa49L, + 0x8780a784f3c53bceL, 0x58a82b769f142799L, 0x08cd849cc1468426L, + 0x4dfce809c380ae35L }, + { 0x45069cb2d527b780L, 0xd52da015977930ddL, 0x10cc600be27d0263L, + 0x34102c26bb2d1b2bL, 0x4c652623554adf3cL, 0xd689138245f0ff47L, + 0x83fa8cc5ca916e7cL, 0x1e10f139d15c8d8aL, 0xf173dc2e81dc56b3L, + 0x7fcecb045c4ed9baL, 0x307fd7d847d01228L, 0x24a571539f3a532fL, + 0x59e9e81de2153c22L, 0xc562595de428a408L, 0xdc7daff89339bd23L, + 0x0d075908b8a06802L }, + { 0x870af2a7de085f2aL, 0x88fcd24fbe99b2e5L, 0x88c0d26159ca413bL, + 0x1f02a2e48559f851L, 0x83b96021f622da0dL, 0x5c05c2f56dca3615L, + 0x0148cf1c7910c682L, 0x392f2896272695beL, 0x883d0bb5a8d64ef6L, + 0xef0d22441cfcbc52L, 0xf5dafcec526117e5L, 0xb68612b9f04928e9L, + 0x283f744d393f2e2aL, 0xfbeed7ed700c1151L, 0xf2cde215a4360dfeL, + 0x24fa961c2f08535aL }, + { 0x0767db3f616df7f6L, 0x643057d8fbd90326L, 0x174daa906e82d544L, + 0x2284f345689643dbL, 0x18b191dfcc89a060L, 0xbab46af4d6c27d12L, + 0x5a57f486c9895145L, 0xc03214e9cc942f9eL, 0x273e1c8f41950158L, + 0x8ceb759f39ad43abL, 0x5e1b8b7fe50ee173L, 0xf635b1fc8f4d7d4eL, + 0x8eff77e3755603f3L, 0x201f61d17752fa60L, 0x94d7a03d4a6fb6e1L, + 0x371cc23dfc4f0114L }, + { 0x289b115dda90c351L, 0x6d196ebf364d9c06L, 0x77a89202f650b31bL, + 0xcc28c1646f57642fL, 0xdc4f7e3608100127L, 0x8836cd08dc4c807bL, + 0x1280f156e00240f2L, 0x3f9a6d7899cb3953L, 0x40a494d33a802038L, + 0x45697e91e87d3474L, 0x70d97d0726dde24aL, 0x06f6a58d7640c30eL, + 0x03c2c0e85ba6e6c6L, 0x330f6a7af1bc13e8L, 0x3e602e4fc9f4d78fL, + 0x92b6bca00c80fb7fL }, + { 0x2e3d5c835f00822eL, 0x0e825712b8b16f12L, 0x81c329c492b0a330L, + 0x6b4e32ada7cc1954L, 0x0bee9cee1bb1413fL, 0xedfb7baa4a92ca27L, + 0xcd472afaea3b9153L, 0xe8f09e7e00f0c0f9L, 0xa4e1d8725cdebb70L, + 0xfe2bae084a9b63b6L, 0xf40141b83fd58f65L, 0xd7ec5edaa3b62759L, + 0x9aaf6e67790e3088L, 0x215ad8301f277e31L, 0xe7db4b98cf33871cL, + 0x71ff62c94f02f89dL }, + { 0xaa4c71022a4a84d9L, 0xe2ee4acd5ebc71e6L, 0x3b11a8a5f1cd6578L, + 0x83f5ef9ffff120a5L, 0xa4c598e109e65033L, 0xe1e9f990ca044180L, + 0x8b832d46f59828c1L, 0x753f28a033af536bL, 0x92edc4b1b6d4f68aL, + 0xedde692a72ccd1f0L, 0xd3aa0f7dd2226432L, 0x38dbb63ea3d2661cL, + 0xf1e19fc6fdc37ddaL, 0x6c18b35084ef6b4cL, 0xe6a83fe9df1bba69L, + 0x40fd47e75f958273L }, + { 0x5b88b746267140a4L, 0x6dbbfc1eeab6f2fbL, 0xdd9ec88e69862548L, + 0x69beeba12eb6efc2L, 0xcfc2214a8ac8ff88L, 0x95d5c96eb5a21950L, + 0x93389c054171fb69L, 0x2d85d4521b468337L, 0x14d68a084113425cL, + 0xe52c0139ec6c2174L, 0x20cf0b97f730084dL, 0x1ac16a261f578aa3L, + 0x18b9fab3f9b6ae43L, 0x68d82111d854a695L, 0x0b334d98dffbe286L, + 0x5b1c1157e639338cL }, + { 0x90edaab172b6bb8fL, 0x8dc64ed202fc92c2L, 0xf42ba3c5fe694c73L, + 0x316dc65fcb54dce4L, 0xcb2d66a3632420dcL, 0x16e706e7056dcf94L, + 0x2809c764a4f32c9dL, 0xab18d830ea6edca8L, 0x4fd1ace681c65f57L, + 0x1f91651c7da12c10L, 0x0ac3bd66c7791a48L, 0xb6ad1cf4785e67a3L, + 0xe4d3fc44da0fd591L, 0xce1648016e1c6344L, 0x84de9cb833e50ab3L, + 0x963ab83aa756eef4L }, + { 0x944b47d8df4ea5a3L, 0x965688155cfe45feL, 0xd16e7d588a3c3564L, + 0x84e55b3ee7c99e15L, 0x3fee204df55071bcL, 0x71006f2904057dceL, + 0xfe8c390dbba75570L, 0x3645bcb63319adacL, 0x8189e8b07c20bfd8L, + 0x8e5509697d7d9578L, 0x037d1321b99f4e3bL, 0x011b2521a60cfb6aL, + 0x66594aaa837382daL, 0xc89b91fd83c1dc07L, 0x6b82b899076b9884L, + 0x443480fcbe45c558L }, + { 0xf8ffffb49114221aL, 0x4aec4f2e3e857a7aL, 0x42e2d0e40fa54787L, + 0xef3e6b31d6f96152L, 0xb2296537fbfe9b77L, 0xc2a9d0f2fb43a86aL, + 0x241284ed24572ac6L, 0xa3868917e721ba7bL, 0xdbef7c00c117a78dL, + 0x38149071d31605acL, 0xc2dada9e065a8ee9L, 0xd5b138d8c442be82L, + 0x9b6c224bf6d72b58L, 0xb9d355cf8eb03e6dL, 0xab6d1eb0a1700371L, + 0x97118a88cffaa7ebL }, + { 0xbf9c59a2cdecb5d8L, 0x8083c81ba93a6866L, 0x24e0dd8104774fbfL, + 0xe779a3caa02070b4L, 0x9d352fbb0fbfb781L, 0xa8b0d8203ef2a1c4L, + 0xb858637b14b3e501L, 0x5ba70a498a882ff2L, 0xa27300833b06efa5L, + 0xa42c02f4102fee2aL, 0xe4e762998a0223a5L, 0xdba2ba2685c3fc72L, + 0x554fe763fe52eae7L, 0x30b5405a270f45f6L, 0xd56a177aa573387cL, + 0x17c0778d4b71fa82L }, + { 0x0e6dff1d2735e37bL, 0xc9884e56656ec572L, 0xa2f5ac9d9ebba978L, + 0x40fa4518ba09f3c4L, 0x8c3fa177f5b04377L, 0xa1a1decd967a2ecaL, + 0x768bca700528bd40L, 0xf224952b18691c4aL, 0x16e12c45e86d5fd5L, + 0x7a0d915737859a6aL, 0x723f4309a0ffce0eL, 0x5a8db79ba96cc9a3L, + 0x6dd12ae01ad23a38L, 0x9ffec3a1e2bf5d84L, 0xd6ce84e1a452ed66L, + 0x1219d5c8571fe4c6L }, + { 0x43eaa67f262969ebL, 0x3a3ab39d2f03e773L, 0xe6127e5157bb0909L, + 0x0f82b0ed8d150274L, 0xffffcad8e580bdbdL, 0x51d3d075a9743e6bL, + 0x1484bdb18bac11d6L, 0x95cd9990eb24c388L, 0x216a61d07fac67c6L, + 0x4308f762a04e6b87L, 0x2865dd61cba57cc8L, 0x3c296b0dd234a07aL, + 0x76f928393a0793f9L, 0x70b57e1f0be29eceL, 0x1314a82f7e626f42L, + 0x2c8d7ab2d657f230L }, + { 0x67cf58920825e4d6L, 0xdf51eaa56ef83b44L, 0x63e665d81310108dL, + 0x229f89f58dd0963fL, 0x8c4b14dd9df6436aL, 0x99dae469d45ebba7L, + 0x118aab775a4df381L, 0xda8978bd29e37febL, 0x69ced5aaaca2d7efL, + 0x6c98d05dc67d6a8aL, 0x7474bf0d77f84a34L, 0xd4428b2eed8cd59aL, + 0xb0fd1cd5d1d398fbL, 0x596013db94a20b11L, 0x96eb705a1b404c44L, + 0x2299d2774b09d958L }, + { 0x5b9cd58dc64397e6L, 0xac198f1ebf6dd31eL, 0x5866d8e13e9f1db2L, + 0x405ae2878fcdc68cL, 0xa4b280cde53c01fdL, 0xdc963f2d411db5f6L, + 0xed5d5189bec4f8a0L, 0x336fd13d916ee98bL, 0x6925b1b3042df48eL, + 0x0cf56291ace0074eL, 0xe8d38b4825317e95L, 0xc7ad1d2b821c446bL, + 0x71c44135f0b65934L, 0x971b736f52ca0d50L, 0xaf9ffa5727b46c26L, + 0x21ac67791936618eL }, + { 0xab420e3f2d7fbcd2L, 0x1272247397bdfc18L, 0x492033f84df5d4b4L, + 0x6fcd42363807b7d3L, 0xdfc19b09b33c3625L, 0x13d6f375a0f22814L, + 0x70978a59037c19b8L, 0x4f3989970ff27b9cL, 0xfc0e1a45615a4389L, + 0xffa3496a3e602f74L, 0xc3f1c431b261ca1cL, 0x612211dbee0164cdL, + 0x30463ee4e7f7be9fL, 0x015f7e7892c2e1bbL, 0x663d88d624483a56L, + 0x0e8ec1e70e62d9d8L }, + { 0xa88ccc298a0878ddL, 0x99ac175d6640071aL, 0x90344820a5173617L, + 0x316d023edd58a315L, 0x30785bd488d221a1L, 0xb74b3de7959c48e3L, + 0x42ee03824c67a771L, 0x59ef6cdde0b91453L, 0x7830ae289b237e91L, + 0xe1847a4c495d8325L, 0x67b1217ed0773666L, 0x58192c86a294a325L, + 0x76aa0f56864d8326L, 0xe2a2bd12f4b13e5bL, 0xd850c1c01b6b73fdL, + 0x653a795f5d103635L }, + { 0xcfe2898550dcb199L, 0xb35b8e5e7fa02b60L, 0xbca7d7c3c97603d0L, + 0xb0e5288d27f131b5L, 0x3aa704dee2b12d52L, 0xe206b1d81db725c7L, + 0x0b12839ac5d1b113L, 0x14f970cbdb45d763L, 0xc997f93eb2125e8eL, + 0xbd75739cee7daa26L, 0x46ecbd3f1fef20e9L, 0xf994a1147c6a42b1L, + 0xd289eb4f27fb0fd1L, 0x11186d319a40da4bL, 0x083f65a5fb9d7976L, + 0x30dfc47bd444675eL }, + { 0xbcfc5ae29eaadfe8L, 0x25027e54b4d4e812L, 0xab0702df8b533561L, + 0xa2b9c20456a6a214L, 0xb1a3df7a3059068eL, 0xa3514b219883110fL, + 0xb7be2336c4b78e1cL, 0x17073ce63e2f6984L, 0x86e114a62ddf7ac6L, + 0x276192bf07d7c3c8L, 0x5da69e0beb1ae289L, 0x983af17525184939L, + 0x9ac52a4d407a3aa0L, 0x1535c7daae0fe218L, 0xe16fe872397f2501L, + 0x572a591f54c212cfL }, + { 0x4966841909a5553aL, 0x3f054318327733bcL, 0xf9ceb4b23eefd690L, + 0xbd3cbf9bf22126d4L, 0x6d9671c02fed9578L, 0xbba597ceca0306d8L, + 0xb705ed613d674fe5L, 0xf1d3622b67f33f76L, 0x15bcf3c611cb8c31L, + 0xa38467dce53d1aa9L, 0x902fe929f908ab43L, 0x6e3e499d8d15767aL, + 0x8142db5c90afd07bL, 0x120c6fbc6c8b190eL, 0x80c8655324919a4eL, + 0x65c2cbe1d8c82c3cL }, + { 0x684cda20a660bb63L, 0x27dc3b0a86e86245L, 0x76472cf66ba0eed7L, + 0x79c162e5679dd158L, 0xb688427708452d44L, 0x829bc6b3413f579eL, + 0x92ea15ec95011770L, 0x5e34e30047738183L, 0x8c3ca34973e1d2f1L, + 0xa5c4f1dc229bd3deL, 0x783eff1b94ef7ed3L, 0x46db738ddfae7a1aL, + 0x4353d72e1a099852L, 0x2533ad58a0dcf4abL, 0xd80550160e7888b9L, + 0x831440d53ba77f66L }, + { 0xf43e2e32f611b2daL, 0x5d066e29d0fa46acL, 0xe897f3e8820b3c0dL, + 0xc45c28e61d3e44f0L, 0x929d7f66dfd27a66L, 0x735b860a101e8517L, + 0xea3fce983de078ddL, 0xc9977db5638ce11aL, 0x0488382f48536b3bL, + 0x7e0c7a3c64cadfc6L, 0x3cd17f7f82147b71L, 0xe95663cc1b411e3eL, + 0x5739ac8f985fb46dL, 0x385399cdbcf119caL, 0x4a985a70e15a2815L, + 0x504c3a8a6d5f4566L }, + { 0x00b55283b8fa53c7L, 0x985cff38509474e3L, 0x234d241c437ce25fL, + 0x29832430e5a129edL, 0x6ad38956aabcc674L, 0xa2dc001d7ee81ee1L, + 0x4c23c6b6670b2702L, 0xb35e567ea6e8a3bbL, 0xbc70b3cea69673eaL, + 0x85a7a9c3e6e28eacL, 0x2ae684de5537b7daL, 0x5ecac3e56de937dcL, + 0xbf2ea6c9f8430422L, 0x38caf7d077fdc520L, 0xc27af0b169f56addL, + 0x496e4699c71d21d2L }, + { 0xba14fc829fa93467L, 0xc2e376840eb2a614L, 0x659bcfaf4833e09bL, + 0xbc8597523686bdccL, 0x40bfd08081f3216aL, 0xc463bda617c081b8L, + 0xbd01fa86bb04793bL, 0x5a21ece62cd640c5L, 0x97bf6a542203d5c4L, + 0xceb40edc951167b7L, 0xd67aacaf765ba268L, 0x8ba0d9e9aeab51f9L, + 0xc14b215eb0d6863aL, 0x354cdcdbe5f06952L, 0x4f2b5ccfcb3744b5L, + 0x1338917313037fe8L }, + { 0xee68064045003cd1L, 0xfdac17bc44ae2ac6L, 0x4bcd419fde8e5314L, + 0x81e34eb9c7cea95cL, 0xbb57762d38f37e01L, 0xecc4cfb0260990c8L, + 0x0bc493f950a34a7bL, 0x68074172543304efL, 0xaec0fcb26bc8aa2aL, + 0x9e7a9b463b45fea5L, 0x4bb2952e55fbdbacL, 0x50f0c0a60485dff4L, + 0x02c5104d4dea4796L, 0xd2cefa09695e3a02L, 0x4c8102b46da1f345L, + 0x422eb573f3833fbdL }, + { 0xac592eb6a6ad3f47L, 0xb0861f6d9714ba0eL, 0x57c1e91907281459L, + 0xcf7c94e264ea5803L, 0x725376ac54b12723L, 0xf2a6ba41dafb736aL, + 0xc89e8920cba03cdcL, 0xf2e20cb45b0fd3adL, 0x26ea5a54d66059feL, + 0xee63fa8b889df8bcL, 0x40f1c7e166a3f2bfL, 0x09febc9c747312e1L, + 0x7d19b9c2727999ffL, 0xa9fbbb4cb7fd2b05L, 0xcfba27d7a0da2dc6L, + 0x368541cf2c252582L }, + { 0x510d3c9e22799d37L, 0x1b677de5acfa333aL, 0x4e6ae18f080f795bL, + 0x69b53c2aafc8dfc2L, 0x797541b60e842dc2L, 0xd5a6f2afac067fe8L, + 0xd0208a03bd07d877L, 0x34b473f0654be2f2L, 0xe67c102af515e23eL, + 0xb00dbf9d2ac1af48L, 0xe264fa41b6a13d00L, 0x1669786a97e94c11L, + 0x09d8cf2d86a586f4L, 0x073bf869c7f927e9L, 0xb89778802241a566L, + 0x59a5bf5922261334L }, + { 0xe9d1c91e81347191L, 0x186c1abceb969972L, 0x07888767a9d46a7fL, + 0xda93cfccdaa7d397L, 0x08bee9f1d91b9aa0L, 0x8267fd78f8dd3c6cL, + 0xf93860d094228100L, 0x6a6a71aadadb47fbL, 0x9caa06b7a6156f8aL, + 0xaa1b05e039848bc9L, 0x36ddc2372aaa9135L, 0x77e7e079b13f3bd1L, + 0x8d0b5cbe4acc5f4dL, 0x04da45f8984cfd36L, 0xf14ef618d3d3e0f8L, + 0x467564c143eb799cL }, + { 0x8d725904b6fff5d7L, 0x037f33af92dc4752L, 0x9095d5756d20b8aaL, + 0x32235fc143baec39L, 0xa2feb4af68a2b9b0L, 0x61c5031894d35c61L, + 0xac92b6a2ea877486L, 0x8eb48b15011bc6f3L, 0xa28fe128c79edcb2L, + 0x9f71bc0ca5d2a006L, 0xf31677322f15b850L, 0xfe8d728c7a036218L, + 0x068f39cb4f81e09eL, 0x1773f0167b7c50d9L, 0x0d0f7adbed6a1e03L, + 0x8a0dee164ee984d5L }, + { 0x504991bf47366e6fL, 0xb8084d9fe86c3005L, 0x14c4c751a40cce36L, + 0xbbb46aa63f1961e2L, 0x56a785f940445e43L, 0xdb8d1b57c91e215fL, + 0x6a8e453ec7ee808dL, 0xc0367ef8bbaa1e8cL, 0x310d91f1e3e18109L, + 0xf97cfd0e7e20a2c3L, 0xf1e80c84554cc277L, 0xe89bbc1d7b628403L, + 0x7778a9663fe0a17cL, 0x9e9db19fc1f00073L, 0x2ce7fe7db6f6bed2L, + 0x7b04b5d2ee97ce23L }, + { 0x5b546bc782c5faf8L, 0x1a734c5e8eb81097L, 0x3d566861e77851e0L, + 0x833a1013e956d51fL, 0xc7351731c3c3c37cL, 0x607738fbe0c148ecL, + 0x2ec6f0bbe1bbef41L, 0x0aa2ac6ecfa51857L, 0x072902d766e3adf0L, + 0xcd4d5089c622d6e3L, 0x3ae21b23a6dd802fL, 0xe5465a5533886372L, + 0xd85119a0a8d81822L, 0x4f14d0323786977aL, 0x515b081c9c7b272cL, + 0x1c6a95a4c99be31cL }, + { 0xa6b14ad5c2821363L, 0x829c18234d17de1cL, 0xaef5d2c4ccade848L, + 0xf412ab3982489e27L, 0x92c9c098f081d927L, 0x6f87bdf475cbad1fL, + 0xf4aadab81a1d9fb1L, 0x475a7923b75f3b76L, 0x99dd0ad6dbbba8feL, + 0x836f61644b70ab45L, 0x2a46488134bd9af1L, 0x5c91226eba9abda3L, + 0x4cec8709e65625fbL, 0xd4b3919e0818e4beL, 0xa5c09c8414f6879cL, + 0x72708a0230a864c9L }, + { 0x4f33c0b1f34a466cL, 0xa1bae09c7f9d45baL, 0xd70f0fee0e28785cL, + 0x824c714690880881L, 0xe2416c2abb043da3L, 0x733da713cec6f432L, + 0x2b590649c9793e1cL, 0xdb62d5b0b35c9365L, 0x355eb6e23e5c1b2aL, + 0xcfe8b5cebb16b515L, 0x9e081869f709691cL, 0xc865f9fb61a85bd5L, + 0xf169d3ccfae103f7L, 0x9525c47373467e9dL, 0x7db55c0b43695113L, + 0x7491c74c73265d21L }, + { 0x312ed5bf80d2b94dL, 0x1b8ac633ba4b260bL, 0xac86c58cd62219a1L, + 0x317ccf6baeb82c8eL, 0x2dfb29ee59ef9cedL, 0xdaa7d898e42bcd5aL, + 0x93e295c85974b201L, 0x69e75784d9fc5adcL, 0xd6c4709f012aa3baL, + 0x1fda9f37c85d3cb9L, 0xe5487e25d3dd4abdL, 0x00fd4b010b3ba22eL, + 0xcb591493c6e8dcbbL, 0xb7329fabbce68664L, 0x6829d1c268906b76L, + 0x8bcfd3e574176841L }, + { 0x06882734d3c8c314L, 0x95f0b2f111870833L, 0xb937f7c3c068ba16L, + 0x5365e0d877924787L, 0x15527e5e1f992227L, 0x0a06964827dffd4fL, + 0xd58b3df22f586389L, 0x83446b896af20eadL, 0x09d7970b50746257L, + 0xd9e8d2064022a691L, 0xd1e5f8af671ec379L, 0x6f542509057fe91eL, + 0xf14dda8152890418L, 0xbd78010e1db932adL, 0x3e18d1e4905a9378L, + 0x53cadcf7bd37ab49L }, + { 0x1bb5edf75e53d0ffL, 0xd886606c888abf67L, 0x6491b0f812206d15L, + 0xb3018345e22b6a33L, 0xaba6794bb173b317L, 0x8c1e58677dc9e595L, + 0x4e106482239624d1L, 0x61752e59da55dd53L, 0x018b4eab9e42879cL, + 0xcaf6784b491f2bedL, 0x3dcdb9d21e79429eL, 0x3694148510f26224L, + 0x106f190aa650ec5cL, 0x7542a5aeb69a9760L, 0x69bd75e9c32d1046L, + 0x90849964bf8c62b1L }, + { 0xb1390cf65a93c661L, 0x184862649db5f056L, 0x92a93a9da51a1788L, + 0x1b0cbb8f6772de9aL, 0x6e67febd7c71487cL, 0xf9b4382d4e62423eL, + 0x96fda50ebb5a42f8L, 0xc921b3376089a4f2L, 0x49d32d7b875ec516L, + 0xbd86d2cac410124bL, 0xf6862209c421fb7aL, 0x3e1949abf6b7de33L, + 0xcdee18f0e93c9268L, 0xd4edbd5e08dc4cc0L, 0xc2b75be473580d22L, + 0x3d7f6ffa468cd7e8L }, + { 0xea7b290cdffbd5d1L, 0x9d759da6970338dfL, 0x56680b0890feedc9L, + 0xbc690af542dce68eL, 0x8519df2bb2ae4d82L, 0x5612467f7f195b60L, + 0x659a342cd83c21f4L, 0x55771bf555651633L, 0x5fc68935548ba562L, + 0xb54192039492f23aL, 0x567528e39c9c6017L, 0x3f064ed4511e6019L, + 0x303f9eb91d16a555L, 0x3e18c4fd2254abeeL, 0x40994d6ffd434e7cL, + 0x8fb12d3f6dde74e6L }, + { 0x6c6381a2293cb7a4L, 0x453e09f0b87b7e4dL, 0x4f212823078ac3efL, + 0xe89ffad0578cae91L, 0x4a2b696a716ba4ddL, 0x14681a14f6f580a0L, + 0x1358f97b4c2f1307L, 0x878969962932fb89L, 0x29dd850a268a5af7L, + 0xaf771f6dfe239f83L, 0x5f20fd2e4f47499dL, 0x9b643e77867ca0e9L, + 0xe7858ecd375981ecL, 0xbe946a5919ab1c97L, 0x4f9303a206ff3453L, + 0x3fcc673175d237b1L }, + { 0x509debd5df21f920L, 0xfaf70e1fc1401b90L, 0x2429cbfd95a64aafL, + 0xf21208552c37a122L, 0x1d4c93f47deb926bL, 0x12f3e4c09fb3f1dcL, + 0x56085a595b51bc46L, 0x2a2f5d62f10fdbd2L, 0x60dd62cfdf0cb3c2L, + 0x154424a36b0f254bL, 0xc3a5a05d564612b7L, 0xbebe30cfa1f5249cL, + 0x24ec69037e62a188L, 0x75f0fbacaf429939L, 0xd41345dcb3fa8685L, + 0x645146fdc7151c34L }, + { 0xecec633aba1924f9L, 0xbba6f136006326e1L, 0x203757ac7e50fc17L, + 0xca531919ef3d8e00L, 0x9545a6aa51dc5a74L, 0x6e21d58fd31412b8L, + 0x01bc30057bb1d000L, 0xf1789c696ed1a9c3L, 0x7af2d35f9858fa48L, + 0x434d09b98197be85L, 0x1dc0775529aa265dL, 0xcad03be7c058fa80L, + 0x92d70a9f54ba14ceL, 0x6dc785056c050a74L, 0x2a7ca4a94d005ddaL, + 0x448d3d72abfb9f2eL }, + { 0xdc56f14529b33989L, 0x868351bca9ae815aL, 0xb3f456134b074414L, + 0x955ce42a3cd9f33bL, 0x13ade4ec5ff6e4a3L, 0xd3aac715a50eaa91L, + 0x0c61ec995666efdfL, 0x108a28b8f6a4470aL, 0x402ef584e54844c9L, + 0xb825b162d0e2f337L, 0x3dcd131fb46f7cbcL, 0x208178ec96f2fd89L, + 0x4d8c5d6725928c78L, 0x285a33df9963c459L, 0x72497175d92a309fL, + 0x76881479cb7019a5L }, + { 0xba43a11491767eedL, 0x5e11b9ad92bf65dbL, 0xe8a22ce003a5e21aL, + 0x636044212a335415L, 0xc2c563b44a9ead62L, 0x4bc06264a0b2aee5L, + 0x75b8d5758bf2e1d7L, 0x1cff0ee7d08a265dL, 0x17914e1db0b712a7L, + 0xc35925d04b18692dL, 0xde253f4c56cce815L, 0xa479241c9fff0e3aL, + 0x50b9d06eddabed19L, 0x6713526059fae506L, 0xf37600fb532ce180L, + 0x670eb01c5e5a8626L }, + { 0xdf73c0af73cdbb43L, 0xcf08ecc57f2431adL, 0x917805412a1a3845L, + 0x69a104f29224ddf1L, 0x4352f38dbeac7effL, 0xfc3b3b4e7c2d1322L, + 0xa69e9430b5e4b476L, 0x7d932340975a46f0L, 0x8093899e5d64eeceL, + 0x7b821250db2345e9L, 0x235529327f4b796bL, 0x2ee9cc154bb90b1fL, + 0x1fa9c8f59112f7d6L, 0x2d0f2f981cbaae32L, 0xb77f03660075166aL, + 0x504852e7635dff27L }, + { 0x2f0f3ce5a2f392faL, 0x326c076aec6c9078L, 0xad01de9284baaaf6L, + 0xb01b16d3cbe8e993L, 0x71305c242d950908L, 0xc66fd6173853af38L, + 0x7735140ed3c429a0L, 0x8a31b12a1fabf027L, 0xa0530002058b3177L, + 0xabffd9fca9c7deb9L, 0xd05ef69be8667d30L, 0x2f3a7308e9a9e13fL, + 0x3f4c9a19b91eae9cL, 0x50d0cee7618ce6c4L, 0xfb24dc405240f8b0L, + 0x992fe151f7e90cc4L }, + { 0x4454db3138f197aaL, 0xa4ded69d87872f98L, 0x97b427b044f0a828L, + 0x9821e1aea31e48c6L, 0xe38cb09fdd98efecL, 0x20b84fa8480cb3aeL, + 0xba5bb4a847475573L, 0xa9be080acd50e96bL, 0xc4451e9cef103550L, + 0x626ee75fc441325cL, 0x6eea5e9838a5e33dL, 0x7321beb9a2b0abd2L, + 0xca92e4849b6082a9L, 0x1dc8168a992bcc2aL, 0x134ecf4b9c8eb9fbL, + 0x5a68bfa84c5b71e0L }, + { 0xb4ff3b45ff0a2bfbL, 0xd105fff95502f8b0L, 0x14de58855b1c0c26L, + 0xed16865b0d3b9d04L, 0x2f5a2453026d3917L, 0x6a22f493f4db3c0eL, + 0x4871548ae2418f2eL, 0x6ab363a8509bef61L, 0x91ca1e3ab8cbbbecL, + 0x71e0dc984011a396L, 0xff982e0a0d5ca577L, 0xeb40b04581897bc1L, + 0x4bc24a46085ad5e7L, 0xd15c8fa0a6337b7cL, 0x56ce6ef7bef1628fL, + 0x78acfdf99f5ef439L }, + { 0x45bf7f15f8520189L, 0x954202a0c77f61c4L, 0x39edc6b9dfa22e1bL, + 0xd2d602671f4a3487L, 0xcd9339294814cc52L, 0xde76a12405e9f123L, + 0xe2306ea0ae36b6f7L, 0x53815218b83a58e0L, 0x9862bb76a041231aL, + 0xe8da253cbf31be71L, 0x2dfc533237de861fL, 0xf25c93f690ae4890L, + 0x66bcb8f08baa6ed2L, 0x6f10ae0f908b4a29L, 0x8cb4b48cb061c949L, + 0x0ad92d73d075a366L }, + { 0xbfb95fedc2ca548aL, 0x4778c62080cd89abL, 0xbe99154b3466c280L, + 0xea3be093d4be8902L, 0x847b799513e681edL, 0xf22a8f4b02f40161L, + 0x3ef2cb4d4aeb7fe8L, 0x9adc5151b3aed5f6L, 0xec1ccfd198c31163L, + 0xdc2ac17ba3d7d88fL, 0x08fa64d346421097L, 0x5ebf80b794b90bcfL, + 0x1b78b4ba0b50a9ebL, 0x1a4fe934279aa66bL, 0x8ef4dcaf075b3cedL, + 0x95bbd8a070a6e9aeL }, + { 0x59f92495e614bbd0L, 0x7567a887b823e363L, 0xe247c9ecfc1bd6a7L, + 0x2bfaaf478e835c42L, 0x314ef4e0aade066aL, 0x072baa635c16d336L, + 0xfa429c71e2f0e389L, 0xcac1e5d0bd07d90fL, 0x69ff35ea514f5c04L, + 0x893053fcc0554ec1L, 0xab1d86b72a35947fL, 0xe29fb0602aebe487L, + 0xa0a10d6ddfb9cf21L, 0xad147059f20dfcf5L, 0x480dc66fb8867a2aL, + 0x375a884fc125a919L }, + { 0x178cbe2e1217f7eaL, 0x1a161e2a875c6dabL, 0xf7707ec01bdb1a54L, + 0x678864a0e4fd73caL, 0xbaebc664d13a0d86L, 0x40325f99c8d30668L, + 0xb93ed9c92f1c5950L, 0xfdf36763541e0667L, 0xfd97fbb0b91a6763L, + 0x26aa69ea6079c9a0L, 0xc7303c801eaa8c47L, 0xdec75c81afa63c55L, + 0x01cdcde24fd12adbL, 0x9fe0dda71968838aL, 0x66bb093b38415379L, + 0x268d818b08cb84ecL }, + { 0x73dae35841580555L, 0x4fc32e67473d103bL, 0x240c1013beccc1abL, + 0xda4099f2b24ee9deL, 0x37b0cb5b9fa8e066L, 0xb5ae04e46438d7eeL, + 0x7f7d31642b720140L, 0x86ef4edb339e4a78L, 0xa5e77eed3a7d8375L, + 0x883fad37bd707c2eL, 0x816b633a0f979189L, 0xe24c028a2e7a208eL, + 0x1171fe3c4435516aL, 0x3eb93b334f5f2bf5L, 0x8419ed4b01b53a56L, + 0x8b02735c056ca44bL }, + { 0xb89bb464e1019195L, 0x1de4c026f3fc28c1L, 0xac120e6e2bfc3b21L, + 0xec71bc5a91bdf92fL, 0x485d7ab40d995bc9L, 0x97c6768ee6491ffeL, + 0xd9552d19afbce265L, 0xbae6c7fe8e1b76c2L, 0x167d8281d7e3ad1bL, + 0x3e149af95e989734L, 0xd1f0024c8a0c8182L, 0xf571ffdbc3006c0dL, + 0xb32ecf7e58773d4cL, 0x5822a782fd3540d8L, 0x5ab45c3f04365042L, + 0x400e3aa04b4d85feL }, + { 0x473216495e46e4a2L, 0x37a2ed6424136074L, 0x659223b1c60ec77dL, + 0x5e13aac3e5e0ac2eL, 0xda17c41bc5107ab7L, 0x65b22ec973c253dbL, + 0xff3867b8a5012296L, 0xfed660d50621a99bL, 0xa3c28506c89fc3f5L, + 0x3ed350b9f16451a7L, 0x27c3e03267cb586fL, 0xc807c779967185b1L, + 0x09c157d44a13009bL, 0x362f7647adaf1f4dL, 0x4a42b9acf3a6a198L, + 0x131c3da28da6e039L }, + { 0x4a785ff1a7da83baL, 0xf415b425d04f4436L, 0x7c0899bdec03f812L, + 0xc58d411a80f5f4a2L, 0x3d32d610fda251b9L, 0x99bb4504cd3b2f32L, + 0x198c444bf4c2083cL, 0x60c261af730e83fdL, 0x060ca4dfcb02db90L, + 0x0ff7838b9df1e7c8L, 0x6b79cf97c4c690c9L, 0x131514d75d75f154L, + 0xa7c074f11cb0e8ffL, 0xb920aac1b2c17615L, 0xde8098ad44aa0ff0L, + 0x71d1a46a34545ce9L }, + { 0x76178f76fa1b382eL, 0xa0d8ecc3772dda0dL, 0xaa5aab2ac5d4d130L, + 0x27d38ba48d72622cL, 0xc5410db6ca3bed06L, 0xf637a588793ceccfL, + 0x1f65dafd6e65e3d7L, 0xc3b44a8560a45641L, 0x0f47b3a84f78540bL, + 0x824fdadd5e4d60f6L, 0xd8ccf90c17d3b6d5L, 0x008eabdf325fc13aL, + 0x3e90d7163648fab9L, 0x3964ff3a24c52d4bL, 0xb95cc416533d0acbL, + 0x6cd2699f1167f521L }, + { 0x2d8c0b3b12f4f3acL, 0xb03dcfe299d1bdfbL, 0x540034f830f37326L, + 0x22dd68937c5a8c82L, 0xeb7093d0cd8f1442L, 0x892795a7585742f2L, + 0xe15f282c087adaddL, 0x7bbdc74916ab7b5eL, 0xd30fe40ba58acbb4L, + 0x0de417ebe2bac39bL, 0x4b4b19a6c61a04bcL, 0x9338c34df2735569L, + 0xe8f0374230ab196fL, 0xfa2efcb86c88c965L, 0x19eee274c7eeb826L, + 0x327c063fda345dc2L }, + { 0xab399eff5b47cd53L, 0xbbe9869d1943aefeL, 0xe64ecc7b1402a866L, + 0xc3e7c2aab1c25a16L, 0xc4216b79022de271L, 0xe58dfcc8366d6a5fL, + 0xd159509eda813336L, 0x370400f2130bfb7cL, 0x1be4e05993b48780L, + 0x0623a1fe39f3cd22L, 0x72aa22b2eecb4f87L, 0x1af4c4966c27b83bL, + 0x7a42a94bda5fa5bfL, 0x9afba82248b01af2L, 0xeb6b9d2a3670112cL, + 0x020f19d1c0df6856L }, + { 0x37051a86a4dbba20L, 0xb618ebc6db1de5c5L, 0x9a780a19e6525840L, + 0x9440302dd2bccc4dL, 0xe9ff023d10285a24L, 0x3b937ee33a486268L, + 0xe37ee2f24cd61147L, 0x79fbbfd3a3d057cfL, 0x5fba16d3ccddefceL, + 0x916058ec5b231727L, 0x47699ebe720c3adbL, 0x262743868b4f6bbaL, + 0x54b0092af18a0770L, 0x99d090ebacca1160L, 0xf757e1ff0c888f60L, + 0x79e72720b0050544L }, + { 0x632acf252820a239L, 0xb1a3974eaae6b310L, 0xd61fd6ba48c0a1dfL, + 0xd2453c395a3ee7aaL, 0x548455a0b980446dL, 0x9f29d97bde16676fL, + 0xf252ca0c789375a1L, 0xe961af3e7743a985L, 0x70c79c5666cdbd8dL, + 0x14a3854ecbc538f9L, 0x58daa73aa126851cL, 0xe9b5bb452a9f558cL, + 0x37af7f83fbd15e05L, 0xa448792738a1939dL, 0xe428b2b59511a056L, + 0x001d3ce37015846dL }, + { 0xd6be36b9e145b1d7L, 0xf3e3938a009c5664L, 0x2e562e7de7c0f6dbL, + 0x951044e6c343f539L, 0xa5ab62b8d90897b1L, 0xb1a1f70b512f797cL, + 0x91cdd754750f28e4L, 0xb4c80e2fffb8165dL, 0x65ed39c7594d02b3L, + 0xcc12a49d56833edcL, 0xe73694bcf3693a18L, 0x34cc134afcd2c404L, + 0x071bd5fc11d40194L, 0x05759047fc585e46L, 0xb3280360790b7a04L, + 0x4bb8c6fc40afc684L }, + { 0x3120e2ddfd0f8796L, 0x6968a40db133c9deL, 0xfea366c0a9369c6eL, + 0x37e5b6d66007273bL, 0x39e4ecf08cb81439L, 0x487fe9cd9febc005L, + 0xeb8af4440199b53cL, 0x2f124e3b293519ebL, 0x860c218ac82c9c16L, + 0xacd1d6f2709dc590L, 0x5696d54536d50529L, 0xc03f5df959120bfcL, + 0x99a3e88d10ffa690L, 0xd4f9cfa56c432827L, 0x2e8fea9e9a135d89L, + 0x3699a881b6a77e78L }, + { 0x5bca33721eb1c64dL, 0xe9cf3a2df1d28154L, 0xb7e2e9b36537106fL, + 0x06c171514f7cbf4dL, 0xcbde416e2058b37fL, 0x82c53a7e8834e9c5L, + 0x94dbdfe2e9ac3a75L, 0x795ec6cbc5e67c02L, 0x8c23c25f1426a80dL, + 0xee2cd20d6a8d4f9fL, 0x838daa54d3b7c235L, 0xb9e08ec03d7a4d52L, + 0xca9475e9781cb473L, 0x7271f39e5ec31caaL, 0x1df08e9f82535187L, + 0x4f3a4b03208aff8bL }, + { 0x0f7b81071ed095f8L, 0x23e37fa6da226d4eL, 0x8b0f9852afb36d1dL, + 0xb114634e07d8e311L, 0xb9634a97e3e0f16eL, 0x2454bb9c421eec37L, + 0xb4ecd5dbd72b21c1L, 0xf96038686df20d7cL, 0x9f5359fddf86e0a2L, + 0xc43d54fa5ac488aaL, 0x56d714abd1049df4L, 0x13152b3eb020607aL, + 0x49be1c187a02325eL, 0x44f24f4a52ae84dbL, 0x9e525c030b5a7b80L, + 0x6d874446a6d179fdL }, + { 0xd29d07aabe9a42f5L, 0x1fd5316c3781ccc8L, 0x71a75a6d9dc69ea1L, + 0x4e19e0df88fee91aL, 0x99c2b4dcf8d44f12L, 0x05f6df9231ae94e4L, + 0x27fba876cf28ccc2L, 0x6e1a0f01f57f7cebL, 0xe03f1f34f3fd3b74L, + 0xa0edc4a742c1d213L, 0x5caac2707deb8580L, 0x0f5d791faf0848bcL, + 0x17f514ad07ac759dL, 0x95a39734904fc531L, 0x95a4aca97bb70f3dL, + 0x3cf384c9ff9c5609L }, + { 0x700506bace1fc9e3L, 0x49721742676b0399L, 0x2b4a1b8de72bf7b3L, + 0xca8602a879b209f7L, 0x90580b90ce26a8e1L, 0x1ef339b7fe24f39aL, + 0xb6c5d991629362e1L, 0x51174e1a577b24f4L, 0xf380fcb505e451e9L, + 0xf4d97afb148321bdL, 0x099806bb747e5d2aL, 0x85525d65be99a608L, + 0x264828d9d455e820L, 0x8c8c5405d8560a65L, 0x3c67e73c71030770L, + 0x2b248850ee73df26L }, + { 0x2173cde68541159fL, 0x78224c184fb410b2L, 0x07a286191f2ca1c7L, + 0x52c207d6a8b23e40L, 0x071a0210a6b2344aL, 0xdb0e587cb5ed2945L, + 0x6c56b8ef810fcc6cL, 0x1248c58f62d843b9L, 0x4b90363d74c66975L, + 0x6348f7f2e66c66f6L, 0xb2f9d441c126bcbeL, 0xac07f2a373ce49e8L, + 0x52486758e81b0df0L, 0xa108b54d1d4621d1L, 0x17261ece74414a1cL, + 0x938b3bcc6a3ac215L }, + { 0xa9e4a16be4ded340L, 0x8e65fb2a80e88036L, 0x97089606dcd73acbL, + 0x1c3a0434aaa657a9L, 0xf304fc5849101b06L, 0xe60fb61ada0bb64cL, + 0x818c2aecf5542df5L, 0x7402057656f76d5fL, 0xb566b79092533d97L, + 0xae4655e574d6eb5fL, 0x60f7a1b5a55b44b7L, 0x7970179b93747ea5L, + 0x8ae7e0e8f2dace56L, 0x9847460784e83c06L, 0x24e8c9ed15307341L, + 0x6cff58a5d9e89d6bL }, + { 0x508c01b003e51f68L, 0xe1d1f2251d2fe7d6L, 0xf7998d0b09bd8805L, + 0x255e907a03e415b7L, 0xd148467d607d9798L, 0x055c3b1e9b453896L, + 0x35001013809f50f4L, 0xfbbb2fa6d0233fdcL, 0x0b680b0aff1820b8L, + 0xb1d404dc38d317e0L, 0x133d5444ccc8c7dfL, 0x7fa847e66ec13f84L, + 0xc33f83d8046e2e48L, 0x3c627fc54863b3acL, 0x5f67f8aaeb936af7L, + 0x5fe4ac8f31b79327L }, + { 0x581aa4bf8b6f401eL, 0x05db12a3ad5c7ed4L, 0x7b0187266fb07b4aL, + 0xfdd11f049c22bcd4L, 0x5454a7d469371c95L, 0x066c55fb99a46eafL, + 0x18637c7c7fef96d0L, 0xbafc1d346b83e95cL, 0x55c3859300bb42dcL, + 0xdd8dec2b34e7e712L, 0x69c9cfb0b184cee8L, 0x8dcc0c4249a27864L, + 0x290d95f22010f2e7L, 0x86e254c96977a420L, 0x20931c89eb2abdadL, + 0x81377164121c0548L }, + { 0x6266b25e9c5a8edfL, 0x6e1388c21078a7adL, 0x5f02737d4876eedfL, + 0x242fa7f962744617L, 0x3e2cfbd9b385382aL, 0xbadad7b102f71befL, + 0x562abcfa677d0a92L, 0x573ebd1751fdff34L, 0xd7f658527c250c78L, + 0xe0cf16eec47ca896L, 0x8ccd79b067622c9eL, 0x31fc5882f8f2c075L, + 0x9232b37ea6008515L, 0x4d7bb36182e8c5baL, 0xbf24735cd2f146feL, + 0x79c280ee9cd2db98L }, + { 0xbdcc8203f2b48122L, 0xa8c04916b04ac48eL, 0xacf064dc9fc4885eL, + 0xab83899782c1001cL, 0x7339e721676de250L, 0x17aa5aea8e1ab820L, + 0x24d28ca06bc14b2eL, 0x570c5bb7816b6230L, 0x6c51235ccee6b606L, + 0x1b2bf89f183eae42L, 0x3e3af3c69c66274bL, 0xe0b04426b51e38bcL, + 0x26dbc58e73e40e3bL, 0x3f9dd578b5be5be4L, 0x9fd9f79152c8f408L, + 0x758073a4a9e3ff4fL }, + { 0x7d27b0578691ca22L, 0xf206bfd613a2a1b6L, 0xe84bd385ac795413L, + 0xc5d18a2a75536607L, 0x2e166de7c8a0e24cL, 0x56d5750c3c474dbdL, + 0xdef444c11366843aL, 0x14646e53cf4b8432L, 0x4bc0d030a9fd9783L, + 0xbda4c824297ee203L, 0x3d0b10bffd7be6c7L, 0x2d21647608c7f3ffL, + 0x06e52599b4fd4c45L, 0xfbab9fa149e9e104L, 0x9342a7fa8661d32dL, + 0x3f3e3458faf66aa8L }, + { 0x51ec35af951597aaL, 0xb677d4ac49df64ebL, 0x0276cd9c9bf4eff5L, + 0x423eca49515a2935L, 0x8a696553fd9bb9c3L, 0xf99ee9dfede1f09cL, + 0xb8fa2956199e5f98L, 0xb763875835292c32L, 0x8734eddcfc40e81bL, + 0xd82d5e9f65457d95L, 0xc8ee323e30c78d2bL, 0xe77b2e4cc1433d67L, + 0x56d9f8073c8314aeL, 0x441eede22a0e2f63L, 0x1e9e17ed6c48295eL, + 0x640d20c434c294efL }, + { 0x4e9a0b8e3284d513L, 0x074c3545f315053aL, 0xb36e740745acd52aL, + 0xd80bdcfc1de50db7L, 0x8d9d47dc2549fc46L, 0x29b6ef13303f07a8L, + 0x4e461aca6d4ad4c2L, 0xca8e351dfc9f1b73L, 0x8bc4094d57460e65L, + 0xb6302b330f32d367L, 0x69a074b6285742e8L, 0xdfe52b11876c29c3L, + 0xf39e4609912bd17aL, 0x8ee40d66349aa639L, 0xb968902ac72e05c1L, + 0x0f9c1ca8c0d92816L }, + { 0x1ebbaab367433df3L, 0xb6aa534715d3628cL, 0x13a320d897f0c5ccL, + 0x72c918cb65e408f9L, 0x4b638854d5373451L, 0x731399a30b4dca09L, + 0xcf2567300a3b1326L, 0x5ea60dfa6608b388L, 0x58ad74b07b290dfdL, + 0x83202789d7694f9bL, 0x48593db8b6630fb1L, 0x3db47f70c65e3eafL, + 0x63949c913e7263f8L, 0x9b9acec6e6e6ff33L, 0x34bd9ba7098a8240L, + 0x7e31c12f45d36ec5L }, + { 0xbe281d680dfd2dd7L, 0x1efacb0024ab61d8L, 0xb9c3005f94431f97L, + 0x660c8dfa959cb3bcL, 0xfdd5fc30cffbb406L, 0x7a4631be7969a10dL, + 0x336e309ede13fd1bL, 0x76b3bfadfc947076L, 0xfa91925ddcc72223L, + 0x741f0d73156c4ee1L, 0x4f64ee410e2b3747L, 0x86be92d3efc4d93cL, + 0xc53b7e03fc4fbb2eL, 0xac196cf5337ca1bbL, 0x4de41a307e23ba60L, + 0x1a219c45326d5357L }, + { 0xfdcf7ef8aa4db0bcL, 0x2e2318067b6c9963L, 0xc26390673d8a192fL, + 0xc0cec2e2ffdc7771L, 0x997c8e35a2fc0edbL, 0x78e10ec182cc6043L, + 0xfd0de2cb2b0c8120L, 0x4d6c457f69e57f8eL, 0x953e69b25b53f1c3L, + 0x422a330ac4f89cb8L, 0x92ff232995566be6L, 0x73cd502d437442d1L, + 0xf04ce590bea69403L, 0x6ac1537ef8030662L, 0xe02bcf77b6d0bf93L, + 0x17aaa999bc90192fL }, + { 0x0d3d56438e55db2eL, 0x835dee433b946851L, 0x1a1440e55b88462fL, + 0xa6ff3b35ea17e27cL, 0x23f99c36dd95f7a9L, 0x7217fdd9bdd672cfL, + 0xf400ac1edd2045c0L, 0x94b55c874ff06b25L, 0x0a44a0e50e4a49beL, + 0xe8925e91b43b6813L, 0x78bedde1214f96c5L, 0x0f456a4c0f97fa97L, + 0xa28fd86ba5bfd267L, 0x3b4b2d8fbe7608efL, 0xfbd5ff8c226474bcL, + 0x6b282af0a5f3b24aL }, + { 0x78fc025f6341a595L, 0x591c38d6a445e28cL, 0x72bd6e3deb446842L, + 0x3f9466d375547833L, 0x911414d3083e16c4L, 0x145d946695a7acb4L, + 0x102ddf098fd2fb64L, 0x2a2b2d2d0bfd87b1L, 0x69e9be5c59455088L, + 0xee378bf4a80245deL, 0x80b0bd68b2306b0eL, 0x76a545c6c2be9f3dL, + 0x429d167b4802c245L, 0x13e644272b412dfbL, 0xb664f529ee8d9762L, + 0x6d4f5d2354706ebfL }, + { 0x35c8f2b600ba9f88L, 0xfdc807e07bb6d0bfL, 0x0a126d42b3b81e5bL, + 0x335ce6cea7ac781eL, 0x3e308e6ff37dcba6L, 0x028dca6263c96487L, + 0x72eba57e8818434dL, 0xa9e3d59f79b78a26L, 0xd2f0a7dd2f07aea3L, + 0xe0fe467824d05f74L, 0xb20851700116deb6L, 0x9c2a5e9258f37580L, + 0xe78bd7a574070bb3L, 0x551fc872b9977d90L, 0x6eda93c440db81b4L, + 0x4aaf0b4fd65d34adL }, + { 0x9bef25063514c7afL, 0xb09e7dadbc181eadL, 0xef3cae878fa3ec58L, + 0xd8dbfab5173b8685L, 0xb2490fc0921d32ddL, 0x4eef386b8bd9c466L, + 0xc1cdd52fa061dbdbL, 0x64de989a25bc04dbL, 0x06f9836b85728636L, + 0x11a5a8048be44aa0L, 0x16dede4e097018c7L, 0x72aec577b2c11fb1L, + 0x144dade1a721ecd9L, 0xf99c526bd6ebf3a9L, 0xa1d4165b1c2e14d7L, + 0x8b2cbd3982bc6337L }, + { 0x28ec1bf28a52e991L, 0x0ba202f6cf9d42ecL, 0x8307d130c634ea45L, + 0x3fc257b3c5762b9cL, 0xbd3298d1487c2a2dL, 0xca14f1a7a319488aL, + 0xc70ca93b06ba06d2L, 0x9aa3f4b3ee405e89L, 0xcc64eeb335deeae7L, + 0xd155f57803bf1d4cL, 0x041ec0b545616bfdL, 0x23df80e6086e33f6L, + 0x399a79c8f0243cf5L, 0x86c2824e874ccd58L, 0x220eeaec8fc5c831L, + 0x57e283047dbe3670L }, + { 0x6e60b698fbcdf666L, 0xbdd06a998bebb1d2L, 0x4044adba80498436L, + 0xd76bf75e522bc88dL, 0x655c4b9b28423b20L, 0x65c0f49253398a72L, + 0x76d4f2b70ca37601L, 0x469899252030fa5aL, 0x96b37e87b6054705L, + 0xef96f73153de1b2fL, 0x5ecbbc8cad54ef05L, 0xeb289d0aa93617b0L, + 0x3ac0fbd57cba217dL, 0xd0d3cb5619d4a2d7L, 0xe8bee9d4c91d6063L, + 0x4f12e037696ffda6L }, + { 0x4ccfa42215f1a610L, 0x804a5c553786519aL, 0x1246a45473838134L, + 0xfa15b4844b284e2aL, 0x36464c65146d1320L, 0xfb6ba88c70a8a0faL, + 0x74e7cee793c4804eL, 0x8c34d22cb95ae16aL, 0x9d9ed89ff9c1d4ddL, + 0x61a0866d32025371L, 0x45b232b29bd6444aL, 0xf888e92cf277bab1L, + 0x73e69c6ea9448b02L, 0x1a496ea95b521ecbL, 0xa8f78ea75858afb2L, + 0x83d2333eb1266f91L }, + { 0x1c63328867b478d7L, 0xa1ee1ae150a2fc9cL, 0x05b6ab3018d2241bL, + 0x69f1f288893cd696L, 0x159d6660a8117a87L, 0xe812011970e73d77L, + 0x528fef0093f55f0aL, 0xb3978db8d854dfb2L, 0xd6b43ef6f45d9fbbL, + 0x17de4bfed5bee397L, 0xa01e0f596bf76dadL, 0x28b2280e3d40754cL, + 0x8edb6122f8e86ef3L, 0x8226b6afb7d1e586L, 0x463532152f40a55bL, + 0x7362f13ec5a31621L }, + { 0x792eb27c73c0c430L, 0x8cc0a65fa51c3657L, 0x50a5ceced2194f1bL, + 0x18945688814b4947L, 0xbbf0a81a4b6fbbf4L, 0x376f4f58f0aa8608L, + 0xd9361d683987795eL, 0xb6510cd8e3a8d0d5L, 0x63e2fdbfb6c1a455L, + 0x2c91154eaec891f9L, 0x0eb1e715ff568f64L, 0xe7af9cd72f2b399eL, + 0x1fc39bac89f0bf0bL, 0xf0861d9290983695L, 0xd9b16f02da0a20a8L, + 0x2f10693fa38c0eadL }, + { 0x07a6ce910c06ded2L, 0xf974842f2fd9087bL, 0xe468bfd6a9f635a6L, + 0x04b618911ed60626L, 0x1fb2f89f369ee548L, 0x9cbd1113dc96a201L, + 0x6759acfe10d633acL, 0x64ba66fc8faa629eL, 0xa686ae4947f38283L, + 0x828c3a05d59cda99L, 0x7c7afb1408ea2f6eL, 0x2551c8e4af3953c8L, + 0x5b53d2799daa9e4fL, 0x1eff68d4ad6f1940L, 0x2775dbdd96437cdbL, + 0x985f83e44fe7a043L }, + { 0x89603c16eaf45294L, 0x70131160c24b5751L, 0x4c11201839d6b52dL, + 0x7079cf02ed943340L, 0x0c5b028b74f41b68L, 0x3dc3f0769c8ac1e1L, + 0x5ac5eea3f8b24f0eL, 0xee6684bae34c5c22L, 0xa5259e639abc452aL, + 0xb07d2cd1e9df45ccL, 0x07019c931a443cfaL, 0x68fddaa992c003b3L, + 0x2d9f179c0d8cbc2eL, 0xbbf15a6f1e781ca7L, 0x54d779d550dcc799L, + 0x0c88e5400fe962f1L }, + { 0x84f71a6ae8f44357L, 0xf75b4bf63a3cab6aL, 0x334c9d9e5aebc680L, + 0xcecaf0848a753ef2L, 0xe28014c1075e3c8eL, 0xbb9d5a38f74f8d3aL, + 0x75988464b80e32aeL, 0x7b328e6ff2bc3792L, 0xebbb1fafeed0e197L, + 0x674eac955a33065aL, 0x8c19fd8f922dbce8L, 0x8c17ae85987b907aL, + 0x89f336273b3a2cd7L, 0xebaea019fa87772fL, 0x4e5de4993a25ced6L, + 0x8e2560b8af110715L }, + { 0x56d3746c3141aba6L, 0x45a1079fbab2cf9eL, 0xb63828319cdd27c7L, + 0x222376329dfd950eL, 0x1e0b15cd3a9408ffL, 0x49a80200b1160118L, + 0x2719db5da383bba7L, 0x6078340a651046d5L, 0x8929d4de97523b1fL, + 0x4040345c8e0a28abL, 0x61275ac20adf09c7L, 0xb41ab2652331d611L, + 0x230cc77c5391ca50L, 0x88be0c928f922315L, 0xfef3d92b92fd9a29L, + 0x59005f228324f2e5L }, + { 0x6bb1750c3c4c1c74L, 0xbe73aac0e966fb79L, 0x85a75d9266c5973fL, + 0x8c97f9323a8656b6L, 0x2b7043b150446cdeL, 0x548916f73ff3897fL, + 0x913dd01cb18b72b2L, 0xd0a751f1488c0de6L, 0x191757148558ca58L, + 0x9771430144a663daL, 0x2df190acb0e08618L, 0x0080fc0cf39ead9cL, + 0x0085ac6e17382da1L, 0xe97918513262a338L, 0xe4495936b43bae8dL, + 0x57a78e26d783df6eL }, + { 0x161b346f40dbddd8L, 0x2b49a9279410c3acL, 0x8c5427831886cf3bL, + 0x72df323233b93debL, 0x9c8d59f540df579dL, 0xe5d7a67dc20ef500L, + 0xc46b391867f08643L, 0xecfa2445ad96adc3L, 0x658f589b0c4544d0L, + 0xe6ec9301e08417d7L, 0x6ca5ef6ac454e288L, 0x4191048fac0f462dL, + 0x852407d808d8a036L, 0xb4c533a7f6d35b7eL, 0x3251e4128f6ada87L, + 0x1ca370c581c472e8L }, + { 0x94bd5171a801b68aL, 0x7312879cfd1998b3L, 0x4905aabf41163202L, + 0xb5fe87f4f5b01fdbL, 0x78de523a9cda128bL, 0x0bf161a1c7bd31f7L, + 0xb5decfd023904c35L, 0x224b2882e188f12dL, 0x0dd2801df99dae74L, + 0xcad467b508cd1cd2L, 0x6c311c3dc0867e39L, 0x71a117202b425072L, + 0x83bf464e2efd9003L, 0x53d0448a1dbd3b03L, 0x32db52f4e6265baaL, + 0x2584b34c4c33ac79L }, + { 0x3cb863892aeec688L, 0xa5e740ba45fbe523L, 0x422e71f7fd60b5f8L, + 0x455d185c4874913dL, 0x04c2bb36fa17d80dL, 0x3f271854ac054524L, + 0x76dd3045a8b9a657L, 0x2e42c3e162ee7cc8L, 0x002667064df6c7d0L, + 0x5927dd51dc7cb488L, 0x6b3faabe187897e0L, 0xfe6ad22ef2d5737cL, + 0xafb60269ff51a9ffL, 0xe1c8354569807baaL, 0xacddb6ff951ca49aL, + 0x7e8113743f9ab085L }, + { 0xad722a8b830a88b1L, 0x91918ea8ce1117e1L, 0x3e02d0b80409b47dL, + 0xb53812d36c46d1d3L, 0x2fd09db0e589669cL, 0x9845cd0615b0cd5eL, + 0x0c1c155a2386c453L, 0xda774de5f5ff43cbL, 0xbb076b98e391c0cdL, + 0x97d71eff5004f286L, 0x23e0b46caeec0bfeL, 0xe453866732a1ad94L, + 0xfe0c9f81396da422L, 0x6376c1a263db2bfeL, 0x001c7918ba56fa91L, + 0x436b8c64df8485a6L }, + { 0x88117e9d8ab764bcL, 0xdfa61e94a077df84L, 0x5a7765d30c18eebdL, + 0x548916affc9451dcL, 0x01a52e33071a347aL, 0x633b95deb23b41dfL, + 0xdd7d68c943c8c286L, 0xe4f9d41e18d97068L, 0x79908b908c92799dL, + 0xe614148ed47394a3L, 0xe5018517cd51e53fL, 0x5060075e0243dcb6L, + 0xe5dcde6217954405L, 0x6f7c90e1537da5ffL, 0x1df7aae40768cb66L, + 0x5266ca9e6dbe95e1L }, + { 0x84ddee6d1386b3dbL, 0xf9e4af5a7c38e540L, 0xb3418440eb04f49dL, + 0x2138a1e8fde5a4fdL, 0x3e6e692430257cfcL, 0x3519c6e319fd70c1L, + 0x8f34e17486c31ff0L, 0xf1e298fd940ce1e8L, 0x6fb8cb1d14960d7cL, + 0x207c13472b2f3bffL, 0x899a20b4146ef8ffL, 0x7dec362b7bd3e220L, + 0xa975044e626bea27L, 0x0f32b4494fb4cb67L, 0xc17a09201fc6703aL, + 0x41f325b99cd84a2bL }, + { 0x312ed513ce2843a4L, 0xe748498e00728afcL, 0xa8ef28224d864ce5L, + 0x34064704a620083bL, 0x5905e1d94bed338dL, 0x2a578cb5063e7b38L, + 0x98276d96289e7bb9L, 0xdfe2dc47f17b7341L, 0x5923521f1dac8944L, + 0x3db6d28d23400aa7L, 0xc647705ea761ba43L, 0x8947ba6d9bfd07ddL, + 0x00f2e3ac242ca8fdL, 0x49ef4670eb8c3468L, 0x7db3d37bd9aa18fdL, + 0x56b30fb6e58cea9eL }, + { 0x07ecdcaacd80a428L, 0x7af922dc8732c891L, 0x20d887983ada441fL, + 0x3bed9a44924b008aL, 0x2123533cb2e81c3aL, 0xc34e407565f807d3L, + 0x0bfaefa51f2faecbL, 0x78b634a5ade8a88dL, 0xc4e0b7f894392a91L, + 0x3092237790bb1cd8L, 0xdea9b4faf87204aeL, 0x3edf81f585d3cd83L, + 0x58f88c51c6523a79L, 0xe472fb8b17c0d969L, 0x899081e5dccf7f07L, + 0x1353cc5758bdd146L }, + { 0x28a5649739bf6e18L, 0x59e8b5a2649b89c7L, 0x8d9434a0dce8b8e7L, + 0xd935bf512047040cL, 0x2ab3a1646a7b8e82L, 0xf1583ed627f81294L, + 0x8416a7e072d67297L, 0x49685d86cd39e42bL, 0x8a797fc7958ddbadL, + 0xa558f928155ce6deL, 0x75f4e570f8a36235L, 0xbc69cfc052877ae5L, + 0x8f4193a9a6b16ebdL, 0x8d1df43cbb1cc1f1L, 0x723a830e5a21e789L, + 0x3ec2185df451df58L }, + { 0xb9d4c7d71f0bc2d7L, 0x6982c6cc6e51d412L, 0x92e02d93a09f80f6L, + 0xb7dd2d25047ae09cL, 0x3503149f37f351f9L, 0x69d49ce1c77850beL, + 0x60242acb12f0d2c8L, 0xba188c567bc28b9dL, 0x8e40612106bc0550L, + 0xb0d84b1f8d7d4329L, 0xb4a67ae7d38951e0L, 0xb527c57b8bc97607L, + 0xbc93c5f35497aa72L, 0x5f1de8cc39bdd666L, 0x3087dc5ce9d447a3L, + 0x89b356b6a211abe5L }, + { 0xed6db0afdfdcc837L, 0x0fb80baaa871b7a9L, 0x413abfc91c1d4b72L, + 0xf5b56bf7adac9e5cL, 0x5664a2da8b8657a3L, 0x11b04f720e41d94eL, + 0x63e11d2637433658L, 0xee628ecef426daeaL, 0x011619c9cb162dc2L, + 0x9cf5817f87648643L, 0xe1bb97025584bc86L, 0x2cc27cef00bf7928L, + 0x4ef3a80edc60eee5L, 0x7e1202be87adc2f9L, 0x656f18e08a0d4f52L, + 0x39c4f10d57c5d126L }, + { 0xb3a9b68ce88aecd3L, 0x555b0918a518aa9dL, 0xedc1cdad4bd4ee54L, + 0x79b68b6702068d84L, 0x7dac80d0811ac72dL, 0x6d1e6d35a81a0a78L, + 0xc841e9ea3bd16283L, 0xa7bc1775894c4444L, 0xf2b63725f1aa1202L, + 0xbec7767ec7d4c556L, 0x2817ebb3d46ff51bL, 0xfde5be8d73f7e339L, + 0x44c6c9775aed24c4L, 0x0b9a1707b6e579cfL, 0xcff164789069fbccL, + 0x414b542d49152b00L }, + { 0x33c31e58606e173bL, 0x5b7f4e1b90e6713aL, 0x425fb512debb20afL, + 0xc788c61705120e70L, 0x3ef056029013e4ecL, 0x9f9d35ac81c6e6d7L, + 0xe131e88f9450690aL, 0x708f9b3244af082eL, 0xb2e4d66c1ba2aea9L, + 0xaf1f4a6e740db29cL, 0x74ab9248d1843007L, 0x13338ef8ed556a6cL, + 0xf48e623e270d17a6L, 0x3c7362fa9608f5bfL, 0x43977874444e8515L, + 0x52678d6ae00b8b2aL }, + { 0x5dff1c59df36aeb4L, 0x52d6653ca92bc0abL, 0x0e03f496927a5f81L, + 0x8509d4142dfd491fL, 0x258c2c52a571f89bL, 0x2bd6180493334485L, + 0x1a33e94f3f7d9e09L, 0xfab418d32c1bf906L, 0xf39c490e5aa5695cL, + 0x0e41196ef6d2d7ffL, 0x3ecd40750f7948a9L, 0x4b58f9b2d3053b4fL, + 0xb8ee842a5d9974c9L, 0x23a59c1dbf22f682L, 0x045ac614c8efcea6L, + 0x7040ba5bc10ceeddL }, + { 0x2c364f81515a1a96L, 0x31a63503184327e0L, 0x0a0966501ad93d4fL, + 0x9d7694f1273b6173L, 0x8886d876d2cda9d2L, 0x1e01a7422814c177L, + 0x3492276b8667696bL, 0x2fd4f0c65b25f006L, 0x6527349ffb294c4aL, + 0xc1fe0d8ade1d336fL, 0xaf9a23e8e7e3860eL, 0x97d2b721b774c31eL, + 0xfac3e5824365784aL, 0xff2dff4e70f4eaa3L, 0x3d281e1afe873248L, + 0x9043a6d60bd1c9c1L }, + { 0x1511a0fe766c7937L, 0x1b2ded5cabbc3be3L, 0x2ac160cce00888acL, + 0x928754bd616200f3L, 0xb801c83d34a2ea06L, 0x8ad7a03a9cbe106fL, + 0x996b0822cedfcd94L, 0xc3c3463ae4069880L, 0xfb12ea4df597f663L, + 0x2c8d383440c92af9L, 0x79bc85c64e8da154L, 0x95771fa2db4e801aL, + 0x7bd2c1381e3579b2L, 0xe45c75dfffaad078L, 0xb0760a3cb73eac46L, + 0x26362b483a125f35L }, + { 0x25c68d28eefc3e89L, 0x2d0ee87769e9ee71L, 0x8b07bb86af5e4b75L, + 0xdb709072cb86b333L, 0xfd3d20eaff552bacL, 0xa5eeb2b14c0da1e9L, + 0x391f688a44f97145L, 0x21fbd3101e06d485L, 0x45e4f2a5bea9cd49L, + 0x7b60d464a7bf21daL, 0x193f88c8054d5471L, 0x5ace53d1bee0f2e9L, + 0x92c26563c1439273L, 0x9c86e0b296c6b5eeL, 0x452fe23109ff59baL, + 0x2e952b20555c935eL }, + { 0x2a846bcad75f886eL, 0xe68a5dbed43dfc58L, 0x103e45b6007b1b86L, + 0x580e2ec9355ff2b5L, 0xbc702f26a263ecc9L, 0x2835b386181e5e33L, + 0x025113ec6c122076L, 0xa5c26e3a7fbd856dL, 0x8ef83fb39d6ebcb1L, + 0x7aaa53f2a44d2fa8L, 0x7c14ef3353b1fa97L, 0xff604a1117559a30L, + 0x2bcd96b0b09377e0L, 0xa5c14896db2f0273L, 0x1c0a84c9eb53ef06L, + 0x1236d01730378e4bL }, + { 0xd7481c8fc084373bL, 0x29ae4768646097aeL, 0x1300dfa0613bc34bL, + 0x3712714c934bc2b0L, 0x865246290e2be7e2L, 0x554fbb9fed010800L, + 0xf0ec0b3842314576L, 0x65baf594330a3282L, 0x3bdde1a8706ef817L, + 0x7d2c727dba7530e9L, 0xbb0c5d6674cc95cbL, 0xb3fcd3652438906dL, + 0x19881941d14658f3L, 0xe616f5556c97f0e9L, 0x353c2d854b9ec7eaL, + 0x02a48014620cb56eL }, + { 0x11d6d23d506ccd38L, 0x229a1c549059baa6L, 0x717c9c2769d011c5L, + 0xe87e1b46d828937dL, 0xf5d63bbb83835083L, 0xf0a7b427aadac258L, + 0x99ab26bd9f154d1fL, 0xdec0ffbf8ec955fdL, 0xee957c6749fcb880L, + 0x32395dee1e0114deL, 0x192a64b7369f46c7L, 0x4304466091eb2599L, + 0xbe2da887a2e8c3daL, 0xa44e2c25c3556d18L, 0x31390414b55f75f3L, + 0x1d8bde6f8f217fe0L }, + { 0x03cd39f8a2028924L, 0x6e54f19cb06ecb9fL, 0x862bbcb7d6f05846L, + 0xdbe067165a060776L, 0x9397c97ab10fec10L, 0xf42138266f1bb65cL, + 0x414deccba672ba38L, 0x594d4d43f88b05e6L, 0x7993f57aac94d4d1L, + 0x74fc2a6abfb17638L, 0xd8196b5bb6fc655aL, 0xdc375c84ee8d2139L, + 0xb9b00a02360d3a26L, 0xb36ed35cdeb93b87L, 0xf565b28bcc83209eL, + 0x349c6943c61013c1L }, + { 0xd1b394444de6c88aL, 0xd5c2c4714700207eL, 0xb6f458a221c2b780L, + 0x749f75640850993eL, 0x400ba579baef0c18L, 0x2d742938737c70f0L, + 0xc5a8e2ec21467ebfL, 0x243a666e5337f453L, 0xc991f1c7ed0bd50aL, + 0x3a7f3e90f4bd1f91L, 0x96089e8a5f0e129bL, 0xd0d3a17707389635L, + 0x9cf842d527182ac9L, 0x211952990817c5c2L, 0xa32f327e87255769L, + 0x056587ab89c2d8faL }, + { 0x008562ed1ce4733dL, 0x5faff7cb98e51444L, 0x5f03021fa9ab46b9L, + 0x89494c5eb61a8c13L, 0x57c9503636b35976L, 0x6be84c8f2ac2d2f6L, + 0x0e5b34d89bd2703eL, 0xc4ad918f7e872abbL, 0xc2a89e9fc4052ee1L, + 0xc2caee3f3190b51eL, 0x58fd14376fff254fL, 0x6f3c0d68883e0972L, + 0x63d0a0e90fb15438L, 0xc438764bf6caae00L, 0x815f15653f1d0f6cL, + 0x1b87f2edb86cdbdeL }, + { 0x35792bbb2b0b15b1L, 0xa3e4b5a7ce6ba779L, 0xfbacffd9dd8f3779L, + 0x005450bdc298d1efL, 0x0e3f5556c47031c6L, 0x0770f07a95d68066L, + 0xce3e84e02d1052c2L, 0xb050791e7aa8cc54L, 0x4d621e73ba3223a3L, + 0x87b9b94d39632990L, 0x8df9cb477eb8056dL, 0xe2430de8edfca0ccL, + 0x374bf4169712a0caL, 0xbe3f3c7788848a99L, 0xb22b87b1c4a3e59eL, + 0x8e0227c43e95bc23L }, + { 0x000e22a83210964dL, 0xdccd5df5ff056eebL, 0x02173a1fdaf1ead7L, + 0xd02833e067cdcae3L, 0x1cc574cb8bdcc90cL, 0x86eca7143224b4f5L, + 0xd00e603abb3f8298L, 0xb98ece1b0c1a8debL, 0x228a46e4378c261dL, + 0xc6f9dd0da6165e5dL, 0xb3ae38994b7ef0e2L, 0x3a3c16b3bda9f306L, + 0x5e9a26d338a084dbL, 0x528e59935394e950L, 0x848ecb114ea206bcL, + 0x14b15ab540545d6eL }, + { 0x0f6d86c9664c59a2L, 0x3dfe2be160fd7aa5L, 0x33f9b5699072cb8eL, + 0x5f2325d98176a7e0L, 0x79a0d4e74587080bL, 0xa4ee0def0d5d4e05L, + 0xc0ad9ffac87b28e1L, 0xd6f18d2f3f09b4eeL, 0xcc896ae7292e9d87L, + 0xca88953d6094763cL, 0xdbee97a818fbf9faL, 0xdf20e0e94b63d701L, + 0xcbba6e3047ea722fL, 0xce57e1ca612b571fL, 0x1e16ac76009a55f5L, + 0x742bbed8c4389e2eL }, + { 0x23ea86dcc1dc2c73L, 0x4bbbfd5bc1643abfL, 0x07f8fa1f24d8ca1fL, + 0xde68a6e08cb5cac7L, 0x7d54c64b54e66a7dL, 0x789dba22a9b7ad78L, + 0x4d88d540e364ab94L, 0xc8c2e02d1f72e011L, 0x4c82605746e2a278L, + 0xe6c35bb34b187c7dL, 0xed8b3dfeeb8fe0c9L, 0xb6bc34e87d11e415L, + 0xb3908bbfb865c7f9L, 0x717d1ce6e1ecc17cL, 0x151e3308f7cdd69bL, + 0x97bd5a14b5c94124L }, + { 0xe01c62fe81e82861L, 0x703d4b6ddd42c40eL, 0x7e52e55be65e91e5L, + 0xb8b493745abbbfddL, 0xb4f15f52c72a45f4L, 0xce8435a8550f29d8L, + 0x9df76b9b582de75fL, 0x52e84c5fa20c8b96L, 0xaf77d2d10a8a0af4L, + 0x0389bbd8ca6013c3L, 0xb0d9b9ba26f8305fL, 0xf053e8480cec8b9aL, + 0x4d63367affabda18L, 0x50f53be4a6424c2aL, 0xf892c58c864fba2eL, + 0x317c6d3148cc5469L }, + { 0x0c3525b02cb7d42bL, 0x55240bc9310facaeL, 0x8d5d2022ff20408fL, + 0x6b01402fe0c10ea0L, 0x7fbef68a718eb23dL, 0xa0146b5a41252a19L, + 0x59afce48110e0d6eL, 0xe9a1d27f022de181L, 0x6db96d16dc3f49daL, + 0xfc1ae3f5efbe4008L, 0xf9d70641eccbc11cL, 0x49022279525f8636L, + 0x3769796ac2763c30L, 0x9cc3483c1d90630bL, 0x451651f0ee3d3f17L, + 0x6ae597399da0b8fdL }, + { 0x57b13bc7bff4d2eeL, 0x2075422930b173d8L, 0xb6254bd50794936cL, + 0x1d5f232a5efd55beL, 0xc06f4a854e0c3389L, 0xcf2c5b598e61f944L, + 0xc564861ffd5f87b7L, 0xee261fb15a2afa4cL, 0xb0ff72262d97a774L, + 0x1a89ae22d6cf007aL, 0x28880534d346f214L, 0x8fe73bff97b6497eL, + 0x8a8595b2fa2afffcL, 0x9ef9cf3ef151a726L, 0xa84ee5f1e744b82bL, + 0x6649048dbc63fe72L }, + { 0x91b7bb781e8b760dL, 0xd47b0bd825aadaa0L, 0x81493d9ffab5226fL, + 0x4a6dd226bffc148eL, 0x5a032f8aa29be3dbL, 0x318dbc7034b0ab0bL, + 0xdcccbfb57d654868L, 0x8506ab379c581e46L, 0x09136a6e2830ece2L, + 0x48b79356cf6c80c7L, 0xfa176377ef6b1e86L, 0x2c9c1cc183f0f1c9L, + 0x96f0526d16abedddL, 0x3e0e98e2a93b0de4L, 0x6f2d7ada0f13873aL, + 0x4eb93b5cf3fa49ecL }, + { 0xbd89f7e5e11fae32L, 0xd13d74f5c4023f51L, 0x1b0014df491c3f6fL, + 0x1d849a57555279b7L, 0xbb9e889705ba0068L, 0x82222419c13ca2caL, + 0xafbbb685fd33676fL, 0x931c3f5275878a2aL, 0x12aeefefef3d5173L, + 0x189a5cc8bd8a6878L, 0x82cffdb3d99f0c16L, 0xbf565406a19d48b6L, + 0x5605e223e9c6c4e0L, 0x53e781de86804172L, 0xcdf5c90bc7001cc8L, + 0x2b582d937c043f68L }, + { 0xa1165c8281abc2aeL, 0xa73380f5e2b69ecaL, 0xc097b3d207fff66fL, + 0x5d60382654776506L, 0xdcbac9f3b57fa21cL, 0x78750db4c98dbdd5L, + 0x85e21103d9eff32aL, 0xceed172c2f11c41cL, 0xa8e392649e348c09L, + 0x71cb936b831eddfbL, 0x915c3d06f50864a3L, 0xfe8e33cde93acfcdL, + 0x4bee10d7b3f2f7aaL, 0xc1d8eb48eb7cee9aL, 0x4fa49ce3fa574afdL, + 0x78615109862db4c0L }, + { 0x3fe3f4807ae72c21L, 0x631aa144fd0f0da5L, 0xc76ee1e8f8c3a454L, + 0x379ae09451b4f1abL, 0x2a3a4397d7cdbb24L, 0x7a14cffe82bd5fcdL, + 0xbbe4ed12f427ef5aL, 0x9b0a43ee284d3ccfL, 0x57b78b938eec6e1eL, + 0x18d404e467b8e87bL, 0x0c8adc0534374c20L, 0x643736055428deb5L, + 0xb4d80ec0c3afa2cfL, 0x6d51f93c3aa956f9L, 0x9f9a28ab84161c68L, + 0x540b6bb76bc9c025L }, + { 0x04e1734c321d315dL, 0x4ef56612d86e05d0L, 0xeafae145bba8cd81L, + 0x1fb07a49acdc789aL, 0x6a21e9ad5877570fL, 0x2e4a837eb9bc53deL, + 0x436db2931d6298ebL, 0x43afbc78ea362f45L, 0x2a973d97aabf6585L, + 0xdce7dabe0c924d60L, 0xf69d98f07cadf0e9L, 0xe0b505a175020538L, + 0x3db7d1a34461cd29L, 0xe1c287765e20e818L, 0x2ca2586752dd50f6L, + 0x897cab1492e0388cL }, + { 0x59ed38130d8bab8aL, 0xc11d364ca438200aL, 0x0687bf2c40581415L, + 0x86ad0d3a7ac89674L, 0x44928105b97411a0L, 0x74984b11f383371cL, + 0x70d2ed840d1a831eL, 0xd883628b6c912fe0L, 0x44f8f7fb14fa88d2L, + 0x564f2a4dcf0ac93eL, 0x82f629aaa6c24fa6L, 0xab906ba3bf6cd949L, + 0x2c822e6720a5182dL, 0x2ff47dac30eb93a5L, 0xdc62c4a4fff673aaL, + 0x64b00763476b0ec5L }, + { 0x1e3f533eb3c9a404L, 0xb1db7f73b7ef9952L, 0xc7f13e296c253693L, + 0x7ce7f4c40738eed4L, 0xccfd3b33ce26cad0L, 0xd878493501ec5cf1L, + 0x3f8fc09ddc084e01L, 0x217cab32c39b5acfL, 0x42daf0bb9ef5551cL, + 0xfbc76f56e1217a95L, 0x80178b12c237002aL, 0x0b52c39fb070a293L, + 0xe3925153576ca964L, 0x2555942419d68e36L, 0x291fb82c09e50e84L, + 0x7dd22ea66618ed8cL }, + { 0x7ffe844b49cbb3bfL, 0xde0cc7045562fb25L, 0x1e6ee5379f5a845aL, + 0x956d7f26e51277fcL, 0x2c75d4b930635718L, 0x39a1489296957f34L, + 0x8cf4eb3282e5742bL, 0x6b0d3ddd83247b72L, 0x67a9f633201a4237L, + 0x416403c11414a485L, 0x60afd447b6f6a916L, 0x95f94930dac6f790L, + 0x685ff94bbd3b9d82L, 0x5c8f98fc51cadf0fL, 0x9559c88ab13b7489L, + 0x31377c665f18fcc8L }, + { 0x35c5de097dcfb35fL, 0x2dccca9f01cc36f8L, 0x7e93e85d7576cb63L, + 0x0c2dd48af7b4b375L, 0x9d95cd4fb09a19b5L, 0x752ed15971bfe607L, + 0x439880cf2596dad2L, 0xe52efb5369e90a6fL, 0x4409766303d3e60aL, + 0xfcf364faa95070e0L, 0xd8f993b605624dd2L, 0xb35a982400d5e467L, + 0xe289d0240c8f4524L, 0xef45423c648a0179L, 0x3a5fd695587edabdL, + 0x3dacc50ca11e5271L }, + { 0xcb3e4f946499ae4cL, 0xa46dcbe17053c527L, 0x807f5ce9be782e8aL, + 0xb6c64d28d8481e45L, 0xf35e4518aa286fd0L, 0xf7b7b9badf1cdb49L, + 0xf3fb6210aec23eafL, 0x0a9ba385b9bfd2fbL, 0xe51a0d538807f3a0L, + 0x7ab24404b17b2842L, 0x6fd57687f9dd9f0aL, 0xcd1efdb4f3e9df64L, + 0x5dd2df7a60df194dL, 0xbed3f2c3e069df05L, 0x469b756123248a31L, + 0x866949e1694744f7L }, + { 0x3a9a0da53f4ab07aL, 0x2cd6f333f54a6fbfL, 0x0c92e921b23cf290L, + 0xc9581c3e848e3d58L, 0x93af1fbdd3b218abL, 0x38598ea1066cb4d7L, + 0x5001394e990c03a0L, 0x3b664b1e7d0877b5L, 0xd79db1bbd74c7091L, + 0x852d44354e2d5dd0L, 0x0d2b841b3329db82L, 0xfa844eb07b96d480L, + 0x37a50569c295dc46L, 0xc2d3837394f7ec4eL, 0xdc3884ff5b083177L, + 0x574352b88b1fa598L }, + { 0xed2193f70d5d7ce9L, 0x3c19fd260b487eafL, 0x7c44ab597be65fd0L, + 0xdd9da86078270d56L, 0x8a84ec00baa70198L, 0x2ec27e49285985dfL, + 0x996ccaf0de2028d8L, 0x4e7648c761c2201dL, 0xa96335bc091c19ebL, + 0x253a3a69f0d6782bL, 0x3f204340d2946493L, 0x444521a1099f6873L, + 0x5fcbcc096996011aL, 0x3884d5d8f853a94eL, 0x2418c624d3b6a3a1L, + 0x3e431af206ae3c4fL }, + { 0xf967d93983d381f1L, 0x36501aaed0c033c3L, 0xbf3af4d054410768L, + 0xa86d15985093a6d3L, 0x43ae0741d92f2900L, 0xfeb2afa636f0b755L, + 0xd090a6a3aa456d6fL, 0x336a4fdaaefdb646L, 0xfd1bfe441a942f7dL, + 0x7fc2a3ed851ee41eL, 0x4f1c968611e935c5L, 0xcd57766653bbb343L, + 0xf26931baad896c2aL, 0x8a0fbbd186bbfa41L, 0x1c3d7d82a203cef1L, + 0x6dad3f15e2664d35L }, + { 0xd1940b7d12ec35a1L, 0x6219c5b6e7dfb128L, 0x2cc278c6f13321d5L, + 0x5e76904a33c58eb6L, 0x15090f55d9903c43L, 0x061bc926c3d96a19L, + 0x974a9f038c0acba7L, 0x7a4140217198b21bL, 0xb069599df8958c6fL, + 0x517f2f1dbebd0129L, 0x1109a613df3a8dc3L, 0x08e58448672375c5L, + 0x56590ba49383d2d3L, 0xfc3ee7c60bff837cL, 0xc87a539027d2d55fL, + 0x2438e9d45f517a3fL }, + { 0xc4a453088815af3cL, 0xe55f1a32f3c9bed5L, 0xaef1cdc997b65ddfL, + 0x61c61d9412e51eb5L, 0xbd0dac54e63f2490L, 0x6f14429cd0b3e231L, + 0xf737c3c2f1da6010L, 0x7150e04b6bbc4fb1L, 0x205b4c891be281cbL, + 0xf1b4633cd7701f5bL, 0x8b33ef462a513490L, 0xddb47c7368f1f7f2L, + 0xf4ada511bd416b67L, 0x9d2a97cdff795bb3L, 0x00a8b7b296200e67L, + 0x13f39011afe30e01L }, + { 0x3dd296ef7bd0c827L, 0x506110f34a29ff46L, 0xf87930681c9a515aL, + 0xde8d8045268bca77L, 0xcbb83024998045dfL, 0x3f90d71068c0e584L, + 0x2a838ca8263b6062L, 0x293bb5e7535c5d0bL, 0xceea99d556415110L, + 0xfe311ad01bbda005L, 0x2497e0bfa4d8d018L, 0x33dd77a01cf2b866L, + 0xbc075b73d8c4ba8bL, 0x298466d4722b7bc9L, 0x17a7ce24cbda1b0bL, + 0x458d4b6b680703b6L }, + { 0x8a26a20e4d54d8b2L, 0x05a5696e4d320a0dL, 0x698b5858f994f700L, + 0x7a4adc3c2f6549a8L, 0x1812e8193694d00dL, 0x46b9b000730402bdL, + 0xe10a1449a1b36410L, 0xeae95ea599230220L, 0x3efc2e9b1b4820c3L, + 0xfe5b5cb585c9eb8aL, 0x21ae031997847064L, 0x68ef0b708f27d49fL, + 0x3259ef182f72556bL, 0x00ae0457624db01aL, 0x628e3b065668f95cL, + 0x5f13f5fab6fbbf91L }, + { 0x7c6ed9ae3a9b0dc6L, 0xaea1bde96f883ec8L, 0xea66bf88ea8b3677L, + 0xdefa6abc9a66e3abL, 0xc4d3317b68217ffdL, 0xf741c8f2290df05cL, + 0x1f0fdf177d11674eL, 0xfdf0ece7c35989caL, 0x0eed92df6b9c482dL, + 0x73713e6655bf1ca7L, 0x90acb29025cec99cL, 0x37c9e3a2e803e69cL, + 0x7c0a3c5317713a1aL, 0x350dc5656f5a174dL, 0x11625a4405f802f6L, + 0x2196495da37ba4a2L }, + { 0x00cb2fd313142680L, 0xab9e91d765d14cf4L, 0xc6a0ceabdfe2669eL, + 0xbeefce580ae22bc5L, 0x3c2b7986cb6ec250L, 0x84adb1a2d738f1ffL, + 0x9709bc28516ec8ecL, 0xf36931298e8f7db5L, 0xc48efc6b95b197f9L, + 0x9ff109529aaaa404L, 0x2c3c8cbd144154b0L, 0x33ef7bc3427f3435L, + 0x04a17940d21897c1L, 0x5aa0c47d6ce548a0L, 0x2971cea73d56fa62L, + 0x93ad0eb004475f08L }, + { 0x7a0b6967988a9963L, 0x61e477f76515e8ddL, 0x6274e3863b6b50f2L, + 0x63a9b8d5d33922deL, 0x3c38d3fb687a5b3dL, 0x18f6f09c1302e323L, + 0x254c05c3e02fcccfL, 0xc04ed0b726e662f7L, 0x1d5646b8143fe079L, + 0xef8a9448c9016c8cL, 0xe5674c4bf823d797L, 0x0586f72fbccde451L, + 0xc5fc88d54417eadeL, 0x2b952209576e588dL, 0x4408dd425844d1f9L, + 0x73f8c3f0ea41c034L }, + { 0x89534fc85df763ddL, 0x3b1427f33ac71836L, 0x0db5be176e8f15a0L, + 0x1d390944cb20888eL, 0x7804c9ad857caea6L, 0xaa584428519f7bf3L, + 0x626eecf1293aa8cfL, 0x749e0d98ea36a015L, 0xefff6dae3321edcdL, + 0x963deea628b791ccL, 0xa14e05522d16e361L, 0xa2e058fcb15ae206L, + 0x0f268745fca325e4L, 0x7cf9d40721341a8aL, 0xdfed25d97caa51b8L, + 0x0108ae39adbedd75L }, + { 0x54d178f3a9e88f63L, 0xaa05b11eab0c7325L, 0x773a53e6e261d8a6L, + 0x24db7dae8d0b91c8L, 0xde10b073e9bb004dL, 0xfc8befe754e3090bL, + 0x16af05990cc69c89L, 0xddc838039d59511aL, 0xc3f65b9946c5dafcL, + 0xfbbe4be81ee0a599L, 0x88891e36fb3a9b17L, 0x0c9aad75445dad00L, + 0xdffc46abd5097e1fL, 0x8848089bac85a4e1L, 0x348bb42fa0c45233L, + 0x807c06d8eb13c1dfL }, + { 0x00a969ec98ee0ef6L, 0xba9d54838bb7b7afL, 0x24484c92a02f8fdbL, + 0x7bdb201a8b70557cL, 0xe59343e460ad1af2L, 0x53a9a942998c95fbL, + 0x974db3deda861d3bL, 0xce1525c9ed399c0eL, 0x89b56881f72109bdL, + 0x08ff7d15998211a4L, 0x5df76b3aef0f275aL, 0x93f180f7fa2f358bL, + 0xaac4ffcfc39b0634L, 0x2692c62617583b53L, 0xb2fdfa36b55399fcL, + 0x16424c6c99607a61L }, + { 0x5dd65c55dd2744a9L, 0x2544c1c2fe3af418L, 0x32c82e99efe8b089L, + 0x30b7ab25a9df691aL, 0x983845509be99674L, 0xbcecd258caf2d122L, + 0x88ae4098bcc77272L, 0xd43961414b8efa0cL, 0x44ff67b9ed64d12cL, + 0xa9e655e42e7f3404L, 0x3d16fc4545b0e9ebL, 0x474a3e14f03ded28L, + 0xa3c9adffacccb85cL, 0x3dfe6bc17253a51bL, 0xdddaf4b9fb5831b1L, + 0x5544e602a4f4478aL }, + { 0x897c5313baa80b4fL, 0x0122716f63bdc8efL, 0xae2742db7b42c5a8L, + 0xe9d9e1e90883308cL, 0x352c8c3f2d341ab1L, 0x163d0500ed945870L, + 0x8349dd73c290d9d8L, 0x2053c5e01f6c7d29L, 0x83107446cb42033cL, + 0x76c88bd209d09af1L, 0xd0f70e6eb2794681L, 0x720b59de19b1b540L, + 0x80b7ecdc22994b43L, 0xc1a4cdce2dec53cfL, 0xdd7d3edd1ed60f42L, + 0x5735995ce241d261L }, + { 0xdc4ba3fba0237056L, 0x6856c16433ab3388L, 0xc01eebbd271ec612L, + 0xabdeb033e3031becL, 0x4eee44196118a1f5L, 0xec4974215b600f33L, + 0x1b7185cf08868773L, 0x7b0c46cd7c1b7dfdL, 0xd143b2da4a4c5e89L, + 0xdb9a5984bb1ff94dL, 0xac3904e4c9cf3465L, 0xf8729bc0eace64c9L, + 0x5cc22821768ad99aL, 0xbbd3b0818a9540c2L, 0xe468ed5f049a6917L, + 0x885486df3ec45ef0L }, + { 0x6a942c934bdff464L, 0x3db2719f25a7b451L, 0xccb0070b325be324L, + 0x2055a31b19fe3339L, 0xaca69ae8241ee8ffL, 0x7607dd0855ef8defL, + 0x9e24960f1a1b73c6L, 0xbcb0e8a271d36810L, 0x29e11aa26885e6b9L, + 0x98b5d0ab185eae19L, 0x1a0b96e40f81f91cL, 0x4d0e8bcf994fc503L, + 0x33d81697f119d6e0L, 0x29083287aaa4ce0cL, 0xc5dd4d3ec91ff9d7L, + 0x31cecfe8d4ab962dL }, + { 0x437bfd9afc8b21e8L, 0xe5dd32b3b19436dfL, 0xfe5902d4921c36a0L, + 0x8e9de84da3d0fa90L, 0x9663e6ad5bb523bdL, 0x9800a23faecd6975L, + 0x1009c0d9b4fbb59cL, 0x839aa7bdc9d20ff1L, 0xf502f66decd6fa3dL, + 0x480ed4fbc5516ca9L, 0x65ffa5f66c742ac4L, 0x2b7c7945ff3252f8L, + 0x72fefc0575d9cb3dL, 0x11b0863bd6d6f1d2L, 0x5d8f3cf09a6a4ec3L, + 0x6961b46ada2547b3L }, + { 0xd07b587ecb35e2acL, 0x1ed5546b57af14d9L, 0xeca17a5bdb28a04cL, + 0xa1f91d44709d54f0L, 0xa6e719fd9c6f400eL, 0x4e4b88edfb8ce190L, + 0xf9781edd246e3fd2L, 0xd67120e6b655af5dL, 0xda782d1d93413ca7L, + 0x697e20a29707fa21L, 0x1eb51f3254e84123L, 0x2e254d9e36051f9fL, + 0xddaec42b73ce5be9L, 0x89a9a32ecd3f794fL, 0x1964e22f0781aad9L, + 0x6a63a90c53755212L }, + { 0x76554e003d7acbbbL, 0x2c01668ab74f6108L, 0xe4a29672388c519bL, + 0x016677143eb94d4fL, 0x086a3cdf0cd6d2f6L, 0xf86580217b370f7fL, + 0x658880c15a4d3e7cL, 0xd6ed58165ba3f4a1L, 0xabcc78135ca471ddL, + 0x809bf074e844a576L, 0xa53a81b36ea502eaL, 0xc20b93070e021ed3L, + 0x8c27f8928617f165L, 0xa54764468235cd0bL, 0xffc89ffd82552961L, + 0x51ed4a22d151d90eL }, + { 0x37d6963a449701b4L, 0xea8d91a3bb27caf2L, 0x3ef9be15b572965fL, + 0x75a7a055db50bf7dL, 0xfd67480ece643b9bL, 0xf2a60d2d6ceb5d5eL, + 0x68fc320c5ed7c897L, 0x41c53cf628ce685fL, 0x0e29711f7106615eL, + 0x7a87213823500eccL, 0xaf0a92606c29fe48L, 0x93df3f2ae1ef9712L, + 0x0d5f6fb1d2d169bfL, 0xeb7afe2674a9793cL, 0x4173d94ae9f49256L, + 0x2d6951bc2b8b5ce5L }, + { 0xdd007d9f904e222eL, 0x333f248f86f4e109L, 0xd4994e8b8f429eeeL, + 0x29573415cfc77518L, 0x6e7fea3a0b0f42f1L, 0xc795cb7dc2743519L, + 0x820a8f66711e71a0L, 0x83d95d9c2b874f55L, 0xd4b64d78e70e1627L, + 0x924353f58b92a742L, 0x322048b1447b5e6dL, 0x0bad730cbcf931a0L, + 0x75c4d089a7af2268L, 0x464904c1b83b93f9L, 0xa24eba02165b3aeeL, + 0x65c48e78e08cc5f0L }, + { 0x1a1c73cede222c22L, 0x5683d8cdfcea23b4L, 0x0301cb14b2143b06L, + 0x284adf8f59fcec77L, 0xfb1c581c31204cefL, 0xf54d3eee94735107L, + 0xdbf67f0b4d3188c0L, 0x76a3f2d110f18d12L, 0x3809fa2807d3e013L, + 0xf06f0a4625e7ece0L, 0xd82867edb2895d2eL, 0xe106f48908b0553aL, + 0xe2280fa6ef245445L, 0x402d5785a8d9a3cbL, 0xf63dd9ffd438ba2dL, + 0x36b5cd2c7a6b226fL }, + { 0x87ff4e20545679a7L, 0x64d80b414520c750L, 0x90a357fa9b459cd8L, + 0xa19eaf39c85af1a3L, 0x0d475d798d935a5eL, 0x74501983781a678aL, + 0x748397790cc2e810L, 0xc6a21d112f412244L, 0x8d0e85f936a51a37L, + 0xff50151eeaa74df8L, 0x14e182a793cf99c4L, 0x45593df1376a9ab6L, + 0x18f73caf522389ffL, 0xd27cc960f7445e8aL, 0x0692f4c539a51dc8L, + 0x08d7c144db39bfd8L }, + { 0x809c0d963ecca773L, 0x87ea9192d48c2156L, 0xf0eccd74db6bd641L, + 0x773123742a678cdfL, 0x7a966d8bd1587b7eL, 0xf3c1a1016130a4c6L, + 0x7cc6e8385fce17bdL, 0x95e95bb8a8de7aa4L, 0x3fe1e8b5898308e3L, + 0x0197243ee347694aL, 0xf3fe9c42bb0cd2bfL, 0xb59052640f9b2b49L, + 0x4c385e8bc7367d1fL, 0x1d3050aeb5ee147bL, 0x8e2c387904004ad9L, + 0x5f2aa8eebab70202L }, + { 0xe208d4641266524bL, 0xb7bf3880d0a19f66L, 0xa5aa685eda106ebfL, + 0x0a69e8d3e642dd46L, 0xef349c61c682e4d6L, 0x26f6ee3b0fcb534cL, + 0x7daba12705eb67b8L, 0x2babb27e18be05f6L, 0x959afcba8e2d85d1L, + 0xedcf2d1ae2d9d386L, 0x59dc52e61ea6f06eL, 0xc28278b4866e5ae8L, + 0xd9ff034002bcd3c7L, 0xe884ac76784be82fL, 0xa316498083c9f224L, + 0x62501a98b46ff949L }, + { 0x563f7d9aad264086L, 0xca6a33dba5e0e4bdL, 0xe82530028c8d3d67L, + 0xa288dac846e64b19L, 0xfa3c919720aa4536L, 0x8130c9b0ed553eacL, + 0x622806e02ea8abd3L, 0x52fbf54dceccfe77L, 0xbd9a8e314f0d1b70L, + 0x519d2133d59b1741L, 0xfd74101c9a6fea8aL, 0xd1acf7a0b5c4eb10L, + 0x78499b7391f9da5eL, 0xabaa4c49c0dea586L, 0xcc9c5f73a1f3531aL, + 0x497b15fefd3fc665L }, + { 0x8a56cbaaf45568e9L, 0xf491a0fec7192a6fL, 0xdbb03dd39ab2539aL, + 0xc86522f84ac37da9L, 0x8c8cdba202a0f5b4L, 0x8109fc75a29c539fL, + 0x9cd06d31ca90f02eL, 0x8f31f0443e216dbfL, 0x99aa68acba3ebd91L, + 0x2a80d0d242c007f4L, 0xdd8dffbf86a9b7ceL, 0x405d3e84d6308edcL, + 0xdafa33fe068012caL, 0xc2eebd13edea1071L, 0xb7ae7e5c2ff637e6L, + 0x18d46a6c9e514cb7L }, + { 0x868cbb22a78b7802L, 0x0745ddb2497cbaf4L, 0xc4eb2f3e42ae8addL, + 0xac0abcdab4ceb4e4L, 0x2e0d8325a325fd40L, 0x6cfe057113ac7345L, + 0x7407a788b14171b9L, 0x70eb06036da7a52bL, 0xab0b36f9d85176acL, + 0x14109d297c2954f3L, 0x370de9c8dcd705adL, 0x3f0db5cd7bb5e751L, + 0x45f93d41a06e708cL, 0x10d54f8a7e93050dL, 0x69e6f8e45a38fef9L, + 0x55044601d3f62e40L }, + { 0xd1c5c91006cb9cc9L, 0x542074d741d00014L, 0x7cd8663e11236fb8L, + 0x39721ffe29ad5f82L, 0x1d21fbfa2951fc83L, 0x1cde06e7400d144fL, + 0x9042596b91792e6bL, 0x3365c8e529ad5166L, 0xe2220e859aeefe98L, + 0xbcb5318970c2aee3L, 0x477ca3db9ff100bcL, 0x27074176f532973fL, + 0xa12118ac9a2bd01bL, 0xf34252093dd79f93L, 0x563a8ff7c6f5d7dbL, + 0x0da313fcd7b0ec4fL }, + { 0x37125a8c15aa2557L, 0xca21d70c00893e9cL, 0x4871399467b8a823L, + 0x0d3e9a747cb0042aL, 0x2d2bf4ffc9e2ce18L, 0xd5531a0d049aeac2L, + 0x4d29a616f03d0660L, 0x473d50d61f1b7f00L, 0x3af0ecbbca3de50cL, + 0xe2959bea09c28f27L, 0x6d7c2ea0f8704664L, 0xadfae4e1731083efL, + 0x50940c26941c2554L, 0x44167410a1162d03L, 0x620230d81e82290eL, + 0x63630be8db414accL }, + { 0xbf8d52228a7d2e41L, 0x49e75823eb62f879L, 0x1b4d33dd6c402d89L, + 0x883e04d6de2c59adL, 0xbf3f38f449b9dc38L, 0x9d997d18b4b70c4cL, + 0x1f69b20c13cea045L, 0xca3d702558e2606dL, 0x3d4fd977261d1b79L, + 0x56aeafa85a1436faL, 0x369b3e98bb443c07L, 0xfce5186ce558f6beL, + 0xeb0cd478f8ac8f89L, 0x68074f37d5e5aa72L, 0x295845c068544eb0L, + 0x306a9871f16688edL }, + { 0xbc451e9d634ec136L, 0x1edf27ca0e6f658fL, 0xa9be0152c0db4120L, + 0x87b6ef20c5bfee67L, 0x352832389a2d6023L, 0x60e564d8c7afb899L, + 0x4af22bc00ac9c2deL, 0x28e6f63182a9d22bL, 0xc075c701f532701bL, + 0xf6d418f882075f91L, 0xf9fa628d1beaa511L, 0x551e7a176e72a13dL, + 0x9306215b77f4c01cL, 0x71aba73193c9d588L, 0x6443ebe058e57cd4L, + 0x2833ac41e8103e37L }, + { 0x7e564b868da5ec5cL, 0xac3d9da81c08db24L, 0x9d7c1f0b8c57a728L, + 0x3512afe79d343dc2L, 0xb438e4cffdc60339L, 0x7d5a2700dcfa1941L, + 0xd5f323f827320449L, 0x1b87a58e1393c6e6L, 0xecb68bd104baa431L, + 0xc09c1c5a4722b4d7L, 0xf42faa97206b5faaL, 0xe1dcbcd69976327eL, + 0x655ba9e4087787d9L, 0xbd59c757de5c0191L, 0x673020ed0bcf3538L, + 0x120cd454a49d6303L }, + { 0xebfdb8f4cab0f9eeL, 0xbc003ef02cce58eeL, 0x9b6a68415a8d0665L, + 0x642ed3a69b957774L, 0x3de487f04721ab5cL, 0xef2ff38021a4f0d3L, + 0xbd16f55829dbddcdL, 0x2ef05b4b0e93dff2L, 0xde1faa120bc9aec1L, + 0x66dae2c2d467fa92L, 0x758daf645eb33e34L, 0xa67ad9f68f0103cbL, + 0x151f693a9be02430L, 0xd5698496eb4054bcL, 0x8ef1677e7019336eL, + 0x021cfd167fdeea3eL }, + { 0x5c73715fdf5c36f3L, 0x703bde37d64ad254L, 0x55368d10f2cf7713L, + 0x1e5ec7b70f3993c8L, 0xfdb16776304ae4caL, 0x0d8f717e3d3bb18bL, + 0x5267073f66343d5aL, 0xfaeb52ef156008b5L, 0xb97ad5f9224a470fL, + 0xaf86e391ed2ab51aL, 0xdc0c7e579974302cL, 0xc88fa817fd0ae28aL, + 0x807c22dfbf8ed59cL, 0x5dedc231eb128bb6L, 0x71edcd9ca20595a3L, + 0x07265b46c73cf78eL }, + { 0x73dd99f0bd66232fL, 0xc59aaf89c4027716L, 0xaf826dfa5b860fc4L, + 0x239ea8aa7a943f3bL, 0x0e0e1b1a523c428dL, 0x55ea0e3a6973b95aL, + 0xea399caa2557753bL, 0xf8adf72f06957b1fL, 0x0389f3413bd34302L, + 0x333f27d0f8a43a97L, 0xcd9c0c08adaf796fL, 0x6dcca49b49c12aa2L, + 0xdd88deee7a0ac6e9L, 0x8f47575d0644080eL, 0x6e9d667d0cc2f4bdL, + 0x36c5754b31d1496cL }, + { 0x9120046ef323d84bL, 0xa69911227e789c4fL, 0x4b0eaf4e921b8055L, + 0x6339844a8079974eL, 0xc905466a740f8c79L, 0x1c18d0f7cd6def49L, + 0x5297da6b4b23e4baL, 0x1c09dff3c41800c5L, 0x6c49075b37ef6777L, + 0xa94c3a4050513dedL, 0x3d6742e96b0b1705L, 0xc0784494c48af5aeL, + 0x40c01532c95822deL, 0xa2ddade5c164d94fL, 0xfc8a8ac9a2975eb5L, + 0x06fbf8611946944eL }, + { 0x2d65338e3f45aa97L, 0xd83b58c81d040febL, 0x05fef59b0fdef8b9L, + 0x7beb071ae4d7417cL, 0x982b61f5b30a1a23L, 0x4c5f2a2afb65bd03L, + 0xe40abc9d5cbf6bf3L, 0x422c326df06612a5L, 0xc921e69d9571ae28L, + 0x7c88b10b23d3434eL, 0x96d2e9579da07933L, 0x833d46a13619cf4dL, + 0xd9d19653d95eefa1L, 0x2a7d8411a03e8f0eL, 0x5e64295304bb5ab1L, + 0x5e9ca0fd1f0fa9eaL }, + { 0x5bd54571197c5dc4L, 0xe2da40bfe78a95a2L, 0x65fb9efcffdb0eb2L, + 0xe952dc2c0d17467cL, 0xc1fc9c7bc758c6a3L, 0xfc79562cd4034a9aL, + 0x26e36fbe61f64b56L, 0x6adc4b9e1e84728bL, 0x7f165fd3a8f9ac8aL, + 0x7bc93a4503e3e013L, 0xeacc5513656478e3L, 0xd3391717064ddc77L, + 0x75b318dc76936914L, 0x69b1f1c7362424a6L, 0x8cc2045b49955f34L, + 0x940622b3c6836af8L }, + { 0x4710ccb70d997973L, 0x3b29625dd3f8f115L, 0x8cf0c4d55b97abd5L, + 0xc6321e0a673e14a5L, 0x0541af9d3d262246L, 0xde6d87546fc83b11L, + 0x47e97da8f01652a4L, 0x0f82b3a6ad9802b6L, 0x69aa4075ae9c44b2L, + 0xaf3f5de2ced2bf77L, 0x1ef1ea8a497a40daL, 0x2e0f86083c23ba9cL, + 0xd8a998a4f190a2c8L, 0xe2b49c8ccfde3368L, 0xb9f49824bde6bd71L, + 0x80bb1664785bedb6L }, + { 0x05e575fefd145cb5L, 0x155ee561ac5e6883L, 0x461e70cf8793b273L, + 0x9f1553de133b2338L, 0x2fb9e0c3a2a7ba07L, 0xc3bfd6a83e7086faL, + 0xb6ba85008bb4cb93L, 0x0b66d78976f82dbdL, 0x7d5a6ff654eb49ffL, + 0xcd65d2371f20b322L, 0x79ea49c254e29cdcL, 0x64975963cb118ff9L, + 0x969598ddcc58000bL, 0x95107918110c779cL, 0xedfc154863b85a35L, + 0x077ba5ea41212350L }, + { 0x0b3a38d3cdd86f61L, 0x431214450502a0abL, 0x1912edc5806d0272L, + 0x01dc1f988a32f10fL, 0xbb1d31d10e80c760L, 0xd46ec7e5f464e8b3L, + 0xd569af369abf49eeL, 0x9d286ea72cdade77L, 0x2be7020d45ad5920L, + 0xabe5236e6299ae7fL, 0xc93179bdd3f55c07L, 0x8138995a52350e80L, + 0x0901265caff07586L, 0x5b3c81b2f4739653L, 0xbaf7581d9bc77d21L, + 0x6b2006df4591a2e2L }, + { 0xb2fe50a8965b1bc1L, 0x931f536a962bb4fdL, 0xd5718d33000e7f99L, + 0x84728f2553d5125eL, 0x4f8a6184d2125cafL, 0x54f1a701357f679eL, + 0x70a9f40c1531c05aL, 0x10d0cb976fa8b775L, 0xb476f41e9dc12ce9L, + 0x5c8d7a752755f894L, 0xd6c12e10625741a4L, 0x262a6fb8c917b16cL, + 0x24d116e638d6b0a0L, 0x849540c032c38e83L, 0x855b911c66868afcL, + 0x53217ea6bd26b550L }, + { 0xfc840473259f52b4L, 0x968da9cbe621146cL, 0x964eb85ecacbd26eL, + 0xab7daa2de4a54344L, 0x6dc3b848381a4ff7L, 0xa07a96b341c815efL, + 0xc4fae9e8c3d4b1e1L, 0x0f938d1e42ce9ea8L, 0xa727dacc35cc052fL, + 0xc81e01c9e9a06f07L, 0xa9e08dcb4a6d65a1L, 0xf8e2d1736044a9a6L, + 0x99893dd0f2bd295bL, 0xa08d3379f9781b12L, 0x64bd600161830ac2L, + 0x0386931ed9adbeefL }, + { 0xd0d7abb3d09885a5L, 0xed9d2b67e355bb07L, 0x3bc238cf536ebaedL, + 0x61ca2e78699ce4d6L, 0x354ff447111594cdL, 0x55cbe70903316ad2L, + 0x418679fd49fff5c4L, 0x75bacd750f9c6c40L, 0x677edc882972721aL, + 0x82596887e5ef502fL, 0x459e9367bf320e0eL, 0x81ce36ef8bbdccb2L, + 0x1ba097fcb766863dL, 0xcd3a21d6d58c6db8L, 0x0e4967cdb4a8748bL, + 0x2caaf74915041c20L }, + { 0x44f980066ed20424L, 0xb3e4ea2322471545L, 0x268ed1a5781a8c86L, + 0x48d0ab757ae5b70bL, 0x6ca8b320356d3982L, 0x9ce8e6812df31fa4L, + 0xb909d232d925dcf2L, 0x302c8f78f56723deL, 0x11725d69abac96f9L, + 0x656a47ca57d1a170L, 0x6bb5d511c18a2be7L, 0xb56e45f1ad50d9d9L, + 0x36e886e270b05518L, 0xc7c71f3d09d8ff91L, 0x65a1bbe29350361eL, + 0x86d7f53245fe3bd8L }, + { 0x99f16eb6b0bf719aL, 0xb69750988bc3d913L, 0xfae50e5226cd01b4L, + 0xd3e3ac5490898d1cL, 0x4da3b9db887ec666L, 0x58300644fbea45b8L, + 0x369f3bd98355b058L, 0x0fb239a8579bcc13L, 0x4f5b45396e2bd811L, + 0x007f3baf24198fd2L, 0x68a676db8837d51dL, 0x68eeea62eae75b16L, + 0x5ffe5f943db6083cL, 0x52c94d0f7d836c5aL, 0x5a4c3c6fcbc1ff85L, + 0x682a55e386c0b4ddL }, + { 0xc8f235a4587495aaL, 0x2276026c34c7245dL, 0xd6ae0cc5b75a46e3L, + 0x890d3965ecc3e5e7L, 0x1b13342f14296629L, 0xc89927e68a877227L, + 0x1543f27e2324a68bL, 0x6c44768449cdc21aL, 0x9bc7fd4f1452d0acL, + 0x2cc30a31ff4b045cL, 0x415d46a0852f7611L, 0xad737052c6fdd7a6L, + 0xdcecc3ab7b4c7c91L, 0xd2cdf01b7688d70cL, 0x054f2542e40d3905L, + 0x02227fa6fefe4dcdL }, + { 0x1805efd9b751948bL, 0x8efeed46fdfd225dL, 0xcb128e094f2c8b22L, + 0x9d1090bf96f7c5e5L, 0x0959d044b4cbeca0L, 0x21c955f98e08cb04L, + 0xbc1f279d68fa4fceL, 0xb021e14e0710ae9aL, 0x64d16e9f881167f4L, + 0xf5a5c22ebbc9f1a5L, 0x5f3716dfe3420eeaL, 0x971eb915d5c4e843L, + 0x64fc55fc28ffba81L, 0x3427e54d7dd37578L, 0x446e6a6215ebc7d0L, + 0x547e249a29269778L }, + { 0x4706868aa1ffda27L, 0xb4e6cdcc7955cf50L, 0xf65151e10a63f3d8L, + 0x5b4127ea9de5e70aL, 0x3d2c09baf9342823L, 0x18c99d83aa2f7d51L, + 0xa0c5bb1dddeec025L, 0x7ffddf8403dcf1ceL, 0xe57e4d29616fdedaL, + 0xd24565697932a1f0L, 0x7475e0e83191d4e3L, 0x3479bea1c220218bL, + 0xfceb5c908bcb2505L, 0x1c685cea3c6132e6L, 0xc42dc745bfe6c1ebL, + 0x45a41cc0d2b08eeaL }, + { 0x3ea9b2c74dbbf0e1L, 0x41ff962fa17cf70eL, 0xdc1ea7585eeb4c66L, + 0x4f5412d2a9beb17eL, 0x2c9e4f52a285741aL, 0x93df7da4984fd11fL, + 0xb2afbddc0df3184eL, 0x96323d252421e375L, 0xc87be1e449df781eL, + 0x145601ed3d589beaL, 0x0f0bd9bd28fff6ddL, 0x2d3259d48a0f298cL, + 0x362d7a77d88e6944L, 0xa84c06b6b6ac2af6L, 0xba850ac9d087da02L, + 0x128763c942ee40c8L }, + { 0x29a80f07acbac178L, 0x7cc2004434b08f6eL, 0xe9631d1470feded2L, + 0xb2115da386615767L, 0x7c75f5c4cb088548L, 0x5b29d2139a2e8e03L, + 0xfe9fda668b881752L, 0x3f1d8d88c1de7ebcL, 0xb476565e03218123L, + 0x07365561b1c995f3L, 0x2160cb18b13eb71bL, 0x7e8da51399b3a0ebL, + 0x5e8ca1f9b20fcd74L, 0x6a7e0067b4126d72L, 0x1e8204b768bb637fL, + 0x75e96bccfc4f74d2L }, + { 0x189d1fdc0d19716eL, 0xdf5850587c384525L, 0x64a846d1ea987d2aL, + 0x12b6bf836c07150fL, 0x91d85d464d6fd5b7L, 0xa97888364f53f55fL, + 0x60083bd881509129L, 0xa7672683ea876f48L, 0xe80b2e7ac15b2489L, + 0x985ef8d242d1d992L, 0x9c57b029cf3de492L, 0xfe02f83cb1487627L, + 0xaeba4fe48ae5b687L, 0x8a86f09b5d6b8196L, 0xd88f566ba16e523dL, + 0x309a6e9aba268949L }, + { 0xef27ee50bdfbe97aL, 0x1a5fe70fb8c50c4dL, 0xcc7beb017fe09f5cL, + 0x8fa15a85bed36cc5L, 0xc0c3acdb7550ed3aL, 0xc581ef87eb908681L, + 0xa15b3362c49d5ccbL, 0x0fbb17141fa264e8L, 0x267f8d8f8e1eee88L, + 0xd31ccfd621c2b63dL, 0x924dbe7d53be7efdL, 0xd42e877fdb2a358aL, + 0xcf9673c775d68ac1L, 0xe35978fd714fea55L, 0xeeb366535769b202L, + 0x0458258ad7593789L }, + { 0x5df71a74a042dbdfL, 0x2d4058575779dfa2L, 0x0e66cba70d2e6657L, + 0x285d6745ca2e892eL, 0xf56a8def0f0e6b5fL, 0xe0ee851da30767c3L, + 0x98c0565843346b9cL, 0xb35fce26d6b3c742L, 0xc0895bff39777e00L, + 0x83c8f6a6e7b6d886L, 0xbee148434f02904bL, 0x7f74915b2e84ec34L, + 0xbaaf663c96d10991L, 0x004b8757e41facc0L, 0xa2b880e56f86c029L, + 0x53f4a3e095b77358L }, + { 0x11bb08ce89fc48e7L, 0xba60c577afab5aebL, 0xf06bcbf8a0c1cb5aL, + 0x7d2efaea79757cb6L, 0xe26d90b176319160L, 0x42aa1ab62b77b7a9L, + 0x38eec0cd285df2bfL, 0xd35947f5f3a8f7f0L, 0x97c8dc0efc1cb5b5L, + 0xfeb8cca0c45845cfL, 0x16e8d989249e26f2L, 0x7c264e6d483ed89aL, + 0x13a3f14551d91073L, 0x8501562e305e99f0L, 0xaaf98d746908d563L, + 0x0a99e653d723d236L }, + { 0x23536f46abbc0559L, 0xc163067b9aa1a160L, 0x229fd2290c1681b5L, + 0x61254be11378e907L, 0xc60ff57aab793a2dL, 0xa6f2df8b466552dbL, + 0x9ad318938c170a36L, 0xc5cd9abe29b74d9aL, 0xcf747273f7848523L, + 0xc126a93a0d0e3063L, 0xfe2021e34248e3d8L, 0xd97343ee8323ddfaL, + 0x9f768775332639e7L, 0x9650fc3175325548L, 0xb595dbd13eebf7eaL, + 0x3a95cb45010fcbc0L }, + { 0x954e68cb39d7ff2eL, 0x8dd1cb4bc1d5c48fL, 0x02a92c777169438aL, + 0x7965c0b091cad8ceL, 0x0c5798ab32cd08d2L, 0x1a5bc3c3a6902bdaL, + 0x545d09255186d218L, 0xf0077cdbd27e64dbL, 0x0157caa48cd092daL, + 0x2a2fa3a024532ab3L, 0xa5fb639b41ccaba3L, 0x01702dc14744aee6L, + 0x485bb436cdba93daL, 0x93597f66329784f1L, 0x5d713c1ddad672c3L, + 0x366d222e030b7245L }, + { 0xd50b4875573ea5b2L, 0x0fce401ba90da44dL, 0x7b53fa657a1a0310L, + 0x722a80a5cf114460L, 0x0b8ebf05a538bf49L, 0xae141147d32acd21L, + 0x6692712c7b5ad07dL, 0x6dc5fee73f48ca07L, 0x98ed14992b8a78d8L, + 0x4e8b3145dd2f1759L, 0x43408de15f971b8eL, 0x055ea6ddadf1b368L, + 0x4bb76e73e5932b7eL, 0x44287153d30893fdL, 0x173dccd20661bfdaL, + 0x9072ba9979defd25L }, + { 0x474de4dd9620ea39L, 0xfbf1649fc831cee8L, 0x0b0e8bb1cd3a9c43L, + 0x6a38286f3f3df1d5L, 0x4ed072b38f0ec9b3L, 0xa6e4c987729c09e3L, + 0xea3e8ac68ad12242L, 0x6ae0e22bfbdfa5baL, 0x56171ecfb0a0f592L, + 0x33b2886d6b871f8dL, 0x6b19bea935e11bdaL, 0x4d815a407f0f153fL, + 0x7e608d977d6c02eeL, 0x7e8f23d9b6a88f46L, 0x26ac9652439d1654L, + 0x8d92c6bd35546c29L }, + { 0xb3e0d7ceabeb0ff7L, 0xfbe352543e0e42f8L, 0x57d1b226de808499L, + 0x9ece2e1f1cd44bc3L, 0x1245adbc435cfee1L, 0x874ee840f93f581cL, + 0x916a779cbda0b947L, 0xabcc815afa57ae0aL, 0x97adec2df0a621b0L, + 0xbe6a502b81f90bdcL, 0x54bf9de153bde63dL, 0xa88fdabf78884c25L, + 0x30aa52b1cbbb5470L, 0xf805396c29053ef5L, 0x8d43d8988dd827eaL, + 0x4e4bec175c1ae5c0L }, + { 0xbf8483a2fcc09676L, 0x457c4a3f19ea9a94L, 0xa6852ef3d702a5ddL, + 0xe7915fd2843fe7d8L, 0x644bba9816e35158L, 0x8d1b95d09ed746f0L, + 0x47704581b90af0b5L, 0x0bd4bc6bd4fd135eL, 0xa6dce067b4e833a5L, + 0x2c0e8f30ff56a9a1L, 0xa9c80800ec2c63feL, 0x449c20a598f508a8L, + 0x02b94cb33292813aL, 0x647e3d28ec7e81a2L, 0x72e67d1ab4877677L, + 0x7a4aa3f56f9ded24L }, + { 0x559ef1bae27a0045L, 0xdc812d4fb242cb50L, 0x23a478e439cf8d24L, + 0x97544fc59b3f9c54L, 0x5ac68132affa1fcfL, 0x74f8fee034a2c83bL, + 0x96cc640fcd3f4bb7L, 0x775dce9db0512ea6L, 0x67dca19dcdce381eL, + 0xc1eeb3f3a9d3fe55L, 0x38e0bf421a19274fL, 0x15992fb428d69b12L, + 0x48fcebde9fd09df8L, 0xdc9dfa4fb41ab5dfL, 0x0cbd7dc8c0a269c5L, + 0x60282a7bf7f0ade1L }, + { 0x7c07e538dceea2e7L, 0x38a322c83c42061dL, 0x676828f94f1f6516L, + 0xf21b69fbc7776a10L, 0xc63a3417b5e6b405L, 0x4c99f25891a7b642L, + 0x38692ca82cad1440L, 0xf1e82ffe00869bcdL, 0xc30b714e16fe466aL, + 0x5fb742f919019138L, 0xe90166d00fa516aeL, 0x5550f7acd8c73a43L, + 0x2d6a407dfbc5c372L, 0xe47a753968cc39edL, 0x3fd286d94a5fbe70L, + 0x5f4ae9c723c6b942L }, + { 0xd96a2dda53f4d561L, 0x286d45d016da1992L, 0x449a01fbfdd4b051L, + 0x25488a0d9f2195eaL, 0xc4151b0aa37661b3L, 0xb98c471ef9e5ee02L, + 0xa4bca86ea8658817L, 0xbbcadb877a68fc0aL, 0x88b346496b7366a9L, + 0x32ee98d415661c2dL, 0xf5b3b4c6c901420cL, 0xa23527352f2752afL, + 0x2f64ce73510e4d9cL, 0x939a7f26aca4aa80L, 0x9cd3e291401aa503L, + 0x92a01423dc46afd2L }, + { 0xe9f24be11c2f7dbdL, 0xda8c900fb7d527faL, 0x963e25bb8648f128L, + 0x9ab713e248141941L, 0xe87f7d017a6756fbL, 0x274dd85e058d90bdL, + 0x823fee7a82566abdL, 0x9f6230d774240195L, 0x04579f2cacb5e46eL, + 0x2a22626316a4c87eL, 0x9ca19a43d99b0857L, 0x86dc2ba3e488789eL, + 0xf960b5b99406c3bdL, 0x6f2c428b8960957eL, 0x90748706161c515bL, + 0x0fc8fe1eaa88cb9bL }, + { 0x68ae1bedfeb90f2dL, 0xf393bb3ca48b1559L, 0x2be62f9cf64e9635L, + 0x354c2410f8be75c2L, 0xbd7ea7035e6f7529L, 0xc264868e162cab31L, + 0xb1391e70c860f3ffL, 0xdf367c751d89837eL, 0xe150b6b42bf32941L, + 0x95e8f46e78c1318fL, 0x2b3f1daba2c4b160L, 0xc6ccf5ce701afbf3L, + 0x3ad275305e8874c5L, 0x39285e515dc6dcbeL, 0x3c954d86d99892ddL, + 0x2d0ba862dfd3789fL }, + { 0xeacd8ee8b472e1afL, 0xeb354eaeb76abbccL, 0x9b520bf8d0d93fbdL, + 0xfccd60d7fe6fc706L, 0xa9353ddea4ee2f39L, 0x5eb0925e9a81e51eL, + 0xee334da1d1366777L, 0xc1d28c9fd5354d69L, 0xb977175592a5ed54L, + 0x5d3e367fb7f70d81L, 0x7be7eecaa933ae7aL, 0x264cf1f9e23cfbb7L, + 0x0d129f4a89497681L, 0x705375a409b6235bL, 0xccf64c7548a376daL, + 0x963c87124d41dbfcL }, + { 0xbae290cbde36a814L, 0x9bdb0195733b12b5L, 0x0ebad867f77fe0e1L, + 0x0a7d19fd29720ceaL, 0x434d76519029ec72L, 0x856aff17bb51911eL, + 0xd0a25d9ad80a7f60L, 0xffca86aff848c106L, 0x53e8bdf943ad749cL, + 0xfb9e0284e3e696bbL, 0x3eb6630aeeee4215L, 0x9d8fbb9e2ecf3c63L, + 0x71da4ffa4e00c0c0L, 0xb296be595d57beacL, 0x1751fbada8cec7efL, + 0x2d03eb3cff55d7bdL }, + { 0xeb16925f04f2ec1dL, 0xa878f2760d147ee2L, 0x442df604aad9d9e0L, + 0x891df44b3f71035bL, 0xc28272b38cb95d5bL, 0x6f14efb55ee8ed23L, + 0xf3c4460f13b0f3e3L, 0x889f9bd76bd7335eL, 0x889ee771f755ba6eL, + 0x626984feed219b6cL, 0x2d44c737ec2ee411L, 0xb94385a263efcd37L, + 0xd909321b6637826bL, 0xc24f8a793ee6b7a7L, 0xa3ca8d24a7cf61b7L, + 0x842e40c1c54bacd9L }, + { 0x5a268ed6a661d843L, 0x02328cca4f5b30cdL, 0x16e6fed11311e177L, + 0x690decb4c6695967L, 0xbdac5bf657b2e280L, 0x827f82ca1efe42d0L, + 0xc554ec0aca5fca2fL, 0xac5276c1dde45506L, 0xb7f4cb08e3077513L, + 0x8caf6d9acc8797ccL, 0xd59648140d9332d2L, 0xcc6ae297285a409fL, + 0x7773c2a56223d093L, 0x2d5266ac5128fc09L, 0xa596b7cbbc31fe6cL, + 0x0e63319acac91328L }, + { 0xb5cd2fadf0360ac2L, 0x86b660de285e605aL, 0x82c6cf10e25b9b14L, + 0x9d5fa38daa9ac554L, 0x3dfcf1b8526c070eL, 0x0379a96b3fccc52dL, + 0xe3659c290bfcc7f5L, 0x5b1a3db569d3e6a1L, 0xb41528b59b7b42d5L, + 0x934defa49c22a006L, 0x90f380189b4ce3b6L, 0xb073bc04b3abaf32L, + 0x27a5a222ff8389e2L, 0x0b7a9d51ffa5a35bL, 0x4939ecef28e1a7c2L, + 0x88839da21872705aL }, + { 0x56b66c30701ce29aL, 0x3acaf12658981d50L, 0xd4dafc0c105f9f21L, + 0xfee571e6373e3d13L, 0xe7269c86fa2ee3caL, 0xf5cca64add20385aL, + 0x217f27573000e9acL, 0xc934db470e7273efL, 0x4294f4f7355b6776L, + 0x1faa36b96fc05180L, 0x8f88b1dbb052190bL, 0x35791b90e9eaef52L, + 0xf37fb2ebdb681b90L, 0x39d0a51d4415c369L, 0xfc59cca71d2e21c9L, + 0x64128cfea1f50c26L }, + { 0xf03678a2e8f5b0b5L, 0x5c7e249cd340f059L, 0x4144044193ca7cecL, + 0x075ca346bc83af98L, 0xf39f0033faa8bbb0L, 0x3d18f0edf38230f7L, + 0x78dff00cd448f345L, 0x849228c0d51aa475L, 0xdd4e270830c928d1L, + 0xc66ba6868f12cfd3L, 0x091049db88b3a206L, 0xd865d059016dae01L, + 0x4599e905e253e37dL, 0x322cf0c27ce9871bL, 0x014f54da174a132eL, + 0x93634a09bdabcbdaL }, + { 0x62826b27a9a2e304L, 0xc57e1866c1a4c124L, 0x913ab83222381710L, + 0x7e9b6b85a9847cfeL, 0x29655cf12b5f46fdL, 0x7295572b8038e66dL, + 0xe4cba6016fa95eabL, 0xbbc11071b9deda81L, 0x97f0009a3f1cf61eL, + 0x5372777b373e0cfbL, 0x302f909cd139d63bL, 0x1ed672da4f87d78eL, + 0x362077a3b4048763L, 0xc408c32d9dcc22b2L, 0x4b4c5bf226deeee7L, + 0x266cb467bc06357eL }, + { 0x6faa4154b56363e8L, 0x4b4fd0783c1aa4dbL, 0x14358dde2b9e6597L, + 0x5b34ae3efa004b84L, 0xcf44b2ecf19911a6L, 0x55caa833a536bf78L, + 0x606e1eb98870dc95L, 0xe3c3287d09f3511dL, 0x68b2f4eb9d5cf364L, + 0xc154e89263ab8c9eL, 0x1548828ec36ab611L, 0x0932bfcba1b7d120L, + 0x7ee7b5bc5315b8d7L, 0x782fd0d1f7473ac1L, 0xbcb029a83c8f2af3L, + 0x4b1d5a1b52454ee1L }, + { 0x12fe517463d52c0cL, 0x3735525e188c099dL, 0x5c621563360e3956L, + 0x88b3f1caacfa5a43L, 0x90123a0a797e8107L, 0xba31f6b5b15e080aL, + 0xd7de5e12fca3dadaL, 0x3287361b0df511c8L, 0x7cc800d465757d4eL, + 0x10810f3d5207ec91L, 0x0d4e56f130eea0e3L, 0xbbf7ee133ea5a2ecL, + 0x6fc07762be6abbd0L, 0xc831fdce120bf619L, 0xe07439fab622d42aL, + 0x8186b93f508e4b27L }, + { 0xc619d15409312867L, 0x7e042c05bfaf7db4L, 0xc1cf16681f5f5ddaL, + 0x50aa5057a4fc3d82L, 0xed30ed65ce68b8feL, 0xecb01c0bbeb4d644L, + 0x7b5dc444831c0497L, 0x351e6a009b7d9b1cL, 0x4bb863b9d9477c91L, + 0xaba6589105d4110aL, 0x30086cf443580b7aL, 0xb139c07690be357eL, + 0x12bfff1a27b5214eL, 0x79cfc6d722c3ab57L, 0x4743de57f34a9bfaL, + 0x0bf97e97c9ee2b2aL }, + { 0x96ec4ec8dda19e96L, 0x54ce18ea6c306e8bL, 0x7e83612b65f6918aL, + 0x1ac6f68b0d9a0d99L, 0x98a697a462fdcc09L, 0x65ce25f195bc3e13L, + 0x1896ecdab3939730L, 0x9eb81a0f32f12806L, 0xd3d7416e1d2dc7dfL, + 0xe22c7976ad473599L, 0x3de37a9a9f5ef439L, 0x6b7ac0ab9e69d94eL, + 0xe6bfa9e00a9d0bc8L, 0x576a870d5676f120L, 0x3bd91bb4feaac23fL, + 0x8fe5482c3e40aabbL }, + { 0x85ae67c2ce9a4d1eL, 0x4c3eb8034f1d2038L, 0x5c6c8f3a25d06192L, + 0x803de0ad308fb41cL, 0x9961f5bce71c294eL, 0xdc62078df02eb0daL, + 0xc87ef515b64ae8b6L, 0x69679f1e50b4d18fL, 0xc5c009a152199f43L, + 0xa7d484be0f640a5fL, 0x4c918bb123dab566L, 0xa67c114c64275d2cL, + 0x95a913b9cad2ded6L, 0x189ed18b6b4b5c8dL, 0x4aeb6206b42d3bf6L, + 0x3928c669bbc8bc3fL }, + { 0xde4bea4adacb4b64L, 0x03f62a44f26179a1L, 0xf3aac94e7a9112a4L, + 0x90448fbdd36f331eL, 0x426042bc407b85c4L, 0x5ad8a5962121b77bL, + 0x31674a4f67cee984L, 0x7fae8bbe4e3b2f0dL, 0x681df6dda7c930ebL, + 0xadeefa98c259d0d4L, 0x1b14d9e6bea1c1fdL, 0x3baadc8b21d405d1L, + 0xf01dff9373892754L, 0x81c35b3ef071cde4L, 0x1704d2e19150d0d9L, + 0x6ccc888f355134f6L }, + { 0xf8d36f0e7ad7504cL, 0xbca3265ff7959dddL, 0x0dcd1edefede67aaL, + 0x1276f4cebaebf32fL, 0x6825a6e6014edcfcL, 0x0b8c1a8299ad8eb7L, + 0x312024a909b8ce1eL, 0xcb8fd98b9cbd351aL, 0xa4841378fab1e8beL, + 0x17ed0f5d3973cacfL, 0xa17e1484259d5254L, 0x53d5b84374b91393L, + 0x8f792b211aca3ce9L, 0x035ff110c8c0f815L, 0x6afa6357ad4ed7bdL, + 0x2f151980b26faef9L }, + { 0x0c8631da29d2d439L, 0x121fbbc2bc039955L, 0x3e5a97926c05b75bL, + 0x6d6cf4c0b6ce47ecL, 0xbaaa17679d88c658L, 0x031db9e7f3355a17L, + 0x8381e3d80aef5a85L, 0xc71db29015a31bdfL, 0x638f6b749498fd7dL, + 0x44edf3f913beeef6L, 0xe6173271f4ab67b3L, 0x3a202c70fd22df11L, + 0xf7be0389205c4e92L, 0x1c219085a8eb9920L, 0x6c805ce8beb54aaaL, + 0x354b05b70ac58d65L }, + { 0x7171e2367a9170e9L, 0x01eec42d4cad50cdL, 0xffbe824f3cddccfbL, + 0xa73e8ce3a66cae1aL, 0xb7138a7f965c7d01L, 0x00058e3f5c3d971eL, + 0x52591ac32ff0a72bL, 0xa32fb5bcbbbce76fL, 0xf3241ab8a9f81a18L, + 0xf31d3332eca68630L, 0x847af9fc4482f13bL, 0x6196e217a4681be2L, + 0x9938f932e55efcf9L, 0x3e7dacb870acc705L, 0xd41be893cf09fac2L, + 0x48dc55c4ae3523a1L }, + { 0x8e623826a5092193L, 0xe46ec3626898970cL, 0x2f1356af25c9eb41L, + 0x4178064083c7d245L, 0x982def6797d00e38L, 0x382eb6e7a512151cL, + 0x154e10778af58869L, 0x187070758a51cf02L, 0xcdeba9f771313c58L, + 0x5d67b973ba155904L, 0x851c9f4b1d0d7b3aL, 0x19f29d718b8af2cdL, + 0xcb94ccff986b8d62L, 0x8725e24bb93b9c33L, 0x405ce4c566e38c68L, + 0x5f6a8edd0b6dc021L }, + { 0x83704ca58f9a8690L, 0x3f3697662f76a407L, 0xfbc12d8c69201028L, + 0x4cd58f16bce3a4cfL, 0x7804664a04aab26dL, 0x005cfbba4ea457a8L, + 0x537951b3b8a59794L, 0x4ca2b9e44fe1f739L, 0xe4428acddf325797L, + 0x648da3420ea243dbL, 0xcce6562bf43ce01eL, 0x840f0421f27db490L, + 0x156ccb708bfb7cf0L, 0x9b33480d5a8797d3L, 0x2e12e07a9eb814bbL, + 0x1ca65072ca7f87acL }, + { 0xfbb321cf2b9d25a0L, 0x66affdca40a746dbL, 0xc1c1530e59e368b5L, + 0x56ed1ea47d80068fL, 0x9b74d8fe5647dd68L, 0x1d96b50789b78da8L, + 0x39b752438bbe3391L, 0xef8d443e0d858c5fL, 0x4dd2db499646aa34L, + 0x7fad3bd1e667543cL, 0xd0d710c068980985L, 0x9f7aff3249facabaL, + 0x055dec1c14f9a192L, 0xaca663991fb307a1L, 0xac44fd9135ffff64L, + 0x462cafb6cbad3ceeL }, + { 0x1660a647de3237ddL, 0x95f735cc82b87404L, 0xf7879f59ddfa55f8L, + 0x15ef043e726b914aL, 0x1875393d1c93e298L, 0xa1a2be746ef18331L, + 0x4e7e8dfc25a9a12bL, 0xdfefc97da9c3917fL, 0xbc875d030a2ebe41L, + 0x0f75d235a732d1ccL, 0x06fee7fed9baa6d3L, 0xaa784fab65f48576L, + 0x23155e22513f83c0L, 0xd2fb77183e8f9d13L, 0x2a291503b546eafdL, + 0x1293c98c6cd93608L }, + { 0x7278125149d53b77L, 0xa6ab403d96eafac7L, 0xb7d7c7db4a36b711L, + 0x8238c70887e771c1L, 0x495f6abf33b37522L, 0xb0b0289c8c87530dL, + 0xca83cb86e77b111aL, 0xbe1c0fb8a1bd189eL, 0x58cfb2fb1ae9d7c7L, + 0xd05c23c54940c3e8L, 0x16e79e4174ad9107L, 0xa0a47f05064e7142L, + 0xc6929cd4fdfd614fL, 0xedb2584c3946988bL, 0x73e4b5f3e46f8fb1L, + 0x53b79aa168ea94baL }, + { 0x216fafce44bbb6a1L, 0xd3a5bba067821728L, 0xef1e4b30a9dd939aL, + 0x022eaf3df19efafeL, 0xfed5abce7b4ec014L, 0x64968ee6512c6738L, + 0x2311986929fe89a2L, 0x0d539d8d47397c05L, 0x6400bc54234596c4L, + 0xb9287f585346611dL, 0x04099903c9d5da0fL, 0xe5ef4997c83af2a8L, + 0xc89dc01b328151e1L, 0x150fb4a958401104L, 0x40a6f7d5f3872c9dL, + 0x8290d6d156c2e833L }, + { 0xf84637c6d8546946L, 0xda134a3969ec57faL, 0xd42359a4d789007eL, + 0xb42557fe0dc7b809L, 0xe62ae52d2d6784a9L, 0xa2714ca60bcadb5fL, + 0xcc208de633aafca5L, 0x2380ed5ced967811L, 0x6e6b55e9db321660L, + 0x1bead02ca675235aL, 0x51cc6ef9b33fa0e1L, 0xfd223e26f06a2a08L, + 0x00f332e1ec47b3cfL, 0x459f297ba0aa984eL, 0x6fa1d969ee952e14L, + 0x506ef1ab304fabb0L }, + { 0x11b4eb2735bff163L, 0x7130b96fea9fa984L, 0x66aceb3f9deb27ceL, + 0xa2daf1a59dd1c3d5L, 0xf5090a7ea73075aaL, 0x36a6af39e3071b58L, + 0xa28d633ddf73ad9cL, 0xdd354cacbdc89a16L, 0xdfea3423d4dcbc3cL, + 0x6eec74d2379d92d1L, 0xe14a456f8eed6765L, 0xfabe7743fa8feb1fL, + 0x1404ccf8b98fcbc7L, 0x6ccd2fbff71a706eL, 0xdaaf3fdb4d85c678L, + 0x415b7dbf15200344L }, + { 0x970105867d8377a7L, 0x068a3d68cb803272L, 0xfd67d289f03a4c32L, + 0x4bc7095d93c8f290L, 0x712fa13ce9e5a2b8L, 0xfc6ac6c60feb9f3bL, + 0x0cda36d96e0e54c2L, 0x4549975186320a01L, 0xf9318c9197f00f11L, + 0x01dc4c3fe6936508L, 0x769a2ef985f068aaL, 0x3522cef0a2b5511cL, + 0x006965edb4122e05L, 0xfce0fafcc175d43fL, 0x525dc9bdec831d59L, + 0x1ec314f1af58879dL }, + { 0x0663feef2c8310c2L, 0xaa7e14da457e3f74L, 0x392b10fce5346887L, + 0xcde4a38f637ec2c5L, 0x50773320b542f8dfL, 0x341302f9f7de1711L, + 0x018b1c63ae4b9bc6L, 0xf001c46edd2f9e6fL, 0xd3bb0a9726eccfa0L, + 0xa931b99d7746e0c7L, 0xe0c8b6f7f5875aecL, 0xbb32f17c96939c82L, + 0x765135d23de5a664L, 0x71936cb452abfa6bL, 0xad5cc08f2dc105deL, + 0x17e91d127fff5788L }, + { 0xbe92ced3b7e051caL, 0xc644d4fd19c776d4L, 0xc8ab4b520086784bL, + 0x3ea66227ce9d6b31L, 0x395249a3d289e9c7L, 0x54509e65d12a19eeL, + 0xa7bd46928c365aecL, 0x354997e477963e0eL, 0x0d765957b599732dL, + 0x99584aeb91d4a3b6L, 0x6e653ea41deb3e28L, 0xca7c98ed572571dfL, + 0xf301a38fb18ae1f9L, 0x1629f7c263f7b97eL, 0xdf242282afc4a0d5L, + 0x118f3b4b3ddd0c01L }, + { 0x74a0a0a87ad4762bL, 0x1aef84da8c58d175L, 0x16ff49604cf76d86L, + 0xc0be87867e60d98bL, 0x83637ffb3ecc1dbaL, 0xc244a6095dd6147aL, + 0xa3e178345b0846e5L, 0x735eb686e77a4c05L, 0x5bc18b4fdf758695L, + 0x15618d0b1bdfe52fL, 0x878ecc0d00715ba1L, 0x1dbdbd1ac2dd617fL, + 0x21d2b63121b61710L, 0x22ce8a7944f593c2L, 0x3b9b536a44f17024L, + 0x01d0a67c8d03e727L }, + { 0x7b9642361e46533cL, 0xe9477990fb88c2aeL, 0x019b5d16a42c4a18L, + 0x7135e81dd83c7a45L, 0x74a69bdd4cb663e3L, 0x7b67ecdbe76c0d63L, + 0x03d5452111e68da6L, 0x596cceb5d2e8650aL, 0xcd572dfd2af03b37L, + 0x52364ba1fabd5952L, 0x7f47d456b4ed8569L, 0x5ad8b572c950d5d4L, + 0xcadd2dfa486e2f84L, 0xdd527b43c56bb044L, 0xc9adba24997c08e6L, + 0x1b625b067da6320fL }, + { 0x44dfaa7b4fd8446dL, 0xc01b2f01af6febebL, 0xbf444388fe8838b5L, + 0xf33c434fbba9758bL, 0x2b971cba87156bc9L, 0x6b245e5c1f49098bL, + 0x87dcb5342b41c5ddL, 0xdb1f80c634d852d7L, 0x6d6e32582433da34L, + 0xf66820653f7df0c2L, 0xc4ca567c360cb365L, 0x321faac29826656aL, + 0x13f5ca6fbf069768L, 0x15397921a7076639L, 0xbdf143288400736eL, + 0x333eca9619fc948dL }, + { 0x23337948ac775d81L, 0x38c2518fd41dbbcaL, 0x623c7a4fbcfce948L, + 0xaad3623654703fe7L, 0x2b3a13a413fb3b5bL, 0x5db3565a7f5c01f0L, + 0xd72408dc52359661L, 0x5a17f8e51d616e91L, 0x90c16eebcb25b999L, + 0xf35e8cf13393743eL, 0x987da74ae54b64a7L, 0x557b322a65cd449dL, + 0x765082a537e7b15dL, 0x4d25c742f2cd134fL, 0xae9d9c074ccf0746L, + 0x72fc21108728d135L }, + { 0xa906b203f96004c8L, 0xd83f95cf458055ffL, 0xd77d586755f35909L, + 0x4a9ea6fbe550c8eeL, 0x91c8cca955a06081L, 0x4a1fee78bce82062L, + 0xeb9ade069a3df85eL, 0xfbbdcf0c7d3de666L, 0x228a391b5d336d51L, + 0x760f8d285c2ffc3cL, 0x1ee48de32f7b165bL, 0x03803d8456177040L, + 0xe573f6489deff9a0L, 0xe1a2738ea17e35a4L, 0x238ef17c8840a6c6L, + 0x480946f8b11ed92dL }, + { 0x84c747a8fd71f119L, 0x19e65c5e53eb3695L, 0x0e2f67866298587aL, + 0x48a48899ab18d6f4L, 0xa1a99024c630b8c0L, 0x849750962caaf892L, + 0xc8869abae20fd624L, 0x3b72b04d6c2b7dd4L, 0xe2775eb60992f7d0L, + 0x0089c06e7d06e684L, 0xcb3b4361e4bbd007L, 0xa1ae666b4ba846e4L, + 0xc01c2eb246464d9eL, 0xf86f2be6c1f8539fL, 0x16e8e8aecf68afc7L, + 0x8dab61fdc7386902L }, + { 0x42a5c903d54d1d45L, 0xacd4297eff4f9ba2L, 0x2d88b52034d478b4L, + 0x35b2ba2b08c4621aL, 0xd3d239bb34865402L, 0x1de76aed911f32e6L, + 0x877f8bcf3f06fdc2L, 0x802714c19ec51502L, 0xa10444eba590700dL, + 0x8694229f31dcc957L, 0x5ece77abb8169fedL, 0x55be8a152caf080eL, + 0x3eb21b14cbd7cef1L, 0x9def7ad167b97ee1L, 0xe03ca879118f690cL, + 0x6f77e62df99b29e7L }, + { 0xa271bdede40bbf59L, 0x177ba4536401aad6L, 0x1755e03573541cd1L, + 0x3465b4664b71b02fL, 0x22eb7113a813359fL, 0x9792a8fd6f38eac7L, + 0x11aa012fff3bf3b5L, 0x99aafabff85c3fbfL, 0x91e0a2ef06c0cc42L, + 0x314d5d57773b7b3aL, 0xae5e2e76d669840aL, 0x861360732e5a8be6L, + 0xee6d7578c1cf5580L, 0x2344e00f68bed102L, 0x799d78868184f0ebL, + 0x63819c91c3d2cf80L }, + { 0xca5392e17884b073L, 0x9ec3a1fceb1267eaL, 0x3d07f5f0907038a7L, + 0xcb2ac07ce4c47b70L, 0xf96664ee1bf96b91L, 0xebf575892aea4fbfL, + 0x5aabf391fade6500L, 0xc5b3376f171d1204L, 0x1ff60c51a0d3d81aL, + 0x10b2cfe7976a844bL, 0xe131cc9abda6125aL, 0xe0fc16d34ebd453eL, + 0xc0d0319a504b6bc1L, 0xe43a0be70a2f8cabL, 0xc80afeec55e49b47L, + 0x67d48d128265d7eeL }, + { 0x068d59a7ea2d56d6L, 0xd71abd0e27480a63L, 0x6bd11db0ae7366cdL, + 0xfbb639ca07204ebcL, 0x89a242e7f77e6293L, 0xdee7ca2b75ba8c3dL, + 0x472ddc3d64a2f9a8L, 0x84229df47561a010L, 0x95f62c85c5b649d4L, + 0xfdd56b1b4dc927cdL, 0xfe8bb1205ee60596L, 0x3efcaa50abf29401L, + 0xd4900d0f10d1c184L, 0x2cf113a928b01df5L, 0xa3d7ebc31f0e43f5L, + 0x27950e38e8384dc7L }, + { 0xeab21ff0e1d0fa79L, 0x4b9fd033048b5de9L, 0x4c9346892fe374cbL, + 0xbb4827fa4eb21f6bL, 0x46716f79a925e7e7L, 0x1442bf367dd4c531L, + 0x2073954cd2e96ddfL, 0x4e0141ae8502aa89L, 0x8ee00e1a8eef6cc9L, + 0x55ce84915880cdafL, 0xff3aba5c69628046L, 0x335cc4f85d15dfbfL, + 0xa7f0440c9f684f25L, 0xae80453fbb1e5bd8L, 0xa1c99813ff2225abL, + 0x54ff788479b25d71L }, + { 0x27c6ee30de40b068L, 0x9226465be6f3a51eL, 0xe24a4604fa3b21f6L, + 0x50a5a5adc0418115L, 0xe32854418df90d2bL, 0xbb74e58fdcb0c00fL, + 0xc68f1b3b4a2c08e3L, 0x339df0810ccd9ec9L, 0x915362dcb786ea9fL, + 0x28945e31c955aeadL, 0xd6a2c01d8b6a6c6bL, 0x069e82dc3678a427L, + 0x1787550028c9302cL, 0x8acda9659fa101e6L, 0x4e4e4573ee30b286L, + 0x8adbad853f1830feL }, + { 0x060ae11f0969d524L, 0xf42fdaf7f39bcc79L, 0x3cec67667cc1fcc2L, + 0x456b9cf2e2336d4fL, 0x6aa1f5de8e1c0f7fL, 0xcdbc2ad20984fb0eL, + 0x4090cfa61b464b28L, 0x40d86f301243f3efL, 0x95b16ccccd5e87e7L, + 0x403f168c3026cd41L, 0xdbe386cb816c0730L, 0x14eb86f358407a1dL, + 0xf588b4f81717e1afL, 0xb75c41a666cbc96cL, 0xf342c1aa027e71c1L, + 0x73930036c0945e5fL }, + { 0x954f757d22cdaf42L, 0x788b591df4181aabL, 0x8b986819f5514f25L, + 0x69642e08f18fd5bcL, 0x92b305d1022ceb91L, 0x1715903e6a4f6985L, + 0x4bd7d69d61179caeL, 0xdacdfd5dd29c01aaL, 0x705ddd5ad91108ccL, + 0x434ac7b164ac8f15L, 0x61a514e1b524632fL, 0x45b9e61b731fc447L, + 0xcf561348e0961b31L, 0x9c28a96773eaf223L, 0x5bd10182aa7c99d3L, + 0x8bc6ec4ae42965e2L }, + { 0xd096e5c0e7f2a32bL, 0xff54800c09388a30L, 0x06fe437c401e360cL, + 0x6655fc9cbb6054a6L, 0x510e18608457aa6eL, 0xa0acfca22b29b2b7L, + 0x732483e351b7da61L, 0xe31471ee6be6c8caL, 0xe565431c8b65c9a1L, + 0xfc9ac3b948d65cbbL, 0xd308fc21ae9b2aa8L, 0xd6a7df0daa60aa6aL, + 0x2844d96a982fc0d4L, 0xab012c2c5847a4d7L, 0x2b3c8f71dceb8955L, + 0x8e85437dbe9c7e15L }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 16]; + sp_digit tx[2 * 16]; + sp_digit ty[2 * 16]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 16 * 2; + ty = td + 5 * 16 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 16); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 16); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_16(tx, ty, t); + sp_1024_proj_mul_qx1_16(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_16(tx, tx, t); + sp_1024_mont_mul_16(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_16(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = px + py */ + sp_1024_mont_add_16(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_16(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_16(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_16(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_16(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_16(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_16(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_16(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_16(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + sp_1024_mont_inv_16(t1, p->z, t2); + sp_1024_mont_sqr_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 16); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 16; + sp_digit* pz2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* l = t + 8 * 16; + sp_digit* ty = t + 10 * 16; + + /* v = v^2 */ + sp_1024_proj_sqr_16(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_16(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_16(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_16(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_16(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_16(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_16(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_16(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_16(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_16(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_16(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_16(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_16(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_16(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_16(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_16(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_16(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_16(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_16(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_16(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* h = t + 8 * 16; + sp_digit* r = t + 10 * 16; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_16(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_16(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_16(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_16(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_16(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_16(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_16(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_16(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_16(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_16(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_16(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_16(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_16(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_16(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_16(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_16(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_16(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_16(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_16(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_16(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_16(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_16(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit qx_px[2 * 16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_16(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + qx_px = td + 8 * 16 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + + sp_1024_mont_add_16(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 64] >> (i % 64)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_16(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_16(vx, vy, t); + sp_1024_proj_sqr_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_16(vx, vx, t); + sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_16(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* h = t + 8 * 16; + sp_digit* r = t + 10 * 16; + + /* h = p.z^2 */ + sp_1024_mont_sqr_16(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_16(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_16(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_16(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_16(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_16(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_16(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_16(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_16(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_16(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_16(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_16(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_16(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_16(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_16(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_16(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_16(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_16(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_16(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_16(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_16(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_16(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_16(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_16(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_16(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_16(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_16(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_16(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_16(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 16; + sp_digit* pz2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* l = t + 8 * 16; + sp_digit* ty = t + 10 * 16; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_16(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_16(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_16(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_16(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_16(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_16(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_16(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_16(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_16(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_16(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_16(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_16(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_16(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_16(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_16(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_16(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_16(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_16(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_16(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_16(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_16(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[32]; + sp_digit (*pre_vy)[32]; + sp_digit (*pre_nvy)[32]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit pre_vx[16][32]; + sp_digit pre_vy[16][32]; + sp_digit pre_nvy[16][32]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_16(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2); + pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2); + pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2); + pre_p = (sp_point_1024*)(td + 56 * 16 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16); + sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16); + sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_16(vx, vy, t); + sp_1024_proj_sqr_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_16(vx, vx, t); + sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_16(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 16; + sp_digit* t2 = t + 2 * 2 * 16; + sp_digit* l = t + 4 * 2 * 16; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_16(l, py, p1024_mod); + sp_1024_mont_inv_16(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_16(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_16(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_16(t2, t1, p1024_mod); + sp_1024_mont_add_16(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_16(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_16(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_16(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 16); + XMEMCPY(cr, t2, sizeof(sp_digit) * 16); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_16(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 16; + sp_digit* c = t + 2 * 2 * 16; + sp_digit* l = t + 4 * 2 * 16; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_16(l, cx, px, p1024_mod); + sp_1024_mont_inv_16(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_16(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_16(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_16(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_16(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_16(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_16(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 16); + XMEMCPY(cr, c, sizeof(sp_digit) * 16); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_16(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 16; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_16(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_16(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_16(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_16(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 16]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 16 * 2); +#endif + + sp_1024_point_from_ecc_point_16(p, pm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_16(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_16(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_16(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_16(c, c, t); + sp_1024_mont_map_16(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_16(c, c, &pre_p[j/2], t); + sp_1024_mont_map_16(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_16(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_16(c, c, neg, t); + sp_1024_mont_map_16(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_16(c, c, t); + sp_1024_mont_map_16(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(neg, 1, NULL); + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[32]; + sp_digit (*pre_vy)[32]; + sp_digit (*pre_nvy)[32]; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit pre_vx[16][32]; + sp_digit pre_vy[16][32]; + sp_digit pre_nvy[16][32]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2); + pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2); + pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16); + sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16); + sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 16); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_16(vx, vy, t); + sp_1024_proj_sqr_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_16(vx, vx, t); + sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_16(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i; + int j; + byte* d; + + for (i = n - 1,j = 0; i >= 7; i -= 8) { + r[j] = ((sp_digit)a[i - 0] << 0) | + ((sp_digit)a[i - 1] << 8) | + ((sp_digit)a[i - 2] << 16) | + ((sp_digit)a[i - 3] << 24) | + ((sp_digit)a[i - 4] << 32) | + ((sp_digit)a[i - 5] << 40) | + ((sp_digit)a[i - 6] << 48) | + ((sp_digit)a[i - 7] << 56); + j++; + } + + if (i >= 0) { + r[j] = 0; + + d = (byte*)r; + switch (i) { + case 6: d[n - 1 - 6] = a[6]; //fallthrough + case 5: d[n - 1 - 5] = a[5]; //fallthrough + case 4: d[n - 1 - 4] = a[4]; //fallthrough + case 3: d[n - 1 - 3] = a[3]; //fallthrough + case 2: d[n - 1 - 2] = a[2]; //fallthrough + case 1: d[n - 1 - 1] = a[1]; //fallthrough + case 0: d[n - 1 - 0] = a[0]; //fallthrough + } + j++; + } + + for (; j < size; j++) { + r[j] = 0; + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_16(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[16 * 4]; +#endif + sp_digit* t2 = NULL; + int64_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 16; + + sp_1024_sqr_16(t1, point->y); + (void)sp_1024_mod_16(t1, t1, p1024_mod); + sp_1024_sqr_16(t2, point->x); + (void)sp_1024_mod_16(t2, t2, p1024_mod); + sp_1024_mul_16(t2, t2, point->x); + (void)sp_1024_mod_16(t2, t2, p1024_mod); + (void)sp_1024_sub_16(t2, p1024_mod, t2); + sp_1024_mont_add_16(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_16(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_16(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_16(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_16(t1, p1024_mod); + sp_1024_cond_sub_16(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(t1); + if (!sp_1024_iszero_16(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 16, pX); + sp_1024_from_mp(pub->y, 16, pY); + sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_16(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[16]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 16, pX); + sp_1024_from_mp(pub->y, 16, pY); + sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 16, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_16(pub->x) != 0) && + (sp_1024_iszero_16(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_16(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_16(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_16(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_1024_ecc_mulmod_16(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_16(p->x) == 0) || + (sp_1024_iszero_16(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_1024_ecc_mulmod_base_16(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_16(p->x, pub->x) != 0) || + (sp_1024_cmp_16(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* WOLFSSL_SP_ARM64_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c index cddcffa2f..9f1a198c4 100644 --- a/wolfcrypt/src/sp_armthumb.c +++ b/wolfcrypt/src/sp_armthumb.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,7 +58,8 @@ */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -100,7 +101,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -134,7 +136,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -173,7 +177,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_2048_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 2048 / 8 - 1; a[j] = 0; @@ -716,7 +723,9 @@ SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, sp_digit a1[8]; sp_digit b1[8]; sp_digit z2[16]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_8(a1, a, &a[8]); cb = sp_2048_add_8(b1, b, &b[8]); @@ -1105,7 +1114,9 @@ SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, sp_digit a1[16]; sp_digit b1[16]; sp_digit z2[32]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_16(a1, a, &a[16]); cb = sp_2048_add_16(b1, b, &b[16]); @@ -1763,7 +1774,9 @@ SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, sp_digit a1[32]; sp_digit b1[32]; sp_digit z2[64]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_32(a1, a, &a[32]); cb = sp_2048_add_32(b1, b, &b[32]); @@ -2498,7 +2511,7 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -2507,7 +2520,8 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -2516,7 +2530,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -2791,8 +2805,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_32(r, a, b); sp_2048_mont_reduce_32(r, m, mp); @@ -2805,8 +2819,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_32(r, a); sp_2048_mont_reduce_32(r, m, mp); @@ -3130,35 +3144,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 64]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3206,34 +3216,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -3254,9 +3264,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -3275,35 +3284,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 64]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3367,34 +3372,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -3416,16 +3421,15 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -3442,7 +3446,7 @@ static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m) sp_2048_sub_in_place_64(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -3634,8 +3638,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_64(r, a, b); sp_2048_mont_reduce_64(r, m, mp); @@ -3648,8 +3652,8 @@ static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_64(r, a); sp_2048_mont_reduce_64(r, m, mp); @@ -3990,35 +3994,31 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 128]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_2048_mont_setup(m, &mp); @@ -4066,34 +4066,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -4114,9 +4114,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4135,35 +4134,31 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 128]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_2048_mont_setup(m, &mp); @@ -4227,34 +4222,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -4276,9 +4271,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4299,19 +4293,18 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128], m[64], r[128]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 256) { @@ -4325,22 +4318,18 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 64 * 2; - m = r + 64 * 2; - } #endif if (err == MP_OKAY) { + r = a + 64 * 2; + m = r + 64 * 2; ah = a + 64; sp_2048_from_bin(ah, 64, in, inLen); @@ -4413,10 +4402,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -4479,13 +4467,17 @@ SP_NOINLINE static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[64 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -4514,13 +4506,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 64; m = a + 128; @@ -4531,31 +4525,36 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_2048_from_mp(m, 64, mm); err = sp_2048_mod_exp_64(r, a, d, 2048, m, 0); } + if (err == MP_OKAY) { sp_2048_to_bin(r, out); *outLen = 256; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[64 * 2]; - sp_digit p[32], q[32], dp[32]; - sp_digit tmpa[64], tmpb[64]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[32 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -4575,31 +4574,23 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 64 * 2; q = p + 32; qi = dq = dp = q + 32; tmpa = qi + 32; tmpb = tmpa + 64; - - r = t + 64; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_2048_from_bin(a, 64, in, inLen); sp_2048_from_mp(p, 32, pm); sp_2048_from_mp(q, 32, qm); @@ -4631,18 +4622,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 32 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -4666,17 +4654,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 64; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -4689,14 +4679,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -4723,10 +4715,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -5178,34 +5173,31 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[193]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 128; -#else - tmp = &td[128]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_64(norm, m); @@ -5223,34 +5215,34 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_2048_lshift_64(r, norm, (byte)y); + sp_2048_lshift_64(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -5261,7 +5253,7 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, sp_2048_mont_sqr_64(r, r, m, mp); sp_2048_mont_sqr_64(r, r, m, mp); - sp_2048_lshift_64(r, r, (byte)y); + sp_2048_lshift_64(r, r, y); sp_2048_mul_d_64(tmp, norm, r[64]); r[64] = 0; o = sp_2048_add_64(r, r, tmp); @@ -5276,9 +5268,8 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -5297,11 +5288,13 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; word32 i; @@ -5336,6 +5329,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -5357,10 +5351,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -5397,7 +5394,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -5411,7 +5408,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -5453,7 +5451,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -5487,7 +5486,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -5526,7 +5527,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_3072_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 3072 / 8 - 1; a[j] = 0; @@ -6153,7 +6157,9 @@ SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, sp_digit a1[12]; sp_digit b1[12]; sp_digit z2[24]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_12(a1, a, &a[12]); cb = sp_3072_add_12(b1, b, &b[12]); @@ -6683,7 +6689,9 @@ SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, sp_digit a1[24]; sp_digit b1[24]; sp_digit z2[48]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_24(a1, a, &a[24]); cb = sp_3072_add_24(b1, b, &b[24]); @@ -7608,7 +7616,9 @@ SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, sp_digit a1[48]; sp_digit b1[48]; sp_digit z2[96]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_48(a1, a, &a[48]); cb = sp_3072_add_48(b1, b, &b[48]); @@ -8359,7 +8369,7 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -8368,7 +8378,8 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -8377,7 +8388,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -8653,8 +8664,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_48(r, a, b); sp_3072_mont_reduce_48(r, m, mp); @@ -8667,8 +8678,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_48(r, a); sp_3072_mont_reduce_48(r, m, mp); @@ -8992,35 +9003,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 96]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -9068,34 +9075,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -9116,9 +9123,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -9137,35 +9143,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 96]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -9229,34 +9231,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -9278,16 +9280,15 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -9304,7 +9305,7 @@ static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m) sp_3072_sub_in_place_96(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -9500,8 +9501,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_96(r, a, b); sp_3072_mont_reduce_96(r, m, mp); @@ -9514,8 +9515,8 @@ static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_96(r, a); sp_3072_mont_reduce_96(r, m, mp); @@ -9858,35 +9859,31 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 192]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 192), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 192; -#else - t[i] = &td[i * 192]; -#endif } sp_3072_mont_setup(m, &mp); @@ -9934,34 +9931,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 96); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -9982,9 +9979,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -10003,35 +9999,31 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 192]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 192), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 192; -#else - t[i] = &td[i * 192]; -#endif } sp_3072_mont_setup(m, &mp); @@ -10095,34 +10087,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 96); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -10144,9 +10136,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -10167,19 +10158,18 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[192], m[96], r[192]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[96 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 384) { @@ -10193,22 +10183,18 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 96 * 2; - m = r + 96 * 2; - } #endif if (err == MP_OKAY) { + r = a + 96 * 2; + m = r + 96 * 2; ah = a + 96; sp_3072_from_bin(ah, 96, in, inLen); @@ -10281,10 +10267,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -10347,13 +10332,17 @@ SP_NOINLINE static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[96 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -10382,13 +10371,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 96; m = a + 192; @@ -10399,31 +10390,36 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_3072_from_mp(m, 96, mm); err = sp_3072_mod_exp_96(r, a, d, 3072, m, 0); } + if (err == MP_OKAY) { sp_3072_to_bin(r, out); *outLen = 384; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 96); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 96); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[96 * 2]; - sp_digit p[48], q[48], dp[48]; - sp_digit tmpa[96], tmpb[96]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[48 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -10443,31 +10439,23 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 96 * 2; q = p + 48; qi = dq = dp = q + 48; tmpa = qi + 48; tmpb = tmpa + 96; - - r = t + 96; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_3072_from_bin(a, 96, in, inLen); sp_3072_from_mp(p, 48, pm); sp_3072_from_mp(q, 48, qm); @@ -10499,18 +10487,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 48 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -10534,17 +10519,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 96; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 96; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -10557,14 +10544,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 96; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -10591,10 +10580,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[192], e[96], m[96]; + sp_digit b[192]; + sp_digit e[96]; + sp_digit m[96]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -11244,34 +11236,31 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[289]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 192; -#else - tmp = &td[192]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_96(norm, m); @@ -11289,34 +11278,34 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_3072_lshift_96(r, norm, (byte)y); + sp_3072_lshift_96(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -11327,7 +11316,7 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, sp_3072_mont_sqr_96(r, r, m, mp); sp_3072_mont_sqr_96(r, r, m, mp); - sp_3072_lshift_96(r, r, (byte)y); + sp_3072_lshift_96(r, r, y); sp_3072_mul_d_96(tmp, norm, r[96]); r[96] = 0; o = sp_3072_add_96(r, r, tmp); @@ -11342,9 +11331,8 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -11363,11 +11351,13 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[192], e[96], m[96]; + sp_digit b[192]; + sp_digit e[96]; + sp_digit m[96]; sp_digit* r = b; word32 i; @@ -11402,6 +11392,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -11423,10 +11414,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -11463,7 +11457,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -11477,7 +11471,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -11519,7 +11514,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -11553,7 +11549,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -11592,7 +11590,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_4096_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 4096 / 8 - 1; a[j] = 0; @@ -12738,7 +12739,9 @@ SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, sp_digit a1[64]; sp_digit b1[64]; sp_digit z2[128]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_64(a1, a, &a[64]); cb = sp_2048_add_64(b1, b, &b[64]); @@ -13137,7 +13140,8 @@ SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -13146,7 +13150,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -13232,7 +13236,7 @@ static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m) sp_4096_sub_in_place_128(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -13426,8 +13430,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_128(r, a, b); sp_4096_mont_reduce_128(r, m, mp); @@ -13440,8 +13444,8 @@ static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_128(r, a); sp_4096_mont_reduce_128(r, m, mp); @@ -13784,35 +13788,31 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 256]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 256; -#else - t[i] = &td[i * 256]; -#endif } sp_4096_mont_setup(m, &mp); @@ -13860,34 +13860,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 128); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -13908,9 +13908,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -13929,35 +13928,31 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 256]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 256; -#else - t[i] = &td[i * 256]; -#endif } sp_4096_mont_setup(m, &mp); @@ -14021,34 +14016,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 128); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -14070,9 +14065,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -14093,19 +14087,18 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[256], m[128], r[256]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[128 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 512) { @@ -14119,22 +14112,18 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 128 * 2; - m = r + 128 * 2; - } #endif if (err == MP_OKAY) { + r = a + 128 * 2; + m = r + 128 * 2; ah = a + 128; sp_4096_from_bin(ah, 128, in, inLen); @@ -14207,10 +14196,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -14274,13 +14262,17 @@ SP_NOINLINE static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[128 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -14309,13 +14301,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 128; m = a + 256; @@ -14326,31 +14320,36 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_4096_from_mp(m, 128, mm); err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0); } + if (err == MP_OKAY) { sp_4096_to_bin(r, out); *outLen = 512; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 128); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 128); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128 * 2]; - sp_digit p[64], q[64], dp[64]; - sp_digit tmpa[128], tmpb[128]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -14370,31 +14369,23 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 128 * 2; q = p + 64; qi = dq = dp = q + 64; tmpa = qi + 64; tmpb = tmpa + 128; - - r = t + 128; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_4096_from_bin(a, 128, in, inLen); sp_4096_from_mp(p, 64, pm); sp_4096_from_mp(q, 64, qm); @@ -14426,18 +14417,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 64 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -14461,17 +14449,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 128; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 128; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -14484,14 +14474,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 128; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -14518,10 +14510,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[256], e[128], m[128]; + sp_digit b[256]; + sp_digit e[128]; + sp_digit m[128]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -15367,34 +15362,31 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[385]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 256; -#else - tmp = &td[256]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_128(norm, m); @@ -15412,34 +15404,34 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_4096_lshift_128(r, norm, (byte)y); + sp_4096_lshift_128(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -15450,7 +15442,7 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, sp_4096_mont_sqr_128(r, r, m, mp); sp_4096_mont_sqr_128(r, r, m, mp); - sp_4096_lshift_128(r, r, (byte)y); + sp_4096_lshift_128(r, r, y); sp_4096_mul_d_128(tmp, norm, r[128]); r[128] = 0; o = sp_4096_add_128(r, r, tmp); @@ -15465,9 +15457,8 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -15486,11 +15477,13 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[256], e[128], m[128]; + sp_digit b[256]; + sp_digit e[128]; + sp_digit m[128]; sp_digit* r = b; word32 i; @@ -15525,6 +15518,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -15537,19 +15531,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, } #endif /* WOLFSSL_HAVE_SP_DH */ -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 8]; + /* Y ordinate of point. */ sp_digit y[2 * 8]; + /* Z ordinate of point. */ sp_digit z[2 * 8]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -15619,305 +15617,6 @@ static const sp_digit p256_b[8] = { }; #endif -static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - */ -static int sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ - int64_t t[8]; - int64_t a64[8]; - int64_t o; - - (void)m; - - a64[0] = a[0]; - a64[1] = a[1]; - a64[2] = a[2]; - a64[3] = a[3]; - a64[4] = a[4]; - a64[5] = a[5]; - a64[6] = a[6]; - a64[7] = a[7]; - - /* 1 1 0 -1 -1 -1 -1 0 */ - t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6]; - /* 0 1 1 0 -1 -1 -1 -1 */ - t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7]; - /* 0 0 1 1 0 -1 -1 -1 */ - t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7]; - /* -1 -1 0 2 2 1 0 -1 */ - t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7]; - /* 0 -1 -1 0 2 2 1 0 */ - t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6]; - /* 0 0 -1 -1 0 2 2 1 */ - t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7]; - /* -1 -1 0 0 0 1 3 2 */ - t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7]; - /* 1 0 -1 -1 -1 -1 0 3 */ - t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - o = t[7] >> 32; t[7] &= 0xffffffff; - t[0] += o; - t[3] -= o; - t[6] -= o; - t[7] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - r[0] = t[0]; - r[1] = t[1]; - r[2] = t[2]; - r[3] = t[3]; - r[4] = t[4]; - r[5] = t[5]; - r[6] = t[6]; - r[7] = t[7]; - - return MP_OKAY; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 32 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 32 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xffffffff; - s = 32U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 32U) <= (word32)DIGIT_BIT) { - s += 32U; - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 32) { - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - s = 32 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_256. - * - * p Point of type sp_point_256 (result). - * pm Point of type ecc_point. - */ -static void sp_256_point_from_ecc_point_8(sp_point_256* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_256_from_mp(p->x, 8, pm->x); - sp_256_from_mp(p->y, 8, pm->y); - sp_256_from_mp(p->z, 8, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_256_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 32 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); - r->used = 8; - mp_clamp(r); -#elif DIGIT_BIT < 32 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 8; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 32) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 32 - s; - } - r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 8; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 32 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 32 - s; - } - else { - s += 32; - } - } - r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_256 to type ecc_point. - * - * p Point of type sp_point_256. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_256_point_to_ecc_point_8(const sp_point_256* p, ecc_point* pm) -{ - int err; - - err = sp_256_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, pm->z); - } - - return err; -} - /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -16018,6 +15717,602 @@ SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, XMEMCPY(r, tmp, sizeof(tmp)); } +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #64\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #60\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #64\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #32\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + int64_t t[8]; + int64_t a64[8]; + int64_t o; + + (void)m; + + a64[0] = a[0]; + a64[1] = a[1]; + a64[2] = a[2]; + a64[3] = a[3]; + a64[4] = a[4]; + a64[5] = a[5]; + a64[6] = a[6]; + a64[7] = a[7]; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point_256* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_256 to type ecc_point. + * + * p Point of type sp_point_256. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_8(const sp_point_256* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pm->z); + } + + return err; +} + /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -16332,161 +16627,13 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_256_mul_8(r, a, b); sp_256_mont_reduce_8(r, m, mp); } -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "mov r3, #0\n\t" - "mov r4, #0\n\t" - "mov r5, #0\n\t" - "mov r8, r3\n\t" - "mov r11, %[r]\n\t" - "mov r6, #64\n\t" - "neg r6, r6\n\t" - "add sp, r6\n\t" - "mov r10, sp\n\t" - "mov r9, %[a]\n\t" - "\n1:\n\t" - "mov %[r], #0\n\t" - "mov r6, #28\n\t" - "mov %[a], r8\n\t" - "sub %[a], r6\n\t" - "sbc r6, r6\n\t" - "mvn r6, r6\n\t" - "and %[a], r6\n\t" - "mov r2, r8\n\t" - "sub r2, %[a]\n\t" - "add %[a], r9\n\t" - "add r2, r9\n\t" - "\n2:\n\t" - "cmp r2, %[a]\n\t" - "beq 4f\n\t" - "# Multiply * 2: Start\n\t" - "ldr r6, [%[a]]\n\t" - "ldr r7, [r2]\n\t" - "lsl r6, r6, #16\n\t" - "lsl r7, r7, #16\n\t" - "lsr r6, r6, #16\n\t" - "lsr r7, r7, #16\n\t" - "mul r7, r6\n\t" - "add r3, r7\n\t" - "adc r4, %[r]\n\t" - "adc r5, %[r]\n\t" - "add r3, r7\n\t" - "adc r4, %[r]\n\t" - "adc r5, %[r]\n\t" - "ldr r7, [r2]\n\t" - "lsr r7, r7, #16\n\t" - "mul r6, r7\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "ldr r6, [%[a]]\n\t" - "ldr r7, [r2]\n\t" - "lsr r6, r6, #16\n\t" - "lsr r7, r7, #16\n\t" - "mul r7, r6\n\t" - "add r4, r7\n\t" - "adc r5, %[r]\n\t" - "add r4, r7\n\t" - "adc r5, %[r]\n\t" - "ldr r7, [r2]\n\t" - "lsl r7, r7, #16\n\t" - "lsr r7, r7, #16\n\t" - "mul r6, r7\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "# Multiply * 2: Done\n\t" - "bal 5f\n\t" - "\n4:\n\t" - "# Square: Start\n\t" - "ldr r6, [%[a]]\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "lsr r6, r6, #16\n\t" - "mul r6, r6\n\t" - "add r3, r6\n\t" - "adc r4, %[r]\n\t" - "adc r5, %[r]\n\t" - "mul r7, r7\n\t" - "add r4, r7\n\t" - "adc r5, %[r]\n\t" - "ldr r6, [%[a]]\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "lsr r6, r6, #16\n\t" - "mul r6, r7\n\t" - "lsr r7, r6, #15\n\t" - "lsl r6, r6, #17\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "# Square: Done\n\t" - "\n5:\n\t" - "add %[a], #4\n\t" - "sub r2, #4\n\t" - "mov r6, #32\n\t" - "add r6, r9\n\t" - "cmp %[a], r6\n\t" - "beq 3f\n\t" - "cmp %[a], r2\n\t" - "bgt 3f\n\t" - "mov r7, r8\n\t" - "add r7, r9\n\t" - "cmp %[a], r7\n\t" - "ble 2b\n\t" - "\n3:\n\t" - "mov %[r], r10\n\t" - "mov r7, r8\n\t" - "str r3, [%[r], r7]\n\t" - "mov r3, r4\n\t" - "mov r4, r5\n\t" - "mov r5, #0\n\t" - "add r7, #4\n\t" - "mov r8, r7\n\t" - "mov r6, #56\n\t" - "cmp r7, r6\n\t" - "ble 1b\n\t" - "mov %[a], r9\n\t" - "str r3, [%[r], r7]\n\t" - "mov %[r], r11\n\t" - "mov %[a], r10\n\t" - "mov r3, #60\n\t" - "\n4:\n\t" - "ldr r6, [%[a], r3]\n\t" - "str r6, [%[r], r3]\n\t" - "sub r3, #4\n\t" - "bge 4b\n\t" - "mov r6, #64\n\t" - "add sp, r6\n\t" - : - : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" - ); -} - /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -16494,8 +16641,8 @@ SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_256_sqr_8(r, a); sp_256_mont_reduce_8(r, m, mp); @@ -16519,7 +16666,7 @@ static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint32_t p256_mod_minus_2[8] = { @@ -16652,7 +16799,8 @@ SP_NOINLINE static int32_t sp_256_cmp_8(const sp_digit* a, const sp_digit* b) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*8; @@ -16688,100 +16836,6 @@ static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "mov r7, #0\n\t" - "add r6, #32\n\t" - "sub r7, #1\n\t" - "\n1:\n\t" - "add %[c], r7\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r]]\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c]\n\t" - "add %[a], #4\n\t" - "add %[b], #4\n\t" - "add %[r], #4\n\t" - "cmp %[a], r6\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7" - ); - - return c; -} - -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[b], #0]\n\t" - "add r4, r5\n\t" - "str r4, [%[r], #0]\n\t" - "ldr r4, [%[a], #4]\n\t" - "ldr r5, [%[b], #4]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #4]\n\t" - "ldr r4, [%[a], #8]\n\t" - "ldr r5, [%[b], #8]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #8]\n\t" - "ldr r4, [%[a], #12]\n\t" - "ldr r5, [%[b], #12]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[b], #16]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #16]\n\t" - "ldr r4, [%[a], #20]\n\t" - "ldr r5, [%[b], #20]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #20]\n\t" - "ldr r4, [%[a], #24]\n\t" - "ldr r5, [%[b], #24]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #24]\n\t" - "ldr r4, [%[a], #28]\n\t" - "ldr r5, [%[b], #28]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #28]\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -17415,97 +17469,6 @@ static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_d sp_256_mont_sub_8(y, y, t2, p256_mod); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "add r6, #32\n\t" - "\n1:\n\t" - "mov r5, #0\n\t" - "sub r5, %[c]\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "sbc r4, r5\n\t" - "str r4, [%[r]]\n\t" - "sbc %[c], %[c]\n\t" - "add %[a], #4\n\t" - "add %[b], #4\n\t" - "add %[r], #4\n\t" - "cmp %[a], r6\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6" - ); - - return c; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[a], #4]\n\t" - "ldr r6, [%[b], #0]\n\t" - "ldr r7, [%[b], #4]\n\t" - "sub r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #0]\n\t" - "str r5, [%[r], #4]\n\t" - "ldr r4, [%[a], #8]\n\t" - "ldr r5, [%[a], #12]\n\t" - "ldr r6, [%[b], #8]\n\t" - "ldr r7, [%[b], #12]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #8]\n\t" - "str r5, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[a], #20]\n\t" - "ldr r6, [%[b], #16]\n\t" - "ldr r7, [%[b], #20]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #16]\n\t" - "str r5, [%[r], #20]\n\t" - "ldr r4, [%[a], #24]\n\t" - "ldr r5, [%[a], #28]\n\t" - "ldr r6, [%[b], #24]\n\t" - "ldr r7, [%[b], #28]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #24]\n\t" - "str r5, [%[r], #28]\n\t" - "sbc %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Compare two numbers to determine if they are equal. * Constant time implementation. * @@ -17729,8 +17692,8 @@ static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_8(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -17885,9 +17848,11 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Simple, smaller code size and memory size, of windowing. - * Calculate uindow of 4 bits. - * Only add points from table. + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 256 doubles. + * 76 adds. * * r Resulting point. * g Point to multiply. @@ -17900,55 +17865,55 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table, static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td[16]; - sp_point_256 rtd; - sp_digit tmpd[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 t[16 + 1]; + sp_digit tmp[2 * 8 * 5]; +#endif + sp_point_256* rt = NULL; #ifndef WC_NO_CACHE_RESISTANT - sp_point_256 pd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* p = NULL; +#else + sp_point_256 p[1]; #endif -#endif - sp_point_256* t; - sp_point_256* rt; -#ifndef WC_NO_CACHE_RESISTANT - sp_point_256* p; -#endif - sp_digit* tmp; +#endif /* !WC_NO_CACHE_RESISTANT */ sp_digit n; int i; - int c, y; - int err; + int c; + int y; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -#ifndef WC_NO_CACHE_RESISTANT - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 17, heap, DYNAMIC_TYPE_ECC); -#else - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 16, heap, DYNAMIC_TYPE_ECC); -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + #ifndef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), + heap, DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } + #endif + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { -#ifndef WC_NO_CACHE_RESISTANT - #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - p = t + 16; - #else - p = &pd; - #endif -#endif + rt = t + 16; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; @@ -17989,7 +17954,7 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons i = 6; n = k[i+1] << 0; c = 28; - y = n >> 28; + y = (int)(n >> 28); #ifndef WC_NO_CACHE_RESISTANT if (ct) { sp_256_get_point_16_8(rt, t, y); @@ -18036,30 +18001,39 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_256) * 16); - XFREE(t, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmpd, sizeof(tmpd)); - ForceZero(td, sizeof(td)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif - sp_256_point_free_8(rt, 1, heap); + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 8 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#ifndef WC_NO_CACHE_RESISTANT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (p != NULL) + #endif + { + ForceZero(p, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* !WC_NO_CACHE_RESISTANT */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_256 { - sp_digit x[8]; - sp_digit y[8]; -} sp_table_entry_256; - #ifdef FP_ECC /* Double the Montgomery form projective point p a number of times. * @@ -18068,7 +18042,8 @@ typedef struct sp_table_entry_256 { * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*8; @@ -18149,6 +18124,36 @@ static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t) sp_256_div2_8(y, y, p256_mod); } +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +#endif /* FP_ECC */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[8]; + sp_digit y[8]; +} sp_table_entry_256; + +#ifdef FP_ECC #endif /* FP_ECC */ /* Add two Montgomery form projective points. The second point has a q value of * one. @@ -18234,29 +18239,11 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, #ifdef WOLFSSL_SP_SMALL #ifdef FP_ECC -/* Convert the projective point to affine. - * Ordinates are in Montgomery form. - * - * a Point to convert. - * t Temporary data. - */ -static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 8; - sp_digit* tmp = t + 4 * 8; - - sp_256_mont_inv_8(t1, a->z, tmp); - - sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); - - sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); - XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); -} - /* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 64 bits between * * a The base point. * table Place to store generated point data. @@ -18266,26 +18253,30 @@ static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_8(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_8(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -18330,9 +18321,10 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a, } } - sp_256_point_free_8(s2, 0, heap); - sp_256_point_free_8(s1, 0, heap); - sp_256_point_free_8( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -18391,8 +18383,10 @@ static void sp_256_get_entry_16_8(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 4 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -18406,17 +18400,19 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 8 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -18424,27 +18420,30 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=63; j<4; j++,x+=64) { + x = 63; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 64; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -18458,8 +18457,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=62; i>=0; i--) { y = 0; - for (j=0,x=i; j<4; j++,x+=64) { + x = i; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 64; } sp_256_proj_point_dbl_8(rt, rt, t); @@ -18485,13 +18486,12 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(rt, 0, heap); return err; } @@ -18501,16 +18501,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[8]; + /* Y ordinate of point that table was generated from. */ sp_digit y[8]; + /* Precomputation table for point. */ sp_table_entry_256 table[16]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -18518,9 +18527,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -18629,6 +18644,10 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ #else #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 32 bits between * * a The base point. * table Place to store generated point data. @@ -18638,26 +18657,30 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ static int sp_256_gen_stripe_table_8(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_8(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -18702,9 +18725,10 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a, } } - sp_256_point_free_8(s2, 0, heap); - sp_256_point_free_8(s1, 0, heap); - sp_256_point_free_8( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -18763,8 +18787,10 @@ static void sp_256_get_entry_256_8(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -18778,17 +18804,19 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 8 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -18796,27 +18824,30 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=31; j<8; j++,x+=32) { + x = 31; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 32; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -18830,8 +18861,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=30; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=32) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 32; } sp_256_proj_point_dbl_8(rt, rt, t); @@ -18857,13 +18890,12 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(rt, 0, heap); return err; } @@ -18873,16 +18905,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[8]; + /* Y ordinate of point that table was generated from. */ sp_digit y[8]; + /* Precomputation table for point. */ sp_table_entry_256 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -18890,9 +18931,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -19009,28 +19056,31 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 8, km); sp_256_point_from_ecc_point_8(point, gm); @@ -19041,17 +19091,101 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_8(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[8 + 8 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_8(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 8; + + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + sp_256_point_from_ecc_point_8(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_8(point, point, addP, tmp); + + if (map) { + sp_256_map_8(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 64 between points. + */ static const sp_table_entry_256 p256_table[16] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -19136,6 +19270,11 @@ static const sp_table_entry_256 p256_table[16] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -19151,6 +19290,10 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 32 between points. + */ static const sp_table_entry_256 p256_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -20435,6 +20578,11 @@ static const sp_table_entry_256 p256_table[256] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -20460,28 +20608,30 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 8, km); @@ -20491,12 +20641,90 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_8(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[8 + 8 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (8 + 8 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_8(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 8; + + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_8(point, point, addP, tmp); + + if (map) { + sp_256_map_8(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -20514,7 +20742,7 @@ static int sp_256_iszero_8(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -20563,7 +20791,8 @@ SP_NOINLINE static void sp_256_add_one_8(sp_digit* a) */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -20626,41 +20855,46 @@ static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[8]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_256_point_new_8(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_8(rng, k); } if (err == MP_OKAY) { @@ -20685,15 +20919,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_8(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_8(infinity, 1, heap); -#endif - sp_256_point_free_8(point, 1, heap); return err; } @@ -20707,7 +20940,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_256_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 256 / 8 - 1; a[j] = 0; @@ -20748,33 +20984,35 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; if (*outLen < 32U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -20787,12 +21025,12 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(point, 0, heap); return err; } @@ -21190,7 +21428,7 @@ static const uint32_t p256_order_minus_2[8] = { }; #else /* The low half of the order-2 of the P256 curve. */ -static const uint32_t p256_order_low[4] = { +static const sp_int_digit p256_order_low[4] = { 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU }; #endif /* WOLFSSL_SP_SMALL */ @@ -21336,7 +21574,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ for (i=127; i>=112; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21346,7 +21584,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ for (i=107; i>=64; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21356,7 +21594,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ for (i=59; i>=32; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21366,7 +21604,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ for (i=27; i>=0; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21377,12 +21615,63 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(k); + + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -21417,8 +21706,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -21436,13 +21725,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 8, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_8(rng, ctx->k); @@ -21470,6 +21756,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_8(ctx->r, p256_order); sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_8(ctx->r); + + sp_256_from_mp(ctx->x, 8, priv); + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); ctx->state = 4; break; } @@ -21526,6 +21815,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -21558,72 +21850,55 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*8]; - sp_digit xd[2*8]; - sp_digit kd[2*8]; - sp_digit rd[2*8]; - sp_digit td[3 * 2*8]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 8]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 8; - x = d + 2 * 8; - k = d + 4 * 8; - r = d + 6 * 8; - tmp = d + 8 * 8; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 8; + k = e + 4 * 8; + r = e + 6 * 8; + tmp = e + 8 * 8; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 8, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 8, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_8(rng, k); @@ -21633,7 +21908,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -21644,38 +21919,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_8(r); - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_8(k, k, p256_norm_order); - err = sp_256_mod_8(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_8(k); - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_8(kInv, k, tmp); - sp_256_norm_8(kInv); + sp_256_from_mp(x, 8, priv); + sp_256_from_bin(e, 8, hash, (int)hashLen); - /* s = r * x + e */ - sp_256_mul_8(x, x, r); - err = sp_256_mod_8(x, x, p256_order); + err = sp_256_calc_s_8(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_8(x); - carry = sp_256_add_8(s, e, x); - sp_256_cond_sub_8(s, s, p256_order, 0 - carry); - sp_256_norm_8(s); - c = sp_256_cmp_8(s, p256_order); - sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_8(s); - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_8(s, s, kInv); - sp_256_norm_8(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_8(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -21689,20 +21945,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_8(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -22284,6 +22544,96 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ + + sp_256_proj_point_add_8(p1, p1, p2, tmp); + if (sp_256_iszero_8(p1->z)) { + if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { + sp_256_proj_point_dbl_8(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_256_mod_inv_8(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_256_mul_8(s, s, p256_norm_order); + } + err = sp_256_mod_8(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + +#else + { + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_8(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -22302,8 +22652,7 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -22322,8 +22671,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -22338,7 +22688,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); sp_256_from_mp(ctx->s, 8, sm); sp_256_from_mp(ctx->p2.x, 8, pX); sp_256_from_mp(ctx->p2.y, 8, pY); @@ -22396,57 +22746,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_8(ctx->p1.z)) { - if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<8; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -22454,22 +22780,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_8(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -22477,130 +22804,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*8]; - sp_digit u2d[2*8]; - sp_digit sd[2*8]; - sp_digit tmpd[2*8 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 8]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_8(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 8; - u2 = d + 2 * 8; - s = d + 4 * 8; - tmp = d + 6 * 8; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 8; + s = u1 + 4 * 8; + tmp = u1 + 6 * 8; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 8, hash, (int)hashLen); - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); sp_256_from_mp(s, 8, sm); sp_256_from_mp(p2->x, 8, pX); sp_256_from_mp(p2->y, 8, pY); sp_256_from_mp(p2->z, 8, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_256_mod_inv_8(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_8(s, s, p256_norm_order); - } - err = sp_256_mod_8(s, s, p256_order); + err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_8(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_8(s, s, tmp); - sp_256_mont_mul_order_8(u1, u1, s); - sp_256_mont_mul_order_8(u2, u2, s); - } - -#else - { - sp_256_mont_mul_order_8(u1, u1, s); - sp_256_mont_mul_order_8(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_256_proj_point_add_8(p1, p1, p2, tmp); - if (sp_256_iszero_8(p1->z)) { - if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { - sp_256_proj_point_dbl_8(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); } @@ -22611,7 +22871,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); carry = sp_256_add_8(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -22619,26 +22879,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_8(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_8(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p1, 0, heap); - sp_256_point_free_8(p2, 0, heap); return err; } @@ -22652,34 +22912,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_8(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*8]; - sp_digit t2d[2*8]; + sp_digit t1[8 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 8; - t2 = d + 2 * 8; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 8; sp_256_sqr_8(t1, point->y); (void)sp_256_mod_8(t1, t1, p256_mod); @@ -22699,10 +22951,9 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -22715,16 +22966,23 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_8(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 8, pX); sp_256_from_mp(pub->y, 8, pY); @@ -22733,7 +22991,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_8(pub, NULL); } - sp_256_point_free_8(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -22749,47 +23010,48 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[8]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; - sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_256_point_new_8(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_256* pub = NULL; +#else + sp_digit priv[8]; + sp_point_256 pub[2]; #endif + sp_point_256* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 8, pX); sp_256_from_mp(pub->y, 8, pY); sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); @@ -22803,12 +23065,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || - sp_256_cmp_8(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_8(pub->x, p256_mod) >= 0) || + (sp_256_cmp_8(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -22820,12 +23081,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_8(p->x) == 0) || - (sp_256_iszero_8(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) || + (sp_256_iszero_8(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -22833,22 +23092,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_8(p->x, pub->x) != 0 || - sp_256_cmp_8(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_8(p->x, pub->x) != 0) || + (sp_256_cmp_8(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(pub, 0, heap); return err; } @@ -22872,33 +23129,35 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; - err = sp_256_point_new_8(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 8, pX); sp_256_from_mp(p->y, 8, pY); sp_256_from_mp(p->z, 8, pZ); @@ -22919,13 +23178,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(q, 0, NULL); - sp_256_point_free_8(p, 0, NULL); return err; } @@ -22944,25 +23202,28 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_8(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -22983,12 +23244,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, NULL); return err; } @@ -23003,32 +23264,36 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_8(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 8, pX); sp_256_from_mp(p->y, 8, pY); sp_256_from_mp(p->z, 8, pZ); - sp_256_map_8(p, p, tmp); + sp_256_map_8(p, p, tmp); } if (err == MP_OKAY) { @@ -23041,12 +23306,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, NULL); return err; } @@ -23059,31 +23324,23 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_8(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 8]; - sp_digit t2d[2 * 8]; + sp_digit t1[4 * 8]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 8; - t2 = d + 2 * 8; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 8; { /* t2 = y ^ 0x2 */ @@ -23118,10 +23375,9 @@ static int sp_256_mont_sqrt_8(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -23137,31 +23393,22 @@ static int sp_256_mont_sqrt_8(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 8]; - sp_digit yd[2 * 8]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 8]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 8; - y = d + 2 * 8; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 8; sp_256_from_mp(x, 8, xm); err = sp_256_mod_mul_norm_8(x, x, p256_mod); @@ -23194,10 +23441,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -23208,9 +23454,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 12]; + /* Y ordinate of point. */ sp_digit y[2 * 12]; + /* Z ordinate of point. */ sp_digit z[2 * 12]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; @@ -23280,336 +23530,6 @@ static const sp_digit p384_b[12] = { }; #endif -static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* t; -#else - int64_t t[12]; -#endif - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); - if (t == NULL) { - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ - t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11]; - /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ - t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11]; - /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ - t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11]; - /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ - t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11]; - /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ - t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11]; - /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ - t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11]; - /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ - t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11]; - /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ - t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11]; - /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ - t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8]; - /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ - t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9]; - /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ - t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10]; - /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ - t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - o = t[11] >> 32; t[11] &= 0xffffffff; - t[0] += o; - t[1] -= o; - t[3] += o; - t[4] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - - r[0] = t[0]; - r[1] = t[1]; - r[2] = t[2]; - r[3] = t[3]; - r[4] = t[4]; - r[5] = t[5]; - r[6] = t[6]; - r[7] = t[7]; - r[8] = t[8]; - r[9] = t[9]; - r[10] = t[10]; - r[11] = t[11]; - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) - XFREE(t, NULL, DYNAMIC_TYPE_ECC); -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 32 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 32 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xffffffff; - s = 32U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 32U) <= (word32)DIGIT_BIT) { - s += 32U; - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 32) { - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - s = 32 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_384. - * - * p Point of type sp_point_384 (result). - * pm Point of type ecc_point. - */ -static void sp_384_point_from_ecc_point_12(sp_point_384* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_384_from_mp(p->x, 12, pm->x); - sp_384_from_mp(p->y, 12, pm->y); - sp_384_from_mp(p->z, 12, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_384_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 32 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); - r->used = 12; - mp_clamp(r); -#elif DIGIT_BIT < 32 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 12; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 32) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 32 - s; - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 12; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 32 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 32 - s; - } - else { - s += 32; - } - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_384 to type ecc_point. - * - * p Point of type sp_point_384. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) -{ - int err; - - err = sp_384_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pm->z); - } - - return err; -} - /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -23710,6 +23630,665 @@ SP_NOINLINE static void sp_384_mul_12(sp_digit* r, const sp_digit* a, XMEMCPY(r, tmp, sizeof(tmp)); } +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #96\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #48\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #88\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #92\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #96\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #48\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, #48\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[12]; +#endif + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + r[8] = t[8]; + r[9] = t[9]; + r[10] = t[10]; + r[11] = t[11]; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_12(sp_point_384* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_384_from_mp(p->x, 12, pm->x); + sp_384_from_mp(p->y, 12, pm->y); + sp_384_from_mp(p->z, 12, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); + r->used = 12; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -23901,161 +24480,13 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_12(r, a, b); sp_384_mont_reduce_12(r, m, mp); } -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "mov r3, #0\n\t" - "mov r4, #0\n\t" - "mov r5, #0\n\t" - "mov r8, r3\n\t" - "mov r11, %[r]\n\t" - "mov r6, #96\n\t" - "neg r6, r6\n\t" - "add sp, r6\n\t" - "mov r10, sp\n\t" - "mov r9, %[a]\n\t" - "\n1:\n\t" - "mov %[r], #0\n\t" - "mov r6, #44\n\t" - "mov %[a], r8\n\t" - "sub %[a], r6\n\t" - "sbc r6, r6\n\t" - "mvn r6, r6\n\t" - "and %[a], r6\n\t" - "mov r2, r8\n\t" - "sub r2, %[a]\n\t" - "add %[a], r9\n\t" - "add r2, r9\n\t" - "\n2:\n\t" - "cmp r2, %[a]\n\t" - "beq 4f\n\t" - "# Multiply * 2: Start\n\t" - "ldr r6, [%[a]]\n\t" - "ldr r7, [r2]\n\t" - "lsl r6, r6, #16\n\t" - "lsl r7, r7, #16\n\t" - "lsr r6, r6, #16\n\t" - "lsr r7, r7, #16\n\t" - "mul r7, r6\n\t" - "add r3, r7\n\t" - "adc r4, %[r]\n\t" - "adc r5, %[r]\n\t" - "add r3, r7\n\t" - "adc r4, %[r]\n\t" - "adc r5, %[r]\n\t" - "ldr r7, [r2]\n\t" - "lsr r7, r7, #16\n\t" - "mul r6, r7\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "ldr r6, [%[a]]\n\t" - "ldr r7, [r2]\n\t" - "lsr r6, r6, #16\n\t" - "lsr r7, r7, #16\n\t" - "mul r7, r6\n\t" - "add r4, r7\n\t" - "adc r5, %[r]\n\t" - "add r4, r7\n\t" - "adc r5, %[r]\n\t" - "ldr r7, [r2]\n\t" - "lsl r7, r7, #16\n\t" - "lsr r7, r7, #16\n\t" - "mul r6, r7\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "# Multiply * 2: Done\n\t" - "bal 5f\n\t" - "\n4:\n\t" - "# Square: Start\n\t" - "ldr r6, [%[a]]\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "lsr r6, r6, #16\n\t" - "mul r6, r6\n\t" - "add r3, r6\n\t" - "adc r4, %[r]\n\t" - "adc r5, %[r]\n\t" - "mul r7, r7\n\t" - "add r4, r7\n\t" - "adc r5, %[r]\n\t" - "ldr r6, [%[a]]\n\t" - "lsr r7, r6, #16\n\t" - "lsl r6, r6, #16\n\t" - "lsr r6, r6, #16\n\t" - "mul r6, r7\n\t" - "lsr r7, r6, #15\n\t" - "lsl r6, r6, #17\n\t" - "add r3, r6\n\t" - "adc r4, r7\n\t" - "adc r5, %[r]\n\t" - "# Square: Done\n\t" - "\n5:\n\t" - "add %[a], #4\n\t" - "sub r2, #4\n\t" - "mov r6, #48\n\t" - "add r6, r9\n\t" - "cmp %[a], r6\n\t" - "beq 3f\n\t" - "cmp %[a], r2\n\t" - "bgt 3f\n\t" - "mov r7, r8\n\t" - "add r7, r9\n\t" - "cmp %[a], r7\n\t" - "ble 2b\n\t" - "\n3:\n\t" - "mov %[r], r10\n\t" - "mov r7, r8\n\t" - "str r3, [%[r], r7]\n\t" - "mov r3, r4\n\t" - "mov r4, r5\n\t" - "mov r5, #0\n\t" - "add r7, #4\n\t" - "mov r8, r7\n\t" - "mov r6, #88\n\t" - "cmp r7, r6\n\t" - "ble 1b\n\t" - "mov %[a], r9\n\t" - "str r3, [%[r], r7]\n\t" - "mov %[r], r11\n\t" - "mov %[a], r10\n\t" - "mov r3, #92\n\t" - "\n4:\n\t" - "ldr r6, [%[a], r3]\n\t" - "str r6, [%[r], r3]\n\t" - "sub r3, #4\n\t" - "bge 4b\n\t" - "mov r6, #96\n\t" - "add sp, r6\n\t" - : - : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" - ); -} - /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -24063,8 +24494,8 @@ SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_12(r, a); sp_384_mont_reduce_12(r, m, mp); @@ -24088,7 +24519,7 @@ static void sp_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint32_t p384_mod_minus_2[12] = { @@ -24237,7 +24668,8 @@ SP_NOINLINE static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*12; @@ -24273,116 +24705,6 @@ static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "mov r7, #0\n\t" - "add r6, #48\n\t" - "sub r7, #1\n\t" - "\n1:\n\t" - "add %[c], r7\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r]]\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c]\n\t" - "add %[a], #4\n\t" - "add %[b], #4\n\t" - "add %[r], #4\n\t" - "cmp %[a], r6\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7" - ); - - return c; -} - -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[b], #0]\n\t" - "add r4, r5\n\t" - "str r4, [%[r], #0]\n\t" - "ldr r4, [%[a], #4]\n\t" - "ldr r5, [%[b], #4]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #4]\n\t" - "ldr r4, [%[a], #8]\n\t" - "ldr r5, [%[b], #8]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #8]\n\t" - "ldr r4, [%[a], #12]\n\t" - "ldr r5, [%[b], #12]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[b], #16]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #16]\n\t" - "ldr r4, [%[a], #20]\n\t" - "ldr r5, [%[b], #20]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #20]\n\t" - "ldr r4, [%[a], #24]\n\t" - "ldr r5, [%[b], #24]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #24]\n\t" - "ldr r4, [%[a], #28]\n\t" - "ldr r5, [%[b], #28]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #28]\n\t" - "ldr r4, [%[a], #32]\n\t" - "ldr r5, [%[b], #32]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #32]\n\t" - "ldr r4, [%[a], #36]\n\t" - "ldr r5, [%[b], #36]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #36]\n\t" - "ldr r4, [%[a], #40]\n\t" - "ldr r5, [%[b], #40]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #40]\n\t" - "ldr r4, [%[a], #44]\n\t" - "ldr r5, [%[b], #44]\n\t" - "adc r4, r5\n\t" - "str r4, [%[r], #44]\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -24429,113 +24751,6 @@ SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_384_cond_sub_12(r, r, m, 0 - o); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "add r6, #48\n\t" - "\n1:\n\t" - "mov r5, #0\n\t" - "sub r5, %[c]\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "sbc r4, r5\n\t" - "str r4, [%[r]]\n\t" - "sbc %[c], %[c]\n\t" - "add %[a], #4\n\t" - "add %[b], #4\n\t" - "add %[r], #4\n\t" - "cmp %[a], r6\n\t" - "bne 1b\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6" - ); - - return c; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[a], #4]\n\t" - "ldr r6, [%[b], #0]\n\t" - "ldr r7, [%[b], #4]\n\t" - "sub r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #0]\n\t" - "str r5, [%[r], #4]\n\t" - "ldr r4, [%[a], #8]\n\t" - "ldr r5, [%[a], #12]\n\t" - "ldr r6, [%[b], #8]\n\t" - "ldr r7, [%[b], #12]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #8]\n\t" - "str r5, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[a], #20]\n\t" - "ldr r6, [%[b], #16]\n\t" - "ldr r7, [%[b], #20]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #16]\n\t" - "str r5, [%[r], #20]\n\t" - "ldr r4, [%[a], #24]\n\t" - "ldr r5, [%[a], #28]\n\t" - "ldr r6, [%[b], #24]\n\t" - "ldr r7, [%[b], #28]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #24]\n\t" - "str r5, [%[r], #28]\n\t" - "ldr r4, [%[a], #32]\n\t" - "ldr r5, [%[a], #36]\n\t" - "ldr r6, [%[b], #32]\n\t" - "ldr r7, [%[b], #36]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #32]\n\t" - "str r5, [%[r], #36]\n\t" - "ldr r4, [%[a], #40]\n\t" - "ldr r5, [%[a], #44]\n\t" - "ldr r6, [%[b], #40]\n\t" - "ldr r7, [%[b], #44]\n\t" - "sbc r4, r6\n\t" - "sbc r5, r7\n\t" - "str r4, [%[r], #40]\n\t" - "str r5, [%[r], #44]\n\t" - "sbc %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r7" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -25092,8 +25307,8 @@ static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_12(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -25272,9 +25487,11 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Simple, smaller code size and memory size, of windowing. - * Calculate uindow of 4 bits. - * Only add points from table. + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 384 doubles. + * 108 adds. * * r Resulting point. * g Point to multiply. @@ -25287,55 +25504,55 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table, static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td[16]; - sp_point_384 rtd; - sp_digit tmpd[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 t[16 + 1]; + sp_digit tmp[2 * 12 * 6]; +#endif + sp_point_384* rt = NULL; #ifndef WC_NO_CACHE_RESISTANT - sp_point_384 pd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* p = NULL; +#else + sp_point_384 p[1]; #endif -#endif - sp_point_384* t; - sp_point_384* rt; -#ifndef WC_NO_CACHE_RESISTANT - sp_point_384* p; -#endif - sp_digit* tmp; +#endif /* !WC_NO_CACHE_RESISTANT */ sp_digit n; int i; - int c, y; - int err; + int c; + int y; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -#ifndef WC_NO_CACHE_RESISTANT - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 17, heap, DYNAMIC_TYPE_ECC); -#else - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + #ifndef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), + heap, DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } + #endif + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { -#ifndef WC_NO_CACHE_RESISTANT - #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - p = t + 16; - #else - p = &pd; - #endif -#endif + rt = t + 16; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; @@ -25376,7 +25593,7 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con i = 10; n = k[i+1] << 0; c = 28; - y = n >> 28; + y = (int)(n >> 28); #ifndef WC_NO_CACHE_RESISTANT if (ct) { sp_384_get_point_16_12(rt, t, y); @@ -25423,30 +25640,39 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 12 * 6); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_384) * 16); - XFREE(t, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmpd, sizeof(tmpd)); - ForceZero(td, sizeof(td)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif - sp_384_point_free_12(rt, 1, heap); + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 12 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#ifndef WC_NO_CACHE_RESISTANT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (p != NULL) + #endif + { + ForceZero(p, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* !WC_NO_CACHE_RESISTANT */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_384 { - sp_digit x[12]; - sp_digit y[12]; -} sp_table_entry_384; - #ifdef FP_ECC /* Double the Montgomery form projective point p a number of times. * @@ -25455,7 +25681,8 @@ typedef struct sp_table_entry_384 { * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*12; @@ -25536,6 +25763,36 @@ static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) sp_384_div2_12(y, y, p384_mod); } +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 12; + sp_digit* tmp = t + 4 * 12; + + sp_384_mont_inv_12(t1, a->z, tmp); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod)); +} + +#endif /* FP_ECC */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[12]; + sp_digit y[12]; +} sp_table_entry_384; + +#ifdef FP_ECC #endif /* FP_ECC */ /* Add two Montgomery form projective points. The second point has a q value of * one. @@ -25621,29 +25878,11 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, #ifdef WOLFSSL_SP_SMALL #ifdef FP_ECC -/* Convert the projective point to affine. - * Ordinates are in Montgomery form. - * - * a Point to convert. - * t Temporary data. - */ -static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) -{ - sp_digit* t1 = t; - sp_digit* t2 = t + 2 * 12; - sp_digit* tmp = t + 4 * 12; - - sp_384_mont_inv_12(t1, a->z, tmp); - - sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); - - sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); - XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod)); -} - /* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 96 bits between * * a The base point. * table Place to store generated point data. @@ -25653,26 +25892,30 @@ static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_12(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_12(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -25717,9 +25960,10 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a, } } - sp_384_point_free_12(s2, 0, heap); - sp_384_point_free_12(s1, 0, heap); - sp_384_point_free_12( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -25794,8 +26038,10 @@ static void sp_384_get_entry_16_12(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 4 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^96, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -25809,17 +26055,19 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 12 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -25827,27 +26075,30 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=95; j<4; j++,x+=96) { + x = 95; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 96; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -25861,8 +26112,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=94; i>=0; i--) { y = 0; - for (j=0,x=i; j<4; j++,x+=96) { + x = i; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 96; } sp_384_proj_point_dbl_12(rt, rt, t); @@ -25888,13 +26141,12 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(rt, 0, heap); return err; } @@ -25904,16 +26156,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[12]; + /* Y ordinate of point that table was generated from. */ sp_digit y[12]; + /* Precomputation table for point. */ sp_table_entry_384 table[16]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -25921,9 +26182,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -26032,6 +26299,10 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp #else #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 48 bits between * * a The base point. * table Place to store generated point data. @@ -26041,26 +26312,30 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp static int sp_384_gen_stripe_table_12(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_12(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -26105,9 +26380,10 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a, } } - sp_384_point_free_12(s2, 0, heap); - sp_384_point_free_12(s1, 0, heap); - sp_384_point_free_12( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -26182,8 +26458,10 @@ static void sp_384_get_entry_256_12(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -26197,17 +26475,19 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 12 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -26215,27 +26495,30 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 47; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 48; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -26249,8 +26532,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=46; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 48; } sp_384_proj_point_dbl_12(rt, rt, t); @@ -26276,13 +26561,12 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(rt, 0, heap); return err; } @@ -26292,16 +26576,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[12]; + /* Y ordinate of point that table was generated from. */ sp_digit y[12]; + /* Precomputation table for point. */ sp_table_entry_384 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -26309,9 +26602,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -26428,28 +26727,31 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 12, km); sp_384_point_from_ecc_point_12(point, gm); @@ -26460,17 +26762,101 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_12(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[12 + 12 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_12(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 12; + + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(point, gm); + sp_384_point_from_ecc_point_12(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_12(point, point, addP, tmp); + + if (map) { + sp_384_map_12(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 96 between points. + */ static const sp_table_entry_384 p384_table[16] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -26555,6 +26941,11 @@ static const sp_table_entry_384 p384_table[16] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^96, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -26570,6 +26961,10 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 48 between points. + */ static const sp_table_entry_384 p384_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -27854,6 +28249,11 @@ static const sp_table_entry_384 p384_table[256] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -27879,28 +28279,30 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 12, km); @@ -27910,12 +28312,90 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_12(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[12 + 12 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (12 + 12 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_12(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 12; + + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_12(point, point, addP, tmp); + + if (map) { + sp_384_map_12(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -27934,7 +28414,7 @@ static int sp_384_iszero_12(const sp_digit* a) a[8] | a[9] | a[10] | a[11]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -27995,7 +28475,8 @@ SP_NOINLINE static void sp_384_add_one_12(sp_digit* a) */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -28058,41 +28539,46 @@ static int sp_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[12]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_384_point_new_12(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_12(rng, k); } if (err == MP_OKAY) { @@ -28117,15 +28603,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_12(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_12(infinity, 1, heap); -#endif - sp_384_point_free_12(point, 1, heap); return err; } @@ -28139,7 +28624,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_384_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 384 / 8 - 1; a[j] = 0; @@ -28180,33 +28668,35 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; if (*outLen < 48U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -28219,12 +28709,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(point, 0, heap); return err; } @@ -28644,7 +29134,6 @@ static const uint32_t p384_order_minus_2[12] = { /* The low half of the order-2 of the P384 curve. */ static const uint32_t p384_order_low[6] = { 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U - }; #endif /* WOLFSSL_SP_SMALL */ @@ -28792,7 +29281,7 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_12(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_12(t2, t2); - if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_384_mont_mul_order_12(t2, t2, a); } } @@ -28801,12 +29290,63 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(k, k, p384_norm_order); + err = sp_384_mod_12(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(k); + + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_12(kInv, k, tmp); + sp_384_norm_12(kInv); + + /* s = r * x + e */ + sp_384_mul_12(x, x, r); + err = sp_384_mod_12(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(x); + carry = sp_384_add_12(s, e, x); + sp_384_cond_sub_12(s, s, p384_order, 0 - carry); + sp_384_norm_12(s); + c = sp_384_cmp_12(s, p384_order); + sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(s, s, kInv); + sp_384_norm_12(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -28841,8 +29381,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -28860,13 +29400,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 12, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_12(rng, ctx->k); @@ -28894,6 +29431,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_12(ctx->r, p384_order); sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_12(ctx->r); + + sp_384_from_mp(ctx->x, 12, priv); + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); ctx->state = 4; break; } @@ -28950,6 +29490,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -28982,72 +29525,55 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*12]; - sp_digit xd[2*12]; - sp_digit kd[2*12]; - sp_digit rd[2*12]; - sp_digit td[3 * 2*12]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 12]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 12; - x = d + 2 * 12; - k = d + 4 * 12; - r = d + 6 * 12; - tmp = d + 8 * 12; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 12; + k = e + 4 * 12; + r = e + 6 * 12; + tmp = e + 8 * 12; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 12, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 12, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_12(rng, k); @@ -29057,7 +29583,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -29068,38 +29594,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_12(r); - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_12(k, k, p384_norm_order); - err = sp_384_mod_12(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_12(k); - /* kInv = 1/k mod order */ - sp_384_mont_inv_order_12(kInv, k, tmp); - sp_384_norm_12(kInv); + sp_384_from_mp(x, 12, priv); + sp_384_from_bin(e, 12, hash, (int)hashLen); - /* s = r * x + e */ - sp_384_mul_12(x, x, r); - err = sp_384_mod_12(x, x, p384_order); + err = sp_384_calc_s_12(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_12(x); - carry = sp_384_add_12(s, e, x); - sp_384_cond_sub_12(s, s, p384_order, 0 - carry); - sp_384_norm_12(s); - c = sp_384_cmp_12(s, p384_order); - sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_12(s); - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_12(s, s, kInv); - sp_384_norm_12(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_12(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -29113,20 +29620,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 12); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_12(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -29915,6 +30426,100 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ + + sp_384_proj_point_add_12(p1, p1, p2, tmp); + if (sp_384_iszero_12(p1->z)) { + if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { + sp_384_proj_point_dbl_12(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_12(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_384_mul_12(s, s, p384_norm_order); + } + err = sp_384_mod_12(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_384_mont_inv_order_12(s, s, tmp); + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + +#else + { + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_12(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -29933,8 +30538,7 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -29953,8 +30557,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -29969,7 +30574,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); sp_384_from_mp(ctx->s, 12, sm); sp_384_from_mp(ctx->p2.x, 12, pX); sp_384_from_mp(ctx->p2.y, 12, pY); @@ -30027,57 +30632,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_12(ctx->p1.z)) { - if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<12; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -30085,22 +30666,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_12(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -30108,134 +30690,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*12]; - sp_digit u2d[2*12]; - sp_digit sd[2*12]; - sp_digit tmpd[2*12 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 12]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_12(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 12; - u2 = d + 2 * 12; - s = d + 4 * 12; - tmp = d + 6 * 12; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 12; + s = u1 + 4 * 12; + tmp = u1 + 6 * 12; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 12, hash, (int)hashLen); - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); sp_384_from_mp(s, 12, sm); sp_384_from_mp(p2->x, 12, pX); sp_384_from_mp(p2->y, 12, pY); sp_384_from_mp(p2->z, 12, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_12(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_384_mul_12(s, s, p384_norm_order); - } - err = sp_384_mod_12(s, s, p384_order); + err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_12(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_384_mont_inv_order_12(s, s, tmp); - sp_384_mont_mul_order_12(u1, u1, s); - sp_384_mont_mul_order_12(u2, u2, s); - } - -#else - { - sp_384_mont_mul_order_12(u1, u1, s); - sp_384_mont_mul_order_12(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_384_proj_point_add_12(p1, p1, p2, tmp); - if (sp_384_iszero_12(p1->z)) { - if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { - sp_384_proj_point_dbl_12(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - p1->x[8] = 0; - p1->x[9] = 0; - p1->x[10] = 0; - p1->x[11] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); } @@ -30246,7 +30757,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); carry = sp_384_add_12(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -30254,26 +30765,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_12(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_12(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p1, 0, heap); - sp_384_point_free_12(p2, 0, heap); return err; } @@ -30287,34 +30798,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_12(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*12]; - sp_digit t2d[2*12]; + sp_digit t1[12 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 12; - t2 = d + 2 * 12; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 12; sp_384_sqr_12(t1, point->y); (void)sp_384_mod_12(t1, t1, p384_mod); @@ -30334,10 +30837,9 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -30350,16 +30852,23 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_12(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 12, pX); sp_384_from_mp(pub->y, 12, pY); @@ -30368,7 +30877,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_12(pub, NULL); } - sp_384_point_free_12(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -30384,47 +30896,48 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[12]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; - sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_384_point_new_12(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_384* pub = NULL; +#else + sp_digit priv[12]; + sp_point_384 pub[2]; #endif + sp_point_384* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 12, pX); sp_384_from_mp(pub->y, 12, pY); sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); @@ -30438,12 +30951,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_12(pub->x, p384_mod) >= 0 || - sp_384_cmp_12(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_12(pub->x, p384_mod) >= 0) || + (sp_384_cmp_12(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -30455,12 +30967,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_12(p->x) == 0) || - (sp_384_iszero_12(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) || + (sp_384_iszero_12(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -30468,22 +30978,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_12(p->x, pub->x) != 0 || - sp_384_cmp_12(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_12(p->x, pub->x) != 0) || + (sp_384_cmp_12(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(pub, 0, heap); return err; } @@ -30507,33 +31015,35 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; - err = sp_384_point_new_12(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 12, pX); sp_384_from_mp(p->y, 12, pY); sp_384_from_mp(p->z, 12, pZ); @@ -30554,13 +31064,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(q, 0, NULL); - sp_384_point_free_12(p, 0, NULL); return err; } @@ -30579,25 +31088,28 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_12(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -30618,12 +31130,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, NULL); return err; } @@ -30638,32 +31150,36 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_12(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 12, pX); sp_384_from_mp(p->y, 12, pY); sp_384_from_mp(p->z, 12, pZ); - sp_384_map_12(p, p, tmp); + sp_384_map_12(p, p, tmp); } if (err == MP_OKAY) { @@ -30676,12 +31192,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, NULL); return err; } @@ -30694,43 +31210,28 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_12(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 12]; - sp_digit t2d[2 * 12]; - sp_digit t3d[2 * 12]; - sp_digit t4d[2 * 12]; - sp_digit t5d[2 * 12]; + sp_digit t1[5 * 2 * 12]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 12; - t2 = d + 2 * 12; - t3 = d + 4 * 12; - t4 = d + 6 * 12; - t5 = d + 8 * 12; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 12; + t3 = t1 + 4 * 12; + t4 = t1 + 6 * 12; + t5 = t1 + 8 * 12; { /* t2 = y ^ 0x2 */ @@ -30790,10 +31291,9 @@ static int sp_384_mont_sqrt_12(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -30809,31 +31309,22 @@ static int sp_384_mont_sqrt_12(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 12]; - sp_digit yd[2 * 12]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 12]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 12; - y = d + 2 * 12; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 12; sp_384_from_mp(x, 12, xm); err = sp_384_mod_mul_norm_12(x, x, p384_mod); @@ -30866,16 +31357,13223 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 32]; + /* Y ordinate of point. */ + sp_digit y[2 * 32]; + /* Z ordinate of point. */ + sp_digit z[2 * 32]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[16 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #64\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #60\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #128\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #60\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #64\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #124\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #128\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u; + sp_digit ca; + sp_digit cb; + + ca = sp_1024_add_16(a1, a, &a[16]); + cb = sp_1024_add_16(b1, b, &b[16]); + u = ca & cb; + sp_1024_mul_16(z1, a1, b1); + sp_1024_mul_16(z2, &a[16], &b[16]); + sp_1024_mul_16(z0, a, b); + sp_1024_mask_16(r + 32, a1, 0 - cb); + sp_1024_mask_16(b1, b1, 0 - ca); + u += sp_1024_add_16(r + 32, r + 32, b1); + u += sp_1024_sub_in_place_32(z1, z2); + u += sp_1024_sub_in_place_32(z1, z0); + u += sp_1024_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + (void)sp_1024_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_1024_add_16(a1, a, &a[16]); + sp_1024_sqr_16(z1, a1); + sp_1024_sqr_16(z2, &a[16]); + sp_1024_sqr_16(z0, a); + sp_1024_mask_16(r + 32, a1, 0 - u); + u += sp_1024_add_16(r + 32, r + 32, r + 32); + u += sp_1024_sub_in_place_32(z1, z2); + u += sp_1024_sub_in_place_32(z1, z0); + u += sp_1024_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + (void)sp_1024_add_32(r + 32, r + 32, z2); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[32 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #128\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #128\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* !WOLFSSL_SP_SMALL */ +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[32] = { + 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823, + 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8, + 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4, + 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27, + 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198, + 0x0a563fda,0x997abb1f +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[32] = { + 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc, + 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57, + 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b, + 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8, + 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67, + 0xf5a9c025,0x668544e0 +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x7c8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[32] = { + 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08, + 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a, + 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd, + 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9, + 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466, + 0xc2958ff6,0x265eaec7 +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5, + 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339, + 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7, + 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0, + 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005, + 0x332c29ad,0x53fc09ee, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a, + 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80, + 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c, + 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4, + 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053, + 0x3f6009f1,0x0a824906, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #128\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #128\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_1024_cmp_32(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #124\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + sp_digit hi = t1[32 + i] - (t1[32 + i] == div); + r1 = div_1024_word_32(hi, t1[32 + i - 1], div); + + sp_1024_mul_d_32(t2, d, r1); + t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_1024_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2); + sp_1024_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_1024_cmp_32(t1, d) >= 0; + sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_1024_div_32(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + sp_1024_mul_32(r, a, p1024_norm_mod); + return sp_1024_mod_32(r, r, m); +} + + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_32(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 32, pm->x); + sp_1024_from_mp(p->y, 32, pm->y); + sp_1024_from_mp(p->z, 32, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #124\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+31] += m[31] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[31] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[31] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "ldr r6, [%[m]]\n\t" + "neg %[ca], %[ca]\n\t" + "sub r6, r7\n\t" + "sbc r6, r6\n\t" + "orr %[ca], r6\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_1024_cond_sub_32(a - 32, a, m, ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_32(r, a, b); + sp_1024_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_32(r, a); + sp_1024_mont_reduce_32(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 32]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 32); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_1024_norm_32(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + int32_t n; + + sp_1024_mont_inv_32(t1, p->z, t + 2*32); + + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 32, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_32(r->x, p1024_mod); + sp_1024_cond_sub_32(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 32, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_32(r->y, p1024_mod); + sp_1024_cond_sub_32(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "add r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "mov %[b], #0\n\t" + "ldr r7, [%[m], #124]\n\t" + "adc %[b], %[b]\n\t" + "sub r7, r5\n\t" + "neg %[b], %[b]\n\t" + "sbc r7, r7\n\t" + "orr %[b], r7\n\t" + "ldr r4, [%[r], #0]\n\t" + "ldr r5, [%[r], #4]\n\t" + "ldr r6, [%[m], #0]\n\t" + "ldr r7, [%[m], #4]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[r], #8]\n\t" + "ldr r5, [%[r], #12]\n\t" + "ldr r6, [%[m], #8]\n\t" + "ldr r7, [%[m], #12]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[r], #16]\n\t" + "ldr r5, [%[r], #20]\n\t" + "ldr r6, [%[m], #16]\n\t" + "ldr r7, [%[m], #20]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[r], #24]\n\t" + "ldr r5, [%[r], #28]\n\t" + "ldr r6, [%[m], #24]\n\t" + "ldr r7, [%[m], #28]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[r], #32]\n\t" + "ldr r5, [%[r], #36]\n\t" + "ldr r6, [%[m], #32]\n\t" + "ldr r7, [%[m], #36]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[r], #40]\n\t" + "ldr r5, [%[r], #44]\n\t" + "ldr r6, [%[m], #40]\n\t" + "ldr r7, [%[m], #44]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[r], #48]\n\t" + "ldr r5, [%[r], #52]\n\t" + "ldr r6, [%[m], #48]\n\t" + "ldr r7, [%[m], #52]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[r], #56]\n\t" + "ldr r5, [%[r], #60]\n\t" + "ldr r6, [%[m], #56]\n\t" + "ldr r7, [%[m], #60]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[r], #64]\n\t" + "ldr r5, [%[r], #68]\n\t" + "ldr r6, [%[m], #64]\n\t" + "ldr r7, [%[m], #68]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[r], #72]\n\t" + "ldr r5, [%[r], #76]\n\t" + "ldr r6, [%[m], #72]\n\t" + "ldr r7, [%[m], #76]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[r], #80]\n\t" + "ldr r5, [%[r], #84]\n\t" + "ldr r6, [%[m], #80]\n\t" + "ldr r7, [%[m], #84]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[r], #88]\n\t" + "ldr r5, [%[r], #92]\n\t" + "ldr r6, [%[m], #88]\n\t" + "ldr r7, [%[m], #92]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[r], #96]\n\t" + "ldr r5, [%[r], #100]\n\t" + "ldr r6, [%[m], #96]\n\t" + "ldr r7, [%[m], #100]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[r], #104]\n\t" + "ldr r5, [%[r], #108]\n\t" + "ldr r6, [%[m], #104]\n\t" + "ldr r7, [%[m], #108]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[r], #112]\n\t" + "ldr r5, [%[r], #116]\n\t" + "ldr r6, [%[m], #112]\n\t" + "ldr r7, [%[m], #116]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[r], #120]\n\t" + "ldr r5, [%[r], #124]\n\t" + "ldr r6, [%[m], #120]\n\t" + "ldr r7, [%[m], #124]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "add r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "mov r3, #0\n\t" + "ldr r4, [%[m], #124]\n\t" + "adc r3, r3\n\t" + "sub r4, r7\n\t" + "neg r3, r3\n\t" + "sbc r4, r4\n\t" + "orr r3, r4\n\t" + "ldr r4, [%[r], #0]\n\t" + "ldr r5, [%[r], #4]\n\t" + "ldr r6, [%[m], #0]\n\t" + "ldr r7, [%[m], #4]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[r], #8]\n\t" + "ldr r5, [%[r], #12]\n\t" + "ldr r6, [%[m], #8]\n\t" + "ldr r7, [%[m], #12]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[r], #16]\n\t" + "ldr r5, [%[r], #20]\n\t" + "ldr r6, [%[m], #16]\n\t" + "ldr r7, [%[m], #20]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[r], #24]\n\t" + "ldr r5, [%[r], #28]\n\t" + "ldr r6, [%[m], #24]\n\t" + "ldr r7, [%[m], #28]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[r], #32]\n\t" + "ldr r5, [%[r], #36]\n\t" + "ldr r6, [%[m], #32]\n\t" + "ldr r7, [%[m], #36]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[r], #40]\n\t" + "ldr r5, [%[r], #44]\n\t" + "ldr r6, [%[m], #40]\n\t" + "ldr r7, [%[m], #44]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[r], #48]\n\t" + "ldr r5, [%[r], #52]\n\t" + "ldr r6, [%[m], #48]\n\t" + "ldr r7, [%[m], #52]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[r], #56]\n\t" + "ldr r5, [%[r], #60]\n\t" + "ldr r6, [%[m], #56]\n\t" + "ldr r7, [%[m], #60]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[r], #64]\n\t" + "ldr r5, [%[r], #68]\n\t" + "ldr r6, [%[m], #64]\n\t" + "ldr r7, [%[m], #68]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[r], #72]\n\t" + "ldr r5, [%[r], #76]\n\t" + "ldr r6, [%[m], #72]\n\t" + "ldr r7, [%[m], #76]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[r], #80]\n\t" + "ldr r5, [%[r], #84]\n\t" + "ldr r6, [%[m], #80]\n\t" + "ldr r7, [%[m], #84]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[r], #88]\n\t" + "ldr r5, [%[r], #92]\n\t" + "ldr r6, [%[m], #88]\n\t" + "ldr r7, [%[m], #92]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[r], #96]\n\t" + "ldr r5, [%[r], #100]\n\t" + "ldr r6, [%[m], #96]\n\t" + "ldr r7, [%[m], #100]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[r], #104]\n\t" + "ldr r5, [%[r], #108]\n\t" + "ldr r6, [%[m], #104]\n\t" + "ldr r7, [%[m], #108]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[r], #112]\n\t" + "ldr r5, [%[r], #116]\n\t" + "ldr r6, [%[m], #112]\n\t" + "ldr r7, [%[m], #116]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[r], #120]\n\t" + "ldr r5, [%[r], #124]\n\t" + "ldr r6, [%[m], #120]\n\t" + "ldr r7, [%[m], #124]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r3" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "add r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "mov r3, #0\n\t" + "ldr r4, [%[m], #124]\n\t" + "adc r3, r3\n\t" + "sub r4, r7\n\t" + "neg r3, r3\n\t" + "sbc r4, r4\n\t" + "orr r3, r4\n\t" + "ldr r4, [%[r], #0]\n\t" + "ldr r5, [%[r], #4]\n\t" + "ldr r6, [%[m], #0]\n\t" + "ldr r7, [%[m], #4]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[r], #8]\n\t" + "ldr r5, [%[r], #12]\n\t" + "ldr r6, [%[m], #8]\n\t" + "ldr r7, [%[m], #12]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[r], #16]\n\t" + "ldr r5, [%[r], #20]\n\t" + "ldr r6, [%[m], #16]\n\t" + "ldr r7, [%[m], #20]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[r], #24]\n\t" + "ldr r5, [%[r], #28]\n\t" + "ldr r6, [%[m], #24]\n\t" + "ldr r7, [%[m], #28]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[r], #32]\n\t" + "ldr r5, [%[r], #36]\n\t" + "ldr r6, [%[m], #32]\n\t" + "ldr r7, [%[m], #36]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[r], #40]\n\t" + "ldr r5, [%[r], #44]\n\t" + "ldr r6, [%[m], #40]\n\t" + "ldr r7, [%[m], #44]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[r], #48]\n\t" + "ldr r5, [%[r], #52]\n\t" + "ldr r6, [%[m], #48]\n\t" + "ldr r7, [%[m], #52]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[r], #56]\n\t" + "ldr r5, [%[r], #60]\n\t" + "ldr r6, [%[m], #56]\n\t" + "ldr r7, [%[m], #60]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[r], #64]\n\t" + "ldr r5, [%[r], #68]\n\t" + "ldr r6, [%[m], #64]\n\t" + "ldr r7, [%[m], #68]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[r], #72]\n\t" + "ldr r5, [%[r], #76]\n\t" + "ldr r6, [%[m], #72]\n\t" + "ldr r7, [%[m], #76]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[r], #80]\n\t" + "ldr r5, [%[r], #84]\n\t" + "ldr r6, [%[m], #80]\n\t" + "ldr r7, [%[m], #84]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[r], #88]\n\t" + "ldr r5, [%[r], #92]\n\t" + "ldr r6, [%[m], #88]\n\t" + "ldr r7, [%[m], #92]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[r], #96]\n\t" + "ldr r5, [%[r], #100]\n\t" + "ldr r6, [%[m], #96]\n\t" + "ldr r7, [%[m], #100]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[r], #104]\n\t" + "ldr r5, [%[r], #108]\n\t" + "ldr r6, [%[m], #104]\n\t" + "ldr r7, [%[m], #108]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[r], #112]\n\t" + "ldr r5, [%[r], #116]\n\t" + "ldr r6, [%[m], #112]\n\t" + "ldr r7, [%[m], #116]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[r], #120]\n\t" + "ldr r5, [%[r], #124]\n\t" + "ldr r6, [%[m], #120]\n\t" + "ldr r7, [%[m], #124]\n\t" + "and r6, r3\n\t" + "and r7, r3\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[r], #0]\n\t" + "ldr r7, [%[r], #4]\n\t" + "add r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[r], #8]\n\t" + "ldr r7, [%[r], #12]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[r], #16]\n\t" + "ldr r7, [%[r], #20]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #16]\n\t" + "str r7, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[r], #24]\n\t" + "ldr r7, [%[r], #28]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[r], #32]\n\t" + "ldr r7, [%[r], #36]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #32]\n\t" + "str r7, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[r], #40]\n\t" + "ldr r7, [%[r], #44]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[r], #48]\n\t" + "ldr r7, [%[r], #52]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #48]\n\t" + "str r7, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[r], #56]\n\t" + "ldr r7, [%[r], #60]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[r], #64]\n\t" + "ldr r7, [%[r], #68]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #64]\n\t" + "str r7, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[r], #72]\n\t" + "ldr r7, [%[r], #76]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[r], #80]\n\t" + "ldr r7, [%[r], #84]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #80]\n\t" + "str r7, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[r], #88]\n\t" + "ldr r7, [%[r], #92]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[r], #96]\n\t" + "ldr r7, [%[r], #100]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #96]\n\t" + "str r7, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[r], #104]\n\t" + "ldr r7, [%[r], #108]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[r], #112]\n\t" + "ldr r7, [%[r], #116]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #112]\n\t" + "str r7, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[r], #120]\n\t" + "ldr r7, [%[r], #124]\n\t" + "adc r6, r4\n\t" + "adc r7, r5\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "mov r3, #0\n\t" + "ldr r5, [%[m], #124]\n\t" + "adc r3, r3\n\t" + "sub r5, r7\n\t" + "neg r3, r3\n\t" + "sbc r5, r5\n\t" + "orr r3, r5\n\t" + "ldr r6, [%[r], #0]\n\t" + "ldr r7, [%[r], #4]\n\t" + "ldr r4, [%[m], #0]\n\t" + "ldr r5, [%[m], #4]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sub r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "ldr r6, [%[r], #8]\n\t" + "ldr r7, [%[r], #12]\n\t" + "ldr r4, [%[m], #8]\n\t" + "ldr r5, [%[m], #12]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r6, [%[r], #16]\n\t" + "ldr r7, [%[r], #20]\n\t" + "ldr r4, [%[m], #16]\n\t" + "ldr r5, [%[m], #20]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #16]\n\t" + "str r7, [%[r], #20]\n\t" + "ldr r6, [%[r], #24]\n\t" + "ldr r7, [%[r], #28]\n\t" + "ldr r4, [%[m], #24]\n\t" + "ldr r5, [%[m], #28]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r6, [%[r], #32]\n\t" + "ldr r7, [%[r], #36]\n\t" + "ldr r4, [%[m], #32]\n\t" + "ldr r5, [%[m], #36]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #32]\n\t" + "str r7, [%[r], #36]\n\t" + "ldr r6, [%[r], #40]\n\t" + "ldr r7, [%[r], #44]\n\t" + "ldr r4, [%[m], #40]\n\t" + "ldr r5, [%[m], #44]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r6, [%[r], #48]\n\t" + "ldr r7, [%[r], #52]\n\t" + "ldr r4, [%[m], #48]\n\t" + "ldr r5, [%[m], #52]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #48]\n\t" + "str r7, [%[r], #52]\n\t" + "ldr r6, [%[r], #56]\n\t" + "ldr r7, [%[r], #60]\n\t" + "ldr r4, [%[m], #56]\n\t" + "ldr r5, [%[m], #60]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r6, [%[r], #64]\n\t" + "ldr r7, [%[r], #68]\n\t" + "ldr r4, [%[m], #64]\n\t" + "ldr r5, [%[m], #68]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #64]\n\t" + "str r7, [%[r], #68]\n\t" + "ldr r6, [%[r], #72]\n\t" + "ldr r7, [%[r], #76]\n\t" + "ldr r4, [%[m], #72]\n\t" + "ldr r5, [%[m], #76]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r6, [%[r], #80]\n\t" + "ldr r7, [%[r], #84]\n\t" + "ldr r4, [%[m], #80]\n\t" + "ldr r5, [%[m], #84]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #80]\n\t" + "str r7, [%[r], #84]\n\t" + "ldr r6, [%[r], #88]\n\t" + "ldr r7, [%[r], #92]\n\t" + "ldr r4, [%[m], #88]\n\t" + "ldr r5, [%[m], #92]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r6, [%[r], #96]\n\t" + "ldr r7, [%[r], #100]\n\t" + "ldr r4, [%[m], #96]\n\t" + "ldr r5, [%[m], #100]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #96]\n\t" + "str r7, [%[r], #100]\n\t" + "ldr r6, [%[r], #104]\n\t" + "ldr r7, [%[r], #108]\n\t" + "ldr r4, [%[m], #104]\n\t" + "ldr r5, [%[m], #108]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r6, [%[r], #112]\n\t" + "ldr r7, [%[r], #116]\n\t" + "ldr r4, [%[m], #112]\n\t" + "ldr r5, [%[m], #116]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #112]\n\t" + "str r7, [%[r], #116]\n\t" + "ldr r6, [%[r], #120]\n\t" + "ldr r7, [%[r], #124]\n\t" + "ldr r4, [%[m], #120]\n\t" + "ldr r5, [%[m], #124]\n\t" + "and r4, r3\n\t" + "and r5, r3\n\t" + "sbc r6, r4\n\t" + "sbc r7, r5\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r3" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "sbc %[b], %[b]\n\t" + "ldr r4, [%[r], #0]\n\t" + "ldr r5, [%[r], #4]\n\t" + "ldr r6, [%[m], #0]\n\t" + "ldr r7, [%[m], #4]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "add r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[r], #8]\n\t" + "ldr r5, [%[r], #12]\n\t" + "ldr r6, [%[m], #8]\n\t" + "ldr r7, [%[m], #12]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[r], #16]\n\t" + "ldr r5, [%[r], #20]\n\t" + "ldr r6, [%[m], #16]\n\t" + "ldr r7, [%[m], #20]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[r], #24]\n\t" + "ldr r5, [%[r], #28]\n\t" + "ldr r6, [%[m], #24]\n\t" + "ldr r7, [%[m], #28]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[r], #32]\n\t" + "ldr r5, [%[r], #36]\n\t" + "ldr r6, [%[m], #32]\n\t" + "ldr r7, [%[m], #36]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[r], #40]\n\t" + "ldr r5, [%[r], #44]\n\t" + "ldr r6, [%[m], #40]\n\t" + "ldr r7, [%[m], #44]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[r], #48]\n\t" + "ldr r5, [%[r], #52]\n\t" + "ldr r6, [%[m], #48]\n\t" + "ldr r7, [%[m], #52]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[r], #56]\n\t" + "ldr r5, [%[r], #60]\n\t" + "ldr r6, [%[m], #56]\n\t" + "ldr r7, [%[m], #60]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[r], #64]\n\t" + "ldr r5, [%[r], #68]\n\t" + "ldr r6, [%[m], #64]\n\t" + "ldr r7, [%[m], #68]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[r], #72]\n\t" + "ldr r5, [%[r], #76]\n\t" + "ldr r6, [%[m], #72]\n\t" + "ldr r7, [%[m], #76]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[r], #80]\n\t" + "ldr r5, [%[r], #84]\n\t" + "ldr r6, [%[m], #80]\n\t" + "ldr r7, [%[m], #84]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[r], #88]\n\t" + "ldr r5, [%[r], #92]\n\t" + "ldr r6, [%[m], #88]\n\t" + "ldr r7, [%[m], #92]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[r], #96]\n\t" + "ldr r5, [%[r], #100]\n\t" + "ldr r6, [%[m], #96]\n\t" + "ldr r7, [%[m], #100]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[r], #104]\n\t" + "ldr r5, [%[r], #108]\n\t" + "ldr r6, [%[m], #104]\n\t" + "ldr r7, [%[m], #108]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[r], #112]\n\t" + "ldr r5, [%[r], #116]\n\t" + "ldr r6, [%[m], #112]\n\t" + "ldr r7, [%[m], #116]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[r], #120]\n\t" + "ldr r5, [%[r], #124]\n\t" + "ldr r6, [%[m], #120]\n\t" + "ldr r7, [%[m], #124]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "mov r6, #0\n\t" + "adc %[b], r6\n\t" + "ldr r4, [%[r], #0]\n\t" + "ldr r5, [%[r], #4]\n\t" + "ldr r6, [%[m], #0]\n\t" + "ldr r7, [%[m], #4]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "add r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[r], #8]\n\t" + "ldr r5, [%[r], #12]\n\t" + "ldr r6, [%[m], #8]\n\t" + "ldr r7, [%[m], #12]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[r], #16]\n\t" + "ldr r5, [%[r], #20]\n\t" + "ldr r6, [%[m], #16]\n\t" + "ldr r7, [%[m], #20]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[r], #24]\n\t" + "ldr r5, [%[r], #28]\n\t" + "ldr r6, [%[m], #24]\n\t" + "ldr r7, [%[m], #28]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[r], #32]\n\t" + "ldr r5, [%[r], #36]\n\t" + "ldr r6, [%[m], #32]\n\t" + "ldr r7, [%[m], #36]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[r], #40]\n\t" + "ldr r5, [%[r], #44]\n\t" + "ldr r6, [%[m], #40]\n\t" + "ldr r7, [%[m], #44]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[r], #48]\n\t" + "ldr r5, [%[r], #52]\n\t" + "ldr r6, [%[m], #48]\n\t" + "ldr r7, [%[m], #52]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[r], #56]\n\t" + "ldr r5, [%[r], #60]\n\t" + "ldr r6, [%[m], #56]\n\t" + "ldr r7, [%[m], #60]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[r], #64]\n\t" + "ldr r5, [%[r], #68]\n\t" + "ldr r6, [%[m], #64]\n\t" + "ldr r7, [%[m], #68]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[r], #72]\n\t" + "ldr r5, [%[r], #76]\n\t" + "ldr r6, [%[m], #72]\n\t" + "ldr r7, [%[m], #76]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[r], #80]\n\t" + "ldr r5, [%[r], #84]\n\t" + "ldr r6, [%[m], #80]\n\t" + "ldr r7, [%[m], #84]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[r], #88]\n\t" + "ldr r5, [%[r], #92]\n\t" + "ldr r6, [%[m], #88]\n\t" + "ldr r7, [%[m], #92]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[r], #96]\n\t" + "ldr r5, [%[r], #100]\n\t" + "ldr r6, [%[m], #96]\n\t" + "ldr r7, [%[m], #100]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[r], #104]\n\t" + "ldr r5, [%[r], #108]\n\t" + "ldr r6, [%[m], #104]\n\t" + "ldr r7, [%[m], #108]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[r], #112]\n\t" + "ldr r5, [%[r], #116]\n\t" + "ldr r6, [%[m], #112]\n\t" + "ldr r7, [%[m], #116]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[r], #120]\n\t" + "ldr r5, [%[r], #124]\n\t" + "ldr r6, [%[m], #120]\n\t" + "ldr r7, [%[m], #124]\n\t" + "and r6, %[b]\n\t" + "and r7, %[b]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7" + ); +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, #1\n\t" + "add r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "adc r5, r6\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +static void sp_1024_rshift1_32(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r2, [%[a]]\n\t" + "ldr r3, [%[a], #4]\n\t" + "lsr r2, r2, #1\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r2, [%[r], #0]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r3, [%[r], #4]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r4, [%[r], #8]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r2, [%[r], #12]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r3, [%[r], #16]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r4, [%[r], #20]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r2, [%[r], #24]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r3, [%[r], #28]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r4, [%[r], #32]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r2, [%[r], #36]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r3, [%[r], #40]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r4, [%[r], #44]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r2, [%[r], #48]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r3, [%[r], #52]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #64]\n\t" + "str r4, [%[r], #56]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #68]\n\t" + "str r2, [%[r], #60]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #72]\n\t" + "str r3, [%[r], #64]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #76]\n\t" + "str r4, [%[r], #68]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #80]\n\t" + "str r2, [%[r], #72]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #84]\n\t" + "str r3, [%[r], #76]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #88]\n\t" + "str r4, [%[r], #80]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #92]\n\t" + "str r2, [%[r], #84]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #96]\n\t" + "str r3, [%[r], #88]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #100]\n\t" + "str r4, [%[r], #92]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #104]\n\t" + "str r2, [%[r], #96]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #108]\n\t" + "str r3, [%[r], #100]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #112]\n\t" + "str r4, [%[r], #104]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #116]\n\t" + "str r2, [%[r], #108]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #120]\n\t" + "str r3, [%[r], #112]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #124]\n\t" + "str r4, [%[r], #116]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "str r2, [%[r], #120]\n\t" + "str r3, [%[r], #124]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1)); + sp_1024_rshift1_32(r, r); + r[31] |= o << 31; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_32_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_32_ctx; + +static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*32; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_32(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_32(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_32(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_32(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_32(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_32(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_32(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_32(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_32(y, y, t2, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) | + (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) | + (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) | + (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) | + (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_32_ctx { + int state; + sp_1024_proj_point_dbl_32_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_32_ctx; + +static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*32; + ctx->t3 = t + 4*32; + ctx->t4 = t + 6*32; + ctx->t5 = t + 8*32; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_32(ctx->t1, p1024_mod, q->y); + sp_1024_norm_32(ctx->t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_32_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_32(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_32(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_32(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_32(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_32(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_32(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* t3 = t + 4*32; + sp_digit* t4 = t + 6*32; + sp_digit* t5 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_32(t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_32(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_32(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_32(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_32(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(x, x, t5, p1024_mod); + sp_1024_mont_dbl_32(t1, y, p1024_mod); + sp_1024_mont_sub_32(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_32(y, y, x, p1024_mod); + sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(y, y, t5, p1024_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 1024 doubles. + * 268 adds. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[16 + 1]; + sp_digit tmp[2 * 32 * 5]; +#endif + sp_point_1024* rt = NULL; + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 16; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod); + (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod); + (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod); + t[1].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 30; + n = k[i+1] << 0; + c = 28; + y = (int)(n >> 28); + XMEMCPY(rt, &t[y], sizeof(sp_point_1024)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_add_32(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_1024_map_32(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 32 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*32; + sp_digit* b = t + 4*32; + sp_digit* t1 = t + 6*32; + sp_digit* t2 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_32(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_32(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(t2, b, p1024_mod); + sp_1024_mont_sub_32(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_32(y, b, x, p1024_mod); + sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(y, y, p1024_mod); + sp_1024_mont_sub_32(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_32(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(t2, b, p1024_mod); + sp_1024_mont_sub_32(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_32(y, b, x, p1024_mod); + sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(y, y, p1024_mod); + sp_1024_mont_sub_32(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_32(y, y, p1024_mod); +} + +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* tmp = t + 4 * 32; + + sp_1024_mont_inv_32(t1, a->z, tmp); + + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[32]; + sp_digit y[32]; +} sp_table_entry_1024; + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* t3 = t + 4*32; + sp_digit* t4 = t + 6*32; + sp_digit* t5 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_32(t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_32(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_32(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_32(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_32(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_32(t1, t3, p1024_mod); + sp_1024_mont_sub_32(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_32(t3, t3, x, p1024_mod); + sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(y, t3, t5, p1024_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 256 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_32(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_32(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<4; i++) { + sp_1024_proj_point_dbl_n_32(t, 256, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^256, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 32 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 255; + for (j=0; j<4; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 256; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=254; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<4; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 256; + } + + sp_1024_proj_point_dbl_32(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_32(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_32(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[32]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[32]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[16]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 32 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#else +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_32(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_32(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_32(t, 128, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 32 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_32(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_32(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_32(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[32]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[32]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 32 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(point, gm); + + err = sp_1024_ecc_mulmod_32(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 256 between points. + */ +static const sp_table_entry_1024 p1024_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0, + 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995, + 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867, + 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173, + 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc, + 0x1c49f80b,0x8dfff96a }, + { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88, + 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16, + 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e, + 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf, + 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329, + 0xde3c01f3,0x2aa1207b } }, + /* 2 */ + { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f, + 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab, + 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa, + 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9, + 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec, + 0xdf9398a4,0x40247985 }, + { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb, + 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861, + 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36, + 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd, + 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb, + 0xc8b79d80,0x1a6fd1e6 } }, + /* 3 */ + { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452, + 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e, + 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d, + 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37, + 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4, + 0x15614750,0x29b7d4dc }, + { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54, + 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7, + 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a, + 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903, + 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310, + 0x5382497e,0x5d092802 } }, + /* 4 */ + { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6, + 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd, + 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd, + 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521, + 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494, + 0x0f1fa7d7,0x2ab3bd47 }, + { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135, + 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2, + 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f, + 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c, + 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1, + 0x4c27d229,0x93a4b416 } }, + /* 5 */ + { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1, + 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519, + 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e, + 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30, + 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6, + 0x32ee7763,0x342ce0d7 }, + { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a, + 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858, + 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66, + 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433, + 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb, + 0xe156fd20,0x455f4af3 } }, + /* 6 */ + { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9, + 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee, + 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d, + 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8, + 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead, + 0x5c37c334,0x65713c29 }, + { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6, + 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424, + 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862, + 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1, + 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5, + 0x3bae3c38,0x6b0e996c } }, + /* 7 */ + { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269, + 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7, + 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da, + 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e, + 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342, + 0x678223f8,0x4022a205 }, + { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d, + 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6, + 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd, + 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21, + 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11, + 0x24a6a956,0x312179cb } }, + /* 8 */ + { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41, + 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7, + 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b, + 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5, + 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1, + 0x04ecf056,0x325d2796 }, + { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1, + 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153, + 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c, + 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9, + 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e, + 0xe32a79d3,0x19d48546 } }, + /* 9 */ + { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0, + 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea, + 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df, + 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634, + 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d, + 0xb4e453b0,0x1b3ace6c }, + { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35, + 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630, + 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824, + 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387, + 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64, + 0x192f0a14,0x538ec33e } }, + /* 10 */ + { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8, + 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699, + 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984, + 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32, + 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076, + 0xb6f8aa25,0x13cbee76 }, + { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23, + 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492, + 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e, + 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50, + 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c, + 0xe02e8967,0x4e0a1ada } }, + /* 11 */ + { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67, + 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198, + 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7, + 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d, + 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6, + 0x9f99c999,0x733e30d9 }, + { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7, + 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a, + 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a, + 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0, + 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492, + 0xb79a5c0c,0x56facb39 } }, + /* 12 */ + { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6, + 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c, + 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e, + 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb, + 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52, + 0xf18c2b91,0x57ea2b4b }, + { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a, + 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee, + 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069, + 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b, + 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927, + 0xea7935c9,0x60480b46 } }, + /* 13 */ + { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7, + 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117, + 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5, + 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0, + 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb, + 0x9a8f88cc,0x0774a0d3 }, + { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f, + 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61, + 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91, + 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df, + 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303, + 0x2432014b,0x08151954 } }, + /* 14 */ + { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28, + 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20, + 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1, + 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55, + 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7, + 0xf0860497,0x1fe09f94 }, + { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c, + 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a, + 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994, + 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa, + 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c, + 0xdb62526a,0x4de95786 } }, + /* 15 */ + { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96, + 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5, + 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5, + 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc, + 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e, + 0xe636980c,0x1c94418b }, + { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a, + 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4, + 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98, + 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474, + 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422, + 0xb55235ba,0x611bfbb2 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^256, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0, + 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995, + 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867, + 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173, + 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc, + 0x1c49f80b,0x8dfff96a }, + { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88, + 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16, + 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e, + 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf, + 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329, + 0xde3c01f3,0x2aa1207b } }, + /* 2 */ + { { 0x01900955,0xa95b6dae,0xceb4656d,0xa5dc9cc1,0xe72fe95b,0x50c78907, + 0xa040c334,0xa1ae5447,0x7952ea6e,0x91191370,0x6d097305,0x54ff7343, + 0xbda4d10f,0xa4db0074,0x91644070,0xfd5306f1,0x8b24522c,0x14b9fe73, + 0x7849f762,0x1468dad6,0xb0dcd2e4,0x87b29a18,0x5e1ad492,0xadd7f1a1, + 0xdbba2a1a,0x9ac63a81,0x81223379,0x01379c5b,0xb0e53bc8,0xf402b2f0, + 0x0bf13b61,0x8c3eb27f }, + { 0xe513696f,0x9a4ad3e1,0x18c81ffa,0x0350ba5c,0x3c033d13,0x1e2fc136, + 0x17a531bc,0x53da6e71,0x1aed610d,0x42ec6490,0xe99ff567,0xd33e8df7, + 0x3deed12a,0xe4aad73e,0x180f4deb,0xd983b465,0x502f30b4,0x99365269, + 0xa8918d7f,0x7e2799ab,0x700fc79a,0x0ffe84b6,0x40bfd8c2,0x7b4400d6, + 0x5d2641bd,0xc3a21d21,0xc32621cb,0x79839442,0xb1401e83,0xace6500b, + 0x251c4310,0x7bf4163e } }, + /* 3 */ + { { 0xe3fd589e,0x1c174f88,0xdf974a03,0xdb501790,0x3e70549f,0xd09623e3, + 0x15924f34,0x8d091eff,0xf9b65ac5,0xeef79cad,0x3f69c2cf,0xd2cc4262, + 0x52cd82bc,0x817d9032,0xa5f1dddd,0xacf4f4d9,0x5011b6bd,0xd0612635, + 0x2ed140c9,0x9f74490d,0x4db686d2,0x64092e8c,0x776b0fcc,0x225eef16, + 0xdf16aeb6,0x0e8c01e9,0x84bbd82a,0x62836741,0x8956e337,0x757574e2, + 0x705a7f07,0x9871edc6 }, + { 0x776535f7,0xbd0b76d5,0x2635b3b8,0x5214d602,0x9d216f64,0xc0c25ad9, + 0x5515bf75,0xfd4df3a7,0x5e9f1675,0x24a625bc,0x406873e7,0x3c35efb7, + 0xbb2e5c4a,0xef5c9a33,0x806b198a,0xa971b35e,0xa3c690ed,0x9f5c0ca5, + 0x8e1e2341,0xa8d5dd89,0x955ad9e4,0x4cecbcce,0x248d3416,0x2ecf4407, + 0x45c0af6e,0x1abb3811,0x1c780fff,0x3f4bee82,0xc272ed57,0xd14df768, + 0x371637ad,0x397ed10a } }, + /* 4 */ + { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f, + 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab, + 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa, + 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9, + 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec, + 0xdf9398a4,0x40247985 }, + { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb, + 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861, + 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36, + 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd, + 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb, + 0xc8b79d80,0x1a6fd1e6 } }, + /* 5 */ + { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452, + 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e, + 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d, + 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37, + 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4, + 0x15614750,0x29b7d4dc }, + { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54, + 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7, + 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a, + 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903, + 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310, + 0x5382497e,0x5d092802 } }, + /* 6 */ + { { 0xff2f780d,0x583a2b7e,0xd7d76b1d,0x34d26820,0x86f74aec,0xe3c32847, + 0x10823feb,0x0fd42212,0xfb5e7bf4,0x227e417e,0xa568f8cd,0x510d49b6, + 0x1781bbec,0x53bce7d6,0x2f3718b7,0x9cfe3f22,0xd9de6c1f,0x7f44e89f, + 0x3fac9b55,0xf1cc553f,0xe6f300bc,0x9d2d0846,0x9f0ae6b1,0x976c82a2, + 0x24b8bbe0,0xe63dbf5e,0x973a5aa7,0x4cac7f45,0x84dd33c7,0xc6eb6237, + 0x142fee5d,0x0a26e434 }, + { 0xacaa9a08,0x8081339f,0x5246ece1,0x40f31105,0x61393747,0x892c8170, + 0x242f02e1,0x8d8d4103,0x3b5de98a,0x482bfd20,0x5abbe952,0x89ef946b, + 0x37698249,0xb8d218b9,0x66617c7a,0xd5268e89,0x8b7d2b91,0x962e7551, + 0xfe8d67c3,0x2c5c7973,0x2b017c51,0x42e3150a,0xc1a29469,0x6f4e5ebc, + 0x531c7083,0xa39910ce,0xb77b9e50,0xaf4f6eb4,0xda120ad0,0x68cbb175, + 0xb92636ec,0x19497c61 } }, + /* 7 */ + { { 0x417659a8,0x6920b0c6,0x92cb28ff,0xc77ab9c7,0xb687797f,0x55b67180, + 0xe7759363,0x4caf58c1,0x5561b186,0x5155bdb6,0x780f4946,0x2e64e355, + 0x229a8b20,0xeb0ac9b7,0x2571bd60,0x88594d78,0xe3fa78f9,0x5dcc0939, + 0x2ac2d379,0x7b8b4830,0xb90f1444,0x505fbf60,0x3ce4b3c1,0xac610e81, + 0xd59b5c18,0x39a4f27a,0x7cea0222,0x5fa33973,0x8dff1c7b,0xe578730b, + 0x517bf7a6,0x96b91b8b }, + { 0x9aac087c,0xc1a991f4,0x6cfdb28d,0xce62f74e,0x5f7600d6,0x08d6ff9a, + 0xf917f9c9,0xd781cd04,0x3de52dbf,0x7796f5f6,0x2ed72180,0xe7db64e0, + 0x6fa4137d,0x0f0876f6,0x3ca1f716,0x3271ee64,0x7c4ab8a3,0xcb9b2058, + 0x39481047,0xcba17107,0x598c5c37,0xdf9a190d,0x6f20e125,0x0cb6e72a, + 0xf4f2902d,0xa3142204,0x7ce2dcfb,0x42d28cb9,0xa3d3c351,0xdf261b8a, + 0xcffc249d,0x73f3d315 } }, + /* 8 */ + { { 0xe6fd3673,0x5d86855b,0x9d214b7b,0x309b70af,0xdcc46cd3,0x8d332f90, + 0x595510de,0xe553c015,0x38c1251c,0x5746a096,0x85cc1bc9,0xcd7cea5b, + 0x002eba8f,0x4ffa1468,0x22fcd77c,0x10a3cb70,0xc4ea05e3,0xb6999dfb, + 0x4efa756e,0x3375a0d0,0xdced5fd8,0x4d90279e,0x251fd56e,0x48192403, + 0x82a4c5f1,0xe87633a4,0x1b34105b,0x3170d130,0x7247e578,0x93998b0f, + 0x436ba1fa,0x88934f64 }, + { 0x4713eabc,0xf09f43b0,0xaccdc517,0x4ca7dd91,0xef13ca7c,0x27daa63b, + 0x2588184b,0x8b2e5a7a,0xd95dc269,0x0a8cb612,0xe1f2f14c,0x346975a2, + 0xe172935c,0x1f29b8ed,0xd40bc1e3,0xc3cbfd6e,0x132623da,0xd3f46b3f, + 0xfb0b7681,0xc115be6d,0x56da4344,0x5e31c345,0xa8e43d98,0xa7c63f18, + 0x4bddb4ea,0x55cb2083,0x4a54f58c,0xb16a0c38,0x46fd69d9,0x74eacca2, + 0x153548e1,0x0d1898bb } }, + /* 9 */ + { { 0xe35ef043,0x4ea73461,0x3496b564,0x107b67d9,0xd0f83a3c,0xd62c173b, + 0x51d29c35,0xfad4b038,0x71b1c1a4,0x3f42882a,0x54b43b9e,0x5d2bcf66, + 0x2abdf543,0xc77b15aa,0xdabe3dc1,0x5cb38a80,0xa481673b,0x15fda0ae, + 0xe7b90ebe,0x86996b4d,0x2bc8f3d8,0x84f87e25,0x37c4e424,0xaded03d6, + 0xd7a7afd8,0xe5ede666,0xa1ccb93a,0x80dd95a2,0x46fba391,0xa55cfd25, + 0x46f82e60,0x2bdab1dc }, + { 0xfa6fed61,0x7a4de22b,0xcc8dd94e,0xca458aa5,0x071222f5,0x3e372df1, + 0xe5aff377,0x06a4b44f,0x4a738e6d,0xbc2d0ba7,0x5f31f136,0x1a470e1d, + 0xe102a911,0x77ff933a,0x310c7885,0x8b380a50,0x783fc5ac,0x9f3c0228, + 0x44725d06,0xec668925,0x5ac84221,0x878f0e16,0xcfda6e8a,0x9a3af1af, + 0x78cd2aba,0x0183ed37,0x826d0eae,0x32cdbd60,0xcbee6415,0xb3234661, + 0xb9c10120,0x353eb892 } }, + /* 10 */ + { { 0x10b5521e,0xc8fdcad6,0x52e702f0,0x1a11b440,0x8ffda49c,0x6302680d, + 0xcbf36bad,0xcdb9654a,0x4c10a2d7,0x7b58ce11,0xe630e7e0,0x1e5d1f7d, + 0x6760a813,0x8cbe3d7d,0x6480d77f,0xeb35866b,0x7f036219,0x58728cf3, + 0x42a8a757,0xdd5865ed,0x906a2870,0x283f1f1d,0xa51f906b,0x79e23fa4, + 0x543b20a8,0xf2ac6e83,0xb81e7754,0x4f0b6379,0x840016ee,0x57fbc0d4, + 0xe621b67d,0x8da20771 }, + { 0xecce65ec,0x3c855004,0xb748185e,0x76d10d1f,0x78797ad2,0x64be7bca, + 0x77e54aad,0x43444db0,0xbe0df0ff,0x17b6b0c9,0x055086a4,0x8fc4256c, + 0xfd74d5a3,0xf952c43b,0x01c4edb8,0x501e005a,0x4a57e328,0xd5172dfc, + 0x535d6ee3,0xdb40ce4e,0x0c650918,0xbaef1e5c,0x857561fc,0xe85145e7, + 0x34a224c6,0xe468536a,0x0ec0e0a2,0x69a8e227,0x242b03fc,0xb3f52247, + 0xc3bebd5f,0x862f55e2 } }, + /* 11 */ + { { 0x226049fe,0x2d6a390f,0xdcbbc9fb,0xcc92a578,0x97634fb7,0xa52feca4, + 0x3dea5893,0x2b340cb6,0x2a49e916,0xa39f338a,0x949e41f3,0x26b2df3d, + 0x065a7e40,0xc71c7cdb,0x468281a2,0x4a9b84a0,0x731eeeca,0x63eeb503, + 0x76cbb725,0xe6d09134,0xb94a678c,0x0cf979a9,0x808fd9f1,0xb44d8c3b, + 0xe0afc5b9,0xe60da613,0x3ea5be69,0x52dce7de,0xdc1ee74f,0x3a5d6864, + 0x3bc80790,0x71ab2891 }, + { 0x3b5b60ad,0xcf618fc4,0x4a0c3184,0x0afb5e30,0xbc403302,0xd22381cc, + 0xdb1c0c66,0x33cf8953,0xa6112a8d,0x9c994e4d,0xd1967a86,0xd7aae2c3, + 0x5b7acd29,0xc28d5493,0x6c9a57fb,0x8075bd13,0x9c8427f9,0xc9c0373e, + 0x193225f5,0x2cbca18d,0x442c018c,0x73777d13,0xfbb3a727,0xebe5ed47, + 0x1962dc18,0x70437d49,0x2dc08806,0xf39c1e09,0x15fff35c,0x03e9c6f7, + 0x5e360a65,0x8d087bb6 } }, + /* 12 */ + { { 0x3fdc1844,0xbe212302,0x105eac56,0x6eca27ef,0xf168a348,0x2183a606, + 0xe1d7a4cb,0x295f807d,0x7ef5d43e,0x7246a632,0xc77025c7,0xae143205, + 0xf3484e3e,0x4bdfc7ca,0xdf52c075,0xec939895,0xd7a9cac0,0x82e655f6, + 0x8baeddb0,0x985dfe20,0x527de731,0x79c817e4,0x313de1ea,0x30ce0fbc, + 0xcc4f6cbb,0x9df95b89,0xf5bb20cd,0xf2aedf1e,0x1a8cfb01,0xfc1e0a89, + 0x63edb7ec,0x225ed34a }, + { 0xbabb1a85,0x3e13154d,0x1e6a565a,0xd3d8dae7,0xab4b100f,0xd3217d56, + 0xebc78e1a,0xd44d934e,0x48e73d37,0x0215321b,0x201e43cb,0xbbc90bfa, + 0x27500905,0x3c23f1d0,0xc86691a1,0x2a2e5000,0x6065841c,0x08b2bad2, + 0x30026b60,0x15d41caf,0x5276ce61,0x1712c2f4,0x15932ffb,0x01c4c3e7, + 0x6a74caf2,0x7894e13d,0x0c0537a4,0x02d6f5df,0xc2b1c97e,0xa8fb7602, + 0xd0887c7b,0x612b60e5 } }, + /* 13 */ + { { 0xba245d6b,0xefd495cf,0xa2ce3ff6,0x5cf0cbb7,0xdff5feee,0x24da2ac0, + 0xcf28c6a3,0x90c914f8,0x4308a56b,0x72fdb50d,0x13d72034,0x03dbf779, + 0x822ac9e9,0xcfa5ec91,0x3aea3e81,0x0dde73c8,0x66289139,0x545ba962, + 0xca6acbd3,0xa52f648b,0x98a0683a,0xff6f276e,0xa378ed52,0x2536d3ac, + 0x885ac1d9,0x353c2c54,0x00bc84a7,0xcaff52da,0x37684167,0x3971f81c, + 0xd2d7986e,0x0f7334e1 }, + { 0x6596067e,0xafbb5c83,0x38c19806,0x33e54e19,0x39cb0dcc,0x8285d967, + 0x424035f9,0x2b53f43d,0xdfef9095,0x38c531f8,0xdb0f571a,0x90fbe8e4, + 0xa39ca787,0x9a0c1ed2,0x606f2620,0x2fecc1d6,0x72b7cb4a,0x9dc890b1, + 0xccbb7868,0xc33ca6fb,0xfe73ee49,0xd1b11082,0xfcb66c48,0x590b7d17, + 0x86e14573,0x9356b0a6,0x053ead85,0x75d682c4,0xc54d30fb,0xb2ae55fa, + 0xf8aee949,0x67636a72 } }, + /* 14 */ + { { 0xb91d6bea,0x638063bc,0x923ecb96,0xae263a2e,0xc627aca6,0x9d7b0992, + 0x77af9e7e,0xc6ed001a,0x24aafebb,0x9214accf,0x78055a90,0xa3564b96, + 0xe027499d,0x00999b1c,0xe46a06a5,0xe413a4e1,0x2e51efe7,0xa05d13f6, + 0x9ba843be,0x35e87d34,0x3183159e,0x0a633825,0x54601923,0x6023e8ba, + 0xb7fd1cf2,0x9b107721,0xfdf2fd53,0x46b5542b,0x1c18af38,0xb314f4f8, + 0x60ac8965,0x086f9876 }, + { 0x8cbb9850,0x76701954,0xa20d2c8c,0x6210b730,0x5335670c,0x4084d057, + 0x0324baea,0x3ecdc595,0xc76ee9b4,0x607fc5f2,0x440ffa64,0xf393d00f, + 0x2dc1463c,0xe0111796,0x9c7725e7,0xf00b8251,0x5bd1d186,0x35e60736, + 0x2cf72aac,0xf3d8554c,0xefa3497d,0xb4dd0fde,0xf646ad11,0xd712268c, + 0x9f7b8ead,0x07c20afb,0xfc06dfe5,0x630969d4,0x7245549a,0x76b7df1c, + 0xe61ae810,0x681f9403 } }, + /* 15 */ + { { 0xc9a0623b,0x7cad5163,0x67fab8d4,0xdbf82957,0x81af7c7c,0x2ccab0ec, + 0xe966d5c2,0x469e38c8,0xf0d4e41c,0x34430d52,0xa52b359c,0x426075a2, + 0x33bd0127,0x242dd3e3,0x9fed2341,0xcda3f635,0xd7d52ffa,0x4df33730, + 0x7640c3ef,0x5fff56f0,0x1bbde57c,0x4783c21c,0xeb8bb336,0xd8784a2a, + 0xead08405,0x1ec7c533,0xf9b62bd4,0x4b7f1423,0x7075d4af,0x5543145c, + 0xba60590a,0x0c9de94a }, + { 0x95d5682b,0x8ed72735,0x2ec276ed,0x711c4283,0x8b36a0d2,0xd1f4aed5, + 0x8498a88f,0x62ab40c4,0x4480f451,0x58c8fc62,0xb79cffe2,0x8bc8ca4b, + 0x701a359d,0x90ab583c,0x3fd5d15d,0xaee31a73,0xc912333c,0x02a5597b, + 0xb6c3e3c2,0x1019cae4,0x29938088,0xe513042c,0xf47c8199,0x0e00283d, + 0xf2a00e92,0x90d68e58,0xa775ae3b,0x69e2df41,0x871c30b2,0xb8d2eca5, + 0xbb1de396,0x733dca0e } }, + /* 16 */ + { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6, + 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd, + 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd, + 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521, + 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494, + 0x0f1fa7d7,0x2ab3bd47 }, + { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135, + 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2, + 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f, + 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c, + 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1, + 0x4c27d229,0x93a4b416 } }, + /* 17 */ + { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1, + 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519, + 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e, + 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30, + 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6, + 0x32ee7763,0x342ce0d7 }, + { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a, + 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858, + 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66, + 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433, + 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb, + 0xe156fd20,0x455f4af3 } }, + /* 18 */ + { { 0x754ec21c,0xc057f262,0xe3a1ba38,0x3eacd4c9,0x116c1fe9,0x3a0210d1, + 0xeacc8ab6,0xe4ea4e94,0xea6f32ca,0x31c00c9a,0x86b975ce,0x5cb6239d, + 0xa14ea1e9,0x654d5d8c,0x5067fc8b,0x230d31f4,0x6355fecb,0x48bb90cb, + 0xdc172e8e,0x78f81ece,0xcb006737,0x288380a8,0xe162d012,0x19b02e01, + 0xc5af145c,0x0e087a06,0xb72dc354,0xf04dc8b7,0x8de3c066,0xf70ef214, + 0x13009fb7,0x4f148243 }, + { 0x6e2055e2,0x5e004fce,0x86c32067,0x89e247ea,0x5f9daaa2,0x4ebcbd95, + 0xceb7f63b,0xd15f212f,0x863784a0,0x5ecc5c1f,0x75760251,0x53b3800b, + 0x8a6a2954,0xeb9301c3,0xa13cdd19,0x0f16ba18,0x887c2d24,0x8313d251, + 0x9a9413f6,0xf9923585,0xfe3fd7c5,0x423405e6,0x16e0ee05,0x678aeb34, + 0x3fadaab0,0x1f3be7bb,0x82884471,0x7901fa2c,0x4d662ff6,0xc950db30, + 0x3c01170b,0x74d5d2d4 } }, + /* 19 */ + { { 0x2b5bfe11,0xa3002dc0,0x52d321e7,0x0733410d,0x9679ba89,0x15920f65, + 0x685b236e,0x0e248c14,0x346f6040,0x8cfab594,0x40c717f0,0x9f57afb7, + 0x66044576,0x0dbab28c,0x9cdc3247,0x0fa09968,0xc230ed05,0x41e02ae2, + 0xe45bef74,0x0d961554,0xce4d7b6f,0x9688a982,0x5e62d22e,0xfadefac7, + 0xbd2cba28,0xaf1512a6,0xbe7c749f,0x78868e62,0xae9f5a6b,0x88048d81, + 0xc5857a29,0x6b1a5442 }, + { 0x43242066,0x9f5ab9ad,0x2ccca2ae,0x0afef1b5,0x988edc4e,0xb1b43ec7, + 0x0341b0d5,0x0d0c00f1,0xb50aab37,0x4d68b8f7,0xf3a64a99,0x9a8e4e6f, + 0x7f1a684e,0x198338fb,0x351a0f5c,0x8bc0e748,0xdac44515,0x2cacf2cd, + 0x5e9ff76b,0xc14d3999,0x16393055,0x54a01b3f,0x888d8376,0x6ac3eea5, + 0x723277b1,0xb84d9a9a,0xe11dbbbf,0x99132691,0xabb67178,0x597717ae, + 0x8bb14ac8,0x4c213526 } }, + /* 20 */ + { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9, + 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee, + 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d, + 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8, + 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead, + 0x5c37c334,0x65713c29 }, + { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6, + 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424, + 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862, + 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1, + 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5, + 0x3bae3c38,0x6b0e996c } }, + /* 21 */ + { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269, + 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7, + 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da, + 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e, + 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342, + 0x678223f8,0x4022a205 }, + { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d, + 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6, + 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd, + 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21, + 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11, + 0x24a6a956,0x312179cb } }, + /* 22 */ + { { 0x07615ac2,0xa94cc3ca,0x121ad581,0x85865e64,0xa7986b79,0xae47616f, + 0x9d5e0f1d,0x395a40eb,0x3d9457ea,0xa9143264,0xfa2865d9,0x8de6d6a3, + 0x1014ae8c,0x0771db96,0x976a87cb,0x77a7cce6,0x143a0f60,0xa7de42e1, + 0xd993d934,0xe203cc09,0x98ec4c3d,0x92018693,0x3a25df4b,0xd77546d8, + 0x62b02d6b,0x0ad9eb47,0xd05a7189,0xfaaaf208,0x431221bb,0x5238181f, + 0x733511ea,0x417d6c78 }, + { 0x0e91e9a8,0x3cbd81b7,0xc370d6b3,0x73340418,0x8eaa2373,0x825db10a, + 0x6c7d6756,0x8f2b09e4,0x94c33ded,0xe288ee9b,0x1695e3fb,0xcd8426bb, + 0xdce9e888,0xa6176c86,0x6165e362,0x3f4c8922,0x6063fb09,0x514e411f, + 0xc8f9e04c,0x6907ac20,0xdfd2ad61,0xcef7469c,0x8452199a,0xba30bae4, + 0x12ac3462,0x30681293,0xc92d482d,0x011be873,0xe8330995,0xff4cbf89, + 0xd1470a0a,0x02189d52 } }, + /* 23 */ + { { 0x92599c69,0x73e419dd,0x7fec32ca,0x5b94221b,0x09bbfbfd,0xb2bf9bd2, + 0x63ed895b,0x61ea97a4,0x3f486f79,0x6609146b,0xfd141a39,0xbd1c7a05, + 0x83d64135,0xc79ec8cf,0x9883507b,0x7f8fd42f,0x17b3d027,0xafcb53b7, + 0x67ca5a21,0x86658dcd,0xcd149786,0xa6a6c0ac,0x34b95067,0x16f3d70e, + 0xdf44958c,0x371208e3,0xec280212,0xd2dd64e6,0x30782c71,0x33b2c4ab, + 0x521176fa,0x7bbf8abd }, + { 0xa78b981a,0xbe9e4aaf,0x304ec828,0x788b4e36,0x3959dea3,0x0c45cf39, + 0x240b39c7,0x70a9bdd3,0x28383b7d,0x499cd7dd,0x307a1026,0x30690b2e, + 0xee92f1b3,0x2262d598,0xb4725a48,0xc62d77de,0x7bc3aa0e,0xa16f25bc, + 0xd15ef7fa,0x62dd8b65,0x0b96d68f,0xd979221d,0xa00f1906,0xb92885c3, + 0xeb74c740,0xfa476b9b,0xc7576222,0x217ddbb5,0x5788504f,0xc2782c30, + 0xf812716b,0x860d096c } }, + /* 24 */ + { { 0x4d79bbf9,0xfebc337d,0x69f74f80,0x5d53eab8,0x33104d53,0xff36a095, + 0x196f8b97,0x2ab820da,0x75ce6909,0x961d3d1f,0x04683754,0xb197ec04, + 0x93a6cb9b,0xa68ce1bf,0xc5f021a3,0x503456ff,0x8940ffdb,0xb50a2db1, + 0xef004209,0x77c50f8f,0x04965875,0xd635d177,0x8bb8770a,0x725766d9, + 0xa078e53e,0x8e19b028,0xf9fc8378,0x364d4cca,0xf0dd39a0,0x1a3df411, + 0x03adf920,0x7e80e442 }, + { 0x539a1ddf,0x4b5f8a57,0xee486562,0xd248e7ae,0x816021e1,0x1c7b491d, + 0xfd36d2c4,0x2e7b871b,0x0aec00d9,0xda38b504,0x6193f1b3,0xf2827612, + 0xfb1f78d6,0x69c3fe86,0xe827ac33,0x56c8b786,0x3487c8f7,0x1687f6c7, + 0x19dee5bc,0xab8f2217,0xff399418,0x04e8473f,0xa9027c80,0xf384c014, + 0xaa1d2e28,0x9967be9a,0xe065eef1,0x869686d3,0xc7bd837c,0x737c6b08, + 0x9e8bd863,0x5dcab5d1 } }, + /* 25 */ + { { 0x9a7d772b,0x0784283a,0xe540959b,0x6b49e525,0x86414ab5,0x546bb008, + 0x9d74b2a9,0xd4448162,0x203b0b1b,0x267890ad,0xc8d3f86b,0x1e7a82bc, + 0xd85a83c7,0x1352bfb5,0xfad07ccf,0xf29f16e3,0x41e0c43f,0xc02a63b8, + 0x6b379fef,0x904f22c5,0xb1244f26,0x19d8a653,0x3a28bdea,0x6635b6df, + 0xf6d455ce,0x18b68851,0x9cff3735,0x74ac2818,0x8b2cbdab,0xad40f9df, + 0xadc9d498,0x08cc2d9e }, + { 0xc170c84b,0x2e6a6866,0x5a49a484,0xbb989e8b,0xd04c8992,0x7b0e00e0, + 0x61b3a423,0x55ad3478,0xb0d01899,0x3c952450,0xe3100cb3,0xe3922155, + 0xf03276d0,0x19265b6e,0x76d42b53,0x0fe8595a,0xfc6353b6,0x0a96dee0, + 0x246f893e,0x761e0dc8,0xf0a74cba,0x4ec902be,0x3fdfad9b,0x61008684, + 0x4fdb6975,0x5d6a60e4,0x7ef7590a,0x3f53aac8,0x12870a37,0xd29e6be0, + 0x55aa55b0,0x991fadc1 } }, + /* 26 */ + { { 0xb4844ffe,0x82bc4b0f,0x60f8b871,0x73922714,0x4ce3f1f3,0x8ac000e2, + 0x163519ec,0xf0d548b4,0x88288b5f,0x7aaf842b,0x2bdc9a70,0x9e8b0c4c, + 0x4ba5fd67,0xa06d5152,0xf93cdec3,0xd0b1afa0,0xdf89f8f0,0x280955ba, + 0xeea32c92,0x86cbe92d,0x3fe05be4,0x0cae3f99,0xfa6919aa,0xf2607095, + 0x6e0f1b8b,0x0f54741e,0x30ecf988,0x2aed1f74,0x734991d7,0x9296f76b, + 0x259f0fe9,0x66cf8d28 }, + { 0x226f5868,0x9b01905b,0x16909e9e,0xc102e88c,0x4a37eb54,0x2bd08916, + 0xc9816323,0xf72253e8,0x86bac53c,0x37f84e9d,0xafeaaaf7,0x2e352454, + 0x2ca0046e,0x67c86f77,0x6663372e,0x86bce50e,0xb6950a04,0xf6a3a960, + 0xfc1aba93,0x61f994d7,0xc1326e6e,0x1957c12b,0x2e56b005,0x9b658fe4, + 0x8592740c,0x9cd297fc,0x177f26a5,0x7654ce9b,0xa79d2ebb,0xaaa699db, + 0x0ecb6448,0x5fca0c5a } }, + /* 27 */ + { { 0x569a6663,0xe26e25f3,0xe6aa4ca7,0x09597ee7,0x8d18b80c,0x25a4cda6, + 0x22926730,0x450602b5,0x07387209,0x9af5f650,0x26733a53,0xfeeedb34, + 0x86572951,0x0f5ce768,0x8398ae9a,0x872a360b,0x2b30f6c3,0x60347a80, + 0x1a162158,0xd2113b23,0xee6c6dec,0x6fd9cf92,0x5cbcf9e6,0x85f0a5a8, + 0x2ba3fe84,0xd7a5a6e4,0x51ecd727,0xaafe6720,0xa2081a10,0xe09c6bb2, + 0xb973b0b4,0x657acbf0 }, + { 0xc274c8d4,0x3130466f,0x30a994d1,0x42765176,0x7079435f,0x217258ca, + 0xeb897a06,0x44850406,0x561ee130,0xf38dfeee,0xaa1778bb,0x11f4facf, + 0xb9abb9e9,0x765c6617,0xd8f10932,0xb135499b,0xa73b9159,0xc0eb6337, + 0x6f7e8b6a,0xf2c1ccf1,0x187def53,0x5b32c03a,0x830b9c62,0x89ad1d49, + 0x2f10e538,0x1735eae3,0x9d5f55bc,0xb1cbd9c2,0xe539db0d,0x42428c47, + 0xc852b3bb,0x3d2da412 } }, + /* 28 */ + { { 0x871f2865,0x97702b6e,0x142920d6,0x56cb639f,0x45b58611,0x328522a0, + 0xf3b13812,0xf3943ad1,0x712206e8,0xe6c2200a,0xa34d59ea,0xc2890e5a, + 0xf6b7f759,0xab52fd40,0x180bf567,0xf522c8de,0xaccee396,0x181e97b2, + 0xc4ea5cbb,0xe0375819,0xab51d3ef,0x0d9985e8,0xbcb50fd8,0xe26c96ca, + 0x97e1c80d,0xfb9d6b13,0xf796357d,0x582b1814,0x07f4c7fb,0x89a78221, + 0xc0357e61,0x02aeef2d }, + { 0x2c7ec9be,0x2ba7926f,0x7258b201,0x292f307e,0xc6fa6b4a,0x74e62a10, + 0xe2bcc5ab,0x80c08549,0x7bb8c073,0xb4160db8,0x329f194d,0xd5ef0529, + 0x6dda4a9c,0x0eb8da14,0x15ea23d1,0x0b5d43d2,0xfc34bfae,0x6cebef02, + 0x848757a7,0xacd364d0,0x2d34cca3,0xc1401368,0x1d2d95e2,0x09ca6742, + 0x786eaa28,0xc3fd1d6e,0xa2965fec,0x9eb1136d,0xc0779203,0x48871baa, + 0x4b15aeb0,0x6b446c01 } }, + /* 29 */ + { { 0x25e8fe80,0xc819eb2e,0x98238a17,0x2b5f7906,0x81e41849,0xd6f1e996, + 0x98ea6d45,0x58ad8ad6,0xbfd02e40,0x5bae5ad4,0xa812416d,0x016dc327, + 0xa3347ca1,0x8b31a985,0x82a65391,0x0b4da610,0xb48c35fb,0x1cb91b2d, + 0xd2aaf8c4,0x9e96817c,0xcdfdcdc0,0x1a630483,0x12b69254,0x70559361, + 0xf8a2a097,0x5fdcd712,0x35cc5281,0x59ab623a,0x932b6095,0x30c8ebe0, + 0xb08e052f,0x8613424b }, + { 0xb2231d8a,0x28902063,0xd9a61667,0xb0f62329,0x071a9f27,0xaafa0fe7, + 0x603f047e,0x6bcd8960,0xfd92a1c3,0x118cca76,0x71d483b6,0x3414e62b, + 0xba705262,0xa123ccdd,0xfd9b5c5a,0x1a576437,0x4c8d0fa3,0xa5301bc2, + 0x102427cd,0x96f0ad44,0xd3aa6c02,0x0e6fb5e0,0x072a3996,0xcd8c4880, + 0x840d3fad,0x4dafca12,0xde91d541,0x29f4ca3d,0x8441734d,0x0037c598, + 0x9ccfe57c,0x86333a99 } }, + /* 30 */ + { { 0xecf53b40,0xd213a751,0x2f78a542,0xcff2c6f2,0xf13ae56d,0x0f59f0e2, + 0x0e61748e,0x91f8ccbf,0xd72c4145,0x0aadecb9,0x4c9cdcb7,0x6b2ed852, + 0x1eaffc70,0x8e00b72c,0xaa728102,0x89b24285,0xb679cafa,0xaa7ea7e0, + 0x4f0a6f6f,0x5d2b8c26,0x0e804397,0x7ed7b173,0xc8573049,0x5a93eb45, + 0x0986e93e,0xc92bf5d4,0x6a20c0af,0x526b5a9c,0xb99dc3af,0x0adf47c9, + 0xba202cc9,0x12b25fe2 }, + { 0x33eea395,0x09b8d78a,0xf633fc5c,0xc7a93618,0x270eceef,0x7e821629, + 0xc628ed0c,0x524779b8,0xa1d68939,0x91db5ca1,0x586edc90,0x8626e18e, + 0xfeb3f3bf,0xfe023e8b,0x0250171c,0x6279fde1,0x55e172de,0xe52ec7dc, + 0xc6d4ca45,0x445e8695,0xbdbc10f1,0x42de3878,0x6fc3835e,0x2b114de8, + 0x7e10b652,0x9faba456,0x390e78fe,0x4111d82a,0xaedf0aca,0x576b61c2, + 0x74accb74,0x216279a9 } }, + /* 31 */ + { { 0x4047f747,0xc14cdabf,0xc1315a1e,0x03ca233d,0x40e5d0a7,0x59e7cbd3, + 0xbb413869,0x1fd0c4e9,0x0f01fbd8,0x189d08b1,0xa76b823d,0x50449c42, + 0x398b00a1,0x81c224a1,0x8e8179e4,0x08084e4f,0x698e41e9,0xfd8af994, + 0x5610bf2e,0x1e30e37c,0xa7d2790f,0x4e6a043f,0xb3195388,0x9d96e60c, + 0x03799dfd,0xe75f986d,0xf8ff902f,0x3b4a8f11,0x7588416e,0xfa945378, + 0x9827535e,0x20683e3f }, + { 0xd0378878,0xcb582e26,0xa7945787,0x9e214c23,0x8f6688b3,0x13d000bf, + 0x40515270,0x7548d4f5,0x40111f5d,0x7113c15d,0xa8bff902,0x3bf5a526, + 0x9b4945cc,0xbda6b010,0xbc2f3a05,0x83dcc74e,0x43efdfa1,0x2aef6284, + 0x565c5bf4,0xd2e60ee9,0x592f243a,0x4f0fa10d,0x1bc3bf51,0x6ae58b32, + 0x60576a74,0x813b0868,0x4d73081a,0x0bc023f8,0x32dcee59,0x9fd03aa0, + 0x27d6c795,0x5e416bf5 } }, + /* 32 */ + { { 0x026cc23c,0x24313760,0xb5b29058,0xf819aaee,0xc5d2ee17,0xa92272f8, + 0xee5cc402,0x8048e7cb,0x77def07d,0xdbc7d6ee,0xf6af821e,0x61d69244, + 0x996cbb89,0x5f7966ed,0x96a155a4,0xf81b17ea,0x03f3ed56,0xb2d9ef70, + 0xe882a5b2,0x5e6e5906,0xae947180,0x86fa1072,0x658c76f4,0x34d9fc51, + 0xcb035aa0,0x9f603dc0,0x75be6481,0xb7b39feb,0xcf04a9ef,0xca87554a, + 0x87b4fde3,0x4ff682ec }, + { 0xd0a10ad5,0x3125627f,0x968e6f45,0x7fd45c72,0x806a1163,0x2981bd6b, + 0xde5033e3,0xb92de1cd,0xbf4f8988,0x3b44b45e,0xdae7e1dc,0xca1b9896, + 0x0778d878,0x52166e5a,0xa5116847,0x82d472be,0xf2895445,0xfbdd382a, + 0x5d6ec4c9,0x22ed1602,0xb6552b02,0x3614eb1c,0xa1e6210f,0x63c5df73, + 0x021a74a7,0xe9160285,0xc65cbd4d,0xa44ca400,0x0f15e299,0x48cb187e, + 0x3402507c,0x51eb818e } }, + /* 33 */ + { { 0xb92100ab,0x1fc1d178,0x9605b839,0xdf2e3d60,0xb71e59d0,0x12a7c255, + 0x14fcbe04,0x3f8b6675,0x59fd06af,0x0e8a3935,0x12020d07,0x56326502, + 0x528e7be5,0x6696fcd1,0x0c7b7654,0x6588514b,0x5912a5b5,0x0cd80f8c, + 0xf324cb7f,0x8bafef04,0xc6da3d75,0x6b53eecf,0x31d1df2f,0xedef48d8, + 0x73812b6d,0xf336b965,0xee626031,0xc82eae4a,0xd244f09b,0x300abd32, + 0x31d9647f,0x8b0af955 }, + { 0x2e603544,0xb770180a,0x221acd9e,0x2b573ac3,0x62407032,0x3a17f665, + 0xb89abc3d,0xad3e74ad,0xd793225a,0x8a3d2e3a,0xef02564b,0x457bba04, + 0xfc2dd2b5,0x8875652f,0xe67143e8,0xd2905d15,0x02e48d70,0x6d884b42, + 0xc7636a57,0x06f99219,0x35e378df,0xa8dc3421,0x10c64a02,0x95c1d73d, + 0xcc157a66,0xcd6a4ece,0x8e24a354,0xbadcc1c8,0x9839329d,0x8024f1b2, + 0x4da48ad0,0x5363e549 } }, + /* 34 */ + { { 0xe23fc641,0x1f5523b7,0x86667063,0xfe54e72f,0x8e009d2f,0x294a15f5, + 0x8c57f5e1,0xf203997f,0xb16d64dc,0xa229724c,0x4baa2ffb,0x697be4fd, + 0x0a6e8ed6,0x3f507e46,0x78508536,0x0afe3a5d,0x95408208,0xeeef6cdd, + 0xf2c4237c,0x701fd889,0x5c385253,0x496d883a,0x72a212f1,0xe25c67ed, + 0x1ff78fcd,0x4b416783,0xc16f4146,0xe9967004,0xc45b0697,0xfa45c3a1, + 0x3fbd30c3,0x63334018 }, + { 0xa2fbbbce,0x39c9a0cc,0xaa0cb744,0x876f6e5c,0x3438ece3,0x9ce6010e, + 0x13802d82,0x0aad148e,0x9cd45a1b,0x9c3e5c60,0x7bcfc1e0,0x875cb859, + 0xd8584dd0,0xb19ff790,0xd81c2a2b,0x2598b81e,0x02be07e3,0x118bdf2f, + 0xb9765ce9,0x074fc8ee,0xb24f95ae,0x125e9d88,0x0c98f09d,0x3bb12cdc, + 0xa0b74b27,0x4a6aee07,0xc08077ce,0x4723d2f9,0xbea8026f,0x959447d6, + 0x16280b73,0x93a7075c } }, + /* 35 */ + { { 0x715b27f9,0x26bbefe2,0x2a280923,0xa935a5e2,0xfd58a26a,0x5ddf23af, + 0x7c138694,0x54c83e16,0x892a2153,0x44799bc9,0x9b8d09f5,0x4e6e4710, + 0xd588ea68,0xc63af616,0x883ab1b6,0x5e896706,0x3d209336,0x3c1393a0, + 0x92c23dda,0xd02f2921,0xdcf6ea43,0xab70cb7a,0x791559e1,0x12434ea8, + 0x6d70ff0b,0x040680db,0x2832ba45,0x1a10fe52,0xe5f0cb8f,0xd69f9c08, + 0x44b141fd,0x1a7422ac }, + { 0x9f40b675,0xc3a9dd2e,0xfcc71f39,0x2a7c6603,0x1948e342,0x18939a61, + 0xed0ab484,0x8f3b6158,0xee31ca6b,0xa3aa7d97,0xf7a8db63,0xbc1e865e, + 0x2c7c62e4,0x315f8c09,0x9f5c6d0f,0xa260788f,0x4b6f3ec5,0xb1833129, + 0x36b4d849,0x73adbcd6,0xbc699a9b,0x66e14890,0x2a1175e7,0xbf3790d8, + 0xfc53ca4f,0x7f43605a,0x87ff6091,0x577f6c47,0x600c82b6,0x827c7552, + 0x9d25599c,0x0944d630 } }, + /* 36 */ + { { 0xe6ab9620,0xcfdeb63e,0x786cd808,0xdff4fa6d,0x456320b3,0x145edd82, + 0xc4943915,0x2ae5f862,0xb73b3f87,0x9508e813,0xe52f97a9,0x3bd805f3, + 0xc9829b62,0xf71b5c28,0x86e0cefc,0xb394c70e,0x23bdb36e,0x534fb1a9, + 0xdbe27e5a,0xd64f5862,0x83ab6169,0xbae23df3,0x27c828cb,0xdd6df1b1, + 0x3a307a8a,0x1901899f,0x811ddf66,0x36cc8659,0x79943b77,0xa3cb7774, + 0x6fd86576,0x7d89f383 }, + { 0xc9f92b2b,0xf8564242,0xc46e32bd,0x700c6a75,0x7f99a5c5,0x93e768b7, + 0x03149568,0xb6efe858,0xc2ce6709,0xbbfe8a19,0xee6ec493,0x721a3b1b, + 0xc371c28d,0x26eeeea9,0x15177e1d,0xd798115e,0xb068a5a5,0xd7bf3bce, + 0x46d2b4b2,0xdf8da220,0x59be9dfc,0x3df0995b,0x77640b79,0xc96897bc, + 0x5a2bd3c5,0xce0cf4c2,0x89afe744,0x16f45d6e,0x3a8509bb,0xb53f3acb, + 0x63f2a6e6,0x449af81f } }, + /* 37 */ + { { 0xa16d9377,0xc2fcf132,0x7e1a2f9e,0x9ab377b3,0x86d19ae5,0x72e1a12e, + 0xd013bbb1,0xd2b12e66,0xcb5f66ba,0x0972e055,0x399eab50,0xd11de1c0, + 0xc65f5ec2,0xc1f314fd,0x8a9ff593,0xfc311841,0xe05246e6,0xdf73c1ec, + 0x1625056d,0xc28d1363,0x6fb25e19,0x30a9dbd7,0x845cd2d7,0x049ed244, + 0xd36e852d,0xc779b83f,0xf68c8a83,0x85a35fc7,0xc95e8033,0x299bf1e1, + 0x20891af5,0x0e8617c3 }, + { 0x67c81b5c,0x53720602,0xe737873c,0x2fa89dcd,0xa8144fd0,0x2a7430b0, + 0x26208c83,0x3006c5a7,0xd8ea40f5,0x4e066660,0x896413a4,0x9dd025f9, + 0x46b9149f,0xbdf380cc,0x0a125cc2,0x80156619,0x52793c37,0x04d6a3b7, + 0x6b7a62f2,0xb6001374,0x585d5978,0xa9cfe268,0x8395fe66,0xdcad0cb8, + 0x46b261f6,0xbab468fc,0x9d9d9218,0xca0ef5ef,0x5e452402,0xc507d4a8, + 0x326cf687,0x6f4404f1 } }, + /* 38 */ + { { 0x4febd3ff,0xa3e1920b,0xfdfd2bba,0xca6234d8,0xe19a9829,0xb7d1af2a, + 0xc6f5bc20,0x23de1610,0xdaa39ca9,0xe204dbf3,0x6d8c70ab,0x2a2de9b8, + 0x7c9d370b,0x272e0c37,0xe565510e,0x80914c06,0x57cbb6b0,0xb611e7a8, + 0xd8266a6e,0x076fc6ef,0x3095801c,0xdfac34ee,0xb9e24063,0x69ff40a2, + 0x787aa5c5,0xa7ba31a9,0x33c70cd2,0x0e4d1fdf,0x6895f074,0x903e3132, + 0x7fb671e2,0x905771f8 }, + { 0xa4062bee,0x5199ba0d,0x94d7d9f9,0x18e7238c,0x1e0922c0,0xf53f29bc, + 0xb12d855f,0xde9b2a81,0x6d68ca29,0x649f3eed,0xc50c097f,0x64adfc34, + 0x9db398a0,0x81964ab9,0x7a587224,0x00d59c47,0x74c5903a,0x09fea396, + 0x15043dd0,0x6aafd8ee,0x5f1ecc20,0xc5721a6e,0x0db9b7b4,0xb6d6a483, + 0x66c8d52a,0x06ffc617,0xacc82a27,0x3de241d6,0x27f2f7a8,0x0605f052, + 0x6404decc,0x6a22953b } }, + /* 39 */ + { { 0x74fce389,0x92452d8f,0x2afa5564,0x059634c0,0xf0ed7825,0x9377ccbb, + 0x37718e0d,0x89f4045b,0x9fa69a4d,0x11074e7d,0x7295b0ba,0x5d70bb07, + 0xf107ede6,0xb22d54ad,0xa1a29c7b,0x5c39a3d8,0xd795e3ab,0x37236c02, + 0x2b589951,0xf7282d00,0x5790bee2,0x5e2265be,0xa8e65ea2,0x91e0ea11, + 0x6001cebd,0x0e71a708,0x2c1c5402,0x16900f5a,0x357f6981,0xc3b2d5c0, + 0x619e3427,0x528c9ea0 }, + { 0x5f26c577,0x1edc86b4,0x9438bd45,0xf8074708,0x792582a7,0x2dfe1013, + 0xde1e569f,0xe08eaca0,0x9a55a356,0x5f952efa,0xe4976216,0xa4d80b53, + 0xcd5d71f2,0xd2b65855,0x66cea3f0,0x246704bf,0x492323ca,0x193f641f, + 0x9adb1325,0xa681855c,0x2d19d652,0x86d522ce,0x5b82ed7b,0x53609f10, + 0x8e150d29,0x3b0f0094,0x0b13e891,0x23ad8bfb,0xf794b449,0xcbb1556c, + 0x738bcf57,0x200f9093 } }, + /* 40 */ + { { 0x8388387f,0xf9b22fc5,0x28e883c5,0xcf26f170,0xd1b7973c,0x447cab90, + 0xf6ec9171,0x8d5d4ea2,0xc30cdbc0,0x2e16f498,0x48623c2b,0xdc92910c, + 0x30dbc545,0xeb1491b0,0x14de21b0,0x631deb2e,0x2fe830f4,0x04a21066, + 0x379c1f3f,0xa4c6979c,0xfb06a795,0x8a732b68,0x1619dfa9,0x3a44327a, + 0x8dbe2c9b,0x91a307d3,0x03989fea,0x939bc8d2,0x0f4a331f,0x3daabaf2, + 0xdd0f55dc,0x5c307e98 }, + { 0x35b233da,0xbbc4e0c4,0x22f6f985,0xe3d29085,0xa8b02468,0x99dd2d21, + 0xa96916e7,0x978f40e9,0x614bcced,0x0327d86c,0xb290762c,0x95e95502, + 0xa879f2ed,0x0ffd2197,0x50e0bd33,0xc4365137,0x0827c4c4,0x26c3148a, + 0x3fcfc0b2,0xc79812a8,0x31928589,0xc3d8d17e,0x8830f42d,0x8b572cfe, + 0x4b07f83f,0x7cd9ff92,0x0a51148f,0x331ca950,0x4c59f9ac,0xd0c53968, + 0xc1434785,0x1df16dfa } }, + /* 41 */ + { { 0x68bcacc3,0xcc7bb4ac,0x430f58cf,0x06ded34f,0xd461855a,0xc59f9f4f, + 0x45c9f0bc,0xf5491994,0x4375c892,0xdc5f7ec6,0x3c85983a,0x1b8708f1, + 0x82fcd087,0xb32a5cc4,0x2d6b4c0f,0xefdcdc35,0x8ac6fb2d,0x4bb24f04, + 0x33906471,0x5982d4f5,0xb83a3ac4,0x162eb52f,0x2337a223,0x7130df28, + 0xcbc3dbd3,0xdce7b802,0x2467ac0e,0x8b395959,0x1b56717e,0x21d3d2e8, + 0x46512617,0x729a7f50 }, + { 0x8420f90a,0x874ed1aa,0x0fe4c855,0x6368e19e,0xb0be74af,0xb62d4aaa, + 0x8ca60ca9,0x76fcc480,0x7645a867,0xf310b5a5,0xddb1b24c,0x131bac9b, + 0x2dea5b44,0xef77d71d,0x72fcc64e,0x4706d210,0x673d77f0,0x29b92691, + 0xe89e0663,0x22e00bf3,0x74077d40,0x472d0cd3,0x829232e2,0x3e21040d, + 0x38dc8533,0x2f916dfb,0x14b8f667,0x48bbb59b,0xd44be19d,0x19de9f4a, + 0x232d9d5c,0x7f6d3649 } }, + /* 42 */ + { { 0x6e794819,0x3bd064de,0xf82ebda1,0x5a6b694e,0xb91e2804,0x1f017fe0, + 0x07a43cd2,0x190d31f3,0x630433e9,0x6c26f226,0x0abfdcb4,0xba488aa7, + 0xa46411c0,0x418d9085,0xbffb5880,0x1b934fe6,0xe200f849,0x75d1e237, + 0xa55413db,0xdf04d63f,0xe23b3f77,0xe216ed75,0x0f91bd30,0xa05866cb, + 0x7729c509,0x84c395d9,0x452ab2d7,0xec97e188,0x0093d686,0x8cb7c1f9, + 0x628f086c,0x2d032395 }, + { 0x4a44b4c5,0xa81c9407,0xcc702c98,0xb9846879,0xceb0dc97,0xcb502287, + 0x6e3aa321,0x30301126,0xe4c256c2,0xc0ac8763,0xe55b4845,0x65034d20, + 0xf240f35b,0xaa96a040,0x7cf7eedc,0x046d26d3,0x3b810656,0x62a5a8e1, + 0x83d70c2b,0x86044b97,0x59e4da8f,0x2fbaff88,0x5457f5d1,0x929d901a, + 0xb531b757,0xd29e1eb2,0x9e4e9739,0x214dabdc,0x4eaa9bd9,0x5bd724fc, + 0x1ef9bb9b,0x734c12b3 } }, + /* 43 */ + { { 0x92f9b086,0x98fe3c2e,0xb3fd4544,0x4641b93e,0x5c02c65c,0x47ce208b, + 0xc4f03242,0x8a52dca1,0x679d29f6,0xb5ec17d9,0x9406f5f4,0x11d2fed0, + 0x0d9ba811,0x260f63dc,0x15472a3f,0xde2b056f,0x007290e6,0x1b170d9f, + 0xb6b5c8f9,0xa2e23e8d,0xcf34c3ee,0x345a2839,0x1b973ee2,0x9bdc5461, + 0xbb24d1c5,0x65bda6c2,0x3c6141a1,0x97d52ba3,0x9d2eb201,0x47bb1612, + 0x21fbe49f,0x7c558a87 }, + { 0x3f350fec,0xb9485a52,0x6a38d4c0,0x016678c5,0x0d5aa64d,0x8ef346a2, + 0xd96da2e4,0xb85daa02,0x4f647b3c,0x845ec4ea,0x0d5e946c,0xc0d1a6ca, + 0x4fa9f4ab,0x41d8d1c1,0x9c8b1303,0x43972cc5,0x434ffbfb,0x67e1f48d, + 0x819d2318,0x350ce93a,0x6ddef23f,0x49f53090,0x200cf12c,0x3c2e6cf9, + 0x640432fc,0x42691cc1,0x72496b52,0xbfff74b4,0x020a97be,0x44527c9f, + 0x7b3c4348,0x34cd7dca } }, + /* 44 */ + { { 0x59e7fe87,0xf031761a,0x0047cd72,0xb1eae31a,0xfae30f62,0x27902e68, + 0xb71db143,0xa666f48d,0x0e0038f4,0x75ee6678,0x02bdd76d,0x3b45ac67, + 0xa0d6cd5c,0x0d2fb828,0x9d8c5b11,0x27ce7f1d,0x120b5e96,0x141fe0e4, + 0xb9267c37,0x95a1b984,0xd60312cd,0x5206e589,0xda549356,0x1867342e, + 0x070c74ac,0x374520b9,0x9557b0b3,0x2703cbb5,0xa6ed8c14,0xf621f59c, + 0xabf7b887,0x7ceb1cc2 }, + { 0xdb7fd65b,0x0647a5bb,0x36c9457c,0xd8d45cc0,0x9e12718a,0xc6da99db, + 0xe93a7fb1,0xed1dbbf4,0xbd1566a1,0x4512c95c,0xdbc0c919,0x4861ba00, + 0x9e7f5269,0x3c6cc298,0x0941aaae,0x67196150,0xc8c538e3,0xbfcf5d0f, + 0xa25a551f,0xad6e9929,0x17ca0f26,0x90710985,0xfa89ef7e,0x743b78ea, + 0x71ab4549,0x39d5ea31,0xe6d1c36d,0x7442f3f3,0x059d568d,0x25a683e0, + 0x227ced5c,0x1f629a99 } }, + /* 45 */ + { { 0xe45a1c3e,0x8925ddac,0x41f7545f,0x72d29365,0x37e7f828,0x45622fcb, + 0x3e4c79d2,0x88234513,0x9c2645d6,0x5dffaf84,0x994802b9,0x3078f4dd, + 0x9d339fa0,0x566927f0,0x9fd91dcc,0x9a500a1e,0x0ab0abd7,0xce008180, + 0x8194e5df,0xd97135a3,0x98adf088,0x9e876307,0x9a45a2a7,0x3baf01b8, + 0x788b4399,0x6fed6154,0xe77a997d,0x980e5722,0x2a378eed,0xaac90ffa, + 0x8bd805a2,0x4a75fda2 }, + { 0x55e74cbc,0xd09a8fbb,0xfab18f25,0x737738ce,0x9764ec3a,0x0fc23ad6, + 0xe7e0ad31,0xc5a7d35b,0xe481cc9b,0xe75e068e,0x3d4aec34,0xf0c2ea99, + 0x0d4a63c4,0xf1324fe8,0x99b0592c,0x5dbb7c16,0xa7e0f46b,0x442d674d, + 0xa300faea,0x5a5d66c7,0x3333ac83,0xe83dc821,0x8c408496,0x70ef812e, + 0x99ef5fc1,0x96e1dcb6,0x1734e862,0x6e2b771b,0x583507d8,0x04629cdc, + 0x23d8179a,0x5819f9ae } }, + /* 46 */ + { { 0x6aa78811,0xd9969121,0x2103e7c3,0xf64ee8f4,0x22b9e698,0xddf01070, + 0x4f582cde,0xe6001f9e,0x2ecfac1a,0x24a608af,0x06393009,0x6ef4c784, + 0xebf72911,0x5262eae6,0x8c4ee5a0,0xddbd0af5,0xecd87bc7,0x875aff90, + 0x6f24f114,0x2fddb34c,0xe865f172,0x48104281,0x886c1b9a,0x95692426, + 0x9ef4231f,0x6f5f3208,0xd0a7e82e,0xaf587acf,0x9ac395c8,0xd6571917, + 0x1364a750,0x7459603c }, + { 0xf41ae519,0x1c2475bf,0x4af8f251,0x34401fb1,0xaefb2c3d,0x70ddfcd2, + 0x51cdaf08,0x9b2d385b,0x8208bb19,0x8531c256,0x4c33f3f6,0x16c89df6, + 0x24571769,0xc23cfa99,0x86d010ba,0x2339b51e,0x22638313,0x08db0e8d, + 0x00fedeb7,0xf769e179,0xa3687ef1,0x3fd96dcb,0x91476475,0xcd046b23, + 0x0c45c8dd,0xf3ff2064,0xb8343d78,0xefd167bd,0x4b77ee90,0x493ccb6d, + 0xb3cf7b45,0x33025513 } }, + /* 47 */ + { { 0x35eaaca1,0x36f00469,0x89119102,0x0c384b75,0xe6d2954c,0xcb375665, + 0xb1e9d6d7,0xcb9199b9,0xc29c2757,0x75852349,0xb8e738d0,0x89cbd1ba, + 0x5923a427,0x9b8dbe90,0x18fe1889,0xa237793e,0xa742e083,0xa4271757, + 0x4eebd613,0x8c4979d2,0xd4f2cf77,0x40325054,0x958705de,0xa3b8a091, + 0x33d999ba,0x1b191bd9,0x3b0fee1e,0xbafefba4,0x3facdf14,0xb3bad184, + 0x4387561c,0x9328adb0 }, + { 0xf906b872,0xabe84e80,0x78262665,0x705523a0,0x3398ccf7,0xd89c6a7e, + 0xf55b5323,0x2fab551d,0x0554dea8,0xa0578eca,0x375589cd,0xef26523d, + 0x864ad750,0xd8fd6242,0x178fe1fe,0x93f27fc5,0x9df87422,0x7b3e6f30, + 0x3750d054,0x2862e49e,0x5dc038a1,0x7d90c6b2,0x84db682b,0xc1a1ae22, + 0x9881930a,0x47f3dab7,0xbaf3e0a4,0x30e6bd52,0xf62d25c5,0x0680025b, + 0xadd0d5e7,0x0aa1f3cf } }, + /* 48 */ + { { 0x22a10453,0xa9822190,0x2a03a10b,0xdd1eb91c,0x96646f3b,0xafbb5d95, + 0xf38b6fc6,0xa58de344,0xb8cfca1d,0xce47c3e5,0x0f70da04,0xfcd8e16d, + 0xda262ed6,0xac44349b,0xc56e2f8e,0x9320d87b,0x19138e58,0x9ce3ea08, + 0xa2b236c0,0xa5862dff,0x8e7efb0d,0x6b0f9a5c,0x16ac78eb,0x4b53432b, + 0x709b51af,0x6ff43105,0x8f519628,0x08e236f8,0xeed403ad,0x1f93f176, + 0x9636545e,0x559337e0 }, + { 0xd8fd807a,0x30ddf738,0xab131222,0xf4e0ec9d,0x625afbc3,0x14a2f4db, + 0x9f12f895,0xd5b70604,0xac3044fd,0xb46f3c23,0xf540148f,0x1b232d1f, + 0x39b4e554,0x61b458f5,0x0dd70b75,0xf694b24a,0x289581d9,0x0fc64299, + 0xee5fe22d,0xc05d49be,0x6a18bf63,0x7af3447f,0x7f1929d6,0xe96a1dc2, + 0xc1551e8c,0x6afe6028,0x2b5d4fa2,0x27dacaf3,0x545c2cb4,0x4a1631bc, + 0xb0c914d3,0x930070f9 } }, + /* 49 */ + { { 0x69a9bc05,0xd2f32c5e,0x589c4b73,0x0a5c19c6,0x94665f9c,0x095c9e5e, + 0xbcfb4c39,0x8ab0f293,0x1ddb7c31,0xb9070877,0x66b38048,0x894e9658, + 0x606bd9bd,0xf19a90cf,0xb6fd2d69,0xcc1d58df,0x461d8a69,0x886dcc4e, + 0xf9ce4831,0xc455c277,0x765f8a82,0x749a5996,0xc3badc8d,0x2ffc668c, + 0x9112cdab,0x38018396,0xb243c7cb,0xa98795c3,0x010a2224,0x8775f310, + 0x587b5e14,0x043a2141 }, + { 0x3a873752,0x7bbe9dbc,0x2f442fee,0xee1493f4,0xc18c2181,0x981ca2c8, + 0xe29769e7,0x00ce3090,0xde768c5f,0xb4626ac8,0x34d7677e,0x33e9ce46, + 0xe0fa94e6,0xf89c2cad,0x41f5b5bf,0x04f5cc11,0x2228c12c,0x2565f736, + 0x0c05cce5,0xf1bf706a,0xbe487c4f,0x5d07ffff,0xa499f1a4,0x3ec43c09, + 0x98d94800,0x4f4e79bb,0x073f12f8,0x8a335a16,0x0f970d6d,0x4bb5eaf7, + 0xf24d0ae8,0x18d0747b } }, + /* 50 */ + { { 0x84601faf,0x58d3c77c,0xaf1c1f72,0xc9465be2,0xd116d806,0xff626798, + 0xd5b0d93c,0x3996c0c6,0x5ec6723a,0x2fa1ad75,0x03ba5349,0x966a8144, + 0x2ac34d8a,0xdc4c9422,0xed675865,0xddf471de,0x953d528f,0xd8aca597, + 0x24ebf67d,0xb2e463b5,0x7e25b4d3,0x25824871,0x43159daa,0x23c5adba, + 0x83357540,0x5458f9c6,0xf938b1a6,0xcf685da7,0xcefed231,0x981a4fda, + 0x08bb5e59,0x711093ed }, + { 0x401f161a,0x12aa3fc6,0x974c5e87,0xf7358560,0x17b5df82,0x4aa252fb, + 0xa48e6299,0xb0b82b07,0x29dd847d,0x00234157,0x4529c5a6,0xf1e54d00, + 0x6d98f538,0xcc1c539e,0x28d3abcb,0x36162b53,0x2a84f0cd,0x75a37938, + 0x4dee7484,0xf717a81b,0x4c23bf1b,0x16cf35fb,0x787e8b3e,0x7fd1c29f, + 0x59b79ab0,0xb7da7e68,0x85f6c60b,0x072100a0,0xe7ed48b5,0x31840159, + 0x4d9c97d4,0x17898bda } }, + /* 51 */ + { { 0xae1b8cf8,0xcd8483d8,0xe9a28856,0x323d4b42,0x204a4bc2,0x7633584f, + 0xca7a69fa,0x4e0b2228,0xf757bab2,0x8afbda8b,0x6cc5f9ca,0x85b24088, + 0xd41a95c3,0x47fb4813,0xc2aabe6b,0x3f1bc53c,0x1ad1599d,0xf22cda3f, + 0xc31ea9b1,0x1b2ec081,0x01614ac1,0x048f304b,0xc6afa7ab,0xce31cee9, + 0x4140dc3d,0x55af7633,0xdce8abba,0x84b7ab37,0xc7cf3efe,0x50de7648, + 0x15356ab2,0x73a88dcf }, + { 0x06e83b39,0x3f868288,0x9f44037d,0x477a4413,0x17dbc841,0xf9058b0f, + 0x54d17549,0x2db64f4f,0xf2307ffe,0xa23cea6a,0x4f126261,0x393efd55, + 0x10f37f26,0x2f4e658a,0xf4ee1e35,0xa4437ce3,0xa93cde8b,0x64ef42a7, + 0x939aa901,0x1debc9f4,0x3d7b5cd4,0x44223d6a,0xf88a3acc,0x789a6a11, + 0x2c608a2d,0x56fb9df8,0xbbf56c06,0xe79db8e3,0x668fa300,0x73c56af2, + 0xae396a1e,0x52f32b17 } }, + /* 52 */ + { { 0xe714f71a,0x56f524c1,0x9add8519,0xc1be1262,0x65cadbe3,0xad9189d8, + 0x5a0fb649,0xd88bf5c8,0x21d192d9,0x9efa6a92,0x6f724b6f,0xe3fe8389, + 0xb250119c,0xec3fae24,0x2ae0d3c0,0x4b6af9f6,0xd619624d,0x8fceba0b, + 0x2fdb6e3a,0x7dc3092b,0x3263cd29,0xc91da376,0xf95c43bd,0x30c0761e, + 0xcdeb44d9,0x89136400,0x43c0d31d,0xfd7dce84,0x9871899f,0x78fec3b1, + 0xefdf58c1,0x79e14d28 }, + { 0x9bb40c55,0xe3822235,0x0ed07a42,0x0a27202d,0x4838c1f4,0x48e6c1a9, + 0xd864a78e,0x2b5f24a7,0x0c6c55c9,0x7e7f140a,0xce12d508,0xe62c104a, + 0xc11b1e10,0x9b0a1a7e,0xafbb3dd5,0xfd8a275f,0x9a3b6b30,0xdff354fe, + 0x46602a01,0x5a105d9e,0x93bb65f7,0x3d371b4d,0x0f82fdeb,0xda5cbf0b, + 0xde468545,0x4601229b,0xc73d517e,0x505e10b9,0x672ff492,0x77cfa541, + 0x99566ce2,0x0d8ec28a } }, + /* 53 */ + { { 0xcbeee995,0x014cf73e,0xd491e80c,0xb2eb88bc,0xd9aba5d4,0x615a6cad, + 0x9304c84d,0x2f7d4633,0x8ab03c9a,0xba0501d2,0x91babb94,0xc8f723de, + 0x50405772,0xc885f977,0xc7fcb094,0xb5e1d2b3,0xdf96c71a,0x61ee7995, + 0x3464499e,0xb8c8daab,0x5f607932,0xdb425ddd,0xb1243587,0x70251ca1, + 0x9fc74340,0x26d7d3be,0xc902ac89,0x8c179310,0x4559a74f,0x72522c15, + 0xc3734afc,0x86001e27 }, + { 0xe7693947,0x13b00ba5,0x012c062b,0x6478641e,0xe85490a8,0xe1a438e0, + 0xd9574d5e,0x5173dbbf,0x9bd3ba61,0x9532eb8c,0x5f3ea075,0x1f41bcb8, + 0x8cbb92b9,0xac1cc247,0x1ef901b4,0x0f34648e,0xd2b3b2ee,0xdd929d1e, + 0xc3d75bfc,0x470f1eab,0x139cf4d2,0x5cdbc6f7,0xf0424953,0xcd86454d, + 0x47fcb383,0x1e079812,0x17df930c,0xb9f209b4,0x114ebc00,0x4225fc31, + 0x347946c1,0x020591cb } }, + /* 54 */ + { { 0x275e0af4,0xe3003721,0xe78a4a4b,0x721141ef,0xd1757485,0x666cfcf6, + 0x168e659e,0x5fa1d737,0x0e2842ee,0x263e3e54,0x948bd5f6,0xadecc3d4, + 0x246b104a,0x019de03d,0xf343d818,0xf8a9e903,0x5b0c0d31,0xcb57ba4a, + 0x51e2765f,0x8246c506,0x6519bf67,0x80c5751f,0xf2119a01,0x5f05c200, + 0x7821d4f4,0x7e6487b8,0x261c3a06,0x262f94aa,0x72146052,0x56cfe489, + 0xa1df05ef,0x5119985f }, + { 0xb18586c0,0x5819497d,0xc6eeaa62,0x004415d6,0x97cda28b,0x7c6a46b6, + 0x7c194594,0x9a149b28,0x4ed3a506,0xb56369fa,0x43c94cb4,0x7092aa66, + 0xa9e9eee2,0x55bce73a,0x77893509,0x34bb2870,0x06eb5326,0x8af95fb0, + 0x9638f485,0x87cd0323,0x5ba75bf8,0x29376268,0x9d42d581,0xf32d6f3d, + 0x65c6d64d,0xa4cad574,0xb2cded41,0x985f50fb,0x9006a067,0xcf34ce0e, + 0x58a57f9a,0x59eaf265 } }, + /* 55 */ + { { 0x6ec3876f,0x7b407efb,0xf0f48648,0x780c6123,0xbf893039,0x2abb56ff, + 0x45a91ab0,0x9592eaa0,0x78811b82,0xce5b84d7,0x1f9f3fc9,0x86a71a34, + 0xf0e7e13b,0xc17fdd86,0x655a0880,0x88ed8297,0x81d5e666,0x75d6dc74, + 0x1d171797,0xeffc9df6,0xe3f79e1f,0x36ad4c8d,0x2046192e,0xdb15317d, + 0x274fda62,0x78c9fa7a,0x82dd9914,0x04ec924f,0x3a64971c,0x059d1e38, + 0x2620bbfb,0x3b4450ea }, + { 0xc776dcdb,0x3db7a955,0x81c8ba47,0x35c4a57c,0x505760fb,0xae285003, + 0xb3aec353,0xe3e80691,0x47117be5,0x380335be,0x056ccf61,0xe1c47e3a, + 0x33977916,0x253cfdeb,0xf5cb7ee1,0x3decdfba,0x7cf4b704,0xf3c9794f, + 0x9ff81462,0x2401680c,0xbe3daa9f,0x4e440e11,0x69f91d8a,0xc5d04377, + 0xcb5e9c5d,0x4106c7a8,0x33b7d24d,0x191909a1,0x3764b4a2,0xe893c838, + 0xc429b614,0x4a7fe30c } }, + /* 56 */ + { { 0x2455c7c5,0xe78f3a70,0x70157754,0x5b7636e8,0x7623262c,0xf32c4524, + 0x1bc780c7,0x2c98b11e,0x915ed877,0xd48eaeac,0x199265f4,0xbb04d3c0, + 0xcfa5200f,0x6b52b19b,0x93ea3fe8,0xc46a0981,0xba758059,0xd82c733d, + 0x1896aacc,0xd324bbd6,0xce8ecd51,0xac09a2fc,0x02fc44b3,0x529918fd, + 0xaaa1784b,0xf0c45e4a,0xfe22085c,0x35626340,0xc50c7d61,0x53cbb676, + 0x65126b23,0x83fa1ea3 }, + { 0x10ccc646,0x60ac86da,0x7b0451e9,0x2ce0637f,0x8a088610,0xbbbcf630, + 0x20349982,0x23c19019,0xfc0bcda0,0x707fc39c,0x1bd4fd7d,0x7f4d1f15, + 0x44713bbb,0xd6a64e74,0xc5ac9e60,0x57bdc676,0x37b61169,0x456c5303, + 0xdcf40a1d,0xd3451396,0x4997d2c7,0xf3edec25,0xc2c4a739,0x534ae9a4, + 0x6a6ad2e2,0x1401397e,0x23e95f81,0x20769d4d,0xde98fabf,0xcee007c6, + 0x931c51e0,0x61409779 } }, + /* 57 */ + { { 0x15156623,0x3ddb32db,0xab7a67c2,0x68137fbc,0x6f19e3c2,0x26011f50, + 0x89924c61,0x34218b02,0xc6804c1c,0x492a0b0f,0xafaae6a7,0xd65be706, + 0x0d01be61,0x3b13d23e,0xf87f4c69,0x44545b47,0x04dc1aa3,0xd42236e2, + 0x3c5161ec,0x6135261d,0xbd88bc07,0x1eb46a63,0x1599d720,0x78c6d836, + 0x69baf0f3,0xf6955fe1,0x17072820,0x467eebd6,0x3e3a340a,0x2f1b8a2a, + 0x2d0b5f88,0x636dac76 }, + { 0xb4c80af3,0x94280db9,0x4e3892ab,0x9a189cd1,0xd1477ddc,0x26e702e0, + 0x68f9f14f,0xe91aee38,0x80baa0b2,0x2864f63a,0x8b714a29,0xacd81f73, + 0xc5fe7cb6,0x30e1b870,0xb10837fd,0x883ea1c3,0x6b20489f,0x2da27953, + 0x58a2da5f,0x3aeb2a68,0x03a8fa14,0xe2330bf2,0xdc70b1c4,0xb5c488b5, + 0x299678f4,0x0a78c4d9,0x25df675c,0x233bd098,0x7b67d368,0x37b5c076, + 0x4d0bef3f,0x2f6dbdfe } }, + /* 58 */ + { { 0x2e4da7c7,0x2f8472fd,0xae677932,0x708cfc91,0x3dc268e2,0x364af08a, + 0x799a2424,0x0f10dfe0,0x71d58bff,0xef912d58,0x988962e6,0x6bf35dfc, + 0x5f47ea0a,0x28b96fa9,0xaad308c1,0x734a79ea,0x9f437bba,0x95730337, + 0x6cf54f75,0x002cbd8e,0xe7632eec,0x47606dcf,0x53193104,0x404b5ecb, + 0x0acf729d,0x0ae0897c,0x3bddf1de,0x89628b86,0xf87d7448,0xeced154e, + 0x458d5d4e,0x5cb6e197 }, + { 0x008c75ed,0x98cef197,0xf6eeaaf8,0x7cf49d3e,0x1875e96d,0x1d6f9e02, + 0xdd9b0d8a,0xfcec2cfe,0xb9576daa,0x38a61cfe,0x36a7dbb8,0x10003f39, + 0x23b814f4,0xb37c3868,0xb80e3153,0x9fb66dcb,0x059847a8,0x9e7e2eba, + 0x35a72770,0xa4ec63fd,0xfc9e0ed0,0x311f3d91,0xd515baa4,0x3c1dc094, + 0xa08cd4e3,0x75a06ebc,0x2ed5eeaa,0xab617238,0xe1f52c1f,0x2e82bbb0, + 0x5175d6e5,0x2149d630 } }, + /* 59 */ + { { 0x5f9311f6,0xee1a8e6f,0xbabc1f85,0xc97e3c9f,0xb494209a,0x4fa7c52e, + 0x19774fe1,0x04c2f51c,0x8555844f,0x5cefd122,0xb5873ab3,0xb53862a3, + 0xcbed19fc,0x768efdd6,0xee58469a,0xcdc12479,0x3d80c09c,0x11237e31, + 0xc044c28c,0xdd74a290,0xbd47e287,0x9ee6517a,0xad0ffeef,0xc2421228, + 0x818d281f,0x4273088f,0x43ec0de1,0xebc744bc,0xb415bd73,0x5b26eccf, + 0xcb07c26c,0x14e2f350 }, + { 0x4216946b,0x548d2a10,0x7a4bd92d,0x6e801f07,0x43695160,0x5996d0a3, + 0x63a197c9,0x0f1b5c2f,0x061f77c9,0x79da3c4f,0x93ff7b22,0x1c1cd634, + 0xa234123f,0x5e61b650,0xf284033c,0x826b34c5,0xc2f34214,0x718b90e8, + 0xae806ec5,0xa5f35620,0xe324a9b4,0xa2fae345,0x8b53cb51,0x8c0bb95e, + 0xf9965778,0xc94f6ac2,0x6b9def32,0x07ec607d,0xd0ed8f27,0x63bf1dba, + 0xdcb61e4f,0x58537e02 } }, + /* 60 */ + { { 0x64f80ba2,0x1f64b064,0x0559a45b,0xe8e055e7,0xf1f4b634,0xc3262b34, + 0xde8c8482,0xef4f7d5f,0xc30c780a,0x9d55dea0,0xcfa1e693,0x1740afb9, + 0x7460c34b,0x2cfe6a66,0x1187c1ee,0xf6695941,0x5f974d94,0x1382f277, + 0x004549eb,0x1ca0ace4,0xbabded02,0xf8244b3f,0x4e3653ea,0xc36f4d06, + 0xc55c5f83,0xeab9f0dc,0xacebce90,0xd93b9cef,0x19061425,0x16658e72, + 0x82d7970d,0x4857835f }, + { 0xd2576210,0xdcd525bc,0xd51b5443,0x9f378aa7,0x1bd83994,0xfe97bf17, + 0xf38ac621,0x930d0f63,0x818408cc,0xaf8f2c17,0x260f53f6,0x2692c87e, + 0xdb0a75e4,0x0ee45407,0xffdb1b37,0x0ec47ae5,0x7aa6a44b,0x769129dc, + 0x2e40b75d,0xb6f932b2,0x95ef3b77,0xe06764d0,0x68bc63e8,0x28fd47f5, + 0x9c0014c0,0xd1810494,0xd7995d8e,0x90e2d3fd,0x6c2a85af,0xeb39a05d, + 0xa21f3128,0x6c0277bd } }, + /* 61 */ + { { 0xb509e7ef,0xe41b7086,0x3d7f9f91,0x8842ec7b,0x5526b88b,0xcd285f94, + 0x051dd0ab,0x6e44e064,0x774f1ceb,0x90198c10,0x123e661b,0x6ecabe98, + 0x32f647d9,0x44811136,0x26c52aee,0x1dd82b45,0x939dc9d5,0xd650907f, + 0xfcd455bf,0xbd5eeef2,0x8d2e5d7c,0x7815a4dd,0x88bc9f2a,0x5ad4ec92, + 0x57a3b322,0xc6f10d0b,0x20b9cbdb,0xe8d0c1e7,0x9b774ee8,0x5a0b071a, + 0xf22fcf8f,0x3067bc9a }, + { 0xb7ca9326,0xe0e589f2,0xb1224f63,0x17a106fd,0x747a57bd,0xb2354521, + 0x62b0882e,0x2614982d,0x4391ffcf,0x7f3af544,0xa84e440d,0x1aaa337b, + 0x941bb071,0x28ea37b0,0x2e4a7f54,0xa957dcb4,0x1a6ad5fb,0xe7ab662c, + 0xf7c36a20,0xd135e381,0x9baa0b6b,0x42e7980c,0x94e4671f,0x4237030c, + 0x8b0922e3,0x24cc63ff,0x445a589f,0xd10d5279,0xa870ff6c,0xbb99d316, + 0xa996c195,0x390c83ca } }, + /* 62 */ + { { 0xffc4a73f,0x50d3fa82,0x3bd53303,0x2665d635,0x264bb77d,0x80a06f8a, + 0x22d73d84,0x81c04a6e,0x0323b8aa,0x2409cff5,0x8c4c4d5a,0x31dce217, + 0x0c0f9c19,0x374aa80e,0x00186bb8,0x0b25a387,0xaaf1487f,0xd0b77a10, + 0xab498de1,0x15f39ad5,0x1aa0c116,0x92e32da6,0x96e25ce8,0x228e3dbd, + 0x5e8646d1,0xb57c88dc,0x267b1c68,0x672b1164,0x600bdec5,0x5d0d807f, + 0x223e573a,0x3ea4007d }, + { 0xa595d0a3,0xd76debd0,0xaff0b3b4,0xa6bd76cb,0x9b1bdb97,0xbf2c154f, + 0x4c714c71,0x62b19ab4,0x221af663,0xc9bf33b9,0x8c941ef6,0x23d87c49, + 0xd79f0f6d,0x255804c3,0x2a7acbc1,0x6f1a1005,0x550528af,0x5dab79d9, + 0xc8d16213,0xfd77a6f0,0xde5e1029,0x40508b6d,0xf95da12b,0xd95ac0f2, + 0x758a8ba1,0x8860af71,0x7160c8fb,0x0b194c83,0xce004d34,0xa40e6c80, + 0x6b14aaa0,0x09f82a17 } }, + /* 63 */ + { { 0xc21366dc,0x60abe588,0xaf75daf9,0x729c0a4f,0xacb93ed4,0x70501fd9, + 0x87a16d70,0xb97e744e,0x98e7361b,0xa42e0a7a,0x28b54cf3,0x1acdaff2, + 0xb7bd9078,0xf087ccbb,0x663250e7,0xda6f3983,0xbaf07c09,0x66d693ee, + 0x8cbaf157,0x79baf4c3,0xdfca99d0,0x5a984e07,0xf26d8dab,0xab4d3247, + 0x7eba36f9,0x4d0be701,0x0e8dd216,0x37bb9e65,0x531c4f03,0x72aa4e24, + 0xb753d85a,0x77d1e984 }, + { 0xd8e62367,0xd9373239,0xb9820cf1,0x3361848b,0x5a9c97c4,0x00c7e344, + 0x14f960fc,0x9a0ec9ae,0x740474b5,0xcf41f0cf,0xece065d5,0xa5eede8f, + 0x9e808610,0xb1de5a4e,0xae0cf75d,0x17c44ae4,0x6b148d0b,0x2fa56323, + 0xd29ff2dc,0x64fa740f,0x88cb212e,0xc605eb8a,0x6a863016,0xf2c771ad, + 0x607b4c17,0x6d6112e7,0x40d49785,0xfe90ec07,0xe256e0e5,0x599be18b, + 0xca54adb0,0x4e6eabec } }, + /* 64 */ + { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41, + 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7, + 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b, + 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5, + 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1, + 0x04ecf056,0x325d2796 }, + { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1, + 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153, + 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c, + 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9, + 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e, + 0xe32a79d3,0x19d48546 } }, + /* 65 */ + { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0, + 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea, + 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df, + 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634, + 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d, + 0xb4e453b0,0x1b3ace6c }, + { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35, + 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630, + 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824, + 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387, + 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64, + 0x192f0a14,0x538ec33e } }, + /* 66 */ + { { 0xa19b56cf,0x193496fe,0x7bb99acd,0x663d77f4,0x57d0a881,0x8f04afa8, + 0x082835fd,0xcced3da2,0x5d82cec7,0x7e21faed,0xf8009c85,0x6e175b99, + 0x2d05a307,0xd9c6e31b,0x81487d82,0x96948d4a,0xd46f6655,0x86ebd3f2, + 0x773ccc49,0x86851aa8,0x8b1640a6,0x3e220f22,0x41a20b75,0x9f06e3a8, + 0x90ac0a6f,0x2cfffe5e,0x8ebeb3fb,0xf5a9b1da,0x6e08e2c9,0x2587d997, + 0x03e9f401,0x6fd60298 }, + { 0x8eb7516a,0x54709f8d,0xbdc598ab,0x83058a74,0x87e801ce,0xd234dd98, + 0xd17b8a96,0xfd0f9d90,0x6e90f6ab,0xaa1e549f,0x5a7ed55b,0x2496ff80, + 0x6c254c19,0x0d9f657a,0xb8962575,0x3cdea49c,0x2dff27de,0xb685a3f0, + 0xdb8bc04b,0x3c50e7fd,0x987236b0,0x904ff0ff,0xbb0d5055,0x494298fd, + 0xe14be8d0,0x34b3386d,0x7c3d30d6,0x7ad34e9c,0xe159fdd9,0x1f2b32bd, + 0xc761e5c0,0x84cfa23c } }, + /* 67 */ + { { 0x8b99b964,0x13bc11eb,0x58e2fc47,0x8e280c0a,0xd4c9a54b,0x870fbc49, + 0xbf6e20fa,0x37a334a2,0xd7c88cfa,0xee583d0d,0xef4af1da,0x05e029a8, + 0x0c2ef8a6,0x6d55e234,0x209e9b62,0x61b6fdfe,0xbb8e080f,0x3b1dad26, + 0x9392fc1a,0x5adbc162,0x0aae3f4e,0x02ac0fe6,0xc2bf4d5b,0x8d99801a, + 0xc282fed2,0x2333f93f,0xb52db33f,0x16dcb10c,0xc55752e7,0x09f90f84, + 0xc84a0d8e,0x287d4c51 }, + { 0x0e9867da,0x5fa58201,0x1a874cda,0x614589b3,0xfbdee22e,0x005e27c5, + 0xe612bda8,0xe357fef5,0x2d3635f9,0x4e0dbedf,0x6f125a86,0x62be70e4, + 0x0d94a2e5,0xa09b9884,0x28b5e5d1,0x7eb99a15,0x751028b5,0x21b9416e, + 0xe06d2cc4,0x1b137fd7,0xfea09845,0x6fa1f517,0xffcecbd7,0x3ba1e966, + 0x832f453e,0xd4c89a4a,0xeca68fa1,0x07b1e2af,0x4bd395a3,0xd0fb4453, + 0xd8ef9e13,0x0132a3dc } }, + /* 68 */ + { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8, + 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699, + 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984, + 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32, + 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076, + 0xb6f8aa25,0x13cbee76 }, + { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23, + 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492, + 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e, + 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50, + 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c, + 0xe02e8967,0x4e0a1ada } }, + /* 69 */ + { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67, + 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198, + 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7, + 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d, + 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6, + 0x9f99c999,0x733e30d9 }, + { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7, + 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a, + 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a, + 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0, + 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492, + 0xb79a5c0c,0x56facb39 } }, + /* 70 */ + { { 0xa3018bfa,0x019165a2,0x9ffad984,0x100c6b24,0x55341a9b,0xbbf1b1f6, + 0x25dc4cc9,0xe6bd1d97,0x2bfffe60,0x52850ed5,0x7e5509ab,0x24e992cc, + 0x4ceb59f1,0xff6c502e,0x1aa7d148,0x2f0b3573,0xe7e3aa46,0xe90c1ddd, + 0xd1142880,0xbaec9f45,0x65be5dd5,0x475cfd26,0x1febce13,0x83abb14e, + 0x80942d30,0x6aba4829,0x297e82c8,0x1e1b235d,0x50d8218d,0xb771cdbe, + 0xd94d6cbb,0x88599266 }, + { 0x155ccaf2,0x08847290,0x7c5b773e,0x8679ebc7,0xb2dd08ed,0xa88b2dd1, + 0x87d475db,0x960a180e,0x6694d02a,0x80fdb6b7,0x3f3f9e96,0x3e8758c9, + 0x4ad836c4,0xbda3f6fa,0x32fb387d,0x9400c581,0x2550200f,0x25a78542, + 0x776ecf18,0x2a97c351,0x566db59a,0x03ebf46e,0x26545eda,0x4743a280, + 0xcf74ab44,0xed169d84,0x88cb3f69,0xbaab931d,0xd8257196,0x70ae932c, + 0xa0c09719,0x797224a6 } }, + /* 71 */ + { { 0x441f3567,0x632923f8,0x2e24bf1d,0xc11c3168,0xb7671fff,0x4b97726b, + 0x7a5e1a22,0x601746a7,0x3addb417,0x53dddea0,0x7f59b846,0x57867a3c, + 0x56cd7ff7,0xb012a987,0xf19ba9a8,0x1bd5fec9,0xf8306748,0x750379a2, + 0xab8c05d1,0x7763445d,0x7903f42a,0x5d7f441b,0xa903e46d,0xc011674d, + 0xadd126c1,0x1b1d3c4d,0x61455b40,0xa2752aac,0x555c356e,0x4da42a68, + 0xd820852c,0x3ff09c15 }, + { 0xf9cb7784,0x4c0a1bce,0x2422f305,0xaec539bc,0x0c414aa7,0x5f40f9fd, + 0xffd42bc4,0xd3aa316c,0x2f358e15,0x42f5a4c3,0xd6e27682,0x00bdcd9e, + 0xf8a5ecee,0x069f789f,0x05e14f5d,0x8078018e,0x8b40c741,0x2bb3e493, + 0x7917f72d,0x5dbc8c1d,0xcc57150c,0xe0eea664,0xc3fa8920,0xa25ecc5a, + 0x1c797164,0x3c21b0f5,0x634ad16b,0x8f09a2f2,0x58391d9a,0x8e730fc5, + 0x4fdfae4c,0x47ef1805 } }, + /* 72 */ + { { 0x3da285e4,0x9965f3d1,0x3a01e3f4,0xba7d4dba,0x61214ad0,0x4738413a, + 0x22397549,0xd3b7d535,0x5a730b92,0xa53dbdcf,0x332d165d,0x3130d92b, + 0x82f97ef4,0x44a28541,0x44dce1b6,0xbf62221c,0x7e2a0ec9,0xbba13858, + 0xcbfad998,0x33f32c8d,0xb5fed44b,0x409e5f3f,0xc66217bb,0x5c328c65, + 0xfcdf71a9,0xb00db69f,0xb8920788,0xa23c2a21,0x3ae6464b,0xf8ab28e6, + 0xb8de0861,0x1a6b6e9c }, + { 0x06af77aa,0xaf6ec2b6,0xa887f065,0x2e60f5cd,0x9f498c56,0x87d21400, + 0xfcbaaf4b,0xdb595b59,0x271ab855,0x0fb592a1,0xd4349b0c,0xa0ce10e5, + 0x887d8c9c,0x9d6187d8,0x154bd6db,0x03ee95f9,0x5d06c999,0x8fe53213, + 0xfb6a64d0,0xf4a7bc30,0x66a4cb60,0x3d22af0d,0x5d37367c,0x16952cef, + 0x997d8e55,0x6f0ea734,0x731732d0,0xb447c70f,0xa9cb3942,0x00ab3034, + 0x28510fd0,0x79dd0180 } }, + /* 73 */ + { { 0x3ac7424e,0x04e0033a,0x60fda4d0,0xdb06b688,0xbcb772fb,0x236a9766, + 0xf297cda4,0x294a8e2b,0xdb013c6e,0x4b0aab85,0x8723a3ad,0x3d2aec98, + 0x13c84a6b,0x0cae32cd,0x70ec169e,0x21888f5e,0x42a88262,0x739633bd, + 0x7b60d9b8,0x68ac792e,0x10769fe1,0x89f2b722,0xd24bed34,0x8f3fcfe6, + 0xa3eb24aa,0xd35efb88,0x484c706b,0xddecfa3f,0x929ece0d,0x7cc119a9, + 0x8d405436,0x87e5ad45 }, + { 0x7d1000a7,0xba99aa9d,0xae823833,0x8b94affc,0xdfb83dc5,0xc8229628, + 0x845a418d,0x2f59fe11,0x5d417054,0xa8b970f8,0x72b71581,0x8918c265, + 0xc0d1dd17,0xe4ef477d,0x3afad7c0,0xb50b4cf3,0x01870a5b,0x21baea79, + 0xbb3a2868,0xc77087f9,0x124a59cd,0x7857531e,0x57f43239,0xed74c26f, + 0x0164c94a,0xd5f5ae25,0xf094bf74,0x6608b7e2,0xfdceea32,0xf4cdb5ba, + 0x990cc045,0x0b712519 } }, + /* 74 */ + { { 0x88d5c64d,0x5a290ca1,0xa7492534,0x0596d749,0x2a00e925,0xa04b0d3d, + 0xcaf7b66b,0x082cd02c,0xecdded83,0x912b50c2,0xff31646e,0x813ce9de, + 0xc75fff95,0x62ae70c7,0x7e2a4615,0x6f6852e0,0x03804fd1,0x320fd7d0, + 0x8218e8d9,0xb1a2a4dd,0xafc645d7,0x4918a6fb,0xe8d9fdbe,0xfb080fa1, + 0x4470b6ee,0x33d4d08a,0x6d974ef7,0xd2ba2077,0x69dae5d2,0x8ecb95a7, + 0x7d69596d,0x7a3f423a }, + { 0x9a929387,0x362d2ca6,0xcb1c1fff,0xabdb7581,0x7e51b6cb,0xd892ec9f, + 0x3a4e131f,0xee8d8632,0x5bd87561,0x4680e3f1,0xd4e7e732,0xe3a597e1, + 0x5581fefe,0x3cc72b7c,0xca8cae0b,0xf3e77f8a,0x5e2fd4af,0xfcc7d7dc, + 0x21355b79,0xdd3a4552,0xa2c07177,0x546b24f2,0x0689621f,0x415b532d, + 0x3f78163e,0x2be9af51,0x33d7ed21,0x27d63b9b,0x96802943,0xab019ef2, + 0x1623faf4,0x2da5fc55 } }, + /* 75 */ + { { 0xc8a5c600,0x62429cf3,0x3fe33e7c,0xa7a80c22,0x0a57ddcb,0x9ffda740, + 0x925b0c74,0xd1ae156d,0x6b100eb0,0x097a43f9,0xef943c81,0x169e945c, + 0x1128cf24,0xa1f734e5,0x419f0133,0x04387c4a,0x01044024,0xc007868b, + 0x90359cf2,0xe5416abf,0x478d54e3,0xf9c76fee,0x42a2173e,0x66219da6, + 0x9fe30141,0x61e03156,0x93ef247e,0xa0ff5ce3,0x072b6592,0x811792ba, + 0x70c854d3,0x855f0219 }, + { 0x847314c4,0x61fbfb6c,0xeb45b96a,0x97906155,0x6ba2afac,0x7102e146, + 0xab949781,0xed51f975,0xc110c4fe,0x9d2f5b17,0xaff57667,0x7ac8ce70, + 0x6eb244e7,0xe7366a21,0x551c65c7,0xdd1bbcec,0xe1a859de,0xb525060a, + 0x8ba7d2e7,0x7a048174,0xab8ea8c4,0xe1a2c541,0x6fdff078,0x6e7824c3, + 0x14874b04,0x79b49fc7,0x06b1f733,0x22ae337f,0x6f8fe6cf,0x1c352192, + 0x525d0797,0x292236cf } }, + /* 76 */ + { { 0x7d8b29dc,0xcdb8d80a,0x08ea648a,0xd17a2024,0xae92be91,0x7db12c5e, + 0xfda72fbc,0x1f347d18,0x9e760c6f,0x11374b40,0xd8e38d91,0x7361e8f1, + 0x739ac1f4,0x7714be9d,0xb4df5c4e,0xc1f9701c,0x6f72cae1,0xd9138ed8, + 0x6ad180c4,0x1c7fe1f7,0x9e2dbf9c,0xf8c185be,0x7c70c44d,0x835db269, + 0xb0d15b5f,0xf997cfea,0x61e6545e,0x5101445a,0x25184e5e,0x16b06884, + 0x7521e7aa,0x7cfac359 }, + { 0x3c0bc53a,0x81182167,0x7e751367,0x84b5ede3,0xa3657a18,0x3ca255fd, + 0xba1fdd98,0x096abbf4,0xc5da77d8,0x9ce8369f,0xaab342c5,0xf27b9ae7, + 0x972059f1,0x06c91bd6,0x914ecfe9,0xee0dab30,0x93f53f12,0xbb647fbb, + 0xffa57e0e,0x30c38a7a,0x9f2ad607,0x517d06ef,0xbb99dcc9,0x49728d87, + 0x446080a1,0xb0034af1,0x12b9c17d,0xcc810c3f,0x772a22a0,0x7225f14f, + 0x1ddf82bd,0x6ce3dc7f } }, + /* 77 */ + { { 0xa4397830,0xc07cd835,0xf4733306,0x4dd9290c,0x29989e8c,0xdd35d3a8, + 0x563d8152,0x79902559,0xe87de61b,0xf278d911,0x1024e35c,0x9c7340c7, + 0x4a0d0e59,0x2d444461,0xf32626a1,0x63e7608f,0xc4c9baa9,0x627a37e9, + 0x76fffd25,0x0c56dc51,0xcef2a1cd,0xcb6defc8,0xefc559d9,0xcbcc0d56, + 0x041cb692,0xe45f3fc5,0xe5161e09,0xcd05c239,0x5c3b559c,0x2a731ee9, + 0xa3d0a16d,0x85151122 }, + { 0x86ff19e2,0x782d0335,0x1da28603,0xc2c60daa,0x557c7eed,0xb2e78cfe, + 0x1bc4e8b0,0xa8f6f984,0x3df35c67,0xcc1f9b4b,0x4764462a,0x96e13603, + 0x7c7ae0b0,0xbf910b97,0x51435956,0x27c7f305,0xf631eae5,0xc14db15c, + 0x7e69b34c,0xa51d6142,0x5fc12ff2,0xdec82851,0xfb887162,0xfcceae13, + 0xde1488bd,0xda332ac1,0x2ee3e74c,0xa20374e2,0xf0ae069c,0x597ea1a1, + 0x77bdec04,0x8b1159f2 } }, + /* 78 */ + { { 0x2f961d30,0x4af71a44,0x7ac7248f,0xbdf968a8,0xb1a906cd,0xd32df87c, + 0x04abf925,0x00c10e26,0xb9f04d4c,0xb8711759,0x939705da,0x00d54e60, + 0xc9f80849,0xf7587433,0x6a7a2375,0x2e9abade,0x94ac17ac,0x5676d478, + 0xc202d99c,0x4ca0525b,0xabfae73d,0x95b8bcad,0x3405991b,0x2371ed38, + 0x458a99c3,0x2b69e47a,0x2b78c866,0x7cac0b18,0xe0232c7c,0x6ceaa79b, + 0x588f7459,0x0bd86433 }, + { 0x7e734189,0xdea1a8b4,0xcfe5fa17,0x52c5ac88,0x11437664,0x444a4d4e, + 0xaf9e9750,0xc2522308,0xd30c6b3b,0x78b1d0c3,0x4c6df477,0x2edae5f0, + 0x2ee88dd7,0x53131d9a,0xacc93e34,0xc4e380ee,0xa8db0e8e,0xd499b1ac, + 0x7f5d49d7,0x77348c16,0x1556ccd7,0xc9663257,0x2611d13d,0x65ce0e8c, + 0xb5a2fdcc,0x2c95fe66,0x8658faa1,0x26698832,0x31c32c98,0xda87d1f4, + 0xfcd91907,0x46650598 } }, + /* 79 */ + { { 0x6b4a5efa,0x4c6c13cc,0x1d07b265,0xc481989b,0x8bdc69c0,0x10b966ce, + 0x2c2531d4,0xf54cfaa2,0xcad0a100,0xcb5f1808,0xee5da449,0xbeb52538, + 0xbedd83cc,0xa6240085,0xd6255c78,0xe792dacf,0x2062058f,0x88371906, + 0xed1658c1,0x96615e83,0x7d28d542,0x4b549b27,0x83b75df3,0xeaf127db, + 0x17fbb942,0x4f60df6d,0xf6f7c930,0xd08631db,0x6018789f,0x17c38f98, + 0xb9a9280c,0x0c43574a }, + { 0x1d20cad0,0x76eb324c,0x8c61108a,0x90decb09,0x6f06d36d,0xa6e9d39c, + 0xbc0da197,0x6cd978ba,0x507ac5ce,0x5948b1c0,0xc5497eb5,0x2bd47164, + 0x4d5914e3,0x2a9c4c0f,0xa759f03c,0x772c5046,0x69ac847e,0xe7d7328a, + 0x3048b330,0xa8d57d0c,0x40f7bace,0xe60034e0,0xa85f1790,0x823d9193, + 0x5c859736,0xa6e9b66c,0x679e1022,0x22ca2c7a,0x09023fa4,0x00e7a19c, + 0x2726d5b9,0x324999f1 } }, + /* 80 */ + { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6, + 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c, + 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e, + 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb, + 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52, + 0xf18c2b91,0x57ea2b4b }, + { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a, + 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee, + 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069, + 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b, + 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927, + 0xea7935c9,0x60480b46 } }, + /* 81 */ + { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7, + 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117, + 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5, + 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0, + 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb, + 0x9a8f88cc,0x0774a0d3 }, + { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f, + 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61, + 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91, + 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df, + 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303, + 0x2432014b,0x08151954 } }, + /* 82 */ + { { 0xfb7b2108,0xf9236d89,0xad75f9aa,0x3ecc83cc,0xb4e1da11,0xf7c72b15, + 0x0315c362,0x552aeaef,0xf272fe3f,0x11e140ed,0x87843ee8,0x99d79bf6, + 0x1d9bb25b,0xce6b54fd,0x5b1bad74,0xb20b0e21,0x5b84c90d,0x54a0214f, + 0xfca6cec9,0x459bbf52,0x9e4df76f,0xe363c48d,0xd64cf17e,0x3045f84e, + 0xf62ada48,0x8402a167,0x6a74ca01,0x2c9e1bf3,0xf691c42d,0xe8cf9d41, + 0xc2c4b874,0x5abf2178 }, + { 0xf3b3bccd,0x4777966b,0xbe3e0caa,0x0047e0f0,0x8c7d5043,0xcb8383b3, + 0x946fd5fc,0xe77e3baf,0xe9ec0e87,0x79baa785,0xc8a18d25,0xd83c557c, + 0x25befcfe,0x9b96e5af,0x98c71b61,0x4f05d15e,0x77e62da1,0x081f991a, + 0xcbaa3821,0x1c6ec781,0xe54d9bfb,0x7522f65d,0x44ed1430,0xf5d05573, + 0x95cafdda,0x3035b31f,0x6378f5bf,0x47e67f43,0x5270b9d9,0x029f7cad, + 0x4d916a48,0x15ad1587 } }, + /* 83 */ + { { 0xaa588ae4,0x00de2ece,0xa371a232,0x552ebc58,0x71230444,0xd00ea934, + 0xe4b1832d,0xafbfa67d,0xb689e843,0x29216341,0x61f4e2e8,0x1f96bbbd, + 0x04c29dc5,0x95420684,0x42317fd1,0xc7fe3827,0x63483162,0xe0a0aec6, + 0x0700184f,0xfc2b94d1,0xfe1fbd85,0x07219973,0xfb074352,0x648b6ab1, + 0xc46e5392,0x23bbdaad,0x00fa56ff,0x0db8dd1f,0x866725f6,0x104815eb, + 0x52e81963,0x3f9c4cca }, + { 0x32ce637e,0xff36b297,0xf5d25cdd,0x81a15f2d,0x8b02ad97,0x1a1d052d, + 0xcfbab3e9,0x2e5f3bbc,0x614eeb75,0x60d2cbd7,0xcd5a793a,0xd4491843, + 0xcdba2144,0x2242cf75,0x88b99766,0xa20705e7,0xec77e132,0x64e12cc0, + 0xb61a9b05,0xb1c14df6,0x74825b5a,0x8fd97f04,0x3da31223,0x95604821, + 0x4d30c70d,0xde486727,0x1c12ee69,0xbcab8f15,0x668d893d,0x5dc638b4, + 0x223f574b,0x6479dad6 } }, + /* 84 */ + { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28, + 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20, + 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1, + 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55, + 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7, + 0xf0860497,0x1fe09f94 }, + { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c, + 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a, + 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994, + 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa, + 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c, + 0xdb62526a,0x4de95786 } }, + /* 85 */ + { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96, + 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5, + 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5, + 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc, + 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e, + 0xe636980c,0x1c94418b }, + { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a, + 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4, + 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98, + 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474, + 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422, + 0xb55235ba,0x611bfbb2 } }, + /* 86 */ + { { 0xf00ad2a1,0xbdbaa55e,0x14a290d7,0x29efa85e,0xe92b1694,0x3b4a4768, + 0x11ec8130,0x67111bcd,0x88bd27b2,0x0e425702,0xd9a03c06,0xf28cf2a3, + 0xf318884a,0xbb7c8d2d,0xe3aaeb20,0xe2ea1462,0x43b85d77,0x33535804, + 0x554ee9bd,0x81ee4482,0xe6aa198f,0xeb2eee9e,0xc26c5944,0x7a5aa804, + 0x82ab167c,0xa0ef2da5,0x02fe21a5,0x5a2ab476,0x3370298e,0x169cb3b8, + 0x0eb3aa8d,0x86e6c544 }, + { 0x0b793d9b,0xede03321,0x1ddb5ece,0xf79fade1,0x68930b64,0xf73fda92, + 0xfe4fd1b2,0x06aad97d,0x92a4dc88,0x073a5b1d,0xbc976d75,0x8af8cbd8, + 0x63ce26c0,0x60b4abb1,0xdcb1fb06,0x9c8300a9,0xda95b3d3,0x335a594c, + 0xb37eac87,0x1f97d7d4,0x20eefaab,0xa3d2eba2,0xf3e828c8,0x3258c906, + 0x85ab7781,0xc832616f,0x8c28b617,0x72597192,0x3233b82d,0xcd7196bc, + 0x19fa126d,0x83867eb9 } }, + /* 87 */ + { { 0x22474edb,0x774fe73e,0x1a84e1ae,0x2a766394,0x9c6dd6e3,0x270329ad, + 0x14f8bf5d,0x00c4a415,0xd2267b90,0x3ce2ea37,0x11d24fae,0x12753015, + 0x263a1b78,0x7c14d854,0x1ae0b206,0x20c8401b,0x081f49fc,0xf32a011b, + 0x959c6df8,0x1e8123fb,0x800e1d06,0xa328dc7c,0x24259a9a,0x5876a378, + 0xb7ef6c37,0x23ada8b5,0xa93d4c9f,0x023f6b6e,0xffb6389f,0x89f5414d, + 0xe628b39e,0x4b26bba2 }, + { 0x5d318454,0xd30b1cb4,0xd7436cb6,0x123b749f,0x568a7461,0x3110c726, + 0x1c84fd1e,0xc85de123,0x08403d55,0xa5f8d6e6,0x9b1fabf8,0x395b6e13, + 0x3cfedce0,0xfe6d68c3,0x94b91110,0x1d90381f,0x2dcc6eb7,0xf0a8ea81, + 0x7e90ca2b,0x59e80413,0xc8a25c5a,0xbeb5fc07,0x5d84663c,0x009c253a, + 0x910b6a7c,0x00b15073,0x4108f8d5,0x8607da4c,0xcb901e65,0x02c3d9c3, + 0x2c9615c6,0x4d697bc5 } }, + /* 88 */ + { { 0xefa8fb40,0xe0db1ef0,0x5ba3989c,0x29021c5b,0x809d19df,0xa8d6fb15, + 0x4c1219e1,0x6b787b73,0x14ef05e2,0x6417e168,0x8f9796e2,0x449342db, + 0xbf84421b,0x2f878a5e,0xe94a4536,0xe71916d7,0xae119693,0x9818bba3, + 0x5768804e,0xec674be9,0xf8424f8a,0x0a26074c,0x466ce6ab,0xdbc93b9d, + 0xc920078b,0xb3f15a98,0x3870f1a3,0x9d10fd0d,0xe4e785a7,0xa61241d9, + 0xe6c8cd80,0x76ca87a1 }, + { 0xe02e48b7,0x4357fb56,0xcc09e9c6,0xfbd14b13,0x24069cf0,0xdb5f2435, + 0x2c3b01a9,0xf878165c,0xe6956dad,0xe549e7c4,0xbbd60b68,0xf2fe9538, + 0x059dc653,0x952f856b,0xb377fe9b,0xd3f60225,0xbfe908c4,0x6a0c7328, + 0xbc8f5f2d,0xce6aa2d3,0x24425050,0xf7213443,0x3d3b3ce5,0x17e1266a, + 0xc1677512,0x75b5e43f,0x37fb894a,0x15927062,0x2be3e375,0x15260753, + 0x6da3b7be,0x27e7f2c6 } }, + /* 89 */ + { { 0xe6a15883,0x638f65ad,0x66afdb33,0xd4a7e68c,0xd3f12de5,0x6207b6ab, + 0x37b87810,0x1c6ff950,0x64acf6d3,0xc0d44cb2,0xf2be78c2,0x163ac601, + 0x1636980e,0x1c63cc5a,0x95c9349b,0x3e92cfe8,0x41ec7220,0x7738e0d8, + 0x2d5fa961,0x6169d764,0xc3e028e9,0x2aa776c1,0xb16d5409,0x93dc5646, + 0x706df4d9,0xa0b27fb5,0xce9c6b97,0x9e991170,0x53c85f40,0xea8e42be, + 0x83246528,0x02e96437 }, + { 0xae78ea1f,0x91540add,0x7b670e96,0x51a1b74d,0xf7006826,0xf9936441, + 0x7d7520c7,0x8f97d6ea,0x69ce12e1,0x0faa6a02,0x79208342,0x2590aca8, + 0x75614436,0x7a483863,0xf381408f,0x07c6149e,0xd7853406,0x733bf584, + 0x9abbb6f7,0x8761b010,0xf528a09a,0xe4eb249f,0x2e00ae3c,0x08781ed8, + 0x2178effa,0x864c1b25,0x9d513a7e,0xcc1e62a2,0x1919062f,0xedb8b94e, + 0x4f16527d,0x739f53da } }, + /* 90 */ + { { 0x924adc5f,0x7a5f4a88,0xa818f56d,0x95646c16,0x7795f954,0x0ec49129, + 0xd19c5400,0x2b48753d,0x205912b4,0x16fa236b,0xe87a4946,0x6b3d65f3, + 0x045fd066,0xa7174a01,0x12a5e140,0xb6350313,0xa96b8623,0xa79c4b44, + 0x9ab003d5,0x7a339d65,0x3826f31a,0xc72f30c6,0x6f7090cd,0xb4e7390c, + 0x906ebe24,0x59ac6c36,0xbba4505a,0x39a7f06d,0xc58c413a,0x839991e1, + 0xa20e0e84,0x020c23ff }, + { 0xafc74661,0x120e4ada,0x277fc065,0x37bbcf63,0xb6dce799,0x41049cf6, + 0x7b161ba1,0x5b8d6b53,0xa9610fb2,0x22218431,0xdfdde769,0xde9ec9d1, + 0x42d80630,0xd32bfa4d,0x6244df4b,0x3885702a,0x45592dfb,0xcdedd1ed, + 0xfb4e01b8,0x0e1df45b,0x86e215b0,0x8f4bded2,0x6a937e6a,0x80935487, + 0x8130f723,0x415278ba,0x38a821f8,0xc6dc4692,0xfd8b4f8a,0x2207b119, + 0xf9269cef,0x76e7bf53 } }, + /* 91 */ + { { 0x27ebd187,0x5f128428,0xb65aadbb,0x8d3320ab,0x72258695,0xb042765a, + 0x8f0986ab,0xda3f33f9,0xaebff503,0x411807a7,0x825f71a5,0x25c776ca, + 0xff7df24b,0xc0de7bed,0x165f1fb4,0xda8b0f42,0x731f3ae3,0x5f3ff737, + 0x193e0a52,0x4cd1d7e7,0xb6b3ba46,0x8df84aa3,0xaa1f3782,0xba84b897, + 0xe7733ac7,0x6e7960cc,0x50981a21,0x4d46d6ab,0x7cbb80ed,0x1ec12c25, + 0x2b96ef09,0x79e7ad27 }, + { 0x8f30caae,0x3cd970dc,0x0a6ebef4,0x85cabcf1,0xc714616d,0x63c1863e, + 0x519e3a98,0x1c50db0b,0x64cb13d6,0xf39b8963,0x22547b69,0xdf67d81f, + 0xd67db0cc,0x7157abb9,0x889491b7,0xccca25ba,0x7a27e0dc,0xf689207c, + 0x0fd43281,0x34ae8fbe,0x5720ec09,0xa5d91f73,0xcdfd7bed,0xb2f61909, + 0x4a039e32,0x1ec10232,0xdb0d8fdc,0xd3c3d65e,0x4fe5005d,0x32c916c8, + 0x4c0bea94,0x7f8c37ac } }, + /* 92 */ + { { 0x43ac05e5,0x33ec1e54,0xcd8d3825,0xda4a4da4,0x88bf9e2b,0x86d88c0b, + 0xb53811dc,0x34d71dd0,0xa3c3aba4,0x655040d2,0xb61611be,0x2bc40949, + 0x279a4fa0,0x1c2d426e,0x3b065ac3,0x535a5aa2,0xc52ea890,0xdaa8a32f, + 0x9fddad22,0x5a5deca7,0x2ab3b26f,0x911f05fd,0xf37cd81e,0x5dace7db, + 0x90d16b8c,0x0e0e44e7,0xe4f5894e,0x15e68aed,0xfc92a74f,0xafe04999, + 0x970e7c2f,0x1d7703aa }, + { 0x3f0062a9,0xa8a4c81d,0xd96a20ba,0xe31eb2b8,0x864bd101,0x66dd98df, + 0x4413b614,0xba05f592,0xe9a555f8,0x51a67a0d,0x2e4b52d1,0xacc2f097, + 0x7184ab23,0xab5daaec,0x7c7f691b,0xce08b43e,0x76c427f4,0x520e530b, + 0xe423ebdc,0x7d352069,0x34df14ce,0x6b5e39e8,0x446305ac,0x3dcbf295, + 0xfe34cdc1,0x682cb2e1,0x111f5afb,0xd4ac45d1,0x47f296f9,0xc5ef63cd, + 0x93c20871,0x0a2c40ec } }, + /* 93 */ + { { 0xaf5747db,0x09bc384f,0xc06ab86b,0x3bad6086,0x9e7c1547,0xa406882e, + 0x55977abf,0x2d5326d1,0xda81deb0,0x063a9a05,0x524b6111,0x9a86e4a7, + 0x4ab2eb90,0x1402f87a,0xd5c600ba,0x7d0721d4,0xf289fdbf,0x1a2fd9a9, + 0xecde6f07,0xf5dce66d,0xdab9fa73,0x62171277,0x6c474bab,0x6d2dc49f, + 0x76eed033,0xdc017e1f,0x4da825d3,0xb97175c0,0x54b05e43,0x6c297e3d, + 0x56c9c87e,0x2efb4546 }, + { 0x8b21c064,0xa4712b00,0x4a70629e,0xd186fe42,0x9b74f0af,0x6435b340, + 0x7ec9e629,0x6965aa43,0xc4c60d08,0xdda14673,0xbf3057aa,0x0b656670, + 0x3ce86f60,0x7f05e840,0x04401a16,0xc05073a9,0x294e607e,0x16b1e638, + 0x69cf7046,0x20783252,0xe8ce7d3a,0x2941141b,0x7577053d,0xd38ad8d3, + 0xcaa6630d,0xdba68fb3,0xe9504350,0xecbeaff1,0x1d2d760b,0x9f5166d5, + 0x462891e4,0x337532ce } }, + /* 94 */ + { { 0x3a00bb9b,0x3f111853,0x45f66685,0x2d2ffbae,0xd4aee24d,0x9ae11a85, + 0x0341856e,0x18ba1e1b,0x2731349f,0xa9ac8178,0x545715b5,0xc13dfd4a, + 0x5daad2ea,0xa5f7423c,0x535b76a7,0x30a483b9,0xff873e9b,0x92e9ada4, + 0x723a1055,0x15662d84,0x8edac4e0,0xb935497b,0x39d8fa70,0x61b6441a, + 0x40d1589f,0x1541d756,0xf0a05f0a,0x62994237,0x6bb28908,0xfd8b0034, + 0xd4cd32bf,0x192a2b5d }, + { 0x365ced07,0x63576628,0x05de1d1f,0x029f32fb,0xbf40a7aa,0x6d17b9bc, + 0x9bb50a47,0x1b1b2a08,0x795a6278,0x9389abbb,0xb34fc19b,0x52cff60f, + 0x387d8739,0xf3ab9492,0x6920ccd6,0xa8f053e6,0x63a9b4f0,0x3ef2dd4b, + 0x51e82129,0x9ab0ede1,0x0838bfa1,0xafba0c0b,0x9ffc11be,0x2bd5a7ac, + 0x95cc0878,0x058bfd95,0xf8c2f0c6,0x686d48a3,0x1d9b31ba,0xc33abaaf, + 0x3bc0c268,0x632e2289 } }, + /* 95 */ + { { 0x15a1ccca,0x1c851d20,0x7e522bc3,0x4efe290c,0x18eab053,0x0b741d55, + 0xbc85e217,0xae656197,0x01cf8b29,0xae13141e,0x66948478,0x2e2cb593, + 0xc31bd8ae,0xeb57bb0f,0xc264e788,0xdecef5d6,0x9cb96d86,0x6fa856cc, + 0x279183da,0x2db16813,0x383d796a,0xf03f3820,0x1d0c6fed,0x58a456ff, + 0x8a6abd9b,0x25589805,0x83f96f19,0x339f52c5,0xda7e9ea7,0xcf6ded8f, + 0x5d1ccd45,0x68c3d9c1 }, + { 0xe6b392b7,0x67e26265,0x775d9509,0xcec1d9bf,0xd76514f7,0xe16abcd4, + 0x0de72e1c,0xd86f59b2,0x1adfb033,0xa66e43cd,0x05e457cc,0xdb344340, + 0x5681daa2,0xb67a7916,0xf0114731,0xc32e7bab,0xd3b1e961,0x066fe16e, + 0xf63d26e6,0x924e298e,0x541add6d,0x9bea0dd8,0x9982f971,0xef9500df, + 0xc5f076ac,0x5c876e63,0xb23d396b,0x55e12ae5,0x2ec6747a,0x09efbb36, + 0x233286a5,0x8f2055ee } }, + /* 96 */ + { { 0xb82c1af0,0x4a4ab9e3,0xf2cae264,0xfc65e9e7,0x60187d46,0x4feaac0a, + 0xe393b363,0x27d3f335,0x819bacce,0x9c9f7c00,0xb8aa6611,0x3f7418b5, + 0x372aae95,0xffa94557,0x8db38589,0x937d7804,0x6f1fbc1c,0xd10c86df, + 0xa2f0a0ce,0x48aebd89,0x367439eb,0xae5d5fa2,0x3f17d2d8,0x103a6a0b, + 0x411d9894,0xf233f68a,0x218b67a2,0x7fece8b3,0x2319bf06,0x0422540f, + 0x340d322e,0x1292c8c9 }, + { 0x0386463d,0xf5eb5587,0x0371d97f,0xd4bbc2b2,0x0b819c5a,0x1b364571, + 0xcf04ad41,0x0cbb42d6,0x66939ec1,0x5d819c76,0xa01847e7,0x8745ac13, + 0x1c7232e4,0x4f704b02,0xacb05780,0x2c9e58a0,0xb561e295,0x9523b8b3, + 0x79f9ba35,0x3384df00,0x1eaa9628,0x78231fc2,0x8aea2b90,0xa2eac54f, + 0x30d1c263,0x8075ed77,0xfb339000,0xacb44ed5,0xf011293a,0x92546ac2, + 0xeb821764,0x7c78762b } }, + /* 97 */ + { { 0x067902b6,0xb8f7d6fb,0xd1735980,0xb2823a43,0x59741ddd,0x062cfb12, + 0x4033f95c,0x6e391b07,0x68589b8c,0x3831d0a3,0x522290f2,0xe3474d49, + 0x222e1f3a,0x4dab14d6,0x53f08d39,0x8f00fcde,0x707f28f5,0x559917ae, + 0x068e607c,0x166aa0ba,0xd7e1f824,0x602713e7,0x4d6a328f,0x7c255540, + 0x9890cd2a,0x0d2e3264,0xeca0b20a,0xf2207944,0x52f4e09c,0x5c98dc07, + 0xd84de81d,0x69403504 }, + { 0xe5407206,0xf8b7b366,0x0d88fa8c,0x1ecf54cf,0xf7272e6f,0x6fefe548, + 0x81ab4468,0xd6531372,0x4e474408,0x52cb5f0e,0x6490737f,0x9e426b3a, + 0x4980d071,0x2576c19b,0x0f272caf,0x91f34628,0x468f31c9,0x78e60a4f, + 0x90844d89,0x8776a329,0xb951582b,0x8a55700c,0x14b1adbf,0xab1af365, + 0xfbd343ef,0x22ebff92,0xb7d81f34,0x32f9fb01,0xba6b30e1,0xad850e06, + 0xbc5f9546,0x6da9e027 } }, + /* 98 */ + { { 0x5c9490ce,0x21eee4c2,0x0df68381,0xa96ec4a3,0xa4a9368e,0xe6c607e0, + 0x4bc262f3,0xd8b0492a,0x460c34ff,0x0846a210,0x28df33cd,0xf7ff7a64, + 0x21827612,0x10c55044,0x149bcd01,0x9d25fce9,0xcfc613dc,0x725611cd, + 0x97f51ce5,0x159f7e88,0x4e8c08b5,0x3fa3bf31,0x75e7538f,0xea156115, + 0x91c84020,0xd1e0a951,0xcf02ad0a,0x0d2268ba,0x058b8e5f,0xa04c6ac4, + 0xb3515912,0x773b40b9 }, + { 0x3631cfd2,0x00ff2cdc,0x807737bc,0x14c4c2d3,0x338a5270,0xd600616a, + 0xb32cabde,0xd0e3306d,0xa70b17ca,0x336738ea,0x79f353ee,0xf2f4aa8d, + 0x576f3ad3,0x712f6ad9,0x89b2bce0,0xe4279852,0xda92ca30,0x05d8f94d, + 0xd8492dd9,0x9891d475,0x4d15e4bd,0x3e06a5ca,0x254eabbd,0x4725d4eb, + 0xc0ed513c,0x31394ace,0xbbfaae6c,0x7e0f9859,0x833fd137,0xdc125546, + 0xc56c4f75,0x12b46385 } }, + /* 99 */ + { { 0x932951de,0x810dbebd,0x5aa69c94,0x96959d42,0xecb2f08d,0x5fc49c04, + 0x2250b82c,0xac74f0cc,0x3aec4e1d,0x96a439a5,0x90499acd,0xc33cab9a, + 0x54d9b3af,0x2fccde66,0x3863ae8b,0xf4af285c,0x46febf88,0x2373373e, + 0x3c9ab7ed,0x751d672c,0xfe12020c,0xc1c51130,0x52f3e56e,0xad82402f, + 0xa4a64a81,0x3489ab7a,0xd9f163f2,0x0a1fb661,0x0e553317,0x17c69be1, + 0x7d88d417,0x61c1935e }, + { 0x3492ae43,0x2e722d9b,0x0538f05a,0x1ef89d95,0x200aab63,0xae77e588, + 0xeba4b117,0x2872c120,0x3a461cb8,0x5c2432c8,0xcb938f26,0x315b3434, + 0x8c4c7dc0,0x05bf2ac5,0x596b378d,0xd2e501dd,0xcb890c30,0xa8506c9f, + 0x7c361f0c,0x3d0af461,0x5a35cbae,0x21f7b718,0xf3fc0138,0xbd1035f1, + 0x8b248edf,0x74628af5,0x48c9cae0,0x8d6421d0,0x2ca18773,0x75e3da39, + 0x71d3db94,0x27ad0df2 } }, + /* 100 */ + { { 0x305b5aed,0x9e3bda79,0x5998d6a7,0x2c67d4a4,0x0f7eb700,0xc855e1d3, + 0x147d1c44,0xc18a7e9e,0xc89540ed,0x3ea99618,0x7e6bfd20,0xa53be20a, + 0xecc14437,0xc9487e64,0x34ef85c6,0x72979207,0xd5e1ebd5,0xfa0d4e71, + 0x4d48d6b6,0xfda2b1e6,0x66e200d4,0x782a1e05,0x5a5366a1,0x2a3c70da, + 0x1a473738,0xfe3fbd2b,0x7fe020e8,0xd7ef8c06,0xeacfb665,0xec686fde, + 0x6dd1542f,0x5d9b5e27 }, + { 0xcb3e472e,0x3637c5a5,0x30a1405e,0x2153d927,0xb4498558,0x009992e5, + 0xf39a0851,0x18f00ccd,0xb5c6c560,0x26237c11,0x1343540e,0x418ed408, + 0x7e7f3184,0xfef7cbf0,0xbf48576b,0xecd92366,0xbc94c91a,0x1b75be1a, + 0x4a162276,0x8e1778de,0xc5c6bcb8,0xc52e57d3,0x5ab71858,0x5cc382c7, + 0x3f6e39f9,0xe12c2c28,0xd62735fc,0x4c7e0ef2,0x835a5996,0xe071deb1, + 0xcbb8c766,0x24f891cd } }, + /* 101 */ + { { 0x6778c1e2,0x24ef60bf,0x00d5be5c,0xff49c03d,0x2f01a09f,0xec11986e, + 0xae096e58,0x59a728a4,0x7077984c,0xaabbcedb,0x870ca5a5,0xfb473bd2, + 0x4de30e3d,0x8c928c61,0x4f67abca,0x3fae7f9a,0xec21a9cf,0x83c2b2eb, + 0x9cd9b5de,0xafa70d62,0xc60b18df,0xadeaea59,0x4049b54c,0xd5fef7be, + 0x6dd310e3,0xfceebc76,0x8f6321cc,0x7748efe3,0x18ee8af5,0xfe9c32b1, + 0xd42df612,0x863ac3cf }, + { 0xb85a2fe2,0x0a36fca7,0xee429dc6,0xf3e70d08,0x141c3944,0x8c9ba209, + 0x67272a0a,0x306a8106,0xf968bd06,0xe69a1555,0x153c603d,0xb86f7e47, + 0xef56e4fa,0x9706614a,0x98780b4c,0xc0dc36b8,0x3a1d3263,0x43657fe2, + 0x435522c9,0x01f97a86,0xedfef679,0xd91897f6,0x6daa17a0,0xebbe31d4, + 0x85accfbd,0x6f179100,0x8f9fc1de,0xe0da6e32,0xe1e7142c,0x1c9d53db, + 0x8b86725a,0x3e3f1b1e } }, + /* 102 */ + { { 0x7b7fbf05,0xb7ea15c0,0x1f1a3882,0x992f11b6,0xd1dcd1bc,0xc9ddd95a, + 0xad0f7e8b,0x31f5b7fa,0xfca7ab79,0x2936e5eb,0x19a55be6,0x30f417dc, + 0x43cde554,0x1f6f4e43,0x82f044bf,0x971f5e65,0x4288c408,0x73c3b8e4, + 0xb807f575,0x61aac59f,0x818b58f0,0xa64ee2dd,0x97a3b0d3,0x6f7a0a60, + 0x0394b058,0x8b85ecc8,0xbfb3517d,0x9a059474,0xa79c3f06,0x89ad5977, + 0x700a8025,0x81208ed8 }, + { 0x14c4ce37,0x10935099,0xa1aa48a6,0xf34bb843,0x580d58e8,0x86007024, + 0xb375b8ba,0x6db42c49,0xed3bde83,0xac365524,0x649233b6,0x5521e1b4, + 0x64dd946f,0xbc7cc5d5,0xbfb5b6ae,0x9c14b035,0x0146c1a3,0x7f22ba18, + 0x872214f5,0x0b62fbbc,0xb4921764,0x3acfd7f7,0xcb4d6df1,0x5ff10da1, + 0x62600a91,0x660e2620,0x81d9167f,0x7ac7da9d,0xb6e7a199,0x6e8e260c, + 0x80deb3c2,0x44383fb8 } }, + /* 103 */ + { { 0xe44f9af6,0xe107f01d,0x8cb1fa1c,0x36381a4d,0xfb7dd493,0xe65be3ec, + 0x26a8839f,0xd0b8435a,0x3ec789d8,0xee60f915,0x2bcc5e1f,0xe25fea50, + 0x7e44a81c,0x0477c0c5,0x230ba5b8,0x349e9f83,0xde180dd9,0xdd42f32f, + 0x64a3d11c,0x8b039eaf,0xbeb7083a,0x80ef884e,0xf12742cb,0x288e60c4, + 0x720a0262,0x44156cc5,0x7253b77f,0xcd547de6,0xa6013a59,0x9829a6ec, + 0x0d548445,0x8aee708f }, + { 0x32c54409,0x18f22d9c,0x75ebaac4,0xa9ebfa46,0x86284981,0x90e2e928, + 0x6b3a8e0c,0xd0201f6f,0xbd77641e,0xc973016c,0x70170575,0xf926f2f0, + 0xfec0ce01,0x4984048f,0xf319d304,0xbf696211,0xc91a88c4,0x74b5c844, + 0xe0030a82,0x4c40fbce,0xe4f6d521,0xbed67525,0x29d67d1e,0xaf7e47cc, + 0xc21d3536,0xfa307db8,0xbbb29405,0x56b6c46a,0x033e805f,0xf059a7e3, + 0x6096a5a0,0x970f61fe } }, + /* 104 */ + { { 0x1bec8e4a,0x1bc53d23,0x35a6034c,0x8809ac14,0x509e464d,0x4ee081da, + 0x8a488235,0x496ae1fd,0x325864b6,0xa1ae9863,0x74cd069f,0xbaca13e9, + 0xb1d8a6b4,0x3738cc58,0xe76b9da4,0x5fa71f58,0xc7eb16fb,0xc919be88, + 0xad4e429d,0xf5c8f13f,0x2499f9ed,0x4583b671,0xa10d8bd7,0xbce20115, + 0x5790bb7e,0xf66d7605,0x482b78dd,0x9316aede,0x75f855fa,0xe0d8fb2d, + 0x5a7dcca7,0x404b5b94 }, + { 0x517a15c7,0xf9ee682a,0xef880202,0xaae4cfbc,0x5106a354,0xcee2c139, + 0x170febe7,0x5de60192,0x73d0c54b,0x589e39fd,0x8c9092b7,0x195c7135, + 0x0a7bfe5f,0xcb7ed53f,0xf61cc979,0x2bd9242a,0x5395f7d9,0x8d2ef16c, + 0x70b32f09,0x0d4ac1ca,0x52d185c1,0xa587526d,0x942d6195,0x2932b04a, + 0xa500b0ac,0xfe25a979,0x562fd230,0x5fa1f4ae,0x20da253c,0x60f55af2, + 0x83146002,0x7faa11b5 } }, + /* 105 */ + { { 0x6e402149,0xb0ba4f0c,0x963cc119,0x3584cc1d,0xa6527476,0x7740dc1a, + 0xc95715f2,0x3f77ff75,0x3f89fb0e,0xb2f234ad,0xef9be3ff,0x55159032, + 0x04237e82,0xfc9fb21d,0xa153ed93,0xeb2eff38,0x10041d13,0x89d53ae0, + 0x7f1bd828,0xcf2e545b,0x43953ea5,0xdd4a27ce,0xd85e75c8,0x00d2e5d4, + 0x241be1c3,0xeb93ed62,0x0242032d,0x1e53f25f,0xc3a4e701,0xb9957636, + 0xed98febf,0x14b63a52 }, + { 0x71c43336,0x7610b553,0x23a4824b,0x19dfd4a6,0x0286051b,0x7b97a2e0, + 0x8f5f1edb,0x86abbb9c,0x9b67daad,0x67a57d77,0xcd5ffafb,0x8ace506d, + 0x89ac3c63,0x85da9f95,0x75a3d150,0x081cbaa8,0xe9346ed2,0x03353d8f, + 0xa1f9a02d,0xb2ab61f1,0x3a659c71,0xb0cb0937,0x4f5df8a1,0xb7e0e30b, + 0xeb7d5a1d,0x77c4c741,0x728e5cf0,0x8f046c9c,0xf7c171ac,0x32dd0bc7, + 0x836d2655,0x02485873 } }, + /* 106 */ + { { 0x75a4cd8d,0xcd40dd23,0x97bcba78,0x132ca433,0x258d61f5,0x30c5cd84, + 0xda1e8e68,0x0a7ec059,0x1d65d40a,0x07a8f171,0xf4350d76,0x869e655e, + 0x5983ae42,0xb98ce6f0,0x9d8bebd0,0x7b61391d,0xb1ba5d49,0x3a529e25, + 0x1f6b2cf6,0x46f732e9,0x3fa3b629,0xbd66ec6a,0xc3ef0ed2,0x397950ec, + 0x5f08b476,0xee9008cb,0x965a0e2e,0xfd6be425,0x1177bc87,0x78ed513c, + 0xfe512dae,0x6798cedf }, + { 0x1b97c5c6,0x49e3f8fd,0x78c3b33f,0x39fbab3e,0x40f595ba,0x44274412, + 0x5d7d4376,0x174225b9,0x79c44777,0x880b3fcc,0x3296b245,0xdc3aca83, + 0x1734e184,0x55913df7,0x9c934472,0xa4db23d3,0xd1420a11,0xcebb3733, + 0xf3608bdc,0xb9d20cf9,0x30cfe13f,0xa618acf6,0x5f30874c,0x75f06b31, + 0x9f0005a5,0x506efe7f,0x01bfc9db,0x8aaea78c,0xf78e7c41,0xf9179255, + 0x52e96395,0x3ea7aed2 } }, + /* 107 */ + { { 0x5b06ae25,0x98617e04,0xcb5750ef,0xbcac148d,0x604c2ba2,0x91ea2f0e, + 0x76b78975,0x00c19f6b,0x651da181,0x79b9b6d0,0xc945705b,0xf3225beb, + 0x5c005bf1,0x30b435f3,0xbc24d86d,0x440b4482,0xd6373777,0x2b8f0996, + 0x1c44b4dc,0x65fd6c56,0x30906999,0xe9405ee6,0x08aa1ec1,0x19ff0924, + 0x3d2f2895,0xeef3246a,0xbc746797,0x016c3765,0xd0705f7e,0x62d2569f, + 0x05250044,0x6a8ad39c }, + { 0x46be7282,0xe45f020d,0x21380f12,0x9405afed,0xd5da6ad0,0x4cdca5bd, + 0x7f8be61e,0xc2d6f184,0x596b8178,0x20132953,0x7a8df954,0x8d3b1e7b, + 0x39572b4d,0x757c61bb,0x80cc3b56,0xd749b57b,0x37b3ffec,0x9590ff93, + 0x145dc94d,0x39bbb653,0x2335e573,0x70c1c606,0xf763feba,0x9c2e72d7, + 0xcc61b732,0x4768e424,0xaa73f2ca,0x777d2fa6,0xc5cb58cd,0xdee4dbaa, + 0x9cfae1aa,0x1a181179 } }, + /* 108 */ + { { 0x77575ed0,0x6f6ff62f,0x7d1da99b,0x18f14fa9,0x69efd7f6,0x2e72aefb, + 0xddc28633,0xc45ab4cb,0x586c5834,0xb0e20d48,0x39775dd8,0xd397011a, + 0xf4134498,0x0130c808,0xf5115ed8,0x2d408eba,0x0260ded9,0xc506a05c, + 0x19cab911,0x9e5b7362,0xe8693a86,0x4cf508c6,0xcc773617,0x4e71245f, + 0x95d89ca3,0x2f71aa1f,0x607bbc98,0x4bba7c6a,0x212b7fd2,0xf3a515e7, + 0x9230f5a8,0x7d2ddc75 }, + { 0x4ed2cae8,0x3d05816d,0xb9c00377,0x4cf6bc7d,0x646b08d4,0xc23e98e6, + 0x4b9c0180,0xf9ee6c61,0xef9179c1,0xe11c9a13,0x8ed9688a,0xa5b6147e, + 0xd06670a7,0x7afeb648,0x17685275,0xd670333c,0x75f9e8f2,0xa89dd969, + 0x37a68ade,0xbb57228d,0x454cb186,0x21a05d5e,0x063dd550,0x4810158f, + 0x4cb6caf3,0x92dd4f08,0x7854abe7,0x70c4d852,0x6e729d76,0x845969dc, + 0xb1bf40ba,0x5a52f87a } }, + /* 109 */ + { { 0x09ecacbd,0xed019e91,0x7b89bdea,0x6544023d,0x5707371e,0x7cc51f0b, + 0x16c8e217,0x14832b04,0x81259ab5,0xb1aa6682,0x23e361d4,0x6e100f92, + 0xe3a95c2a,0xe593eee9,0x16c10e26,0x699b6bbd,0x9473a13f,0xad487873, + 0xb274987c,0xf1c14dc5,0x2559e2e9,0x57dc0075,0xc3d47ad2,0x8449849d, + 0xdd527793,0x83df278a,0xeefd5b99,0x770e3ec8,0x76bd02a0,0x2ae58446, + 0x3e705ffe,0x17f02764 }, + { 0x29abea1f,0xdda4010d,0x2407ac4c,0x636b9695,0x0433218b,0x96a60129, + 0x163d534a,0xf221fc3b,0xccc20565,0x05ba15be,0x96285577,0x1238e54d, + 0x878804d3,0x1b144257,0xa89a9fe4,0x96fbf304,0x4be642b1,0xc8a7f06c, + 0x6e2b085e,0xdd1a20e8,0xff4a591d,0x8f7f27c2,0xa4a343b8,0xc17b0753, + 0xbb173d4d,0x684b1e88,0x3dc07bbe,0x3accea44,0x4c441d77,0xdb15c88d, + 0x53e5957e,0x0ef0309a } }, + /* 110 */ + { { 0xfa8e5b60,0x4fc25721,0x691c0bb2,0x646938ad,0x0b0a2248,0xe46d4b76, + 0x7de16877,0x863f9ac2,0x2721c630,0x503bb6ef,0x0b67fb02,0xf8c199df, + 0xe07abd39,0x78c1ed72,0xb32f0dda,0xcf9deb7b,0x6c3c89f3,0xaff726f0, + 0x1972225a,0xb7008b2d,0x4f145f5c,0x8f5a6117,0x457c4f37,0x4e0e6f8c, + 0x1c453c64,0x8bbdaa44,0xa6e92c80,0x57be326d,0x5d773561,0xa9bc3fd9, + 0xbb37b72a,0x3d3b6cc6 }, + { 0x9722c880,0x6e6f12cc,0x286b6889,0x3a1b6ae7,0xad2fafec,0xba1cc09b, + 0x43bb8bef,0xad64ad7a,0x97c3f4c3,0xa5af6a00,0xc353a91b,0x2afcb0d9, + 0x69ccbf6b,0xca13fcab,0xf2abc190,0x699a1391,0x23a247e5,0x2dbd5542, + 0x95488d9a,0xe206180f,0x1244cc3c,0xba9e7bff,0x87d3a365,0x29297abe, + 0xfa4ca5e2,0x4054fa38,0x67be1b6c,0xb390623d,0x78f41a44,0x1fa67c57, + 0xc7b544e7,0x2e946e43 } }, + /* 111 */ + { { 0xc60934ae,0x2980fddf,0x164206d1,0x2c3e7eff,0x416ed75a,0xf75e7f96, + 0x5cd0b2dc,0xfac60cf3,0x1faad87b,0xddc4bece,0x9849e5dd,0x753fa87c, + 0x2c1bf1ae,0xc5d516a3,0x14732b4b,0x565dbea8,0xce48696b,0x007ebe3a, + 0xcdb97694,0x40ca74d6,0x65e4e7be,0x3f5cd270,0x3aac4ebc,0x74847c01, + 0x43d6c3a1,0x6762e034,0x467a076a,0x690d8c95,0x1eda677d,0x768d78d6, + 0x0181d8c2,0x0997ce55 }, + { 0x965a0b81,0x9297746c,0xe5e12dfa,0x48b58be6,0x715f437f,0x5573b3c4, + 0xb565c459,0xe425e907,0x1582797c,0x4f43f512,0x8ea5474f,0xe5dafa6f, + 0x13de04ac,0x2aeb8fbe,0xe8a07c83,0xed7f95f0,0x662c09fe,0x3e012a6e, + 0xc742cf17,0xbf96e9b8,0xe28a1c45,0x8ea5759a,0x5cf4e2f3,0x475941b4, + 0xf901a019,0x7dd3c02d,0x70916b2e,0xe7a4deea,0x2fa9b988,0x50b272b5, + 0xd0917fe6,0x96f9f09f } }, + /* 112 */ + { { 0x2c310a96,0x78e8aac4,0xf7a2a734,0x32a98303,0x23962207,0xc46ca83d, + 0xd9541280,0xad131e6e,0x2cabe911,0x5791fc5e,0x841b6c68,0x50cb77eb, + 0x3d3c8878,0xaff93dea,0xf1007bce,0x06541f1d,0x55cdf1fd,0x4ee729c2, + 0x323e3972,0xe0f71317,0xad4d08c1,0xa2de7a41,0xa35e22bf,0xa9912abf, + 0x89b03325,0xa050122b,0x06514d4e,0x8b9e51f4,0x79d3e0ab,0x423c7aad, + 0x40b8fea5,0x71998e26 }, + { 0xceb6ed78,0x40140fcd,0x18534516,0x653cf377,0xe8d60dcc,0x0450b65a, + 0x9dac55f8,0xce6c1a76,0xae05686c,0x8a96a92d,0x12712562,0x2fe44762, + 0xa4f39425,0x747bcb50,0xfc531fc2,0xf0ec6ff2,0x10fe9ff0,0xc97c3447, + 0x9c792cff,0xfb488783,0x026fb019,0x552c5248,0xd804c290,0x4001a29c, + 0x35c8ca73,0x742b5ad8,0x6ee5dfa0,0xc3781f17,0x3dfa4ab1,0xca6b85f0, + 0x0b0d32ac,0x8389941a } }, + /* 113 */ + { { 0xde067dff,0xc0f062a2,0xbcb80162,0xd4f32690,0x0707a2bd,0x98cd990d, + 0xfae4a391,0x5afc63b8,0xb32ad814,0x684f1b7b,0xf199dfb1,0xb0a2dce2, + 0x48f25848,0x2260e17f,0xc2d5e862,0x7393db00,0x338cf171,0x9e88f854, + 0x02acf522,0x00679429,0x6835af3d,0x19157cb8,0xb8a2614c,0x2faa6f92, + 0x134ec46c,0x04ff95f5,0xfb7a8135,0xcf00626e,0xb37a4704,0x454b3d05, + 0x2694ec25,0x1fbfda31 }, + { 0xc8f69c77,0xfdebb657,0xa3df88fa,0x92a8278b,0xc1fb78b4,0x463b5571, + 0x11c71a33,0xd2066a1a,0x089958b0,0x10c88143,0xcf9d67a6,0xb975c7e0, + 0x73037b8f,0xdaa5d208,0x40bf5861,0x5ee5005d,0x7dba69a9,0x300e6ce7, + 0xc962cc74,0x893c3cb3,0x4cf84055,0x0ac98629,0x225c9d70,0x0a7ef63a, + 0xb91e47e8,0xfe184869,0x8c2f84be,0x1b9d7deb,0xc0e278bf,0x67788915, + 0xc426f19e,0x4f9488ca } }, + /* 114 */ + { { 0xdd51b8ce,0x610dfcd4,0x36230e80,0x08579278,0x36599562,0xedc7ff1c, + 0xe2cae877,0x905ead4b,0xe7967608,0xa1c325d9,0xbd38926c,0x3e39eddd, + 0x5f6f0a4e,0xda92c868,0xf47a0fa4,0xe16f800a,0xe5f60aab,0x50b4db5b, + 0x983853d3,0x3665412f,0x9b79789c,0x64b62250,0x4e0e72b2,0xea560058, + 0xe555c2bb,0xabbd4901,0x17292e11,0x378419a7,0xe174218f,0x6e0b5aaa, + 0x8f796b92,0x688e0684 }, + { 0x313b8f64,0xcdfef641,0x942c7462,0xaef11b7b,0x5c0d8abd,0x067cfb77, + 0xaf4041a9,0x608ea5f0,0x6935210f,0x23d5bd82,0x27917a08,0x5ab904fc, + 0x45d22d21,0x85dbb1fe,0x4d36159f,0xc3d5e509,0x1d39b8f2,0xaebb528e, + 0xf44acef0,0xdd5ca828,0x20c57a54,0x24209adf,0x78f95f44,0x5742b433, + 0xa9337d37,0xd11fa7d9,0xc64cfdb7,0xd66a0c09,0x9bb817ec,0x56e55b8f, + 0xe4c41265,0x1723c7e3 } }, + /* 115 */ + { { 0xdc8b43f3,0x9a6486d8,0x26409e68,0xfc3e0e61,0xd9b46003,0x1889c437, + 0x6284ec7b,0x3a850335,0x6a9dbaea,0x5a3665c4,0xe978933c,0x7bf6941d, + 0x69341490,0x1ed5a510,0x8cb8002d,0x664a7b7a,0x60ed0a59,0x603f76e4, + 0x1f4ebf27,0xc3e06ba3,0xf2c38a7f,0x296ced41,0xcf1db08a,0x2ac18f79, + 0xcde7a3b6,0xc919e882,0xdbf68b06,0x15e77d29,0x4e947cb5,0x21978baa, + 0x7630993a,0x84bf542b }, + { 0xe364f21e,0xc1decda9,0x012e557e,0x0d6cf345,0x588f90e1,0xba246848, + 0xe3b104b8,0x9f6dda4b,0xe3aef57a,0x6bf7a346,0xe8327ea9,0x210299fe, + 0xda95e6c7,0xaa99f487,0xd2cdf645,0x24ff813e,0x8bd414b8,0xd1dbb2d2, + 0xcafa1a61,0x065101af,0x9cdebda4,0x7d9f4b9a,0xe41039e4,0xaf41b395, + 0xc50adf42,0xe3e9e6ba,0x341e9e49,0x4f2133ae,0xcb157f23,0x4968c0f3, + 0xda068153,0x383f827b } }, + /* 116 */ + { { 0x6583ff4c,0x2ec46a21,0x4ad709e7,0x4e645a29,0xc04ca12a,0xdc66e9cf, + 0x9160a7e5,0x82f128f4,0x569c762e,0xbfb227b1,0xc2edb8e7,0xf80c7963, + 0x49a0f688,0xa7dafe06,0x2d14b8cc,0xb7e41754,0x86de40be,0x3a0c5c53, + 0x1db79331,0xf0d05286,0xfbfe071b,0xb902ce69,0x210e9903,0x61e46956, + 0xf703ebb8,0xfaef874e,0xdd5f78b6,0xf668947e,0x5af5ea3a,0x6fe86547, + 0x43f94625,0x3b121f15 }, + { 0x659275e9,0x5b26e847,0x6d0fce50,0x47581cfd,0x8aa3f1ef,0x55f5cbfd, + 0xe484e60e,0x1e7be315,0xfe9698e4,0xd8f1a20f,0x7ab04784,0x25d46da9, + 0x834cdb3e,0xa526db75,0x8d08a009,0x1fd408d9,0x5b5ca816,0xfc004b20, + 0x65e4bbe8,0x5b3e3bb3,0x759bb6ef,0xf50cc125,0xc2fac737,0xf05fa817, + 0xd273951a,0x9ee102d2,0xfecb3367,0x2a8e540b,0x2a6a515f,0x673446fb, + 0x37290c83,0x5505e1d1 } }, + /* 117 */ + { { 0xd15e68a6,0x0c3014a1,0x64dd35e5,0x6f9f0b26,0x03ad67f9,0x18c3742d, + 0xd2c14484,0x74818c0e,0x0d41a3cb,0xc5181169,0xc49f3e9e,0x65c8c83f, + 0x2c279386,0x9b260c61,0xced04e9c,0xf6086fae,0xfd7c4758,0xa7b2cceb, + 0x90297fd8,0x4b3c3133,0x09701ac8,0xca8264e8,0x508b3762,0x9f976a87, + 0x983a8dfe,0x5d582714,0xd9d598e9,0x350d2669,0x0f6fd348,0x85cb89cb, + 0xa574317c,0x617d80d4 }, + { 0x70022b67,0x4cef267e,0x3768b94a,0x80536bb5,0xd2784462,0x3153a566, + 0x38243919,0x49054d44,0x5df78c4a,0x8d11e172,0xd5a1e35a,0x9b252a71, + 0x8171e31d,0x07866c80,0x1b38a00e,0x0a8501db,0xce770236,0x2ed932b8, + 0x8edaf7d0,0xa2d77609,0xb93006e9,0x3aee5dab,0xbbfeb036,0xfaffc8c4, + 0x4e21b38b,0x077b9678,0xdca8e069,0x491fc59f,0x0e938471,0x3f624f55, + 0x7cd1780b,0x5156f508 } }, + /* 118 */ + { { 0x0206e8d0,0x58234e22,0x7f15af32,0xf5f6f5d4,0xd638950f,0xafab7289, + 0x7d4495f4,0x66ec4d09,0x68da80a9,0xad890c5d,0x64f8a36b,0xe4aa0920, + 0x0f4d5c5f,0x799e257e,0x24495e31,0x44c677ae,0xa5b8e352,0x720387b3, + 0x75a287b9,0x703790f4,0xc3c1f2f7,0x54895cc5,0x41a7fa41,0xb8680f9b, + 0xb00b008b,0xfcd47458,0xba6473cb,0x149cc838,0xac9be19a,0x78ed5f7a, + 0xb33765ba,0x5254599c }, + { 0xa21b54c4,0x08739679,0xb6497d9d,0x029ece2a,0xc8488640,0xf14f1a92, + 0xe9fa79d9,0xae48dcff,0x46c208db,0x14b911c2,0xdae3f69e,0x5ab0fbf2, + 0xd1edb838,0x180ac87e,0x188586bb,0x146fd718,0x5467cbd0,0x210eb654, + 0x1667cfee,0xaa239408,0xb73d1a60,0xdb125c1a,0x881c1cbe,0xde685300, + 0x37c30232,0xfe34c713,0x6f3c8d18,0xc6c6070e,0xb4af4e83,0x07e365ba, + 0xdcf82b45,0x22f0a7ed } }, + /* 119 */ + { { 0xea7f1b7f,0xe262791f,0xdcff09d4,0x9c3d8c5d,0x39c7dc58,0x86c2a9c3, + 0x4276e8c0,0x4dad4017,0xe9fe1d56,0x0a918f59,0x2aa810c9,0xb8d79670, + 0x4aa5cdc4,0xeb7a8836,0xe7afa72e,0xfc4c23bb,0x4ac86908,0x4dbb5c9e, + 0x6a0c7e6f,0x37e39013,0x49c218d2,0x855d7001,0x94b324a2,0xe475bc67, + 0x6287a071,0xc98a8dc6,0x5fb4323c,0x395a299b,0x0c0389e9,0xe186c3ee, + 0x16734c46,0x79f81e6f }, + { 0x364f3c4e,0x83f2c1f3,0x1367e14b,0x536b2ac5,0x5933e43d,0x44a6dcfc, + 0x10d961fe,0x34e59475,0x7e3f2aae,0x08234ece,0xbdea7f25,0xcb92e00a, + 0xa791a124,0x1efba4f0,0x1192d53a,0xc2086fd2,0xb51c8af6,0xfec0d0fc, + 0xdc0f1b5f,0x48d1b2ca,0x812dbe19,0xb07a388f,0xdedbdd45,0x40873a6a, + 0xd702589a,0xbc2a1268,0x17e27b64,0xbbf6e3a8,0x6d386e85,0x73ee5663, + 0x9de7c000,0x442ecd37 } }, + /* 120 */ + { { 0x8a2f90a6,0xb4cd1ae6,0x6f5ad0cc,0xf277d41d,0x401d4b8e,0x6a3828c4, + 0xd8376631,0xe817a134,0xf5e1124b,0x142b758d,0xfd6b95e4,0x25fbc69d, + 0xd74a9e3e,0xa30c9f5f,0xd89663ce,0x5ac0f163,0x0ce6386d,0x32a9eef7, + 0xd8ed5544,0x7a690ea5,0x9889427a,0x5de23ff0,0xeaaced58,0x75ad36a5, + 0xd3e18465,0x3514a6c1,0x7f093910,0x3d9162c3,0xe33d56e8,0x5c10add9, + 0x06aa691e,0x85176b73 }, + { 0x28a21e38,0xa32110fa,0x5773d538,0x97b6379d,0x2d020dc4,0xd3697bbf, + 0x961833cd,0x59177593,0xe5fa8516,0x6d7045fa,0x786ab5d2,0x3390f29a, + 0xdc4f5b70,0xac0bda30,0xdcc615c6,0xcca0240a,0xc5146d91,0x8e1f1702, + 0xa72cef87,0xceb472d0,0x0b669ba1,0x84840708,0x7e61aa0a,0x79b08f9d, + 0x4669560b,0x388160be,0x948eb71e,0x23935c2d,0x9431590c,0xd7fd83c0, + 0x6e5768b3,0x8ab154bb } }, + /* 121 */ + { { 0x353c4a96,0x28686003,0x905cd835,0x4e5c60e8,0x8f66f8cc,0xbd591364, + 0x9faccf9e,0xb6b80b98,0xe32639e5,0xbc1c1fae,0x278aadeb,0x2f6396d2, + 0x1898202d,0x00a796d0,0x3a474835,0x18ab548f,0xb31b0e3e,0xacd056c3, + 0x0164512d,0x15ba68dd,0x4b03f3bc,0x203836d9,0xd8f206c5,0xd64eca6b, + 0x9f1779b6,0x931a361e,0x52ab34a8,0xd82690fc,0x92922e22,0x342bb8e0, + 0xe00b02a9,0x1bfcdd84 }, + { 0x75a365d9,0x310b9a43,0x08d8fb03,0xd4ade15e,0xd742df83,0x9c9753d7, + 0xde318742,0xcf7309d4,0x3360ace0,0x1228e212,0xf7669643,0x1043d238, + 0xf90f5a53,0xfc2adbed,0x7b5f9397,0x41d64cb7,0xc446d010,0x5200b30a, + 0x231720fe,0xc3c8642d,0xb9aa2075,0xfcc0122d,0x041eae47,0x856e3b12, + 0x68c876a4,0x45864455,0x233606b1,0x1a1c7842,0x227757bf,0x9b766d1f, + 0xf7b9d4f1,0x25b78a3b } }, + /* 122 */ + { { 0x156707ce,0x90835718,0x4314f90a,0x9bdc2398,0x8be57dbd,0x017c885a, + 0xad63a4b8,0xd4bba225,0x15aacffd,0x5ce71b86,0x72954722,0x5f266475, + 0x4f0ad3dd,0x0a80f1f7,0xfc352ed7,0x010538a3,0x4203c6ca,0xf8a64045, + 0x330c73b4,0x2b2c7a88,0x02dcac1b,0xb3433ee6,0xed2b17c7,0x2e0499cf, + 0xbd6329c7,0x9f8681a4,0x36fadc37,0x38979946,0x92b7895b,0xdc5650c8, + 0x65a51cf0,0x70ab9570 }, + { 0x7b585d93,0x46778ec4,0xa633fe4e,0xca6d3610,0x4ea0311a,0x21da154e, + 0xbd64002f,0xaf22190b,0xd91cb7a9,0x9e633ac7,0xee6837d7,0xed13c31f, + 0x1616ee8a,0xda4a07d7,0x3afcd616,0xd78a2732,0xba14d694,0xc06696e5, + 0x4df58420,0x733754d7,0x2778e3c9,0xe85e504e,0x55b5a5c2,0x3055aa0c, + 0x8a3acb5c,0x313df538,0x2a088eda,0x5896acb5,0x84c85dde,0xfc8842a0, + 0x51dde6be,0x5fec9f79 } }, + /* 123 */ + { { 0xfe519f99,0x5ebc2c7c,0xe5410353,0xe396bd80,0x8a3988f3,0xaded9402, + 0xd601bda1,0x1c03b735,0x14ce64ac,0xfd302036,0x01240290,0x5837ebe9, + 0xa554097d,0xcaaea1a3,0xb0b88139,0xdce73d25,0xecb090b9,0x35ed412b, + 0xd63dab3c,0x99029ff7,0x062db071,0x555437d9,0x42a4c11d,0x277d2f56, + 0x24fc9109,0x477fa645,0x2799254d,0x7b12e9b7,0xd84c618c,0x7ad2ae22, + 0xce8ed195,0x0a8d5663 }, + { 0x0a21fde1,0x43ac5163,0x6903d849,0xcfcf5dd6,0x5fdd6281,0x6d2499ee, + 0x77a49a34,0x4dedc6f0,0x2875c06f,0x46bda2c0,0x347b8046,0xd0e0e0f6, + 0x5e67836f,0x1058169b,0xde8a8042,0xc961912a,0xa93b3d32,0xdf3fea0a, + 0x0c576bc5,0x9f138edb,0xd8d37e47,0x7971ad6e,0xcce5e7cb,0xeab85739, + 0x1d202b40,0x88a4b434,0xe3a1fd26,0x5d842557,0xb3a86f91,0x872fabd5, + 0x6aa4629f,0x95b93493 } }, + /* 124 */ + { { 0x99f951de,0x9998a701,0xf058db45,0x8fade596,0xf3d03dd3,0x4d479c1e, + 0x33b141d3,0x6e928d5d,0xacfe8a40,0x9a465800,0xc1cefa3d,0xd108ad2f, + 0xe013726e,0x64b96921,0x8e83bb9f,0xb9b6a6b6,0x1242e544,0x29f1e6dc, + 0x2f65966b,0xd3f8f676,0x5e105b41,0xa34dd096,0x16011e1c,0xd4e9139a, + 0x2515541b,0xeea4dc68,0xc822166d,0x6f8030ac,0x31d16124,0xbdc7ae1d, + 0x621afa7d,0x2e25ef51 }, + { 0xdd8e7357,0x2533cf8f,0xeaceddb8,0x333ba218,0x0784d2ac,0x68e3e31d, + 0xf2804ae2,0x1c927f36,0x77e7ad7e,0x01433d22,0x587f78a0,0x0b401cf0, + 0xaa0027ae,0x9dfcf036,0x1d9a46b5,0xc9e46c8b,0x1f288d32,0xaa6de486, + 0x1b8a043d,0xdd56da2f,0xf2d0bb56,0x346230e5,0x19defb56,0x19f0b6e4, + 0x21d2c874,0x55ec37cd,0xb70e45b3,0x3dbf0397,0xac7ce852,0xf0862a8d, + 0xe141f3d6,0x87979ea7 } }, + /* 125 */ + { { 0x7f1c747f,0x9b7e7b3f,0xc6e63369,0x151a4c1d,0xb372dba0,0x4273ff70, + 0xd3ee54fe,0xca6d2234,0xd33cae0f,0x12fc8e0c,0x5dd6f10c,0x27328538, + 0xf01a9cf9,0xc86f3fbd,0xe36cae91,0x5322677f,0x2fefea44,0x39a70033, + 0xce8af217,0x2c9ca328,0xf6a731f4,0xc0256776,0x66a96813,0xc687b3df, + 0x8db2eda8,0x194aab12,0xeec4febd,0xde30dc5a,0x979241b2,0xc052236a, + 0xc23d4c16,0x3ec98802 }, + { 0x4072f74d,0x0f9e760c,0xab594059,0xe78eb0de,0xc9b009c2,0xdb3dea40, + 0x38b59ae5,0x47e875f0,0x2b4daa06,0xf40eb436,0x090f3788,0x9a6a4f92, + 0xedbfaf8b,0xefebe9af,0x9867e256,0xf87f96a5,0x75ab6aeb,0x1e6fed23, + 0x3fdb13cb,0x17f2782a,0x70fa2621,0x5102c71e,0xfd4c0dbe,0x5d2b06ec, + 0x30347297,0x537cc268,0x2b67e780,0x8dbf5e2b,0xba25da32,0x2f633f3a, + 0xefaec914,0x3e9315e8 } }, + /* 126 */ + { { 0x239a9ea9,0x9255cfa5,0x0be33a62,0x20f3c690,0x9cb642bd,0x759eeb4b, + 0x00bae718,0x3316c546,0xf3410f84,0x874a76d5,0x90f129b6,0x123b502e, + 0x12851f1c,0xadc8f9a8,0x1b62408c,0xf57b764a,0x1a80777b,0x116ec01f, + 0x1f0ddc5c,0x746ecef2,0xe5a6a5a7,0x3c49d47c,0x06e955ba,0x1e15dbe7, + 0xb45d79b0,0x629c0c79,0x778d1087,0x11278308,0x8c6a22d7,0x22585dc7, + 0x0a682791,0x2ed02a0d }, + { 0x4daa2682,0x53043416,0x01359625,0x0e26d32b,0xbd867097,0x449c834a, + 0xee77ae2e,0x11a19d2b,0x3af6c169,0x39bd529a,0x5cd61054,0x36cca5c0, + 0xdc6c0fe1,0x6370a59b,0xb93d5135,0xca420d27,0x554c451a,0xd8730d45, + 0x96cdebf2,0xebd258c9,0xa50f9a05,0x0cb1b990,0x7b0f0151,0x69a8c97a, + 0x11d217e1,0x2cc36d34,0x752f75e8,0xf117688a,0xa09b2a61,0x1db01394, + 0xa9efd7dd,0x14627844 } }, + /* 127 */ + { { 0x232803cf,0x6bca3aed,0x9a96ff34,0xc1e4398b,0x74ab788b,0xcaf6757f, + 0x7e68c04d,0xc3a53e00,0x5cb7cd20,0x5f969c19,0xdc068bca,0xf28b65a6, + 0x1d863032,0xe3ca01d3,0x87808e14,0x9b733b81,0xefe618be,0xb5d704d9, + 0xb01b946d,0x276f3542,0xfbedddbf,0xe057e19e,0x903275ce,0x7d182f2b, + 0x880f7bc6,0x3cdc5f77,0x78476c14,0xd6f03d3f,0xa9ba5072,0x035f5557, + 0xb4029628,0x7acb57b6 }, + { 0x44e6b07c,0xd2413569,0xe1c7345d,0x451c4cc9,0xe273b9fb,0x407444d8, + 0xb88e34fc,0xfe496079,0xf152776d,0x77d184cf,0xc742299c,0x6d1033b9, + 0x77bf2897,0x29a0a684,0xee8f0420,0x59ffdf10,0x44bb56d6,0x4e17146c, + 0xfb9ae855,0x831d06c2,0xd93e7cd5,0xb2cb82db,0x3c96b607,0x83381c46, + 0x7549e2a8,0x06aed251,0x774a21d4,0xef97891c,0x8675fbdd,0xae9807c7, + 0x6363516c,0x6a5a05b9 } }, + /* 128 */ + { { 0x6a8f4f33,0x92e71ea6,0x4dea8f4a,0xf2fc6fc6,0xfee88461,0xd356252c, + 0x08954d08,0x59b0a83e,0x468ab766,0x5bd68c23,0x900f8d04,0x40281357, + 0x52b867ae,0x181c19c0,0x18764c41,0x986a5169,0x13575d24,0xcb01dfae, + 0x593677b7,0x17269ae5,0x46dc9b19,0xf6d17025,0xc40097c8,0x8de68499, + 0x259c407b,0x76df0032,0x17d29d8b,0x4091aad9,0x4a7ab5f6,0xa7f46d21, + 0x70ece48c,0x688054b4 }, + { 0x51a5b86c,0xf0d168aa,0x95777247,0x2437e4d8,0xf1720329,0xae844076, + 0x9647a54e,0x0a7ac87d,0x0405622c,0x1e597a4b,0xf0a79f2f,0xedefe5c6, + 0x4d55156d,0xaf3ef0c2,0xef047cf6,0x917fb04e,0x54b62137,0x3792799f, + 0x314be0b8,0x875ea32f,0x0c466b0c,0xe157c65b,0x7e218978,0xd28c90ce, + 0xcde587af,0xb90fc3ba,0x8b877bed,0xdd32d71c,0xca8e10cd,0x3b432200, + 0xd94f6e53,0x0021f419 } }, + /* 129 */ + { { 0x43519d26,0x2191122c,0x40a51845,0xbdafac1d,0x548bb89f,0xcc6f71e9, + 0x16844bf9,0x9ef3375c,0x178e8d55,0xe7789f79,0x1f8be1c5,0x04f599b6, + 0x2cbbde40,0x8088c99a,0x893206c9,0x8939a260,0xfcd30851,0xa1ae4bff, + 0xe08feafe,0x664cb3fe,0xff14aabc,0x61f38099,0x2a841ef9,0x0d8394cc, + 0x17f01db6,0x75fad8ad,0x6debb773,0x6fc34576,0xa4252512,0x1e716b05, + 0x29e1ed9f,0x79855880 }, + { 0x95106473,0xa2cb3aaa,0x5a61da04,0x95fafa41,0x539563c0,0xfd3c9362, + 0x95312b87,0xbaa48091,0xbf885c76,0x6c7e7582,0x230c78d5,0x70f6dab6, + 0x7747440d,0x8ce3051c,0xffdb6186,0x6dbebd14,0x190e4096,0xb0e041fa, + 0x6ee62e2a,0xba10c466,0x74f333d6,0x93d57e2a,0xfe7b9b66,0x006aadc4, + 0x06d2837d,0xfaf72f6c,0x910741ea,0x318cc5e6,0x65692477,0x9c502609, + 0x1d0fb08d,0x95d823c3 } }, + /* 130 */ + { { 0x140528a5,0x6aeebd86,0x53979bc8,0xf268c2ba,0x4ec144ab,0xb1bc9b8a, + 0x82a7d7ed,0x1efabb0d,0x4e0118d8,0xf12c70d1,0xa1c1558e,0x31607168, + 0xe4b7e73e,0x33e428b7,0x83aec9dd,0x63176637,0xe12ac35c,0x5172ffbe, + 0xbc17b2a4,0x37df0bfb,0x741f812a,0x4212f870,0xe2888f9c,0x3dcecbdb, + 0x756ca55d,0xa9dc15aa,0xb9028e41,0xf31918ec,0x6aeadb03,0x7ede0285, + 0x78654f54,0x0e2708d5 }, + { 0xcde20f88,0x2270cc53,0x5f5b1039,0x9338272c,0x5dcb1dbf,0x5042e19e, + 0xb72d74c1,0x4b3de219,0x2aaaaa55,0x16c49a8b,0xbba86ba6,0x008443e5, + 0x20cf1695,0xee6bcd72,0xa89abd11,0x59ffac6b,0xf115639d,0x2831217b, + 0xf34cba52,0xe4d28af2,0x0727a906,0xf27f03e7,0x69017766,0x6842c79f, + 0x7a81123e,0xcb3469bd,0xa42973b8,0x48c0f346,0x23990dbd,0xfc5784a6, + 0xfb299678,0x0d3dab3b } }, + /* 131 */ + { { 0xce29c3cc,0x8f8376e6,0xf016cbc6,0xcb0507ec,0x5e394ce1,0xdebff996, + 0x73c50d41,0x24fc526f,0x2d16ce3d,0x4edd5a54,0x91c13141,0xbb37bdd9, + 0xe33a8606,0xe3442ef2,0xc0629da8,0x2ae90337,0x592ab331,0x57faec64, + 0xd82b857b,0x1a938997,0xa3373176,0xad6c8cb9,0x9086751f,0x82595de2, + 0x18c17196,0xa81e97fb,0xbf697357,0xe4f48a13,0x5cb89f69,0xa1387c2e, + 0x5874b426,0x530b4eeb }, + { 0xbab7b5ae,0xe9f275a1,0x03a57bf4,0xbb69dc4d,0xa45c505b,0xc974dc4a, + 0x416ac402,0x726369f3,0xaed985dc,0x735e4e78,0xcdd446a1,0x0548d879, + 0x9e16b02a,0x84ceb069,0x789b11a6,0xf73f6fa4,0xb2a4e784,0x6aa0c41f, + 0x93a9b697,0xb1f76902,0xf03a8ab2,0x814cce00,0x844d66c1,0x64cb255b, + 0x30952201,0xb794e7d6,0x3da32271,0xe052d4e4,0x08b6a4d9,0x5278b2e7, + 0x80c6577f,0x90942552 } }, + /* 132 */ + { { 0x0d5b4c2f,0xd269a14d,0x5c8a649c,0x2b8fc59b,0xb0e37d4a,0x95becb3a, + 0x9111037e,0xfda1a768,0x94e35322,0x5810e05a,0xa178fafc,0xa24dcc12, + 0x8e3dce62,0x5c2c63b2,0x9452c444,0x995c3f17,0x42d45161,0x35330ec3, + 0xb4ef8129,0xa025a60a,0x8bae9c13,0x85493252,0xe2e3caf8,0x25d1a606, + 0x3649bf47,0xd44091ab,0x704ec5f1,0xc7d0afbf,0xbd8b3333,0x27bd1d62, + 0xcfe616f5,0x50570111 }, + { 0xf534356b,0xd0084ace,0x4b4b0fbc,0x9df1de05,0xcee04dc1,0x021afe05, + 0x361b78e1,0x64bde688,0xef78d38b,0xa324fcc7,0xeb0a5e4e,0xfeb372ce, + 0x65811996,0xef04fcb3,0x5eb0ab4e,0x7dce5d50,0x238c586e,0x1e29b588, + 0xbcd80037,0xde5e3197,0x4806b9cf,0x8bf5e451,0xd18e67ab,0x4330968b, + 0xf9f63fad,0x26a7d04e,0xb5c18bb4,0xa1c7f123,0x25dce22c,0x485b8482, + 0xd540e79f,0x8ff0b36f } }, + /* 133 */ + { { 0x3ff42cff,0x99f2e2f4,0x1c35317c,0xa3c19f9d,0xaba1b545,0xdb749392, + 0x4afa9a32,0x84232b05,0xd7dcd436,0x0b855d46,0x45cf9915,0x8ac35e20, + 0xf001a218,0xd7cf22c7,0xed408305,0x057d35ae,0x553ccfcd,0x25a4a519, + 0x93e2b939,0x5e565793,0x3422ec27,0xa20332b0,0x3ac53958,0x9b09005e, + 0x79e9b163,0x628051a3,0xfc6618d6,0xb4a0dc09,0x6748e7af,0x9e0e857f, + 0xc577d63e,0x71b28eee }, + { 0x99726bf8,0x4942b0cd,0x1c208f3c,0x1290a3b9,0xb0598eaa,0xfd7290e7, + 0xa25a9128,0xc6a7791f,0xc037d7da,0x2d33db24,0x70e2837b,0xc21efeb0, + 0xe3dae2a0,0xbf70d96e,0x85076027,0x43ed8191,0x4d4ad7e3,0x4aeb0aa8, + 0xe8c5b74c,0xbc75101f,0xad26ebdd,0xdbfb2a6e,0x6b78aa4e,0xba812068, + 0xe1159848,0xc94aa8f2,0x3eba5c4e,0x0d10d9db,0x6318295a,0xce7fec47, + 0x330d925a,0x7294711a } }, + /* 134 */ + { { 0x32bbd495,0xfce45904,0xbe54973f,0x330f4dd1,0x5d9c3f4e,0x006bee1d, + 0x59ba7204,0x40ee6078,0x42c2c768,0xc194fd3f,0xe9fe88be,0xa0e76b12, + 0xec2b0210,0x17cddddb,0x00811ec7,0x689d436b,0x284be9e4,0xa6a6ba37, + 0x007d4114,0xabc395b2,0x0f11e744,0xf8cdf9f3,0xe9396402,0xc5febec8, + 0xeeb46285,0x8a751743,0xc6e0d137,0x99bf8782,0xbeb292e3,0x3965e170, + 0x5801fd5f,0x001c39d8 }, + { 0xda4a0912,0xf4805cb9,0x4410bca4,0xd27cb76a,0xec71d65b,0xef3dcb8e, + 0x4816849a,0x780fbb2b,0xa8b24635,0xef6a7026,0x12c44e68,0x15625c88, + 0x4d7a74a8,0x624c232c,0x4b1631e4,0x81a77037,0xdb917c2e,0x04e4f7f1, + 0x1f61ed95,0x1d0465fd,0xcbde6e3d,0xb1048049,0xd7131fcf,0x637ce0c1, + 0x8ada4715,0x22e4dbc2,0xace99726,0xf7530c5c,0xee287450,0xa0160dcc, + 0xbb91af13,0x9132e670 } }, + /* 135 */ + { { 0x7996099d,0x8057efe2,0xa06e608c,0xb72344db,0xd0958588,0xeb4a8740, + 0x79e5aee9,0xe53daf06,0x908a2fad,0xc9560a9a,0x107e706a,0x7f4be131, + 0x2830246a,0x6d5f3d9b,0x27cca3e6,0xa5f8e8da,0x4c28f292,0xeb51dca6, + 0xf31dfd78,0x4cfa310e,0x2ca073e5,0x92e0c7c2,0xa40da683,0x102f1694, + 0x750d38fc,0x16bb07cc,0xbadae035,0x703e83e2,0xb4d3c9dd,0xea93c066, + 0x79940ed1,0x7d0b03e5 }, + { 0x4dd94c63,0x5fe7ea30,0x738b0b3a,0x57ef01c5,0xa14e6b4b,0x9534a78c, + 0xa5353276,0x07622cde,0x7c22d006,0xaf696a07,0x7d46b209,0x733c1886, + 0x626c2b4a,0x9654ccbb,0xa84f3c4c,0xa098d3a1,0x2d734b74,0x3596f9ed, + 0x5d551c90,0xdfd3021a,0x1ec5123f,0xe2ba7d2f,0xb2c1aa39,0xf9726925, + 0xf8eb2927,0xd2e75d0e,0x19192a6f,0xfaba712e,0x9b83e50e,0xa606b43a, + 0xdab5de60,0x31b1782f } }, + /* 136 */ + { { 0x4034db92,0x878dba45,0x8f34dc4d,0xa3977901,0xdf754c33,0x8d004f2e, + 0xcd563a88,0xeaa5954a,0xbb5ffad1,0xa29d6c89,0xb0d8bdb8,0xa8adf655, + 0x8cdbdb47,0xf7fb842d,0x80d3205b,0xb72e3a03,0x7cac7ca9,0xc335b0b2, + 0xd8a5475d,0xffc60bcb,0xeba4d25f,0x736f7719,0x0c50fca6,0x3d901c38, + 0x80c01900,0x1fdacf7b,0x5681f84d,0x75cf658f,0x5cefbbc1,0x57a7e634, + 0x3e07ed1f,0x6fc0fbe5 }, + { 0xb81b0e5f,0x496d116b,0x2ac853b8,0xd82dd2a5,0x327387f0,0x357e22d4, + 0xba912c59,0x3e332a84,0x49d5dcc1,0x8b71c643,0x438d85d3,0x0c982ee9, + 0xbf7fcd4e,0x90b9553c,0x38fed5e3,0x2cb39bbc,0x5ac42903,0xa2c67c9c, + 0xbf07da55,0xebf21217,0xa0b9e4ee,0x55ac05ad,0x8ee9e0c6,0x10bb12c2, + 0x48bb6e3f,0x5cf3aee5,0x8b046e91,0x4ae7269c,0xaa0e553f,0xcb266012, + 0xa94c8fc8,0x701935a1 } }, + /* 137 */ + { { 0xa4626dea,0xde58d41d,0x15b9039f,0x25ef66ca,0x3164e65b,0x99a810a4, + 0x748cfccf,0x9fe6daad,0x2f142fa9,0x7ab9a6bd,0x5d471796,0xa4cba168, + 0x6bc3a39b,0x12d30b36,0x8bf45076,0x1f46a5dc,0x1421ac0e,0xb868e529, + 0x59bba1c4,0x7a686206,0xda698b90,0x2b4b552e,0xe5453707,0x5039dcd4, + 0x9e90165f,0x42a07a9e,0xd7d45dfc,0xa838fff3,0x3b5ceb30,0x41991e5a, + 0x969ca600,0x6c961ec8 }, + { 0xc4e7eb46,0x703bdc1b,0x596c7b48,0xd6bac557,0x66afd74d,0x4f9917cd, + 0x656ce6f3,0x56355105,0x32497175,0x3d1fb50c,0x63effb2d,0xfda6783e, + 0xeefaa2bd,0xbd79f1f3,0x17af9ef7,0xa4efbe54,0x5a55b7a4,0x6cef6462, + 0x1a713304,0x116f3238,0xb95625a3,0xdb2a2a7f,0x0b027e96,0x6a0aa43a, + 0x4832b3bc,0x458fe5d2,0x5adfaac0,0x523418df,0xc49e7f9a,0xc05a89cb, + 0x69e24b53,0x830883d8 } }, + /* 138 */ + { { 0x02557389,0x959b1c62,0xadefc0bc,0x5fe5ce97,0x8330f383,0x893bbe7f, + 0x16cfb81e,0x27e0c6af,0xd04428fd,0x6f64e65b,0xb79e6182,0x53de9245, + 0x487e11ca,0x08a313c1,0x445bce93,0x65cec3b9,0xd67ed49e,0x33bc0314, + 0x30782352,0x69f36b24,0x93ad31d2,0xd78e5daf,0xc780890c,0xf2682b70, + 0x9e45efe9,0x7015c34f,0xe6cbafea,0x135d4ba4,0x7e3fcc6c,0x43a378a4, + 0x96638f8c,0x2376f97f }, + { 0xae575b99,0x0a6e1ec0,0x81b970dc,0x7e14cb4f,0xd3a73947,0xf00a3824, + 0xfb235a9d,0x0b4b9c81,0x5bf62944,0x8d15115f,0x1e165d7a,0xcfd35b43, + 0xb2ee3e3b,0x5d12fea2,0xf5182e7b,0x629984a6,0xc365d08e,0x4e43e2f3, + 0x30f36e72,0x99327091,0xfd345401,0x698b4a00,0xbaf96dce,0x23c4fd0e, + 0x23675554,0xa60ba0ae,0xb0325784,0x51bdac2d,0x215464a1,0x8ab4190a, + 0x6bf10296,0x8c461661 } }, + /* 139 */ + { { 0x2d1f36a5,0xeffca258,0x894c5f2d,0x0eded2b2,0x43ced84f,0x35a5cdb8, + 0xdb0e3b9b,0x290f8982,0x0719a112,0xcce0eaf0,0x39a362d6,0xd0e657e4, + 0x62697e47,0x5516a55d,0x8e636514,0x269e1f77,0xd50269bc,0x5e3dedcb, + 0x441c57c5,0xecec2300,0xc705578d,0xdb83f31c,0x1e489eab,0x1bdefb73, + 0x395fcdb4,0x20b678cf,0xff9db001,0x908cf91c,0x55f52cc8,0xcbebc6f4, + 0xb4c61162,0x155ea622 }, + { 0x876fa42e,0x94be2f1f,0x7fadeee7,0xab5e8749,0x38c865af,0x692e70f5, + 0xdf8059b0,0x16e99b84,0x8b5a7ac9,0x0ceb606e,0x2d463d2b,0xced23357, + 0x2a9a09a0,0x2d0f2623,0x3861fbdf,0x2529998c,0xc1be310b,0x711888a7, + 0x0d8aade3,0x9b1229c5,0x3b13533d,0xdbcf9b78,0xff029708,0x3ca746f8, + 0xda83ef88,0xa5a013a1,0x4ab28444,0x8e904d18,0xbcbd4aba,0x2fe84b3d, + 0x259058c3,0x8f570f24 } }, + /* 140 */ + { { 0x2ca9c508,0xdeb66c8a,0x69d6b780,0x2dc5bec2,0x88ead600,0x16d61266, + 0x49d72614,0x61841b97,0xce472e6f,0x41e40e6c,0x1fa7a876,0xada24264, + 0xcc3997a0,0x45b9fd33,0x7c15dcf4,0xb25e8fa9,0x12e9629d,0x0124ceb2, + 0x7db3d956,0x3a8c72c6,0x7c1a7844,0x8e2ded2b,0x6dd027ff,0x94ab09c6, + 0x7e7a2bc6,0xf89a057d,0xcf70c763,0xad8bf226,0xc8a26212,0x4cb268e7, + 0xb2c44c1d,0x3d171e87 }, + { 0x8ce49820,0x382ac16e,0xc0c44dc9,0x24ee45e2,0x73e858c4,0x0ec67912, + 0x46327cf9,0x918cb25c,0xc6159c1f,0x43e3876b,0x37545cb3,0xb6b6e0e0, + 0x5d12347e,0x64b839ab,0xa300d541,0x72e09274,0x881c1169,0x26ab28e6, + 0xeb75a843,0x4a580fff,0x359120df,0x0a5802ca,0x3209f4a3,0x7fee82d0, + 0x8e6a9380,0xb518016b,0xc2ee11ca,0xb99c6c70,0xab9d4ec7,0x16105af1, + 0x34cd9004,0x234e98f8 } }, + /* 141 */ + { { 0x14db9cda,0xff435208,0x96adec90,0x99cfdc47,0xaf458b6d,0x843aaa6f, + 0x743eaa31,0x3f1f7415,0x61735d81,0x915e192e,0x0ac595d5,0x3441a22d, + 0xc044bc8d,0x704bbf67,0xbe23a236,0x2f960471,0x15d1d557,0xcc326388, + 0x76b1dd94,0x9410230b,0x0c1c8a67,0xf2e5439f,0x833c910d,0x56b141ac, + 0x865b84df,0x467c999f,0x21f02b7b,0x1b0251fa,0x96216950,0xde5b5260, + 0xce3a1e93,0x6a2130e3 }, + { 0x4b3ca1a7,0xd21b67a0,0x00c0ce80,0xaf42ed53,0x932cf07a,0x22ccd368, + 0x5c25c35a,0x36523a81,0x8dd04d06,0xecdd3958,0xb2f93a3b,0x73da3502, + 0xd5e5b530,0x4c5e0c3c,0x13268777,0xef9f5486,0x1e742292,0xed87fefc, + 0xa24e5ede,0x6d9ac29e,0x33849f1a,0x08abc9f0,0x40f23905,0xb09b2292, + 0x7f934353,0x6791072c,0xe6aeb550,0x102a6381,0x96feb870,0x3ee07409, + 0x9c4d2830,0x34f06faa } }, + /* 142 */ + { { 0x2348f005,0x869dc79f,0xdf4920b1,0x9b5c5d71,0x6dee64a4,0xfd1b57ca, + 0xe82a4fb4,0x21b7f734,0xb9578366,0x637cb834,0x7d287d96,0xc934101b, + 0x0392ecab,0x1590f8ac,0x7f75f4e3,0x280dc373,0x6a61ac62,0x8b36f50f, + 0xa65568da,0x74f58304,0xd930870a,0x80d792a9,0xfc8895cc,0x6d17b192, + 0x4914939f,0x498392fa,0xd41d5b9e,0xaf36027d,0x5caa82b5,0x452d79e2, + 0xf4115d1a,0x764d47b1 }, + { 0xa2ee8b9c,0x5df22303,0x85dfcd48,0x1b9f72d3,0x10813a37,0x6b42b983, + 0x3de741f5,0xe28c523b,0xf303bb5b,0x0857625a,0xac9bf9af,0x926f299a, + 0x0d445b34,0x21beac08,0xd6ba2c0e,0x6a523a02,0x7fce2864,0xe302a1b1, + 0xe300c1ea,0x4516a235,0x7b4a9311,0x4543736a,0xc0cc89f7,0xd3c0b9e8, + 0x40ed88de,0x0481904f,0x3cb7fc70,0x4f269b56,0x321b9738,0x09a1d53a, + 0x230a3810,0x1c0dd9c3 } }, + /* 143 */ + { { 0xc46a7d9a,0xffaa1f67,0xbedf91cc,0x64743334,0x47a42f2e,0x45833a74, + 0x241ffaa9,0x67980051,0x335efe6b,0x70979a84,0xf08b2403,0x5f0613f5, + 0x64f211dc,0x6bb22fcd,0xa0572cfc,0xe1b8b2a3,0x7950a14a,0x19e0eb41, + 0x3eb6cd4c,0xe634bb29,0x470a25ff,0x31a04b25,0xa3d15a0a,0xa41f7ac9, + 0xbf2fede9,0xefed85ec,0x81b94a00,0x1f581f5f,0x9ef4a15c,0xaa3996b0, + 0xb06041bc,0x52d8be39 }, + { 0xfd631a2f,0xbd1536f6,0xb351a8dc,0x91fae7f0,0x9b126212,0xd1a590c7, + 0x2bd0f435,0x52d4875f,0x92b0ea70,0x9aedb6d3,0xb83ab89e,0x0bd0abdc, + 0x89fe192c,0x827a1062,0x102a0bda,0x6566a960,0xce036814,0xda083037, + 0x58639405,0x30bed79f,0xdbca8df9,0x972019b6,0xefdaa3f5,0x89201286, + 0x5236b892,0xb337b996,0x28fc2e73,0x11d3e38e,0x880e8da3,0x70787f41, + 0xdae4a45d,0x6cff6367 } }, + /* 144 */ + { { 0xf89a8bb4,0xbd3d0433,0x93b98f71,0x42144c33,0x03470a2d,0x82b616c8, + 0xe5da089e,0x98fcc757,0x7bf5fda6,0x542354ef,0x9ebd34cc,0x1885c253, + 0xbec5dd0d,0x2e20b285,0x782a1bca,0xe71bbbe1,0x9b854ef0,0x959ded30, + 0x8997fa6a,0x17249979,0xd81f3c45,0x50cf8fa8,0x60c11152,0xa9a3b517, + 0xecf845ea,0xc9b0ef7d,0xb9fed11b,0xc9339e23,0x28256080,0xc93e9c5c, + 0x613ec1e7,0x1d2c8217 }, + { 0x987cfc93,0x7381347d,0xf187f810,0x047603bb,0x1250ca31,0x3fa6bc9d, + 0xbb055bf3,0x480091e0,0x3a3af87c,0xbdf95f1a,0x140540ab,0xe2687770, + 0xd7fe045b,0x998df730,0xb723bc2d,0xb398135f,0x15ebec46,0xac230f8c, + 0x5f5561c0,0xe08e1830,0xda60a47f,0x7c0fbf4c,0xe16d4bfc,0x06e95c24, + 0x74617e92,0x74163495,0x4ae0c20e,0x39719869,0x2131e2b6,0xfe269312, + 0x0a537722,0x25486e36 } }, + /* 145 */ + { { 0x53572806,0x618795ca,0x656968e1,0xb2c89449,0x3fb323ae,0x149c2c97, + 0x409bc7d6,0xfb15de26,0xc79121b3,0xa90cda72,0x204cabbb,0x6d2fa14e, + 0x91604125,0xcbcda6f7,0xb435f947,0x25086261,0xc282eb10,0xdb686c38, + 0xf1a791cb,0x51016d62,0x61a2266c,0x6b1c7ed1,0x271d74a6,0x26780666, + 0x824287a4,0xb5ffeda1,0xbbe4f0f3,0xcbe503ff,0xb9482a74,0xd7f7f0be, + 0x088493f1,0x751b2358 }, + { 0xe9c9be68,0xd597b9d6,0x67d10c6c,0x1794b5c4,0x7762b2f4,0xa88cdc3d, + 0xa1b44e11,0x6d94a63a,0xaaa8eca8,0xfb0bbbb9,0xc963d87f,0xf4b0f2d0, + 0x5dc7075d,0xb753062c,0x49933989,0xfed726ac,0x57f9ccde,0x5da60638, + 0x75f8c766,0x221c392a,0x5dc672ca,0xcd264d95,0xb66ecc8d,0x7004ff22, + 0x18a458ba,0xfb1aa9ae,0x8babd653,0xea9644df,0x2ba0de7c,0xa9378e80, + 0xca2c6c75,0x144cc12d } }, + /* 146 */ + { { 0x2989aa3a,0x593a0a1d,0x59e6e64d,0xd83f2283,0xd32e732e,0xe938b0cb, + 0x3c3cb249,0xf4c464c5,0xf89ea6ac,0x9750a5f8,0x346cfc32,0x467e5bbf, + 0x37b2b809,0xc9bfab9d,0x3b339c6d,0xf8eb7453,0x3b766dee,0x3fe01fbe, + 0xef6aea27,0xb3154254,0x7be61b10,0x555c3df2,0xdd818488,0x70fb6d81, + 0xbbe714f9,0xda1af3a4,0x9d18f693,0x575f2017,0x2465b839,0xdc08fc6b, + 0x6b84a951,0x874ecf33 }, + { 0xbbb3f6be,0x624af83e,0x08bb423d,0xf578fbb9,0xd7873527,0x5623b0ba, + 0xa62e0442,0xc3659bd8,0xfe236f79,0x2903b167,0xe53f26a6,0x55a430c6, + 0x3ad712cf,0x222547ae,0x76eb272b,0xb73890d7,0x3d628df9,0x95b4f70b, + 0x53eae4ac,0x9f0e13b0,0xe7f2174e,0x5b4f5138,0x98dbae17,0x75482cf9, + 0x44518480,0x2b69bbde,0xcafef15c,0x4f279652,0xb6bcaf19,0xa0a3ef2b, + 0xce4c634f,0x31fb8581 } }, + /* 147 */ + { { 0x615cd607,0x398306d1,0xaa32c3a6,0x680c9faa,0x7779131d,0xe87a705b, + 0x36708b00,0x1031013a,0x9445297f,0x814fa0e1,0xa6a79b56,0x70c5583a, + 0x4b16bed4,0x03039cbf,0xaaaaf8d3,0x18a7ca8d,0x5cdb68a5,0xf33159e7, + 0xd23814fa,0xdea0e738,0x8d0f4f9f,0xeb352718,0xdcdff032,0xb0b76609, + 0x3d48338b,0x65ba8ea9,0x55dd507a,0x18044d82,0x4a4a50b4,0x844a223e, + 0x18e19e54,0x98323000 }, + { 0x57f3d5a6,0x28a21027,0x6e8cadcd,0xffce5648,0x02551f3b,0x9590381b, + 0x935ebdf1,0xb26cc64f,0xc083aa6e,0x60611291,0x88e4cf41,0xcd988a66, + 0xdd53b1b5,0x581c3f73,0x77fc621d,0x78c804a9,0xfadca2fa,0x31874330, + 0xc83ccf02,0xf7008da4,0xa79a4707,0xc4122a1d,0x4a915eb5,0x9a8e0d3f, + 0xd0123660,0xa2de157d,0x65ead2a0,0x45ef43b2,0x188db285,0xd0a22ade, + 0x922e0caa,0x8abbe39e } }, + /* 148 */ + { { 0x3a2d2f01,0xb4446905,0x5dc6685c,0xd27c3193,0x1d74a027,0x6a908bbf, + 0x5b50ec1d,0x01da350f,0x3f3c2e26,0x1d3dd45e,0xb836ee92,0xf66e11d0, + 0x474b979c,0x7e03908f,0x98b87834,0x19e7c5b9,0xbd3d1de9,0xa741d3fe, + 0x1ef6059b,0x63c68e8d,0x3674e247,0x9b9ff939,0x3e7e67f6,0x1d7d53e7, + 0xaee9e248,0x698dc326,0xb3bd984c,0x52f23eda,0x6f8fe8a7,0xf95e31b0, + 0xc3d0ba95,0x0f15b4d0 }, + { 0x790a8d85,0x8f2f6635,0xe2595af1,0x51bffbae,0x24b51287,0xd15b7ec6, + 0x3234715d,0x7639b6ab,0x2bc5441d,0x0cdd5299,0xf6d05833,0x54800ea4, + 0xf6d6e360,0x21efd752,0x19290613,0xc0b7ffe5,0xeea898cd,0xb68a5825, + 0x22982266,0xecedba92,0xbbd06bb2,0x678a91b0,0x4bb6b0cb,0xb2436dc0, + 0xcaf8ea98,0xcf7a99e7,0x71aa05bb,0xb92d0e6e,0xf5993eb1,0xbf8d0471, + 0x20385ddb,0x515db378 } }, + /* 149 */ + { { 0x6f5bef22,0xee43eaaa,0x20348712,0x952d2698,0x7a3af6c6,0x1e4c484e, + 0x9a8c9403,0x18d434c6,0x5001899a,0x63e5d741,0xfe8ea40c,0x5238dbbc, + 0x96798721,0xca6cc8d2,0x04acbde8,0x73db6aee,0xb7f993ce,0xbf69328d, + 0xad45e334,0xa3f79bbf,0x7c1f1630,0x8c51ec93,0x9b00a6de,0x4907325f, + 0x12d82bc3,0x49e6acb4,0x0ec59fc9,0x5901b36d,0x9cf34e3b,0xcb09b710, + 0x1abf4c02,0x2de0487e }, + { 0x8dd9d484,0x18b722f3,0x7c77bacc,0x83349393,0x93d92b8a,0x58dbb8f1, + 0x8e3fac25,0x80d78d50,0x745f4a7d,0xf0500981,0x877cc29d,0xd072bfed, + 0xc30a89f8,0x67abf8f2,0x9a0820d7,0x92c567ea,0x8a3a5738,0x425ab12e, + 0xf055521b,0xc162faeb,0xb94ea5e9,0xee1c4f26,0x3d71e546,0x1e414994, + 0x43e8be1d,0x258183b8,0xef9eae0b,0x44917c82,0x73874a30,0x6813a457, + 0xcc42f86e,0x6f6ac071 } }, + /* 150 */ + { { 0x4dd6e3b1,0xd38822ad,0xad620869,0xfc78e1cc,0x2cacde80,0xe7843845, + 0xa8469fe3,0x121cc14a,0xe67e8ef2,0x8e8f3da7,0x4d347448,0xdb83d16e, + 0x798631f4,0x3ba1dd98,0x0a4c4c17,0xdfab5977,0x3edc701f,0x1f0a1306, + 0x6cd8ff28,0x4649d601,0xbcc55bc9,0x2267230b,0x5760412a,0x02a19c60, + 0x328faef6,0xc719d5f1,0xf67eaad9,0x27cb969e,0x719bafb5,0xf342530e, + 0xff5a82cb,0x6e2c24cc }, + { 0xadaf8793,0x6313024b,0x035c948e,0x944bccf1,0x953500bf,0xe9a066b7, + 0x1d116765,0x7991a946,0x9fd93c78,0x95addb2e,0xe92e5495,0x05d2c037, + 0x9f03e5cf,0xcb145b18,0x95aa1f72,0x81ae48ca,0x135a6e4f,0x203f2702, + 0x49b2a7d5,0x2bcef5a2,0x02d7f2a3,0x0687a900,0x6c6745b0,0x2f7d3228, + 0x86507305,0x3da8a875,0x2e8dc58f,0xbe38b884,0xdbf11185,0x6b48bf34, + 0x97c08f91,0x5af7fd0d } }, + /* 151 */ + { { 0xf4a224a5,0x55f9b950,0xcc50273a,0x41904574,0x643f1fd5,0x34f81330, + 0x0e50f783,0x996801bb,0x89581712,0x866d7403,0xa4091d36,0xdb9a405d, + 0x16a46fe7,0xf1e379df,0x83bf9168,0x8d04a93f,0x32b20bca,0xae4c8335, + 0xf72a1c10,0x99d334b1,0xd8195db4,0x8fbc9977,0xfba14b5d,0xcaeb3dff, + 0x76daf476,0x60fef022,0xdb5b72f4,0x4b948dfe,0xb6dfb062,0x5185c925, + 0x9609d4ae,0x27a9c381 }, + { 0xf12a93af,0x73c37346,0x5536634d,0x028b707c,0x498193d1,0x8efa58d5, + 0xef21b69d,0x4f83a5cc,0xa788a0e2,0x05cbb0a3,0x65b13c98,0x01031781, + 0x2b73784c,0xfea20e58,0xe50361f2,0xdf9713a0,0xd0cc22d9,0x31449a0f, + 0x7c5e2e1b,0x183752e7,0xb67044cf,0x6e44d6bd,0x733e177a,0x012dde95, + 0x08ee2c23,0x68b49669,0x1f5f1949,0xd9bb0541,0x6acd886f,0x95182c71, + 0xfbde9244,0x1c690694 } }, + /* 152 */ + { { 0x3a880026,0x5db67d17,0x125d95f2,0x89c4f0a0,0x3f6cb7a4,0x29050551, + 0x5cbbdca5,0x3eb231d1,0x972bcbd3,0xf8cffc99,0xad55a03a,0xcb4ef4d4, + 0x22867c2f,0x944d47ca,0x0ead1aa5,0x96d88548,0xcbc8b045,0x76a57cf8, + 0x005e55a0,0xdfe5844b,0x1d18a097,0x5e9e7e19,0x52923c74,0x957a26e8, + 0x7f5db339,0xd0867b79,0x63bed0c8,0x2553408e,0x689ad23c,0x1596e5d5, + 0xa504c339,0x7b8c13d6 }, + { 0x52fb6901,0x2fc43aad,0x16ca253b,0x1c0313f9,0x515aadc6,0x1475830a, + 0x7f577dc2,0xc93d1926,0xf723c0dd,0x26e52e8e,0x3eb9f6da,0x2f1e0eb8, + 0xf180376d,0x9979de82,0xb0834939,0x43e28ecb,0xa39c38e7,0x9a2d51dc, + 0xa8e3f6b5,0x6e6063a9,0x4b9b3270,0x4cf1da3a,0xd2f8915d,0x6e5348a2, + 0x50507912,0x5e75e3e0,0x20d383fa,0xaeffce57,0x8fd2fb29,0x1d6d53cc, + 0x696f4cd0,0x0e3c3ef6 } }, + /* 153 */ + { { 0x21ee1d83,0x3bc337c1,0x787b7788,0x97e08f6d,0x138fa4ce,0xbf709fcc, + 0xa0348e58,0xbaf77647,0xa55e672d,0x04f8babc,0x7d5ec5dd,0x0ed2919d, + 0x33e99218,0x8ce64bff,0x24b059af,0xac09fc57,0xdc5e32ba,0x506831f9, + 0x465af6a9,0x26a22677,0xc97f1ff8,0x3c5efe66,0xbc6087fd,0x1515e0d6, + 0xaa8edc6b,0xb1a39c5e,0x0e79ed29,0x3dd816bb,0xbc3788b8,0x6cc13769, + 0xc092a51c,0x463098e3 }, + { 0xc8bd0fa7,0x3a6408c7,0xce6bde49,0xd1764311,0x283ef7be,0xe315e108, + 0x99b5d938,0x8213cc77,0x45a49a6b,0xaf7f1581,0xe529e4d1,0xd00fdb0f, + 0xce66c9d6,0x55d38f77,0x1bd4b952,0xb4f7ccc0,0xaf71f986,0x8d975b49, + 0xcd64d00a,0x12b59fcb,0xa5a3bad7,0x1860e504,0x2b5c89f1,0x6d976044, + 0x7a3e231f,0xfed0c659,0x178cba92,0x58114c33,0x6698e11e,0xe2e74c06, + 0xa348b85a,0x7f8fd093 } }, + /* 154 */ + { { 0xc19428af,0xf24592ca,0x3a308665,0x192a1c81,0xe30bbd7f,0x42589812, + 0x836c6bb9,0x10db0723,0x598e4987,0x9c7a41e9,0x6ead6f4b,0x8aff179e, + 0x75862c44,0x70f8f9b9,0x6f21983e,0x6b3b0237,0x98e65152,0x25d83e9b, + 0xd751218a,0x3b2d26a8,0x9d6f1da6,0x9508281a,0xa5a81f74,0x8df78d05, + 0xe4687471,0xd79ee559,0x6787d8cc,0x2060ca57,0xa8476c95,0x427a84ff, + 0xe6435131,0x87b64c51 }, + { 0x4b30d3c4,0x87f46f65,0x23b4ef14,0xcdec4c5c,0x63ca4d68,0xb3b74766, + 0xcf3fb56d,0x1df34269,0x0fd7d46a,0xd4f139c4,0x6a69a8bd,0xa3b7c7c7, + 0xcbadd7d2,0xee56b4c9,0xac942334,0xb28ff342,0x786f1da3,0x0046fdfa, + 0xb700c82e,0xce5d149c,0x50966597,0xca30ef81,0xfcff4bdd,0x44a20609, + 0x44925268,0x0f2f65e7,0xd4021f38,0xe5b6552c,0x042dbbd0,0x77ea9c2a, + 0xd9c062f5,0x8c95267c } }, + /* 155 */ + { { 0x5fc1abb1,0x6655032e,0x12fe4743,0x2215af54,0x29f05ef5,0xfd657560, + 0xdc191be9,0xb0e73325,0xc08639b0,0x7ab3c65e,0x1c3e6673,0x67507f51, + 0xc8615555,0x638befc3,0x42f0c4ad,0x5d0188cf,0xd896186d,0x843a301c, + 0xb2c6741e,0x045603f7,0xfa3cd1d0,0xf7545c0c,0x4a40672e,0xf612affd, + 0x45b9e8dd,0x56197c9f,0x87922d74,0xb453237d,0x4b2d59bf,0xbf132e3a, + 0xb84a6a16,0x8afa1b73 }, + { 0xe793ac70,0x6b3596ea,0xeef6dd10,0x4c94ef8e,0x70422e40,0x926b4fa2, + 0xe9e5d763,0xc8c71dce,0xf512aadf,0x352fcb70,0xa883975f,0x1b7ba138, + 0x058c3b13,0x57991390,0x97740fd1,0x9692092a,0x160b0697,0x19ad945b, + 0x10837ab2,0xbc634388,0xf174bb71,0x76ee11c4,0xab1b80eb,0x6111bfc1, + 0x70ec458a,0xbc82bac8,0x312d3325,0xeee60127,0xb240adc8,0xb4118b1a, + 0x2b5a093c,0x67211191 } }, + /* 156 */ + { { 0xf55cf9bf,0x91e99306,0xa46b96d9,0x9b045308,0x9e7a65df,0xae3c1e1d, + 0xc731bcbb,0x453cb151,0xa4d58a61,0x14be5227,0x97c74cc2,0x39dac922, + 0x822e00d6,0x4d0f7a45,0xc62b03df,0xafeb1d51,0xbaa18b2d,0xbb1dc3a4, + 0xdf2b74f0,0x7f3c7178,0x896b6a33,0xfcd328a6,0x1dce055f,0xe95ed454, + 0x6a4e2b87,0x97fbc76b,0xfa59dce9,0xe5ec67f1,0xcc0367c1,0x052368ac, + 0x54e4a3fe,0x7c863916 }, + { 0xca7388cf,0x55e94b5e,0xc0335d38,0x17cc0a60,0x616f85ba,0x9b69b78b, + 0x10122980,0x705d02ef,0x1cfd0a79,0x565a6e80,0x7d1ee352,0xeb74a96d, + 0x427b9dad,0x5c8832ed,0xe6d5330f,0x96ea8528,0x18d24ee8,0x30d8862b, + 0x9ff939f7,0x9cd38ed5,0x01060252,0x690fc9a2,0x2303b3ff,0xc62d88b8, + 0xdd52b469,0xfc42d7a4,0x8cad2d93,0x06f8dfa2,0x60920438,0x50236090, + 0xfce855ad,0x32582758 } }, + /* 157 */ + { { 0x359e8c60,0xeb20e45f,0x364ca186,0xc71bb8a5,0xdff8e110,0x02b15071, + 0x4c93e578,0x074e91d3,0xb829d0d8,0xc0326e00,0x626a83fa,0x3c192258, + 0xfb29a09e,0x387a64d5,0xe5ac5c82,0xcaaa3d34,0xada2da29,0x8ed685e5, + 0xeb29650e,0x92720267,0x763802f3,0xf7184b19,0xdf6b1aea,0x23f5dd0e, + 0x25e6125d,0xbe1fa347,0x0c872a1a,0xd6287f9d,0xac57c3af,0x49aa93d2, + 0x5bda7656,0x1a4e6a71 }, + { 0x554d1267,0x1a126ede,0x1cd02b48,0x37f94533,0xce31fb1d,0xd70af04c, + 0x097dc012,0xcf410b0b,0x36c7b6c5,0x930e1d17,0xc6891085,0x902fee41, + 0x79fb638f,0x349ba4a7,0xacd6f8df,0xa16c5821,0x2e076ace,0xfb3b83c1, + 0xe501d14d,0x6b8d033b,0x20f2d2da,0x0593d452,0x99df1880,0x3752526d, + 0x9feb33a6,0xca32351c,0x1f6ef456,0xd91343bc,0x35b9dc8a,0xc74857db, + 0x85b4e832,0x856a7c93 } }, + /* 158 */ + { { 0x0d0a5583,0xa007d002,0xeda4658a,0x2f1301dd,0x34d939be,0x91c07964, + 0xa70c0836,0xa0cb6780,0xbe81e540,0xc0b4df95,0x5d4ac8b8,0x6cbbcd34, + 0x54756239,0x57c52ed0,0x1805ceb6,0xcac2dca4,0x79344255,0x915ee6ab, + 0x24c9a2a6,0x366def31,0x8c12c674,0xbd3b962f,0x7dbb7c3b,0xaab64f1b, + 0xe22bb95b,0x3c0e4553,0xc4c63b74,0x2408feba,0x2a4da631,0x3ca77312, + 0xc636da40,0x62889084 }, + { 0x8cb8d208,0xa457fd53,0x543f06d4,0x7a8f8009,0xf2eff2ab,0xb66de154, + 0xf72517e7,0xfddb28eb,0xf9389d2c,0x0149fe66,0xd85b88ce,0x79e8773f, + 0x0ba543f7,0x452e090b,0xb0b03fc0,0xdeb9b5cf,0x6c5ed77b,0x3113448a, + 0x8ffc0372,0x3609f3cf,0x5c1b4c4a,0x2bc9c46d,0x8fa59be9,0xe66f3bf3, + 0xcdb02691,0x1396bf5f,0x009f88f9,0xf1ec59d4,0x2ad9dfe3,0xc2903456, + 0x5ada4d58,0x79d8122c } }, + /* 159 */ + { { 0xaa529507,0x14d4e4ce,0x74655d00,0x056a0814,0x4f0fc474,0xc0d30a38, + 0x3443cb8e,0x8a8203ea,0x97f1728d,0x33c62fb0,0xb520ef52,0x8a38dcfd, + 0x7cac9d3e,0xa0f90d5d,0x873cea50,0x28a7b0bf,0x6c6c41cb,0xd115ae3a, + 0xa13812c1,0xa35171da,0x624d507e,0x25d4bba5,0x7e98f42f,0x91dad289, + 0x96a41371,0xffd6b1e9,0xb69e5b77,0xd46c2125,0x20c4f707,0xc7d2b424, + 0x8142557a,0x2ab3af95 }, + { 0x6a5372a6,0x86ca074c,0x56292ba7,0x728fb83e,0x77741cf5,0x745596dc, + 0x520ef49d,0x70b4cea1,0x61e46472,0x1472fe34,0x3fb8ac5d,0xf4d6bd66, + 0xc10bc071,0x46e52cc9,0x371a3461,0x28794efe,0x276fe877,0xa4850718, + 0x9bef5ab4,0xedad5773,0x3f15c815,0x24c2d9ff,0x8f8395c3,0x188950e5, + 0x80b6a855,0xbae40996,0x8a8803e1,0x4f53e22c,0x039d25ee,0xaf233f61, + 0x250409ca,0x07db2c35 } }, + /* 160 */ + { { 0x037d4703,0xc7f3b8db,0xc5f488b9,0xe83708df,0x8471d402,0x1fba830f, + 0x5a2faae9,0xa55ee8d2,0x5404fc1e,0xc2e5bf10,0xaa2d5651,0x647d5027, + 0x7ebaf5f9,0x37a53c0c,0x95b30abf,0x7adf0bb2,0xd64c93ba,0x5a62e1fe, + 0xe2ef4a78,0x7ffc18c0,0x4d2cd04f,0x139dd9d9,0x5ea0af02,0x253fbab7, + 0x0fef9acf,0x7c8100ea,0xc8615aa7,0x74c5384d,0x9fe52069,0xcb28682d, + 0xcf7dd759,0x08b6ca8f }, + { 0x036c3b5a,0xe04e5bea,0x7f9f2b4b,0x38726102,0x29797c0f,0xa9fca570, + 0x82879ea3,0x1656180b,0x607f0ddf,0x153389bb,0x67b0e087,0x99a1223c, + 0x9d897fc7,0x0d1808ec,0x916edf19,0x9470711a,0x07217118,0xf8f52f2b, + 0xd18888b6,0x5d8b29ff,0x4cc6f900,0xef1e22c5,0xeb24877f,0xc4036165, + 0x35479525,0xfda95233,0x6861468a,0xd622a421,0x74faba08,0x5d043b07, + 0x0d31a7d2,0x2c337b02 } }, + /* 161 */ + { { 0xea22fa65,0x7b2305bc,0xd159f63a,0xbe183ef4,0x3f35923f,0x3473d87d, + 0xc11d7753,0xb27fb306,0x2a054cff,0x702e7e6b,0xaf185619,0x3ce9f97c, + 0x4e7d51c5,0x83550243,0xf356ac5b,0xa63e3d82,0xd7645131,0x867b7caa, + 0xa671fc9d,0xee85e6af,0x2b07cd77,0x3b985ede,0xffda5193,0x07d598b0, + 0xa942dc36,0xb10eca39,0x506218a9,0x17f3dcee,0x06b7d5ca,0x3d94e8d1, + 0xed8831c9,0x509b2634 }, + { 0x48caed54,0xb1b9414e,0xcbf51e97,0x77a78c6c,0x4de9b258,0xa4688c8d, + 0x91ee3d78,0x0024137c,0xe30ee64c,0xa68f9234,0x88190d78,0x573255bc, + 0xba80690b,0x41e8e05f,0xec354f4c,0x50038d84,0xdfa52816,0xb18f02d6, + 0xccb63fda,0xc47f9007,0xe98ae455,0x29d480fb,0x5d0e319d,0x4ac45d22, + 0x026db719,0xd06f3575,0x2c3587b9,0x733b9e20,0x2c317727,0x22483992, + 0x54bb8752,0x1592d5a7 } }, + /* 162 */ + { { 0xcf7453f0,0x5778d9a2,0xed83c1f0,0xaffb899a,0xe0a82ba7,0xae6506d3, + 0xea3d5081,0x32c84e1a,0x810aa38b,0x9ad528c0,0xbd37d041,0xb1fdb020, + 0xd06ce41f,0x78d6cbe1,0x2e74b7f6,0xd287f0f0,0xc43bb022,0xf5cd2575, + 0xf81a71b3,0x6d28f2f3,0xc633e7f4,0xe65bb1f5,0xc4fc580e,0x32e5fc1c, + 0xbb7b07a5,0xcd55539f,0xc3caaf3a,0xb5a94471,0x4cc22d2d,0xb958bdf4, + 0x77a2777c,0x1614bdbd }, + { 0xed0ab04d,0x4c1f0230,0x6e2082ea,0xae347b00,0xc42c5b5f,0x9f10bc63, + 0xde019935,0xb0539e6f,0x65dd0825,0xd89bd4e7,0xbbceda16,0x92260fef, + 0xe62aca32,0x8aaa755c,0x5ec82c5f,0xed762fa9,0x18650768,0x99e64c01, + 0xc92e348c,0x57dd6245,0x31ea6d68,0x0db88a77,0x07b44736,0xef0012ab, + 0x171d70fe,0xb9356b94,0x03f891b0,0xe68b0628,0xb79c20a2,0x3a54a53a, + 0xb00b0728,0x489656c7 } }, + /* 163 */ + { { 0x71353c25,0xe43649ba,0x13f67e24,0x517f27a1,0x1c1eb9e3,0x10bd333a, + 0x78e29bf9,0x94e1c05c,0x4743f15d,0x84fe7d97,0x90da2df0,0x9c874908, + 0x53673be1,0x82403fa7,0x1baea1b1,0x7ebf5db4,0x24180ead,0xcfe0ae35, + 0xc2f50c3f,0x1d15873f,0x70661cd9,0x16851ad6,0xa51e8c2c,0x802968d9, + 0xe0161099,0xe7d1a9cd,0xa8a7ea56,0x2b153c89,0x06e3c498,0x6d41b789, + 0xd6769dcb,0x082bb2e9 }, + { 0xc4d6615f,0x6180ef46,0x01b9829c,0xfc629dc1,0x0fb264ca,0xde222ec0, + 0x10ecc2c4,0xc5457e06,0x1eea2c4d,0x95ce599f,0x8f9c5b2c,0x0433fa72, + 0xcd6310f9,0xee035462,0xce2e2253,0x84c57c3b,0x96d87e44,0x6c8ec31a, + 0xa452c5a7,0x30bfe393,0xa047b235,0xc592b140,0xc018545e,0x7bd8be18, + 0x5c178c46,0x794e0107,0x2e23005b,0x48471946,0x622a54f3,0x2665e237, + 0x901c9042,0x36451a46 } }, + /* 164 */ + { { 0x19893e71,0x17802d18,0x539a2082,0xa1765d8b,0x2302ecfc,0xfc6aea01, + 0x365bf59d,0x8d4cf51b,0x0d232a80,0x87741d72,0x18e80427,0xac343eb3, + 0xe74739ec,0x553ecb2f,0x1a8b07ca,0xaeca79a8,0x56f4ab3a,0x089ff322, + 0x3fa1d1f7,0x5e95d729,0xf62a9a16,0x260569ae,0xaa08ddc2,0x5e776232, + 0x1b7bb54a,0x93fabec3,0x743d56e7,0x48a20956,0xeb0ebeff,0x749cdb12, + 0x69b8fcf1,0x705307a4 }, + { 0xe488310b,0x7a8e4c04,0x5325cd7b,0x12726e32,0x4983efac,0x5d0fd8b0, + 0x02ddb913,0x796e552c,0x77b9685c,0x0eeca3f7,0xb15f24a3,0x9b766e89, + 0x48efc979,0x7c2736d6,0xa8021c6c,0x3d619685,0xa0b2f1ea,0xfe33e278, + 0xb676d6b0,0x95c69879,0x1af4e0be,0xa0747319,0x36c4ee55,0xa2fab5f1, + 0x59e5f3b9,0x6938b8ff,0x39cafe6e,0x1e114da4,0x6a6ad120,0xc9595ec3, + 0x57e62aec,0x80f79bd0 } }, + /* 165 */ + { { 0x60af09b3,0x3cef42a7,0x933dfe14,0x3c016ebd,0xed85eaa8,0x720cf1e0, + 0xceaa3bc9,0xd4f5e99f,0xb7106f97,0x7216b9d2,0xc9668ad2,0x65f34c36, + 0x5b0c651f,0xa8fb82bc,0xf2fda4de,0x20f42f1c,0xd21f659e,0xeb31ab2c, + 0xa13d1618,0xb7a776c7,0x38662be5,0xec441022,0xcad08e0b,0xc825da70, + 0x022c0180,0x99299079,0x2aef9ffd,0x7623bda0,0xf5c58b50,0xde84f4f3, + 0xd824ff19,0x5f5a5da4 }, + { 0x7e8311dc,0x5737257e,0x466cf136,0xdef94f51,0xb05ca21a,0xa73e1645, + 0x02e4ab37,0x38ea9b3c,0x8579165b,0x7760eac9,0xc24b01a4,0xdffdd047, + 0x3fb95584,0x188d4fd1,0x25548bda,0xfaac38b8,0x59e9dcac,0x1a79a6f0, + 0x09a2700f,0x983f720f,0xfb8a7e48,0x8cbba554,0x47a1fad5,0x38a19968, + 0x5abd6b5e,0x11856547,0xf3716ec2,0x75113d31,0x4212907b,0x1391e781, + 0x0dc15889,0x5319c801 } }, + /* 166 */ + { { 0x6b61c3af,0x2320136e,0x07b4bb68,0x1d40f2de,0x380c97f0,0x651dee7f, + 0x6a8c313a,0xa978ba70,0x2011ca10,0x22c587d6,0xab1f445b,0x48bba218, + 0xe50444e6,0x8c5eaf07,0x442fccf9,0x5549f02a,0x3d80493d,0x2564746f, + 0x79c04591,0x42d24f61,0xabdc8887,0x1600fa18,0xded38f8f,0x5cb8600a, + 0x923aeb46,0xa4bf9b90,0x1e1c578a,0xd63fee35,0xebb9ea14,0xf3c9c5ac, + 0xf11a4ff0,0x3d13314d }, + { 0xb4513d1e,0xe5cc662d,0xd55952bd,0xde78a8c5,0xe7f86d0a,0xe8a37a3f, + 0x7a04f0c5,0xca2d12a4,0x2e25d06c,0x4c6696e4,0xb2136071,0x52614698, + 0x89f6e1cb,0xf4d2701b,0x80efd95e,0xaafd6177,0xc5bb6907,0xe6d73ac4, + 0x420db35a,0x49e874ac,0xf2751fa0,0x11631de4,0xa1fa2edd,0xb29f7336, + 0xb7fd794d,0x4c406864,0xe22f92a6,0x73cb21d3,0x2043cc76,0xeae904e6, + 0xb322c6ad,0x67f28a9f } }, + /* 167 */ + { { 0xca148ab5,0x7c17b258,0xb3c60051,0xb9a1976f,0xc8f28df9,0xea260698, + 0xe8d45017,0x87b2cc74,0x0578a422,0x37257329,0x17bec732,0x81d5ee25, + 0x1d48bbc4,0xd7411fcf,0x487f5cfe,0x46217e6b,0x41eb8e1b,0xcb007ac5, + 0xe05a00c8,0xc41c57a6,0xd2f9fa99,0x1f954d2b,0x40941cad,0x370bd5db, + 0x3829509d,0xe487879c,0x5ceca5ee,0x4c137552,0xfd3efb9e,0xe8ef7fa4, + 0x1bd1bdb2,0x5ff09174 }, + { 0x579c6632,0x791912a4,0xb8a20815,0xbb19a44f,0x535639d3,0xf4f97b84, + 0xbc3c9bce,0xe57e2bcb,0xf19e6410,0x122b3f2b,0x1357d9ad,0x1f0189da, + 0x79e5ff66,0x675573bb,0xef2f3c4c,0x444e5c98,0x04d10731,0xd6f61e20, + 0xac75d635,0x0dfa366f,0x2c854f23,0x9fc47c86,0x0ad0850b,0xc04ae43e, + 0x2f720c32,0x5ce94f64,0xa753bc9d,0x67efae65,0xb0373a63,0xc27d30d3, + 0x29721646,0x6681013a } }, + /* 168 */ + { { 0xe84509df,0x1385d913,0xcf339376,0xe978bedd,0x3423a148,0x2df425d3, + 0xee8cb579,0x43fa0ae3,0x31c4553c,0xf015369d,0xdfbf1d48,0x05cf08bb, + 0x9444244a,0xadff4be6,0xa35dda33,0x01635f81,0xe76fab7c,0x085c8949, + 0x16737783,0x4bd7fcde,0xa254f8d2,0xfd8cb52c,0x413ec985,0x62168a66, + 0x7a9026cc,0xf2db9741,0x50e1e1b7,0x3962ee56,0xd3beffde,0xbee0a346, + 0x0bdfab1f,0x3b35b72f }, + { 0x535c3749,0xbff8de9f,0x8add9c48,0x23c1f20f,0xc8f8f663,0xa975b37b, + 0xe8f3ae49,0x2529e475,0x1d5e2628,0xc32f10d5,0x67862f1d,0x5ac0d297, + 0x854cbe36,0x13c79338,0x4b67e462,0x48f004ef,0xe5d10ee1,0xfa37a150, + 0xd28288a0,0x4974778d,0xcfb73f4d,0x96830a66,0x07804952,0x9f444013, + 0x9760b694,0x8233c709,0x25b75c99,0x8340cca5,0xc771f99c,0x3f62e40b, + 0xcd95c685,0x47d0a1eb } }, + /* 169 */ + { { 0x652811f1,0x266f4fff,0x62ef3002,0xeaacaa93,0x50cba0ca,0x6c387a55, + 0x007f5467,0xa350142a,0x202f2673,0xc7fd102a,0x33dc6e65,0x5daee570, + 0x064a63d9,0x60682ec3,0x462b251e,0x46cf0bb0,0x5da936e7,0x0e030ca5, + 0x434265b5,0xc87a60f2,0x69b4e8f5,0x9637b2bb,0x7ad7770a,0x601fb58c, + 0xed3a15a6,0x1f2147f6,0x2995e961,0x05b47d5e,0x83213a16,0xcb0ca9b3, + 0x4995a85c,0x8f4b614a }, + { 0x4b4eb3c1,0x5aa8ec19,0x20323a70,0x8c549ac4,0x4f6cc6aa,0x00d49322, + 0x45f9a5a3,0x0e53b9bb,0x0897abbb,0xe46ef110,0xd7acd7d0,0xfe873e57, + 0x0f7cb588,0x7cfccfe5,0xc85557d1,0x0ea53d65,0x7288f2e2,0xfdd9eb44, + 0xc0eb68a8,0xab2dedfa,0x08603a0c,0x58221470,0x00feb06c,0x69464689, + 0x25e5caac,0x804cf5bf,0x9fc91ae9,0xd8559858,0x73c45eae,0xed9378b1, + 0x524c9801,0x8f942d02 } }, + /* 170 */ + { { 0x8e845808,0x1f1ec302,0xb77abfc5,0xc302bffa,0xf8d97dc7,0x26afd4b9, + 0x3aac594b,0x3d3a83c4,0x674d94dc,0xe3b74bd1,0xcaa5911c,0x4464b737, + 0x871c2cd2,0x62925773,0x3b4440fe,0x419f2485,0xe052ad7d,0xdda6a0f3, + 0x846c86c0,0x645280d6,0xf8324f42,0xa25689fa,0x07cf117a,0xc74ad1e8, + 0x8ddc9db7,0x5626dea0,0x966fc85d,0x52620373,0xf3b1eb53,0xe0ad57c3, + 0x949c1acb,0x38300252 }, + { 0x5e744723,0xa0ef5a40,0x1ae08481,0xdb5bcf75,0xfec1f76f,0xabfad8cc, + 0xfab37fc6,0xfba5d831,0xc8fedb78,0xbe39e248,0xad93f310,0xa5cfad5f, + 0x913d5c24,0x747fdb1e,0x4518b7f5,0x052a47c9,0x7cfb4327,0x9e208d6c, + 0x70e538be,0xb135cb9c,0x5bb17916,0x36352759,0x5b3106c7,0xa2c07880, + 0xc209bb06,0xd2d42a06,0xd3c504ad,0xb525b471,0x822ce034,0xc9f4b368, + 0xeb4185a5,0x15f18796 } }, + /* 171 */ + { { 0x0aee4684,0x094dea06,0x7cdbdbc8,0x42b21f06,0xb1931319,0xa439e149, + 0x81a7dba6,0xea4bdd41,0x3c2ae80f,0xc6213706,0x12823dc2,0xb58b0967, + 0x832611b1,0x7443d515,0x13c20384,0x2e16f831,0x2bd992d2,0x0ce204d6, + 0xf419388b,0x499dbcd6,0x1d3778c7,0x492ded1d,0xc5ddae73,0x9d5bd74f, + 0x994b6259,0xd4813d52,0x0e86ca68,0x191d9cf6,0xf3e9c2ac,0x562179ea, + 0x9fee1238,0x6146f1f3 }, + { 0x078e2aa6,0xbd06d33e,0x9dee9265,0x693af7f7,0xdaa40e84,0xd56e0f81, + 0x9b9a407e,0x05fbbb88,0xede99519,0xdcf44adc,0x092dba39,0x7f71f8d3, + 0x4231774b,0x675b5da5,0xa5f605eb,0x7456a251,0x87a39a9e,0x9031d4af, + 0x05b474bd,0xdb430006,0xb665aa91,0xbda5dbf2,0x6631eeb4,0x5d1a3df5, + 0x62377c58,0x028149ef,0x685d0bff,0x2e1af4e9,0x82a465de,0xe0ea0875, + 0x06bd0050,0x95543f9e } }, + /* 172 */ + { { 0x85d7c6ef,0xf7cbc6f4,0x63b1bc24,0xcad8084d,0xbf8cba62,0xdf90ce88, + 0xb455c192,0x98e4b686,0x774fc6ed,0x6146b8d5,0x7ae20077,0x70e2389e, + 0x61c22529,0x5241c479,0x3884e5f5,0x7d221510,0x17e28273,0xd6d20ce2, + 0x4f2674f8,0xe3119f51,0x70c011db,0x85459055,0xfcfb760e,0xdfab75d9, + 0x9e8c2a19,0x9546362a,0x4a7d4b27,0x4b6d3f8a,0xee5d698c,0xa5c87104, + 0x2ba296ff,0x6db43478 }, + { 0x5c3f0d95,0x06486493,0x4e748895,0x8917db82,0x6b2f3e44,0xf73fdf62, + 0x2b7f574b,0xc60edc54,0xaf732723,0xbe1c09a2,0x7cad114c,0x7d34669d, + 0x321aaff9,0x9646600a,0xed0cd61c,0xb94e2bba,0xdec4750e,0x866e1a41, + 0xb1a89f58,0xa1be990d,0xf2759693,0xc39e4d6c,0xc0e0dddf,0x11cfb780, + 0xd99c8a41,0xf0afcd7f,0x6e1c3050,0xcebffadb,0x96d2c6e4,0x4f3981b0, + 0x2ae27a94,0x07a791e7 } }, + /* 173 */ + { { 0x1e9f0300,0xe70e9047,0xbccdf904,0xe0253ad9,0xff053078,0x51c0289d, + 0xae893462,0xf1ef092e,0xa4846845,0x2c90a91a,0xf1dad4b4,0x1946eda0, + 0x33df67b2,0xf07650f3,0x0b15a014,0xc6e988db,0xb542f0f9,0x72e0c66e, + 0xe0c0378f,0x5d4b6311,0xae86950d,0x548badaa,0xb35f1c8f,0x6801638d, + 0x944d1ad4,0x129e3216,0x40471d32,0x9951bac8,0x85e94dde,0x03cc29f3, + 0x4543ecac,0x6d6acc2e }, + { 0x57b2d299,0xeb999e95,0xe3d721cd,0x3a2bcd9b,0xbb4cb444,0x2e60384f, + 0xdc060faa,0xae177709,0x8c987cde,0x74f0e6d3,0x1076fbed,0x9a237cf8, + 0x7983fbff,0x69af1513,0x323f9584,0x6c3f7a1d,0x6db64398,0x3e21cacf, + 0x96703d92,0x7cd8134f,0xb8393f76,0x0755898f,0x2e825222,0x1b5b28bc, + 0x7924aa7c,0xb78799c1,0x81427a8a,0x1db378f2,0xff289492,0xd5a451b1, + 0x3d3c46ee,0x79d18212 } }, + /* 174 */ + { { 0x109d5589,0x1a3edff9,0x029b4499,0xded52eb4,0xb4b54adf,0x13eb9d30, + 0xa27bff67,0x4f9214c1,0x67f0f460,0x4c817ee7,0xc3a50e28,0xbadf8d83, + 0x94026237,0xc5dc03c9,0x966647c1,0x5f29581b,0x8a0687f3,0x10b6a089, + 0x31634517,0xae787cec,0x62e75188,0x2001dba5,0x45e2c3fb,0x55d4e1a7, + 0xb67d3395,0xbfcacdeb,0xbc6842ee,0xa1a0af9c,0x3e88580b,0x50590a2b, + 0xa784cdc8,0x73104491 }, + { 0x2648d676,0x44ca2cdf,0x4f1b12b1,0x9a85eca5,0x2980e1eb,0x1b9dac94, + 0x1ac8aa89,0xf30d3709,0xc719e195,0x73072ab7,0x2f703797,0xba518c82, + 0xac0067f6,0xac090e14,0x8dcd2927,0x0e6cfc70,0x21e7da63,0x4f5889e2, + 0x8371c7c6,0xb4aaa40b,0x8f7878c9,0x1f9dabe2,0xd84caf3f,0xf78aed6b, + 0x9e0e1d92,0x3c39dd07,0x122424dc,0x680be5fb,0x0bdc0099,0xf41b214d, + 0x5180c54f,0x6a8f8fc9 } }, + /* 175 */ + { { 0x53235132,0x62a1ed63,0x59dba88b,0x1db233f1,0x291efdd8,0x85625452, + 0xb25111ae,0xc7505297,0x1d701bd8,0xb5921af9,0x9774f45d,0xb4d05d72, + 0xf18e73ff,0x6e3d4c5e,0x899b3038,0x897d985f,0xc89b1558,0x8a9c30fb, + 0x4d13181c,0x3c92d1a3,0x2223320e,0x292e86ba,0x01ceed02,0xcf2454c2, + 0x583f309f,0x27a45f74,0xad0fd1a3,0x75a6102c,0xcb9c7538,0xdb4f45d2, + 0xdb283fd7,0x4752d8c1 }, + { 0xd5dff4d5,0x514d6cea,0x45a827f4,0x74cd5fdb,0x4fc7135e,0x1070a60c, + 0x1be5778e,0xdec0bb78,0x58dc6b08,0x271e12cd,0x54bc2496,0xb765089b, + 0x619098ac,0x6ddf2c63,0x67528832,0xfd6ebac6,0xc2508af1,0xeaa2d025, + 0x4dcfc1f0,0x13c2cda8,0x45510be0,0x1c7836a8,0x1a886801,0x3904688d, + 0xafaf2545,0x643132aa,0x2830a88d,0x49685577,0x8744b470,0x569491ca, + 0x75fb8552,0x3a6518f3 } }, + /* 176 */ + { { 0x224042a0,0xaaa8ed50,0x2452f1e6,0x6cb4e3b0,0x768211d8,0xedca5f4c, + 0xef4d5d3f,0x4e0fe3f9,0x522d46e5,0x33a8e2a4,0xf1446775,0x5998e21f, + 0xf592d01b,0x1496c50e,0x83a67739,0x69104c2f,0x472bbf00,0x28670bcb, + 0x503177bd,0x8ea883b2,0x7d2712a2,0xc5d8bc05,0xb439c994,0x41ef9317, + 0xdcda1aff,0x9801d3a8,0x7038f6fb,0xd686eeb5,0xfbfbf820,0xe80c5cd0, + 0xedc25817,0x540ac363 }, + { 0xfe7f43df,0xa71969a9,0x2c1b9e4c,0xe6653808,0x859c2917,0xad9677d8, + 0x96aa4404,0xbaca9545,0xff1297da,0x0e9d855f,0x22aea7de,0x1f61897b, + 0x36f13f8e,0x96edccfd,0x16e200df,0x627d3070,0xc98988a4,0x729f0736, + 0x97f231d2,0x95e25e60,0xf6048752,0xaf7f221b,0x4019b299,0xd6682609, + 0x26b4b1d9,0x1d99de09,0x1acdd7a3,0xec47cf66,0x6ebe15e9,0x4de9f2b3, + 0xfa16974f,0x17db32ec } }, + /* 177 */ + { { 0x6cf40599,0x75ef6919,0x00c020ea,0x7ea10dfb,0xfcaaf679,0x3da5ae7b, + 0x88ddd678,0x0d663ca3,0x255bcfcd,0x5a21f8fe,0xe344bc7e,0xe9c3f538, + 0x548e0632,0x35f62b1d,0x43c6e64d,0x654f2425,0x26993627,0xc755a7a6, + 0xb0f41324,0xa3b7c5f7,0x3a2180f3,0x05697f79,0x1e81675b,0x6cf85fb1, + 0xe53428f5,0x6d3cdb35,0x52d28b02,0xe3aa1591,0xf7a3fb78,0xa8470255, + 0xa194445d,0x460bd01b }, + { 0xc24d8077,0xbc34dc23,0x4c720d2c,0x82f4b580,0x6f5d1ffe,0xa29da911, + 0x92783ce2,0x578af520,0xb5904af3,0xe29f51ab,0xf7aa1190,0x46c570d7, + 0x571bddf0,0x4a522fba,0xae89bb51,0xbf4e2a06,0x59f3444d,0x799b35cc, + 0x26cc2557,0xc3028367,0xafcec177,0x94a4e985,0x7c36cbd0,0xadaf7dcb, + 0x75d39077,0xed31b787,0x2d3e24bc,0x52d6904f,0x1f95421b,0xc5ca2669, + 0x1734878d,0x7d342c3c } }, + /* 178 */ + { { 0x11fd127f,0xe5cf2c0a,0x119e4c5e,0x66d36bb8,0x6ef56ac3,0x621ab252, + 0xe5430675,0x30cfeaee,0xac3e9619,0x2ede27d2,0xf8fce671,0x6413513a, + 0x075f4c3d,0x6159c61b,0x59069d98,0xd447efe9,0xea76aea9,0xaf8d6f68, + 0x0f5bd164,0xac5dc61b,0x1e88bb98,0xdbab446e,0x1ba92320,0x618b8b16, + 0x78989865,0xa0eafb3c,0xc08b7e82,0x0c7abcc2,0x20d160bb,0x10f09b6e, + 0x8e4c63a7,0x5be0afa6 }, + { 0x1bbbf49c,0x82ab6d38,0x8c0703fe,0x3e09ce49,0xe10f4263,0xeca58b5d, + 0xda5a4532,0xd9cc6581,0xf618f7b7,0x07e18876,0x250f7fe7,0x0419a5e3, + 0xde6b86be,0xbb1a9e90,0x37359169,0x584a7deb,0x5149db2c,0x38eb3489, + 0xb0ebabb8,0x14546a33,0xc2f88a92,0x0067f0b0,0x0a2db019,0xbde0dfe7, + 0xc63e6f3e,0xba51b06c,0xe9206fad,0xa19127b9,0xfe80dc0a,0xe4eb5e87, + 0xd4de30ae,0x1e6fccf5 } }, + /* 179 */ + { { 0xaa8ac924,0xb57dff66,0xc298b3e8,0x06e9ad31,0x65fb080c,0xd140e329, + 0x1d95c93f,0x7dab211d,0x8a180caa,0x6d68d842,0xa20ded69,0x1a929408, + 0x38df461f,0xa8151753,0x60eae932,0xff5604ae,0x7dae4c0b,0x901b9e49, + 0xde262e89,0x4573a97f,0xf1084983,0xed69d9a4,0x64724f1d,0x8ffa022f, + 0xea85a15f,0xd5f1c2e4,0x01453794,0x4c626ce9,0xbf0907dd,0x80440cd6, + 0x5ddaa837,0x4522d461 }, + { 0xebfbe7c5,0x8895f079,0x84ef3446,0x30ea1ded,0xd4a1ab96,0x716a9eb6, + 0x50a30c68,0x1a4a5d22,0x0043bbaa,0x5a16631c,0x5010e5f5,0xbd107502, + 0x3d8c0556,0xbffe3e9d,0x07772419,0x31b30b18,0x84b82297,0x90ff7ef0, + 0xf21a18c3,0x00c37d75,0x565bb8f8,0x18d0a635,0x45e3bceb,0xbac1da2a, + 0x23f0b08d,0x1c38e90c,0x5fbc5ac5,0xf1ba1aa2,0xdda71fc6,0x09d5256b, + 0x6d7e40ba,0x346501a9 } }, + /* 180 */ + { { 0xcc2b0f1d,0x86be448c,0xac4c3703,0xe3eb45c9,0x9fc96bbf,0x5387f65d, + 0x5ae27fda,0xcef3c4e9,0x1bc18089,0xa008f776,0x22ca18a1,0xf374a084, + 0x53b73371,0xee882842,0x7cc09354,0xcb6fc6d8,0x61496d6b,0x8489ec1b, + 0x49e325c4,0xa92c29b9,0x7bdec166,0x15c6ca52,0xdcea2813,0x95444eee, + 0x3a21154f,0x34683eb3,0xd39061cf,0x8fb26f98,0x06c940bb,0xc3b08aa8, + 0xe554c96d,0x7c1d42cf }, + { 0xdc110aa7,0x766e703f,0xf362e378,0xab7b79d7,0x5aadca3c,0xd259c75d, + 0x60be3373,0x2a6eca79,0x06c4e8ff,0xf4744a4b,0xf3b705bf,0xb2842cce, + 0xae304b53,0x1a3af5aa,0x1b2d31b8,0x7bbfa201,0x4bee88d9,0xc4ba6eba, + 0x565cb839,0x2d3565ce,0xdaf7ece8,0x24808696,0xe6959745,0x2c7ccce7, + 0xe94f9837,0xefd6eb3c,0x3811a326,0x0a33b4cf,0xfffa93a6,0x14203f43, + 0x73c31d90,0x031e9828 } }, + /* 181 */ + { { 0x765a17ff,0x4fefecfc,0xd1290a65,0xa09f3888,0x938da038,0xbf265c46, + 0xa169ad46,0x4bb6145d,0x23a62fe8,0x33cf8214,0xabc860a5,0x562df571, + 0x815c38c4,0xbf2a90fa,0x17eda875,0x45ba1d6e,0x946fa5e1,0x799d881a, + 0xb90f5a3b,0x6c1be784,0xb10ff52a,0x0910a37c,0xa4f4fd36,0xc38c1fe4, + 0x8e2d3ba0,0xc3180fc5,0xb17a6187,0x3e2ff050,0x943a35c2,0x3a00059b, + 0xa28cc51c,0x494d3645 }, + { 0x4ba021f8,0x398426b6,0x796deb6c,0xd14c9083,0x7e36c762,0x6d2e5395, + 0x751cf216,0x8f556eca,0x19b24a19,0xdaca1e00,0x4b20c2ae,0x47887da4, + 0xff41a733,0x93ed4ccd,0x5c7c0cd7,0x8d717c44,0x91bf7009,0xcc48634a, + 0x3b59bbaf,0xa1f146f9,0xe5624f15,0xdd38bb39,0x303f8443,0x96d41aad, + 0x4bf104fc,0x6b670f03,0x29706582,0x0503f9ed,0xb34200f5,0x768e1f47, + 0xbbd4c6f3,0x3cfdcc5e } }, + /* 182 */ + { { 0xb523e13d,0x536c2a86,0x2920d0a0,0x1014a458,0xe7571296,0x3d52b478, + 0x7eb51bea,0x05746066,0x87b0e919,0x709f7861,0x686888e8,0x028aed88, + 0xd94afcd4,0x79a809d7,0xe2129af3,0x50c6032f,0x983c4082,0x75e4be72, + 0x7ab3be8e,0x98331bbb,0xb618c728,0xd31a032c,0x3f59c4a4,0x36dd85a1, + 0xed4f61e2,0xdbece345,0x1e571715,0xba7aaccd,0x64a1ebd7,0x138c58da, + 0x3d1aeea1,0x89296d0f }, + { 0xcca82c97,0xb165288f,0x1427e8dc,0x26c6c12d,0x4c3edda9,0x66a94f07, + 0xeaa01ebe,0x94600e1e,0x30f5e86d,0x14abce7c,0xcb456a31,0x741d7020, + 0x279f42c2,0xab05aa13,0xd4238468,0x70b60faf,0x318d39e6,0xa18efec1, + 0x8920b318,0xeb07f1ac,0xd8399e03,0x01e3cba8,0x3c81a301,0x65f8932e, + 0xccc667d8,0xae8bca7d,0xa268607c,0xcee1ae79,0xcac0a12c,0x3182e64c, + 0x2b1a4c54,0x9233a2f7 } }, + /* 183 */ + { { 0x0acbee17,0x717e8df6,0x5c24fcdc,0x0f0959c2,0xe54ffcb0,0x46f09887, + 0xd285116b,0xb993deca,0xbba1fa51,0x0bfaa4f8,0xd0f2183e,0x9c9249ef, + 0x96847779,0xf93cb358,0x2322d421,0x284bfb7f,0xd42af009,0x40cc709a, + 0x9bb1d615,0xc69f2274,0x717c3c6a,0x76f50b3a,0xbb9c5eeb,0x8b21e985, + 0xa4783b5f,0x58fb19ae,0x52e1c3e7,0x04c86b9b,0xf2971ac8,0xaca59092, + 0x21ed8291,0x2bb26a69 }, + { 0x15f81416,0x98a34435,0xaaff5bb4,0x086e72e7,0x0317261c,0x3d1f64de, + 0x5c0a1cfe,0x31c0786c,0xb3683401,0x542ea4d8,0x1a39b4cd,0x2f77273a, + 0xcbef27f1,0x14fe7ee1,0x16bb27dc,0xee7fc09e,0x410e5dc7,0xc0dccc17, + 0x1943b3dd,0xa3466742,0x3f31c1b7,0x92934b60,0xc22c1070,0x0186ded9, + 0x799f966b,0xa37ee8ba,0x249b0893,0x0f3bfcb4,0x2e92d4de,0xbae61447, + 0xe196eb08,0x937cb3f8 } }, + /* 184 */ + { { 0x16fbfdce,0x57c0e77c,0xc98d4cc0,0xea034cc9,0x42572d20,0xe7606d72, + 0x0019a83c,0x9861b55c,0xf1597162,0x80ba2803,0x05a0fd7b,0x0f4141dd, + 0x4b0daaa2,0x8865913b,0xaa3848ec,0xe6685746,0x3e0485d2,0x16d15a5a, + 0x3b6905dd,0x81c0c774,0x818af2ba,0xcec31b7d,0xd2b74b78,0x80d8f194, + 0x543e2f28,0xca659db2,0x9fb07c1c,0x31b83a7d,0x1f1048c0,0x86537fdc, + 0x78586a11,0x4d57bb07 }, + { 0x53b396b6,0xbc4b768a,0x93b51dac,0xbc8b24c4,0xa30ae1b3,0x33e511eb, + 0x945147c5,0x893bbd95,0x179fe3ce,0x6cc86031,0x3f920bd4,0x34b0a167, + 0x6b256160,0xb32912eb,0x9d168d83,0xbc69a2a4,0xef0dd128,0xb4949e7a, + 0x872699e1,0x2613419a,0xbf21376b,0x06c58477,0xa4f97147,0xe55b1909, + 0x7b9b745f,0x63d6eb75,0x08df3c85,0xb5365b29,0x55fcfae3,0x0e257e43, + 0x979f2aa8,0x1067c118 } }, + /* 185 */ + { { 0x32bf8883,0xc8455084,0x6fd06667,0x4755286a,0x77c2335d,0xd70b0f8f, + 0x2f4a2c94,0x678e60da,0xd118acf5,0xa468d8ac,0xbf5b90d9,0xce93830b, + 0xed4e9104,0xea4b1c74,0x27776ea4,0xac67316d,0x361bab12,0xb98ad75c, + 0x99122451,0xc323d482,0x530a43ae,0x26440220,0x3292d5a5,0x3a44532e, + 0x5fecf1bc,0xdb48694b,0xc667b8b8,0xe4e0516e,0xa4306ade,0xb3aa595f, + 0xf34e9725,0x7e4f7091 }, + { 0xb7f70919,0x3f3816e9,0x16b003f5,0x765216ed,0x778c99e5,0x46c6cff4, + 0x30a51810,0xe6a5abe8,0x45e728db,0xef6f49e6,0xcaccefd6,0x6fdd73ea, + 0x8c37f3f7,0xec394e6f,0xb6407fc3,0x73320802,0x96625cbd,0x988e8f7a, + 0x7cabfb00,0x83292363,0x407f359a,0x258ba9df,0xccbfae50,0xff01aee5, + 0xfe251813,0xfbeaeace,0x83f1cba1,0x9c69f161,0x9eadcdb5,0x512c58ad, + 0x6ccce8bd,0x2ae49cd4 } }, + /* 186 */ + { { 0xc40849f2,0x1239b0e3,0xa441098c,0x5136a4cd,0xe547f649,0x61535a99, + 0x7a9bbac6,0x92e4bdc4,0x53547af6,0x195a1646,0x8b47a74a,0x85ecb319, + 0x9de6a2b2,0x278553fc,0x0e2ba52d,0x471c038a,0x35bcba93,0x12ba1b88, + 0x6f31eca2,0xd4bf50da,0x802b32c6,0xd146e3f6,0x3c64c8c4,0x0c9c0131, + 0xeed21297,0xad30f12d,0x9c68530f,0x9b75bffb,0x8918de51,0x23c0ad3e, + 0xa73771b7,0x180e9d52 }, + { 0x29ab77b0,0xc316542f,0xf7aee628,0xdd411d9c,0x353c2f40,0x044c0685, + 0x4b0ae4cf,0x638dc7e4,0x95fc266f,0xa0924185,0xfd2feb7d,0x639da671, + 0x5ea39798,0x56858ed5,0x58f3832a,0x7a694f31,0xd316d831,0xa94233c6, + 0x30a35a7b,0x2fcacb26,0xf1ff713b,0xfef8f7dd,0x59eee2f3,0x8b9b4525, + 0x156d064a,0xd1b4f91b,0x2f5cfcfc,0x177866c2,0x3777eb41,0x12bc2566, + 0xd8ab85b4,0x21ca6f3c } }, + /* 187 */ + { { 0xa3e66635,0x0e162b13,0x2a9f76af,0x1ef20a2b,0x46db3356,0xab473a30, + 0x7802bb8d,0x0840bd77,0xa699b44c,0x5b6baf5e,0x1b2207f1,0xc6e11900, + 0x790b0105,0xe5de16a9,0xdb67f004,0x22b12f15,0x8a025d25,0x185fad45, + 0xdf0a1142,0xbccf6953,0xf45034c0,0x4c42129b,0x1c277bff,0x0f740400, + 0x280a9e18,0x6e440b4c,0x842aa2b4,0x767de8f5,0x05e8d94f,0x3de20ab8, + 0x20227635,0x5aff5859 }, + { 0xa8458e40,0x805acd20,0x149732bd,0x5a5557d8,0x5f1ca72d,0xc7074131, + 0x952b5323,0x7f2e269c,0x6494fadf,0x5c592556,0x1a7d2666,0x153b7acd, + 0x86fe2865,0xa6df063d,0x57d53b6b,0x1e91db13,0xe93ead01,0x9195bb89, + 0x2963bfe6,0x3d71e1af,0x88278886,0xfab2b9c2,0x3b859b6f,0x77836692, + 0xf7029dd1,0x6e695174,0x7b984561,0xc7987876,0x5907d849,0x64fb4f1d, + 0x88d8a977,0x3eab7e1c } }, + /* 188 */ + { { 0x52e5718b,0xc73a94b6,0xf4cee1e9,0xe3aefa54,0x553eedea,0x654e9e63, + 0x5f3aca1a,0xf2541e1b,0x0d083316,0xd7129489,0xfb7f950e,0x7965af63, + 0xc74e3e4a,0xd8fc9e0d,0xeaf79ebc,0xb4ee48d2,0x8b7787e6,0xa458a86a, + 0xf7cceaf0,0xd8c7621f,0xdf67980d,0x8228eeff,0xf9106727,0x210d4742, + 0xb07e3629,0x91f63501,0x7971e29d,0x441761c6,0x03a3b8a5,0xc0ccc65f, + 0x38e09544,0x3491da4f }, + { 0xcb062eae,0x6706d046,0x5d08776d,0xee7db735,0x292315d2,0x80de8052, + 0xc402bbdb,0x40785662,0x26ed3337,0x5f93525c,0x7d568ed3,0x6cea14d6, + 0x66888b1e,0x916a1189,0x5dc71675,0x0fbd5205,0xe4575df2,0x833d1077, + 0xec092335,0x4e93100a,0x6cd85389,0x2f9e1d01,0x43226368,0xeebd3725, + 0x1ba4cfd7,0x401d172b,0x574c5838,0x377dab9d,0x80d517de,0xaeaa6958, + 0x6ad15a18,0x0c843dfd } }, + /* 189 */ + { { 0xc9373300,0x455811ff,0x99fdc300,0x1c39332a,0x353cb655,0xe19bb81c, + 0x96a83d27,0x774b924a,0xb2ee3f1a,0xcbfc8fcb,0x010d56c7,0xaf278ec4, + 0xe0abaf79,0x6fde682f,0x7339aebf,0x7566d072,0x71205db6,0xbd35ad5d, + 0x7051c9d0,0xb5bbe694,0xd3a3067c,0x577db480,0x572d7530,0x2c70ff54, + 0xe06d853d,0xe8615aec,0x05abfb5d,0x71999ccb,0xea0a8ed7,0xeeefc96b, + 0x35f6df69,0x2dcc469d }, + { 0xc65f0e77,0xcca6cd06,0xbd71b14a,0xddcc7980,0x3c93cc00,0xb6221f8b, + 0xae8cbf57,0xddfcd5b3,0x76f8e63f,0xbc92973f,0x06e132b7,0xe9848a34, + 0xd51ec9e2,0x4cc59a03,0x3a33081a,0x9c9d32bb,0x80e8466b,0x00121052, + 0x1bbe7295,0xc2b0032a,0x24938448,0xdbfc6572,0xb6bba0ff,0xe972a0ce, + 0xc0a94802,0xf60c0a4f,0x599d8bc7,0xf62c41cc,0x312da0b8,0x820c96ee, + 0xcdbdf9fc,0x5a1a65db } }, + /* 190 */ + { { 0x42485684,0xbfba691a,0x29c470c9,0x613116b9,0xe62a0519,0xb4b01971, + 0x5ff499da,0xf3245aa6,0xa5238eff,0xc2ef87f4,0xcc9d5515,0xc16dc6ba, + 0x2dbdacac,0x5a7f227e,0xa9bbaecb,0x8dedaac4,0x2e7c9885,0xff308a6d, + 0xe6895593,0x4c6f2fc2,0x177e0611,0x3655f285,0x300b1bee,0xa63e8d06, + 0x13c17b54,0xbed0ce79,0xc4974262,0xca4abe35,0xbc4e4037,0xf4b44a17, + 0xefe5fbd9,0x5ae95099 }, + { 0x804f7455,0x122e5ee7,0x22066682,0x341a4997,0x7795e333,0x97d24c31, + 0xe48efced,0x12f4123c,0x19fbc21c,0xe8738d92,0x0663a3ae,0xbb3bdc61, + 0x8593a6db,0x3603d8c2,0xe3c1ac75,0x926227f2,0x5eaae519,0xfea92ac0, + 0xfd6812ac,0x5b596f0b,0xfc2a82dc,0x3ce7e844,0x63522b27,0x3840481a, + 0x52867895,0x836088b1,0x26588688,0x21ffb7cc,0x2f4a7cac,0x0ca33161, + 0xa3edd298,0x4110667e } }, + /* 191 */ + { { 0xc2d04b63,0x81830357,0xf4929a18,0x3fc5a34d,0x22d195df,0xc73bf6da, + 0xcb432473,0x14df2f89,0xe997f138,0x345afe5c,0x8b9604f4,0xd8e3f5f9, + 0x50c10ae5,0xad7942e9,0xeed25ff3,0xcefd5447,0x0e73c0cc,0xbf68e51e, + 0xab54fa4c,0x5b1ad591,0x12b61c8c,0x8bbc1105,0xb5abf760,0xbb932913, + 0x01e79649,0xdb1231be,0x040ccbe7,0xd0a83e91,0x90a96db9,0x3dde426f, + 0x34df11ea,0x1cceb645 }, + { 0x0c6d0f55,0x2d210c4f,0x9c673c9d,0x6cadf61b,0xa9ce3fbb,0xdd7f9919, + 0x93b063e4,0x135f494c,0x145a93be,0x580bdb3c,0x0f52ef7c,0x4d872332, + 0x8814bb6a,0x74d876e8,0xc7a97dee,0x4f6f723a,0x3e3cd833,0x7de2b8f0, + 0xae720270,0x6162f082,0xddfa486e,0xe88ec2d4,0x8d3a17c6,0xd965c859, + 0x3980171a,0x62e59e54,0xbbef6b22,0x0ab6285d,0x4d48b203,0x3cf45195, + 0x4ea25ea3,0x1f175233 } }, + /* 192 */ + { { 0x3467ea91,0x808a765b,0xfd2d9c45,0x3f4632ee,0x9cf2bc6f,0x7b75dc6d, + 0x359813ae,0xefc8d240,0xe44cbd8d,0x23ecb209,0x21525622,0x59ba10e3, + 0x3f1ee19a,0xfa14d934,0xfb0c48f7,0xdf97c21b,0xea30d437,0xc4e62890, + 0x651475c2,0xb286e2a4,0x126672a5,0x291f01e4,0x31aab3b8,0x9c6fda5c, + 0xe17d22ec,0xb7277a5a,0x914f0bad,0xbd88ed83,0x6a2392e1,0xd0b05d1b, + 0x65893c2b,0x4cb8af90 }, + { 0xbb4b1953,0xa2b02057,0xf597f6ee,0x4ce08b44,0x5e6412c8,0x854f5d9b, + 0xb3cd4919,0x1913262d,0x6e42bb5d,0x902762e4,0xd78e7f60,0x8355c8e6, + 0x38b6c16c,0x8efaa824,0xe550f618,0xd0173790,0xe57d778e,0x118af462, + 0x715b4714,0xa16ad5e8,0x41dea4f9,0x900596c3,0x280ca610,0x2a957c32, + 0x374c65a1,0x2faee800,0x50080414,0xdb105127,0xff080fa1,0x8c1db931, + 0xd79878fc,0x486a5c25 } }, + /* 193 */ + { { 0x941b4f36,0x0521e213,0xf803b4f9,0xbaacfb14,0x52a54ba8,0xfdf1e22e, + 0x8fe4796c,0xacfabbba,0x58dbacb6,0xae0788db,0xc19dfa51,0xdf98d736, + 0x35a716ee,0x155c286a,0x9c86461b,0xbe7d4676,0x63a64a5e,0x50b6380f, + 0x9f609262,0x14b41914,0xa2dfc5b3,0x0919a7d0,0xcef466ac,0xc454da55, + 0x6986aaec,0x93fa4a24,0x71a49ced,0x5090b171,0xc1fa75ad,0x602f1d6c, + 0x78e4c054,0x5d269f89 }, + { 0x14920419,0x3a74030c,0x90968739,0x0845d868,0xeeb70fa6,0x81b994c4, + 0xd9fc5bcb,0xabcaa06d,0xf58f8f2d,0x06539427,0xb1dc52aa,0x35c85f67, + 0x2c911baa,0x5a7d8d72,0xaec2d834,0x4041005c,0x7a8e5347,0xb5868a44, + 0x8de512c3,0x04ee180b,0x211168eb,0x4daa66e5,0x2317cd8a,0xc0bd5dab, + 0x61164df6,0xa1d4185d,0x1dbad7c9,0xacedca26,0x09b02683,0x0fe4b5ac, + 0x26d9550f,0x8ac9995a } }, + /* 194 */ + { { 0x2640a39d,0xb2c8dc9b,0xede0c9f9,0x21ff0b38,0xa1ecba0a,0x74f469bd, + 0x080d0417,0x8a902ccd,0xf4994604,0xe956fa32,0x9776ab15,0x348f85cf, + 0x0066f492,0xc21fc6ee,0xfeeef367,0x35b1ebfe,0x4613e5ed,0x7804581c, + 0xea6ba071,0xcbdfe8e6,0x950d73ed,0xddfcaa32,0x1da48889,0xc9747936, + 0xdbaffbd1,0xce867c8c,0x1cbaeae7,0xd267431f,0x897912c8,0x68255045, + 0xd7ea1e4d,0x0c7c1ddc }, + { 0x1ce963a7,0x53aa30cc,0xc4c5fade,0x7352f64c,0x2828afbf,0x2b9aa2f8, + 0xca212107,0x64273c56,0x85a576dc,0xaadd7654,0x90b5c77c,0x6196ac3e, + 0xd1aaf39b,0x20d43e9f,0xcd05cbc4,0xfc392062,0x4c0ff2fd,0x14163872, + 0x2ae821e6,0xcf32b8d8,0x3fa7a3f0,0x5f58f943,0xf644ca92,0xaebf1d2d, + 0x1918a75f,0x0c061563,0x6b876118,0x7989b5ed,0xad412441,0xbf342445, + 0x1df633ab,0x24ffc9ae } }, + /* 195 */ + { { 0x93c7cb2b,0x89fcdc05,0x590053fb,0xc1243b95,0x6182343c,0x601debcf, + 0x66c18a63,0x364546ef,0xec913287,0xa5290701,0xf9788c31,0xc35b8026, + 0x92d1f7d7,0x852b862a,0x0aa79728,0x1809cb05,0xa3cb2005,0x897d467c, + 0x9ef5b946,0xf20c77c0,0xf2241984,0xc3372c42,0xf35bb206,0xda053e0d, + 0xa9c140b5,0xbc26c6d0,0xcb56fb33,0x61cfcc0c,0x299b3968,0x1c3cf9ef, + 0x40621ba4,0x89e4d3d1 }, + { 0xa45a9be3,0xd35e80e7,0x07356fbd,0xc4daa578,0xb967bc2f,0x0186d62e, + 0x47cd16e3,0xa702679e,0x5f30ce9b,0xca2f1c02,0x1f864f50,0xf1205b46, + 0x85061d66,0x7fd6d797,0x8a08809e,0x47edc4f6,0x9a4d3ae2,0x5dac0449, + 0x6d1f9da8,0xf844664a,0xd7a83a71,0x9f30ce84,0xeaac33f1,0xe9382bac, + 0x948622ab,0x1f033831,0xf7681eb2,0xb037a4ba,0x99a1b5c7,0xd156a908, + 0xe6f1d0fb,0x675d3e6f } }, + /* 196 */ + { { 0x707193e5,0xd9767ffd,0x810358e5,0xe478aa91,0x328d8ef7,0x5634f9ff, + 0x6dbbd9a7,0x913a0ee8,0x7e215686,0x379b2968,0x89d9da38,0x903f410a, + 0x1b1334d2,0xd9f8d7b9,0xbd82efb5,0x9fe74229,0x3803c778,0xdb568b62, + 0xd3d25344,0x93e9a350,0x724497e8,0x559c35b0,0xa169e23b,0xc472d436, + 0xcc5b4c69,0x09864632,0x83c7f531,0x9f6d759d,0x1e497888,0xa91cf1db, + 0x60af1a4b,0x5f7f92fe }, + { 0x0545167e,0xf18a1cc6,0xaffa88e0,0x55ee2e02,0x432a7bcf,0x24cdff51, + 0xa7510866,0x7382da42,0x40511af7,0xe894c11f,0x2aaf1423,0xaa4e4e31, + 0xf63dd2ae,0x8c3d36f0,0xd7660635,0xfc5c9550,0x37ea7eab,0x01253731, + 0x39b950f6,0x2a5cd598,0x40e63442,0x95a0f601,0xf2ac7045,0x905e238e, + 0x446b0f73,0x44bacc0e,0xc448578a,0x4cd4206e,0xa5bd7803,0x367b1aaa, + 0x0a2b458d,0x25beced9 } }, + /* 197 */ + { { 0x0c33a8fb,0x079a7382,0x0f25dc1d,0xcfbf6cd1,0xc6d482b6,0x4ffc73f8, + 0x07bf844a,0x3e51f18c,0x599162f0,0xa7651236,0x14013811,0xac59a74e, + 0xe55018a0,0x957a6865,0xe3ca09b1,0xe1ec51bd,0xa960253f,0xbc0c7eb3, + 0x7de03f84,0xe83bfd14,0x52fbdb09,0xc0540ed1,0xcea15ec1,0x6ba52edd, + 0x4b261307,0xf3d30ed5,0xe8397206,0x9bd7bae8,0x096373aa,0xf20d8692, + 0xc3b0bf63,0x0a616a4b }, + { 0x6e1339c9,0x2075f3ed,0xbf8b00a6,0x7afaa072,0xbccd9b47,0xdfafec82, + 0x00ca54c7,0x4713158f,0x38bc31ae,0x449102f1,0x310dfc8a,0xaf98f158, + 0x59e954d4,0xc9ef2075,0xc527a0c4,0xe8021af9,0x7a192023,0x6e801277, + 0x7fb02377,0x635f538c,0xe8c9e951,0x5df1974f,0x15cc9097,0x0287faed, + 0xf7a5115c,0xfa0728f0,0x0fac623d,0x90dbfbe6,0x0311ba09,0xa8d40fd4, + 0x07c6464c,0x876d154e } }, + /* 198 */ + { { 0xc2d3ea8a,0xd3a4d6d2,0xa842600e,0x36be681b,0xe4070672,0xc53f100d, + 0x6a7d7a7b,0xe3e5b6fe,0x5d5e1a83,0x6e6994f9,0x76097c2a,0x07cacd22, + 0xa6791011,0x12d98dba,0x102e0e24,0xddfc4461,0xd493272a,0x4815dbc2, + 0xa9436696,0x7e38e64b,0x32b2bf90,0x4960eb1a,0xd928e28b,0xda457525, + 0x2a077c9e,0x72f75b39,0x7fd61d00,0x27760cbb,0x0f4b1456,0xaf235d1b, + 0xe76d1700,0x3040c23b }, + { 0x4efa9a70,0xb10dc55b,0x53e86610,0xd4de414f,0x09f8a27f,0x3d95c113, + 0x06661d3c,0x505109a5,0x60eb513e,0xcaa2994a,0x1e7d338b,0x3ee41537, + 0x4651e71f,0x4fd145fc,0xcbc313b4,0x51bbf838,0x1eb92150,0xb039e078, + 0x14bf5ac7,0xe8696b44,0x8be0d48c,0x2d667188,0xdd8f2b6f,0xbe93b2f5, + 0xeb8a7f8a,0xc1dfd1e7,0x90f751c5,0x862b3dd9,0xa32a74be,0x1eb1ad58, + 0x1ebbc9a2,0x5486d79a } }, + /* 199 */ + { { 0xa1359e13,0xcb2e34ff,0x28196051,0x202d8dbf,0x23564b5e,0xe95e023d, + 0x42f6ac12,0xfb1340b6,0xb653725d,0x543ba852,0x8d2466ad,0x81aedcd6, + 0x547c728b,0xbf780224,0x9569fb65,0x559f8a11,0xdfb22ec9,0x505b7a62, + 0x9eed5e52,0x07107540,0x299f6f11,0x9c899288,0x3db6f8c7,0xa7d69261, + 0xb3ca79a9,0x30eb7fb3,0xfb2160b0,0xcab99bb8,0xd28b409a,0xd2012568, + 0x5ac45f8b,0x380f1b0f }, + { 0xe6a0068f,0xc0b99e6b,0xc8a73753,0x4b67cf2a,0xb2faeb7c,0xa6c9a548, + 0x340260c3,0x7f417f99,0xcc0f739e,0x8ee56855,0x780949da,0xf08b510f, + 0x8d5c6eff,0xb1770fc2,0xfd96a7bb,0xb4f5abee,0xf2665a2a,0xa07b1136, + 0xb601dcf9,0x2fb380a4,0x162becc6,0xcc803614,0xee6b83b3,0x3498fb96, + 0xa8c17eeb,0xea9b0fd6,0xa177efc2,0x5834b5ba,0x5b110b3e,0x929044f5, + 0xebd7285e,0x4abedded } }, + /* 200 */ + { { 0x700ef376,0x3355e1b9,0x66cdabff,0xd56e5d9a,0x47e87646,0xb3dc2575, + 0x00f79369,0x28f44b8a,0xa0c52e29,0x08c32b1e,0x3729b392,0x5a78de12, + 0xb26d239d,0x4184519a,0xe0ce4a6b,0x23f6b4b7,0xacb2a9f9,0x235f6f8a, + 0xe2064a59,0xbb8bc454,0x1bf3062e,0x37efd034,0x94dff6f9,0x6bac683b, + 0x8aa7fa06,0xc3364b1e,0xce0b3745,0x0616772a,0xd1e3fb0f,0x46f08d08, + 0x18e132d3,0x6a20abb3 }, + { 0x6a85cbc7,0xea831016,0x934f9aa7,0xd0990946,0xe778f1b3,0xc2211088, + 0x2247b799,0x7ea4ff8f,0x454484ce,0xb3171d71,0x4f98c364,0x29403949, + 0x97df1458,0x5da911f3,0x09439116,0xa6b58093,0x174238bc,0x75f9509a, + 0x8209758d,0xfeb51821,0xa47925d0,0xae0c6021,0xaf8a315e,0x0e946694, + 0x6bad04b7,0xae7af8a3,0xf072447d,0x44c15e7f,0xa5456ffe,0x5184668a, + 0xbf36b977,0x45e353a7 } }, + /* 201 */ + { { 0x93092f71,0x76056764,0xf5b92d71,0xeb66b6c2,0xe2c8b6c5,0x9db3149b, + 0x20c0363e,0xf62f583a,0x03cd7097,0x688acd33,0xebb916ac,0x85d0c0f8, + 0x84c19b0e,0x1bf7462c,0x7c4a6ad1,0xc76ed5f9,0xd119f369,0xec8b88ba, + 0xebe50b83,0x59b8371b,0x866706a6,0x0cc69508,0xf8373d2c,0x531c75a3, + 0x2a5a02fb,0x4e1cd3a3,0xda39a1d0,0xe8274778,0x75da333e,0xedfc5bbb, + 0xca79bd36,0x15941f24 }, + { 0xa77dd512,0x42e8c0f8,0x1dc365f6,0xa91b59a7,0x08753862,0xe80d14cd, + 0xd272faca,0x1624230d,0x4027cb5a,0xeea3ec16,0xc1ef9f03,0xc1700b59, + 0x0da3148d,0xd411c127,0xc4181af1,0x801ee448,0x9e3a900b,0xedf28559, + 0x0d09affd,0x5d67b0bd,0x8b370024,0xd839df96,0xe6f836b8,0x3b6307e0, + 0xbd3201c9,0x5382e588,0x7a1d02bb,0x636d8a6b,0x968641e9,0x70b7db76, + 0x118fad03,0x6d17c34a } }, + /* 202 */ + { { 0xc181c99b,0xcf608841,0xc87bdcaf,0xb65dc901,0x3720dabe,0xb460b447, + 0x5377515b,0x4c79c396,0x0a96c277,0xd447f22e,0x2ac0f440,0x0d952130, + 0xc90583ad,0x8330b26b,0x928904a0,0xe25e977a,0x85c50b18,0x1deaffd9, + 0xa5ad5f6a,0xcf4dbcb7,0xc8a37ed5,0xcbcd0019,0x1e9850b6,0x7846dd90, + 0xb0b8e605,0x1ac8194a,0x34132f90,0xb9728571,0xf56ee28b,0x4ce9f149, + 0x3e9e1d4e,0x1ab9b5a4 }, + { 0x314fa7a3,0x206dab92,0x478ff963,0xcc4af0f0,0x904d9fdb,0x4cce1713, + 0x12c045fe,0xac20a2eb,0xfd8f6d7d,0x44fc5478,0xca7b6ffa,0x886e72c5, + 0x6fd6f758,0x7fa4529b,0x92a820d5,0x4df1d1b1,0x2789f149,0x3d812f9f, + 0xaabb53d2,0x9842f083,0x2a03ab32,0x2648539b,0xb1512502,0x631ce090, + 0x731f6bd5,0xe1294d15,0x9436e634,0xb229361d,0x3ca966af,0x8c4281c4, + 0xc21ab3ed,0x24b34956 } }, + /* 203 */ + { { 0x659824e2,0x49bdcb86,0x4e13e74c,0x6dc4ce48,0x6bbe1eea,0xa4c01a26, + 0x1e3ec457,0x47b2b8e7,0x2f5a8e4b,0x7e8b15e0,0xe333530d,0xe81eb6e6, + 0x17a45202,0xacba369e,0xd70e4c9f,0x81241431,0x3e12beb8,0xc190af4b, + 0x11f486fd,0x53270523,0x29fb2bce,0x9f6c41e1,0xb70f6c08,0xbe6287eb, + 0x3feb4477,0x1479850a,0x9bcf18bb,0xfcfdfb11,0xda80d040,0x925c292f, + 0x7e3c5bf9,0x212d65e5 }, + { 0xca15cf08,0x23adb386,0x81e172eb,0x4dfa4ac4,0x4d42d0c0,0x9d1dbf93, + 0x74404dc7,0xd9cf6073,0xe932bfcd,0x60508441,0x1c682a98,0x9ae910ca, + 0x41ac1cc0,0x9528fc18,0xdbbed630,0xe6a120ae,0x30ccf250,0x94e0e1ec, + 0xe58bbf2f,0xfe84ba54,0x9faa4415,0xc66d0b4f,0xecee7ce5,0x0c58f1e7, + 0x6fa6873a,0x7a1d43eb,0x399f1348,0x96c6c5a0,0xe6727ab7,0xe6ef9aaa, + 0x9a5c2447,0x66afa554 } }, + /* 204 */ + { { 0xc980e91d,0xda5aaba8,0x6ac98efa,0xa93cf509,0x8da32662,0xb0990e0a, + 0x0081453e,0x01d21530,0x3d71de84,0x2bb0d33e,0x3e19a012,0x465f6d80, + 0x78a838e7,0x5902ff4c,0x1931348c,0x74e2afb7,0x9cfb057b,0xa4932757, + 0x3ad03f8f,0x761ea642,0x58ffa40a,0xb7d4c245,0x77a87e30,0xb5e9c0d9, + 0xc9c84d26,0xd1c5edba,0x3d1963a0,0xeca8839a,0xebf6bf0d,0xbc6f2f35, + 0x0d58abdf,0x01ef0631 }, + { 0x3ecdcbb0,0x2bf90316,0x27c1c955,0x19e2d728,0x9575c930,0x9e527030, + 0x96983930,0x0dc1c5a9,0x7cd082df,0xef9f80ff,0xdf97e051,0xcd915075, + 0x9cc61b55,0xf286fffe,0x80f24cc4,0x352db38f,0x36523ae3,0xed9b99ec, + 0x10b104a9,0x109a8ca8,0x305203ad,0xc2700fe7,0x769400f5,0x2a2ee24e, + 0xee0c452c,0xd595d399,0xf7f02a41,0x0ab75d6a,0x0db730b7,0x34108099, + 0x5e8d1202,0x0e4f5ffd } }, + /* 205 */ + { { 0x0ff14c38,0xbd1c6444,0xaece11f2,0x9a5b59fa,0x22af6330,0xaa4605a7, + 0x82af24ee,0xddc9f65a,0xeb9a1159,0xf4ee4bfe,0x74e84eaf,0x2463d076, + 0x0e0baace,0x88cbe1e0,0xd5fabdcb,0x7ca568ea,0xc57eb99d,0xbd80d524, + 0xe9be9873,0x9c46572c,0x7300b85e,0x918a1dcd,0x40f54176,0x49221312, + 0xb5b14236,0xf7e324ff,0x2434f16a,0x40dda501,0xa133d97c,0x08833421, + 0x0876f020,0x33d41161 }, + { 0x9878e5ec,0x7531a36b,0x46918232,0x5de3e321,0xd0a30464,0xd15f9a33, + 0xaa173659,0x734c1b87,0xf925d4fe,0xac2094a2,0xc262b0f4,0x43c965a1, + 0x447d5cbc,0x759c903e,0x05239300,0x92af215e,0x1f593f34,0xfffb6d5f, + 0xc3cddb5f,0x65943b4b,0xbfdd5408,0x9d03a29c,0x198d76c0,0x8f7cda6b, + 0xc0f27b59,0xc0790a22,0x8cb58ccf,0xba557a84,0x76c54fdc,0x5922052d, + 0x47b6b466,0x2d3de7aa } }, + /* 206 */ + { { 0x65add3b7,0xaade7462,0xabf24c2a,0xe5888f35,0xe1a57d93,0xd41549ca, + 0x2c76f7bf,0x0e22e18e,0xbe3202b3,0x67f288ea,0x1d1d0f0a,0xb79a66ba, + 0x2881ad18,0x0e0ab749,0xc7adb0e9,0x7d424086,0x2842132f,0x870c32c5, + 0x58f9a09e,0x858477f1,0xec025589,0x422a9372,0xa5098777,0xbe428c5c, + 0x57660058,0x45b79564,0x957f37cf,0x6c7fc631,0xd6316289,0x8b7023dd, + 0x5b1c12a6,0x47003bb6 }, + { 0xc91c1c96,0xd99401c1,0x27a12970,0xaa5dcdf9,0xc3c29107,0x3ab92e17, + 0xa3fe4710,0x26fce8f7,0x4ee998ee,0xb0d09d5e,0x8e3a41f8,0xafa62204, + 0xa26ca506,0xb1c012a5,0x99b57252,0x2c6f734c,0x512f7fe1,0x1093d79f, + 0xacee19a6,0x2f30906e,0x056d1ea6,0x6bff8381,0xeff35f21,0x61c75856, + 0xc1ad2224,0x6e07e978,0x6b20fde8,0x2cca6ca1,0x633fe81b,0xab4d6d2d, + 0xb06a2ce6,0x73dff504 } }, + /* 207 */ + { { 0xd8e20fb8,0x8b615805,0x82b533f0,0x7c6873e4,0x56a854ca,0x5205f001, + 0xcb369211,0x87fec6ac,0xc7f092b7,0x1fa3c0ec,0xe845fe4c,0x5b36647e, + 0xf8b1f112,0xd4781e85,0x8b0f1a6f,0xc6526839,0xdcb8eb92,0xceeb8c6c, + 0x8e5f6d52,0x133f0ead,0xc8d934dc,0x31883e23,0x428ac45a,0x214ed5bd, + 0xdbbfca85,0xf77ca492,0x07e5ae13,0xdf4113fe,0x72ab05fb,0x63e4a0d2, + 0x7148f535,0x7544d0b7 }, + { 0x80797ace,0x4fe8d134,0xaf86d97e,0x216d6aa0,0xef5a68fc,0xdbf0a688, + 0x9f9b2684,0x18b26f45,0x8999d2fc,0x52fefcfa,0x62423955,0xd5af8d82, + 0xf63a3780,0x8f123469,0xdcd4feaf,0x2933454f,0xa73b5d09,0xba8018b7, + 0xe5552c18,0x9af1f276,0xff26bb1c,0xc5d4773d,0x06dd4f44,0x9ef49410, + 0x5f39ba49,0xad8f12f9,0xf66ca4f2,0x5767f6dc,0x7922f59a,0xba8773f1, + 0xc1e42d49,0x220081ea } }, + /* 208 */ + { { 0xba37a0ba,0x3043d573,0xdd176df6,0x05a431bc,0xc42070f7,0x03322cfc, + 0x67c2d109,0x5cabd30e,0xcbf8bcfa,0x362c95de,0x7787b10b,0xd767d277, + 0x6ec05e64,0x612c915e,0xce69c30e,0x9e669631,0x682e2635,0x27c9dd8f, + 0x95ffcc38,0x79021f12,0x8a2adca2,0x06a8ee79,0x4b5d500a,0x8e00e784, + 0x8d80d6c5,0x87746fc7,0x915f10cc,0x246053be,0x219f6fd8,0x844e328b, + 0x11bd3733,0x620541ac }, + { 0x509e5a29,0x0f7fd382,0xb432531e,0x8748d7d0,0xcd3883b9,0x8f749354, + 0x8bfbb17a,0xc6b8ac74,0x05f2d2c5,0xa4616a66,0x1bcb1b83,0xb3d96625, + 0x2fee265a,0xcf753104,0xdb225058,0xc70d73fb,0xf0c2d556,0x1211d434, + 0x54b259b3,0x862061d8,0xc42b3f7d,0xffe4606d,0xe86a4949,0x4c5c8585, + 0x160eedac,0x04ddcc8b,0x568e2420,0x1804ce67,0x42141656,0x91f3855a, + 0xf932be97,0x7f378198 } }, + /* 209 */ + { { 0xdfa6639a,0x9a374bda,0x02ab7391,0x0cbd48d4,0x47031e2d,0x5c5ef236, + 0xd0599d1f,0xb49ee2bc,0xe0d38443,0xd285eb60,0x269392e8,0xdbbea92f, + 0xb8bc538f,0x91455fbf,0xe469b768,0xae259ff1,0x41de5682,0xc1cecb1f, + 0x9952d1ae,0xc876f071,0xe7bf7446,0x1ce25181,0x282ad2f1,0xcb93ad86, + 0x6ba4ef67,0x8fa3cd31,0xe507aa3e,0xfce68a04,0xa61bb608,0xced74170, + 0xf6ac10d0,0x6de716b3 }, + { 0x172d6dc5,0xd4e58d04,0x6397c65c,0xbed2cde6,0x0c9eb4e8,0x7ae77e18, + 0x75fa2edb,0x56275468,0xa91e6738,0x4b30324e,0x235c8b2e,0x6023a856, + 0xa8f92887,0x9df6d6c2,0xf6f5e8b5,0xec2c185f,0x3ad5748a,0x7892e12b, + 0xd54aefbc,0x7aebb4f2,0xee868821,0x14915448,0xb1d9bd5b,0xa26c5f71, + 0x2ff00df7,0xe5ccd166,0xb95b1dee,0xebc99f17,0x3fe1f774,0x90983616, + 0xbb3d25b0,0x51f90830 } }, + /* 210 */ + { { 0xf2922461,0x49376fa1,0x1650d0d1,0xdbb1b1c3,0x0dd8608d,0x92b91c33, + 0x36b89906,0x3e612c4b,0xdf560052,0xe1977b0b,0x636a2545,0xf8afff70, + 0x11723d8e,0xcda7d278,0x81bde7ba,0x0b0bc4bb,0xed2a578e,0x3cb080b2, + 0x171b2e02,0x5bda0d0d,0x941bb9ae,0xf6df38cf,0xc14a65c5,0x85dd81db, + 0xc19dd98e,0x7f98c82d,0x52206f93,0xc613747f,0x5f5bbe78,0x9e13a2c2, + 0x0aa34be7,0x5eed218e }, + { 0x01d4dc0b,0xe1565754,0xf566bb07,0xa1ae5f27,0xb82225d5,0xe985ebeb, + 0x1189ec6b,0x5f3ad21c,0xecce4d9d,0x17da518c,0xd6b65b59,0xc84a2d3e, + 0x8ffa771c,0x7f988175,0x2ac69a7a,0x50d6ae12,0xc6e6846d,0xcb7f30b1, + 0x5bd0bb13,0x8c023a60,0xd73f2407,0x9a10fecd,0xe5f0a996,0x8c5158cc, + 0xbd8f5806,0xd26bf615,0x915a46e1,0xaf32ea87,0x0287d308,0xeaf74e81, + 0xa6264254,0x8c14ba06 } }, + /* 211 */ + { { 0xb17ee201,0x0c877895,0x88e57a77,0xc05aa471,0x97822456,0x19c3e763, + 0xc9c3ba1d,0x0be6f8c0,0xb4389ebe,0xfe85f4ff,0x0ce7fbb6,0x538bccce, + 0x65266c64,0x876eab2a,0xcf9a3842,0x5c9ac690,0xccc8f981,0x9f5cf3b1, + 0x9cf687de,0xfa17be6a,0x83835c15,0xfcfc10fc,0x150ef2eb,0x086b0fdb, + 0x884a52e6,0x9f97ecd9,0xb0cd1eb8,0x416e6fa2,0x3ecc03ba,0xe2bd1599, + 0xeabb165e,0x645c0a5d }, + { 0x50aa7e31,0xd94c4205,0x2f851da5,0xaec8df0c,0x3c726e6a,0x99646909, + 0x2619bf9a,0x72dbdc36,0xe253fbd5,0x1b4260e0,0x8c709e06,0x97c259fb, + 0xcddaec5b,0xfabf7cbb,0xe4b703e9,0xb4d5e8b1,0x0734efdd,0x1b06e56e, + 0x1f55f8a5,0x02d4a4f9,0x3f565c8d,0x7f8608ba,0x816d1d94,0x822f47d2, + 0x5ce7b136,0x0cc36156,0x31d04242,0xe46ee5ef,0x683567f6,0xb2a65f70, + 0xd2fa6c91,0x27e9ff40 } }, + /* 212 */ + { { 0xd7e952e7,0x75251893,0xc735bf18,0x15b30583,0x96fe0491,0x732b5992, + 0x806d2fca,0x27451858,0x1b885ed9,0x71ab76a0,0x6d9f55ec,0xbdce9d97, + 0x48f2ba9c,0x3da60b20,0x592b132b,0x6977c086,0x099051d7,0xb6dca9cb, + 0xd188ae25,0xd9c2ab23,0xe20aaf3d,0x9f469f3f,0x5aad74d0,0xdbd1f7cf, + 0x22a9eb3b,0x3d5efe5c,0x137010c4,0x8c5edfa2,0x57870260,0xada2217b, + 0x3dac9776,0x4feee567 }, + { 0xb5d3d780,0x30e18d52,0x07166744,0x4dadb5d3,0x5a742156,0x320d386e, + 0x8d6bbb86,0x5d8c290e,0x2d263dd1,0x981a4323,0x98984636,0x33d0e7ca, + 0xa519acb1,0x5138784d,0xdddc81ff,0x832e3fab,0x3199a43a,0xfc278594, + 0x32743163,0x5b4cabcf,0x74f94fa7,0x9fa010bd,0x5694a627,0xc28a743d, + 0xcb657a24,0xc1d2a888,0xe86a25ea,0x7eef2503,0x04c561ff,0xed11a5d3, + 0x9c9ede0e,0x4fe818e7 } }, + /* 213 */ + { { 0x7fc1c7ff,0x00252c9d,0x9fa89ad1,0xa9bd419d,0x4064e9cc,0xc93a124a, + 0x43942ecc,0x384cbcb8,0x8749695b,0x004c21fd,0x421165bf,0x69c81d9f, + 0xdde01102,0xe2325628,0x5a9b004d,0xec937457,0xf6dcfc21,0xfb3346bf, + 0x4d372c7d,0xac4da64b,0xf20494e2,0xcecb7ad3,0xe867c150,0x562c41b5, + 0xc2b723d8,0x299395ce,0x7ee53231,0xc91adfc5,0xf10b6597,0xe06f1161, + 0xb74d3ffc,0x81915529 }, + { 0x6ed9d4ee,0x8ec12431,0x689aff01,0x3dffa154,0x2a89a3f4,0x4aba349f, + 0xd467efb2,0x2db1e8e2,0x039102e2,0x18dea354,0xe52f082b,0x422ab853, + 0xed36dd47,0x7130a2c1,0x0295d1ee,0xca60e86d,0x7c7f5ad3,0xe6ac6808, + 0xde864658,0x0f83cecf,0x461d1265,0x72e66c21,0xbd385099,0xfeef4150, + 0xa6632289,0x0f183f3a,0x792dc795,0x275454be,0x11367702,0x2744c11b, + 0xe8ea6ef3,0x7d06bcc7 } }, + /* 214 */ + { { 0x7090212f,0x89285942,0x5521e844,0x691b7d4c,0xbe2dbb92,0x4c038422, + 0xbd81f880,0x317721ed,0xac89bc36,0xc136cbee,0x7b8f004d,0x4f71b60b, + 0x4e218ab8,0x269132d0,0xe6cc814d,0xb0e2496e,0x75fadc15,0x0b2ce317, + 0x66d223c5,0x82e3c084,0x4c612f8b,0x9721caa6,0xa4b65355,0x59a751eb, + 0xc7d3d9d1,0x3433aad5,0xe80d4246,0x1e61b9d2,0xfc673caa,0x149f655f, + 0xd0f9cb92,0x48b52b99 }, + { 0xefdc05be,0xa3915399,0x13e095e9,0xde70db18,0xcddb3fda,0x447862e9, + 0x1a009451,0xa2b03162,0x23920ea3,0x4b27980c,0xa23b8feb,0xac5394f1, + 0x3e5616d4,0x163f7256,0xb714219a,0xaa0ff93f,0x93d62474,0xd26f96d2, + 0x7dcfe276,0xdd212ea8,0x47038d15,0xab27bf2f,0xf418168e,0xe58c8325, + 0xb32a989a,0xe3704222,0xbfc9f13b,0xa3694390,0x0d0684ad,0xf16e2606, + 0x9d8c76ec,0x17c0de87 } }, + /* 215 */ + { { 0xdcc01958,0xbca5f453,0x1ce88393,0x7d945954,0x561f5b6d,0x5e6350a1, + 0x7e2d36bc,0x291c3c86,0xa5ac3a6c,0xf6c7ed84,0xd98006cd,0x7913c40b, + 0x5671ec3b,0xf78bb087,0xb43e89a9,0x1c928f6e,0xae1ea1ed,0xfdf28df3, + 0xb924b2b5,0x62bba5b1,0x1a116e05,0x491d2705,0x167ed3e3,0x08ec02b7, + 0x5bc0b046,0xe291cf7b,0x8c5d7f59,0x30e50169,0xf5c799b7,0x0c7c350d, + 0x0ac6e1d7,0x6862b9e2 }, + { 0x9ffa1f64,0x56c6f4e7,0xa1e24349,0xfed6a91a,0xcdb75232,0xe9a0ee0c, + 0x0322d607,0xbfc90b37,0x462fef87,0x29480ad2,0xc2bfcf34,0xfc214969, + 0xa539e38f,0x6e5211e0,0x12a5149c,0x2a59ec26,0xd706b532,0x195fe212, + 0xe99c8429,0xf77fb108,0x5dc80482,0x74ceaea3,0xbd92d298,0xa5a6030b, + 0xaaea15ee,0xad42dca5,0x4987109c,0xd6ac3bc7,0x290af649,0xc64e1c40, + 0x51f8de6c,0x5093fa2d } }, + /* 216 */ + { { 0x4c2d553b,0xc4cf3280,0x3b966c29,0xdc1abe22,0x2296914a,0x556a549c, + 0x999976c9,0xd8c9f8b5,0x776e83f3,0xc22c57bd,0x7c85ec57,0x4f2942ab, + 0x6e2c61f5,0xef3407e5,0xf213db48,0xf005e8ca,0xf32698c7,0x470c853d, + 0xcac0a54b,0xe6f488d7,0x60b7501e,0xb6bd6bed,0x714a4bd9,0xf0103106, + 0x6e098894,0x5285bc3b,0xf5f92a00,0xec06741a,0xef7ef24a,0x32f16426, + 0x6c77a438,0x12f9c44d }, + { 0x83313a1c,0x1951e964,0x33c58b37,0x98edd3da,0xc7ac4044,0x4edbbf52, + 0x0dcb5ee8,0x866ca6f7,0x6dd422f8,0xec0ae8f5,0x0661ec2e,0x1077bc54, + 0xd422523c,0x6d39913a,0x58e7cb3e,0xd105e1e8,0xc979bb45,0x47c9397f, + 0x0997b592,0x3221d4a9,0xe8952fe7,0x0ef628a3,0x4e946241,0xd08d5827, + 0x59780f40,0x64cbed0f,0x08e110ec,0x13d7c227,0x7679b1a3,0xd186d866, + 0x26ae1d18,0x02f75e4e } }, + /* 217 */ + { { 0x47f307d7,0x1b637ebf,0xd0141477,0x6b644a6a,0x2e05a80c,0x82a33d65, + 0xfed07b31,0xc8f1a0f3,0x3696e597,0xc09ee7f9,0xc7ffc01e,0xcdaa7ec3, + 0xf8f373b9,0x549f88fe,0xc3bb8989,0xc88d1961,0xdfcaa7b7,0xd92a4fe9, + 0x3ae4ab20,0x12ff9ee2,0xf5ecb1a5,0xf5aea641,0xe32fb47d,0xe769237f, + 0x25d085c0,0x96a5c420,0x26c755a2,0xdc912558,0x9bce9723,0x580b985f, + 0x63961941,0x72b1b566 }, + { 0x790e5558,0x9d708a08,0x0689af80,0x98536041,0x42313b5f,0xe85e7b8a, + 0x55a49d1a,0xe6ba1292,0xac371b0b,0x5e76c4b0,0x938e6e19,0x58504f39, + 0x60ae9a21,0x8dd41422,0x968485ce,0xd8b04e9b,0x887efe43,0xf94c4ba5, + 0xf11c5e73,0x11268e67,0xcf6b99c4,0x92623e28,0x7a0a9662,0xf2d0aaa8, + 0x4ca02ed3,0xb266772a,0x2d63b551,0x68ee8e4e,0x2e78b5b5,0xcdebb299, + 0xe17225ad,0x5df19216 } }, + /* 218 */ + { { 0x8df2e7e3,0x20027e1e,0xd8da07de,0xb183cc68,0x4b4ae694,0xce35ba69, + 0x3ca62e88,0x896d97df,0x52efed2c,0x3de4713b,0x26bd084f,0xd006c40e, + 0xfc81923b,0x1e9b71bb,0x1aacc6b0,0x9991c7b6,0x8f656840,0x650c9364, + 0x87f47524,0x138561d1,0xbffd3ca2,0x610f2b11,0xfa191418,0x96915faf, + 0x955e5309,0x8f1236de,0xa1872d79,0x613cbeea,0x66a2a48b,0x7f7b44ea, + 0xe0a89c32,0x452265c2 }, + { 0x25430010,0x4ad5ec79,0xebd090c0,0xcac786ff,0x20a9d3f5,0xa5f9f4ff, + 0xa3edc65f,0xfcbf4112,0x0cf3eb11,0x8824839c,0x8aa5b700,0xb8dd6d4e, + 0xb7568ab8,0xe2271dfd,0xb744560e,0xe43ec373,0x1cf75296,0x78eaf926, + 0x3fa96d9b,0x1809ae0e,0xdc25dfd5,0x0b312d2d,0x6bab7711,0x6b8f78b4, + 0xb5ecf1e4,0x069efc8d,0x609fecaa,0xc1952bae,0x5f4dbde1,0x43e302ed, + 0x1e078555,0x14b02bf9 } }, + /* 219 */ + { { 0xb87e5b57,0x2c71c768,0xf531a557,0x0bcc78f7,0xf7597dc8,0x4ff93f8b, + 0x139e175f,0xb28e026d,0xcb94ca6c,0x6b83b727,0x0079f7fc,0x2eafe3b2, + 0xcf3bd170,0x2aca54de,0x6af0dc6c,0x17c4133c,0xccf5e35e,0xbea1e665, + 0x345505c6,0xa6691a48,0xe6100b89,0x2633abd0,0xc17d0388,0x966c6706, + 0x1a0cf90c,0x7aefffbe,0xd0add64c,0x4d847be7,0xaea2aa46,0xd49bcdfb, + 0x2cc7d0a5,0x85e07e74 }, + { 0x0bc25bca,0x23aae0a6,0xe44f64ec,0x6e8e55f1,0xb607b773,0xe1e696d8, + 0xd3005909,0xaa90a746,0x2cbc4990,0x072b1ccd,0xc68e2f5d,0x0d0fe6c6, + 0x53e28ec9,0x920ec5f0,0xf0040cc1,0x79b21fb4,0xfcc4a2c7,0xa7375bd3, + 0xe1bac7dd,0xf5f5def9,0x35c0f8d3,0xdc315d79,0x2cacd318,0x7117c170, + 0xe926f71c,0x6f2823c4,0xed02f39a,0x38db58bb,0x7db69323,0xe5b49231, + 0x8d49f430,0x0964039f } }, + /* 220 */ + { { 0x56999eba,0x21774f16,0xb1de6305,0x3d8ee287,0xde0b2669,0xd81af726, + 0x3f8942a1,0x37446939,0xea03e13c,0xbcf6b615,0x94e273cf,0xd30c0c35, + 0xc6725c56,0x4fd33a56,0xa8be97a2,0xa57534ad,0x7c22a251,0x799242a6, + 0x9d0c5c49,0x4e51bdb5,0xc6a42768,0xd7cd76cc,0xd426bf59,0x914097ac, + 0x66e9beb2,0x59404a2c,0x5c96e3e9,0x4738fe98,0xaad666d0,0xbcbb3e0e, + 0x63bc5e56,0x626b0fd2 }, + { 0xe1a1ec42,0x47217dba,0xab5acc50,0xaa6ae7db,0x865331d1,0xb7e1ab1e, + 0x3d30126f,0xb8453070,0xdee61851,0x280649e0,0xea689544,0x8806f4a3, + 0xcb56f632,0x4bbe43ad,0xbcaff94f,0x036b9bda,0xbd0637be,0x0d941e65, + 0x686f3abb,0x82179d44,0xaad6afd6,0x1486912c,0xff7e1534,0x9a3b891e, + 0xeb86fd96,0x88c426ce,0x117928c3,0xb56e6a81,0x96399e00,0x933e7135, + 0xa17b6ac1,0x09bbddd9 } }, + /* 221 */ + { { 0xe4fd3673,0x75e39c1d,0xa65c8e07,0xf880d9d1,0x7289c7fe,0x4725c1dc, + 0x3529d200,0x5b6735ee,0x3c747af3,0xc1f8f2ed,0x912efdf5,0x5cf3998f, + 0x49859c39,0xed722618,0x0e69795d,0x23793a2f,0x86b1d2a7,0x8a6ab8d6, + 0x22a882e4,0x00c815de,0xf9db8d7e,0xbe77d6fc,0x02267547,0x0886fb32, + 0x49c10edc,0xb62687d4,0x7c83ed4c,0x9f1c3e17,0x5af366ea,0xe6d5d7f0, + 0xd1efad24,0x2eaa01b8 }, + { 0x1f357c74,0x5e47fb70,0xa9e3b794,0x93085c4a,0x6e85a905,0x4f098733, + 0xbe0244c9,0xf53808ff,0xa3b5660d,0x91dddf93,0xf3b95ed6,0x8b76377b, + 0xbb3920d4,0x91b911b7,0x86a13cf3,0x7ccf08bf,0xea018e58,0x53ed8f97, + 0x78c55194,0xb1ea4343,0xe0d2d5a6,0x8e6adde9,0x9b96259a,0xfc2b248f, + 0xeef17ddd,0x96ebceae,0x557f9c85,0xf694b443,0x07d5bba8,0x48cd150f, + 0xb4c1986b,0x02d31de9 } }, + /* 222 */ + { { 0xde79499d,0xa6bb9e1e,0xfd0fc2ad,0xf6ca8ff8,0x1a7d9356,0xbec0f8e8, + 0xe8f06327,0xbc3d1c9f,0x3b300beb,0x805c7217,0x413c181b,0x00420a08, + 0xf0ca9d01,0x9e9a167e,0x1aeeddd6,0x076c909d,0x8e3a8a72,0x64a1997f, + 0xa77b429e,0x3ce7f7a7,0x5c94d3e9,0xaac0fbf4,0xe6d48407,0xf37694a7, + 0xa91921e7,0xf56679e2,0xee1dbbd6,0xf23fe0f3,0xcbf9fa99,0xc7917566, + 0xe0f4d765,0x965860f2 }, + { 0x7fa5f79c,0xe734702b,0x5af2d26d,0x930bd426,0x6c73e0ce,0x45bd8b98, + 0x4ee44a2d,0x7dbe7bed,0x956c8a1a,0xc129e024,0x77cdf80e,0x6fdc05ac, + 0x589ca59b,0x70a6ba2b,0x999825af,0xfc484021,0x7a23f0b6,0x1d284b54, + 0x28a0a8af,0xb1da10a4,0x2b2af6d8,0xb1eb1b31,0x33935ee3,0xf051443a, + 0x8effa6ec,0x7a07eb26,0xd662654c,0x16ee4086,0x4549ee4c,0x7a7bc501, + 0x1fa98a52,0x65081032 } }, + /* 223 */ + { { 0xb67ed9b2,0x49f0e460,0xc36d93d2,0x0cda0fd0,0x88c75e1c,0xbb5963e9, + 0x614bc0c9,0x757bbe93,0x9a768605,0x9a9b8801,0x48edc544,0xa8b7e2af, + 0xb51a5985,0x9e77ed9e,0xebbf024c,0xdd025274,0x1545c636,0x598b6288, + 0x4800dba0,0x39bdaed0,0x81e2a23a,0x7fc20139,0x550cb4f2,0xdc66fd5c, + 0xb52068c7,0xad27032f,0x8169fa15,0xc9a0bcae,0x3a7ca8a2,0x60606f21, + 0x9862652f,0x98295046 }, + { 0x2e11c128,0x3e374600,0x0e6dca7e,0x80dfae5d,0xd9552264,0xe44016e2, + 0x880b7143,0xf65f88f2,0x526b881c,0xca3d28d4,0xdfb86afe,0xf9c59dd1, + 0x4c74f958,0x548860c2,0x9cb69f4f,0xd06ea43c,0x7334ecec,0x5343c9ae, + 0x35329713,0x5cc2ccd6,0x5f3a6c0c,0xa95ff403,0xb372653b,0x2e01a1cc, + 0xa250523d,0x31510fdf,0xa6227eb2,0xeee538e2,0xca23cd10,0xeadfc8a0, + 0x3e78f54b,0x4b7e6e1b } }, + /* 224 */ + { { 0xdb5f928b,0x79c9076f,0xb7347cec,0xe6250bb6,0xac00ec41,0x54b67798, + 0x9d9619c7,0x900d20ba,0x59e4343f,0xed42c0d0,0x451935d7,0x3df39e85, + 0x64f701ce,0x26391182,0xe1f87aac,0xce8f2554,0x65f91aaa,0xfddd6789, + 0xa324539f,0x96cd163f,0x4bace995,0x5c815f2c,0xa94f9ea5,0xd78c8c2a, + 0xef24e455,0x7ab2aff4,0x1cddc26a,0xf0ed6409,0x00ca2822,0x954a420b, + 0xd3297658,0x0611c4c5 }, + { 0xa9e81829,0xf192001c,0x08a282cc,0xded33320,0x8f9ded9b,0x0bfd7de1, + 0xb7889003,0x6793ac0d,0x3577a5dd,0xbb00d91d,0x802d3c2b,0xe17a23a7, + 0xfb549014,0xff95f88c,0xc71b6e07,0x7cd1bf4b,0x23588c8b,0x2e3b24a0, + 0xa4112076,0x9b5335b8,0xc4056d30,0x2481c05e,0xe916a1b5,0x55c7410c, + 0x850179f4,0xbbe03271,0xb3cd1208,0x15e6c177,0x90cbfe50,0x509a24c0, + 0x1c108566,0x82079529 } }, + /* 225 */ + { { 0x1c7d353e,0x5d2d3cff,0x7de0ce3b,0xd5e7eccd,0x6ca87635,0xb4b1075f, + 0x25f9ad3e,0xda8404e0,0x205cb5ae,0x6b963e89,0x09f221a1,0x9e5ee0d8, + 0xea41aca4,0xd64c85d9,0x34442a34,0x6a46c4e9,0x3cf655a4,0xac6ff97e, + 0xe5417d7c,0x76565c1e,0xeebf9c4c,0x681009a9,0x88da6388,0x95b61d39, + 0xf6b472c6,0x6402b46a,0x0b7f1171,0x1fde5165,0xbe0c05e3,0x94f8f273, + 0xa88344a7,0x7487b036 }, + { 0x9c3e2370,0xa860e575,0xf8048719,0x19d58193,0xa6e2f9aa,0x3a0dbf3c, + 0x6144719b,0xb6c7e959,0xdeffec21,0xa9049c74,0x3f50cebf,0x8ba064b2, + 0x49a1de15,0xb12822c0,0xb1d527f2,0xb654b7d9,0x0ffd0430,0xc470859d, + 0x4f05446b,0x37c74a67,0xa3add995,0xe553251b,0xe33533b5,0x4a3ed6cb, + 0x27e419ce,0x2f2f44d0,0xa5d1b979,0x2d84ee82,0xdb6fa69f,0xcc76b123, + 0x21fa3bdd,0x834f85c5 } }, + /* 226 */ + { { 0x2ce9b31a,0x329347c1,0xfe3fb3b7,0x1d88522a,0x52ff90fd,0x4bcefb4d, + 0x2b1a081d,0x53b17386,0x2a411f08,0x538c11ba,0x141b603a,0x7895b93c, + 0xb10bd741,0x2993b9aa,0x09912986,0xccbbd046,0xeea0aba5,0x669fafb0, + 0x35661897,0xd4844622,0x367ffa54,0x4a63b89c,0x1c3478da,0xcbad5d1d, + 0xaa6034f7,0xc5339227,0xe61b1391,0x0e6d705f,0xf74ff515,0xdd14b660, + 0x5332b54c,0x639d8b0a }, + { 0x162217cd,0xfa423162,0x811c28e6,0x2e0e4a2a,0x21766dc0,0x68d9ce18, + 0x046a06ef,0x51263739,0xdde92101,0x44eea231,0x114298d3,0x0607c8f2, + 0x63d957e9,0x27f272ba,0xa5e8cae1,0xe7ce80cc,0x24f7a63f,0x5816ebe2, + 0x89673e34,0x4dece5a7,0x536babd4,0x13756a22,0xe3bf77af,0x644d61ae, + 0x2bcf98bc,0x60b2bf6e,0x29fa962c,0x3b0b59f3,0xabb50023,0xb0769a1a, + 0x0c75402c,0x40903136 } }, + /* 227 */ + { { 0x1670433f,0x84d2873a,0x25493dfc,0xc9394df6,0x80fcf89e,0xeb05a19a, + 0xdb297616,0xe39e4310,0xd9e63046,0x50742dc9,0x1de9ca9e,0xf31ad8c8, + 0xfb7b1d0d,0x86aabf94,0x1b3c82d1,0x36cda27a,0x39702d84,0xfb1a2ef4, + 0x46081299,0x280bfddc,0xd2396238,0xe4b2b48d,0x7b3c9353,0x2db2c2f3, + 0x12fb8a69,0xd5b5b317,0x08180474,0xf9b87a3b,0x1e952578,0xd8590986, + 0xf37a2bc8,0x80668eed }, + { 0xb39a0249,0xe2edcd35,0xb2f8aeae,0xaf230cd4,0x7223df05,0x295b15e4, + 0xe0e937f4,0xbb66982a,0x8cbc9162,0x019d2b72,0xcf49dca1,0x5c512ae9, + 0x630f07b4,0x11b491a7,0xa03874e9,0x48d4f34c,0x44cb7433,0xc1fd0ea6, + 0xf95b30c3,0x13f79ae1,0xed8b60ac,0x40362d4d,0x61ead81c,0x9e8314ff, + 0x498c3d28,0xed600dd4,0xc2521702,0x5fcb1c19,0x3a9c1f33,0x592329fc, + 0x1bde6ce9,0x04677548 } }, + /* 228 */ + { { 0x39233c96,0xee3de56e,0x80737eaf,0x868c409c,0x201abc68,0xacae11bd, + 0x2b486205,0x0f2cea9b,0x6f19056c,0xe32387e1,0xa5dc2a41,0xea75365a, + 0x12b4be86,0x76c29acc,0x8d63294d,0xa01fcab7,0x0cab9f24,0x81dbe88b, + 0xf414c054,0x76646e5b,0xcb96b7aa,0xfe111893,0x7664e097,0xb649f5b1, + 0x53fcf5a9,0xa196422e,0x0b7ff634,0x5978c9bd,0x3c229895,0xb5feb38e, + 0x0833c456,0x038a49fb }, + { 0x13e93257,0x35e3818c,0xa612741b,0x14cebc9d,0x7caac06b,0x4f6e9249, + 0x3daa1116,0x82278e33,0x4de2034a,0xe7cc565e,0x0a1ba630,0xbb7dc95f, + 0x66956fbd,0x81dd9f23,0xbb132dd6,0xc63e6319,0xfc241337,0x6e22b022, + 0x7e8beb1c,0x23848193,0xd8c938ac,0x83b1994d,0xa6bb5644,0xb54cfaca, + 0x06f91807,0x1a7cd44e,0xa8f8d9f3,0x1dd439bb,0x7f74a8e6,0x660c2a78, + 0x121b5660,0x4bb76e22 } }, + /* 229 */ + { { 0xe6354817,0x7a151e8a,0xf038b438,0x33d494ea,0x85958986,0x4c86c688, + 0x1dcbac12,0x72153827,0xc0edad06,0xf487af8c,0xe500e5d6,0xad33051f, + 0xd6e47f55,0x0a711b1b,0x8c746ad5,0xa68709a7,0x6402f35e,0x27f17262, + 0xfb30c130,0xc6d08efa,0xc06c7497,0x9ef1c041,0xdcc3e2da,0xd0c74ece, + 0x092e1073,0x30c5f96e,0x2aa12b74,0x0f1393cf,0x2107eb02,0x24584016, + 0x7b76f98b,0x8843d25f }, + { 0xedb2a83e,0x4e1501dc,0x2bb8d724,0xbcfe8fb0,0xd925df62,0x09020659, + 0x42ab6fc3,0x3c715dcf,0xa0f09dfd,0x73c05055,0xe3590aea,0x126745d8, + 0x76ff749e,0x5382f4d8,0xa920c663,0xfc69feef,0x9fd711ca,0xde160211, + 0x9075c4d5,0x4219c3bd,0x3ded6bf2,0x3800cbd1,0x6263a116,0x8c7ea0eb, + 0x7d264c37,0x35bd7958,0x7159c98c,0x56e22e45,0xfa7373b5,0x71bf2a2d, + 0x8935c949,0x0503f939 } }, + /* 230 */ + { { 0x71dad4f6,0x65addc66,0x024bea1b,0x238e4889,0xf605d3dd,0xfb76c8e2, + 0xb0d96b89,0x13d5f5de,0x6601b2cb,0xe0b5ba35,0x83e3d254,0xe37d491d, + 0x240c8ea7,0xe8860423,0xe91c99ba,0x374182f3,0xa87ad919,0x26c2caf9, + 0xf574f295,0x4b13040a,0x944000a3,0x5b9bced1,0x06df42e7,0x4ccc57be, + 0x4bd1089d,0x22e8ec50,0xdddbb500,0x0c53177a,0x9ecfeadb,0x690d31d2, + 0x176668f9,0x735778fe }, + { 0x843c1137,0x0f86ee3e,0x3f0b73cd,0x3c1c42fa,0x8ab20e3a,0x0e75679d, + 0x16242fae,0x6f95f1f4,0x39b092e4,0x7b88e11c,0x4c236ac0,0x1629403e, + 0x2dac02e6,0x66105f41,0x862e0632,0x74dc28a7,0xf3b23c8d,0x2118ffb2, + 0x0745ffbf,0x1182417c,0x4c05711e,0x49b55a04,0xcefbe4de,0x2c665b74, + 0x97bf7107,0x1cc4c01d,0xc54f0676,0xb2ca06da,0x7450d0f8,0xfc599daa, + 0x1a3182a1,0x52e637a6 } }, + /* 231 */ + { { 0x6bebc6db,0x481700f1,0xf9503d92,0x4a6b45db,0x5d153919,0xc715cd3c, + 0xe5ad2abc,0x942a1c05,0xab7b466f,0x36a82433,0xba13918b,0xba413bed, + 0x90f4e6ce,0x698a5624,0xf3f1f3ca,0xbb720da6,0x63471ab3,0x2116d41d, + 0x303d3609,0xe00d2227,0x463ba69e,0x7fd4cc00,0x62845fd1,0xac609e4d, + 0x80adc9c7,0x63603b2c,0x45fafbca,0xbf16fc9a,0xc4bc94ab,0x41007f7f, + 0xa74b1698,0x7c916b4f }, + { 0x78bac2d4,0xc1026f91,0x2601a875,0x8a2e8098,0x0073d640,0xad2f276e, + 0xfcc1fb88,0x443610c4,0xca6b291f,0x5727b822,0x88ec60fc,0x0645532c, + 0xed9ad48b,0x51e48899,0xf543f103,0x841b48b5,0xd591ceeb,0xa6ccb1be, + 0x9dcf5a8b,0xfc4adf0f,0xb347ddb4,0x3a7ca020,0xcb44c521,0xaa1accc2, + 0x0527c0c4,0x773b6828,0x7023cf50,0xaa374c10,0x6b74c926,0x733d1000, + 0x77a8d07c,0x1ff3916f } }, + /* 232 */ + { { 0xf997939d,0xaa218fe4,0x791583b3,0x3d4dfbbb,0x87f7560b,0xb3a7b5da, + 0x5da92c98,0xa9c02801,0x46666f4a,0xe1eb4aad,0x14ce9dd7,0x2eb17a51, + 0xef8f3076,0xf46a66a4,0x810e546e,0x900b45c6,0x4baf04dd,0xf7af2258, + 0x5c84d42f,0x3cc1c872,0x8e4c83de,0x3093f225,0x170d88b2,0x62fade41, + 0xac076e44,0xe19612e4,0x32dd141b,0xf48d7346,0x925e34da,0xc1b1f759, + 0x072b90c9,0x19ed1a56 }, + { 0x6c735473,0x9cf7fcde,0x6003bc3e,0xaab88e67,0xfb199bb8,0x12187cbc, + 0x9accccbd,0xbb730441,0xb0f65459,0x214aff3c,0x6f926282,0x6aec81a3, + 0x9f9d20b8,0xaa82cb32,0x5773cc90,0x82f3f90f,0xf62257e1,0x4af60e6b, + 0xbd4762df,0xf18b44bf,0xdb970753,0x3948b129,0x7c22c18e,0xc6e920e9, + 0x57be97ad,0x393d6208,0x46b637f9,0xe8d7382c,0xf1fed1d5,0xf6625ccb, + 0x68681599,0x6f31e0f9 } }, + /* 233 */ + { { 0x82b8f204,0xc45afe55,0xd358b54a,0xac0441b6,0xacd5f5ed,0x7213e7bf, + 0x139bcd93,0x1914c70b,0x96dbcbb0,0x714b4581,0x1ed35d21,0xe9297d35, + 0x6a3e1f20,0x8f640837,0x2f3cd705,0x150a8a9d,0xdcdd9f6d,0xfb36e801, + 0x5cf56d82,0x5a54eb65,0x92aa5a21,0x7610500c,0x3b089f03,0xd10d0ae2, + 0xc42b66e8,0x491b2079,0x0eee8d48,0x4af1ae3d,0x41556f45,0x137e4c28, + 0x63d8a7e6,0x875e3308 }, + { 0xaf6c0acc,0xdc80fddc,0xbb1e7c08,0xd5ad1e66,0x828585ad,0xdc717ae1, + 0x275c7da6,0xbdc54340,0xd26b9e15,0xf4b4c852,0x6a05fa50,0x5f0a1fbf, + 0x817bcb32,0xc6f81e47,0x70ff2e1d,0x2cbd4328,0x67c7f7fc,0x8a249016, + 0xb585a6c4,0xd045acb7,0x4666c057,0x2e972ad4,0xe6d7d63d,0xc74d87cf, + 0x0e274144,0xf7067d87,0x8b2584ae,0xb2ca157a,0x75f0fdeb,0x495c5bfb, + 0xf386e009,0x5abb0581 } }, + /* 234 */ + { { 0xf0c97f57,0x8be62d2b,0x962f28c7,0x0fe04871,0x47b50abb,0xc548a467, + 0x44fa09ed,0xf6b26e03,0xab05a96e,0xfd44c6e3,0x70e6ae82,0xedb0032c, + 0xd7e4899d,0x28bd402b,0x9b7c11c2,0x43f2e963,0xce913716,0x0ec3fc0e, + 0x02fd0f8c,0x769b8bc9,0x7cabc3ac,0x9d9cb3aa,0x06924cc9,0xe88a8892, + 0x42609014,0xa51461aa,0x962e79e0,0xc7f4aa8b,0x8b1b3e80,0x4ef0210a, + 0x1bfee4bc,0x70544680 }, + { 0x121901c1,0xfab3d713,0xfead54aa,0xe90a2627,0xbc08ba23,0x64f6d285, + 0x36ec227e,0x8d993015,0x06c191ab,0x99a16ab9,0xf649ce2c,0x86b1cf5b, + 0x66be3a80,0x59206759,0xccba2cf0,0x18836279,0xeff53486,0x2c157b87, + 0x4b223af2,0xbfac9896,0x0aae7a57,0xcd0fd4f0,0x63218a80,0xdaddb940, + 0xdf88f14e,0x3844bb79,0xb71ed9fd,0xc1b3e3d4,0xd6205036,0x6c634a13, + 0xb8680a6b,0x6f56aecf } }, + /* 235 */ + { { 0xd9205c5d,0xb01dc803,0x67123929,0x68955f7d,0x9d9b6565,0x3debbffd, + 0xd3b1acfe,0xb844395e,0x6094eeff,0x04328b21,0x22991feb,0x6631ffa8, + 0x190dd075,0x0dde66e6,0xe8577c05,0x75b03c55,0x91722407,0x6c91ce5f, + 0x8ebb3a3f,0x9a288a40,0x058a1396,0x1d376f8a,0x9a6e0676,0xf3a59457, + 0x7b71d288,0x103029c5,0xb44c30c0,0x0843f428,0x730e0b9c,0xd8e6aff8, + 0x4ed644ad,0x7b6be811 }, + { 0x3d3aa54e,0x3ec38e4a,0xd83d509a,0x10233943,0x243955e2,0xf84aa621, + 0xf51d3d44,0x29104717,0x7eca4e37,0x62d2442c,0x85fa55de,0x8c5a523d, + 0x851da1b5,0xc6f5ccda,0x20001468,0x044bcaa8,0xe01702e0,0xf7501e68, + 0xe6a0acec,0xf0819359,0xac0ef0b2,0x33dda6ad,0xfd964f01,0x97aeedc8, + 0x530b90d8,0x48dacd0e,0xb84122eb,0x4c5fad6f,0xd700a1de,0x2284ec1e, + 0xdbca5474,0x86f9a835 } }, + /* 236 */ + { { 0x450cc69f,0x0e1d9055,0xc9edf98f,0x50eb14bc,0xee7eba01,0x1bb94e77, + 0x998f8e53,0x5f7a6737,0x1b16eef0,0x588384e3,0xd85c5e15,0xbb928723, + 0xcbd952aa,0xfe51e345,0x7e241674,0xc5d0ee28,0x100182f0,0xfdc146ef, + 0xe7f5be2c,0x0f739e92,0xb656bd3e,0x501ab3af,0x5168e289,0xb1552dde, + 0xb8ee104a,0x940dfe31,0xc4304475,0x42923603,0xc460a913,0x9306f114, + 0x03b51f86,0x5bfa9faf }, + { 0x107b258e,0x2a23f52c,0xd66341dc,0x989e82bb,0x823cff1a,0x54a3ced8, + 0x719b491f,0xf45b7794,0x2433dfb8,0x898c2218,0xc49250ee,0x0f9dd91c, + 0x4fa17655,0x50c2a2ae,0x2c327f45,0xf7aa1ce4,0x583b1e41,0x13a15ad6, + 0xa1bfad9e,0x9aa0d5a5,0x8e1fbdcd,0x9b1caa28,0x915f7f87,0xaf9283b6, + 0x87e81a1e,0xc10e4e0c,0x1080d296,0x04fdca56,0x12755bd8,0x6acc9616, + 0x828feeda,0x1b1266aa } }, + /* 237 */ + { { 0x774ee49c,0x4ebc0a00,0xcb6237d7,0x776f6852,0x5df938a3,0xfc0544ac, + 0xb6fbfbbd,0xc3388ec8,0x745f2eae,0x84ac8bcd,0xb1ece937,0xa9c56609, + 0x7de8fa13,0x656fb6ac,0xa532b871,0x5f8ded74,0xaa889f09,0xab0d428b, + 0x10b7aec2,0x43b27f28,0xfeecb34c,0x26426e1e,0x9e89c2db,0x44431b6b, + 0x39211090,0xaac4bc5d,0x4fd81058,0x926f7368,0x471ef60e,0x452fa691, + 0x218d7a23,0x33517fdb }, + { 0x593c4a36,0xa9c33f46,0x36b1a9ee,0xac69d718,0x4277beec,0x55a20c1d, + 0x7e4f179c,0x3e8ca24e,0xd46d88a2,0x57373369,0x730702f8,0x71ceb1cc, + 0x35eed574,0x8b184d97,0x0704cec2,0x7f4517a2,0xd7062a53,0x7f129d18, + 0xb1d77e1c,0x07a4571b,0x8350d8b2,0x774ac309,0x61fab8ef,0x27b2919f, + 0xb5dd801b,0xa7c4cc13,0x1434591f,0xe7e6255b,0x5a3592b3,0x349937b8, + 0x30c77549,0x31fac63d } }, + /* 238 */ + { { 0x04913fb6,0x2ee8cf1b,0x1769a6b3,0x7e401350,0x783e61f0,0x790ebb71, + 0xe27f2ffe,0x1e5107f9,0xedaf89bf,0x124ba67f,0xe58de68d,0x189200e1, + 0x6df5abee,0x962732a3,0xacbeb4aa,0x72cc37cf,0xe93c5a76,0xb0c5fa96, + 0xde63393b,0x4c2a317c,0x830b2d6c,0x97f65e67,0x1be5b96a,0x4afc3504, + 0x730ce66d,0x0bf40a60,0x9340d84f,0x96a1ba79,0x07626b08,0x3ee18254, + 0x7ab0cbf5,0x01db35db }, + { 0xac0efee2,0x6e0fbc2d,0xd71dbb45,0x8406ebcd,0x19b69abe,0xe72bde3e, + 0x37e01822,0x49cb7e61,0x11458b4c,0xcbb8c01c,0x687c5d63,0x420b4847, + 0x454c6776,0x1847dfa1,0xd1839d18,0xbede911d,0x278df046,0x1b9dc9c9, + 0x881a336c,0x294bd62b,0x93e77adc,0x7f096879,0x43ce3ba7,0x7ac90665, + 0x7764eefc,0x148695fd,0x9ac465cf,0xe0c20f0b,0xa6e2cdb1,0x636e8d28, + 0xd755341d,0x7b6ba98c } }, + /* 239 */ + { { 0xc1881ab4,0xcb1d9e03,0xb3168c88,0x19c25d55,0x282364ce,0xa82d3d47, + 0xf161aa24,0x95994390,0xe1ebb2c9,0x7838bc00,0xbdec7a75,0x8fd5dfcc, + 0x4ff7220a,0x4dd203c2,0x0efeff48,0x5ec173b3,0x16428b35,0x99f1d2b3, + 0x056e813f,0xc06bd9e5,0xc0b319f1,0x929172ba,0xfd223b15,0x6ae0e384, + 0x98d091ed,0xbd01059e,0xa654648e,0x6b3168e4,0x3375e798,0x2211447f, + 0x71eb4508,0x47e81019 }, + { 0xbc8c290d,0x7045d45a,0x810fb33a,0xa33d1355,0x46fbbf2f,0x2baf0092, + 0x385c7cd9,0xacff3f1b,0xe161985c,0xc5b150ec,0x2a888748,0xc6ee0a7f, + 0x5e88dcc8,0x9d888c8e,0xccb86443,0x4dd735f2,0x3c40f6f2,0xcc1e13b7, + 0xf3fed691,0xfc3a25ff,0x257ee5c7,0x4cb43b17,0xf32db135,0xaa654f93, + 0x02dff2d3,0x44f58d0a,0xa8ca6394,0x78e3f188,0xf3e86697,0x39646cce, + 0xe0dce87b,0x785b1902 } }, + /* 240 */ + { { 0xa92f9a20,0xfcce2361,0x9d64540e,0xb7bdca87,0x1d00d7c5,0xd4739a85, + 0x2e97c926,0x067ac8dc,0x78da6a8b,0x2aea3ffe,0x63c51b69,0x6828bf54, + 0x7155141a,0x76f1c479,0x3977d810,0xf4bcbef6,0x541bce7a,0x75bc4949, + 0xd17041a5,0xe01f4066,0x87755eaf,0xd282d5bd,0x59e7ae80,0x6e2107dd, + 0x382ab36f,0xaa56e166,0xb9d1d634,0x65ee8ef6,0xce4ed844,0x99a2160a, + 0xb7712c27,0x6557c367 }, + { 0xd75b6e52,0x561b0268,0x118d0e89,0xb0813640,0x6a2eb1ae,0xcff53330, + 0x6d090894,0x4e462226,0xb5fc1d48,0xbb351227,0x57a3062d,0x9365ea07, + 0xd66e2dc5,0x4caca37b,0xb9095887,0x220d7d23,0x8c4473bf,0x9c0fd393, + 0x6787da4f,0xadff370a,0xd057f4b8,0xef0aebcc,0x1173f33a,0x205e744c, + 0x925a26b4,0xb8d1f0a5,0x722fbbfd,0xa9364f49,0x8227d284,0xc891ae77, + 0xa0e08ab4,0x15c40d04 } }, + /* 241 */ + { { 0x2a0e18d1,0x9baf169a,0x4c0327c2,0x9971c017,0x7bc262ce,0xd81a323f, + 0x818ff379,0x2099db8d,0x4cd3c330,0x663f663d,0x011a0553,0xef5325c3, + 0xf980a470,0x9cd70bdc,0x1c9ed070,0xe64452d1,0xac676e13,0xafbf43f4, + 0xae85c2a5,0x97bec0a6,0x470490c4,0x2faae550,0x491e6ba9,0x0ab97a87, + 0xaafa9914,0x4055f537,0x36726557,0xfc95adbb,0xd119d6bf,0x646343b9, + 0x9d341e37,0x788e94a0 }, + { 0x9c53461a,0x053a6fe5,0x08e3b6ed,0x75ec897e,0x0768d939,0xa8f5d2f3, + 0xcc213d4f,0x9bd6bff6,0x05b0147c,0x590c7b41,0x7c7b8169,0x20a3628b, + 0x5bce78e9,0xc66a086e,0x4dec1d8f,0x3dd4d282,0xc19dcce9,0x890acf44, + 0xd8435a7e,0x6632d875,0xea6381b2,0x590167c1,0xf0dcc128,0xb2259797, + 0x46f8d463,0x91a612b4,0xc15efa39,0x42185d78,0x119f6788,0xdf55ec37, + 0x780dea93,0x91b19cc6 } }, + /* 242 */ + { { 0xcb5d8b80,0xebf2709d,0xfc35660e,0x03b96182,0x055ef969,0xb873d991, + 0xe47c4342,0xd1ea4b4d,0xd54f8867,0xcc4b9244,0xfd8d77ef,0x93b1a2ca, + 0xe8c1f563,0x068d24e7,0x49973056,0x5f5fabb6,0x0542374f,0x83248c50, + 0x3f38e913,0xc36de2b5,0x7bb680be,0xed07e8eb,0xd8f313b5,0x964813d7, + 0xafd2d392,0x7bb6a069,0x0848a31a,0xc06d848e,0xe4f0c325,0x6867fb2f, + 0x067343af,0x3c2ba834 }, + { 0x9d3ad63b,0xab62d775,0x59e0eb1f,0x3f9cab97,0x3885e117,0x70332a63, + 0xe20b2f9e,0xf22cafce,0x49eca947,0xb529ba7e,0x6228d88d,0x24954216, + 0x39239561,0x80ea23ec,0xd4370644,0x1b8907e7,0x563e4e44,0x4b7fa455, + 0xb2a4b0fa,0xcca9829e,0x48060792,0xd0a720a4,0x246991ce,0x8ccdda0c, + 0x348d086b,0x37a2325b,0xf60aee13,0x566ed509,0x147f253f,0x3d30e091, + 0xc1073bd8,0x1fa627a5 } }, + /* 243 */ + { { 0x42478fd4,0xa11222a2,0x670b2000,0xacf4c6f1,0x8359c6de,0xf71bb04f, + 0x7b93cdbc,0x618e2829,0x230db60b,0x96e1bae3,0x965b3b29,0xf17fd3b4, + 0xbc7055dd,0xa58639c6,0x4b817d7f,0xc3ea92ed,0xd23b08a4,0x9082b2a6, + 0xdc17010e,0x8471228a,0x20e89d97,0x753b9e46,0x03ff77c9,0xcf7e4f97, + 0x2bbe60e5,0x6c3f8245,0xb80e017d,0x9e432cbc,0xc0a45edb,0x150a5acd, + 0x4798743e,0x67b8bd05 }, + { 0xf4797cf7,0xe66079b4,0xd03fde02,0xe31c998a,0x54caaef1,0x5aa3763a, + 0xf7649711,0x64d9a1fe,0xaf29b1a7,0x7ce0dc73,0xfb66ca93,0x6661b083, + 0x32fb6a78,0xbf4d74fe,0xdf00a561,0x25f6ef09,0x831d1159,0x2bc4383f, + 0x536bde37,0x6d5cc10c,0x882cc65b,0xd4945f9f,0x451a99b8,0x81f48f13, + 0x6bac11a4,0x140161cd,0xf18a4a0a,0x9d94d4ed,0xa467a824,0x65363165, + 0xa4c9aedf,0x74297aa9 } }, + /* 244 */ + { { 0xe21124ba,0xc49758a4,0xa87ffbd2,0x99bd8198,0x3d6638a8,0x45fbcdd1, + 0x15f7bf76,0x94645ff8,0xc4e6d57e,0x5fa6736f,0x92e61db9,0x1eae6475, + 0xcbdf944a,0x79575c0c,0x25b31d74,0xa3d13047,0x4cab5ae6,0x7881df22, + 0x1a2887f2,0x8dbfd299,0xa26ac459,0x23d07590,0xd8661d4a,0x2e589852, + 0x8a0140f7,0x37b5c13b,0x3fb3782a,0x0f94199e,0x1bc14e90,0x722aa059, + 0xd55bbb12,0x89aab7ba }, + { 0xd656bdc7,0x8b345a96,0xe176cd3b,0x43bdc8af,0x32d64c43,0xd69518b6, + 0x79b82b41,0xfcf364a7,0xffb0cf82,0x907b344e,0x5101287b,0xf3d0c83c, + 0x34cd90ef,0xe9f26a59,0x07082b5c,0xe5f5aaf2,0xece7c165,0x4eb72c75, + 0xbe986cd6,0xe9590a81,0xff1536aa,0xfeef498f,0xa8263d5e,0x04560243, + 0x54ae872b,0x940be14f,0xe3207686,0xbee7bcc9,0xc1bc4d7a,0xd496a27d, + 0x5940ab46,0x002dc297 } }, + /* 245 */ + { { 0xb69d60c3,0xee533937,0xfe972755,0x260be552,0xc0c725a6,0xb11fb78d, + 0xcab2e7c2,0x6982c27e,0xee2322cb,0x4bceedd9,0x122704f7,0x952b19ed, + 0x854a6165,0x2df4c285,0x7b192485,0xba40b5bf,0x0119f52a,0xfcbca950, + 0xe5add86f,0x7467d1cb,0xd9d0f2c1,0x9bf536fb,0xb8d4ebc9,0x3c296e34, + 0x05a81317,0x0495f8f4,0x73335f76,0x8c59e8d6,0xe0542122,0x0b53d324, + 0x3c3bda73,0x4d564535 }, + { 0x7e5c0877,0x7322f800,0x0ca9a764,0x481b43e6,0xa2c12716,0x231f4f4b, + 0xed3136c2,0x09596857,0x38db30de,0xae826322,0x99908ebc,0x652fad40, + 0xaf0d231e,0x0b8d1814,0x09cbc349,0x2680c54b,0x4bf3bf8e,0xfd4562f3, + 0x092b595f,0x2985090b,0x5e15fc34,0xe6f39ca4,0xbc378168,0x70175191, + 0x845a4a87,0x906944b3,0x82a1541a,0xacc6d74a,0xb155c8b4,0xadc9bab3, + 0x77306c62,0x1f2f89ce } }, + /* 246 */ + { { 0x9affefdf,0x8253ef41,0x4cf9256b,0x05d7ece5,0xb444e483,0x377002f2, + 0xcba5471f,0xb189755f,0xd5cbe015,0xc88483cb,0x6a0b8429,0x254f7c69, + 0x61f3f61d,0x18850bd4,0x0a247157,0x7ba21089,0xd92eeb0d,0x35abbc2e, + 0x965dec89,0xfb56cabe,0xbc55684a,0x9da23724,0x6a7a7492,0xd8ba396f, + 0x2ef4ba46,0xfcb90db7,0x9909b27a,0xdd234fe0,0x76f4366e,0xbdf3c164, + 0x17e50d47,0x09c8097f }, + { 0x60050c07,0x6a04b140,0x43a8e37e,0xc29e8318,0xbb55e41f,0xcb9429b2, + 0x2ce60e3a,0xed2fea5a,0xdb9d82f4,0xdc7b1ff3,0x687d37fa,0x48ebecc3, + 0xecb07539,0x79153e32,0x57075692,0x6a60054f,0x800759ba,0x3871cd0c, + 0x30922df1,0x17a7386f,0x83357b7c,0x4e9fc59e,0x39415186,0x1d26b3a9, + 0xd34db889,0x912a0222,0x59fcdb71,0x6672fcf4,0x44ff3036,0x5a3f268d, + 0x6911e16c,0x6f113ed3 } }, + /* 247 */ + { { 0x1836f1c9,0x52a9df59,0x4232307d,0xfa6519f5,0x5ded285a,0x8406c701, + 0xaf627f75,0x0a1545ca,0xace0417d,0xae1111ee,0xa6113443,0xfb28bdf6, + 0x52dbcbcb,0xde9ef0ab,0x7813e658,0xe9dc181b,0x99127225,0x0b1dabdb, + 0x22814c59,0x5f0598e3,0xd934ee7e,0x5c3b966e,0xb99ba4bf,0x4eb84eda, + 0x3c1b55e7,0xb2919a34,0x94aa860f,0xa9addb49,0xf6811ff6,0x1b7220df, + 0xd1a183e2,0x6636a23b }, + { 0x20587283,0xdf5d5a2d,0xef07fc5d,0x0b3822c9,0x0ef6de38,0x1786bd55, + 0x25d1671d,0x163cf907,0x1cdb1def,0x74bf971f,0x0842fc4a,0x5749e830, + 0x27f854f7,0x0e2edbc7,0xbce24acb,0xbb27bbda,0x05bed08d,0xc1b19cec, + 0xf7c904bc,0xaada123e,0xd89982db,0x02429f1b,0x65f6e632,0x49d3616e, + 0xee59fd32,0xa3789fa8,0xfe9f29f5,0x160ba3ba,0xaf5378a0,0x0f2d3b61, + 0x73c2a6f8,0x7aeecc76 } }, + /* 248 */ + { { 0xdc43b0db,0xf3a4757c,0x98119cad,0x3d8a4e85,0x4616c156,0xf8095bf6, + 0x4f533e97,0x3e2a07bc,0x39cfc5ad,0xa9824367,0xcd68052c,0x18a6ba3a, + 0x8a1cec66,0xbd60e590,0x02b1b695,0xae3841a5,0x190a195b,0x986dff12, + 0xad31fd9b,0x2df2beac,0xcc728f7b,0x7d893224,0x0cf0a992,0xc38ea738, + 0x586a44ea,0xa8439a80,0x1615f03c,0xede7f7f0,0x27a1f885,0x48249908, + 0xb78a7645,0x28ec4006 }, + { 0xa2fe0009,0xe1820c2e,0xf13874e9,0xe11ba5d2,0xc524db52,0x97522454, + 0x7fede529,0x4d477426,0x9b2500d4,0x01d3419a,0x1869244b,0xce08a492, + 0xdd1be1b9,0xba169023,0x32a301e0,0x242c3e54,0x70906788,0x9b56f7ba, + 0xc74a8cc4,0xf0ad2a09,0xd76f9439,0x99cd1841,0x621fb60e,0xeddafe0b, + 0xbc397634,0x056bee54,0xff7f0a84,0x4653f860,0x2011c0af,0x6bd4876f, + 0x0c9525c3,0x134f4cc7 } }, + /* 249 */ + { { 0xe938dff4,0x9621a3ec,0x486a79a3,0x7d101a7b,0xde950537,0xf2c4ef97, + 0xe65d87db,0xf3184099,0x373b8cfa,0xb89c7ffb,0xe842916e,0x68baa505, + 0x4ebea764,0xa790fd09,0xe592892b,0x679df6d4,0xfcfed741,0x2023331c, + 0x9880ff21,0x0bf4efd2,0xd0344501,0x7ca78ddd,0x342858c8,0x2cb09ecb, + 0x2575487a,0x9e5eb6dc,0xebcb0491,0x50675a15,0x7381d471,0x09d2e74f, + 0x83d3d6f4,0x6ea37829 }, + { 0x4e5cc40a,0xc65c094b,0x1af37dfb,0x7a2e3f6a,0xf9026e44,0xef677e9d, + 0x93880f53,0xb7878c95,0x7f644aa9,0x4aa30b07,0x2f208c3c,0xa0c51683, + 0x658d663b,0x7c0277ae,0xae1d9130,0xef0b3c38,0x695c3ea4,0x302f37a7, + 0x6a0c5e0d,0xe004c1c5,0x20cbcf9f,0x9fd495c4,0x568a0e7c,0x706d5b9d, + 0x59286454,0x8b225dff,0x8d9a709c,0x527d4465,0x87c08d68,0x47c558da, + 0xbb4ef07d,0x606ee6e6 } }, + /* 250 */ + { { 0x57c621f6,0x02d99fc7,0x7fe83d48,0x292e40c1,0x9ef199b0,0x1bdfc7a1, + 0xe62c7666,0x78a04102,0xe6738753,0x16cda370,0x1e3a65af,0xbc81974d, + 0xf78fe209,0x19742048,0xbf5981c6,0xc83a058a,0x9c89702d,0xf26b2434, + 0x9d1a678a,0x988b2f1e,0xff29ae29,0x472bf9b0,0x1d7cf5ec,0xa143e398, + 0xb268ddd8,0x9c9d7e45,0x5fc4ff76,0x166cda55,0xa4aa7673,0x6044cdf0, + 0xe9148707,0x49dba6f7 }, + { 0xa758e37a,0x20e47fb2,0x2d8eaf66,0xaf6b31d7,0x6f9c2210,0x352ad5f9, + 0x90efc32b,0x0093f727,0x41e4b264,0x435c99dc,0x05b15795,0xbfa878e0, + 0x0e673575,0x99c520a4,0x87eea759,0xca682594,0xf12a348b,0x029f7b81, + 0x2aa2ce35,0xa547cc18,0xead5e2c5,0xa11d874b,0x55682cdf,0x9af0349b, + 0x8bbe8e66,0xf86ebfea,0xf55394ab,0x3dab8782,0xebc8eb8f,0x458bf797, + 0x9b7de78c,0x4890a7a4 } }, + /* 251 */ + { { 0x8da995f6,0xd7299689,0xec6156ef,0xd39eaae7,0x356a82d5,0x6959040c, + 0xc135bcfe,0xb2046b21,0x0f595c78,0xea720b64,0xe7c5fb40,0x02824efa, + 0x0edb3bfc,0x97d8fd4c,0x79f24ebe,0x12f02905,0x187ea6b9,0x16fc47cf, + 0x789d5c23,0xc219fd27,0x89263ecc,0x233a6b6c,0x8b6d30a6,0x823634b2, + 0xc9b33680,0xca352e25,0x40c77456,0x9388d6ca,0x3c92065b,0xf8e55b0b, + 0x02439a76,0x5c17474b }, + { 0x8aaccab5,0xd888e7c2,0xaaced05b,0x18027836,0xccec0f65,0x185b877d, + 0x125c2882,0x93cadc1c,0x67fdc54c,0x45df540a,0xc2788a33,0x4f3c86e2, + 0xe3a0fa2c,0x3e874469,0x273983cf,0xc59daa47,0x4a96d8a5,0x3063c48b, + 0xc2e58915,0xc38d2bcf,0x84e428c3,0x90e78b87,0xf0c4fd53,0x900a292c, + 0x941e6005,0xb7f92db7,0x6ca53a1c,0x95679241,0xb1ab0fa7,0x35f6f31d, + 0x7b58408c,0x5d675eb4 } }, + /* 252 */ + { { 0x870c6025,0xaeee1a77,0x91a2dfca,0xfc4a23b7,0x386b64c4,0x7b0e60c4, + 0xe5ae72b1,0xd5d5b17d,0x9eefa212,0x6dfc88ac,0xd4038b96,0x4feaefbe, + 0x8e2d2ecc,0x099ac356,0x012af207,0x548ea612,0x89c31218,0x4ffed9db, + 0xe0e67331,0x1c1e91c4,0xaf8300e0,0x009bb64f,0x6773c3be,0x8780501c, + 0xc08219fa,0xe0cd6ede,0xf81b06ff,0x7c055e07,0xe080b36f,0x82b63f9c, + 0x0a9feca3,0x02fccbaf }, + { 0xb47cac61,0x9991d4d1,0xab86e12c,0x2e9d1687,0x2b94f042,0x8c6855ec, + 0x48e648e5,0xca400519,0xef89ac57,0x9ba91fb2,0x1be792cd,0x4f419206, + 0xbd0f1e15,0x82d221cb,0xfc444019,0x062eb13b,0x99790fdc,0xf3a97c32, + 0x6067a64b,0x4e796d94,0x6d23775a,0xc46dd300,0xed7f0f23,0x8672c4d5, + 0x3b4f63d7,0x821851dc,0xd26273f2,0x50a3ae0c,0xeac60f6f,0x800e58fc, + 0x13845545,0x56f1e456 } }, + /* 253 */ + { { 0x32c24f3b,0x01ccb3f6,0x06d817e6,0x99eb1c7f,0x6aa26776,0x8dc640bb, + 0x0845d5e0,0x7838affe,0xf81a79a8,0xf34fecb1,0x3e6819b0,0x6a2e282d, + 0x8237a4b8,0xc4b977ce,0x87636439,0x0f46b3db,0x97970497,0xa465f540, + 0x8791be43,0xd7e08762,0x34198ec6,0x00220b6c,0x093d94bb,0x57b38637, + 0x29d690b2,0x84012e16,0x20aad1a4,0x02ec9db5,0x85dc34e3,0xafee2fc6, + 0x25500cf8,0x911d1936 }, + { 0xf5e5af5b,0x13b1bd58,0x7b6a22a7,0xa7ca263b,0xf3af2adc,0xab6bec4d, + 0xa04420bd,0x16651e59,0x4ba36c11,0x3b448b3b,0xff424310,0x3c62bfcd, + 0xf1a96cbb,0xde15c4a5,0xe4d1f980,0xbe0ad8a1,0x36673a3a,0x812bd14e, + 0x9212acdd,0x40303af6,0x576095ce,0x8f6dab9c,0x107f5ca5,0x7df1882a, + 0x8896a3b0,0xb903e63c,0xd863b3f0,0xf5048544,0xc09887de,0x5e5019b9, + 0xa0f53865,0x2be744fe } }, + /* 254 */ + { { 0x5b50f324,0x054cd05f,0x1ea3c7a2,0xb9b1eb24,0x7ff8e6b7,0x4a858a5c, + 0xec040882,0xd83902fe,0xd0cba9bd,0x72b26494,0xb29c9e1e,0xd0176f90, + 0xcebadb81,0x05d4eb02,0x372b8bfc,0x874405b1,0x79ead190,0x5c412881, + 0xec2b48cd,0xd44a3dd3,0x3f4d5033,0x84499a77,0x564c3a09,0xb37b38cd, + 0xf42e803b,0x80e99497,0xb8f518b2,0xc07b47a0,0x3568fde4,0xc710e3c5, + 0xcead0e7a,0x735f542f }, + { 0x38380039,0xcaa9a171,0xf74d19c8,0xadfafe17,0xccbc1a8b,0x92d4393e, + 0xfe029705,0x3c5dbf39,0x930e9b36,0x4552b5ab,0x2afd494a,0x7ee63032, + 0x3f02ac43,0x826a9ad7,0x99356298,0x98c53562,0x7342bb39,0x0c869f87, + 0xe4f9b79a,0xd7510020,0xd34789a9,0x6361d1a4,0xcfa85637,0xf0ded5ba, + 0x88ac07e4,0x407ee73f,0x09ef1cbd,0xfac7d03f,0x4d475bad,0x25d697cb, + 0x14bd399e,0x1e984c9d } }, + /* 255 */ + { { 0x4850c817,0xc76d0561,0x3489812d,0xb08a5b19,0x5e58cbbe,0x7273d154, + 0x4be61e5a,0x8900b5fa,0xd7aeb8e1,0xaa088691,0xd35a3d4b,0xe66666af, + 0x57ec7d3d,0x38a2c199,0x668d6f5c,0xa0648e8f,0x7adc1746,0x1f9fc92c, + 0x843065c3,0x23a116c0,0x61e6ae69,0x36370a20,0x2aa47e73,0x626c3736, + 0xdeff6d84,0x540c25f2,0xcdbed2d4,0x9804824c,0x039a9492,0x4b5bfce0, + 0x76942e01,0x6c474a56 }, + { 0x7d88e3a1,0x3aeb9a41,0xc484742a,0x105d3c88,0x3fe61131,0xe59de8d1, + 0x1a869e8b,0x148f5b6b,0xaa75d90a,0x7a8abc59,0x62146013,0x2f0c9bc7, + 0xc3824cd9,0x43faa747,0x6a5d0b92,0x81763a18,0x9bcbaebc,0xbbc341bc, + 0xf745d1dd,0xe1813160,0xb75ce5f4,0xa53ce52d,0xd50de4c2,0x15eae66c, + 0x75d7656d,0x5ed8996c,0xc4ca552a,0xe4ff5711,0x3c5305b4,0x215e985a, + 0xfa1ba2ce,0x6b258954 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#endif + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + + err = sp_1024_ecc_mulmod_base_32(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[32 + 32 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (32 + 32 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 32; + + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_ecc_mulmod_base_32(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_1024_proj_point_add_32(point, point, addP, tmp); + + if (map) { + sp_1024_map_32(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 32]; +#endif + int err = MP_OKAY; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 32, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_32(point, gm); + err = sp_1024_gen_stripe_table_32(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(point, gm); + +#ifndef WOLFSSL_SP_SMALL + err = sp_1024_ecc_mulmod_stripe_32(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_32(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_32(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_32(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_32(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_32(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_32(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_32(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_32(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_32(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_32(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_32(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_32(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 32]; + sp_digit tx[2 * 32]; + sp_digit ty[2 * 32]; + sp_digit b[2 * 32]; + sp_digit e[2 * 32]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 32 * 2; + ty = td + 5 * 32 * 2; + b = td + 6 * 32 * 2; + e = td + 7 * 32 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 32, base); + sp_1024_from_mp(e, 32, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32); + sp_1024_mul_32(b, b, p1024_norm_mod); + err = sp_1024_mod_32(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 32); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_32(tx, ty, t); + if ((e[i / 32] >> (i % 32)) & 1) { + sp_1024_proj_mul_qx1_32(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_32(tx, tx, t); + + XMEMSET(tx + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_32(r, tx, ty); + err = sp_1024_mod_32(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][32] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 }, + { 0x335c1685, 0x170a46d2, 0xe1007a58, 0xeac9e971, 0x43ca4a73, + 0x40e8f3df, 0x82642475, 0x2646f815, 0xb36576d1, 0x3af49bb4, + 0x72bf1afb, 0xd89e2d14, 0x2fd151e6, 0x27be882c, 0x8f88717c, + 0xaddedc85, 0x16ac6c6f, 0xd6d859bf, 0x2d8eae58, 0x0e741a1b, + 0x61c1f30d, 0x6faf7a00, 0x9b67e096, 0x66dbd09a, 0x7d3b4f7d, + 0x21f11c06, 0xc727c98e, 0x6152ba02, 0xe86cb221, 0xafd58891, + 0x6bd3baf4, 0x59e93c6a }, + { 0x71dd4594, 0xe54dd36f, 0x00aef1e6, 0xbbc9cc9f, 0xa19f6530, + 0x9ea5a44e, 0x3f520928, 0x8588aa99, 0x8f5c1418, 0x9753794c, + 0xc11399fa, 0x118bd792, 0xf5cb6ab5, 0xb9bd3afd, 0x2ecb9652, + 0x813d1cb2, 0x40389813, 0xfd456267, 0x4ac8431c, 0x51f7119b, + 0x0a180eb6, 0xdd9f6a91, 0x9f7bfa2e, 0x13946d17, 0x50a9d0d9, + 0x16f18631, 0x6f8373d3, 0x5f19c20d, 0x9b6a52b9, 0xbe85ac6a, + 0x74f62e03, 0x63ef187b }, + { 0x016f45e7, 0x7c376b7f, 0x2bec82f8, 0x1c1bdb57, 0xce429b60, + 0x7392f741, 0xc7afd81d, 0x6fdbf0a2, 0x7241098b, 0xbda41b1f, + 0xbb60f8cf, 0x5b407474, 0xb330bc4d, 0x933e0d41, 0x733fa3be, + 0xae182830, 0x0f5c6cd1, 0xa0ed299b, 0x3f9860c8, 0x7ff3354e, + 0x15559c41, 0xb1360986, 0x129f85cb, 0xab0cb63c, 0x47685fbe, + 0x682ecc49, 0xeb199633, 0x505e8ec2, 0xddac2cda, 0x90dcc794, + 0xf192da23, 0x4fe6791c }, + { 0x05e8733c, 0x94a423d5, 0x1d5717c1, 0xcc845e65, 0xe961b322, + 0x237c7e88, 0xdb4181cc, 0x0c4471c6, 0x713bd721, 0x00c875e2, + 0xb2c17b09, 0x9dfde9ed, 0xe88ceaf6, 0x430a6de5, 0x7b81cea6, + 0xaaa7a61a, 0x233f98d5, 0xea52d026, 0x60689a9a, 0xb55efdd0, + 0x5cac4aab, 0x30cfa7ce, 0x8e950761, 0xfa4db114, 0x4e9a1e52, + 0x309570c4, 0x1a040170, 0x18c21f61, 0xbe78d9d2, 0x555d1ffe, + 0x561db297, 0x04482a18 }, + { 0x73d486d8, 0xe7758ac2, 0x61cdc1e7, 0x8169f946, 0x2188ab4f, + 0x723c99fc, 0xf3373630, 0xa0e54f02, 0xbd8c2260, 0x560bee25, + 0x4531bc60, 0x28fc307c, 0x7e44feb5, 0xd6f21f1a, 0x57128d37, + 0xc8e4499c, 0xd7b2ea45, 0x963b053e, 0x32a3d222, 0x40c27a04, + 0x35459668, 0x5b51854d, 0xd73557e9, 0x66e1a49f, 0x8692077a, + 0x0d267fd9, 0xe7342702, 0xfa1350d3, 0x68ccdb44, 0x1a9c3f25, + 0xdedbf89f, 0x833a0ff8 }, + { 0xab376b76, 0xa8c419c7, 0x27d0f0cc, 0x3b7294f3, 0xa90c514d, + 0xe56bb9e2, 0xa62575a6, 0x931ba51e, 0x098c0a88, 0x56fee07b, + 0xb4c16a2a, 0x04be5aee, 0xe6eb260b, 0xe513350b, 0xa1d5c270, + 0x339edad6, 0xe9dbadd1, 0xf366ed59, 0x2dd06ec0, 0x4213be88, + 0xcb1187db, 0x22d639c8, 0xd8a1058a, 0x1fec95e1, 0xa2b744f1, + 0x03f73ea6, 0xf4f05c0c, 0x741fd51a, 0x85f811a0, 0x2e2df95a, + 0xeb24965f, 0x692b3ce3 }, + { 0xd2a127b4, 0x0ce6cb72, 0x8f92816f, 0x66a46ea5, 0x47a37616, + 0x43ecf463, 0xe0ab96ee, 0x163d9a01, 0xb2edbe8c, 0xc8145c6d, + 0x4de4e665, 0x2f426cae, 0x74e252f9, 0x174d0b40, 0x7d2af831, + 0x54c240d7, 0x3d652936, 0x581fa397, 0xa09d4695, 0x05b9491c, + 0x5452643c, 0x8c4e8533, 0xd4128327, 0x32d64331, 0x70361f25, + 0x64479038, 0x89ef09f2, 0x774191b1, 0x81de5fe0, 0xc0cf0aaf, + 0xf40042d6, 0x333e430a }, + { 0xcf26d3b7, 0x5df04de4, 0xb53f79be, 0x57a77306, 0x1808b664, + 0xa4013c5f, 0x85037360, 0xef291ea4, 0x0b061037, 0x1ffc9d7d, + 0x65c913bb, 0xd9d04dd9, 0xf13b8587, 0x948a37af, 0xfe3ee755, + 0xb5443483, 0x04631386, 0x3fc21e74, 0xcddeb58c, 0xb3a104e5, + 0x6572cd52, 0x94fe1862, 0x15aaa408, 0xeb9a71a1, 0x459ea462, + 0x8adc6fe5, 0x4aeb02a3, 0xbb18d175, 0x2f7791d1, 0xae127636, + 0xd6bbd708, 0x10e8b31d }, + { 0x3ed9f1af, 0xb87f03e5, 0x56676166, 0x03ad2477, 0x74ce15b8, + 0x38dcd630, 0x26b1e85b, 0x1877e2b0, 0x1af99c15, 0xb1654d17, + 0x9382547a, 0x9782e9e4, 0x26d55ef5, 0x6dc7fc7c, 0x2fbeb54c, + 0x9038f95d, 0x036c0357, 0xfe590dfe, 0x4fdc3f7f, 0xcfcb6eae, + 0xf35e1a88, 0xcb1fbc54, 0xda0a5568, 0x3c8e1db2, 0x5b6f5557, + 0x9a87393f, 0xe7ac0a06, 0x38646b32, 0x2a8495ab, 0xfd261c83, + 0x0cdcc4bc, 0x6485524c }, + { 0xc4a6ff2a, 0x1abfb3e2, 0x35a6428a, 0x2aa03fba, 0x89aff742, + 0x884227f0, 0xba5dbd93, 0x2337883a, 0xd2a182cb, 0x38186ae9, + 0x49a01f05, 0xb9f0764d, 0x917b1e7a, 0x92411feb, 0x570cbb5b, + 0x700b1903, 0xb914be7c, 0x5d5181d5, 0x1981182d, 0x135c4437, + 0x574b9997, 0x32758d24, 0x632d28b2, 0xa650a8f5, 0xfa383f09, + 0x24078bac, 0x00a33d80, 0x6546a60c, 0x2df8b449, 0xa4061c7a, + 0xf234563c, 0x1f76f3f2 }, + { 0x44c436b0, 0x9aa2c143, 0x1f69c87a, 0x79070556, 0x5f6db2df, + 0x35f3117b, 0xed56ba82, 0x85761f41, 0x7d0afa48, 0xf831464f, + 0x3adce71e, 0xa99f2915, 0x116b7488, 0xb27bf693, 0x9bb9443a, + 0xa98a5a8c, 0x2ee5fde8, 0x7f878026, 0x1812acb7, 0x3a6f93dd, + 0xdc84bc92, 0xaf92a4cc, 0xf1d4995a, 0x3c2562af, 0x04ed899d, + 0xfd9fc33c, 0x4ed2a538, 0xc028ca94, 0x049ea726, 0xd0f367bb, + 0x3d108e05, 0x04924ffb }, + { 0xc673562f, 0x06548e3d, 0xe2eae48c, 0xd3b33025, 0x5e1c6977, + 0xe61fd32b, 0x6ebe557b, 0x424e2064, 0x41d6e18e, 0x767391c0, + 0x14d7e95b, 0x4b8ebb8e, 0x20991b8c, 0x4ae8b7d4, 0xe01290d3, + 0xf8a0df66, 0x925e5f4e, 0xc97e24a3, 0x1508272a, 0x79a7b2cb, + 0x25072661, 0xb40b072e, 0x9062fa49, 0xdad9e182, 0xf3c53bce, + 0x8780a784, 0x9f142799, 0x58a82b76, 0xc1468426, 0x08cd849c, + 0xc380ae35, 0x4dfce809 }, + { 0xd527b780, 0x45069cb2, 0x977930dd, 0xd52da015, 0xe27d0263, + 0x10cc600b, 0xbb2d1b2b, 0x34102c26, 0x554adf3c, 0x4c652623, + 0x45f0ff47, 0xd6891382, 0xca916e7c, 0x83fa8cc5, 0xd15c8d8a, + 0x1e10f139, 0x81dc56b3, 0xf173dc2e, 0x5c4ed9ba, 0x7fcecb04, + 0x47d01228, 0x307fd7d8, 0x9f3a532f, 0x24a57153, 0xe2153c22, + 0x59e9e81d, 0xe428a408, 0xc562595d, 0x9339bd23, 0xdc7daff8, + 0xb8a06802, 0x0d075908 }, + { 0xde085f2a, 0x870af2a7, 0xbe99b2e5, 0x88fcd24f, 0x59ca413b, + 0x88c0d261, 0x8559f851, 0x1f02a2e4, 0xf622da0d, 0x83b96021, + 0x6dca3615, 0x5c05c2f5, 0x7910c682, 0x0148cf1c, 0x272695be, + 0x392f2896, 0xa8d64ef6, 0x883d0bb5, 0x1cfcbc52, 0xef0d2244, + 0x526117e5, 0xf5dafcec, 0xf04928e9, 0xb68612b9, 0x393f2e2a, + 0x283f744d, 0x700c1151, 0xfbeed7ed, 0xa4360dfe, 0xf2cde215, + 0x2f08535a, 0x24fa961c }, + { 0x616df7f6, 0x0767db3f, 0xfbd90326, 0x643057d8, 0x6e82d544, + 0x174daa90, 0x689643db, 0x2284f345, 0xcc89a060, 0x18b191df, + 0xd6c27d12, 0xbab46af4, 0xc9895145, 0x5a57f486, 0xcc942f9e, + 0xc03214e9, 0x41950158, 0x273e1c8f, 0x39ad43ab, 0x8ceb759f, + 0xe50ee173, 0x5e1b8b7f, 0x8f4d7d4e, 0xf635b1fc, 0x755603f3, + 0x8eff77e3, 0x7752fa60, 0x201f61d1, 0x4a6fb6e1, 0x94d7a03d, + 0xfc4f0114, 0x371cc23d }, + { 0xda90c351, 0x289b115d, 0x364d9c06, 0x6d196ebf, 0xf650b31b, + 0x77a89202, 0x6f57642f, 0xcc28c164, 0x08100127, 0xdc4f7e36, + 0xdc4c807b, 0x8836cd08, 0xe00240f2, 0x1280f156, 0x99cb3953, + 0x3f9a6d78, 0x3a802038, 0x40a494d3, 0xe87d3474, 0x45697e91, + 0x26dde24a, 0x70d97d07, 0x7640c30e, 0x06f6a58d, 0x5ba6e6c6, + 0x03c2c0e8, 0xf1bc13e8, 0x330f6a7a, 0xc9f4d78f, 0x3e602e4f, + 0x0c80fb7f, 0x92b6bca0 }, + { 0x5f00822e, 0x2e3d5c83, 0xb8b16f12, 0x0e825712, 0x92b0a330, + 0x81c329c4, 0xa7cc1954, 0x6b4e32ad, 0x1bb1413f, 0x0bee9cee, + 0x4a92ca27, 0xedfb7baa, 0xea3b9153, 0xcd472afa, 0x00f0c0f9, + 0xe8f09e7e, 0x5cdebb70, 0xa4e1d872, 0x4a9b63b6, 0xfe2bae08, + 0x3fd58f65, 0xf40141b8, 0xa3b62759, 0xd7ec5eda, 0x790e3088, + 0x9aaf6e67, 0x1f277e31, 0x215ad830, 0xcf33871c, 0xe7db4b98, + 0x4f02f89d, 0x71ff62c9 }, + { 0x2a4a84d9, 0xaa4c7102, 0x5ebc71e6, 0xe2ee4acd, 0xf1cd6578, + 0x3b11a8a5, 0xfff120a5, 0x83f5ef9f, 0x09e65033, 0xa4c598e1, + 0xca044180, 0xe1e9f990, 0xf59828c1, 0x8b832d46, 0x33af536b, + 0x753f28a0, 0xb6d4f68a, 0x92edc4b1, 0x72ccd1f0, 0xedde692a, + 0xd2226432, 0xd3aa0f7d, 0xa3d2661c, 0x38dbb63e, 0xfdc37dda, + 0xf1e19fc6, 0x84ef6b4c, 0x6c18b350, 0xdf1bba69, 0xe6a83fe9, + 0x5f958273, 0x40fd47e7 }, + { 0x267140a4, 0x5b88b746, 0xeab6f2fb, 0x6dbbfc1e, 0x69862548, + 0xdd9ec88e, 0x2eb6efc2, 0x69beeba1, 0x8ac8ff88, 0xcfc2214a, + 0xb5a21950, 0x95d5c96e, 0x4171fb69, 0x93389c05, 0x1b468337, + 0x2d85d452, 0x4113425c, 0x14d68a08, 0xec6c2174, 0xe52c0139, + 0xf730084d, 0x20cf0b97, 0x1f578aa3, 0x1ac16a26, 0xf9b6ae43, + 0x18b9fab3, 0xd854a695, 0x68d82111, 0xdffbe286, 0x0b334d98, + 0xe639338c, 0x5b1c1157 }, + { 0x72b6bb8f, 0x90edaab1, 0x02fc92c2, 0x8dc64ed2, 0xfe694c73, + 0xf42ba3c5, 0xcb54dce4, 0x316dc65f, 0x632420dc, 0xcb2d66a3, + 0x056dcf94, 0x16e706e7, 0xa4f32c9d, 0x2809c764, 0xea6edca8, + 0xab18d830, 0x81c65f57, 0x4fd1ace6, 0x7da12c10, 0x1f91651c, + 0xc7791a48, 0x0ac3bd66, 0x785e67a3, 0xb6ad1cf4, 0xda0fd591, + 0xe4d3fc44, 0x6e1c6344, 0xce164801, 0x33e50ab3, 0x84de9cb8, + 0xa756eef4, 0x963ab83a }, + { 0xdf4ea5a3, 0x944b47d8, 0x5cfe45fe, 0x96568815, 0x8a3c3564, + 0xd16e7d58, 0xe7c99e15, 0x84e55b3e, 0xf55071bc, 0x3fee204d, + 0x04057dce, 0x71006f29, 0xbba75570, 0xfe8c390d, 0x3319adac, + 0x3645bcb6, 0x7c20bfd8, 0x8189e8b0, 0x7d7d9578, 0x8e550969, + 0xb99f4e3b, 0x037d1321, 0xa60cfb6a, 0x011b2521, 0x837382da, + 0x66594aaa, 0x83c1dc07, 0xc89b91fd, 0x076b9884, 0x6b82b899, + 0xbe45c558, 0x443480fc }, + { 0x9114221a, 0xf8ffffb4, 0x3e857a7a, 0x4aec4f2e, 0x0fa54787, + 0x42e2d0e4, 0xd6f96152, 0xef3e6b31, 0xfbfe9b77, 0xb2296537, + 0xfb43a86a, 0xc2a9d0f2, 0x24572ac6, 0x241284ed, 0xe721ba7b, + 0xa3868917, 0xc117a78d, 0xdbef7c00, 0xd31605ac, 0x38149071, + 0x065a8ee9, 0xc2dada9e, 0xc442be82, 0xd5b138d8, 0xf6d72b58, + 0x9b6c224b, 0x8eb03e6d, 0xb9d355cf, 0xa1700371, 0xab6d1eb0, + 0xcffaa7eb, 0x97118a88 }, + { 0xcdecb5d8, 0xbf9c59a2, 0xa93a6866, 0x8083c81b, 0x04774fbf, + 0x24e0dd81, 0xa02070b4, 0xe779a3ca, 0x0fbfb781, 0x9d352fbb, + 0x3ef2a1c4, 0xa8b0d820, 0x14b3e501, 0xb858637b, 0x8a882ff2, + 0x5ba70a49, 0x3b06efa5, 0xa2730083, 0x102fee2a, 0xa42c02f4, + 0x8a0223a5, 0xe4e76299, 0x85c3fc72, 0xdba2ba26, 0xfe52eae7, + 0x554fe763, 0x270f45f6, 0x30b5405a, 0xa573387c, 0xd56a177a, + 0x4b71fa82, 0x17c0778d }, + { 0x2735e37b, 0x0e6dff1d, 0x656ec572, 0xc9884e56, 0x9ebba978, + 0xa2f5ac9d, 0xba09f3c4, 0x40fa4518, 0xf5b04377, 0x8c3fa177, + 0x967a2eca, 0xa1a1decd, 0x0528bd40, 0x768bca70, 0x18691c4a, + 0xf224952b, 0xe86d5fd5, 0x16e12c45, 0x37859a6a, 0x7a0d9157, + 0xa0ffce0e, 0x723f4309, 0xa96cc9a3, 0x5a8db79b, 0x1ad23a38, + 0x6dd12ae0, 0xe2bf5d84, 0x9ffec3a1, 0xa452ed66, 0xd6ce84e1, + 0x571fe4c6, 0x1219d5c8 }, + { 0x262969eb, 0x43eaa67f, 0x2f03e773, 0x3a3ab39d, 0x57bb0909, + 0xe6127e51, 0x8d150274, 0x0f82b0ed, 0xe580bdbd, 0xffffcad8, + 0xa9743e6b, 0x51d3d075, 0x8bac11d6, 0x1484bdb1, 0xeb24c388, + 0x95cd9990, 0x7fac67c6, 0x216a61d0, 0xa04e6b87, 0x4308f762, + 0xcba57cc8, 0x2865dd61, 0xd234a07a, 0x3c296b0d, 0x3a0793f9, + 0x76f92839, 0x0be29ece, 0x70b57e1f, 0x7e626f42, 0x1314a82f, + 0xd657f230, 0x2c8d7ab2 }, + { 0x0825e4d6, 0x67cf5892, 0x6ef83b44, 0xdf51eaa5, 0x1310108d, + 0x63e665d8, 0x8dd0963f, 0x229f89f5, 0x9df6436a, 0x8c4b14dd, + 0xd45ebba7, 0x99dae469, 0x5a4df381, 0x118aab77, 0x29e37feb, + 0xda8978bd, 0xaca2d7ef, 0x69ced5aa, 0xc67d6a8a, 0x6c98d05d, + 0x77f84a34, 0x7474bf0d, 0xed8cd59a, 0xd4428b2e, 0xd1d398fb, + 0xb0fd1cd5, 0x94a20b11, 0x596013db, 0x1b404c44, 0x96eb705a, + 0x4b09d958, 0x2299d277 }, + { 0xc64397e6, 0x5b9cd58d, 0xbf6dd31e, 0xac198f1e, 0x3e9f1db2, + 0x5866d8e1, 0x8fcdc68c, 0x405ae287, 0xe53c01fd, 0xa4b280cd, + 0x411db5f6, 0xdc963f2d, 0xbec4f8a0, 0xed5d5189, 0x916ee98b, + 0x336fd13d, 0x042df48e, 0x6925b1b3, 0xace0074e, 0x0cf56291, + 0x25317e95, 0xe8d38b48, 0x821c446b, 0xc7ad1d2b, 0xf0b65934, + 0x71c44135, 0x52ca0d50, 0x971b736f, 0x27b46c26, 0xaf9ffa57, + 0x1936618e, 0x21ac6779 }, + { 0x2d7fbcd2, 0xab420e3f, 0x97bdfc18, 0x12722473, 0x4df5d4b4, + 0x492033f8, 0x3807b7d3, 0x6fcd4236, 0xb33c3625, 0xdfc19b09, + 0xa0f22814, 0x13d6f375, 0x037c19b8, 0x70978a59, 0x0ff27b9c, + 0x4f398997, 0x615a4389, 0xfc0e1a45, 0x3e602f74, 0xffa3496a, + 0xb261ca1c, 0xc3f1c431, 0xee0164cd, 0x612211db, 0xe7f7be9f, + 0x30463ee4, 0x92c2e1bb, 0x015f7e78, 0x24483a56, 0x663d88d6, + 0x0e62d9d8, 0x0e8ec1e7 }, + { 0x8a0878dd, 0xa88ccc29, 0x6640071a, 0x99ac175d, 0xa5173617, + 0x90344820, 0xdd58a315, 0x316d023e, 0x88d221a1, 0x30785bd4, + 0x959c48e3, 0xb74b3de7, 0x4c67a771, 0x42ee0382, 0xe0b91453, + 0x59ef6cdd, 0x9b237e91, 0x7830ae28, 0x495d8325, 0xe1847a4c, + 0xd0773666, 0x67b1217e, 0xa294a325, 0x58192c86, 0x864d8326, + 0x76aa0f56, 0xf4b13e5b, 0xe2a2bd12, 0x1b6b73fd, 0xd850c1c0, + 0x5d103635, 0x653a795f }, + { 0x50dcb199, 0xcfe28985, 0x7fa02b60, 0xb35b8e5e, 0xc97603d0, + 0xbca7d7c3, 0x27f131b5, 0xb0e5288d, 0xe2b12d52, 0x3aa704de, + 0x1db725c7, 0xe206b1d8, 0xc5d1b113, 0x0b12839a, 0xdb45d763, + 0x14f970cb, 0xb2125e8e, 0xc997f93e, 0xee7daa26, 0xbd75739c, + 0x1fef20e9, 0x46ecbd3f, 0x7c6a42b1, 0xf994a114, 0x27fb0fd1, + 0xd289eb4f, 0x9a40da4b, 0x11186d31, 0xfb9d7976, 0x083f65a5, + 0xd444675e, 0x30dfc47b }, + { 0x9eaadfe8, 0xbcfc5ae2, 0xb4d4e812, 0x25027e54, 0x8b533561, + 0xab0702df, 0x56a6a214, 0xa2b9c204, 0x3059068e, 0xb1a3df7a, + 0x9883110f, 0xa3514b21, 0xc4b78e1c, 0xb7be2336, 0x3e2f6984, + 0x17073ce6, 0x2ddf7ac6, 0x86e114a6, 0x07d7c3c8, 0x276192bf, + 0xeb1ae289, 0x5da69e0b, 0x25184939, 0x983af175, 0x407a3aa0, + 0x9ac52a4d, 0xae0fe218, 0x1535c7da, 0x397f2501, 0xe16fe872, + 0x54c212cf, 0x572a591f }, + { 0x09a5553a, 0x49668419, 0x327733bc, 0x3f054318, 0x3eefd690, + 0xf9ceb4b2, 0xf22126d4, 0xbd3cbf9b, 0x2fed9578, 0x6d9671c0, + 0xca0306d8, 0xbba597ce, 0x3d674fe5, 0xb705ed61, 0x67f33f76, + 0xf1d3622b, 0x11cb8c31, 0x15bcf3c6, 0xe53d1aa9, 0xa38467dc, + 0xf908ab43, 0x902fe929, 0x8d15767a, 0x6e3e499d, 0x90afd07b, + 0x8142db5c, 0x6c8b190e, 0x120c6fbc, 0x24919a4e, 0x80c86553, + 0xd8c82c3c, 0x65c2cbe1 }, + { 0xa660bb63, 0x684cda20, 0x86e86245, 0x27dc3b0a, 0x6ba0eed7, + 0x76472cf6, 0x679dd158, 0x79c162e5, 0x08452d44, 0xb6884277, + 0x413f579e, 0x829bc6b3, 0x95011770, 0x92ea15ec, 0x47738183, + 0x5e34e300, 0x73e1d2f1, 0x8c3ca349, 0x229bd3de, 0xa5c4f1dc, + 0x94ef7ed3, 0x783eff1b, 0xdfae7a1a, 0x46db738d, 0x1a099852, + 0x4353d72e, 0xa0dcf4ab, 0x2533ad58, 0x0e7888b9, 0xd8055016, + 0x3ba77f66, 0x831440d5 }, + { 0xf611b2da, 0xf43e2e32, 0xd0fa46ac, 0x5d066e29, 0x820b3c0d, + 0xe897f3e8, 0x1d3e44f0, 0xc45c28e6, 0xdfd27a66, 0x929d7f66, + 0x101e8517, 0x735b860a, 0x3de078dd, 0xea3fce98, 0x638ce11a, + 0xc9977db5, 0x48536b3b, 0x0488382f, 0x64cadfc6, 0x7e0c7a3c, + 0x82147b71, 0x3cd17f7f, 0x1b411e3e, 0xe95663cc, 0x985fb46d, + 0x5739ac8f, 0xbcf119ca, 0x385399cd, 0xe15a2815, 0x4a985a70, + 0x6d5f4566, 0x504c3a8a }, + { 0xb8fa53c7, 0x00b55283, 0x509474e3, 0x985cff38, 0x437ce25f, + 0x234d241c, 0xe5a129ed, 0x29832430, 0xaabcc674, 0x6ad38956, + 0x7ee81ee1, 0xa2dc001d, 0x670b2702, 0x4c23c6b6, 0xa6e8a3bb, + 0xb35e567e, 0xa69673ea, 0xbc70b3ce, 0xe6e28eac, 0x85a7a9c3, + 0x5537b7da, 0x2ae684de, 0x6de937dc, 0x5ecac3e5, 0xf8430422, + 0xbf2ea6c9, 0x77fdc520, 0x38caf7d0, 0x69f56add, 0xc27af0b1, + 0xc71d21d2, 0x496e4699 }, + { 0x9fa93467, 0xba14fc82, 0x0eb2a614, 0xc2e37684, 0x4833e09b, + 0x659bcfaf, 0x3686bdcc, 0xbc859752, 0x81f3216a, 0x40bfd080, + 0x17c081b8, 0xc463bda6, 0xbb04793b, 0xbd01fa86, 0x2cd640c5, + 0x5a21ece6, 0x2203d5c4, 0x97bf6a54, 0x951167b7, 0xceb40edc, + 0x765ba268, 0xd67aacaf, 0xaeab51f9, 0x8ba0d9e9, 0xb0d6863a, + 0xc14b215e, 0xe5f06952, 0x354cdcdb, 0xcb3744b5, 0x4f2b5ccf, + 0x13037fe8, 0x13389173 }, + { 0x45003cd1, 0xee680640, 0x44ae2ac6, 0xfdac17bc, 0xde8e5314, + 0x4bcd419f, 0xc7cea95c, 0x81e34eb9, 0x38f37e01, 0xbb57762d, + 0x260990c8, 0xecc4cfb0, 0x50a34a7b, 0x0bc493f9, 0x543304ef, + 0x68074172, 0x6bc8aa2a, 0xaec0fcb2, 0x3b45fea5, 0x9e7a9b46, + 0x55fbdbac, 0x4bb2952e, 0x0485dff4, 0x50f0c0a6, 0x4dea4796, + 0x02c5104d, 0x695e3a02, 0xd2cefa09, 0x6da1f345, 0x4c8102b4, + 0xf3833fbd, 0x422eb573 }, + { 0xa6ad3f47, 0xac592eb6, 0x9714ba0e, 0xb0861f6d, 0x07281459, + 0x57c1e919, 0x64ea5803, 0xcf7c94e2, 0x54b12723, 0x725376ac, + 0xdafb736a, 0xf2a6ba41, 0xcba03cdc, 0xc89e8920, 0x5b0fd3ad, + 0xf2e20cb4, 0xd66059fe, 0x26ea5a54, 0x889df8bc, 0xee63fa8b, + 0x66a3f2bf, 0x40f1c7e1, 0x747312e1, 0x09febc9c, 0x727999ff, + 0x7d19b9c2, 0xb7fd2b05, 0xa9fbbb4c, 0xa0da2dc6, 0xcfba27d7, + 0x2c252582, 0x368541cf }, + { 0x22799d37, 0x510d3c9e, 0xacfa333a, 0x1b677de5, 0x080f795b, + 0x4e6ae18f, 0xafc8dfc2, 0x69b53c2a, 0x0e842dc2, 0x797541b6, + 0xac067fe8, 0xd5a6f2af, 0xbd07d877, 0xd0208a03, 0x654be2f2, + 0x34b473f0, 0xf515e23e, 0xe67c102a, 0x2ac1af48, 0xb00dbf9d, + 0xb6a13d00, 0xe264fa41, 0x97e94c11, 0x1669786a, 0x86a586f4, + 0x09d8cf2d, 0xc7f927e9, 0x073bf869, 0x2241a566, 0xb8977880, + 0x22261334, 0x59a5bf59 }, + { 0x81347191, 0xe9d1c91e, 0xeb969972, 0x186c1abc, 0xa9d46a7f, + 0x07888767, 0xdaa7d397, 0xda93cfcc, 0xd91b9aa0, 0x08bee9f1, + 0xf8dd3c6c, 0x8267fd78, 0x94228100, 0xf93860d0, 0xdadb47fb, + 0x6a6a71aa, 0xa6156f8a, 0x9caa06b7, 0x39848bc9, 0xaa1b05e0, + 0x2aaa9135, 0x36ddc237, 0xb13f3bd1, 0x77e7e079, 0x4acc5f4d, + 0x8d0b5cbe, 0x984cfd36, 0x04da45f8, 0xd3d3e0f8, 0xf14ef618, + 0x43eb799c, 0x467564c1 }, + { 0xb6fff5d7, 0x8d725904, 0x92dc4752, 0x037f33af, 0x6d20b8aa, + 0x9095d575, 0x43baec39, 0x32235fc1, 0x68a2b9b0, 0xa2feb4af, + 0x94d35c61, 0x61c50318, 0xea877486, 0xac92b6a2, 0x011bc6f3, + 0x8eb48b15, 0xc79edcb2, 0xa28fe128, 0xa5d2a006, 0x9f71bc0c, + 0x2f15b850, 0xf3167732, 0x7a036218, 0xfe8d728c, 0x4f81e09e, + 0x068f39cb, 0x7b7c50d9, 0x1773f016, 0xed6a1e03, 0x0d0f7adb, + 0x4ee984d5, 0x8a0dee16 }, + { 0x47366e6f, 0x504991bf, 0xe86c3005, 0xb8084d9f, 0xa40cce36, + 0x14c4c751, 0x3f1961e2, 0xbbb46aa6, 0x40445e43, 0x56a785f9, + 0xc91e215f, 0xdb8d1b57, 0xc7ee808d, 0x6a8e453e, 0xbbaa1e8c, + 0xc0367ef8, 0xe3e18109, 0x310d91f1, 0x7e20a2c3, 0xf97cfd0e, + 0x554cc277, 0xf1e80c84, 0x7b628403, 0xe89bbc1d, 0x3fe0a17c, + 0x7778a966, 0xc1f00073, 0x9e9db19f, 0xb6f6bed2, 0x2ce7fe7d, + 0xee97ce23, 0x7b04b5d2 }, + { 0x82c5faf8, 0x5b546bc7, 0x8eb81097, 0x1a734c5e, 0xe77851e0, + 0x3d566861, 0xe956d51f, 0x833a1013, 0xc3c3c37c, 0xc7351731, + 0xe0c148ec, 0x607738fb, 0xe1bbef41, 0x2ec6f0bb, 0xcfa51857, + 0x0aa2ac6e, 0x66e3adf0, 0x072902d7, 0xc622d6e3, 0xcd4d5089, + 0xa6dd802f, 0x3ae21b23, 0x33886372, 0xe5465a55, 0xa8d81822, + 0xd85119a0, 0x3786977a, 0x4f14d032, 0x9c7b272c, 0x515b081c, + 0xc99be31c, 0x1c6a95a4 }, + { 0xc2821363, 0xa6b14ad5, 0x4d17de1c, 0x829c1823, 0xccade848, + 0xaef5d2c4, 0x82489e27, 0xf412ab39, 0xf081d927, 0x92c9c098, + 0x75cbad1f, 0x6f87bdf4, 0x1a1d9fb1, 0xf4aadab8, 0xb75f3b76, + 0x475a7923, 0xdbbba8fe, 0x99dd0ad6, 0x4b70ab45, 0x836f6164, + 0x34bd9af1, 0x2a464881, 0xba9abda3, 0x5c91226e, 0xe65625fb, + 0x4cec8709, 0x0818e4be, 0xd4b3919e, 0x14f6879c, 0xa5c09c84, + 0x30a864c9, 0x72708a02 }, + { 0xf34a466c, 0x4f33c0b1, 0x7f9d45ba, 0xa1bae09c, 0x0e28785c, + 0xd70f0fee, 0x90880881, 0x824c7146, 0xbb043da3, 0xe2416c2a, + 0xcec6f432, 0x733da713, 0xc9793e1c, 0x2b590649, 0xb35c9365, + 0xdb62d5b0, 0x3e5c1b2a, 0x355eb6e2, 0xbb16b515, 0xcfe8b5ce, + 0xf709691c, 0x9e081869, 0x61a85bd5, 0xc865f9fb, 0xfae103f7, + 0xf169d3cc, 0x73467e9d, 0x9525c473, 0x43695113, 0x7db55c0b, + 0x73265d21, 0x7491c74c }, + { 0x80d2b94d, 0x312ed5bf, 0xba4b260b, 0x1b8ac633, 0xd62219a1, + 0xac86c58c, 0xaeb82c8e, 0x317ccf6b, 0x59ef9ced, 0x2dfb29ee, + 0xe42bcd5a, 0xdaa7d898, 0x5974b201, 0x93e295c8, 0xd9fc5adc, + 0x69e75784, 0x012aa3ba, 0xd6c4709f, 0xc85d3cb9, 0x1fda9f37, + 0xd3dd4abd, 0xe5487e25, 0x0b3ba22e, 0x00fd4b01, 0xc6e8dcbb, + 0xcb591493, 0xbce68664, 0xb7329fab, 0x68906b76, 0x6829d1c2, + 0x74176841, 0x8bcfd3e5 }, + { 0xd3c8c314, 0x06882734, 0x11870833, 0x95f0b2f1, 0xc068ba16, + 0xb937f7c3, 0x77924787, 0x5365e0d8, 0x1f992227, 0x15527e5e, + 0x27dffd4f, 0x0a069648, 0x2f586389, 0xd58b3df2, 0x6af20ead, + 0x83446b89, 0x50746257, 0x09d7970b, 0x4022a691, 0xd9e8d206, + 0x671ec379, 0xd1e5f8af, 0x057fe91e, 0x6f542509, 0x52890418, + 0xf14dda81, 0x1db932ad, 0xbd78010e, 0x905a9378, 0x3e18d1e4, + 0xbd37ab49, 0x53cadcf7 }, + { 0x5e53d0ff, 0x1bb5edf7, 0x888abf67, 0xd886606c, 0x12206d15, + 0x6491b0f8, 0xe22b6a33, 0xb3018345, 0xb173b317, 0xaba6794b, + 0x7dc9e595, 0x8c1e5867, 0x239624d1, 0x4e106482, 0xda55dd53, + 0x61752e59, 0x9e42879c, 0x018b4eab, 0x491f2bed, 0xcaf6784b, + 0x1e79429e, 0x3dcdb9d2, 0x10f26224, 0x36941485, 0xa650ec5c, + 0x106f190a, 0xb69a9760, 0x7542a5ae, 0xc32d1046, 0x69bd75e9, + 0xbf8c62b1, 0x90849964 }, + { 0x5a93c661, 0xb1390cf6, 0x9db5f056, 0x18486264, 0xa51a1788, + 0x92a93a9d, 0x6772de9a, 0x1b0cbb8f, 0x7c71487c, 0x6e67febd, + 0x4e62423e, 0xf9b4382d, 0xbb5a42f8, 0x96fda50e, 0x6089a4f2, + 0xc921b337, 0x875ec516, 0x49d32d7b, 0xc410124b, 0xbd86d2ca, + 0xc421fb7a, 0xf6862209, 0xf6b7de33, 0x3e1949ab, 0xe93c9268, + 0xcdee18f0, 0x08dc4cc0, 0xd4edbd5e, 0x73580d22, 0xc2b75be4, + 0x468cd7e8, 0x3d7f6ffa }, + { 0xdffbd5d1, 0xea7b290c, 0x970338df, 0x9d759da6, 0x90feedc9, + 0x56680b08, 0x42dce68e, 0xbc690af5, 0xb2ae4d82, 0x8519df2b, + 0x7f195b60, 0x5612467f, 0xd83c21f4, 0x659a342c, 0x55651633, + 0x55771bf5, 0x548ba562, 0x5fc68935, 0x9492f23a, 0xb5419203, + 0x9c9c6017, 0x567528e3, 0x511e6019, 0x3f064ed4, 0x1d16a555, + 0x303f9eb9, 0x2254abee, 0x3e18c4fd, 0xfd434e7c, 0x40994d6f, + 0x6dde74e6, 0x8fb12d3f }, + { 0x293cb7a4, 0x6c6381a2, 0xb87b7e4d, 0x453e09f0, 0x078ac3ef, + 0x4f212823, 0x578cae91, 0xe89ffad0, 0x716ba4dd, 0x4a2b696a, + 0xf6f580a0, 0x14681a14, 0x4c2f1307, 0x1358f97b, 0x2932fb89, + 0x87896996, 0x268a5af7, 0x29dd850a, 0xfe239f83, 0xaf771f6d, + 0x4f47499d, 0x5f20fd2e, 0x867ca0e9, 0x9b643e77, 0x375981ec, + 0xe7858ecd, 0x19ab1c97, 0xbe946a59, 0x06ff3453, 0x4f9303a2, + 0x75d237b1, 0x3fcc6731 }, + { 0xdf21f920, 0x509debd5, 0xc1401b90, 0xfaf70e1f, 0x95a64aaf, + 0x2429cbfd, 0x2c37a122, 0xf2120855, 0x7deb926b, 0x1d4c93f4, + 0x9fb3f1dc, 0x12f3e4c0, 0x5b51bc46, 0x56085a59, 0xf10fdbd2, + 0x2a2f5d62, 0xdf0cb3c2, 0x60dd62cf, 0x6b0f254b, 0x154424a3, + 0x564612b7, 0xc3a5a05d, 0xa1f5249c, 0xbebe30cf, 0x7e62a188, + 0x24ec6903, 0xaf429939, 0x75f0fbac, 0xb3fa8685, 0xd41345dc, + 0xc7151c34, 0x645146fd }, + { 0xba1924f9, 0xecec633a, 0x006326e1, 0xbba6f136, 0x7e50fc17, + 0x203757ac, 0xef3d8e00, 0xca531919, 0x51dc5a74, 0x9545a6aa, + 0xd31412b8, 0x6e21d58f, 0x7bb1d000, 0x01bc3005, 0x6ed1a9c3, + 0xf1789c69, 0x9858fa48, 0x7af2d35f, 0x8197be85, 0x434d09b9, + 0x29aa265d, 0x1dc07755, 0xc058fa80, 0xcad03be7, 0x54ba14ce, + 0x92d70a9f, 0x6c050a74, 0x6dc78505, 0x4d005dda, 0x2a7ca4a9, + 0xabfb9f2e, 0x448d3d72 }, + { 0x29b33989, 0xdc56f145, 0xa9ae815a, 0x868351bc, 0x4b074414, + 0xb3f45613, 0x3cd9f33b, 0x955ce42a, 0x5ff6e4a3, 0x13ade4ec, + 0xa50eaa91, 0xd3aac715, 0x5666efdf, 0x0c61ec99, 0xf6a4470a, + 0x108a28b8, 0xe54844c9, 0x402ef584, 0xd0e2f337, 0xb825b162, + 0xb46f7cbc, 0x3dcd131f, 0x96f2fd89, 0x208178ec, 0x25928c78, + 0x4d8c5d67, 0x9963c459, 0x285a33df, 0xd92a309f, 0x72497175, + 0xcb7019a5, 0x76881479 }, + { 0x91767eed, 0xba43a114, 0x92bf65db, 0x5e11b9ad, 0x03a5e21a, + 0xe8a22ce0, 0x2a335415, 0x63604421, 0x4a9ead62, 0xc2c563b4, + 0xa0b2aee5, 0x4bc06264, 0x8bf2e1d7, 0x75b8d575, 0xd08a265d, + 0x1cff0ee7, 0xb0b712a7, 0x17914e1d, 0x4b18692d, 0xc35925d0, + 0x56cce815, 0xde253f4c, 0x9fff0e3a, 0xa479241c, 0xddabed19, + 0x50b9d06e, 0x59fae506, 0x67135260, 0x532ce180, 0xf37600fb, + 0x5e5a8626, 0x670eb01c }, + { 0x73cdbb43, 0xdf73c0af, 0x7f2431ad, 0xcf08ecc5, 0x2a1a3845, + 0x91780541, 0x9224ddf1, 0x69a104f2, 0xbeac7eff, 0x4352f38d, + 0x7c2d1322, 0xfc3b3b4e, 0xb5e4b476, 0xa69e9430, 0x975a46f0, + 0x7d932340, 0x5d64eece, 0x8093899e, 0xdb2345e9, 0x7b821250, + 0x7f4b796b, 0x23552932, 0x4bb90b1f, 0x2ee9cc15, 0x9112f7d6, + 0x1fa9c8f5, 0x1cbaae32, 0x2d0f2f98, 0x0075166a, 0xb77f0366, + 0x635dff27, 0x504852e7 }, + { 0xa2f392fa, 0x2f0f3ce5, 0xec6c9078, 0x326c076a, 0x84baaaf6, + 0xad01de92, 0xcbe8e993, 0xb01b16d3, 0x2d950908, 0x71305c24, + 0x3853af38, 0xc66fd617, 0xd3c429a0, 0x7735140e, 0x1fabf027, + 0x8a31b12a, 0x058b3177, 0xa0530002, 0xa9c7deb9, 0xabffd9fc, + 0xe8667d30, 0xd05ef69b, 0xe9a9e13f, 0x2f3a7308, 0xb91eae9c, + 0x3f4c9a19, 0x618ce6c4, 0x50d0cee7, 0x5240f8b0, 0xfb24dc40, + 0xf7e90cc4, 0x992fe151 }, + { 0x38f197aa, 0x4454db31, 0x87872f98, 0xa4ded69d, 0x44f0a828, + 0x97b427b0, 0xa31e48c6, 0x9821e1ae, 0xdd98efec, 0xe38cb09f, + 0x480cb3ae, 0x20b84fa8, 0x47475573, 0xba5bb4a8, 0xcd50e96b, + 0xa9be080a, 0xef103550, 0xc4451e9c, 0xc441325c, 0x626ee75f, + 0x38a5e33d, 0x6eea5e98, 0xa2b0abd2, 0x7321beb9, 0x9b6082a9, + 0xca92e484, 0x992bcc2a, 0x1dc8168a, 0x9c8eb9fb, 0x134ecf4b, + 0x4c5b71e0, 0x5a68bfa8 }, + { 0xff0a2bfb, 0xb4ff3b45, 0x5502f8b0, 0xd105fff9, 0x5b1c0c26, + 0x14de5885, 0x0d3b9d04, 0xed16865b, 0x026d3917, 0x2f5a2453, + 0xf4db3c0e, 0x6a22f493, 0xe2418f2e, 0x4871548a, 0x509bef61, + 0x6ab363a8, 0xb8cbbbec, 0x91ca1e3a, 0x4011a396, 0x71e0dc98, + 0x0d5ca577, 0xff982e0a, 0x81897bc1, 0xeb40b045, 0x085ad5e7, + 0x4bc24a46, 0xa6337b7c, 0xd15c8fa0, 0xbef1628f, 0x56ce6ef7, + 0x9f5ef439, 0x78acfdf9 }, + { 0xf8520189, 0x45bf7f15, 0xc77f61c4, 0x954202a0, 0xdfa22e1b, + 0x39edc6b9, 0x1f4a3487, 0xd2d60267, 0x4814cc52, 0xcd933929, + 0x05e9f123, 0xde76a124, 0xae36b6f7, 0xe2306ea0, 0xb83a58e0, + 0x53815218, 0xa041231a, 0x9862bb76, 0xbf31be71, 0xe8da253c, + 0x37de861f, 0x2dfc5332, 0x90ae4890, 0xf25c93f6, 0x8baa6ed2, + 0x66bcb8f0, 0x908b4a29, 0x6f10ae0f, 0xb061c949, 0x8cb4b48c, + 0xd075a366, 0x0ad92d73 }, + { 0xc2ca548a, 0xbfb95fed, 0x80cd89ab, 0x4778c620, 0x3466c280, + 0xbe99154b, 0xd4be8902, 0xea3be093, 0x13e681ed, 0x847b7995, + 0x02f40161, 0xf22a8f4b, 0x4aeb7fe8, 0x3ef2cb4d, 0xb3aed5f6, + 0x9adc5151, 0x98c31163, 0xec1ccfd1, 0xa3d7d88f, 0xdc2ac17b, + 0x46421097, 0x08fa64d3, 0x94b90bcf, 0x5ebf80b7, 0x0b50a9eb, + 0x1b78b4ba, 0x279aa66b, 0x1a4fe934, 0x075b3ced, 0x8ef4dcaf, + 0x70a6e9ae, 0x95bbd8a0 }, + { 0xe614bbd0, 0x59f92495, 0xb823e363, 0x7567a887, 0xfc1bd6a7, + 0xe247c9ec, 0x8e835c42, 0x2bfaaf47, 0xaade066a, 0x314ef4e0, + 0x5c16d336, 0x072baa63, 0xe2f0e389, 0xfa429c71, 0xbd07d90f, + 0xcac1e5d0, 0x514f5c04, 0x69ff35ea, 0xc0554ec1, 0x893053fc, + 0x2a35947f, 0xab1d86b7, 0x2aebe487, 0xe29fb060, 0xdfb9cf21, + 0xa0a10d6d, 0xf20dfcf5, 0xad147059, 0xb8867a2a, 0x480dc66f, + 0xc125a919, 0x375a884f }, + { 0x1217f7ea, 0x178cbe2e, 0x875c6dab, 0x1a161e2a, 0x1bdb1a54, + 0xf7707ec0, 0xe4fd73ca, 0x678864a0, 0xd13a0d86, 0xbaebc664, + 0xc8d30668, 0x40325f99, 0x2f1c5950, 0xb93ed9c9, 0x541e0667, + 0xfdf36763, 0xb91a6763, 0xfd97fbb0, 0x6079c9a0, 0x26aa69ea, + 0x1eaa8c47, 0xc7303c80, 0xafa63c55, 0xdec75c81, 0x4fd12adb, + 0x01cdcde2, 0x1968838a, 0x9fe0dda7, 0x38415379, 0x66bb093b, + 0x08cb84ec, 0x268d818b }, + { 0x41580555, 0x73dae358, 0x473d103b, 0x4fc32e67, 0xbeccc1ab, + 0x240c1013, 0xb24ee9de, 0xda4099f2, 0x9fa8e066, 0x37b0cb5b, + 0x6438d7ee, 0xb5ae04e4, 0x2b720140, 0x7f7d3164, 0x339e4a78, + 0x86ef4edb, 0x3a7d8375, 0xa5e77eed, 0xbd707c2e, 0x883fad37, + 0x0f979189, 0x816b633a, 0x2e7a208e, 0xe24c028a, 0x4435516a, + 0x1171fe3c, 0x4f5f2bf5, 0x3eb93b33, 0x01b53a56, 0x8419ed4b, + 0x056ca44b, 0x8b02735c }, + { 0xe1019195, 0xb89bb464, 0xf3fc28c1, 0x1de4c026, 0x2bfc3b21, + 0xac120e6e, 0x91bdf92f, 0xec71bc5a, 0x0d995bc9, 0x485d7ab4, + 0xe6491ffe, 0x97c6768e, 0xafbce265, 0xd9552d19, 0x8e1b76c2, + 0xbae6c7fe, 0xd7e3ad1b, 0x167d8281, 0x5e989734, 0x3e149af9, + 0x8a0c8182, 0xd1f0024c, 0xc3006c0d, 0xf571ffdb, 0x58773d4c, + 0xb32ecf7e, 0xfd3540d8, 0x5822a782, 0x04365042, 0x5ab45c3f, + 0x4b4d85fe, 0x400e3aa0 }, + { 0x5e46e4a2, 0x47321649, 0x24136074, 0x37a2ed64, 0xc60ec77d, + 0x659223b1, 0xe5e0ac2e, 0x5e13aac3, 0xc5107ab7, 0xda17c41b, + 0x73c253db, 0x65b22ec9, 0xa5012296, 0xff3867b8, 0x0621a99b, + 0xfed660d5, 0xc89fc3f5, 0xa3c28506, 0xf16451a7, 0x3ed350b9, + 0x67cb586f, 0x27c3e032, 0x967185b1, 0xc807c779, 0x4a13009b, + 0x09c157d4, 0xadaf1f4d, 0x362f7647, 0xf3a6a198, 0x4a42b9ac, + 0x8da6e039, 0x131c3da2 }, + { 0xa7da83ba, 0x4a785ff1, 0xd04f4436, 0xf415b425, 0xec03f812, + 0x7c0899bd, 0x80f5f4a2, 0xc58d411a, 0xfda251b9, 0x3d32d610, + 0xcd3b2f32, 0x99bb4504, 0xf4c2083c, 0x198c444b, 0x730e83fd, + 0x60c261af, 0xcb02db90, 0x060ca4df, 0x9df1e7c8, 0x0ff7838b, + 0xc4c690c9, 0x6b79cf97, 0x5d75f154, 0x131514d7, 0x1cb0e8ff, + 0xa7c074f1, 0xb2c17615, 0xb920aac1, 0x44aa0ff0, 0xde8098ad, + 0x34545ce9, 0x71d1a46a }, + { 0xfa1b382e, 0x76178f76, 0x772dda0d, 0xa0d8ecc3, 0xc5d4d130, + 0xaa5aab2a, 0x8d72622c, 0x27d38ba4, 0xca3bed06, 0xc5410db6, + 0x793ceccf, 0xf637a588, 0x6e65e3d7, 0x1f65dafd, 0x60a45641, + 0xc3b44a85, 0x4f78540b, 0x0f47b3a8, 0x5e4d60f6, 0x824fdadd, + 0x17d3b6d5, 0xd8ccf90c, 0x325fc13a, 0x008eabdf, 0x3648fab9, + 0x3e90d716, 0x24c52d4b, 0x3964ff3a, 0x533d0acb, 0xb95cc416, + 0x1167f521, 0x6cd2699f }, + { 0x12f4f3ac, 0x2d8c0b3b, 0x99d1bdfb, 0xb03dcfe2, 0x30f37326, + 0x540034f8, 0x7c5a8c82, 0x22dd6893, 0xcd8f1442, 0xeb7093d0, + 0x585742f2, 0x892795a7, 0x087adadd, 0xe15f282c, 0x16ab7b5e, + 0x7bbdc749, 0xa58acbb4, 0xd30fe40b, 0xe2bac39b, 0x0de417eb, + 0xc61a04bc, 0x4b4b19a6, 0xf2735569, 0x9338c34d, 0x30ab196f, + 0xe8f03742, 0x6c88c965, 0xfa2efcb8, 0xc7eeb826, 0x19eee274, + 0xda345dc2, 0x327c063f }, + { 0x5b47cd53, 0xab399eff, 0x1943aefe, 0xbbe9869d, 0x1402a866, + 0xe64ecc7b, 0xb1c25a16, 0xc3e7c2aa, 0x022de271, 0xc4216b79, + 0x366d6a5f, 0xe58dfcc8, 0xda813336, 0xd159509e, 0x130bfb7c, + 0x370400f2, 0x93b48780, 0x1be4e059, 0x39f3cd22, 0x0623a1fe, + 0xeecb4f87, 0x72aa22b2, 0x6c27b83b, 0x1af4c496, 0xda5fa5bf, + 0x7a42a94b, 0x48b01af2, 0x9afba822, 0x3670112c, 0xeb6b9d2a, + 0xc0df6856, 0x020f19d1 }, + { 0xa4dbba20, 0x37051a86, 0xdb1de5c5, 0xb618ebc6, 0xe6525840, + 0x9a780a19, 0xd2bccc4d, 0x9440302d, 0x10285a24, 0xe9ff023d, + 0x3a486268, 0x3b937ee3, 0x4cd61147, 0xe37ee2f2, 0xa3d057cf, + 0x79fbbfd3, 0xccddefce, 0x5fba16d3, 0x5b231727, 0x916058ec, + 0x720c3adb, 0x47699ebe, 0x8b4f6bba, 0x26274386, 0xf18a0770, + 0x54b0092a, 0xacca1160, 0x99d090eb, 0x0c888f60, 0xf757e1ff, + 0xb0050544, 0x79e72720 }, + { 0x2820a239, 0x632acf25, 0xaae6b310, 0xb1a3974e, 0x48c0a1df, + 0xd61fd6ba, 0x5a3ee7aa, 0xd2453c39, 0xb980446d, 0x548455a0, + 0xde16676f, 0x9f29d97b, 0x789375a1, 0xf252ca0c, 0x7743a985, + 0xe961af3e, 0x66cdbd8d, 0x70c79c56, 0xcbc538f9, 0x14a3854e, + 0xa126851c, 0x58daa73a, 0x2a9f558c, 0xe9b5bb45, 0xfbd15e05, + 0x37af7f83, 0x38a1939d, 0xa4487927, 0x9511a056, 0xe428b2b5, + 0x7015846d, 0x001d3ce3 }, + { 0xe145b1d7, 0xd6be36b9, 0x009c5664, 0xf3e3938a, 0xe7c0f6db, + 0x2e562e7d, 0xc343f539, 0x951044e6, 0xd90897b1, 0xa5ab62b8, + 0x512f797c, 0xb1a1f70b, 0x750f28e4, 0x91cdd754, 0xffb8165d, + 0xb4c80e2f, 0x594d02b3, 0x65ed39c7, 0x56833edc, 0xcc12a49d, + 0xf3693a18, 0xe73694bc, 0xfcd2c404, 0x34cc134a, 0x11d40194, + 0x071bd5fc, 0xfc585e46, 0x05759047, 0x790b7a04, 0xb3280360, + 0x40afc684, 0x4bb8c6fc }, + { 0xfd0f8796, 0x3120e2dd, 0xb133c9de, 0x6968a40d, 0xa9369c6e, + 0xfea366c0, 0x6007273b, 0x37e5b6d6, 0x8cb81439, 0x39e4ecf0, + 0x9febc005, 0x487fe9cd, 0x0199b53c, 0xeb8af444, 0x293519eb, + 0x2f124e3b, 0xc82c9c16, 0x860c218a, 0x709dc590, 0xacd1d6f2, + 0x36d50529, 0x5696d545, 0x59120bfc, 0xc03f5df9, 0x10ffa690, + 0x99a3e88d, 0x6c432827, 0xd4f9cfa5, 0x9a135d89, 0x2e8fea9e, + 0xb6a77e78, 0x3699a881 }, + { 0x1eb1c64d, 0x5bca3372, 0xf1d28154, 0xe9cf3a2d, 0x6537106f, + 0xb7e2e9b3, 0x4f7cbf4d, 0x06c17151, 0x2058b37f, 0xcbde416e, + 0x8834e9c5, 0x82c53a7e, 0xe9ac3a75, 0x94dbdfe2, 0xc5e67c02, + 0x795ec6cb, 0x1426a80d, 0x8c23c25f, 0x6a8d4f9f, 0xee2cd20d, + 0xd3b7c235, 0x838daa54, 0x3d7a4d52, 0xb9e08ec0, 0x781cb473, + 0xca9475e9, 0x5ec31caa, 0x7271f39e, 0x82535187, 0x1df08e9f, + 0x208aff8b, 0x4f3a4b03 }, + { 0x1ed095f8, 0x0f7b8107, 0xda226d4e, 0x23e37fa6, 0xafb36d1d, + 0x8b0f9852, 0x07d8e311, 0xb114634e, 0xe3e0f16e, 0xb9634a97, + 0x421eec37, 0x2454bb9c, 0xd72b21c1, 0xb4ecd5db, 0x6df20d7c, + 0xf9603868, 0xdf86e0a2, 0x9f5359fd, 0x5ac488aa, 0xc43d54fa, + 0xd1049df4, 0x56d714ab, 0xb020607a, 0x13152b3e, 0x7a02325e, + 0x49be1c18, 0x52ae84db, 0x44f24f4a, 0x0b5a7b80, 0x9e525c03, + 0xa6d179fd, 0x6d874446 }, + { 0xbe9a42f5, 0xd29d07aa, 0x3781ccc8, 0x1fd5316c, 0x9dc69ea1, + 0x71a75a6d, 0x88fee91a, 0x4e19e0df, 0xf8d44f12, 0x99c2b4dc, + 0x31ae94e4, 0x05f6df92, 0xcf28ccc2, 0x27fba876, 0xf57f7ceb, + 0x6e1a0f01, 0xf3fd3b74, 0xe03f1f34, 0x42c1d213, 0xa0edc4a7, + 0x7deb8580, 0x5caac270, 0xaf0848bc, 0x0f5d791f, 0x07ac759d, + 0x17f514ad, 0x904fc531, 0x95a39734, 0x7bb70f3d, 0x95a4aca9, + 0xff9c5609, 0x3cf384c9 }, + { 0xce1fc9e3, 0x700506ba, 0x676b0399, 0x49721742, 0xe72bf7b3, + 0x2b4a1b8d, 0x79b209f7, 0xca8602a8, 0xce26a8e1, 0x90580b90, + 0xfe24f39a, 0x1ef339b7, 0x629362e1, 0xb6c5d991, 0x577b24f4, + 0x51174e1a, 0x05e451e9, 0xf380fcb5, 0x148321bd, 0xf4d97afb, + 0x747e5d2a, 0x099806bb, 0xbe99a608, 0x85525d65, 0xd455e820, + 0x264828d9, 0xd8560a65, 0x8c8c5405, 0x71030770, 0x3c67e73c, + 0xee73df26, 0x2b248850 }, + { 0x8541159f, 0x2173cde6, 0x4fb410b2, 0x78224c18, 0x1f2ca1c7, + 0x07a28619, 0xa8b23e40, 0x52c207d6, 0xa6b2344a, 0x071a0210, + 0xb5ed2945, 0xdb0e587c, 0x810fcc6c, 0x6c56b8ef, 0x62d843b9, + 0x1248c58f, 0x74c66975, 0x4b90363d, 0xe66c66f6, 0x6348f7f2, + 0xc126bcbe, 0xb2f9d441, 0x73ce49e8, 0xac07f2a3, 0xe81b0df0, + 0x52486758, 0x1d4621d1, 0xa108b54d, 0x74414a1c, 0x17261ece, + 0x6a3ac215, 0x938b3bcc }, + { 0xe4ded340, 0xa9e4a16b, 0x80e88036, 0x8e65fb2a, 0xdcd73acb, + 0x97089606, 0xaaa657a9, 0x1c3a0434, 0x49101b06, 0xf304fc58, + 0xda0bb64c, 0xe60fb61a, 0xf5542df5, 0x818c2aec, 0x56f76d5f, + 0x74020576, 0x92533d97, 0xb566b790, 0x74d6eb5f, 0xae4655e5, + 0xa55b44b7, 0x60f7a1b5, 0x93747ea5, 0x7970179b, 0xf2dace56, + 0x8ae7e0e8, 0x84e83c06, 0x98474607, 0x15307341, 0x24e8c9ed, + 0xd9e89d6b, 0x6cff58a5 }, + { 0x03e51f68, 0x508c01b0, 0x1d2fe7d6, 0xe1d1f225, 0x09bd8805, + 0xf7998d0b, 0x03e415b7, 0x255e907a, 0x607d9798, 0xd148467d, + 0x9b453896, 0x055c3b1e, 0x809f50f4, 0x35001013, 0xd0233fdc, + 0xfbbb2fa6, 0xff1820b8, 0x0b680b0a, 0x38d317e0, 0xb1d404dc, + 0xccc8c7df, 0x133d5444, 0x6ec13f84, 0x7fa847e6, 0x046e2e48, + 0xc33f83d8, 0x4863b3ac, 0x3c627fc5, 0xeb936af7, 0x5f67f8aa, + 0x31b79327, 0x5fe4ac8f }, + { 0x8b6f401e, 0x581aa4bf, 0xad5c7ed4, 0x05db12a3, 0x6fb07b4a, + 0x7b018726, 0x9c22bcd4, 0xfdd11f04, 0x69371c95, 0x5454a7d4, + 0x99a46eaf, 0x066c55fb, 0x7fef96d0, 0x18637c7c, 0x6b83e95c, + 0xbafc1d34, 0x00bb42dc, 0x55c38593, 0x34e7e712, 0xdd8dec2b, + 0xb184cee8, 0x69c9cfb0, 0x49a27864, 0x8dcc0c42, 0x2010f2e7, + 0x290d95f2, 0x6977a420, 0x86e254c9, 0xeb2abdad, 0x20931c89, + 0x121c0548, 0x81377164 }, + { 0x9c5a8edf, 0x6266b25e, 0x1078a7ad, 0x6e1388c2, 0x4876eedf, + 0x5f02737d, 0x62744617, 0x242fa7f9, 0xb385382a, 0x3e2cfbd9, + 0x02f71bef, 0xbadad7b1, 0x677d0a92, 0x562abcfa, 0x51fdff34, + 0x573ebd17, 0x7c250c78, 0xd7f65852, 0xc47ca896, 0xe0cf16ee, + 0x67622c9e, 0x8ccd79b0, 0xf8f2c075, 0x31fc5882, 0xa6008515, + 0x9232b37e, 0x82e8c5ba, 0x4d7bb361, 0xd2f146fe, 0xbf24735c, + 0x9cd2db98, 0x79c280ee }, + { 0xf2b48122, 0xbdcc8203, 0xb04ac48e, 0xa8c04916, 0x9fc4885e, + 0xacf064dc, 0x82c1001c, 0xab838997, 0x676de250, 0x7339e721, + 0x8e1ab820, 0x17aa5aea, 0x6bc14b2e, 0x24d28ca0, 0x816b6230, + 0x570c5bb7, 0xcee6b606, 0x6c51235c, 0x183eae42, 0x1b2bf89f, + 0x9c66274b, 0x3e3af3c6, 0xb51e38bc, 0xe0b04426, 0x73e40e3b, + 0x26dbc58e, 0xb5be5be4, 0x3f9dd578, 0x52c8f408, 0x9fd9f791, + 0xa9e3ff4f, 0x758073a4 }, + { 0x8691ca22, 0x7d27b057, 0x13a2a1b6, 0xf206bfd6, 0xac795413, + 0xe84bd385, 0x75536607, 0xc5d18a2a, 0xc8a0e24c, 0x2e166de7, + 0x3c474dbd, 0x56d5750c, 0x1366843a, 0xdef444c1, 0xcf4b8432, + 0x14646e53, 0xa9fd9783, 0x4bc0d030, 0x297ee203, 0xbda4c824, + 0xfd7be6c7, 0x3d0b10bf, 0x08c7f3ff, 0x2d216476, 0xb4fd4c45, + 0x06e52599, 0x49e9e104, 0xfbab9fa1, 0x8661d32d, 0x9342a7fa, + 0xfaf66aa8, 0x3f3e3458 }, + { 0x951597aa, 0x51ec35af, 0x49df64eb, 0xb677d4ac, 0x9bf4eff5, + 0x0276cd9c, 0x515a2935, 0x423eca49, 0xfd9bb9c3, 0x8a696553, + 0xede1f09c, 0xf99ee9df, 0x199e5f98, 0xb8fa2956, 0x35292c32, + 0xb7638758, 0xfc40e81b, 0x8734eddc, 0x65457d95, 0xd82d5e9f, + 0x30c78d2b, 0xc8ee323e, 0xc1433d67, 0xe77b2e4c, 0x3c8314ae, + 0x56d9f807, 0x2a0e2f63, 0x441eede2, 0x6c48295e, 0x1e9e17ed, + 0x34c294ef, 0x640d20c4 }, + { 0x3284d513, 0x4e9a0b8e, 0xf315053a, 0x074c3545, 0x45acd52a, + 0xb36e7407, 0x1de50db7, 0xd80bdcfc, 0x2549fc46, 0x8d9d47dc, + 0x303f07a8, 0x29b6ef13, 0x6d4ad4c2, 0x4e461aca, 0xfc9f1b73, + 0xca8e351d, 0x57460e65, 0x8bc4094d, 0x0f32d367, 0xb6302b33, + 0x285742e8, 0x69a074b6, 0x876c29c3, 0xdfe52b11, 0x912bd17a, + 0xf39e4609, 0x349aa639, 0x8ee40d66, 0xc72e05c1, 0xb968902a, + 0xc0d92816, 0x0f9c1ca8 }, + { 0x67433df3, 0x1ebbaab3, 0x15d3628c, 0xb6aa5347, 0x97f0c5cc, + 0x13a320d8, 0x65e408f9, 0x72c918cb, 0xd5373451, 0x4b638854, + 0x0b4dca09, 0x731399a3, 0x0a3b1326, 0xcf256730, 0x6608b388, + 0x5ea60dfa, 0x7b290dfd, 0x58ad74b0, 0xd7694f9b, 0x83202789, + 0xb6630fb1, 0x48593db8, 0xc65e3eaf, 0x3db47f70, 0x3e7263f8, + 0x63949c91, 0xe6e6ff33, 0x9b9acec6, 0x098a8240, 0x34bd9ba7, + 0x45d36ec5, 0x7e31c12f }, + { 0x0dfd2dd7, 0xbe281d68, 0x24ab61d8, 0x1efacb00, 0x94431f97, + 0xb9c3005f, 0x959cb3bc, 0x660c8dfa, 0xcffbb406, 0xfdd5fc30, + 0x7969a10d, 0x7a4631be, 0xde13fd1b, 0x336e309e, 0xfc947076, + 0x76b3bfad, 0xdcc72223, 0xfa91925d, 0x156c4ee1, 0x741f0d73, + 0x0e2b3747, 0x4f64ee41, 0xefc4d93c, 0x86be92d3, 0xfc4fbb2e, + 0xc53b7e03, 0x337ca1bb, 0xac196cf5, 0x7e23ba60, 0x4de41a30, + 0x326d5357, 0x1a219c45 }, + { 0xaa4db0bc, 0xfdcf7ef8, 0x7b6c9963, 0x2e231806, 0x3d8a192f, + 0xc2639067, 0xffdc7771, 0xc0cec2e2, 0xa2fc0edb, 0x997c8e35, + 0x82cc6043, 0x78e10ec1, 0x2b0c8120, 0xfd0de2cb, 0x69e57f8e, + 0x4d6c457f, 0x5b53f1c3, 0x953e69b2, 0xc4f89cb8, 0x422a330a, + 0x95566be6, 0x92ff2329, 0x437442d1, 0x73cd502d, 0xbea69403, + 0xf04ce590, 0xf8030662, 0x6ac1537e, 0xb6d0bf93, 0xe02bcf77, + 0xbc90192f, 0x17aaa999 }, + { 0x8e55db2e, 0x0d3d5643, 0x3b946851, 0x835dee43, 0x5b88462f, + 0x1a1440e5, 0xea17e27c, 0xa6ff3b35, 0xdd95f7a9, 0x23f99c36, + 0xbdd672cf, 0x7217fdd9, 0xdd2045c0, 0xf400ac1e, 0x4ff06b25, + 0x94b55c87, 0x0e4a49be, 0x0a44a0e5, 0xb43b6813, 0xe8925e91, + 0x214f96c5, 0x78bedde1, 0x0f97fa97, 0x0f456a4c, 0xa5bfd267, + 0xa28fd86b, 0xbe7608ef, 0x3b4b2d8f, 0x226474bc, 0xfbd5ff8c, + 0xa5f3b24a, 0x6b282af0 }, + { 0x6341a595, 0x78fc025f, 0xa445e28c, 0x591c38d6, 0xeb446842, + 0x72bd6e3d, 0x75547833, 0x3f9466d3, 0x083e16c4, 0x911414d3, + 0x95a7acb4, 0x145d9466, 0x8fd2fb64, 0x102ddf09, 0x0bfd87b1, + 0x2a2b2d2d, 0x59455088, 0x69e9be5c, 0xa80245de, 0xee378bf4, + 0xb2306b0e, 0x80b0bd68, 0xc2be9f3d, 0x76a545c6, 0x4802c245, + 0x429d167b, 0x2b412dfb, 0x13e64427, 0xee8d9762, 0xb664f529, + 0x54706ebf, 0x6d4f5d23 }, + { 0x00ba9f88, 0x35c8f2b6, 0x7bb6d0bf, 0xfdc807e0, 0xb3b81e5b, + 0x0a126d42, 0xa7ac781e, 0x335ce6ce, 0xf37dcba6, 0x3e308e6f, + 0x63c96487, 0x028dca62, 0x8818434d, 0x72eba57e, 0x79b78a26, + 0xa9e3d59f, 0x2f07aea3, 0xd2f0a7dd, 0x24d05f74, 0xe0fe4678, + 0x0116deb6, 0xb2085170, 0x58f37580, 0x9c2a5e92, 0x74070bb3, + 0xe78bd7a5, 0xb9977d90, 0x551fc872, 0x40db81b4, 0x6eda93c4, + 0xd65d34ad, 0x4aaf0b4f }, + { 0x3514c7af, 0x9bef2506, 0xbc181ead, 0xb09e7dad, 0x8fa3ec58, + 0xef3cae87, 0x173b8685, 0xd8dbfab5, 0x921d32dd, 0xb2490fc0, + 0x8bd9c466, 0x4eef386b, 0xa061dbdb, 0xc1cdd52f, 0x25bc04db, + 0x64de989a, 0x85728636, 0x06f9836b, 0x8be44aa0, 0x11a5a804, + 0x097018c7, 0x16dede4e, 0xb2c11fb1, 0x72aec577, 0xa721ecd9, + 0x144dade1, 0xd6ebf3a9, 0xf99c526b, 0x1c2e14d7, 0xa1d4165b, + 0x82bc6337, 0x8b2cbd39 }, + { 0x8a52e991, 0x28ec1bf2, 0xcf9d42ec, 0x0ba202f6, 0xc634ea45, + 0x8307d130, 0xc5762b9c, 0x3fc257b3, 0x487c2a2d, 0xbd3298d1, + 0xa319488a, 0xca14f1a7, 0x06ba06d2, 0xc70ca93b, 0xee405e89, + 0x9aa3f4b3, 0x35deeae7, 0xcc64eeb3, 0x03bf1d4c, 0xd155f578, + 0x45616bfd, 0x041ec0b5, 0x086e33f6, 0x23df80e6, 0xf0243cf5, + 0x399a79c8, 0x874ccd58, 0x86c2824e, 0x8fc5c831, 0x220eeaec, + 0x7dbe3670, 0x57e28304 }, + { 0xfbcdf666, 0x6e60b698, 0x8bebb1d2, 0xbdd06a99, 0x80498436, + 0x4044adba, 0x522bc88d, 0xd76bf75e, 0x28423b20, 0x655c4b9b, + 0x53398a72, 0x65c0f492, 0x0ca37601, 0x76d4f2b7, 0x2030fa5a, + 0x46989925, 0xb6054705, 0x96b37e87, 0x53de1b2f, 0xef96f731, + 0xad54ef05, 0x5ecbbc8c, 0xa93617b0, 0xeb289d0a, 0x7cba217d, + 0x3ac0fbd5, 0x19d4a2d7, 0xd0d3cb56, 0xc91d6063, 0xe8bee9d4, + 0x696ffda6, 0x4f12e037 }, + { 0x15f1a610, 0x4ccfa422, 0x3786519a, 0x804a5c55, 0x73838134, + 0x1246a454, 0x4b284e2a, 0xfa15b484, 0x146d1320, 0x36464c65, + 0x70a8a0fa, 0xfb6ba88c, 0x93c4804e, 0x74e7cee7, 0xb95ae16a, + 0x8c34d22c, 0xf9c1d4dd, 0x9d9ed89f, 0x32025371, 0x61a0866d, + 0x9bd6444a, 0x45b232b2, 0xf277bab1, 0xf888e92c, 0xa9448b02, + 0x73e69c6e, 0x5b521ecb, 0x1a496ea9, 0x5858afb2, 0xa8f78ea7, + 0xb1266f91, 0x83d2333e }, + { 0x67b478d7, 0x1c633288, 0x50a2fc9c, 0xa1ee1ae1, 0x18d2241b, + 0x05b6ab30, 0x893cd696, 0x69f1f288, 0xa8117a87, 0x159d6660, + 0x70e73d77, 0xe8120119, 0x93f55f0a, 0x528fef00, 0xd854dfb2, + 0xb3978db8, 0xf45d9fbb, 0xd6b43ef6, 0xd5bee397, 0x17de4bfe, + 0x6bf76dad, 0xa01e0f59, 0x3d40754c, 0x28b2280e, 0xf8e86ef3, + 0x8edb6122, 0xb7d1e586, 0x8226b6af, 0x2f40a55b, 0x46353215, + 0xc5a31621, 0x7362f13e }, + { 0x73c0c430, 0x792eb27c, 0xa51c3657, 0x8cc0a65f, 0xd2194f1b, + 0x50a5cece, 0x814b4947, 0x18945688, 0x4b6fbbf4, 0xbbf0a81a, + 0xf0aa8608, 0x376f4f58, 0x3987795e, 0xd9361d68, 0xe3a8d0d5, + 0xb6510cd8, 0xb6c1a455, 0x63e2fdbf, 0xaec891f9, 0x2c91154e, + 0xff568f64, 0x0eb1e715, 0x2f2b399e, 0xe7af9cd7, 0x89f0bf0b, + 0x1fc39bac, 0x90983695, 0xf0861d92, 0xda0a20a8, 0xd9b16f02, + 0xa38c0ead, 0x2f10693f }, + { 0x0c06ded2, 0x07a6ce91, 0x2fd9087b, 0xf974842f, 0xa9f635a6, + 0xe468bfd6, 0x1ed60626, 0x04b61891, 0x369ee548, 0x1fb2f89f, + 0xdc96a201, 0x9cbd1113, 0x10d633ac, 0x6759acfe, 0x8faa629e, + 0x64ba66fc, 0x47f38283, 0xa686ae49, 0xd59cda99, 0x828c3a05, + 0x08ea2f6e, 0x7c7afb14, 0xaf3953c8, 0x2551c8e4, 0x9daa9e4f, + 0x5b53d279, 0xad6f1940, 0x1eff68d4, 0x96437cdb, 0x2775dbdd, + 0x4fe7a043, 0x985f83e4 }, + { 0xeaf45294, 0x89603c16, 0xc24b5751, 0x70131160, 0x39d6b52d, + 0x4c112018, 0xed943340, 0x7079cf02, 0x74f41b68, 0x0c5b028b, + 0x9c8ac1e1, 0x3dc3f076, 0xf8b24f0e, 0x5ac5eea3, 0xe34c5c22, + 0xee6684ba, 0x9abc452a, 0xa5259e63, 0xe9df45cc, 0xb07d2cd1, + 0x1a443cfa, 0x07019c93, 0x92c003b3, 0x68fddaa9, 0x0d8cbc2e, + 0x2d9f179c, 0x1e781ca7, 0xbbf15a6f, 0x50dcc799, 0x54d779d5, + 0x0fe962f1, 0x0c88e540 }, + { 0xe8f44357, 0x84f71a6a, 0x3a3cab6a, 0xf75b4bf6, 0x5aebc680, + 0x334c9d9e, 0x8a753ef2, 0xcecaf084, 0x075e3c8e, 0xe28014c1, + 0xf74f8d3a, 0xbb9d5a38, 0xb80e32ae, 0x75988464, 0xf2bc3792, + 0x7b328e6f, 0xeed0e197, 0xebbb1faf, 0x5a33065a, 0x674eac95, + 0x922dbce8, 0x8c19fd8f, 0x987b907a, 0x8c17ae85, 0x3b3a2cd7, + 0x89f33627, 0xfa87772f, 0xebaea019, 0x3a25ced6, 0x4e5de499, + 0xaf110715, 0x8e2560b8 }, + { 0x3141aba6, 0x56d3746c, 0xbab2cf9e, 0x45a1079f, 0x9cdd27c7, + 0xb6382831, 0x9dfd950e, 0x22237632, 0x3a9408ff, 0x1e0b15cd, + 0xb1160118, 0x49a80200, 0xa383bba7, 0x2719db5d, 0x651046d5, + 0x6078340a, 0x97523b1f, 0x8929d4de, 0x8e0a28ab, 0x4040345c, + 0x0adf09c7, 0x61275ac2, 0x2331d611, 0xb41ab265, 0x5391ca50, + 0x230cc77c, 0x8f922315, 0x88be0c92, 0x92fd9a29, 0xfef3d92b, + 0x8324f2e5, 0x59005f22 }, + { 0x3c4c1c74, 0x6bb1750c, 0xe966fb79, 0xbe73aac0, 0x66c5973f, + 0x85a75d92, 0x3a8656b6, 0x8c97f932, 0x50446cde, 0x2b7043b1, + 0x3ff3897f, 0x548916f7, 0xb18b72b2, 0x913dd01c, 0x488c0de6, + 0xd0a751f1, 0x8558ca58, 0x19175714, 0x44a663da, 0x97714301, + 0xb0e08618, 0x2df190ac, 0xf39ead9c, 0x0080fc0c, 0x17382da1, + 0x0085ac6e, 0x3262a338, 0xe9791851, 0xb43bae8d, 0xe4495936, + 0xd783df6e, 0x57a78e26 }, + { 0x40dbddd8, 0x161b346f, 0x9410c3ac, 0x2b49a927, 0x1886cf3b, + 0x8c542783, 0x33b93deb, 0x72df3232, 0x40df579d, 0x9c8d59f5, + 0xc20ef500, 0xe5d7a67d, 0x67f08643, 0xc46b3918, 0xad96adc3, + 0xecfa2445, 0x0c4544d0, 0x658f589b, 0xe08417d7, 0xe6ec9301, + 0xc454e288, 0x6ca5ef6a, 0xac0f462d, 0x4191048f, 0x08d8a036, + 0x852407d8, 0xf6d35b7e, 0xb4c533a7, 0x8f6ada87, 0x3251e412, + 0x81c472e8, 0x1ca370c5 }, + { 0xa801b68a, 0x94bd5171, 0xfd1998b3, 0x7312879c, 0x41163202, + 0x4905aabf, 0xf5b01fdb, 0xb5fe87f4, 0x9cda128b, 0x78de523a, + 0xc7bd31f7, 0x0bf161a1, 0x23904c35, 0xb5decfd0, 0xe188f12d, + 0x224b2882, 0xf99dae74, 0x0dd2801d, 0x08cd1cd2, 0xcad467b5, + 0xc0867e39, 0x6c311c3d, 0x2b425072, 0x71a11720, 0x2efd9003, + 0x83bf464e, 0x1dbd3b03, 0x53d0448a, 0xe6265baa, 0x32db52f4, + 0x4c33ac79, 0x2584b34c }, + { 0x2aeec688, 0x3cb86389, 0x45fbe523, 0xa5e740ba, 0xfd60b5f8, + 0x422e71f7, 0x4874913d, 0x455d185c, 0xfa17d80d, 0x04c2bb36, + 0xac054524, 0x3f271854, 0xa8b9a657, 0x76dd3045, 0x62ee7cc8, + 0x2e42c3e1, 0x4df6c7d0, 0x00266706, 0xdc7cb488, 0x5927dd51, + 0x187897e0, 0x6b3faabe, 0xf2d5737c, 0xfe6ad22e, 0xff51a9ff, + 0xafb60269, 0x69807baa, 0xe1c83545, 0x951ca49a, 0xacddb6ff, + 0x3f9ab085, 0x7e811374 }, + { 0x830a88b1, 0xad722a8b, 0xce1117e1, 0x91918ea8, 0x0409b47d, + 0x3e02d0b8, 0x6c46d1d3, 0xb53812d3, 0xe589669c, 0x2fd09db0, + 0x15b0cd5e, 0x9845cd06, 0x2386c453, 0x0c1c155a, 0xf5ff43cb, + 0xda774de5, 0xe391c0cd, 0xbb076b98, 0x5004f286, 0x97d71eff, + 0xaeec0bfe, 0x23e0b46c, 0x32a1ad94, 0xe4538667, 0x396da422, + 0xfe0c9f81, 0x63db2bfe, 0x6376c1a2, 0xba56fa91, 0x001c7918, + 0xdf8485a6, 0x436b8c64 }, + { 0x8ab764bc, 0x88117e9d, 0xa077df84, 0xdfa61e94, 0x0c18eebd, + 0x5a7765d3, 0xfc9451dc, 0x548916af, 0x071a347a, 0x01a52e33, + 0xb23b41df, 0x633b95de, 0x43c8c286, 0xdd7d68c9, 0x18d97068, + 0xe4f9d41e, 0x8c92799d, 0x79908b90, 0xd47394a3, 0xe614148e, + 0xcd51e53f, 0xe5018517, 0x0243dcb6, 0x5060075e, 0x17954405, + 0xe5dcde62, 0x537da5ff, 0x6f7c90e1, 0x0768cb66, 0x1df7aae4, + 0x6dbe95e1, 0x5266ca9e }, + { 0x1386b3db, 0x84ddee6d, 0x7c38e540, 0xf9e4af5a, 0xeb04f49d, + 0xb3418440, 0xfde5a4fd, 0x2138a1e8, 0x30257cfc, 0x3e6e6924, + 0x19fd70c1, 0x3519c6e3, 0x86c31ff0, 0x8f34e174, 0x940ce1e8, + 0xf1e298fd, 0x14960d7c, 0x6fb8cb1d, 0x2b2f3bff, 0x207c1347, + 0x146ef8ff, 0x899a20b4, 0x7bd3e220, 0x7dec362b, 0x626bea27, + 0xa975044e, 0x4fb4cb67, 0x0f32b449, 0x1fc6703a, 0xc17a0920, + 0x9cd84a2b, 0x41f325b9 }, + { 0xce2843a4, 0x312ed513, 0x00728afc, 0xe748498e, 0x4d864ce5, + 0xa8ef2822, 0xa620083b, 0x34064704, 0x4bed338d, 0x5905e1d9, + 0x063e7b38, 0x2a578cb5, 0x289e7bb9, 0x98276d96, 0xf17b7341, + 0xdfe2dc47, 0x1dac8944, 0x5923521f, 0x23400aa7, 0x3db6d28d, + 0xa761ba43, 0xc647705e, 0x9bfd07dd, 0x8947ba6d, 0x242ca8fd, + 0x00f2e3ac, 0xeb8c3468, 0x49ef4670, 0xd9aa18fd, 0x7db3d37b, + 0xe58cea9e, 0x56b30fb6 }, + { 0xcd80a428, 0x07ecdcaa, 0x8732c891, 0x7af922dc, 0x3ada441f, + 0x20d88798, 0x924b008a, 0x3bed9a44, 0xb2e81c3a, 0x2123533c, + 0x65f807d3, 0xc34e4075, 0x1f2faecb, 0x0bfaefa5, 0xade8a88d, + 0x78b634a5, 0x94392a91, 0xc4e0b7f8, 0x90bb1cd8, 0x30922377, + 0xf87204ae, 0xdea9b4fa, 0x85d3cd83, 0x3edf81f5, 0xc6523a79, + 0x58f88c51, 0x17c0d969, 0xe472fb8b, 0xdccf7f07, 0x899081e5, + 0x58bdd146, 0x1353cc57 }, + { 0x39bf6e18, 0x28a56497, 0x649b89c7, 0x59e8b5a2, 0xdce8b8e7, + 0x8d9434a0, 0x2047040c, 0xd935bf51, 0x6a7b8e82, 0x2ab3a164, + 0x27f81294, 0xf1583ed6, 0x72d67297, 0x8416a7e0, 0xcd39e42b, + 0x49685d86, 0x958ddbad, 0x8a797fc7, 0x155ce6de, 0xa558f928, + 0xf8a36235, 0x75f4e570, 0x52877ae5, 0xbc69cfc0, 0xa6b16ebd, + 0x8f4193a9, 0xbb1cc1f1, 0x8d1df43c, 0x5a21e789, 0x723a830e, + 0xf451df58, 0x3ec2185d }, + { 0x1f0bc2d7, 0xb9d4c7d7, 0x6e51d412, 0x6982c6cc, 0xa09f80f6, + 0x92e02d93, 0x047ae09c, 0xb7dd2d25, 0x37f351f9, 0x3503149f, + 0xc77850be, 0x69d49ce1, 0x12f0d2c8, 0x60242acb, 0x7bc28b9d, + 0xba188c56, 0x06bc0550, 0x8e406121, 0x8d7d4329, 0xb0d84b1f, + 0xd38951e0, 0xb4a67ae7, 0x8bc97607, 0xb527c57b, 0x5497aa72, + 0xbc93c5f3, 0x39bdd666, 0x5f1de8cc, 0xe9d447a3, 0x3087dc5c, + 0xa211abe5, 0x89b356b6 }, + { 0xdfdcc837, 0xed6db0af, 0xa871b7a9, 0x0fb80baa, 0x1c1d4b72, + 0x413abfc9, 0xadac9e5c, 0xf5b56bf7, 0x8b8657a3, 0x5664a2da, + 0x0e41d94e, 0x11b04f72, 0x37433658, 0x63e11d26, 0xf426daea, + 0xee628ece, 0xcb162dc2, 0x011619c9, 0x87648643, 0x9cf5817f, + 0x5584bc86, 0xe1bb9702, 0x00bf7928, 0x2cc27cef, 0xdc60eee5, + 0x4ef3a80e, 0x87adc2f9, 0x7e1202be, 0x8a0d4f52, 0x656f18e0, + 0x57c5d126, 0x39c4f10d }, + { 0xe88aecd3, 0xb3a9b68c, 0xa518aa9d, 0x555b0918, 0x4bd4ee54, + 0xedc1cdad, 0x02068d84, 0x79b68b67, 0x811ac72d, 0x7dac80d0, + 0xa81a0a78, 0x6d1e6d35, 0x3bd16283, 0xc841e9ea, 0x894c4444, + 0xa7bc1775, 0xf1aa1202, 0xf2b63725, 0xc7d4c556, 0xbec7767e, + 0xd46ff51b, 0x2817ebb3, 0x73f7e339, 0xfde5be8d, 0x5aed24c4, + 0x44c6c977, 0xb6e579cf, 0x0b9a1707, 0x9069fbcc, 0xcff16478, + 0x49152b00, 0x414b542d }, + { 0x606e173b, 0x33c31e58, 0x90e6713a, 0x5b7f4e1b, 0xdebb20af, + 0x425fb512, 0x05120e70, 0xc788c617, 0x9013e4ec, 0x3ef05602, + 0x81c6e6d7, 0x9f9d35ac, 0x9450690a, 0xe131e88f, 0x44af082e, + 0x708f9b32, 0x1ba2aea9, 0xb2e4d66c, 0x740db29c, 0xaf1f4a6e, + 0xd1843007, 0x74ab9248, 0xed556a6c, 0x13338ef8, 0x270d17a6, + 0xf48e623e, 0x9608f5bf, 0x3c7362fa, 0x444e8515, 0x43977874, + 0xe00b8b2a, 0x52678d6a }, + { 0xdf36aeb4, 0x5dff1c59, 0xa92bc0ab, 0x52d6653c, 0x927a5f81, + 0x0e03f496, 0x2dfd491f, 0x8509d414, 0xa571f89b, 0x258c2c52, + 0x93334485, 0x2bd61804, 0x3f7d9e09, 0x1a33e94f, 0x2c1bf906, + 0xfab418d3, 0x5aa5695c, 0xf39c490e, 0xf6d2d7ff, 0x0e41196e, + 0x0f7948a9, 0x3ecd4075, 0xd3053b4f, 0x4b58f9b2, 0x5d9974c9, + 0xb8ee842a, 0xbf22f682, 0x23a59c1d, 0xc8efcea6, 0x045ac614, + 0xc10ceedd, 0x7040ba5b }, + { 0x515a1a96, 0x2c364f81, 0x184327e0, 0x31a63503, 0x1ad93d4f, + 0x0a096650, 0x273b6173, 0x9d7694f1, 0xd2cda9d2, 0x8886d876, + 0x2814c177, 0x1e01a742, 0x8667696b, 0x3492276b, 0x5b25f006, + 0x2fd4f0c6, 0xfb294c4a, 0x6527349f, 0xde1d336f, 0xc1fe0d8a, + 0xe7e3860e, 0xaf9a23e8, 0xb774c31e, 0x97d2b721, 0x4365784a, + 0xfac3e582, 0x70f4eaa3, 0xff2dff4e, 0xfe873248, 0x3d281e1a, + 0x0bd1c9c1, 0x9043a6d6 }, + { 0x766c7937, 0x1511a0fe, 0xabbc3be3, 0x1b2ded5c, 0xe00888ac, + 0x2ac160cc, 0x616200f3, 0x928754bd, 0x34a2ea06, 0xb801c83d, + 0x9cbe106f, 0x8ad7a03a, 0xcedfcd94, 0x996b0822, 0xe4069880, + 0xc3c3463a, 0xf597f663, 0xfb12ea4d, 0x40c92af9, 0x2c8d3834, + 0x4e8da154, 0x79bc85c6, 0xdb4e801a, 0x95771fa2, 0x1e3579b2, + 0x7bd2c138, 0xffaad078, 0xe45c75df, 0xb73eac46, 0xb0760a3c, + 0x3a125f35, 0x26362b48 }, + { 0xeefc3e89, 0x25c68d28, 0x69e9ee71, 0x2d0ee877, 0xaf5e4b75, + 0x8b07bb86, 0xcb86b333, 0xdb709072, 0xff552bac, 0xfd3d20ea, + 0x4c0da1e9, 0xa5eeb2b1, 0x44f97145, 0x391f688a, 0x1e06d485, + 0x21fbd310, 0xbea9cd49, 0x45e4f2a5, 0xa7bf21da, 0x7b60d464, + 0x054d5471, 0x193f88c8, 0xbee0f2e9, 0x5ace53d1, 0xc1439273, + 0x92c26563, 0x96c6b5ee, 0x9c86e0b2, 0x09ff59ba, 0x452fe231, + 0x555c935e, 0x2e952b20 }, + { 0xd75f886e, 0x2a846bca, 0xd43dfc58, 0xe68a5dbe, 0x007b1b86, + 0x103e45b6, 0x355ff2b5, 0x580e2ec9, 0xa263ecc9, 0xbc702f26, + 0x181e5e33, 0x2835b386, 0x6c122076, 0x025113ec, 0x7fbd856d, + 0xa5c26e3a, 0x9d6ebcb1, 0x8ef83fb3, 0xa44d2fa8, 0x7aaa53f2, + 0x53b1fa97, 0x7c14ef33, 0x17559a30, 0xff604a11, 0xb09377e0, + 0x2bcd96b0, 0xdb2f0273, 0xa5c14896, 0xeb53ef06, 0x1c0a84c9, + 0x30378e4b, 0x1236d017 }, + { 0xc084373b, 0xd7481c8f, 0x646097ae, 0x29ae4768, 0x613bc34b, + 0x1300dfa0, 0x934bc2b0, 0x3712714c, 0x0e2be7e2, 0x86524629, + 0xed010800, 0x554fbb9f, 0x42314576, 0xf0ec0b38, 0x330a3282, + 0x65baf594, 0x706ef817, 0x3bdde1a8, 0xba7530e9, 0x7d2c727d, + 0x74cc95cb, 0xbb0c5d66, 0x2438906d, 0xb3fcd365, 0xd14658f3, + 0x19881941, 0x6c97f0e9, 0xe616f555, 0x4b9ec7ea, 0x353c2d85, + 0x620cb56e, 0x02a48014 }, + { 0x506ccd38, 0x11d6d23d, 0x9059baa6, 0x229a1c54, 0x69d011c5, + 0x717c9c27, 0xd828937d, 0xe87e1b46, 0x83835083, 0xf5d63bbb, + 0xaadac258, 0xf0a7b427, 0x9f154d1f, 0x99ab26bd, 0x8ec955fd, + 0xdec0ffbf, 0x49fcb880, 0xee957c67, 0x1e0114de, 0x32395dee, + 0x369f46c7, 0x192a64b7, 0x91eb2599, 0x43044660, 0xa2e8c3da, + 0xbe2da887, 0xc3556d18, 0xa44e2c25, 0xb55f75f3, 0x31390414, + 0x8f217fe0, 0x1d8bde6f }, + { 0xa2028924, 0x03cd39f8, 0xb06ecb9f, 0x6e54f19c, 0xd6f05846, + 0x862bbcb7, 0x5a060776, 0xdbe06716, 0xb10fec10, 0x9397c97a, + 0x6f1bb65c, 0xf4213826, 0xa672ba38, 0x414deccb, 0xf88b05e6, + 0x594d4d43, 0xac94d4d1, 0x7993f57a, 0xbfb17638, 0x74fc2a6a, + 0xb6fc655a, 0xd8196b5b, 0xee8d2139, 0xdc375c84, 0x360d3a26, + 0xb9b00a02, 0xdeb93b87, 0xb36ed35c, 0xcc83209e, 0xf565b28b, + 0xc61013c1, 0x349c6943 }, + { 0x4de6c88a, 0xd1b39444, 0x4700207e, 0xd5c2c471, 0x21c2b780, + 0xb6f458a2, 0x0850993e, 0x749f7564, 0xbaef0c18, 0x400ba579, + 0x737c70f0, 0x2d742938, 0x21467ebf, 0xc5a8e2ec, 0x5337f453, + 0x243a666e, 0xed0bd50a, 0xc991f1c7, 0xf4bd1f91, 0x3a7f3e90, + 0x5f0e129b, 0x96089e8a, 0x07389635, 0xd0d3a177, 0x27182ac9, + 0x9cf842d5, 0x0817c5c2, 0x21195299, 0x87255769, 0xa32f327e, + 0x89c2d8fa, 0x056587ab }, + { 0x1ce4733d, 0x008562ed, 0x98e51444, 0x5faff7cb, 0xa9ab46b9, + 0x5f03021f, 0xb61a8c13, 0x89494c5e, 0x36b35976, 0x57c95036, + 0x2ac2d2f6, 0x6be84c8f, 0x9bd2703e, 0x0e5b34d8, 0x7e872abb, + 0xc4ad918f, 0xc4052ee1, 0xc2a89e9f, 0x3190b51e, 0xc2caee3f, + 0x6fff254f, 0x58fd1437, 0x883e0972, 0x6f3c0d68, 0x0fb15438, + 0x63d0a0e9, 0xf6caae00, 0xc438764b, 0x3f1d0f6c, 0x815f1565, + 0xb86cdbde, 0x1b87f2ed }, + { 0x2b0b15b1, 0x35792bbb, 0xce6ba779, 0xa3e4b5a7, 0xdd8f3779, + 0xfbacffd9, 0xc298d1ef, 0x005450bd, 0xc47031c6, 0x0e3f5556, + 0x95d68066, 0x0770f07a, 0x2d1052c2, 0xce3e84e0, 0x7aa8cc54, + 0xb050791e, 0xba3223a3, 0x4d621e73, 0x39632990, 0x87b9b94d, + 0x7eb8056d, 0x8df9cb47, 0xedfca0cc, 0xe2430de8, 0x9712a0ca, + 0x374bf416, 0x88848a99, 0xbe3f3c77, 0xc4a3e59e, 0xb22b87b1, + 0x3e95bc23, 0x8e0227c4 }, + { 0x3210964d, 0x000e22a8, 0xff056eeb, 0xdccd5df5, 0xdaf1ead7, + 0x02173a1f, 0x67cdcae3, 0xd02833e0, 0x8bdcc90c, 0x1cc574cb, + 0x3224b4f5, 0x86eca714, 0xbb3f8298, 0xd00e603a, 0x0c1a8deb, + 0xb98ece1b, 0x378c261d, 0x228a46e4, 0xa6165e5d, 0xc6f9dd0d, + 0x4b7ef0e2, 0xb3ae3899, 0xbda9f306, 0x3a3c16b3, 0x38a084db, + 0x5e9a26d3, 0x5394e950, 0x528e5993, 0x4ea206bc, 0x848ecb11, + 0x40545d6e, 0x14b15ab5 }, + { 0x664c59a2, 0x0f6d86c9, 0x60fd7aa5, 0x3dfe2be1, 0x9072cb8e, + 0x33f9b569, 0x8176a7e0, 0x5f2325d9, 0x4587080b, 0x79a0d4e7, + 0x0d5d4e05, 0xa4ee0def, 0xc87b28e1, 0xc0ad9ffa, 0x3f09b4ee, + 0xd6f18d2f, 0x292e9d87, 0xcc896ae7, 0x6094763c, 0xca88953d, + 0x18fbf9fa, 0xdbee97a8, 0x4b63d701, 0xdf20e0e9, 0x47ea722f, + 0xcbba6e30, 0x612b571f, 0xce57e1ca, 0x009a55f5, 0x1e16ac76, + 0xc4389e2e, 0x742bbed8 }, + { 0xc1dc2c73, 0x23ea86dc, 0xc1643abf, 0x4bbbfd5b, 0x24d8ca1f, + 0x07f8fa1f, 0x8cb5cac7, 0xde68a6e0, 0x54e66a7d, 0x7d54c64b, + 0xa9b7ad78, 0x789dba22, 0xe364ab94, 0x4d88d540, 0x1f72e011, + 0xc8c2e02d, 0x46e2a278, 0x4c826057, 0x4b187c7d, 0xe6c35bb3, + 0xeb8fe0c9, 0xed8b3dfe, 0x7d11e415, 0xb6bc34e8, 0xb865c7f9, + 0xb3908bbf, 0xe1ecc17c, 0x717d1ce6, 0xf7cdd69b, 0x151e3308, + 0xb5c94124, 0x97bd5a14 }, + { 0x81e82861, 0xe01c62fe, 0xdd42c40e, 0x703d4b6d, 0xe65e91e5, + 0x7e52e55b, 0x5abbbfdd, 0xb8b49374, 0xc72a45f4, 0xb4f15f52, + 0x550f29d8, 0xce8435a8, 0x582de75f, 0x9df76b9b, 0xa20c8b96, + 0x52e84c5f, 0x0a8a0af4, 0xaf77d2d1, 0xca6013c3, 0x0389bbd8, + 0x26f8305f, 0xb0d9b9ba, 0x0cec8b9a, 0xf053e848, 0xffabda18, + 0x4d63367a, 0xa6424c2a, 0x50f53be4, 0x864fba2e, 0xf892c58c, + 0x48cc5469, 0x317c6d31 }, + { 0x2cb7d42b, 0x0c3525b0, 0x310facae, 0x55240bc9, 0xff20408f, + 0x8d5d2022, 0xe0c10ea0, 0x6b01402f, 0x718eb23d, 0x7fbef68a, + 0x41252a19, 0xa0146b5a, 0x110e0d6e, 0x59afce48, 0x022de181, + 0xe9a1d27f, 0xdc3f49da, 0x6db96d16, 0xefbe4008, 0xfc1ae3f5, + 0xeccbc11c, 0xf9d70641, 0x525f8636, 0x49022279, 0xc2763c30, + 0x3769796a, 0x1d90630b, 0x9cc3483c, 0xee3d3f17, 0x451651f0, + 0x9da0b8fd, 0x6ae59739 }, + { 0xbff4d2ee, 0x57b13bc7, 0x30b173d8, 0x20754229, 0x0794936c, + 0xb6254bd5, 0x5efd55be, 0x1d5f232a, 0x4e0c3389, 0xc06f4a85, + 0x8e61f944, 0xcf2c5b59, 0xfd5f87b7, 0xc564861f, 0x5a2afa4c, + 0xee261fb1, 0x2d97a774, 0xb0ff7226, 0xd6cf007a, 0x1a89ae22, + 0xd346f214, 0x28880534, 0x97b6497e, 0x8fe73bff, 0xfa2afffc, + 0x8a8595b2, 0xf151a726, 0x9ef9cf3e, 0xe744b82b, 0xa84ee5f1, + 0xbc63fe72, 0x6649048d }, + { 0x1e8b760d, 0x91b7bb78, 0x25aadaa0, 0xd47b0bd8, 0xfab5226f, + 0x81493d9f, 0xbffc148e, 0x4a6dd226, 0xa29be3db, 0x5a032f8a, + 0x34b0ab0b, 0x318dbc70, 0x7d654868, 0xdcccbfb5, 0x9c581e46, + 0x8506ab37, 0x2830ece2, 0x09136a6e, 0xcf6c80c7, 0x48b79356, + 0xef6b1e86, 0xfa176377, 0x83f0f1c9, 0x2c9c1cc1, 0x16abeddd, + 0x96f0526d, 0xa93b0de4, 0x3e0e98e2, 0x0f13873a, 0x6f2d7ada, + 0xf3fa49ec, 0x4eb93b5c }, + { 0xe11fae32, 0xbd89f7e5, 0xc4023f51, 0xd13d74f5, 0x491c3f6f, + 0x1b0014df, 0x555279b7, 0x1d849a57, 0x05ba0068, 0xbb9e8897, + 0xc13ca2ca, 0x82222419, 0xfd33676f, 0xafbbb685, 0x75878a2a, + 0x931c3f52, 0xef3d5173, 0x12aeefef, 0xbd8a6878, 0x189a5cc8, + 0xd99f0c16, 0x82cffdb3, 0xa19d48b6, 0xbf565406, 0xe9c6c4e0, + 0x5605e223, 0x86804172, 0x53e781de, 0xc7001cc8, 0xcdf5c90b, + 0x7c043f68, 0x2b582d93 }, + { 0x81abc2ae, 0xa1165c82, 0xe2b69eca, 0xa73380f5, 0x07fff66f, + 0xc097b3d2, 0x54776506, 0x5d603826, 0xb57fa21c, 0xdcbac9f3, + 0xc98dbdd5, 0x78750db4, 0xd9eff32a, 0x85e21103, 0x2f11c41c, + 0xceed172c, 0x9e348c09, 0xa8e39264, 0x831eddfb, 0x71cb936b, + 0xf50864a3, 0x915c3d06, 0xe93acfcd, 0xfe8e33cd, 0xb3f2f7aa, + 0x4bee10d7, 0xeb7cee9a, 0xc1d8eb48, 0xfa574afd, 0x4fa49ce3, + 0x862db4c0, 0x78615109 }, + { 0x7ae72c21, 0x3fe3f480, 0xfd0f0da5, 0x631aa144, 0xf8c3a454, + 0xc76ee1e8, 0x51b4f1ab, 0x379ae094, 0xd7cdbb24, 0x2a3a4397, + 0x82bd5fcd, 0x7a14cffe, 0xf427ef5a, 0xbbe4ed12, 0x284d3ccf, + 0x9b0a43ee, 0x8eec6e1e, 0x57b78b93, 0x67b8e87b, 0x18d404e4, + 0x34374c20, 0x0c8adc05, 0x5428deb5, 0x64373605, 0xc3afa2cf, + 0xb4d80ec0, 0x3aa956f9, 0x6d51f93c, 0x84161c68, 0x9f9a28ab, + 0x6bc9c025, 0x540b6bb7 }, + { 0x321d315d, 0x04e1734c, 0xd86e05d0, 0x4ef56612, 0xbba8cd81, + 0xeafae145, 0xacdc789a, 0x1fb07a49, 0x5877570f, 0x6a21e9ad, + 0xb9bc53de, 0x2e4a837e, 0x1d6298eb, 0x436db293, 0xea362f45, + 0x43afbc78, 0xaabf6585, 0x2a973d97, 0x0c924d60, 0xdce7dabe, + 0x7cadf0e9, 0xf69d98f0, 0x75020538, 0xe0b505a1, 0x4461cd29, + 0x3db7d1a3, 0x5e20e818, 0xe1c28776, 0x52dd50f6, 0x2ca25867, + 0x92e0388c, 0x897cab14 }, + { 0x0d8bab8a, 0x59ed3813, 0xa438200a, 0xc11d364c, 0x40581415, + 0x0687bf2c, 0x7ac89674, 0x86ad0d3a, 0xb97411a0, 0x44928105, + 0xf383371c, 0x74984b11, 0x0d1a831e, 0x70d2ed84, 0x6c912fe0, + 0xd883628b, 0x14fa88d2, 0x44f8f7fb, 0xcf0ac93e, 0x564f2a4d, + 0xa6c24fa6, 0x82f629aa, 0xbf6cd949, 0xab906ba3, 0x20a5182d, + 0x2c822e67, 0x30eb93a5, 0x2ff47dac, 0xfff673aa, 0xdc62c4a4, + 0x476b0ec5, 0x64b00763 }, + { 0xb3c9a404, 0x1e3f533e, 0xb7ef9952, 0xb1db7f73, 0x6c253693, + 0xc7f13e29, 0x0738eed4, 0x7ce7f4c4, 0xce26cad0, 0xccfd3b33, + 0x01ec5cf1, 0xd8784935, 0xdc084e01, 0x3f8fc09d, 0xc39b5acf, + 0x217cab32, 0x9ef5551c, 0x42daf0bb, 0xe1217a95, 0xfbc76f56, + 0xc237002a, 0x80178b12, 0xb070a293, 0x0b52c39f, 0x576ca964, + 0xe3925153, 0x19d68e36, 0x25559424, 0x09e50e84, 0x291fb82c, + 0x6618ed8c, 0x7dd22ea6 }, + { 0x49cbb3bf, 0x7ffe844b, 0x5562fb25, 0xde0cc704, 0x9f5a845a, + 0x1e6ee537, 0xe51277fc, 0x956d7f26, 0x30635718, 0x2c75d4b9, + 0x96957f34, 0x39a14892, 0x82e5742b, 0x8cf4eb32, 0x83247b72, + 0x6b0d3ddd, 0x201a4237, 0x67a9f633, 0x1414a485, 0x416403c1, + 0xb6f6a916, 0x60afd447, 0xdac6f790, 0x95f94930, 0xbd3b9d82, + 0x685ff94b, 0x51cadf0f, 0x5c8f98fc, 0xb13b7489, 0x9559c88a, + 0x5f18fcc8, 0x31377c66 }, + { 0x7dcfb35f, 0x35c5de09, 0x01cc36f8, 0x2dccca9f, 0x7576cb63, + 0x7e93e85d, 0xf7b4b375, 0x0c2dd48a, 0xb09a19b5, 0x9d95cd4f, + 0x71bfe607, 0x752ed159, 0x2596dad2, 0x439880cf, 0x69e90a6f, + 0xe52efb53, 0x03d3e60a, 0x44097663, 0xa95070e0, 0xfcf364fa, + 0x05624dd2, 0xd8f993b6, 0x00d5e467, 0xb35a9824, 0x0c8f4524, + 0xe289d024, 0x648a0179, 0xef45423c, 0x587edabd, 0x3a5fd695, + 0xa11e5271, 0x3dacc50c }, + { 0x6499ae4c, 0xcb3e4f94, 0x7053c527, 0xa46dcbe1, 0xbe782e8a, + 0x807f5ce9, 0xd8481e45, 0xb6c64d28, 0xaa286fd0, 0xf35e4518, + 0xdf1cdb49, 0xf7b7b9ba, 0xaec23eaf, 0xf3fb6210, 0xb9bfd2fb, + 0x0a9ba385, 0x8807f3a0, 0xe51a0d53, 0xb17b2842, 0x7ab24404, + 0xf9dd9f0a, 0x6fd57687, 0xf3e9df64, 0xcd1efdb4, 0x60df194d, + 0x5dd2df7a, 0xe069df05, 0xbed3f2c3, 0x23248a31, 0x469b7561, + 0x694744f7, 0x866949e1 }, + { 0x3f4ab07a, 0x3a9a0da5, 0xf54a6fbf, 0x2cd6f333, 0xb23cf290, + 0x0c92e921, 0x848e3d58, 0xc9581c3e, 0xd3b218ab, 0x93af1fbd, + 0x066cb4d7, 0x38598ea1, 0x990c03a0, 0x5001394e, 0x7d0877b5, + 0x3b664b1e, 0xd74c7091, 0xd79db1bb, 0x4e2d5dd0, 0x852d4435, + 0x3329db82, 0x0d2b841b, 0x7b96d480, 0xfa844eb0, 0xc295dc46, + 0x37a50569, 0x94f7ec4e, 0xc2d38373, 0x5b083177, 0xdc3884ff, + 0x8b1fa598, 0x574352b8 }, + { 0x0d5d7ce9, 0xed2193f7, 0x0b487eaf, 0x3c19fd26, 0x7be65fd0, + 0x7c44ab59, 0x78270d56, 0xdd9da860, 0xbaa70198, 0x8a84ec00, + 0x285985df, 0x2ec27e49, 0xde2028d8, 0x996ccaf0, 0x61c2201d, + 0x4e7648c7, 0x091c19eb, 0xa96335bc, 0xf0d6782b, 0x253a3a69, + 0xd2946493, 0x3f204340, 0x099f6873, 0x444521a1, 0x6996011a, + 0x5fcbcc09, 0xf853a94e, 0x3884d5d8, 0xd3b6a3a1, 0x2418c624, + 0x06ae3c4f, 0x3e431af2 }, + { 0x83d381f1, 0xf967d939, 0xd0c033c3, 0x36501aae, 0x54410768, + 0xbf3af4d0, 0x5093a6d3, 0xa86d1598, 0xd92f2900, 0x43ae0741, + 0x36f0b755, 0xfeb2afa6, 0xaa456d6f, 0xd090a6a3, 0xaefdb646, + 0x336a4fda, 0x1a942f7d, 0xfd1bfe44, 0x851ee41e, 0x7fc2a3ed, + 0x11e935c5, 0x4f1c9686, 0x53bbb343, 0xcd577666, 0xad896c2a, + 0xf26931ba, 0x86bbfa41, 0x8a0fbbd1, 0xa203cef1, 0x1c3d7d82, + 0xe2664d35, 0x6dad3f15 }, + { 0x12ec35a1, 0xd1940b7d, 0xe7dfb128, 0x6219c5b6, 0xf13321d5, + 0x2cc278c6, 0x33c58eb6, 0x5e76904a, 0xd9903c43, 0x15090f55, + 0xc3d96a19, 0x061bc926, 0x8c0acba7, 0x974a9f03, 0x7198b21b, + 0x7a414021, 0xf8958c6f, 0xb069599d, 0xbebd0129, 0x517f2f1d, + 0xdf3a8dc3, 0x1109a613, 0x672375c5, 0x08e58448, 0x9383d2d3, + 0x56590ba4, 0x0bff837c, 0xfc3ee7c6, 0x27d2d55f, 0xc87a5390, + 0x5f517a3f, 0x2438e9d4 }, + { 0x8815af3c, 0xc4a45308, 0xf3c9bed5, 0xe55f1a32, 0x97b65ddf, + 0xaef1cdc9, 0x12e51eb5, 0x61c61d94, 0xe63f2490, 0xbd0dac54, + 0xd0b3e231, 0x6f14429c, 0xf1da6010, 0xf737c3c2, 0x6bbc4fb1, + 0x7150e04b, 0x1be281cb, 0x205b4c89, 0xd7701f5b, 0xf1b4633c, + 0x2a513490, 0x8b33ef46, 0x68f1f7f2, 0xddb47c73, 0xbd416b67, + 0xf4ada511, 0xff795bb3, 0x9d2a97cd, 0x96200e67, 0x00a8b7b2, + 0xafe30e01, 0x13f39011 }, + { 0x7bd0c827, 0x3dd296ef, 0x4a29ff46, 0x506110f3, 0x1c9a515a, + 0xf8793068, 0x268bca77, 0xde8d8045, 0x998045df, 0xcbb83024, + 0x68c0e584, 0x3f90d710, 0x263b6062, 0x2a838ca8, 0x535c5d0b, + 0x293bb5e7, 0x56415110, 0xceea99d5, 0x1bbda005, 0xfe311ad0, + 0xa4d8d018, 0x2497e0bf, 0x1cf2b866, 0x33dd77a0, 0xd8c4ba8b, + 0xbc075b73, 0x722b7bc9, 0x298466d4, 0xcbda1b0b, 0x17a7ce24, + 0x680703b6, 0x458d4b6b }, + { 0x4d54d8b2, 0x8a26a20e, 0x4d320a0d, 0x05a5696e, 0xf994f700, + 0x698b5858, 0x2f6549a8, 0x7a4adc3c, 0x3694d00d, 0x1812e819, + 0x730402bd, 0x46b9b000, 0xa1b36410, 0xe10a1449, 0x99230220, + 0xeae95ea5, 0x1b4820c3, 0x3efc2e9b, 0x85c9eb8a, 0xfe5b5cb5, + 0x97847064, 0x21ae0319, 0x8f27d49f, 0x68ef0b70, 0x2f72556b, + 0x3259ef18, 0x624db01a, 0x00ae0457, 0x5668f95c, 0x628e3b06, + 0xb6fbbf91, 0x5f13f5fa }, + { 0x3a9b0dc6, 0x7c6ed9ae, 0x6f883ec8, 0xaea1bde9, 0xea8b3677, + 0xea66bf88, 0x9a66e3ab, 0xdefa6abc, 0x68217ffd, 0xc4d3317b, + 0x290df05c, 0xf741c8f2, 0x7d11674e, 0x1f0fdf17, 0xc35989ca, + 0xfdf0ece7, 0x6b9c482d, 0x0eed92df, 0x55bf1ca7, 0x73713e66, + 0x25cec99c, 0x90acb290, 0xe803e69c, 0x37c9e3a2, 0x17713a1a, + 0x7c0a3c53, 0x6f5a174d, 0x350dc565, 0x05f802f6, 0x11625a44, + 0xa37ba4a2, 0x2196495d }, + { 0x13142680, 0x00cb2fd3, 0x65d14cf4, 0xab9e91d7, 0xdfe2669e, + 0xc6a0ceab, 0x0ae22bc5, 0xbeefce58, 0xcb6ec250, 0x3c2b7986, + 0xd738f1ff, 0x84adb1a2, 0x516ec8ec, 0x9709bc28, 0x8e8f7db5, + 0xf3693129, 0x95b197f9, 0xc48efc6b, 0x9aaaa404, 0x9ff10952, + 0x144154b0, 0x2c3c8cbd, 0x427f3435, 0x33ef7bc3, 0xd21897c1, + 0x04a17940, 0x6ce548a0, 0x5aa0c47d, 0x3d56fa62, 0x2971cea7, + 0x04475f08, 0x93ad0eb0 }, + { 0x988a9963, 0x7a0b6967, 0x6515e8dd, 0x61e477f7, 0x3b6b50f2, + 0x6274e386, 0xd33922de, 0x63a9b8d5, 0x687a5b3d, 0x3c38d3fb, + 0x1302e323, 0x18f6f09c, 0xe02fcccf, 0x254c05c3, 0x26e662f7, + 0xc04ed0b7, 0x143fe079, 0x1d5646b8, 0xc9016c8c, 0xef8a9448, + 0xf823d797, 0xe5674c4b, 0xbccde451, 0x0586f72f, 0x4417eade, + 0xc5fc88d5, 0x576e588d, 0x2b952209, 0x5844d1f9, 0x4408dd42, + 0xea41c034, 0x73f8c3f0 }, + { 0x5df763dd, 0x89534fc8, 0x3ac71836, 0x3b1427f3, 0x6e8f15a0, + 0x0db5be17, 0xcb20888e, 0x1d390944, 0x857caea6, 0x7804c9ad, + 0x519f7bf3, 0xaa584428, 0x293aa8cf, 0x626eecf1, 0xea36a015, + 0x749e0d98, 0x3321edcd, 0xefff6dae, 0x28b791cc, 0x963deea6, + 0x2d16e361, 0xa14e0552, 0xb15ae206, 0xa2e058fc, 0xfca325e4, + 0x0f268745, 0x21341a8a, 0x7cf9d407, 0x7caa51b8, 0xdfed25d9, + 0xadbedd75, 0x0108ae39 }, + { 0xa9e88f63, 0x54d178f3, 0xab0c7325, 0xaa05b11e, 0xe261d8a6, + 0x773a53e6, 0x8d0b91c8, 0x24db7dae, 0xe9bb004d, 0xde10b073, + 0x54e3090b, 0xfc8befe7, 0x0cc69c89, 0x16af0599, 0x9d59511a, + 0xddc83803, 0x46c5dafc, 0xc3f65b99, 0x1ee0a599, 0xfbbe4be8, + 0xfb3a9b17, 0x88891e36, 0x445dad00, 0x0c9aad75, 0xd5097e1f, + 0xdffc46ab, 0xac85a4e1, 0x8848089b, 0xa0c45233, 0x348bb42f, + 0xeb13c1df, 0x807c06d8 }, + { 0x98ee0ef6, 0x00a969ec, 0x8bb7b7af, 0xba9d5483, 0xa02f8fdb, + 0x24484c92, 0x8b70557c, 0x7bdb201a, 0x60ad1af2, 0xe59343e4, + 0x998c95fb, 0x53a9a942, 0xda861d3b, 0x974db3de, 0xed399c0e, + 0xce1525c9, 0xf72109bd, 0x89b56881, 0x998211a4, 0x08ff7d15, + 0xef0f275a, 0x5df76b3a, 0xfa2f358b, 0x93f180f7, 0xc39b0634, + 0xaac4ffcf, 0x17583b53, 0x2692c626, 0xb55399fc, 0xb2fdfa36, + 0x99607a61, 0x16424c6c }, + { 0xdd2744a9, 0x5dd65c55, 0xfe3af418, 0x2544c1c2, 0xefe8b089, + 0x32c82e99, 0xa9df691a, 0x30b7ab25, 0x9be99674, 0x98384550, + 0xcaf2d122, 0xbcecd258, 0xbcc77272, 0x88ae4098, 0x4b8efa0c, + 0xd4396141, 0xed64d12c, 0x44ff67b9, 0x2e7f3404, 0xa9e655e4, + 0x45b0e9eb, 0x3d16fc45, 0xf03ded28, 0x474a3e14, 0xacccb85c, + 0xa3c9adff, 0x7253a51b, 0x3dfe6bc1, 0xfb5831b1, 0xdddaf4b9, + 0xa4f4478a, 0x5544e602 }, + { 0xbaa80b4f, 0x897c5313, 0x63bdc8ef, 0x0122716f, 0x7b42c5a8, + 0xae2742db, 0x0883308c, 0xe9d9e1e9, 0x2d341ab1, 0x352c8c3f, + 0xed945870, 0x163d0500, 0xc290d9d8, 0x8349dd73, 0x1f6c7d29, + 0x2053c5e0, 0xcb42033c, 0x83107446, 0x09d09af1, 0x76c88bd2, + 0xb2794681, 0xd0f70e6e, 0x19b1b540, 0x720b59de, 0x22994b43, + 0x80b7ecdc, 0x2dec53cf, 0xc1a4cdce, 0x1ed60f42, 0xdd7d3edd, + 0xe241d261, 0x5735995c }, + { 0xa0237056, 0xdc4ba3fb, 0x33ab3388, 0x6856c164, 0x271ec612, + 0xc01eebbd, 0xe3031bec, 0xabdeb033, 0x6118a1f5, 0x4eee4419, + 0x5b600f33, 0xec497421, 0x08868773, 0x1b7185cf, 0x7c1b7dfd, + 0x7b0c46cd, 0x4a4c5e89, 0xd143b2da, 0xbb1ff94d, 0xdb9a5984, + 0xc9cf3465, 0xac3904e4, 0xeace64c9, 0xf8729bc0, 0x768ad99a, + 0x5cc22821, 0x8a9540c2, 0xbbd3b081, 0x049a6917, 0xe468ed5f, + 0x3ec45ef0, 0x885486df }, + { 0x4bdff464, 0x6a942c93, 0x25a7b451, 0x3db2719f, 0x325be324, + 0xccb0070b, 0x19fe3339, 0x2055a31b, 0x241ee8ff, 0xaca69ae8, + 0x55ef8def, 0x7607dd08, 0x1a1b73c6, 0x9e24960f, 0x71d36810, + 0xbcb0e8a2, 0x6885e6b9, 0x29e11aa2, 0x185eae19, 0x98b5d0ab, + 0x0f81f91c, 0x1a0b96e4, 0x994fc503, 0x4d0e8bcf, 0xf119d6e0, + 0x33d81697, 0xaaa4ce0c, 0x29083287, 0xc91ff9d7, 0xc5dd4d3e, + 0xd4ab962d, 0x31cecfe8 }, + { 0xfc8b21e8, 0x437bfd9a, 0xb19436df, 0xe5dd32b3, 0x921c36a0, + 0xfe5902d4, 0xa3d0fa90, 0x8e9de84d, 0x5bb523bd, 0x9663e6ad, + 0xaecd6975, 0x9800a23f, 0xb4fbb59c, 0x1009c0d9, 0xc9d20ff1, + 0x839aa7bd, 0xecd6fa3d, 0xf502f66d, 0xc5516ca9, 0x480ed4fb, + 0x6c742ac4, 0x65ffa5f6, 0xff3252f8, 0x2b7c7945, 0x75d9cb3d, + 0x72fefc05, 0xd6d6f1d2, 0x11b0863b, 0x9a6a4ec3, 0x5d8f3cf0, + 0xda2547b3, 0x6961b46a }, + { 0xcb35e2ac, 0xd07b587e, 0x57af14d9, 0x1ed5546b, 0xdb28a04c, + 0xeca17a5b, 0x709d54f0, 0xa1f91d44, 0x9c6f400e, 0xa6e719fd, + 0xfb8ce190, 0x4e4b88ed, 0x246e3fd2, 0xf9781edd, 0xb655af5d, + 0xd67120e6, 0x93413ca7, 0xda782d1d, 0x9707fa21, 0x697e20a2, + 0x54e84123, 0x1eb51f32, 0x36051f9f, 0x2e254d9e, 0x73ce5be9, + 0xddaec42b, 0xcd3f794f, 0x89a9a32e, 0x0781aad9, 0x1964e22f, + 0x53755212, 0x6a63a90c }, + { 0x3d7acbbb, 0x76554e00, 0xb74f6108, 0x2c01668a, 0x388c519b, + 0xe4a29672, 0x3eb94d4f, 0x01667714, 0x0cd6d2f6, 0x086a3cdf, + 0x7b370f7f, 0xf8658021, 0x5a4d3e7c, 0x658880c1, 0x5ba3f4a1, + 0xd6ed5816, 0x5ca471dd, 0xabcc7813, 0xe844a576, 0x809bf074, + 0x6ea502ea, 0xa53a81b3, 0x0e021ed3, 0xc20b9307, 0x8617f165, + 0x8c27f892, 0x8235cd0b, 0xa5476446, 0x82552961, 0xffc89ffd, + 0xd151d90e, 0x51ed4a22 }, + { 0x449701b4, 0x37d6963a, 0xbb27caf2, 0xea8d91a3, 0xb572965f, + 0x3ef9be15, 0xdb50bf7d, 0x75a7a055, 0xce643b9b, 0xfd67480e, + 0x6ceb5d5e, 0xf2a60d2d, 0x5ed7c897, 0x68fc320c, 0x28ce685f, + 0x41c53cf6, 0x7106615e, 0x0e29711f, 0x23500ecc, 0x7a872138, + 0x6c29fe48, 0xaf0a9260, 0xe1ef9712, 0x93df3f2a, 0xd2d169bf, + 0x0d5f6fb1, 0x74a9793c, 0xeb7afe26, 0xe9f49256, 0x4173d94a, + 0x2b8b5ce5, 0x2d6951bc }, + { 0x904e222e, 0xdd007d9f, 0x86f4e109, 0x333f248f, 0x8f429eee, + 0xd4994e8b, 0xcfc77518, 0x29573415, 0x0b0f42f1, 0x6e7fea3a, + 0xc2743519, 0xc795cb7d, 0x711e71a0, 0x820a8f66, 0x2b874f55, + 0x83d95d9c, 0xe70e1627, 0xd4b64d78, 0x8b92a742, 0x924353f5, + 0x447b5e6d, 0x322048b1, 0xbcf931a0, 0x0bad730c, 0xa7af2268, + 0x75c4d089, 0xb83b93f9, 0x464904c1, 0x165b3aee, 0xa24eba02, + 0xe08cc5f0, 0x65c48e78 }, + { 0xde222c22, 0x1a1c73ce, 0xfcea23b4, 0x5683d8cd, 0xb2143b06, + 0x0301cb14, 0x59fcec77, 0x284adf8f, 0x31204cef, 0xfb1c581c, + 0x94735107, 0xf54d3eee, 0x4d3188c0, 0xdbf67f0b, 0x10f18d12, + 0x76a3f2d1, 0x07d3e013, 0x3809fa28, 0x25e7ece0, 0xf06f0a46, + 0xb2895d2e, 0xd82867ed, 0x08b0553a, 0xe106f489, 0xef245445, + 0xe2280fa6, 0xa8d9a3cb, 0x402d5785, 0xd438ba2d, 0xf63dd9ff, + 0x7a6b226f, 0x36b5cd2c }, + { 0x545679a7, 0x87ff4e20, 0x4520c750, 0x64d80b41, 0x9b459cd8, + 0x90a357fa, 0xc85af1a3, 0xa19eaf39, 0x8d935a5e, 0x0d475d79, + 0x781a678a, 0x74501983, 0x0cc2e810, 0x74839779, 0x2f412244, + 0xc6a21d11, 0x36a51a37, 0x8d0e85f9, 0xeaa74df8, 0xff50151e, + 0x93cf99c4, 0x14e182a7, 0x376a9ab6, 0x45593df1, 0x522389ff, + 0x18f73caf, 0xf7445e8a, 0xd27cc960, 0x39a51dc8, 0x0692f4c5, + 0xdb39bfd8, 0x08d7c144 }, + { 0x3ecca773, 0x809c0d96, 0xd48c2156, 0x87ea9192, 0xdb6bd641, + 0xf0eccd74, 0x2a678cdf, 0x77312374, 0xd1587b7e, 0x7a966d8b, + 0x6130a4c6, 0xf3c1a101, 0x5fce17bd, 0x7cc6e838, 0xa8de7aa4, + 0x95e95bb8, 0x898308e3, 0x3fe1e8b5, 0xe347694a, 0x0197243e, + 0xbb0cd2bf, 0xf3fe9c42, 0x0f9b2b49, 0xb5905264, 0xc7367d1f, + 0x4c385e8b, 0xb5ee147b, 0x1d3050ae, 0x04004ad9, 0x8e2c3879, + 0xbab70202, 0x5f2aa8ee }, + { 0x1266524b, 0xe208d464, 0xd0a19f66, 0xb7bf3880, 0xda106ebf, + 0xa5aa685e, 0xe642dd46, 0x0a69e8d3, 0xc682e4d6, 0xef349c61, + 0x0fcb534c, 0x26f6ee3b, 0x05eb67b8, 0x7daba127, 0x18be05f6, + 0x2babb27e, 0x8e2d85d1, 0x959afcba, 0xe2d9d386, 0xedcf2d1a, + 0x1ea6f06e, 0x59dc52e6, 0x866e5ae8, 0xc28278b4, 0x02bcd3c7, + 0xd9ff0340, 0x784be82f, 0xe884ac76, 0x83c9f224, 0xa3164980, + 0xb46ff949, 0x62501a98 }, + { 0xad264086, 0x563f7d9a, 0xa5e0e4bd, 0xca6a33db, 0x8c8d3d67, + 0xe8253002, 0x46e64b19, 0xa288dac8, 0x20aa4536, 0xfa3c9197, + 0xed553eac, 0x8130c9b0, 0x2ea8abd3, 0x622806e0, 0xceccfe77, + 0x52fbf54d, 0x4f0d1b70, 0xbd9a8e31, 0xd59b1741, 0x519d2133, + 0x9a6fea8a, 0xfd74101c, 0xb5c4eb10, 0xd1acf7a0, 0x91f9da5e, + 0x78499b73, 0xc0dea586, 0xabaa4c49, 0xa1f3531a, 0xcc9c5f73, + 0xfd3fc665, 0x497b15fe }, + { 0xf45568e9, 0x8a56cbaa, 0xc7192a6f, 0xf491a0fe, 0x9ab2539a, + 0xdbb03dd3, 0x4ac37da9, 0xc86522f8, 0x02a0f5b4, 0x8c8cdba2, + 0xa29c539f, 0x8109fc75, 0xca90f02e, 0x9cd06d31, 0x3e216dbf, + 0x8f31f044, 0xba3ebd91, 0x99aa68ac, 0x42c007f4, 0x2a80d0d2, + 0x86a9b7ce, 0xdd8dffbf, 0xd6308edc, 0x405d3e84, 0x068012ca, + 0xdafa33fe, 0xedea1071, 0xc2eebd13, 0x2ff637e6, 0xb7ae7e5c, + 0x9e514cb7, 0x18d46a6c }, + { 0xa78b7802, 0x868cbb22, 0x497cbaf4, 0x0745ddb2, 0x42ae8add, + 0xc4eb2f3e, 0xb4ceb4e4, 0xac0abcda, 0xa325fd40, 0x2e0d8325, + 0x13ac7345, 0x6cfe0571, 0xb14171b9, 0x7407a788, 0x6da7a52b, + 0x70eb0603, 0xd85176ac, 0xab0b36f9, 0x7c2954f3, 0x14109d29, + 0xdcd705ad, 0x370de9c8, 0x7bb5e751, 0x3f0db5cd, 0xa06e708c, + 0x45f93d41, 0x7e93050d, 0x10d54f8a, 0x5a38fef9, 0x69e6f8e4, + 0xd3f62e40, 0x55044601 }, + { 0x06cb9cc9, 0xd1c5c910, 0x41d00014, 0x542074d7, 0x11236fb8, + 0x7cd8663e, 0x29ad5f82, 0x39721ffe, 0x2951fc83, 0x1d21fbfa, + 0x400d144f, 0x1cde06e7, 0x91792e6b, 0x9042596b, 0x29ad5166, + 0x3365c8e5, 0x9aeefe98, 0xe2220e85, 0x70c2aee3, 0xbcb53189, + 0x9ff100bc, 0x477ca3db, 0xf532973f, 0x27074176, 0x9a2bd01b, + 0xa12118ac, 0x3dd79f93, 0xf3425209, 0xc6f5d7db, 0x563a8ff7, + 0xd7b0ec4f, 0x0da313fc }, + { 0x15aa2557, 0x37125a8c, 0x00893e9c, 0xca21d70c, 0x67b8a823, + 0x48713994, 0x7cb0042a, 0x0d3e9a74, 0xc9e2ce18, 0x2d2bf4ff, + 0x049aeac2, 0xd5531a0d, 0xf03d0660, 0x4d29a616, 0x1f1b7f00, + 0x473d50d6, 0xca3de50c, 0x3af0ecbb, 0x09c28f27, 0xe2959bea, + 0xf8704664, 0x6d7c2ea0, 0x731083ef, 0xadfae4e1, 0x941c2554, + 0x50940c26, 0xa1162d03, 0x44167410, 0x1e82290e, 0x620230d8, + 0xdb414acc, 0x63630be8 }, + { 0x8a7d2e41, 0xbf8d5222, 0xeb62f879, 0x49e75823, 0x6c402d89, + 0x1b4d33dd, 0xde2c59ad, 0x883e04d6, 0x49b9dc38, 0xbf3f38f4, + 0xb4b70c4c, 0x9d997d18, 0x13cea045, 0x1f69b20c, 0x58e2606d, + 0xca3d7025, 0x261d1b79, 0x3d4fd977, 0x5a1436fa, 0x56aeafa8, + 0xbb443c07, 0x369b3e98, 0xe558f6be, 0xfce5186c, 0xf8ac8f89, + 0xeb0cd478, 0xd5e5aa72, 0x68074f37, 0x68544eb0, 0x295845c0, + 0xf16688ed, 0x306a9871 }, + { 0x634ec136, 0xbc451e9d, 0x0e6f658f, 0x1edf27ca, 0xc0db4120, + 0xa9be0152, 0xc5bfee67, 0x87b6ef20, 0x9a2d6023, 0x35283238, + 0xc7afb899, 0x60e564d8, 0x0ac9c2de, 0x4af22bc0, 0x82a9d22b, + 0x28e6f631, 0xf532701b, 0xc075c701, 0x82075f91, 0xf6d418f8, + 0x1beaa511, 0xf9fa628d, 0x6e72a13d, 0x551e7a17, 0x77f4c01c, + 0x9306215b, 0x93c9d588, 0x71aba731, 0x58e57cd4, 0x6443ebe0, + 0xe8103e37, 0x2833ac41 }, + { 0x8da5ec5c, 0x7e564b86, 0x1c08db24, 0xac3d9da8, 0x8c57a728, + 0x9d7c1f0b, 0x9d343dc2, 0x3512afe7, 0xfdc60339, 0xb438e4cf, + 0xdcfa1941, 0x7d5a2700, 0x27320449, 0xd5f323f8, 0x1393c6e6, + 0x1b87a58e, 0x04baa431, 0xecb68bd1, 0x4722b4d7, 0xc09c1c5a, + 0x206b5faa, 0xf42faa97, 0x9976327e, 0xe1dcbcd6, 0x087787d9, + 0x655ba9e4, 0xde5c0191, 0xbd59c757, 0x0bcf3538, 0x673020ed, + 0xa49d6303, 0x120cd454 }, + { 0xcab0f9ee, 0xebfdb8f4, 0x2cce58ee, 0xbc003ef0, 0x5a8d0665, + 0x9b6a6841, 0x9b957774, 0x642ed3a6, 0x4721ab5c, 0x3de487f0, + 0x21a4f0d3, 0xef2ff380, 0x29dbddcd, 0xbd16f558, 0x0e93dff2, + 0x2ef05b4b, 0x0bc9aec1, 0xde1faa12, 0xd467fa92, 0x66dae2c2, + 0x5eb33e34, 0x758daf64, 0x8f0103cb, 0xa67ad9f6, 0x9be02430, + 0x151f693a, 0xeb4054bc, 0xd5698496, 0x7019336e, 0x8ef1677e, + 0x7fdeea3e, 0x021cfd16 }, + { 0xdf5c36f3, 0x5c73715f, 0xd64ad254, 0x703bde37, 0xf2cf7713, + 0x55368d10, 0x0f3993c8, 0x1e5ec7b7, 0x304ae4ca, 0xfdb16776, + 0x3d3bb18b, 0x0d8f717e, 0x66343d5a, 0x5267073f, 0x156008b5, + 0xfaeb52ef, 0x224a470f, 0xb97ad5f9, 0xed2ab51a, 0xaf86e391, + 0x9974302c, 0xdc0c7e57, 0xfd0ae28a, 0xc88fa817, 0xbf8ed59c, + 0x807c22df, 0xeb128bb6, 0x5dedc231, 0xa20595a3, 0x71edcd9c, + 0xc73cf78e, 0x07265b46 }, + { 0xbd66232f, 0x73dd99f0, 0xc4027716, 0xc59aaf89, 0x5b860fc4, + 0xaf826dfa, 0x7a943f3b, 0x239ea8aa, 0x523c428d, 0x0e0e1b1a, + 0x6973b95a, 0x55ea0e3a, 0x2557753b, 0xea399caa, 0x06957b1f, + 0xf8adf72f, 0x3bd34302, 0x0389f341, 0xf8a43a97, 0x333f27d0, + 0xadaf796f, 0xcd9c0c08, 0x49c12aa2, 0x6dcca49b, 0x7a0ac6e9, + 0xdd88deee, 0x0644080e, 0x8f47575d, 0x0cc2f4bd, 0x6e9d667d, + 0x31d1496c, 0x36c5754b }, + { 0xf323d84b, 0x9120046e, 0x7e789c4f, 0xa6991122, 0x921b8055, + 0x4b0eaf4e, 0x8079974e, 0x6339844a, 0x740f8c79, 0xc905466a, + 0xcd6def49, 0x1c18d0f7, 0x4b23e4ba, 0x5297da6b, 0xc41800c5, + 0x1c09dff3, 0x37ef6777, 0x6c49075b, 0x50513ded, 0xa94c3a40, + 0x6b0b1705, 0x3d6742e9, 0xc48af5ae, 0xc0784494, 0xc95822de, + 0x40c01532, 0xc164d94f, 0xa2ddade5, 0xa2975eb5, 0xfc8a8ac9, + 0x1946944e, 0x06fbf861 }, + { 0x3f45aa97, 0x2d65338e, 0x1d040feb, 0xd83b58c8, 0x0fdef8b9, + 0x05fef59b, 0xe4d7417c, 0x7beb071a, 0xb30a1a23, 0x982b61f5, + 0xfb65bd03, 0x4c5f2a2a, 0x5cbf6bf3, 0xe40abc9d, 0xf06612a5, + 0x422c326d, 0x9571ae28, 0xc921e69d, 0x23d3434e, 0x7c88b10b, + 0x9da07933, 0x96d2e957, 0x3619cf4d, 0x833d46a1, 0xd95eefa1, + 0xd9d19653, 0xa03e8f0e, 0x2a7d8411, 0x04bb5ab1, 0x5e642953, + 0x1f0fa9ea, 0x5e9ca0fd }, + { 0x197c5dc4, 0x5bd54571, 0xe78a95a2, 0xe2da40bf, 0xffdb0eb2, + 0x65fb9efc, 0x0d17467c, 0xe952dc2c, 0xc758c6a3, 0xc1fc9c7b, + 0xd4034a9a, 0xfc79562c, 0x61f64b56, 0x26e36fbe, 0x1e84728b, + 0x6adc4b9e, 0xa8f9ac8a, 0x7f165fd3, 0x03e3e013, 0x7bc93a45, + 0x656478e3, 0xeacc5513, 0x064ddc77, 0xd3391717, 0x76936914, + 0x75b318dc, 0x362424a6, 0x69b1f1c7, 0x49955f34, 0x8cc2045b, + 0xc6836af8, 0x940622b3 }, + { 0x0d997973, 0x4710ccb7, 0xd3f8f115, 0x3b29625d, 0x5b97abd5, + 0x8cf0c4d5, 0x673e14a5, 0xc6321e0a, 0x3d262246, 0x0541af9d, + 0x6fc83b11, 0xde6d8754, 0xf01652a4, 0x47e97da8, 0xad9802b6, + 0x0f82b3a6, 0xae9c44b2, 0x69aa4075, 0xced2bf77, 0xaf3f5de2, + 0x497a40da, 0x1ef1ea8a, 0x3c23ba9c, 0x2e0f8608, 0xf190a2c8, + 0xd8a998a4, 0xcfde3368, 0xe2b49c8c, 0xbde6bd71, 0xb9f49824, + 0x785bedb6, 0x80bb1664 }, + { 0xfd145cb5, 0x05e575fe, 0xac5e6883, 0x155ee561, 0x8793b273, + 0x461e70cf, 0x133b2338, 0x9f1553de, 0xa2a7ba07, 0x2fb9e0c3, + 0x3e7086fa, 0xc3bfd6a8, 0x8bb4cb93, 0xb6ba8500, 0x76f82dbd, + 0x0b66d789, 0x54eb49ff, 0x7d5a6ff6, 0x1f20b322, 0xcd65d237, + 0x54e29cdc, 0x79ea49c2, 0xcb118ff9, 0x64975963, 0xcc58000b, + 0x969598dd, 0x110c779c, 0x95107918, 0x63b85a35, 0xedfc1548, + 0x41212350, 0x077ba5ea }, + { 0xcdd86f61, 0x0b3a38d3, 0x0502a0ab, 0x43121445, 0x806d0272, + 0x1912edc5, 0x8a32f10f, 0x01dc1f98, 0x0e80c760, 0xbb1d31d1, + 0xf464e8b3, 0xd46ec7e5, 0x9abf49ee, 0xd569af36, 0x2cdade77, + 0x9d286ea7, 0x45ad5920, 0x2be7020d, 0x6299ae7f, 0xabe5236e, + 0xd3f55c07, 0xc93179bd, 0x52350e80, 0x8138995a, 0xaff07586, + 0x0901265c, 0xf4739653, 0x5b3c81b2, 0x9bc77d21, 0xbaf7581d, + 0x4591a2e2, 0x6b2006df }, + { 0x965b1bc1, 0xb2fe50a8, 0x962bb4fd, 0x931f536a, 0x000e7f99, + 0xd5718d33, 0x53d5125e, 0x84728f25, 0xd2125caf, 0x4f8a6184, + 0x357f679e, 0x54f1a701, 0x1531c05a, 0x70a9f40c, 0x6fa8b775, + 0x10d0cb97, 0x9dc12ce9, 0xb476f41e, 0x2755f894, 0x5c8d7a75, + 0x625741a4, 0xd6c12e10, 0xc917b16c, 0x262a6fb8, 0x38d6b0a0, + 0x24d116e6, 0x32c38e83, 0x849540c0, 0x66868afc, 0x855b911c, + 0xbd26b550, 0x53217ea6 }, + { 0x259f52b4, 0xfc840473, 0xe621146c, 0x968da9cb, 0xcacbd26e, + 0x964eb85e, 0xe4a54344, 0xab7daa2d, 0x381a4ff7, 0x6dc3b848, + 0x41c815ef, 0xa07a96b3, 0xc3d4b1e1, 0xc4fae9e8, 0x42ce9ea8, + 0x0f938d1e, 0x35cc052f, 0xa727dacc, 0xe9a06f07, 0xc81e01c9, + 0x4a6d65a1, 0xa9e08dcb, 0x6044a9a6, 0xf8e2d173, 0xf2bd295b, + 0x99893dd0, 0xf9781b12, 0xa08d3379, 0x61830ac2, 0x64bd6001, + 0xd9adbeef, 0x0386931e }, + { 0xd09885a5, 0xd0d7abb3, 0xe355bb07, 0xed9d2b67, 0x536ebaed, + 0x3bc238cf, 0x699ce4d6, 0x61ca2e78, 0x111594cd, 0x354ff447, + 0x03316ad2, 0x55cbe709, 0x49fff5c4, 0x418679fd, 0x0f9c6c40, + 0x75bacd75, 0x2972721a, 0x677edc88, 0xe5ef502f, 0x82596887, + 0xbf320e0e, 0x459e9367, 0x8bbdccb2, 0x81ce36ef, 0xb766863d, + 0x1ba097fc, 0xd58c6db8, 0xcd3a21d6, 0xb4a8748b, 0x0e4967cd, + 0x15041c20, 0x2caaf749 }, + { 0x6ed20424, 0x44f98006, 0x22471545, 0xb3e4ea23, 0x781a8c86, + 0x268ed1a5, 0x7ae5b70b, 0x48d0ab75, 0x356d3982, 0x6ca8b320, + 0x2df31fa4, 0x9ce8e681, 0xd925dcf2, 0xb909d232, 0xf56723de, + 0x302c8f78, 0xabac96f9, 0x11725d69, 0x57d1a170, 0x656a47ca, + 0xc18a2be7, 0x6bb5d511, 0xad50d9d9, 0xb56e45f1, 0x70b05518, + 0x36e886e2, 0x09d8ff91, 0xc7c71f3d, 0x9350361e, 0x65a1bbe2, + 0x45fe3bd8, 0x86d7f532 }, + { 0xb0bf719a, 0x99f16eb6, 0x8bc3d913, 0xb6975098, 0x26cd01b4, + 0xfae50e52, 0x90898d1c, 0xd3e3ac54, 0x887ec666, 0x4da3b9db, + 0xfbea45b8, 0x58300644, 0x8355b058, 0x369f3bd9, 0x579bcc13, + 0x0fb239a8, 0x6e2bd811, 0x4f5b4539, 0x24198fd2, 0x007f3baf, + 0x8837d51d, 0x68a676db, 0xeae75b16, 0x68eeea62, 0x3db6083c, + 0x5ffe5f94, 0x7d836c5a, 0x52c94d0f, 0xcbc1ff85, 0x5a4c3c6f, + 0x86c0b4dd, 0x682a55e3 }, + { 0x587495aa, 0xc8f235a4, 0x34c7245d, 0x2276026c, 0xb75a46e3, + 0xd6ae0cc5, 0xecc3e5e7, 0x890d3965, 0x14296629, 0x1b13342f, + 0x8a877227, 0xc89927e6, 0x2324a68b, 0x1543f27e, 0x49cdc21a, + 0x6c447684, 0x1452d0ac, 0x9bc7fd4f, 0xff4b045c, 0x2cc30a31, + 0x852f7611, 0x415d46a0, 0xc6fdd7a6, 0xad737052, 0x7b4c7c91, + 0xdcecc3ab, 0x7688d70c, 0xd2cdf01b, 0xe40d3905, 0x054f2542, + 0xfefe4dcd, 0x02227fa6 }, + { 0xb751948b, 0x1805efd9, 0xfdfd225d, 0x8efeed46, 0x4f2c8b22, + 0xcb128e09, 0x96f7c5e5, 0x9d1090bf, 0xb4cbeca0, 0x0959d044, + 0x8e08cb04, 0x21c955f9, 0x68fa4fce, 0xbc1f279d, 0x0710ae9a, + 0xb021e14e, 0x881167f4, 0x64d16e9f, 0xbbc9f1a5, 0xf5a5c22e, + 0xe3420eea, 0x5f3716df, 0xd5c4e843, 0x971eb915, 0x28ffba81, + 0x64fc55fc, 0x7dd37578, 0x3427e54d, 0x15ebc7d0, 0x446e6a62, + 0x29269778, 0x547e249a }, + { 0xa1ffda27, 0x4706868a, 0x7955cf50, 0xb4e6cdcc, 0x0a63f3d8, + 0xf65151e1, 0x9de5e70a, 0x5b4127ea, 0xf9342823, 0x3d2c09ba, + 0xaa2f7d51, 0x18c99d83, 0xddeec025, 0xa0c5bb1d, 0x03dcf1ce, + 0x7ffddf84, 0x616fdeda, 0xe57e4d29, 0x7932a1f0, 0xd2456569, + 0x3191d4e3, 0x7475e0e8, 0xc220218b, 0x3479bea1, 0x8bcb2505, + 0xfceb5c90, 0x3c6132e6, 0x1c685cea, 0xbfe6c1eb, 0xc42dc745, + 0xd2b08eea, 0x45a41cc0 }, + { 0x4dbbf0e1, 0x3ea9b2c7, 0xa17cf70e, 0x41ff962f, 0x5eeb4c66, + 0xdc1ea758, 0xa9beb17e, 0x4f5412d2, 0xa285741a, 0x2c9e4f52, + 0x984fd11f, 0x93df7da4, 0x0df3184e, 0xb2afbddc, 0x2421e375, + 0x96323d25, 0x49df781e, 0xc87be1e4, 0x3d589bea, 0x145601ed, + 0x28fff6dd, 0x0f0bd9bd, 0x8a0f298c, 0x2d3259d4, 0xd88e6944, + 0x362d7a77, 0xb6ac2af6, 0xa84c06b6, 0xd087da02, 0xba850ac9, + 0x42ee40c8, 0x128763c9 }, + { 0xacbac178, 0x29a80f07, 0x34b08f6e, 0x7cc20044, 0x70feded2, + 0xe9631d14, 0x86615767, 0xb2115da3, 0xcb088548, 0x7c75f5c4, + 0x9a2e8e03, 0x5b29d213, 0x8b881752, 0xfe9fda66, 0xc1de7ebc, + 0x3f1d8d88, 0x03218123, 0xb476565e, 0xb1c995f3, 0x07365561, + 0xb13eb71b, 0x2160cb18, 0x99b3a0eb, 0x7e8da513, 0xb20fcd74, + 0x5e8ca1f9, 0xb4126d72, 0x6a7e0067, 0x68bb637f, 0x1e8204b7, + 0xfc4f74d2, 0x75e96bcc }, + { 0x0d19716e, 0x189d1fdc, 0x7c384525, 0xdf585058, 0xea987d2a, + 0x64a846d1, 0x6c07150f, 0x12b6bf83, 0x4d6fd5b7, 0x91d85d46, + 0x4f53f55f, 0xa9788836, 0x81509129, 0x60083bd8, 0xea876f48, + 0xa7672683, 0xc15b2489, 0xe80b2e7a, 0x42d1d992, 0x985ef8d2, + 0xcf3de492, 0x9c57b029, 0xb1487627, 0xfe02f83c, 0x8ae5b687, + 0xaeba4fe4, 0x5d6b8196, 0x8a86f09b, 0xa16e523d, 0xd88f566b, + 0xba268949, 0x309a6e9a }, + { 0xbdfbe97a, 0xef27ee50, 0xb8c50c4d, 0x1a5fe70f, 0x7fe09f5c, + 0xcc7beb01, 0xbed36cc5, 0x8fa15a85, 0x7550ed3a, 0xc0c3acdb, + 0xeb908681, 0xc581ef87, 0xc49d5ccb, 0xa15b3362, 0x1fa264e8, + 0x0fbb1714, 0x8e1eee88, 0x267f8d8f, 0x21c2b63d, 0xd31ccfd6, + 0x53be7efd, 0x924dbe7d, 0xdb2a358a, 0xd42e877f, 0x75d68ac1, + 0xcf9673c7, 0x714fea55, 0xe35978fd, 0x5769b202, 0xeeb36653, + 0xd7593789, 0x0458258a }, + { 0xa042dbdf, 0x5df71a74, 0x5779dfa2, 0x2d405857, 0x0d2e6657, + 0x0e66cba7, 0xca2e892e, 0x285d6745, 0x0f0e6b5f, 0xf56a8def, + 0xa30767c3, 0xe0ee851d, 0x43346b9c, 0x98c05658, 0xd6b3c742, + 0xb35fce26, 0x39777e00, 0xc0895bff, 0xe7b6d886, 0x83c8f6a6, + 0x4f02904b, 0xbee14843, 0x2e84ec34, 0x7f74915b, 0x96d10991, + 0xbaaf663c, 0xe41facc0, 0x004b8757, 0x6f86c029, 0xa2b880e5, + 0x95b77358, 0x53f4a3e0 }, + { 0x89fc48e7, 0x11bb08ce, 0xafab5aeb, 0xba60c577, 0xa0c1cb5a, + 0xf06bcbf8, 0x79757cb6, 0x7d2efaea, 0x76319160, 0xe26d90b1, + 0x2b77b7a9, 0x42aa1ab6, 0x285df2bf, 0x38eec0cd, 0xf3a8f7f0, + 0xd35947f5, 0xfc1cb5b5, 0x97c8dc0e, 0xc45845cf, 0xfeb8cca0, + 0x249e26f2, 0x16e8d989, 0x483ed89a, 0x7c264e6d, 0x51d91073, + 0x13a3f145, 0x305e99f0, 0x8501562e, 0x6908d563, 0xaaf98d74, + 0xd723d236, 0x0a99e653 }, + { 0xabbc0559, 0x23536f46, 0x9aa1a160, 0xc163067b, 0x0c1681b5, + 0x229fd229, 0x1378e907, 0x61254be1, 0xab793a2d, 0xc60ff57a, + 0x466552db, 0xa6f2df8b, 0x8c170a36, 0x9ad31893, 0x29b74d9a, + 0xc5cd9abe, 0xf7848523, 0xcf747273, 0x0d0e3063, 0xc126a93a, + 0x4248e3d8, 0xfe2021e3, 0x8323ddfa, 0xd97343ee, 0x332639e7, + 0x9f768775, 0x75325548, 0x9650fc31, 0x3eebf7ea, 0xb595dbd1, + 0x010fcbc0, 0x3a95cb45 }, + { 0x39d7ff2e, 0x954e68cb, 0xc1d5c48f, 0x8dd1cb4b, 0x7169438a, + 0x02a92c77, 0x91cad8ce, 0x7965c0b0, 0x32cd08d2, 0x0c5798ab, + 0xa6902bda, 0x1a5bc3c3, 0x5186d218, 0x545d0925, 0xd27e64db, + 0xf0077cdb, 0x8cd092da, 0x0157caa4, 0x24532ab3, 0x2a2fa3a0, + 0x41ccaba3, 0xa5fb639b, 0x4744aee6, 0x01702dc1, 0xcdba93da, + 0x485bb436, 0x329784f1, 0x93597f66, 0xdad672c3, 0x5d713c1d, + 0x030b7245, 0x366d222e }, + { 0x573ea5b2, 0xd50b4875, 0xa90da44d, 0x0fce401b, 0x7a1a0310, + 0x7b53fa65, 0xcf114460, 0x722a80a5, 0xa538bf49, 0x0b8ebf05, + 0xd32acd21, 0xae141147, 0x7b5ad07d, 0x6692712c, 0x3f48ca07, + 0x6dc5fee7, 0x2b8a78d8, 0x98ed1499, 0xdd2f1759, 0x4e8b3145, + 0x5f971b8e, 0x43408de1, 0xadf1b368, 0x055ea6dd, 0xe5932b7e, + 0x4bb76e73, 0xd30893fd, 0x44287153, 0x0661bfda, 0x173dccd2, + 0x79defd25, 0x9072ba99 }, + { 0x9620ea39, 0x474de4dd, 0xc831cee8, 0xfbf1649f, 0xcd3a9c43, + 0x0b0e8bb1, 0x3f3df1d5, 0x6a38286f, 0x8f0ec9b3, 0x4ed072b3, + 0x729c09e3, 0xa6e4c987, 0x8ad12242, 0xea3e8ac6, 0xfbdfa5ba, + 0x6ae0e22b, 0xb0a0f592, 0x56171ecf, 0x6b871f8d, 0x33b2886d, + 0x35e11bda, 0x6b19bea9, 0x7f0f153f, 0x4d815a40, 0x7d6c02ee, + 0x7e608d97, 0xb6a88f46, 0x7e8f23d9, 0x439d1654, 0x26ac9652, + 0x35546c29, 0x8d92c6bd }, + { 0xabeb0ff7, 0xb3e0d7ce, 0x3e0e42f8, 0xfbe35254, 0xde808499, + 0x57d1b226, 0x1cd44bc3, 0x9ece2e1f, 0x435cfee1, 0x1245adbc, + 0xf93f581c, 0x874ee840, 0xbda0b947, 0x916a779c, 0xfa57ae0a, + 0xabcc815a, 0xf0a621b0, 0x97adec2d, 0x81f90bdc, 0xbe6a502b, + 0x53bde63d, 0x54bf9de1, 0x78884c25, 0xa88fdabf, 0xcbbb5470, + 0x30aa52b1, 0x29053ef5, 0xf805396c, 0x8dd827ea, 0x8d43d898, + 0x5c1ae5c0, 0x4e4bec17 }, + { 0xfcc09676, 0xbf8483a2, 0x19ea9a94, 0x457c4a3f, 0xd702a5dd, + 0xa6852ef3, 0x843fe7d8, 0xe7915fd2, 0x16e35158, 0x644bba98, + 0x9ed746f0, 0x8d1b95d0, 0xb90af0b5, 0x47704581, 0xd4fd135e, + 0x0bd4bc6b, 0xb4e833a5, 0xa6dce067, 0xff56a9a1, 0x2c0e8f30, + 0xec2c63fe, 0xa9c80800, 0x98f508a8, 0x449c20a5, 0x3292813a, + 0x02b94cb3, 0xec7e81a2, 0x647e3d28, 0xb4877677, 0x72e67d1a, + 0x6f9ded24, 0x7a4aa3f5 }, + { 0xe27a0045, 0x559ef1ba, 0xb242cb50, 0xdc812d4f, 0x39cf8d24, + 0x23a478e4, 0x9b3f9c54, 0x97544fc5, 0xaffa1fcf, 0x5ac68132, + 0x34a2c83b, 0x74f8fee0, 0xcd3f4bb7, 0x96cc640f, 0xb0512ea6, + 0x775dce9d, 0xcdce381e, 0x67dca19d, 0xa9d3fe55, 0xc1eeb3f3, + 0x1a19274f, 0x38e0bf42, 0x28d69b12, 0x15992fb4, 0x9fd09df8, + 0x48fcebde, 0xb41ab5df, 0xdc9dfa4f, 0xc0a269c5, 0x0cbd7dc8, + 0xf7f0ade1, 0x60282a7b }, + { 0xdceea2e7, 0x7c07e538, 0x3c42061d, 0x38a322c8, 0x4f1f6516, + 0x676828f9, 0xc7776a10, 0xf21b69fb, 0xb5e6b405, 0xc63a3417, + 0x91a7b642, 0x4c99f258, 0x2cad1440, 0x38692ca8, 0x00869bcd, + 0xf1e82ffe, 0x16fe466a, 0xc30b714e, 0x19019138, 0x5fb742f9, + 0x0fa516ae, 0xe90166d0, 0xd8c73a43, 0x5550f7ac, 0xfbc5c372, + 0x2d6a407d, 0x68cc39ed, 0xe47a7539, 0x4a5fbe70, 0x3fd286d9, + 0x23c6b942, 0x5f4ae9c7 }, + { 0x53f4d561, 0xd96a2dda, 0x16da1992, 0x286d45d0, 0xfdd4b051, + 0x449a01fb, 0x9f2195ea, 0x25488a0d, 0xa37661b3, 0xc4151b0a, + 0xf9e5ee02, 0xb98c471e, 0xa8658817, 0xa4bca86e, 0x7a68fc0a, + 0xbbcadb87, 0x6b7366a9, 0x88b34649, 0x15661c2d, 0x32ee98d4, + 0xc901420c, 0xf5b3b4c6, 0x2f2752af, 0xa2352735, 0x510e4d9c, + 0x2f64ce73, 0xaca4aa80, 0x939a7f26, 0x401aa503, 0x9cd3e291, + 0xdc46afd2, 0x92a01423 }, + { 0x1c2f7dbd, 0xe9f24be1, 0xb7d527fa, 0xda8c900f, 0x8648f128, + 0x963e25bb, 0x48141941, 0x9ab713e2, 0x7a6756fb, 0xe87f7d01, + 0x058d90bd, 0x274dd85e, 0x82566abd, 0x823fee7a, 0x74240195, + 0x9f6230d7, 0xacb5e46e, 0x04579f2c, 0x16a4c87e, 0x2a226263, + 0xd99b0857, 0x9ca19a43, 0xe488789e, 0x86dc2ba3, 0x9406c3bd, + 0xf960b5b9, 0x8960957e, 0x6f2c428b, 0x161c515b, 0x90748706, + 0xaa88cb9b, 0x0fc8fe1e }, + { 0xfeb90f2d, 0x68ae1bed, 0xa48b1559, 0xf393bb3c, 0xf64e9635, + 0x2be62f9c, 0xf8be75c2, 0x354c2410, 0x5e6f7529, 0xbd7ea703, + 0x162cab31, 0xc264868e, 0xc860f3ff, 0xb1391e70, 0x1d89837e, + 0xdf367c75, 0x2bf32941, 0xe150b6b4, 0x78c1318f, 0x95e8f46e, + 0xa2c4b160, 0x2b3f1dab, 0x701afbf3, 0xc6ccf5ce, 0x5e8874c5, + 0x3ad27530, 0x5dc6dcbe, 0x39285e51, 0xd99892dd, 0x3c954d86, + 0xdfd3789f, 0x2d0ba862 }, + { 0xb472e1af, 0xeacd8ee8, 0xb76abbcc, 0xeb354eae, 0xd0d93fbd, + 0x9b520bf8, 0xfe6fc706, 0xfccd60d7, 0xa4ee2f39, 0xa9353dde, + 0x9a81e51e, 0x5eb0925e, 0xd1366777, 0xee334da1, 0xd5354d69, + 0xc1d28c9f, 0x92a5ed54, 0xb9771755, 0xb7f70d81, 0x5d3e367f, + 0xa933ae7a, 0x7be7eeca, 0xe23cfbb7, 0x264cf1f9, 0x89497681, + 0x0d129f4a, 0x09b6235b, 0x705375a4, 0x48a376da, 0xccf64c75, + 0x4d41dbfc, 0x963c8712 }, + { 0xde36a814, 0xbae290cb, 0x733b12b5, 0x9bdb0195, 0xf77fe0e1, + 0x0ebad867, 0x29720cea, 0x0a7d19fd, 0x9029ec72, 0x434d7651, + 0xbb51911e, 0x856aff17, 0xd80a7f60, 0xd0a25d9a, 0xf848c106, + 0xffca86af, 0x43ad749c, 0x53e8bdf9, 0xe3e696bb, 0xfb9e0284, + 0xeeee4215, 0x3eb6630a, 0x2ecf3c63, 0x9d8fbb9e, 0x4e00c0c0, + 0x71da4ffa, 0x5d57beac, 0xb296be59, 0xa8cec7ef, 0x1751fbad, + 0xff55d7bd, 0x2d03eb3c }, + { 0x04f2ec1d, 0xeb16925f, 0x0d147ee2, 0xa878f276, 0xaad9d9e0, + 0x442df604, 0x3f71035b, 0x891df44b, 0x8cb95d5b, 0xc28272b3, + 0x5ee8ed23, 0x6f14efb5, 0x13b0f3e3, 0xf3c4460f, 0x6bd7335e, + 0x889f9bd7, 0xf755ba6e, 0x889ee771, 0xed219b6c, 0x626984fe, + 0xec2ee411, 0x2d44c737, 0x63efcd37, 0xb94385a2, 0x6637826b, + 0xd909321b, 0x3ee6b7a7, 0xc24f8a79, 0xa7cf61b7, 0xa3ca8d24, + 0xc54bacd9, 0x842e40c1 }, + { 0xa661d843, 0x5a268ed6, 0x4f5b30cd, 0x02328cca, 0x1311e177, + 0x16e6fed1, 0xc6695967, 0x690decb4, 0x57b2e280, 0xbdac5bf6, + 0x1efe42d0, 0x827f82ca, 0xca5fca2f, 0xc554ec0a, 0xdde45506, + 0xac5276c1, 0xe3077513, 0xb7f4cb08, 0xcc8797cc, 0x8caf6d9a, + 0x0d9332d2, 0xd5964814, 0x285a409f, 0xcc6ae297, 0x6223d093, + 0x7773c2a5, 0x5128fc09, 0x2d5266ac, 0xbc31fe6c, 0xa596b7cb, + 0xcac91328, 0x0e63319a }, + { 0xf0360ac2, 0xb5cd2fad, 0x285e605a, 0x86b660de, 0xe25b9b14, + 0x82c6cf10, 0xaa9ac554, 0x9d5fa38d, 0x526c070e, 0x3dfcf1b8, + 0x3fccc52d, 0x0379a96b, 0x0bfcc7f5, 0xe3659c29, 0x69d3e6a1, + 0x5b1a3db5, 0x9b7b42d5, 0xb41528b5, 0x9c22a006, 0x934defa4, + 0x9b4ce3b6, 0x90f38018, 0xb3abaf32, 0xb073bc04, 0xff8389e2, + 0x27a5a222, 0xffa5a35b, 0x0b7a9d51, 0x28e1a7c2, 0x4939ecef, + 0x1872705a, 0x88839da2 }, + { 0x701ce29a, 0x56b66c30, 0x58981d50, 0x3acaf126, 0x105f9f21, + 0xd4dafc0c, 0x373e3d13, 0xfee571e6, 0xfa2ee3ca, 0xe7269c86, + 0xdd20385a, 0xf5cca64a, 0x3000e9ac, 0x217f2757, 0x0e7273ef, + 0xc934db47, 0x355b6776, 0x4294f4f7, 0x6fc05180, 0x1faa36b9, + 0xb052190b, 0x8f88b1db, 0xe9eaef52, 0x35791b90, 0xdb681b90, + 0xf37fb2eb, 0x4415c369, 0x39d0a51d, 0x1d2e21c9, 0xfc59cca7, + 0xa1f50c26, 0x64128cfe }, + { 0xe8f5b0b5, 0xf03678a2, 0xd340f059, 0x5c7e249c, 0x93ca7cec, + 0x41440441, 0xbc83af98, 0x075ca346, 0xfaa8bbb0, 0xf39f0033, + 0xf38230f7, 0x3d18f0ed, 0xd448f345, 0x78dff00c, 0xd51aa475, + 0x849228c0, 0x30c928d1, 0xdd4e2708, 0x8f12cfd3, 0xc66ba686, + 0x88b3a206, 0x091049db, 0x016dae01, 0xd865d059, 0xe253e37d, + 0x4599e905, 0x7ce9871b, 0x322cf0c2, 0x174a132e, 0x014f54da, + 0xbdabcbda, 0x93634a09 }, + { 0xa9a2e304, 0x62826b27, 0xc1a4c124, 0xc57e1866, 0x22381710, + 0x913ab832, 0xa9847cfe, 0x7e9b6b85, 0x2b5f46fd, 0x29655cf1, + 0x8038e66d, 0x7295572b, 0x6fa95eab, 0xe4cba601, 0xb9deda81, + 0xbbc11071, 0x3f1cf61e, 0x97f0009a, 0x373e0cfb, 0x5372777b, + 0xd139d63b, 0x302f909c, 0x4f87d78e, 0x1ed672da, 0xb4048763, + 0x362077a3, 0x9dcc22b2, 0xc408c32d, 0x26deeee7, 0x4b4c5bf2, + 0xbc06357e, 0x266cb467 }, + { 0xb56363e8, 0x6faa4154, 0x3c1aa4db, 0x4b4fd078, 0x2b9e6597, + 0x14358dde, 0xfa004b84, 0x5b34ae3e, 0xf19911a6, 0xcf44b2ec, + 0xa536bf78, 0x55caa833, 0x8870dc95, 0x606e1eb9, 0x09f3511d, + 0xe3c3287d, 0x9d5cf364, 0x68b2f4eb, 0x63ab8c9e, 0xc154e892, + 0xc36ab611, 0x1548828e, 0xa1b7d120, 0x0932bfcb, 0x5315b8d7, + 0x7ee7b5bc, 0xf7473ac1, 0x782fd0d1, 0x3c8f2af3, 0xbcb029a8, + 0x52454ee1, 0x4b1d5a1b }, + { 0x63d52c0c, 0x12fe5174, 0x188c099d, 0x3735525e, 0x360e3956, + 0x5c621563, 0xacfa5a43, 0x88b3f1ca, 0x797e8107, 0x90123a0a, + 0xb15e080a, 0xba31f6b5, 0xfca3dada, 0xd7de5e12, 0x0df511c8, + 0x3287361b, 0x65757d4e, 0x7cc800d4, 0x5207ec91, 0x10810f3d, + 0x30eea0e3, 0x0d4e56f1, 0x3ea5a2ec, 0xbbf7ee13, 0xbe6abbd0, + 0x6fc07762, 0x120bf619, 0xc831fdce, 0xb622d42a, 0xe07439fa, + 0x508e4b27, 0x8186b93f }, + { 0x09312867, 0xc619d154, 0xbfaf7db4, 0x7e042c05, 0x1f5f5dda, + 0xc1cf1668, 0xa4fc3d82, 0x50aa5057, 0xce68b8fe, 0xed30ed65, + 0xbeb4d644, 0xecb01c0b, 0x831c0497, 0x7b5dc444, 0x9b7d9b1c, + 0x351e6a00, 0xd9477c91, 0x4bb863b9, 0x05d4110a, 0xaba65891, + 0x43580b7a, 0x30086cf4, 0x90be357e, 0xb139c076, 0x27b5214e, + 0x12bfff1a, 0x22c3ab57, 0x79cfc6d7, 0xf34a9bfa, 0x4743de57, + 0xc9ee2b2a, 0x0bf97e97 }, + { 0xdda19e96, 0x96ec4ec8, 0x6c306e8b, 0x54ce18ea, 0x65f6918a, + 0x7e83612b, 0x0d9a0d99, 0x1ac6f68b, 0x62fdcc09, 0x98a697a4, + 0x95bc3e13, 0x65ce25f1, 0xb3939730, 0x1896ecda, 0x32f12806, + 0x9eb81a0f, 0x1d2dc7df, 0xd3d7416e, 0xad473599, 0xe22c7976, + 0x9f5ef439, 0x3de37a9a, 0x9e69d94e, 0x6b7ac0ab, 0x0a9d0bc8, + 0xe6bfa9e0, 0x5676f120, 0x576a870d, 0xfeaac23f, 0x3bd91bb4, + 0x3e40aabb, 0x8fe5482c }, + { 0xce9a4d1e, 0x85ae67c2, 0x4f1d2038, 0x4c3eb803, 0x25d06192, + 0x5c6c8f3a, 0x308fb41c, 0x803de0ad, 0xe71c294e, 0x9961f5bc, + 0xf02eb0da, 0xdc62078d, 0xb64ae8b6, 0xc87ef515, 0x50b4d18f, + 0x69679f1e, 0x52199f43, 0xc5c009a1, 0x0f640a5f, 0xa7d484be, + 0x23dab566, 0x4c918bb1, 0x64275d2c, 0xa67c114c, 0xcad2ded6, + 0x95a913b9, 0x6b4b5c8d, 0x189ed18b, 0xb42d3bf6, 0x4aeb6206, + 0xbbc8bc3f, 0x3928c669 }, + { 0xdacb4b64, 0xde4bea4a, 0xf26179a1, 0x03f62a44, 0x7a9112a4, + 0xf3aac94e, 0xd36f331e, 0x90448fbd, 0x407b85c4, 0x426042bc, + 0x2121b77b, 0x5ad8a596, 0x67cee984, 0x31674a4f, 0x4e3b2f0d, + 0x7fae8bbe, 0xa7c930eb, 0x681df6dd, 0xc259d0d4, 0xadeefa98, + 0xbea1c1fd, 0x1b14d9e6, 0x21d405d1, 0x3baadc8b, 0x73892754, + 0xf01dff93, 0xf071cde4, 0x81c35b3e, 0x9150d0d9, 0x1704d2e1, + 0x355134f6, 0x6ccc888f }, + { 0x7ad7504c, 0xf8d36f0e, 0xf7959ddd, 0xbca3265f, 0xfede67aa, + 0x0dcd1ede, 0xbaebf32f, 0x1276f4ce, 0x014edcfc, 0x6825a6e6, + 0x99ad8eb7, 0x0b8c1a82, 0x09b8ce1e, 0x312024a9, 0x9cbd351a, + 0xcb8fd98b, 0xfab1e8be, 0xa4841378, 0x3973cacf, 0x17ed0f5d, + 0x259d5254, 0xa17e1484, 0x74b91393, 0x53d5b843, 0x1aca3ce9, + 0x8f792b21, 0xc8c0f815, 0x035ff110, 0xad4ed7bd, 0x6afa6357, + 0xb26faef9, 0x2f151980 }, + { 0x29d2d439, 0x0c8631da, 0xbc039955, 0x121fbbc2, 0x6c05b75b, + 0x3e5a9792, 0xb6ce47ec, 0x6d6cf4c0, 0x9d88c658, 0xbaaa1767, + 0xf3355a17, 0x031db9e7, 0x0aef5a85, 0x8381e3d8, 0x15a31bdf, + 0xc71db290, 0x9498fd7d, 0x638f6b74, 0x13beeef6, 0x44edf3f9, + 0xf4ab67b3, 0xe6173271, 0xfd22df11, 0x3a202c70, 0x205c4e92, + 0xf7be0389, 0xa8eb9920, 0x1c219085, 0xbeb54aaa, 0x6c805ce8, + 0x0ac58d65, 0x354b05b7 }, + { 0x7a9170e9, 0x7171e236, 0x4cad50cd, 0x01eec42d, 0x3cddccfb, + 0xffbe824f, 0xa66cae1a, 0xa73e8ce3, 0x965c7d01, 0xb7138a7f, + 0x5c3d971e, 0x00058e3f, 0x2ff0a72b, 0x52591ac3, 0xbbbce76f, + 0xa32fb5bc, 0xa9f81a18, 0xf3241ab8, 0xeca68630, 0xf31d3332, + 0x4482f13b, 0x847af9fc, 0xa4681be2, 0x6196e217, 0xe55efcf9, + 0x9938f932, 0x70acc705, 0x3e7dacb8, 0xcf09fac2, 0xd41be893, + 0xae3523a1, 0x48dc55c4 }, + { 0xa5092193, 0x8e623826, 0x6898970c, 0xe46ec362, 0x25c9eb41, + 0x2f1356af, 0x83c7d245, 0x41780640, 0x97d00e38, 0x982def67, + 0xa512151c, 0x382eb6e7, 0x8af58869, 0x154e1077, 0x8a51cf02, + 0x18707075, 0x71313c58, 0xcdeba9f7, 0xba155904, 0x5d67b973, + 0x1d0d7b3a, 0x851c9f4b, 0x8b8af2cd, 0x19f29d71, 0x986b8d62, + 0xcb94ccff, 0xb93b9c33, 0x8725e24b, 0x66e38c68, 0x405ce4c5, + 0x0b6dc021, 0x5f6a8edd }, + { 0x8f9a8690, 0x83704ca5, 0x2f76a407, 0x3f369766, 0x69201028, + 0xfbc12d8c, 0xbce3a4cf, 0x4cd58f16, 0x04aab26d, 0x7804664a, + 0x4ea457a8, 0x005cfbba, 0xb8a59794, 0x537951b3, 0x4fe1f739, + 0x4ca2b9e4, 0xdf325797, 0xe4428acd, 0x0ea243db, 0x648da342, + 0xf43ce01e, 0xcce6562b, 0xf27db490, 0x840f0421, 0x8bfb7cf0, + 0x156ccb70, 0x5a8797d3, 0x9b33480d, 0x9eb814bb, 0x2e12e07a, + 0xca7f87ac, 0x1ca65072 }, + { 0x2b9d25a0, 0xfbb321cf, 0x40a746db, 0x66affdca, 0x59e368b5, + 0xc1c1530e, 0x7d80068f, 0x56ed1ea4, 0x5647dd68, 0x9b74d8fe, + 0x89b78da8, 0x1d96b507, 0x8bbe3391, 0x39b75243, 0x0d858c5f, + 0xef8d443e, 0x9646aa34, 0x4dd2db49, 0xe667543c, 0x7fad3bd1, + 0x68980985, 0xd0d710c0, 0x49facaba, 0x9f7aff32, 0x14f9a192, + 0x055dec1c, 0x1fb307a1, 0xaca66399, 0x35ffff64, 0xac44fd91, + 0xcbad3cee, 0x462cafb6 }, + { 0xde3237dd, 0x1660a647, 0x82b87404, 0x95f735cc, 0xddfa55f8, + 0xf7879f59, 0x726b914a, 0x15ef043e, 0x1c93e298, 0x1875393d, + 0x6ef18331, 0xa1a2be74, 0x25a9a12b, 0x4e7e8dfc, 0xa9c3917f, + 0xdfefc97d, 0x0a2ebe41, 0xbc875d03, 0xa732d1cc, 0x0f75d235, + 0xd9baa6d3, 0x06fee7fe, 0x65f48576, 0xaa784fab, 0x513f83c0, + 0x23155e22, 0x3e8f9d13, 0xd2fb7718, 0xb546eafd, 0x2a291503, + 0x6cd93608, 0x1293c98c }, + { 0x49d53b77, 0x72781251, 0x96eafac7, 0xa6ab403d, 0x4a36b711, + 0xb7d7c7db, 0x87e771c1, 0x8238c708, 0x33b37522, 0x495f6abf, + 0x8c87530d, 0xb0b0289c, 0xe77b111a, 0xca83cb86, 0xa1bd189e, + 0xbe1c0fb8, 0x1ae9d7c7, 0x58cfb2fb, 0x4940c3e8, 0xd05c23c5, + 0x74ad9107, 0x16e79e41, 0x064e7142, 0xa0a47f05, 0xfdfd614f, + 0xc6929cd4, 0x3946988b, 0xedb2584c, 0xe46f8fb1, 0x73e4b5f3, + 0x68ea94ba, 0x53b79aa1 }, + { 0x44bbb6a1, 0x216fafce, 0x67821728, 0xd3a5bba0, 0xa9dd939a, + 0xef1e4b30, 0xf19efafe, 0x022eaf3d, 0x7b4ec014, 0xfed5abce, + 0x512c6738, 0x64968ee6, 0x29fe89a2, 0x23119869, 0x47397c05, + 0x0d539d8d, 0x234596c4, 0x6400bc54, 0x5346611d, 0xb9287f58, + 0xc9d5da0f, 0x04099903, 0xc83af2a8, 0xe5ef4997, 0x328151e1, + 0xc89dc01b, 0x58401104, 0x150fb4a9, 0xf3872c9d, 0x40a6f7d5, + 0x56c2e833, 0x8290d6d1 }, + { 0xd8546946, 0xf84637c6, 0x69ec57fa, 0xda134a39, 0xd789007e, + 0xd42359a4, 0x0dc7b809, 0xb42557fe, 0x2d6784a9, 0xe62ae52d, + 0x0bcadb5f, 0xa2714ca6, 0x33aafca5, 0xcc208de6, 0xed967811, + 0x2380ed5c, 0xdb321660, 0x6e6b55e9, 0xa675235a, 0x1bead02c, + 0xb33fa0e1, 0x51cc6ef9, 0xf06a2a08, 0xfd223e26, 0xec47b3cf, + 0x00f332e1, 0xa0aa984e, 0x459f297b, 0xee952e14, 0x6fa1d969, + 0x304fabb0, 0x506ef1ab }, + { 0x35bff163, 0x11b4eb27, 0xea9fa984, 0x7130b96f, 0x9deb27ce, + 0x66aceb3f, 0x9dd1c3d5, 0xa2daf1a5, 0xa73075aa, 0xf5090a7e, + 0xe3071b58, 0x36a6af39, 0xdf73ad9c, 0xa28d633d, 0xbdc89a16, + 0xdd354cac, 0xd4dcbc3c, 0xdfea3423, 0x379d92d1, 0x6eec74d2, + 0x8eed6765, 0xe14a456f, 0xfa8feb1f, 0xfabe7743, 0xb98fcbc7, + 0x1404ccf8, 0xf71a706e, 0x6ccd2fbf, 0x4d85c678, 0xdaaf3fdb, + 0x15200344, 0x415b7dbf }, + { 0x7d8377a7, 0x97010586, 0xcb803272, 0x068a3d68, 0xf03a4c32, + 0xfd67d289, 0x93c8f290, 0x4bc7095d, 0xe9e5a2b8, 0x712fa13c, + 0x0feb9f3b, 0xfc6ac6c6, 0x6e0e54c2, 0x0cda36d9, 0x86320a01, + 0x45499751, 0x97f00f11, 0xf9318c91, 0xe6936508, 0x01dc4c3f, + 0x85f068aa, 0x769a2ef9, 0xa2b5511c, 0x3522cef0, 0xb4122e05, + 0x006965ed, 0xc175d43f, 0xfce0fafc, 0xec831d59, 0x525dc9bd, + 0xaf58879d, 0x1ec314f1 }, + { 0x2c8310c2, 0x0663feef, 0x457e3f74, 0xaa7e14da, 0xe5346887, + 0x392b10fc, 0x637ec2c5, 0xcde4a38f, 0xb542f8df, 0x50773320, + 0xf7de1711, 0x341302f9, 0xae4b9bc6, 0x018b1c63, 0xdd2f9e6f, + 0xf001c46e, 0x26eccfa0, 0xd3bb0a97, 0x7746e0c7, 0xa931b99d, + 0xf5875aec, 0xe0c8b6f7, 0x96939c82, 0xbb32f17c, 0x3de5a664, + 0x765135d2, 0x52abfa6b, 0x71936cb4, 0x2dc105de, 0xad5cc08f, + 0x7fff5788, 0x17e91d12 }, + { 0xb7e051ca, 0xbe92ced3, 0x19c776d4, 0xc644d4fd, 0x0086784b, + 0xc8ab4b52, 0xce9d6b31, 0x3ea66227, 0xd289e9c7, 0x395249a3, + 0xd12a19ee, 0x54509e65, 0x8c365aec, 0xa7bd4692, 0x77963e0e, + 0x354997e4, 0xb599732d, 0x0d765957, 0x91d4a3b6, 0x99584aeb, + 0x1deb3e28, 0x6e653ea4, 0x572571df, 0xca7c98ed, 0xb18ae1f9, + 0xf301a38f, 0x63f7b97e, 0x1629f7c2, 0xafc4a0d5, 0xdf242282, + 0x3ddd0c01, 0x118f3b4b }, + { 0x7ad4762b, 0x74a0a0a8, 0x8c58d175, 0x1aef84da, 0x4cf76d86, + 0x16ff4960, 0x7e60d98b, 0xc0be8786, 0x3ecc1dba, 0x83637ffb, + 0x5dd6147a, 0xc244a609, 0x5b0846e5, 0xa3e17834, 0xe77a4c05, + 0x735eb686, 0xdf758695, 0x5bc18b4f, 0x1bdfe52f, 0x15618d0b, + 0x00715ba1, 0x878ecc0d, 0xc2dd617f, 0x1dbdbd1a, 0x21b61710, + 0x21d2b631, 0x44f593c2, 0x22ce8a79, 0x44f17024, 0x3b9b536a, + 0x8d03e727, 0x01d0a67c }, + { 0x1e46533c, 0x7b964236, 0xfb88c2ae, 0xe9477990, 0xa42c4a18, + 0x019b5d16, 0xd83c7a45, 0x7135e81d, 0x4cb663e3, 0x74a69bdd, + 0xe76c0d63, 0x7b67ecdb, 0x11e68da6, 0x03d54521, 0xd2e8650a, + 0x596cceb5, 0x2af03b37, 0xcd572dfd, 0xfabd5952, 0x52364ba1, + 0xb4ed8569, 0x7f47d456, 0xc950d5d4, 0x5ad8b572, 0x486e2f84, + 0xcadd2dfa, 0xc56bb044, 0xdd527b43, 0x997c08e6, 0xc9adba24, + 0x7da6320f, 0x1b625b06 }, + { 0x4fd8446d, 0x44dfaa7b, 0xaf6febeb, 0xc01b2f01, 0xfe8838b5, + 0xbf444388, 0xbba9758b, 0xf33c434f, 0x87156bc9, 0x2b971cba, + 0x1f49098b, 0x6b245e5c, 0x2b41c5dd, 0x87dcb534, 0x34d852d7, + 0xdb1f80c6, 0x2433da34, 0x6d6e3258, 0x3f7df0c2, 0xf6682065, + 0x360cb365, 0xc4ca567c, 0x9826656a, 0x321faac2, 0xbf069768, + 0x13f5ca6f, 0xa7076639, 0x15397921, 0x8400736e, 0xbdf14328, + 0x19fc948d, 0x333eca96 }, + { 0xac775d81, 0x23337948, 0xd41dbbca, 0x38c2518f, 0xbcfce948, + 0x623c7a4f, 0x54703fe7, 0xaad36236, 0x13fb3b5b, 0x2b3a13a4, + 0x7f5c01f0, 0x5db3565a, 0x52359661, 0xd72408dc, 0x1d616e91, + 0x5a17f8e5, 0xcb25b999, 0x90c16eeb, 0x3393743e, 0xf35e8cf1, + 0xe54b64a7, 0x987da74a, 0x65cd449d, 0x557b322a, 0x37e7b15d, + 0x765082a5, 0xf2cd134f, 0x4d25c742, 0x4ccf0746, 0xae9d9c07, + 0x8728d135, 0x72fc2110 }, + { 0xf96004c8, 0xa906b203, 0x458055ff, 0xd83f95cf, 0x55f35909, + 0xd77d5867, 0xe550c8ee, 0x4a9ea6fb, 0x55a06081, 0x91c8cca9, + 0xbce82062, 0x4a1fee78, 0x9a3df85e, 0xeb9ade06, 0x7d3de666, + 0xfbbdcf0c, 0x5d336d51, 0x228a391b, 0x5c2ffc3c, 0x760f8d28, + 0x2f7b165b, 0x1ee48de3, 0x56177040, 0x03803d84, 0x9deff9a0, + 0xe573f648, 0xa17e35a4, 0xe1a2738e, 0x8840a6c6, 0x238ef17c, + 0xb11ed92d, 0x480946f8 }, + { 0xfd71f119, 0x84c747a8, 0x53eb3695, 0x19e65c5e, 0x6298587a, + 0x0e2f6786, 0xab18d6f4, 0x48a48899, 0xc630b8c0, 0xa1a99024, + 0x2caaf892, 0x84975096, 0xe20fd624, 0xc8869aba, 0x6c2b7dd4, + 0x3b72b04d, 0x0992f7d0, 0xe2775eb6, 0x7d06e684, 0x0089c06e, + 0xe4bbd007, 0xcb3b4361, 0x4ba846e4, 0xa1ae666b, 0x46464d9e, + 0xc01c2eb2, 0xc1f8539f, 0xf86f2be6, 0xcf68afc7, 0x16e8e8ae, + 0xc7386902, 0x8dab61fd }, + { 0xd54d1d45, 0x42a5c903, 0xff4f9ba2, 0xacd4297e, 0x34d478b4, + 0x2d88b520, 0x08c4621a, 0x35b2ba2b, 0x34865402, 0xd3d239bb, + 0x911f32e6, 0x1de76aed, 0x3f06fdc2, 0x877f8bcf, 0x9ec51502, + 0x802714c1, 0xa590700d, 0xa10444eb, 0x31dcc957, 0x8694229f, + 0xb8169fed, 0x5ece77ab, 0x2caf080e, 0x55be8a15, 0xcbd7cef1, + 0x3eb21b14, 0x67b97ee1, 0x9def7ad1, 0x118f690c, 0xe03ca879, + 0xf99b29e7, 0x6f77e62d }, + { 0xe40bbf59, 0xa271bded, 0x6401aad6, 0x177ba453, 0x73541cd1, + 0x1755e035, 0x4b71b02f, 0x3465b466, 0xa813359f, 0x22eb7113, + 0x6f38eac7, 0x9792a8fd, 0xff3bf3b5, 0x11aa012f, 0xf85c3fbf, + 0x99aafabf, 0x06c0cc42, 0x91e0a2ef, 0x773b7b3a, 0x314d5d57, + 0xd669840a, 0xae5e2e76, 0x2e5a8be6, 0x86136073, 0xc1cf5580, + 0xee6d7578, 0x68bed102, 0x2344e00f, 0x8184f0eb, 0x799d7886, + 0xc3d2cf80, 0x63819c91 }, + { 0x7884b073, 0xca5392e1, 0xeb1267ea, 0x9ec3a1fc, 0x907038a7, + 0x3d07f5f0, 0xe4c47b70, 0xcb2ac07c, 0x1bf96b91, 0xf96664ee, + 0x2aea4fbf, 0xebf57589, 0xfade6500, 0x5aabf391, 0x171d1204, + 0xc5b3376f, 0xa0d3d81a, 0x1ff60c51, 0x976a844b, 0x10b2cfe7, + 0xbda6125a, 0xe131cc9a, 0x4ebd453e, 0xe0fc16d3, 0x504b6bc1, + 0xc0d0319a, 0x0a2f8cab, 0xe43a0be7, 0x55e49b47, 0xc80afeec, + 0x8265d7ee, 0x67d48d12 }, + { 0xea2d56d6, 0x068d59a7, 0x27480a63, 0xd71abd0e, 0xae7366cd, + 0x6bd11db0, 0x07204ebc, 0xfbb639ca, 0xf77e6293, 0x89a242e7, + 0x75ba8c3d, 0xdee7ca2b, 0x64a2f9a8, 0x472ddc3d, 0x7561a010, + 0x84229df4, 0xc5b649d4, 0x95f62c85, 0x4dc927cd, 0xfdd56b1b, + 0x5ee60596, 0xfe8bb120, 0xabf29401, 0x3efcaa50, 0x10d1c184, + 0xd4900d0f, 0x28b01df5, 0x2cf113a9, 0x1f0e43f5, 0xa3d7ebc3, + 0xe8384dc7, 0x27950e38 }, + { 0xe1d0fa79, 0xeab21ff0, 0x048b5de9, 0x4b9fd033, 0x2fe374cb, + 0x4c934689, 0x4eb21f6b, 0xbb4827fa, 0xa925e7e7, 0x46716f79, + 0x7dd4c531, 0x1442bf36, 0xd2e96ddf, 0x2073954c, 0x8502aa89, + 0x4e0141ae, 0x8eef6cc9, 0x8ee00e1a, 0x5880cdaf, 0x55ce8491, + 0x69628046, 0xff3aba5c, 0x5d15dfbf, 0x335cc4f8, 0x9f684f25, + 0xa7f0440c, 0xbb1e5bd8, 0xae80453f, 0xff2225ab, 0xa1c99813, + 0x79b25d71, 0x54ff7884 }, + { 0xde40b068, 0x27c6ee30, 0xe6f3a51e, 0x9226465b, 0xfa3b21f6, + 0xe24a4604, 0xc0418115, 0x50a5a5ad, 0x8df90d2b, 0xe3285441, + 0xdcb0c00f, 0xbb74e58f, 0x4a2c08e3, 0xc68f1b3b, 0x0ccd9ec9, + 0x339df081, 0xb786ea9f, 0x915362dc, 0xc955aead, 0x28945e31, + 0x8b6a6c6b, 0xd6a2c01d, 0x3678a427, 0x069e82dc, 0x28c9302c, + 0x17875500, 0x9fa101e6, 0x8acda965, 0xee30b286, 0x4e4e4573, + 0x3f1830fe, 0x8adbad85 }, + { 0x0969d524, 0x060ae11f, 0xf39bcc79, 0xf42fdaf7, 0x7cc1fcc2, + 0x3cec6766, 0xe2336d4f, 0x456b9cf2, 0x8e1c0f7f, 0x6aa1f5de, + 0x0984fb0e, 0xcdbc2ad2, 0x1b464b28, 0x4090cfa6, 0x1243f3ef, + 0x40d86f30, 0xcd5e87e7, 0x95b16ccc, 0x3026cd41, 0x403f168c, + 0x816c0730, 0xdbe386cb, 0x58407a1d, 0x14eb86f3, 0x1717e1af, + 0xf588b4f8, 0x66cbc96c, 0xb75c41a6, 0x027e71c1, 0xf342c1aa, + 0xc0945e5f, 0x73930036 }, + { 0x22cdaf42, 0x954f757d, 0xf4181aab, 0x788b591d, 0xf5514f25, + 0x8b986819, 0xf18fd5bc, 0x69642e08, 0x022ceb91, 0x92b305d1, + 0x6a4f6985, 0x1715903e, 0x61179cae, 0x4bd7d69d, 0xd29c01aa, + 0xdacdfd5d, 0xd91108cc, 0x705ddd5a, 0x64ac8f15, 0x434ac7b1, + 0xb524632f, 0x61a514e1, 0x731fc447, 0x45b9e61b, 0xe0961b31, + 0xcf561348, 0x73eaf223, 0x9c28a967, 0xaa7c99d3, 0x5bd10182, + 0xe42965e2, 0x8bc6ec4a }, + { 0xe7f2a32b, 0xd096e5c0, 0x09388a30, 0xff54800c, 0x401e360c, + 0x06fe437c, 0xbb6054a6, 0x6655fc9c, 0x8457aa6e, 0x510e1860, + 0x2b29b2b7, 0xa0acfca2, 0x51b7da61, 0x732483e3, 0x6be6c8ca, + 0xe31471ee, 0x8b65c9a1, 0xe565431c, 0x48d65cbb, 0xfc9ac3b9, + 0xae9b2aa8, 0xd308fc21, 0xaa60aa6a, 0xd6a7df0d, 0x982fc0d4, + 0x2844d96a, 0x5847a4d7, 0xab012c2c, 0xdceb8955, 0x2b3c8f71, + 0xbe9c7e15, 0x8e85437d }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 32]; + sp_digit tx[2 * 32]; + sp_digit ty[2 * 32]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 32 * 2; + ty = td + 5 * 32 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 32); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_32(tx, ty, t); + sp_1024_proj_mul_qx1_32(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_32(tx, tx, t); + sp_1024_mont_mul_32(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_32(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = px + py */ + sp_1024_mont_add_32(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_32(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_32(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_32(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_32(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_32(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_32(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_32(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + sp_1024_mont_inv_32(t1, p->z, t2); + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 32); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 32; + sp_digit* pz2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* l = t + 8 * 32; + sp_digit* ty = t + 10 * 32; + + /* v = v^2 */ + sp_1024_proj_sqr_32(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_32(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_32(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_32(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_32(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_32(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_32(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_32(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_32(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* h = t + 8 * 32; + sp_digit* r = t + 10 * 32; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_32(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_32(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_32(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_32(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_32(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_32(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_32(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_32(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_32(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_32(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_32(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_32(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit qx_px[2 * 32]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_32(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + qx_px = td + 8 * 32 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + + sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* h = t + 8 * 32; + sp_digit* r = t + 10 * 32; + + /* h = p.z^2 */ + sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_32(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_32(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_32(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_32(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_32(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_32(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 32; + sp_digit* pz2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* l = t + 8 * 32; + sp_digit* ty = t + 10 * 32; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_32(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_32(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_32(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_32(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_32(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_32(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[64]; + sp_digit (*pre_vy)[64]; + sp_digit (*pre_nvy)[64]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit pre_vx[16][64]; + sp_digit pre_vy[16][64]; + sp_digit pre_nvy[16][64]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_32(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2); + pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2); + pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2); + pre_p = (sp_point_1024*)(td + 56 * 32 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32); + sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32); + sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 32; + sp_digit* t2 = t + 2 * 2 * 32; + sp_digit* l = t + 4 * 2 * 32; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_32(l, py, p1024_mod); + sp_1024_mont_inv_32(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_32(t2, t1, p1024_mod); + sp_1024_mont_add_32(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_32(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 32); + XMEMCPY(cr, t2, sizeof(sp_digit) * 32); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 32; + sp_digit* c = t + 2 * 2 * 32; + sp_digit* l = t + 4 * 2 * 32; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_32(l, cx, px, p1024_mod); + sp_1024_mont_inv_32(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_32(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_32(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 32); + XMEMCPY(cr, c, sizeof(sp_digit) * 32); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 32; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_32(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_32(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 32]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 32 * 2); +#endif + + sp_1024_point_from_ecc_point_32(p, pm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_32(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_32(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_32(c, c, t); + sp_1024_mont_map_32(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t); + sp_1024_mont_map_32(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_32(c, c, neg, t); + sp_1024_mont_map_32(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_32(c, c, t); + sp_1024_mont_map_32(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(neg, 1, NULL); + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[64]; + sp_digit (*pre_vy)[64]; + sp_digit (*pre_nvy)[64]; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit pre_vx[16][64]; + sp_digit pre_vy[16][64]; + sp_digit pre_nvy[16][64]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2); + pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2); + pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32); + sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32); + sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_32(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] | + a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] | + a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_32(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[32 * 4]; +#endif + sp_digit* t2 = NULL; + int32_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 32; + + sp_1024_sqr_32(t1, point->y); + (void)sp_1024_mod_32(t1, t1, p1024_mod); + sp_1024_sqr_32(t2, point->x); + (void)sp_1024_mod_32(t2, t2, p1024_mod); + sp_1024_mul_32(t2, t2, point->x); + (void)sp_1024_mod_32(t2, t2, p1024_mod); + (void)sp_1024_sub_32(t2, p1024_mod, t2); + sp_1024_mont_add_32(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_32(t1, p1024_mod); + sp_1024_cond_sub_32(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(t1); + if (!sp_1024_iszero_32(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 32, pX); + sp_1024_from_mp(pub->y, 32, pY); + sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_32(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[32]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 32, pX); + sp_1024_from_mp(pub->y, 32, pY); + sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 32, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_32(pub->x) != 0) && + (sp_1024_iszero_32(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_32(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) || + (sp_1024_iszero_32(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_32(p->x, pub->x) != 0) || + (sp_1024_cmp_32(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* WOLFSSL_SP_ARM_THUMB_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index db0fedc95..f1d41aafe 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -75,7 +75,8 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 }; */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -117,7 +118,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 23 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -151,7 +153,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -190,7 +194,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_2048_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<89; i++) { r[i+1] += r[i] >> 23; @@ -1011,7 +1018,9 @@ SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[89]) * b[89]; @@ -1043,7 +1052,9 @@ SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[89]) * a[89]; @@ -1154,7 +1165,9 @@ SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[44]) * b[44]; @@ -1186,7 +1199,9 @@ SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[44]) * a[44]; @@ -1216,7 +1231,7 @@ SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -1225,7 +1240,8 @@ SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -1571,7 +1587,6 @@ static void sp_2048_mont_reduce_45(sp_digit* a, const sp_digit* m, sp_digit mp) sp_2048_mul_add_45(a+i, m, mu); a[i+1] += a[i] >> 23; a[i] &= 0x7fffff; - sp_2048_mont_shift_45(a, a); sp_2048_cond_sub_45(a, a, m, 0 - (((a[44] >> 12) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -1587,8 +1602,8 @@ static void sp_2048_mont_reduce_45(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_45(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_45(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_45(r, a, b); sp_2048_mont_reduce_45(r, m, mp); @@ -1601,8 +1616,8 @@ static void sp_2048_mont_mul_45(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_45(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_45(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_45(r, a); sp_2048_mont_reduce_45(r, m, mp); @@ -1702,26 +1717,8 @@ static void sp_2048_cond_add_45(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 45; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -1731,19 +1728,19 @@ SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<40; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (23 - n)) & 0x7fffff); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (23 - n)) & 0x7fffff); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (23 - n)) & 0x7fffff); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (23 - n)) & 0x7fffff); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (23 - n)) & 0x7fffff); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (23 - n)) & 0x7fffff); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (23 - n)) & 0x7fffff); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (23 - n)) & 0x7fffff); } - r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff; - r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff; - r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff; - r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff; + r[40] = (a[40] >> n) | ((a[41] << (23 - n)) & 0x7fffff); + r[41] = (a[41] >> n) | ((a[42] << (23 - n)) & 0x7fffff); + r[42] = (a[42] >> n) | ((a[43] << (23 - n)) & 0x7fffff); + r[43] = (a[43] >> n) | ((a[44] << (23 - n)) & 0x7fffff); #endif r[44] = a[44] >> n; } @@ -1752,17 +1749,19 @@ SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 23 bits from d1 and top 8 bits from d0. */ - d = (d1 << 8) | (d0 >> 15); + d = (d1 << 8) + (d0 >> 15); r = d / dv; d -= r * dv; /* Up to 9 bits in r */ /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 7) & ((1 << 8) - 1); + d += (d0 >> 7) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -1770,10 +1769,11 @@ static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0, /* Remaining 7 bits from d0. */ r <<= 7; d <<= 7; - d |= d0 & ((1 << 7) - 1); + d += d0 & ((1 << 7) - 1); t = d / dv; r += t; + /* All 23 bits from d1 and top 8 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -1781,72 +1781,65 @@ static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[90 + 1], t2d[45 + 1], sdd[45 + 1]; + sp_digit t1[4 * 45 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 45 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 45 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 90 + 1; + t2 = t1 + 90 + 1; sd = t2 + 45 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_2048_mul_d_45(sd, d, 1L << 11); sp_2048_mul_d_90(t1, a, 1L << 11); dv = sd[44]; + t1[45 + 45] += t1[45 + 45 - 1] >> 23; + t1[45 + 45 - 1] &= 0x7fffff; for (i=45; i>=0; i--) { - sp_digit hi; - t1[45 + i] += t1[45 + i - 1] >> 23; - t1[45 + i - 1] &= 0x7fffff; - hi = t1[45 + i] - (t1[45 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[45 + i]; d1 <<= 23; d1 += t1[45 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_2048_div_word_45(hi, t1[45 + i - 1], dv); + r1 = sp_2048_div_word_45(t1[45 + i], t1[45 + i - 1], dv); #endif sp_2048_mul_d_45(t2, sd, r1); (void)sp_2048_sub_45(&t1[i], &t1[i], t2); + sp_2048_norm_45(&t1[i]); t1[45 + i] -= t2[45]; t1[45 + i] += t1[45 + i - 1] >> 23; t1[45 + i - 1] &= 0x7fffff; @@ -1863,7 +1856,7 @@ static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_2048_mul_d_45(t2, sd, r1); sp_2048_sub_45(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 45U); + XMEMCPY(r, t1, sizeof(*r) * 90U); for (i=0; i<44; i++) { r[i+1] += r[i] >> 23; r[i] &= 0x7fffff; @@ -1875,10 +1868,9 @@ static int sp_2048_div_45(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_2048_rshift_45(r, r, 11); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -1909,35 +1901,31 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 90]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 45 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 45 * 2); -#else - t[i] = &td[i * 45 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 45U * 2U); } @@ -1992,43 +1980,38 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 90]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 45 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 45 * 2); -#else - t[i] = &td[i * 45 * 2]; -#endif } sp_2048_mont_setup(m, &mp); @@ -2082,47 +2065,40 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 45 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 90) + 90]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 90) + 90), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 90; rt = td + 2880; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 90]; - rt = &td[2880]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_45(norm, m); @@ -2193,7 +2169,7 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 90); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (9 - c); c += 23; @@ -2219,16 +2195,15 @@ static int sp_2048_mod_exp_45(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 2048 bits, just need to subtract. @@ -2476,7 +2451,7 @@ static void sp_2048_mont_reduce_90(sp_digit* a, const sp_digit* m, sp_digit mp) sp_2048_norm_90(a + 90); -#ifdef WOLFSSL_HAVE_SP_DH +#ifdef WOLFSSL_SP_DH if (mp != 1) { for (i=0; i<89; i++) { mu = (a[i] * mp) & 0x7fffff; @@ -2510,7 +2485,6 @@ static void sp_2048_mont_reduce_90(sp_digit* a, const sp_digit* m, sp_digit mp) a[i+1] += a[i] >> 23; a[i] &= 0x7fffff; #endif - sp_2048_mont_shift_90(a, a); sp_2048_cond_sub_90(a, a, m, 0 - (((a[89] >> 1) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -2526,8 +2500,8 @@ static void sp_2048_mont_reduce_90(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_90(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_90(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_90(r, a, b); sp_2048_mont_reduce_90(r, m, mp); @@ -2540,8 +2514,8 @@ static void sp_2048_mont_mul_90(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_90(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_90(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_90(r, a); sp_2048_mont_reduce_90(r, m, mp); @@ -2635,46 +2609,8 @@ static void sp_2048_cond_add_90(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 90; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 90; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -2684,16 +2620,16 @@ SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<88; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (23 - n)) & 0x7fffff); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (23 - n)) & 0x7fffff); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (23 - n)) & 0x7fffff); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (23 - n)) & 0x7fffff); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (23 - n)) & 0x7fffff); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (23 - n)) & 0x7fffff); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (23 - n)) & 0x7fffff); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (23 - n)) & 0x7fffff); } - r[88] = ((a[88] >> n) | (a[89] << (23 - n))) & 0x7fffff; + r[88] = (a[88] >> n) | ((a[89] << (23 - n)) & 0x7fffff); #endif r[89] = a[89] >> n; } @@ -2702,17 +2638,19 @@ SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 23 bits from d1 and top 8 bits from d0. */ - d = (d1 << 8) | (d0 >> 15); + d = (d1 << 8) + (d0 >> 15); r = d / dv; d -= r * dv; /* Up to 9 bits in r */ /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 7) & ((1 << 8) - 1); + d += (d0 >> 7) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -2720,10 +2658,11 @@ static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0, /* Remaining 7 bits from d0. */ r <<= 7; d <<= 7; - d |= d0 & ((1 << 7) - 1); + d += d0 & ((1 << 7) - 1); t = d / dv; r += t; + /* All 23 bits from d1 and top 8 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -2731,72 +2670,65 @@ static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[180 + 1], t2d[90 + 1], sdd[90 + 1]; + sp_digit t1[4 * 90 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 90 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 90 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 180 + 1; + t2 = t1 + 180 + 1; sd = t2 + 90 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_2048_mul_d_90(sd, d, 1L << 22); sp_2048_mul_d_180(t1, a, 1L << 22); dv = sd[89]; + t1[90 + 90] += t1[90 + 90 - 1] >> 23; + t1[90 + 90 - 1] &= 0x7fffff; for (i=90; i>=0; i--) { - sp_digit hi; - t1[90 + i] += t1[90 + i - 1] >> 23; - t1[90 + i - 1] &= 0x7fffff; - hi = t1[90 + i] - (t1[90 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[90 + i]; d1 <<= 23; d1 += t1[90 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_2048_div_word_90(hi, t1[90 + i - 1], dv); + r1 = sp_2048_div_word_90(t1[90 + i], t1[90 + i - 1], dv); #endif sp_2048_mul_d_90(t2, sd, r1); (void)sp_2048_sub_90(&t1[i], &t1[i], t2); + sp_2048_norm_90(&t1[i]); t1[90 + i] -= t2[90]; t1[90 + i] += t1[90 + i - 1] >> 23; t1[90 + i - 1] &= 0x7fffff; @@ -2813,7 +2745,7 @@ static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_2048_mul_d_90(t2, sd, r1); sp_2048_sub_90(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 90U); + XMEMCPY(r, t1, sizeof(*r) * 180U); for (i=0; i<89; i++) { r[i+1] += r[i] >> 23; r[i] &= 0x7fffff; @@ -2825,10 +2757,9 @@ static int sp_2048_div_90(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_2048_rshift_90(r, r, 22); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -2861,35 +2792,31 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 180]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 90 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 90 * 2); -#else - t[i] = &td[i * 90 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 90U * 2U); } @@ -2944,43 +2871,38 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 180]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 90 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 90 * 2); -#else - t[i] = &td[i * 90 * 2]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3034,47 +2956,40 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 90 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 180) + 180]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 180) + 180), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 180; rt = td + 5760; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 180]; - rt = &td[5760]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_90(norm, m); @@ -3145,7 +3060,7 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 180); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (9 - c); c += 23; @@ -3171,15 +3086,14 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */ /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_RSA @@ -3195,15 +3109,18 @@ static int sp_2048_mod_exp_90(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[90 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -3228,15 +3145,16 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } +#endif if (err == MP_OKAY) { - a = d; r = a + 90 * 2; m = r + 90 * 2; norm = r; @@ -3289,20 +3207,21 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[180], md[90], rd[180]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[90 * 5]; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -3324,27 +3243,20 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { a = d; r = a + 90 * 2; m = r + 90 * 2; - } -#else - a = ad; - m = md; - r = rd; -#endif - if (err == MP_OKAY) { sp_2048_from_bin(a, 90, in, inLen); #if DIGIT_BIT >= 23 e[0] = (sp_digit)em->dp[0]; @@ -3408,10 +3320,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } #endif return err; @@ -3420,7 +3331,7 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #ifndef WOLFSSL_RSA_PUBLIC_ONLY #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) -#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */ /* RSA private key operation. * * in Array of bytes representing the number to exponentiate, base. @@ -3438,14 +3349,18 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a = NULL; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[90 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -3474,13 +3389,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 90; m = a + 180; @@ -3491,20 +3408,34 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_2048_from_mp(m, 90, mm); err = sp_2048_mod_exp_90(r, a, d, 2048, m, 0); } + if (err == MP_OKAY) { sp_2048_to_bin(r, out); *outLen = 256; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 90); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 90); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[180], d[90], m[90]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit d[90 * 4]; +#endif + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -3531,7 +3462,20 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + a = d + 90; + m = a + 180; + r = a; + sp_2048_from_bin(a, 90, in, inLen); sp_2048_from_mp(d, 90, dm); sp_2048_from_mp(m, 90, mm); @@ -3543,22 +3487,35 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } - XMEMSET(d, 0, sizeof(sp_digit) * 90); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 90); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #else -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[45 * 11]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -3579,22 +3536,21 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) { + if (a == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - a = t; p = a + 90 * 2; q = p + 45; qi = dq = dp = q + 45; tmpa = qi + 45; tmpb = tmpa + 90; - - r = t + 90; + r = a + 90; sp_2048_from_bin(a, 90, in, inLen); sp_2048_from_mp(p, 45, pm); @@ -3608,6 +3564,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } if (err == MP_OKAY) { (void)sp_2048_sub_45(tmpa, tmpa, tmpb); + sp_2048_norm_45(tmpa); sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); @@ -3625,17 +3582,31 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 45 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 45 * 11); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[90 * 2]; - sp_digit p[45], q[45], dp[45], dq[45], qi[45]; - sp_digit tmpa[90], tmpb[90]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[45 * 13]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -3656,7 +3627,25 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 13, NULL, + DYNAMIC_TYPE_RSA); + if (a == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = a + 90 * 2; + q = p + 45; + dp = q + 45; + dq = dp + 45; + qi = dq + 45; + tmpa = qi + 45; + tmpb = tmpa + 90; + r = a; + sp_2048_from_bin(a, 90, in, inLen); sp_2048_from_mp(p, 45, pm); sp_2048_from_mp(q, 45, qm); @@ -3672,6 +3661,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, if (err == MP_OKAY) { (void)sp_2048_sub_45(tmpa, tmpa, tmpb); + sp_2048_norm_45(tmpa); sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); sp_2048_mul_45(tmpa, tmpa, qi); @@ -3687,16 +3677,18 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); - XMEMSET(dq, 0, sizeof(dq)); - XMEMSET(qi, 0, sizeof(qi)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) +if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 45 * 13); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } @@ -3720,17 +3712,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 90; mp_clamp(r); #elif DIGIT_BIT < 23 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 90; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 23) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -3743,14 +3737,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 90; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 23 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -3777,15 +3773,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[90 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 2048) { @@ -3801,16 +3801,16 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 90 * 2; m = e + 90; r = b; @@ -3826,21 +3826,27 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_2048_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 90U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 90U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[180], ed[90], md[90]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[90 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -3857,26 +3863,19 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 90 * 2; - m = e + 90; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 90 * 2; + m = e + 90; + r = b; + sp_2048_from_mp(b, 90, base); sp_2048_from_mp(e, 90, exp); sp_2048_from_mp(m, 90, mod); @@ -3889,14 +3888,17 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 90U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 90U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 90U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -3905,7 +3907,8 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) #ifdef WOLFSSL_HAVE_SP_DH #ifdef HAVE_FFDHE_2048 -SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, const sp_digit* a, + byte n) { #ifdef WOLFSSL_SP_SMALL int i; @@ -3915,7 +3918,8 @@ SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, sp_digit* a, byte n) r[i] = ((a[i] << n) | (a[i-1] >> (23 - n))) & 0x7fffff; } #else - sp_int_digit s, t; + sp_int_digit s; + sp_int_digit t; s = (sp_int_digit)a[89]; r[90] = s >> (23U - n); @@ -4112,35 +4116,31 @@ SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, sp_digit* a, byte n) static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[271]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 271, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 180; XMEMSET(td, 0, sizeof(sp_digit) * 271); -#else - tmp = &td[180]; - XMEMSET(td, 0, sizeof(td)); -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_90(norm, m); @@ -4166,7 +4166,7 @@ static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const n <<= 4; c -= 4; sp_2048_lshift_90(r, norm, (byte)y); - for (; i>=0 || c>=4; ) { + while ((i >= 0) || (c >= 4)) { if (c < 4) { n |= e[i--] << (9 - c); c += 23; @@ -4198,9 +4198,8 @@ static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4220,16 +4219,19 @@ static int sp_2048_mod_exp_2_90(sp_digit* r, const sp_digit* e, int bits, const * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[90 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; if (mp_count_bits(base) > 2048) { @@ -4245,15 +4247,15 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 90 * 2; m = e + 90; r = b; @@ -4281,21 +4283,27 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, XMEMMOVE(out, out + i, *outLen); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 90U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 90U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[180], ed[90], md[90]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[90 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; int err = MP_OKAY; @@ -4312,26 +4320,20 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 90 * 2; - m = e + 90; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 90 * 2; + m = e + 90; + r = b; + sp_2048_from_mp(b, 90, base); sp_2048_from_bin(e, 90, exp, expLen); sp_2048_from_mp(m, 90, mod); @@ -4353,19 +4355,23 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256U && out[i] == 0U; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 90U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 90U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 90U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -4381,15 +4387,19 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[45 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 1024) { @@ -4405,16 +4415,16 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 45 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 45 * 2; m = e + 45; r = b; @@ -4431,21 +4441,27 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_2048_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 45U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 90U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[90], ed[45], md[45]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[45 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -4462,26 +4478,19 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 45 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 45 * 2; - m = e + 45; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 45 * 2; + m = e + 45; + r = b; + sp_2048_from_mp(b, 45, base); sp_2048_from_mp(e, 45, exp); sp_2048_from_mp(m, 45, mod); @@ -4495,20 +4504,23 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 45U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 45U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 90U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -4522,7 +4534,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -4564,7 +4577,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 23 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -4598,7 +4612,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -4637,7 +4653,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_3072_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<133; i++) { r[i+1] += r[i] >> 23; @@ -4680,7 +4699,8 @@ static void sp_3072_to_bin(sp_digit* r, byte* a) SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j; + int i; + int j; int64_t t[134]; XMEMSET(t, 0, sizeof(t)); @@ -4703,7 +4723,8 @@ SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) { - int i, j; + int i; + int j; int64_t t[134]; XMEMSET(t, 0, sizeof(t)); @@ -4904,7 +4925,9 @@ SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[133]) * b[133]; @@ -4936,7 +4959,9 @@ SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_3072_sqr_134(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[133]) * a[133]; @@ -5045,7 +5070,9 @@ SP_NOINLINE static int sp_3072_sub_67(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[66]) * b[66]; @@ -5077,7 +5104,9 @@ SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[66]) * a[66]; @@ -5107,7 +5136,7 @@ SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -5116,7 +5145,8 @@ SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -5390,7 +5420,8 @@ static void sp_3072_mont_shift_67(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; - sp_digit n, s; + sp_digit n; + sp_digit s; s = a[67]; n = a[66] >> 18; @@ -5403,7 +5434,8 @@ static void sp_3072_mont_shift_67(sp_digit* r, const sp_digit* a) n += s << 5; r[66] = n; #else - sp_digit n, s; + sp_digit n; + sp_digit s; int i; s = a[67]; n = a[66] >> 18; @@ -5456,7 +5488,6 @@ static void sp_3072_mont_reduce_67(sp_digit* a, const sp_digit* m, sp_digit mp) sp_3072_mul_add_67(a+i, m, mu); a[i+1] += a[i] >> 23; a[i] &= 0x7fffff; - sp_3072_mont_shift_67(a, a); sp_3072_cond_sub_67(a, a, m, 0 - (((a[66] >> 18) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -5472,8 +5503,8 @@ static void sp_3072_mont_reduce_67(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_67(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_67(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_67(r, a, b); sp_3072_mont_reduce_67(r, m, mp); @@ -5486,8 +5517,8 @@ static void sp_3072_mont_mul_67(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_67(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_67(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_67(r, a); sp_3072_mont_reduce_67(r, m, mp); @@ -5591,40 +5622,23 @@ static void sp_3072_cond_add_67(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 67; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif #ifdef WOLFSSL_SP_DIV_32 static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 23 bits from d1 and top 8 bits from d0. */ - d = (d1 << 8) | (d0 >> 15); + d = (d1 << 8) + (d0 >> 15); r = d / dv; d -= r * dv; /* Up to 9 bits in r */ /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 7) & ((1 << 8) - 1); + d += (d0 >> 7) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -5632,10 +5646,11 @@ static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0, /* Remaining 7 bits from d0. */ r <<= 7; d <<= 7; - d |= d0 & ((1 << 7) - 1); + d += d0 & ((1 << 7) - 1); t = d / dv; r += t; + /* All 23 bits from d1 and top 8 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -5643,66 +5658,60 @@ static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[134], t2d[67 + 1]; + sp_digit t1[3 * 67 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 67 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 67 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 67; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 67; dv = d[66]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 67U); for (i=66; i>=0; i--) { - sp_digit hi; t1[67 + i] += t1[67 + i - 1] >> 23; t1[67 + i - 1] &= 0x7fffff; - hi = t1[67 + i] - (t1[67 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[67 + i]; d1 <<= 23; d1 += t1[67 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_3072_div_word_67(hi, t1[67 + i - 1], dv); + r1 = sp_3072_div_word_67(t1[67 + i], t1[67 + i - 1], dv); #endif sp_3072_mul_d_67(t2, d, r1); (void)sp_3072_sub_67(&t1[i], &t1[i], t2); + sp_3072_norm_67(&t1[i]); t1[67 + i] -= t2[67]; t1[67 + i] += t1[67 + i - 1] >> 23; t1[67 + i - 1] &= 0x7fffff; @@ -5719,7 +5728,7 @@ static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_3072_mul_d_67(t2, d, r1); (void)sp_3072_sub_67(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 67U); + XMEMCPY(r, t1, sizeof(*r) * 134U); for (i=0; i<66; i++) { r[i+1] += r[i] >> 23; r[i] &= 0x7fffff; @@ -5728,10 +5737,9 @@ static int sp_3072_div_67(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -5762,35 +5770,31 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 134]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 67 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 67 * 2); -#else - t[i] = &td[i * 67 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 67U * 2U); } @@ -5845,43 +5849,38 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 134]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 67 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 67 * 2); -#else - t[i] = &td[i * 67 * 2]; -#endif } sp_3072_mont_setup(m, &mp); @@ -5935,47 +5934,40 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 67 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 134) + 134]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 134) + 134), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 134; rt = td + 4288; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 134]; - rt = &td[4288]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_67(norm, m); @@ -6046,7 +6038,7 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 134); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (9 - c); c += 23; @@ -6072,16 +6064,15 @@ static int sp_3072_mod_exp_67(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 3072 bits, just need to subtract. @@ -6353,7 +6344,7 @@ static void sp_3072_mont_reduce_134(sp_digit* a, const sp_digit* m, sp_digit mp) sp_3072_norm_134(a + 134); -#ifdef WOLFSSL_HAVE_SP_DH +#ifdef WOLFSSL_SP_DH if (mp != 1) { for (i=0; i<133; i++) { mu = (a[i] * mp) & 0x7fffff; @@ -6387,7 +6378,6 @@ static void sp_3072_mont_reduce_134(sp_digit* a, const sp_digit* m, sp_digit mp) a[i+1] += a[i] >> 23; a[i] &= 0x7fffff; #endif - sp_3072_mont_shift_134(a, a); sp_3072_cond_sub_134(a, a, m, 0 - (((a[133] >> 13) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -6403,8 +6393,8 @@ static void sp_3072_mont_reduce_134(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_134(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_134(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_134(r, a, b); sp_3072_mont_reduce_134(r, m, mp); @@ -6417,8 +6407,8 @@ static void sp_3072_mont_mul_134(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_134(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_134(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_134(r, a); sp_3072_mont_reduce_134(r, m, mp); @@ -6516,46 +6506,8 @@ static void sp_3072_cond_add_134(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 134; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 134; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -6565,20 +6517,20 @@ SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<128; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (23 - n)) & 0x7fffff); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (23 - n)) & 0x7fffff); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (23 - n)) & 0x7fffff); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (23 - n)) & 0x7fffff); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (23 - n)) & 0x7fffff); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (23 - n)) & 0x7fffff); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (23 - n)) & 0x7fffff); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (23 - n)) & 0x7fffff); } - r[128] = ((a[128] >> n) | (a[129] << (23 - n))) & 0x7fffff; - r[129] = ((a[129] >> n) | (a[130] << (23 - n))) & 0x7fffff; - r[130] = ((a[130] >> n) | (a[131] << (23 - n))) & 0x7fffff; - r[131] = ((a[131] >> n) | (a[132] << (23 - n))) & 0x7fffff; - r[132] = ((a[132] >> n) | (a[133] << (23 - n))) & 0x7fffff; + r[128] = (a[128] >> n) | ((a[129] << (23 - n)) & 0x7fffff); + r[129] = (a[129] >> n) | ((a[130] << (23 - n)) & 0x7fffff); + r[130] = (a[130] >> n) | ((a[131] << (23 - n)) & 0x7fffff); + r[131] = (a[131] >> n) | ((a[132] << (23 - n)) & 0x7fffff); + r[132] = (a[132] >> n) | ((a[133] << (23 - n)) & 0x7fffff); #endif r[133] = a[133] >> n; } @@ -6587,17 +6539,19 @@ SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 23 bits from d1 and top 8 bits from d0. */ - d = (d1 << 8) | (d0 >> 15); + d = (d1 << 8) + (d0 >> 15); r = d / dv; d -= r * dv; /* Up to 9 bits in r */ /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 7) & ((1 << 8) - 1); + d += (d0 >> 7) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -6605,10 +6559,11 @@ static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0, /* Remaining 7 bits from d0. */ r <<= 7; d <<= 7; - d |= d0 & ((1 << 7) - 1); + d += d0 & ((1 << 7) - 1); t = d / dv; r += t; + /* All 23 bits from d1 and top 8 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -6616,72 +6571,65 @@ static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[268 + 1], t2d[134 + 1], sdd[134 + 1]; + sp_digit t1[4 * 134 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 134 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 134 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 268 + 1; + t2 = t1 + 268 + 1; sd = t2 + 134 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_3072_mul_d_134(sd, d, 1L << 10); sp_3072_mul_d_268(t1, a, 1L << 10); dv = sd[133]; + t1[134 + 134] += t1[134 + 134 - 1] >> 23; + t1[134 + 134 - 1] &= 0x7fffff; for (i=134; i>=0; i--) { - sp_digit hi; - t1[134 + i] += t1[134 + i - 1] >> 23; - t1[134 + i - 1] &= 0x7fffff; - hi = t1[134 + i] - (t1[134 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[134 + i]; d1 <<= 23; d1 += t1[134 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_3072_div_word_134(hi, t1[134 + i - 1], dv); + r1 = sp_3072_div_word_134(t1[134 + i], t1[134 + i - 1], dv); #endif sp_3072_mul_d_134(t2, sd, r1); (void)sp_3072_sub_134(&t1[i], &t1[i], t2); + sp_3072_norm_134(&t1[i]); t1[134 + i] -= t2[134]; t1[134 + i] += t1[134 + i - 1] >> 23; t1[134 + i - 1] &= 0x7fffff; @@ -6698,7 +6646,7 @@ static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_3072_mul_d_134(t2, sd, r1); sp_3072_sub_134(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 134U); + XMEMCPY(r, t1, sizeof(*r) * 268U); for (i=0; i<133; i++) { r[i+1] += r[i] >> 23; r[i] &= 0x7fffff; @@ -6710,10 +6658,9 @@ static int sp_3072_div_134(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_3072_rshift_134(r, r, 10); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -6746,35 +6693,31 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 268]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 134 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 134 * 2); -#else - t[i] = &td[i * 134 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 134U * 2U); } @@ -6829,43 +6772,38 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 268]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 134 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 134 * 2); -#else - t[i] = &td[i * 134 * 2]; -#endif } sp_3072_mont_setup(m, &mp); @@ -6919,47 +6857,40 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e XMEMCPY(r, t[0], sizeof(*r) * 134 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 268) + 268]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 268) + 268), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 268; rt = td + 8576; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 268]; - rt = &td[8576]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_134(norm, m); @@ -7030,7 +6961,7 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 268); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (9 - c); c += 23; @@ -7056,15 +6987,14 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */ /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_RSA @@ -7080,15 +7010,18 @@ static int sp_3072_mod_exp_134(sp_digit* r, const sp_digit* a, const sp_digit* e * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[134 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -7113,15 +7046,16 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } +#endif if (err == MP_OKAY) { - a = d; r = a + 134 * 2; m = r + 134 * 2; norm = r; @@ -7174,20 +7108,21 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[268], md[134], rd[268]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[134 * 5]; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -7209,27 +7144,20 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { a = d; r = a + 134 * 2; m = r + 134 * 2; - } -#else - a = ad; - m = md; - r = rd; -#endif - if (err == MP_OKAY) { sp_3072_from_bin(a, 134, in, inLen); #if DIGIT_BIT >= 23 e[0] = (sp_digit)em->dp[0]; @@ -7293,10 +7221,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } #endif return err; @@ -7305,7 +7232,7 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #ifndef WOLFSSL_RSA_PUBLIC_ONLY #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) -#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */ /* RSA private key operation. * * in Array of bytes representing the number to exponentiate, base. @@ -7323,14 +7250,18 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a = NULL; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[134 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -7359,13 +7290,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 134; m = a + 268; @@ -7376,20 +7309,34 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_3072_from_mp(m, 134, mm); err = sp_3072_mod_exp_134(r, a, d, 3072, m, 0); } + if (err == MP_OKAY) { sp_3072_to_bin(r, out); *outLen = 384; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 134); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 134); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[268], d[134], m[134]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit d[134 * 4]; +#endif + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -7416,7 +7363,20 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + a = d + 134; + m = a + 268; + r = a; + sp_3072_from_bin(a, 134, in, inLen); sp_3072_from_mp(d, 134, dm); sp_3072_from_mp(m, 134, mm); @@ -7428,22 +7388,35 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } - XMEMSET(d, 0, sizeof(sp_digit) * 134); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 134); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #else -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[67 * 11]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -7464,22 +7437,21 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) { + if (a == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - a = t; p = a + 134 * 2; q = p + 67; qi = dq = dp = q + 67; tmpa = qi + 67; tmpb = tmpa + 134; - - r = t + 134; + r = a + 134; sp_3072_from_bin(a, 134, in, inLen); sp_3072_from_mp(p, 67, pm); @@ -7493,6 +7465,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } if (err == MP_OKAY) { (void)sp_3072_sub_67(tmpa, tmpa, tmpb); + sp_3072_norm_67(tmpa); sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); @@ -7510,17 +7483,31 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 67 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 67 * 11); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[134 * 2]; - sp_digit p[67], q[67], dp[67], dq[67], qi[67]; - sp_digit tmpa[134], tmpb[134]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[67 * 13]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -7541,7 +7528,25 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 13, NULL, + DYNAMIC_TYPE_RSA); + if (a == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = a + 134 * 2; + q = p + 67; + dp = q + 67; + dq = dp + 67; + qi = dq + 67; + tmpa = qi + 67; + tmpb = tmpa + 134; + r = a; + sp_3072_from_bin(a, 134, in, inLen); sp_3072_from_mp(p, 67, pm); sp_3072_from_mp(q, 67, qm); @@ -7557,6 +7562,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, if (err == MP_OKAY) { (void)sp_3072_sub_67(tmpa, tmpa, tmpb); + sp_3072_norm_67(tmpa); sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); sp_3072_mul_67(tmpa, tmpa, qi); @@ -7572,16 +7578,18 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); - XMEMSET(dq, 0, sizeof(dq)); - XMEMSET(qi, 0, sizeof(qi)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) +if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 67 * 13); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } @@ -7605,17 +7613,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 134; mp_clamp(r); #elif DIGIT_BIT < 23 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 134; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 23) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -7628,14 +7638,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 134; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 23 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -7662,15 +7674,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[134 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 3072) { @@ -7686,16 +7702,16 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 134 * 2; m = e + 134; r = b; @@ -7711,21 +7727,27 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_3072_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 134U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 134U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[268], ed[134], md[134]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[134 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -7742,26 +7764,19 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 134 * 2; - m = e + 134; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 134 * 2; + m = e + 134; + r = b; + sp_3072_from_mp(b, 134, base); sp_3072_from_mp(e, 134, exp); sp_3072_from_mp(m, 134, mod); @@ -7774,14 +7789,17 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 134U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 134U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 134U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -7790,7 +7808,8 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) #ifdef WOLFSSL_HAVE_SP_DH #ifdef HAVE_FFDHE_3072 -SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, const sp_digit* a, + byte n) { #ifdef WOLFSSL_SP_SMALL int i; @@ -7800,7 +7819,8 @@ SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, sp_digit* a, byte n) r[i] = ((a[i] << n) | (a[i-1] >> (23 - n))) & 0x7fffff; } #else - sp_int_digit s, t; + sp_int_digit s; + sp_int_digit t; s = (sp_int_digit)a[133]; r[134] = s >> (23U - n); @@ -8085,35 +8105,31 @@ SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, sp_digit* a, byte n) static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[403]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 403, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 268; XMEMSET(td, 0, sizeof(sp_digit) * 403); -#else - tmp = &td[268]; - XMEMSET(td, 0, sizeof(td)); -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_134(norm, m); @@ -8139,7 +8155,7 @@ static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const n <<= 4; c -= 4; sp_3072_lshift_134(r, norm, (byte)y); - for (; i>=0 || c>=4; ) { + while ((i >= 0) || (c >= 4)) { if (c < 4) { n |= e[i--] << (9 - c); c += 23; @@ -8171,9 +8187,8 @@ static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -8193,16 +8208,19 @@ static int sp_3072_mod_exp_2_134(sp_digit* r, const sp_digit* e, int bits, const * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[134 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; if (mp_count_bits(base) > 3072) { @@ -8218,15 +8236,15 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 134 * 2; m = e + 134; r = b; @@ -8254,21 +8272,27 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, XMEMMOVE(out, out + i, *outLen); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 134U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 134U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[268], ed[134], md[134]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[134 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; int err = MP_OKAY; @@ -8285,26 +8309,20 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 134 * 2; - m = e + 134; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 134 * 2; + m = e + 134; + r = b; + sp_3072_from_mp(b, 134, base); sp_3072_from_bin(e, 134, exp, expLen); sp_3072_from_mp(m, 134, mod); @@ -8326,19 +8344,23 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384U && out[i] == 0U; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 134U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 134U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 134U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -8354,15 +8376,19 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[67 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 1536) { @@ -8378,16 +8404,16 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 67 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 67 * 2; m = e + 67; r = b; @@ -8404,21 +8430,27 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_3072_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 67U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 134U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[134], ed[67], md[67]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[67 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -8435,26 +8467,19 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 67 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 67 * 2; - m = e + 67; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 67 * 2; + m = e + 67; + r = b; + sp_3072_from_mp(b, 67, base); sp_3072_from_mp(e, 67, exp); sp_3072_from_mp(m, 67, mod); @@ -8468,20 +8493,23 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 67U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 67U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 134U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -8495,7 +8523,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -8537,7 +8566,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 21 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -8571,7 +8601,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -8610,7 +8642,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_4096_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<195; i++) { r[i+1] += r[i] >> 21; @@ -8653,7 +8688,8 @@ static void sp_4096_to_bin(sp_digit* r, byte* a) SP_NOINLINE static void sp_4096_mul_49(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j; + int i; + int j; int64_t t[98]; XMEMSET(t, 0, sizeof(t)); @@ -8676,7 +8712,8 @@ SP_NOINLINE static void sp_4096_mul_49(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_4096_sqr_49(sp_digit* r, const sp_digit* a) { - int i, j; + int i; + int j; int64_t t[98]; XMEMSET(t, 0, sizeof(t)); @@ -8969,7 +9006,9 @@ SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_4096_mul_196(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[195]) * b[195]; @@ -9001,7 +9040,9 @@ SP_NOINLINE static void sp_4096_mul_196(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_4096_sqr_196(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[195]) * a[195]; @@ -9082,7 +9123,9 @@ SP_NOINLINE static int sp_4096_sub_98(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_4096_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[97]) * b[97]; @@ -9114,7 +9157,9 @@ SP_NOINLINE static void sp_4096_mul_98(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_4096_sqr_98(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[97]) * a[97]; @@ -9144,8 +9189,8 @@ SP_NOINLINE static void sp_4096_sqr_98(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -9154,7 +9199,8 @@ SP_NOINLINE static void sp_4096_sqr_98(sp_digit* r, const sp_digit* a) */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -9477,7 +9523,6 @@ static void sp_4096_mont_reduce_98(sp_digit* a, const sp_digit* m, sp_digit mp) sp_4096_mul_add_98(a+i, m, mu); a[i+1] += a[i] >> 21; a[i] &= 0x1fffff; - sp_4096_mont_shift_98(a, a); sp_4096_cond_sub_98(a, a, m, 0 - (((a[97] >> 11) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -9493,8 +9538,8 @@ static void sp_4096_mont_reduce_98(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_98(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_98(r, a, b); sp_4096_mont_reduce_98(r, m, mp); @@ -9507,8 +9552,8 @@ static void sp_4096_mont_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_98(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_98(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_98(r, a); sp_4096_mont_reduce_98(r, m, mp); @@ -9608,46 +9653,8 @@ static void sp_4096_cond_add_98(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_sub_98(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 98; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_add_98(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 98; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -9657,16 +9664,16 @@ SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<96; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (21 - n))) & 0x1fffff; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (21 - n))) & 0x1fffff; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (21 - n))) & 0x1fffff; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (21 - n))) & 0x1fffff; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (21 - n))) & 0x1fffff; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (21 - n))) & 0x1fffff; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (21 - n))) & 0x1fffff; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (21 - n))) & 0x1fffff; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (21 - n)) & 0x1fffff); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (21 - n)) & 0x1fffff); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (21 - n)) & 0x1fffff); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (21 - n)) & 0x1fffff); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (21 - n)) & 0x1fffff); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (21 - n)) & 0x1fffff); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (21 - n)) & 0x1fffff); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (21 - n)) & 0x1fffff); } - r[96] = ((a[96] >> n) | (a[97] << (21 - n))) & 0x1fffff; + r[96] = (a[96] >> n) | ((a[97] << (21 - n)) & 0x1fffff); #endif r[97] = a[97] >> n; } @@ -9675,17 +9682,19 @@ SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_4096_div_word_98(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 21 bits from d1 and top 10 bits from d0. */ - d = (d1 << 10) | (d0 >> 11); + d = (d1 << 10) + (d0 >> 11); r = d / dv; d -= r * dv; /* Up to 11 bits in r */ /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 1) & ((1 << 10) - 1); + d += (d0 >> 1) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -9693,10 +9702,11 @@ static WC_INLINE sp_digit sp_4096_div_word_98(sp_digit d1, sp_digit d0, /* Remaining 1 bits from d0. */ r <<= 1; d <<= 1; - d |= d0 & ((1 << 1) - 1); + d += d0 & ((1 << 1) - 1); t = d / dv; r += t; + /* All 21 bits from d1 and top 10 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -9704,72 +9714,65 @@ static WC_INLINE sp_digit sp_4096_div_word_98(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[196 + 1], t2d[98 + 1], sdd[98 + 1]; + sp_digit t1[4 * 98 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 98 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 98 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 196 + 1; + t2 = t1 + 196 + 1; sd = t2 + 98 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_4096_mul_d_98(sd, d, 1L << 10); sp_4096_mul_d_196(t1, a, 1L << 10); dv = sd[97]; + t1[98 + 98] += t1[98 + 98 - 1] >> 21; + t1[98 + 98 - 1] &= 0x1fffff; for (i=98; i>=0; i--) { - sp_digit hi; - t1[98 + i] += t1[98 + i - 1] >> 21; - t1[98 + i - 1] &= 0x1fffff; - hi = t1[98 + i] - (t1[98 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[98 + i]; d1 <<= 21; d1 += t1[98 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_4096_div_word_98(hi, t1[98 + i - 1], dv); + r1 = sp_4096_div_word_98(t1[98 + i], t1[98 + i - 1], dv); #endif sp_4096_mul_d_98(t2, sd, r1); (void)sp_4096_sub_98(&t1[i], &t1[i], t2); + sp_4096_norm_98(&t1[i]); t1[98 + i] -= t2[98]; t1[98 + i] += t1[98 + i - 1] >> 21; t1[98 + i - 1] &= 0x1fffff; @@ -9786,7 +9789,7 @@ static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_mul_d_98(t2, sd, r1); sp_4096_sub_98(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 98U); + XMEMCPY(r, t1, sizeof(*r) * 196U); for (i=0; i<97; i++) { r[i+1] += r[i] >> 21; r[i] &= 0x1fffff; @@ -9798,10 +9801,9 @@ static int sp_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_rshift_98(r, r, 10); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -9832,35 +9834,31 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 196]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 98 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 98 * 2); -#else - t[i] = &td[i * 98 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 98U * 2U); } @@ -9915,43 +9913,38 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 196]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 98 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 98 * 2); -#else - t[i] = &td[i * 98 * 2]; -#endif } sp_4096_mont_setup(m, &mp); @@ -10005,47 +9998,40 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 98 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 196) + 196]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 196) + 196), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 196; rt = td + 6272; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 196]; - rt = &td[6272]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_98(norm, m); @@ -10116,7 +10102,7 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 196); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (11 - c); c += 21; @@ -10142,17 +10128,16 @@ static int sp_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */ /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 4096 bits, just need to subtract. @@ -10412,7 +10397,7 @@ static void sp_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp) sp_4096_norm_196(a + 196); -#ifdef WOLFSSL_HAVE_SP_DH +#ifdef WOLFSSL_SP_DH if (mp != 1) { for (i=0; i<195; i++) { mu = (a[i] * mp) & 0x1fffff; @@ -10446,7 +10431,6 @@ static void sp_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp) a[i+1] += a[i] >> 21; a[i] &= 0x1fffff; #endif - sp_4096_mont_shift_196(a, a); sp_4096_cond_sub_196(a, a, m, 0 - (((a[195] >> 1) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -10462,8 +10446,8 @@ static void sp_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_196(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_196(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_196(r, a, b); sp_4096_mont_reduce_196(r, m, mp); @@ -10476,8 +10460,8 @@ static void sp_4096_mont_mul_196(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_196(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_196(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_196(r, a); sp_4096_mont_reduce_196(r, m, mp); @@ -10573,46 +10557,8 @@ static void sp_4096_cond_add_196(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 196; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_add_196(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 196; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -10622,18 +10568,18 @@ SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<192; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (21 - n))) & 0x1fffff; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (21 - n))) & 0x1fffff; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (21 - n))) & 0x1fffff; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (21 - n))) & 0x1fffff; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (21 - n))) & 0x1fffff; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (21 - n))) & 0x1fffff; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (21 - n))) & 0x1fffff; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (21 - n))) & 0x1fffff; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (21 - n)) & 0x1fffff); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (21 - n)) & 0x1fffff); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (21 - n)) & 0x1fffff); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (21 - n)) & 0x1fffff); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (21 - n)) & 0x1fffff); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (21 - n)) & 0x1fffff); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (21 - n)) & 0x1fffff); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (21 - n)) & 0x1fffff); } - r[192] = ((a[192] >> n) | (a[193] << (21 - n))) & 0x1fffff; - r[193] = ((a[193] >> n) | (a[194] << (21 - n))) & 0x1fffff; - r[194] = ((a[194] >> n) | (a[195] << (21 - n))) & 0x1fffff; + r[192] = (a[192] >> n) | ((a[193] << (21 - n)) & 0x1fffff); + r[193] = (a[193] >> n) | ((a[194] << (21 - n)) & 0x1fffff); + r[194] = (a[194] >> n) | ((a[195] << (21 - n)) & 0x1fffff); #endif r[195] = a[195] >> n; } @@ -10642,17 +10588,19 @@ SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_4096_div_word_196(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 21 bits from d1 and top 10 bits from d0. */ - d = (d1 << 10) | (d0 >> 11); + d = (d1 << 10) + (d0 >> 11); r = d / dv; d -= r * dv; /* Up to 11 bits in r */ /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 1) & ((1 << 10) - 1); + d += (d0 >> 1) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -10660,10 +10608,11 @@ static WC_INLINE sp_digit sp_4096_div_word_196(sp_digit d1, sp_digit d0, /* Remaining 1 bits from d0. */ r <<= 1; d <<= 1; - d |= d0 & ((1 << 1) - 1); + d += d0 & ((1 << 1) - 1); t = d / dv; r += t; + /* All 21 bits from d1 and top 10 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -10671,72 +10620,65 @@ static WC_INLINE sp_digit sp_4096_div_word_196(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[392 + 1], t2d[196 + 1], sdd[196 + 1]; + sp_digit t1[4 * 196 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 196 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 196 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 392 + 1; + t2 = t1 + 392 + 1; sd = t2 + 196 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_4096_mul_d_196(sd, d, 1L << 20); sp_4096_mul_d_392(t1, a, 1L << 20); dv = sd[195]; + t1[196 + 196] += t1[196 + 196 - 1] >> 21; + t1[196 + 196 - 1] &= 0x1fffff; for (i=196; i>=0; i--) { - sp_digit hi; - t1[196 + i] += t1[196 + i - 1] >> 21; - t1[196 + i - 1] &= 0x1fffff; - hi = t1[196 + i] - (t1[196 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[196 + i]; d1 <<= 21; d1 += t1[196 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_4096_div_word_196(hi, t1[196 + i - 1], dv); + r1 = sp_4096_div_word_196(t1[196 + i], t1[196 + i - 1], dv); #endif sp_4096_mul_d_196(t2, sd, r1); (void)sp_4096_sub_196(&t1[i], &t1[i], t2); + sp_4096_norm_196(&t1[i]); t1[196 + i] -= t2[196]; t1[196 + i] += t1[196 + i - 1] >> 21; t1[196 + i - 1] &= 0x1fffff; @@ -10753,7 +10695,7 @@ static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_mul_d_196(t2, sd, r1); sp_4096_sub_196(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 196U); + XMEMCPY(r, t1, sizeof(*r) * 392U); for (i=0; i<195; i++) { r[i+1] += r[i] >> 21; r[i] &= 0x1fffff; @@ -10765,10 +10707,9 @@ static int sp_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_rshift_196(r, r, 20); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -10801,35 +10742,31 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 392]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 196 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 196 * 2); -#else - t[i] = &td[i * 196 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 196U * 2U); } @@ -10884,43 +10821,38 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 392]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 196 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 196 * 2); -#else - t[i] = &td[i * 196 * 2]; -#endif } sp_4096_mont_setup(m, &mp); @@ -10974,47 +10906,40 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e XMEMCPY(r, t[0], sizeof(*r) * 196 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 392) + 392]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 392) + 392), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 392; rt = td + 12544; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 392]; - rt = &td[12544]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_196(norm, m); @@ -11085,7 +11010,7 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 392); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (11 - c); c += 21; @@ -11111,15 +11036,14 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */ /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_RSA @@ -11135,15 +11059,18 @@ static int sp_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[196 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -11168,15 +11095,16 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } +#endif if (err == MP_OKAY) { - a = d; r = a + 196 * 2; m = r + 196 * 2; norm = r; @@ -11229,20 +11157,21 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[392], md[196], rd[392]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[196 * 5]; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -11264,27 +11193,20 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { a = d; r = a + 196 * 2; m = r + 196 * 2; - } -#else - a = ad; - m = md; - r = rd; -#endif - if (err == MP_OKAY) { sp_4096_from_bin(a, 196, in, inLen); #if DIGIT_BIT >= 21 e[0] = (sp_digit)em->dp[0]; @@ -11348,10 +11270,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } #endif return err; @@ -11360,7 +11281,7 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #ifndef WOLFSSL_RSA_PUBLIC_ONLY #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) -#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */ /* RSA private key operation. * * in Array of bytes representing the number to exponentiate, base. @@ -11378,14 +11299,18 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a = NULL; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[196 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -11414,13 +11339,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 196; m = a + 392; @@ -11431,20 +11358,34 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_4096_from_mp(m, 196, mm); err = sp_4096_mod_exp_196(r, a, d, 4096, m, 0); } + if (err == MP_OKAY) { sp_4096_to_bin(r, out); *outLen = 512; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 196); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 196); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[392], d[196], m[196]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit d[196 * 4]; +#endif + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -11471,7 +11412,20 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + a = d + 196; + m = a + 392; + r = a; + sp_4096_from_bin(a, 196, in, inLen); sp_4096_from_mp(d, 196, dm); sp_4096_from_mp(m, 196, mm); @@ -11483,22 +11437,35 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } - XMEMSET(d, 0, sizeof(sp_digit) * 196); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 196); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #else -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[98 * 11]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -11519,22 +11486,21 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) { + if (a == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - a = t; p = a + 196 * 2; q = p + 98; qi = dq = dp = q + 98; tmpa = qi + 98; tmpb = tmpa + 196; - - r = t + 196; + r = a + 196; sp_4096_from_bin(a, 196, in, inLen); sp_4096_from_mp(p, 98, pm); @@ -11548,6 +11514,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } if (err == MP_OKAY) { (void)sp_4096_sub_98(tmpa, tmpa, tmpb); + sp_4096_norm_98(tmpa); sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); @@ -11565,17 +11532,31 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 98 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 98 * 11); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[196 * 2]; - sp_digit p[98], q[98], dp[98], dq[98], qi[98]; - sp_digit tmpa[196], tmpb[196]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[98 * 13]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -11596,7 +11577,25 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 13, NULL, + DYNAMIC_TYPE_RSA); + if (a == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = a + 196 * 2; + q = p + 98; + dp = q + 98; + dq = dp + 98; + qi = dq + 98; + tmpa = qi + 98; + tmpb = tmpa + 196; + r = a; + sp_4096_from_bin(a, 196, in, inLen); sp_4096_from_mp(p, 98, pm); sp_4096_from_mp(q, 98, qm); @@ -11612,6 +11611,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, if (err == MP_OKAY) { (void)sp_4096_sub_98(tmpa, tmpa, tmpb); + sp_4096_norm_98(tmpa); sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); sp_4096_mul_98(tmpa, tmpa, qi); @@ -11627,16 +11627,18 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); - XMEMSET(dq, 0, sizeof(dq)); - XMEMSET(qi, 0, sizeof(qi)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) +if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 98 * 13); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } @@ -11660,17 +11662,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 196; mp_clamp(r); #elif DIGIT_BIT < 21 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 196; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 21) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -11683,14 +11687,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 196; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 21 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -11717,15 +11723,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[196 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 4096) { @@ -11741,16 +11751,16 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 196 * 2; m = e + 196; r = b; @@ -11766,21 +11776,27 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_4096_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 196U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 196U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[392], ed[196], md[196]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[196 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -11797,26 +11813,19 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 196 * 2; - m = e + 196; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 196 * 2; + m = e + 196; + r = b; + sp_4096_from_mp(b, 196, base); sp_4096_from_mp(e, 196, exp); sp_4096_from_mp(m, 196, mod); @@ -11829,14 +11838,17 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 196U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 196U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 196U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -11845,7 +11857,8 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) #ifdef WOLFSSL_HAVE_SP_DH #ifdef HAVE_FFDHE_4096 -SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, const sp_digit* a, + byte n) { #ifdef WOLFSSL_SP_SMALL int i; @@ -11855,7 +11868,8 @@ SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, sp_digit* a, byte n) r[i] = ((a[i] << n) | (a[i-1] >> (21 - n))) & 0x1fffff; } #else - sp_int_digit s, t; + sp_int_digit s; + sp_int_digit t; s = (sp_int_digit)a[195]; r[196] = s >> (21U - n); @@ -12264,35 +12278,31 @@ SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, sp_digit* a, byte n) static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[589]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 589, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 392; XMEMSET(td, 0, sizeof(sp_digit) * 589); -#else - tmp = &td[392]; - XMEMSET(td, 0, sizeof(td)); -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_196(norm, m); @@ -12318,7 +12328,7 @@ static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const n <<= 4; c -= 4; sp_4096_lshift_196(r, norm, (byte)y); - for (; i>=0 || c>=4; ) { + while ((i >= 0) || (c >= 4)) { if (c < 4) { n |= e[i--] << (11 - c); c += 21; @@ -12350,9 +12360,8 @@ static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -12372,16 +12381,19 @@ static int sp_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[196 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; if (mp_count_bits(base) > 4096) { @@ -12397,15 +12409,15 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 196 * 2; m = e + 196; r = b; @@ -12433,21 +12445,27 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, XMEMMOVE(out, out + i, *outLen); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 196U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 196U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[392], ed[196], md[196]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[196 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; int err = MP_OKAY; @@ -12464,26 +12482,20 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 196 * 2; - m = e + 196; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 196 * 2; + m = e + 196; + r = b; + sp_4096_from_mp(b, 196, base); sp_4096_from_bin(e, 196, exp, expLen); sp_4096_from_mp(m, 196, mod); @@ -12505,38 +12517,46 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512U && out[i] == 0U; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 196U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 196U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 196U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif } #endif /* WOLFSSL_HAVE_SP_DH */ -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 10]; + /* Y ordinate of point. */ sp_digit y[2 * 10]; + /* Z ordinate of point. */ sp_digit z[2 * 10]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -12606,370 +12626,6 @@ static const sp_digit p256_b[10] = { }; #endif -static int sp_256_point_new_ex_10(void* heap, sp_point_256* sp, sp_point_256** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_10(sp_point_256* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* td; -#else - int64_t td[8]; - int64_t a32d[8]; -#endif - int64_t* t; - int64_t* a32; - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); - if (td == NULL) { - return MEMORY_E; - } -#endif - - if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = td; - a32 = td + 8; -#else - t = td; - a32 = a32d; -#endif - - a32[0] = a[0]; - a32[0] |= a[1] << 26U; - a32[0] &= 0xffffffffL; - a32[1] = (sp_digit)(a[1] >> 6); - a32[1] |= a[2] << 20U; - a32[1] &= 0xffffffffL; - a32[2] = (sp_digit)(a[2] >> 12); - a32[2] |= a[3] << 14U; - a32[2] &= 0xffffffffL; - a32[3] = (sp_digit)(a[3] >> 18); - a32[3] |= a[4] << 8U; - a32[3] &= 0xffffffffL; - a32[4] = (sp_digit)(a[4] >> 24); - a32[4] |= a[5] << 2U; - a32[4] |= a[6] << 28U; - a32[4] &= 0xffffffffL; - a32[5] = (sp_digit)(a[6] >> 4); - a32[5] |= a[7] << 22U; - a32[5] &= 0xffffffffL; - a32[6] = (sp_digit)(a[7] >> 10); - a32[6] |= a[8] << 16U; - a32[6] &= 0xffffffffL; - a32[7] = (sp_digit)(a[8] >> 16); - a32[7] |= a[9] << 10U; - a32[7] &= 0xffffffffL; - - /* 1 1 0 -1 -1 -1 -1 0 */ - t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; - /* 0 1 1 0 -1 -1 -1 -1 */ - t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; - /* 0 0 1 1 0 -1 -1 -1 */ - t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; - /* -1 -1 0 2 2 1 0 -1 */ - t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; - /* 0 -1 -1 0 2 2 1 0 */ - t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; - /* 0 0 -1 -1 0 2 2 1 */ - t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; - /* -1 -1 0 0 0 1 3 2 */ - t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; - /* 1 0 -1 -1 -1 -1 0 3 */ - t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; - - t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; - t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; - t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; - t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; - t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; - t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; - t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; - o = t[7] >> 32U; t[7] &= 0xffffffffL; - t[0] += o; - t[3] -= o; - t[6] -= o; - t[7] += o; - t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; - t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; - t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; - t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; - t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; - t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; - t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; - - r[0] = (sp_digit)(t[0]) & 0x3ffffffL; - r[1] = (sp_digit)(t[0] >> 26U); - r[1] |= (sp_digit)(t[1] << 6U); - r[1] &= 0x3ffffffL; - r[2] = (sp_digit)(t[1] >> 20U); - r[2] |= (sp_digit)(t[2] << 12U); - r[2] &= 0x3ffffffL; - r[3] = (sp_digit)(t[2] >> 14U); - r[3] |= (sp_digit)(t[3] << 18U); - r[3] &= 0x3ffffffL; - r[4] = (sp_digit)(t[3] >> 8U); - r[4] |= (sp_digit)(t[4] << 24U); - r[4] &= 0x3ffffffL; - r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; - r[6] = (sp_digit)(t[4] >> 28U); - r[6] |= (sp_digit)(t[5] << 4U); - r[6] &= 0x3ffffffL; - r[7] = (sp_digit)(t[5] >> 22U); - r[7] |= (sp_digit)(t[6] << 10U); - r[7] &= 0x3ffffffL; - r[8] = (sp_digit)(t[6] >> 16U); - r[8] |= (sp_digit)(t[7] << 16U); - r[8] &= 0x3ffffffL; - r[9] = (sp_digit)(t[7] >> 10U); - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_ECC); - } -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 26 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 26 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x3ffffff; - s = 26U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 26U) <= (word32)DIGIT_BIT) { - s += 26U; - r[j] &= 0x3ffffff; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 26) { - r[j] &= 0x3ffffff; - if (j + 1 >= size) { - break; - } - s = 26 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_256. - * - * p Point of type sp_point_256 (result). - * pm Point of type ecc_point. - */ -static void sp_256_point_from_ecc_point_10(sp_point_256* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_256_from_mp(p->x, 10, pm->x); - sp_256_from_mp(p->y, 10, pm->y); - sp_256_from_mp(p->z, 10, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_256_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 26 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 10); - r->used = 10; - mp_clamp(r); -#elif DIGIT_BIT < 26 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 10; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 26) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 26 - s; - } - r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 10; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 26 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 26 - s; - } - else { - s += 26; - } - } - r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_256 to type ecc_point. - * - * p Point of type sp_point_256. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_256_point_to_ecc_point_10(const sp_point_256* p, ecc_point* pm) -{ - int err; - - err = sp_256_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, pm->z); - } - - return err; -} - #ifdef WOLFSSL_SP_SMALL /* Multiply a and b into r. (r = a * b) * @@ -12980,7 +12636,9 @@ static int sp_256_point_to_ecc_point_10(const sp_point_256* p, ecc_point* pm) SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[9]) * b[9]; @@ -13139,6 +12797,411 @@ SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a, } #endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int i; + int j; + int k; + int64_t c; + + c = ((int64_t)a[9]) * a[9]; + r[19] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 17; k >= 0; k--) { + for (i = 9; i >= 0; i--) { + j = k - i; + if (j >= 10 || i <= j) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) { + c += ((int64_t)a[i]) * a[i]; + } + + r[k + 2] += (sp_digit)(c >> 52); + r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff); + c = (c & 0x3ffffff) << 26; + } + r[0] = (sp_digit)(c >> 26); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; + int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; + int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 + + ((int64_t)a[ 1]) * a[ 1]; + int64_t t3 = (((int64_t)a[ 0]) * a[ 3] + + ((int64_t)a[ 1]) * a[ 2]) * 2; + int64_t t4 = (((int64_t)a[ 0]) * a[ 4] + + ((int64_t)a[ 1]) * a[ 3]) * 2 + + ((int64_t)a[ 2]) * a[ 2]; + int64_t t5 = (((int64_t)a[ 0]) * a[ 5] + + ((int64_t)a[ 1]) * a[ 4] + + ((int64_t)a[ 2]) * a[ 3]) * 2; + int64_t t6 = (((int64_t)a[ 0]) * a[ 6] + + ((int64_t)a[ 1]) * a[ 5] + + ((int64_t)a[ 2]) * a[ 4]) * 2 + + ((int64_t)a[ 3]) * a[ 3]; + int64_t t7 = (((int64_t)a[ 0]) * a[ 7] + + ((int64_t)a[ 1]) * a[ 6] + + ((int64_t)a[ 2]) * a[ 5] + + ((int64_t)a[ 3]) * a[ 4]) * 2; + int64_t t8 = (((int64_t)a[ 0]) * a[ 8] + + ((int64_t)a[ 1]) * a[ 7] + + ((int64_t)a[ 2]) * a[ 6] + + ((int64_t)a[ 3]) * a[ 5]) * 2 + + ((int64_t)a[ 4]) * a[ 4]; + int64_t t9 = (((int64_t)a[ 0]) * a[ 9] + + ((int64_t)a[ 1]) * a[ 8] + + ((int64_t)a[ 2]) * a[ 7] + + ((int64_t)a[ 3]) * a[ 6] + + ((int64_t)a[ 4]) * a[ 5]) * 2; + int64_t t10 = (((int64_t)a[ 1]) * a[ 9] + + ((int64_t)a[ 2]) * a[ 8] + + ((int64_t)a[ 3]) * a[ 7] + + ((int64_t)a[ 4]) * a[ 6]) * 2 + + ((int64_t)a[ 5]) * a[ 5]; + int64_t t11 = (((int64_t)a[ 2]) * a[ 9] + + ((int64_t)a[ 3]) * a[ 8] + + ((int64_t)a[ 4]) * a[ 7] + + ((int64_t)a[ 5]) * a[ 6]) * 2; + int64_t t12 = (((int64_t)a[ 3]) * a[ 9] + + ((int64_t)a[ 4]) * a[ 8] + + ((int64_t)a[ 5]) * a[ 7]) * 2 + + ((int64_t)a[ 6]) * a[ 6]; + int64_t t13 = (((int64_t)a[ 4]) * a[ 9] + + ((int64_t)a[ 5]) * a[ 8] + + ((int64_t)a[ 6]) * a[ 7]) * 2; + int64_t t14 = (((int64_t)a[ 5]) * a[ 9] + + ((int64_t)a[ 6]) * a[ 8]) * 2 + + ((int64_t)a[ 7]) * a[ 7]; + int64_t t15 = (((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = ((int64_t)a[ 9]) * a[ 9]; + + t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; + t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; + t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; + t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; + t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; + t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; + t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; + t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; + t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; + t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; + t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; + t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; + t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; + t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; + t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; + t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; + t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; + t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; + r[19] = (sp_digit)(t18 >> 26); + r[18] = t18 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 10; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + r[ 9] = a[ 9] + b[ 9]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 10; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + r[ 5] = a[ 5] - b[ 5]; + r[ 6] = a[ 6] - b[ 6]; + r[ 7] = a[ 7] - b[ 7]; + r[ 8] = a[ 8] - b[ 8]; + r[ 9] = a[ 9] - b[ 9]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 26 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 26U) <= (word32)DIGIT_BIT) { + s += 26U; + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + s = 26 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_10(sp_point_256* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 10, pm->x); + sp_256_from_mp(p->y, 10, pm->y); + sp_256_from_mp(p->z, 10, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 26 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 10); + r->used = 10; + mp_clamp(r); +#elif DIGIT_BIT < 26 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 10; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 26) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 26 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 10; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 26 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 26 - s; + } + else { + s += 26; + } + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_256 to type ecc_point. + * + * p Point of type sp_point_256. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_10(const sp_point_256* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pm->z); + } + + return err; +} + #define sp_256_mont_reduce_order_10 sp_256_mont_reduce_10 /* Compare a with b in constant time. @@ -13286,7 +13349,8 @@ static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; - sp_digit n, s; + sp_digit n; + sp_digit s; s = a[10]; n = a[9] >> 22; @@ -13299,7 +13363,8 @@ static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) n += s << 4; r[9] = n; #else - sp_digit n, s; + sp_digit n; + sp_digit s; s = a[10]; n = a[9] >> 22; n += (s & 0x3ffffff) << 4; r[ 0] = n & 0x3ffffff; @@ -13374,137 +13439,13 @@ static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_256_mul_10(r, a, b); sp_256_mont_reduce_10(r, m, mp); } -#ifdef WOLFSSL_SP_SMALL -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) -{ - int i, j, k; - int64_t c; - - c = ((int64_t)a[9]) * a[9]; - r[19] = (sp_digit)(c >> 26); - c = (c & 0x3ffffff) << 26; - for (k = 17; k >= 0; k--) { - for (i = 9; i >= 0; i--) { - j = k - i; - if (j >= 10 || i <= j) { - break; - } - if (j < 0) { - continue; - } - - c += ((int64_t)a[i]) * a[j] * 2; - } - if (i == j) { - c += ((int64_t)a[i]) * a[i]; - } - - r[k + 2] += (sp_digit)(c >> 52); - r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff); - c = (c & 0x3ffffff) << 26; - } - r[0] = (sp_digit)(c >> 26); -} - -#else -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) -{ - int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; - int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; - int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 - + ((int64_t)a[ 1]) * a[ 1]; - int64_t t3 = (((int64_t)a[ 0]) * a[ 3] - + ((int64_t)a[ 1]) * a[ 2]) * 2; - int64_t t4 = (((int64_t)a[ 0]) * a[ 4] - + ((int64_t)a[ 1]) * a[ 3]) * 2 - + ((int64_t)a[ 2]) * a[ 2]; - int64_t t5 = (((int64_t)a[ 0]) * a[ 5] - + ((int64_t)a[ 1]) * a[ 4] - + ((int64_t)a[ 2]) * a[ 3]) * 2; - int64_t t6 = (((int64_t)a[ 0]) * a[ 6] - + ((int64_t)a[ 1]) * a[ 5] - + ((int64_t)a[ 2]) * a[ 4]) * 2 - + ((int64_t)a[ 3]) * a[ 3]; - int64_t t7 = (((int64_t)a[ 0]) * a[ 7] - + ((int64_t)a[ 1]) * a[ 6] - + ((int64_t)a[ 2]) * a[ 5] - + ((int64_t)a[ 3]) * a[ 4]) * 2; - int64_t t8 = (((int64_t)a[ 0]) * a[ 8] - + ((int64_t)a[ 1]) * a[ 7] - + ((int64_t)a[ 2]) * a[ 6] - + ((int64_t)a[ 3]) * a[ 5]) * 2 - + ((int64_t)a[ 4]) * a[ 4]; - int64_t t9 = (((int64_t)a[ 0]) * a[ 9] - + ((int64_t)a[ 1]) * a[ 8] - + ((int64_t)a[ 2]) * a[ 7] - + ((int64_t)a[ 3]) * a[ 6] - + ((int64_t)a[ 4]) * a[ 5]) * 2; - int64_t t10 = (((int64_t)a[ 1]) * a[ 9] - + ((int64_t)a[ 2]) * a[ 8] - + ((int64_t)a[ 3]) * a[ 7] - + ((int64_t)a[ 4]) * a[ 6]) * 2 - + ((int64_t)a[ 5]) * a[ 5]; - int64_t t11 = (((int64_t)a[ 2]) * a[ 9] - + ((int64_t)a[ 3]) * a[ 8] - + ((int64_t)a[ 4]) * a[ 7] - + ((int64_t)a[ 5]) * a[ 6]) * 2; - int64_t t12 = (((int64_t)a[ 3]) * a[ 9] - + ((int64_t)a[ 4]) * a[ 8] - + ((int64_t)a[ 5]) * a[ 7]) * 2 - + ((int64_t)a[ 6]) * a[ 6]; - int64_t t13 = (((int64_t)a[ 4]) * a[ 9] - + ((int64_t)a[ 5]) * a[ 8] - + ((int64_t)a[ 6]) * a[ 7]) * 2; - int64_t t14 = (((int64_t)a[ 5]) * a[ 9] - + ((int64_t)a[ 6]) * a[ 8]) * 2 - + ((int64_t)a[ 7]) * a[ 7]; - int64_t t15 = (((int64_t)a[ 6]) * a[ 9] - + ((int64_t)a[ 7]) * a[ 8]) * 2; - int64_t t16 = (((int64_t)a[ 7]) * a[ 9]) * 2 - + ((int64_t)a[ 8]) * a[ 8]; - int64_t t17 = (((int64_t)a[ 8]) * a[ 9]) * 2; - int64_t t18 = ((int64_t)a[ 9]) * a[ 9]; - - t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; - t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; - t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; - t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; - t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; - t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; - t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; - t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; - t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; - t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; - t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; - t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; - t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; - t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; - t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; - t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; - t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; - t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; - r[19] = (sp_digit)(t18 >> 26); - r[18] = t18 & 0x3ffffff; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -13512,8 +13453,8 @@ SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_256_sqr_10(r, a); sp_256_mont_reduce_10(r, m, mp); @@ -13537,7 +13478,7 @@ static void sp_256_mont_sqr_n_10(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint32_t p256_mod_minus_2[8] = { @@ -13621,7 +13562,8 @@ static void sp_256_mont_inv_10(sp_digit* r, const sp_digit* a, sp_digit* td) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_10(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_10(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*10; @@ -13657,49 +13599,6 @@ static void sp_256_map_10(sp_point_256* r, const sp_point_256* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 10; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] + b[ 0]; - r[ 1] = a[ 1] + b[ 1]; - r[ 2] = a[ 2] + b[ 2]; - r[ 3] = a[ 3] + b[ 3]; - r[ 4] = a[ 4] + b[ 4]; - r[ 5] = a[ 5] + b[ 5]; - r[ 6] = a[ 6] + b[ 6]; - r[ 7] = a[ 7] + b[ 7]; - r[ 8] = a[ 8] + b[ 8]; - r[ 9] = a[ 9] + b[ 9]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -13752,50 +13651,6 @@ static void sp_256_mont_tpl_10(sp_digit* r, const sp_digit* a, const sp_digit* m sp_256_norm_10(r); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 10; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] - b[ 0]; - r[ 1] = a[ 1] - b[ 1]; - r[ 2] = a[ 2] - b[ 2]; - r[ 3] = a[ 3] - b[ 3]; - r[ 4] = a[ 4] - b[ 4]; - r[ 5] = a[ 5] - b[ 5]; - r[ 6] = a[ 6] - b[ 6]; - r[ 7] = a[ 7] - b[ 7]; - r[ 8] = a[ 8] - b[ 8]; - r[ 9] = a[ 9] - b[ 9]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -13838,6 +13693,7 @@ static void sp_256_mont_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b const sp_digit* m) { (void)sp_256_sub_10(r, a, b); + sp_256_norm_10(r); sp_256_cond_add_10(r, r, m, r[9] >> 22); sp_256_norm_10(r); } @@ -13848,13 +13704,13 @@ static void sp_256_mont_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b * r Result of shift. * a Number to shift. */ -SP_NOINLINE static void sp_256_rshift1_10(sp_digit* r, sp_digit* a) +SP_NOINLINE static void sp_256_rshift1_10(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; for (i=0; i<9; i++) { - r[i] = ((a[i] >> 1) + (a[i + 1] << 25)) & 0x3ffffff; + r[i] = (a[i] >> 1) + ((a[i + 1] << 25) & 0x3ffffff); } #else r[0] = (a[0] >> 1) + ((a[1] << 25) & 0x3ffffff); @@ -14302,8 +14158,8 @@ static int sp_256_proj_point_add_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_10(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -14389,10 +14245,140 @@ static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, con } } +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[2 * 8]; +#endif + int64_t* a32 = NULL; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) + return MEMORY_E; +#endif + + if (err == MP_OKAY) { + a32 = t + 8; + + a32[0] = a[0]; + a32[0] |= a[1] << 26U; + a32[0] &= 0xffffffffL; + a32[1] = (a[1] >> 6); + a32[1] |= a[2] << 20U; + a32[1] &= 0xffffffffL; + a32[2] = (a[2] >> 12); + a32[2] |= a[3] << 14U; + a32[2] &= 0xffffffffL; + a32[3] = (a[3] >> 18); + a32[3] |= a[4] << 8U; + a32[3] &= 0xffffffffL; + a32[4] = (a[4] >> 24); + a32[4] |= a[5] << 2U; + a32[4] |= a[6] << 28U; + a32[4] &= 0xffffffffL; + a32[5] = (a[6] >> 4); + a32[5] |= a[7] << 22U; + a32[5] &= 0xffffffffL; + a32[6] = (a[7] >> 10); + a32[6] |= a[8] << 16U; + a32[6] &= 0xffffffffL; + a32[7] = (a[8] >> 16); + a32[7] |= a[9] << 10U; + a32[7] &= 0xffffffffL; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + o = t[7] >> 32U; t[7] &= 0xffffffffL; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + + r[0] = (sp_digit)(t[0]) & 0x3ffffffL; + r[1] = (sp_digit)(t[0] >> 26U); + r[1] |= (sp_digit)(t[1] << 6U); + r[1] &= 0x3ffffffL; + r[2] = (sp_digit)(t[1] >> 20U); + r[2] |= (sp_digit)(t[2] << 12U); + r[2] &= 0x3ffffffL; + r[3] = (sp_digit)(t[2] >> 14U); + r[3] |= (sp_digit)(t[3] << 18U); + r[3] &= 0x3ffffffL; + r[4] = (sp_digit)(t[3] >> 8U); + r[4] |= (sp_digit)(t[4] << 24U); + r[4] &= 0x3ffffffL; + r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; + r[6] = (sp_digit)(t[4] >> 28U); + r[6] |= (sp_digit)(t[5] << 4U); + r[6] &= 0x3ffffffL; + r[7] = (sp_digit)(t[5] >> 22U); + r[7] |= (sp_digit)(t[6] << 10U); + r[7] &= 0x3ffffffL; + r[8] = (sp_digit)(t[6] >> 16U); + r[8] |= (sp_digit)(t[7] << 16U); + r[8] &= 0x3ffffffL; + r[9] = (sp_digit)(t[7] >> 10U); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_SMALL /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Small implementation using add and double that is cache attack resistant but + * allocates memory rather than use large stacks. + * 256 adds and doubles. + * * r Resulting point. * g Point to multiply. * k Scalar to multiply by. @@ -14516,33 +14502,37 @@ static int sp_256_ecc_mulmod_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp_digit* k, - int map, int ct, void* heap) +static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, + const sp_digit* k, int map, int ct, void* heap) { -#ifdef WOLFSSL_SP_NO_MALLOC +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else sp_point_256 t[3]; sp_digit tmp[2 * 10 * 5]; -#else - sp_point_256* t; - sp_digit* tmp; #endif sp_digit n; int i; - int c, y; + int c; + int y; int err = MP_OKAY; - /* Implementatio is constant time. */ + /* Implementation is constant time. */ (void)ct; (void)heap; -#ifndef WOLFSSL_SP_NO_MALLOC - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { @@ -14593,19 +14583,24 @@ static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp } } -#ifndef WOLFSSL_SP_NO_MALLOC - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); - XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_256) * 3); - XFREE(t, NULL, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(tmp)); - ForceZero(t, sizeof(t)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 10 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -14667,7 +14662,8 @@ static void sp_256_cond_copy_10(sp_digit* r, const sp_digit* a, const sp_digit m * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_10(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_10(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*10; @@ -14755,8 +14751,8 @@ static void sp_256_proj_point_dbl_n_10(sp_point_256* p, int n, sp_digit* t) * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, const sp_point_256* p, - int n, int m, sp_digit* t) +static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, + const sp_point_256* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*10; @@ -14767,6 +14763,7 @@ static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, const sp_point_256 sp_digit* y = r[(1<x[i]; @@ -14783,7 +14780,10 @@ static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, const sp_point_256 /* W = Z^4 */ sp_256_mont_sqr_10(w, z, p256_mod, p256_mp_mod); sp_256_mont_sqr_10(w, w, p256_mod, p256_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_256_mont_sqr_10(t1, x, p256_mod, p256_mp_mod); sp_256_mont_sub_10(t1, t1, w, p256_mod); @@ -14791,14 +14791,14 @@ static void sp_256_proj_point_dbl_n_store_10(sp_point_256* r, const sp_point_256 /* B = X*Y^2 */ sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); sp_256_mont_mul_10(b, t2, x, p256_mod, p256_mp_mod); - x = r[(1<y); + sp_256_norm_10(negy); sp_256_cond_copy_10(p->y, negy, (sp_digit)0 - v[i].neg); sp_256_proj_point_add_10(rt, rt, p, tmp); } @@ -15178,14 +15180,12 @@ static int sp_256_ecc_mulmod_win_add_sub_10(sp_point_256* r, const sp_point_256* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(p, 0, heap); - sp_256_point_free_10(rt, 0, heap); return err; } @@ -15298,6 +15298,10 @@ static void sp_256_proj_to_affine_10(sp_point_256* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 32 bits between * * a The base point. * table Place to store generated point data. @@ -15307,26 +15311,30 @@ static void sp_256_proj_to_affine_10(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_10(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_10(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_10(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -15371,9 +15379,10 @@ static int sp_256_gen_stripe_table_10(const sp_point_256* a, } } - sp_256_point_free_10(s2, 0, heap); - sp_256_point_free_10(s1, 0, heap); - sp_256_point_free_10( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -15440,8 +15449,10 @@ static void sp_256_get_entry_256_10(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -15455,17 +15466,19 @@ static int sp_256_ecc_mulmod_stripe_10(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 10 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 10 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -15473,27 +15486,30 @@ static int sp_256_ecc_mulmod_stripe_10(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_10(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=31; j<8; j++,x+=32) { + x = 31; + for (j=0; j<8; j++) { y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j); + x += 32; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -15507,8 +15523,10 @@ static int sp_256_ecc_mulmod_stripe_10(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=30; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=32) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j); + x += 32; } sp_256_proj_point_dbl_10(rt, rt, t); @@ -15534,13 +15552,12 @@ static int sp_256_ecc_mulmod_stripe_10(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(p, 0, heap); - sp_256_point_free_10(rt, 0, heap); return err; } @@ -15550,16 +15567,25 @@ static int sp_256_ecc_mulmod_stripe_10(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[10]; + /* Y ordinate of point that table was generated from. */ sp_digit y[10]; + /* Precomputation table for point. */ sp_table_entry_256 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -15567,9 +15593,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -15686,28 +15718,31 @@ static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[10]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[10]; +#endif int err = MP_OKAY; - err = sp_256_point_new_10(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 10, km); sp_256_point_from_ecc_point_10(point, gm); @@ -15718,12 +15753,92 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_10(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[10 + 10 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (10 + 10 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_10(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 10; + + sp_256_from_mp(k, 10, km); + sp_256_point_from_ecc_point_10(point, gm); + sp_256_point_from_ecc_point_10(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_10(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_10(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_10(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_10(point, point, addP, tmp); + + if (map) { + sp_256_map_10(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_10(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -15746,6 +15861,10 @@ static int sp_256_ecc_mulmod_base_10(sp_point_256* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 32 between points. + */ static const sp_table_entry_256 p256_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -17030,6 +17149,11 @@ static const sp_table_entry_256 p256_table[256] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -17055,28 +17179,30 @@ static int sp_256_ecc_mulmod_base_10(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[10]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[10]; +#endif int err = MP_OKAY; - err = sp_256_point_new_10(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 10, km); @@ -17086,12 +17212,90 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_10(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[10 + 10 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (10 + 10 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_10(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 10; + + sp_256_from_mp(k, 10, km); + sp_256_point_from_ecc_point_10(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_10(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_10(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_10(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_10(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_10(point, point, addP, tmp); + + if (map) { + sp_256_map_10(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_10(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -17110,7 +17314,7 @@ static int sp_256_iszero_10(const sp_digit* a) a[8] | a[9]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * r A single precision integer. @@ -17131,7 +17335,8 @@ SP_NOINLINE static void sp_256_add_one_10(sp_digit* a) */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -17194,41 +17399,46 @@ static int sp_256_ecc_gen_k_10(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[10]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[10]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_256_point_new_10(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_10(rng, k); } if (err == MP_OKAY) { @@ -17253,15 +17463,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_10(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_10(infinity, 1, heap); -#endif - sp_256_point_free_10(point, 1, heap); return err; } @@ -17275,7 +17484,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_256_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<9; i++) { r[i+1] += r[i] >> 26; @@ -17320,33 +17532,35 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[10]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[10]; +#endif int err = MP_OKAY; if (*outLen < 32U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -17359,12 +17573,12 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(point, 0, heap); return err; } @@ -17425,17 +17639,19 @@ SP_NOINLINE static void sp_256_mul_d_10(sp_digit* r, const sp_digit* a, static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 26 bits from d1 and top 5 bits from d0. */ - d = (d1 << 5) | (d0 >> 21); + d = (d1 << 5) + (d0 >> 21); r = d / dv; d -= r * dv; /* Up to 6 bits in r */ /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 16) & ((1 << 5) - 1); + d += (d0 >> 16) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -17443,7 +17659,7 @@ static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 11) & ((1 << 5) - 1); + d += (d0 >> 11) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -17451,7 +17667,7 @@ static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 6) & ((1 << 5) - 1); + d += (d0 >> 6) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -17459,7 +17675,7 @@ static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 1) & ((1 << 5) - 1); + d += (d0 >> 1) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -17467,10 +17683,11 @@ static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, /* Remaining 1 bits from d0. */ r <<= 1; d <<= 1; - d |= d0 & ((1 << 1) - 1); + d += d0 & ((1 << 1) - 1); t = d / dv; r += t; + /* All 26 bits from d1 and top 5 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -17478,66 +17695,60 @@ static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_256_div_10(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_256_div_10(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[20], t2d[10 + 1]; + sp_digit t1[3 * 10 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 10 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 10 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 10; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 10; dv = d[9]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 10U); for (i=9; i>=0; i--) { - sp_digit hi; t1[10 + i] += t1[10 + i - 1] >> 26; t1[10 + i - 1] &= 0x3ffffff; - hi = t1[10 + i] - (t1[10 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[10 + i]; d1 <<= 26; d1 += t1[10 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_256_div_word_10(hi, t1[10 + i - 1], dv); + r1 = sp_256_div_word_10(t1[10 + i], t1[10 + i - 1], dv); #endif sp_256_mul_d_10(t2, d, r1); (void)sp_256_sub_10(&t1[i], &t1[i], t2); + sp_256_norm_10(&t1[i]); t1[10 + i] -= t2[10]; t1[10 + i] += t1[10 + i - 1] >> 26; t1[10 + i - 1] &= 0x3ffffff; @@ -17554,7 +17765,7 @@ static int sp_256_div_10(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_256_mul_d_10(t2, d, r1); (void)sp_256_sub_10(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 10U); + XMEMCPY(r, t1, sizeof(*r) * 20U); for (i=0; i<9; i++) { r[i+1] += r[i] >> 26; r[i] &= 0x3ffffff; @@ -17563,10 +17774,9 @@ static int sp_256_div_10(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -17594,7 +17804,7 @@ static const uint32_t p256_order_minus_2[8] = { }; #else /* The low half of the order-2 of the P256 curve. */ -static const uint32_t p256_order_low[4] = { +static const sp_int_digit p256_order_low[4] = { 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU }; #endif /* WOLFSSL_SP_SMALL */ @@ -17740,7 +17950,7 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ for (i=127; i>=112; i--) { sp_256_mont_sqr_order_10(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_10(t2, t2, a); } } @@ -17750,7 +17960,7 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ for (i=107; i>=64; i--) { sp_256_mont_sqr_order_10(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_10(t2, t2, a); } } @@ -17760,7 +17970,7 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ for (i=59; i>=32; i--) { sp_256_mont_sqr_order_10(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_10(t2, t2, a); } } @@ -17770,7 +17980,7 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ for (i=27; i>=0; i--) { sp_256_mont_sqr_order_10(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_10(t2, t2, a); } } @@ -17781,12 +17991,63 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_10(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_10(k, k, p256_norm_order); + err = sp_256_mod_10(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_10(k); + + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_10(kInv, k, tmp); + sp_256_norm_10(kInv); + + /* s = r * x + e */ + sp_256_mul_10(x, x, r); + err = sp_256_mod_10(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(x); + carry = sp_256_add_10(s, e, x); + sp_256_cond_sub_10(s, s, p256_order, 0 - carry); + sp_256_norm_10(s); + c = sp_256_cmp_10(s, p256_order); + sp_256_cond_sub_10(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_10(s, s, kInv); + sp_256_norm_10(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -17821,8 +18082,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -17840,13 +18101,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 10, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 10, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_10(rng, ctx->k); @@ -17874,6 +18132,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_10(ctx->r, p256_order); sp_256_cond_sub_10(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_10(ctx->r); + + sp_256_from_mp(ctx->x, 10, priv); + sp_256_from_bin(ctx->e, 10, hash, (int)hashLen); ctx->state = 4; break; } @@ -17930,6 +18191,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -17962,72 +18226,55 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*10]; - sp_digit xd[2*10]; - sp_digit kd[2*10]; - sp_digit rd[2*10]; - sp_digit td[3 * 2*10]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 10]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_256_point_new_10(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 10, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 10, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 10; - x = d + 2 * 10; - k = d + 4 * 10; - r = d + 6 * 10; - tmp = d + 8 * 10; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 10; + k = e + 4 * 10; + r = e + 6 * 10; + tmp = e + 8 * 10; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 10, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 10, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_10(rng, k); @@ -18037,7 +18284,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_10(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_10(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -18048,38 +18295,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_10(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_10(r); - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_10(k, k, p256_norm_order); - err = sp_256_mod_10(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_10(k); - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_10(kInv, k, tmp); - sp_256_norm_10(kInv); + sp_256_from_mp(x, 10, priv); + sp_256_from_bin(e, 10, hash, (int)hashLen); - /* s = r * x + e */ - sp_256_mul_10(x, x, r); - err = sp_256_mod_10(x, x, p256_order); + err = sp_256_calc_s_10(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_10(x); - carry = sp_256_add_10(s, e, x); - sp_256_cond_sub_10(s, s, p256_order, 0 - carry); - sp_256_norm_10(s); - c = sp_256_cmp_10(s, p256_order); - sp_256_cond_sub_10(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_10(s); - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_10(s, s, kInv); - sp_256_norm_10(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_10(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_10(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -18093,20 +18321,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 10); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 10U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 10U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 10U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 10U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 10U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 10U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_10(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 10); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -18156,20 +18388,18 @@ static int sp_256_num_bits_10(const sp_digit* a) static int sp_256_mod_inv_10(sp_digit* r, const sp_digit* a, const sp_digit* m) { int err = MP_OKAY; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - sp_digit* u; - sp_digit* v; - sp_digit* b; - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u = NULL; #else - sp_digit u[10]; - sp_digit v[10]; - sp_digit b[10]; - sp_digit d[10]; + sp_digit u[10 * 4]; #endif - int ut, vt; + sp_digit* v = NULL; + sp_digit* b = NULL; + sp_digit* d = NULL; + int ut; + int vt; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10 * 4, NULL, DYNAMIC_TYPE_ECC); if (u == NULL) @@ -18177,11 +18407,9 @@ static int sp_256_mod_inv_10(sp_digit* r, const sp_digit* a, const sp_digit* m) #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) v = u + 10; b = u + 2 * 10; d = u + 3 * 10; -#endif XMEMCPY(u, m, sizeof(sp_digit) * 10); XMEMCPY(v, a, sizeof(sp_digit) * 10); @@ -18259,7 +18487,7 @@ static int sp_256_mod_inv_10(sp_digit* r, const sp_digit* a, const sp_digit* m) else XMEMCPY(r, d, sizeof(sp_digit) * 10); } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (u != NULL) XFREE(u, NULL, DYNAMIC_TYPE_ECC); #endif @@ -18268,6 +18496,98 @@ static int sp_256_mod_inv_10(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_10(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ + + sp_256_proj_point_add_10(p1, p1, p2, tmp); + if (sp_256_iszero_10(p1->z)) { + if (sp_256_iszero_10(p1->x) && sp_256_iszero_10(p1->y)) { + sp_256_proj_point_dbl_10(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_10(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_256_mod_inv_10(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_256_mul_10(s, s, p256_norm_order); + } + err = sp_256_mod_10(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_10(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_256_mont_inv_order_10(s, s, tmp); + sp_256_mont_mul_order_10(u1, u1, s); + sp_256_mont_mul_order_10(u2, u2, s); + } + +#else + { + sp_256_mont_mul_order_10(u1, u1, s); + sp_256_mont_mul_order_10(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_256_ecc_mulmod_base_10(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_10(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_10(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_10(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -18286,8 +18606,7 @@ static int sp_256_mod_inv_10(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -18306,8 +18625,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -18322,7 +18642,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 10, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 10, r); + sp_256_from_mp(ctx->u2, 10, rm); sp_256_from_mp(ctx->s, 10, sm); sp_256_from_mp(ctx->p2.x, 10, pX); sp_256_from_mp(ctx->p2.y, 10, pY); @@ -18380,57 +18700,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_10(ctx->p1.z)) { - if (sp_256_iszero_10(ctx->p1.x) && sp_256_iszero_10(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<10; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 10, r); + sp_256_from_mp(ctx->u2, 10, rm); err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_10(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 10, r); + sp_256_from_mp(ctx->u2, 10, rm); carry = sp_256_add_10(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -18438,22 +18734,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_10(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -18461,132 +18758,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*10]; - sp_digit u2d[2*10]; - sp_digit sd[2*10]; - sp_digit tmpd[2*10 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 10]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_10(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 10, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 10, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 10; - u2 = d + 2 * 10; - s = d + 4 * 10; - tmp = d + 6 * 10; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 10; + s = u1 + 4 * 10; + tmp = u1 + 6 * 10; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 10, hash, (int)hashLen); - sp_256_from_mp(u2, 10, r); + sp_256_from_mp(u2, 10, rm); sp_256_from_mp(s, 10, sm); sp_256_from_mp(p2->x, 10, pX); sp_256_from_mp(p2->y, 10, pY); sp_256_from_mp(p2->z, 10, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_256_mod_inv_10(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_10(s, s, p256_norm_order); - } - err = sp_256_mod_10(s, s, p256_order); + err = sp_256_calc_vfy_point_10(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_10(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_10(s, s, tmp); - sp_256_mont_mul_order_10(u1, u1, s); - sp_256_mont_mul_order_10(u2, u2, s); - } - -#else - { - sp_256_mont_mul_order_10(u1, u1, s); - sp_256_mont_mul_order_10(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_256_ecc_mulmod_base_10(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_10(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_10(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_256_proj_point_add_10(p1, p1, p2, tmp); - if (sp_256_iszero_10(p1->z)) { - if (sp_256_iszero_10(p1->x) && sp_256_iszero_10(p1->y)) { - sp_256_proj_point_dbl_10(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - p1->x[8] = 0; - p1->x[9] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 10, r); + sp_256_from_mp(u2, 10, rm); err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); } @@ -18597,7 +18825,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_10(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 10, r); + sp_256_from_mp(u2, 10, rm); carry = sp_256_add_10(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -18605,26 +18833,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_10(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_10(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_10(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(p1, 0, heap); - sp_256_point_free_10(p2, 0, heap); return err; } @@ -18638,34 +18866,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_10(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_10(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*10]; - sp_digit t2d[2*10]; + sp_digit t1[10 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 10; - t2 = d + 2 * 10; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 10; sp_256_sqr_10(t1, point->y); (void)sp_256_mod_10(t1, t1, p256_mod); @@ -18685,10 +18905,9 @@ static int sp_256_ecc_is_point_10(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -18701,16 +18920,23 @@ static int sp_256_ecc_is_point_10(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_10(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 10, pX); sp_256_from_mp(pub->y, 10, pY); @@ -18719,7 +18945,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_10(pub, NULL); } - sp_256_point_free_10(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -18735,47 +18964,48 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[10]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; - sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_256_point_new_10(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_10(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_256* pub = NULL; +#else + sp_digit priv[10]; + sp_point_256 pub[2]; #endif + sp_point_256* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 10, pX); sp_256_from_mp(pub->y, 10, pY); sp_256_from_bin(pub->z, 10, one, (int)sizeof(one)); @@ -18789,12 +19019,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_10(pub->x, p256_mod) >= 0 || - sp_256_cmp_10(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_10(pub->x, p256_mod) >= 0) || + (sp_256_cmp_10(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -18806,12 +19035,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_256_ecc_mulmod_10(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_10(p->x) == 0) || - (sp_256_iszero_10(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_10(p->x) == 0) || + (sp_256_iszero_10(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -18819,22 +19046,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_256_ecc_mulmod_base_10(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_10(p->x, pub->x) != 0 || - sp_256_cmp_10(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_10(p->x, pub->x) != 0) || + (sp_256_cmp_10(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_10(p, 0, heap); - sp_256_point_free_10(pub, 0, heap); return err; } @@ -18858,33 +19083,35 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 10 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 10 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; - err = sp_256_point_new_10(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_10(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 10, pX); sp_256_from_mp(p->y, 10, pY); sp_256_from_mp(p->z, 10, pZ); @@ -18905,13 +19132,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(q, 0, NULL); - sp_256_point_free_10(p, 0, NULL); return err; } @@ -18930,25 +19156,28 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 10 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 10 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_10(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -18969,12 +19198,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(p, 0, NULL); return err; } @@ -18989,32 +19218,36 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 10 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 10 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_10(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 10, pX); sp_256_from_mp(p->y, 10, pY); sp_256_from_mp(p->z, 10, pZ); - sp_256_map_10(p, p, tmp); + sp_256_map_10(p, p, tmp); } if (err == MP_OKAY) { @@ -19027,12 +19260,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_10(p, 0, NULL); return err; } @@ -19045,31 +19278,23 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_10(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 10]; - sp_digit t2d[2 * 10]; + sp_digit t1[4 * 10]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 10; - t2 = d + 2 * 10; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 10; { /* t2 = y ^ 0x2 */ @@ -19104,10 +19329,9 @@ static int sp_256_mont_sqrt_10(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -19123,31 +19347,22 @@ static int sp_256_mont_sqrt_10(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 10]; - sp_digit yd[2 * 10]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 10]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 10; - y = d + 2 * 10; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 10; sp_256_from_mp(x, 10, xm); err = sp_256_mod_mul_norm_10(x, x, p256_mod); @@ -19180,10 +19395,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -19194,23 +19408,27 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 15]; + /* Y ordinate of point. */ sp_digit y[2 * 15]; + /* Z ordinate of point. */ sp_digit z[2 * 15]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; /* The modulus (prime) of the curve P384. */ static const sp_digit p384_mod[15] = { 0x3ffffff,0x000003f,0x0000000,0x3fc0000,0x2ffffff,0x3ffffff,0x3ffffff, - 0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x00fffff - + 0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff, + 0x00fffff }; /* The Montogmery normalizer for modulus of the curve P384. */ static const sp_digit p384_norm_mod[15] = { 0x0000001,0x3ffffc0,0x3ffffff,0x003ffff,0x1000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000 - + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000 }; /* The Montogmery multiplier for modulus of the curve P384. */ static sp_digit p384_mp_mod = 0x000001; @@ -19219,22 +19437,22 @@ static sp_digit p384_mp_mod = 0x000001; /* The order of the curve P384. */ static const sp_digit p384_order[15] = { 0x0c52973,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f, - 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x00fffff - + 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff, + 0x00fffff }; #endif /* The order of the curve P384 minus 2. */ static const sp_digit p384_order2[15] = { 0x0c52971,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f, - 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x00fffff - + 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff, + 0x00fffff }; #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) /* The Montogmery normalizer for order of the curve P384. */ static const sp_digit p384_norm_order[15] = { 0x33ad68d,0x0f9a54c,0x1885131,0x136dd3d,0x0a7e5f2,0x2f23488,0x1cb27e0, - 0x00000e2,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000 - + 0x00000e2,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000 }; #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -19246,22 +19464,22 @@ static const sp_point_384 p384_base = { /* X ordinate */ { 0x2760ab7,0x1178e1c,0x296c3a5,0x176fd54,0x05502f2,0x0950a8e,0x3741e08, - 0x26e6167,0x3628ba7,0x11b874e,0x3320ad7,0x2c71c7b,0x305378e,0x288afa2,0x00aa87c, - + 0x26e6167,0x3628ba7,0x11b874e,0x3320ad7,0x2c71c7b,0x305378e,0x288afa2, + 0x00aa87c, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L }, /* Y ordinate */ { 0x0ea0e5f,0x0c75f24,0x019d7a4,0x33875fa,0x00a60b1,0x17c2e30,0x1a3113b, - 0x051f3a7,0x1bd289a,0x27e3d07,0x1292dc2,0x27a62fe,0x22c6f5d,0x392a589,0x003617d, - + 0x051f3a7,0x1bd289a,0x27e3d07,0x1292dc2,0x27a62fe,0x22c6f5d,0x392a589, + 0x003617d, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L }, /* Z ordinate */ { 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, - + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L }, /* infinity */ @@ -19270,416 +19488,11 @@ static const sp_point_384 p384_base = { #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) static const sp_digit p384_b[15] = { 0x3ec2aef,0x1723b74,0x119d2a8,0x23628bb,0x2c65639,0x004e1d6,0x14088f5, - 0x104480c,0x06efe81,0x2460767,0x23f82d1,0x23815af,0x2e7e498,0x3e9f88f,0x00b3312 - + 0x104480c,0x06efe81,0x2460767,0x23f82d1,0x23815af,0x2e7e498,0x3e9f88f, + 0x00b3312 }; #endif -static int sp_384_point_new_ex_15(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_15(heap, sp, p) sp_384_point_new_ex_15((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_15(heap, sp, p) sp_384_point_new_ex_15((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_15(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mod_mul_norm_15(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* td; -#else - int64_t td[12]; - int64_t a32d[12]; -#endif - int64_t* t; - int64_t* a32; - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (td == NULL) { - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = td; - a32 = td + 12; -#else - t = td; - a32 = a32d; -#endif - - a32[0] = a[0]; - a32[0] |= a[1] << 26U; - a32[0] &= 0xffffffffL; - a32[1] = (sp_digit)(a[1] >> 6); - a32[1] |= a[2] << 20U; - a32[1] &= 0xffffffffL; - a32[2] = (sp_digit)(a[2] >> 12); - a32[2] |= a[3] << 14U; - a32[2] &= 0xffffffffL; - a32[3] = (sp_digit)(a[3] >> 18); - a32[3] |= a[4] << 8U; - a32[3] &= 0xffffffffL; - a32[4] = (sp_digit)(a[4] >> 24); - a32[4] |= a[5] << 2U; - a32[4] |= a[6] << 28U; - a32[4] &= 0xffffffffL; - a32[5] = (sp_digit)(a[6] >> 4); - a32[5] |= a[7] << 22U; - a32[5] &= 0xffffffffL; - a32[6] = (sp_digit)(a[7] >> 10); - a32[6] |= a[8] << 16U; - a32[6] &= 0xffffffffL; - a32[7] = (sp_digit)(a[8] >> 16); - a32[7] |= a[9] << 10U; - a32[7] &= 0xffffffffL; - a32[8] = (sp_digit)(a[9] >> 22); - a32[8] |= a[10] << 4U; - a32[8] |= a[11] << 30U; - a32[8] &= 0xffffffffL; - a32[9] = (sp_digit)(a[11] >> 2); - a32[9] |= a[12] << 24U; - a32[9] &= 0xffffffffL; - a32[10] = (sp_digit)(a[12] >> 8); - a32[10] |= a[13] << 18U; - a32[10] &= 0xffffffffL; - a32[11] = (sp_digit)(a[13] >> 14); - a32[11] |= a[14] << 12U; - a32[11] &= 0xffffffffL; - - /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ - t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; - /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ - t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; - /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ - t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; - /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ - t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; - /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ - t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; - /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ - t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; - /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ - t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; - /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ - t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; - /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ - t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; - /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ - t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; - /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ - t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; - /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ - t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - o = t[11] >> 32; t[11] &= 0xffffffff; - t[0] += o; - t[1] -= o; - t[3] += o; - t[4] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - - r[0] = (sp_digit)(t[0]) & 0x3ffffffL; - r[1] = (sp_digit)(t[0] >> 26U); - r[1] |= (sp_digit)(t[1] << 6U); - r[1] &= 0x3ffffffL; - r[2] = (sp_digit)(t[1] >> 20U); - r[2] |= (sp_digit)(t[2] << 12U); - r[2] &= 0x3ffffffL; - r[3] = (sp_digit)(t[2] >> 14U); - r[3] |= (sp_digit)(t[3] << 18U); - r[3] &= 0x3ffffffL; - r[4] = (sp_digit)(t[3] >> 8U); - r[4] |= (sp_digit)(t[4] << 24U); - r[4] &= 0x3ffffffL; - r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; - r[6] = (sp_digit)(t[4] >> 28U); - r[6] |= (sp_digit)(t[5] << 4U); - r[6] &= 0x3ffffffL; - r[7] = (sp_digit)(t[5] >> 22U); - r[7] |= (sp_digit)(t[6] << 10U); - r[7] &= 0x3ffffffL; - r[8] = (sp_digit)(t[6] >> 16U); - r[8] |= (sp_digit)(t[7] << 16U); - r[8] &= 0x3ffffffL; - r[9] = (sp_digit)(t[7] >> 10U); - r[9] |= (sp_digit)(t[8] << 22U); - r[9] &= 0x3ffffffL; - r[10] = (sp_digit)(t[8] >> 4U) & 0x3ffffffL; - r[11] = (sp_digit)(t[8] >> 30U); - r[11] |= (sp_digit)(t[9] << 2U); - r[11] &= 0x3ffffffL; - r[12] = (sp_digit)(t[9] >> 24U); - r[12] |= (sp_digit)(t[10] << 8U); - r[12] &= 0x3ffffffL; - r[13] = (sp_digit)(t[10] >> 18U); - r[13] |= (sp_digit)(t[11] << 14U); - r[13] &= 0x3ffffffL; - r[14] = (sp_digit)(t[11] >> 12U); - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) - XFREE(td, NULL, DYNAMIC_TYPE_ECC); -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 26 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 26 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x3ffffff; - s = 26U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 26U) <= (word32)DIGIT_BIT) { - s += 26U; - r[j] &= 0x3ffffff; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 26) { - r[j] &= 0x3ffffff; - if (j + 1 >= size) { - break; - } - s = 26 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_384. - * - * p Point of type sp_point_384 (result). - * pm Point of type ecc_point. - */ -static void sp_384_point_from_ecc_point_15(sp_point_384* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_384_from_mp(p->x, 15, pm->x); - sp_384_from_mp(p->y, 15, pm->y); - sp_384_from_mp(p->z, 15, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_384_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 26 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 15); - r->used = 15; - mp_clamp(r); -#elif DIGIT_BIT < 26 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 15; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 26) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 26 - s; - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 15; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 26 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 26 - s; - } - else { - s += 26; - } - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_384 to type ecc_point. - * - * p Point of type sp_point_384. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_384_point_to_ecc_point_15(const sp_point_384* p, ecc_point* pm) -{ - int err; - - err = sp_384_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pm->z); - } - - return err; -} - #ifdef WOLFSSL_SP_SMALL /* Multiply a and b into r. (r = a * b) * @@ -19690,7 +19503,9 @@ static int sp_384_point_to_ecc_point_15(const sp_point_384* p, ecc_point* pm) SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int64_t c; c = ((int64_t)a[14]) * b[14]; @@ -19984,6 +19799,496 @@ SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a, } #endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a) +{ + int i; + int j; + int k; + int64_t c; + + c = ((int64_t)a[14]) * a[14]; + r[29] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 27; k >= 0; k--) { + for (i = 14; i >= 0; i--) { + j = k - i; + if (j >= 15 || i <= j) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) { + c += ((int64_t)a[i]) * a[i]; + } + + r[k + 2] += (sp_digit)(c >> 52); + r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff); + c = (c & 0x3ffffff) << 26; + } + r[0] = (sp_digit)(c >> 26); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; + int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; + int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 + + ((int64_t)a[ 1]) * a[ 1]; + int64_t t3 = (((int64_t)a[ 0]) * a[ 3] + + ((int64_t)a[ 1]) * a[ 2]) * 2; + int64_t t4 = (((int64_t)a[ 0]) * a[ 4] + + ((int64_t)a[ 1]) * a[ 3]) * 2 + + ((int64_t)a[ 2]) * a[ 2]; + int64_t t5 = (((int64_t)a[ 0]) * a[ 5] + + ((int64_t)a[ 1]) * a[ 4] + + ((int64_t)a[ 2]) * a[ 3]) * 2; + int64_t t6 = (((int64_t)a[ 0]) * a[ 6] + + ((int64_t)a[ 1]) * a[ 5] + + ((int64_t)a[ 2]) * a[ 4]) * 2 + + ((int64_t)a[ 3]) * a[ 3]; + int64_t t7 = (((int64_t)a[ 0]) * a[ 7] + + ((int64_t)a[ 1]) * a[ 6] + + ((int64_t)a[ 2]) * a[ 5] + + ((int64_t)a[ 3]) * a[ 4]) * 2; + int64_t t8 = (((int64_t)a[ 0]) * a[ 8] + + ((int64_t)a[ 1]) * a[ 7] + + ((int64_t)a[ 2]) * a[ 6] + + ((int64_t)a[ 3]) * a[ 5]) * 2 + + ((int64_t)a[ 4]) * a[ 4]; + int64_t t9 = (((int64_t)a[ 0]) * a[ 9] + + ((int64_t)a[ 1]) * a[ 8] + + ((int64_t)a[ 2]) * a[ 7] + + ((int64_t)a[ 3]) * a[ 6] + + ((int64_t)a[ 4]) * a[ 5]) * 2; + int64_t t10 = (((int64_t)a[ 0]) * a[10] + + ((int64_t)a[ 1]) * a[ 9] + + ((int64_t)a[ 2]) * a[ 8] + + ((int64_t)a[ 3]) * a[ 7] + + ((int64_t)a[ 4]) * a[ 6]) * 2 + + ((int64_t)a[ 5]) * a[ 5]; + int64_t t11 = (((int64_t)a[ 0]) * a[11] + + ((int64_t)a[ 1]) * a[10] + + ((int64_t)a[ 2]) * a[ 9] + + ((int64_t)a[ 3]) * a[ 8] + + ((int64_t)a[ 4]) * a[ 7] + + ((int64_t)a[ 5]) * a[ 6]) * 2; + int64_t t12 = (((int64_t)a[ 0]) * a[12] + + ((int64_t)a[ 1]) * a[11] + + ((int64_t)a[ 2]) * a[10] + + ((int64_t)a[ 3]) * a[ 9] + + ((int64_t)a[ 4]) * a[ 8] + + ((int64_t)a[ 5]) * a[ 7]) * 2 + + ((int64_t)a[ 6]) * a[ 6]; + int64_t t13 = (((int64_t)a[ 0]) * a[13] + + ((int64_t)a[ 1]) * a[12] + + ((int64_t)a[ 2]) * a[11] + + ((int64_t)a[ 3]) * a[10] + + ((int64_t)a[ 4]) * a[ 9] + + ((int64_t)a[ 5]) * a[ 8] + + ((int64_t)a[ 6]) * a[ 7]) * 2; + int64_t t14 = (((int64_t)a[ 0]) * a[14] + + ((int64_t)a[ 1]) * a[13] + + ((int64_t)a[ 2]) * a[12] + + ((int64_t)a[ 3]) * a[11] + + ((int64_t)a[ 4]) * a[10] + + ((int64_t)a[ 5]) * a[ 9] + + ((int64_t)a[ 6]) * a[ 8]) * 2 + + ((int64_t)a[ 7]) * a[ 7]; + int64_t t15 = (((int64_t)a[ 1]) * a[14] + + ((int64_t)a[ 2]) * a[13] + + ((int64_t)a[ 3]) * a[12] + + ((int64_t)a[ 4]) * a[11] + + ((int64_t)a[ 5]) * a[10] + + ((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 2]) * a[14] + + ((int64_t)a[ 3]) * a[13] + + ((int64_t)a[ 4]) * a[12] + + ((int64_t)a[ 5]) * a[11] + + ((int64_t)a[ 6]) * a[10] + + ((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 3]) * a[14] + + ((int64_t)a[ 4]) * a[13] + + ((int64_t)a[ 5]) * a[12] + + ((int64_t)a[ 6]) * a[11] + + ((int64_t)a[ 7]) * a[10] + + ((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = (((int64_t)a[ 4]) * a[14] + + ((int64_t)a[ 5]) * a[13] + + ((int64_t)a[ 6]) * a[12] + + ((int64_t)a[ 7]) * a[11] + + ((int64_t)a[ 8]) * a[10]) * 2 + + ((int64_t)a[ 9]) * a[ 9]; + int64_t t19 = (((int64_t)a[ 5]) * a[14] + + ((int64_t)a[ 6]) * a[13] + + ((int64_t)a[ 7]) * a[12] + + ((int64_t)a[ 8]) * a[11] + + ((int64_t)a[ 9]) * a[10]) * 2; + int64_t t20 = (((int64_t)a[ 6]) * a[14] + + ((int64_t)a[ 7]) * a[13] + + ((int64_t)a[ 8]) * a[12] + + ((int64_t)a[ 9]) * a[11]) * 2 + + ((int64_t)a[10]) * a[10]; + int64_t t21 = (((int64_t)a[ 7]) * a[14] + + ((int64_t)a[ 8]) * a[13] + + ((int64_t)a[ 9]) * a[12] + + ((int64_t)a[10]) * a[11]) * 2; + int64_t t22 = (((int64_t)a[ 8]) * a[14] + + ((int64_t)a[ 9]) * a[13] + + ((int64_t)a[10]) * a[12]) * 2 + + ((int64_t)a[11]) * a[11]; + int64_t t23 = (((int64_t)a[ 9]) * a[14] + + ((int64_t)a[10]) * a[13] + + ((int64_t)a[11]) * a[12]) * 2; + int64_t t24 = (((int64_t)a[10]) * a[14] + + ((int64_t)a[11]) * a[13]) * 2 + + ((int64_t)a[12]) * a[12]; + int64_t t25 = (((int64_t)a[11]) * a[14] + + ((int64_t)a[12]) * a[13]) * 2; + int64_t t26 = (((int64_t)a[12]) * a[14]) * 2 + + ((int64_t)a[13]) * a[13]; + int64_t t27 = (((int64_t)a[13]) * a[14]) * 2; + int64_t t28 = ((int64_t)a[14]) * a[14]; + + t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; + t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; + t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; + t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; + t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; + t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; + t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; + t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; + t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; + t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; + t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; + t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; + t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; + t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; + t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; + t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; + t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; + t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; + t19 += t18 >> 26; r[18] = t18 & 0x3ffffff; + t20 += t19 >> 26; r[19] = t19 & 0x3ffffff; + t21 += t20 >> 26; r[20] = t20 & 0x3ffffff; + t22 += t21 >> 26; r[21] = t21 & 0x3ffffff; + t23 += t22 >> 26; r[22] = t22 & 0x3ffffff; + t24 += t23 >> 26; r[23] = t23 & 0x3ffffff; + t25 += t24 >> 26; r[24] = t24 & 0x3ffffff; + t26 += t25 >> 26; r[25] = t25 & 0x3ffffff; + t27 += t26 >> 26; r[26] = t26 & 0x3ffffff; + t28 += t27 >> 26; r[27] = t27 & 0x3ffffff; + r[29] = (sp_digit)(t28 >> 26); + r[28] = t28 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 15; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + r[ 9] = a[ 9] + b[ 9]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + r[13] = a[13] + b[13]; + r[14] = a[14] + b[14]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 15; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + r[ 5] = a[ 5] - b[ 5]; + r[ 6] = a[ 6] - b[ 6]; + r[ 7] = a[ 7] - b[ 7]; + r[ 8] = a[ 8] - b[ 8]; + r[ 9] = a[ 9] - b[ 9]; + r[10] = a[10] - b[10]; + r[11] = a[11] - b[11]; + r[12] = a[12] - b[12]; + r[13] = a[13] - b[13]; + r[14] = a[14] - b[14]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 26 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 26U) <= (word32)DIGIT_BIT) { + s += 26U; + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + s = 26 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_15(sp_point_384* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_384_from_mp(p->x, 15, pm->x); + sp_384_from_mp(p->y, 15, pm->y); + sp_384_from_mp(p->z, 15, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 26 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 15); + r->used = 15; + mp_clamp(r); +#elif DIGIT_BIT < 26 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 15; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 26) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 26 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 15; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 26 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 26 - s; + } + else { + s += 26; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_15(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + #define sp_384_mont_reduce_order_15 sp_384_mont_reduce_15 /* Compare a with b in constant time. @@ -20209,7 +20514,6 @@ static void sp_384_mont_reduce_15(sp_digit* a, const sp_digit* m, sp_digit mp) sp_384_mul_add_15(a+i, m, mu); a[i+1] += a[i] >> 26; a[i] &= 0x3ffffff; - sp_384_mont_shift_15(a, a); sp_384_cond_sub_15(a, a, m, 0 - (((a[14] >> 20) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -20225,212 +20529,13 @@ static void sp_384_mont_reduce_15(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_15(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_15(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_15(r, a, b); sp_384_mont_reduce_15(r, m, mp); } -#ifdef WOLFSSL_SP_SMALL -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a) -{ - int i, j, k; - int64_t c; - - c = ((int64_t)a[14]) * a[14]; - r[29] = (sp_digit)(c >> 26); - c = (c & 0x3ffffff) << 26; - for (k = 27; k >= 0; k--) { - for (i = 14; i >= 0; i--) { - j = k - i; - if (j >= 15 || i <= j) { - break; - } - if (j < 0) { - continue; - } - - c += ((int64_t)a[i]) * a[j] * 2; - } - if (i == j) { - c += ((int64_t)a[i]) * a[i]; - } - - r[k + 2] += (sp_digit)(c >> 52); - r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff); - c = (c & 0x3ffffff) << 26; - } - r[0] = (sp_digit)(c >> 26); -} - -#else -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a) -{ - int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; - int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; - int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 - + ((int64_t)a[ 1]) * a[ 1]; - int64_t t3 = (((int64_t)a[ 0]) * a[ 3] - + ((int64_t)a[ 1]) * a[ 2]) * 2; - int64_t t4 = (((int64_t)a[ 0]) * a[ 4] - + ((int64_t)a[ 1]) * a[ 3]) * 2 - + ((int64_t)a[ 2]) * a[ 2]; - int64_t t5 = (((int64_t)a[ 0]) * a[ 5] - + ((int64_t)a[ 1]) * a[ 4] - + ((int64_t)a[ 2]) * a[ 3]) * 2; - int64_t t6 = (((int64_t)a[ 0]) * a[ 6] - + ((int64_t)a[ 1]) * a[ 5] - + ((int64_t)a[ 2]) * a[ 4]) * 2 - + ((int64_t)a[ 3]) * a[ 3]; - int64_t t7 = (((int64_t)a[ 0]) * a[ 7] - + ((int64_t)a[ 1]) * a[ 6] - + ((int64_t)a[ 2]) * a[ 5] - + ((int64_t)a[ 3]) * a[ 4]) * 2; - int64_t t8 = (((int64_t)a[ 0]) * a[ 8] - + ((int64_t)a[ 1]) * a[ 7] - + ((int64_t)a[ 2]) * a[ 6] - + ((int64_t)a[ 3]) * a[ 5]) * 2 - + ((int64_t)a[ 4]) * a[ 4]; - int64_t t9 = (((int64_t)a[ 0]) * a[ 9] - + ((int64_t)a[ 1]) * a[ 8] - + ((int64_t)a[ 2]) * a[ 7] - + ((int64_t)a[ 3]) * a[ 6] - + ((int64_t)a[ 4]) * a[ 5]) * 2; - int64_t t10 = (((int64_t)a[ 0]) * a[10] - + ((int64_t)a[ 1]) * a[ 9] - + ((int64_t)a[ 2]) * a[ 8] - + ((int64_t)a[ 3]) * a[ 7] - + ((int64_t)a[ 4]) * a[ 6]) * 2 - + ((int64_t)a[ 5]) * a[ 5]; - int64_t t11 = (((int64_t)a[ 0]) * a[11] - + ((int64_t)a[ 1]) * a[10] - + ((int64_t)a[ 2]) * a[ 9] - + ((int64_t)a[ 3]) * a[ 8] - + ((int64_t)a[ 4]) * a[ 7] - + ((int64_t)a[ 5]) * a[ 6]) * 2; - int64_t t12 = (((int64_t)a[ 0]) * a[12] - + ((int64_t)a[ 1]) * a[11] - + ((int64_t)a[ 2]) * a[10] - + ((int64_t)a[ 3]) * a[ 9] - + ((int64_t)a[ 4]) * a[ 8] - + ((int64_t)a[ 5]) * a[ 7]) * 2 - + ((int64_t)a[ 6]) * a[ 6]; - int64_t t13 = (((int64_t)a[ 0]) * a[13] - + ((int64_t)a[ 1]) * a[12] - + ((int64_t)a[ 2]) * a[11] - + ((int64_t)a[ 3]) * a[10] - + ((int64_t)a[ 4]) * a[ 9] - + ((int64_t)a[ 5]) * a[ 8] - + ((int64_t)a[ 6]) * a[ 7]) * 2; - int64_t t14 = (((int64_t)a[ 0]) * a[14] - + ((int64_t)a[ 1]) * a[13] - + ((int64_t)a[ 2]) * a[12] - + ((int64_t)a[ 3]) * a[11] - + ((int64_t)a[ 4]) * a[10] - + ((int64_t)a[ 5]) * a[ 9] - + ((int64_t)a[ 6]) * a[ 8]) * 2 - + ((int64_t)a[ 7]) * a[ 7]; - int64_t t15 = (((int64_t)a[ 1]) * a[14] - + ((int64_t)a[ 2]) * a[13] - + ((int64_t)a[ 3]) * a[12] - + ((int64_t)a[ 4]) * a[11] - + ((int64_t)a[ 5]) * a[10] - + ((int64_t)a[ 6]) * a[ 9] - + ((int64_t)a[ 7]) * a[ 8]) * 2; - int64_t t16 = (((int64_t)a[ 2]) * a[14] - + ((int64_t)a[ 3]) * a[13] - + ((int64_t)a[ 4]) * a[12] - + ((int64_t)a[ 5]) * a[11] - + ((int64_t)a[ 6]) * a[10] - + ((int64_t)a[ 7]) * a[ 9]) * 2 - + ((int64_t)a[ 8]) * a[ 8]; - int64_t t17 = (((int64_t)a[ 3]) * a[14] - + ((int64_t)a[ 4]) * a[13] - + ((int64_t)a[ 5]) * a[12] - + ((int64_t)a[ 6]) * a[11] - + ((int64_t)a[ 7]) * a[10] - + ((int64_t)a[ 8]) * a[ 9]) * 2; - int64_t t18 = (((int64_t)a[ 4]) * a[14] - + ((int64_t)a[ 5]) * a[13] - + ((int64_t)a[ 6]) * a[12] - + ((int64_t)a[ 7]) * a[11] - + ((int64_t)a[ 8]) * a[10]) * 2 - + ((int64_t)a[ 9]) * a[ 9]; - int64_t t19 = (((int64_t)a[ 5]) * a[14] - + ((int64_t)a[ 6]) * a[13] - + ((int64_t)a[ 7]) * a[12] - + ((int64_t)a[ 8]) * a[11] - + ((int64_t)a[ 9]) * a[10]) * 2; - int64_t t20 = (((int64_t)a[ 6]) * a[14] - + ((int64_t)a[ 7]) * a[13] - + ((int64_t)a[ 8]) * a[12] - + ((int64_t)a[ 9]) * a[11]) * 2 - + ((int64_t)a[10]) * a[10]; - int64_t t21 = (((int64_t)a[ 7]) * a[14] - + ((int64_t)a[ 8]) * a[13] - + ((int64_t)a[ 9]) * a[12] - + ((int64_t)a[10]) * a[11]) * 2; - int64_t t22 = (((int64_t)a[ 8]) * a[14] - + ((int64_t)a[ 9]) * a[13] - + ((int64_t)a[10]) * a[12]) * 2 - + ((int64_t)a[11]) * a[11]; - int64_t t23 = (((int64_t)a[ 9]) * a[14] - + ((int64_t)a[10]) * a[13] - + ((int64_t)a[11]) * a[12]) * 2; - int64_t t24 = (((int64_t)a[10]) * a[14] - + ((int64_t)a[11]) * a[13]) * 2 - + ((int64_t)a[12]) * a[12]; - int64_t t25 = (((int64_t)a[11]) * a[14] - + ((int64_t)a[12]) * a[13]) * 2; - int64_t t26 = (((int64_t)a[12]) * a[14]) * 2 - + ((int64_t)a[13]) * a[13]; - int64_t t27 = (((int64_t)a[13]) * a[14]) * 2; - int64_t t28 = ((int64_t)a[14]) * a[14]; - - t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; - t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; - t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; - t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; - t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; - t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; - t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; - t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; - t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; - t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; - t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; - t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; - t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; - t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; - t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; - t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; - t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; - t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; - t19 += t18 >> 26; r[18] = t18 & 0x3ffffff; - t20 += t19 >> 26; r[19] = t19 & 0x3ffffff; - t21 += t20 >> 26; r[20] = t20 & 0x3ffffff; - t22 += t21 >> 26; r[21] = t21 & 0x3ffffff; - t23 += t22 >> 26; r[22] = t22 & 0x3ffffff; - t24 += t23 >> 26; r[23] = t23 & 0x3ffffff; - t25 += t24 >> 26; r[24] = t24 & 0x3ffffff; - t26 += t25 >> 26; r[25] = t25 & 0x3ffffff; - t27 += t26 >> 26; r[26] = t26 & 0x3ffffff; - t28 += t27 >> 26; r[27] = t27 & 0x3ffffff; - r[29] = (sp_digit)(t28 >> 26); - r[28] = t28 & 0x3ffffff; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -20438,8 +20543,8 @@ SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_15(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_15(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_15(r, a); sp_384_mont_reduce_15(r, m, mp); @@ -20463,7 +20568,7 @@ static void sp_384_mont_sqr_n_15(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint32_t p384_mod_minus_2[12] = { @@ -20563,7 +20668,8 @@ static void sp_384_mont_inv_15(sp_digit* r, const sp_digit* a, sp_digit* td) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_15(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_15(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*15; @@ -20599,54 +20705,6 @@ static void sp_384_map_15(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 15; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] + b[ 0]; - r[ 1] = a[ 1] + b[ 1]; - r[ 2] = a[ 2] + b[ 2]; - r[ 3] = a[ 3] + b[ 3]; - r[ 4] = a[ 4] + b[ 4]; - r[ 5] = a[ 5] + b[ 5]; - r[ 6] = a[ 6] + b[ 6]; - r[ 7] = a[ 7] + b[ 7]; - r[ 8] = a[ 8] + b[ 8]; - r[ 9] = a[ 9] + b[ 9]; - r[10] = a[10] + b[10]; - r[11] = a[11] + b[11]; - r[12] = a[12] + b[12]; - r[13] = a[13] + b[13]; - r[14] = a[14] + b[14]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -20699,55 +20757,6 @@ static void sp_384_mont_tpl_15(sp_digit* r, const sp_digit* a, const sp_digit* m sp_384_norm_15(r); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 15; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] - b[ 0]; - r[ 1] = a[ 1] - b[ 1]; - r[ 2] = a[ 2] - b[ 2]; - r[ 3] = a[ 3] - b[ 3]; - r[ 4] = a[ 4] - b[ 4]; - r[ 5] = a[ 5] - b[ 5]; - r[ 6] = a[ 6] - b[ 6]; - r[ 7] = a[ 7] - b[ 7]; - r[ 8] = a[ 8] - b[ 8]; - r[ 9] = a[ 9] - b[ 9]; - r[10] = a[10] - b[10]; - r[11] = a[11] - b[11]; - r[12] = a[12] - b[12]; - r[13] = a[13] - b[13]; - r[14] = a[14] - b[14]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -20795,6 +20804,7 @@ static void sp_384_mont_sub_15(sp_digit* r, const sp_digit* a, const sp_digit* b const sp_digit* m) { (void)sp_384_sub_15(r, a, b); + sp_384_norm_15(r); sp_384_cond_add_15(r, r, m, r[14] >> 20); sp_384_norm_15(r); } @@ -20805,13 +20815,13 @@ static void sp_384_mont_sub_15(sp_digit* r, const sp_digit* a, const sp_digit* b * r Result of shift. * a Number to shift. */ -SP_NOINLINE static void sp_384_rshift1_15(sp_digit* r, sp_digit* a) +SP_NOINLINE static void sp_384_rshift1_15(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; for (i=0; i<14; i++) { - r[i] = ((a[i] >> 1) + (a[i + 1] << 25)) & 0x3ffffff; + r[i] = (a[i] >> 1) + ((a[i + 1] << 25) & 0x3ffffff); } #else r[0] = (a[0] >> 1) + ((a[1] << 25) & 0x3ffffff); @@ -21265,8 +21275,8 @@ static int sp_384_proj_point_add_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_15(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -21352,10 +21362,182 @@ static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, con } } +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mod_mul_norm_15(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[2 * 12]; +#endif + int64_t* a32 = NULL; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + a32 = t + 12; + + a32[0] = a[0]; + a32[0] |= a[1] << 26U; + a32[0] &= 0xffffffffL; + a32[1] = (a[1] >> 6); + a32[1] |= a[2] << 20U; + a32[1] &= 0xffffffffL; + a32[2] = (a[2] >> 12); + a32[2] |= a[3] << 14U; + a32[2] &= 0xffffffffL; + a32[3] = (a[3] >> 18); + a32[3] |= a[4] << 8U; + a32[3] &= 0xffffffffL; + a32[4] = (a[4] >> 24); + a32[4] |= a[5] << 2U; + a32[4] |= a[6] << 28U; + a32[4] &= 0xffffffffL; + a32[5] = (a[6] >> 4); + a32[5] |= a[7] << 22U; + a32[5] &= 0xffffffffL; + a32[6] = (a[7] >> 10); + a32[6] |= a[8] << 16U; + a32[6] &= 0xffffffffL; + a32[7] = (a[8] >> 16); + a32[7] |= a[9] << 10U; + a32[7] &= 0xffffffffL; + a32[8] = (a[9] >> 22); + a32[8] |= a[10] << 4U; + a32[8] |= a[11] << 30U; + a32[8] &= 0xffffffffL; + a32[9] = (a[11] >> 2); + a32[9] |= a[12] << 24U; + a32[9] &= 0xffffffffL; + a32[10] = (a[12] >> 8); + a32[10] |= a[13] << 18U; + a32[10] &= 0xffffffffL; + a32[11] = (a[13] >> 14); + a32[11] |= a[14] << 12U; + a32[11] &= 0xffffffffL; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = (sp_digit)(t[0]) & 0x3ffffffL; + r[1] = (sp_digit)(t[0] >> 26U); + r[1] |= (sp_digit)(t[1] << 6U); + r[1] &= 0x3ffffffL; + r[2] = (sp_digit)(t[1] >> 20U); + r[2] |= (sp_digit)(t[2] << 12U); + r[2] &= 0x3ffffffL; + r[3] = (sp_digit)(t[2] >> 14U); + r[3] |= (sp_digit)(t[3] << 18U); + r[3] &= 0x3ffffffL; + r[4] = (sp_digit)(t[3] >> 8U); + r[4] |= (sp_digit)(t[4] << 24U); + r[4] &= 0x3ffffffL; + r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; + r[6] = (sp_digit)(t[4] >> 28U); + r[6] |= (sp_digit)(t[5] << 4U); + r[6] &= 0x3ffffffL; + r[7] = (sp_digit)(t[5] >> 22U); + r[7] |= (sp_digit)(t[6] << 10U); + r[7] &= 0x3ffffffL; + r[8] = (sp_digit)(t[6] >> 16U); + r[8] |= (sp_digit)(t[7] << 16U); + r[8] &= 0x3ffffffL; + r[9] = (sp_digit)(t[7] >> 10U); + r[9] |= (sp_digit)(t[8] << 22U); + r[9] &= 0x3ffffffL; + r[10] = (sp_digit)(t[8] >> 4U) & 0x3ffffffL; + r[11] = (sp_digit)(t[8] >> 30U); + r[11] |= (sp_digit)(t[9] << 2U); + r[11] &= 0x3ffffffL; + r[12] = (sp_digit)(t[9] >> 24U); + r[12] |= (sp_digit)(t[10] << 8U); + r[12] &= 0x3ffffffL; + r[13] = (sp_digit)(t[10] >> 18U); + r[13] |= (sp_digit)(t[11] << 14U); + r[13] &= 0x3ffffffL; + r[14] = (sp_digit)(t[11] >> 12U); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_SMALL /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Small implementation using add and double that is cache attack resistant but + * allocates memory rather than use large stacks. + * 384 adds and doubles. + * * r Resulting point. * g Point to multiply. * k Scalar to multiply by. @@ -21479,33 +21661,37 @@ static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k, - int map, int ct, void* heap) +static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, int ct, void* heap) { -#ifdef WOLFSSL_SP_NO_MALLOC +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else sp_point_384 t[3]; sp_digit tmp[2 * 15 * 6]; -#else - sp_point_384* t; - sp_digit* tmp; #endif sp_digit n; int i; - int c, y; + int c; + int y; int err = MP_OKAY; - /* Implementatio is constant time. */ + /* Implementation is constant time. */ (void)ct; (void)heap; -#ifndef WOLFSSL_SP_NO_MALLOC - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { @@ -21556,19 +21742,24 @@ static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp } } -#ifndef WOLFSSL_SP_NO_MALLOC - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 15 * 6); - XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_384) * 3); - XFREE(t, NULL, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(tmp)); - ForceZero(t, sizeof(t)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 15 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -21640,7 +21831,8 @@ static void sp_384_cond_copy_15(sp_digit* r, const sp_digit* a, const sp_digit m * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_15(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_15(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*15; @@ -21728,8 +21920,8 @@ static void sp_384_proj_point_dbl_n_15(sp_point_384* p, int n, sp_digit* t) * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r, const sp_point_384* p, - int n, int m, sp_digit* t) +static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r, + const sp_point_384* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*15; @@ -21740,6 +21932,7 @@ static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r, const sp_point_384 sp_digit* y = r[(1<x[i]; @@ -21756,7 +21949,10 @@ static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r, const sp_point_384 /* W = Z^4 */ sp_384_mont_sqr_15(w, z, p384_mod, p384_mp_mod); sp_384_mont_sqr_15(w, w, p384_mod, p384_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod); sp_384_mont_sub_15(t1, t1, w, p384_mod); @@ -21764,14 +21960,14 @@ static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r, const sp_point_384 /* B = X*Y^2 */ sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod); sp_384_mont_mul_15(b, t2, x, p384_mod, p384_mp_mod); - x = r[(1<y); + sp_384_norm_15(negy); sp_384_cond_copy_15(p->y, negy, (sp_digit)0 - v[i].neg); sp_384_proj_point_add_15(rt, rt, p, tmp); } @@ -22181,14 +22379,12 @@ static int sp_384_ecc_mulmod_win_add_sub_15(sp_point_384* r, const sp_point_384* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(p, 0, heap); - sp_384_point_free_15(rt, 0, heap); return err; } @@ -22301,6 +22497,10 @@ static void sp_384_proj_to_affine_15(sp_point_384* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 48 bits between * * a The base point. * table Place to store generated point data. @@ -22310,26 +22510,30 @@ static void sp_384_proj_to_affine_15(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_15(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_15(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_15(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -22374,9 +22578,10 @@ static int sp_384_gen_stripe_table_15(const sp_point_384* a, } } - sp_384_point_free_15(s2, 0, heap); - sp_384_point_free_15(s1, 0, heap); - sp_384_point_free_15( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -22463,8 +22668,10 @@ static void sp_384_get_entry_256_15(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -22478,17 +22685,19 @@ static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 15 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 15 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -22496,27 +22705,30 @@ static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_15(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 47; + for (j=0; j<8; j++) { y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j); + x += 48; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -22530,8 +22742,10 @@ static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=46; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j); + x += 48; } sp_384_proj_point_dbl_15(rt, rt, t); @@ -22557,13 +22771,12 @@ static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(p, 0, heap); - sp_384_point_free_15(rt, 0, heap); return err; } @@ -22573,16 +22786,25 @@ static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[15]; + /* Y ordinate of point that table was generated from. */ sp_digit y[15]; + /* Precomputation table for point. */ sp_table_entry_384 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -22590,9 +22812,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -22709,28 +22937,31 @@ static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[15]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[15]; +#endif int err = MP_OKAY; - err = sp_384_point_new_15(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 15, km); sp_384_point_from_ecc_point_15(point, gm); @@ -22741,12 +22972,92 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_15(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[15 + 15 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (15 + 15 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_15(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 15; + + sp_384_from_mp(k, 15, km); + sp_384_point_from_ecc_point_15(point, gm); + sp_384_point_from_ecc_point_15(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_15(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_15(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_15(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_15(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_15(point, point, addP, tmp); + + if (map) { + sp_384_map_15(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_15(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -22769,6 +23080,10 @@ static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 48 between points. + */ static const sp_table_entry_384 p384_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -24563,6 +24878,11 @@ static const sp_table_entry_384 p384_table[256] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -24588,28 +24908,30 @@ static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[15]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[15]; +#endif int err = MP_OKAY; - err = sp_384_point_new_15(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 15, km); @@ -24619,12 +24941,90 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_15(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[15 + 15 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (15 + 15 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_15(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 15; + + sp_384_from_mp(k, 15, km); + sp_384_point_from_ecc_point_15(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_15(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_15(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_15(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_15(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_15(point, point, addP, tmp); + + if (map) { + sp_384_map_15(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_15(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -24643,7 +25043,7 @@ static int sp_384_iszero_15(const sp_digit* a) a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * r A single precision integer. @@ -24664,7 +25064,8 @@ SP_NOINLINE static void sp_384_add_one_15(sp_digit* a) */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -24727,41 +25128,46 @@ static int sp_384_ecc_gen_k_15(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[15]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[15]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_384_point_new_15(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_15(rng, k); } if (err == MP_OKAY) { @@ -24786,15 +25192,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_15(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_15(infinity, 1, heap); -#endif - sp_384_point_free_15(point, 1, heap); return err; } @@ -24808,7 +25213,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_384_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<14; i++) { r[i+1] += r[i] >> 26; @@ -24853,33 +25261,35 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[15]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[15]; +#endif int err = MP_OKAY; if (*outLen < 48U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -24892,12 +25302,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(point, 0, heap); return err; } @@ -24968,17 +25378,19 @@ SP_NOINLINE static void sp_384_mul_d_15(sp_digit* r, const sp_digit* a, static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 26 bits from d1 and top 5 bits from d0. */ - d = (d1 << 5) | (d0 >> 21); + d = (d1 << 5) + (d0 >> 21); r = d / dv; d -= r * dv; /* Up to 6 bits in r */ /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 16) & ((1 << 5) - 1); + d += (d0 >> 16) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -24986,7 +25398,7 @@ static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 11) & ((1 << 5) - 1); + d += (d0 >> 11) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -24994,7 +25406,7 @@ static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 6) & ((1 << 5) - 1); + d += (d0 >> 6) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -25002,7 +25414,7 @@ static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, /* Next 5 bits from d0. */ r <<= 5; d <<= 5; - d |= (d0 >> 1) & ((1 << 5) - 1); + d += (d0 >> 1) & ((1 << 5) - 1); t = d / dv; d -= t * dv; r += t; @@ -25010,10 +25422,11 @@ static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, /* Remaining 1 bits from d0. */ r <<= 1; d <<= 1; - d |= d0 & ((1 << 1) - 1); + d += d0 & ((1 << 1) - 1); t = d / dv; r += t; + /* All 26 bits from d1 and top 5 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_32 */ @@ -25021,66 +25434,60 @@ static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_384_div_15(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_384_div_15(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_32 int64_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[30], t2d[15 + 1]; + sp_digit t1[3 * 15 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 15 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 15 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 15; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 15; dv = d[14]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 15U); for (i=14; i>=0; i--) { - sp_digit hi; t1[15 + i] += t1[15 + i - 1] >> 26; t1[15 + i - 1] &= 0x3ffffff; - hi = t1[15 + i] - (t1[15 + i] == dv); #ifndef WOLFSSL_SP_DIV_32 - d1 = hi; + d1 = t1[15 + i]; d1 <<= 26; d1 += t1[15 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_384_div_word_15(hi, t1[15 + i - 1], dv); + r1 = sp_384_div_word_15(t1[15 + i], t1[15 + i - 1], dv); #endif sp_384_mul_d_15(t2, d, r1); (void)sp_384_sub_15(&t1[i], &t1[i], t2); + sp_384_norm_15(&t1[i]); t1[15 + i] -= t2[15]; t1[15 + i] += t1[15 + i - 1] >> 26; t1[15 + i - 1] &= 0x3ffffff; @@ -25097,7 +25504,7 @@ static int sp_384_div_15(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_384_mul_d_15(t2, d, r1); (void)sp_384_sub_15(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 15U); + XMEMCPY(r, t1, sizeof(*r) * 30U); for (i=0; i<14; i++) { r[i+1] += r[i] >> 26; r[i] &= 0x3ffffff; @@ -25106,10 +25513,9 @@ static int sp_384_div_15(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -25139,7 +25545,6 @@ static const uint32_t p384_order_minus_2[12] = { /* The low half of the order-2 of the P384 curve. */ static const uint32_t p384_order_low[6] = { 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U - }; #endif /* WOLFSSL_SP_SMALL */ @@ -25287,7 +25692,7 @@ static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_15(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_15(t2, t2); - if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_384_mont_mul_order_15(t2, t2, a); } } @@ -25296,12 +25701,63 @@ static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_15(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_15(k, k, p384_norm_order); + err = sp_384_mod_15(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_15(k); + + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_15(kInv, k, tmp); + sp_384_norm_15(kInv); + + /* s = r * x + e */ + sp_384_mul_15(x, x, r); + err = sp_384_mod_15(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_15(x); + carry = sp_384_add_15(s, e, x); + sp_384_cond_sub_15(s, s, p384_order, 0 - carry); + sp_384_norm_15(s); + c = sp_384_cmp_15(s, p384_order); + sp_384_cond_sub_15(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_15(s, s, kInv); + sp_384_norm_15(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -25336,8 +25792,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -25355,13 +25811,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 15, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 15, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_15(rng, ctx->k); @@ -25389,6 +25842,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_15(ctx->r, p384_order); sp_384_cond_sub_15(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_15(ctx->r); + + sp_384_from_mp(ctx->x, 15, priv); + sp_384_from_bin(ctx->e, 15, hash, (int)hashLen); ctx->state = 4; break; } @@ -25445,6 +25901,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -25477,72 +25936,55 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*15]; - sp_digit xd[2*15]; - sp_digit kd[2*15]; - sp_digit rd[2*15]; - sp_digit td[3 * 2*15]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 15]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_384_point_new_15(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 15; - x = d + 2 * 15; - k = d + 4 * 15; - r = d + 6 * 15; - tmp = d + 8 * 15; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 15; + k = e + 4 * 15; + r = e + 6 * 15; + tmp = e + 8 * 15; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 15, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 15, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_15(rng, k); @@ -25552,7 +25994,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -25563,38 +26005,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_15(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_15(r); - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_15(k, k, p384_norm_order); - err = sp_384_mod_15(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_15(k); - /* kInv = 1/k mod order */ - sp_384_mont_inv_order_15(kInv, k, tmp); - sp_384_norm_15(kInv); + sp_384_from_mp(x, 15, priv); + sp_384_from_bin(e, 15, hash, (int)hashLen); - /* s = r * x + e */ - sp_384_mul_15(x, x, r); - err = sp_384_mod_15(x, x, p384_order); + err = sp_384_calc_s_15(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_15(x); - carry = sp_384_add_15(s, e, x); - sp_384_cond_sub_15(s, s, p384_order, 0 - carry); - sp_384_norm_15(s); - c = sp_384_cmp_15(s, p384_order); - sp_384_cond_sub_15(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_15(s); - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_15(s, s, kInv); - sp_384_norm_15(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_15(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_15(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -25608,20 +26031,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 15); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 15U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_15(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 15); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -25671,20 +26098,18 @@ static int sp_384_num_bits_15(const sp_digit* a) static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m) { int err = MP_OKAY; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - sp_digit* u; - sp_digit* v; - sp_digit* b; - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u = NULL; #else - sp_digit u[15]; - sp_digit v[15]; - sp_digit b[15]; - sp_digit d[15]; + sp_digit u[15 * 4]; #endif - int ut, vt; + sp_digit* v = NULL; + sp_digit* b = NULL; + sp_digit* d = NULL; + int ut; + int vt; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, NULL, DYNAMIC_TYPE_ECC); if (u == NULL) @@ -25692,11 +26117,9 @@ static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m) #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) v = u + 15; b = u + 2 * 15; d = u + 3 * 15; -#endif XMEMCPY(u, m, sizeof(sp_digit) * 15); XMEMCPY(v, a, sizeof(sp_digit) * 15); @@ -25774,7 +26197,7 @@ static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m) else XMEMCPY(r, d, sizeof(sp_digit) * 15); } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (u != NULL) XFREE(u, NULL, DYNAMIC_TYPE_ECC); #endif @@ -25783,6 +26206,103 @@ static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_15(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ + + sp_384_proj_point_add_15(p1, p1, p2, tmp); + if (sp_384_iszero_15(p1->z)) { + if (sp_384_iszero_15(p1->x) && sp_384_iszero_15(p1->y)) { + sp_384_proj_point_dbl_15(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + p1->x[12] = 0; + p1->x[13] = 0; + p1->x[14] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_15(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_15(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_384_mul_15(s, s, p384_norm_order); + } + err = sp_384_mod_15(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_15(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_384_mont_inv_order_15(s, s, tmp); + sp_384_mont_mul_order_15(u1, u1, s); + sp_384_mont_mul_order_15(u2, u2, s); + } + +#else + { + sp_384_mont_mul_order_15(u1, u1, s); + sp_384_mont_mul_order_15(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_384_ecc_mulmod_base_15(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_15(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_15(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_15(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_15(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -25801,8 +26321,7 @@ static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -25821,8 +26340,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -25837,7 +26357,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 15, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 15, r); + sp_384_from_mp(ctx->u2, 15, rm); sp_384_from_mp(ctx->s, 15, sm); sp_384_from_mp(ctx->p2.x, 15, pX); sp_384_from_mp(ctx->p2.y, 15, pY); @@ -25895,57 +26415,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_15(ctx->p1.z)) { - if (sp_384_iszero_15(ctx->p1.x) && sp_384_iszero_15(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<15; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 15, r); + sp_384_from_mp(ctx->u2, 15, rm); err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_15(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 15, r); + sp_384_from_mp(ctx->u2, 15, rm); carry = sp_384_add_15(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -25953,22 +26449,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_15(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -25976,137 +26473,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*15]; - sp_digit u2d[2*15]; - sp_digit sd[2*15]; - sp_digit tmpd[2*15 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 15]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_15(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 15, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 15, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 15; - u2 = d + 2 * 15; - s = d + 4 * 15; - tmp = d + 6 * 15; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 15; + s = u1 + 4 * 15; + tmp = u1 + 6 * 15; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 15, hash, (int)hashLen); - sp_384_from_mp(u2, 15, r); + sp_384_from_mp(u2, 15, rm); sp_384_from_mp(s, 15, sm); sp_384_from_mp(p2->x, 15, pX); sp_384_from_mp(p2->y, 15, pY); sp_384_from_mp(p2->z, 15, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_15(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_384_mul_15(s, s, p384_norm_order); - } - err = sp_384_mod_15(s, s, p384_order); + err = sp_384_calc_vfy_point_15(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_15(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_384_mont_inv_order_15(s, s, tmp); - sp_384_mont_mul_order_15(u1, u1, s); - sp_384_mont_mul_order_15(u2, u2, s); - } - -#else - { - sp_384_mont_mul_order_15(u1, u1, s); - sp_384_mont_mul_order_15(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_384_ecc_mulmod_base_15(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_15(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_15(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_15(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_384_proj_point_add_15(p1, p1, p2, tmp); - if (sp_384_iszero_15(p1->z)) { - if (sp_384_iszero_15(p1->x) && sp_384_iszero_15(p1->y)) { - sp_384_proj_point_dbl_15(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - p1->x[8] = 0; - p1->x[9] = 0; - p1->x[10] = 0; - p1->x[11] = 0; - p1->x[12] = 0; - p1->x[13] = 0; - p1->x[14] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 15, r); + sp_384_from_mp(u2, 15, rm); err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); } @@ -26117,7 +26540,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_15(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 15, r); + sp_384_from_mp(u2, 15, rm); carry = sp_384_add_15(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -26125,26 +26548,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_15(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_15(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_15(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(p1, 0, heap); - sp_384_point_free_15(p2, 0, heap); return err; } @@ -26158,34 +26581,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_15(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_15(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*15]; - sp_digit t2d[2*15]; + sp_digit t1[15 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 15; - t2 = d + 2 * 15; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 15; sp_384_sqr_15(t1, point->y); (void)sp_384_mod_15(t1, t1, p384_mod); @@ -26205,10 +26620,9 @@ static int sp_384_ecc_is_point_15(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -26221,16 +26635,23 @@ static int sp_384_ecc_is_point_15(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_15(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 15, pX); sp_384_from_mp(pub->y, 15, pY); @@ -26239,7 +26660,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_15(pub, NULL); } - sp_384_point_free_15(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -26255,47 +26679,48 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[15]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; - sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_384_point_new_15(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_15(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_384* pub = NULL; +#else + sp_digit priv[15]; + sp_point_384 pub[2]; #endif + sp_point_384* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 15, pX); sp_384_from_mp(pub->y, 15, pY); sp_384_from_bin(pub->z, 15, one, (int)sizeof(one)); @@ -26309,12 +26734,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_15(pub->x, p384_mod) >= 0 || - sp_384_cmp_15(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_15(pub->x, p384_mod) >= 0) || + (sp_384_cmp_15(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -26326,12 +26750,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_384_ecc_mulmod_15(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_15(p->x) == 0) || - (sp_384_iszero_15(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_15(p->x) == 0) || + (sp_384_iszero_15(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -26339,22 +26761,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_384_ecc_mulmod_base_15(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_15(p->x, pub->x) != 0 || - sp_384_cmp_15(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_15(p->x, pub->x) != 0) || + (sp_384_cmp_15(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_15(p, 0, heap); - sp_384_point_free_15(pub, 0, heap); return err; } @@ -26378,33 +26798,35 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 15 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 15 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; - err = sp_384_point_new_15(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_15(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 15, pX); sp_384_from_mp(p->y, 15, pY); sp_384_from_mp(p->z, 15, pZ); @@ -26425,13 +26847,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(q, 0, NULL); - sp_384_point_free_15(p, 0, NULL); return err; } @@ -26450,25 +26871,28 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 15 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 15 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_15(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -26489,12 +26913,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(p, 0, NULL); return err; } @@ -26509,32 +26933,36 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 15 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 15 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_15(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 15, pX); sp_384_from_mp(p->y, 15, pY); sp_384_from_mp(p->z, 15, pZ); - sp_384_map_15(p, p, tmp); + sp_384_map_15(p, p, tmp); } if (err == MP_OKAY) { @@ -26547,12 +26975,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_15(p, 0, NULL); return err; } @@ -26565,43 +26993,28 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_15(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 15]; - sp_digit t2d[2 * 15]; - sp_digit t3d[2 * 15]; - sp_digit t4d[2 * 15]; - sp_digit t5d[2 * 15]; + sp_digit t1[5 * 2 * 15]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 15, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 15, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 15; - t2 = d + 2 * 15; - t3 = d + 4 * 15; - t4 = d + 6 * 15; - t5 = d + 8 * 15; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 15; + t3 = t1 + 4 * 15; + t4 = t1 + 6 * 15; + t5 = t1 + 8 * 15; { /* t2 = y ^ 0x2 */ @@ -26661,10 +27074,9 @@ static int sp_384_mont_sqrt_15(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -26680,31 +27092,22 @@ static int sp_384_mont_sqrt_15(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 15]; - sp_digit yd[2 * 15]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 15]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 15, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 15, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 15; - y = d + 2 * 15; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 15; sp_384_from_mp(x, 15, xm); err = sp_384_mod_mul_norm_15(x, x, p384_mod); @@ -26737,17 +27140,11312 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 42]; + /* Y ordinate of point. */ + sp_digit y[2 * 42]; + /* Z ordinate of point. */ + sp_digit z[2 * 42]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int64_t t0 = ((int64_t)a[ 0]) * b[ 0]; + int64_t t1 = ((int64_t)a[ 0]) * b[ 1] + + ((int64_t)a[ 1]) * b[ 0]; + int64_t t2 = ((int64_t)a[ 0]) * b[ 2] + + ((int64_t)a[ 1]) * b[ 1] + + ((int64_t)a[ 2]) * b[ 0]; + int64_t t3 = ((int64_t)a[ 0]) * b[ 3] + + ((int64_t)a[ 1]) * b[ 2] + + ((int64_t)a[ 2]) * b[ 1] + + ((int64_t)a[ 3]) * b[ 0]; + int64_t t4 = ((int64_t)a[ 0]) * b[ 4] + + ((int64_t)a[ 1]) * b[ 3] + + ((int64_t)a[ 2]) * b[ 2] + + ((int64_t)a[ 3]) * b[ 1] + + ((int64_t)a[ 4]) * b[ 0]; + int64_t t5 = ((int64_t)a[ 0]) * b[ 5] + + ((int64_t)a[ 1]) * b[ 4] + + ((int64_t)a[ 2]) * b[ 3] + + ((int64_t)a[ 3]) * b[ 2] + + ((int64_t)a[ 4]) * b[ 1] + + ((int64_t)a[ 5]) * b[ 0]; + int64_t t6 = ((int64_t)a[ 0]) * b[ 6] + + ((int64_t)a[ 1]) * b[ 5] + + ((int64_t)a[ 2]) * b[ 4] + + ((int64_t)a[ 3]) * b[ 3] + + ((int64_t)a[ 4]) * b[ 2] + + ((int64_t)a[ 5]) * b[ 1] + + ((int64_t)a[ 6]) * b[ 0]; + int64_t t7 = ((int64_t)a[ 1]) * b[ 6] + + ((int64_t)a[ 2]) * b[ 5] + + ((int64_t)a[ 3]) * b[ 4] + + ((int64_t)a[ 4]) * b[ 3] + + ((int64_t)a[ 5]) * b[ 2] + + ((int64_t)a[ 6]) * b[ 1]; + int64_t t8 = ((int64_t)a[ 2]) * b[ 6] + + ((int64_t)a[ 3]) * b[ 5] + + ((int64_t)a[ 4]) * b[ 4] + + ((int64_t)a[ 5]) * b[ 3] + + ((int64_t)a[ 6]) * b[ 2]; + int64_t t9 = ((int64_t)a[ 3]) * b[ 6] + + ((int64_t)a[ 4]) * b[ 5] + + ((int64_t)a[ 5]) * b[ 4] + + ((int64_t)a[ 6]) * b[ 3]; + int64_t t10 = ((int64_t)a[ 4]) * b[ 6] + + ((int64_t)a[ 5]) * b[ 5] + + ((int64_t)a[ 6]) * b[ 4]; + int64_t t11 = ((int64_t)a[ 5]) * b[ 6] + + ((int64_t)a[ 6]) * b[ 5]; + int64_t t12 = ((int64_t)a[ 6]) * b[ 6]; + + t1 += t0 >> 25; r[ 0] = t0 & 0x1ffffff; + t2 += t1 >> 25; r[ 1] = t1 & 0x1ffffff; + t3 += t2 >> 25; r[ 2] = t2 & 0x1ffffff; + t4 += t3 >> 25; r[ 3] = t3 & 0x1ffffff; + t5 += t4 >> 25; r[ 4] = t4 & 0x1ffffff; + t6 += t5 >> 25; r[ 5] = t5 & 0x1ffffff; + t7 += t6 >> 25; r[ 6] = t6 & 0x1ffffff; + t8 += t7 >> 25; r[ 7] = t7 & 0x1ffffff; + t9 += t8 >> 25; r[ 8] = t8 & 0x1ffffff; + t10 += t9 >> 25; r[ 9] = t9 & 0x1ffffff; + t11 += t10 >> 25; r[10] = t10 & 0x1ffffff; + t12 += t11 >> 25; r[11] = t11 & 0x1ffffff; + r[13] = (sp_digit)(t12 >> 25); + r[12] = t12 & 0x1ffffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_7(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; + int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; + int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 + + ((int64_t)a[ 1]) * a[ 1]; + int64_t t3 = (((int64_t)a[ 0]) * a[ 3] + + ((int64_t)a[ 1]) * a[ 2]) * 2; + int64_t t4 = (((int64_t)a[ 0]) * a[ 4] + + ((int64_t)a[ 1]) * a[ 3]) * 2 + + ((int64_t)a[ 2]) * a[ 2]; + int64_t t5 = (((int64_t)a[ 0]) * a[ 5] + + ((int64_t)a[ 1]) * a[ 4] + + ((int64_t)a[ 2]) * a[ 3]) * 2; + int64_t t6 = (((int64_t)a[ 0]) * a[ 6] + + ((int64_t)a[ 1]) * a[ 5] + + ((int64_t)a[ 2]) * a[ 4]) * 2 + + ((int64_t)a[ 3]) * a[ 3]; + int64_t t7 = (((int64_t)a[ 1]) * a[ 6] + + ((int64_t)a[ 2]) * a[ 5] + + ((int64_t)a[ 3]) * a[ 4]) * 2; + int64_t t8 = (((int64_t)a[ 2]) * a[ 6] + + ((int64_t)a[ 3]) * a[ 5]) * 2 + + ((int64_t)a[ 4]) * a[ 4]; + int64_t t9 = (((int64_t)a[ 3]) * a[ 6] + + ((int64_t)a[ 4]) * a[ 5]) * 2; + int64_t t10 = (((int64_t)a[ 4]) * a[ 6]) * 2 + + ((int64_t)a[ 5]) * a[ 5]; + int64_t t11 = (((int64_t)a[ 5]) * a[ 6]) * 2; + int64_t t12 = ((int64_t)a[ 6]) * a[ 6]; + + t1 += t0 >> 25; r[ 0] = t0 & 0x1ffffff; + t2 += t1 >> 25; r[ 1] = t1 & 0x1ffffff; + t3 += t2 >> 25; r[ 2] = t2 & 0x1ffffff; + t4 += t3 >> 25; r[ 3] = t3 & 0x1ffffff; + t5 += t4 >> 25; r[ 4] = t4 & 0x1ffffff; + t6 += t5 >> 25; r[ 5] = t5 & 0x1ffffff; + t7 += t6 >> 25; r[ 6] = t6 & 0x1ffffff; + t8 += t7 >> 25; r[ 7] = t7 & 0x1ffffff; + t9 += t8 >> 25; r[ 8] = t8 & 0x1ffffff; + t10 += t9 >> 25; r[ 9] = t9 & 0x1ffffff; + t11 += t10 >> 25; r[10] = t10 & 0x1ffffff; + t12 += t11 >> 25; r[11] = t11 & 0x1ffffff; + r[13] = (sp_digit)(t12 >> 25); + r[12] = t12 & 0x1ffffff; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_sub_14(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + r[ 5] = a[ 5] - b[ 5]; + r[ 6] = a[ 6] - b[ 6]; + r[ 7] = a[ 7] - b[ 7]; + r[ 8] = a[ 8] - b[ 8]; + r[ 9] = a[ 9] - b[ 9]; + r[10] = a[10] - b[10]; + r[11] = a[11] - b[11]; + r[12] = a[12] - b[12]; + r[13] = a[13] - b[13]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_14(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + r[ 9] = a[ 9] + b[ 9]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + r[13] = a[13] + b[13]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_21(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[14]; + sp_digit p1[14]; + sp_digit p2[14]; + sp_digit p3[14]; + sp_digit p4[14]; + sp_digit p5[14]; + sp_digit t0[14]; + sp_digit t1[14]; + sp_digit t2[14]; + sp_digit a0[7]; + sp_digit a1[7]; + sp_digit a2[7]; + sp_digit b0[7]; + sp_digit b1[7]; + sp_digit b2[7]; + (void)sp_1024_add_7(a0, a, &a[7]); + (void)sp_1024_add_7(b0, b, &b[7]); + (void)sp_1024_add_7(a1, &a[7], &a[14]); + (void)sp_1024_add_7(b1, &b[7], &b[14]); + (void)sp_1024_add_7(a2, a0, &a[14]); + (void)sp_1024_add_7(b2, b0, &b[14]); + sp_1024_mul_7(p0, a, b); + sp_1024_mul_7(p2, &a[7], &b[7]); + sp_1024_mul_7(p4, &a[14], &b[14]); + sp_1024_mul_7(p1, a0, b0); + sp_1024_mul_7(p3, a1, b1); + sp_1024_mul_7(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2U*21U); + (void)sp_1024_sub_14(t0, p3, p2); + (void)sp_1024_sub_14(t1, p1, p2); + (void)sp_1024_sub_14(t2, p5, t0); + (void)sp_1024_sub_14(t2, t2, t1); + (void)sp_1024_sub_14(t0, t0, p4); + (void)sp_1024_sub_14(t1, t1, p0); + (void)sp_1024_add_14(r, r, p0); + (void)sp_1024_add_14(&r[7], &r[7], t1); + (void)sp_1024_add_14(&r[14], &r[14], t2); + (void)sp_1024_add_14(&r[21], &r[21], t0); + (void)sp_1024_add_14(&r[28], &r[28], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_21(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[14]; + sp_digit p1[14]; + sp_digit p2[14]; + sp_digit p3[14]; + sp_digit p4[14]; + sp_digit p5[14]; + sp_digit t0[14]; + sp_digit t1[14]; + sp_digit t2[14]; + sp_digit a0[7]; + sp_digit a1[7]; + sp_digit a2[7]; + (void)sp_1024_add_7(a0, a, &a[7]); + (void)sp_1024_add_7(a1, &a[7], &a[14]); + (void)sp_1024_add_7(a2, a0, &a[14]); + sp_1024_sqr_7(p0, a); + sp_1024_sqr_7(p2, &a[7]); + sp_1024_sqr_7(p4, &a[14]); + sp_1024_sqr_7(p1, a0); + sp_1024_sqr_7(p3, a1); + sp_1024_sqr_7(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2U*21U); + (void)sp_1024_sub_14(t0, p3, p2); + (void)sp_1024_sub_14(t1, p1, p2); + (void)sp_1024_sub_14(t2, p5, t0); + (void)sp_1024_sub_14(t2, t2, t1); + (void)sp_1024_sub_14(t0, t0, p4); + (void)sp_1024_sub_14(t1, t1, p0); + (void)sp_1024_add_14(r, r, p0); + (void)sp_1024_add_14(&r[7], &r[7], t1); + (void)sp_1024_add_14(&r[14], &r[14], t2); + (void)sp_1024_add_14(&r[21], &r[21], t0); + (void)sp_1024_add_14(&r[28], &r[28], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_21(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[16] = a[16] + b[16]; + r[17] = a[17] + b[17]; + r[18] = a[18] + b[18]; + r[19] = a[19] + b[19]; + r[20] = a[20] + b[20]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_42(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[40] = a[40] + b[40]; + r[41] = a[41] + b[41]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_sub_42(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[40] = a[40] - b[40]; + r[41] = a[41] - b[41]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_42(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[42]; + sp_digit* a1 = z1; + sp_digit b1[21]; + sp_digit* z2 = r + 42; + (void)sp_1024_add_21(a1, a, &a[21]); + (void)sp_1024_add_21(b1, b, &b[21]); + sp_1024_mul_21(z2, &a[21], &b[21]); + sp_1024_mul_21(z0, a, b); + sp_1024_mul_21(z1, a1, b1); + (void)sp_1024_sub_42(z1, z1, z2); + (void)sp_1024_sub_42(z1, z1, z0); + (void)sp_1024_add_42(r + 21, r + 21, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_42(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[42]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 42; + (void)sp_1024_add_21(a1, a, &a[21]); + sp_1024_sqr_21(z2, &a[21]); + sp_1024_sqr_21(z0, a); + sp_1024_sqr_21(z1, a1); + (void)sp_1024_sub_42(z1, z1, z2); + (void)sp_1024_sub_42(z1, z1, z0); + (void)sp_1024_add_42(r + 21, r + 21, z1); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_42(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + int j; + int k; + int64_t c; + + c = ((int64_t)a[41]) * b[41]; + r[83] = (sp_digit)(c >> 25); + c = (c & 0x1ffffff) << 25; + for (k = 81; k >= 0; k--) { + for (i = 41; i >= 0; i--) { + j = k - i; + if (j >= 42) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += (sp_digit)(c >> 50); + r[k + 1] = (sp_digit)((c >> 25) & 0x1ffffff); + c = (c & 0x1ffffff) << 25; + } + r[0] = (sp_digit)(c >> 25); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_42(sp_digit* r, const sp_digit* a) +{ + int i; + int j; + int k; + int64_t c; + + c = ((int64_t)a[41]) * a[41]; + r[83] = (sp_digit)(c >> 25); + c = (c & 0x1ffffff) << 25; + for (k = 81; k >= 0; k--) { + for (i = 41; i >= 0; i--) { + j = k - i; + if (j >= 42 || i <= j) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) { + c += ((int64_t)a[i]) * a[i]; + } + + r[k + 2] += (sp_digit)(c >> 50); + r[k + 1] = (sp_digit)((c >> 25) & 0x1ffffff); + c = (c & 0x1ffffff) << 25; + } + r[0] = (sp_digit)(c >> 25); +} + +#endif /* !WOLFSSL_SP_SMALL */ +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[42] = { + 0x0a85feb,0x0c03d7f,0x1a1d99b,0x0158f59,0x00c5df1,0x02bed84,0x1a08e26, + 0x03ff9c7,0x156971f,0x1ca6b57,0x1026aa7,0x18a4387,0x02a7cf3,0x18c2954, + 0x0bfd2a0,0x039c36d,0x1cd6568,0x0289562,0x09ad335,0x18c90e6,0x06d0e26, + 0x1a53335,0x0d5b49f,0x1911432,0x1b39ff7,0x05873c8,0x14c6967,0x050e61a, + 0x1c0f1b2,0x1593f17,0x0bbd02a,0x167c034,0x09ae358,0x04130df,0x138672d, + 0x1482d81,0x1ad0657,0x0308cc6,0x0ff6997,0x03e14ac,0x0997abb,0x0000000 +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[42] = { + 0x157a015,0x13fc280,0x05e2664,0x1ea70a6,0x1f3a20e,0x1d4127b,0x05f71d9, + 0x1c00638,0x0a968e0,0x03594a8,0x0fd9558,0x075bc78,0x1d5830c,0x073d6ab, + 0x1402d5f,0x1c63c92,0x0329a97,0x1d76a9d,0x1652cca,0x0736f19,0x192f1d9, + 0x05accca,0x12a4b60,0x06eebcd,0x04c6008,0x1a78c37,0x0b39698,0x1af19e5, + 0x03f0e4d,0x0a6c0e8,0x1442fd5,0x0983fcb,0x1651ca7,0x1becf20,0x0c798d2, + 0x0b7d27e,0x052f9a8,0x1cf7339,0x1009668,0x1c1eb53,0x0668544,0x0000000 +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[42] = { + 0x1aa17fb,0x1b00f5f,0x0e87666,0x08563d6,0x003177c,0x10afb61,0x1e82389, + 0x18ffe71,0x1d5a5c7,0x1f29ad5,0x1c09aa9,0x1e290e1,0x00a9f3c,0x0630a55, + 0x0aff4a8,0x00e70db,0x173595a,0x08a2558,0x126b4cd,0x1632439,0x09b4389, + 0x1e94ccd,0x1356d27,0x1e4450c,0x06ce7fd,0x1961cf2,0x1531a59,0x1143986, + 0x1f03c6c,0x1564fc5,0x02ef40a,0x059f00d,0x1a6b8d6,0x0904c37,0x0ce19cb, + 0x1d20b60,0x16b4195,0x18c2331,0x03fda65,0x18f852b,0x0265eae,0x0000000 +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0x0e63895,0x0e455f5,0x05e6203,0x092cfc1,0x00ec46c,0x1fb9f64,0x18e96d8, + 0x10fdd22,0x080728d,0x0e7da66,0x1a44375,0x029b74c,0x14a7c15,0x1d306f3, + 0x00b0ce5,0x1e5c34e,0x0548b72,0x199be43,0x1756f32,0x015eecb,0x0890976, + 0x13a0367,0x1c62f67,0x13bf4aa,0x1f22cdb,0x10821ea,0x00c2c27,0x1621b72, + 0x0e2308a,0x1b607b6,0x0fed7b6,0x16dfef9,0x0b2f204,0x034e34c,0x1f582bb, + 0x1456345,0x1ed9b52,0x1cc8029,0x0a6b429,0x1dc6658,0x053fc09,0x0000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x1ef16d7,0x19feb8d,0x1379d55,0x00d4cfb,0x0db9b57,0x1da31b5,0x0b56b56, + 0x153017b,0x1e9cb99,0x1a8ad6b,0x1357c84,0x0f3f8b4,0x09492d9,0x0b2554c, + 0x1bc7a00,0x05fc158,0x0b5b765,0x0656b4b,0x1551f1b,0x15c22f5,0x12b970d, + 0x0654f01,0x105b3fc,0x028165c,0x18ccf9a,0x0fb35ac,0x17c3795,0x0fefebc, + 0x0ec2b9e,0x14fa32a,0x1e3d7a9,0x03c2822,0x1778d82,0x0834b1e,0x00580a6, + 0x0ba7d04,0x1634a13,0x18f8299,0x027c7e7,0x00c7ec0,0x00a8249,0x0000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_1024_mul_d_42(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 42; i++) { + t += tb * a[i]; + r[i] = (sp_digit)(t & 0x1ffffff); + t >>= 25; + } + r[42] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t = 0; + sp_digit t2; + int64_t p[4]; + int i; + + for (i = 0; i < 40; i += 4) { + p[0] = tb * a[i + 0]; + p[1] = tb * a[i + 1]; + p[2] = tb * a[i + 2]; + p[3] = tb * a[i + 3]; + t += p[0]; + t2 = (sp_digit)(t & 0x1ffffff); + t >>= 25; + r[i + 0] = (sp_digit)t2; + t += p[1]; + t2 = (sp_digit)(t & 0x1ffffff); + t >>= 25; + r[i + 1] = (sp_digit)t2; + t += p[2]; + t2 = (sp_digit)(t & 0x1ffffff); + t >>= 25; + r[i + 2] = (sp_digit)t2; + t += p[3]; + t2 = (sp_digit)(t & 0x1ffffff); + t >>= 25; + r[i + 3] = (sp_digit)t2; + } + t += tb * a[40]; + r[40] = (sp_digit)(t & 0x1ffffff); + t >>= 25; + t += tb * a[41]; + r[41] = (sp_digit)(t & 0x1ffffff); + t >>= 25; + r[42] = (sp_digit)(t & 0x1ffffff); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_1024_cond_add_42(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 42; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[40] = a[40] + (b[40] & m); + r[41] = a[41] + (b[41] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_sub_42(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 42; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#endif +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_42(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 42; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_1024_div_word_42(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d; + sp_digit r; + sp_digit t; + + /* All 25 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) + (d0 >> 19); + r = d / dv; + d -= r * dv; + /* Up to 7 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 13) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 13 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 7) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 19 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 1) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Remaining 1 bits from d0. */ + r <<= 1; + d <<= 1; + d += d0 & ((1 << 1) - 1); + t = d / dv; + r += t; + + /* All 25 bits from d1 and top 6 bits from d0. */ + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * Large number of bits in last word. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_1024_div_42(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[3 * 42 + 1]; +#endif + sp_digit* t2 = NULL; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 42 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t1 == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + t2 = t1 + 2 * 42; + + dv = d[40]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 42U); + for (i=40; i>=0; i--) { + t1[42 + i] += t1[42 + i - 1] >> 25; + t1[42 + i - 1] &= 0x1ffffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[41 + i]; + d1 <<= 25; + d1 += t1[41 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_1024_div_word_42(t1[41 + i], t1[41 + i - 1], dv); +#endif + + sp_1024_mul_d_42(t2, d, r1); + (void)sp_1024_sub_42(&t1[i], &t1[i], t2); + sp_1024_norm_42(&t1[i]); + t1[42 + i] -= t2[42]; + t1[41 + i] += t1[41 + i - 1] >> 25; + t1[41 + i - 1] &= 0x1ffffff; + r1 = (((-t1[41 + i]) << 25) - t1[41 + i - 1]) / dv; + r1++; + sp_1024_mul_d_42(t2, d, r1); + (void)sp_1024_add_42(&t1[i], &t1[i], t2); + t1[41 + i] += t1[41 + i - 1] >> 25; + t1[41 + i - 1] &= 0x1ffffff; + } + t1[41 - 1] += t1[41 - 2] >> 25; + t1[41 - 2] &= 0x1ffffff; + r1 = t1[41 - 1] / dv; + + sp_1024_mul_d_42(t2, d, r1); + (void)sp_1024_sub_42(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 84U); + for (i=0; i<40; i++) { + r[i+1] += r[i] >> 25; + r[i] &= 0x1ffffff; + } + sp_1024_cond_add_42(r, r, d, 0 - ((r[40] < 0) ? + (sp_digit)1 : (sp_digit)0)); + r[41] = 0; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_1024_mod_42(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_1024_div_42(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_42(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + sp_1024_mul_42(r, a, p1024_norm_mod); + return sp_1024_mod_42(r, r, m); +} + + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_42(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_42(heap, sp, p) sp_1024_point_new_ex_42((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_42(heap, sp, p) sp_1024_point_new_ex_42((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_42(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 25 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 25 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x1ffffff; + s = 25U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 25U) <= (word32)DIGIT_BIT) { + s += 25U; + r[j] &= 0x1ffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 25) { + r[j] &= 0x1ffffff; + if (j + 1 >= size) { + break; + } + s = 25 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_42(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 42, pm->x); + sp_1024_from_mp(p->y, 42, pm->y); + sp_1024_from_mp(p->z, 42, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 25 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 42); + r->used = 42; + mp_clamp(r); +#elif DIGIT_BIT < 25 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 42; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 25) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 25 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 42; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 25 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 25 - s; + } + else { + s += 25; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_42(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_1024_cmp_42(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=41; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[41] - b[41]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[40] - b[40]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 32; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_1024_cond_sub_42(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 42; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[40] = a[40] - (b[40] & m); + r[41] = a[41] - (b[41] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_1024_mul_add_42(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 42; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffff; + t >>= 25; + } + r[42] += (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffff); + for (i = 0; i < 40; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 25) + (t[5] & 0x1ffffff)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 25) + (t[6] & 0x1ffffff)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 25) + (t[7] & 0x1ffffff)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 25) + (t[0] & 0x1ffffff)); + } + t[1] = tb * a[41]; r[41] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff)); + r[42] += (sp_digit)(t[1] >> 25); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 25. + * + * a Array of sp_digit to normalize. + */ +static void sp_1024_norm_42(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 41; i++) { + a[i+1] += a[i] >> 25; + a[i] &= 0x1ffffff; + } +#else + int i; + for (i = 0; i < 40; i += 8) { + a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff; + a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff; + a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff; + a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff; + a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff; + a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff; + a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff; + a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff; + } + a[40+1] += a[40] >> 25; a[40] &= 0x1ffffff; +#endif +} + +/* Shift the result in the high 1024 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_1024_mont_shift_42(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word32 n; + + n = a[40] >> 24; + for (i = 0; i < 40; i++) { + n += (word32)a[41 + i] << 1; + r[i] = n & 0x1ffffff; + n >>= 25; + } + n += (word32)a[81] << 1; + r[40] = n; +#else + word32 n; + int i; + + n = (word32)a[40]; + n = n >> 24U; + for (i = 0; i < 40; i += 8) { + n += (word32)a[i+41] << 1U; r[i+0] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+42] << 1U; r[i+1] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+43] << 1U; r[i+2] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+44] << 1U; r[i+3] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+45] << 1U; r[i+4] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+46] << 1U; r[i+5] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+47] << 1U; r[i+6] = n & 0x1ffffff; n >>= 25U; + n += (word32)a[i+48] << 1U; r[i+7] = n & 0x1ffffff; n >>= 25U; + } + n += (word32)a[81] << 1U; r[40] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[41], 0, sizeof(*r) * 41U); +} + +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_1024_mont_reduce_42(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_1024_norm_42(a + 41); + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<40; i++) { + mu = (a[i] * mp) & 0x1ffffff; + sp_1024_mul_add_42(a+i, m, mu); + a[i+1] += a[i] >> 25; + } + mu = (a[i] * mp) & 0xffffffL; + sp_1024_mul_add_42(a+i, m, mu); + a[i+1] += a[i] >> 25; + a[i] &= 0x1ffffff; + } + else { + for (i=0; i<40; i++) { + mu = a[i] & 0x1ffffff; + sp_1024_mul_add_42(a+i, m, mu); + a[i+1] += a[i] >> 25; + } + mu = a[i] & 0xffffffL; + sp_1024_mul_add_42(a+i, m, mu); + a[i+1] += a[i] >> 25; + a[i] &= 0x1ffffff; + } +#else + for (i=0; i<40; i++) { + mu = (a[i] * mp) & 0x1ffffff; + sp_1024_mul_add_42(a+i, m, mu); + a[i+1] += a[i] >> 25; + } + mu = (a[i] * mp) & 0xffffffL; + sp_1024_mul_add_42(a+i, m, mu); + a[i+1] += a[i] >> 25; + a[i] &= 0x1ffffff; +#endif + sp_1024_norm_42(a + 41); + sp_1024_mont_shift_42(a, a); + sp_1024_cond_sub_42(a, a, m, 0 - (((a[40] - m[40]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_42(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_42(r, a, b); + sp_1024_mont_reduce_42(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_42(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_42(r, a); + sp_1024_mont_reduce_42(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_42(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 42]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 42); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_42(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_42(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 42); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_42(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_42(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_42(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_42(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*42; + int32_t n; + + sp_1024_mont_inv_42(t1, p->z, t + 2*42); + + sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_42(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 42, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_42(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_42(r->x, p1024_mod); + sp_1024_cond_sub_42(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_42(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 42, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_42(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_42(r->y, p1024_mod); + sp_1024_cond_sub_42(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_add_42(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_1024_add_42(r, a, b); + sp_1024_norm_42(r); + sp_1024_cond_sub_42(r, r, m, 0 - (((r[40] - m[40]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(r); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_dbl_42(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_1024_add_42(r, a, a); + sp_1024_norm_42(r); + sp_1024_cond_sub_42(r, r, m, 0 - (((r[40] - m[40]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(r); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_tpl_42(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_1024_add_42(r, a, a); + sp_1024_norm_42(r); + sp_1024_cond_sub_42(r, r, m, 0 - (((r[40] - m[40]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(r); + (void)sp_1024_add_42(r, r, a); + sp_1024_norm_42(r); + sp_1024_cond_sub_42(r, r, m, 0 - (((r[40] - m[40]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(r); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_sub_42(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_1024_sub_42(r, a, b); + sp_1024_norm_42(r); + sp_1024_cond_add_42(r, r, m, r[41] >> 7); + sp_1024_norm_42(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +SP_NOINLINE static void sp_1024_rshift1_42(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<41; i++) { + r[i] = (a[i] >> 1) + ((a[i + 1] << 24) & 0x1ffffff); + } +#else + r[0] = (a[0] >> 1) + ((a[1] << 24) & 0x1ffffff); + r[1] = (a[1] >> 1) + ((a[2] << 24) & 0x1ffffff); + r[2] = (a[2] >> 1) + ((a[3] << 24) & 0x1ffffff); + r[3] = (a[3] >> 1) + ((a[4] << 24) & 0x1ffffff); + r[4] = (a[4] >> 1) + ((a[5] << 24) & 0x1ffffff); + r[5] = (a[5] >> 1) + ((a[6] << 24) & 0x1ffffff); + r[6] = (a[6] >> 1) + ((a[7] << 24) & 0x1ffffff); + r[7] = (a[7] >> 1) + ((a[8] << 24) & 0x1ffffff); + r[8] = (a[8] >> 1) + ((a[9] << 24) & 0x1ffffff); + r[9] = (a[9] >> 1) + ((a[10] << 24) & 0x1ffffff); + r[10] = (a[10] >> 1) + ((a[11] << 24) & 0x1ffffff); + r[11] = (a[11] >> 1) + ((a[12] << 24) & 0x1ffffff); + r[12] = (a[12] >> 1) + ((a[13] << 24) & 0x1ffffff); + r[13] = (a[13] >> 1) + ((a[14] << 24) & 0x1ffffff); + r[14] = (a[14] >> 1) + ((a[15] << 24) & 0x1ffffff); + r[15] = (a[15] >> 1) + ((a[16] << 24) & 0x1ffffff); + r[16] = (a[16] >> 1) + ((a[17] << 24) & 0x1ffffff); + r[17] = (a[17] >> 1) + ((a[18] << 24) & 0x1ffffff); + r[18] = (a[18] >> 1) + ((a[19] << 24) & 0x1ffffff); + r[19] = (a[19] >> 1) + ((a[20] << 24) & 0x1ffffff); + r[20] = (a[20] >> 1) + ((a[21] << 24) & 0x1ffffff); + r[21] = (a[21] >> 1) + ((a[22] << 24) & 0x1ffffff); + r[22] = (a[22] >> 1) + ((a[23] << 24) & 0x1ffffff); + r[23] = (a[23] >> 1) + ((a[24] << 24) & 0x1ffffff); + r[24] = (a[24] >> 1) + ((a[25] << 24) & 0x1ffffff); + r[25] = (a[25] >> 1) + ((a[26] << 24) & 0x1ffffff); + r[26] = (a[26] >> 1) + ((a[27] << 24) & 0x1ffffff); + r[27] = (a[27] >> 1) + ((a[28] << 24) & 0x1ffffff); + r[28] = (a[28] >> 1) + ((a[29] << 24) & 0x1ffffff); + r[29] = (a[29] >> 1) + ((a[30] << 24) & 0x1ffffff); + r[30] = (a[30] >> 1) + ((a[31] << 24) & 0x1ffffff); + r[31] = (a[31] >> 1) + ((a[32] << 24) & 0x1ffffff); + r[32] = (a[32] >> 1) + ((a[33] << 24) & 0x1ffffff); + r[33] = (a[33] >> 1) + ((a[34] << 24) & 0x1ffffff); + r[34] = (a[34] >> 1) + ((a[35] << 24) & 0x1ffffff); + r[35] = (a[35] >> 1) + ((a[36] << 24) & 0x1ffffff); + r[36] = (a[36] >> 1) + ((a[37] << 24) & 0x1ffffff); + r[37] = (a[37] >> 1) + ((a[38] << 24) & 0x1ffffff); + r[38] = (a[38] >> 1) + ((a[39] << 24) & 0x1ffffff); + r[39] = (a[39] >> 1) + ((a[40] << 24) & 0x1ffffff); + r[40] = (a[40] >> 1) + ((a[41] << 24) & 0x1ffffff); +#endif + r[41] = a[41] >> 1; +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_1024_div2_42(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_1024_cond_add_42(r, a, m, 0 - (a[0] & 1)); + sp_1024_norm_42(r); + sp_1024_rshift1_42(r, r); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_42_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_42_ctx; + +static int sp_1024_proj_point_dbl_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_42_ctx* ctx = (sp_1024_proj_point_dbl_42_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*42; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_42(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_42(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_42(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_42(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_42(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_42(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_42(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_42(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_42(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_42(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_42(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_42(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_42(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_42(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*42; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_42(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_42(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_42(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_42(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_42(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_42(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_42(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_42(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_42(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_42(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_42(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_42(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_42(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_42(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_42(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_42(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_42(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_42(y, y, t2, p1024_mod); +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_42(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) | + (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) | + (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) | + (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) | + (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31]) | + (a[32] ^ b[32]) | (a[33] ^ b[33]) | (a[34] ^ b[34]) | (a[35] ^ b[35]) | + (a[36] ^ b[36]) | (a[37] ^ b[37]) | (a[38] ^ b[38]) | (a[39] ^ b[39]) | + (a[40] ^ b[40]) | (a[41] ^ b[41])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_42_ctx { + int state; + sp_1024_proj_point_dbl_42_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_42_ctx; + +static int sp_1024_proj_point_add_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_42_ctx* ctx = (sp_1024_proj_point_add_42_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*42; + ctx->t3 = t + 4*42; + ctx->t4 = t + 6*42; + ctx->t5 = t + 8*42; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_42(ctx->t1, p1024_mod, q->y); + sp_1024_norm_42(ctx->t1); + if ((sp_1024_cmp_equal_42(p->x, q->x) & sp_1024_cmp_equal_42(p->z, q->z) & + (sp_1024_cmp_equal_42(p->y, q->y) | sp_1024_cmp_equal_42(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_42_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<42; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<42; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<42; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_42(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_42(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_42(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_42(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_42(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_42(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_42(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_42(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_42(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_42(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_42(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_42(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_42(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_42(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_42(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_42(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_42(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*42; + sp_digit* t3 = t + 4*42; + sp_digit* t4 = t + 6*42; + sp_digit* t5 = t + 8*42; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_42(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_42(t1); + if ((sp_1024_cmp_equal_42(p->x, q->x) & sp_1024_cmp_equal_42(p->z, q->z) & + (sp_1024_cmp_equal_42(p->y, q->y) | sp_1024_cmp_equal_42(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_42(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<42; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<42; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<42; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_42(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_42(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_42(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_42(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_42(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_42(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_42(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(x, x, t5, p1024_mod); + sp_1024_mont_dbl_42(t1, y, p1024_mod); + sp_1024_mont_sub_42(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_42(y, y, x, p1024_mod); + sp_1024_mont_mul_42(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(y, y, t5, p1024_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Small implementation using add and double that is cache attack resistant but + * allocates memory rather than use large stacks. + * 1024 adds and doubles. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_ecc_mulmod_42_ctx { + int state; + union { + sp_1024_proj_point_dbl_42_ctx dbl_ctx; + sp_1024_proj_point_add_42_ctx add_ctx; + }; + sp_point_1024 t[3]; + sp_digit tmp[2 * 42 * 5]; + sp_digit n; + int i; + int c; + int y; +} sp_1024_ecc_mulmod_42_ctx; + +static int sp_1024_ecc_mulmod_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* g, const sp_digit* k, int map, int ct, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_1024_ecc_mulmod_42_ctx* ctx = (sp_1024_ecc_mulmod_42_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_ecc_mulmod_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + /* Implementation is constant time. */ + (void)ct; + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_1024) * 3); + ctx->i = 40; + ctx->c = 24; + ctx->n = k[ctx->i--] << (25 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_42(ctx->t[1].x, g->x, p1024_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_1024_mod_mul_norm_42(ctx->t[1].y, g->y, p1024_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_1024_mod_mul_norm_42(ctx->t[1].z, g->z, p1024_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 25; + } + ctx->y = (ctx->n >> 24) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_1024_proj_point_add_42_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_1024)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_1024_proj_point_dbl_42_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_1024)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_1024_map_42(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_1024)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + +static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[3]; + sp_digit tmp[2 * 42 * 5]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_1024) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod); + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod); + + if (err == MP_OKAY) { + i = 40; + c = 24; + n = k[i--] << (25 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 25; + } + + y = (n >> 24) & 1; + n <<= 1; + + sp_1024_proj_point_add_42(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_1024)); + sp_1024_proj_point_dbl_42(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_1024)); + } + + if (map != 0) { + sp_1024_map_42(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 42 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[42]; + sp_digit y[42]; +} sp_table_entry_1024; + +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +static void sp_1024_cond_copy_42(sp_digit* r, const sp_digit* a, const sp_digit m) +{ + sp_digit t[42]; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 42; i++) { + t[i] = r[i] ^ a[i]; + } + for (i = 0; i < 42; i++) { + r[i] ^= t[i] & m; + } +#else + t[ 0] = r[ 0] ^ a[ 0]; + t[ 1] = r[ 1] ^ a[ 1]; + t[ 2] = r[ 2] ^ a[ 2]; + t[ 3] = r[ 3] ^ a[ 3]; + t[ 4] = r[ 4] ^ a[ 4]; + t[ 5] = r[ 5] ^ a[ 5]; + t[ 6] = r[ 6] ^ a[ 6]; + t[ 7] = r[ 7] ^ a[ 7]; + t[ 8] = r[ 8] ^ a[ 8]; + t[ 9] = r[ 9] ^ a[ 9]; + t[10] = r[10] ^ a[10]; + t[11] = r[11] ^ a[11]; + t[12] = r[12] ^ a[12]; + t[13] = r[13] ^ a[13]; + t[14] = r[14] ^ a[14]; + t[15] = r[15] ^ a[15]; + t[16] = r[16] ^ a[16]; + t[17] = r[17] ^ a[17]; + t[18] = r[18] ^ a[18]; + t[19] = r[19] ^ a[19]; + t[20] = r[20] ^ a[20]; + t[21] = r[21] ^ a[21]; + t[22] = r[22] ^ a[22]; + t[23] = r[23] ^ a[23]; + t[24] = r[24] ^ a[24]; + t[25] = r[25] ^ a[25]; + t[26] = r[26] ^ a[26]; + t[27] = r[27] ^ a[27]; + t[28] = r[28] ^ a[28]; + t[29] = r[29] ^ a[29]; + t[30] = r[30] ^ a[30]; + t[31] = r[31] ^ a[31]; + t[32] = r[32] ^ a[32]; + t[33] = r[33] ^ a[33]; + t[34] = r[34] ^ a[34]; + t[35] = r[35] ^ a[35]; + t[36] = r[36] ^ a[36]; + t[37] = r[37] ^ a[37]; + t[38] = r[38] ^ a[38]; + t[39] = r[39] ^ a[39]; + t[40] = r[40] ^ a[40]; + t[41] = r[41] ^ a[41]; + r[ 0] ^= t[ 0] & m; + r[ 1] ^= t[ 1] & m; + r[ 2] ^= t[ 2] & m; + r[ 3] ^= t[ 3] & m; + r[ 4] ^= t[ 4] & m; + r[ 5] ^= t[ 5] & m; + r[ 6] ^= t[ 6] & m; + r[ 7] ^= t[ 7] & m; + r[ 8] ^= t[ 8] & m; + r[ 9] ^= t[ 9] & m; + r[10] ^= t[10] & m; + r[11] ^= t[11] & m; + r[12] ^= t[12] & m; + r[13] ^= t[13] & m; + r[14] ^= t[14] & m; + r[15] ^= t[15] & m; + r[16] ^= t[16] & m; + r[17] ^= t[17] & m; + r[18] ^= t[18] & m; + r[19] ^= t[19] & m; + r[20] ^= t[20] & m; + r[21] ^= t[21] & m; + r[22] ^= t[22] & m; + r[23] ^= t[23] & m; + r[24] ^= t[24] & m; + r[25] ^= t[25] & m; + r[26] ^= t[26] & m; + r[27] ^= t[27] & m; + r[28] ^= t[28] & m; + r[29] ^= t[29] & m; + r[30] ^= t[30] & m; + r[31] ^= t[31] & m; + r[32] ^= t[32] & m; + r[33] ^= t[33] & m; + r[34] ^= t[34] & m; + r[35] ^= t[35] & m; + r[36] ^= t[36] & m; + r[37] ^= t[37] & m; + r[38] ^= t[38] & m; + r[39] ^= t[39] & m; + r[40] ^= t[40] & m; + r[41] ^= t[41] & m; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_42(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*42; + sp_digit* b = t + 4*42; + sp_digit* t1 = t + 6*42; + sp_digit* t2 = t + 8*42; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_42(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_42(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_42(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_42(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_42(t2, b, p1024_mod); + sp_1024_mont_sub_42(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_42(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_42(y, b, x, p1024_mod); + sp_1024_mont_mul_42(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_42(y, y, p1024_mod); + sp_1024_mont_sub_42(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_42(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_42(t2, b, p1024_mod); + sp_1024_mont_sub_42(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_42(y, b, x, p1024_mod); + sp_1024_mont_mul_42(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_42(y, y, p1024_mod); + sp_1024_mont_sub_42(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_42(y, y, p1024_mod); +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_store_42(sp_point_1024* r, + const sp_point_1024* p, int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*42; + sp_digit* b = t + 4*42; + sp_digit* t1 = t + 6*42; + sp_digit* t2 = t + 8*42; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<42; i++) { + y[i] = p->y[i]; + } + for (i=0; i<42; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_1024_mont_dbl_42(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_42(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_42(w, w, p1024_mod, p1024_mp_mod); + j = m; + for (i=1; i<=n; i++) { + j *= 2; + + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_42(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_42(t2, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(b, t2, x, p1024_mod, p1024_mp_mod); + x = r[j].x; + /* X = A^2 - 2B */ + sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_42(t1, b, p1024_mod); + sp_1024_mont_sub_42(x, x, t1, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_42(r[j].z, z, y, p1024_mod, p1024_mp_mod); + z = r[j].z; + /* t2 = Y^4 */ + sp_1024_mont_sqr_42(t2, t2, p1024_mod, p1024_mp_mod); + if (i != n) { + /* W = W*Y^4 */ + sp_1024_mont_mul_42(w, w, t2, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_42(y, b, x, p1024_mod); + sp_1024_mont_mul_42(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_42(y, y, p1024_mod); + sp_1024_mont_sub_42(y, y, t2, p1024_mod); + + /* Y = Y/2 */ + sp_1024_div2_42(r[j].y, y, p1024_mod); + r[j].infinity = 0; + } +} + +/* Add two Montgomery form projective points. + * + * ra Result of addition. + * rs Result of subtraction. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_sub_42(sp_point_1024* ra, + sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*42; + sp_digit* t3 = t + 4*42; + sp_digit* t4 = t + 6*42; + sp_digit* t5 = t + 8*42; + sp_digit* t6 = t + 10*42; + sp_digit* x = ra->x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_42(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_42(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_42(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_42(t2, t2, t1, p1024_mod); + /* RS = S2 + S1 */ + sp_1024_mont_add_42(t6, t4, t3, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_42(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_1024_mont_mul_42(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(z, z, t2, p1024_mod, p1024_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_42(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_42(xs, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(x, x, t5, p1024_mod); + sp_1024_mont_sub_42(xs, xs, t5, p1024_mod); + sp_1024_mont_dbl_42(t1, y, p1024_mod); + sp_1024_mont_sub_42(x, x, t1, p1024_mod); + sp_1024_mont_sub_42(xs, xs, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_1024_mont_sub_42(ys, y, xs, p1024_mod); + sp_1024_mont_sub_42(y, y, x, p1024_mod); + sp_1024_mont_mul_42(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(t6, p1024_mod, t6, p1024_mod); + sp_1024_mont_mul_42(ys, ys, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(y, y, t5, p1024_mod); + sp_1024_mont_sub_42(ys, ys, t5, p1024_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_1024 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_1024; + +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_42_7[130] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static const uint8_t recode_neg_42_7[130] = { + 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, 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, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to perform. + */ +static void sp_1024_ecc_recode_7_42(const sp_digit* k, ecc_recode_1024* v) +{ + int i; + int j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<147; i++) { + y = (int8_t)n; + if (o + 7 < 25) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 25) { + n >>= 7; + if (++j < 42) + n = k[j]; + o = 0; + } + else if (++j < 42) { + n = k[j]; + y |= (uint8_t)((n << (25 - o)) & 0x7f); + o -= 18; + n >>= o; + } + + y += (uint8_t)carry; + v[i].i = recode_index_42_7[y]; + v[i].neg = recode_neg_42_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Window technique of 7 bits. (Add-Sub variation.) + * Calculate 0..64 times the point. Use function that adds and + * subtracts the same two points. + * Recode to add or subtract one of the computed points. + * Double to push up. + * NOT a sliding window. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_win_add_sub_42(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[65+2]; + sp_digit tmp[2 * 42 * 6]; +#endif + sp_point_1024* rt = NULL; + sp_point_1024* p = NULL; + sp_digit* negy; + int i; + ecc_recode_1024 v[147]; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * + (65+2), heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 65; + p = t + 65+1; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[64] */ + sp_1024_proj_point_dbl_n_store_42(t, &t[ 1], 6, 1, tmp); + sp_1024_proj_point_add_42(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[ 6], &t[ 3], tmp); + sp_1024_proj_point_add_sub_42(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[10], &t[ 5], tmp); + sp_1024_proj_point_add_sub_42(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[12], &t[ 6], tmp); + sp_1024_proj_point_dbl_42(&t[14], &t[ 7], tmp); + sp_1024_proj_point_add_sub_42(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[18], &t[ 9], tmp); + sp_1024_proj_point_add_sub_42(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[20], &t[10], tmp); + sp_1024_proj_point_dbl_42(&t[22], &t[11], tmp); + sp_1024_proj_point_add_sub_42(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[24], &t[12], tmp); + sp_1024_proj_point_dbl_42(&t[26], &t[13], tmp); + sp_1024_proj_point_add_sub_42(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[28], &t[14], tmp); + sp_1024_proj_point_dbl_42(&t[30], &t[15], tmp); + sp_1024_proj_point_add_sub_42(&t[31], &t[29], &t[30], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[34], &t[17], tmp); + sp_1024_proj_point_add_sub_42(&t[35], &t[33], &t[34], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[36], &t[18], tmp); + sp_1024_proj_point_dbl_42(&t[38], &t[19], tmp); + sp_1024_proj_point_add_sub_42(&t[39], &t[37], &t[38], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[40], &t[20], tmp); + sp_1024_proj_point_dbl_42(&t[42], &t[21], tmp); + sp_1024_proj_point_add_sub_42(&t[43], &t[41], &t[42], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[44], &t[22], tmp); + sp_1024_proj_point_dbl_42(&t[46], &t[23], tmp); + sp_1024_proj_point_add_sub_42(&t[47], &t[45], &t[46], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[48], &t[24], tmp); + sp_1024_proj_point_dbl_42(&t[50], &t[25], tmp); + sp_1024_proj_point_add_sub_42(&t[51], &t[49], &t[50], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[52], &t[26], tmp); + sp_1024_proj_point_dbl_42(&t[54], &t[27], tmp); + sp_1024_proj_point_add_sub_42(&t[55], &t[53], &t[54], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[56], &t[28], tmp); + sp_1024_proj_point_dbl_42(&t[58], &t[29], tmp); + sp_1024_proj_point_add_sub_42(&t[59], &t[57], &t[58], &t[ 1], tmp); + sp_1024_proj_point_dbl_42(&t[60], &t[30], tmp); + sp_1024_proj_point_dbl_42(&t[62], &t[31], tmp); + sp_1024_proj_point_add_sub_42(&t[63], &t[61], &t[62], &t[ 1], tmp); + + negy = t[0].y; + + sp_1024_ecc_recode_7_42(k, v); + + i = 146; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024)); + for (--i; i>=0; i--) { + sp_1024_proj_point_dbl_n_42(rt, 7, tmp); + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024)); + sp_1024_mont_sub_42(negy, p1024_mod, p->y, p1024_mod); + sp_1024_norm_42(negy); + sp_1024_cond_copy_42(p->y, negy, (sp_digit)0 - v[i].neg); + sp_1024_proj_point_add_42(rt, rt, p, tmp); + } + + if (map != 0) { + sp_1024_map_42(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_42(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*42; + sp_digit* t3 = t + 4*42; + sp_digit* t4 = t + 6*42; + sp_digit* t5 = t + 8*42; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_42(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_42(t1); + if ((sp_1024_cmp_equal_42(p->x, q->x) & sp_1024_cmp_equal_42(p->z, q->z) & + (sp_1024_cmp_equal_42(p->y, q->y) | sp_1024_cmp_equal_42(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_42(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<42; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<42; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<42; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_42(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_42(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_42(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_42(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_42(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_42(t1, t3, p1024_mod); + sp_1024_mont_sub_42(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_42(t3, t3, x, p1024_mod); + sp_1024_mont_mul_42(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_42(y, t3, t5, p1024_mod); + } +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_42(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + sp_digit* tmp = t + 4 * 42; + + sp_1024_mont_inv_42(t1, a->z, tmp); + + sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_42(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_42(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_42(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_42(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_42(t, 128, tmp); + sp_1024_proj_to_affine_42(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_42(t, s1, s2, tmp); + sp_1024_proj_to_affine_42(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC | !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_42(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 42 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_42(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_42(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_42(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[42]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[42]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_42(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_win_add_sub_42(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 42 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_42(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_win_add_sub_42(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_42(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[42]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 42, km); + sp_1024_point_from_ecc_point_42(point, gm); + + err = sp_1024_ecc_mulmod_42(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_42(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_1024_ecc_mulmod_42(r, &p1024_base, k, map, ct, heap); +} + +#else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x0162bc2,0x03f6370,0x0a26fe7,0x0621512,0x1decc6e,0x04cec0e, + 0x077c279,0x030bab3,0x06d3582,0x14b7514,0x17e36e6,0x0fa6e18, + 0x0601aec,0x067ae83,0x0b92656,0x1aff1ce,0x17d3e91,0x1617394, + 0x0a7cbd6,0x03b725b,0x19ed862,0x13ad2b3,0x12c9b21,0x0ad5582, + 0x185df2c,0x1cc9199,0x131a84f,0x111ce9a,0x08ec11b,0x18b9ffd, + 0x1bc4852,0x03e7f3f,0x0386a27,0x1da2750,0x0d3b039,0x0d7b363, + 0x0ecd349,0x12946e7,0x1e02ebf,0x0d43893,0x08dfff9 }, + { 0x03c0c83,0x03a9d60,0x15d6d29,0x11579b9,0x08e69d1,0x1adb24b, + 0x06e23dd,0x0a5c707,0x0bf58f3,0x01fca4d,0x0f05720,0x0cf37a1, + 0x025f702,0x07f94c6,0x0fd745a,0x12edd0b,0x198c6c7,0x01fb75e, + 0x178f86d,0x0315e88,0x0093206,0x072a732,0x19f5566,0x09fdb3c, + 0x1283b50,0x08bd823,0x15c361d,0x0a1957f,0x1addbe4,0x145f9fa, + 0x1291f58,0x0f19699,0x037ef30,0x0248400,0x14f1ac7,0x0e9c291, + 0x0fcfd83,0x0b6994a,0x007cf89,0x0f7bc78,0x02aa120 } }, + /* 2 */ + { { 0x1900955,0x1b6d700,0x15b6a56,0x039d68c,0x05dc9cc,0x17f4add, + 0x0241f9c,0x068a18f,0x1a040c3,0x0d72a23,0x0ba9ba8,0x06e0f2a, + 0x0591191,0x1684b98,0x1fdcd0d,0x1a21ea9,0x074bda4,0x0526d80, + 0x059101c,0x060de32,0x122cfd5,0x19c5922,0x052e7f9,0x093eec4, + 0x0dad678,0x1720a34,0x02c3734,0x0f65343,0x1ad4928,0x18d0af0, + 0x06ab75f,0x1b77454,0x0c63a81,0x119bccd,0x116e048,0x10026f3, + 0x10e53bc,0x0159785,0x0ed87d0,0x0fe17e2,0x08c3eb2 }, + { 0x113696f,0x169f0f2,0x1fea692,0x1831903,0x0350ba5,0x019e898, + 0x104d8f0,0x1783c5f,0x117a531,0x1ed3738,0x1584354,0x092035d, + 0x0742ec6,0x14cffab,0x0fa37df,0x1a255a6,0x13e3dee,0x1f2556b, + 0x003d37a,0x0768ca3,0x10b4d98,0x14a8179,0x064d949,0x1231aff, + 0x199aba8,0x1cd3f13,0x19c03f1,0x1ffd096,0x1fd8c20,0x006b205, + 0x0f5ed10,0x0ba4c83,0x1a21d21,0x110e5e1,0x110b0c9,0x06f3072, + 0x11401e8,0x132805d,0x10c42b3,0x07c4a38,0x07bf416 } }, + /* 3 */ + { { 0x1fd589e,0x1a7c471,0x080c705,0x01bf2e9,0x1b50179,0x182a4fe, + 0x08f8cf9,0x069a12c,0x115924f,0x0848f7f,0x196b163,0x195bf36, + 0x0feef79,0x1fb4e16,0x1310988,0x10579a5,0x03252cd,0x0c0bec8, + 0x17c7777,0x09e9b34,0x16bdacf,0x1aa808d,0x1418498,0x1a28193, + 0x0490d2e,0x1694fba,0x1136da1,0x08125d1,0x0b0fcc6,0x178b3bb, + 0x0d8897b,0x1be2d5d,0x08c01e9,0x1ec1507,0x1d0612e,0x0ec506c, + 0x0956e33,0x1aba714,0x1fc1dd5,0x18ce0b4,0x09871ed }, + { 0x16535f7,0x1bb6abb,0x0ee2f42,0x044c6b6,0x1214d60,0x10b7b22, + 0x16b6674,0x0eb8184,0x15515bf,0x0a6f9d3,0x1c59d7f,0x0b78bd3, + 0x0724a62,0x003439f,0x0d7bedd,0x0b89478,0x033bb2e,0x177ae4d, + 0x01ac662,0x0366bd0,0x10eda97,0x12d1e34,0x07d7032,0x03c4683, + 0x1dd898e,0x0f2546a,0x1a556b6,0x19d9799,0x0d34164,0x0203924, + 0x1b8bb3d,0x08b815e,0x0bb3811,0x007ff8d,0x1a0871e,0x0e7e97d, + 0x0272ed5,0x06fbb46,0x0deb745,0x0146e2c,0x0397ed1 } }, + /* 4 */ + { { 0x15c2a27,0x105d93a,0x11133cf,0x12b2b0b,0x138e42f,0x142f306, + 0x0f83c64,0x01e8d62,0x076273d,0x1f66860,0x115a6b0,0x010a327, + 0x0a7800f,0x01a8c0c,0x139d2ad,0x06c77e0,0x0388496,0x1492c55, + 0x032253f,0x0cc2f97,0x09a0845,0x15157cb,0x02f18aa,0x08cd1b3, + 0x0280b5a,0x07d3361,0x1aa64bd,0x193beb1,0x001e99b,0x1bec9fa, + 0x03976c2,0x1898718,0x0614fe1,0x0fb59f0,0x1470b33,0x11aa622, + 0x0143b61,0x1abaf67,0x0629071,0x10bbf27,0x0402479 }, + { 0x1055746,0x128bc47,0x1b83ee8,0x001563c,0x05ba004,0x14934be, + 0x053eeb0,0x081c363,0x15b4f47,0x18a908c,0x1ee951d,0x03a1376, + 0x0425009,0x1cd09cd,0x19d2186,0x154fcf4,0x1b3f353,0x15d4209, + 0x110f3bb,0x0ee3244,0x1bd0afe,0x1b1c23d,0x0511a34,0x149285a, + 0x19ff63d,0x02b30fb,0x075096d,0x0ac7438,0x1f46301,0x07e6baf, + 0x124f09c,0x1d65005,0x0072090,0x0380221,0x172f217,0x08d1e19, + 0x1a032e7,0x01b97df,0x0760329,0x1cd916f,0x01a6fd1 } }, + /* 5 */ + { { 0x15116a3,0x1480d46,0x11fe59e,0x0965ebe,0x0b84439,0x15d79d8, + 0x1514983,0x019c735,0x160ccfc,0x10df30b,0x1d4fc87,0x07a5987, + 0x16ac07e,0x0f688dd,0x00e3838,0x16185bb,0x1071c15,0x022a3a9, + 0x083f96e,0x1a8e912,0x096d70d,0x16f238c,0x06882f8,0x04ed8f8, + 0x1ad8a59,0x1039e1f,0x0f221bb,0x04d4398,0x031ac40,0x179bb74, + 0x1967f6d,0x158a03a,0x0a35d1a,0x142ba13,0x0415036,0x0a15d31, + 0x0bd734e,0x0ef0525,0x11d4197,0x1b82ac2,0x029b7d4 }, + { 0x1f4e20b,0x1e165e5,0x131512c,0x1eb1988,0x1c3f548,0x06560f8, + 0x06d516c,0x0427301,0x100f806,0x007815a,0x0417803,0x11200cd, + 0x0ce612b,0x01a80c4,0x0563b5e,0x0ed651e,0x0583f55,0x0600ee2, + 0x11524b8,0x0064e54,0x0443298,0x1d07fc9,0x1de9588,0x1a1b882, + 0x02b0029,0x03d6895,0x049e03a,0x0824a8b,0x13f272b,0x1c8186a, + 0x0347af3,0x048603d,0x0e6ea40,0x083cc5d,0x1cbe8df,0x183cbe7, + 0x02b4126,0x0161881,0x125fa4d,0x004a704,0x05d0928 } }, + /* 6 */ + { { 0x12f780d,0x115bf7f,0x0c7560e,0x01afaed,0x14d2682,0x1ba5761, + 0x0a11e1b,0x1d7c786,0x010823f,0x1ea1109,0x19efd03,0x02fdf6b, + 0x0d227e4,0x12b47c6,0x03526da,0x177d8a2,0x1d61781,0x1a9de73, + 0x1cdc62d,0x1c7e445,0x0c1f9cf,0x0fecef3,0x1fd13a2,0x15936aa, + 0x0553f3f,0x05e78e6,0x1b9bcc0,0x1a5a108,0x0ae6b19,0x01514f8, + 0x1825db2,0x0497177,0x03dbf5e,0x12d53f3,0x1d165ce,0x0e9958f, + 0x04dd33c,0x15b11bc,0x1b9771b,0x068285f,0x00a26e4 }, + { 0x0aa9a08,0x099cfd6,0x1386020,0x0aa48dd,0x00f3110,0x1c9ba3a, + 0x005c184,0x1c31259,0x1242f02,0x0c6a081,0x17a62a3,0x1a4076b, + 0x12482bf,0x0d5df4a,0x1be51ad,0x1049313,0x0b93769,0x15c690c, + 0x1985f1e,0x0d1d12c,0x0b91d52,0x08c5be9,0x058b9d5,0x11acf87, + 0x07973fe,0x028962e,0x08ac05f,0x05c62a1,0x0294694,0x0f5e60d, + 0x00dbd39,0x0a638e1,0x19910ce,0x1cf2851,0x1ad2dde,0x015e9ed, + 0x1a120ad,0x05d8bae,0x0dbb1a3,0x0c3724c,0x019497c } }, + /* 7 */ + { { 0x17659a8,0x0586320,0x03fda48,0x0f25965,0x077ab9c,0x03bcbfe, + 0x1c602da,0x0c6ab6c,0x1e77593,0x057ac60,0x06c6193,0x1b6caac, + 0x065155b,0x1c07a4a,0x1938d55,0x116405c,0x1b7229a,0x0758564, + 0x15c6f58,0x129af04,0x18f9885,0x1cf1fd3,0x1773024,0x185a6f2, + 0x148302a,0x0223dc5,0x02e43c5,0x00bf7ec,0x04b3c15,0x07409e7, + 0x062b184,0x1ab36b8,0x1a4f27a,0x101111c,0x05cdf3a,0x16bf467, + 0x0dff1c7,0x1c3985c,0x1de9b95,0x116a2f7,0x096b91b }, + { 0x0ac087c,0x0c8fa4d,0x0a3706a,0x1cd9fb6,0x0e62f74,0x1b006b6, + 0x1fe697d,0x19211ad,0x0f917f9,0x1c0e682,0x14b6ff5,0x0bec7bc, + 0x007796f,0x176b90c,0x16d9380,0x026fbcf,0x0f66fa4,0x107843b, + 0x1287dc5,0x03dcc87,0x18a3327,0x0c3e255,0x12e6c81,0x090208f, + 0x1710739,0x01be5d0,0x1566317,0x1f34321,0x00e125d,0x1395379, + 0x0b432db,0x1e9e520,0x1142204,0x16e7dd1,0x12e5f38,0x0285a51, + 0x03d3c35,0x130dc55,0x092777c,0x02b9ff8,0x073f3d3 } }, + /* 8 */ + { { 0x0fd3673,0x142adf3,0x0ded761,0x1f3a429,0x109b70a,0x0236699, + 0x0be4373,0x1bd1a66,0x1595510,0x0a9e00a,0x0494739,0x012c718, + 0x095746a,0x02e60de,0x1f3a96e,0x1751f9a,0x068002e,0x027fd0a, + 0x0bf35df,0x0796e04,0x05e310a,0x1de2750,0x0da6677,0x1f4eadd, + 0x1a0d04e,0x1ec19ba,0x1b73b57,0x1b204f3,0x1fd56e4,0x1201928, + 0x1c52064,0x105498b,0x07633a4,0x0082df4,0x04c06cd,0x1062e1a, + 0x1247e57,0x0cc587b,0x087ea4e,0x0c886d7,0x088934f }, + { 0x113eabc,0x1a1d823,0x145fc27,0x03599b8,0x0ca7dd9,0x09e53e2, + 0x098efbc,0x0964fb5,0x0258818,0x1972d3d,0x1709a62,0x0c25b2b, + 0x0c0a8cb,0x10f978a,0x1a5d68b,0x126b868,0x0ede172,0x18f94dc, + 0x102f078,0x17fadda,0x03dac3c,0x1f89931,0x14fd1ac,0x016ed03, + 0x1be6dfb,0x1a2608a,0x155b690,0x1c63868,0x043d985,0x1f8c547, + 0x1aa9f18,0x097bb69,0x1cb2083,0x07ac62a,0x10e1295,0x1362d41, + 0x06fd69d,0x1566512,0x12385d3,0x1762a6a,0x00d1898 } }, + /* 9 */ + { { 0x15ef043,0x19a30f1,0x15913a9,0x12692d6,0x107b67d,0x1c1d1e0, + 0x05cef43,0x06bac58,0x051d29c,0x16a581c,0x070693e,0x1054e36, + 0x1e3f428,0x0a5a1dc,0x0af3d99,0x1ea86ba,0x1aa2abd,0x0e3bd8a, + 0x0af8f70,0x071501b,0x073b5cb,0x175240b,0x057f682,0x1721d7c, + 0x16b4de7,0x1ec434c,0x14af23c,0x09f0fc4,0x04e4248,0x01eb1be, + 0x162b7b4,0x1af4f5f,0x1ede666,0x05c9d72,0x168a873,0x0301bb2, + 0x06fba39,0x0e7e92a,0x0b98295,0x1b88df0,0x02bdab1 }, + { 0x06fed61,0x0f115fd,0x0539e93,0x0b991bb,0x0a458aa,0x09117ae, + 0x0b7c41c,0x0ee7c6e,0x1e5aff3,0x1525a27,0x0e39b41,0x174e94e, + 0x16bc2d0,0x0f98f89,0x11c3875,0x1522234,0x13ae102,0x0bbffc9, + 0x0431e21,0x1014a06,0x05ac8b3,0x143c1fe,0x07cf008,0x0e4ba0d, + 0x0892544,0x110f633,0x196b210,0x0f1e1c2,0x1a6e8a8,0x18d7e7e, + 0x0ea68eb,0x0f19a55,0x183ed37,0x0875700,0x158209b,0x0a659b7, + 0x0bee641,0x11a330e,0x00482cc,0x1257382,0x0353eb8 } }, + /* 10 */ + { { 0x0b5521e,0x0e56b08,0x0bc323f,0x00a5ce0,0x1a11b44,0x1ed24e0, + 0x1a0363f,0x15ac604,0x0cbf36b,0x0dcb2a5,0x028b5f3,0x1c22982, + 0x007b58c,0x131873f,0x1747df7,0x150263c,0x17d6760,0x1c65f1e, + 0x12035df,0x0b0cd6c,0x0219eb3,0x19bf81b,0x161ca33,0x1514eae, + 0x065ed42,0x0386eac,0x1641a8a,0x107e3e3,0x1f906b2,0x1fd2528, + 0x0a1e788,0x0a87641,0x0ac6e83,0x13baa79,0x0de6e07,0x1c9e16c, + 0x040016e,0x1de06a4,0x0d9f55f,0x0e3cc43,0x08da207 }, + { 0x0ce65ec,0x0a80276,0x0178f21,0x1f6e903,0x16d10d1,0x1cbd693, + 0x1ef29e1,0x15ac97c,0x077e54a,0x1a226d8,0x17c3fd0,0x01937c1, + 0x0417b6b,0x02a8435,0x11095b0,0x1ab471f,0x03bfd74,0x07ca962, + 0x0713b6e,0x1c00b40,0x0328501,0x1e252bf,0x1545cb7,0x0baddc7, + 0x0ce4e53,0x08c6da0,0x1031942,0x15de3cb,0x1561fcb,0x02f3c2b, + 0x11ba145,0x0694449,0x068536a,0x0705172,0x089c3b0,0x18d351c, + 0x042b03f,0x1a91239,0x0f57ecf,0x1c5877d,0x0862f55 } }, + /* 11 */ + { { 0x06049fe,0x11c8791,0x07ecb5a,0x11b9779,0x0c92a57,0x11a7dbe, + 0x1b2925d,0x1274a5f,0x03dea58,0x19a065b,0x07a458a,0x0714549, + 0x13a39f3,0x0a4f20f,0x0cb7cf6,0x0fc804d,0x0db065a,0x1638e3e, + 0x1a0a068,0x1709408,0x0eca4a9,0x01b98f7,0x18fbad4,0x1976e4a, + 0x0913476,0x1c67368,0x06e5299,0x19f2f35,0x0fd9f10,0x061dc04, + 0x0e6d136,0x1c15f8b,0x00da613,0x0df34f3,0x1f78fa9,0x1ea5b9c, + 0x1c1ee74,0x0eb4326,0x01e40e9,0x1227790,0x071ab28 }, + { 0x15b60ad,0x0c7e21d,0x06133d8,0x0094186,0x0afb5e3,0x0019810, + 0x00732f1,0x0cda447,0x1db1c0c,0x1e7c4a9,0x04aa34c,0x1c9b4c2, + 0x069c994,0x08cb3d4,0x0ab8b0f,0x19a53af,0x0935b7a,0x1e146aa, + 0x12695fe,0x0b7a26d,0x07f9807,0x1f4e421,0x12700dc,0x0644beb, + 0x0a18d19,0x0c6165e,0x0d10b00,0x06eefa2,0x13a7277,0x16a3fdd, + 0x063af97,0x032c5b8,0x0437d49,0x0440338,0x1824b70,0x19e7383, + 0x15fff35,0x14e37b8,0x029940f,0x16cbc6c,0x08d087b } }, + /* 12 */ + { { 0x1dc1844,0x091811f,0x115af88,0x1e20bd5,0x0eca27e,0x1451a43, + 0x0981bc5,0x1964307,0x1e1d7a4,0x0afc03e,0x1750f8a,0x0c64fde, + 0x077246a,0x03b812e,0x050c817,0x09c7d5c,0x1caf348,0x0a5efe3, + 0x1d4b01d,0x07312bb,0x0ac0ec9,0x1b6bd4e,0x00b9957,0x15dbb61, + 0x1fe208b,0x198cc2e,0x1149f79,0x13902fc,0x1de1ea7,0x07de189, + 0x0ecc338,0x1989ed9,0x1f95b89,0x19066ce,0x1c7bd6e,0x03e55db, + 0x1a8cfb0,0x0f05448,0x0dfb3f0,0x094c7db,0x0225ed3 }, + { 0x0bb1a85,0x18aa6dd,0x1968f84,0x0e3cd4a,0x13d8dae,0x058807e, + 0x1f55aad,0x035a642,0x0ebc78e,0x026c9a7,0x1cf4df5,0x043691c, + 0x0b02153,0x100f21e,0x1242fe8,0x0120b77,0x1d02750,0x09e11f8, + 0x019a468,0x1ca0019,0x041c2a2,0x093032c,0x022caeb,0x004d6c0, + 0x01caf30,0x1308aea,0x1149db3,0x0e2585e,0x132ffb1,0x01f38ac, + 0x1c80713,0x0d4e995,0x094e13d,0x09bd23c,0x177c301,0x1c05ade, + 0x02b1c97,0x1dbb016,0x1f1eea3,0x1cba110,0x0612b60 } }, + /* 13 */ + { { 0x0245d6b,0x04ae7dd,0x1fdbbf5,0x0f459c7,0x1cf0cbb,0x1aff772, + 0x0ab037f,0x14649b4,0x0cf28c6,0x0648a7c,0x0295ae4,0x0a1a861, + 0x1472fdb,0x09eb901,0x16fdde4,0x193d207,0x091822a,0x0e7d2f6, + 0x0ba8fa0,0x1ce7907,0x11390dd,0x1133144,0x1516ea5,0x0d597a6, + 0x1648bca,0x01d5297,0x1a6281a,0x1ede4ed,0x18ed52f,0x09d651b, + 0x16494db,0x110b583,0x13c2c54,0x042539a,0x0b6802f,0x0f95fea, + 0x1768416,0x18fc0e1,0x061b8e5,0x1c3a5af,0x00f7334 }, + { 0x196067e,0x1ae41b2,0x001abee,0x1271833,0x13e54e1,0x0586e61, + 0x1659ce7,0x1f3050b,0x1424035,0x1a9fa1e,0x1e4254a,0x03f1bfd, + 0x1a38c53,0x0d87ab8,0x1efa393,0x14f0f21,0x0d2a39c,0x04d060f, + 0x01bc988,0x1983acc,0x0b4a2fe,0x18b95be,0x0772242,0x176f0d1, + 0x0a6fbcc,0x124e19e,0x0bf9cfb,0x0362210,0x166c48d,0x1e8bfe5, + 0x1cd642d,0x10dc28a,0x156b0a6,0x156c2c9,0x0b1014f,0x16ebad0, + 0x054d30f,0x172afd6,0x1a526ca,0x0e5f15d,0x067636a } }, + /* 14 */ + { { 0x11d6bea,0x031de5c,0x0e598e0,0x1d247d9,0x0e263a2,0x13d6535, + 0x0264b18,0x0fd3af6,0x077af9e,0x176800d,0x0bfaef1,0x199e495, + 0x109214a,0x1c02ad4,0x1592e59,0x0933b46,0x11ce027,0x0804ccd, + 0x11a81a9,0x0749c3c,0x0fe7e41,0x1b1728f,0x081744f,0x150877d, + 0x07d349b,0x0cf1af4,0x14c60c5,0x14c6704,0x0019230,0x145d2a3, + 0x1c9808f,0x16ffa39,0x1107721,0x17ea9cd,0x10aff7c,0x108d6aa, + 0x1c18af3,0x0a7a7c0,0x02596cc,0x0ecc159,0x0086f98 }, + { 0x0bb9850,0x00caa46,0x1231d9c,0x01441a5,0x0210b73,0x1ab3863, + 0x1415d4c,0x1d48109,0x10324ba,0x166e2ca,0x1ba6d0f,0x0be58ed, + 0x04607fc,0x0207fd3,0x04f403d,0x08c79e7,0x1962dc1,0x1f0088b, + 0x11dc979,0x1704a33,0x1186f00,0x1b2de8e,0x0d7981c,0x1ee5558, + 0x0554c2c,0x0bef9ec,0x1bbe8d2,0x09ba1fb,0x06ad11b,0x13467b2, + 0x0b75c48,0x13ef71d,0x1c20afb,0x16ff283,0x0753f01,0x14c612d, + 0x1245549,0x1bef8e3,0x1a041da,0x007cc35,0x0681f94 } }, + /* 15 */ + { { 0x1a0623b,0x0a8b1e4,0x0351f2b,0x0ecff57,0x1bf8295,0x17be3e6, + 0x0c3b206,0x1845995,0x0e966d5,0x14f1c64,0x1390711,0x1aa5e1a, + 0x1c34430,0x12959ac,0x181d68a,0x0024e84,0x1e333bd,0x09216e9, + 0x1fb48d0,0x07ec6b3,0x0ffacda,0x186bea9,0x137ccdc,0x08187de, + 0x156f076,0x0be2fff,0x106ef79,0x0f07843,0x0bb3364,0x051575c, + 0x01761e1,0x1d5a108,0x0c7c533,0x115ea0f,0x108fe6d,0x1e96fe2, + 0x1075d4a,0x018a2e3,0x1642955,0x09574c0,0x00c9de9 }, + { 0x1d5682b,0x1939aca,0x1bb63b5,0x065d84e,0x111c428,0x1b50693, + 0x0bb562c,0x11fa3e9,0x08498a8,0x155a062,0x03d1458,0x18c4890, + 0x0258c8f,0x1bce7ff,0x123292e,0x06b3b17,0x03c701a,0x0c855ac, + 0x1f57457,0x0634e67,0x133caee,0x1de4891,0x00a9565,0x187c784, + 0x1cae4b6,0x044080c,0x10a64e0,0x0a26085,0x1c8199e,0x141efa3, + 0x0483800,0x1e5401d,0x0d68e58,0x0d71dc8,0x1d069dd,0x04d3c5b, + 0x071c30b,0x097652c,0x18e5ae3,0x01d763b,0x0733dca } }, + /* 16 */ + { { 0x159213a,0x04ae825,0x003bd6d,0x131ae04,0x0a67203,0x13b8e0e, + 0x02698ad,0x1969796,0x02b9eb0,0x156f76a,0x0e88489,0x0ea919b, + 0x11eb544,0x1844486,0x06aff37,0x08d681c,0x163698e,0x029284c, + 0x0ba704e,0x1fe1610,0x1a71e1b,0x06a884c,0x0862793,0x172398f, + 0x0c9bcc9,0x05f11b0,0x104dfb1,0x17a9afb,0x119f6e9,0x1290e8a, + 0x00f40d5,0x19f064a,0x15f6d78,0x1515a5f,0x00c637b,0x19c8602, + 0x0f4c319,0x09924a7,0x09f5f0c,0x08e1e3f,0x02ab3bd }, + { 0x02c9fbb,0x1db4049,0x1b455d4,0x101e2d8,0x069e7dc,0x00b77e4, + 0x144d6eb,0x1370688,0x0846d1d,0x19351da,0x18b0850,0x1dc765a, + 0x15b517f,0x0594956,0x016be88,0x15826d2,0x11a2cad,0x0952b89, + 0x0f6f2a3,0x009b1fd,0x1fb2cd9,0x179f9b2,0x17fb6a1,0x0fd5439, + 0x1b208dc,0x1e0384b,0x129179d,0x1346b50,0x1d118e8,0x031667a, + 0x1a105e8,0x03edd33,0x00c04a8,0x1043e9e,0x12c2e9e,0x05888e0, + 0x1ea22ad,0x0513e89,0x148a5be,0x02c984f,0x093a4b4 } }, + /* 17 */ + { { 0x11efb7a,0x18de08f,0x1037509,0x0c67f99,0x0e4e68e,0x0fa8545, + 0x123c6c4,0x1133b37,0x1af0760,0x0181cc7,0x14380d5,0x05f6887, + 0x0145e24,0x1b71ea6,0x1b09467,0x15a12e7,0x190ba9b,0x1d5b87b, + 0x06b7443,0x0255abf,0x02b4de6,0x070a74a,0x0e0df95,0x1716d15, + 0x056d3dd,0x0040bad,0x106b0a9,0x10b6467,0x080f94e,0x1618786, + 0x1e7e3fd,0x1131b69,0x17f3fb7,0x1ee6ea5,0x113d169,0x0b458c0, + 0x1e3d389,0x15d97b7,0x1dd8fce,0x1ae65dc,0x0342ce0 }, + { 0x1491b1f,0x109ca67,0x0e57ac9,0x0e3213c,0x1caaeed,0x126df56, + 0x0156a7f,0x09bb988,0x1493d60,0x1d3308e,0x17afbc5,0x147439c, + 0x15ba445,0x11cc4e5,0x0b8a163,0x1080dd0,0x08283f5,0x0dcb7a1, + 0x055b3d5,0x0ef7334,0x0a0e998,0x13270b3,0x0be41a9,0x12eda27, + 0x1d353b2,0x100e750,0x1cdb186,0x1f82de4,0x155d86e,0x0219d87, + 0x0076c13,0x11d6698,0x0b4b269,0x101401e,0x1de0ab9,0x0a71a0f, + 0x03be3ec,0x161de5a,0x1f4810e,0x1e7c2ad,0x0455f4a } }, + /* 18 */ + { { 0x14ec21c,0x1f9313a,0x08e3015,0x13c7437,0x1eacd4c,0x160ff49, + 0x0434445,0x16c7404,0x0eacc8a,0x075274a,0x1ccb2b9,0x1935d4d, + 0x0e31c00,0x035cbae,0x0d88e76,0x143d2b9,0x18ca14e,0x1b2a6ae, + 0x019ff22,0x1a63e8a,0x1ecb230,0x05b1aaf,0x122ee43,0x02e5d1c, + 0x01ecedc,0x19bbc7c,0x032c019,0x1107015,0x02d0122,0x1700f0b, + 0x17066c0,0x18b5e28,0x0087a06,0x0e1aa07,0x02dedcb,0x0de09b9, + 0x0de3c06,0x07790a4,0x07edfdc,0x0862601,0x04f1482 }, + { 0x02055e2,0x027e737,0x019d780,0x150d864,0x09e247e,0x0ed5514, + 0x0f6557e,0x0769d79,0x1ceb7f6,0x0af9097,0x1e12834,0x183f0c6, + 0x115ecc5,0x1abb012,0x0ce002d,0x052a8a7,0x1c38a6a,0x0f5c980, + 0x04f3746,0x0d74314,0x0d240f1,0x08c43e1,0x00c4f49,0x12827ed, + 0x035859a,0x1e2fcc9,0x1bf8ff5,0x04680bc,0x00ee054,0x159a0b7, + 0x0c19e2b,0x07f5b55,0x13be7bb,0x022388f,0x08b20a2,0x0cf203f, + 0x0d662ff,0x086d982,0x05c2f25,0x1a87802,0x074d5d2 } }, + /* 19 */ + { { 0x15bfe11,0x016e015,0x079e8c0,0x1aa5a64,0x0733410,0x1cdd448, + 0x03d9659,0x0dc2b24,0x0685b23,0x112460a,0x1d81003,0x0b2868d, + 0x108cfab,0x00638bf,0x15ebedd,0x08aed3e,0x08c6604,0x186dd59, + 0x1370c91,0x0132d13,0x0d050fa,0x1161187,0x10780ab,0x0b7dee8, + 0x01554e4,0x1b786cb,0x0b3935e,0x0d11530,0x02d22e9,0x1d63af3, + 0x0a3eb7b,0x17a5974,0x11512a6,0x03a4fd7,0x198af9f,0x16f10d1, + 0x0e9f5a6,0x0246c0d,0x1e8a620,0x0858b0a,0x06b1a54 }, + { 0x1242066,0x15cd6a1,0x0aba7d6,0x0a59994,0x0afef1b,0x076e270, + 0x0fb1e62,0x1ab6368,0x10341b0,0x0860078,0x0aacdc3,0x11ef6a1, + 0x194d68b,0x19d3254,0x03939bf,0x0d09d35,0x0fb7f1a,0x00cc19c, + 0x14683d7,0x01ce906,0x05158bc,0x06ed622,0x0b2b3cb,0x13feed6, + 0x139995e,0x02ae0a6,0x1c58e4c,0x0940367,0x0d83765,0x1752c44, + 0x0c5ab0f,0x0e464ef,0x04d9a9a,0x0dddfdc,0x1a47847,0x1132264, + 0x0bb6717,0x1b8bd75,0x12b2165,0x04d1762,0x04c2135 } }, + /* 20 */ + { { 0x1532833,0x1f0534a,0x019cb9b,0x1dac4da,0x0bca228,0x0f39ded, + 0x1cf6592,0x018455d,0x0f03c4c,0x041d43d,0x1a6d148,0x0eba6a2, + 0x09e954e,0x1a28354,0x1d427b9,0x19f20ae,0x16e2aea,0x0a4e593, + 0x09027e4,0x0ebaeff,0x16b9082,0x1ef85de,0x187adbc,0x0264e08, + 0x002cbe4,0x058ca41,0x06c7126,0x0be7f84,0x1fee593,0x05d41b0, + 0x1cddb1a,0x0a1c0a3,0x18cbbd9,0x1382150,0x01e4c63,0x1647095, + 0x00dd1e8,0x155f56c,0x10cd0a4,0x052b86f,0x065713c }, + { 0x0b77b9a,0x05474e7,0x11a7733,0x0e476d2,0x0f97e72,0x0eb5941, + 0x0fb9a80,0x1fd8ed5,0x15abecd,0x092901e,0x0435c0e,0x0104525, + 0x1889448,0x1818a21,0x04c5092,0x08f87f3,0x1f17cd4,0x182104e, + 0x0157209,0x1e40b39,0x00697c6,0x112b607,0x165f5e1,0x05b2989, + 0x1b6fe41,0x0eead4e,0x0665310,0x134c8b2,0x1e21a31,0x0550e44, + 0x03848d2,0x18d407e,0x0904b50,0x17f566b,0x055a985,0x16ab82a, + 0x1cc7693,0x1b68dab,0x0f0e138,0x0d8775c,0x06b0e99 } }, + /* 21 */ + { { 0x0eced00,0x04fd5e6,0x0998c9e,0x15cb6f5,0x1237e71,0x0f5e6f9, + 0x189a4b7,0x11f0f65,0x0b61dad,0x1922890,0x1e00f2d,0x1c91a6b, + 0x0de11e5,0x0c72878,0x137d75e,0x15725f6,0x0b4bcd2,0x0b07734, + 0x138cd8f,0x165eb83,0x064798a,0x0d3e6a1,0x056e8e7,0x1e9f67e, + 0x172eb83,0x06d8d32,0x0395bc2,0x1eefbd1,0x0562c20,0x1b0f0b9, + 0x1d05d0d,0x114b1e1,0x0349ff8,0x0eb715f,0x1c6e134,0x09c09b4, + 0x1e9ff3b,0x0781a14,0x08fe0da,0x00acf04,0x04022a2 }, + { 0x1847375,0x1de82c1,0x0bc149e,0x047e8a3,0x1ae56b6,0x163f8c1, + 0x1c9352c,0x11ac331,0x14525b9,0x1191fad,0x0212d7b,0x07341c1, + 0x16a9d8d,0x1d8963b,0x0175fdb,0x182a9a0,0x03e708b,0x06b8e24, + 0x109506f,0x0dfa50e,0x1ddb8ca,0x06fc1cb,0x02bcf73,0x199e486, + 0x131253e,0x1c6dc06,0x0163606,0x0e87421,0x191f68c,0x1590b89, + 0x1fcfd23,0x06776ca,0x13aff88,0x03f18a4,0x15981f9,0x0c3a2bd, + 0x008279f,0x0acd88f,0x0a55840,0x196494d,0x0312179 } }, + /* 22 */ + { { 0x1615ac2,0x061e503,0x1606a53,0x082435a,0x05865e6,0x0c35bcc, + 0x185be9e,0x03b5c8e,0x19d5e0f,0x0ad2075,0x115fa8e,0x04c87b2, + 0x19a9143,0x1d1432e,0x19b5a8f,0x15d191b,0x1961014,0x183b8ed, + 0x1daa1f2,0x0f99cd2,0x0f6077a,0x108a1d0,0x09f790b,0x127b269, + 0x1cc09d9,0x01ef101,0x0e63b13,0x04030d2,0x05df4b9,0x036c1d1, + 0x1af5dd5,0x0c5605a,0x0d9eb47,0x138c485,0x0823416,0x17f555e, + 0x031221b,0x1c0c0fa,0x047a948,0x0f0e66a,0x0417d6c }, + { 0x091e9a8,0x0c0db87,0x1accf2f,0x1186e1a,0x1334041,0x1511b9b, + 0x0c42a3a,0x0ad04bb,0x06c7d67,0x19584f2,0x0cf7b63,0x1d37298, + 0x1be288e,0x0b4af1f,0x0109aec,0x1d1119b,0x086dce9,0x1530bb6, + 0x05978d8,0x191244c,0x1b093f4,0x0fb031f,0x1453904,0x1f3c098, + 0x1ac20c8,0x0b0b483,0x137f4ab,0x1dee8d3,0x12199ac,0x1d72422, + 0x18ae8c2,0x0255868,0x0681293,0x0a41698,0x01cf24b,0x0a0237d, + 0x0833099,0x065fc4f,0x0282bfd,0x0a5a28e,0x002189d } }, + /* 23 */ + { { 0x0599c69,0x00ceec9,0x0b29cf9,0x16ffd86,0x1b94221,0x1dfdfea, + 0x06f4826,0x0b7657f,0x063ed89,0x0f54bd2,0x01bde58,0x08d67e9, + 0x1966091,0x1e8a0d1,0x071e817,0x0826b7a,0x0cf83d6,0x1e3cf64, + 0x020d41e,0x1fa85f3,0x10277f8,0x1b8bd9e,0x0bf2d4e,0x194b443, + 0x18dcd67,0x1c34332,0x1334525,0x0d4d815,0x195067a,0x0b871a5, + 0x0305bcf,0x1be892b,0x11208e3,0x001091b,0x139bb0a,0x03a5bac, + 0x10782c7,0x1962559,0x1dbe8ce,0x17aa422,0x07bbf8a }, + { 0x18b981a,0x12557d3,0x00a2fa7,0x0c609d9,0x188b4e3,0x0cef51b, + 0x13ce4e5,0x18e188b,0x1240b39,0x054dee9,0x00edf5c,0x0fba507, + 0x06499cd,0x183d081,0x1a42cb8,0x1e36660,0x198ee92,0x011316a, + 0x11c9692,0x1aefbd6,0x0a0ec62,0x1e3de1d,0x085bc96,0x0bdeff5, + 0x18b65d1,0x147b16e,0x142e5b5,0x12f2443,0x0f1906d,0x02e1d00, + 0x102e4a2,0x1d6e98e,0x0476b9b,0x1b1117d,0x0ed71d5,0x1e42fbb, + 0x1788504,0x1c16182,0x1c5af09,0x0d9f024,0x0860d09 } }, + /* 24 */ + { { 0x179bbf9,0x019bea6,0x1e03faf,0x10d3ee9,0x1d53eab,0x0826a9a, + 0x08254cc,0x12ffe6d,0x0196f8b,0x15c106d,0x19a424a,0x1a3eeb9, + 0x14961d3,0x02341ba,0x05fb010,0x1973763,0x1bf93a6,0x1d34670, + 0x17c0868,0x08adff8,0x1fdb503,0x18c4a07,0x0d428b6,0x0008413, + 0x10f8fef,0x03abbe2,0x1c12596,0x0c6ba2e,0x18770ad,0x136cc5d, + 0x0f9c95d,0x140f1ca,0x019b028,0x041bc47,0x132be7f,0x006c9a9, + 0x10dd39a,0x1efa08f,0x1e48068,0x084075b,0x07e80e4 }, + { 0x19a1ddf,0x1c52ba9,0x15892d7,0x1ddc90c,0x1248e7a,0x1010f0e, + 0x1247605,0x18838f6,0x1fd36d2,0x13dc38d,0x100364b,0x0a0815d, + 0x13da38b,0x10c9f8d,0x009d849,0x0f1ade5,0x086fb1f,0x1b4e1ff, + 0x009eb0c,0x116f0dd,0x08f756c,0x039a43e,0x05a1fdb,0x1bdcb78, + 0x1221719,0x00c55c7,0x1ffce65,0x09d08e7,0x027c800,0x000a548, + 0x0a3ce13,0x1543a5c,0x167be9a,0x0f778cc,0x1b4f819,0x190d2d0, + 0x07bd837,0x1e35846,0x1618dcd,0x1a33d17,0x05dcab5 } }, + /* 25 */ + { { 0x07d772b,0x0141d4d,0x166c1e1,0x0bca812,0x0b49e52,0x00a55ab, + 0x0c02219,0x152a8d7,0x09d74b2,0x02240b1,0x0c2c6f5,0x015a407, + 0x0b26789,0x0469fc3,0x1ea0af3,0x1078e3c,0x1b5d85a,0x189a95f, + 0x0b41f33,0x1e2dc7f,0x043ff29,0x1c20f06,0x100a98e,0x06f3fdf, + 0x122c56b,0x1934827,0x0ec4913,0x13b14ca,0x08bdea1,0x1b6f9d1, + 0x13998d6,0x1eda8ab,0x0b68851,0x19b9a8c,0x006273f,0x16e9585, + 0x0b2cbda,0x007cefc,0x15262b5,0x13d5b93,0x008cc2d }, + { 0x170c84b,0x1343360,0x1210b9a,0x16b4934,0x1b989e8,0x0644c95, + 0x0038341,0x046f61c,0x061b3a4,0x0d69a3c,0x0062655,0x08a161a, + 0x133c952,0x1188065,0x0488557,0x0eda1c7,0x16ef032,0x18c932d, + 0x1b50ad4,0x10b2b4e,0x13b60fe,0x107e31a,0x02a5b7b,0x0df127c, + 0x00dc824,0x05d3b0f,0x1bc29d3,0x1d92057,0x1fad9b4,0x03421fe, + 0x1d58402,0x09fb6d2,0x16a60e4,0x1ac852e,0x0b21fbd,0x0e7ea75, + 0x12870a3,0x0f35f00,0x156c34a,0x182ab54,0x0991fad } }, + /* 26 */ + { { 0x0844ffe,0x02587da,0x01c60af,0x08c1f17,0x1392271,0x11f8f9b, + 0x0038933,0x1d91580,0x0163519,0x06aa45a,0x022d7fc,0x0857105, + 0x107aaf8,0x15ee4d3,0x02c3130,0x1facf3d,0x1524ba5,0x1d036a8, + 0x04f37b0,0x035f41f,0x18f0d0b,0x1d6fc4f,0x0a02556,0x1465924, + 0x1e92dee,0x1f24365,0x04ff816,0x195c7f3,0x0919aa0,0x184afd3, + 0x02fc981,0x0dc1e37,0x154741e,0x07cc407,0x1dd0c3b,0x0e55da3, + 0x134991d,0x0b7bb5b,0x03fa64a,0x0504b3e,0x066cf8d }, + { 0x06f5868,0x0c82d91,0x1a7a6c0,0x182d213,0x0102e88,0x1bf5aa6, + 0x0245928,0x04657a1,0x0c98163,0x19129f4,0x0b14f3d,0x1d3b0d7, + 0x1737f84,0x17f5557,0x0d49152,0x008dc5c,0x1772ca0,0x133e437, + 0x198cdcb,0x19ca1cc,0x0a0486b,0x105b4a8,0x1da8ea5,0x0357527, + 0x194d7fc,0x13730fc,0x0f04c9b,0x12af825,0x16b0051,0x07f2172, + 0x0326d96,0x10b24e8,0x0d297fc,0x19352ce,0x1a6c5df,0x16eca99, + 0x079d2eb,0x134cedd,0x19122aa,0x0b41d96,0x05fca0c } }, + /* 27 */ + { { 0x09a6663,0x112f9ab,0x129f89b,0x0fcd549,0x09597ee,0x0c5c060, + 0x1369a34,0x0604b49,0x1229267,0x083015a,0x01c8251,0x0ca00e7, + 0x139af5f,0x13399d2,0x1bb6cd0,0x052a3fd,0x1688657,0x107ae73, + 0x0e62ba6,0x146c170,0x16c3872,0x0015987,0x180d1ea,0x02c42b0, + 0x13b231a,0x0f66908,0x0bb9b1b,0x1fb39f2,0x1cf9e66,0x12d42e5, + 0x01217c2,0x05747fd,0x1a5a6e4,0x06b93eb,0x1c8147b,0x0155fcc, + 0x02081a1,0x0e35d95,0x0c2d382,0x1e172e7,0x0657acb }, + { 0x074c8d4,0x02337e1,0x1344c4c,0x0c61532,0x0276517,0x1ca1afa, + 0x16329c1,0x00c42e4,0x0eb897a,0x0428203,0x1b84c11,0x1ddcac3, + 0x1bf38df,0x150bbc5,0x1d3eb3e,0x173d223,0x017b9ab,0x13b2e33, + 0x03c424c,0x0a9337b,0x1159b13,0x1bd39dc,0x103ad8c,0x0fd16d5, + 0x1ccf16f,0x1a9f960,0x0861f7b,0x1665807,0x0b9c625,0x0ea4c18, + 0x0e226b4,0x05e21ca,0x135eae3,0x1aade0b,0x070a757,0x1b6397b, + 0x0539db0,0x014623f,0x0ceed09,0x02590a5,0x03d2da4 } }, + /* 28 */ + { { 0x11f2865,0x015b743,0x035a5dc,0x1e28524,0x16cb639,0x1ac308a, + 0x08a8116,0x024650a,0x1f3b138,0x1ca1d68,0x081ba3c,0x0014e24, + 0x0ae6c22,0x11a6acf,0x024396a,0x1eeb385,0x140f6b7,0x1d5a97e, + 0x002fd59,0x0591bc3,0x0396f52,0x1956677,0x0607a5e,0x1d4b976, + 0x15819c4,0x1f7f01b,0x02ad474,0x1b330bd,0x150fd80,0x0b655e5, + 0x03789b2,0x12fc390,0x19d6b13,0x11abefd,0x0053de5,0x16b0563, + 0x07f4c7f,0x13c1108,0x1f98626,0x05b806a,0x002aeef }, + { 0x07ec9be,0x1c93796,0x0804ae9,0x1ce4b16,0x092f307,0x1d35a51, + 0x0a8431b,0x156e9cc,0x1e2bcc5,0x06042a4,0x0301ce0,0x1b70f77, + 0x0db4160,0x194f8ca,0x1bc14a4,0x09539ab,0x0146dda,0x0875c6d, + 0x17a88f4,0x1a87a42,0x1fae0b5,0x017e1a5,0x1b3afbc,0x10eaf4e, + 0x164d084,0x051d669,0x00b4d33,0x028026d,0x0d95e2c,0x13a10e9, + 0x0a02729,0x0f0dd54,0x1fd1d6e,0x12ff661,0x0db68a5,0x073d622, + 0x0077920,0x038dd56,0x0bac122,0x002962b,0x06b446c } }, + /* 29 */ + { { 0x1e8fe80,0x0f59712,0x085f206,0x0d30471,0x0b5f790,0x120c249, + 0x1a65a07,0x08bade3,0x098ea6d,0x056c56b,0x00b9016,0x15a97fa, + 0x0d5bae5,0x140920b,0x1b70c9e,0x0f94202,0x185a334,0x0c598d4, + 0x0a994e4,0x1b4c210,0x15fb0b4,0x16da461,0x072e46c,0x155f188, + 0x0817cd2,0x0e04f4b,0x0f37f73,0x14c6090,0x1692541,0x09b0895, + 0x05dc156,0x1f14541,0x1dcd712,0x02940af,0x08e8d73,0x0ab356c, + 0x132b609,0x0475f04,0x014bcc3,0x097611c,0x0861342 }, + { 0x0231d8a,0x01031d9,0x199ca24,0x13b34c2,0x10f6232,0x0d4f93d, + 0x03f9c1c,0x0fd55f4,0x0603f04,0x1e6c4b0,0x0a870da,0x14edfb2, + 0x16118cc,0x18ea41d,0x05398ad,0x0a4c468,0x0ddba70,0x15091e6, + 0x166d716,0x0ec86ff,0x0fa31a5,0x0126468,0x094c06f,0x0484f9b, + 0x0ad4410,0x0014b78,0x034ea9b,0x1cdf6bc,0x0a39960,0x0440039, + 0x0b73631,0x1081a7f,0x1afca12,0x0eaa0a6,0x08f77a4,0x1a53e99, + 0x0441734,0x1be2cc4,0x195f000,0x133399f,0x086333a } }, + /* 30 */ + { { 0x0f53b40,0x1d3a8f6,0x150b484,0x045ef14,0x0ff2c6f,0x1d72b6e, + 0x1c38bc4,0x11c1eb3,0x10e6174,0x0fc665f,0x1105164,0x1973ae5, + 0x170aade,0x064e6e5,0x0bb6149,0x1f8e0d6,0x12c1eaf,0x147005b, + 0x09ca040,0x04850b5,0x0afa89b,0x105b3ce,0x0a9fa9f,0x014dedf, + 0x18c264f,0x1cbae95,0x0c3a010,0x1daf62e,0x1730497,0x15a2e42, + 0x0f96a4f,0x0130dd2,0x12bf5d4,0x06057e4,0x0a71a88,0x1ea4d6b, + 0x199dc3a,0x0fa3e4d,0x0b3242b,0x1c57440,0x012b25f }, + { 0x1eea395,0x06bc519,0x117026e,0x11ec67f,0x07a9361,0x076777e, + 0x058a49c,0x018fd04,0x0c628ed,0x123bcdc,0x1a24e54,0x194343a, + 0x1091db5,0x0c376e4,0x09b8639,0x1e77f0c,0x08bfeb3,0x07f011f, + 0x09405c7,0x13fbc20,0x12de627,0x0e2af0b,0x194bb1f,0x1a9948b, + 0x08695c6,0x078a22f,0x02f6f04,0x05bc70f,0x03835e4,0x06f437e, + 0x148ac45,0x0fc216c,0x1aba456,0x13c7f4f,0x00a8e43,0x148223b, + 0x0edf0ac,0x15b0e15,0x12dd15d,0x152e959,0x0216279 } }, + /* 31 */ + { { 0x047f747,0x06d5fa0,0x087b053,0x1b8262b,0x03ca233,0x12e8538, + 0x12f4d03,0x0d2b3cf,0x1bb4138,0x1e86274,0x07ef607,0x11621e0, + 0x1d189d0,0x13b5c11,0x112710a,0x00142a0,0x0a1398b,0x040e112, + 0x1a05e79,0x109c9f1,0x01e9080,0x0a34c72,0x1f62be6,0x0217e5d, + 0x0e37c56,0x0878f18,0x1e9f49e,0x1cd4087,0x1953884,0x1306598, + 0x1f6765b,0x006f33b,0x15f986d,0x1c817f3,0x1c47e3f,0x1c76951, + 0x1588416,0x0a29bc3,0x14d7bea,0x07f304e,0x020683e }, + { 0x0378878,0x0171368,0x1e1f2d6,0x074f28a,0x1e214c2,0x134459c, + 0x002fe3d,0x0e027a0,0x1405152,0x0a46a7a,0x047d75d,0x02ba802, + 0x027113c,0x145ffc8,0x1d6949a,0x08b9877,0x0109b49,0x0ded358, + 0x10bce81,0x198e9d7,0x1fa183d,0x0221f7e,0x0abbd8a,0x0b8b7e8, + 0x00ee956,0x01d6973,0x1564bc9,0x1e1f421,0x03bf514,0x05990de, + 0x1d1ab96,0x0c0aed4,0x13b0868,0x1840d40,0x0fe135c,0x1217804, + 0x12dcee5,0x081d501,0x11e567f,0x1ea4fad,0x05e416b } }, + /* 32 */ + { { 0x06cc23c,0x09bb001,0x016090c,0x1d6b652,0x1819aae,0x09770bf, + 0x1cbe317,0x0055244,0x1ee5cc4,0x02473e5,0x1bc1f60,0x0ddcefb, + 0x1edbc7d,0x1b57c10,0x15a4913,0x17712c3,0x0ed996c,0x02fbcb3, + 0x1a85569,0x162fd52,0x0d56f81,0x1801f9f,0x0cb67bd,0x1054b65, + 0x05906e8,0x0c02f37,0x0aba51c,0x0df420e,0x0c76f48,0x1e28b2c, + 0x080d367,0x19606b5,0x1603dc0,0x13240cf,0x1fadd6f,0x1f6f673, + 0x0f04a9e,0x03aaa56,0x1f78f2a,0x1d90f69,0x04ff682 }, + { 0x0a10ad5,0x0b13fe8,0x1d14c49,0x052d1cd,0x1fd45c7,0x1508b1b, + 0x0f5ae01,0x1c65303,0x1de5033,0x096f0e6,0x1e2622e,0x08bd7e9, + 0x1c3b44b,0x0d73f0e,0x06e625b,0x1b0f194,0x05a0778,0x1a90b37, + 0x1445a11,0x08e57d4,0x144582d,0x157944a,0x1ef74e0,0x0dd8993, + 0x116025d,0x1811176,0x12d954a,0x0c29d63,0x06210f3,0x0fb9d0f, + 0x09d8f17,0x00434e9,0x1160285,0x05ea6f4,0x1003197,0x1348994, + 0x0f15e29,0x058c3f0,0x141f123,0x11c6804,0x051eb81 } }, + /* 33 */ + { { 0x12100ab,0x0e8bc5c,0x00e47f0,0x012c0b7,0x1f2e3d6,0x0f2ce86, + 0x10956dc,0x008254f,0x114fcbe,0x1c5b33a,0x141abcf,0x126ab3f, + 0x070e8a3,0x0901068,0x0c99408,0x0f7caac,0x0d1528e,0x0334b7e, + 0x11edd95,0x10a2961,0x05b5658,0x062c895,0x033603e,0x04996fe, + 0x1ef04f3,0x0bac5d7,0x1f1b68f,0x16a7dd9,0x11df2f6,0x046c18e, + 0x1b7b7bd,0x0e70256,0x136b965,0x13018f9,0x192bb98,0x17905d5, + 0x1244f09,0x055e996,0x191fcc0,0x0aa63b2,0x08b0af9 }, + { 0x0603544,0x00c0517,0x167addc,0x0644359,0x0b573ac,0x0038191, + 0x1d99589,0x07a742f,0x1b89abc,0x09f3a56,0x0c896ab,0x1c75af2, + 0x0b8a3d2,0x17812b2,0x1eee813,0x1a56a8a,0x12ffc2d,0x0443ab2, + 0x19c50fa,0x00ba2bc,0x0d70d29,0x0101724,0x1b6212d,0x0c6d4ae, + 0x19219c7,0x06f837c,0x04d78de,0x11b8684,0x064a02a,0x0b9e886, + 0x19a5707,0x1982af4,0x16a4ece,0x051aa66,0x0722389,0x1b75b98, + 0x1839329,0x1278d94,0x02b4200,0x0929b49,0x05363e5 } }, + /* 34 */ + { { 0x03fc641,0x091dbf1,0x018c7d5,0x1f0ccce,0x1e54e72,0x004e97f, + 0x057d638,0x1c25294,0x18c57f5,0x101ccbf,0x159373c,0x049962d, + 0x1ba2297,0x05d517f,0x1ef93f5,0x11dacd2,0x0460a6e,0x11fa83f, + 0x014214d,0x1c74baf,0x02080af,0x0ecaa04,0x1bbbdb3,0x18846f9, + 0x1d889f2,0x129b80f,0x0970e14,0x12db107,0x0212f14,0x13f6b95, + 0x1378971,0x03fef1f,0x1416783,0x1a0a325,0x001305b,0x0fd32ce, + 0x045b069,0x02e1d0e,0x0c30fe9,0x0307f7a,0x0633340 }, + { 0x0fbbbce,0x0d06651,0x1d10e72,0x1954196,0x076f6e5,0x1c7671c, + 0x00438d0,0x10539cc,0x013802d,0x1568a47,0x11686c2,0x18c139a, + 0x009c3e5,0x1de7e0f,0x172e165,0x09ba10e,0x190d858,0x1d8cffb, + 0x0070a8a,0x11703db,0x07e3259,0x17815f0,0x0462f7c,0x0ecb9d2, + 0x1c8eeb9,0x0d703a7,0x02c93e5,0x04bd3b1,0x18f09d1,0x166e064, + 0x09ceec4,0x1416e96,0x06aee07,0x03be725,0x0be7020,0x1e8e47a, + 0x1ea8026,0x0a23eb5,0x02dce56,0x0b82c50,0x093a707 } }, + /* 35 */ + { { 0x15b27f9,0x1f7f138,0x048c9ae,0x0454501,0x0935a5e,0x0c51355, + 0x08ebff5,0x128bbbe,0x07c1386,0x0641f0b,0x08854d5,0x1793125, + 0x1544799,0x0dc684f,0x1b91c42,0x1d4d09c,0x016d588,0x1631d7b, + 0x00eac6d,0x12ce0d1,0x13365e8,0x101e904,0x0f04e4e,0x1847bb4, + 0x1292192,0x121e817,0x0b73dba,0x16e196f,0x1559e1a,0x07543c8, + 0x02c490d,0x0dae1fe,0x00680db,0x15d2282,0x1948a0c,0x1e3421f, + 0x05f0cb8,0x0fce047,0x107f75a,0x1588962,0x01a7422 }, + { 0x140b675,0x0ee974f,0x1ce70ea,0x07f98e3,0x0a7c660,0x0471a11, + 0x0698465,0x1083127,0x0ed0ab4,0x19db0ac,0x0729ae3,0x1b2fdc6, + 0x03a3aa7,0x1bd46db,0x07a197b,0x0c5c978,0x0092c7c,0x198afc6, + 0x1d71b43,0x00f11f3,0x1ec5a26,0x14a5b79,0x0c60cc4,0x169b093, + 0x1bcd636,0x14db9d6,0x02f1a66,0x0dc2912,0x1175e76,0x086c150, + 0x13efcde,0x1f8a794,0x143605a,0x1b048bf,0x111e1ff,0x0caefed, + 0x000c82b,0x1e3aa93,0x1667209,0x0613a4a,0x00944d6 } }, + /* 36 */ + { { 0x0ab9620,0x15b1f73,0x00233f7,0x1af0d9b,0x1ff4fa6,0x119059e, + 0x1760915,0x02a28bd,0x0c49439,0x172fc31,0x0cfe1ca,0x10276e7, + 0x099508e,0x1297cbd,0x16017cf,0x136c477,0x028c982,0x07b8dae, + 0x1b833bf,0x098e1d0,0x136eb39,0x1491ded,0x14d3ec6,0x1c4fcb4, + 0x15862db,0x0b4eb27,0x0e0ead8,0x15c47be,0x0828cbb,0x18d893e, + 0x02b75b7,0x07460f5,0x101899f,0x0efb30c,0x1966047,0x0e6d990, + 0x19943b7,0x05bbba3,0x195da8f,0x106dfb0,0x07d89f3 }, + { 0x1f92b2b,0x1212164,0x0af7e15,0x0b88dc6,0x100c6a7,0x0cd2e2b, + 0x1a2ddfe,0x0d127ce,0x0031495,0x177f42c,0x199c26d,0x1433859, + 0x13bbfe8,0x1737624,0x068ec6f,0x1851ae4,0x0a9c371,0x0937777, + 0x145df87,0x1022bc2,0x05a5d79,0x0758345,0x15efcef,0x1a56965, + 0x1a22046,0x0fe6fc6,0x0d66fa7,0x1be132b,0x040b793,0x0bde3bb, + 0x11725a2,0x0b457a7,0x00cf4c2,0x1f3a267,0x15ba26b,0x162de8b, + 0x1a8509b,0x1f9d659,0x09b9ad4,0x03ec7e5,0x0449af8 } }, + /* 37 */ + { { 0x16d9377,0x0789950,0x1e7b0bf,0x06fc345,0x1ab377b,0x08cd72c, + 0x084ba1b,0x162e5c3,0x0d013bb,0x1589733,0x1d9aeb4,0x00ab96b, + 0x100972e,0x1ccf55a,0x0778700,0x0bd85a2,0x0fdc65f,0x1e0f98a, + 0x0a7fd64,0x0230831,0x06e6fc3,0x1670292,0x17dcf07,0x04a0adb, + 0x1136316,0x10ce146,0x1dbec97,0x0153b7a,0x1cd2d73,0x0922422, + 0x0b4127b,0x1a6dd0a,0x179b83f,0x04541e3,0x1f1fda3,0x070b46b, + 0x095e803,0x0df8f0e,0x06bd4a6,0x1864112,0x00e8617 }, + { 0x1c81b5c,0x1030133,0x1cf14dc,0x1bce6f0,0x0fa89dc,0x0a27e81, + 0x0c2c2a0,0x10654e8,0x126208c,0x00362d3,0x0903d4c,0x0cc1b1d, + 0x044e066,0x04b209d,0x14097e6,0x0293f3b,0x0cc46b9,0x15ef9c0, + 0x0849730,0x0acc321,0x1c37801,0x1ba93c9,0x0135a8e,0x0f4c5e4, + 0x013746b,0x0bc5b00,0x0161756,0x139fc4d,0x15fe66a,0x065c41c, + 0x1db72b4,0x08d64c3,0x0b468fc,0x0c90c5d,0x17be767,0x05941de, + 0x1e45240,0x03ea542,0x1da1f14,0x1e264d9,0x06f4404 } }, + /* 38 */ + { { 0x1ebd3ff,0x0c905a7,0x0eea8f8,0x11fbfa5,0x0a6234d,0x0d4c14e, + 0x0bcab86,0x0416fa3,0x0c6f5bc,0x1ef0b08,0x0e72a48,0x17e7b54, + 0x0be204d,0x16c6385,0x0b7a6e1,0x06e1654,0x0377c9d,0x1139706, + 0x1595443,0x02980dc,0x16b0809,0x142be5d,0x0d8479e,0x04cd4dd, + 0x1c6efd8,0x00e03b7,0x18c2560,0x1f5869d,0x024063d,0x00515cf, + 0x115a7fd,0x0f0f54b,0x1ba31a9,0x1866953,0x1f7ccf1,0x081c9a3, + 0x0895f07,0x1f18993,0x1c78a40,0x1f0ff6c,0x0905771 }, + { 0x0062bee,0x0dd06d2,0x07e5466,0x1929afb,0x18e7238,0x0491600, + 0x0a6f078,0x0bfea7e,0x1b12d85,0x14d9540,0x0328a77,0x1ddadad, + 0x1f649f3,0x028604b,0x0b7f0d3,0x13140c9,0x0b99db3,0x040cb25, + 0x0961c89,0x0b388ef,0x103a00d,0x0b3a62c,0x027fa8e,0x0087ba0, + 0x1d8ee15,0x0103557,0x197c7b3,0x0ae434d,0x19b7b4c,0x124186d, + 0x0aadb5a,0x0cd91aa,0x0ffc617,0x0151383,0x075ab32,0x107bc48, + 0x07f2f7a,0x02f8291,0x17b3018,0x076c809,0x06a2295 } }, + /* 39 */ + { { 0x0fce389,0x096c7ba,0x1592491,0x0055f4a,0x059634c,0x16bc128, + 0x132efc3,0x01b26ef,0x137718e,0x0fa022d,0x1a69362,0x1cfb3f4, + 0x1a11074,0x194ad85,0x1c2ec1d,0x1dbccba,0x0adf107,0x1d916aa, + 0x068a71e,0x1347b14,0x03ab5c3,0x016bcaf,0x0dc8db0,0x0b132a2, + 0x02d002b,0x1717b94,0x195e42f,0x1c44cb7,0x065ea25,0x1508d47, + 0x0f64783,0x0c0039d,0x071a708,0x02a0107,0x1d68b07,0x022d201, + 0x157f698,0x196ae01,0x0d09f0e,0x140c33c,0x0528c9e }, + { 0x126c577,0x0435a2f,0x15147b7,0x1128717,0x1807470,0x12c153f, + 0x0404de4,0x13e5bfc,0x0de1e56,0x0475650,0x168d5b8,0x1df534a, + 0x165f952,0x124bb10,0x1602d4f,0x0e3e549,0x055cd5d,0x0695b2c, + 0x1b3a8fc,0x0e097ec,0x03ca246,0x0fa4919,0x064fd90,0x1b6264a, + 0x1855c9a,0x1295340,0x18b4675,0x0daa459,0x02ed7b8,0x0f882dc, + 0x0a54d82,0x11c2a1a,0x10f0094,0x1f4489d,0x0fec2c4,0x12475b1, + 0x1794b44,0x18aab67,0x13d5f2e,0x126e717,0x0200f90 } }, + /* 40 */ + { { 0x188387f,0x117e2c1,0x0f17e6c,0x0051d10,0x0f26f17,0x1bcb9e6, + 0x0ae4346,0x0e288f9,0x0f6ec91,0x0aea751,0x136f023,0x0931861, + 0x0b2e16f,0x04311e1,0x04a4431,0x18a8bb9,0x1b030db,0x0758a48, + 0x137886c,0x1bd65c2,0x10f4631,0x1317f41,0x0128841,0x1383e7e, + 0x0979c37,0x1cad263,0x03ec1a9,0x14e656d,0x19dfa98,0x193d0b0, + 0x06ce910,0x11b7c59,0x1a307d3,0x04ff548,0x03480e6,0x1f27379, + 0x0f4a331,0x155d790,0x15770f6,0x131ba1e,0x05c307e }, + { 0x1b233da,0x070621a,0x0616ef1,0x0a45edf,0x03d2908,0x1812347, + 0x0b486a2,0x1cf33ba,0x1a96916,0x1c7a074,0x0f33b65,0x10d8c29, + 0x0c0327d,0x19483b1,0x1a5540a,0x1e5db2b,0x197a879,0x187fe90, + 0x0382f4c,0x0ca26ea,0x04c4c43,0x050413e,0x09b0c52,0x19f8164, + 0x012a83f,0x0c4e3cc,0x18c64a1,0x07b1a2f,0x10f42dc,0x167f441, + 0x0fe2d5c,0x0960ff0,0x0d9ff92,0x08a47be,0x0540294,0x1866395, + 0x0c59f9a,0x029cb42,0x11e1743,0x1f58286,0x01df16d } }, + /* 41 */ + { { 0x0bcacc3,0x1da5634,0x033f31e,0x1e861eb,0x06ded34,0x10c2ad0, + 0x07d3f51,0x1798b3f,0x045c9f0,0x0a48cca,0x17224bd,0x1d8c86e, + 0x1adc5f7,0x1e42cc1,0x01c23c4,0x1a10e37,0x0c482fc,0x1d9952e, + 0x15ad303,0x19b86a5,0x1b2defd,0x0245637,0x12ec93c,0x120c8e2, + 0x0d4f533,0x1622cc1,0x1ee0e8e,0x0c5d6a5,0x17a2231,0x0f94119, + 0x14dc4c3,0x19787b7,0x0e7b802,0x1d6076e,0x0564919,0x1d1672b, + 0x1b56717,0x09e9740,0x0985c87,0x0a08ca2,0x0729a7f }, + { 0x020f90a,0x168d542,0x01561d3,0x1c1fc99,0x0368e19,0x1f3a57b, + 0x12aaac2,0x1536c5a,0x08ca60c,0x17e6240,0x16a19dd,0x0b4aec8, + 0x0cf310b,0x0ed8d92,0x06eb26f,0x0b68826,0x11d2dea,0x177bbeb, + 0x0bf3193,0x0da420e,0x17f0470,0x08b39eb,0x0a6e49a,0x13c0cc6, + 0x00bf3e8,0x0a01170,0x0dd01df,0x0e5a19a,0x1232e24,0x0206c14, + 0x0ccf884,0x071b90a,0x1916dfb,0x07b3397,0x166c52e,0x1a91776, + 0x144be19,0x0f4fa56,0x0757067,0x092465b,0x07f6d36 } }, + /* 42 */ + { { 0x0794819,0x0326f37,0x1684ef4,0x1df05d7,0x1a6b694,0x0f14022, + 0x1ff82e4,0x1a43e02,0x107a43c,0x08698f9,0x10cfa46,0x044cc60, + 0x146c26f,0x055fee5,0x1222a9c,0x0238174,0x085a464,0x020c6c8, + 0x1fed620,0x069fcd7,0x18491b9,0x1bf1007,0x1d74788,0x0a827b6, + 0x0d63fa5,0x1bbef82,0x1788ecf,0x042ddae,0x11bd30e,0x136587c, + 0x0268161,0x0ee538a,0x0c395d9,0x1596bc2,0x062114a,0x0dd92fc, + 0x0093d68,0x1be0fc8,0x021b232,0x12ac51e,0x02d0323 }, + { 0x044b4c5,0x04a03a5,0x1262a07,0x1398e05,0x1984687,0x186e4bd, + 0x08a1f3a,0x04396a0,0x06e3aa3,0x0180893,0x095b08c,0x0ec7c98, + 0x05c0ac8,0x12ada42,0x00d3483,0x1e6b6ca,0x040f240,0x0554b50, + 0x13dfbb7,0x1a4da6f,0x0656046,0x109dc08,0x18a96a3,0x1ae1856, + 0x04b9783,0x147c302,0x0167936,0x1f75ff1,0x17f5d12,0x080d2a2, + 0x15e4a76,0x16a636e,0x09e1eb2,0x14b9ce9,0x0f72793,0x12429b5, + 0x0eaa9bd,0x0b927e2,0x0ee6d6f,0x1663df3,0x0734c12 } }, + /* 43 */ + { { 0x0f9b086,0x11e1749,0x151263f,0x1d67fa8,0x0641b93,0x01632e2, + 0x0822d70,0x0848f9c,0x1c4f032,0x1296e50,0x14a7da2,0x0fb2cf3, + 0x14b5ec1,0x0a037af,0x14bfb42,0x1502223,0x1dc0d9b,0x19307b1, + 0x151ca8f,0x160ade2,0x10e6de2,0x0f80394,0x06c5c36,0x16b91f2, + 0x03e8db6,0x1f75171,0x073cd30,0x08b4507,0x173ee23,0x0a308dc, + 0x1166f71,0x17649a3,0x1bda6c2,0x0a0d0b2,0x0e8cf18,0x032faa5, + 0x1d2eb20,0x1d8b094,0x1927d1e,0x10e43f7,0x07c558a }, + { 0x1350fec,0x02d291f,0x1302e52,0x0ad471a,0x016678c,0x0d53268, + 0x11a8835,0x1c91de6,0x0d96da2,0x02ed501,0x11ecf2e,0x09d49ec, + 0x0c845ec,0x06af4a3,0x1469b28,0x1e95781,0x1c14fa9,0x1a0ec68, + 0x122c4c0,0x0e598b3,0x1bfb439,0x06a1a7f,0x19f87d2,0x13a4630, + 0x0e93a81,0x11f9a86,0x01b77bc,0x13ea612,0x0cf12c4,0x167c900, + 0x1f0f0b9,0x0c80865,0x0691cc1,0x0b5a921,0x12d1c92,0x1d7ffee, + 0x020a97b,0x093e4f8,0x10d2111,0x194f678,0x034cd7d } }, + /* 44 */ + { { 0x1e7fe87,0x0bb0d2c,0x15cbc0c,0x14008f9,0x11eae31,0x1187b15, + 0x0b9a3eb,0x0864f20,0x1b71db1,0x1337a46,0x00e3d29,0x0cf01c0, + 0x0d75ee6,0x015eebb,0x116b19c,0x19ab876,0x028a0d6,0x08697dc, + 0x16316c4,0x1cfe3b3,0x1e9627c,0x120905a,0x0507f83,0x04cf86e, + 0x1b984b9,0x166cad0,0x07580c4,0x040dcb1,0x1493565,0x1a176d2, + 0x0b0619c,0x00e18e9,0x14520b9,0x1d8599b,0x0ed6555,0x084e079, + 0x06ed8c1,0x10face5,0x0e21fd8,0x18557ef,0x07ceb1c }, + { 0x17fd65b,0x1d2dded,0x15f0191,0x006d928,0x18d45cc,0x0938c56, + 0x0676e78,0x1638db5,0x0e93a7f,0x08eddfa,0x159a87b,0x12b97a2, + 0x194512c,0x0de0648,0x186e803,0x0a4d290,0x0989e7f,0x11e3661, + 0x0506aab,0x12c2a01,0x18e3671,0x07e4629,0x0ff3d74,0x0b4aa3f, + 0x09929a2,0x19356b7,0x145f283,0x00e2130,0x09ef7e9,0x1c757d4, + 0x125d0ed,0x0e3568a,0x1d5ea31,0x0e1b69c,0x0fcf9b4,0x1ae885e, + 0x059d568,0x1341f00,0x1b57096,0x13244f9,0x01f629a } }, + /* 45 */ + { { 0x05a1c3e,0x0eed672,0x117e249,0x0a83eea,0x12d2936,0x13fc143, + 0x0bf2cdf,0x1a48ac4,0x13e4c79,0x011a289,0x19175a2,0x1f09384, + 0x195dffa,0x0ca4015,0x1e3d376,0x13f4060,0x1f09d33,0x02b3493, + 0x1f64773,0x00143d3,0x0bd79a5,0x0005585,0x1380206,0x129cbbf, + 0x135a381,0x0446cb8,0x1e62b7c,0x1d0ec60,0x05a2a79,0x00dc4d2, + 0x064eebc,0x0f11687,0x1ed6154,0x14cbeb7,0x1c8b9de,0x1b301ca, + 0x0a378ee,0x0487fd1,0x0168aab,0x14517b0,0x04a75fd }, + { 0x1e74cbc,0x147ddaa,0x1c97426,0x1df5631,0x137738c,0x12761d3, + 0x0eb5a5d,0x0621f84,0x1e7e0ad,0x0d3e9ad,0x07326f1,0x0d1dc90, + 0x14e75e0,0x1ea5761,0x10baa64,0x0c789e1,0x1e80d4a,0x0789927, + 0x06c164b,0x16f82d3,0x146b5db,0x06d3f07,0x110b59d,0x001f5d4, + 0x166c7a3,0x041ad2e,0x04ccceb,0x107b904,0x008496e,0x0097462, + 0x105c3be,0x133debf,0x0e1dcb6,0x074314b,0x1c6c5cd,0x10dc56e, + 0x183507d,0x114e6e2,0x05e6811,0x15c47b0,0x05819f9 } }, + /* 46 */ + { { 0x0a78811,0x14890b5,0x1f0f665,0x084207c,0x164ee8f,0x1cf34c7, + 0x041c08a,0x1bdbbe0,0x04f582c,0x1000fcf,0x1eb06b9,0x115e5d9, + 0x0924a60,0x031c980,0x1d31e10,0x05222dd,0x0e6ebf7,0x0293175, + 0x113b968,0x1a15eb1,0x1bc7ddb,0x08766c3,0x01d6bfe,0x049e229, + 0x1b34c6f,0x0b917ee,0x07a197c,0x1020850,0x0c1b9a4,0x1213443, + 0x07e55a4,0x13de846,0x15f3208,0x1f41737,0x0b3f429,0x115eb0f, + 0x1ac395c,0x0b8c8bc,0x09d4359,0x07826c9,0x0745960 }, + { 0x01ae519,0x03adffa,0x0944709,0x0295f1e,0x14401fb,0x1d961e9, + 0x1f34abb,0x010e1bb,0x151cdaf,0x1969c2d,0x02ec666,0x04ad041, + 0x168531c,0x0619f9f,0x12277d9,0x02ed22d,0x0992457,0x1611e7d, + 0x1b4042e,0x136a3d0,0x0313233,0x069131c,0x0236c3a,0x1fdbd6e, + 0x1e17900,0x178fbb4,0x0e8da1f,0x1fb2db9,0x0764753,0x1591c8a, + 0x1773411,0x0188b91,0x1ff2064,0x01ebc79,0x1ef6e0d,0x01dfa2c, + 0x0b77ee9,0x1e65b6a,0x1ed1524,0x027679e,0x0330255 } }, + /* 47 */ + { { 0x1eaaca1,0x002349a,0x0408dbc,0x0b12232,0x0c384b7,0x094aa60, + 0x159979b,0x1af966e,0x1b1e9d6,0x1c8ccdc,0x109d5f2,0x0693853, + 0x1075852,0x1c739c6,0x12f46ea,0x1484f13,0x0905923,0x0cdc6df, + 0x03f8622,0x0ef27c3,0x0083a23,0x0bd3a17,0x0909c5d,0x1d7ac27, + 0x179d24e,0x1bbc624,0x1353cb3,0x0064a0a,0x0705de4,0x1048cac, + 0x0ea8ee2,0x067b333,0x1191bd9,0x1f70f0d,0x0e90ec3,0x0975fdf, + 0x1facdf1,0x1d68c21,0x15872ce,0x160870e,0x09328ad }, + { 0x106b872,0x027407c,0x1996afa,0x00f04c4,0x105523a,0x0c667bb, + 0x1a9f8ce,0x047b138,0x1f55b53,0x1d5aa8e,0x137aa0b,0x1d940aa, + 0x0da0578,0x1baac4e,0x09948f4,0x1aea1de,0x042864a,0x16c7eb1, + 0x1e3f87f,0x04ff8a2,0x142293f,0x184efc3,0x1ecf9bc,0x0a1a0a8, + 0x0e49e37,0x0509431,0x097700e,0x1b218d6,0x1b682b7,0x1711426, + 0x02b0686,0x1310326,0x1f3dab7,0x1f05223,0x154aebc,0x0a61cd7, + 0x162d25c,0x00012df,0x1579c1a,0x19f5ba1,0x00aa1f3 } }, + /* 48 */ + { { 0x0a10453,0x110c811,0x042ea60,0x1854074,0x1d1eb91,0x12379de, + 0x1765659,0x18d5f76,0x0f38b6f,0x0c6f1a2,0x1f28769,0x07cb719, + 0x04ce47c,0x07b86d0,0x16385b4,0x05dadf9,0x09bda26,0x156221a, + 0x15b8be3,0x01b0f78,0x0e58932,0x040c89c,0x0738fa8,0x1646d81, + 0x02dffa2,0x186d2c3,0x1239fbe,0x161f34b,0x0c78eb6,0x01958b5, + 0x0bd2d4d,0x0e136a3,0x1f43105,0x0cb1437,0x1be23d4,0x1a11c46, + 0x0ed403a,0x09f8bb7,0x151787e,0x1c12c6c,0x0559337 }, + { 0x0fd807a,0x0fb9c6c,0x0888c37,0x1b56262,0x14e0ec9,0x0d7de1f, + 0x1d36d89,0x12a2945,0x09f12f8,0x0db8302,0x0113f75,0x1847586, + 0x0fb46f3,0x1aa00a4,0x08cb47f,0x1caa836,0x0f539b4,0x0b0da2c, + 0x175c2dd,0x0964941,0x01d9f69,0x0c944ac,0x03f190a,0x0bfc45a, + 0x149beee,0x1b1e02e,0x1da862f,0x15e688f,0x1929d67,0x0ee13f8, + 0x033a5a8,0x182aa3d,0x0fe6028,0x0a7d135,0x0bccad7,0x084fb59, + 0x145c2cb,0x0b18de2,0x0534d28,0x1f36192,0x0930070 } }, + /* 49 */ + { { 0x1a9bc05,0x1962f34,0x0dcf4bc,0x0cb1389,0x0a5c19c,0x132fce0, + 0x0797a51,0x07212b9,0x1bcfb4c,0x1587949,0x0df0c62,0x10ee3bb, + 0x08b9070,0x1359c02,0x13a5961,0x1b37b12,0x0cf606b,0x0f8cd48, + 0x1bf4b5a,0x1ab1bf6,0x0a69cc1,0x07230ec,0x021b731,0x19c9063, + 0x1c277f9,0x141622a,0x19d97e2,0x0934b32,0x1adc8d7,0x134661d, + 0x0acbff1,0x122259b,0x0018396,0x1e3e59c,0x170ec90,0x09530f2, + 0x010a222,0x1af9880,0x178521d,0x082b0f6,0x0043a21 }, + { 0x0873752,0x14ede1d,0x1fb9eef,0x085e885,0x0e1493f,0x0610c0f, + 0x08b2306,0x1cf3039,0x0e29769,0x0671848,0x1a317c0,0x1591bce, + 0x1eb4626,0x1a6bb3b,0x1a73918,0x129cc67,0x0ade0fa,0x1fc4e16, + 0x07d6d6f,0x0b98228,0x012c04f,0x1b11146,0x09597dc,0x00b99ca, + 0x1706a0c,0x027f8df,0x1ef921f,0x1a0ffff,0x19f1a45,0x1e04d24, + 0x000fb10,0x131b290,0x14e79bb,0x1897c27,0x08581cf,0x1b1466b, + 0x0f970d6,0x1af57b8,0x02ba12e,0x0f7e49a,0x018d074 } }, + /* 50 */ + { { 0x0601faf,0x1e3be42,0x1dc9634,0x055e383,0x09465be,0x0b6c036, + 0x19e6344,0x079fec4,0x0d5b0d9,0x0cb6063,0x19c8e8e,0x1aeabd8, + 0x092fa1a,0x01dd29a,0x1aa0510,0x09b152c,0x0222ac3,0x0ee264a, + 0x159d619,0x08e3bdd,0x128fddf,0x0bca9ea,0x162b296,0x1d7ecfb, + 0x063b524,0x069d972,0x05f896d,0x0b0490e,0x159daa2,0x16dd218, + 0x1008f16,0x1066aea,0x058f9c6,0x058d32a,0x169fe4e,0x039ed0b, + 0x0efed23,0x0d27ed6,0x1796660,0x1da1176,0x0711093 }, + { 0x01f161a,0x11fe320,0x1a1c4aa,0x012e98b,0x1735856,0x1aefc17, + 0x14bec5e,0x1329544,0x1a48e62,0x05c1583,0x1611f6c,0x02ae53b, + 0x0600234,0x0294e2d,0x1953401,0x1ea71e3,0x19e6d98,0x1e60e29, + 0x034eaf2,0x0c56a65,0x10cd361,0x1c15427,0x1d68de4,0x1dce908, + 0x1a81b4d,0x18dfb8b,0x0d308ef,0x0d9e6bf,0x1e8b3e1,0x014fbc3, + 0x0c1ff47,0x0b36f35,0x1da7e68,0x16305db,0x028217d,0x0a0e420, + 0x07ed48b,0x0200acf,0x05f50c6,0x1b49b39,0x017898b } }, + /* 51 */ + { { 0x01b8cf8,0x041ec57,0x015b361,0x05d3451,0x123d4b4,0x0525e11, + 0x1613c81,0x1f4ec66,0x0ca7a69,0x1059114,0x1eeac93,0x1517eea, + 0x0a8afbd,0x1662fce,0x0c90221,0x12b870b,0x013d41a,0x1a3fda4, + 0x0aaaf9a,0x178a798,0x199d3f1,0x1f8d68a,0x1c8b368,0x03d5363, + 0x0c081c3,0x1608d97,0x0c05852,0x091e609,0x0fa7ab0,0x0774e35, + 0x0f738c7,0x08281b8,0x1af7633,0x055dd2a,0x0cdf73a,0x1d096f5, + 0x07cf3ef,0x0f3b246,0x1aac943,0x19e2a6a,0x073a88d }, + { 0x0e83b39,0x1414403,0x0df4fe1,0x073e880,0x077a441,0x0de420a, + 0x02c3c5f,0x093f20b,0x154d175,0x0db27a7,0x01fff8b,0x14d5e46, + 0x01a23ce,0x0789313,0x0fbf555,0x0fe4c72,0x18a10f3,0x097a732, + 0x13b878d,0x06f9c7e,0x1e8ba44,0x13d49e6,0x193bd0a,0x1355202, + 0x1c9f493,0x06a0ef5,0x08f5ed7,0x08447ad,0x0a3acc4,0x1508fc4, + 0x0b5e269,0x058c114,0x0fb9df8,0x0b6032b,0x038eefd,0x01cf3b7, + 0x068fa30,0x02b5793,0x1a879cf,0x02f5c72,0x052f32b } }, + /* 52 */ + { { 0x114f71a,0x09260f3,0x14655bd,0x0535bb0,0x01be126,0x056df1e, + 0x0276197,0x0935b23,0x05a0fb6,0x045fae4,0x064b676,0x152443a, + 0x0f9efa6,0x17b925b,0x1fa0e25,0x02339c7,0x024b250,0x0761fd7, + 0x0b834f0,0x15f3ec5,0x024d4b6,0x05eb0cb,0x03f3ae8,0x1b6dc75, + 0x1092b2f,0x094bee1,0x18c98f3,0x123b46e,0x1c43bdc,0x1b0f7ca, + 0x164c301,0x19bd689,0x1136400,0x0698ec4,0x1a110f0,0x1ffafb9, + 0x1871899,0x1f61d8c,0x16305e3,0x051dfbe,0x079e14d }, + { 0x1b40c55,0x1111acd,0x090b8e0,0x1a1da0f,0x0a27202,0x1c60fa0, + 0x106a520,0x11c91cd,0x1d864a7,0x1af9253,0x115724a,0x081418d, + 0x087e7f1,0x07096a8,0x0b0412b,0x03c21cc,0x07ec11b,0x0cd850d, + 0x1eecf75,0x144ebf5,0x0b30fd8,0x1f4d1db,0x17fcd53,0x0c05403, + 0x05d9e46,0x0fbad08,0x164eed9,0x1a6e369,0x02fdeb3,0x1f8587c, + 0x1176972,0x1bc8d0a,0x001229b,0x0a8bf23,0x02e71cf,0x04a0bc2, + 0x072ff49,0x07d2a0b,0x1b389df,0x11532ac,0x00d8ec2 } }, + /* 53 */ + { { 0x1eee995,0x07b9f65,0x0030053,0x19a923d,0x12eb88b,0x15d2ea5, + 0x1b2b766,0x09ac2b4,0x19304c8,0x1bea319,0x00f268b,0x03a5156, + 0x14ba050,0x08dd5dc,0x1dc8f7a,0x0aee591,0x1775040,0x06442fc, + 0x1ff2c25,0x03a5678,0x071ab5e,0x0aefcb6,0x187b9e6,0x0c8933c, + 0x0daab34,0x0995c64,0x157d81e,0x1684bbb,0x043587d,0x0e50d89, + 0x101c094,0x13f8e86,0x0d7d3be,0x1564493,0x0c43240,0x1f182f2, + 0x0559a74,0x09160aa,0x12bf1c9,0x04f86e6,0x086001e }, + { 0x1693947,0x005d2f3,0x18ac4ec,0x1c02580,0x0478641,0x0a48543, + 0x0e383a1,0x0bdc348,0x1d9574d,0x0b9eddf,0x0ee9854,0x171937a, + 0x159532e,0x0f9f503,0x106f2e1,0x125723e,0x0478cbb,0x0560e61, + 0x1be406d,0x08c91c3,0x12ee0f3,0x0f6959d,0x1764a74,0x1aeb7f9, + 0x11eabc3,0x0692387,0x1c4e73d,0x19b78de,0x0249535,0x02a6f82, + 0x00f3619,0x08ff967,0x0079812,0x1c9860f,0x06d05f7,0x0173e41, + 0x114ebc0,0x12fe188,0x11b0508,0x19668f2,0x0020591 } }, + /* 54 */ + { { 0x15e0af4,0x01b9093,0x092f8c0,0x1fcf149,0x121141e,0x1aba42b, + 0x1f3db45,0x13cccd9,0x1168e65,0x1d0eb9b,0x010bb97,0x1ca81c5, + 0x16263e3,0x0a45eaf,0x1b30f52,0x020955b,0x03d246b,0x000cef0, + 0x0d0f606,0x13d207e,0x0d31f8a,0x052d860,0x12d5ee9,0x1c4ecbf, + 0x0c50651,0x1b3c123,0x1d9466f,0x018aea3,0x119a018,0x0100790, + 0x1d17c17,0x0f043a9,0x06487b8,0x01d033f,0x12a8987,0x044c5f2, + 0x1214605,0x07f244b,0x017bd5b,0x0bf43be,0x0511998 }, + { 0x18586c0,0x0a4bed8,0x0989606,0x0d8ddd5,0x004415d,0x06d1458, + 0x11ada5f,0x128f8d4,0x07c1945,0x10a4d94,0x0e941a6,0x13f49da, + 0x14b5636,0x01e4a65,0x04aa999,0x1ddc4e1,0x13aa9e9,0x0aade73, + 0x1e24d42,0x1650e0e,0x132634b,0x180375a,0x02be57e,0x071e90b, + 0x1032396,0x1fc43e6,0x016e9d6,0x126ec4d,0x02d5812,0x179ecea, + 0x137ccb5,0x0cb8dac,0x0cad574,0x0f6a0d2,0x03eecb3,0x0f30bea, + 0x1006a06,0x1a67074,0x1fe6b3c,0x0cab14a,0x059eaf2 } }, + /* 55 */ + { { 0x0c3876f,0x03f7db7,0x1921ed0,0x07e1e90,0x180c612,0x04981cb, + 0x15bfefe,0x1605576,0x045a91a,0x0c97550,0x046e0a5,0x09aef10, + 0x09ce5b8,0x0fcf9fe,0x09c68d0,0x1c2770d,0x186f0e7,0x060bfee, + 0x1568220,0x1b052ec,0x066688e,0x1a40eaf,0x1d75b71,0x02e2f2e, + 0x09df61d,0x10ff7fe,0x178fde7,0x0d5a991,0x06192e3,0x18be902, + 0x18b6c54,0x04e9fb4,0x0c9fa7a,0x0cc8a3c,0x093e0b7,0x1809d92, + 0x1a64971,0x0e8f1c1,0x0efec16,0x1d44c41,0x03b4450 }, + { 0x176dcdb,0x1d4aae3,0x091cf6d,0x1903917,0x15c4a57,0x0bb07d9, + 0x1400d41,0x0a75c50,0x1b3aec3,0x1f40348,0x05ef978,0x0b7c8e2, + 0x0138033,0x02b667b,0x111f8e8,0x0f22dc3,0x1eb3397,0x0929e7e, + 0x172dfb8,0x19bf75e,0x17043de,0x07be7a5,0x1cf25e5,0x1f028c5, + 0x1680c9f,0x14f9200,0x06f8f6a,0x1c881c2,0x191d8a4,0x01bbb4f, + 0x1771741,0x196bd38,0x106c7a8,0x1e926a0,0x0684ced,0x0432321, + 0x1764b4a,0x09e41c1,0x0d853a2,0x0198853,0x04a7fe3 } }, + /* 56 */ + { { 0x055c7c5,0x19d3812,0x1d539e3,0x10e02ae,0x1b7636e,0x1193162, + 0x11491d8,0x18fe658,0x01bc780,0x04c588f,0x1b61dcb,0x1d5922b, + 0x14d48ea,0x0cc932f,0x0134f00,0x0401f76,0x19bcfa5,0x035a958, + 0x0fa8ffa,0x1413032,0x0059c46,0x1edd3ac,0x160b1cc,0x12d5599, + 0x0bbd618,0x0a8e992,0x133a3b3,0x181345f,0x1c44b3a,0x0c7e817, + 0x12d4a64,0x15542f0,0x0c45e4a,0x1042e78,0x0d03f88,0x026ac4c, + 0x050c7d6,0x05db3b6,0x1ac8d4f,0x146ca24,0x083fa1e }, + { 0x0ccc646,0x0436d08,0x07a582b,0x1ef608a,0x0ce0637,0x0443081, + 0x1d8c228,0x1057779,0x1203499,0x1e0c80c,0x0f36808,0x0739f81, + 0x1d707fc,0x0dea7eb,0x1347c54,0x07776fe,0x0744471,0x06b5327, + 0x16b2798,0x1b8ced8,0x116957b,0x019bdb0,0x115b14c,0x1e8143a, + 0x11396dc,0x163e9a2,0x15265f4,0x07dbd84,0x04a739f,0x14d2616, + 0x1894d2b,0x0d4d5a5,0x001397e,0x0afc08a,0x15348fa,0x1e40ed3, + 0x1e98fab,0x1003e36,0x147833b,0x0f32638,0x0614097 } }, + /* 57 */ + { { 0x1156623,0x1996d8a,0x1f08f76,0x1956f4c,0x08137fb,0x0cf1e13, + 0x07d41bc,0x0c24c02,0x089924c,0x010c581,0x013070d,0x161f8d0, + 0x07492a0,0x17d5735,0x16f9c1a,0x17cc3ac,0x03e0d01,0x09d89e9, + 0x01fd31a,0x08b68ff,0x1aa3445,0x11026e0,0x15088db,0x0a2c3d9, + 0x1261d3c,0x003b09a,0x0ef622f,0x1d68d4c,0x19d7201,0x0c1b0ac, + 0x1cde31b,0x0d375e1,0x0955fe1,0x194107b,0x0f585c1,0x148cfdd, + 0x1e3a340,0x0dc5151,0x17e20bc,0x0ec5a16,0x0636dac }, + { 0x0c80af3,0x006dcda,0x0aae50a,0x029c712,0x1a189cd,0x03beee4, + 0x00b8345,0x09e4dce,0x068f9f1,0x08d771c,0x0a82cba,0x0c75017, + 0x092864f,0x05b8a51,0x1607dce,0x0f96d59,0x070c5fe,0x09870dc, + 0x0420dff,0x1d43876,0x089f883,0x09b5902,0x0b689e5,0x145b4be, + 0x12a6858,0x10a1d75,0x080ea3e,0x046617e,0x10b1c4e,0x045aee3, + 0x1d2d712,0x0532cf1,0x078c4d9,0x1b3ae05,0x0260977,0x104677a, + 0x1b67d36,0x1ae03b3,0x1bcfcde,0x1fc9a17,0x02f6dbd } }, + /* 58 */ + { { 0x04da7c7,0x0397e97,0x04c8be1,0x035ccef,0x108cfc9,0x0134713, + 0x1c228f7,0x0486c95,0x0799a24,0x1886ff0,0x162ffc3,0x1ab0e3a, + 0x06ef912,0x0c44b17,0x1cd77f2,0x1d414d7,0x1a95f47,0x0945cb7, + 0x0b4c230,0x14f3d55,0x1bba734,0x1bcfa1b,0x055cc0c,0x1ea9eeb, + 0x0bd8e6c,0x1760016,0x1f9d8cb,0x0ec0db9,0x1931044,0x0f65a98, + 0x075012d,0x0159ee5,0x0e0897c,0x0f8ef05,0x0e18ef7,0x1112c51, + 0x187d744,0x168aa77,0x1753bb3,0x12e8b1a,0x05cb6e1 }, + { 0x08c75ed,0x178cb80,0x0be2633,0x1deddd5,0x1cf49d3,0x1af4b6b, + 0x0780861,0x1143adf,0x0dd9b0d,0x076167f,0x1db6abf,0x19fd72a, + 0x1838a61,0x1b53edd,0x000fce4,0x029e820,0x06823b8,0x1d9be1c, + 0x0038c54,0x0cdb977,0x07a89fb,0x1d02cc2,0x079f8ba,0x14e4ee1, + 0x063fd35,0x1685276,0x07f2783,0x023e7b2,0x15baa43,0x004a6a8, + 0x18cf077,0x14119a9,0x1a06ebc,0x0f7553a,0x08e0bb5,0x1f56c2e, + 0x01f52c1,0x015dd87,0x15b94ba,0x060a2eb,0x02149d6 } }, + /* 59 */ + { { 0x19311f6,0x14737af,0x1e17b86,0x1f75783,0x097e3c9,0x0a104d6, + 0x114bad2,0x1c29f4f,0x019774f,0x0617a8e,0x16113c1,0x02450aa, + 0x135cefd,0x1ac39d5,0x0e18a8e,0x033f96a,0x1d6cbed,0x13b477e, + 0x19611a6,0x0248f3d,0x009ccdc,0x189ec06,0x0448df8,0x0898518, + 0x0a290c0,0x143eeba,0x0af51f8,0x1dcca2f,0x0ffeef9,0x0914568, + 0x07f0908,0x1031a50,0x073088f,0x006f0a1,0x12f10fb,0x07d78e8, + 0x1415bd7,0x137667d,0x109b16c,0x0a1960f,0x014e2f3 }, + { 0x016946b,0x0950821,0x04b5523,0x0ef497b,0x0e801f0,0x14a8b03, + 0x1428d0d,0x192b32d,0x163a197,0x18dae17,0x1ddf243,0x189e0c3, + 0x0279da3,0x09ffbd9,0x07358d2,0x0247e38,0x050a234,0x02f30db, + 0x0a100cf,0x16698be,0x0214826,0x146179a,0x1c62e43,0x100dd8a, + 0x15620ae,0x0da52f9,0x178c92a,0x05f5c68,0x13cb51a,0x1caf45a, + 0x1e2302e,0x1f32cae,0x14f6ac2,0x0f79964,0x01f5ae7,0x0e0fd8c, + 0x10ed8f2,0x1f8edd6,0x0793d8e,0x005b96c,0x058537e } }, + /* 60 */ + { { 0x0f80ba2,0x0583232,0x116c7d9,0x0e0ab34,0x08e055e,0x1a5b1a7, + 0x0acd3c7,0x105864c,0x1de8c84,0x1a7beaf,0x11e02bb,0x1d41861, + 0x139d55d,0x07d0f34,0x102bee7,0x186962e,0x0667460,0x1167f35, + 0x061f07b,0x12b2822,0x0d94f66,0x1bafcba,0x04e0bc9,0x08a93d6, + 0x0ace400,0x0810e50,0x1eeaf7b,0x1048967,0x1653eaf,0x0683271, + 0x00f0dbd,0x18ab8bf,0x0b9f0dc,0x1e74875,0x13beb3a,0x0bb2773, + 0x1906142,0x12c7390,0x05c3459,0x0bf05af,0x0485783 }, + { 0x0576210,0x092de69,0x110f735,0x0faa36a,0x1f378aa,0x0c1cca4, + 0x0fc5c6f,0x043fd2f,0x1f38ac6,0x18687b1,0x1023324,0x182f030, + 0x16af8f2,0x1307a9f,0x04b21f8,0x0ebc84d,0x007db0a,0x187722a, + 0x1f6c6cd,0x08f5cbf,0x044b0ec,0x0e3d535,0x1da44a7,0x0816eba, + 0x132b22e,0x1bbdb7c,0x0257bce,0x00cec9a,0x1c63e8e,0x03fab45, + 0x100a3f5,0x1380029,0x1810494,0x0aec768,0x0ff75e6,0x1f21c5a, + 0x0c2a85a,0x1cd02eb,0x0c4a3ac,0x17b443e,0x06c0277 } }, + /* 61 */ + { { 0x109e7ef,0x1b8435a,0x1e47906,0x167aff3,0x0842ec7,0x135c45c, + 0x17e5154,0x1579a50,0x0051dd0,0x1227032,0x1c73adb,0x1820ee9, + 0x1b90198,0x091f330,0x12afa60,0x08fb2dd,0x13632f6,0x1224088, + 0x1b14abb,0x10568a4,0x09d51dd,0x1fc9cee,0x1594241,0x1a8ab7f, + 0x0eef2fc,0x0be5eaf,0x1634b97,0x102b49b,0x1c9f2a7,0x1649445, + 0x0896b53,0x0af4766,0x0f10d0b,0x0e5ede3,0x079c82e,0x11d1a18, + 0x1b774ee,0x05838d4,0x13e3d68,0x135e45f,0x03067bc }, + { 0x1ca9326,0x0c4f95b,0x1d8f839,0x1b62449,0x17a106f,0x1d2bde8, + 0x11485d1,0x05d646a,0x162b088,0x10a4c16,0x07ff3c9,0x0a88872, + 0x0d7f3af,0x1427220,0x0a8cdee,0x160e235,0x1b0941b,0x014751b, + 0x1929fd5,0x0fb9685,0x15fba95,0x160d356,0x19ead98,0x186d441, + 0x1e381f7,0x1b5e89a,0x126ea82,0x05cf301,0x04671f4,0x01864a7, + 0x18d08dc,0x1161245,0x0cc63ff,0x12c4f92,0x09e5116,0x19a21aa, + 0x0870ff6,0x0ce98b5,0x10656ee,0x195532d,0x0390c83 } }, + /* 62 */ + { { 0x1c4a73f,0x1fd417f,0x0c0d434,0x0a77aa6,0x0665d63,0x05dbbe9, + 0x1be2899,0x1090140,0x022d73d,0x0e02537,0x0ee2aa0,0x1fea064, + 0x1a2409c,0x062626a,0x173885e,0x1383263,0x00e0c0f,0x01ba554, + 0x0061aee,0x0b470e0,0x087f0b2,0x085578a,0x142dde8,0x0931bc3, + 0x19ad5ab,0x08b0af9,0x186a830,0x05c65b4,0x025ce89,0x1edecb7, + 0x1448a38,0x0bd0c8d,0x17c88dc,0x18e345a,0x059099e,0x0ace562, + 0x000bdec,0x06c03fb,0x15ce974,0x0fa447c,0x03ea400 }, + { 0x195d0a3,0x0f5e852,0x0ed35db,0x175fe16,0x06bd76c,0x0dedcbd, + 0x0553e6c,0x0e37e58,0x04c714c,0x158cd5a,0x0bd98d8,0x0772443, + 0x16c9bf3,0x064a0f7,0x161f126,0x01eda47,0x0c3d79f,0x092ac02, + 0x09eb2f0,0x14200a5,0x08af6f1,0x0caa829,0x176ade7,0x1a2c426, + 0x1a6f0c8,0x014febb,0x1779784,0x00a116d,0x1da12b4,0x00797ca, + 0x087656b,0x0eb1517,0x060af71,0x0647dc4,0x120dc58,0x0816329, + 0x0e004d3,0x0736406,0x0aa8290,0x02ed629,0x009f82a } }, + /* 63 */ + { { 0x01366dc,0x1f2c461,0x0be582a,0x1f5eebb,0x129c0a4,0x1c9f6a3, + 0x07f66b2,0x0e0e0a0,0x087a16d,0x0bf3a27,0x1cd86ee,0x14f531c, + 0x13a42e0,0x145aa67,0x136bfc8,0x120f035,0x0bbb7bd,0x1f843e6, + 0x18c9439,0x1e7306c,0x1c09da6,0x175d783,0x19b5a4f,0x175e2ae, + 0x0f4c38c,0x0e83cdd,0x1f7f2a6,0x15309c0,0x0d8dab5,0x1923f93, + 0x1e6ad34,0x0fd746d,0x10be701,0x0e90b26,0x19943a3,0x066f773, + 0x131c4f0,0x1527122,0x16169ca,0x1096ea7,0x077d1e9 }, + { 0x0e62367,0x1991cec,0x13c764d,0x1773041,0x1361848,0x0e4be21, + 0x18d116a,0x1f8018f,0x014f960,0x10764d7,0x11d2d66,0x019ee80, + 0x15cf41f,0x167032e,0x1bb7a3f,0x10c214b,0x04e9e80,0x0d8ef2d, + 0x1833dd7,0x0895c95,0x0d0b17c,0x11b58a4,0x0be958c,0x13fe5b8, + 0x0740fd2,0x097327d,0x0a232c8,0x0c0bd71,0x063016c,0x18d6b54, + 0x05fcb1d,0x0c0f698,0x16112e7,0x04bc2b6,0x101d035,0x0bfd21d, + 0x0256e0e,0x0df0c5f,0x0b6c166,0x1d994a9,0x04e6eab } }, + /* 64 */ + { { 0x199cfe6,0x191e9fd,0x05e2540,0x0d92668,0x1b09bc2,0x1efdb7b, + 0x07905f2,0x0c0c822,0x089a757,0x08a0ba2,0x0672c24,0x1bf2212, + 0x0f4c633,0x1cb5fe9,0x17f1f1c,0x0c5b6e2,0x1128cab,0x04650ca, + 0x16e06ab,0x0e48e69,0x054a306,0x15da626,0x199e891,0x0452c8d, + 0x0a0fabf,0x0b86bbf,0x07e96d7,0x17da2be,0x1192f35,0x16d2e17, + 0x0b695a1,0x0fecd21,0x0cac72a,0x085beef,0x0a8b2a9,0x1e1895e, + 0x0049ad2,0x0318e0b,0x1c15bd1,0x12c09d9,0x0325d27 }, + { 0x048c144,0x0fdaaa4,0x1ccbb84,0x0b6d4f5,0x0e06292,0x0f07cd2, + 0x1a384da,0x03c24b6,0x0ca53b2,0x0cded73,0x03a86eb,0x00b85d3, + 0x15f50d6,0x0f97d1c,0x0e7854e,0x065eb7b,0x12de915,0x1a2b871, + 0x1a89435,0x0d315c8,0x1145810,0x1656cec,0x1ff6551,0x1d2f4bc, + 0x0772111,0x174d5fb,0x14927e0,0x1453efa,0x11df63c,0x1cd4cc2, + 0x196a714,0x0e3a1c7,0x184d54b,0x095ab7e,0x1670107,0x15a3c08, + 0x1d80096,0x19f5b77,0x1e74f3a,0x08dc654,0x019d485 } }, + /* 65 */ + { { 0x140f5e5,0x0f747da,0x145ff86,0x1e09cd1,0x06d2a52,0x1ee438c, + 0x036c2b6,0x191a464,0x0d03a7f,0x01d6ad4,0x12e45aa,0x078e117, + 0x0054bf8,0x1728f42,0x084cfa8,0x1bbbe12,0x024cb52,0x1de71c2, + 0x0418d60,0x0f7c806,0x1176d5c,0x0fa2c71,0x107aee7,0x09b577f, + 0x19639bc,0x0d457d8,0x13015c9,0x0c6a1fc,0x01cd243,0x031a427, + 0x17ab128,0x1828b71,0x1f73154,0x0191bd6,0x167acd2,0x00154db, + 0x0bff272,0x1a2e1ee,0x14ec28c,0x0d969c8,0x01b3ace }, + { 0x0a8bdc5,0x1f2f4c8,0x02240d0,0x1ac60d4,0x0203bf9,0x0429075, + 0x068d639,0x00d3091,0x0de7d1d,0x08bef5f,0x0574fef,0x0daebef, + 0x1f8fafa,0x1c3d851,0x13ad8c0,0x1d5f549,0x132ffdd,0x1700b35, + 0x19d9380,0x1c40a8f,0x1304a2f,0x127438f,0x156ae60,0x05d88bc, + 0x136bb95,0x065515e,0x12a4348,0x1698290,0x1cfb537,0x19c3bad, + 0x1954c67,0x0d30589,0x0238a4a,0x1490e9a,0x071e840,0x1d4576c, + 0x1b3ab17,0x030db26,0x0285078,0x07c325e,0x0538ec3 } }, + /* 66 */ + { { 0x19b56cf,0x04b7f50,0x0b3464d,0x08f7733,0x063d77f,0x085440b, + 0x0bea15f,0x1fb1e09,0x0082835,0x0769ed1,0x0b3b1f3,0x15dabb0, + 0x057e21f,0x1c004e4,0x05d6e67,0x1460edc,0x11b2d05,0x16ce371, + 0x0521f60,0x091a950,0x0655969,0x196a37b,0x01baf4f,0x0799893, + 0x11aa877,0x0534342,0x0a2c590,0x1c441e4,0x020b753,0x11d420d, + 0x1be7c1b,0x1215814,0x0fffe5e,0x159fd96,0x076a3af,0x13eb536, + 0x0e08e2c,0x03eccbb,0x1d00496,0x13007d3,0x06fd602 }, + { 0x0b7516a,0x04fc6c7,0x02ad51c,0x097b8b3,0x03058a7,0x1400e74, + 0x176621f,0x12da469,0x0d17b8a,0x087cec8,0x03daaff,0x093edd2, + 0x1baa1e5,0x0d3f6aa,0x05bfe01,0x0983249,0x17a6c25,0x086cfb2, + 0x025895d,0x1d49397,0x07de3cd,0x1816ff9,0x0da168f,0x1178097, + 0x0e7fddb,0x1581e28,0x1e61c8d,0x009fe1f,0x0d50559,0x0c7edd8, + 0x141250a,0x1c297d1,0x0b3386d,0x0986b1a,0x1a71f0f,0x12f5a69, + 0x0159fdd,0x15995ef,0x197007c,0x0798ec3,0x084cfa2 } }, + /* 67 */ + { { 0x199b964,0x008f5c5,0x111c4ef,0x14b1c5f,0x0e280c0,0x04d2a5c, + 0x0f12753,0x1f50e1f,0x0bf6e20,0x1d19a51,0x0233e8d,0x1a1baf9, + 0x1aee583,0x17a578e,0x180a6a3,0x1f14c0b,0x0340c2e,0x136aaf1, + 0x027a6d8,0x0dfbfc4,0x080f61b,0x135dc70,0x0ec76b4,0x125f834, + 0x1c16293,0x1a72d6d,0x182ab8f,0x05581fc,0x1f4d5b0,0x000d615, + 0x14a3666,0x18505fd,0x133f93f,0x0d99f91,0x0432d4b,0x0e2db96, + 0x055752e,0x1c87c26,0x0363827,0x0a39094,0x0287d4c }, + { 0x09867da,0x0c10087,0x13697e9,0x06350e9,0x014589b,0x0f71173, + 0x09f17ef,0x15000bc,0x1e612bd,0x1abff7a,0x18d7e78,0x1dbe5a6, + 0x064e0db,0x17892d4,0x0f9c391,0x145cac5,0x0840d94,0x0d04dcc, + 0x02d7974,0x13342a5,0x08b57eb,0x173a881,0x086e505,0x0da5988, + 0x17fd7e0,0x0228d89,0x1ffa826,0x1f43ea2,0x0ecbd76,0x14b37fe, + 0x0f8ee87,0x1065e8a,0x0c89a4a,0x147d0ea,0x0abfb29,0x060f63c, + 0x0bd395a,0x1da229a,0x0784f43,0x1b9b1df,0x00132a3 } }, + /* 68 */ + { { 0x16374c2,0x03bc2ab,0x010394f,0x0308e4e,0x060526d,0x0650227, + 0x1b7208a,0x027140c,0x0f1ce13,0x1f0e0d9,0x0c31747,0x10659bd, + 0x0f2aeec,0x0e5fc13,0x1659a66,0x14b134e,0x081de77,0x0668c47, + 0x0634495,0x1c1fc02,0x186ae5c,0x0203c85,0x0850aa6,0x158519d, + 0x1043f39,0x0027147,0x021f796,0x1ddf052,0x19a8c54,0x0d997b1, + 0x13e0f0c,0x0b10ef2,0x10454a7,0x0d9c8eb,0x154062c,0x0b94c6b, + 0x11d9c79,0x1f503b1,0x0a8973b,0x0ed6df1,0x013cbee }, + { 0x13f34f3,0x15f07c6,0x1f8de72,0x1946c2f,0x1da9c31,0x0a1350d, + 0x1b88f76,0x00964db,0x1f29c91,0x0eecb13,0x1b34efa,0x02d3c58, + 0x16033eb,0x1e5d10c,0x1cfd24b,0x1907914,0x00bb858,0x1c971bf, + 0x0ecfeed,0x05594c4,0x00a2e4f,0x0f325f0,0x00407ec,0x11ec891, + 0x1826a94,0x073c8d3,0x1241c98,0x0280cf6,0x0bb8354,0x1528718, + 0x1bbddd2,0x1933380,0x122ca80,0x04288fc,0x16e42e8,0x00d70c6, + 0x05fa04f,0x09b5ae1,0x0259efe,0x1b5c05d,0x04e0a1a } }, + /* 69 */ + { { 0x1a29c4d,0x1333845,0x0250032,0x1c45310,0x008240c,0x0ed3a96, + 0x1299c5b,0x068438b,0x1abbbfa,0x04e0722,0x0a2dc9a,0x0bfa7da, + 0x141d754,0x0be2b55,0x0884663,0x13acabe,0x1743875,0x0a59ec7, + 0x1f942e2,0x121bf71,0x1a16934,0x0bf4075,0x0d907d7,0x1596a6f, + 0x1a5eb79,0x12f3d86,0x1c30757,0x16d6292,0x1a429aa,0x1346d2e, + 0x0948ce3,0x05eda5e,0x010c437,0x079d3f0,0x1b4994c,0x1844de2, + 0x0bef08b,0x187bdb6,0x12667be,0x1b33f33,0x0733e30 }, + { 0x02a38f9,0x10ac152,0x1403b3f,0x1c8e616,0x0ec2d58,0x0bb5965, + 0x1ca9f7a,0x1765dc5,0x1a969c1,0x029ceda,0x136d2bc,0x02d1f9d, + 0x0231954,0x13d4748,0x1dcd22b,0x0a83fe5,0x1cc3121,0x10eac6b, + 0x080ab94,0x0b6eb84,0x15a75d2,0x0d7a041,0x17aa659,0x1369c8d, + 0x16a4152,0x0cd9ff5,0x1ef49eb,0x192ff6d,0x1f900b5,0x0a60130, + 0x07b61d5,0x009ab63,0x03031d9,0x0cdce5a,0x06e32c8,0x1e67abd, + 0x1ee00bc,0x01ea491,0x17031e9,0x0736f34,0x056facb } }, + /* 70 */ + { { 0x1018bfa,0x0b2d151,0x0610064,0x093ff5b,0x100c6b2,0x1a0d4d8, + 0x0c7d954,0x19377e3,0x125dc4c,0x15e8ecb,0x1ff9839,0x1daa57f, + 0x0b52850,0x1f2a84d,0x1a64b31,0x0b3e249,0x02e4ceb,0x07fb628, + 0x0a9f452,0x166ae63,0x0a462f0,0x0ef3f1d,0x1a43077,0x0285101, + 0x09f45d1,0x0eadd76,0x1996f97,0x0eb9fa4,0x0bce134,0x18a70ff, + 0x0c20eae,0x101285a,0x0ba4829,0x1416435,0x0d74a5f,0x1a3c364, + 0x10d8218,0x18e6df2,0x1b2eedd,0x0cdb29a,0x0885992 }, + { 0x15ccaf2,0x039480a,0x1cf8221,0x0ef8b6e,0x0679ebc,0x0e8476c, + 0x0b746cb,0x1b75116,0x087d475,0x1050c07,0x1340aa5,0x0d6ecd2, + 0x1680fdb,0x1f9fcf4,0x01d6324,0x06d887d,0x0fa4ad8,0x0ded1fb, + 0x0bece1f,0x018b026,0x000f940,0x0112a81,0x0969e15,0x0dd9e30, + 0x1c35177,0x0cd154b,0x1959b6d,0x07d7e8d,0x145eda0,0x1140132, + 0x1111d0e,0x19ee956,0x1169d84,0x19fb4f6,0x0c76232,0x0d75572, + 0x1825719,0x1749966,0x05c65c2,0x14d4181,0x0797224 } }, + /* 71 */ + { { 0x01f3567,0x091fc22,0x1c758ca,0x105c497,0x011c316,0x138fffe, + 0x1c9aedd,0x044972e,0x17a5e1a,0x00ba353,0x16d05d8,0x1d4075b, + 0x0653ddd,0x1facdc2,0x019e8f1,0x0ffeeaf,0x18756cd,0x0580954, + 0x066ea6a,0x0bfd93e,0x07481bd,0x117c183,0x1d40de6,0x1180ba2, + 0x1445dab,0x0153bb1,0x0de40fd,0x1afe883,0x03e46d5,0x13a6d48, + 0x1070045,0x15ba24d,0x11d3c4d,0x0ada00d,0x0ab1851,0x1d44ea5, + 0x155c356,0x1215342,0x014b136,0x02bb041,0x03ff09c }, + { 0x1cb7784,0x10de77c,0x0c15302,0x184845e,0x0ec539b,0x00a553d, + 0x1e7f431,0x188be81,0x0ffd42b,0x1d518b6,0x1638574,0x09865e6, + 0x0242f5a,0x0b713b4,0x0f7367b,0x1d9dc01,0x09ff8a5,0x0834fbc, + 0x17853d7,0x10031c0,0x0741807,0x09c5a06,0x0aecf92,0x02fee5a, + 0x08c1d79,0x0862ede,0x13315c5,0x01dd4cc,0x1a8920e,0x062d61f, + 0x192897b,0x038f2e2,0x021b0f5,0x168b59e,0x0bc98d2,0x151e134, + 0x18391d9,0x1987e2a,0x0b93239,0x00a9fbf,0x047ef18 } }, + /* 72 */ + { { 0x1a285e4,0x0f9e89e,0x0fd2659,0x147403c,0x1a7d4db,0x10a5685, + 0x104e984,0x0928e70,0x1223975,0x1dbea9a,0x0c2e4b4,0x1b9eb4e, + 0x1da53db,0x19968b2,0x0c364ac,0x0fde862,0x14182f9,0x1225142, + 0x137386d,0x0444388,0x0ec9bf6,0x0c3f150,0x0ee84e1,0x1f5b331, + 0x12c8dcb,0x02599f9,0x1ed7fb5,0x013cbe7,0x0217bb4,0x0632e33, + 0x0a570ca,0x1f9bee3,0x00db69f,0x103c458,0x0886e24,0x1744785, + 0x1ae6464,0x1594731,0x02187e2,0x13971bc,0x01a6b6e }, + { 0x0af77aa,0x1615b03,0x0196bdb,0x1b510fe,0x0e60f5c,0x04c62b1, + 0x050027d,0x0970fa4,0x1fcbaaf,0x1acadac,0x0ae1576,0x05424e3, + 0x0c0fb59,0x0a1a4d8,0x1384397,0x1193941,0x1d8887d,0x1ceb0c3, + 0x152f5b6,0x1d2bf22,0x099903e,0x09ae836,0x03f94c8,0x0d4c9a1, + 0x1bc30fb,0x1b07a53,0x159a932,0x1a455e1,0x17367c3,0x1677ae9, + 0x1545a54,0x132fb1c,0x10ea734,0x1996837,0x1c3dcc5,0x05688f8, + 0x09cb394,0x15981a5,0x03f4002,0x10050a2,0x079dd01 } }, + /* 73 */ + { { 0x0c7424e,0x0019d1d,0x1340138,0x10c1fb4,0x1b06b68,0x1bb97de, + 0x05d9af2,0x14846d5,0x1f297cd,0x0a54715,0x04f1b8a,0x170bb60, + 0x0d4b0aa,0x0391d1d,0x0abb262,0x094d67a,0x0cd13c8,0x1065719, + 0x03b05a7,0x111ebce,0x0262218,0x1ea1544,0x1ce58ce,0x0c1b370, + 0x0792e7b,0x1f0b456,0x0841da7,0x13e56e4,0x0bed348,0x07f3692, + 0x0aa3cff,0x147d649,0x15efb88,0x03835e9,0x08fd213,0x1bbbd9f, + 0x129ece0,0x008cd4c,0x150d9f3,0x08b1a80,0x087e5ad }, + { 0x11000a7,0x0d54ebe,0x00ceea6,0x195d047,0x0b94aff,0x1c1ee2c, + 0x058a37e,0x11b9045,0x1845a41,0x1acff08,0x05c150b,0x01f0ba8, + 0x01a8b97,0x195b8ac,0x0630995,0x1ba2f12,0x17dc0d1,0x07277a3, + 0x0beb5f0,0x1699e67,0x0a5bb50,0x1c80c38,0x086eba9,0x07450d0, + 0x087f9bb,0x0e6e3b8,0x1849296,0x10aea63,0x1432397,0x0137abf, + 0x12bb5d3,0x002c992,0x1f5ae25,0x05fba6a,0x1f8bc25,0x04cc116, + 0x1dceea3,0x06dadd7,0x10117d3,0x0333219,0x00b7125 } }, + /* 74 */ + { { 0x0d5c64d,0x08650c4,0x14d168a,0x134e924,0x0596d74,0x0074928, + 0x034f4a8,0x0d74096,0x0caf7b6,0x0166816,0x17b60c2,0x0185d9b, + 0x0e912b5,0x1f98b23,0x0f3a77b,0x1ff2b02,0x0c7c75f,0x0b15738, + 0x18a9185,0x10a5c0f,0x0fd16f6,0x0801c02,0x0c83f5f,0x031d1b2, + 0x0a4dd82,0x0ebd8d1,0x0ebf191,0x12314df,0x19fdbe4,0x07d0f46, + 0x1bbec20,0x088e16d,0x1d4d08a,0x1a77b99,0x01ddb65,0x05a5744, + 0x09dae5d,0x05cad3b,0x165b63b,0x074fad2,0x07a3f42 }, + { 0x0929387,0x096534d,0x1ffcd8b,0x0396383,0x0bdb758,0x08db65d, + 0x1b27df9,0x03fb125,0x03a4e13,0x146c319,0x01d587b,0x07e2b7b, + 0x124680e,0x0a73f39,0x0965f87,0x1fdfdc7,0x17c5581,0x19e6395, + 0x0a32b82,0x0eff159,0x14aff3e,0x0e2f17e,0x1f31f5f,0x06ab6f3, + 0x0455221,0x0bbee9d,0x0a8b01c,0x08d649e,0x09621f5,0x0996834, + 0x0f9056d,0x07ef02c,0x1e9af51,0x1f69095,0x0e6ccf5,0x064fac7, + 0x1680294,0x00cf794,0x1ebd2ac,0x0aa2c47,0x02da5fc } }, + /* 75 */ + { { 0x0a5c600,0x14e79e4,0x19f1890,0x047fc67,0x07a80c2,0x0beee5d, + 0x09d0029,0x0e93ffb,0x1925b0c,0x0d70ab6,0x003ac34,0x07f2d62, + 0x01097a4,0x17ca1e4,0x07a5173,0x19e482d,0x0e51128,0x1d0fb9a, + 0x067c04c,0x10f8948,0x0024043,0x0580822,0x1001e1a,0x06b39e5, + 0x16abf90,0x071f2a0,0x191e355,0x138edfd,0x02173ef,0x0ed3215, + 0x1059886,0x13fc602,0x1e03156,0x1923f30,0x138e4fb,0x0541feb, + 0x072b659,0x0bc95d0,0x1534e04,0x032e190,0x0855f02 }, + { 0x07314c4,0x1fdb642,0x05a987e,0x0bd68b7,0x1790615,0x1157d64, + 0x18519ae,0x102e205,0x1ab9497,0x0a8fcba,0x0313fbb,0x162f822, + 0x079d2f5,0x17fabb3,0x12339c2,0x089cef5,0x0216eb2,0x1f39b35, + 0x1471971,0x1779d8a,0x19dedd1,0x0570d42,0x0d49418,0x14fa5cf, + 0x081748b,0x0623d02,0x06ae3aa,0x03458a8,0x1ff078e,0x1261b7e, + 0x011b9e0,0x0290e96,0x1b49fc7,0x0fb99bc,0x0dfc1ac,0x1e455c6, + 0x0f8fe6c,0x1a90c93,0x01e5c70,0x19ea4ba,0x0292236 } }, + /* 76 */ + { { 0x18b29dc,0x06c053e,0x122b36e,0x0811d4c,0x117a202,0x095f48e, + 0x0b17aba,0x178fb62,0x0fda72f,0x19a3e8c,0x1831bc7,0x16813ce, + 0x1111374,0x0c71c6c,0x187a3c7,0x183e8e6,0x09d739a,0x13b8a5f, + 0x137d713,0x12e0396,0x0ae1c1f,0x0c37b96,0x1644e3b,0x1a30189, + 0x1e1f76a,0x1ce0e3f,0x1a78b6f,0x11830b7,0x10c44df,0x1934be3, + 0x17e0d76,0x161a2b6,0x197cfea,0x12a2f7c,0x1169879,0x1ca2028, + 0x05184e5,0x1834421,0x19ea85a,0x0b2ea43,0x07cfac3 }, + { 0x00bc53a,0x010b39e,0x0d9e046,0x06fcea2,0x04b5ede,0x12bd0c4, + 0x157f68d,0x1307944,0x0ba1fdd,0x0b55dfa,0x09df602,0x0d3f8bb, + 0x059ce83,0x1559a16,0x1ee6b9e,0x0b3e3e4,0x1d69720,0x083648d, + 0x053b3fa,0x1b56612,0x1f12ee0,0x1dc9fa9,0x0ed91fe,0x14afc1d, + 0x18a7aff,0x1039861,0x1e7cab5,0x02fa0dd,0x19dcc95,0x06c3ddc, + 0x08525ca,0x088c101,0x0034af1,0x0e0bed8,0x10fc4ae,0x0199021, + 0x172a22a,0x12f8a7b,0x00af5c8,0x0fe3bbf,0x06ce3dc } }, + /* 77 */ + { { 0x0397830,0x06c1ad2,0x0c1b01f,0x19e8e66,0x0dd9290,0x0c4f462, + 0x14ea0a6,0x0a5ba6b,0x1563d81,0x0c812ac,0x17986de,0x1223d0f, + 0x1cf278d,0x081271a,0x1cd031c,0x01cb338,0x0614a0d,0x096a222, + 0x0c989a8,0x0ec11fe,0x1aa963e,0x14e264d,0x189e8df,0x1fffa4a, + 0x0dc5176,0x0e6862b,0x033bca8,0x16dbdf9,0x0559d9c,0x06ab77e, + 0x04b2f30,0x008396d,0x05f3fc5,0x10f04f2,0x08e7945,0x199a0b8, + 0x1c3b559,0x198f74a,0x085b4a9,0x04547a1,0x0851511 }, + { 0x0ff19e2,0x0819ac3,0x180de0b,0x143b450,0x02c60da,0x1e3f76e, + 0x033f955,0x16165cf,0x01bc4e8,0x07b7cc2,0x0d719ea,0x16967be, + 0x0acc1f9,0x03b2231,0x184d80d,0x1c1612d,0x1977c7a,0x15fc885, + 0x050d655,0x0fe60aa,0x0ae527c,0x0e7b18f,0x10536c5,0x0d36699, + 0x161427e,0x1f9528e,0x057f04b,0x1d9050a,0x087162d,0x1709fdc, + 0x0f7f33a,0x1bc2911,0x0332ac1,0x1f3a66d,0x1388bb8,0x194406e, + 0x10ae069,0x1f50d0f,0x1b01165,0x1e4ef7b,0x08b1159 } }, + /* 78 */ + { { 0x1961d30,0x18d2217,0x123d2bd,0x10f58e4,0x1df968a,0x148366d, + 0x1e1f2c6,0x04ba65b,0x004abf9,0x0608713,0x0135300,0x0eb373e, + 0x1ab8711,0x09cb82e,0x1553982,0x0109201,0x033c9f8,0x0fbac3a, + 0x09e88dd,0x1575bcd,0x17ac2e9,0x1c4a560,0x159db51,0x005b338, + 0x0525bc2,0x19ea650,0x16afeb9,0x0b71795,0x05991b9,0x169c1a0, + 0x10c8dc7,0x08b1533,0x169e47a,0x0643315,0x0c60ade,0x18f9581, + 0x00232c7,0x1553cdf,0x1d165b3,0x066b11e,0x00bd864 }, + { 0x0734189,0x0d45a3f,0x085f7a8,0x119fcbf,0x12c5ac8,0x01bb322, + 0x1353845,0x0a08894,0x0af9e97,0x1291184,0x11acef0,0x0187a61, + 0x1778b1d,0x0636fa3,0x16b97c1,0x11bae5d,0x19a2ee8,0x029898e, + 0x1324f8d,0x0701dd5,0x0e8ec4e,0x16546d8,0x15266c6,0x0ba93af, + 0x08c167f,0x06bbb9a,0x1c555b3,0x12cc64a,0x11d13dc,0x0746130, + 0x1319738,0x16b45fb,0x095fe66,0x07d5096,0x00ca196,0x104cd31, + 0x11c32c9,0x03e8fa1,0x0641f6a,0x131f9b2,0x0466505 } }, + /* 79 */ + { { 0x14a5efa,0x009e635,0x099531b,0x163a0f6,0x0481989,0x0e34e06, + 0x19b3a2f,0x1a82172,0x02c2531,0x0a67d51,0x028403d,0x101195a, + 0x09cb5f1,0x172ed22,0x0d494e3,0x107997d,0x085bedd,0x0531200, + 0x189571e,0x05b59fa,0x058fe79,0x0310310,0x020dc64,0x02cb183, + 0x15e83ed,0x0a14b30,0x1df4a35,0x16a9364,0x175df34,0x13edc1d, + 0x10babc4,0x02ff772,0x160df6d,0x1e49827,0x076fdbd,0x1fa10c6, + 0x0018789,0x01c7cc3,0x0a0305f,0x0957352,0x00c4357 }, + { 0x120cad0,0x199260e,0x0229dba,0x1318c22,0x10decb0,0x0369b6c, + 0x14e71bc,0x12f4dd3,0x0bc0da1,0x06cbc5d,0x0b1739b,0x0380a0f, + 0x155948b,0x02a4bf5,0x151c593,0x029c657,0x00f4d59,0x0154e26, + 0x1d67c0f,0x18a08d4,0x047e772,0x0534d64,0x19f5cca,0x0916661, + 0x17d0c30,0x167546a,0x0103dee,0x0c0069c,0x1f1790e,0x08c9d42, + 0x0da08f6,0x0b90b2e,0x0e9b66c,0x1081153,0x11e99e7,0x0845945, + 0x09023fa,0x13d0ce0,0x156e403,0x1e24e4d,0x0324999 } }, + /* 80 */ + { { 0x0834915,0x1576b3e,0x193599f,0x1578bd6,0x1f77aa6,0x0b1008c, + 0x0f2d897,0x184e53d,0x0699fd9,0x1771279,0x153db02,0x10e8571, + 0x16e1eb5,0x0a64bb6,0x049c430,0x1d4cafe,0x135f6d9,0x0489c81, + 0x1ad4019,0x16e0920,0x0e4f668,0x07043b7,0x1965a68,0x13b26c0, + 0x1bf3f2f,0x1e77c80,0x06d2678,0x16350ca,0x1bcaaaf,0x09fdf96, + 0x0da02e5,0x12e760d,0x12cc566,0x1b63218,0x070cebc,0x0a6a69b, + 0x10ffd81,0x031d290,0x0ae4791,0x097e318,0x057ea2b }, + { 0x0a0f2f2,0x0f0b145,0x12a803d,0x0a1c8d7,0x0c7e75c,0x116216c, + 0x11e6a92,0x0052f56,0x014baa2,0x0798475,0x0f30bad,0x1a28d28, + 0x04a901b,0x176ac40,0x0497fbb,0x01ef976,0x0f99d18,0x0328164, + 0x1603187,0x0a72322,0x1ee3e53,0x1493880,0x1f89e01,0x14e4e2e, + 0x040a1fa,0x0a9bd05,0x0931d6c,0x05db9c0,0x0f1c223,0x1305a9c, + 0x0bb688d,0x17c60fa,0x1511e98,0x1705a26,0x19026eb,0x0e484ed, + 0x1ff1f30,0x061c93b,0x0d7269e,0x08dd4f2,0x060480b } }, + /* 81 */ + { { 0x072ece3,0x03eb31c,0x03e0c42,0x1b2ab6e,0x1f29be7,0x1caddc2, + 0x13f1e73,0x0436a16,0x1dbffa6,0x171dac6,0x0ae976e,0x0501c04, + 0x1c0e61d,0x00c0a24,0x0b9445d,0x0a90af1,0x040cf55,0x1058994, + 0x03382c3,0x1da36d7,0x1e3d800,0x0abc6ae,0x0d77ff7,0x14ad68e, + 0x0237469,0x173fbf2,0x0636442,0x0bc646d,0x13c7c7d,0x0950318, + 0x196dbfd,0x1525bd3,0x02fe20d,0x0885dad,0x1f4f448,0x0683668, + 0x00c16f2,0x082f6da,0x0233316,0x1a7351f,0x00774a0 }, + { 0x1b6c106,0x0c0d5f1,0x02dceb8,0x1f1bc2a,0x0ebe163,0x1aa41b2, + 0x0e0bdbc,0x02d9eeb,0x13ac7ac,0x1069031,0x1c8abea,0x0cd0522, + 0x135c680,0x08aa2aa,0x0507984,0x1c7eee7,0x038bf5d,0x10b893f, + 0x0bed076,0x1fbe063,0x066332c,0x08c3de4,0x11a24f2,0x0593933, + 0x06744a6,0x0a3ba82,0x1658b06,0x0d0cdc5,0x0cdf4c9,0x046f9bc, + 0x0c9227b,0x0680ff4,0x060709b,0x148689d,0x0565544,0x07a6fa4, + 0x1ab9227,0x11e981d,0x0052e58,0x0a84864,0x0081519 } }, + /* 82 */ + { { 0x17b2108,0x1b6c4fd,0x06abe48,0x195aebf,0x1ecc83c,0x10ed089, + 0x0ac56d3,0x0c5ef8e,0x10315c3,0x0957577,0x0bf8fd5,0x01dbe4e, + 0x0811e14,0x03c21f7,0x15e6fda,0x164b733,0x0fd1d9b,0x06735aa, + 0x0c6eb5d,0x161c42b,0x090db20,0x07adc26,0x1528085,0x14d9d92, + 0x1bf52fc,0x1b7a2cd,0x167937d,0x06c7891,0x0cf17ee,0x1c276b2, + 0x120c117,0x1ec55b4,0x002a167,0x06500c2,0x0fcda9d,0x1a593c3, + 0x1691c42,0x07cea0f,0x0e1d3a3,0x0f18589,0x05abf21 }, + { 0x1b3bccd,0x1cb35f9,0x12a91dd,0x017c7c1,0x0047e0f,0x1ea8218, + 0x00ece31,0x1f99707,0x1946fd5,0x1bf1dd7,0x103a1f9,0x0f0bd3d, + 0x0579baa,0x0450c69,0x0f155f3,0x1f9fdb0,0x1af25be,0x0cdcb72, + 0x031c6d8,0x0ba2bd3,0x0da14f0,0x0d3bf31,0x0207e64,0x1547042, + 0x0c781cb,0x1fd8e37,0x1795366,0x0a45ecb,0x0d14307,0x0ab9a27, + 0x16bd741,0x12b95fb,0x035b31f,0x07adf98,0x1d0d8de,0x128fccf, + 0x1270b9d,0x0fbe56a,0x1a9200a,0x10e9b22,0x015ad15 } }, + /* 83 */ + { { 0x0588ae4,0x1176755,0x08c8037,0x1146e34,0x152ebc5,0x1182222, + 0x0a4d1c4,0x05ba01d,0x1e4b183,0x1dfd33e,0x07a10eb,0x06836d1, + 0x0829216,0x10fa717,0x05aeef5,0x13b8a3f,0x08404c2,0x0caa103, + 0x08c5ff4,0x1c704e8,0x1162c7f,0x0331a41,0x18282bb,0x000309f, + 0x194d107,0x0c2fe15,0x0ff87ef,0x0e4332e,0x0743520,0x1558fd8, + 0x049922d,0x188dca7,0x1bbdaad,0x12b7f91,0x147c03e,0x0c1b71b, + 0x066725f,0x040af5c,0x0658c41,0x194a5d0,0x03f9c4c }, + { 0x0ce637e,0x1594b99,0x1377fcd,0x1beba4b,0x01a15f2,0x0156cbc, + 0x014b62c,0x1d2343a,0x0cfbab3,0x12f9dde,0x1badd4b,0x17aec29, + 0x1a60d2c,0x06ad3c9,0x124610f,0x04289a8,0x175cdba,0x1112167, + 0x02e65d9,0x0e0bcf1,0x0132a20,0x00763bf,0x19384b3,0x035360a, + 0x14df6b6,0x1ad58e0,0x11d2096,0x1fb2fe0,0x0312238,0x04109ed, + 0x0365581,0x09a618e,0x0486727,0x17734ef,0x1c54704,0x1b79571, + 0x068d893,0x031c5a3,0x15d2d77,0x1ac447e,0x06479da } }, + /* 84 */ + { { 0x05f2b26,0x02279d8,0x1db15a4,0x150173e,0x135a294,0x087b575, + 0x1f8a10a,0x0ef1073,0x1026a58,0x10e7d91,0x1fe70dd,0x0d6c5cb, + 0x1676892,0x0588e2b,0x19b3480,0x07dfd75,0x15672a0,0x16e42bb, + 0x06eb58e,0x1c0e95c,0x199c0ca,0x10eb84e,0x0ff9246,0x003b382, + 0x1ded665,0x1fbbb62,0x070cabb,0x1b4dd94,0x1683e81,0x0eaae2b, + 0x11d4212,0x1bf31b0,0x0392e9c,0x0d2b24f,0x00bd936,0x05f5af3, + 0x037b98b,0x01dedbd,0x0125fdf,0x129e10c,0x01fe09f }, + { 0x048cc63,0x1f5573b,0x1c51269,0x02cf9f4,0x13ea251,0x1fa2ac8, + 0x048f194,0x10df917,0x181a16e,0x0abb0cd,0x1919d36,0x0096790, + 0x1a0c7e8,0x0b0b2cc,0x0204d28,0x04651f9,0x1690a65,0x11b3754, + 0x0f240a7,0x0652c09,0x0d2b415,0x0a57155,0x1be7866,0x0217deb, + 0x08c527f,0x0304f15,0x1b19efe,0x07b96b0,0x0cc25d7,0x01fd422, + 0x14fd869,0x0e9d66c,0x14e7eea,0x007816b,0x1c1b749,0x09e66ac, + 0x1d83bcb,0x03b4a67,0x149abbb,0x10db6c4,0x04de957 } }, + /* 85 */ + { { 0x1eac2f7,0x1e98a9e,0x0a39219,0x156c3b3,0x0084778,0x1bd96ad, + 0x1be582a,0x0f3e76e,0x0cfdf4f,0x059802b,0x0e3d2c0,0x1c2a635, + 0x01d0701,0x0e3bce8,0x1e52356,0x0a6e20f,0x0bc8267,0x03e4ca7, + 0x02eb530,0x09a9dc9,0x1058110,0x1adfe4e,0x1e63382,0x13f5016, + 0x0898d30,0x157e3e5,0x16b2ccf,0x0489e44,0x0f31750,0x06fe2d9, + 0x0d3547a,0x149af7c,0x049ba6b,0x015a19f,0x131ef68,0x142ec1e, + 0x0435275,0x11b53f2,0x06030df,0x117cc6d,0x01c9441 }, + { 0x1dc1414,0x1098984,0x14dd0e8,0x1887926,0x060765f,0x0fbce70, + 0x081eb7d,0x194dfe6,0x085d4cf,0x18c58fd,0x0656adb,0x0e5cc7d, + 0x02f5c42,0x1415980,0x0682792,0x0fe2c24,0x11b9714,0x1415b2e, + 0x029ff89,0x0784184,0x0726499,0x0c7338b,0x067272e,0x1688141, + 0x0d673fe,0x1e2ad01,0x04946d2,0x1e7f53c,0x1338ea3,0x023a502, + 0x12dd76f,0x0f613ed,0x0b4044b,0x1a3049e,0x0862010,0x04cecfb, + 0x098ceac,0x028a110,0x0d6ea5e,0x1656aa4,0x0611bfb } }, + /* 86 */ + { { 0x00ad2a1,0x152af78,0x035ef6e,0x1c29452,0x09efa85,0x158b4a1, + 0x11da3a4,0x0607694,0x111ec81,0x1888de6,0x149ec99,0x0e05117, + 0x060e425,0x0cd01e0,0x033ca8f,0x11095e5,0x12df318,0x05dbe46, + 0x0eabac8,0x1428c5c,0x1d77e2e,0x0221dc2,0x0cd4d60,0x09dd37a, + 0x0448255,0x0c7c0f7,0x1b9aa86,0x165ddd3,0x0c5944e,0x1402613, + 0x1f1e96a,0x105562c,0x0ef2da5,0x110d2d0,0x11d80bf,0x1cb4556, + 0x1370298,0x0e59dc1,0x0aa345a,0x0881d67,0x086e6c5 }, + { 0x1793d9b,0x0199085,0x1b3bb78,0x023bb6b,0x179fade,0x0985b27, + 0x16a49a2,0x165ee7f,0x1fe4fd1,0x1556cbe,0x1372201,0x163b254, + 0x15073a5,0x1e4bb6b,0x1e32f62,0x04d8115,0x1b163ce,0x1305a55, + 0x12c7ec1,0x060153b,0x13d39c8,0x066d4ad,0x0cd6965,0x0fd590e, + 0x1d7d4b3,0x1558fcb,0x0883bbe,0x07a5d74,0x0828c8a,0x048379f, + 0x004c963,0x10b56ef,0x032616f,0x05b0be4,0x064a30a,0x1ae4b2e, + 0x1233b82,0x18cb5e1,0x049b735,0x17233f4,0x083867e } }, + /* 87 */ + { { 0x0474edb,0x1f39f11,0x06b9dd3,0x083509c,0x0a76639,0x16eb719, + 0x0a6b671,0x0ba4e06,0x114f8bf,0x062520a,0x19ee400,0x146fa44, + 0x0e3ce2e,0x08e927d,0x1d4c054,0x036f024,0x054263a,0x13e0a6c, + 0x0b82c81,0x1080363,0x09fc20c,0x0d840fa,0x1cca804,0x138dbf1, + 0x123fb95,0x0830f40,0x1200387,0x0651b8f,0x059a9aa,0x11bc121, + 0x0dd61da,0x16fded8,0x1ada8b5,0x0a64f91,0x0dbaa4f,0x1e047ed, + 0x1fb6389,0x1aa0a6f,0x0ce7a27,0x145cc51,0x04b26bb }, + { 0x1318454,0x18e5a2e,0x12db4c2,0x1fae86d,0x123b749,0x053a308, + 0x11c995a,0x03c6221,0x11c84fd,0x02ef091,0x00f5572,0x0dcc108, + 0x18a5f8d,0x0d8fd5f,0x16db84e,0x1b9c072,0x0c33cfe,0x07f36b4, + 0x12e4444,0x00703f2,0x0eb71d9,0x0096e63,0x1c2a3aa,0x1219457, + 0x004137e,0x02d2cf4,0x1f22897,0x1d6bf80,0x04663cb,0x129d2ec, + 0x1f00270,0x12216d4,0x0b15073,0x07c6a80,0x0931042,0x0b0c0fb, + 0x0b901e6,0x01ece1e,0x057180b,0x18a592c,0x04d697b } }, + /* 88 */ + { { 0x1a8fb40,0x18f7877,0x0273836,0x16b7473,0x09021c5,0x0e8cef9, + 0x1ec5602,0x1c351ad,0x14c1219,0x1bc3db9,0x1c1789a,0x02d029d, + 0x026417e,0x07cbcb7,0x04d0b6e,0x0843689,0x05ebf84,0x117c3c5, + 0x052914d,0x122dafd,0x1693e71,0x11d708c,0x06062ee,0x0d1009d, + 0x14be957,0x1c57633,0x13e1093,0x144c0e9,0x0ce6ab0,0x1dcea33, + 0x02f6f24,0x192400f,0x1f15a98,0x078d1d9,0x1434e1c,0x0f3a21f, + 0x04e785a,0x0920ecf,0x1360298,0x143cd91,0x076ca87 }, + { 0x02e48b7,0x1fdab70,0x07190d5,0x079813d,0x1bd14b1,0x034e787, + 0x090d490,0x153b6be,0x02c3b01,0x03c0b2e,0x15b6b7e,0x0f89cd2, + 0x08e549e,0x1deb05b,0x1fa54e2,0x18ca7e5,0x16b059d,0x1ca97c2, + 0x0ddffa6,0x0c044b6,0x08c4d3f,0x145ff48,0x1a831cc,0x11ebe5a, + 0x0a2d3bc,0x0286735,0x0c91094,0x0e42688,0x1b3ce5f,0x13351e9, + 0x0485f84,0x182ceea,0x1b5e43f,0x1c4a53a,0x0188dfe,0x0a2b24e, + 0x0be3e37,0x1303a99,0x0def854,0x18cdb47,0x027e7f2 } }, + /* 89 */ + { { 0x0a15883,0x1b2d6f3,0x0ccd8e3,0x18cd5fb,0x14a7e68,0x1896f2e, + 0x0daaf4f,0x020c40f,0x037b878,0x037fca8,0x13db4c7,0x1964c95, + 0x02c0d44,0x195f3c6,0x0eb1807,0x1301c2c,0x05a1636,0x18e31e6, + 0x1724d26,0x059fd12,0x12203e9,0x0c20f63,0x1dce383,0x0bf52c2, + 0x1d7642d,0x074b0b4,0x070f80a,0x154eed8,0x0d54092,0x0b2358b, + 0x1664f71,0x0e0dbe9,0x0b27fb5,0x035cbd0,0x05c33a7,0x013d322, + 0x13c85f4,0x07215f2,0x194a3aa,0x06f0648,0x002e964 }, + { 0x078ea1f,0x0056ed7,0x1a5a455,0x1af6ce1,0x11a1b74,0x0034132, + 0x19107dc,0x18ff326,0x07d7520,0x1cbeb75,0x184b863,0x1404d39, + 0x020faa6,0x1c9041a,0x042b2a1,0x0886c4b,0x0637561,0x1bd241c, + 0x0e05023,0x0c293de,0x140607c,0x026bc29,0x1ccefd6,0x1776dee, + 0x1b0109a,0x04d43b0,0x1fd4a28,0x09d6493,0x00ae3ce,0x0f6c170, + 0x1e821e0,0x042f1df,0x04c1b25,0x09d3f43,0x0a8a754,0x1f983cc, + 0x1919062,0x1c5ca70,0x149f7b6,0x1b49e2c,0x0739f53 } }, + /* 90 */ + { { 0x04adc5f,0x1a54449,0x15b5e97,0x0d5031e,0x15646c1,0x0afcaa4, + 0x044a5de,0x0001d89,0x1d19c54,0x1a43a9e,0x044ad0a,0x06d640b, + 0x0616fa2,0x143d24a,0x0f597cf,0x1a0ccd6,0x001045f,0x0538ba5, + 0x0a97850,0x0a06262,0x0623b63,0x0254b5c,0x09e712d,0x16007ab, + 0x19d659a,0x18d3d19,0x18e09bc,0x0e5e618,0x1090cdc,0x1c8637b, + 0x092d39c,0x120dd7c,0x1ac6c36,0x0282d2c,0x01b6ee9,0x14734fe, + 0x058c413,0x0cc8f0e,0x03a120e,0x1ff441c,0x0020c23 }, + { 0x1c74661,0x1256d57,0x0194483,0x064eff8,0x17bbcf6,0x0e73cc9, + 0x073dadb,0x1428209,0x17b161b,0x1c6b5a9,0x043ec96,0x086352c, + 0x0922218,0x0feef3b,0x07b2747,0x00c61bd,0x04d42d8,0x1e995fd, + 0x09137d2,0x0ae054c,0x0dfb388,0x16a2ac9,0x137b747,0x09c0371, + 0x1f45bfb,0x0d8070e,0x0a1b885,0x1e97bda,0x137e6a8,0x0a43b54, + 0x08e024d,0x10261ee,0x15278ba,0x010fc20,0x1a48e2a,0x158db88, + 0x1d8b4f8,0x03d88cf,0x073bc88,0x0a7f24d,0x076e7bf } }, + /* 91 */ + { { 0x1ebd187,0x1421413,0x16ed7c4,0x176cb55,0x0d3320a,0x12c34ac, + 0x1d969c8,0x1576084,0x18f0986,0x11f99fc,0x1fd40f6,0x0f4f5d7, + 0x0541180,0x012fb8d,0x11ddb2a,0x1e4964b,0x1edff7d,0x0606f3d, + 0x197c7ed,0x161e842,0x1ae3da8,0x1bb98f9,0x17cffdc,0x07c14a4, + 0x1d7e719,0x1232668,0x0edacee,0x1bf0954,0x1f37828,0x1c4bd50, + 0x11eea12,0x1cee675,0x07960cc,0x00d10b7,0x1aad426,0x1a9a8da, + 0x1cbb80e,0x009612b,0x1bc247b,0x04e572d,0x079e7ad }, + { 0x130caae,0x0b86e47,0x1bd0f36,0x0214dd7,0x05cabcf,0x0a30b6c, + 0x018fb1c,0x130c783,0x1519e3a,0x0286d85,0x0c4f587,0x12c6c99, + 0x09f39b8,0x112a3db,0x19f607c,0x16199be,0x1b9d67d,0x1b8abd5, + 0x025246d,0x144b751,0x00dcccc,0x1e3d13f,0x1da2481,0x1a86503, + 0x08fbe0f,0x0049a57,0x0d5c83b,0x0bb23ee,0x1d7beda,0x0c84e6f, + 0x0cacbd8,0x094073c,0x0c10232,0x0c7ee0f,0x197b6c3,0x1ba787a, + 0x0fe5005,0x048b642,0x1aa50cb,0x1589817,0x07f8c37 } }, + /* 92 */ + { { 0x1ac05e5,0x00f2a21,0x0094cfb,0x099b1a7,0x1a4a4da,0x1fcf15e, + 0x0302e22,0x1b90db1,0x0b53811,0x06b8ee8,0x0eae90d,0x01a5478, + 0x1e65504,0x1b0b08d,0x1102526,0x09f4057,0x06e279a,0x18e16a1, + 0x0c196b0,0x14b5447,0x0890535,0x17e2975,0x16aa28c,0x1bb5a45, + 0x1eca79f,0x137ad2e,0x14aacec,0x023e0bf,0x1cd81e9,0x13edf9b, + 0x03176b3,0x121a2d7,0x00e44e7,0x0c4a707,0x0bb793d,0x1e2bcd1, + 0x1c92a74,0x1024ccf,0x1f0bebf,0x1552e1c,0x01d7703 }, + { 0x10062a9,0x0640e9f,0x02eaa29,0x11b2d44,0x031eb2b,0x05e880f, + 0x0637e19,0x028cdbb,0x04413b6,0x102fac9,0x1557e2e,0x141bd34, + 0x1151a67,0x1725a96,0x10bc25c,0x1564759,0x0ec7184,0x1d5aed5, + 0x11fda46,0x11687cf,0x07f4ce0,0x05bb621,0x148394c,0x047d7b8, + 0x12069e4,0x0673e9a,0x00d37c5,0x16bc73d,0x0305ac6,0x194aa23, + 0x104f72f,0x1fc699b,0x02cb2e1,0x1ad7db4,0x1744447,0x13a9588, + 0x07f296f,0x17b1e6a,0x021c717,0x1d92784,0x00a2c40 } }, + /* 93 */ + { { 0x15747db,0x01c27d7,0x01ac26f,0x0d80d57,0x1bad608,0x1e0aa39, + 0x020ba79,0x17f480d,0x155977a,0x0a99368,0x077ac0b,0x140bb50, + 0x11063a9,0x0925b08,0x01b929d,0x1d72135,0x07a4ab2,0x10a017c, + 0x171802e,0x0e43a9a,0x1dbf7d0,0x14f944f,0x068bf66,0x1bcde0e, + 0x0e66dec,0x139faee,0x1f6ae7e,0x042e24e,0x074bab6,0x024fb62, + 0x0cdb4b7,0x0eddda0,0x0017e1f,0x012e9ee,0x170136a,0x0772e2e, + 0x14b05e4,0x14bf1ea,0x121f9b0,0x08cad93,0x02efb45 }, + { 0x121c064,0x0958045,0x0a7a91c,0x0494e0c,0x1186fe4,0x1a7857e, + 0x0cd026d,0x052c86b,0x17ec9e6,0x0b2d521,0x183421a,0x0ce7898, + 0x0adda14,0x1f982bd,0x19599c2,0x0dec016,0x0403ce8,0x13f82f4, + 0x1100685,0x00e7520,0x007ec05,0x1c14a73,0x05ac798,0x19ee08c, + 0x0325269,0x09d103c,0x0fa339f,0x1282283,0x17053d2,0x0c69bab, + 0x0374e2b,0x1954cc6,0x1a68fb3,0x021a86d,0x1fc7a54,0x17d97d5, + 0x1d2d760,0x08b36a8,0x047927d,0x19c8c51,0x0337532 } }, + /* 94 */ + { { 0x000bb9b,0x08c299d,0x1a14fc4,0x1c8becc,0x0d2ffba,0x1771269, + 0x06a1752,0x0dd35c2,0x1034185,0x05d0f0d,0x04d27c6,0x02f04e6, + 0x15a9ac8,0x0a2b8ad,0x0f7f529,0x1a5d582,0x03c5daa,0x1d2fba1, + 0x0d6dda9,0x090772a,0x1e9b30a,0x127fc39,0x04ba6b6,0x07420ab, + 0x02d8472,0x0700ab3,0x0e3b6b1,0x126a92f,0x18fa70b,0x020d1ce, + 0x07d86d9,0x081a2b1,0x141d756,0x02f850a,0x08dfc28,0x10c5328, + 0x0bb2890,0x05801a3,0x0cafff6,0x0bba99a,0x0192a2b }, + { 0x05ced07,0x1b3141b,0x147d8d5,0x160bbc3,0x029f32f,0x0053d50, + 0x0e6f2fd,0x08eda2f,0x09bb50a,0x18d9504,0x0989e06,0x1776f2b, + 0x1b9389a,0x19a7e0c,0x13fd83e,0x10e72a5,0x092387d,0x179d5ca, + 0x0483335,0x00a7ccd,0x14f0a8f,0x05b1d4d,0x0fbcb75,0x1d04252, + 0x0ede151,0x1d0cd58,0x0c20e2f,0x1f74181,0x1c11bea,0x13d64ff, + 0x1e0af56,0x12b9810,0x18bfd95,0x1786302,0x028fe30,0x14d0da9, + 0x1d9b31b,0x1d5d578,0x109a30c,0x1127781,0x0632e22 } }, + /* 95 */ + { { 0x1a1ccca,0x08e900a,0x0f0c721,0x18fca45,0x0efe290,0x155829a, + 0x0755463,0x02e16e8,0x1bc85e2,0x132b0cb,0x1e2ca6b,0x083c039, + 0x18ae131,0x134a423,0x0b2d64d,0x1b15c5c,0x10fc31b,0x075abdd, + 0x09939e2,0x1debad8,0x0d86dec,0x064e5cb,0x1bea15b,0x12307b4, + 0x1681327,0x0b516d8,0x00e0f5e,0x007e704,0x0c6fedf,0x0b7f8e8, + 0x06d6291,0x114d57b,0x1589805,0x0b78c92,0x0b160fe,0x0e673ea, + 0x1a7e9ea,0x16f6c7e,0x135173d,0x182ba39,0x068c3d9 }, + { 0x0b392b7,0x13132f3,0x14259f8,0x1eeebb2,0x0ec1d9b,0x128a7be, + 0x0f3535d,0x039c2d5,0x00de72e,0x037acd9,0x1ec0cf6,0x079a35b, + 0x0ca66e4,0x02f22be,0x0d10d00,0x1b545b6,0x1165681,0x0db3d3c, + 0x00451cc,0x1cf757e,0x0961c32,0x1769d8f,0x019bf85,0x07a4dcc, + 0x0298ef6,0x0b6c927,0x01506b7,0x17d41bb,0x02f9719,0x006fccc, + 0x0b3be54,0x18be0ed,0x0876e63,0x09cb5ae,0x0b96c8f,0x14abc25, + 0x0ec6747,0x17dd9b1,0x01a9427,0x1dc4665,0x08f2055 } }, + /* 96 */ + { { 0x02c1af0,0x15cf1dc,0x0991292,0x0fe595c,0x1c65e9e,0x0c3ea37, + 0x0b02980,0x0c69fd5,0x1e393b3,0x1e9f99a,0x0eb3389,0x1801033, + 0x119c9f7,0x1c55330,0x1d062d6,0x15d2a7e,0x157372a,0x0ffd4a2, + 0x16ce162,0x1af0091,0x1c1c937,0x0fb78fd,0x144321b,0x1e1419d, + 0x0bd89a2,0x0f5a457,0x08d9d0e,0x1cbabf4,0x17d2d8a,0x15059f8, + 0x05040e9,0x0823b31,0x033f68a,0x1b3d179,0x02cc862,0x0cffd9d, + 0x0319bf0,0x112a079,0x0c8b810,0x192681a,0x01292c8 }, + { 0x186463d,0x1aac381,0x05ffd7a,0x0406e3b,0x14bbc2b,0x00ce2d6, + 0x115c42e,0x082366c,0x0cf04ad,0x05da16b,0x0e7b043,0x18eccd2, + 0x075d819,0x100c23f,0x116b04e,0x065c90e,0x1021c72,0x027b825, + 0x12c15e0,0x1cb1415,0x02952c9,0x19dab0f,0x0548ee2,0x1f3746b, + 0x0df0079,0x11419c2,0x087aaa5,0x10463f8,0x0a2b907,0x02a7c57, + 0x18e8bab,0x061a384,0x075ed77,0x1c80040,0x1b57ecc,0x1559689, + 0x1011293,0x0a35617,0x05d9249,0x057d704,0x07c7876 } }, + /* 97 */ + { { 0x07902b6,0x1eb7d83,0x0602e3d,0x07a2e6b,0x12823a4,0x1a0eeed, + 0x1ec4965,0x0b80c59,0x14033f9,0x11c8d83,0x026e31b,0x0146d0b, + 0x123831d,0x0911487,0x11d3525,0x03e75c6,0x0d6222e,0x0a6d58a, + 0x0fc234e,0x01f9bca,0x08f58f0,0x17383f9,0x156645e,0x11cc0f8, + 0x0a0ba06,0x0120b35,0x1f5f87e,0x004e27c,0x0a328f6,0x0aa026b, + 0x0a9f095,0x131219a,0x12e3264,0x0590506,0x0513b28,0x19e440f, + 0x12f4e09,0x0c6e03a,0x1a07572,0x009b09b,0x0694035 }, + { 0x1407206,0x1d9b372,0x0a33e2d,0x1e1b11f,0x1ecf54c,0x1397378, + 0x19523dc,0x0d0dfdf,0x081ab44,0x12989b9,0x1d10235,0x1e1c9c8, + 0x1f52cb5,0x124839b,0x109ace9,0x1a0e33c,0x19b4980,0x192bb60, + 0x1c9cb2b,0x068c501,0x11c991f,0x07a3479,0x1e39829,0x1089b12, + 0x0a32990,0x015c3bb,0x12e5456,0x14aae01,0x11adbf8,0x19b28a5, + 0x1beac6b,0x1f7a687,0x0ebff92,0x00f9a11,0x0c06df6,0x0265f3f, + 0x1a6b30e,0x0287035,0x0551ab6,0x04f78bf,0x06da9e0 } }, + /* 98 */ + { { 0x09490ce,0x172612e,0x0e0487b,0x061bed0,0x096ec4a,0x149b475, + 0x01f8292,0x1e7cd8c,0x04bc262,0x0582495,0x10d3ff6,0x04208c1, + 0x0d0846a,0x146f99e,0x1fde990,0x0ec25ef,0x0442182,0x08862a8, + 0x126f340,0x0bf9d22,0x13dc9d2,0x06e7e30,0x1c95847,0x1ea39ca, + 0x17e8897,0x05a8acf,0x053a302,0x1f477e6,0x07538f3,0x108abaf, + 0x083a855,0x1239080,0x1e0a951,0x1568568,0x02eb3c0,0x1e1a44d, + 0x058b8e5,0x0635620,0x1644a81,0x17366a2,0x0773b40 }, + { 0x031cfd2,0x1966e1b,0x1ef003f,0x0700ee6,0x14c4c2d,0x0529380, + 0x185a8ce,0x1bdac00,0x1b32cab,0x0719836,0x0c5f2b4,0x11d54e1, + 0x0e33673,0x1cf9a9f,0x1d2aa35,0x075a7e5,0x0d9576f,0x03897b5, + 0x06caf38,0x0f30a51,0x0a30e42,0x06ed496,0x01763e5,0x0925bb2, + 0x1d475d8,0x05ecc48,0x0934579,0x1c0d4b9,0x0eabbd3,0x0a7592a, + 0x0f11c97,0x181daa2,0x1394ace,0x1573618,0x0166efe,0x0efc1f3, + 0x033fd13,0x092aa34,0x13dd770,0x10b8ad8,0x012b463 } }, + /* 99 */ + { { 0x12951de,0x0df5ec9,0x1252043,0x04b54d3,0x16959d4,0x197846c, + 0x07013b2,0x058bf89,0x02250b8,0x03a7866,0x113876b,0x134a75d, + 0x0d96a43,0x0824cd6,0x0f2ae6a,0x1675f86,0x06654d9,0x197e66f, + 0x018eba2,0x1e50b87,0x1f88f4a,0x1f237f5,0x08dccdc,0x1356fda, + 0x1672c3c,0x1063a8e,0x03f8480,0x038a226,0x13e56ec,0x0017a97, + 0x006b609,0x1494c95,0x089ab7a,0x0b1f91a,0x198767c,0x0e143f6, + 0x0e55331,0x034df08,0x1505c5f,0x0bcfb11,0x061c193 }, + { 0x092ae43,0x116cd9a,0x0168b9c,0x0a0a71e,0x1ef89d9,0x0555b18, + 0x1962080,0x02f5cef,0x0eba4b1,0x0396090,0x1872e0a,0x0590748, + 0x065c243,0x05c9c79,0x16cd0d3,0x0fb8062,0x0c58c4c,0x082df95, + 0x05acde3,0x0a03bab,0x0c30d2e,0x0fe5c48,0x0a141b2,0x06c3e19, + 0x0f4617c,0x1d71e85,0x0168d72,0x03ef6e3,0x1c01382,0x1af8f9f, + 0x17ef440,0x116491d,0x0628af5,0x0e5703a,0x0741232,0x071ac84, + 0x0ca1877,0x11ed1c9,0x16e51d7,0x1e4e3a7,0x027ad0d } }, + /* 100 */ + { { 0x05b5aed,0x1ed3c98,0x1a9e78e,0x08b331a,0x0c67d4a,0x1f5b801, + 0x1874c3d,0x08990ab,0x0147d1c,0x0c53f4f,0x1503b70,0x0c31912, + 0x003ea99,0x1f35fe9,0x0ef8829,0x0886f4a,0x064ecc1,0x164a43f, + 0x13be171,0x0f240e6,0x0bd5729,0x18eaf0f,0x1e83539,0x091ad6d, + 0x0b1e64d,0x06a7ed1,0x159b880,0x10543c0,0x1366a17,0x186d2d2, + 0x0e0a8f1,0x0348e6e,0x03fbd2b,0x010747f,0x1019ff8,0x0bafdf1, + 0x0acfb66,0x1437ef7,0x150bfb1,0x04edba2,0x05d9b5e }, + { 0x13e472e,0x1e2d2e5,0x0178d8d,0x0e61428,0x0153d92,0x04c2ac1, + 0x04b96d1,0x0a20133,0x1f39a08,0x0780666,0x1b15806,0x18236b8, + 0x0e26237,0x09a1aa0,0x03b5020,0x0630883,0x1f07e7f,0x1ff7be5, + 0x1d215da,0x1246cd7,0x091aecd,0x0d5e4a6,0x06dd6f8,0x02c44ec, + 0x178de4a,0x05c470b,0x0f171af,0x0a5cafa,0x171858c,0x0163ad5, + 0x1e5730e,0x07edc73,0x12c2c28,0x19afe70,0x1bcb589,0x0c98fc1, + 0x035a599,0x18ef58c,0x11d9b81,0x19b9771,0x024f891 } }, + /* 101 */ + { { 0x178c1e2,0x1b05fb3,0x197093b,0x1a01ab7,0x1f49c03,0x00d04ff, + 0x061b8bc,0x0b1d823,0x0ae096e,0x0d39452,0x1e61316,0x1db6e0e, + 0x05aabbc,0x038652d,0x11cef4a,0x01c7bf6,0x0614de3,0x1464946, + 0x1d9eaf2,0x1cff349,0x09cf3fa,0x15f610d,0x00f0acb,0x1b36bbd, + 0x10d629c,0x06fd7d3,0x07182c6,0x1bd5d4b,0x09b54ca,0x1bdf202, + 0x18f57fb,0x0dba621,0x0eebc76,0x190e67e,0x1f8e3d8,0x0aee91d, + 0x18ee8af,0x0e19588,0x1d84bfa,0x19fa85b,0x0863ac3 }, + { 0x05a2fe2,0x17e53dc,0x171828d,0x11dc853,0x13e70d0,0x0e1ca27, + 0x0882450,0x0151937,0x067272a,0x0354083,0x02f418c,0x0aabf2d, + 0x1de69a1,0x0a9e301,0x1bdf91c,0x1c9f570,0x14aef56,0x04b8330, + 0x01e02d3,0x186d713,0x1263c0d,0x111d0e9,0x10d95ff,0x0aa4592, + 0x17a8643,0x13c80fc,0x1bb7fbd,0x12312fe,0x0a17a0d,0x18ea36d, + 0x0f7aef8,0x10b599f,0x1179100,0x1e0ef37,0x18ca3e7,0x19c1b4d, + 0x01e7142,0x0ea9edf,0x1c96872,0x03d170c,0x03e3f1b } }, + /* 102 */ + { { 0x17fbf05,0x10ae03d,0x020adfa,0x0c3e347,0x192f11b,0x0e68de4, + 0x1656b47,0x11793bb,0x0ad0f7e,0x0fadbfd,0x1eade4c,0x0bd7f94, + 0x062936e,0x0cd2adf,0x1d05f70,0x1caa861,0x04343cd,0x18fb7a7, + 0x0bc112f,0x1ebccb0,0x0408971,0x1221446,0x1cf0ee3,0x00feaea, + 0x0c59fb8,0x07830d5,0x16062d6,0x0c9dc5b,0x03b0d3a,0x05304bd, + 0x161bde8,0x0072960,0x185ecc8,0x1a8bec5,0x11d2fec,0x0d340b2, + 0x079c3f0,0x16acbbd,0x0009626,0x1b0e015,0x081208e }, + { 0x0c4ce37,0x1a84c8a,0x0298424,0x0743549,0x134bb84,0x06ac747, + 0x1c09160,0x1750c00,0x1b375b8,0x0da1624,0x0f7a0db,0x0a49da7, + 0x16ac365,0x124919d,0x08786d1,0x128deaa,0x1d564dd,0x15e3e62, + 0x1ed6dab,0x09606b7,0x01a39c1,0x0c00a36,0x1fc8ae8,0x04429ea, + 0x0fbbc87,0x1b205b1,0x1ed2485,0x159fafe,0x0d6df13,0x06d0e5a, + 0x0457fc4,0x0c4c015,0x00e2620,0x08b3fb3,0x0a76076,0x12f58fb, + 0x16e7a19,0x0713065,0x0cf09ba,0x17101bd,0x044383f } }, + /* 103 */ + { { 0x04f9af6,0x1f80ef2,0x0873841,0x1b1963f,0x16381a4,0x1eea499, + 0x18fb3ed,0x13fccb7,0x026a883,0x05c21ad,0x1e27634,0x122a7d8, + 0x1fee60f,0x15e62f0,0x17fa940,0x15039c4,0x0c57e44,0x0023be0, + 0x0c2e96e,0x1d3f064,0x0dd9349,0x17ef0c0,0x1750bcc,0x147a239, + 0x19eaf64,0x01d4581,0x1afadc2,0x01df109,0x0742cb8,0x1062789, + 0x188a239,0x0e41404,0x0156cc5,0x1dbbfa2,0x1799c94,0x139aa8f, + 0x06013a5,0x14d3765,0x0111660,0x11e1aa9,0x08aee70 }, + { 0x0c54409,0x116ce19,0x0b1063c,0x0cebd75,0x09ebfa4,0x1424c0d, + 0x1a4a218,0x01921c5,0x16b3a8e,0x0100fb7,0x1d907b4,0x02d97ae, + 0x15c9730,0x180b82b,0x09bcbc1,0x19c03f2,0x08ffec0,0x024c202, + 0x0c674c1,0x12c423e,0x08c4bf6,0x02648d4,0x1d2d721,0x0061504, + 0x0fbcee0,0x090a620,0x1793db5,0x1dacea4,0x167d1eb,0x03e614e, + 0x0dabdf9,0x1843a6a,0x0307db8,0x14a02fd,0x11aaeec,0x1ead6d8, + 0x033e805,0x0cd3f18,0x09683c1,0x1fcc12d,0x0970f61 } }, + /* 104 */ + { { 0x1ec8e4a,0x09e918d,0x0d306f1,0x086b4c0,0x0809ac1,0x0f2326c, + 0x0076942,0x06a9dc1,0x18a4882,0x0b570fe,0x0192d92,0x10c664b, + 0x1fa1ae9,0x1a66834,0x1284fa5,0x14d6975,0x058b1d8,0x01b9c66, + 0x1dae769,0x0e3eb1c,0x16fb5fa,0x0463f58,0x12466fa,0x09c853b, + 0x0f13fad,0x0f6fae4,0x049267e,0x0b076ce,0x0d8bd74,0x008ad08, + 0x1faf388,0x0af2176,0x06d7605,0x1bc6efb,0x1b7920a,0x15262d5, + 0x15f855f,0x0c7d96b,0x1329f83,0x128b4fb,0x0404b5b }, + { 0x17a15c7,0x1341528,0x080be7b,0x19df100,0x0ae4cfb,0x0351aa5, + 0x104e544,0x1cf9dc5,0x0170feb,0x0f300c9,0x03152d7,0x13fae7a, + 0x17589e3,0x0648495,0x171c4d6,0x1fcbe32,0x13f0a7b,0x0e5bf6a, + 0x187325e,0x124855e,0x17d92bd,0x1629caf,0x034bbc5,0x1665e13, + 0x0c1ca70,0x0e086a5,0x154b461,0x0b0ea4d,0x0d6195a,0x18254a1, + 0x0b0a4ca,0x14a0161,0x025a979,0x1e9187f,0x12b958b,0x18bf43e, + 0x00da253,0x1aad791,0x1800983,0x16b0628,0x07faa11 } }, + /* 105 */ + { { 0x0402149,0x1278637,0x0466c2e,0x1b2c798,0x1584cc1,0x093a3b1, + 0x1706a99,0x1e4ee81,0x1c95715,0x1bbffba,0x07ec38f,0x095a7f1, + 0x1fb2f23,0x17cdf1f,0x05640cb,0x0fd04aa,0x01d0423,0x1fe4fd9, + 0x054fb64,0x1dfe714,0x1d13eb2,0x1008020,0x02754eb,0x037b051, + 0x0545b7f,0x152e797,0x190e54f,0x1a944f9,0x1e75c8d,0x12ea6c2, + 0x10c034b,0x04837c3,0x193ed62,0x10196f5,0x097c090,0x023ca7e, + 0x03a4e70,0x0abb1b6,0x1fafee6,0x0a5db31,0x014b63a }, + { 0x1c43336,0x05aa9b8,0x092dd84,0x0c47490,0x19dfd4a,0x03028d8, + 0x08b800a,0x1b6f72f,0x08f5f1e,0x155ddce,0x1f6ab61,0x1aef36c, + 0x1b67a57,0x06affd7,0x13941b7,0x078c715,0x19589ac,0x042ed4f, + 0x168f454,0x197550e,0x0ed2081,0x07f49a3,0x00cd4f6,0x1f3405a, + 0x161f1a1,0x038d955,0x1ce9967,0x0196126,0x1df8a1b,0x1185a7a, + 0x076df83,0x1d6fab4,0x1c4c741,0x12e783b,0x1271ca3,0x191e08d, + 0x17c171a,0x0e85e3f,0x09954cb,0x0e706da,0x0024858 } }, + /* 106 */ + { { 0x1a4cd8d,0x06e91ba,0x09e3350,0x072f797,0x132ca43,0x06b0fa8, + 0x1361096,0x0d0618b,0x1da1e8e,0x13f602c,0x1750282,0x02e23ac, + 0x1607a8f,0x1a1a86b,0x079957b,0x15c850d,0x0f05983,0x05cc673, + 0x162faf4,0x02723b3,0x1d497b6,0x12d8dd2,0x0e94a78,0x0d659ec, + 0x132e91f,0x114a37b,0x08fe8ed,0x1acdd8d,0x0f0ed2b,0x087661f, + 0x1d8e5e5,0x0be1168,0x09008cb,0x1071777,0x1096596,0x0ffad7c, + 0x1177bc8,0x16a89e0,0x0b6b9e3,0x1bffca2,0x06798ce }, + { 0x197c5c6,0x1fc7e8d,0x0cfd278,0x1cf1876,0x19fbab3,0x1acadd1, + 0x1104903,0x0ec884e,0x15d7d43,0x1a112dc,0x111ddc5,0x1f98f38, + 0x05880b3,0x194b592,0x0eb2a0c,0x1c309b8,0x1f71734,0x12ac89e, + 0x124d11c,0x1647a73,0x0a11a4d,0x19e8a10,0x13aecdc,0x0c117b9, + 0x00cf9f3,0x09fdce9,0x18c33f8,0x0c3159e,0x10874ca,0x1598af9, + 0x095d7c1,0x13e000b,0x06efe7f,0x1e4eda8,0x1e3006f,0x03155d4, + 0x178e7c4,0x0bc92af,0x18e57e4,0x1a4a5d2,0x03ea7ae } }, + /* 107 */ + { { 0x106ae25,0x0bf022d,0x03be618,0x1b96aea,0x1cac148,0x0615d15, + 0x0bc3981,0x0eb23d4,0x176b789,0x060cfb5,0x1686040,0x0da0ca3, + 0x1b79b9b,0x04a2b82,0x0896faf,0x0b7e3e6,0x1f35c00,0x0985a1a, + 0x109361b,0x1689057,0x1777440,0x0b6b1b9,0x0ae3c26,0x08969b8, + 0x16c561c,0x0ccb2fe,0x18c241a,0x1280bdc,0x0a1ec1e,0x0492045, + 0x05467fc,0x07a5e51,0x0f3246a,0x033cbf7,0x1d96f1d,0x1c02d86, + 0x10705f7,0x092b4fe,0x001118b,0x1380a4a,0x06a8ad3 }, + { 0x0be7282,0x18106a3,0x1c4b917,0x1a42701,0x1405afe,0x0d35684, + 0x096f757,0x03c99b9,0x07f8be6,0x16b78c2,0x0e05e30,0x12a6b2d, + 0x1420132,0x1d46fca,0x0ec79ed,0x0569b1a,0x1bb3957,0x13abe30, + 0x0330ed5,0x136af70,0x1fecd74,0x099bd9f,0x05643fe,0x0bb929b, + 0x1b65314,0x0b99cdd,0x188cd79,0x01838c0,0x03feba7,0x196bfbb, + 0x0ca70b9,0x198c36e,0x168e424,0x1f96523,0x1e9aa9c,0x1aeefa5, + 0x05cb58c,0x126dd56,0x186ab7b,0x0f339f5,0x01a1811 } }, + /* 108 */ + { { 0x1575ed0,0x1fb17bb,0x066dbdb,0x12fa3b5,0x18f14fa,0x17ebfb0, + 0x0bbeda7,0x0665ce5,0x1ddc286,0x02d5a65,0x1160d31,0x1a90b0d, + 0x18b0e20,0x1cbbaee,0x05c0468,0x08931a7,0x008f413,0x0009864, + 0x14457b6,0x011d75e,0x1ed92d4,0x0e01306,0x1141a81,0x1957223, + 0x1736219,0x1434f2d,0x1ba1a4e,0x19ea118,0x1736174,0x122fe63, + 0x08d39c4,0x12bb139,0x171aa1f,0x1de4c17,0x11a981e,0x049774f, + 0x012b7fd,0x128af39,0x1d6a3ce,0x0eb2461,0x07d2ddc }, + { 0x0d2cae8,0x0c0b6a7,0x0ddcf41,0x1b73800,0x0cf6bc7,0x15846a2, + 0x0639991,0x101847d,0x14b9c01,0x0f73630,0x05e707e,0x1427df2, + 0x0ae11c9,0x076cb44,0x0d851fa,0x0e14f4b,0x048d066,0x0bd7f5b, + 0x1da149d,0x0066782,0x08f2d67,0x14bafcf,0x0a27765,0x14d15bd, + 0x1228d37,0x0c35dab,0x191532c,0x0340bab,0x1dd5502,0x0ac7831, + 0x1cd2040,0x0996d95,0x0dd4f08,0x055f3c9,0x0149e15,0x0ce189b, + 0x0e729d7,0x0cb4ee3,0x102ea11,0x0f5637e,0x05a52f8 } }, + /* 109 */ + { { 0x1ecacbd,0x0cf4884,0x17abb40,0x1af7137,0x0544023,0x039b8f3, + 0x07c2d5c,0x02ef98a,0x016c8e2,0x0419582,0x166ad45,0x0d05024, + 0x14b1aa6,0x11f1b0e,0x0403e48,0x0b854dc,0x0e9e3a9,0x172c9f7, + 0x1b04389,0x16d77a2,0x013f699,0x19ca39d,0x0b521e1,0x0e930f9, + 0x14dc5b2,0x174f8e0,0x1495678,0x0fb800e,0x147ad25,0x024ee1e, + 0x04e1126,0x1baa4ef,0x1df278a,0x0adccc1,0x1b23bbf,0x00ee1c7, + 0x16bd02a,0x12c2233,0x17ff8ab,0x0c87ce0,0x017f027 }, + { 0x1abea1f,0x0008694,0x1133769,0x0a480f5,0x036b969,0x1990c5b, + 0x004a410,0x0952d4c,0x1163d53,0x110fe1d,0x081597c,0x0b7d998, + 0x1705ba1,0x0b142ab,0x0e39536,0x009a624,0x0578788,0x00d8a21, + 0x026a7f9,0x17e6095,0x02b196f,0x1625f32,0x1229fc1,0x05610bd, + 0x020e86e,0x08eee8d,0x0bfd296,0x1efe4f8,0x0343b88,0x03a9d25, + 0x13705ec,0x1762e7a,0x04b1e88,0x03ddf34,0x0910f70,0x0e7599d, + 0x0c441d7,0x0ae446a,0x055fb6c,0x134a7cb,0x00ef030 } }, + /* 110 */ + { { 0x08e5b60,0x12b90fd,0x0ec93f0,0x1ad2381,0x046938a,0x0511243, + 0x12dd82c,0x0efc8da,0x07de168,0x11fcd61,0x0718c21,0x0dde4e4, + 0x02503bb,0x05b3fd8,0x106677c,0x17a73f1,0x172e07a,0x13c60f6, + 0x0cbc376,0x1bd6f76,0x09f3cf9,0x18361e4,0x0bfdc9b,0x0e444b5, + 0x08b2d19,0x1ae5b80,0x1d3c517,0x1eb4c22,0x1c4f378,0x17c622b, + 0x1913839,0x0388a78,0x1bdaa44,0x0964045,0x09b69ba,0x02af7c6, + 0x1d77356,0x1e1feca,0x0dcaaa6,0x18d766f,0x03d3b6c }, + { 0x122c880,0x189664b,0x0225b9b,0x0e50d6d,0x1a1b6ae,0x17d7f61, + 0x1026eb4,0x1df7439,0x043bb8b,0x0b256bd,0x0fd30eb,0x14012f8, + 0x1ba5af6,0x01a9d48,0x1f2c367,0x17ed655,0x0ab69cc,0x06509fe, + 0x0aaf064,0x142723e,0x07e5699,0x0111d12,0x0b6f555,0x0911b34, + 0x0180f95,0x01e7103,0x1c49133,0x153cf7f,0x13a365b,0x1d5f43e, + 0x188a4a5,0x1f4994b,0x054fa38,0x10db620,0x08f59ef,0x096720c, + 0x18f41a4,0x133e2bb,0x1139c7e,0x0878f6a,0x02e946e } }, + /* 111 */ + { { 0x00934ae,0x07eefe3,0x1b44a60,0x1e2c840,0x0c3e7ef,0x176bad1, + 0x1fe5905,0x1b9eebc,0x15cd0b2,0x1630679,0x0b61efe,0x1d9c3f5, + 0x1dddc4b,0x0c24f2e,0x0fea1f2,0x1e35cea,0x0a32c1b,0x1e2ea8b, + 0x11ccad2,0x1b7d502,0x096b565,0x1d67243,0x001faf8,0x172ed28, + 0x074d6cd,0x1df2065,0x0197939,0x1eb9a4e,0x0c4ebc3,0x1e009d5, + 0x085d211,0x087ad87,0x162e034,0x103b533,0x125519e,0x1ad21b1, + 0x1eda677,0x06bc6b0,0x16309da,0x0aa0303,0x00997ce }, + { 0x05a0b81,0x1ba364b,0x17ea4a5,0x0dcbc25,0x08b58be,0x0fa1bfa, + 0x0cf11c5,0x0b2aae7,0x1b565c4,0x012f483,0x09e5f39,0x0a242b0, + 0x0f4f43f,0x0752a3a,0x16be9be,0x00959cb,0x1be13de,0x19575c7, + 0x0281f20,0x1f2be1d,0x09feed7,0x1733160,0x0f804a9,0x0859e2e, + 0x0e9b8c7,0x022dfcb,0x0b8a287,0x1d4aeb3,0x14e2f38,0x00da2e7, + 0x0651d65,0x1f20340,0x1d3c02d,0x0b5973e,0x1ba9c24,0x11cf49b, + 0x0fa9b98,0x19395a9,0x1ff9942,0x13fa122,0x096f9f0 } }, + /* 112 */ + { { 0x0310a96,0x0556216,0x1cd1e3a,0x07ef454,0x12a9830,0x0b11039, + 0x0a0f48e,0x10188d9,0x0d95412,0x0898f37,0x0fa446b,0x18bc595, + 0x085791f,0x020db63,0x12ddfae,0x110f0a1,0x1ea3d3c,0x157fc9e, + 0x0401ef3,0x083e3be,0x11fd065,0x012ae6f,0x13b9ca7,0x07c72e4, + 0x1131732,0x060f07b,0x06b5342,0x05bcf48,0x1e22bfa,0x155fd1a, + 0x096a644,0x1136066,0x050122b,0x0a6a750,0x07d0194,0x17173ca, + 0x19d3e0a,0x1e3d56b,0x1fa9508,0x04c8171,0x071998e }, + { 0x0b6ed78,0x007e6e7,0x1459005,0x0e30a68,0x053cf37,0x0b06e63, + 0x0d96ba3,0x1f008a1,0x09dac55,0x1360d3b,0x15a1b33,0x125b5c0, + 0x028a96a,0x093892b,0x1911d88,0x1284a5f,0x150a4f3,0x13a3de5, + 0x114c7f0,0x18dfe5f,0x1ff0f0e,0x03887f4,0x125f0d1,0x0f259ff, + 0x087839c,0x00cfda4,0x0009bec,0x0a58a49,0x04c2905,0x114e6c0, + 0x1cd0006,0x06b9194,0x02b5ad8,0x0efd03a,0x1c5dbb9,0x0386f03, + 0x1dfa4ab,0x15c2f81,0x0cab329,0x034161a,0x0838994 } }, + /* 113 */ + { { 0x0067dff,0x031516f,0x058b03c,0x0179700,0x14f3269,0x03d15ee, + 0x064341c,0x123319b,0x0fae4a3,0x17e31dc,0x0b60516,0x16f7665, + 0x11684f1,0x18ccefd,0x08b738b,0x0b09161,0x17f48f2,0x1113070, + 0x0b57a18,0x07b6018,0x1171739,0x0a19c67,0x07a23e1,0x159ea45, + 0x1942902,0x19e8033,0x01a0d6b,0x122af97,0x02614c1,0x17c95c5, + 0x1b0bea9,0x0269d88,0x0ff95f5,0x1409a82,0x09bbede,0x099e00c, + 0x137a470,0x059e82d,0x1b09515,0x0624d29,0x01fbfda }, + { 0x0f69c77,0x1db2be4,0x03ebf7a,0x1747bf1,0x12a8278,0x1dbc5a4, + 0x155c707,0x0668c76,0x011c71a,0x103350d,0x0562c34,0x0286113, + 0x0610c88,0x07ceb3d,0x1d71f83,0x0f71f72,0x0087303,0x0ed52e9, + 0x02fd618,0x0a00ba8,0x09a95ee,0x13bedd3,0x0c039b3,0x0c598e8, + 0x03cb3c9,0x02ac49e,0x0533e10,0x15930c5,0x1c9d700,0x1b1d112, + 0x1a029fb,0x1723c8f,0x0184869,0x1c25f7f,0x17ae30b,0x1e373af, + 0x00e278b,0x1c448ae,0x1c6799d,0x195884d,0x04f9488 } }, + /* 114 */ + { { 0x151b8ce,0x0fe6a6e,0x1a01843,0x106c461,0x0857927,0x0ccab10, + 0x1fc70d9,0x0efdb8f,0x1e2cae8,0x02f56a5,0x19d8224,0x0bb3cf2, + 0x0ca1c32,0x1e9c493,0x0e7b776,0x0149c7c,0x0685f6f,0x06d4964, + 0x11e83e9,0x1f0015e,0x0aabe16,0x0df2fb0,0x142d36d,0x070a7a6, + 0x1412f98,0x04e1b32,0x026de5e,0x096c44a,0x0e72b26,0x002c270, + 0x0efa958,0x1caab85,0x1bd4901,0x09708d5,0x069c5ca,0x1e6f083, + 0x0174218,0x05ad557,0x1ae49b8,0x1091ef2,0x0688e06 }, + { 0x13b8f64,0x17b2098,0x118b37f,0x172858e,0x0ef11b7,0x06c55ed, + 0x1eddd70,0x1520cf9,0x0af4041,0x04752f8,0x14843d8,0x1b04d26, + 0x0823d5b,0x13c8bd0,0x0e413f0,0x05a42b5,0x1fe45d2,0x1c2edd8, + 0x14d8567,0x0bca129,0x18f2c3d,0x070e9cd,0x0baed4a,0x0959de1, + 0x0a828f4,0x12a6eae,0x1c8315e,0x084135b,0x195f442,0x1a19bc7, + 0x0dd5d0a,0x15266fa,0x11fa7d9,0x07edbe8,0x1027193,0x19acd41, + 0x1bb817e,0x12adc7c,0x049955b,0x1c7c988,0x01723c7 } }, + /* 115 */ + { { 0x08b43f3,0x0436c6e,0x19a2699,0x024c813,0x1c3e0e6,0x1a3001f, + 0x110df66,0x0f63113,0x16284ec,0x142819a,0x16eba8e,0x0b88d53, + 0x1c5a366,0x14bc499,0x1da5077,0x02920f7,0x1106934,0x08f6ad2, + 0x12e000b,0x14f6f51,0x0a59664,0x1230768,0x180fddb,0x09d7e4e, + 0x06ba31f,0x13fe1f0,0x07cb0e2,0x12d9da8,0x1db08a2,0x07bce78, + 0x0d8ab06,0x19bcf47,0x119e882,0x1458364,0x14a76fd,0x0a2bcef, + 0x0e947cb,0x0bc5d52,0x064e886,0x056ec61,0x084bf54 }, + { 0x164f21e,0x166d4f1,0x15fb077,0x0a025ca,0x0d6cf34,0x07c8708, + 0x1a12162,0x1717448,0x1e3b104,0x1b6ed25,0x1bd5ea7,0x068dc75, + 0x096bf7a,0x14193f5,0x00a67fb,0x1cd8e42,0x087da95,0x0d54cfa, + 0x0b37d91,0x1f027da,0x14b824f,0x0945ea0,0x1476ecb,0x1f434c3, + 0x101afca,0x0d20328,0x0a737af,0x1b3e973,0x1039e47,0x19caf20, + 0x10abd06,0x18a15be,0x1e9e6ba,0x14f24f1,0x0eb8d07,0x069e426, + 0x0b157f2,0x146079e,0x0054d25,0x0f7b40d,0x0383f82 } }, + /* 116 */ + { { 0x183ff4c,0x03510b2,0x079cbb1,0x1295ae1,0x0e645a2,0x0650952, + 0x1a73f01,0x1cbb8cd,0x09160a7,0x178947a,0x11d8ba0,0x0f62ad3, + 0x07bfb22,0x0176dc7,0x031e58f,0x1ed11f0,0x00649a0,0x053ed7f, + 0x1452e33,0x082ea85,0x00beb7e,0x09c36f2,0x0e83171,0x16f2662, + 0x052861d,0x18df868,0x07eff81,0x12059cd,0x0e9903b,0x14ab108, + 0x0e18791,0x1ee07d7,0x0ef874e,0x1bc5b7d,0x11fb757,0x15ecd12, + 0x1af5ea3,0x1432a3a,0x11895bf,0x02a87f2,0x03b121f }, + { 0x19275e9,0x17423b2,0x19416c9,0x1ada1f9,0x07581cf,0x11f8f7a, + 0x12ff62a,0x01cabeb,0x1e484e6,0x13df18a,0x1a63907,0x041ffd2, + 0x04d8f1a,0x1d5823c,0x151b6a5,0x1b67c4b,0x175834c,0x0d2936d, + 0x1422802,0x0811b31,0x08161fd,0x102dae5,0x1f0012c,0x1c977d1, + 0x03bb365,0x177ad9f,0x15d66ed,0x0a19824,0x1ac737f,0x140be17, + 0x06bc17e,0x1a4e72a,0x0e102d2,0x199b3cf,0x102ffb2,0x1e551ca, + 0x0a6a515,0x1a237d9,0x0320d9c,0x1a26e52,0x05505e1 } }, + /* 117 */ + { { 0x15e68a6,0x00a50e8,0x179430c,0x0cc9ba6,0x0f9f0b2,0x16b3fcb, + 0x1d0b40e,0x1083186,0x0d2c144,0x040c607,0x068f2dd,0x02d21a8, + 0x1ec5181,0x024f9f4,0x12320ff,0x1270ccb,0x0612c27,0x04d9306, + 0x1b413a7,0x10df5d9,0x0758f60,0x15febe2,0x09ecb33,0x052ffb1, + 0x0313390,0x164259e,0x0025c06,0x1504c9d,0x0b3762c,0x1543a84, + 0x1fa7e5d,0x130751b,0x1582714,0x0cc74ae,0x19a7675,0x106a1a4, + 0x0f6fd34,0x05c4e58,0x0c5f217,0x1a94ae8,0x0617d80 }, + { 0x0022b67,0x1933f38,0x052933b,0x0a6ed17,0x00536bb,0x1c22314, + 0x0959b49,0x03262a7,0x0382439,0x082a6a2,0x1e31292,0x02e4bbe, + 0x1a8d11e,0x0ad0f1a,0x094a9c7,0x1c63b36,0x0808171,0x103c336, + 0x0ce2803,0x0a03b63,0x02360a8,0x1c673b8,0x0bb64ca,0x1b5efa0, + 0x176098e,0x174d16b,0x0ee4c01,0x15dcbb5,0x1eb0363,0x04625df, + 0x02febff,0x09c4367,0x17b9678,0x0703483,0x167f72a,0x02923f8, + 0x0e93847,0x1127aa8,0x1e02cfd,0x010f9a2,0x05156f5 } }, + /* 118 */ + { { 0x006e8d0,0x1a71101,0x1cc9608,0x08fe2b5,0x15f6f5d,0x1c4a87f, + 0x1ca2758,0x1e95f56,0x17d4495,0x1762684,0x0a02a59,0x18bad1b, + 0x0bad890,0x127c51b,0x0a82481,0x0b8bfc9,0x17e0f4d,0x0bccf12, + 0x112578c,0x0cef5c4,0x035244c,0x19d2dc7,0x1c80e1e,0x1450f72, + 0x190f475,0x17bb81b,0x170f07c,0x0912b98,0x07fa415,0x07cda0d, + 0x02ee1a0,0x1601601,0x0d47458,0x039e5fe,0x00e2e99,0x1429399, + 0x0c9be19,0x16afbd5,0x196e9e3,0x139666e,0x0525459 }, + { 0x01b54c4,0x1cb3cd1,0x167421c,0x156c92f,0x029ece2,0x0443200, + 0x06a4b21,0x1b3e29e,0x1e9fa79,0x1246e7f,0x08236eb,0x03848d8, + 0x1e14b91,0x0d71fb4,0x0c3efcb,0x17070b5,0x07ed1ed,0x18c0564, + 0x02161ae,0x1fae303,0x0bd0146,0x0a2a33e,0x0843ad9,0x0cf9fdc, + 0x1940816,0x1305511,0x0adcf46,0x1624b83,0x1c1cbed,0x0980440, + 0x0cb79a1,0x06f8604,0x034c713,0x0468c7f,0x1c39bcf,0x078d8c0, + 0x14af4e8,0x11b2dd5,0x0ad141f,0x1dbb9f0,0x022f0a7 } }, + /* 119 */ + { { 0x07f1b7f,0x13c8ff5,0x0753898,0x1bb9fe1,0x1c3d8c5,0x03ee2c4, + 0x0a70ce7,0x1810d85,0x14276e8,0x0d6a00b,0x1875593,0x1eb3d3f, + 0x090a918,0x1554086,0x15e59c0,0x19b8971,0x0364aa5,0x175bd44, + 0x1ebe9cb,0x184777c,0x0908fc4,0x0f25643,0x136ed72,0x018fcde, + 0x190136a,0x0691bf1,0x0527086,0x0abae00,0x1324a28,0x1e33ca5, + 0x1c791d6,0x0c50f40,0x18a8dc6,0x0191e64,0x066d7ed,0x1272b45, + 0x0c0389e,0x0361f70,0x1311b86,0x0de2ce6,0x079f81e }, + { 0x04f3c4e,0x160f99b,0x052e0fc,0x0a26cfc,0x136b2ac,0x19f21ea, + 0x173f164,0x1fc894d,0x110d961,0x072ca3a,0x1caab8d,0x1d9cfc7, + 0x0508234,0x1ef53f9,0x04b802a,0x1424997,0x0f0a791,0x10f7dd2, + 0x064b54e,0x10dfa42,0x0af6c20,0x1e5a8e4,0x1fb0343,0x01e36bf, + 0x1b2cadc,0x10ca468,0x1e04b6f,0x00f4711,0x1bdd45b,0x1d356f6, + 0x069021c,0x1ae04b1,0x02a1268,0x13db25e,0x0ea05f8,0x0b77edc, + 0x0d386e8,0x172b31b,0x10001cf,0x06f3bcf,0x0442ecd } }, + /* 120 */ + { { 0x02f90a6,0x08d7345,0x0332d33,0x1adeb5a,0x1277d41,0x0ea5c77, + 0x0a31100,0x062d470,0x0d83766,0x00bd09a,0x04492fa,0x0b1bebc, + 0x04142b7,0x1eb5caf,0x1ef1a77,0x13c7c4b,0x15fd74a,0x151864f, + 0x02598f3,0x01e2c7b,0x186d5ac,0x1b86731,0x0caa7bb,0x1daaa88, + 0x10ea5d8,0x13d3d34,0x0262250,0x1bc47fe,0x0ced585,0x1b52f55, + 0x195d6b4,0x1a7c308,0x114a6c1,0x09c881a,0x0b0dfc2,0x107b22c, + 0x033d56e,0x0856ecf,0x1a47970,0x0e60d54,0x085176b }, + { 0x0a21e38,0x0887d14,0x14e28c8,0x1aaee7a,0x17b6379,0x0106e24, + 0x1eefcb4,0x19ba6d2,0x1961833,0x08bbac9,0x0a14596,0x0bf5cbf, + 0x126d704,0x1c355ae,0x043ca69,0x0b6e067,0x030dc4f,0x15605ed, + 0x1318571,0x004815b,0x0d91cca,0x01628a3,0x0387c5c,0x059df0f, + 0x072d0a7,0x1d0e75a,0x002d9a6,0x09080e1,0x01aa0a8,0x07cebf3, + 0x02de6c2,0x08cd2ac,0x08160be,0x15b8f1c,0x10b6523,0x184726b, + 0x1431590,0x1ec1e04,0x1a2cf5f,0x176dcae,0x08ab154 } }, + /* 121 */ + { { 0x13c4a96,0x030019a,0x00d4a1a,0x1120b9b,0x0e5c60e,0x137c662, + 0x04d923d,0x13d7ab2,0x09faccf,0x15c05cc,0x18e796d,0x1f5dc64, + 0x0bbc1c1,0x13c556f,0x18e5b48,0x0405a5e,0x0d01898,0x08053cb, + 0x091d20d,0x16a91e7,0x0e3e18a,0x01d98d8,0x0b3415b,0x0c8a25b, + 0x068dd01,0x1de0add,0x052c0fc,0x00706db,0x1206c52,0x0535ec7, + 0x0db593b,0x13e2ef3,0x11a361e,0x19a5449,0x03f14aa,0x05b04d2, + 0x12922e2,0x15dc704,0x00aa4d0,0x109c016,0x01bfcdd }, + { 0x1a365d9,0x1cd21ba,0x0c0cc42,0x1c11b1f,0x14ade15,0x016fc1e, + 0x14f5f5d,0x085392e,0x0de3187,0x1b984ea,0x02b3833,0x042466c, + 0x031228e,0x1bb34b2,0x10f48e3,0x0b4a620,0x1edf90f,0x1fe156d, + 0x0d7e4e5,0x0c996ef,0x101041d,0x0562236,0x14802cc,0x02e41fc, + 0x0642d23,0x03ae1e4,0x16e6a88,0x1980245,0x1eae47f,0x1d89020, + 0x09215b8,0x0d190ed,0x1864455,0x10358a2,0x01088cd,0x1e3438f, + 0x027757b,0x1b368f9,0x153c66d,0x077ef73,0x025b78a } }, + /* 122 */ + { { 0x16707ce,0x1ab8c0a,0x042a420,0x108629f,0x1bdc239,0x12bedec, + 0x0216a2f,0x17002f9,0x1ad63a4,0x05dd112,0x0b3ff75,0x170c2b5, + 0x025ce71,0x194aa39,0x09991d5,0x1a7babe,0x1f74f0a,0x1854078, + 0x10d4bb5,0x0a7147f,0x06ca010,0x02a101e,0x1e29901,0x018e769, + 0x07a8833,0x00d9596,0x180b72b,0x06867dc,0x0b17c7b,0x0ce7f69, + 0x11cb812,0x17ac653,0x18681a4,0x16e1bcf,0x0518dbe,0x16712f3, + 0x12b7895,0x0b28644,0x073c371,0x0e0cb4a,0x070ab95 }, + { 0x1585d93,0x1c7623d,0x193919d,0x014c67f,0x0a6d361,0x10188d6, + 0x055393a,0x05e43b4,0x1bd6400,0x1910c85,0x12dea6b,0x158fb23, + 0x179e633,0x17341be,0x04f0c7f,0x1dd15da,0x1d71616,0x16d2503, + 0x0bf3585,0x144e647,0x1694d78,0x12dd0a6,0x1019a5b,0x1eb0841, + 0x154d74d,0x1e4b99b,0x189de38,0x10bca09,0x15a5c2e,0x15062ad, + 0x170c156,0x1147596,0x13df538,0x0476d18,0x12d4a82,0x1cb12d5, + 0x04c85dd,0x0421504,0x19afbf2,0x0f2a3bb,0x05fec9f } }, + /* 123 */ + { { 0x0519f99,0x0163e7f,0x0d4d7af,0x01ca820,0x0396bd8,0x1cc479f, + 0x0500a28,0x1435bdb,0x1d601bd,0x001db9a,0x1992b07,0x006c299, + 0x10fd302,0x0092014,0x0dfafa4,0x012fab0,0x1a3a554,0x0e55750, + 0x02e204e,0x0e7a4b6,0x10b9dce,0x15f6584,0x0d7b504,0x07b5678, + 0x09ff7d6,0x038cc81,0x0418b6c,0x0aa86fb,0x04c11d5,0x17ab215, + 0x0249df4,0x049f922,0x17fa645,0x092a6a3,0x06dc9e6,0x18f625d, + 0x184c618,0x0957116,0x14655eb,0x0c79d1d,0x00a8d56 }, + { 0x021fde1,0x028b185,0x01250eb,0x0cd207b,0x0fcf5dd,0x0eb140e, + 0x067b97f,0x068da49,0x077a49a,0x0f6e378,0x1701bd3,0x058050e, + 0x0646bda,0x1a3dc02,0x18383d8,0x106dfa1,0x09b5e67,0x1082c0b, + 0x1a2a010,0x032255b,0x1d32c96,0x05549d9,0x17cffa8,0x0aed78b, + 0x18edb0c,0x123cf89,0x1b634df,0x12e35ad,0x05e7cb7,0x0b9ce67, + 0x103aae1,0x03a4056,0x0a4b434,0x0fe9344,0x155f8e8,0x02bb084, + 0x13a86f9,0x17d5ead,0x18a7e1c,0x126d548,0x095b934 } }, + /* 124 */ + { { 0x1f951de,0x05380cc,0x0d16666,0x0de0b1b,0x0fade59,0x081ee9c, + 0x0707bcf,0x1a69a8f,0x133b141,0x14946ae,0x1a2901b,0x100159f, + 0x1d9a465,0x00e77d1,0x022b4bf,0x0e4dda2,0x121e013,0x1b25cb4, + 0x1a0eee7,0x0d4d6d1,0x0544b9b,0x0e09217,0x0a7c79b,0x0cb2cd6, + 0x0f6762f,0x1a0e9fc,0x1978416,0x069ba12,0x011e1ca,0x09cd0b0, + 0x06f53a4,0x04a2aa8,0x0a4dc68,0x10b36f7,0x02b3208,0x08df006, + 0x11d1612,0x03d70e9,0x1e9f6f7,0x0a2c435,0x02e25ef }, + { 0x18e7357,0x1e7c7ee,0x16e094c,0x11d59db,0x133ba21,0x0269561, + 0x18c741e,0x1c4d1c7,0x0f2804a,0x0493f9b,0x1eb5f87,0x1a44efc, + 0x0001433,0x0c3fbc5,0x10073c1,0x04f5c16,0x036aa00,0x0cefe78, + 0x16691ad,0x08d9163,0x0d32c9e,0x030f944,0x0a9b792,0x114087b, + 0x0da2f1b,0x1ab6eab,0x17cb42e,0x08c461c,0x1efb563,0x1b720ce, + 0x1d067c2,0x043a590,0x1ec37cd,0x122d9aa,0x0e5edc3,0x047b7e0, + 0x0c7ce85,0x031546d,0x1cf5bc2,0x14fc283,0x087979e } }, + /* 125 */ + { { 0x11c747f,0x13d9fbf,0x0da66df,0x1b8dcc6,0x151a4c1,0x196dd00, + 0x1fdc2cd,0x1fc84e7,0x0d3ee54,0x136911a,0x12b83f2,0x1c19a67, + 0x0c12fc8,0x0eeb788,0x0ca14e1,0x139f24e,0x1bdf01a,0x0e4379f, + 0x0db2ba4,0x04ceffc,0x0a44532,0x1997f7f,0x0e69c00,0x115e42e, + 0x0a328ce,0x0fa164e,0x1bda9cc,0x004acee,0x096813c,0x19efb35, + 0x0a31a1e,0x11b65db,0x14aab12,0x07f5e8c,0x116bbb1,0x05bc61b, + 0x179241b,0x0911b54,0x1305b01,0x005847a,0x03ec988 }, + { 0x072f74d,0x13b0620,0x01643e7,0x1d56b28,0x078eb0d,0x1804e17, + 0x1a90326,0x1cbb67b,0x038b59a,0x1f43af8,0x16a8191,0x086c569, + 0x08f40eb,0x04879bc,0x1a93e48,0x15f1734,0x1afedbf,0x177f5f4, + 0x019f895,0x1f2d4b3,0x0aebf87,0x11bad5b,0x079bfb4,0x1b62796, + 0x0782a3f,0x1108bf9,0x19c3e89,0x02058e3,0x0c0dbe5,0x03767ea, + 0x05d74ac,0x06068e5,0x17cc268,0x1f3c029,0x18acad9,0x051b7eb, + 0x1a25da3,0x119f9d5,0x12450bd,0x1d1df5d,0x03e9315 } }, + /* 126 */ + { { 0x19a9ea9,0x0e7d291,0x098a495,0x0017c67,0x00f3c69,0x1b215e9, + 0x1ad2e72,0x030eb3d,0x000bae7,0x18b62a3,0x043e10c,0x0dabe68, + 0x16874a7,0x087894d,0x0ed40ba,0x03e3824,0x1a81285,0x056e47c, + 0x0d89023,0x16ec943,0x177bf57,0x0f8d403,0x045bb00,0x01bb8b8, + 0x0cef21f,0x0d3ba37,0x13969a9,0x1893a8f,0x0955ba3,0x0df3837, + 0x0c07857,0x168baf3,0x09c0c79,0x08843b1,0x0c21de3,0x0e224f0, + 0x0c6a22d,0x0c2ee3c,0x09e4489,0x01a14d0,0x02ed02a }, + { 0x1aa2682,0x01a0b26,0x18954c1,0x16026b2,0x0e26d32,0x03384b8, + 0x00d2af6,0x05c8939,0x1ee77ae,0x0d0ce95,0x1b05a44,0x053475e, + 0x1439bd5,0x0e6b082,0x1329701,0x01fc26d,0x19bdc6c,0x0b1b852, + 0x04f544d,0x041a4f7,0x051aca4,0x02aaa62,0x161cc35,0x19bd7e5, + 0x058c996,0x102f5e9,0x02943e6,0x1963732,0x0f01510,0x04bd3d8, + 0x185a6a3,0x023a42f,0x0c36d34,0x1baf416,0x0229d4b,0x03e22ed, + 0x009b2a6,0x1809ca5,0x15f7476,0x08953df,0x0146278 } }, + /* 127 */ + { { 0x12803cf,0x11d7691,0x1cd1af2,0x17352df,0x01e4398,0x15bc45e, + 0x1d5fdd2,0x09b95ec,0x07e68c0,0x1d29f00,0x1f34830,0x1832b96, + 0x0a5f969,0x0e0345e,0x02d969b,0x06065e5,0x1d31d86,0x071e500, + 0x1e02385,0x0677030,0x18be9b7,0x0cf7f30,0x0d75c13,0x03728db, + 0x13542b0,0x0df93b7,0x1befb77,0x00afc33,0x1275cee,0x1795c81, + 0x119f460,0x1101ef7,0x0dc5f77,0x1b60a1e,0x14fde11,0x05ade07, + 0x09ba507,0x0faaabd,0x058a00d,0x16d6805,0x07acb57 }, + { 0x0e6b07c,0x09ab4a2,0x1177490,0x13c38e6,0x051c4cc,0x19dcfda, + 0x1136389,0x1f880e8,0x1b88e34,0x124b03c,0x09ddb7f,0x099fe2a, + 0x1c77d18,0x03a114c,0x040cee7,0x0512eda,0x08477bf,0x014d053, + 0x1a3c108,0x1fbe21d,0x16d659f,0x16225da,0x1385c51,0x135d0aa, + 0x106c2fb,0x06ac18e,0x0f64f9f,0x059705b,0x16b607b,0x0e231e4, + 0x0a20ce0,0x0ea93c5,0x0aed251,0x110ea03,0x0471dd2,0x1bdf2f1, + 0x0675fbd,0x0c03e3c,0x145b2ba,0x172c6c6,0x06a5a05 } }, + /* 128 */ + { { 0x08f4f33,0x18f5335,0x1d2a4b9,0x0c9bd51,0x12fc6fc,0x144230f, + 0x094b3fb,0x011a6ac,0x008954d,0x0d8541f,0x0add996,0x18468d1, + 0x045bd68,0x0807c68,0x0a04d5e,0x0cf5c80,0x1c052b8,0x08c0e0c, + 0x01d9310,0x14a2d23,0x1d24986,0x1709aba,0x12c077e,0x06cef6f, + 0x09ae559,0x18c8b93,0x151b726,0x0da2e04,0x0097c8f,0x024ce20, + 0x1ee379a,0x04b3880,0x0df0032,0x14ec5bb,0x0b645f4,0x0c81235, + 0x0a7ab5f,0x1a3690a,0x192329f,0x168e1d9,0x0688054 }, + { 0x1a5b86c,0x0b45528,0x091fc34,0x112aeee,0x0437e4d,0x1901949, + 0x101dbc5,0x09d5d08,0x19647a5,0x13d643e,0x1588b02,0x1496080, + 0x0f1e597,0x1853cf9,0x1bf971b,0x02adbdb,0x0c24d55,0x1579f78, + 0x1c11f3d,0x1f609dd,0x0137917,0x0faa5b1,0x0de49e6,0x097c170, + 0x0a32f31,0x18643af,0x0c3119a,0x02af8cb,0x018978e,0x08673f1, + 0x0bf4a32,0x19bcb0f,0x10fc3ba,0x1bdf6dc,0x1c722e1,0x1bba65a, + 0x0a8e10c,0x0191006,0x1b94ced,0x033b29e,0x00021f4 } }, + /* 129 */ + { { 0x1519d26,0x0891621,0x0114864,0x1a814a3,0x1dafac1,0x05dc4fd, + 0x1c7a552,0x1f398de,0x016844b,0x1799bae,0x1a35567,0x1ef22f1, + 0x05e7789,0x0fc5f0e,0x1d666d8,0x1bc8009,0x19a2cbb,0x0c04464, + 0x04c81b2,0x1344c11,0x0851893,0x1ffe698,0x086b92f,0x11fd5fd, + 0x0b3fee0,0x15e3326,0x07fc52a,0x03e7013,0x041ef96,0x0a66154, + 0x0d8360e,0x02fe03b,0x1fad8ad,0x1dbb9ba,0x15d9b7a,0x04df868, + 0x0425251,0x18b582d,0x1b67c79,0x10053c3,0x0798558 }, + { 0x1106473,0x19d554a,0x08128b2,0x02b4c3b,0x15fafa4,0x0ab1e04, + 0x04d894e,0x10ffa79,0x195312b,0x1524048,0x0171dae,0x0b057f1, + 0x156c7e7,0x11863c6,0x1db6ad8,0x0881ae1,0x11c7747,0x1467182, + 0x1f6d861,0x1d7a29f,0x00966db,0x1d0c872,0x0c38107,0x1cc5c55, + 0x0c4666e,0x1eb5d08,0x09d3ccc,0x07aafc5,0x1b9b669,0x16e27f3, + 0x1f401aa,0x00da506,0x0f72f6c,0x1a0f57d,0x179a441,0x0e63198, + 0x0569247,0x081304b,0x0c23671,0x1863a1f,0x095d823 } }, + /* 130 */ + { { 0x00528a5,0x15ec30a,0x0f21abb,0x14a72f3,0x1268c2b,0x00a255f, + 0x06e293b,0x1db6379,0x182a7d7,0x17d5d86,0x0463607,0x01a29c0, + 0x0ef12c7,0x10e0aac,0x181c5a2,0x1ce7c62,0x0b7e4b7,0x099f214, + 0x0ebb277,0x0ecc6f0,0x035c631,0x1f70956,0x145cbfe,0x02f6548, + 0x10bfbbc,0x0951bef,0x01d07e0,0x0425f0e,0x088f9c4,0x05edf14, + 0x174f73b,0x0ead94a,0x1dc15aa,0x14720d4,0x03b2e40,0x07e6323, + 0x0aeadb0,0x0f0142b,0x13d51fb,0x1aaf0ca,0x00e2708 }, + { 0x1e20f88,0x06629e6,0x00e489c,0x18beb62,0x1338272,0x058edfc, + 0x1867977,0x182a085,0x1b72d74,0x19ef10c,0x0aa9552,0x1516555, + 0x0616c49,0x1dd435d,0x0110f96,0x02d2a01,0x17220cf,0x0f735e6, + 0x026af44,0x1f58d75,0x039d59f,0x1df88ab,0x0a0c485,0x09974a4, + 0x08af2f3,0x0837269,0x1c1c9ea,0x04fe07c,0x017766f,0x03cfb48, + 0x0f9a10b,0x0f50224,0x13469bd,0x0b9dc65,0x0d1a90a,0x1a9181e, + 0x03990db,0x0bc2531,0x059e3f1,0x077f653,0x00d3dab } }, + /* 131 */ + { { 0x029c3cc,0x1bb7367,0x0f1a3e0,0x19e02d9,0x0b0507e,0x1ca670e, + 0x1e65978,0x083bd7f,0x173c50d,0x07e2937,0x1b38f49,0x14a85a2, + 0x014edd5,0x08e098a,0x0def766,0x10c0d76,0x0f2e33a,0x071a217, + 0x018a76a,0x12066f8,0x13312ae,0x122c955,0x15febb1,0x0570af6, + 0x18997d8,0x0bb0d49,0x068cdcc,0x1ad9197,0x06751fa,0x0ef1484, + 0x05a0965,0x03182e3,0x01e97fb,0x0b9abd4,0x084efda,0x13c9e91, + 0x1cb89f6,0x1c3e172,0x0d09a84,0x1d6b0e9,0x0530b4e }, + { 0x0b7b5ae,0x13ad0dd,0x0fd3a7c,0x1a074af,0x1b69dc4,0x0e282dd, + 0x1712a91,0x00592e9,0x1416ac4,0x131b4f9,0x061771c,0x1cf15db, + 0x01735e4,0x06ea235,0x12361e7,0x160540a,0x0699e16,0x1426758, + 0x026c469,0x1edf48f,0x0784f73,0x0fd9527,0x1aa8310,0x1536d2e, + 0x1690293,0x15958fb,0x03c0ea2,0x02999c0,0x0d66c18,0x12adc22, + 0x005932c,0x0612a44,0x194e7d6,0x19138db,0x1390f68,0x13c0a5a, + 0x08b6a4d,0x1c59738,0x15dfd49,0x0a5018c,0x0909425 } }, + /* 132 */ + { { 0x15b4c2f,0x0d0a686,0x127349a,0x16b914c,0x0b8fc59,0x11bea51, + 0x12ceac3,0x0fd2b7d,0x0911103,0x0d0d3b4,0x0d4c8bf,0x00b529c, + 0x1c5810e,0x10bc7d7,0x137304a,0x19cc544,0x1b28e3d,0x02e1631, + 0x114b111,0x187e2f2,0x1161995,0x01a16a2,0x0d4cc3b,0x1df0252, + 0x1a60ab4,0x009d012,0x0a2eba7,0x0a9264a,0x03caf88,0x1303717, + 0x11c9746,0x06c937e,0x04091ab,0x162f8ea,0x1efdc13,0x078fa15, + 0x1d8b333,0x1e8eb15,0x05bd49e,0x0239fcc,0x0505701 }, + { 0x134356b,0x025677a,0x1ef3402,0x0a96961,0x1df1de0,0x1026e0c, + 0x1f8173b,0x1c20435,0x0361b78,0x05ef344,0x034e2d9,0x198fdef, + 0x0ea324f,0x15852f2,0x0cdcb3b,0x0332dfd,0x0b36581,0x177827e, + 0x1ac2ad3,0x1cbaa0b,0x186e7dc,0x0411c62,0x078a6d6,0x1b0006e, + 0x03197bc,0x0e7ef2f,0x05201ae,0x17ebc8a,0x0e67ab8,0x0b45e8c, + 0x0b50cc2,0x1f3ec7f,0x0a7d04e,0x0c5da13,0x048ed70,0x19438fe, + 0x05dce22,0x0dc2411,0x19e7d21,0x0dfaa81,0x08ff0b3 } }, + /* 133 */ + { { 0x1f42cff,0x1717a1f,0x05f267c,0x1a386a6,0x03c19f9,0x10daa2d, + 0x04e4aae,0x065b6e9,0x14afa9a,0x0119582,0x1350da1,0x1a8dafb, + 0x150b855,0x02e7cc8,0x10d7881,0x1443115,0x0c7f001,0x0ebe791, + 0x15020c1,0x1a6b5dd,0x0fcd057,0x0caa9e6,0x0969294,0x1c57272, + 0x0579393,0x013af2b,0x00d08bb,0x0406656,0x053958a,0x002f1d6, + 0x18e6c24,0x0f3d362,0x08051a3,0x10c6b31,0x1027f19,0x1f6941b, + 0x0748e7a,0x0742bfb,0x158fa78,0x1dd8aef,0x071b28e }, + { 0x1726bf8,0x15866cc,0x1cf1250,0x1238411,0x1290a3b,0x0cc7550, + 0x0439ec1,0x051fae5,0x1a25a91,0x153bc8f,0x1f5f6b1,0x1649806, + 0x1b2d33d,0x187141b,0x07bfac1,0x1c54184,0x16ee3da,0x1dfb86c, + 0x141d809,0x1b03230,0x17e343e,0x1426a56,0x12bac2a,0x18b6e98, + 0x1101fe8,0x1eede3a,0x1ab49ba,0x17f654d,0x18aa4ed,0x103435b, + 0x122ea04,0x1c22b30,0x14aa8f2,0x12e2764,0x076cfae,0x141a21b, + 0x0318295,0x1ff623b,0x0496b39,0x034661b,0x0729471 } }, + /* 134 */ + { { 0x0bbd495,0x02c8219,0x1cfff39,0x037ca92,0x130f4dd,0x0e1fa71, + 0x1b87576,0x00800d7,0x059ba72,0x077303c,0x0b1da10,0x1a7e858, + 0x1ec194f,0x14ff445,0x19dac4b,0x0042141,0x1dbec2b,0x18be6ee, + 0x02047b1,0x1a86d60,0x09e4689,0x1b9425f,0x09a9ae8,0x0fa8229, + 0x195b200,0x1a255e1,0x0c3c479,0x119bf3e,0x196402f,0x1f64749, + 0x01717fa,0x1dd68c5,0x0751743,0x0689bc5,0x1e0b1b8,0x07337f0, + 0x1eb292e,0x12f0b85,0x1f57ce5,0x1b0b003,0x0001c39 }, + { 0x04a0912,0x02e5ced,0x1293d20,0x1488217,0x127cb76,0x18eb2de, + 0x12e3bb1,0x135de7b,0x1481684,0x007dd95,0x0918d5e,0x004d516, + 0x08ef6a7,0x0962273,0x1897220,0x0e9502a,0x12c4d7a,0x0312611, + 0x0c58c79,0x0ee06e9,0x1c2e81a,0x18edc8b,0x01393df,0x0c3db2a, + 0x065fd1f,0x11e8e82,0x072f79b,0x0209009,0x131fcfb,0x1060eb8, + 0x0558df3,0x115b48e,0x0e4dbc2,0x0cb9311,0x1172b3a,0x01eea61, + 0x0e28745,0x0b06e67,0x0bc4e80,0x0e17723,0x09132e6 } }, + /* 135 */ + { { 0x196099d,0x1f7f13c,0x0232015,0x1740dcc,0x172344d,0x0ac2c45, + 0x01d0342,0x1d3d695,0x079e5ae,0x09ed783,0x08beb79,0x1535211, + 0x0ac9560,0x083f383,0x12f84c4,0x048d4fe,0x19b2830,0x136af9e, + 0x1f328f9,0x11d1b44,0x1292a5f,0x1326147,0x1ad4772,0x03bfaf1, + 0x0310ef3,0x1f2a67d,0x08b281c,0x05c18f8,0x0da6839,0x0b4a520, + 0x1f040bc,0x0ea1a71,0x0bb07cc,0x1701a8b,0x0f8aeb6,0x1ae07d0, + 0x14d3c9d,0x09e0335,0x03b47aa,0x1caf328,0x07d0b03 }, + { 0x1d94c63,0x1f51826,0x0ce97f9,0x0ae7161,0x17ef01c,0x0735a5a, + 0x09e3285,0x0ed2a69,0x0a53532,0x1b1166f,0x0b40181,0x140ef84, + 0x09af696,0x1ea3590,0x0f06219,0x05694e6,0x0bb626c,0x04b2a66, + 0x013cf13,0x11a7435,0x0b74a09,0x1696b9a,0x0d65be7,0x0aa3920, + 0x1021a5d,0x11fefe9,0x1c7b144,0x0574fa5,0x01aa39e,0x1492d96, + 0x09fe5c9,0x1f1d652,0x0e75d0e,0x09537e9,0x04b8646,0x1df574e, + 0x1b83e50,0x035a1d4,0x1798298,0x05fb56b,0x031b178 } }, + /* 136 */ + { { 0x034db92,0x0dd22a0,0x11361e3,0x031e69b,0x0397790,0x1aa619d, + 0x13cbb7d,0x1111a00,0x0cd563a,0x152caa5,0x1feb47a,0x191376b, + 0x18a29d6,0x186c5ed,0x0b7d956,0x1b68f51,0x02d8cdb,0x1fbfdc2, + 0x034c816,0x1c74070,0x1ca9b72,0x193e563,0x10cd6c2,0x14a8ebb, + 0x00bcbd8,0x12fffe3,0x07ae934,0x06deee3,0x10fca67,0x0e1c062, + 0x000f640,0x1018032,0x1dacf7b,0x0fc268f,0x163d5a0,0x02eb9ec, + 0x1cefbbc,0x13f31a2,0x1b47d5e,0x1ca7c0f,0x06fc0fb }, + { 0x01b0e5f,0x088b5dc,0x0ee125b,0x0a5590a,0x182dd2a,0x19c3f86, + 0x08b50c9,0x0b26afc,0x0ba912c,0x1199542,0x177304f,0x0c8693a, + 0x138b71c,0x01c6c2e,0x060bba5,0x19a9c19,0x13cbf7f,0x1c85caa, + 0x03fb578,0x0737787,0x09032cb,0x0e2d621,0x08b19f2,0x00fb4ab, + 0x01217bf,0x07775f9,0x1682e79,0x0b580b5,0x09e0c65,0x0961477, + 0x0fc42ec,0x09176dc,0x0f3aee5,0x03748ae,0x1a722c1,0x1e95ce4, + 0x0a0e553,0x1330095,0x03f232c,0x1435299,0x0701935 } }, + /* 137 */ + { { 0x0626dea,0x06a0ed2,0x0e7f796,0x142b720,0x05ef66c,0x12732d9, + 0x04290c5,0x19f3350,0x1748cfc,0x1f36d56,0x10bea67,0x0d7a5e2, + 0x167ab9a,0x0ea38bc,0x12e85a1,0x1473749,0x1366bc3,0x1096985, + 0x0fd141d,0x0d4bb91,0x0c0e1f4,0x148a10d,0x0e1a394,0x1774389, + 0x0620659,0x1c83d34,0x1b69a62,0x1696aa5,0x0537072,0x0e6a72a, + 0x17d40e7,0x13d202c,0x0a07a9e,0x02efe21,0x1fcf5f5,0x015071f, + 0x1b5ceb3,0x0c8f2d1,0x0980106,0x1912d39,0x06c961e }, + { 0x0e7eb46,0x1ee0de2,0x0d21c0e,0x0eb2d8f,0x16bac55,0x17eba6e, + 0x05f359a,0x1e69f32,0x1656ce6,0x11aa882,0x05c5d55,0x0a18649, + 0x0d3d1fb,0x11f7fd9,0x099e0f9,0x1457bfb,0x1f3eefa,0x1debcf8, + 0x1ebe7bd,0x1f7ca82,0x17a4a4e,0x112d2ad,0x1b3bd91,0x0e26608, + 0x132381a,0x0d188b7,0x1ee5589,0x165454f,0x027e96d,0x121d058, + 0x0f1a82a,0x0906567,0x18fe5d2,0x1d56022,0x037d6b7,0x14a4683, + 0x049e7f9,0x0d44e5e,0x12d4f01,0x1b0d3c4,0x0830883 } }, + /* 138 */ + { { 0x0557389,0x18e3101,0x02f2566,0x0f5bdf8,0x1fe5ce9,0x1879c1a, + 0x0f9fe0c,0x03d1277,0x116cfb8,0x1f06357,0x10a3f49,0x0cb7a08, + 0x026f64e,0x1bcf30c,0x17a4916,0x02394a7,0x1c1487e,0x1845189, + 0x116f3a4,0x1d87728,0x149e65c,0x0a6b3f6,0x0cef00c,0x0f046a4, + 0x16b2430,0x0e934f9,0x1e4eb4c,0x0f1cbb5,0x00890cd,0x15b863c, + 0x1a7c9a0,0x13c8bdf,0x015c34f,0x1d7f538,0x0e939b2,0x1826ba9, + 0x1e3fcc6,0x11bc523,0x03e310e,0x0ff2cc7,0x02376f9 }, + { 0x0575b99,0x10f6057,0x037029b,0x1f0372e,0x1e14cb4,0x139ca3b, + 0x0e0934e,0x13be014,0x1fb235a,0x1a5ce40,0x18a5102,0x02beb7e, + 0x1a8d151,0x0f0b2eb,0x14d6d0c,0x07c779f,0x0a2b2ee,0x1ae897f, + 0x1460b9e,0x13094de,0x108e629,0x19e1b2e,0x1390f8b,0x1e6dce4, + 0x0709130,0x000cc99,0x03f4d15,0x1316940,0x196dce6,0x1e875d7, + 0x1508f13,0x046ceaa,0x00ba0ae,0x12bc253,0x10b6c0c,0x02a37b5, + 0x015464a,0x1a0c851,0x00a5a2a,0x0c2d7e2,0x08c4616 } }, + /* 139 */ + { { 0x11f36a5,0x0512c16,0x1cb7bff,0x051298b,0x0eded2b,0x076c278, + 0x136e10f,0x1366b4b,0x0db0e3b,0x087c4c1,0x068448a,0x15e00e3, + 0x16cce0e,0x1cd1b16,0x1995f90,0x0fc8fa1,0x15d6269,0x02a8b52, + 0x198d945,0x1c3eef1,0x09bc269,0x05ea813,0x178f7b7,0x038af8a, + 0x0230044,0x1c6f676,0x131c155,0x1707e63,0x089eabd,0x1db98f2, + 0x0d06f7b,0x072bf9b,0x0b678cf,0x0d80090,0x0473fe7,0x112119f, + 0x15f52cc,0x15e37a2,0x0458b2f,0x045698c,0x0155ea6 }, + { 0x16fa42e,0x1178fc3,0x1b9e52f,0x12ff5bd,0x0b5e874,0x0432d7d, + 0x1c3d4e3,0x160d25c,0x0df8059,0x174cdc2,0x09eb245,0x00dd16b, + 0x0b0ceb6,0x16a31e9,0x148cd5c,0x013419d,0x0232a9a,0x1968793, + 0x0187ef7,0x1333187,0x110b252,0x13e0df1,0x1c46222,0x1155bc6, + 0x029c50d,0x19ecd89,0x00ec4d4,0x179f36f,0x029708d,0x037c7f8, + 0x020f29d,0x1b507df,0x1a013a1,0x1422252,0x14612ac,0x151d209, + 0x1cbd4ab,0x14259ed,0x1630cbf,0x0484b20,0x08f570f } }, + /* 140 */ + { { 0x0a9c508,0x1364516,0x1e037ad,0x04d3ad6,0x0dc5bec,0x156b001, + 0x0499a23,0x0282dac,0x149d726,0x0c20dcb,0x1cb9bd8,0x1cd99c8, + 0x1641e40,0x0fd3d43,0x0890990,0x12f415b,0x133cc39,0x022dcfe, + 0x105773d,0x1d1f52f,0x029db25,0x190974b,0x004933a,0x167b2ac, + 0x072c67d,0x0221d46,0x0df069e,0x1c5bda5,0x1027ff8,0x04e336e, + 0x11a52ac,0x0fcf457,0x09a057d,0x063b1fc,0x089b3dc,0x055b17e, + 0x08a2621,0x193473e,0x1307532,0x10f6588,0x03d171e }, + { 0x0e49820,0x160b746,0x1724e0a,0x0581889,0x04ee45e,0x142c621, + 0x1e449cf,0x1f21d8c,0x046327c,0x0c6592e,0x16707e4,0x0ed78c2, + 0x1343e38,0x1baa2e5,0x0db8380,0x068fd6d,0x1ab5d12,0x0b25c1c, + 0x0c03550,0x0124e94,0x116972e,0x13440e0,0x09aaca3,0x0eb5086, + 0x00fffeb,0x06fa52c,0x08d6448,0x14b0059,0x09f4a30,0x0168190, + 0x001ffba,0x11cd527,0x118016b,0x108e55a,0x11c30bb,0x0f7338d, + 0x0b9d4ec,0x082d78d,0x0401058,0x1f0699b,0x0234e98 } }, + /* 141 */ + { { 0x0db9cda,0x1a9040a,0x1243fd0,0x0f2d5bd,0x19cfdc4,0x02c5b6c, + 0x0a9bebd,0x0630875,0x1743eaa,0x18fba0a,0x0d7604f,0x125cc2e, + 0x15915e1,0x0562cae,0x10688b4,0x1791a68,0x167c044,0x13825df, + 0x188e88d,0x0c08e37,0x15572f9,0x040ae8e,0x130c98e,0x163bb29, + 0x0230b76,0x133ca08,0x1c30722,0x05ca873,0x1c910df,0x00d6419, + 0x17d5ac5,0x10cb709,0x07c999f,0x015bda3,0x07e887c,0x003604a, + 0x1621695,0x0da9304,0x07a4f79,0x1c79c74,0x06a2130 }, + { 0x13ca1a7,0x1b3d025,0x1a03486,0x0601819,0x0f42ed5,0x16783d5, + 0x14da24c,0x0b44599,0x15c25c3,0x1291d40,0x013418d,0x12b11ba, + 0x1becdd3,0x197c9d1,0x168d40a,0x16a60e7,0x03cd5e5,0x1a62f06, + 0x0c9a1dd,0x1ea90c2,0x0292ef9,0x1e0f3a1,0x1b61ffb,0x09cbdbd, + 0x0c29ea2,0x18d36cd,0x00ce127,0x115793e,0x1239050,0x1149207, + 0x14ec26c,0x0ff2686,0x191072c,0x15aa833,0x0e079ab,0x002054c, + 0x16feb87,0x103a04c,0x0a0c0fb,0x155389a,0x034f06f } }, + /* 142 */ + { { 0x148f005,0x0e3cf91,0x02c61a7,0x03be924,0x1b5c5d7,0x1732524, + 0x15f29b7,0x169fa36,0x0e82a4f,0x0dbfb9a,0x1e0d988,0x106972a, + 0x16637cb,0x1e943ec,0x0d0406d,0x1d95792,0x0ac0392,0x18ac87c, + 0x1dd7d38,0x1b86e6f,0x0c62280,0x07b530d,0x02cdbd4,0x0aad1b5, + 0x18304a6,0x1853a7a,0x0764c21,0x01af255,0x0895cc8,0x18c97e4, + 0x07db45e,0x0922927,0x18392fa,0x0adcf24,0x09f7507,0x0b5e6c0, + 0x1caa82b,0x16bcf12,0x1746914,0x163e822,0x0764d47 }, + { 0x0ee8b9c,0x11181d1,0x152177c,0x070bbf9,0x1b9f72d,0x009d1b8, + 0x0e60c42,0x1ead685,0x13de741,0x146291d,0x0eed6f8,0x04b5e60, + 0x0f08576,0x164dfcd,0x1bca66a,0x0b66924,0x0080d44,0x110df56, + 0x1ae8b03,0x047405a,0x08646a5,0x18bfe71,0x18c0a86,0x00183d5, + 0x0a235e3,0x188a28b,0x09ed2a4,0x0a86e6d,0x0c89f74,0x1cf4606, + 0x17b4f02,0x081db11,0x081904f,0x1fe3802,0x0d58f2d,0x109e4d3, + 0x121b973,0x10ea9d1,0x0e04026,0x1864614,0x01c0dd9 } }, + /* 143 */ + { { 0x06a7d9a,0x10fb3e2,0x0733fea,0x097dbf2,0x0474333,0x1217973, + 0x0e9d11e,0x1528b06,0x1241ffa,0x1cc0028,0x1bf9ad9,0x150866b, + 0x0370979,0x1845920,0x0184fd7,0x023b8be,0x1cd64f2,0x035d917, + 0x015cb3f,0x1165474,0x014ae1b,0x00bca85,0x06783ad,0x16d9a98, + 0x0bb293e,0x0fff31a,0x151c289,0x0340964,0x115a0a3,0x1d64d1e, + 0x1a6907d,0x17e5fdb,0x1ed85ec,0x0a50077,0x1d7e06e,0x183eb03, + 0x1ef4a15,0x1ccb584,0x106f2a8,0x07360c0,0x052d8be }, + { 0x1631a2f,0x09b7b7e,0x0372f45,0x0166a35,0x11fae7f,0x0931094, + 0x0431e6c,0x06ba34b,0x12bd0f4,0x16a43af,0x03a9c14,0x0da7256, + 0x1e9aedb,0x1c1d5c4,0x142af72,0x0325817,0x06289fe,0x1413d08, + 0x00a82f6,0x0d52c02,0x0814656,0x1be701b,0x16820c0,0x0c7280b, + 0x0d79f58,0x0fc985f,0x1b6f2a3,0x0e40336,0x1aa3f59,0x094377e, + 0x04a2480,0x0a46d71,0x137b996,0x01739d9,0x0e38a3f,0x0623a7c, + 0x080e8da,0x1c3fa0c,0x09175c1,0x0cfb5c9,0x06cff63 } }, + /* 144 */ + { { 0x09a8bb4,0x08219fc,0x1dc6f4f,0x0727731,0x02144c3,0x038516a, + 0x05b200d,0x13d056c,0x1e5da08,0x07e63ab,0x17f69a6,0x09def7e, + 0x0c54235,0x0f5e9a6,0x017094e,0x1ba1a31,0x085bec5,0x1171059, + 0x00a86f2,0x1777c2f,0x0ef0e71,0x184dc2a,0x05677b4,0x12ff4d5, + 0x0997989,0x0228b92,0x03607cf,0x019f1f5,0x0111525,0x1a8bb06, + 0x1aaa68e,0x1d9f08b,0x1b0ef7d,0x1688de4,0x188ee7f,0x0192673, + 0x0825608,0x1f4e2e1,0x1079f24,0x02ec27d,0x01d2c82 }, + { 0x07cfc93,0x09a3ecc,0x0041ce0,0x17e30ff,0x047603b,0x0865188, + 0x0f27449,0x1e67f4d,0x0bb055b,0x00048f0,0x0be1f12,0x1e34747, + 0x0bbdf95,0x0a02a05,0x1a1ddc0,0x008b7c4,0x130d7fe,0x0ccc6fb, + 0x1c8ef0b,0x1026bf6,0x0c46b39,0x060af5f,0x0b08c3e,0x0aac381, + 0x018305f,0x03ff047,0x1369829,0x181f7e9,0x0d4bfc7,0x0e1270b, + 0x0481ba5,0x0e8c2fd,0x0163495,0x061073a,0x01a52b8,0x0c72e33, + 0x0131e2b,0x1349891,0x1dc8bf8,0x06c14a6,0x025486e } }, + /* 145 */ + { { 0x1572806,0x1cae529,0x0385861,0x12cad2d,0x12c8944,0x1991d75, + 0x0b25cfe,0x1ac2938,0x0409bc7,0x18aef13,0x0486cfe,0x14e58f2, + 0x1ba90cd,0x102655d,0x0be8538,0x0824ada,0x0f79160,0x1e5e6d3, + 0x10d7e51,0x10c4c36,0x0b10250,0x1c61417,0x16da1b0,0x14f2397, + 0x16d62f1,0x1362880,0x0586889,0x1638fda,0x1d74a66,0x0333138, + 0x09099e0,0x104850f,0x1ffeda1,0x07879da,0x0ffeef9,0x0997ca0, + 0x19482a7,0x1bf85f5,0x04fc75f,0x0b01109,0x0751b23 }, + { 0x1c9be68,0x1dceb74,0x11b3565,0x08cfa21,0x1794b5c,0x11597a0, + 0x170f5dd,0x0235119,0x0a1b44e,0x0ca531d,0x03b2a1b,0x1773555, + 0x1ffb0bb,0x04b1ec3,0x0c3cb43,0x00ebbe9,0x02c5dc7,0x0dba983, + 0x064ce62,0x0e4d589,0x0cdefed,0x1c2bfce,0x1769818,0x1f18ecc, + 0x0392a75,0x165110e,0x157719c,0x1a4c9b2,0x0ecc8dc,0x1f915b3, + 0x0e9c013,0x03148b1,0x11aa9ae,0x1eb29fd,0x137e2ea,0x19d52c8, + 0x0ba0de7,0x1bc7401,0x1b1d6a4,0x05b9458,0x0144cc1 } }, + /* 146 */ + { { 0x189aa3a,0x1050e94,0x193564e,0x06b3cdc,0x183f228,0x1739976, + 0x0c32f4c,0x093d271,0x13c3cb2,0x0623262,0x1a9ab3d,0x0bf1f13, + 0x129750a,0x1a367e1,0x1f96efc,0x170128c,0x19d37b2,0x0e4dfd5, + 0x0cce71b,0x16e8a67,0x0deef8e,0x1f1dbb3,0x0ff807e,0x0d5d44e, + 0x14254ef,0x188598a,0x09ef986,0x0ab87be,0x0184885,0x16c0eec, + 0x1e5c3ed,0x177ce29,0x01af3a4,0x07b49ed,0x005e746,0x12aebe4, + 0x0465b83,0x047e359,0x0a54770,0x066d709,0x0874ecf }, + { 0x1b3f6be,0x17c1f5d,0x08f5892,0x1211768,0x1578fbb,0x039a93f, + 0x0c2eb5e,0x084ac47,0x0a62e04,0x1b2cdec,0x0dbde70,0x02cffc4, + 0x062903b,0x129f935,0x090c31b,0x0259eab,0x1ae3ad7,0x19112a3, + 0x1bac9ca,0x1121aee,0x0df9b73,0x059eb14,0x056d3dc,0x1d5c959, + 0x013b053,0x1a74f87,0x039fc85,0x169ea27,0x1bae175,0x167ccc6, + 0x001d520,0x088a309,0x169bbde,0x178ae15,0x194b2bf,0x129e4f2, + 0x16bcaf1,0x11f795d,0x18d3e82,0x1039c98,0x031fb85 } }, + /* 147 */ + { { 0x15cd607,0x18368b0,0x0e98e60,0x1554658,0x080c9fa,0x1c898eb, + 0x1c16ddd,0x001d0f4,0x036708b,0x018809d,0x14a5fc4,0x01c3288, + 0x16814fa,0x1353cda,0x11560ea,0x17da8e1,0x0bf4b16,0x18181ce, + 0x0aabe34,0x0f951b5,0x08a518a,0x13ae6db,0x1ccc567,0x07029f5, + 0x0e738d2,0x1cfef50,0x02343d3,0x166a4e3,0x1ff032e,0x1304ee6, + 0x02ec2dd,0x07a9067,0x1ba8ea9,0x0a83d32,0x1609577,0x0830089, + 0x0a4a50b,0x05111f2,0x0795211,0x00031c3,0x0983230 }, + { 0x1f3d5a6,0x10813ab,0x1734a28,0x10dd195,0x1fce564,0x0a8f9df, + 0x0e06c09,0x1e32b20,0x1935ebd,0x1366327,0x0ea9bac,0x0523810, + 0x0160611,0x047267a,0x062299a,0x1636b9b,0x173dd53,0x0ac0e1f, + 0x1ff1887,0x100952e,0x02fa78c,0x187d6e5,0x0c61d0c,0x0799e04, + 0x08da4c8,0x183fb80,0x169e691,0x0824543,0x115eb5c,0x069fa54, + 0x1826a38,0x1a0246c,0x0de157d,0x1695051,0x0ec997a,0x0a8bde8, + 0x188db28,0x11156f0,0x032ab42,0x13d245c,0x08abbe3 } }, + /* 148 */ + { { 0x02d2f01,0x034829d,0x0172d11,0x06bb8cd,0x127c319,0x1a5013e, + 0x02efc75,0x03ad521,0x15b50ec,0x0ed1a87,0x10b8980,0x08bc7e7, + 0x121d3dd,0x1c1b774,0x1b84742,0x12f39ec,0x08f474b,0x03f01c8, + 0x02e1e0d,0x0f8b733,0x1de919e,0x1f5e9e8,0x09d074f,0x1ec0b37, + 0x08e8d1e,0x123b1e3,0x04d9d38,0x173ff27,0x1e67f69,0x09f39f3, + 0x12075f5,0x15dd3c4,0x18dc326,0x0cc2634,0x1b6acef,0x0ea5e47, + 0x0f8fe8a,0x0f18d83,0x0ea57e5,0x1a187a1,0x00f15b4 }, + { 0x10a8d85,0x1b31abc,0x0bc63cb,0x1dc4b2b,0x11bffba,0x1a8943a, + 0x1fb1892,0x0bba2b6,0x1323471,0x11cdb55,0x151075d,0x0532578, + 0x130cdd5,0x1b682c1,0x0003a93,0x1c6c0a9,0x152f6d6,0x190f7eb, + 0x04a4184,0x0fffca3,0x18cdc0b,0x12f7544,0x0da2960,0x13044cd, + 0x1ba9222,0x1d97676,0x02ef41a,0x0f15236,0x16b0cb6,0x16e025d, + 0x062c90d,0x195f1d5,0x17a99e7,0x102dde7,0x19b9c6a,0x03725a1, + 0x15993eb,0x068238f,0x1776efe,0x0f04070,0x0515db3 } }, + /* 149 */ + { { 0x15bef22,0x1f55537,0x1c4bb90,0x1040690,0x152d269,0x1d7b634, + 0x12139e8,0x0063c98,0x09a8c94,0x06a1a63,0x0626686,0x0e82a00, + 0x0c63e5d,0x1f47520,0x0e36ef3,0x10e42a4,0x0d29679,0x0653664, + 0x12b2f7a,0x16d5dc0,0x13ce73d,0x06dbfcc,0x0fda4ca,0x08bc669, + 0x19bbfad,0x11851fb,0x0df07c5,0x18a3d92,0x00a6de8,0x192fcd8, + 0x10d241c,0x025b057,0x1e6acb4,0x0cfe4a4,0x0db43b1,0x16b2036, + 0x1cf34e3,0x04db884,0x1300b2c,0x0fc357e,0x02de048 }, + { 0x1d9d484,0x19179c6,0x0b3062d,0x06f8ef7,0x0334939,0x0c95c54, + 0x0e3c64f,0x04ab1b7,0x08e3fac,0x06bc6a8,0x1d29f60,0x1302e8b, + 0x1df0500,0x03be614,0x1caffb6,0x113f1a0,0x0f2c30a,0x1b3d5fc, + 0x0820835,0x0acfd53,0x173892c,0x17451d2,0x1096ac4,0x0aaa436, + 0x0faebf0,0x0f4e0b1,0x1ae53a9,0x1c389e4,0x11e546e,0x04ca1eb, + 0x0747905,0x087d17c,0x18183b8,0x1570592,0x120bbe7,0x008922f, + 0x13874a3,0x09d22bb,0x1e1b9a0,0x0e39885,0x06f6ac0 } }, + /* 150 */ + { { 0x1d6e3b1,0x01156a6,0x01a74e2,0x195ac41,0x1c78e1c,0x166f407, + 0x0e114b2,0x1c7cf08,0x0a8469f,0x10e60a5,0x1a3bc84,0x1b4fccf, + 0x088e8f3,0x069a3a2,0x00f45b9,0x063e9b7,0x1987986,0x19dd0ee, + 0x0931305,0x16b2ee1,0x101fdfa,0x031f6e3,0x07c284c,0x1b1fe50, + 0x1d6016c,0x1e4a324,0x0ef3156,0x04ce461,0x00412a2,0x0e302bb, + 0x1d80a86,0x0651f5d,0x119d5f1,0x1556ce3,0x1a7bd9f,0x0a4f972, + 0x119bafb,0x0129873,0x00b2fcd,0x199feb5,0x06e2c24 }, + { 0x1af8793,0x18125d6,0x12398c4,0x0206b92,0x144bccf,0x1a805fc, + 0x19ade54,0x0cbd340,0x01d1167,0x0c8d4a3,0x04f1e1e,0x165d3fb, + 0x1595add,0x14972a4,0x14b00df,0x1cb9e0b,0x1189f03,0x1658a2d, + 0x16a87dc,0x1c91952,0x0e4f81a,0x0109ad3,0x080fc9c,0x1654faa, + 0x0f5a249,0x15195e7,0x000b5fc,0x0d0f520,0x0745b00,0x1914363, + 0x014bdf4,0x10ca0e6,0x1a8a875,0x0e2c79e,0x0210ba3,0x0b7c717, + 0x1bf1118,0x045f9a6,0x03e45ad,0x01b2f81,0x05af7fd } }, + /* 151 */ + { { 0x0a224a5,0x0dca87a,0x1ce957e,0x0998a04,0x0190457,0x1f8feaa, + 0x04cc190,0x10669f0,0x10e50f7,0x0b400dd,0x005c4a6,0x080712b, + 0x16866d7,0x12048e9,0x0690176,0x0dfcfb7,0x1df16a4,0x078f1bc, + 0x0efe45a,0x09527f0,0x0bca8d0,0x1a99590,0x0b9320c,0x0543821, + 0x134b1f7,0x0da4ce9,0x1f60657,0x1f7932e,0x014b5d8,0x1efffdd, + 0x1db2bac,0x0edb5e8,0x0fef022,0x1b97a30,0x17fb6d6,0x0497291, + 0x16dfb06,0x02e492d,0x152b946,0x1032c13,0x027a9c3 }, + { 0x12a93af,0x1b9a378,0x0d35cf0,0x18aa6cc,0x028b707,0x00c9e88, + 0x1635526,0x13b1df4,0x0ef21b6,0x1c1d2e6,0x0283893,0x01474f1, + 0x1805cbb,0x12d89e4,0x00c5e05,0x0f09802,0x0582b73,0x17f5107, + 0x140d87c,0x0e2741c,0x02d9df9,0x07e8661,0x0c51268,0x0bc5c36, + 0x152e77c,0x0678c1b,0x16d9c11,0x1c89ad7,0x1e177a6,0x0f4ab99, + 0x08c04b7,0x011dc58,0x0b49669,0x18ca4b4,0x15047d7,0x1fb3760, + 0x0acd886,0x0c1638b,0x0491254,0x129f7bd,0x01c6906 } }, + /* 152 */ + { { 0x0880026,0x13e8b9d,0x17c976d,0x0024bb2,0x09c4f0a,0x165bd24, + 0x01544fd,0x14a520a,0x15cbbdc,0x15918e8,0x0f2f4cf,0x19332e5, + 0x1af8cff,0x16aad01,0x13bd352,0x0f85f96,0x1ca2286,0x0ca26a3, + 0x1ab46a9,0x110a901,0x104596d,0x1c65e45,0x1da95f3,0x0bcab40, + 0x1844b00,0x04beff2,0x0474628,0x1d3cfc3,0x123c745,0x1374294, + 0x0e655e8,0x0febb66,0x0867b79,0x1686468,0x02398ef,0x184aa68, + 0x089ad23,0x0b72eab,0x10ce456,0x1ad4a09,0x07b8c13 }, + { 0x0fb6901,0x01d56a9,0x14ecbf1,0x122d944,0x1c0313f,0x0d56e30, + 0x00c2945,0x18428eb,0x07f577d,0x09e8c93,0x0f03772,0x1d1dee4, + 0x1a26e52,0x1f5cfb6,0x0783ae0,0x06eda5e,0x082f180,0x0ccbcef, + 0x020d24e,0x051d976,0x18e743e,0x0e51ce1,0x068b547,0x1c7ed6b, + 0x063a9a8,0x1383730,0x092e6cc,0x19e3b47,0x18915d4,0x0451697, + 0x049b94d,0x0a0a0f2,0x075e3e0,0x1c1fd2f,0x195c834,0x135dff9, + 0x0fd2fb2,0x16a9e64,0x1334075,0x1ecd2de,0x00e3c3e } }, + /* 153 */ + { { 0x1ee1d83,0x19be090,0x1e20ef0,0x1af0f6e,0x17e08f6,0x07d2674, + 0x07f304e,0x0b17ee1,0x1a0348e,0x17bbb23,0x199cb6e,0x15794ab, + 0x1d04f8b,0x1eaf62e,0x14a4675,0x124301d,0x1ff33e9,0x1c67325, + 0x12c166b,0x13f8ae4,0x12baac0,0x1cee2f1,0x141a0c7,0x0b5ed52, + 0x0267746,0x1fc1351,0x1b25fc7,0x18bdfcc,0x0087fd3,0x106b5e3, + 0x1ac5457,0x1551db8,0x1a39c5e,0x0f694d8,0x1aec39e,0x107bb02, + 0x1c3788b,0x009bb4d,0x09471b3,0x1c78125,0x0463098 }, + { 0x0bd0fa7,0x00463e4,0x1924e99,0x039cd7b,0x1176431,0x1f7bdf6, + 0x18420a0,0x071c62b,0x199b5d9,0x109e63b,0x1269ae0,0x0b028b4, + 0x11af7f1,0x1294f26,0x03f6c3f,0x193ada0,0x177ce66,0x12ae9c7, + 0x0f52e54,0x0f99803,0x1986b4f,0x04d7b8f,0x0365d6d,0x0c9a015, + 0x19fcbcd,0x16b895a,0x12968ee,0x10c1ca0,0x1c89f11,0x102215a, + 0x07db65d,0x0f47c46,0x0d0c659,0x05d497f,0x10cc5e3,0x1cb0229, + 0x0698e11,0x13a6033,0x0e16b8b,0x1274691,0x07f8fd0 } }, + /* 154 */ + { { 0x19428af,0x0c96560,0x1997c91,0x0274610,0x192a1c8,0x05debf8, + 0x0604b8c,0x17284b1,0x1836c6b,0x06d8391,0x19261c4,0x03d2b31, + 0x0b9c7a4,0x1756b7a,0x1fc5e79,0x0588915,0x1b97586,0x1387c7c, + 0x1c8660f,0x16046ed,0x11526b3,0x0dcc732,0x09760fa,0x0a24314, + 0x126a8d7,0x0d31d96,0x0a75bc7,0x0a10503,0x081f749,0x0682d2d, + 0x1c637de,0x1c8d0e8,0x19ee559,0x1ec666b,0x095d9e1,0x0a40c19, + 0x08476c9,0x1d427fd,0x144c509,0x0a3cc86,0x087b64c }, + { 0x130d3c4,0x037b2a5,0x1c521fd,0x184769d,0x0dec4c5,0x0526b46, + 0x11d998f,0x0db676e,0x1cf3fb5,0x0f9a134,0x1f51a87,0x13881fa, + 0x1dd4f13,0x1534d45,0x0df1f1d,0x1afa547,0x0c9cbad,0x0772b5a, + 0x12508cd,0x1fe6855,0x1da3b28,0x1d3c378,0x0011bf7,0x001905c, + 0x1149cb7,0x0cbe72e,0x0542599,0x1461df0,0x1f4bddc,0x0304fe7, + 0x1a11288,0x08924a4,0x12f65e7,0x10f9c07,0x14b3500,0x01cb6ca, + 0x042dbbd,0x154e150,0x18bd5df,0x0f9b380,0x08c9526 } }, + /* 155 */ + { { 0x1c1abb1,0x081972f,0x1d0d995,0x0825fc8,0x0215af5,0x182f7a9, + 0x1d580a7,0x1d3faca,0x1dc191b,0x0739992,0x18e6c2c,0x0cbd810, + 0x137ab3c,0x0e1f333,0x141fd44,0x0aaaace,0x1c3c861,0x0b1c5f7, + 0x0bc312b,0x03119e8,0x186d5d0,0x0e6c4b0,0x010e8c0,0x18ce83d, + 0x003f7b2,0x0e8022b,0x13e8f34,0x0ea8b81,0x00672ef,0x17fea52, + 0x177d84a,0x08b73d1,0x0197c9f,0x116ba2b,0x0df61e4,0x1f68a64, + 0x0b2d59b,0x09971d2,0x1a85afc,0x0e77094,0x08afa1b }, + { 0x193ac70,0x0cb7573,0x1441acd,0x1dddedb,0x0c94ef8,0x0117202, + 0x13e89c1,0x0c724d6,0x0e9e5d7,0x0638ee7,0x0aab7f2,0x16e1ea2, + 0x1f352fc,0x1441cba,0x1ee84e2,0x0762636,0x190058c,0x0abcc89, + 0x1dd03f4,0x0412552,0x0697969,0x0d8b058,0x066b651,0x106f564, + 0x1438810,0x1b8de31,0x13c5d2e,0x0ddc238,0x1b80eb7,0x1fe0d58, + 0x0298446,0x0e1d88b,0x082bac8,0x09992de,0x049cc4b,0x11ddcc0, + 0x1240adc,0x08c58d5,0x024f2d0,0x12256b4,0x0672111 } }, + /* 156 */ + { { 0x15cf9bf,0x0c9837a,0x1b6647a,0x1148d72,0x1b04530,0x1d32efc, + 0x0787679,0x1775c78,0x1c731bc,0x09e58a8,0x1629851,0x044f49a, + 0x0214be5,0x0be3a66,0x16b248a,0x001ac73,0x045822e,0x1a687bd, + 0x18ac0f7,0x163aa38,0x0b2dafe,0x125d50c,0x0ec770e,0x056e9e1, + 0x07178df,0x119bf9e,0x1a25ada,0x19a6514,0x0e055ff,0x0a2a0ee, + 0x01fa57b,0x0d49c57,0x1fbc76b,0x0ee74cb,0x1fc7e96,0x03cbd8c, + 0x0c0367c,0x11b4566,0x08ff814,0x02ca9c9,0x07c8639 }, + { 0x07388cf,0x0a5af65,0x14e157a,0x018066b,0x17cc0a6,0x17c2dd0, + 0x0de2d85,0x10136d3,0x1101229,0x02e8177,0x1429e5c,0x1d0039f, + 0x12565a6,0x1e8f71a,0x1d2a5b5,0x13b5bd6,0x0ed427b,0x1ae4419, + 0x1b54cc3,0x150a51c,0x0ee896e,0x158c692,0x0c36218,0x1f273ee, + 0x18ed59f,0x1294e69,0x0804180,0x121f934,0x03b3ff6,0x045c118, + 0x1a718b6,0x1baa568,0x042d7a4,0x096c9fe,0x1e8a32b,0x100df1b, + 0x0092043,0x11b0483,0x156b540,0x0b1f9d0,0x0325827 } }, + /* 157 */ + { { 0x19e8c60,0x0722f9a,0x061bac8,0x0a6c994,0x071bb8a,0x1c70886, + 0x141c77f,0x0f00562,0x14c93e5,0x1a748e9,0x0743601,0x1c01705, + 0x1ac0326,0x113541f,0x0648961,0x1413c78,0x0d5fb29,0x11c3d32, + 0x16b1720,0x147a69c,0x1a29caa,0x12d6d16,0x03b5a17,0x052ca1d, + 0x00267eb,0x179c939,0x05d8e00,0x0e30963,0x0b1aeaf,0x0e876fb, + 0x1748fd7,0x04bcc24,0x01fa347,0x1950d5f,0x1e74321,0x1fac50f, + 0x0c57c3a,0x1549e95,0x1d95926,0x0e2b7b4,0x01a4e6a }, + { 0x14d1267,0x1376f2a,0x0d20684,0x0639a05,0x17f9453,0x18fd8e9, + 0x1c13338,0x025ae15,0x1097dc0,0x1a08585,0x1edb173,0x1a2e6d8, + 0x05930e1,0x0344884,0x0bfb907,0x0c71f20,0x0a779fb,0x19a4dd2, + 0x135be37,0x18b0435,0x0acea16,0x009703b,0x1ecee0f,0x003a29b, + 0x1033be5,0x16d35c6,0x0883cb4,0x0b27a8a,0x1f18800,0x0936cce, + 0x098dd49,0x13fd667,0x032351c,0x17a2b65,0x0ef07db,0x15b2268, + 0x15b9dc8,0x042bed9,0x1a0cb1d,0x1270b69,0x0856a7c } }, + /* 158 */ + { { 0x10a5583,0x1e80106,0x162a801,0x1bdb48c,0x0f1301d,0x0c9cdf1, + 0x1e590d3,0x06d2380,0x0a70c08,0x065b3c0,0x0795028,0x1f2b7d0, + 0x18c0b4d,0x0ea5645,0x0ef34d1,0x0c472d9,0x0d05475,0x12be297, + 0x00173ad,0x05b9483,0x0255cac,0x15bc9a2,0x0457b9a,0x193454d, + 0x1ef3124,0x13a1b36,0x1e304b1,0x1a772c5,0x1b7c3bb,0x078dbed, + 0x16eaad9,0x1c45772,0x00e4553,0x11dba1e,0x1aeb131,0x024811f, + 0x0a4da63,0x13b9891,0x16900f2,0x1098c6d,0x0628890 }, + { 0x0b8d208,0x1fea9c6,0x1b52915,0x12a87e0,0x1a8f800,0x17f955b, + 0x18553cb,0x1cf6cdb,0x1f72517,0x0ed9475,0x0274b3f,0x1ccdf27, + 0x0e0149f,0x0c2dc46,0x1a1dcff,0x087eef3,0x10b0ba5,0x0229704, + 0x02c0ff0,0x136b9f6,0x177bdeb,0x05362f6,0x0c44d12,0x1f806e4, + 0x1f3cf8f,0x0251b04,0x15706d3,0x179388d,0x059be92,0x1df9c7d, + 0x04799bc,0x19b604d,0x196bf5f,0x1c47c89,0x0750027,0x07e3d8b, + 0x0ad9dfe,0x081a2b1,0x135630a,0x058b5b4,0x079d812 } }, + /* 159 */ + { { 0x0529507,0x0726755,0x1400535,0x08e8cab,0x056a081,0x07e23a0, + 0x028e13c,0x11d81a6,0x03443cb,0x14101f5,0x05ca362,0x1f612fe, + 0x1233c62,0x1a9077a,0x0e373f6,0x13a7d14,0x15d7cac,0x0507c86, + 0x1cf3a94,0x0f617f0,0x01cb28a,0x1d36362,0x14456b8,0x0702583, + 0x171daa1,0x03f51a8,0x1589354,0x0ba9774,0x18f42f2,0x0944bf4, + 0x1c6476b,0x12d4826,0x1d6b1e9,0x12dbbff,0x0496da7,0x0fa8d84, + 0x00c4f70,0x095a121,0x155eb1f,0x12b0284,0x02ab3af }, + { 0x05372a6,0x103a635,0x0e9e1b2,0x1cac525,0x128fb83,0x1a0e7ab, + 0x05b71dd,0x13ae8ab,0x1520ef4,0x05a6750,0x1191c9c,0x1c68c3c, + 0x1d1472f,0x1fdc562,0x15af598,0x180e3e9,0x0c9c10b,0x0a37296, + 0x1c68d18,0x129dfc6,0x0877287,0x0c13b7f,0x092141c,0x1deb569, + 0x157739b,0x00af6d6,0x1cfc572,0x0985b3f,0x0395c32,0x0872c7c, + 0x1546225,0x1016d50,0x0e40996,0x001f0dd,0x08b22a2,0x1c9ea7c, + 0x039d25e,0x119fb08,0x0272abc,0x06a4a08,0x007db2c } }, + /* 160 */ + { { 0x17d4703,0x1dc6d81,0x02e71fc,0x1f8be91,0x083708d,0x18ea017, + 0x00c3e11,0x1d23f75,0x05a2faa,0x0af7469,0x13f07a9,0x1e20a80, + 0x11c2e5b,0x1516ab2,0x1f5409e,0x1ebf2c8,0x00c7eba,0x19bd29e, + 0x16cc2af,0x1e17652,0x13ba7ad,0x1f6b264,0x1698b87,0x1de94f0, + 0x018c0e2,0x027bffe,0x0534b34,0x073bb3b,0x00af021,0x1d5baf5, + 0x13c94fe,0x01fdf35,0x08100ea,0x0ad53be,0x0137218,0x12e98a7, + 0x1fe5206,0x143416c,0x15d672c,0x11f9efb,0x008b6ca }, + { 0x16c3b5a,0x12df501,0x0d2f813,0x04ff3e5,0x1872610,0x1cbe079, + 0x095c0a5,0x14753f9,0x182879e,0x12b0c05,0x1c377c5,0x1376c0f, + 0x0715338,0x13d8704,0x08488f1,0x0ff8f33,0x0ec9d89,0x0868c04, + 0x05bb7c6,0x00e2352,0x1118947,0x158390b,0x1e3d4bc,0x111116d, + 0x129ffd1,0x0802ec5,0x15331be,0x1e3c458,0x04877fe,0x10b2f59, + 0x097100d,0x06a8f2a,0x1a95233,0x0a3457e,0x1085a18,0x11ac454, + 0x14faba0,0x021d83b,0x09f4974,0x0041a63,0x02c337b } }, + /* 161 */ + { { 0x022fa65,0x182de75,0x18e9ec8,0x09a2b3e,0x1e183ef,0x1ac91fd, + 0x161f4fc,0x0a668e7,0x0c11d77,0x13fd983,0x1533fec,0x1cd6540, + 0x19702e7,0x178c2b0,0x1a7e5f2,0x0a38a79,0x0434e7d,0x1c1aa81, + 0x0d5ab16,0x1c7b05e,0x1131a63,0x156bb22,0x019edf2,0x0e3f93b, + 0x1e6afa6,0x0bbf742,0x18ac1f3,0x1730bdb,0x1a51933,0x0c587fe, + 0x0d81f56,0x15285b8,0x10eca39,0x10c54d8,0x13b9418,0x142fe7b, + 0x06b7d5c,0x0a74688,0x0c724f6,0x069db10,0x0509b26 }, + { 0x0caed54,0x0a0a724,0x1a5ec6e,0x1997ea3,0x17a78c6,0x14d92c3, + 0x0323537,0x0f148d1,0x091ee3d,0x01209be,0x1b99300,0x0469c61, + 0x18a68f9,0x040c86b,0x0c956f2,0x0d216ae,0x05fba80,0x020f470, + 0x10d53d3,0x071b09d,0x0816500,0x0b6fd29,0x0c63c0b,0x16c7fb5, + 0x19007cc,0x02ae23f,0x0fa62b9,0x13a901f,0x0e319d2,0x0e912e8, + 0x0652b11,0x004db6e,0x06f3575,0x0c3dce8,0x1880b0d,0x0ee6773, + 0x0c31772,0x041cc91,0x01d4889,0x14ea977,0x01592d5 } }, + /* 162 */ + { { 0x17453f0,0x06cd167,0x07c15de,0x15db078,0x0ffb899,0x1415d3d, + 0x01b4f82,0x1035cca,0x0ea3d50,0x164270d,0x0a8e2cc,0x1181021, + 0x019ad52,0x1e9be82,0x1f6c082,0x1c83f63,0x1e1d06c,0x13c6b65, + 0x19d2dfd,0x0fe1e05,0x1022d28,0x1ae21dd,0x1d73495,0x034e367, + 0x0f2f3f8,0x1fa3694,0x1718cf9,0x0cb763e,0x1c580ee,0x1e0e627, + 0x094cb97,0x176f60f,0x155539f,0x1579d66,0x11c70f2,0x1b6b528, + 0x0cc22d2,0x0c5efa2,0x1ddf2e5,0x17aef44,0x01614bd }, + { 0x10ab04d,0x1811876,0x0ba9307,0x00dc410,0x0e347b0,0x162dafd, + 0x0f18f10,0x06b3e21,0x1de0199,0x029cf37,0x142096c,0x09cecbb, + 0x16d89bd,0x1de76d0,0x0983fbe,0x1946524,0x15ce62a,0x1c5553a, + 0x1b20b17,0x0c5f52b,0x0768ed7,0x008c328,0x0679930,0x05c6919, + 0x16245c9,0x0b42bee,0x1cc7a9b,0x1b7114e,0x1447360,0x095583d, + 0x1fbbc00,0x02e3ae1,0x1356b94,0x048d85c,0x18a00fe,0x05cd160, + 0x179c20a,0x0a529d5,0x01ca0e9,0x18f6016,0x0489656 } }, + /* 163 */ + { { 0x1353c25,0x124dd38,0x189390d,0x0227ecf,0x117f27a,0x0f5cf1a, + 0x0cce870,0x1f2217a,0x078e29b,0x070e02e,0x0fc5765,0x1b2e8e8, + 0x1084fe7,0x086d16f,0x01d2422,0x077c339,0x1a75367,0x0c1201f, + 0x0eba86c,0x1ebb683,0x0ead7eb,0x1a920c0,0x13f82b8,0x1ea187f, + 0x1873fc2,0x06c8e8a,0x19c1987,0x0d0a35a,0x1e8c2c1,0x146cd28, + 0x06600a5,0x1c02c21,0x1d1a9cd,0x1f52b73,0x1226a29,0x10562a7, + 0x06e3c49,0x00dbc48,0x0772db5,0x1d3aced,0x0082bb2 }, + { 0x0d6615f,0x077a362,0x0a71860,0x0203730,0x1c629dc,0x1932657, + 0x0bb003e,0x189bc44,0x010ecc2,0x0a2bf03,0x08b1371,0x133e3dd, + 0x0c95ce5,0x07ce2d9,0x0cfe9ca,0x021f208,0x062cd63,0x1f701aa, + 0x18b8894,0x0af8779,0x1e4484c,0x0d4b6c3,0x1b23b0c,0x0a58b4e, + 0x1e393a4,0x11a985f,0x02811ec,0x0b25628,0x18545ec,0x1f0c600, + 0x119ef62,0x0b82f18,0x14e0107,0x1802dbc,0x0518b88,0x06908e3, + 0x022a54f,0x12f11bb,0x0410899,0x08d2039,0x036451a } }, + /* 164 */ + { { 0x1893e71,0x0168c0c,0x02085e0,0x16a7344,0x01765d8,0x01767e5, + 0x1a8048c,0x13bf8d5,0x1365bf5,0x0a67a8d,0x0caa023,0x1ae41a4, + 0x0787741,0x0c74021,0x0d0facc,0x073d958,0x12fe747,0x12a9f65, + 0x0a2c1f2,0x14f3503,0x0b3aaec,0x112b7a5,0x0227fcc,0x143a3ee, + 0x1d7293f,0x10b2f4a,0x1bd8aa6,0x0c0ad35,0x08ddc22,0x1119550, + 0x12979dd,0x036f76a,0x1fabec3,0x0ab73c9,0x0559d0f,0x1e91441, + 0x0b0ebef,0x0e6d897,0x1f3c5d2,0x148d371,0x0705307 }, + { 0x088310b,0x1260272,0x15edea3,0x04a64b9,0x12726e3,0x01f7d60, + 0x162c126,0x026ba1f,0x002ddb9,0x0b72a96,0x05a171e,0x07eeef7, + 0x030eeca,0x18af925,0x1d9ba26,0x192f336,0x0d648ef,0x03e139b, + 0x000871b,0x032d0b5,0x11ea3d6,0x1c50597,0x1f8cf89,0x0edad61, + 0x09879b6,0x05f4ae3,0x046bd38,0x00e8e63,0x04ee55a,0x1af89b6, + 0x0e68bea,0x0b3cbe7,0x138b8ff,0x17f3734,0x1690e72,0x003c229, + 0x0a6ad12,0x0caf61b,0x0abb325,0x1a0afcc,0x080f79b } }, + /* 165 */ + { { 0x0af09b3,0x1a153b0,0x1850f3b,0x1b267bf,0x1c016eb,0x02f5541, + 0x1c783b6,0x192e419,0x1ceaa3b,0x07af4cf,0x01be5f5,0x13a56e2, + 0x127216b,0x04b3456,0x1cd30db,0x0ca3ecb,0x0bc5b0c,0x1547dc1, + 0x0bf6937,0x085e39e,0x059e20f,0x16690fb,0x1acc6ac,0x07a2c31, + 0x176c7a1,0x1f2dbd3,0x08e198a,0x1888204,0x108e0be,0x0d38656, + 0x0032097,0x0045803,0x1299079,0x1cffecc,0x1680abb,0x00ec477, + 0x15c58b5,0x027a79f,0x1fc677a,0x149b049,0x05f5a5d }, + { 0x08311dc,0x192bf3f,0x04d95cd,0x028cd9e,0x1ef94f5,0x0e510d6, + 0x05916c1,0x06f4e7c,0x002e4ab,0x0754d9e,0x04596ce,0x15930af, + 0x047760e,0x012580d,0x1f7411f,0x0ab09bf,0x1d13fb9,0x10c46a7, + 0x15522f6,0x1871704,0x1cacfaa,0x182cf4e,0x069e69b,0x144e01e, + 0x1720f09,0x1244c1f,0x13ee29f,0x19774aa,0x01fad58,0x0cb423d, + 0x178e286,0x0b57ad6,0x1856547,0x0b76108,0x14c7cdc,0x16ea227, + 0x0212907,0x08f3c0a,0x162244e,0x0021b82,0x05319c8 } }, + /* 166 */ + { { 0x161c3af,0x009b735,0x0da08c8,0x1c0f697,0x1d40f2d,0x064bf80, + 0x1b9fce0,0x074ca3b,0x06a8c31,0x0bc5d38,0x072842a,0x0fac402, + 0x1b22c58,0x158fa22,0x0ee8862,0x089cc91,0x107e504,0x0c62f57, + 0x10bf33e,0x13e0548,0x093d554,0x179ec02,0x09591d1,0x1808b22, + 0x04f6179,0x043a169,0x02af722,0x0c01f43,0x138f8f1,0x10056f6, + 0x11972e1,0x12475d6,0x0bf9b90,0x02bc552,0x18d4787,0x09ac7fd, + 0x0bb9ea1,0x04e2d67,0x13fc3cf,0x09be234,0x03d1331 }, + { 0x0513d1e,0x03316da,0x0af7973,0x0baab2a,0x1e78a8c,0x1c36856, + 0x1e8ff9f,0x18bd146,0x07a04f0,0x1168952,0x1741b32,0x0dc85c4, + 0x114c669,0x1909b03,0x1851a62,0x1c396a4,0x01b89f6,0x17a6938, + 0x03bf657,0x1ac2ef0,0x0907aaf,0x0262ddb,0x19b5ceb,0x01b66b5, + 0x074ac42,0x1d024f4,0x13c9d47,0x02c63bc,0x1a2edd1,0x199b50f, + 0x136ca7d,0x16ffaf2,0x0406864,0x1c95326,0x074f88b,0x0ce7964, + 0x0043cc7,0x1482731,0x11ab7ab,0x13f6645,0x067f28a } }, + /* 167 */ + { { 0x0148ab5,0x1d92c65,0x0145f05,0x1f678c0,0x19a1976,0x1946fcd, + 0x01a6323,0x02fd44c,0x0e8d450,0x1d9663a,0x02908a1,0x06520af, + 0x1237257,0x0bdf639,0x157b894,0x1778903,0x1cf1d48,0x16ba08f, + 0x01fd73f,0x02fcd69,0x0e1b462,0x02a0f5c,0x12c01eb,0x0b40191, + 0x057a6e0,0x14ce20e,0x0f4be7e,0x1f2a9a5,0x141cad1,0x0aeda04, + 0x074dc2f,0x07052a1,0x087879c,0x052f772,0x154973b,0x1c9826e, + 0x1d3efb9,0x17bfd27,0x0f6cba3,0x0e837a3,0x05ff091 }, + { 0x19c6632,0x089522b,0x0055e46,0x1f71441,0x1b19a44,0x0b1ce9d, + 0x1ee114d,0x19de9f2,0x1bc3c9b,0x0bf15e5,0x1990439,0x1e57e33, + 0x0d122b3,0x09abecd,0x0062768,0x1fecc3e,0x1bb79e5,0x033aab9, + 0x1cbcf13,0x1cb931d,0x0731444,0x1002688,0x15bd878,0x0ebac6b, + 0x0366fac,0x19186fd,0x18b2153,0x1f88f90,0x10850b9,0x121f056, + 0x0cb012b,0x05ee418,0x0e94f64,0x1de4eae,0x19969d4,0x06cfdf5, + 0x10373a6,0x1e9869d,0x0591b09,0x07452e4,0x0668101 } }, + /* 168 */ + { { 0x04509df,0x0ec89f4,0x0dd84e1,0x1b9e672,0x0978bed,0x11d0a47, + 0x0974cd0,0x0f25be8,0x1ee8cb5,0x1fd0571,0x1154f10,0x0d3a638, + 0x08f0153,0x0fdf8ea,0x13c22ef,0x048940b,0x1e69444,0x1d6ffa5, + 0x0d7768c,0x06bf034,0x0b7c016,0x04f3b7d,0x0217225,0x0e6ef06, + 0x1fcde16,0x06925eb,0x128953e,0x1b196a5,0x1ec985f,0x0533209, + 0x131885a,0x0f5204d,0x0db9741,0x0f0dbf9,0x1959438,0x1c72c5d, + 0x13beffd,0x1051a36,0x0ac7efb,0x05e17bf,0x03b35b7 }, + { 0x15c3749,0x06f4fa9,0x1122ffe,0x1f15bb3,0x03c1f20,0x1c7b319, + 0x0cdef23,0x09352eb,0x1e8f3ae,0x094f23a,0x1898a09,0x01aa3ab, + 0x1dc32f1,0x13c3178,0x1034a5d,0x17c6cb5,0x138854c,0x109e3c9, + 0x0d9f918,0x0009de9,0x0ee148f,0x0872e88,0x1e8de85,0x1051141, + 0x0778dd2,0x1a6a4ba,0x1b3edcf,0x0d0614c,0x0049529,0x000983c, + 0x0527d11,0x12ec16d,0x033c709,0x1ae4cc1,0x129496d,0x1906819, + 0x0771f99,0x117205e,0x11a14fd,0x1d79b2b,0x047d0a1 } }, + /* 169 */ + { { 0x12811f1,0x1a7ffb2,0x000899b,0x06c5de6,0x0aacaa9,0x05d0657, + 0x1e95543,0x0ced870,0x0007f54,0x1a80a15,0x1c99ce8,0x0054405, + 0x05c7fd1,0x19ee373,0x0bb95c0,0x0c7b2bb,0x0c3064a,0x1303417, + 0x18ac947,0x1e17608,0x16e746c,0x12aed49,0x0380c32,0x084cb6a, + 0x060f243,0x07ae43d,0x0da6d3a,0x0c6f657,0x17770a9,0x1ac63d6, + 0x099807e,0x1da742b,0x12147f6,0x0f4b08f,0x1578a65,0x0c0b68f, + 0x03213a1,0x0654d9c,0x0a1732c,0x094932b,0x08f4b61 }, + { 0x14eb3c1,0x0760ca5,0x09c16aa,0x0840647,0x0c549ac,0x1663554, + 0x04c893d,0x14601a9,0x145f9a5,0x129dcdd,0x1eaeec3,0x0220112, + 0x10e46ef,0x0bd66be,0x01cf95f,0x16b11fd,0x1e50f7c,0x0be7e67, + 0x01555f4,0x0a7acb9,0x12e20ea,0x0239447,0x1f767ad,0x1d6d151, + 0x1edfac0,0x1065596,0x002180e,0x104428e,0x1eb06c5,0x0344807, + 0x0b1a519,0x04bcb95,0x04cf5bf,0x08d74c0,0x01627f2,0x1db0ab3, + 0x13c45ea,0x09bc58b,0x06007b6,0x004a499,0x08f942d } }, + /* 170 */ + { { 0x0845808,0x1618147,0x1f147c7,0x156ef57,0x0302bff,0x0cbee3e, + 0x152e7e3,0x0964d5f,0x03aac59,0x09d41e2,0x165370f,0x17a2ce9, + 0x1ce3b74,0x0552c88,0x192dcdf,0x059a488,0x173871c,0x131492b, + 0x0d1103f,0x1e490a7,0x0d7d419,0x19f0295,0x1769a83,0x0d90d81, + 0x080d684,0x1a13229,0x0be0c93,0x04ad13f,0x0f117aa,0x08f403e, + 0x0df1d2b,0x11bb93b,0x026dea0,0x1e42eab,0x0dce59b,0x06a4c40, + 0x13b1eb5,0x16abe1f,0x06b2f82,0x0a52938,0x0383002 }, + { 0x0744723,0x1ad202f,0x120683b,0x0a35c10,0x1b5bcf7,0x00fbb7e, + 0x16333fb,0x18d57f5,0x1fab37f,0x1d2ec18,0x1b6de3e,0x049191f, + 0x10be39e,0x16c9f98,0x13eb57e,0x0b8494b,0x11e913d,0x0ba3fed, + 0x1462dfd,0x148f928,0x0327052,0x163e7da,0x0788235,0x1ca717d, + 0x1cb9c70,0x08b589a,0x056ec5e,0x0c6a4eb,0x1106c73,0x1c402d9, + 0x01a8b01,0x1841376,0x0d42a06,0x08256e9,0x11c74f1,0x096a4b6, + 0x022ce03,0x1a59b44,0x0169727,0x12dd683,0x015f187 } }, + /* 171 */ + { { 0x0ee4684,0x0f50305,0x0f20253,0x0cf9b7b,0x02b21f0,0x09898ca, + 0x18526c6,0x14d4873,0x181a7db,0x125eea0,0x0ba03fa,0x0e0c785, + 0x02c6213,0x09411ee,0x02c259c,0x023636b,0x1158326,0x03a21ea, + 0x0f080e1,0x0df0622,0x12d22e1,0x0b15ecc,0x0338813,0x0327116, + 0x1bcd6f4,0x063a4ce,0x1474dde,0x125bda3,0x1dae734,0x0ba7e2e, + 0x166756f,0x13296c4,0x0813d52,0x165346a,0x13d83a1,0x18323b3, + 0x13e9c2a,0x10bcf57,0x048e158,0x1e73fdc,0x06146f1 }, + { 0x18e2aa6,0x1699f03,0x0996f41,0x0f3bdd2,0x093af7f,0x1207423, + 0x03e076a,0x0fdaadc,0x09b9a40,0x0fdddc4,0x0654641,0x15b9dbd, + 0x19dcf44,0x0496dd1,0x1c7e34c,0x0ee96fe,0x1a54231,0x1b3adae, + 0x17d817a,0x0d44a34,0x1a9e745,0x17c3d1c,0x040c752,0x168e97b, + 0x1000605,0x148eda1,0x0ad996a,0x1b4bb7e,0x11eeb4b,0x1efab31, + 0x1617468,0x0c46ef8,0x08149ef,0x085ff81,0x13a5a17,0x1c5c35e, + 0x02a465d,0x15043ac,0x0014383,0x13c0d7a,0x095543f } }, + /* 172 */ + { { 0x1d7c6ef,0x1e37a42,0x1093df2,0x1ac7637,0x0ad8084,0x065d316, + 0x13a22fe,0x125bf21,0x0b455c1,0x0725b43,0x1f1bb66,0x11aaee9, + 0x176146b,0x1d71003,0x188e279,0x04a52e1,0x07961c2,0x0a920e2, + 0x021397d,0x042a207,0x02737d2,0x110bf14,0x15b4833,0x04ce9f1, + 0x19f514f,0x0edf188,0x15c3004,0x0a8b20a,0x1b760e8,0x1aecfe7, + 0x0677ead,0x13d1854,0x146362a,0x0a593ca,0x1e2929f,0x1896da7, + 0x0e5d698,0x0438827,0x05bfe97,0x0f05745,0x06db434 }, + { 0x03f0d95,0x03249ae,0x0254192,0x049ce91,0x0917db8,0x179f224, + 0x17d89ac,0x097ee7f,0x02b7f57,0x1076e2a,0x0c9c8f1,0x13455ee, + 0x0cbe1c0,0x1e5688a,0x0d19a75,0x15ff2fa,0x00a321a,0x04b2330, + 0x1433587,0x1c5775d,0x150eb94,0x00ef623,0x019b869,0x1513eb1, + 0x0990db1,0x149d0df,0x13c9d65,0x073c9ad,0x00dddfc,0x1bc0607, + 0x104473e,0x1b33914,0x0afcd7f,0x0182878,0x0b6db87,0x099d7ff, + 0x16d2c6e,0x1cc0d84,0x1ea513c,0x1ce55c4,0x007a791 } }, + /* 173 */ + { { 0x09f0300,0x148238f,0x04139c3,0x13799bf,0x00253ad,0x02983c7, + 0x0a277fc,0x0c4a380,0x0ae8934,0x0f78497,0x11a117c,0x1235490, + 0x142c90a,0x18ed6a5,0x11bb683,0x0cf6432,0x0f333df,0x0783b28, + 0x0c56805,0x1311b61,0x10f9c6e,0x175aa17,0x1cb8319,0x1806f1e, + 0x16311e0,0x086aea5,0x0aba1a5,0x09175b5,0x1f1c8f5,0x11c6d9a, + 0x151a005,0x1289a35,0x09e3216,0x18e9909,0x0b21011,0x1d32a37, + 0x05e94dd,0x0614f9c,0x1b2b00f,0x05c8a87,0x06d6acc }, + { 0x1b2d299,0x0cf4aab,0x0737ae6,0x17c7ae4,0x1a2bcd9,0x065a221, + 0x0e13eed,0x1545cc0,0x1dc060f,0x10bbb84,0x01f37ab,0x0da7193, + 0x0d74f0e,0x083b7df,0x08df3e0,0x1f7ff34,0x1137983,0x034d78a, + 0x08fe561,0x1ef43a6,0x03986c3,0x07b6db2,0x0f8872b,0x0e07b24, + 0x0134f96,0x1bb3e6c,0x1ee0e4f,0x0eab131,0x0252220,0x145e174, + 0x1f06d6c,0x0f24954,0x18799c1,0x13d455b,0x03ca050,0x043b66f, + 0x1f28949,0x1228d8f,0x11bbb56,0x0247a78,0x079d182 } }, + /* 174 */ + { { 0x09d5589,0x16ffc88,0x126468f,0x0805368,0x1ed52eb,0x1aa56fe, + 0x074c2d2,0x0ce27d7,0x1a27bff,0x1c90a60,0x03d1813,0x1dcecfe, + 0x084c817,0x01d2871,0x17e360f,0x0c46f75,0x1c99402,0x0e2ee01, + 0x19991f0,0x12b0372,0x07f35f2,0x04c5034,0x042da82,0x0c68a2e, + 0x07cec31,0x0c4573c,0x158b9d4,0x0003b74,0x02c3fb2,0x10d3a2f, + 0x0555753,0x16cfa67,0x1cacdeb,0x021775f,0x1e72f1a,0x1743415, + 0x1e88580,0x0c85159,0x1372141,0x1234f09,0x0731044 }, + { 0x048d676,0x1166f93,0x0ac5132,0x0a9e362,0x1a85eca,0x0070f5c, + 0x0b250a6,0x112373b,0x11ac8aa,0x1869b84,0x078657c,0x156f8e3, + 0x1773072,0x17b81bc,0x1463208,0x0cfed74,0x014ac00,0x1d60487, + 0x1734a49,0x19f8e11,0x1a630e6,0x1110f3e,0x13d6227,0x0e38f8c, + 0x0a40b83,0x064da55,0x0a3de1e,0x1f3b57c,0x0caf3f1,0x16b5ec2, + 0x04bde2b,0x13c1c3b,0x039dd07,0x0126e1e,0x17ec489,0x12d017c, + 0x0bdc009,0x0d90a68,0x1153fd0,0x192a301,0x06a8f8f } }, + /* 175 */ + { { 0x1235132,0x0f6b1a9,0x022d8a8,0x02b3b75,0x1db233f,0x0f7eec0, + 0x15148a4,0x15d0ac4,0x1b25111,0x1a8294b,0x006f631,0x15f23ae, + 0x1db5921,0x0bba7a2,0x14175ca,0x0e7ff69,0x05ef18e,0x0371ea6, + 0x066cc0e,0x1b30bf1,0x1558897,0x1de44d8,0x02a70c3,0x0263039, + 0x0d1a34d,0x1071e49,0x08888cc,0x125d0d7,0x0eed022,0x0a6100e, + 0x07f3c91,0x0b07e61,0x1a45f74,0x1e8d193,0x00b2b43,0x10eb4c2, + 0x0b9c753,0x07a2e96,0x0ff5f6d,0x183b650,0x04752d8 }, + { 0x1dff4d5,0x0b6756a,0x1fd1453,0x168b504,0x14cd5fd,0x0389af3, + 0x098313f,0x11c20e1,0x01be577,0x1605dbc,0x11ac237,0x059ab1b, + 0x16271e1,0x0a5e124,0x194226d,0x131596e,0x0636190,0x136ef96, + 0x1d4a20c,0x1d758cc,0x0af1fd6,0x12e1284,0x1aa8b40,0x19f83e1, + 0x0cda84d,0x1f009e1,0x0115442,0x18f06d5,0x0868011,0x14468d4, + 0x114e411,0x15f5e4a,0x03132aa,0x05446b2,0x15dca0c,0x0092d0a, + 0x0744b47,0x0a48e54,0x015495a,0x1e6ebf7,0x03a6518 } }, + /* 176 */ + { { 0x04042a0,0x076a811,0x079aaaa,0x0048a5e,0x0cb4e3b,0x0108ec3, + 0x17d31da,0x07fdb94,0x1ef4d5d,0x107f1fc,0x151b953,0x0548a45, + 0x1533a8e,0x18a233b,0x063887f,0x1a036b3,0x10ef592,0x08a4b62, + 0x0e99dce,0x00985f0,0x1f00691,0x05a395d,0x0a19c2f,0x062ef7a, + 0x083b250,0x1514754,0x15f49c4,0x0bb1780,0x19c994c,0x098bda1, + 0x1fd07be,0x1b9b435,0x001d3a8,0x07b7dcc,0x1ad5c0e,0x01ad0dd, + 0x1bfbf82,0x062e687,0x1605fa0,0x0c7db84,0x0540ac3 }, + { 0x07f43df,0x0b4d4ff,0x19329c6,0x1058373,0x0665380,0x0e148bf, + 0x1df6216,0x0095b2c,0x196aa44,0x1654aa2,0x0a5f6ae,0x0abffe2, + 0x1e0e9d8,0x115753e,0x18625ec,0x07f1c3e,0x0fd36f1,0x1cb76e6, + 0x1b88037,0x1a60e02,0x08a4627,0x1b64c4c,0x1ca7c1c,0x1e463a4, + 0x05e6097,0x1a94af1,0x0fd8121,0x1efe443,0x19b299a,0x1304a00, + 0x16759a0,0x04d6963,0x199de09,0x0ebd18e,0x1d986b3,0x13d88f9, + 0x0ebe15e,0x14f959b,0x05d3d37,0x1d9f42d,0x017db32 } }, + /* 177 */ + { { 0x0f40599,0x1b48cb6,0x03a9d7b,0x1601804,0x1ea10df,0x157b3cb, + 0x0b9eff2,0x0f07b4b,0x188ddd6,0x0b31e51,0x0f3f343,0x11fc4ab, + 0x1e5a21f,0x11a25e3,0x10fd4e3,0x00c65d3,0x11d548e,0x09afb15, + 0x0f1b993,0x1e484a8,0x1627654,0x13134c9,0x11d569e,0x1e82649, + 0x1c5f7b0,0x079d1db,0x04e8860,0x0ad2fef,0x01675b0,0x0fd88f4, + 0x1d5b3e1,0x1ca6851,0x13cdb35,0x1458136,0x16454b4,0x11c7542, + 0x17a3fb7,0x03812af,0x11176a1,0x0374328,0x0460bd0 }, + { 0x04d8077,0x06e11e1,0x14b2f0d,0x0098e41,0x02f4b58,0x0e8fff4, + 0x0a445bd,0x1c5453b,0x092783c,0x1c57a90,0x012bcd5,0x03576b2, + 0x10e29f5,0x1bd508c,0x115c35f,0x1bbe08d,0x1ba571b,0x0a52917, + 0x1a26ed4,0x1c540d5,0x044dbf4,0x062cf9a,0x1e66cd7,0x1984aae, + 0x0836726,0x0bbe181,0x16bf3b0,0x0949d30,0x16cbd09,0x1ee5be1, + 0x1deb6bd,0x0eba720,0x131b787,0x1125e76,0x013cb4f,0x16a5ad2, + 0x1f95421,0x0513348,0x01e3717,0x0782e69,0x07d342c } }, + /* 178 */ + { { 0x1fd127f,0x1960508,0x117b973,0x10233c9,0x06d36bb,0x1ab561b, + 0x0c949bb,0x0eac435,0x0e54306,0x067f577,0x1a5864c,0x0fa5587, + 0x112ede2,0x1c7e733,0x04d44eb,0x0987ac8,0x01b075f,0x030ace3, + 0x041a766,0x0fdfd2b,0x0ea9d44,0x14753b5,0x0be35bd,0x0b7a2c9, + 0x1c61b0f,0x1cc562e,0x187a22e,0x175688d,0x092320d,0x058b0dd, + 0x195862e,0x0f13130,0x0eafb3c,0x1bf4150,0x130b022,0x1618f57, + 0x00d160b,0x184db71,0x18e9c43,0x14d1c98,0x05be0af }, + { 0x1bbf49c,0x1b69c0d,0x0ffa0aa,0x13180e0,0x1e09ce4,0x07a1319, + 0x02d7784,0x065d94b,0x1da5a45,0x0e632c0,0x03dedf6,0x10edec3, + 0x0707e18,0x1287bff,0x066978c,0x10d7c08,0x090de6b,0x0dd8d4f, + 0x1cd645a,0x14fbd66,0x1b2c584,0x04a8a4e,0x0e3acd2,0x1d75770, + 0x06a33b0,0x1490a2a,0x030be22,0x00cfe16,0x0db0190,0x0ff3851, + 0x0faf783,0x18c7cde,0x051b06c,0x037d6dd,0x1ee7a48,0x1543224, + 0x1e80dc0,0x15af43f,0x0c2bb93,0x1eba9bc,0x01e6fcc } }, + /* 179 */ + { { 0x08ac924,0x0ffb355,0x0fa2d5f,0x0385316,0x06e9ad3,0x1d84060, + 0x18ca597,0x07fa281,0x11d95c9,0x0d5908e,0x0032a9f,0x1085143, + 0x096d68d,0x1106f6b,0x04a5022,0x08c3e35,0x15338df,0x1540a8b, + 0x03aba4c,0x0c095cc,0x0c0bff5,0x04bed72,0x0406e79,0x04c5d13, + 0x1a97fde,0x0c1a2b9,0x13c4212,0x1ad3b34,0x124f1de,0x0117b23, + 0x17e3fe8,0x1d50b42,0x1f1c2e4,0x09bca6a,0x13a4051,0x1a98c4d, + 0x1f0907d,0x02066b5,0x0a0de01,0x0c2bbb5,0x04522d4 }, + { 0x1fbe7c5,0x0f83cf5,0x111a225,0x1b09de6,0x10ea1de,0x10d5cb1, + 0x07adb52,0x0d0e2d5,0x050a30c,0x1252e91,0x0eeea86,0x0638008, + 0x155a166,0x080872f,0x041d409,0x00aad7a,0x09d3d8c,0x0dfff1f, + 0x1ddc906,0x0616300,0x029731b,0x18425c1,0x043fdfb,0x0343187, + 0x17d75f2,0x07c0061,0x15596ee,0x11a14c6,0x03bceb1,0x0d1522f, + 0x036eb07,0x047e161,0x038e90c,0x02d628e,0x0a897ef,0x0de3743, + 0x1da71fc,0x0a92b5e,0x102e827,0x152dafc,0x0346501 } }, + /* 180 */ + { { 0x02b0f1d,0x1224666,0x1c0e1af,0x1358986,0x03eb45c,0x04b5dff, + 0x1d9767f,0x1b4a70f,0x15ae27f,0x179e274,0x0602273,0x0eec378, + 0x01a008f,0x11650c5,0x1d28210,0x066e3e6,0x04253b7,0x0774414, + 0x13024d5,0x1f8db0f,0x0d6bcb6,0x0db0a4b,0x01227b0,0x1c64b89, + 0x029b949,0x0b35496,0x09ef7b0,0x0b8d94a,0x0a28131,0x07776e7, + 0x13e5511,0x074422a,0x0683eb3,0x030e79a,0x1e634e4,0x171f64d, + 0x06c940b,0x1845540,0x125b70e,0x19fcaa9,0x07c1d42 }, + { 0x0110aa7,0x1381fee,0x0de1d9b,0x0fe6c5c,0x0b7b79d,0x16e51e5, + 0x11d756a,0x0e7a4b3,0x160be33,0x137653c,0x13a3fca,0x14960d8, + 0x1ff4744,0x19db82d,0x010b33b,0x096a765,0x1aaae30,0x00d1d7a, + 0x0cb4c6e,0x1f44023,0x08d97bb,0x1d25f74,0x112e9ba,0x0b97073, + 0x165ce56,0x074169a,0x1b6bdfb,0x09010d2,0x1597452,0x0673f34, + 0x0dcb1f3,0x1d29f30,0x1d6eb3c,0x0d19377,0x133ce04,0x0c14676, + 0x1ffa93a,0x101fa1f,0x0764050,0x050e786,0x0031e98 } }, + /* 181 */ + { { 0x05a17ff,0x1f67e3b,0x09953fb,0x11a2521,0x009f388,0x06d01c5, + 0x1711a4e,0x08d7e4c,0x1a169ad,0x1db0a2e,0x18bfa12,0x0428474, + 0x0533cf8,0x15e4305,0x0b7d5c6,0x07188ac,0x0fa815c,0x0df9548, + 0x1fb6a1d,0x143adc2,0x05e145b,0x0d4a37d,0x1e67620,0x01eb476, + 0x1e784b9,0x095360d,0x12c43fd,0x122146f,0x14fd360,0x0ff2527, + 0x0830e30,0x11c5a77,0x1180fc5,0x130c3e1,0x0142c5e,0x047c5fe, + 0x143a35c,0x0002cdc,0x11470e8,0x08b4519,0x0494d36 }, + { 0x1a021f8,0x0135b25,0x0db0e61,0x06f2dbd,0x114c908,0x1b63b16, + 0x14e55f8,0x02cda5c,0x0751cf2,0x1aab765,0x0928663,0x1c00336, + 0x0edaca1,0x0590615,0x021f691,0x14e668f,0x0cdff41,0x1c9f6a6, + 0x11f0335,0x02f888b,0x10098d7,0x0548dfb,0x131218d,0x0b3775f, + 0x146f93b,0x18ad0f8,0x0795893,0x1a71767,0x1f8443d,0x0d56981, + 0x1f25b50,0x097e209,0x1670f03,0x032c135,0x07b4a5c,0x0a0a07f, + 0x134200f,0x070fa3d,0x11bcdda,0x0bd77a9,0x03cfdcc } }, + /* 182 */ + { { 0x123e13d,0x015435a,0x02814db,0x105241a,0x1014a45,0x0b894b0, + 0x0d1e39d,0x1d47aa5,0x07eb51b,0x0ba3033,0x03a4641,0x10c30f6, + 0x08709f7,0x1434447,0x02bb621,0x1f9a805,0x1d7d94a,0x1bcd404, + 0x084a6bc,0x0c065fc,0x008250c,0x194c1e2,0x1d792f9,0x1677d1c, + 0x11bbb7a,0x1944c19,0x12d8631,0x0634065,0x19c4a4d,0x02d09fa, + 0x188db76,0x1da9ec3,0x1ece345,0x18b8aed,0x1334795,0x0f74f55, + 0x04a1ebd,0x062c6d3,0x1ba844e,0x01e7a35,0x089296d }, + { 0x0a82c97,0x09447e6,0x0372c59,0x1a284fd,0x06c6c12,0x1f6ed49, + 0x13c1d30,0x17ccd52,0x0eaa01e,0x030070f,0x17a1b65,0x1cf861e, + 0x1114abc,0x05a2b51,0x075c083,0x08584e8,0x013279f,0x05582d5, + 0x108e11a,0x0c1f5fa,0x19e670b,0x0098c69,0x0863bfb,0x0416631, + 0x1f1ac89,0x101f583,0x0360e67,0x03c7975,0x01a3010,0x09971e4, + 0x16197e2,0x1998ccf,0x08bca7d,0x0303e57,0x19e689a,0x199dc35, + 0x0ac0a12,0x0173266,0x13150c6,0x1ee5634,0x09233a2 } }, + /* 183 */ + { { 0x0cbee17,0x146fb05,0x1371c5f,0x04b849f,0x0f0959c,0x07fe580, + 0x0621f95,0x0d68de1,0x0d28511,0x0c9ef65,0x07e946e,0x09f1774, + 0x1e0bfaa,0x08790c1,0x04927bf,0x0eef339,0x1589684,0x0fc9e59, + 0x0c8b508,0x17f6fe4,0x1009284,0x0d6a157,0x10331c2,0x163ac2a, + 0x122749b,0x035634f,0x09c5f0f,0x0dea167,0x1c5eeb7,0x14c2ddc, + 0x17e2c87,0x148f076,0x0fb19ae,0x0e1f3ac,0x0e6d4b8,0x100990d, + 0x12971ac,0x12c8497,0x00a46b2,0x0d243db,0x02bb26a }, + { 0x1f81416,0x1a21a8a,0x0ed2628,0x0f55feb,0x086e72e,0x0b930e0, + 0x193780c,0x1fc7a3e,0x05c0a1c,0x0e03c36,0x00d004c,0x09b166d, + 0x0d542ea,0x0d1cda6,0x1dc9ce8,0x04fe25e,0x0e1cbef,0x00a7f3f, + 0x1aec9f7,0x1f813c2,0x1dc7ee7,0x0ba0872,0x1037330,0x08767bb, + 0x0674219,0x0dbd1a3,0x00fcc70,0x052696c,0x0c10709,0x0f6ce11, + 0x1ac061b,0x0f33f2c,0x17ee8ba,0x18449d1,0x12d0926,0x1c1e77f, + 0x0e92d4d,0x130a239,0x1ac22eb,0x1f1c32d,0x0937cb3 } }, + /* 184 */ + { { 0x0fbfdce,0x073be0b,0x13015f0,0x13931a9,0x0a034cc,0x0b96907, + 0x1b5c909,0x079cec0,0x00019a8,0x030daae,0x05c58a6,0x1007e2b, + 0x1b80ba2,0x02d07eb,0x1050774,0x155441e,0x13b4b0d,0x04432c8, + 0x08e123b,0x10ae8d5,0x05d2e66,0x0d1f024,0x05b4569,0x0d20bba, + 0x0c7743b,0x15d40e0,0x16062bc,0x1d8636f,0x174b78c,0x18ca695, + 0x0a20363,0x0a87c5e,0x0659db2,0x03e0e65,0x09f67ec,0x0063707, + 0x1f1048c,0x09bfee0,0x1a84619,0x00ef0b0,0x04d57bb }, + { 0x1b396b6,0x1bb4529,0x16b2f12,0x09276a3,0x1c8b24c,0x0570d9d, + 0x047ae8c,0x18a67ca,0x1945147,0x09ddeca,0x1f8f3a2,0x00622f3, + 0x146cc86,0x1fc905e,0x0c2859c,0x0c2c069,0x0eb6b25,0x1d99489, + 0x145a360,0x1345493,0x1128bc6,0x1d7786e,0x0d25279,0x04d33c3, + 0x1419a87,0x1b59309,0x1efc84d,0x0d8b08e,0x1971470,0x0c84d27, + 0x17f956c,0x0f736e8,0x1d6eb75,0x19e42b1,0x0ca4237,0x076a6cb, + 0x15fcfae,0x12bf21a,0x0aaa038,0x0312f3e,0x01067c1 } }, + /* 185 */ + { { 0x0bf8883,0x0a84219,0x199f211,0x14dfa0c,0x0755286,0x0119aea, + 0x03e3ddf,0x129ae16,0x02f4a2c,0x1c7306d,0x02b3d59,0x1159a23, + 0x19a468d,0x1fadc86,0x04e0c2e,0x122099d,0x074ed4e,0x075258e, + 0x1dddba9,0x0e62da4,0x0b12ac6,0x0e1b0dd,0x0e62b5d,0x02448a3, + 0x1d48299,0x1d76191,0x014c290,0x0c88044,0x12d5a52,0x0997194, + 0x0f0e911,0x0bfd9e3,0x148694b,0x1dc5c6d,0x05bb199,0x1dc9c0a, + 0x04306ad,0x152cafd,0x05c96ce,0x123e69d,0x07e4f70 }, + { 0x1f70919,0x00b74db,0x0fd4fce,0x1a2d600,0x165216e,0x064cf2b, + 0x13fd1de,0x0208d8d,0x030a518,0x152d5f4,0x1ca36f9,0x13cc8bc, + 0x16ef6f4,0x056677e,0x175cfab,0x1e7eedf,0x06f8c37,0x1f61ca7, + 0x1901ff0,0x0410056,0x1cbd733,0x1d4b312,0x0623a3d,0x157f601, + 0x123637c,0x0cd4194,0x1d01fcd,0x0b1753b,0x1fae502,0x1772e65, + 0x04ffc06,0x1fc4a30,0x1eaeace,0x0e5d0fd,0x05860fc,0x0b38d3e, + 0x1eadcdb,0x162c56c,0x1a2f544,0x1a8d999,0x02ae49c } }, + /* 186 */ + { { 0x00849f2,0x0d871e2,0x063048e,0x1b48821,0x1136a4c,0x03fb24a, + 0x16a6795,0x18cc2a6,0x07a9bba,0x1725ee2,0x11ebda4,0x0c8ca6a, + 0x0a195a1,0x05a3d3a,0x1b2cc66,0x145650b,0x1fc9de6,0x093c2a9, + 0x18ae94b,0x1807141,0x1a93471,0x041ade5,0x04ae86e,0x063d944, + 0x150da6f,0x1636a5f,0x1a00acc,0x028dc7e,0x04c8c4d,0x00989e3, + 0x05c3270,0x1dda425,0x130f12d,0x02987d6,0x1fee71a,0x0336eb7, + 0x0918de5,0x00569f4,0x1c6dc8f,0x0a54e6e,0x0180e9d }, + { 0x1ab77b0,0x12a1794,0x18a30c5,0x19ef5dc,0x1d411d9,0x1e17a06, + 0x01a14d4,0x19e0898,0x04b0ae4,0x1c6e3f2,0x1099bd8,0x030b2bf, + 0x1da0924,0x1e97f5b,0x07699c7,0x12f30c7,0x0d55ea3,0x12b42c7, + 0x03ce0ca,0x129e62b,0x18317a6,0x03698b6,0x0a508cf,0x146b4f7, + 0x0cb2630,0x09d97e5,0x17c7fdc,0x1df1efb,0x0ee2f3f,0x0292acf, + 0x12a2e6d,0x02ada0c,0x1b4f91b,0x07e7e68,0x1b08bd7,0x022ef0c, + 0x1777eb4,0x1e12b31,0x016d04a,0x079b157,0x021ca6f } }, + /* 187 */ + { { 0x1e66635,0x11589d1,0x1abc385,0x16553ee,0x1ef20a2,0x0d99ab0, + 0x0e8c11b,0x11b568e,0x17802bb,0x0205ebb,0x06d1302,0x1ebd4d3, + 0x115b6ba,0x0d9103f,0x1846400,0x0020b8d,0x0a9790b,0x072ef0b, + 0x0d9fc01,0x025e2bb,0x1d2522b,0x02c5012,0x0617eb5,0x0142284, + 0x16953df,0x0605e67,0x0fd140d,0x1884253,0x077bff4,0x02000e1, + 0x0603dd0,0x050153c,0x0440b4c,0x1515a37,0x03d610a,0x1eecfbd, + 0x05e8d94,0x11055c0,0x1d8d4f7,0x0b24044,0x05aff58 }, + { 0x0458e40,0x1669054,0x0af6016,0x10292e6,0x1a5557d,0x0e5396a, + 0x104c57c,0x0478e0e,0x0952b53,0x197134e,0x13eb7df,0x0aacc92, + 0x065c592,0x0d3e933,0x0edeb34,0x050ca2a,0x03d86fe,0x1d36f83, + 0x1f54eda,0x03b626a,0x0d011e9,0x04f49f5,0x04656ee,0x0c77fcd, + 0x1e1af29,0x0431eb8,0x0a209e2,0x1565738,0x059b6ff,0x13491dc, + 0x145de0d,0x1ee053b,0x0695174,0x022b0b7,0x01d9ee6,0x138f30f, + 0x1907d84,0x1da78ea,0x0a5dd93,0x03911b1,0x03eab7e } }, + /* 188 */ + { { 0x0e5718b,0x14a5b29,0x07a71ce,0x09e99dc,0x03aefa5,0x1f76f57, + 0x0798d54,0x034ca9d,0x15f3aca,0x12a0f0d,0x00cc5bc,0x09121a1, + 0x0ed7129,0x1dbfca8,0x196bd8f,0x07c94f2,0x00dc74e,0x06c7e4f, + 0x0bde7af,0x1c91a5d,0x07e6b4e,0x1545bbc,0x09162a1,0x199d5e1, + 0x1621ff7,0x006ec63,0x1f7d9e6,0x0451ddf,0x1067278,0x03a17c8, + 0x0a48435,0x160fc6c,0x1f63501,0x0f14ec8,0x0719e5c,0x0a882ec, + 0x03a3b8a,0x06632f8,0x0551303,0x09e71c1,0x03491da }, + { 0x1062eae,0x1682365,0x1db59c1,0x0aba10e,0x0e7db73,0x118ae97, + 0x00148a4,0x1b701bd,0x0c402bb,0x03c2b31,0x14ccdd0,0x04b84dd, + 0x135f935,0x1eab476,0x1a85359,0x1163cd9,0x1896688,0x0c8b508, + 0x171c59d,0x1aa40ab,0x1df20fb,0x1bf22ba,0x00cf441,0x012466b, + 0x1100aec,0x1c4a749,0x05b3614,0x1f3c3a0,0x0263682,0x1b92a19, + 0x15fbaf4,0x037499f,0x01d172b,0x02c1c20,0x0e755d3,0x1c6efb5, + 0x00d517d,0x1534ac4,0x16862ba,0x1fad5a2,0x00c843d } }, + /* 189 */ + { { 0x1373300,0x008ffe4,0x0c01156,0x1533fb8,0x1c39332,0x1e5b2a8, + 0x0e070d4,0x04fc337,0x096a83d,0x1a5c925,0x18fc69d,0x1f9765d, + 0x07cbfc8,0x0086ab6,0x09e3b10,0x15ef35e,0x02fe0ab,0x1b7ef34, + 0x0ce6baf,0x0da0e4e,0x1db6756,0x0eb8902,0x0f4d6b5,0x0a393a1, + 0x1e69470,0x13e5add,0x034e8c1,0x0efb690,0x0d75305,0x1faa2b9, + 0x0f4b1c3,0x1c0db0a,0x0615aec,0x1fdaef4,0x132c16a,0x0ee3333, + 0x0a0a8ed,0x17e4b5f,0x17da7bb,0x13a6bed,0x02dcc46 }, + { 0x05f0e77,0x1668363,0x052b329,0x017ae36,0x1dcc798,0x09e6006, + 0x07e2cf2,0x0af6c44,0x1ae8cbf,0x0fe6ad9,0x0398ff7,0x0e7eedf, + 0x17bc929,0x0370995,0x01228d0,0x193c5d3,0x003d51e,0x12662cd, + 0x08cc206,0x1a65767,0x066b9c9,0x0940742,0x0004841,0x17ce52a, + 0x0032a1b,0x0246158,0x08924e1,0x17f8cae,0x1ba0ffd,0x10675b5, + 0x00ba5ca,0x1815290,0x00c0a4f,0x0c5e3fb,0x0731667,0x11ec588, + 0x112da0b,0x064b771,0x1e7f208,0x1b79b7b,0x05a1a65 } }, + /* 190 */ + { { 0x0485684,0x1348d21,0x0326fee,0x125388e,0x013116b,0x15028cb, + 0x065c798,0x1b56960,0x05ff499,0x1922d53,0x0e3bffc,0x0fe94a4, + 0x15c2ef8,0x064eaa8,0x1b71aeb,0x1595982,0x07e2dbd,0x1ad3f91, + 0x06eebb2,0x1b55895,0x18858de,0x16973e4,0x1fcc229,0x112ab27, + 0x12fc2e6,0x108a637,0x145df81,0x0cabe50,0x0b1bee3,0x0683180, + 0x15298fa,0x02782f6,0x0d0ce79,0x1a1315f,0x18d7125,0x0f94957, + 0x1c4e403,0x1a250bd,0x1ef67d2,0x133dfcb,0x05ae950 }, + { 0x04f7455,0x12f73c0,0x1a0848b,0x0e440cc,0x141a499,0x0af1999, + 0x130c5de,0x1db2fa4,0x0e48efc,0x17a091e,0x0f08704,0x1b2433f, + 0x0ee8738,0x0331d1d,0x0ef7184,0x14db776,0x0c28593,0x09b01ec, + 0x0f06b1d,0x044fe5c,0x0519926,0x002f557,0x1faa4ab,0x0d02559, + 0x16f0bfd,0x16e2dac,0x13f0aa0,0x19cfd08,0x122b273,0x040d31a, + 0x054e101,0x0a50cf1,0x16088b1,0x0434441,0x1f30996,0x1843ff6, + 0x0f4a7ca,0x1198b09,0x14a6032,0x0fd47db,0x0411066 } }, + /* 191 */ + { { 0x0d04b63,0x181abe1,0x0862060,0x1be9253,0x1fc5a34,0x08caef9, + 0x1db688b,0x0e78e77,0x1cb4324,0x06f97c4,0x1fc4e05,0x1cb9d32, + 0x14345af,0x05cb027,0x18fd7e6,0x015cbb1,0x0e950c1,0x1d6bca1, + 0x1b497fc,0x1aa88fd,0x00cccef,0x0f0739e,0x0fda394,0x0a9f499, + 0x0d591ab,0x0462d8d,0x144ad87,0x1778220,0x0bf7608,0x1489dad, + 0x126ee4c,0x003cf2c,0x11231be,0x065f3ed,0x1a44103,0x13a1507, + 0x10a96db,0x0f2137c,0x047a8f7,0x08a69be,0x01cceb6 }, + { 0x06d0f55,0x0862786,0x1274b48,0x1738ce7,0x0cadf61,0x071fddb, + 0x06466a7,0x1c9baff,0x093b063,0x1afa4a6,0x0a4ef84,0x167828b, + 0x1c580bd,0x07a977b,0x01c8cc8,0x176d49b,0x0e88814,0x13a6c3b, + 0x1ea5f7b,0x1ee4758,0x18334f6,0x181f1e6,0x1f78ae3,0x0e404e0, + 0x0f082ae,0x03730b1,0x1377e92,0x111d85a,0x1a17c6e,0x042cc69, + 0x06b6597,0x073002e,0x0e59e54,0x1b59131,0x0176efb,0x06156c5, + 0x0d48b20,0x1a28caa,0x17a8cf3,0x0669d44,0x01f1752 } }, + /* 192 */ + { { 0x067ea91,0x13b2d9a,0x1116022,0x1dfa5b3,0x1f4632e,0x195e379, + 0x171b673,0x15cf6eb,0x0359813,0x1e46920,0x12f637b,0x0413c89, + 0x0223ecb,0x10a92b1,0x0e8438c,0x1c334b3,0x1343f1e,0x1fd0a6c, + 0x0c3123d,0x0f8437f,0x1437df9,0x0875186,0x11398a2,0x028eb85, + 0x0e2a465,0x152d943,0x104999c,0x123e03c,0x0ab3b82,0x0d2e18d, + 0x1b271bf,0x1c2fa45,0x1277a5a,0x185d6db,0x160e453,0x037b11d, + 0x0a2392e,0x182e8db,0x0f0af42,0x120cb12,0x04cb8af }, + { 0x14b1953,0x0102bdd,0x1bba8ac,0x09eb2fe,0x0ce08b4,0x1209642, + 0x1766d79,0x0330a9e,0x1b3cd49,0x0899316,0x0aed746,0x05c8dc8, + 0x0090276,0x0bc73fb,0x157239b,0x182d906,0x02438b6,0x0477d54, + 0x1543d86,0x0e6f21c,0x178ed01,0x1172beb,0x0462bd1,0x0b68e28, + 0x0d5e871,0x07cd0b5,0x0d077a9,0x000b2d8,0x0ca6109,0x1e19140, + 0x084aa55,0x06e98cb,0x1aee800,0x0020a17,0x049d402,0x03b620a, + 0x1f080fa,0x0edc98f,0x1e3f230,0x04baf30,0x0486a5c } }, + /* 193 */ + { { 0x01b4f36,0x0f109ca,0x13e4148,0x09f0076,0x1aacfb1,0x12a5d45, + 0x188b94a,0x0d9fbe3,0x08fe479,0x07d5ddd,0x0eb2dab,0x11b6b1b, + 0x11ae078,0x00cefd2,0x0635cdb,0x02dddbf,0x06a35a7,0x18aae14, + 0x1219186,0x1a8ced3,0x0a5ebe7,0x07b1d32,0x142d8e0,0x0c124c4, + 0x019149f,0x0d98a5a,0x028b7f1,0x12334fa,0x1466ac0,0x0d2ae77, + 0x1b31153,0x0d30d55,0x1fa4a24,0x04e76c9,0x05c5c69,0x1aa1216, + 0x01fa75a,0x178eb66,0x1015180,0x112f1c9,0x05d269f }, + { 0x0920419,0x001860a,0x1ce4e9d,0x11212d0,0x0845d86,0x1b87d30, + 0x05313ba,0x1970373,0x1d9fc5b,0x1e55036,0x1e3cb6a,0x084feb1, + 0x0a06539,0x18ee295,0x1217d9e,0x037546b,0x1722c91,0x02d3ec6, + 0x1b0b60d,0x0200b95,0x1347404,0x023d472,0x0d61a29,0x1ca2587, + 0x0180b8d,0x0758277,0x148445a,0x1b54cdc,0x17cd8a4,0x0ed5918, + 0x1db02f5,0x0c22c9b,0x1d4185d,0x16be4d0,0x089876e,0x0759db9, + 0x09b0268,0x125ad60,0x1543c3f,0x0b44db2,0x08ac999 } }, + /* 194 */ + { { 0x040a39d,0x06e4d93,0x07e6cb2,0x11dbc19,0x01ff0b3,0x165d051, + 0x1a6f687,0x02ee9e8,0x1080d04,0x1481666,0x0518122,0x1465e93, + 0x15e956f,0x0bbb558,0x03e173e,0x1e92469,0x0ee0066,0x1e10fe3, + 0x1bbbcd9,0x03d7fdf,0x05ed35b,0x0e2309f,0x1e01160,0x0d740e2, + 0x1e8e6ea,0x1f6e5ef,0x0a5435c,0x1bf9546,0x048889d,0x1c9b0ed, + 0x14725d1,0x1b75ff7,0x0867c8c,0x17573e7,0x0c7c72e,0x11a4ce8, + 0x097912c,0x12a822c,0x07935a0,0x1b9afd4,0x00c7c1d }, + { 0x0e963a7,0x118660e,0x0b794ea,0x19898bf,0x1352f64,0x1457dfb, + 0x08be0a0,0x00e5735,0x0ca2121,0x0139e2b,0x15db719,0x0ca90b4, + 0x1caadd7,0x085ae3b,0x05ab0fa,0x1e736c3,0x09fd1aa,0x0106a1f, + 0x14172f1,0x1240c59,0x12fdfc3,0x192607f,0x05058e1,0x1d043cc, + 0x0b8d82a,0x1f86799,0x0cfe9e8,0x1eb1f28,0x04ca925,0x0e96fb2, + 0x17ebafc,0x032314e,0x0061563,0x1b08c06,0x17b5ae1,0x02f3136, + 0x0d41244,0x1a1222d,0x0ceaefc,0x15c3bec,0x024ffc9 } }, + /* 195 */ + { { 0x1c7cb2b,0x06e02c9,0x0fee27f,0x0ab200a,0x01243b9,0x011a1e6, + 0x1af3d86,0x0c6c03b,0x166c18a,0x122a377,0x04ca1cd,0x0e03d92, + 0x11a5290,0x1cbc461,0x16e009b,0x1efaf86,0x02a92d1,0x04295c3, + 0x0a9e5ca,0x13960a1,0x0005180,0x1e51e59,0x025f519,0x1eb728d, + 0x077c09e,0x0c27906,0x0bc8906,0x066e588,0x1bb206c,0x1f06f9a, + 0x0d76814,0x1538281,0x026c6d0,0x17d99de,0x10332d5,0x10c39f9, + 0x099b396,0x1e7cf79,0x06e9070,0x1a280c4,0x089e4d3 }, + { 0x05a9be3,0x14073d2,0x1ef74d7,0x100e6ad,0x04daa57,0x13de17e, + 0x158bae5,0x1c6030d,0x047cd16,0x18133cf,0x033a6e9,0x1804be6, + 0x10ca2f1,0x0fc327a,0x0816d18,0x03acde2,0x1978506,0x13feb6b, + 0x0822027,0x1b89ed1,0x1ae247e,0x04cd269,0x176b011,0x03f3b50, + 0x0664a6d,0x138fc22,0x135ea0e,0x1e619d0,0x0c33f19,0x15d6755, + 0x0afa4e0,0x1290c45,0x1033831,0x00f590f,0x12ebdda,0x0f606f4, + 0x19a1b5c,0x0b54844,0x143ef45,0x0dfcde3,0x0675d3e } }, + /* 196 */ + { { 0x07193e5,0x13ffeb8,0x039765d,0x030206b,0x0478aa9,0x06c77bf, + 0x1e7fcca,0x14eac69,0x06dbbd9,0x09d0774,0x055a1a4,0x12d0fc4, + 0x18379b2,0x04eced1,0x0fd042a,0x069a520,0x1b91b13,0x0ecfc6b, + 0x160bbed,0x0e84537,0x07789fe,0x111c01e,0x16d5a2d,0x1a4a689, + 0x1a350d3,0x1f449f4,0x01c9125,0x0b386b6,0x09e23b5,0x0a1b50b, + 0x1a711cb,0x198b698,0x1864632,0x1fa9884,0x16760f1,0x113edae, + 0x1e49788,0x0e78ed8,0x0692ea4,0x1fcc15e,0x05f7f92 }, + { 0x145167e,0x10e6302,0x0383c62,0x055ff51,0x15ee2e0,0x153de7a, + 0x1fd450c,0x0cc499b,0x0a75108,0x1c16d21,0x046bddc,0x023e80a, + 0x03e894c,0x15578a1,0x13938c4,0x1a55d54,0x0f0f63d,0x0c61e9b, + 0x1d9818d,0x192aa1a,0x1eabfc5,0x189bf53,0x00494dc,0x172a1ec, + 0x0d59839,0x021152e,0x050398d,0x0b41ec0,0x0c70459,0x11c7795, + 0x1ce4178,0x088d61e,0x0bacc0e,0x02bc522,0x01bb112,0x0699a84, + 0x05bd780,0x1d8d555,0x11634d9,0x1b21456,0x025bece } }, + /* 197 */ + { { 0x033a8fb,0x139c106,0x10741e6,0x021e4bb,0x0fbf6cd,0x0a415b6, + 0x1cfe31b,0x0949ff8,0x007bf84,0x128f8c6,0x058bc0f,0x046cb32, + 0x11a7651,0x0a009c0,0x1669d38,0x0314158,0x065e550,0x0cabd34, + 0x0f2826c,0x18a37bc,0x053fe1e,0x19d4b01,0x0f031fa,0x1c07f09, + 0x1fd147d,0x184f41d,0x054bef6,0x00a81da,0x015ec1c,0x176ee75, + 0x01dae94,0x0964c26,0x1d30ed5,0x0b90379,0x0ba3a0e,0x1537af7, + 0x096373a,0x06c3490,0x0fd8fc8,0x0978761,0x00a616a }, + { 0x01339c9,0x0f9f6b7,0x029881d,0x057f160,0x1afaa07,0x06cda3b, + 0x1b20af3,0x18fbf5f,0x100ca54,0x1898ac7,0x10c6b91,0x05e2717, + 0x0a44910,0x1886fe4,0x063c560,0x0a9a95f,0x07559e9,0x064f790, + 0x149e831,0x0435f38,0x0023e80,0x1bbd0c9,0x1ba0049,0x16046ee, + 0x1538c7f,0x0a8b1af,0x1fa327a,0x1be32e9,0x0c90975,0x1d768ae, + 0x1700a1f,0x1ef4a22,0x00728f0,0x0311efd,0x0f983eb,0x1321b7f, + 0x0311ba0,0x0a07ea0,0x11932a3,0x09c0f8c,0x0876d15 } }, + /* 198 */ + { { 0x0d3ea8a,0x06b6961,0x003b4e9,0x175084c,0x16be681,0x0383391, + 0x0403790,0x0f78a7e,0x06a7d7a,0x1f2db7f,0x186a0f8,0x09f2bab, + 0x0a6e699,0x1b04be1,0x12b3489,0x020220f,0x1baa679,0x0096cc6, + 0x00b8389,0x1888c22,0x072addf,0x016a499,0x120576f,0x086cd2c, + 0x0e64ba9,0x1c83f1c,0x08cacaf,0x12c1d63,0x08e28b4,0x1a92ec9, + 0x07b6915,0x0540ef9,0x0f75b39,0x10e8039,0x12edff5,0x0c4eec1, + 0x0f4b145,0x11ae8d8,0x05c02bc,0x077ceda,0x03040c2 }, + { 0x0fa9a70,0x0e2ada7,0x1842c43,0x1ea7d0c,0x14de414,0x1c513fe, + 0x1044c27,0x0787b2b,0x106661d,0x02884d2,0x0d44f94,0x1294c1d, + 0x0bcaa29,0x0f3e99c,0x19054dc,0x1ce3e7d,0x1fc4651,0x027e8a2, + 0x0f0c4ed,0x17f0719,0x015051b,0x1c0f5c9,0x0c0e781,0x17eb58f, + 0x16b4414,0x0467434,0x022f835,0x1acce31,0x0f2b6f2,0x197aeec, + 0x02afa4e,0x1d714ff,0x1dfd1e7,0x1a8e2e0,0x176643d,0x1d0c567, + 0x032a74b,0x18d6ac5,0x126887a,0x1343d77,0x05486d7 } }, + /* 199 */ + { { 0x1359e13,0x11a7fd0,0x01472cb,0x1e5032c,0x002d8db,0x0b25af1, + 0x008f48d,0x025d2bc,0x042f6ac,0x189a05b,0x0dc977e,0x10a56ca, + 0x0d543ba,0x0692335,0x0bb735a,0x0e51703,0x024547c,0x0dfbc01, + 0x15a7ed9,0x1f14232,0x0ec9559,0x116fd91,0x1416de9,0x1dabca4, + 0x075409e,0x1888388,0x00a67db,0x1913251,0x16f8c79,0x09309ed, + 0x0a69f5a,0x16794f3,0x0eb7fb3,0x0b05818,0x0ee3ec8,0x1595733, + 0x128b409,0x0092b46,0x17e2f48,0x01eb588,0x0380f1b }, + { 0x0a0068f,0x0cf35f3,0x1d4f02e,0x15914e6,0x0b67cf2,0x1d75be2, + 0x09522cb,0x1874d93,0x1340260,0x1a0bfcc,0x1dce79f,0x10ab981, + 0x1a8ee56,0x1c04a4e,0x02d443d,0x0ddffe1,0x1c28d5c,0x1d8bb87, + 0x165a9ee,0x0b57ddf,0x1a2ab4f,0x1b79332,0x081ec44,0x003b9f3, + 0x180a4b6,0x06317d9,0x1058afb,0x19006c2,0x0b83b3c,0x1dcb773, + 0x1acd263,0x15182fd,0x09b0fd6,0x1f7e175,0x16ea85d,0x1cb0696, + 0x1b110b3,0x08227aa,0x0a17a4a,0x1dbd7ae,0x04abedd } }, + /* 200 */ + { { 0x00ef376,0x0f0dcb8,0x0ffccd5,0x14cd9b5,0x156e5d9,0x143b236, + 0x095d51f,0x0d367b8,0x000f793,0x07a25c5,0x14b8a4a,0x163d418, + 0x1208c32,0x1b94d9c,0x1e37848,0x0473ab4,0x19ab26d,0x1a0c228, + 0x033929a,0x0d696fc,0x09f923f,0x0556595,0x08d7dbe,0x00c94b2, + 0x1c454e2,0x1175dc5,0x106fcc1,0x0fdfa06,0x1ff6f93,0x141dca6, + 0x019aeb1,0x1154ff4,0x1364b1e,0x19ba2e1,0x1cab382,0x1e0c2ce, + 0x11e3fb0,0x1846846,0x0cb4d1b,0x16631c2,0x06a20ab }, + { 0x085cbc7,0x1880b35,0x0a9faa0,0x0d269f3,0x1099094,0x1c78d9e, + 0x042239d,0x1338442,0x12247b7,0x1527fc7,0x121339f,0x1ae28a8, + 0x04b3171,0x07cc61b,0x100e525,0x028b052,0x1f397df,0x12ed488, + 0x050e445,0x0b01261,0x18bca6b,0x0d0ba11,0x1d7e542,0x012eb1a, + 0x1182182,0x0e87f5a,0x0691e49,0x1c18c04,0x0a315ea,0x134a57c, + 0x0dc3a51,0x0d75a09,0x07af8a3,0x1223ed7,0x19ffc1c,0x1c8982b, + 0x05456ff,0x0233455,0x0e5dd46,0x14f7e6d,0x045e353 } }, + /* 201 */ + { { 0x1092f71,0x0b3b249,0x15c5d81,0x05eb725,0x0b66b6c,0x045b62f, + 0x0526f8b,0x07d3b66,0x020c036,0x117ac1d,0x15c25fd,0x1a66079, + 0x0c688ac,0x15dc8b5,0x14303e3,0x1361d0b,0x02c84c1,0x08dfba3, + 0x1129ab4,0x1dabf2f,0x1369c76,0x1d688cf,0x1b22e22,0x1ca1707, + 0x0371beb,0x1532cdc,0x02199c1,0x198d2a1,0x173d2c0,0x1ad1fc1, + 0x1ed4c71,0x054b405,0x01cd3a3,0x0d0e827,0x1de368e,0x1dd04e8, + 0x15da333,0x1e2dddb,0x0f4dbb7,0x04994f3,0x015941f }, + { 0x17dd512,0x0607c53,0x17d90ba,0x0e3b86c,0x091b59a,0x1a9c315, + 0x0533421,0x195d01a,0x1d272fa,0x1121186,0x1f2d685,0x182c804, + 0x03eea3e,0x00f7cf8,0x1c02d67,0x0291b82,0x1270da3,0x0ea08e0, + 0x10606bc,0x1dc8918,0x100b801,0x0ccf1d4,0x1b7ca15,0x0135ffb, + 0x1b0bd0d,0x0122eb3,0x1a2cdc0,0x1073bf2,0x1836b8d,0x03f0737, + 0x124ed8c,0x17a6403,0x182e588,0x0815da9,0x09ade87,0x12c6db1, + 0x168641e,0x1bedbb4,0x0b40dc2,0x094231f,0x06d17c3 } }, + /* 202 */ + { { 0x181c99b,0x04420e0,0x12bf3d8,0x0390f7b,0x165dc90,0x106d5f5, + 0x0d11cdc,0x0b768c1,0x0537751,0x03ce1cb,0x1b09dd3,0x045c152, + 0x00d447f,0x15607a2,0x05484c0,0x1075a1b,0x06bc905,0x0419859, + 0x0a24128,0x1d2ef52,0x0b18e25,0x0cc2e28,0x077abff,0x15abed4, + 0x1bcb7a5,0x16ae7a6,0x07228df,0x179a003,0x1850b6c,0x0ec80f4, + 0x015e11b,0x16171cc,0x0c8194a,0x197c80d,0x15c4d04,0x1772e50, + 0x156ee28,0x14f8a4f,0x0753933,0x1487d3c,0x01ab9b5 }, + { 0x14fa7a3,0x0d5c918,0x058c81b,0x008f1ff,0x0c4af0f,0x06cfede, + 0x05c4e41,0x1fc999c,0x112c045,0x0105175,0x1db5f6b,0x08f1fb1, + 0x1a44fc5,0x053db7f,0x1b9cb17,0x1eeb110,0x09b6fd6,0x0bfd229, + 0x0aa0835,0x03a3632,0x11494df,0x0f93c4f,0x0f604be,0x176a7a4, + 0x0f083aa,0x1994c21,0x0ca80ea,0x0c90a73,0x1125022,0x104858a, + 0x1558c73,0x0e63ed7,0x1294d15,0x1731a70,0x187650d,0x1f64526, + 0x1ca966a,0x0140e21,0x0cfb631,0x0ad8435,0x024b349 } }, + /* 203 */ + { { 0x19824e2,0x0e5c332,0x1d3126f,0x109c27c,0x0dc4ce4,0x1f0f753, + 0x06899ae,0x0af4980,0x11e3ec4,0x1d95c73,0x0a392d1,0x0bc05eb, + 0x0d7e8b1,0x1199a98,0x07adb9b,0x0a405d0,0x09e17a4,0x1d65d1b, + 0x1c39327,0x082863a,0x1eb8812,0x059f095,0x10642bd,0x1e90dfb, + 0x1052311,0x1e72993,0x04a7eca,0x1ed883c,0x0f6c089,0x03f5db8, + 0x1def98a,0x07fd688,0x079850a,0x18c5d8a,0x0c466f3,0x01f9fbf, + 0x1a80d04,0x0e1497e,0x16fe649,0x1cafc78,0x0212d65 }, + { 0x015cf08,0x0d9c365,0x0bac8eb,0x0903c2e,0x0dfa4ac,0x0168602, + 0x0fe4d35,0x18f3a3b,0x174404d,0x0e7b039,0x0aff376,0x0883d26, + 0x1860508,0x0e34154,0x1a44328,0x0398135,0x01841ac,0x04a947e, + 0x0efb58c,0x02415db,0x1250e6a,0x1618667,0x0538387,0x1177e5f, + 0x0ba54e5,0x00aff42,0x1e7ea91,0x0cda169,0x0e7ce5c,0x18f3f67, + 0x0e83163,0x0df4d0e,0x01d43eb,0x189a43d,0x1680e67,0x0f2d8d8, + 0x06727ab,0x17cd557,0x0911f9b,0x0a934b8,0x066afa5 } }, + /* 204 */ + { { 0x180e91d,0x155d464,0x1beb696,0x12d5931,0x093cf50,0x1193315, + 0x0382a36,0x07d6132,0x0008145,0x0e90a98,0x077a100,0x067c7ae, + 0x122bb0d,0x1f0cd00,0x17db600,0x071ce8c,0x14c78a8,0x02c817f, + 0x04c4d23,0x055f6e3,0x057b74e,0x0bce7d8,0x0924c9d,0x1a07f1f, + 0x0a6423a,0x0053b0f,0x1563fe9,0x0fa9848,0x087e30b,0x006cbbd, + 0x09ad7a7,0x193909a,0x1c5edba,0x0b1d068,0x0e68f46,0x1bd9510, + 0x0bf6bf0,0x17979af,0x0af7ef1,0x0621ab1,0x001ef06 }, + { 0x0cdcbb0,0x0818b1f,0x0554afe,0x104f839,0x19e2d72,0x1ae4980, + 0x1c0c255,0x0613ca4,0x1969839,0x0e0e2d4,0x020b7c3,0x01fef9a, + 0x11ef9f8,0x0fcbf02,0x04541d7,0x036ab9b,0x1fe9cc6,0x079437f, + 0x03c9331,0x1b671f0,0x1ae3352,0x161b291,0x1b66e67,0x1620953, + 0x08ca810,0x1d6884d,0x1cc1480,0x04e01fc,0x1400f5c,0x11273b4, + 0x0b0a8bb,0x1dc188a,0x195d399,0x01520ea,0x15abdfc,0x0e156eb, + 0x0db730b,0x08404c8,0x04808d0,0x1fabd1a,0x00e4f5f } }, + /* 205 */ + { { 0x1f14c38,0x0322207,0x07caf47,0x155d9c2,0x1a5b59f,0x17b1984, + 0x0169c8a,0x1dd548c,0x082af24,0x0e4fb2d,0x0845677,0x17fdd73, + 0x0ff4ee4,0x1a74275,0x18f41d9,0x1559c48,0x1e00e0b,0x1c465f0, + 0x17eaf72,0x0ad1d5a,0x199d7ca,0x1262bf5,0x0f60354,0x17d30e7, + 0x0572ce9,0x02f4e23,0x15cc02e,0x03143b9,0x1541769,0x0989207, + 0x0d92488,0x16b6284,0x1e324ff,0x078b57b,0x140490d,0x1881bb4, + 0x0133d97,0x019a10d,0x1c08022,0x0c210ed,0x033d411 }, + { 0x078e5ec,0x0d1b5cc,0x08c9d4c,0x028d230,0x1de3e32,0x1182322, + 0x068cf42,0x0b3a2bf,0x1aa1736,0x1a60dc3,0x1753f9c,0x0945f24, + 0x14ac209,0x0131587,0x1259687,0x0b97887,0x03e447d,0x03ace48, + 0x148e4c0,0x1e42bc0,0x1f3492a,0x0f8fac9,0x1ffedb5,0x19bb6bf, + 0x03b4bc3,0x00432ca,0x12ff755,0x1a07453,0x0d76c09,0x0d358cc, + 0x1663df3,0x181e4f6,0x0790a22,0x0c667e0,0x0a1232d,0x1974aaf, + 0x16c54fd,0x110296b,0x0d19964,0x1548f6d,0x02d3de7 } }, + /* 206 */ + { { 0x1add3b7,0x13a3132,0x10aaab7,0x0b57e49,0x05888f3,0x12bec9f, + 0x1272b86,0x17fa82a,0x02c76f7,0x11170c7,0x080acc3,0x11d57c6, + 0x0a67f28,0x0e8e878,0x0699ae8,0x15a316f,0x1492881,0x087055b, + 0x1eb6c3a,0x04810d8,0x132f7d4,0x0294210,0x01c30cb,0x1f3413d, + 0x077f158,0x0c4c2c2,0x0bb0095,0x045526e,0x0987774,0x062e528, + 0x162f90a,0x0aecc00,0x1b79564,0x19be7a2,0x18c655f,0x12d8ff8, + 0x1631628,0x1811eee,0x04a9a2d,0x16cb638,0x047003b }, + { 0x11c1c96,0x000e0e4,0x05c3665,0x124f425,0x0a5dcdf,0x014883d, + 0x0b85f0f,0x0207572,0x1a3fe47,0x17e747b,0x0663b89,0x1abc9dd, + 0x18b0d09,0x071d20f,0x0988812,0x14a0d5f,0x0a5a26c,0x158e009, + 0x06d5c94,0x1ee6993,0x1fe12c6,0x0fa897b,0x0424f5e,0x1dc334c, + 0x0906eac,0x1531798,0x0415b47,0x17ff070,0x135f216,0x0c2b77f, + 0x091871d,0x1835a44,0x007e978,0x07ef437,0x1285ac8,0x165994d, + 0x033fe81,0x06b696b,0x0b39aad,0x00960d4,0x073dff5 } }, + /* 207 */ + { { 0x0e20fb8,0x0ac02ec,0x0fc22d8,0x09056a6,0x1c6873e,0x142a653, + 0x1c0055a,0x022a40b,0x0cb3692,0x1ff6356,0x024ade1,0x01d98fe, + 0x0c1fa3c,0x1422ff2,0x0d991fb,0x1e224b6,0x085f8b1,0x1ea3c0f, + 0x0c3c69b,0x04d0731,0x0b92c65,0x166e5c7,0x13bae31,0x0bedaa5, + 0x10ead8e,0x06e099f,0x0f2364d,0x03107c4,0x0ac45a3,0x0adea14, + 0x014853b,0x1b77f95,0x17ca492,0x0d709fb,0x0ff81f9,0x17be822, + 0x12ab05f,0x1250693,0x1d4d58f,0x16ee291,0x07544d0 }, + { 0x0797ace,0x0689a40,0x05f93fa,0x015f0db,0x016d6aa,0x0d347e1, + 0x09a23bd,0x109b7e1,0x19f9b26,0x05937a2,0x074bf06,0x19f5133, + 0x1552fef,0x11211ca,0x0be3609,0x06f01ab,0x069f63a,0x1c7891a, + 0x1353fab,0x068a9fb,0x1d09293,0x1bd39da,0x0ea0062,0x0aa5831, + 0x1f276e5,0x18e4d78,0x17fc9ae,0x0ba8ee7,0x1d4f44c,0x0a08036, + 0x1267bd2,0x0be7374,0x18f12f9,0x0527956,0x1b73d9b,0x14aecfe, + 0x1922f59,0x03b9f8b,0x0b526ea,0x1d583c8,0x0220081 } }, + /* 208 */ + { { 0x037a0ba,0x1eab9dd,0x17d8c10,0x19ba2ed,0x05a431b,0x10387b8, + 0x0b3f310,0x0120664,0x067c2d1,0x055e987,0x02f3e97,0x0bbd97f, + 0x0b362c9,0x1bc3d88,0x19f49dd,0x0bcc9ae,0x15e6ec0,0x1309648, + 0x19a70c3,0x0d2c639,0x06359e6,0x07b4171,0x09f2776,0x1ff9870, + 0x01f1295,0x0513c81,0x0628ab7,0x0d51dcf,0x1d500a0,0x13c225a, + 0x1163803,0x11b01ad,0x1746fc7,0x1886643,0x0efa457,0x1048c0a, + 0x019f6fd,0x0719459,0x0dcce11,0x158237a,0x0620541 }, + { 0x09e5a29,0x1e9c128,0x0c783df,0x016864a,0x0748d7d,0x1c41dcc, + 0x04d5334,0x0f51ee9,0x08bfbb1,0x15c563a,0x0b4b171,0x14cc0be, + 0x03a4616,0x0de58dc,0x1659894,0x04cb567,0x1042fee,0x067ba98, + 0x0c89416,0x1ae7f7b,0x1556c70,0x1a78616,0x0484750,0x164b366, + 0x061d854,0x1bec310,0x1710acf,0x1fc8c0d,0x0a4949f,0x02c2f43, + 0x0b13172,0x02c1ddb,0x0ddcc8b,0x1121002,0x199d5a3,0x0c30099, + 0x0214165,0x19c2ad2,0x0fa5e47,0x131f265,0x07f3781 } }, + /* 209 */ + { { 0x1a6639a,0x1a5ed6f,0x0e4668d,0x080556e,0x0cbd48d,0x018f168, + 0x1c8d91c,0x03eb8bd,0x0d0599d,0x04f715e,0x0e110ed,0x16c1c1a, + 0x08d285e,0x1349c97,0x0faa4bc,0x0a71fb7,0x1bfb8bc,0x048a2af, + 0x11a6dda,0x0b3fe3c,0x1682ae2,0x0fa0ef2,0x1073b2c,0x0a5a35d, + 0x0f07199,0x023643b,0x079efdd,0x19c4a30,0x0ad2f11,0x16c3141, + 0x19f2e4e,0x0d749de,0x1a3cd31,0x1d51f47,0x0813941,0x11f9cd1, + 0x061bb60,0x0ba0b85,0x043433b,0x167ed58,0x06de716 }, + { 0x12d6dc5,0x0c6820b,0x1973539,0x0cc72f8,0x1ed2cde,0x0f5a745, + 0x1f86032,0x1b6f5ce,0x075fa2e,0x113aa34,0x199ce15,0x049d523, + 0x0e4b303,0x11ae459,0x08ea158,0x0510ec0,0x0c2a8f9,0x0cefb6b, + 0x1bd7a2d,0x1830bfe,0x148aec2,0x159d6ab,0x1e24b84,0x095df78, + 0x1b4f2d5,0x010bd75,0x03ba1a2,0x0922a89,0x19bd5b1,0x0fb8d8e, + 0x1de89b1,0x05fe01b,0x1ccd166,0x18ef772,0x1c5ee56,0x09d7933, + 0x1fe1f77,0x0c1b0b1,0x096c242,0x061767a,0x051f908 } }, + /* 210 */ + { { 0x0922461,0x1b7d0f9,0x034524d,0x062ca1a,0x1bb1b1c,0x0c3046e, + 0x070cc37,0x00d2572,0x136b899,0x1309625,0x180148f,0x1617bea, + 0x05e1977,0x11b512a,0x0bffdc1,0x07b1df1,0x0781172,0x166d3e9, + 0x06f79ee,0x1789770,0x178e0b0,0x1976952,0x0f2c202,0x0365c04, + 0x00d0d17,0x0d72ded,0x1e506ee,0x0dbe719,0x0a65c5f,0x00ede0a, + 0x03a1776,0x1833bb3,0x198c82d,0x037c9bf,0x11fd488,0x118c26e, + 0x1f5bbe7,0x09d1612,0x12f9e78,0x11c1546,0x05eed21 }, + { 0x1d4dc0b,0x12baa00,0x0c1f855,0x0feacd7,0x01ae5f2,0x1112ead, + 0x1afaee0,0x0d7d30b,0x01189ec,0x19d690e,0x1936757,0x0319d99, + 0x1917da5,0x0b5b2da,0x128b4fb,0x0ee3990,0x1758ffa,0x13fcc40, + 0x0b1a69e,0x0d5c245,0x046d50d,0x18e3734,0x12dfcc2,0x1a17627, + 0x03a605b,0x003c601,0x175cfc9,0x1421fd9,0x10a9969,0x0c6672f, + 0x01a3145,0x17b1eb0,0x06bf615,0x12370e9,0x0a1e456,0x115e65d, + 0x0287d30,0x1ba7408,0x10953ab,0x00d4c4c,0x08c14ba } }, + /* 211 */ + { { 0x17ee201,0x1bc4ad8,0x09dc321,0x0311caf,0x005aa47,0x01122b6, + 0x19d8e5e,0x03a3387,0x0c9c3ba,0x1f37c60,0x027af82,0x09ff687, + 0x16fe85f,0x0673fdd,0x02f3338,0x0d8c8a7,0x12a6526,0x143b755, + 0x1e68e10,0x158d219,0x19815c9,0x18e6647,0x07d73ce,0x1ed0fbd, + 0x1be6a9c,0x00afd0b,0x120e0d7,0x19f821f,0x0ef2ebf,0x07ed8a8, + 0x19821ac,0x11094a5,0x197ecd9,0x08f5c4f,0x1e8ac33,0x1482dcd, + 0x1ecc03b,0x1e8acc9,0x0597b8a,0x0bbd576,0x0645c0a }, + { 0x0aa7e31,0x02102a8,0x1697653,0x185f0a3,0x0ec8df0,0x1937355, + 0x1a424f1,0x13532c8,0x02619bf,0x16dee1b,0x0fef55c,0x01c1c4a, + 0x061b426,0x06384f0,0x10967ee,0x1d8b72f,0x0bbcdda,0x0fd5fbe, + 0x12dc0fa,0x0bd163c,0x0fddb4d,0x17039a7,0x06c1b95,0x0abf14a, + 0x0a4f91f,0x046816a,0x08fd597,0x1f0c117,0x0d1d947,0x03e940b, + 0x0da08bd,0x0b9cf62,0x0c36156,0x0212106,0x17bcc74,0x0dc8ddc, + 0x083567f,0x132fb83,0x1b246ca,0x081a5f4,0x027e9ff } }, + /* 212 */ + { { 0x1e952e7,0x08c49eb,0x1c61d49,0x078e6b7,0x15b3058,0x1f02488, + 0x1664a5b,0x194e656,0x0806d2f,0x1a28c2c,0x017b649,0x0d40371, + 0x0c71ab7,0x16cfaaf,0x13a765d,0x175397b,0x12048f2,0x19ed305, + 0x04ac4ca,0x0f810cb,0x11d7697,0x0584c82,0x0db72a7,0x1115c4b, + 0x0ab23d1,0x19eece1,0x1f882ab,0x1e8d3e7,0x0d74d09,0x1be7ad5, + 0x0ef6f47,0x04553d6,0x15efe5c,0x008621e,0x1e884dc,0x0118bdb, + 0x1787026,0x1110bda,0x05ddab6,0x0ce7b59,0x04feee5 }, + { 0x1d3d780,0x0c6a95a,0x1d10c38,0x060e2cc,0x0dadb5d,0x1a10ab2, + 0x0e1b969,0x10c641a,0x08d6bbb,0x0c61487,0x18f7457,0x06465a4, + 0x16981a4,0x0c4c231,0x1439f2a,0x1596267,0x04da519,0x1a89c3c, + 0x177207f,0x1c7f57b,0x043a832,0x0a18ccd,0x1f09e16,0x0e862c7, + 0x0abcf32,0x1d3ada6,0x15d3e53,0x1f40217,0x14a6279,0x1a1eab4, + 0x0930a29,0x196caf4,0x1d2a888,0x112f560,0x140fa1a,0x1efdde4, + 0x04c561f,0x08d2e98,0x1783bb4,0x1cf393d,0x04fe818 } }, + /* 213 */ + { { 0x1c1c7ff,0x0964ebf,0x0b44009,0x1b3f513,0x09bd419,0x1274e65, + 0x0492901,0x1999274,0x043942e,0x0265e5c,0x05a56ce,0x03fb0e9, + 0x1f004c2,0x0108b2d,0x120767d,0x02204d3,0x028dde0,0x0f1192b, + 0x0a6c013,0x06e8aeb,0x1c21ec9,0x1ffb6e7,0x1eccd1a,0x06e58fb, + 0x1a64b4d,0x0715626,0x0fc8125,0x1d96f5a,0x07c150c,0x00daf43, + 0x16158b1,0x1856e47,0x19395ce,0x0991894,0x1f15fb9,0x0f9235b, + 0x110b659,0x1788b0f,0x0fff381,0x0536e9a,0x0819155 }, + { 0x0d9d4ee,0x09218b7,0x1c063b0,0x08d135f,0x1dffa15,0x04d1fa1, + 0x0d27caa,0x1649574,0x0d467ef,0x0d8f471,0x040b88b,0x06a8072, + 0x0b18dea,0x1297841,0x0aae14f,0x1ba8e84,0x0c1ed36,0x1389851, + 0x0a5747b,0x01d0da0,0x1ad3ca6,0x043e3fa,0x19ab1a0,0x10c8cb1, + 0x1cecfde,0x13287c1,0x0518744,0x05ccd84,0x1850997,0x00a85e9, + 0x027fbbd,0x14cc645,0x1183f3a,0x0e3ca87,0x12f9e4b,0x044ea8a, + 0x1136770,0x02608d8,0x1bbcc9d,0x18fd1d4,0x07d06bc } }, + /* 214 */ + { { 0x090212f,0x02ca138,0x011224a,0x18aa43d,0x091b7d4,0x16ddc93, + 0x0108af8,0x1009807,0x1bd81f8,0x0bb90f6,0x06f0d8c,0x17dd591, + 0x0dc136c,0x1dc7802,0x1c6d82d,0x115709e,0x0d04e21,0x0934899, + 0x1b32053,0x0492ddc,0x1c15b0e,0x0bbafd6,0x02cb38c,0x1a4478a, + 0x1c08466,0x1c5c171,0x193184b,0x0e43954,0x1653559,0x08f5d25, + 0x145669d,0x18fa7b3,0x033aad5,0x0a1231a,0x074ba03,0x143cc37, + 0x1c673ca,0x0fb2aff,0x12e4852,0x133a1f3,0x048b52b }, + { 0x1dc05be,0x0a9ccf7,0x17a68e4,0x1027c12,0x1e70db1,0x0d9fed6, + 0x18ba737,0x0a288f0,0x01a0094,0x15818b1,0x083a8e8,0x1018472, + 0x0b4b279,0x111dc7f,0x14e53c6,0x02da958,0x0563e56,0x10b1fb9, + 0x1c50866,0x1ff27f6,0x0474aa0,0x0949eb1,0x149be5b,0x19fc4ed, + 0x12ea87d,0x08aee90,0x1d1c0e3,0x164f7e5,0x18168ea,0x0192fa0, + 0x06b9632,0x1665531,0x1704222,0x0f89df1,0x0e42ff2,0x1b46d28, + 0x0d0684a,0x1713030,0x1dbb3c5,0x10f3b18,0x017c0de } }, + /* 215 */ + { { 0x0c01958,0x0fa29ee,0x0e4ef29,0x0839d10,0x1d94595,0x0fadb6b, + 0x1428558,0x178bcc6,0x07e2d36,0x08e1e43,0x10e9b0a,0x1b094b5, + 0x0df6c7e,0x0cc0036,0x04f102f,0x1d876f2,0x0875671,0x0fbc5d8, + 0x10fa26a,0x051edd6,0x01ed1c9,0x19d70f5,0x1f7ca37,0x049656b, + 0x1a5b1b9,0x102b15d,0x146845b,0x123a4e0,0x1ed3e34,0x015b8b3, + 0x11823b0,0x0b78160,0x091cf7b,0x0bfacf1,0x05a6317,0x0e61ca0, + 0x15c799b,0x1e1a86f,0x1875c31,0x1c4158d,0x06862b9 }, + { 0x1fa1f64,0x17a73cf,0x0d255b1,0x1543c48,0x1ed6a91,0x1ba9197, + 0x1b83336,0x00fd341,0x10322d6,0x1e4859b,0x1fbe1ef,0x15a48c5, + 0x1429480,0x015fe79,0x08525a7,0x1c71ff8,0x1e0a539,0x0372908, + 0x0a94527,0x13d84c2,0x15322a5,0x096b835,0x0657f88,0x1390852, + 0x1b108e9,0x0417bbf,0x0d77201,0x099d5d4,0x12d2987,0x0185dec, + 0x1ba9698,0x155d42b,0x142dca5,0x1884e56,0x0f1d261,0x13ad587, + 0x090af64,0x070e201,0x179b319,0x05aa3f1,0x05093fa } }, + /* 216 */ + { { 0x02d553b,0x1994026,0x10a7133,0x04772cd,0x1c1abe2,0x0b48a56, + 0x152708a,0x192aad4,0x1999976,0x064fc5a,0x1a0fcf6,0x0f7aeed, + 0x17c22c5,0x1e42f62,0x0a50aad,0x0c3ea9e,0x1e56e2c,0x0779a03, + 0x084f6d2,0x0bd195e,0x18c7f00,0x1ef9934,0x11c3214,0x1814a96, + 0x088d7ca,0x00f737a,0x1582dd4,0x0d7ad7d,0x0a4bd9b,0x188338a, + 0x053c040,0x0dc1311,0x085bc3b,0x0950029,0x106bd7e,0x15d80ce, + 0x0f7ef24,0x18b2137,0x090e0cb,0x09ad8ef,0x012f9c4 }, + { 0x1313a1c,0x0f4b241,0x0cdc654,0x14678b1,0x18edd3d,0x1620224, + 0x0fd4b1e,0x1d09db7,0x10dcb5e,0x136537b,0x108be21,0x11eadba, + 0x0eec0ae,0x0330f61,0x1def150,0x0a47820,0x13ad422,0x1369cc8, + 0x039f2cf,0x0bc3d0b,0x1b45d10,0x1fe4bcd,0x11f24e5,0x12f6b24, + 0x1d4a909,0x1f39910,0x0fa254b,0x1dec514,0x1462410,0x0c13a74, + 0x1034235,0x0b2f01e,0x0cbed0f,0x0887632,0x089c238,0x0627af8, + 0x1679b1a,0x036c333,0x0746346,0x09c4d5c,0x002f75e } }, + /* 217 */ + { { 0x1f307d7,0x1bf5fa3,0x11dc6d8,0x15a0282,0x0b644a6,0x02d4063, + 0x0f594b8,0x0630546,0x1fed07b,0x078d079,0x1b965f2,0x0ff26d2, + 0x1ec09ee,0x03ffe00,0x0a9fb0f,0x0e7739b,0x0fef8f3,0x0aa4fc4, + 0x0eee262,0x1a32c38,0x07b7c88,0x14efe55,0x164a93f,0x1c95641, + 0x19ee23a,0x0d2897f,0x07d7b2c,0x0b5d4c8,0x0fb47df,0x11bff19, + 0x1039da4,0x04ba10b,0x0a5c420,0x1aad14b,0x15609b1,0x07b9224, + 0x1bce972,0x05cc2fc,0x0650560,0x0ccc72c,0x072b1b5 }, + { 0x10e5558,0x045043c,0x1e0275c,0x020d135,0x1853604,0x189dafc, + 0x1ee2908,0x035d0bc,0x055a49d,0x15d0949,0x1c6c2f9,0x0961586, + 0x195e76c,0x09c7370,0x1413ce6,0x13442b0,0x02260ae,0x146ea0a, + 0x1a12173,0x009d372,0x1e43d8b,0x12c43f7,0x1e5312e,0x038bce7, + 0x08e67f1,0x0e20893,0x033dae6,0x04c47c5,0x0a96629,0x15543d0, + 0x14fcb42,0x099405d,0x066772a,0x1daa8d9,0x1938b58,0x0ad1dd1, + 0x0e78b5b,0x15d94c9,0x096b737,0x02dc2e4,0x05df192 } }, + /* 218 */ + { { 0x1f2e7e3,0x13f0f46,0x1f78800,0x11b1b40,0x1183cc6,0x05734a5, + 0x0e9a52d,0x1119c6b,0x13ca62e,0x0b6cbef,0x1fb4b22,0x0276a5d, + 0x0f3de47,0x135e842,0x01b1038,0x12477a0,0x1bbfc81,0x00f4db8, + 0x0ab31ac,0x038f6c3,0x0840999,0x1247b2b,0x194324d,0x1e8ea48, + 0x161d187,0x05109c2,0x06fff4f,0x021e562,0x1914186,0x0fd7fd0, + 0x0265a45,0x12abca6,0x11236de,0x196bcc7,0x1baa861,0x16c2797, + 0x06a2a48,0x1da2753,0x070c9fd,0x185c151,0x0452265 }, + { 0x1430010,0x0f63c92,0x03012b5,0x1fd7a12,0x0ac786f,0x14e9fae, + 0x1d3fc82,0x0bf4bf3,0x0a3edc6,0x05fa089,0x0fac47f,0x073819e, + 0x0088248,0x0552db8,0x175b53a,0x1157171,0x1fdb756,0x171138e, + 0x1d11583,0x1d86e76,0x1296e43,0x130e7ba,0x1e3abe4,0x152db36, + 0x1ae0e3f,0x1ea8c04,0x1770977,0x16625a5,0x0b77110,0x1c5a35d, + 0x191ae3d,0x16bd9e3,0x09efc8d,0x1f65503,0x0eb9827,0x03832a5, + 0x1f4dbde,0x118176a,0x015550f,0x1f23c0f,0x014b02b } }, + /* 219 */ + { { 0x07e5b57,0x0e3b45c,0x155cb1c,0x0fea634,0x0bcc78f,0x0cbee40, + 0x0fe2fdd,0x0be9ff2,0x1139e17,0x1470136,0x1329b2c,0x0e4f972, + 0x1c6b83b,0x003cfbf,0x0bf8ec8,0x1a2e05d,0x0decf3b,0x015652a, + 0x0bc371b,0x082678d,0x035e17c,0x12e67af,0x0fa8799,0x0aa0b8d, + 0x11a4834,0x1c4d334,0x0398402,0x0c6757a,0x1d03882,0x138360b, + 0x03259b1,0x03419f2,0x0efffbe,0x0eb263d,0x0f9f42b,0x0c9b08f, + 0x0ea2aa4,0x0de6fdd,0x1429752,0x0e8598f,0x085e07e }, + { 0x1c25bca,0x1705305,0x13b08ea,0x03c89ec,0x0e8e55f,0x03dbb9b, + 0x05b62d8,0x013c3cd,0x0d30059,0x14853a3,0x112642a,0x199a597, + 0x1d072b1,0x034717a,0x03f9b1b,0x11d921a,0x1f053e2,0x0c90762, + 0x0010330,0x043f69e,0x02c779b,0x09fe625,0x09cdd6f,0x1758fbb, + 0x1def9e1,0x069fafa,0x04d703e,0x1862baf,0x0cd318d,0x00b8165, + 0x071c45f,0x1d24dee,0x12823c4,0x179cd37,0x02efb40,0x0671b6b, + 0x1db6932,0x1a4918b,0x1d0c396,0x13f1a93,0x0096403 } }, + /* 220 */ + { { 0x0999eba,0x1a78b2b,0x0c1485d,0x0f63bcc,0x1d8ee28,0x0593349, + 0x1dc9b78,0x143b035,0x13f8942,0x1a2349c,0x0f84f0d,0x0c2bd40, + 0x0fbcf6b,0x0a7139e,0x03030d6,0x0b8ada6,0x056c672,0x127e99d, + 0x02fa5e8,0x0a695b5,0x0251a57,0x133e115,0x1e6490a,0x018b892, + 0x1bdb59d,0x1b42728,0x131a909,0x0f9aed9,0x06bf59d,0x0bd66a1, + 0x0ca4502,0x0cdd37d,0x1404a2c,0x171f4ac,0x1a61725,0x008e71f, + 0x0ad666d,0x1d9f075,0x1795af2,0x1a4c778,0x0626b0f }, + { 0x1a1ec42,0x0bedd70,0x11411c8,0x1756b59,0x0a6ae7d,0x0998e8d, + 0x0ac7a19,0x0df6fc3,0x03d3012,0x0229838,0x186146e,0x13c1bdc, + 0x0428064,0x15344aa,0x01bd28f,0x1ec6510,0x1adcb56,0x1a5df21, + 0x12bfe53,0x1737b57,0x17be036,0x12de831,0x0365079,0x0de7576, + 0x19d4468,0x1eb410b,0x12ab5ab,0x090d225,0x1e15341,0x048f7fb, + 0x05a68ee,0x1d70dfb,0x0c426ce,0x09461c4,0x0a0445e,0x016adcd, + 0x16399e0,0x1f389ac,0x1ab064c,0x1b342f6,0x009bbdd } }, + /* 221 */ + { { 0x0fd3673,0x1ce0ef2,0x181dd78,0x034cb91,0x1880d9d,0x04e3ff7, + 0x10771ca,0x0008e4b,0x03529d2,0x1b39af7,0x11ebcd6,0x05da78e, + 0x15c1f8f,0x08977ef,0x1ce663e,0x13872b9,0x0184985,0x0f6b913, + 0x19a5e57,0x12745e1,0x12a7237,0x0b4358e,0x029aae3,0x15105c9, + 0x015de22,0x0bf0064,0x13e76e3,0x1cefadf,0x067547b,0x1d99011, + 0x170221b,0x093821d,0x02687d4,0x1f6a65b,0x185df20,0x153e387, + 0x1af366e,0x0aebf82,0x0b4939b,0x171a3df,0x02eaa01 }, + { 0x1357c74,0x1fdb80f,0x1e51791,0x1553c76,0x13085c4,0x02d482c, + 0x01ccdba,0x1929e13,0x1be0244,0x09c047f,0x159837d,0x1f27476, + 0x1691ddd,0x19dcaf6,0x1d8ddef,0x041a916,0x1b7bb39,0x1c8dc88, + 0x1a84f3c,0x1e117f0,0x0e587cc,0x0bf500c,0x14fb63e,0x18aa328, + 0x0434378,0x0d358f5,0x07834b5,0x1cd5bbd,0x16259a8,0x1247cdc, + 0x177f0ac,0x1dde2fb,0x0ebceae,0x1ce42cb,0x110d55f,0x11ed296, + 0x07d5bba,0x068a878,0x061ad23,0x1d36983,0x002d31d } }, + /* 222 */ + { { 0x079499d,0x1cf0f6f,0x0ab69ae,0x11fa1f8,0x16ca8ff,0x1ec9ab7, + 0x1e3a069,0x04f7d81,0x1e8f063,0x01e8e4f,0x002faef,0x042e766, + 0x1b805c7,0x009e0c0,0x1082821,0x13a0200,0x07ef0ca,0x14f4d0b, + 0x0bbb775,0x19213a3,0x0a72076,0x1fc71d4,0x1928665,0x0f6853c, + 0x1f7a7a7,0x1f49e73,0x1172534,0x1581f7e,0x148407a,0x0a53f36, + 0x19fcdda,0x1523243,0x16679e2,0x0ddeb7a,0x03cfb87,0x13e47fc, + 0x0bf9fa9,0x08bab36,0x15d971e,0x1e5c1e9,0x0965860 }, + { 0x1a5f79c,0x03815bf,0x09b79cd,0x0cb5e5a,0x130bd42,0x19f0674, + 0x02e61b1,0x05a8b7b,0x14ee44a,0x0df3df6,0x122869f,0x00492ad, + 0x0ec129e,0x1be6fc0,0x17016b1,0x14b36df,0x02b589c,0x1b8535d, + 0x066096b,0x1080433,0x10b6fc4,0x0a3d11f,0x074a12d,0x141515e, + 0x010a428,0x16c58ed,0x04acabd,0x03d6366,0x135ee3b,0x021d19c, + 0x1b3c145,0x11dff4d,0x007eb26,0x132a63d,0x021b598,0x182ddc8, + 0x0549ee4,0x1de280a,0x02949e9,0x0643f53,0x0650810 } }, + /* 223 */ + { { 0x07ed9b2,0x072305b,0x0f4927c,0x0186db2,0x0cda0fd,0x03af0e0, + 0x18fa623,0x19376b2,0x1614bc0,0x0bddf49,0x1a1815d,0x100334e, + 0x049a9b8,0x0476e2a,0x0df8abd,0x0b30b51,0x19eb51a,0x04f3bf6, + 0x0efc093,0x04a4e9d,0x0636dd0,0x040aa2e,0x1662d8a,0x001b740, + 0x1aed048,0x11d1cde,0x06078a8,0x1f84027,0x0cb4f27,0x1eae2a8, + 0x11f719b,0x16a40d1,0x127032f,0x0fd0ad6,0x12ba05a,0x0593417, + 0x1a7ca8a,0x1037909,0x194bd81,0x08d30c4,0x0982950 }, + { 0x011c128,0x1a30017,0x09f8f8d,0x1a1cdb9,0x00dfae5,0x0a91324, + 0x05b8b65,0x087c880,0x0880b71,0x12fc479,0x0e2073d,0x11a8a4d, + 0x1eca3d2,0x0fdc357,0x1167747,0x1f2b1f3,0x0c24c74,0x1aa4430, + 0x12da7d3,0x1d48793,0x0cecd06,0x17399a7,0x14d0f26,0x0652e26, + 0x0ccd635,0x0062e61,0x0d7ce9b,0x12bfe80,0x12653ba,0x10e659b, + 0x0f4b806,0x144a0a4,0x1510fdf,0x13f5918,0x038a988,0x01ddca7, + 0x0a23cd1,0x0fe4506,0x1d52fab,0x0367cf1,0x04b7e6e } }, + /* 224 */ + { { 0x15f928b,0x083b7ed,0x13b1e72,0x0d6e68f,0x06250bb,0x007620f, + 0x1de62b0,0x18ea96c,0x09d9619,0x006905d,0x10d0fe4,0x01a0b3c, + 0x17ed42c,0x028c9ae,0x1ce7a15,0x0039c7b,0x18264f7,0x0131c88, + 0x07e1eab,0x1e4aa9c,0x1aaace8,0x04b2fc8,0x1f7759e,0x048a73f, + 0x1163fa3,0x0cacb66,0x112eb3a,0x1902be5,0x0f9ea55,0x061554a, + 0x1575e32,0x1de49c8,0x0b2aff4,0x0e1353d,0x1024737,0x05e1dac, + 0x00ca282,0x0521058,0x1d96255,0x18ba652,0x00611c4 }, + { 0x1e81829,0x1000e54,0x0b33c64,0x0011450,0x1ed3332,0x0ef6cde, + 0x1f7863e,0x00617fa,0x1b78890,0x1c9d606,0x1e97759,0x123a6ae, + 0x0bbb00d,0x00169e1,0x1e88e9e,0x12029c2,0x08cfb54,0x1ffcafc, + 0x1c6db81,0x037e978,0x0c8b7cd,0x1011ac4,0x0b8ec92,0x02240ec, + 0x135b8a4,0x0984da9,0x1b1015b,0x090380b,0x16a1b52,0x0086748, + 0x1d1571d,0x10a02f3,0x1e03271,0x089045d,0x05decf3,0x002bcd8, + 0x10cbfe5,0x0d12604,0x0159942,0x0523821,0x0820795 } }, + /* 225 */ + { { 0x07d353e,0x09e7f8e,0x18ed74b,0x1afbc19,0x15e7ecc,0x143b1ae, + 0x01d7db2,0x07d6962,0x025f9ad,0x1420270,0x12d6bb6,0x1d1240b, + 0x016b963,0x04f910d,0x17b8360,0x159493c,0x1d9ea41,0x06b2642, + 0x1110a8d,0x0d89d26,0x15a46a4,0x1f1e7b2,0x0b1bfe5,0x082faf9, + 0x05c1ee5,0x0263b2b,0x07bafe7,0x1020135,0x1a63886,0x0e9cc46, + 0x11a56d8,0x1ed68e5,0x002b46a,0x188b8b2,0x05942df,0x063fbca, + 0x1e0c05e,0x1c7939d,0x1129e53,0x06d5106,0x07487b0 }, + { 0x03e2370,0x072bace,0x1c66a18,0x07f0090,0x19d5819,0x117cd50, + 0x0fcf29b,0x136741b,0x1614471,0x163f4ac,0x1fb086d,0x18e9bdf, + 0x1fa9049,0x1fa8675,0x08192c8,0x1bc2b17,0x0c049a1,0x1589411, + 0x07549fc,0x096fb36,0x0430b65,0x0e87fe8,0x111c216,0x00a88d7, + 0x14a674f,0x0ca9be3,0x0e8eb76,0x0aa64a3,0x1533b5e,0x0b65f19, + 0x13928fb,0x04fc833,0x12f44d0,0x0dcbc97,0x1a0a974,0x1e5b09d, + 0x1b6fa69,0x1b5891e,0x0ef7731,0x18a43f4,0x0834f85 } }, + /* 226 */ + { { 0x0e9b31a,0x1a3e096,0x0edcca4,0x15fc7f6,0x1d88522,0x1fc87e8, + 0x1ed354b,0x03a979d,0x02b1a08,0x1d8b9c3,0x047c214,0x0374548, + 0x1a538c1,0x0a0db01,0x056e4f0,0x1ae82f1,0x1aab10b,0x114c9dc, + 0x0644a61,0x17a08c1,0x0ba5ccb,0x1877505,0x19a7ebe,0x0cc312e, + 0x0462235,0x12a6a42,0x10d9ffe,0x14c7713,0x1478da4,0x0e8e8e1, + 0x1df2eb5,0x154c069,0x1339227,0x189c8e2,0x017f986,0x0a1cdae, + 0x174ff51,0x0a5b307,0x0d53374,0x014a665,0x0639d8b }, + { 0x02217cd,0x118b10b,0x039be90,0x1502385,0x0e0e4a2,0x1b36e01, + 0x1386085,0x1ded1b3,0x1046a06,0x0931b9c,0x0484054,0x0463bbd, + 0x1344eea,0x08a14c6,0x01f23c8,0x0afd20c,0x0ba63d9,0x093f939, + 0x17a32b8,0x1d01994,0x063fe7c,0x11127bd,0x1605baf,0x0ce7c68, + 0x0e5a789,0x1ea26f6,0x094daea,0x06ead44,0x1f77af1,0x10d771d, + 0x0f19135,0x0579f31,0x0b2bf6e,0x14b1630,0x07cca7e,0x067616b, + 0x0bb5002,0x1b4d0d5,0x100b2c1,0x06c18ea,0x0409031 } }, + /* 227 */ + { { 0x070433f,0x1439d0b,0x17f2134,0x0c4a927,0x09394df,0x1e7c4f6, + 0x0866a03,0x02dd60b,0x0db2976,0x1cf2188,0x18c11b8,0x1b93b3c, + 0x1e50742,0x0ef4e54,0x06b6320,0x03a1be6,0x194fb7b,0x0c3555f, + 0x0cf20b4,0x1b44f43,0x0d8436c,0x1a1cb81,0x1ec68bb,0x0102533, + 0x1fddc46,0x11c1405,0x1748e58,0x0965691,0x1c9353e,0x0179bd9, + 0x1a4b6cb,0x025f714,0x1b5b317,0x0023a6a,0x08ec206,0x11f370f, + 0x1e95257,0x0c84c30,0x0af2361,0x1dbe6f4,0x080668e }, + { 0x19a0249,0x0e69ad9,0x1abb8bb,0x0965f15,0x0f230cd,0x11ef82d, + 0x05791c8,0x1e852b6,0x0e0e937,0x1b34c15,0x12458ae,0x16e5197, + 0x01019d2,0x07a4ee5,0x144aba7,0x00f68b8,0x1a7630f,0x088da48, + 0x00e1d3a,0x09e6994,0x143348d,0x132265b,0x107f43a,0x0b66187, + 0x19ae1f9,0x05609fb,0x17b62d8,0x006c5a9,0x0ad81c4,0x0a7fb0f, + 0x0a27a0c,0x093187a,0x1600dd4,0x10b8176,0x1067094,0x06bf963, + 0x1a9c1f3,0x1194fe1,0x1b3a564,0x09037bc,0x0046775 } }, + /* 228 */ + { { 0x1233c96,0x0f2b71c,0x1abfb8f,0x1900e6f,0x068c409,0x0d5e344, + 0x046f480,0x00b595c,0x12b4862,0x196754d,0x0415b03,0x0fc2de3, + 0x01e3238,0x12ee152,0x1d4d96a,0x17d0dd4,0x0cc12b4,0x0bb614d, + 0x158ca53,0x1f956f1,0x1f24a01,0x058655c,0x0076fa2,0x02980a9, + 0x06e5bf4,0x1d53b32,0x0f2e5ad,0x1c22312,0x04e097f,0x1ad8bb3, + 0x0a6d927,0x0a7f9eb,0x196422e,0x1fb1a50,0x06f42df,0x0ab2f19, + 0x1c22989,0x1f59c71,0x1115ad7,0x1f61067,0x0038a49 }, + { 0x1e93257,0x1c0c609,0x106cd78,0x1b4c24e,0x14cebc9,0x1560358, + 0x04925f2,0x02c9edd,0x13daa11,0x113c719,0x080d2a0,0x0cbc9bc, + 0x10e7cc5,0x050dd31,0x1f7257c,0x0df7b76,0x1236695,0x140eecf, + 0x0c4cb75,0x1cc6337,0x1337c63,0x117e120,0x1b88ac0,0x117d638, + 0x081937e,0x05611c2,0x176324e,0x0763329,0x1b56448,0x1d65535, + 0x01ed533,0x00df230,0x07cd44e,0x06cf98d,0x06eea3e,0x0c3ba87, + 0x1f74a8e,0x06153c3,0x1598198,0x0442436,0x04bb76e } }, + /* 229 */ + { { 0x0354817,0x08f4573,0x10e1e85,0x15e0716,0x13d494e,0x0ac4c31, + 0x11a2216,0x024990d,0x11dcbac,0x10a9c13,0x16b419c,0x1f1981d, + 0x16f487a,0x128072e,0x0cc147f,0x0feab5a,0x11bd6e4,0x085388d, + 0x11d1ab5,0x0e134f1,0x135ea68,0x1132017,0x09fc5c9,0x0618260, + 0x08efafb,0x04be368,0x0701b1d,0x1de3808,0x03e2da9,0x07676e6, + 0x1cf431d,0x0125c20,0x0c5f96e,0x095ba18,0x0f3caa8,0x041e272, + 0x0107eb0,0x0c200b1,0x1e62c91,0x0bef6ed,0x08843d2 }, + { 0x1b2a83e,0x080ee76,0x1c91385,0x005771a,0x1cfe8fb,0x12efb15, + 0x0196764,0x1861204,0x142ab6f,0x038aee7,0x0277f4f,0x00ab41e, + 0x0a73c05,0x11ac857,0x19d1763,0x0e93c24,0x0d876ff,0x1a9c17a, + 0x0483198,0x13fddf5,0x11cafc6,0x08cfeb8,0x1785808,0x0eb89ab, + 0x1c3bd90,0x1f9210c,0x04f7b5a,0x100197a,0x03a1163,0x1075b13, + 0x0de31fa,0x0fa4c98,0x1bd7958,0x0e4c61a,0x1915c56,0x0aadc45, + 0x1a7373b,0x1f9516f,0x12525c6,0x073126b,0x00503f9 } }, + /* 230 */ + { { 0x1dad4f6,0x0ee3338,0x086d96b,0x120497d,0x038e488,0x02e9ee9, + 0x1238bd8,0x113f6ed,0x0b0d96b,0x1eafaef,0x06cb2c4,0x146acc0, + 0x14e0b5b,0x01f1e92,0x1f52476,0x11d4fc6,0x023240c,0x1744302, + 0x047266e,0x0305e7d,0x1919374,0x1cd43d6,0x09b0b2b,0x0e9e52a, + 0x1040af5,0x051a589,0x0651000,0x17379da,0x1f42e75,0x0bdf036, + 0x0753331,0x097a211,0x0e8ec50,0x1da8011,0x1deb776,0x1618a62, + 0x1ecfead,0x0698e94,0x1a3e5a4,0x1fc2ecc,0x0735778 }, + { 0x03c1137,0x1771f42,0x0f343e1,0x147e16e,0x1c1c42f,0x19071d1, + 0x19e762a,0x15c1cea,0x016242f,0x1caf8fa,0x024b91b,0x0238736, + 0x007b88e,0x0611b56,0x0a500f9,0x005cc2c,0x1412dac,0x133082f, + 0x18b818c,0x18514f0,0x1c8d74d,0x1979d91,0x08463fe,0x08bff7e, + 0x0417c07,0x08f08c1,0x113015c,0x136ab40,0x1be4de4,0x0dba677, + 0x01cb199,0x12f7ee2,0x0c4c01d,0x1833b0e,0x1b6b153,0x1165940, + 0x1450d0f,0x0cced53,0x00a87f1,0x14c3463,0x052e637 } }, + /* 231 */ + { { 0x1ebc6db,0x18078b5,0x1649205,0x17f2a07,0x0a6b45d,0x0a9c8ca, + 0x134f174,0x1798e2b,0x1e5ad2a,0x0150e02,0x0d19be5,0x086756f, + 0x0b36a82,0x1d09c8c,0x104efb6,0x1cd9d74,0x02490f4,0x134c52b, + 0x0fc7cf2,0x041b4de,0x1ab3bb7,0x0eb1a38,0x0845b50,0x07a6c12, + 0x1222730,0x14f7006,0x0118ee9,0x1fa9980,0x045fd17,0x0f26b14, + 0x11eb182,0x1015b93,0x1603b2c,0x17de531,0x126917e,0x177e2df, + 0x04bc94a,0x003fbfe,0x05a6104,0x09f4e96,0x07c916b }, + { 0x0bac2d4,0x137c8bc,0x01d7040,0x104c035,0x0a2e809,0x19eb204, + 0x09db801,0x1115a5e,0x0fcc1fb,0x01b0862,0x0ca47d1,0x104594d, + 0x1c5727b,0x0476307,0x1154cb2,0x1a9160c,0x099ed9a,0x1a8f244, + 0x150fc40,0x16916be,0x0eeb841,0x1f6ac8e,0x09b32c6,0x19eb517, + 0x0df0f9d,0x0da7e25,0x02cd1f7,0x14f9404,0x04c5213,0x066165a, + 0x112a86b,0x00a4f81,0x13b6828,0x1e7a83b,0x1041c08,0x0d546e9, + 0x0b74c92,0x1e88003,0x141f1cc,0x0deef51,0x01ff391 } }, + /* 232 */ + { { 0x197939d,0x0c7f27c,0x0ecea88,0x16f22b0,0x1d4dfbb,0x1bab059, + 0x0d76a1f,0x131674f,0x15da92c,0x0e01400,0x19bd2aa,0x155a8cc, + 0x17e1eb4,0x0a674ee,0x0c5e944,0x060ec5d,0x0a4ef8f,0x17a3533, + 0x043951b,0x168b8d0,0x04dd900,0x0c25d78,0x1debc89,0x109a85f, + 0x1c8725c,0x1ef1e60,0x1639320,0x0127e44,0x0d88b23,0x0f208b8, + 0x1118beb,0x1580edc,0x19612e4,0x08a0df0,0x0d18cb7,0x15e91ae, + 0x125e34d,0x18fbacc,0x0432706,0x0ac0e57,0x019ed1a }, + { 0x0735473,0x1fe6f36,0x10fa73d,0x0ec0077,0x0ab88e6,0x0ccddc5, + 0x1f2f3ec,0x17a2430,0x19acccc,0x1b98220,0x195166e,0x1e7961e, + 0x02214af,0x17c9314,0x1b2068d,0x04170d5,0x1329f9d,0x0554165, + 0x1dcf324,0x07f21ea,0x17e182f,0x15fb112,0x12bd839,0x08ec5be, + 0x144bfbd,0x1a9f8c5,0x076e5c1,0x1291625,0x02c18e3,0x1074be1, + 0x0b71ba4,0x0af7d2f,0x13d6208,0x11bfc9c,0x00b11ad,0x0bd1ae7, + 0x11fed1d,0x112e65f,0x05667d9,0x1f2d0d0,0x06f31e0 } }, + /* 233 */ + { { 0x0b8f204,0x17f2ac1,0x152b116,0x0da6b16,0x0c0441b,0x0afaf6d, + 0x19efeb3,0x126e427,0x1139bcd,0x08a6385,0x0f2ec06,0x0b032db, + 0x01714b4,0x0f69ae9,0x0a5f4d4,0x03e41d2,0x0376a3e,0x0c7b204, + 0x1cf35c1,0x15153a5,0x1f6d150,0x00ee6ec,0x1ecdba0,0x1eadb05, + 0x0eb655c,0x110ad2a,0x124aa96,0x0c20a01,0x089f037,0x05711d8, + 0x1a34434,0x18856cd,0x11b2079,0x146a424,0x18f43bb,0x0a95e35, + 0x01556f4,0x1f26142,0x09f984d,0x010c7b1,0x0875e33 }, + { 0x16c0acc,0x07eee57,0x1023720,0x0d763cf,0x15ad1e6,0x02c2d6e, + 0x1eb860a,0x14db8e2,0x0275c7d,0x0e2a1a0,0x0e7856f,0x10a5a4d, + 0x10f4b4c,0x1502fd2,0x0287efd,0x19664be,0x047817b,0x0e37c0f, + 0x03fcb87,0x1a8650e,0x17fc2cb,0x0b33e3f,0x0289240,0x10b4d89, + 0x1acb7b5,0x02be822,0x11199b0,0x1d2e55a,0x17d63d2,0x03e7f36, + 0x1131d36,0x01c4e82,0x1067d87,0x0c2577b,0x15ea2c9,0x1765942, + 0x15f0fde,0x0e2dfdb,0x1802525,0x103e70d,0x05abb05 } }, + /* 234 */ + { { 0x0c97f57,0x11695f8,0x031e2f9,0x032c5e5,0x0fe0487,0x1a855d8, + 0x0919d1e,0x1db8a91,0x144fa09,0x1593701,0x16a5bbd,0x0dc7560, + 0x02fd44c,0x1873574,0x0c00cb1,0x1133bdb,0x02bd7e4,0x1145ea0, + 0x0df0470,0x05d2c73,0x171643f,0x0767489,0x03b0ff0,0x1fa1f18, + 0x18bc902,0x1d63b4d,0x09f2af0,0x1b39675,0x124cc99,0x0449034, + 0x053a22a,0x084c120,0x11461aa,0x13cf052,0x0a2e58b,0x018fe95, + 0x0b1b3e8,0x1810854,0x192f13b,0x10037fd,0x0705446 }, + { 0x01901c1,0x1eb8989,0x12abeac,0x0ffd5aa,0x090a262,0x045d11f, + 0x14a16f0,0x0fcc9ed,0x136ec22,0x0cc980a,0x0646ae3,0x15720d8, + 0x0c99a16,0x1b24e71,0x0c73d6f,0x075010d,0x15966be,0x02c9033, + 0x12e8b3c,0x06c4f39,0x1486188,0x03f7fa9,0x0b055ee,0x04475e4, + 0x098964b,0x12bdfd6,0x002ab9e,0x1a1fa9e,0x018a80c,0x1ca0319, + 0x13b6b76,0x1bf11e2,0x044bb79,0x16cfe9c,0x0f52dc7,0x0d8367c, + 0x1620503,0x11a509e,0x029adb1,0x19f70d0,0x06f56ae } }, + /* 235 */ + { { 0x1205c5d,0x0e401ec,0x04a6c07,0x1ace247,0x08955f7,0x0db2b2b, + 0x0fff676,0x1fc7bd7,0x0d3b1ac,0x0221caf,0x13bbfee,0x1642c12, + 0x0b04328,0x114c8ff,0x0c7fea0,0x1a0eacc,0x0e6190d,0x086ef33, + 0x015df01,0x0078abd,0x040775b,0x0fc8b91,0x1b24739,0x176747e, + 0x08a408e,0x1cb4d14,0x0816284,0x1a6edf1,0x0e06761,0x0a2bcd3, + 0x023ce96,0x0f6e3a5,0x03029c5,0x0186008,0x10a2d13,0x181087e, + 0x130e0b9,0x1357fc3,0x112b763,0x0229dac,0x07b6be8 }, + { 0x13aa54e,0x1c7251e,0x0268fb0,0x07b07aa,0x1023394,0x1caaf10, + 0x0988490,0x089f095,0x1f51d3d,0x088238b,0x0938dca,0x0858fd9, + 0x1e62d24,0x02fd2ae,0x16948f6,0x1436b18,0x0da851d,0x0637ae6, + 0x000051a,0x1795504,0x02e0044,0x14700b8,0x1dd4079,0x14159d9, + 0x19359e6,0x0597840,0x16b03bc,0x07bb4d5,0x164f013,0x16e47ec, + 0x1625ebb,0x0a61721,0x0dacd0e,0x09175a4,0x15bee10,0x1c98bf5, + 0x1700a1d,0x02760f6,0x151d08a,0x06bb794,0x086f9a8 } }, + /* 236 */ + { { 0x10cc69f,0x0c82aa2,0x063c387,0x1993dbf,0x10eb14b,0x1f5d00a, + 0x139dfb9,0x0a63772,0x1998f8e,0x1bd339b,0x1bbbc17,0x09c6362, + 0x1558838,0x0c2e2f0,0x04a1c8f,0x0a55577,0x145cbd9,0x07f28f1, + 0x189059d,0x01dc50f,0x02f0c5d,0x178800c,0x1f7051b,0x1eb7c59, + 0x19e92e7,0x09f07b9,0x1ed95af,0x0035675,0x08e2895,0x16ef28b, + 0x12ac554,0x171dc20,0x00dfe31,0x0223aca,0x180f10c,0x0685246, + 0x0460a91,0x03788a6,0x07e1a4c,0x15e076a,0x05bfa9f }, + { 0x07b258e,0x1fa9608,0x0770a88,0x17acc68,0x189e82b,0x1e7f8d4, + 0x13b6208,0x03ea947,0x0719b49,0x02dbbca,0x0f7ee3d,0x0430486, + 0x0e898c2,0x0249287,0x0776473,0x0ecaa1f,0x0ae4fa1,0x0a86151, + 0x10c9fd1,0x1439c85,0x1e41f7a,0x0b2c1d8,0x04e856b,0x17f5b3c, + 0x0d5a5a1,0x0e6cd50,0x02387ef,0x1639545,0x1f7f879,0x01db48a, + 0x07abe4a,0x10fd034,0x10e4e0c,0x0694b60,0x0958420,0x1009fb9, + 0x12755bd,0x064b0b0,0x1bb69ab,0x155051f,0x01b1266 } }, + /* 237 */ + { { 0x14ee49c,0x005003b,0x1f5d3af,0x0596c46,0x176f685,0x1c9c51b, + 0x112b177,0x17bf80a,0x0b6fbfb,0x19c4764,0x1cbabb0,0x179ae8b, + 0x1784ac8,0x18f6749,0x1159826,0x1f42753,0x0ac7de8,0x0b2b7db, + 0x14cae1c,0x1bdae94,0x1f095f8,0x05d5444,0x0ac350a,0x16f5d85, + 0x07f2810,0x1a621d9,0x1bfbb2c,0x0c84dc3,0x09c2db2,0x0db5cf4, + 0x041110c,0x0724221,0x0c4bc5d,0x0082c55,0x0da13f6,0x1d24dee, + 0x071ef60,0x17d348a,0x1e88d14,0x1b6431a,0x033517f }, + { 0x13c4a36,0x19fa32c,0x07baa70,0x106d635,0x0c69d71,0x1bdf765, + 0x0307509,0x138ab44,0x07e4f17,0x1465127,0x162288f,0x06d3a8d, + 0x1857373,0x1983817,0x13ac731,0x1aae8e3,0x19735ee,0x1458c26, + 0x1c133b0,0x0a2f440,0x0a537f4,0x0c6b831,0x1fc4a74,0x1aefc38, + 0x0571bb1,0x05903d2,0x060d436,0x0e95861,0x1ab8ef7,0x08cfb0f, + 0x06c9eca,0x16bbb00,0x1c4cc13,0x02c8fd3,0x156c50d,0x07cfcc4, + 0x1a3592b,0x0c9bdc2,0x1d524d2,0x07a618e,0x031fac6 } }, + /* 238 */ + { { 0x0913fb6,0x0678d82,0x1accbba,0x002ed34,0x1e40135,0x1f30f83, + 0x0edc5e0,0x1fcf21d,0x1e27f2f,0x12883fc,0x1e26fc7,0x0cffdb5, + 0x0d124ba,0x12c6f34,0x0480387,0x157dc31,0x0a36df5,0x14b1399, + 0x12fad2a,0x186f9f5,0x1a7672c,0x0b749e2,0x0c317ea,0x0c67277, + 0x0317cde,0x0b62615,0x1e0c2cb,0x0fecbcc,0x05b96a9,0x1a820df, + 0x1b52bf0,0x0e619cc,0x1f40a60,0x06c2785,0x09e64d0,0x112d437, + 0x07626b0,0x10c12a0,0x12fd4fb,0x1b6f561,0x001db35 }, + { 0x00efee2,0x1de16d6,0x0d15b83,0x1bae3b7,0x0406ebc,0x1b4d5f4, + 0x178f866,0x045ce57,0x137e018,0x0e5bf30,0x162d312,0x0038228, + 0x03cbb8c,0x143e2eb,0x02d211d,0x0ceec84,0x1a1454c,0x00c23ef, + 0x060e746,0x1d223ba,0x1046bed,0x0493c6f,0x06e7727,0x03466d8, + 0x1d62b88,0x16e14a5,0x064f9de,0x1e12d0f,0x0e3ba77,0x0332a1e, + 0x1f1eb24,0x0eec9dd,0x08695fd,0x032e78a,0x1c2e6b1,0x03c1841, + 0x06e2cdb,0x1746945,0x0d0758d,0x119aeaa,0x07b6ba9 } }, + /* 239 */ + { { 0x1881ab4,0x0cf01e0,0x12232c7,0x0b662d1,0x19c25d5,0x11b2670, + 0x0f51ca0,0x049505a,0x0f161aa,0x0cca1c8,0x0ecb265,0x1801c3d, + 0x157838b,0x1ef63d3,0x1577f32,0x044151f,0x1c24ff7,0x026e901, + 0x1bfbfd2,0x02e7661,0x0b355ec,0x198b214,0x067c74a,0x0dd027f, + 0x1d9e505,0x0f8e035,0x0b02cc6,0x0522e57,0x023b159,0x11c27e9, + 0x1b5ab83,0x131a123,0x101059e,0x032475e,0x0392995,0x10d662d, + 0x1375e79,0x08a23f9,0x1142088,0x032e3d6,0x047e810 }, + { 0x08c290d,0x0ea2d5e,0x0ce9c11,0x0b021f6,0x033d135,0x1ddf97d, + 0x002491b,0x1b2575e,0x1385c7c,0x07f9f8d,0x066172b,0x01d9c2c, + 0x08c5b15,0x154443a,0x1b829fc,0x1b9918d,0x08e5e88,0x1cec446, + 0x12e1910,0x0e6be59,0x16f24dd,0x1b9e207,0x130784e,0x1fdad23, + 0x025fff3,0x0e3fe1d,0x1c95fb9,0x1968762,0x0db1354,0x07c9f99, + 0x14ea995,0x005bfe5,0x0f58d0a,0x131ca22,0x0622a32,0x0ef1c7e, + 0x13e8669,0x1236677,0x1a1ece5,0x005c1b9,0x0785b19 } }, + /* 240 */ + { { 0x12f9a20,0x111b0d4,0x103bf33,0x0f3ac8a,0x17bdca8,0x006be2d, + 0x06a1474,0x04da8e7,0x02e97c9,0x13d646e,0x09aa2c1,0x1ffcf1b, + 0x092aea3,0x11e28db,0x0a2fd51,0x02834d0,0x0797155,0x03b78e2, + 0x05df604,0x197dec7,0x0e7af4b,0x04aa0de,0x1d6f125,0x0e0834a, + 0x14066d1,0x157f00f,0x161dd57,0x0505ab7,0x07ae80d,0x03eeacf, + 0x1bdb884,0x0705566,0x056e166,0x0eb1a55,0x1bdae74,0x08cbdd1, + 0x0e4ed84,0x110b056,0x0b09e66,0x0cf6ee2,0x06557c3 }, + { 0x15b6e52,0x181346b,0x1a25586,0x00231a1,0x1081364,0x1758d75, + 0x0ccc1a8,0x1299fea,0x06d0908,0x1231113,0x1075213,0x044f6bf, + 0x0dbb351,0x0bd1831,0x197a81d,0x05b8b26,0x17bd66e,0x1a65651, + 0x0425621,0x1afa477,0x13bf220,0x09c6223,0x0703f4e,0x10fb49f, + 0x1370a67,0x05c56ff,0x13415fd,0x1e15d79,0x13f33ae,0x1a2608b, + 0x0d08179,0x124b44d,0x0d1f0a5,0x1ddfedc,0x1d25c8b,0x09526c9, + 0x0227d28,0x08d73bc,0x02ad322,0x00941c1,0x015c40d } }, + /* 241 */ + { { 0x00e18d1,0x18b4d15,0x1f0a6eb,0x0e98064,0x1971c01,0x0131674, + 0x0c8fdef,0x0f3b034,0x1818ff3,0x04cedc6,0x0f0cc08,0x0c7a99a, + 0x13663f6,0x008d02a,0x14c970c,0x148e1de,0x1dcf980,0x04e6b85, + 0x127b41c,0x08a5a23,0x0e13e64,0x1a5633b,0x0befd0f,0x10b854b, + 0x0c0a6ae,0x0624bdf,0x011c124,0x1f55caa,0x1e6ba92,0x1d43a48, + 0x0502ae5,0x155f532,0x055f537,0x132aba0,0x16ecd9c,0x1ff92b5, + 0x1119d6b,0x11a1dce,0x078dd91,0x1413a68,0x0788e94 }, + { 0x053461a,0x137f2ce,0x1bb414e,0x1c11c76,0x15ec897,0x146c9cb, + 0x14bcc1d,0x09f51eb,0x0cc213d,0x1eb5ffb,0x0051f26,0x16820b6, + 0x09590c7,0x1e3dc0b,0x08d8a2d,0x0f1d241,0x06e5bce,0x1e33504, + 0x17b0763,0x09a5049,0x0ce93dd,0x0260cee,0x0242b3d,0x086b4fd, + 0x0d875d8,0x0d93319,0x07a98e0,0x1202cf8,0x1cc1285,0x0bcbf86, + 0x18ec896,0x08df1a8,0x1a612b4,0x17d1cc8,0x15e3057,0x108430b, + 0x119f678,0x0af61b8,0x1aa4f7d,0x18cf01b,0x091b19c } }, + /* 242 */ + { { 0x15d8b80,0x1384ee5,0x183bafc,0x05f86ac,0x03b9618,0x0f7cb48, + 0x1664415,0x08570e7,0x1e47c43,0x0f525a6,0x1e219f4,0x0489aa9, + 0x0fcc4b9,0x1ec6bbf,0x0c68b2b,0x1eac727,0x0e7e8c1,0x1034692, + 0x065cc15,0x1f576c9,0x174f5f5,0x0802a11,0x00c9231,0x071d227, + 0x1e2b53f,0x05f61b6,0x0deeda0,0x1a0fd1d,0x1313b5e,0x09ebec7, + 0x04a5920,0x15fa5a7,0x1b6a069,0x0518d3d,0x1238212,0x0b80db0, + 0x04f0c32,0x13fd97f,0x10ebda1,0x0680ce6,0x03c2ba8 }, + { 0x13ad63b,0x16bbace,0x0c7ead8,0x0eb3c1d,0x1f9cab9,0x02f08b9, + 0x0a98ce2,0x13ce066,0x0e20b2f,0x11657e7,0x12a51fc,0x14fc93d, + 0x0db529b,0x11146c4,0x0550859,0x12ac249,0x1ec3923,0x0407511, + 0x10dc191,0x120fcfa,0x0e441b8,0x0aab1f2,0x12dfe91,0x14961f4, + 0x1829eb2,0x1c96654,0x1120181,0x014e414,0x0991ced,0x0d06123, + 0x1ae3337,0x0691a10,0x1a2325b,0x177099b,0x1427d82,0x1eacdda, + 0x147f253,0x1870488,0x0ef60f4,0x14b820e,0x01fa627 } }, + /* 243 */ + { { 0x0478fd4,0x1115121,0x0002844,0x02ce164,0x0cf4c6f,0x0ce36f5, + 0x0c13e0d,0x179ee37,0x17b93cd,0x0c71414,0x16d82d8,0x15c6461, + 0x0996e1b,0x0b2d9d9,0x1ff4ed2,0x0abbbe2,0x1c6bc70,0x1d2c31c, + 0x0e05f5f,0x1525da9,0x08a4c3e,0x13691d8,0x0420aca,0x02e021d, + 0x1228adc,0x0cbc238,0x1883a27,0x0a773c8,0x1f77c97,0x07cb81f, + 0x1973df9,0x0577cc1,0x03f8245,0x100beb6,0x12f2e03,0x173c865, + 0x00a45ed,0x052d66e,0x1d0f854,0x00a8f30,0x067b8bd }, + { 0x0797cf7,0x03cda7a,0x180b998,0x15a07fb,0x031c998,0x055778f, + 0x1d8e953,0x022b546,0x0f76497,0x06cd0ff,0x06c69d9,0x18e75e5, + 0x137ce0d,0x1db3654,0x186c20f,0x0d4f0cc,0x0fe32fb,0x0dfa6ba, + 0x1c02958,0x0dde13b,0x115925f,0x1fc18e8,0x0af10e0,0x0d7bc6e, + 0x0c10c53,0x12db6ae,0x1e20b31,0x0928bf3,0x1a99b8d,0x0789a28, + 0x09207d2,0x0d75823,0x00161cd,0x125050a,0x13b7c62,0x093b29a, + 0x0467a82,0x1b18b2d,0x0bb7d94,0x1534993,0x074297a } }, + /* 244 */ + { { 0x01124ba,0x1ac5271,0x0f4b125,0x1150fff,0x19bd819,0x131c544, + 0x13744f5,0x0ec8bf7,0x015f7bf,0x0322ffc,0x1b55fa5,0x06df89c, + 0x195fa67,0x09730ed,0x0b991d6,0x128943d,0x00ccbdf,0x03cabae, + 0x16cc75d,0x02608e4,0x1ae6a3d,0x112655a,0x1e2077c,0x0510fe4, + 0x1d2991a,0x02cc6df,0x0289ab1,0x07a0eb2,0x061d4a2,0x0c296c3, + 0x1dcb962,0x1140281,0x1b5c13b,0x1bc151b,0x0678fec,0x001f283, + 0x1bc14e9,0x15502c8,0x0ec49c8,0x175aab7,0x089aab7 }, + { 0x056bdc7,0x02d4b6b,0x14ee2cd,0x1fc2ed9,0x03bdc8a,0x0b2621a, + 0x062d8cb,0x083ad2a,0x179b82b,0x079b253,0x033e0bf,0x089dff6, + 0x1b907b3,0x0880943,0x14320f1,0x121dfe7,0x05934cd,0x074f935, + 0x1c20ad7,0x0b55e40,0x0165e5f,0x1af673e,0x13adcb1,0x130d9ac, + 0x10a81be,0x15574ac,0x1ffc54d,0x1dde931,0x063d5ef,0x0121d41, + 0x0ac1158,0x0a95d0e,0x00be14f,0x03b434a,0x13278c8,0x157dcf7, + 0x01bc4d7,0x0b513ee,0x0ad1b52,0x12eb281,0x0002dc2 } }, + /* 245 */ + { { 0x09d60c3,0x19c9bdb,0x1d57b94,0x05fd2e4,0x060be55,0x0392d31, + 0x0de3703,0x185623f,0x0cab2e7,0x0c1613f,0x0c8b2da,0x1bb3dc4, + 0x174bcee,0x0913827,0x0ac67b4,0x0c2cb2a,0x085854a,0x096fa61, + 0x0c64921,0x016b7ef,0x152aba4,0x08008cf,0x1f2f2a5,0x15bb0df, + 0x1d1cbe5,0x160ba33,0x0f6743c,0x17ea6df,0x14ebc99,0x171a5c6, + 0x05cf0a5,0x00b5026,0x095f8f4,0x1afbb02,0x0359ccc,0x0518b3d, + 0x0054212,0x09e9927,0x169cc2d,0x06a7877,0x04d5645 }, + { 0x05c0877,0x17c003f,0x1d91cc8,0x0c19534,0x081b43e,0x00938b2, + 0x13d2e8b,0x184463e,0x1ed3136,0x0acb42b,0x0cc3782,0x064471b, + 0x1cae826,0x0cc8475,0x0beb502,0x0463cca,0x014af0d,0x085c68c, + 0x072f0d2,0x018a961,0x1f8e268,0x19a5f9d,0x1f5158b,0x056b2bf, + 0x1090b09,0x01a14c2,0x117857f,0x0de7394,0x178168e,0x08c8de1, + 0x01dc05d,0x108b495,0x06944b3,0x0aa0d48,0x1d2a0a8,0x09598da, + 0x1155c8b,0x04dd59d,0x1b18ab7,0x19cee60,0x01f2f89 } }, + /* 246 */ + { { 0x0ffefdf,0x1f7a0cd,0x15ae094,0x0a99f24,0x05d7ece,0x0272418, + 0x00bcad1,0x03e6ee0,0x1cba547,0x0c4baaf,0x0f8056c,0x0797ab9, + 0x09c8848,0x1505c21,0x13df1a5,0x1ec3a4a,0x1d461f3,0x18c4285, + 0x0891c55,0x0421121,0x0b0d7ba,0x176c977,0x0d6aef0,0x0bbd912, + 0x0cabe96,0x0257dab,0x12f155a,0x1b446e4,0x1a74929,0x1cb7b53, + 0x11b62e8,0x05de974,0x0b90db7,0x0d93d7e,0x1f82642,0x1dba469, + 0x16f4366,0x19e0b23,0x0351ef7,0x0fe2fca,0x009c809 }, + { 0x0050c07,0x058a030,0x0df9a81,0x108751c,0x029e831,0x0af20fe, + 0x0a6caed,0x0759728,0x02ce60e,0x097f52d,0x160bd3b,0x1fe7b73, + 0x1adc7b1,0x143e9bf,0x1afb30d,0x0ea7291,0x032ecb0,0x13c8a9f, + 0x1c1d5a4,0x000a9ea,0x19ba6a6,0x064003a,0x0e1c734,0x1245be2, + 0x1386f30,0x1be0bd3,0x1a0cd5e,0x1d3f8b3,0x0151864,0x19d49ca, + 0x024749a,0x1a69b71,0x12a0222,0x06db8c8,0x13d167f,0x0ccce5f, + 0x04ff303,0x1f9346a,0x185b168,0x1a6d223,0x06f113e } }, + /* 247 */ + { { 0x036f1c9,0x0efac8c,0x01f54aa,0x0a84646,0x1a6519f,0x16942d7, + 0x11c0577,0x0eb080d,0x0af627f,0x10aa2e5,0x0105f42,0x03dd59c, + 0x03ae111,0x13089a2,0x0a2f7da,0x19797f6,0x0ab52db,0x06f4f78, + 0x004f996,0x183036f,0x1225e9d,0x0dcc893,0x02c76af,0x10298b2, + 0x198e322,0x13f2f82,0x1b64d3b,0x18772cd,0x1ba4bf5,0x076d5cc, + 0x19d3ae1,0x07836ab,0x0919a34,0x14307d9,0x0d2652a,0x0d535bb, + 0x16811ff,0x19106ff,0x00f886d,0x077a343,0x06636a2 }, + { 0x0587283,0x0ad1690,0x11777d7,0x13de0ff,0x0b3822c,0x1b6f1c0, + 0x0f5543b,0x03a2f0d,0x125d167,0x11e7c83,0x0c77bc5,0x0e3e39b, + 0x0a74bf9,0x04217e2,0x127a0c0,0x0a9eeae,0x1c727f8,0x187176d, + 0x13892b2,0x0f77b57,0x108dbb2,0x1602df6,0x106c673,0x1920979, + 0x0123ef7,0x16dd56d,0x0f62660,0x04853e3,0x16e6320,0x10b732f, + 0x0c9274d,0x1dcb3fa,0x1789fa8,0x194fad1,0x0eebfa7,0x002c174, + 0x0f5378a,0x169db0d,0x09be03c,0x0ece785,0x07aeecc } }, + /* 248 */ + { { 0x043b0db,0x03abe6e,0x12b7ce9,0x0b30233,0x1d8a4e8,0x0b60ab1, + 0x16fd918,0x12ff012,0x04f533e,0x11503de,0x1f16b4f,0x06ce739, + 0x0ca9824,0x06b4029,0x09ae8eb,0x1d8cc31,0x1908a1c,0x0deb072, + 0x0ac6da5,0x10834a0,0x195bae3,0x090c850,0x061b7fc,0x063fb37, + 0x0beacad,0x1bd96f9,0x1331ca3,0x1b12644,0x10a9927,0x139c067, + 0x1ab0e3a,0x0b0d489,0x0439a80,0x0f81e54,0x1fc0585,0x0bdbcfe, + 0x07a1f88,0x124c841,0x1d91520,0x00d6f14,0x028ec40 }, + { 0x0fe0009,0x1061751,0x13a7860,0x05e270e,0x011ba5d,0x126da97, + 0x0915314,0x0532ea4,0x07fede5,0x0a3ba13,0x1403513,0x0335364, + 0x0b01d34,0x0c34922,0x0229248,0x1c3739c,0x023dd1b,0x05d0b48, + 0x0a8c078,0x187ca86,0x0788242,0x1d38483,0x06d5bde,0x0951989, + 0x12a09c7,0x01cf856,0x075dbe5,0x139a308,0x1fb60e9,0x1f05b10, + 0x0d3b76b,0x17872ec,0x16bee54,0x1854202,0x0183fdf,0x1e8ca7f, + 0x0011c0a,0x0a43b79,0x0970daf,0x18e192a,0x0134f4c } }, + /* 249 */ + { { 0x138dff4,0x0d1f674,0x068e588,0x1690d4f,0x1d101a7,0x0a829bb, + 0x1be5f7a,0x1b7e589,0x1e65d87,0x18c204c,0x0e33ebc,0x1ff66e7, + 0x0eb89c7,0x142148b,0x0ea9417,0x14ec8d1,0x1094ebe,0x1d3c87e, + 0x164a24a,0x1beda9c,0x1741679,0x0e7e7f6,0x0808ccc,0x101fe42, + 0x0efd298,0x08085fa,0x1740d11,0x194f1bb,0x0858c87,0x0f659a1, + 0x1e8b2c2,0x04aea90,0x05eb6dc,0x18248cf,0x0857af2,0x02a0ceb, + 0x1381d47,0x0973a7b,0x15bd027,0x05307a7,0x06ea378 }, + { 0x05cc40a,0x004a5a7,0x17ef197,0x1435e6f,0x1a2e3f6,0x0137223, + 0x1fa77e4,0x0a7dece,0x193880f,0x1c3c64a,0x112aa6d,0x160efec, + 0x1c4aa30,0x1790461,0x1145a0c,0x0cc7741,0x1ae658d,0x03e013b, + 0x187644c,0x1678715,0x1ea4ef0,0x13b4ae1,0x0c0bcde,0x018bc1a, + 0x0c1c56a,0x1cff002,0x10832f3,0x1fa92b8,0x0a0e7c9,0x0dceab4, + 0x151c1b5,0x0b250c8,0x1225dff,0x1384e45,0x1196366,0x10a4fa8, + 0x07c08d6,0x02ac6d4,0x1c1f51f,0x1cd769d,0x0606ee6 } }, + /* 250 */ + { { 0x1c621f6,0x0cfe3ab,0x15200b6,0x02ffd07,0x092e40c,0x18ccd81, + 0x11e867b,0x0cc37bf,0x0e62c76,0x0502081,0x0e1d4de,0x06e1cce, + 0x0f16cda,0x0f1d32d,0x0065d34,0x1c41379,0x048f78f,0x10cba10, + 0x1d66071,0x140b157,0x102dc83,0x1a4e44b,0x1c9ac90,0x034cf15, + 0x12f1e9d,0x114cc45,0x03fca6b,0x0e57f36,0x1cf5ec4,0x11cc0eb, + 0x162850f,0x164d1bb,0x09d7e45,0x07fbb4e,0x09557f1,0x062cd9b, + 0x04aa767,0x0266f85,0x01c1d81,0x1efd229,0x049dba6 }, + { 0x158e37a,0x03fd953,0x1d98839,0x0e5b1d5,0x0f6b31d,0x0e11085, + 0x157e5be,0x0566a55,0x190efc3,0x049fb93,0x12c9900,0x13b883c, + 0x15435c9,0x02d8abc,0x0a1e380,0x06aeb7f,0x0a40e67,0x0cce290, + 0x1fba9d6,0x104b290,0x148bca6,0x00f8951,0x00a7dee,0x1459c6a, + 0x1cc182a,0x162d2a3,0x0fab578,0x023b0e9,0x082cdfa,0x1a4daab, + 0x19a6bc0,0x1177d1c,0x06ebfea,0x1ca55fc,0x1e0bd54,0x1e7b570, + 0x0bc8eb8,0x05fbcbf,0x19e3116,0x14936fb,0x04890a7 } }, + /* 251 */ + { { 0x1a995f6,0x0cb44c6,0x1bbf5ca,0x0fd8c2a,0x139eaae,0x15416ae, + 0x01030d5,0x1fcd2b2,0x1c135bc,0x1023590,0x0571e2c,0x16c81eb, + 0x00ea720,0x13e2fda,0x0093beb,0x077f805,0x14c0edb,0x14bec7e, + 0x07c93af,0x00520af,0x06b912f,0x078c3f5,0x05bf11f,0x13ab846, + 0x1fd2778,0x166610c,0x122498f,0x0674d6d,0x0d30a62,0x1a5945b, + 0x00208d8,0x193666d,0x0352e25,0x1ba2b65,0x1b29031,0x172711a, + 0x1c92065,0x12ad859,0x069dbe3,0x0960487,0x05c1747 }, + { 0x0accab5,0x073e145,0x016f622,0x0d559da,0x1802783,0x1607b28, + 0x01df733,0x10430b7,0x0125c28,0x1e56e0e,0x1715324,0x0814cff, + 0x1345df5,0x013c451,0x0f21b8b,0x1f4589e,0x069e3a0,0x19f43a2, + 0x1ce60f3,0x1b548e4,0x18a5c59,0x05a54b6,0x0c18f12,0x1cb122a, + 0x12bcfc2,0x061e1c6,0x1e1390a,0x01cf170,0x04fd539,0x1496786, + 0x0164028,0x1283cc0,0x1f92db7,0x09d0e5b,0x0905b29,0x0f2acf2, + 0x11ab0fa,0x1b798ed,0x10230d7,0x168f6b0,0x05d675e } }, + /* 252 */ + { { 0x10c6025,0x10d3bc3,0x1f2abbb,0x0f2345b,0x1c4a23b,0x15b2627, + 0x18310e1,0x162f61c,0x1e5ae72,0x0ead8be,0x1e884b5,0x11593dd, + 0x166dfc8,0x0a01c5c,0x1abbefb,0x05d989f,0x1568e2d,0x184cd61, + 0x04abc81,0x1d4c240,0x1218548,0x0dc4e18,0x13ffb67,0x1cce662, + 0x091c4e0,0x0700e0f,0x1ebe0c0,0x01376c9,0x13c3be0,0x080e33b, + 0x1ea1e01,0x1810433,0x0cd6ede,0x1837ff0,0x181fe06,0x1ef80ab, + 0x0080b36,0x1b1fce7,0x1b28e0a,0x15e153f,0x002fccb }, + { 0x07cac61,0x0ea68da,0x04b2664,0x0f570dc,0x0e9d168,0x0a78211, + 0x157b0ae,0x1cb18d0,0x148e648,0x120028c,0x06b15f2,0x1f65df1, + 0x0d9ba91,0x0df3c96,0x1064818,0x03c2a9e,0x1cbbd0f,0x0c16910, + 0x1111006,0x1d6277f,0x0fdc062,0x194cbc8,0x1cea5f0,0x0cf4c97, + 0x16d9460,0x1ad273c,0x01b48dd,0x08dba60,0x1f0f23c,0x026af6b, + 0x15e19cb,0x0769ec7,0x01851dc,0x139f941,0x1833498,0x1ea1475, + 0x0ac60f6,0x072c7e7,0x1551600,0x0ac2708,0x056f1e4 } }, + /* 253 */ + { { 0x0c24f3b,0x059fb19,0x1f98073,0x1e0db02,0x19eb1c7,0x1133bb4, + 0x102edaa,0x1c11b8c,0x00845d5,0x01c57ff,0x09e6a1e,0x1963f03, + 0x10f34fe,0x1f340cd,0x0b8a0b4,0x14970d4,0x1ce8237,0x0e25cbb, + 0x1d8d90e,0x0d67b70,0x04970f4,0x004bcb8,0x09197d5,0x1237c87, + 0x0876287,0x1636bf0,0x10d0663,0x004416d,0x1d94bb0,0x031b849, + 0x0c95ece,0x053ad21,0x0012e16,0x168d242,0x16d482a,0x0605d93, + 0x05dc34e,0x1717e34,0x033e2bf,0x06c4aa0,0x0911d19 }, + { 0x1e5af5b,0x0deac7a,0x0a9c4ec,0x16f6d44,0x07ca263,0x17956e5, + 0x1b137ce,0x17b56d7,0x1a04420,0x1328f2c,0x0db0445,0x1676974, + 0x103b448,0x1fa1218,0x18aff37,0x0d97678,0x0a5f1a9,0x06f0ae2, + 0x1347e60,0x15b143c,0x1a3abe0,0x071b339,0x004af45,0x02559bb, + 0x03af692,0x0e72018,0x115d825,0x1edb573,0x1f5ca58,0x0415083, + 0x0c1f7c6,0x1112d47,0x103e63c,0x1d9f85c,0x1513618,0x1dea090, + 0x009887d,0x080cdce,0x0e19579,0x1fd41ea,0x02be744 } }, + /* 254 */ + { { 0x150f324,0x0682fad,0x1e88153,0x083d478,0x19b1eb2,0x1c735bd, + 0x02971ff,0x104950b,0x0ec0408,0x01c817f,0x0ea6f76,0x0929a19, + 0x1e72b26,0x194e4f0,0x05dbe42,0x1b703a0,0x102ceba,0x002ea75, + 0x1cae2ff,0x080b626,0x1190874,0x00bcf56,0x17104a2,0x056919a, + 0x03dd3ec,0x019ea25,0x1cfd354,0x089334e,0x0c3a098,0x1c66ab2, + 0x0eecdec,0x1e85d00,0x0e99497,0x08c5940,0x1e82e3d,0x0980f68, + 0x1568fde,0x0871e29,0x039eb1c,0x05f9d5a,0x0735f54 }, + { 0x0380039,0x0d0b89c,0x07232aa,0x0fee9a3,0x0dfafe1,0x1e0d45d, + 0x0e4fb32,0x00b25a8,0x1fe0297,0x02edf9c,0x1a6cd8f,0x0b57261, + 0x0a4552b,0x157ea4a,0x198c0c8,0x15886fd,0x0d73f02,0x041354d, + 0x04d58a6,0x0a6ac53,0x1b3998c,0x03b9a15,0x0321a7e,0x1f36f34, + 0x10020e4,0x0d4eba8,0x134d1e2,0x06c3a34,0x0856376,0x0add67d, + 0x193c37b,0x111580f,0x07ee73f,0x18e5ea0,0x00fc27b,0x1bf58fa, + 0x0d475ba,0x0b4be5a,0x0e67897,0x13a297a,0x01e984c } }, + /* 255 */ + { { 0x050c817,0x082b0a4,0x04b71db,0x1269130,0x108a5b1,0x0c65df5, + 0x1455179,0x0b4e4e7,0x04be61e,0x0805afd,0x1ae3862,0x0d23af5, + 0x0baa088,0x09ad1ea,0x1999abf,0x0fa7bcc,0x19957ec,0x01c5160, + 0x1a35bd7,0x091d1ec,0x1746a06,0x163d6e0,0x07e7f24,0x060cb86, + 0x116c084,0x13491d0,0x01879ab,0x0c6e144,0x047e733,0x1b9b155, + 0x01189b0,0x1bdfedb,0x00c25f2,0x1696a2a,0x093336f,0x0530090, + 0x039a949,0x0dfe700,0x0b8052d,0x0aced28,0x06c474a }, + { 0x188e3a1,0x1cd20be,0x10a8eba,0x118908e,0x105d3c8,0x1308988, + 0x1a344ff,0x117cb3b,0x11a869e,0x047adb5,0x1764285,0x18b354e, + 0x137a8ab,0x110a300,0x0326f1d,0x099b25e,0x147c382,0x121fd53, + 0x09742e4,0x0c7430d,0x0ebc817,0x1e4de5d,0x0ef0d06,0x08ba3bb, + 0x13160f7,0x0fa70c0,0x16dd739,0x0a79ca5,0x0de4c2a,0x13366a8, + 0x1b457ab,0x0ebaeca,0x0d8996c,0x12a952f,0x1c47132,0x09c9fea, + 0x1c5305b,0x0f4c2d1,0x08b3885,0x0a9f437,0x06b2589 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_42(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#endif + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[42]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 42, km); + + err = sp_1024_ecc_mulmod_base_42(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_42(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[42 + 42 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (42 + 42 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 42; + + sp_1024_from_mp(k, 42, km); + sp_1024_point_from_ecc_point_42(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_42(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_42(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_42(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_ecc_mulmod_base_42(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_1024_proj_point_add_42(point, point, addP, tmp); + + if (map) { + sp_1024_map_42(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_42(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 42]; +#endif + int err = MP_OKAY; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 42, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_42(point, gm); + err = sp_1024_gen_stripe_table_42(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[42]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 42, km); + sp_1024_point_from_ecc_point_42(point, gm); + +#ifndef WOLFSSL_SP_SMALL + err = sp_1024_ecc_mulmod_stripe_42(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_42(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_42(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_42(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_42(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_42(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_42(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_42(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_42(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_42(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_42(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_42(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_42(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_42(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 42]; + sp_digit tx[2 * 42]; + sp_digit ty[2 * 42]; + sp_digit b[2 * 42]; + sp_digit e[2 * 42]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 42 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 42 * 2; + ty = td + 5 * 42 * 2; + b = td + 6 * 42 * 2; + e = td + 7 * 42 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 42, base); + sp_1024_from_mp(e, 42, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 42); + sp_1024_mul_42(b, b, p1024_norm_mod); + err = sp_1024_mod_42(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 42); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_42(tx, ty, t); + if ((e[i / 25] >> (i % 25)) & 1) { + sp_1024_proj_mul_qx1_42(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_42(tx, tx, t); + + XMEMSET(tx + 42, 0, sizeof(sp_digit) * 42); + sp_1024_mont_reduce_42(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 42, 0, sizeof(sp_digit) * 42); + sp_1024_mont_reduce_42(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_42(r, tx, ty); + err = sp_1024_mod_42(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][42] = { + { 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, + 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, + 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, + 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, + 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, + 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, + 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000 }, + { 0x15c1685, 0x1236919, 0x09605c2, 0x03c200f, 0x0ac9e97, 0x052539f, + 0x1cf7d0f, 0x0ea81d1, 0x1826424, 0x1237c0a, 0x15db449, 0x176966c, + 0x1b3af49, 0x195f8d7, 0x078b451, 0x0a3cdb1, 0x02c2fd1, 0x013df44, + 0x1e21c5f, 0x1db90b1, 0x0c6fadd, 0x1f8b563, 0x15b6166, 0x11d5cb1, + 0x01a1b2d, 0x186873a, 0x018707c, 0x1f5ef40, 0x07e0966, 0x084d4db, + 0x1f59b6f, 0x0fa769e, 0x1f11c06, 0x1e4c710, 0x080b1c9, 0x02c2a57, + 0x086cb22, 0x0ac448f, 0x0ebd2bf, 0x0d4d7a7, 0x059e93c }, + { 0x1dd4594, 0x0e9b7b8, 0x079b953, 0x1e015de, 0x1bc9cc9, 0x0fb2985, + 0x0913a86, 0x0513d4b, 0x13f5209, 0x0c4554c, 0x1050621, 0x12991eb, + 0x1a97537, 0x0089ccf, 0x02f5e4b, 0x0d56a23, 0x0fdf5cb, 0x15cde9d, + 0x1b2e594, 0x1a39645, 0x1813813, 0x13a01c4, 0x1f51589, 0x1908639, + 0x1119b4a, 0x15b28fb, 0x0428603, 0x1b3ed52, 0x1bfa2ed, 0x168bcfb, + 0x1644e51, 0x0a153a1, 0x0f18631, 0x1b9e98b, 0x0835be0, 0x12be338, + 0x1b6a52b, 0x02d6354, 0x0b80efa, 0x0f6e9ec, 0x063ef18 }, + { 0x16f45e7, 0x1b5bf80, 0x0be1f0d, 0x0e57d90, 0x1c1bdb5, 0x014db00, + 0x1dd0739, 0x03ae725, 0x0c7afd8, 0x1edf851, 0x04262db, 0x163ee48, + 0x0fbda41, 0x1db07c6, 0x101d1d2, 0x1789ab6, 0x141b330, 0x1499f06, + 0x0cfe8ef, 0x105060e, 0x0cd1ae1, 0x0d87ae3, 0x083b4a6, 0x130c191, + 0x1354e3f, 0x020bff9, 0x1855567, 0x026c130, 0x1f85cbb, 0x1b1e094, + 0x0faac32, 0x08ed0bf, 0x02ecc49, 0x0cb19b4, 0x1b0bac6, 0x14a0bd1, + 0x1dac2cd, 0x0e63ca6, 0x1688e43, 0x039e325, 0x04fe679 }, + { 0x1e8733c, 0x011ea82, 0x1f06529, 0x0a3aae2, 0x0c845e6, 0x10d9916, + 0x1fa23a5, 0x19846f8, 0x0db4181, 0x02238e3, 0x0f5c843, 0x0bc4e27, + 0x0900c87, 0x1960bd8, 0x1f7a7b6, 0x1d5ed3b, 0x1e5e88c, 0x1218536, + 0x0e073a9, 0x0f4c34f, 0x18d5aaa, 0x13119fc, 0x1a94b40, 0x0d13535, + 0x0fdd060, 0x155daaf, 0x1972b12, 0x019f4f9, 0x1507613, 0x188a474, + 0x14be936, 0x09d343c, 0x09570c4, 0x000b818, 0x1d84681, 0x0431843, + 0x1e78d9d, 0x0e8fff5, 0x0ca5d55, 0x030ac3b, 0x004482a }, + { 0x1d486d8, 0x0c56139, 0x079f9dd, 0x0cc39b8, 0x0169f94, 0x0455a7c, + 0x067f086, 0x060e479, 0x0f33736, 0x072a781, 0x1089828, 0x1c4b7b1, + 0x00560be, 0x0298de3, 0x1f0c1f1, 0x1fd6a51, 0x11a7e44, 0x1eb790f, + 0x1c4a34d, 0x089338a, 0x0a45c8e, 0x1f6bd97, 0x058ec14, 0x147a445, + 0x07a0432, 0x1342061, 0x14d5165, 0x16a30a9, 0x1557e95, 0x124feb9, + 0x1e99b86, 0x10d240e, 0x1267fd9, 0x0138106, 0x034f9cd, 0x09f426a, + 0x08ccdb4, 0x0e1f92b, 0x1e27c6a, 0x1f1bdb7, 0x0833a0f }, + { 0x1376b76, 0x00ce3d5, 0x0332a31, 0x064fa1e, 0x1b7294f, 0x0628a69, + 0x0e78aa4, 0x14dcad7, 0x0a62575, 0x18dd28f, 0x102a224, 0x00f6131, + 0x0a56fee, 0x1a60b51, 0x0f96bba, 0x04c1609, 0x10be6eb, 0x072899a, + 0x075709c, 0x1db5ad4, 0x0dd1339, 0x0cf4edd, 0x1cd9bb5, 0x1a0dd81, + 0x1be882d, 0x1eda109, 0x032c461, 0x05ac739, 0x01058a2, 0x0af0ec5, + 0x1c47fb2, 0x1456e89, 0x1f73ea6, 0x02e0601, 0x146bd3c, 0x00e83fa, + 0x05f811a, 0x16fcad4, 0x0597cb8, 0x1c7d649, 0x0692b3c }, + { 0x0a127b4, 0x165b969, 0x05bc339, 0x0b1f250, 0x06a46ea, 0x11bb0b3, + 0x1d18d1e, 0x1dc87d9, 0x1e0ab96, 0x11ecd00, 0x16fa305, 0x18db65d, + 0x05c8145, 0x06f2733, 0x109b2b9, 0x0a5f25e, 0x14074e2, 0x08ba685, + 0x14abe0c, 0x0481aef, 0x093654c, 0x0b9eb29, 0x1607e8e, 0x13a8d2a, + 0x1491ca0, 0x01e02dc, 0x0d51499, 0x189d0a6, 0x1283278, 0x0198ea0, + 0x094cb59, 0x0e06c3e, 0x0479038, 0x184f932, 0x06c627b, 0x00ee832, + 0x01de5fe, 0x078557c, 0x10b5b03, 0x015e800, 0x0333e43 }, + { 0x126d3b7, 0x026f267, 0x06f977c, 0x0d6a7ef, 0x17a7730, 0x045b322, + 0x0f17c60, 0x0c14802, 0x0850373, 0x1948f52, 0x1840dfb, 0x1afa160, + 0x1b1ffc9, 0x12e489d, 0x1413765, 0x10b0fb3, 0x1aff13b, 0x0ca451b, + 0x18fb9d5, 0x086907f, 0x1386b54, 0x1a02318, 0x0ff0879, 0x1bd6b18, + 0x104e5cd, 0x0a959d0, 0x0995cb3, 0x09fc30c, 0x0aa4089, 0x18d08ad, + 0x18bae69, 0x08b3d48, 0x0dc6fe5, 0x18151c5, 0x05d52ba, 0x037631a, + 0x0f7791d, 0x093b1b1, 0x15c22b8, 0x03bad77, 0x010e8b3 }, + { 0x0d9f1af, 0x181f29f, 0x059ae1f, 0x0eaccec, 0x03ad247, 0x070adc0, + 0x158c1d3, 0x0b671b9, 0x026b1e8, 0x03bf158, 0x0670546, 0x1a2e35f, + 0x1ab1654, 0x09c12a3, 0x00ba792, 0x0bdeb2f, 0x07c26d5, 0x036e3fe, + 0x1efad53, 0x11f2ba5, 0x0357903, 0x1f01b60, 0x1f96437, 0x1b87eff, + 0x16eae4f, 0x14467e5, 0x13cd786, 0x163f78a, 0x0a5568c, 0x0ed96d0, + 0x15cf238, 0x0b6deaa, 0x087393f, 0x005034d, 0x0ccb9eb, 0x1670c8d, + 0x0a8495a, 0x130e419, 0x112f3f4, 0x09819b9, 0x0648552 }, + { 0x0a6ff2a, 0x1d9f162, 0x0a286af, 0x146b4c8, 0x0aa03fb, 0x17fba11, + 0x09fc226, 0x1271084, 0x0ba5dbd, 0x19bc41d, 0x060b2c8, 0x15d3a54, + 0x0538186, 0x04d00f8, 0x1c1d935, 0x03cf573, 0x1eb917b, 0x1c9208f, + 0x1c32ed6, 0x163206a, 0x1e7c700, 0x0adc8a5, 0x1754607, 0x102305a, + 0x0443719, 0x0cb89ae, 0x115d2e6, 0x04eb1a4, 0x0d28b23, 0x147ab19, + 0x0269942, 0x1f4707e, 0x0078bac, 0x19ec012, 0x1830028, 0x12ca8d4, + 0x0df8b44, 0x030e3d1, 0x158f290, 0x1e5e468, 0x01f76f3 }, + { 0x0c436b0, 0x160a1a2, 0x01ea6a8, 0x0c3ed39, 0x1907055, 0x16d96fb, + 0x045ed7d, 0x1046be6, 0x1ed56ba, 0x0bb0fa0, 0x0be9221, 0x0c9efa1, + 0x1ef8314, 0x1d6e738, 0x07ca454, 0x0e91153, 0x093116b, 0x1593dfb, + 0x0ee510e, 0x14b5193, 0x1de8a98, 0x131772f, 0x1fe1e00, 0x025596e, + 0x193dd18, 0x0491d37, 0x137212f, 0x1f25499, 0x14995aa, 0x1157f8e, + 0x074f095, 0x009db13, 0x19fc33c, 0x1529c7e, 0x0a513b4, 0x0d80519, + 0x049ea72, 0x19b3dd8, 0x0381743, 0x1f67a21, 0x004924f }, + { 0x073562f, 0x0471ee3, 0x1230195, 0x0bc5d5c, 0x13b3302, 0x0e34bbe, + 0x14cad78, 0x0f7cc3f, 0x06ebe55, 0x1271032, 0x1b86390, 0x038083a, + 0x1b76739, 0x0a6bf4a, 0x03aee38, 0x0371897, 0x1d42099, 0x1a5745b, + 0x004a434, 0x01becdc, 0x1f4ef8a, 0x11c92f2, 0x125f892, 0x0104e55, + 0x1b2cb15, 0x130bcd3, 0x18941c9, 0x08160e5, 0x02fa49b, 0x10c1483, + 0x13b6b67, 0x1e78a77, 0x180a784, 0x013ccc3, 0x0dda7c5, 0x0cb1505, + 0x0146842, 0x06c24e6, 0x0b8d423, 0x0138701, 0x04dfce8 }, + { 0x127b780, 0x14e596a, 0x0375141, 0x0b2ef26, 0x152da01, 0x1e8131e, + 0x1802f89, 0x0562198, 0x0bb2d1b, 0x0081613, 0x0b7cf0d, 0x0c46aa9, + 0x074c652, 0x02f87fa, 0x0244e09, 0x0dcf9ad, 0x0c5ca91, 0x141fd46, + 0x0572362, 0x01e273a, 0x16b31e1, 0x1740ee2, 0x1c5cf70, 0x09db375, + 0x0cb045c, 0x1143fe7, 0x011f404, 0x00ffafb, 0x1a532f3, 0x18a9cf9, + 0x0889295, 0x1c42a78, 0x1e9e81d, 0x052042c, 0x057790a, 0x078ac4b, + 0x1339bd2, 0x1ed7fc4, 0x1a00b71, 0x0117140, 0x00d0759 }, + { 0x0085f2a, 0x17953ef, 0x0b961c2, 0x1f7d336, 0x08fcd24, 0x05209dc, + 0x1498567, 0x0a31181, 0x08559f8, 0x1815172, 0x0b68347, 0x0043ec4, + 0x1583b96, 0x16e51b0, 0x0170bd5, 0x18d04b8, 0x11c7910, 0x100a467, + 0x1c9a56f, 0x1e512c4, 0x0ef6392, 0x1ad46b2, 0x020f42e, 0x1f978a5, + 0x122441c, 0x1f2f786, 0x1149845, 0x0bb5f9d, 0x0928e9f, 0x095cf82, + 0x0aada18, 0x0727e5c, 0x03f744d, 0x008a894, 0x1fb5c03, 0x1df7dda, + 0x04360df, 0x06f10ad, 0x14d6bcb, 0x0385e10, 0x024fa96 }, + { 0x16df7f6, 0x1ed9fb0, 0x0c981d9, 0x11f7b20, 0x043057d, 0x016aa23, + 0x0aa41ba, 0x1b62e9b, 0x1689643, 0x14279a2, 0x0681808, 0x03bf991, + 0x1218b19, 0x0b613e8, 0x0d1abd3, 0x0a28b75, 0x086c989, 0x12d2bfa, + 0x1250be7, 0x0429d39, 0x0158c03, 0x07a0ca8, 0x09cf872, 0x15a8756, + 0x1759f39, 0x0b9c675, 0x1f943b8, 0x1c3716f, 0x0d7d4e5, 0x18fe47a, + 0x1cfd8d6, 0x0eaac07, 0x0ff77e3, 0x17d3047, 0x0745dd4, 0x02403ec, + 0x0a6fb6e, 0x0bd01ea, 0x0045253, 0x07bf89e, 0x0371cc2 }, + { 0x090c351, 0x188aeed, 0x1018a26, 0x1e6c9b3, 0x0d196eb, 0x08598db, + 0x0480bd9, 0x05eef51, 0x06f5764, 0x01460b2, 0x00049f3, 0x1c6c102, + 0x1bdc4f7, 0x0e26403, 0x0db3423, 0x081e510, 0x156e002, 0x1894078, + 0x072ce54, 0x14daf13, 0x00383f9, 0x099d401, 0x1029253, 0x0fa68e8, + 0x17e91e8, 0x12522b4, 0x1c9b778, 0x01b2fa0, 0x00c30e7, 0x12c6bb2, + 0x1181bda, 0x0b74dcd, 0x1c2c0e8, 0x009f401, 0x09ebc6f, 0x1e661ed, + 0x09f4d78, 0x101727e, 0x1edfcf9, 0x1401901, 0x092b6bc }, + { 0x100822e, 0x0ae41af, 0x1c48b8f, 0x057162d, 0x0e82571, 0x1851980, + 0x0a7124a, 0x0a90386, 0x1a7cc19, 0x1a71956, 0x0504fda, 0x19dc376, + 0x070bee9, 0x0549651, 0x1edeea9, 0x122a7db, 0x0faea3b, 0x0e6a395, + 0x03c303e, 0x013cfc0, 0x1b70e8f, 0x192e6f5, 0x0938761, 0x136c76d, + 0x1ae084a, 0x1b2ff15, 0x00ff563, 0x0802837, 0x162759f, 0x0f6d51d, + 0x0235fb1, 0x0f21c61, 0x0af6e67, 0x1bf18cd, 0x00c07c9, 0x1842b5b, + 0x0f33871, 0x0da5cc6, 0x1e2779f, 0x1929e05, 0x071ff62 }, + { 0x04a84d9, 0x0388115, 0x079aa93, 0x1abd78e, 0x02ee4ac, 0x06b2bc7, + 0x0a297c7, 0x14a7623, 0x1fff120, 0x1faf7cf, 0x1940ce0, 0x11c213c, + 0x00a4c59, 0x050220c, 0x1a7e643, 0x05183c3, 0x146f598, 0x1c5c196, + 0x0ebd4da, 0x1e51406, 0x168a753, 0x18db6a7, 0x04bb712, 0x199a3e1, + 0x0692a72, 0x01976ef, 0x1748899, 0x07541ef, 0x12661cd, 0x1b1f51e, + 0x168e36e, 0x1fb86fb, 0x1e19fc6, 0x1b5a678, 0x0d4213b, 0x12d8316, + 0x1f1bba6, 0x141ff4e, 0x009cf9a, 0x1cebf2b, 0x040fd47 }, + { 0x07140a4, 0x05ba313, 0x0bed6e2, 0x1dd56de, 0x0dbbfc1, 0x0312a43, + 0x12239a6, 0x185bb3d, 0x12eb6ef, 0x0df75d0, 0x03fe21a, 0x0295159, + 0x10cfc22, 0x1ad10ca, 0x15725ba, 0x1f6d32b, 0x0054171, 0x1c99c4e, + 0x0d1a0cd, 0x0ba8a43, 0x025c2d8, 0x042089a, 0x0535a28, 0x0d842e8, + 0x00139ec, 0x026f296, 0x1fdcc02, 0x019e172, 0x178aa32, 0x15130fa, + 0x10c6b05, 0x1f36d5c, 0x0b9fab3, 0x0534a8c, 0x0447615, 0x0cd1b04, + 0x1ffbe28, 0x19a6cc6, 0x0ce302c, 0x0afcc72, 0x05b1c11 }, + { 0x0b6bb8f, 0x0d558b9, 0x0b0a43b, 0x0405f92, 0x0dc64ed, 0x14a639c, + 0x08f17f9, 0x1c9e857, 0x1cb54dc, 0x0b6e32f, 0x108370c, 0x0d46c64, + 0x14cb2d6, 0x02b6e7c, 0x19c1b9c, 0x0593a2d, 0x164a4f3, 0x01404e3, + 0x09bb72a, 0x11b061d, 0x1f57ab1, 0x1340e32, 0x13f46b3, 0x1425820, + 0x1651c7d, 0x1240fc8, 0x1b1de46, 0x15877ac, 0x1e67a30, 0x0e7a3c2, + 0x046dab4, 0x1b41fab, 0x0d3fc44, 0x031a272, 0x0005b87, 0x079c2c9, + 0x13e50ab, 0x0f4e5c1, 0x1bbd213, 0x0754ead, 0x0963ab8 }, + { 0x14ea5a3, 0x1a3ec6f, 0x17fa512, 0x0ab9fc8, 0x1656881, 0x1e1ab24, + 0x1f56228, 0x02ba2dc, 0x0e7c99e, 0x072ad9f, 0x01c6f21, 0x009beaa, + 0x0e3fee2, 0x0202bee, 0x001bca4, 0x0aae0e2, 0x10dbba7, 0x07f461c, + 0x0c66b6b, 0x0b796c6, 0x1fd8364, 0x183e105, 0x00627a2, 0x0fb2af1, + 0x109697d, 0x11dc72a, 0x06e67d3, 0x06fa264, 0x0cfb6a0, 0x1290d30, + 0x168046c, 0x106e705, 0x0594aaa, 0x0ee03b3, 0x07f60f0, 0x0991372, + 0x076b988, 0x015c4c8, 0x11561ae, 0x1f97c8b, 0x0443480 }, + { 0x114221a, 0x1ffda48, 0x09ebe3f, 0x1c7d0af, 0x0aec4f2, 0x12a3c3a, + 0x143903e, 0x0a485c5, 0x1d6f961, 0x19f3598, 0x1a6ddfb, 0x0a6ff7f, + 0x0ab2296, 0x1da1d43, 0x0a743cb, 0x0558d85, 0x0ed2457, 0x1920942, + 0x1c86e9e, 0x0d122fc, 0x078da38, 0x00608bd, 0x16fbdf0, 0x02c0b59, + 0x09071d3, 0x1749c0a, 0x18196a3, 0x05b5b53, 0x02be82c, 0x1c6c622, + 0x16356c4, 0x1edae56, 0x16c224b, 0x01f36cd, 0x173e3ac, 0x0373a6a, + 0x0170037, 0x168f585, 0x09faead, 0x1119ff5, 0x097118a }, + { 0x1ecb5d8, 0x02cd166, 0x019afe7, 0x175274d, 0x0083c81, 0x1ba7dfc, + 0x1760411, 0x16849c1, 0x0a02070, 0x1bcd1e5, 0x1ede079, 0x1f761f7, + 0x049d352, 0x1f7950e, 0x0c36080, 0x1ca0351, 0x17b14b3, 0x15c2c31, + 0x0a20bfc, 0x0e14931, 0x0fa55ba, 0x019d837, 0x089cc02, 0x05fdc55, + 0x002f410, 0x1d2d216, 0x0628088, 0x09cec53, 0x03fc72e, 0x1d1342e, + 0x19f6e8a, 0x1fca5d5, 0x14fe763, 0x1a2fb2a, 0x01689c3, 0x18616a8, + 0x0573387, 0x150bbd5, 0x1ea0b55, 0x11a96e3, 0x017c077 }, + { 0x135e37b, 0x0ff8e93, 0x15c839b, 0x0ccadd8, 0x09884e5, 0x1dd4bc6, + 0x0b2767a, 0x18945eb, 0x0ba09f3, 0x07d228c, 0x010ddd0, 0x02efeb6, + 0x0a8c3fa, 0x0b3d176, 0x0877b36, 0x17a8143, 0x0700528, 0x13b45e5, + 0x01a4712, 0x092a563, 0x1fd5f22, 0x02f436a, 0x05b84b1, 0x10b34d4, + 0x1915737, 0x1073d06, 0x0683ff3, 0x047e861, 0x0cc9a37, 0x1bcdd4b, + 0x0e16a36, 0x035a474, 0x1d12ae0, 0x1aec236, 0x0e878af, 0x0d3ffd8, + 0x0452ed6, 0x074270d, 0x1931b5b, 0x190ae3f, 0x01219d5 }, + { 0x02969eb, 0x1533f93, 0x1dcd0fa, 0x1a5e07c, 0x1a3ab39, 0x1d84849, + 0x1f9455e, 0x0e9cc24, 0x18d1502, 0x1c15876, 0x02f6f43, 0x15b1cb0, + 0x0bffffc, 0x14ba1f3, 0x14f41d6, 0x023aca3, 0x1b18bac, 0x00a425e, + 0x0c930e2, 0x1b3321d, 0x07c695c, 0x083fd63, 0x085a987, 0x09cd70e, + 0x0f762a0, 0x0642184, 0x072e95f, 0x10cbbac, 0x14a07a2, 0x1586e91, + 0x1e4f0a5, 0x0740f27, 0x0f92839, 0x14f673b, 0x187c2f8, 0x04e16af, + 0x1e626f4, 0x0a5417b, 0x1c8c04c, 0x165acaf, 0x02c8d7a }, + { 0x025e4d6, 0x1ac4904, 0x0d119f3, 0x0addf07, 0x1f51eaa, 0x080846e, + 0x197604c, 0x07ec7cc, 0x18dd096, 0x14fc4fa, 0x190da88, 0x09bb3be, + 0x078c4b1, 0x0a2f5dd, 0x16b91a7, 0x1e70333, 0x1775a4d, 0x188c555, + 0x078dffa, 0x12f17a5, 0x17efda8, 0x1556516, 0x1a73b56, 0x0fad514, + 0x0d05dc6, 0x11a364c, 0x15dfe12, 0x08e97e1, 0x0cd59a7, 0x059776c, + 0x1ef510a, 0x1a3a731, 0x0fd1cd5, 0x10588d8, 0x0f6e528, 0x08b2c02, + 0x1b404c4, 0x15b82d0, 0x165625b, 0x0ee9613, 0x02299d2 }, + { 0x04397e6, 0x06ac6e3, 0x0c796e7, 0x1d7edba, 0x0c198f1, 0x0f8ed95, + 0x16384fa, 0x118b0cd, 0x18fcdc6, 0x02d7143, 0x1007f50, 0x019bca7, + 0x16a4b28, 0x008edaf, 0x058fcb5, 0x1f141b9, 0x189bec4, 0x1f6aea8, + 0x05bba62, 0x1fa27b2, 0x148e336, 0x198216f, 0x1a496c6, 0x1c00e9c, + 0x16291ac, 0x14a867a, 0x0094c5f, 0x11a7169, 0x1c446be, 0x0e95c10, + 0x0d31eb4, 0x1e16cb2, 0x1c44135, 0x106a838, 0x0dbd4b2, 0x0d2e36e, + 0x07b46c2, 0x0ffd2b9, 0x1863abe, 0x0f2326c, 0x021ac67 }, + { 0x17fbcd2, 0x1071f96, 0x1062ad0, 0x072f7bf, 0x1272247, 0x1aea5a0, + 0x0cfe137, 0x1a69240, 0x03807b7, 0x1e6a11b, 0x10d895b, 0x1613667, + 0x14dfc19, 0x1079140, 0x15bcdd6, 0x0337027, 0x059037c, 0x0384bc5, + 0x1fc9ee7, 0x13132e1, 0x03894f3, 0x02b0ad2, 0x1f03869, 0x0c05ee9, + 0x1496a3e, 0x10e7fd1, 0x06c9872, 0x07e3886, 0x0164cdc, 0x08edf70, + 0x07d8488, 0x1cfef7d, 0x0463ee4, 0x170dd98, 0x19e24b0, 0x0c02bef, + 0x04483a5, 0x1ec46b1, 0x1676198, 0x1ce1cc5, 0x00e8ec1 }, + { 0x00878dd, 0x06614c5, 0x1c6aa23, 0x1acc800, 0x19ac175, 0x0b9b0bc, + 0x1208294, 0x02b2068, 0x0dd58a3, 0x0b6811f, 0x088684c, 0x17a911a, + 0x0330785, 0x0ace247, 0x12cf79e, 0x14ee36e, 0x1824c67, 0x1a17701, + 0x02e4514, 0x1ed9bbc, 0x1e9159e, 0x144d91b, 0x1e0c2b8, 0x0bb064a, + 0x07a4c49, 0x13370c2, 0x1b41dcd, 0x0f6242f, 0x14a3256, 0x1643514, + 0x0996064, 0x10c9b06, 0x0aa0f56, 0x09f2dbb, 0x144bd2c, 0x1bc5457, + 0x1b6b73f, 0x0860e00, 0x0d8d761, 0x0beba20, 0x0653a79 }, + { 0x0dcb199, 0x144c2a8, 0x0d833f8, 0x1cff405, 0x135b8e5, 0x1b01e85, + 0x15f0f25, 0x16b794f, 0x127f131, 0x0729446, 0x04b54ac, 0x09bdc56, + 0x073aa70, 0x0edb92e, 0x01ac760, 0x16227c4, 0x19ac5d1, 0x1858941, + 0x0d175d8, 0x12e197b, 0x1e8e14f, 0x1f59092, 0x1265fe4, 0x0fb544d, + 0x1739cee, 0x074deba, 0x1c7fbc8, 0x0dd97a7, 0x0a42b14, 0x108a3e3, + 0x147e652, 0x04ff61f, 0x089eb4f, 0x06d25e9, 0x14c6690, 0x0c2230d, + 0x1b9d797, 0x1fb2d2f, 0x19d7820, 0x0f7a888, 0x030dfc4 }, + { 0x0aadfe8, 0x02d714f, 0x004af3f, 0x0969a9d, 0x05027e5, 0x099ab09, + 0x00b7e2d, 0x029560e, 0x056a6a2, 0x15ce102, 0x041a3a8, 0x1ef460b, + 0x0fb1a3d, 0x0c41888, 0x1452c86, 0x11c3946, 0x136c4b7, 0x05bdf11, + 0x18bda61, 0x0e79cc7, 0x1ac6170, 0x1316efb, 0x01b8452, 0x1af8791, + 0x192bf07, 0x14493b0, 0x0fac6b8, 0x1b4d3c1, 0x1849395, 0x18ba928, + 0x08260eb, 0x080f475, 0x0c52a4d, 0x1f10c4d, 0x1f6ab83, 0x022a6b8, + 0x197f250, 0x17f4391, 0x04b3f85, 0x03ea984, 0x0572a59 }, + { 0x1a5553a, 0x1420c84, 0x0ef1259, 0x1064ee6, 0x1f05431, 0x17eb481, + 0x0d2c8fb, 0x1a9f39d, 0x1f22126, 0x09e5fcd, 0x1655e2f, 0x03805fd, + 0x186d967, 0x0501836, 0x0965f3b, 0x09fcb77, 0x1613d67, 0x15b82f6, + 0x1fccfdd, 0x06c456c, 0x0c31f1d, 0x0308e5c, 0x056f3cf, 0x07a3552, + 0x067dce5, 0x1a1d1c2, 0x07e422a, 0x005fd25, 0x15767a9, 0x04cec68, + 0x1edb8f9, 0x1215fa0, 0x142db5c, 0x18c8740, 0x1ef1b22, 0x1c2418d, + 0x04919a4, 0x0432a99, 0x0b0f203, 0x1c3b190, 0x065c2cb }, + { 0x060bb63, 0x06d1053, 0x0915a13, 0x150dd0c, 0x07dc3b0, 0x10776b9, + 0x0b3d9ae, 0x0b0ec8e, 0x1679dd1, 0x0e0b172, 0x14b511e, 0x04ee108, + 0x1eb6884, 0x009fabc, 0x06f1acd, 0x02ee105, 0x1ec9501, 0x1c9750a, + 0x1dce060, 0x09c6008, 0x12f15e3, 0x04b9f0e, 0x030f28d, 0x137a7bd, + 0x0f1dc22, 0x169d2e2, 0x0e53bdf, 0x107dfe3, 0x0e7a1a7, 0x19c6efd, + 0x1491b6d, 0x0341330, 0x153d72e, 0x07a55a1, 0x1562837, 0x124a675, + 0x0e7888b, 0x02a80b0, 0x1fd9b60, 0x1aa774e, 0x0831440 }, + { 0x011b2da, 0x117197b, 0x1ab3d0f, 0x13a1f48, 0x1d066e2, 0x059e06a, + 0x1cfa208, 0x1e1d12f, 0x01d3e44, 0x02e1473, 0x09e99b1, 0x1ecdbfa, + 0x17929d7, 0x080f428, 0x16e1828, 0x0f1bae6, 0x0983de0, 0x1751fe7, + 0x0e33846, 0x0efb6ac, 0x0b3bc99, 0x17a429b, 0x01220e0, 0x195bf8c, + 0x07a3c64, 0x1b8bf06, 0x1e0851e, 0x19a2fef, 0x011e3e3, 0x11e60da, + 0x1b7a559, 0x130bf68, 0x139ac8f, 0x08ce52b, 0x0736f3c, 0x0a70a73, + 0x015a281, 0x0c2d387, 0x115992a, 0x114dabe, 0x0504c3a }, + { 0x0fa53c7, 0x0a941dc, 0x138c02d, 0x10a128e, 0x185cff3, 0x1e712fc, + 0x090710d, 0x1da469a, 0x0e5a129, 0x0c19218, 0x1319d0a, 0x12ad557, + 0x016ad38, 0x1f740f7, 0x1700075, 0x04e0545, 0x0b6670b, 0x1a611e3, + 0x1ba28ee, 0x1cacfd4, 0x13eab35, 0x07534b3, 0x0f1c2cf, 0x1c51d59, + 0x1a9c3e6, 0x1ed42d3, 0x1954ded, 0x15cd09b, 0x0937dc2, 0x01f2b6f, + 0x0897b2b, 0x1f08608, 0x12ea6c9, 0x0e2905f, 0x1f41dff, 0x1a7195e, + 0x09f56ad, 0x1d7858b, 0x0874b09, 0x1338e3a, 0x0496e46 }, + { 0x1a93467, 0x07e414f, 0x1852e85, 0x081d654, 0x02e3768, 0x19f04de, + 0x13ebd20, 0x198cb37, 0x03686bd, 0x042cba9, 0x0c85aaf, 0x010103e, + 0x1840bfd, 0x0be040d, 0x18ef698, 0x0f27788, 0x086bb04, 0x0de80fd, + 0x1359031, 0x03d9cc5, 0x15c45a2, 0x0a1101e, 0x05efda9, 0x022cf6f, + 0x00edc95, 0x134675a, 0x1dd96e8, 0x0cf5595, 0x0b51f9d, 0x0cf4d75, + 0x0ea2e83, 0x161ad0c, 0x14b215e, 0x034a960, 0x136f97c, 0x0a6a99b, + 0x0b3744b, 0x15ae67e, 0x1ffa13c, 0x0e62606, 0x0133891 }, + { 0x1003cd1, 0x0032022, 0x0b1bb9a, 0x18895c5, 0x1dac17b, 0x07298a7, + 0x1067f7a, 0x0b8979a, 0x1c7cea9, 0x0f1a75c, 0x0df8060, 0x0c5a71e, + 0x08bb577, 0x1304c86, 0x1133ec0, 0x094f7d9, 0x1f950a3, 0x185e249, + 0x10cc13b, 0x0e82e4a, 0x0a2a680, 0x1935e45, 0x0bb03f2, 0x08bfd4b, + 0x09b463b, 0x1d64f3d, 0x1957ef6, 0x17652a5, 0x05dff44, 0x0053024, + 0x05943c3, 0x09bd48f, 0x0c5104d, 0x11d0101, 0x0825a57, 0x0ba59df, + 0x0da1f34, 0x00815a3, 0x0fef532, 0x0e7e706, 0x0422eb5 }, + { 0x0ad3f47, 0x0975b53, 0x083ab16, 0x1b2e297, 0x10861f6, 0x140a2cd, + 0x1a4641c, 0x006af83, 0x064ea58, 0x1be4a71, 0x049c8f3, 0x0d58a96, + 0x0a72537, 0x0d7db9b, 0x09ae907, 0x079b9e5, 0x120cba0, 0x0e44f44, + 0x0c3f4eb, 0x041968b, 0x19fef2e, 0x0a6b302, 0x09ba969, 0x13bf178, + 0x1fa8b88, 0x15ff731, 0x059a8fc, 0x01e38fc, 0x1312e14, 0x1e4e3a3, + 0x1fc27fa, 0x0e4f333, 0x119b9c2, 0x09582be, 0x0d32dff, 0x0d53f77, + 0x00da2dc, 0x1d13ebd, 0x0960b3e, 0x19e584a, 0x0368541 }, + { 0x0799d37, 0x09e4f11, 0x0ce9443, 0x0b59f46, 0x1b677de, 0x07bcad8, + 0x1863c20, 0x1849cd5, 0x0afc8df, 0x0da9e15, 0x10b709a, 0x036c1d0, + 0x0879754, 0x16033ff, 0x09bcabe, 0x1b0efab, 0x003bd07, 0x1681045, + 0x152f8bc, 0x08e7e0c, 0x023e34b, 0x157a8af, 0x199f040, 0x1835e91, + 0x1bf9d2a, 0x0805806, 0x06da84f, 0x04c9f48, 0x094c11e, 0x1c354bf, + 0x1d059a5, 0x10d4b0d, 0x1d8cf2d, 0x093f484, 0x01a71fe, 0x0c0e77f, + 0x0241a56, 0x0bbc401, 0x04cd2e2, 0x0b2444c, 0x059a5bf }, + { 0x1347191, 0x0e48f40, 0x05cba74, 0x19d72d3, 0x186c1ab, 0x0a353f8, + 0x01d9ea7, 0x12e0f11, 0x0daa7d3, 0x149e7e6, 0x0e6a836, 0x13e3b23, + 0x0c08bee, 0x1c6e9e3, 0x19ff5e3, 0x1020104, 0x0d09422, 0x1fc9c30, + 0x0b6d1fe, 0x14e355b, 0x0f8a6a6, 0x1bd30ab, 0x072a81a, 0x1091793, + 0x105e039, 0x09ad50d, 0x1caaaa4, 0x0dbb846, 0x1f3bd13, 0x103cd89, + 0x135df9f, 0x09598be, 0x10b5cbe, 0x07e9b46, 0x17e2613, 0x1009b48, + 0x13d3e0f, 0x077b0c6, 0x1e673c5, 0x18287d6, 0x0467564 }, + { 0x0fff5d7, 0x12c825b, 0x1d4a35c, 0x1f25b88, 0x037f33a, 0x105c550, + 0x155d5b4, 0x073212b, 0x143baec, 0x111afe0, 0x0ae6c0c, 0x095ed14, + 0x01a2feb, 0x0a69ae3, 0x1140c62, 0x0e90cc3, 0x0a2ea87, 0x1d6495b, + 0x046f1bc, 0x09162a0, 0x1cb28eb, 0x1463cf6, 0x08a3f84, 0x1a5400d, + 0x1bc0ca5, 0x0284fb8, 0x08bc56e, 0x062cee6, 0x036218f, 0x19463d0, + 0x07bfa35, 0x09f03c1, 0x08f39cb, 0x0286c83, 0x0059edf, 0x062ee7e, + 0x0d6a1e0, 0x07bd6df, 0x0135434, 0x02c9dd3, 0x08a0dee }, + { 0x1366e6f, 0x0c8dfa3, 0x0015412, 0x1fd0d86, 0x18084d9, 0x06671b5, + 0x11d4690, 0x1c42989, 0x03f1961, 0x1da3553, 0x11790ee, 0x0bf2808, + 0x1f56a78, 0x048f10a, 0x0346d5f, 0x1011bb7, 0x13ec7ee, 0x0354722, + 0x0ea87a3, 0x0cfdf17, 0x0109c03, 0x18f1f0c, 0x0c43647, 0x0414586, + 0x0fd0e7e, 0x13bfcbe, 0x1155330, 0x03d0190, 0x028403f, 0x1e0ebdb, + 0x1f3a26e, 0x07fc142, 0x178a966, 0x00039bb, 0x067f07c, 0x053d3b6, + 0x16f6bed, 0x13ff3ed, 0x1388cb3, 0x1a5dd2f, 0x07b04b5 }, + { 0x0c5faf8, 0x035e3c1, 0x025d6d5, 0x1d1d702, 0x1a734c5, 0x1c28f00, + 0x1a1879d, 0x03e7aac, 0x1e956d5, 0x19d0809, 0x0f0df20, 0x0e63878, + 0x0cc7351, 0x1060a47, 0x1dce3ef, 0x1de82c0, 0x0bbe1bb, 0x1976378, + 0x1e94615, 0x0558dd9, 0x0df00aa, 0x0bb371d, 0x01ca40b, 0x045adc6, + 0x15089c6, 0x017e6a6, 0x0e9b760, 0x15c4364, 0x0863723, 0x0d2a99c, + 0x08b9519, 0x151b030, 0x05119a0, 0x14bbd6c, 0x00c8de1, 0x189e29a, + 0x1c7b272, 0x0d840e4, 0x18c7145, 0x1499337, 0x01c6a95 }, + { 0x0821363, 0x0a56ae1, 0x18729ac, 0x069a2fb, 0x029c182, 0x16f4244, + 0x14b1332, 0x04f5deb, 0x182489e, 0x009559c, 0x07649fd, 0x0131e10, + 0x1f92c9c, 0x1ae5d68, 0x01ef7d1, 0x13f62df, 0x0b81a1d, 0x17a556d, + 0x1d7cedd, 0x14f2476, 0x08fe475, 0x0b6dddd, 0x067742b, 0x0e1568b, + 0x161644b, 0x178c1b7, 0x04d2f66, 0x148c910, 0x1abda32, 0x11375d4, + 0x1ed7244, 0x1ccac4b, 0x0ec8709, 0x0725f26, 0x0678206, 0x19a9672, + 0x14f6879, 0x004e420, 0x1932697, 0x0046150, 0x072708a }, + { 0x14a466c, 0x1e058f9, 0x16e93cc, 0x18ff3a8, 0x01bae09, 0x143c2e5, + 0x03fb838, 0x103ae1e, 0x0908808, 0x12638a3, 0x10f68e0, 0x1855760, + 0x12e2416, 0x07637a1, 0x0f69c4f, 0x07c38e6, 0x049c979, 0x095ac83, + 0x0d724d9, 0x05ab616, 0x1b2adb6, 0x111f2e0, 0x0d57adb, 0x02d6a2a, + 0x0b5cebb, 0x08e67f4, 0x07dc25a, 0x1c1030d, 0x085bd59, 0x1cfdb0d, + 0x1df2197, 0x1f5c207, 0x169d3cc, 0x13f4ef8, 0x11cdcd1, 0x072a4b8, + 0x0369511, 0x1aae05a, 0x17485f6, 0x098e64c, 0x07491c7 }, + { 0x0d2b94d, 0x16adfc0, 0x182cc4b, 0x0774964, 0x1b8ac63, 0x110cd08, + 0x1163358, 0x11d590d, 0x1aeb82c, 0x0be67b5, 0x1e73b4c, 0x13dcb3d, + 0x1a2dfb2, 0x1215e6a, 0x09f6263, 0x16403b5, 0x1c85974, 0x049f14a, + 0x07f16b7, 0x0eaf09b, 0x03ba69e, 0x0f80955, 0x15b11c2, 0x0ba7973, + 0x09f37c8, 0x15e8fed, 0x174f752, 0x0a90fc4, 0x1ba22ee, 0x0580859, + 0x0ec03f5, 0x18dd1b9, 0x1591493, 0x1433265, 0x1eaef39, 0x0d6e653, + 0x08906b7, 0x14e8e13, 0x1a105a0, 0x1cae82e, 0x08bcfd3 }, + { 0x1c8c314, 0x0139a69, 0x00cc1a2, 0x02230e1, 0x15f0b2f, 0x145d0b4, + 0x1df0f01, 0x10f726f, 0x0779247, 0x1b2f06c, 0x04889d4, 0x1cbc3f3, + 0x0f15527, 0x13effea, 0x01a5920, 0x0c71214, 0x1f22f58, 0x0eac59e, + 0x0bc83ab, 0x08d712d, 0x0257834, 0x05a83a3, 0x0275e5c, 0x0454d22, + 0x0d20640, 0x1bcecf4, 0x1d9c7b0, 0x03cbf15, 0x1fe91ed, 0x128482b, + 0x061bd50, 0x0a51208, 0x14dda81, 0x09956f8, 0x043876e, 0x117af00, + 0x105a937, 0x0c68f24, 0x0ad24f8, 0x1ef7a6f, 0x053cadc }, + { 0x053d0ff, 0x0f6fbaf, 0x1d9c6ed, 0x1911157, 0x1886606, 0x10368ae, + 0x0c3e048, 0x066c923, 0x1e22b6a, 0x180c1a2, 0x0ecc5ec, 0x129762e, + 0x15aba67, 0x1ee4f2c, 0x079619d, 0x049a318, 0x0822396, 0x1a70832, + 0x0957754, 0x0a5cb3b, 0x079c617, 0x15cf214, 0x0062d3a, 0x03e57da, + 0x0784b49, 0x14f657b, 0x0879e50, 0x1b9b73a, 0x1262243, 0x0a42887, + 0x170da50, 0x14ca1d8, 0x06f190a, 0x14bb008, 0x16bada6, 0x0cea854, + 0x032d104, 0x1ebaf4e, 0x18ac5a6, 0x0c97f18, 0x0908499 }, + { 0x093c661, 0x0867b2d, 0x015ac4e, 0x093b6be, 0x1848626, 0x0d0bc40, + 0x0ea7694, 0x1352552, 0x16772de, 0x1865dc7, 0x0521f06, 0x1d7af8e, + 0x1e6e67f, 0x0731211, 0x0d0e0b5, 0x085f1f3, 0x10ebb5a, 0x14b7ed2, + 0x022693c, 0x03666ec, 0x0516c92, 0x1dc3af6, 0x1274cb5, 0x0202496, + 0x0d2cac4, 0x1bd5ec3, 0x071087e, 0x0d0c441, 0x17de33f, 0x04d5fb5, + 0x1a0f865, 0x1d27924, 0x1ee18f0, 0x0266066, 0x1578237, 0x05a9db7, + 0x13580d2, 0x1badf23, 0x15fa30a, 0x1f48d19, 0x03d7f6f }, + { 0x1fbd5d1, 0x194866f, 0x037fa9e, 0x0d2e067, 0x1d759da, 0x1f76e4c, + 0x02c2243, 0x11cacd0, 0x142dce6, 0x034857a, 0x19360af, 0x1e57655, + 0x008519d, 0x1f8cadb, 0x04919fd, 0x043e8ac, 0x02cd83c, 0x1b2cd1a, + 0x159458c, 0x0e37eaa, 0x0562557, 0x1aaa45d, 0x17f1a24, 0x125e474, + 0x1920394, 0x00bdaa0, 0x0e72718, 0x0cea51c, 0x1e60195, 0x076a288, + 0x154fc19, 0x03a2d4a, 0x03f9eb9, 0x055f718, 0x13f4895, 0x187c318, + 0x1d434e7, 0x0ca6b7f, 0x1d39902, 0x07edbbc, 0x08fb12d }, + { 0x13cb7a4, 0x1c0d114, 0x1935b18, 0x0170f6f, 0x053e09f, 0x0561f7a, + 0x0a08c1e, 0x1229e42, 0x0578cae, 0x04ffd68, 0x0e9377a, 0x12d4e2d, + 0x004a2b6, 0x1b7ac05, 0x1a06853, 0x0260e28, 0x17b4c2f, 0x089ac7c, + 0x04cbee2, 0x12d32c5, 0x1af7878, 0x0513452, 0x0a77614, 0x0473f06, + 0x11f6dfe, 0x0ced7bb, 0x193d1d2, 0x1e41fa5, 0x1ca0e95, 0x1f3bc33, + 0x1b26d90, 0x06eb303, 0x1858ecd, 0x18e4bf3, 0x096466a, 0x077d28d, + 0x06ff345, 0x0981d10, 0x0dec53e, 0x062eba4, 0x03fcc67 }, + { 0x121f920, 0x0f5eaef, 0x0e41427, 0x1f82803, 0x1af70e1, 0x132557f, + 0x12ff656, 0x0444853, 0x12c37a1, 0x109042a, 0x0e49afc, 0x07e8fbd, + 0x1c1d4c9, 0x0fd9f8e, 0x1cf9302, 0x1788c25, 0x0595b51, 0x12b042d, + 0x043f6f4, 0x1ebac5e, 0x13c22a2, 0x07ef865, 0x183758b, 0x01e4a96, + 0x024a36b, 0x15b8aa2, 0x1559184, 0x074b40b, 0x15249cc, 0x1867d0f, + 0x022faf8, 0x0fcc543, 0x0ec6903, 0x14c9c92, 0x0eb2bd0, 0x0aebe1f, + 0x13fa868, 0x09a2ee5, 0x070d350, 0x1fb8e2a, 0x0645146 }, + { 0x01924f9, 0x0319d5d, 0x1b87b3b, 0x0c00c64, 0x1ba6f13, 0x087e0bd, + 0x15eb1f9, 0x000406e, 0x1ef3d8e, 0x1298c8c, 0x1169d32, 0x0d54a3b, + 0x189545a, 0x098a095, 0x087563f, 0x1a000dc, 0x0057bb1, 0x180de18, + 0x1b46a70, 0x1138d2d, 0x1a48f17, 0x0fcc2c7, 0x1ebcb4d, 0x12f7d0a, + 0x109b981, 0x12ea1a6, 0x14a6a89, 0x1b80eea, 0x18fa801, 0x1df3e02, + 0x13b2b40, 0x0a97429, 0x0d70a9f, 0x0853a49, 0x1415b01, 0x14db8f0, + 0x0d005dd, 0x1e5254a, 0x07cb8a9, 0x0e557f7, 0x0448d3d }, + { 0x1b33989, 0x178a294, 0x056b715, 0x19535d0, 0x068351b, 0x03a20a4, + 0x1584d2c, 0x07767e8, 0x03cd9f3, 0x0ae7215, 0x1b928e5, 0x09d8bfe, + 0x1113ade, 0x1287554, 0x0ab1c56, 0x1dfbfa7, 0x0995666, 0x10630f6, + 0x1a911c2, 0x145171e, 0x04c9108, 0x0272a42, 0x100bbd6, 0x1c5e66e, + 0x1b162d0, 0x05e5c12, 0x1ed1bdf, 0x1b9a263, 0x12fd893, 0x1c764b7, + 0x1e08205, 0x04b2518, 0x18c5d67, 0x1e22ca6, 0x0f7e658, 0x1e50b46, + 0x192a309, 0x04b8bae, 0x06695c9, 0x0f396e0, 0x0768814 }, + { 0x1767eed, 0x1d08a48, 0x176ee90, 0x1b257ec, 0x1e11b9a, 0x12f10d2, + 0x0b3800e, 0x02bd144, 0x12a3354, 0x1b02210, 0x1ab5898, 0x0768953, + 0x05c2c56, 0x1059577, 0x1018992, 0x1c3ae97, 0x1758bf2, 0x0badc6a, + 0x0228997, 0x1e1dcfa, 0x12a71cf, 0x0ed85b8, 0x05e4538, 0x030d25a, + 0x125d04b, 0x00ae1ac, 0x115b33a, 0x1c4a7e9, 0x1f0e3ad, 0x120e4ff, + 0x06691e4, 0x1bb57da, 0x0b9d06e, 0x1728328, 0x098167e, 0x00ce26a, + 0x132ce18, 0x1b007da, 0x0189bcd, 0x038bcb5, 0x0670eb0 }, + { 0x1cdbb43, 0x1e057b9, 0x06b77dc, 0x0afe486, 0x0f08ecc, 0x0d1c22e, + 0x01504a8, 0x1e322f0, 0x09224dd, 0x0d08279, 0x11fbfda, 0x071b7d5, + 0x024352f, 0x1e16899, 0x0eced39, 0x168edf8, 0x030b5e4, 0x0534f4a, + 0x1d691bc, 0x0646812, 0x0ece7d9, 0x0f2eb27, 0x0024e26, 0x0468bd3, + 0x01250db, 0x0b5bdc1, 0x09fd2de, 0x06aa526, 0x190b1f2, 0x060aa5d, + 0x158bba7, 0x12225ef, 0x1a9c8f5, 0x157190f, 0x1e6072e, 0x145a1e5, + 0x0075166, 0x1f81b30, 0x1fc9edd, 0x1cec6bb, 0x0504852 }, + { 0x0f392fa, 0x19e72d1, 0x01e0bc3, 0x15d8d92, 0x126c076, 0x1d557b1, + 0x17a4a12, 0x1275a03, 0x1cbe8e9, 0x00d8b69, 0x142422c, 0x18485b2, + 0x1871305, 0x1c29d79, 0x1bf585c, 0x053418c, 0x00ed3c4, 0x1bb9a8a, + 0x1eafc09, 0x0362543, 0x11778a3, 0x0102c59, 0x0814c00, 0x18fbd73, + 0x1d9fca9, 0x09855ff, 0x0fa199f, 0x00bded3, 0x09e13fd, 0x198474d, + 0x070bce9, 0x1723d5d, 0x14c9a19, 0x073621f, 0x1b9d863, 0x00a1a19, + 0x1240f8b, 0x126e202, 0x03313ec, 0x0a3efd2, 0x0992fe1 }, + { 0x0f197aa, 0x06d989c, 0x1e61115, 0x1b0f0e5, 0x04ded69, 0x1854145, + 0x09ec113, 0x18d2f68, 0x0a31e48, 0x010f0d7, 0x03bfb26, 0x013fbb3, + 0x0ee38cb, 0x040659d, 0x0e13ea1, 0x0aae641, 0x0a84747, 0x1dd2dda, + 0x1543a5a, 0x1c10159, 0x1550a9b, 0x0e77881, 0x111147a, 0x08264b9, + 0x0e75fc4, 0x19eb137, 0x00e2978, 0x1dd4bd3, 0x10abd26, 0x1f5cd15, + 0x0a5cc86, 0x136c105, 0x092e484, 0x1e61565, 0x1a2a64a, 0x163b902, + 0x1c8eb9f, 0x0767a5c, 0x1c7804d, 0x15098b6, 0x05a68bf }, + { 0x10a2bfb, 0x19da2ff, 0x02c2d3f, 0x12aa05f, 0x1105fff, 0x0e06136, + 0x162156c, 0x00829bc, 0x10d3b9d, 0x08b432d, 0x14e45fb, 0x08a604d, + 0x0e2f5a2, 0x1a6d9e0, 0x08bd24f, 0x11e5cd4, 0x08ae241, 0x0a438aa, + 0x026fbd8, 0x06c750a, 0x1bec6ab, 0x1d5c65d, 0x0472878, 0x023472d, + 0x0dc9840, 0x0bbb8f0, 0x0835729, 0x1f305c1, 0x097bc1f, 0x1822c0c, + 0x19fad02, 0x010b5ab, 0x1c24a46, 0x1bdbe25, 0x1e8298c, 0x1fa2b91, + 0x1ef1628, 0x07377bd, 0x1d0e55b, 0x1f33ebd, 0x078acfd }, + { 0x0520189, 0x1bf8afc, 0x071116f, 0x018efec, 0x154202a, 0x11170dc, + 0x11ae77e, 0x10e73db, 0x11f4a34, 0x16b0133, 0x13314b4, 0x1252902, + 0x03cd933, 0x02f4f89, 0x1da8490, 0x16defbc, 0x0a0ae36, 0x0711837, + 0x00e9638, 0x02a4317, 0x031a538, 0x1b50209, 0x0618aed, 0x0637ce3, + 0x0253cbf, 0x10ff46d, 0x08df7a1, 0x1bf8a66, 0x0e48902, 0x09fb485, + 0x14bc972, 0x11754dd, 0x0bcb8f0, 0x1a514b3, 0x183e422, 0x12de215, + 0x1061c94, 0x1a5a465, 0x08d9a32, 0x0e7a0eb, 0x00ad92d }, + { 0x0ca548a, 0x0aff6e1, 0x06aefee, 0x01019b1, 0x0778c62, 0x1361402, + 0x0552cd1, 0x0057d32, 0x1d4be89, 0x11df049, 0x1a07b7a, 0x132a27c, + 0x01847b7, 0x017a00b, 0x0aa3d2c, 0x0ffd1e4, 0x14d4aeb, 0x11f7965, + 0x0ebb57d, 0x18a2a36, 0x11639ad, 0x08cc618, 0x1b0733f, 0x1afb11f, + 0x0c17ba3, 0x04bee15, 0x0d19084, 0x11f4c9a, 0x190bcf0, 0x005bca5, + 0x1ad7afe, 0x016a153, 0x178b4ba, 0x153358d, 0x04d09e6, 0x1a349fd, + 0x075b3ce, 0x1a6e578, 0x1a6ba3b, 0x140e14d, 0x095bbd8 }, + { 0x014bbd0, 0x0924af3, 0x0d8d67e, 0x0f7047c, 0x1567a88, 0x0deb53b, + 0x127b3f0, 0x085c48f, 0x18e835c, 0x1fd57a3, 0x1819a8a, 0x09c155b, + 0x16314ef, 0x0e0b699, 0x0aea98d, 0x1c7120e, 0x071e2f0, 0x1fd214e, + 0x141f643, 0x03cba17, 0x1c04cac, 0x1528a7a, 0x1a7fcd7, 0x0aa9d82, + 0x053fcc0, 0x03fc498, 0x1ca8d65, 0x163b0d6, 0x0be487a, 0x1830157, + 0x0878a7e, 0x1bf739e, 0x0a10d6d, 0x0fe7ad0, 0x0167c83, 0x155a28e, + 0x18867a2, 0x06e337d, 0x0a46520, 0x09f824b, 0x0375a88 }, + { 0x017f7ea, 0x05f1709, 0x16ac5e3, 0x150eb8d, 0x1a161e2, 0x0d8d2a0, + 0x1fb006f, 0x195eee0, 0x0e4fd73, 0x1c43250, 0x0836199, 0x0cc9a27, + 0x08baebc, 0x0469833, 0x0c97e67, 0x0b2a080, 0x1c92f1c, 0x1dc9f6c, + 0x1078199, 0x06cec6a, 0x0763fdf, 0x185c8d3, 0x1f65fee, 0x0f39341, + 0x069ea60, 0x0239355, 0x007aaa3, 0x0e60790, 0x063c55c, 0x0e40d7d, + 0x16f7b1d, 0x09fa255, 0x1cdcde2, 0x041c500, 0x169c65a, 0x133fc1b, + 0x1841537, 0x1d849d9, 0x013b19a, 0x1161197, 0x0268d81 }, + { 0x1580555, 0x171ac20, 0x00edcf6, 0x0e8e7a2, 0x0fc32e6, 0x0660d5a, + 0x0404efb, 0x1bc4818, 0x0b24ee9, 0x1204cf9, 0x03819b6, 0x16b73f5, + 0x0e37b0c, 0x121c6bf, 0x0b81391, 0x002816b, 0x1642b72, 0x03fbe98, + 0x0e7929e, 0x1e9db66, 0x037586e, 0x169d3ec, 0x0979dfb, 0x0e0f85d, + 0x1ad37bd, 0x0c4c41f, 0x083e5e4, 0x02d6c67, 0x1a208e8, 0x0145173, + 0x1ab8930, 0x0886aa2, 0x171fe3c, 0x195fa88, 0x0ccd3d7, 0x0c7d727, + 0x01b53a5, 0x0cf6a58, 0x0912e10, 0x0b80ad9, 0x08b0273 }, + { 0x1019195, 0x1da3270, 0x0306e26, 0x0de7f85, 0x1de4c02, 0x1e1d908, + 0x039b8af, 0x05f5824, 0x091bdf9, 0x038de2d, 0x056f27b, 0x15681b3, + 0x1e485d7, 0x13248ff, 0x119da3b, 0x1c4cb2f, 0x119afbc, 0x16caa96, + 0x186ddb0, 0x0d8ffd1, 0x0d1bbae, 0x00ebf1d, 0x059f60a, 0x1312e68, + 0x09af95e, 0x0c11f0a, 0x1228320, 0x03e0049, 0x006c0dd, 0x1fede18, + 0x133d5c7, 0x0b0ee7a, 0x12ecf7e, 0x0a06c59, 0x1e0bf4d, 0x04b0454, + 0x0436504, 0x1a2e1f8, 0x017f96a, 0x140969b, 0x0400e3a }, + { 0x046e4a2, 0x10b24af, 0x01d11cc, 0x084826c, 0x17a2ed6, 0x0763be9, + 0x08ec718, 0x05ccb24, 0x1e5e0ac, 0x109d561, 0x01eadd7, 0x08378a2, + 0x1bda17c, 0x19e129e, 0x0c8bb25, 0x0452ccb, 0x1b8a501, 0x1ff9c33, + 0x1886a66, 0x0cc1aa0, 0x03f5fed, 0x03644fe, 0x08f0a14, 0x0c8a34f, + 0x150b9f1, 0x0379f69, 0x099f2d6, 0x0f87c06, 0x1185b12, 0x03bccb3, + 0x06f201f, 0x0942601, 0x1c157d4, 0x18fa684, 0x191eb6b, 0x106c5ee, + 0x13a6a19, 0x015cd67, 0x180e529, 0x1451b4d, 0x0131c3d }, + { 0x1da83ba, 0x02ff8d3, 0x10d929e, 0x0ba09e8, 0x1415b42, 0x01fc097, + 0x066f7b0, 0x144f811, 0x080f5f4, 0x0c6a08d, 0x0946e71, 0x0c21fb4, + 0x123d32d, 0x069d979, 0x0ed1413, 0x0107933, 0x04bf4c2, 0x08cc622, + 0x0c3a0ff, 0x04c35ee, 0x1b9060c, 0x0fe5816, 0x0183293, 0x1e3cf90, + 0x1838b9d, 0x06487fb, 0x1f131a4, 0x16f39f2, 0x15f1546, 0x0a6baeb, + 0x1fc4c54, 0x03961d1, 0x1c074f1, 0x0bb0ad3, 0x0b06cb0, 0x0172415, + 0x04aa0ff, 0x004c56a, 0x173a77a, 0x0d468a8, 0x071d1a4 }, + { 0x01b382e, 0x1c7bb7d, 0x0835d85, 0x06ee5bb, 0x00d8ecc, 0x0a68985, + 0x0acab17, 0x05954b5, 0x08d7262, 0x1e9c5d2, 0x0fb4189, 0x1b6d947, + 0x0fc5410, 0x1c9e766, 0x0de9621, 0x1c7afec, 0x0fd6e65, 0x08fb2ed, + 0x0291590, 0x08950ac, 0x140bc3b, 0x1427bc2, 0x03d1ece, 0x09ac1ec, + 0x1dadd5e, 0x16ac127, 0x105f4ed, 0x1199f21, 0x1fc13ad, 0x15ef992, + 0x0e4023a, 0x06c91f5, 0x090d716, 0x096a59f, 0x1ce8931, 0x1672c9f, + 0x133d0ac, 0x0e620b2, 0x1d486e5, 0x13e22cf, 0x06cd269 }, + { 0x0f4f3ac, 0x0059d89, 0x17ecb63, 0x0533a37, 0x103dcfe, 0x19b9935, + 0x0d3e0c3, 0x104a800, 0x17c5a8c, 0x16eb449, 0x1c51088, 0x07a19b1, + 0x12eb709, 0x0c2ba17, 0x09e569d, 0x1b5bb12, 0x02c087a, 0x170af94, + 0x1aaded7, 0x1b8e922, 0x0bb47bb, 0x05d2c56, 0x14c3f90, 0x1758737, + 0x017ebe2, 0x05e06f2, 0x1b18681, 0x1696334, 0x1355694, 0x01a6f93, + 0x1be4ce3, 0x0615632, 0x0f03742, 0x064b2f4, 0x12e1b22, 0x0df45df, + 0x07eeb82, 0x17713a6, 0x1770867, 0x07fb468, 0x0327c06 }, + { 0x147cd53, 0x0cf7fad, 0x1bfaace, 0x1a32875, 0x1be9869, 0x0154335, + 0x131ec50, 0x02dcc9d, 0x0b1c25a, 0x1f3e155, 0x1789c70, 0x16f2045, + 0x1fc4216, 0x1b36b52, 0x037f320, 0x0666dcb, 0x09eda81, 0x068aca8, + 0x0c2fedf, 0x0801e42, 0x0780370, 0x0cc9da4, 0x06f9381, 0x1e79a44, + 0x1a1fe39, 0x1c38311, 0x0bbb2d3, 0x0554456, 0x07b83b7, 0x024b361, + 0x0fc6bd3, 0x1b4bf4b, 0x042a94b, 0x00d793d, 0x008922c, 0x1935f75, + 0x1670112, 0x15ce951, 0x1a15bad, 0x1a381be, 0x0020f19 }, + { 0x0dbba20, 0x08d4352, 0x1714dc1, 0x0db63bc, 0x1618ebc, 0x092c205, + 0x0286799, 0x09b34f0, 0x1d2bccc, 0x0201816, 0x0168925, 0x047a205, + 0x08e9ff0, 0x1d24313, 0x04dfb8c, 0x0228e77, 0x0f24cd6, 0x1f1bf71, + 0x0f415f3, 0x177fa74, 0x0fce79f, 0x09e66ef, 0x17ee85b, 0x0462e4e, + 0x058ec5b, 0x16dc8b0, 0x19c830e, 0x0ed33d7, 0x0f6bba4, 0x01c345a, + 0x1c0989d, 0x1e3140e, 0x0b0092a, 0x108b02a, 0x03aeb32, 0x0133a12, + 0x0c888f6, 0x0bf0ff8, 0x01513dd, 0x041600a, 0x079e727 }, + { 0x020a239, 0x1679294, 0x0c418ca, 0x1d55cd6, 0x11a3974, 0x0050efd, + 0x15ae923, 0x155ac3f, 0x15a3ee7, 0x1229e1c, 0x0111b74, 0x0b41730, + 0x0f54845, 0x0f0b33b, 0x0a765ef, 0x0eb433e, 0x00c7893, 0x0f92965, + 0x1d0ea61, 0x035e7ce, 0x1d8de96, 0x0b3366d, 0x1c31e71, 0x18a71f2, + 0x1854ecb, 0x08e0a51, 0x0a849a1, 0x11b54e7, 0x1f558c5, 0x1da2954, + 0x017a6d6, 0x1f7a2bc, 0x1af7f83, 0x0c9ce9b, 0x049ce28, 0x0d4890f, + 0x1511a05, 0x14595ac, 0x011b790, 0x1c6e02b, 0x0001d3c }, + { 0x145b1d7, 0x11b5cf0, 0x19935af, 0x140138a, 0x13e3938, 0x007b6df, + 0x0b9f79f, 0x0725cac, 0x0c343f5, 0x0882273, 0x025ec65, 0x0571b21, + 0x1ca5ab6, 0x0897bcb, 0x087dc2d, 0x051c963, 0x154750f, 0x0c8e6eb, + 0x1ee0597, 0x101c5ff, 0x02b3b4c, 0x03aca68, 0x197b4e7, 0x1067db8, + 0x0a49d56, 0x10c6609, 0x13cda4e, 0x0e6d297, 0x12c404e, 0x09a57e6, + 0x050d330, 0x023a803, 0x11bd5fc, 0x02f2303, 0x011ff16, 0x080aeb2, + 0x190b7a0, 0x1401b03, 0x11a12cc, 0x1f8815f, 0x04bb8c6 }, + { 0x10f8796, 0x0716efe, 0x0778c48, 0x1b62679, 0x0968a40, 0x1b4e373, + 0x19b02a4, 0x077fd46, 0x0600727, 0x1f2db6b, 0x0050e4d, 0x19e1197, + 0x0539e4e, 0x0ff5e00, 0x1ffa736, 0x16a7890, 0x0440199, 0x1f5c57a, + 0x04d467a, 0x049c765, 0x1c162f1, 0x0564164, 0x0183086, 0x13b8b21, + 0x1d6f270, 0x094d668, 0x14db541, 0x0d2daa8, 0x120bfc5, 0x0efcac8, + 0x04300fd, 0x021ff4d, 0x1a3e88d, 0x19413cc, 0x1e95b10, 0x13a9f39, + 0x1a135d8, 0x07f54f4, 0x1f9e0ba, 0x1036d4e, 0x03699a8 }, + { 0x0b1c64d, 0x119b90f, 0x05516f2, 0x1be3a50, 0x09cf3a2, 0x1b8837f, + 0x1a6cd94, 0x09b6fc5, 0x14f7cbf, 0x160b8a8, 0x02cdfc1, 0x02dc40b, + 0x05cbde4, 0x041a74e, 0x114e9fa, 0x074eb05, 0x1e2e9ac, 0x14a6def, + 0x1799f00, 0x1d8d978, 0x080d795, 0x0f8a135, 0x0308f09, 0x11a9f3f, + 0x0d20d6a, 0x11af716, 0x134edf0, 0x071b54a, 0x1a4d528, 0x07601eb, + 0x1cee782, 0x0f03968, 0x09475e9, 0x18e5565, 0x0e797b0, 0x0ee4e3e, + 0x0253518, 0x18474fc, 0x1fe2c77, 0x0064115, 0x04f3a4b }, + { 0x0d095f8, 0x1c0838f, 0x15383de, 0x0db444d, 0x03e37fa, 0x19b68e9, + 0x0614abe, 0x023161f, 0x007d8e3, 0x08a31a7, 0x03c5bac, 0x152fc7c, + 0x17b9634, 0x010f761, 0x152ee71, 0x0438248, 0x1dbd72b, 0x05a766a, + 0x17c835f, 0x0070d0d, 0x00a2f96, 0x1eefc37, 0x07d4d67, 0x1891155, + 0x154fa5a, 0x0fa621e, 0x0f44127, 0x0dae295, 0x00607a5, 0x159f581, + 0x1784c54, 0x0f40464, 0x1be1c18, 0x1426da4, 0x1d294ab, 0x0089e49, + 0x0b5a7b8, 0x092e018, 0x1e7f679, 0x08d4da2, 0x06d8744 }, + { 0x09a42f5, 0x083d55f, 0x13234a7, 0x186f039, 0x1fd5316, 0x034f508, + 0x169b677, 0x034e34e, 0x188fee9, 0x10cf06f, 0x113c493, 0x09b9f1a, + 0x0499c2b, 0x18d74a7, 0x1db7e48, 0x199840b, 0x076cf28, 0x193fdd4, + 0x15fdf3a, 0x141e03e, 0x1b746e1, 0x1a79fe9, 0x180fc7c, 0x183a427, + 0x1c4a742, 0x0c05076, 0x01f7ae1, 0x195584e, 0x0848bc5, 0x1c8fd78, + 0x0743d75, 0x00f58eb, 0x1f514ad, 0x1e2988b, 0x1cd2413, 0x1b2b472, + 0x1bb70f3, 0x125654b, 0x1582656, 0x193ff38, 0x03cf384 }, + { 0x01fc9e3, 0x0835d67, 0x0e65c01, 0x04ced60, 0x0972174, 0x15fbd9a, + 0x06e379c, 0x1ee5694, 0x079b209, 0x1430154, 0x1aa3872, 0x17219c4, + 0x1a90580, 0x1f1279c, 0x1cce6df, 0x0c5c23d, 0x1916293, 0x05b62ec, + 0x1dec93d, 0x0e9c34a, 0x11e9511, 0x1a82f22, 0x1ce03f2, 0x106437b, + 0x17afb14, 0x0957a6c, 0x0dd1f97, 0x13300d7, 0x19a6080, 0x0eb2df4, + 0x0821549, 0x1a8abd0, 0x04828d9, 0x1053293, 0x1017615, 0x011918a, + 0x1103077, 0x13f39e3, 0x17c98f1, 0x0a1dce7, 0x02b2488 }, + { 0x141159f, 0x1e6f342, 0x02c885c, 0x109f682, 0x18224c1, 0x1650e3b, + 0x018647c, 0x0800f45, 0x0a8b23e, 0x16103eb, 0x08d1294, 0x04214d6, + 0x05071a0, 0x1af694a, 0x03961f2, 0x198d9b6, 0x0ef810f, 0x0b62b5c, + 0x0b610ee, 0x118b1ec, 0x0975124, 0x1eba633, 0x12e40d8, 0x0d8cdec, + 0x0f7f2e6, 0x05f31a4, 0x07049af, 0x05f3a88, 0x0e49e8b, 0x1951b9e, + 0x1c2b01f, 0x1d0361b, 0x0486758, 0x110e8a9, 0x1534751, 0x1942116, + 0x14414a1, 0x130f673, 0x108545c, 0x198d475, 0x0938b3b }, + { 0x0ded340, 0x050b5f2, 0x00daa79, 0x1501d10, 0x0e65fb2, 0x0b9d65c, + 0x0581b73, 0x1532e11, 0x0aaa657, 0x01d021a, 0x006c187, 0x18b0922, + 0x0cf304f, 0x0d05db2, 0x03ed86b, 0x05bebcc, 0x0ecf554, 0x1c0c615, + 0x1bddb57, 0x040aeca, 0x1d97740, 0x0849299, 0x0d59ade, 0x1add6bf, + 0x055e574, 0x05bd723, 0x16956d1, 0x01ef436, 0x147ea56, 0x0bcdc9b, + 0x159e5c0, 0x1e5b59c, 0x0e7e0e8, 0x01e0345, 0x181e13a, 0x03308e8, + 0x1530734, 0x1464f68, 0x075ac93, 0x14bb3d1, 0x06cff58 }, + { 0x1e51f68, 0x000d801, 0x1f59423, 0x0a3a5fc, 0x01d1f22, 0x1ec402f, + 0x0342c26, 0x16fef33, 0x003e415, 0x0af483d, 0x165e609, 0x0cfac0f, + 0x16d1484, 0x0da29c4, 0x170ec7a, 0x0a1e80a, 0x013809f, 0x01a8008, + 0x008cff7, 0x165f4da, 0x00b8fbb, 0x057f8c1, 0x02da02c, 0x1a62fc0, + 0x004dc38, 0x1efd8ea, 0x1333231, 0x067aa88, 0x013f841, 0x03f3376, + 0x121fea1, 0x008dc5c, 0x13f83d8, 0x1d9d661, 0x1f15218, 0x0e78c4f, + 0x0b936af, 0x13fc557, 0x04c9d7d, 0x11e636f, 0x05fe4ac }, + { 0x16f401e, 0x1525fc5, 0x1b51606, 0x075ab8f, 0x05db12a, 0x183da50, + 0x01c99be, 0x1a8f603, 0x09c22bc, 0x0e88f82, 0x1c7257f, 0x0fa8d26, + 0x0f5454a, 0x0cd2375, 0x1b157ee, 0x12da00c, 0x07c7fef, 0x00c31be, + 0x0e0fa57, 0x183a68d, 0x02dcbaf, 0x09805da, 0x1570e16, 0x1cfce24, + 0x1ec2b34, 0x1746ec6, 0x02c6133, 0x13939f6, 0x0278646, 0x062124d, + 0x19e3730, 0x04021e5, 0x10d95f2, 0x1d21014, 0x1325a5d, 0x1b0dc4a, + 0x0b2abda, 0x098e44f, 0x0152082, 0x0c82438, 0x0813771 }, + { 0x05a8edf, 0x1592f4e, 0x1eb5899, 0x0420f14, 0x0e1388c, 0x1b776fb, + 0x1cdf521, 0x02ebe04, 0x1627446, 0x017d3fc, 0x14e0a89, 0x17b3670, + 0x0f3e2cf, 0x017b8df, 0x16b5ec4, 0x0152575, 0x0fa677d, 0x02b155e, + 0x07f7fcd, 0x1d7a2ea, 0x0c78573, 0x093e128, 0x15fd961, 0x0f9512d, + 0x116eec4, 0x04f7067, 0x019d88b, 0x199af36, 0x12c0758, 0x0c417c7, + 0x054c7f1, 0x14c010a, 0x032b37e, 0x062dd49, 0x0d860ba, 0x1c9af76, + 0x12f146f, 0x1239ae6, 0x16e62fc, 0x1dd39a5, 0x079c280 }, + { 0x0b48122, 0x04101f9, 0x123af73, 0x0d60958, 0x08c0491, 0x02442f5, + 0x193727f, 0x03959e0, 0x182c100, 0x1c1c4cb, 0x178942a, 0x0e42ced, + 0x007339e, 0x070d5c1, 0x0a96baa, 0x0965c2f, 0x0a06bc1, 0x0126946, + 0x05ad88c, 0x18b76f0, 0x1606570, 0x0e67735, 0x1b1448d, 0x07d5c84, + 0x1f89f18, 0x1a58d95, 0x1a71989, 0x1c75e78, 0x1e38bc3, 0x02135a8, + 0x0ef82c1, 0x0e7c81c, 0x0dbc58e, 0x12df213, 0x15e2d6f, 0x107f3ba, + 0x12c8f40, 0x0cfbc8a, 0x1fd3e7f, 0x14953c7, 0x0758073 }, + { 0x091ca22, 0x1d82bc3, 0x06d9f49, 0x0c27454, 0x1206bfd, 0x1caa09f, + 0x14e16b1, 0x00fd097, 0x0755366, 0x0e8c515, 0x0389331, 0x1bcf914, + 0x1d2e166, 0x1e23a6d, 0x155d430, 0x10874ad, 0x0c11366, 0x16f7a22, + 0x1d2e10c, 0x08dca79, 0x1783146, 0x1854fec, 0x12f0340, 0x0fdc406, + 0x0c82429, 0x163ded2, 0x1ff5ef9, 0x1a16217, 0x07f3ff3, 0x123b046, + 0x114b485, 0x169fa98, 0x0e52599, 0x0f08203, 0x1e8527a, 0x1bf7573, + 0x0661d32, 0x0153fd4, 0x1aaa24d, 0x0b1f5ec, 0x03f3e34 }, + { 0x11597aa, 0x01ad7ca, 0x13ad47b, 0x1893bec, 0x1677d4a, 0x1a77fad, + 0x136726f, 0x06a04ed, 0x1515a29, 0x11f6524, 0x0ee70d0, 0x0aa7fb3, + 0x1c8a696, 0x16f0f84, 0x07ba77f, 0x0bf31f3, 0x156199e, 0x15c7d14, + 0x14a4b0c, 0x070eb06, 0x081bb76, 0x0e7e207, 0x01cd3b7, 0x08afb2b, + 0x15e9f65, 0x095ec16, 0x18c31e3, 0x11dc647, 0x033d67c, 0x172660a, + 0x0bb9dec, 0x0790629, 0x0d9f807, 0x117b1ab, 0x1788a83, 0x1c883dd, + 0x0c48295, 0x0f0bf6b, 0x053bc7a, 0x1886985, 0x0640d20 }, + { 0x084d513, 0x105c719, 0x14e93a6, 0x0be62a0, 0x074c354, 0x166a950, + 0x1d01d16, 0x16f66dc, 0x01de50d, 0x005ee7e, 0x07f11b6, 0x0fb84a9, + 0x088d9d4, 0x181f83d, 0x0dbbc4c, 0x1a98453, 0x0ca6d4a, 0x1a7230d, + 0x127c6dc, 0x1c6a3bf, 0x0e65ca8, 0x06aba30, 0x02f1025, 0x065a6cf, + 0x02b330f, 0x1745b18, 0x18a15d0, 0x1340e96, 0x0c29c36, 0x1588c3b, + 0x1eb7f94, 0x12257a2, 0x19e4609, 0x1531cf9, 0x1598d26, 0x031dc81, + 0x072e05c, 0x1448156, 0x0a05ae5, 0x15181b2, 0x00f9c1c }, + { 0x1433df3, 0x1d559b3, 0x0a307ae, 0x0e2ba6c, 0x16aa534, 0x1862e65, + 0x083625f, 0x1f22746, 0x165e408, 0x1648c65, 0x1cd145c, 0x10a9aa6, + 0x094b638, 0x05a6e50, 0x04e668c, 0x0264ce6, 0x1300a3b, 0x06792b3, + 0x1822ce2, 0x0c1bf4c, 0x0dfd5ea, 0x183d948, 0x162b5d2, 0x0d29f36, + 0x02789d7, 0x1d8c190, 0x02d98c3, 0x10b27b7, 0x1e3eaf4, 0x1fb8632, + 0x1e0f6d1, 0x07ce4c7, 0x1949c91, 0x17f99b1, 0x1b1b9b9, 0x0137359, + 0x098a824, 0x1ecdd38, 0x1bb14d2, 0x05e8ba6, 0x07e31c1 }, + { 0x1fd2dd7, 0x00eb406, 0x0762f8a, 0x004956c, 0x1efacb0, 0x018fcb8, + 0x0017e51, 0x1797386, 0x0959cb3, 0x10646fd, 0x0ed0199, 0x18619ff, + 0x0dfdd5f, 0x1cb4d08, 0x118c6f9, 0x1fa36f4, 0x09ede13, 0x119b718, + 0x1251c1d, 0x077f5bf, 0x022376b, 0x0eee639, 0x1ea4649, 0x0d89dc3, + 0x10d7315, 0x1a3ba0f, 0x0438acd, 0x1ec9dc8, 0x04d93c4, 0x0969f7e, + 0x0ba1afa, 0x1f89f76, 0x13b7e03, 0x050dde2, 0x13d4cdf, 0x015832d, + 0x1e23ba6, 0x120d183, 0x14d5d37, 0x08a64da, 0x01a219c }, + { 0x04db0bc, 0x1bf7c55, 0x058ff73, 0x0cf6d93, 0x0e23180, 0x050c979, + 0x0419cf6, 0x0e384c7, 0x0ffdc77, 0x0676171, 0x103b6f0, 0x1c6b45f, + 0x03997c8, 0x0166302, 0x1843b06, 0x10240f1, 0x0cb2b0c, 0x17e86f1, + 0x0795fe3, 0x188afed, 0x11c34d6, 0x192da9f, 0x054f9a6, 0x1f13971, + 0x0330ac4, 0x1f32115, 0x065559a, 0x05fe465, 0x1442d19, 0x0816a1b, + 0x00dcf35, 0x17d4d28, 0x04ce590, 0x1833178, 0x0dfbe00, 0x06d582a, + 0x16d0bf9, 0x15e7bbd, 0x064bf80, 0x1337920, 0x017aaa9 }, + { 0x055db2e, 0x0ab21c7, 0x014434f, 0x067728d, 0x035dee4, 0x042317c, + 0x103956e, 0x0f83428, 0x1ea17e2, 0x17f9d9a, 0x17dea69, 0x186dbb2, + 0x0f23f99, 0x1eeb396, 0x05ff766, 0x08b80e4, 0x01edd20, 0x0fa0056, + 0x1fc1ac9, 0x0ab90e9, 0x09be94b, 0x1287252, 0x0291283, 0x076d026, + 0x05e91b4, 0x162f449, 0x04853e5, 0x117dbbc, 0x17fa977, 0x152607c, + 0x19c3d15, 0x14b7fa4, 0x08fd86b, 0x10477d1, 0x163ef9d, 0x1876965, + 0x026474b, 0x0affc61, 0x0c92bef, 0x1e14be7, 0x06b282a }, + { 0x141a595, 0x0012fb1, 0x0a31e3f, 0x0d488bc, 0x191c38d, 0x0234212, + 0x1b8f7ad, 0x066e57a, 0x1755478, 0x1ca3369, 0x185b10f, 0x09a6107, + 0x1491141, 0x0ad3d65, 0x176519a, 0x1f6c828, 0x1098fd2, 0x08816ef, + 0x0ff61ec, 0x165a5a1, 0x10882a2, 0x0e2ca2a, 0x1a7a6f9, 0x0048bbc, + 0x18bf4a8, 0x187771b, 0x02c8c1a, 0x01617ad, 0x1e9f3d8, 0x02e3615, + 0x115da95, 0x0900584, 0x09d167b, 0x096fda1, 0x109cad0, 0x0427cc8, + 0x0e8d976, 0x127a94f, 0x1bafed9, 0x046a8e0, 0x06d4f5d }, + { 0x0ba9f88, 0x0795b00, 0x02fcd72, 0x00f76da, 0x1dc807e, 0x1c0f2df, + 0x1b50ace, 0x03c1424, 0x0a7ac78, 0x1ae7367, 0x172e98c, 0x1cdfe6f, + 0x073e308, 0x11e4b24, 0x0372989, 0x0869a05, 0x17e8818, 0x13975d2, + 0x06de289, 0x07ab3ef, 0x0ea3a9e, 0x0e9783d, 0x14bc29f, 0x1a0bee9, + 0x0467824, 0x15b707f, 0x00045b7, 0x0410a2e, 0x137580b, 0x0f492c7, + 0x0ce70a9, 0x0e80e17, 0x18bd7a5, 0x1bec873, 0x01cae65, 0x08aa3f9, + 0x00db81b, 0x0d49e22, 0x0d2b5bb, 0x09facba, 0x04aaf0b }, + { 0x114c7af, 0x192831a, 0x1ab66fb, 0x1b78303, 0x109e7da, 0x11f62c5, + 0x0ba1e3e, 0x10bde79, 0x1173b86, 0x06dfd5a, 0x14cb776, 0x1f81243, + 0x06b2490, 0x05ece23, 0x1bce1ae, 0x1b7b69d, 0x12fa061, 0x1e0e6ea, + 0x16f0136, 0x1d31344, 0x063664d, 0x15c2b94, 0x01be60d, 0x1c89540, + 0x1a8048b, 0x06388d2, 0x1825c06, 0x0dbdbc9, 0x011fb11, 0x02bbd96, + 0x165cabb, 0x14e43d9, 0x04dade1, 0x1f9d48a, 0x09af5ba, 0x0ff338a, + 0x1c2e14d, 0x0a0b2d8, 0x18cde87, 0x0730578, 0x08b2cbd }, + { 0x052e991, 0x00df945, 0x0bb0a3b, 0x0d9f3a8, 0x0ba202f, 0x1a75228, + 0x144c318, 0x139060f, 0x1c5762b, 0x1e12bd9, 0x10a8b4f, 0x11a290f, + 0x0abd329, 0x118ca44, 0x053c69e, 0x00da594, 0x13b06ba, 0x0e38654, + 0x19017a2, 0x07e967d, 0x0ae79aa, 0x199aef7, 0x13193ba, 0x17e3a99, + 0x1f57803, 0x1fee8aa, 0x151585a, 0x083d816, 0x0e33f60, 0x0073043, + 0x1d48f7e, 0x1e04879, 0x19a79c8, 0x066ac1c, 0x093a1d3, 0x030d850, + 0x0fc5c83, 0x0775764, 0x0d9c088, 0x008fb7c, 0x057e283 }, + { 0x1cdf666, 0x05b4c7d, 0x0749b98, 0x1317d76, 0x1dd06a9, 0x04c21b5, + 0x0b6ea01, 0x11a8089, 0x0522bc8, 0x1b5fbaf, 0x08ec835, 0x1736508, + 0x12655c4, 0x099cc53, 0x103d249, 0x0ec02cb, 0x0b70ca3, 0x13b6a79, + 0x00c3e96, 0x11324a4, 0x0705469, 0x03db02a, 0x05acdfa, 0x1bc365f, + 0x0f73153, 0x182f7cb, 0x12b553b, 0x1d97791, 0x1617b05, 0x0e85549, + 0x1f7aca2, 0x0f97442, 0x0c0fbd5, 0x0516b9d, 0x0d58675, 0x07a1a79, + 0x091d606, 0x1f74ea6, 0x1f69ba2, 0x06ed2df, 0x04f12e0 }, + { 0x1f1a610, 0x1d2110a, 0x0669333, 0x0a6f0ca, 0x004a5c5, 0x01c09a4, + 0x09151ce, 0x054248d, 0x04b284e, 0x10ada42, 0x144c83e, 0x18ca28d, + 0x1a36464, 0x1854507, 0x1aea231, 0x1009df6, 0x0e793c4, 0x13a73e7, + 0x056b85a, 0x09a4597, 0x14dd8c3, 0x0ffce0e, 0x0767b62, 0x004a6e3, + 0x0866d32, 0x02530d0, 0x0a6f591, 0x0b64656, 0x17bab14, 0x1496793, + 0x00be223, 0x1528916, 0x1e69c6e, 0x10f65b9, 0x1aa56d4, 0x043492d, + 0x1858afb, 0x1bc753a, 0x1be46a3, 0x07d624c, 0x083d233 }, + { 0x1b478d7, 0x1994433, 0x1270718, 0x02a145f, 0x01ee1ae, 0x09120dd, + 0x0acc063, 0x12c0b6d, 0x0893cd6, 0x0f8f944, 0x05ea1da, 0x0cc1502, + 0x17159d6, 0x18739eb, 0x0480465, 0x0be15d0, 0x10093f5, 0x12947f7, + 0x01537ec, 0x0f1b71b, 0x1fbbb39, 0x1b7a2ec, 0x15ad0fb, 0x17dc72f, + 0x04bfed5, 0x0d68bef, 0x05afddb, 0x003c1eb, 0x00754ca, 0x14071ea, + 0x1cca2c8, 0x1f1d0dd, 0x0db6122, 0x0f2c347, 0x1abedf4, 0x17044d6, + 0x0f40a55, 0x1a990a9, 0x0588518, 0x07d8b46, 0x07362f1 }, + { 0x1c0c430, 0x1593e39, 0x195de4b, 0x1f4a386, 0x0cc0a65, 0x0ca78dc, + 0x13b3b48, 0x08ea14b, 0x0814b49, 0x04a2b44, 0x1eefd06, 0x103496d, + 0x08bbf0a, 0x1855430, 0x1bd3d63, 0x0f2bc6e, 0x1683987, 0x0ec9b0e, + 0x0ea3435, 0x0219b1c, 0x0455b65, 0x1fdb60d, 0x18f8bf6, 0x19123f2, + 0x1154eae, 0x1b21648, 0x17fd5a3, 0x1d63ce2, 0x0b399e0, 0x0e6b979, + 0x02f9ebe, 0x113e17e, 0x1c39bac, 0x01b4a8f, 0x164a426, 0x11e10c3, + 0x1a0a20a, 0x18b7816, 0x03ab766, 0x07f4718, 0x02f1069 }, + { 0x006ded2, 0x1674886, 0x01ec1e9, 0x1e5fb21, 0x1974842, 0x1b1ad37, + 0x0ff5aa7, 0x04dc8d1, 0x11ed606, 0x05b0c48, 0x1b95201, 0x113e6d3, + 0x011fb2f, 0x0e4b510, 0x0f4444f, 0x0675939, 0x0fe10d6, 0x133acd6, + 0x1ea98a7, 0x14cdf91, 0x028364b, 0x04a3f9c, 0x09a1ab9, 0x139b533, + 0x03a05d5, 0x1b74146, 0x1023a8b, 0x18f5f62, 0x1953c87, 0x0472579, + 0x13c9547, 0x13b553c, 0x153d279, 0x18ca02d, 0x0352b5b, 0x163dfed, + 0x16437cd, 0x1aedeec, 0x0810c9d, 0x1c89fcf, 0x0985f83 }, + { 0x0f45294, 0x01e0b75, 0x1d46258, 0x018496a, 0x1013116, 0x0b5a96b, + 0x08060e7, 0x0809822, 0x0ed9433, 0x03ce781, 0x106da1c, 0x0516e9e, + 0x010c5b0, 0x0e4560f, 0x10fc1da, 0x09e1c7b, 0x0a3f8b2, 0x12d62f7, + 0x0d31708, 0x0d0975c, 0x052aee6, 0x11cd5e2, 0x0949679, 0x1be8b99, + 0x12cd1e9, 0x07d583e, 0x0c6910f, 0x0e03392, 0x0003b30, 0x0d54c96, + 0x0b9a3f7, 0x01b1978, 0x19f179c, 0x00e5396, 0x09bc79e, 0x1377e2b, + 0x10dcc79, 0x0bbceaa, 0x18bc553, 0x0801fd2, 0x00c88e5 }, + { 0x0f44357, 0x18d3574, 0x0daa13d, 0x0c74795, 0x175b4bf, 0x15e3407, + 0x076796b, 0x1e46699, 0x08a753e, 0x1657842, 0x18f23b3, 0x09820eb, + 0x1ae2801, 0x1ba7c69, 0x07568e3, 0x0655d77, 0x064b80e, 0x13acc42, + 0x0af0de4, 0x051cdfe, 0x01977b3, 0x17f7687, 0x1aeec7e, 0x0660cb5, + 0x0ac955a, 0x07433a7, 0x1e48b6f, 0x1833fb1, 0x1b907a8, 0x1742cc3, + 0x15e305e, 0x0767459, 0x1f33627, 0x1bb97c4, 0x0067ea1, 0x0dd75d4, + 0x1a25ced, 0x0ef24c9, 0x01c5539, 0x1715e22, 0x08e2560 }, + { 0x141aba6, 0x1ba3618, 0x1e795b4, 0x1f75659, 0x05a1079, 0x0e93e3a, + 0x0a0c673, 0x01d6c70, 0x09dfd95, 0x111bb19, 0x1023fc8, 0x0b9a752, + 0x181e0b1, 0x188b008, 0x0a00802, 0x1774e93, 0x15da383, 0x0938ced, + 0x14411b5, 0x106814c, 0x1b1f607, 0x0f4ba91, 0x024a753, 0x0145157, + 0x0345c8e, 0x0e3a020, 0x082b7c2, 0x024eb58, 0x11d6116, 0x1932919, + 0x142d06a, 0x0a72394, 0x10cc77c, 0x1118a91, 0x124a3e4, 0x13117c1, + 0x12fd9a2, 0x19ec95c, 0x1cb97fb, 0x0450649, 0x059005f }, + { 0x04c1c74, 0x0ba861e, 0x0de5aec, 0x01d2cdf, 0x1e73aac, 0x02cb9fd, + 0x176499b, 0x16d0b4e, 0x03a8656, 0x04bfc99, 0x11b37a3, 0x0762a08, + 0x1f2b704, 0x1ff9c4b, 0x0245bdc, 0x0e564a9, 0x01cb18b, 0x1489ee8, + 0x0230379, 0x0ea3e29, 0x0a58d0a, 0x0a42ac6, 0x0645d5c, 0x14cc7b4, + 0x1430144, 0x10c4bb8, 0x12c3821, 0x1be3215, 0x1ead9c2, 0x1e0679c, + 0x0840203, 0x02e705b, 0x085ac6e, 0x1519c00, 0x0144c98, 0x1bd2f23, + 0x143bae8, 0x04ac9b5, 0x17dbb91, 0x04daf07, 0x057a78e }, + { 0x0dbddd8, 0x19a37a0, 0x0eb0586, 0x0f28218, 0x0b49a92, 0x03679d9, + 0x09e0c62, 0x1d718a8, 0x033b93d, 0x16f9919, 0x1d5e75c, 0x13ea81b, + 0x009c8d5, 0x01077a8, 0x15e99f7, 0x10c87cb, 0x11867f0, 0x1e2359c, + 0x165ab70, 0x14488b5, 0x04d0ecf, 0x0d8622a, 0x1963d62, 0x1082fae, + 0x09301e0, 0x1447376, 0x0b11538, 0x194bded, 0x0f462d6, 0x0247d60, + 0x0d90644, 0x011b140, 0x12407d8, 0x1adbf42, 0x0e9fdb4, 0x0f698a6, + 0x0f6ada8, 0x08f2094, 0x1cba0c9, 0x18b0388, 0x01ca370 }, + { 0x001b68a, 0x0a8b8d4, 0x02ce52f, 0x19fa333, 0x1312879, 0x0b19013, + 0x0aafd04, 0x1b6920b, 0x0f5b01f, 0x0ff43fa, 0x084a2ed, 0x047539b, + 0x1778de5, 0x03de98f, 0x1c58687, 0x0986a17, 0x1d02390, 0x0daef67, + 0x0623c4b, 0x165105c, 0x0e74224, 0x0efcced, 0x0374a00, 0x19a39a4, + 0x067b508, 0x11ce56a, 0x170219f, 0x1862387, 0x0250726, 0x0b9015a, + 0x00dc684, 0x05dfb20, 0x1bf464e, 0x09d81c1, 0x122876f, 0x14a7a08, + 0x06265ba, 0x0da97a7, 0x0b1e4cb, 0x0989867, 0x02584b3 }, + { 0x0eec688, 0x031c495, 0x148cf2e, 0x148bf7c, 0x05e740b, 0x105afc5, + 0x1c7dff5, 0x07a845c, 0x0487491, 0x0ae8c2e, 0x1f60351, 0x166df42, + 0x0404c2b, 0x1602a29, 0x09c6152, 0x14cae7e, 0x045a8b9, 0x03b6e98, + 0x0bb9f32, 0x0587c2c, 0x07d02e4, 0x0326fb6, 0x000999c, 0x0f96910, + 0x1dd51dc, 0x1f02c93, 0x1861e25, 0x167f557, 0x15737c6, 0x0917796, + 0x1fff9ab, 0x1fea353, 0x1b60269, 0x03dd557, 0x1515a60, 0x15c3906, + 0x151ca49, 0x0edb7fc, 0x0c216b3, 0x0e87f35, 0x07e8113 }, + { 0x10a88b1, 0x11545c1, 0x1f86b5c, 0x119c222, 0x11918ea, 0x04da3ec, + 0x142e010, 0x1a67c05, 0x16c46d1, 0x09c0969, 0x059a72d, 0x1b61cb1, + 0x1e2fd09, 0x0ad866a, 0x1173418, 0x188a730, 0x15a2386, 0x1860e0a, + 0x17fd0f2, 0x0e9bcbe, 0x00cdda7, 0x0c71c8e, 0x0ec1dae, 0x009e50d, + 0x11eff50, 0x1ff4beb, 0x12bbb02, 0x07c168d, 0x01ad942, 0x0333995, + 0x08b914e, 0x072db48, 0x00c9f81, 0x195ff7f, 0x06898f6, 0x02c6ed8, + 0x1a56fa9, 0x0e3c8c5, 0x0169800, 0x0c9bf09, 0x0436b8c }, + { 0x0b764bc, 0x0bf4ec5, 0x1e12204, 0x0940efb, 0x1fa61e9, 0x0c775ee, + 0x1974c30, 0x1b8b4ee, 0x1fc9451, 0x0448b57, 0x08d1e95, 0x1c660e3, + 0x1f01a52, 0x191da0e, 0x0ee577a, 0x1850cc6, 0x0c943c8, 0x06ebeb4, + 0x0365c1a, 0x13a83c3, 0x199de4f, 0x0846493, 0x1e6422e, 0x0e72946, + 0x0148ed4, 0x09ff30a, 0x1f35479, 0x0a030a2, 0x03dcb6e, 0x03af012, + 0x0154180, 0x02f2a88, 0x1dcde62, 0x0d2fff2, 0x03854df, 0x0cdef92, + 0x0768cb6, 0x1bd5720, 0x0578477, 0x13cdb7d, 0x05266ca }, + { 0x186b3db, 0x0f73689, 0x1502137, 0x14f871c, 0x19e4af5, 0x027a4ef, + 0x01103ac, 0x1fb6683, 0x0fde5a4, 0x09c50f4, 0x15f3f08, 0x1248604, + 0x013e6e6, 0x0cfeb86, 0x0671b8c, 0x03fe06a, 0x17486c3, 0x0479a70, + 0x103387a, 0x0531fb2, 0x0d7cf1e, 0x0e8a4b0, 0x1bee32c, 0x05e77fe, + 0x013472b, 0x07f903e, 0x1051bbe, 0x1334416, 0x13e2208, 0x1b15bde, + 0x09df7b0, 0x0c4d7d4, 0x175044e, 0x065b3d4, 0x11253ed, 0x141e656, + 0x1fc6703, 0x1d04900, 0x128af05, 0x17339b0, 0x041f325 }, + { 0x02843a4, 0x16a89e7, 0x0bf0c4b, 0x1c00e51, 0x0748498, 0x032672f, + 0x0a08936, 0x07751de, 0x0a62008, 0x0032382, 0x14ce34d, 0x03b297d, + 0x185905e, 0x031f3d9, 0x15e32d4, 0x0f77254, 0x196289e, 0x0cc13b6, + 0x05edcd0, 0x05b88fe, 0x0944dfe, 0x0f8ed64, 0x1648d48, 0x080154e, + 0x0d28d23, 0x1219edb, 0x1a9d86e, 0x0c8ee0b, 0x1d07ddc, 0x1d36cdf, + 0x1f6251e, 0x0485951, 0x0f2e3ac, 0x01a3400, 0x19c3ae3, 0x1a93de8, + 0x19aa18f, 0x19e9bde, 0x1aa79f6, 0x16dcb19, 0x056b30f }, + { 0x180a428, 0x06e5566, 0x02441fb, 0x190e659, 0x1af922d, 0x0d220fb, + 0x01e60eb, 0x11441b1, 0x0924b00, 0x1f6cd22, 0x0070e8e, 0x067965d, + 0x1321235, 0x12fc03e, 0x13901d5, 0x15d9786, 0x1a51f2f, 0x085fd77, + 0x17a2a23, 0x0c694b5, 0x0a9178b, 0x1c4a1c9, 0x11382df, 0x17639b1, + 0x0237790, 0x0571849, 0x0be1c81, 0x1d5369f, 0x13cd83d, 0x00fac2e, + 0x1e4fb7e, 0x18ca474, 0x0f88c51, 0x06cb4ac, 0x0e2c5f0, 0x0fc8e5f, + 0x1ccf7f0, 0x0840f2e, 0x1451a26, 0x0aeb17b, 0x01353cc }, + { 0x1bf6e18, 0x0b24b9c, 0x071ca29, 0x04c9371, 0x19e8b5a, 0x145c73a, + 0x0d28373, 0x0191b28, 0x1204704, 0x09adfa8, 0x0e3a0b6, 0x02c8d4f, + 0x142ab3a, 0x13fc094, 0x160fb58, 0x0e52fe2, 0x1e072d6, 0x1c20b53, + 0x14e790a, 0x10bb0d9, 0x1bad496, 0x03cac6e, 0x029e5ff, 0x0b9cdbd, + 0x0f92815, 0x11ad2ac, 0x03e28d8, 0x0be9cae, 0x077ae57, 0x07e0294, + 0x0f6f1a7, 0x14d62dd, 0x14193a9, 0x060f8c7, 0x10f2ec7, 0x131a3be, + 0x1a21e78, 0x1d41872, 0x17d61c8, 0x0bbe8a3, 0x03ec218 }, + { 0x10bc2d7, 0x063eb8f, 0x104ae75, 0x18dca3a, 0x0982c6c, 0x0fc07b3, + 0x0b64e82, 0x13925c0, 0x1047ae0, 0x1ee9692, 0x0d47e6d, 0x093e6fe, + 0x1e35031, 0x03bc285, 0x1527387, 0x1a590d3, 0x0cb12f0, 0x0b01215, + 0x0f0a2e7, 0x1118acf, 0x0550ba1, 0x10835e0, 0x0390184, 0x0fa8653, + 0x04b1f8d, 0x0f0586c, 0x1f4e254, 0x094cf5c, 0x097607b, 0x02bdc5e, + 0x1cad49f, 0x0a92f54, 0x093c5f3, 0x0eb335e, 0x0330e6f, 0x06be3bd, + 0x09d447a, 0x03ee2e7, 0x0af94c2, 0x16d4423, 0x089b356 }, + { 0x1dcc837, 0x0d857ef, 0x1ea7b5b, 0x1550e36, 0x0fb80ba, 0x0ea5b90, + 0x0ff2470, 0x0b88275, 0x1adac9e, 0x0dab5fb, 0x195e8fd, 0x05b5170, + 0x0e5664a, 0x0720eca, 0x0c13dc8, 0x06cb023, 0x1263743, 0x131f08e, + 0x109b6ba, 0x051d9de, 0x0dc2ee6, 0x04e58b1, 0x0045867, 0x0c90c86, + 0x1817f87, 0x0434e7a, 0x095612f, 0x03772e0, 0x1f7928e, 0x1e77805, + 0x194b309, 0x1b8c1dd, 0x0f3a80e, 0x0e17ca7, 0x0afa1eb, 0x04fc240, + 0x0a0d4f5, 0x178c704, 0x1449995, 0x01aaf8b, 0x039c4f1 }, + { 0x08aecd3, 0x0db4674, 0x0a76cea, 0x114a315, 0x155b091, 0x0a772a2, + 0x136b52f, 0x109db83, 0x102068d, 0x0db45b3, 0x0b1cb5e, 0x01a1023, + 0x187dac8, 0x140d053, 0x079b4d6, 0x0c506da, 0x1ea3bd1, 0x06420f4, + 0x0531111, 0x182eeb1, 0x1202a7b, 0x12f8d50, 0x1cad8dc, 0x1a98aad, + 0x1767ec7, 0x08ddf63, 0x0f51bfd, 0x102fd76, 0x17e3392, 0x1f46b9f, + 0x113f796, 0x0b5da49, 0x0c6c977, 0x0bce7a2, 0x1c1edb9, 0x1817342, + 0x1069fbc, 0x18b23c4, 0x0ac033f, 0x05a922a, 0x0414b54 }, + { 0x06e173b, 0x18f2c30, 0x04e8cf0, 0x1721cce, 0x1b7f4e1, 0x1d9057a, + 0x0d44b7a, 0x0e084bf, 0x105120e, 0x1c4630b, 0x0f93b31, 0x0c05202, + 0x173ef05, 0x00e3736, 0x074d6b2, 0x0d2153f, 0x08f9450, 0x17098f4, + 0x12bc20b, 0x1f36648, 0x0ea9708, 0x160dd15, 0x0cb9359, 0x01b6539, + 0x14a6e74, 0x003d78f, 0x034610c, 0x0957249, 0x156a6c7, 0x077c76a, + 0x0984cce, 0x04e1a2f, 0x08e623e, 0x07adffa, 0x0bea582, 0x0a78e6c, + 0x044e851, 0x0bbc3a2, 0x02ca90e, 0x0d5c017, 0x052678d }, + { 0x136aeb4, 0x18e2cef, 0x02ad77f, 0x1952578, 0x12d6653, 0x1d2fc0a, + 0x1d25a49, 0x03e1c07, 0x02dfd49, 0x084ea0a, 0x07e26e1, 0x18a54ae, + 0x05258c2, 0x0999a24, 0x1586012, 0x13c1257, 0x14f3f7d, 0x10d19f4, + 0x106fe41, 0x0831a65, 0x095cfab, 0x072d52b, 0x1ce7124, 0x1a5afff, + 0x1196ef6, 0x0548720, 0x143de52, 0x1d9a80e, 0x053b4f3, 0x1cd9698, + 0x1252d63, 0x0bb32e9, 0x0ee842a, 0x17b415c, 0x1076fc8, 0x0c474b3, + 0x08efcea, 0x0d630a6, 0x1bb7411, 0x0b78219, 0x07040ba }, + { 0x15a1a96, 0x127c0a8, 0x1f80b0d, 0x0630864, 0x11a6350, 0x0c9ea79, + 0x199406b, 0x0e61412, 0x1273b61, 0x0bb4a78, 0x16a74a7, 0x10eda59, + 0x178886d, 0x140a60b, 0x0069d08, 0x0d2d63c, 0x16b8667, 0x11a4913, + 0x0c97c01, 0x09e18cb, 0x0c4a2fd, 0x0ffd94a, 0x1949cd2, 0x03a66de, + 0x00d8ade, 0x10760ff, 0x039f8e1, 0x1f3447d, 0x14c31ea, 0x1b90dbb, + 0x12a5f4a, 0x086caf0, 0x0c3e582, 0x07551fd, 0x1d39c3d, 0x11fe5bf, + 0x1e87324, 0x140f0d7, 0x12704f4, 0x1ac17a3, 0x09043a6 }, + { 0x06c7937, 0x0d07f3b, 0x0f8c544, 0x1957787, 0x1b2ded5, 0x0444560, + 0x1833380, 0x1e65582, 0x1616200, 0x143aa5e, 0x0ba81a4, 0x107a694, + 0x0fb801c, 0x0e5f083, 0x15e80ea, 0x19b2915, 0x022cedf, 0x04cb584, + 0x101a620, 0x068c75c, 0x1663c3c, 0x06facbf, 0x1ec4ba9, 0x19255f3, + 0x1383440, 0x0aa1646, 0x193a368, 0x13790b8, 0x0e801a7, 0x0fd16da, + 0x0ca55dc, 0x03c6af3, 0x1d2c138, 0x1683c3d, 0x177ffea, 0x0dc8b8e, + 0x173eac4, 0x1b051e5, 0x17cd6c1, 0x0907424, 0x026362b }, + { 0x0fc3e89, 0x1469477, 0x19c4971, 0x0ed3d3d, 0x0d0ee87, 0x0f25ba9, + 0x0ee1abd, 0x067160f, 0x0cb86b3, 0x1b84839, 0x14aeb36, 0x01d5fea, + 0x09fd3d2, 0x0606d0f, 0x1bacac5, 0x0e28b4b, 0x08a44f9, 0x09c8fb4, + 0x181b521, 0x17a6203, 0x0d4921f, 0x12df54e, 0x11793ca, 0x17e43b4, + 0x0d464a7, 0x038bdb0, 0x0015355, 0x127f119, 0x00f2e91, 0x09e8df7, + 0x1cd6b39, 0x1828724, 0x0c26563, 0x15af749, 0x02ca5b1, 0x15390dc, + 0x09ff59b, 0x17f1188, 0x04d7914, 0x040aab9, 0x02e952b }, + { 0x15f886e, 0x035e56b, 0x1160aa1, 0x1da87bf, 0x068a5db, 0x1d8dc37, + 0x116d801, 0x16a207c, 0x1355ff2, 0x0071764, 0x0fb3256, 0x1e4d44c, + 0x13bc702, 0x0c0f2f1, 0x0d6ce18, 0x040ec50, 0x1ec6c12, 0x0812889, + 0x1ef615b, 0x04dc74f, 0x1cb1a5c, 0x19ceb75, 0x03be0fe, 0x09a5f51, + 0x053f2a4, 0x14bbd55, 0x0d4ec7e, 0x1829de6, 0x159a307, 0x05088ba, + 0x183fd81, 0x16126ef, 0x1cd96b0, 0x1813995, 0x025b6cb, 0x0d4b829, + 0x0b53ef0, 0x054264f, 0x0392c70, 0x02e606f, 0x01236d0 }, + { 0x084373b, 0x00e47e0, 0x1ebb5d2, 0x10c8c12, 0x09ae476, 0x1de1a59, + 0x17e8184, 0x1602601, 0x0934bc2, 0x18938a6, 0x0f9f88d, 0x0c521c5, + 0x0086524, 0x1680840, 0x13eee7f, 0x08aecaa, 0x1384231, 0x1787605, + 0x0c28ca0, 0x15eb286, 0x181765b, 0x1438377, 0x0ef7786, 0x0ea61d2, + 0x0727dba, 0x0e5be96, 0x19d3325, 0x1618bac, 0x18906db, 0x09b2921, + 0x1cecff3, 0x1a28cb1, 0x1881941, 0x1f8748c, 0x1555b25, 0x15cc2de, + 0x0b9ec7e, 0x1e16c2a, 0x0d5b8d4, 0x028c419, 0x002a480 }, + { 0x06ccd38, 0x1691ea8, 0x0a98475, 0x0920b37, 0x029a1c5, 0x0808e29, + 0x0709da7, 0x0fae2f9, 0x0d82893, 0x03f0da3, 0x0d420fa, 0x1777070, + 0x18f5d63, 0x156d612, 0x09ed09e, 0x09a3fe1, 0x0bd9f15, 0x0ccd593, + 0x1b2557f, 0x01ff7f1, 0x1880dec, 0x13a4fe5, 0x1ba55f1, 0x00229bd, + 0x15dee1e, 0x163991c, 0x1cda7d1, 0x1254c96, 0x0b25991, 0x033048f, + 0x1690c11, 0x145d187, 0x02da887, 0x0b68c5f, 0x10970d5, 0x07489c5, + 0x155f75f, 0x1c820a5, 0x1ff80c4, 0x0df1e42, 0x01d8bde }, + { 0x0028924, 0x09cfc51, 0x0e7c0f3, 0x1960dd9, 0x0e54f19, 0x182c233, + 0x0f2df5b, 0x0ed0c57, 0x05a0607, 0x1f0338b, 0x1fb0436, 0x12f5621, + 0x1c9397c, 0x178ddb2, 0x084e099, 0x17471e8, 0x0cba672, 0x120a6f6, + 0x022c179, 0x1a9a87f, 0x14d1594, 0x1d564a6, 0x1e64fd5, 0x162ec70, + 0x02a6abf, 0x0ad3a7e, 0x0edbf19, 0x1032d6b, 0x0d2139d, 0x0e42774, + 0x09b70dd, 0x06c1a74, 0x1b00a02, 0x09dc3dc, 0x0d737ae, 0x1d66dda, + 0x0c83209, 0x12d945e, 0x04f07d5, 0x0878c20, 0x0349c69 }, + { 0x1e6c88a, 0x1ca2226, 0x01fb46c, 0x028e004, 0x15c2c47, 0x015bc06, + 0x1628887, 0x07d6de8, 0x0085099, 0x04fbab2, 0x1c3061d, 0x0af375d, + 0x10400ba, 0x19be387, 0x1d0a4e1, 0x0fd7e5a, 0x0ec2146, 0x1e2d471, + 0x0cdfd14, 0x14ccdca, 0x150a243, 0x03f685e, 0x12647c7, 0x17a3f23, + 0x13e90f4, 0x14d9d3f, 0x097c384, 0x0c113d1, 0x1896359, 0x10bb839, + 0x127434e, 0x04e3055, 0x0f842d5, 0x1e2e14e, 0x0a64205, 0x124232a, + 0x0725576, 0x17993f4, 0x163ea8c, 0x1571385, 0x0056587 }, + { 0x0e4733d, 0x0b1768e, 0x1110021, 0x1731ca2, 0x1faff7c, 0x15a35ca, + 0x0087ea6, 0x026be06, 0x0b61a8c, 0x0a4a62f, 0x0d65da2, 0x006c6d6, + 0x1657c95, 0x1561697, 0x1a1323c, 0x0e07cd7, 0x0d89bd2, 0x1872d9a, + 0x1a1caae, 0x1b231ef, 0x0ee1c4a, 0x0fe2029, 0x10aa27a, 0x1216a3d, + 0x0ee3f31, 0x0a7e165, 0x1dbffc9, 0x11fa286, 0x1e09725, 0x06b4441, + 0x0e1bcf0, 0x01f62a8, 0x1d0a0e9, 0x1570031, 0x192fdb2, 0x198870e, + 0x1f1d0f6, 0x0f8ab29, 0x16f7a05, 0x1db70d9, 0x01b87f2 }, + { 0x10b15b1, 0x095dd95, 0x1de4d5e, 0x0f9cd74, 0x03e4b5a, 0x079bbcd, + 0x1ff6776, 0x1dff759, 0x1c298d1, 0x02a285e, 0x00c7180, 0x0aad88e, + 0x060e3f5, 0x0aeb403, 0x1c3c1ea, 0x0a5840e, 0x0e02d10, 0x0671f42, + 0x0aa3315, 0x00f23cf, 0x03a3b05, 0x19dd191, 0x1358879, 0x0c65320, + 0x1b94d39, 0x0b6c3dc, 0x1dfae01, 0x1bf3968, 0x1ca0cc8, 0x06f476f, + 0x12b890c, 0x12e2541, 0x14bf416, 0x0454c9b, 0x11de221, 0x1d7c7e7, + 0x04a3e59, 0x15c3d8e, 0x0f08ec8, 0x1887d2b, 0x08e0227 }, + { 0x010964d, 0x1115419, 0x1bac003, 0x0bfe0ad, 0x1ccd5df, 0x18f56be, + 0x0e87f6b, 0x1c6042e, 0x067cdca, 0x01419f0, 0x1324334, 0x099717b, + 0x151cc57, 0x19125a7, 0x1b29c50, 0x105310d, 0x03abb3f, 0x1e80730, + 0x106a37a, 0x1d9c361, 0x061db98, 0x121bc61, 0x08a291b, 0x02cbcba, + 0x1dd0da6, 0x071637c, 0x052dfbc, 0x075c713, 0x09f306b, 0x0b59ded, + 0x16ce8f0, 0x0714109, 0x09a26d3, 0x074a82f, 0x064d4e5, 0x18a51cb, + 0x0ea206b, 0x076588a, 0x175ba12, 0x16a80a8, 0x014b15a }, + { 0x04c59a2, 0x0c364b3, 0x0a943db, 0x02c1faf, 0x1dfe2be, 0x1965c71, + 0x0d5a641, 0x1c067f3, 0x18176a7, 0x19192ec, 0x1c202d7, 0x09ce8b0, + 0x0579a0d, 0x06aea70, 0x1b837bc, 0x051c349, 0x1fac87b, 0x16056cf, + 0x1c26d3b, 0x031a5e7, 0x1d87d6f, 0x1394974, 0x13225ab, 0x128ec79, + 0x0953d60, 0x0fd6544, 0x0063efe, 0x17dd2f5, 0x03d701d, 0x1074a5b, + 0x0bf7c83, 0x08fd4e4, 0x1ba6e30, 0x1ab8fe5, 0x072984a, 0x0b9cafc, + 0x009a55f, 0x0b563b0, 0x078b878, 0x1b18871, 0x0742bbe }, + { 0x1dc2c73, 0x1436e60, 0x0afc8fa, 0x1782c87, 0x0bbbfd5, 0x0c650fa, + 0x1e87c93, 0x18e0ff1, 0x08cb5ca, 0x1345370, 0x19a9f77, 0x0c96a9c, + 0x187d54c, 0x14dbd6b, 0x076e88a, 0x15728f1, 0x140e364, 0x0a6c46a, + 0x1dcb804, 0x05c05a3, 0x0278c8c, 0x0ba3715, 0x1320981, 0x030f8fa, + 0x15bb34b, 0x064f361, 0x1bae3f8, 0x1b167bf, 0x11e415e, 0x1a743e8, + 0x1e6daf0, 0x170cb8f, 0x1908bbf, 0x060be59, 0x139b87b, 0x16e2fa3, + 0x17cdd69, 0x0f19847, 0x1049054, 0x0296b92, 0x097bd5a }, + { 0x1e82861, 0x0317f40, 0x103b807, 0x1bba858, 0x103d4b6, 0x0f48f2b, + 0x1956f99, 0x1bafca5, 0x05abbbf, 0x05a49ba, 0x0917d2e, 0x1ea58e5, + 0x18b4f15, 0x0a8794e, 0x010d6a1, 0x1cebf9d, 0x19b582d, 0x14efbb5, + 0x08322e5, 0x1098bf4, 0x0af452e, 0x0885450, 0x0bddf4b, 0x0c02787, + 0x1bbd8ca, 0x02f81c4, 0x089be0c, 0x01b3737, 0x0c8b9ab, 0x1424067, + 0x063c14f, 0x1ff57b4, 0x163367a, 0x1261526, 0x0f92990, 0x1ca1ea7, + 0x064fba2, 0x0962c64, 0x151a7e2, 0x0629198, 0x0317c6d }, + { 0x0b7d42b, 0x092d816, 0x12b830d, 0x12621f5, 0x15240bc, 0x102047a, + 0x0808bfc, 0x1411aba, 0x1e0c10e, 0x180a017, 0x1ac8f5a, 0x0d14e31, + 0x197fbef, 0x0092950, 0x051ad69, 0x01add40, 0x048110e, 0x0acd7e7, + 0x08b7860, 0x03a4fe0, 0x09dae9a, 0x0b6e1fa, 0x1b6e5b4, 0x17c8010, + 0x0e3f5ef, 0x08e7e0d, 0x07b32f0, 0x13ae0c8, 0x1f8636f, 0x113ca92, + 0x0c12408, 0x184ec78, 0x169796a, 0x031859b, 0x00f0764, 0x0f39869, + 0x0e3d3f1, 0x0b28f87, 0x0e3f514, 0x0733b41, 0x06ae597 }, + { 0x1f4d2ee, 0x09de3df, 0x0f615ec, 0x126162e, 0x0075422, 0x0a49b61, + 0x12f541e, 0x17d6c4a, 0x05efd55, 0x0af9195, 0x10ce247, 0x150a9c1, + 0x04c06f4, 0x0730fca, 0x0b16d66, 0x10f6f9e, 0x01ffd5f, 0x062b243, + 0x08abe93, 0x0c3f62b, 0x0774ee2, 0x1316cbd, 0x0c3fdc8, 0x19e00f5, + 0x1ae22d6, 0x10a0d44, 0x134d1bc, 0x11100a6, 0x16497e2, 0x1dffcbd, + 0x1f23f9c, 0x1f455ff, 0x08595b2, 0x0d39345, 0x1cfbc54, 0x173df39, + 0x0744b82, 0x0772f8f, 0x1f9caa1, 0x11b78c7, 0x0664904 }, + { 0x08b760d, 0x1ddbc0f, 0x0a8246d, 0x104b55b, 0x147b0bd, 0x1a9137e, + 0x0f67fea, 0x11d0292, 0x0bffc14, 0x136e913, 0x0f8f6d2, 0x1f15453, + 0x0b5a032, 0x1a58558, 0x036f1c0, 0x090d063, 0x1b57d65, 0x16e665f, + 0x1160791, 0x0d566f3, 0x0ce2850, 0x1714187, 0x0244da9, 0x0d9018e, + 0x19356cf, 0x143245b, 0x1fbdac7, 0x142ec6e, 0x10f1c9f, 0x0e60c1f, + 0x174b270, 0x02d57db, 0x0f0526d, 0x186f24b, 0x038aa4e, 0x147c1d3, + 0x0f13873, 0x16bd6d0, 0x127b1bc, 0x0b9e7f4, 0x04eb93b }, + { 0x11fae32, 0x0fbf2f0, 0x1d46f62, 0x0b88047, 0x113d74f, 0x0e1fb7e, + 0x0537d24, 0x16e3600, 0x1555279, 0x0c24d2b, 0x0801a07, 0x112e0b7, + 0x0abb9e8, 0x009e516, 0x0889067, 0x0cedf04, 0x085fd33, 0x157dddb, + 0x161e28a, 0x187ea4e, 0x1173931, 0x17f79ea, 0x04abbbf, 0x114d0f0, + 0x05cc8bd, 0x00b0c4d, 0x0f667c3, 0x059ffb6, 0x1d48b68, 0x0a0350c, + 0x182fd59, 0x1d38d89, 0x005e223, 0x020b92b, 0x077a1a0, 0x10a7cf0, + 0x07001cc, 0x1ae485e, 0x0fda337, 0x126f808, 0x02b582d }, + { 0x1abc2ae, 0x12e4140, 0x1b2a845, 0x0bc56d3, 0x073380f, 0x1ffb37d, + 0x0cf481f, 0x00d812f, 0x0547765, 0x0b01c13, 0x1e88717, 0x13e76af, + 0x15dcbac, 0x04c6dee, 0x1d436d3, 0x1e654f0, 0x103d9ef, 0x042f108, + 0x1c47107, 0x1a2e585, 0x0c09cee, 0x124f1a4, 0x0a38e49, 0x03dbbf7, + 0x1936b83, 0x051b8e5, 0x1bd4219, 0x02b87a0, 0x1acfcd9, 0x19e6f49, + 0x0abfa38, 0x167e5ef, 0x1ee10d7, 0x0774d25, 0x0d23adf, 0x1b83b1d, + 0x1a574af, 0x124e71f, 0x0d3013e, 0x0130c5b, 0x0786151 }, + { 0x0e72c21, 0x1fa403d, 0x1694ff8, 0x09fa1e1, 0x031aa14, 0x01d22a3, + 0x187a3e3, 0x1578edd, 0x051b4f1, 0x1cd704a, 0x16ec90d, 0x072faf9, + 0x0d2a3a4, 0x015eafe, 0x0533ffa, 0x1deb4f4, 0x112f427, 0x1ddf276, + 0x0134f33, 0x1487dc5, 0x0e1e9b0, 0x09c7763, 0x15ede2e, 0x171d0f6, + 0x004e467, 0x0100c6a, 0x14d0dd3, 0x1915b80, 0x08deb50, 0x1b02aa1, + 0x13d90dc, 0x1875f45, 0x0d80ec0, 0x0ab7cda, 0x04f0eaa, 0x10daa3f, + 0x04161c6, 0x0d1455c, 0x100967e, 0x16ed793, 0x0540b6b }, + { 0x01d315d, 0x0b9a619, 0x1740138, 0x05b0dc0, 0x0ef5661, 0x1466c0a, + 0x18516ee, 0x135d5f5, 0x1acdc78, 0x1d83d24, 0x1d5c3c7, 0x135ab0e, + 0x1e6a21e, 0x1cde29e, 0x12a0dfa, 0x131d65c, 0x0931d62, 0x0a1b6d9, + 0x08d8bd1, 0x1f78f1d, 0x058543a, 0x0bd55fb, 0x0aa5cf6, 0x1249ac0, + 0x1dabe0c, 0x074ee73, 0x01f2b7c, 0x0d3b31e, 0x020538f, 0x02d0ba8, + 0x0a782d4, 0x088c39a, 0x1b7d1a3, 0x0740c1e, 0x1dd9788, 0x0dc3850, + 0x12dd50f, 0x112c33a, 0x0e230b2, 0x02925c0, 0x0897cab }, + { 0x18bab8a, 0x09c0986, 0x002967b, 0x1948704, 0x011d364, 0x0c0a0ae, + 0x0fcb101, 0x0e80d0f, 0x07ac896, 0x156869d, 0x1046821, 0x020b72e, + 0x1c44928, 0x19c19b8, 0x0612c47, 0x1063ce9, 0x1840d1a, 0x0386976, + 0x1244bf8, 0x06c516d, 0x08d2d88, 0x1d8a7d4, 0x113e3df, 0x015927c, + 0x12a4dcf, 0x1d32b27, 0x0a9b093, 0x05ec535, 0x0cd9498, 0x15d1dfb, + 0x0b6ae41, 0x0414a30, 0x0822e67, 0x1c9d296, 0x16b0c3a, 0x145fe8f, + 0x1ff673a, 0x1162527, 0x03b1771, 0x0c68ed6, 0x064b007 }, + { 0x1c9a404, 0x1a99f59, 0x054878f, 0x076fdf3, 0x11db7f7, 0x129b49d, + 0x0f8a5b0, 0x1a98fe2, 0x00738ee, 0x073fa62, 0x1b2b41f, 0x16679c4, + 0x11ccfd3, 0x00f62e7, 0x1e124d4, 0x09c03b0, 0x09ddc08, 0x19fc7e0, + 0x0e6d6b3, 0x1956658, 0x151c217, 0x1dcf7aa, 0x10b6bc2, 0x042f52a, + 0x16f56e1, 0x0157de3, 0x0b08dc0, 0x002f162, 0x10a2938, 0x01cfd83, + 0x1902d4b, 0x0aed952, 0x1925153, 0x1471b71, 0x1090675, 0x084aab2, + 0x09e50e8, 0x0fdc160, 0x1b630a4, 0x14ccc31, 0x07dd22e }, + { 0x1cbb3bf, 0x14225a4, 0x0c95fff, 0x08aac5f, 0x1e0cc70, 0x0d422d6, + 0x194de7d, 0x1f83cdd, 0x0e51277, 0x0b6bf93, 0x0d5c625, 0x097260c, + 0x142c75d, 0x0b4abf9, 0x085224a, 0x0e85673, 0x13282e5, 0x1467a75, + 0x0c91edc, 0x1a7bbb0, 0x02376b0, 0x19900d2, 0x19ea7d8, 0x029490a, + 0x003c114, 0x08b20b2, 0x1edbdaa, 0x015fa88, 0x06f7906, 0x04986d6, + 0x00a57e5, 0x17a773b, 0x05ff94b, 0x16f87b4, 0x03f1472, 0x12b91f3, + 0x113b748, 0x0ce4455, 0x1f32255, 0x0ccbe31, 0x031377c }, + { 0x1cfb35f, 0x0ef04be, 0x1be0d71, 0x1e03986, 0x0dccca9, 0x1b65b19, + 0x1a175d5, 0x0eafd27, 0x0f7b4b3, 0x016ea45, 0x0866d43, 0x1a9f613, + 0x079d95c, 0x18dff30, 0x0bb4565, 0x1b5a4ea, 0x0cf2596, 0x1a1cc40, + 0x07a429b, 0x1df6a6d, 0x060ae52, 0x1181e9f, 0x11025d9, 0x0a0e1c0, + 0x164faa9, 0x0e97e79, 0x1815893, 0x11f3276, 0x15e467d, 0x0c12006, + 0x092cd6a, 0x0191e8a, 0x089d024, 0x100bcf1, 0x08f1922, 0x1bde8a8, + 0x187edab, 0x0feb4aa, 0x149c4e9, 0x019423c, 0x03dacc5 }, + { 0x099ae4c, 0x127ca32, 0x149f2cf, 0x02e0a78, 0x046dcbe, 0x1c17455, + 0x173a6f9, 0x08b00fe, 0x0d8481e, 0x1632694, 0x01bf42d, 0x0a31545, + 0x09f35e4, 0x0f8e6da, 0x0dee6eb, 0x07d5fef, 0x010aec2, 0x1f9fdb1, + 0x06ff4be, 0x17470b7, 0x13a00a9, 0x09c403f, 0x1946835, 0x0f65085, + 0x04404b1, 0x1853d59, 0x1fe7767, 0x1faaed0, 0x09df646, 0x1eda79f, + 0x137347b, 0x0c1be32, 0x1d2df7a, 0x0ef82ae, 0x0b0f81a, 0x037da7e, + 0x03248a3, 0x0dbab09, 0x113dd1a, 0x1c2d28e, 0x0866949 }, + { 0x14ab07a, 0x106d29f, 0x1efcea6, 0x07ea94d, 0x0cd6f33, 0x1e79481, + 0x1a486c8, 0x0b01925, 0x0848e3d, 0x0ac0e1f, 0x0862af2, 0x1f7ba76, + 0x1793af1, 0x03365a6, 0x1663a84, 0x0074070, 0x14e990c, 0x0a8009c, + 0x1421ded, 0x0c963cf, 0x10913b6, 0x1deba63, 0x15e76c6, 0x05abba1, + 0x144354e, 0x1c14296, 0x0ccca76, 0x1a57083, 0x16d4800, 0x07583dc, + 0x11bea11, 0x1852bb8, 0x1a50569, 0x1f6271b, 0x0dce53d, 0x0f85a70, + 0x1b08317, 0x1c427fa, 0x0966370, 0x171163f, 0x0574352 }, + { 0x15d7ce9, 0x0c9fb86, 0x1abfb48, 0x0c1690f, 0x1c19fd2, 0x132fe81, + 0x0ad65ef, 0x0acf889, 0x078270d, 0x0ced430, 0x1c06637, 0x1801754, + 0x1f8a84e, 0x142cc2e, 0x109f924, 0x051b05d, 0x0f0de20, 0x0ccb665, + 0x0708807, 0x0c918ec, 0x19eb4e7, 0x1e048e0, 0x0a58cd6, 0x1acf057, + 0x03a69f0, 0x049929d, 0x034a519, 0x1e40868, 0x1f68733, 0x10d084c, + 0x0691114, 0x0d32c02, 0x1cbcc09, 0x1d4a72f, 0x1763e14, 0x027109a, + 0x13b6a3a, 0x0c63126, 0x0f13c90, 0x1e40d5c, 0x03e431a }, + { 0x1d381f1, 0x1ec9cc1, 0x0f0fe59, 0x1da1806, 0x16501aa, 0x0083b41, + 0x1d34151, 0x1a77e75, 0x05093a6, 0x0368acc, 0x1ca402a, 0x0e83b25, + 0x1543ae0, 0x1b785ba, 0x0cabe98, 0x0dadffd, 0x0a3aa45, 0x1684853, + 0x1bf6d91, 0x149fb55, 0x0f7d336, 0x020d4a1, 0x1f46ff9, 0x03dc83d, + 0x0a3ed85, 0x0e2bfe1, 0x1847a4d, 0x1e392d0, 0x1bb3434, 0x1b3329d, + 0x0ab355d, 0x15b12d8, 0x06931ba, 0x1fd20f9, 0x0f461ae, 0x03141f7, + 0x0203cef, 0x1ebec15, 0x134d470, 0x02bc4cc, 0x06dad3f }, + { 0x0ec35a1, 0x005be89, 0x04a3465, 0x0dcfbf6, 0x0219c5b, 0x1990eab, + 0x1e31bc4, 0x16c5984, 0x033c58e, 0x13b4825, 0x00f10d7, 0x1eabb32, + 0x1915090, 0x01ecb50, 0x06f249b, 0x1974e0c, 0x1038c0a, 0x1cba54f, + 0x0662c86, 0x028042e, 0x0c6f7a4, 0x0efc4ac, 0x0c1a566, 0x17a0253, + 0x12f1dbe, 0x0e1a8bf, 0x0f7cea3, 0x02134c2, 0x0375c51, 0x0224339, + 0x14c2396, 0x12707a5, 0x0590ba4, 0x1c1be2b, 0x1f182ff, 0x1ff87dc, + 0x07d2d55, 0x1d29c81, 0x1e8ff21, 0x1a8bea2, 0x02438e9 }, + { 0x015af3c, 0x0298444, 0x1b57129, 0x05e7937, 0x055f1a3, 0x1b2eeff, + 0x137265e, 0x16b5de3, 0x012e51e, 0x0e30eca, 0x1c92418, 0x18a9cc7, + 0x11bd0da, 0x0859f11, 0x0510a73, 0x0c020de, 0x1c2f1da, 0x0fb9be1, + 0x0ef13ec, 0x01c096d, 0x01cb715, 0x048df14, 0x0816d32, 0x0e03eb6, + 0x0633cd7, 0x04878da, 0x18a944d, 0x1667de8, 0x11f7f28, 0x1e39b47, + 0x19f76d1, 0x17a82d6, 0x0ada511, 0x0add9fa, 0x1f37fde, 0x0f3a552, + 0x16200e6, 0x145bd94, 0x0380402, 0x0235fc6, 0x013f390 }, + { 0x1d0c827, 0x14b77bd, 0x1d18f74, 0x069453f, 0x106110f, 0x0d28ad2, + 0x0c1a072, 0x0eff0f2, 0x1268bca, 0x146c022, 0x01177f7, 0x0049330, + 0x04cbb83, 0x146072c, 0x0435c41, 0x0c0c47f, 0x0a8263b, 0x19541c6, + 0x0d71742, 0x176bcea, 0x1110293, 0x0aab20a, 0x13baa67, 0x17b400b, + 0x11ad01b, 0x00c7f18, 0x1e93634, 0x092fc17, 0x12b8662, 0x1bd00e7, + 0x02ccf75, 0x1b18975, 0x0075b73, 0x1bde4de, 0x1b51c8a, 0x165308c, + 0x0bda1b0, 0x13e7126, 0x00ed85e, 0x0d6d00e, 0x0458d4b }, + { 0x154d8b2, 0x1510726, 0x0836289, 0x1c9a641, 0x05a5696, 0x0a7b800, + 0x16163e6, 0x150d316, 0x02f6549, 0x1256e1e, 0x134035e, 0x10326d2, + 0x1d1812e, 0x1982015, 0x0e6c001, 0x0c8208d, 0x049a1b3, 0x070850a, + 0x048c088, 0x12bd4b3, 0x00c3eae, 0x0d8da41, 0x0fbf0ba, 0x193d714, + 0x15cb585, 0x0327f2d, 0x065e11c, 0x035c063, 0x07d49f2, 0x05b8479, + 0x1ada3bc, 0x05ee4aa, 0x059ef18, 0x0d80d19, 0x115d893, 0x18015c0, + 0x1668f95, 0x071d832, 0x0fe458a, 0x1f56df7, 0x05f13f5 }, + { 0x09b0dc6, 0x16cd71d, 0x1b21f1b, 0x12df107, 0x0ea1bde, 0x059b3bd, + 0x0fe23aa, 0x157d4cd, 0x09a66e3, 0x17d355e, 0x05fff77, 0x02f6d04, + 0x1cc4d33, 0x1486f82, 0x10723c8, 0x0ce9dee, 0x1177d11, 0x10f87ef, + 0x0d66272, 0x01d9cf8, 0x082dfdf, 0x0fb5ce2, 0x03bb64b, 0x17e394e, + 0x13e6655, 0x0ce39b8, 0x00973b2, 0x0159652, 0x03e69c9, 0x11d1740, + 0x068df27, 0x02ee274, 0x00a3c53, 0x10ba6be, 0x1595bd6, 0x0c6a1b8, + 0x05f802f, 0x112d220, 0x0928845, 0x0bb46f7, 0x0219649 }, + { 0x1142680, 0x197e989, 0x13d0032, 0x0ecba29, 0x0b9e91d, 0x11334f5, + 0x13aaf7f, 0x18b8d41, 0x00ae22b, 0x177e72c, 0x1b0942f, 0x130d96d, + 0x1f3c2b7, 0x0b9c78f, 0x0b6c68b, 0x191d909, 0x028516e, 0x0cb84de, + 0x1a3df6d, 0x1262531, 0x17f9f36, 0x15cad8c, 0x1123bf1, 0x1554809, + 0x109529a, 0x0584ff8, 0x1451055, 0x1879197, 0x1f34352, 0x1de1a13, + 0x104cfbd, 0x1a4312f, 0x0a17940, 0x0a45002, 0x11f5b39, 0x04b5418, + 0x1d56fa6, 0x18e7539, 0x17c20a5, 0x160088e, 0x093ad0e }, + { 0x08a9963, 0x1b4b3cc, 0x0375e82, 0x0eca2bd, 0x01e477f, 0x15a8793, + 0x18e18ed, 0x1bcc4e9, 0x1d33922, 0x1d4dc6a, 0x096cf58, 0x07f6d0f, + 0x033c38d, 0x0981719, 0x1dbc270, 0x1999e31, 0x1c3e02f, 0x192a602, + 0x1b998bd, 0x1da16e4, 0x0079c04, 0x1c0a1ff, 0x075591a, 0x002d918, + 0x09448c9, 0x1cbf7c5, 0x0fe08f5, 0x0ace989, 0x0de451e, 0x1b97de6, + 0x178161b, 0x0882fd5, 0x1fc88d5, 0x12c46e2, 0x08255db, 0x12572a4, + 0x1844d1f, 0x046ea12, 0x100d110, 0x1e1d483, 0x073f8c3 }, + { 0x1f763dd, 0x1a7e42e, 0x00da254, 0x06758e3, 0x1b1427f, 0x078ad01, + 0x0f85dba, 0x11c1b6b, 0x0cb2088, 0x09c84a2, 0x12ba987, 0x135b0af, + 0x137804c, 0x08cfbdf, 0x16110a1, 0x1519f54, 0x0f1293a, 0x0b13776, + 0x08da805, 0x1c1b31d, 0x0dcd749, 0x171990f, 0x1bffdb6, 0x16f2399, + 0x1eea628, 0x1b0cb1e, 0x08b45b8, 0x029c0aa, 0x1ae206a, 0x0c7e58a, + 0x1928b81, 0x1f9464b, 0x1268745, 0x00d4507, 0x101c84d, 0x10f9f3a, + 0x1caa51b, 0x1692ecb, 0x175d77f, 0x0735b7d, 0x00108ae }, + { 0x1e88f63, 0x0bc79d4, 0x0c95534, 0x1d5618e, 0x0a05b11, 0x10ec535, + 0x14f9b89, 0x190ee74, 0x08d0b91, 0x06dbed7, 0x0c01349, 0x00e7d37, + 0x0bde10b, 0x0a71848, 0x02fbf9d, 0x13913f9, 0x1990cc6, 0x10b5782, + 0x1565446, 0x1070073, 0x1afcddc, 0x0ca362e, 0x10fd96e, 0x1c14b33, + 0x04be81e, 0x18bfddf, 0x1becea6, 0x11123c6, 0x1dad008, 0x16baa22, + 0x07c326a, 0x1aa12fc, 0x1fc46ab, 0x0d270ef, 0x026eb21, 0x0710901, + 0x00c4523, 0x05da17d, 0x1077cd2, 0x1b1d627, 0x0807c06 }, + { 0x0ee0ef6, 0x0b4f64c, 0x1ebc02a, 0x07176f6, 0x1a9d548, 0x17c7edd, + 0x1324a80, 0x0f84890, 0x08b7055, 0x1ed900d, 0x146bc9e, 0x07c8c15, + 0x1be5934, 0x0cc64af, 0x0a6a50a, 0x03a76a7, 0x1deda86, 0x14ba6d9, + 0x14e6703, 0x0a4b93d, 0x09bdce1, 0x00fb908, 0x026d5a2, 0x1042349, + 0x17d1599, 0x1ad047f, 0x0bbc3c9, 0x1beed67, 0x0f358b5, 0x007bfd1, + 0x0d24fc6, 0x187360c, 0x0c4ffcf, 0x01da9d5, 0x18985d6, 0x184d258, + 0x155399f, 0x1efd1b5, 0x1e986cb, 0x0d932c0, 0x016424c }, + { 0x12744a9, 0x12e2aee, 0x1061775, 0x05fc75e, 0x0544c1c, 0x1458449, + 0x0ba67bf, 0x0346590, 0x1a9df69, 0x05bd592, 0x0659d0c, 0x0aa137d, + 0x0298384, 0x0579689, 0x1b34963, 0x0e4e579, 0x098bcc7, 0x0445720, + 0x0e3be83, 0x12c2829, 0x112cd43, 0x1cf6b26, 0x113fd9e, 0x0fe6808, + 0x055e42e, 0x0f5d4f3, 0x1516c3a, 0x1a2df88, 0x1ded283, 0x1f0a781, + 0x1711d28, 0x1599970, 0x1c9adff, 0x1d28dd1, 0x0f05c94, 0x027bfcd, + 0x1b5831b, 0x0d7a5cf, 0x11e2b77, 0x00549e8, 0x05544e6 }, + { 0x0a80b4f, 0x02989dd, 0x03be25f, 0x1ec77b9, 0x0122716, 0x0162d40, + 0x10b6ded, 0x1195c4e, 0x1088330, 0x0ecf0f4, 0x106ac7a, 0x187e5a6, + 0x10352c8, 0x16ca2c3, 0x0f41403, 0x1b3b02c, 0x173c290, 0x0c1a4ee, + 0x1db1f4a, 0x078bc03, 0x033c205, 0x0365a10, 0x00c41d1, 0x1a135e3, + 0x08bd209, 0x140bb64, 0x1ac9e51, 0x01ee1cd, 0x11b540d, 0x0cef0cd, + 0x10dc82d, 0x0453296, 0x0b7ecdc, 0x029e7c0, 0x1738b7b, 0x0583499, + 0x1ed60f4, 0x1e9f6e8, 0x1498775, 0x0b9c483, 0x0573599 }, + { 0x0237056, 0x1d1fdd0, 0x0e23712, 0x0867566, 0x0856c16, 0x0f63093, + 0x1aef49c, 0x1d9803d, 0x1e3031b, 0x1ef5819, 0x0287d6a, 0x0832c23, + 0x134eee4, 0x0db0079, 0x125d085, 0x10ee7d8, 0x1cf0886, 0x08db8c2, + 0x106df7f, 0x188d9af, 0x1e897b0, 0x0d25262, 0x1450ecb, 0x03ff29b, + 0x05984bb, 0x032edcd, 0x13273cd, 0x187209c, 0x0e64c9a, 0x0de0756, + 0x06be1ca, 0x0ed15b3, 0x0c22821, 0x0a0612e, 0x02062a5, 0x0f77a76, + 0x049a691, 0x1476af8, 0x17bc391, 0x1be7d88, 0x0885486 }, + { 0x1dff464, 0x01649a5, 0x1145aa5, 0x1e4b4f6, 0x1db2719, 0x0df1921, + 0x01c2cc9, 0x0739960, 0x119fe33, 0x02ad18d, 0x1ba3fc8, 0x15d0483, + 0x0faca69, 0x0af7c6f, 0x01f7421, 0x0e78cec, 0x00f1a1b, 0x04f124b, + 0x074da04, 0x01d144e, 0x06b9bcb, 0x113442f, 0x0a7846a, 0x0bd5c32, + 0x1d0ab18, 0x08e4c5a, 0x103e07e, 0x14172dc, 0x0fc5031, 0x05e7cca, + 0x181343a, 0x1e233ad, 0x1d81697, 0x0670619, 0x0a1eaa9, 0x0e52106, + 0x091ff9d, 0x0ea69f6, 0x058b717, 0x1d1a957, 0x031cecf }, + { 0x08b21e8, 0x1fecd7e, 0x1b7d0de, 0x0763286, 0x05dd32b, 0x0e1b507, + 0x00b5248, 0x121fcb2, 0x1a3d0fa, 0x14ef426, 0x148ef63, 0x0d5ab76, + 0x159663e, 0x1766b4b, 0x00288fe, 0x16b3930, 0x0d9b4fb, 0x08804e0, + 0x07483fc, 0x154f7b9, 0x1a3d839, 0x16f66b7, 0x1d40bd9, 0x0a2d953, + 0x0d4fbc5, 0x1622407, 0x19b1d0a, 0x0bff4be, 0x1252f86, 0x1ca2ff9, + 0x0f4adf1, 0x0ebb396, 0x0fefc05, 0x178e939, 0x18ef5b5, 0x0623610, + 0x1a6a4ec, 0x079e784, 0x11ecd76, 0x0d5b44a, 0x06961b4 }, + { 0x135e2ac, 0x1ac3f65, 0x136741e, 0x16af5e2, 0x1ed5546, 0x1450260, + 0x1e96f6c, 0x1e1d942, 0x0709d54, 0x0fc8ea2, 0x1d003a8, 0x13fb38d, + 0x10a6e71, 0x1dc670c, 0x12e23b7, 0x07fa49c, 0x0dd246e, 0x0fcbc0f, + 0x1956bd7, 0x0241cd6, 0x1ca7d67, 0x0ec9a09, 0x169e0b4, 0x00ff443, + 0x020a297, 0x091b4bf, 0x0953a10, 0x1d6a3e6, 0x051f9f1, 0x06cf1b0, + 0x1a4b895, 0x0e79cb7, 0x1aec42b, 0x1bca7ee, 0x0cbb34f, 0x1313534, + 0x0781aad, 0x1271178, 0x1484865, 0x018a6ea, 0x06a63a9 }, + { 0x17acbbb, 0x0a7001e, 0x0421d95, 0x156e9ec, 0x0c01668, 0x0628cd9, + 0x059c8e2, 0x09fc945, 0x03eb94d, 0x0b33b8a, 0x1b4bd80, 0x19be19a, + 0x1f086a3, 0x1d9b87b, 0x1960085, 0x07cf9f0, 0x0c15a4d, 0x0b2c440, + 0x0e8fd28, 0x1ab02cb, 0x11ddd6e, 0x09ae523, 0x0af31e0, 0x0894aed, + 0x1f074e8, 0x175404d, 0x0dba940, 0x0a75036, 0x021ed3a, 0x0983870, + 0x197082e, 0x10c2fe2, 0x027f892, 0x0e685c6, 0x111a08d, 0x034a8ec, + 0x0255296, 0x044ffec, 0x1643bff, 0x045a2a3, 0x051ed4a }, + { 0x09701b4, 0x14b1d22, 0x0bc8df5, 0x07764f9, 0x0a8d91a, 0x194b2ff, + 0x0f856d5, 0x0fa7df3, 0x1db50bf, 0x0d3d02a, 0x10ee6dd, 0x101d9cc, + 0x1efd674, 0x1675aea, 0x09834b5, 0x1912fe5, 0x00c5ed7, 0x1b47e19, + 0x0339a17, 0x0a79ec5, 0x015e41c, 0x0fb8833, 0x038a5c4, 0x0a01d98, + 0x1213823, 0x1243d43, 0x01b0a7f, 0x1e1524c, 0x0f9712a, 0x1f9570f, + 0x0fe4f7c, 0x1a5a2d3, 0x15f6fb1, 0x0bc9e06, 0x1899d2a, 0x0dd6f5f, + 0x09f4925, 0x19eca57, 0x1739505, 0x1785716, 0x02d6951 }, + { 0x04e222e, 0x03ecfc8, 0x0427740, 0x1f0de9c, 0x133f248, 0x014f771, + 0x13a2e3d, 0x031a932, 0x1cfc775, 0x0ab9a0a, 0x1d0bc4a, 0x1474161, + 0x196e7fe, 0x013a1a8, 0x0572df7, 0x0e3418f, 0x166711e, 0x0c10547, + 0x0e1d3d5, 0x12bb385, 0x162783d, 0x1c73870, 0x152d935, 0x1254e85, + 0x153f58b, 0x136c921, 0x0511ed7, 0x0440916, 0x1931a03, 0x19865e7, + 0x1a02eb5, 0x14f5e44, 0x1c4d089, 0x1c9fcba, 0x1306e0e, 0x1c8c920, + 0x165b3ae, 0x075d010, 0x117c289, 0x0f1c119, 0x065c48e }, + { 0x0222c22, 0x039e76f, 0x0ed0687, 0x1bf9d44, 0x1683d8c, 0x0a1d832, + 0x12c52c8, 0x0ee0603, 0x159fcec, 0x0256fc7, 0x0133bca, 0x1038624, + 0x07fb1c5, 0x0a39a88, 0x134fbba, 0x11181ea, 0x10b4d31, 0x16dfb3f, + 0x03c6344, 0x07e5a22, 0x001376a, 0x1403e9f, 0x0e027e8, 0x1cfd9c0, + 0x10a4625, 0x0977837, 0x16ca257, 0x1050cfd, 0x10553ad, 0x1a44845, + 0x117841b, 0x1de48a8, 0x0280fa6, 0x0d1e5f1, 0x1e16a36, 0x1a805aa, + 0x1438ba2, 0x1eecffe, 0x089bfd8, 0x058f4d6, 0x036b5cd }, + { 0x05679a7, 0x1a7102a, 0x1d421ff, 0x028a418, 0x04d80b4, 0x02ce6c3, + 0x15fea6d, 0x1472146, 0x1c85af1, 0x0cf579c, 0x0d697a8, 0x1af31b2, + 0x0a0d475, 0x1c0d33c, 0x140660d, 0x1d020e8, 0x1790cc2, 0x03a41cb, + 0x1d04891, 0x043a225, 0x1a37c6a, 0x1c9b528, 0x0343a17, 0x14e9bf1, + 0x0151eea, 0x0e27fa8, 0x1e4f3e6, 0x09c3054, 0x0a9ab61, 0x1ef89bb, + 0x1fd1564, 0x0a44713, 0x0f73caf, 0x02f450c, 0x0583dd1, 0x11a4f99, + 0x19a51dc, 0x097a629, 0x0ff601a, 0x089b673, 0x008d7c1 }, + { 0x0cca773, 0x006cb1f, 0x055a027, 0x05a9184, 0x07ea919, 0x15eb20c, + 0x135d36d, 0x1bfe1d9, 0x02a678c, 0x19891ba, 0x01edf9d, 0x1b17a2b, + 0x067a966, 0x1098526, 0x1068405, 0x02f7be7, 0x0385fce, 0x03e6374, + 0x0379ea9, 0x12b7715, 0x08e395e, 0x1ac4c18, 0x0ff87a2, 0x08ed294, + 0x1243ee3, 0x15f80cb, 0x0aec334, 0x07fd388, 0x1b2b49f, 0x093207c, + 0x07ed641, 0x18e6cfa, 0x0385e8b, 0x10a3da6, 0x02bad7b, 0x123a60a, + 0x04004ad, 0x161c3c8, 0x0080a38, 0x1dd756e, 0x05f2aa8 }, + { 0x066524b, 0x06a3209, 0x1d9b882, 0x01a1433, 0x17bf388, 0x08375fd, + 0x1a17b68, 0x08d4b54, 0x1e642dd, 0x134f469, 0x0b93582, 0x18c38d0, + 0x0cef349, 0x07e5a9a, 0x1dbb8ec, 0x0cf704d, 0x12705eb, 0x13ed5d0, + 0x02f817d, 0x1764fc3, 0x05d12ba, 0x1d4716c, 0x0566bf2, 0x1b3a70d, + 0x12d1ae2, 0x03776e7, 0x187a9bc, 0x13b8a5c, 0x0e5ae85, 0x1c5a433, + 0x11f0a09, 0x00579a7, 0x1ff0340, 0x1f417ec, 0x11d9e12, 0x09d1095, + 0x03c9f22, 0x0b24c04, 0x1e5268c, 0x13168df, 0x062501a }, + { 0x1264086, 0x1becd56, 0x12f558f, 0x174bc1c, 0x0a6a33d, 0x069eb3e, + 0x0c00a32, 0x033d04a, 0x046e64b, 0x1446d64, 0x0914da8, 0x032e415, + 0x0cfa3c9, 0x16aa9f5, 0x0c326c3, 0x157a702, 0x0e02ea8, 0x1b11403, + 0x1b33f9d, 0x17ea9b9, 0x1b7052f, 0x18a7868, 0x0f66a38, 0x1362e83, + 0x12133d5, 0x14528ce, 0x1269bfa, 0x1ae8203, 0x04eb10f, 0x1bd05ae, + 0x17b46b3, 0x123f3b4, 0x0499b73, 0x152c33c, 0x1127037, 0x1557549, + 0x01f3531, 0x0e2fb9d, 0x1199732, 0x1fdfa7f, 0x0497b15 }, + { 0x05568e9, 0x165d57a, 0x09be295, 0x1d8e325, 0x1491a0f, 0x1929cd7, + 0x0f74e6a, 0x153b760, 0x04ac37d, 0x032917c, 0x03d6d32, 0x1744054, + 0x1f8c8cd, 0x114e29c, 0x027f1d6, 0x1e05d02, 0x131ca90, 0x1ce6836, + 0x1885b6f, 0x03e0887, 0x1d918f3, 0x165d1f5, 0x066a9a2, 0x1800fe9, + 0x0d0d242, 0x1e71540, 0x1e1aa6d, 0x1b1bff7, 0x108edcd, 0x1f426b1, + 0x1290174, 0x00d0025, 0x0fa33fe, 0x10838ed, 0x144fb7a, 0x0d85dd7, + 0x0ff637e, 0x173f2e1, 0x132dede, 0x0d93ca2, 0x018d46a }, + { 0x18b7802, 0x05d9153, 0x0bd21a3, 0x0492f97, 0x0745ddb, 0x17456e8, + 0x0bcf90a, 0x1c989d6, 0x0b4ceb4, 0x0055e6d, 0x17f502b, 0x064b464, + 0x052e0d8, 0x09d639a, 0x1f815c4, 0x0e372d9, 0x188b141, 0x1ba03d3, + 0x169e94a, 0x160c06d, 0x16ac70e, 0x1cec28b, 0x0ac2cdb, 0x052a9e7, + 0x09d297c, 0x0d68a08, 0x03735c1, 0x0e1bd39, 0x15e7513, 0x1ae6bdd, + 0x030fc36, 0x140dce1, 0x1f93d41, 0x18286a2, 0x1e29fa4, 0x1221aa9, + 0x1a38fef, 0x137c722, 0x0b901a7, 0x003a7ec, 0x0550446 }, + { 0x0cb9cc9, 0x0e48803, 0x0053471, 0x0e83a00, 0x142074d, 0x11b7dc2, + 0x198f844, 0x104f9b0, 0x029ad5f, 0x0b90fff, 0x07f20ce, 0x17f452a, + 0x0f1d21f, 0x00068a2, 0x1781b9d, 0x05cd639, 0x16b9179, 0x148212c, + 0x06b5459, 0x0b91ca5, 0x1e98336, 0x02cd777, 0x188883a, 0x1855dc7, + 0x1318970, 0x05e5e5a, 0x0e7fc40, 0x0ef947b, 0x12973f4, 0x00bb7a9, + 0x06c9c1d, 0x13457a0, 0x12118ac, 0x1cfc9d0, 0x0824f75, 0x17e684a, + 0x06f5d7d, 0x1d47fbe, 0x1b13d58, 0x1f9af61, 0x00da313 }, + { 0x1aa2557, 0x12d460a, 0x1a70dc4, 0x1801127, 0x0a21d70, 0x1c5411e, + 0x0e6519e, 0x05490e2, 0x07cb004, 0x09f4d3a, 0x0b38603, 0x09ff93c, + 0x022d2bf, 0x024d756, 0x14c6834, 0x00cc1aa, 0x016f03d, 0x02694d3, + 0x1c6dfc0, 0x1aa1ac3, 0x050c473, 0x1de51ef, 0x0ebc3b2, 0x1851e4e, + 0x19bea09, 0x132714a, 0x03e1c11, 0x1af85d4, 0x1083ef6, 0x1270b98, + 0x152b7eb, 0x128384a, 0x0940c26, 0x11681a8, 0x1042845, 0x1c882ce, + 0x1e82290, 0x01186c0, 0x12b3188, 0x1d1b682, 0x063630b }, + { 0x07d2e41, 0x0a91145, 0x01e6fe3, 0x07d6c5f, 0x09e7582, 0x0016c4a, + 0x0cf75b1, 0x15a369a, 0x0de2c59, 0x01f026b, 0x0770e22, 0x11e8937, + 0x0cbf3f3, 0x1a5b862, 0x065f462, 0x1408b3b, 0x00c13ce, 0x08fb4d9, + 0x038981b, 0x1ae04ab, 0x1b79ca3, 0x1b930e8, 0x0f53f65, 0x0286df4, + 0x0afa85a, 0x003ab57, 0x02ed10f, 0x0d367d3, 0x18f6be3, 0x0c3672a, + 0x027f394, 0x1f1591f, 0x10cd478, 0x0d53975, 0x1cdf579, 0x00d00e9, + 0x08544eb, 0x0c22e03, 0x023b4a5, 0x0e3e2cd, 0x0306a98 }, + { 0x14ec136, 0x08f4eb1, 0x163ef11, 0x141cdec, 0x1edf27c, 0x0da0900, + 0x0054b03, 0x0cf537c, 0x0c5bfee, 0x1db7790, 0x15808e1, 0x0471345, + 0x1935283, 0x03d7dc4, 0x1959363, 0x185bcc1, 0x1c00ac9, 0x1a57915, + 0x0aa748a, 0x0dec630, 0x101b28e, 0x00fa993, 0x101d71c, 0x00ebf23, + 0x018f882, 0x088fb6a, 0x146faa9, 0x13f4c51, 0x12a13df, 0x1d0bb73, + 0x0715479, 0x0efe980, 0x106215b, 0x0eac449, 0x1cc64f2, 0x08e3574, + 0x18e57cd, 0x01f5f02, 0x0f8dd91, 0x083d020, 0x02833ac }, + { 0x1a5ec5c, 0x125c346, 0x0c91f95, 0x103811b, 0x0c3d9da, 0x0bd3945, + 0x07c2e31, 0x1853af8, 0x19d343d, 0x08957f3, 0x180ce4d, 0x099ffb8, + 0x01b438e, 0x0e7d0ca, 0x1689c03, 0x00892fa, 0x1f82732, 0x16af991, + 0x0e4f1b9, 0x0f4b1c2, 0x04311b8, 0x08825d5, 0x1b2da2f, 0x04569af, + 0x01c5a47, 0x1d5604e, 0x1c81ad7, 0x085f552, 0x16327ef, 0x1e6b4cb, + 0x1678772, 0x010ef0f, 0x15ba9e4, 0x000c8b2, 0x1d5f797, 0x117ab38, + 0x0bcf353, 0x1810768, 0x18c0d9c, 0x0a9493a, 0x0120cd4 }, + { 0x0b0f9ee, 0x0dc7a65, 0x03bbaff, 0x00599cb, 0x1c003ef, 0x068332d, + 0x1a1056a, 0x0e936d4, 0x09b9577, 0x01769d3, 0x06ad719, 0x0fe08e4, + 0x133de48, 0x10d2786, 0x0bfce00, 0x1bb9bde, 0x15829db, 0x15e8b7a, + 0x1a4f7fc, 0x00b6961, 0x0ec12ef, 0x0905e4d, 0x1787ea8, 0x0cff525, + 0x0e2c2d4, 0x11a336d, 0x117accf, 0x0b1b5ec, 0x0103cb7, 0x0cfb478, + 0x0c299eb, 0x137c048, 0x11f693a, 0x02a5e0a, 0x125bad0, 0x1daad30, + 0x1019336, 0x18b3bf3, 0x1a8fa3b, 0x02cffbd, 0x0021cfd }, + { 0x15c36f3, 0x1b8afef, 0x095171c, 0x0fac95a, 0x103bde3, 0x07bb89b, + 0x03443cb, 0x190aa6d, 0x10f3993, 0x12f63db, 0x0b93287, 0x0eec609, + 0x0bfdb16, 0x1e9dd8c, 0x03dc5f8, 0x07ab41b, 0x13f6634, 0x0a93383, + 0x158022d, 0x16a5de2, 0x070ffae, 0x1c91252, 0x0e5eb57, 0x0556a35, + 0x0e391ed, 0x01657c3, 0x1e65d0c, 0x1818fca, 0x0ae28ad, 0x140bfe8, + 0x073223e, 0x17f1dab, 0x07c22df, 0x145db40, 0x08c7ac4, 0x06bbdb8, + 0x020595a, 0x16e6ce5, 0x1de39c7, 0x08d8e79, 0x007265b }, + { 0x166232f, 0x0ccf85e, 0x1c59cf7, 0x138804e, 0x059aaf8, 0x0307e26, + 0x1b7e96e, 0x0775f04, 0x07a943f, 0x1cf5455, 0x110a348, 0x1634a47, + 0x1a0e0e1, 0x14b9dca, 0x1a838e9, 0x0ea76ab, 0x0aa2557, 0x1f51cce, + 0x1a55ec7, 0x1bee5e0, 0x0302f8a, 0x009de9a, 0x00e27cd, 0x148752e, + 0x127d0f8, 0x0b7999f, 0x02b6bde, 0x1b38181, 0x012aa2c, 0x124da4e, + 0x1a5b732, 0x0f4158d, 0x188deee, 0x004076e, 0x1d74191, 0x1b1e8ea, + 0x0cc2f4b, 0x0eb33e8, 0x125b1ba, 0x09663a2, 0x036c575 }, + { 0x123d84b, 0x0023779, 0x113e448, 0x04fcf13, 0x0699112, 0x0dc02ad, + 0x0bd3a48, 0x09c961d, 0x0807997, 0x19cc225, 0x1e31e58, 0x0cd4e81, + 0x09c9054, 0x06b6f7a, 0x06343df, 0x1c97438, 0x06b4b23, 0x0a94bed, + 0x1060031, 0x13bfe78, 0x07771c0, 0x0d9bf7b, 0x1b1241d, 0x0a27bda, + 0x03a4050, 0x182d4a6, 0x05ac2c5, 0x1ace85d, 0x0af5ae3, 0x024a624, + 0x17b01e1, 0x192b045, 0x0c01532, 0x06ca7a0, 0x1797059, 0x0b45bb5, + 0x02975eb, 0x054564d, 0x0513bf2, 0x0c2328d, 0x006fbf8 }, + { 0x145aa97, 0x099c71f, 0x1facb59, 0x103a081, 0x183b58c, 0x0f7c5ce, + 0x1d66c3f, 0x0f80bfd, 0x0e4d741, 0x1f5838d, 0x08688de, 0x03eb661, + 0x03982b6, 0x1db2de8, 0x17ca8ab, 0x0d7e698, 0x09d5cbf, 0x0f2055e, + 0x01984a9, 0x1864dbe, 0x0e28422, 0x0ecab8d, 0x124879a, 0x1a6869d, + 0x0b10b23, 0x099be44, 0x1e7681e, 0x0da5d2a, 0x19cf4d9, 0x03509b0, + 0x0860cf5, 0x1b2bddf, 0x1d19653, 0x147876c, 0x104680f, 0x0254fb0, + 0x04bb5ab, 0x1214a98, 0x0a7a979, 0x1fa3e1f, 0x05e9ca0 }, + { 0x17c5dc4, 0x0a2b88c, 0x16896f5, 0x1fcf152, 0x02da40b, 0x0d87597, + 0x07bf3ff, 0x0f8cbf7, 0x00d1746, 0x0a96e16, 0x031a8fa, 0x18f78eb, + 0x1ac1fc9, 0x0a01a54, 0x1e558b3, 0x096adf8, 0x1be61f6, 0x19371b7, + 0x1a11ca2, 0x18973c3, 0x0c8a6ad, 0x09d47cd, 0x1fc597f, 0x1c7c026, + 0x13a4503, 0x071bde4, 0x0d9591e, 0x1598aa2, 0x0ddc77e, 0x0b8b832, + 0x0534ce4, 0x0ed26d2, 0x1b318dc, 0x012533a, 0x071cd89, 0x08d363e, + 0x09955f3, 0x01022da, 0x1abe233, 0x1678d06, 0x0940622 }, + { 0x1997973, 0x0665b86, 0x04551c4, 0x1ba7f1e, 0x1b29625, 0x0bd5ea9, + 0x113556e, 0x14b19e1, 0x0673e14, 0x1190f05, 0x18891b1, 0x1f3a7a4, + 0x110541a, 0x17e41d8, 0x1b61d51, 0x0a549bc, 0x1a8f016, 0x123f4be, + 0x16600ad, 0x05674d5, 0x04b20f8, 0x1ad74e2, 0x1a6a901, 0x1a57eee, + 0x15de2ce, 0x06d579f, 0x0925e90, 0x1de3d51, 0x03ba9c1, 0x03041e1, + 0x120b83e, 0x1e32145, 0x0a998a4, 0x119b46c, 0x12333f7, 0x03c5693, + 0x1de6bd7, 0x1a4c125, 0x1b6dae7, 0x0c8f0b7, 0x080bb16 }, + { 0x1145cb5, 0x0baff7e, 0x020c179, 0x0358bcd, 0x155ee56, 0x09d9398, + 0x1c33e1e, 0x0708c3c, 0x0133b23, 0x18aa9ef, 0x1ee81e7, 0x0187454, + 0x1a2fb9e, 0x1f38437, 0x0ff5aa0, 0x1972787, 0x1008bb4, 0x0db5d42, + 0x1be0b6f, 0x0daf12e, 0x09ff0b6, 0x1b2a75a, 0x1f569bf, 0x0416644, + 0x1d2371f, 0x06e66b2, 0x09538a7, 0x13d4938, 0x118ff97, 0x0cb1e58, + 0x02d925d, 0x198b000, 0x09598dd, 0x03bce4b, 0x0460443, 0x0b2a20f, + 0x03b85a3, 0x1e0aa43, 0x08d43b7, 0x1d48242, 0x0077ba5 }, + { 0x1d86f61, 0x11c69e6, 0x02ac2ce, 0x0a0a054, 0x0312144, 0x1681392, + 0x1b71601, 0x01e3225, 0x08a32f1, 0x0ee0fcc, 0x031d800, 0x03a21d0, + 0x13bb1d3, 0x1a32745, 0x1bb1f97, 0x093dda8, 0x1369abf, 0x1eab4d7, + 0x136b79d, 0x10dd4e5, 0x19209d2, 0x06a2d6a, 0x0af9c08, 0x1335cfe, + 0x1236e62, 0x003d5f2, 0x174fd57, 0x1262f37, 0x150e80c, 0x0cad291, + 0x01a04e2, 0x15fe0eb, 0x101265c, 0x1cb2984, 0x06cbd1c, 0x02b6790, + 0x1bc77d2, 0x1bac0ec, 0x08b8aeb, 0x1be8b23, 0x06b2006 }, + { 0x05b1bc1, 0x128544b, 0x13f6cbf, 0x152c576, 0x131f536, 0x073fccc, + 0x034cc00, 0x0bdaae3, 0x153d512, 0x0394792, 0x0972be1, 0x0309a42, + 0x1e4f8a6, 0x1abfb3c, 0x1c69c04, 0x180b4a9, 0x00c1531, 0x0b854fa, + 0x1ea2ddd, 0x01972ed, 0x0ce910d, 0x0f4ee09, 0x0d1dbd0, 0x0abf129, + 0x17a7527, 0x0d22e46, 0x01895d0, 0x0d825c2, 0x17b16cd, 0x17dc648, + 0x08098a9, 0x071ad61, 0x0d116e6, 0x1c74192, 0x0300cb0, 0x19092a8, + 0x06868af, 0x0dc88e3, 0x0d54215, 0x14d7a4d, 0x053217e }, + { 0x19f52b4, 0x0023992, 0x11b3f21, 0x17cc422, 0x168da9c, 0x05e9374, + 0x0e17b2b, 0x0892c9d, 0x1e4a543, 0x1bed516, 0x093fdea, 0x1090703, + 0x0f6dc3b, 0x00e40af, 0x1ea5acd, 0x163c340, 0x1e8c3d4, 0x0627d74, + 0x0b3a7aa, 0x071a3c8, 0x052f0f9, 0x061ae60, 0x09c9f6b, 0x140de0f, + 0x001c9e9, 0x0d0e40f, 0x0d29b59, 0x13c11b9, 0x04a9a6a, 0x08b9b02, + 0x16fe38b, 0x1e57a52, 0x1893dd0, 0x00d894c, 0x0de7e5e, 0x05411a6, + 0x01830ac, 0x1eb000b, 0x0fbbd92, 0x03db35b, 0x0038693 }, + { 0x09885a5, 0x1d5d9e8, 0x0c1f435, 0x0fc6ab7, 0x0d9d2b6, 0x175d76f, + 0x0e33d4d, 0x1ac7784, 0x0699ce4, 0x0e5173c, 0x1653358, 0x088e222, + 0x12354ff, 0x0198b56, 0x12f9c24, 0x1eb88ab, 0x1fd49ff, 0x020c33c, + 0x1e71b10, 0x159aea1, 0x121a75b, 0x0414b93, 0x19dfb72, 0x1dea05e, + 0x16887e5, 0x107412c, 0x1efcc83, 0x0b3d26c, 0x1dccb24, 0x1b77c5d, + 0x0f60738, 0x16ecd0c, 0x1a097fc, 0x036dc0d, 0x075b563, 0x179a744, + 0x14a8748, 0x04b3e6d, 0x0708039, 0x0922a08, 0x02caaf7 }, + { 0x0d20424, 0x0c00337, 0x151513e, 0x06448e2, 0x13e4ea2, 0x0d46435, + 0x14695e0, 0x0164d1d, 0x17ae5b7, 0x06855ba, 0x14e6092, 0x06406ad, + 0x046ca8b, 0x16f98fd, 0x1a39a04, 0x1b9e539, 0x032d925, 0x15c84e9, + 0x159c8f7, 0x191ef1e, 0x16f9302, 0x14d5d64, 0x045c975, 0x1a342e0, + 0x047ca57, 0x1f3b2b5, 0x070628a, 0x176baa2, 0x10d9d96, 0x02f8d6a, + 0x062d5b9, 0x0e160aa, 0x0e886e2, 0x07fc89b, 0x1cf4276, 0x1d8f8e3, + 0x1350361, 0x10ddf14, 0x0ef6196, 0x0648bfc, 0x086d7f5 }, + { 0x0bf719a, 0x0b75b58, 0x044e67c, 0x111787b, 0x1697509, 0x0680da5, + 0x039489b, 0x039f5ca, 0x090898d, 0x1f1d62a, 0x1b199b4, 0x13b710f, + 0x184da3b, 0x1df522d, 0x0c01913, 0x160b0b0, 0x1d98355, 0x19b4f9d, + 0x1e6f304, 0x047350a, 0x18110fb, 0x1cb715e, 0x13d6d14, 0x0331fa4, + 0x13baf24, 0x08e803f, 0x0e20df5, 0x114cedb, 0x075b166, 0x1531757, + 0x0f1a3bb, 0x07b6c10, 0x1fe5f94, 0x1b62d2f, 0x143df60, 0x0aa5929, + 0x0bc1ff8, 0x061e37e, 0x0d37569, 0x1c70d81, 0x0682a55 }, + { 0x07495aa, 0x11ad22c, 0x117723c, 0x18698e4, 0x0276026, 0x0d23719, + 0x03316dd, 0x1cfad5c, 0x1ecc3e5, 0x0869cb2, 0x0598a62, 0x085e285, + 0x071b133, 0x0543b91, 0x0649f9a, 0x14d1791, 0x07e2324, 0x10aa1f9, + 0x0737086, 0x08ed089, 0x10ac6c4, 0x078a296, 0x06f1ff5, 0x09608b9, + 0x10a31ff, 0x1089661, 0x0214bdd, 0x02ba8d4, 0x1dd7a64, 0x1829637, + 0x046b5cd, 0x0f698f9, 0x0ecc3ab, 0x06b866e, 0x006dda2, 0x0ba59be, + 0x040d390, 0x0792a17, 0x1373415, 0x14dfdfc, 0x002227f }, + { 0x151948b, 0x0f7ecdb, 0x0974601, 0x0dfbfa4, 0x0efeed4, 0x1645914, + 0x038253c, 0x1cb9625, 0x196f7c5, 0x088485f, 0x0fb2827, 0x0089699, + 0x040959d, 0x0704658, 0x12557e6, 0x09f9c43, 0x19d68fa, 0x15e0f93, + 0x1c42ba6, 0x03c29c0, 0x07f4b02, 0x0fc408b, 0x19345ba, 0x193e34a, + 0x1c22ebb, 0x1757ad2, 0x1f8d083, 0x1e6e2db, 0x04e8435, 0x1c8aeae, + 0x0065c7a, 0x051ff75, 0x0fc55fc, 0x1babc32, 0x1535f74, 0x00684fc, + 0x15ebc7d, 0x1735310, 0x05de111, 0x134524d, 0x0547e24 }, + { 0x1ffda27, 0x1434550, 0x1d411c1, 0x18f2ab9, 0x14e6cdc, 0x11f9ec5, + 0x1478429, 0x015eca2, 0x09de5e7, 0x1a093f5, 0x10a08d6, 0x1375f26, + 0x113d2c0, 0x1517bea, 0x126760e, 0x1804a31, 0x11dddee, 0x15062dd, + 0x0f73c73, 0x1bbf080, 0x1eda7ff, 0x14b0b7e, 0x195f934, 0x06543e1, + 0x1656979, 0x071e922, 0x00c6475, 0x08ebc1d, 0x00218b7, 0x1f50e11, + 0x014d1e6, 0x117964a, 0x0eb5c90, 0x099737e, 0x13a8f18, 0x1638d0b, + 0x1fe6c1e, 0x16e3a2d, 0x03bab10, 0x181a561, 0x045a41c }, + { 0x1bbf0e1, 0x0d963a6, 0x1c38faa, 0x1f42f9e, 0x01ff962, 0x15a6332, + 0x09d617b, 0x0fdb83d, 0x0a9beb1, 0x1aa0969, 0x15d0693, 0x1ea5450, + 0x1f2c9e4, 0x0c27e88, 0x17df692, 0x0309d27, 0x1dc0df3, 0x0d957de, + 0x10878dd, 0x047a4a4, 0x181e963, 0x1224efb, 0x121ef87, 0x0b137d5, + 0x001ed3d, 0x16e8a2b, 0x14a3ffd, 0x1e17b37, 0x0f298c0, 0x0cea450, + 0x110b4c9, 0x1b11cd2, 0x02d7a77, 0x0157b1b, 0x1adadab, 0x0550980, + 0x1087da0, 0x028564e, 0x10322ea, 0x19285dc, 0x0128763 }, + { 0x0bac178, 0x00783d6, 0x1db8a6a, 0x0869611, 0x1cc2004, 0x1f6f693, + 0x07451c3, 0x0cfd2c6, 0x1866157, 0x108aed1, 0x021522c, 0x0b89961, + 0x037c75f, 0x0d17470, 0x0a7484e, 0x02ea4b6, 0x0668b88, 0x07f4fed, + 0x0779faf, 0x1b1b118, 0x01233f1, 0x0f0190c, 0x0d1d959, 0x1932be7, + 0x05561b1, 0x18d839b, 0x02c4fad, 0x02c1963, 0x13a0eb2, 0x1289ccd, + 0x1d1fa36, 0x1641f9a, 0x08ca1f9, 0x136b92f, 0x019ed04, 0x1ed4fc0, + 0x08bb637, 0x01025bb, 0x1d3487a, 0x199f89e, 0x075e96b }, + { 0x119716e, 0x08fee06, 0x1494627, 0x10f8708, 0x1f58505, 0x0c3e956, + 0x11b47aa, 0x01ec950, 0x16c0715, 0x15b5fc1, 0x1f56dc4, 0x1a8c9ad, + 0x1f91d85, 0x07a9faa, 0x1e220d9, 0x1225352, 0x1d88150, 0x030041d, + 0x0a1dbd2, 0x0e4d07d, 0x0489a76, 0x1d60ad9, 0x1a02cb9, 0x1a3b325, + 0x0f8d242, 0x0494c2f, 0x073cf79, 0x18af605, 0x0876279, 0x1c1e58a, + 0x01ff80b, 0x115cb6d, 0x0ba4fe4, 0x1c0cb57, 0x026d75a, 0x1b150de, + 0x016e523, 0x07ab35d, 0x0252762, 0x135744d, 0x0309a6e }, + { 0x1fbe97a, 0x1f7285e, 0x1137bc9, 0x1f718a1, 0x1a5fe70, 0x104fae0, + 0x1ac05ff, 0x18b98f7, 0x1bed36c, 0x1d0ad42, 0x03b4ea3, 0x19b6eaa, + 0x01c0c3a, 0x15c8434, 0x007be1f, 0x0b9978b, 0x162c49d, 0x050ad99, + 0x1e8993a, 0x162e283, 0x0e880fb, 0x07c70f7, 0x099fe36, 0x1856c7a, + 0x0cfd621, 0x17ee98e, 0x154ef9f, 0x049b7cf, 0x0a358a9, 0x03bfed9, + 0x10750ba, 0x0ebad15, 0x19673c7, 0x1f52ae7, 0x03f5c53, 0x05c6b2f, + 0x1769b20, 0x19b329a, 0x0de27ba, 0x115aeb2, 0x0045825 }, + { 0x042dbdf, 0x18d3a50, 0x1e8977d, 0x0eaef3b, 0x0d40585, 0x17332b9, + 0x12e9c34, 0x05c1ccd, 0x1ca2e89, 0x02eb3a2, 0x19ad7ca, 0x1bde1e1, + 0x03f56a8, 0x1183b3e, 0x1ba1476, 0x0d739c1, 0x0584334, 0x14c602b, + 0x1acf1d0, 0x1f9c4da, 0x1e00b35, 0x1f9cbbb, 0x102256f, 0x16db10d, + 0x0f6a6e7, 0x025c1e4, 0x0d3c0a4, 0x1dc2908, 0x04ec34b, 0x08ad974, + 0x045fdd2, 0x12da213, 0x0af663c, 0x1d6605d, 0x1d5f907, 0x1200970, + 0x0f86c02, 0x1c4072b, 0x1cd628a, 0x1c12b6e, 0x053f4a3 }, + { 0x1fc48e7, 0x1846744, 0x0bac46e, 0x0f5f56b, 0x1a60c57, 0x00e5ad5, + 0x12fe283, 0x16de0d7, 0x079757c, 0x0977d75, 0x064581f, 0x0162ec6, + 0x09e26d9, 0x15bbdbd, 0x0a86ad8, 0x1e57e85, 0x0cd285d, 0x01c7760, + 0x0ea3dfc, 0x128febe, 0x15b5d35, 0x077e0e5, 0x05f2370, 0x0b08b9f, + 0x0cca0c4, 0x1797f5c, 0x0492789, 0x0dd1b31, 0x1ed89a1, 0x0736a41, + 0x1cdf099, 0x0a3b220, 0x1a3f145, 0x14cf809, 0x18b8c17, 0x070a02a, + 0x0908d56, 0x1cc6ba3, 0x148daab, 0x0a7ae47, 0x00a99e6 }, + { 0x1bc0559, 0x1b7a355, 0x05808d4, 0x1735434, 0x0163067, 0x0b40dae, + 0x148a430, 0x00e453f, 0x11378e9, 0x092a5f0, 0x04e8b58, 0x0af556f, + 0x1bc60ff, 0x0332a96, 0x1cb7e2d, 0x0146d4d, 0x0938c17, 0x14d698c, + 0x06dd366, 0x1b357c5, 0x0523c5c, 0x19fbc24, 0x13dd1c9, 0x01c60c7, + 0x0a93a0d, 0x1ec6093, 0x0d09238, 0x1c4043c, 0x03ddfaf, 0x01f7419, + 0x19f65cd, 0x0664c73, 0x1768775, 0x12aa44f, 0x10c5d4c, 0x152ca1f, + 0x1eebf7e, 0x0aede89, 0x12f02d6, 0x08a021f, 0x03a95cb }, + { 0x1d7ff2e, 0x134659c, 0x123e553, 0x1783ab8, 0x0dd1cb4, 0x14a1c54, + 0x0b1ddc5, 0x19c0552, 0x091cad8, 0x0b2e058, 0x142349e, 0x1156659, + 0x1a0c579, 0x134815e, 0x16f0f0e, 0x1a43034, 0x1255186, 0x1aa2e84, + 0x09f9936, 0x0ef9b7a, 0x12daf00, 0x1246684, 0x0055f2a, 0x0a65566, + 0x1a3a024, 0x1d19517, 0x0d0732a, 0x0bf6c73, 0x04aee6a, 0x16e0a3a, + 0x16805c0, 0x19b7527, 0x05bb436, 0x1c278a4, 0x1d98ca5, 0x0726b2f, + 0x1ad672c, 0x189e0ee, 0x1c91575, 0x05c0616, 0x0366d22 }, + { 0x13ea5b2, 0x1a43aab, 0x1137542, 0x17521b4, 0x0fce401, 0x0d01880, + 0x1e995e8, 0x0c0f6a7, 0x1cf1144, 0x1154052, 0x02fd25c, 0x1e0b4a7, + 0x010b8eb, 0x0995669, 0x050451f, 0x1a0fb5c, 0x12c7b5a, 0x1b34938, + 0x1d23281, 0x0bfdce7, 0x18d86dc, 0x0c95c53, 0x063b452, 0x05e2eb3, + 0x13145dd, 0x1c72745, 0x057e5c6, 0x06811bc, 0x11b3684, 0x136ed6f, + 0x1f8157a, 0x1cb2656, 0x1b76e73, 0x049fea5, 0x054f4c2, 0x148850e, + 0x0661bfd, 0x1ee6690, 0x1f4945c, 0x132f3bd, 0x09072ba }, + { 0x020ea39, 0x0f26ecb, 0x1ba11d3, 0x1f90639, 0x1bf1649, 0x1d4e21f, + 0x02ec734, 0x1aa161d, 0x13f3df1, 0x11c1437, 0x1b26cda, 0x05671e1, + 0x034ed07, 0x194e04f, 0x193261d, 0x044854d, 0x0c68ad1, 0x1751f45, + 0x0f7e96e, 0x01c457f, 0x15926ae, 0x07d8507, 0x1585c7b, 0x10e3f1a, + 0x0886d6b, 0x1ed19d9, 0x04d7846, 0x16337d5, 0x0f153f6, 0x0d203f8, + 0x1b93605, 0x0fad805, 0x0608d97, 0x047a33f, 0x0f66daa, 0x08fd1e4, + 0x039d165, 0x164b292, 0x1b0a49a, 0x17a6aa8, 0x08d92c6 }, + { 0x1eb0ff7, 0x06be755, 0x0be2cf8, 0x087c1c8, 0x1be3525, 0x00424cf, + 0x0c89b7a, 0x186afa3, 0x11cd44b, 0x167170f, 0x13fb867, 0x1b7886b, + 0x1c1245a, 0x1c9fac0, 0x13ba103, 0x1728f0e, 0x19cbda0, 0x148b53b, + 0x095eb82, 0x1902b5f, 0x01b0abc, 0x16f8531, 0x05eb7b0, 0x1f217b9, + 0x0502b81, 0x11edf35, 0x054ef79, 0x097f3bc, 0x084c255, 0x0d5fbc4, + 0x1c2a23f, 0x19776a8, 0x0aa52b1, 0x09f7a98, 0x05b0a41, 0x15f00a7, + 0x0dd827e, 0x01ec4c4, 0x1970235, 0x02eb835, 0x04e4bec }, + { 0x0c09676, 0x041d17e, 0x0a52fe1, 0x1e33d53, 0x057c4a3, 0x0152eea, + 0x0bbcf5c, 0x1b14d0a, 0x0843fe7, 0x1c8afe9, 0x0d45639, 0x15302dc, + 0x10644bb, 0x0f6ba37, 0x06e5742, 0x1e16b1a, 0x181b90a, 0x123b822, + 0x13f44d7, 0x0978d7a, 0x13a50bd, 0x13da741, 0x09b7381, 0x0ad5343, + 0x08f30ff, 0x1ff1607, 0x03b0b18, 0x1390100, 0x1508a8a, 0x1052cc7, + 0x0e91270, 0x0652502, 0x0b94cb3, 0x140d101, 0x14a3b1f, 0x0ec8fc7, + 0x1487767, 0x133e8d5, 0x1b491cb, 0x1eadf3b, 0x07a4aa3 }, + { 0x07a0045, 0x178dd71, 0x0d41567, 0x1f64859, 0x1c812d4, 0x07c6926, + 0x1e390e7, 0x0a84748, 0x19b3f9c, 0x1aa27e2, 0x087f3e5, 0x02655ff, + 0x1b5ac68, 0x1a51641, 0x1e3fb80, 0x0976ee9, 0x00fcd3f, 0x14b6632, + 0x0144ba9, 0x1b9d3b6, 0x181e775, 0x0ee6e71, 0x19f7286, 0x1a7fcaa, + 0x0b3f3a9, 0x1a7e0f7, 0x0868649, 0x11c17e8, 0x169b123, 0x17da146, + 0x1e05664, 0x13fa13b, 0x0fcebde, 0x15aefa4, 0x093ed06, 0x0bb93bf, + 0x00a269c, 0x1ebee46, 0x0b78432, 0x0f7efe1, 0x060282a }, + { 0x0eea2e7, 0x1f29c6e, 0x1875f01, 0x1078840, 0x18a322c, 0x0fb28b1, + 0x0a3e53c, 0x020ced0, 0x1c7776a, 0x10db4fd, 0x1ad017c, 0x082f6bc, + 0x02c63a3, 0x08d3db2, 0x067c962, 0x0288099, 0x0a82cad, 0x09c3496, + 0x021a6f3, 0x105ffc0, 0x066af1e, 0x070b7f2, 0x10c2dc5, 0x0032271, + 0x142f919, 0x1572fdb, 0x003e945, 0x1202cda, 0x073a43e, 0x1bd66c6, + 0x1c95543, 0x1f78b86, 0x16a407d, 0x01cf696, 0x14e5a33, 0x01c8f4e, + 0x0a5fbe7, 0x09436ca, 0x0e508ff, 0x18e478d, 0x05f4ae9 }, + { 0x1f4d561, 0x116ed29, 0x064b65a, 0x002db43, 0x086d45d, 0x0a58289, + 0x007eff7, 0x1d48934, 0x19f2195, 0x0a44506, 0x1986cc9, 0x161546e, + 0x02c4151, 0x1cf2f70, 0x0311c7b, 0x1102f73, 0x06ea865, 0x1525e54, + 0x09a3f02, 0x15b70ef, 0x06a9bbc, 0x04b5b9b, 0x022cd19, 0x0cc385b, + 0x098d415, 0x1061977, 0x1b24050, 0x0b67698, 0x0752aff, 0x139a979, + 0x07288d4, 0x0a21c9b, 0x164ce73, 0x0554017, 0x1c9ab29, 0x072734f, + 0x001aa50, 0x09f148a, 0x0bf4a73, 0x047b88d, 0x092a014 }, + { 0x02f7dbd, 0x125f08e, 0x1feba7c, 0x1f6faa4, 0x1a8c900, 0x0478946, + 0x096ee19, 0x0832c7c, 0x0481419, 0x15b89f1, 0x1d5bee6, 0x1a02f4c, + 0x1de87f7, 0x02c6c85, 0x1376178, 0x0d57a4e, 0x07a8256, 0x0c11ff7, + 0x1090065, 0x0461aee, 0x046e9f6, 0x16565af, 0x0115e7c, 0x14990fc, + 0x0626316, 0x02b9511, 0x0f666c2, 0x1943348, 0x08789e9, 0x15d1f24, + 0x0f61b70, 0x1280d87, 0x160b5b9, 0x04abf7c, 0x0a2e258, 0x16de588, + 0x161c515, 0x1a43830, 0x12e6e41, 0x03d5511, 0x00fc8fe }, + { 0x0b90f2d, 0x10df6ff, 0x1565a2b, 0x1949162, 0x1393bb3, 0x074b1af, + 0x0be73d9, 0x18457cc, 0x0f8be75, 0x0a61208, 0x1dd4a4d, 0x0e06bcd, + 0x11bd7ea, 0x0b16559, 0x1921a38, 0x1e7ff84, 0x070c860, 0x1589c8f, + 0x16260df, 0x0cf8ea3, 0x0941df3, 0x1a15f99, 0x18542da, 0x182631f, + 0x0f46e78, 0x0b04af4, 0x0e8b12c, 0x167e3b5, 0x1afbf32, 0x1ae7380, + 0x1171b33, 0x0bd10e9, 0x0d27530, 0x16e5f1d, 0x1945771, 0x1a7250b, + 0x199892d, 0x0aa6c36, 0x1e27cf2, 0x0c5bfa6, 0x02d0ba8 }, + { 0x072e1af, 0x0c7745a, 0x0f33ab3, 0x1d6ed57, 0x0b354ea, 0x0c9fdef, + 0x02fe343, 0x00d36a4, 0x1fe6fc7, 0x066b06b, 0x18bce7f, 0x1bbd49d, + 0x1ea9353, 0x0d40f28, 0x0c2497a, 0x0ceeebd, 0x1a1d136, 0x0f719a6, + 0x14d535a, 0x05193fa, 0x0d54c1d, 0x0ac952f, 0x0e5dc5d, 0x1ee1b03, + 0x0367fb7, 0x13d2e9f, 0x0aa4ceb, 0x17cfdd9, 0x1cfbb77, 0x18fcf11, + 0x0049933, 0x11292ed, 0x1129f4a, 0x111ad86, 0x169026d, 0x14e0a6e, + 0x08a376d, 0x1b263aa, 0x16ff333, 0x0249a83, 0x0963c87 }, + { 0x036a814, 0x14865ef, 0x0ad6eb8, 0x0ae6762, 0x1bdb019, 0x1ff070c, + 0x1619fdd, 0x1d41d75, 0x129720c, 0x13e8cfe, 0x07b1c82, 0x0ca3205, + 0x1e434d7, 0x1da8c88, 0x1abfc5e, 0x0fec10a, 0x19ad80a, 0x168512e, + 0x0123041, 0x150d5ff, 0x149cffc, 0x1ca1d6b, 0x14fa2f7, 0x1cd2d76, + 0x00284e3, 0x10afdcf, 0x0bbbb90, 0x1d6cc61, 0x0f3c633, 0x1dcf176, + 0x102763e, 0x09c0181, 0x1da4ffa, 0x1df5638, 0x1965755, 0x1f652d7, + 0x08cec7e, 0x08fdd6d, 0x15ef45d, 0x079feab, 0x02d03eb }, + { 0x0f2ec1d, 0x1492f82, 0x1b8bac5, 0x0c1a28f, 0x0878f27, 0x0cecf05, + 0x1d812ab, 0x0b6885b, 0x13f7103, 0x08efa25, 0x05756e2, 0x0567197, + 0x03c2827, 0x0f74769, 0x053bed5, 0x1e7c6de, 0x00f13b0, 0x179e223, + 0x0f5ccd7, 0x1f37aed, 0x1a6e889, 0x18fbaad, 0x0227b9d, 0x04336d9, + 0x184feed, 0x008b134, 0x1fb0bb9, 0x1a898e6, 0x0fcd372, 0x02d131f, + 0x1aee50e, 0x0cc6f04, 0x109321b, 0x15bd3ec, 0x09e4fb9, 0x0f849f1, + 0x07cf61b, 0x0546925, 0x0b3668f, 0x1838a97, 0x0842e40 }, + { 0x061d843, 0x1476b53, 0x0335689, 0x149eb66, 0x02328cc, 0x08f0bb8, + 0x1fb444c, 0x0ce2dcd, 0x0c66959, 0x086f65a, 0x0b8a01a, 0x17ecaf6, + 0x10bdac5, 0x0f7f216, 0x1fe0b28, 0x1945f04, 0x00aca5f, 0x162aa76, + 0x1791541, 0x04ed83b, 0x1513ac5, 0x047183b, 0x0dfd32c, 0x10f2f99, + 0x16d9acc, 0x1694657, 0x10364cc, 0x0b2c902, 0x1a409fd, 0x114b942, + 0x04f31ab, 0x0c447a1, 0x173c2a5, 0x07e04bb, 0x1ab144a, 0x185aa4c, + 0x1c31fe6, 0x0b5be5d, 0x04ca296, 0x1359592, 0x00e6331 }, + { 0x0360ac2, 0x097d6f8, 0x016ad73, 0x1c50bcc, 0x06b660d, 0x0dcd8a4, + 0x13c4389, 0x0a9058d, 0x1aa9ac5, 0x0afd1c6, 0x101c3a7, 0x0370a4d, + 0x0d3dfcf, 0x1fe6629, 0x1e6a5ac, 0x18fea06, 0x0290bfc, 0x0f1b2ce, + 0x074f9a8, 0x147b6ad, 0x02d55b1, 0x1acdbda, 0x0d054a2, 0x045400d, + 0x1efa49c, 0x1db49a6, 0x026d338, 0x01e7003, 0x0baf329, 0x1e0259d, + 0x18ac1ce, 0x1ff0713, 0x1a5a222, 0x0d1ad93, 0x1547fe9, 0x0416f53, + 0x08e1a7c, 0x1cf6779, 0x1c16924, 0x14430e4, 0x088839d }, + { 0x01ce29a, 0x1361838, 0x15415ad, 0x0cb1303, 0x1acaf12, 0x0fcf909, + 0x1f03041, 0x027a9b5, 0x0373e3d, 0x172b8f3, 0x1b8f2bf, 0x190df45, + 0x1ae7269, 0x0e901c2, 0x132992b, 0x1d359eb, 0x1573000, 0x190bf93, + 0x19c9cfb, 0x09b68e1, 0x0776c93, 0x1b9aadb, 0x10a53d3, 0x180a300, + 0x036b96f, 0x0858fd5, 0x0ec1486, 0x1f1163b, 0x0aef528, 0x0dc874f, + 0x040d5e4, 0x1b6d037, 0x17fb2eb, 0x0e1b4f9, 0x1475105, 0x1273a14, + 0x1d2e21c, 0x0ce6538, 0x0309bf1, 0x1fd43ea, 0x064128c }, + { 0x0f5b0b5, 0x13c5174, 0x0167c0d, 0x19a681e, 0x1c7e249, 0x053e762, + 0x011064f, 0x1308288, 0x0bc83af, 0x1ae51a3, 0x02eec01, 0x0067f55, + 0x17f39f0, 0x19c1187, 0x063c3b7, 0x1e68a7a, 0x00cd448, 0x0bc6ff8, + 0x146a91d, 0x045181a, 0x08d1849, 0x0418649, 0x175389c, 0x0259fa7, + 0x1a6868f, 0x1036335, 0x0e22ce8, 0x122093b, 0x0dae010, 0x082c80b, + 0x1f76197, 0x1c4a7c6, 0x199e905, 0x0c38da2, 0x0309f3a, 0x1c6459e, + 0x174a132, 0x07aa6d0, 0x12f6805, 0x0137b57, 0x093634a }, + { 0x1a2e304, 0x13593d4, 0x04918a0, 0x0d83498, 0x057e186, 0x1c0b886, + 0x0e0c888, 0x1fd2275, 0x1a9847c, 0x14db5c2, 0x1d1bf5f, 0x19e256b, + 0x0d29655, 0x001c733, 0x0555cae, 0x0bd56e5, 0x0016fa9, 0x0f265d3, + 0x077b6a0, 0x0220e37, 0x161ebbc, 0x0d1f8e7, 0x05fc002, 0x07c19f7, + 0x0777b37, 0x11da9b9, 0x1344e75, 0x005f213, 0x07d78e3, 0x196d27c, + 0x18c7b59, 0x168090e, 0x02077a3, 0x011591b, 0x0cb6773, 0x0f88118, + 0x06deeee, 0x062df91, 0x0d5f92d, 0x0cf780c, 0x0266cb4 }, + { 0x16363e8, 0x120aa5a, 0x136dbea, 0x1078354, 0x0b4fd07, 0x0f32cba, + 0x03778ae, 0x108286b, 0x0fa004b, 0x19a571f, 0x0446996, 0x05d9e33, + 0x18cf44b, 0x129b5fb, 0x12aa0ce, 0x1b92aab, 0x0b98870, 0x0b0370f, + 0x07cd447, 0x0650fa1, 0x1364e3c, 0x15ceae7, 0x1a2cbd3, 0x157193c, + 0x0e89263, 0x108e0aa, 0x1b0daad, 0x0a91051, 0x17d1201, 0x1fe5d0d, + 0x15c24ca, 0x0a62b71, 0x0e7b5bc, 0x19d60bf, 0x0347dd1, 0x06f05fa, + 0x1c8f2af, 0x1814d41, 0x13b86f2, 0x036a48a, 0x04b1d5a }, + { 0x1d52c0c, 0x128ba31, 0x06744bf, 0x1c31181, 0x1735525, 0x071cab1, + 0x0558cd8, 0x086b8c4, 0x0acfa5a, 0x059f8e5, 0x1a041e2, 0x1414f2f, + 0x0a90123, 0x18af040, 0x0c7dad6, 0x1b5b574, 0x012fca3, 0x06bef2f, + 0x17d4472, 0x0e6c361, 0x1d4e328, 0x0a32bab, 0x1f32003, 0x00fd922, + 0x10f3d52, 0x0718840, 0x04c3ba8, 0x1a9cade, 0x05a2ec0, 0x17099f5, + 0x142efdf, 0x17cd577, 0x1c07762, 0x1fb0cb7, 0x1738482, 0x159063f, + 0x1622d42, 0x1a1cfd5, 0x12c9f81, 0x07ea11c, 0x08186b9 }, + { 0x1312867, 0x0e8aa04, 0x16d3186, 0x0b7f5ef, 0x1e042c0, 0x0faeed3, + 0x059a07d, 0x105839e, 0x1a4fc3d, 0x055282b, 0x02e3f94, 0x1acb9cd, + 0x04ed30e, 0x1f5a6b2, 0x0c0702e, 0x0092fd9, 0x044831c, 0x03daee2, + 0x0df66c7, 0x1cd4013, 0x1c91351, 0x1ceca3b, 0x12ee18e, 0x1a82214, + 0x0589105, 0x1bd55d3, 0x110d602, 0x0010d9e, 0x1e357e3, 0x003b485, + 0x13ac4e7, 0x04f6a42, 0x0bfff1a, 0x1d5ab89, 0x1b5c8b0, 0x14f39f8, + 0x134a9bf, 0x01ef2bf, 0x0aca91d, 0x12f93dc, 0x00bf97e }, + { 0x1a19e96, 0x027646e, 0x1a2e5bb, 0x14d860d, 0x14ce18e, 0x1b48c52, + 0x184ad97, 0x132fd06, 0x10d9a0d, 0x1637b45, 0x1730246, 0x0f48c5f, + 0x1398a69, 0x0ade1f0, 0x13897c6, 0x12e60cb, 0x0dab393, 0x10c4b76, + 0x0bc4a01, 0x10341e6, 0x07df9eb, 0x170e96e, 0x14f5d05, 0x08e6b33, + 0x07976ad, 0x01cf116, 0x0a7d7bd, 0x1bc6f53, 0x09d94e3, 0x0055cf3, + 0x121adeb, 0x0153a17, 0x0bfa9e0, 0x1789073, 0x1c3559d, 0x1eaed50, + 0x1eaac23, 0x0c8dda7, 0x0aaecef, 0x0587c81, 0x08fe548 }, + { 0x09a4d1e, 0x133e167, 0x00e216b, 0x069e3a4, 0x0c3eb80, 0x0830c92, + 0x03ce897, 0x038b8d9, 0x1308fb4, 0x01ef056, 0x10a53a0, 0x0b79ce3, + 0x1a9961f, 0x1817586, 0x1881e37, 0x1d16db8, 0x115b64a, 0x1e43f7a, + 0x02d3463, 0x0f3e3ca, 0x1f43696, 0x10a90cc, 0x1170026, 0x0c814bf, + 0x084be0f, 0x0b353ea, 0x048f6ad, 0x1923176, 0x075d2c4, 0x08a6321, + 0x15a99f0, 0x195a5bd, 0x1a913b9, 0x1ae46ca, 0x062dad2, 0x0c313da, + 0x142d3bf, 0x15b1035, 0x0f0fd2b, 0x0d37791, 0x03928c6 }, + { 0x0cb4b64, 0x1f5256d, 0x0687792, 0x09e4c2f, 0x03f62a4, 0x0889520, + 0x12539ea, 0x03de755, 0x1d36f33, 0x02247de, 0x0e17124, 0x057880f, + 0x1b42604, 0x1090dbb, 0x1629658, 0x1d308b5, 0x04f67ce, 0x098b3a5, + 0x18ecbc3, 0x1d177c9, 0x10eb7fa, 0x0ed3e49, 0x1a077db, 0x0b3a1a8, + 0x0fa98c2, 0x0fed6f7, 0x1afa870, 0x1629b3c, 0x1405d11, 0x0e4590e, + 0x150eeab, 0x0e7124e, 0x01dff93, 0x0e6f278, 0x0cfbc1c, 0x130386b, + 0x1150d0d, 0x026970c, 0x0d3d85c, 0x11e6aa2, 0x06ccc88 }, + { 0x0d7504c, 0x1b7873d, 0x1777e34, 0x1fef2b3, 0x1ca3265, 0x0f33d55, + 0x07b7bfb, 0x05e1b9a, 0x0baebf3, 0x13b7a67, 0x1b73f04, 0x0dcc029, + 0x176825a, 0x0cd6c75, 0x0306a0a, 0x19c3c17, 0x0a909b8, 0x1189012, + 0x12f4d46, 0x1fb3173, 0x08becb8, 0x1c7d58f, 0x092104d, 0x0e7959f, + 0x10f5d39, 0x12a0bf6, 0x1096754, 0x02fc290, 0x191393a, 0x1c21ba5, + 0x1a54f56, 0x0359479, 0x1792b21, 0x07c0ac7, 0x0443230, 0x1a06bfe, + 0x0d4ed7b, 0x1d31abd, 0x0bbe5ab, 0x10164df, 0x02f1519 }, + { 0x1d2d439, 0x118ed14, 0x0554321, 0x0578073, 0x121fbbc, 0x02dbad8, + 0x05e49b0, 0x1d87cb5, 0x0b6ce47, 0x0b67a60, 0x031961b, 0x0ecf3b1, + 0x17baaa1, 0x199aad0, 0x076e79f, 0x0b50a06, 0x1d80aef, 0x1c1c0f1, + 0x168c6f7, 0x1b65202, 0x1d7dc71, 0x1a4a4c7, 0x18e3dad, 0x17dddec, + 0x1f3f913, 0x1d9a276, 0x07d2ad9, 0x0c2e64e, 0x02df11e, 0x16387e9, + 0x048e880, 0x040b89d, 0x1be0389, 0x1cc907b, 0x0216a3a, 0x1438432, + 0x1eb54aa, 0x002e745, 0x03595b2, 0x16e158b, 0x0354b05 }, + { 0x09170e9, 0x0f11b3d, 0x0335c5c, 0x1a995aa, 0x01eec42, 0x0ee67d8, + 0x0093cf3, 0x035ff7d, 0x1a66cae, 0x19f4671, 0x11f4069, 0x14ff2cb, + 0x1eb7138, 0x0e1ecb8, 0x01638fd, 0x14e5600, 0x0c32ff0, 0x1a92c8d, + 0x0ef39db, 0x1f6b797, 0x1a18a32, 0x1c54fc0, 0x1cc906a, 0x14d0c61, + 0x13332ec, 0x09df98e, 0x11120bc, 0x08f5f3f, 0x081be28, 0x110bd23, + 0x1e5865b, 0x1cabdf9, 0x138f932, 0x06382cc, 0x12e1c2b, 0x047cfb5, + 0x0f09fac, 0x0df449e, 0x08e8750, 0x1895c6a, 0x048dc55 }, + { 0x1092193, 0x11c1352, 0x1c32398, 0x04d1312, 0x046ec36, 0x04f5a0f, + 0x15abc97, 0x08a5e26, 0x083c7d2, 0x0bc0320, 0x0038e10, 0x1ecf2fa, + 0x1c982de, 0x12890a8, 0x0badb9e, 0x110d270, 0x0778af5, 0x10aa708, + 0x09473c0, 0x00e0eb1, 0x1c58187, 0x1bb8989, 0x137aea7, 0x02ab209, + 0x1b973ba, 0x19d2eb3, 0x0c7435e, 0x0a393e9, 0x0af2cd8, 0x0eb8c5c, + 0x18867ca, 0x130d71a, 0x194ccff, 0x1ce19e5, 0x092ee4e, 0x110e4bc, + 0x06e38c6, 0x0e7262b, 0x1008501, 0x1ba16db, 0x05f6a8e }, + { 0x19a8690, 0x02652c7, 0x101e0dc, 0x0c5eed4, 0x1f36976, 0x1008141, + 0x0b631a4, 0x19ff782, 0x0bce3a4, 0x06ac78b, 0x0ac9b53, 0x0c94095, + 0x0878046, 0x07522bd, 0x173eee9, 0x12f2800, 0x1b3b8a5, 0x0a9bca8, + 0x1f87dce, 0x0573c89, 0x17974ca, 0x06ef992, 0x1910a2b, 0x14487b7, + 0x1a3420e, 0x00f3246, 0x0fd0f38, 0x19ccac5, 0x1db490c, 0x0210f93, + 0x1c2103c, 0x117f6f9, 0x16ccb70, 0x1cbe98a, 0x00356a1, 0x1736669, + 0x1eb814b, 0x09703d4, 0x01eb0b8, 0x0e594ff, 0x01ca650 }, + { 0x19d25a0, 0x190e795, 0x1b6feec, 0x14814e8, 0x06affdc, 0x11b45ab, + 0x14c3967, 0x11f8382, 0x07d8006, 0x1768f52, 0x1f75a15, 0x11fcac8, + 0x089b74d, 0x04dbc6d, 0x05ad41e, 0x067223b, 0x0438bbe, 0x19cdba9, + 0x1616317, 0x1a887c1, 0x0a34ef8, 0x04cb235, 0x1374b6d, 0x0cea878, + 0x13bd1e6, 0x0c2bfd6, 0x01a2602, 0x01ae218, 0x1acabad, 0x1f9924f, + 0x04a7deb, 0x029f343, 0x15dec1c, 0x183d082, 0x0e647ec, 0x09594cc, + 0x15ffff6, 0x027ec89, 0x0f3bab1, 0x16d975a, 0x0462caf }, + { 0x03237dd, 0x05323ef, 0x1010598, 0x190570e, 0x15f735c, 0x1d2afc4, + 0x07d6777, 0x095ef0f, 0x0726b91, 0x0f7821f, 0x0f8a605, 0x127a392, + 0x1118753, 0x1778c19, 0x08af9d1, 0x1425743, 0x1fc25a9, 0x1a73f46, + 0x070e45f, 0x1f92fb5, 0x1e41dfe, 0x0185175, 0x0f21d74, 0x065a399, + 0x1d235a7, 0x16987ba, 0x1b66ea9, 0x0dfdcff, 0x1485760, 0x07d5b2f, + 0x102a9e1, 0x0a27f07, 0x1155e22, 0x1ce8991, 0x1c60fa3, 0x1ba5f6e, + 0x1546eaf, 0x148a81d, 0x0d820a8, 0x118d9b2, 0x01293c9 }, + { 0x1d53b77, 0x00928a4, 0x0b1dc9e, 0x1b2dd5f, 0x06ab403, 0x1b5b88d, + 0x11f6d28, 0x1836faf, 0x087e771, 0x11c6384, 0x0dd48a0, 0x157e676, + 0x0d495f6, 0x0643a98, 0x0c0a272, 0x0223561, 0x186e77b, 0x16541e5, + 0x06f4627, 0x181f714, 0x17c7be1, 0x1d8d74e, 0x1633ecb, 0x08187d0, + 0x023c549, 0x083e82e, 0x05d2b64, 0x0dcf3c8, 0x0e71421, 0x1f82832, + 0x13e8291, 0x1fbfac2, 0x0929cd4, 0x14c45e3, 0x0130e51, 0x03db64b, + 0x046f8fb, 0x125af9f, 0x052e9cf, 0x142d1d5, 0x053b79a }, + { 0x0bbb6a1, 0x1d7e722, 0x1ca085b, 0x00cf042, 0x13a5bba, 0x0ec9cd6, + 0x12cc2a7, 0x1fdde3c, 0x1f19efa, 0x117579e, 0x1b00500, 0x179cf69, + 0x18fed5a, 0x0896339, 0x05a3b99, 0x11344c9, 0x06929fe, 0x09188cc, + 0x1ce5f01, 0x073b1a8, 0x16c40d5, 0x0a11a2c, 0x19002f1, 0x08cc23a, + 0x07f5853, 0x107dc94, 0x0f27576, 0x0813320, 0x1af2a80, 0x04cbe41, + 0x18797bd, 0x06502a3, 0x09dc01b, 0x0088264, 0x12a5610, 0x1a2a1f6, + 0x13872c9, 0x137beaf, 0x1a0cd02, 0x1a2ad85, 0x08290d6 }, + { 0x0546946, 0x11be36c, 0x1febe11, 0x12d3d8a, 0x1a134a3, 0x04803f6, + 0x166935e, 0x013a846, 0x00dc7b8, 0x012abff, 0x1e12a6d, 0x0a5a5ac, + 0x1fe62ae, 0x05e56da, 0x1c53298, 0x1f94b44, 0x1e633aa, 0x0e61046, + 0x1659e04, 0x01dab9d, 0x1660238, 0x14ed990, 0x1b9ad57, 0x0ea46b4, + 0x0d02ca6, 0x0708df5, 0x06ccfe8, 0x0398ddf, 0x0a2a085, 0x1f13783, + 0x13ff488, 0x1d88f67, 0x0f332e1, 0x14c2700, 0x05ee82a, 0x088b3e5, + 0x0e952e1, 0x10ecb4f, 0x0aec1be, 0x156609f, 0x0506ef1 }, + { 0x1bff163, 0x075939a, 0x061046d, 0x1fd53f5, 0x1130b96, 0x1593e73, + 0x1acfe77, 0x1aacd59, 0x19dd1c3, 0x16d78d2, 0x01d6aa8, 0x14fd4e6, + 0x18f5090, 0x11838da, 0x09abce7, 0x15b386d, 0x13ddf73, 0x15146b1, + 0x1722685, 0x0a99597, 0x1c3cdd3, 0x11ea6e5, 0x17fa8d0, 0x13b25a3, + 0x074d237, 0x1b2b776, 0x1e3bb59, 0x02948ad, 0x0feb1fe, 0x1ba1fd4, + 0x11feaf9, 0x1731f97, 0x004ccf8, 0x138370a, 0x1effdc6, 0x10d99a5, + 0x0d85c67, 0x179feda, 0x00d136a, 0x17e2a40, 0x0415b7d }, + { 0x18377a7, 0x082c33e, 0x09ca5c0, 0x1197006, 0x068a3d6, 0x1d26190, + 0x14a27c0, 0x121facf, 0x193c8f2, 0x1e384ae, 0x168ae12, 0x0279d3c, + 0x1b712fa, 0x07f5cf9, 0x1ab1b18, 0x0a985f8, 0x0d96e0e, 0x0866d1b, + 0x18c8280, 0x132ea30, 0x0f11454, 0x08cbf80, 0x1e4c632, 0x126ca11, + 0x04c3fe6, 0x05500ee, 0x0617c1a, 0x0d345df, 0x15511c7, 0x0778515, + 0x014d48b, 0x168245c, 0x06965ed, 0x0ea1f80, 0x0bf305d, 0x13f9c1f, + 0x0c831d5, 0x0ee4def, 0x01e7549, 0x1e35eb1, 0x01ec314 }, + { 0x08310c2, 0x1ff7796, 0x1dd0198, 0x148afc7, 0x0a7e14d, 0x1a3443d, + 0x043f394, 0x18a7256, 0x1637ec2, 0x0f251c7, 0x0be37f3, 0x06416a8, + 0x1150773, 0x1bef0b8, 0x04c0be7, 0x1378c68, 0x063ae4b, 0x180c58e, + 0x14be79b, 0x0388ddb, 0x0fa0f00, 0x0b93766, 0x14eec2a, 0x08dc18f, + 0x1b99d77, 0x1765498, 0x1fd61d6, 0x01916de, 0x139c82e, 0x18be4b4, + 0x192eccb, 0x07bcb4c, 0x05135d2, 0x1fd35bb, 0x12d14aa, 0x1ce326d, + 0x0dc105d, 0x0e60479, 0x15e22b5, 0x024fffe, 0x017e91d }, + { 0x1e051ca, 0x16769db, 0x1b52fa4, 0x1a338ee, 0x0644d4f, 0x033c25e, + 0x12d4802, 0x0639156, 0x1ce9d6b, 0x1533113, 0x07a71cf, 0x1347a51, + 0x0e39524, 0x08950cf, 0x1427997, 0x0b5d8a8, 0x0928c36, 0x153dea3, + 0x1e58f83, 0x132fc8e, 0x132d354, 0x0bdaccb, 0x035d965, 0x1a9476c, + 0x04aeb91, 0x1144cac, 0x1077acf, 0x1cca7d4, 0x0571df6, 0x0c76ab9, + 0x1e729f2, 0x16315c3, 0x101a38f, 0x1dcbf79, 0x1f098fd, 0x0a2c53e, + 0x0fc4a0d, 0x1211415, 0x030077c, 0x0967bba, 0x0118f3b }, + { 0x0d4762b, 0x050543d, 0x05d5d28, 0x1518b1a, 0x1aef84d, 0x1bb6c30, + 0x1258133, 0x1162dfe, 0x07e60d9, 0x05f43c3, 0x1076eb0, 0x1ff67d9, + 0x1a83637, 0x0eeb0a3, 0x1129825, 0x08dcb84, 0x0345b08, 0x0d1f0bc, + 0x1de9301, 0x1d6d0dc, 0x0695735, 0x07efbac, 0x16f062d, 0x1bfca5e, + 0x18d0b1b, 0x1d08ab0, 0x1401c56, 0x0f1d981, 0x1d617f8, 0x1e8d616, + 0x04076f6, 0x0436c2e, 0x1d2b631, 0x0c9e110, 0x09e513d, 0x08459d1, + 0x04f1702, 0x0da9b52, 0x19c9cee, 0x0f91a07, 0x001d0a6 }, + { 0x046533c, 0x1211b0f, 0x0ab9ee5, 0x01f7118, 0x0947799, 0x16250c7, + 0x1745a90, 0x08a0336, 0x1d83c7a, 0x09af40e, 0x198f8dc, 0x17ba996, + 0x0374a69, 0x13b606b, 0x19fb36f, 0x11b4cf6, 0x12111e6, 0x101eaa2, + 0x0ba1942, 0x199d6ba, 0x1b37596, 0x1e95781, 0x1355cb7, 0x17ab2a5, + 0x04ba1fa, 0x0b4a91b, 0x1ad3b61, 0x1e8fa8a, 0x10d5d47, 0x1ab964a, + 0x0116b62, 0x090dc5f, 0x0dd2dfa, 0x1d82265, 0x0d0f15a, 0x0dbaa4f, + 0x197c08e, 0x16dd124, 0x0c83f26, 0x00cfb4c, 0x01b625b }, + { 0x1d8446d, 0x1d53da7, 0x0fad137, 0x035edfd, 0x001b2f0, 0x041c5ae, + 0x10e23fa, 0x1177e88, 0x1bba975, 0x19e21a7, 0x15af27c, 0x19750e2, + 0x0b2b971, 0x0fa484c, 0x0917970, 0x18bbad6, 0x1342b41, 0x1c3ee5a, + 0x13614b5, 0x1f018c6, 0x1a34db1, 0x0c1219e, 0x1b5b8c9, 0x0fbe184, + 0x020653f, 0x1b2fb34, 0x10d832c, 0x0994acf, 0x06656ac, 0x15614c1, + 0x1a0c87e, 0x17e0d2e, 0x1f5ca6f, 0x1b31c89, 0x04869c1, 0x1c2a72f, + 0x0400736, 0x18a1944, 0x05236f7, 0x12c33f9, 0x0333eca }, + { 0x0775d81, 0x1bca456, 0x0f288cc, 0x1fa83b7, 0x18c2518, 0x1e74a41, + 0x1e93ef3, 0x1cec478, 0x054703f, 0x169b11b, 0x0ced6ea, 0x074827f, + 0x102b3a1, 0x1fae00f, 0x0cd5969, 0x12cc2bb, 0x0dc5235, 0x0eb9204, + 0x1585ba4, 0x0ff1ca3, 0x19995a1, 0x15e592d, 0x04305bb, 0x126e87d, + 0x08cf133, 0x053f9af, 0x0b952d9, 0x10fb4e9, 0x0d449d9, 0x191532e, + 0x17555ec, 0x06fcf62, 0x05082a5, 0x089a7bb, 0x1d0bcb3, 0x0c9a4b8, + 0x0ccf074, 0x0ece03a, 0x144d6ba, 0x0210e51, 0x072fc21 }, + { 0x16004c8, 0x15901fc, 0x17fea41, 0x1e8b00a, 0x183f95c, 0x19ac84e, + 0x1619d57, 0x1ddaefa, 0x1e550c8, 0x14f537d, 0x0182052, 0x1952ab4, + 0x0291c8c, 0x1e74103, 0x07fb9e2, 0x1f0bc94, 0x0069a3d, 0x175cd6f, + 0x14f7999, 0x1b9e18f, 0x0d51fbb, 0x0dae99b, 0x08a28e4, 0x05ff878, + 0x18d285c, 0x12dbb07, 0x0cbdec5, 0x1dc91bc, 0x1770401, 0x1ec22b0, + 0x0800e00, 0x13bdff3, 0x173f648, 0x11ad272, 0x0e3a85f, 0x0dc344e, + 0x0840a6c, 0x0778be4, 0x164b48e, 0x1f1623d, 0x0480946 }, + { 0x171f119, 0x1a3d47e, 0x1a56131, 0x1ca7d66, 0x19e65c5, 0x0c2c3d0, + 0x19e198a, 0x1e81c5e, 0x1ab18d6, 0x052444c, 0x02e3012, 0x00498c6, + 0x12a1a99, 0x16557c4, 0x05d4258, 0x1ac4909, 0x0bae20f, 0x064434d, + 0x10adf75, 0x05609ad, 0x17d03b7, 0x1b04c97, 0x189dd7a, 0x00dcd09, + 0x1c06e7d, 0x0038044, 0x0792ef4, 0x167686c, 0x0846e4c, 0x1335a5d, + 0x07a86b9, 0x08c8c9b, 0x01c2eb2, 0x029cfe0, 0x0f9b07e, 0x0ff0de5, + 0x0f68afc, 0x1474576, 0x1a4085b, 0x1fb8e70, 0x08dab61 }, + { 0x14d1d45, 0x0e481ea, 0x0e890a9, 0x1dfe9f3, 0x0cd4297, 0x0a3c5a5, + 0x0d480d3, 0x0345b11, 0x108c462, 0x0d95d15, 0x195008d, 0x1376690, + 0x06d3d23, 0x088f997, 0x19dabb6, 0x1fb843b, 0x1cf3f06, 0x143bfc5, + 0x1b14540, 0x0e29833, 0x100d802, 0x15d2c83, 0x0841113, 0x1b992af, + 0x0229f31, 0x1f6c34a, 0x0ee05a7, 0x1d9cef5, 0x0f080e5, 0x050a965, + 0x1c556fa, 0x197af9d, 0x0b21b14, 0x0bf709f, 0x0b459ee, 0x193bdef, + 0x118f690, 0x1e543c8, 0x0a79f80, 0x05bf336, 0x06f77e6 }, + { 0x00bbf59, 0x0def6f2, 0x0b5a89c, 0x06c8035, 0x177ba45, 0x0a0e688, + 0x180d5cd, 0x05e2eab, 0x04b71b0, 0x032da33, 0x0cd67cd, 0x0227502, + 0x0722eb7, 0x179c756, 0x04aa3f5, 0x1e76b2f, 0x12fff3b, 0x188d500, + 0x0170fef, 0x15f57ff, 0x0c4299a, 0x1783606, 0x047828b, 0x076f675, + 0x15d5777, 0x00518a6, 0x1b59a61, 0x1cbc5ce, 0x1a8be6a, 0x1039972, + 0x002184d, 0x1839eab, 0x06d7578, 0x1688177, 0x003da2f, 0x164689c, + 0x0184f0e, 0x0ebc434, 0x13e01e6, 0x12387a5, 0x063819c }, + { 0x084b073, 0x1c970bc, 0x1fab294, 0x19d624c, 0x1ec3a1f, 0x181c53c, + 0x1d7c241, 0x0e07a0f, 0x0e4c47b, 0x195603e, 0x05ae472, 0x09dc37f, + 0x1ff9666, 0x157527d, 0x1d5d624, 0x0ca01d7, 0x191fade, 0x02d55f9, + 0x1c74481, 0x066ede2, 0x181ac5b, 0x08d069e, 0x07fd831, 0x0d50896, + 0x0cfe797, 0x12d0859, 0x0af6984, 0x0263993, 0x1d453ee, 0x0b69a75, + 0x10783f0, 0x0a096d7, 0x0d0319a, 0x1c655e0, 0x0f9c28b, 0x0fc8741, + 0x15e49b4, 0x057f762, 0x15fbb20, 0x02504cb, 0x067d48d }, + { 0x02d56d6, 0x0acd3f5, 0x098c1a3, 0x1c4e901, 0x171abd0, 0x19b366e, + 0x076c2b9, 0x178d7a2, 0x007204e, 0x1db1ce5, 0x198a4fe, 0x05cfeef, + 0x1d89a24, 0x1add461, 0x19f28ad, 0x1f351bd, 0x03d64a2, 0x02396ee, + 0x1586804, 0x053be8e, 0x09d4842, 0x02e2db2, 0x057d8b2, 0x1924f9b, + 0x16b1b4d, 0x0cb7eea, 0x017b981, 0x1d17624, 0x129401f, 0x152855f, + 0x010fbf2, 0x021a383, 0x0900d0f, 0x00efaea, 0x0ea4a2c, 0x0a59e22, + 0x1f0e43f, 0x0bf5e18, 0x1371e8f, 0x071d070, 0x027950e }, + { 0x1d0fa79, 0x10ff870, 0x17a7aac, 0x060916b, 0x0b9fd03, 0x11ba65a, + 0x11a24bf, 0x0d69926, 0x04eb21f, 0x1a413fd, 0x179f9ee, 0x1ef3524, + 0x1146716, 0x1eea629, 0x10afcd9, 0x0dbbe28, 0x14cd2e9, 0x09039ca, + 0x140aaa2, 0x02835d0, 0x0cc94e0, 0x0d4777b, 0x03b8038, 0x1019b5f, + 0x0849158, 0x0232ae7, 0x11a58a0, 0x1e7574b, 0x15dfbff, 0x027c2e8, + 0x094cd73, 0x13ed09e, 0x1f0440c, 0x12dec53, 0x14feec7, 0x175d008, + 0x1f2225a, 0x04cc09f, 0x175c687, 0x108f364, 0x054ff78 }, + { 0x040b068, 0x177186f, 0x14789f1, 0x17cde74, 0x1226465, 0x1d90fb4, + 0x11813e8, 0x02bc494, 0x1c04181, 0x052d2d6, 0x0434ad4, 0x08831bf, + 0x0fe3285, 0x0e58600, 0x1d3963f, 0x011c776, 0x13b4a2c, 0x0e3478d, + 0x13367b2, 0x1be1021, 0x0a9f339, 0x0e5bc37, 0x0454d8b, 0x0ab5d5b, + 0x05e31c9, 0x035944a, 0x162da9b, 0x0d45803, 0x18a427d, 0x016e1b3, + 0x0b01a7a, 0x0519260, 0x1875500, 0x080f30b, 0x05967e8, 0x0d159b5, + 0x0e30b28, 0x0722b9f, 0x0c3f939, 0x10a7e30, 0x08adbad }, + { 0x169d524, 0x1708f84, 0x11e4182, 0x0fe7379, 0x142fdaf, 0x00fe617, + 0x19d99f3, 0x09e79d8, 0x0e2336d, 0x0b5ce79, 0x103dfd1, 0x0bbd1c3, + 0x0e6aa1f, 0x04c27d8, 0x0f0ab48, 0x096519b, 0x1a61b46, 0x1a04867, + 0x090fcfb, 0x10de602, 0x07e740d, 0x0666af4, 0x056c5b3, 0x04d9a83, + 0x1168c30, 0x198201f, 0x0e05b01, 0x17c70d9, 0x007a1dd, 0x0379ac2, + 0x0bc53ae, 0x02e2fc3, 0x188b4f8, 0x1e4b67a, 0x06999b2, 0x036eb88, + 0x027e71c, 0x0160d50, 0x1797fcd, 0x06d8128, 0x0739300 }, + { 0x0cdaf42, 0x1babe91, 0x0aae553, 0x1be8303, 0x188b591, 0x08a792b, + 0x1a067d5, 0x1791730, 0x0f18fd5, 0x0b21704, 0x13ae45a, 0x0ba2045, + 0x0592b30, 0x1527b4c, 0x05640f9, 0x1395c2e, 0x09d6117, 0x125ebeb, + 0x0a7006a, 0x1bfabba, 0x08ccdac, 0x0d6c888, 0x1c17775, 0x1591e2a, + 0x0c7b164, 0x197a1a5, 0x06d4918, 0x034a29c, 0x1fc4476, 0x130db98, + 0x0c516e7, 0x1c12c36, 0x1561348, 0x17911e7, 0x059dcfa, 0x0738515, + 0x0a7c99d, 0x0880c15, 0x197896f, 0x095c852, 0x08bc6ec }, + { 0x1f2a32b, 0x172e073, 0x08c3425, 0x1812711, 0x1f54800, 0x0f1b067, + 0x10df100, 0x14c0dfc, 0x0bb6054, 0x12afe4e, 0x1ea9b99, 0x10c108a, + 0x17510e1, 0x1594d95, 0x0b3f288, 0x1b4c341, 0x1e351b7, 0x1399241, + 0x0f9b232, 0x08e3dcd, 0x09a1e31, 0x0e45b2e, 0x195950c, 0x1acb977, + 0x0c3b948, 0x1547e4d, 0x06ba6ca, 0x0611f84, 0x00aa6ad, 0x0f86d53, + 0x1535a9f, 0x1305f81, 0x044d96a, 0x1d26b94, 0x10b1611, 0x0b56025, + 0x1ceb895, 0x1e47b8e, 0x1f854ac, 0x0fb7d38, 0x08e8543 }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 42]; + sp_digit tx[2 * 42]; + sp_digit ty[2 * 42]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 42 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 42 * 2; + ty = td + 5 * 42 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 42); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 42); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_42(tx, ty, t); + sp_1024_proj_mul_qx1_42(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_42(tx, tx, t); + sp_1024_mont_mul_42(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 42, 0, sizeof(sp_digit) * 42); + sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_42(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + + /* t1 = px + py */ + sp_1024_mont_add_42(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_42(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_42(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_42(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_42(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_42(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_42(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_42(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_42(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + + sp_1024_mont_inv_42(t1, p->z, t2); + sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_42(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 42); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_42(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 42; + sp_digit* pz2 = t + 2 * 42; + sp_digit* rx = t + 4 * 42; + sp_digit* ry = t + 6 * 42; + sp_digit* l = t + 8 * 42; + sp_digit* ty = t + 10 * 42; + + /* v = v^2 */ + sp_1024_proj_sqr_42(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_42(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_42(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_42(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_42(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_42(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_42(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_42(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_42(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_42(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_42(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_42(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_42(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + sp_digit* rx = t + 4 * 42; + sp_digit* ry = t + 6 * 42; + sp_digit* h = t + 8 * 42; + sp_digit* r = t + 10 * 42; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_42(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_42(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_42(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_42(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_42(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_42(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_42(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_42(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_42(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_42(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_42(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_42(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_42(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_42(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 42]; + sp_digit vx[2 * 42]; + sp_digit vy[2 * 42]; + sp_digit qx_px[2 * 42]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_42(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 42 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 42 * 2; + vy = td + 7 * 42 * 2; + qx_px = td + 8 * 42 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_42(p, pm); + sp_1024_point_from_ecc_point_42(q, qm); + + err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42); + + sp_1024_mont_add_42(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 25] >> (i % 25)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_42(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_42(vx, vy, t); + sp_1024_proj_sqr_42(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_42(vx, vx, t); + sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 42, 0, sizeof(sp_digit) * 42); + sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_42(c, 1, NULL); + sp_1024_point_free_42(q, 1, NULL); + sp_1024_point_free_42(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_42(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 42; + sp_digit* rx = t + 4 * 42; + sp_digit* ry = t + 6 * 42; + sp_digit* h = t + 8 * 42; + sp_digit* r = t + 10 * 42; + + /* h = p.z^2 */ + sp_1024_mont_sqr_42(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_42(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_42(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_42(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_42(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_42(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_42(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_42(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_42(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_42(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_42(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_42(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_42(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_42(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_42(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_42(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_42(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_42(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_42(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_42(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_42(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_42(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 42; + sp_digit* pz2 = t + 2 * 42; + sp_digit* rx = t + 4 * 42; + sp_digit* ry = t + 6 * 42; + sp_digit* l = t + 8 * 42; + sp_digit* ty = t + 10 * 42; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_42(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_42(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_42(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_42(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_42(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_42(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_42(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_42(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_42(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_42(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_42(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_42(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_42(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[84]; + sp_digit (*pre_vy)[84]; + sp_digit (*pre_nvy)[84]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 42]; + sp_digit vx[2 * 42]; + sp_digit vy[2 * 42]; + sp_digit pre_vx[16][84]; + sp_digit pre_vy[16][84]; + sp_digit pre_nvy[16][84]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_42(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 42 * 2; + vy = td + 7 * 42 * 2; + pre_vx = (sp_digit(*)[84])(td + 8 * 42 * 2); + pre_vy = (sp_digit(*)[84])(td + 24 * 42 * 2); + pre_nvy = (sp_digit(*)[84])(td + 40 * 42 * 2); + pre_p = (sp_point_1024*)(td + 56 * 42 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_42(p, pm); + sp_1024_point_from_ecc_point_42(q, qm); + + err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42); + sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42); + sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42); + sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_42(vx, vy, t); + sp_1024_proj_sqr_42(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_42(vx, vx, t); + sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 42, 0, sizeof(sp_digit) * 42); + sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_42(c, 1, NULL); + sp_1024_point_free_42(q, 1, NULL); + sp_1024_point_free_42(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_42(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 42; + sp_digit* t2 = t + 2 * 2 * 42; + sp_digit* l = t + 4 * 2 * 42; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_42(l, py, p1024_mod); + sp_1024_mont_inv_42(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_42(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_42(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_42(t2, t1, p1024_mod); + sp_1024_mont_add_42(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_42(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_42(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_42(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 42); + XMEMCPY(cr, t2, sizeof(sp_digit) * 42); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_42(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 42; + sp_digit* c = t + 2 * 2 * 42; + sp_digit* l = t + 4 * 2 * 42; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_42(l, cx, px, p1024_mod); + sp_1024_mont_inv_42(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_42(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_42(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_42(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_42(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_42(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_42(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 42); + XMEMCPY(cr, c, sizeof(sp_digit) * 42); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_42(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 42; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_42(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_42(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_42(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_42(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 42]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 42 * 2); +#endif + + sp_1024_point_from_ecc_point_42(p, pm); + + err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_42(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_42(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_42(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_42(c, c, t); + sp_1024_mont_map_42(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_42(c, c, &pre_p[j/2], t); + sp_1024_mont_map_42(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_42(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_42(c, c, neg, t); + sp_1024_mont_map_42(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_42(c, c, t); + sp_1024_mont_map_42(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_42(neg, 1, NULL); + sp_1024_point_free_42(c, 1, NULL); + sp_1024_point_free_42(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[84]; + sp_digit (*pre_vy)[84]; + sp_digit (*pre_nvy)[84]; +#else + sp_digit t[6 * 2 * 42]; + sp_digit vx[2 * 42]; + sp_digit vy[2 * 42]; + sp_digit pre_vx[16][84]; + sp_digit pre_vy[16][84]; + sp_digit pre_nvy[16][84]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_42(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 42 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 42 * 2; + vy = td + 7 * 42 * 2; + pre_vx = (sp_digit(*)[84])(td + 8 * 42 * 2); + pre_vy = (sp_digit(*)[84])(td + 24 * 42 * 2); + pre_nvy = (sp_digit(*)[84])(td + 40 * 42 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_42(p, pm); + sp_1024_point_from_ecc_point_42(q, qm); + + err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42); + sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42); + sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42); + sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 42); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_42(vx, vy, t); + sp_1024_proj_sqr_42(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_42(vx, vx, t); + sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 42, 0, sizeof(sp_digit) * 42); + sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_42(c, 1, NULL); + sp_1024_point_free_42(q, 1, NULL); + sp_1024_point_free_42(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_42(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] | + a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] | + a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31] | + a[32] | a[33] | a[34] | a[35] | a[36] | a[37] | a[38] | a[39] | + a[40] | a[41]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 17U) { + r[j] &= 0x1ffffff; + s = 25U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_42(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[42 * 4]; +#endif + sp_digit* t2 = NULL; + int32_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 42; + + sp_1024_sqr_42(t1, point->y); + (void)sp_1024_mod_42(t1, t1, p1024_mod); + sp_1024_sqr_42(t2, point->x); + (void)sp_1024_mod_42(t2, t2, p1024_mod); + sp_1024_mul_42(t2, t2, point->x); + (void)sp_1024_mod_42(t2, t2, p1024_mod); + (void)sp_1024_sub_42(t2, p1024_mod, t2); + sp_1024_mont_add_42(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_42(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_42(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_42(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_42(t1, p1024_mod); + sp_1024_cond_sub_42(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_42(t1); + if (!sp_1024_iszero_42(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 42, pX); + sp_1024_from_mp(pub->y, 42, pY); + sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_42(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[42]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 42, pX); + sp_1024_from_mp(pub->y, 42, pY); + sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 42, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_42(pub->x) != 0) && + (sp_1024_iszero_42(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_42(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_42(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_42(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_1024_ecc_mulmod_42(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_42(p->x) == 0) || + (sp_1024_iszero_42(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_1024_ecc_mulmod_base_42(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_42(p->x, pub->x) != 0) || + (sp_1024_cmp_42(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* SP_WORD_SIZE == 32 */ #endif /* !WOLFSSL_SP_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 96c96aff9..2669c4287 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -75,7 +75,8 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 }; */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -117,7 +118,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 57 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -151,7 +153,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -190,7 +194,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_2048_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<35; i++) { r[i+1] += r[i] >> 57; @@ -680,7 +687,9 @@ SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[35]) * b[35]; @@ -712,7 +721,9 @@ SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[35]) * a[35]; @@ -792,7 +803,9 @@ SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[17]) * b[17]; @@ -824,7 +837,9 @@ SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[17]) * a[17]; @@ -854,7 +869,7 @@ SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -863,7 +878,8 @@ SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -1181,7 +1197,6 @@ static void sp_2048_mont_reduce_18(sp_digit* a, const sp_digit* m, sp_digit mp) sp_2048_mul_add_18(a+i, m, mu); a[i+1] += a[i] >> 57; a[i] &= 0x1ffffffffffffffL; - sp_2048_mont_shift_18(a, a); sp_2048_cond_sub_18(a, a, m, 0 - (((a[17] >> 55) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -1197,8 +1212,8 @@ static void sp_2048_mont_reduce_18(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_18(r, a, b); sp_2048_mont_reduce_18(r, m, mp); @@ -1211,8 +1226,8 @@ static void sp_2048_mont_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_18(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_18(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_18(r, a); sp_2048_mont_reduce_18(r, m, mp); @@ -1312,60 +1327,23 @@ static void sp_2048_cond_add_18(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 18; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 18; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif #ifdef WOLFSSL_SP_DIV_64 static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 57 bits from d1 and top 6 bits from d0. */ - d = (d1 << 6) | (d0 >> 51); + d = (d1 << 6) + (d0 >> 51); r = d / dv; d -= r * dv; /* Up to 7 bits in r */ /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 45) & ((1 << 6) - 1); + d += (d0 >> 45) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1373,7 +1351,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 39) & ((1 << 6) - 1); + d += (d0 >> 39) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1381,7 +1359,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 33) & ((1 << 6) - 1); + d += (d0 >> 33) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1389,7 +1367,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 27) & ((1 << 6) - 1); + d += (d0 >> 27) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1397,7 +1375,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 21) & ((1 << 6) - 1); + d += (d0 >> 21) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1405,7 +1383,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 15) & ((1 << 6) - 1); + d += (d0 >> 15) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1413,7 +1391,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 9) & ((1 << 6) - 1); + d += (d0 >> 9) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1421,7 +1399,7 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 3) & ((1 << 6) - 1); + d += (d0 >> 3) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -1429,10 +1407,11 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Remaining 3 bits from d0. */ r <<= 3; d <<= 3; - d |= d0 & ((1 << 3) - 1); + d += d0 & ((1 << 3) - 1); t = d / dv; r += t; + /* All 57 bits from d1 and top 6 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -1440,66 +1419,60 @@ static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[36], t2d[18 + 1]; + sp_digit t1[3 * 18 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 18 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 18 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 18; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 18; dv = d[17]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 18U); for (i=17; i>=0; i--) { - sp_digit hi; t1[18 + i] += t1[18 + i - 1] >> 57; t1[18 + i - 1] &= 0x1ffffffffffffffL; - hi = t1[18 + i] - (t1[18 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[18 + i]; d1 <<= 57; d1 += t1[18 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_2048_div_word_18(hi, t1[18 + i - 1], dv); + r1 = sp_2048_div_word_18(t1[18 + i], t1[18 + i - 1], dv); #endif sp_2048_mul_d_18(t2, d, r1); (void)sp_2048_sub_18(&t1[i], &t1[i], t2); + sp_2048_norm_18(&t1[i]); t1[18 + i] -= t2[18]; t1[18 + i] += t1[18 + i - 1] >> 57; t1[18 + i - 1] &= 0x1ffffffffffffffL; @@ -1516,7 +1489,7 @@ static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_2048_mul_d_18(t2, d, r1); (void)sp_2048_sub_18(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 18U); + XMEMCPY(r, t1, sizeof(*r) * 36U); for (i=0; i<17; i++) { r[i+1] += r[i] >> 57; r[i] &= 0x1ffffffffffffffL; @@ -1525,10 +1498,9 @@ static int sp_2048_div_18(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -1559,35 +1531,31 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 36]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 18 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 18 * 2); -#else - t[i] = &td[i * 18 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 18U * 2U); } @@ -1642,43 +1610,38 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 36]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 18 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 18 * 2); -#else - t[i] = &td[i * 18 * 2]; -#endif } sp_2048_mont_setup(m, &mp); @@ -1732,47 +1695,40 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 18 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 36) + 36]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 36) + 36), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 36; rt = td + 1152; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 36]; - rt = &td[1152]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_18(norm, m); @@ -1843,7 +1799,7 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 36); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (7 - c); c += 57; @@ -1869,16 +1825,15 @@ static int sp_2048_mod_exp_18(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 2048 bits, just need to subtract. @@ -2086,7 +2041,8 @@ static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; - sp_digit n, s; + sp_digit n; + sp_digit s; s = a[36]; n = a[35] >> 53; @@ -2099,7 +2055,8 @@ static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a) n += s << 4; r[35] = n; #else - sp_digit n, s; + sp_digit n; + sp_digit s; int i; s = a[36]; n = a[35] >> 53; @@ -2145,7 +2102,7 @@ static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp) sp_2048_norm_36(a + 36); -#ifdef WOLFSSL_HAVE_SP_DH +#ifdef WOLFSSL_SP_DH if (mp != 1) { for (i=0; i<35; i++) { mu = (a[i] * mp) & 0x1ffffffffffffffL; @@ -2179,7 +2136,6 @@ static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp) a[i+1] += a[i] >> 57; a[i] &= 0x1ffffffffffffffL; #endif - sp_2048_mont_shift_36(a, a); sp_2048_cond_sub_36(a, a, m, 0 - (((a[35] >> 53) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -2195,8 +2151,8 @@ static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_36(r, a, b); sp_2048_mont_reduce_36(r, m, mp); @@ -2209,8 +2165,8 @@ static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_36(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_36(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_36(r, a); sp_2048_mont_reduce_36(r, m, mp); @@ -2253,60 +2209,23 @@ static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 36; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 36; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif #ifdef WOLFSSL_SP_DIV_64 static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 57 bits from d1 and top 6 bits from d0. */ - d = (d1 << 6) | (d0 >> 51); + d = (d1 << 6) + (d0 >> 51); r = d / dv; d -= r * dv; /* Up to 7 bits in r */ /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 45) & ((1 << 6) - 1); + d += (d0 >> 45) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2314,7 +2233,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 39) & ((1 << 6) - 1); + d += (d0 >> 39) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2322,7 +2241,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 33) & ((1 << 6) - 1); + d += (d0 >> 33) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2330,7 +2249,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 27) & ((1 << 6) - 1); + d += (d0 >> 27) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2338,7 +2257,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 21) & ((1 << 6) - 1); + d += (d0 >> 21) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2346,7 +2265,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 15) & ((1 << 6) - 1); + d += (d0 >> 15) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2354,7 +2273,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 9) & ((1 << 6) - 1); + d += (d0 >> 9) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2362,7 +2281,7 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 3) & ((1 << 6) - 1); + d += (d0 >> 3) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -2370,10 +2289,11 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Remaining 3 bits from d0. */ r <<= 3; d <<= 3; - d |= d0 & ((1 << 3) - 1); + d += d0 & ((1 << 3) - 1); t = d / dv; r += t; + /* All 57 bits from d1 and top 6 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -2381,66 +2301,60 @@ static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[72], t2d[36 + 1]; + sp_digit t1[3 * 36 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 36 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 36 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 36; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 36; dv = d[35]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 36U); for (i=35; i>=0; i--) { - sp_digit hi; t1[36 + i] += t1[36 + i - 1] >> 57; t1[36 + i - 1] &= 0x1ffffffffffffffL; - hi = t1[36 + i] - (t1[36 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[36 + i]; d1 <<= 57; d1 += t1[36 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_2048_div_word_36(hi, t1[36 + i - 1], dv); + r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv); #endif sp_2048_mul_d_36(t2, d, r1); (void)sp_2048_sub_36(&t1[i], &t1[i], t2); + sp_2048_norm_36(&t1[i]); t1[36 + i] -= t2[36]; t1[36 + i] += t1[36 + i - 1] >> 57; t1[36 + i - 1] &= 0x1ffffffffffffffL; @@ -2457,7 +2371,7 @@ static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_2048_mul_d_36(t2, d, r1); (void)sp_2048_sub_36(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 36U); + XMEMCPY(r, t1, sizeof(*r) * 72U); for (i=0; i<35; i++) { r[i+1] += r[i] >> 57; r[i] &= 0x1ffffffffffffffL; @@ -2466,10 +2380,9 @@ static int sp_2048_div_36(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -2502,35 +2415,31 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 72]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 36 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 36 * 2); -#else - t[i] = &td[i * 36 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 36U * 2U); } @@ -2585,43 +2494,38 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 72]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 36 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 36 * 2); -#else - t[i] = &td[i * 36 * 2]; -#endif } sp_2048_mont_setup(m, &mp); @@ -2675,47 +2579,40 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 72) + 72]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 72) + 72), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 72; rt = td + 2304; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 72]; - rt = &td[2304]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_36(norm, m); @@ -2786,7 +2683,7 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 72); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (7 - c); c += 57; @@ -2812,15 +2709,14 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */ /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_RSA @@ -2836,15 +2732,18 @@ static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[36 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -2869,15 +2768,16 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } +#endif if (err == MP_OKAY) { - a = d; r = a + 36 * 2; m = r + 36 * 2; norm = r; @@ -2930,20 +2830,21 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[72], md[36], rd[72]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[36 * 5]; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -2965,27 +2866,20 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { a = d; r = a + 36 * 2; m = r + 36 * 2; - } -#else - a = ad; - m = md; - r = rd; -#endif - if (err == MP_OKAY) { sp_2048_from_bin(a, 36, in, inLen); #if DIGIT_BIT >= 57 e[0] = (sp_digit)em->dp[0]; @@ -3049,10 +2943,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } #endif return err; @@ -3061,7 +2954,7 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #ifndef WOLFSSL_RSA_PUBLIC_ONLY #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) -#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */ /* RSA private key operation. * * in Array of bytes representing the number to exponentiate, base. @@ -3079,14 +2972,18 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a = NULL; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[36 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -3115,13 +3012,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 36; m = a + 72; @@ -3132,20 +3031,34 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_2048_from_mp(m, 36, mm); err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); } + if (err == MP_OKAY) { sp_2048_to_bin(r, out); *outLen = 256; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 36); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 36); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[72], d[36], m[36]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit d[36 * 4]; +#endif + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -3172,7 +3085,20 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + a = d + 36; + m = a + 72; + r = a; + sp_2048_from_bin(a, 36, in, inLen); sp_2048_from_mp(d, 36, dm); sp_2048_from_mp(m, 36, mm); @@ -3184,22 +3110,35 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } - XMEMSET(d, 0, sizeof(sp_digit) * 36); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 36); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #else -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[18 * 11]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -3220,22 +3159,21 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) { + if (a == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - a = t; p = a + 36 * 2; q = p + 18; qi = dq = dp = q + 18; tmpa = qi + 18; tmpb = tmpa + 36; - - r = t + 36; + r = a + 36; sp_2048_from_bin(a, 36, in, inLen); sp_2048_from_mp(p, 18, pm); @@ -3249,6 +3187,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } if (err == MP_OKAY) { (void)sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_norm_18(tmpa); sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); @@ -3266,17 +3205,31 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 18 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 18 * 11); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[36 * 2]; - sp_digit p[18], q[18], dp[18], dq[18], qi[18]; - sp_digit tmpa[36], tmpb[36]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[18 * 13]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -3297,7 +3250,25 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 13, NULL, + DYNAMIC_TYPE_RSA); + if (a == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = a + 36 * 2; + q = p + 18; + dp = q + 18; + dq = dp + 18; + qi = dq + 18; + tmpa = qi + 18; + tmpb = tmpa + 36; + r = a; + sp_2048_from_bin(a, 36, in, inLen); sp_2048_from_mp(p, 18, pm); sp_2048_from_mp(q, 18, qm); @@ -3313,6 +3284,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, if (err == MP_OKAY) { (void)sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_norm_18(tmpa); sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); sp_2048_mul_18(tmpa, tmpa, qi); @@ -3328,16 +3300,18 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); - XMEMSET(dq, 0, sizeof(dq)); - XMEMSET(qi, 0, sizeof(qi)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) +if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 18 * 13); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } @@ -3361,17 +3335,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 36; mp_clamp(r); #elif DIGIT_BIT < 57 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 36; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 57) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -3384,14 +3360,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 36; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 57 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -3418,15 +3396,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[36 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 2048) { @@ -3442,16 +3424,16 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 36 * 2; m = e + 36; r = b; @@ -3467,21 +3449,27 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_2048_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 36U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 36U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[72], ed[36], md[36]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[36 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -3498,26 +3486,19 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 36 * 2; - m = e + 36; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 36 * 2; + m = e + 36; + r = b; + sp_2048_from_mp(b, 36, base); sp_2048_from_mp(e, 36, exp); sp_2048_from_mp(m, 36, mod); @@ -3530,14 +3511,17 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 36U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 36U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 36U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -3546,7 +3530,8 @@ int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) #ifdef WOLFSSL_HAVE_SP_DH #ifdef HAVE_FFDHE_2048 -SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, const sp_digit* a, + byte n) { #ifdef WOLFSSL_SP_SMALL int i; @@ -3556,7 +3541,8 @@ SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, sp_digit* a, byte n) r[i] = ((a[i] << n) | (a[i-1] >> (57 - n))) & 0x1ffffffffffffffL; } #else - sp_int_digit s, t; + sp_int_digit s; + sp_int_digit t; s = (sp_int_digit)a[35]; r[36] = s >> (57U - n); @@ -3645,35 +3631,31 @@ SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, sp_digit* a, byte n) static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[109]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 109, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 72; XMEMSET(td, 0, sizeof(sp_digit) * 109); -#else - tmp = &td[72]; - XMEMSET(td, 0, sizeof(td)); -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_36(norm, m); @@ -3699,7 +3681,7 @@ static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const n <<= 5; c -= 5; sp_2048_lshift_36(r, norm, (byte)y); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (7 - c); c += 57; @@ -3732,9 +3714,8 @@ static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -3754,16 +3735,19 @@ static int sp_2048_mod_exp_2_36(sp_digit* r, const sp_digit* e, int bits, const * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[36 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; if (mp_count_bits(base) > 2048) { @@ -3779,15 +3763,15 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 36 * 2; m = e + 36; r = b; @@ -3815,21 +3799,27 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, XMEMMOVE(out, out + i, *outLen); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 36U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 36U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[72], ed[36], md[36]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[36 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; int err = MP_OKAY; @@ -3846,26 +3836,20 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 36 * 2; - m = e + 36; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 36 * 2; + m = e + 36; + r = b; + sp_2048_from_mp(b, 36, base); sp_2048_from_bin(e, 36, exp, expLen); sp_2048_from_mp(m, 36, mod); @@ -3887,19 +3871,23 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256U && out[i] == 0U; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 36U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 36U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 36U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -3915,15 +3903,19 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[18 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 1024) { @@ -3939,16 +3931,16 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 18 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 18 * 2; m = e + 18; r = b; @@ -3965,21 +3957,27 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_2048_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 18U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 36U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[36], ed[18], md[18]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[18 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -3996,26 +3994,19 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 18 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 18 * 2; - m = e + 18; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 18 * 2; + m = e + 18; + r = b; + sp_2048_from_mp(b, 18, base); sp_2048_from_mp(e, 18, exp); sp_2048_from_mp(m, 18, mod); @@ -4029,20 +4020,23 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 18U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 18U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 36U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -4056,7 +4050,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -4098,7 +4093,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 57 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -4132,7 +4128,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -4171,7 +4169,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_3072_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<53; i++) { r[i+1] += r[i] >> 57; @@ -4773,7 +4774,9 @@ SP_NOINLINE static int sp_3072_sub_54(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[53]) * b[53]; @@ -4805,7 +4808,9 @@ SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[53]) * a[53]; @@ -4943,7 +4948,9 @@ SP_NOINLINE static int sp_3072_sub_27(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[26]) * b[26]; @@ -4978,7 +4985,8 @@ SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j; + int i; + int j; int128_t t[54]; XMEMSET(t, 0, sizeof(t)); @@ -5003,7 +5011,9 @@ SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[26]) * a[26]; @@ -5040,7 +5050,8 @@ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) */ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) { - int i, j; + int i; + int j; int128_t t[54]; XMEMSET(t, 0, sizeof(t)); @@ -5058,7 +5069,7 @@ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -5067,7 +5078,8 @@ SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -5342,7 +5354,8 @@ static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; - sp_digit n, s; + sp_digit n; + sp_digit s; s = a[27]; n = a[26] >> 54; @@ -5355,7 +5368,8 @@ static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a) n += s << 3; r[26] = n; #else - sp_digit n, s; + sp_digit n; + sp_digit s; int i; s = a[27]; n = a[26] >> 54; @@ -5408,7 +5422,6 @@ static void sp_3072_mont_reduce_27(sp_digit* a, const sp_digit* m, sp_digit mp) sp_3072_mul_add_27(a+i, m, mu); a[i+1] += a[i] >> 57; a[i] &= 0x1ffffffffffffffL; - sp_3072_mont_shift_27(a, a); sp_3072_cond_sub_27(a, a, m, 0 - (((a[26] >> 54) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -5424,8 +5437,8 @@ static void sp_3072_mont_reduce_27(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_27(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_27(r, a, b); sp_3072_mont_reduce_27(r, m, mp); @@ -5438,8 +5451,8 @@ static void sp_3072_mont_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_27(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_27(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_27(r, a); sp_3072_mont_reduce_27(r, m, mp); @@ -5547,17 +5560,19 @@ static void sp_3072_cond_add_27(sp_digit* r, const sp_digit* a, static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 57 bits from d1 and top 6 bits from d0. */ - d = (d1 << 6) | (d0 >> 51); + d = (d1 << 6) + (d0 >> 51); r = d / dv; d -= r * dv; /* Up to 7 bits in r */ /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 45) & ((1 << 6) - 1); + d += (d0 >> 45) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5565,7 +5580,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 39) & ((1 << 6) - 1); + d += (d0 >> 39) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5573,7 +5588,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 33) & ((1 << 6) - 1); + d += (d0 >> 33) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5581,7 +5596,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 27) & ((1 << 6) - 1); + d += (d0 >> 27) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5589,7 +5604,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 21) & ((1 << 6) - 1); + d += (d0 >> 21) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5597,7 +5612,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 15) & ((1 << 6) - 1); + d += (d0 >> 15) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5605,7 +5620,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 9) & ((1 << 6) - 1); + d += (d0 >> 9) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5613,7 +5628,7 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 3) & ((1 << 6) - 1); + d += (d0 >> 3) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -5621,10 +5636,11 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Remaining 3 bits from d0. */ r <<= 3; d <<= 3; - d |= d0 & ((1 << 3) - 1); + d += d0 & ((1 << 3) - 1); t = d / dv; r += t; + /* All 57 bits from d1 and top 6 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -5632,66 +5648,60 @@ static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[54], t2d[27 + 1]; + sp_digit t1[3 * 27 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 27 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 27 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 27; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 27; dv = d[26]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 27U); for (i=26; i>=0; i--) { - sp_digit hi; t1[27 + i] += t1[27 + i - 1] >> 57; t1[27 + i - 1] &= 0x1ffffffffffffffL; - hi = t1[27 + i] - (t1[27 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[27 + i]; d1 <<= 57; d1 += t1[27 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_3072_div_word_27(hi, t1[27 + i - 1], dv); + r1 = sp_3072_div_word_27(t1[27 + i], t1[27 + i - 1], dv); #endif sp_3072_mul_d_27(t2, d, r1); (void)sp_3072_sub_27(&t1[i], &t1[i], t2); + sp_3072_norm_27(&t1[i]); t1[27 + i] -= t2[27]; t1[27 + i] += t1[27 + i - 1] >> 57; t1[27 + i - 1] &= 0x1ffffffffffffffL; @@ -5708,7 +5718,7 @@ static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_3072_mul_d_27(t2, d, r1); (void)sp_3072_sub_27(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 27U); + XMEMCPY(r, t1, sizeof(*r) * 54U); for (i=0; i<26; i++) { r[i+1] += r[i] >> 57; r[i] &= 0x1ffffffffffffffL; @@ -5717,10 +5727,9 @@ static int sp_3072_div_27(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -5751,35 +5760,31 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 54]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 27 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 27 * 2); -#else - t[i] = &td[i * 27 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 27U * 2U); } @@ -5834,43 +5839,38 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 54]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 27 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 27 * 2); -#else - t[i] = &td[i * 27 * 2]; -#endif } sp_3072_mont_setup(m, &mp); @@ -5924,47 +5924,40 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 27 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 54) + 54]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 54) + 54), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 54; rt = td + 1728; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 54]; - rt = &td[1728]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_27(norm, m); @@ -6035,7 +6028,7 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 54); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (7 - c); c += 57; @@ -6061,16 +6054,15 @@ static int sp_3072_mod_exp_27(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 3072 bits, just need to subtract. @@ -6342,7 +6334,7 @@ static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp) sp_3072_norm_54(a + 54); -#ifdef WOLFSSL_HAVE_SP_DH +#ifdef WOLFSSL_SP_DH if (mp != 1) { for (i=0; i<53; i++) { mu = (a[i] * mp) & 0x1ffffffffffffffL; @@ -6376,7 +6368,6 @@ static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp) a[i+1] += a[i] >> 57; a[i] &= 0x1ffffffffffffffL; #endif - sp_3072_mont_shift_54(a, a); sp_3072_cond_sub_54(a, a, m, 0 - (((a[53] >> 51) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -6392,8 +6383,8 @@ static void sp_3072_mont_reduce_54(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_54(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_54(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_54(r, a, b); sp_3072_mont_reduce_54(r, m, mp); @@ -6406,8 +6397,8 @@ static void sp_3072_mont_mul_54(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_54(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_54(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_54(r, a); sp_3072_mont_reduce_54(r, m, mp); @@ -6456,17 +6447,19 @@ static void sp_3072_cond_add_54(sp_digit* r, const sp_digit* a, static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 57 bits from d1 and top 6 bits from d0. */ - d = (d1 << 6) | (d0 >> 51); + d = (d1 << 6) + (d0 >> 51); r = d / dv; d -= r * dv; /* Up to 7 bits in r */ /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 45) & ((1 << 6) - 1); + d += (d0 >> 45) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6474,7 +6467,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 39) & ((1 << 6) - 1); + d += (d0 >> 39) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6482,7 +6475,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 33) & ((1 << 6) - 1); + d += (d0 >> 33) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6490,7 +6483,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 27) & ((1 << 6) - 1); + d += (d0 >> 27) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6498,7 +6491,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 21) & ((1 << 6) - 1); + d += (d0 >> 21) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6506,7 +6499,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 15) & ((1 << 6) - 1); + d += (d0 >> 15) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6514,7 +6507,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 9) & ((1 << 6) - 1); + d += (d0 >> 9) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6522,7 +6515,7 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Next 6 bits from d0. */ r <<= 6; d <<= 6; - d |= (d0 >> 3) & ((1 << 6) - 1); + d += (d0 >> 3) & ((1 << 6) - 1); t = d / dv; d -= t * dv; r += t; @@ -6530,10 +6523,11 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Remaining 3 bits from d0. */ r <<= 3; d <<= 3; - d |= d0 & ((1 << 3) - 1); + d += d0 & ((1 << 3) - 1); t = d / dv; r += t; + /* All 57 bits from d1 and top 6 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -6541,66 +6535,60 @@ static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[108], t2d[54 + 1]; + sp_digit t1[3 * 54 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 54 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 54 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 54; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 54; dv = d[53]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 54U); for (i=53; i>=0; i--) { - sp_digit hi; t1[54 + i] += t1[54 + i - 1] >> 57; t1[54 + i - 1] &= 0x1ffffffffffffffL; - hi = t1[54 + i] - (t1[54 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[54 + i]; d1 <<= 57; d1 += t1[54 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_3072_div_word_54(hi, t1[54 + i - 1], dv); + r1 = sp_3072_div_word_54(t1[54 + i], t1[54 + i - 1], dv); #endif sp_3072_mul_d_54(t2, d, r1); (void)sp_3072_sub_54(&t1[i], &t1[i], t2); + sp_3072_norm_54(&t1[i]); t1[54 + i] -= t2[54]; t1[54 + i] += t1[54 + i - 1] >> 57; t1[54 + i - 1] &= 0x1ffffffffffffffL; @@ -6617,7 +6605,7 @@ static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_3072_mul_d_54(t2, d, r1); (void)sp_3072_sub_54(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 54U); + XMEMCPY(r, t1, sizeof(*r) * 108U); for (i=0; i<53; i++) { r[i+1] += r[i] >> 57; r[i] &= 0x1ffffffffffffffL; @@ -6626,10 +6614,9 @@ static int sp_3072_div_54(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -6662,35 +6649,31 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 108]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 54 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 54 * 2); -#else - t[i] = &td[i * 54 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 54U * 2U); } @@ -6745,43 +6728,38 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 108]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 54 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 54 * 2); -#else - t[i] = &td[i * 54 * 2]; -#endif } sp_3072_mont_setup(m, &mp); @@ -6835,47 +6813,40 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 54 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 108) + 108]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 108) + 108), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 108; rt = td + 3456; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 108]; - rt = &td[3456]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_54(norm, m); @@ -6946,7 +6917,7 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 108); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (7 - c); c += 57; @@ -6972,15 +6943,14 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */ /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_RSA @@ -6996,15 +6966,18 @@ static int sp_3072_mod_exp_54(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[54 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -7029,15 +7002,16 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } +#endif if (err == MP_OKAY) { - a = d; r = a + 54 * 2; m = r + 54 * 2; norm = r; @@ -7090,20 +7064,21 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[108], md[54], rd[108]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[54 * 5]; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -7125,27 +7100,20 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { a = d; r = a + 54 * 2; m = r + 54 * 2; - } -#else - a = ad; - m = md; - r = rd; -#endif - if (err == MP_OKAY) { sp_3072_from_bin(a, 54, in, inLen); #if DIGIT_BIT >= 57 e[0] = (sp_digit)em->dp[0]; @@ -7209,10 +7177,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } #endif return err; @@ -7221,7 +7188,7 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #ifndef WOLFSSL_RSA_PUBLIC_ONLY #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) -#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */ /* RSA private key operation. * * in Array of bytes representing the number to exponentiate, base. @@ -7239,14 +7206,18 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a = NULL; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[54 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -7275,13 +7246,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 54; m = a + 108; @@ -7292,20 +7265,34 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_3072_from_mp(m, 54, mm); err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); } + if (err == MP_OKAY) { sp_3072_to_bin(r, out); *outLen = 384; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 54); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 54); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[108], d[54], m[54]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit d[54 * 4]; +#endif + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -7332,7 +7319,20 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + a = d + 54; + m = a + 108; + r = a; + sp_3072_from_bin(a, 54, in, inLen); sp_3072_from_mp(d, 54, dm); sp_3072_from_mp(m, 54, mm); @@ -7344,22 +7344,35 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } - XMEMSET(d, 0, sizeof(sp_digit) * 54); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 54); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #else -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[27 * 11]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -7380,22 +7393,21 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) { + if (a == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - a = t; p = a + 54 * 2; q = p + 27; qi = dq = dp = q + 27; tmpa = qi + 27; tmpb = tmpa + 54; - - r = t + 54; + r = a + 54; sp_3072_from_bin(a, 54, in, inLen); sp_3072_from_mp(p, 27, pm); @@ -7409,6 +7421,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } if (err == MP_OKAY) { (void)sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_norm_27(tmpa); sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); @@ -7426,17 +7439,31 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 27 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 27 * 11); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[54 * 2]; - sp_digit p[27], q[27], dp[27], dq[27], qi[27]; - sp_digit tmpa[54], tmpb[54]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[27 * 13]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -7457,7 +7484,25 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 13, NULL, + DYNAMIC_TYPE_RSA); + if (a == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = a + 54 * 2; + q = p + 27; + dp = q + 27; + dq = dp + 27; + qi = dq + 27; + tmpa = qi + 27; + tmpb = tmpa + 54; + r = a; + sp_3072_from_bin(a, 54, in, inLen); sp_3072_from_mp(p, 27, pm); sp_3072_from_mp(q, 27, qm); @@ -7473,6 +7518,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, if (err == MP_OKAY) { (void)sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_norm_27(tmpa); sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); sp_3072_mul_27(tmpa, tmpa, qi); @@ -7488,16 +7534,18 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); - XMEMSET(dq, 0, sizeof(dq)); - XMEMSET(qi, 0, sizeof(qi)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) +if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 27 * 13); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } @@ -7521,17 +7569,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 54; mp_clamp(r); #elif DIGIT_BIT < 57 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 54; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 57) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -7544,14 +7594,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 54; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 57 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -7578,15 +7630,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[54 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 3072) { @@ -7602,16 +7658,16 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 54 * 2; m = e + 54; r = b; @@ -7627,21 +7683,27 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_3072_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 54U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 54U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[108], ed[54], md[54]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[54 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -7658,26 +7720,19 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 54 * 2; - m = e + 54; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 54 * 2; + m = e + 54; + r = b; + sp_3072_from_mp(b, 54, base); sp_3072_from_mp(e, 54, exp); sp_3072_from_mp(m, 54, mod); @@ -7690,14 +7745,17 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 54U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 54U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 54U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -7706,7 +7764,8 @@ int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) #ifdef WOLFSSL_HAVE_SP_DH #ifdef HAVE_FFDHE_3072 -SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, const sp_digit* a, + byte n) { #ifdef WOLFSSL_SP_SMALL int i; @@ -7716,7 +7775,8 @@ SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, sp_digit* a, byte n) r[i] = ((a[i] << n) | (a[i-1] >> (57 - n))) & 0x1ffffffffffffffL; } #else - sp_int_digit s, t; + sp_int_digit s; + sp_int_digit t; s = (sp_int_digit)a[53]; r[54] = s >> (57U - n); @@ -7841,35 +7901,31 @@ SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, sp_digit* a, byte n) static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[163]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 163, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 108; XMEMSET(td, 0, sizeof(sp_digit) * 163); -#else - tmp = &td[108]; - XMEMSET(td, 0, sizeof(td)); -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_54(norm, m); @@ -7895,7 +7951,7 @@ static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const n <<= 5; c -= 5; sp_3072_lshift_54(r, norm, (byte)y); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (7 - c); c += 57; @@ -7928,9 +7984,8 @@ static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -7950,16 +8005,19 @@ static int sp_3072_mod_exp_2_54(sp_digit* r, const sp_digit* e, int bits, const * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[54 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; if (mp_count_bits(base) > 3072) { @@ -7975,15 +8033,15 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 54 * 2; m = e + 54; r = b; @@ -8011,21 +8069,27 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, XMEMMOVE(out, out + i, *outLen); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 54U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 54U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[108], ed[54], md[54]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[54 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; int err = MP_OKAY; @@ -8042,26 +8106,20 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 54 * 2; - m = e + 54; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 54 * 2; + m = e + 54; + r = b; + sp_3072_from_mp(b, 54, base); sp_3072_from_bin(e, 54, exp, expLen); sp_3072_from_mp(m, 54, mod); @@ -8083,19 +8141,23 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384U && out[i] == 0U; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 54U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 54U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 54U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -8111,15 +8173,19 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[27 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 1536) { @@ -8135,16 +8201,16 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 27 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 27 * 2; m = e + 27; r = b; @@ -8161,21 +8227,27 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_3072_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 27U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 54U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[54], ed[27], md[27]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[27 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -8192,26 +8264,19 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 27 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 27 * 2; - m = e + 27; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 27 * 2; + m = e + 27; + r = b; + sp_3072_from_mp(b, 27, base); sp_3072_from_mp(e, 27, exp); sp_3072_from_mp(m, 27, mod); @@ -8225,20 +8290,23 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 27U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 27U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 54U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -8252,7 +8320,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -8294,7 +8363,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 53 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -8328,7 +8398,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -8367,7 +8439,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_4096_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<77; i++) { r[i+1] += r[i] >> 53; @@ -9095,7 +9170,9 @@ SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_4096_mul_78(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[77]) * b[77]; @@ -9127,7 +9204,9 @@ SP_NOINLINE static void sp_4096_mul_78(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_4096_sqr_78(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[77]) * a[77]; @@ -9241,7 +9320,9 @@ SP_NOINLINE static int sp_4096_sub_39(sp_digit* r, const sp_digit* a, SP_NOINLINE static void sp_4096_mul_39(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[38]) * b[38]; @@ -9273,7 +9354,9 @@ SP_NOINLINE static void sp_4096_mul_39(sp_digit* r, const sp_digit* a, */ SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[38]) * a[38]; @@ -9303,8 +9386,8 @@ SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -9313,7 +9396,8 @@ SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a) */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -9673,7 +9757,6 @@ static void sp_4096_mont_reduce_39(sp_digit* a, const sp_digit* m, sp_digit mp) sp_4096_mul_add_39(a+i, m, mu); a[i+1] += a[i] >> 53; a[i] &= 0x1fffffffffffffL; - sp_4096_mont_shift_39(a, a); sp_4096_cond_sub_39(a, a, m, 0 - (((a[38] >> 34) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -9689,8 +9772,8 @@ static void sp_4096_mont_reduce_39(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_39(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_39(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_39(r, a, b); sp_4096_mont_reduce_39(r, m, mp); @@ -9703,8 +9786,8 @@ static void sp_4096_mont_mul_39(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_39(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_39(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_39(r, a); sp_4096_mont_reduce_39(r, m, mp); @@ -9812,26 +9895,8 @@ static void sp_4096_cond_add_39(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_add_39(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 39; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -9841,21 +9906,21 @@ SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<32; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (53 - n))) & 0x1fffffffffffffL; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (53 - n))) & 0x1fffffffffffffL; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (53 - n))) & 0x1fffffffffffffL; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (53 - n))) & 0x1fffffffffffffL; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (53 - n))) & 0x1fffffffffffffL; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (53 - n))) & 0x1fffffffffffffL; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (53 - n))) & 0x1fffffffffffffL; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (53 - n))) & 0x1fffffffffffffL; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (53 - n)) & 0x1fffffffffffffL); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (53 - n)) & 0x1fffffffffffffL); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (53 - n)) & 0x1fffffffffffffL); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (53 - n)) & 0x1fffffffffffffL); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (53 - n)) & 0x1fffffffffffffL); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (53 - n)) & 0x1fffffffffffffL); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (53 - n)) & 0x1fffffffffffffL); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (53 - n)) & 0x1fffffffffffffL); } - r[32] = ((a[32] >> n) | (a[33] << (53 - n))) & 0x1fffffffffffffL; - r[33] = ((a[33] >> n) | (a[34] << (53 - n))) & 0x1fffffffffffffL; - r[34] = ((a[34] >> n) | (a[35] << (53 - n))) & 0x1fffffffffffffL; - r[35] = ((a[35] >> n) | (a[36] << (53 - n))) & 0x1fffffffffffffL; - r[36] = ((a[36] >> n) | (a[37] << (53 - n))) & 0x1fffffffffffffL; - r[37] = ((a[37] >> n) | (a[38] << (53 - n))) & 0x1fffffffffffffL; + r[32] = (a[32] >> n) | ((a[33] << (53 - n)) & 0x1fffffffffffffL); + r[33] = (a[33] >> n) | ((a[34] << (53 - n)) & 0x1fffffffffffffL); + r[34] = (a[34] >> n) | ((a[35] << (53 - n)) & 0x1fffffffffffffL); + r[35] = (a[35] >> n) | ((a[36] << (53 - n)) & 0x1fffffffffffffL); + r[36] = (a[36] >> n) | ((a[37] << (53 - n)) & 0x1fffffffffffffL); + r[37] = (a[37] >> n) | ((a[38] << (53 - n)) & 0x1fffffffffffffL); #endif r[38] = a[38] >> n; } @@ -9864,17 +9929,19 @@ SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 53 bits from d1 and top 10 bits from d0. */ - d = (d1 << 10) | (d0 >> 43); + d = (d1 << 10) + (d0 >> 43); r = d / dv; d -= r * dv; /* Up to 11 bits in r */ /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 33) & ((1 << 10) - 1); + d += (d0 >> 33) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -9882,7 +9949,7 @@ static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 23) & ((1 << 10) - 1); + d += (d0 >> 23) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -9890,7 +9957,7 @@ static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 13) & ((1 << 10) - 1); + d += (d0 >> 13) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -9898,7 +9965,7 @@ static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 3) & ((1 << 10) - 1); + d += (d0 >> 3) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -9906,10 +9973,11 @@ static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, /* Remaining 3 bits from d0. */ r <<= 3; d <<= 3; - d |= d0 & ((1 << 3) - 1); + d += d0 & ((1 << 3) - 1); t = d / dv; r += t; + /* All 53 bits from d1 and top 10 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -9917,72 +9985,65 @@ static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[78 + 1], t2d[39 + 1], sdd[39 + 1]; + sp_digit t1[4 * 39 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 39 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 39 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 78 + 1; + t2 = t1 + 78 + 1; sd = t2 + 39 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_4096_mul_d_39(sd, d, 1L << 19); sp_4096_mul_d_78(t1, a, 1L << 19); dv = sd[38]; + t1[39 + 39] += t1[39 + 39 - 1] >> 53; + t1[39 + 39 - 1] &= 0x1fffffffffffffL; for (i=39; i>=0; i--) { - sp_digit hi; - t1[39 + i] += t1[39 + i - 1] >> 53; - t1[39 + i - 1] &= 0x1fffffffffffffL; - hi = t1[39 + i] - (t1[39 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[39 + i]; d1 <<= 53; d1 += t1[39 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_4096_div_word_39(hi, t1[39 + i - 1], dv); + r1 = sp_4096_div_word_39(t1[39 + i], t1[39 + i - 1], dv); #endif sp_4096_mul_d_39(t2, sd, r1); (void)sp_4096_sub_39(&t1[i], &t1[i], t2); + sp_4096_norm_39(&t1[i]); t1[39 + i] -= t2[39]; t1[39 + i] += t1[39 + i - 1] >> 53; t1[39 + i - 1] &= 0x1fffffffffffffL; @@ -9999,7 +10060,7 @@ static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_mul_d_39(t2, sd, r1); sp_4096_sub_39(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 39U); + XMEMCPY(r, t1, sizeof(*r) * 78U); for (i=0; i<38; i++) { r[i+1] += r[i] >> 53; r[i] &= 0x1fffffffffffffL; @@ -10011,10 +10072,9 @@ static int sp_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_rshift_39(r, r, 19); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -10045,35 +10105,31 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 78]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 39 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 39 * 2); -#else - t[i] = &td[i * 39 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 39U * 2U); } @@ -10128,43 +10184,38 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 78]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 39 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 39 * 2); -#else - t[i] = &td[i * 39 * 2]; -#endif } sp_4096_mont_setup(m, &mp); @@ -10218,47 +10269,40 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 39 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 78) + 78]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 78) + 78), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 78; rt = td + 2496; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 78]; - rt = &td[2496]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_39(norm, m); @@ -10329,7 +10373,7 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 78); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (11 - c); c += 53; @@ -10355,17 +10399,16 @@ static int sp_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ -#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */ /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 4096 bits, just need to subtract. @@ -10637,7 +10680,7 @@ static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp) sp_4096_norm_78(a + 78); -#ifdef WOLFSSL_HAVE_SP_DH +#ifdef WOLFSSL_SP_DH if (mp != 1) { for (i=0; i<77; i++) { mu = (a[i] * mp) & 0x1fffffffffffffL; @@ -10671,7 +10714,6 @@ static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp) a[i+1] += a[i] >> 53; a[i] &= 0x1fffffffffffffL; #endif - sp_4096_mont_shift_78(a, a); sp_4096_cond_sub_78(a, a, m, 0 - (((a[77] >> 15) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -10687,8 +10729,8 @@ static void sp_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_78(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_78(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_78(r, a, b); sp_4096_mont_reduce_78(r, m, mp); @@ -10701,8 +10743,8 @@ static void sp_4096_mont_mul_78(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_78(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_78(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_78(r, a); sp_4096_mont_reduce_78(r, m, mp); @@ -10800,46 +10842,8 @@ static void sp_4096_cond_add_78(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#ifdef WOLFSSL_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 78; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#endif -#ifdef WOLFSSL_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_4096_add_78(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 78; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#endif -SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, const sp_digit* a, + byte n) { int i; @@ -10849,20 +10853,20 @@ SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n) } #else for (i=0; i<72; i += 8) { - r[i+0] = ((a[i+0] >> n) | (a[i+1] << (53 - n))) & 0x1fffffffffffffL; - r[i+1] = ((a[i+1] >> n) | (a[i+2] << (53 - n))) & 0x1fffffffffffffL; - r[i+2] = ((a[i+2] >> n) | (a[i+3] << (53 - n))) & 0x1fffffffffffffL; - r[i+3] = ((a[i+3] >> n) | (a[i+4] << (53 - n))) & 0x1fffffffffffffL; - r[i+4] = ((a[i+4] >> n) | (a[i+5] << (53 - n))) & 0x1fffffffffffffL; - r[i+5] = ((a[i+5] >> n) | (a[i+6] << (53 - n))) & 0x1fffffffffffffL; - r[i+6] = ((a[i+6] >> n) | (a[i+7] << (53 - n))) & 0x1fffffffffffffL; - r[i+7] = ((a[i+7] >> n) | (a[i+8] << (53 - n))) & 0x1fffffffffffffL; + r[i+0] = (a[i+0] >> n) | ((a[i+1] << (53 - n)) & 0x1fffffffffffffL); + r[i+1] = (a[i+1] >> n) | ((a[i+2] << (53 - n)) & 0x1fffffffffffffL); + r[i+2] = (a[i+2] >> n) | ((a[i+3] << (53 - n)) & 0x1fffffffffffffL); + r[i+3] = (a[i+3] >> n) | ((a[i+4] << (53 - n)) & 0x1fffffffffffffL); + r[i+4] = (a[i+4] >> n) | ((a[i+5] << (53 - n)) & 0x1fffffffffffffL); + r[i+5] = (a[i+5] >> n) | ((a[i+6] << (53 - n)) & 0x1fffffffffffffL); + r[i+6] = (a[i+6] >> n) | ((a[i+7] << (53 - n)) & 0x1fffffffffffffL); + r[i+7] = (a[i+7] >> n) | ((a[i+8] << (53 - n)) & 0x1fffffffffffffL); } - r[72] = ((a[72] >> n) | (a[73] << (53 - n))) & 0x1fffffffffffffL; - r[73] = ((a[73] >> n) | (a[74] << (53 - n))) & 0x1fffffffffffffL; - r[74] = ((a[74] >> n) | (a[75] << (53 - n))) & 0x1fffffffffffffL; - r[75] = ((a[75] >> n) | (a[76] << (53 - n))) & 0x1fffffffffffffL; - r[76] = ((a[76] >> n) | (a[77] << (53 - n))) & 0x1fffffffffffffL; + r[72] = (a[72] >> n) | ((a[73] << (53 - n)) & 0x1fffffffffffffL); + r[73] = (a[73] >> n) | ((a[74] << (53 - n)) & 0x1fffffffffffffL); + r[74] = (a[74] >> n) | ((a[75] << (53 - n)) & 0x1fffffffffffffL); + r[75] = (a[75] >> n) | ((a[76] << (53 - n)) & 0x1fffffffffffffL); + r[76] = (a[76] >> n) | ((a[77] << (53 - n)) & 0x1fffffffffffffL); #endif r[77] = a[77] >> n; } @@ -10871,17 +10875,19 @@ SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n) static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 53 bits from d1 and top 10 bits from d0. */ - d = (d1 << 10) | (d0 >> 43); + d = (d1 << 10) + (d0 >> 43); r = d / dv; d -= r * dv; /* Up to 11 bits in r */ /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 33) & ((1 << 10) - 1); + d += (d0 >> 33) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -10889,7 +10895,7 @@ static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 23) & ((1 << 10) - 1); + d += (d0 >> 23) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -10897,7 +10903,7 @@ static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 13) & ((1 << 10) - 1); + d += (d0 >> 13) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -10905,7 +10911,7 @@ static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, /* Next 10 bits from d0. */ r <<= 10; d <<= 10; - d |= (d0 >> 3) & ((1 << 10) - 1); + d += (d0 >> 3) & ((1 << 10) - 1); t = d / dv; d -= t * dv; r += t; @@ -10913,10 +10919,11 @@ static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, /* Remaining 3 bits from d0. */ r <<= 3; d <<= 3; - d |= d0 & ((1 << 3) - 1); + d += d0 & ((1 << 3) - 1); t = d / dv; r += t; + /* All 53 bits from d1 and top 10 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -10924,72 +10931,65 @@ static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Full implementation. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[156 + 1], t2d[78 + 1], sdd[78 + 1]; + sp_digit t1[4 * 78 + 3]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* sd; + sp_digit* t2 = NULL; + sp_digit* sd = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 78 + 3), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 78 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif (void)m; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 156 + 1; + t2 = t1 + 156 + 1; sd = t2 + 78 + 1; -#else - t1 = t1d; - t2 = t2d; - sd = sdd; -#endif sp_4096_mul_d_78(sd, d, 1L << 38); sp_4096_mul_d_156(t1, a, 1L << 38); dv = sd[77]; + t1[78 + 78] += t1[78 + 78 - 1] >> 53; + t1[78 + 78 - 1] &= 0x1fffffffffffffL; for (i=78; i>=0; i--) { - sp_digit hi; - t1[78 + i] += t1[78 + i - 1] >> 53; - t1[78 + i - 1] &= 0x1fffffffffffffL; - hi = t1[78 + i] - (t1[78 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[78 + i]; d1 <<= 53; d1 += t1[78 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_4096_div_word_78(hi, t1[78 + i - 1], dv); + r1 = sp_4096_div_word_78(t1[78 + i], t1[78 + i - 1], dv); #endif sp_4096_mul_d_78(t2, sd, r1); (void)sp_4096_sub_78(&t1[i], &t1[i], t2); + sp_4096_norm_78(&t1[i]); t1[78 + i] -= t2[78]; t1[78 + i] += t1[78 + i - 1] >> 53; t1[78 + i - 1] &= 0x1fffffffffffffL; @@ -11006,7 +11006,7 @@ static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_mul_d_78(t2, sd, r1); sp_4096_sub_78(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 78U); + XMEMCPY(r, t1, sizeof(*r) * 156U); for (i=0; i<77; i++) { r[i+1] += r[i] >> 53; r[i] &= 0x1fffffffffffffL; @@ -11018,10 +11018,9 @@ static int sp_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_4096_rshift_78(r, r, 38); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -11054,35 +11053,31 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, const sp_digit* m, int reduceA) { #ifdef WOLFSSL_SP_SMALL -#if !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; #else sp_digit td[3 * 156]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#if !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 78 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 78 * 2); -#else - t[i] = &td[i * 78 * 2]; -#endif XMEMSET(t[i], 0, sizeof(sp_digit) * 78U * 2U); } @@ -11137,43 +11132,38 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, } -#if !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #elif !defined(WC_NO_CACHE_RESISTANT) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[3 * 156]; #endif - sp_digit* t[3]; - sp_digit* norm; + sp_digit* t[3] = {0, 0, 0}; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 78 * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<3; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + (i * 78 * 2); -#else - t[i] = &td[i * 78 * 2]; -#endif } sp_4096_mont_setup(m, &mp); @@ -11227,47 +11217,40 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, XMEMCPY(r, t[0], sizeof(*r) * 78 * 2); } -#ifdef WOLFSSL_SMALL_STACK - if (td != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #else #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[(32 * 156) + 156]; #endif sp_digit* t[32]; - sp_digit* rt; - sp_digit* norm; + sp_digit* rt = NULL; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 156) + 156), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) for (i=0; i<32; i++) t[i] = td + i * 156; rt = td + 4992; -#else - for (i=0; i<32; i++) - t[i] = &td[i * 156]; - rt = &td[4992]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_78(norm, m); @@ -11338,7 +11321,7 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, n <<= 5; c -= 5; XMEMCPY(rt, t[y], sizeof(sp_digit) * 156); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (11 - c); c += 53; @@ -11364,15 +11347,14 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; #endif } -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */ /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_RSA @@ -11388,15 +11370,18 @@ static int sp_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[78 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit e[1] = {0}; sp_digit mp; int i; @@ -11421,15 +11406,16 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } +#endif if (err == MP_OKAY) { - a = d; r = a + 78 * 2; m = r + 78 * 2; norm = r; @@ -11482,20 +11468,21 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[156], md[78], rd[156]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[78 * 5]; #endif - sp_digit* a; - sp_digit* m; - sp_digit* r; + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; sp_digit e[1] = {0}; int err = MP_OKAY; @@ -11517,27 +11504,20 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { a = d; r = a + 78 * 2; m = r + 78 * 2; - } -#else - a = ad; - m = md; - r = rd; -#endif - if (err == MP_OKAY) { sp_4096_from_bin(a, 78, in, inLen); #if DIGIT_BIT >= 53 e[0] = (sp_digit)em->dp[0]; @@ -11601,10 +11581,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } #endif return err; @@ -11613,7 +11592,7 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, #ifndef WOLFSSL_RSA_PUBLIC_ONLY #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) -#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */ /* RSA private key operation. * * in Array of bytes representing the number to exponentiate, base. @@ -11631,14 +11610,18 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* a = NULL; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[78 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -11667,13 +11650,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 78; m = a + 156; @@ -11684,20 +11669,34 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_4096_from_mp(m, 78, mm); err = sp_4096_mod_exp_78(r, a, d, 4096, m, 0); } + if (err == MP_OKAY) { sp_4096_to_bin(r, out); *outLen = 512; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 78); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 78); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[156], d[78], m[78]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit d[78 * 4]; +#endif + sp_digit* a = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)pm; @@ -11724,7 +11723,20 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + a = d + 78; + m = a + 156; + r = a; + sp_4096_from_bin(a, 78, in, inLen); sp_4096_from_mp(d, 78, dm); sp_4096_from_mp(m, 78, mm); @@ -11736,22 +11748,35 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } - XMEMSET(d, 0, sizeof(sp_digit) * 78); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 78); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #else -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* t = NULL; - sp_digit* a; - sp_digit* p; - sp_digit* q; - sp_digit* dp; - sp_digit* dq; - sp_digit* qi; - sp_digit* tmpa; - sp_digit* tmpb; - sp_digit* r; +#if defined(WOLFSSL_SP_SMALL) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[39 * 11]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -11772,22 +11797,21 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) { + if (a == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - a = t; p = a + 78 * 2; q = p + 39; qi = dq = dp = q + 39; tmpa = qi + 39; tmpb = tmpa + 78; - - r = t + 78; + r = a + 78; sp_4096_from_bin(a, 78, in, inLen); sp_4096_from_mp(p, 39, pm); @@ -11801,6 +11825,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } if (err == MP_OKAY) { (void)sp_4096_sub_39(tmpa, tmpa, tmpb); + sp_4096_norm_39(tmpa); sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); @@ -11818,17 +11843,31 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 39 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 39 * 11); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else - sp_digit a[78 * 2]; - sp_digit p[39], q[39], dp[39], dq[39], qi[39]; - sp_digit tmpa[78], tmpb[78]; - sp_digit* r = a; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; +#else + sp_digit a[39 * 13]; +#endif + sp_digit* p = NULL; + sp_digit* q = NULL; + sp_digit* dp = NULL; + sp_digit* dq = NULL; + sp_digit* qi = NULL; + sp_digit* tmpa = NULL; + sp_digit* tmpb = NULL; + sp_digit* r = NULL; int err = MP_OKAY; (void)dm; @@ -11849,7 +11888,25 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 13, NULL, + DYNAMIC_TYPE_RSA); + if (a == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = a + 78 * 2; + q = p + 39; + dp = q + 39; + dq = dp + 39; + qi = dq + 39; + tmpa = qi + 39; + tmpb = tmpa + 78; + r = a; + sp_4096_from_bin(a, 78, in, inLen); sp_4096_from_mp(p, 39, pm); sp_4096_from_mp(q, 39, qm); @@ -11865,6 +11922,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, if (err == MP_OKAY) { (void)sp_4096_sub_39(tmpa, tmpa, tmpb); + sp_4096_norm_39(tmpa); sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); sp_4096_mul_39(tmpa, tmpa, qi); @@ -11880,16 +11938,18 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); - XMEMSET(dq, 0, sizeof(dq)); - XMEMSET(qi, 0, sizeof(qi)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) +if (a != NULL) +#endif + { + ForceZero(a, sizeof(sp_digit) * 39 * 13); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; -#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* WOLFSSL_SP_SMALL */ #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } @@ -11913,17 +11973,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 78; mp_clamp(r); #elif DIGIT_BIT < 53 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 78; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 53) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -11936,14 +11998,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 78; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 53 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -11970,15 +12034,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[78 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int expBits = mp_count_bits(exp); if (mp_count_bits(base) > 4096) { @@ -11994,16 +12062,16 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } - +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 78 * 2; m = e + 78; r = b; @@ -12019,21 +12087,27 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = sp_4096_to_mp(r, res); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 78U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 78U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[156], ed[78], md[78]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[78 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; int err = MP_OKAY; int expBits = mp_count_bits(exp); @@ -12050,26 +12124,19 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 78 * 2; - m = e + 78; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 78 * 2; + m = e + 78; + r = b; + sp_4096_from_mp(b, 78, base); sp_4096_from_mp(e, 78, exp); sp_4096_from_mp(m, 78, mod); @@ -12082,14 +12149,17 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 78U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 78U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 78U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif @@ -12098,7 +12168,8 @@ int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) #ifdef WOLFSSL_HAVE_SP_DH #ifdef HAVE_FFDHE_4096 -SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, sp_digit* a, byte n) +SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, const sp_digit* a, + byte n) { #ifdef WOLFSSL_SP_SMALL int i; @@ -12108,7 +12179,8 @@ SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, sp_digit* a, byte n) r[i] = ((a[i] << n) | (a[i-1] >> (53 - n))) & 0x1fffffffffffffL; } #else - sp_int_digit s, t; + sp_int_digit s; + sp_int_digit t; s = (sp_int_digit)a[77]; r[78] = s >> (53U - n); @@ -12281,35 +12353,31 @@ SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, sp_digit* a, byte n) static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[235]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 235, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 156; XMEMSET(td, 0, sizeof(sp_digit) * 235); -#else - tmp = &td[156]; - XMEMSET(td, 0, sizeof(td)); -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_78(norm, m); @@ -12335,7 +12403,7 @@ static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const n <<= 5; c -= 5; sp_4096_lshift_78(r, norm, (byte)y); - for (; i>=0 || c>=5; ) { + while ((i >= 0) || (c >= 5)) { if (c < 5) { n |= e[i--] << (11 - c); c += 53; @@ -12368,9 +12436,8 @@ static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -12390,16 +12457,19 @@ static int sp_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { #ifdef WOLFSSL_SP_SMALL int err = MP_OKAY; - sp_digit* d = NULL; - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; +#else + sp_digit b[78 * 4]; +#endif + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; if (mp_count_bits(base) > 4096) { @@ -12415,15 +12485,15 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) { + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; - } } +#endif if (err == MP_OKAY) { - b = d; e = b + 78 * 2; m = e + 78; r = b; @@ -12451,21 +12521,27 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, XMEMMOVE(out, out + i, *outLen); } - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 78U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) +#endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 78U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif } return err; #else -#ifndef WOLFSSL_SMALL_STACK - sp_digit bd[156], ed[78], md[78]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* b = NULL; #else - sp_digit* d = NULL; + sp_digit b[78 * 4]; #endif - sp_digit* b; - sp_digit* e; - sp_digit* m; - sp_digit* r; + sp_digit* e = NULL; + sp_digit* m = NULL; + sp_digit* r = NULL; word32 i; int err = MP_OKAY; @@ -12482,26 +12558,20 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, err = MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); - if (d == NULL) + b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, + DYNAMIC_TYPE_DH); + if (b == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - b = d; - e = b + 78 * 2; - m = e + 78; - r = b; - } -#else - r = b = bd; - e = ed; - m = md; #endif if (err == MP_OKAY) { + e = b + 78 * 2; + m = e + 78; + r = b; + sp_4096_from_mp(b, 78, base); sp_4096_from_bin(e, 78, exp, expLen); sp_4096_from_mp(m, 78, mod); @@ -12523,38 +12593,46 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512U && out[i] == 0U; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); } -#ifdef WOLFSSL_SMALL_STACK - if (d != NULL) { - XMEMSET(e, 0, sizeof(sp_digit) * 78U); - XFREE(d, NULL, DYNAMIC_TYPE_DH); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 78U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (b != NULL) #endif + { + /* only "e" is sensitive and needs zeroized */ + if (e != NULL) + ForceZero(e, sizeof(sp_digit) * 78U); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(b, NULL, DYNAMIC_TYPE_DH); + #endif + } return err; #endif } #endif /* WOLFSSL_HAVE_SP_DH */ -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 5]; + /* Y ordinate of point. */ sp_digit y[2 * 5]; + /* Z ordinate of point. */ sp_digit z[2 * 5]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -12624,353 +12702,6 @@ static const sp_digit p256_b[5] = { }; #endif -static int sp_256_point_new_ex_5(void* heap, sp_point_256* sp, sp_point_256** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_5(sp_point_256* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_256_mod_mul_norm_5(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* td; -#else - int64_t td[8]; - int64_t a32d[8]; -#endif - int64_t* t; - int64_t* a32; - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); - if (td == NULL) { - return MEMORY_E; - } -#endif - - if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = td; - a32 = td + 8; -#else - t = td; - a32 = a32d; -#endif - - a32[0] = (sp_digit)(a[0]) & 0xffffffffL; - a32[1] = (sp_digit)(a[0] >> 32U); - a32[1] |= (sp_digit)(a[1] << 20U); - a32[1] &= 0xffffffffL; - a32[2] = (sp_digit)(a[1] >> 12U) & 0xffffffffL; - a32[3] = (sp_digit)(a[1] >> 44U); - a32[3] |= (sp_digit)(a[2] << 8U); - a32[3] &= 0xffffffffL; - a32[4] = (sp_digit)(a[2] >> 24U); - a32[4] |= (sp_digit)(a[3] << 28U); - a32[4] &= 0xffffffffL; - a32[5] = (sp_digit)(a[3] >> 4U) & 0xffffffffL; - a32[6] = (sp_digit)(a[3] >> 36U); - a32[6] |= (sp_digit)(a[4] << 16U); - a32[6] &= 0xffffffffL; - a32[7] = (sp_digit)(a[4] >> 16U) & 0xffffffffL; - - /* 1 1 0 -1 -1 -1 -1 0 */ - t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; - /* 0 1 1 0 -1 -1 -1 -1 */ - t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; - /* 0 0 1 1 0 -1 -1 -1 */ - t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; - /* -1 -1 0 2 2 1 0 -1 */ - t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; - /* 0 -1 -1 0 2 2 1 0 */ - t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; - /* 0 0 -1 -1 0 2 2 1 */ - t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; - /* -1 -1 0 0 0 1 3 2 */ - t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; - /* 1 0 -1 -1 -1 -1 0 3 */ - t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; - - t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; - t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; - t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; - t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; - t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; - t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; - t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; - o = t[7] >> 32U; t[7] &= 0xffffffffL; - t[0] += o; - t[3] -= o; - t[6] -= o; - t[7] += o; - t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; - t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; - t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; - t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; - t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; - t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; - t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; - - r[0] = t[0]; - r[0] |= t[1] << 32U; - r[0] &= 0xfffffffffffffLL; - r[1] = (sp_digit)(t[1] >> 20); - r[1] |= t[2] << 12U; - r[1] |= t[3] << 44U; - r[1] &= 0xfffffffffffffLL; - r[2] = (sp_digit)(t[3] >> 8); - r[2] |= t[4] << 24U; - r[2] &= 0xfffffffffffffLL; - r[3] = (sp_digit)(t[4] >> 28); - r[3] |= t[5] << 4U; - r[3] |= t[6] << 36U; - r[3] &= 0xfffffffffffffLL; - r[4] = (sp_digit)(t[6] >> 16); - r[4] |= t[7] << 16U; - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_ECC); - } -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 52 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 52 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xfffffffffffffL; - s = 52U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 52U) <= (word32)DIGIT_BIT) { - s += 52U; - r[j] &= 0xfffffffffffffL; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 52) { - r[j] &= 0xfffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 52 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_256. - * - * p Point of type sp_point_256 (result). - * pm Point of type ecc_point. - */ -static void sp_256_point_from_ecc_point_5(sp_point_256* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_256_from_mp(p->x, 5, pm->x); - sp_256_from_mp(p->y, 5, pm->y); - sp_256_from_mp(p->z, 5, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_256_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 52 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 5); - r->used = 5; - mp_clamp(r); -#elif DIGIT_BIT < 52 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 5; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 52) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 52 - s; - } - r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 5; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 52 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 52 - s; - } - else { - s += 52; - } - } - r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_256 to type ecc_point. - * - * p Point of type sp_point_256. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_256_point_to_ecc_point_5(const sp_point_256* p, ecc_point* pm) -{ - int err; - - err = sp_256_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_256_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(p->z, pm->z); - } - - return err; -} - #ifdef WOLFSSL_SP_SMALL /* Multiply a and b into r. (r = a * b) * @@ -12981,7 +12712,9 @@ static int sp_256_point_to_ecc_point_5(const sp_point_256* p, ecc_point* pm) SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[4]) * b[4]; @@ -13055,6 +12788,351 @@ SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a, } #endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) +{ + int i; + int j; + int k; + int128_t c; + + c = ((int128_t)a[4]) * a[4]; + r[9] = (sp_digit)(c >> 52); + c = (c & 0xfffffffffffffL) << 52; + for (k = 7; k >= 0; k--) { + for (i = 4; i >= 0; i--) { + j = k - i; + if (j >= 5 || i <= j) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) { + c += ((int128_t)a[i]) * a[i]; + } + + r[k + 2] += (sp_digit)(c >> 104); + r[k + 1] = (sp_digit)((c >> 52) & 0xfffffffffffffL); + c = (c & 0xfffffffffffffL) << 52; + } + r[0] = (sp_digit)(c >> 52); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = ((int128_t)a[ 4]) * a[ 4]; + + t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffL; + t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffL; + t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffL; + t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffL; + t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffL; + t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffL; + t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffL; + t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffL; + r[9] = (sp_digit)(t8 >> 52); + r[8] = t8 & 0xfffffffffffffL; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 5; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 5; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 52 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 52 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xfffffffffffffL; + s = 52U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 52U) <= (word32)DIGIT_BIT) { + s += 52U; + r[j] &= 0xfffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 52) { + r[j] &= 0xfffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 52 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_5(sp_point_256* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 5, pm->x); + sp_256_from_mp(p->y, 5, pm->y); + sp_256_from_mp(p->z, 5, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 52 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 5); + r->used = 5; + mp_clamp(r); +#elif DIGIT_BIT < 52 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 5; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 52) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 52 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 5; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 52 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 52 - s; + } + else { + s += 52; + } + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_256 to type ecc_point. + * + * p Point of type sp_point_256. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_5(const sp_point_256* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pm->z); + } + + return err; +} + #define sp_256_mont_reduce_order_5 sp_256_mont_reduce_5 /* Compare a with b in constant time. @@ -13249,87 +13327,13 @@ static void sp_256_mont_reduce_5(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_256_mont_mul_5(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_256_mont_mul_5(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_256_mul_5(r, a, b); sp_256_mont_reduce_5(r, m, mp); } -#ifdef WOLFSSL_SP_SMALL -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) -{ - int i, j, k; - int128_t c; - - c = ((int128_t)a[4]) * a[4]; - r[9] = (sp_digit)(c >> 52); - c = (c & 0xfffffffffffffL) << 52; - for (k = 7; k >= 0; k--) { - for (i = 4; i >= 0; i--) { - j = k - i; - if (j >= 5 || i <= j) { - break; - } - if (j < 0) { - continue; - } - - c += ((int128_t)a[i]) * a[j] * 2; - } - if (i == j) { - c += ((int128_t)a[i]) * a[i]; - } - - r[k + 2] += (sp_digit)(c >> 104); - r[k + 1] = (sp_digit)((c >> 52) & 0xfffffffffffffL); - c = (c & 0xfffffffffffffL) << 52; - } - r[0] = (sp_digit)(c >> 52); -} - -#else -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) -{ - int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; - int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; - int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 - + ((int128_t)a[ 1]) * a[ 1]; - int128_t t3 = (((int128_t)a[ 0]) * a[ 3] - + ((int128_t)a[ 1]) * a[ 2]) * 2; - int128_t t4 = (((int128_t)a[ 0]) * a[ 4] - + ((int128_t)a[ 1]) * a[ 3]) * 2 - + ((int128_t)a[ 2]) * a[ 2]; - int128_t t5 = (((int128_t)a[ 1]) * a[ 4] - + ((int128_t)a[ 2]) * a[ 3]) * 2; - int128_t t6 = (((int128_t)a[ 2]) * a[ 4]) * 2 - + ((int128_t)a[ 3]) * a[ 3]; - int128_t t7 = (((int128_t)a[ 3]) * a[ 4]) * 2; - int128_t t8 = ((int128_t)a[ 4]) * a[ 4]; - - t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffL; - t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffL; - t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffL; - t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffL; - t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffL; - t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffL; - t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffL; - t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffL; - r[9] = (sp_digit)(t8 >> 52); - r[8] = t8 & 0xfffffffffffffL; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -13337,8 +13341,8 @@ SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_256_mont_sqr_5(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_256_mont_sqr_5(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_256_sqr_5(r, a); sp_256_mont_reduce_5(r, m, mp); @@ -13362,7 +13366,7 @@ static void sp_256_mont_sqr_n_5(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint64_t p256_mod_minus_2[4] = { @@ -13446,7 +13450,8 @@ static void sp_256_mont_inv_5(sp_digit* r, const sp_digit* a, sp_digit* td) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_5(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_5(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*5; @@ -13482,44 +13487,6 @@ static void sp_256_map_5(sp_point_256* r, const sp_point_256* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 5; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] + b[ 0]; - r[ 1] = a[ 1] + b[ 1]; - r[ 2] = a[ 2] + b[ 2]; - r[ 3] = a[ 3] + b[ 3]; - r[ 4] = a[ 4] + b[ 4]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -13572,45 +13539,6 @@ static void sp_256_mont_tpl_5(sp_digit* r, const sp_digit* a, const sp_digit* m) sp_256_norm_5(r); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 5; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] - b[ 0]; - r[ 1] = a[ 1] - b[ 1]; - r[ 2] = a[ 2] - b[ 2]; - r[ 3] = a[ 3] - b[ 3]; - r[ 4] = a[ 4] - b[ 4]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -13648,6 +13576,7 @@ static void sp_256_mont_sub_5(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m) { (void)sp_256_sub_5(r, a, b); + sp_256_norm_5(r); sp_256_cond_add_5(r, r, m, r[4] >> 48); sp_256_norm_5(r); } @@ -13658,13 +13587,13 @@ static void sp_256_mont_sub_5(sp_digit* r, const sp_digit* a, const sp_digit* b, * r Result of shift. * a Number to shift. */ -SP_NOINLINE static void sp_256_rshift1_5(sp_digit* r, sp_digit* a) +SP_NOINLINE static void sp_256_rshift1_5(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; for (i=0; i<4; i++) { - r[i] = ((a[i] >> 1) + (a[i + 1] << 51)) & 0xfffffffffffffL; + r[i] = (a[i] >> 1) + ((a[i + 1] << 51) & 0xfffffffffffffL); } #else r[0] = (a[0] >> 1) + ((a[1] << 51) & 0xfffffffffffffL); @@ -14106,8 +14035,8 @@ static int sp_256_proj_point_add_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_5(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -14193,10 +14122,123 @@ static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, cons } } +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mod_mul_norm_5(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[2 * 8]; +#endif + int64_t* a32 = NULL; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) + return MEMORY_E; +#endif + + if (err == MP_OKAY) { + a32 = t + 8; + + a32[0] = (sp_digit)(a[0]) & 0xffffffffL; + a32[1] = (sp_digit)(a[0] >> 32U); + a32[1] |= (sp_digit)(a[1] << 20U); + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[1] >> 12U) & 0xffffffffL; + a32[3] = (sp_digit)(a[1] >> 44U); + a32[3] |= (sp_digit)(a[2] << 8U); + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[2] >> 24U); + a32[4] |= (sp_digit)(a[3] << 28U); + a32[4] &= 0xffffffffL; + a32[5] = (sp_digit)(a[3] >> 4U) & 0xffffffffL; + a32[6] = (sp_digit)(a[3] >> 36U); + a32[6] |= (sp_digit)(a[4] << 16U); + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[4] >> 16U) & 0xffffffffL; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + o = t[7] >> 32U; t[7] &= 0xffffffffL; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + + r[0] = t[0]; + r[0] |= t[1] << 32U; + r[0] &= 0xfffffffffffffLL; + r[1] = (t[1] >> 20); + r[1] |= t[2] << 12U; + r[1] |= t[3] << 44U; + r[1] &= 0xfffffffffffffLL; + r[2] = (t[3] >> 8); + r[2] |= t[4] << 24U; + r[2] &= 0xfffffffffffffLL; + r[3] = (t[4] >> 28); + r[3] |= t[5] << 4U; + r[3] |= t[6] << 36U; + r[3] &= 0xfffffffffffffLL; + r[4] = (t[6] >> 16); + r[4] |= t[7] << 16U; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_SMALL /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Small implementation using add and double that is cache attack resistant but + * allocates memory rather than use large stacks. + * 256 adds and doubles. + * * r Resulting point. * g Point to multiply. * k Scalar to multiply by. @@ -14320,33 +14362,37 @@ static int sp_256_ecc_mulmod_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, const sp_digit* k, - int map, int ct, void* heap) +static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, + const sp_digit* k, int map, int ct, void* heap) { -#ifdef WOLFSSL_SP_NO_MALLOC +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else sp_point_256 t[3]; sp_digit tmp[2 * 5 * 5]; -#else - sp_point_256* t; - sp_digit* tmp; #endif sp_digit n; int i; - int c, y; + int c; + int y; int err = MP_OKAY; - /* Implementatio is constant time. */ + /* Implementation is constant time. */ (void)ct; (void)heap; -#ifndef WOLFSSL_SP_NO_MALLOC - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { @@ -14397,19 +14443,24 @@ static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, const sp_ } } -#ifndef WOLFSSL_SP_NO_MALLOC - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); - XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_256) * 3); - XFREE(t, NULL, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(tmp)); - ForceZero(t, sizeof(t)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 5 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -14461,7 +14512,8 @@ static void sp_256_cond_copy_5(sp_digit* r, const sp_digit* a, const sp_digit m) * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_5(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_5(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*5; @@ -14549,8 +14601,8 @@ static void sp_256_proj_point_dbl_n_5(sp_point_256* p, int n, sp_digit* t) * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, const sp_point_256* p, - int n, int m, sp_digit* t) +static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, + const sp_point_256* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*5; @@ -14561,6 +14613,7 @@ static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, const sp_point_256* sp_digit* y = r[(1<x[i]; @@ -14577,7 +14630,10 @@ static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, const sp_point_256* /* W = Z^4 */ sp_256_mont_sqr_5(w, z, p256_mod, p256_mp_mod); sp_256_mont_sqr_5(w, w, p256_mod, p256_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_256_mont_sqr_5(t1, x, p256_mod, p256_mp_mod); sp_256_mont_sub_5(t1, t1, w, p256_mod); @@ -14585,14 +14641,14 @@ static void sp_256_proj_point_dbl_n_store_5(sp_point_256* r, const sp_point_256* /* B = X*Y^2 */ sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); sp_256_mont_mul_5(b, t2, x, p256_mod, p256_mp_mod); - x = r[(1<y); + sp_256_norm_5(negy); sp_256_cond_copy_5(p->y, negy, (sp_digit)0 - v[i].neg); sp_256_proj_point_add_5(rt, rt, p, tmp); } @@ -14942,14 +15000,12 @@ static int sp_256_ecc_mulmod_win_add_sub_5(sp_point_256* r, const sp_point_256* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(p, 0, heap); - sp_256_point_free_5(rt, 0, heap); return err; } @@ -15062,6 +15118,10 @@ static void sp_256_proj_to_affine_5(sp_point_256* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 32 bits between * * a The base point. * table Place to store generated point data. @@ -15071,26 +15131,30 @@ static void sp_256_proj_to_affine_5(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_5(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_5(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_5(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -15135,9 +15199,10 @@ static int sp_256_gen_stripe_table_5(const sp_point_256* a, } } - sp_256_point_free_5(s2, 0, heap); - sp_256_point_free_5(s1, 0, heap); - sp_256_point_free_5( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -15184,8 +15249,10 @@ static void sp_256_get_entry_256_5(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -15199,17 +15266,19 @@ static int sp_256_ecc_mulmod_stripe_5(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 5 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 5 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -15217,27 +15286,30 @@ static int sp_256_ecc_mulmod_stripe_5(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_5(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=31; j<8; j++,x+=32) { + x = 31; + for (j=0; j<8; j++) { y |= (int)(((k[x / 52] >> (x % 52)) & 1) << j); + x += 32; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -15251,8 +15323,10 @@ static int sp_256_ecc_mulmod_stripe_5(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=30; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=32) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 52] >> (x % 52)) & 1) << j); + x += 32; } sp_256_proj_point_dbl_5(rt, rt, t); @@ -15278,13 +15352,12 @@ static int sp_256_ecc_mulmod_stripe_5(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(p, 0, heap); - sp_256_point_free_5(rt, 0, heap); return err; } @@ -15294,16 +15367,25 @@ static int sp_256_ecc_mulmod_stripe_5(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[5]; + /* Y ordinate of point that table was generated from. */ sp_digit y[5]; + /* Precomputation table for point. */ sp_table_entry_256 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -15311,9 +15393,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -15430,28 +15518,31 @@ static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[5]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[5]; +#endif int err = MP_OKAY; - err = sp_256_point_new_5(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 5, km); sp_256_point_from_ecc_point_5(point, gm); @@ -15462,12 +15553,92 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_5(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[5 + 5 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (5 + 5 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_5(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 5; + + sp_256_from_mp(k, 5, km); + sp_256_point_from_ecc_point_5(point, gm); + sp_256_point_from_ecc_point_5(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_5(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_5(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_5(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_5(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_5(point, point, addP, tmp); + + if (map) { + sp_256_map_5(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_5(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -15490,6 +15661,10 @@ static int sp_256_ecc_mulmod_base_5(sp_point_256* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 32 between points. + */ static const sp_table_entry_256 p256_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -16774,6 +16949,11 @@ static const sp_table_entry_256 p256_table[256] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -16799,28 +16979,30 @@ static int sp_256_ecc_mulmod_base_5(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[5]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[5]; +#endif int err = MP_OKAY; - err = sp_256_point_new_5(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 5, km); @@ -16830,12 +17012,90 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_5(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[5 + 5 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (5 + 5 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_5(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 5; + + sp_256_from_mp(k, 5, km); + sp_256_point_from_ecc_point_5(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_5(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_5(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_5(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_5(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_5(point, point, addP, tmp); + + if (map) { + sp_256_map_5(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_5(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -16853,7 +17113,7 @@ static int sp_256_iszero_5(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * r A single precision integer. @@ -16874,7 +17134,8 @@ SP_NOINLINE static void sp_256_add_one_5(sp_digit* a) */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -16937,41 +17198,46 @@ static int sp_256_ecc_gen_k_5(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[5]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[5]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_256_point_new_5(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_5(rng, k); } if (err == MP_OKAY) { @@ -16996,15 +17262,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_5(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_5(infinity, 1, heap); -#endif - sp_256_point_free_5(point, 1, heap); return err; } @@ -17018,7 +17283,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_256_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<4; i++) { r[i+1] += r[i] >> 52; @@ -17063,33 +17331,35 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[5]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[5]; +#endif int err = MP_OKAY; if (*outLen < 32U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -17102,12 +17372,12 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(point, 0, heap); return err; } @@ -17158,17 +17428,19 @@ SP_NOINLINE static void sp_256_mul_d_5(sp_digit* r, const sp_digit* a, static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 52 bits from d1 and top 11 bits from d0. */ - d = (d1 << 11) | (d0 >> 41); + d = (d1 << 11) + (d0 >> 41); r = d / dv; d -= r * dv; /* Up to 12 bits in r */ /* Next 11 bits from d0. */ r <<= 11; d <<= 11; - d |= (d0 >> 30) & ((1 << 11) - 1); + d += (d0 >> 30) & ((1 << 11) - 1); t = d / dv; d -= t * dv; r += t; @@ -17176,7 +17448,7 @@ static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, /* Next 11 bits from d0. */ r <<= 11; d <<= 11; - d |= (d0 >> 19) & ((1 << 11) - 1); + d += (d0 >> 19) & ((1 << 11) - 1); t = d / dv; d -= t * dv; r += t; @@ -17184,7 +17456,7 @@ static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, /* Next 11 bits from d0. */ r <<= 11; d <<= 11; - d |= (d0 >> 8) & ((1 << 11) - 1); + d += (d0 >> 8) & ((1 << 11) - 1); t = d / dv; d -= t * dv; r += t; @@ -17192,10 +17464,11 @@ static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, /* Remaining 8 bits from d0. */ r <<= 8; d <<= 8; - d |= d0 & ((1 << 8) - 1); + d += d0 & ((1 << 8) - 1); t = d / dv; r += t; + /* All 52 bits from d1 and top 11 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -17203,66 +17476,60 @@ static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_256_div_5(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_256_div_5(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[10], t2d[5 + 1]; + sp_digit t1[3 * 5 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 5 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 5 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 5; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 5; dv = d[4]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 5U); for (i=4; i>=0; i--) { - sp_digit hi; t1[5 + i] += t1[5 + i - 1] >> 52; t1[5 + i - 1] &= 0xfffffffffffffL; - hi = t1[5 + i] - (t1[5 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[5 + i]; d1 <<= 52; d1 += t1[5 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_256_div_word_5(hi, t1[5 + i - 1], dv); + r1 = sp_256_div_word_5(t1[5 + i], t1[5 + i - 1], dv); #endif sp_256_mul_d_5(t2, d, r1); (void)sp_256_sub_5(&t1[i], &t1[i], t2); + sp_256_norm_5(&t1[i]); t1[5 + i] -= t2[5]; t1[5 + i] += t1[5 + i - 1] >> 52; t1[5 + i - 1] &= 0xfffffffffffffL; @@ -17279,7 +17546,7 @@ static int sp_256_div_5(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_256_mul_d_5(t2, d, r1); (void)sp_256_sub_5(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 5U); + XMEMCPY(r, t1, sizeof(*r) * 10U); for (i=0; i<4; i++) { r[i+1] += r[i] >> 52; r[i] &= 0xfffffffffffffL; @@ -17288,10 +17555,9 @@ static int sp_256_div_5(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -17319,7 +17585,7 @@ static const uint64_t p256_order_minus_2[4] = { }; #else /* The low half of the order-2 of the P256 curve. */ -static const uint64_t p256_order_low[2] = { +static const sp_int_digit p256_order_low[2] = { 0xf3b9cac2fc63254fU,0xbce6faada7179e84U }; #endif /* WOLFSSL_SP_SMALL */ @@ -17465,7 +17731,7 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ for (i=127; i>=112; i--) { sp_256_mont_sqr_order_5(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_5(t2, t2, a); } } @@ -17475,7 +17741,7 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ for (i=107; i>=64; i--) { sp_256_mont_sqr_order_5(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_5(t2, t2, a); } } @@ -17485,7 +17751,7 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ for (i=59; i>=32; i--) { sp_256_mont_sqr_order_5(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_5(t2, t2, a); } } @@ -17495,7 +17761,7 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ for (i=27; i>=0; i--) { sp_256_mont_sqr_order_5(t2, t2); - if (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_256_mont_mul_order_5(t2, t2, a); } } @@ -17506,12 +17772,63 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_5(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int64_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_5(k, k, p256_norm_order); + err = sp_256_mod_5(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_5(k); + + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_5(kInv, k, tmp); + sp_256_norm_5(kInv); + + /* s = r * x + e */ + sp_256_mul_5(x, x, r); + err = sp_256_mod_5(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(x); + carry = sp_256_add_5(s, e, x); + sp_256_cond_sub_5(s, s, p256_order, 0 - carry); + sp_256_norm_5(s); + c = sp_256_cmp_5(s, p256_order); + sp_256_cond_sub_5(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_5(s, s, kInv); + sp_256_norm_5(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -17546,8 +17863,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -17565,13 +17882,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 5, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 5, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_5(rng, ctx->k); @@ -17599,6 +17913,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_5(ctx->r, p256_order); sp_256_cond_sub_5(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_5(ctx->r); + + sp_256_from_mp(ctx->x, 5, priv); + sp_256_from_bin(ctx->e, 5, hash, (int)hashLen); ctx->state = 4; break; } @@ -17655,6 +17972,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -17687,72 +18007,55 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*5]; - sp_digit xd[2*5]; - sp_digit kd[2*5]; - sp_digit rd[2*5]; - sp_digit td[3 * 2*5]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 5]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int64_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_256_point_new_5(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 5; - x = d + 2 * 5; - k = d + 4 * 5; - r = d + 6 * 5; - tmp = d + 8 * 5; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 5; + k = e + 4 * 5; + r = e + 6 * 5; + tmp = e + 8 * 5; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 5, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 5, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_5(rng, k); @@ -17762,7 +18065,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_5(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_5(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -17773,38 +18076,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_5(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_5(r); - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_5(k, k, p256_norm_order); - err = sp_256_mod_5(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_5(k); - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_5(kInv, k, tmp); - sp_256_norm_5(kInv); + sp_256_from_mp(x, 5, priv); + sp_256_from_bin(e, 5, hash, (int)hashLen); - /* s = r * x + e */ - sp_256_mul_5(x, x, r); - err = sp_256_mod_5(x, x, p256_order); + err = sp_256_calc_s_5(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_5(x); - carry = sp_256_add_5(s, e, x); - sp_256_cond_sub_5(s, s, p256_order, 0 - carry); - sp_256_norm_5(s); - c = sp_256_cmp_5(s, p256_order); - sp_256_cond_sub_5(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_5(s); - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_5(s, s, kInv); - sp_256_norm_5(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_5(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_5(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -17818,20 +18102,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 5); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 5U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 5U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_5(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -17886,20 +18174,18 @@ static int sp_256_num_bits_5(const sp_digit* a) static int sp_256_mod_inv_5(sp_digit* r, const sp_digit* a, const sp_digit* m) { int err = MP_OKAY; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - sp_digit* u; - sp_digit* v; - sp_digit* b; - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u = NULL; #else - sp_digit u[5]; - sp_digit v[5]; - sp_digit b[5]; - sp_digit d[5]; + sp_digit u[5 * 4]; #endif - int ut, vt; + sp_digit* v = NULL; + sp_digit* b = NULL; + sp_digit* d = NULL; + int ut; + int vt; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 4, NULL, DYNAMIC_TYPE_ECC); if (u == NULL) @@ -17907,11 +18193,9 @@ static int sp_256_mod_inv_5(sp_digit* r, const sp_digit* a, const sp_digit* m) #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) v = u + 5; b = u + 2 * 5; d = u + 3 * 5; -#endif XMEMCPY(u, m, sizeof(sp_digit) * 5); XMEMCPY(v, a, sizeof(sp_digit) * 5); @@ -17989,7 +18273,7 @@ static int sp_256_mod_inv_5(sp_digit* r, const sp_digit* a, const sp_digit* m) else XMEMCPY(r, d, sizeof(sp_digit) * 5); } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (u != NULL) XFREE(u, NULL, DYNAMIC_TYPE_ECC); #endif @@ -17998,6 +18282,93 @@ static int sp_256_mod_inv_5(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_5(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ + + sp_256_proj_point_add_5(p1, p1, p2, tmp); + if (sp_256_iszero_5(p1->z)) { + if (sp_256_iszero_5(p1->x) && sp_256_iszero_5(p1->y)) { + sp_256_proj_point_dbl_5(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_5(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_256_mod_inv_5(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_256_mul_5(s, s, p256_norm_order); + } + err = sp_256_mod_5(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_5(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_256_mont_inv_order_5(s, s, tmp); + sp_256_mont_mul_order_5(u1, u1, s); + sp_256_mont_mul_order_5(u2, u2, s); + } + +#else + { + sp_256_mont_mul_order_5(u1, u1, s); + sp_256_mont_mul_order_5(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_256_ecc_mulmod_base_5(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_5(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_5(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_5(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_5(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -18016,8 +18387,7 @@ static int sp_256_mod_inv_5(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -18036,8 +18406,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -18052,7 +18423,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 5, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 5, r); + sp_256_from_mp(ctx->u2, 5, rm); sp_256_from_mp(ctx->s, 5, sm); sp_256_from_mp(ctx->p2.x, 5, pX); sp_256_from_mp(ctx->p2.y, 5, pY); @@ -18110,57 +18481,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_5(ctx->p1.z)) { - if (sp_256_iszero_5(ctx->p1.x) && sp_256_iszero_5(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<5; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 5, r); + sp_256_from_mp(ctx->u2, 5, rm); err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_5(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int64_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int64_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 5, r); + sp_256_from_mp(ctx->u2, 5, rm); carry = sp_256_add_5(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -18168,22 +18515,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_5(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -18191,127 +18539,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*5]; - sp_digit u2d[2*5]; - sp_digit sd[2*5]; - sp_digit tmpd[2*5 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 5]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int64_t c; - int err; + int64_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_5(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 5, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 5, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 5; - u2 = d + 2 * 5; - s = d + 4 * 5; - tmp = d + 6 * 5; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 5; + s = u1 + 4 * 5; + tmp = u1 + 6 * 5; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 5, hash, (int)hashLen); - sp_256_from_mp(u2, 5, r); + sp_256_from_mp(u2, 5, rm); sp_256_from_mp(s, 5, sm); sp_256_from_mp(p2->x, 5, pX); sp_256_from_mp(p2->y, 5, pY); sp_256_from_mp(p2->z, 5, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_256_mod_inv_5(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_5(s, s, p256_norm_order); - } - err = sp_256_mod_5(s, s, p256_order); + err = sp_256_calc_vfy_point_5(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_5(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_5(s, s, tmp); - sp_256_mont_mul_order_5(u1, u1, s); - sp_256_mont_mul_order_5(u2, u2, s); - } - -#else - { - sp_256_mont_mul_order_5(u1, u1, s); - sp_256_mont_mul_order_5(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_256_ecc_mulmod_base_5(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_5(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_5(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_5(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_256_proj_point_add_5(p1, p1, p2, tmp); - if (sp_256_iszero_5(p1->z)) { - if (sp_256_iszero_5(p1->x) && sp_256_iszero_5(p1->y)) { - sp_256_proj_point_dbl_5(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 5, r); + sp_256_from_mp(u2, 5, rm); err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); } @@ -18322,7 +18606,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_5(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 5, r); + sp_256_from_mp(u2, 5, rm); carry = sp_256_add_5(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -18330,26 +18614,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_5(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_5(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_5(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(p1, 0, heap); - sp_256_point_free_5(p2, 0, heap); return err; } @@ -18363,34 +18647,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_5(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_5(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*5]; - sp_digit t2d[2*5]; + sp_digit t1[5 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 5; - t2 = d + 2 * 5; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 5; sp_256_sqr_5(t1, point->y); (void)sp_256_mod_5(t1, t1, p256_mod); @@ -18410,10 +18686,9 @@ static int sp_256_ecc_is_point_5(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -18426,16 +18701,23 @@ static int sp_256_ecc_is_point_5(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_5(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 5, pX); sp_256_from_mp(pub->y, 5, pY); @@ -18444,7 +18726,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_5(pub, NULL); } - sp_256_point_free_5(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -18460,47 +18745,48 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[5]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; - sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_256_point_new_5(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_5(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_256* pub = NULL; +#else + sp_digit priv[5]; + sp_point_256 pub[2]; #endif + sp_point_256* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 5, pX); sp_256_from_mp(pub->y, 5, pY); sp_256_from_bin(pub->z, 5, one, (int)sizeof(one)); @@ -18514,12 +18800,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_5(pub->x, p256_mod) >= 0 || - sp_256_cmp_5(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_5(pub->x, p256_mod) >= 0) || + (sp_256_cmp_5(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -18531,12 +18816,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_256_ecc_mulmod_5(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_5(p->x) == 0) || - (sp_256_iszero_5(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_5(p->x) == 0) || + (sp_256_iszero_5(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -18544,22 +18827,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_256_ecc_mulmod_base_5(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_5(p->x, pub->x) != 0 || - sp_256_cmp_5(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_5(p->x, pub->x) != 0) || + (sp_256_cmp_5(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_5(p, 0, heap); - sp_256_point_free_5(pub, 0, heap); return err; } @@ -18583,33 +18864,35 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 5 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 5 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; - err = sp_256_point_new_5(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_5(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 5, pX); sp_256_from_mp(p->y, 5, pY); sp_256_from_mp(p->z, 5, pZ); @@ -18630,13 +18913,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(q, 0, NULL); - sp_256_point_free_5(p, 0, NULL); return err; } @@ -18655,25 +18937,28 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 5 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 5 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_5(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -18694,12 +18979,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(p, 0, NULL); return err; } @@ -18714,32 +18999,36 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 5 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 5 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_5(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 5, pX); sp_256_from_mp(p->y, 5, pY); sp_256_from_mp(p->z, 5, pZ); - sp_256_map_5(p, p, tmp); + sp_256_map_5(p, p, tmp); } if (err == MP_OKAY) { @@ -18752,12 +19041,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_5(p, 0, NULL); return err; } @@ -18770,31 +19059,23 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_5(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 5]; - sp_digit t2d[2 * 5]; + sp_digit t1[4 * 5]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 5; - t2 = d + 2 * 5; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 5; { /* t2 = y ^ 0x2 */ @@ -18829,10 +19110,9 @@ static int sp_256_mont_sqrt_5(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -18848,31 +19128,22 @@ static int sp_256_mont_sqrt_5(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 5]; - sp_digit yd[2 * 5]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 5]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 5; - y = d + 2 * 5; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 5; sp_256_from_mp(x, 5, xm); err = sp_256_mod_mul_norm_5(x, x, p256_mod); @@ -18905,10 +19176,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -18919,9 +19189,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 7]; + /* Y ordinate of point. */ sp_digit y[2 * 7]; + /* Z ordinate of point. */ sp_digit z[2 * 7]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; @@ -18959,26 +19233,26 @@ static const sp_digit p384_norm_order[7] = { #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) /* The Montogmery multiplier for order of the curve P384. */ -static sp_digit p384_mp_order = 0x546089e88fdc45l; +static sp_digit p384_mp_order = 0x546089e88fdc45L; #endif /* The base point of curve P384. */ static const sp_point_384 p384_base = { /* X ordinate */ { - 0x545e3872760ab7L,0x64bb7eaa52d874L,0x020950a8e1540bL, - 0x5d3cdcc2cfba0fL,0x0ad746e1d3b628L,0x26f1d638e3de64L,0x2aa1f288afa2c1L, + 0x545e3872760ab7L,0x64bb7eaa52d874L,0x020950a8e1540bL,0x5d3cdcc2cfba0fL, + 0x0ad746e1d3b628L,0x26f1d638e3de64L,0x2aa1f288afa2c1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L }, /* Y ordinate */ { - 0x431d7c90ea0e5fL,0x639c3afd033af4L,0x4ed7c2e3002982L, - 0x44d0a3e74ed188L,0x2dc29f8f41dbd2L,0x0debb3d317f252L,0x0d85f792a5898bL, + 0x431d7c90ea0e5fL,0x639c3afd033af4L,0x4ed7c2e3002982L,0x44d0a3e74ed188L, + 0x2dc29f8f41dbd2L,0x0debb3d317f252L,0x0d85f792a5898bL, 0L, 0L, 0L, 0L, 0L, 0L, 0L }, /* Z ordinate */ { - 0x00000000000001L,0x00000000000000L,0x00000000000000L, - 0x00000000000000L,0x00000000000000L,0x00000000000000L,0x00000000000000L, + 0x00000000000001L,0x00000000000000L,0x00000000000000L,0x00000000000000L, + 0x00000000000000L,0x00000000000000L,0x00000000000000L, 0L, 0L, 0L, 0L, 0L, 0L, 0L }, /* infinity */ @@ -18991,384 +19265,6 @@ static const sp_digit p384_b[7] = { }; #endif -static int sp_384_point_new_ex_7(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_7(heap, sp, p) sp_384_point_new_ex_7((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_7(heap, sp, p) sp_384_point_new_ex_7((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_7(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mod_mul_norm_7(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* td; -#else - int64_t td[12]; - int64_t a32d[12]; -#endif - int64_t* t; - int64_t* a32; - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (td == NULL) { - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = td; - a32 = td + 12; -#else - t = td; - a32 = a32d; -#endif - - a32[0] = (sp_digit)(a[0]) & 0xffffffffL; - a32[1] = (sp_digit)(a[0] >> 32U); - a32[1] |= (sp_digit)(a[1] << 23U); - a32[1] &= 0xffffffffL; - a32[2] = (sp_digit)(a[1] >> 9U) & 0xffffffffL; - a32[3] = (sp_digit)(a[1] >> 41U); - a32[3] |= (sp_digit)(a[2] << 14U); - a32[3] &= 0xffffffffL; - a32[4] = (sp_digit)(a[2] >> 18U) & 0xffffffffL; - a32[5] = (sp_digit)(a[2] >> 50U); - a32[5] |= (sp_digit)(a[3] << 5U); - a32[5] &= 0xffffffffL; - a32[6] = (sp_digit)(a[3] >> 27U); - a32[6] |= (sp_digit)(a[4] << 28U); - a32[6] &= 0xffffffffL; - a32[7] = (sp_digit)(a[4] >> 4U) & 0xffffffffL; - a32[8] = (sp_digit)(a[4] >> 36U); - a32[8] |= (sp_digit)(a[5] << 19U); - a32[8] &= 0xffffffffL; - a32[9] = (sp_digit)(a[5] >> 13U) & 0xffffffffL; - a32[10] = (sp_digit)(a[5] >> 45U); - a32[10] |= (sp_digit)(a[6] << 10U); - a32[10] &= 0xffffffffL; - a32[11] = (sp_digit)(a[6] >> 22U) & 0xffffffffL; - - /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ - t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; - /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ - t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; - /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ - t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; - /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ - t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; - /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ - t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; - /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ - t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; - /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ - t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; - /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ - t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; - /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ - t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; - /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ - t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; - /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ - t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; - /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ - t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - o = t[11] >> 32; t[11] &= 0xffffffff; - t[0] += o; - t[1] -= o; - t[3] += o; - t[4] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - - r[0] = t[0]; - r[0] |= t[1] << 32U; - r[0] &= 0x7fffffffffffffLL; - r[1] = (sp_digit)(t[1] >> 23); - r[1] |= t[2] << 9U; - r[1] |= t[3] << 41U; - r[1] &= 0x7fffffffffffffLL; - r[2] = (sp_digit)(t[3] >> 14); - r[2] |= t[4] << 18U; - r[2] |= t[5] << 50U; - r[2] &= 0x7fffffffffffffLL; - r[3] = (sp_digit)(t[5] >> 5); - r[3] |= t[6] << 27U; - r[3] &= 0x7fffffffffffffLL; - r[4] = (sp_digit)(t[6] >> 28); - r[4] |= t[7] << 4U; - r[4] |= t[8] << 36U; - r[4] &= 0x7fffffffffffffLL; - r[5] = (sp_digit)(t[8] >> 19); - r[5] |= t[9] << 13U; - r[5] |= t[10] << 45U; - r[5] &= 0x7fffffffffffffLL; - r[6] = (sp_digit)(t[10] >> 10); - r[6] |= t[11] << 22U; - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) - XFREE(td, NULL, DYNAMIC_TYPE_ECC); -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 55 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 55 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0x7fffffffffffffL; - s = 55U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 55U) <= (word32)DIGIT_BIT) { - s += 55U; - r[j] &= 0x7fffffffffffffL; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 55) { - r[j] &= 0x7fffffffffffffL; - if (j + 1 >= size) { - break; - } - s = 55 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_384. - * - * p Point of type sp_point_384 (result). - * pm Point of type ecc_point. - */ -static void sp_384_point_from_ecc_point_7(sp_point_384* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_384_from_mp(p->x, 7, pm->x); - sp_384_from_mp(p->y, 7, pm->y); - sp_384_from_mp(p->z, 7, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_384_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 55 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 7); - r->used = 7; - mp_clamp(r); -#elif DIGIT_BIT < 55 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 7; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 55) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 55 - s; - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 7; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 55 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 55 - s; - } - else { - s += 55; - } - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_384 to type ecc_point. - * - * p Point of type sp_point_384. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_384_point_to_ecc_point_7(const sp_point_384* p, ecc_point* pm) -{ - int err; - - err = sp_384_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pm->z); - } - - return err; -} - #ifdef WOLFSSL_SP_SMALL /* Multiply a and b into r. (r = a * b) * @@ -19379,7 +19275,9 @@ static int sp_384_point_to_ecc_point_7(const sp_point_384* p, ecc_point* pm) SP_NOINLINE static void sp_384_mul_7(sp_digit* r, const sp_digit* a, const sp_digit* b) { - int i, j, k; + int i; + int j; + int k; int128_t c; c = ((int128_t)a[6]) * b[6]; @@ -19481,6 +19379,372 @@ SP_NOINLINE static void sp_384_mul_7(sp_digit* r, const sp_digit* a, } #endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_7(sp_digit* r, const sp_digit* a) +{ + int i; + int j; + int k; + int128_t c; + + c = ((int128_t)a[6]) * a[6]; + r[13] = (sp_digit)(c >> 55); + c = (c & 0x7fffffffffffffL) << 55; + for (k = 11; k >= 0; k--) { + for (i = 6; i >= 0; i--) { + j = k - i; + if (j >= 7 || i <= j) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) { + c += ((int128_t)a[i]) * a[i]; + } + + r[k + 2] += (sp_digit)(c >> 110); + r[k + 1] = (sp_digit)((c >> 55) & 0x7fffffffffffffL); + c = (c & 0x7fffffffffffffL) << 55; + } + r[0] = (sp_digit)(c >> 55); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_7(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 0]) * a[ 5] + + ((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 0]) * a[ 6] + + ((int128_t)a[ 1]) * a[ 5] + + ((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((int128_t)a[ 2]) * a[ 6] + + ((int128_t)a[ 3]) * a[ 5]) * 2 + + ((int128_t)a[ 4]) * a[ 4]; + int128_t t9 = (((int128_t)a[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = ((int128_t)a[ 6]) * a[ 6]; + + t1 += t0 >> 55; r[ 0] = t0 & 0x7fffffffffffffL; + t2 += t1 >> 55; r[ 1] = t1 & 0x7fffffffffffffL; + t3 += t2 >> 55; r[ 2] = t2 & 0x7fffffffffffffL; + t4 += t3 >> 55; r[ 3] = t3 & 0x7fffffffffffffL; + t5 += t4 >> 55; r[ 4] = t4 & 0x7fffffffffffffL; + t6 += t5 >> 55; r[ 5] = t5 & 0x7fffffffffffffL; + t7 += t6 >> 55; r[ 6] = t6 & 0x7fffffffffffffL; + t8 += t7 >> 55; r[ 7] = t7 & 0x7fffffffffffffL; + t9 += t8 >> 55; r[ 8] = t8 & 0x7fffffffffffffL; + t10 += t9 >> 55; r[ 9] = t9 & 0x7fffffffffffffL; + t11 += t10 >> 55; r[10] = t10 & 0x7fffffffffffffL; + t12 += t11 >> 55; r[11] = t11 & 0x7fffffffffffffL; + r[13] = (sp_digit)(t12 >> 55); + r[12] = t12 & 0x7fffffffffffffL; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_add_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 7; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_add_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_sub_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 7; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_384_sub_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + r[ 5] = a[ 5] - b[ 5]; + r[ 6] = a[ 6] - b[ 6]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 55 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 55 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x7fffffffffffffL; + s = 55U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 55U) <= (word32)DIGIT_BIT) { + s += 55U; + r[j] &= 0x7fffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 55) { + r[j] &= 0x7fffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 55 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_7(sp_point_384* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_384_from_mp(p->x, 7, pm->x); + sp_384_from_mp(p->y, 7, pm->y); + sp_384_from_mp(p->z, 7, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 55 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 7); + r->used = 7; + mp_clamp(r); +#elif DIGIT_BIT < 55 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 7; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 55) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 55 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 7; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 55 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 55 - s; + } + else { + s += 55; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_7(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + #define sp_384_mont_reduce_order_7 sp_384_mont_reduce_7 /* Compare a with b in constant time. @@ -19660,7 +19924,6 @@ static void sp_384_mont_reduce_7(sp_digit* a, const sp_digit* m, sp_digit mp) sp_384_mul_add_7(a+i, m, mu); a[i+1] += a[i] >> 55; a[i] &= 0x7fffffffffffffL; - sp_384_mont_shift_7(a, a); sp_384_cond_sub_7(a, a, m, 0 - (((a[6] >> 54) > 0) ? (sp_digit)1 : (sp_digit)0)); @@ -19676,104 +19939,13 @@ static void sp_384_mont_reduce_7(sp_digit* a, const sp_digit* m, sp_digit mp) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_7(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_7(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_7(r, a, b); sp_384_mont_reduce_7(r, m, mp); } -#ifdef WOLFSSL_SP_SMALL -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_sqr_7(sp_digit* r, const sp_digit* a) -{ - int i, j, k; - int128_t c; - - c = ((int128_t)a[6]) * a[6]; - r[13] = (sp_digit)(c >> 55); - c = (c & 0x7fffffffffffffL) << 55; - for (k = 11; k >= 0; k--) { - for (i = 6; i >= 0; i--) { - j = k - i; - if (j >= 7 || i <= j) { - break; - } - if (j < 0) { - continue; - } - - c += ((int128_t)a[i]) * a[j] * 2; - } - if (i == j) { - c += ((int128_t)a[i]) * a[i]; - } - - r[k + 2] += (sp_digit)(c >> 110); - r[k + 1] = (sp_digit)((c >> 55) & 0x7fffffffffffffL); - c = (c & 0x7fffffffffffffL) << 55; - } - r[0] = (sp_digit)(c >> 55); -} - -#else -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_sqr_7(sp_digit* r, const sp_digit* a) -{ - int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; - int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; - int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 - + ((int128_t)a[ 1]) * a[ 1]; - int128_t t3 = (((int128_t)a[ 0]) * a[ 3] - + ((int128_t)a[ 1]) * a[ 2]) * 2; - int128_t t4 = (((int128_t)a[ 0]) * a[ 4] - + ((int128_t)a[ 1]) * a[ 3]) * 2 - + ((int128_t)a[ 2]) * a[ 2]; - int128_t t5 = (((int128_t)a[ 0]) * a[ 5] - + ((int128_t)a[ 1]) * a[ 4] - + ((int128_t)a[ 2]) * a[ 3]) * 2; - int128_t t6 = (((int128_t)a[ 0]) * a[ 6] - + ((int128_t)a[ 1]) * a[ 5] - + ((int128_t)a[ 2]) * a[ 4]) * 2 - + ((int128_t)a[ 3]) * a[ 3]; - int128_t t7 = (((int128_t)a[ 1]) * a[ 6] - + ((int128_t)a[ 2]) * a[ 5] - + ((int128_t)a[ 3]) * a[ 4]) * 2; - int128_t t8 = (((int128_t)a[ 2]) * a[ 6] - + ((int128_t)a[ 3]) * a[ 5]) * 2 - + ((int128_t)a[ 4]) * a[ 4]; - int128_t t9 = (((int128_t)a[ 3]) * a[ 6] - + ((int128_t)a[ 4]) * a[ 5]) * 2; - int128_t t10 = (((int128_t)a[ 4]) * a[ 6]) * 2 - + ((int128_t)a[ 5]) * a[ 5]; - int128_t t11 = (((int128_t)a[ 5]) * a[ 6]) * 2; - int128_t t12 = ((int128_t)a[ 6]) * a[ 6]; - - t1 += t0 >> 55; r[ 0] = t0 & 0x7fffffffffffffL; - t2 += t1 >> 55; r[ 1] = t1 & 0x7fffffffffffffL; - t3 += t2 >> 55; r[ 2] = t2 & 0x7fffffffffffffL; - t4 += t3 >> 55; r[ 3] = t3 & 0x7fffffffffffffL; - t5 += t4 >> 55; r[ 4] = t4 & 0x7fffffffffffffL; - t6 += t5 >> 55; r[ 5] = t5 & 0x7fffffffffffffL; - t7 += t6 >> 55; r[ 6] = t6 & 0x7fffffffffffffL; - t8 += t7 >> 55; r[ 7] = t7 & 0x7fffffffffffffL; - t9 += t8 >> 55; r[ 8] = t8 & 0x7fffffffffffffL; - t10 += t9 >> 55; r[ 9] = t9 & 0x7fffffffffffffL; - t11 += t10 >> 55; r[10] = t10 & 0x7fffffffffffffL; - t12 += t11 >> 55; r[11] = t11 & 0x7fffffffffffffL; - r[13] = (sp_digit)(t12 >> 55); - r[12] = t12 & 0x7fffffffffffffL; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -19781,8 +19953,8 @@ SP_NOINLINE static void sp_384_sqr_7(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_7(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_7(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_7(r, a); sp_384_mont_reduce_7(r, m, mp); @@ -19806,7 +19978,7 @@ static void sp_384_mont_sqr_n_7(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint64_t p384_mod_minus_2[6] = { @@ -19906,7 +20078,8 @@ static void sp_384_mont_inv_7(sp_digit* r, const sp_digit* a, sp_digit* td) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_7(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_7(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*7; @@ -19942,46 +20115,6 @@ static void sp_384_map_7(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_add_7(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 7; i++) { - r[i] = a[i] + b[i]; - } - - return 0; -} -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_add_7(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] + b[ 0]; - r[ 1] = a[ 1] + b[ 1]; - r[ 2] = a[ 2] + b[ 2]; - r[ 3] = a[ 3] + b[ 3]; - r[ 4] = a[ 4] + b[ 4]; - r[ 5] = a[ 5] + b[ 5]; - r[ 6] = a[ 6] + b[ 6]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -20034,47 +20167,6 @@ static void sp_384_mont_tpl_7(sp_digit* r, const sp_digit* a, const sp_digit* m) sp_384_norm_7(r); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_sub_7(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - int i; - - for (i = 0; i < 7; i++) { - r[i] = a[i] - b[i]; - } - - return 0; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static int sp_384_sub_7(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - r[ 0] = a[ 0] - b[ 0]; - r[ 1] = a[ 1] - b[ 1]; - r[ 2] = a[ 2] - b[ 2]; - r[ 3] = a[ 3] - b[ 3]; - r[ 4] = a[ 4] - b[ 4]; - r[ 5] = a[ 5] - b[ 5]; - r[ 6] = a[ 6] - b[ 6]; - - return 0; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -20114,6 +20206,7 @@ static void sp_384_mont_sub_7(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m) { (void)sp_384_sub_7(r, a, b); + sp_384_norm_7(r); sp_384_cond_add_7(r, r, m, r[6] >> 54); sp_384_norm_7(r); } @@ -20124,13 +20217,13 @@ static void sp_384_mont_sub_7(sp_digit* r, const sp_digit* a, const sp_digit* b, * r Result of shift. * a Number to shift. */ -SP_NOINLINE static void sp_384_rshift1_7(sp_digit* r, sp_digit* a) +SP_NOINLINE static void sp_384_rshift1_7(sp_digit* r, const sp_digit* a) { #ifdef WOLFSSL_SP_SMALL int i; for (i=0; i<6; i++) { - r[i] = ((a[i] >> 1) + (a[i + 1] << 54)) & 0x7fffffffffffffL; + r[i] = (a[i] >> 1) + ((a[i + 1] << 54) & 0x7fffffffffffffL); } #else r[0] = (a[0] >> 1) + ((a[1] << 54) & 0x7fffffffffffffL); @@ -20574,8 +20667,8 @@ static int sp_384_proj_point_add_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_7(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -20661,10 +20754,155 @@ static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, cons } } +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mod_mul_norm_7(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[2 * 12]; +#endif + int64_t* a32 = NULL; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + a32 = t + 12; + + a32[0] = (sp_digit)(a[0]) & 0xffffffffL; + a32[1] = (sp_digit)(a[0] >> 32U); + a32[1] |= (sp_digit)(a[1] << 23U); + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[1] >> 9U) & 0xffffffffL; + a32[3] = (sp_digit)(a[1] >> 41U); + a32[3] |= (sp_digit)(a[2] << 14U); + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[2] >> 18U) & 0xffffffffL; + a32[5] = (sp_digit)(a[2] >> 50U); + a32[5] |= (sp_digit)(a[3] << 5U); + a32[5] &= 0xffffffffL; + a32[6] = (sp_digit)(a[3] >> 27U); + a32[6] |= (sp_digit)(a[4] << 28U); + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[4] >> 4U) & 0xffffffffL; + a32[8] = (sp_digit)(a[4] >> 36U); + a32[8] |= (sp_digit)(a[5] << 19U); + a32[8] &= 0xffffffffL; + a32[9] = (sp_digit)(a[5] >> 13U) & 0xffffffffL; + a32[10] = (sp_digit)(a[5] >> 45U); + a32[10] |= (sp_digit)(a[6] << 10U); + a32[10] &= 0xffffffffL; + a32[11] = (sp_digit)(a[6] >> 22U) & 0xffffffffL; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[0] |= t[1] << 32U; + r[0] &= 0x7fffffffffffffLL; + r[1] = (t[1] >> 23); + r[1] |= t[2] << 9U; + r[1] |= t[3] << 41U; + r[1] &= 0x7fffffffffffffLL; + r[2] = (t[3] >> 14); + r[2] |= t[4] << 18U; + r[2] |= t[5] << 50U; + r[2] &= 0x7fffffffffffffLL; + r[3] = (t[5] >> 5); + r[3] |= t[6] << 27U; + r[3] &= 0x7fffffffffffffLL; + r[4] = (t[6] >> 28); + r[4] |= t[7] << 4U; + r[4] |= t[8] << 36U; + r[4] &= 0x7fffffffffffffLL; + r[5] = (t[8] >> 19); + r[5] |= t[9] << 13U; + r[5] |= t[10] << 45U; + r[5] &= 0x7fffffffffffffLL; + r[6] = (t[10] >> 10); + r[6] |= t[11] << 22U; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_SMALL /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Small implementation using add and double that is cache attack resistant but + * allocates memory rather than use large stacks. + * 384 adds and doubles. + * * r Resulting point. * g Point to multiply. * k Scalar to multiply by. @@ -20788,33 +21026,37 @@ static int sp_384_ecc_mulmod_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_digit* k, - int map, int ct, void* heap) +static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, int ct, void* heap) { -#ifdef WOLFSSL_SP_NO_MALLOC +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else sp_point_384 t[3]; sp_digit tmp[2 * 7 * 6]; -#else - sp_point_384* t; - sp_digit* tmp; #endif sp_digit n; int i; - int c, y; + int c; + int y; int err = MP_OKAY; - /* Implementatio is constant time. */ + /* Implementation is constant time. */ (void)ct; (void)heap; -#ifndef WOLFSSL_SP_NO_MALLOC - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { @@ -20865,19 +21107,24 @@ static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_ } } -#ifndef WOLFSSL_SP_NO_MALLOC - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 7 * 6); - XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_384) * 3); - XFREE(t, NULL, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(tmp)); - ForceZero(t, sizeof(t)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 7 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -20933,7 +21180,8 @@ static void sp_384_cond_copy_7(sp_digit* r, const sp_digit* a, const sp_digit m) * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_7(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_7(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*7; @@ -21021,8 +21269,8 @@ static void sp_384_proj_point_dbl_n_7(sp_point_384* p, int n, sp_digit* t) * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_store_7(sp_point_384* r, const sp_point_384* p, - int n, int m, sp_digit* t) +static void sp_384_proj_point_dbl_n_store_7(sp_point_384* r, + const sp_point_384* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*7; @@ -21033,6 +21281,7 @@ static void sp_384_proj_point_dbl_n_store_7(sp_point_384* r, const sp_point_384* sp_digit* y = r[(1<x[i]; @@ -21049,7 +21298,10 @@ static void sp_384_proj_point_dbl_n_store_7(sp_point_384* r, const sp_point_384* /* W = Z^4 */ sp_384_mont_sqr_7(w, z, p384_mod, p384_mp_mod); sp_384_mont_sqr_7(w, w, p384_mod, p384_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_384_mont_sqr_7(t1, x, p384_mod, p384_mp_mod); sp_384_mont_sub_7(t1, t1, w, p384_mod); @@ -21057,14 +21309,14 @@ static void sp_384_proj_point_dbl_n_store_7(sp_point_384* r, const sp_point_384* /* B = X*Y^2 */ sp_384_mont_sqr_7(t2, y, p384_mod, p384_mp_mod); sp_384_mont_mul_7(b, t2, x, p384_mod, p384_mp_mod); - x = r[(1<y); + sp_384_norm_7(negy); sp_384_cond_copy_7(p->y, negy, (sp_digit)0 - v[i].neg); sp_384_proj_point_add_7(rt, rt, p, tmp); } @@ -21426,14 +21680,12 @@ static int sp_384_ecc_mulmod_win_add_sub_7(sp_point_384* r, const sp_point_384* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(p, 0, heap); - sp_384_point_free_7(rt, 0, heap); return err; } @@ -21546,6 +21798,10 @@ static void sp_384_proj_to_affine_7(sp_point_384* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 48 bits between * * a The base point. * table Place to store generated point data. @@ -21555,26 +21811,30 @@ static void sp_384_proj_to_affine_7(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_7(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_7(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_7(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -21619,9 +21879,10 @@ static int sp_384_gen_stripe_table_7(const sp_point_384* a, } } - sp_384_point_free_7(s2, 0, heap); - sp_384_point_free_7(s1, 0, heap); - sp_384_point_free_7( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -21676,8 +21937,10 @@ static void sp_384_get_entry_256_7(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -21691,17 +21954,19 @@ static int sp_384_ecc_mulmod_stripe_7(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 7 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 7 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -21709,27 +21974,30 @@ static int sp_384_ecc_mulmod_stripe_7(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_7(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 47; + for (j=0; j<8; j++) { y |= (int)(((k[x / 55] >> (x % 55)) & 1) << j); + x += 48; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -21743,8 +22011,10 @@ static int sp_384_ecc_mulmod_stripe_7(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=46; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 55] >> (x % 55)) & 1) << j); + x += 48; } sp_384_proj_point_dbl_7(rt, rt, t); @@ -21770,13 +22040,12 @@ static int sp_384_ecc_mulmod_stripe_7(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(p, 0, heap); - sp_384_point_free_7(rt, 0, heap); return err; } @@ -21786,16 +22055,25 @@ static int sp_384_ecc_mulmod_stripe_7(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[7]; + /* Y ordinate of point that table was generated from. */ sp_digit y[7]; + /* Precomputation table for point. */ sp_table_entry_384 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -21803,9 +22081,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -21922,28 +22206,31 @@ static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[7]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[7]; +#endif int err = MP_OKAY; - err = sp_384_point_new_7(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 7, km); sp_384_point_from_ecc_point_7(point, gm); @@ -21954,12 +22241,92 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_7(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[7 + 7 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (7 + 7 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_7(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 7; + + sp_384_from_mp(k, 7, km); + sp_384_point_from_ecc_point_7(point, gm); + sp_384_point_from_ecc_point_7(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_7(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_7(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_7(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_7(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_7(point, point, addP, tmp); + + if (map) { + sp_384_map_7(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_7(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -21982,6 +22349,10 @@ static int sp_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 48 between points. + */ static const sp_table_entry_384 p384_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -23776,6 +24147,11 @@ static const sp_table_entry_384 p384_table[256] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -23801,28 +24177,30 @@ static int sp_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[7]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[7]; +#endif int err = MP_OKAY; - err = sp_384_point_new_7(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 7, km); @@ -23832,12 +24210,90 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_7(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[7 + 7 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (7 + 7 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_7(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 7; + + sp_384_from_mp(k, 7, km); + sp_384_point_from_ecc_point_7(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_7(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_7(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_7(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_7(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_7(point, point, addP, tmp); + + if (map) { + sp_384_map_7(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_7(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -23855,7 +24311,7 @@ static int sp_384_iszero_7(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * r A single precision integer. @@ -23876,7 +24332,8 @@ SP_NOINLINE static void sp_384_add_one_7(sp_digit* a) */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -23939,41 +24396,46 @@ static int sp_384_ecc_gen_k_7(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[7]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[7]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_384_point_new_7(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_7(rng, k); } if (err == MP_OKAY) { @@ -23998,15 +24460,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_7(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_7(infinity, 1, heap); -#endif - sp_384_point_free_7(point, 1, heap); return err; } @@ -24020,7 +24481,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_384_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; for (i=0; i<6; i++) { r[i+1] += r[i] >> 55; @@ -24065,33 +24529,35 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[7]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[7]; +#endif int err = MP_OKAY; if (*outLen < 48U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -24104,12 +24570,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(point, 0, heap); return err; } @@ -24164,17 +24630,19 @@ SP_NOINLINE static void sp_384_mul_d_7(sp_digit* r, const sp_digit* a, static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, sp_digit dv) { - sp_digit d, r, t; + sp_digit d; + sp_digit r; + sp_digit t; /* All 55 bits from d1 and top 8 bits from d0. */ - d = (d1 << 8) | (d0 >> 47); + d = (d1 << 8) + (d0 >> 47); r = d / dv; d -= r * dv; /* Up to 9 bits in r */ /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 39) & ((1 << 8) - 1); + d += (d0 >> 39) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -24182,7 +24650,7 @@ static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 31) & ((1 << 8) - 1); + d += (d0 >> 31) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -24190,7 +24658,7 @@ static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 23) & ((1 << 8) - 1); + d += (d0 >> 23) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -24198,7 +24666,7 @@ static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 15) & ((1 << 8) - 1); + d += (d0 >> 15) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -24206,7 +24674,7 @@ static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, /* Next 8 bits from d0. */ r <<= 8; d <<= 8; - d |= (d0 >> 7) & ((1 << 8) - 1); + d += (d0 >> 7) & ((1 << 8) - 1); t = d / dv; d -= t * dv; r += t; @@ -24214,10 +24682,11 @@ static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, /* Remaining 7 bits from d0. */ r <<= 7; d <<= 7; - d |= d0 & ((1 << 7) - 1); + d += d0 & ((1 << 7) - 1); t = d / dv; r += t; + /* All 55 bits from d1 and top 8 bits from d0. */ return r; } #endif /* WOLFSSL_SP_DIV_64 */ @@ -24225,66 +24694,60 @@ static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, /* Divide d in a and put remainder into r (m*d + r = a) * m is not calculated as it is not needed at this time. * + * Large number of bits in last word. + * * a Number to be divided. * d Number to divide with. * m Multiplier result. * r Remainder from the division. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. */ -static int sp_384_div_7(const sp_digit* a, const sp_digit* d, sp_digit* m, - sp_digit* r) +static int sp_384_div_7(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) { int i; #ifndef WOLFSSL_SP_DIV_64 int128_t d1; #endif - sp_digit dv, r1; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[14], t2d[7 + 1]; + sp_digit t1[3 * 7 + 1]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 7 + 1), NULL, +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 7 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = td; - t2 = td + 2 * 7; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 7; dv = d[6]; XMEMCPY(t1, a, sizeof(*t1) * 2U * 7U); for (i=6; i>=0; i--) { - sp_digit hi; t1[7 + i] += t1[7 + i - 1] >> 55; t1[7 + i - 1] &= 0x7fffffffffffffL; - hi = t1[7 + i] - (t1[7 + i] == dv); #ifndef WOLFSSL_SP_DIV_64 - d1 = hi; + d1 = t1[7 + i]; d1 <<= 55; d1 += t1[7 + i - 1]; r1 = (sp_digit)(d1 / dv); #else - r1 = sp_384_div_word_7(hi, t1[7 + i - 1], dv); + r1 = sp_384_div_word_7(t1[7 + i], t1[7 + i - 1], dv); #endif sp_384_mul_d_7(t2, d, r1); (void)sp_384_sub_7(&t1[i], &t1[i], t2); + sp_384_norm_7(&t1[i]); t1[7 + i] -= t2[7]; t1[7 + i] += t1[7 + i - 1] >> 55; t1[7 + i - 1] &= 0x7fffffffffffffL; @@ -24301,7 +24764,7 @@ static int sp_384_div_7(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_384_mul_d_7(t2, d, r1); (void)sp_384_sub_7(t1, t1, t2); - XMEMCPY(r, t1, sizeof(*r) * 2U * 7U); + XMEMCPY(r, t1, sizeof(*r) * 14U); for (i=0; i<6; i++) { r[i+1] += r[i] >> 55; r[i] &= 0x7fffffffffffffL; @@ -24310,10 +24773,9 @@ static int sp_384_div_7(const sp_digit* a, const sp_digit* d, sp_digit* m, (sp_digit)1 : (sp_digit)0)); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { - XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return err; @@ -24343,7 +24805,6 @@ static const uint64_t p384_order_minus_2[6] = { /* The low half of the order-2 of the P384 curve. */ static const uint64_t p384_order_low[3] = { 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU - }; #endif /* WOLFSSL_SP_SMALL */ @@ -24491,7 +24952,7 @@ static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_7(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_7(t2, t2); - if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_384_mont_mul_order_7(t2, t2, a); } } @@ -24500,12 +24961,63 @@ static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_7(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int64_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_7(k, k, p384_norm_order); + err = sp_384_mod_7(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_7(k); + + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_7(kInv, k, tmp); + sp_384_norm_7(kInv); + + /* s = r * x + e */ + sp_384_mul_7(x, x, r); + err = sp_384_mod_7(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_7(x); + carry = sp_384_add_7(s, e, x); + sp_384_cond_sub_7(s, s, p384_order, 0 - carry); + sp_384_norm_7(s); + c = sp_384_cmp_7(s, p384_order); + sp_384_cond_sub_7(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_7(s, s, kInv); + sp_384_norm_7(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -24540,8 +25052,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -24559,13 +25071,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 7, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 7, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_7(rng, ctx->k); @@ -24593,6 +25102,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_7(ctx->r, p384_order); sp_384_cond_sub_7(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_7(ctx->r); + + sp_384_from_mp(ctx->x, 7, priv); + sp_384_from_bin(ctx->e, 7, hash, (int)hashLen); ctx->state = 4; break; } @@ -24649,6 +25161,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -24681,72 +25196,55 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*7]; - sp_digit xd[2*7]; - sp_digit kd[2*7]; - sp_digit rd[2*7]; - sp_digit td[3 * 2*7]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 7]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int64_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_384_point_new_7(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 7, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 7, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 7; - x = d + 2 * 7; - k = d + 4 * 7; - r = d + 6 * 7; - tmp = d + 8 * 7; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 7; + k = e + 4 * 7; + r = e + 6 * 7; + tmp = e + 8 * 7; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 7, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 7, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_7(rng, k); @@ -24756,7 +25254,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_7(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_7(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -24767,38 +25265,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_7(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_7(r); - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_7(k, k, p384_norm_order); - err = sp_384_mod_7(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_7(k); - /* kInv = 1/k mod order */ - sp_384_mont_inv_order_7(kInv, k, tmp); - sp_384_norm_7(kInv); + sp_384_from_mp(x, 7, priv); + sp_384_from_bin(e, 7, hash, (int)hashLen); - /* s = r * x + e */ - sp_384_mul_7(x, x, r); - err = sp_384_mod_7(x, x, p384_order); + err = sp_384_calc_s_7(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_7(x); - carry = sp_384_add_7(s, e, x); - sp_384_cond_sub_7(s, s, p384_order, 0 - carry); - sp_384_norm_7(s); - c = sp_384_cmp_7(s, p384_order); - sp_384_cond_sub_7(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_7(s); - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_7(s, s, kInv); - sp_384_norm_7(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_7(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_7(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -24812,20 +25291,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 7); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 7U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 7U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_7(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 7); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -24880,20 +25363,18 @@ static int sp_384_num_bits_7(const sp_digit* a) static int sp_384_mod_inv_7(sp_digit* r, const sp_digit* a, const sp_digit* m) { int err = MP_OKAY; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - sp_digit* u; - sp_digit* v; - sp_digit* b; - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u = NULL; #else - sp_digit u[7]; - sp_digit v[7]; - sp_digit b[7]; - sp_digit d[7]; + sp_digit u[7 * 4]; #endif - int ut, vt; + sp_digit* v = NULL; + sp_digit* b = NULL; + sp_digit* d = NULL; + int ut; + int vt; -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 4, NULL, DYNAMIC_TYPE_ECC); if (u == NULL) @@ -24901,11 +25382,9 @@ static int sp_384_mod_inv_7(sp_digit* r, const sp_digit* a, const sp_digit* m) #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) v = u + 7; b = u + 2 * 7; d = u + 3 * 7; -#endif XMEMCPY(u, m, sizeof(sp_digit) * 7); XMEMCPY(v, a, sizeof(sp_digit) * 7); @@ -24983,7 +25462,7 @@ static int sp_384_mod_inv_7(sp_digit* r, const sp_digit* a, const sp_digit* m) else XMEMCPY(r, d, sizeof(sp_digit) * 7); } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (u != NULL) XFREE(u, NULL, DYNAMIC_TYPE_ECC); #endif @@ -24992,6 +25471,95 @@ static int sp_384_mod_inv_7(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_7(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ + + sp_384_proj_point_add_7(p1, p1, p2, tmp); + if (sp_384_iszero_7(p1->z)) { + if (sp_384_iszero_7(p1->x) && sp_384_iszero_7(p1->y)) { + sp_384_proj_point_dbl_7(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_7(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_7(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_384_mul_7(s, s, p384_norm_order); + } + err = sp_384_mod_7(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_7(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_384_mont_inv_order_7(s, s, tmp); + sp_384_mont_mul_order_7(u1, u1, s); + sp_384_mont_mul_order_7(u2, u2, s); + } + +#else + { + sp_384_mont_mul_order_7(u1, u1, s); + sp_384_mont_mul_order_7(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_384_ecc_mulmod_base_7(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_7(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_7(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_7(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_7(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -25010,8 +25578,7 @@ static int sp_384_mod_inv_7(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -25030,8 +25597,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -25046,7 +25614,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 7, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 7, r); + sp_384_from_mp(ctx->u2, 7, rm); sp_384_from_mp(ctx->s, 7, sm); sp_384_from_mp(ctx->p2.x, 7, pX); sp_384_from_mp(ctx->p2.y, 7, pY); @@ -25104,57 +25672,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_7(ctx->p1.z)) { - if (sp_384_iszero_7(ctx->p1.x) && sp_384_iszero_7(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<7; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 7, r); + sp_384_from_mp(ctx->u2, 7, rm); err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_7(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int64_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int64_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 7, r); + sp_384_from_mp(ctx->u2, 7, rm); carry = sp_384_add_7(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -25162,22 +25706,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_7(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -25185,129 +25730,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*7]; - sp_digit u2d[2*7]; - sp_digit sd[2*7]; - sp_digit tmpd[2*7 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 7]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int64_t c; - int err; + int64_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_7(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 7, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 7, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 7; - u2 = d + 2 * 7; - s = d + 4 * 7; - tmp = d + 6 * 7; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 7; + s = u1 + 4 * 7; + tmp = u1 + 6 * 7; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 7, hash, (int)hashLen); - sp_384_from_mp(u2, 7, r); + sp_384_from_mp(u2, 7, rm); sp_384_from_mp(s, 7, sm); sp_384_from_mp(p2->x, 7, pX); sp_384_from_mp(p2->y, 7, pY); sp_384_from_mp(p2->z, 7, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_7(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_384_mul_7(s, s, p384_norm_order); - } - err = sp_384_mod_7(s, s, p384_order); + err = sp_384_calc_vfy_point_7(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_7(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_384_mont_inv_order_7(s, s, tmp); - sp_384_mont_mul_order_7(u1, u1, s); - sp_384_mont_mul_order_7(u2, u2, s); - } - -#else - { - sp_384_mont_mul_order_7(u1, u1, s); - sp_384_mont_mul_order_7(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_384_ecc_mulmod_base_7(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_7(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_7(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_7(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_384_proj_point_add_7(p1, p1, p2, tmp); - if (sp_384_iszero_7(p1->z)) { - if (sp_384_iszero_7(p1->x) && sp_384_iszero_7(p1->y)) { - sp_384_proj_point_dbl_7(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 7, r); + sp_384_from_mp(u2, 7, rm); err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); } @@ -25318,7 +25797,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_7(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 7, r); + sp_384_from_mp(u2, 7, rm); carry = sp_384_add_7(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -25326,26 +25805,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_7(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_7(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_7(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(p1, 0, heap); - sp_384_point_free_7(p2, 0, heap); return err; } @@ -25359,34 +25838,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_7(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_7(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*7]; - sp_digit t2d[2*7]; + sp_digit t1[7 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 7; - t2 = d + 2 * 7; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 7; sp_384_sqr_7(t1, point->y); (void)sp_384_mod_7(t1, t1, p384_mod); @@ -25406,10 +25877,9 @@ static int sp_384_ecc_is_point_7(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -25422,16 +25892,23 @@ static int sp_384_ecc_is_point_7(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_7(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 7, pX); sp_384_from_mp(pub->y, 7, pY); @@ -25440,7 +25917,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_7(pub, NULL); } - sp_384_point_free_7(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -25456,47 +25936,48 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[7]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; - sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_384_point_new_7(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_7(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_384* pub = NULL; +#else + sp_digit priv[7]; + sp_point_384 pub[2]; #endif + sp_point_384* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 7, pX); sp_384_from_mp(pub->y, 7, pY); sp_384_from_bin(pub->z, 7, one, (int)sizeof(one)); @@ -25510,12 +25991,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_7(pub->x, p384_mod) >= 0 || - sp_384_cmp_7(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_7(pub->x, p384_mod) >= 0) || + (sp_384_cmp_7(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -25527,12 +26007,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_384_ecc_mulmod_7(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_7(p->x) == 0) || - (sp_384_iszero_7(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_7(p->x) == 0) || + (sp_384_iszero_7(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -25540,22 +26018,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_384_ecc_mulmod_base_7(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_7(p->x, pub->x) != 0 || - sp_384_cmp_7(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_7(p->x, pub->x) != 0) || + (sp_384_cmp_7(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_7(p, 0, heap); - sp_384_point_free_7(pub, 0, heap); return err; } @@ -25579,33 +26055,35 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 7 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 7 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; - err = sp_384_point_new_7(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_7(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 7, pX); sp_384_from_mp(p->y, 7, pY); sp_384_from_mp(p->z, 7, pZ); @@ -25626,13 +26104,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(q, 0, NULL); - sp_384_point_free_7(p, 0, NULL); return err; } @@ -25651,25 +26128,28 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 7 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 7 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_7(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -25690,12 +26170,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(p, 0, NULL); return err; } @@ -25710,32 +26190,36 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 7 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 7 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_7(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 7, pX); sp_384_from_mp(p->y, 7, pY); sp_384_from_mp(p->z, 7, pZ); - sp_384_map_7(p, p, tmp); + sp_384_map_7(p, p, tmp); } if (err == MP_OKAY) { @@ -25748,12 +26232,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_7(p, 0, NULL); return err; } @@ -25766,43 +26250,28 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_7(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 7]; - sp_digit t2d[2 * 7]; - sp_digit t3d[2 * 7]; - sp_digit t4d[2 * 7]; - sp_digit t5d[2 * 7]; + sp_digit t1[5 * 2 * 7]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 7, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 7, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 7; - t2 = d + 2 * 7; - t3 = d + 4 * 7; - t4 = d + 6 * 7; - t5 = d + 8 * 7; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 7; + t3 = t1 + 4 * 7; + t4 = t1 + 6 * 7; + t5 = t1 + 8 * 7; { /* t2 = y ^ 0x2 */ @@ -25862,10 +26331,9 @@ static int sp_384_mont_sqrt_7(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -25881,31 +26349,22 @@ static int sp_384_mont_sqrt_7(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 7]; - sp_digit yd[2 * 7]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 7]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 7, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 7, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 7; - y = d + 2 * 7; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 7; sp_384_from_mp(x, 7, xm); err = sp_384_mod_mul_norm_7(x, x, p384_mod); @@ -25938,17 +26397,10384 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 18]; + /* Y ordinate of point. */ + sp_digit y[2 * 18]; + /* Z ordinate of point. */ + sp_digit z[2 * 18]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 0]) * b[ 5] + + ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1] + + ((int128_t)a[ 5]) * b[ 0]; + int128_t t6 = ((int128_t)a[ 0]) * b[ 6] + + ((int128_t)a[ 1]) * b[ 5] + + ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2] + + ((int128_t)a[ 5]) * b[ 1] + + ((int128_t)a[ 6]) * b[ 0]; + int128_t t7 = ((int128_t)a[ 0]) * b[ 7] + + ((int128_t)a[ 1]) * b[ 6] + + ((int128_t)a[ 2]) * b[ 5] + + ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3] + + ((int128_t)a[ 5]) * b[ 2] + + ((int128_t)a[ 6]) * b[ 1] + + ((int128_t)a[ 7]) * b[ 0]; + int128_t t8 = ((int128_t)a[ 0]) * b[ 8] + + ((int128_t)a[ 1]) * b[ 7] + + ((int128_t)a[ 2]) * b[ 6] + + ((int128_t)a[ 3]) * b[ 5] + + ((int128_t)a[ 4]) * b[ 4] + + ((int128_t)a[ 5]) * b[ 3] + + ((int128_t)a[ 6]) * b[ 2] + + ((int128_t)a[ 7]) * b[ 1] + + ((int128_t)a[ 8]) * b[ 0]; + int128_t t9 = ((int128_t)a[ 1]) * b[ 8] + + ((int128_t)a[ 2]) * b[ 7] + + ((int128_t)a[ 3]) * b[ 6] + + ((int128_t)a[ 4]) * b[ 5] + + ((int128_t)a[ 5]) * b[ 4] + + ((int128_t)a[ 6]) * b[ 3] + + ((int128_t)a[ 7]) * b[ 2] + + ((int128_t)a[ 8]) * b[ 1]; + int128_t t10 = ((int128_t)a[ 2]) * b[ 8] + + ((int128_t)a[ 3]) * b[ 7] + + ((int128_t)a[ 4]) * b[ 6] + + ((int128_t)a[ 5]) * b[ 5] + + ((int128_t)a[ 6]) * b[ 4] + + ((int128_t)a[ 7]) * b[ 3] + + ((int128_t)a[ 8]) * b[ 2]; + int128_t t11 = ((int128_t)a[ 3]) * b[ 8] + + ((int128_t)a[ 4]) * b[ 7] + + ((int128_t)a[ 5]) * b[ 6] + + ((int128_t)a[ 6]) * b[ 5] + + ((int128_t)a[ 7]) * b[ 4] + + ((int128_t)a[ 8]) * b[ 3]; + int128_t t12 = ((int128_t)a[ 4]) * b[ 8] + + ((int128_t)a[ 5]) * b[ 7] + + ((int128_t)a[ 6]) * b[ 6] + + ((int128_t)a[ 7]) * b[ 5] + + ((int128_t)a[ 8]) * b[ 4]; + int128_t t13 = ((int128_t)a[ 5]) * b[ 8] + + ((int128_t)a[ 6]) * b[ 7] + + ((int128_t)a[ 7]) * b[ 6] + + ((int128_t)a[ 8]) * b[ 5]; + int128_t t14 = ((int128_t)a[ 6]) * b[ 8] + + ((int128_t)a[ 7]) * b[ 7] + + ((int128_t)a[ 8]) * b[ 6]; + int128_t t15 = ((int128_t)a[ 7]) * b[ 8] + + ((int128_t)a[ 8]) * b[ 7]; + int128_t t16 = ((int128_t)a[ 8]) * b[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffL; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffL; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffL; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffL; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffL; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffL; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffL; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffL; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffL; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffL; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffL; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffL; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffL; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffL; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffL; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffL; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffL; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_9(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 0]) * a[ 5] + + ((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 0]) * a[ 6] + + ((int128_t)a[ 1]) * a[ 5] + + ((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 0]) * a[ 7] + + ((int128_t)a[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((int128_t)a[ 0]) * a[ 8] + + ((int128_t)a[ 1]) * a[ 7] + + ((int128_t)a[ 2]) * a[ 6] + + ((int128_t)a[ 3]) * a[ 5]) * 2 + + ((int128_t)a[ 4]) * a[ 4]; + int128_t t9 = (((int128_t)a[ 1]) * a[ 8] + + ((int128_t)a[ 2]) * a[ 7] + + ((int128_t)a[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 2]) * a[ 8] + + ((int128_t)a[ 3]) * a[ 7] + + ((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 3]) * a[ 8] + + ((int128_t)a[ 4]) * a[ 7] + + ((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = (((int128_t)a[ 4]) * a[ 8] + + ((int128_t)a[ 5]) * a[ 7]) * 2 + + ((int128_t)a[ 6]) * a[ 6]; + int128_t t13 = (((int128_t)a[ 5]) * a[ 8] + + ((int128_t)a[ 6]) * a[ 7]) * 2; + int128_t t14 = (((int128_t)a[ 6]) * a[ 8]) * 2 + + ((int128_t)a[ 7]) * a[ 7]; + int128_t t15 = (((int128_t)a[ 7]) * a[ 8]) * 2; + int128_t t16 = ((int128_t)a[ 8]) * a[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffL; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffL; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffL; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffL; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffL; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffL; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffL; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffL; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffL; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffL; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffL; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffL; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffL; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffL; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffL; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffL; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffL; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[16] = a[16] + b[16]; + r[17] = a[17] + b[17]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[16] = a[16] - b[16]; + r[17] = a[17] - b[17]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit b1[9]; + sp_digit* z2 = r + 18; + (void)sp_1024_add_9(a1, a, &a[9]); + (void)sp_1024_add_9(b1, b, &b[9]); + sp_1024_mul_9(z2, &a[9], &b[9]); + sp_1024_mul_9(z0, a, b); + sp_1024_mul_9(z1, a1, b1); + (void)sp_1024_sub_18(z1, z1, z2); + (void)sp_1024_sub_18(z1, z1, z0); + (void)sp_1024_add_18(r + 9, r + 9, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_18(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 18; + (void)sp_1024_add_9(a1, a, &a[9]); + sp_1024_sqr_9(z2, &a[9]); + sp_1024_sqr_9(z0, a); + sp_1024_sqr_9(z1, a1); + (void)sp_1024_sub_18(z1, z1, z2); + (void)sp_1024_sub_18(z1, z1, z0); + (void)sp_1024_add_18(r + 9, r + 9, z1); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + int j; + int k; + int128_t c; + + c = ((int128_t)a[17]) * b[17]; + r[35] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffL) << 57; + for (k = 33; k >= 0; k--) { + for (i = 17; i >= 0; i--) { + j = k - i; + if (j >= 18) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += (sp_digit)(c >> 114); + r[k + 1] = (sp_digit)((c >> 57) & 0x1ffffffffffffffL); + c = (c & 0x1ffffffffffffffL) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_18(sp_digit* r, const sp_digit* a) +{ + int i; + int j; + int k; + int128_t c; + + c = ((int128_t)a[17]) * a[17]; + r[35] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffL) << 57; + for (k = 33; k >= 0; k--) { + for (i = 17; i >= 0; i--) { + j = k - i; + if (j >= 18 || i <= j) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) { + c += ((int128_t)a[i]) * a[i]; + } + + r[k + 2] += (sp_digit)(c >> 114); + r[k + 1] = (sp_digit)((c >> 57) & 0x1ffffffffffffffL); + c = (c & 0x1ffffffffffffffL) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* !WOLFSSL_SP_SMALL */ +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[18] = { + 0x06d807afea85febL,0x0ef88563d6743b3L,0x008e2615f6c2031L,0x1ead2e3e3ff9c7dL, + 0x1c3c09aa9f94d6aL,0x02954153e79e290L,0x07386dabfd2a0c6L,0x1a8a2558b9acad0L, + 0x0e26c6487326b4cL,0x0b693fa53335368L,0x06ce7fdf222864dL,0x01aa634b3961cf2L, + 0x07e2fc0f1b22873L,0x19f00d177a05559L,0x0d20986fa6b8d62L,0x0caf482d819c339L, + 0x1da65c61198dad0L,0x04cbd5d8f852b1fL +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[18] = { + 0x1927f850157a015L,0x11077a9c298bc4cL,0x1f71d9ea093dfceL,0x0152d1c1c006382L, + 0x03c3f655606b295L,0x1d6abeac1861d6fL,0x18c7925402d5f39L,0x0575daa7465352fL, + 0x11d939b78cd94b3L,0x1496c05acccac97L,0x19318020ddd79b2L,0x1e559cb4c69e30dL, + 0x181d03f0e4dd78cL,0x060ff2e885faaa6L,0x12df6790594729dL,0x1350b7d27e63cc6L, + 0x0259a39ee67252fL,0x03342a2707ad4e0L +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x10420077c8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[18] = { + 0x19b601ebfaa17fbL,0x0bbe2158f59d0ecL,0x082389857db080cL,0x17ab4b8f8ffe71fL, + 0x070f026aa7e535aL,0x10a55054f9e78a4L,0x01ce1b6aff4a831L,0x06a289562e6b2b4L, + 0x0389b1921cc9ad3L,0x0ada4fe94ccd4daL,0x11b39ff7c88a193L,0x186a98d2ce5873cL, + 0x09f8bf03c6c8a1cL,0x167c0345de81556L,0x0b48261be9ae358L,0x032bd20b60670ceL, + 0x1f69971846636b4L,0x0132f5763e14ac7L +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0x00dc8abeae63895L,0x023624b3f04bcc4L,0x0e96d8fdcfb203bL, + 0x1900e51b0fdd22cL,0x1a66910dd5cfb4cL,0x106f3a53e0a8a6dL, + 0x1cb869c0b0ce5e9L,0x19666f90ca916e5L,0x09760af765dd5bcL, + 0x0c5ecf3a0367448L,0x17c8b36e77e955cL,0x172061613c2087aL, + 0x00f6ce2308ab10dL,0x1b7fbe5fdaf6db6L,0x1b1a71a62cbc812L, + 0x16a5456345fac15L,0x1ad0a7990053ed9L,0x029fe04f7199614L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x1573fd71bef16d7L,0x0dab83533ee6f3aL,0x156b56ed18dab6eL, + 0x0fd3973353017b5L,0x05a4d5f213515adL,0x0554c4a496cbcfeL, + 0x0bf82b1bc7a0059L,0x0d995ad2d6b6ecaL,0x170dae117ad547cL, + 0x0b67f8654f0195cL,0x06333e68502cb90L,0x0bcbe1bcabecd6bL, + 0x14654ec2b9e7f7fL,0x0f0a08bc7af534fL,0x0641a58f5de3608L, + 0x1426ba7d0402c05L,0x1f1f9f1f0533634L,0x0054124831fb004L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x000000000000001L,0x000000000000000L,0x000000000000000L, + 0x000000000000000L,0x000000000000000L,0x000000000000000L, + 0x000000000000000L,0x000000000000000L,0x000000000000000L, + 0x000000000000000L,0x000000000000000L,0x000000000000000L, + 0x000000000000000L,0x000000000000000L,0x000000000000000L, + 0x000000000000000L,0x000000000000000L,0x000000000000000L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_1024_mul_d_18(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 18; i++) { + t += tb * a[i]; + r[i] = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + } + r[18] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t = 0; + sp_digit t2; + int128_t p[4]; + int i; + + for (i = 0; i < 16; i += 4) { + p[0] = tb * a[i + 0]; + p[1] = tb * a[i + 1]; + p[2] = tb * a[i + 2]; + p[3] = tb * a[i + 3]; + t += p[0]; + t2 = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + r[i + 0] = (sp_digit)t2; + t += p[1]; + t2 = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + r[i + 1] = (sp_digit)t2; + t += p[2]; + t2 = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + r[i + 2] = (sp_digit)t2; + t += p[3]; + t2 = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + r[i + 3] = (sp_digit)t2; + } + t += tb * a[16]; + r[16] = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + t += tb * a[17]; + r[17] = (sp_digit)(t & 0x1ffffffffffffffL); + t >>= 57; + r[18] = (sp_digit)(t & 0x1ffffffffffffffL); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_1024_cond_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[16] = a[16] + (b[16] & m); + r[17] = a[17] + (b[17] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#endif +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_1024_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_1024_div_word_18(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d; + sp_digit r; + sp_digit t; + + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) + (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 7 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 45) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 13 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 39) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 19 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 33) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 27) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 21) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 37 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 15) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 43 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 9) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 49 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d += (d0 >> 3) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 55 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d += d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + /* All 57 bits from d1 and top 6 bits from d0. */ + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * Large number of bits in last word. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_1024_div_18(const sp_digit* a, const sp_digit* d, + const sp_digit* m, sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv; + sp_digit r1; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[3 * 18 + 1]; +#endif + sp_digit* t2 = NULL; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 18 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t1 == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + t2 = t1 + 2 * 18; + + dv = d[17]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 18U); + for (i=17; i>=0; i--) { + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[18 + i]; + d1 <<= 57; + d1 += t1[18 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_1024_div_word_18(t1[18 + i], t1[18 + i - 1], dv); +#endif + + sp_1024_mul_d_18(t2, d, r1); + (void)sp_1024_sub_18(&t1[i], &t1[i], t2); + sp_1024_norm_18(&t1[i]); + t1[18 + i] -= t2[18]; + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffL; + r1 = (((-t1[18 + i]) << 57) - t1[18 + i - 1]) / dv; + r1++; + sp_1024_mul_d_18(t2, d, r1); + (void)sp_1024_add_18(&t1[i], &t1[i], t2); + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffL; + } + t1[18 - 1] += t1[18 - 2] >> 57; + t1[18 - 2] &= 0x1ffffffffffffffL; + r1 = t1[18 - 1] / dv; + + sp_1024_mul_d_18(t2, d, r1); + (void)sp_1024_sub_18(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 36U); + for (i=0; i<17; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffL; + } + sp_1024_cond_add_18(r, r, d, 0 - ((r[17] < 0) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_1024_mod_18(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_1024_div_18(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_18(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + sp_1024_mul_18(r, a, p1024_norm_mod); + return sp_1024_mod_18(r, r, m); +} + + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_18(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_18(heap, sp, p) sp_1024_point_new_ex_18((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_18(heap, sp, p) sp_1024_point_new_ex_18((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_18(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 57 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x1ffffffffffffffL; + s = 57U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 57U) <= (word32)DIGIT_BIT) { + s += 57U; + r[j] &= 0x1ffffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 57 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_18(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 18, pm->x); + sp_1024_from_mp(p->y, 18, pm->y); + sp_1024_from_mp(p->z, 18, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 57 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 18); + r->used = 18; + mp_clamp(r); +#elif DIGIT_BIT < 57 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 18; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 57) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 57 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 18; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 57 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 57 - s; + } + else { + s += 57; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_18(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_1024_cmp_18(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=17; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[17] - b[17]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[16] - b[16]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 8; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_1024_cond_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[16] = a[16] - (b[16] & m); + r[17] = a[17] - (b[17] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_1024_mul_add_18(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 18; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffL; + t >>= 57; + } + r[18] += (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffffffffffffL); + for (i = 0; i < 16; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 57) + (t[1] & 0x1ffffffffffffffL)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 57) + (t[2] & 0x1ffffffffffffffL)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 57) + (t[3] & 0x1ffffffffffffffL)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 57) + (t[4] & 0x1ffffffffffffffL)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 57) + (t[5] & 0x1ffffffffffffffL)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 57) + (t[6] & 0x1ffffffffffffffL)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 57) + (t[7] & 0x1ffffffffffffffL)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 57) + (t[0] & 0x1ffffffffffffffL)); + } + t[1] = tb * a[17]; r[17] += (sp_digit)((t[0] >> 57) + (t[1] & 0x1ffffffffffffffL)); + r[18] += (sp_digit)(t[1] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_1024_norm_18(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 17; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffL; + } +#else + int i; + for (i = 0; i < 16; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffL; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffL; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffL; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffL; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffL; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffL; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffL; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffL; + } + a[16+1] += a[16] >> 57; a[16] &= 0x1ffffffffffffffL; +#endif +} + +/* Shift the result in the high 1024 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_1024_mont_shift_18(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word64 n; + + n = a[17] >> 55; + for (i = 0; i < 17; i++) { + n += (word64)a[18 + i] << 2; + r[i] = n & 0x1ffffffffffffffL; + n >>= 57; + } + n += (word64)a[35] << 2; + r[17] = n; +#else + word64 n; + int i; + + n = (word64)a[17]; + n = n >> 55U; + for (i = 0; i < 16; i += 8) { + n += (word64)a[i+18] << 2U; r[i+0] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+19] << 2U; r[i+1] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+20] << 2U; r[i+2] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+21] << 2U; r[i+3] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+22] << 2U; r[i+4] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+23] << 2U; r[i+5] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+24] << 2U; r[i+6] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+25] << 2U; r[i+7] = n & 0x1ffffffffffffffUL; n >>= 57U; + } + n += (word64)a[34] << 2U; r[16] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[35] << 2U; r[17] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[18], 0, sizeof(*r) * 18U); +} + +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_1024_mont_reduce_18(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_1024_norm_18(a + 18); + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<17; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffL; + sp_1024_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7fffffffffffffL; + sp_1024_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffL; + } + else { + for (i=0; i<17; i++) { + mu = a[i] & 0x1ffffffffffffffL; + sp_1024_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = a[i] & 0x7fffffffffffffL; + sp_1024_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffL; + } +#else + for (i=0; i<17; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffL; + sp_1024_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7fffffffffffffL; + sp_1024_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffL; +#endif + sp_1024_mont_shift_18(a, a); + sp_1024_cond_sub_18(a, a, m, 0 - (((a[17] - m[17]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_18(r, a, b); + sp_1024_mont_reduce_18(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_18(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_18(r, a); + sp_1024_mont_reduce_18(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_18(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 18]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 18); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_18(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_18(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 18); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_18(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_18(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_18(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_18(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*18; + int64_t n; + + sp_1024_mont_inv_18(t1, p->z, t + 2*18); + + sp_1024_mont_sqr_18(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_18(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 18, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_18(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_18(r->x, p1024_mod); + sp_1024_cond_sub_18(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_18(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 18, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_18(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_18(r->y, p1024_mod); + sp_1024_cond_sub_18(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_add_18(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_1024_add_18(r, a, b); + sp_1024_norm_18(r); + sp_1024_cond_sub_18(r, r, m, 0 - (((r[17] - m[17]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(r); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_dbl_18(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_1024_add_18(r, a, a); + sp_1024_norm_18(r); + sp_1024_cond_sub_18(r, r, m, 0 - (((r[17] - m[17]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(r); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_tpl_18(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_1024_add_18(r, a, a); + sp_1024_norm_18(r); + sp_1024_cond_sub_18(r, r, m, 0 - (((r[17] - m[17]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(r); + (void)sp_1024_add_18(r, r, a); + sp_1024_norm_18(r); + sp_1024_cond_sub_18(r, r, m, 0 - (((r[17] - m[17]) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(r); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_1024_mont_sub_18(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_1024_sub_18(r, a, b); + sp_1024_norm_18(r); + sp_1024_cond_add_18(r, r, m, r[17] >> 55); + sp_1024_norm_18(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +SP_NOINLINE static void sp_1024_rshift1_18(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<17; i++) { + r[i] = (a[i] >> 1) + ((a[i + 1] << 56) & 0x1ffffffffffffffL); + } +#else + r[0] = (a[0] >> 1) + ((a[1] << 56) & 0x1ffffffffffffffL); + r[1] = (a[1] >> 1) + ((a[2] << 56) & 0x1ffffffffffffffL); + r[2] = (a[2] >> 1) + ((a[3] << 56) & 0x1ffffffffffffffL); + r[3] = (a[3] >> 1) + ((a[4] << 56) & 0x1ffffffffffffffL); + r[4] = (a[4] >> 1) + ((a[5] << 56) & 0x1ffffffffffffffL); + r[5] = (a[5] >> 1) + ((a[6] << 56) & 0x1ffffffffffffffL); + r[6] = (a[6] >> 1) + ((a[7] << 56) & 0x1ffffffffffffffL); + r[7] = (a[7] >> 1) + ((a[8] << 56) & 0x1ffffffffffffffL); + r[8] = (a[8] >> 1) + ((a[9] << 56) & 0x1ffffffffffffffL); + r[9] = (a[9] >> 1) + ((a[10] << 56) & 0x1ffffffffffffffL); + r[10] = (a[10] >> 1) + ((a[11] << 56) & 0x1ffffffffffffffL); + r[11] = (a[11] >> 1) + ((a[12] << 56) & 0x1ffffffffffffffL); + r[12] = (a[12] >> 1) + ((a[13] << 56) & 0x1ffffffffffffffL); + r[13] = (a[13] >> 1) + ((a[14] << 56) & 0x1ffffffffffffffL); + r[14] = (a[14] >> 1) + ((a[15] << 56) & 0x1ffffffffffffffL); + r[15] = (a[15] >> 1) + ((a[16] << 56) & 0x1ffffffffffffffL); + r[16] = (a[16] >> 1) + ((a[17] << 56) & 0x1ffffffffffffffL); +#endif + r[17] = a[17] >> 1; +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_1024_div2_18(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_1024_cond_add_18(r, a, m, 0 - (a[0] & 1)); + sp_1024_norm_18(r); + sp_1024_rshift1_18(r, r); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_18_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_18_ctx; + +static int sp_1024_proj_point_dbl_18_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_18_ctx* ctx = (sp_1024_proj_point_dbl_18_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_18_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*18; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_18(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_18(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_18(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_18(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_18(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_18(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_18(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_18(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_18(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_18(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_18(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_18(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_18(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_18(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_18(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_18(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_18(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_18(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_18(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*18; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_18(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_18(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_18(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_18(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_18(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_18(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_18(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_18(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_18(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_18(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_18(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_18(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_18(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_18(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_18(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_18(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_18(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_18(y, y, t2, p1024_mod); +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_18(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) | + (a[16] ^ b[16]) | (a[17] ^ b[17])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_18_ctx { + int state; + sp_1024_proj_point_dbl_18_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_18_ctx; + +static int sp_1024_proj_point_add_18_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_18_ctx* ctx = (sp_1024_proj_point_add_18_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_18_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*18; + ctx->t3 = t + 4*18; + ctx->t4 = t + 6*18; + ctx->t5 = t + 8*18; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_18(ctx->t1, p1024_mod, q->y); + sp_1024_norm_18(ctx->t1); + if ((sp_1024_cmp_equal_18(p->x, q->x) & sp_1024_cmp_equal_18(p->z, q->z) & + (sp_1024_cmp_equal_18(p->y, q->y) | sp_1024_cmp_equal_18(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_18_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<18; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<18; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<18; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_18(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_18(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_18(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_18(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_18(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_18(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_18(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_18(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_18(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_18(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_18(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_18(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_18(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_18(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_18(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_18(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_18(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_18(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_18(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_18(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_18(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_18(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_18(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_18(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*18; + sp_digit* t3 = t + 4*18; + sp_digit* t4 = t + 6*18; + sp_digit* t5 = t + 8*18; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_18(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_18(t1); + if ((sp_1024_cmp_equal_18(p->x, q->x) & sp_1024_cmp_equal_18(p->z, q->z) & + (sp_1024_cmp_equal_18(p->y, q->y) | sp_1024_cmp_equal_18(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_18(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<18; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<18; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<18; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_18(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_18(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_18(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_18(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_18(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_18(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_18(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_18(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_18(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(x, x, t5, p1024_mod); + sp_1024_mont_dbl_18(t1, y, p1024_mod); + sp_1024_mont_sub_18(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_18(y, y, x, p1024_mod); + sp_1024_mont_mul_18(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(y, y, t5, p1024_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Small implementation using add and double that is cache attack resistant but + * allocates memory rather than use large stacks. + * 1024 adds and doubles. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_ecc_mulmod_18_ctx { + int state; + union { + sp_1024_proj_point_dbl_18_ctx dbl_ctx; + sp_1024_proj_point_add_18_ctx add_ctx; + }; + sp_point_1024 t[3]; + sp_digit tmp[2 * 18 * 5]; + sp_digit n; + int i; + int c; + int y; +} sp_1024_ecc_mulmod_18_ctx; + +static int sp_1024_ecc_mulmod_18_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* g, const sp_digit* k, int map, int ct, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_1024_ecc_mulmod_18_ctx* ctx = (sp_1024_ecc_mulmod_18_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_ecc_mulmod_18_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + /* Implementation is constant time. */ + (void)ct; + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_1024) * 3); + ctx->i = 17; + ctx->c = 55; + ctx->n = k[ctx->i--] << (57 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_18(ctx->t[1].x, g->x, p1024_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_1024_mod_mul_norm_18(ctx->t[1].y, g->y, p1024_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_1024_mod_mul_norm_18(ctx->t[1].z, g->z, p1024_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 57; + } + ctx->y = (ctx->n >> 56) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_1024_proj_point_add_18_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_1024)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_1024_proj_point_dbl_18_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_1024)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_1024_map_18(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_1024)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + +static int sp_1024_ecc_mulmod_18(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[3]; + sp_digit tmp[2 * 18 * 5]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 18 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_1024) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_18(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_18(t[1].y, g->y, p1024_mod); + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_18(t[1].z, g->z, p1024_mod); + + if (err == MP_OKAY) { + i = 17; + c = 55; + n = k[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_1024_proj_point_add_18(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_1024)); + sp_1024_proj_point_dbl_18(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_1024)); + } + + if (map != 0) { + sp_1024_map_18(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 18 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[18]; + sp_digit y[18]; +} sp_table_entry_1024; + +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +static void sp_1024_cond_copy_18(sp_digit* r, const sp_digit* a, const sp_digit m) +{ + sp_digit t[18]; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) { + t[i] = r[i] ^ a[i]; + } + for (i = 0; i < 18; i++) { + r[i] ^= t[i] & m; + } +#else + t[ 0] = r[ 0] ^ a[ 0]; + t[ 1] = r[ 1] ^ a[ 1]; + t[ 2] = r[ 2] ^ a[ 2]; + t[ 3] = r[ 3] ^ a[ 3]; + t[ 4] = r[ 4] ^ a[ 4]; + t[ 5] = r[ 5] ^ a[ 5]; + t[ 6] = r[ 6] ^ a[ 6]; + t[ 7] = r[ 7] ^ a[ 7]; + t[ 8] = r[ 8] ^ a[ 8]; + t[ 9] = r[ 9] ^ a[ 9]; + t[10] = r[10] ^ a[10]; + t[11] = r[11] ^ a[11]; + t[12] = r[12] ^ a[12]; + t[13] = r[13] ^ a[13]; + t[14] = r[14] ^ a[14]; + t[15] = r[15] ^ a[15]; + t[16] = r[16] ^ a[16]; + t[17] = r[17] ^ a[17]; + r[ 0] ^= t[ 0] & m; + r[ 1] ^= t[ 1] & m; + r[ 2] ^= t[ 2] & m; + r[ 3] ^= t[ 3] & m; + r[ 4] ^= t[ 4] & m; + r[ 5] ^= t[ 5] & m; + r[ 6] ^= t[ 6] & m; + r[ 7] ^= t[ 7] & m; + r[ 8] ^= t[ 8] & m; + r[ 9] ^= t[ 9] & m; + r[10] ^= t[10] & m; + r[11] ^= t[11] & m; + r[12] ^= t[12] & m; + r[13] ^= t[13] & m; + r[14] ^= t[14] & m; + r[15] ^= t[15] & m; + r[16] ^= t[16] & m; + r[17] ^= t[17] & m; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_18(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*18; + sp_digit* b = t + 4*18; + sp_digit* t1 = t + 6*18; + sp_digit* t2 = t + 8*18; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_18(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_18(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_18(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_18(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_18(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_18(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_18(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_18(t2, b, p1024_mod); + sp_1024_mont_sub_18(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_18(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_18(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_18(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_18(y, b, x, p1024_mod); + sp_1024_mont_mul_18(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_18(y, y, p1024_mod); + sp_1024_mont_sub_18(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_18(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_18(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_18(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_18(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_18(t2, b, p1024_mod); + sp_1024_mont_sub_18(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_18(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_18(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_18(y, b, x, p1024_mod); + sp_1024_mont_mul_18(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_18(y, y, p1024_mod); + sp_1024_mont_sub_18(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_18(y, y, p1024_mod); +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_store_18(sp_point_1024* r, + const sp_point_1024* p, int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*18; + sp_digit* b = t + 4*18; + sp_digit* t1 = t + 6*18; + sp_digit* t2 = t + 8*18; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<18; i++) { + y[i] = p->y[i]; + } + for (i=0; i<18; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_1024_mont_dbl_18(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_18(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_18(w, w, p1024_mod, p1024_mp_mod); + j = m; + for (i=1; i<=n; i++) { + j *= 2; + + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_18(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_18(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_18(t2, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(b, t2, x, p1024_mod, p1024_mp_mod); + x = r[j].x; + /* X = A^2 - 2B */ + sp_1024_mont_sqr_18(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_18(t1, b, p1024_mod); + sp_1024_mont_sub_18(x, x, t1, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_18(r[j].z, z, y, p1024_mod, p1024_mp_mod); + z = r[j].z; + /* t2 = Y^4 */ + sp_1024_mont_sqr_18(t2, t2, p1024_mod, p1024_mp_mod); + if (i != n) { + /* W = W*Y^4 */ + sp_1024_mont_mul_18(w, w, t2, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_18(y, b, x, p1024_mod); + sp_1024_mont_mul_18(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_18(y, y, p1024_mod); + sp_1024_mont_sub_18(y, y, t2, p1024_mod); + + /* Y = Y/2 */ + sp_1024_div2_18(r[j].y, y, p1024_mod); + r[j].infinity = 0; + } +} + +/* Add two Montgomery form projective points. + * + * ra Result of addition. + * rs Result of subtraction. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_sub_18(sp_point_1024* ra, + sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*18; + sp_digit* t3 = t + 4*18; + sp_digit* t4 = t + 6*18; + sp_digit* t5 = t + 8*18; + sp_digit* t6 = t + 10*18; + sp_digit* x = ra->x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_18(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_18(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_18(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_18(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_18(t2, t2, t1, p1024_mod); + /* RS = S2 + S1 */ + sp_1024_mont_add_18(t6, t4, t3, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_18(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_1024_mont_mul_18(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(z, z, t2, p1024_mod, p1024_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_18(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_18(xs, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_18(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(x, x, t5, p1024_mod); + sp_1024_mont_sub_18(xs, xs, t5, p1024_mod); + sp_1024_mont_dbl_18(t1, y, p1024_mod); + sp_1024_mont_sub_18(x, x, t1, p1024_mod); + sp_1024_mont_sub_18(xs, xs, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_1024_mont_sub_18(ys, y, xs, p1024_mod); + sp_1024_mont_sub_18(y, y, x, p1024_mod); + sp_1024_mont_mul_18(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(t6, p1024_mod, t6, p1024_mod); + sp_1024_mont_mul_18(ys, ys, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(y, y, t5, p1024_mod); + sp_1024_mont_sub_18(ys, ys, t5, p1024_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_1024 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_1024; + +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_18_7[130] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static const uint8_t recode_neg_18_7[130] = { + 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, 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, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to perform. + */ +static void sp_1024_ecc_recode_7_18(const sp_digit* k, ecc_recode_1024* v) +{ + int i; + int j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<147; i++) { + y = (int8_t)n; + if (o + 7 < 57) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 57) { + n >>= 7; + if (++j < 18) + n = k[j]; + o = 0; + } + else if (++j < 18) { + n = k[j]; + y |= (uint8_t)((n << (57 - o)) & 0x7f); + o -= 50; + n >>= o; + } + + y += (uint8_t)carry; + v[i].i = recode_index_18_7[y]; + v[i].neg = recode_neg_18_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Window technique of 7 bits. (Add-Sub variation.) + * Calculate 0..64 times the point. Use function that adds and + * subtracts the same two points. + * Recode to add or subtract one of the computed points. + * Double to push up. + * NOT a sliding window. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_win_add_sub_18(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[65+2]; + sp_digit tmp[2 * 18 * 6]; +#endif + sp_point_1024* rt = NULL; + sp_point_1024* p = NULL; + sp_digit* negy; + int i; + ecc_recode_1024 v[147]; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * + (65+2), heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 18 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 65; + p = t + 65+1; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_18(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(t[1].y, g->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(t[1].z, g->z, p1024_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[64] */ + sp_1024_proj_point_dbl_n_store_18(t, &t[ 1], 6, 1, tmp); + sp_1024_proj_point_add_18(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[ 6], &t[ 3], tmp); + sp_1024_proj_point_add_sub_18(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[10], &t[ 5], tmp); + sp_1024_proj_point_add_sub_18(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[12], &t[ 6], tmp); + sp_1024_proj_point_dbl_18(&t[14], &t[ 7], tmp); + sp_1024_proj_point_add_sub_18(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[18], &t[ 9], tmp); + sp_1024_proj_point_add_sub_18(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[20], &t[10], tmp); + sp_1024_proj_point_dbl_18(&t[22], &t[11], tmp); + sp_1024_proj_point_add_sub_18(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[24], &t[12], tmp); + sp_1024_proj_point_dbl_18(&t[26], &t[13], tmp); + sp_1024_proj_point_add_sub_18(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[28], &t[14], tmp); + sp_1024_proj_point_dbl_18(&t[30], &t[15], tmp); + sp_1024_proj_point_add_sub_18(&t[31], &t[29], &t[30], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[34], &t[17], tmp); + sp_1024_proj_point_add_sub_18(&t[35], &t[33], &t[34], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[36], &t[18], tmp); + sp_1024_proj_point_dbl_18(&t[38], &t[19], tmp); + sp_1024_proj_point_add_sub_18(&t[39], &t[37], &t[38], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[40], &t[20], tmp); + sp_1024_proj_point_dbl_18(&t[42], &t[21], tmp); + sp_1024_proj_point_add_sub_18(&t[43], &t[41], &t[42], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[44], &t[22], tmp); + sp_1024_proj_point_dbl_18(&t[46], &t[23], tmp); + sp_1024_proj_point_add_sub_18(&t[47], &t[45], &t[46], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[48], &t[24], tmp); + sp_1024_proj_point_dbl_18(&t[50], &t[25], tmp); + sp_1024_proj_point_add_sub_18(&t[51], &t[49], &t[50], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[52], &t[26], tmp); + sp_1024_proj_point_dbl_18(&t[54], &t[27], tmp); + sp_1024_proj_point_add_sub_18(&t[55], &t[53], &t[54], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[56], &t[28], tmp); + sp_1024_proj_point_dbl_18(&t[58], &t[29], tmp); + sp_1024_proj_point_add_sub_18(&t[59], &t[57], &t[58], &t[ 1], tmp); + sp_1024_proj_point_dbl_18(&t[60], &t[30], tmp); + sp_1024_proj_point_dbl_18(&t[62], &t[31], tmp); + sp_1024_proj_point_add_sub_18(&t[63], &t[61], &t[62], &t[ 1], tmp); + + negy = t[0].y; + + sp_1024_ecc_recode_7_18(k, v); + + i = 146; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024)); + for (--i; i>=0; i--) { + sp_1024_proj_point_dbl_n_18(rt, 7, tmp); + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024)); + sp_1024_mont_sub_18(negy, p1024_mod, p->y, p1024_mod); + sp_1024_norm_18(negy); + sp_1024_cond_copy_18(p->y, negy, (sp_digit)0 - v[i].neg); + sp_1024_proj_point_add_18(rt, rt, p, tmp); + } + + if (map != 0) { + sp_1024_map_18(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_18(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*18; + sp_digit* t3 = t + 4*18; + sp_digit* t4 = t + 6*18; + sp_digit* t5 = t + 8*18; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_18(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_18(t1); + if ((sp_1024_cmp_equal_18(p->x, q->x) & sp_1024_cmp_equal_18(p->z, q->z) & + (sp_1024_cmp_equal_18(p->y, q->y) | sp_1024_cmp_equal_18(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_18(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<18; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<18; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<18; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_18(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_18(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_18(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_18(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_18(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_18(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_18(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_18(t1, t3, p1024_mod); + sp_1024_mont_sub_18(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_18(t3, t3, x, p1024_mod); + sp_1024_mont_mul_18(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_18(y, t3, t5, p1024_mod); + } +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_18(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + sp_digit* tmp = t + 4 * 18; + + sp_1024_mont_inv_18(t1, a->z, tmp); + + sp_1024_mont_sqr_18(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_18(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_18(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_18(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_18(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_18(t, 128, tmp); + sp_1024_proj_to_affine_18(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_18(t, s1, s2, tmp); + sp_1024_proj_to_affine_18(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC | !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_18(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 18 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 18 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 57] >> (x % 57)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 57] >> (x % 57)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_18(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_18(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_18(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[18]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[18]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_18(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_18(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_win_add_sub_18(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 18 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_18(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_win_add_sub_18(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_18(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[18]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 18, km); + sp_1024_point_from_ecc_point_18(point, gm); + + err = sp_1024_ecc_mulmod_18(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_18(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_18(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_1024_ecc_mulmod_18(r, &p1024_base, k, map, ct, heap); +} + +#else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x19c7ec6e0162bc2L,0x0637188544944dfL,0x17c27926760777bL, + 0x10da6b0430bab33L,0x10c5f8db9a96ea2L,0x1ae83300d763e9bL, + 0x15fe39cb9265633L,0x0b585ce52fa7d23L,0x18621db92da9f2fL, + 0x1936433ad2b3cf6L,0x0e177cb15aab052L,0x09a98d427f32466L, + 0x13ffa8ec11b88e7L,0x0f9fcff7890a58bL,0x19ed13a80e1a89cL, + 0x0692d7b36369d81L,0x00bafe528dceecdL,0x046fffcb50e24fcL }, + { 0x0a4753ac03c0c83L,0x14e8c55e6e6badaL,0x0e23ddd6d925a39L, + 0x157eb1e6a5c7073L,0x1d0bc15c803f949L,0x194c612fb8133cdL, + 0x05dba16fd745a3fL,0x1687edd7b318d8fL,0x120618af445e3e1L, + 0x1eaacc72a732049L,0x1ca0ed413fb6799L,0x17fae1b0ea2f608L, + 0x1f3f5addbe450caL,0x1c65a66523eb145L,0x071242000dfbcc1L, + 0x1b06e9c291a78d6L,0x1f3e256d3294fcfL,0x01550903def1e00L } }, + /* 2 */ + { { 0x15b6dae01900955L,0x04e60e75a32b6d4L,0x041f9cbfa56e977L, + 0x0f40818668a18f1L,0x1952ea6ea1ae544L,0x04b982c88c89b83L, + 0x1443d53fdcd0db4L,0x0e149b600e97b49L,0x0fd5306f1916440L, + 0x05cff39c5922916L,0x036b59e127dd885L,0x143161b9a5c828dL, + 0x015e1ad49287b29L,0x0ddd150d56ebf8dL,0x088cde66b18ea07L, + 0x07790026f38b702L,0x161f402b2f0b0e5L,0x0461f593f85f89dL }, + { 0x04ad3e1e513696fL,0x05d2e0c640ffd4dL,0x04d8f00cf44c0d4L, + 0x022f4a63783c5f8L,0x1aed610d53da6e7L,0x0ffab3a17632480L, + 0x144ab4cfa37dfa6L,0x1d7c955ae7c7bddL,0x0d983b465180f4dL, + 0x09b2934a817985aL,0x1e66aea24635fe6L,0x096ce01f8f34fc4L, + 0x1640bfd8c20ffe8L,0x0e9320debda2006L,0x098872f0e887485L, + 0x03d06f307288586L,0x110ace6500bb140L,0x03dfa0b1f128e21L } }, + /* 3 */ + { { 0x0174f88e3fd589eL,0x00bc86fcba5018eL,0x0f8cf9c1527f6d4L, + 0x1e2b249e69a12c4L,0x19b65ac58d091efL,0x14e167f77bce56fL, + 0x00af34b310988fdL,0x1bb02fb2064a59bL,0x1acf4f4d9a5f1ddL, + 0x030931aa808db5eL,0x112434bb4503274L,0x1d189b6d0da53eeL, + 0x16776b0fcc64092L,0x0f8b575b112f778L,0x0ef60a83a3007a7L, + 0x1c66ec506ce8309L,0x107757574e28956L,0x04c38f6e3382d3fL }, + { 0x10b76d5776535f7L,0x06b01131ad9dc5eL,0x0b667485bd91485L, + 0x0eaa2b7eeb8184bL,0x1e9f1675fd4df3aL,0x1439f3925312de2L, + 0x17128f0d7bedd01L,0x115deb93467765cL,0x1a971b35e806b19L, + 0x1ae0652d1e34876L,0x17762638788d067L,0x199d2ab5b3c951aL, + 0x07248d34164cecbL,0x02e057b71767a20L,0x1e03ffc6aece045L, + 0x1daae7e97dd0438L,0x1add14df768c272L,0x01cbf68851b8b1bL } }, + /* 4 */ + { { 0x13e0bb2755c2a27L,0x1217cacac2e2267L,0x183c64a179834e3L, + 0x00ec4e7a1e8d627L,0x193c569ac3ecd0cL,0x08c0c53c0078428L, + 0x0d8efc139d2ad0dL,0x1fd24b15471092cL,0x08456617cb8c894L, + 0x1e31555157cb4d0L,0x08a02d6919a3662L,0x0b1d5325e9f4cd8L, + 0x193f401e99bc9dfL,0x0261c6072ed85beL,0x137dacf81853f87L, + 0x16c31aa622a3859L,0x0a41c7575ece143L,0x020123cc2efc9ccL }, + { 0x1a251788f055746L,0x100200558f3707dL,0x13eeb0a49a5f16eL, + 0x12b69e8e81c3632L,0x1bb7ba547715211L,0x109cd2128048e84L, + 0x0a9f9e99d2186e6L,0x1dd75082767e6a7L,0x0afe771922443ceL, + 0x023469b1c23dde8L,0x1e7fd8f69250b45L,0x0383a84b68acc3eL, + 0x0d75ff46301563aL,0x159401649e1387eL,0x171c011081c8243L, + 0x05ce8d1e19b9790L,0x180ca4372fbfa03L,0x00d37e8f3645bceL } }, + /* 5 */ + { { 0x07a901a8d5116a3L,0x021ca597afa3fcbL,0x114983aebcec2e1L, + 0x0ec199f819c735aL,0x0c3f53f21e1be61L,0x088ddb5603f1e96L, + 0x0c30b760e38387bL,0x1708a8ea60e382bL,0x170dd4748920fe5L, + 0x1105f16f238c4b6L,0x1eb629649db1f06L,0x1987910ddc0e787L, + 0x176e831ac4026a1L,0x16280eb2cfedb79L,0x16a15d09a8d746aL, + 0x069ca15d3120a81L,0x15065dde0a4abd7L,0x014dbea6e0ab0a3L }, + { 0x0b3c2cbcbf4e20bL,0x1aa47ac662262a2L,0x0d516c32b07c70fL, + 0x0a01f00c4273013L,0x066905e00c0f02bL,0x080c4673095c480L, + 0x1daca3c563b5e0dL,0x1c1803b88b07eaaL,0x129803272a45492L, + 0x1d2b11d07fc9221L,0x08ac00a7437105dL,0x08b24f01d0f5a25L, + 0x030d53f272b4125L,0x12180f468f5e7c8L,0x1f41e62eb9ba900L, + 0x024d83cbe7e5f46L,0x17e9342c31022b4L,0x02e84940129c124L } }, + /* 6 */ + { { 0x03a2b7eff2f780dL,0x134106bebb58eacL,0x011e1bdd2bb0d34L, + 0x0421047fd7c7865L,0x1b5e7bf40fd4221L,0x147c66913f20bf7L, + 0x0efb1443526da95L,0x16ea779cfac2f03L,0x19cfe3f222f3718L, + 0x1a2744fecef360fL,0x1154fcfeb26d55fL,0x108dcde60179e39L, + 0x029f0ae6b19d2d0L,0x125c5df04bb6415L,0x0e96a9f98f6fd78L, + 0x0678e9958fe8b2eL,0x05dc6eb623784ddL,0x00513721a0a17f7L }, + { 0x081339facaa9a08L,0x18882a9237670c0L,0x05c184e4dd1d03cL, + 0x06485e05c312590L,0x1b5de98a8d8d410L,0x1df4a92415fe901L, + 0x0092627be51ad6aL,0x0f571a431726ed3L,0x1d5268e8966617cL, + 0x1173aa8c5be95c8L,0x11e5cffa359f0e5L,0x0a145602f8a258bL, + 0x1cc1a2946942e31L,0x098e3841b7a72f5L,0x1ee79428e644339L, + 0x015a15e9edd696eL,0x0ec68cbb175da12L,0x00ca4be30dc931bL } }, + /* 7 */ + { { 0x120b0c6417659a8L,0x15ce3c965947fb4L,0x0602da1de5ff1deL, + 0x03ceeb26c6ab6ceL,0x1561b1864caf58cL,0x07a4a328aadedb2L, + 0x02c80b9938d55e0L,0x0c1d615936e4535L,0x188594d782571bdL, + 0x0e6049cf1fd3c7cL,0x0d20c0ab0b4de57L,0x1ec1721e2888f71L, + 0x013ce4b3c1505fbL,0x0acdae0c5630874L,0x1a80888e693c9ebL, + 0x038f6bf4672e6f9L,0x1a6e578730b8dffL,0x04b5c8dc5a8bdfbL }, + { 0x1a991f49aac087cL,0x17ba7367ed946e0L,0x1e697dd8035b398L, + 0x09f22ff39211adfL,0x1de52dbfd781cd0L,0x0b90c03bcb7afb1L, + 0x04df79f6d9380bbL,0x02c1e10edecdf48L,0x13271ee643ca1f7L, + 0x1cd902c3e255c51L,0x05c41ce520411f2L,0x121ab318b86f974L, + 0x0a6f20e125df9a1L,0x1a794816865b739L,0x18b73ee8c508813L, + 0x186a285a51972f9L,0x09ddf261b8aa3d3L,0x039f9e98ae7fe12L } }, + /* 8 */ + { { 0x186855be6fd3673L,0x1b857ce90a5bdaeL,0x1e437311b34cc26L, + 0x0ab2aa21bd1a665L,0x18c1251ce553c01L,0x060de4aba3504b1L, + 0x0ea3f35f3a96e17L,0x0f89ff428d0005dL,0x110a3cb7022fcd7L, + 0x14ccefde27502f1L,0x1683413be9d5badL,0x0f3db9dabfb066eL, + 0x03251fd56e4d902L,0x015262f8a40c920L,0x0d0416fa1d8ce92L, + 0x1caf062e1a26036L,0x1fa93998b0f7247L,0x04449a7b221b5d0L }, + { 0x09f43b04713eabcL,0x1eec8d666e28bf8L,0x18efbc4f29f1329L, + 0x144b1030964fb54L,0x195dc2698b2e5a7L,0x1978a605465b096L, + 0x04d70d1a5d68b87L,0x1c63e5371dbc2e5L,0x0c3cbfd6ed40bc1L, + 0x1fa359f899311edL,0x16f9b7ec2dda074L,0x068aadb48689822L, + 0x18a8e43d985e31cL,0x05eeda7553e31f8L,0x153d631572c820dL, + 0x0d3b362d4187094L,0x0e174eacca246fdL,0x0068c4c5d8a9aa4L } }, + /* 9 */ + { { 0x0a73461e35ef043L,0x1b3ec9a4b5ab227L,0x1cef43e0e8f041eL, + 0x10a3a5386bac582L,0x11b1c1a4fad4b03L,0x1a1dcf1fa144153L, + 0x1d50d74af3d9952L,0x1838ef62b54557bL,0x15cb38a80dabe3dL, + 0x0fed0575240b39dL,0x05ad379ee43af85L,0x1c4a5791e7b10d3L, + 0x1637c4e42484f87L,0x0bd3d7ec56f681eL,0x132e4eb97b7999bL, + 0x1472301bb2b4543L,0x060a55cfd2546fbL,0x015ed58ee237c17L }, + { 0x04de22bfa6fed61L,0x0c552e646eca73dL,0x17c41c488bd7291L, + 0x1fcb5fe6ee7c6e5L,0x0a738e6d06a4b44L,0x18f89b5e1685d3aL, + 0x0a444691c38757cL,0x10aefff2675c205L,0x08b380a50310c78L, + 0x19e01143c1fe2d6L,0x1a249511c9741a7L,0x1c2cb5908443d8cL, + 0x0fcfda6e8a878f0L,0x1c66955d4d1d78dL,0x1b43ab8060fb4ddL, + 0x0c82a659b7ac104L,0x120b3234661cbeeL,0x01a9f5c495ce080L } }, + /* 10 */ + { { 0x0fdcad610b5521eL,0x0da202973817864L,0x00363ff69270684L, + 0x1597e6d75ac604dL,0x0c10a2d7cdb9654L,0x1873f03dac6708aL, + 0x0a04c79747df798L,0x0ff197c7afacec1L,0x1eb35866b6480d7L, + 0x0394679bf81b10cL,0x0197b50aa29d5d6L,0x1e3b20d450e1babL, + 0x04a51f906b283f1L,0x0a1d90543cf11fdL,0x079dd53cab1ba0dL, + 0x02ddc9e16c6f370L,0x07d57fbc0d48400L,0x046d103b8f310dbL }, + { 0x0855004ecce65ecL,0x0868fdba40c2f1eL,0x0f29e1e5eb49db4L, + 0x00efca955ac97cfL,0x1e0df0ff43444dbL,0x0843520bdb5864dL, + 0x1568e3f1095b015L,0x171f2a58877fae9L,0x0501e005a01c4edL, + 0x08b96fe252bf194L,0x0339394d75bb8f5L,0x1cb818ca1231b68L, + 0x07857561fcbaef1L,0x1a5112637428a2fL,0x103828b91a14da8L, + 0x007f8d351c44e1dL,0x15fb3f52247242bL,0x04317aaf161df5eL } }, + /* 11 */ + { { 0x16a390f226049feL,0x152bc6e5de4fd96L,0x12925d8d3edf324L, + 0x0c7bd4b1274a5fdL,0x0a49e9162b340cbL,0x0f20f9d1cf99c51L, + 0x1f9009acb7cf652L,0x1458e38f9b60cb4L,0x04a9b84a0468281L, + 0x1f75a81b98f7765L,0x0244d1db2edc958L,0x13537294cf19cdaL, + 0x1b808fd9f10cf97L,0x1057e2dcda26c61L,0x096f9a79836984fL, + 0x1ce9ea5b9cfbc7dL,0x1903a5d6864dc1eL,0x038d594489de403L }, + { 0x1618fc43b5b60adL,0x1af18250618c267L,0x0732f100cc082beL, + 0x07b63818cda4470L,0x06112a8d33cf895L,0x0b3d434e4ca726dL, + 0x134a75eab8b0f46L,0x1f7851aa926b6f5L,0x18075bd136c9a57L, + 0x0e01b9f4e4213fcL,0x12863464c897d72L,0x1a2688580318597L, + 0x07fbb3a72773777L,0x0cb16e0c75f2f6aL,0x1022019c10df524L, + 0x1e6b9e7383c125bL,0x06503e9c6f715ffL,0x046843ddb2f1b05L } }, + /* 12 */ + { { 0x02123023fdc1844L,0x113f7882f562b5fL,0x181bc5a28d21bb2L, + 0x1bc3af499643074L,0x1ef5d43e295f807L,0x1812e3b92353193L, + 0x138fab850c8171dL,0x0ea97bf8f95e690L,0x0ec939895df52c0L, + 0x1732afb6bd4e560L,0x17f8822ebb76c20L,0x0fc8a4fbce6330bL, + 0x1c313de1ea79c81L,0x0627b65d986707dL,0x0ec833677e56e27L, + 0x1f603e55dbe3debL,0x1ecfc1e0a891a8cL,0x0112f69a531f6dbL }, + { 0x013154dbabb1a85L,0x06d738f352b2d1fL,0x155aad2c403f4f6L, + 0x1dd78f1c35a642fL,0x08e73d37d44d934L,0x0f21e5810a990daL, + 0x02416ef242fe880L,0x1427847e3a04ea0L,0x02a2e5000c86691L, + 0x0595d693032c20eL,0x1072bcc009ad802L,0x05e8a4ed9cc22baL, + 0x0715932ffb1712cL,0x153a657900e261fL,0x014de91e25384f5L, + 0x192fc05adebbe18L,0x07ba8fb7602c2b1L,0x03095b072e8443eL } }, + /* 13 */ + { { 0x1d495cfba245d6bL,0x065dbd1671ffb77L,0x0b037fd7fbb973cL, + 0x119e518d4649b45L,0x0308a56b90c914fL,0x0b901a397eda86aL, + 0x127a40f6fdde44fL,0x1039f4bd9230455L,0x10dde73c83aea3eL, + 0x02dd4b13314489cL,0x1d922f29ab2f4d5L,0x0edd3140d0754a5L, + 0x0ca378ed52ff6f2L,0x042d60ec929b69dL,0x0f2129cd4f0b152L, + 0x082cf95fea5b401L,0x06e3971f81c3768L,0x007b99a70e96bccL }, + { 0x1bb5c836596067eL,0x0a70c9c60cc0357L,0x059ce72c3730cf9L, + 0x1a84806bf3050bbL,0x1fef90952b53f43L,0x07ab8d1c6298fc6L, + 0x09e1e43efa3936cL,0x04134183da54739L,0x02fecc1d6606f26L, + 0x0e44858b95be5a5L,0x129bef32ede1a27L,0x0105fce7dc93867L, + 0x17fcb66c48d1b11L,0x0370a2b9ac85be8L,0x0fab6164d5ac29aL, + 0x061f6ebad05880aL,0x149b2ae55fac54dL,0x033b1b5397c5774L } }, + /* 14 */ + { { 0x18063bcb91d6beaL,0x11d17491f65cb31L,0x064b189eb29ab89L, + 0x14ef5f3cfd3af61L,0x04aafebbc6ed001L,0x02ad48490a56679L, + 0x126768d592e59e0L,0x14a01333639c04eL,0x1e413a4e1e46a06L, + 0x02e89fb1728f7f3L,0x01f4d26ea10efa8L,0x104a63062b3c6bdL, + 0x1a546019230a633L,0x1bfe8e793011f45L,0x1cbf54e6c41dc86L, + 0x15e708d6aa857fbL,0x165b314f4f81c18L,0x00437cc3b305644L }, + { 0x07019548cbb9850L,0x05b98510696463bL,0x015d4cd59c31884L, + 0x0a064975d48109aL,0x076ee9b43ecdc59L,0x07fd32303fe2f96L, + 0x118f3ce4f403d10L,0x1cfc0222f2c5b82L,0x0f00b82519c7725L, + 0x0f3039b2de8e8c3L,0x015530b3dcaab0dL,0x1fbddf4692fbe7bL, + 0x0cf646ad11b4dd0L,0x0fbdc756eb89134L,0x01b7f941f082beeL, + 0x0a934c612d3a9f8L,0x01076b7df1c7245L,0x0340fca01f30d74L } }, + /* 15 */ + { { 0x0ad5163c9a0623bL,0x014abb3fd5c6a3eL,0x03b206bdf1f36feL, + 0x11d2cdab8459956L,0x10d4e41c469e38cL,0x159ace1a2186a97L, + 0x0049d0981d68a94L,0x082485ba7c6677aL,0x0cda3f6359fed23L, + 0x0f99b986bea97fdL,0x1d5bc1d9030fbd3L,0x0438377bcaf8bffL, + 0x0aeb8bb3364783cL,0x15684202ec3c251L,0x0d8af507b1f14cfL, + 0x1a95e96fe2847f3L,0x10a5543145c7075L,0x0064ef4a55d302cL }, + { 0x0d7273595d5682bL,0x0214197613b76c7L,0x1b562cda8349c47L, + 0x090931511fa3e95L,0x0480f45162ab40cL,0x0e7ff12c647e312L, + 0x0d6762f23292edeL,0x0bb2156b078e034L,0x0aee31a733fd5d1L, + 0x152acbde489199eL,0x072b92db0f8f080L,0x085853270110203L, + 0x1df47c8199e5130L,0x195007490700141L,0x1d6b8ee435a3963L, + 0x06164d3c5be834eL,0x196b8d2eca5871cL,0x0399ee5075d8ef1L } }, + /* 16 */ + { { 0x1b495d04b59213aL,0x1901cc6b810077aL,0x0698ad9dc707299L, + 0x08573d619697961L,0x0cdba21226adeedL,0x044868f5aa23aa4L, + 0x11ad0386aff37c2L,0x070a4a132c6d31cL,0x1e1bff0b082e9c1L, + 0x0c4f266a884cd38L,0x0326f326e4731e8L,0x0fb826fd897c46cL, + 0x01d1519f6e9bd4dL,0x07c19281e81ab29L,0x1ba8ad2fd7db5e3L, + 0x06339c86020631bL,0x1d7c3132494ef4cL,0x01559dea3878fd3L }, + { 0x153b680922c9fbbL,0x13ee4078b6368abL,0x04d6eb05bbf21a7L, + 0x0908da3b370688aL,0x12d62c214326a3bL,0x14956ada8bff71dL, + 0x0b04da416be882cL,0x11a54ae2634595bL,0x0cd904d8febdbcaL, + 0x1f6d4379f9b2fd9L,0x1ec82371faa8737L,0x150948bcef80e12L, + 0x0ccf5d118e89a35L,0x0fb74cf420bd031L,0x1e821f4f03012a0L, + 0x055a5888e096174L,0x0296f8a27d13ea2L,0x049d25a0b2613e9L } }, + /* 17 */ + { { 0x0271bc11f1efb7aL,0x1347319fe6606eaL,0x03c6c47d42a2b93L, + 0x1f5e0ec1133b379L,0x043d0e035430398L,0x11ea60a2f1217daL, + 0x0b425cfb09467dbL,0x01f56e1ef217537L,0x0de612ad5f9add1L, + 0x01bf2a70a74a15aL,0x095b4f76e2da2aeL,0x0678358548102ebL, + 0x10f0c80f94e85b2L,0x04c6da7cfc7fb61L,0x09f73752dfcfedeL, + 0x0712b458c089e8bL,0x163f3abb2f6fe3dL,0x01a16706b99773bL }, + { 0x1261394cf491b1fL,0x1776b8c84f1caf5L,0x156a7f936fab72aL, + 0x1a927ac09bb9880L,0x1ce5ebef17a6611L,0x0c4e5add222d1d0L, + 0x0101ba0b8a1638eL,0x0ab72de850507ebL,0x099877b99a156cfL, + 0x1c83533270b3507L,0x074d4eca5db44ebL,0x1e4e6d8c34039d4L, + 0x13b0f55d86efc16L,0x0759a600ed82621L,0x1980a00f2d2c9a6L, + 0x07d8a71a0fef055L,0x12043ac3bcb43beL,0x022afa579f0ab7eL } }, + /* 18 */ + { { 0x057f262754ec21cL,0x06a64f1d0dd1c60L,0x034445b07fa4fabL, + 0x09d599156c74042L,0x0a6f32cae4ea4e9L,0x1cbae718e0064d7L, + 0x087a572d88e761aL,0x116ca9abb19429dL,0x1230d31f45067fcL, + 0x05dc865b1aaff65L,0x007b3b705cba392L,0x01519600ce6ef1fL, + 0x01e162d01228838L,0x02d78a2e0cd8170L,0x0b70d503821e81bL, + 0x180cde09b916f6eL,0x1b7f70ef2148de3L,0x0278a412189804fL }, + { 0x0004fce6e2055e2L,0x123f543619033afL,0x16557e76aa8a278L, + 0x1f9d6fec769d797L,0x063784a0d15f212L,0x1b0128af662e0fcL, + 0x0a5514ece002dd5L,0x033d726038714d4L,0x00f16ba18a13cddL, + 0x189e928c43e1692L,0x08d6166a504fda0L,0x0bcdfc7faf8bf32L, + 0x1416e0ee0542340L,0x1fd6d55833c5759L,0x02111c47cef9eecL, + 0x05fecf203f45905L,0x10bc950db304d66L,0x03a6ae96a1e008bL } }, + /* 19 */ + { { 0x1002dc02b5bfe11L,0x1a086a96990f3d1L,0x1d9659e6ea241ccL, + 0x08d0b646dc2b241L,0x146f60400e248c1L,0x038bf8467d5aca1L, + 0x115da7d5ebedd03L,0x08e1b756518cc08L,0x10fa099689cdc32L, + 0x0f0157161187682L,0x185553916fbdd10L,0x13059c9af6de1b2L, + 0x075e62d22e9688aL,0x1e965d147d6f7d6L,0x1f1d27ebc544a9aL, + 0x0b4d6f10d1cc57cL,0x02988048d81ae9fL,0x0358d2a2162c2bdL }, + { 0x15ab9ad43242066L,0x178da966651574fL,0x1b1e623b71382bfL, + 0x02068361ab63687L,0x150aab370d0c00fL,0x13254ca6b45c7bdL, + 0x1a13a6a3939bfceL,0x0b8330671f6fe34L,0x18bc0e748351a0fL, + 0x0567966ed62228aL,0x14e6657a7fddacbL,0x167e2c7260ab829L, + 0x05888d837654a01L,0x19193bd8b561f75L,0x076eefee1366a69L, + 0x0e2f132264d23c2L,0x0c8597717aeabb6L,0x026109a9345d8a5L } }, + /* 20 */ + { { 0x06fe0a695532833L,0x111476b13683397L,0x0f659279cef6af2L, + 0x15e0789818455deL,0x15169b452083a87L,0x083544f4aa73ae9L, + 0x13e415dd427b9d1L,0x12293964edc55d5L,0x108275d77fa409fL, + 0x0f5b79ef85deb5cL,0x080b2f904c9c118L,0x184363893163290L, + 0x08361fee5935f3fL,0x087028f9bb6345dL,0x039c10a8632ef65L, + 0x03d16470950f263L,0x134292abead80ddL,0x032b89e14ae1be1L }, + { 0x0cca8e9ceb77b9aL,0x1f39391db4a34eeL,0x1b9a8075aca0be5L, + 0x1ab57d9bfd8ed57L,0x09290d703925203L,0x18a21c44a240411L, + 0x11f0fe64c5092c0L,0x04e08413be2f9a8L,0x17c6f2059c855c8L, + 0x0bebc312b607034L,0x16dbf904b653136L,0x0b23329883bab53L, + 0x01c89e21a319a64L,0x03501f87091a455L,0x05bfab35a412d43L, + 0x0d276ab82a2ad4cL,0x0384e36d1b57cc7L,0x035874cb61dd71eL } }, + /* 21 */ + { { 0x0789fabcceced00L,0x1f38d72dbd53319L,0x09a4b77af37cc8dL, + 0x016c3b5b1f0f65cL,0x135f803cb724512L,0x128786f08f2f246L, + 0x0ae4bed37d75e63L,0x07ac1dcd16979a5L,0x198ab2f5c1ce336L, + 0x0dd1ced3e6a1323L,0x15cbae0fd3ecfc5L,0x1d11cade11b634cL, + 0x1e172562c20f77dL,0x052c787a0ba1bb0L,0x1475b8af8d27fe2L, + 0x1e769c09b4e3709L,0x1f8368f03429e9fL,0x020115102b3c111L }, + { 0x07bbd0583847375L,0x0b5b11fa28d7829L,0x09352cb1fc60eb9L, + 0x168a4b731ac331eL,0x0e0884b5ee323f5L,0x0963bb54ec69cd0L, + 0x1055340175fdbecL,0x179ae38907ce117L,0x18ca6fd28742541L, + 0x179ee66fc1cbeedL,0x14c494fb33c90c2L,0x0210b1b0371b701L, + 0x0171391f68c743aL,0x19ddb2bf9fa4759L,0x191f8c524ebfe20L, + 0x0f3ec3a2bdacc0fL,0x15610159b11e082L,0x01890bce5925354L } }, + /* 22 */ + { { 0x14cc3ca07615ac2L,0x12f32090d6ac0d4L,0x05be9e61ade6161L, + 0x173abc1e3b5c8ecL,0x1d9457ea395a40eL,0x1432ecd48a19321L, + 0x0ba32379b5a8fe8L,0x1960ee3b72c2029L,0x077a7cce6976a87L, + 0x1ef21708a1d07b0L,0x0f3027664f64d29L,0x0d2731d8987bc40L, + 0x183a25df4b92018L,0x115816b5ebbaa36L,0x169c6242b67ad1dL, + 0x04377f555e411a0L,0x1ea5238181f4312L,0x020beb63c399a88L }, + { 0x0bd81b70e91e9a8L,0x0020c61b86b599eL,0x042a3aa88dcdccdL, + 0x08d8facead04bb6L,0x14c33ded8f2b09eL,0x0af1fdf144774dcL, + 0x1a22336109aec5aL,0x0c54c2ed90db9d3L,0x13f4c89226165e3L, + 0x0a7208fb031fd84L,0x1eb08323e781314L,0x0d39bfa55ac2d20L, + 0x048452199acef74L,0x09561a315d185d7L,0x0b520b4c1a04a4cL, + 0x0132a0237d0e792L,0x00aff4cbf89e833L,0x0010c4ea968a385L } }, + /* 23 */ + { { 0x1e419dd92599c69L,0x0110dbff6196539L,0x0f4826efeff56e5L, + 0x08c7db12b7657f3L,0x1f486f7961ea97aL,0x0a0d1cb3048a359L, + 0x104d6f471e817f4L,0x0f78f3d919f07acL,0x17f8fd42f988350L, + 0x1e5a9db8bd9e813L,0x1637359f296886bL,0x01599a292f0d0ccL, + 0x0e34b95067a6a6cL,0x0fa24ac60b79eb8L,0x0a00848dc48238fL, + 0x058e3a5bac9cdd8L,0x0fa33b2c4ab3078L,0x03ddfc55ea908bbL }, + { 0x09e4aafa78b981aL,0x1a71b182764145fL,0x1ce4e5677a8de22L, + 0x064816738e188b9L,0x08383b7d70a9bddL,0x1d081324ce6bee9L, + 0x1c6ccc1a42cb8c1L,0x09044c5ab31dd25L,0x0c62d77deb4725aL, + 0x0b792de3de1d507L,0x162d97457bdfea8L,0x043a172dad1ec5bL, + 0x03a00f1906d9792L,0x15ba63a05c9442eL,0x15d888be91dae6fL, + 0x0a09e42fbb76b8eL,0x16bc2782c305788L,0x0430684b67c0938L } }, + /* 24 */ + { { 0x0bc337d4d79bbf9L,0x1f55c34fba7c07fL,0x0254cc41354d754L, + 0x1432df172ffe6d4L,0x15ce69092ab820dL,0x141baa4b0e9e8fbL, + 0x12e6ec65fb01011L,0x1474d19c37f274dL,0x1503456ffc5f021L, + 0x08516d8c4a07fedL,0x143e3fbc010826dL,0x02ee092cb0eaef8L, + 0x198bb8770ad635dL,0x103c729f392bb36L,0x1f20de23866c0a2L, + 0x073406c9a9995f3L,0x1201a3df411f0ddL,0x03f40722101d6fcL }, + { 0x15f8a57539a1ddfL,0x073d7772432b125L,0x047605808787492L, + 0x17fa6da58838f69L,0x0aec00d92e7b871L,0x09f8d9ed1c5a820L, + 0x1e35bca09d84986L,0x066d387fd0df63eL,0x156c8b786e827acL, + 0x143fb639a43e47bL,0x1c885c677b96f05L,0x0e7ffe732831571L, + 0x14a9027c8004e84L,0x150e971479c2600L,0x197bbc6659efa6aL, + 0x106f90d2d0da7c0L,0x063737c6b08c7bdL,0x02ee55ae8cf45ecL } }, + /* 25 */ + { { 0x184283a9a7d772bL,0x0f292f2a04acd83L,0x002219052ad5ad2L, + 0x053ae96552a8d76L,0x003b0b1bd444816L,0x09fc35933c48569L, + 0x00f1c79ea0af323L,0x19e26a57f6bb0b5L,0x1f29f16e3fad07cL, + 0x01531dc20f0621fL,0x1c8b15acde7fbf0L,0x0ca762489e4d209L, + 0x1f3a28bdea19d8aL,0x1b6a2ae7331adb6L,0x1fcdcd462da2147L, + 0x17b56e958503139L,0x098ad40f9df8b2cL,0x0046616cf56e4eaL }, + { 0x06a6866c170c84bL,0x04f45ad24d24217L,0x03834132264aee6L, + 0x10c3674846f61c0L,0x10d0189955ad347L,0x0806599e4a92285L, + 0x1db438e4885578cL,0x0a6324cb6dde064L,0x00fe8595a76d42bL, + 0x14b6f707e31a9dbL,0x18372091be24f82L,0x057de14e9974ec3L, + 0x043fdfad9b4ec90L,0x07edb4bab080434L,0x1dd642975a98391L, + 0x0146e7ea75590fdL,0x1b0d29e6be01287L,0x04c8fd6e0aad52aL } }, + /* 26 */ + { { 0x0bc4b0fb4844ffeL,0x1138a307c5c38c1L,0x0389338fc7cdce4L, + 0x082c6a33d915800L,0x08288b5ff0d548bL,0x0e4d383d57c215cL, + 0x1f59e7a2c3130afL,0x18740daa2a4974bL,0x0d0b1afa0f93cdeL, + 0x004aadd6fc4fc78L,0x0fa4b7ba8cb248aL,0x1f327fc0b7c90d9L, + 0x15fa6919aa0cae3L,0x17078dc5f930384L,0x1b3e6203d51d079L, + 0x123ae55da3ee861L,0x1e99296f76b7349L,0x03367c69412cf87L }, + { 0x101905b226f5868L,0x174460b484f4f4dL,0x045928dfad53040L, + 0x119302c64657a11L,0x06bac53cf72253eL,0x15557b9bfc274ecL, + 0x011b8b8d49152bfL,0x05ccf90deee5940L,0x086bce50e666337L, + 0x151d4b05b4a8502L,0x06535ff06aea4fdL,0x02578264dcdcc3fL, + 0x042e56b0051957cL,0x02c93a064db2c7fL,0x1fc9a96734a5ff2L, + 0x05d76eca99d362eL,0x048aaa699dba79dL,0x02fe5062d0765b2L } }, + /* 27 */ + { { 0x06e25f3569a6663L,0x0bf73f3552653f1L,0x169a3462e030256L, + 0x0a4524ce604b499L,0x07387209450602bL,0x199d29cd7afb280L, + 0x0a547fbbb6cd099L,0x1341eb9ced10caeL,0x1872a360b8398aeL, + 0x01a3d4015987b61L,0x04ec8c685885618L,0x1f25dcd8dbd9a42L, + 0x085cbcf9e66fd9cL,0x15d1ff4242f852dL,0x1b35c9f5e969b90L, + 0x0342155fcce40a3L,0x0b4e09c6bb2a208L,0x032bd65f85cb9d8L }, + { 0x130466fc274c8d4L,0x128bb1854ca6898L,0x0329c1e50d7d09dL, + 0x0dd712f40c42e4bL,0x161ee1304485040L,0x0bbc5df9c6ff772L, + 0x0e7a447d3eb3ea8L,0x064ecb8cc2f7357L,0x1b135499bd8f109L, + 0x075b19bd39dc8acL,0x0733c5bdfa2dab0L,0x007430fbdea7e58L, + 0x09830b9c625b32cL,0x1788729c44d68eaL,0x17d56f05cd7ab8cL, + 0x1b61b6397b3853aL,0x1bb42428c47e539L,0x01e96d209642959L } }, + /* 28 */ + { { 0x1702b6e871f2865L,0x1b1cf8a14906b4bL,0x0a8116d618455b2L, + 0x03e7627024650a4L,0x112206e8f3943adL,0x06acf5736110053L, + 0x1dd670a24396a8dL,0x0cf56a5fa81ed6fL,0x0f522c8de180bf5L, + 0x00f4bd9566771cbL,0x1d606713a972ec6L,0x0bd156a3a7dfc06L, + 0x0abcb50fd80d998L,0x0bf0e406f1364b6L,0x058d5f7ee75ac4eL, + 0x18ff6b0563029efL,0x06189a7822107f4L,0x001577796e01abfL }, + { 0x1a7926f2c7ec9beL,0x1983f392c590095L,0x08431be9ad28a4bL, + 0x13c5798b56e9cc5L,0x1bb8c07380c0854L,0x0f8ca6da0b06dc3L, + 0x12a7357bc14a4caL,0x1a21d71b428dbb4L,0x00b5d43d215ea23L, + 0x075f7817e1a5fd7L,0x0d9342121d5e9dbL,0x06d05a69994759aL, + 0x021d2d95e2c1401L,0x1c37551404e533aL,0x0597fb30ff475b9L, + 0x124073d6226db45L,0x0b048871baac077L,0x035a23600a58ad7L } }, + /* 29 */ + { { 0x019eb2e25e8fe80L,0x1bc834c11c50be4L,0x065a07906124ad7L, + 0x0d31d4da8bade3dL,0x1fd02e4058ad8adL,0x0920b6add72d6a5L, + 0x1f28405b70c9ea0L,0x1231663530b4668L,0x10b4da61082a653L, + 0x05c8d96da461afdL,0x1a05f34aabe3107L,0x09079bfb9b813d2L, + 0x0112b692541a630L,0x1c51504bb82ac9bL,0x1314a057f735c4bL, + 0x0c12ab356c4746bL,0x12f30c8ebe0932bL,0x04309a125d84702L }, + { 0x0902063b2231d8aL,0x11194ecd30b3394L,0x1f9c1c6a7c9ec3dL, + 0x00c07e08fd55f41L,0x1d92a1c36bcd896L,0x0a41db08c6653b7L, + 0x14988d05398adc7L,0x0b5424799bb74e0L,0x11a576437fd9b5cL, + 0x0980de1264687d1L,0x02b51040909f369L,0x0bc1a754d8052deL, + 0x00072a39960e6fbL,0x02069fd6e6c6244L,0x047550536bf284aL, + 0x0e69a53e9947bbdL,0x17c0037c5988441L,0x043199d4cce67f2L } }, + /* 30 */ + { { 0x013a751ecf53b40L,0x1637917bc52a169L,0x038bc4eb95b73fcL, + 0x1e1cc2e91c1eb3eL,0x172c414591f8ccbL,0x0e6e5b8556f65ceL, + 0x1f1c1acbb614932L,0x0051c016e583d5fL,0x089b24285aa7281L, + 0x13f53f05b3ce57dL,0x0e30993c29bdbeaL,0x02e61d00872eba5L, + 0x05c85730497ed7bL,0x04c3749f2d49f5aL,0x08302bf24afd750L, + 0x1875ea4d6b538d4L,0x0c90adf47c9b99dL,0x009592ff15d1016L }, + { 0x1b8d78a33eea395L,0x09b0c7b19fe2e04L,0x18a49c3b3bbf1eaL, + 0x118c51da18fd042L,0x01d68939524779bL,0x176e4848edae50dL, + 0x1cefe189b863961L,0x039fc047d17fd67L,0x06279fde1025017L, + 0x09763ee2af0b96fL,0x1a1a571b5329179L,0x10f17b7821e288bL, + 0x086fc3835e42de3L,0x1f085b291588a6fL,0x039e3fa7eae9159L, + 0x015948223b05472L,0x174576b61c2aedfL,0x010b13cd4ba5665L } }, + /* 31 */ + { { 0x14cdabf4047f747L,0x1119ee098ad0f60L,0x0f4d0397429c0f2L, + 0x13768270d2b3cf9L,0x0f01fbd81fd0c4eL,0x15c11e8c4e84588L, + 0x002854112710a9dL,0x1c9038449427316L,0x108084e4f8e8179L, + 0x0c57cca34c720f4L,0x038df15842fcbbfL,0x087f4fa4f21e3c6L, + 0x0cb31953884e6a0L,0x01bccefececb730L,0x1fe40bf9d7e61b4L, + 0x082dc76951e23f1L,0x15efa9453787588L,0x010341f1fcc13a9L }, + { 0x1582e26d0378878L,0x0a611d3ca2bc3e5L,0x02fe3d9a22ce788L, + 0x0a80a2a4e027a00L,0x00111f5d7548d4fL,0x1ffc813889e0aeaL, + 0x11730efd6949aa2L,0x00b7b4d60213692L,0x183dcc74ebc2f3aL, + 0x177b14221f7efd0L,0x183ba559716fd0aL,0x021ab25e4875a5cL, + 0x121bc3bf514f0faL,0x102bb53a3572c59L,0x1cc206a04ec21a1L, + 0x1dcb2178047f09aL,0x1959fd03aa032dcL,0x02f20b5fa93eb63L } }, + /* 32 */ + { { 0x0313760026cc23cL,0x0d5775ad9482c12L,0x0be3174bb85fe06L, + 0x17dcb988055244eL,0x17def07d8048e7cL,0x17c10f6de3eb773L, + 0x0ee25875a4913daL,0x148bef2cddb32d9L,0x0f81b17ea96a155L, + 0x16cf7b801f9f6abL,0x19641ba20a96cacL,0x00e55d28e300bcdL, + 0x11658c76f486fa1L,0x0581ad501a6cfe2L,0x0f992067d80f703L, + 0x153df6f673fd6ebL,0x1e3ca87554acf04L,0x027fb417643da7eL }, + { 0x125627fd0a10ad5L,0x02e394b4737a298L,0x15ae01a8458dff5L, + 0x1bbca067c653037L,0x1f4f8988b92de1cL,0x13f0ee1da25a2f5L, + 0x161e3286e625b6bL,0x08ea42cdcb40ef1L,0x182d472bea51168L, + 0x1ee9c157944aa22L,0x14580975bb1327eL,0x16396caa560445dL, + 0x13a1e6210f3614eL,0x010d3a53b1e2efbL,0x172f537a4580a14L, + 0x1c533489948018cL,0x07c48cb187e0f15L,0x028f5c0c71a0128L } }, + /* 33 */ + { { 0x1c1d178b92100abL,0x11eb04b02dc1c8fL,0x0956dc7967437cbL, + 0x0a29f97c08254f8L,0x19fd06af3f8b667L,0x01068387451c9aaL, + 0x1ef9558c9940848L,0x0a8cd2df9a2a51cL,0x16588514b0c7b76L, + 0x06c07c62c8952daL,0x1fbc13cc932dfc3L,0x1d9f8db47aeb175L, + 0x1831d1df2f6b53eL,0x19c095b6f6f7a46L,0x18980c7ccdae595L, + 0x1e137905d5c95dcL,0x07f300abd32d244L,0x045857caa98ecb2L }, + { 0x170180a2e603544L,0x19d61910d66cf5bL,0x19958901c0c8ad5L, + 0x1b7135787a742feL,0x1793225aad3e74aL,0x012b25c51e971d6L, + 0x14ad515eee813bcL,0x1d110eaca5ff85bL,0x0d2905d15e67143L, + 0x0c425a1017246b8L,0x0648671d8da95dbL,0x08426bc6f1be0dfL, + 0x1d10c64a02a8dc3L,0x060abd334ae0eb9L,0x0928d5335a93b3bL, + 0x0653b75b983911cL,0x0d08024f1b29839L,0x029b1f2a4a6d245L } }, + /* 34 */ + { { 0x15523b7e23fc641L,0x07397c33338318fL,0x17d6380274bff95L, + 0x1f18afebc252942L,0x116d64dcf203997L,0x1517fdd114b9265L, + 0x03b59a5ef93f52eL,0x06c7ea0fc8c14ddL,0x00afe3a5d785085L, + 0x177b66ecaa04104L,0x1f6227cb108df3bL,0x1074b870a4a6e03L, + 0x0d72a212f1496d8L,0x0ffbc7e6f12e33fL,0x1bd05192d059e0cL, + 0x00d2fd32ce00982L,0x0c3fa45c3a1c45bL,0x03199a00c1fde98L }, + { 0x1c9a0cca2fbbbceL,0x1b72e55065ba21cL,0x0438d0e3b38e1dbL, + 0x1c27005b0539cc0L,0x1cd45a1b0aad148L,0x07e0f04e1f2e304L, + 0x137421d72e165efL,0x057633fef21b0b0L,0x12598b81ed81c2aL, + 0x0c5ef97815f03f1L,0x1f23bae5d973a44L,0x1b11649f2b5c0e9L, + 0x1c0c98f09d125e9L,0x105ba5939dd8966L,0x001df3929abb81eL, + 0x004de8e47a5f381L,0x173959447d6bea8L,0x049d383ae0b1405L } }, + /* 35 */ + { { 0x0bbefe2715b27f9L,0x0d2f11514049193L,0x0ebff56289aaa4dL, + 0x0cf8270d28bbbe4L,0x092a215354c83e1L,0x0684faa23ccde4cL, + 0x1a9a139b91c426eL,0x16d8c75ec2dab11L,0x05e896706883ab1L, + 0x009c9d01e90499bL,0x1ca4864b08f768fL,0x16f5b9edd487a05L, + 0x08791559e1ab70cL,0x16b87f858921a75L,0x0cae914101a036dL, + 0x1971e3421fca450L,0x1fdd69f9c08e5f0L,0x00d3a11562258a0L }, + { 0x1a9dd2e9f40b675L,0x03301fe638f9ce1L,0x098465238d08a9fL, + 0x11da15690831273L,0x0e31ca6b8f3b615L,0x146db1d1d53ecbfL, + 0x18b92f07a197bdeL,0x01e62bf181258f8L,0x1a260788f9f5c6dL, + 0x0c19894a5b79f62L,0x16f358dad36126cL,0x112178d33536e75L, + 0x182a1175e766e14L,0x1e29e527df9bc86L,0x1fd8245fd0d816bL, + 0x1056caefed88f0fL,0x19c827c7552600cL,0x004a26b184e92acL } }, + /* 36 */ + { { 0x1deb63ee6ab9620L,0x07d36bc366c0467L,0x1609158c82cf7fdL, + 0x058928722a28bdbL,0x173b3f872ae5f86L,0x17cbd4ca847409dL, + 0x06d88ef6017cf94L,0x1f9ee36b8519305L,0x0b394c70e86e0ceL, + 0x1a7d8d491ded9b7L,0x1d618b6f89f9694L,0x1be70756c2d3ac9L, + 0x1127c828cbbae23L,0x1d183d456eb6f8dL,0x0777d986406267cL, + 0x076ee6d990cb302L,0x176a3cb77747994L,0x03ec4f9c1b7ec32L }, + { 0x0564242c9f92b2bL,0x0353ae237195efcL,0x02ddfe669715c03L, + 0x1006292ad127cedL,0x02ce6709b6efe85L,0x176249ddff450ceL, + 0x10a35c868ec6fb9L,0x03a4ddddd5386e3L,0x1d798115e15177eL, + 0x1df9de7583452d2L,0x1688811b4ad2cb5L,0x12b6b37d3bf9bf1L, + 0x1c77640b793df09L,0x0d15e9e2e4b44bdL,0x0bf9d133833d309L, + 0x013762de8badd13L,0x0e6b53f3acb3a85L,0x0224d7c0fb1f953L } }, + /* 37 */ + { { 0x0fcf132a16d9377L,0x1bbd9bf0d17cf61L,0x04ba1b466b966acL, + 0x0da0277762e5c34L,0x0b5f66bad2b12e6L,0x0f55a804b9702aeL, + 0x17b0b44778700e6L,0x12783e629fb8cbeL,0x0fc3118418a9ff5L, + 0x1b9e0f670292373L,0x144d8c589415b77L,0x17aedf64bc33851L, + 0x04845cd2d730a9dL,0x09b74296824f692L,0x0322a0f1de6e0ffL, + 0x100670b46bf8fedL,0x0f5299bf1e1c95eL,0x007430be190448dL }, + { 0x172060267c81b5cL,0x04ee6f39bc39e29L,0x02c2a0513f40beaL, + 0x0e4c41190654e86L,0x18ea40f53006c5aL,0x1209d2270333306L, + 0x0527e774097e625L,0x1857be701988d72L,0x1801566190a125cL, + 0x06b51dba93c9e1bL,0x004dd1ade98bc81L,0x04d0b0bab2f16c0L, + 0x188395fe66a9cfeL,0x035930fb6e56865L,0x0764862ead1a3f1L, + 0x04805941debdf3bL,0x087c507d4a85e45L,0x037a2027899367bL } }, + /* 38 */ + { { 0x1e1920b4febd3ffL,0x11a6c7efe95dd51L,0x1cab866a60a7298L, + 0x018deb78416fa35L,0x1aa39ca923de161L,0x063855f1026df9eL, + 0x0dc2ca8b7a6e1b6L,0x01c4e5c186ef93aL,0x080914c06e56551L, + 0x108f3d42be5db58L,0x1f1bbf6099a9badL,0x09dc612b00380edL, + 0x02b9e24063dfac3L,0x1c3d52e2b4ffa05L,0x11c334a9ee8c6a5L, + 0x1e0e81c9a3fbe67L,0x1e2903e31326895L,0x0482bb8fc3fdb38L }, + { 0x199ba0da4062beeL,0x191c64a6becfca8L,0x06f078248b00639L, + 0x03625b0abfea7e5L,0x0d68ca29de9b2a8L,0x0604bfb24f9f76bL, + 0x0628192b7f0d314L,0x049032c95733b67L,0x000d59c477a5872L, + 0x0ff51cb3a62c81dL,0x1f63b85410f7402L,0x14dcbe3d9840d55L, + 0x030db9b7b4c5721L,0x13646a955b6b524L,0x120a89c1bff185dL, + 0x1ef507bc483ad59L,0x0cc0605f05227f2L,0x035114a9db2026fL } }, + /* 39 */ + { { 0x0452d8f74fce389L,0x11a60157d2ab249L,0x12efc3b5e094165L, + 0x166ee31c1b26ef9L,0x1fa69a4d89f4045L,0x0ad85d0883a73ecL, + 0x1b79975c2ec1dcaL,0x0f7645aa95be20fL,0x15c39a3d8a1a29cL, + 0x191b6016bcaf1d5L,0x00b400ad626544dL,0x0b7caf217dc5ee5L, + 0x11a8e65ea25e226L,0x1000e75ec8f0750L,0x071500839c69c21L, + 0x0d3022d201eb458L,0x027c3b2d5c0357fL,0x029464f5030cf1aL }, + { 0x0dc86b45f26c577L,0x1a3844a1c5ea28fL,0x004de4960a9fe01L, + 0x01bc3cad3e5bfc2L,0x1a55a356e08eacaL,0x0bb10b2fca977d4L, + 0x1c7ca93602d4f92L,0x1e1a56cb0ab9abaL,0x0246704bf66cea3L, + 0x09fb20fa49191e5L,0x0615726b6c4c946L,0x059c5a33aca54d0L, + 0x105b82ed7b86d52L,0x070a8694a9b04f8L,0x04fa244ec3c0252L, + 0x16892475b17f616L,0x157cbb1556cf794L,0x01007c849b9c5e7L } }, + /* 40 */ + { { 0x1b22fc58388387fL,0x178b8147441e2fcL,0x0e4346de5cf33c9L, + 0x05edd922e288f95L,0x030cdbc08d5d4eaL,0x111e15970b7a4c6L, + 0x11517724a443121L,0x161d629236061b7L,0x0631deb2e14de21L, + 0x051083317f4187aL,0x1a5e70de707cfc1L,0x16d1f60d4f2b498L, + 0x1a1619dfa98a732L,0x06df164d9d22193L,0x0627faa468c1f4eL, + 0x0663f273791a407L,0x1dc3daabaf20f4aL,0x02e183f4c6e87aaL }, + { 0x1c4e0c435b233daL,0x14842917b7cc2ddL,0x1486a2c091a38f4L, + 0x1352d22dcf33ba5L,0x014bcced978f40eL,0x083b160193ec363L, + 0x1cbb657a5540acaL,0x0661ffa432f50f3L,0x0c436513750e0bdL, + 0x1618a450413e262L,0x004aa0ff3f02c89L,0x02fc63250b138f3L, + 0x1e8830f42dc3d8dL,0x0583fc1fc5ab967L,0x144523df367fe49L, + 0x1f358663952a014L,0x185d0c539684c59L,0x00ef8b6fd60a1a3L } }, + /* 41 */ + { { 0x07bb4ac68bcacc3L,0x169a7a187ac67e6L,0x1d3f518615681b7L, + 0x088b93e1798b3f3L,0x0375c892f549199L,0x02cc1d6e2fbf632L, + 0x1421c6e1c23c4f2L,0x01f6654b98905f9L,0x1efdcdc352d6b4cL, + 0x1d9278245637d96L,0x0b53d4ce4191c52L,0x0a5f70747588b30L, + 0x082337a223162ebL,0x05e1ede9b8986f9L,0x19eb03b739ee00bL, + 0x0e2fd1672b2b248L,0x01721d3d2e81b56L,0x0394d3fa8232893L }, + { 0x14ed1aa8420f90aL,0x070cf07f2642ac3L,0x0aaac2f9d2bd8daL, + 0x01194c19536c5a9L,0x1645a86776fcc48L,0x18d92679885ad2bL, + 0x16d104c6eb26f76L,0x09ddeefae3a5bd4L,0x04706d21072fcc6L, + 0x0dc9348b39ebbf8L,0x002fcfa278198caL,0x19a6e80efa8045cL, + 0x0d829232e2472d0L,0x1c6e42999f10820L,0x0e3d99cbe45b7ecL, + 0x1c33a91776b3629L,0x15c19de9f4ad44bL,0x03fb69b249196ceL } }, + /* 42 */ + { { 0x1d064de6e794819L,0x1b4a77c175ed09dL,0x1f82e478a01169aL, + 0x060f4879a43e02fL,0x030433e9190d31fL,0x1fee5a361379133L, + 0x04702e9222a9c2aL,0x100831b210b48c8L,0x11b934fe6bffb58L, + 0x0e8f11bf1007c24L,0x1358fe95504f6ddL,0x1aebc4767eefbe0L, + 0x0b0f91bd30e216eL,0x1b94e284d02c336L,0x0aacb5e130e5765L, + 0x1ad0dd92fc3108aL,0x06c8cb7c1f90093L,0x0168191cab14784L }, + { 0x01c94074a44b4c5L,0x0343ce638164c54L,0x0a1f3ac3725ee61L, + 0x0cdc75464396a04L,0x04c256c23030112L,0x0da422e05643b1fL, + 0x1cd6d940d348395L,0x1b9552d4081e481L,0x0046d26d37cf7eeL, + 0x152d4709dc0832bL,0x112e5e0f5c30ad8L,0x1f10b3c9b51f0c0L, + 0x1a5457f5d12fbafL,0x1a98dbabc94ec80L,0x13a5ce74a787acaL, + 0x137b2429b57b93cL,0x19b5bd724fc4eaaL,0x039a609598f7cddL } }, + /* 43 */ + { { 0x0fe3c2e92f9b086L,0x0dc9f59fea2a24cL,0x022d700b1971190L, + 0x0389e064848f9c4L,0x079d29f68a52dcaL,0x037afa5af60becbL, + 0x0a044474bfb4250L,0x07e4c1ec7b81b37L,0x0de2b056f15472aL, + 0x18b86cf80394873L,0x08fa36dad723e46L,0x10739e6987dd45cL, + 0x011b973ee2345a2L,0x1d9268e2cdee2a3L,0x185068596f69b0aL, + 0x164032faa574678L,0x09f47bb16129d2eL,0x03e2ac54390fdf2L }, + { 0x1485a523f350fecL,0x13c62b51c6a605cL,0x1a88356a9934059L, + 0x05b2db45c91de68L,0x0f647b3cb85daa0L,0x0f4a36422f62752L, + 0x1d2af03469b2835L,0x00683b1a3829f53L,0x143972cc59c8b13L, + 0x1f0fa46a1a7fdfdL,0x13a4ea06748c619L,0x0120dbbde47e6a1L, + 0x19200cf12c49f53L,0x1202197e1e17367L,0x125ad4909a47305L, + 0x12f7d7ffee968e4L,0x14844527c9f020aL,0x01a66bee53d9e21L } }, + /* 44 */ + { { 0x031761a59e7fe87L,0x1718d0023e6b978L,0x19a3eb8c3d8ac7aL, + 0x1b6e3b62864f205L,0x0e0038f4a666f48L,0x1eebb6baf7333c0L, + 0x13570ed16b19c0aL,0x0221a5f705141adL,0x027ce7f1d9d8c5bL, + 0x00ff0720905af4bL,0x06e612e499f0dc5L,0x0b13ac06259b2b4L, + 0x0eda5493565206eL,0x03863a560c339a1L,0x15ec2ccdd1482e4L, + 0x118284e07976b2aL,0x087f621f59ca6edL,0x03e758e6155fbdcL }, + { 0x047a5bbdb7fd65bL,0x02e601b64a2be03L,0x076e7849c62b635L, + 0x09d274ff638db53L,0x1d1566a1ed1dbbfL,0x00648ca28964ae5L, + 0x149a52186e8036fL,0x15c78d985313cfeL,0x1671961500941aaL, + 0x1e7ae87e4629c71L,0x1a64a68969547efL,0x130a2f941e4d5adL, + 0x0afa89ef7e90710L,0x18d5a2a4ba1dbc7L,0x1470db4e757a8c5L, + 0x0ad1ae885e7e7cdL,0x15c25a683e0059dL,0x00fb14d4c913e76L } }, + /* 45 */ + { { 0x125ddace45a1c3eL,0x149b2a0fbaa2fc4L,0x1f2cdf9fe0a1cb4L, + 0x067c98f3a48ac45L,0x1c2645d68823451L,0x04015caeffd7c24L, + 0x07e80c1e3d37665L,0x198acd24fe13a67L,0x19a500a1e9fd91dL, + 0x10040c0055855ebL,0x04d68e0653977f3L,0x060f315be111b2eL, + 0x189a45a2a79e876L,0x1c45a1cc9dd780dL,0x1ea65f5bfb58551L, + 0x11ddb301cae45ceL,0x1a2aac90ffa2a37L,0x0253afed145ec02L }, + { 0x09a8fbb55e74cbcL,0x19c677d58c792e8L,0x0b5a5d93b0e9cddL, + 0x17cfc15a621f847L,0x0481cc9bc5a7d35L,0x05761a73af03477L, + 0x18f13c30baa64f5L,0x059e2649fd01a94L,0x15dbb7c1699b059L, + 0x016b3a6d3f07a35L,0x159b1e8c03eba91L,0x104266675906b4bL, + 0x0e8c408496e83dcL,0x0cf7afe0b877c09L,0x0d3a18a5b8772daL, + 0x00fb0dc56ee362eL,0x19a04629cdc5835L,0x02c0cfcd711ec0bL } }, + /* 46 */ + { { 0x19691216aa78811L,0x1747a1081f3e1ecL,0x01c08ae79a63d93L, + 0x1c9eb059bdbbe02L,0x0ecfac1ae6001f9L,0x1c9804925304579L, + 0x0a445bbd31e1018L,0x140a4c5d5cdd7eeL,0x1ddbd0af58c4ee5L, + 0x1ad7fc8766c3de3L,0x16cd31bc93c4521L,0x0503d0cbe2e45fbL, + 0x06886c1b9a48104L,0x0f7a118fcab4921L,0x09fa0b9bd7cc822L, + 0x12b915eb0f59fa1L,0x150d65719179ac3L,0x03a2cb01e09b253L }, + { 0x02475bff41ae519L,0x00fd8a57c79288eL,0x134abbecb0f4d10L, + 0x16a39b5e10e1bbfL,0x0208bb199b2d385L,0x19f9fb4298e12b4L, + 0x05da45b2277d930L,0x1758479f53248aeL,0x12339b51e86d010L, + 0x06d87469131c189L,0x0785e403fb7adc2L,0x1b9746d0fde3eedL, + 0x03914764753fd96L,0x0622e46ee682359L,0x0d0f5e3cffc8190L, + 0x1dd21dfa2cf7b70L,0x145493ccb6d4b77L,0x019812a89d9e7bdL } }, + /* 47 */ + { { 0x0f0046935eaaca1L,0x025bac488c8811bL,0x19979b4a553030eL, + 0x1363d3adaf966eaL,0x029c2757cb9199bL,0x139c683ac291a4eL, + 0x0909e272f46eae3L,0x113371b7d20b247L,0x1a237793e18fe18L, + 0x0138babd3a17041L,0x05e7493baf584e9L,0x00a9a9e59eef189L, + 0x11958705de40325L,0x19ecccdd51dc504L,0x03fb8786c646f64L, + 0x1be2975fdf74876L,0x01cb3bad1843facL,0x0499456d821c3abL }, + { 0x1e84e80f906b872L,0x091d03c131332d5L,0x09f8ce6333ddc15L, + 0x1beab6a647b138dL,0x0554dea82fab551L,0x0ac4e6d02bc7650L, + 0x15d43bc9948f4ddL,0x1fdb1fac4850c95L,0x093f27fc5178fe1L, + 0x19f37984efc3a11L,0x0b9278dd434151eL,0x0d64bb80714250cL, + 0x0284db682b7d90cL,0x0c40c98560d0d71L,0x1cf82911fcf6adeL, + 0x04b8a61cd7aa575L,0x1e70680025bf62dL,0x00550f9e7d6e86aL } }, + /* 48 */ + { { 0x182219022a10453L,0x15c8e1501d085d4L,0x16565991bcef747L, + 0x09e716df8d5f76bL,0x18cfca1da58de34L,0x186d026723e1f2dL, + 0x0bb5bf36385b43dL,0x11d58886937b44cL,0x09320d87bc56e2fL, + 0x071f5040c89c72cL,0x18b7fe8ac8db027L,0x14b91cfdf61b4b0L, + 0x0b16ac78eb6b0f9L,0x184da8d7a5a9a19L,0x14658a1bfd0c415L, + 0x0075a11c46df11eL,0x05e1f93f176eed4L,0x02ac99bf04b1b2aL }, + { 0x0ddf738d8fd807aL,0x0764ed589891118L,0x136d896bef0fd38L, + 0x093e25f12a2945eL,0x0c3044fdd5b7060L,0x000a47da379e11dL, + 0x195506c8cb47fd5L,0x0eac368b1ea7369L,0x1f694b24a0dd70bL, + 0x1e3214c944ac0ecL,0x1526fbb97f88b43L,0x08fed4317ec780bL, + 0x027f1929d67af34L,0x00aa8f4674b50eeL,0x1753e89abf980a3L, + 0x059684fb595e656L,0x0d34a1631bc545cL,0x04980387cd8648aL } }, + /* 49 */ + { { 0x0f32c5e69a9bc05L,0x00ce32c4e25b9e9L,0x197a51997e70297L, + 0x0779f6987212b93L,0x1ddb7c318ab0f29L,0x19c0245c83843b8L, + 0x166f6253a59619aL,0x0d3e335219ec0d7L,0x1cc1d58dfb6fd2dL, + 0x036e627230ec534L,0x1709dfe73920c62L,0x132cecbf150588aL, + 0x0cc3badc8d749a5L,0x088966d597fe334L,0x10f1f2ce0060e5aL, + 0x04449530f2b8764L,0x0148775f310010aL,0x0021d10a0ac3dafL }, + { 0x1be9dbc3a873752L,0x049fa17a217f73dL,0x0b2306308607b85L, + 0x01c52ed3cf30394L,0x1e768c5f00ce309L,0x0bb3bf5a3135646L, + 0x05398cfa73918d3L,0x17ff138595bc1f5L,0x004f5cc1141f5b5L, + 0x0b2fb9b11146096L,0x1dc1a8301733949L,0x1fff7c90f89fe37L, + 0x09a499f1a45d07fL,0x0c6ca4001f621e0L,0x0fc4be13d39e6eeL, + 0x01adb1466b42c0eL,0x0e84bb5eaf70f97L,0x00c683a3df92685L } }, + /* 50 */ + { { 0x0d3c77c84601fafL,0x12df1578e0fb92cL,0x1e63445b601b251L, + 0x0dab61b279fec4cL,0x1ec6723a3996c0cL,0x1d29a497d0d6baaL, + 0x1362a59aa05100eL,0x0cbb89928445586L,0x1ddf471deed6758L, + 0x05652cbca9ea947L,0x118ed493afd9f76L,0x10e2fc4b69a765cL, + 0x1a43159daa25824L,0x019abaa011e2d6dL,0x0e2c6995163e71aL, + 0x1a4639ed0bb4ff2L,0x059981a4fdacefeL,0x0388849f6845dafL }, + { 0x0aa3fc6401f161aL,0x0c2b04ba62f4389L,0x0bec5ed77e0bdcdL, + 0x0f491cc5329544aL,0x09dd847db0b82b0L,0x14e2d30011a0ab9L, + 0x1d4e3c795340114L,0x1979838a73cdb31L,0x136162b5328d3abL, + 0x0d1bc9c15427866L,0x1ea06d37b9d211dL,0x0bf698477e37ee2L, + 0x1f787e8b3e16cf3L,0x0cdbcd583fe8e14L,0x1db182edf69f9a1L, + 0x0916a0e4201410bL,0x1d431840159e7edL,0x00bc4c5ed26ce4bL } }, + /* 51 */ + { { 0x18483d8ae1b8cf8L,0x0a5a174d1442b66L,0x013c81292f08c8fL, + 0x1194f4d3f4ec66bL,0x1757bab24e0b222L,0x02fce5457ded45fL, + 0x0570e16c90221b3L,0x0d68ff69027a835L,0x13f1bc53cc2aabeL, + 0x1166d1f8d68acceL,0x1b02070c7aa6c7cL,0x009602c29582365L, + 0x09c6afa7ab048f3L,0x00a06e1ee718e77L,0x1a2aee956bdd8cdL, + 0x07dfd096f566fb9L,0x0b250de7648c7cfL,0x039d446e78a9ab5L }, + { 0x186828806e83b39L,0x12209cfa201be9fL,0x0c3c5f6f21051deL, + 0x1ea9a2ea93f20b1L,0x12307ffe2db64f4L,0x093130d11e75357L, + 0x1fc98e4fbf5553cL,0x06a5e9ccb1421e6L,0x1a4437ce3f4ee1eL, + 0x077a153d49e6f45L,0x0f27d24e6aa4059L,0x1ad47af6b9a83bdL, + 0x11f88a3acc44223L,0x16304516bc4d350L,0x1d5b0195bee77e0L, + 0x14601cf3b71c777L,0x01e73c56af2668fL,0x02979958bd71cb5L } }, + /* 52 */ + { { 0x0f524c1e714f71aL,0x109314d6ec28cabL,0x0761972b6f8f06fL, + 0x10b41f6c935b231L,0x01d192d9d88bf5cL,0x1925b7cf7d35491L, + 0x046738ffa0e25bdL,0x181d87f5c4964a0L,0x14b6af9f62ae0d3L, + 0x1e75d05eb0cb126L,0x0c24acbf6db8ea3L,0x06ec64c79a52fb8L, + 0x1ef95c43bdc91daL,0x06f5a26c98603b0L,0x1034c76244d9003L, + 0x1133ffafb9d0887L,0x0c178fec3b19871L,0x03cf0a69477efacL }, + { 0x18222359bb40c55L,0x1901687683d2171L,0x06a520e307d0289L, + 0x0fb0c94f1c91cd8L,0x0c6c55c92b5f24aL,0x096a843f3f8a050L, + 0x0784398b0412b38L,0x1ab361434fd8236L,0x0fd8a275fafbb3dL, + 0x1f9aa7f4d1db598L,0x0176791980a8077L,0x169b2776cbeeb42L, + 0x0b0f82fdeb3d371L,0x0f2342a2ed2e5f8L,0x0f545f918048a6fL, + 0x1e924a0bc21738eL,0x0e277cfa541672fL,0x006c761454cab36L } }, + /* 53 */ + { { 0x14cf73ecbeee995L,0x1c45e6a48f40600L,0x12b766ae9752cbaL, + 0x072609909ac2b4dL,0x0ab03c9a2f7d463L,0x1d5dca5d0280e94L, + 0x15dcb23dc8f7a46L,0x129910bf2eea080L,0x0b5e1d2b3c7fcb0L, + 0x0f73ccaefcb638dL,0x036aacd19126798L,0x1bbabec0f265719L, + 0x01b1243587db425L,0x0fe3a1a038128e5L,0x00ab2249b5f4efaL, + 0x14e9f182f262192L,0x0fc72522c154559L,0x043000f13e1b9a5L }, + { 0x1b00ba5e7693947L,0x0320f0096031589L,0x0383a15242a191eL, + 0x1fb2ae9abdc3487L,0x1bd3ba615173dbbL,0x1f503aca9975c64L, + 0x04ae47d06f2e17cL,0x1695839848f1977L,0x00f34648e1ef901L, + 0x0c94e8f6959d977L,0x1c7aaf0f5d6ff37L,0x0dee2739e9a48e1L, + 0x0df04249535cdbcL,0x03fe59c1e6c322aL,0x17e4c30781e6049L, + 0x1780173e413682fL,0x0c14225fc31114eL,0x00102c8e59a3ca3L } }, + /* 54 */ + { { 0x1003721275e0af4L,0x0a0f7f3c52525f1L,0x13db45d5d215c84L, + 0x0e2d1ccb3cccd9fL,0x0e2842ee5fa1d73L,0x05eafb131f1f2a0L, + 0x0412ab7b30f5252L,0x030033bc07a48d6L,0x1f8a9e903f343d8L, + 0x1abdd252d860698L,0x1b14194789d97f2L,0x0a3eca337ecf048L, + 0x00f2119a0180c57L,0x1c10ea7a2f82e10L,0x070e819f9921ee1L, + 0x0c0a44c5f29544cL,0x1ef56cfe4897214L,0x0288ccc2fd0ef82L }, + { 0x019497db18586c0L,0x00aeb637755312cL,0x1ada5f368a2c011L, + 0x10f8328b28f8d48L,0x0ed3a5069a149b2L,0x04a65a5ab1b4fd2L, + 0x1bb89c24aa9990fL,0x012ab79ce7553d3L,0x034bb2870778935L, + 0x17cafd80375a993L,0x140c8e58e3d2162L,0x04d0b74eb7f10f9L, + 0x1d9d42d58129376L,0x12e36b26f996b79L,0x137b506932b55d1L, + 0x140cf30bea1f765L,0x19acf34ce0e9006L,0x02cf57932ac52bfL } }, + /* 55 */ + { { 0x1407efb6ec3876fL,0x03091f87a43243dL,0x1bfefe24c0e5e03L, + 0x008b5235605576aL,0x18811b829592eaaL,0x0f9fe4e72dc26bbL, + 0x184ee1a9c68d07eL,0x10182ffbb0de1cfL,0x088ed8297655a08L, + 0x0eb6e3a40eaf333L,0x1277d8745c5e5ddL,0x191bc7ef3c3fdffL, + 0x1d2046192e36ad4L,0x13a7ed316d8a98bL,0x1766451e327e9e8L, + 0x12e3809d9249f05L,0x1fb059d1e383a64L,0x01da2287513105dL }, + { 0x1b7a955c776dcdbL,0x052be40e45d239eL,0x000d415d83ecd71L, + 0x03675d86a75c50aL,0x07117be5e3e8069L,0x1667b09c019adf2L, + 0x1e45b8711f8e815L,0x1c24a79fbd6672eL,0x03decdfbaf5cb7eL, + 0x1e4bca7be7a5b82L,0x05a0327fe0518bcL,0x1c237c7b553e480L, + 0x1769f91d8a4e440L,0x05af4e2ee2e821bL,0x0df4935041b1ea3L, + 0x169443232134267L,0x014e893c8383764L,0x0253ff1866214dbL } }, + /* 56 */ + { { 0x18f3a702455c7c5L,0x11b74380abbaa73L,0x1491d88c98b16ddL, + 0x1c378f018fe6588L,0x115ed8772c98b11L,0x0932fa6a4757564L, + 0x0803eec134f0066L,0x1d0d6a563379f4aL,0x1c46a098193ea3fL, + 0x016399edd3ac02cL,0x12ef58625aab336L,0x05f99d1d9aa3a64L, + 0x1d02fc44b3ac09aL,0x1550bc25a94c8c7L,0x0882173c311792aL, + 0x0fac26ac4c681fcL,0x12353cbb676c50cL,0x041fd0f51b28935L }, + { 0x0ac86da10ccc646L,0x031bfbd8228f4b0L,0x18c228221840b38L, + 0x12406933057779eL,0x1c0bcda023c1901L,0x0a7ebeb83fe1ce7L, + 0x0eeedfd347c546fL,0x0c1ad4c9ce888e2L,0x157bdc676c5ac9eL, + 0x0b629819bdb08b4L,0x144e5b73d028751L,0x184a932fa58fa68L, + 0x04c2c4a739f3edeL,0x1535697129a574dL,0x1a57e045004e5f9L, + 0x1f57e40ed3a9a47L,0x1e0cee007c6de98L,0x030a04bbcc98e28L } }, + /* 57 */ + { { 0x1db32db15156623L,0x1bfde55bd33e11eL,0x1d41bc678f09a04L, + 0x05132498c24c023L,0x06804c1c34218b0L,0x157353a4950587eL, + 0x0f987596f9c1abeL,0x0d27627a47c1a03L,0x144545b47f87f4cL, + 0x0111b71026e0d51L,0x149874f14587b35L,0x14c77b11780ec26L, + 0x161599d7201eb46L,0x14dd7879bc636c1L,0x01ca083da557f85L, + 0x068148cfdd7ac2eL,0x1882f1b8a2a3e3aL,0x031b6d63b1685afL }, + { 0x0280db9b4c80af3L,0x04e68a71c4955caL,0x0b83451df772686L, + 0x10d1f3e29e4dce0L,0x00baa0b2e91aee3L,0x18a51494327b1d4L, + 0x1f2dab3607dce2dL,0x1fa61c370e18bfcL,0x1883ea1c3b10837L, + 0x0d13ca9b590244fL,0x0ca9a1628b697cbL,0x17e40751f42875dL, + 0x15dc70b1c4e2330L,0x14cb3c7a5ae2445L,0x17d9d7029e31364L, + 0x1a6d04677a1304bL,0x13f37b5c0767b67L,0x017b6deff2685f7L } }, + /* 58 */ + { { 0x18472fd2e4da7c7L,0x07e48d733bc9917L,0x0228f709a389c23L, + 0x00f33448486c95eL,0x11d58bff0f10dfeL,0x04b17377c896ac3L, + 0x1a829afcd77f262L,0x1825172df52be8fL,0x0734a79eaaad308L, + 0x0b9819bcfa1bdddL,0x12f639b3d53dd65L,0x1b9fcec65dd8005L, + 0x0b5319310447606L,0x0567b94ea025af6L,0x177c7782b8225f0L, + 0x0e89112c5170c77L,0x14eeced154ef87dL,0x02e5b70cba2c6aeL }, + { 0x0cef197008c75edL,0x04e9f7b77557c4cL,0x180861d7a5b5f3dL, + 0x1dbb361b143adf3L,0x19576daafcec2cfL,0x13eddc1c530e7f5L, + 0x053d04000fce4daL,0x0a766f870d04770L,0x09fb66dcbb80e31L, + 0x13f175d02cc23d4L,0x118ff4d69c9dc27L,0x1b23f93c1da149dL, + 0x14d515baa4311f3L,0x10466a719e0ee04L,0x157baa9d681baf2L, + 0x0583f56c2e4705dL,0x0e52e82bbb0e1f5L,0x010a4eb1828baebL } }, + /* 59 */ + { { 0x01a8e6f5f9311f6L,0x11e4fdd5e0fc2f7L,0x14bad250826b25fL, + 0x1832ee9fc29f4f8L,0x0555844f04c2f51L,0x039d59ae77e8914L, + 0x067f2d4e18a8ed6L,0x134ed1dfbad97daL,0x0cdc12479ee5846L, + 0x091bf189ec0604eL,0x128a4301130a304L,0x02f57a8fc50fbaeL, + 0x08ad0ffeef9ee65L,0x00c6940fe121091L,0x1b0378509cc223eL, + 0x17ae7d78e897887L,0x06c5b26eccfb415L,0x00a7179a86583e1L }, + { 0x08d2a104216946bL,0x00f83bd25ec96aaL,0x028d0da54581ba0L, + 0x1ec7432f92b32daL,0x061f77c90f1b5c2L,0x1fbd913ced1e278L, + 0x048fc707358d24fL,0x078bcc36ca14468L,0x0826b34c5f28403L, + 0x0c5c8746179a10aL,0x0d5882ba01bb15cL,0x068bc64953694beL, + 0x1e8b53cb51a2faeL,0x1ccb2bbc4605dcaL,0x077bccb253dab0bL, + 0x11e4e0fd8c0fad7L,0x04f63bf1dbad0edL,0x02c29bf016e5b0fL } }, + /* 60 */ + { { 0x164b06464f80ba2L,0x02af382acd22d8fL,0x0cd3c7d2d8d3a38L, + 0x1fbd190905864c5L,0x030c780aef4f7d5L,0x10f349ceaaef506L, + 0x10d2c5d02bee73eL,0x1dc59fcd4cce8c1L,0x0f66959411187c1L, + 0x1c1793bafcba6caL,0x02b390011527ac4L,0x167f757bda04394L, + 0x064e3653eaf8244L,0x02ae2fc1e1b7a68L,0x1af3a43aae7c373L, + 0x0284bb27739df59L,0x10d16658e721906L,0x0242bc1afc16bcbL }, + { 0x0d525bcd2576210L,0x1c553ea8daa21eeL,0x1c5c6f60e6527cdL, + 0x07e7158c43fd2f7L,0x018408cc930d0f6L,0x07a9fb57c7960bcL, + 0x1d7909a4b21f898L,0x06e1dc8a80fb614L,0x10ec47ae5ffdb1bL, + 0x14894ee3d535225L,0x04cac8b902dd75dL,0x09a12bde76ef6dfL, + 0x1568bc63e8e0676L,0x0e000a60147ea3fL,0x065763b46041252L, + 0x10b5f21c5a7fbafL,0x128eb39a05d6c2aL,0x036013bded10f98L } }, + /* 61 */ + { { 0x01b7086b509e7efL,0x1763d9ebfcfc8f2L,0x1e51549ae22e210L, + 0x080a3ba1579a50bL,0x174f1ceb6e44e06L,0x1f330dc80cc6083L, + 0x11f65bb2afa6048L,0x1dc8902226c65ecL,0x11dd82b4526c52aL, + 0x128483fc9cee4eaL,0x1bbbcbf35156ff5L,0x09bb1a5cbaf97abL, + 0x1288bc9f2a7815aL,0x0bd1d9912d6a764L,0x0e72f6f1bc4342dL, + 0x09dd1d1a183ce41L,0x18f5a0b071a9b77L,0x01833de4d7917e7L }, + { 0x0e589f2b7ca9326L,0x0837ed89127b1f0L,0x1485d1e95ef45e8L, + 0x1ac561105d646a8L,0x0391ffcf2614982L,0x072206bf9d7aa22L, + 0x0c1c46aa8cdeea1L,0x0a851d46f612837L,0x1a957dcb42e4a7fL, + 0x1d5b3160d356afdL,0x178e07df0da8839L,0x1019375416d7a26L, + 0x0c94e4671f42e79L,0x05849171a11b818L,0x169627c93318ffeL, + 0x1fed9a21aa4f288L,0x195bb99d316a870L,0x01c8641e554cb60L } }, + /* 62 */ + { { 0x0d3fa82ffc4a73fL,0x0eb1a9dea9981a8L,0x1e28992eddf4999L, + 0x1c45ae7b090140dL,0x0323b8aa81c04a6L,0x0626ad1204e7fa8L, + 0x07064c773885e31L,0x1706e95501c181fL,0x10b25a38700186bL, + 0x05bbd085578a43fL,0x0e6b56ad2637874L,0x1b4c3541822c2beL, + 0x1d96e25ce892e32L,0x0f43236891471edL,0x1ec71a2d5f22371L, + 0x1bd8ace5622c84cL,0x13a5d0d807f600bL,0x01f52003e911f2bL }, + { 0x16debd0a595d0a3L,0x0bb65d7f859da6bL,0x153e6c6f6e5e9afL, + 0x0898e298e37e582L,0x021af66362b19abL,0x0a0f7b64df99dc9L, + 0x03db48f61f12632L,0x1824ab00987af3eL,0x16f1a10052a7acbL, + 0x0d5bcecaa829457L,0x1e9bc32345884d7L,0x16dbbcbc2053faeL, + 0x12f95da12b40508L,0x1ac545d0ecad607L,0x18323ee2182bdc5L, + 0x09a6816329906e2L,0x0a0a40e6c80ce00L,0x004fc150bb58a55L } }, + /* 63 */ + { { 0x0abe588c21366dcL,0x00527d7baed7cb0L,0x1f66b2e4fb51ca7L, + 0x1d0f42dae0e0a03L,0x18e7361bb97e744L,0x1aa679d217053d4L, + 0x041e06b36bfc8a2L,0x1cfe10f99776f7bL,0x1da6f3983663250L, + 0x16b49f75d783e04L,0x0bd30e32ebc55d9L,0x1c0fbf9533a0f37L, + 0x07f26d8dab5a984L,0x1f5d1b7cd5a6992L,0x0374859342f9c05L, + 0x09e066f773cca1dL,0x05a72aa4e24531cL,0x03be8f4c25ba9ecL }, + { 0x1373239d8e62367L,0x0c245dcc10678ecL,0x0d116a725f10cd8L, + 0x1c29f2c1f8018fcL,0x140474b59a0ec9aL,0x1032eae7a0f867bL, + 0x0184297bb7a3fb3L,0x0bb63bcb49d3d01L,0x117c44ae4ae0cf7L, + 0x1d2b191b58a4685L,0x09d03f4a7fcb70bL,0x17151196425cc9fL, + 0x0d6a863016c605eL,0x103da60bf963b8dL,0x1525e15b5844b9dL, + 0x1c1cbfd21d80e81L,0x1b0599be18be256L,0x0273755f6652a56L } }, + /* 64 */ + { { 0x10323d3fb99cfe6L,0x0de136499a0bc4aL,0x1905f2f7edbdec2L, + 0x09134eaec0c8223L,0x10919cb09114174L,0x15fe97a6319efc8L, + 0x18b6dc57f1f1ce5L,0x15919432a251956L,0x0306724734db81aL, + 0x13d1235da6262a5L,0x1a83eafc8a591b9L,0x0be3f4b6bae1aefL, + 0x05c2f192f35bed1L,0x1fb34856d2b436dL,0x0942df77b2b1ca9L, + 0x15a5e1895e54595L,0x056f44631c16049L,0x0192e93cb027678L }, + { 0x011fb554848c144L,0x11492db53d79977L,0x0384da783e69381L, + 0x0d94a7643c24b6dL,0x0e98ea1bad9bdaeL,0x17d1cafa86b02e1L, + 0x0cbd6f6e7854e7cL,0x1ae8ae1c65bd22aL,0x1810698ae46a250L, + 0x1ecaa3656cec8a2L,0x19dc8447a5e979fL,0x0faa493f05d357eL, + 0x099851df63ca29fL,0x18e871f2d4e29cdL,0x074ad5bf613552dL, + 0x012d5a3c08b3808L,0x1d3ceb3eb6efd80L,0x00cea42a371953cL } }, + /* 65 */ + { { 0x019ee8fb540f5e5L,0x152978273468bffL,0x16c2b6f721c61b4L, + 0x11a074ff91a4641L,0x08bcb916a83ad5aL,0x08f4202a5fc1e38L, + 0x1777c2484cfa8b9L,0x10779c7084996a5L,0x0d5c7be40310635L, + 0x0f5dcefa2c718bbL,0x0658e6f136aeff0L,0x1fc980ae4b515f6L, + 0x1484e1cd2436350L,0x00a2dc6f5625031L,0x120c8deb7dcc553L, + 0x04e40154dbb3d66L,0x1b0a3345c3dcbffL,0x00d9d67365a7229L }, + { 0x143e5e990a8bdc5L,0x1dfceb183504481L,0x08d63921483a880L, + 0x1dbcfa3a0d30913L,0x1f795d3fbd17debL,0x1d851fc7d7d36baL, + 0x1abea933ad8c0e1L,0x005c02cd665ffbbL,0x0a2fe20547e764eL, + 0x0d5cc127438f982L,0x14daee54bb11795L,0x0909521a4195457L, + 0x0775bcfb537b4c1L,0x14c16272a98cf9cL,0x00a4874d08e2929L, + 0x162fd4576c38f42L,0x0141e061b64db3aL,0x029c7619f0c9785L } }, + /* 66 */ + { { 0x13496fea19b56cfL,0x0bbfa3ddccd668cL,0x1ea15f42a20598fL, + 0x0410506bfb1e095L,0x1d82cec7cced3daL,0x004e42bf10fd76aL, + 0x08c1db85d6e67e0L,0x105b38dc6365a0bL,0x196948d4a81487dL, + 0x175e9f96a37b32aL,0x146aa1dcf331261L,0x1e45162c814d0d0L, + 0x0841a20b753e220L,0x08560537cf8371dL,0x0facfecb3fff97aL, + 0x1c593eb5363b51dL,0x0012587d9976e08L,0x037eb014c01f4faL }, + { 0x0709f8d8eb7516aL,0x0c53a5ee2cc55aaL,0x16621fa0073a0c1L, + 0x01a2f7152da469bL,0x0e90f6abfd0f9d9L,0x1f6aadd50f2a4fbL, + 0x13064925bfe0169L,0x0ea1b3ecaf4d84aL,0x03cdea49cb89625L, + 0x142d1f816ff93efL,0x039ff76e2f012edL,0x01ff30e46d6078aL, + 0x1dbb0d5055904ffL,0x10a5f46824a14c7L,0x0f4c358d2cce1b7L, + 0x1fbb2f5a69d38f8L,0x1c01f2b32bde159L,0x04267d11e63b0f2L } }, + /* 67 */ + { { 0x1bc11eb8b99b964L,0x006052c717e2389L,0x11275326952e38aL, + 0x057edc41f50e1f7L,0x17c88cfa37a334aL,0x0578ed772c1e86eL, + 0x1e2981780a6a3bdL,0x0c4daabc468185dL,0x161b6fdfe209e9bL, + 0x18ed6935dc70407L,0x0f058a4e4bf068eL,0x1fcc155c7e9cb5bL, + 0x1ac2bf4d5b02ac0L,0x01417f6946ccc00L,0x0b6ccfc8ccfe4ffL, + 0x0a5ce2db962196aL,0x18e09f90f84c557L,0x0143ea628e42506L }, + { 0x1a582010e9867daL,0x0c4d98d43a66d2fL,0x1f17ef7b88b9851L, + 0x0bcc257b5000bc4L,0x0d3635f9e357fefL,0x092d432706df6f9L, + 0x08b958af9c391bcL,0x1a3413731081b29L,0x17eb99a1528b5e5L, + 0x0dca0b73a88145aL,0x0dff5f81b4b3108L,0x0a2ffd41308a362L, + 0x06ffcecbd76fa1fL,0x0197a29f1dd0f4bL,0x09a3e875322692aL, + 0x12b460f63c55fd9L,0x013d0fb44534bd3L,0x0009951ee6c77cfL } }, + /* 68 */ + { { 0x13c7785576374c2L,0x09368c239382072L,0x17208a328113981L, + 0x05e39c2627140cdL,0x0deb0c5d1fe1c1bL,0x1fc137957764196L, + 0x096269d659a6672L,0x0a99a311d03bcefL,0x0e5ce0fe0118d12L, + 0x0a154c203c85c35L,0x1c10fce6b0a33a8L,0x05210fbcb009c51L, + 0x12f639a8c54eef8L,0x0c43bca7c1e18d9L,0x0c6ce475c11529dL, + 0x18f2b94c6baa031L,0x025cefea07631d9L,0x009e5f73b5b7c55L }, + { 0x1cabe0f8d3f34f3L,0x0e18e51b0bff1bcL,0x188f76509a86f6aL, + 0x0fe539220964dbdL,0x02c6cd3be9dd962L,0x1d10cb019f58b4fL, + 0x120f229cfd24bf2L,0x16f25c6fc1770b1L,0x0e4f2aca623b3fbL, + 0x080fd8f325f0051L,0x1e09aa523d91220L,0x0f6920e4c1cf234L, + 0x10e30bb83541406L,0x04cce0377bba552L,0x0821447e48b2a03L, + 0x009e0d70c6b7217L,0x167bf936b5c25faL,0x027050d6d701744L } }, + /* 69 */ + { { 0x0ca66708ba29c4dL,0x12067114c404a00L,0x099c5b769d4b020L, + 0x0b5777f468438b9L,0x1ed28b72689c0e4L,0x02b55a0ebaa2fe9L, + 0x075957c8846635fL,0x112967b1ee870ebL,0x093490dfb8fe50bL, + 0x120faebf4075d0bL,0x1697ade6b2d4dedL,0x092e183abcbcf61L, + 0x0da5da429aab6b1L,0x17b69792919c734L,0x0c3ce9f804310dcL, + 0x0117844de2da4caL,0x199efb0f7b6cbefL,0x0399f186ccfcce4L }, + { 0x0fe1582a42a38f9L,0x16ac723985a8076L,0x0a9f7a5dacb2bb0L, + 0x0b52d383765dc5eL,0x1cecdb4af0539dbL,0x14748118caa0b47L, + 0x1507fcbdcd22b9eL,0x0a43ab1af986242L,0x15d25b75c2202aeL, + 0x154cb2d7a041ad3L,0x0da9054a6d391b7L,0x16df7a4f5b367fdL, + 0x00261f900b5c97fL,0x026ad8cf6c3aaa6L,0x0866e72d0c0c764L, + 0x0179e67abd37196L,0x00c7a43d4923ee0L,0x02b7d659cdbcd2eL } }, + /* 70 */ + { { 0x19165a2a3018bfaL,0x035924ffd6cc200L,0x07d954d06a6c403L, + 0x0e4bb8999377e36L,0x0bfffe60e6bd1d9L,0x0a84d5a942876a9L, + 0x167c493a64b31f9L,0x091fed8a05c99d6L,0x02f0b35731aa7d1L, + 0x0860eeef3f1d523L,0x127d174450a203aL,0x1a4ccb7cbbab75dL, + 0x0e1febce13475cfL,0x004a169841d5d8aL,0x1fa0b21aae920a6L, + 0x0431a3c3646ba52L,0x0bbb771cdbe50d8L,0x0442cc9336ca6b6L }, + { 0x0847290155ccaf2L,0x0f5e3be2dbb9f04L,0x1746cb7423b619eL, + 0x1d0fa8ebb751165L,0x0694d02a960a180L,0x1fcf4b407edb5bbL, + 0x0db10fa1d6324fcL,0x0fb7b47edf495b0L,0x19400c58132fb38L, + 0x0d3c2a112a81007L,0x1f0d45ddbb3c609L,0x08dcacdb6b34552L, + 0x0026545eda03ebfL,0x07ba55a223a1d14L,0x12cfda7b45a7613L, + 0x0e32d7557263b11L,0x11970ae932cd825L,0x03cb9125350604bL } }, + /* 71 */ + { { 0x12923f8441f3567L,0x018b417125f8eb1L,0x09aedd9c7fff047L, + 0x0ef4bc3444972eeL,0x1addb417601746aL,0x0cdc2329eeef501L, + 0x1ffdd5e19e8f1fdL,0x1516025530ead9aL,0x01bd5fec9f19ba9L, + 0x081bcd17c1833a4L,0x0d1176ae301745dL,0x0836f207e854eecL, + 0x0da903e46d5d7f4L,0x16e89360e008b3aL,0x1156d006c74f136L, + 0x06add44ea5558c2L,0x12c4da42a68555cL,0x01ff84e0aec1042L }, + { 0x00a1bcef9cb7784L,0x09cde12117982a6L,0x07f431052a9ebb1L, + 0x19ffa85788be81fL,0x0f358e15d3aa316L,0x113b41217ad2619L, + 0x1b3b802f7367b5bL,0x0ba0d3ef13ff14bL,0x18078018e05e14fL, + 0x1d9f249c5a063a0L,0x123075e45fdcb4aL,0x0cc998ae2a18bb7L, + 0x1ac3fa8920e0eeaL,0x0e3cb8b2512f662L,0x12b45acf086c3d4L, + 0x03b351e1345e4c6L,0x04c8e730fc55839L,0x023f78c02a7efd7L } }, + /* 72 */ + { { 0x165f3d13da285e4L,0x0a6dd1d00f1fa4cL,0x04e984852b42e9fL, + 0x0a4472ea928e708L,0x1a730b92d3b7d53L,0x168b2ed29edee7aL, + 0x1fbd0c4c364acccL,0x16c89450a8305f2L,0x1bf62221c44dce1L, + 0x1d09c2c3f150764L,0x0cb2372feb6662eL,0x1e7f6bfda89667eL, + 0x05c66217bb409e5L,0x1e6fb8d4ae19463L,0x0481e22c036da7fL, + 0x08c974478544371L,0x061f8ab28e63ae6L,0x00d35b74e5c6f04L }, + { 0x16ec2b606af77aaL,0x07ae6d443f832d7L,0x10027d263158b98L, + 0x13f9755e970fa42L,0x071ab855db595b5L,0x1a4d8607dac9509L, + 0x032728338439750L,0x1b73ac30fb110fbL,0x103ee95f9154bd6L, + 0x1f29909ae8364ccL,0x1ef0c3eda993423L,0x1e1acd4996c1e94L, + 0x0f5d37367c3d22aL,0x0cbec72a8b4a967L,0x05ccb41bc3a9cd2L, + 0x07285688f8e1ee6L,0x1d000ab3034a9cbL,0x03cee80c0142887L } }, + /* 73 */ + { { 0x0e0033a3ac7424eL,0x15b44307ed26802L,0x1d9af2ddcbef6c1L, + 0x17e52f9b4846d52L,0x1b013c6e294a8e2L,0x11d1d6a58555c2eL, + 0x129acf4abb2621cL,0x13c195c659a2790L,0x021888f5e70ec16L, + 0x1cb19dea1544131L,0x11e4b9ed8366e1cL,0x0e4420ed3fc2d15L, + 0x06d24bed3489f2bL,0x11f59255479fe7fL,0x131c1af4d7bee22L, + 0x19c1bbbd9f47e90L,0x0367cc119a9929eL,0x043f2d6a2c6a02aL }, + { 0x099aa9d7d1000a7L,0x057fe57411c19ddL,0x18a37ee0f7162e5L, + 0x0308b4831b90452L,0x1d4170542f59fe1L,0x1b8ac0d45cb87c2L, + 0x1745e24630995caL,0x181c9de8efb81a3L,0x1b50b4cf33afad7L, + 0x0dd753c80c3852dL,0x021fe6ece8a1a08L,0x063c2494b39b8eeL, + 0x0f57f4323978575L,0x00b264a576ba613L,0x052fdd357d6b894L, + 0x1d464cc116fc5e1L,0x045f4cdb5bafdceL,0x005b8928ccc8660L } }, + /* 74 */ + { { 0x0290ca188d5c64dL,0x16ba4d3a4929a2dL,0x14f4a803a494165L, + 0x1995ef6cd740961L,0x0cdded83082cd02L,0x18b2374895a8617L, + 0x1fe5604f3a77bfcL,0x02ac55ce18f8ebfL,0x16f6852e07e2a46L, + 0x107ebe801c027e8L,0x0a93760863a364cL,0x0df75f8c8baf634L, + 0x01e8d9fdbe4918aL,0x02385b777d8407dL,0x05d3bdccf534229L, + 0x1cba5a57440eedbL,0x16d8ecb95a769daL,0x03d1fa11d3eb4acL }, + { 0x02d2ca69a929387L,0x1bac0e58e0fff9bL,0x127df946db2eaf6L, + 0x04749c263fb125dL,0x1bd87561ee8d863L,0x13f399234071f8aL, + 0x1fbfb8e965f8753L,0x016798e56f8ab03L,0x1f3e77f8aca8caeL, + 0x063ebee2f17ea57L,0x09154884d56de7fL,0x09e54580e2efba7L, + 0x0d0689621f546b2L,0x1fbc0b1f20ada99L,0x15fb484afa6bd44L, + 0x052864fac773667L,0x0f4ab019ef29680L,0x016d2fe2a8b11fdL } }, + /* 75 */ + { { 0x0429cf3c8a5c600L,0x006111ff19f3e31L,0x1d00295f772e9eaL, + 0x1b24b618e93ffb4L,0x0b100eb0d1ae156L,0x0a1e4084bd21fcbL, + 0x13c905a7a5173beL,0x06743ee69ca2251L,0x004387c4a419f01L, + 0x003c34580822012L,0x05aafe40d673cb0L,0x1fdc8f1aa9c7ca8L, + 0x0642a2173ef9c76L,0x0ff180a0b310cedL,0x1bc91f98780c55aL, + 0x0cb2541feb9c727L,0x0d3811792ba072bL,0x042af810cb8642aL }, + { 0x1fbfb6c847314c4L,0x030aaf5a2dcb530L,0x0519ae8abeb25e4L, + 0x0b57292f02e205cL,0x0110c4feed51f97L,0x1abb33ce97ad8beL, + 0x1139deb2339c2bfL,0x18fce6cd442dd64L,0x0dd1bbcec551c65L, + 0x092830570d42cefL,0x1205d22e9f4b9edL,0x0a83571d5188f40L, + 0x036fdff078e1a2cL,0x0a43a582373c126L,0x0c7dccde6d27f1cL, + 0x1cd9e455c66fe0dL,0x1971c3521926f8fL,0x014911b67a92e83L } }, + /* 76 */ + { { 0x1b8d80a7d8b29dcL,0x110120475324566L,0x117aba4afa4745eL, + 0x11fb4e5f78fb625L,0x1e760c6f1f347d1L,0x11c6c8889ba5a04L, + 0x107d1cd87a3c763L,0x09cee297d3ae735L,0x1c1f9701cb4df5cL, + 0x089c76c37b96570L,0x1f87ddab4603136L,0x0b7d3c5b7f3838fL, + 0x097c70c44df8c18L,0x1868adafc1aed93L,0x199517be65f3faaL, + 0x09cbca20288b4c3L,0x1aa16b068842518L,0x03e7d61acba90f3L }, + { 0x11821673c0bc53aL,0x0f6f1bf3a89b3c0L,0x17f68d95e86212dL, + 0x09743fbb307944aL,0x05da77d8096abbfL,0x19a162ce741b4feL, + 0x167c7c9ee6b9eaaL,0x1d20d9237ad2e40L,0x0ee0dab30914ecfL, + 0x1b23fddc9fa9f89L,0x0e29ebfe95f83aeL,0x0ddf3e55ac0e618L, + 0x07bb99dcc9517d0L,0x02304050a4b946cL,0x0e705f6c00d2bc5L, + 0x045419902187e25L,0x0bd7225f14f772aL,0x03671ee3f8eefc1L } }, + /* 77 */ + { { 0x07cd835a4397830L,0x094867a39998360L,0x0ea0a6627a31376L, + 0x12ac7b02a5ba6baL,0x087de61b7990255L,0x1271ae793c6c88fL, + 0x0396671cd031c40L,0x1425a8888c2941aL,0x163e7608ff32626L, + 0x13d1bf4e264dd54L,0x1b7145dbfff4958L,0x1f919de5439a18aL, + 0x16efc559d9cb6deL,0x020e5b4965e606aL,0x0587827917cff14L, + 0x0ab399a0b8473caL,0x16d2a731ee95c3bL,0x0428a889151e850L }, + { 0x02d033586ff19e2L,0x106d50ed14301bcL,0x13f955f1fbb70b1L, + 0x083789d16165cf1L,0x1df35c67a8f6f98L,0x122315660fcda59L, + 0x182c25b84d80d1dL,0x0ad7f22172ef8f5L,0x127c7f305514359L, + 0x0a6d8ae7b18f572L,0x158509f9a6cd330L,0x10a2bf825fe54a3L, + 0x13fb887162dec82L,0x0f0a445efe67570L,0x18f9d3368ccab07L, + 0x00d394406e9c45dL,0x004597ea1a1f0aeL,0x04588acf93bdef6L } }, + /* 78 */ + { { 0x0f71a442f961d30L,0x0b4543d639247a5L,0x01f2c6a41b36f7eL, + 0x0c0957f24ba65bfL,0x19f04d4c00c10e2L,0x0b82ed5c388bacdL, + 0x02124035539824eL,0x0ebeeb0e86793f0L,0x02e9abade6a7a23L, + 0x13b6a3c4a560bd6L,0x01496f080b66715L,0x195b57f5ce7a994L, + 0x183405991b95b8bL,0x02c54ce191b8f69L,0x1e32198ada791e9L, + 0x058f8f958163056L,0x0596ceaa79be023L,0x005ec3219ac47baL }, + { 0x0a1a8b47e734189L,0x0d64467f2fd0befL,0x1538450dd9914b1L, + 0x115f3d2ea088949L,0x130c6b3bc252230L,0x16fa3bbc58e861eL, + 0x0375cbb6b97c131L,0x068a6263b345dd1L,0x0c4e380eeacc93eL, + 0x04cd8d6546d8747L,0x123059fd75275f5L,0x04ae2aad99aeee6L, + 0x0c2611d13dc9663L,0x1ad17ee632e7074L,0x163ea84b257f99aL, + 0x059304cd310650cL,0x107da87d1f431c3L,0x0233282cc7e6c8cL } }, + /* 79 */ + { { 0x06c13cc6b4a5efaL,0x0cc4d8e83d932a6L,0x1b3a2f71a703120L, + 0x04584a63a82172cL,0x0ad0a100f54cfaaL,0x0ed224e5af8c046L, + 0x00f32fad494e3b9L,0x0f14c48010b7dbbL,0x1e792dacfd6255cL, + 0x01b8c83103102c7L,0x057a0fb45963062L,0x164efa51aa852ccL, + 0x1b83b75df34b549L,0x0bfddca1757893eL,0x1df24c13d837db4L, + 0x0f13fa10c63b7edL,0x00c17c38f986018L,0x00621aba55cd494L }, + { 0x0eb324c1d20cad0L,0x16584c63088453bL,0x0e71bc1b4db6437L, + 0x15781b432f4dd3aL,0x107ac5ce6cd978bL,0x04bf5aaca458e02L, + 0x0538caf51c59315L,0x0785538981e9ab2L,0x0772c5046a759f0L, + 0x1eb994534d6423fL,0x15f430c122ccc39L,0x09c081ef759d51aL, + 0x13a85f1790e6003L,0x0e42cb9b411ec8cL,0x078408a9ba6d9b1L, + 0x07f48459458f4cfL,0x1b900e7a19c0902L,0x01924ccf893936aL } }, + /* 80 */ + { { 0x07eaed67c834915L,0x1d5355e2f5b26b3L,0x12d8975880467ddL, + 0x04d33fb384e53d7L,0x0b8d4f6c0aee24fL,0x04bb6b70f5ac3a1L, + 0x1a995fc49c43053L,0x0c92272066bedb3L,0x1668b704906b500L, + 0x0cb4d07043b7727L,0x06fcfcbe764d819L,0x0ca36933c79df20L, + 0x1bf2dbcaaafb1a8L,0x0b9d835b405ca9fL,0x1cdb190c4b3159aL, + 0x1b02a6a69b38675L,0x191e4463a5210ffL,0x02bf515a5f8c615L }, + { 0x0f5e1628aa0f2f2L,0x13ae287235e5500L,0x1e6a928b10b631fL, + 0x14297544052f568L,0x0943cc2eb4f308eL,0x0ac4025480de8a3L, + 0x03df2ec497fbbbbL,0x038ca0591f33a30L,0x1e53539191580c6L, + 0x113c03493880f71L,0x090287ea9c9c5dfL,0x1c0498eb62a6f41L, + 0x0b538f1c2232edcL,0x1f183e976d11b30L,0x0bb82d135447a62L, + 0x1e60e484edc8137L,0x1c9a78c39277ff1L,0x0302405a3753c9aL } }, + /* 81 */ + { { 0x1087d663872ece3L,0x0df3ecaadb87c18L,0x1f1e73e56ee17caL, + 0x1bb7ff4c436a169L,0x0022ba5dbae3b58L,0x00a24e0730e9407L, + 0x15215e2b9445d06L,0x01c162650819eaaL,0x1800ed1b6b8ce0bL, + 0x0effeeabc6aef1eL,0x108dd1a695ad1cdL,0x06d31b2215cfefcL, + 0x006313c7c7d5e32L,0x1496f4f2db7fa95L,0x08442ed68bf8836L, + 0x0de4683668fa7a2L,0x0ccc5905edb40c1L,0x003ba5069cd47c4L }, + { 0x0e181abe3b6c106L,0x10b1fc6f0a85b9dL,0x00bdbcd520d93afL, + 0x06758f582d9eeb7L,0x091722afaa0d206L,0x0a2aa9ae3403341L, + 0x18fddce50798445L,0x1b42e24fc717ebbL,0x132cfdf031afb41L, + 0x1449e48c3de4331L,0x119d1298b272671L,0x1c5b2c58328eea0L, + 0x1f378cdf4c96866L,0x1a03fd19244f646L,0x04a4344e981c26cL, + 0x044e7a6fa42b2aaL,0x14b9623d303bab9L,0x0040a8caa121900L } }, + /* 82 */ + { { 0x1236d89fb7b2108L,0x041e656bafcd57cL,0x0c56d3876844fb3L, + 0x1e062b86c5ef8e5L,0x1272fe3f552aeaeL,0x021f7408f0a076fL, + 0x0c96e675e6fda1eL,0x0e99cd6a9fa3b37L,0x1b20b0e215b1badL, + 0x05010a7adc26486L,0x0efd4bf29b3b255L,0x091b3c9beede8b3L, + 0x0ed64cf17ee363cL,0x1b156d241822fc2L,0x1d32806100a859fL, + 0x1885a593c37e6d4L,0x074e8cf9d41f691L,0x02d5f90bc61625cL }, + { 0x177966bf3b3bccdL,0x1f0785f1f065523L,0x0ece31f5410c011L, + 0x1f28dfabf997070L,0x09ec0e87e77e3baL,0x10c692bcdd53c2fL, + 0x1f3fb60f155f322L,0x0c3372dcb5e4b7dL,0x14f05d15e98c71bL, + 0x00fcc8d3bf316d0L,0x1b1e072ea8e0842L,0x0cbbca9b37f638dL, + 0x1344ed14307522fL,0x0ae57eed7ae82abL,0x1e3d6fcc0d6cc7eL, + 0x173b28fccfe86c6L,0x048029f7cad5270L,0x00ad68ac3a6c8b5L } }, + /* 83 */ + { { 0x0de2eceaa588ae4L,0x15e2c51b8d11900L,0x04d1c48c111154bL, + 0x1bc963065ba01d5L,0x1689e843afbfa67L,0x1a71741490b1a0dL, + 0x077147e5aeef587L,0x1a32a840d080985L,0x0c7fe382742317fL, + 0x050576331a418b1L,0x0e53441c00613f8L,0x12e7fc3f7b0bf85L, + 0x11fb07435207219L,0x023729c93245b55L,0x1e95bfc8eef6ab7L, + 0x04bec1b71ba3e01L,0x163104815eb8667L,0x01fce266529740cL }, + { 0x136b29732ce637eL,0x0af96fae92e6effL,0x14b62c0ab65e068L, + 0x199f7567d2343a0L,0x014eeb752e5f3bbL,0x0d3c9d306965ebbL, + 0x085135124610f35L,0x0cc44859eeb9b74L,0x0a20705e788b997L, + 0x0709660763bf099L,0x0537dad86a6c159L,0x1e08e904b6b5638L, + 0x013da312238fd97L,0x06986386cab0241L,0x04bb9a779219c9dL, + 0x1127b79571e2a38L,0x14b5dc638b4668dL,0x0323ced6b111fabL } }, + /* 84 */ + { { 0x09044f3b05f2b26L,0x114a5405cfbb62bL,0x18a10a43dabacd6L, + 0x0604d4b0ef1073fL,0x0e5ff9c3761cfb2L,0x08e2bb3b44935b1L, + 0x0fbfaeb9b34802cL,0x075b90aeeace540L,0x00cae074ae1bad6L, + 0x1f248d0eb84ecceL,0x177b5994076704fL,0x19438655dfeeed8L, + 0x15c57683e81da6eL,0x0fcc6c23a8424eaL,0x166959278e4ba73L, + 0x13165f5af305ec9L,0x097f7c3bdb7a37bL,0x00ff04fca784302L }, + { 0x1a7eaae7648cc63L,0x11288b3e7d38a24L,0x08f194fd15644faL, + 0x170342dd0df9172L,0x1c864674d957619L,0x0b2ccd063f40259L, + 0x08ca3f2204d2858L,0x13c6cdd52d214caL,0x1415329604bc902L, + 0x1cf0cca57155695L,0x0a3149fc42fbd7bL,0x0b0d8cf7f0c13c5L, + 0x1a844cc25d73dcbL,0x1a759b29fb0d21fL,0x0903c0b5d39fba9L, + 0x17969e66ace0dbaL,0x06aeec7694cfd83L,0x026f4abc36db129L } }, + /* 85 */ + { { 0x067d3153deac2f7L,0x03bc55b0ecd4724L,0x1e582adecb56821L, + 0x0d9fbe9ef3e76edL,0x11ab8f4b00b3005L,0x1bce80e8380f0a9L, + 0x14dc41fe5235671L,0x180f9329d7904ceL,0x01104d4ee48bad4L, + 0x0c6705adfe4e82cL,0x0a2634c27ea02deL,0x044b59667d5f8f9L, + 0x1c5b2f31750244fL,0x126bdf1a6a8f46fL,0x080ad0cf926e9aeL, + 0x04eb42ec1e98f7bL,0x00c37e36a7e4435L,0x00e4a20c5f31b4cL }, + { 0x1a2131309dc1414L,0x1b2fe21e49a9ba1L,0x01eb7d7de738181L, + 0x150ba99f94dfe64L,0x03e995ab6f18b1fL,0x1598017ae213973L, + 0x1fc5848682792a0L,0x04d056cba372e28L,0x04993c20c20a7feL, + 0x0e4e5cc7338b393L,0x0b59cffad102826L,0x13c24a36978ab40L, + 0x14a05338ea3f3faL,0x1d84fb65baede23L,0x10d1824f2d0112dL, + 0x1d584cecfb43100L,0x1ba97851422098cL,0x0308dfdd95aa91aL } }, + /* 86 */ + { { 0x1baa55ef00ad2a1L,0x1d42f0a51486bdeL,0x1da3a4ac5a50a7bL, + 0x1a23d9026076948L,0x08bd27b267111bcL,0x101e0307212b814L, + 0x0212bca33ca8f66L,0x04176f91a5be631L,0x1e2ea1462e3aaebL, + 0x1a9ac0221dc2ebbL,0x191209553ba6f4cL,0x1d3dcd54331f03dL, + 0x04c26c5944eb2eeL,0x01558b3e3d2d540L,0x1f8869683bcb696L, + 0x0531cb45568ec05L,0x08d169cb3b83370L,0x0437362a20759d5L }, + { 0x1e033210b793d9bL,0x1d6f08eedaf6776L,0x0a49a24c2d93de7L, + 0x1bfc9fa365ee7fbL,0x12a4dc8806aad97L,0x0bb6ba839d2d8ecL, + 0x09b022be32f62f2L,0x00cc1695762c79cL,0x19c8300a9dcb1fbL, + 0x1ad2ca66d4ad9e9L,0x1f5f52cdfab21ccL,0x174441ddf5563f2L, + 0x06f3e828c8a3d2eL,0x02d5bbc0992c648L,0x0a2d85f20c985beL, + 0x1705ae4b2e32518L,0x06dcd7196bc3233L,0x041c33f5c8cfd09L } }, + /* 87 */ + { { 0x14fe73e22474edbL,0x131ca0d4270d73bL,0x06b671b75b8ca9dL, + 0x0a29f17eba4e065L,0x12267b9000c4a41L,0x0927d71e71751beL, + 0x06de049d4c05447L,0x00cf829b0a84c74L,0x020c8401b1ae0b2L, + 0x195008d840fa4feL,0x048fee5671b7e3cL,0x18f9001c3a0c3d0L, + 0x1824259a9aa328dL,0x1bf7b61bac3b51bL,0x0f5327c8eb6a2d6L, + 0x0713e047ed6dd52L,0x19e89f5414dffb6L,0x025935dd1731459L }, + { 0x10b1cb45d318454L,0x1ba4feba1b65b69L,0x1c995a29d18448eL, + 0x063909fa3c62218L,0x08403d55c85de12L,0x0fd5fc52fc6b730L, + 0x17380e56db84e6cL,0x021fcdad18679fdL,0x11d90381f94b911L, + 0x054754096e6375bL,0x00104dfa4328afcL,0x180f9144b8b4b3dL, + 0x1a5d84663cbeb5fL,0x0885b53e004e129L,0x023e35402c541ceL, + 0x03ccb0c0fb49882L,0x1c602c3d9c3cb90L,0x026b4bde2964b0aL } }, + /* 88 */ + { { 0x0db1ef0efa8fb40L,0x10e2dadd1cc4e70L,0x0c560274677ca40L, + 0x06982433c351adfL,0x14ef05e26b787b7L,0x0bcb71320bf0b40L, + 0x1086d124d0b6e3eL,0x06c5f0f14bd7f08L,0x1e71916d7e94a45L, + 0x00c5dd1d708cb49L,0x1d2fa55da2013a6L,0x0e99f0849f15d8cL, + 0x1d466ce6ab0a260L,0x049003c5ede49dcL,0x1c3c68ecfc56a63L, + 0x10b4f3a21fa1a70L,0x180a61241d9e4e7L,0x03b6543d0f36466L }, + { 0x157fb56e02e48b7L,0x0a589e604f4e321L,0x10d4901a73c3ef4L, + 0x1858760353b6be4L,0x06956dadf878165L,0x0b05b472a4f3e27L, + 0x1194fcbfa54e2efL,0x1372a5f0ad60b3bL,0x0d3f60225b377feL, + 0x10639945ff48462L,0x0a8b4ef23d7cb5aL,0x08864884a0a19cdL, + 0x0a3d3b3ce5f7213L,0x00b3ba890bf0933L,0x1ee2529d6d790ffL, + 0x1c6ea2b24e0c46fL,0x1be152607532be3L,0x013f3f96336d1dbL } }, + /* 89 */ + { { 0x18f65ade6a15883L,0x1f3463357ed99b1L,0x1aaf4fc4b797529L, + 0x006f70f020c40f6L,0x04acf6d31c6ff95L,0x1f3c61606a26593L, + 0x0603858eb1807caL,0x13638c798b42c6dL,0x03e92cfe895c934L, + 0x19c706c20f63910L,0x075d90b57ea585dL,0x0d8387c051d2c2dL, + 0x06b16d54092aa77L,0x1836fa6cc9ee2b2L,0x071ae5e82c9fed5L, + 0x0be813d3222e19dL,0x128ea8e42be53c8L,0x00174b21bc19232L }, + { 0x1540addae78ea1fL,0x0dba6bdb3874b48L,0x1107dc01a099468L, + 0x14faea418ff326cL,0x09ce12e18f97d6eL,0x1041a107d535013L, + 0x110d89642b2a1e4L,0x11ef49070c6eac2L,0x007c6149ef38140L, + 0x19dfac26bc29a03L,0x06c0426aeedbddcL,0x093fea5141350ecL, + 0x182e00ae3ce4eb2L,0x10bc77fd043c0f6L,0x144e9fa19306c94L, + 0x00c5f983cc5453aL,0x07dedb8b94e1919L,0x039cfa9ed278b29L } }, + /* 90 */ + { { 0x05f4a88924adc5fL,0x0360b540c7ab6bdL,0x04a5de57e552559L, + 0x1ba338a8001d892L,0x005912b42b48753L,0x1d24a30b7d11b59L, + 0x14199acf597cfa1L,0x0814e2e940208bfL,0x1b635031312a5e1L, + 0x1ce25a254b5c311L,0x0e75966ac00f569L,0x018c704de634f46L, + 0x0c6f7090cdc72f3L,0x08375f125a739c8L,0x091416966b1b0daL, + 0x08274734fe0db77L,0x084839991e1c58cL,0x0010611ffd10707L }, + { 0x00e4adaafc74661L,0x1e7b193bfe03289L,0x13dadb739e64deeL, + 0x06f62c374282093L,0x09610fb25b8d6b5L,0x0ef3b49110c218dL, + 0x018c37a7b27477fL,0x097a657f49a85b0L,0x13885702a6244dfL, + 0x0f6e8f6a2ac96fdL,0x17d16fed3806e33L,0x1da50dc42b601c3L, + 0x076a937e6a8f4bdL,0x00987b91c049aa4L,0x0a087e10549e2eaL, + 0x09f158db88d2471L,0x0ef2207b119fd8bL,0x03b73dfa9fc934eL } }, + /* 91 */ + { { 0x112842827ebd187L,0x19055db2d56ddafL,0x1969c8961a5634cL, + 0x131e130d576084eL,0x0ebff503da3f33fL,0x0fb8d2a08c03d3dL, + 0x1c92c971ddb2a09L,0x16981bcf7dbfefbL,0x1da8b0f42165f1fL, + 0x19ffb9bb98f9d71L,0x075f9c64f829497L,0x15476d67748c99aL, + 0x17aa1f37828df84L,0x13b99d63dd425c4L,0x0606885b9e58333L, + 0x101da9a8dad56a1L,0x1091ec12c257cbbL,0x03cf3d69395cb77L }, + { 0x0d970dc8f30caaeL,0x15e7885375f7a1eL,0x18fb1c5185b6172L, + 0x16a33c7530c7830L,0x04cb13d61c50db0L,0x0a3db4f9cdc4b1bL, + 0x0c3337d9f607c89L,0x16ee2af5773acfbL,0x0ccca25ba889491L, + 0x144903e3d13f06eL,0x1a3ef83f50ca07dL,0x1ee6ae41d812695L, + 0x09cdfd7beda5d91L,0x0501cf19597b0c8L,0x0363f707b0408c9L, + 0x000bba787acbdb6L,0x09432c916c84fe5L,0x03fc61bd62605f5L } }, + /* 92 */ + { { 0x1ec1e5443ac05e5L,0x126d266c69c1299L,0x102e22fe78af692L, + 0x016a7023b90db11L,0x03c3aba434d71ddL,0x0b08df32a820695L, + 0x13e80af102526d8L,0x186385a84dc4f34L,0x0535a5aa23b065aL, + 0x1545197e2975448L,0x17b29e7f76b48b6L,0x0bfa556764deb4bL, + 0x1bf37cd81e911f0L,0x0868b5c62ed673eL,0x1d625383839139eL, + 0x14e9e2bcd15dbc9L,0x02fafe04999fc92L,0x00ebb81d54b873eL }, + { 0x0a4c81d3f0062a9L,0x1595c6cb5105d54L,0x037e192f44078c7L, + 0x0488276c28cdbb3L,0x09a555f8ba05f59L,0x05a968a8d33d06fL, + 0x0ac8eb30bc25cb9L,0x03756bb55d8e309L,0x0ce08b43e7c7f69L, + 0x1072985bb6213faL,0x1481a7908faf714L,0x13d069be299cfa6L, + 0x15446305ac6b5e3L,0x1f1a66e09ee5f94L,0x07d6beda0b2cb87L, + 0x12df3a9588ba222L,0x071c5ef63cd47f2L,0x00516207649e104L } }, + /* 93 */ + { { 0x1bc384faf5747dbL,0x0b04360355c3584L,0x00ba79f0551ceebL, + 0x02ab2ef57f480d1L,0x1a81deb02d5326dL,0x05b088831d4d02eL, + 0x1ae426a1b929d49L,0x1742805f0f49565L,0x17d0721d4d5c600L, + 0x117ecd4f944fedfL,0x1399b7b379bc1c6L,0x04efb573f4e7ebbL, + 0x1f6c474bab62171L,0x1b776819b696e24L,0x0a0974f7005f87dL, + 0x0bc8772e2eb809bL,0x07e6c297e3d54b0L,0x0177da2a32b64e4L }, + { 0x0712b008b21c064L,0x17f212538314f52L,0x0d026dd3c2bf461L, + 0x06fd93cc52c86b6L,0x04c60d086965aa4L,0x182bd56ed0a339eL, + 0x1bd802d9599c2fcL,0x02cfe0bd08079d0L,0x0c05073a904401aL, + 0x158f31c14a7303fL,0x00c949a73dc1185L,0x0837d19cfa7440fL, + 0x137577053d29411L,0x05533186e9c56c6L,0x1410d436e9a3ecfL, + 0x0ec17d97d5fe3d2L,0x1e49f5166d51d2dL,0x019ba9967231448L } }, + /* 94 */ + { { 0x11118533a00bb9bL,0x1fdd722fb33429fL,0x0a1752bb8934b4bL, + 0x1606830add35c23L,0x0731349f18ba1e1L,0x0b8adad4d640bc1L, + 0x14bab04f7f52951L,0x14f4bee8478bb55L,0x130a483b9535b76L, + 0x174d6d27fc39f4dL,0x18b611c8e841564L,0x12f71db589c02acL, + 0x1a39d8fa70b9354L,0x0068ac4fb0db220L,0x0817c2855075d59L, + 0x11210c532846fe1L,0x0bffd8b00346bb2L,0x00c9515aeea6699L }, + { 0x1576628365ced07L,0x1997d82ef0e8fb1L,0x06f2fd029ea80a7L, + 0x11376a148eda2f7L,0x195a62781b1b2a0L,0x07e0cdc9c4d5ddbL, + 0x01ce54b3fd83ecdL,0x1ade757292470fbL,0x0a8f053e66920ccL, + 0x1796ea5b1d4da78L,0x03b78547a084a4fL,0x181610717f43356L, + 0x0c9ffc11beafba0L,0x0ae6043c15ead3dL,0x10bc318162ff656L, + 0x06374d0da9147f1L,0x068c33abaaf1d9bL,0x0319711449de061L } }, + /* 95 */ + { { 0x0851d2015a1cccaL,0x114863f2915e18eL,0x155463aac14d3bfL, + 0x0f790bc42e16e83L,0x01cf8b29ae65619L,0x0a423c57098a0f0L, + 0x162b8b8b2d64d9aL,0x111d6af761f8637L,0x0decef5d6c264e7L, + 0x1d42b664e5cb6c3L,0x05a04c9e460f69bL,0x1040707af2d45b6L, + 0x1f1d0c6fedf03f3L,0x05355ecdac522b7L,0x1e5bc6495626016L, + 0x13d4e673ea58b07L,0x145cf6ded8fda7eL,0x03461ece0ae8e66L }, + { 0x1e26265e6b392b7L,0x0ecdfbbaeca84b3L,0x13535d9453df3b0L, + 0x041bce5c39c2d57L,0x1adfb033d86f59bL,0x122be6533721e68L, + 0x16a8b6cd10d0017L,0x0636cf4f22cad03L,0x1c32e7babf01147L, + 0x137f0b769d8f4b0L,0x18a63bd8f49b981L,0x1bb0a835badb249L, + 0x1f9982f9719bea0L,0x02f83b5677ca806L,0x0f4e5ad721db98fL, + 0x0e8f4abc255cb64L,0x0a509efbb362ec6L,0x047902af7119943L } }, + /* 96 */ + { { 0x04ab9e3b82c1af0L,0x0f4f3f965713225L,0x10298061f51bf19L, + 0x0bc72766c69fd55L,0x019bacce27d3f33L,0x153308ce4fbe004L, + 0x0ba54fdd062d6e2L,0x113ff528aae6e55L,0x0937d78048db385L, + 0x086436fb78fde0eL,0x1af6268bc2833b4L,0x1f446ce873d6915L, + 0x0b3f17d2d8ae5d5L,0x008ecc4a081d350L,0x02d9e8bc8cfda29L, + 0x17e0cffd9d16643L,0x02e0422540f2319L,0x0094964649a0699L }, + { 0x1eb55870386463dL,0x1e15901b8ecbffaL,0x15c42e06716b52eL, + 0x0d9e095a82366c8L,0x06939ec10cbb42dL,0x0c23f3aec0ce3b3L, + 0x0cb921d16b04e80L,0x1009ee0960438e4L,0x12c9e58a0acb057L, + 0x091dc59dab0f14aL,0x137c01e7e6e8d65L,0x1f843d552c50670L, + 0x0f8aea2b9078231L,0x1868e131d17562aL,0x0ce400201d7b5dcL, + 0x0527559689dabf6L,0x16492546ac2f011L,0x03e3c3b15f5c10bL } }, + /* 97 */ + { { 0x0f7d6fb067902b6L,0x11d21e8b9acc05cL,0x0c4965d07776ca0L, + 0x0e8067f2b80c59fL,0x08589b8c6e391b0L,0x1148791c18e851bL, + 0x07ceb8d1d352548L,0x0729b5629ac445cL,0x18f00fcde53f08dL, + 0x0cc8bd7383f947aL,0x0a82e81a3981f15L,0x07cfafc3f0482cdL, + 0x004d6a328f60271L,0x0c4866953e12aaaL,0x082c82834b8c992L, + 0x1c139e440f289d9L,0x01d5c98dc0752f4L,0x034a01a826c26f4L }, + { 0x0b7b366e5407206L,0x1aa6786c47d467cL,0x1523dc9cb9bc7b3L, + 0x05035688d0dfdfcL,0x0e474408d653137L,0x0839bfa965af872L, + 0x141c67909ace992L,0x15e4aed83369301L,0x191f346280f272cL, + 0x0730527a34798e4L,0x1a8ca642113625eL,0x001972a2b0570eeL, + 0x0514b1adbf8a557L,0x1de9a1f7d58d79bL,0x1607cd08baffe4bL, + 0x061c265f3f6036fL,0x146ad850e06ba6bL,0x036d4f013de2fcaL } }, + /* 98 */ + { { 0x1eee4c25c9490ceL,0x1625186fb41c090L,0x1f8292a4da3aa5bL, + 0x149784c5e7cd8c0L,0x060c34ffd8b0492L,0x0f99e6842351082L, + 0x1d84bdffde990a3L,0x002218aa0884304L,0x09d25fce9149bcdL, + 0x12b08e6e7e309eeL,0x1dfa225fd47395cL,0x1e629d18116a2b3L, + 0x1575e7538f3fa3bL,0x08e42010750ab08L,0x00ab42b4782a546L, + 0x11cbe1a44d1759eL,0x112a04c6ac4058bL,0x03b9da05cd9a8acL }, + { 0x0ff2cdc3631cfd2L,0x06169c03b9bde00L,0x05a8ce2949c0531L, + 0x1b665957bdac00cL,0x070b17cad0e3306L,0x19a9f719b39c755L, + 0x0eb4fcbd2aa35e7L,0x1c0e25ed5b2aedeL,0x0e427985289b2bcL, + 0x0ec7ca6ed496518L,0x0751d76124b7641L,0x0b949a2bc97b312L, + 0x0b254eabbd3e06aL,0x0076a89e2392ea7L,0x1eab9b0c4e52b3bL, + 0x1a26efc1f30b377L,0x175dc125546833fL,0x0095a31c2e2b627L } }, + /* 99 */ + { { 0x10dbebd932951deL,0x0cea12d534e4a40L,0x1013b2cbc2365a5L, + 0x1844a17058bf893L,0x1aec4e1dac74f0cL,0x04cd66cb521cd29L, + 0x0cebf0cf2ae6a41L,0x1165f99bccca9b3L,0x0f4af285c3863aeL, + 0x1b99b9f237f5fc4L,0x159cb0f26adfb48L,0x0261fc240418ea3L, + 0x0f52f3e56ec1c51L,0x12532540d6c1201L,0x1c58fc8d226adeaL, + 0x0662e143f6cc3b3L,0x01717c69be10e55L,0x030e0c9af3ec46aL }, + { 0x0722d9b3492ae43L,0x04eca829c782d17L,0x1620802aad8c7beL, + 0x01d749622f5cefcL,0x1a461cb82872c12L,0x09c7932e1219641L, + 0x1f700c56cd0d32eL,0x11a0b7e558b1898L,0x0d2e501dd596b37L, + 0x028364fe5c48618L,0x0bd185f0d87c32aL,0x0e30b46b975c7a1L, + 0x11f3fc013821f7bL,0x0592476fde881afL,0x1272b81d18a2bd6L, + 0x10ee71ac843a091L,0x19475e3da392ca1L,0x013d686f938e9edL } }, + /* 100 */ + { { 0x03bda79305b5aedL,0x1ea522ccc6b53cfL,0x074c3dfadc00b19L, + 0x1c28fa388990abcL,0x089540edc18a7e9L,0x15fe901f54cb0c6L, + 0x110de94ef8829f9L,0x18d9290fcc9d982L,0x17297920734ef85L, + 0x106a738eaf0f5eaL,0x0ac79935235adbeL,0x1c0acdc401a9fb4L, + 0x1a5a5366a1782a1L,0x0d239b9c151e386L,0x18083a3f8fef4acL, + 0x16ccbafdf180cffL,0x02fec686fdeeacfL,0x02ecdaf13b6e8aaL }, + { 0x037c5a5cb3e472eL,0x1ec939850a02f1bL,0x0b96d1261560854L, + 0x1be73410a201332L,0x15c6c56018f00ccL,0x01aa071311be08dL, + 0x0c611063b50204dL,0x0d7fdef97e0fcfeL,0x0ecd92366bf4857L, + 0x1badf0d5e4a648dL,0x1de379285889d86L,0x0fa78b8d79711c2L, + 0x075ab71858c52e5L,0x1fb71cfcae61c16L,0x09cd7f384b0b0a0L, + 0x0b32c98fc1de5acL,0x166e071deb1835aL,0x0127c48e6e5dc63L } }, + /* 101 */ + { { 0x0ef60bf6778c1e2L,0x0e01e806adf2e12L,0x01b8bc06827ffd2L, + 0x095c12dcb1d8233L,0x1077984c59a728aL,0x0652d2d55de76dbL, + 0x038f7ed1cef4a1cL,0x195192518c29bc6L,0x13fae7f9a4f67abL, + 0x1e15975f610d4e7L,0x1c358a7366d77a0L,0x14b38c1631bf5f4L, + 0x1e4049b54cadeaeL,0x16e98871eaff7bdL,0x18c8733f3baf1d9L, + 0x115eaee91dfc71eL,0x012fe9c32b118eeL,0x0431d61e7ea16fbL }, + { 0x036fca7b85a2fe2L,0x1868477214ee305L,0x08245070e513cf9L, + 0x0cce4e541519374L,0x1968bd06306a810L,0x1e301ef34d0aaafL, + 0x193eae1bdf91c54L,0x0992e0cc295deadL,0x1c0dc36b898780bL, + 0x1b2bff11d0e9931L,0x05ea190d548b250L,0x0feddbfdecf203fL, + 0x146daa17a0d9189L,0x02d667def5df18eL,0x07f0779bc5e4402L, + 0x02859c1b4dc651fL,0x05a1c9d53dbe1e7L,0x01f1f8d8f45c339L } }, + /* 102 */ + { { 0x1ea15c07b7fbf05L,0x188db0f8d1c415bL,0x056b477346f264bL, + 0x155a1efd1793bbbL,0x1ca7ab7931f5b7fL,0x12adf3149b72f5fL, + 0x19550c3d05f7066L,0x17e3ede9c86879bL,0x0971f5e6582f044L, + 0x1e1dc7221446204L,0x0b167ee01fd5d5cL,0x05bb0316b1e0c35L, + 0x0097a3b0d3a64eeL,0x01ca582c37bd053L,0x0cd45f62e17b320L, + 0x07e0d340b28e97fL,0x02589ad5977a79cL,0x04090476c380540L }, + { 0x093509914c4ce37L,0x1dc21d0d5245308L,0x0091603563a3cd2L, + 0x1366eb71750c00eL,0x0d3bde836db42c4L,0x0919db561b2a927L, + 0x051bd548786d192L,0x15d78f98baac9bbL,0x19c14b035bfb5b6L, + 0x1915d0c00a360d1L,0x0beef21c8853d5fL,0x0fef69242ec816cL, + 0x01cb4d6df13acfdL,0x11300548aff886dL,0x16459fd98389881L, + 0x14332f58fb53b03L,0x1c26e8e260cb6e7L,0x0221c1fdc406f59L } }, + /* 103 */ + { { 0x107f01de44f9af6L,0x00d26c658fd0e70L,0x0fb3edf7524cd8eL, + 0x144d51073fccb7cL,0x1ec789d8d0b8435L,0x062f0ff7307c8a9L, + 0x0a073897fa940afL,0x17008ef818afc89L,0x1349e9f83230ba5L, + 0x0a17997ef0c06ecL,0x0e7abd928f44737L,0x109d7d6e1075160L, + 0x04f12742cb80ef8L,0x190501311447306L,0x14eddfd1055b315L, + 0x074b39aa8fbcce4L,0x0459829a6eca601L,0x04577384786aa42L }, + { 0x0f22d9c32c54409L,0x1fd233af5d5620cL,0x04a218a12606a7aL, + 0x1ed6751c1921c5dL,0x1d77641ed0201f6L,0x0b82bae4b980b65L, + 0x13807e49bcbc1c0L,0x0089308091ffd81L,0x0bf696211f319d3L, + 0x05ae422648d4462L,0x03ef3b800c2a09dL,0x0a4bc9edaa42988L, + 0x0c29d67d1ebed67L,0x010e9a9b57bf23eL,0x0ca5017e8c1f6e3L, + 0x100bead6d88d577L,0x1a0f059a7e3033eL,0x04b87b0ff304b52L } }, + /* 104 */ + { { 0x1c53d231bec8e4aL,0x0d60a1ad301a60dL,0x076942791936202L, + 0x1b1491046a9dc10L,0x125864b6496ae1fL,0x06834fd0d74c319L, + 0x09ad2eb284fa5d3L,0x1486e7198b163b1L,0x15fa71f58e76b9dL, + 0x08cdf4463f58b7dL,0x03c4feb5390a772L,0x0ce24933f3dbeb9L, + 0x15a10d8bd74583bL,0x0bc85dbf5e71008L,0x0ade377d9b5d815L, + 0x0abf5262d5dbc90L,0x0a7e0d8fb2d75f8L,0x02025adca2d3ee6L }, + { 0x1ee682a517a15c7L,0x067de77c401017cL,0x04e5441a8d52ab9L, + 0x042e1fd7cf9dc58L,0x13d0c54b5de6019L,0x08495bac4f1cfebL, + 0x1f97c6571c4d632L,0x0f396fdaa7e14f7L,0x12bd9242af61cc9L, + 0x09778b629cafbecL,0x0b0729c2ccbc263L,0x04daa5a30b821a9L, + 0x0a942d6195a5875L,0x128058561499582L,0x0bf48c3f896a5e6L, + 0x04a78bf43e95cacL,0x00260f55af220daL,0x03fd508dac18a30L } }, + /* 105 */ + { { 0x0ba4f0c6e402149L,0x0660ecb1e608cd8L,0x106a9949d1d8d61L, + 0x0b92ae2be4ee81bL,0x1f89fb0e3f77ff7L,0x0df1ffd9791a569L, + 0x1fa09545640cbbeL,0x127f93f643a0846L,0x1eb2eff38a153edL, + 0x0ea9d7008020e89L,0x19516dfc6f60a22L,0x0f9c872a7d4b9e5L, + 0x14d85e75c8dd4a2L,0x120df0e1806972eL,0x1080cb7ae4fb588L, + 0x1ce023ca7e4be04L,0x0bfb9957636c3a4L,0x00a5b1d2976cc7fL }, + { 0x010b55371c43336L,0x1ea5311d24125bbL,0x0b800a18146c677L, + 0x191ebe3db6f72f4L,0x1b67daad86abbb9L,0x0ffd7db3d2bebbcL, + 0x0f18e2b3941b735L,0x0a10bb53f2b1358L,0x0081cbaa875a3d1L, + 0x19a9ec7f49a3769L,0x0d87c687e680b40L,0x126e74cb38e3655L, + 0x0b4f5df8a1b0cb0L,0x15bead0edbf0718L,0x03973c1df131d07L, + 0x0e3591e08d938e5L,0x05532dd0bc7f7c1L,0x001242c39c1b693L } }, + /* 106 */ + { { 0x140dd2375a4cd8dL,0x05219cbde5d3c66L,0x1610963587d44cbL, + 0x13b43d1cd0618b9L,0x1d65d40a0a7ec05L,0x1a86bb03d478b88L, + 0x0b90a1a79957bd0L,0x1a17319cde0b307L,0x17b61391d9d8bebL, + 0x1294f12d8dd2ea4L,0x1ccba47dacb3d8eL,0x18d47f476c528deL, + 0x0cc3ef0ed2bd66eL,0x0f845a3b1cbca87L,0x16838bbba40232dL, + 0x1790ffad7c84b2cL,0x1ae78ed513c1177L,0x033cc676fff2896L }, + { 0x1e3f8fd1b97c5c6L,0x1d59f3c61d99fa4L,0x104903d656e8e7eL, + 0x12bafa86ec884e8L,0x19c44777174225bL,0x0b5922c4059fe63L, + 0x1861370eb2a0ccaL,0x0e4ab227bee2e69L,0x1a4db23d39c9344L, + 0x15d9b99e8a10508L,0x0833e7cd822f733L,0x19ec619fc27f73aL, + 0x115f30874ca618aL,0x0f8002d2baf8359L,0x0ff276d41bbf9feL, + 0x0f883155d4f1803L,0x195f9179255f78eL,0x01f53d7692974b1L } }, + /* 107 */ + { { 0x0617e045b06ae25L,0x00a46e5aba877ccL,0x1c398130ae8af2bL, + 0x16ed6f12eb23d45L,0x051da18100c19f6L,0x02b82dbcdcdb683L, + 0x16fc7cc896faf25L,0x0da61686be6b800L,0x1440b4482bc24d8L, + 0x1c784cb6b1b9bbbL,0x15b1587112d370aL,0x1dcc6120d332cbfL, + 0x0408aa1ec1e9405L,0x1e97944a8cff849L,0x1d19e5fbbcc91a8L, + 0x0befc02d86ecb78L,0x04462d2569fd070L,0x0354569ce029280L }, + { 0x05f020d46be7282L,0x0d7f6909c078972L,0x16f75769ab42501L, + 0x08ff17cc3c99b94L,0x196b8178c2d6f18L,0x06fcaa100994a9aL, + 0x0ad3634ec79edeaL,0x0aceaf8c37672aeL,0x0d749b57b80cc3bL, + 0x0c87fc99bd9fff6L,0x0ed94c517725365L,0x0c0c466bcae6737L, + 0x17f763feba70c1cL,0x0630db994e17396L,0x1cfcb291da39093L, + 0x0b19aeefa5f4d54L,0x1aadee4dbaac5cbL,0x00d0c08bcce7d70L } }, + /* 108 */ + { { 0x16ff62f77575ed0L,0x0a7d4be8ed4cdb7L,0x1beda7bf5fd863cL, + 0x17bb850c665ce55L,0x186c5834c45ab4cL,0x1baeec587106a42L, + 0x112634e5c0468e5L,0x1b002619011e826L,0x12d408ebaf5115eL, + 0x083502e01306f6cL,0x0dcd88672ae4471L,0x118dd0d2750d3cbL, + 0x1fcc7736174cf50L,0x0aec4e51a738922L,0x1eef260bdc6a87eL, + 0x0ffa49774f8d4c0L,0x1a8f3a515e7212bL,0x03e96ee3ac9187aL }, + { 0x105816d4ed2cae8L,0x15e3edce001bb9eL,0x039991ac235133dL, + 0x0297380301847d3L,0x0f9179c1f9ee6c6L,0x0cb445708e4d09fL, + 0x1c29e96d851fa3bL,0x0eaf5fd6c91a0ccL,0x0d670333c176852L, + 0x04eecb4bafcf479L,0x1c8a34de9a2b7aaL,0x1abc8a99630d76aL, + 0x0f063dd55021a05L,0x065b6579a4080acL,0x152af9e4b753c21L, + 0x13aece189b0a4f0L,0x0ba845969dc6e72L,0x02d297c3d58dfa0L } }, + /* 109 */ + { { 0x1019e9109ecacbdL,0x0011ebdc4def576L,0x1c2d5c1cdc79951L, + 0x082d91c42ef98a3L,0x01259ab514832b0L,0x11b0ea58d533414L, + 0x170a9b8403e488fL,0x04dcb27ddd3c752L,0x1699b6bbd16c10eL, + 0x0a43c39ca39d09fL,0x053716c9d261f2bL,0x00ea4ab3c5d3e38L, + 0x1dc3d47ad257dc0L,0x0ea93bc9c224c24L,0x1f56e660f7c9e2bL, + 0x00540ee1c7d91ddL,0x1fe2ae5844676bdL,0x00bf813b21f382fL }, + { 0x1a4010d29abea1fL,0x1cb4a9203d6266eL,0x04a410cc862d8daL, + 0x162c7aa6952d4c0L,0x0cc20565f221fc3L,0x142abb82dd0adf6L, + 0x0134c48e3953658L,0x1c8362884af0f10L,0x196fbf304a89a9fL, + 0x053f83625f32158L,0x0883a1b8ac217b2L,0x0f85fe94b23bba3L, + 0x13a4a343b88f7f2L,0x1d8b9ea6e0bd83aL,0x101eef9a12c7a22L, + 0x03aee7599d4887bL,0x17edb15c88d4c44L,0x00778184d29f2caL } }, + /* 110 */ + { { 0x1c25721fa8e5b60L,0x09c56b48e05d927L,0x0dd82c28892191aL, + 0x04fbc2d0efc8da9L,0x0721c630863f9acL,0x13fd81281ddb779L, + 0x0f4e7e306677c2dL,0x1b4f183dae5c0f5L,0x1cf9deb7bb32f0dL, + 0x1fb9378361e44f9L,0x022cb465c8896abL,0x022e9e28beb96e0L, + 0x0c457c4f378f5a6L,0x0e229e32270737cL,0x1a4b2022ef6a910L, + 0x06ac2af7c64db4dL,0x12aa9bc3fd95d77L,0x01e9db6635d9bdbL }, + { 0x06f12cc9722c880L,0x1b5739435b444b7L,0x026eb4bebfb0e86L, + 0x14877717df74398L,0x17c3f4c3ad64ad7L,0x09d48dd2d7b5004L, + 0x0fdacabf2c3670dL,0x1219427f956d399L,0x1699a1391f2abc1L, + 0x0deaaa111d123f2L,0x18603e55223668bL,0x17fe24899879c40L, + 0x1e87d3a365ba9e7L,0x1d2652f11494bd5L,0x0f86db10153e8e3L, + 0x034896720c47acfL,0x0e71fa67c5778f4L,0x0174a3721e3daa2L } }, + /* 111 */ + { { 0x180fddfc60934aeL,0x13f7f8b21036894L,0x1e5905bb5d68b0fL, + 0x06b9a165b9eebcfL,0x1faad87bfac60cfL,0x04f2eeeee25f670L, + 0x1c6b9d4fea1f261L,0x0978baa2d465837L,0x1565dbea814732bL, + 0x03f5f1d672434b5L,0x09d35b36e5da500L,0x04e0cbc9cf7c819L, + 0x013aac4ebc3f5cdL,0x01eb61d0ba423e0L,0x1e81da99d8b80d1L, + 0x0cefad21b192a8cL,0x0c2768d78d61edaL,0x004cbe72a80c0ecL }, + { 0x097746c965a0b81L,0x0c5f372f096fd49L,0x0f11c57d0dfd22dL, + 0x0f6acb88b2aae76L,0x1582797ce425e90L,0x12a3a7a7a1fa890L, + 0x012b3976be9be3aL,0x10655d71f7c27bcL,0x0ed7f95f0e8a07cL, + 0x1009537331604ffL,0x1ba6e31d0b3c5cfL,0x0b35c514388b7f2L, + 0x145cf4e2f38ea57L,0x1c80d00ca3aca0dL,0x045acb9f74f00b7L, + 0x17311cf49bdd4e1L,0x1e650b272b52fa9L,0x04b7cf84fe848bfL } }, + /* 112 */ + { { 0x0e8aac42c310a96L,0x0c181fbd1539a3cL,0x00f48e58881ccaaL, + 0x1db2a8250188d95L,0x0cabe911ad131e6L,0x0db6342bc8fe2f1L, + 0x021e1432ddfae10L,0x19d5ff27bd47a79L,0x106541f1df1007bL, + 0x17394e12ae6f8feL,0x1c4c5cc8f8e5c93L,0x14835a9a1183c1eL, + 0x1fa35e22bfa2de7L,0x04d81992d4c8955L,0x145353a814048aeL, + 0x1c157173ca3e80cL,0x0a5423c7aad79d3L,0x038ccc713205c7fL }, + { 0x0140fcdceb6ed78L,0x079bb8c29a28b20L,0x196ba358373194fL, + 0x0d3b58abf008a16L,0x0e05686cce6c1a7L,0x1892b1454b5496dL, + 0x05094bf911d8849L,0x184e8f796a149e7L,0x0f0ec6ff2fc531fL, + 0x0be1a23887f4ff8L,0x021e0e71e4b3ff2L,0x049004df6033f69L, + 0x1cd804c290552c5L,0x1ae46539a000d14L,0x1977e81d0ad6b60L, + 0x0956386f03e2eddL,0x0acca6b85f03dfaL,0x041c4ca0d058699L } }, + /* 113 */ + { { 0x0f062a2de067dffL,0x193485e5c00b160L,0x04341c1e8af753cL, + 0x11f5c94723319b3L,0x132ad8145afc63bL,0x0cefd8b4278dbddL, + 0x16122c28b738bc6L,0x0c444c1c2fe91e4L,0x17393db00c2d5e8L, + 0x1447c2a19c678b8L,0x1e50a40ab3d48a7L,0x1970d06b5e7a00cL, + 0x12b8a2614c19157L,0x09a7623617d537cL,0x1ea04d413fe57d4L, + 0x08e099e00c4ddf6L,0x025454b3d05b37aL,0x00fdfed18934a76L }, + { 0x1ebb657c8f69c77L,0x013c5d1efc47d7eL,0x15c707ede2d24aaL, + 0x14238e34668c76aL,0x089958b0d2066a1L,0x0eb3d3086440a18L, + 0x1ee3ee5d71f833eL,0x0c3b54ba410e606L,0x15ee5005d40bf58L, + 0x0073673bedd34d4L,0x10f2cf258b31d0cL,0x0c5299f080ab127L, + 0x1a225c9d700ac98L,0x1c8f23f4053f7b1L,0x0be12fbf86121a6L, + 0x0f17e373afbd718L,0x19e67788915c0e2L,0x027ca4465621378L } }, + /* 114 */ + { { 0x10dfcd4dd51b8ceL,0x1c93c1b11874030L,0x1c70d9665588215L, + 0x17c595d0efdb8ffL,0x07967608905ead4L,0x1c493650e192ecfL, + 0x02938f8e7b776f4L,0x149b52590d0bedeL,0x1e16f800af47a0fL, + 0x05a6dadf2fb0555L,0x1504be60e14f4d4L,0x04a136f2f1386ccL, + 0x184e0e72b264b62L,0x12aae15df52b002L,0x0a4b846aef52407L, + 0x0431e6f08334e2eL,0x1926e0b5aaae174L,0x03447034247bcb5L }, + { 0x1fef641313b8f64L,0x08dbdca163a3166L,0x0ddd70362af6bbcL, + 0x015e8083520cf9fL,0x0935210f608ea5fL,0x08bd0411eadec13L, + 0x0b4856ae413f09eL,0x13f0bb763fc8ba4L,0x0c3d5e5094d3615L, + 0x15da9470e9cdc79L,0x12a0a3d12b3bc2bL,0x15be418af4a9babL, + 0x1378f95f4424209L,0x1499be9baba15a1L,0x133f6df447e9f66L, + 0x02fd9acd418138cL,0x06556e55b8f9bb8L,0x00b91e3f1f26209L } }, + /* 115 */ + { { 0x06486d8dc8b43f3L,0x1073093204f344dL,0x10df66d1800ff0fL, + 0x0ac509d8f631138L,0x0a9dbaea3a85033L,0x1c499e2d1b32e23L, + 0x05241efda5077a5L,0x05a3dab4a20d268L,0x1664a7b7a8cb800L, + 0x01fbb723076852cL,0x01ae8c7d3afc9d8L,0x1a83e58714ff87cL, + 0x19cf1db08a296ceL,0x06f3d1db1560c7bL,0x1da2c1b2467a20bL, + 0x0f96a2bcefa53b7L,0x13a21978baa4e94L,0x0425faa15bb184cL }, + { 0x1decda9e364f21eL,0x079a280972abf60L,0x0121623e438435bL, + 0x17c76209717448dL,0x03aef57a9f6dda4L,0x193f54b5fbd1a37L, + 0x19b1c840a67fba0L,0x08b5533e90fb52bL,0x024ff813ed2cdf6L, + 0x0edd96945ea0a5cL,0x0406bf2be869874L,0x173539bd7b480caL, + 0x15e41039e47d9f4L,0x02856fa157a0d9cL,0x07a79278fa79aebL, + 0x0fe469e42675c68L,0x1534968c0f3cb15L,0x01c1fc13ded0340L } }, + /* 116 */ + { { 0x0c46a216583ff4cL,0x02d14a56b84f397L,0x073f013284a9399L, + 0x0922c14fcbb8cddL,0x169c762e82f128fL,0x16dc73dfd913d8aL, + 0x1da23e031e58f0bL,0x1994fb5fc0c9341L,0x0b7e417542d14b8L, + 0x1062e29c36f205fL,0x014a1876de4cc4eL,0x1cd3f7fc0e37e1aL, + 0x16210e9903b902cL,0x1b81f5dc30f234aL,0x17de2dbebbe1d3bL, + 0x1d475ecd128fdbaL,0x0256fe865475af5L,0x01d890f8aa1fca3L }, + { 0x126e847659275e9L,0x00e7eb687e7282dL,0x0ff62a8fc7bd1d6L, + 0x0bc909cc1cabeb9L,0x1e9698e41e7be31L,0x1823c26c78d107fL, + 0x16cf89751b6a5eaL,0x0134a4db6eb0699L,0x01fd408d98d08a0L, + 0x00025902dae540bL,0x18eecd9792efa3fL,0x024aeb376ddeb67L, + 0x17c2fac737f50ccL,0x0939ca8d782fd40L,0x12ccd9e7b840b4bL, + 0x0a2be551ca817fdL,0x083673446fb2a6aL,0x02a82f0e89b9486L } }, + /* 117 */ + { { 0x03014a1d15e68a6L,0x18593326e9af286L,0x10b40eb59fe5be7L, + 0x1da58289083186eL,0x0d41a3cb74818c0L,0x0f9f4f628c08b48L, + 0x04e19972320ff12L,0x139364c18c2584fL,0x0f6086faeced04eL, + 0x1d96675febe23acL,0x10c4ce40a5ff629L,0x09d012e03590967L, + 0x07508b3762ca826L,0x0c1d46ff4fcbb54L,0x15663a575609c52L, + 0x1a6906a1a4cd3b3L,0x17c85cb89cb0f6fL,0x030bec06a52ba18L }, + { 0x0ef267e70022b67L,0x1b5da9bb45ca526L,0x159b49e1118a014L, + 0x087048723262a74L,0x1df78c4a49054d4L,0x10f1ad4688f0b92L, + 0x18c766c94a9c756L,0x01c0f0cd90102e3L,0x00a8501db1b38a0L, + 0x16c995c673b811bL,0x1dd8263b6bdf40bL,0x1b5772600dd345aL, + 0x04bbfeb0363aee5L,0x0710d9c5fd7fe46L,0x0a381a41dee59e1L, + 0x108e2923f8b3fb9L,0x00b3f624f550e93L,0x028ab7a843e68bcL } }, + /* 118 */ + { { 0x0234e220206e8d0L,0x17aea3f8ad7992cL,0x0a2758e2543fd7dL, + 0x12fa892be95f56eL,0x08da80a966ec4d0L,0x1c51b5d6c4862ebL, + 0x1717f92a8248193L,0x062f33c4afc1e9aL,0x044c677ae24495eL, + 0x101c3d9d2dc71a9L,0x1e43d1d68a1ee5cL,0x198b8783e5eee06L, + 0x1b41a7fa4154895L,0x18058045dc3407cL,0x191cf2ff351d162L, + 0x1c3342939907174L,0x1ba78ed5f7aac9bL,0x0292a2cce599bb2L }, + { 0x0739679a21b54c4L,0x167155b24bece84L,0x0a4b212219000a7L, + 0x1fd3f4f3b3e29e3L,0x06c208dbae48dcfL,0x11fb4f0a5c88e12L, + 0x0e0e16ac3efcb6bL,0x176301590fda3dbL,0x0146fd718188586L, + 0x0875b2a2a33e5e8L,0x0e5020599f3fb88L,0x18356e7a34c1544L, + 0x00881c1cbedb125L,0x1be181196f34298L,0x0f23463f8d31c4cL, + 0x09d078d8c0e1cdeL,0x14507e365bab4afL,0x0117853f6ee7c15L } }, + /* 119 */ + { { 0x062791fea7f1b7fL,0x0c62eee7f84ea71L,0x070ce71f716270fL, + 0x0e84edd1810d855L,0x09fe1d564dad401L,0x1408648548c7acfL, + 0x13712e35e59c0aaL,0x05dd6f5106c954bL,0x0fc4c23bbe7afa7L, + 0x0ddae4f25643484L,0x0e404da831f9bd3L,0x0002938431a46fcL, + 0x0794b324a2855d7L,0x1143d038f23ade3L,0x0d0c8f3262a3719L, + 0x113d272b45336bfL,0x046e186c3ee0c03L,0x03cfc0f378b39a6L }, + { 0x1f2c1f3364f3c4eL,0x1956289b3f0a5c1L,0x13f164cf90f54daL, + 0x0a21b2c3fc894dbL,0x1e3f2aae34e5947L,0x153f928411a7673L, + 0x084932e4b802af7L,0x0743df749e14f23L,0x0c2086fd21192d5L, + 0x160687e5a8e457bL,0x06cb2b703c6d7ffL,0x111f025b7c3291aL, + 0x0adedbdd45b07a3L,0x0b812c4d20439d3L,0x189ed92f0a849a3L, + 0x0dd0b77edc7502fL,0x00073ee56636d38L,0x02217669bcef3e0L } }, + /* 120 */ + { { 0x0cd1ae68a2f90a6L,0x1ea0eb7ad68665aL,0x031100752e3bc9dL, + 0x09b06ecc62d4705L,0x15e1124be817a13L,0x15caf20a15bac6fL, + 0x078f897ef1a77f5L,0x19d46193ebfae95L,0x15ac0f163d89663L, + 0x154f77b86731c36L,0x043a9763b55510cL,0x1fe1311284f4f4dL, + 0x05eaaced585de23L,0x09f0c232bad69b5L,0x024e440d4529b07L, + 0x0add07b22c586feL,0x11e5c10add9e33dL,0x0428bb5b9835534L }, + { 0x12110fa28a21e38L,0x11bceabb9ea9c51L,0x0efcb40837125edL, + 0x072c30679ba6d2fL,0x05fa85165917759L,0x155ae936b822fd7L, + 0x16dc0ce43ca69e1L,0x18d5817b461b89eL,0x1cca0240adcc615L, + 0x10f8b81628a36c8L,0x11cb429cb3be1e3L,0x0e1016cd37439d6L, + 0x1d7e61aa0a84840L,0x0334ab05bcd847cL,0x03adc78e20582f9L, + 0x0b2184726b85b29L,0x0b3d7fd83c09431L,0x04558aa5db72bb4L } }, + /* 121 */ + { { 0x0686003353c4a96L,0x03074482e6c1a94L,0x0d923d9be331397L, + 0x113f599f3d7ab22L,0x032639e5b6b80b9L,0x0556f5de0e0fd77L, + 0x080b4bd8e5b489eL,0x06a014f2da03130L,0x018ab548f3a4748L, + 0x0682b61d98d871fL,0x09a374059144b6bL,0x0db29607e7782b7L, + 0x0bd8f206c520383L,0x0f8bbcdb6b27653L,0x0acd2a24c68d87aL, + 0x05c45b04d21f8a5L,0x0a9342bb8e09292L,0x00dfe6ec2700581L }, + { 0x10b9a4375a365d9L,0x0f0af046c7d8198L,0x0f5f5d0b7e0f52bL, + 0x09bc630e85392eaL,0x1360ace0cf7309dL,0x134b21891471091L, + 0x1694c410f48e3ddL,0x12ff855b7dbf21eL,0x041d64cb77b5f93L, + 0x100598562236808L,0x0190b48c5c83f94L,0x045b735440eb879L, + 0x12041eae47fcc01L,0x14643b5242b71d8L,0x0d81ac516191155L, + 0x0af7e3438f08446L,0x0f19b766d1f2277L,0x012dbc51dfbdceaL } }, + /* 122 */ + { { 0x0835718156707ceL,0x011cc218a7c8548L,0x016a2f95f6f66f7L, + 0x0b5ac7497002f91L,0x15aacffdd4bba22L,0x0aa3912e738dc30L, + 0x14f757c9991d5caL,0x1ae1501e3ee9e15L,0x0010538a3fc352eL, + 0x0532022a101e365L,0x11ea20cc31ced3eL,0x1dcc05b95836565L, + 0x0fed2b17c7b3433L,0x1eb194e397024ceL,0x1eb70de7e1a0692L, + 0x112b6712f328c6dL,0x0f0dc5650c892b7L,0x03855cab832d28eL }, + { 0x0778ec47b585d93L,0x09b085319ff2723L,0x15393a80c46b29bL, + 0x177ac8005e43b42L,0x191cb7a9af22190L,0x141bebcf319d63eL, + 0x1ba2bb44f0c7fb9L,0x02db4940fae2c2dL,0x0d78a27323afcd6L, + 0x0334b72dd0a6b4aL,0x1d535d37d610830L,0x009c4ef1c792e66L, + 0x0c55b5a5c2e85e5L,0x051d65ae182ad50L,0x0223b68c4f7d4e2L, + 0x0bbbcb12d596a54L,0x0befc8842a084c8L,0x02ff64fbca8eef3L } }, + /* 123 */ + { { 0x0bc2c7cfe519f99L,0x15ec072a081a9afL,0x100a28e623cf8e5L, + 0x0bac037b435bdb2L,0x14ce64ac1c03b73L,0x1201487e98101b0L, + 0x025f560dfafa404L,0x073955d43474aa8L,0x1dce73d25b0b881L, + 0x0f6a095f658485cL,0x0a7fdf58f6acf0dL,0x0fb20c5b60e3320L, + 0x1642a4c11d55543L,0x127e488493be97aL,0x06495351dfe9914L, + 0x0c318f625d36e4fL,0x1957ad2ae22d84cL,0x00546ab31e74768L }, + { 0x1ac51630a21fde1L,0x1aeeb3481ec24a1L,0x07b97f758a073f3L, + 0x00ef493468da493L,0x0875c06f4dedc6fL,0x1dc023235ed1601L, + 0x00dbf438383d8d1L,0x08420b02d36bccfL,0x0c961912ade8a80L, + 0x19ff505549d9e99L,0x0e3b6c315daf177L,0x1addb1a6fc8f3e2L, + 0x19cce5e7cb7971aL,0x0e9015a0755c2b9L,0x087f49a2292d0d0L, + 0x0df22bb084aafc7L,0x09f872fabd5b3a8L,0x04adc9a49b55231L } }, + /* 124 */ + { { 0x198a70199f951deL,0x0f2cb782c6da2ccL,0x107bcf40f74e3ebL, + 0x1a676283a69a8f3L,0x0cfe8a406e928d5L,0x077d1ecd232c005L, + 0x1c9bb4422b4bf07L,0x13ec972d243c026L,0x0b9b6a6b68e83bbL, + 0x0f8f36e092172a2L,0x03d9d8bd9659acaL,0x012cbc20b683a7fL, + 0x1a16011e1ca34ddL,0x128aaa0dea7489cL,0x08859b7ba9371a0L, + 0x0c248df00615990L,0x07dbdc7ae1d31d1L,0x01712f7a8b10d7dL }, + { 0x133cf8fdd8e7357L,0x1d10c75676edc12L,0x0c741e134ab0cceL, + 0x0de50095c4d1c7cL,0x17e7ad7e1c927f3L,0x1fbc5000a19e913L, + 0x09eb82d0073c161L,0x16b3bf9e06d5400L,0x0c9e46c8b1d9a46L, + 0x136f2430f944699L,0x1b68bc6e2810f6aL,0x01cbe5a176adbaaL, + 0x0419defb5634623L,0x10e9643a0cf85b7L,0x03916cd57b0df34L, + 0x1d0a47b7e072f6eL,0x1d6f0862a8dac7cL,0x043cbcf53f0a0f9L } }, + /* 125 */ + { { 0x17e7b3f7f1c747fL,0x1260ee37319b4cdL,0x1dc2cdcb6e80546L, + 0x09a7dca9fc84e7fL,0x133cae0fca6d223L,0x0b7886097e47066L, + 0x073e49cca14e177L,0x12390de7f7be035L,0x05322677fe36caeL, + 0x0d3801997f7f522L,0x128ca33a2bc85ceL,0x0eeded4e63e8593L, + 0x1f66a96813c0256L,0x06d976d46343d9eL,0x113faf4652aac4aL, + 0x08365bc61b8b5ddL,0x016c052236a9792L,0x01f64c401611ea6L }, + { 0x19e760c4072f74dL,0x1586f55aca02c87L,0x090326c0270b9e3L, + 0x00716b35cbb67bdL,0x0b4daa0647e875fL,0x079bc47a075a1b1L, + 0x0be2e69a93e4824L,0x0addfd7d35fdb7fL,0x1f87f96a59867e2L, + 0x137f691bad5b575L,0x09e0a8ff6c4f2c7L,0x0e3ce1f44c422feL, + 0x0cfd4c0dbe5102cL,0x181a394bae95837L,0x19f9e014df309a0L, + 0x1b4651b7ebc5656L,0x1142f633f3aba25L,0x01f498af477d764L } }, + /* 126 */ + { { 0x055cfa5239a9ea9L,0x1e34805f19d3149L,0x0d2e72d90af483cL, + 0x0c0175ce30eb3ddL,0x13410f843316c54L,0x1894db43a53b6afL, + 0x07c7048ed40ba43L,0x1195b91f350250aL,0x1f57b764a1b6240L, + 0x0b7600f8d403bbdL,0x1b3bc87c3771704L,0x08f9cb4d4b4ee8dL, + 0x0706e955ba3c49dL,0x1a2ebcd80f0aedfL,0x034421d8a7031e6L, + 0x045ae224f0610efL,0x19122585dc78c6aL,0x017681506853413L }, + { 0x10434164daa2682L,0x16995809acb12a9L,0x0d2af619c25c389L, + 0x17dcef5c5c89390L,0x1af6c16911a19d2L,0x0b082a1cdea94d1L, + 0x03f84db32970173L,0x06ac6e14b37b8d8L,0x0ca420d27b93d51L, + 0x03986a2aaa6228dL,0x0963265b37afcb6L,0x13214a1f340bd7aL, + 0x1a7b0f01510cb1bL,0x08e90bf0b4d464bL,0x0bdd7a0b30db4d0L, + 0x054c3e22ed114eaL,0x1dd1db01394a09bL,0x00a313c2254f7ebL } }, + /* 127 */ + { { 0x1ca3aed232803cfL,0x01cc5cd4b7f9a35L,0x15fdd2ade22f079L, + 0x00fcd1809b95eceL,0x1cb7cd20c3a53e0L,0x0345e52fcb4e0caL, + 0x0c0cbca2d969b70L,0x029c79403a63b0cL,0x09b733b8187808eL, + 0x0eb826cf7f30c5fL,0x1cd50ac06e51b6dL,0x033df7dbbb7e4edL, + 0x0b903275cee057eL,0x0407bde33e8c179L,0x11db050f3717ddeL, + 0x0a0e5ade07a7ef0L,0x028035f5557a9baL,0x03d65abdb5a014bL }, + { 0x041356944e6b07cL,0x02664f0e39a2ee9L,0x136389cee7ed147L, + 0x13711c69f880e88L,0x1152776dfe49607L,0x0114ce3be8c267fL, + 0x0a25db440cee71dL,0x04053414d08ef7eL,0x059ffdf10ee8f04L, + 0x10b8a36225dab6bL,0x141b0bee6ba1553L,0x05b7b27cf9ab063L, + 0x063c96b607b2cb8L,0x1aa4f154419c0e2L,0x12887501abb4945L, + 0x1f7bbdf2f1238eeL,0x16cae9807c78675L,0x0352d02dcb1b1a8L } }, + /* 128 */ + { { 0x0e71ea66a8f4f33L,0x037e326f547a549L,0x14b3fba21187cbfL, + 0x1c112a9a11a6ac4L,0x068ab76659b0a83L,0x07c6822deb4611aL, + 0x19eb900a04d5e40L,0x08230383380a570L,0x0986a516918764cL, + 0x180efd709abae92L,0x1a6b9564d9dedf2L,0x004a8db936322e4L, + 0x19c40097c8f6d17L,0x12ce203dc6f3424L,0x14a762ddb7c00c8L, + 0x16bec812355b22fL,0x08ca7f46d214a7aL,0x034402a5a387672L }, + { 0x0d168aa51a5b86cL,0x1f26c4abbb923f8L,0x01dbc5c80ca490dL, + 0x1b2c8f4a9d5d088L,0x0405622c0a7ac87L,0x13cf978f2cbd258L, + 0x055b7b7bf971bc2L,0x1ed5e7de1849aaaL,0x1917fb04eef047cL, + 0x1c93ccfaa5b109bL,0x1a8cbcc52f82e0dL,0x0cb6188cd6190ebL, + 0x0e7e218978e157cL,0x06f2c3d7e946486L,0x01defb6e43f0eebL, + 0x0219bba65ae3917L,0x0533b432200ca8eL,0x00010fa0ceca7b7L } }, + /* 129 */ + { { 0x191122c43519d26L,0x1d60ea0528c2290L,0x07a5522ee27ef6bL, + 0x182d0897f398deeL,0x178e8d559ef3375L,0x05f0e2f3bc4fbc8L, + 0x1790013d666d87eL,0x193011193345977L,0x18939a260893206L, + 0x0d725fffe698428L,0x12cffb823fabfa8L,0x0133fe295578cc9L, + 0x0c2a841ef961f38L,0x0bf80edb06c1ca6L,0x1aeddcdd7eb62b4L, + 0x04a24df868aecdbL,0x19f1e716b05a425L,0x03cc2ac4014f0f6L }, + { 0x0cb3aaa95106473L,0x17d20ad30ed0251L,0x0d894e558f0257eL, + 0x032a62570ffa792L,0x1f885c76baa4809L,0x063c6ab63f3ac15L, + 0x11035c3db6ad88cL,0x10d19c60a38ee8eL,0x06dbebd14ffdb61L, + 0x07020fd0c87204bL,0x031199bb98b8aacL,0x1c54e9e667ad742L, + 0x04fe7b9b6693d57L,0x036941be803556eL,0x01d07abebdcbdb0L, + 0x048ee63198bcd22L,0x08d9c5026096569L,0x04aec11e18e87d8L } }, + /* 130 */ + { { 0x0eebd86140528a5L,0x0615d29cbcde435L,0x0e293b0512afc9aL, + 0x1b054fafdb63793L,0x0e0118d81efabb0L,0x00aac778963868aL, + 0x19cf8c581c5a287L,0x1ba67c8516fc96fL,0x06317663783aec9L, + 0x0b97fdf709561aeL,0x1c2feef05eca914L,0x10e0e83f02546fbL, + 0x1be2888f9c4212fL,0x1ab652ae9ee765eL,0x00a3906a77056a9L, + 0x1b607e63231d972L,0x1547ede02856aeaL,0x00713846abc32a7L }, + { 0x070cc53cde20f88L,0x013962fad881c91L,0x0679772c76fe4ceL, + 0x136e5ae982a085cL,0x0aaaaa554b3de21L,0x1435d30b624d459L, + 0x05a5402110f96eeL,0x023dcd79ae4419eL,0x159ffac6ba89abdL, + 0x01890bdf88ab1ceL,0x0a2bcbcd32e948aL,0x07ce0e4f520dc9aL, + 0x1f69017766f27f0L,0x1d40891f342163cL,0x0a5cee32cd1a6f5L, + 0x01b7a9181e68d48L,0x078fc5784a62399L,0x0069ed59dfd94cbL } }, + /* 131 */ + { { 0x18376e6ce29c3ccL,0x083f6780b65e347L,0x065978e533872c1L, + 0x1ee78a1a83bd7ffL,0x0d16ce3d24fc526L,0x0098a0a76ead2a1L, + 0x0181aecdef76647L,0x151c6885de5c675L,0x12ae90337c0629dL, + 0x1fd76322c955998L,0x0e265f60ae15ed5L,0x1973466e62ec352L, + 0x029086751fad6c8L,0x0c60b8cb412caefL,0x1a5cd5ea07a5fecL, + 0x13ed3c9e914277eL,0x026a1387c2e5cb8L,0x02985a775ac3a5aL }, + { 0x1f275a1bab7b5aeL,0x0ee2681d2bdfa74L,0x112a9171416eedaL, + 0x0682d5880592e9bL,0x0ed985dc726369fL,0x0a2350b9af273c5L, + 0x0c0a8152361e737L,0x14d099d60d33c2dL,0x0f73f6fa4789b11L, + 0x150620fd95273c2L,0x1da40a4ea6da5daL,0x1c01e075156563eL, + 0x1b844d66c1814ccL,0x184a9100b26592aL,0x08c89c6de539f58L, + 0x149b3c0a5a9c87bL,0x17f5278b2e708b6L,0x0484a12a940632bL } }, + /* 132 */ + { { 0x069a14d0d5b4c2fL,0x1e2cdae45324e69L,0x0ceac38df528ae3L, + 0x11222206fd2b7d9L,0x14e35322fda1a76L,0x1c7d7e2c08702d4L, + 0x1398a8937304a85L,0x088b858c7651c7bL,0x1995c3f179452c4L, + 0x0998761a16a28b0L,0x16982ad3be04a4dL,0x04a5175d3827404L, + 0x06e2e3caf885493L,0x1b24dfa392e8d30L,0x13b17c7510246acL, + 0x066678fa15f7ee0L,0x0f527bd1d62bd8bL,0x0282b8088e7f30bL }, + { 0x0084acef534356bL,0x0ef02a5a587de68L,0x18173b81370677cL, + 0x106c36f1c20435fL,0x0f78d38b64bde68L,0x052f2751927e63fL, + 0x0665bfacdcb3bacL,0x09dde09f966cb02L,0x07dce5d505eb0abL, + 0x114dac411c62c37L,0x18c65ef36000dc7L,0x08a2900d739fbcbL, + 0x0bd18e67ab8bf5eL,0x1cfb1fd6a1984b4L,0x1062ed09a9f413bL, + 0x1c459438fe2476bL,0x19f485b848225dcL,0x047f859b7eaa073L } }, + /* 133 */ + { { 0x1f2e2f43ff42cffL,0x0cfce8e1a98be4cL,0x0e4aae86d5168f0L, + 0x0a95f53465b6e92L,0x17dcd43684232b0L,0x07cc8a85c2aea36L, + 0x088622b0d788117L,0x00baf9e458fe003L,0x1057d35aeed4083L, + 0x0d2528caa9e67e6L,0x195e4e4f8ae4e49L,0x05606845d84ebcaL, + 0x1e3ac53958a2033L,0x1cf4d8b1cd84802L,0x19863598a01468dL, + 0x1cf5f6941b813f8L,0x03e9e0e857f6748L,0x038d9477762bbebL }, + { 0x142b0cd99726bf8L,0x051dc8e10479e24L,0x039ec1663aa84a4L, + 0x1f44b52251fae52L,0x0037d7dac6a7791L,0x1141bd9699ed926L, + 0x18a83087bfac1c3L,0x04f7ee1b2ddc7b5L,0x143ed8191850760L, + 0x175855426a56bf1L,0x14407fa316dd312L,0x14dd5a4dd7bb78eL, + 0x086b78aa4edbfb2L,0x108acc245d40903L,0x0e9713b252aa3cbL, + 0x052b41a21b3b67dL,0x05ace7fec476318L,0x0394a388d1986c9L } }, + /* 134 */ + { { 0x0e4590432bbd495L,0x1a6e8df2a4b9ffeL,0x18757670fd38cc3L, + 0x10b374e40800d7dL,0x02c2c76840ee607L,0x1f445f60ca7e9faL, + 0x00842839dac4ba7L,0x18e2f9bbbb7d856L,0x0689d436b00811eL, + 0x1535d1b9425f4f2L,0x0e56c801f504529L,0x13e61e23ce89578L, + 0x08e9396402f8cdfL,0x175a3142e2ff5f6L,0x18344de29d45d0fL, + 0x125c7337f0f058dL,0x15f3965e170beb2L,0x0000e1cec2c00feL }, + { 0x0805cb9da4a0912L,0x05bb522085e527aL,0x0e3bb1c7596f49fL, + 0x16902d0935de7b9L,0x08b24635780fbb2L,0x02273477b538135L, + 0x1d2a0558972204bL,0x1c8c49846589af4L,0x081a770374b1631L, + 0x0727bf8edc8be17L,0x1197f47d87b6541L,0x009397bcdc7a3a0L, + 0x01d7131fcfb1048L,0x056d238ab1be706L,0x1a65c988b936f0aL, + 0x0e8a1eea618b959L,0x113a0160dccee28L,0x0489973385dc8d7L } }, + /* 135 */ + { { 0x057efe27996099dL,0x1a26dd037304640L,0x1d0342561622dc8L, + 0x0cf3cb5dd3d6950L,0x108a2fade53daf0L,0x1f383564ab054d4L, + 0x091a9fd2f84c441L,0x1ccdabe7b365060L,0x0a5f8e8da27cca3L, + 0x1a8ee5326147949L,0x08c43bcc77f5e3aL,0x0f845940e7ca99fL, + 0x14a40da68392e0cL,0x1a869c7e08178b4L,0x16b80d45aec1f31L, + 0x193bae07d07c575L,0x0d1ea93c066b4d3L,0x03e8581f2bcca07L }, + { 0x1e7ea304dd94c63L,0x180e2b9c5859d2fL,0x1e328539ad2d5fbL, + 0x1d4a6a64ed2a694L,0x1c22d00607622cdL,0x035904d7b4b503bL, + 0x0ad29ccf06219f5L,0x0992ca99976c4d8L,0x0a098d3a1a84f3cL, + 0x0cb7cf696b9a5baL,0x0c086975547240dL,0x1a5e3d8a247fbfaL, + 0x05b2c1aa39e2ba7L,0x1c759493fcb9349L,0x064a9bf4b9d743bL, + 0x1ca1df574e25c32L,0x060a606b43a9b83L,0x018d8bc17ed5aefL } }, + /* 136 */ + { { 0x18dba454034db92L,0x1bc80c79a6e26c3L,0x1cbb7dd530ce8e5L, + 0x159aac75111a009L,0x1b5ffad1eaa5954L,0x0c5edc514eb644dL, + 0x16d1ea2b7d956c3L,0x0b7eff7085b19b7L,0x1b72e3a0380d320L, + 0x19ad8593e563e54L,0x182f2f62951d770L,0x0e33d749a4bfff8L, + 0x180c50fca6736f7L,0x00600c801ec80e1L,0x007e1347f6b3deeL, + 0x17782eb9ecb1eadL,0x11f57a7e6345cefL,0x037e07df29f03f6L }, + { 0x16d116bb81b0e5fL,0x0e952956429dc24L,0x0b50c9ce1fc360bL, + 0x09752258b26afc4L,0x09d5dcc13e332a8L,0x06c2e9c5b8e321aL, + 0x135383260bba50eL,0x1c72172aa797effL,0x12cb39bbc38fed5L, + 0x1633e4e2d621481L,0x08485efc1f69568L,0x0b5b4173c9ddd7eL, + 0x028ee9e0c655ac0L,0x045db71f885d896L,0x011ba4573cebb95L, + 0x0aa7e95ce4d3916L,0x1c8cb266012aa0eL,0x0380c9ad0d4a647L } }, + /* 137 */ + { { 0x058d41da4626deaL,0x1b3650adc81cfefL,0x0290c593996c97bL, + 0x1ae919f99f33502L,0x0f142fa99fe6daaL,0x038bcb3d5cd35e9L, + 0x08e6e932e85a175L,0x0ec25a6166cd787L,0x01f46a5dc8bf450L, + 0x03472948a10d607L,0x01881966ee8712eL,0x0a5db4d31720f4dL, + 0x14e54537072b4b5L,0x0f480b2fa81cee6L,0x15177f10a81ea7aL, + 0x1d6615071ffe7afL,0x00041991e5a3b5cL,0x0364b0f644b4e53L }, + { 0x03bdc1bc4e7eb46L,0x162abacb63da438L,0x1f359abf5d375aeL, + 0x0acad9cde69f322L,0x124971755635510L,0x17fd969e8fda861L, + 0x08af7f699e0f98fL,0x1ef7af3e3e7ddf5L,0x0a4efbe5417af9eL, + 0x077b2312d2adbd2L,0x1cc8e069c4cc11bL,0x14ff72ac4b4622dL, + 0x1a0b027e96db2a2L,0x041959de3505521L,0x17eab01163f9749L, + 0x0ff34a46831beb5L,0x153c05a89cbc49eL,0x0418441ec34f125L } }, + /* 138 */ + { { 0x19b1c6202557389L,0x0e74bd6f7e05e4aL,0x19fe0cc3ce0d7f9L, + 0x1e2d9f703d12777L,0x104428fd27e0c6aL,0x0f30c137b2732deL, + 0x047294f7a4916deL,0x1261146278290fcL,0x065cec3b9445bceL, + 0x1de018a6b3f6a4fL,0x0dac90c1e08d48cL,0x1b5f275a63a4d3eL, + 0x10c780890cd78e5L,0x0f22f7f4f93415bL,0x12ebfa9c0570d3eL, + 0x198d826ba9749cdL,0x18c43a378a47e3fL,0x011bb7cbfcb31c7L }, + { 0x06e1ec0ae575b99L,0x065a7c0dcb86e05L,0x00934e9ce51df85L, + 0x03f646b53be0147L,0x1bf629440b4b9c8L,0x0b2ebd468a88afaL, + 0x0f8ef3f4d6d0c78L,0x0f6ba25fd4565dcL,0x0629984a6f5182eL, + 0x121f179e1b2e847L,0x09c244c3cdb9c93L,0x1401fa68a803326L, + 0x0ebaf96dce698b4L,0x11b3aaaa11e27e8L,0x0c95e12982e82b8L, + 0x0c942a37b585b60L,0x0968ab4190a2154L,0x046230b30b5f881L } }, + /* 139 */ + { { 0x1fca2582d1f36a5L,0x1695944a62f96f7L,0x16e10f3b613c3b7L, + 0x05b61c77366b4b9L,0x0719a112290f898L,0x11b16b667075780L, + 0x1f91f43995f90e6L,0x028aa2d4abac4d2L,0x0269e1f778e6365L, + 0x11ef6e5ea8134deL,0x108c0110715f157L,0x06398e0aaf1bd9dL, + 0x131e489eabdb83fL,0x1cafe6da0def7dbL,0x076c00482d9e33cL, + 0x059912119f239ffL,0x162cbebc6f455f5L,0x00aaf53115a6308L }, + { 0x0be2f1f876fa42eL,0x143a4bfd6f773caL,0x03d4e32196bead7L, + 0x09bf00b360d25ceL,0x0b5a7ac916e99b8L,0x031e958675b0374L, + 0x026833b48cd5cb5L,0x1be5a1e4c465534L,0x12529998c3861fbL, + 0x08c4453e0df1885L,0x08a714362ab78dcL,0x16f07626a67b362L, + 0x18ff029708dbcf9L,0x0d41f7c41e53a37L,0x0ca111296804e87L, + 0x095751d209a3095L,0x0c32fe84b3dbcbdL,0x047ab879212c82cL } }, + /* 140 */ + { { 0x0b66c8a2ca9c508L,0x0df6134eb5bc06fL,0x099a23ab5800b71L, + 0x0e93ae4c282dac2L,0x0e472e6f61841b9L,0x13d43b20f207366L, + 0x05e82b68909907eL,0x1e88b73fa679873L,0x1b25e8fa97c15dcL, + 0x09267590974b14eL,0x11cb19f6cf65580L,0x1a56f834f088751L, + 0x066dd027ff8e2deL,0x1f3d15e34a5584eL,0x1c31d8fe26815f5L, + 0x0c4255b17e44d9eL,0x01d4cb268e7c8a2L,0x01e8b8f43d96226L }, + { 0x02ac16e8ce49820L,0x122f1606226e49cL,0x0449cfa1631093bL, + 0x188c64f9f21d8cfL,0x06159c1f918cb25L,0x0a2e59a1f1c3b5eL, + 0x0d1fadadb8380ddL,0x082c9707356ba24L,0x172e09274a300d5L, + 0x1559473440e08b4L,0x003fffadd6a10c9L,0x05946b2241be94bL, + 0x103209f4a30a580L,0x073549c03ff7416L,0x1b8472ad46005aeL, + 0x09d8f7338d8e185L,0x00416105af1ab9dL,0x011a74c7c1a66c8L } }, + /* 141 */ + { { 0x143520814db9cdaL,0x1ee23cb56f6487fL,0x09bebd162db6673L, + 0x0ae87d546308755L,0x01735d813f1f741L,0x02caeac8af0c973L, + 0x0f234d10688b42bL,0x06ce0977ecf8089L,0x12f960471be23a2L, + 0x01931c40ae8eaabL,0x008c2ddac776533L,0x073e183914cf282L, + 0x0c833c910df2e54L,0x032dc26fab58a0dL,0x1c0aded19f2667eL, + 0x0d2a03604a3f443L,0x093de5b52609621L,0x035109871e71d0fL }, + { 0x01b67a04b3ca1a7L,0x176a98060674069L,0x0da24cb3c1eabd0L, + 0x02b84b86b44599aL,0x0dd04d0636523a8L,0x1c9d1df66e9cac4L, + 0x0d4c1cf68d40acbL,0x0ee98bc1879abcbL,0x0ef9f5486132687L, + 0x0c3ff7e0f3a1149L,0x0b0a7a89397b7bbL,0x13e067093e34db3L, + 0x1240f2390508abcL,0x1fc9a1a9d84d914L,0x0bad5419e441cb1L, + 0x170e02054c703cdL,0x0303ee0740996feL,0x01a7837d54e2694L } }, + /* 142 */ + { { 0x09dc79f2348f005L,0x02eb8efa49058c3L,0x1f29b7b992926d7L, + 0x09d0549f69fa36aL,0x1957836621b7f73L,0x143ecb31be5c1a5L, + 0x1b2af24d0406df4L,0x1c62b21f1580725L,0x0280dc3737f75f4L, + 0x19b7a87b530d631L,0x160c129955a36a2L,0x0553b2610e14e9eL, + 0x12fc8895cc80d79L,0x048a49cfb68bd8cL,0x0756e79260e4be9L, + 0x1056b5e6c04fba8L,0x11a452d79e25caaL,0x03b26a3d8fa08aeL }, + { 0x1f22303a2ee8b9cL,0x1b969c2efe6a42eL,0x060c4204e8dc6e7L, + 0x167bce83ead6857L,0x1303bb5be28c523L,0x0dfcd7842bb12d7L, + 0x16cd249bca66ab2L,0x01c437d58101a88L,0x06a523a02d6ba2cL, + 0x18150d8bfe71432L,0x1a88d78c0307ab8L,0x06d4f69526228a2L, + 0x08c0cc89f745437L,0x0076c46f69e05cfL,0x0dff1c01206413dL, + 0x12e709e4d36ac79L,0x01009a1d53a321bL,0x00e06ece191851cL } }, + /* 143 */ + { { 0x1aa1f67c46a7d9aL,0x0199a5f6fc8e67fL,0x09d11e90bcb991dL, + 0x02483ff5528b067L,0x135efe6b6798005L,0x059201b84bcd421L, + 0x047717c184fd7c2L,0x1f8d7645f9ac9e4L,0x0e1b8b2a3a0572cL, + 0x0f075a0bca850a5L,0x12eca4fadb35306L,0x164a8e144bffcc6L, + 0x09a3d15a0a31a04L,0x1f97f6f4d20fbd6L,0x0e52803bfb617b2L, + 0x142b83eb03ebf03L,0x1bcaa3996b09ef4L,0x0296c5f1cd83020L }, + { 0x11536f6fd631a2fL,0x173f859a8d46e5eL,0x031e6c49884a47eL, + 0x1e57a1e86ba34b2L,0x12b0ea7052d4875L,0x1d5c4f4d76db69cL, + 0x064b02f42af72e0L,0x1b504f420c513fcL,0x06566a960102a0bL, + 0x104181be701b40aL,0x1b5e7d618e50176L,0x136db7951bf2617L, + 0x06efdaa3f597201L,0x091b5c494490094L,0x1f0b9ceccdee659L, + 0x11b4623a7c71c51L,0x05d70787f41880eL,0x0367fb1b3ed7252L } }, + /* 144 */ + { { 0x13d0433f89a8bb4L,0x02619c9dcc7b8deL,0x1b200d1c28b5085L, + 0x0fcbb4113d056c2L,0x1bf5fda698fcc75L,0x1e9a662a11aa77bL, + 0x174346217094e7aL,0x1945c41650b7d8bL,0x0e71bbbe1782a1bL, + 0x0cef6984dc2a778L,0x1265e6265fe9aa5L,0x1f51b03e788a2e4L, + 0x1760c1115250cf8L,0x167c22f554d1da8L,0x1fb446f26c3bdf7L, + 0x0c10192673c4773L,0x1e7c93e9c5c2825L,0x00e96410bb09f60L }, + { 0x181347d987cfc93L,0x101ddf8c3fc0839L,0x1274494328c411dL, + 0x01760ab7e67f4d7L,0x1a3af87c480091eL,0x02a055defcaf8d1L, + 0x0116f89a1ddc050L,0x05b331bee61affcL,0x0b398135fb723bcL, + 0x01187c60af5f623L,0x1860c17d558702bL,0x1e99b4c148ffc11L, + 0x04e16d4bfc7c0fbL,0x1a30bf490374ae1L,0x1830839d058d255L, + 0x1c56c72e330d295L,0x122fe2693122131L,0x012a4371b0529bbL } }, + /* 145 */ + { { 0x18795ca53572806L,0x04a24b2b4b470b0L,0x125cfecc8ebacb2L, + 0x0c81378fac29385L,0x079121b3fb15de2L,0x0655ddd4866d396L, + 0x10495b4be853881L,0x08f979b4def22c0L,0x025086261b435f9L, + 0x1b4361c61417588L,0x05b58bc69e472f6L,0x1da2c3444cd8a20L, + 0x06271d74a66b1c7L,0x012143d2133c033L,0x193c3ced7ffb686L, + 0x054e997ca07ff77L,0x1f1d7f7f0beb948L,0x03a8d91ac044249L }, + { 0x197b9d6e9c9be68L,0x05ae233e886366aL,0x10f5dd8acbd05e5L, + 0x1543689c235119bL,0x0aa8eca86d94a63L,0x11ec3ffd85dddcdL, + 0x01d77d2c3cb4325L,0x1136ea60c58bb8eL,0x0fed726ac499339L, + 0x0d3031c2bfce66fL,0x10e4a9d7e31d997L,0x1b2abb8ce594443L, + 0x02b66ecc8dcd264L,0x0c522c5d38027f9L,0x0af594fec6aa6b8L, + 0x1bcf9d52c89bf17L,0x075a9378e802ba0L,0x00a266096e51636L } }, + /* 146 */ + { { 0x13a0a1d2989aa3aL,0x19141acf37326acL,0x032f4cb9ccbb60fL, + 0x0a78796493d2716L,0x189ea6acf4c464cL,0x167e194ba852fc7L, + 0x0e02519f96efcd1L,0x0db937f573a6f65L,0x0f8eb74533b339cL, + 0x1f00fdf1dbb36f7L,0x150953bdaba89cfL,0x1be4f7cc3621662L, + 0x01dd818488555c3L,0x1df38a7cb87db6cL,0x063da4f686bce92L, + 0x17072aebe402f3aL,0x151dc08fc6b2465L,0x043a76799b5c254L }, + { 0x04af83ebbb3f6beL,0x07ddc845da11eb1L,0x02eb5e1cd49fd5eL, + 0x114c5c0884ac476L,0x1e236f79c3659bdL,0x1f93531481d8b3fL, + 0x04b3d5690c31b94L,0x056444a8f5c75aeL,0x1b73890d776eb27L, + 0x0da7b859eb146fcL,0x184ec14fab92b25L,0x0271cfe42e9d3e1L, + 0x1998dbae175b4f5L,0x0228c2403aa4167L,0x1fbc570ada6ef79L, + 0x15e329e4f2ca595L,0x14fa0a3ef2bb6bcL,0x018fdc2c0e72631L } }, + /* 147 */ + { { 0x18306d1615cd607L,0x04fd5551961d31cL,0x016ddde44c75a03L, + 0x146ce11601d0f4eL,0x1445297f1031013L,0x13cdab40a7d070cL, + 0x0fb51c31560ea9aL,0x1a60607397e962dL,0x118a7ca8daaaaf8L, + 0x198acf3ae6db452L,0x039ce348e053ebcL,0x0e311a1e9f3fbd4L, + 0x09dcdff032eb352L,0x1ea419c5d85bb30L,0x17541e996ea3aa4L, + 0x0a16830089b04abL,0x054844a223e4a4aL,0x04c1918000c70cfL }, + { 0x0a2102757f3d5a6L,0x12b24374656e694L,0x006c09547cefff3L, + 0x1f26bd7be32b207L,0x0083aa6eb26cc64L,0x1267a0b0308948eL, + 0x0c6d73662299a23L,0x03ab0387ee7baa7L,0x078c804a977fc62L, + 0x0c3a1987d6e517dL,0x02369320f33c08cL,0x143b4f348e0fee0L, + 0x1f4a915eb5c4122L,0x08091b304d47069L,0x1ab4a828b7855f7L, + 0x1650a8bde8764cbL,0x0aad0a22ade188dL,0x0455df1cf491706L } }, + /* 148 */ + { { 0x04469053a2d2f01L,0x018c9aee3342e5aL,0x0efc75d2809f49fL, + 0x1eb6a1d83ad5211L,0x1f3c2e2601da350L,0x1b77490e9eea2f1L, + 0x05e73d9b84742e0L,0x068fc07211e8e97L,0x119e7c5b998b878L, + 0x1a0e9ff5e9e8ef4L,0x1a3a347bd8166e9L,0x12726ce9c48ec78L, + 0x073e7e67f69b9ffL,0x1774f1240ebea9fL,0x0f66131a6370c9aL, + 0x1d14ea5e47db567L,0x095f95e31b06f8fL,0x0078ada6861e85dL }, + { 0x12f6635790a8d85L,0x1fdd7712cad78c7L,0x1b1892d44a1d46fL, + 0x166468e2bba2b6fL,0x0bc5441d7639b6aL,0x082c19866ea94c9L, + 0x18d8152003a93dbL,0x02643dfaea5edadL,0x1c0b7ffe5192906L, + 0x1452c12f7544c66L,0x16ea488a60899adL,0x036177a0d765d9dL, + 0x004bb6b0cb678a9L,0x057c754c5921b6eL,0x0a816ef3dea679fL, + 0x07d63725a1cdce3L,0x1dbbf8d0471f599L,0x028aed9bc101c2eL } }, + /* 149 */ + { { 0x043eaaa6f5bef22L,0x0934c101a438977L,0x0139e8ebdb1a54bL, + 0x0d351928063c989L,0x1001899a18d434cL,0x07520631f2eba0aL, + 0x01c8548e36ef3faL,0x1d194d991a52cf3L,0x073db6aee04acbdL, + 0x1b49946dbfcc9e7L,0x1e6efeb5178cd2fL,0x1926f83e2c6147eL, + 0x1f9b00a6de8c51eL,0x096c15e1a483992L,0x1167f25279ab2d0L, + 0x09c76b20366da1dL,0x002cb09b7109cf3L,0x016f0243f0d5fa6L }, + { 0x0b722f38dd9d484L,0x049c9be3bdd660cL,0x03c64f64ae2a0cdL, + 0x011c7f584ab1b77L,0x145f4a7d80d78d5L,0x1e614ef82804c0bL, + 0x027e341caffb61dL,0x1aecf57f1e58615L,0x092c567ea9a0820L, + 0x12d5897451d2b9cL,0x0bebafc155486d0L,0x1e4d729d4bd382cL, + 0x143d71e546ee1c4L,0x01f45f0e8f20a4cL,0x07ab82c96060ee1L, + 0x094608922f905dfL,0x06e6813a4577387L,0x037b56038e6217cL } }, + /* 150 */ + { { 0x18822ad4dd6e3b1L,0x070e656b10434e9L,0x0114b2b37a03f1eL, + 0x15508d3fc7cf087L,0x067e8ef2121cc14L,0x1a3a2447479ed3fL, + 0x0c7d36e0f45b934L,0x02e7743bb30f30cL,0x1dfab59770a4c4cL, + 0x18509831f6e380fL,0x075805b363fca07L,0x0617798ab7928c9L, + 0x005760412a22672L,0x1947d77b0150ce3L,0x1faab671c6757c4L, + 0x15f6a4f972d3decL,0x0cbf342530e719bL,0x0371612667fad41L }, + { 0x113024badaf8793L,0x1e67881ae4a4731L,0x1ade54d402fe512L, + 0x0c3a22cecbd340cL,0x1fd93c787991a94L,0x172a4acad6ed974L, + 0x1973c174b00dfa4L,0x0e59628b6313e07L,0x181ae48ca95aa1fL, + 0x01f938109ad3727L,0x1bd68926ca9f548L,0x120005afe546579L, + 0x086c6745b00687aL,0x0328398297be991L,0x037163cf6a2a1d6L, + 0x0230b7c7171085dL,0x1916b48bf34dbf1L,0x02d7bfe86cbe047L } }, + /* 151 */ + { { 0x1f9b950f4a224a5L,0x022ba6628139d2aL,0x0cc190fc7f55064L, + 0x161ca1ef0669f02L,0x09581712996801bL,0x048e9b4336ba01cL, + 0x1bf9f6e69017690L,0x0d1e3c6f3be2d48L,0x08d04a93f83bf91L, + 0x126419a995905e5L,0x0cd2c7dca87042bL,0x12efb032bb6933aL, + 0x1ffba14b5d8fbc9L,0x1b6d7a3b65759efL,0x16dcbd183fbc089L, + 0x160c497291bfdb6L,0x0ae5185c925b6dfL,0x013d4e1c0cb04eaL }, + { 0x1c37346f12a93afL,0x1b83e2a9b31a6b9L,0x035526064f440a2L, + 0x19de436d3b1df4bL,0x0788a0e24f83a5cL,0x189e4c02e5d851dL, + 0x1e130040c5e0596L,0x1e5fd441cb056e6L,0x1df9713a0e50361L, + 0x0a24d07e866116cL,0x1d4b9df178b86ccL,0x0d7b6ce0899e306L, + 0x15733e177a6e44dL,0x047716118096ef4L,0x17c6525a2d259a4L, + 0x110dfb3760a823eL,0x04495182c716acdL,0x00e34834a7def49L } }, + /* 152 */ + { { 0x1b67d173a880026L,0x07850092ecaf92eL,0x1544fdb2de92271L, + 0x02b977b94a520a0L,0x172bcbd33eb231dL,0x0ad01d7c67fe4ccL, + 0x1f0bf2d3bd352b5L,0x14b289a8f94450cL,0x196d885480ead1aL, + 0x152be7c65e45822L,0x16112c01795681dL,0x1c323a31412fbfcL, + 0x0852923c745e9e7L,0x1faed99ccabd137L,0x0fb43234219ede5L, + 0x1a4784aa6811cc7L,0x1391596e5d5689aL,0x03dc609eb528261L }, + { 0x1c43aad52fb6901L,0x189fc8b65129d97L,0x0c29456ab718700L, + 0x0cfeaefb8428eb0L,0x1723c0ddc93d192L,0x1cfb6d137297477L, + 0x0ddb4bc783ae0faL,0x07332f3bd05e300L,0x143e28ecbb08349L, + 0x116a8ee51ce1c73L,0x018ea6a38fdad66L,0x1474973664e0dccL, + 0x02d2f8915d4cf1dL,0x08283c893729a45L,0x14e0fe979d78f81L, + 0x1f6535dff9cae41L,0x0d01d6d53cc8fd2L,0x0071e1f7b34b7a6L } }, + /* 153 */ + { { 0x1c337c121ee1d83L,0x047b6bc3dbbc41dL,0x1f304e3e933a5f8L, + 0x0f40691cb17ee13L,0x055e672dbaf7764L,0x0f62ee827c5d5e5L, + 0x048603b4a4675f5L,0x15f19cc97fe67d3L,0x0ac09fc5724b059L, + 0x03418fcee2f195dL,0x0899dd196bdaa54L,0x1ccd92fe3ff04d4L, + 0x16bc6087fd3c5efL,0x15476e358a8af06L,0x1e7b4a6c68e717aL, + 0x111707bb02d761cL,0x11c6cc13769bc37L,0x023184c71e04952L }, + { 0x06408c7c8bd0fa7L,0x12188e735ef249dL,0x0420a0fbdefb45dL, + 0x0f336bb271c62bcL,0x05a49a6b8213cc7L,0x14f268d7bf8ac0aL, + 0x1275b403f6c3f94L,0x0a4aba71eef9ccdL,0x0b4f7ccc01bd4b9L, + 0x0cbada4d7b8fcc3L,0x167f2f3593402a3L,0x0a094b4775ae256L, + 0x042b5c89f11860eL,0x1d1f118fb6cbb02L,0x032ea4bfb431965L, + 0x1c23cb02298662fL,0x05ae2e74c066698L,0x03fc7e849d1a45cL } }, + /* 154 */ + { { 0x04592cac19428afL,0x10e409d184332f9L,0x004b8c2ef5fc64aL, + 0x0706d8d77284b13L,0x198e498710db072L,0x16b7a5ce3d20f4aL, + 0x0b1122bfc5e79baL,0x07ce1f1f372eb0cL,0x06b3b02376f2198L, + 0x0ec1f4dcc7328a9L,0x149aa35d4486289L,0x10353ade3b4c765L, + 0x05a5a81f7495082L,0x12343a38c6fbc68L,0x01f63335e7b9567L, + 0x0d92a40c194aecfL,0x131427a84ffa847L,0x043db2628f321a8L }, + { 0x1f46f654b30d3c4L,0x0262e11da778a43L,0x1d998f2935a337bL, + 0x139e7f6adb676e8L,0x0fd7d46a1df3426L,0x14d45eea789ce20L, + 0x15f4a8edf1f1da9L,0x069dcad6993975bL,0x1b28ff342ac9423L, + 0x0237efd3c378ed1L,0x145272dc0320b80L,0x1f02a12ccb2f9cbL, + 0x09fcff4bddca30eL,0x024929342251030L,0x0087ce03cbd979dL, + 0x177a1cb6caa59a8L,0x0f577ea9c2a042dL,0x0464a933e6ce031L } }, + /* 155 */ + { { 0x055032e5fc1abb1L,0x0d7aa097f23a1b3L,0x1580a7c17bd4885L, + 0x0bb83237d3facaeL,0x008639b0b0e7332L,0x1f3339bd59e32f6L, + 0x155559d41fd4470L,0x15ac717df8790c2L,0x15d0188cf42f0c4L, + 0x01d180e6c4b0c36L,0x180fdecb19d07a1L,0x1819f479a3a008aL, + 0x1d4a40672ef7545L,0x02dcf46efb0957fL,0x048b5d15865f27dL, + 0x0b37f68a646fb0fL,0x016bf132e3a4b2dL,0x0457d0db9dc2535L }, + { 0x13596eae793ac70L,0x077c7777b6e8835L,0x1e89c108b901325L, + 0x1dd3cbaec724d69L,0x1512aadfc8c71dcL,0x01cbaf9a97e5b87L, + 0x0ec4c6dee84e2a2L,0x1a2af3227200b18L,0x19692092a97740fL, + 0x0d6ca2d8b05834bL,0x0d0e20420deac86L,0x0389e2e976e378cL, + 0x01ab1b80eb76ee1L,0x187622c53088dfeL,0x0b4cc96f20aeb21L, + 0x15b91ddcc024e62L,0x13cb4118b1ab240L,0x0339088c895ad04L } }, + /* 156 */ + { { 0x1e99306f55cf9bfL,0x029845235cb6cc8L,0x187679e9977e6c1L, + 0x038e6379775c783L,0x04d58a61453cb15L,0x03a6610a5f2913dL, + 0x00358e76b248a5fL,0x1be9a1ef48b045cL,0x1afeb1d51c62b03L, + 0x18ee1d25d50c596L,0x11c5e37cadd3c2eL,0x114d12d6d466fe7L, + 0x141dce055ffcd32L,0x152715c3f4af6a2L,0x16773a65fef1dadL, + 0x0cf83cbd8cfe3f4L,0x1fe052368accc03L,0x03e431c8b2a7251L }, + { 0x1e94b5eca7388cfL,0x005306019ae9c2aL,0x1e2d85be16e85f3L, + 0x1e2024530136d36L,0x1cfd0a79705d02eL,0x0f71a92b2d37400L, + 0x076b7add2a5b5f4L,0x01eb91065da84f7L,0x096ea8528e6d533L, + 0x06c43158c692774L,0x0e3b567fe4e7dccL,0x1344020c04a539aL, + 0x182303b3ff690fcL,0x0ea95a34e316c45L,0x0b4b64ff10b5e93L, + 0x008700df1bf4519L,0x1ad502360906092L,0x0192c13ac7e742aL } }, + /* 157 */ + { { 0x120e45f359e8c60L,0x1dc529b2650c375L,0x01c77fe384431c6L, + 0x069927caf00562aL,0x1829d0d8074e91dL,0x1541fd601937005L, + 0x08278f064896189L,0x10470f4c9abf653L,0x1caaa3d34e5ac5cL, + 0x16b42f2d6d16d14L,0x08099faca5943a3L,0x1632ec7005e724eL, + 0x0edf6b1aeaf7184L,0x12f3092e91faee8L,0x01ca86af87e8d1cL, + 0x1875fac50ff3a19L,0x05649aa93d2ac57L,0x00d273538aded3bL }, + { 0x0126ede554d1267L,0x0a2998e6815a40dL,0x013338c7ec74dfeL, + 0x1612fb8025ae15eL,0x16c7b6c5cf410b0L,0x048842c9870e8b9L, + 0x18e3e40bfb9071aL,0x1be6937494ef3f6L,0x0a16c5821acd6f8L, + 0x19dc1e09703b567L,0x140cef94074537eL,0x08a441e5a5b4d71L, + 0x0d99df18800593dL,0x0ff599d31ba9293L,0x1bbd15b28c8d472L, + 0x1b915b22687783eL,0x032c74857db35b9L,0x042b53e49c2da74L } }, + /* 158 */ + { { 0x007d0020d0a5583L,0x180eef6d232c550L,0x0590d364e6f8bc4L, + 0x014e18106d2380fL,0x1e81e540a0cb678L,0x05645c605a6fcadL, + 0x188e5b2ef34d175L,0x16caf8a5da0a8eaL,0x1cac2dca41805ceL, + 0x0af7355bc9a212aL,0x17bcc493268a9a4L,0x0c5f18258ce86cdL, + 0x1b7dbb7c3bbd3b9L,0x1115dcadd55b278L,0x118edd0f039154fL, + 0x14c624811fd7589L,0x0403ca773122a4dL,0x031444842631b6dL }, + { 0x057fd538cb8d208L,0x1c004aa1f836a52L,0x0553cbbfcaadea3L, + 0x17ee4a2fcf6cdbcL,0x19389d2cfddb28eL,0x0dc46700a4ff337L, + 0x10fdde7a1dcff61L,0x1808a5c1216174aL,0x1deb9b5cfb0b03fL, + 0x089a245362f6bbdL,0x07cf3e3ff00dc8cL,0x08dab83698946c1L, + 0x138fa59be92bc9cL,0x06d81348f3379dfL,0x07e23e44e5afd7fL, + 0x1bfc7e3d8b3a801L,0x158c29034562ad9L,0x03cec09162d6d26L } }, + /* 159 */ + { { 0x0d4e4ceaa529507L,0x1040a3a32ae800aL,0x08e13c3f11d015aL, + 0x146887971d81a61L,0x17f1728d8a8203eL,0x1077a919e317d84L, + 0x074fa28e373f6d4L,0x0a141f21abaf959L,0x128a7b0bf873ceaL, + 0x08ad71d363620e5L,0x05c76a84e04b074L,0x174ac49aa0fd46aL, + 0x097e98f42f25d4bL,0x0b5209b8c8ed694L,0x0796ddfff5ac7a6L, + 0x1ee0fa8d8424b6dL,0x17ac7d2b42420c4L,0x01559d7cac0a12aL }, + { 0x0ca074c6a5372a6L,0x1dc1f2b1495d3c3L,0x1b71ddd073d5ca3L, + 0x02a41de93ae8ab2L,0x01e4647270b4ceaL,0x1c562e8a397f1a3L, + 0x101c7d35af598feL,0x0c28dca59938217L,0x128794efe371a34L, + 0x042838c13b7f43bL,0x155dce6fbd6ad29L,0x13fe7e2b902bdb5L, + 0x058f8395c324c2dL,0x005b542a8c44a87L,0x0200f86eb90265aL, + 0x04bdc9ea7c45915L,0x1caaf233f61039dL,0x003ed961a928204L } }, + /* 160 */ + { { 0x1f3b8db037d4703L,0x1846fe2fa445ce3L,0x0c3e11c7500ba0dL, + 0x04b45f55d23f750L,0x1404fc1ea55ee8dL,0x16ab28e172df882L, + 0x1d7e591f5409ea8L,0x17e6f4a7818fd75L,0x07adf0bb295b30aL, + 0x13170ff6b2649ddL,0x1063038bbd29e16L,0x13b29a59a09efffL, + 0x175ea0af02139ddL,0x07f7cd67929fdd5L,0x1856a9df20403a8L, + 0x040d2e98a709b90L,0x159cb28682d9fe5L,0x0045b6547e7beebL }, + { 0x04e5bea036c3b5aL,0x130813fcf95a5f0L,0x15c0a5e5f03ce1cL, + 0x17050f3d4753f94L,0x007f0ddf1656180L,0x1870438a99c4ddbL, + 0x1ff1e668488f19eL,0x0321a3011d93b12L,0x09470711a916edfL, + 0x07a97958390b88cL,0x0ca7ff462222dbeL,0x058a998df200bb1L, + 0x05eb24877fef1e2L,0x1aa3ca92e201b0bL,0x1851a2bf6a548ccL, + 0x17411ac454842d0L,0x1d25d043b0774faL,0x01619bd810698d3L } }, + /* 161 */ + { { 0x12305bcea22fa65L,0x01f7a68acfb1d3dL,0x01f4fcd648fef86L, + 0x0d823aeea668e7bL,0x0a054cffb27fb30L,0x0c2b0cb8173f359L, + 0x14714f3a7e5f2bcL,0x0b706aa04869cfaL,0x1a63e3d82f356acL, + 0x13dbe556bb22898L,0x179abe99c7f2761L,0x1dbc560f9aefdd0L, + 0x10ffda51933b985L,0x14a16e1b03eacc5L,0x18862a6c43b28e6L, + 0x1ab942fe7b9dca0L,0x1c93d94e8d106b7L,0x0284d931a76c418L }, + { 0x1b9414e48caed54L,0x1c63665fa8f4bd8L,0x123537a6c961de9L, + 0x1923dc7af148d11L,0x030ee64c0024137L,0x0c86bc5347c91a7L, + 0x1a42d5cc956f220L,0x09883d1c0bf7500L,0x050038d84ec354fL, + 0x0c7816b6fd2940bL,0x1e401f32d8ff6acL,0x01f7d315c8ab88fL, + 0x025d0e319d29d48L,0x0136db8ca5622e9L,0x0d61ee741bcd5d4L, + 0x0ee4ee6773c4058L,0x152224839922c31L,0x00ac96ad3aa5dc3L } }, + /* 162 */ + { { 0x178d9a2cf7453f0L,0x1c4cd76c1e0f82bL,0x1b4f82a0ae9ebfeL, + 0x15d47aa1035cca0L,0x010aa38b32c84e1L,0x1be820cd6a94604L, + 0x1907ec7f6c082f4L,0x1ecf1ad97c3a0d9L,0x0d287f0f02e74b7L, + 0x0e692bae21dd811L,0x03cbcfe069c6cfdL,0x03eb8c67cfe8da5L, + 0x1cc4fc580ee65bbL,0x1dbd83d29972fe0L,0x12abceb35554e7eL, + 0x05a5b6b5288e387L,0x17cb958bdf44cc2L,0x00b0a5edebbd13bL }, + { 0x01f0230ed0ab04dL,0x03d803710417526L,0x118f10b16d7eb8dL, + 0x1fbc03326b3e217L,0x05dd0825b0539e6L,0x076d0b6c4dea73bL, + 0x128ca48983fbeefL,0x0bf1554eab9cc55L,0x0ed762fa95ec82cL, + 0x0f326008c3283b4L,0x15891724b8d2326L,0x14ee63d4dad0afbL, + 0x0b07b447360db88L,0x0b8eb87f7780095L,0x1e246c2e4d5ae50L, + 0x04145cd160c5007L,0x1283a54a53ab79cL,0x0244b2b63d80583L } }, + /* 163 */ + { { 0x03649ba71353c25L,0x193d089fb3f1272L,0x0ce8707ae78d45fL, + 0x18f1c537f2217a6L,0x0743f15d94e1c05L,0x0d16f8427f3ecbaL, + 0x0ef86721d242243L,0x16304807f4ea6ceL,0x17ebf5db41baea1L, + 0x1f0571a920c0756L,0x161cff0bd430ff3L,0x15ace0cc39b23a2L, + 0x19a51e8c2c16851L,0x100b084cc014b46L,0x09fa95b9f46a737L, + 0x18930562a791351L,0x1cb6d41b78906e3L,0x00415d974eb3b4eL }, + { 0x180ef46c4d6615fL,0x14ee080dcc14e30L,0x1b003ec9932bf18L, + 0x0c21d98589bc445L,0x1eea2c4dc5457e0L,0x0e2d964ae72ccf8L, + 0x043e410cfe9ca3eL,0x0a7dc06a8c59ac6L,0x084c57c3bce2e22L, + 0x047618d4b6c3f22L,0x1f8e4e914b169dbL,0x0281408f646a617L, + 0x18c018545ec592bL,0x0e0bc6233dec5f0L,0x08c016de538041dL, + 0x0a9e6908e328c5cL,0x0422665e237622aL,0x01b228d23480e48L } }, + /* 164 */ + { { 0x1802d1819893e71L,0x12ec5a9cd10410bL,0x08048c0bb3f285dL, + 0x166cb7eb3bf8d5dL,0x0d232a808d4cf51L,0x140213c3ba0eb90L, + 0x0e7b2b0d0facc63L,0x194aa7d965fce8eL,0x0aeca79a81a8b07L, + 0x04ff9912b7a559dL,0x175ca4fe8747dc2L,0x135dec55342cbd2L, + 0x12aa08ddc226056L,0x0dbddaa52f3bb11L,0x0f55b9e4feafb0cL, + 0x17dfe914412ace8L,0x0f1749cdb12eb0eL,0x0382983d234dc7eL }, + { 0x08e4c04e488310bL,0x137192992e6bdbdL,0x02c1260fbeb049cL, + 0x1805bb7226ba1fbL,0x17b9685c796e552L,0x0f9251877651fbbL, + 0x125e66dd9ba26c5L,0x0d8f84e6dac91dfL,0x03d619685a8021cL, + 0x119f13c505978f5L,0x1a61e6d9db5ac3fL,0x063235e9c17d2b8L, + 0x1136c4ee55a0747L,0x0cf2f9dcd17d5afL,0x12bf9b9a4e2e3fdL, + 0x1a2403c229b4873L,0x0ecc9595ec36a6aL,0x0407bcde82bf315L } }, + /* 165 */ + { { 0x0ef42a760af09b3L,0x0b75ec99eff0a1eL,0x0783b617aaa0f00L, + 0x1f9d547792e419eL,0x17106f97d4f5e99L,0x134569390b5ce95L, + 0x1947d97cd30db25L,0x1bd51f70578b618L,0x020f42f1cf2fda4L, + 0x198d596690fb2cfL,0x1ddb1e84f45863aL,0x004470cc57cb6f4L, + 0x10cad08e0bec441L,0x011600c06412ed3L,0x1be7ff664a641e4L, + 0x116a0ec477b4055L,0x119de84f4f3f5c5L,0x02fad2ed26c127fL }, + { 0x137257e7e8311dcL,0x0a7a8a336789b2bL,0x1916c172886b7beL, + 0x1805c9566f4e7c2L,0x0579165b38ea9b3L,0x0580d23bb07564cL, + 0x156137ff7411f09L,0x1b4311a9fa27f72L,0x0faac38b825548bL, + 0x13cd3782cf4ee56L,0x1dc83c2689c03c6L,0x0aa9f714fc91307L, + 0x0847a1fad58cbbaL,0x0d5eb5af1c50ccbL,0x1c5bb084615951dL, + 0x120f6ea227a63e6L,0x0891391e7814212L,0x0298ce40086e0acL } }, + /* 166 */ + { { 0x120136e6b61c3afL,0x0796f03da5db411L,0x19fce0325fc0750L, + 0x00d5186274ca3bdL,0x0011ca10a978ba7L,0x0fa22d9162c3eb1L, + 0x1139922ee8862acL,0x1f318bd5e0fca08L,0x15549f02a442fccL, + 0x0b23a379ec0249eL,0x093d85e70116449L,0x143157b9110e85aL, + 0x0aded38f8f1600fL,0x091d75a32e5c300L,0x0715e2a92fe6e42L, + 0x1d429ac7fdc6a3cL,0x1f0f3c9c5acebb9L,0x01e8998a6f88d27L }, + { 0x1cc662db4513d1eL,0x05462eaaca95ef2L,0x08ff9fe1b42b79eL, + 0x08f409e18bd146fL,0x0e25d06cca2d12aL,0x09b038a6334b721L, + 0x1872d49851a62c8L,0x0bde9a4e03713edL,0x1aafd617780efd9L, + 0x16b9d6262ddb483L,0x01d2b10836cd6b9L,0x1bc9e4ea3f4093dL, + 0x16a1fa2edd11631L,0x1bfebca6d94fb99L,0x0be4a993101a192L, + 0x198ece79643a7c4L,0x0adeae904e62043L,0x033f9454fd99163L } }, + /* 167 */ + { { 0x017b258ca148ab5L,0x0cbb7d9e30028beL,0x1a6323ca37e6e68L, + 0x09d1a8a02fd44c0L,0x0578a42287b2cc7L,0x1f63991b92b9948L, + 0x0ef120757b8945eL,0x1fdae823f9e3a91L,0x146217e6b487f5cL, + 0x1803d62a0f5c70dL,0x115e9b816803232L,0x1a57a5f3f533883L, + 0x1b40941cad1f954L,0x1c14a84e9b85eaeL,0x1b297bb921e1e70L, + 0x1f73c9826eaa4b9L,0x1b2e8ef7fa4fd3eL,0x02ff848ba0de8deL }, + { 0x11912a4579c6632L,0x0d227dc51040abcL,0x0e114d58e74eec6L, + 0x177879379de9f2fL,0x119e6410e57e2bcL,0x0becd689159f95fL, + 0x1fd987c0627684dL,0x098ceaae776f3cbL,0x1444e5c98ef2f3cL, + 0x17b0f1002688398L,0x08d9beb1d758d75L,0x190c590a9e461bfL, + 0x1e0ad0850b9fc47L,0x17b906196025721L,0x14ef27573a53d90L, + 0x074c6cfdf5ccb4eL,0x046c27d30d3b037L,0x03340809d14b90bL } }, + /* 168 */ + { { 0x185d913e84509dfL,0x05f6ee799c9bb09L,0x174cd08e8523a5eL, + 0x07dd196af25be84L,0x11c4553c43fa0aeL,0x1f8ea4780a9b4e9L, + 0x09128173c22ef7eL,0x0675bfe97cd2888L,0x001635f81a35ddaL, + 0x02e44a4f3b7d5beL,0x1ff37859cdde0c2L,0x0a5944a9f1a497aL, + 0x06413ec985fd8cbL,0x1d481366310b453L,0x18786dfcb6e5d05L, + 0x1ffbc72c5dcaca1L,0x11fbee0a346d3beL,0x01d9adb9785efd5L }, + { 0x1f8de9f535c3749L,0x0f907c56ece245fL,0x0def23e3d98c8f0L, + 0x0bd1e75c9352eb6L,0x1d5e26282529e47L,0x03178ee197886a8L, + 0x0f8d96b034a5d9eL,0x0c4278f26710a99L,0x148f004ef4b67e4L, + 0x11bd0a872e88770L,0x11de374a0a2283eL,0x14cd9f6e7e9a92eL, + 0x130780495296830L,0x0bb05b4a4fa2200L,0x0dd726608cf1c26L, + 0x1f3390681994a4bL,0x0853f62e40bc771L,0x023e850f5e6cae3L } }, + /* 169 */ + { { 0x06f4fff652811f1L,0x05549b177980113L,0x0955432e832baabL, + 0x1400fea8ced870fL,0x002f2673a350142L,0x0e3732e3fe88151L, + 0x18f6576bb95c0cfL,0x03cc0d05d860c94L,0x146cf0bb0462b25L, + 0x1018652aed49b73L,0x0983c90d0996d43L,0x0576d369d1eb90fL, + 0x0c7ad7770a9637bL,0x169d0ad3300fdacL,0x057a5847c851fdbL, + 0x0742c0b68fabc53L,0x05ccb0ca9b38321L,0x047a5b0a524cad4L }, + { 0x0a8ec194b4eb3c1L,0x04d6210191d382dL,0x0c893db31aaa315L, + 0x168bf34b4601a92L,0x0897abbb0e53b9bL,0x166be8723778880L, + 0x0d623fa1cf95f5eL,0x1a2f9f99fca1ef9L,0x00ea53d65c85557L, + 0x0ecf5a239447971L,0x17b7eb03ada2a3fL,0x08e010c07419565L, + 0x0900feb06c58221L,0x12f2e55634a3234L,0x1246ba60133d6fcL, + 0x0bd5db0ab30b13fL,0x001ed9378b173c4L,0x047ca168129264cL } }, + /* 170 */ + { { 0x11ec3028e845808L,0x15ffd5bbd5fe28fL,0x12e7e365f71f0c0L, + 0x087558b2964d5faL,0x074d94dc3d3a83cL,0x12c88e71dba5e8bL, + 0x0b3491192dcdf2aL,0x1fcc524aee70e38L,0x1419f24853b4440L, + 0x0d35079f02956beL,0x0a035a11b21b037L,0x13f5f0649e84c8aL, + 0x0807cf117aa2568L,0x06ee4edbe3a568fL,0x1bf2175589b7a82L, + 0x1d6a6a4c406e72cL,0x0cbe0ad57c3f3b1L,0x01c1801294a4e0dL }, + { 0x0ef5a405e744723L,0x1e7ba8d704240d0L,0x0333fb07ddbf6d6L, + 0x03f566ff8d57f5bL,0x08fedb78fba5d83L,0x09f9885f1cf1246L, + 0x17092973eb57eb6L,0x1eae8ffb63d227aL,0x1052a47c94518b7L, + 0x11046b63e7da193L,0x172e71c394e2fa7L,0x0eb2b762f22d626L, + 0x005b3106c736352L,0x0104dd8351603c4L,0x11412b74b50a81bL, + 0x1c0696a4b68e3a7L,0x1a5c9f4b368822cL,0x00af8c3cb75a0c2L } }, + /* 171 */ + { { 0x14dea060aee4684L,0x10f833e6dede404L,0x0526c64c4c650acL, + 0x03034fb74d4873cL,0x1c2ae80fea4bdd4L,0x011ee163109b831L, + 0x046c6d62c259c4aL,0x108e887aa2b064cL,0x02e16f83113c203L, + 0x071026b15ecc969L,0x16f35bd064e22c3L,0x1a3a3a6ef18e933L, + 0x0fc5ddae73492deL,0x0ca5b12cceadebaL,0x01b29a35204f54aL, + 0x18558323b39ec1dL,0x038562179eaf3e9L,0x030a378f9cff709L }, + { 0x106d33e078e2aa6L,0x17bfbcef74932deL,0x1e076a903a11a4eL, + 0x11373480fdaadc1L,0x0de9951905fbbb8L,0x16dd1cee7a256e7L, + 0x1dd2dfdc7e34c24L,0x1d6ceb6bb4a8462L,0x07456a251a5f605L, + 0x018ea57c3d1cd4fL,0x0c001816d1d2f64L,0x17e56ccb5523b68L, + 0x156631eeb4bda5dL,0x111bbe2c2e8d1efL,0x1742ffc0a0527bdL, + 0x0cbbc5c35e9d2d0L,0x050e0ea087582a4L,0x04aaa1fcf035e80L } }, + /* 172 */ + { { 0x1cbc6f485d7c6efL,0x00426b1d8de127bL,0x1a22fe32e98b2b6L, + 0x0d68ab8325bf219L,0x174fc6ed98e4b68L,0x11003bb0a35c6abL, + 0x094a5c388e279ebL,0x1eaa48388f2c384L,0x17d2215103884e5L, + 0x16906710bf14139L,0x067d453c99d3e35L,0x00aae18023b7c62L, + 0x19fcfb760e85459L,0x0f46150cefd5baeL,0x1f52c9e5518d8aaL, + 0x0d31896da7f1494L,0x0ffa5c87104ee5dL,0x036da1a3c15d14bL }, + { 0x04864935c3f0d95L,0x1edc1273a444a83L,0x1d89acbcf912245L, + 0x0856feae97ee7fbL,0x0f732723c60edc5L,0x1688a65f0e04d15L, + 0x0bfe5f4d19a75f2L,0x0392c8cc0146435L,0x0b94e2bbaed0cd6L, + 0x1370d20ef623a87L,0x1a6436c6a27d621L,0x1ad9e4eb2d27437L, + 0x00c0e0dddfc39e4L,0x0cce452088e7dbcL,0x070c143c2bf35ffL, + 0x18dc99d7ff5b6dcL,0x0944f3981b096d2L,0x003d3c8f395713dL } }, + /* 173 */ + { { 0x10e90471e9f0300L,0x09d6cde66fc8273L,0x0277fc14c1e3809L, + 0x1d5d1268c4a3805L,0x04846845f1ef092L,0x0d6a5a1648548d5L, + 0x19ec8651bb683c7L,0x029e0eca1e667beL,0x1c6e988db0b15a0L, + 0x17063375aa1787cL,0x0d8c478300de3dcL,0x1b555d0d2a1aba9L, + 0x0db35f1c8f548baL,0x0a268d6a3400b1cL,0x11c74c84a78c85aL, + 0x09bbd32a3759080L,0x0ac03cc29f385e9L,0x036b5661722a1f6L }, + { 0x1999e9557b2d299L,0x1e6cdf1eb90e6f5L,0x013eed32d110e8aL, + 0x13b80c1f545cc07L,0x0c987cdeae17770L,0x1b7df6ba787369cL, + 0x1effe688df3e041L,0x108d35e2a26f307L,0x06c3f7a1d323f95L, + 0x110e567b6db21ccL,0x004d3e59c0f648fL,0x131f70727eecf9bL, + 0x1c2e82522207558L,0x1c92553e0dad945L,0x109ea2ade1e6705L, + 0x129243b66f1e502L,0x0eed5a451b1ff28L,0x03ce8c1091e9e23L } }, + /* 174 */ + { { 0x03edff9109d5589L,0x0975a014da24c8dL,0x14c2d2d52b7f7b5L, + 0x0344f7fece27d73L,0x07f0f4604f9214cL,0x1287142640bf73bL, + 0x188deeb7e360f0eL,0x1838bb807932804L,0x15f29581b966647L, + 0x05b5044c50343f9L,0x01f3b0c58d145c4L,0x174ac5cea3115cfL, + 0x0745e2c3fb2001dL,0x1b3e99caaaea70dL,0x1a10bbaff2b37aeL, + 0x0b01743415f3978L,0x1c850590a2b3e88L,0x039882248d3c266L }, + { 0x0ca2cdf2648d676L,0x0f652a78d8958a2L,0x1250a60387ae6a1L, + 0x1235915512373b5L,0x0719e195f30d370L,0x181bcbb983955beL, + 0x19fdae9463208bdL,0x04f58121c295800L,0x10e6cfc708dcd29L, + 0x1ac44f110f3ed31L,0x0a902e0dc71f193L,0x17c51ef0f193695L, + 0x0bd84caf3f1f9daL,0x0f070ec97bc576bL,0x0909370f0e7741eL, + 0x00132d017cbf624L,0x14ff41b214d0bdcL,0x03547c7e4a8c062L } }, + /* 175 */ + { { 0x0a1ed6353235132L,0x119f8acedd445b1L,0x1148a47bf76076cL, + 0x0f64a2235d0ac4aL,0x1d701bd8c750529L,0x1a7a2edac90d7c8L, + 0x1cffed34175ca5dL,0x070dc7a98bde31cL,0x0897d985f899b30L, + 0x14e187de44d8aacL,0x0b468d344c60722L,0x0d744446641c792L, + 0x0201ceed02292e8L,0x0c1f984fe7922a6L,0x03f468c9e917dd1L, + 0x0ea70eb4c20595aL,0x1d7db4f45d2cb9cL,0x023a96c60ed941fL }, + { 0x14d6cead5dff4d5L,0x0afeda2d413fa28L,0x18313f1c4d79d33L, + 0x1037caef1c20e14L,0x18dc6b08dec0bb7L,0x1e124b138f0966aL, + 0x062b2dd94226d52L,0x064dbbe58c6c321L,0x1fd6ebac6675288L, + 0x1516812e1284578L,0x0b36a1373f07c3aL,0x0d508aa217c0278L, + 0x0d1a8868011c783L,0x17d792a29c82344L,0x0c2a23590c4caaaL, + 0x168e092d0aaee50L,0x152569491ca8744L,0x01d328c79bafdc2L } }, + /* 176 */ + { { 0x0a8ed50224042a0L,0x071d8122978f355L,0x1d31da084761b2dL, + 0x13de9aba7fdb94bL,0x122d46e54e0fe3fL,0x0233ba99d471522L, + 0x1406d6663887fc5L,0x072292d8a1deb25L,0x069104c2f83a677L, + 0x03385e5a395df80L,0x020ec940c5def4aL,0x180afa4e25451d5L, + 0x17b439c994c5d8bL,0x0e6d0d7fa0f7c98L,0x0e3dbee60074ea3L, + 0x1f041ad0ddd6ae0L,0x017e80c5cd0fbfbL,0x02a0561b1f6e12cL }, + { 0x11969a9fe7f43dfL,0x09c04160dcf2653L,0x1f621670a45f999L, + 0x0b2d5488095b2ceL,0x1f1297dabaca954L,0x1753ef074ec2affL, + 0x0fe387d8625ec8aL,0x1bf2ddb99fa6de2L,0x0627d307016e200L, + 0x14f839b64c4c452L,0x0979825fc8c749cL,0x0437ec090ea52bcL, + 0x094019b299af7f2L,0x135a58eceb34130L,0x1375e8c76677824L, + 0x02bd3d88f9ecc35L,0x14f4de9f2b36ebeL,0x00bed99767d0b4bL } }, + /* 177 */ + { { 0x1ef69196cf40599L,0x086fd806010753aL,0x19eff2abd9e5fa8L, + 0x0711bbacf07b4b5L,0x055bcfcd0d663caL,0x025e3f2d10fc7f1L, + 0x018cba70fd4e38dL,0x09a6bec563aa91cL,0x1654f242543c6e6L, + 0x1aad3d3134c9b13L,0x1f17dec3d04c931L,0x1ef2744301e7476L, + 0x111e81675b05697L,0x129a147ab67c2fdL,0x14a2c09b4f36cd7L, + 0x1f6f1c7542b22a5L,0x05da8470255f7a3L,0x02305e80dd0ca22L }, + { 0x034dc23c24d8077L,0x05ac0263906965eL,0x0445bd747ffa0bdL, + 0x0124f079c5453b5L,0x15904af3578af52L,0x1508c8714fa8d5dL, + 0x177c11b15c35fdeL,0x0a294a45f74ae37L,0x1bf4e2a06ae89bbL, + 0x0cd9ae62cf9a226L,0x0a0d9c9b30955deL,0x130b5f9d82ef860L, + 0x0b7c36cbd094a4eL,0x1ae9c83bd6d7beeL,0x0f892f3b4c6de1dL, + 0x08436a5ad209e5aL,0x18dc5ca26691f95L,0x03e9a161e0b9a43L } }, + /* 178 */ + { { 0x1cf2c0a11fd127fL,0x1b5dc08cf262f72L,0x0949bbd5ab0d9b4L, + 0x1dca860ceac4356L,0x0c3e961930cfeaeL,0x1e7338976f13e95L, + 0x130f5904d44ebe3L,0x130c2b38c360ebeL,0x1d447efe959069dL, + 0x1c6b7b4753b5754L,0x17186c3d6f4592bL,0x08dc3d11773158bL, + 0x161ba92320dbab4L,0x1c4c4c32b0c5c58L,0x02dfa0a83abecf1L, + 0x0c17618f5798581L,0x1a710f09b6e20d1L,0x02df057d3472631L }, + { 0x0ab6d381bbbf49cL,0x0e724c60381ff41L,0x0d77843d098cf82L, + 0x03b4b48a65d94b1L,0x1618f7b7d9cc658L,0x07bff383f0c43b7L, + 0x01af81066978c94L,0x0d376353d21bcd7L,0x0584a7deb373591L, + 0x0759a44a8a4ed96L,0x11a8cec3aeaee0eL,0x016185f1152428aL, + 0x070a2db0190067fL,0x031f379f5ef06ffL,0x081beb6e946c1b3L, + 0x1b81543224f73d2L,0x0aee4eb5e87fe80L,0x00f37e67aea6f18L } }, + /* 179 */ + { { 0x17dff66aa8ac924L,0x0d698e14c59f45aL,0x0ca597ec20301baL, + 0x1a3b2b927fa281cL,0x0a180caa7dab211L,0x06f6b4b6b46c214L, + 0x1187c6a4a502288L,0x065502a2ea671beL,0x1ff5604ae60eae9L, + 0x00dcf24bed72605L,0x0ea5ff7898ba264L,0x1349e21093068aeL, + 0x0f64724f1ded69dL,0x1542d0afc7fd011L,0x114de5357c70b93L, + 0x00fba98c4d9d202L,0x03780440cd6bf09L,0x022916a30aeed54L }, + { 0x095f079ebfbe7c5L,0x10ef6c2779a2344L,0x1adb5286ae58c3aL, + 0x04a14618d0e2d53L,0x0043bbaa1a4a5d2L,0x0872faad0b318e0L, + 0x0155af441d40940L,0x0337ffc7d3a7b18L,0x131b30b18077724L, + 0x07fbf78425c114bL,0x0df5d7c868630e4L,0x0c6aacb771f0018L, + 0x0a45e3bceb18d0aL,0x11f85846dd60ed1L,0x0f16b1470e3a430L, + 0x03f8de3743544bfL,0x0ba09d5256bdda7L,0x01a3280d4b6bf20L } }, + /* 180 */ + { { 0x0be448ccc2b0f1dL,0x1a2e4d6261b81c3L,0x19767f25aeff8faL, + 0x12b5c4ffb4a70feL,0x1bc18089cef3c4eL,0x050c50d0047bbb0L, + 0x0cdc7cdd282108bL,0x0a9dd105084a76eL,0x1cb6fc6d87cc093L, + 0x044f60db0a4b6b5L,0x10a6e5278c97121L,0x14a4f7bd82cd525L, + 0x0edcea281315c6cL,0x1d108aa7caa2277L,0x041873cd1a0faccL, + 0x081771f64df31a7L,0x16dc3b08aa806c9L,0x03e0ea167f2aa64L }, + { 0x06e703fdc110aa7L,0x1bcebf9b171bc3bL,0x1d756ab728f2adeL, + 0x12c17c66e7a4b38L,0x06c4e8ff2a6eca7L,0x1b82dffa3a25258L, + 0x12d4eca10b33bceL,0x1703475eb555c60L,0x17bbfa2011b2d31L, + 0x05d375d25f7446cL,0x1597395972e0e71L,0x0d2db5efd9d05a6L, + 0x07e695974524808L,0x14a7cc1b963e667L,0x0468c9bbf5bacf3L, + 0x1274c1467699e70L,0x19014203f43fffaL,0x0018f4c1439e18eL } }, + /* 181 */ + { { 0x1efecfc765a17ffL,0x19c4468948532a7L,0x111a4e3680e2827L, + 0x1b42d35a8d7e4cbL,0x03a62fe84bb6145L,0x04305299e7c10a1L, + 0x0e31158b7d5c6afL,0x0eb7e5521f502b8L,0x145ba1d6e17eda8L, + 0x0cec40d4a37d2f0L,0x0f9e12e43d68edeL,0x06f9621fea54d83L, + 0x04a4f4fd360910aL,0x07169dd061c60ffL,0x1e9861f0c603f16L, + 0x06b847c5fe0a162L,0x11c3a00059b943aL,0x024a69b22d14662L }, + { 0x18426b64ba021f8L,0x04841bcb6f5b61cL,0x0e55f8db1d8b453L, + 0x14ea39e42cda5caL,0x19b24a198f556ecL,0x1061576d650f000L, + 0x09ccd1e21f6912cL,0x1af27da999bfe83L,0x18d717c445c7c0cL, + 0x02431a548dfb804L,0x051be4ed66eebf3L,0x1673cac49e2b43eL, + 0x0d303f8443dd38bL,0x05f8827e4b6a0d5L,0x1c19609ad9c3c0dL, + 0x001ea0a07f3da52L,0x0f3768e1f47b342L,0x01e7ee62f5dea63L } }, + /* 182 */ + { { 0x16c2a86b523e13dL,0x0522c1490685029L,0x11e39d5c4a58405L, + 0x0cfd6a37d47aa56L,0x07b0e9190574606L,0x144474384fbc30cL, + 0x1f3500a2bb621a1L,0x1e6f35013afb295L,0x050c6032fe2129aL, + 0x0f25f394c1e2041L,0x0c6eedeacefa39dL,0x06596c318e51306L, + 0x013f59c4a4d31a0L,0x16a7b0f11b6ec2dL,0x15c5c576fb38d17L, + 0x1d7af74f5599a3cL,0x0a1138c58da64a1L,0x04494b6879e8d77L }, + { 0x165288fcca82c97L,0x160968a13f46e58L,0x1c1d30fb76a49b1L, + 0x1dd5403d7ccd529L,0x10f5e86d94600e1L,0x02b5188a55e73e1L, + 0x10b09d075c0832dL,0x0d1560b54264f3eL,0x070b60fafd42384L, + 0x0c77f6098c69cf3L,0x1fc6b22482cc628L,0x1751b0733c07d60L, + 0x0e3c81a30101e3cL,0x066333ec32fc499L,0x1a181f2ba2f29f7L, + 0x142599dc35cf344L,0x0543182e64ccac0L,0x04919d17b958d26L } }, + /* 183 */ + { { 0x17e8df60acbee17L,0x0ace12e127e6e38L,0x021f953ff2c03c2L, + 0x15a50a22d68de13L,0x1ba1fa51b993decL,0x190c1f05fd527c5L, + 0x1dde6724927bf43L,0x043f27966b12d08L,0x1284bfb7f2322d4L, + 0x066384d6a157804L,0x1c89d26ec758550L,0x1674e2f878d58d3L, + 0x05bb9c5eeb76f50L,0x123c1dafc590f4cL,0x1870f9d63ec66baL, + 0x035900990d736a5L,0x091aca59092f297L,0x015d9353490f6c1L }, + { 0x0a3443515f81416L,0x13973d57fadda4cL,0x13780c5c987021bL, + 0x18b81439fc7a3ecL,0x1368340131c0786L,0x1cda66aa17526c5L, + 0x09fc4bddc9ce868L,0x1b829fcfdc397deL,0x1ee7fc09e16bb27L, + 0x06e660ba0872ee3L,0x199d08650ecf770L,0x16c07e63836f468L, + 0x19c22c107092934L,0x1ccfcb3580c36f6L,0x06c224e8dfba2e9L, + 0x1a9bc1e77f96849L,0x108bae614472e92L,0x049be59fc70cb75L } }, + /* 184 */ + { { 0x1c0e77c16fbfdceL,0x1a664e4c6a6602bL,0x15c9095cb483a80L, + 0x1800335079cec0dL,0x115971629861b55L,0x107ebdc05d1401fL, + 0x0aa883d05077416L,0x1d910cb2276961bL,0x0e6685746aa3848L, + 0x168ad2d1f0242e9L,0x031dd0eda417745L,0x16fb0315e575038L, + 0x14d2b74b78cec31L,0x0a1f1794406c78cL,0x0c1f073299676c9L, + 0x09180637074fb3fL,0x01186537fdc1f10L,0x026abdd83bc2c35L }, + { 0x04b768a53b396b6L,0x1926249da8ed65eL,0x07ae8c2b86cef22L, + 0x0b28a28f8a67ca2L,0x179fe3ce893bbd9L,0x0905ea366430188L, + 0x18580d2c2859cfeL,0x107665225d6d64aL,0x0bc69a2a49d168dL, + 0x04a4f3d7786e894L,0x0d066a1c9a6786dL,0x08ef7e426ed64c2L, + 0x09a4f9714706c58L,0x1dcdba2ff2ad8c8L,0x17cf2158f5badd5L, + 0x1f5c76a6cb65211L,0x0a80e257e4355fcL,0x00833e08c4bcf95L } }, + /* 185 */ + { { 0x045508432bf8883L,0x0943537e83333e4L,0x1e3ddf08cd751d5L, + 0x145e945929ae161L,0x1118acf5678e60dL,0x0dc86cd2346c566L, + 0x044133a4e0c2efdL,0x149d49638e9da9dL,0x0ac67316d27776eL, + 0x0c56bae1b0dd589L,0x0f520a64489146eL,0x0440a614875d864L, + 0x0e3292d5a526440L,0x0ff678de1d22299L,0x19ee2e36d21a52dL, + 0x0d5bdc9c0a2dd8cL,0x125b3aa595fa430L,0x03f27b848f9a74bL }, + { 0x13816e9b7f70919L,0x10b768b5801fa9fL,0x1fd1de326795d94L, + 0x10614a30208d8d9L,0x05e728dbe6a5abeL,0x0677eb77b7a4f32L, + 0x1cfddbf75cfab2bL,0x187d8729cdf186fL,0x173320802b6407fL, + 0x04747bd4b312e5eL,0x048d8df2afec026L,0x13be80fe6b35065L, + 0x05ccbfae50258baL,0x1f128c09ff80d77L,0x1c72e87efabab3bL, + 0x19b6b38d3e2c307L,0x0bd512c58ad9eadL,0x015724e6a366674L } }, + /* 186 */ + { { 0x039b0e3c40849f2L,0x15266d22084c609L,0x0a67951fd92544dL, + 0x08f537758cc2a6bL,0x13547af692e4bdcL,0x03d3a50cad0b232L, + 0x08aca17b2cc662dL,0x05a4f0aa7f93bcdL,0x1471c038a0e2ba5L, + 0x15d0dc41ade5d49L,0x1d4369bcc7b2884L,0x07ed0056658da97L, + 0x113c64c8c4d146eL,0x1769094b864e009L,0x1a14c3eb4c3c4b7L, + 0x1bca336eb7ff738L,0x1b723c0ad3e8918L,0x00c074ea9539bb8L }, + { 0x116542f29ab77b0L,0x08ece7bd7731461L,0x1a14d4f0bd03750L, + 0x089615c99e08980L,0x15fc266f638dc7eL,0x17f5bed04920c2cL, + 0x05e618e7699c7f4L,0x054ad0b1daabd47L,0x17a694f3158f383L, + 0x0a119e3698b6c18L,0x0b2c98c28d69eeaL,0x0fbbe3fee2765f9L, + 0x0559eee2f3fef8fL,0x0ab6832545cda29L,0x173f3f346d3e46cL, + 0x1d6822ef0cd845eL,0x1b412bc25663777L,0x010e5379e6c55c2L } }, + /* 187 */ + { { 0x0162b13a3e66635L,0x10515954fbb5787L,0x08c11b6ccd587bcL, + 0x0ef005771b568e7L,0x0699b44c0840bd7L,0x1103f8adb5d7af5L, + 0x004171b8464006cL,0x009cbbc2d52f216L,0x122b12f15db67f0L, + 0x02fd6a2c5012e92L,0x1da54f7c2845086L,0x0537e8a06981799L, + 0x001c277bff4c421L,0x14054f0c07ba020L,0x0aa8ad1b9102d30L, + 0x1b29eecfbd1eb08L,0x0353de20ab805e8L,0x02d7fac2c90113bL }, + { 0x05acd20a8458e40L,0x0abec0a4b995ec0L,0x04c57c729cb5695L, + 0x192a56a6478e0e8L,0x0494fadf7f2e269L,0x1e93332e2c92ab3L, + 0x0a19454edeb3469L,0x0d74dbe0c7b0dfcL,0x11e91db1357d53bL, + 0x0caddc4f49f5680L,0x0786bca58eff9a4L,0x1385104f110c7aeL, + 0x123b859b6ffab2bL,0x1b814ee8bbc1b34L,0x0611585b9a545d3L, + 0x1b0938f30f0ecf7L,0x17764fb4f1d5907L,0x01f55bf0e446c54L } }, + /* 188 */ + { { 0x13a94b652e5718bL,0x17d2a7a6770f4e3L,0x198d54fbb7ab8ebL, + 0x16be759434ca9d3L,0x0d083316f2541e1L,0x1fca876b894a448L, + 0x0f929e596bd8fedL,0x179b1f93c1b8e9cL,0x0b4ee48d2eaf79eL, + 0x02c543545bbc3f3L,0x1d887fdf33abc29L,0x1dffbecf301bb18L, + 0x02f91067278228eL,0x183f1b149086a3aL,0x1c78a7647d8d406L, + 0x1714a882ec38cf2L,0x144c0ccc65f03a3L,0x01a48ed279c704aL }, + { 0x106d046cb062eaeL,0x0db9aae843bb6b3L,0x0148a48c574bb9fL, + 0x05880577b701bd0L,0x06ed33374078566L,0x0b4769afc9a92e1L, + 0x02c79b3a85359f5L,0x0eb22d42312cd11L,0x00fbd52055dc716L, + 0x19e883bf22baef9L,0x0c402bb0248cd60L,0x1a02d9b0a7129d2L, + 0x05432263682f9e1L,0x0dd267ebf75e9b9L,0x13160e100745cacL, + 0x02fbc6efb573aaeL,0x018aeaa695880d5L,0x006421efeb568adL } }, + /* 189 */ + { { 0x15811ffc9373300L,0x099954cfee18022L,0x0070d4f2d95470eL, + 0x152d507a4fc3377L,0x12ee3f1a774b924L,0x06ab63e5fe47e5dL, + 0x0bde6bc9e3b1004L,0x17edfbcd05fc157L,0x07566d0727339aeL, + 0x09ad6aeb8902edbL,0x0f9a51c1472742fL,0x0901a7460cf96b7L, + 0x14572d7530577dbL,0x1036c29e96387faL,0x0afed77a1856bb3L, + 0x11daee33339960bL,0x169eeefc96bea0aL,0x016e6234e9afb6fL }, + { 0x0a6cd06c65f0e77L,0x03cc05eb8d8a566L,0x1e2cf24f3003773L, + 0x075d197eaf6c443L,0x16f8e63fddfcd5bL,0x10995bde494b9fbL, + 0x1278ba61228d01bL,0x034998b3407aa3dL,0x19c9d32bb3a3308L, + 0x009082940742335L,0x000ca86ef9ca540L,0x0ae449270891856L, + 0x0eb6bba0ffdbfc6L,0x0054a40174b9506L,0x0762f1fd830293fL, + 0x14171ec588398b3L,0x1fc820c96ee312dL,0x02d0d32ede6defcL } }, + /* 190 */ + { { 0x1ba691a42485684L,0x08b5c94e23864dfL,0x05c798a8146584cL, + 0x0cbfe933b569603L,0x05238efff3245aaL,0x0eaa8ae177c3fa5L, + 0x0b2b305b71aeb32L,0x196b4fe44fc5b7bL,0x18dedaac4a9bbaeL, + 0x1984536973e4c42L,0x1cbf0b9a25564ffL,0x050a2efc0c2298dL, + 0x06300b1bee3655fL,0x09e0bdaa531f468L,0x05d098afb4339e4L, + 0x0806f94957c6b89L,0x1d9f4b44a17bc4eL,0x02d74a84cf7f2fdL }, + { 0x02e5ee7804f7455L,0x124cb9103334109L,0x10c5de578cccd06L, + 0x19c91df9db2fa49L,0x19fbc21c12f4123L,0x11d1d77439c6c90L, + 0x09b6eecef718419L,0x0ea6c07b1850b27L,0x1926227f2e3c1acL, + 0x15495602f55728cL,0x05bc2ff5a04ab3fL,0x1089f85505b8b6bL, + 0x1a63522b273ce7eL,0x09433c4a9c20240L,0x1621a220d8222c5L, + 0x0f95843ff6f984cL,0x0980ca331612f4aL,0x02088333f51f6e9L } }, + /* 191 */ + { { 0x1830357c2d04b63L,0x0d1a6fa494d0c40L,0x1b688b46577cff1L, + 0x13968648e78e77eL,0x0997f13814df2f8L,0x0b027a1a2d7f2e7L, + 0x02b97638fd7e62eL,0x1e75af285d2a182L,0x0cefd5447eed25fL, + 0x1b4728f0739e066L,0x0b5646ad53e932fL,0x020a256c3918b63L, + 0x13b5abf7608bbc1L,0x00f3cb24ddc9948L,0x0332f9f6c48c6f8L, + 0x0db73a1507d2208L,0x1ea3dde426f90a9L,0x00e675b229a6f88L }, + { 0x1210c4f0c6d0f55L,0x0fb0dce339e4e96L,0x0466a738feedb2bL, + 0x192760c7c9baff3L,0x145a93be135f494L,0x0977be2c05ed9e0L, + 0x0eda9361c8cc83dL,0x1dce9b0edd11029L,0x14f6f723ac7a97dL, + 0x0f15c781f1e6c19L,0x0bc20ab9c809c1fL,0x05a9bbf490dcc2cL, + 0x198d3a17c6e88ecL,0x1cc00b8d6cb2e42L,0x1bdac898b967950L, + 0x16406156c50bb77L,0x0a33cf451954d48L,0x00f8ba919a7512fL } }, + /* 192 */ + { { 0x08a765b3467ea91L,0x119777e96ce22c0L,0x11b673caf1bcfd1L, + 0x006b30275cf6ebbL,0x044cbd8defc8d24L,0x092b1111f65904fL, + 0x1866966e8438c85L,0x1eff429b2687e3dL,0x1df97c21bfb0c48L, + 0x073144875186a1bL,0x1b8a919451d70b1L,0x03c824cce54b650L, + 0x1c31aab3b8291f0L,0x10be91764e37ed2L,0x13c2eb6dc9de96bL, + 0x125c37b11db0722L,0x02bd0b05d1b6a23L,0x0265c57c832c49eL }, + { 0x0b02057bb4b1953L,0x045a27acbfb7751L,0x166d79904b21338L, + 0x1b679a92330a9ebL,0x0e42bb5d1913262L,0x073fb04813b1723L, + 0x105b20d57239b5eL,0x0311df55048716dL,0x0d0173790e550f6L, + 0x0c57a3172bebbc7L,0x0b57a1c56d1c504L,0x0d8683bd49f342dL, + 0x12280ca61090059L,0x1ba632d0954abe1L,0x0201050bebba000L, + 0x01f43b620a24ea0L,0x0fc8c1db931ff08L,0x024352e12ebcc3cL } }, + /* 193 */ + { { 0x121e213941b4f36L,0x07d8a7c01da7c82L,0x08b94a952ea2eabL, + 0x151fc8f2d9fbe3cL,0x18dbacb6acfabbbL,0x0efd28d703c46daL, + 0x05bbb7e635cdb06L,0x0362ab850d46b4eL,0x0be7d46769c8646L, + 0x05b1c07b1d3252fL,0x1064527d8249894L,0x0fa145bf8b66296L, + 0x15cef466ac0919aL,0x14c35576622a6d2L,0x09273b64fe92891L, + 0x0eb5aa12162e2e3L,0x054602f1d6cc1faL,0x02e934fc4bc7260L }, + { 0x074030c14920419L,0x0ec34484b439c9dL,0x1313badc3e98211L, + 0x1bb3f8b79703732L,0x158f8f2dabcaa06L,0x0e29550329ca13fL, + 0x06ea8d7217d9ec7L,0x068b4fb1ae45922L,0x14041005caec2d8L, + 0x0c345223d4729a3L,0x18602e37944b0edL,0x0dca4222d1d609dL, + 0x0b2317cd8a4daa6L,0x108b26fb605eaedL,0x0eb5f2687506175L, + 0x04d0759db944c3bL,0x10f0fe4b5ac09b0L,0x04564ccad136caaL } }, + /* 194 */ + { { 0x0c8dc9b2640a39dL,0x1859c76f064fcd9L,0x06f687b2e82887fL, + 0x1a101a082ee9e8dL,0x149946048a902ccL,0x1b558af4ab7d197L, + 0x1d248d23e173e5dL,0x0cf843f8ddc00cdL,0x135b1ebfefeeef3L, + 0x0022c0e2309f2f6L,0x1fa39ba9ae81c5eL,0x14652a1ae7db97bL, + 0x161da48889ddfcaL,0x0dd7fde8e4ba3c9L,0x0ebab9f3a19f233L, + 0x02591a4ce863e39L,0x04d682550458979L,0x0063e0eee6bf50fL }, + { 0x1aa30cc1ce963a7L,0x17b266262fd6f29L,0x0be0a0a2befdcd4L, + 0x0d9442420e57354L,0x05a576dc64273c5L,0x1ae3be556ebb2a4L, + 0x1ce6d865ab0fa42L,0x18841a87d3fa355L,0x1fc392062cd05cbL, + 0x00b1c392607f97eL,0x0ae360aba087985L,0x12867f4f47e19e6L, + 0x0df644ca925f58fL,0x0c8c53afd75f8e9L,0x01d84603018558cL, + 0x04882f3136bdad7L,0x1abbf342445ad41L,0x0127fe4d70efb19L } }, + /* 195 */ + { { 0x1fcdc0593c7cb2bL,0x01dcaac8029fdc4L,0x0f3d8608d0f3049L, + 0x1ecd8314c6c03bdL,0x0c913287364546eL,0x1c4618d2948380fL, + 0x1df5f0d6e009be5L,0x0510a570c5525a3L,0x11809cb050aa797L, + 0x0bea33e51e59002L,0x11df027bd6e51a2L,0x1885e4483309e41L, + 0x0df35bb206c3372L,0x14e0a05aed029f0L,0x15beccef09b1b42L, + 0x072d0c39f981996L,0x1a41c3cf9ef299bL,0x044f269e8a0310dL }, + { 0x15e80e7a45a9be3L,0x152bc039ab7dee9L,0x18bae59ef0bf136L, + 0x1c8f9a2dc6030daL,0x1f30ce9ba702679L,0x0327a865178e012L, + 0x0759bc4816d187eL,0x13cffadaf2f0a0cL,0x047edc4f68a0880L, + 0x0d60224cd269d71L,0x119929b47e76a17L,0x1d09af5074e3f08L, + 0x0ceaac33f19f30cL,0x0a431155f49c15dL,0x1a07ac87c0ce0c6L, + 0x16b8f606f4975eeL,0x0fbd156a90899a1L,0x033ae9f37f378e8L } }, + /* 196 */ + { { 0x1767ffd707193e5L,0x05548c081ac72ecL,0x07fcca363bdf91eL, + 0x10db77b34eac69fL,0x1e215686913a0eeL,0x0ced1c1bcd94b43L, + 0x0d34a40fd042a27L,0x16bb3f1af723626L,0x09fe74229bd82efL, + 0x1ab45b11c01e3bcL,0x068d434f494d136L,0x0b60e4892fd127dL, + 0x16a169e23b559c3L,0x062da634e2396a1L,0x11fd4c4261918cbL, + 0x0f1113edaeb3b07L,0x04ba91cf1db1e49L,0x02fbfc97f30578dL }, + { 0x18a1cc60545167eL,0x1170157fd447078L,0x1d450ca9ef3d57bL, + 0x054ea210cc499bfL,0x00511af77382da4L,0x178a11f44a608faL, + 0x14abaa93938c4aaL,0x06b187a6de1ec7bL,0x1fc5c9550d76606L, + 0x0929b989bf53f55L,0x135660e6e543d80L,0x0c0281cc688454bL, + 0x0ef2ac704595a0fL,0x023587b9c82f11cL,0x1215e2912eb3039L, + 0x0f00699a840dd88L,0x18d367b1aaaa5bdL,0x012df676c8515a2L } }, + /* 197 */ + { { 0x19a73820c33a8fbL,0x1b6688792ee0e83L,0x0fe31b520adb3efL, + 0x180f7f08949ff8eL,0x199162f03e51f18L,0x009c08d3b2891b2L, + 0x06282b1669d3850L,0x1632af4d0cbcaa0L,0x1e1ec51bde3ca09L, + 0x0063f59d4b0129fL,0x0ff451f780fe12fL,0x1da2a5f7b613d07L, + 0x1dcea15ec1c0540L,0x05930983b5d2976L,0x0e5c81bcf4c3b55L, + 0x0e75537af75d1d0L,0x163f20d86920963L,0x00530b525e1d85fL }, + { 0x075f3ed6e1339c9L,0x150395fc5805310L,0x120af3366d1debeL, + 0x1e0194a98fbf5fdL,0x18bc31ae4713158L,0x06fe45224881789L, + 0x15352be63c560c4L,0x18993de40eab3d2L,0x1e8021af9c527a0L, + 0x140093bbd0c9011L,0x1d4e31fec08dddbL,0x0e9fd193d2a2c6bL, + 0x0d15cc90975df19L,0x1bd288ae0143fd7L,0x0b188f7e81ca3c3L, + 0x1741321b7f7cc1fL,0x04ca8d40fd40311L,0x043b68aa703e323L } }, + /* 198 */ + { { 0x1a4d6d2c2d3ea8aL,0x1340dd421300769L,0x0037901c19c8dafL, + 0x1cd4faf4f78a7e2L,0x1d5e1a83e3e5b6fL,0x04be153734ca7caL, + 0x040441f2b3489d8L,0x04825b31b754cf2L,0x0ddfc4461102e0eL, + 0x00aede16a499395L,0x03992ea50d9a592L,0x163465657f20fc7L, + 0x05d928e28b4960eL,0x1503be4f6d22ba9L,0x1587401cbdd6ce4L, + 0x028ac4eec1976ffL,0x100af235d1b0f4bL,0x01820611df3b68bL }, + { 0x10dc55b4efa9a70L,0x120a7a9f4330858L,0x044c27e289ff537L, + 0x0a0ccc3a787b2b8L,0x00eb513e505109aL,0x1e99c5e5514ca53L, + 0x19c7cfb9054dc79L,0x1689fa28bf88ca3L,0x051bbf838cbc313L, + 0x01cf03c0f5c90a8L,0x05ad1052fd6b1ecL,0x031117c1a919d0dL, + 0x15dd8f2b6f2d667L,0x15c53fc55f49d97L,0x1dd4717077f479fL, + 0x0e97d0c567bb321L,0x1a21eb1ad58a32aL,0x02a436bcd0f5de4L } }, + /* 199 */ + { { 0x12e34ffa1359e13L,0x0c6df940cb028e5L,0x08f48d592d7880bL, + 0x0c85ed5825d2bc0L,0x1653725dfb1340bL,0x123356aa1dd4295L, + 0x1ca2e06bb735a34L,0x0cb7ef00448a8f8L,0x1559f8a119569fbL, + 0x02dbd316fd91764L,0x01d5027bb579494L,0x0510533ede220e2L, + 0x013db6f8c79c899L,0x19e53cd4d3eb493L,0x08582c0c3adfeceL, + 0x0813595733771f6L,0x18bd2012568d28bL,0x01c078d87ad622fL }, + { 0x0b99e6be6a0068fL,0x1e79564539ba9e0L,0x1522cbebadf12d9L, + 0x126804c1874d934L,0x0c0f739e7f417f9L,0x04a4ed4772b42aeL, + 0x1bbffc22d443de0L,0x17762ee1f851ab8L,0x0b4f5abeefd96a7L, + 0x03d889b79332d15L,0x0e0292d80773e68L,0x0c282c57d98c5f6L, + 0x16ee6b83b3cc803L,0x1460bf759a4c7dcL,0x1dfbf0baa6c3f5aL, + 0x0167cb0696b7542L,0x05e929044f55b11L,0x0255f6ef6f5eb94L } }, + /* 200 */ + { { 0x155e1b9700ef376L,0x12ecd3366d5ff99L,0x15d51fa1d91b55bL, + 0x1401ef26d367b84L,0x00c52e2928f44b8L,0x14d9c90461958f5L, + 0x08e7569e37848dcL,0x0d68308a33564daL,0x123f6b4b7e0ce4aL, + 0x1afb7c5565954fcL,0x0f1153881929648L,0x006837e60c5d771L, + 0x1b94dff6f937efdL,0x0553fd0335d6341L,0x02cdd170cd92c7aL, + 0x1f61e0c2cee559cL,0x0d346f08d08d1e3L,0x0351055d98c7099L }, + { 0x08310166a85cbc7L,0x084a349a7cd53f5L,0x02239de3c6cf426L, + 0x1e448f6f3384422L,0x054484ce7ea4ff8L,0x0c61b2598b8eb8aL, + 0x05160a500e5253eL,0x02cbb5223e72fbeL,0x0a6b58093094391L, + 0x0fca84d0ba11c5eL,0x1460860825d635dL,0x004348f24ba1fd6L, + 0x14af8a315eae0c6L,0x15d6825b874a334L,0x1c911f6b9ebe28dL, + 0x0dffc8982bcffe0L,0x1775184668aa545L,0x022f1a9d3df9b5cL } }, + /* 201 */ + { { 0x005676493092f71L,0x15b617adc96b8bbL,0x126f8b22db17ad9L, + 0x1441806c7d3b662L,0x03cd7097f62f583L,0x1c8b56344566998L, + 0x06c3a174303e3aeL,0x1a237ee8c590983L,0x1c76ed5f97c4a6aL, + 0x045c45d688cf9b4L,0x00dc6faf942e0fbL,0x0a110cce0d4cb37L, + 0x03f8373d2c0cc69L,0x152d017da98e3adL,0x0e6874138734e8cL, + 0x0667dd04e8ef1b4L,0x136edfc5bbb75daL,0x00aca0f92653cdeL }, + { 0x0e8c0f8a77dd512L,0x1acd38ee1b2fb21L,0x133421d4e18aa46L, + 0x1ba4e5f595d01a2L,0x0027cb5a1624230L,0x17cf81f751f60b2L, + 0x0523705c02d6707L,0x1e3a823824e1b46L,0x1801ee448c4181aL, + 0x0f942accf1d4805L,0x1ec2f43426bff7bL,0x1f2d166e0048bacL, + 0x00e6f836b8d839dL,0x1e9900e49db183fL,0x0740aed4e0b9622L, + 0x083d2c6db14d6f4L,0x10370b7db769686L,0x0368be1a508c7d6L } }, + /* 202 */ + { { 0x1608841c181c99bL,0x0e480e43dee57e7L,0x111cdc836afad97L, + 0x0ca6eea2b768c16L,0x0a96c2774c79c39L,0x007a206a23f9170L, + 0x00eb4365484c0abL,0x141066164d7920bL,0x0e25e977a928904L, + 0x0f57fecc2e2858cL,0x16f2de96b57da87L,0x00339146fdab9e9L, + 0x101e9850b6cbcd0L,0x185c7302bc236ecL,0x04cbe406b20652aL, + 0x1c51772e50ae268L,0x14e4ce9f149f56eL,0x00d5cdad21f4f0eL }, + { 0x06dab92314fa7a3L,0x1787823c7fcb190L,0x1c4e41367f6f312L, + 0x1625808bfc999c2L,0x1d8f6d7dac20a2eL,0x1db7fd227e2a3c7L, + 0x1dd6221b9cb1729L,0x1aaff48a536dfadL,0x14df1d1b192a820L, + 0x0c097cf93c4f8a4L,0x0bc20eaaed4f48fL,0x073654075665308L, + 0x10b151250226485L,0x198fb5eab18e704L,0x0db98d384a53455L, + 0x0cd5f64526c3b28L,0x1ed8c4281c43ca9L,0x01259a4ab610d59L } }, + /* 203 */ + { { 0x1bdcb86659824e2L,0x067242709f3a624L,0x0899aef87ba9b71L, + 0x0e3c7d88af49803L,0x0f5a8e4b47b2b8eL,0x19a986bf458af01L, + 0x1480ba07adb9b8cL,0x13f59746d3c2f48L,0x081241431d70e4cL, + 0x0c857a59f095f5cL,0x1c148c47d21bf70L,0x03c253f6579ca64L, + 0x0bb70f6c089f6c4L,0x1ff5a23bdf3143fL,0x13c62ec51e61428L, + 0x1a081f9fbf62337L,0x1f9925c292fda80L,0x01096b2f2bf1e2dL }, + { 0x1adb386ca15cf08L,0x1256240f0b97591L,0x1e4d350b430137eL, + 0x06e8809b8f3a3b7L,0x0932bfcdd9cf607L,0x14154c30284220fL, + 0x073026ba4432871L,0x0612a51f8308358L,0x0e6a120aedbbed6L, + 0x07070f618667928L,0x12e953962efcbe5L,0x169f3f54882bfd0L, + 0x07ecee7ce5c66d0L,0x17d3439d062c78fL,0x07c4d21e8750fadL, + 0x0f56f2d8d8b4073L,0x047e6ef9aaae672L,0x03357d2aa4d2e12L } }, + /* 204 */ + { { 0x05aaba8c980e91dL,0x07a84b564c77d6dL,0x182a368c998aa4fL, + 0x0001028a7d61321L,0x1d71de8401d2153L,0x0cd00915d8699f1L, + 0x0e39d197db600f8L,0x118b205fe98f150L,0x174e2afb7193134L, + 0x04993abce7d82bdL,0x1a9908eb40fe3e9L,0x048ab1ff4814ec3L, + 0x1977a87e30b7d4cL,0x04e426935af4e06L,0x0658e834717b6ebL, + 0x17e1bd95107347aL,0x1dfbc6f2f35ebf6L,0x000f7831886ac55L }, + { 0x1f903163ecdcbb0L,0x16b9413e0e4aa95L,0x00c255d724c0678L, + 0x132d3072613ca4eL,0x1cd082df0dc1c5aL,0x0bf028f7cfc07fbL, + 0x06d57364541d77eL,0x189e50dfffd398cL,0x1352db38f80f24cL, + 0x0cdccf61b291d71L,0x0a32a042c412a7bL,0x1fce60a4075a213L, + 0x0e769400f5c2700L,0x170622961517712L,0x1c0a90756574e67L, + 0x0616e156ebad5efL,0x002341080990db7L,0x00727affeaf4689L } }, + /* 205 */ + { { 0x11c64440ff14c38L,0x1acfd576708f95eL,0x169c8abd8cc2696L, + 0x15055e49dd548c0L,0x0b9a1159ddc9f65L,0x142757fa7725ff7L, + 0x0ab38918f41d9d3L,0x1971197c3c01c17L,0x17ca568ead5fabdL, + 0x0c06a9262bf5cceL,0x195cb3a6fa61cefL,0x1b9ae60170bd388L, + 0x1240f54176918a1L,0x1ad8a11b2491098L,0x0d3c5abdf8c93feL, + 0x1b2f881bb4a0248L,0x02008833421a133L,0x019ea08b0843b78L }, + { 0x131a36b9878e5ecL,0x1f190a348c1193aL,0x08cf428c1191778L, + 0x0f542e6cb3a2bf3L,0x1925d4fe734c1b8L,0x11587a56104a517L, + 0x172f10f25968709L,0x000eb39207c88faL,0x092af215e052393L, + 0x1fdb6af8fac9f9aL,0x10ed2f0f376d7ffL,0x05397fbaa810cb2L, + 0x0b198d76c09d03aL,0x00793dacc7be6d3L,0x0d6333f01e4288bL, + 0x09fb974aaf50919L,0x0665922052d76c5L,0x0169ef3d523db5aL } }, + /* 206 */ + { { 0x0de746265add3b7L,0x0479ad5f9261555L,0x072b8695f64f962L, + 0x1c58edef7fa82a9L,0x1e3202b30e22e18L,0x0e878533f944755L, + 0x0b462de699ae874L,0x1d21c156e925103L,0x17d424086c7adb0L, + 0x186196294210997L,0x11dfc563e6827a1L,0x06e5d804ab130b0L, + 0x1ca5098777422a9L,0x0bb3002c5f21462L,0x1fcdf3d16de5591L, + 0x0c512d8ff8c632aL,0x0a68b7023ddd631L,0x023801ddb2d8e09L }, + { 0x19401c1c91c1c96L,0x0e6fc93d094b86cL,0x185f0f0a441ea97L, + 0x0f47fc8e2075725L,0x0ee998ee26fce8fL,0x1d20fc58684eaf2L, + 0x0941abe98881238L,0x0a56380254b44d9L,0x12c6f734c99b572L, + 0x049ebcfa897bff0L,0x0241bab3b866984L,0x07020ada3d4c5e6L, + 0x16eff35f216bff8L,0x00d6911230e3ac2L,0x083f7a1b81fa5e3L, + 0x1d0365994d942d6L,0x0e6ab4d6d2d633fL,0x039effa82583516L } }, + /* 207 */ + { { 0x1615805d8e20fb8L,0x039f2415a99f845L,0x00055aa15329f1aL, + 0x19966d2422a40beL,0x07f092b787fec6aL,0x02ff260fd1e0766L, + 0x1c4496cd991fba1L,0x0dfa8f03d0bf163L,0x0c65268398b0f1aL, + 0x175c6366e5c75c9L,0x1c3ab6397db54b3L,0x1c4791b269b8267L, + 0x1d428ac45a31883L,0x0ddfe54290a76adL,0x196b84fddf2924bL, + 0x00bf7be8227fc0fL,0x13563e4a0d272abL,0x03aa2685bb8a47aL }, + { 0x1e8d13480797aceL,0x0b55057c36cbf27L,0x1a23bd69a3f085bL, + 0x0b3f364d09b7e14L,0x0999d2fc18b26f4L,0x011caaa97f7e7d4L, + 0x0de0356be360989L,0x15f1e2468d3ec74L,0x12933454fdcd4feL, + 0x1400c5bd39dae84L,0x07c9db9554b062eL,0x0e7bfe4d763935eL, + 0x1006dd4f44c5d47L,0x0f9cdd24cf7a4a0L,0x1b293cab63c4be5L, + 0x1eb34aecfedb9ecL,0x149ba8773f17922L,0x0110040f560f216L } }, + /* 208 */ + { { 0x043d573ba37a0baL,0x018de6e8bb6fb18L,0x13f31081c3dc169L, + 0x1ccf85a21206645L,0x0bf8bcfa5cabd30L,0x03d8859b164aef6L, + 0x179935d9f49dddeL,0x01cc25922bcdd80L,0x19e669631ce69c3L, + 0x1e4eec7b417131aL,0x087c4a57ff30e09L,0x1cf31455b944f20L, + 0x044b5d500a06a8eL,0x06c06b62c70073cL,0x17c43321dd1bf1eL, + 0x0dfb048c0a77d22L,0x133844e328b219fL,0x03102a0d608de9bL }, + { 0x17fd382509e5a29L,0x06be85a19298f07L,0x0d5334e20ee61d2L, + 0x0917f762f51ee92L,0x05f2d2c5c6b8ac7L,0x058dc1d230b5330L, + 0x0996acf6598946fL,0x0b19eea62085fdcL,0x0c70d73fbdb2250L, + 0x108ea1a78616aabL,0x01876152c966cc4L,0x00db88567efb0c4L, + 0x05e86a4949ffe46L,0x0b0776d6262e42cL,0x03890801377322cL, + 0x02cac30099cceadL,0x09791f3855a4214L,0x03f9bc0cc7c995fL } }, + /* 209 */ + { { 0x0374bdadfa6639aL,0x0a46a0155b9c8cdL,0x08d91c0c78b432fL, + 0x19a0b33a3eb8bdeL,0x00d38443b49ee2bL,0x09c9746942f5b07L, + 0x14e3f6efaa4bc9aL,0x0d1228abf7f7178L,0x0ae259ff1e469b7L, + 0x0e7658fa0ef2b41L,0x1bc1c6654b46bb0L,0x0303cf7ee88d90eL, + 0x06282ad2f11ce25L,0x15d277b3e5c9d6cL,0x01ea8fa3e8f34c5L, + 0x16c11f9cd1409caL,0x0d0ced74170a61bL,0x036f38b59fb5608L }, + { 0x0e58d04172d6dc5L,0x166f331cbe32e6aL,0x1860327ad3a2fb4L, + 0x10ebf45db6f5cefL,0x091e67385627546L,0x0e4597259819275L, + 0x0a21d808ea1588dL,0x16b3bedad8551f2L,0x0ec2c185ff6f5e8L, + 0x04970959d6aba45L,0x0ed3cb552bbef1eL,0x0891dd0d1042f5dL, + 0x11b1d9bd5b14915L,0x17f806fbd1362fbL,0x16c77bb97334598L, + 0x1eee9d7933e2f72L,0x1b0909836163fe1L,0x028fc84185d9e92L } }, + /* 210 */ + { { 0x1376fa1f2922461L,0x0d8e18b286868a4L,0x10cc376182376ecL, + 0x166d71320d25723L,0x1f5600523e612c4L,0x1512a2f0cbbd85eL, + 0x0f63be2bffdc18dL,0x1759b4fa4f022e4L,0x00b0bc4bb81bde7L, + 0x058405976952bc7L,0x0834345c6cb808fL,0x119f2837735cb7bL, + 0x1bc14a65c5f6df3L,0x00ceecc742eec0eL,0x081be4dfe6320b7L, + 0x17cf18c26e8fea4L,0x1e79e13a2c25f5bL,0x02f7690c70551a5L }, + { 0x156575401d4dc0bL,0x12f93fab35d83f0L,0x0faee088975686bL, + 0x182313d8d7d30bdL,0x0cce4d9d5f3ad21L,0x1b2dac8bed28c67L, + 0x1dc732128b4fb5aL,0x0f4ff3102eb1ff4L,0x150d6ae122ac69aL, + 0x1bf9858e3734236L,0x08e9816f42ec4f2L,0x1d9bae7e480f180L, + 0x0ce5f0a9969a10fL,0x1ec7ac034628ac6L,0x1691b8749afd856L, + 0x1a6115e65d50f22L,0x054eaf74e810287L,0x0460a5d03531321L } }, + /* 211 */ + { { 0x0877895b17ee201L,0x15238c472bd3b86L,0x1d8e5e08915b016L, + 0x019387743a3387cL,0x14389ebe0be6f8cL,0x13fddb7f42fa7fdL, + 0x1b1914e2f333833L,0x0850edd5654ca4cL,0x15c9ac690cf9a38L, + 0x1ae79d8e6647cc0L,0x1ef9aa73da1f7a7L,0x01f90706b82bf42L, + 0x1b150ef2ebfcfc1L,0x04252973043587eL,0x1347ae27e5fb366L, + 0x0077482dcdf4561L,0x05ee2bd15993eccL,0x0322e052ef55d8bL }, + { 0x14c420550aa7e31L,0x06f8617c28ed2ecL,0x0424f1c9b9aabb2L, + 0x0c4c337f3532c8dL,0x0253fbd572dbdc3L,0x184f030da130707L, + 0x1b16e5f0967ee31L,0x1d3f57ef9779bb5L,0x1b4d5e8b1e4b703L, + 0x18372b7039a77eeL,0x1293e47d57e2946L,0x11747eacb91a05aL, + 0x12816d1d947f860L,0x0e73d89b4117a3eL,0x1410908330d8559L, + 0x0cfedc8ddcbde63L,0x091b2a65f706835L,0x013f4ffa0697d36L } }, + /* 212 */ + { { 0x1251893d7e952e7L,0x182c1e39adf8c3aL,0x064a5bf8124456cL, + 0x1100da5f94e656bL,0x1b885ed92745185L,0x0faaf638d5bb500L, + 0x0ea72f73a765db6L,0x0567b4c164091e5L,0x16977c086592b13L, + 0x16e54e584c828ebL,0x0aac8f4622b896dL,0x1e7fc4155e7bb38L, + 0x0f5aad74d09f469L,0x1154f59dede8fbeL,0x1c04310f57bf970L, + 0x004c118bdbf4426L,0x176ada2217b5787L,0x027f772b39ed64bL }, + { 0x0e18d52b5d3d780L,0x0dae9838b33a218L,0x01b969d0855936bL, + 0x1d1ad7770c641a7L,0x0d263dd15d8c290L,0x0c231b4c0d21919L, + 0x0b2c4cf439f2a62L,0x1fea270f09b4a33L,0x0832e3fabdddc81L, + 0x013c2ca18ccd21dL,0x12af3cc9d0c58ffL,0x017ae9f29f4eb69L, + 0x1d5694a6279fa01L,0x05b2bd1261453a1L,0x1a897ab074aa223L, + 0x0c3fefdde4a07d0L,0x00eed11a5d304c5L,0x027f40c73ce4f6fL } }, + /* 213 */ + { { 0x0252c9d7fc1c7ffL,0x0a0cecfd44d6880L,0x09290193a732a6fL, + 0x1087285d9992742L,0x0749695b384cbcbL,0x08b2df802610fecL, + 0x04409a720767d08L,0x09bc464ac51bbc0L,0x1ec9374575a9b00L, + 0x199a35ffb6e7e10L,0x16992d34dcb1f7eL,0x15a7e40929c5589L, + 0x15e867c150cecb7L,0x015b91ec2b1620dL,0x194c8c4a64e573bL, + 0x0cb2f9235bf8afdL,0x1fce06f1161f10bL,0x040c8aa94dba69fL }, + { 0x0c124316ed9d4eeL,0x1d0aa344d7f80c7L,0x127caa268fd0f7fL, + 0x05a8cfdf6495746L,0x039102e22db1e8eL,0x1784158c6f51aa0L, + 0x1751d08aae14f94L,0x1dce2614583da6dL,0x1ca60e86d0295d1L, + 0x15634043e3fad69L,0x0f3b3f7a1919639L,0x18428c3a24ca1f0L, + 0x10bd38509972e66L,0x13319144ff77a0aL,0x0b71e543c60fceaL, + 0x0ee044ea8a97cf2L,0x0f32744c11b1136L,0x03e835e63f47537L } }, + /* 214 */ + { { 0x12859427090212fL,0x1bea62a90f42244L,0x108af8b6ee49a46L, + 0x1b7b03f10098070L,0x0c89bc36317721eL,0x078026e09b65f75L, + 0x02ae13dc6d82deeL,0x09a4d2265a09c43L,0x1b0e2496ee6cc81L, + 0x196718bbafd6e0aL,0x0f02119b488f142L,0x154c98c25f1705cL, + 0x0ba4b653559721cL,0x03e9ece8acd3a8fL,0x0350918d0ceab57L, + 0x079543cc373a5d0L,0x192149f655ffc67L,0x0245a95cce87ce5L }, + { 0x1915399efdc05beL,0x06d8c09f04af4d1L,0x0ba7376cff6b79cL, + 0x04340128a288f0cL,0x03920ea3a2b0316L,0x1dc7f5a593cc061L, + 0x05b52b14e53c688L,0x1342c7ee4ac7cacL,0x0aa0ff93fb71421L, + 0x137cb6949eb123aL,0x04baa1f73f89db4L,0x1e5e8e071a2bba4L, + 0x05f418168eab27bL,0x19954c4d72c6419L,0x127c4ef8dc1088aL, + 0x1095b46d287217fL,0x0ecf16e26060d06L,0x00be06f43cec63bL } }, + /* 215 */ + { { 0x0a5f453dcc01958L,0x02caa0e7441c9deL,0x0285587d6db5f65L, + 0x0cfc5a6d78bcc6aL,0x05ac3a6c291c3c8L,0x000366fb63f6c25L, + 0x1b0ede44f102f66L,0x153ef17610eace3L,0x11c928f6eb43e89L, + 0x0f946f9d70f50f6L,0x0e96c6e492cad7fL,0x0e0a3422dc0ac57L, + 0x17167ed3e3491d2L,0x0de058230476015L,0x175fd678a473dedL, + 0x1336e61ca02d318L,0x1d70c7c350df5c7L,0x034315cf1056370L }, + { 0x0c6f4e79ffa1f64L,0x1548d50f121a4abL,0x183336dd48cbfb5L, + 0x0e0645ac0fd341dL,0x062fef87bfc90b3L,0x1fe79a14a405692L, + 0x18e3ff08525a70aL,0x138dca423c14a73L,0x02a59ec2612a514L, + 0x0aff1096b835a99L,0x1ec423a67210a46L,0x1d46bb900905eefL, + 0x0bbd92d29874ceaL,0x15750af752d3018L,0x01c4272b50b7296L, + 0x1ec93ad58778e93L,0x06cc64e1c40290aL,0x02849fd16a8fc6fL } }, + /* 216 */ + { { 0x0cf32804c2d553bL,0x15f111dcb3614e2L,0x12708a5a452b706L, + 0x0b3332ed92aad4aL,0x176e83f3d8c9f8bL,0x02f62be1162bdebL, + 0x187d53ca50aadf2L,0x091de680fcadc58L,0x1f005e8caf213dbL, + 0x186429ef9934c63L,0x12235f2b02952d1L,0x17dac16ea03dcdeL, + 0x06714a4bd9b6bd6L,0x1704c44a7808188L,0x1e4a8014a16f0edL, + 0x1e495d80ce835ebL,0x03832f16426ef7eL,0x0097ce226b63bd2L }, + { 0x151e96483313a1cL,0x0e9ed19e2c59b8cL,0x1d4b1eb1011263bL, + 0x0e1b96bdd09db77L,0x0dd422f8866ca6fL,0x10f6177605747abL, + 0x148f041def15019L,0x07cda732275a844L,0x1d105e1e858e7cbL, + 0x1e49cbfe4bcdda2L,0x0752a4265ed6491L,0x1147d12a5fce644L, + 0x074e9462410ef62L,0x0cbc07a06846ac1L,0x18443b1932fb43dL, + 0x1634627af844e11L,0x118d186d8667679L,0x0017baf2713570eL } }, + /* 217 */ + { { 0x1637ebf47f307d7L,0x02535680a0a3b8dL,0x1594b816a031ad9L, + 0x07fda0f66305467L,0x1696e597c8f1a0fL,0x1fe00f604f73fc9L, + 0x1cee736a9fb0f1fL,0x112a93f11fdf1e6L,0x1c88d1961c3bb89L, + 0x09527f4efe553dbL,0x1e7b88eb92ac836L,0x0c83ebd9634a25fL, + 0x1fe32fb47df5aeaL,0x12e842e073b491bL,0x11d568a5a971080L, + 0x12e47b9224ab04dL,0x141580b985f9bceL,0x03958dab331cb0cL }, + { 0x1708a08790e5558L,0x1b0208344d7c04eL,0x0e2908c4ed7e614L, + 0x04ab493a35d0bcfL,0x0c371b0be6ba129L,0x07370caf3b62585L, + 0x0688561413ce64eL,0x19d1ba82844c15dL,0x1d8b04e9b968485L, + 0x0a625d2c43f7f21L,0x1a399fc47179cfeL,0x1c519ed73388224L, + 0x087a0a966292623L,0x06501769f968555L,0x18ed546c999dca9L, + 0x16b6ad1dd1c9c5aL,0x1adcdebb2992e78L,0x02ef8c90b70b912L } }, + /* 218 */ + { { 0x0027e1e8df2e7e3L,0x1e6346c6d03ef10L,0x09a52d2b9a52c60L, + 0x1e794c5d119c6b7L,0x12efed2c896d97dL,0x1e84279ef2389daL, + 0x048ef401b10389aL,0x1603d36e377f903L,0x09991c7b61aacc6L, + 0x08649b247b2b420L,0x1587461fd1d4919L,0x16237ffa7944270L, + 0x0ffa191418610f2L,0x0aaf2984cb48afdL,0x01cb5e63c48db7aL, + 0x14916c2797dd543L,0x0327f7b44ea66a2L,0x0229132e170544eL }, + { 0x0d5ec7925430010L,0x1c37ff5e8486025L,0x13fc82a74fd72b1L, + 0x0547db8cbf4bf3eL,0x0cf3eb11fcbf411L,0x12db80441241ce0L, + 0x02ae2e375b53a2aL,0x01dc44e3bfb6eadL,0x0e43ec373b74456L, + 0x0757c930e7ba94bL,0x06b838fea5b66deL,0x1a5bb84bbfaa301L, + 0x146bab77110b312L,0x1af678f235c7bc5L,0x07fb2a81a7bf236L, + 0x17bc3832a575cc1L,0x15543e302ed5f4dL,0x00a5815fc8f03c2L } }, + /* 219 */ + { { 0x071c768b87e5b57L,0x03c7bfa98d2ab96L,0x1e2fdd65f7202f3L, + 0x1a273c2ebe9ff27L,0x0b94ca6cb28e026L,0x1cfbfe35c1db93eL, + 0x145c0babf8ec801L,0x0d85594a9bd9e77L,0x017c4133c6af0dcL, + 0x150f332e67af1afL,0x046920d154171afL,0x17a1cc2017134cdL, + 0x06c17d03882633aL,0x0d067c864b36338L,0x0b75931ebbffef8L, + 0x1548c9b08f7cfa1L,0x0a5d49bcdfbaea2L,0x042f03f3a1663e8L }, + { 0x1aae0a60bc25bcaL,0x12af8f227b27611L,0x1b62d81eddcdba3L, + 0x0da600b213c3cd2L,0x0cbc4990aa90a74L,0x0717ae83958e669L, + 0x03b24343f9b1b1aL,0x183241d8be0a7c5L,0x179b21fb4f0040cL, + 0x19bade9fe625163L,0x177be786eb1f769L,0x1af26b81f1a7ebeL, + 0x102cacd318dc315L,0x14937b8e388be0bL,0x00bce69bca08f13L, + 0x1264671b6b177daL,0x030e5b492317db6L,0x004b201cfc6a4faL } }, + /* 220 */ + { { 0x1774f1656999ebaL,0x17143d8ef318290L,0x1c9b782c99a4f63L, + 0x127f128543b035eL,0x0a03e13c3744693L,0x1139e7de7b5b0afL, + 0x1715b4c3030d653L,0x1449fa674ad8ce4L,0x1a57534ada8be97L, + 0x0c921533e115128L,0x06f6d674317125eL,0x0d998d484ed09caL, + 0x0cd426bf59d7cd7L,0x1374df5948a04bdL,0x05b8fa5650128b1L, + 0x0cda08e71fd30b9L,0x056bcbb3e0eaad6L,0x0313587e931de2fL }, + { 0x1217dbae1a1ec42L,0x173edd5ad662823L,0x0c7a194cc746a9aL, + 0x007a6024df6fc35L,0x1ee61851b845307L,0x144aa2140324f06L, + 0x1d8ca201bd28fa9L,0x09e977c875b96adL,0x0036b9bdabcaff9L, + 0x0ca0f32de831bdfL,0x1e7511a1bceaec3L,0x025955ad5fad042L, + 0x1eff7e153414869L,0x15c37ecb4d1dc48L,0x1e4a30e23109b3bL, + 0x13c016adcd50222L,0x0c1933e71359639L,0x004ddeeecd0bdb5L } }, + /* 221 */ + { { 0x1e39c1de4fd3673L,0x06ce8d32e4703baL,0x0771ca271ffbe20L, + 0x1c6a53a4008e4b8L,0x1c747af35b6735eL,0x177efae0fc79769L, + 0x070e573ce663e44L,0x0bbdae44c30930bL,0x123793a2f0e6979L, + 0x1355c6b4358e953L,0x0057788aa20b922L,0x0df9f3b71afc019L, + 0x1202267547be77dL,0x04e0876e04437d9L,0x00fb532d89a1f51L, + 0x0cdd53e387c2ef9L,0x124e6d5d7f05af3L,0x0175500dc68f7d6L }, + { 0x047fb701f357c74L,0x02e2554f1dbca2fL,0x1ccdba16a4164c2L, + 0x1f7c0489929e130L,0x03b5660df53808fL,0x1caf6b48eeefc9dL, + 0x083522dd8ddefceL,0x1e72372236f7672L,0x07ccf08bf86a13cL, + 0x1f6c7cbf500c72cL,0x090d0de31546514L,0x1bd3c1a5ab4d63dL, + 0x0f9b96259a8e6adL,0x1778beeefe15924L,0x1fe72165baf3abbL, + 0x17751ed296886aaL,0x06b48cd150f07d5L,0x001698ef4da60ccL } }, + /* 222 */ + { { 0x0bb9e1ede79499dL,0x147fc7e87e156d3L,0x03a069f64d5bdb2L, + 0x1fd1e0c64f7d81fL,0x1b300bebbc3d1c9L,0x1e0c0dc02e390b9L, + 0x074040108282104L,0x1ad3d342cfde195L,0x0076c909d1aeeddL, + 0x050ccbfc71d4539L,0x1fde9e9ded0a799L,0x17e8b929a7d279cL, + 0x07e6d48407aac0fL,0x148c90f3f9bb4a5L,0x076ef5bd599e78aL, + 0x1f533e47fc1e7dcL,0x165c7917566cbf9L,0x04b2c3079707a6bL }, + { 0x134702b7fa5f79cL,0x1ea132d796936f3L,0x0e61b1cf833a4c2L, + 0x1a9dc8945a8b7b1L,0x156c8a1a7dbe7beL,0x06fc076094f0124L, + 0x0966dbf7016b1dfL,0x15ee14d7456b139L,0x0fc484021999825L, + 0x09425aa3d11f85bL,0x084290a282a2bc7L,0x16625655edb163bL, + 0x1a33935ee3b1eb1L,0x077fd3767828a21L,0x1899531e81fac9aL, + 0x1dc982ddc810dacL,0x0527a7bc5014549L,0x0328408190fd4c5L } }, + /* 223 */ + { { 0x1f0e460b67ed9b2L,0x107e861b6c9e924L,0x0fa6231d7870336L, + 0x06c297819376b2cL,0x1a768605757bbe9L,0x16e2a24d4dc400cL, + 0x16616a2df8abd23L,0x0993cefdb3d6a34L,0x0dd025274ebbf02L, + 0x0c5b1440aa2e31bL,0x16bb4120036e816L,0x027303c54474737L, + 0x1c550cb4f27fc20L,0x1a903463ee337eaL,0x1a7e856b49c0cbeL, + 0x151459341795d02L,0x12f60606f213a7cL,0x04c14a8234c3132L }, + { 0x03746002e11c128L,0x1d72e8736e53f1fL,0x1b8b65548992037L, + 0x051016e287c8802L,0x126b881cf65f88fL,0x1c357f651e946a2L, + 0x1e563e71677477eL,0x09ea910c18498e9L,0x0d06ea43c9cb69fL, + 0x1a1e4d7399a7676L,0x0b3358d4ca5c4d4L,0x0806be74d818b98L, + 0x0cb372653ba95ffL,0x1128291e9700d0eL,0x089fac8c5443f7eL, + 0x19a21ddca71c54cL,0x14beadfc8a0ca23L,0x025bf370d9f3c7aL } }, + /* 224 */ + { { 0x1c9076fdb5f928bL,0x085db5b9a3e763cL,0x1e62b003b107989L, + 0x153b2c338ea96ceL,0x19e4343f900d20bL,0x0c9aebf6a160682L, + 0x00738f7ce7a1514L,0x1584c722304c9eeL,0x0ce8f2554e1f87aL, + 0x0eeb3c4b2fc8d55L,0x1458fe8c914e7ffL,0x1e589759d32b2d9L, + 0x0aa94f9ea55c815L,0x1792722aebc6461L,0x17709a9eacabfd3L, + 0x05045e1dac81239L,0x058954a420b00caL,0x00308e262e994bbL }, + { 0x192001ca9e81829L,0x199900451416678L,0x17863e77b66f7b4L, + 0x1b6f11200617fafL,0x1577a5dd6793ac0L,0x169e15dd806c8e9L, + 0x0405385e88e9e00L,0x00fff2bf119f6a9L,0x17cd1bf4bc71b6eL, + 0x11d925011ac4645L,0x0cd6e2904481d8bL,0x00bd880ada6136aL, + 0x0ce916a1b52481cL,0x0280bcfa2ae3a08L,0x1344822ef80c9c6L, + 0x1fca02bcd82ef67L,0x166509a24c090cbL,0x04103ca948e0842L } }, + /* 225 */ + { { 0x12d3cff1c7d353eL,0x1f666bef0671daeL,0x1d7db2a1d8d7579L, + 0x004bf35a7d69620L,0x005cb5aeda8404eL,0x1910d0b5cb1f449L, + 0x0b292797b836027L,0x069ac990bb3d483L,0x06a46c4e934442aL, + 0x037fcbf1e7b2ad2L,0x19707b9505f5f2bL,0x1353dd7f3898ecaL, + 0x1988da638868100L,0x1b5a39634adb0e9L,0x1fc45c5900ad1abL, + 0x00bc63fbca2ca16L,0x0a794f8f273be0cL,0x03a43d81b5441a2L }, + { 0x060e5759c3e2370L,0x0c0c9fc02438cd4L,0x1cf29b8be6a8675L, + 0x12c288e336741b7L,0x1effec21b6c7e95L,0x08675fd4824e3a6L, + 0x178562e8192c8fdL,0x1e5625045809343L,0x0b654b7d9b1d527L, + 0x03842ce87fe8218L,0x1d299d3c1511af1L,0x0a37475bb32a6f8L, + 0x0be33533b5e5532L,0x13f20ce7251f6b6L,0x146e5e4bcbd1340L, + 0x14d3e5b09dd054bL,0x1ddcc76b123db6fL,0x041a7c2e290fd1dL } }, + /* 226 */ + { { 0x09347c12ce9b31aL,0x029157f1fd9db99L,0x0d354bfe43f4762L, + 0x0c5634103a979dfL,0x0a411f0853b1738L,0x0db01d29c608dd1L, + 0x15d05e256e4f050L,0x10c532773556217L,0x1ccbbd046099129L, + 0x14fd7d8775055d2L,0x111888d598625d9L,0x11386cfff4a9a90L, + 0x1d1c3478da4a63bL,0x15301a7be5d6ae8L,0x06c4e4714ce489eL, + 0x1ea2a1cdae0bfccL,0x14cdd14b660f74fL,0x031cec58529995aL }, + { 0x0423162162217cdL,0x12515408e14737dL,0x186085d9b700b83L, + 0x1208d40dded1b39L,0x1de921015126373L,0x014c69a2775118eL, + 0x15fa4181f23c845L,0x1c24fe4e574c7b2L,0x1e7ce80cca5e8caL, + 0x00b75f1127bd31fL,0x13969e259cf8d16L,0x1444a6d757a89bdL, + 0x0ee3bf77af13756L,0x15e7cc5e3226b0dL,0x1ea58b182cafdb8L, + 0x000467616b3e653L,0x02cb0769a1aabb5L,0x02048189b063aa0L } }, + /* 227 */ + { { 0x0d2873a1670433fL,0x0a6fb12a49efe42L,0x066a03f3e27b24eL, + 0x01b652ec2dd60b4L,0x19e63046e39e431L,0x14e54f283a16e4eL, + 0x07437cc6b632077L,0x1a30d557f29f6f6L,0x036cda27a1b3c82L, + 0x18d177a1cb816c2L,0x0ff77118204a67eL,0x091ba472c470501L, + 0x137b3c9353e4b2bL,0x097dc53496d9617L,0x06011d356d6cc5cL, + 0x04af1f370f47610L,0x1c8d85909861e95L,0x040334776f9bd15L }, + { 0x0edcd35b39a0249L,0x1866a597c575771L,0x1791c88f7c16bc8L, + 0x15c1d26fe852b62L,0x0cbc9162bb66982L,0x04ee5080ce95b94L, + 0x01ed17144aba73dL,0x1d22369234ec61eL,0x148d4f34ca03874L, + 0x0fe87532265ba19L,0x1e6b87e56cc30f0L,0x1a9bdb16c15827eL, + 0x1f61ead81c40362L,0x04c61e944f418a7L,0x1485c0bb5803751L, + 0x03e66bf96383384L,0x0e9592329fc3a9cL,0x00233baa40def36L } }, + /* 228 */ + { { 0x03de56e39233c96L,0x0204e4039bf57f7L,0x06f4806af1a21a3L, + 0x165690c40b595c2L,0x0f19056c0f2cea9L,0x0e1520f191c3f0bL, + 0x0fa1ba9d4d96a97L,0x09aed8535982569L,0x0a01fcab78d6329L, + 0x0edf4458655cf92L,0x11b96fd05301520L,0x1127972d6f54eccL, + 0x117664e097fe111L,0x09fe7ad4db24fadL,0x1ffd8d2865908b9L, + 0x1312ab2f1937a16L,0x056b5feb38e3c22L,0x001c524fd8419e2L }, + { 0x1e3818c13e93257L,0x15e4ed3093a0d9aL,0x0925f2ab01ac533L, + 0x067b54222c9edd2L,0x0de2034a82278e3L,0x0dd31873e62b2f2L, + 0x1bef6edf7257c28L,0x1ad03bb3e46cd2aL,0x1c63e6319bb132dL, + 0x11158117e12099bL,0x12064dfa2fac71bL,0x129bb1927158470L, + 0x0aa6bb564483b19L,0x037c8c03daa67d6L,0x1e367cc69f35138L, + 0x151cc3ba8737751L,0x060660c2a787f74L,0x025dbb711090dabL } }, + /* 229 */ + { { 0x0151e8ae6354817L,0x04a75781c5a1c3dL,0x1a2216562618cf5L, + 0x0e3b975824990d8L,0x00edad067215382L,0x0072eb7a43d7c66L, + 0x1fd56b4cc147f94L,0x1aa14e23637adc8L,0x0a68709a78c746aL, + 0x1f8b931320179afL,0x023bebecc304c09L,0x008380d8e92f8daL, + 0x0edcc3e2da9ef1cL,0x04970839e863a76L,0x084add0c317e5b8L, + 0x1d6041e27279e55L,0x18b245840162107L,0x04421e92fbdbb7cL }, + { 0x01501dcedb2a83eL,0x147d815dc6b9227L,0x196764977d8af3fL, + 0x1e8556df8612040L,0x00f09dfd3c715dcL,0x0c857539e0282adL, + 0x1d278499d17638dL,0x0c6a705e9b0edfeL,0x0fc69feefa920c6L, + 0x10b0108cfeb88e5L,0x070ef641d713577L,0x17a27bdad7e4843L, + 0x0b6263a1163800cL,0x1e93261bc63f507L,0x1672630d6f5e561L, + 0x0e76aadc45c8ae2L,0x14971bf2a2dfa73L,0x00281fc9cc49ae4L } }, + /* 230 */ + { { 0x1addc6671dad4f6L,0x124448125f50db2L,0x038bd8174f748e3L, + 0x1d61b2d713f6ed9L,0x0601b2cb13d5f5dL,0x11e92a705add1abL, + 0x03a9f8df524760fL,0x175d10c08464819L,0x1374182f3e91c99L, + 0x161657cd43d6c8cL,0x0c102bd5d3ca549L,0x1da328800146962L, + 0x1e06df42e75b9bcL,0x05e8844ea6662bdL,0x16ed4008ba3b141L, + 0x1d5b618a62ef5bbL,0x0f9690d31d29ecfL,0x039abbc7f0bb334L }, + { 0x186ee3e843c1137L,0x0217d1f85b9e687L,0x1e762ac838e8f07L, + 0x082c485f5c1ceacL,0x19b092e46f95f1fL,0x11b5603dc4708e1L, + 0x00b9858a500f930L,0x064cc20be825b58L,0x174dc28a7862e06L, + 0x08c7fd979d91e46L,0x0905f01d17fefc8L,0x1408980ae23c230L, + 0x14cefbe4de49b55L,0x0bdfb88396332dbL,0x13c19d873130076L, + 0x1a1f165940db58aL,0x0a1fc599daa7450L,0x029731bd30d18c1L } }, + /* 231 */ + { { 0x01700f16bebc6dbL,0x1a2edfca81ec924L,0x14f17454e46529aL, + 0x0bcb5a55798e2b9L,0x0b7b466f942a1c0L,0x09c8c59b541219dL, + 0x19b3ae904efb6e8L,0x194d314ac4921e9L,0x1bb720da6f3f1f3L, + 0x08b6a0eb1a38d59L,0x14889cc0f4d8248L,0x18008c774d3dc01L, + 0x0d62845fd17fd4cL,0x0056e4e3d6304f2L,0x1ebef298d80ecb2L, + 0x129577e2df9348bL,0x09841007f7fc4bcL,0x03e48b5a7d3a58bL }, + { 0x1026f9178bac2d4L,0x1404c1300d43ae0L,0x1db801cf590228bL, + 0x09f983f7115a5e4L,0x0a6b291f443610cL,0x16307e2b93dc116L, + 0x1522c19154cb223L,0x006a3c91133db35L,0x1841b48b5f543f1L, + 0x16658df6ac8e775L,0x0b7c3e773d6a2e9L,0x0041668fbb69f89L, + 0x02cb44c5213a7caL,0x0293e062550d666L,0x08f3d41dceda0a0L, + 0x1924d546e9820e0L,0x07c733d10006b74L,0x00ff9c8b7bbd468L } }, + /* 232 */ + { { 0x0218fe4f997939dL,0x0fdddbc8ac1d9d5L,0x176a1fdd582cf53L, + 0x02bb525931674f6L,0x06666f4aa9c0280L,0x074eebf0f5a556aL, + 0x0c1d8bac5e94453L,0x0dde8d4cd49df1eL,0x1900b45c6810e54L, + 0x1d7912c25d7826eL,0x0721c9721350bfdL,0x044b1c9907bc798L, + 0x01170d88b23093fL,0x1603b722317d6f2L,0x174506f86584b92L, + 0x069b5e91ae68c65L,0x0c9c1b1f759925eL,0x00cf68d2b0395c8L }, + { 0x0f7fcde6c735473L,0x04733b001de1f4eL,0x12f3ec666ee2aaeL, + 0x033599997a2430fL,0x10f65459bb73044L,0x09314110a57f9e5L, + 0x082e1abb2068dbeL,0x121550596653f3aL,0x182f3f90f5773ccL, + 0x17b0735fb112bf0L,0x0d12fef51d8b7d2L,0x0253b72e0ea7e31L, + 0x097c22c18e3948bL,0x0bdf4bd6e374907L,0x0d8dfe4e4f58821L, + 0x1a3abd1ae70588dL,0x199f6625ccbf1feL,0x03798f07cb4340aL } }, + /* 233 */ + { { 0x05afe5582b8f204L,0x020db69ac5aa562L,0x1efeb357d7b6b01L, + 0x1627379b26e427cL,0x16dbcbb01914c70L,0x09ae90b8a5a2c0cL, + 0x07c83a4a5f4d47bL,0x00b1ec8106ed47cL,0x1150a8a9d2f3cd7L, + 0x19b7400ee6ecfb6L,0x13ad9573d5b60beL,0x00192554b442b4aL, + 0x023b089f0376105L,0x0215b3746886857L,0x1ba3521246c81e7L, + 0x0de8a95e35c7a1dL,0x1e6137e4c284155L,0x043af198431ec53L }, + { 0x080fddcaf6c0accL,0x08f335d8f3e046eL,0x0b860a1616b756bL, + 0x004eb8fb4db8e2fL,0x126b9e15bdc5434L,0x02fd287a5a64296L, + 0x12cc97c287efda8L,0x03b8df03c8f02f7L,0x02cbd432870ff2eL, + 0x112480b33e3fbfeL,0x16b2ded6169b122L,0x15a88ccd80afa08L, + 0x0fe6d7d63d2e972L,0x0713a0a263a6c3eL,0x09612bbdc19f61cL, + 0x1fbd765942af516L,0x009495c5bfb75f0L,0x02d5d82c0f9c370L } }, + /* 234 */ + { { 0x1e62d2bf0c97f57L,0x02438cb179463c5L,0x119d1ed42aec3f8L, + 0x0689f413db8a914L,0x0b05a96ef6b26e0L,0x1357417ea26371dL, + 0x02677b6c00cb1c3L,0x184517a8057afc9L,0x043f2e9639b7c11L, + 0x161fe0767489b8bL,0x0e2f240bf43e303L,0x0754f9578758ed3L, + 0x1206924cc99d9cbL,0x0130480a7445444L,0x0b9e782945186a9L, + 0x07d018fe955172cL,0x0bc4ef0210a8b1bL,0x0382a23400dff72L }, + { 0x0b3d713121901c1L,0x11313ff56aa557dL,0x0a16f022e88fa42L, + 0x0a6dd844fcc9edaL,0x06c191ab8d99301L,0x04e7164cd0b55c8L, + 0x0ea021ac73d6fd9L,0x1e0b240ceb2cd7cL,0x018836279ccba2cL, + 0x00abdc3f7fa9a43L,0x1262592c88ebc8bL,0x09e0155cf4af7f5L, + 0x0063218a80cd0fdL,0x0fc478a76d6edcaL,0x07b67f4e112ede7L, + 0x0a06d8367c7a96eL,0x06b6c634a13d620L,0x037ab5767dc3405L } }, + /* 235 */ + { { 0x01dc803d9205c5dL,0x0afbeb3891c94d8L,0x1ff6766d9595a25L, + 0x1da76359fc7bd77L,0x0094eeffb844395L,0x0c8ff582194590bL, + 0x141d598c7fea08aL,0x00a1bbccdcc321bL,0x175b03c55e8577cL, + 0x048e72fc8b91203L,0x0229023aece8fdbL,0x1f140b14272d345L, + 0x179a6e06761d376L,0x1db8e94479d2ca2L,0x130c30040c0a715L, + 0x017381087e85168L,0x0add8e6aff8730eL,0x03db5f408a76b22L }, + { 0x0c38e4a3d3aa54eL,0x19ca1ec1ea84d1fL,0x188490e55788408L, + 0x0fea3a7a89f0954L,0x1eca4e372910471L,0x1d2aef316922163L, + 0x086d6316948f617L,0x0d18deb99b50a3bL,0x0044bcaa8200014L, + 0x1a80f34700b8170L,0x064d679a82b3b3dL,0x0d5b581de165e10L, + 0x08fd964f0133ddaL,0x0985c86c4bd776eL,0x1048bad236b3439L, + 0x143bc98bf5adf70L,0x0742284ec1ed700L,0x0437cd41aede52aL } }, + /* 236 */ + { { 0x01d9055450cc69fL,0x18a5e64f6fcc787L,0x19dfb9fae80543aL, + 0x0f331f1ca637729L,0x1b16eef05f7a673L,0x0e2f0aac41c2718L, + 0x14aaaee4a1c8f61L,0x0e9fca3c68b97b2L,0x0c5d0ee287e2416L, + 0x0e0a3778800c178L,0x0e7a4b9fd6f8b3fL,0x075f6cad7a7c1eeL, + 0x1e5168e289501abL,0x1c77082558aa96eL,0x0c111d65037f8c6L, + 0x1522685246c0788L,0x1869306f114c460L,0x02dfd4fd781da8fL }, + { 0x023f52c107b258eL,0x1415deb31a0ee15L,0x1b6208f3fc6a627L, + 0x08e336923ea9479L,0x0433dfb8f45b779L,0x09287744c6110c1L, + 0x1d9543e77647312L,0x08aa185455c9f42L,0x1f7aa1ce42c327fL, + 0x1d0ad6b2c1d8f20L,0x03569686feb6784L,0x14511c3f7b9b354L, + 0x16915f7f879b1caL,0x03f40d0f57c941dL,0x0034a5b04393832L, + 0x0b7b009fb94ac21L,0x0da6acc96161275L,0x00d8933554147f7L } }, + /* 237 */ + { { 0x0bc0a00774ee49cL,0x1b42965b11beba7L,0x12b177e4e28dddbL, + 0x116df7f77bf80a8L,0x145f2eaec3388ecL,0x16749bc25645e6bL, + 0x1e84ea7159826c7L,0x0e2cadf6d58fbd1L,0x15f8ded74a532b8L, + 0x186a145d5444f84L,0x09fca042debb0aaL,0x1c3dfdd96698876L, + 0x0b9e89c2db26426L,0x1c90884822218dbL,0x1604162ab12f174L, + 0x1ec1d24dee6d09fL,0x023452fa691471eL,0x019a8bfed90c6bdL }, + { 0x1c33f46593c4a36L,0x0eb8c1b58d4f754L,0x107509defbb2b1aL, + 0x1cfc9e2f38ab441L,0x146d88a23e8ca24L,0x03817c2b9b99b4eL, + 0x155d1c73ac731ccL,0x18516309b2e6bddL,0x17f4517a20704ceL, + 0x1894e8c6b831529L,0x115c6ec75df871fL,0x061306a1b1640f4L, + 0x1f61fab8ef774acL,0x1aeec00d93d948cL,0x0d1647e9f13304eL, + 0x12567cfcc4ab628L,0x149349937b85a35L,0x018fd631e9863baL } }, + /* 238 */ + { { 0x0e8cf1b04913fb6L,0x009a80bb4d35997L,0x0dc5e0f987c1f90L, + 0x13c4fe5ffcf21d7L,0x0daf89bf1e5107fL,0x06f3468925d33ffL, + 0x0afb86248038796L,0x1552c4e6546dbebL,0x072cc37cfacbeb4L, + 0x062fd4b749e2d3bL,0x08c5f3798ce4eecL,0x1ccf06165ad8985L, + 0x041be5b96a97f65L,0x19867336a57e1a8L,0x103613c2fd02981L, + 0x0d6112d4374f326L,0x1f53ee182540762L,0x000ed9aedbd5865L }, + { 0x00fbc2dac0efee2L,0x175e6eb8edda2b7L,0x18f866da6afa101L, + 0x026fc03045ce57bL,0x11458b4c49cb7e6L,0x1e2eb1e5dc600e0L, + 0x19dd9082d211da1L,0x030308fbf428a98L,0x0bede911dd1839dL, + 0x1cee4e493c6f823L,0x0f58ae2068cdb06L,0x10f327cef5b8529L, + 0x0543ce3ba77f096L,0x1bb2777e3d64833L,0x111973c521a57f5L, + 0x19b63c1841e1735L,0x01d636e8d28a6e2L,0x03db5d4c66baa9aL } }, + /* 239 */ + { { 0x11d9e03c1881ab4L,0x12eaad98b464465L,0x151ca08d9338670L, + 0x01e2c35449505a7L,0x01ebb2c99599439L,0x163d3abc1c5e007L, + 0x0882a3f577f32f7L,0x0909ba407849feeL,0x15ec173b30efeffL, + 0x0f8e9598b21459aL,0x0f679415ba04fe6L,0x0575816633e380dL, + 0x04fd223b1592917L,0x0c6848f6b57071cL,0x151923af404167aL, + 0x1cf30d662d1c94cL,0x1082211447f3375L,0x023f4080cb8f5a2L }, + { 0x045d45abc8c290dL,0x089aac087d99d38L,0x02491beefcbe8cfL, + 0x1670b8f9b2575e0L,0x0161985cacff3f1L,0x0443a462d8a8767L, + 0x173231bb829fcaaL,0x0873b11191cbd11L,0x04dd735f2ccb864L, + 0x00f09db9e207b79L,0x0897ffcffb5a473L,0x162e4afdcb8ff87L, + 0x13f32db1354cb43L,0x016ff969d532a7cL,0x1298e5113d63428L, + 0x0cd2ef1c7e31151L,0x07b39646ccef3e8L,0x03c2d8c81706e74L } }, + /* 240 */ + { { 0x0ce2361a92f9a20L,0x0e543ceb22a077eL,0x0a1474035f16defL, + 0x185d2f924da8e73L,0x18da6a8b067ac8dL,0x028db495751fff3L, + 0x05069a0a2fd518fL,0x020ede388f2e2aaL,0x0f4bcbef63977d8L, + 0x0de24a4aa0de73dL,0x1d019b45c10695dL,0x0b7b0eeabd5fc03L, + 0x1d59e7ae80d282dL,0x1c1559b7b71083eL,0x14758d2a95b8598L, + 0x1b088cbdd1ded73L,0x02799a2160ace4eL,0x032abe1b3dbb896L }, + { 0x01b0268d75b6e52L,0x09b2008c68744abL,0x0cc1a8bac6bac20L, + 0x0cda1211299fea6L,0x15fc1d484e46222L,0x118316dd9a8913dL, + 0x0b7164d97a81d5eL,0x10e995946f7acdcL,0x1220d7d23b90958L, + 0x007e9c9c62239dfL,0x1cdc299e1f693e7L,0x1799a0afe9715bfL, + 0x0c1173f33aef0aeL,0x092d135a102f3a2L,0x0beeff6e347c296L, + 0x1a509526c9e92e4L,0x0b4c891ae778227L,0x00ae20682507045L } }, + /* 241 */ + { { 0x1af169a2a0e18d1L,0x0e00ba60193e14dL,0x08fdef098b3a65cL, + 0x1b031fe6f3b0346L,0x0cd3c3302099db8L,0x0d02a9b31fb31eaL, + 0x091c3bd4c970c04L,0x0e139ae17b9f301L,0x1e64452d11c9ed0L, + 0x1dfa1fa5633b709L,0x1b029aba170a96bL,0x0aa08e0921892f7L, + 0x07491e6ba92faaeL,0x157d4c8a055cbd4L,0x1c9955d0157d4deL, + 0x1ad7ff92b5b766cL,0x037646343b9d119L,0x03c474a504e9a0fL }, + { 0x13a6fe59c53461aL,0x044bf0471db7682L,0x0bcc1da364e5d7bL, + 0x0d98427a9f51ebaL,0x05b0147c9bd6bffL,0x1dc0b4ac863da08L, + 0x1e3a4828d8a2df1L,0x11f8cd410dcb79cL,0x13dd4d2824dec1dL, + 0x08567a260cee674L,0x0b61d7610d69fa2L,0x0f83d4c70364cc6L, + 0x17f0dcc12859016L,0x037c6a31d912cbcL,0x17be8e646984ad1L, + 0x0cf108430baf182L,0x093df55ec37119fL,0x048d8ce633c06f5L } }, + /* 242 */ + { { 0x1f2709dcb5d8b80L,0x0b0c17e1ab30775L,0x0644157be5a40eeL, + 0x1bc8f8868570e7bL,0x154f8867d1ea4b4L,0x06bbf7e625c9226L, + 0x1d58e4ec68b2bf6L,0x0ac0d1a49cfd183L,0x15f5fabb6499730L, + 0x192462802a11ba7L,0x178ad4fce3a44e0L,0x11d6f76d017d86dL, + 0x17d8f313b5ed07eL,0x17e969c94b2409eL,0x1228c69eeda81a6L, + 0x1864b80db091c10L,0x1af6867fb2fe4f0L,0x01e15d41a0339a1L }, + { 0x162d7759d3ad63bL,0x055cbacf0758fd5L,0x098ce217845cfe7L, + 0x1dc4165f3ce0665L,0x09eca947f22cafcL,0x146c46da94dd3f2L, + 0x055849255085988L,0x08901d447d87247L,0x01b8907e7d43706L, + 0x1bfd22aab1f2722L,0x060a7aca92c3e92L,0x0148900c0f25995L, + 0x0c246991ced0a72L,0x1a468435c666ed0L,0x02bb84cde88c96cL, + 0x04a7eacddaa13ecL,0x1d83d30e091147fL,0x00fd313d2e0839dL } }, + /* 243 */ + { { 0x11222a242478fd4L,0x06378b385900050L,0x013e0d671b7ab3dL, + 0x12f7279b79ee376L,0x030db60b618e282L,0x0d9d94cb70dd719L, + 0x15777c5ff4ed259L,0x0ff4b0c738d78e0L,0x0c3ea92ed4b817dL, + 0x0415953691d8452L,0x048a2b705c043a4L,0x1c8c41d13b2f08eL, + 0x1703ff77c9753b9L,0x15df3072e7bf27cL,0x03805f5b0fe0914L, + 0x0bdb73c86597970L,0x03e150a5acdc0a4L,0x033dc5e82a3cc3aL }, + { 0x06079b4f4797cf7L,0x04cc5681fef0173L,0x18e9532abbc78c7L, + 0x1deec92e22b546eL,0x0f29b1a764d9a1fL,0x136549be706e39dL, + 0x1a9e19986c20fedL,0x0c37e9ae9fc65f6L,0x125f6ef09df00a5L, + 0x1e21c1fc18e88acL,0x1304314daf78dcaL,0x1f3f10598cb6dabL, + 0x13451a99b8d4945L,0x15d608d240fa478L,0x029282850058735L, + 0x150493b29a9dbe3L,0x0df65363165a467L,0x03a14bd54d264d7L } }, + /* 244 */ + { { 0x09758a4e21124baL,0x0c0cc543ffde962L,0x1744f598e2a266fL, + 0x102bef7eec8bf79L,0x04e6d57e94645ffL,0x130edcafd339b7eL, + 0x051287ab991d64bL,0x0e8f2aeb81997bfL,0x0a3d1304725b31dL, + 0x040ef912655ad73L,0x1f4a6468a21fc9eL,0x0b2144d588b31b7L, + 0x12d8661d4a23d07L,0x0500a07b972c4c2L,0x0cde0a8ded704eeL, + 0x09d201f28333c7fL,0x112722aa0591bc1L,0x044d55bdd6aadddL }, + { 0x1345a96d656bdc7L,0x0e457f0bb669dc5L,0x02d8cb59310d0efL, + 0x0ef3705683ad2a3L,0x1fb0cf82fcf364aL,0x00943dc83d9a277L, + 0x043bfcf4320f144L,0x0b9d3e4d4b2699bL,0x1e5f5aaf207082bL, + 0x15b963af673e0b2L,0x042a06fa61b3593L,0x131ffe2a6d55d2bL, + 0x03a8263d5efeef4L,0x0a574395822b012L,0x081da1a502f853dL, + 0x09af57dcf7993c6L,0x146d496a27dc1bcL,0x00016e14baca055L } }, + /* 245 */ + { { 0x0533937b69d60c3L,0x1f2a97f4b93aaf7L,0x1e37031c9698982L, + 0x1d9565cf85623f6L,0x0e2322cb6982c27L,0x13827ba5e776ecfL, + 0x1859654ac67b448L,0x10a5be9850b0a94L,0x0ba40b5bf7b1924L, + 0x05e54a8008cfa95L,0x1f472f96b761bffL,0x0df7b3a1e582e8cL, + 0x14b8d4ebc99bf53L,0x02d4098b9e14b71L,0x0cd7dd81257e3d0L, + 0x0424518b3d1ace6L,0x0730b53d324e054L,0x026ab229a9e1dedL }, + { 0x122f8007e5c0877L,0x1a1f30654d3b239L,0x1d2e8b049c59206L, + 0x0fda626d84463e9L,0x18db30de0959685L,0x08475e574131911L, + 0x08c7994beb50266L,0x092171a30295e1aL,0x02680c54b09cbc3L, + 0x0a2b179a5f9dfc7L,0x14242c24ad657ffL,0x1948bc2bf868530L, + 0x11bc378168e6f39L,0x022d2543b80ba8cL,0x085506a41a512ceL, + 0x19169598dae9505L,0x062adc9bab3b155L,0x00f97c4e73b9836L } }, + /* 246 */ + { { 0x053ef419affefdfL,0x1f672a67c92b5c1L,0x0bcad113920c175L, + 0x1f974a8e3e6ee00L,0x15cbe015b189755L,0x05c214e44241e5eL, + 0x1d874953df1a5a8L,0x0ae310a17a8c3e7L,0x17ba210890a2471L, + 0x0d5de176c977586L,0x1b2afa5977b224dL,0x0e4978aad095f6aL, + 0x0f6a7a74929da23L,0x177a5d236c5d1cbL,0x026c9ebf2e436dcL, + 0x06cddba469fc132L,0x147bdf3c16476f4L,0x004e404bf8bf286L }, + { 0x004b14060050c07L,0x1418c21d471bf35L,0x06caed57907f0a7L, + 0x1459cc1c7597285L,0x1b9d82f4ed2fea5L,0x1e9bfd6e3d8ff9eL, + 0x1d4e523afb30da1L,0x124f22a7c65d960L,0x06a60054f570756L, + 0x038e6864003acddL,0x1ce1bcc248b7c4eL,0x0b3d066af6f82f4L, + 0x09394151864e9fcL,0x09a6dc448e9359dL,0x1f36dc644a8088bL, + 0x0606ccce5f9e8b3L,0x16c5a3f268d44ffL,0x037889f69b488f0L } }, + /* 247 */ + { { 0x0a9df591836f1c9L,0x08cfaa119183ea9L,0x1c0577b4a16be99L, + 0x155ec4feeb080d8L,0x0ce0417d0a1545cL,0x089a21d70888f75L, + 0x12f2feca2f7da98L,0x0b1bd3de156a5b7L,0x1e9dc181b7813e6L, + 0x18ed5edcc893912L,0x16638c8a0531642L,0x0cddb269dcfcbe0L, + 0x1ab99ba4bf5c3b9L,0x1e0daaf3a75c276L,0x0aa183eca4668d0L, + 0x03fed535bb69329L,0x1e21b7220dff681L,0x0331b511de8d0c1L }, + { 0x15d5a2d20587283L,0x01164f783fe2eefL,0x15543bdb78e02ceL, + 0x0e4ba2ce3a2f0d7L,0x1cdb1def163cf90L,0x017e253a5fcb8f8L, + 0x153dd5d27a0c021L,0x1961c5db78e4ff0L,0x1bb27bbdabce24aL, + 0x0d8ce7602df6846L,0x0848fbdf2412f30L,0x1e37b13305b755bL, + 0x0e65f6e63202429L,0x172cfe9924e9b0bL,0x07ca7d68de27ea3L, + 0x0f1402c174775fdL,0x0f80f2d3b61af53L,0x03d77663b39e153L } }, + /* 248 */ + { { 0x1a4757cdc43b0dbL,0x12742cc08ce56f9L,0x0fd9185b0558f62L, + 0x189ea67d2ff012bL,0x19cfc5ad3e2a07bL,0x14029654c121b39L, + 0x1b198629ae8eb35L,0x12b7ac1cb211439L,0x1ae3841a502b1b6L, + 0x036ff890c850cadL,0x0afab2b4c7f66e6L,0x044998e51ef65beL, + 0x180cf0a9927d893L,0x0c35227561c7539L,0x057c0f2a10e6a01L, + 0x1f10bdbcfefe02cL,0x0454824990827a1L,0x0147620035bc53bL }, + { 0x1820c2ea2fe0009L,0x1d2e9789c3a74f0L,0x115314936d4b846L, + 0x0cffdbca532ea44L,0x1b2500d44d47742L,0x14922580e9a0cd4L, + 0x186e73822924861L,0x1c1742d2047ba37L,0x0242c3e5432a301L, + 0x1ab7bdd384833c4L,0x14a8271d2a33126L,0x1083aedf2873e15L, + 0x0b621fb60e99cd1L,0x1e1cbb1a76ed7f0L,0x1fc2a1015afb952L, + 0x1815e8ca7f0c1feL,0x1c36bd4876f2011L,0x009a7a663864a92L } }, + /* 249 */ + { { 0x021a3ece938dff4L,0x00d3da4353cd1cbL,0x1e5f7a5414ddf44L, + 0x13ccbb0fb7e589dL,0x173b8cfaf318409L,0x0148b75c4e3ffd9L, + 0x09d91a2ea9417a1L,0x0574f21fa129d7dL,0x1679df6d4e59289L, + 0x011998e7e7f6ba0L,0x13bf4a6203fc848L,0x1bbba0688a0217eL, + 0x0b342858c87ca78L,0x12baa43d16584f6L,0x12c1246797adb70L, + 0x1a8e2a0ceb42bd7L,0x0f409d2e74f7381L,0x03751bc14c1e9ebL }, + { 0x05c094b4e5cc40aL,0x11fb50d79befde3L,0x1a77e409b911e8bL, + 0x0b27101ea7decefL,0x1f644aa9b7878c9L,0x10461e25518583bL, + 0x198ee83145a0cbcL,0x060f804ef5ccb1aL,0x0ef0b3c38ae1d91L, + 0x0179bd3b4ae1f52L,0x130715a8317834cL,0x0b8841979f3fc00L, + 0x1d568a0e7c9fd49L,0x0c94322a3836adcL,0x069c2722c8977fdL, + 0x11ad0a4fa88cb1bL,0x07d47c558da87c0L,0x0303773735da778L } }, + /* 250 */ + { { 0x0d99fc757c621f6L,0x12060bff41ea401L,0x1e867bc666c0a4bL, + 0x05cc58eccc37bf8L,0x0673875378a0410L,0x1d32d78b66d1b87L, + 0x18826f2065d3478L,0x18c32e84091ef1fL,0x1c83a058abf5981L, + 0x135921a4e44b816L,0x0cbc7a74699e2bcL,0x1361fe535c53311L, + 0x181d7cf5ec472bfL,0x19346eec50a1f1cL,0x113fdda7275f916L, + 0x0ece62cd9b4aabfL,0x1076044cdf0a4aaL,0x024edd37bf48a43L }, + { 0x0e47fb2a758e37aL,0x198eb96c757b310L,0x17e5be708842bdaL, + 0x0f21df86566a55aL,0x01e4b2640093f72L,0x18abcaa1ae4cee2L, + 0x0d5d6fea1e38016L,0x0b3338a41481cceL,0x1ca68259487eea7L, + 0x14fbdc0f8951a45L,0x1f3060aa8b38d40L,0x0e97d5abc58b4a8L, + 0x1b55682cdfa11d8L,0x05df47334d781a4L,0x14e52afe1baffaaL, + 0x1d71e7b570f05eaL,0x18c458bf797ebc8L,0x0244853d24dbef3L } }, + /* 251 */ + { { 0x12996898da995f6L,0x15573f630ab77ebL,0x1030d5aa0b574e7L, + 0x03826b79fcd2b20L,0x0f595c78b2046b2L,0x02fda0753905b20L, + 0x0eff00a093beb9fL,0x17d2fb1fa981db6L,0x112f0290579f24eL, + 0x17e23e78c3f535cL,0x07f49de275708c5L,0x16d9124c7d99843L, + 0x128b6d30a6233a6L,0x04d99b40411b1a5L,0x11dd15b28d4b897L, + 0x00cb72711ad9481L,0x076f8e55b0b3c92L,0x02e0ba3a58121cdL }, + { 0x088e7c28aaccab5L,0x13c1b5567682decL,0x1df733b03d94600L, + 0x1824b8510430b70L,0x07fdc54c93cadc1L,0x1c4519a2efaa053L, + 0x1e8b13cf21b8b09L,0x19e7d0e88d3c741L,0x1c59daa47273983L, + 0x031e245a54b6c52L,0x14af3f0b962454cL,0x170f09c85187871L, + 0x0cf0c4fd5390e78L,0x0a0f3002c805149L,0x094e872dfe4b6deL, + 0x01f4f2acf2482d9L,0x08c35f6f31db1abL,0x02eb3af5a3dac20L } }, + /* 252 */ + { { 0x0ee1a77870c6025L,0x111dbc8d16fe557L,0x0310e1ad9313f12L, + 0x1bcb5ce562f61ccL,0x1eefa212d5d5b17L,0x01c5cb36fe44564L, + 0x0bb313fabbefb50L,0x00e133586ad1c5aL,0x0548ea612012af2L, + 0x1ff6cedc4e1890cL,0x1a47138399ccc53L,0x0c9f5f0601c0383L, + 0x1c6773c3be009bbL,0x00410cfd43c0280L,0x06c1bff8335bb7bL, + 0x166def80abc0ff0L,0x0a382b63f9ce080L,0x0017e65d7854ff6L }, + { 0x191d4d1b47cac61L,0x08b43d5c370964cL,0x17b0ae53c108ba7L, + 0x1291cc91cb18d0aL,0x0f89ac57ca40051L,0x13c966cdd48fd97L, + 0x078553d0648186fL,0x03305a443977a1eL,0x0062eb13bfc4440L, + 0x1d4be194cbc87eeL,0x05b651819e992fcL,0x0600da46eeb49cfL, + 0x15ed7f0f23c46ddL,0x1da7b1ebc339626L,0x189cfca08614770L, + 0x01edea1475c19a4L,0x145800e58fceac6L,0x02b78f22b09c22aL } }, + /* 253 */ + { { 0x1ccb3f632c24f3bL,0x18e3f836c0bf300L,0x02edaa899dda67aL, + 0x1c108babc11b8c8L,0x181a79a87838affL,0x140cd879a7f658fL, + 0x092e1a8b8a0b4f9L,0x0738972ef9d046fL,0x10f46b3db876364L, + 0x032faa04bcb824bL,0x021d8a1e46f90e9L,0x16d868331d8dafcL, + 0x17093d94bb00220L,0x14eb48592bd9c31L,0x0ab46921004b858L, + 0x069c605d93b6a41L,0x0f8afee2fc685dcL,0x0488e8c9b12a806L }, + { 0x1b1bd58f5e5af5bL,0x1131dbdb5115389L,0x1137cebcab729f2L, + 0x134088417b56d7dL,0x0ba36c1116651e5L,0x0121881da2459daL, + 0x1b2ecf18aff37fdL,0x101bc2b894be352L,0x0be0ad8a1e4d1f9L, + 0x095e8a71b339d1dL,0x00ebda484ab3760L,0x1738aec12b9c806L, + 0x0a107f5ca58f6daL,0x044b51d83ef8c41L,0x18ecfc2e40f98f2L, + 0x10fbdea090a89b0L,0x0655e5019b9c098L,0x015f3a27f507a9cL } }, + /* 254 */ + { { 0x14cd05f5b50f324L,0x0f5920f51e3d102L,0x0971ffe39adee6cL, + 0x1dd8081104950b1L,0x10cba9bdd83902fL,0x0e4f0f3959324a6L, + 0x16e07405dbe42caL,0x1f80ba9d6059d75L,0x0874405b1372b8bL, + 0x0209440bcf568c8L,0x08f74fb0ad23357L,0x14ee7e9aa067a89L, + 0x0d564c3a0984499L,0x1a17401dd9bd9c6L,0x1d462ca03a6525fL, + 0x1fbc980f68f4171L,0x07ac710e3c53568L,0x039afaa17e75687L }, + { 0x0a9a17138380039L,0x17f0bfba68ce465L,0x04fb32f06a2eb7eL, + 0x13fc052e0b25a87L,0x130e9b363c5dbf3L,0x1ea4a522a95ad5cL, + 0x0b10dfb98c0c8abL,0x13104d535ae7e05L,0x198c53562993562L, + 0x0434fc3b9a15d9cL,0x04008393e6de683L,0x0349a68f1353aeaL, + 0x1acfa856376361dL,0x045603f2786f6adL,0x1bc72f501fb9cfeL, + 0x0b75bf58fa07e13L,0x19e25d697cb4d47L,0x00f4c264e8a5e9cL } }, + /* 255 */ + { { 0x16d05614850c817L,0x12d8c9a44c096e3L,0x055179632efac22L, + 0x1497cc3cb4e4e7aL,0x17aeb8e18900b5fL,0x0d1ea5d5044348eL, + 0x1f4f799999abf4dL,0x0b871458332afd8L,0x0a0648e8f668d6fL, + 0x1cfe4963d6e0ba3L,0x045b0210c1970c7L,0x1440c3cd5cd2474L, + 0x162aa47e7336370L,0x0f7fb6c231361b9L,0x0fb4b51503097cbL, + 0x12925300904999bL,0x0014b5bfce0039aL,0x03623a52b3b4a17L }, + { 0x0eb9a417d88e3a1L,0x09e4462423a151dL,0x0344ff9844c4417L, + 0x16350d3d17cb3bdL,0x0a75d90a148f5b6L,0x0a3009bd455e2cdL, + 0x13364bc326f1d88L,0x12487f54e8f8704L,0x081763a186a5d0bL, + 0x1e1a0de4de5d75eL,0x04c583dd174776eL,0x0a5b6eb9cbe9c30L, + 0x0cd50de4c2a53ceL,0x1aebb2b68af5733L,0x12954a97b6265b1L, + 0x00b69c9feae2389L,0x0ce215e985a3c53L,0x03592c4aa7d0dd1L } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_18(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_18(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#endif + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[18]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 18, km); + + err = sp_1024_ecc_mulmod_base_18(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_18(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[18 + 18 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (18 + 18 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 18; + + sp_1024_from_mp(k, 18, km); + sp_1024_point_from_ecc_point_18(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_18(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_18(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_18(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_ecc_mulmod_base_18(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_1024_proj_point_add_18(point, point, addP, tmp); + + if (map) { + sp_1024_map_18(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_18(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 18]; +#endif + int err = MP_OKAY; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 18, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_18(point, gm); + err = sp_1024_gen_stripe_table_18(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[18]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 18, km); + sp_1024_point_from_ecc_point_18(point, gm); + +#ifndef WOLFSSL_SP_SMALL + err = sp_1024_ecc_mulmod_stripe_18(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_18(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_18(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_18(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_18(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_18(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_18(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_18(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_18(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_18(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_18(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_18(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_18(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_18(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 18]; + sp_digit tx[2 * 18]; + sp_digit ty[2 * 18]; + sp_digit b[2 * 18]; + sp_digit e[2 * 18]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 18 * 2; + ty = td + 5 * 18 * 2; + b = td + 6 * 18 * 2; + e = td + 7 * 18 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 18, base); + sp_1024_from_mp(e, 18, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 18); + sp_1024_mul_18(b, b, p1024_norm_mod); + err = sp_1024_mod_18(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 18); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_18(tx, ty, t); + if ((e[i / 57] >> (i % 57)) & 1) { + sp_1024_proj_mul_qx1_18(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_18(tx, tx, t); + + XMEMSET(tx + 18, 0, sizeof(sp_digit) * 18); + sp_1024_mont_reduce_18(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 18, 0, sizeof(sp_digit) * 18); + sp_1024_mont_reduce_18(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_18(r, tx, ty); + err = sp_1024_mod_18(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][18] = { + { 0x000000000000000L, 0x000000000000000L, 0x000000000000000L, + 0x000000000000000L, 0x000000000000000L, 0x000000000000000L, + 0x000000000000000L, 0x000000000000000L, 0x000000000000000L, + 0x000000000000000L, 0x000000000000000L, 0x000000000000000L, + 0x000000000000000L, 0x000000000000000L, 0x000000000000000L, + 0x000000000000000L, 0x000000000000000L, 0x000000000000000L }, + { 0x10a46d2335c1685L, 0x0f4b8f0803d2c0bL, 0x0f7d0f2929cfab2L, + 0x0b04c848ea81d1eL, 0x136576d12646f81L, 0x1f8d7d9d7a4dda5L, + 0x1479b6278b451caL, 0x0f84f7d10585fa2L, 0x1addedc858f8871L, + 0x16c2cdf8b563637L, 0x10686cb63ab9635L, 0x1400c383e61a1ceL, + 0x1a9b67e0966faf7L, 0x1e9da7beb36de84L, 0x09f263887c47019L, + 0x16442c2a574058eL, 0x0f4afd58891e86cL, 0x02cf49e3535e9ddL }, + { 0x14dd36f71dd4594L, 0x0e64f805778f372L, 0x113a867d94c2ef2L, + 0x127ea412513d4b4L, 0x0f5c14188588aa9L, 0x09ccfd4ba9bca64L, + 0x1aad4462f5e4b04L, 0x0a5737a75fbeb96L, 0x1813d1cb22ecb96L, + 0x0a2b133a01c4c09L, 0x1c466d2b210c73fL, 0x152214301d6ca3eL, + 0x179f7bfa2edd9f6L, 0x0854e86c89ca368L, 0x00dcf4c5bc618c5L, + 0x0a572be33841adfL, 0x003be85ac6a9b6aL, 0x031f78c3dba7b17L }, + { 0x0376b7f016f45e7L, 0x1edab95f6417c3eL, 0x1d07390a6d80706L, + 0x058f5fb03ae725eL, 0x1241098b6fdbf0aL, 0x107c67ded20d8fbL, + 0x0f1356d01d1d2edL, 0x17d267c1a836661L, 0x1ae182830733fa3L, + 0x07694cd87ae3668L, 0x0cd538fe6183228L, 0x130c2aab3882ffeL, + 0x1c129f85cbb1360L, 0x03b42fdf55865b1L, 0x06658cda0bb3125L, + 0x059b4a0bd1d85d6L, 0x02390dcc794ddacL, 0x027f33c8e78c96dL }, + { 0x0a423d505e8733cL, 0x02f328eab8be0caL, 0x1a23a586cc8b321L, + 0x0db683039846f8fL, 0x113bd7210c4471cL, 0x00bd8480643af13L, + 0x1abda77f7a7b6cbL, 0x14c8614dbcbd119L, 0x1aaa7a61a7b81ceL, + 0x1296813119fcc6aL, 0x1bf74181a26a6baL, 0x0f9cb95895576abL, + 0x148e95076130cfaL, 0x074d0f297d26d88L, 0x01005c0c255c311L, + 0x1b3a431843ec234L, 0x097555d1ffebe78L, 0x00224150c2b0ed9L }, + { 0x1758ac273d486d8L, 0x0fca330e6e0f3f3L, 0x07f08622ad3e05aL, + 0x05e66e6c60e4793L, 0x1d8c2260a0e54f0L, 0x18de302b05f712dL, + 0x1fad4a3f0c1f114L, 0x06fade43e34fc89L, 0x1c8e4499c57128dL, + 0x11d829f6bd97522L, 0x09e810ca8f488a5L, 0x0a9a6a8b2cd0818L, + 0x1fd73557e95b518L, 0x034903bd3370d24L, 0x0d09c083499ff66L, + 0x1b689f426a1a7ceL, 0x09f1a9c3f2568ccL, 0x0419d07fc6f6dfcL }, + { 0x0c419c7ab376b76L, 0x14a7993e8786654L, 0x078aa4314534edcL, + 0x1d4c4aeb4dcad77L, 0x098c0a88931ba51L, 0x00b5152b7f703d8L, + 0x0982c12f96bbad3L, 0x0e1ca266a17cdd6L, 0x1339edad6a1d5c2L, + 0x1b376acf4edd6e8L, 0x0efa20b741bb03cL, 0x139196230fb6842L, + 0x01d8a1058a22d63L, 0x115ba2788ff64afL, 0x1c170300fdcfa9aL, + 0x02340e83faa35e9L, 0x05f2e2df95a85f8L, 0x034959e71f5924bL }, + { 0x0e6cb72d2a127b4L, 0x03752c7c940b786L, 0x118d1e8dd8599a9L, + 0x03c1572ddc87d9eL, 0x12edbe8c163d9a0L, 0x127332e40a2e36dL, + 0x14be4bd09b2b937L, 0x0622e9a1680e9c4L, 0x054c240d77d2af8L, + 0x00fd1cb9eb2949bL, 0x05247282751a556L, 0x0a66a8a4c8780b7L, + 0x11d41283278c4e8L, 0x181b0f92996b219L, 0x1bc27c9911e40e1L, + 0x0bfc0ee83236313L, 0x0d6c0cf0aaf81deL, 0x0199f21857a0021L }, + { 0x1f04de4cf26d3b7L, 0x1b9835a9fbcdf2eL, 0x117c6022d9915e9L, + 0x090a06e6c148027L, 0x0b061037ef291eaL, 0x0489dd8ffe4ebe8L, + 0x0161f6741376597L, 0x0ab29146f5fe277L, 0x0b5443483fe3ee7L, + 0x1e10f3a023189c3L, 0x041397377ad630fL, 0x10c4cae59aa5674L, + 0x0115aaa40894fe1L, 0x02cf523175cd38dL, 0x1ac0a8e2b71bf95L, + 0x123a37631a2ea95L, 0x108ae1276362f77L, 0x00874598eeb5debL }, + { 0x07f03e53ed9f1afL, 0x0923bab33b0b35cL, 0x18c1d33856e00ebL, + 0x004d63d0b671b9aL, 0x1af99c151877e2bL, 0x012a3d58b2a68b8L, + 0x17bd65e0ba7924eL, 0x098db8ff8f84daaL, 0x19038f95d2fbeb5L, + 0x12c86ff01b601abL, 0x0dbab93f70fdfffL, 0x18a9e6bc35119f9L, + 0x12da0a5568cb1fbL, 0x0db7aaab9e470edL, 0x0b0281a6a1ce4fdL, + 0x12b5670c8d665cfL, 0x0bcfd261c832a84L, 0x03242a926066e62L }, + { 0x0bfb3e2c4a6ff2aL, 0x01fdd1ad321450dL, 0x1fc226bfdd08aa8L, + 0x1574bb7b2710844L, 0x12a182cb2337883L, 0x100f829c0c3574eL, + 0x079eae7c1d93526L, 0x0b724823fd722f6L, 0x0700b1903570cbbL, + 0x0a8c0eadc8a5f3eL, 0x1110dc660460b57L, 0x1a48ae97332e26bL, + 0x15632d28b232758L, 0x1d1c1f84d328547L, 0x08cf600901e2eb3L, + 0x16892ca8d4c1801L, 0x03ca4061c7a2df8L, 0x00fbb79f9791a2bL }, + { 0x0a2c14344c436b0L, 0x182ab0fb4e43d4dL, 0x05ed7db6cb7de41L, + 0x03daad75046be62L, 0x1d0afa4885761f4L, 0x0e738f7c18a327bL, + 0x1d222a67ca454ebL, 0x07564f7ed2622d6L, 0x0a98a5a8c9bb944L, + 0x1c3c0131772fef4L, 0x1e4f74604ab2ddfL, 0x0999b909792474dL, + 0x0ff1d4995aaf92aL, 0x0276c4ce9e12b15L, 0x14a94e3f67f0cf0L, + 0x14e4d805195289dL, 0x005d0f367bb049eL, 0x0024927fd9e8847L }, + { 0x0548e3dc673562fL, 0x19812f175724603L, 0x0cad7871a5df4ecL, + 0x08dd7caaf7cc3faL, 0x01d6e18e424e206L, 0x0bf4adbb39c8e02L, + 0x06e312e3aee3853L, 0x1a695d16fa84132L, 0x0f8a0df66e01290L, + 0x0bf1251c92f2fa7L, 0x1ecb2c54209cab2L, 0x0e5c4a0e4cc2f34L, + 0x029062fa49b40b0L, 0x19e29de76d6cf0cL, 0x0509e661e029e13L, + 0x1084cb15056ed3eL, 0x03508cd849cc146L, 0x026fe7404e1c057L }, + { 0x1069cb2d527b780L, 0x0d00acbbc986ea2L, 0x002f89f4098f54bL, + 0x0d765a36562198cL, 0x154adf3c34102c2L, 0x187fa3a6329311aL, + 0x1b9f35a244e0917L, 0x11507f5198b9522L, 0x11e10f139d15c8dL, + 0x0b9ee1740ee2b59L, 0x1b2c11713b66ebcL, 0x0fb08fa02450ff9L, + 0x139f3a532f307fdL, 0x110a9e111252b8aL, 0x0a2902167a7a077L, + 0x17a478ac4b2bbc8L, 0x002dc7daff89339L, 0x00683ac845c5034L }, + { 0x10af2a7de085f2aL, 0x06927df4cd972c3L, 0x0985672904ee23fL, + 0x090ab3f0a31181aL, 0x1622da0d1f02a2eL, 0x051b0ac1dcb010fL, + 0x11a0970170bd5b7L, 0x17c02919e38f221L, 0x0392f2896272695L, + 0x01e85dad46b277bL, 0x14891073f2f14a2L, 0x19d8a4c22fcbde1L, + 0x19f04928e9f5dafL, 0x1c9f97155b43095L, 0x0304544a0fdd134L, + 0x01bfdf7ddafdae0L, 0x15af2cde215a436L, 0x0127d4b0e178429L }, + { 0x167db3f616df7f6L, 0x02bec7dec819303L, 0x0a41ba0b551190cL, + 0x0ad12c87b62e9b5L, 0x0c89a0602284f34L, 0x013e890c58c8efeL, + 0x14516ead1abd35bL, 0x13cb4afe90d9312L, 0x0c03214e9cc942fL, + 0x19f0e47a0ca80acL, 0x0dd67ce6b50eac9L, 0x16ffca1dc2e719dL, + 0x1c8f4d7d4e5e1b8L, 0x1aab01f9fb1ad8fL, 0x14be9823bfddf8dL, + 0x16dc2403ec3a2eeL, 0x11494d7a03d4a6fL, 0x01b8e611efe2780L }, + { 0x09b115dda90c351L, 0x0b75f9b26ce0314L, 0x080bd942cc6db46L, + 0x08deaec85eef512L, 0x08100127cc28c16L, 0x06403dee27bf1b0L, + 0x103ca20db342371L, 0x0a62501e2adc004L, 0x03f9a6d7899cb39L, + 0x0524a699d40101cL, 0x05fa47a1f4d1d10L, 0x1a0e4dbbc4948adL, + 0x0d7640c30e70d97L, 0x0dd37363037b52cL, 0x0f04fa00f0b03a1L, + 0x1af1e661ed4f5e3L, 0x17f3e602e4fc9f4L, 0x0495b5e5006407dL }, + { 0x03d5c835f00822eL, 0x12b895c58b78917L, 0x07124ac28cc03a0L, + 0x1b4f9832a903865L, 0x1bb1413f6b4e32aL, 0x09651385f74e770L, + 0x0454fb7edeea92aL, 0x1f39a8e55f5d477L, 0x0e8f09e7e00f0c0L, + 0x070ec392e6f5db8L, 0x0eb8212a6d8eda9L, 0x03707fab1ecbfc5L, + 0x1aa3b62759f4014L, 0x1c8718446bf62f6L, 0x09df8c66abdb99dL, + 0x10e3842b5b0603eL, 0x09de7db4b98cf33L, 0x038ffb164a7817cL }, + { 0x04c71022a4a84d9L, 0x12566af5e38f355L, 0x0297c73595e38bbL, + 0x1fffe2414a76235L, 0x09e6503383f5ef9L, 0x0220c05262cc708L, + 0x0a30787a7e64328L, 0x0d717065a8deb30L, 0x0753f28a033af53L, + 0x176e258db6a7b45L, 0x19a4a9cb3347c24L, 0x1efba444c865dbbL, + 0x1ea3d2661cd3aa0L, 0x1ee1beed1c6ddb1L, 0x1bdad33c7867f1bL, + 0x174d2d83166a109L, 0x073e6a83fe9df1bL, 0x0207ea3f3afcac1L }, + { 0x188b746267140a4L, 0x1fe0f755b797dadL, 0x0239a6189521b6eL, + 0x025d6ddf85bb3d9L, 0x0ac8ff8869beebaL, 0x110ca867e110a54L, + 0x1eda6575725bad6L, 0x06f2671380a82e3L, 0x02d85d4521b4683L, + 0x06b45042089a12eL, 0x1004e7b1b085d05L, 0x172fee60109bca5L, + 0x061f578aa320cf0L, 0x1cdb57218d60b51L, 0x1529a5462e7eacfL, + 0x1c50cd1b04223b0L, 0x18c0b334d98dffbL, 0x02d8e08abf31c99L }, + { 0x0edaab172b6bb8fL, 0x12769017e496148L, 0x0f17f9a531ce371L, + 0x1f96a9b9c9e8574L, 0x032420dc316dc65L, 0x16e7ca6596b351bL, + 0x0b2745b9c1b9c15L, 0x15050138ec949e6L, 0x1ab18d830ea6edcL, + 0x1e8d67340e32fabL, 0x059471f684b0413L, 0x1acd8ef234903f2L, + 0x14785e67a30ac3bL, 0x0d07eac8db568e7L, 0x0718d13934ff113L, + 0x015679c2c9002dcL, 0x0f484de9cb833e5L, 0x04b1d5c1d53ab77L }, + { 0x04b47d8df4ea5a3L, 0x1440aae7f22ff4aL, 0x156228f0d592595L, + 0x1dcf933c2ba2dcfL, 0x155071bc84e55b3L, 0x02bee71ff71026fL, + 0x155c1c401bca410L, 0x159fd18721b774eL, 0x03645bcb63319adL, + 0x0c4f4583e105fecL, 0x1425a5f5f655e20L, 0x0643733e9c771caL, + 0x01a60cfb6a037d1L, 0x01b9c16d008d929L, 0x107701d99652aaaL, + 0x13109913723fb07L, 0x1586b82b899076bL, 0x0221a407e5f22e2L }, + { 0x0ffffb49114221aL, 0x027971f42bd3d7cL, 0x03903e951e1d2bbL, + 0x03adf2c2a485c5aL, 0x1bfe9b77ef3e6b3L, 0x01d4355914b29bfL, + 0x0ab1b0aa743cbedL, 0x0f6482509da48aeL, 0x1a3868917e721baL, + 0x1f7be00608bd3c6L, 0x1241c74c5816b36L, 0x153c0cb51dd2702L, + 0x18c442be82c2dadL, 0x1b6b95ac6ad89c6L, 0x0c0f9b66db0892fL, + 0x006e373a6ab9f1dL, 0x1ebab6d1eb0a170L, 0x04b88c54467fd53L }, + { 0x19c59a2cdecb5d8L, 0x1e40dd49d34335fL, 0x160411dd3efe020L, + 0x154040e16849c1bL, 0x0fbfb781e779a3cL, 0x1950e24e9a97dd8L, + 0x19406a2c36080fbL, 0x1e570b0c6f62967L, 0x15ba70a498a882fL, + 0x13980419d8377d2L, 0x100bd040bfb8aa8L, 0x05331404474b485L, + 0x0685c3fc72e4e76L, 0x1f297573edd15d1L, 0x03d17d9553f9d8fL, + 0x070f8616a80b44eL, 0x082d56a177aa573L, 0x00be03bc6a5b8fdL }, + { 0x06dff1d2735e37bL, 0x0272b32b762b907L, 0x12767aeea5e3262L, + 0x117413e78945eb5L, 0x15b0437740fa451L, 0x1d1765461fd0bbfL, + 0x0f50286877b3659L, 0x094ed1794e00a51L, 0x1f224952b18691cL, + 0x1709622f436afeaL, 0x16455cde1669a85L, 0x061341ff9c1cf41L, + 0x1ba96cc9a3723f4L, 0x0d691d1c2d46dbcL, 0x0fd7611b744ab80L, + 0x1dacd3ffd8743c5L, 0x0c6d6ce84e1a452L, 0x0090ceae42b8ff2L }, + { 0x1eaa67f262969ebL, 0x159ce9781f3b9a1L, 0x19455eec2424e8eL, + 0x1b1a2a04e9cc24fL, 0x0580bdbd0f82b0eL, 0x1a1f35ffffe56c7L, + 0x04759474f41d6a5L, 0x11029097b631758L, 0x095cd9990eb24c3L, + 0x0b530e83fd633e3L, 0x03dd8a8139ae1c8L, 0x1ac3974af990861L, + 0x0dd234a07a2865dL, 0x1d03c9fc9e14b58L, 0x18a7b39dbe4a0e4L, + 0x0de84e16afc3e17L, 0x0301314a82f7e62L, 0x01646bd596b2bf9L }, + { 0x1cf58920825e4d6L, 0x0f552b77c1da233L, 0x17604c4042377d4L, + 0x0b1ba12c7ec7cccL, 0x1df6436a229f89fL, 0x0f5dd3c6258a6ecL, + 0x1ce06676b91a751L, 0x1d6231556eeb49bL, 0x1da8978bd29e37fL, + 0x0e76ad556516bf7L, 0x03417719f5aa29aL, 0x1e1aeff09468d93L, + 0x0eed8cd59a7474bL, 0x08e9cc7dea21459L, 0x0882c46c3f47357L, + 0x09888b2c027b729L, 0x15896eb705a1b40L, 0x0114ce93ba584ecL }, + { 0x19cd58dc64397e6L, 0x0c78f5fb6e98f2dL, 0x0384fa7c76cab06L, + 0x0f1f9b8d18b0cdbL, 0x053c01fd405ae28L, 0x0edafb52594066fL, + 0x1e2837258fcb504L, 0x117dabaa3137d89L, 0x0336fd13d916ee9L, + 0x092d8d98216fa47L, 0x158a46b3801d39aL, 0x16904a62fd2a19eL, + 0x0b821c446be8d38L, 0x185b2c9a63d68e9L, 0x1283541c71104d7L, + 0x0d84d2e36e6dea5L, 0x18eaf9ffa5727b4L, 0x010d633bc8c9b30L }, + { 0x1420e3f2d7fbcd2L, 0x11239cbdefe0c55L, 0x0fe137d752d049cL, + 0x0c700f6fa692406L, 0x133c36256fcd423L, 0x19140a6fe0cd84dL, + 0x066e04f5bcdd683L, 0x138e12f14b206f8L, 0x14f3989970ff27bL, + 0x0070d22b0ad21c4L, 0x0d25a8f980bdd3fL, 0x086364c39439ff4L, + 0x1bee0164cdc3f1cL, 0x13fbdf4fb09108eL, 0x10b86ecc118fb93L, + 0x074ac02befcf125L, 0x1d8663d88d62448L, 0x0074760f387316cL }, + { 0x08ccc298a0878ddL, 0x00baeb320038d54L, 0x0082945cd85e66bL, + 0x1dbab1462b20689L, 0x08d221a1316d023L, 0x0e2471983c2dea4L, + 0x09dc6dd2cf79e56L, 0x0a685dc070498cfL, 0x159ef6cdde0b914L, + 0x01857144d91bf48L, 0x11e93125760c95eL, 0x02fda0ee6ccdc30L, + 0x06a294a32567b12L, 0x0326c1932c0c964L, 0x0c4f96ddaa83d5aL, + 0x0e7fbc5457a25e9L, 0x035d850c1c01b6bL, 0x0329d3cafae881bL }, + { 0x1e2898550dcb199L, 0x1c72f3fd015b067L, 0x1f0f25d80f42cd6L, + 0x1a4fe2636b794faL, 0x02b12d52b0e5288L, 0x1b92e39d53826f7L, + 0x0c44f881ac76076L, 0x0c6162507358ba3L, 0x014f970cbdb45d7L, + 0x0cbfc9f59092f47L, 0x15ce73b9f6a89b2L, 0x1a7e3fde41d37aeL, + 0x147c6a42b146ecbL, 0x13fd87e8fcca508L, 0x103692f4a27ad3cL, + 0x0f2ec2230da6334L, 0x15e083f65a5fb9dL, 0x0186fe23dea2233L }, + { 0x0fc5ae29eaadfe8L, 0x13f2a5a6a74095eL, 0x0b7e2d4cd584940L, + 0x08ad4d4429560e0L, 0x1059068ea2b9c20L, 0x018887d8d1efbd1L, + 0x038728d452c8662L, 0x1096f7c466d896fL, 0x017073ce63e2f69L, + 0x1708a5316efbd63L, 0x064afc1f5f0f221L, 0x1c17d635c5124ecL, + 0x15251849395da69L, 0x003d1d504c1d78bL, 0x03f88626b14a935L, + 0x04a022a6b8fb55cL, 0x0cfe16fe872397fL, 0x02b952c8faa6109L }, + { 0x166841909a5553aL, 0x0a18c193b99de24L, 0x12c8fbbf5a40fc1L, + 0x17e4424da9f39d6L, 0x0fed9578bd3cbf9L, 0x01836c36cb38e01L, + 0x13f96ee965f3b28L, 0x0ed6e0bdac27aceL, 0x1f1d3622b67f33fL, + 0x0de79e308e5c618L, 0x119f7394f46aa45L, 0x1253f2115687470L, + 0x1d8d15767a902feL, 0x0857e83db71f24cL, 0x02c643a050b6d72L, + 0x1349c2418df78d9L, 0x03c80c865532491L, 0x032e165f0ec6416L }, + { 0x04cda20a660bb63L, 0x01d8543743122b4L, 0x13d9ae83bb5c9f7L, + 0x0acf3ba2b0ec8e5L, 0x08452d4479c162eL, 0x1fabcf5b44213b8L, + 0x05dc20a6f1acd04L, 0x10725d42bd92a02L, 0x15e34e300477381L, + 0x01e51a4b9f0e978L, 0x13c7708a6f4f7a3L, 0x1e3729defda74b8L, + 0x0ddfae7a1a783efL, 0x0d04cc29236db9cL, 0x173d2ad0d4f5cb8L, + 0x111724a675ab141L, 0x166d80550160e78L, 0x0418a206a9dd3bfL }, + { 0x03e2e32f611b2daL, 0x13714e87d23567aL, 0x0fa2082cf035741L, + 0x0c3a7c89e1d12feL, 0x1fd27a66c45c28eL, 0x0f428bc94ebfb36L, + 0x1e375cd6e182840L, 0x035d47f9d307bc0L, 0x1c9977db5638ce1L, + 0x0441c17a429b59dL, 0x11e8f1932b7f181L, 0x1eff0428f6e2fc1L, + 0x0c1b411e3e3cd17L, 0x0c2fda36f4ab31eL, 0x1c467295ce6b23eL, + 0x0502a70a7339b79L, 0x1664a985a70e15aL, 0x028261d4536afa2L }, + { 0x0b55283b8fa53c7L, 0x07f9c284a3a7180L, 0x10710df3897e617L, + 0x01cb4253da469a4L, 0x0abcc6742983243L, 0x140f70b569c4ab5L, + 0x09c0a8b700075fbL, 0x17698478d6cce16L, 0x0b35e567ea6e8a3L, + 0x03859e7534b39f5L, 0x1ea70f9b8a3ab2fL, 0x09bcaa6f6fb50b4L, + 0x056de937dc2ae68L, 0x1c2182112f6561fL, 0x1f71482fcba9b27L, + 0x0d5ba7195efa0efL, 0x1d2c27af0b169f5L, 0x024b7234ce38e90L }, + { 0x014fc829fa93467L, 0x1bb420759530a5dL, 0x1ebd20cf826f0b8L, + 0x046d0d7b98cb379L, 0x01f3216abc85975L, 0x0040dc205fe8404L, + 0x1e4ef118ef6985fL, 0x18b7a03f50d7608L, 0x05a21ece62cd640L, + 0x1dfb52a1101eae2L, 0x103b7254459ede5L, 0x195eecb744d19d6L, + 0x09aeab51f9d67aaL, 0x186b431d45d06cfL, 0x1c1a54b052c857aL, + 0x0896a6a99b9b7cbL, 0x1e84f2b5ccfcb37L, 0x0099c48b98981bfL }, + { 0x068064045003cd1L, 0x00bde2257156377L, 0x067f7a394c53f6bL, + 0x138f9d52b8979a8L, 0x18f37e0181e34ebL, 0x04c8645dabbb169L, + 0x129efb3133ec098L, 0x1de178927f2a146L, 0x068074172543304L, + 0x1607e5935e45515L, 0x0a6d18ed17fa96bL, 0x0a5cabf7b7593cfL, + 0x060485dff44bb29L, 0x06f523cb2878605L, 0x178e8080b144135L, + 0x1e68ba59df412d2L, 0x1bd4c8102b46da1L, 0x021175ab9f9c19fL }, + { 0x0592eb6a6ad3f47L, 0x10fb6cb8a5d0756L, 0x04641ca05166c21L, + 0x04c9d4b006af83dL, 0x14b12723cf7c94eL, 0x1db9b53929bb562L, + 0x0f373ca9ae9076bL, 0x15b913d12419740L, 0x0f2e20cb45b0fd3L, + 0x1752d2a6b302cffL, 0x0fea2e2277e2f09L, 0x0fc2cd47e57fdccL, + 0x1c747312e140f1cL, 0x193cccff84ff5e4L, 0x1f4ac15f466e709L, + 0x05b8d53f776996fL, 0x182cfba27d7a0daL, 0x01b42a0e7961292L }, + { 0x10d3c9e22799d37L, 0x1bef2d67d199d28L, 0x063c203de56c6d9L, + 0x155f91bf849cd5cL, 0x0e842dc269b53c2L, 0x033ff43cbaa0db0L, + 0x161df569bcabeb0L, 0x1e5a04114077a0fL, 0x034b473f0654be2L, + 0x13e08157a8af11fL, 0x16fe74ab06bd239L, 0x14836d427a01601L, + 0x0a97e94c11e264fL, 0x0352c37a0b34bc3L, 0x1e49fa427633cb6L, + 0x14acc0e77f0d38fL, 0x134b89778802241L, 0x02cd2dfac911309L }, + { 0x1d1c91e81347191L, 0x00d5e75cb4cb974L, 0x1d9ea751a9fc61bL, + 0x19b54fa72e0f110L, 0x191b9aa0da93cfcL, 0x0e9e36045f74f8eL, + 0x00402099ff5e3e3L, 0x1f7f270c1a12845L, 0x06a6a71aadadb47L, + 0x055035bd30ab7c5L, 0x0c1780e6122f267L, 0x046e5555226b543L, + 0x19b13f3bd136ddcL, 0x05662fa6bbf3f03L, 0x133f4da342d72f9L, + 0x1c1f009b48bf130L, 0x19cf14ef618d3d3L, 0x0233ab260a1f5bcL }, + { 0x1725904b6fff5d7L, 0x199d7c96e23a946L, 0x15d5b482e2a80dfL, + 0x028775d873212baL, 0x08a2b9b032235fcL, 0x09ae30d17f5a57bL, + 0x1d21987140c6253L, 0x1e759256d45d50eL, 0x08eb48b15011bc6L, + 0x147f09463cf6e59L, 0x06f032974a801a8L, 0x0e645e2b70a13eeL, + 0x0c7a036218f3167L, 0x07c0f04f7f46b94L, 0x1f143641a3ce72dL, + 0x03c062ee7e02cf6L, 0x0d50d0f7adbed6aL, 0x04506f70b2774c2L }, + { 0x04991bf47366e6fL, 0x026cff4361802a8L, 0x1d46903338dae02L, + 0x0c7e32c3c429898L, 0x00445e43bbb46aaL, 0x0f10afab53c2fcaL, + 0x002376e346d5f24L, 0x118d51c8a7d8fddL, 0x1c0367ef8bbaa1eL, + 0x086c8f8f1f0c084L, 0x13f439f8828b0ccL, 0x1908aa9984eff2fL, + 0x1d7b628403f1e80L, 0x1ff050be744dde0L, 0x1c001cddde2a598L, + 0x17da53d3b633f83L, 0x0232ce7fe7db6f6L, 0x03d825ae9774be7L }, + { 0x1546bc782c5faf8L, 0x1a62f475c084badL, 0x01879de1478069cL, + 0x07d2adaa3e7aacdL, 0x03c3c37c833a101L, 0x00a476639a8b98eL, + 0x1bd0581dce3ef83L, 0x0ae5d8de177c377L, 0x00aa2ac6ecfa518L, + 0x194816bb371d6f8L, 0x154227188b5b8c1L, 0x16474dbb005f9a9L, + 0x15338863723ae21L, 0x146c0c1172a32d2L, 0x01a5deb61446682L, + 0x04e589e29a0646fL, 0x11c515b081c9c7bL, 0x00e354ad264cdf1L }, + { 0x0b14ad5c2821363L, 0x00c11a68bef0e53L, 0x0b1332b7a1220a7L, + 0x1304913c4f5debaL, 0x1081d927f412ab3L, 0x05d68fc964e04c7L, + 0x07ec5be1ef7d1d7L, 0x0ede955b570343bL, 0x0475a7923b75f3bL, + 0x0ee856b6dddd47fL, 0x1d85912dc2ad166L, 0x1102697b35e306dL, + 0x0eba9abda32a464L, 0x132b12fdae48913L, 0x06392f933b21c27L, + 0x10f39a967233c10L, 0x0c9a5c09c8414f6L, 0x039384501185432L }, + { 0x133c0b1f34a466cL, 0x1704e3fcea2dd27L, 0x1fb838a1e17286eL, + 0x0d21101103ae1e1L, 0x1b043da3824c714L, 0x037a197120b6155L, + 0x0f871ccf69c4f3bL, 0x0ca56b20c9392f2L, 0x0db62d5b0b35c93L, + 0x0af5b711f2e0d95L, 0x02d73aec5ad454dL, 0x10d3ee12d2399fdL, + 0x1b61a85bd59e081L, 0x1d7081fbe432fcfL, 0x119fa77c5a74f33L, + 0x0a2272a4b88e6e6L, 0x1217db55c0b4369L, 0x03a48e3a639932eL }, + { 0x12ed5bf80d2b94dL, 0x16319dd25930598L, 0x1633588866846e2L, + 0x175d70591d590d8L, 0x19ef9ced317ccf6L, 0x15e6ad16fd94f72L, + 0x0c8076a9f626390L, 0x1b927c52b90b2e9L, 0x069e75784d9fc5aL, + 0x162384f809551ddL, 0x0a7cdf2174f2e75L, 0x1c4ba7ba957a3fbL, + 0x010b3ba22ee5487L, 0x03746e5d807ea58L, 0x19a19932d64524fL, + 0x0d6ed6e653f5779L, 0x0416829d1c26890L, 0x045e7e9f2ba0bb4L }, + { 0x0882734d3c8c314L, 0x0597888c3841983L, 0x1f0f01a2e85a57cL, + 0x10ef248f0f726feL, 0x1f9922275365e0dL, 0x0ffea78aa93f2f0L, + 0x18e24281a59209fL, 0x15bab167be45eb0L, 0x183446b896af20eL, + 0x0ebcb85a83a312bL, 0x034819008a9a442L, 0x115ece3d86f3b3dL, + 0x09057fe91ed1e5fL, 0x0944820c37aa128L, 0x0e4cab7c5376a05L, + 0x126f17af0021c3bL, 0x1493e18d1e4905aL, 0x029e56e7bde9bd5L }, + { 0x1b5edf75e53d0ffL, 0x1303644455fb38dL, 0x03e04881b457621L, + 0x0bc456d466c9236L, 0x1173b317b301834L, 0x04f2cad5d33ca5dL, + 0x093463079619df7L, 0x0a69c20c904472cL, 0x061752e59da55ddL, + 0x0c5a755cf2143ceL, 0x19e12d247cafb40L, 0x13a43cf2853d95eL, + 0x0510f262243dcdbL, 0x1328762e1b4a0a4L, 0x06a5d8041bc642aL, + 0x0208cea854b5d6dL, 0x0b169bd75e9c32dL, 0x048424cb25fc631L }, + { 0x1390cf65a93c661L, 0x031324edaf82b58L, 0x0a7694685e20612L, + 0x1ecee5bd3525527L, 0x1c71487c1b0cbb8L, 0x11211f3733ff5ebL, + 0x10be3e6d0e0b539L, 0x1e52dfb4a1d76b4L, 0x0c921b3376089a4L, + 0x0e996bdc3af628bL, 0x1b4b2b1040492d2L, 0x04138843f6f57b0L, + 0x0bf6b7de33f6862L, 0x149e49341f0ca4dL, 0x171330337b863c3L, + 0x01a45a9db7abc11L, 0x1e8c2b75be47358L, 0x01ebfb7fd23466bL }, + { 0x07b290cdffbd5d1L, 0x0ced34b819c6ff5L, 0x0c2243fbb72675dL, + 0x0a85b9cd1cacd01L, 0x12ae4d82bc690afL, 0x0cadb0428cef95dL, + 0x087d1584919fdfcL, 0x066cb346859b078L, 0x055771bf5556516L, + 0x1e3449aaa45d2b1L, 0x06480e524bc8e97L, 0x11c73938c02f6a8L, + 0x14511e601956752L, 0x0e8b52aa9f83276L, 0x152afb8c0fe7ae4L, + 0x09cf87c3189fa44L, 0x0e640994d6ffd43L, 0x047d8969fb6ef3aL }, + { 0x06381a2293cb7a4L, 0x104f85c3dbf26b6L, 0x008c1e2b0fbd14fL, + 0x00af195d229e425L, 0x116ba4dde89ffadL, 0x1ac0502515b4b53L, + 0x04c1c51a06853dbL, 0x11226b1f2f6985eL, 0x1878969962932fbL, + 0x0eec28513452d7bL, 0x1c7db7f88e7e0caL, 0x1a5c9e8e933b5eeL, + 0x17867ca0e95f20fL, 0x1bacc0f64db21f3L, 0x0ac725f9e163b34L, + 0x068a77d28d4b233L, 0x1b14f9303a206ffL, 0x01fe63398bae91bL }, + { 0x09debd5df21f920L, 0x1870fe0a00dc828L, 0x0ff656992abfebdL, + 0x0a586f424448539L, 0x1deb926bf212085L, 0x19f8ee0ea649fa3L, + 0x0f1184bcf93027eL, 0x1a4ac10b4b2b6a3L, 0x02a2f5d62f10fdbL, + 0x06eb167ef8659e1L, 0x10928dac3c952d8L, 0x00baac8c256e2a8L, + 0x0fa1f5249cc3a5aL, 0x1f3150c45f5f186L, 0x10a64e493b1a40dL, + 0x10d0aebe1f7595eL, 0x034d41345dcb3faL, 0x03228a37ee38a8eL }, + { 0x0ec633aba1924f9L, 0x1789b00319370f6L, 0x1eb1f943f05eee9L, + 0x13de7b1c00406eaL, 0x11dc5a74ca53191L, 0x0a095c4aa2d3552L, + 0x14001b887563f4cL, 0x1860378600af763L, 0x0f1789c696ed1a9L, + 0x17969afcc2c7d24L, 0x1426e6065efa15eL, 0x0eaa53544cba869L, + 0x07c058fa801dc07L, 0x0a5d0a6765681dfL, 0x01429d24b5c2a7dL, + 0x0bbb4db8f0a0ad8L, 0x12e2a7ca4a94d00L, 0x022469eb955fdcfL }, + { 0x056f14529b33989L, 0x1a8de54d740ad6eL, 0x184d2c1d10521a0L, + 0x1479b3e67767e8aL, 0x1ff6e4a3955ce42L, 0x07554889d6f2762L, + 0x1bf7f4eab1c5694L, 0x01418c3d932accdL, 0x1108a28b8f6a447L, + 0x0177ac272a42264L, 0x16c58b438bccdd0L, 0x063f68def979704L, + 0x0c96f2fd893dcd1L, 0x12c9463c1040bc7L, 0x18f11653631759cL, + 0x0613e50b467bf32L, 0x1a572497175d92aL, 0x03b440a3ce5b80cL }, + { 0x043a11491767eedL, 0x0dcd6c95fb2edddL, 0x13800e978869784L, + 0x025466a82bd1445L, 0x0a9ead626360442L, 0x195772e162b1da2L, + 0x1875d2f01899282L, 0x0baeb71aaeb17e5L, 0x11cff0ee7d08a26L, + 0x1c8a70ed85b8953L, 0x0497412c61a4b45L, 0x1e98ad99d02b86bL, + 0x1c9fff0e3ade253L, 0x0ed5f68cd23c920L, 0x1eb941942e741bbL, + 0x1c300ce26a4c0b3L, 0x026f37600fb532cL, 0x03387580e2f2d43L }, + { 0x173c0af73cdbb43L, 0x07662bf9218d6efL, 0x1504a868e1173c2L, + 0x052449bbe322f00L, 0x1eac7eff69a104fL, 0x16899121a979c6dL, + 0x0d1dbf0eced39f0L, 0x1e14d3d28616bc9L, 0x07d932340975a46L, + 0x049c4cf2eb27767L, 0x0849436c8d17a60L, 0x1264fe96f2d6f70L, + 0x154bb90b1f23552L, 0x08897beb1774e60L, 0x0eab8c87ea723d6L, + 0x02cd45a1e5f3039L, 0x127b77f03660075L, 0x028242973b1aeffL }, + { 0x10f3ce5a2f392faL, 0x003b57636483c17L, 0x1a4a12eaabd8c9bL, + 0x0797d1d3275a03bL, 0x0d950908b01b16dL, 0x09d79c38982e121L, + 0x0a68319bf585ce1L, 0x04eee6a281da788L, 0x18a31b12a1fabf0L, + 0x029800102c598bbL, 0x1f67f2a71f7ae68L, 0x0d37d0ccfa6157fL, + 0x08e9a9e13fd05efL, 0x1c8f574e179d398L, 0x0339b10fd326866L, + 0x1f160a1a19dcec3L, 0x0c4fb24dc405240L, 0x04c97f0a8fbf486L }, + { 0x054db3138f197aaL, 0x16b4ec3c397cc22L, 0x1ec113c2a0a2937L, + 0x1d463c918d2f684L, 0x1d98efec9821e1aL, 0x0659d771c6584feL, + 0x155cc82e13ea120L, 0x0d774b769508e8eL, 0x0a9be080acd50e9L, + 0x0228f4e77881aa8L, 0x1b9d7f1104c9731L, 0x1d30714bc67ac4dL, + 0x19a2b0abd26eea5L, 0x0db04154b990df5L, 0x0af30ab2a4b9212L, + 0x173f63b902d1532L, 0x1e0134ecf4b9c8eL, 0x02d345fd4262db8L }, + { 0x0ff3b45ff0a2bfbL, 0x0fffcaa817c585aL, 0x02156c70309b441L, + 0x161a773a0829bcbL, 0x026d3917ed16865L, 0x0d9e0717ad12298L, + 0x03cb9a88bd24fd3L, 0x0c290e2a915c483L, 0x06ab363a8509befL, + 0x0e50f1d5c65ddf6L, 0x03726100468e5a4L, 0x1c141ab94aeee3cL, + 0x0581897bc1ff982L, 0x042d6af3f5a0582L, 0x0cdedf12f092918L, + 0x0c51fa2b91f414cL, 0x03956ce6ef7bef1L, 0x03c567efccfaf7aL }, + { 0x1bf7f15f8520189L, 0x1015063bfb0e222L, 0x1ae77e88b86e550L, + 0x0e3e94690e73db8L, 0x0814cc52d2d6026L, 0x14f891e6c99c94aL, + 0x0dbdf79da849017L, 0x1c1c460dd415c6dL, 0x053815218b83a58L, + 0x0315dbb5020918dL, 0x0894f2fcc6f9c66L, 0x06646fbd0c3fd1bL, + 0x1690ae48902dfc5L, 0x05d53769792e49fL, 0x02d28a59af2e3c2L, + 0x19292de215c1f21L, 0x1668cb4b48cb061L, 0x0056c96b9e83ad1L }, + { 0x1b95fedc2ca548aL, 0x063104066c4d5dfL, 0x152cd19b0a011deL, + 0x07a97d12057d322L, 0x13e681edea3be09L, 0x1a00b0c23dbcca8L, + 0x1ffa3c8aa3d2c0bL, 0x1ec7de5969a95d6L, 0x19adc5151b3aed5L, + 0x00e67e8cc6188b1L, 0x0b05ee8f5f623fbL, 0x09a68c84212fb85L, + 0x1794b90bcf08fa6L, 0x05a854f5af5fc05L, 0x06a99ac6de2d2e8L, + 0x079da349fd2684fL, 0x1ae8ef4dcaf075bL, 0x04addec50385374L }, + { 0x1f92495e614bbd0L, 0x1d443dc11f1b1acL, 0x07b3f06f5a9dd59L, + 0x0f1d06b885c48f9L, 0x0ade066a2bfaaf4L, 0x0b699b18a77a705L, + 0x18e241caea98d70L, 0x01ff48538e3c5e1L, 0x0cac1e5d0bd07d9L, + 0x0ff9af528a7ae02L, 0x014ff301553b05aL, 0x0d6e546b28ff126L, + 0x002aebe487ab1d8L, 0x0fdce790f14fd83L, 0x037f3d6828435b7L, + 0x0f4555a28e0b3e4L, 0x119480dc66fb886L, 0x01bad4427e092d4L }, + { 0x18cbe2e1217f7eaL, 0x10f1543ae36d58bL, 0x1b006f6c6950685L, + 0x01c9fae795eee0fL, 0x113a0d86678864aL, 0x0983345d75e3326L, + 0x1654100c97e6723L, 0x0cf727db3925e38L, 0x1fdf36763541e06L, + 0x0cbfdd85c8d33b1L, 0x09a7a981e72683fL, 0x19003d55188e4d5L, + 0x01afa63c55c7303L, 0x07e8956def63ae4L, 0x1a20e2807373789L, + 0x0a6f33fc1bb4e32L, 0x0ec66bb093b3841L, 0x01346c0c58465c2L }, + { 0x1dae35841580555L, 0x19733a39e881db9L, 0x004efb3306ad3f0L, + 0x05649dd3bc48182L, 0x1fa8e066da4099fL, 0x1c6bf71bd865adcL, + 0x00502d6b8139190L, 0x0f0fefa62c856e4L, 0x186ef4edb339e4aL, + 0x0f3bf769d3ec1baL, 0x1eb4def5c1f0ba9L, 0x06741f2f2313107L, + 0x0a2e7a208e816b6L, 0x021aa8b57126014L, 0x17cafd445c7f8f1L, + 0x074ac7d7276669eL, 0x04b8419ed4b01b5L, 0x0458139ae02b652L }, + { 0x09bb464e1019195L, 0x0601379fe1460dcL, 0x19b8aff0ec84779L, + 0x15237bf25f58241L, 0x0d995bc9ec71bc5L, 0x048fff242ebd5a0L, + 0x189965f19da3b99L, 0x185b2aa5a335f79L, 0x1bae6c7fe8e1b76L, + 0x13ec140ebf1d68dL, 0x126be57a625cd05L, 0x0499141903047c2L, + 0x1bc3006c0dd1f00L, 0x0c3b9ea67ab8ffeL, 0x0d50362ccbb3df9L, + 0x0a084b0454f05faL, 0x1fe5ab45c3f0436L, 0x020071d5025a6c2L }, + { 0x13216495e46e4a2L, 0x176b21209b03a23L, 0x0ec7183b1df4de8L, + 0x07cbc1585ccb244L, 0x05107ab75e13aacL, 0x0129eded0be20deL, + 0x08a5996c8bb25cfL, 0x137fe70cf714a02L, 0x1fed660d50621a9L, + 0x1e14283644fe1faL, 0x0d42e7c591469e8L, 0x0064cf96b0de7daL, + 0x19967185b127c3eL, 0x0509804de403e3bL, 0x0bc7d3427055f51L, + 0x143306c5eec8f5bL, 0x0394a42b9acf3a6L, 0x0098e1ed146d370L }, + { 0x0785ff1a7da83baL, 0x0da12e827a21b25L, 0x06f7b00fe04bd05L, + 0x1501ebe944f8113L, 0x1da251b9c58d411L, 0x1d97991e996b087L, + 0x020f266ed141334L, 0x1fa33188897e984L, 0x060c261af730e83L, + 0x106526fe5816dc8L, 0x1e0e2e77c79f201L, 0x1f2f898d21921feL, + 0x175d75f1546b79cL, 0x0e58747f898a8a6L, 0x105d8569f01d3c4L, + 0x01fe17241558365L, 0x0e9de8098ad44aaL, 0x038e8d2351a2a2eL }, + { 0x0178f76fa1b382eL, 0x07661bb96ed06bbL, 0x0cab175344c2836L, + 0x091ae4c45954b55L, 0x0a3bed0627d38baL, 0x1e7667e2a086db6L, + 0x18f5fd8de9621e4L, 0x0823ecbb5fadccbL, 0x1c3b44a8560a456L, + 0x1a3d9d427bc2a05L, 0x1f6b75793583d83L, 0x12182fa76dab049L, + 0x1f325fc13ad8ccfL, 0x1b247d5c804755eL, 0x114b52cfa435c58L, + 0x0159672c9fe7449L, 0x121b95cc416533dL, 0x0366934cf88b3faL }, + { 0x18c0b3b12f4f3acL, 0x0e7f14ce8defd96L, 0x13e0c3cdcc9ac0fL, + 0x06f8b51904a8006L, 0x0d8f144222dd689L, 0x0ba17975b849e86L, + 0x16b76249e569d61L, 0x0bdc2be505810f5L, 0x07bbdc74916ab7bL, + 0x187f205d2c565daL, 0x105faf8aeb0e6f4L, 0x134d8c3409781bcL, + 0x0df27355694b4b1L, 0x18558cb7c99c61aL, 0x0232597a3c0dd08L, + 0x1704df45df970d9L, 0x1c219eee274c7eeL, 0x0193e031fed1a2eL }, + { 0x1399eff5b47cd53L, 0x0c34e8ca1d77f55L, 0x11ec500aa19aefaL, + 0x156384b42dcc9d9L, 0x022de271c3e7c2aL, 0x16b52fe210b5bc8L, + 0x0ccdb9637f320d9L, 0x0f9a2b2a13db502L, 0x0370400f2130bfbL, + 0x1f2702cc9da43c0L, 0x0e87f8e7cf34886L, 0x0565dd969f0e0c4L, + 0x166c27b83b72aa2L, 0x0d2fd2df8d7a624L, 0x0c06bc9e90aa52fL, + 0x0225935f7504491L, 0x056eb6b9d2a3670L, 0x001078ce8e06fb4L }, + { 0x1051a86a4dbba20L, 0x075e36d8ef2e29bL, 0x086799496102d86L, + 0x1ba579989b34f01L, 0x10285a249440302L, 0x04313474ff811e8L, + 0x0451cee4dfb8ce9L, 0x19fc6fdc5e499acL, 0x079fbbfd3a3d057L, + 0x1dd0b69e66ef7e7L, 0x0163b16c8c5c9d7L, 0x1d7ce41875b722cL, + 0x068b4f6bba47699L, 0x18c503b81313a1cL, 0x128458152c024abL, + 0x11ec133a121d759L, 0x144f757e1ff0c88L, 0x03cf39390580282L }, + { 0x12acf252820a239L, 0x1cba75573598831L, 0x1ae92302877ec68L, + 0x12b47dcf55ac3faL, 0x1980446dd2453c3L, 0x0b33b7aa422ad05L, + 0x1d6867ca765ef78L, 0x10be4a59418f126L, 0x1e961af3e7743a9L, + 0x063ce2b3366dec6L, 0x0e153b2f14e3e5cL, 0x0e75424d0a38294L, + 0x052a9f558c58daaL, 0x1de8af02f4daddaL, 0x0864e74debdfe0fL, + 0x140ad4890f24e71L, 0x06de428b2b59511L, 0x0000e9e71b80ac2L }, + { 0x0be36b9e145b1d7L, 0x1c9c5004e2b326bL, 0x19f79f03db6fcf8L, + 0x0d8687ea725cac5L, 0x190897b1951044eL, 0x17bcbe52d5b15c6L, + 0x0a392c687dc2d44L, 0x0bb239baea8ea1eL, 0x1b4c80e2fffb816L, + 0x0f69ce3aca68159L, 0x0a92755a0cfb719L, 0x0979e6d27431982L, + 0x0afcd2c404e7369L, 0x08ea00ca1a6609aL, 0x16179181c6f57f0L, + 0x0f4080aeb208ff8L, 0x084b3280360790bL, 0x025dc637e2057e3L }, + { 0x120e2ddfd0f8796L, 0x05206d899e4ef18L, 0x1b02a4da71b9a5aL, + 0x0cc00e4e77fd46cL, 0x0cb8143937e5b6dL, 0x15e0029cf276784L, + 0x0d4f121ffa7367fL, 0x1d7d715e8880333L, 0x02f124e3b293519L, + 0x10610c564164e0bL, 0x075bc9c27716421L, 0x0a8a6daa0a5359aL, + 0x1959120bfc5696dL, 0x087fd348601faefL, 0x10ca09e668fa234L, + 0x0bb13a9f39f4ad8L, 0x0782e8fea9e9a13L, 0x01b4cd440db53bfL }, + { 0x1ca33721eb1c64dL, 0x19d16f8e940aa2dL, 0x06cd94dc41bfa73L, + 0x029ef97e9b6fc5dL, 0x0058b37f06c1715L, 0x1a74e2e5ef20b71L, + 0x0e9d60b14e9fa20L, 0x00529b7bfc5d358L, 0x1795ec6cbc5e67cL, + 0x011e12f8a135406L, 0x134835aa353e7e3L, 0x14a9a76f846bdc5L, + 0x003d7a4d52838daL, 0x1c0e5a39dcf0476L, 0x10c72ab2a51d7a5L, + 0x0a30ee4e3e73cbdL, 0x18b1df08e9f8253L, 0x0279d258190457fL }, + { 0x17b81071ed095f8L, 0x1bfd36d1136a707L, 0x014abecdb4748f8L, + 0x1c0fb1c623161f3L, 0x03e0f16eb114634L, 0x0f761bdcb1a54bfL, + 0x087049152ee7108L, 0x0f969d9abb7ae56L, 0x0f96038686df20dL, + 0x1a9acfeefc37051L, 0x1553e96b1222aa7L, 0x0957a2093be9887L, + 0x1eb020607a56d71L, 0x1d01192f098a959L, 0x0ba136d26f87061L, + 0x0f70089e49e94a5L, 0x1fd9e525c030b5aL, 0x036c3a2235368bcL }, + { 0x09d07aabe9a42f5L, 0x098b61bc0e66469L, 0x09b6771a7a847f5L, + 0x1f11fdd234e34ebL, 0x18d44f124e19e0dL, 0x174a724ce15a6e7L, + 0x1330817db7e48c6L, 0x1d64ff750ed9e51L, 0x06e1a0f01f57f7cL, + 0x01f8f9a79fe9dbaL, 0x17129d0b07484f8L, 0x04e0fbd70b0141dL, + 0x1faf0848bc5caacL, 0x03d63ace87aebc8L, 0x13f14c45fd452b4L, + 0x01e7b2b472e6920L, 0x00995a4aca97bb7L, 0x01e79c264ffce2bL }, + { 0x00506bace1fc9e3L, 0x10ba133b581ccb8L, 0x0e379cafdecd25cL, + 0x10f36413ee56943L, 0x0e26a8e1ca8602aL, 0x1279cd482c05c86L, + 0x18b847bcce6dff8L, 0x1e96d8bb322c526L, 0x151174e1a577b24L, + 0x1c07e5a82f228f4L, 0x05ebec520c86f7cL, 0x0d76e8fcba55e9bL, + 0x05be99a60809980L, 0x0a2af41042a92ebL, 0x15829949920a367L, + 0x00ee11918a80bb0L, 0x1263c67e73c7103L, 0x0159244287739efL }, + { 0x173cde68541159fL, 0x1260c27da085910L, 0x18647cb2871de08L, + 0x0d51647c800f450L, 0x06b2344a52c207dL, 0x1694a2838d01085L, + 0x131b36c3961f2d7L, 0x172d8ad71df021fL, 0x11248c58f62d843L, + 0x1c81b1eba6334baL, 0x03dfcb99b19bd92L, 0x0883824d797cc69L, + 0x0373ce49e8b2f9dL, 0x140d86f85603f95L, 0x118874549219d63L, + 0x0943942116a9a3aL, 0x01517261ece7441L, 0x049c59de6351d61L }, + { 0x1e4a16be4ded340L, 0x0fd954074401b54L, 0x181b735ceb2e399L, + 0x09554caf532e112L, 0x09101b061c3a043L, 0x05db2679827e2c2L, + 0x0b7d7983ed86b68L, 0x0bf031855d9eaa8L, 0x17402057656f76dL, + 0x0b35bc849299ecbL, 0x195795d35bad7edL, 0x036b4ab6896f5c8L, + 0x1b93747ea560f7aL, 0x196d672b3cb80bcL, 0x1a0f01a2b9f83a3L, + 0x0e683308e8c0f09L, 0x16b24e8c9ed1530L, 0x0367fac52ecf44eL }, + { 0x08c01b003e51f68L, 0x0f9128e97f3eb28L, 0x142c26f62017874L, + 0x1407c82b6fef331L, 0x007d9798255e907L, 0x029c4b68a4233ebL, + 0x143d01570ec7a6dL, 0x1b86a002027013eL, 0x0fbbb2fa6d0233fL, + 0x1b405857f8c105cL, 0x101370e34c5f802L, 0x088999918fbf63aL, + 0x066ec13f84133d5L, 0x023717243fd423fL, 0x18eceb30cfe0f60L, + 0x0d5ee78c4ff8a90L, 0x1275f67f8aaeb93L, 0x02ff2564798dbc9L }, + { 0x01aa4bf8b6f401eL, 0x18951d6ae3f6a2cL, 0x1c99bec1ed28176L, + 0x09384579a8f6030L, 0x09371c95fdd11f0L, 0x123757aa2a53ea3L, + 0x05b4019b157ee66L, 0x0b830c6f8f8ffdfL, 0x0bafc1d346b83e9L, + 0x0e1c2c9805da16eL, 0x17b0acd39f9c495L, 0x1f6163099dd1bb1L, + 0x0249a2786469c9cL, 0x10087973c6e6062L, 0x1de9080a43657c8L, + 0x17b5b0dc4a992d2L, 0x14820931c89eb2aL, 0x0409bb8b2090e02L }, + { 0x066b25e9c5a8edfL, 0x1c461083c53d6b1L, 0x0df521dbbb7db84L, + 0x12c4e88c2ebe04eL, 0x1385382a242fa7fL, 0x1b8df79f167decdL, + 0x02a4aeb6b5ec40bL, 0x068ac5579f4cefaL, 0x0573ebd1751fdffL, + 0x1fb2c293e12863cL, 0x1c5bbb11f2a25b5L, 0x1360cec4593dc19L, + 0x02f8f2c0758ccd7L, 0x1300428a98fe2c4L, 0x1a316ea48cacdfaL, + 0x08dfc9af766c305L, 0x198bf24735cd2f1L, 0x03ce140774e696dL }, + { 0x1cc8203f2b48122L, 0x0248b582562475eL, 0x13727f12217aa30L, + 0x0f0582003959e0cL, 0x076de250ab83899L, 0x0d5c10399cf390bL, + 0x12cb85ea96baa38L, 0x06049a51940d782L, 0x0570c5bb7816b62L, + 0x02891ae67735b03L, 0x0fe27c60fab909bL, 0x078d38cc4e96365L, + 0x06b51e38bc3e3afL, 0x19f2071df058221L, 0x0f96f909b6f1639L, + 0x1e8107f3baaf16bL, 0x14f9fd9f79152c8L, 0x03ac039d254f1ffL }, + { 0x127b0578691ca22L, 0x15feb09d150db3eL, 0x0e16b1e5504fc81L, + 0x14eaa6cc0fd097aL, 0x08a0e24cc5d18a2L, 0x03a6de970b36f3eL, + 0x010e95b55d430f1L, 0x065bde8898226cdL, 0x114646e53cf4b84L, + 0x1e0681854fecbc1L, 0x132090a5fb880d2L, 0x017ffaf7cd8f7b4L, + 0x1608c7f3ff3d0b1L, 0x1a7ea6229690b23L, 0x1a784101b949666L, + 0x1a65bf7573f4293L, 0x0a89342a7fa8661L, 0x01f9f1a2c7d7b35L }, + { 0x1ec35af951597aaL, 0x1ea5624efb275a8L, 0x16726fd3bfd6d9dL, + 0x12a2b4526a04ed9L, 0x1d9bb9c3423eca4L, 0x10f84e4534b2a9fL, + 0x17e63e67ba77fb7L, 0x06571f452ac333cL, 0x1b763875835292cL, + 0x19a76ee7e20740dL, 0x157a7d9515f6561L, 0x047c618f1a57b05L, + 0x0cc1433d67c8ee3L, 0x1e418a5773bd972L, 0x038bd8d5b67e01cL, + 0x052bc883ddbc454L, 0x0ef1e9e17ed6c48L, 0x0320690621a614aL }, + { 0x09a0b8e3284d513L, 0x01aa2f98a829d27L, 0x101d16b354a81d3L, + 0x183bca1b6f66dceL, 0x0549fc46d80bdcfL, 0x1f83d446cea3ee1L, + 0x15308a6dbbc4cc0L, 0x0e69c8c3594da95L, 0x1ca8e351dfc9f1bL, + 0x1e204a6aba30732L, 0x00accc3ccb4d9e2L, 0x096c50ae85d16c6L, + 0x11876c29c369a07L, 0x0895e8bd6ff2958L, 0x06a98e7ce791826L, + 0x00b831dc81acc69L, 0x016b968902ac72eL, 0x007ce0e54606c94L }, + { 0x0bbaab367433df3L, 0x129a38ae9b1460fL, 0x03625fc31732daaL, + 0x16cbc811f227464L, 0x1537345172c918cL, 0x06e504a5b1c42a6L, + 0x04c99cc4e668c2dL, 0x1119e4ace601476L, 0x15ea60dfa6608b3L, + 0x056ba583d9486feL, 0x009e275da53e6d6L, 0x1b716cc61f63064L, + 0x10c65e3eaf48593L, 0x1f3931fc1eda3fbL, 0x19bfccd8e527244L, + 0x1048137359d8dcdL, 0x0c534bd9ba7098aL, 0x03f18e097a2e9b7L }, + { 0x0281d680dfd2dd7L, 0x165801255b0ec5fL, 0x017e510c7e5c7beL, + 0x152b39677973860L, 0x0ffbb406660c8dfL, 0x14d086feeafe186L, + 0x1f46de918c6f9e5L, 0x0ec66dc613dbc27L, 0x176b3bfadfc9470L, + 0x148c92eee639111L, 0x1c35cc55b13b87eL, 0x1c821c566e8ee83L, + 0x13efc4d93c4f64eL, 0x1e27dd97435f496L, 0x1f286ef14edf80fL, + 0x174c15832d9ea66L, 0x1574de41a307e23L, 0x00d10ce229936a9L }, + { 0x1cf7ef8aa4db0bcL, 0x18c033db64cb1feL, 0x019cf62864bcb88L, + 0x05ffb8eee384c72L, 0x02fc0edbc0cec2eL, 0x063021ccbe471adL, + 0x00481e3843b060bL, 0x11dfa1bc5965619L, 0x14d6c457f69e57fL, + 0x09f34d92da9f8e1L, 0x08cc2b13e272e25L, 0x06532aacd7cc845L, + 0x0d437442d192ff2L, 0x1f534a01b9e6a81L, 0x00c198bc1339642L, + 0x17f26d582a6fdf0L, 0x12fe02bcf77b6d0L, 0x00bd554ccde480cL }, + { 0x13d56438e55db2eL, 0x0f7219dca342886L, 0x03956e2118be0d7L, + 0x0bd42fc4f834288L, 0x1d95f7a9a6ff3b3L, 0x0b396791fcce1b6L, + 0x11701c85ff766f7L, 0x04be801583dba40L, 0x094b55c874ff06bL, + 0x1225072872524dfL, 0x097a46d0eda04c2L, 0x1bc2429f2d8bd12L, + 0x0c0f97fa9778bedL, 0x12dfe93387a2b52L, 0x1d823be8a3f61aeL, + 0x0e97876965b1f7cL, 0x04afbd5ff8c2264L, 0x03594157852f9d9L }, + { 0x0fc025f6341a595L, 0x01c6b5222f1463cL, 0x18f7ad11a109647L, + 0x06eaa8f066e57adL, 0x083e16c43f9466dL, 0x13d65a488a0a698L, + 0x1ed905176519a56L, 0x162205bbe131fa5L, 0x02a2b2d2d0bfd87L, + 0x0f4df2e2ca2a844L, 0x1e2fd2a0091779aL, 0x1ad16460d61ddc6L, + 0x06c2be9f3d80b0bL, 0x04016122bb52a2eL, 0x104b7ed0a7459edL, + 0x12ec427cc884e56L, 0x0bfb664f529ee8dL, 0x036a7ae91aa3837L }, + { 0x1c8f2b600ba9f88L, 0x003f03ddb685f9aL, 0x150acee0796ff72L, + 0x1d4f58f03c1424dL, 0x137dcba6335ce6cL, 0x04b2439f184737fL, + 0x10d340a3729898fL, 0x04ce5d74afd1030L, 0x1a9e3d59f79b78aL, + 0x17853ee9783d751L, 0x1919e093417dd34L, 0x02e0022dbd6dc1fL, + 0x1258f37580b2085L, 0x1a0385d9ce152f4L, 0x05df6439e2f5e95L, + 0x10368aa3f90e573L, 0x0ad6eda93c440dbL, 0x0255785a7eb2e9aL }, + { 0x1ef25063514c7afL, 0x13ed6de0c0f56cdL, 0x1a1e3e8fb162c27L, + 0x0a2e770d0bde795L, 0x121d32ddd8dbfabL, 0x0ce233592487e04L, + 0x16f6d3bbce1ae2fL, 0x1b7839baa5f40c3L, 0x064de989a25bc04L, + 0x17cc1b5c2b9431bL, 0x16a0122f912a801L, 0x1c9c12e0318e234L, + 0x17b2c11fb116dedL, 0x1390f66cb95762bL, 0x1afcea45136b786L, + 0x029aff338a4d7adL, 0x137a1d4165b1c2eL, 0x045965e9cc15e31L }, + { 0x0ec1bf28a52e991L, 0x1017b67cea17614L, 0x04c318d3a9142e8L, + 0x078aec5739060faL, 0x087c2a2d3fc257bL, 0x0ca4455e994c68aL, + 0x01b4b2853c69e8cL, 0x1138e1952760d74L, 0x19aa3f4b3ee405eL, + 0x03277599aef7573L, 0x17d5e00efc75333L, 0x016a8ac2d7fba2aL, + 0x06086e33f6041ecL, 0x18121e7a91efc07L, 0x1333560e669e723L, + 0x190630d85049d0eL, 0x070220eeaec8fc5L, 0x02bf141823edf1bL }, + { 0x060b698fbcdf666L, 0x0354cc5f5d8e937L, 0x16ea012610daf74L, + 0x1ca457911a80895L, 0x08423b20d76bf75L, 0x1cc53932ae25cd9L, + 0x1d8059703d2494cL, 0x0b4eda9e56e1946L, 0x1469899252030faL, + 0x159bf43db02a382L, 0x1bdcc54f786cbe5L, 0x19195aa9de0bdf2L, + 0x0aa93617b05ecbbL, 0x1e5d10bef5944e8L, 0x1528b5ceb03ef55L, + 0x0c0c7a1a796ac33L, 0x1a6e8bee9d4c91dL, 0x02789701bb4b7feL }, + { 0x0cfa42215f1a610L, 0x12e2a9bc328cd26L, 0x1151ce0e04d2012L, + 0x0896509c54248d4L, 0x146d1320fa15b48L, 0x14507d1b2326328L, + 0x0013bedaea231c2L, 0x0d4e9cf9dcf2789L, 0x18c34d22cb95ae1L, + 0x0cf6c4ffce0ea6eL, 0x0219b4c8094dc67L, 0x056537ac8894c34L, + 0x0cf277bab145b23L, 0x14a245817c44749L, 0x1487b2dcf9a71baL, + 0x15f643492dd52b6L, 0x191a8f78ea75858L, 0x041e9199f589337L }, + { 0x063328867b478d7L, 0x10d70a8517e4e0eL, 0x0cc06348906e87bL, + 0x111279ad2c0b6d5L, 0x08117a8769f1f28L, 0x139ebb8aceb3305L, + 0x17c2ba0480465c3L, 0x164a51fde0127eaL, 0x1b3978db8d854dfL, + 0x15a1f7b7a2ecfddL, 0x192ffb56fb8e5f5L, 0x1eb2d7eedb5a2fbL, + 0x0e3d40754ca01e0L, 0x1c7437799459140L, 0x147961a3b6d848bL, + 0x14ab7044d6d5f6fL, 0x021463532152f40L, 0x039b1789f62d18bL }, + { 0x12eb27c73c0c430L, 0x0532fd28e1b2bbcL, 0x1b3b48653c6e330L, + 0x110296928ea14b9L, 0x0b6fbbf41894568L, 0x1543045df8540d2L, + 0x1e578ddbd3d63c2L, 0x1abb26c3ad0730eL, 0x1b6510cd8e3a8d0L, + 0x1f17edfdb60d22aL, 0x04553abb2247e58L, 0x0e2bfead1ec8592L, + 0x172f2b399e0eb1eL, 0x04f85f85f3d7ce6L, 0x060da547f0e6eb2L, + 0x04151e10c3b2521L, 0x0add9b16f02da0aL, 0x01788349fd1c607L }, + { 0x1a6ce910c06ded2L, 0x0421797ec843d83L, 0x1f5aa7d8d69be5dL, + 0x023dac0c4dc8d17L, 0x169ee54804b6189L, 0x0b51008fd97c4f9L, + 0x0ceb272f4444f72L, 0x13cceb359fc21acL, 0x164ba66fc8faa62L, + 0x1435724a3f9c141L, 0x10e81756736a669L, 0x162811d45edd051L, + 0x04af3953c87c7afL, 0x0ed54f2792a8e47L, 0x1bc65016d4f49e6L, + 0x0f9b63dfed1a95aL, 0x0432775dbdd9643L, 0x04c2fc1f227f3d0L }, + { 0x1603c16eaf45294L, 0x188b06125aba8c4L, 0x0060e75ad4b5c04L, + 0x05db28668098224L, 0x14f41b687079cf0L, 0x0560f0862d8145bL, + 0x13c38f70fc1da72L, 0x044b58bdd47f164L, 0x0ee6684bae34c5cL, + 0x092cf31cd5e2295L, 0x14b347a77d17329L, 0x1926348879f560fL, + 0x0992c003b307019L, 0x06c65e17347eed5L, 0x1e0729cb67c5e70L, + 0x18f3377e2b4de3cL, 0x0f154d779d550dcL, 0x0064472a007f4b1L }, + { 0x0f71a6ae8f44357L, 0x1a5fb1d1e55b542L, 0x16796baf1a03dd6L, + 0x0914ea7de466993L, 0x075e3c8ececaf08L, 0x07c69d71400a608L, + 0x0cabaee7568e3ddL, 0x124eb3108c9701cL, 0x17b328e6ff2bc37L, + 0x1dd8fd7f76870cbL, 0x1ab25568cc196baL, 0x1b1f245b79d0ce9L, + 0x05987b907a8c19fL, 0x1d9d166bc60bd74L, 0x01ddcbe27ccd89cL, + 0x19dadd75d4033f5L, 0x1154e5de4993a25L, 0x04712b05c578883L }, + { 0x0d3746c3141aba6L, 0x083cfdd5967cf2bL, 0x00c673749f1d168L, + 0x053bfb2a1d6c705L, 0x1a9408ff2223763L, 0x0b008c0f058ae69L, + 0x0ee9d26a00802c4L, 0x1aa4e33b6bb4707L, 0x16078340a651046L, + 0x094ea6f4ba91d8fL, 0x00d1723828a2ae2L, 0x158415be138e808L, + 0x052331d61161275L, 0x09c8e5285a0d593L, 0x0488c548c331df1L, + 0x13453117c19251fL, 0x0e5fef3d92b92fdL, 0x02c802f91419279L }, + { 0x1b1750c3c4c1c74L, 0x1d56074b37dbcb5L, 0x16499b165cfef9cL, + 0x04750cad6d0b4ebL, 0x10446cde8c97f93L, 0x19c4bf95b821d8aL, + 0x1cac952245bdcffL, 0x1cd227ba0396316L, 0x0d0a751f1488c0dL, + 0x08bab8a42ac652cL, 0x050c0512998f686L, 0x015961c10c312eeL, + 0x0cf39ead9c2df19L, 0x0b9c16d080407e0L, 0x18a8ce00216b1b8L, + 0x15d1bd2f230a264L, 0x16ee4495936b43bL, 0x02bd3c7136bc1efL }, + { 0x01b346f40dbddd8L, 0x0d493ca0861d60bL, 0x1e0c621b3cecad2L, + 0x0467727bd718a84L, 0x00df579d72df323L, 0x077a804e46acfaaL, + 0x0190f975e99f708L, 0x18788d67230cfe1L, 0x0ecfa2445ad96adL, + 0x0c7ac4d8622a268L, 0x124c0782105f5d9L, 0x1ed588a9c511cddL, + 0x0fac0f462d6ca5eL, 0x046c501b20c8824L, 0x14d6dfa14901f60L, + 0x1b50f698a674fedL, 0x0e83251e4128f6aL, 0x00e51b862c0e239L }, + { 0x0bd5171a801b68aL, 0x143ce7e8ccc59caL, 0x0afd0458c809cc4L, + 0x09eb603fb6920b5L, 0x1cda128bb5fe87fL, 0x1e98fbbc6f291d4L, + 0x130d42fc586871eL, 0x05b6bbd9fa04720L, 0x0224b2882e188f1L, + 0x0e9400efcced73aL, 0x119ed4233473483L, 0x187b810cfc7395aL, + 0x002b4250726c311L, 0x177ec801b8d08b9L, 0x0f4ec0e0efd1938L, + 0x0b754a7a089143bL, 0x07932db52f4e626L, 0x012c259a62619d6L }, + { 0x0b863892aeec688L, 0x1a05d22fdf2919eL, 0x07dff582d7e2979L, + 0x1890e9227a845ceL, 0x1a17d80d455d185L, 0x02a29202615d9b7L, + 0x0995cfc9c6152b0L, 0x190edba608b5173L, 0x02e42c3e162ee7cL, + 0x013338326fb63e8L, 0x1f754771f2d2200L, 0x157c30f12fc0b24L, + 0x0ef2d5737c6b3faL, 0x1fa8d4ffff35691L, 0x001eeaabed809a7L, + 0x14935c3906a8ad3L, 0x085acddb6ff951cL, 0x03f4089ba1fcd58L }, + { 0x1722a8b830a88b1L, 0x0c75467088bf0d6L, 0x02e01026d1f6464L, + 0x06d88da3a67c05aL, 0x0589669cb53812dL, 0x1866af17e84ed87L, + 0x1114e6117341856L, 0x19618382ab4470dL, 0x1da774de5f5ff43L, + 0x183b5cc71c8e066L, 0x1c7bfd4013ca1aeL, 0x08d95dd817fd2faL, + 0x0732a1ad9423e0bL, 0x1cb6d2117229c33L, 0x16caffbf8327e04L, + 0x1f522c6ed8344c7L, 0x1a6001c7918ba56L, 0x021b5c6326fc242L }, + { 0x0117e9d8ab764bcL, 0x10f4a503befc244L, 0x174c3063baf77e9L, + 0x1ff928a3b8b4eecL, 0x071a347a548916aL, 0x1da0ef80d297198L, + 0x10a198cee577ac8L, 0x0d1bafad1928791L, 0x1e4f9d41e18d970L, + 0x0c845c846493cceL, 0x10523b51ce528deL, 0x0a2f9aa3ca7fcc2L, + 0x1e0243dcb6e5018L, 0x0bcaa202a83003aL, 0x1f697ff97737988L, + 0x196ccdef921c2a6L, 0x1e11df7aae40768L, 0x02933654f36df4aL }, + { 0x0ddee6d1386b3dbL, 0x057ad3e1c72a042L, 0x1103ac13d277e79L, + 0x11fbcb49fb66830L, 0x10257cfc2138a1eL, 0x1eb8609f3734921L, + 0x07fc0d4671b8c67L, 0x1d11e69c2e90d86L, 0x0f1e298fd940ce1L, + 0x1dc658e8a4b06beL, 0x104d1cacbceffdbL, 0x016828ddf1fe40fL, + 0x0b7bd3e220899a2L, 0x1135f513bef61b1L, 0x0d32d9ea5d41139L, + 0x0e0741e6568929fL, 0x02bc17a09201fc6L, 0x020f992dcce6c25L }, + { 0x12ed513ce2843a4L, 0x024c70039457e18L, 0x0089361933979d2L, + 0x094c40107751de5L, 0x0bed338d3406470L, 0x1f3d9c2c82f0ecaL, + 0x1eee4a95e32d418L, 0x083304edb2c513cL, 0x0dfe2dc47f17b73L, + 0x091a90f8ed644a2L, 0x1b4a348d002a9d6L, 0x00bd4ec374867b6L, + 0x0d9bfd07ddc6477L, 0x1216547ec4a3dd3L, 0x030d1a003cb8eb0L, + 0x031fa93de8ce1d7L, 0x09e7db3d37bd9aaL, 0x02b5987db72c675L }, + { 0x1ecdcaacd80a428L, 0x0916e4399644883L, 0x1e60eb69107debeL, + 0x092496011441b10L, 0x12e81c3a3bed9a4L, 0x1c03e99091a99e5L, + 0x0bb2f0d3901d597L, 0x11a17f5df4a3e5fL, 0x178b634a5ade8a8L, + 0x0705bfc4a1c9548L, 0x088dde42ec73631L, 0x09f5f0e4095c612L, + 0x1585d3cd83dea9bL, 0x03291d3c9f6fc0fL, 0x10365a563e23147L, + 0x0fe0fc8e5f7162fL, 0x146899081e5dccfL, 0x009a9e62bac5ee8L }, + { 0x0a5649739bf6e18L, 0x05ad1324dc4e394L, 0x128373a2e39d67aL, + 0x02408e08191b286L, 0x0a7b8e82d935bf5L, 0x1c094a1559d0b23L, + 0x1ca5fc560fb589fL, 0x057082d4fc0e5acL, 0x149685d86cd39e4L, + 0x13cbfe3cac6edd6L, 0x03e4a055739b7a2L, 0x0ae1f146c46b4abL, + 0x0052877ae575f4eL, 0x1358b75ede34e7eL, 0x07307c63d064ea6L, + 0x1cf131a3be87976L, 0x158723a830e5a21L, 0x01f610c2efa28efL }, + { 0x1d4c7d71f0bc2d7L, 0x163663728ea095cL, 0x164e827e03d9a60L, + 0x0a08f5c13925c05L, 0x17f351f9b7dd2d2L, 0x1c285f1a818a4f9L, + 0x14b21a75273871dL, 0x13ac048559625e1L, 0x0ba188c567bc28bL, + 0x1203090835e02a8L, 0x012c7e35f50ca63L, 0x15cfa712a3c161bL, + 0x1b8bc97607b4a67L, 0x0a4bd5395a93e2bL, 0x0f7599af24f17cdL, + 0x08f46be3bd19873L, 0x1e53087dc5ce9d4L, 0x044d9ab5b5108d5L }, + { 0x16db0afdfdcc837L, 0x005d55438dbd4f6L, 0x1f2470752dc83eeL, + 0x0f5b593cb882757L, 0x0b8657a3f5b56bfL, 0x00eca72b32516d4L, + 0x0d96046c13dc839L, 0x1d4c7c23a4c6e86L, 0x0ee628ecef426daL, + 0x08b0ce4e58b16e1L, 0x1605fe1d92190c0L, 0x0e04ab09790d39eL, + 0x0f00bf7928e1bb9L, 0x0e30777296613e7L, 0x0b70be53bcea03bL, + 0x09ea4fc24057d0fL, 0x126656f18e08a0dL, 0x01ce27886abe2e8L }, + { 0x1a9b68ce88aecd3L, 0x1848c528c554ed9L, 0x16b52f53b951556L, + 0x0e040d1b09db839L, 0x011ac72d79b68b6L, 0x0d053c3ed640684L, + 0x18a0db479b4d6a0L, 0x0899083d3d477a2L, 0x0a7bc1775894c44L, + 0x15b1b92f8d50901L, 0x1dd9fb1f53155bcL, 0x1767a8dfea377d8L, + 0x0d73f7e3392817eL, 0x0d7692627ef2df4L, 0x195e73d131b25ddL, + 0x1f79817342e0f6dL, 0x100cff164789069L, 0x020a5aa16a48a95L }, + { 0x1c31e58606e173bL, 0x1a70dc873389d19L, 0x144b7aec82bd6dfL, + 0x0e0a241ce084bf6L, 0x1013e4ecc788c61L, 0x03736b9f782b014L, + 0x1a42a7e74d6b207L, 0x05dc263d11f28a0L, 0x1708f9b3244af08L, + 0x1726b360dd15754L, 0x1d29b9d036ca72cL, 0x0491a308600f5e3L, + 0x18ed556a6c74ab9L, 0x13868bd30999c77L, 0x023d6ffd23988f8L, + 0x10a2a78e6c5f52cL, 0x12a43977874444eL, 0x02933c6b57005c5L }, + { 0x1ff1c59df36aeb4L, 0x1329e5495e055aeL, 0x125a49e97e054b5L, + 0x085bfa923e1c07eL, 0x0571f89b8509d41L, 0x19a24292c616295L, + 0x07824af5860124cL, 0x00c3467d29e7efbL, 0x0fab418d32c1bf9L, + 0x1ce24872d52b4aeL, 0x0465bbdb4b5fffcL, 0x00ea1ef291521c8L, + 0x12d3053b4f3ecd4L, 0x0eccba64a5ac7cdL, 0x08bda0ae3ba10a9L, + 0x19d4c474b383b7eL, 0x0dd045ac614c8efL, 0x038205d2de08677L }, + { 0x0364f81515a1a96L, 0x11a818c2193f016L, 0x19406b64f53cc69L, + 0x024e76c2e61412cL, 0x12cda9d29d7694fL, 0x0a60bbc4436c3b6L, + 0x1a5ac78069d08a0L, 0x00c69244ed70cceL, 0x02fd4f0c65b25f0L, + 0x0939a4ffd94a625L, 0x18362b7874cdbd9L, 0x07d1cfc70c1d83fL, + 0x01b774c31eaf9a2L, 0x01b2bc254be95b9L, 0x1d3aa8feb0f9609L, + 0x06491fe5bfe9ce1L, 0x1c13d281e1afe87L, 0x04821d36b05e8e4L }, + { 0x111a0fe766c7937L, 0x0f6ae55de1df18aL, 0x0333802222b06cbL, + 0x1ac2c401e65582cL, 0x14a2ea06928754bL, 0x1f0837dc00e41e9L, + 0x136522b5e80ea72L, 0x10132d610459dbfL, 0x1c3c3463ae40698L, + 0x1897526facbfb31L, 0x14e0d10324abe7eL, 0x0b8c9d1b42a8591L, + 0x02db4e801a79bc8L, 0x0f1abcd94abb8fdL, 0x0ab41e1ef4b04e0L, + 0x1588dc8b8ebbfffL, 0x135b0760a3cb73eL, 0x0131b15a41d092fL }, + { 0x1c68d28eefc3e89L, 0x1743bb4f4f73892L, 0x0e1abd792dd4b43L, + 0x05970d6667160f7L, 0x1f552bacdb70907L, 0x06d0f4fe9e90757L, + 0x1c51697bacac530L, 0x10a723ed11489f2L, 0x121fbd3101e06d4L, + 0x0f27952df54e6a4L, 0x0351929efc87691L, 0x11900a9aa8e2f6cL, + 0x11bee0f2e9193f8L, 0x00a1c939ad6729eL, 0x11ad7ba4b09958fL, + 0x0b375390dc1652dL, 0x15e452fe23109ffL, 0x0174a95902aae49L }, + { 0x0846bcad75f886eL, 0x12edf6a1efe2c15L, 0x16d801ec6e1b9a2L, + 0x126abfe56a207c8L, 0x0263ecc9580e2ecL, 0x0f2f19de3817935L, + 0x081d8a0d6ce1860L, 0x0da04a227d8d824L, 0x1a5c26e3a7fbd85L, + 0x17c1fd9ceb75e58L, 0x094fca9134bea23L, 0x1e66a763f52ef55L, + 0x1117559a307c14eL, 0x1849bbf07fb0250L, 0x0bc09ccaf365ac2L, + 0x1de0d4b82912db6L, 0x04b1c0a84c9eb53L, 0x0091b680b981bc7L }, + { 0x1481c8fc084373bL, 0x123b432304bd76bL, 0x1e8184ef0d2ca6bL, + 0x19269785602601bL, 0x0e2be7e23712714L, 0x008400432923148L, + 0x115d9553eee7fb4L, 0x105e1d816708462L, 0x165baf594330a32L, + 0x1eef0d438377c0bL, 0x11c9f6e9d4c3a4eL, 0x1acce9992b96fa5L, + 0x052438906dbb0c5L, 0x08a32c79d9fe69bL, 0x05fc3a466206507L, + 0x18fd5cc2deaaad9L, 0x16e353c2d854b9eL, 0x00152400a31065aL }, + { 0x1d6d23d506ccd38L, 0x10e2a482cdd5308L, 0x109da74047148a6L, + 0x0db05126fae2f93L, 0x03835083e87e1b4L, 0x0d612c7aeb1dddcL, + 0x1347fc29ed09eabL, 0x1fb33564d7b3e2aL, 0x0dec0ffbf8ec955L, + 0x14abe33a4fe5c40L, 0x0577b87804537bbL, 0x096e6d3e8d8e647L, + 0x0091eb2599192a6L, 0x117461ed2182233L, 0x155b462f8b6a21eL, + 0x0ebe7489c584b86L, 0x1e031390414b55fL, 0x00ec5ef37c790bfL }, + { 0x1cd39f8a2028924L, 0x078ce583765cf81L, 0x12df5bc16119b95L, + 0x0cb40c0eed0c577L, 0x110fec10dbe0671L, 0x0ddb2e49cbe4bd5L, + 0x0e8e3d084e099bcL, 0x1cc829bd9974ce5L, 0x1594d4d43f88b05L, + 0x0c9fabd564a6a68L, 0x10a9aafec5d8e1eL, 0x16b76df8cab4e9fL, + 0x04ee8d2139d8196L, 0x1b069d136e1bae4L, 0x0e4ee1ee6c02808L, + 0x0413d66dda6b9bdL, 0x1c1f565b28bcc83L, 0x01a4e34a1e30809L }, + { 0x1b394444de6c88aL, 0x16238a380103f68L, 0x0288870ade03570L, + 0x0810a1327d6de8bL, 0x1aef0c18749f756L, 0x1e38782005d2bcdL, + 0x1fafcb5d0a4e1cdL, 0x0a78b51c5d8428cL, 0x0243a666e5337f4L, + 0x0c8f8e3f685ea85L, 0x1cfa43d2f47e472L, 0x1d14be1c253674fL, + 0x170738963596089L, 0x138c1564e869d0bL, 0x05f170a73e10b54L, + 0x0aed24232a53210L, 0x0faa32f327e8725L, 0x002b2c3d5c4e16cL }, + { 0x08562ed1ce4733dL, 0x1fbe5cc728a2200L, 0x087ea6ad1ae57ebL, + 0x1d6c351826be060L, 0x16b3597689494c5L, 0x01697b2be4a81b1L, + 0x1c0f9afa1323cabL, 0x1761cb669b137a4L, 0x1c4ad918f7e872aL, + 0x1544f4fe2029770L, 0x0bb8fcc642d47b0L, 0x086edffe4a9f859L, + 0x08883e097258fd1L, 0x07d8aa1c379e06bL, 0x12ab8018f4283a4L, + 0x01ed98870ec97edL, 0x1de815f15653f1dL, 0x00dc3f976dc366dL }, + { 0x1792bbb2b0b15b1L, 0x05ad3e735d3bc9aL, 0x1f67763cdde68f9L, + 0x1b8531a3dff759fL, 0x047031c6005450bL, 0x0b4033071faaab6L, + 0x14b081dc3c1ea57L, 0x0a99c7d09c05a20L, 0x1b050791e7aa8ccL, + 0x0b10f39dd1911d1L, 0x06e534e58ca6413L, 0x168efd700adb0f7L, + 0x08edfca0cc8df9cL, 0x0b895065712186fL, 0x0122a64dd2fd05aL, + 0x1cb3d7c7e78ef11L, 0x023b22b87b1c4a3L, 0x0470113e21f4adeL }, + { 0x00e22a83210964dL, 0x0aefaff82b77580L, 0x087f6bc7ab5f733L, + 0x00cf9b95c6042e7L, 0x0bdcc90cd02833eL, 0x125a7a8e62ba65cL, + 0x00a621bb29c50c8L, 0x1d7a01cc075767fL, 0x1b98ece1b0c1a8dL, + 0x14523721bc6130eL, 0x077436985979748L, 0x113296fde1c58dfL, + 0x13bda9f306b3ae3L, 0x1c50426d9d1e0b5L, 0x053a5417a689b4cL, + 0x00d78a51cb326a7L, 0x16e848ecb114ea2L, 0x00a58ad5aa02a2eL }, + { 0x16d86c9664c59a2L, 0x115f0b07ebd5287L, 0x15a641cb2e38f7fL, + 0x1302ed4fc067f36L, 0x0587080b5f2325dL, 0x0ea702bcd06a73aL, + 0x0a38693b837bc35L, 0x1dd815b3ff590f6L, 0x1d6f18d2f3f09b4L, + 0x044b57394974ec3L, 0x0254f58251d8f33L, 0x0f5031f7f3f5951L, + 0x094b63d701dbee9L, 0x03f53917ef90707L, 0x0ad5c7f2ee9b8c1L, + 0x0abeb9cafc394c2L, 0x02e1e16ac76009aL, 0x03a15df6c621c4fL }, + { 0x1ea86dcc1dc2c73L, 0x1feade0b21d5f91L, 0x087c9363287d2eeL, + 0x01196b958e0ff1fL, 0x14e66a7dde68a6eL, 0x1bd6bc3eaa6325aL, + 0x0ae51e276e88aa6L, 0x0229b11aa81c6c9L, 0x0c8c2e02d1f72e0L, + 0x041302ba371513cL, 0x0d6ecd2c61f1f53L, 0x1bfdd71fc193cd8L, + 0x087d11e415ed8b3L, 0x1c32e3fcdb5e1a7L, 0x1b305f2ce422efeL, + 0x1ad36e2fa39cdc3L, 0x124151e3308f7cdL, 0x04bdead0a5ae4a0L }, + { 0x01c62fe81e82861L, 0x0a5b6eea1620770L, 0x156f997a4795c0fL, + 0x08b5777fbafca5cL, 0x072a45f4b8b4937L, 0x0794ec5a78afa96L, + 0x19d7f3a10d6a154L, 0x12d3beed736b05bL, 0x052e84c5fa20c8bL, + 0x1bbe9688545057aL, 0x06ef6329804f0ebL, 0x13744df060be071L, + 0x080cec8b9ab0d9bL, 0x1fd5ed0c7829f42L, 0x10930a9358cd9ebL, + 0x1745ca1ea77c94cL, 0x069f892c58c864fL, 0x018be3698a4662aL }, + { 0x03525b02cb7d42bL, 0x005e49887d65706L, 0x008bfc81023d549L, + 0x1fc1821d411aba4L, 0x118eb23d6b01402L, 0x12950cbfdf7b453L, + 0x035ba8051ad6904L, 0x102b35f9c90221cL, 0x0e9a1d27f022de1L, + 0x0dcb68b6e1fa4edL, 0x0b8fd7bef90021bL, 0x0c83d9978239f83L, + 0x19525f8636f9d70L, 0x013b1e182481113L, 0x0418c2cdda5e5abL, + 0x07e2f398690783bL, 0x0fd451651f0ee3dL, 0x03572cb9cced05cL }, + { 0x1b13bc7bff4d2eeL, 0x0a1149858b9ec2bL, 0x0f541e524db081dL, + 0x14bdfaab7d6c4a9L, 0x0e0c33891d5f232L, 0x10fca26037a542aL, + 0x01edf3cb16d6639L, 0x0998ac90c3ffabfL, 0x0ee261fb15a2afaL, + 0x07fb91316cbd3baL, 0x06b88b5b3c01eacL, 0x0a69a68de428351L, + 0x1f97b6497e28880L, 0x1d157ffe47f39dfL, 0x1469c9a2a1656cbL, + 0x170573df39e7de2L, 0x072a84ee5f1e744L, 0x033248246de31ffL }, + { 0x1b7bb781e8b760dL, 0x185ec12d56d5048L, 0x167fead489bf51eL, + 0x0d7ff8291d02927L, 0x029be3db4a6dd22L, 0x185585ad0197c55L, + 0x121a0c636f1c0d2L, 0x08db9997f6afacaL, 0x08506ab379c581eL, + 0x089b53714187671L, 0x1e4d5b3db2031c2L, 0x06efded63d0c916L, + 0x0183f0f1c9fa176L, 0x0b55f6ee964e0e6L, 0x0ec37925bc149b4L, + 0x10e747c1d31c552L, 0x1ec6f2d7ada0f13L, 0x0275c9dae79fd24L }, + { 0x189f7e5e11fae32L, 0x0ba7ae2011fa8deL, 0x137d2470fdbf44fL, + 0x0eaaa4f36e36002L, 0x05ba00681d849a5L, 0x1e51655dcf444b8L, + 0x19dbe0888906704L, 0x0555f776d0bfa66L, 0x1931c3f5275878aL, + 0x15777f7f79ea8b9L, 0x097322f629a1e04L, 0x1b67b33e182c313L, + 0x06a19d48b682cffL, 0x14e362705fab2a0L, 0x00105c95817888fL, + 0x03990a7cf03bd0dL, 0x168cdf5c90bc700L, 0x015ac16c9be021fL }, + { 0x1165c8281abc2aeL, 0x1c07af15b4f6550L, 0x0f481fffd9be9ccL, + 0x0ca8eeca0d812f6L, 0x157fa21c5d60382L, 0x06deeaee5d64f9dL, + 0x1cca9e1d436d326L, 0x0390bc42207b3dfL, 0x1ceed172c2f11c4L, + 0x071c9324f1a4604L, 0x0e4dae0c7b77eeaL, 0x1a0dea10c946e39L, + 0x0de93acfcd915c3L, 0x19f97bd57f4719eL, 0x1f3ba692fb8435eL, + 0x095fb83b1d691d6L, 0x0c04fa49ce3fa57L, 0x03c30a884c316daL }, + { 0x1e3f4807ae72c21L, 0x150a27e8786d29fL, 0x07a3e30e91518c6L, + 0x08a369e3578eddcL, 0x17cdbb24379ae09L, 0x1eafe6951d21cbeL, + 0x1bd69e8533ffa0aL, 0x19f77c9da25e84fL, 0x09b0a43ee284d3cL, + 0x1dbc5c9c776370fL, 0x1013919ee3a1ed5L, 0x180a686e984031aL, + 0x055428deb50c8adL, 0x01d7d167b21b9b0L, 0x0a55be6d3603b03L, + 0x038d0daa3f27875L, 0x0259f9a28ab8416L, 0x02a05b5dbb5e4e0L }, + { 0x0e1734c321d315dL, 0x0b3096c3702e802L, 0x0516eea336053bdL, + 0x1359b8f135d5f5cL, 0x1877570f1fb07a4L, 0x1e29ef3510f4d6aL, + 0x063acb92a0dfae6L, 0x08a86db65263ac5L, 0x143afbc78ea362fL, + 0x14b9ecbd55fb2c2L, 0x1f6af832493580aL, 0x11e0f95be1d3b9cL, + 0x0175020538f69d9L, 0x0230e694f05a82dL, 0x083a060f6df468dL, + 0x0a1edc3850eecbcL, 0x08c2ca2586752ddL, 0x044be558a49701cL }, + { 0x1ed38130d8bab8aL, 0x09b26521c10052cL, 0x1cb101605057047L, + 0x14f5912ce80d0f7L, 0x197411a086ad0d3L, 0x019b8e22494082dL, + 0x00c79d2612c47ceL, 0x1c0e1a5db081a35L, 0x0d883628b6c912fL, + 0x07c7bfd8a7d4469L, 0x1ca9373c2b24f91L, 0x13554d849f4cac9L, + 0x03bf6cd94982f62L, 0x10528c16d5c835dL, 0x1ae4e94b208b99cL, + 0x0e7545fe8fb5861L, 0x0c5dc62c4a4fff6L, 0x0325803b1a3b587L }, + { 0x03f533eb3c9a404L, 0x1bfb9dbf7cca90fL, 0x18a5b094da4ec76L, + 0x080e71dda98fe27L, 0x0e26cad07ce7f4cL, 0x162e78e67e9d99eL, + 0x1380761e124d407L, 0x19e7f1f813bb810L, 0x0217cab32c39b5aL, + 0x16d785dcf7aaa8eL, 0x1dbd5b8485ea550L, 0x1625846e0055f78L, + 0x1fb070a29380178L, 0x0bb654b205a961cL, 0x15a38db8e49454dL, + 0x01d084aab284833L, 0x18c291fb82c09e5L, 0x03ee91753330c76L }, + { 0x1fe844b49cbb3bfL, 0x063822ab17d92bfL, 0x14de7d6a116b783L, + 0x0dca24eff83cddcL, 0x10635718956d7f2L, 0x0abf9a163aea5c9L, + 0x1d0ace685224a5aL, 0x0e519e9d66505caL, 0x16b0d3ddd83247bL, + 0x1d4fb19900d211bL, 0x100f04505292159L, 0x088f6ded522c82cL, + 0x10dac6f79060afdL, 0x1e9dcec14afca49L, 0x12b7c3da17fe52eL, + 0x0e912b91f31f8a3L, 0x0c89559c88ab13bL, 0x0189bbe332f8c7eL }, + { 0x1c5de097dcfb35fL, 0x0654f80e61b7c1aL, 0x0175d5db2d8cb73L, + 0x15ef6966eafd27dL, 0x109a19b50c2dd48L, 0x1ff303cecae6a7dL, + 0x16b49d4bb4565c6L, 0x0de8731019e4b2dL, 0x0e52efb5369e90aL, + 0x004bb3181e9f305L, 0x0d93eaa541c3811L, 0x076c0ac49ba5f9eL, + 0x0400d5e467d8f99L, 0x0647a29259ad4c1L, 0x02805e78a274090L, + 0x1b57bde8a8478c9L, 0x0713a5fd695587eL, 0x01ed66286508f29L }, + { 0x13e4f946499ae4cL, 0x0e5f0b829e293e5L, 0x13a6f9e0ba2a91bL, + 0x11b0903c8b00febL, 0x0a286fd0b6c64d2L, 0x0e6da4f9af228c5L, + 0x0fabfdedee6eb7cL, 0x1f7e7f6c4215d84L, 0x00a9ba385b9bfd2L, + 0x08d06a9c403f9d0L, 0x091012c5eca10b9L, 0x0d0ff3bb3e14f56L, + 0x14f3e9df646fd57L, 0x106f8ca6e68f7edL, 0x1a77c15774b7de9L, + 0x114637da7e587c0L, 0x0f7469b75612324L, 0x04334a4f0b4a3a2L }, + { 0x09a0da53f4ab07aL, 0x17999faa537df9dL, 0x0486c8f3ca40b35L, + 0x1d091c7ab01925dL, 0x13b218abc9581c3L, 0x165a6bc9d78fdeeL, + 0x00e80e1663a8419L, 0x16aa002729d3218L, 0x13b664b1e7d0877L, + 0x1ced8ddeba63848L, 0x1510d538b577435L, 0x08366653b7050a5L, + 0x107b96d4800d2b8L, 0x014aee237d42275L, 0x1dfb138de9415a7L, + 0x062ef85a706e729L, 0x198dc3884ff5b08L, 0x02ba1a95c458fd2L }, + { 0x12193f70d5d7ce9L, 0x0fe9305a43f57f6L, 0x0d65ef997f40f06L, + 0x00f04e1aacf8895L, 0x1aa70198dd9da86L, 0x0cc2efc54276005L, + 0x0a360bb09f924a1L, 0x03b32d995e1bc40L, 0x14e7648c761c220L, + 0x0b19ade048e0cf5L, 0x08e9a7c359e0aeaL, 0x0681a528c9264a7L, + 0x01099f68733f204L, 0x14cb008d222290dL, 0x14ea5397f2f3025L, + 0x147427109abb1f0L, 0x04f2418c624d3b6L, 0x01f218d7903571eL }, + { 0x167d93983d381f1L, 0x00d57686019e1fcL, 0x134151041da0d94L, + 0x10a1274da77e75eL, 0x192f2900a86d159L, 0x185baaa1d703a0eL, + 0x1b5bffacabe98dbL, 0x08da1214d47548aL, 0x1336a4fdaaefdb6L, + 0x08dff220d4a17beL, 0x0a8fb6147b907bfL, 0x0d0c23d26b8aff8L, + 0x0653bbb3434f1c9L, 0x16c4b61566abbb3L, 0x0efe907c9a4c6eaL, + 0x19de3141f77a30dL, 0x1351c3d7d82a203L, 0x036d69f8af13326L }, + { 0x1940b7d12ec35a1L, 0x0e2db73efd89468L, 0x031bc4cc8755886L, + 0x14678b1d6c5984fL, 0x19903c435e76904L, 0x0cb50c8a8487aaeL, + 0x12e9c186f249b0fL, 0x0372e953e071815L, 0x17a4140217198b2L, + 0x034accefc4ac637L, 0x1cbc76faf404a6cL, 0x0c27be751b86a2fL, + 0x08672375c51109aL, 0x09c1e9698472c22L, 0x1fe0df159642e92L, + 0x1aabff87dcf8c17L, 0x03fc87a539027d2L, 0x0121c74ea2fa8bdL }, + { 0x0a453088815af3cL, 0x18d1979e4df6ae2L, 0x17265ed9777f957L, + 0x0825ca3d6b5de39L, 0x063f249061c61d9L, 0x19f118de86d62a7L, + 0x18041bc510a7342L, 0x163ee6f8785e3b4L, 0x17150e04b6bbc4fL, + 0x02da6448df140e5L, 0x118cf35dc07d6c8L, 0x1e8c54a26921e36L, + 0x1368f1f7f28b33eL, 0x1ea0b5b3eeda3e3L, 0x1e56ecfd2b69446L, + 0x01ccf3a552f9bfeL, 0x00100a8b7b29620L, 0x009f9c808d7f187L }, + { 0x1d296ef7bd0c827L, 0x08879a514ffa31eL, 0x01a072694569418L, + 0x0a4d1794eff0f26L, 0x198045dfde8d804L, 0x0072c265dc18124L, + 0x18188fe435c41a3L, 0x016550719504c76L, 0x0293bb5e7535c5dL, + 0x1754ceaab20a888L, 0x046b406ef680173L, 0x017f49b1a031fc6L, + 0x001cf2b8662497eL, 0x0c625d4599eebbdL, 0x0adef26f01d6dcfL, + 0x036165308cda8e4L, 0x1b617a7ce24cbdaL, 0x022c6a5b5b40381L }, + { 0x026a20e4d54d8b2L, 0x0b4b726990506c5L, 0x0163e653dc00169L, + 0x185eca9350d316bL, 0x1694d00d7a4adc3L, 0x02015e8c09740c9L, + 0x190411ae6c001ccL, 0x041c21428934366L, 0x1eae95ea5992302L, + 0x17e174d8da41061L, 0x0d72d61727ae28fL, 0x06332f08e0c9fcbL, + 0x108f27d49f21ae0L, 0x17b92ab5b47785bL, 0x136c068c967bc60L, + 0x1f2b8015c08aec4L, 0x191628e3b065668L, 0x02f89fafd5b7ddfL }, + { 0x06ed9ae3a9b0dc6L, 0x0def4b7c41f643eL, 0x1e23aa2cd9deba8L, + 0x1934cdc757d4cd7L, 0x08217ffddefa6abL, 0x06f82e626998bdbL, + 0x19d3bdd0723c8a4L, 0x1943e1fbe2efa22L, 0x1fdf0ece7c35989L, + 0x176c96fb5ce2416L, 0x04f99956fc729c3L, 0x05204b9d9338e6eL, + 0x02e803e69c90acbL, 0x0bb89d0d1be4f1dL, 0x1685d35f028f14cL, + 0x005ec6a1b8acadeL, 0x0a211625a4405f8L, 0x010cb24aed1bdd2L }, + { 0x0cb2fd313142680L, 0x148ebb2e8a67a00L, 0x1aaf7f899a7aae7L, + 0x1015c4578b8d419L, 0x0b6ec250beefce5L, 0x1c78ff9e15bcc36L, + 0x123b212b6c68b5cL, 0x16b2e137850a2ddL, 0x1f36931298e8f7dL, + 0x0477e35cad8cbfcL, 0x04254a6aaa90131L, 0x197a2882a9613feL, + 0x03427f34352c3c8L, 0x090c4be099f7bdeL, 0x19522801285e503L, + 0x1f4c4b54188fad9L, 0x1082971cea73d56L, 0x049d687580223afL }, + { 0x00b6967988a9963L, 0x03bfbb28af46ebdL, 0x0e18edad43c9879L, + 0x0ba67245bcc4e9cL, 0x087a5b3d63a9b8dL, 0x0171919e1c69fdbL, + 0x1333c63dbc2704cL, 0x1ee4a980b87c05fL, 0x1c04ed0b726e662L, + 0x0ab235c0a1ff03cL, 0x0a51232405b2307L, 0x1897f047af2fdf1L, + 0x0fbccde451e5674L, 0x020bf56f02c37b9L, 0x1b9623717f22355L, + 0x1a3f2572a4412aeL, 0x0344408dd425844L, 0x039fc61f87520e0L }, + { 0x1534fc85df763ddL, 0x013f99d638c1b44L, 0x185dba3c5680ec5L, + 0x099641111c1b6b7L, 0x057caea61d39094L, 0x0fbdf9bc0264d6cL, + 0x0a33ea96110a146L, 0x02ac4ddd9e25275L, 0x1749e0d98ea36a0L, + 0x1ffb6d71990f6e6L, 0x17ba98a2de4733bL, 0x0aa45a2dc6c32c7L, + 0x1cb15ae206a14e0L, 0x1e5192f251702c7L, 0x0d06a283c9a1d17L, + 0x0a370f9f3a80e42L, 0x175dfed25d97caaL, 0x00084571cd6df6eL }, + { 0x0d178f3a9e88f63L, 0x0d88f55863992aaL, 0x0f9b8987629aa81L, + 0x1d1a172390ee74aL, 0x09bb004d24db7daL, 0x118485ef085839fL, + 0x07227f22fbf9d53L, 0x0342d5e0b32198dL, 0x0ddc838039d5951L, + 0x1fb2dcca362ed7eL, 0x192fa07b8296670L, 0x1c6df675362ff77L, + 0x15445dad0088891L, 0x0a84bf0f864d56bL, 0x01693877ff11aafL, + 0x0a4671090113759L, 0x1df348bb42fa0c4L, 0x0403e036c7589e0L }, + { 0x0a969ec98ee0ef6L, 0x0aa41c5dbdbd780L, 0x124a80be3f6eea7L, + 0x1516e0aaf848909L, 0x00ad1af27bdb201L, 0x064afdf2c9a1f23L, + 0x074ed4ea6a50a66L, 0x01d2e9b67bdb50cL, 0x1ce1525c9ed399cL, + 0x0dab440fb9084deL, 0x1df456660846922L, 0x1675de1e4eb411fL, + 0x17fa2f358b5df76L, 0x01cd831a49f8c07L, 0x160ed4eab13ff3fL, + 0x133f84d258c4c2eL, 0x061b2fdfa36b553L, 0x00b2126364cb03dL }, + { 0x1d65c55dd2744a9L, 0x060e17f1d7a0c2eL, 0x1a67bfa2c224951L, + 0x0b53bed23465905L, 0x1be9967430b7ab2L, 0x1968914c1c22a84L, + 0x1c9caf3b349632bL, 0x019115c8131798eL, 0x0d43961414b8efaL, + 0x07fb3dcf6b26896L, 0x195790b9fcd0111L, 0x188a8b61d3d753cL, + 0x14f03ded283d16fL, 0x16665c2e23a51f0L, 0x14e946e8f26b7feL, + 0x063627bfcd782e4L, 0x18adddaf4b9fb58L, 0x02aa27301527a23L }, + { 0x17c5313baa80b4fL, 0x138b7b1dee477c4L, 0x0b6ded0b16a0048L, + 0x12110661195c4e8L, 0x0d341ab1e9d9e1eL, 0x0a2c381a96461f9L, + 0x1676058f41403b6L, 0x0530693bae78521L, 0x02053c5e01f6c7dL, + 0x1883a2365a1019eL, 0x022f4827426bc60L, 0x1cdd64f28d02ed9L, + 0x1e19b1b540d0f70L, 0x114ca5a1b905aceL, 0x1b14f3e02dfb370L, + 0x01e8583499b9c5bL, 0x061dd7d3edd1ed6L, 0x02b9accae7120e9L }, + { 0x04ba3fba0237056L, 0x160b219d599c46eL, 0x0ef49c7b1849a15L, + 0x07c60637d9803ddL, 0x0118a1f5abdeb03L, 0x100799a777220cbL, + 0x01dcfb125d0856dL, 0x1fa36e30b9e110dL, 0x17b0c46cd7c1b7dL, + 0x0a1d96d25262f44L, 0x096612ec7fe5374L, 0x09c9939e68cbb73L, + 0x00eace64c9ac390L, 0x1b456ccd7c394deL, 0x05503097308a085L, + 0x0d22f77a7610315L, 0x0f0e468ed5f049aL, 0x0442a436f9f622fL }, + { 0x0942c934bdff464L, 0x138cf92d3da28b5L, 0x1c2cc96f8c90f6cL, + 0x1633fc667399600L, 0x041ee8ff2055a31L, 0x17c6f7d6534d741L, + 0x1cf19d81f742157L, 0x0213c492c1e3436L, 0x1bcb0e8a271d368L, + 0x0f08d513442f35cL, 0x1742ac617ab864aL, 0x0dc81f03f239316L, + 0x0f994fc5031a0b9L, 0x188ceb70268745eL, 0x0933830cf605a5fL, + 0x1f3ae5210650f55L, 0x02dc5dd4d3ec91fL, 0x018e767f46a55cbL }, + { 0x17bfd9afc8b21e8L, 0x09959d8ca1b6fa1L, 0x0b524870da83977L, + 0x1b47a1f521fcb20L, 0x1bb523bd8e9de84L, 0x06b4bacb31f356aL, + 0x0d672600288febbL, 0x1e2201381b369f7L, 0x1839aa7bdc9d20fL, + 0x0817b36f66b7d1eL, 0x1b53ef1545b2a7dL, 0x0becd8e85588901L, + 0x05ff3252f865ffaL, 0x1aece59e95be3caL, 0x15bc749cbfbf015L, + 0x09d8623610c77adL, 0x1b35d8f3cf09a6aL, 0x034b0da356d12a3L }, + { 0x07b587ecb35e2acL, 0x0aa35abd78a6ce8L, 0x096f6ca281307b5L, + 0x08e13aa9e1d942fL, 0x1c6f400ea1f91d4L, 0x0670c853738cfecL, + 0x0ff49392e23b7eeL, 0x0bbf2f03dba48dcL, 0x1d67120e6b655afL, + 0x13c168ec9a09e53L, 0x18828a5c1fe8876L, 0x1e64a9d08246d2fL, + 0x1e36051f9f1eb51L, 0x19e72df49712a6cL, 0x0fde53f76bb10adL, + 0x155b31353465d9aL, 0x0121964e22f0781L, 0x03531d48629baa9L }, + { 0x0554e003d7acbbbL, 0x0b3455ba7b0843bL, 0x19c8e231466cb00L, + 0x087d729a9fc9452L, 0x0cd6d2f60166771L, 0x1b87bf84351e6f8L, + 0x0f9f3e1960085ecL, 0x142cb110182b49aL, 0x1d6ed58165ba3f4L, + 0x1e63c09ae5238eeL, 0x0fc1d3a11295daaL, 0x0366dd4a05d5013L, + 0x070e021ed3a53a8L, 0x030bf8b2e105c98L, 0x0d7342e309fe24aL, + 0x052c34a8ec88d04L, 0x10effc89ffd8255L, 0x028f6a51168a8ecL }, + { 0x1d6963a449701b4L, 0x0c8d1dd93e5791bL, 0x1856d5ca597faa3L, + 0x0bb6a17efa7df37L, 0x0e643b9b75a7a05L, 0x15aeaf7eb3a4076L, + 0x1225fca9834b5b3L, 0x0bed1f86418bdafL, 0x041c53cf628ce68L, + 0x114b88fb88330afL, 0x1c84e08d403b303L, 0x04c0d853fc90f50L, + 0x0ae1ef9712af0a9L, 0x0968b4dfc9ef9f9L, 0x0a5e4f0357dbec7L, + 0x124add6f5fc4ce9L, 0x0e54173d94ae9f4L, 0x016b4a8de15c5aeL }, + { 0x1007d9f904e222eL, 0x19247c37a7084eeL, 0x1a2e3d0a7bb8ccfL, + 0x0b9f8eea31a9329L, 0x0b0f42f12957341L, 0x1a1a8cb73ff51d0L, + 0x1c6831e572df709L, 0x0ab04151ecce23cL, 0x183d95d9c2b874fL, + 0x05b26bc73870b13L, 0x0d4fd62e4a9d0b5L, 0x116288f6bcdb248L, + 0x0cbcf931a032204L, 0x13d7913405d6b98L, 0x0ee4fe5d7134226L, + 0x075dc8c92098370L, 0x1f0a24eba02165bL, 0x032e2473c704662L }, + { 0x01c73cede222c22L, 0x1ec66fe7511da0dL, 0x0c52c850ec195a0L, + 0x1eb3f9d8ee06039L, 0x11204cef284adf8L, 0x19a883fd8e2c0e1L, + 0x02303d534fbba51L, 0x025b7ecfe169a63L, 0x176a3f2d110f18dL, + 0x004fd1403e9f009L, 0x1c2918979fb380eL, 0x0fdb6512ba5de0dL, + 0x0908b0553ad8286L, 0x17922a22f0837a4L, 0x1668f2f88a03e9bL, + 0x1745a805aaf0b51L, 0x06ff63dd9ffd438L, 0x01b5ae6963d3591L }, + { 0x1ff4e20545679a7L, 0x005a0a29063a843L, 0x1fea6d167361936L, + 0x1390b5e3472146aL, 0x0d935a5ea19eaf3L, 0x0d33c506a3aebccL, + 0x1a041d140660de0L, 0x088e9072ef21985L, 0x1c6a21d112f4122L, + 0x08742fc9b528d1bL, 0x00547baa9d37e23L, 0x054f279f3389feaL, + 0x11376a9ab614e18L, 0x0911c4ffa2ac9efL, 0x1117a2863dcf2bdL, + 0x03b91a4f992c1eeL, 0x1d80692f4c539a5L, 0x0046be0a26d9cdfL }, + { 0x09c0d963ecca773L, 0x148c96a4610ab40L, 0x15d36daf59061faL, + 0x0854cf19bfe1d99L, 0x11587b7e7731237L, 0x1852633d4b36c5eL, + 0x05ef7cf06840584L, 0x148f98dd070bf9cL, 0x195e95bb8a8de7aL, + 0x1f0f45ac4c18471L, 0x1c90fb8d1da528fL, 0x18857619a57e032L, + 0x040f9b2b49f3fe9L, 0x039b3e8fdac8293L, 0x1b851ed30e17a2fL, + 0x095b23a60a15d6bL, 0x0028e2c38790400L, 0x02f9554775d5b81L }, + { 0x008d4641266524bL, 0x19c406850cfb371L, 0x017b6841bafedefL, + 0x07cc85ba8d4b54dL, 0x0682e4d60a69e8dL, 0x05a9a6779a4e30eL, + 0x19ee09bdbb8ec3fL, 0x1ecfb57424e0bd6L, 0x12babb27e18be05L, + 0x0cd7e5d4716c2e8L, 0x1cb46b8b674e1a5L, 0x05cc3d4de0dddb9L, + 0x14866e5ae859dc5L, 0x015e69e3e1413c5L, 0x12fa0bf67fc0d00L, + 0x1e449d10958ecf0L, 0x149a316498083c9L, 0x031280d4c5a37fcL }, + { 0x03f7d9aad264086L, 0x119edd2f0725eabL, 0x000a3234f59f29aL, + 0x108dcc9633d04a6L, 0x00aa4536a288dacL, 0x0a9f567d1e48cb9L, + 0x0af4e04c326c3b5L, 0x0eec4500dc05d51L, 0x052fbf54dceccfeL, + 0x0cd4718a7868db8L, 0x1484cf566c5d06fL, 0x003934dfd514a33L, + 0x00b5c4eb10fd741L, 0x08fced2f68d67bdL, 0x17a9619e1266dceL, + 0x0a6355754989381L, 0x065cc9c5f73a1f3L, 0x024bd8aff7e9fe3L }, + { 0x056cbaaf45568e9L, 0x0d07f638c9537c5L, 0x174e6ac94e6bd24L, + 0x109586fb53b7607L, 0x02a0f5b4c86522fL, 0x0e29cfc6466dd10L, + 0x1c0ba0427f1d68aL, 0x17f39a0da639521L, 0x18f31f0443e216dL, + 0x0d534565d1f5ec8L, 0x0343490b001fd26L, 0x1f7f0d536f9c550L, + 0x04d6308edcdd8dfL, 0x03400965202e9f4L, 0x1a841c76be8cff8L, + 0x06fcd85dd7a27dbL, 0x0b7b7ae7e5c2ff6L, 0x00c6a35364f28a6L }, + { 0x08cbb22a78b7802L, 0x0eed924be5d7a43L, 0x1cf90aba2b741d1L, + 0x15699d69c989d65L, 0x0325fd40ac0abcdL, 0x1639a29706c192dL, + 0x1c6e5b3f815c44eL, 0x056e80f4f116282L, 0x070eb06036da7a5L, + 0x1859b7cec28bb56L, 0x0274a5f0a553ceaL, 0x1391b9ae0b5a282L, + 0x0d7bb5e751370deL, 0x103738461f86daeL, 0x04c143517e4f506L, + 0x1fdf221aa9f14fdL, 0x04069e6f8e45a38L, 0x02a822300e9fb17L }, + { 0x1c5c91006cb9cc9L, 0x03a6ba0e8000a68L, 0x18f8448dbee1508L, + 0x1c535abf04f9b0cL, 0x0951fc8339721ffL, 0x068a278e90fdfd1L, + 0x0b9ac73781b9d00L, 0x0cd2084b2d722f2L, 0x03365c8e529ad51L, + 0x1110742cd777f4cL, 0x14c625c30abb8f8L, 0x07b73fe20179796L, + 0x16f532973f477caL, 0x0d15e80d9383a0bL, 0x15e7e4e848462b2L, + 0x1afb7e684a4127bL, 0x04f563a8ff7c6f5L, 0x006d189fe6bd876L }, + { 0x1125a8c15aa2557L, 0x0eb8600449f4e1bL, 0x06519ee2a08f288L, + 0x08f960085490e27L, 0x09e2ce180d3e9a7L, 0x0d75611695fa7feL, + 0x01983554c683412L, 0x0009a534c2de07aL, 0x0473d50d61f1b7fL, + 0x178765de51ef286L, 0x166fa8270a3c9ceL, 0x1d41f0e08cc9c52L, + 0x01731083ef6d7c2L, 0x0a0e12aa56fd727L, 0x058b40d4250309aL, + 0x0521c882ce82142L, 0x0cc620230d81e82L, 0x031b185f46da0a5L }, + { 0x18d52228a7d2e41L, 0x1ac11f5b17c3cdfL, 0x0f75b100b625279L, + 0x0dbc58b35a369a6L, 0x09b9dc38883e04dL, 0x1b86265f9f9c7a2L, + 0x081167665f462d2L, 0x0da3ed36418279dL, 0x1ca3d702558e260L, + 0x0a7ecbb930e8dbcL, 0x1abea16850dbe8fL, 0x1d317688780ead5L, + 0x0ce558f6be369b3L, 0x1c5647c4fe728c3L, 0x196a9cbac3351e3L, + 0x09d60d00e9e6fabL, 0x0ed295845c06854L, 0x018354c38f8b344L }, + { 0x0451e9d634ec136L, 0x193e50737b2c7deL, 0x054b036d04807b7L, + 0x018b7fdccf537c0L, 0x1a2d602387b6ef2L, 0x17dc4c9a94191c4L, + 0x10b79839593631eL, 0x05695e457801593L, 0x128e6f63182a9d2L, + 0x03ae380fa99380dL, 0x1063e2081d7e470L, 0x051a37d54a23edaL, + 0x176e72a13df9fa6L, 0x1bfa600e2a8f3d0L, 0x12756224c18856dL, + 0x0f9a8e3574e6327L, 0x0376443ebe058e5L, 0x01419d620f4081fL }, + { 0x0564b868da5ec5cL, 0x0ced40e046d923fL, 0x1c2e315e9ca2b0fL, + 0x0f3a687b853af83L, 0x1dc603393512afeL, 0x1d0ca0da1c7267fL, + 0x01125f5689c0373L, 0x1cdabe647f04e64L, 0x11b87a58e1393c6L, + 0x05b45e8825d5218L, 0x1071691c8ad35fbL, 0x152e40d6bf55813L, + 0x169976327ef42faL, 0x043bc3ecf0ee5e6L, 0x1700645956ea790L, + 0x06a717ab38eafbcL, 0x103673020ed0bcfL, 0x009066a2a524eb1L }, + { 0x1fdb8f4cab0f9eeL, 0x01f7816672c7775L, 0x01056a341996f00L, + 0x0d372aeee936d4dL, 0x0721ab5c642ed3aL, 0x1278699ef243f82L, + 0x17737bcbfce0086L, 0x1e57a2deab053b7L, 0x12ef05b4b0e93dfL, + 0x10fd50905e4d760L, 0x0b8b0b519fea4b7L, 0x1ec8bd667c68cdbL, + 0x168f0103cb758daL, 0x0df01218533d6cfL, 0x10152f0547da4eaL, + 0x066ddaad3092dd6L, 0x03e8ef1677e7019L, 0x0010e7e8b3fef75L }, + { 0x073715fdf5c36f3L, 0x1ef1beb25692a2eL, 0x1443cb3ddc4dc0eL, + 0x0e1e732790aa6d1L, 0x104ae4ca1e5ec7bL, 0x1dd8c5fed8b3bb1L, + 0x0f568363dc5f8f4L, 0x16aa4ce0e7ecc68L, 0x1faeb52ef156008L, + 0x0bd6afc91252387L, 0x1b8e47b4aad46aeL, 0x1caf32e860595f0L, + 0x17fd0ae28adc0c7L, 0x1fc76ace6447d40L, 0x04a2eda01f08b7eL, + 0x12b46bbdb8463d6L, 0x18e71edcd9ca205L, 0x003932da3639e7bL }, + { 0x1dd99f0bd66232fL, 0x157c4e2013b8b39L, 0x17e96e183f13166L, + 0x14f5287e775f04dL, 0x123c428d239ea8aL, 0x19dcad07070d8d2L, + 0x1d4ed57a838e9a5L, 0x03fd47339544aaeL, 0x0f8adf72f06957bL, + 0x1c4f9a09de9a181L, 0x1c9f43e290ea5c0L, 0x18115b5ef2de667L, + 0x1b49c12aa2cd9c0L, 0x1d056374b6e6524L, 0x110203b76237bb9L, + 0x1e97b1e8eaeba0cL, 0x16c6e9d667d0cc2L, 0x01b62baa598e8a4L }, + { 0x120046ef323d84bL, 0x088913f3c4e27c8L, 0x1d3a486e01569a6L, + 0x1500f32e9c961d5L, 0x140f8c796339844L, 0x16f7a4e482a3353L, + 0x192e8706343df35L, 0x18aa52fb4d69647L, 0x11c09dff3c41800L, + 0x02483ad9bf7b3bbL, 0x10e9014144f7b5bL, 0x05d2d6162e0b529L, + 0x14c48af5ae3d674L, 0x04ac116f603c224L, 0x193653d030054cbL, + 0x0bd6b45bb5bcb82L, 0x04efc8a8ac9a297L, 0x0037dfc308ca34aL }, + { 0x165338e3f45aa97L, 0x1ac640e8207f596L, 0x166c3f7be2e760eL, + 0x15c9ae82f80bfdeL, 0x130a1a237beb071L, 0x12de81cc15b0fadL, + 0x1afcd317ca8abedL, 0x14bc815793ab97eL, 0x0422c326df06612L, + 0x090f34ecab8d714L, 0x02c42c8f4d0d3b2L, 0x12af3b40f266f91L, + 0x013619cf4d96d2eL, 0x0caf77d0c19ea35L, 0x0fa3c3b6746594fL, + 0x0b56254fb082340L, 0x1ea5e64295304bbL, 0x02f4e507e8f87d4L }, + { 0x1d54571197c5dc4L, 0x1205ff3c54ad12dL, 0x1bf3ff6c3acb8b6L, + 0x181a2e8cf8cbf73L, 0x0758c6a3e952dc2L, 0x01a54d60fe4e3deL, + 0x12d5bf1e558b350L, 0x1164dc6df7cc3ecL, 0x06adc4b9e1e8472L, + 0x18b2fe9d47cd645L, 0x04e9140f8f804dfL, 0x0a26cac8f1c6f79L, + 0x17064ddc77eacc5L, 0x1b49b48a699c8b8L, 0x0909299d6cc6371L, + 0x0be68d363e38e6cL, 0x0f88cc2045b4995L, 0x04a031159e341b5L }, + { 0x110ccb70d997973L, 0x0b12ee9fc788aa3L, 0x13556e5eaf54ecaL, + 0x14ce7c294b19e18L, 0x1d262246c6321e0L, 0x041d8882a0d7ce9L, + 0x14a9379b61d51bfL, 0x16c8fd2fb51e02cL, 0x00f82b3a6ad9802L, + 0x0d5203ad74e2259L, 0x1d778b3b4afdddaL, 0x151492f481b55e7L, + 0x083c23ba9c1ef1eL, 0x18c851641707c30L, 0x178cda362a66293L, + 0x17ae3c56939199fL, 0x1b6b9f49824bde6L, 0x0405d8b323c2df6L }, + { 0x1e575fefd145cb5L, 0x172b0d62f344182L, 0x033e1e4ec9cc557L, + 0x1c267646708c3ceL, 0x02a7ba079f1553dL, 0x18437d17dcf061dL, + 0x12e4f0eff5aa0f9L, 0x17b6d750a011769L, 0x10b66d78976f82dL, + 0x0ad37fb2a75a4ffL, 0x1748dc7c82cc89fL, 0x1384a9c539b99acL, + 0x03cb118ff979ea4L, 0x062c0005b24bacbL, 0x031de725a566377L, + 0x0b46b2a20f23022L, 0x150edfc154863b8L, 0x003bdd2f5209091L }, + { 0x13a38d3cdd86f61L, 0x10a228281505585L, 0x171601b409c90c4L, + 0x111465e21e3225dL, 0x0e80c76001dc1f9L, 0x127459dd8e98e88L, + 0x127bb51bb1f97d1L, 0x0efaad35e6d357eL, 0x09d286ea72cdadeL, + 0x1f38106a2d6ac90L, 0x148db98a66b9fcaL, 0x137ba7eab80f57cL, + 0x1a52350e80c9317L, 0x17f83ac3409c4caL, 0x1ce594c24049972L, + 0x0fa42b6790365e8L, 0x0e2baf7581d9bc7L, 0x03590036fa2c8d1L }, + { 0x0fe50a8965b1bc1L, 0x1a9b54b15da7ed9L, 0x14cc0039fe664c7L, + 0x0aa7aa24bdaae31L, 0x12125caf84728f2L, 0x1fb3cf27c530c26L, + 0x1016953c69c04d5L, 0x0eae153e8182a63L, 0x110d0cb976fa8b7L, + 0x03b7a0f4ee09674L, 0x15e9d49d57e252dL, 0x1c20c4ae8348b91L, + 0x18c917b16cd6c12L, 0x1c6b5850131537dL, 0x10e3a0c93445b98L, + 0x115f9092a818065L, 0x150855b911c6686L, 0x02990bf535e935aL }, + { 0x0840473259f52b4L, 0x0d4e5f3108a367eL, 0x017b2b2f49ba5a3L, + 0x1bc94a86892c9d7L, 0x181a4ff7ab7daa2L, 0x040af7b6e1dc241L, + 0x0c78681ea5acd07L, 0x15189f5d3d187a9L, 0x10f938d1e42ce9eL, + 0x193ed661ae60297L, 0x180727a681bc1e9L, 0x1b9694dacb43903L, + 0x136044a9a6a9e08L, 0x195e94adfc7168bL, 0x1e06c4a6624f743L, + 0x01585411a66f3f2L, 0x0ef64bd60016183L, 0x001c3498f6cd6dfL }, + { 0x0d7abb3d09885a5L, 0x095b3f1aadd83e8L, 0x033d4dbaebb7b67L, + 0x10d339c9ac77847L, 0x111594cd61ca2e7L, 0x18b5691aa7fa238L, + 0x1d711572f9c240cL, 0x080830cf3fa93ffL, 0x075bacd750f9c6cL, + 0x1bf6e4414b9390dL, 0x05a21f97bd40bd9L, 0x06cf7e641c1d04bL, + 0x0f8bbdccb2459e9L, 0x1bb3431ec0e71b7L, 0x031b6e06e825ff2L, + 0x0e9179a7443adabL, 0x0200e4967cdb4a8L, 0x016557ba48a820eL }, + { 0x0f980066ed20424L, 0x0751191238aa2a2L, 0x0695e06a321acf9L, + 0x0af5cb6e164d1daL, 0x156d398248d0ab7L, 0x198fd2365459901L, + 0x173ca73a39a04b7L, 0x1bd7213a465b24bL, 0x1302c8f78f56723L, + 0x0b92eb4d5d64b7cL, 0x091f295f4685c04L, 0x0a23831457cecadL, + 0x11ad50d9d96bb5dL, 0x18582a8c5ab722fL, 0x163fe44dba21b89L, + 0x06c3d8f8e3e7a13L, 0x1d865a1bbe29350L, 0x0436bfa9922ff1dL }, + { 0x1f16eb6b0bf719aL, 0x1a84c45e1ec89ccL, 0x19489b3406d2da5L, + 0x0921131a39f5ca1L, 0x087ec666d3e3ac5L, 0x1522dc26d1dcedcL, + 0x0c16160c01913efL, 0x0266d3e77b306abL, 0x10fb239a8579bccL, + 0x1ada29cb715ec08L, 0x1ceebc90663f493L, 0x0db7106faa3a00fL, + 0x02eae75b1668a67L, 0x1edb041e3477753L, 0x00db1697ff97e50L, + 0x1ff0aa5929a1efbL, 0x0dd5a4c3c6fcbc1L, 0x034152af1c3605aL }, + { 0x0f235a4587495aaL, 0x101361a63922ee4L, 0x1316dd691b8c89dL, + 0x0bd987cbcfad5c1L, 0x14296629890d396L, 0x03b9138d899a178L, + 0x09a2f22649f9a2aL, 0x0342a87e4fc4649L, 0x06c44768449cdc2L, + 0x1e3fea78a296856L, 0x0c28c7fd2c11726L, 0x0d410a5eec22598L, + 0x12c6fdd7a6415d4L, 0x1da63e48d6b9b82L, 0x0235c3373b30eadL, + 0x0720ba59be036edL, 0x1cd054f2542e40dL, 0x001113fd37f7f26L }, + { 0x005efd9b751948bL, 0x176a37efe912e8cL, 0x18253cb22c8a3bfL, + 0x1f2def8bcb96251L, 0x14cbeca09d1090bL, 0x04658204ace8225L, + 0x13f38872557e638L, 0x135783e4f3ad1f4L, 0x0b021e14e0710aeL, + 0x068b74fc408b3faL, 0x1708baef27c6959L, 0x0dbfc6841dd5eb4L, + 0x15d5c4e8435f371L, 0x147fdd40cb8f5c8L, 0x14dd5e193f157f0L, + 0x18fa0684fca9afbL, 0x178446e6a6215ebL, 0x02a3f124d14934bL }, + { 0x106868aa1ffda27L, 0x166e63caae7a823L, 0x0784298fcf62d39L, + 0x153bcbce15eca2aL, 0x193428235b4127eL, 0x17bea89e9604dd7L, + 0x100946326760ea8L, 0x19d418b763bbbddL, 0x07ffddf8403dcf1L, + 0x0bf2694b0b7ef6dL, 0x1595a5e4ca87c39L, 0x01d06323a9c7a48L, + 0x01c220218b7475eL, 0x05e592829a3cdf5L, 0x184cb9bf3ad7242L, + 0x183d638d0b9d478L, 0x0eac42dc745bfe6L, 0x022d20e60695847L }, + { 0x0a9b2c74dbbf0e1L, 0x1cb17d0be7b871fL, 0x1d617bad319907fL, + 0x05537d62fdb83d4L, 0x0285741a4f5412dL, 0x07e88f964f27a95L, + 0x0613a4f7df69261L, 0x0eb655f7bb81be6L, 0x096323d252421e3L, + 0x03df0f224efbc0fL, 0x1807b4f5626fab2L, 0x137a51ffedba28aL, + 0x148a0f298c0f0bdL, 0x0c4734a216992ceL, 0x0b0abd8d8b5e9dfL, + 0x1b40550980d6d6dL, 0x0c8ba850ac9d087L, 0x00943b1e4a17720L }, + { 0x1a80f07acbac178L, 0x100221a5847b714L, 0x1451c3fb7b49f30L, + 0x070cc2aecfd2c63L, 0x0b088548b2115daL, 0x174701be3afae26L, + 0x05d496ca7484e68L, 0x179fd3fb4cd1710L, 0x13f1d8d88c1de7eL, + 0x03b2b2f0190c091L, 0x195586c72657cedL, 0x1631627d6e360e6L, + 0x1399b3a0eb2160cL, 0x1907e6ba3f46d28L, 0x049b5c97a3287e6L, + 0x0c6fed4fc00cf68L, 0x0d21e8204b768bbL, 0x03af4b5e67e27baL }, + { 0x09d1fdc0d19716eL, 0x0282c3e1c22928cL, 0x1b47aa61f4ab7d6L, + 0x06d80e2a1ec9508L, 0x0d6fd5b712b6bf8L, 0x09faafc8ec2ea32L, + 0x044a6a5e220d93dL, 0x090c01077b102a1L, 0x1a7672683ea876fL, + 0x005973d60ad9244L, 0x1be3490b47664baL, 0x00539e7bc92530bL, + 0x1cb14876279c57bL, 0x0572db43ff017c1L, 0x1ae065abae93f92L, + 0x0a47b150de136baL, 0x149d88f566ba16eL, 0x0184d374d5d1344L }, + { 0x127ee50bdfbe97aL, 0x1f387dc628626f7L, 0x0c05ff827d70697L, + 0x0b7da6d98b98f7dL, 0x1550ed3a8fa15a8L, 0x084340e061d66dbL, + 0x1732f1607be1faeL, 0x1d142b666c5893aL, 0x00fbb17141fa264L, + 0x13fc6c7c70f7744L, 0x133f58870ad8f49L, 0x1cfaa77cfdfba63L, + 0x1fdb2a358a924dbL, 0x1aeb4560ea1743bL, 0x13fa9573e59cf1dL, + 0x16405c6b2f1fae2L, 0x189eeb366535769L, 0x0022c12c56bac9bL }, + { 0x1f71a74a042dbdfL, 0x02c2babbcefd12eL, 0x0e9c34b9995cb50L, + 0x0b945d125c1ccd9L, 0x0f0e6b5f285d674L, 0x03b3e1fab546f78L, + 0x1ae7383ba14768cL, 0x0853180acb08668L, 0x0b35fce26d6b3c7L, + 0x044adff9cbbbf00L, 0x03da9b9edb621b0L, 0x10869e052097079L, + 0x1b2e84ec34bee14L, 0x0b6884c8bfba48aL, 0x07eb302eabd98f2L, + 0x1805200970eafc8L, 0x158a2b880e56f86L, 0x029fa51f04adbb9L }, + { 0x1bb08ce89fc48e7L, 0x062bbd7d5ad7588L, 0x0fe283072d6ae98L, + 0x14f2eaf96de0d79L, 0x163191607d2efaeL, 0x1bdbd4f136c858bL, + 0x1cafd0aa86ad8adL, 0x1e071dd819a50bbL, 0x1d35947f5f3a8f7L, + 0x1e46e077e0e5adaL, 0x0332831161173e5L, 0x1312493c4de5fd7L, + 0x0d483ed89a16e8dL, 0x08ec8839be13273L, 0x17a67c04e8fc515L, + 0x1aac70a02ac5c60L, 0x036aaf98d746908L, 0x0054cf329eb91e9L }, + { 0x1536f46abbc0559L, 0x1833dcd50d0b011L, 0x08a4305a06d7058L, + 0x0226f1d20e453faL, 0x0b793a2d61254beL, 0x12a96de307fabd5L, + 0x028da9bcb7e2d19L, 0x13535a63127182eL, 0x1c5cd9abe29b74dL, + 0x1ba3939fbc24291L, 0x1aa4e83438c18f3L, 0x03c68491c7b1824L, + 0x0e8323ddfafe202L, 0x19931cf3ecb9a1fL, 0x0c955227dda1dd4L, + 0x1efd52ca1f862eaL, 0x1c0b595dbd13eebL, 0x01d4ae5a28087e5L }, + { 0x14e68cb39d7ff2eL, 0x0e5a5e0eae247caL, 0x11ddc5a50e2a374L, + 0x012395b19c05525L, 0x12cd08d27965c0bL, 0x0815ed062bcc559L, + 0x14860696f0f0e9aL, 0x1b6a8ba124aa30dL, 0x0f0077cdbd27e64L, + 0x0abe5524668496dL, 0x1e8e80914caacc0L, 0x073683995746545L, + 0x014744aee6a5fb6L, 0x06dd49ed00b816eL, 0x05e13c5216ed0dbL, + 0x0e58726b2fecc65L, 0x0455d713c1ddad6L, 0x01b3691170185b9L }, + { 0x10b4875573ea5b2L, 0x1200dd486d226eaL, 0x0995e8680c403f3L, + 0x0b9e2288c0f6a7fL, 0x0538bf49722a80aL, 0x15669085c75f82dL, + 0x141f6b850451f4cL, 0x00ecd24e258f6b5L, 0x06dc5fee73f48caL, + 0x0768a4c95c53c6cL, 0x0cc51774bc5d666L, 0x1bc2bf2e371c9d1L, + 0x1dadf1b36843408L, 0x12c995bf02af536L, 0x0224ff52eddb9cfL, + 0x17fb48850e2a7a6L, 0x125173dccd20661L, 0x048395d4cbcef7eL }, + { 0x14de4dd9620ea39L, 0x0b24fe418e77423L, 0x0ec734ea710fefcL, + 0x1e7e7be3aa161d1L, 0x0f0ec9b36a38286L, 0x0e04f1a7683959cL, + 0x0890a9b93261dcaL, 0x175d47d158d15a2L, 0x06ae0e22bfbdfa5L, + 0x10b8f67d8507ac9L, 0x0a21b5ae1c7e355L, 0x1d526bc237b4676L, + 0x007f0f153f6b19bL, 0x1eb6017726c0ad2L, 0x0a23d19f982365dL, + 0x02ca8fd1e47b36dL, 0x02926ac9652439dL, 0x046c9635e9aaa36L }, + { 0x1e0d7ceabeb0ff7L, 0x1a92a1f07217c59L, 0x089b7a021267ef8L, + 0x1e39a89786afa36L, 0x035cfee19ece2e1L, 0x1fac0e0922d6de2L, + 0x0e51e1d3ba103e4L, 0x01522d4ef397b41L, 0x0abcc815afa57aeL, + 0x1d6f616f85310d8L, 0x0940ae07e42f725L, 0x1bc2a77bcc7b7cdL, + 0x1f78884c2554bf9L, 0x05ddaa385447ed5L, 0x014fbd4c2a94ac7L, + 0x04fd5f00a72d852L, 0x1c08d43d8988dd8L, 0x02725f60bae0d72L }, + { 0x18483a2fcc09676L, 0x0251f8cf54d4a5fL, 0x1bcf5c0a977515fL, + 0x05087fcfb14d0a5L, 0x16e35158e7915fdL, 0x0ba3783225dd4c0L, + 0x1c2d6346e57427bL, 0x0bc8ee08b037215L, 0x10bd4bc6bd4fd13L, + 0x16e7033da7419d2L, 0x1a3cc3fd5aa6869L, 0x1001d858c7fc581L, + 0x0598f508a8a9c80L, 0x1949409d224e105L, 0x1fa06880ae532ccL, + 0x0eceec8fc7a51d8L, 0x12472e67d1ab487L, 0x03d2551fab7cef6L }, + { 0x19ef1bae27a0045L, 0x096a7d92165a82aL, 0x0390e73e3493720L, + 0x0b367f38a84748fL, 0x0ffa1fcf97544fcL, 0x11641dad6340995L, + 0x12eddd3e3fb80d2L, 0x14d2d98c81f9a7eL, 0x0775dce9db0512eL, + 0x1ee50cee6e71c0fL, 0x1acfcea74ff9559L, 0x1e8434324e9f83dL, + 0x1428d69b1238e0bL, 0x0fe84efc0acc97dL, 0x06ad77d23f3af7aL, + 0x0d38bb93bf49f68L, 0x1e10cbd7dc8c0a2L, 0x03014153dfbf856L }, + { 0x007e538dceea2e7L, 0x191641e21030ebeL, 0x03e53c7d9458e28L, + 0x178eeed420ced05L, 0x15e6b405f21b69fL, 0x13db21631d1a0bdL, + 0x051013267c96246L, 0x19a70d25950595aL, 0x0f1e82ffe00869bL, + 0x185b8a70b7f2335L, 0x1d0be4640644e30L, 0x0da01f4a2d5cbf6L, + 0x0cd8c73a43e9016L, 0x1de2e1b92aa87bdL, 0x130e7b4b5a901f7L, + 0x17ce1c8f4ea72d1L, 0x1423fd286d94a5fL, 0x02fa574e391e35cL }, + { 0x16a2dda53f4d561L, 0x0a2e80b6d0cc96cL, 0x07eff752c144a1bL, + 0x1b3e432bd489340L, 0x037661b325488a0L, 0x12f701620a8d855L, + 0x0205ee6311c7be7L, 0x015497950dd50cbL, 0x1bbcadb877a68fcL, + 0x059a324b5b9b354L, 0x1a6350559870b62L, 0x098d9202841865dL, + 0x152f2752aff5b3bL, 0x088726ce511a939L, 0x092aa00bd9339cdL, + 0x14a072734fe4d59L, 0x1d29cd3e291401aL, 0x049500a11ee2357L }, + { 0x1f24be11c2f7dbdL, 0x04807dbea93fd74L, 0x16ee1923c4a36a3L, + 0x04902832832c7c4L, 0x1a6756fb9ab713eL, 0x06c85ef43fbe80bL, + 0x1aaf49d37617816L, 0x12b047fdcf504acL, 0x09f6230d7742401L, + 0x02bcf96565af237L, 0x09898c5a9321f81L, 0x1487b33610ae544L, + 0x03e488789e9ca19L, 0x0a0361dec36e15dL, 0x18255fbe582d6e6L, + 0x0a2b6de58851712L, 0x19b90748706161cL, 0x007e47f0f554465L }, + { 0x0ae1bedfeb90f2dL, 0x1dd9e52458aacb4L, 0x1e73d93a58d7ce4L, + 0x01f17ceb8457cc5L, 0x1e6f7529354c241L, 0x165598debf5381aL, + 0x1cfff09921a3858L, 0x0fd62723ce190c1L, 0x1df367c751d8983L, + 0x0a85b5a15f994a0L, 0x03d1b9e304c63f8L, 0x1b57458962c12bdL, + 0x0e701afbf32b3f1L, 0x0f443a62e3667aeL, 0x11b72f8eb49d4c1L, + 0x125ba7250bca2bbL, 0x09f3c954d86d998L, 0x01685d4316fe9bcL }, + { 0x0cd8ee8b472e1afL, 0x0a7575bb55de675L, 0x0fe34364fef7acdL, + 0x0ffcdf8e0d36a41L, 0x04ee2f39fccd60dL, 0x00f28f549a9eef5L, + 0x19ddd7ac2497a6aL, 0x0d3dc669b43a26cL, 0x0c1d28c9fd5354dL, + 0x0bb8baac952f6aaL, 0x18d9fedfdc3606eL, 0x1d9552675cf4ba7L, + 0x19e23cfbb77be7eL, 0x04a4bb40932678fL, 0x0d88d6c344a7d2aL, + 0x0edb4e0a6eb4813L, 0x1fcccf64c7548a3L, 0x04b1e438926a0edL }, + { 0x0e290cbde36a814L, 0x180cab99d895addL, 0x019fddff83866f6L, + 0x1a52e419d41d75bL, 0x1029ec720a7d19fL, 0x08c88f21a6bb28cL, + 0x1fd8215abfc5eedL, 0x00da144bb35b014L, 0x0ffca86aff848c1L, + 0x1f45efca1d6ba4eL, 0x180a138f9a5aed4L, 0x0615dddc842bf73L, + 0x1e2ecf3c633eb66L, 0x070060604ec7ddcL, 0x15efab1c7693fe9L, + 0x18fdf652d7cb2baL, 0x1bd1751fbada8ceL, 0x01681f59e7faaebL }, + { 0x116925f04f2ec1dL, 0x0793b068a3f7175L, 0x1812ab676782a1eL, + 0x167ee206b6885beL, 0x0cb95d5b891df44L, 0x147691e1413959cL, + 0x1cf8dbc53bed57bL, 0x0bde7888c1e2761L, 0x0889f9bd76bd733L, + 0x04f73b8fbaadd37L, 0x0613fbb4866db22L, 0x0e6fd85dc822c4dL, + 0x0263efcd372d44cL, 0x131bc135dca1c2dL, 0x19ade9f6424c86dL, + 0x0c36f849f14f27dL, 0x0d9a3ca8d24a7cfL, 0x042172060e2a5d6L }, + { 0x0268ed6a661d843L, 0x1466527ad9866adL, 0x1b444c4785dc08cL, + 0x098cd2b2ce2dcdfL, 0x17b2e280690decbL, 0x1f21685ed62dfb2L, + 0x128be09fe0b287bL, 0x00d8aa9d81594bfL, 0x1ac5276c1dde455L, + 0x1fa65847183ba89L, 0x1db66b321e5f32dL, 0x10281b2665a5195L, + 0x17285a409fd5964L, 0x1111e849e635714L, 0x0a3f025ddcf0a95L, + 0x1fcd85aa4cd58a2L, 0x128a596b7cbbc31L, 0x0073198cd656489L }, + { 0x1cd2fadf0360ac2L, 0x1306f142f302d5aL, 0x1c43896e6c521adL, + 0x1b55358aa9058d9L, 0x126c070e9d5fa38L, 0x0662969efe78dc2L, + 0x11fd40de6a5acffL, 0x143c6cb385217f9L, 0x15b1a3db569d3e6L, + 0x00a945acdbda16aL, 0x17be92708a801adL, 0x00313699c76d269L, + 0x04b3abaf3290f38L, 0x1fc1c4f15839de0L, 0x0968d6c9e96888bL, + 0x14f8416f53aa3ffL, 0x05a4939ecef28e1L, 0x04441ced10c3938L }, + { 0x0b66c30701ce29aL, 0x178932c4c0ea82bL, 0x1030417e7c84eb2L, + 0x0c6e7c7a27a9b5fL, 0x1a2ee3cafee571eL, 0x101c2d73934e437L, + 0x1a6b3d732992b74L, 0x1de42fe4eae6001L, 0x0c934db470e7273L, + 0x14a7a7b9aadb3bbL, 0x08dae5bf0146010L, 0x03b760a432163f5L, + 0x10e9eaef528f88bL, 0x0db40dc81abc8dcL, 0x0570da7cdfecbafL, + 0x0439273a14a3a88L, 0x026fc59cca71d2eL, 0x03209467f50fa86L }, + { 0x03678a2e8f5b0b5L, 0x1124e69a0782cf8L, 0x11064f29f3b171fL, + 0x0d79075f3082880L, 0x1aa8bbb0075ca34L, 0x01187bf9cf8019fL, + 0x1cd14f463c3b7ceL, 0x0eaf1bfe019a891L, 0x1849228c0d51aa4L, + 0x0a7138418649468L, 0x0e9a1a3c4b3f4f7L, 0x13b71167440d8cdL, + 0x19016dae0109104L, 0x1129f1beec32e82L, 0x1a61c6d1667a417L, + 0x0265c6459e184f9L, 0x1da014f54da174aL, 0x049b1a504ded5e5L }, + { 0x0826b27a9a2e304L, 0x10c3360d2609231L, 0x00c888e05c4315fL, + 0x0b5308f9fd22757L, 0x0b5f46fd7e9b6b8L, 0x1c733694b2ae789L, + 0x17aadca555cae00L, 0x103c9974c02df52L, 0x0bbc11071b9dedaL, + 0x1f8004d1f8e7b0fL, 0x09ddecdcf833ee5L, 0x0139a273ac76a6eL, + 0x1a4f87d78e302f9L, 0x1a0243b18f6b396L, 0x1308ac8d881de8eL, + 0x1ddcf8811865b3bL, 0x17e4b4c5bf226deL, 0x013365a33de031aL }, + { 0x1aa4154b56363e8L, 0x1e83c1e0d526db7L, 0x1778ae79965d2d3L, + 0x1df4009708286b1L, 0x119911a65b34ae3L, 0x1b5fbc67a259767L, + 0x17255572aa0ce94L, 0x03ac0dc3d7310e1L, 0x0e3c3287d09f351L, + 0x0597a75ceae79b2L, 0x13a2498eae3279aL, 0x051d86d56c2382aL, + 0x0ba1b7d12015488L, 0x098adc6b84995feL, 0x11ceb05fb9ed6f1L, + 0x055e6f05fa1a3eeL, 0x0e1bcb029a83c8fL, 0x0258ead0da922a7L }, + { 0x0fe517463d52c0cL, 0x0a92f0c4604ce89L, 0x158cd838e558dcdL, + 0x1559f4b486b8c42L, 0x197e810788b3f1cL, 0x0f040548091d053L, + 0x16b6ae8c7dad6c5L, 0x191afbcbc25f947L, 0x03287361b0df511L, + 0x064006a32babea7L, 0x043cf5481fb245fL, 0x0de261dd41c6210L, + 0x133ea5a2ec0d4e5L, 0x1f355de85dfbf70L, 0x02fd865bf01dd8aL, + 0x1a8559063fb9c24L, 0x127e07439fab622L, 0x040c35c9fa84725L }, + { 0x019d15409312867L, 0x01602dfd7beda63L, 0x19a07d7d7769f81L, + 0x0f49f87b05839e2L, 0x0e68b8fe50aa505L, 0x1a6b22769876b2eL, + 0x0125fb2c0702efaL, 0x038f6bb88890638L, 0x1351e6a009b7d9bL, + 0x1dc31dceca3be48L, 0x196244175044292L, 0x19e886b016f5574L, + 0x1690be357e30086L, 0x13da90a7589ce03L, 0x10ead5c4afffc68L, + 0x137f4f39f8dae45L, 0x12a4743de57f34aL, 0x005fcbf4be4f715L }, + { 0x0ec4ec8dda19e96L, 0x10c7536183745cbL, 0x04ad97da4629533L, + 0x161b341b32fd06cL, 0x02fdcc091ac6f68L, 0x1e1f09cc534bd23L, + 0x05cc1973897c656L, 0x00c312dd9b56727L, 0x19eb81a0f32f128L, + 0x1eba0b70e96e3efL, 0x11e5dab51cd6674L, 0x15353ebde873c45L, + 0x0b9e69d94e3de37L, 0x054e85e435bd605L, 0x1dbc4839afea780L, + 0x1847eaed50e1aacL, 0x0bb3bd91bb4feaaL, 0x047f2a4161f2055L }, + { 0x1ae67c2ce9a4d1eL, 0x15c01a78e901c42L, 0x1ce89741864930fL, + 0x1a611f6838b8d91L, 0x071c294e803de0aL, 0x17586d4cb0fade7L, + 0x1a2db71881e37c0L, 0x11f90fdea2b6c95L, 0x169679f1e50b4d1L, + 0x0e004d0a90ccfa1L, 0x1212f83d90297f1L, 0x176247b56acd4faL, + 0x0c64275d2c4c918L, 0x05696f6b533e08aL, 0x12d723656a44ee7L, + 0x077ec313da316d6L, 0x03f4aeb6206b42dL, 0x01c946334dde45eL }, + { 0x04bea4adacb4b64L, 0x115227930bcd0efL, 0x0539ea444a900fdL, + 0x1ba6de663de7559L, 0x007b85c490448fbL, 0x10dbbda130215e2L, + 0x1a6116b62965884L, 0x01a62ce949ecf9dL, 0x17fae8bbe4e3b2fL, + 0x00efb6ed3e49875L, 0x1bea6309674351aL, 0x13cd7d4383fb5bdL, + 0x0b21d405d11b14dL, 0x19c493aa1dd56e4L, 0x1c73793c077fe4dL, + 0x1a1b30386b67de0L, 0x0f61704d2e19150L, 0x0366644479aa89aL }, + { 0x0d36f0e7ad7504cL, 0x1932ffbcaceeefcL, 0x1b7bfb799eaaf28L, + 0x1d75d7e65e1b9a3L, 0x014edcfc1276f4cL, 0x16c75bb412d3730L, + 0x138782e306a0a66L, 0x034624049521371L, 0x0cb8fd98b9cbd35L, + 0x04209bc7d58f45fL, 0x143d74e5cf2b3e9L, 0x09084b3aa4a82fdL, + 0x0374b91393a17e1L, 0x0d651e74a9eadc2L, 0x103e0563de4ac84L, + 0x1af7a06bfe22191L, 0x0f96afa6357ad4eL, 0x0178a8cc05937d7L }, + { 0x08631da29d2d439L, 0x1dde15e01ccaa86L, 0x1e49b016dd6c487L, + 0x016d9c8fd87cb52L, 0x1d88c6586d6cf4cL, 0x1aad0bdd550bb3cL, + 0x16a140c76e79fccL, 0x1bf0703c7b015deL, 0x1c71db29015a31bL, + 0x1c7b5ba4a4c7ebeL, 0x17cfe44efbbbd98L, 0x04e3e956cf6689dL, + 0x10fd22df11e6173L, 0x102e27491d10163L, 0x1ae6483def80e24L, + 0x095543843210b51L, 0x1656c805ce8beb5L, 0x01aa582db8562c6L }, + { 0x171e2367a9170e9L, 0x16216a656a866b8L, 0x093cf37733ec07bL, + 0x074cd95c35ff7d0L, 0x165c7d01a73e8ceL, 0x1ecb8f5b89c53fcL, + 0x09cac001638fd70L, 0x0dea4b235865fe1L, 0x0a32fb5bcbbbce7L, + 0x1920d5c54fc0d0cL, 0x14cccbb29a18c3cL, 0x13f88905e277e63L, + 0x17a4681be2847afL, 0x12af7e7cb0cb710L, 0x0b31c1664e3e4cbL, + 0x1f5847cfb5970e1L, 0x1a1d41be893cf09L, 0x0246e2ae2571a91L }, + { 0x0623826a5092193L, 0x161b1344c4b8647L, 0x1abc9727ad0791bL, + 0x01078fa48a5e26aL, 0x17d00e384178064L, 0x090a8e4c16f7b3cL, + 0x021a4e0badb9e94L, 0x0042a9c20ef15ebL, 0x0187070758a51cfL, + 0x0f5d4fbb8989e2cL, 0x1ee5cee85564133L, 0x1e963a1af674bacL, + 0x118b8af2cd851c9L, 0x0c35c6b10cf94ebL, 0x0ee70cf2e5333feL, + 0x118d10e4bc49772L, 0x021405ce4c566e3L, 0x02fb5476e85b6e0L }, + { 0x1704ca58f9a8690L, 0x14bb317bb5203c1L, 0x1631a48040a0fcdL, + 0x0d79c7499ff7825L, 0x04aab26d4cd58f1L, 0x122bd43c0233250L, + 0x05e500173eee93aL, 0x072a6f2a367714bL, 0x14ca2b9e44fe1f7L, + 0x0214566ef992bcbL, 0x168d083a890f6f9L, 0x0c57e879c03cc91L, + 0x01f27db490cce65L, 0x05fdbe784207821L, 0x01e5f4c55b32dc2L, + 0x029773666901ab5L, 0x1ac2e12e07a9eb8L, 0x00e532839653fc3L }, + { 0x1b321cf2b9d25a0L, 0x1fee52053a36dfdL, 0x0c39678da2d59abL, + 0x08fb000d1f8382aL, 0x1647dd6856ed1eaL, 0x1bc6d44dba6c7f2L, + 0x0ce44765ad41e26L, 0x0be736ea487177cL, 0x0ef8d443e0d858cL, + 0x0e96da4cb23551aL, 0x14ef47999d50f13L, 0x0180d130130aff5L, + 0x1249facabad0d71L, 0x0a7cd0c94fbd7f9L, 0x0cc1e841577b070L, + 0x1fec9594cc7323fL, 0x0eeac44fd9135ffL, 0x0231657db65d69eL }, + { 0x060a647de3237ddL, 0x19ae6415c3a020bL, 0x1d6777e957e257dL, + 0x1ce4d72295ef0f3L, 0x1c93e29815ef043L, 0x18c1988c3a9c9e8L, + 0x084ae868af9d1bbL, 0x0fe9cfd1bf84b53L, 0x1dfefc97da9c391L, + 0x043ae8185175f20L, 0x1748d69ccb4732fL, 0x0ffdb3754da61eeL, + 0x0b65f4857606feeL, 0x089fc1e0553c27dL, 0x03e744c8c557889L, + 0x1d5fba5f6ee307dL, 0x0082a291503b546L, 0x00949e4c6366c9bL }, + { 0x078125149d53b77L, 0x1a01ecb757d63b9L, 0x1f6d28dadc469aaL, + 0x110fcee3836faf8L, 0x13b375228238c70L, 0x03a986a4afb55f9L, + 0x0446ac2c0a27232L, 0x13d9507970dcef6L, 0x1be1c0fb8a1bd18L, + 0x067d97d8d74ebe3L, 0x108f1525030fa16L, 0x1c82e95b220fa0bL, + 0x05064e714216e79L, 0x1efeb0a7d0523f8L, 0x11a622f1a4a7353L, + 0x11f63db64b09872L, 0x0ba73e4b5f3e46fL, 0x029dbcd50b4754aL }, + { 0x16fafce44bbb6a1L, 0x0ddd033c10b9410L, 0x0cc2a7764e6b4e9L, + 0x1be33df5fdde3c9L, 0x1b4ec014022eaf3L, 0x16339c7f6ad5e73L, + 0x02689925a3b9944L, 0x00a462330d253fdL, 0x00d539d8d47397cL, + 0x0005e2a11a2cb62L, 0x01fd614d1984759L, 0x120793abb41f725L, + 0x17c83af2a804099L, 0x1940a8f0f2f7a4cL, 0x10044132277006cL, + 0x0593a2a1f6952b0L, 0x03340a6f7d5f387L, 0x041486b68ab6174L }, + { 0x04637c6d8546946L, 0x1a51cb4f62bfd7cL, 0x06935e2401fb684L, + 0x1c1b8f7013a846bL, 0x0d6784a9b42557fL, 0x056daff31572969L, + 0x1f29689c532982fL, 0x02398411bcc6755L, 0x02380ed5ced9678L, + 0x135aaf4ed990b30L, 0x0b40b299d48d69bL, 0x1df3667f41c237dL, + 0x06f06a2a0851cc6L, 0x1623d9e7fe911f1L, 0x0aa613803cccb87L, + 0x05c288b3e52f741L, 0x1b06fa1d969ee95L, 0x0283778d59827d5L }, + { 0x1b4eb2735bff163L, 0x05cb7f54fd4c208L, 0x0cfe77ac9f39c4cL, + 0x0b3ba387aacd59dL, 0x073075aaa2daf1aL, 0x038dac7a84853f5L, + 0x0b670da9abce78cL, 0x02d451ac67bbee7L, 0x0dd354cacbdc89aL, + 0x1f51a11ea6e5e1eL, 0x11d348de764b477L, 0x0adf1ddacecadddL, + 0x03fa8feb1fe14a4L, 0x1cc7e5e3fd5f3baL, 0x069c1b8501333e2L, + 0x18cf0d99a5f7feeL, 0x144daaf3fdb4d85L, 0x020adbedf8a9001L }, + { 0x10105867d8377a7L, 0x11eb465c019394bL, 0x0a27c0e930c81a2L, + 0x1b2791e521facfaL, 0x09e5a2b84bc7095L, 0x15cf9db897d09e7L, + 0x1530bf1ab1b183fL, 0x00219b46db2dc1cL, 0x14549975186320aL, + 0x098c648cbf80788L, 0x1130ff9a4d9423eL, 0x1df30be0d15403bL, + 0x10a2b5511c769a2L, 0x1a0917029a91677L, 0x1d750fc01a597b6L, + 0x03ab3f9c1f5f982L, 0x19d525dc9bdec83L, 0x00f618a78d7ac43L }, + { 0x063feef2c8310c2L, 0x10a6d22bf1fba03L, 0x03f394d1a21ea9fL, + 0x1ec6fd858a72562L, 0x1542f8dfcde4a38L, 0x0f0b88a83b99905L, + 0x06f18d04c0be7dfL, 0x0de031638c75c97L, 0x0f001c46edd2f9eL, + 0x1dd854b937667d0L, 0x06e675dd1b831f4L, 0x0defeb0eb5d9526L, + 0x1c96939c82e0c8bL, 0x1ef2d3325d9978bL, 0x0afe9add944d748L, + 0x00bbce326d968a5L, 0x188ad5cc08f2dc1L, 0x00bf48e893fffabL }, + { 0x092ced3b7e051caL, 0x06a7e8ce3bb6a5fL, 0x0d480219e12f191L, + 0x0f9d3ad66391569L, 0x1289e9c73ea6622L, 0x150cf71ca924d1eL, + 0x16bb15142799744L, 0x01d4f7a8d25186cL, 0x1354997e477963eL, + 0x0bb2cabdaccb996L, 0x012bae47528ed83L, 0x1d483bd67c5132bL, + 0x0d572571df6e653L, 0x18c570fce53e4c7L, 0x1dee5fbcc068e3eL, + 0x141aa2c53ef84c7L, 0x001df242282afc4L, 0x008c79da59eee86L }, + { 0x0a0a0a87ad4762bL, 0x1c26d462c68babaL, 0x058133ddb6186bbL, + 0x0cfcc1b3162dfe9L, 0x1ecc1dbac0be878L, 0x0b0a3d41b1bffd9L, + 0x11b970912982577L, 0x00b47c2f068b610L, 0x1735eb686e77a4cL, + 0x1e0c5a7efbac34aL, 0x06342c6f7f94bd6L, 0x181a00e2b7422acL, + 0x1ac2dd617f878ecL, 0x10db0b880edede8L, 0x1d64f08874ad8c4L, + 0x0e048459d14f289L, 0x1273b9b536a44f1L, 0x000e8533e4681f3L }, + { 0x19642361e46533cL, 0x1bcc87dc461573dL, 0x145a90b12863a51L, + 0x1bb078f48a0336bL, 0x0cb663e37135e81L, 0x1606b1ba534deeaL, + 0x03699ed9fb36f9dL, 0x01407aa8a4223cdL, 0x1596cceb5d2e865L, + 0x0ab96fe95781d9bL, 0x192e87eaf5654b3L, 0x08ad69db0ad2a46L, + 0x12c950d5d47f47dL, 0x043717c22d6c5abL, 0x1aec1132b74b7e9L, + 0x011cdbaa4f6878aL, 0x00fc9adba24997cL, 0x00db12d833ed319L }, + { 0x0dfaa7b4fd8446dL, 0x19780d7b7f5f5a2L, 0x0e23fa20e2d7006L, + 0x1f7752eb177e888L, 0x07156bc9f33c434L, 0x0484c595cb8e5d4L, + 0x11775ac9179707dL, 0x1af0fb96a685683L, 0x0db1f80c634d852L, + 0x0b7192c1219ed1aL, 0x008194fdf7c309bL, 0x0cf86c1966cbecdL, + 0x029826656ac4ca5L, 0x1f834bb4190fd56L, 0x01d98e44fd729beL, + 0x0e6dc2a72f2434eL, 0x08dbdf143288400L, 0x0199f654b0cfe4aL }, + { 0x1337948ac775d81L, 0x128c7ea0edde511L, 0x093ef3f3a520e30L, + 0x0ca8e07fcec478fL, 0x13fb3b5baad3623L, 0x0e00f8159d09d20L, + 0x0598576cd5969fdL, 0x123ae4811b8a46bL, 0x15a17f8e51d616eL, + 0x060b775e592dcccL, 0x1a33c4ce4dd0fa4L, 0x0e95ca96c94fe6bL, + 0x0a65cd449d987daL, 0x1bf3d8aeaabd991L, 0x1344d3dd9420a94L, + 0x00e8c9a4b8e85e5L, 0x135ae9d9c074ccfL, 0x0397e1088439468L }, + { 0x106b203f96004c8L, 0x1cae7a2c02affd4L, 0x019d57cd642760fL, + 0x17caa191ddaefabL, 0x15a060814a9ea6fL, 0x14103148e46654aL, + 0x1e179287fb9e2f3L, 0x0cdd735bc0d347bL, 0x1fbbdcf0c7d3de6L, + 0x1451c8dae99b6a8L, 0x1e34a170bff0f08L, 0x1bc65ef62cb6ec1L, + 0x04561770401ee48L, 0x0ef7fcd001c01ecL, 0x1f8d69395cfd922L, + 0x14d8dc344e71d42L, 0x12d238ef17c8840L, 0x02404a37c588f6cL }, + { 0x0c747a8fd71f119L, 0x12e2f29f59b4ac2L, 0x1e198a6161e8679L, + 0x135631ade81c5ecL, 0x0630b8c048a4889L, 0x157c4950d4c8126L, + 0x15892125d4258b2L, 0x1a9910d3575c41fL, 0x03b72b04d6c2b7dL, + 0x13baf5b04c97be8L, 0x0701b9f41b9a138L, 0x06c3c977a00e011L, + 0x0b4ba846e4cb3b4L, 0x032326cf50d7333L, 0x1e14e7f0070bac9L, + 0x15f8ff0de57cd83L, 0x10216e8e8aecf68L, 0x046d5b0fee39c34L }, + { 0x0a5c903d54d1d45L, 0x014bf7fa7cdd121L, 0x1480d351e2d2b35L, + 0x161188c4345b116L, 0x1486540235b2ba2L, 0x0f997369e91cdd9L, + 0x1f708779dabb644L, 0x0050eff179e7e0dL, 0x1802714c19ec515L, + 0x0822275d2c83806L, 0x108a7cc773255e8L, 0x0f57702d3fdb0d2L, + 0x152caf080e5ece7L, 0x05ebe778aadf450L, 0x0e5fb84fac86c53L, + 0x0d2193bdef5a2cfL, 0x1e7e03ca879118fL, 0x037bbf316fccd94L }, + { 0x071bdede40bbf59L, 0x1d229b200d56b51L, 0x00d5cd5073445deL, + 0x0c96e3605e2eabcL, 0x0813359f3465b46L, 0x1c75639175b889dL, + 0x1ced65e4aa3f5bcL, 0x17e2354025ffe77L, 0x099aafabff85c3fL, + 0x0f0517783606621L, 0x15755ddcedecea4L, 0x1cedacd30814629L, + 0x132e5a8be6ae5e2L, 0x00e7aac04309b03L, 0x0fb440bb9b5d5e3L, + 0x1e1d64689c01ed1L, 0x180799d78868184L, 0x031c0ce48e1e967L }, + { 0x05392e17884b073L, 0x1d0fe758933f565L, 0x17c241c0e29e7b0L, + 0x19c988f6e07a0feL, 0x1bf96b91cb2ac07L, 0x1527dffcb332770L, + 0x19403afd5d624abL, 0x008b557e723f5bcL, 0x0c5b3376f171d12L, + 0x1fb0628d069ec0dL, 0x0b3f9e5daa112c7L, 0x19357b4c24b4216L, + 0x134ebd453ee131cL, 0x0825b5e0f07e0b6L, 0x0be32af0340c669L, + 0x1368fc87417ce14L, 0x1eec80afeec55e4L, 0x033ea46894132ebL }, + { 0x08d59a7ea2d56d6L, 0x15e8713a4053183L, 0x16c2b9cd9b375c6L, + 0x140e409d78d7a23L, 0x177e6293fbb639cL, 0x1d461ec4d12173fL, + 0x1e6a37b9f28add6L, 0x0208e5bb87ac945L, 0x084229df47561a0L, + 0x0fb1642e2db24eaL, 0x15ac6d37249f365L, 0x0240bdcc0b2dfbaL, + 0x10abf29401fe8bbL, 0x0868e0c21f7e552L, 0x0c077d75240343cL, + 0x087ea59e2275251L, 0x1c7a3d7ebc31f0eL, 0x013ca871c741c26L }, + { 0x0b21ff0e1d0fa79L, 0x1e8198245aef4f5L, 0x1a24bf8dd32d2e7L, + 0x149d643ed699268L, 0x0925e7e7bb4827fL, 0x0a6298a338b7bcdL, + 0x1b77c510afcd9f7L, 0x11240e72a99a5d2L, 0x14e0141ae8502aaL, + 0x170070d4777b664L, 0x1a1245620336be3L, 0x14b8d2c5008cab9L, + 0x185d15dfbfff3abL, 0x0fb4279299ae627L, 0x0796f629fc11032L, + 0x04b575d008a7f76L, 0x171a1c99813ff22L, 0x02a7fbc423cd92eL }, + { 0x1c6ee30de40b068L, 0x1232df379d28f13L, 0x1813e8ec87da489L, + 0x1b8083022bc4948L, 0x0df90d2b50a5a5aL, 0x186007f1942a20cL, + 0x0238eedd3963f72L, 0x1938d1e36769458L, 0x1339df0810ccd9eL, + 0x0a9b16e5bc3754fL, 0x1178c72556bab64L, 0x003b16d4d8d6512L, + 0x1c3678a427d6a2cL, 0x14649816034f416L, 0x08407985e1d5400L, + 0x1650d159b52cb3fL, 0x0fe4e4e4573ee30L, 0x0456dd6c29f8c18L }, + { 0x00ae11f0969d524L, 0x1ed7bf9cde63c83L, 0x1d99f307f30bd0bL, + 0x05c466da9e79d8cL, 0x0e1c0f7f456b9cfL, 0x027d873550faef4L, + 0x12ca336f0ab4826L, 0x1de81219f4c368cL, 0x140d86f301243f3L, + 0x0d8b66666af43f3L, 0x1c5a30c09b35065L, 0x0d9702d80e60807L, + 0x1358407a1ddbe38L, 0x0b8bf0d78a75c37L, 0x12f25b3d622d3e0L, + 0x0e3836eb8834ccdL, 0x05ff342c1aa027eL, 0x039c9801b604a2fL }, + { 0x14f757d22cdaf42L, 0x1ac8efa0c0d55caL, 0x0067d5453c95e22L, + 0x11e31fab791730dL, 0x022ceb9169642e0L, 0x07b4c2c95982e88L, + 0x072b85c5640f9a9L, 0x15497afad3ac22fL, 0x0dacdfd5dd29c01L, + 0x02eeead6c888466L, 0x0b1ec592b23c55cL, 0x09c36a48c65e869L, + 0x1b731fc44761a51L, 0x104b0d98a2dcf30L, 0x1abc88f3d584d23L, + 0x133a7385152cee7L, 0x1e25bd10182aa7cL, 0x045e376257214b2L }, + { 0x096e5c0e7f2a32bL, 0x04006049c451868L, 0x0df10078d833fd5L, + 0x1976c0a94c0dfc8L, 0x0457aa6e6655fc9L, 0x14d95ba8870c304L, + 0x1698682b3f288acL, 0x194e64907c6a36fL, 0x1e31471ee6be6c8L, + 0x0b2a18e45b2e4d0L, 0x0b0ee5235972ef9L, 0x18435d365551f93L, + 0x0daa60aa6ad308fL, 0x0c17e06a6b53ef8L, 0x11e935ca11365aaL, + 0x112ab56025858b0L, 0x0152b3c8f71dcebL, 0x04742a1bedf4e3fL }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 18]; + sp_digit tx[2 * 18]; + sp_digit ty[2 * 18]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 18 * 2; + ty = td + 5 * 18 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 18); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 18); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_18(tx, ty, t); + sp_1024_proj_mul_qx1_18(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_18(tx, tx, t); + sp_1024_mont_mul_18(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 18, 0, sizeof(sp_digit) * 18); + sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_18(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + + /* t1 = px + py */ + sp_1024_mont_add_18(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_18(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_18(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_18(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_18(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_18(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_18(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_18(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_18(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + + sp_1024_mont_inv_18(t1, p->z, t2); + sp_1024_mont_sqr_18(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_18(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 18); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_18(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 18; + sp_digit* pz2 = t + 2 * 18; + sp_digit* rx = t + 4 * 18; + sp_digit* ry = t + 6 * 18; + sp_digit* l = t + 8 * 18; + sp_digit* ty = t + 10 * 18; + + /* v = v^2 */ + sp_1024_proj_sqr_18(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_18(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_18(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_18(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_18(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_18(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_18(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_18(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_18(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_18(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_18(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_18(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_18(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_18(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_18(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_18(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_18(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_18(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_18(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_18(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_18(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_18(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_18(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_18(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_18(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_18(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_18(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + sp_digit* rx = t + 4 * 18; + sp_digit* ry = t + 6 * 18; + sp_digit* h = t + 8 * 18; + sp_digit* r = t + 10 * 18; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_18(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_18(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_18(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_18(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_18(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_18(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_18(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_18(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_18(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_18(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_18(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_18(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_18(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_18(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_18(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_18(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_18(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_18(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_18(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_18(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_18(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_18(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_18(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_18(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_18(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 18]; + sp_digit vx[2 * 18]; + sp_digit vy[2 * 18]; + sp_digit qx_px[2 * 18]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_18(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 18 * 2; + vy = td + 7 * 18 * 2; + qx_px = td + 8 * 18 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_18(p, pm); + sp_1024_point_from_ecc_point_18(q, qm); + + err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 18); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 18); + + sp_1024_mont_add_18(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_18(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 57] >> (i % 57)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_18(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_18(vx, vy, t); + sp_1024_proj_sqr_18(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_18(vx, vx, t); + sp_1024_mont_mul_18(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 18, 0, sizeof(sp_digit) * 18); + sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_18(c, 1, NULL); + sp_1024_point_free_18(q, 1, NULL); + sp_1024_point_free_18(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_18(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 18; + sp_digit* rx = t + 4 * 18; + sp_digit* ry = t + 6 * 18; + sp_digit* h = t + 8 * 18; + sp_digit* r = t + 10 * 18; + + /* h = p.z^2 */ + sp_1024_mont_sqr_18(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_18(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_18(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_18(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_18(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_18(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_18(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_18(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_18(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_18(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_18(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_18(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_18(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_18(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_18(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_18(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_18(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_18(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_18(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_18(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_18(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_18(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_18(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_18(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_18(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_18(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_18(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_18(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_18(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_18(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_18(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_18(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_18(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_18(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 18; + sp_digit* pz2 = t + 2 * 18; + sp_digit* rx = t + 4 * 18; + sp_digit* ry = t + 6 * 18; + sp_digit* l = t + 8 * 18; + sp_digit* ty = t + 10 * 18; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_18(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_18(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_18(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_18(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_18(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_18(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_18(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_18(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_18(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_18(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_18(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_18(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_18(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_18(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_18(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_18(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_18(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_18(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_18(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_18(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_18(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_18(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_18(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_18(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_18(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_18(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_18(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[36]; + sp_digit (*pre_vy)[36]; + sp_digit (*pre_nvy)[36]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 18]; + sp_digit vx[2 * 18]; + sp_digit vy[2 * 18]; + sp_digit pre_vx[16][36]; + sp_digit pre_vy[16][36]; + sp_digit pre_nvy[16][36]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_18(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 18 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 18 * 2; + vy = td + 7 * 18 * 2; + pre_vx = (sp_digit(*)[36])(td + 8 * 18 * 2); + pre_vy = (sp_digit(*)[36])(td + 24 * 18 * 2); + pre_nvy = (sp_digit(*)[36])(td + 40 * 18 * 2); + pre_p = (sp_point_1024*)(td + 56 * 18 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_18(p, pm); + sp_1024_point_from_ecc_point_18(q, qm); + + err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 18); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 18); + sp_1024_mont_sub_18(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 18); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 18); + sp_1024_accumulate_line_dbl_18(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 18); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 18); + sp_1024_proj_mul_18(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_18(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_18(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 18); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 18); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_18(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_18(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_18(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_18(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_18(vx, vy, t); + sp_1024_proj_sqr_18(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_18(vx, vx, t); + sp_1024_mont_mul_18(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 18, 0, sizeof(sp_digit) * 18); + sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_18(c, 1, NULL); + sp_1024_point_free_18(q, 1, NULL); + sp_1024_point_free_18(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_18(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 18; + sp_digit* t2 = t + 2 * 2 * 18; + sp_digit* l = t + 4 * 2 * 18; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_18(l, py, p1024_mod); + sp_1024_mont_inv_18(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_18(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_18(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_18(t2, t1, p1024_mod); + sp_1024_mont_add_18(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_18(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_18(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_18(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 18); + XMEMCPY(cr, t2, sizeof(sp_digit) * 18); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_18(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 18; + sp_digit* c = t + 2 * 2 * 18; + sp_digit* l = t + 4 * 2 * 18; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_18(l, cx, px, p1024_mod); + sp_1024_mont_inv_18(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_18(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_18(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_18(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_18(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_18(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_18(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 18); + XMEMCPY(cr, c, sizeof(sp_digit) * 18); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_18(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 18; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_18(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_18(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_18(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_18(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 18]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 18 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 18 * 2); +#endif + + sp_1024_point_from_ecc_point_18(p, pm); + + err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_18(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_18(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_18(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_18(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_18(c, c, t); + sp_1024_mont_map_18(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_18(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_18(c, c, &pre_p[j/2], t); + sp_1024_mont_map_18(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_18(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_18(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_18(c, c, neg, t); + sp_1024_mont_map_18(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_18(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_18(c, c, t); + sp_1024_mont_map_18(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_18(neg, 1, NULL); + sp_1024_point_free_18(c, 1, NULL); + sp_1024_point_free_18(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[36]; + sp_digit (*pre_vy)[36]; + sp_digit (*pre_nvy)[36]; +#else + sp_digit t[6 * 2 * 18]; + sp_digit vx[2 * 18]; + sp_digit vy[2 * 18]; + sp_digit pre_vx[16][36]; + sp_digit pre_vy[16][36]; + sp_digit pre_nvy[16][36]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_18(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 18 * 2; + vy = td + 7 * 18 * 2; + pre_vx = (sp_digit(*)[36])(td + 8 * 18 * 2); + pre_vy = (sp_digit(*)[36])(td + 24 * 18 * 2); + pre_nvy = (sp_digit(*)[36])(td + 40 * 18 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_18(p, pm); + sp_1024_point_from_ecc_point_18(q, qm); + + err = sp_1024_mod_mul_norm_18(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_18(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 18); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 18); + sp_1024_mont_sub_18(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 18); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 18); + sp_1024_accumulate_line_dbl_18(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 18); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 18); + sp_1024_proj_mul_18(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_18(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_18(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 18); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 18); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 18); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_18(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_18(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_18(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_18(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_18(vx, vy, t); + sp_1024_proj_sqr_18(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_18(vx, vx, t); + sp_1024_mont_mul_18(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 18, 0, sizeof(sp_digit) * 18); + sp_1024_mont_reduce_18(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_18(c, 1, NULL); + sp_1024_point_free_18(q, 1, NULL); + sp_1024_point_free_18(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_18(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] | + a[16] | a[17]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 49U) { + r[j] &= 0x1ffffffffffffffL; + s = 57U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_18(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[18 * 4]; +#endif + sp_digit* t2 = NULL; + int64_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 18; + + sp_1024_sqr_18(t1, point->y); + (void)sp_1024_mod_18(t1, t1, p1024_mod); + sp_1024_sqr_18(t2, point->x); + (void)sp_1024_mod_18(t2, t2, p1024_mod); + sp_1024_mul_18(t2, t2, point->x); + (void)sp_1024_mod_18(t2, t2, p1024_mod); + (void)sp_1024_sub_18(t2, p1024_mod, t2); + sp_1024_mont_add_18(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_18(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_18(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_18(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_18(t1, p1024_mod); + sp_1024_cond_sub_18(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_18(t1); + if (!sp_1024_iszero_18(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 18, pX); + sp_1024_from_mp(pub->y, 18, pY); + sp_1024_from_bin(pub->z, 18, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_18(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[18]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 18, pX); + sp_1024_from_mp(pub->y, 18, pY); + sp_1024_from_bin(pub->z, 18, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 18, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_18(pub->x) != 0) && + (sp_1024_iszero_18(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_18(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_18(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_18(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_1024_ecc_mulmod_18(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_18(p->x) == 0) || + (sp_1024_iszero_18(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_1024_ecc_mulmod_base_18(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_18(p->x, pub->x) != 0) || + (sp_1024_cmp_18(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* SP_WORD_SIZE == 64 */ #endif /* !WOLFSSL_SP_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c index f2e9132bc..7d08726d6 100644 --- a/wolfcrypt/src/sp_cortexm.c +++ b/wolfcrypt/src/sp_cortexm.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -67,7 +67,8 @@ */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -109,7 +110,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -143,7 +145,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -182,7 +186,10 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_2048_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 2048 / 8 - 1; a[j] = 0; @@ -1277,7 +1284,9 @@ SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, sp_digit a1[8]; sp_digit b1[8]; sp_digit z2[16]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_8(a1, a, &a[8]); cb = sp_2048_add_8(b1, b, &b[8]); @@ -1570,7 +1579,9 @@ SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, sp_digit a1[16]; sp_digit b1[16]; sp_digit z2[32]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_16(a1, a, &a[16]); cb = sp_2048_add_16(b1, b, &b[16]); @@ -2023,7 +2034,9 @@ SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, sp_digit a1[32]; sp_digit b1[32]; sp_digit z2[64]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_32(a1, a, &a[32]); cb = sp_2048_add_32(b1, b, &b[32]); @@ -2692,7 +2705,7 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -2701,7 +2714,8 @@ SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -2710,7 +2724,7 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -2922,8 +2936,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_32(r, a, b); sp_2048_mont_reduce_32(r, m, mp); @@ -2936,8 +2950,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_32(r, a); sp_2048_mont_reduce_32(r, m, mp); @@ -3149,35 +3163,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 64]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3225,34 +3235,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -3273,9 +3283,8 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -3294,35 +3303,31 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 64]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 64), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 64; -#else - t[i] = &td[i * 64]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3386,34 +3391,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -3435,16 +3440,15 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -3461,7 +3465,7 @@ static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m) sp_2048_sub_in_place_64(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -3615,8 +3619,8 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_64(r, a, b); sp_2048_mont_reduce_64(r, m, mp); @@ -3629,8 +3633,8 @@ static void sp_2048_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_64(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_64(r, a); sp_2048_mont_reduce_64(r, m, mp); @@ -3884,35 +3888,31 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 128]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_2048_mont_setup(m, &mp); @@ -3960,34 +3960,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -4008,9 +4008,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4029,35 +4028,31 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 128]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 128), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 128; -#else - t[i] = &td[i * 128]; -#endif } sp_2048_mont_setup(m, &mp); @@ -4121,34 +4116,34 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -4170,9 +4165,8 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -4193,19 +4187,18 @@ static int sp_2048_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128], m[64], r[128]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 256) { @@ -4219,22 +4212,18 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 64 * 2; - m = r + 64 * 2; - } #endif if (err == MP_OKAY) { + r = a + 64 * 2; + m = r + 64 * 2; ah = a + 64; sp_2048_from_bin(ah, 64, in, inLen); @@ -4307,10 +4296,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -4375,13 +4363,17 @@ SP_NOINLINE static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[64 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -4410,13 +4402,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 64; m = a + 128; @@ -4427,31 +4421,36 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, sp_2048_from_mp(m, 64, mm); err = sp_2048_mod_exp_64(r, a, d, 2048, m, 0); } + if (err == MP_OKAY) { sp_2048_to_bin(r, out); *outLen = 256; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[64 * 2]; - sp_digit p[32], q[32], dp[32]; - sp_digit tmpa[64], tmpb[64]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[32 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -4471,31 +4470,23 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 64 * 2; q = p + 32; qi = dq = dp = q + 32; tmpa = qi + 32; tmpb = tmpa + 64; - - r = t + 64; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_2048_from_bin(a, 64, in, inLen); sp_2048_from_mp(p, 32, pm); sp_2048_from_mp(q, 32, qm); @@ -4527,18 +4518,15 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 32 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -4562,17 +4550,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 64; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -4585,14 +4575,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -4619,10 +4611,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -5074,34 +5069,31 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[193]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 128; -#else - tmp = &td[128]; -#endif sp_2048_mont_setup(m, &mp); sp_2048_mont_norm_64(norm, m); @@ -5119,34 +5111,34 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_2048_lshift_64(r, norm, (byte)y); + sp_2048_lshift_64(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -5157,7 +5149,7 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, sp_2048_mont_sqr_64(r, r, m, mp); sp_2048_mont_sqr_64(r, r, m, mp); - sp_2048_lshift_64(r, r, (byte)y); + sp_2048_lshift_64(r, r, y); sp_2048_mul_d_64(tmp, norm, r[64]); r[64] = 0; o = sp_2048_add_64(r, r, tmp); @@ -5172,9 +5164,8 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -5193,11 +5184,13 @@ static int sp_2048_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; word32 i; @@ -5232,6 +5225,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -5253,10 +5247,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -5293,7 +5290,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -5307,7 +5304,8 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -5349,7 +5347,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -5383,7 +5382,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -5422,7 +5423,10 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_3072_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 3072 / 8 - 1; a[j] = 0; @@ -5920,7 +5924,9 @@ SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, sp_digit a1[12]; sp_digit b1[12]; sp_digit z2[24]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_12(a1, a, &a[12]); cb = sp_3072_add_12(b1, b, &b[12]); @@ -6293,7 +6299,9 @@ SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, sp_digit a1[24]; sp_digit b1[24]; sp_digit z2[48]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_24(a1, a, &a[24]); cb = sp_3072_add_24(b1, b, &b[24]); @@ -6906,7 +6914,9 @@ SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, sp_digit a1[48]; sp_digit b1[48]; sp_digit z2[96]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_3072_add_48(a1, a, &a[48]); cb = sp_3072_add_48(b1, b, &b[48]); @@ -7589,7 +7599,7 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -7598,7 +7608,8 @@ SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -7607,7 +7618,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -7819,8 +7830,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_48(r, a, b); sp_3072_mont_reduce_48(r, m, mp); @@ -7833,8 +7844,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_48(r, a); sp_3072_mont_reduce_48(r, m, mp); @@ -8046,35 +8057,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 96]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -8122,34 +8129,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -8170,9 +8177,8 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -8191,35 +8197,31 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 96]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 96), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 96; -#else - t[i] = &td[i * 96]; -#endif } sp_3072_mont_setup(m, &mp); @@ -8283,34 +8285,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -8332,16 +8334,15 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; } #endif /* WOLFSSL_SP_SMALL */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -8358,7 +8359,7 @@ static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m) sp_3072_sub_in_place_96(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -8513,8 +8514,8 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_96(r, a, b); sp_3072_mont_reduce_96(r, m, mp); @@ -8527,8 +8528,8 @@ static void sp_3072_mont_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_96(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_96(r, a); sp_3072_mont_reduce_96(r, m, mp); @@ -8784,35 +8785,31 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 192]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 192), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 192; -#else - t[i] = &td[i * 192]; -#endif } sp_3072_mont_setup(m, &mp); @@ -8860,34 +8857,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 96); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -8908,9 +8905,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -8929,35 +8925,31 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 192]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 192), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 192; -#else - t[i] = &td[i * 192]; -#endif } sp_3072_mont_setup(m, &mp); @@ -9021,34 +9013,34 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 96); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -9070,9 +9062,8 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -9093,19 +9084,18 @@ static int sp_3072_mod_exp_96(sp_digit* r, const sp_digit* a, const sp_digit* e, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[192], m[96], r[192]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[96 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 384) { @@ -9119,22 +9109,18 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 96 * 2; - m = r + 96 * 2; - } #endif if (err == MP_OKAY) { + r = a + 96 * 2; + m = r + 96 * 2; ah = a + 96; sp_3072_from_bin(ah, 96, in, inLen); @@ -9207,10 +9193,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -9275,13 +9260,17 @@ SP_NOINLINE static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[96 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -9310,13 +9299,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 96; m = a + 192; @@ -9327,31 +9318,36 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, sp_3072_from_mp(m, 96, mm); err = sp_3072_mod_exp_96(r, a, d, 3072, m, 0); } + if (err == MP_OKAY) { sp_3072_to_bin(r, out); *outLen = 384; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 96); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 96); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[96 * 2]; - sp_digit p[48], q[48], dp[48]; - sp_digit tmpa[96], tmpb[96]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[48 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -9371,31 +9367,23 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 96 * 2; q = p + 48; qi = dq = dp = q + 48; tmpa = qi + 48; tmpb = tmpa + 96; - - r = t + 96; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_3072_from_bin(a, 96, in, inLen); sp_3072_from_mp(p, 48, pm); sp_3072_from_mp(q, 48, qm); @@ -9427,18 +9415,15 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 48 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -9462,17 +9447,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 96; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 96; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -9485,14 +9472,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 96; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -9519,10 +9508,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[192], e[96], m[96]; + sp_digit b[192]; + sp_digit e[96]; + sp_digit m[96]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -10170,34 +10162,31 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[289]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 192; -#else - tmp = &td[192]; -#endif sp_3072_mont_setup(m, &mp); sp_3072_mont_norm_96(norm, m); @@ -10215,34 +10204,34 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_3072_lshift_96(r, norm, (byte)y); + sp_3072_lshift_96(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -10253,7 +10242,7 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, sp_3072_mont_sqr_96(r, r, m, mp); sp_3072_mont_sqr_96(r, r, m, mp); - sp_3072_lshift_96(r, r, (byte)y); + sp_3072_lshift_96(r, r, y); sp_3072_mul_d_96(tmp, norm, r[96]); r[96] = 0; o = sp_3072_add_96(r, r, tmp); @@ -10268,9 +10257,8 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -10289,11 +10277,13 @@ static int sp_3072_mod_exp_2_96(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[192], e[96], m[96]; + sp_digit b[192]; + sp_digit e[96]; + sp_digit m[96]; sp_digit* r = b; word32 i; @@ -10328,6 +10318,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -10349,10 +10340,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -10389,7 +10383,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -10403,7 +10397,8 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -10445,7 +10440,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -10479,7 +10475,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -10518,7 +10516,10 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) */ static void sp_4096_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 4096 / 8 - 1; a[j] = 0; @@ -11245,7 +11246,9 @@ SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, sp_digit a1[64]; sp_digit b1[64]; sp_digit z2[128]; - sp_digit u, ca, cb; + sp_digit u; + sp_digit ca; + sp_digit cb; ca = sp_2048_add_64(a1, a, &a[64]); cb = sp_2048_add_64(b1, b, &b[64]); @@ -11609,7 +11612,8 @@ SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -11618,7 +11622,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } /* Mul a by digit b into r. (r = a * b) @@ -11678,7 +11682,7 @@ static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m) sp_4096_sub_in_place_128(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -11832,8 +11836,8 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_128(r, a, b); sp_4096_mont_reduce_128(r, m, mp); @@ -11846,8 +11850,8 @@ static void sp_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_128(r, a); sp_4096_mont_reduce_128(r, m, mp); @@ -12103,35 +12107,31 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[16 * 256]; #endif sp_digit* t[16]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (16 * 256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<16; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 256; -#else - t[i] = &td[i * 256]; -#endif } sp_4096_mont_setup(m, &mp); @@ -12179,34 +12179,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 128); for (; i>=0 || c>=4; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 28); + y = (byte)(n >> 28); n <<= 4; c = 28; } else if (c < 4) { - y = (int)(n >> 28); + y = (byte)(n >> 28); n = e[i--]; c = 4 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 28) & 0xf); + y = (byte)((n >> 28) & 0xf); n <<= 4; c -= 4; } @@ -12227,9 +12227,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -12248,35 +12247,31 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e int bits, const sp_digit* m, int reduceA) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[32 * 256]; #endif sp_digit* t[32]; - sp_digit* norm; + sp_digit* norm = NULL; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (32 * 256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; for (i=0; i<32; i++) { -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) t[i] = td + i * 256; -#else - t[i] = &td[i * 256]; -#endif } sp_4096_mont_setup(m, &mp); @@ -12340,34 +12335,34 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 128); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -12389,9 +12384,8 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -12412,19 +12406,18 @@ static int sp_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[256], m[128], r[256]; -#else - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[128 * 5]; +#endif sp_digit* m = NULL; sp_digit* r = NULL; -#endif sp_digit *ah = NULL; - sp_digit e[1]; + sp_digit e[1] = {0}; int err = MP_OKAY; if (*outLen < 512) { @@ -12438,22 +12431,18 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 128 * 2; - m = r + 128 * 2; - } #endif if (err == MP_OKAY) { + r = a + 128 * 2; + m = r + 128 * 2; ah = a + 128; sp_4096_from_bin(ah, 128, in, inLen); @@ -12526,10 +12515,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -12595,13 +12583,17 @@ SP_NOINLINE static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) - sp_digit* a = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[128 * 4]; +#endif + sp_digit* a = NULL; sp_digit* m = NULL; sp_digit* r = NULL; int err = MP_OKAY; @@ -12630,13 +12622,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) { + if (d == NULL) err = MEMORY_E; - } } +#endif + if (err == MP_OKAY) { a = d + 128; m = a + 256; @@ -12647,31 +12641,36 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, sp_4096_from_mp(m, 128, mm); err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0); } + if (err == MP_OKAY) { sp_4096_to_bin(r, out); *outLen = 512; } - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 128); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) +#endif + { + /* only "a" and "r" are sensitive and need zeroized (same pointer) */ + if (a != NULL) + ForceZero(a, sizeof(sp_digit) * 128); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif } return err; #else -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit a[128 * 2]; - sp_digit p[64], q[64], dp[64]; - sp_digit tmpa[128], tmpb[128]; -#else - sp_digit* t = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* a = NULL; +#else + sp_digit a[64 * 11]; +#endif sp_digit* p = NULL; sp_digit* q = NULL; sp_digit* dp = NULL; sp_digit* tmpa = NULL; sp_digit* tmpb = NULL; -#endif sp_digit* r = NULL; sp_digit* qi = NULL; sp_digit* dq = NULL; @@ -12691,31 +12690,23 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 128 * 2; q = p + 64; qi = dq = dp = q + 64; tmpa = qi + 64; tmpb = tmpa + 128; - - r = t + 128; - } -#else -#endif - - if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) r = a; - qi = dq = dp; -#endif + sp_4096_from_bin(a, 128, in, inLen); sp_4096_from_mp(p, 64, pm); sp_4096_from_mp(q, 64, qm); @@ -12747,18 +12738,15 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpa, 0, sizeof(tmpa)); - XMEMSET(tmpb, 0, sizeof(tmpb)); - XMEMSET(p, 0, sizeof(p)); - XMEMSET(q, 0, sizeof(q)); - XMEMSET(dp, 0, sizeof(dp)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 64 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ return err; } @@ -12782,17 +12770,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 128; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 128; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -12805,14 +12795,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 128; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -12839,10 +12831,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[256], e[128], m[128]; + sp_digit b[256]; + sp_digit e[128]; + sp_digit m[128]; sp_digit* r = b; int expBits = mp_count_bits(exp); @@ -13686,34 +13681,31 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* td; + sp_digit* td = NULL; #else sp_digit td[385]; #endif - sp_digit* norm; - sp_digit* tmp; + sp_digit* norm = NULL; + sp_digit* tmp = NULL; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (td == NULL) { + if (td == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { norm = td; -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) tmp = td + 256; -#else - tmp = &td[256]; -#endif sp_4096_mont_setup(m, &mp); sp_4096_mont_norm_128(norm, m); @@ -13731,34 +13723,34 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 32 - c; } - sp_4096_lshift_128(r, norm, (byte)y); + sp_4096_lshift_128(r, norm, y); for (; i>=0 || c>=5; ) { if (c == 0) { n = e[i--]; - y = (int)(n >> 27); + y = (byte)(n >> 27); n <<= 5; c = 27; } else if (c < 5) { - y = (int)(n >> 27); + y = (byte)(n >> 27); n = e[i--]; c = 5 - c; - y |= (int)(n >> (32 - c)); + y |= (byte)(n >> (32 - c)); n <<= c; c = 32 - c; } else { - y = (int)((n >> 27) & 0x1f); + y = (byte)((n >> 27) & 0x1f); n <<= 5; c -= 5; } @@ -13769,7 +13761,7 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, sp_4096_mont_sqr_128(r, r, m, mp); sp_4096_mont_sqr_128(r, r, m, mp); - sp_4096_lshift_128(r, r, (byte)y); + sp_4096_lshift_128(r, r, y); sp_4096_mul_d_128(tmp, norm, r[128]); r[128] = 0; o = sp_4096_add_128(r, r, tmp); @@ -13784,9 +13776,8 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) { + if (td != NULL) XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } #endif return err; @@ -13805,11 +13796,13 @@ static int sp_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[256], e[128], m[128]; + sp_digit b[256]; + sp_digit e[128]; + sp_digit m[128]; sp_digit* r = b; word32 i; @@ -13844,6 +13837,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -13856,19 +13850,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, } #endif /* WOLFSSL_HAVE_SP_DH */ -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 8]; + /* Y ordinate of point. */ sp_digit y[2 * 8]; + /* Z ordinate of point. */ sp_digit z[2 * 8]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -13938,50 +13936,1047 @@ static const sp_digit p256_b[8] = { }; #endif -static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p) +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) { - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; + sp_digit tmp_arr[8]; + sp_digit* tmp = tmp_arr; + + __asm__ __volatile__ ( + /* A[0] * B[0] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r3, r4, r6, r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[1] */ + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r8\n\t" + /* A[1] * B[0] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[1] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[0] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[1] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[0] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[1] * B[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[2] * B[2] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[3] * B[1] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[0] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[2] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[1] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[0] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[3] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[2] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[1] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[0] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[1] * B[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[2] * B[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[3] * B[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[3] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[5] * B[2] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[6] * B[1] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[0] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * B[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[4] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[3] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[2] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[1] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * B[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[4] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[3] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[2] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * B[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[5] * B[5] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[6] * B[4] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[3] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * B[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[5] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[4] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * B[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[6] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[5] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * B[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[6] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * B[7] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + /* Transfer tmp to r */ + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r8" + ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap) +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; + sp_digit tmp_arr[8]; + sp_digit* tmp = tmp_arr; + __asm__ __volatile__ ( + /* A[0] * A[0] */ + "ldr r6, [%[a], #0]\n\t" + "umull r3, r4, r6, r6\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[1] */ + "ldr r8, [%[a], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[1] */ + "ldr r6, [%[a], #4]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[2] */ + "ldr r6, [%[a], #8]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r5, r5, r9\n\t" + "adcs r3, r3, r10\n\t" + "adc r4, r4, r11\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[3] */ + "ldr r6, [%[a], #12]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * A[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[2] * A[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[4] * A[4] */ + "ldr r6, [%[a], #16]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r5, r5, r9\n\t" + "adcs r3, r3, r10\n\t" + "adc r4, r4, r11\n\t" + "str r5, [%[r], #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * A[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[3] * A[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[4] * A[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[r], #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * A[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[4] * A[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[5] * A[5] */ + "ldr r6, [%[a], #20]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[r], #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * A[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * A[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * A[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * A[6] */ + "ldr r6, [%[a], #24]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * A[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * A[7] */ + "ldr r6, [%[a], #28]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + /* Transfer tmp to r */ + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11" + ); } +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #32\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, r6, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ /* Multiply a number by Montogmery normalizer mod modulus (prime). * * r The resulting Montgomery form number. @@ -14234,7 +15229,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 32 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -14268,7 +15264,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -14304,7 +15302,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) * p Point of type sp_point_256 (result). * pm Point of type ecc_point. */ -static void sp_256_point_from_ecc_point_8(sp_point_256* p, const ecc_point* pm) +static void sp_256_point_from_ecc_point_8(sp_point_256* p, + const ecc_point* pm) { XMEMSET(p->x, 0, sizeof(p->x)); XMEMSET(p->y, 0, sizeof(p->y)); @@ -14331,17 +15330,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = 8; mp_clamp(r); #elif DIGIT_BIT < 32 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 8; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 32) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -14354,14 +15355,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 8; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 32 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -15594,7 +16597,7 @@ static void sp_256_mont_sqr_n_8(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint32_t p256_mod_minus_2[8] = { @@ -15998,7 +17001,8 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*8; @@ -16034,92 +17038,6 @@ static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "mov r8, #0\n\t" - "add r6, r6, #32\n\t" - "sub r8, r8, #1\n\t" - "\n1:\n\t" - "adds %[c], %[c], r8\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "adcs r4, r4, r5\n\t" - "str r4, [%[r]]\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c], %[c]\n\t" - "add %[a], %[a], #4\n\t" - "add %[b], %[b], #4\n\t" - "add %[r], %[r], #4\n\t" - "cmp %[a], r6\n\t" -#ifdef __GNUC__ - "bne 1b\n\t" -#else - "bne.n 1b\n\t" -#endif /* __GNUC__ */ - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r8" - ); - - return c; -} - -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r8" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -16681,101 +17599,6 @@ static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_d sp_256_mont_sub_8(y, y, t2, p256_mod); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "add r6, r6, #32\n\t" - "\n1:\n\t" - "mov r5, #0\n\t" - "subs r5, r5, %[c]\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "sbcs r4, r4, r5\n\t" - "str r4, [%[r]]\n\t" - "sbc %[c], %[c], %[c]\n\t" - "add %[a], %[a], #4\n\t" - "add %[b], %[b], #4\n\t" - "add %[r], %[r], #4\n\t" - "cmp %[a], r6\n\t" -#ifdef __GNUC__ - "bne 1b\n\t" -#else - "bne.n 1b\n\t" -#endif /* __GNUC__ */ - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6" - ); - - return c; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[a], #4]\n\t" - "ldr r6, [%[b], #0]\n\t" - "ldr r8, [%[b], #4]\n\t" - "subs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #0]\n\t" - "str r5, [%[r], #4]\n\t" - "ldr r4, [%[a], #8]\n\t" - "ldr r5, [%[a], #12]\n\t" - "ldr r6, [%[b], #8]\n\t" - "ldr r8, [%[b], #12]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #8]\n\t" - "str r5, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[a], #20]\n\t" - "ldr r6, [%[b], #16]\n\t" - "ldr r8, [%[b], #20]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #16]\n\t" - "str r5, [%[r], #20]\n\t" - "ldr r4, [%[a], #24]\n\t" - "ldr r5, [%[a], #28]\n\t" - "ldr r6, [%[b], #24]\n\t" - "ldr r8, [%[b], #28]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #24]\n\t" - "str r5, [%[r], #28]\n\t" - "sbc %[c], %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r8" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Compare two numbers to determine if they are equal. * Constant time implementation. * @@ -16999,8 +17822,8 @@ static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_8(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -17155,9 +17978,11 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Simple, smaller code size and memory size, of windowing. - * Calculate uindow of 4 bits. - * Only add points from table. + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 256 doubles. + * 76 adds. * * r Resulting point. * g Point to multiply. @@ -17170,55 +17995,55 @@ static void sp_256_get_point_16_8(sp_point_256* r, const sp_point_256* table, static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td[16]; - sp_point_256 rtd; - sp_digit tmpd[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 t[16 + 1]; + sp_digit tmp[2 * 8 * 5]; +#endif + sp_point_256* rt = NULL; #ifndef WC_NO_CACHE_RESISTANT - sp_point_256 pd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* p = NULL; +#else + sp_point_256 p[1]; #endif -#endif - sp_point_256* t; - sp_point_256* rt; -#ifndef WC_NO_CACHE_RESISTANT - sp_point_256* p; -#endif - sp_digit* tmp; +#endif /* !WC_NO_CACHE_RESISTANT */ sp_digit n; int i; - int c, y; - int err; + int c; + int y; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -#ifndef WC_NO_CACHE_RESISTANT - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 17, heap, DYNAMIC_TYPE_ECC); -#else - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 16, heap, DYNAMIC_TYPE_ECC); -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + #ifndef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), + heap, DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } + #endif + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { -#ifndef WC_NO_CACHE_RESISTANT - #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - p = t + 16; - #else - p = &pd; - #endif -#endif + rt = t + 16; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; @@ -17259,7 +18084,7 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons i = 6; n = k[i+1] << 0; c = 28; - y = n >> 28; + y = (int)(n >> 28); #ifndef WC_NO_CACHE_RESISTANT if (ct) { sp_256_get_point_16_8(rt, t, y); @@ -17306,30 +18131,39 @@ static int sp_256_ecc_mulmod_fast_8(sp_point_256* r, const sp_point_256* g, cons } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_256) * 16); - XFREE(t, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmpd, sizeof(tmpd)); - ForceZero(td, sizeof(td)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif - sp_256_point_free_8(rt, 1, heap); + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 8 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#ifndef WC_NO_CACHE_RESISTANT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (p != NULL) + #endif + { + ForceZero(p, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* !WC_NO_CACHE_RESISTANT */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_256 { - sp_digit x[8]; - sp_digit y[8]; -} sp_table_entry_256; - #ifdef FP_ECC /* Double the Montgomery form projective point p a number of times. * @@ -17338,7 +18172,8 @@ typedef struct sp_table_entry_256 { * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_8(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*8; @@ -17441,6 +18276,14 @@ static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); } +#endif /* FP_ECC */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[8]; + sp_digit y[8]; +} sp_table_entry_256; + +#ifdef FP_ECC #endif /* FP_ECC */ /* Add two Montgomery form projective points. The second point has a q value of * one. @@ -17527,6 +18370,10 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, #ifdef WOLFSSL_SP_SMALL #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 64 bits between * * a The base point. * table Place to store generated point data. @@ -17536,26 +18383,30 @@ static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, static int sp_256_gen_stripe_table_8(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_8(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -17600,9 +18451,10 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a, } } - sp_256_point_free_8(s2, 0, heap); - sp_256_point_free_8(s1, 0, heap); - sp_256_point_free_8( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -17661,8 +18513,10 @@ static void sp_256_get_entry_16_8(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 4 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -17676,17 +18530,19 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 8 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -17694,27 +18550,30 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=63; j<4; j++,x+=64) { + x = 63; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 64; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -17728,8 +18587,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=62; i>=0; i--) { y = 0; - for (j=0,x=i; j<4; j++,x+=64) { + x = i; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 64; } sp_256_proj_point_dbl_8(rt, rt, t); @@ -17755,13 +18616,12 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(rt, 0, heap); return err; } @@ -17771,16 +18631,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[8]; + /* Y ordinate of point that table was generated from. */ sp_digit y[8]; + /* Precomputation table for point. */ sp_table_entry_256 table[16]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -17788,9 +18657,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -17899,6 +18774,10 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ #else #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 32 bits between * * a The base point. * table Place to store generated point data. @@ -17908,26 +18787,30 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ static int sp_256_gen_stripe_table_8(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_8(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -17972,9 +18855,10 @@ static int sp_256_gen_stripe_table_8(const sp_point_256* a, } } - sp_256_point_free_8(s2, 0, heap); - sp_256_point_free_8(s1, 0, heap); - sp_256_point_free_8( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -18033,8 +18917,10 @@ static void sp_256_get_entry_256_8(sp_point_256* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -18048,17 +18934,19 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 8 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 8 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -18066,27 +18954,30 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_8(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=31; j<8; j++,x+=32) { + x = 31; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 32; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -18100,8 +18991,10 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=30; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=32) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 32; } sp_256_proj_point_dbl_8(rt, rt, t); @@ -18127,13 +19020,12 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(rt, 0, heap); return err; } @@ -18143,16 +19035,25 @@ static int sp_256_ecc_mulmod_stripe_8(sp_point_256* r, const sp_point_256* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[8]; + /* Y ordinate of point that table was generated from. */ sp_digit y[8]; + /* Precomputation table for point. */ sp_table_entry_256 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -18160,9 +19061,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -18279,28 +19186,31 @@ static int sp_256_ecc_mulmod_8(sp_point_256* r, const sp_point_256* g, const sp_ * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 8, km); sp_256_point_from_ecc_point_8(point, gm); @@ -18311,17 +19221,101 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_8(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[8 + 8 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (8 + 8 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_8(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 8; + + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + sp_256_point_from_ecc_point_8(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_8(point, point, addP, tmp); + + if (map) { + sp_256_map_8(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 64 between points. + */ static const sp_table_entry_256 p256_table[16] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -18406,6 +19400,11 @@ static const sp_table_entry_256 p256_table[16] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -18421,6 +19420,10 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 32 between points. + */ static const sp_table_entry_256 p256_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -19705,6 +20708,11 @@ static const sp_table_entry_256 p256_table[256] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^32, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -19730,28 +20738,30 @@ static int sp_256_ecc_mulmod_base_8(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 8, km); @@ -19761,12 +20771,90 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_8(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[8 + 8 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (8 + 8 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_8(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 8; + + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_8(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_256_proj_point_add_8(point, point, addP, tmp); + + if (map) { + sp_256_map_8(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -19784,7 +20872,7 @@ static int sp_256_iszero_8(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -19833,7 +20921,8 @@ SP_NOINLINE static void sp_256_add_one_8(sp_digit* a) */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -19896,41 +20985,46 @@ static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[8]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_256_point_new_8(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_8(rng, k); } if (err == MP_OKAY) { @@ -19955,15 +21049,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_8(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_8(infinity, 1, heap); -#endif - sp_256_point_free_8(point, 1, heap); return err; } @@ -19977,7 +21070,10 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_256_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 256 / 8 - 1; a[j] = 0; @@ -20018,33 +21114,35 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[8]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[8]; +#endif int err = MP_OKAY; if (*outLen < 32U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -20057,527 +21155,18 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(point, 0, heap); return err; } #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Multiply a and b into r. (r = a * b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit tmp_arr[8]; - sp_digit* tmp = tmp_arr; - - __asm__ __volatile__ ( - /* A[0] * B[0] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r3, r4, r6, r8\n\t" - "mov r5, #0\n\t" - "str r3, [%[tmp], #0]\n\t" - "mov r3, #0\n\t" - /* A[0] * B[1] */ - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adc r5, r5, r8\n\t" - /* A[1] * B[0] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[tmp], #4]\n\t" - "mov r4, #0\n\t" - /* A[0] * B[2] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[1] * B[1] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[2] * B[0] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "str r5, [%[tmp], #8]\n\t" - "mov r5, #0\n\t" - /* A[0] * B[3] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[1] * B[2] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[2] * B[1] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[3] * B[0] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "str r3, [%[tmp], #12]\n\t" - "mov r3, #0\n\t" - /* A[0] * B[4] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[1] * B[3] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[2] * B[2] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[3] * B[1] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[4] * B[0] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[tmp], #16]\n\t" - "mov r4, #0\n\t" - /* A[0] * B[5] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[1] * B[4] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[2] * B[3] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[3] * B[2] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[4] * B[1] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[5] * B[0] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "str r5, [%[tmp], #20]\n\t" - "mov r5, #0\n\t" - /* A[0] * B[6] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[1] * B[5] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[2] * B[4] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[3] * B[3] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[4] * B[2] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[5] * B[1] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[6] * B[0] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "str r3, [%[tmp], #24]\n\t" - "mov r3, #0\n\t" - /* A[0] * B[7] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[1] * B[6] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[2] * B[5] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[3] * B[4] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[4] * B[3] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[5] * B[2] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[6] * B[1] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[7] * B[0] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #0]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[tmp], #28]\n\t" - "mov r4, #0\n\t" - /* A[1] * B[7] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[2] * B[6] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[3] * B[5] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[4] * B[4] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[5] * B[3] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[6] * B[2] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[7] * B[1] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "str r5, [%[r], #32]\n\t" - "mov r5, #0\n\t" - /* A[2] * B[7] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[3] * B[6] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[4] * B[5] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[5] * B[4] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[6] * B[3] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[7] * B[2] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "str r3, [%[r], #36]\n\t" - "mov r3, #0\n\t" - /* A[3] * B[7] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[4] * B[6] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[5] * B[5] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[6] * B[4] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[7] * B[3] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[r], #40]\n\t" - "mov r4, #0\n\t" - /* A[4] * B[7] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[5] * B[6] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[6] * B[5] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[7] * B[4] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "str r5, [%[r], #44]\n\t" - "mov r5, #0\n\t" - /* A[5] * B[7] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[6] * B[6] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[7] * B[5] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "str r3, [%[r], #48]\n\t" - "mov r3, #0\n\t" - /* A[6] * B[7] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - /* A[7] * B[6] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[r], #52]\n\t" - "mov r4, #0\n\t" - /* A[7] * B[7] */ - "ldr r6, [%[a], #28]\n\t" - "ldr r8, [%[b], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adc r3, r3, r8\n\t" - "str r5, [%[r], #56]\n\t" - "str r3, [%[r], #60]\n\t" - /* Transfer tmp to r */ - "ldr r3, [%[tmp], #0]\n\t" - "ldr r4, [%[tmp], #4]\n\t" - "ldr r5, [%[tmp], #8]\n\t" - "ldr r6, [%[tmp], #12]\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [%[tmp], #16]\n\t" - "ldr r4, [%[tmp], #20]\n\t" - "ldr r5, [%[tmp], #24]\n\t" - "ldr r6, [%[tmp], #28]\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - : - : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) - : "memory", "r3", "r4", "r5", "r6", "r8" - ); -} - #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) #ifdef WOLFSSL_SP_SMALL @@ -20837,357 +21426,6 @@ static WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) -{ - sp_digit tmp_arr[8]; - sp_digit* tmp = tmp_arr; - __asm__ __volatile__ ( - /* A[0] * A[0] */ - "ldr r6, [%[a], #0]\n\t" - "umull r3, r4, r6, r6\n\t" - "mov r5, #0\n\t" - "str r3, [%[tmp], #0]\n\t" - "mov r3, #0\n\t" - /* A[0] * A[1] */ - "ldr r8, [%[a], #4]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adc r5, r5, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[tmp], #4]\n\t" - "mov r4, #0\n\t" - /* A[0] * A[2] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adc r3, r3, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[1] * A[1] */ - "ldr r6, [%[a], #4]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "str r5, [%[tmp], #8]\n\t" - "mov r5, #0\n\t" - /* A[0] * A[3] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[1] * A[2] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[a], #8]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r3, r3, r9\n\t" - "adcs r4, r4, r10\n\t" - "adc r5, r5, r11\n\t" - "str r3, [%[tmp], #12]\n\t" - "mov r3, #0\n\t" - /* A[0] * A[4] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[1] * A[3] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[2] * A[2] */ - "ldr r6, [%[a], #8]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r4, r4, r9\n\t" - "adcs r5, r5, r10\n\t" - "adc r3, r3, r11\n\t" - "str r4, [%[tmp], #16]\n\t" - "mov r4, #0\n\t" - /* A[0] * A[5] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[1] * A[4] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[2] * A[3] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[a], #12]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r5, r5, r9\n\t" - "adcs r3, r3, r10\n\t" - "adc r4, r4, r11\n\t" - "str r5, [%[tmp], #20]\n\t" - "mov r5, #0\n\t" - /* A[0] * A[6] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[1] * A[5] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[2] * A[4] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[3] * A[3] */ - "ldr r6, [%[a], #12]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r3, r3, r9\n\t" - "adcs r4, r4, r10\n\t" - "adc r5, r5, r11\n\t" - "str r3, [%[tmp], #24]\n\t" - "mov r3, #0\n\t" - /* A[0] * A[7] */ - "ldr r6, [%[a], #0]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[1] * A[6] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[2] * A[5] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[3] * A[4] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[a], #16]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r4, r4, r9\n\t" - "adcs r5, r5, r10\n\t" - "adc r3, r3, r11\n\t" - "str r4, [%[tmp], #28]\n\t" - "mov r4, #0\n\t" - /* A[1] * A[7] */ - "ldr r6, [%[a], #4]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[2] * A[6] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[3] * A[5] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[4] * A[4] */ - "ldr r6, [%[a], #16]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r5, r5, r9\n\t" - "adcs r3, r3, r10\n\t" - "adc r4, r4, r11\n\t" - "str r5, [%[r], #32]\n\t" - "mov r5, #0\n\t" - /* A[2] * A[7] */ - "ldr r6, [%[a], #8]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[3] * A[6] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[4] * A[5] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[a], #20]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r3, r3, r9\n\t" - "adcs r4, r4, r10\n\t" - "adc r5, r5, r11\n\t" - "str r3, [%[r], #36]\n\t" - "mov r3, #0\n\t" - /* A[3] * A[7] */ - "ldr r6, [%[a], #12]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r9, r10, r6, r8\n\t" - "mov r11, #0\n\t" - /* A[4] * A[6] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r9, r9, r6\n\t" - "adcs r10, r10, r8\n\t" - "adc r11, r11, #0\n\t" - /* A[5] * A[5] */ - "ldr r6, [%[a], #20]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "adds r9, r9, r9\n\t" - "adcs r10, r10, r10\n\t" - "adc r11, r11, r11\n\t" - "adds r4, r4, r9\n\t" - "adcs r5, r5, r10\n\t" - "adc r3, r3, r11\n\t" - "str r4, [%[r], #40]\n\t" - "mov r4, #0\n\t" - /* A[4] * A[7] */ - "ldr r6, [%[a], #16]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - /* A[5] * A[6] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[a], #24]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "adds r5, r5, r6\n\t" - "adcs r3, r3, r8\n\t" - "adc r4, r4, #0\n\t" - "str r5, [%[r], #44]\n\t" - "mov r5, #0\n\t" - /* A[5] * A[7] */ - "ldr r6, [%[a], #20]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - /* A[6] * A[6] */ - "ldr r6, [%[a], #24]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, #0\n\t" - "str r3, [%[r], #48]\n\t" - "mov r3, #0\n\t" - /* A[6] * A[7] */ - "ldr r6, [%[a], #24]\n\t" - "ldr r8, [%[a], #28]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "adc r3, r3, #0\n\t" - "str r4, [%[r], #52]\n\t" - "mov r4, #0\n\t" - /* A[7] * A[7] */ - "ldr r6, [%[a], #28]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r5, r5, r6\n\t" - "adc r3, r3, r8\n\t" - "str r5, [%[r], #56]\n\t" - "str r3, [%[r], #60]\n\t" - /* Transfer tmp to r */ - "ldr r3, [%[tmp], #0]\n\t" - "ldr r4, [%[tmp], #4]\n\t" - "ldr r5, [%[tmp], #8]\n\t" - "ldr r6, [%[tmp], #12]\n\t" - "str r3, [%[r], #0]\n\t" - "str r4, [%[r], #4]\n\t" - "str r5, [%[r], #8]\n\t" - "str r6, [%[r], #12]\n\t" - "ldr r3, [%[tmp], #16]\n\t" - "ldr r4, [%[tmp], #20]\n\t" - "ldr r5, [%[tmp], #24]\n\t" - "ldr r6, [%[tmp], #28]\n\t" - "str r3, [%[r], #16]\n\t" - "str r4, [%[r], #20]\n\t" - "str r5, [%[r], #24]\n\t" - "str r6, [%[r], #28]\n\t" - : - : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) - : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11" - ); -} - #ifdef WOLFSSL_SP_SMALL /* Order-2 for the P256 curve. */ static const uint32_t p256_order_minus_2[8] = { @@ -21196,7 +21434,7 @@ static const uint32_t p256_order_minus_2[8] = { }; #else /* The low half of the order-2 of the P256 curve. */ -static const uint32_t p256_order_low[4] = { +static const sp_int_digit p256_order_low[4] = { 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU }; #endif /* WOLFSSL_SP_SMALL */ @@ -21342,7 +21580,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ for (i=127; i>=112; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21352,7 +21590,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ for (i=107; i>=64; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21362,7 +21600,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ for (i=59; i>=32; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21372,7 +21610,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ for (i=27; i>=0; i--) { sp_256_mont_sqr_order_8(t2, t2); - if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_256_mont_mul_order_8(t2, t2, a); } } @@ -21383,12 +21621,63 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(k); + + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -21423,8 +21712,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -21442,13 +21731,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 8, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_8(rng, ctx->k); @@ -21476,6 +21762,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_8(ctx->r, p256_order); sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_8(ctx->r); + + sp_256_from_mp(ctx->x, 8, priv); + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); ctx->state = 4; break; } @@ -21532,6 +21821,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -21564,72 +21856,55 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*8]; - sp_digit xd[2*8]; - sp_digit kd[2*8]; - sp_digit rd[2*8]; - sp_digit td[3 * 2*8]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 8]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_256_point_new_8(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 8; - x = d + 2 * 8; - k = d + 4 * 8; - r = d + 6 * 8; - tmp = d + 8 * 8; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 8; + k = e + 4 * 8; + r = e + 6 * 8; + tmp = e + 8 * 8; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 8, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 8, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_8(rng, k); @@ -21639,7 +21914,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -21650,38 +21925,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_8(r); - /* Conv k to Montgomery form (mod order) */ - sp_256_mul_8(k, k, p256_norm_order); - err = sp_256_mod_8(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_8(k); - /* kInv = 1/k mod order */ - sp_256_mont_inv_order_8(kInv, k, tmp); - sp_256_norm_8(kInv); + sp_256_from_mp(x, 8, priv); + sp_256_from_bin(e, 8, hash, (int)hashLen); - /* s = r * x + e */ - sp_256_mul_8(x, x, r); - err = sp_256_mod_8(x, x, p256_order); + err = sp_256_calc_s_8(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_8(x); - carry = sp_256_add_8(s, e, x); - sp_256_cond_sub_8(s, s, p256_order, 0 - carry); - sp_256_norm_8(s); - c = sp_256_cmp_8(s, p256_order); - sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_8(s); - /* s = s * k^-1 mod order */ - sp_256_mont_mul_order_8(s, s, kInv); - sp_256_norm_8(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_8(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -21695,20 +21951,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_8(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -21999,6 +22259,96 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_8(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ + + sp_256_proj_point_add_8(p1, p1, p2, tmp); + if (sp_256_iszero_8(p1->z)) { + if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { + sp_256_proj_point_dbl_8(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_256_mod_inv_8(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_256_mul_8(s, s, p256_norm_order); + } + err = sp_256_mod_8(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + +#else + { + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_8(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -22017,8 +22367,7 @@ static int sp_256_mod_inv_8(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -22037,8 +22386,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -22053,7 +22403,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); sp_256_from_mp(ctx->s, 8, sm); sp_256_from_mp(ctx->p2.x, 8, pX); sp_256_from_mp(ctx->p2.y, 8, pY); @@ -22111,57 +22461,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_8(ctx->p1.z)) { - if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<8; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->u2, 8, rm); carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -22169,22 +22495,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_8(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -22192,130 +22519,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*8]; - sp_digit u2d[2*8]; - sp_digit sd[2*8]; - sp_digit tmpd[2*8 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 8]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_8(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 8; - u2 = d + 2 * 8; - s = d + 4 * 8; - tmp = d + 6 * 8; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 8; + s = u1 + 4 * 8; + tmp = u1 + 6 * 8; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 8, hash, (int)hashLen); - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); sp_256_from_mp(s, 8, sm); sp_256_from_mp(p2->x, 8, pX); sp_256_from_mp(p2->y, 8, pY); sp_256_from_mp(p2->z, 8, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_256_mod_inv_8(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_256_mul_8(s, s, p256_norm_order); - } - err = sp_256_mod_8(s, s, p256_order); + err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_8(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_256_mont_inv_order_8(s, s, tmp); - sp_256_mont_mul_order_8(u1, u1, s); - sp_256_mont_mul_order_8(u2, u2, s); - } - -#else - { - sp_256_mont_mul_order_8(u1, u1, s); - sp_256_mont_mul_order_8(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_256_ecc_mulmod_base_8(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_8(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_8(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_256_proj_point_add_8(p1, p1, p2, tmp); - if (sp_256_iszero_8(p1->z)) { - if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { - sp_256_proj_point_dbl_8(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); } @@ -22326,7 +22586,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 8, r); + sp_256_from_mp(u2, 8, rm); carry = sp_256_add_8(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -22334,26 +22594,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_8(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_8(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p1, 0, heap); - sp_256_point_free_8(p2, 0, heap); return err; } @@ -22367,34 +22627,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_8(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*8]; - sp_digit t2d[2*8]; + sp_digit t1[8 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 8; - t2 = d + 2 * 8; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 8; sp_256_sqr_8(t1, point->y); (void)sp_256_mod_8(t1, t1, p256_mod); @@ -22414,10 +22666,9 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -22430,16 +22681,23 @@ static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_8(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 8, pX); sp_256_from_mp(pub->y, 8, pY); @@ -22448,7 +22706,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_8(pub, NULL); } - sp_256_point_free_8(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -22464,47 +22725,48 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[8]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; - sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_256_point_new_8(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_8(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_256* pub = NULL; +#else + sp_digit priv[8]; + sp_point_256 pub[2]; #endif + sp_point_256* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 8, pX); sp_256_from_mp(pub->y, 8, pY); sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); @@ -22518,12 +22780,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || - sp_256_cmp_8(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_8(pub->x, p256_mod) >= 0) || + (sp_256_cmp_8(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -22535,12 +22796,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_8(p->x) == 0) || - (sp_256_iszero_8(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_8(p->x) == 0) || + (sp_256_iszero_8(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -22548,22 +22807,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_256_ecc_mulmod_base_8(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_8(p->x, pub->x) != 0 || - sp_256_cmp_8(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_8(p->x, pub->x) != 0) || + (sp_256_cmp_8(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_8(p, 0, heap); - sp_256_point_free_8(pub, 0, heap); return err; } @@ -22587,33 +22844,35 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; - err = sp_256_point_new_8(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_8(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 8, pX); sp_256_from_mp(p->y, 8, pY); sp_256_from_mp(p->z, 8, pZ); @@ -22634,13 +22893,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(q, 0, NULL); - sp_256_point_free_8(p, 0, NULL); return err; } @@ -22659,25 +22917,28 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_8(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -22698,12 +22959,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, NULL); return err; } @@ -22718,32 +22979,36 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 8 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 8 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_8(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 8, pX); sp_256_from_mp(p->y, 8, pY); sp_256_from_mp(p->z, 8, pZ); - sp_256_map_8(p, p, tmp); + sp_256_map_8(p, p, tmp); } if (err == MP_OKAY) { @@ -22756,12 +23021,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_8(p, 0, NULL); return err; } @@ -22774,31 +23039,23 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_8(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 8]; - sp_digit t2d[2 * 8]; + sp_digit t1[4 * 8]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 8; - t2 = d + 2 * 8; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 8; { /* t2 = y ^ 0x2 */ @@ -22833,10 +23090,9 @@ static int sp_256_mont_sqrt_8(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -22852,31 +23108,22 @@ static int sp_256_mont_sqrt_8(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 8]; - sp_digit yd[2 * 8]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 8]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 8; - y = d + 2 * 8; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 8; sp_256_from_mp(x, 8, xm); err = sp_256_mod_mul_norm_8(x, x, p256_mod); @@ -22909,10 +23156,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -22923,9 +23169,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 12]; + /* Y ordinate of point. */ sp_digit y[2 * 12]; + /* Z ordinate of point. */ sp_digit z[2 * 12]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; @@ -22995,336 +23245,6 @@ static const sp_digit p384_b[12] = { }; #endif -static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - -/* Multiply a number by Montogmery normalizer mod modulus (prime). - * - * r The resulting Montgomery form number. - * a The number to convert. - * m The modulus (prime). - * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. - */ -static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* t; -#else - int64_t t[12]; -#endif - int64_t o; - int err = MP_OKAY; - - (void)m; - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); - if (t == NULL) { - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ - t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11]; - /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ - t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11]; - /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ - t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11]; - /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ - t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11]; - /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ - t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11]; - /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ - t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11]; - /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ - t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11]; - /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ - t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11]; - /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ - t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8]; - /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ - t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9]; - /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ - t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10]; - /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ - t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11]; - - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - o = t[11] >> 32; t[11] &= 0xffffffff; - t[0] += o; - t[1] -= o; - t[3] += o; - t[4] += o; - t[1] += t[0] >> 32; t[0] &= 0xffffffff; - t[2] += t[1] >> 32; t[1] &= 0xffffffff; - t[3] += t[2] >> 32; t[2] &= 0xffffffff; - t[4] += t[3] >> 32; t[3] &= 0xffffffff; - t[5] += t[4] >> 32; t[4] &= 0xffffffff; - t[6] += t[5] >> 32; t[5] &= 0xffffffff; - t[7] += t[6] >> 32; t[6] &= 0xffffffff; - t[8] += t[7] >> 32; t[7] &= 0xffffffff; - t[9] += t[8] >> 32; t[8] &= 0xffffffff; - t[10] += t[9] >> 32; t[9] &= 0xffffffff; - t[11] += t[10] >> 32; t[10] &= 0xffffffff; - - r[0] = t[0]; - r[1] = t[1]; - r[2] = t[2]; - r[3] = t[3]; - r[4] = t[4]; - r[5] = t[5]; - r[6] = t[6]; - r[7] = t[7]; - r[8] = t[8]; - r[9] = t[9]; - r[10] = t[10]; - r[11] = t[11]; - } - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) - XFREE(t, NULL, DYNAMIC_TYPE_ECC); -#endif - - return err; -} - -/* Convert an mp_int to an array of sp_digit. - * - * r A single precision integer. - * size Maximum number of bytes to convert - * a A multi-precision integer. - */ -static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) -{ -#if DIGIT_BIT == 32 - int j; - - XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); - - for (j = a->used; j < size; j++) { - r[j] = 0; - } -#elif DIGIT_BIT > 32 - int i, j = 0; - word32 s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i] << s); - r[j] &= 0xffffffff; - s = 32U - s; - if (j + 1 >= size) { - break; - } - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - while ((s + 32U) <= (word32)DIGIT_BIT) { - s += 32U; - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - if (s < (word32)DIGIT_BIT) { - /* lint allow cast of mismatch word32 and mp_digit */ - r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ - } - else { - r[++j] = 0L; - } - } - s = (word32)DIGIT_BIT - s; - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#else - int i, j = 0, s = 0; - - r[0] = 0; - for (i = 0; i < a->used && j < size; i++) { - r[j] |= ((sp_digit)a->dp[i]) << s; - if (s + DIGIT_BIT >= 32) { - r[j] &= 0xffffffff; - if (j + 1 >= size) { - break; - } - s = 32 - s; - if (s == DIGIT_BIT) { - r[++j] = 0; - s = 0; - } - else { - r[++j] = a->dp[i] >> s; - s = DIGIT_BIT - s; - } - } - else { - s += DIGIT_BIT; - } - } - - for (j++; j < size; j++) { - r[j] = 0; - } -#endif -} - -/* Convert a point of type ecc_point to type sp_point_384. - * - * p Point of type sp_point_384 (result). - * pm Point of type ecc_point. - */ -static void sp_384_point_from_ecc_point_12(sp_point_384* p, const ecc_point* pm) -{ - XMEMSET(p->x, 0, sizeof(p->x)); - XMEMSET(p->y, 0, sizeof(p->y)); - XMEMSET(p->z, 0, sizeof(p->z)); - sp_384_from_mp(p->x, 12, pm->x); - sp_384_from_mp(p->y, 12, pm->y); - sp_384_from_mp(p->z, 12, pm->z); - p->infinity = 0; -} - -/* Convert an array of sp_digit to an mp_int. - * - * a A single precision integer. - * r A multi-precision integer. - */ -static int sp_384_to_mp(const sp_digit* a, mp_int* r) -{ - int err; - - err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); - if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ -#if DIGIT_BIT == 32 - XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); - r->used = 12; - mp_clamp(r); -#elif DIGIT_BIT < 32 - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 12; i++) { - r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; - s = DIGIT_BIT - s; - r->dp[++j] = (mp_digit)(a[i] >> s); - while (s + DIGIT_BIT <= 32) { - s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; - if (s == SP_WORD_SIZE) { - r->dp[j] = 0; - } - else { - r->dp[j] = (mp_digit)(a[i] >> s); - } - } - s = 32 - s; - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#else - int i, j = 0, s = 0; - - r->dp[0] = 0; - for (i = 0; i < 12; i++) { - r->dp[j] |= ((mp_digit)a[i]) << s; - if (s + 32 >= DIGIT_BIT) { - #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; - #endif - s = DIGIT_BIT - s; - r->dp[++j] = a[i] >> s; - s = 32 - s; - } - else { - s += 32; - } - } - r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; - mp_clamp(r); -#endif - } - - return err; -} - -/* Convert a point of type sp_point_384 to type ecc_point. - * - * p Point of type sp_point_384. - * pm Point of type ecc_point (result). - * returns MEMORY_E when allocation of memory in ecc_point fails otherwise - * MP_OKAY. - */ -static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) -{ - int err; - - err = sp_384_to_mp(p->x, pm->x); - if (err == MP_OKAY) { - err = sp_384_to_mp(p->y, pm->y); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(p->z, pm->z); - } - - return err; -} - /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -23410,6 +23330,631 @@ SP_NOINLINE static void sp_384_mul_12(sp_digit* r, const sp_digit* a, XMEMCPY(r, tmp_arr, sizeof(tmp_arr)); } +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #96\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" +#ifdef __GNUC__ + "beq 4f\n\t" +#else + "beq.n 4f\n\t" +#endif /* __GNUC__ */ + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ +#ifdef __GNUC__ + "bal 5f\n\t" +#else + "bal.n 5f\n\t" +#endif /* __GNUC__ */ + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #48\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "beq 3f\n\t" +#else + "beq.n 3f\n\t" +#endif /* __GNUC__ */ + "cmp %[a], r2\n\t" +#ifdef __GNUC__ + "bgt 3f\n\t" +#else + "bgt.n 3f\n\t" +#endif /* __GNUC__ */ + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" +#ifdef __GNUC__ + "ble 2b\n\t" +#else + "ble.n 2b\n\t" +#endif /* __GNUC__ */ + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #88\n\t" + "cmp r8, r6\n\t" +#ifdef __GNUC__ + "ble 1b\n\t" +#else + "ble.n 1b\n\t" +#endif /* __GNUC__ */ + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #92\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" +#ifdef __GNUC__ + "bge 4b\n\t" +#else + "bge.n 4b\n\t" +#endif /* __GNUC__ */ + "mov r6, #96\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #48\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, r6, #48\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r8, [%[b], #44]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; +#else + int64_t t[12]; +#endif + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + (int64_t)a[0] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[8] + (int64_t)a[10] + (int64_t)a[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[9] + (int64_t)a[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + (int64_t)a[0] - (int64_t)a[2] + (int64_t)a[3] + (int64_t)a[8] + (int64_t)a[9] - (int64_t)a[10] - (int64_t)a[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + (int64_t)a[0] + (int64_t)a[1] - (int64_t)a[3] + (int64_t)a[4] + (int64_t)a[8] + 2 * (int64_t)a[9] + (int64_t)a[10] - 2 * (int64_t)a[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + (int64_t)a[1] + (int64_t)a[2] - (int64_t)a[4] + (int64_t)a[5] + (int64_t)a[9] + 2 * (int64_t)a[10] + (int64_t)a[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + (int64_t)a[2] + (int64_t)a[3] - (int64_t)a[5] + (int64_t)a[6] + (int64_t)a[10] + 2 * (int64_t)a[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + (int64_t)a[3] + (int64_t)a[4] - (int64_t)a[6] + (int64_t)a[7] + (int64_t)a[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + (int64_t)a[4] + (int64_t)a[5] - (int64_t)a[7] + (int64_t)a[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + (int64_t)a[5] + (int64_t)a[6] - (int64_t)a[8] + (int64_t)a[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + (int64_t)a[6] + (int64_t)a[7] - (int64_t)a[9] + (int64_t)a[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + (int64_t)a[7] + (int64_t)a[8] - (int64_t)a[10] + (int64_t)a[11]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + r[8] = t[8]; + r[9] = t[9]; + r[10] = t[10]; + r[11] = t[11]; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_12(sp_point_384* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_384_from_mp(p->x, 12, pm->x); + sp_384_from_mp(p->y, 12, pm->y); + sp_384_from_mp(p->z, 12, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); + r->used = 12; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -23564,137 +24109,13 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_12(r, a, b); sp_384_mont_reduce_12(r, m, mp); } -/* Square a and put result in r. (r = a * a) - * - * r A single precision integer. - * a A single precision integer. - */ -SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) -{ - __asm__ __volatile__ ( - "mov r3, #0\n\t" - "mov r4, #0\n\t" - "mov r5, #0\n\t" - "mov r9, r3\n\t" - "mov r12, %[r]\n\t" - "mov r6, #96\n\t" - "neg r6, r6\n\t" - "add sp, sp, r6\n\t" - "mov r11, sp\n\t" - "mov r10, %[a]\n\t" - "\n1:\n\t" - "mov %[r], #0\n\t" - "mov r6, #44\n\t" - "mov %[a], r9\n\t" - "subs %[a], %[a], r6\n\t" - "sbc r6, r6, r6\n\t" - "mvn r6, r6\n\t" - "and %[a], %[a], r6\n\t" - "mov r2, r9\n\t" - "sub r2, r2, %[a]\n\t" - "add %[a], %[a], r10\n\t" - "add r2, r2, r10\n\t" - "\n2:\n\t" - "cmp r2, %[a]\n\t" -#ifdef __GNUC__ - "beq 4f\n\t" -#else - "beq.n 4f\n\t" -#endif /* __GNUC__ */ - /* Multiply * 2: Start */ - "ldr r6, [%[a]]\n\t" - "ldr r8, [r2]\n\t" - "umull r6, r8, r6, r8\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, %[r]\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, %[r]\n\t" - /* Multiply * 2: Done */ -#ifdef __GNUC__ - "bal 5f\n\t" -#else - "bal.n 5f\n\t" -#endif /* __GNUC__ */ - "\n4:\n\t" - /* Square: Start */ - "ldr r6, [%[a]]\n\t" - "umull r6, r8, r6, r6\n\t" - "adds r3, r3, r6\n\t" - "adcs r4, r4, r8\n\t" - "adc r5, r5, %[r]\n\t" - /* Square: Done */ - "\n5:\n\t" - "add %[a], %[a], #4\n\t" - "sub r2, r2, #4\n\t" - "mov r6, #48\n\t" - "add r6, r6, r10\n\t" - "cmp %[a], r6\n\t" -#ifdef __GNUC__ - "beq 3f\n\t" -#else - "beq.n 3f\n\t" -#endif /* __GNUC__ */ - "cmp %[a], r2\n\t" -#ifdef __GNUC__ - "bgt 3f\n\t" -#else - "bgt.n 3f\n\t" -#endif /* __GNUC__ */ - "mov r8, r9\n\t" - "add r8, r8, r10\n\t" - "cmp %[a], r8\n\t" -#ifdef __GNUC__ - "ble 2b\n\t" -#else - "ble.n 2b\n\t" -#endif /* __GNUC__ */ - "\n3:\n\t" - "mov %[r], r11\n\t" - "mov r8, r9\n\t" - "str r3, [%[r], r8]\n\t" - "mov r3, r4\n\t" - "mov r4, r5\n\t" - "mov r5, #0\n\t" - "add r8, r8, #4\n\t" - "mov r9, r8\n\t" - "mov r6, #88\n\t" - "cmp r8, r6\n\t" -#ifdef __GNUC__ - "ble 1b\n\t" -#else - "ble.n 1b\n\t" -#endif /* __GNUC__ */ - "mov %[a], r10\n\t" - "str r3, [%[r], r8]\n\t" - "mov %[r], r12\n\t" - "mov %[a], r11\n\t" - "mov r3, #92\n\t" - "\n4:\n\t" - "ldr r6, [%[a], r3]\n\t" - "str r6, [%[r], r3]\n\t" - "subs r3, r3, #4\n\t" -#ifdef __GNUC__ - "bge 4b\n\t" -#else - "bge.n 4b\n\t" -#endif /* __GNUC__ */ - "mov r6, #96\n\t" - "add sp, sp, r6\n\t" - : - : [r] "r" (r), [a] "r" (a) - : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" - ); -} - /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -23702,8 +24123,8 @@ SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_12(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_12(r, a); sp_384_mont_reduce_12(r, m, mp); @@ -23727,7 +24148,7 @@ static void sp_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint32_t p384_mod_minus_2[12] = { @@ -23880,7 +24301,8 @@ SP_NOINLINE static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b) * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*12; @@ -23916,102 +24338,6 @@ static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -#ifdef WOLFSSL_SP_SMALL -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "mov r8, #0\n\t" - "add r6, r6, #48\n\t" - "sub r8, r8, #1\n\t" - "\n1:\n\t" - "adds %[c], %[c], r8\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "adcs r4, r4, r5\n\t" - "str r4, [%[r]]\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c], %[c]\n\t" - "add %[a], %[a], #4\n\t" - "add %[b], %[b], #4\n\t" - "add %[r], %[r], #4\n\t" - "cmp %[a], r6\n\t" -#ifdef __GNUC__ - "bne 1b\n\t" -#else - "bne.n 1b\n\t" -#endif /* __GNUC__ */ - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r8" - ); - - return c; -} - -#else -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adds r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "ldm %[a]!, {r4, r5}\n\t" - "ldm %[b]!, {r6, r8}\n\t" - "adcs r4, r4, r6\n\t" - "adcs r5, r5, r8\n\t" - "stm %[r]!, {r4, r5}\n\t" - "mov %[c], #0\n\t" - "adc %[c], %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r8" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -24058,117 +24384,6 @@ SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_384_cond_sub_12(r, r, m, 0 - o); } -#ifdef WOLFSSL_SP_SMALL -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "mov r6, %[a]\n\t" - "add r6, r6, #48\n\t" - "\n1:\n\t" - "mov r5, #0\n\t" - "subs r5, r5, %[c]\n\t" - "ldr r4, [%[a]]\n\t" - "ldr r5, [%[b]]\n\t" - "sbcs r4, r4, r5\n\t" - "str r4, [%[r]]\n\t" - "sbc %[c], %[c], %[c]\n\t" - "add %[a], %[a], #4\n\t" - "add %[b], %[b], #4\n\t" - "add %[r], %[r], #4\n\t" - "cmp %[a], r6\n\t" -#ifdef __GNUC__ - "bne 1b\n\t" -#else - "bne.n 1b\n\t" -#endif /* __GNUC__ */ - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6" - ); - - return c; -} - -#else -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, - const sp_digit* b) -{ - sp_digit c = 0; - - __asm__ __volatile__ ( - "ldr r4, [%[a], #0]\n\t" - "ldr r5, [%[a], #4]\n\t" - "ldr r6, [%[b], #0]\n\t" - "ldr r8, [%[b], #4]\n\t" - "subs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #0]\n\t" - "str r5, [%[r], #4]\n\t" - "ldr r4, [%[a], #8]\n\t" - "ldr r5, [%[a], #12]\n\t" - "ldr r6, [%[b], #8]\n\t" - "ldr r8, [%[b], #12]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #8]\n\t" - "str r5, [%[r], #12]\n\t" - "ldr r4, [%[a], #16]\n\t" - "ldr r5, [%[a], #20]\n\t" - "ldr r6, [%[b], #16]\n\t" - "ldr r8, [%[b], #20]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #16]\n\t" - "str r5, [%[r], #20]\n\t" - "ldr r4, [%[a], #24]\n\t" - "ldr r5, [%[a], #28]\n\t" - "ldr r6, [%[b], #24]\n\t" - "ldr r8, [%[b], #28]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #24]\n\t" - "str r5, [%[r], #28]\n\t" - "ldr r4, [%[a], #32]\n\t" - "ldr r5, [%[a], #36]\n\t" - "ldr r6, [%[b], #32]\n\t" - "ldr r8, [%[b], #36]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #32]\n\t" - "str r5, [%[r], #36]\n\t" - "ldr r4, [%[a], #40]\n\t" - "ldr r5, [%[a], #44]\n\t" - "ldr r6, [%[b], #40]\n\t" - "ldr r8, [%[b], #44]\n\t" - "sbcs r4, r4, r6\n\t" - "sbcs r5, r5, r8\n\t" - "str r4, [%[r], #40]\n\t" - "str r5, [%[r], #44]\n\t" - "sbc %[c], %[c], %[c]\n\t" - : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) - : - : "memory", "r4", "r5", "r6", "r8" - ); - - return c; -} - -#endif /* WOLFSSL_SP_SMALL */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -24716,8 +24931,8 @@ static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_12(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -24896,9 +25111,11 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Simple, smaller code size and memory size, of windowing. - * Calculate uindow of 4 bits. - * Only add points from table. + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 384 doubles. + * 108 adds. * * r Resulting point. * g Point to multiply. @@ -24911,55 +25128,55 @@ static void sp_384_get_point_16_12(sp_point_384* r, const sp_point_384* table, static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td[16]; - sp_point_384 rtd; - sp_digit tmpd[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 t[16 + 1]; + sp_digit tmp[2 * 12 * 6]; +#endif + sp_point_384* rt = NULL; #ifndef WC_NO_CACHE_RESISTANT - sp_point_384 pd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* p = NULL; +#else + sp_point_384 p[1]; #endif -#endif - sp_point_384* t; - sp_point_384* rt; -#ifndef WC_NO_CACHE_RESISTANT - sp_point_384* p; -#endif - sp_digit* tmp; +#endif /* !WC_NO_CACHE_RESISTANT */ sp_digit n; int i; - int c, y; - int err; + int c; + int y; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -#ifndef WC_NO_CACHE_RESISTANT - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 17, heap, DYNAMIC_TYPE_ECC); -#else - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + #ifndef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), + heap, DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } + #endif + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif if (err == MP_OKAY) { -#ifndef WC_NO_CACHE_RESISTANT - #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - p = t + 16; - #else - p = &pd; - #endif -#endif + rt = t + 16; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; @@ -25000,7 +25217,7 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con i = 10; n = k[i+1] << 0; c = 28; - y = n >> 28; + y = (int)(n >> 28); #ifndef WC_NO_CACHE_RESISTANT if (ct) { sp_384_get_point_16_12(rt, t, y); @@ -25047,30 +25264,39 @@ static int sp_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, con } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 12 * 6); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_point_384) * 16); - XFREE(t, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmpd, sizeof(tmpd)); - ForceZero(td, sizeof(td)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) #endif - sp_384_point_free_12(rt, 1, heap); + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 12 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#ifndef WC_NO_CACHE_RESISTANT + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (p != NULL) + #endif + { + ForceZero(p, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(p, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* !WC_NO_CACHE_RESISTANT */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } -/* A table entry for pre-computed points. */ -typedef struct sp_table_entry_384 { - sp_digit x[12]; - sp_digit y[12]; -} sp_table_entry_384; - #ifdef FP_ECC /* Double the Montgomery form projective point p a number of times. * @@ -25079,7 +25305,8 @@ typedef struct sp_table_entry_384 { * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_12(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*12; @@ -25182,6 +25409,14 @@ static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod)); } +#endif /* FP_ECC */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[12]; + sp_digit y[12]; +} sp_table_entry_384; + +#ifdef FP_ECC #endif /* FP_ECC */ /* Add two Montgomery form projective points. The second point has a q value of * one. @@ -25268,6 +25503,10 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, #ifdef WOLFSSL_SP_SMALL #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 96 bits between * * a The base point. * table Place to store generated point data. @@ -25277,26 +25516,30 @@ static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, static int sp_384_gen_stripe_table_12(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_12(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -25341,9 +25584,10 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a, } } - sp_384_point_free_12(s2, 0, heap); - sp_384_point_free_12(s1, 0, heap); - sp_384_point_free_12( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -25418,8 +25662,10 @@ static void sp_384_get_entry_16_12(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 4 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^96, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -25433,17 +25679,19 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 12 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -25451,27 +25699,30 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=95; j<4; j++,x+=96) { + x = 95; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 96; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -25485,8 +25736,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=94; i>=0; i--) { y = 0; - for (j=0,x=i; j<4; j++,x+=96) { + x = i; + for (j=0; j<4; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 96; } sp_384_proj_point_dbl_12(rt, rt, t); @@ -25512,13 +25765,12 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(rt, 0, heap); return err; } @@ -25528,16 +25780,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[12]; + /* Y ordinate of point that table was generated from. */ sp_digit y[12]; + /* Precomputation table for point. */ sp_table_entry_384 table[16]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -25545,9 +25806,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -25656,6 +25923,10 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp #else #ifdef FP_ECC /* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 48 bits between * * a The base point. * table Place to store generated point data. @@ -25665,26 +25936,30 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp static int sp_384_gen_stripe_table_12(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_12(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -25729,9 +26004,10 @@ static int sp_384_gen_stripe_table_12(const sp_point_384* a, } } - sp_384_point_free_12(s2, 0, heap); - sp_384_point_free_12(s1, 0, heap); - sp_384_point_free_12( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -25806,8 +26082,10 @@ static void sp_384_get_entry_256_12(sp_point_384* r, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 8 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -25821,17 +26099,19 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, const sp_table_entry_384* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 rtd; - sp_point_384 pd; - sp_digit td[2 * 12 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_384 rt[2]; + sp_digit t[2 * 12 * 6]; #endif - sp_point_384* rt; sp_point_384* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -25839,27 +26119,30 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, (void)heap; - err = sp_384_point_new_12(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 47; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 48; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -25873,8 +26156,10 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, rt->infinity = !y; for (i=46; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<8; j++) { y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 48; } sp_384_proj_point_dbl_12(rt, rt, t); @@ -25900,13 +26185,12 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(rt, 0, heap); return err; } @@ -25916,16 +26200,25 @@ static int sp_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[12]; + /* Y ordinate of point that table was generated from. */ sp_digit y[12]; + /* Precomputation table for point. */ sp_table_entry_384 table[256]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -25933,9 +26226,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -26052,28 +26351,31 @@ static int sp_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 12, km); sp_384_point_from_ecc_point_12(point, gm); @@ -26084,17 +26386,101 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_12(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[12 + 12 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (12 + 12 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_12(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 12; + + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(point, gm); + sp_384_point_from_ecc_point_12(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_12(point, point, addP, tmp); + + if (map) { + sp_384_map_12(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 96 between points. + */ static const sp_table_entry_384 p384_table[16] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -26179,6 +26565,11 @@ static const sp_table_entry_384 p384_table[16] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^96, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -26194,6 +26585,10 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, } #else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 48 between points. + */ static const sp_table_entry_384 p384_table[256] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -27478,6 +27873,11 @@ static const sp_table_entry_384 p384_table[256] = { /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^48, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -27503,28 +27903,30 @@ static int sp_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 12, km); @@ -27534,12 +27936,90 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_12(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[12 + 12 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (12 + 12 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_12(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 12; + + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_12(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_384_proj_point_add_12(point, point, addP, tmp); + + if (map) { + sp_384_map_12(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -27558,7 +28038,7 @@ static int sp_384_iszero_12(const sp_digit* a) a[8] | a[9] | a[10] | a[11]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ /* Add 1 to a. (a = a + 1) * * a A single precision integer. @@ -27619,7 +28099,8 @@ SP_NOINLINE static void sp_384_add_one_12(sp_digit* a) */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -27682,41 +28163,46 @@ static int sp_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[12]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + (void)heap; - err = sp_384_point_new_12(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_12(rng, k); } if (err == MP_OKAY) { @@ -27741,15 +28227,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_12(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_12(infinity, 1, heap); -#endif - sp_384_point_free_12(point, 1, heap); return err; } @@ -27763,7 +28248,10 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) */ static void sp_384_to_bin(sp_digit* r, byte* a) { - int i, j, s = 0, b; + int i; + int j; + int s = 0; + int b; j = 384 / 8 - 1; a[j] = 0; @@ -27804,33 +28292,35 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[12]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[12]; +#endif int err = MP_OKAY; if (*outLen < 48U) { err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -27843,12 +28333,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(point, 0, heap); return err; } @@ -28138,7 +28628,6 @@ static const uint32_t p384_order_minus_2[12] = { /* The low half of the order-2 of the P384 curve. */ static const uint32_t p384_order_low[6] = { 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U - }; #endif /* WOLFSSL_SP_SMALL */ @@ -28286,7 +28775,7 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_12(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_12(t2, t2); - if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { sp_384_mont_mul_order_12(t2, t2, a); } } @@ -28295,12 +28784,63 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, #endif /* WOLFSSL_SP_SMALL */ } -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int32_t c; + sp_digit* kInv = k; + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(k, k, p384_norm_order); + err = sp_384_mod_12(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(k); + + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_12(kInv, k, tmp); + sp_384_norm_12(kInv); + + /* s = r * x + e */ + sp_384_mul_12(x, x, r); + err = sp_384_mod_12(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(x); + carry = sp_384_add_12(s, e, x); + sp_384_cond_sub_12(s, s, p384_order, 0 - carry); + sp_384_norm_12(s); + c = sp_384_cmp_12(s, p384_order); + sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(s, s, kInv); + sp_384_norm_12(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -28335,8 +28875,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -28354,13 +28894,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 12, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_12(rng, ctx->k); @@ -28388,6 +28925,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_12(ctx->r, p384_order); sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_12(ctx->r); + + sp_384_from_mp(ctx->x, 12, priv); + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); ctx->state = 4; break; } @@ -28444,6 +28984,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -28476,72 +29019,55 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*12]; - sp_digit xd[2*12]; - sp_digit kd[2*12]; - sp_digit rd[2*12]; - sp_digit td[3 * 2*12]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 12]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int32_t c; + int err = MP_OKAY; int i; (void)heap; - err = sp_384_point_new_12(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 12; - x = d + 2 * 12; - k = d + 4 * 12; - r = d + 6 * 12; - tmp = d + 8 * 12; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 12; + k = e + 4 * 12; + r = e + 6 * 12; + tmp = e + 8 * 12; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 12, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 12, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_12(rng, k); @@ -28551,7 +29077,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_zero(km); } if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -28562,38 +29088,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_12(r); - /* Conv k to Montgomery form (mod order) */ - sp_384_mul_12(k, k, p384_norm_order); - err = sp_384_mod_12(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_12(k); - /* kInv = 1/k mod order */ - sp_384_mont_inv_order_12(kInv, k, tmp); - sp_384_norm_12(kInv); + sp_384_from_mp(x, 12, priv); + sp_384_from_bin(e, 12, hash, (int)hashLen); - /* s = r * x + e */ - sp_384_mul_12(x, x, r); - err = sp_384_mod_12(x, x, p384_order); + err = sp_384_calc_s_12(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_12(x); - carry = sp_384_add_12(s, e, x); - sp_384_cond_sub_12(s, s, p384_order, 0 - carry); - sp_384_norm_12(s); - c = sp_384_cmp_12(s, p384_order); - sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_12(s); - /* s = s * k^-1 mod order */ - sp_384_mont_mul_order_12(s, s, kInv); - sp_384_norm_12(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_12(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -28607,20 +29114,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 12); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_12(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -28955,6 +29466,100 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_12(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ + + sp_384_proj_point_add_12(p1, p1, p2, tmp); + if (sp_384_iszero_12(p1->z)) { + if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { + sp_384_proj_point_dbl_12(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_12(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ + { + sp_384_mul_12(s, s, p384_norm_order); + } + err = sp_384_mod_12(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(s); +#ifdef WOLFSSL_SP_SMALL + { + sp_384_mont_inv_order_12(s, s, tmp); + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + +#else + { + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ + err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_12(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -28973,8 +29578,7 @@ static int sp_384_mod_inv_12(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -28993,8 +29597,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -29009,7 +29614,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); sp_384_from_mp(ctx->s, 12, sm); sp_384_from_mp(ctx->p2.x, 12, pX); sp_384_from_mp(ctx->p2.y, 12, pY); @@ -29067,57 +29672,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_12(ctx->p1.z)) { - if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<12; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int32_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int32_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->u2, 12, rm); carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -29125,22 +29706,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_12(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -29148,134 +29730,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*12]; - sp_digit u2d[2*12]; - sp_digit sd[2*12]; - sp_digit tmpd[2*12 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 12]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int32_t c; - int err; + int32_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_12(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 12; - u2 = d + 2 * 12; - s = d + 4 * 12; - tmp = d + 6 * 12; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 12; + s = u1 + 4 * 12; + tmp = u1 + 6 * 12; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 12, hash, (int)hashLen); - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); sp_384_from_mp(s, 12, sm); sp_384_from_mp(p2->x, 12, pX); sp_384_from_mp(p2->y, 12, pY); sp_384_from_mp(p2->z, 12, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_12(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ - { - sp_384_mul_12(s, s, p384_norm_order); - } - err = sp_384_mod_12(s, s, p384_order); + err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_12(s); -#ifdef WOLFSSL_SP_SMALL - { - sp_384_mont_inv_order_12(s, s, tmp); - sp_384_mont_mul_order_12(u1, u1, s); - sp_384_mont_mul_order_12(u2, u2, s); - } - -#else - { - sp_384_mont_mul_order_12(u1, u1, s); - sp_384_mont_mul_order_12(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ - err = sp_384_ecc_mulmod_base_12(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_12(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_12(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { - { - sp_384_proj_point_add_12(p1, p1, p2, tmp); - if (sp_384_iszero_12(p1->z)) { - if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { - sp_384_proj_point_dbl_12(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - p1->x[6] = 0; - p1->x[7] = 0; - p1->x[8] = 0; - p1->x[9] = 0; - p1->x[10] = 0; - p1->x[11] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); } @@ -29286,7 +29797,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 12, r); + sp_384_from_mp(u2, 12, rm); carry = sp_384_add_12(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -29294,26 +29805,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_12(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_12(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p1, 0, heap); - sp_384_point_free_12(p2, 0, heap); return err; } @@ -29327,34 +29838,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_12(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*12]; - sp_digit t2d[2*12]; + sp_digit t1[12 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 12; - t2 = d + 2 * 12; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 12; sp_384_sqr_12(t1, point->y); (void)sp_384_mod_12(t1, t1, p384_mod); @@ -29374,10 +29877,9 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -29390,16 +29892,23 @@ static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_12(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 12, pX); sp_384_from_mp(pub->y, 12, pY); @@ -29408,7 +29917,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_12(pub, NULL); } - sp_384_point_free_12(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -29424,47 +29936,48 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[12]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; - sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; - - err = sp_384_point_new_12(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_12(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } + sp_point_384* pub = NULL; +#else + sp_digit priv[12]; + sp_point_384 pub[2]; #endif + sp_point_384* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 12, pX); sp_384_from_mp(pub->y, 12, pY); sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); @@ -29478,12 +29991,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_12(pub->x, p384_mod) >= 0 || - sp_384_cmp_12(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_12(pub->x, p384_mod) >= 0) || + (sp_384_cmp_12(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -29495,12 +30007,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Point * order = infinity */ err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_12(p->x) == 0) || - (sp_384_iszero_12(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_12(p->x) == 0) || + (sp_384_iszero_12(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -29508,22 +30018,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) /* Base * private = point */ err = sp_384_ecc_mulmod_base_12(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_12(p->x, pub->x) != 0 || - sp_384_cmp_12(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_12(p->x, pub->x) != 0) || + (sp_384_cmp_12(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_12(p, 0, heap); - sp_384_point_free_12(pub, 0, heap); return err; } @@ -29547,33 +30055,35 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; - err = sp_384_point_new_12(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_12(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 12, pX); sp_384_from_mp(p->y, 12, pY); sp_384_from_mp(p->z, 12, pZ); @@ -29594,13 +30104,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(q, 0, NULL); - sp_384_point_free_12(p, 0, NULL); return err; } @@ -29619,25 +30128,28 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_12(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -29658,12 +30170,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, NULL); return err; } @@ -29678,32 +30190,36 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 12 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 12 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_12(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 12, pX); sp_384_from_mp(p->y, 12, pY); sp_384_from_mp(p->z, 12, pZ); - sp_384_map_12(p, p, tmp); + sp_384_map_12(p, p, tmp); } if (err == MP_OKAY) { @@ -29716,12 +30232,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_12(p, 0, NULL); return err; } @@ -29734,43 +30250,28 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_12(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 12]; - sp_digit t2d[2 * 12]; - sp_digit t3d[2 * 12]; - sp_digit t4d[2 * 12]; - sp_digit t5d[2 * 12]; + sp_digit t1[5 * 2 * 12]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 12; - t2 = d + 2 * 12; - t3 = d + 4 * 12; - t4 = d + 6 * 12; - t5 = d + 8 * 12; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 12; + t3 = t1 + 4 * 12; + t4 = t1 + 6 * 12; + t5 = t1 + 8 * 12; { /* t2 = y ^ 0x2 */ @@ -29830,10 +30331,9 @@ static int sp_384_mont_sqrt_12(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -29849,31 +30349,22 @@ static int sp_384_mont_sqrt_12(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 12]; - sp_digit yd[2 * 12]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 12]; +#endif sp_digit* y = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 12; - y = d + 2 * 12; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 12; sp_384_from_mp(x, 12, xm); err = sp_384_mod_mul_norm_12(x, x, p384_mod); @@ -29906,16 +30397,12022 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 32]; + /* Y ordinate of point. */ + sp_digit y[2 * 32]; + /* Z ordinate of point. */ + sp_digit z[2 * 32]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp_arr[16 * 2]; + sp_digit* tmp = tmp_arr; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #64\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #60\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" +#ifdef __GNUC__ + "beq 3f\n\t" +#else + "beq.n 3f\n\t" +#endif /* __GNUC__ */ + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "ble 2b\n\t" +#else + "ble.n 2b\n\t" +#endif /* __GNUC__ */ + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #120\n\t" + "cmp r8, r6\n\t" +#ifdef __GNUC__ + "ble 1b\n\t" +#else + "ble.n 1b\n\t" +#endif /* __GNUC__ */ + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + XMEMCPY(r, tmp_arr, sizeof(tmp_arr)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_16(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #128\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #60\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" +#ifdef __GNUC__ + "beq 4f\n\t" +#else + "beq.n 4f\n\t" +#endif /* __GNUC__ */ + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ +#ifdef __GNUC__ + "bal 5f\n\t" +#else + "bal.n 5f\n\t" +#endif /* __GNUC__ */ + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #64\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "beq 3f\n\t" +#else + "beq.n 3f\n\t" +#endif /* __GNUC__ */ + "cmp %[a], r2\n\t" +#ifdef __GNUC__ + "bgt 3f\n\t" +#else + "bgt.n 3f\n\t" +#endif /* __GNUC__ */ + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" +#ifdef __GNUC__ + "ble 2b\n\t" +#else + "ble.n 2b\n\t" +#endif /* __GNUC__ */ + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #120\n\t" + "cmp r8, r6\n\t" +#ifdef __GNUC__ + "ble 1b\n\t" +#else + "ble.n 1b\n\t" +#endif /* __GNUC__ */ + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #124\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" +#ifdef __GNUC__ + "bge 4b\n\t" +#else + "bge.n 4b\n\t" +#endif /* __GNUC__ */ + "mov r6, #128\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u; + sp_digit ca; + sp_digit cb; + + ca = sp_1024_add_16(a1, a, &a[16]); + cb = sp_1024_add_16(b1, b, &b[16]); + u = ca & cb; + sp_1024_mul_16(z1, a1, b1); + sp_1024_mul_16(z2, &a[16], &b[16]); + sp_1024_mul_16(z0, a, b); + sp_1024_mask_16(r + 32, a1, 0 - cb); + sp_1024_mask_16(b1, b1, 0 - ca); + u += sp_1024_add_16(r + 32, r + 32, b1); + u += sp_1024_sub_in_place_32(z1, z2); + u += sp_1024_sub_in_place_32(z1, z0); + u += sp_1024_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + (void)sp_1024_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_1024_add_16(a1, a, &a[16]); + sp_1024_sqr_16(z1, a1); + sp_1024_sqr_16(z2, &a[16]); + sp_1024_sqr_16(z0, a); + sp_1024_mask_16(r + 32, a1, 0 - u); + u += sp_1024_add_16(r + 32, r + 32, r + 32); + u += sp_1024_sub_in_place_32(z1, z2); + u += sp_1024_sub_in_place_32(z1, z0); + u += sp_1024_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + (void)sp_1024_add_32(r + 32, r + 32, z2); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp_arr[32 * 2]; + sp_digit* tmp = tmp_arr; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #128\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" +#ifdef __GNUC__ + "beq 3f\n\t" +#else + "beq.n 3f\n\t" +#endif /* __GNUC__ */ + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "ble 2b\n\t" +#else + "ble.n 2b\n\t" +#endif /* __GNUC__ */ + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #248\n\t" + "cmp r8, r6\n\t" +#ifdef __GNUC__ + "ble 1b\n\t" +#else + "ble.n 1b\n\t" +#endif /* __GNUC__ */ + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + XMEMCPY(r, tmp_arr, sizeof(tmp_arr)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" +#ifdef __GNUC__ + "beq 4f\n\t" +#else + "beq.n 4f\n\t" +#endif /* __GNUC__ */ + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ +#ifdef __GNUC__ + "bal 5f\n\t" +#else + "bal.n 5f\n\t" +#endif /* __GNUC__ */ + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #128\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "beq 3f\n\t" +#else + "beq.n 3f\n\t" +#endif /* __GNUC__ */ + "cmp %[a], r2\n\t" +#ifdef __GNUC__ + "bgt 3f\n\t" +#else + "bgt.n 3f\n\t" +#endif /* __GNUC__ */ + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" +#ifdef __GNUC__ + "ble 2b\n\t" +#else + "ble.n 2b\n\t" +#endif /* __GNUC__ */ + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #248\n\t" + "cmp r8, r6\n\t" +#ifdef __GNUC__ + "ble 1b\n\t" +#else + "ble.n 1b\n\t" +#endif /* __GNUC__ */ + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" +#ifdef __GNUC__ + "bge 4b\n\t" +#else + "bge.n 4b\n\t" +#endif /* __GNUC__ */ + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#endif /* !WOLFSSL_SP_SMALL */ +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[32] = { + 0xfea85feb,0x666d807a,0xac7ace87,0x80c5df10,0x89857db0,0xfce3e823, + 0x56971f1f,0x9f94d6af,0x1c3c09aa,0xa7cf3c52,0x31852a82,0xb6aff4a8, + 0x65681ce1,0x512ac5cd,0x326b4cd4,0xe26c6487,0xa666a6d0,0x356d27f4, + 0xf7c88a19,0xe791b39f,0x31a59cb0,0x228730d5,0xe2fc0f1b,0xf40aab27, + 0xb3e01a2e,0xbe9ae358,0x9cb48261,0x416c0ce1,0xdad0657a,0x65c61198, + 0x0a563fda,0x997abb1f +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[32] = { + 0x0157a015,0x99927f85,0x53853178,0x7f3a20ef,0x767a824f,0x031c17dc, + 0xa968e0e0,0x606b2950,0xe3c3f655,0x5830c3ad,0xce7ad57d,0x49500b57, + 0x9a97e31e,0xaed53a32,0xcd94b32b,0x1d939b78,0x5999592f,0xca92d80b, + 0x083775e6,0x186e4c60,0xce5a634f,0xdd78cf2a,0x1d03f0e4,0x0bf554d8, + 0x4c1fe5d1,0x41651ca7,0x634b7d9e,0xbe93f31e,0x252f9a85,0x9a39ee67, + 0xf5a9c025,0x668544e0 +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x7c8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[32] = { + 0xbfaa17fb,0xd99b601e,0x2b1eb3a1,0x203177c4,0xe2615f6c,0xff38fa08, + 0xd5a5c7c7,0xa7e535ab,0x870f026a,0xa9f3cf14,0x0c614aa0,0x6dabfd2a, + 0x595a0738,0x144ab173,0xcc9ad335,0x389b1921,0x2999a9b4,0x4d5b49fd, + 0xfdf22286,0x39e46ce7,0x4c69672c,0xc8a1cc35,0xf8bf03c6,0xbd02aac9, + 0x2cf8068b,0x6fa6b8d6,0x672d2098,0x905b0338,0x36b4195e,0x99718466, + 0xc2958ff6,0x265eaec7 +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0xeae63895,0x880dc8ab,0x967e0979,0x80ec46c4,0xb63f73ec,0xee9163a5, + 0x80728d87,0xd5cfb4cc,0xba66910d,0xa7c1514d,0x7a60de74,0xa702c339, + 0x8b72f2e1,0x337c8654,0x5dd5bccb,0x9760af76,0x406ce890,0x718bd9e7, + 0xdb9dfa55,0x43d5f22c,0x30b09e10,0xab10db90,0xf6ce2308,0xb5edb6c0, + 0xb6ff7cbf,0x98b2f204,0x0aec69c6,0x2b1a2fd6,0x3ed9b52a,0x0a799005, + 0x332c29ad,0x53fc09ee, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x1bef16d7,0x75573fd7,0x6a67dcde,0xadb9b570,0xd5bb4636,0x80bdad5a, + 0xe9cb99a9,0x13515ad7,0xc5a4d5f2,0x492d979f,0x164aa989,0xac6f1e80, + 0xb7652fe0,0xcad696b5,0xad547c6c,0x70dae117,0xa9e032b9,0x416cff0c, + 0x9a140b2e,0x6b598ccf,0xf0de55f6,0xe7f7f5e5,0x654ec2b9,0xf5ea69f4, + 0x1e141178,0x3d778d82,0x02990696,0xd3e82016,0x3634a135,0xf9f1f053, + 0x3f6009f1,0x0a824906, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" +#ifdef __GNUC__ + "blt 1b\n\t" +#else + "blt.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #128\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #128\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" +#ifdef __GNUC__ + "blt 1b\n\t" +#else + "blt.n 1b\n\t" +#endif /* __GNUC__ */ + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_32(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_1024_cmp_32(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #124\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" +#ifdef __GNUC__ + "bge 1b\n\t" +#else + "bge.n 1b\n\t" +#endif /* __GNUC__ */ + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r8" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + sp_digit hi = t1[32 + i] - (t1[32 + i] == div); + r1 = div_1024_word_32(hi, t1[32 + i - 1], div); + + sp_1024_mul_d_32(t2, d, r1); + t1[32 + i] += sp_1024_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_1024_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2); + sp_1024_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_1024_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_1024_cmp_32(t1, d) >= 0; + sp_1024_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_1024_div_32(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_32(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + sp_1024_mul_32(r, a, p1024_norm_mod); + return sp_1024_mod_32(r, r, m); +} + + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_32(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_32(heap, sp, p) sp_1024_point_new_ex_32((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_32(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_32(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 32, pm->x); + sp_1024_from_mp(p->y, 32, pm->y); + sp_1024_from_mp(p->z, 32, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_32(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #128\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #120\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" +#ifdef __GNUC__ + "blt 2b\n\t" +#else + "blt.n 2b\n\t" +#endif /* __GNUC__ */ + /* a[i+30] += m[30] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+31] += m[31] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[31] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[31] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #120\n\t" + "cmp r10, r11\n\t" +#ifdef __GNUC__ + "blt 1b\n\t" +#else + "blt.n 1b\n\t" +#endif /* __GNUC__ */ + "ldr r6, [%[m]]\n\t" + "subs r6, r6, r8\n\t" + "neg %[ca], %[ca]\n\t" + "sbc r6, r6, r6\n\t" + "orr %[ca], %[ca], r6\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_1024_cond_sub_32(a - 32, a, m, ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_32(r, a, b); + sp_1024_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_32(r, a); + sp_1024_mont_reduce_32(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_32(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 32]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 32); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_32(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_32(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 32); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_32(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_32(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_1024_norm_32(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_32(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + int32_t n; + + sp_1024_mont_inv_32(t1, p->z, t + 2*32); + + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_32(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 32, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_32(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_32(r->x, p1024_mod); + sp_1024_cond_sub_32(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_32(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 32, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_32(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_32(r->y, p1024_mod); + sp_1024_cond_sub_32(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldr r14, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r14, r14, r7\n\t" + "neg r12, r12\n\t" + "sbc r14, r14, r14\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r14\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_dbl_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldr r4, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r4, r4, r14\n\t" + "neg r12, r12\n\t" + "sbc r4, r4, r4\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r4\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_tpl_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7, r8, r9, r10, r14}\n\t" + "ldr r4, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r4, r4, r14\n\t" + "neg r12, r12\n\t" + "sbc r4, r4, r4\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r4\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + "sub %[m], %[m], #128\n\t" + "sub %[a], %[a], #128\n\t" + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adds r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldr r7, [%[m], #124]\n\t" + "adc r12, r12, #0\n\t" + "subs r7, r7, r14\n\t" + "neg r12, r12\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], #128\n\t" + "orr r12, r7\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "subs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbcs r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "ldm %[r], {r8, r9, r10, r14}\n\t" + "ldm %[m]!, {r4, r5, r6, r7}\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, r12\n\t" + "and r6, r6, r12\n\t" + "and r7, r7, r12\n\t" + "sbcs r8, r8, r4\n\t" + "sbcs r9, r9, r5\n\t" + "sbcs r10, r10, r6\n\t" + "sbc r14, r14, r7\n\t" + "stm %[r]!, {r8, r9, r10, r14}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_mont_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[a]!, {r4, r5, r6, r7}\n\t" + "ldm %[b]!, {r8, r9, r10, r14}\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sbc r12, r12, r12\n\t" + "sub %[r], %[r], #128\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "ldm %[r], {r4, r5, r6, r7}\n\t" + "ldm %[m]!, {r8, r9, r10, r14}\n\t" + "and r8, r8, r12\n\t" + "and r9, r9, r12\n\t" + "and r10, r10, r12\n\t" + "and r14, r14, r12\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adc r7, r7, r14\n\t" + "stm %[r]!, {r4, r5, r6, r7}\n\t" + "sub %[r], %[r], #128\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "adds r5, %[c], #-1\n\t" + "ldr r5, [%[a], r8]\n\t" + "adcs r5, r5, r6\n\t" + "mov %[c], #0\n\t" + "adcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" +#ifdef __GNUC__ + "blt 1b\n\t" +#else + "blt.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +static void sp_1024_rshift1_32(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r2, [%[a]]\n\t" + "ldr r3, [%[a], #4]\n\t" + "lsr r2, r2, #1\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r2, [%[r], #0]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r3, [%[r], #4]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r4, [%[r], #8]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r2, [%[r], #12]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r3, [%[r], #16]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r4, [%[r], #20]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r2, [%[r], #24]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r3, [%[r], #28]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r4, [%[r], #32]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r2, [%[r], #36]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r3, [%[r], #40]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r4, [%[r], #44]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r2, [%[r], #48]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r3, [%[r], #52]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #64]\n\t" + "str r4, [%[r], #56]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #68]\n\t" + "str r2, [%[r], #60]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #72]\n\t" + "str r3, [%[r], #64]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #76]\n\t" + "str r4, [%[r], #68]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #80]\n\t" + "str r2, [%[r], #72]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #84]\n\t" + "str r3, [%[r], #76]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #88]\n\t" + "str r4, [%[r], #80]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #92]\n\t" + "str r2, [%[r], #84]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #96]\n\t" + "str r3, [%[r], #88]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #100]\n\t" + "str r4, [%[r], #92]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #104]\n\t" + "str r2, [%[r], #96]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #108]\n\t" + "str r3, [%[r], #100]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #112]\n\t" + "str r4, [%[r], #104]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #116]\n\t" + "str r2, [%[r], #108]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #120]\n\t" + "str r3, [%[r], #112]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #124]\n\t" + "str r4, [%[r], #116]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "str r2, [%[r], #120]\n\t" + "str r3, [%[r], #124]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_1024_div2_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_1024_cond_add_32(r, a, m, 0 - (a[0] & 1)); + sp_1024_rshift1_32(r, r); + r[31] |= o << 31; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_32_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_32_ctx; + +static int sp_1024_proj_point_dbl_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_32_ctx* ctx = (sp_1024_proj_point_dbl_32_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*32; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_32(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_32(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_32(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_32(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_32(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_32(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_32(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_32(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_32(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_32(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_32(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_32(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_32(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_32(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_32(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_32(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_32(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_32(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_32(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_32(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_32(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_32(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_32(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_32(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_32(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_32(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_32(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_32(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_32(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_32(y, y, t2, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, r6, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" +#ifdef __GNUC__ + "bne 1b\n\t" +#else + "bne.n 1b\n\t" +#endif /* __GNUC__ */ + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_1024_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r8, [%[b], #44]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r8, [%[b], #52]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #56]\n\t" + "ldr r8, [%[b], #60]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r8, [%[b], #68]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #72]\n\t" + "ldr r8, [%[b], #76]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r8, [%[b], #84]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #88]\n\t" + "ldr r8, [%[b], #92]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r8, [%[b], #100]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #104]\n\t" + "ldr r8, [%[b], #108]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r8, [%[b], #116]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #120]\n\t" + "ldr r8, [%[b], #124]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_32(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15]) | + (a[16] ^ b[16]) | (a[17] ^ b[17]) | (a[18] ^ b[18]) | (a[19] ^ b[19]) | + (a[20] ^ b[20]) | (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) | + (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) | (a[27] ^ b[27]) | + (a[28] ^ b[28]) | (a[29] ^ b[29]) | (a[30] ^ b[30]) | (a[31] ^ b[31])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_32_ctx { + int state; + sp_1024_proj_point_dbl_32_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_32_ctx; + +static int sp_1024_proj_point_add_32_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_32_ctx* ctx = (sp_1024_proj_point_add_32_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_32_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*32; + ctx->t3 = t + 4*32; + ctx->t4 = t + 6*32; + ctx->t5 = t + 8*32; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_32(ctx->t1, p1024_mod, q->y); + sp_1024_norm_32(ctx->t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_32_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_32(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_32(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_32(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_32(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_32(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_32(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_32(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_32(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_32(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_32(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_32(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_32(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_32(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_32(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_32(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_32(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_32(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_32(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_32(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* t3 = t + 4*32; + sp_digit* t4 = t + 6*32; + sp_digit* t5 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_32(t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_32(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_32(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_32(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_32(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_32(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_32(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_32(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(x, x, t5, p1024_mod); + sp_1024_mont_dbl_32(t1, y, p1024_mod); + sp_1024_mont_sub_32(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_32(y, y, x, p1024_mod); + sp_1024_mont_mul_32(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(y, y, t5, p1024_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Fast implementation that generates a pre-computation table. + * 4 bits of window (no sliding!). + * Uses add and double for calculating table. + * 1024 doubles. + * 268 adds. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_fast_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[16 + 1]; + sp_digit tmp[2 * 32 * 5]; +#endif + sp_point_1024* rt = NULL; + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * (16 + 1), + heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 16; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + (void)sp_1024_mod_mul_norm_32(t[1].x, g->x, p1024_mod); + (void)sp_1024_mod_mul_norm_32(t[1].y, g->y, p1024_mod); + (void)sp_1024_mod_mul_norm_32(t[1].z, g->z, p1024_mod); + t[1].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_1024_proj_point_add_32(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_1024_proj_point_add_32(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_1024_proj_point_add_32(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_1024_proj_point_dbl_32(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_1024_proj_point_add_32(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_1024_proj_point_dbl_32(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_1024_proj_point_add_32(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_1024_proj_point_dbl_32(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_1024_proj_point_add_32(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_1024_proj_point_dbl_32(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_1024_proj_point_add_32(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 30; + n = k[i+1] << 0; + c = 28; + y = (int)(n >> 28); + XMEMCPY(rt, &t[y], sizeof(sp_point_1024)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_dbl_32(rt, rt, tmp); + sp_1024_proj_point_add_32(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_1024_map_32(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 32 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_32(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*32; + sp_digit* b = t + 4*32; + sp_digit* t1 = t + 6*32; + sp_digit* t2 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_32(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_32(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_32(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(t2, b, p1024_mod); + sp_1024_mont_sub_32(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_32(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_32(y, b, x, p1024_mod); + sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(y, y, p1024_mod); + sp_1024_mont_sub_32(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_32(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_32(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_32(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_32(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(t2, b, p1024_mod); + sp_1024_mont_sub_32(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_32(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_32(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_32(y, b, x, p1024_mod); + sp_1024_mont_mul_32(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_32(y, y, p1024_mod); + sp_1024_mont_sub_32(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_32(y, y, p1024_mod); +} + +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_32(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* tmp = t + 4 * 32; + + sp_1024_mont_inv_32(t1, a->z, tmp); + + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_32(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[32]; + sp_digit y[32]; +} sp_table_entry_1024; + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_32(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*32; + sp_digit* t3 = t + 4*32; + sp_digit* t4 = t + 6*32; + sp_digit* t5 = t + 8*32; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_32(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_32(t1); + if ((sp_1024_cmp_equal_32(p->x, q->x) & sp_1024_cmp_equal_32(p->z, q->z) & + (sp_1024_cmp_equal_32(p->y, q->y) | sp_1024_cmp_equal_32(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_32(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<32; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<32; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<32; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_32(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_32(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_32(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_32(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_32(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_32(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_32(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_32(t1, t3, p1024_mod); + sp_1024_mont_sub_32(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_32(t3, t3, x, p1024_mod); + sp_1024_mont_mul_32(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_32(y, t3, t5, p1024_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Generate the pre-computed table of points for the base point. + * + * width = 4 + * 16 entries + * 256 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_32(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_32(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<4; i++) { + sp_1024_proj_point_dbl_n_32(t, 256, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^256, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 32 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 255; + for (j=0; j<4; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 256; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=254; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<4; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 256; + } + + sp_1024_proj_point_dbl_32(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_32(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_32(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[32]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[32]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[16]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 32 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#else +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_32(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_32(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_32(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_32(t, 128, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_32(t, s1, s2, tmp); + sp_1024_proj_to_affine_32(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC || !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_32(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 32 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 32 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 32] >> (x % 32)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_32(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_32(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_32(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[32]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[32]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_32(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_32(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 32 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_32(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_fast_32(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_32(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(point, gm); + + err = sp_1024_ecc_mulmod_32(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 4 points combined into a table of 16 points. + * Distance of 256 between points. + */ +static const sp_table_entry_1024 p1024_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0, + 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995, + 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867, + 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173, + 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc, + 0x1c49f80b,0x8dfff96a }, + { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88, + 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16, + 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e, + 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf, + 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329, + 0xde3c01f3,0x2aa1207b } }, + /* 2 */ + { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f, + 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab, + 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa, + 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9, + 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec, + 0xdf9398a4,0x40247985 }, + { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb, + 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861, + 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36, + 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd, + 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb, + 0xc8b79d80,0x1a6fd1e6 } }, + /* 3 */ + { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452, + 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e, + 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d, + 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37, + 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4, + 0x15614750,0x29b7d4dc }, + { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54, + 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7, + 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a, + 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903, + 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310, + 0x5382497e,0x5d092802 } }, + /* 4 */ + { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6, + 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd, + 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd, + 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521, + 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494, + 0x0f1fa7d7,0x2ab3bd47 }, + { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135, + 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2, + 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f, + 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c, + 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1, + 0x4c27d229,0x93a4b416 } }, + /* 5 */ + { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1, + 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519, + 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e, + 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30, + 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6, + 0x32ee7763,0x342ce0d7 }, + { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a, + 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858, + 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66, + 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433, + 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb, + 0xe156fd20,0x455f4af3 } }, + /* 6 */ + { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9, + 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee, + 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d, + 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8, + 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead, + 0x5c37c334,0x65713c29 }, + { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6, + 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424, + 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862, + 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1, + 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5, + 0x3bae3c38,0x6b0e996c } }, + /* 7 */ + { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269, + 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7, + 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da, + 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e, + 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342, + 0x678223f8,0x4022a205 }, + { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d, + 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6, + 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd, + 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21, + 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11, + 0x24a6a956,0x312179cb } }, + /* 8 */ + { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41, + 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7, + 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b, + 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5, + 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1, + 0x04ecf056,0x325d2796 }, + { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1, + 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153, + 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c, + 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9, + 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e, + 0xe32a79d3,0x19d48546 } }, + /* 9 */ + { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0, + 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea, + 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df, + 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634, + 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d, + 0xb4e453b0,0x1b3ace6c }, + { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35, + 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630, + 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824, + 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387, + 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64, + 0x192f0a14,0x538ec33e } }, + /* 10 */ + { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8, + 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699, + 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984, + 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32, + 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076, + 0xb6f8aa25,0x13cbee76 }, + { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23, + 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492, + 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e, + 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50, + 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c, + 0xe02e8967,0x4e0a1ada } }, + /* 11 */ + { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67, + 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198, + 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7, + 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d, + 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6, + 0x9f99c999,0x733e30d9 }, + { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7, + 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a, + 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a, + 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0, + 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492, + 0xb79a5c0c,0x56facb39 } }, + /* 12 */ + { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6, + 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c, + 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e, + 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb, + 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52, + 0xf18c2b91,0x57ea2b4b }, + { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a, + 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee, + 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069, + 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b, + 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927, + 0xea7935c9,0x60480b46 } }, + /* 13 */ + { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7, + 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117, + 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5, + 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0, + 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb, + 0x9a8f88cc,0x0774a0d3 }, + { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f, + 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61, + 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91, + 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df, + 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303, + 0x2432014b,0x08151954 } }, + /* 14 */ + { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28, + 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20, + 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1, + 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55, + 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7, + 0xf0860497,0x1fe09f94 }, + { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c, + 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a, + 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994, + 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa, + 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c, + 0xdb62526a,0x4de95786 } }, + /* 15 */ + { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96, + 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5, + 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5, + 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc, + 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e, + 0xe636980c,0x1c94418b }, + { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a, + 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4, + 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98, + 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474, + 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422, + 0xb55235ba,0x611bfbb2 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^256, ... + * Pre-generated: products of all combinations of above. + * 4 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#else +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xe0162bc2,0xbf9c7ec6,0x10a89289,0xddecc6e3,0x9e499d81,0x5d599df0, + 0x6d358218,0x9a96ea28,0x70c5f8db,0x01aec7d3,0x8cf5d066,0xe72e4995, + 0x3e91d7f8,0xc2e7297d,0xda9f2f5a,0x8621db92,0x5a5679ed,0x4b26c867, + 0x2c56aac1,0x233385df,0xc6a13f99,0xb88e74d4,0xffa8ec11,0x1214b173, + 0x1f3f9fef,0xa0386a27,0xc0e7b44e,0xbd9b1b4e,0xeecd3496,0xafe528dc, + 0x1c49f80b,0x8dfff96a }, + { 0xc03c0c83,0xb4a4753a,0xabcdcd75,0x68e69d18,0xf775b649,0xe3839b88, + 0xbf58f352,0x803f949a,0xbd0bc15c,0x5f702679,0x8ff298c2,0x85bf5d16, + 0xc6c7976e,0x3f6ebd98,0x45e3e1b4,0x20618af4,0x54e64093,0x67d5598e, + 0x504fed9e,0xb047283b,0x70d87517,0x450cabfd,0x3f5addbe,0x47d628bf, + 0x78cb4cca,0x0037ef30,0x6b1c4908,0x4e148d3c,0x4fcfd837,0xe256d329, + 0xde3c01f3,0x2aa1207b } }, + /* 2 */ + { { 0x01900955,0xa95b6dae,0xceb4656d,0xa5dc9cc1,0xe72fe95b,0x50c78907, + 0xa040c334,0xa1ae5447,0x7952ea6e,0x91191370,0x6d097305,0x54ff7343, + 0xbda4d10f,0xa4db0074,0x91644070,0xfd5306f1,0x8b24522c,0x14b9fe73, + 0x7849f762,0x1468dad6,0xb0dcd2e4,0x87b29a18,0x5e1ad492,0xadd7f1a1, + 0xdbba2a1a,0x9ac63a81,0x81223379,0x01379c5b,0xb0e53bc8,0xf402b2f0, + 0x0bf13b61,0x8c3eb27f }, + { 0xe513696f,0x9a4ad3e1,0x18c81ffa,0x0350ba5c,0x3c033d13,0x1e2fc136, + 0x17a531bc,0x53da6e71,0x1aed610d,0x42ec6490,0xe99ff567,0xd33e8df7, + 0x3deed12a,0xe4aad73e,0x180f4deb,0xd983b465,0x502f30b4,0x99365269, + 0xa8918d7f,0x7e2799ab,0x700fc79a,0x0ffe84b6,0x40bfd8c2,0x7b4400d6, + 0x5d2641bd,0xc3a21d21,0xc32621cb,0x79839442,0xb1401e83,0xace6500b, + 0x251c4310,0x7bf4163e } }, + /* 3 */ + { { 0xe3fd589e,0x1c174f88,0xdf974a03,0xdb501790,0x3e70549f,0xd09623e3, + 0x15924f34,0x8d091eff,0xf9b65ac5,0xeef79cad,0x3f69c2cf,0xd2cc4262, + 0x52cd82bc,0x817d9032,0xa5f1dddd,0xacf4f4d9,0x5011b6bd,0xd0612635, + 0x2ed140c9,0x9f74490d,0x4db686d2,0x64092e8c,0x776b0fcc,0x225eef16, + 0xdf16aeb6,0x0e8c01e9,0x84bbd82a,0x62836741,0x8956e337,0x757574e2, + 0x705a7f07,0x9871edc6 }, + { 0x776535f7,0xbd0b76d5,0x2635b3b8,0x5214d602,0x9d216f64,0xc0c25ad9, + 0x5515bf75,0xfd4df3a7,0x5e9f1675,0x24a625bc,0x406873e7,0x3c35efb7, + 0xbb2e5c4a,0xef5c9a33,0x806b198a,0xa971b35e,0xa3c690ed,0x9f5c0ca5, + 0x8e1e2341,0xa8d5dd89,0x955ad9e4,0x4cecbcce,0x248d3416,0x2ecf4407, + 0x45c0af6e,0x1abb3811,0x1c780fff,0x3f4bee82,0xc272ed57,0xd14df768, + 0x371637ad,0x397ed10a } }, + /* 4 */ + { { 0x755c2a27,0xcf3e0bb2,0x59585c44,0xd38e42f9,0x19285e60,0x46b13e0f, + 0x76273d0f,0xc3ecd0c0,0x193c569a,0x7800f085,0x4351818a,0xf04e74ab, + 0x8496363b,0x9258aa38,0xb8c894fe,0x8456617c,0x2af969a0,0x8bc62aaa, + 0x5a4668d9,0x66c2280b,0xa992f4fa,0xbc9df58e,0x3f401e99,0x5db0b7d9, + 0xc4c38c0e,0xe0614fe1,0x2ccdf6b3,0xd531151c,0xe143b618,0x1c7575ec, + 0xdf9398a4,0x40247985 }, + { 0x8f055746,0xfba25178,0x0ab1e6e0,0xc5ba0040,0xac292697,0xe1b194fb, + 0x5b4f4740,0x77152119,0x9bb7ba54,0x250091d0,0xb9a139a4,0x7a674861, + 0xf353aa7e,0xba8413b3,0x2443ceee,0xafe77192,0x3847bbd0,0x14468d36, + 0x3da4942d,0x61f79ff6,0xd425b456,0x1563a1c1,0x75ff4630,0x3c270fcd, + 0xeb2802c9,0x42072090,0xc85c7004,0x68f0cdcb,0xfa032e74,0xca4372fb, + 0xc8b79d80,0x1a6fd1e6 } }, + /* 5 */ + { { 0x8d5116a3,0x967a901a,0xb2f5f47f,0x0b844394,0x60ebaf3b,0xe39ad452, + 0x60ccfc0c,0x1e1be617,0xcc3f53f2,0xac07e3d2,0x1ed11bb6,0xdd838e0e, + 0x1c15b0c2,0x45475307,0x920fe5b8,0x70dd4748,0xe471896d,0x1a20be2d, + 0x59276c7c,0x3c3fad8a,0xc886ee07,0x026a1cc3,0x6e831ac4,0x9fdb6f37, + 0xac501d65,0x26a35d1a,0x40da8574,0x0ae98905,0xabd734e5,0x65dde0a4, + 0x15614750,0x29b7d4dc }, + { 0xcbf4e20b,0x44b3c2cb,0x58cc44c5,0x1c3f548f,0x5b0cac1f,0x39809b54, + 0x00f80621,0x0c0f02b5,0x066905e0,0xe612b890,0x8350188c,0x8f158ed7, + 0x3f5576b2,0xc01dc458,0xa45492e0,0x29803272,0x0ff92443,0x77a5623a, + 0x29d0dc41,0xd12a2b00,0x2780e87a,0xb4125459,0x0d53f272,0x1ebcf903, + 0x24301e8d,0xbae6ea40,0xa37d0798,0x1e5f3f2f,0x22b4126c,0x9342c310, + 0x5382497e,0x5d092802 } }, + /* 6 */ + { { 0xff2f780d,0x583a2b7e,0xd7d76b1d,0x34d26820,0x86f74aec,0xe3c32847, + 0x10823feb,0x0fd42212,0xfb5e7bf4,0x227e417e,0xa568f8cd,0x510d49b6, + 0x1781bbec,0x53bce7d6,0x2f3718b7,0x9cfe3f22,0xd9de6c1f,0x7f44e89f, + 0x3fac9b55,0xf1cc553f,0xe6f300bc,0x9d2d0846,0x9f0ae6b1,0x976c82a2, + 0x24b8bbe0,0xe63dbf5e,0x973a5aa7,0x4cac7f45,0x84dd33c7,0xc6eb6237, + 0x142fee5d,0x0a26e434 }, + { 0xacaa9a08,0x8081339f,0x5246ece1,0x40f31105,0x61393747,0x892c8170, + 0x242f02e1,0x8d8d4103,0x3b5de98a,0x482bfd20,0x5abbe952,0x89ef946b, + 0x37698249,0xb8d218b9,0x66617c7a,0xd5268e89,0x8b7d2b91,0x962e7551, + 0xfe8d67c3,0x2c5c7973,0x2b017c51,0x42e3150a,0xc1a29469,0x6f4e5ebc, + 0x531c7083,0xa39910ce,0xb77b9e50,0xaf4f6eb4,0xda120ad0,0x68cbb175, + 0xb92636ec,0x19497c61 } }, + /* 7 */ + { { 0x417659a8,0x6920b0c6,0x92cb28ff,0xc77ab9c7,0xb687797f,0x55b67180, + 0xe7759363,0x4caf58c1,0x5561b186,0x5155bdb6,0x780f4946,0x2e64e355, + 0x229a8b20,0xeb0ac9b7,0x2571bd60,0x88594d78,0xe3fa78f9,0x5dcc0939, + 0x2ac2d379,0x7b8b4830,0xb90f1444,0x505fbf60,0x3ce4b3c1,0xac610e81, + 0xd59b5c18,0x39a4f27a,0x7cea0222,0x5fa33973,0x8dff1c7b,0xe578730b, + 0x517bf7a6,0x96b91b8b }, + { 0x9aac087c,0xc1a991f4,0x6cfdb28d,0xce62f74e,0x5f7600d6,0x08d6ff9a, + 0xf917f9c9,0xd781cd04,0x3de52dbf,0x7796f5f6,0x2ed72180,0xe7db64e0, + 0x6fa4137d,0x0f0876f6,0x3ca1f716,0x3271ee64,0x7c4ab8a3,0xcb9b2058, + 0x39481047,0xcba17107,0x598c5c37,0xdf9a190d,0x6f20e125,0x0cb6e72a, + 0xf4f2902d,0xa3142204,0x7ce2dcfb,0x42d28cb9,0xa3d3c351,0xdf261b8a, + 0xcffc249d,0x73f3d315 } }, + /* 8 */ + { { 0xe6fd3673,0x5d86855b,0x9d214b7b,0x309b70af,0xdcc46cd3,0x8d332f90, + 0x595510de,0xe553c015,0x38c1251c,0x5746a096,0x85cc1bc9,0xcd7cea5b, + 0x002eba8f,0x4ffa1468,0x22fcd77c,0x10a3cb70,0xc4ea05e3,0xb6999dfb, + 0x4efa756e,0x3375a0d0,0xdced5fd8,0x4d90279e,0x251fd56e,0x48192403, + 0x82a4c5f1,0xe87633a4,0x1b34105b,0x3170d130,0x7247e578,0x93998b0f, + 0x436ba1fa,0x88934f64 }, + { 0x4713eabc,0xf09f43b0,0xaccdc517,0x4ca7dd91,0xef13ca7c,0x27daa63b, + 0x2588184b,0x8b2e5a7a,0xd95dc269,0x0a8cb612,0xe1f2f14c,0x346975a2, + 0xe172935c,0x1f29b8ed,0xd40bc1e3,0xc3cbfd6e,0x132623da,0xd3f46b3f, + 0xfb0b7681,0xc115be6d,0x56da4344,0x5e31c345,0xa8e43d98,0xa7c63f18, + 0x4bddb4ea,0x55cb2083,0x4a54f58c,0xb16a0c38,0x46fd69d9,0x74eacca2, + 0x153548e1,0x0d1898bb } }, + /* 9 */ + { { 0xe35ef043,0x4ea73461,0x3496b564,0x107b67d9,0xd0f83a3c,0xd62c173b, + 0x51d29c35,0xfad4b038,0x71b1c1a4,0x3f42882a,0x54b43b9e,0x5d2bcf66, + 0x2abdf543,0xc77b15aa,0xdabe3dc1,0x5cb38a80,0xa481673b,0x15fda0ae, + 0xe7b90ebe,0x86996b4d,0x2bc8f3d8,0x84f87e25,0x37c4e424,0xaded03d6, + 0xd7a7afd8,0xe5ede666,0xa1ccb93a,0x80dd95a2,0x46fba391,0xa55cfd25, + 0x46f82e60,0x2bdab1dc }, + { 0xfa6fed61,0x7a4de22b,0xcc8dd94e,0xca458aa5,0x071222f5,0x3e372df1, + 0xe5aff377,0x06a4b44f,0x4a738e6d,0xbc2d0ba7,0x5f31f136,0x1a470e1d, + 0xe102a911,0x77ff933a,0x310c7885,0x8b380a50,0x783fc5ac,0x9f3c0228, + 0x44725d06,0xec668925,0x5ac84221,0x878f0e16,0xcfda6e8a,0x9a3af1af, + 0x78cd2aba,0x0183ed37,0x826d0eae,0x32cdbd60,0xcbee6415,0xb3234661, + 0xb9c10120,0x353eb892 } }, + /* 10 */ + { { 0x10b5521e,0xc8fdcad6,0x52e702f0,0x1a11b440,0x8ffda49c,0x6302680d, + 0xcbf36bad,0xcdb9654a,0x4c10a2d7,0x7b58ce11,0xe630e7e0,0x1e5d1f7d, + 0x6760a813,0x8cbe3d7d,0x6480d77f,0xeb35866b,0x7f036219,0x58728cf3, + 0x42a8a757,0xdd5865ed,0x906a2870,0x283f1f1d,0xa51f906b,0x79e23fa4, + 0x543b20a8,0xf2ac6e83,0xb81e7754,0x4f0b6379,0x840016ee,0x57fbc0d4, + 0xe621b67d,0x8da20771 }, + { 0xecce65ec,0x3c855004,0xb748185e,0x76d10d1f,0x78797ad2,0x64be7bca, + 0x77e54aad,0x43444db0,0xbe0df0ff,0x17b6b0c9,0x055086a4,0x8fc4256c, + 0xfd74d5a3,0xf952c43b,0x01c4edb8,0x501e005a,0x4a57e328,0xd5172dfc, + 0x535d6ee3,0xdb40ce4e,0x0c650918,0xbaef1e5c,0x857561fc,0xe85145e7, + 0x34a224c6,0xe468536a,0x0ec0e0a2,0x69a8e227,0x242b03fc,0xb3f52247, + 0xc3bebd5f,0x862f55e2 } }, + /* 11 */ + { { 0x226049fe,0x2d6a390f,0xdcbbc9fb,0xcc92a578,0x97634fb7,0xa52feca4, + 0x3dea5893,0x2b340cb6,0x2a49e916,0xa39f338a,0x949e41f3,0x26b2df3d, + 0x065a7e40,0xc71c7cdb,0x468281a2,0x4a9b84a0,0x731eeeca,0x63eeb503, + 0x76cbb725,0xe6d09134,0xb94a678c,0x0cf979a9,0x808fd9f1,0xb44d8c3b, + 0xe0afc5b9,0xe60da613,0x3ea5be69,0x52dce7de,0xdc1ee74f,0x3a5d6864, + 0x3bc80790,0x71ab2891 }, + { 0x3b5b60ad,0xcf618fc4,0x4a0c3184,0x0afb5e30,0xbc403302,0xd22381cc, + 0xdb1c0c66,0x33cf8953,0xa6112a8d,0x9c994e4d,0xd1967a86,0xd7aae2c3, + 0x5b7acd29,0xc28d5493,0x6c9a57fb,0x8075bd13,0x9c8427f9,0xc9c0373e, + 0x193225f5,0x2cbca18d,0x442c018c,0x73777d13,0xfbb3a727,0xebe5ed47, + 0x1962dc18,0x70437d49,0x2dc08806,0xf39c1e09,0x15fff35c,0x03e9c6f7, + 0x5e360a65,0x8d087bb6 } }, + /* 12 */ + { { 0x3fdc1844,0xbe212302,0x105eac56,0x6eca27ef,0xf168a348,0x2183a606, + 0xe1d7a4cb,0x295f807d,0x7ef5d43e,0x7246a632,0xc77025c7,0xae143205, + 0xf3484e3e,0x4bdfc7ca,0xdf52c075,0xec939895,0xd7a9cac0,0x82e655f6, + 0x8baeddb0,0x985dfe20,0x527de731,0x79c817e4,0x313de1ea,0x30ce0fbc, + 0xcc4f6cbb,0x9df95b89,0xf5bb20cd,0xf2aedf1e,0x1a8cfb01,0xfc1e0a89, + 0x63edb7ec,0x225ed34a }, + { 0xbabb1a85,0x3e13154d,0x1e6a565a,0xd3d8dae7,0xab4b100f,0xd3217d56, + 0xebc78e1a,0xd44d934e,0x48e73d37,0x0215321b,0x201e43cb,0xbbc90bfa, + 0x27500905,0x3c23f1d0,0xc86691a1,0x2a2e5000,0x6065841c,0x08b2bad2, + 0x30026b60,0x15d41caf,0x5276ce61,0x1712c2f4,0x15932ffb,0x01c4c3e7, + 0x6a74caf2,0x7894e13d,0x0c0537a4,0x02d6f5df,0xc2b1c97e,0xa8fb7602, + 0xd0887c7b,0x612b60e5 } }, + /* 13 */ + { { 0xba245d6b,0xefd495cf,0xa2ce3ff6,0x5cf0cbb7,0xdff5feee,0x24da2ac0, + 0xcf28c6a3,0x90c914f8,0x4308a56b,0x72fdb50d,0x13d72034,0x03dbf779, + 0x822ac9e9,0xcfa5ec91,0x3aea3e81,0x0dde73c8,0x66289139,0x545ba962, + 0xca6acbd3,0xa52f648b,0x98a0683a,0xff6f276e,0xa378ed52,0x2536d3ac, + 0x885ac1d9,0x353c2c54,0x00bc84a7,0xcaff52da,0x37684167,0x3971f81c, + 0xd2d7986e,0x0f7334e1 }, + { 0x6596067e,0xafbb5c83,0x38c19806,0x33e54e19,0x39cb0dcc,0x8285d967, + 0x424035f9,0x2b53f43d,0xdfef9095,0x38c531f8,0xdb0f571a,0x90fbe8e4, + 0xa39ca787,0x9a0c1ed2,0x606f2620,0x2fecc1d6,0x72b7cb4a,0x9dc890b1, + 0xccbb7868,0xc33ca6fb,0xfe73ee49,0xd1b11082,0xfcb66c48,0x590b7d17, + 0x86e14573,0x9356b0a6,0x053ead85,0x75d682c4,0xc54d30fb,0xb2ae55fa, + 0xf8aee949,0x67636a72 } }, + /* 14 */ + { { 0xb91d6bea,0x638063bc,0x923ecb96,0xae263a2e,0xc627aca6,0x9d7b0992, + 0x77af9e7e,0xc6ed001a,0x24aafebb,0x9214accf,0x78055a90,0xa3564b96, + 0xe027499d,0x00999b1c,0xe46a06a5,0xe413a4e1,0x2e51efe7,0xa05d13f6, + 0x9ba843be,0x35e87d34,0x3183159e,0x0a633825,0x54601923,0x6023e8ba, + 0xb7fd1cf2,0x9b107721,0xfdf2fd53,0x46b5542b,0x1c18af38,0xb314f4f8, + 0x60ac8965,0x086f9876 }, + { 0x8cbb9850,0x76701954,0xa20d2c8c,0x6210b730,0x5335670c,0x4084d057, + 0x0324baea,0x3ecdc595,0xc76ee9b4,0x607fc5f2,0x440ffa64,0xf393d00f, + 0x2dc1463c,0xe0111796,0x9c7725e7,0xf00b8251,0x5bd1d186,0x35e60736, + 0x2cf72aac,0xf3d8554c,0xefa3497d,0xb4dd0fde,0xf646ad11,0xd712268c, + 0x9f7b8ead,0x07c20afb,0xfc06dfe5,0x630969d4,0x7245549a,0x76b7df1c, + 0xe61ae810,0x681f9403 } }, + /* 15 */ + { { 0xc9a0623b,0x7cad5163,0x67fab8d4,0xdbf82957,0x81af7c7c,0x2ccab0ec, + 0xe966d5c2,0x469e38c8,0xf0d4e41c,0x34430d52,0xa52b359c,0x426075a2, + 0x33bd0127,0x242dd3e3,0x9fed2341,0xcda3f635,0xd7d52ffa,0x4df33730, + 0x7640c3ef,0x5fff56f0,0x1bbde57c,0x4783c21c,0xeb8bb336,0xd8784a2a, + 0xead08405,0x1ec7c533,0xf9b62bd4,0x4b7f1423,0x7075d4af,0x5543145c, + 0xba60590a,0x0c9de94a }, + { 0x95d5682b,0x8ed72735,0x2ec276ed,0x711c4283,0x8b36a0d2,0xd1f4aed5, + 0x8498a88f,0x62ab40c4,0x4480f451,0x58c8fc62,0xb79cffe2,0x8bc8ca4b, + 0x701a359d,0x90ab583c,0x3fd5d15d,0xaee31a73,0xc912333c,0x02a5597b, + 0xb6c3e3c2,0x1019cae4,0x29938088,0xe513042c,0xf47c8199,0x0e00283d, + 0xf2a00e92,0x90d68e58,0xa775ae3b,0x69e2df41,0x871c30b2,0xb8d2eca5, + 0xbb1de396,0x733dca0e } }, + /* 16 */ + { { 0x4b59213a,0xf5b495d0,0x8d70200e,0xca672039,0x2b6771c1,0x4bcb09a6, + 0x2b9eb0cb,0x26adeed4,0x8cdba212,0xeb544754,0xf08890d1,0x0e1abfcd, + 0x698e46b4,0x52509963,0x82e9c138,0xe1bff0b0,0x51099a71,0xa189e4cd, + 0xc9b91cc7,0x2360c9bc,0x137ec4be,0x9bd4d7dc,0xd1519f6e,0xd0356521, + 0xcf832503,0xbf5f6d78,0x8deea2b4,0xe4301031,0xef4c319c,0xc3132494, + 0x0f1fa7d7,0x2ab3bd47 }, + { 0x922c9fbb,0x5753b680,0x0f16c6d1,0x869e7dc8,0xbac16efc,0x83445135, + 0x846d1d9b,0x4326a3b4,0xb2d62c21,0xb517fee3,0x0b292ad5,0x6905afa2, + 0x2cadac13,0x2a57131a,0xebdbca8d,0xcd904d8f,0x3f365fb2,0xdfeda86f, + 0xdc7eaa1c,0x7097b208,0xa45e77c0,0x89a35a84,0xcf5d118e,0x417a062c, + 0x1f6e99e8,0x3c0c04a8,0xba7a087d,0xc44704b0,0x3ea22ad2,0x6f8a27d1, + 0x4c27d229,0x93a4b416 } }, + /* 17 */ + { { 0x1f1efb7a,0xd4271bc1,0x33fccc0d,0xae4e68e6,0xb11f50a8,0x9d9bc8f1, + 0xaf076089,0x5430398f,0x443d0e03,0x45e242fb,0xf6e3d4c1,0x73ec2519, + 0xba9bad09,0xab70f790,0xf9add10f,0xde612ad5,0x14e942b4,0xb837e54e, + 0xddb8b68a,0x175a56d3,0x1ac2a408,0xe85b233c,0xf0c80f94,0xf8ff6c30, + 0x898db4f9,0x4b7f3fb7,0x45a7dcdd,0xa2c6044f,0xfe3d3895,0xf3abb2f6, + 0x32ee7763,0x342ce0d7 }, + { 0xcf491b1f,0xeb261394,0x1909e395,0xdcaaeed7,0x9fe4dbea,0xdcc4055a, + 0x493d604d,0x17a6611d,0x1ce5ebef,0xba445a3a,0xe3989cb5,0xe82e2858, + 0x83f58406,0xb96f4282,0xa156cf55,0x99877b99,0x4e166a0e,0xaf906a66, + 0xb2976d13,0xcea1d353,0x36c61a01,0xefc16f27,0xb0f55d86,0xdb04c433, + 0x8eb34c01,0x3cb4b269,0x2ae60280,0x38d07f78,0x43be3ec5,0x43ac3bcb, + 0xe156fd20,0x455f4af3 } }, + /* 18 */ + { { 0x754ec21c,0xc057f262,0xe3a1ba38,0x3eacd4c9,0x116c1fe9,0x3a0210d1, + 0xeacc8ab6,0xe4ea4e94,0xea6f32ca,0x31c00c9a,0x86b975ce,0x5cb6239d, + 0xa14ea1e9,0x654d5d8c,0x5067fc8b,0x230d31f4,0x6355fecb,0x48bb90cb, + 0xdc172e8e,0x78f81ece,0xcb006737,0x288380a8,0xe162d012,0x19b02e01, + 0xc5af145c,0x0e087a06,0xb72dc354,0xf04dc8b7,0x8de3c066,0xf70ef214, + 0x13009fb7,0x4f148243 }, + { 0x6e2055e2,0x5e004fce,0x86c32067,0x89e247ea,0x5f9daaa2,0x4ebcbd95, + 0xceb7f63b,0xd15f212f,0x863784a0,0x5ecc5c1f,0x75760251,0x53b3800b, + 0x8a6a2954,0xeb9301c3,0xa13cdd19,0x0f16ba18,0x887c2d24,0x8313d251, + 0x9a9413f6,0xf9923585,0xfe3fd7c5,0x423405e6,0x16e0ee05,0x678aeb34, + 0x3fadaab0,0x1f3be7bb,0x82884471,0x7901fa2c,0x4d662ff6,0xc950db30, + 0x3c01170b,0x74d5d2d4 } }, + /* 19 */ + { { 0x2b5bfe11,0xa3002dc0,0x52d321e7,0x0733410d,0x9679ba89,0x15920f65, + 0x685b236e,0x0e248c14,0x346f6040,0x8cfab594,0x40c717f0,0x9f57afb7, + 0x66044576,0x0dbab28c,0x9cdc3247,0x0fa09968,0xc230ed05,0x41e02ae2, + 0xe45bef74,0x0d961554,0xce4d7b6f,0x9688a982,0x5e62d22e,0xfadefac7, + 0xbd2cba28,0xaf1512a6,0xbe7c749f,0x78868e62,0xae9f5a6b,0x88048d81, + 0xc5857a29,0x6b1a5442 }, + { 0x43242066,0x9f5ab9ad,0x2ccca2ae,0x0afef1b5,0x988edc4e,0xb1b43ec7, + 0x0341b0d5,0x0d0c00f1,0xb50aab37,0x4d68b8f7,0xf3a64a99,0x9a8e4e6f, + 0x7f1a684e,0x198338fb,0x351a0f5c,0x8bc0e748,0xdac44515,0x2cacf2cd, + 0x5e9ff76b,0xc14d3999,0x16393055,0x54a01b3f,0x888d8376,0x6ac3eea5, + 0x723277b1,0xb84d9a9a,0xe11dbbbf,0x99132691,0xabb67178,0x597717ae, + 0x8bb14ac8,0x4c213526 } }, + /* 20 */ + { { 0x95532833,0x2e6fe0a6,0xd626d067,0xabca228e,0x649e73bd,0x22aef3d9, + 0xf03c4c0c,0x2083a87a,0x35169b45,0xe954e75d,0x74506a89,0x577509ee, + 0x2aeacf90,0x49cb276e,0xfa409f91,0x08275d77,0xf0bbd6b9,0x61eb6f3d, + 0xe4132704,0x948202cb,0xb1c498b1,0x35f3fc21,0x361fee59,0x76c68ba8, + 0x50e051f3,0xa18cbbd9,0x318e7042,0x2384a879,0x80dd1e8b,0x292abead, + 0x5c37c334,0x65713c29 }, + { 0xceb77b9a,0xdccca8e9,0x23b69469,0x2f97e727,0xa01d6b28,0xc76abee6, + 0x5abecdfe,0x3925203d,0x29290d70,0x89448082,0xb0314438,0xf9931424, + 0x7cd447c3,0x04209df1,0xc855c827,0x7c6f2059,0x56c0e069,0xd97d7862, + 0x412d94c4,0x5a9db6fe,0x994c41dd,0x19a64591,0xc89e21a3,0x12348aa1, + 0xc6a03f0e,0xd6904b50,0xa616feac,0x55c15156,0x7cc7693b,0x4e36d1b5, + 0x3bae3c38,0x6b0e996c } }, + /* 21 */ + { { 0xcceced00,0x32789fab,0xe5b7aa66,0x3237e71a,0x2ddebcdf,0x87b2e269, + 0xb61dad8f,0xb7245120,0xd35f803c,0xe11e5e48,0x98e50f0d,0xfb4df5d7, + 0xbcd2ab92,0x60ee68b4,0x1ce3363d,0x98ab2f5c,0x7cd42647,0x15ba39da, + 0x83f4fb3f,0x1a6572eb,0xe56f08db,0x0f77de88,0x172562c2,0x1743761e, + 0x8a58f0f4,0xbe349ff8,0x84d1d6e2,0xe04da71b,0x9e9ff3b4,0x368f0342, + 0x678223f8,0x4022a205 }, + { 0x83847375,0x527bbd05,0x3f451af0,0x3ae56b62,0x4b2c7f18,0x6198f24d, + 0x4525b98d,0xee323f5b,0x0e0884b5,0xa9d8d39a,0xfb12c776,0xd005d7f6, + 0x708bc154,0xd71c483e,0x742541bc,0x8ca6fd28,0xf8397ddb,0x0af3dccd, + 0x3eccf243,0xb80d3125,0x58d81b8d,0xc743a108,0x71391f68,0x3f48eb21, + 0x33bb657f,0x493aff88,0x07e47e31,0x1d15ed66,0xe08279f6,0x10159b11, + 0x24a6a956,0x312179cb } }, + /* 22 */ + { { 0x07615ac2,0xa94cc3ca,0x121ad581,0x85865e64,0xa7986b79,0xae47616f, + 0x9d5e0f1d,0x395a40eb,0x3d9457ea,0xa9143264,0xfa2865d9,0x8de6d6a3, + 0x1014ae8c,0x0771db96,0x976a87cb,0x77a7cce6,0x143a0f60,0xa7de42e1, + 0xd993d934,0xe203cc09,0x98ec4c3d,0x92018693,0x3a25df4b,0xd77546d8, + 0x62b02d6b,0x0ad9eb47,0xd05a7189,0xfaaaf208,0x431221bb,0x5238181f, + 0x733511ea,0x417d6c78 }, + { 0x0e91e9a8,0x3cbd81b7,0xc370d6b3,0x73340418,0x8eaa2373,0x825db10a, + 0x6c7d6756,0x8f2b09e4,0x94c33ded,0xe288ee9b,0x1695e3fb,0xcd8426bb, + 0xdce9e888,0xa6176c86,0x6165e362,0x3f4c8922,0x6063fb09,0x514e411f, + 0xc8f9e04c,0x6907ac20,0xdfd2ad61,0xcef7469c,0x8452199a,0xba30bae4, + 0x12ac3462,0x30681293,0xc92d482d,0x011be873,0xe8330995,0xff4cbf89, + 0xd1470a0a,0x02189d52 } }, + /* 23 */ + { { 0x92599c69,0x73e419dd,0x7fec32ca,0x5b94221b,0x09bbfbfd,0xb2bf9bd2, + 0x63ed895b,0x61ea97a4,0x3f486f79,0x6609146b,0xfd141a39,0xbd1c7a05, + 0x83d64135,0xc79ec8cf,0x9883507b,0x7f8fd42f,0x17b3d027,0xafcb53b7, + 0x67ca5a21,0x86658dcd,0xcd149786,0xa6a6c0ac,0x34b95067,0x16f3d70e, + 0xdf44958c,0x371208e3,0xec280212,0xd2dd64e6,0x30782c71,0x33b2c4ab, + 0x521176fa,0x7bbf8abd }, + { 0xa78b981a,0xbe9e4aaf,0x304ec828,0x788b4e36,0x3959dea3,0x0c45cf39, + 0x240b39c7,0x70a9bdd3,0x28383b7d,0x499cd7dd,0x307a1026,0x30690b2e, + 0xee92f1b3,0x2262d598,0xb4725a48,0xc62d77de,0x7bc3aa0e,0xa16f25bc, + 0xd15ef7fa,0x62dd8b65,0x0b96d68f,0xd979221d,0xa00f1906,0xb92885c3, + 0xeb74c740,0xfa476b9b,0xc7576222,0x217ddbb5,0x5788504f,0xc2782c30, + 0xf812716b,0x860d096c } }, + /* 24 */ + { { 0x4d79bbf9,0xfebc337d,0x69f74f80,0x5d53eab8,0x33104d53,0xff36a095, + 0x196f8b97,0x2ab820da,0x75ce6909,0x961d3d1f,0x04683754,0xb197ec04, + 0x93a6cb9b,0xa68ce1bf,0xc5f021a3,0x503456ff,0x8940ffdb,0xb50a2db1, + 0xef004209,0x77c50f8f,0x04965875,0xd635d177,0x8bb8770a,0x725766d9, + 0xa078e53e,0x8e19b028,0xf9fc8378,0x364d4cca,0xf0dd39a0,0x1a3df411, + 0x03adf920,0x7e80e442 }, + { 0x539a1ddf,0x4b5f8a57,0xee486562,0xd248e7ae,0x816021e1,0x1c7b491d, + 0xfd36d2c4,0x2e7b871b,0x0aec00d9,0xda38b504,0x6193f1b3,0xf2827612, + 0xfb1f78d6,0x69c3fe86,0xe827ac33,0x56c8b786,0x3487c8f7,0x1687f6c7, + 0x19dee5bc,0xab8f2217,0xff399418,0x04e8473f,0xa9027c80,0xf384c014, + 0xaa1d2e28,0x9967be9a,0xe065eef1,0x869686d3,0xc7bd837c,0x737c6b08, + 0x9e8bd863,0x5dcab5d1 } }, + /* 25 */ + { { 0x9a7d772b,0x0784283a,0xe540959b,0x6b49e525,0x86414ab5,0x546bb008, + 0x9d74b2a9,0xd4448162,0x203b0b1b,0x267890ad,0xc8d3f86b,0x1e7a82bc, + 0xd85a83c7,0x1352bfb5,0xfad07ccf,0xf29f16e3,0x41e0c43f,0xc02a63b8, + 0x6b379fef,0x904f22c5,0xb1244f26,0x19d8a653,0x3a28bdea,0x6635b6df, + 0xf6d455ce,0x18b68851,0x9cff3735,0x74ac2818,0x8b2cbdab,0xad40f9df, + 0xadc9d498,0x08cc2d9e }, + { 0xc170c84b,0x2e6a6866,0x5a49a484,0xbb989e8b,0xd04c8992,0x7b0e00e0, + 0x61b3a423,0x55ad3478,0xb0d01899,0x3c952450,0xe3100cb3,0xe3922155, + 0xf03276d0,0x19265b6e,0x76d42b53,0x0fe8595a,0xfc6353b6,0x0a96dee0, + 0x246f893e,0x761e0dc8,0xf0a74cba,0x4ec902be,0x3fdfad9b,0x61008684, + 0x4fdb6975,0x5d6a60e4,0x7ef7590a,0x3f53aac8,0x12870a37,0xd29e6be0, + 0x55aa55b0,0x991fadc1 } }, + /* 26 */ + { { 0xb4844ffe,0x82bc4b0f,0x60f8b871,0x73922714,0x4ce3f1f3,0x8ac000e2, + 0x163519ec,0xf0d548b4,0x88288b5f,0x7aaf842b,0x2bdc9a70,0x9e8b0c4c, + 0x4ba5fd67,0xa06d5152,0xf93cdec3,0xd0b1afa0,0xdf89f8f0,0x280955ba, + 0xeea32c92,0x86cbe92d,0x3fe05be4,0x0cae3f99,0xfa6919aa,0xf2607095, + 0x6e0f1b8b,0x0f54741e,0x30ecf988,0x2aed1f74,0x734991d7,0x9296f76b, + 0x259f0fe9,0x66cf8d28 }, + { 0x226f5868,0x9b01905b,0x16909e9e,0xc102e88c,0x4a37eb54,0x2bd08916, + 0xc9816323,0xf72253e8,0x86bac53c,0x37f84e9d,0xafeaaaf7,0x2e352454, + 0x2ca0046e,0x67c86f77,0x6663372e,0x86bce50e,0xb6950a04,0xf6a3a960, + 0xfc1aba93,0x61f994d7,0xc1326e6e,0x1957c12b,0x2e56b005,0x9b658fe4, + 0x8592740c,0x9cd297fc,0x177f26a5,0x7654ce9b,0xa79d2ebb,0xaaa699db, + 0x0ecb6448,0x5fca0c5a } }, + /* 27 */ + { { 0x569a6663,0xe26e25f3,0xe6aa4ca7,0x09597ee7,0x8d18b80c,0x25a4cda6, + 0x22926730,0x450602b5,0x07387209,0x9af5f650,0x26733a53,0xfeeedb34, + 0x86572951,0x0f5ce768,0x8398ae9a,0x872a360b,0x2b30f6c3,0x60347a80, + 0x1a162158,0xd2113b23,0xee6c6dec,0x6fd9cf92,0x5cbcf9e6,0x85f0a5a8, + 0x2ba3fe84,0xd7a5a6e4,0x51ecd727,0xaafe6720,0xa2081a10,0xe09c6bb2, + 0xb973b0b4,0x657acbf0 }, + { 0xc274c8d4,0x3130466f,0x30a994d1,0x42765176,0x7079435f,0x217258ca, + 0xeb897a06,0x44850406,0x561ee130,0xf38dfeee,0xaa1778bb,0x11f4facf, + 0xb9abb9e9,0x765c6617,0xd8f10932,0xb135499b,0xa73b9159,0xc0eb6337, + 0x6f7e8b6a,0xf2c1ccf1,0x187def53,0x5b32c03a,0x830b9c62,0x89ad1d49, + 0x2f10e538,0x1735eae3,0x9d5f55bc,0xb1cbd9c2,0xe539db0d,0x42428c47, + 0xc852b3bb,0x3d2da412 } }, + /* 28 */ + { { 0x871f2865,0x97702b6e,0x142920d6,0x56cb639f,0x45b58611,0x328522a0, + 0xf3b13812,0xf3943ad1,0x712206e8,0xe6c2200a,0xa34d59ea,0xc2890e5a, + 0xf6b7f759,0xab52fd40,0x180bf567,0xf522c8de,0xaccee396,0x181e97b2, + 0xc4ea5cbb,0xe0375819,0xab51d3ef,0x0d9985e8,0xbcb50fd8,0xe26c96ca, + 0x97e1c80d,0xfb9d6b13,0xf796357d,0x582b1814,0x07f4c7fb,0x89a78221, + 0xc0357e61,0x02aeef2d }, + { 0x2c7ec9be,0x2ba7926f,0x7258b201,0x292f307e,0xc6fa6b4a,0x74e62a10, + 0xe2bcc5ab,0x80c08549,0x7bb8c073,0xb4160db8,0x329f194d,0xd5ef0529, + 0x6dda4a9c,0x0eb8da14,0x15ea23d1,0x0b5d43d2,0xfc34bfae,0x6cebef02, + 0x848757a7,0xacd364d0,0x2d34cca3,0xc1401368,0x1d2d95e2,0x09ca6742, + 0x786eaa28,0xc3fd1d6e,0xa2965fec,0x9eb1136d,0xc0779203,0x48871baa, + 0x4b15aeb0,0x6b446c01 } }, + /* 29 */ + { { 0x25e8fe80,0xc819eb2e,0x98238a17,0x2b5f7906,0x81e41849,0xd6f1e996, + 0x98ea6d45,0x58ad8ad6,0xbfd02e40,0x5bae5ad4,0xa812416d,0x016dc327, + 0xa3347ca1,0x8b31a985,0x82a65391,0x0b4da610,0xb48c35fb,0x1cb91b2d, + 0xd2aaf8c4,0x9e96817c,0xcdfdcdc0,0x1a630483,0x12b69254,0x70559361, + 0xf8a2a097,0x5fdcd712,0x35cc5281,0x59ab623a,0x932b6095,0x30c8ebe0, + 0xb08e052f,0x8613424b }, + { 0xb2231d8a,0x28902063,0xd9a61667,0xb0f62329,0x071a9f27,0xaafa0fe7, + 0x603f047e,0x6bcd8960,0xfd92a1c3,0x118cca76,0x71d483b6,0x3414e62b, + 0xba705262,0xa123ccdd,0xfd9b5c5a,0x1a576437,0x4c8d0fa3,0xa5301bc2, + 0x102427cd,0x96f0ad44,0xd3aa6c02,0x0e6fb5e0,0x072a3996,0xcd8c4880, + 0x840d3fad,0x4dafca12,0xde91d541,0x29f4ca3d,0x8441734d,0x0037c598, + 0x9ccfe57c,0x86333a99 } }, + /* 30 */ + { { 0xecf53b40,0xd213a751,0x2f78a542,0xcff2c6f2,0xf13ae56d,0x0f59f0e2, + 0x0e61748e,0x91f8ccbf,0xd72c4145,0x0aadecb9,0x4c9cdcb7,0x6b2ed852, + 0x1eaffc70,0x8e00b72c,0xaa728102,0x89b24285,0xb679cafa,0xaa7ea7e0, + 0x4f0a6f6f,0x5d2b8c26,0x0e804397,0x7ed7b173,0xc8573049,0x5a93eb45, + 0x0986e93e,0xc92bf5d4,0x6a20c0af,0x526b5a9c,0xb99dc3af,0x0adf47c9, + 0xba202cc9,0x12b25fe2 }, + { 0x33eea395,0x09b8d78a,0xf633fc5c,0xc7a93618,0x270eceef,0x7e821629, + 0xc628ed0c,0x524779b8,0xa1d68939,0x91db5ca1,0x586edc90,0x8626e18e, + 0xfeb3f3bf,0xfe023e8b,0x0250171c,0x6279fde1,0x55e172de,0xe52ec7dc, + 0xc6d4ca45,0x445e8695,0xbdbc10f1,0x42de3878,0x6fc3835e,0x2b114de8, + 0x7e10b652,0x9faba456,0x390e78fe,0x4111d82a,0xaedf0aca,0x576b61c2, + 0x74accb74,0x216279a9 } }, + /* 31 */ + { { 0x4047f747,0xc14cdabf,0xc1315a1e,0x03ca233d,0x40e5d0a7,0x59e7cbd3, + 0xbb413869,0x1fd0c4e9,0x0f01fbd8,0x189d08b1,0xa76b823d,0x50449c42, + 0x398b00a1,0x81c224a1,0x8e8179e4,0x08084e4f,0x698e41e9,0xfd8af994, + 0x5610bf2e,0x1e30e37c,0xa7d2790f,0x4e6a043f,0xb3195388,0x9d96e60c, + 0x03799dfd,0xe75f986d,0xf8ff902f,0x3b4a8f11,0x7588416e,0xfa945378, + 0x9827535e,0x20683e3f }, + { 0xd0378878,0xcb582e26,0xa7945787,0x9e214c23,0x8f6688b3,0x13d000bf, + 0x40515270,0x7548d4f5,0x40111f5d,0x7113c15d,0xa8bff902,0x3bf5a526, + 0x9b4945cc,0xbda6b010,0xbc2f3a05,0x83dcc74e,0x43efdfa1,0x2aef6284, + 0x565c5bf4,0xd2e60ee9,0x592f243a,0x4f0fa10d,0x1bc3bf51,0x6ae58b32, + 0x60576a74,0x813b0868,0x4d73081a,0x0bc023f8,0x32dcee59,0x9fd03aa0, + 0x27d6c795,0x5e416bf5 } }, + /* 32 */ + { { 0x026cc23c,0x24313760,0xb5b29058,0xf819aaee,0xc5d2ee17,0xa92272f8, + 0xee5cc402,0x8048e7cb,0x77def07d,0xdbc7d6ee,0xf6af821e,0x61d69244, + 0x996cbb89,0x5f7966ed,0x96a155a4,0xf81b17ea,0x03f3ed56,0xb2d9ef70, + 0xe882a5b2,0x5e6e5906,0xae947180,0x86fa1072,0x658c76f4,0x34d9fc51, + 0xcb035aa0,0x9f603dc0,0x75be6481,0xb7b39feb,0xcf04a9ef,0xca87554a, + 0x87b4fde3,0x4ff682ec }, + { 0xd0a10ad5,0x3125627f,0x968e6f45,0x7fd45c72,0x806a1163,0x2981bd6b, + 0xde5033e3,0xb92de1cd,0xbf4f8988,0x3b44b45e,0xdae7e1dc,0xca1b9896, + 0x0778d878,0x52166e5a,0xa5116847,0x82d472be,0xf2895445,0xfbdd382a, + 0x5d6ec4c9,0x22ed1602,0xb6552b02,0x3614eb1c,0xa1e6210f,0x63c5df73, + 0x021a74a7,0xe9160285,0xc65cbd4d,0xa44ca400,0x0f15e299,0x48cb187e, + 0x3402507c,0x51eb818e } }, + /* 33 */ + { { 0xb92100ab,0x1fc1d178,0x9605b839,0xdf2e3d60,0xb71e59d0,0x12a7c255, + 0x14fcbe04,0x3f8b6675,0x59fd06af,0x0e8a3935,0x12020d07,0x56326502, + 0x528e7be5,0x6696fcd1,0x0c7b7654,0x6588514b,0x5912a5b5,0x0cd80f8c, + 0xf324cb7f,0x8bafef04,0xc6da3d75,0x6b53eecf,0x31d1df2f,0xedef48d8, + 0x73812b6d,0xf336b965,0xee626031,0xc82eae4a,0xd244f09b,0x300abd32, + 0x31d9647f,0x8b0af955 }, + { 0x2e603544,0xb770180a,0x221acd9e,0x2b573ac3,0x62407032,0x3a17f665, + 0xb89abc3d,0xad3e74ad,0xd793225a,0x8a3d2e3a,0xef02564b,0x457bba04, + 0xfc2dd2b5,0x8875652f,0xe67143e8,0xd2905d15,0x02e48d70,0x6d884b42, + 0xc7636a57,0x06f99219,0x35e378df,0xa8dc3421,0x10c64a02,0x95c1d73d, + 0xcc157a66,0xcd6a4ece,0x8e24a354,0xbadcc1c8,0x9839329d,0x8024f1b2, + 0x4da48ad0,0x5363e549 } }, + /* 34 */ + { { 0xe23fc641,0x1f5523b7,0x86667063,0xfe54e72f,0x8e009d2f,0x294a15f5, + 0x8c57f5e1,0xf203997f,0xb16d64dc,0xa229724c,0x4baa2ffb,0x697be4fd, + 0x0a6e8ed6,0x3f507e46,0x78508536,0x0afe3a5d,0x95408208,0xeeef6cdd, + 0xf2c4237c,0x701fd889,0x5c385253,0x496d883a,0x72a212f1,0xe25c67ed, + 0x1ff78fcd,0x4b416783,0xc16f4146,0xe9967004,0xc45b0697,0xfa45c3a1, + 0x3fbd30c3,0x63334018 }, + { 0xa2fbbbce,0x39c9a0cc,0xaa0cb744,0x876f6e5c,0x3438ece3,0x9ce6010e, + 0x13802d82,0x0aad148e,0x9cd45a1b,0x9c3e5c60,0x7bcfc1e0,0x875cb859, + 0xd8584dd0,0xb19ff790,0xd81c2a2b,0x2598b81e,0x02be07e3,0x118bdf2f, + 0xb9765ce9,0x074fc8ee,0xb24f95ae,0x125e9d88,0x0c98f09d,0x3bb12cdc, + 0xa0b74b27,0x4a6aee07,0xc08077ce,0x4723d2f9,0xbea8026f,0x959447d6, + 0x16280b73,0x93a7075c } }, + /* 35 */ + { { 0x715b27f9,0x26bbefe2,0x2a280923,0xa935a5e2,0xfd58a26a,0x5ddf23af, + 0x7c138694,0x54c83e16,0x892a2153,0x44799bc9,0x9b8d09f5,0x4e6e4710, + 0xd588ea68,0xc63af616,0x883ab1b6,0x5e896706,0x3d209336,0x3c1393a0, + 0x92c23dda,0xd02f2921,0xdcf6ea43,0xab70cb7a,0x791559e1,0x12434ea8, + 0x6d70ff0b,0x040680db,0x2832ba45,0x1a10fe52,0xe5f0cb8f,0xd69f9c08, + 0x44b141fd,0x1a7422ac }, + { 0x9f40b675,0xc3a9dd2e,0xfcc71f39,0x2a7c6603,0x1948e342,0x18939a61, + 0xed0ab484,0x8f3b6158,0xee31ca6b,0xa3aa7d97,0xf7a8db63,0xbc1e865e, + 0x2c7c62e4,0x315f8c09,0x9f5c6d0f,0xa260788f,0x4b6f3ec5,0xb1833129, + 0x36b4d849,0x73adbcd6,0xbc699a9b,0x66e14890,0x2a1175e7,0xbf3790d8, + 0xfc53ca4f,0x7f43605a,0x87ff6091,0x577f6c47,0x600c82b6,0x827c7552, + 0x9d25599c,0x0944d630 } }, + /* 36 */ + { { 0xe6ab9620,0xcfdeb63e,0x786cd808,0xdff4fa6d,0x456320b3,0x145edd82, + 0xc4943915,0x2ae5f862,0xb73b3f87,0x9508e813,0xe52f97a9,0x3bd805f3, + 0xc9829b62,0xf71b5c28,0x86e0cefc,0xb394c70e,0x23bdb36e,0x534fb1a9, + 0xdbe27e5a,0xd64f5862,0x83ab6169,0xbae23df3,0x27c828cb,0xdd6df1b1, + 0x3a307a8a,0x1901899f,0x811ddf66,0x36cc8659,0x79943b77,0xa3cb7774, + 0x6fd86576,0x7d89f383 }, + { 0xc9f92b2b,0xf8564242,0xc46e32bd,0x700c6a75,0x7f99a5c5,0x93e768b7, + 0x03149568,0xb6efe858,0xc2ce6709,0xbbfe8a19,0xee6ec493,0x721a3b1b, + 0xc371c28d,0x26eeeea9,0x15177e1d,0xd798115e,0xb068a5a5,0xd7bf3bce, + 0x46d2b4b2,0xdf8da220,0x59be9dfc,0x3df0995b,0x77640b79,0xc96897bc, + 0x5a2bd3c5,0xce0cf4c2,0x89afe744,0x16f45d6e,0x3a8509bb,0xb53f3acb, + 0x63f2a6e6,0x449af81f } }, + /* 37 */ + { { 0xa16d9377,0xc2fcf132,0x7e1a2f9e,0x9ab377b3,0x86d19ae5,0x72e1a12e, + 0xd013bbb1,0xd2b12e66,0xcb5f66ba,0x0972e055,0x399eab50,0xd11de1c0, + 0xc65f5ec2,0xc1f314fd,0x8a9ff593,0xfc311841,0xe05246e6,0xdf73c1ec, + 0x1625056d,0xc28d1363,0x6fb25e19,0x30a9dbd7,0x845cd2d7,0x049ed244, + 0xd36e852d,0xc779b83f,0xf68c8a83,0x85a35fc7,0xc95e8033,0x299bf1e1, + 0x20891af5,0x0e8617c3 }, + { 0x67c81b5c,0x53720602,0xe737873c,0x2fa89dcd,0xa8144fd0,0x2a7430b0, + 0x26208c83,0x3006c5a7,0xd8ea40f5,0x4e066660,0x896413a4,0x9dd025f9, + 0x46b9149f,0xbdf380cc,0x0a125cc2,0x80156619,0x52793c37,0x04d6a3b7, + 0x6b7a62f2,0xb6001374,0x585d5978,0xa9cfe268,0x8395fe66,0xdcad0cb8, + 0x46b261f6,0xbab468fc,0x9d9d9218,0xca0ef5ef,0x5e452402,0xc507d4a8, + 0x326cf687,0x6f4404f1 } }, + /* 38 */ + { { 0x4febd3ff,0xa3e1920b,0xfdfd2bba,0xca6234d8,0xe19a9829,0xb7d1af2a, + 0xc6f5bc20,0x23de1610,0xdaa39ca9,0xe204dbf3,0x6d8c70ab,0x2a2de9b8, + 0x7c9d370b,0x272e0c37,0xe565510e,0x80914c06,0x57cbb6b0,0xb611e7a8, + 0xd8266a6e,0x076fc6ef,0x3095801c,0xdfac34ee,0xb9e24063,0x69ff40a2, + 0x787aa5c5,0xa7ba31a9,0x33c70cd2,0x0e4d1fdf,0x6895f074,0x903e3132, + 0x7fb671e2,0x905771f8 }, + { 0xa4062bee,0x5199ba0d,0x94d7d9f9,0x18e7238c,0x1e0922c0,0xf53f29bc, + 0xb12d855f,0xde9b2a81,0x6d68ca29,0x649f3eed,0xc50c097f,0x64adfc34, + 0x9db398a0,0x81964ab9,0x7a587224,0x00d59c47,0x74c5903a,0x09fea396, + 0x15043dd0,0x6aafd8ee,0x5f1ecc20,0xc5721a6e,0x0db9b7b4,0xb6d6a483, + 0x66c8d52a,0x06ffc617,0xacc82a27,0x3de241d6,0x27f2f7a8,0x0605f052, + 0x6404decc,0x6a22953b } }, + /* 39 */ + { { 0x74fce389,0x92452d8f,0x2afa5564,0x059634c0,0xf0ed7825,0x9377ccbb, + 0x37718e0d,0x89f4045b,0x9fa69a4d,0x11074e7d,0x7295b0ba,0x5d70bb07, + 0xf107ede6,0xb22d54ad,0xa1a29c7b,0x5c39a3d8,0xd795e3ab,0x37236c02, + 0x2b589951,0xf7282d00,0x5790bee2,0x5e2265be,0xa8e65ea2,0x91e0ea11, + 0x6001cebd,0x0e71a708,0x2c1c5402,0x16900f5a,0x357f6981,0xc3b2d5c0, + 0x619e3427,0x528c9ea0 }, + { 0x5f26c577,0x1edc86b4,0x9438bd45,0xf8074708,0x792582a7,0x2dfe1013, + 0xde1e569f,0xe08eaca0,0x9a55a356,0x5f952efa,0xe4976216,0xa4d80b53, + 0xcd5d71f2,0xd2b65855,0x66cea3f0,0x246704bf,0x492323ca,0x193f641f, + 0x9adb1325,0xa681855c,0x2d19d652,0x86d522ce,0x5b82ed7b,0x53609f10, + 0x8e150d29,0x3b0f0094,0x0b13e891,0x23ad8bfb,0xf794b449,0xcbb1556c, + 0x738bcf57,0x200f9093 } }, + /* 40 */ + { { 0x8388387f,0xf9b22fc5,0x28e883c5,0xcf26f170,0xd1b7973c,0x447cab90, + 0xf6ec9171,0x8d5d4ea2,0xc30cdbc0,0x2e16f498,0x48623c2b,0xdc92910c, + 0x30dbc545,0xeb1491b0,0x14de21b0,0x631deb2e,0x2fe830f4,0x04a21066, + 0x379c1f3f,0xa4c6979c,0xfb06a795,0x8a732b68,0x1619dfa9,0x3a44327a, + 0x8dbe2c9b,0x91a307d3,0x03989fea,0x939bc8d2,0x0f4a331f,0x3daabaf2, + 0xdd0f55dc,0x5c307e98 }, + { 0x35b233da,0xbbc4e0c4,0x22f6f985,0xe3d29085,0xa8b02468,0x99dd2d21, + 0xa96916e7,0x978f40e9,0x614bcced,0x0327d86c,0xb290762c,0x95e95502, + 0xa879f2ed,0x0ffd2197,0x50e0bd33,0xc4365137,0x0827c4c4,0x26c3148a, + 0x3fcfc0b2,0xc79812a8,0x31928589,0xc3d8d17e,0x8830f42d,0x8b572cfe, + 0x4b07f83f,0x7cd9ff92,0x0a51148f,0x331ca950,0x4c59f9ac,0xd0c53968, + 0xc1434785,0x1df16dfa } }, + /* 41 */ + { { 0x68bcacc3,0xcc7bb4ac,0x430f58cf,0x06ded34f,0xd461855a,0xc59f9f4f, + 0x45c9f0bc,0xf5491994,0x4375c892,0xdc5f7ec6,0x3c85983a,0x1b8708f1, + 0x82fcd087,0xb32a5cc4,0x2d6b4c0f,0xefdcdc35,0x8ac6fb2d,0x4bb24f04, + 0x33906471,0x5982d4f5,0xb83a3ac4,0x162eb52f,0x2337a223,0x7130df28, + 0xcbc3dbd3,0xdce7b802,0x2467ac0e,0x8b395959,0x1b56717e,0x21d3d2e8, + 0x46512617,0x729a7f50 }, + { 0x8420f90a,0x874ed1aa,0x0fe4c855,0x6368e19e,0xb0be74af,0xb62d4aaa, + 0x8ca60ca9,0x76fcc480,0x7645a867,0xf310b5a5,0xddb1b24c,0x131bac9b, + 0x2dea5b44,0xef77d71d,0x72fcc64e,0x4706d210,0x673d77f0,0x29b92691, + 0xe89e0663,0x22e00bf3,0x74077d40,0x472d0cd3,0x829232e2,0x3e21040d, + 0x38dc8533,0x2f916dfb,0x14b8f667,0x48bbb59b,0xd44be19d,0x19de9f4a, + 0x232d9d5c,0x7f6d3649 } }, + /* 42 */ + { { 0x6e794819,0x3bd064de,0xf82ebda1,0x5a6b694e,0xb91e2804,0x1f017fe0, + 0x07a43cd2,0x190d31f3,0x630433e9,0x6c26f226,0x0abfdcb4,0xba488aa7, + 0xa46411c0,0x418d9085,0xbffb5880,0x1b934fe6,0xe200f849,0x75d1e237, + 0xa55413db,0xdf04d63f,0xe23b3f77,0xe216ed75,0x0f91bd30,0xa05866cb, + 0x7729c509,0x84c395d9,0x452ab2d7,0xec97e188,0x0093d686,0x8cb7c1f9, + 0x628f086c,0x2d032395 }, + { 0x4a44b4c5,0xa81c9407,0xcc702c98,0xb9846879,0xceb0dc97,0xcb502287, + 0x6e3aa321,0x30301126,0xe4c256c2,0xc0ac8763,0xe55b4845,0x65034d20, + 0xf240f35b,0xaa96a040,0x7cf7eedc,0x046d26d3,0x3b810656,0x62a5a8e1, + 0x83d70c2b,0x86044b97,0x59e4da8f,0x2fbaff88,0x5457f5d1,0x929d901a, + 0xb531b757,0xd29e1eb2,0x9e4e9739,0x214dabdc,0x4eaa9bd9,0x5bd724fc, + 0x1ef9bb9b,0x734c12b3 } }, + /* 43 */ + { { 0x92f9b086,0x98fe3c2e,0xb3fd4544,0x4641b93e,0x5c02c65c,0x47ce208b, + 0xc4f03242,0x8a52dca1,0x679d29f6,0xb5ec17d9,0x9406f5f4,0x11d2fed0, + 0x0d9ba811,0x260f63dc,0x15472a3f,0xde2b056f,0x007290e6,0x1b170d9f, + 0xb6b5c8f9,0xa2e23e8d,0xcf34c3ee,0x345a2839,0x1b973ee2,0x9bdc5461, + 0xbb24d1c5,0x65bda6c2,0x3c6141a1,0x97d52ba3,0x9d2eb201,0x47bb1612, + 0x21fbe49f,0x7c558a87 }, + { 0x3f350fec,0xb9485a52,0x6a38d4c0,0x016678c5,0x0d5aa64d,0x8ef346a2, + 0xd96da2e4,0xb85daa02,0x4f647b3c,0x845ec4ea,0x0d5e946c,0xc0d1a6ca, + 0x4fa9f4ab,0x41d8d1c1,0x9c8b1303,0x43972cc5,0x434ffbfb,0x67e1f48d, + 0x819d2318,0x350ce93a,0x6ddef23f,0x49f53090,0x200cf12c,0x3c2e6cf9, + 0x640432fc,0x42691cc1,0x72496b52,0xbfff74b4,0x020a97be,0x44527c9f, + 0x7b3c4348,0x34cd7dca } }, + /* 44 */ + { { 0x59e7fe87,0xf031761a,0x0047cd72,0xb1eae31a,0xfae30f62,0x27902e68, + 0xb71db143,0xa666f48d,0x0e0038f4,0x75ee6678,0x02bdd76d,0x3b45ac67, + 0xa0d6cd5c,0x0d2fb828,0x9d8c5b11,0x27ce7f1d,0x120b5e96,0x141fe0e4, + 0xb9267c37,0x95a1b984,0xd60312cd,0x5206e589,0xda549356,0x1867342e, + 0x070c74ac,0x374520b9,0x9557b0b3,0x2703cbb5,0xa6ed8c14,0xf621f59c, + 0xabf7b887,0x7ceb1cc2 }, + { 0xdb7fd65b,0x0647a5bb,0x36c9457c,0xd8d45cc0,0x9e12718a,0xc6da99db, + 0xe93a7fb1,0xed1dbbf4,0xbd1566a1,0x4512c95c,0xdbc0c919,0x4861ba00, + 0x9e7f5269,0x3c6cc298,0x0941aaae,0x67196150,0xc8c538e3,0xbfcf5d0f, + 0xa25a551f,0xad6e9929,0x17ca0f26,0x90710985,0xfa89ef7e,0x743b78ea, + 0x71ab4549,0x39d5ea31,0xe6d1c36d,0x7442f3f3,0x059d568d,0x25a683e0, + 0x227ced5c,0x1f629a99 } }, + /* 45 */ + { { 0xe45a1c3e,0x8925ddac,0x41f7545f,0x72d29365,0x37e7f828,0x45622fcb, + 0x3e4c79d2,0x88234513,0x9c2645d6,0x5dffaf84,0x994802b9,0x3078f4dd, + 0x9d339fa0,0x566927f0,0x9fd91dcc,0x9a500a1e,0x0ab0abd7,0xce008180, + 0x8194e5df,0xd97135a3,0x98adf088,0x9e876307,0x9a45a2a7,0x3baf01b8, + 0x788b4399,0x6fed6154,0xe77a997d,0x980e5722,0x2a378eed,0xaac90ffa, + 0x8bd805a2,0x4a75fda2 }, + { 0x55e74cbc,0xd09a8fbb,0xfab18f25,0x737738ce,0x9764ec3a,0x0fc23ad6, + 0xe7e0ad31,0xc5a7d35b,0xe481cc9b,0xe75e068e,0x3d4aec34,0xf0c2ea99, + 0x0d4a63c4,0xf1324fe8,0x99b0592c,0x5dbb7c16,0xa7e0f46b,0x442d674d, + 0xa300faea,0x5a5d66c7,0x3333ac83,0xe83dc821,0x8c408496,0x70ef812e, + 0x99ef5fc1,0x96e1dcb6,0x1734e862,0x6e2b771b,0x583507d8,0x04629cdc, + 0x23d8179a,0x5819f9ae } }, + /* 46 */ + { { 0x6aa78811,0xd9969121,0x2103e7c3,0xf64ee8f4,0x22b9e698,0xddf01070, + 0x4f582cde,0xe6001f9e,0x2ecfac1a,0x24a608af,0x06393009,0x6ef4c784, + 0xebf72911,0x5262eae6,0x8c4ee5a0,0xddbd0af5,0xecd87bc7,0x875aff90, + 0x6f24f114,0x2fddb34c,0xe865f172,0x48104281,0x886c1b9a,0x95692426, + 0x9ef4231f,0x6f5f3208,0xd0a7e82e,0xaf587acf,0x9ac395c8,0xd6571917, + 0x1364a750,0x7459603c }, + { 0xf41ae519,0x1c2475bf,0x4af8f251,0x34401fb1,0xaefb2c3d,0x70ddfcd2, + 0x51cdaf08,0x9b2d385b,0x8208bb19,0x8531c256,0x4c33f3f6,0x16c89df6, + 0x24571769,0xc23cfa99,0x86d010ba,0x2339b51e,0x22638313,0x08db0e8d, + 0x00fedeb7,0xf769e179,0xa3687ef1,0x3fd96dcb,0x91476475,0xcd046b23, + 0x0c45c8dd,0xf3ff2064,0xb8343d78,0xefd167bd,0x4b77ee90,0x493ccb6d, + 0xb3cf7b45,0x33025513 } }, + /* 47 */ + { { 0x35eaaca1,0x36f00469,0x89119102,0x0c384b75,0xe6d2954c,0xcb375665, + 0xb1e9d6d7,0xcb9199b9,0xc29c2757,0x75852349,0xb8e738d0,0x89cbd1ba, + 0x5923a427,0x9b8dbe90,0x18fe1889,0xa237793e,0xa742e083,0xa4271757, + 0x4eebd613,0x8c4979d2,0xd4f2cf77,0x40325054,0x958705de,0xa3b8a091, + 0x33d999ba,0x1b191bd9,0x3b0fee1e,0xbafefba4,0x3facdf14,0xb3bad184, + 0x4387561c,0x9328adb0 }, + { 0xf906b872,0xabe84e80,0x78262665,0x705523a0,0x3398ccf7,0xd89c6a7e, + 0xf55b5323,0x2fab551d,0x0554dea8,0xa0578eca,0x375589cd,0xef26523d, + 0x864ad750,0xd8fd6242,0x178fe1fe,0x93f27fc5,0x9df87422,0x7b3e6f30, + 0x3750d054,0x2862e49e,0x5dc038a1,0x7d90c6b2,0x84db682b,0xc1a1ae22, + 0x9881930a,0x47f3dab7,0xbaf3e0a4,0x30e6bd52,0xf62d25c5,0x0680025b, + 0xadd0d5e7,0x0aa1f3cf } }, + /* 48 */ + { { 0x22a10453,0xa9822190,0x2a03a10b,0xdd1eb91c,0x96646f3b,0xafbb5d95, + 0xf38b6fc6,0xa58de344,0xb8cfca1d,0xce47c3e5,0x0f70da04,0xfcd8e16d, + 0xda262ed6,0xac44349b,0xc56e2f8e,0x9320d87b,0x19138e58,0x9ce3ea08, + 0xa2b236c0,0xa5862dff,0x8e7efb0d,0x6b0f9a5c,0x16ac78eb,0x4b53432b, + 0x709b51af,0x6ff43105,0x8f519628,0x08e236f8,0xeed403ad,0x1f93f176, + 0x9636545e,0x559337e0 }, + { 0xd8fd807a,0x30ddf738,0xab131222,0xf4e0ec9d,0x625afbc3,0x14a2f4db, + 0x9f12f895,0xd5b70604,0xac3044fd,0xb46f3c23,0xf540148f,0x1b232d1f, + 0x39b4e554,0x61b458f5,0x0dd70b75,0xf694b24a,0x289581d9,0x0fc64299, + 0xee5fe22d,0xc05d49be,0x6a18bf63,0x7af3447f,0x7f1929d6,0xe96a1dc2, + 0xc1551e8c,0x6afe6028,0x2b5d4fa2,0x27dacaf3,0x545c2cb4,0x4a1631bc, + 0xb0c914d3,0x930070f9 } }, + /* 49 */ + { { 0x69a9bc05,0xd2f32c5e,0x589c4b73,0x0a5c19c6,0x94665f9c,0x095c9e5e, + 0xbcfb4c39,0x8ab0f293,0x1ddb7c31,0xb9070877,0x66b38048,0x894e9658, + 0x606bd9bd,0xf19a90cf,0xb6fd2d69,0xcc1d58df,0x461d8a69,0x886dcc4e, + 0xf9ce4831,0xc455c277,0x765f8a82,0x749a5996,0xc3badc8d,0x2ffc668c, + 0x9112cdab,0x38018396,0xb243c7cb,0xa98795c3,0x010a2224,0x8775f310, + 0x587b5e14,0x043a2141 }, + { 0x3a873752,0x7bbe9dbc,0x2f442fee,0xee1493f4,0xc18c2181,0x981ca2c8, + 0xe29769e7,0x00ce3090,0xde768c5f,0xb4626ac8,0x34d7677e,0x33e9ce46, + 0xe0fa94e6,0xf89c2cad,0x41f5b5bf,0x04f5cc11,0x2228c12c,0x2565f736, + 0x0c05cce5,0xf1bf706a,0xbe487c4f,0x5d07ffff,0xa499f1a4,0x3ec43c09, + 0x98d94800,0x4f4e79bb,0x073f12f8,0x8a335a16,0x0f970d6d,0x4bb5eaf7, + 0xf24d0ae8,0x18d0747b } }, + /* 50 */ + { { 0x84601faf,0x58d3c77c,0xaf1c1f72,0xc9465be2,0xd116d806,0xff626798, + 0xd5b0d93c,0x3996c0c6,0x5ec6723a,0x2fa1ad75,0x03ba5349,0x966a8144, + 0x2ac34d8a,0xdc4c9422,0xed675865,0xddf471de,0x953d528f,0xd8aca597, + 0x24ebf67d,0xb2e463b5,0x7e25b4d3,0x25824871,0x43159daa,0x23c5adba, + 0x83357540,0x5458f9c6,0xf938b1a6,0xcf685da7,0xcefed231,0x981a4fda, + 0x08bb5e59,0x711093ed }, + { 0x401f161a,0x12aa3fc6,0x974c5e87,0xf7358560,0x17b5df82,0x4aa252fb, + 0xa48e6299,0xb0b82b07,0x29dd847d,0x00234157,0x4529c5a6,0xf1e54d00, + 0x6d98f538,0xcc1c539e,0x28d3abcb,0x36162b53,0x2a84f0cd,0x75a37938, + 0x4dee7484,0xf717a81b,0x4c23bf1b,0x16cf35fb,0x787e8b3e,0x7fd1c29f, + 0x59b79ab0,0xb7da7e68,0x85f6c60b,0x072100a0,0xe7ed48b5,0x31840159, + 0x4d9c97d4,0x17898bda } }, + /* 51 */ + { { 0xae1b8cf8,0xcd8483d8,0xe9a28856,0x323d4b42,0x204a4bc2,0x7633584f, + 0xca7a69fa,0x4e0b2228,0xf757bab2,0x8afbda8b,0x6cc5f9ca,0x85b24088, + 0xd41a95c3,0x47fb4813,0xc2aabe6b,0x3f1bc53c,0x1ad1599d,0xf22cda3f, + 0xc31ea9b1,0x1b2ec081,0x01614ac1,0x048f304b,0xc6afa7ab,0xce31cee9, + 0x4140dc3d,0x55af7633,0xdce8abba,0x84b7ab37,0xc7cf3efe,0x50de7648, + 0x15356ab2,0x73a88dcf }, + { 0x06e83b39,0x3f868288,0x9f44037d,0x477a4413,0x17dbc841,0xf9058b0f, + 0x54d17549,0x2db64f4f,0xf2307ffe,0xa23cea6a,0x4f126261,0x393efd55, + 0x10f37f26,0x2f4e658a,0xf4ee1e35,0xa4437ce3,0xa93cde8b,0x64ef42a7, + 0x939aa901,0x1debc9f4,0x3d7b5cd4,0x44223d6a,0xf88a3acc,0x789a6a11, + 0x2c608a2d,0x56fb9df8,0xbbf56c06,0xe79db8e3,0x668fa300,0x73c56af2, + 0xae396a1e,0x52f32b17 } }, + /* 52 */ + { { 0xe714f71a,0x56f524c1,0x9add8519,0xc1be1262,0x65cadbe3,0xad9189d8, + 0x5a0fb649,0xd88bf5c8,0x21d192d9,0x9efa6a92,0x6f724b6f,0xe3fe8389, + 0xb250119c,0xec3fae24,0x2ae0d3c0,0x4b6af9f6,0xd619624d,0x8fceba0b, + 0x2fdb6e3a,0x7dc3092b,0x3263cd29,0xc91da376,0xf95c43bd,0x30c0761e, + 0xcdeb44d9,0x89136400,0x43c0d31d,0xfd7dce84,0x9871899f,0x78fec3b1, + 0xefdf58c1,0x79e14d28 }, + { 0x9bb40c55,0xe3822235,0x0ed07a42,0x0a27202d,0x4838c1f4,0x48e6c1a9, + 0xd864a78e,0x2b5f24a7,0x0c6c55c9,0x7e7f140a,0xce12d508,0xe62c104a, + 0xc11b1e10,0x9b0a1a7e,0xafbb3dd5,0xfd8a275f,0x9a3b6b30,0xdff354fe, + 0x46602a01,0x5a105d9e,0x93bb65f7,0x3d371b4d,0x0f82fdeb,0xda5cbf0b, + 0xde468545,0x4601229b,0xc73d517e,0x505e10b9,0x672ff492,0x77cfa541, + 0x99566ce2,0x0d8ec28a } }, + /* 53 */ + { { 0xcbeee995,0x014cf73e,0xd491e80c,0xb2eb88bc,0xd9aba5d4,0x615a6cad, + 0x9304c84d,0x2f7d4633,0x8ab03c9a,0xba0501d2,0x91babb94,0xc8f723de, + 0x50405772,0xc885f977,0xc7fcb094,0xb5e1d2b3,0xdf96c71a,0x61ee7995, + 0x3464499e,0xb8c8daab,0x5f607932,0xdb425ddd,0xb1243587,0x70251ca1, + 0x9fc74340,0x26d7d3be,0xc902ac89,0x8c179310,0x4559a74f,0x72522c15, + 0xc3734afc,0x86001e27 }, + { 0xe7693947,0x13b00ba5,0x012c062b,0x6478641e,0xe85490a8,0xe1a438e0, + 0xd9574d5e,0x5173dbbf,0x9bd3ba61,0x9532eb8c,0x5f3ea075,0x1f41bcb8, + 0x8cbb92b9,0xac1cc247,0x1ef901b4,0x0f34648e,0xd2b3b2ee,0xdd929d1e, + 0xc3d75bfc,0x470f1eab,0x139cf4d2,0x5cdbc6f7,0xf0424953,0xcd86454d, + 0x47fcb383,0x1e079812,0x17df930c,0xb9f209b4,0x114ebc00,0x4225fc31, + 0x347946c1,0x020591cb } }, + /* 54 */ + { { 0x275e0af4,0xe3003721,0xe78a4a4b,0x721141ef,0xd1757485,0x666cfcf6, + 0x168e659e,0x5fa1d737,0x0e2842ee,0x263e3e54,0x948bd5f6,0xadecc3d4, + 0x246b104a,0x019de03d,0xf343d818,0xf8a9e903,0x5b0c0d31,0xcb57ba4a, + 0x51e2765f,0x8246c506,0x6519bf67,0x80c5751f,0xf2119a01,0x5f05c200, + 0x7821d4f4,0x7e6487b8,0x261c3a06,0x262f94aa,0x72146052,0x56cfe489, + 0xa1df05ef,0x5119985f }, + { 0xb18586c0,0x5819497d,0xc6eeaa62,0x004415d6,0x97cda28b,0x7c6a46b6, + 0x7c194594,0x9a149b28,0x4ed3a506,0xb56369fa,0x43c94cb4,0x7092aa66, + 0xa9e9eee2,0x55bce73a,0x77893509,0x34bb2870,0x06eb5326,0x8af95fb0, + 0x9638f485,0x87cd0323,0x5ba75bf8,0x29376268,0x9d42d581,0xf32d6f3d, + 0x65c6d64d,0xa4cad574,0xb2cded41,0x985f50fb,0x9006a067,0xcf34ce0e, + 0x58a57f9a,0x59eaf265 } }, + /* 55 */ + { { 0x6ec3876f,0x7b407efb,0xf0f48648,0x780c6123,0xbf893039,0x2abb56ff, + 0x45a91ab0,0x9592eaa0,0x78811b82,0xce5b84d7,0x1f9f3fc9,0x86a71a34, + 0xf0e7e13b,0xc17fdd86,0x655a0880,0x88ed8297,0x81d5e666,0x75d6dc74, + 0x1d171797,0xeffc9df6,0xe3f79e1f,0x36ad4c8d,0x2046192e,0xdb15317d, + 0x274fda62,0x78c9fa7a,0x82dd9914,0x04ec924f,0x3a64971c,0x059d1e38, + 0x2620bbfb,0x3b4450ea }, + { 0xc776dcdb,0x3db7a955,0x81c8ba47,0x35c4a57c,0x505760fb,0xae285003, + 0xb3aec353,0xe3e80691,0x47117be5,0x380335be,0x056ccf61,0xe1c47e3a, + 0x33977916,0x253cfdeb,0xf5cb7ee1,0x3decdfba,0x7cf4b704,0xf3c9794f, + 0x9ff81462,0x2401680c,0xbe3daa9f,0x4e440e11,0x69f91d8a,0xc5d04377, + 0xcb5e9c5d,0x4106c7a8,0x33b7d24d,0x191909a1,0x3764b4a2,0xe893c838, + 0xc429b614,0x4a7fe30c } }, + /* 56 */ + { { 0x2455c7c5,0xe78f3a70,0x70157754,0x5b7636e8,0x7623262c,0xf32c4524, + 0x1bc780c7,0x2c98b11e,0x915ed877,0xd48eaeac,0x199265f4,0xbb04d3c0, + 0xcfa5200f,0x6b52b19b,0x93ea3fe8,0xc46a0981,0xba758059,0xd82c733d, + 0x1896aacc,0xd324bbd6,0xce8ecd51,0xac09a2fc,0x02fc44b3,0x529918fd, + 0xaaa1784b,0xf0c45e4a,0xfe22085c,0x35626340,0xc50c7d61,0x53cbb676, + 0x65126b23,0x83fa1ea3 }, + { 0x10ccc646,0x60ac86da,0x7b0451e9,0x2ce0637f,0x8a088610,0xbbbcf630, + 0x20349982,0x23c19019,0xfc0bcda0,0x707fc39c,0x1bd4fd7d,0x7f4d1f15, + 0x44713bbb,0xd6a64e74,0xc5ac9e60,0x57bdc676,0x37b61169,0x456c5303, + 0xdcf40a1d,0xd3451396,0x4997d2c7,0xf3edec25,0xc2c4a739,0x534ae9a4, + 0x6a6ad2e2,0x1401397e,0x23e95f81,0x20769d4d,0xde98fabf,0xcee007c6, + 0x931c51e0,0x61409779 } }, + /* 57 */ + { { 0x15156623,0x3ddb32db,0xab7a67c2,0x68137fbc,0x6f19e3c2,0x26011f50, + 0x89924c61,0x34218b02,0xc6804c1c,0x492a0b0f,0xafaae6a7,0xd65be706, + 0x0d01be61,0x3b13d23e,0xf87f4c69,0x44545b47,0x04dc1aa3,0xd42236e2, + 0x3c5161ec,0x6135261d,0xbd88bc07,0x1eb46a63,0x1599d720,0x78c6d836, + 0x69baf0f3,0xf6955fe1,0x17072820,0x467eebd6,0x3e3a340a,0x2f1b8a2a, + 0x2d0b5f88,0x636dac76 }, + { 0xb4c80af3,0x94280db9,0x4e3892ab,0x9a189cd1,0xd1477ddc,0x26e702e0, + 0x68f9f14f,0xe91aee38,0x80baa0b2,0x2864f63a,0x8b714a29,0xacd81f73, + 0xc5fe7cb6,0x30e1b870,0xb10837fd,0x883ea1c3,0x6b20489f,0x2da27953, + 0x58a2da5f,0x3aeb2a68,0x03a8fa14,0xe2330bf2,0xdc70b1c4,0xb5c488b5, + 0x299678f4,0x0a78c4d9,0x25df675c,0x233bd098,0x7b67d368,0x37b5c076, + 0x4d0bef3f,0x2f6dbdfe } }, + /* 58 */ + { { 0x2e4da7c7,0x2f8472fd,0xae677932,0x708cfc91,0x3dc268e2,0x364af08a, + 0x799a2424,0x0f10dfe0,0x71d58bff,0xef912d58,0x988962e6,0x6bf35dfc, + 0x5f47ea0a,0x28b96fa9,0xaad308c1,0x734a79ea,0x9f437bba,0x95730337, + 0x6cf54f75,0x002cbd8e,0xe7632eec,0x47606dcf,0x53193104,0x404b5ecb, + 0x0acf729d,0x0ae0897c,0x3bddf1de,0x89628b86,0xf87d7448,0xeced154e, + 0x458d5d4e,0x5cb6e197 }, + { 0x008c75ed,0x98cef197,0xf6eeaaf8,0x7cf49d3e,0x1875e96d,0x1d6f9e02, + 0xdd9b0d8a,0xfcec2cfe,0xb9576daa,0x38a61cfe,0x36a7dbb8,0x10003f39, + 0x23b814f4,0xb37c3868,0xb80e3153,0x9fb66dcb,0x059847a8,0x9e7e2eba, + 0x35a72770,0xa4ec63fd,0xfc9e0ed0,0x311f3d91,0xd515baa4,0x3c1dc094, + 0xa08cd4e3,0x75a06ebc,0x2ed5eeaa,0xab617238,0xe1f52c1f,0x2e82bbb0, + 0x5175d6e5,0x2149d630 } }, + /* 59 */ + { { 0x5f9311f6,0xee1a8e6f,0xbabc1f85,0xc97e3c9f,0xb494209a,0x4fa7c52e, + 0x19774fe1,0x04c2f51c,0x8555844f,0x5cefd122,0xb5873ab3,0xb53862a3, + 0xcbed19fc,0x768efdd6,0xee58469a,0xcdc12479,0x3d80c09c,0x11237e31, + 0xc044c28c,0xdd74a290,0xbd47e287,0x9ee6517a,0xad0ffeef,0xc2421228, + 0x818d281f,0x4273088f,0x43ec0de1,0xebc744bc,0xb415bd73,0x5b26eccf, + 0xcb07c26c,0x14e2f350 }, + { 0x4216946b,0x548d2a10,0x7a4bd92d,0x6e801f07,0x43695160,0x5996d0a3, + 0x63a197c9,0x0f1b5c2f,0x061f77c9,0x79da3c4f,0x93ff7b22,0x1c1cd634, + 0xa234123f,0x5e61b650,0xf284033c,0x826b34c5,0xc2f34214,0x718b90e8, + 0xae806ec5,0xa5f35620,0xe324a9b4,0xa2fae345,0x8b53cb51,0x8c0bb95e, + 0xf9965778,0xc94f6ac2,0x6b9def32,0x07ec607d,0xd0ed8f27,0x63bf1dba, + 0xdcb61e4f,0x58537e02 } }, + /* 60 */ + { { 0x64f80ba2,0x1f64b064,0x0559a45b,0xe8e055e7,0xf1f4b634,0xc3262b34, + 0xde8c8482,0xef4f7d5f,0xc30c780a,0x9d55dea0,0xcfa1e693,0x1740afb9, + 0x7460c34b,0x2cfe6a66,0x1187c1ee,0xf6695941,0x5f974d94,0x1382f277, + 0x004549eb,0x1ca0ace4,0xbabded02,0xf8244b3f,0x4e3653ea,0xc36f4d06, + 0xc55c5f83,0xeab9f0dc,0xacebce90,0xd93b9cef,0x19061425,0x16658e72, + 0x82d7970d,0x4857835f }, + { 0xd2576210,0xdcd525bc,0xd51b5443,0x9f378aa7,0x1bd83994,0xfe97bf17, + 0xf38ac621,0x930d0f63,0x818408cc,0xaf8f2c17,0x260f53f6,0x2692c87e, + 0xdb0a75e4,0x0ee45407,0xffdb1b37,0x0ec47ae5,0x7aa6a44b,0x769129dc, + 0x2e40b75d,0xb6f932b2,0x95ef3b77,0xe06764d0,0x68bc63e8,0x28fd47f5, + 0x9c0014c0,0xd1810494,0xd7995d8e,0x90e2d3fd,0x6c2a85af,0xeb39a05d, + 0xa21f3128,0x6c0277bd } }, + /* 61 */ + { { 0xb509e7ef,0xe41b7086,0x3d7f9f91,0x8842ec7b,0x5526b88b,0xcd285f94, + 0x051dd0ab,0x6e44e064,0x774f1ceb,0x90198c10,0x123e661b,0x6ecabe98, + 0x32f647d9,0x44811136,0x26c52aee,0x1dd82b45,0x939dc9d5,0xd650907f, + 0xfcd455bf,0xbd5eeef2,0x8d2e5d7c,0x7815a4dd,0x88bc9f2a,0x5ad4ec92, + 0x57a3b322,0xc6f10d0b,0x20b9cbdb,0xe8d0c1e7,0x9b774ee8,0x5a0b071a, + 0xf22fcf8f,0x3067bc9a }, + { 0xb7ca9326,0xe0e589f2,0xb1224f63,0x17a106fd,0x747a57bd,0xb2354521, + 0x62b0882e,0x2614982d,0x4391ffcf,0x7f3af544,0xa84e440d,0x1aaa337b, + 0x941bb071,0x28ea37b0,0x2e4a7f54,0xa957dcb4,0x1a6ad5fb,0xe7ab662c, + 0xf7c36a20,0xd135e381,0x9baa0b6b,0x42e7980c,0x94e4671f,0x4237030c, + 0x8b0922e3,0x24cc63ff,0x445a589f,0xd10d5279,0xa870ff6c,0xbb99d316, + 0xa996c195,0x390c83ca } }, + /* 62 */ + { { 0xffc4a73f,0x50d3fa82,0x3bd53303,0x2665d635,0x264bb77d,0x80a06f8a, + 0x22d73d84,0x81c04a6e,0x0323b8aa,0x2409cff5,0x8c4c4d5a,0x31dce217, + 0x0c0f9c19,0x374aa80e,0x00186bb8,0x0b25a387,0xaaf1487f,0xd0b77a10, + 0xab498de1,0x15f39ad5,0x1aa0c116,0x92e32da6,0x96e25ce8,0x228e3dbd, + 0x5e8646d1,0xb57c88dc,0x267b1c68,0x672b1164,0x600bdec5,0x5d0d807f, + 0x223e573a,0x3ea4007d }, + { 0xa595d0a3,0xd76debd0,0xaff0b3b4,0xa6bd76cb,0x9b1bdb97,0xbf2c154f, + 0x4c714c71,0x62b19ab4,0x221af663,0xc9bf33b9,0x8c941ef6,0x23d87c49, + 0xd79f0f6d,0x255804c3,0x2a7acbc1,0x6f1a1005,0x550528af,0x5dab79d9, + 0xc8d16213,0xfd77a6f0,0xde5e1029,0x40508b6d,0xf95da12b,0xd95ac0f2, + 0x758a8ba1,0x8860af71,0x7160c8fb,0x0b194c83,0xce004d34,0xa40e6c80, + 0x6b14aaa0,0x09f82a17 } }, + /* 63 */ + { { 0xc21366dc,0x60abe588,0xaf75daf9,0x729c0a4f,0xacb93ed4,0x70501fd9, + 0x87a16d70,0xb97e744e,0x98e7361b,0xa42e0a7a,0x28b54cf3,0x1acdaff2, + 0xb7bd9078,0xf087ccbb,0x663250e7,0xda6f3983,0xbaf07c09,0x66d693ee, + 0x8cbaf157,0x79baf4c3,0xdfca99d0,0x5a984e07,0xf26d8dab,0xab4d3247, + 0x7eba36f9,0x4d0be701,0x0e8dd216,0x37bb9e65,0x531c4f03,0x72aa4e24, + 0xb753d85a,0x77d1e984 }, + { 0xd8e62367,0xd9373239,0xb9820cf1,0x3361848b,0x5a9c97c4,0x00c7e344, + 0x14f960fc,0x9a0ec9ae,0x740474b5,0xcf41f0cf,0xece065d5,0xa5eede8f, + 0x9e808610,0xb1de5a4e,0xae0cf75d,0x17c44ae4,0x6b148d0b,0x2fa56323, + 0xd29ff2dc,0x64fa740f,0x88cb212e,0xc605eb8a,0x6a863016,0xf2c771ad, + 0x607b4c17,0x6d6112e7,0x40d49785,0xfe90ec07,0xe256e0e5,0x599be18b, + 0xca54adb0,0x4e6eabec } }, + /* 64 */ + { { 0xfb99cfe6,0x950323d3,0xc9334178,0x7b09bc26,0x7cbdfb6f,0x64111e41, + 0x89a75760,0x91141744,0x10919cb0,0x4c633df9,0x396bfd2f,0x715fc7c7, + 0x8cab62db,0x8ca19512,0x4db81aac,0x30672473,0xb4c4c54a,0xe67a246b, + 0xbf229646,0xd77ea0fa,0xfa5b5d70,0x5bed15f1,0xc2f192f3,0xa5686da5, + 0x7f6690ad,0xdecac72a,0xcaa50b7d,0x0c4af2a2,0x6049ad2f,0xf44631c1, + 0x04ecf056,0x325d2796 }, + { 0x4848c144,0xee11fb55,0xb6a7af32,0x4e062925,0x369e0f9a,0x125b68e1, + 0xca53b21e,0xad9bdae6,0x2e98ea1b,0xf50d605c,0x9f2fa395,0xbdb9e153, + 0xe91532f5,0x4570e32d,0x46a250d7,0x810698ae,0xad9d9145,0x7fd9546c, + 0x11e97a5e,0xabf67721,0x249f82e9,0xca29f7d5,0x9851df63,0xa9c539a9, + 0x71d0e3e5,0xfd84d54b,0x041d2b56,0xd1e0459c,0xfd80096a,0xceb3eb6e, + 0xe32a79d3,0x19d48546 } }, + /* 65 */ + { { 0xb540f5e5,0xfe19ee8f,0x04e68d17,0x86d2a52f,0xadbdc871,0xd2320db0, + 0xd03a7fc8,0xa83ad5a8,0x08bcb916,0x54bf83c7,0x2e51e840,0x092133ea, + 0xcb52dddf,0xbce38424,0x31063583,0xd5c7be40,0x458e3176,0xc1ebb9df, + 0xbc4dabbf,0xafb19639,0xc05725a8,0x36350fe4,0x84e1cd24,0xac4a0634, + 0xc145b8de,0xadf73154,0xb3483237,0x0aa6dd9e,0xcbff2720,0xa3345c3d, + 0xb4e453b0,0x1b3ace6c }, + { 0x90a8bdc5,0x0343e5e9,0x6306a089,0xa203bf9d,0x8e48520e,0x98489a35, + 0xde7d1d06,0xbd17debe,0x5f795d3f,0x8fafa6d7,0x387b0a3f,0xa4ceb630, + 0xffddeafa,0xe0166b32,0x7e764e02,0xa2fe2054,0xe871f304,0x55ab9824, + 0x952ec45e,0xa2bd36bb,0xa90d20ca,0x7b4c1484,0x75bcfb53,0x5319f387, + 0x6982c4e5,0x34238a4a,0xa102921d,0xa2bb61c7,0xdb3ab17e,0x1e061b64, + 0x192f0a14,0x538ec33e } }, + /* 66 */ + { { 0xa19b56cf,0x193496fe,0x7bb99acd,0x663d77f4,0x57d0a881,0x8f04afa8, + 0x082835fd,0xcced3da2,0x5d82cec7,0x7e21faed,0xf8009c85,0x6e175b99, + 0x2d05a307,0xd9c6e31b,0x81487d82,0x96948d4a,0xd46f6655,0x86ebd3f2, + 0x773ccc49,0x86851aa8,0x8b1640a6,0x3e220f22,0x41a20b75,0x9f06e3a8, + 0x90ac0a6f,0x2cfffe5e,0x8ebeb3fb,0xf5a9b1da,0x6e08e2c9,0x2587d997, + 0x03e9f401,0x6fd60298 }, + { 0x8eb7516a,0x54709f8d,0xbdc598ab,0x83058a74,0x87e801ce,0xd234dd98, + 0xd17b8a96,0xfd0f9d90,0x6e90f6ab,0xaa1e549f,0x5a7ed55b,0x2496ff80, + 0x6c254c19,0x0d9f657a,0xb8962575,0x3cdea49c,0x2dff27de,0xb685a3f0, + 0xdb8bc04b,0x3c50e7fd,0x987236b0,0x904ff0ff,0xbb0d5055,0x494298fd, + 0xe14be8d0,0x34b3386d,0x7c3d30d6,0x7ad34e9c,0xe159fdd9,0x1f2b32bd, + 0xc761e5c0,0x84cfa23c } }, + /* 67 */ + { { 0x8b99b964,0x13bc11eb,0x58e2fc47,0x8e280c0a,0xd4c9a54b,0x870fbc49, + 0xbf6e20fa,0x37a334a2,0xd7c88cfa,0xee583d0d,0xef4af1da,0x05e029a8, + 0x0c2ef8a6,0x6d55e234,0x209e9b62,0x61b6fdfe,0xbb8e080f,0x3b1dad26, + 0x9392fc1a,0x5adbc162,0x0aae3f4e,0x02ac0fe6,0xc2bf4d5b,0x8d99801a, + 0xc282fed2,0x2333f93f,0xb52db33f,0x16dcb10c,0xc55752e7,0x09f90f84, + 0xc84a0d8e,0x287d4c51 }, + { 0x0e9867da,0x5fa58201,0x1a874cda,0x614589b3,0xfbdee22e,0x005e27c5, + 0xe612bda8,0xe357fef5,0x2d3635f9,0x4e0dbedf,0x6f125a86,0x62be70e4, + 0x0d94a2e5,0xa09b9884,0x28b5e5d1,0x7eb99a15,0x751028b5,0x21b9416e, + 0xe06d2cc4,0x1b137fd7,0xfea09845,0x6fa1f517,0xffcecbd7,0x3ba1e966, + 0x832f453e,0xd4c89a4a,0xeca68fa1,0x07b1e2af,0x4bd395a3,0xd0fb4453, + 0xd8ef9e13,0x0132a3dc } }, + /* 68 */ + { { 0x576374c2,0xe53c7785,0x84727040,0xe60526d1,0x228ca044,0x8a066dc8, + 0xf1ce1313,0x1fe1c1b2,0xcdeb0c5d,0x2aeec832,0x9cbf826f,0xa7596699, + 0xde77a589,0xcd188e81,0x118d1254,0xe5ce0fe0,0x0790b86a,0xa142a984, + 0x39ac28ce,0xe28f043f,0x87de5804,0x4eef8290,0xf639a8c5,0x83c31b32, + 0x5887794f,0xd70454a7,0x18b1b391,0xca635d50,0x31d9c795,0xcefea076, + 0xb6f8aa25,0x13cbee76 }, + { 0x8d3f34f3,0x79cabe0f,0xa3617fe3,0xbda9c31c,0xdd9426a1,0xb26dee23, + 0xf29c9104,0xe9dd9627,0xe2c6cd3b,0x033eb169,0xfcba2196,0x8a73f492, + 0xb858c83c,0x92e37e0b,0x23b3fbb7,0xe4f2aca6,0x64be00a2,0x8101fb1e, + 0x948f6448,0x91a7826a,0x907260e7,0x414067b4,0xe30bb835,0xf774aa50, + 0xc999c06e,0xf922ca80,0x0ba08511,0x6b8635b9,0x25fa04f0,0xbf936b5c, + 0xe02e8967,0x4e0a1ada } }, + /* 69 */ + { { 0x8ba29c4d,0x00ca6670,0x22988094,0xc08240ce,0x16dda752,0x21c5ca67, + 0xabbbfa34,0x689c0e45,0x3ed28b72,0x1d7545fd,0xd7c56ab4,0x5f221198, + 0x38759d65,0x4b3d8f74,0x8fe50b89,0x93490dfb,0xe80eba16,0xb641f5d7, + 0x79acb537,0x7b0da5eb,0x0c1d5e5e,0xab6b1497,0xa5da429a,0x2338e68d, + 0x2f6d2f25,0xe010c437,0x6530f3a7,0x226f16d2,0xcbef08bc,0xefb0f7b6, + 0x9f99c999,0x733e30d9 }, + { 0xa42a38f9,0xecfe1582,0x4730b500,0xaec2d58e,0xde976b2c,0x2ee2f2a7, + 0xa969c1bb,0xf0539db5,0xfcecdb4a,0x31954168,0xe7a8e902,0xf2f7348a, + 0x3121541f,0x1d58d7cc,0x2202ae52,0x5d25b75c,0xf40835a7,0xdea9965a, + 0x529b4e46,0x3feb6a41,0xbd27ad9b,0x5c97fb6f,0x261f900b,0xd87554c0, + 0x04d5b19e,0xb43031d9,0xcb219b9c,0x33d5e9b8,0x3ee00bcf,0x7a43d492, + 0xb79a5c0c,0x56facb39 } }, + /* 70 */ + { { 0xa3018bfa,0x019165a2,0x9ffad984,0x100c6b24,0x55341a9b,0xbbf1b1f6, + 0x25dc4cc9,0xe6bd1d97,0x2bfffe60,0x52850ed5,0x7e5509ab,0x24e992cc, + 0x4ceb59f1,0xff6c502e,0x1aa7d148,0x2f0b3573,0xe7e3aa46,0xe90c1ddd, + 0xd1142880,0xbaec9f45,0x65be5dd5,0x475cfd26,0x1febce13,0x83abb14e, + 0x80942d30,0x6aba4829,0x297e82c8,0x1e1b235d,0x50d8218d,0xb771cdbe, + 0xd94d6cbb,0x88599266 }, + { 0x155ccaf2,0x08847290,0x7c5b773e,0x8679ebc7,0xb2dd08ed,0xa88b2dd1, + 0x87d475db,0x960a180e,0x6694d02a,0x80fdb6b7,0x3f3f9e96,0x3e8758c9, + 0x4ad836c4,0xbda3f6fa,0x32fb387d,0x9400c581,0x2550200f,0x25a78542, + 0x776ecf18,0x2a97c351,0x566db59a,0x03ebf46e,0x26545eda,0x4743a280, + 0xcf74ab44,0xed169d84,0x88cb3f69,0xbaab931d,0xd8257196,0x70ae932c, + 0xa0c09719,0x797224a6 } }, + /* 71 */ + { { 0x441f3567,0x632923f8,0x2e24bf1d,0xc11c3168,0xb7671fff,0x4b97726b, + 0x7a5e1a22,0x601746a7,0x3addb417,0x53dddea0,0x7f59b846,0x57867a3c, + 0x56cd7ff7,0xb012a987,0xf19ba9a8,0x1bd5fec9,0xf8306748,0x750379a2, + 0xab8c05d1,0x7763445d,0x7903f42a,0x5d7f441b,0xa903e46d,0xc011674d, + 0xadd126c1,0x1b1d3c4d,0x61455b40,0xa2752aac,0x555c356e,0x4da42a68, + 0xd820852c,0x3ff09c15 }, + { 0xf9cb7784,0x4c0a1bce,0x2422f305,0xaec539bc,0x0c414aa7,0x5f40f9fd, + 0xffd42bc4,0xd3aa316c,0x2f358e15,0x42f5a4c3,0xd6e27682,0x00bdcd9e, + 0xf8a5ecee,0x069f789f,0x05e14f5d,0x8078018e,0x8b40c741,0x2bb3e493, + 0x7917f72d,0x5dbc8c1d,0xcc57150c,0xe0eea664,0xc3fa8920,0xa25ecc5a, + 0x1c797164,0x3c21b0f5,0x634ad16b,0x8f09a2f2,0x58391d9a,0x8e730fc5, + 0x4fdfae4c,0x47ef1805 } }, + /* 72 */ + { { 0x3da285e4,0x9965f3d1,0x3a01e3f4,0xba7d4dba,0x61214ad0,0x4738413a, + 0x22397549,0xd3b7d535,0x5a730b92,0xa53dbdcf,0x332d165d,0x3130d92b, + 0x82f97ef4,0x44a28541,0x44dce1b6,0xbf62221c,0x7e2a0ec9,0xbba13858, + 0xcbfad998,0x33f32c8d,0xb5fed44b,0x409e5f3f,0xc66217bb,0x5c328c65, + 0xfcdf71a9,0xb00db69f,0xb8920788,0xa23c2a21,0x3ae6464b,0xf8ab28e6, + 0xb8de0861,0x1a6b6e9c }, + { 0x06af77aa,0xaf6ec2b6,0xa887f065,0x2e60f5cd,0x9f498c56,0x87d21400, + 0xfcbaaf4b,0xdb595b59,0x271ab855,0x0fb592a1,0xd4349b0c,0xa0ce10e5, + 0x887d8c9c,0x9d6187d8,0x154bd6db,0x03ee95f9,0x5d06c999,0x8fe53213, + 0xfb6a64d0,0xf4a7bc30,0x66a4cb60,0x3d22af0d,0x5d37367c,0x16952cef, + 0x997d8e55,0x6f0ea734,0x731732d0,0xb447c70f,0xa9cb3942,0x00ab3034, + 0x28510fd0,0x79dd0180 } }, + /* 73 */ + { { 0x3ac7424e,0x04e0033a,0x60fda4d0,0xdb06b688,0xbcb772fb,0x236a9766, + 0xf297cda4,0x294a8e2b,0xdb013c6e,0x4b0aab85,0x8723a3ad,0x3d2aec98, + 0x13c84a6b,0x0cae32cd,0x70ec169e,0x21888f5e,0x42a88262,0x739633bd, + 0x7b60d9b8,0x68ac792e,0x10769fe1,0x89f2b722,0xd24bed34,0x8f3fcfe6, + 0xa3eb24aa,0xd35efb88,0x484c706b,0xddecfa3f,0x929ece0d,0x7cc119a9, + 0x8d405436,0x87e5ad45 }, + { 0x7d1000a7,0xba99aa9d,0xae823833,0x8b94affc,0xdfb83dc5,0xc8229628, + 0x845a418d,0x2f59fe11,0x5d417054,0xa8b970f8,0x72b71581,0x8918c265, + 0xc0d1dd17,0xe4ef477d,0x3afad7c0,0xb50b4cf3,0x01870a5b,0x21baea79, + 0xbb3a2868,0xc77087f9,0x124a59cd,0x7857531e,0x57f43239,0xed74c26f, + 0x0164c94a,0xd5f5ae25,0xf094bf74,0x6608b7e2,0xfdceea32,0xf4cdb5ba, + 0x990cc045,0x0b712519 } }, + /* 74 */ + { { 0x88d5c64d,0x5a290ca1,0xa7492534,0x0596d749,0x2a00e925,0xa04b0d3d, + 0xcaf7b66b,0x082cd02c,0xecdded83,0x912b50c2,0xff31646e,0x813ce9de, + 0xc75fff95,0x62ae70c7,0x7e2a4615,0x6f6852e0,0x03804fd1,0x320fd7d0, + 0x8218e8d9,0xb1a2a4dd,0xafc645d7,0x4918a6fb,0xe8d9fdbe,0xfb080fa1, + 0x4470b6ee,0x33d4d08a,0x6d974ef7,0xd2ba2077,0x69dae5d2,0x8ecb95a7, + 0x7d69596d,0x7a3f423a }, + { 0x9a929387,0x362d2ca6,0xcb1c1fff,0xabdb7581,0x7e51b6cb,0xd892ec9f, + 0x3a4e131f,0xee8d8632,0x5bd87561,0x4680e3f1,0xd4e7e732,0xe3a597e1, + 0x5581fefe,0x3cc72b7c,0xca8cae0b,0xf3e77f8a,0x5e2fd4af,0xfcc7d7dc, + 0x21355b79,0xdd3a4552,0xa2c07177,0x546b24f2,0x0689621f,0x415b532d, + 0x3f78163e,0x2be9af51,0x33d7ed21,0x27d63b9b,0x96802943,0xab019ef2, + 0x1623faf4,0x2da5fc55 } }, + /* 75 */ + { { 0xc8a5c600,0x62429cf3,0x3fe33e7c,0xa7a80c22,0x0a57ddcb,0x9ffda740, + 0x925b0c74,0xd1ae156d,0x6b100eb0,0x097a43f9,0xef943c81,0x169e945c, + 0x1128cf24,0xa1f734e5,0x419f0133,0x04387c4a,0x01044024,0xc007868b, + 0x90359cf2,0xe5416abf,0x478d54e3,0xf9c76fee,0x42a2173e,0x66219da6, + 0x9fe30141,0x61e03156,0x93ef247e,0xa0ff5ce3,0x072b6592,0x811792ba, + 0x70c854d3,0x855f0219 }, + { 0x847314c4,0x61fbfb6c,0xeb45b96a,0x97906155,0x6ba2afac,0x7102e146, + 0xab949781,0xed51f975,0xc110c4fe,0x9d2f5b17,0xaff57667,0x7ac8ce70, + 0x6eb244e7,0xe7366a21,0x551c65c7,0xdd1bbcec,0xe1a859de,0xb525060a, + 0x8ba7d2e7,0x7a048174,0xab8ea8c4,0xe1a2c541,0x6fdff078,0x6e7824c3, + 0x14874b04,0x79b49fc7,0x06b1f733,0x22ae337f,0x6f8fe6cf,0x1c352192, + 0x525d0797,0x292236cf } }, + /* 76 */ + { { 0x7d8b29dc,0xcdb8d80a,0x08ea648a,0xd17a2024,0xae92be91,0x7db12c5e, + 0xfda72fbc,0x1f347d18,0x9e760c6f,0x11374b40,0xd8e38d91,0x7361e8f1, + 0x739ac1f4,0x7714be9d,0xb4df5c4e,0xc1f9701c,0x6f72cae1,0xd9138ed8, + 0x6ad180c4,0x1c7fe1f7,0x9e2dbf9c,0xf8c185be,0x7c70c44d,0x835db269, + 0xb0d15b5f,0xf997cfea,0x61e6545e,0x5101445a,0x25184e5e,0x16b06884, + 0x7521e7aa,0x7cfac359 }, + { 0x3c0bc53a,0x81182167,0x7e751367,0x84b5ede3,0xa3657a18,0x3ca255fd, + 0xba1fdd98,0x096abbf4,0xc5da77d8,0x9ce8369f,0xaab342c5,0xf27b9ae7, + 0x972059f1,0x06c91bd6,0x914ecfe9,0xee0dab30,0x93f53f12,0xbb647fbb, + 0xffa57e0e,0x30c38a7a,0x9f2ad607,0x517d06ef,0xbb99dcc9,0x49728d87, + 0x446080a1,0xb0034af1,0x12b9c17d,0xcc810c3f,0x772a22a0,0x7225f14f, + 0x1ddf82bd,0x6ce3dc7f } }, + /* 77 */ + { { 0xa4397830,0xc07cd835,0xf4733306,0x4dd9290c,0x29989e8c,0xdd35d3a8, + 0x563d8152,0x79902559,0xe87de61b,0xf278d911,0x1024e35c,0x9c7340c7, + 0x4a0d0e59,0x2d444461,0xf32626a1,0x63e7608f,0xc4c9baa9,0x627a37e9, + 0x76fffd25,0x0c56dc51,0xcef2a1cd,0xcb6defc8,0xefc559d9,0xcbcc0d56, + 0x041cb692,0xe45f3fc5,0xe5161e09,0xcd05c239,0x5c3b559c,0x2a731ee9, + 0xa3d0a16d,0x85151122 }, + { 0x86ff19e2,0x782d0335,0x1da28603,0xc2c60daa,0x557c7eed,0xb2e78cfe, + 0x1bc4e8b0,0xa8f6f984,0x3df35c67,0xcc1f9b4b,0x4764462a,0x96e13603, + 0x7c7ae0b0,0xbf910b97,0x51435956,0x27c7f305,0xf631eae5,0xc14db15c, + 0x7e69b34c,0xa51d6142,0x5fc12ff2,0xdec82851,0xfb887162,0xfcceae13, + 0xde1488bd,0xda332ac1,0x2ee3e74c,0xa20374e2,0xf0ae069c,0x597ea1a1, + 0x77bdec04,0x8b1159f2 } }, + /* 78 */ + { { 0x2f961d30,0x4af71a44,0x7ac7248f,0xbdf968a8,0xb1a906cd,0xd32df87c, + 0x04abf925,0x00c10e26,0xb9f04d4c,0xb8711759,0x939705da,0x00d54e60, + 0xc9f80849,0xf7587433,0x6a7a2375,0x2e9abade,0x94ac17ac,0x5676d478, + 0xc202d99c,0x4ca0525b,0xabfae73d,0x95b8bcad,0x3405991b,0x2371ed38, + 0x458a99c3,0x2b69e47a,0x2b78c866,0x7cac0b18,0xe0232c7c,0x6ceaa79b, + 0x588f7459,0x0bd86433 }, + { 0x7e734189,0xdea1a8b4,0xcfe5fa17,0x52c5ac88,0x11437664,0x444a4d4e, + 0xaf9e9750,0xc2522308,0xd30c6b3b,0x78b1d0c3,0x4c6df477,0x2edae5f0, + 0x2ee88dd7,0x53131d9a,0xacc93e34,0xc4e380ee,0xa8db0e8e,0xd499b1ac, + 0x7f5d49d7,0x77348c16,0x1556ccd7,0xc9663257,0x2611d13d,0x65ce0e8c, + 0xb5a2fdcc,0x2c95fe66,0x8658faa1,0x26698832,0x31c32c98,0xda87d1f4, + 0xfcd91907,0x46650598 } }, + /* 79 */ + { { 0x6b4a5efa,0x4c6c13cc,0x1d07b265,0xc481989b,0x8bdc69c0,0x10b966ce, + 0x2c2531d4,0xf54cfaa2,0xcad0a100,0xcb5f1808,0xee5da449,0xbeb52538, + 0xbedd83cc,0xa6240085,0xd6255c78,0xe792dacf,0x2062058f,0x88371906, + 0xed1658c1,0x96615e83,0x7d28d542,0x4b549b27,0x83b75df3,0xeaf127db, + 0x17fbb942,0x4f60df6d,0xf6f7c930,0xd08631db,0x6018789f,0x17c38f98, + 0xb9a9280c,0x0c43574a }, + { 0x1d20cad0,0x76eb324c,0x8c61108a,0x90decb09,0x6f06d36d,0xa6e9d39c, + 0xbc0da197,0x6cd978ba,0x507ac5ce,0x5948b1c0,0xc5497eb5,0x2bd47164, + 0x4d5914e3,0x2a9c4c0f,0xa759f03c,0x772c5046,0x69ac847e,0xe7d7328a, + 0x3048b330,0xa8d57d0c,0x40f7bace,0xe60034e0,0xa85f1790,0x823d9193, + 0x5c859736,0xa6e9b66c,0x679e1022,0x22ca2c7a,0x09023fa4,0x00e7a19c, + 0x2726d5b9,0x324999f1 } }, + /* 80 */ + { { 0x7c834915,0x667eaed6,0xbc5eb64d,0x9f77aa6a,0x25d62011,0x729ebcb6, + 0x699fd9c2,0x0aee24f2,0x2b8d4f6c,0xe1eb5874,0x14c976d6,0x7f12710c, + 0xf6d9ea65,0x91390335,0x06b50064,0x668b7049,0x0876ee4f,0x65969a0e, + 0x2f9d9360,0xf901bf3f,0xb499e3ce,0xfb1a8651,0xf2dbcaaa,0x80b953fb, + 0x973b06b6,0x312cc566,0x3af36c64,0x3534d9c3,0x10ffd815,0xe4463a52, + 0xf18c2b91,0x57ea2b4b }, + { 0x8aa0f2f2,0x00f5e162,0x0e46bcaa,0x8c7e75c5,0xa4a2c42d,0x97ab479a, + 0x14baa202,0xb4f308ea,0x6943cc2e,0xa901bd14,0xeed58804,0xbb125fee, + 0x9d180f7c,0x6502c8f9,0x1580c61c,0xe5353919,0x27101ee3,0x7e278069, + 0xfaa72717,0x7a0a40a1,0x4c75b153,0x32edce02,0x538f1c22,0xda23660b, + 0xbe307d2e,0x4d511e98,0x9baee0b4,0x24276e40,0x7ff1f307,0xa78c3927, + 0xea7935c9,0x60480b46 } }, + /* 81 */ + { { 0x3872ece3,0x31087d66,0x955b70f8,0x5f29be7d,0x9cf95bb8,0xb50b4fc7, + 0xdbffa621,0xbae3b58d,0xe022ba5d,0x0e61d280,0x4181449c,0x78ae5117, + 0xcf555485,0x0b132840,0xb8ce0b0e,0x800ed1b6,0x78d5de3d,0x35dffdd5, + 0x69a56b47,0xf7e42374,0x8d910ae7,0xd5e32369,0x6313c7c7,0xb6ff52a0, + 0xa92de9e5,0x5a2fe20d,0xd12110bb,0x41b347d3,0x40c16f23,0xc5905edb, + 0x9a8f88cc,0x0774a0d3 }, + { 0xe3b6c106,0x3ae181ab,0x8de150b7,0x4ebe163f,0x6f354836,0xcf75b82f, + 0x3ac7ac16,0xaa0d2063,0x291722af,0x5c680668,0x11545553,0x73941e61, + 0xbf5de3f7,0x17127e38,0x1afb41da,0x32cfdf03,0x87bc8663,0xc6893c91, + 0xa62c9c99,0x75046744,0x962c1947,0x96866e2d,0x378cdf4c,0x489ec8df, + 0x3407fa32,0x3a60709b,0x551290d1,0xd37d2159,0xbab92273,0x9623d303, + 0x2432014b,0x08151954 } }, + /* 82 */ + { { 0xfb7b2108,0xf9236d89,0xad75f9aa,0x3ecc83cc,0xb4e1da11,0xf7c72b15, + 0x0315c362,0x552aeaef,0xf272fe3f,0x11e140ed,0x87843ee8,0x99d79bf6, + 0x1d9bb25b,0xce6b54fd,0x5b1bad74,0xb20b0e21,0x5b84c90d,0x54a0214f, + 0xfca6cec9,0x459bbf52,0x9e4df76f,0xe363c48d,0xd64cf17e,0x3045f84e, + 0xf62ada48,0x8402a167,0x6a74ca01,0x2c9e1bf3,0xf691c42d,0xe8cf9d41, + 0xc2c4b874,0x5abf2178 }, + { 0xf3b3bccd,0x4777966b,0xbe3e0caa,0x0047e0f0,0x8c7d5043,0xcb8383b3, + 0x946fd5fc,0xe77e3baf,0xe9ec0e87,0x79baa785,0xc8a18d25,0xd83c557c, + 0x25befcfe,0x9b96e5af,0x98c71b61,0x4f05d15e,0x77e62da1,0x081f991a, + 0xcbaa3821,0x1c6ec781,0xe54d9bfb,0x7522f65d,0x44ed1430,0xf5d05573, + 0x95cafdda,0x3035b31f,0x6378f5bf,0x47e67f43,0x5270b9d9,0x029f7cad, + 0x4d916a48,0x15ad1587 } }, + /* 83 */ + { { 0xaa588ae4,0x00de2ece,0xa371a232,0x552ebc58,0x71230444,0xd00ea934, + 0xe4b1832d,0xafbfa67d,0xb689e843,0x29216341,0x61f4e2e8,0x1f96bbbd, + 0x04c29dc5,0x95420684,0x42317fd1,0xc7fe3827,0x63483162,0xe0a0aec6, + 0x0700184f,0xfc2b94d1,0xfe1fbd85,0x07219973,0xfb074352,0x648b6ab1, + 0xc46e5392,0x23bbdaad,0x00fa56ff,0x0db8dd1f,0x866725f6,0x104815eb, + 0x52e81963,0x3f9c4cca }, + { 0x32ce637e,0xff36b297,0xf5d25cdd,0x81a15f2d,0x8b02ad97,0x1a1d052d, + 0xcfbab3e9,0x2e5f3bbc,0x614eeb75,0x60d2cbd7,0xcd5a793a,0xd4491843, + 0xcdba2144,0x2242cf75,0x88b99766,0xa20705e7,0xec77e132,0x64e12cc0, + 0xb61a9b05,0xb1c14df6,0x74825b5a,0x8fd97f04,0x3da31223,0x95604821, + 0x4d30c70d,0xde486727,0x1c12ee69,0xbcab8f15,0x668d893d,0x5dc638b4, + 0x223f574b,0x6479dad6 } }, + /* 84 */ + { { 0xb05f2b26,0x569044f3,0x80b9f76c,0xb35a294a,0x4290f6ae,0x8839fe28, + 0x026a5877,0x761cfb23,0x2e5ff9c3,0x768926b6,0x0b11c576,0xbae6cd20, + 0x72a03efe,0xdc857756,0xe1bad63a,0x0cae074a,0xd709d99c,0x3fe491a1, + 0x6501d9c1,0x76c5ded6,0xc32aeff7,0x1da6eca1,0xc57683e8,0x50849d55, + 0xdf98d847,0x9e392e9c,0x64d9a564,0xfad7982f,0xa37b98b2,0xf7c3bdb7, + 0xf0860497,0x1fe09f94 }, + { 0x7648cc63,0x49a7eaae,0x67cfa714,0x13ea2511,0x653f4559,0xfc8b923c, + 0x81a16e86,0xd957619b,0x3c864674,0x0c7e804b,0x1616599a,0xfc88134a, + 0x0a652328,0x366ea969,0x4bc9029e,0x41532960,0xae2aad2b,0xef9e1994, + 0x7f10bef5,0x9e2a8c52,0xc67bf860,0x73dcb586,0x844cc25d,0xf61a43fa, + 0x74eb3653,0xd74e7eea,0xdd240f02,0xf3356706,0xfd83bcb4,0xeec7694c, + 0xdb62526a,0x4de95786 } }, + /* 85 */ + { { 0x3deac2f7,0x4867d315,0xb61d9a8e,0xa084778a,0x0ab7b2d5,0xf3b76f96, + 0xcfdf4f79,0x00b30056,0x31ab8f4b,0xd0701e15,0x9c779d01,0x07f948d5, + 0x82675371,0x7c994ebc,0x48bad4c0,0x1104d4ee,0xbfc9d058,0x798ce0b5, + 0x309fa80b,0xc7ca898d,0xacb33eaf,0x0244f225,0x5b2f3175,0xd51e8dfc, + 0xa4d7be34,0x3e49ba6b,0xbda02b43,0x1760f4c7,0x4435275a,0x37e36a7e, + 0xe636980c,0x1c94418b }, + { 0x09dc1414,0x43a21313,0x43c93537,0x060765fc,0xdf5f79ce,0x6ff3207a, + 0x85d4cfca,0x6f18b1fa,0x63e995ab,0xf5c4272e,0xa82b3002,0x121a09e4, + 0x97147f16,0x82b65d1b,0x20a7fe26,0x4993c20c,0xe6716726,0x99c9cb98, + 0xfeb440a0,0x5a02d673,0x251b4bc5,0x3f3fa9e1,0xa05338ea,0x75dbc474, + 0x7b09f6cb,0x3cb4044b,0x80434609,0x6767da18,0x098ceac2,0x97851422, + 0xb55235ba,0x611bfbb2 } }, + /* 86 */ + { { 0xf00ad2a1,0xbdbaa55e,0x14a290d7,0x29efa85e,0xe92b1694,0x3b4a4768, + 0x11ec8130,0x67111bcd,0x88bd27b2,0x0e425702,0xd9a03c06,0xf28cf2a3, + 0xf318884a,0xbb7c8d2d,0xe3aaeb20,0xe2ea1462,0x43b85d77,0x33535804, + 0x554ee9bd,0x81ee4482,0xe6aa198f,0xeb2eee9e,0xc26c5944,0x7a5aa804, + 0x82ab167c,0xa0ef2da5,0x02fe21a5,0x5a2ab476,0x3370298e,0x169cb3b8, + 0x0eb3aa8d,0x86e6c544 }, + { 0x0b793d9b,0xede03321,0x1ddb5ece,0xf79fade1,0x68930b64,0xf73fda92, + 0xfe4fd1b2,0x06aad97d,0x92a4dc88,0x073a5b1d,0xbc976d75,0x8af8cbd8, + 0x63ce26c0,0x60b4abb1,0xdcb1fb06,0x9c8300a9,0xda95b3d3,0x335a594c, + 0xb37eac87,0x1f97d7d4,0x20eefaab,0xa3d2eba2,0xf3e828c8,0x3258c906, + 0x85ab7781,0xc832616f,0x8c28b617,0x72597192,0x3233b82d,0xcd7196bc, + 0x19fa126d,0x83867eb9 } }, + /* 87 */ + { { 0x22474edb,0x774fe73e,0x1a84e1ae,0x2a766394,0x9c6dd6e3,0x270329ad, + 0x14f8bf5d,0x00c4a415,0xd2267b90,0x3ce2ea37,0x11d24fae,0x12753015, + 0x263a1b78,0x7c14d854,0x1ae0b206,0x20c8401b,0x081f49fc,0xf32a011b, + 0x959c6df8,0x1e8123fb,0x800e1d06,0xa328dc7c,0x24259a9a,0x5876a378, + 0xb7ef6c37,0x23ada8b5,0xa93d4c9f,0x023f6b6e,0xffb6389f,0x89f5414d, + 0xe628b39e,0x4b26bba2 }, + { 0x5d318454,0xd30b1cb4,0xd7436cb6,0x123b749f,0x568a7461,0x3110c726, + 0x1c84fd1e,0xc85de123,0x08403d55,0xa5f8d6e6,0x9b1fabf8,0x395b6e13, + 0x3cfedce0,0xfe6d68c3,0x94b91110,0x1d90381f,0x2dcc6eb7,0xf0a8ea81, + 0x7e90ca2b,0x59e80413,0xc8a25c5a,0xbeb5fc07,0x5d84663c,0x009c253a, + 0x910b6a7c,0x00b15073,0x4108f8d5,0x8607da4c,0xcb901e65,0x02c3d9c3, + 0x2c9615c6,0x4d697bc5 } }, + /* 88 */ + { { 0xefa8fb40,0xe0db1ef0,0x5ba3989c,0x29021c5b,0x809d19df,0xa8d6fb15, + 0x4c1219e1,0x6b787b73,0x14ef05e2,0x6417e168,0x8f9796e2,0x449342db, + 0xbf84421b,0x2f878a5e,0xe94a4536,0xe71916d7,0xae119693,0x9818bba3, + 0x5768804e,0xec674be9,0xf8424f8a,0x0a26074c,0x466ce6ab,0xdbc93b9d, + 0xc920078b,0xb3f15a98,0x3870f1a3,0x9d10fd0d,0xe4e785a7,0xa61241d9, + 0xe6c8cd80,0x76ca87a1 }, + { 0xe02e48b7,0x4357fb56,0xcc09e9c6,0xfbd14b13,0x24069cf0,0xdb5f2435, + 0x2c3b01a9,0xf878165c,0xe6956dad,0xe549e7c4,0xbbd60b68,0xf2fe9538, + 0x059dc653,0x952f856b,0xb377fe9b,0xd3f60225,0xbfe908c4,0x6a0c7328, + 0xbc8f5f2d,0xce6aa2d3,0x24425050,0xf7213443,0x3d3b3ce5,0x17e1266a, + 0xc1677512,0x75b5e43f,0x37fb894a,0x15927062,0x2be3e375,0x15260753, + 0x6da3b7be,0x27e7f2c6 } }, + /* 89 */ + { { 0xe6a15883,0x638f65ad,0x66afdb33,0xd4a7e68c,0xd3f12de5,0x6207b6ab, + 0x37b87810,0x1c6ff950,0x64acf6d3,0xc0d44cb2,0xf2be78c2,0x163ac601, + 0x1636980e,0x1c63cc5a,0x95c9349b,0x3e92cfe8,0x41ec7220,0x7738e0d8, + 0x2d5fa961,0x6169d764,0xc3e028e9,0x2aa776c1,0xb16d5409,0x93dc5646, + 0x706df4d9,0xa0b27fb5,0xce9c6b97,0x9e991170,0x53c85f40,0xea8e42be, + 0x83246528,0x02e96437 }, + { 0xae78ea1f,0x91540add,0x7b670e96,0x51a1b74d,0xf7006826,0xf9936441, + 0x7d7520c7,0x8f97d6ea,0x69ce12e1,0x0faa6a02,0x79208342,0x2590aca8, + 0x75614436,0x7a483863,0xf381408f,0x07c6149e,0xd7853406,0x733bf584, + 0x9abbb6f7,0x8761b010,0xf528a09a,0xe4eb249f,0x2e00ae3c,0x08781ed8, + 0x2178effa,0x864c1b25,0x9d513a7e,0xcc1e62a2,0x1919062f,0xedb8b94e, + 0x4f16527d,0x739f53da } }, + /* 90 */ + { { 0x924adc5f,0x7a5f4a88,0xa818f56d,0x95646c16,0x7795f954,0x0ec49129, + 0xd19c5400,0x2b48753d,0x205912b4,0x16fa236b,0xe87a4946,0x6b3d65f3, + 0x045fd066,0xa7174a01,0x12a5e140,0xb6350313,0xa96b8623,0xa79c4b44, + 0x9ab003d5,0x7a339d65,0x3826f31a,0xc72f30c6,0x6f7090cd,0xb4e7390c, + 0x906ebe24,0x59ac6c36,0xbba4505a,0x39a7f06d,0xc58c413a,0x839991e1, + 0xa20e0e84,0x020c23ff }, + { 0xafc74661,0x120e4ada,0x277fc065,0x37bbcf63,0xb6dce799,0x41049cf6, + 0x7b161ba1,0x5b8d6b53,0xa9610fb2,0x22218431,0xdfdde769,0xde9ec9d1, + 0x42d80630,0xd32bfa4d,0x6244df4b,0x3885702a,0x45592dfb,0xcdedd1ed, + 0xfb4e01b8,0x0e1df45b,0x86e215b0,0x8f4bded2,0x6a937e6a,0x80935487, + 0x8130f723,0x415278ba,0x38a821f8,0xc6dc4692,0xfd8b4f8a,0x2207b119, + 0xf9269cef,0x76e7bf53 } }, + /* 91 */ + { { 0x27ebd187,0x5f128428,0xb65aadbb,0x8d3320ab,0x72258695,0xb042765a, + 0x8f0986ab,0xda3f33f9,0xaebff503,0x411807a7,0x825f71a5,0x25c776ca, + 0xff7df24b,0xc0de7bed,0x165f1fb4,0xda8b0f42,0x731f3ae3,0x5f3ff737, + 0x193e0a52,0x4cd1d7e7,0xb6b3ba46,0x8df84aa3,0xaa1f3782,0xba84b897, + 0xe7733ac7,0x6e7960cc,0x50981a21,0x4d46d6ab,0x7cbb80ed,0x1ec12c25, + 0x2b96ef09,0x79e7ad27 }, + { 0x8f30caae,0x3cd970dc,0x0a6ebef4,0x85cabcf1,0xc714616d,0x63c1863e, + 0x519e3a98,0x1c50db0b,0x64cb13d6,0xf39b8963,0x22547b69,0xdf67d81f, + 0xd67db0cc,0x7157abb9,0x889491b7,0xccca25ba,0x7a27e0dc,0xf689207c, + 0x0fd43281,0x34ae8fbe,0x5720ec09,0xa5d91f73,0xcdfd7bed,0xb2f61909, + 0x4a039e32,0x1ec10232,0xdb0d8fdc,0xd3c3d65e,0x4fe5005d,0x32c916c8, + 0x4c0bea94,0x7f8c37ac } }, + /* 92 */ + { { 0x43ac05e5,0x33ec1e54,0xcd8d3825,0xda4a4da4,0x88bf9e2b,0x86d88c0b, + 0xb53811dc,0x34d71dd0,0xa3c3aba4,0x655040d2,0xb61611be,0x2bc40949, + 0x279a4fa0,0x1c2d426e,0x3b065ac3,0x535a5aa2,0xc52ea890,0xdaa8a32f, + 0x9fddad22,0x5a5deca7,0x2ab3b26f,0x911f05fd,0xf37cd81e,0x5dace7db, + 0x90d16b8c,0x0e0e44e7,0xe4f5894e,0x15e68aed,0xfc92a74f,0xafe04999, + 0x970e7c2f,0x1d7703aa }, + { 0x3f0062a9,0xa8a4c81d,0xd96a20ba,0xe31eb2b8,0x864bd101,0x66dd98df, + 0x4413b614,0xba05f592,0xe9a555f8,0x51a67a0d,0x2e4b52d1,0xacc2f097, + 0x7184ab23,0xab5daaec,0x7c7f691b,0xce08b43e,0x76c427f4,0x520e530b, + 0xe423ebdc,0x7d352069,0x34df14ce,0x6b5e39e8,0x446305ac,0x3dcbf295, + 0xfe34cdc1,0x682cb2e1,0x111f5afb,0xd4ac45d1,0x47f296f9,0xc5ef63cd, + 0x93c20871,0x0a2c40ec } }, + /* 93 */ + { { 0xaf5747db,0x09bc384f,0xc06ab86b,0x3bad6086,0x9e7c1547,0xa406882e, + 0x55977abf,0x2d5326d1,0xda81deb0,0x063a9a05,0x524b6111,0x9a86e4a7, + 0x4ab2eb90,0x1402f87a,0xd5c600ba,0x7d0721d4,0xf289fdbf,0x1a2fd9a9, + 0xecde6f07,0xf5dce66d,0xdab9fa73,0x62171277,0x6c474bab,0x6d2dc49f, + 0x76eed033,0xdc017e1f,0x4da825d3,0xb97175c0,0x54b05e43,0x6c297e3d, + 0x56c9c87e,0x2efb4546 }, + { 0x8b21c064,0xa4712b00,0x4a70629e,0xd186fe42,0x9b74f0af,0x6435b340, + 0x7ec9e629,0x6965aa43,0xc4c60d08,0xdda14673,0xbf3057aa,0x0b656670, + 0x3ce86f60,0x7f05e840,0x04401a16,0xc05073a9,0x294e607e,0x16b1e638, + 0x69cf7046,0x20783252,0xe8ce7d3a,0x2941141b,0x7577053d,0xd38ad8d3, + 0xcaa6630d,0xdba68fb3,0xe9504350,0xecbeaff1,0x1d2d760b,0x9f5166d5, + 0x462891e4,0x337532ce } }, + /* 94 */ + { { 0x3a00bb9b,0x3f111853,0x45f66685,0x2d2ffbae,0xd4aee24d,0x9ae11a85, + 0x0341856e,0x18ba1e1b,0x2731349f,0xa9ac8178,0x545715b5,0xc13dfd4a, + 0x5daad2ea,0xa5f7423c,0x535b76a7,0x30a483b9,0xff873e9b,0x92e9ada4, + 0x723a1055,0x15662d84,0x8edac4e0,0xb935497b,0x39d8fa70,0x61b6441a, + 0x40d1589f,0x1541d756,0xf0a05f0a,0x62994237,0x6bb28908,0xfd8b0034, + 0xd4cd32bf,0x192a2b5d }, + { 0x365ced07,0x63576628,0x05de1d1f,0x029f32fb,0xbf40a7aa,0x6d17b9bc, + 0x9bb50a47,0x1b1b2a08,0x795a6278,0x9389abbb,0xb34fc19b,0x52cff60f, + 0x387d8739,0xf3ab9492,0x6920ccd6,0xa8f053e6,0x63a9b4f0,0x3ef2dd4b, + 0x51e82129,0x9ab0ede1,0x0838bfa1,0xafba0c0b,0x9ffc11be,0x2bd5a7ac, + 0x95cc0878,0x058bfd95,0xf8c2f0c6,0x686d48a3,0x1d9b31ba,0xc33abaaf, + 0x3bc0c268,0x632e2289 } }, + /* 95 */ + { { 0x15a1ccca,0x1c851d20,0x7e522bc3,0x4efe290c,0x18eab053,0x0b741d55, + 0xbc85e217,0xae656197,0x01cf8b29,0xae13141e,0x66948478,0x2e2cb593, + 0xc31bd8ae,0xeb57bb0f,0xc264e788,0xdecef5d6,0x9cb96d86,0x6fa856cc, + 0x279183da,0x2db16813,0x383d796a,0xf03f3820,0x1d0c6fed,0x58a456ff, + 0x8a6abd9b,0x25589805,0x83f96f19,0x339f52c5,0xda7e9ea7,0xcf6ded8f, + 0x5d1ccd45,0x68c3d9c1 }, + { 0xe6b392b7,0x67e26265,0x775d9509,0xcec1d9bf,0xd76514f7,0xe16abcd4, + 0x0de72e1c,0xd86f59b2,0x1adfb033,0xa66e43cd,0x05e457cc,0xdb344340, + 0x5681daa2,0xb67a7916,0xf0114731,0xc32e7bab,0xd3b1e961,0x066fe16e, + 0xf63d26e6,0x924e298e,0x541add6d,0x9bea0dd8,0x9982f971,0xef9500df, + 0xc5f076ac,0x5c876e63,0xb23d396b,0x55e12ae5,0x2ec6747a,0x09efbb36, + 0x233286a5,0x8f2055ee } }, + /* 96 */ + { { 0xb82c1af0,0x4a4ab9e3,0xf2cae264,0xfc65e9e7,0x60187d46,0x4feaac0a, + 0xe393b363,0x27d3f335,0x819bacce,0x9c9f7c00,0xb8aa6611,0x3f7418b5, + 0x372aae95,0xffa94557,0x8db38589,0x937d7804,0x6f1fbc1c,0xd10c86df, + 0xa2f0a0ce,0x48aebd89,0x367439eb,0xae5d5fa2,0x3f17d2d8,0x103a6a0b, + 0x411d9894,0xf233f68a,0x218b67a2,0x7fece8b3,0x2319bf06,0x0422540f, + 0x340d322e,0x1292c8c9 }, + { 0x0386463d,0xf5eb5587,0x0371d97f,0xd4bbc2b2,0x0b819c5a,0x1b364571, + 0xcf04ad41,0x0cbb42d6,0x66939ec1,0x5d819c76,0xa01847e7,0x8745ac13, + 0x1c7232e4,0x4f704b02,0xacb05780,0x2c9e58a0,0xb561e295,0x9523b8b3, + 0x79f9ba35,0x3384df00,0x1eaa9628,0x78231fc2,0x8aea2b90,0xa2eac54f, + 0x30d1c263,0x8075ed77,0xfb339000,0xacb44ed5,0xf011293a,0x92546ac2, + 0xeb821764,0x7c78762b } }, + /* 97 */ + { { 0x067902b6,0xb8f7d6fb,0xd1735980,0xb2823a43,0x59741ddd,0x062cfb12, + 0x4033f95c,0x6e391b07,0x68589b8c,0x3831d0a3,0x522290f2,0xe3474d49, + 0x222e1f3a,0x4dab14d6,0x53f08d39,0x8f00fcde,0x707f28f5,0x559917ae, + 0x068e607c,0x166aa0ba,0xd7e1f824,0x602713e7,0x4d6a328f,0x7c255540, + 0x9890cd2a,0x0d2e3264,0xeca0b20a,0xf2207944,0x52f4e09c,0x5c98dc07, + 0xd84de81d,0x69403504 }, + { 0xe5407206,0xf8b7b366,0x0d88fa8c,0x1ecf54cf,0xf7272e6f,0x6fefe548, + 0x81ab4468,0xd6531372,0x4e474408,0x52cb5f0e,0x6490737f,0x9e426b3a, + 0x4980d071,0x2576c19b,0x0f272caf,0x91f34628,0x468f31c9,0x78e60a4f, + 0x90844d89,0x8776a329,0xb951582b,0x8a55700c,0x14b1adbf,0xab1af365, + 0xfbd343ef,0x22ebff92,0xb7d81f34,0x32f9fb01,0xba6b30e1,0xad850e06, + 0xbc5f9546,0x6da9e027 } }, + /* 98 */ + { { 0x5c9490ce,0x21eee4c2,0x0df68381,0xa96ec4a3,0xa4a9368e,0xe6c607e0, + 0x4bc262f3,0xd8b0492a,0x460c34ff,0x0846a210,0x28df33cd,0xf7ff7a64, + 0x21827612,0x10c55044,0x149bcd01,0x9d25fce9,0xcfc613dc,0x725611cd, + 0x97f51ce5,0x159f7e88,0x4e8c08b5,0x3fa3bf31,0x75e7538f,0xea156115, + 0x91c84020,0xd1e0a951,0xcf02ad0a,0x0d2268ba,0x058b8e5f,0xa04c6ac4, + 0xb3515912,0x773b40b9 }, + { 0x3631cfd2,0x00ff2cdc,0x807737bc,0x14c4c2d3,0x338a5270,0xd600616a, + 0xb32cabde,0xd0e3306d,0xa70b17ca,0x336738ea,0x79f353ee,0xf2f4aa8d, + 0x576f3ad3,0x712f6ad9,0x89b2bce0,0xe4279852,0xda92ca30,0x05d8f94d, + 0xd8492dd9,0x9891d475,0x4d15e4bd,0x3e06a5ca,0x254eabbd,0x4725d4eb, + 0xc0ed513c,0x31394ace,0xbbfaae6c,0x7e0f9859,0x833fd137,0xdc125546, + 0xc56c4f75,0x12b46385 } }, + /* 99 */ + { { 0x932951de,0x810dbebd,0x5aa69c94,0x96959d42,0xecb2f08d,0x5fc49c04, + 0x2250b82c,0xac74f0cc,0x3aec4e1d,0x96a439a5,0x90499acd,0xc33cab9a, + 0x54d9b3af,0x2fccde66,0x3863ae8b,0xf4af285c,0x46febf88,0x2373373e, + 0x3c9ab7ed,0x751d672c,0xfe12020c,0xc1c51130,0x52f3e56e,0xad82402f, + 0xa4a64a81,0x3489ab7a,0xd9f163f2,0x0a1fb661,0x0e553317,0x17c69be1, + 0x7d88d417,0x61c1935e }, + { 0x3492ae43,0x2e722d9b,0x0538f05a,0x1ef89d95,0x200aab63,0xae77e588, + 0xeba4b117,0x2872c120,0x3a461cb8,0x5c2432c8,0xcb938f26,0x315b3434, + 0x8c4c7dc0,0x05bf2ac5,0x596b378d,0xd2e501dd,0xcb890c30,0xa8506c9f, + 0x7c361f0c,0x3d0af461,0x5a35cbae,0x21f7b718,0xf3fc0138,0xbd1035f1, + 0x8b248edf,0x74628af5,0x48c9cae0,0x8d6421d0,0x2ca18773,0x75e3da39, + 0x71d3db94,0x27ad0df2 } }, + /* 100 */ + { { 0x305b5aed,0x9e3bda79,0x5998d6a7,0x2c67d4a4,0x0f7eb700,0xc855e1d3, + 0x147d1c44,0xc18a7e9e,0xc89540ed,0x3ea99618,0x7e6bfd20,0xa53be20a, + 0xecc14437,0xc9487e64,0x34ef85c6,0x72979207,0xd5e1ebd5,0xfa0d4e71, + 0x4d48d6b6,0xfda2b1e6,0x66e200d4,0x782a1e05,0x5a5366a1,0x2a3c70da, + 0x1a473738,0xfe3fbd2b,0x7fe020e8,0xd7ef8c06,0xeacfb665,0xec686fde, + 0x6dd1542f,0x5d9b5e27 }, + { 0xcb3e472e,0x3637c5a5,0x30a1405e,0x2153d927,0xb4498558,0x009992e5, + 0xf39a0851,0x18f00ccd,0xb5c6c560,0x26237c11,0x1343540e,0x418ed408, + 0x7e7f3184,0xfef7cbf0,0xbf48576b,0xecd92366,0xbc94c91a,0x1b75be1a, + 0x4a162276,0x8e1778de,0xc5c6bcb8,0xc52e57d3,0x5ab71858,0x5cc382c7, + 0x3f6e39f9,0xe12c2c28,0xd62735fc,0x4c7e0ef2,0x835a5996,0xe071deb1, + 0xcbb8c766,0x24f891cd } }, + /* 101 */ + { { 0x6778c1e2,0x24ef60bf,0x00d5be5c,0xff49c03d,0x2f01a09f,0xec11986e, + 0xae096e58,0x59a728a4,0x7077984c,0xaabbcedb,0x870ca5a5,0xfb473bd2, + 0x4de30e3d,0x8c928c61,0x4f67abca,0x3fae7f9a,0xec21a9cf,0x83c2b2eb, + 0x9cd9b5de,0xafa70d62,0xc60b18df,0xadeaea59,0x4049b54c,0xd5fef7be, + 0x6dd310e3,0xfceebc76,0x8f6321cc,0x7748efe3,0x18ee8af5,0xfe9c32b1, + 0xd42df612,0x863ac3cf }, + { 0xb85a2fe2,0x0a36fca7,0xee429dc6,0xf3e70d08,0x141c3944,0x8c9ba209, + 0x67272a0a,0x306a8106,0xf968bd06,0xe69a1555,0x153c603d,0xb86f7e47, + 0xef56e4fa,0x9706614a,0x98780b4c,0xc0dc36b8,0x3a1d3263,0x43657fe2, + 0x435522c9,0x01f97a86,0xedfef679,0xd91897f6,0x6daa17a0,0xebbe31d4, + 0x85accfbd,0x6f179100,0x8f9fc1de,0xe0da6e32,0xe1e7142c,0x1c9d53db, + 0x8b86725a,0x3e3f1b1e } }, + /* 102 */ + { { 0x7b7fbf05,0xb7ea15c0,0x1f1a3882,0x992f11b6,0xd1dcd1bc,0xc9ddd95a, + 0xad0f7e8b,0x31f5b7fa,0xfca7ab79,0x2936e5eb,0x19a55be6,0x30f417dc, + 0x43cde554,0x1f6f4e43,0x82f044bf,0x971f5e65,0x4288c408,0x73c3b8e4, + 0xb807f575,0x61aac59f,0x818b58f0,0xa64ee2dd,0x97a3b0d3,0x6f7a0a60, + 0x0394b058,0x8b85ecc8,0xbfb3517d,0x9a059474,0xa79c3f06,0x89ad5977, + 0x700a8025,0x81208ed8 }, + { 0x14c4ce37,0x10935099,0xa1aa48a6,0xf34bb843,0x580d58e8,0x86007024, + 0xb375b8ba,0x6db42c49,0xed3bde83,0xac365524,0x649233b6,0x5521e1b4, + 0x64dd946f,0xbc7cc5d5,0xbfb5b6ae,0x9c14b035,0x0146c1a3,0x7f22ba18, + 0x872214f5,0x0b62fbbc,0xb4921764,0x3acfd7f7,0xcb4d6df1,0x5ff10da1, + 0x62600a91,0x660e2620,0x81d9167f,0x7ac7da9d,0xb6e7a199,0x6e8e260c, + 0x80deb3c2,0x44383fb8 } }, + /* 103 */ + { { 0xe44f9af6,0xe107f01d,0x8cb1fa1c,0x36381a4d,0xfb7dd493,0xe65be3ec, + 0x26a8839f,0xd0b8435a,0x3ec789d8,0xee60f915,0x2bcc5e1f,0xe25fea50, + 0x7e44a81c,0x0477c0c5,0x230ba5b8,0x349e9f83,0xde180dd9,0xdd42f32f, + 0x64a3d11c,0x8b039eaf,0xbeb7083a,0x80ef884e,0xf12742cb,0x288e60c4, + 0x720a0262,0x44156cc5,0x7253b77f,0xcd547de6,0xa6013a59,0x9829a6ec, + 0x0d548445,0x8aee708f }, + { 0x32c54409,0x18f22d9c,0x75ebaac4,0xa9ebfa46,0x86284981,0x90e2e928, + 0x6b3a8e0c,0xd0201f6f,0xbd77641e,0xc973016c,0x70170575,0xf926f2f0, + 0xfec0ce01,0x4984048f,0xf319d304,0xbf696211,0xc91a88c4,0x74b5c844, + 0xe0030a82,0x4c40fbce,0xe4f6d521,0xbed67525,0x29d67d1e,0xaf7e47cc, + 0xc21d3536,0xfa307db8,0xbbb29405,0x56b6c46a,0x033e805f,0xf059a7e3, + 0x6096a5a0,0x970f61fe } }, + /* 104 */ + { { 0x1bec8e4a,0x1bc53d23,0x35a6034c,0x8809ac14,0x509e464d,0x4ee081da, + 0x8a488235,0x496ae1fd,0x325864b6,0xa1ae9863,0x74cd069f,0xbaca13e9, + 0xb1d8a6b4,0x3738cc58,0xe76b9da4,0x5fa71f58,0xc7eb16fb,0xc919be88, + 0xad4e429d,0xf5c8f13f,0x2499f9ed,0x4583b671,0xa10d8bd7,0xbce20115, + 0x5790bb7e,0xf66d7605,0x482b78dd,0x9316aede,0x75f855fa,0xe0d8fb2d, + 0x5a7dcca7,0x404b5b94 }, + { 0x517a15c7,0xf9ee682a,0xef880202,0xaae4cfbc,0x5106a354,0xcee2c139, + 0x170febe7,0x5de60192,0x73d0c54b,0x589e39fd,0x8c9092b7,0x195c7135, + 0x0a7bfe5f,0xcb7ed53f,0xf61cc979,0x2bd9242a,0x5395f7d9,0x8d2ef16c, + 0x70b32f09,0x0d4ac1ca,0x52d185c1,0xa587526d,0x942d6195,0x2932b04a, + 0xa500b0ac,0xfe25a979,0x562fd230,0x5fa1f4ae,0x20da253c,0x60f55af2, + 0x83146002,0x7faa11b5 } }, + /* 105 */ + { { 0x6e402149,0xb0ba4f0c,0x963cc119,0x3584cc1d,0xa6527476,0x7740dc1a, + 0xc95715f2,0x3f77ff75,0x3f89fb0e,0xb2f234ad,0xef9be3ff,0x55159032, + 0x04237e82,0xfc9fb21d,0xa153ed93,0xeb2eff38,0x10041d13,0x89d53ae0, + 0x7f1bd828,0xcf2e545b,0x43953ea5,0xdd4a27ce,0xd85e75c8,0x00d2e5d4, + 0x241be1c3,0xeb93ed62,0x0242032d,0x1e53f25f,0xc3a4e701,0xb9957636, + 0xed98febf,0x14b63a52 }, + { 0x71c43336,0x7610b553,0x23a4824b,0x19dfd4a6,0x0286051b,0x7b97a2e0, + 0x8f5f1edb,0x86abbb9c,0x9b67daad,0x67a57d77,0xcd5ffafb,0x8ace506d, + 0x89ac3c63,0x85da9f95,0x75a3d150,0x081cbaa8,0xe9346ed2,0x03353d8f, + 0xa1f9a02d,0xb2ab61f1,0x3a659c71,0xb0cb0937,0x4f5df8a1,0xb7e0e30b, + 0xeb7d5a1d,0x77c4c741,0x728e5cf0,0x8f046c9c,0xf7c171ac,0x32dd0bc7, + 0x836d2655,0x02485873 } }, + /* 106 */ + { { 0x75a4cd8d,0xcd40dd23,0x97bcba78,0x132ca433,0x258d61f5,0x30c5cd84, + 0xda1e8e68,0x0a7ec059,0x1d65d40a,0x07a8f171,0xf4350d76,0x869e655e, + 0x5983ae42,0xb98ce6f0,0x9d8bebd0,0x7b61391d,0xb1ba5d49,0x3a529e25, + 0x1f6b2cf6,0x46f732e9,0x3fa3b629,0xbd66ec6a,0xc3ef0ed2,0x397950ec, + 0x5f08b476,0xee9008cb,0x965a0e2e,0xfd6be425,0x1177bc87,0x78ed513c, + 0xfe512dae,0x6798cedf }, + { 0x1b97c5c6,0x49e3f8fd,0x78c3b33f,0x39fbab3e,0x40f595ba,0x44274412, + 0x5d7d4376,0x174225b9,0x79c44777,0x880b3fcc,0x3296b245,0xdc3aca83, + 0x1734e184,0x55913df7,0x9c934472,0xa4db23d3,0xd1420a11,0xcebb3733, + 0xf3608bdc,0xb9d20cf9,0x30cfe13f,0xa618acf6,0x5f30874c,0x75f06b31, + 0x9f0005a5,0x506efe7f,0x01bfc9db,0x8aaea78c,0xf78e7c41,0xf9179255, + 0x52e96395,0x3ea7aed2 } }, + /* 107 */ + { { 0x5b06ae25,0x98617e04,0xcb5750ef,0xbcac148d,0x604c2ba2,0x91ea2f0e, + 0x76b78975,0x00c19f6b,0x651da181,0x79b9b6d0,0xc945705b,0xf3225beb, + 0x5c005bf1,0x30b435f3,0xbc24d86d,0x440b4482,0xd6373777,0x2b8f0996, + 0x1c44b4dc,0x65fd6c56,0x30906999,0xe9405ee6,0x08aa1ec1,0x19ff0924, + 0x3d2f2895,0xeef3246a,0xbc746797,0x016c3765,0xd0705f7e,0x62d2569f, + 0x05250044,0x6a8ad39c }, + { 0x46be7282,0xe45f020d,0x21380f12,0x9405afed,0xd5da6ad0,0x4cdca5bd, + 0x7f8be61e,0xc2d6f184,0x596b8178,0x20132953,0x7a8df954,0x8d3b1e7b, + 0x39572b4d,0x757c61bb,0x80cc3b56,0xd749b57b,0x37b3ffec,0x9590ff93, + 0x145dc94d,0x39bbb653,0x2335e573,0x70c1c606,0xf763feba,0x9c2e72d7, + 0xcc61b732,0x4768e424,0xaa73f2ca,0x777d2fa6,0xc5cb58cd,0xdee4dbaa, + 0x9cfae1aa,0x1a181179 } }, + /* 108 */ + { { 0x77575ed0,0x6f6ff62f,0x7d1da99b,0x18f14fa9,0x69efd7f6,0x2e72aefb, + 0xddc28633,0xc45ab4cb,0x586c5834,0xb0e20d48,0x39775dd8,0xd397011a, + 0xf4134498,0x0130c808,0xf5115ed8,0x2d408eba,0x0260ded9,0xc506a05c, + 0x19cab911,0x9e5b7362,0xe8693a86,0x4cf508c6,0xcc773617,0x4e71245f, + 0x95d89ca3,0x2f71aa1f,0x607bbc98,0x4bba7c6a,0x212b7fd2,0xf3a515e7, + 0x9230f5a8,0x7d2ddc75 }, + { 0x4ed2cae8,0x3d05816d,0xb9c00377,0x4cf6bc7d,0x646b08d4,0xc23e98e6, + 0x4b9c0180,0xf9ee6c61,0xef9179c1,0xe11c9a13,0x8ed9688a,0xa5b6147e, + 0xd06670a7,0x7afeb648,0x17685275,0xd670333c,0x75f9e8f2,0xa89dd969, + 0x37a68ade,0xbb57228d,0x454cb186,0x21a05d5e,0x063dd550,0x4810158f, + 0x4cb6caf3,0x92dd4f08,0x7854abe7,0x70c4d852,0x6e729d76,0x845969dc, + 0xb1bf40ba,0x5a52f87a } }, + /* 109 */ + { { 0x09ecacbd,0xed019e91,0x7b89bdea,0x6544023d,0x5707371e,0x7cc51f0b, + 0x16c8e217,0x14832b04,0x81259ab5,0xb1aa6682,0x23e361d4,0x6e100f92, + 0xe3a95c2a,0xe593eee9,0x16c10e26,0x699b6bbd,0x9473a13f,0xad487873, + 0xb274987c,0xf1c14dc5,0x2559e2e9,0x57dc0075,0xc3d47ad2,0x8449849d, + 0xdd527793,0x83df278a,0xeefd5b99,0x770e3ec8,0x76bd02a0,0x2ae58446, + 0x3e705ffe,0x17f02764 }, + { 0x29abea1f,0xdda4010d,0x2407ac4c,0x636b9695,0x0433218b,0x96a60129, + 0x163d534a,0xf221fc3b,0xccc20565,0x05ba15be,0x96285577,0x1238e54d, + 0x878804d3,0x1b144257,0xa89a9fe4,0x96fbf304,0x4be642b1,0xc8a7f06c, + 0x6e2b085e,0xdd1a20e8,0xff4a591d,0x8f7f27c2,0xa4a343b8,0xc17b0753, + 0xbb173d4d,0x684b1e88,0x3dc07bbe,0x3accea44,0x4c441d77,0xdb15c88d, + 0x53e5957e,0x0ef0309a } }, + /* 110 */ + { { 0xfa8e5b60,0x4fc25721,0x691c0bb2,0x646938ad,0x0b0a2248,0xe46d4b76, + 0x7de16877,0x863f9ac2,0x2721c630,0x503bb6ef,0x0b67fb02,0xf8c199df, + 0xe07abd39,0x78c1ed72,0xb32f0dda,0xcf9deb7b,0x6c3c89f3,0xaff726f0, + 0x1972225a,0xb7008b2d,0x4f145f5c,0x8f5a6117,0x457c4f37,0x4e0e6f8c, + 0x1c453c64,0x8bbdaa44,0xa6e92c80,0x57be326d,0x5d773561,0xa9bc3fd9, + 0xbb37b72a,0x3d3b6cc6 }, + { 0x9722c880,0x6e6f12cc,0x286b6889,0x3a1b6ae7,0xad2fafec,0xba1cc09b, + 0x43bb8bef,0xad64ad7a,0x97c3f4c3,0xa5af6a00,0xc353a91b,0x2afcb0d9, + 0x69ccbf6b,0xca13fcab,0xf2abc190,0x699a1391,0x23a247e5,0x2dbd5542, + 0x95488d9a,0xe206180f,0x1244cc3c,0xba9e7bff,0x87d3a365,0x29297abe, + 0xfa4ca5e2,0x4054fa38,0x67be1b6c,0xb390623d,0x78f41a44,0x1fa67c57, + 0xc7b544e7,0x2e946e43 } }, + /* 111 */ + { { 0xc60934ae,0x2980fddf,0x164206d1,0x2c3e7eff,0x416ed75a,0xf75e7f96, + 0x5cd0b2dc,0xfac60cf3,0x1faad87b,0xddc4bece,0x9849e5dd,0x753fa87c, + 0x2c1bf1ae,0xc5d516a3,0x14732b4b,0x565dbea8,0xce48696b,0x007ebe3a, + 0xcdb97694,0x40ca74d6,0x65e4e7be,0x3f5cd270,0x3aac4ebc,0x74847c01, + 0x43d6c3a1,0x6762e034,0x467a076a,0x690d8c95,0x1eda677d,0x768d78d6, + 0x0181d8c2,0x0997ce55 }, + { 0x965a0b81,0x9297746c,0xe5e12dfa,0x48b58be6,0x715f437f,0x5573b3c4, + 0xb565c459,0xe425e907,0x1582797c,0x4f43f512,0x8ea5474f,0xe5dafa6f, + 0x13de04ac,0x2aeb8fbe,0xe8a07c83,0xed7f95f0,0x662c09fe,0x3e012a6e, + 0xc742cf17,0xbf96e9b8,0xe28a1c45,0x8ea5759a,0x5cf4e2f3,0x475941b4, + 0xf901a019,0x7dd3c02d,0x70916b2e,0xe7a4deea,0x2fa9b988,0x50b272b5, + 0xd0917fe6,0x96f9f09f } }, + /* 112 */ + { { 0x2c310a96,0x78e8aac4,0xf7a2a734,0x32a98303,0x23962207,0xc46ca83d, + 0xd9541280,0xad131e6e,0x2cabe911,0x5791fc5e,0x841b6c68,0x50cb77eb, + 0x3d3c8878,0xaff93dea,0xf1007bce,0x06541f1d,0x55cdf1fd,0x4ee729c2, + 0x323e3972,0xe0f71317,0xad4d08c1,0xa2de7a41,0xa35e22bf,0xa9912abf, + 0x89b03325,0xa050122b,0x06514d4e,0x8b9e51f4,0x79d3e0ab,0x423c7aad, + 0x40b8fea5,0x71998e26 }, + { 0xceb6ed78,0x40140fcd,0x18534516,0x653cf377,0xe8d60dcc,0x0450b65a, + 0x9dac55f8,0xce6c1a76,0xae05686c,0x8a96a92d,0x12712562,0x2fe44762, + 0xa4f39425,0x747bcb50,0xfc531fc2,0xf0ec6ff2,0x10fe9ff0,0xc97c3447, + 0x9c792cff,0xfb488783,0x026fb019,0x552c5248,0xd804c290,0x4001a29c, + 0x35c8ca73,0x742b5ad8,0x6ee5dfa0,0xc3781f17,0x3dfa4ab1,0xca6b85f0, + 0x0b0d32ac,0x8389941a } }, + /* 113 */ + { { 0xde067dff,0xc0f062a2,0xbcb80162,0xd4f32690,0x0707a2bd,0x98cd990d, + 0xfae4a391,0x5afc63b8,0xb32ad814,0x684f1b7b,0xf199dfb1,0xb0a2dce2, + 0x48f25848,0x2260e17f,0xc2d5e862,0x7393db00,0x338cf171,0x9e88f854, + 0x02acf522,0x00679429,0x6835af3d,0x19157cb8,0xb8a2614c,0x2faa6f92, + 0x134ec46c,0x04ff95f5,0xfb7a8135,0xcf00626e,0xb37a4704,0x454b3d05, + 0x2694ec25,0x1fbfda31 }, + { 0xc8f69c77,0xfdebb657,0xa3df88fa,0x92a8278b,0xc1fb78b4,0x463b5571, + 0x11c71a33,0xd2066a1a,0x089958b0,0x10c88143,0xcf9d67a6,0xb975c7e0, + 0x73037b8f,0xdaa5d208,0x40bf5861,0x5ee5005d,0x7dba69a9,0x300e6ce7, + 0xc962cc74,0x893c3cb3,0x4cf84055,0x0ac98629,0x225c9d70,0x0a7ef63a, + 0xb91e47e8,0xfe184869,0x8c2f84be,0x1b9d7deb,0xc0e278bf,0x67788915, + 0xc426f19e,0x4f9488ca } }, + /* 114 */ + { { 0xdd51b8ce,0x610dfcd4,0x36230e80,0x08579278,0x36599562,0xedc7ff1c, + 0xe2cae877,0x905ead4b,0xe7967608,0xa1c325d9,0xbd38926c,0x3e39eddd, + 0x5f6f0a4e,0xda92c868,0xf47a0fa4,0xe16f800a,0xe5f60aab,0x50b4db5b, + 0x983853d3,0x3665412f,0x9b79789c,0x64b62250,0x4e0e72b2,0xea560058, + 0xe555c2bb,0xabbd4901,0x17292e11,0x378419a7,0xe174218f,0x6e0b5aaa, + 0x8f796b92,0x688e0684 }, + { 0x313b8f64,0xcdfef641,0x942c7462,0xaef11b7b,0x5c0d8abd,0x067cfb77, + 0xaf4041a9,0x608ea5f0,0x6935210f,0x23d5bd82,0x27917a08,0x5ab904fc, + 0x45d22d21,0x85dbb1fe,0x4d36159f,0xc3d5e509,0x1d39b8f2,0xaebb528e, + 0xf44acef0,0xdd5ca828,0x20c57a54,0x24209adf,0x78f95f44,0x5742b433, + 0xa9337d37,0xd11fa7d9,0xc64cfdb7,0xd66a0c09,0x9bb817ec,0x56e55b8f, + 0xe4c41265,0x1723c7e3 } }, + /* 115 */ + { { 0xdc8b43f3,0x9a6486d8,0x26409e68,0xfc3e0e61,0xd9b46003,0x1889c437, + 0x6284ec7b,0x3a850335,0x6a9dbaea,0x5a3665c4,0xe978933c,0x7bf6941d, + 0x69341490,0x1ed5a510,0x8cb8002d,0x664a7b7a,0x60ed0a59,0x603f76e4, + 0x1f4ebf27,0xc3e06ba3,0xf2c38a7f,0x296ced41,0xcf1db08a,0x2ac18f79, + 0xcde7a3b6,0xc919e882,0xdbf68b06,0x15e77d29,0x4e947cb5,0x21978baa, + 0x7630993a,0x84bf542b }, + { 0xe364f21e,0xc1decda9,0x012e557e,0x0d6cf345,0x588f90e1,0xba246848, + 0xe3b104b8,0x9f6dda4b,0xe3aef57a,0x6bf7a346,0xe8327ea9,0x210299fe, + 0xda95e6c7,0xaa99f487,0xd2cdf645,0x24ff813e,0x8bd414b8,0xd1dbb2d2, + 0xcafa1a61,0x065101af,0x9cdebda4,0x7d9f4b9a,0xe41039e4,0xaf41b395, + 0xc50adf42,0xe3e9e6ba,0x341e9e49,0x4f2133ae,0xcb157f23,0x4968c0f3, + 0xda068153,0x383f827b } }, + /* 116 */ + { { 0x6583ff4c,0x2ec46a21,0x4ad709e7,0x4e645a29,0xc04ca12a,0xdc66e9cf, + 0x9160a7e5,0x82f128f4,0x569c762e,0xbfb227b1,0xc2edb8e7,0xf80c7963, + 0x49a0f688,0xa7dafe06,0x2d14b8cc,0xb7e41754,0x86de40be,0x3a0c5c53, + 0x1db79331,0xf0d05286,0xfbfe071b,0xb902ce69,0x210e9903,0x61e46956, + 0xf703ebb8,0xfaef874e,0xdd5f78b6,0xf668947e,0x5af5ea3a,0x6fe86547, + 0x43f94625,0x3b121f15 }, + { 0x659275e9,0x5b26e847,0x6d0fce50,0x47581cfd,0x8aa3f1ef,0x55f5cbfd, + 0xe484e60e,0x1e7be315,0xfe9698e4,0xd8f1a20f,0x7ab04784,0x25d46da9, + 0x834cdb3e,0xa526db75,0x8d08a009,0x1fd408d9,0x5b5ca816,0xfc004b20, + 0x65e4bbe8,0x5b3e3bb3,0x759bb6ef,0xf50cc125,0xc2fac737,0xf05fa817, + 0xd273951a,0x9ee102d2,0xfecb3367,0x2a8e540b,0x2a6a515f,0x673446fb, + 0x37290c83,0x5505e1d1 } }, + /* 117 */ + { { 0xd15e68a6,0x0c3014a1,0x64dd35e5,0x6f9f0b26,0x03ad67f9,0x18c3742d, + 0xd2c14484,0x74818c0e,0x0d41a3cb,0xc5181169,0xc49f3e9e,0x65c8c83f, + 0x2c279386,0x9b260c61,0xced04e9c,0xf6086fae,0xfd7c4758,0xa7b2cceb, + 0x90297fd8,0x4b3c3133,0x09701ac8,0xca8264e8,0x508b3762,0x9f976a87, + 0x983a8dfe,0x5d582714,0xd9d598e9,0x350d2669,0x0f6fd348,0x85cb89cb, + 0xa574317c,0x617d80d4 }, + { 0x70022b67,0x4cef267e,0x3768b94a,0x80536bb5,0xd2784462,0x3153a566, + 0x38243919,0x49054d44,0x5df78c4a,0x8d11e172,0xd5a1e35a,0x9b252a71, + 0x8171e31d,0x07866c80,0x1b38a00e,0x0a8501db,0xce770236,0x2ed932b8, + 0x8edaf7d0,0xa2d77609,0xb93006e9,0x3aee5dab,0xbbfeb036,0xfaffc8c4, + 0x4e21b38b,0x077b9678,0xdca8e069,0x491fc59f,0x0e938471,0x3f624f55, + 0x7cd1780b,0x5156f508 } }, + /* 118 */ + { { 0x0206e8d0,0x58234e22,0x7f15af32,0xf5f6f5d4,0xd638950f,0xafab7289, + 0x7d4495f4,0x66ec4d09,0x68da80a9,0xad890c5d,0x64f8a36b,0xe4aa0920, + 0x0f4d5c5f,0x799e257e,0x24495e31,0x44c677ae,0xa5b8e352,0x720387b3, + 0x75a287b9,0x703790f4,0xc3c1f2f7,0x54895cc5,0x41a7fa41,0xb8680f9b, + 0xb00b008b,0xfcd47458,0xba6473cb,0x149cc838,0xac9be19a,0x78ed5f7a, + 0xb33765ba,0x5254599c }, + { 0xa21b54c4,0x08739679,0xb6497d9d,0x029ece2a,0xc8488640,0xf14f1a92, + 0xe9fa79d9,0xae48dcff,0x46c208db,0x14b911c2,0xdae3f69e,0x5ab0fbf2, + 0xd1edb838,0x180ac87e,0x188586bb,0x146fd718,0x5467cbd0,0x210eb654, + 0x1667cfee,0xaa239408,0xb73d1a60,0xdb125c1a,0x881c1cbe,0xde685300, + 0x37c30232,0xfe34c713,0x6f3c8d18,0xc6c6070e,0xb4af4e83,0x07e365ba, + 0xdcf82b45,0x22f0a7ed } }, + /* 119 */ + { { 0xea7f1b7f,0xe262791f,0xdcff09d4,0x9c3d8c5d,0x39c7dc58,0x86c2a9c3, + 0x4276e8c0,0x4dad4017,0xe9fe1d56,0x0a918f59,0x2aa810c9,0xb8d79670, + 0x4aa5cdc4,0xeb7a8836,0xe7afa72e,0xfc4c23bb,0x4ac86908,0x4dbb5c9e, + 0x6a0c7e6f,0x37e39013,0x49c218d2,0x855d7001,0x94b324a2,0xe475bc67, + 0x6287a071,0xc98a8dc6,0x5fb4323c,0x395a299b,0x0c0389e9,0xe186c3ee, + 0x16734c46,0x79f81e6f }, + { 0x364f3c4e,0x83f2c1f3,0x1367e14b,0x536b2ac5,0x5933e43d,0x44a6dcfc, + 0x10d961fe,0x34e59475,0x7e3f2aae,0x08234ece,0xbdea7f25,0xcb92e00a, + 0xa791a124,0x1efba4f0,0x1192d53a,0xc2086fd2,0xb51c8af6,0xfec0d0fc, + 0xdc0f1b5f,0x48d1b2ca,0x812dbe19,0xb07a388f,0xdedbdd45,0x40873a6a, + 0xd702589a,0xbc2a1268,0x17e27b64,0xbbf6e3a8,0x6d386e85,0x73ee5663, + 0x9de7c000,0x442ecd37 } }, + /* 120 */ + { { 0x8a2f90a6,0xb4cd1ae6,0x6f5ad0cc,0xf277d41d,0x401d4b8e,0x6a3828c4, + 0xd8376631,0xe817a134,0xf5e1124b,0x142b758d,0xfd6b95e4,0x25fbc69d, + 0xd74a9e3e,0xa30c9f5f,0xd89663ce,0x5ac0f163,0x0ce6386d,0x32a9eef7, + 0xd8ed5544,0x7a690ea5,0x9889427a,0x5de23ff0,0xeaaced58,0x75ad36a5, + 0xd3e18465,0x3514a6c1,0x7f093910,0x3d9162c3,0xe33d56e8,0x5c10add9, + 0x06aa691e,0x85176b73 }, + { 0x28a21e38,0xa32110fa,0x5773d538,0x97b6379d,0x2d020dc4,0xd3697bbf, + 0x961833cd,0x59177593,0xe5fa8516,0x6d7045fa,0x786ab5d2,0x3390f29a, + 0xdc4f5b70,0xac0bda30,0xdcc615c6,0xcca0240a,0xc5146d91,0x8e1f1702, + 0xa72cef87,0xceb472d0,0x0b669ba1,0x84840708,0x7e61aa0a,0x79b08f9d, + 0x4669560b,0x388160be,0x948eb71e,0x23935c2d,0x9431590c,0xd7fd83c0, + 0x6e5768b3,0x8ab154bb } }, + /* 121 */ + { { 0x353c4a96,0x28686003,0x905cd835,0x4e5c60e8,0x8f66f8cc,0xbd591364, + 0x9faccf9e,0xb6b80b98,0xe32639e5,0xbc1c1fae,0x278aadeb,0x2f6396d2, + 0x1898202d,0x00a796d0,0x3a474835,0x18ab548f,0xb31b0e3e,0xacd056c3, + 0x0164512d,0x15ba68dd,0x4b03f3bc,0x203836d9,0xd8f206c5,0xd64eca6b, + 0x9f1779b6,0x931a361e,0x52ab34a8,0xd82690fc,0x92922e22,0x342bb8e0, + 0xe00b02a9,0x1bfcdd84 }, + { 0x75a365d9,0x310b9a43,0x08d8fb03,0xd4ade15e,0xd742df83,0x9c9753d7, + 0xde318742,0xcf7309d4,0x3360ace0,0x1228e212,0xf7669643,0x1043d238, + 0xf90f5a53,0xfc2adbed,0x7b5f9397,0x41d64cb7,0xc446d010,0x5200b30a, + 0x231720fe,0xc3c8642d,0xb9aa2075,0xfcc0122d,0x041eae47,0x856e3b12, + 0x68c876a4,0x45864455,0x233606b1,0x1a1c7842,0x227757bf,0x9b766d1f, + 0xf7b9d4f1,0x25b78a3b } }, + /* 122 */ + { { 0x156707ce,0x90835718,0x4314f90a,0x9bdc2398,0x8be57dbd,0x017c885a, + 0xad63a4b8,0xd4bba225,0x15aacffd,0x5ce71b86,0x72954722,0x5f266475, + 0x4f0ad3dd,0x0a80f1f7,0xfc352ed7,0x010538a3,0x4203c6ca,0xf8a64045, + 0x330c73b4,0x2b2c7a88,0x02dcac1b,0xb3433ee6,0xed2b17c7,0x2e0499cf, + 0xbd6329c7,0x9f8681a4,0x36fadc37,0x38979946,0x92b7895b,0xdc5650c8, + 0x65a51cf0,0x70ab9570 }, + { 0x7b585d93,0x46778ec4,0xa633fe4e,0xca6d3610,0x4ea0311a,0x21da154e, + 0xbd64002f,0xaf22190b,0xd91cb7a9,0x9e633ac7,0xee6837d7,0xed13c31f, + 0x1616ee8a,0xda4a07d7,0x3afcd616,0xd78a2732,0xba14d694,0xc06696e5, + 0x4df58420,0x733754d7,0x2778e3c9,0xe85e504e,0x55b5a5c2,0x3055aa0c, + 0x8a3acb5c,0x313df538,0x2a088eda,0x5896acb5,0x84c85dde,0xfc8842a0, + 0x51dde6be,0x5fec9f79 } }, + /* 123 */ + { { 0xfe519f99,0x5ebc2c7c,0xe5410353,0xe396bd80,0x8a3988f3,0xaded9402, + 0xd601bda1,0x1c03b735,0x14ce64ac,0xfd302036,0x01240290,0x5837ebe9, + 0xa554097d,0xcaaea1a3,0xb0b88139,0xdce73d25,0xecb090b9,0x35ed412b, + 0xd63dab3c,0x99029ff7,0x062db071,0x555437d9,0x42a4c11d,0x277d2f56, + 0x24fc9109,0x477fa645,0x2799254d,0x7b12e9b7,0xd84c618c,0x7ad2ae22, + 0xce8ed195,0x0a8d5663 }, + { 0x0a21fde1,0x43ac5163,0x6903d849,0xcfcf5dd6,0x5fdd6281,0x6d2499ee, + 0x77a49a34,0x4dedc6f0,0x2875c06f,0x46bda2c0,0x347b8046,0xd0e0e0f6, + 0x5e67836f,0x1058169b,0xde8a8042,0xc961912a,0xa93b3d32,0xdf3fea0a, + 0x0c576bc5,0x9f138edb,0xd8d37e47,0x7971ad6e,0xcce5e7cb,0xeab85739, + 0x1d202b40,0x88a4b434,0xe3a1fd26,0x5d842557,0xb3a86f91,0x872fabd5, + 0x6aa4629f,0x95b93493 } }, + /* 124 */ + { { 0x99f951de,0x9998a701,0xf058db45,0x8fade596,0xf3d03dd3,0x4d479c1e, + 0x33b141d3,0x6e928d5d,0xacfe8a40,0x9a465800,0xc1cefa3d,0xd108ad2f, + 0xe013726e,0x64b96921,0x8e83bb9f,0xb9b6a6b6,0x1242e544,0x29f1e6dc, + 0x2f65966b,0xd3f8f676,0x5e105b41,0xa34dd096,0x16011e1c,0xd4e9139a, + 0x2515541b,0xeea4dc68,0xc822166d,0x6f8030ac,0x31d16124,0xbdc7ae1d, + 0x621afa7d,0x2e25ef51 }, + { 0xdd8e7357,0x2533cf8f,0xeaceddb8,0x333ba218,0x0784d2ac,0x68e3e31d, + 0xf2804ae2,0x1c927f36,0x77e7ad7e,0x01433d22,0x587f78a0,0x0b401cf0, + 0xaa0027ae,0x9dfcf036,0x1d9a46b5,0xc9e46c8b,0x1f288d32,0xaa6de486, + 0x1b8a043d,0xdd56da2f,0xf2d0bb56,0x346230e5,0x19defb56,0x19f0b6e4, + 0x21d2c874,0x55ec37cd,0xb70e45b3,0x3dbf0397,0xac7ce852,0xf0862a8d, + 0xe141f3d6,0x87979ea7 } }, + /* 125 */ + { { 0x7f1c747f,0x9b7e7b3f,0xc6e63369,0x151a4c1d,0xb372dba0,0x4273ff70, + 0xd3ee54fe,0xca6d2234,0xd33cae0f,0x12fc8e0c,0x5dd6f10c,0x27328538, + 0xf01a9cf9,0xc86f3fbd,0xe36cae91,0x5322677f,0x2fefea44,0x39a70033, + 0xce8af217,0x2c9ca328,0xf6a731f4,0xc0256776,0x66a96813,0xc687b3df, + 0x8db2eda8,0x194aab12,0xeec4febd,0xde30dc5a,0x979241b2,0xc052236a, + 0xc23d4c16,0x3ec98802 }, + { 0x4072f74d,0x0f9e760c,0xab594059,0xe78eb0de,0xc9b009c2,0xdb3dea40, + 0x38b59ae5,0x47e875f0,0x2b4daa06,0xf40eb436,0x090f3788,0x9a6a4f92, + 0xedbfaf8b,0xefebe9af,0x9867e256,0xf87f96a5,0x75ab6aeb,0x1e6fed23, + 0x3fdb13cb,0x17f2782a,0x70fa2621,0x5102c71e,0xfd4c0dbe,0x5d2b06ec, + 0x30347297,0x537cc268,0x2b67e780,0x8dbf5e2b,0xba25da32,0x2f633f3a, + 0xefaec914,0x3e9315e8 } }, + /* 126 */ + { { 0x239a9ea9,0x9255cfa5,0x0be33a62,0x20f3c690,0x9cb642bd,0x759eeb4b, + 0x00bae718,0x3316c546,0xf3410f84,0x874a76d5,0x90f129b6,0x123b502e, + 0x12851f1c,0xadc8f9a8,0x1b62408c,0xf57b764a,0x1a80777b,0x116ec01f, + 0x1f0ddc5c,0x746ecef2,0xe5a6a5a7,0x3c49d47c,0x06e955ba,0x1e15dbe7, + 0xb45d79b0,0x629c0c79,0x778d1087,0x11278308,0x8c6a22d7,0x22585dc7, + 0x0a682791,0x2ed02a0d }, + { 0x4daa2682,0x53043416,0x01359625,0x0e26d32b,0xbd867097,0x449c834a, + 0xee77ae2e,0x11a19d2b,0x3af6c169,0x39bd529a,0x5cd61054,0x36cca5c0, + 0xdc6c0fe1,0x6370a59b,0xb93d5135,0xca420d27,0x554c451a,0xd8730d45, + 0x96cdebf2,0xebd258c9,0xa50f9a05,0x0cb1b990,0x7b0f0151,0x69a8c97a, + 0x11d217e1,0x2cc36d34,0x752f75e8,0xf117688a,0xa09b2a61,0x1db01394, + 0xa9efd7dd,0x14627844 } }, + /* 127 */ + { { 0x232803cf,0x6bca3aed,0x9a96ff34,0xc1e4398b,0x74ab788b,0xcaf6757f, + 0x7e68c04d,0xc3a53e00,0x5cb7cd20,0x5f969c19,0xdc068bca,0xf28b65a6, + 0x1d863032,0xe3ca01d3,0x87808e14,0x9b733b81,0xefe618be,0xb5d704d9, + 0xb01b946d,0x276f3542,0xfbedddbf,0xe057e19e,0x903275ce,0x7d182f2b, + 0x880f7bc6,0x3cdc5f77,0x78476c14,0xd6f03d3f,0xa9ba5072,0x035f5557, + 0xb4029628,0x7acb57b6 }, + { 0x44e6b07c,0xd2413569,0xe1c7345d,0x451c4cc9,0xe273b9fb,0x407444d8, + 0xb88e34fc,0xfe496079,0xf152776d,0x77d184cf,0xc742299c,0x6d1033b9, + 0x77bf2897,0x29a0a684,0xee8f0420,0x59ffdf10,0x44bb56d6,0x4e17146c, + 0xfb9ae855,0x831d06c2,0xd93e7cd5,0xb2cb82db,0x3c96b607,0x83381c46, + 0x7549e2a8,0x06aed251,0x774a21d4,0xef97891c,0x8675fbdd,0xae9807c7, + 0x6363516c,0x6a5a05b9 } }, + /* 128 */ + { { 0x6a8f4f33,0x92e71ea6,0x4dea8f4a,0xf2fc6fc6,0xfee88461,0xd356252c, + 0x08954d08,0x59b0a83e,0x468ab766,0x5bd68c23,0x900f8d04,0x40281357, + 0x52b867ae,0x181c19c0,0x18764c41,0x986a5169,0x13575d24,0xcb01dfae, + 0x593677b7,0x17269ae5,0x46dc9b19,0xf6d17025,0xc40097c8,0x8de68499, + 0x259c407b,0x76df0032,0x17d29d8b,0x4091aad9,0x4a7ab5f6,0xa7f46d21, + 0x70ece48c,0x688054b4 }, + { 0x51a5b86c,0xf0d168aa,0x95777247,0x2437e4d8,0xf1720329,0xae844076, + 0x9647a54e,0x0a7ac87d,0x0405622c,0x1e597a4b,0xf0a79f2f,0xedefe5c6, + 0x4d55156d,0xaf3ef0c2,0xef047cf6,0x917fb04e,0x54b62137,0x3792799f, + 0x314be0b8,0x875ea32f,0x0c466b0c,0xe157c65b,0x7e218978,0xd28c90ce, + 0xcde587af,0xb90fc3ba,0x8b877bed,0xdd32d71c,0xca8e10cd,0x3b432200, + 0xd94f6e53,0x0021f419 } }, + /* 129 */ + { { 0x43519d26,0x2191122c,0x40a51845,0xbdafac1d,0x548bb89f,0xcc6f71e9, + 0x16844bf9,0x9ef3375c,0x178e8d55,0xe7789f79,0x1f8be1c5,0x04f599b6, + 0x2cbbde40,0x8088c99a,0x893206c9,0x8939a260,0xfcd30851,0xa1ae4bff, + 0xe08feafe,0x664cb3fe,0xff14aabc,0x61f38099,0x2a841ef9,0x0d8394cc, + 0x17f01db6,0x75fad8ad,0x6debb773,0x6fc34576,0xa4252512,0x1e716b05, + 0x29e1ed9f,0x79855880 }, + { 0x95106473,0xa2cb3aaa,0x5a61da04,0x95fafa41,0x539563c0,0xfd3c9362, + 0x95312b87,0xbaa48091,0xbf885c76,0x6c7e7582,0x230c78d5,0x70f6dab6, + 0x7747440d,0x8ce3051c,0xffdb6186,0x6dbebd14,0x190e4096,0xb0e041fa, + 0x6ee62e2a,0xba10c466,0x74f333d6,0x93d57e2a,0xfe7b9b66,0x006aadc4, + 0x06d2837d,0xfaf72f6c,0x910741ea,0x318cc5e6,0x65692477,0x9c502609, + 0x1d0fb08d,0x95d823c3 } }, + /* 130 */ + { { 0x140528a5,0x6aeebd86,0x53979bc8,0xf268c2ba,0x4ec144ab,0xb1bc9b8a, + 0x82a7d7ed,0x1efabb0d,0x4e0118d8,0xf12c70d1,0xa1c1558e,0x31607168, + 0xe4b7e73e,0x33e428b7,0x83aec9dd,0x63176637,0xe12ac35c,0x5172ffbe, + 0xbc17b2a4,0x37df0bfb,0x741f812a,0x4212f870,0xe2888f9c,0x3dcecbdb, + 0x756ca55d,0xa9dc15aa,0xb9028e41,0xf31918ec,0x6aeadb03,0x7ede0285, + 0x78654f54,0x0e2708d5 }, + { 0xcde20f88,0x2270cc53,0x5f5b1039,0x9338272c,0x5dcb1dbf,0x5042e19e, + 0xb72d74c1,0x4b3de219,0x2aaaaa55,0x16c49a8b,0xbba86ba6,0x008443e5, + 0x20cf1695,0xee6bcd72,0xa89abd11,0x59ffac6b,0xf115639d,0x2831217b, + 0xf34cba52,0xe4d28af2,0x0727a906,0xf27f03e7,0x69017766,0x6842c79f, + 0x7a81123e,0xcb3469bd,0xa42973b8,0x48c0f346,0x23990dbd,0xfc5784a6, + 0xfb299678,0x0d3dab3b } }, + /* 131 */ + { { 0xce29c3cc,0x8f8376e6,0xf016cbc6,0xcb0507ec,0x5e394ce1,0xdebff996, + 0x73c50d41,0x24fc526f,0x2d16ce3d,0x4edd5a54,0x91c13141,0xbb37bdd9, + 0xe33a8606,0xe3442ef2,0xc0629da8,0x2ae90337,0x592ab331,0x57faec64, + 0xd82b857b,0x1a938997,0xa3373176,0xad6c8cb9,0x9086751f,0x82595de2, + 0x18c17196,0xa81e97fb,0xbf697357,0xe4f48a13,0x5cb89f69,0xa1387c2e, + 0x5874b426,0x530b4eeb }, + { 0xbab7b5ae,0xe9f275a1,0x03a57bf4,0xbb69dc4d,0xa45c505b,0xc974dc4a, + 0x416ac402,0x726369f3,0xaed985dc,0x735e4e78,0xcdd446a1,0x0548d879, + 0x9e16b02a,0x84ceb069,0x789b11a6,0xf73f6fa4,0xb2a4e784,0x6aa0c41f, + 0x93a9b697,0xb1f76902,0xf03a8ab2,0x814cce00,0x844d66c1,0x64cb255b, + 0x30952201,0xb794e7d6,0x3da32271,0xe052d4e4,0x08b6a4d9,0x5278b2e7, + 0x80c6577f,0x90942552 } }, + /* 132 */ + { { 0x0d5b4c2f,0xd269a14d,0x5c8a649c,0x2b8fc59b,0xb0e37d4a,0x95becb3a, + 0x9111037e,0xfda1a768,0x94e35322,0x5810e05a,0xa178fafc,0xa24dcc12, + 0x8e3dce62,0x5c2c63b2,0x9452c444,0x995c3f17,0x42d45161,0x35330ec3, + 0xb4ef8129,0xa025a60a,0x8bae9c13,0x85493252,0xe2e3caf8,0x25d1a606, + 0x3649bf47,0xd44091ab,0x704ec5f1,0xc7d0afbf,0xbd8b3333,0x27bd1d62, + 0xcfe616f5,0x50570111 }, + { 0xf534356b,0xd0084ace,0x4b4b0fbc,0x9df1de05,0xcee04dc1,0x021afe05, + 0x361b78e1,0x64bde688,0xef78d38b,0xa324fcc7,0xeb0a5e4e,0xfeb372ce, + 0x65811996,0xef04fcb3,0x5eb0ab4e,0x7dce5d50,0x238c586e,0x1e29b588, + 0xbcd80037,0xde5e3197,0x4806b9cf,0x8bf5e451,0xd18e67ab,0x4330968b, + 0xf9f63fad,0x26a7d04e,0xb5c18bb4,0xa1c7f123,0x25dce22c,0x485b8482, + 0xd540e79f,0x8ff0b36f } }, + /* 133 */ + { { 0x3ff42cff,0x99f2e2f4,0x1c35317c,0xa3c19f9d,0xaba1b545,0xdb749392, + 0x4afa9a32,0x84232b05,0xd7dcd436,0x0b855d46,0x45cf9915,0x8ac35e20, + 0xf001a218,0xd7cf22c7,0xed408305,0x057d35ae,0x553ccfcd,0x25a4a519, + 0x93e2b939,0x5e565793,0x3422ec27,0xa20332b0,0x3ac53958,0x9b09005e, + 0x79e9b163,0x628051a3,0xfc6618d6,0xb4a0dc09,0x6748e7af,0x9e0e857f, + 0xc577d63e,0x71b28eee }, + { 0x99726bf8,0x4942b0cd,0x1c208f3c,0x1290a3b9,0xb0598eaa,0xfd7290e7, + 0xa25a9128,0xc6a7791f,0xc037d7da,0x2d33db24,0x70e2837b,0xc21efeb0, + 0xe3dae2a0,0xbf70d96e,0x85076027,0x43ed8191,0x4d4ad7e3,0x4aeb0aa8, + 0xe8c5b74c,0xbc75101f,0xad26ebdd,0xdbfb2a6e,0x6b78aa4e,0xba812068, + 0xe1159848,0xc94aa8f2,0x3eba5c4e,0x0d10d9db,0x6318295a,0xce7fec47, + 0x330d925a,0x7294711a } }, + /* 134 */ + { { 0x32bbd495,0xfce45904,0xbe54973f,0x330f4dd1,0x5d9c3f4e,0x006bee1d, + 0x59ba7204,0x40ee6078,0x42c2c768,0xc194fd3f,0xe9fe88be,0xa0e76b12, + 0xec2b0210,0x17cddddb,0x00811ec7,0x689d436b,0x284be9e4,0xa6a6ba37, + 0x007d4114,0xabc395b2,0x0f11e744,0xf8cdf9f3,0xe9396402,0xc5febec8, + 0xeeb46285,0x8a751743,0xc6e0d137,0x99bf8782,0xbeb292e3,0x3965e170, + 0x5801fd5f,0x001c39d8 }, + { 0xda4a0912,0xf4805cb9,0x4410bca4,0xd27cb76a,0xec71d65b,0xef3dcb8e, + 0x4816849a,0x780fbb2b,0xa8b24635,0xef6a7026,0x12c44e68,0x15625c88, + 0x4d7a74a8,0x624c232c,0x4b1631e4,0x81a77037,0xdb917c2e,0x04e4f7f1, + 0x1f61ed95,0x1d0465fd,0xcbde6e3d,0xb1048049,0xd7131fcf,0x637ce0c1, + 0x8ada4715,0x22e4dbc2,0xace99726,0xf7530c5c,0xee287450,0xa0160dcc, + 0xbb91af13,0x9132e670 } }, + /* 135 */ + { { 0x7996099d,0x8057efe2,0xa06e608c,0xb72344db,0xd0958588,0xeb4a8740, + 0x79e5aee9,0xe53daf06,0x908a2fad,0xc9560a9a,0x107e706a,0x7f4be131, + 0x2830246a,0x6d5f3d9b,0x27cca3e6,0xa5f8e8da,0x4c28f292,0xeb51dca6, + 0xf31dfd78,0x4cfa310e,0x2ca073e5,0x92e0c7c2,0xa40da683,0x102f1694, + 0x750d38fc,0x16bb07cc,0xbadae035,0x703e83e2,0xb4d3c9dd,0xea93c066, + 0x79940ed1,0x7d0b03e5 }, + { 0x4dd94c63,0x5fe7ea30,0x738b0b3a,0x57ef01c5,0xa14e6b4b,0x9534a78c, + 0xa5353276,0x07622cde,0x7c22d006,0xaf696a07,0x7d46b209,0x733c1886, + 0x626c2b4a,0x9654ccbb,0xa84f3c4c,0xa098d3a1,0x2d734b74,0x3596f9ed, + 0x5d551c90,0xdfd3021a,0x1ec5123f,0xe2ba7d2f,0xb2c1aa39,0xf9726925, + 0xf8eb2927,0xd2e75d0e,0x19192a6f,0xfaba712e,0x9b83e50e,0xa606b43a, + 0xdab5de60,0x31b1782f } }, + /* 136 */ + { { 0x4034db92,0x878dba45,0x8f34dc4d,0xa3977901,0xdf754c33,0x8d004f2e, + 0xcd563a88,0xeaa5954a,0xbb5ffad1,0xa29d6c89,0xb0d8bdb8,0xa8adf655, + 0x8cdbdb47,0xf7fb842d,0x80d3205b,0xb72e3a03,0x7cac7ca9,0xc335b0b2, + 0xd8a5475d,0xffc60bcb,0xeba4d25f,0x736f7719,0x0c50fca6,0x3d901c38, + 0x80c01900,0x1fdacf7b,0x5681f84d,0x75cf658f,0x5cefbbc1,0x57a7e634, + 0x3e07ed1f,0x6fc0fbe5 }, + { 0xb81b0e5f,0x496d116b,0x2ac853b8,0xd82dd2a5,0x327387f0,0x357e22d4, + 0xba912c59,0x3e332a84,0x49d5dcc1,0x8b71c643,0x438d85d3,0x0c982ee9, + 0xbf7fcd4e,0x90b9553c,0x38fed5e3,0x2cb39bbc,0x5ac42903,0xa2c67c9c, + 0xbf07da55,0xebf21217,0xa0b9e4ee,0x55ac05ad,0x8ee9e0c6,0x10bb12c2, + 0x48bb6e3f,0x5cf3aee5,0x8b046e91,0x4ae7269c,0xaa0e553f,0xcb266012, + 0xa94c8fc8,0x701935a1 } }, + /* 137 */ + { { 0xa4626dea,0xde58d41d,0x15b9039f,0x25ef66ca,0x3164e65b,0x99a810a4, + 0x748cfccf,0x9fe6daad,0x2f142fa9,0x7ab9a6bd,0x5d471796,0xa4cba168, + 0x6bc3a39b,0x12d30b36,0x8bf45076,0x1f46a5dc,0x1421ac0e,0xb868e529, + 0x59bba1c4,0x7a686206,0xda698b90,0x2b4b552e,0xe5453707,0x5039dcd4, + 0x9e90165f,0x42a07a9e,0xd7d45dfc,0xa838fff3,0x3b5ceb30,0x41991e5a, + 0x969ca600,0x6c961ec8 }, + { 0xc4e7eb46,0x703bdc1b,0x596c7b48,0xd6bac557,0x66afd74d,0x4f9917cd, + 0x656ce6f3,0x56355105,0x32497175,0x3d1fb50c,0x63effb2d,0xfda6783e, + 0xeefaa2bd,0xbd79f1f3,0x17af9ef7,0xa4efbe54,0x5a55b7a4,0x6cef6462, + 0x1a713304,0x116f3238,0xb95625a3,0xdb2a2a7f,0x0b027e96,0x6a0aa43a, + 0x4832b3bc,0x458fe5d2,0x5adfaac0,0x523418df,0xc49e7f9a,0xc05a89cb, + 0x69e24b53,0x830883d8 } }, + /* 138 */ + { { 0x02557389,0x959b1c62,0xadefc0bc,0x5fe5ce97,0x8330f383,0x893bbe7f, + 0x16cfb81e,0x27e0c6af,0xd04428fd,0x6f64e65b,0xb79e6182,0x53de9245, + 0x487e11ca,0x08a313c1,0x445bce93,0x65cec3b9,0xd67ed49e,0x33bc0314, + 0x30782352,0x69f36b24,0x93ad31d2,0xd78e5daf,0xc780890c,0xf2682b70, + 0x9e45efe9,0x7015c34f,0xe6cbafea,0x135d4ba4,0x7e3fcc6c,0x43a378a4, + 0x96638f8c,0x2376f97f }, + { 0xae575b99,0x0a6e1ec0,0x81b970dc,0x7e14cb4f,0xd3a73947,0xf00a3824, + 0xfb235a9d,0x0b4b9c81,0x5bf62944,0x8d15115f,0x1e165d7a,0xcfd35b43, + 0xb2ee3e3b,0x5d12fea2,0xf5182e7b,0x629984a6,0xc365d08e,0x4e43e2f3, + 0x30f36e72,0x99327091,0xfd345401,0x698b4a00,0xbaf96dce,0x23c4fd0e, + 0x23675554,0xa60ba0ae,0xb0325784,0x51bdac2d,0x215464a1,0x8ab4190a, + 0x6bf10296,0x8c461661 } }, + /* 139 */ + { { 0x2d1f36a5,0xeffca258,0x894c5f2d,0x0eded2b2,0x43ced84f,0x35a5cdb8, + 0xdb0e3b9b,0x290f8982,0x0719a112,0xcce0eaf0,0x39a362d6,0xd0e657e4, + 0x62697e47,0x5516a55d,0x8e636514,0x269e1f77,0xd50269bc,0x5e3dedcb, + 0x441c57c5,0xecec2300,0xc705578d,0xdb83f31c,0x1e489eab,0x1bdefb73, + 0x395fcdb4,0x20b678cf,0xff9db001,0x908cf91c,0x55f52cc8,0xcbebc6f4, + 0xb4c61162,0x155ea622 }, + { 0x876fa42e,0x94be2f1f,0x7fadeee7,0xab5e8749,0x38c865af,0x692e70f5, + 0xdf8059b0,0x16e99b84,0x8b5a7ac9,0x0ceb606e,0x2d463d2b,0xced23357, + 0x2a9a09a0,0x2d0f2623,0x3861fbdf,0x2529998c,0xc1be310b,0x711888a7, + 0x0d8aade3,0x9b1229c5,0x3b13533d,0xdbcf9b78,0xff029708,0x3ca746f8, + 0xda83ef88,0xa5a013a1,0x4ab28444,0x8e904d18,0xbcbd4aba,0x2fe84b3d, + 0x259058c3,0x8f570f24 } }, + /* 140 */ + { { 0x2ca9c508,0xdeb66c8a,0x69d6b780,0x2dc5bec2,0x88ead600,0x16d61266, + 0x49d72614,0x61841b97,0xce472e6f,0x41e40e6c,0x1fa7a876,0xada24264, + 0xcc3997a0,0x45b9fd33,0x7c15dcf4,0xb25e8fa9,0x12e9629d,0x0124ceb2, + 0x7db3d956,0x3a8c72c6,0x7c1a7844,0x8e2ded2b,0x6dd027ff,0x94ab09c6, + 0x7e7a2bc6,0xf89a057d,0xcf70c763,0xad8bf226,0xc8a26212,0x4cb268e7, + 0xb2c44c1d,0x3d171e87 }, + { 0x8ce49820,0x382ac16e,0xc0c44dc9,0x24ee45e2,0x73e858c4,0x0ec67912, + 0x46327cf9,0x918cb25c,0xc6159c1f,0x43e3876b,0x37545cb3,0xb6b6e0e0, + 0x5d12347e,0x64b839ab,0xa300d541,0x72e09274,0x881c1169,0x26ab28e6, + 0xeb75a843,0x4a580fff,0x359120df,0x0a5802ca,0x3209f4a3,0x7fee82d0, + 0x8e6a9380,0xb518016b,0xc2ee11ca,0xb99c6c70,0xab9d4ec7,0x16105af1, + 0x34cd9004,0x234e98f8 } }, + /* 141 */ + { { 0x14db9cda,0xff435208,0x96adec90,0x99cfdc47,0xaf458b6d,0x843aaa6f, + 0x743eaa31,0x3f1f7415,0x61735d81,0x915e192e,0x0ac595d5,0x3441a22d, + 0xc044bc8d,0x704bbf67,0xbe23a236,0x2f960471,0x15d1d557,0xcc326388, + 0x76b1dd94,0x9410230b,0x0c1c8a67,0xf2e5439f,0x833c910d,0x56b141ac, + 0x865b84df,0x467c999f,0x21f02b7b,0x1b0251fa,0x96216950,0xde5b5260, + 0xce3a1e93,0x6a2130e3 }, + { 0x4b3ca1a7,0xd21b67a0,0x00c0ce80,0xaf42ed53,0x932cf07a,0x22ccd368, + 0x5c25c35a,0x36523a81,0x8dd04d06,0xecdd3958,0xb2f93a3b,0x73da3502, + 0xd5e5b530,0x4c5e0c3c,0x13268777,0xef9f5486,0x1e742292,0xed87fefc, + 0xa24e5ede,0x6d9ac29e,0x33849f1a,0x08abc9f0,0x40f23905,0xb09b2292, + 0x7f934353,0x6791072c,0xe6aeb550,0x102a6381,0x96feb870,0x3ee07409, + 0x9c4d2830,0x34f06faa } }, + /* 142 */ + { { 0x2348f005,0x869dc79f,0xdf4920b1,0x9b5c5d71,0x6dee64a4,0xfd1b57ca, + 0xe82a4fb4,0x21b7f734,0xb9578366,0x637cb834,0x7d287d96,0xc934101b, + 0x0392ecab,0x1590f8ac,0x7f75f4e3,0x280dc373,0x6a61ac62,0x8b36f50f, + 0xa65568da,0x74f58304,0xd930870a,0x80d792a9,0xfc8895cc,0x6d17b192, + 0x4914939f,0x498392fa,0xd41d5b9e,0xaf36027d,0x5caa82b5,0x452d79e2, + 0xf4115d1a,0x764d47b1 }, + { 0xa2ee8b9c,0x5df22303,0x85dfcd48,0x1b9f72d3,0x10813a37,0x6b42b983, + 0x3de741f5,0xe28c523b,0xf303bb5b,0x0857625a,0xac9bf9af,0x926f299a, + 0x0d445b34,0x21beac08,0xd6ba2c0e,0x6a523a02,0x7fce2864,0xe302a1b1, + 0xe300c1ea,0x4516a235,0x7b4a9311,0x4543736a,0xc0cc89f7,0xd3c0b9e8, + 0x40ed88de,0x0481904f,0x3cb7fc70,0x4f269b56,0x321b9738,0x09a1d53a, + 0x230a3810,0x1c0dd9c3 } }, + /* 143 */ + { { 0xc46a7d9a,0xffaa1f67,0xbedf91cc,0x64743334,0x47a42f2e,0x45833a74, + 0x241ffaa9,0x67980051,0x335efe6b,0x70979a84,0xf08b2403,0x5f0613f5, + 0x64f211dc,0x6bb22fcd,0xa0572cfc,0xe1b8b2a3,0x7950a14a,0x19e0eb41, + 0x3eb6cd4c,0xe634bb29,0x470a25ff,0x31a04b25,0xa3d15a0a,0xa41f7ac9, + 0xbf2fede9,0xefed85ec,0x81b94a00,0x1f581f5f,0x9ef4a15c,0xaa3996b0, + 0xb06041bc,0x52d8be39 }, + { 0xfd631a2f,0xbd1536f6,0xb351a8dc,0x91fae7f0,0x9b126212,0xd1a590c7, + 0x2bd0f435,0x52d4875f,0x92b0ea70,0x9aedb6d3,0xb83ab89e,0x0bd0abdc, + 0x89fe192c,0x827a1062,0x102a0bda,0x6566a960,0xce036814,0xda083037, + 0x58639405,0x30bed79f,0xdbca8df9,0x972019b6,0xefdaa3f5,0x89201286, + 0x5236b892,0xb337b996,0x28fc2e73,0x11d3e38e,0x880e8da3,0x70787f41, + 0xdae4a45d,0x6cff6367 } }, + /* 144 */ + { { 0xf89a8bb4,0xbd3d0433,0x93b98f71,0x42144c33,0x03470a2d,0x82b616c8, + 0xe5da089e,0x98fcc757,0x7bf5fda6,0x542354ef,0x9ebd34cc,0x1885c253, + 0xbec5dd0d,0x2e20b285,0x782a1bca,0xe71bbbe1,0x9b854ef0,0x959ded30, + 0x8997fa6a,0x17249979,0xd81f3c45,0x50cf8fa8,0x60c11152,0xa9a3b517, + 0xecf845ea,0xc9b0ef7d,0xb9fed11b,0xc9339e23,0x28256080,0xc93e9c5c, + 0x613ec1e7,0x1d2c8217 }, + { 0x987cfc93,0x7381347d,0xf187f810,0x047603bb,0x1250ca31,0x3fa6bc9d, + 0xbb055bf3,0x480091e0,0x3a3af87c,0xbdf95f1a,0x140540ab,0xe2687770, + 0xd7fe045b,0x998df730,0xb723bc2d,0xb398135f,0x15ebec46,0xac230f8c, + 0x5f5561c0,0xe08e1830,0xda60a47f,0x7c0fbf4c,0xe16d4bfc,0x06e95c24, + 0x74617e92,0x74163495,0x4ae0c20e,0x39719869,0x2131e2b6,0xfe269312, + 0x0a537722,0x25486e36 } }, + /* 145 */ + { { 0x53572806,0x618795ca,0x656968e1,0xb2c89449,0x3fb323ae,0x149c2c97, + 0x409bc7d6,0xfb15de26,0xc79121b3,0xa90cda72,0x204cabbb,0x6d2fa14e, + 0x91604125,0xcbcda6f7,0xb435f947,0x25086261,0xc282eb10,0xdb686c38, + 0xf1a791cb,0x51016d62,0x61a2266c,0x6b1c7ed1,0x271d74a6,0x26780666, + 0x824287a4,0xb5ffeda1,0xbbe4f0f3,0xcbe503ff,0xb9482a74,0xd7f7f0be, + 0x088493f1,0x751b2358 }, + { 0xe9c9be68,0xd597b9d6,0x67d10c6c,0x1794b5c4,0x7762b2f4,0xa88cdc3d, + 0xa1b44e11,0x6d94a63a,0xaaa8eca8,0xfb0bbbb9,0xc963d87f,0xf4b0f2d0, + 0x5dc7075d,0xb753062c,0x49933989,0xfed726ac,0x57f9ccde,0x5da60638, + 0x75f8c766,0x221c392a,0x5dc672ca,0xcd264d95,0xb66ecc8d,0x7004ff22, + 0x18a458ba,0xfb1aa9ae,0x8babd653,0xea9644df,0x2ba0de7c,0xa9378e80, + 0xca2c6c75,0x144cc12d } }, + /* 146 */ + { { 0x2989aa3a,0x593a0a1d,0x59e6e64d,0xd83f2283,0xd32e732e,0xe938b0cb, + 0x3c3cb249,0xf4c464c5,0xf89ea6ac,0x9750a5f8,0x346cfc32,0x467e5bbf, + 0x37b2b809,0xc9bfab9d,0x3b339c6d,0xf8eb7453,0x3b766dee,0x3fe01fbe, + 0xef6aea27,0xb3154254,0x7be61b10,0x555c3df2,0xdd818488,0x70fb6d81, + 0xbbe714f9,0xda1af3a4,0x9d18f693,0x575f2017,0x2465b839,0xdc08fc6b, + 0x6b84a951,0x874ecf33 }, + { 0xbbb3f6be,0x624af83e,0x08bb423d,0xf578fbb9,0xd7873527,0x5623b0ba, + 0xa62e0442,0xc3659bd8,0xfe236f79,0x2903b167,0xe53f26a6,0x55a430c6, + 0x3ad712cf,0x222547ae,0x76eb272b,0xb73890d7,0x3d628df9,0x95b4f70b, + 0x53eae4ac,0x9f0e13b0,0xe7f2174e,0x5b4f5138,0x98dbae17,0x75482cf9, + 0x44518480,0x2b69bbde,0xcafef15c,0x4f279652,0xb6bcaf19,0xa0a3ef2b, + 0xce4c634f,0x31fb8581 } }, + /* 147 */ + { { 0x615cd607,0x398306d1,0xaa32c3a6,0x680c9faa,0x7779131d,0xe87a705b, + 0x36708b00,0x1031013a,0x9445297f,0x814fa0e1,0xa6a79b56,0x70c5583a, + 0x4b16bed4,0x03039cbf,0xaaaaf8d3,0x18a7ca8d,0x5cdb68a5,0xf33159e7, + 0xd23814fa,0xdea0e738,0x8d0f4f9f,0xeb352718,0xdcdff032,0xb0b76609, + 0x3d48338b,0x65ba8ea9,0x55dd507a,0x18044d82,0x4a4a50b4,0x844a223e, + 0x18e19e54,0x98323000 }, + { 0x57f3d5a6,0x28a21027,0x6e8cadcd,0xffce5648,0x02551f3b,0x9590381b, + 0x935ebdf1,0xb26cc64f,0xc083aa6e,0x60611291,0x88e4cf41,0xcd988a66, + 0xdd53b1b5,0x581c3f73,0x77fc621d,0x78c804a9,0xfadca2fa,0x31874330, + 0xc83ccf02,0xf7008da4,0xa79a4707,0xc4122a1d,0x4a915eb5,0x9a8e0d3f, + 0xd0123660,0xa2de157d,0x65ead2a0,0x45ef43b2,0x188db285,0xd0a22ade, + 0x922e0caa,0x8abbe39e } }, + /* 148 */ + { { 0x3a2d2f01,0xb4446905,0x5dc6685c,0xd27c3193,0x1d74a027,0x6a908bbf, + 0x5b50ec1d,0x01da350f,0x3f3c2e26,0x1d3dd45e,0xb836ee92,0xf66e11d0, + 0x474b979c,0x7e03908f,0x98b87834,0x19e7c5b9,0xbd3d1de9,0xa741d3fe, + 0x1ef6059b,0x63c68e8d,0x3674e247,0x9b9ff939,0x3e7e67f6,0x1d7d53e7, + 0xaee9e248,0x698dc326,0xb3bd984c,0x52f23eda,0x6f8fe8a7,0xf95e31b0, + 0xc3d0ba95,0x0f15b4d0 }, + { 0x790a8d85,0x8f2f6635,0xe2595af1,0x51bffbae,0x24b51287,0xd15b7ec6, + 0x3234715d,0x7639b6ab,0x2bc5441d,0x0cdd5299,0xf6d05833,0x54800ea4, + 0xf6d6e360,0x21efd752,0x19290613,0xc0b7ffe5,0xeea898cd,0xb68a5825, + 0x22982266,0xecedba92,0xbbd06bb2,0x678a91b0,0x4bb6b0cb,0xb2436dc0, + 0xcaf8ea98,0xcf7a99e7,0x71aa05bb,0xb92d0e6e,0xf5993eb1,0xbf8d0471, + 0x20385ddb,0x515db378 } }, + /* 149 */ + { { 0x6f5bef22,0xee43eaaa,0x20348712,0x952d2698,0x7a3af6c6,0x1e4c484e, + 0x9a8c9403,0x18d434c6,0x5001899a,0x63e5d741,0xfe8ea40c,0x5238dbbc, + 0x96798721,0xca6cc8d2,0x04acbde8,0x73db6aee,0xb7f993ce,0xbf69328d, + 0xad45e334,0xa3f79bbf,0x7c1f1630,0x8c51ec93,0x9b00a6de,0x4907325f, + 0x12d82bc3,0x49e6acb4,0x0ec59fc9,0x5901b36d,0x9cf34e3b,0xcb09b710, + 0x1abf4c02,0x2de0487e }, + { 0x8dd9d484,0x18b722f3,0x7c77bacc,0x83349393,0x93d92b8a,0x58dbb8f1, + 0x8e3fac25,0x80d78d50,0x745f4a7d,0xf0500981,0x877cc29d,0xd072bfed, + 0xc30a89f8,0x67abf8f2,0x9a0820d7,0x92c567ea,0x8a3a5738,0x425ab12e, + 0xf055521b,0xc162faeb,0xb94ea5e9,0xee1c4f26,0x3d71e546,0x1e414994, + 0x43e8be1d,0x258183b8,0xef9eae0b,0x44917c82,0x73874a30,0x6813a457, + 0xcc42f86e,0x6f6ac071 } }, + /* 150 */ + { { 0x4dd6e3b1,0xd38822ad,0xad620869,0xfc78e1cc,0x2cacde80,0xe7843845, + 0xa8469fe3,0x121cc14a,0xe67e8ef2,0x8e8f3da7,0x4d347448,0xdb83d16e, + 0x798631f4,0x3ba1dd98,0x0a4c4c17,0xdfab5977,0x3edc701f,0x1f0a1306, + 0x6cd8ff28,0x4649d601,0xbcc55bc9,0x2267230b,0x5760412a,0x02a19c60, + 0x328faef6,0xc719d5f1,0xf67eaad9,0x27cb969e,0x719bafb5,0xf342530e, + 0xff5a82cb,0x6e2c24cc }, + { 0xadaf8793,0x6313024b,0x035c948e,0x944bccf1,0x953500bf,0xe9a066b7, + 0x1d116765,0x7991a946,0x9fd93c78,0x95addb2e,0xe92e5495,0x05d2c037, + 0x9f03e5cf,0xcb145b18,0x95aa1f72,0x81ae48ca,0x135a6e4f,0x203f2702, + 0x49b2a7d5,0x2bcef5a2,0x02d7f2a3,0x0687a900,0x6c6745b0,0x2f7d3228, + 0x86507305,0x3da8a875,0x2e8dc58f,0xbe38b884,0xdbf11185,0x6b48bf34, + 0x97c08f91,0x5af7fd0d } }, + /* 151 */ + { { 0xf4a224a5,0x55f9b950,0xcc50273a,0x41904574,0x643f1fd5,0x34f81330, + 0x0e50f783,0x996801bb,0x89581712,0x866d7403,0xa4091d36,0xdb9a405d, + 0x16a46fe7,0xf1e379df,0x83bf9168,0x8d04a93f,0x32b20bca,0xae4c8335, + 0xf72a1c10,0x99d334b1,0xd8195db4,0x8fbc9977,0xfba14b5d,0xcaeb3dff, + 0x76daf476,0x60fef022,0xdb5b72f4,0x4b948dfe,0xb6dfb062,0x5185c925, + 0x9609d4ae,0x27a9c381 }, + { 0xf12a93af,0x73c37346,0x5536634d,0x028b707c,0x498193d1,0x8efa58d5, + 0xef21b69d,0x4f83a5cc,0xa788a0e2,0x05cbb0a3,0x65b13c98,0x01031781, + 0x2b73784c,0xfea20e58,0xe50361f2,0xdf9713a0,0xd0cc22d9,0x31449a0f, + 0x7c5e2e1b,0x183752e7,0xb67044cf,0x6e44d6bd,0x733e177a,0x012dde95, + 0x08ee2c23,0x68b49669,0x1f5f1949,0xd9bb0541,0x6acd886f,0x95182c71, + 0xfbde9244,0x1c690694 } }, + /* 152 */ + { { 0x3a880026,0x5db67d17,0x125d95f2,0x89c4f0a0,0x3f6cb7a4,0x29050551, + 0x5cbbdca5,0x3eb231d1,0x972bcbd3,0xf8cffc99,0xad55a03a,0xcb4ef4d4, + 0x22867c2f,0x944d47ca,0x0ead1aa5,0x96d88548,0xcbc8b045,0x76a57cf8, + 0x005e55a0,0xdfe5844b,0x1d18a097,0x5e9e7e19,0x52923c74,0x957a26e8, + 0x7f5db339,0xd0867b79,0x63bed0c8,0x2553408e,0x689ad23c,0x1596e5d5, + 0xa504c339,0x7b8c13d6 }, + { 0x52fb6901,0x2fc43aad,0x16ca253b,0x1c0313f9,0x515aadc6,0x1475830a, + 0x7f577dc2,0xc93d1926,0xf723c0dd,0x26e52e8e,0x3eb9f6da,0x2f1e0eb8, + 0xf180376d,0x9979de82,0xb0834939,0x43e28ecb,0xa39c38e7,0x9a2d51dc, + 0xa8e3f6b5,0x6e6063a9,0x4b9b3270,0x4cf1da3a,0xd2f8915d,0x6e5348a2, + 0x50507912,0x5e75e3e0,0x20d383fa,0xaeffce57,0x8fd2fb29,0x1d6d53cc, + 0x696f4cd0,0x0e3c3ef6 } }, + /* 153 */ + { { 0x21ee1d83,0x3bc337c1,0x787b7788,0x97e08f6d,0x138fa4ce,0xbf709fcc, + 0xa0348e58,0xbaf77647,0xa55e672d,0x04f8babc,0x7d5ec5dd,0x0ed2919d, + 0x33e99218,0x8ce64bff,0x24b059af,0xac09fc57,0xdc5e32ba,0x506831f9, + 0x465af6a9,0x26a22677,0xc97f1ff8,0x3c5efe66,0xbc6087fd,0x1515e0d6, + 0xaa8edc6b,0xb1a39c5e,0x0e79ed29,0x3dd816bb,0xbc3788b8,0x6cc13769, + 0xc092a51c,0x463098e3 }, + { 0xc8bd0fa7,0x3a6408c7,0xce6bde49,0xd1764311,0x283ef7be,0xe315e108, + 0x99b5d938,0x8213cc77,0x45a49a6b,0xaf7f1581,0xe529e4d1,0xd00fdb0f, + 0xce66c9d6,0x55d38f77,0x1bd4b952,0xb4f7ccc0,0xaf71f986,0x8d975b49, + 0xcd64d00a,0x12b59fcb,0xa5a3bad7,0x1860e504,0x2b5c89f1,0x6d976044, + 0x7a3e231f,0xfed0c659,0x178cba92,0x58114c33,0x6698e11e,0xe2e74c06, + 0xa348b85a,0x7f8fd093 } }, + /* 154 */ + { { 0xc19428af,0xf24592ca,0x3a308665,0x192a1c81,0xe30bbd7f,0x42589812, + 0x836c6bb9,0x10db0723,0x598e4987,0x9c7a41e9,0x6ead6f4b,0x8aff179e, + 0x75862c44,0x70f8f9b9,0x6f21983e,0x6b3b0237,0x98e65152,0x25d83e9b, + 0xd751218a,0x3b2d26a8,0x9d6f1da6,0x9508281a,0xa5a81f74,0x8df78d05, + 0xe4687471,0xd79ee559,0x6787d8cc,0x2060ca57,0xa8476c95,0x427a84ff, + 0xe6435131,0x87b64c51 }, + { 0x4b30d3c4,0x87f46f65,0x23b4ef14,0xcdec4c5c,0x63ca4d68,0xb3b74766, + 0xcf3fb56d,0x1df34269,0x0fd7d46a,0xd4f139c4,0x6a69a8bd,0xa3b7c7c7, + 0xcbadd7d2,0xee56b4c9,0xac942334,0xb28ff342,0x786f1da3,0x0046fdfa, + 0xb700c82e,0xce5d149c,0x50966597,0xca30ef81,0xfcff4bdd,0x44a20609, + 0x44925268,0x0f2f65e7,0xd4021f38,0xe5b6552c,0x042dbbd0,0x77ea9c2a, + 0xd9c062f5,0x8c95267c } }, + /* 155 */ + { { 0x5fc1abb1,0x6655032e,0x12fe4743,0x2215af54,0x29f05ef5,0xfd657560, + 0xdc191be9,0xb0e73325,0xc08639b0,0x7ab3c65e,0x1c3e6673,0x67507f51, + 0xc8615555,0x638befc3,0x42f0c4ad,0x5d0188cf,0xd896186d,0x843a301c, + 0xb2c6741e,0x045603f7,0xfa3cd1d0,0xf7545c0c,0x4a40672e,0xf612affd, + 0x45b9e8dd,0x56197c9f,0x87922d74,0xb453237d,0x4b2d59bf,0xbf132e3a, + 0xb84a6a16,0x8afa1b73 }, + { 0xe793ac70,0x6b3596ea,0xeef6dd10,0x4c94ef8e,0x70422e40,0x926b4fa2, + 0xe9e5d763,0xc8c71dce,0xf512aadf,0x352fcb70,0xa883975f,0x1b7ba138, + 0x058c3b13,0x57991390,0x97740fd1,0x9692092a,0x160b0697,0x19ad945b, + 0x10837ab2,0xbc634388,0xf174bb71,0x76ee11c4,0xab1b80eb,0x6111bfc1, + 0x70ec458a,0xbc82bac8,0x312d3325,0xeee60127,0xb240adc8,0xb4118b1a, + 0x2b5a093c,0x67211191 } }, + /* 156 */ + { { 0xf55cf9bf,0x91e99306,0xa46b96d9,0x9b045308,0x9e7a65df,0xae3c1e1d, + 0xc731bcbb,0x453cb151,0xa4d58a61,0x14be5227,0x97c74cc2,0x39dac922, + 0x822e00d6,0x4d0f7a45,0xc62b03df,0xafeb1d51,0xbaa18b2d,0xbb1dc3a4, + 0xdf2b74f0,0x7f3c7178,0x896b6a33,0xfcd328a6,0x1dce055f,0xe95ed454, + 0x6a4e2b87,0x97fbc76b,0xfa59dce9,0xe5ec67f1,0xcc0367c1,0x052368ac, + 0x54e4a3fe,0x7c863916 }, + { 0xca7388cf,0x55e94b5e,0xc0335d38,0x17cc0a60,0x616f85ba,0x9b69b78b, + 0x10122980,0x705d02ef,0x1cfd0a79,0x565a6e80,0x7d1ee352,0xeb74a96d, + 0x427b9dad,0x5c8832ed,0xe6d5330f,0x96ea8528,0x18d24ee8,0x30d8862b, + 0x9ff939f7,0x9cd38ed5,0x01060252,0x690fc9a2,0x2303b3ff,0xc62d88b8, + 0xdd52b469,0xfc42d7a4,0x8cad2d93,0x06f8dfa2,0x60920438,0x50236090, + 0xfce855ad,0x32582758 } }, + /* 157 */ + { { 0x359e8c60,0xeb20e45f,0x364ca186,0xc71bb8a5,0xdff8e110,0x02b15071, + 0x4c93e578,0x074e91d3,0xb829d0d8,0xc0326e00,0x626a83fa,0x3c192258, + 0xfb29a09e,0x387a64d5,0xe5ac5c82,0xcaaa3d34,0xada2da29,0x8ed685e5, + 0xeb29650e,0x92720267,0x763802f3,0xf7184b19,0xdf6b1aea,0x23f5dd0e, + 0x25e6125d,0xbe1fa347,0x0c872a1a,0xd6287f9d,0xac57c3af,0x49aa93d2, + 0x5bda7656,0x1a4e6a71 }, + { 0x554d1267,0x1a126ede,0x1cd02b48,0x37f94533,0xce31fb1d,0xd70af04c, + 0x097dc012,0xcf410b0b,0x36c7b6c5,0x930e1d17,0xc6891085,0x902fee41, + 0x79fb638f,0x349ba4a7,0xacd6f8df,0xa16c5821,0x2e076ace,0xfb3b83c1, + 0xe501d14d,0x6b8d033b,0x20f2d2da,0x0593d452,0x99df1880,0x3752526d, + 0x9feb33a6,0xca32351c,0x1f6ef456,0xd91343bc,0x35b9dc8a,0xc74857db, + 0x85b4e832,0x856a7c93 } }, + /* 158 */ + { { 0x0d0a5583,0xa007d002,0xeda4658a,0x2f1301dd,0x34d939be,0x91c07964, + 0xa70c0836,0xa0cb6780,0xbe81e540,0xc0b4df95,0x5d4ac8b8,0x6cbbcd34, + 0x54756239,0x57c52ed0,0x1805ceb6,0xcac2dca4,0x79344255,0x915ee6ab, + 0x24c9a2a6,0x366def31,0x8c12c674,0xbd3b962f,0x7dbb7c3b,0xaab64f1b, + 0xe22bb95b,0x3c0e4553,0xc4c63b74,0x2408feba,0x2a4da631,0x3ca77312, + 0xc636da40,0x62889084 }, + { 0x8cb8d208,0xa457fd53,0x543f06d4,0x7a8f8009,0xf2eff2ab,0xb66de154, + 0xf72517e7,0xfddb28eb,0xf9389d2c,0x0149fe66,0xd85b88ce,0x79e8773f, + 0x0ba543f7,0x452e090b,0xb0b03fc0,0xdeb9b5cf,0x6c5ed77b,0x3113448a, + 0x8ffc0372,0x3609f3cf,0x5c1b4c4a,0x2bc9c46d,0x8fa59be9,0xe66f3bf3, + 0xcdb02691,0x1396bf5f,0x009f88f9,0xf1ec59d4,0x2ad9dfe3,0xc2903456, + 0x5ada4d58,0x79d8122c } }, + /* 159 */ + { { 0xaa529507,0x14d4e4ce,0x74655d00,0x056a0814,0x4f0fc474,0xc0d30a38, + 0x3443cb8e,0x8a8203ea,0x97f1728d,0x33c62fb0,0xb520ef52,0x8a38dcfd, + 0x7cac9d3e,0xa0f90d5d,0x873cea50,0x28a7b0bf,0x6c6c41cb,0xd115ae3a, + 0xa13812c1,0xa35171da,0x624d507e,0x25d4bba5,0x7e98f42f,0x91dad289, + 0x96a41371,0xffd6b1e9,0xb69e5b77,0xd46c2125,0x20c4f707,0xc7d2b424, + 0x8142557a,0x2ab3af95 }, + { 0x6a5372a6,0x86ca074c,0x56292ba7,0x728fb83e,0x77741cf5,0x745596dc, + 0x520ef49d,0x70b4cea1,0x61e46472,0x1472fe34,0x3fb8ac5d,0xf4d6bd66, + 0xc10bc071,0x46e52cc9,0x371a3461,0x28794efe,0x276fe877,0xa4850718, + 0x9bef5ab4,0xedad5773,0x3f15c815,0x24c2d9ff,0x8f8395c3,0x188950e5, + 0x80b6a855,0xbae40996,0x8a8803e1,0x4f53e22c,0x039d25ee,0xaf233f61, + 0x250409ca,0x07db2c35 } }, + /* 160 */ + { { 0x037d4703,0xc7f3b8db,0xc5f488b9,0xe83708df,0x8471d402,0x1fba830f, + 0x5a2faae9,0xa55ee8d2,0x5404fc1e,0xc2e5bf10,0xaa2d5651,0x647d5027, + 0x7ebaf5f9,0x37a53c0c,0x95b30abf,0x7adf0bb2,0xd64c93ba,0x5a62e1fe, + 0xe2ef4a78,0x7ffc18c0,0x4d2cd04f,0x139dd9d9,0x5ea0af02,0x253fbab7, + 0x0fef9acf,0x7c8100ea,0xc8615aa7,0x74c5384d,0x9fe52069,0xcb28682d, + 0xcf7dd759,0x08b6ca8f }, + { 0x036c3b5a,0xe04e5bea,0x7f9f2b4b,0x38726102,0x29797c0f,0xa9fca570, + 0x82879ea3,0x1656180b,0x607f0ddf,0x153389bb,0x67b0e087,0x99a1223c, + 0x9d897fc7,0x0d1808ec,0x916edf19,0x9470711a,0x07217118,0xf8f52f2b, + 0xd18888b6,0x5d8b29ff,0x4cc6f900,0xef1e22c5,0xeb24877f,0xc4036165, + 0x35479525,0xfda95233,0x6861468a,0xd622a421,0x74faba08,0x5d043b07, + 0x0d31a7d2,0x2c337b02 } }, + /* 161 */ + { { 0xea22fa65,0x7b2305bc,0xd159f63a,0xbe183ef4,0x3f35923f,0x3473d87d, + 0xc11d7753,0xb27fb306,0x2a054cff,0x702e7e6b,0xaf185619,0x3ce9f97c, + 0x4e7d51c5,0x83550243,0xf356ac5b,0xa63e3d82,0xd7645131,0x867b7caa, + 0xa671fc9d,0xee85e6af,0x2b07cd77,0x3b985ede,0xffda5193,0x07d598b0, + 0xa942dc36,0xb10eca39,0x506218a9,0x17f3dcee,0x06b7d5ca,0x3d94e8d1, + 0xed8831c9,0x509b2634 }, + { 0x48caed54,0xb1b9414e,0xcbf51e97,0x77a78c6c,0x4de9b258,0xa4688c8d, + 0x91ee3d78,0x0024137c,0xe30ee64c,0xa68f9234,0x88190d78,0x573255bc, + 0xba80690b,0x41e8e05f,0xec354f4c,0x50038d84,0xdfa52816,0xb18f02d6, + 0xccb63fda,0xc47f9007,0xe98ae455,0x29d480fb,0x5d0e319d,0x4ac45d22, + 0x026db719,0xd06f3575,0x2c3587b9,0x733b9e20,0x2c317727,0x22483992, + 0x54bb8752,0x1592d5a7 } }, + /* 162 */ + { { 0xcf7453f0,0x5778d9a2,0xed83c1f0,0xaffb899a,0xe0a82ba7,0xae6506d3, + 0xea3d5081,0x32c84e1a,0x810aa38b,0x9ad528c0,0xbd37d041,0xb1fdb020, + 0xd06ce41f,0x78d6cbe1,0x2e74b7f6,0xd287f0f0,0xc43bb022,0xf5cd2575, + 0xf81a71b3,0x6d28f2f3,0xc633e7f4,0xe65bb1f5,0xc4fc580e,0x32e5fc1c, + 0xbb7b07a5,0xcd55539f,0xc3caaf3a,0xb5a94471,0x4cc22d2d,0xb958bdf4, + 0x77a2777c,0x1614bdbd }, + { 0xed0ab04d,0x4c1f0230,0x6e2082ea,0xae347b00,0xc42c5b5f,0x9f10bc63, + 0xde019935,0xb0539e6f,0x65dd0825,0xd89bd4e7,0xbbceda16,0x92260fef, + 0xe62aca32,0x8aaa755c,0x5ec82c5f,0xed762fa9,0x18650768,0x99e64c01, + 0xc92e348c,0x57dd6245,0x31ea6d68,0x0db88a77,0x07b44736,0xef0012ab, + 0x171d70fe,0xb9356b94,0x03f891b0,0xe68b0628,0xb79c20a2,0x3a54a53a, + 0xb00b0728,0x489656c7 } }, + /* 163 */ + { { 0x71353c25,0xe43649ba,0x13f67e24,0x517f27a1,0x1c1eb9e3,0x10bd333a, + 0x78e29bf9,0x94e1c05c,0x4743f15d,0x84fe7d97,0x90da2df0,0x9c874908, + 0x53673be1,0x82403fa7,0x1baea1b1,0x7ebf5db4,0x24180ead,0xcfe0ae35, + 0xc2f50c3f,0x1d15873f,0x70661cd9,0x16851ad6,0xa51e8c2c,0x802968d9, + 0xe0161099,0xe7d1a9cd,0xa8a7ea56,0x2b153c89,0x06e3c498,0x6d41b789, + 0xd6769dcb,0x082bb2e9 }, + { 0xc4d6615f,0x6180ef46,0x01b9829c,0xfc629dc1,0x0fb264ca,0xde222ec0, + 0x10ecc2c4,0xc5457e06,0x1eea2c4d,0x95ce599f,0x8f9c5b2c,0x0433fa72, + 0xcd6310f9,0xee035462,0xce2e2253,0x84c57c3b,0x96d87e44,0x6c8ec31a, + 0xa452c5a7,0x30bfe393,0xa047b235,0xc592b140,0xc018545e,0x7bd8be18, + 0x5c178c46,0x794e0107,0x2e23005b,0x48471946,0x622a54f3,0x2665e237, + 0x901c9042,0x36451a46 } }, + /* 164 */ + { { 0x19893e71,0x17802d18,0x539a2082,0xa1765d8b,0x2302ecfc,0xfc6aea01, + 0x365bf59d,0x8d4cf51b,0x0d232a80,0x87741d72,0x18e80427,0xac343eb3, + 0xe74739ec,0x553ecb2f,0x1a8b07ca,0xaeca79a8,0x56f4ab3a,0x089ff322, + 0x3fa1d1f7,0x5e95d729,0xf62a9a16,0x260569ae,0xaa08ddc2,0x5e776232, + 0x1b7bb54a,0x93fabec3,0x743d56e7,0x48a20956,0xeb0ebeff,0x749cdb12, + 0x69b8fcf1,0x705307a4 }, + { 0xe488310b,0x7a8e4c04,0x5325cd7b,0x12726e32,0x4983efac,0x5d0fd8b0, + 0x02ddb913,0x796e552c,0x77b9685c,0x0eeca3f7,0xb15f24a3,0x9b766e89, + 0x48efc979,0x7c2736d6,0xa8021c6c,0x3d619685,0xa0b2f1ea,0xfe33e278, + 0xb676d6b0,0x95c69879,0x1af4e0be,0xa0747319,0x36c4ee55,0xa2fab5f1, + 0x59e5f3b9,0x6938b8ff,0x39cafe6e,0x1e114da4,0x6a6ad120,0xc9595ec3, + 0x57e62aec,0x80f79bd0 } }, + /* 165 */ + { { 0x60af09b3,0x3cef42a7,0x933dfe14,0x3c016ebd,0xed85eaa8,0x720cf1e0, + 0xceaa3bc9,0xd4f5e99f,0xb7106f97,0x7216b9d2,0xc9668ad2,0x65f34c36, + 0x5b0c651f,0xa8fb82bc,0xf2fda4de,0x20f42f1c,0xd21f659e,0xeb31ab2c, + 0xa13d1618,0xb7a776c7,0x38662be5,0xec441022,0xcad08e0b,0xc825da70, + 0x022c0180,0x99299079,0x2aef9ffd,0x7623bda0,0xf5c58b50,0xde84f4f3, + 0xd824ff19,0x5f5a5da4 }, + { 0x7e8311dc,0x5737257e,0x466cf136,0xdef94f51,0xb05ca21a,0xa73e1645, + 0x02e4ab37,0x38ea9b3c,0x8579165b,0x7760eac9,0xc24b01a4,0xdffdd047, + 0x3fb95584,0x188d4fd1,0x25548bda,0xfaac38b8,0x59e9dcac,0x1a79a6f0, + 0x09a2700f,0x983f720f,0xfb8a7e48,0x8cbba554,0x47a1fad5,0x38a19968, + 0x5abd6b5e,0x11856547,0xf3716ec2,0x75113d31,0x4212907b,0x1391e781, + 0x0dc15889,0x5319c801 } }, + /* 166 */ + { { 0x6b61c3af,0x2320136e,0x07b4bb68,0x1d40f2de,0x380c97f0,0x651dee7f, + 0x6a8c313a,0xa978ba70,0x2011ca10,0x22c587d6,0xab1f445b,0x48bba218, + 0xe50444e6,0x8c5eaf07,0x442fccf9,0x5549f02a,0x3d80493d,0x2564746f, + 0x79c04591,0x42d24f61,0xabdc8887,0x1600fa18,0xded38f8f,0x5cb8600a, + 0x923aeb46,0xa4bf9b90,0x1e1c578a,0xd63fee35,0xebb9ea14,0xf3c9c5ac, + 0xf11a4ff0,0x3d13314d }, + { 0xb4513d1e,0xe5cc662d,0xd55952bd,0xde78a8c5,0xe7f86d0a,0xe8a37a3f, + 0x7a04f0c5,0xca2d12a4,0x2e25d06c,0x4c6696e4,0xb2136071,0x52614698, + 0x89f6e1cb,0xf4d2701b,0x80efd95e,0xaafd6177,0xc5bb6907,0xe6d73ac4, + 0x420db35a,0x49e874ac,0xf2751fa0,0x11631de4,0xa1fa2edd,0xb29f7336, + 0xb7fd794d,0x4c406864,0xe22f92a6,0x73cb21d3,0x2043cc76,0xeae904e6, + 0xb322c6ad,0x67f28a9f } }, + /* 167 */ + { { 0xca148ab5,0x7c17b258,0xb3c60051,0xb9a1976f,0xc8f28df9,0xea260698, + 0xe8d45017,0x87b2cc74,0x0578a422,0x37257329,0x17bec732,0x81d5ee25, + 0x1d48bbc4,0xd7411fcf,0x487f5cfe,0x46217e6b,0x41eb8e1b,0xcb007ac5, + 0xe05a00c8,0xc41c57a6,0xd2f9fa99,0x1f954d2b,0x40941cad,0x370bd5db, + 0x3829509d,0xe487879c,0x5ceca5ee,0x4c137552,0xfd3efb9e,0xe8ef7fa4, + 0x1bd1bdb2,0x5ff09174 }, + { 0x579c6632,0x791912a4,0xb8a20815,0xbb19a44f,0x535639d3,0xf4f97b84, + 0xbc3c9bce,0xe57e2bcb,0xf19e6410,0x122b3f2b,0x1357d9ad,0x1f0189da, + 0x79e5ff66,0x675573bb,0xef2f3c4c,0x444e5c98,0x04d10731,0xd6f61e20, + 0xac75d635,0x0dfa366f,0x2c854f23,0x9fc47c86,0x0ad0850b,0xc04ae43e, + 0x2f720c32,0x5ce94f64,0xa753bc9d,0x67efae65,0xb0373a63,0xc27d30d3, + 0x29721646,0x6681013a } }, + /* 168 */ + { { 0xe84509df,0x1385d913,0xcf339376,0xe978bedd,0x3423a148,0x2df425d3, + 0xee8cb579,0x43fa0ae3,0x31c4553c,0xf015369d,0xdfbf1d48,0x05cf08bb, + 0x9444244a,0xadff4be6,0xa35dda33,0x01635f81,0xe76fab7c,0x085c8949, + 0x16737783,0x4bd7fcde,0xa254f8d2,0xfd8cb52c,0x413ec985,0x62168a66, + 0x7a9026cc,0xf2db9741,0x50e1e1b7,0x3962ee56,0xd3beffde,0xbee0a346, + 0x0bdfab1f,0x3b35b72f }, + { 0x535c3749,0xbff8de9f,0x8add9c48,0x23c1f20f,0xc8f8f663,0xa975b37b, + 0xe8f3ae49,0x2529e475,0x1d5e2628,0xc32f10d5,0x67862f1d,0x5ac0d297, + 0x854cbe36,0x13c79338,0x4b67e462,0x48f004ef,0xe5d10ee1,0xfa37a150, + 0xd28288a0,0x4974778d,0xcfb73f4d,0x96830a66,0x07804952,0x9f444013, + 0x9760b694,0x8233c709,0x25b75c99,0x8340cca5,0xc771f99c,0x3f62e40b, + 0xcd95c685,0x47d0a1eb } }, + /* 169 */ + { { 0x652811f1,0x266f4fff,0x62ef3002,0xeaacaa93,0x50cba0ca,0x6c387a55, + 0x007f5467,0xa350142a,0x202f2673,0xc7fd102a,0x33dc6e65,0x5daee570, + 0x064a63d9,0x60682ec3,0x462b251e,0x46cf0bb0,0x5da936e7,0x0e030ca5, + 0x434265b5,0xc87a60f2,0x69b4e8f5,0x9637b2bb,0x7ad7770a,0x601fb58c, + 0xed3a15a6,0x1f2147f6,0x2995e961,0x05b47d5e,0x83213a16,0xcb0ca9b3, + 0x4995a85c,0x8f4b614a }, + { 0x4b4eb3c1,0x5aa8ec19,0x20323a70,0x8c549ac4,0x4f6cc6aa,0x00d49322, + 0x45f9a5a3,0x0e53b9bb,0x0897abbb,0xe46ef110,0xd7acd7d0,0xfe873e57, + 0x0f7cb588,0x7cfccfe5,0xc85557d1,0x0ea53d65,0x7288f2e2,0xfdd9eb44, + 0xc0eb68a8,0xab2dedfa,0x08603a0c,0x58221470,0x00feb06c,0x69464689, + 0x25e5caac,0x804cf5bf,0x9fc91ae9,0xd8559858,0x73c45eae,0xed9378b1, + 0x524c9801,0x8f942d02 } }, + /* 170 */ + { { 0x8e845808,0x1f1ec302,0xb77abfc5,0xc302bffa,0xf8d97dc7,0x26afd4b9, + 0x3aac594b,0x3d3a83c4,0x674d94dc,0xe3b74bd1,0xcaa5911c,0x4464b737, + 0x871c2cd2,0x62925773,0x3b4440fe,0x419f2485,0xe052ad7d,0xdda6a0f3, + 0x846c86c0,0x645280d6,0xf8324f42,0xa25689fa,0x07cf117a,0xc74ad1e8, + 0x8ddc9db7,0x5626dea0,0x966fc85d,0x52620373,0xf3b1eb53,0xe0ad57c3, + 0x949c1acb,0x38300252 }, + { 0x5e744723,0xa0ef5a40,0x1ae08481,0xdb5bcf75,0xfec1f76f,0xabfad8cc, + 0xfab37fc6,0xfba5d831,0xc8fedb78,0xbe39e248,0xad93f310,0xa5cfad5f, + 0x913d5c24,0x747fdb1e,0x4518b7f5,0x052a47c9,0x7cfb4327,0x9e208d6c, + 0x70e538be,0xb135cb9c,0x5bb17916,0x36352759,0x5b3106c7,0xa2c07880, + 0xc209bb06,0xd2d42a06,0xd3c504ad,0xb525b471,0x822ce034,0xc9f4b368, + 0xeb4185a5,0x15f18796 } }, + /* 171 */ + { { 0x0aee4684,0x094dea06,0x7cdbdbc8,0x42b21f06,0xb1931319,0xa439e149, + 0x81a7dba6,0xea4bdd41,0x3c2ae80f,0xc6213706,0x12823dc2,0xb58b0967, + 0x832611b1,0x7443d515,0x13c20384,0x2e16f831,0x2bd992d2,0x0ce204d6, + 0xf419388b,0x499dbcd6,0x1d3778c7,0x492ded1d,0xc5ddae73,0x9d5bd74f, + 0x994b6259,0xd4813d52,0x0e86ca68,0x191d9cf6,0xf3e9c2ac,0x562179ea, + 0x9fee1238,0x6146f1f3 }, + { 0x078e2aa6,0xbd06d33e,0x9dee9265,0x693af7f7,0xdaa40e84,0xd56e0f81, + 0x9b9a407e,0x05fbbb88,0xede99519,0xdcf44adc,0x092dba39,0x7f71f8d3, + 0x4231774b,0x675b5da5,0xa5f605eb,0x7456a251,0x87a39a9e,0x9031d4af, + 0x05b474bd,0xdb430006,0xb665aa91,0xbda5dbf2,0x6631eeb4,0x5d1a3df5, + 0x62377c58,0x028149ef,0x685d0bff,0x2e1af4e9,0x82a465de,0xe0ea0875, + 0x06bd0050,0x95543f9e } }, + /* 172 */ + { { 0x85d7c6ef,0xf7cbc6f4,0x63b1bc24,0xcad8084d,0xbf8cba62,0xdf90ce88, + 0xb455c192,0x98e4b686,0x774fc6ed,0x6146b8d5,0x7ae20077,0x70e2389e, + 0x61c22529,0x5241c479,0x3884e5f5,0x7d221510,0x17e28273,0xd6d20ce2, + 0x4f2674f8,0xe3119f51,0x70c011db,0x85459055,0xfcfb760e,0xdfab75d9, + 0x9e8c2a19,0x9546362a,0x4a7d4b27,0x4b6d3f8a,0xee5d698c,0xa5c87104, + 0x2ba296ff,0x6db43478 }, + { 0x5c3f0d95,0x06486493,0x4e748895,0x8917db82,0x6b2f3e44,0xf73fdf62, + 0x2b7f574b,0xc60edc54,0xaf732723,0xbe1c09a2,0x7cad114c,0x7d34669d, + 0x321aaff9,0x9646600a,0xed0cd61c,0xb94e2bba,0xdec4750e,0x866e1a41, + 0xb1a89f58,0xa1be990d,0xf2759693,0xc39e4d6c,0xc0e0dddf,0x11cfb780, + 0xd99c8a41,0xf0afcd7f,0x6e1c3050,0xcebffadb,0x96d2c6e4,0x4f3981b0, + 0x2ae27a94,0x07a791e7 } }, + /* 173 */ + { { 0x1e9f0300,0xe70e9047,0xbccdf904,0xe0253ad9,0xff053078,0x51c0289d, + 0xae893462,0xf1ef092e,0xa4846845,0x2c90a91a,0xf1dad4b4,0x1946eda0, + 0x33df67b2,0xf07650f3,0x0b15a014,0xc6e988db,0xb542f0f9,0x72e0c66e, + 0xe0c0378f,0x5d4b6311,0xae86950d,0x548badaa,0xb35f1c8f,0x6801638d, + 0x944d1ad4,0x129e3216,0x40471d32,0x9951bac8,0x85e94dde,0x03cc29f3, + 0x4543ecac,0x6d6acc2e }, + { 0x57b2d299,0xeb999e95,0xe3d721cd,0x3a2bcd9b,0xbb4cb444,0x2e60384f, + 0xdc060faa,0xae177709,0x8c987cde,0x74f0e6d3,0x1076fbed,0x9a237cf8, + 0x7983fbff,0x69af1513,0x323f9584,0x6c3f7a1d,0x6db64398,0x3e21cacf, + 0x96703d92,0x7cd8134f,0xb8393f76,0x0755898f,0x2e825222,0x1b5b28bc, + 0x7924aa7c,0xb78799c1,0x81427a8a,0x1db378f2,0xff289492,0xd5a451b1, + 0x3d3c46ee,0x79d18212 } }, + /* 174 */ + { { 0x109d5589,0x1a3edff9,0x029b4499,0xded52eb4,0xb4b54adf,0x13eb9d30, + 0xa27bff67,0x4f9214c1,0x67f0f460,0x4c817ee7,0xc3a50e28,0xbadf8d83, + 0x94026237,0xc5dc03c9,0x966647c1,0x5f29581b,0x8a0687f3,0x10b6a089, + 0x31634517,0xae787cec,0x62e75188,0x2001dba5,0x45e2c3fb,0x55d4e1a7, + 0xb67d3395,0xbfcacdeb,0xbc6842ee,0xa1a0af9c,0x3e88580b,0x50590a2b, + 0xa784cdc8,0x73104491 }, + { 0x2648d676,0x44ca2cdf,0x4f1b12b1,0x9a85eca5,0x2980e1eb,0x1b9dac94, + 0x1ac8aa89,0xf30d3709,0xc719e195,0x73072ab7,0x2f703797,0xba518c82, + 0xac0067f6,0xac090e14,0x8dcd2927,0x0e6cfc70,0x21e7da63,0x4f5889e2, + 0x8371c7c6,0xb4aaa40b,0x8f7878c9,0x1f9dabe2,0xd84caf3f,0xf78aed6b, + 0x9e0e1d92,0x3c39dd07,0x122424dc,0x680be5fb,0x0bdc0099,0xf41b214d, + 0x5180c54f,0x6a8f8fc9 } }, + /* 175 */ + { { 0x53235132,0x62a1ed63,0x59dba88b,0x1db233f1,0x291efdd8,0x85625452, + 0xb25111ae,0xc7505297,0x1d701bd8,0xb5921af9,0x9774f45d,0xb4d05d72, + 0xf18e73ff,0x6e3d4c5e,0x899b3038,0x897d985f,0xc89b1558,0x8a9c30fb, + 0x4d13181c,0x3c92d1a3,0x2223320e,0x292e86ba,0x01ceed02,0xcf2454c2, + 0x583f309f,0x27a45f74,0xad0fd1a3,0x75a6102c,0xcb9c7538,0xdb4f45d2, + 0xdb283fd7,0x4752d8c1 }, + { 0xd5dff4d5,0x514d6cea,0x45a827f4,0x74cd5fdb,0x4fc7135e,0x1070a60c, + 0x1be5778e,0xdec0bb78,0x58dc6b08,0x271e12cd,0x54bc2496,0xb765089b, + 0x619098ac,0x6ddf2c63,0x67528832,0xfd6ebac6,0xc2508af1,0xeaa2d025, + 0x4dcfc1f0,0x13c2cda8,0x45510be0,0x1c7836a8,0x1a886801,0x3904688d, + 0xafaf2545,0x643132aa,0x2830a88d,0x49685577,0x8744b470,0x569491ca, + 0x75fb8552,0x3a6518f3 } }, + /* 176 */ + { { 0x224042a0,0xaaa8ed50,0x2452f1e6,0x6cb4e3b0,0x768211d8,0xedca5f4c, + 0xef4d5d3f,0x4e0fe3f9,0x522d46e5,0x33a8e2a4,0xf1446775,0x5998e21f, + 0xf592d01b,0x1496c50e,0x83a67739,0x69104c2f,0x472bbf00,0x28670bcb, + 0x503177bd,0x8ea883b2,0x7d2712a2,0xc5d8bc05,0xb439c994,0x41ef9317, + 0xdcda1aff,0x9801d3a8,0x7038f6fb,0xd686eeb5,0xfbfbf820,0xe80c5cd0, + 0xedc25817,0x540ac363 }, + { 0xfe7f43df,0xa71969a9,0x2c1b9e4c,0xe6653808,0x859c2917,0xad9677d8, + 0x96aa4404,0xbaca9545,0xff1297da,0x0e9d855f,0x22aea7de,0x1f61897b, + 0x36f13f8e,0x96edccfd,0x16e200df,0x627d3070,0xc98988a4,0x729f0736, + 0x97f231d2,0x95e25e60,0xf6048752,0xaf7f221b,0x4019b299,0xd6682609, + 0x26b4b1d9,0x1d99de09,0x1acdd7a3,0xec47cf66,0x6ebe15e9,0x4de9f2b3, + 0xfa16974f,0x17db32ec } }, + /* 177 */ + { { 0x6cf40599,0x75ef6919,0x00c020ea,0x7ea10dfb,0xfcaaf679,0x3da5ae7b, + 0x88ddd678,0x0d663ca3,0x255bcfcd,0x5a21f8fe,0xe344bc7e,0xe9c3f538, + 0x548e0632,0x35f62b1d,0x43c6e64d,0x654f2425,0x26993627,0xc755a7a6, + 0xb0f41324,0xa3b7c5f7,0x3a2180f3,0x05697f79,0x1e81675b,0x6cf85fb1, + 0xe53428f5,0x6d3cdb35,0x52d28b02,0xe3aa1591,0xf7a3fb78,0xa8470255, + 0xa194445d,0x460bd01b }, + { 0xc24d8077,0xbc34dc23,0x4c720d2c,0x82f4b580,0x6f5d1ffe,0xa29da911, + 0x92783ce2,0x578af520,0xb5904af3,0xe29f51ab,0xf7aa1190,0x46c570d7, + 0x571bddf0,0x4a522fba,0xae89bb51,0xbf4e2a06,0x59f3444d,0x799b35cc, + 0x26cc2557,0xc3028367,0xafcec177,0x94a4e985,0x7c36cbd0,0xadaf7dcb, + 0x75d39077,0xed31b787,0x2d3e24bc,0x52d6904f,0x1f95421b,0xc5ca2669, + 0x1734878d,0x7d342c3c } }, + /* 178 */ + { { 0x11fd127f,0xe5cf2c0a,0x119e4c5e,0x66d36bb8,0x6ef56ac3,0x621ab252, + 0xe5430675,0x30cfeaee,0xac3e9619,0x2ede27d2,0xf8fce671,0x6413513a, + 0x075f4c3d,0x6159c61b,0x59069d98,0xd447efe9,0xea76aea9,0xaf8d6f68, + 0x0f5bd164,0xac5dc61b,0x1e88bb98,0xdbab446e,0x1ba92320,0x618b8b16, + 0x78989865,0xa0eafb3c,0xc08b7e82,0x0c7abcc2,0x20d160bb,0x10f09b6e, + 0x8e4c63a7,0x5be0afa6 }, + { 0x1bbbf49c,0x82ab6d38,0x8c0703fe,0x3e09ce49,0xe10f4263,0xeca58b5d, + 0xda5a4532,0xd9cc6581,0xf618f7b7,0x07e18876,0x250f7fe7,0x0419a5e3, + 0xde6b86be,0xbb1a9e90,0x37359169,0x584a7deb,0x5149db2c,0x38eb3489, + 0xb0ebabb8,0x14546a33,0xc2f88a92,0x0067f0b0,0x0a2db019,0xbde0dfe7, + 0xc63e6f3e,0xba51b06c,0xe9206fad,0xa19127b9,0xfe80dc0a,0xe4eb5e87, + 0xd4de30ae,0x1e6fccf5 } }, + /* 179 */ + { { 0xaa8ac924,0xb57dff66,0xc298b3e8,0x06e9ad31,0x65fb080c,0xd140e329, + 0x1d95c93f,0x7dab211d,0x8a180caa,0x6d68d842,0xa20ded69,0x1a929408, + 0x38df461f,0xa8151753,0x60eae932,0xff5604ae,0x7dae4c0b,0x901b9e49, + 0xde262e89,0x4573a97f,0xf1084983,0xed69d9a4,0x64724f1d,0x8ffa022f, + 0xea85a15f,0xd5f1c2e4,0x01453794,0x4c626ce9,0xbf0907dd,0x80440cd6, + 0x5ddaa837,0x4522d461 }, + { 0xebfbe7c5,0x8895f079,0x84ef3446,0x30ea1ded,0xd4a1ab96,0x716a9eb6, + 0x50a30c68,0x1a4a5d22,0x0043bbaa,0x5a16631c,0x5010e5f5,0xbd107502, + 0x3d8c0556,0xbffe3e9d,0x07772419,0x31b30b18,0x84b82297,0x90ff7ef0, + 0xf21a18c3,0x00c37d75,0x565bb8f8,0x18d0a635,0x45e3bceb,0xbac1da2a, + 0x23f0b08d,0x1c38e90c,0x5fbc5ac5,0xf1ba1aa2,0xdda71fc6,0x09d5256b, + 0x6d7e40ba,0x346501a9 } }, + /* 180 */ + { { 0xcc2b0f1d,0x86be448c,0xac4c3703,0xe3eb45c9,0x9fc96bbf,0x5387f65d, + 0x5ae27fda,0xcef3c4e9,0x1bc18089,0xa008f776,0x22ca18a1,0xf374a084, + 0x53b73371,0xee882842,0x7cc09354,0xcb6fc6d8,0x61496d6b,0x8489ec1b, + 0x49e325c4,0xa92c29b9,0x7bdec166,0x15c6ca52,0xdcea2813,0x95444eee, + 0x3a21154f,0x34683eb3,0xd39061cf,0x8fb26f98,0x06c940bb,0xc3b08aa8, + 0xe554c96d,0x7c1d42cf }, + { 0xdc110aa7,0x766e703f,0xf362e378,0xab7b79d7,0x5aadca3c,0xd259c75d, + 0x60be3373,0x2a6eca79,0x06c4e8ff,0xf4744a4b,0xf3b705bf,0xb2842cce, + 0xae304b53,0x1a3af5aa,0x1b2d31b8,0x7bbfa201,0x4bee88d9,0xc4ba6eba, + 0x565cb839,0x2d3565ce,0xdaf7ece8,0x24808696,0xe6959745,0x2c7ccce7, + 0xe94f9837,0xefd6eb3c,0x3811a326,0x0a33b4cf,0xfffa93a6,0x14203f43, + 0x73c31d90,0x031e9828 } }, + /* 181 */ + { { 0x765a17ff,0x4fefecfc,0xd1290a65,0xa09f3888,0x938da038,0xbf265c46, + 0xa169ad46,0x4bb6145d,0x23a62fe8,0x33cf8214,0xabc860a5,0x562df571, + 0x815c38c4,0xbf2a90fa,0x17eda875,0x45ba1d6e,0x946fa5e1,0x799d881a, + 0xb90f5a3b,0x6c1be784,0xb10ff52a,0x0910a37c,0xa4f4fd36,0xc38c1fe4, + 0x8e2d3ba0,0xc3180fc5,0xb17a6187,0x3e2ff050,0x943a35c2,0x3a00059b, + 0xa28cc51c,0x494d3645 }, + { 0x4ba021f8,0x398426b6,0x796deb6c,0xd14c9083,0x7e36c762,0x6d2e5395, + 0x751cf216,0x8f556eca,0x19b24a19,0xdaca1e00,0x4b20c2ae,0x47887da4, + 0xff41a733,0x93ed4ccd,0x5c7c0cd7,0x8d717c44,0x91bf7009,0xcc48634a, + 0x3b59bbaf,0xa1f146f9,0xe5624f15,0xdd38bb39,0x303f8443,0x96d41aad, + 0x4bf104fc,0x6b670f03,0x29706582,0x0503f9ed,0xb34200f5,0x768e1f47, + 0xbbd4c6f3,0x3cfdcc5e } }, + /* 182 */ + { { 0xb523e13d,0x536c2a86,0x2920d0a0,0x1014a458,0xe7571296,0x3d52b478, + 0x7eb51bea,0x05746066,0x87b0e919,0x709f7861,0x686888e8,0x028aed88, + 0xd94afcd4,0x79a809d7,0xe2129af3,0x50c6032f,0x983c4082,0x75e4be72, + 0x7ab3be8e,0x98331bbb,0xb618c728,0xd31a032c,0x3f59c4a4,0x36dd85a1, + 0xed4f61e2,0xdbece345,0x1e571715,0xba7aaccd,0x64a1ebd7,0x138c58da, + 0x3d1aeea1,0x89296d0f }, + { 0xcca82c97,0xb165288f,0x1427e8dc,0x26c6c12d,0x4c3edda9,0x66a94f07, + 0xeaa01ebe,0x94600e1e,0x30f5e86d,0x14abce7c,0xcb456a31,0x741d7020, + 0x279f42c2,0xab05aa13,0xd4238468,0x70b60faf,0x318d39e6,0xa18efec1, + 0x8920b318,0xeb07f1ac,0xd8399e03,0x01e3cba8,0x3c81a301,0x65f8932e, + 0xccc667d8,0xae8bca7d,0xa268607c,0xcee1ae79,0xcac0a12c,0x3182e64c, + 0x2b1a4c54,0x9233a2f7 } }, + /* 183 */ + { { 0x0acbee17,0x717e8df6,0x5c24fcdc,0x0f0959c2,0xe54ffcb0,0x46f09887, + 0xd285116b,0xb993deca,0xbba1fa51,0x0bfaa4f8,0xd0f2183e,0x9c9249ef, + 0x96847779,0xf93cb358,0x2322d421,0x284bfb7f,0xd42af009,0x40cc709a, + 0x9bb1d615,0xc69f2274,0x717c3c6a,0x76f50b3a,0xbb9c5eeb,0x8b21e985, + 0xa4783b5f,0x58fb19ae,0x52e1c3e7,0x04c86b9b,0xf2971ac8,0xaca59092, + 0x21ed8291,0x2bb26a69 }, + { 0x15f81416,0x98a34435,0xaaff5bb4,0x086e72e7,0x0317261c,0x3d1f64de, + 0x5c0a1cfe,0x31c0786c,0xb3683401,0x542ea4d8,0x1a39b4cd,0x2f77273a, + 0xcbef27f1,0x14fe7ee1,0x16bb27dc,0xee7fc09e,0x410e5dc7,0xc0dccc17, + 0x1943b3dd,0xa3466742,0x3f31c1b7,0x92934b60,0xc22c1070,0x0186ded9, + 0x799f966b,0xa37ee8ba,0x249b0893,0x0f3bfcb4,0x2e92d4de,0xbae61447, + 0xe196eb08,0x937cb3f8 } }, + /* 184 */ + { { 0x16fbfdce,0x57c0e77c,0xc98d4cc0,0xea034cc9,0x42572d20,0xe7606d72, + 0x0019a83c,0x9861b55c,0xf1597162,0x80ba2803,0x05a0fd7b,0x0f4141dd, + 0x4b0daaa2,0x8865913b,0xaa3848ec,0xe6685746,0x3e0485d2,0x16d15a5a, + 0x3b6905dd,0x81c0c774,0x818af2ba,0xcec31b7d,0xd2b74b78,0x80d8f194, + 0x543e2f28,0xca659db2,0x9fb07c1c,0x31b83a7d,0x1f1048c0,0x86537fdc, + 0x78586a11,0x4d57bb07 }, + { 0x53b396b6,0xbc4b768a,0x93b51dac,0xbc8b24c4,0xa30ae1b3,0x33e511eb, + 0x945147c5,0x893bbd95,0x179fe3ce,0x6cc86031,0x3f920bd4,0x34b0a167, + 0x6b256160,0xb32912eb,0x9d168d83,0xbc69a2a4,0xef0dd128,0xb4949e7a, + 0x872699e1,0x2613419a,0xbf21376b,0x06c58477,0xa4f97147,0xe55b1909, + 0x7b9b745f,0x63d6eb75,0x08df3c85,0xb5365b29,0x55fcfae3,0x0e257e43, + 0x979f2aa8,0x1067c118 } }, + /* 185 */ + { { 0x32bf8883,0xc8455084,0x6fd06667,0x4755286a,0x77c2335d,0xd70b0f8f, + 0x2f4a2c94,0x678e60da,0xd118acf5,0xa468d8ac,0xbf5b90d9,0xce93830b, + 0xed4e9104,0xea4b1c74,0x27776ea4,0xac67316d,0x361bab12,0xb98ad75c, + 0x99122451,0xc323d482,0x530a43ae,0x26440220,0x3292d5a5,0x3a44532e, + 0x5fecf1bc,0xdb48694b,0xc667b8b8,0xe4e0516e,0xa4306ade,0xb3aa595f, + 0xf34e9725,0x7e4f7091 }, + { 0xb7f70919,0x3f3816e9,0x16b003f5,0x765216ed,0x778c99e5,0x46c6cff4, + 0x30a51810,0xe6a5abe8,0x45e728db,0xef6f49e6,0xcaccefd6,0x6fdd73ea, + 0x8c37f3f7,0xec394e6f,0xb6407fc3,0x73320802,0x96625cbd,0x988e8f7a, + 0x7cabfb00,0x83292363,0x407f359a,0x258ba9df,0xccbfae50,0xff01aee5, + 0xfe251813,0xfbeaeace,0x83f1cba1,0x9c69f161,0x9eadcdb5,0x512c58ad, + 0x6ccce8bd,0x2ae49cd4 } }, + /* 186 */ + { { 0xc40849f2,0x1239b0e3,0xa441098c,0x5136a4cd,0xe547f649,0x61535a99, + 0x7a9bbac6,0x92e4bdc4,0x53547af6,0x195a1646,0x8b47a74a,0x85ecb319, + 0x9de6a2b2,0x278553fc,0x0e2ba52d,0x471c038a,0x35bcba93,0x12ba1b88, + 0x6f31eca2,0xd4bf50da,0x802b32c6,0xd146e3f6,0x3c64c8c4,0x0c9c0131, + 0xeed21297,0xad30f12d,0x9c68530f,0x9b75bffb,0x8918de51,0x23c0ad3e, + 0xa73771b7,0x180e9d52 }, + { 0x29ab77b0,0xc316542f,0xf7aee628,0xdd411d9c,0x353c2f40,0x044c0685, + 0x4b0ae4cf,0x638dc7e4,0x95fc266f,0xa0924185,0xfd2feb7d,0x639da671, + 0x5ea39798,0x56858ed5,0x58f3832a,0x7a694f31,0xd316d831,0xa94233c6, + 0x30a35a7b,0x2fcacb26,0xf1ff713b,0xfef8f7dd,0x59eee2f3,0x8b9b4525, + 0x156d064a,0xd1b4f91b,0x2f5cfcfc,0x177866c2,0x3777eb41,0x12bc2566, + 0xd8ab85b4,0x21ca6f3c } }, + /* 187 */ + { { 0xa3e66635,0x0e162b13,0x2a9f76af,0x1ef20a2b,0x46db3356,0xab473a30, + 0x7802bb8d,0x0840bd77,0xa699b44c,0x5b6baf5e,0x1b2207f1,0xc6e11900, + 0x790b0105,0xe5de16a9,0xdb67f004,0x22b12f15,0x8a025d25,0x185fad45, + 0xdf0a1142,0xbccf6953,0xf45034c0,0x4c42129b,0x1c277bff,0x0f740400, + 0x280a9e18,0x6e440b4c,0x842aa2b4,0x767de8f5,0x05e8d94f,0x3de20ab8, + 0x20227635,0x5aff5859 }, + { 0xa8458e40,0x805acd20,0x149732bd,0x5a5557d8,0x5f1ca72d,0xc7074131, + 0x952b5323,0x7f2e269c,0x6494fadf,0x5c592556,0x1a7d2666,0x153b7acd, + 0x86fe2865,0xa6df063d,0x57d53b6b,0x1e91db13,0xe93ead01,0x9195bb89, + 0x2963bfe6,0x3d71e1af,0x88278886,0xfab2b9c2,0x3b859b6f,0x77836692, + 0xf7029dd1,0x6e695174,0x7b984561,0xc7987876,0x5907d849,0x64fb4f1d, + 0x88d8a977,0x3eab7e1c } }, + /* 188 */ + { { 0x52e5718b,0xc73a94b6,0xf4cee1e9,0xe3aefa54,0x553eedea,0x654e9e63, + 0x5f3aca1a,0xf2541e1b,0x0d083316,0xd7129489,0xfb7f950e,0x7965af63, + 0xc74e3e4a,0xd8fc9e0d,0xeaf79ebc,0xb4ee48d2,0x8b7787e6,0xa458a86a, + 0xf7cceaf0,0xd8c7621f,0xdf67980d,0x8228eeff,0xf9106727,0x210d4742, + 0xb07e3629,0x91f63501,0x7971e29d,0x441761c6,0x03a3b8a5,0xc0ccc65f, + 0x38e09544,0x3491da4f }, + { 0xcb062eae,0x6706d046,0x5d08776d,0xee7db735,0x292315d2,0x80de8052, + 0xc402bbdb,0x40785662,0x26ed3337,0x5f93525c,0x7d568ed3,0x6cea14d6, + 0x66888b1e,0x916a1189,0x5dc71675,0x0fbd5205,0xe4575df2,0x833d1077, + 0xec092335,0x4e93100a,0x6cd85389,0x2f9e1d01,0x43226368,0xeebd3725, + 0x1ba4cfd7,0x401d172b,0x574c5838,0x377dab9d,0x80d517de,0xaeaa6958, + 0x6ad15a18,0x0c843dfd } }, + /* 189 */ + { { 0xc9373300,0x455811ff,0x99fdc300,0x1c39332a,0x353cb655,0xe19bb81c, + 0x96a83d27,0x774b924a,0xb2ee3f1a,0xcbfc8fcb,0x010d56c7,0xaf278ec4, + 0xe0abaf79,0x6fde682f,0x7339aebf,0x7566d072,0x71205db6,0xbd35ad5d, + 0x7051c9d0,0xb5bbe694,0xd3a3067c,0x577db480,0x572d7530,0x2c70ff54, + 0xe06d853d,0xe8615aec,0x05abfb5d,0x71999ccb,0xea0a8ed7,0xeeefc96b, + 0x35f6df69,0x2dcc469d }, + { 0xc65f0e77,0xcca6cd06,0xbd71b14a,0xddcc7980,0x3c93cc00,0xb6221f8b, + 0xae8cbf57,0xddfcd5b3,0x76f8e63f,0xbc92973f,0x06e132b7,0xe9848a34, + 0xd51ec9e2,0x4cc59a03,0x3a33081a,0x9c9d32bb,0x80e8466b,0x00121052, + 0x1bbe7295,0xc2b0032a,0x24938448,0xdbfc6572,0xb6bba0ff,0xe972a0ce, + 0xc0a94802,0xf60c0a4f,0x599d8bc7,0xf62c41cc,0x312da0b8,0x820c96ee, + 0xcdbdf9fc,0x5a1a65db } }, + /* 190 */ + { { 0x42485684,0xbfba691a,0x29c470c9,0x613116b9,0xe62a0519,0xb4b01971, + 0x5ff499da,0xf3245aa6,0xa5238eff,0xc2ef87f4,0xcc9d5515,0xc16dc6ba, + 0x2dbdacac,0x5a7f227e,0xa9bbaecb,0x8dedaac4,0x2e7c9885,0xff308a6d, + 0xe6895593,0x4c6f2fc2,0x177e0611,0x3655f285,0x300b1bee,0xa63e8d06, + 0x13c17b54,0xbed0ce79,0xc4974262,0xca4abe35,0xbc4e4037,0xf4b44a17, + 0xefe5fbd9,0x5ae95099 }, + { 0x804f7455,0x122e5ee7,0x22066682,0x341a4997,0x7795e333,0x97d24c31, + 0xe48efced,0x12f4123c,0x19fbc21c,0xe8738d92,0x0663a3ae,0xbb3bdc61, + 0x8593a6db,0x3603d8c2,0xe3c1ac75,0x926227f2,0x5eaae519,0xfea92ac0, + 0xfd6812ac,0x5b596f0b,0xfc2a82dc,0x3ce7e844,0x63522b27,0x3840481a, + 0x52867895,0x836088b1,0x26588688,0x21ffb7cc,0x2f4a7cac,0x0ca33161, + 0xa3edd298,0x4110667e } }, + /* 191 */ + { { 0xc2d04b63,0x81830357,0xf4929a18,0x3fc5a34d,0x22d195df,0xc73bf6da, + 0xcb432473,0x14df2f89,0xe997f138,0x345afe5c,0x8b9604f4,0xd8e3f5f9, + 0x50c10ae5,0xad7942e9,0xeed25ff3,0xcefd5447,0x0e73c0cc,0xbf68e51e, + 0xab54fa4c,0x5b1ad591,0x12b61c8c,0x8bbc1105,0xb5abf760,0xbb932913, + 0x01e79649,0xdb1231be,0x040ccbe7,0xd0a83e91,0x90a96db9,0x3dde426f, + 0x34df11ea,0x1cceb645 }, + { 0x0c6d0f55,0x2d210c4f,0x9c673c9d,0x6cadf61b,0xa9ce3fbb,0xdd7f9919, + 0x93b063e4,0x135f494c,0x145a93be,0x580bdb3c,0x0f52ef7c,0x4d872332, + 0x8814bb6a,0x74d876e8,0xc7a97dee,0x4f6f723a,0x3e3cd833,0x7de2b8f0, + 0xae720270,0x6162f082,0xddfa486e,0xe88ec2d4,0x8d3a17c6,0xd965c859, + 0x3980171a,0x62e59e54,0xbbef6b22,0x0ab6285d,0x4d48b203,0x3cf45195, + 0x4ea25ea3,0x1f175233 } }, + /* 192 */ + { { 0x3467ea91,0x808a765b,0xfd2d9c45,0x3f4632ee,0x9cf2bc6f,0x7b75dc6d, + 0x359813ae,0xefc8d240,0xe44cbd8d,0x23ecb209,0x21525622,0x59ba10e3, + 0x3f1ee19a,0xfa14d934,0xfb0c48f7,0xdf97c21b,0xea30d437,0xc4e62890, + 0x651475c2,0xb286e2a4,0x126672a5,0x291f01e4,0x31aab3b8,0x9c6fda5c, + 0xe17d22ec,0xb7277a5a,0x914f0bad,0xbd88ed83,0x6a2392e1,0xd0b05d1b, + 0x65893c2b,0x4cb8af90 }, + { 0xbb4b1953,0xa2b02057,0xf597f6ee,0x4ce08b44,0x5e6412c8,0x854f5d9b, + 0xb3cd4919,0x1913262d,0x6e42bb5d,0x902762e4,0xd78e7f60,0x8355c8e6, + 0x38b6c16c,0x8efaa824,0xe550f618,0xd0173790,0xe57d778e,0x118af462, + 0x715b4714,0xa16ad5e8,0x41dea4f9,0x900596c3,0x280ca610,0x2a957c32, + 0x374c65a1,0x2faee800,0x50080414,0xdb105127,0xff080fa1,0x8c1db931, + 0xd79878fc,0x486a5c25 } }, + /* 193 */ + { { 0x941b4f36,0x0521e213,0xf803b4f9,0xbaacfb14,0x52a54ba8,0xfdf1e22e, + 0x8fe4796c,0xacfabbba,0x58dbacb6,0xae0788db,0xc19dfa51,0xdf98d736, + 0x35a716ee,0x155c286a,0x9c86461b,0xbe7d4676,0x63a64a5e,0x50b6380f, + 0x9f609262,0x14b41914,0xa2dfc5b3,0x0919a7d0,0xcef466ac,0xc454da55, + 0x6986aaec,0x93fa4a24,0x71a49ced,0x5090b171,0xc1fa75ad,0x602f1d6c, + 0x78e4c054,0x5d269f89 }, + { 0x14920419,0x3a74030c,0x90968739,0x0845d868,0xeeb70fa6,0x81b994c4, + 0xd9fc5bcb,0xabcaa06d,0xf58f8f2d,0x06539427,0xb1dc52aa,0x35c85f67, + 0x2c911baa,0x5a7d8d72,0xaec2d834,0x4041005c,0x7a8e5347,0xb5868a44, + 0x8de512c3,0x04ee180b,0x211168eb,0x4daa66e5,0x2317cd8a,0xc0bd5dab, + 0x61164df6,0xa1d4185d,0x1dbad7c9,0xacedca26,0x09b02683,0x0fe4b5ac, + 0x26d9550f,0x8ac9995a } }, + /* 194 */ + { { 0x2640a39d,0xb2c8dc9b,0xede0c9f9,0x21ff0b38,0xa1ecba0a,0x74f469bd, + 0x080d0417,0x8a902ccd,0xf4994604,0xe956fa32,0x9776ab15,0x348f85cf, + 0x0066f492,0xc21fc6ee,0xfeeef367,0x35b1ebfe,0x4613e5ed,0x7804581c, + 0xea6ba071,0xcbdfe8e6,0x950d73ed,0xddfcaa32,0x1da48889,0xc9747936, + 0xdbaffbd1,0xce867c8c,0x1cbaeae7,0xd267431f,0x897912c8,0x68255045, + 0xd7ea1e4d,0x0c7c1ddc }, + { 0x1ce963a7,0x53aa30cc,0xc4c5fade,0x7352f64c,0x2828afbf,0x2b9aa2f8, + 0xca212107,0x64273c56,0x85a576dc,0xaadd7654,0x90b5c77c,0x6196ac3e, + 0xd1aaf39b,0x20d43e9f,0xcd05cbc4,0xfc392062,0x4c0ff2fd,0x14163872, + 0x2ae821e6,0xcf32b8d8,0x3fa7a3f0,0x5f58f943,0xf644ca92,0xaebf1d2d, + 0x1918a75f,0x0c061563,0x6b876118,0x7989b5ed,0xad412441,0xbf342445, + 0x1df633ab,0x24ffc9ae } }, + /* 195 */ + { { 0x93c7cb2b,0x89fcdc05,0x590053fb,0xc1243b95,0x6182343c,0x601debcf, + 0x66c18a63,0x364546ef,0xec913287,0xa5290701,0xf9788c31,0xc35b8026, + 0x92d1f7d7,0x852b862a,0x0aa79728,0x1809cb05,0xa3cb2005,0x897d467c, + 0x9ef5b946,0xf20c77c0,0xf2241984,0xc3372c42,0xf35bb206,0xda053e0d, + 0xa9c140b5,0xbc26c6d0,0xcb56fb33,0x61cfcc0c,0x299b3968,0x1c3cf9ef, + 0x40621ba4,0x89e4d3d1 }, + { 0xa45a9be3,0xd35e80e7,0x07356fbd,0xc4daa578,0xb967bc2f,0x0186d62e, + 0x47cd16e3,0xa702679e,0x5f30ce9b,0xca2f1c02,0x1f864f50,0xf1205b46, + 0x85061d66,0x7fd6d797,0x8a08809e,0x47edc4f6,0x9a4d3ae2,0x5dac0449, + 0x6d1f9da8,0xf844664a,0xd7a83a71,0x9f30ce84,0xeaac33f1,0xe9382bac, + 0x948622ab,0x1f033831,0xf7681eb2,0xb037a4ba,0x99a1b5c7,0xd156a908, + 0xe6f1d0fb,0x675d3e6f } }, + /* 196 */ + { { 0x707193e5,0xd9767ffd,0x810358e5,0xe478aa91,0x328d8ef7,0x5634f9ff, + 0x6dbbd9a7,0x913a0ee8,0x7e215686,0x379b2968,0x89d9da38,0x903f410a, + 0x1b1334d2,0xd9f8d7b9,0xbd82efb5,0x9fe74229,0x3803c778,0xdb568b62, + 0xd3d25344,0x93e9a350,0x724497e8,0x559c35b0,0xa169e23b,0xc472d436, + 0xcc5b4c69,0x09864632,0x83c7f531,0x9f6d759d,0x1e497888,0xa91cf1db, + 0x60af1a4b,0x5f7f92fe }, + { 0x0545167e,0xf18a1cc6,0xaffa88e0,0x55ee2e02,0x432a7bcf,0x24cdff51, + 0xa7510866,0x7382da42,0x40511af7,0xe894c11f,0x2aaf1423,0xaa4e4e31, + 0xf63dd2ae,0x8c3d36f0,0xd7660635,0xfc5c9550,0x37ea7eab,0x01253731, + 0x39b950f6,0x2a5cd598,0x40e63442,0x95a0f601,0xf2ac7045,0x905e238e, + 0x446b0f73,0x44bacc0e,0xc448578a,0x4cd4206e,0xa5bd7803,0x367b1aaa, + 0x0a2b458d,0x25beced9 } }, + /* 197 */ + { { 0x0c33a8fb,0x079a7382,0x0f25dc1d,0xcfbf6cd1,0xc6d482b6,0x4ffc73f8, + 0x07bf844a,0x3e51f18c,0x599162f0,0xa7651236,0x14013811,0xac59a74e, + 0xe55018a0,0x957a6865,0xe3ca09b1,0xe1ec51bd,0xa960253f,0xbc0c7eb3, + 0x7de03f84,0xe83bfd14,0x52fbdb09,0xc0540ed1,0xcea15ec1,0x6ba52edd, + 0x4b261307,0xf3d30ed5,0xe8397206,0x9bd7bae8,0x096373aa,0xf20d8692, + 0xc3b0bf63,0x0a616a4b }, + { 0x6e1339c9,0x2075f3ed,0xbf8b00a6,0x7afaa072,0xbccd9b47,0xdfafec82, + 0x00ca54c7,0x4713158f,0x38bc31ae,0x449102f1,0x310dfc8a,0xaf98f158, + 0x59e954d4,0xc9ef2075,0xc527a0c4,0xe8021af9,0x7a192023,0x6e801277, + 0x7fb02377,0x635f538c,0xe8c9e951,0x5df1974f,0x15cc9097,0x0287faed, + 0xf7a5115c,0xfa0728f0,0x0fac623d,0x90dbfbe6,0x0311ba09,0xa8d40fd4, + 0x07c6464c,0x876d154e } }, + /* 198 */ + { { 0xc2d3ea8a,0xd3a4d6d2,0xa842600e,0x36be681b,0xe4070672,0xc53f100d, + 0x6a7d7a7b,0xe3e5b6fe,0x5d5e1a83,0x6e6994f9,0x76097c2a,0x07cacd22, + 0xa6791011,0x12d98dba,0x102e0e24,0xddfc4461,0xd493272a,0x4815dbc2, + 0xa9436696,0x7e38e64b,0x32b2bf90,0x4960eb1a,0xd928e28b,0xda457525, + 0x2a077c9e,0x72f75b39,0x7fd61d00,0x27760cbb,0x0f4b1456,0xaf235d1b, + 0xe76d1700,0x3040c23b }, + { 0x4efa9a70,0xb10dc55b,0x53e86610,0xd4de414f,0x09f8a27f,0x3d95c113, + 0x06661d3c,0x505109a5,0x60eb513e,0xcaa2994a,0x1e7d338b,0x3ee41537, + 0x4651e71f,0x4fd145fc,0xcbc313b4,0x51bbf838,0x1eb92150,0xb039e078, + 0x14bf5ac7,0xe8696b44,0x8be0d48c,0x2d667188,0xdd8f2b6f,0xbe93b2f5, + 0xeb8a7f8a,0xc1dfd1e7,0x90f751c5,0x862b3dd9,0xa32a74be,0x1eb1ad58, + 0x1ebbc9a2,0x5486d79a } }, + /* 199 */ + { { 0xa1359e13,0xcb2e34ff,0x28196051,0x202d8dbf,0x23564b5e,0xe95e023d, + 0x42f6ac12,0xfb1340b6,0xb653725d,0x543ba852,0x8d2466ad,0x81aedcd6, + 0x547c728b,0xbf780224,0x9569fb65,0x559f8a11,0xdfb22ec9,0x505b7a62, + 0x9eed5e52,0x07107540,0x299f6f11,0x9c899288,0x3db6f8c7,0xa7d69261, + 0xb3ca79a9,0x30eb7fb3,0xfb2160b0,0xcab99bb8,0xd28b409a,0xd2012568, + 0x5ac45f8b,0x380f1b0f }, + { 0xe6a0068f,0xc0b99e6b,0xc8a73753,0x4b67cf2a,0xb2faeb7c,0xa6c9a548, + 0x340260c3,0x7f417f99,0xcc0f739e,0x8ee56855,0x780949da,0xf08b510f, + 0x8d5c6eff,0xb1770fc2,0xfd96a7bb,0xb4f5abee,0xf2665a2a,0xa07b1136, + 0xb601dcf9,0x2fb380a4,0x162becc6,0xcc803614,0xee6b83b3,0x3498fb96, + 0xa8c17eeb,0xea9b0fd6,0xa177efc2,0x5834b5ba,0x5b110b3e,0x929044f5, + 0xebd7285e,0x4abedded } }, + /* 200 */ + { { 0x700ef376,0x3355e1b9,0x66cdabff,0xd56e5d9a,0x47e87646,0xb3dc2575, + 0x00f79369,0x28f44b8a,0xa0c52e29,0x08c32b1e,0x3729b392,0x5a78de12, + 0xb26d239d,0x4184519a,0xe0ce4a6b,0x23f6b4b7,0xacb2a9f9,0x235f6f8a, + 0xe2064a59,0xbb8bc454,0x1bf3062e,0x37efd034,0x94dff6f9,0x6bac683b, + 0x8aa7fa06,0xc3364b1e,0xce0b3745,0x0616772a,0xd1e3fb0f,0x46f08d08, + 0x18e132d3,0x6a20abb3 }, + { 0x6a85cbc7,0xea831016,0x934f9aa7,0xd0990946,0xe778f1b3,0xc2211088, + 0x2247b799,0x7ea4ff8f,0x454484ce,0xb3171d71,0x4f98c364,0x29403949, + 0x97df1458,0x5da911f3,0x09439116,0xa6b58093,0x174238bc,0x75f9509a, + 0x8209758d,0xfeb51821,0xa47925d0,0xae0c6021,0xaf8a315e,0x0e946694, + 0x6bad04b7,0xae7af8a3,0xf072447d,0x44c15e7f,0xa5456ffe,0x5184668a, + 0xbf36b977,0x45e353a7 } }, + /* 201 */ + { { 0x93092f71,0x76056764,0xf5b92d71,0xeb66b6c2,0xe2c8b6c5,0x9db3149b, + 0x20c0363e,0xf62f583a,0x03cd7097,0x688acd33,0xebb916ac,0x85d0c0f8, + 0x84c19b0e,0x1bf7462c,0x7c4a6ad1,0xc76ed5f9,0xd119f369,0xec8b88ba, + 0xebe50b83,0x59b8371b,0x866706a6,0x0cc69508,0xf8373d2c,0x531c75a3, + 0x2a5a02fb,0x4e1cd3a3,0xda39a1d0,0xe8274778,0x75da333e,0xedfc5bbb, + 0xca79bd36,0x15941f24 }, + { 0xa77dd512,0x42e8c0f8,0x1dc365f6,0xa91b59a7,0x08753862,0xe80d14cd, + 0xd272faca,0x1624230d,0x4027cb5a,0xeea3ec16,0xc1ef9f03,0xc1700b59, + 0x0da3148d,0xd411c127,0xc4181af1,0x801ee448,0x9e3a900b,0xedf28559, + 0x0d09affd,0x5d67b0bd,0x8b370024,0xd839df96,0xe6f836b8,0x3b6307e0, + 0xbd3201c9,0x5382e588,0x7a1d02bb,0x636d8a6b,0x968641e9,0x70b7db76, + 0x118fad03,0x6d17c34a } }, + /* 202 */ + { { 0xc181c99b,0xcf608841,0xc87bdcaf,0xb65dc901,0x3720dabe,0xb460b447, + 0x5377515b,0x4c79c396,0x0a96c277,0xd447f22e,0x2ac0f440,0x0d952130, + 0xc90583ad,0x8330b26b,0x928904a0,0xe25e977a,0x85c50b18,0x1deaffd9, + 0xa5ad5f6a,0xcf4dbcb7,0xc8a37ed5,0xcbcd0019,0x1e9850b6,0x7846dd90, + 0xb0b8e605,0x1ac8194a,0x34132f90,0xb9728571,0xf56ee28b,0x4ce9f149, + 0x3e9e1d4e,0x1ab9b5a4 }, + { 0x314fa7a3,0x206dab92,0x478ff963,0xcc4af0f0,0x904d9fdb,0x4cce1713, + 0x12c045fe,0xac20a2eb,0xfd8f6d7d,0x44fc5478,0xca7b6ffa,0x886e72c5, + 0x6fd6f758,0x7fa4529b,0x92a820d5,0x4df1d1b1,0x2789f149,0x3d812f9f, + 0xaabb53d2,0x9842f083,0x2a03ab32,0x2648539b,0xb1512502,0x631ce090, + 0x731f6bd5,0xe1294d15,0x9436e634,0xb229361d,0x3ca966af,0x8c4281c4, + 0xc21ab3ed,0x24b34956 } }, + /* 203 */ + { { 0x659824e2,0x49bdcb86,0x4e13e74c,0x6dc4ce48,0x6bbe1eea,0xa4c01a26, + 0x1e3ec457,0x47b2b8e7,0x2f5a8e4b,0x7e8b15e0,0xe333530d,0xe81eb6e6, + 0x17a45202,0xacba369e,0xd70e4c9f,0x81241431,0x3e12beb8,0xc190af4b, + 0x11f486fd,0x53270523,0x29fb2bce,0x9f6c41e1,0xb70f6c08,0xbe6287eb, + 0x3feb4477,0x1479850a,0x9bcf18bb,0xfcfdfb11,0xda80d040,0x925c292f, + 0x7e3c5bf9,0x212d65e5 }, + { 0xca15cf08,0x23adb386,0x81e172eb,0x4dfa4ac4,0x4d42d0c0,0x9d1dbf93, + 0x74404dc7,0xd9cf6073,0xe932bfcd,0x60508441,0x1c682a98,0x9ae910ca, + 0x41ac1cc0,0x9528fc18,0xdbbed630,0xe6a120ae,0x30ccf250,0x94e0e1ec, + 0xe58bbf2f,0xfe84ba54,0x9faa4415,0xc66d0b4f,0xecee7ce5,0x0c58f1e7, + 0x6fa6873a,0x7a1d43eb,0x399f1348,0x96c6c5a0,0xe6727ab7,0xe6ef9aaa, + 0x9a5c2447,0x66afa554 } }, + /* 204 */ + { { 0xc980e91d,0xda5aaba8,0x6ac98efa,0xa93cf509,0x8da32662,0xb0990e0a, + 0x0081453e,0x01d21530,0x3d71de84,0x2bb0d33e,0x3e19a012,0x465f6d80, + 0x78a838e7,0x5902ff4c,0x1931348c,0x74e2afb7,0x9cfb057b,0xa4932757, + 0x3ad03f8f,0x761ea642,0x58ffa40a,0xb7d4c245,0x77a87e30,0xb5e9c0d9, + 0xc9c84d26,0xd1c5edba,0x3d1963a0,0xeca8839a,0xebf6bf0d,0xbc6f2f35, + 0x0d58abdf,0x01ef0631 }, + { 0x3ecdcbb0,0x2bf90316,0x27c1c955,0x19e2d728,0x9575c930,0x9e527030, + 0x96983930,0x0dc1c5a9,0x7cd082df,0xef9f80ff,0xdf97e051,0xcd915075, + 0x9cc61b55,0xf286fffe,0x80f24cc4,0x352db38f,0x36523ae3,0xed9b99ec, + 0x10b104a9,0x109a8ca8,0x305203ad,0xc2700fe7,0x769400f5,0x2a2ee24e, + 0xee0c452c,0xd595d399,0xf7f02a41,0x0ab75d6a,0x0db730b7,0x34108099, + 0x5e8d1202,0x0e4f5ffd } }, + /* 205 */ + { { 0x0ff14c38,0xbd1c6444,0xaece11f2,0x9a5b59fa,0x22af6330,0xaa4605a7, + 0x82af24ee,0xddc9f65a,0xeb9a1159,0xf4ee4bfe,0x74e84eaf,0x2463d076, + 0x0e0baace,0x88cbe1e0,0xd5fabdcb,0x7ca568ea,0xc57eb99d,0xbd80d524, + 0xe9be9873,0x9c46572c,0x7300b85e,0x918a1dcd,0x40f54176,0x49221312, + 0xb5b14236,0xf7e324ff,0x2434f16a,0x40dda501,0xa133d97c,0x08833421, + 0x0876f020,0x33d41161 }, + { 0x9878e5ec,0x7531a36b,0x46918232,0x5de3e321,0xd0a30464,0xd15f9a33, + 0xaa173659,0x734c1b87,0xf925d4fe,0xac2094a2,0xc262b0f4,0x43c965a1, + 0x447d5cbc,0x759c903e,0x05239300,0x92af215e,0x1f593f34,0xfffb6d5f, + 0xc3cddb5f,0x65943b4b,0xbfdd5408,0x9d03a29c,0x198d76c0,0x8f7cda6b, + 0xc0f27b59,0xc0790a22,0x8cb58ccf,0xba557a84,0x76c54fdc,0x5922052d, + 0x47b6b466,0x2d3de7aa } }, + /* 206 */ + { { 0x65add3b7,0xaade7462,0xabf24c2a,0xe5888f35,0xe1a57d93,0xd41549ca, + 0x2c76f7bf,0x0e22e18e,0xbe3202b3,0x67f288ea,0x1d1d0f0a,0xb79a66ba, + 0x2881ad18,0x0e0ab749,0xc7adb0e9,0x7d424086,0x2842132f,0x870c32c5, + 0x58f9a09e,0x858477f1,0xec025589,0x422a9372,0xa5098777,0xbe428c5c, + 0x57660058,0x45b79564,0x957f37cf,0x6c7fc631,0xd6316289,0x8b7023dd, + 0x5b1c12a6,0x47003bb6 }, + { 0xc91c1c96,0xd99401c1,0x27a12970,0xaa5dcdf9,0xc3c29107,0x3ab92e17, + 0xa3fe4710,0x26fce8f7,0x4ee998ee,0xb0d09d5e,0x8e3a41f8,0xafa62204, + 0xa26ca506,0xb1c012a5,0x99b57252,0x2c6f734c,0x512f7fe1,0x1093d79f, + 0xacee19a6,0x2f30906e,0x056d1ea6,0x6bff8381,0xeff35f21,0x61c75856, + 0xc1ad2224,0x6e07e978,0x6b20fde8,0x2cca6ca1,0x633fe81b,0xab4d6d2d, + 0xb06a2ce6,0x73dff504 } }, + /* 207 */ + { { 0xd8e20fb8,0x8b615805,0x82b533f0,0x7c6873e4,0x56a854ca,0x5205f001, + 0xcb369211,0x87fec6ac,0xc7f092b7,0x1fa3c0ec,0xe845fe4c,0x5b36647e, + 0xf8b1f112,0xd4781e85,0x8b0f1a6f,0xc6526839,0xdcb8eb92,0xceeb8c6c, + 0x8e5f6d52,0x133f0ead,0xc8d934dc,0x31883e23,0x428ac45a,0x214ed5bd, + 0xdbbfca85,0xf77ca492,0x07e5ae13,0xdf4113fe,0x72ab05fb,0x63e4a0d2, + 0x7148f535,0x7544d0b7 }, + { 0x80797ace,0x4fe8d134,0xaf86d97e,0x216d6aa0,0xef5a68fc,0xdbf0a688, + 0x9f9b2684,0x18b26f45,0x8999d2fc,0x52fefcfa,0x62423955,0xd5af8d82, + 0xf63a3780,0x8f123469,0xdcd4feaf,0x2933454f,0xa73b5d09,0xba8018b7, + 0xe5552c18,0x9af1f276,0xff26bb1c,0xc5d4773d,0x06dd4f44,0x9ef49410, + 0x5f39ba49,0xad8f12f9,0xf66ca4f2,0x5767f6dc,0x7922f59a,0xba8773f1, + 0xc1e42d49,0x220081ea } }, + /* 208 */ + { { 0xba37a0ba,0x3043d573,0xdd176df6,0x05a431bc,0xc42070f7,0x03322cfc, + 0x67c2d109,0x5cabd30e,0xcbf8bcfa,0x362c95de,0x7787b10b,0xd767d277, + 0x6ec05e64,0x612c915e,0xce69c30e,0x9e669631,0x682e2635,0x27c9dd8f, + 0x95ffcc38,0x79021f12,0x8a2adca2,0x06a8ee79,0x4b5d500a,0x8e00e784, + 0x8d80d6c5,0x87746fc7,0x915f10cc,0x246053be,0x219f6fd8,0x844e328b, + 0x11bd3733,0x620541ac }, + { 0x509e5a29,0x0f7fd382,0xb432531e,0x8748d7d0,0xcd3883b9,0x8f749354, + 0x8bfbb17a,0xc6b8ac74,0x05f2d2c5,0xa4616a66,0x1bcb1b83,0xb3d96625, + 0x2fee265a,0xcf753104,0xdb225058,0xc70d73fb,0xf0c2d556,0x1211d434, + 0x54b259b3,0x862061d8,0xc42b3f7d,0xffe4606d,0xe86a4949,0x4c5c8585, + 0x160eedac,0x04ddcc8b,0x568e2420,0x1804ce67,0x42141656,0x91f3855a, + 0xf932be97,0x7f378198 } }, + /* 209 */ + { { 0xdfa6639a,0x9a374bda,0x02ab7391,0x0cbd48d4,0x47031e2d,0x5c5ef236, + 0xd0599d1f,0xb49ee2bc,0xe0d38443,0xd285eb60,0x269392e8,0xdbbea92f, + 0xb8bc538f,0x91455fbf,0xe469b768,0xae259ff1,0x41de5682,0xc1cecb1f, + 0x9952d1ae,0xc876f071,0xe7bf7446,0x1ce25181,0x282ad2f1,0xcb93ad86, + 0x6ba4ef67,0x8fa3cd31,0xe507aa3e,0xfce68a04,0xa61bb608,0xced74170, + 0xf6ac10d0,0x6de716b3 }, + { 0x172d6dc5,0xd4e58d04,0x6397c65c,0xbed2cde6,0x0c9eb4e8,0x7ae77e18, + 0x75fa2edb,0x56275468,0xa91e6738,0x4b30324e,0x235c8b2e,0x6023a856, + 0xa8f92887,0x9df6d6c2,0xf6f5e8b5,0xec2c185f,0x3ad5748a,0x7892e12b, + 0xd54aefbc,0x7aebb4f2,0xee868821,0x14915448,0xb1d9bd5b,0xa26c5f71, + 0x2ff00df7,0xe5ccd166,0xb95b1dee,0xebc99f17,0x3fe1f774,0x90983616, + 0xbb3d25b0,0x51f90830 } }, + /* 210 */ + { { 0xf2922461,0x49376fa1,0x1650d0d1,0xdbb1b1c3,0x0dd8608d,0x92b91c33, + 0x36b89906,0x3e612c4b,0xdf560052,0xe1977b0b,0x636a2545,0xf8afff70, + 0x11723d8e,0xcda7d278,0x81bde7ba,0x0b0bc4bb,0xed2a578e,0x3cb080b2, + 0x171b2e02,0x5bda0d0d,0x941bb9ae,0xf6df38cf,0xc14a65c5,0x85dd81db, + 0xc19dd98e,0x7f98c82d,0x52206f93,0xc613747f,0x5f5bbe78,0x9e13a2c2, + 0x0aa34be7,0x5eed218e }, + { 0x01d4dc0b,0xe1565754,0xf566bb07,0xa1ae5f27,0xb82225d5,0xe985ebeb, + 0x1189ec6b,0x5f3ad21c,0xecce4d9d,0x17da518c,0xd6b65b59,0xc84a2d3e, + 0x8ffa771c,0x7f988175,0x2ac69a7a,0x50d6ae12,0xc6e6846d,0xcb7f30b1, + 0x5bd0bb13,0x8c023a60,0xd73f2407,0x9a10fecd,0xe5f0a996,0x8c5158cc, + 0xbd8f5806,0xd26bf615,0x915a46e1,0xaf32ea87,0x0287d308,0xeaf74e81, + 0xa6264254,0x8c14ba06 } }, + /* 211 */ + { { 0xb17ee201,0x0c877895,0x88e57a77,0xc05aa471,0x97822456,0x19c3e763, + 0xc9c3ba1d,0x0be6f8c0,0xb4389ebe,0xfe85f4ff,0x0ce7fbb6,0x538bccce, + 0x65266c64,0x876eab2a,0xcf9a3842,0x5c9ac690,0xccc8f981,0x9f5cf3b1, + 0x9cf687de,0xfa17be6a,0x83835c15,0xfcfc10fc,0x150ef2eb,0x086b0fdb, + 0x884a52e6,0x9f97ecd9,0xb0cd1eb8,0x416e6fa2,0x3ecc03ba,0xe2bd1599, + 0xeabb165e,0x645c0a5d }, + { 0x50aa7e31,0xd94c4205,0x2f851da5,0xaec8df0c,0x3c726e6a,0x99646909, + 0x2619bf9a,0x72dbdc36,0xe253fbd5,0x1b4260e0,0x8c709e06,0x97c259fb, + 0xcddaec5b,0xfabf7cbb,0xe4b703e9,0xb4d5e8b1,0x0734efdd,0x1b06e56e, + 0x1f55f8a5,0x02d4a4f9,0x3f565c8d,0x7f8608ba,0x816d1d94,0x822f47d2, + 0x5ce7b136,0x0cc36156,0x31d04242,0xe46ee5ef,0x683567f6,0xb2a65f70, + 0xd2fa6c91,0x27e9ff40 } }, + /* 212 */ + { { 0xd7e952e7,0x75251893,0xc735bf18,0x15b30583,0x96fe0491,0x732b5992, + 0x806d2fca,0x27451858,0x1b885ed9,0x71ab76a0,0x6d9f55ec,0xbdce9d97, + 0x48f2ba9c,0x3da60b20,0x592b132b,0x6977c086,0x099051d7,0xb6dca9cb, + 0xd188ae25,0xd9c2ab23,0xe20aaf3d,0x9f469f3f,0x5aad74d0,0xdbd1f7cf, + 0x22a9eb3b,0x3d5efe5c,0x137010c4,0x8c5edfa2,0x57870260,0xada2217b, + 0x3dac9776,0x4feee567 }, + { 0xb5d3d780,0x30e18d52,0x07166744,0x4dadb5d3,0x5a742156,0x320d386e, + 0x8d6bbb86,0x5d8c290e,0x2d263dd1,0x981a4323,0x98984636,0x33d0e7ca, + 0xa519acb1,0x5138784d,0xdddc81ff,0x832e3fab,0x3199a43a,0xfc278594, + 0x32743163,0x5b4cabcf,0x74f94fa7,0x9fa010bd,0x5694a627,0xc28a743d, + 0xcb657a24,0xc1d2a888,0xe86a25ea,0x7eef2503,0x04c561ff,0xed11a5d3, + 0x9c9ede0e,0x4fe818e7 } }, + /* 213 */ + { { 0x7fc1c7ff,0x00252c9d,0x9fa89ad1,0xa9bd419d,0x4064e9cc,0xc93a124a, + 0x43942ecc,0x384cbcb8,0x8749695b,0x004c21fd,0x421165bf,0x69c81d9f, + 0xdde01102,0xe2325628,0x5a9b004d,0xec937457,0xf6dcfc21,0xfb3346bf, + 0x4d372c7d,0xac4da64b,0xf20494e2,0xcecb7ad3,0xe867c150,0x562c41b5, + 0xc2b723d8,0x299395ce,0x7ee53231,0xc91adfc5,0xf10b6597,0xe06f1161, + 0xb74d3ffc,0x81915529 }, + { 0x6ed9d4ee,0x8ec12431,0x689aff01,0x3dffa154,0x2a89a3f4,0x4aba349f, + 0xd467efb2,0x2db1e8e2,0x039102e2,0x18dea354,0xe52f082b,0x422ab853, + 0xed36dd47,0x7130a2c1,0x0295d1ee,0xca60e86d,0x7c7f5ad3,0xe6ac6808, + 0xde864658,0x0f83cecf,0x461d1265,0x72e66c21,0xbd385099,0xfeef4150, + 0xa6632289,0x0f183f3a,0x792dc795,0x275454be,0x11367702,0x2744c11b, + 0xe8ea6ef3,0x7d06bcc7 } }, + /* 214 */ + { { 0x7090212f,0x89285942,0x5521e844,0x691b7d4c,0xbe2dbb92,0x4c038422, + 0xbd81f880,0x317721ed,0xac89bc36,0xc136cbee,0x7b8f004d,0x4f71b60b, + 0x4e218ab8,0x269132d0,0xe6cc814d,0xb0e2496e,0x75fadc15,0x0b2ce317, + 0x66d223c5,0x82e3c084,0x4c612f8b,0x9721caa6,0xa4b65355,0x59a751eb, + 0xc7d3d9d1,0x3433aad5,0xe80d4246,0x1e61b9d2,0xfc673caa,0x149f655f, + 0xd0f9cb92,0x48b52b99 }, + { 0xefdc05be,0xa3915399,0x13e095e9,0xde70db18,0xcddb3fda,0x447862e9, + 0x1a009451,0xa2b03162,0x23920ea3,0x4b27980c,0xa23b8feb,0xac5394f1, + 0x3e5616d4,0x163f7256,0xb714219a,0xaa0ff93f,0x93d62474,0xd26f96d2, + 0x7dcfe276,0xdd212ea8,0x47038d15,0xab27bf2f,0xf418168e,0xe58c8325, + 0xb32a989a,0xe3704222,0xbfc9f13b,0xa3694390,0x0d0684ad,0xf16e2606, + 0x9d8c76ec,0x17c0de87 } }, + /* 215 */ + { { 0xdcc01958,0xbca5f453,0x1ce88393,0x7d945954,0x561f5b6d,0x5e6350a1, + 0x7e2d36bc,0x291c3c86,0xa5ac3a6c,0xf6c7ed84,0xd98006cd,0x7913c40b, + 0x5671ec3b,0xf78bb087,0xb43e89a9,0x1c928f6e,0xae1ea1ed,0xfdf28df3, + 0xb924b2b5,0x62bba5b1,0x1a116e05,0x491d2705,0x167ed3e3,0x08ec02b7, + 0x5bc0b046,0xe291cf7b,0x8c5d7f59,0x30e50169,0xf5c799b7,0x0c7c350d, + 0x0ac6e1d7,0x6862b9e2 }, + { 0x9ffa1f64,0x56c6f4e7,0xa1e24349,0xfed6a91a,0xcdb75232,0xe9a0ee0c, + 0x0322d607,0xbfc90b37,0x462fef87,0x29480ad2,0xc2bfcf34,0xfc214969, + 0xa539e38f,0x6e5211e0,0x12a5149c,0x2a59ec26,0xd706b532,0x195fe212, + 0xe99c8429,0xf77fb108,0x5dc80482,0x74ceaea3,0xbd92d298,0xa5a6030b, + 0xaaea15ee,0xad42dca5,0x4987109c,0xd6ac3bc7,0x290af649,0xc64e1c40, + 0x51f8de6c,0x5093fa2d } }, + /* 216 */ + { { 0x4c2d553b,0xc4cf3280,0x3b966c29,0xdc1abe22,0x2296914a,0x556a549c, + 0x999976c9,0xd8c9f8b5,0x776e83f3,0xc22c57bd,0x7c85ec57,0x4f2942ab, + 0x6e2c61f5,0xef3407e5,0xf213db48,0xf005e8ca,0xf32698c7,0x470c853d, + 0xcac0a54b,0xe6f488d7,0x60b7501e,0xb6bd6bed,0x714a4bd9,0xf0103106, + 0x6e098894,0x5285bc3b,0xf5f92a00,0xec06741a,0xef7ef24a,0x32f16426, + 0x6c77a438,0x12f9c44d }, + { 0x83313a1c,0x1951e964,0x33c58b37,0x98edd3da,0xc7ac4044,0x4edbbf52, + 0x0dcb5ee8,0x866ca6f7,0x6dd422f8,0xec0ae8f5,0x0661ec2e,0x1077bc54, + 0xd422523c,0x6d39913a,0x58e7cb3e,0xd105e1e8,0xc979bb45,0x47c9397f, + 0x0997b592,0x3221d4a9,0xe8952fe7,0x0ef628a3,0x4e946241,0xd08d5827, + 0x59780f40,0x64cbed0f,0x08e110ec,0x13d7c227,0x7679b1a3,0xd186d866, + 0x26ae1d18,0x02f75e4e } }, + /* 217 */ + { { 0x47f307d7,0x1b637ebf,0xd0141477,0x6b644a6a,0x2e05a80c,0x82a33d65, + 0xfed07b31,0xc8f1a0f3,0x3696e597,0xc09ee7f9,0xc7ffc01e,0xcdaa7ec3, + 0xf8f373b9,0x549f88fe,0xc3bb8989,0xc88d1961,0xdfcaa7b7,0xd92a4fe9, + 0x3ae4ab20,0x12ff9ee2,0xf5ecb1a5,0xf5aea641,0xe32fb47d,0xe769237f, + 0x25d085c0,0x96a5c420,0x26c755a2,0xdc912558,0x9bce9723,0x580b985f, + 0x63961941,0x72b1b566 }, + { 0x790e5558,0x9d708a08,0x0689af80,0x98536041,0x42313b5f,0xe85e7b8a, + 0x55a49d1a,0xe6ba1292,0xac371b0b,0x5e76c4b0,0x938e6e19,0x58504f39, + 0x60ae9a21,0x8dd41422,0x968485ce,0xd8b04e9b,0x887efe43,0xf94c4ba5, + 0xf11c5e73,0x11268e67,0xcf6b99c4,0x92623e28,0x7a0a9662,0xf2d0aaa8, + 0x4ca02ed3,0xb266772a,0x2d63b551,0x68ee8e4e,0x2e78b5b5,0xcdebb299, + 0xe17225ad,0x5df19216 } }, + /* 218 */ + { { 0x8df2e7e3,0x20027e1e,0xd8da07de,0xb183cc68,0x4b4ae694,0xce35ba69, + 0x3ca62e88,0x896d97df,0x52efed2c,0x3de4713b,0x26bd084f,0xd006c40e, + 0xfc81923b,0x1e9b71bb,0x1aacc6b0,0x9991c7b6,0x8f656840,0x650c9364, + 0x87f47524,0x138561d1,0xbffd3ca2,0x610f2b11,0xfa191418,0x96915faf, + 0x955e5309,0x8f1236de,0xa1872d79,0x613cbeea,0x66a2a48b,0x7f7b44ea, + 0xe0a89c32,0x452265c2 }, + { 0x25430010,0x4ad5ec79,0xebd090c0,0xcac786ff,0x20a9d3f5,0xa5f9f4ff, + 0xa3edc65f,0xfcbf4112,0x0cf3eb11,0x8824839c,0x8aa5b700,0xb8dd6d4e, + 0xb7568ab8,0xe2271dfd,0xb744560e,0xe43ec373,0x1cf75296,0x78eaf926, + 0x3fa96d9b,0x1809ae0e,0xdc25dfd5,0x0b312d2d,0x6bab7711,0x6b8f78b4, + 0xb5ecf1e4,0x069efc8d,0x609fecaa,0xc1952bae,0x5f4dbde1,0x43e302ed, + 0x1e078555,0x14b02bf9 } }, + /* 219 */ + { { 0xb87e5b57,0x2c71c768,0xf531a557,0x0bcc78f7,0xf7597dc8,0x4ff93f8b, + 0x139e175f,0xb28e026d,0xcb94ca6c,0x6b83b727,0x0079f7fc,0x2eafe3b2, + 0xcf3bd170,0x2aca54de,0x6af0dc6c,0x17c4133c,0xccf5e35e,0xbea1e665, + 0x345505c6,0xa6691a48,0xe6100b89,0x2633abd0,0xc17d0388,0x966c6706, + 0x1a0cf90c,0x7aefffbe,0xd0add64c,0x4d847be7,0xaea2aa46,0xd49bcdfb, + 0x2cc7d0a5,0x85e07e74 }, + { 0x0bc25bca,0x23aae0a6,0xe44f64ec,0x6e8e55f1,0xb607b773,0xe1e696d8, + 0xd3005909,0xaa90a746,0x2cbc4990,0x072b1ccd,0xc68e2f5d,0x0d0fe6c6, + 0x53e28ec9,0x920ec5f0,0xf0040cc1,0x79b21fb4,0xfcc4a2c7,0xa7375bd3, + 0xe1bac7dd,0xf5f5def9,0x35c0f8d3,0xdc315d79,0x2cacd318,0x7117c170, + 0xe926f71c,0x6f2823c4,0xed02f39a,0x38db58bb,0x7db69323,0xe5b49231, + 0x8d49f430,0x0964039f } }, + /* 220 */ + { { 0x56999eba,0x21774f16,0xb1de6305,0x3d8ee287,0xde0b2669,0xd81af726, + 0x3f8942a1,0x37446939,0xea03e13c,0xbcf6b615,0x94e273cf,0xd30c0c35, + 0xc6725c56,0x4fd33a56,0xa8be97a2,0xa57534ad,0x7c22a251,0x799242a6, + 0x9d0c5c49,0x4e51bdb5,0xc6a42768,0xd7cd76cc,0xd426bf59,0x914097ac, + 0x66e9beb2,0x59404a2c,0x5c96e3e9,0x4738fe98,0xaad666d0,0xbcbb3e0e, + 0x63bc5e56,0x626b0fd2 }, + { 0xe1a1ec42,0x47217dba,0xab5acc50,0xaa6ae7db,0x865331d1,0xb7e1ab1e, + 0x3d30126f,0xb8453070,0xdee61851,0x280649e0,0xea689544,0x8806f4a3, + 0xcb56f632,0x4bbe43ad,0xbcaff94f,0x036b9bda,0xbd0637be,0x0d941e65, + 0x686f3abb,0x82179d44,0xaad6afd6,0x1486912c,0xff7e1534,0x9a3b891e, + 0xeb86fd96,0x88c426ce,0x117928c3,0xb56e6a81,0x96399e00,0x933e7135, + 0xa17b6ac1,0x09bbddd9 } }, + /* 221 */ + { { 0xe4fd3673,0x75e39c1d,0xa65c8e07,0xf880d9d1,0x7289c7fe,0x4725c1dc, + 0x3529d200,0x5b6735ee,0x3c747af3,0xc1f8f2ed,0x912efdf5,0x5cf3998f, + 0x49859c39,0xed722618,0x0e69795d,0x23793a2f,0x86b1d2a7,0x8a6ab8d6, + 0x22a882e4,0x00c815de,0xf9db8d7e,0xbe77d6fc,0x02267547,0x0886fb32, + 0x49c10edc,0xb62687d4,0x7c83ed4c,0x9f1c3e17,0x5af366ea,0xe6d5d7f0, + 0xd1efad24,0x2eaa01b8 }, + { 0x1f357c74,0x5e47fb70,0xa9e3b794,0x93085c4a,0x6e85a905,0x4f098733, + 0xbe0244c9,0xf53808ff,0xa3b5660d,0x91dddf93,0xf3b95ed6,0x8b76377b, + 0xbb3920d4,0x91b911b7,0x86a13cf3,0x7ccf08bf,0xea018e58,0x53ed8f97, + 0x78c55194,0xb1ea4343,0xe0d2d5a6,0x8e6adde9,0x9b96259a,0xfc2b248f, + 0xeef17ddd,0x96ebceae,0x557f9c85,0xf694b443,0x07d5bba8,0x48cd150f, + 0xb4c1986b,0x02d31de9 } }, + /* 222 */ + { { 0xde79499d,0xa6bb9e1e,0xfd0fc2ad,0xf6ca8ff8,0x1a7d9356,0xbec0f8e8, + 0xe8f06327,0xbc3d1c9f,0x3b300beb,0x805c7217,0x413c181b,0x00420a08, + 0xf0ca9d01,0x9e9a167e,0x1aeeddd6,0x076c909d,0x8e3a8a72,0x64a1997f, + 0xa77b429e,0x3ce7f7a7,0x5c94d3e9,0xaac0fbf4,0xe6d48407,0xf37694a7, + 0xa91921e7,0xf56679e2,0xee1dbbd6,0xf23fe0f3,0xcbf9fa99,0xc7917566, + 0xe0f4d765,0x965860f2 }, + { 0x7fa5f79c,0xe734702b,0x5af2d26d,0x930bd426,0x6c73e0ce,0x45bd8b98, + 0x4ee44a2d,0x7dbe7bed,0x956c8a1a,0xc129e024,0x77cdf80e,0x6fdc05ac, + 0x589ca59b,0x70a6ba2b,0x999825af,0xfc484021,0x7a23f0b6,0x1d284b54, + 0x28a0a8af,0xb1da10a4,0x2b2af6d8,0xb1eb1b31,0x33935ee3,0xf051443a, + 0x8effa6ec,0x7a07eb26,0xd662654c,0x16ee4086,0x4549ee4c,0x7a7bc501, + 0x1fa98a52,0x65081032 } }, + /* 223 */ + { { 0xb67ed9b2,0x49f0e460,0xc36d93d2,0x0cda0fd0,0x88c75e1c,0xbb5963e9, + 0x614bc0c9,0x757bbe93,0x9a768605,0x9a9b8801,0x48edc544,0xa8b7e2af, + 0xb51a5985,0x9e77ed9e,0xebbf024c,0xdd025274,0x1545c636,0x598b6288, + 0x4800dba0,0x39bdaed0,0x81e2a23a,0x7fc20139,0x550cb4f2,0xdc66fd5c, + 0xb52068c7,0xad27032f,0x8169fa15,0xc9a0bcae,0x3a7ca8a2,0x60606f21, + 0x9862652f,0x98295046 }, + { 0x2e11c128,0x3e374600,0x0e6dca7e,0x80dfae5d,0xd9552264,0xe44016e2, + 0x880b7143,0xf65f88f2,0x526b881c,0xca3d28d4,0xdfb86afe,0xf9c59dd1, + 0x4c74f958,0x548860c2,0x9cb69f4f,0xd06ea43c,0x7334ecec,0x5343c9ae, + 0x35329713,0x5cc2ccd6,0x5f3a6c0c,0xa95ff403,0xb372653b,0x2e01a1cc, + 0xa250523d,0x31510fdf,0xa6227eb2,0xeee538e2,0xca23cd10,0xeadfc8a0, + 0x3e78f54b,0x4b7e6e1b } }, + /* 224 */ + { { 0xdb5f928b,0x79c9076f,0xb7347cec,0xe6250bb6,0xac00ec41,0x54b67798, + 0x9d9619c7,0x900d20ba,0x59e4343f,0xed42c0d0,0x451935d7,0x3df39e85, + 0x64f701ce,0x26391182,0xe1f87aac,0xce8f2554,0x65f91aaa,0xfddd6789, + 0xa324539f,0x96cd163f,0x4bace995,0x5c815f2c,0xa94f9ea5,0xd78c8c2a, + 0xef24e455,0x7ab2aff4,0x1cddc26a,0xf0ed6409,0x00ca2822,0x954a420b, + 0xd3297658,0x0611c4c5 }, + { 0xa9e81829,0xf192001c,0x08a282cc,0xded33320,0x8f9ded9b,0x0bfd7de1, + 0xb7889003,0x6793ac0d,0x3577a5dd,0xbb00d91d,0x802d3c2b,0xe17a23a7, + 0xfb549014,0xff95f88c,0xc71b6e07,0x7cd1bf4b,0x23588c8b,0x2e3b24a0, + 0xa4112076,0x9b5335b8,0xc4056d30,0x2481c05e,0xe916a1b5,0x55c7410c, + 0x850179f4,0xbbe03271,0xb3cd1208,0x15e6c177,0x90cbfe50,0x509a24c0, + 0x1c108566,0x82079529 } }, + /* 225 */ + { { 0x1c7d353e,0x5d2d3cff,0x7de0ce3b,0xd5e7eccd,0x6ca87635,0xb4b1075f, + 0x25f9ad3e,0xda8404e0,0x205cb5ae,0x6b963e89,0x09f221a1,0x9e5ee0d8, + 0xea41aca4,0xd64c85d9,0x34442a34,0x6a46c4e9,0x3cf655a4,0xac6ff97e, + 0xe5417d7c,0x76565c1e,0xeebf9c4c,0x681009a9,0x88da6388,0x95b61d39, + 0xf6b472c6,0x6402b46a,0x0b7f1171,0x1fde5165,0xbe0c05e3,0x94f8f273, + 0xa88344a7,0x7487b036 }, + { 0x9c3e2370,0xa860e575,0xf8048719,0x19d58193,0xa6e2f9aa,0x3a0dbf3c, + 0x6144719b,0xb6c7e959,0xdeffec21,0xa9049c74,0x3f50cebf,0x8ba064b2, + 0x49a1de15,0xb12822c0,0xb1d527f2,0xb654b7d9,0x0ffd0430,0xc470859d, + 0x4f05446b,0x37c74a67,0xa3add995,0xe553251b,0xe33533b5,0x4a3ed6cb, + 0x27e419ce,0x2f2f44d0,0xa5d1b979,0x2d84ee82,0xdb6fa69f,0xcc76b123, + 0x21fa3bdd,0x834f85c5 } }, + /* 226 */ + { { 0x2ce9b31a,0x329347c1,0xfe3fb3b7,0x1d88522a,0x52ff90fd,0x4bcefb4d, + 0x2b1a081d,0x53b17386,0x2a411f08,0x538c11ba,0x141b603a,0x7895b93c, + 0xb10bd741,0x2993b9aa,0x09912986,0xccbbd046,0xeea0aba5,0x669fafb0, + 0x35661897,0xd4844622,0x367ffa54,0x4a63b89c,0x1c3478da,0xcbad5d1d, + 0xaa6034f7,0xc5339227,0xe61b1391,0x0e6d705f,0xf74ff515,0xdd14b660, + 0x5332b54c,0x639d8b0a }, + { 0x162217cd,0xfa423162,0x811c28e6,0x2e0e4a2a,0x21766dc0,0x68d9ce18, + 0x046a06ef,0x51263739,0xdde92101,0x44eea231,0x114298d3,0x0607c8f2, + 0x63d957e9,0x27f272ba,0xa5e8cae1,0xe7ce80cc,0x24f7a63f,0x5816ebe2, + 0x89673e34,0x4dece5a7,0x536babd4,0x13756a22,0xe3bf77af,0x644d61ae, + 0x2bcf98bc,0x60b2bf6e,0x29fa962c,0x3b0b59f3,0xabb50023,0xb0769a1a, + 0x0c75402c,0x40903136 } }, + /* 227 */ + { { 0x1670433f,0x84d2873a,0x25493dfc,0xc9394df6,0x80fcf89e,0xeb05a19a, + 0xdb297616,0xe39e4310,0xd9e63046,0x50742dc9,0x1de9ca9e,0xf31ad8c8, + 0xfb7b1d0d,0x86aabf94,0x1b3c82d1,0x36cda27a,0x39702d84,0xfb1a2ef4, + 0x46081299,0x280bfddc,0xd2396238,0xe4b2b48d,0x7b3c9353,0x2db2c2f3, + 0x12fb8a69,0xd5b5b317,0x08180474,0xf9b87a3b,0x1e952578,0xd8590986, + 0xf37a2bc8,0x80668eed }, + { 0xb39a0249,0xe2edcd35,0xb2f8aeae,0xaf230cd4,0x7223df05,0x295b15e4, + 0xe0e937f4,0xbb66982a,0x8cbc9162,0x019d2b72,0xcf49dca1,0x5c512ae9, + 0x630f07b4,0x11b491a7,0xa03874e9,0x48d4f34c,0x44cb7433,0xc1fd0ea6, + 0xf95b30c3,0x13f79ae1,0xed8b60ac,0x40362d4d,0x61ead81c,0x9e8314ff, + 0x498c3d28,0xed600dd4,0xc2521702,0x5fcb1c19,0x3a9c1f33,0x592329fc, + 0x1bde6ce9,0x04677548 } }, + /* 228 */ + { { 0x39233c96,0xee3de56e,0x80737eaf,0x868c409c,0x201abc68,0xacae11bd, + 0x2b486205,0x0f2cea9b,0x6f19056c,0xe32387e1,0xa5dc2a41,0xea75365a, + 0x12b4be86,0x76c29acc,0x8d63294d,0xa01fcab7,0x0cab9f24,0x81dbe88b, + 0xf414c054,0x76646e5b,0xcb96b7aa,0xfe111893,0x7664e097,0xb649f5b1, + 0x53fcf5a9,0xa196422e,0x0b7ff634,0x5978c9bd,0x3c229895,0xb5feb38e, + 0x0833c456,0x038a49fb }, + { 0x13e93257,0x35e3818c,0xa612741b,0x14cebc9d,0x7caac06b,0x4f6e9249, + 0x3daa1116,0x82278e33,0x4de2034a,0xe7cc565e,0x0a1ba630,0xbb7dc95f, + 0x66956fbd,0x81dd9f23,0xbb132dd6,0xc63e6319,0xfc241337,0x6e22b022, + 0x7e8beb1c,0x23848193,0xd8c938ac,0x83b1994d,0xa6bb5644,0xb54cfaca, + 0x06f91807,0x1a7cd44e,0xa8f8d9f3,0x1dd439bb,0x7f74a8e6,0x660c2a78, + 0x121b5660,0x4bb76e22 } }, + /* 229 */ + { { 0xe6354817,0x7a151e8a,0xf038b438,0x33d494ea,0x85958986,0x4c86c688, + 0x1dcbac12,0x72153827,0xc0edad06,0xf487af8c,0xe500e5d6,0xad33051f, + 0xd6e47f55,0x0a711b1b,0x8c746ad5,0xa68709a7,0x6402f35e,0x27f17262, + 0xfb30c130,0xc6d08efa,0xc06c7497,0x9ef1c041,0xdcc3e2da,0xd0c74ece, + 0x092e1073,0x30c5f96e,0x2aa12b74,0x0f1393cf,0x2107eb02,0x24584016, + 0x7b76f98b,0x8843d25f }, + { 0xedb2a83e,0x4e1501dc,0x2bb8d724,0xbcfe8fb0,0xd925df62,0x09020659, + 0x42ab6fc3,0x3c715dcf,0xa0f09dfd,0x73c05055,0xe3590aea,0x126745d8, + 0x76ff749e,0x5382f4d8,0xa920c663,0xfc69feef,0x9fd711ca,0xde160211, + 0x9075c4d5,0x4219c3bd,0x3ded6bf2,0x3800cbd1,0x6263a116,0x8c7ea0eb, + 0x7d264c37,0x35bd7958,0x7159c98c,0x56e22e45,0xfa7373b5,0x71bf2a2d, + 0x8935c949,0x0503f939 } }, + /* 230 */ + { { 0x71dad4f6,0x65addc66,0x024bea1b,0x238e4889,0xf605d3dd,0xfb76c8e2, + 0xb0d96b89,0x13d5f5de,0x6601b2cb,0xe0b5ba35,0x83e3d254,0xe37d491d, + 0x240c8ea7,0xe8860423,0xe91c99ba,0x374182f3,0xa87ad919,0x26c2caf9, + 0xf574f295,0x4b13040a,0x944000a3,0x5b9bced1,0x06df42e7,0x4ccc57be, + 0x4bd1089d,0x22e8ec50,0xdddbb500,0x0c53177a,0x9ecfeadb,0x690d31d2, + 0x176668f9,0x735778fe }, + { 0x843c1137,0x0f86ee3e,0x3f0b73cd,0x3c1c42fa,0x8ab20e3a,0x0e75679d, + 0x16242fae,0x6f95f1f4,0x39b092e4,0x7b88e11c,0x4c236ac0,0x1629403e, + 0x2dac02e6,0x66105f41,0x862e0632,0x74dc28a7,0xf3b23c8d,0x2118ffb2, + 0x0745ffbf,0x1182417c,0x4c05711e,0x49b55a04,0xcefbe4de,0x2c665b74, + 0x97bf7107,0x1cc4c01d,0xc54f0676,0xb2ca06da,0x7450d0f8,0xfc599daa, + 0x1a3182a1,0x52e637a6 } }, + /* 231 */ + { { 0x6bebc6db,0x481700f1,0xf9503d92,0x4a6b45db,0x5d153919,0xc715cd3c, + 0xe5ad2abc,0x942a1c05,0xab7b466f,0x36a82433,0xba13918b,0xba413bed, + 0x90f4e6ce,0x698a5624,0xf3f1f3ca,0xbb720da6,0x63471ab3,0x2116d41d, + 0x303d3609,0xe00d2227,0x463ba69e,0x7fd4cc00,0x62845fd1,0xac609e4d, + 0x80adc9c7,0x63603b2c,0x45fafbca,0xbf16fc9a,0xc4bc94ab,0x41007f7f, + 0xa74b1698,0x7c916b4f }, + { 0x78bac2d4,0xc1026f91,0x2601a875,0x8a2e8098,0x0073d640,0xad2f276e, + 0xfcc1fb88,0x443610c4,0xca6b291f,0x5727b822,0x88ec60fc,0x0645532c, + 0xed9ad48b,0x51e48899,0xf543f103,0x841b48b5,0xd591ceeb,0xa6ccb1be, + 0x9dcf5a8b,0xfc4adf0f,0xb347ddb4,0x3a7ca020,0xcb44c521,0xaa1accc2, + 0x0527c0c4,0x773b6828,0x7023cf50,0xaa374c10,0x6b74c926,0x733d1000, + 0x77a8d07c,0x1ff3916f } }, + /* 232 */ + { { 0xf997939d,0xaa218fe4,0x791583b3,0x3d4dfbbb,0x87f7560b,0xb3a7b5da, + 0x5da92c98,0xa9c02801,0x46666f4a,0xe1eb4aad,0x14ce9dd7,0x2eb17a51, + 0xef8f3076,0xf46a66a4,0x810e546e,0x900b45c6,0x4baf04dd,0xf7af2258, + 0x5c84d42f,0x3cc1c872,0x8e4c83de,0x3093f225,0x170d88b2,0x62fade41, + 0xac076e44,0xe19612e4,0x32dd141b,0xf48d7346,0x925e34da,0xc1b1f759, + 0x072b90c9,0x19ed1a56 }, + { 0x6c735473,0x9cf7fcde,0x6003bc3e,0xaab88e67,0xfb199bb8,0x12187cbc, + 0x9accccbd,0xbb730441,0xb0f65459,0x214aff3c,0x6f926282,0x6aec81a3, + 0x9f9d20b8,0xaa82cb32,0x5773cc90,0x82f3f90f,0xf62257e1,0x4af60e6b, + 0xbd4762df,0xf18b44bf,0xdb970753,0x3948b129,0x7c22c18e,0xc6e920e9, + 0x57be97ad,0x393d6208,0x46b637f9,0xe8d7382c,0xf1fed1d5,0xf6625ccb, + 0x68681599,0x6f31e0f9 } }, + /* 233 */ + { { 0x82b8f204,0xc45afe55,0xd358b54a,0xac0441b6,0xacd5f5ed,0x7213e7bf, + 0x139bcd93,0x1914c70b,0x96dbcbb0,0x714b4581,0x1ed35d21,0xe9297d35, + 0x6a3e1f20,0x8f640837,0x2f3cd705,0x150a8a9d,0xdcdd9f6d,0xfb36e801, + 0x5cf56d82,0x5a54eb65,0x92aa5a21,0x7610500c,0x3b089f03,0xd10d0ae2, + 0xc42b66e8,0x491b2079,0x0eee8d48,0x4af1ae3d,0x41556f45,0x137e4c28, + 0x63d8a7e6,0x875e3308 }, + { 0xaf6c0acc,0xdc80fddc,0xbb1e7c08,0xd5ad1e66,0x828585ad,0xdc717ae1, + 0x275c7da6,0xbdc54340,0xd26b9e15,0xf4b4c852,0x6a05fa50,0x5f0a1fbf, + 0x817bcb32,0xc6f81e47,0x70ff2e1d,0x2cbd4328,0x67c7f7fc,0x8a249016, + 0xb585a6c4,0xd045acb7,0x4666c057,0x2e972ad4,0xe6d7d63d,0xc74d87cf, + 0x0e274144,0xf7067d87,0x8b2584ae,0xb2ca157a,0x75f0fdeb,0x495c5bfb, + 0xf386e009,0x5abb0581 } }, + /* 234 */ + { { 0xf0c97f57,0x8be62d2b,0x962f28c7,0x0fe04871,0x47b50abb,0xc548a467, + 0x44fa09ed,0xf6b26e03,0xab05a96e,0xfd44c6e3,0x70e6ae82,0xedb0032c, + 0xd7e4899d,0x28bd402b,0x9b7c11c2,0x43f2e963,0xce913716,0x0ec3fc0e, + 0x02fd0f8c,0x769b8bc9,0x7cabc3ac,0x9d9cb3aa,0x06924cc9,0xe88a8892, + 0x42609014,0xa51461aa,0x962e79e0,0xc7f4aa8b,0x8b1b3e80,0x4ef0210a, + 0x1bfee4bc,0x70544680 }, + { 0x121901c1,0xfab3d713,0xfead54aa,0xe90a2627,0xbc08ba23,0x64f6d285, + 0x36ec227e,0x8d993015,0x06c191ab,0x99a16ab9,0xf649ce2c,0x86b1cf5b, + 0x66be3a80,0x59206759,0xccba2cf0,0x18836279,0xeff53486,0x2c157b87, + 0x4b223af2,0xbfac9896,0x0aae7a57,0xcd0fd4f0,0x63218a80,0xdaddb940, + 0xdf88f14e,0x3844bb79,0xb71ed9fd,0xc1b3e3d4,0xd6205036,0x6c634a13, + 0xb8680a6b,0x6f56aecf } }, + /* 235 */ + { { 0xd9205c5d,0xb01dc803,0x67123929,0x68955f7d,0x9d9b6565,0x3debbffd, + 0xd3b1acfe,0xb844395e,0x6094eeff,0x04328b21,0x22991feb,0x6631ffa8, + 0x190dd075,0x0dde66e6,0xe8577c05,0x75b03c55,0x91722407,0x6c91ce5f, + 0x8ebb3a3f,0x9a288a40,0x058a1396,0x1d376f8a,0x9a6e0676,0xf3a59457, + 0x7b71d288,0x103029c5,0xb44c30c0,0x0843f428,0x730e0b9c,0xd8e6aff8, + 0x4ed644ad,0x7b6be811 }, + { 0x3d3aa54e,0x3ec38e4a,0xd83d509a,0x10233943,0x243955e2,0xf84aa621, + 0xf51d3d44,0x29104717,0x7eca4e37,0x62d2442c,0x85fa55de,0x8c5a523d, + 0x851da1b5,0xc6f5ccda,0x20001468,0x044bcaa8,0xe01702e0,0xf7501e68, + 0xe6a0acec,0xf0819359,0xac0ef0b2,0x33dda6ad,0xfd964f01,0x97aeedc8, + 0x530b90d8,0x48dacd0e,0xb84122eb,0x4c5fad6f,0xd700a1de,0x2284ec1e, + 0xdbca5474,0x86f9a835 } }, + /* 236 */ + { { 0x450cc69f,0x0e1d9055,0xc9edf98f,0x50eb14bc,0xee7eba01,0x1bb94e77, + 0x998f8e53,0x5f7a6737,0x1b16eef0,0x588384e3,0xd85c5e15,0xbb928723, + 0xcbd952aa,0xfe51e345,0x7e241674,0xc5d0ee28,0x100182f0,0xfdc146ef, + 0xe7f5be2c,0x0f739e92,0xb656bd3e,0x501ab3af,0x5168e289,0xb1552dde, + 0xb8ee104a,0x940dfe31,0xc4304475,0x42923603,0xc460a913,0x9306f114, + 0x03b51f86,0x5bfa9faf }, + { 0x107b258e,0x2a23f52c,0xd66341dc,0x989e82bb,0x823cff1a,0x54a3ced8, + 0x719b491f,0xf45b7794,0x2433dfb8,0x898c2218,0xc49250ee,0x0f9dd91c, + 0x4fa17655,0x50c2a2ae,0x2c327f45,0xf7aa1ce4,0x583b1e41,0x13a15ad6, + 0xa1bfad9e,0x9aa0d5a5,0x8e1fbdcd,0x9b1caa28,0x915f7f87,0xaf9283b6, + 0x87e81a1e,0xc10e4e0c,0x1080d296,0x04fdca56,0x12755bd8,0x6acc9616, + 0x828feeda,0x1b1266aa } }, + /* 237 */ + { { 0x774ee49c,0x4ebc0a00,0xcb6237d7,0x776f6852,0x5df938a3,0xfc0544ac, + 0xb6fbfbbd,0xc3388ec8,0x745f2eae,0x84ac8bcd,0xb1ece937,0xa9c56609, + 0x7de8fa13,0x656fb6ac,0xa532b871,0x5f8ded74,0xaa889f09,0xab0d428b, + 0x10b7aec2,0x43b27f28,0xfeecb34c,0x26426e1e,0x9e89c2db,0x44431b6b, + 0x39211090,0xaac4bc5d,0x4fd81058,0x926f7368,0x471ef60e,0x452fa691, + 0x218d7a23,0x33517fdb }, + { 0x593c4a36,0xa9c33f46,0x36b1a9ee,0xac69d718,0x4277beec,0x55a20c1d, + 0x7e4f179c,0x3e8ca24e,0xd46d88a2,0x57373369,0x730702f8,0x71ceb1cc, + 0x35eed574,0x8b184d97,0x0704cec2,0x7f4517a2,0xd7062a53,0x7f129d18, + 0xb1d77e1c,0x07a4571b,0x8350d8b2,0x774ac309,0x61fab8ef,0x27b2919f, + 0xb5dd801b,0xa7c4cc13,0x1434591f,0xe7e6255b,0x5a3592b3,0x349937b8, + 0x30c77549,0x31fac63d } }, + /* 238 */ + { { 0x04913fb6,0x2ee8cf1b,0x1769a6b3,0x7e401350,0x783e61f0,0x790ebb71, + 0xe27f2ffe,0x1e5107f9,0xedaf89bf,0x124ba67f,0xe58de68d,0x189200e1, + 0x6df5abee,0x962732a3,0xacbeb4aa,0x72cc37cf,0xe93c5a76,0xb0c5fa96, + 0xde63393b,0x4c2a317c,0x830b2d6c,0x97f65e67,0x1be5b96a,0x4afc3504, + 0x730ce66d,0x0bf40a60,0x9340d84f,0x96a1ba79,0x07626b08,0x3ee18254, + 0x7ab0cbf5,0x01db35db }, + { 0xac0efee2,0x6e0fbc2d,0xd71dbb45,0x8406ebcd,0x19b69abe,0xe72bde3e, + 0x37e01822,0x49cb7e61,0x11458b4c,0xcbb8c01c,0x687c5d63,0x420b4847, + 0x454c6776,0x1847dfa1,0xd1839d18,0xbede911d,0x278df046,0x1b9dc9c9, + 0x881a336c,0x294bd62b,0x93e77adc,0x7f096879,0x43ce3ba7,0x7ac90665, + 0x7764eefc,0x148695fd,0x9ac465cf,0xe0c20f0b,0xa6e2cdb1,0x636e8d28, + 0xd755341d,0x7b6ba98c } }, + /* 239 */ + { { 0xc1881ab4,0xcb1d9e03,0xb3168c88,0x19c25d55,0x282364ce,0xa82d3d47, + 0xf161aa24,0x95994390,0xe1ebb2c9,0x7838bc00,0xbdec7a75,0x8fd5dfcc, + 0x4ff7220a,0x4dd203c2,0x0efeff48,0x5ec173b3,0x16428b35,0x99f1d2b3, + 0x056e813f,0xc06bd9e5,0xc0b319f1,0x929172ba,0xfd223b15,0x6ae0e384, + 0x98d091ed,0xbd01059e,0xa654648e,0x6b3168e4,0x3375e798,0x2211447f, + 0x71eb4508,0x47e81019 }, + { 0xbc8c290d,0x7045d45a,0x810fb33a,0xa33d1355,0x46fbbf2f,0x2baf0092, + 0x385c7cd9,0xacff3f1b,0xe161985c,0xc5b150ec,0x2a888748,0xc6ee0a7f, + 0x5e88dcc8,0x9d888c8e,0xccb86443,0x4dd735f2,0x3c40f6f2,0xcc1e13b7, + 0xf3fed691,0xfc3a25ff,0x257ee5c7,0x4cb43b17,0xf32db135,0xaa654f93, + 0x02dff2d3,0x44f58d0a,0xa8ca6394,0x78e3f188,0xf3e86697,0x39646cce, + 0xe0dce87b,0x785b1902 } }, + /* 240 */ + { { 0xa92f9a20,0xfcce2361,0x9d64540e,0xb7bdca87,0x1d00d7c5,0xd4739a85, + 0x2e97c926,0x067ac8dc,0x78da6a8b,0x2aea3ffe,0x63c51b69,0x6828bf54, + 0x7155141a,0x76f1c479,0x3977d810,0xf4bcbef6,0x541bce7a,0x75bc4949, + 0xd17041a5,0xe01f4066,0x87755eaf,0xd282d5bd,0x59e7ae80,0x6e2107dd, + 0x382ab36f,0xaa56e166,0xb9d1d634,0x65ee8ef6,0xce4ed844,0x99a2160a, + 0xb7712c27,0x6557c367 }, + { 0xd75b6e52,0x561b0268,0x118d0e89,0xb0813640,0x6a2eb1ae,0xcff53330, + 0x6d090894,0x4e462226,0xb5fc1d48,0xbb351227,0x57a3062d,0x9365ea07, + 0xd66e2dc5,0x4caca37b,0xb9095887,0x220d7d23,0x8c4473bf,0x9c0fd393, + 0x6787da4f,0xadff370a,0xd057f4b8,0xef0aebcc,0x1173f33a,0x205e744c, + 0x925a26b4,0xb8d1f0a5,0x722fbbfd,0xa9364f49,0x8227d284,0xc891ae77, + 0xa0e08ab4,0x15c40d04 } }, + /* 241 */ + { { 0x2a0e18d1,0x9baf169a,0x4c0327c2,0x9971c017,0x7bc262ce,0xd81a323f, + 0x818ff379,0x2099db8d,0x4cd3c330,0x663f663d,0x011a0553,0xef5325c3, + 0xf980a470,0x9cd70bdc,0x1c9ed070,0xe64452d1,0xac676e13,0xafbf43f4, + 0xae85c2a5,0x97bec0a6,0x470490c4,0x2faae550,0x491e6ba9,0x0ab97a87, + 0xaafa9914,0x4055f537,0x36726557,0xfc95adbb,0xd119d6bf,0x646343b9, + 0x9d341e37,0x788e94a0 }, + { 0x9c53461a,0x053a6fe5,0x08e3b6ed,0x75ec897e,0x0768d939,0xa8f5d2f3, + 0xcc213d4f,0x9bd6bff6,0x05b0147c,0x590c7b41,0x7c7b8169,0x20a3628b, + 0x5bce78e9,0xc66a086e,0x4dec1d8f,0x3dd4d282,0xc19dcce9,0x890acf44, + 0xd8435a7e,0x6632d875,0xea6381b2,0x590167c1,0xf0dcc128,0xb2259797, + 0x46f8d463,0x91a612b4,0xc15efa39,0x42185d78,0x119f6788,0xdf55ec37, + 0x780dea93,0x91b19cc6 } }, + /* 242 */ + { { 0xcb5d8b80,0xebf2709d,0xfc35660e,0x03b96182,0x055ef969,0xb873d991, + 0xe47c4342,0xd1ea4b4d,0xd54f8867,0xcc4b9244,0xfd8d77ef,0x93b1a2ca, + 0xe8c1f563,0x068d24e7,0x49973056,0x5f5fabb6,0x0542374f,0x83248c50, + 0x3f38e913,0xc36de2b5,0x7bb680be,0xed07e8eb,0xd8f313b5,0x964813d7, + 0xafd2d392,0x7bb6a069,0x0848a31a,0xc06d848e,0xe4f0c325,0x6867fb2f, + 0x067343af,0x3c2ba834 }, + { 0x9d3ad63b,0xab62d775,0x59e0eb1f,0x3f9cab97,0x3885e117,0x70332a63, + 0xe20b2f9e,0xf22cafce,0x49eca947,0xb529ba7e,0x6228d88d,0x24954216, + 0x39239561,0x80ea23ec,0xd4370644,0x1b8907e7,0x563e4e44,0x4b7fa455, + 0xb2a4b0fa,0xcca9829e,0x48060792,0xd0a720a4,0x246991ce,0x8ccdda0c, + 0x348d086b,0x37a2325b,0xf60aee13,0x566ed509,0x147f253f,0x3d30e091, + 0xc1073bd8,0x1fa627a5 } }, + /* 243 */ + { { 0x42478fd4,0xa11222a2,0x670b2000,0xacf4c6f1,0x8359c6de,0xf71bb04f, + 0x7b93cdbc,0x618e2829,0x230db60b,0x96e1bae3,0x965b3b29,0xf17fd3b4, + 0xbc7055dd,0xa58639c6,0x4b817d7f,0xc3ea92ed,0xd23b08a4,0x9082b2a6, + 0xdc17010e,0x8471228a,0x20e89d97,0x753b9e46,0x03ff77c9,0xcf7e4f97, + 0x2bbe60e5,0x6c3f8245,0xb80e017d,0x9e432cbc,0xc0a45edb,0x150a5acd, + 0x4798743e,0x67b8bd05 }, + { 0xf4797cf7,0xe66079b4,0xd03fde02,0xe31c998a,0x54caaef1,0x5aa3763a, + 0xf7649711,0x64d9a1fe,0xaf29b1a7,0x7ce0dc73,0xfb66ca93,0x6661b083, + 0x32fb6a78,0xbf4d74fe,0xdf00a561,0x25f6ef09,0x831d1159,0x2bc4383f, + 0x536bde37,0x6d5cc10c,0x882cc65b,0xd4945f9f,0x451a99b8,0x81f48f13, + 0x6bac11a4,0x140161cd,0xf18a4a0a,0x9d94d4ed,0xa467a824,0x65363165, + 0xa4c9aedf,0x74297aa9 } }, + /* 244 */ + { { 0xe21124ba,0xc49758a4,0xa87ffbd2,0x99bd8198,0x3d6638a8,0x45fbcdd1, + 0x15f7bf76,0x94645ff8,0xc4e6d57e,0x5fa6736f,0x92e61db9,0x1eae6475, + 0xcbdf944a,0x79575c0c,0x25b31d74,0xa3d13047,0x4cab5ae6,0x7881df22, + 0x1a2887f2,0x8dbfd299,0xa26ac459,0x23d07590,0xd8661d4a,0x2e589852, + 0x8a0140f7,0x37b5c13b,0x3fb3782a,0x0f94199e,0x1bc14e90,0x722aa059, + 0xd55bbb12,0x89aab7ba }, + { 0xd656bdc7,0x8b345a96,0xe176cd3b,0x43bdc8af,0x32d64c43,0xd69518b6, + 0x79b82b41,0xfcf364a7,0xffb0cf82,0x907b344e,0x5101287b,0xf3d0c83c, + 0x34cd90ef,0xe9f26a59,0x07082b5c,0xe5f5aaf2,0xece7c165,0x4eb72c75, + 0xbe986cd6,0xe9590a81,0xff1536aa,0xfeef498f,0xa8263d5e,0x04560243, + 0x54ae872b,0x940be14f,0xe3207686,0xbee7bcc9,0xc1bc4d7a,0xd496a27d, + 0x5940ab46,0x002dc297 } }, + /* 245 */ + { { 0xb69d60c3,0xee533937,0xfe972755,0x260be552,0xc0c725a6,0xb11fb78d, + 0xcab2e7c2,0x6982c27e,0xee2322cb,0x4bceedd9,0x122704f7,0x952b19ed, + 0x854a6165,0x2df4c285,0x7b192485,0xba40b5bf,0x0119f52a,0xfcbca950, + 0xe5add86f,0x7467d1cb,0xd9d0f2c1,0x9bf536fb,0xb8d4ebc9,0x3c296e34, + 0x05a81317,0x0495f8f4,0x73335f76,0x8c59e8d6,0xe0542122,0x0b53d324, + 0x3c3bda73,0x4d564535 }, + { 0x7e5c0877,0x7322f800,0x0ca9a764,0x481b43e6,0xa2c12716,0x231f4f4b, + 0xed3136c2,0x09596857,0x38db30de,0xae826322,0x99908ebc,0x652fad40, + 0xaf0d231e,0x0b8d1814,0x09cbc349,0x2680c54b,0x4bf3bf8e,0xfd4562f3, + 0x092b595f,0x2985090b,0x5e15fc34,0xe6f39ca4,0xbc378168,0x70175191, + 0x845a4a87,0x906944b3,0x82a1541a,0xacc6d74a,0xb155c8b4,0xadc9bab3, + 0x77306c62,0x1f2f89ce } }, + /* 246 */ + { { 0x9affefdf,0x8253ef41,0x4cf9256b,0x05d7ece5,0xb444e483,0x377002f2, + 0xcba5471f,0xb189755f,0xd5cbe015,0xc88483cb,0x6a0b8429,0x254f7c69, + 0x61f3f61d,0x18850bd4,0x0a247157,0x7ba21089,0xd92eeb0d,0x35abbc2e, + 0x965dec89,0xfb56cabe,0xbc55684a,0x9da23724,0x6a7a7492,0xd8ba396f, + 0x2ef4ba46,0xfcb90db7,0x9909b27a,0xdd234fe0,0x76f4366e,0xbdf3c164, + 0x17e50d47,0x09c8097f }, + { 0x60050c07,0x6a04b140,0x43a8e37e,0xc29e8318,0xbb55e41f,0xcb9429b2, + 0x2ce60e3a,0xed2fea5a,0xdb9d82f4,0xdc7b1ff3,0x687d37fa,0x48ebecc3, + 0xecb07539,0x79153e32,0x57075692,0x6a60054f,0x800759ba,0x3871cd0c, + 0x30922df1,0x17a7386f,0x83357b7c,0x4e9fc59e,0x39415186,0x1d26b3a9, + 0xd34db889,0x912a0222,0x59fcdb71,0x6672fcf4,0x44ff3036,0x5a3f268d, + 0x6911e16c,0x6f113ed3 } }, + /* 247 */ + { { 0x1836f1c9,0x52a9df59,0x4232307d,0xfa6519f5,0x5ded285a,0x8406c701, + 0xaf627f75,0x0a1545ca,0xace0417d,0xae1111ee,0xa6113443,0xfb28bdf6, + 0x52dbcbcb,0xde9ef0ab,0x7813e658,0xe9dc181b,0x99127225,0x0b1dabdb, + 0x22814c59,0x5f0598e3,0xd934ee7e,0x5c3b966e,0xb99ba4bf,0x4eb84eda, + 0x3c1b55e7,0xb2919a34,0x94aa860f,0xa9addb49,0xf6811ff6,0x1b7220df, + 0xd1a183e2,0x6636a23b }, + { 0x20587283,0xdf5d5a2d,0xef07fc5d,0x0b3822c9,0x0ef6de38,0x1786bd55, + 0x25d1671d,0x163cf907,0x1cdb1def,0x74bf971f,0x0842fc4a,0x5749e830, + 0x27f854f7,0x0e2edbc7,0xbce24acb,0xbb27bbda,0x05bed08d,0xc1b19cec, + 0xf7c904bc,0xaada123e,0xd89982db,0x02429f1b,0x65f6e632,0x49d3616e, + 0xee59fd32,0xa3789fa8,0xfe9f29f5,0x160ba3ba,0xaf5378a0,0x0f2d3b61, + 0x73c2a6f8,0x7aeecc76 } }, + /* 248 */ + { { 0xdc43b0db,0xf3a4757c,0x98119cad,0x3d8a4e85,0x4616c156,0xf8095bf6, + 0x4f533e97,0x3e2a07bc,0x39cfc5ad,0xa9824367,0xcd68052c,0x18a6ba3a, + 0x8a1cec66,0xbd60e590,0x02b1b695,0xae3841a5,0x190a195b,0x986dff12, + 0xad31fd9b,0x2df2beac,0xcc728f7b,0x7d893224,0x0cf0a992,0xc38ea738, + 0x586a44ea,0xa8439a80,0x1615f03c,0xede7f7f0,0x27a1f885,0x48249908, + 0xb78a7645,0x28ec4006 }, + { 0xa2fe0009,0xe1820c2e,0xf13874e9,0xe11ba5d2,0xc524db52,0x97522454, + 0x7fede529,0x4d477426,0x9b2500d4,0x01d3419a,0x1869244b,0xce08a492, + 0xdd1be1b9,0xba169023,0x32a301e0,0x242c3e54,0x70906788,0x9b56f7ba, + 0xc74a8cc4,0xf0ad2a09,0xd76f9439,0x99cd1841,0x621fb60e,0xeddafe0b, + 0xbc397634,0x056bee54,0xff7f0a84,0x4653f860,0x2011c0af,0x6bd4876f, + 0x0c9525c3,0x134f4cc7 } }, + /* 249 */ + { { 0xe938dff4,0x9621a3ec,0x486a79a3,0x7d101a7b,0xde950537,0xf2c4ef97, + 0xe65d87db,0xf3184099,0x373b8cfa,0xb89c7ffb,0xe842916e,0x68baa505, + 0x4ebea764,0xa790fd09,0xe592892b,0x679df6d4,0xfcfed741,0x2023331c, + 0x9880ff21,0x0bf4efd2,0xd0344501,0x7ca78ddd,0x342858c8,0x2cb09ecb, + 0x2575487a,0x9e5eb6dc,0xebcb0491,0x50675a15,0x7381d471,0x09d2e74f, + 0x83d3d6f4,0x6ea37829 }, + { 0x4e5cc40a,0xc65c094b,0x1af37dfb,0x7a2e3f6a,0xf9026e44,0xef677e9d, + 0x93880f53,0xb7878c95,0x7f644aa9,0x4aa30b07,0x2f208c3c,0xa0c51683, + 0x658d663b,0x7c0277ae,0xae1d9130,0xef0b3c38,0x695c3ea4,0x302f37a7, + 0x6a0c5e0d,0xe004c1c5,0x20cbcf9f,0x9fd495c4,0x568a0e7c,0x706d5b9d, + 0x59286454,0x8b225dff,0x8d9a709c,0x527d4465,0x87c08d68,0x47c558da, + 0xbb4ef07d,0x606ee6e6 } }, + /* 250 */ + { { 0x57c621f6,0x02d99fc7,0x7fe83d48,0x292e40c1,0x9ef199b0,0x1bdfc7a1, + 0xe62c7666,0x78a04102,0xe6738753,0x16cda370,0x1e3a65af,0xbc81974d, + 0xf78fe209,0x19742048,0xbf5981c6,0xc83a058a,0x9c89702d,0xf26b2434, + 0x9d1a678a,0x988b2f1e,0xff29ae29,0x472bf9b0,0x1d7cf5ec,0xa143e398, + 0xb268ddd8,0x9c9d7e45,0x5fc4ff76,0x166cda55,0xa4aa7673,0x6044cdf0, + 0xe9148707,0x49dba6f7 }, + { 0xa758e37a,0x20e47fb2,0x2d8eaf66,0xaf6b31d7,0x6f9c2210,0x352ad5f9, + 0x90efc32b,0x0093f727,0x41e4b264,0x435c99dc,0x05b15795,0xbfa878e0, + 0x0e673575,0x99c520a4,0x87eea759,0xca682594,0xf12a348b,0x029f7b81, + 0x2aa2ce35,0xa547cc18,0xead5e2c5,0xa11d874b,0x55682cdf,0x9af0349b, + 0x8bbe8e66,0xf86ebfea,0xf55394ab,0x3dab8782,0xebc8eb8f,0x458bf797, + 0x9b7de78c,0x4890a7a4 } }, + /* 251 */ + { { 0x8da995f6,0xd7299689,0xec6156ef,0xd39eaae7,0x356a82d5,0x6959040c, + 0xc135bcfe,0xb2046b21,0x0f595c78,0xea720b64,0xe7c5fb40,0x02824efa, + 0x0edb3bfc,0x97d8fd4c,0x79f24ebe,0x12f02905,0x187ea6b9,0x16fc47cf, + 0x789d5c23,0xc219fd27,0x89263ecc,0x233a6b6c,0x8b6d30a6,0x823634b2, + 0xc9b33680,0xca352e25,0x40c77456,0x9388d6ca,0x3c92065b,0xf8e55b0b, + 0x02439a76,0x5c17474b }, + { 0x8aaccab5,0xd888e7c2,0xaaced05b,0x18027836,0xccec0f65,0x185b877d, + 0x125c2882,0x93cadc1c,0x67fdc54c,0x45df540a,0xc2788a33,0x4f3c86e2, + 0xe3a0fa2c,0x3e874469,0x273983cf,0xc59daa47,0x4a96d8a5,0x3063c48b, + 0xc2e58915,0xc38d2bcf,0x84e428c3,0x90e78b87,0xf0c4fd53,0x900a292c, + 0x941e6005,0xb7f92db7,0x6ca53a1c,0x95679241,0xb1ab0fa7,0x35f6f31d, + 0x7b58408c,0x5d675eb4 } }, + /* 252 */ + { { 0x870c6025,0xaeee1a77,0x91a2dfca,0xfc4a23b7,0x386b64c4,0x7b0e60c4, + 0xe5ae72b1,0xd5d5b17d,0x9eefa212,0x6dfc88ac,0xd4038b96,0x4feaefbe, + 0x8e2d2ecc,0x099ac356,0x012af207,0x548ea612,0x89c31218,0x4ffed9db, + 0xe0e67331,0x1c1e91c4,0xaf8300e0,0x009bb64f,0x6773c3be,0x8780501c, + 0xc08219fa,0xe0cd6ede,0xf81b06ff,0x7c055e07,0xe080b36f,0x82b63f9c, + 0x0a9feca3,0x02fccbaf }, + { 0xb47cac61,0x9991d4d1,0xab86e12c,0x2e9d1687,0x2b94f042,0x8c6855ec, + 0x48e648e5,0xca400519,0xef89ac57,0x9ba91fb2,0x1be792cd,0x4f419206, + 0xbd0f1e15,0x82d221cb,0xfc444019,0x062eb13b,0x99790fdc,0xf3a97c32, + 0x6067a64b,0x4e796d94,0x6d23775a,0xc46dd300,0xed7f0f23,0x8672c4d5, + 0x3b4f63d7,0x821851dc,0xd26273f2,0x50a3ae0c,0xeac60f6f,0x800e58fc, + 0x13845545,0x56f1e456 } }, + /* 253 */ + { { 0x32c24f3b,0x01ccb3f6,0x06d817e6,0x99eb1c7f,0x6aa26776,0x8dc640bb, + 0x0845d5e0,0x7838affe,0xf81a79a8,0xf34fecb1,0x3e6819b0,0x6a2e282d, + 0x8237a4b8,0xc4b977ce,0x87636439,0x0f46b3db,0x97970497,0xa465f540, + 0x8791be43,0xd7e08762,0x34198ec6,0x00220b6c,0x093d94bb,0x57b38637, + 0x29d690b2,0x84012e16,0x20aad1a4,0x02ec9db5,0x85dc34e3,0xafee2fc6, + 0x25500cf8,0x911d1936 }, + { 0xf5e5af5b,0x13b1bd58,0x7b6a22a7,0xa7ca263b,0xf3af2adc,0xab6bec4d, + 0xa04420bd,0x16651e59,0x4ba36c11,0x3b448b3b,0xff424310,0x3c62bfcd, + 0xf1a96cbb,0xde15c4a5,0xe4d1f980,0xbe0ad8a1,0x36673a3a,0x812bd14e, + 0x9212acdd,0x40303af6,0x576095ce,0x8f6dab9c,0x107f5ca5,0x7df1882a, + 0x8896a3b0,0xb903e63c,0xd863b3f0,0xf5048544,0xc09887de,0x5e5019b9, + 0xa0f53865,0x2be744fe } }, + /* 254 */ + { { 0x5b50f324,0x054cd05f,0x1ea3c7a2,0xb9b1eb24,0x7ff8e6b7,0x4a858a5c, + 0xec040882,0xd83902fe,0xd0cba9bd,0x72b26494,0xb29c9e1e,0xd0176f90, + 0xcebadb81,0x05d4eb02,0x372b8bfc,0x874405b1,0x79ead190,0x5c412881, + 0xec2b48cd,0xd44a3dd3,0x3f4d5033,0x84499a77,0x564c3a09,0xb37b38cd, + 0xf42e803b,0x80e99497,0xb8f518b2,0xc07b47a0,0x3568fde4,0xc710e3c5, + 0xcead0e7a,0x735f542f }, + { 0x38380039,0xcaa9a171,0xf74d19c8,0xadfafe17,0xccbc1a8b,0x92d4393e, + 0xfe029705,0x3c5dbf39,0x930e9b36,0x4552b5ab,0x2afd494a,0x7ee63032, + 0x3f02ac43,0x826a9ad7,0x99356298,0x98c53562,0x7342bb39,0x0c869f87, + 0xe4f9b79a,0xd7510020,0xd34789a9,0x6361d1a4,0xcfa85637,0xf0ded5ba, + 0x88ac07e4,0x407ee73f,0x09ef1cbd,0xfac7d03f,0x4d475bad,0x25d697cb, + 0x14bd399e,0x1e984c9d } }, + /* 255 */ + { { 0x4850c817,0xc76d0561,0x3489812d,0xb08a5b19,0x5e58cbbe,0x7273d154, + 0x4be61e5a,0x8900b5fa,0xd7aeb8e1,0xaa088691,0xd35a3d4b,0xe66666af, + 0x57ec7d3d,0x38a2c199,0x668d6f5c,0xa0648e8f,0x7adc1746,0x1f9fc92c, + 0x843065c3,0x23a116c0,0x61e6ae69,0x36370a20,0x2aa47e73,0x626c3736, + 0xdeff6d84,0x540c25f2,0xcdbed2d4,0x9804824c,0x039a9492,0x4b5bfce0, + 0x76942e01,0x6c474a56 }, + { 0x7d88e3a1,0x3aeb9a41,0xc484742a,0x105d3c88,0x3fe61131,0xe59de8d1, + 0x1a869e8b,0x148f5b6b,0xaa75d90a,0x7a8abc59,0x62146013,0x2f0c9bc7, + 0xc3824cd9,0x43faa747,0x6a5d0b92,0x81763a18,0x9bcbaebc,0xbbc341bc, + 0xf745d1dd,0xe1813160,0xb75ce5f4,0xa53ce52d,0xd50de4c2,0x15eae66c, + 0x75d7656d,0x5ed8996c,0xc4ca552a,0xe4ff5711,0x3c5305b4,0x215e985a, + 0xfa1ba2ce,0x6b258954 } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_32(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_32(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#endif + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + + err = sp_1024_ecc_mulmod_base_32(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[32 + 32 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (32 + 32 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 32; + + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_32(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_ecc_mulmod_base_32(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { + sp_1024_proj_point_add_32(point, point, addP, tmp); + + if (map) { + sp_1024_map_32(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 32]; +#endif + int err = MP_OKAY; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 32, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_32(point, gm); + err = sp_1024_gen_stripe_table_32(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[32]; +#endif + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 32, km); + sp_1024_point_from_ecc_point_32(point, gm); + +#ifndef WOLFSSL_SP_SMALL + err = sp_1024_ecc_mulmod_stripe_32(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_32(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_32(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_32(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_32(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_32(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_32(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_32(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_32(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_32(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_32(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_32(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_32(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_32(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 32]; + sp_digit tx[2 * 32]; + sp_digit ty[2 * 32]; + sp_digit b[2 * 32]; + sp_digit e[2 * 32]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 32 * 2; + ty = td + 5 * 32 * 2; + b = td + 6 * 32 * 2; + e = td + 7 * 32 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 32, base); + sp_1024_from_mp(e, 32, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32); + sp_1024_mul_32(b, b, p1024_norm_mod); + err = sp_1024_mod_32(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 32); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_32(tx, ty, t); + if ((e[i / 32] >> (i % 32)) & 1) { + sp_1024_proj_mul_qx1_32(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_32(tx, tx, t); + + XMEMSET(tx + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_32(r, tx, ty); + err = sp_1024_mod_32(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][32] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 }, + { 0x335c1685, 0x170a46d2, 0xe1007a58, 0xeac9e971, 0x43ca4a73, + 0x40e8f3df, 0x82642475, 0x2646f815, 0xb36576d1, 0x3af49bb4, + 0x72bf1afb, 0xd89e2d14, 0x2fd151e6, 0x27be882c, 0x8f88717c, + 0xaddedc85, 0x16ac6c6f, 0xd6d859bf, 0x2d8eae58, 0x0e741a1b, + 0x61c1f30d, 0x6faf7a00, 0x9b67e096, 0x66dbd09a, 0x7d3b4f7d, + 0x21f11c06, 0xc727c98e, 0x6152ba02, 0xe86cb221, 0xafd58891, + 0x6bd3baf4, 0x59e93c6a }, + { 0x71dd4594, 0xe54dd36f, 0x00aef1e6, 0xbbc9cc9f, 0xa19f6530, + 0x9ea5a44e, 0x3f520928, 0x8588aa99, 0x8f5c1418, 0x9753794c, + 0xc11399fa, 0x118bd792, 0xf5cb6ab5, 0xb9bd3afd, 0x2ecb9652, + 0x813d1cb2, 0x40389813, 0xfd456267, 0x4ac8431c, 0x51f7119b, + 0x0a180eb6, 0xdd9f6a91, 0x9f7bfa2e, 0x13946d17, 0x50a9d0d9, + 0x16f18631, 0x6f8373d3, 0x5f19c20d, 0x9b6a52b9, 0xbe85ac6a, + 0x74f62e03, 0x63ef187b }, + { 0x016f45e7, 0x7c376b7f, 0x2bec82f8, 0x1c1bdb57, 0xce429b60, + 0x7392f741, 0xc7afd81d, 0x6fdbf0a2, 0x7241098b, 0xbda41b1f, + 0xbb60f8cf, 0x5b407474, 0xb330bc4d, 0x933e0d41, 0x733fa3be, + 0xae182830, 0x0f5c6cd1, 0xa0ed299b, 0x3f9860c8, 0x7ff3354e, + 0x15559c41, 0xb1360986, 0x129f85cb, 0xab0cb63c, 0x47685fbe, + 0x682ecc49, 0xeb199633, 0x505e8ec2, 0xddac2cda, 0x90dcc794, + 0xf192da23, 0x4fe6791c }, + { 0x05e8733c, 0x94a423d5, 0x1d5717c1, 0xcc845e65, 0xe961b322, + 0x237c7e88, 0xdb4181cc, 0x0c4471c6, 0x713bd721, 0x00c875e2, + 0xb2c17b09, 0x9dfde9ed, 0xe88ceaf6, 0x430a6de5, 0x7b81cea6, + 0xaaa7a61a, 0x233f98d5, 0xea52d026, 0x60689a9a, 0xb55efdd0, + 0x5cac4aab, 0x30cfa7ce, 0x8e950761, 0xfa4db114, 0x4e9a1e52, + 0x309570c4, 0x1a040170, 0x18c21f61, 0xbe78d9d2, 0x555d1ffe, + 0x561db297, 0x04482a18 }, + { 0x73d486d8, 0xe7758ac2, 0x61cdc1e7, 0x8169f946, 0x2188ab4f, + 0x723c99fc, 0xf3373630, 0xa0e54f02, 0xbd8c2260, 0x560bee25, + 0x4531bc60, 0x28fc307c, 0x7e44feb5, 0xd6f21f1a, 0x57128d37, + 0xc8e4499c, 0xd7b2ea45, 0x963b053e, 0x32a3d222, 0x40c27a04, + 0x35459668, 0x5b51854d, 0xd73557e9, 0x66e1a49f, 0x8692077a, + 0x0d267fd9, 0xe7342702, 0xfa1350d3, 0x68ccdb44, 0x1a9c3f25, + 0xdedbf89f, 0x833a0ff8 }, + { 0xab376b76, 0xa8c419c7, 0x27d0f0cc, 0x3b7294f3, 0xa90c514d, + 0xe56bb9e2, 0xa62575a6, 0x931ba51e, 0x098c0a88, 0x56fee07b, + 0xb4c16a2a, 0x04be5aee, 0xe6eb260b, 0xe513350b, 0xa1d5c270, + 0x339edad6, 0xe9dbadd1, 0xf366ed59, 0x2dd06ec0, 0x4213be88, + 0xcb1187db, 0x22d639c8, 0xd8a1058a, 0x1fec95e1, 0xa2b744f1, + 0x03f73ea6, 0xf4f05c0c, 0x741fd51a, 0x85f811a0, 0x2e2df95a, + 0xeb24965f, 0x692b3ce3 }, + { 0xd2a127b4, 0x0ce6cb72, 0x8f92816f, 0x66a46ea5, 0x47a37616, + 0x43ecf463, 0xe0ab96ee, 0x163d9a01, 0xb2edbe8c, 0xc8145c6d, + 0x4de4e665, 0x2f426cae, 0x74e252f9, 0x174d0b40, 0x7d2af831, + 0x54c240d7, 0x3d652936, 0x581fa397, 0xa09d4695, 0x05b9491c, + 0x5452643c, 0x8c4e8533, 0xd4128327, 0x32d64331, 0x70361f25, + 0x64479038, 0x89ef09f2, 0x774191b1, 0x81de5fe0, 0xc0cf0aaf, + 0xf40042d6, 0x333e430a }, + { 0xcf26d3b7, 0x5df04de4, 0xb53f79be, 0x57a77306, 0x1808b664, + 0xa4013c5f, 0x85037360, 0xef291ea4, 0x0b061037, 0x1ffc9d7d, + 0x65c913bb, 0xd9d04dd9, 0xf13b8587, 0x948a37af, 0xfe3ee755, + 0xb5443483, 0x04631386, 0x3fc21e74, 0xcddeb58c, 0xb3a104e5, + 0x6572cd52, 0x94fe1862, 0x15aaa408, 0xeb9a71a1, 0x459ea462, + 0x8adc6fe5, 0x4aeb02a3, 0xbb18d175, 0x2f7791d1, 0xae127636, + 0xd6bbd708, 0x10e8b31d }, + { 0x3ed9f1af, 0xb87f03e5, 0x56676166, 0x03ad2477, 0x74ce15b8, + 0x38dcd630, 0x26b1e85b, 0x1877e2b0, 0x1af99c15, 0xb1654d17, + 0x9382547a, 0x9782e9e4, 0x26d55ef5, 0x6dc7fc7c, 0x2fbeb54c, + 0x9038f95d, 0x036c0357, 0xfe590dfe, 0x4fdc3f7f, 0xcfcb6eae, + 0xf35e1a88, 0xcb1fbc54, 0xda0a5568, 0x3c8e1db2, 0x5b6f5557, + 0x9a87393f, 0xe7ac0a06, 0x38646b32, 0x2a8495ab, 0xfd261c83, + 0x0cdcc4bc, 0x6485524c }, + { 0xc4a6ff2a, 0x1abfb3e2, 0x35a6428a, 0x2aa03fba, 0x89aff742, + 0x884227f0, 0xba5dbd93, 0x2337883a, 0xd2a182cb, 0x38186ae9, + 0x49a01f05, 0xb9f0764d, 0x917b1e7a, 0x92411feb, 0x570cbb5b, + 0x700b1903, 0xb914be7c, 0x5d5181d5, 0x1981182d, 0x135c4437, + 0x574b9997, 0x32758d24, 0x632d28b2, 0xa650a8f5, 0xfa383f09, + 0x24078bac, 0x00a33d80, 0x6546a60c, 0x2df8b449, 0xa4061c7a, + 0xf234563c, 0x1f76f3f2 }, + { 0x44c436b0, 0x9aa2c143, 0x1f69c87a, 0x79070556, 0x5f6db2df, + 0x35f3117b, 0xed56ba82, 0x85761f41, 0x7d0afa48, 0xf831464f, + 0x3adce71e, 0xa99f2915, 0x116b7488, 0xb27bf693, 0x9bb9443a, + 0xa98a5a8c, 0x2ee5fde8, 0x7f878026, 0x1812acb7, 0x3a6f93dd, + 0xdc84bc92, 0xaf92a4cc, 0xf1d4995a, 0x3c2562af, 0x04ed899d, + 0xfd9fc33c, 0x4ed2a538, 0xc028ca94, 0x049ea726, 0xd0f367bb, + 0x3d108e05, 0x04924ffb }, + { 0xc673562f, 0x06548e3d, 0xe2eae48c, 0xd3b33025, 0x5e1c6977, + 0xe61fd32b, 0x6ebe557b, 0x424e2064, 0x41d6e18e, 0x767391c0, + 0x14d7e95b, 0x4b8ebb8e, 0x20991b8c, 0x4ae8b7d4, 0xe01290d3, + 0xf8a0df66, 0x925e5f4e, 0xc97e24a3, 0x1508272a, 0x79a7b2cb, + 0x25072661, 0xb40b072e, 0x9062fa49, 0xdad9e182, 0xf3c53bce, + 0x8780a784, 0x9f142799, 0x58a82b76, 0xc1468426, 0x08cd849c, + 0xc380ae35, 0x4dfce809 }, + { 0xd527b780, 0x45069cb2, 0x977930dd, 0xd52da015, 0xe27d0263, + 0x10cc600b, 0xbb2d1b2b, 0x34102c26, 0x554adf3c, 0x4c652623, + 0x45f0ff47, 0xd6891382, 0xca916e7c, 0x83fa8cc5, 0xd15c8d8a, + 0x1e10f139, 0x81dc56b3, 0xf173dc2e, 0x5c4ed9ba, 0x7fcecb04, + 0x47d01228, 0x307fd7d8, 0x9f3a532f, 0x24a57153, 0xe2153c22, + 0x59e9e81d, 0xe428a408, 0xc562595d, 0x9339bd23, 0xdc7daff8, + 0xb8a06802, 0x0d075908 }, + { 0xde085f2a, 0x870af2a7, 0xbe99b2e5, 0x88fcd24f, 0x59ca413b, + 0x88c0d261, 0x8559f851, 0x1f02a2e4, 0xf622da0d, 0x83b96021, + 0x6dca3615, 0x5c05c2f5, 0x7910c682, 0x0148cf1c, 0x272695be, + 0x392f2896, 0xa8d64ef6, 0x883d0bb5, 0x1cfcbc52, 0xef0d2244, + 0x526117e5, 0xf5dafcec, 0xf04928e9, 0xb68612b9, 0x393f2e2a, + 0x283f744d, 0x700c1151, 0xfbeed7ed, 0xa4360dfe, 0xf2cde215, + 0x2f08535a, 0x24fa961c }, + { 0x616df7f6, 0x0767db3f, 0xfbd90326, 0x643057d8, 0x6e82d544, + 0x174daa90, 0x689643db, 0x2284f345, 0xcc89a060, 0x18b191df, + 0xd6c27d12, 0xbab46af4, 0xc9895145, 0x5a57f486, 0xcc942f9e, + 0xc03214e9, 0x41950158, 0x273e1c8f, 0x39ad43ab, 0x8ceb759f, + 0xe50ee173, 0x5e1b8b7f, 0x8f4d7d4e, 0xf635b1fc, 0x755603f3, + 0x8eff77e3, 0x7752fa60, 0x201f61d1, 0x4a6fb6e1, 0x94d7a03d, + 0xfc4f0114, 0x371cc23d }, + { 0xda90c351, 0x289b115d, 0x364d9c06, 0x6d196ebf, 0xf650b31b, + 0x77a89202, 0x6f57642f, 0xcc28c164, 0x08100127, 0xdc4f7e36, + 0xdc4c807b, 0x8836cd08, 0xe00240f2, 0x1280f156, 0x99cb3953, + 0x3f9a6d78, 0x3a802038, 0x40a494d3, 0xe87d3474, 0x45697e91, + 0x26dde24a, 0x70d97d07, 0x7640c30e, 0x06f6a58d, 0x5ba6e6c6, + 0x03c2c0e8, 0xf1bc13e8, 0x330f6a7a, 0xc9f4d78f, 0x3e602e4f, + 0x0c80fb7f, 0x92b6bca0 }, + { 0x5f00822e, 0x2e3d5c83, 0xb8b16f12, 0x0e825712, 0x92b0a330, + 0x81c329c4, 0xa7cc1954, 0x6b4e32ad, 0x1bb1413f, 0x0bee9cee, + 0x4a92ca27, 0xedfb7baa, 0xea3b9153, 0xcd472afa, 0x00f0c0f9, + 0xe8f09e7e, 0x5cdebb70, 0xa4e1d872, 0x4a9b63b6, 0xfe2bae08, + 0x3fd58f65, 0xf40141b8, 0xa3b62759, 0xd7ec5eda, 0x790e3088, + 0x9aaf6e67, 0x1f277e31, 0x215ad830, 0xcf33871c, 0xe7db4b98, + 0x4f02f89d, 0x71ff62c9 }, + { 0x2a4a84d9, 0xaa4c7102, 0x5ebc71e6, 0xe2ee4acd, 0xf1cd6578, + 0x3b11a8a5, 0xfff120a5, 0x83f5ef9f, 0x09e65033, 0xa4c598e1, + 0xca044180, 0xe1e9f990, 0xf59828c1, 0x8b832d46, 0x33af536b, + 0x753f28a0, 0xb6d4f68a, 0x92edc4b1, 0x72ccd1f0, 0xedde692a, + 0xd2226432, 0xd3aa0f7d, 0xa3d2661c, 0x38dbb63e, 0xfdc37dda, + 0xf1e19fc6, 0x84ef6b4c, 0x6c18b350, 0xdf1bba69, 0xe6a83fe9, + 0x5f958273, 0x40fd47e7 }, + { 0x267140a4, 0x5b88b746, 0xeab6f2fb, 0x6dbbfc1e, 0x69862548, + 0xdd9ec88e, 0x2eb6efc2, 0x69beeba1, 0x8ac8ff88, 0xcfc2214a, + 0xb5a21950, 0x95d5c96e, 0x4171fb69, 0x93389c05, 0x1b468337, + 0x2d85d452, 0x4113425c, 0x14d68a08, 0xec6c2174, 0xe52c0139, + 0xf730084d, 0x20cf0b97, 0x1f578aa3, 0x1ac16a26, 0xf9b6ae43, + 0x18b9fab3, 0xd854a695, 0x68d82111, 0xdffbe286, 0x0b334d98, + 0xe639338c, 0x5b1c1157 }, + { 0x72b6bb8f, 0x90edaab1, 0x02fc92c2, 0x8dc64ed2, 0xfe694c73, + 0xf42ba3c5, 0xcb54dce4, 0x316dc65f, 0x632420dc, 0xcb2d66a3, + 0x056dcf94, 0x16e706e7, 0xa4f32c9d, 0x2809c764, 0xea6edca8, + 0xab18d830, 0x81c65f57, 0x4fd1ace6, 0x7da12c10, 0x1f91651c, + 0xc7791a48, 0x0ac3bd66, 0x785e67a3, 0xb6ad1cf4, 0xda0fd591, + 0xe4d3fc44, 0x6e1c6344, 0xce164801, 0x33e50ab3, 0x84de9cb8, + 0xa756eef4, 0x963ab83a }, + { 0xdf4ea5a3, 0x944b47d8, 0x5cfe45fe, 0x96568815, 0x8a3c3564, + 0xd16e7d58, 0xe7c99e15, 0x84e55b3e, 0xf55071bc, 0x3fee204d, + 0x04057dce, 0x71006f29, 0xbba75570, 0xfe8c390d, 0x3319adac, + 0x3645bcb6, 0x7c20bfd8, 0x8189e8b0, 0x7d7d9578, 0x8e550969, + 0xb99f4e3b, 0x037d1321, 0xa60cfb6a, 0x011b2521, 0x837382da, + 0x66594aaa, 0x83c1dc07, 0xc89b91fd, 0x076b9884, 0x6b82b899, + 0xbe45c558, 0x443480fc }, + { 0x9114221a, 0xf8ffffb4, 0x3e857a7a, 0x4aec4f2e, 0x0fa54787, + 0x42e2d0e4, 0xd6f96152, 0xef3e6b31, 0xfbfe9b77, 0xb2296537, + 0xfb43a86a, 0xc2a9d0f2, 0x24572ac6, 0x241284ed, 0xe721ba7b, + 0xa3868917, 0xc117a78d, 0xdbef7c00, 0xd31605ac, 0x38149071, + 0x065a8ee9, 0xc2dada9e, 0xc442be82, 0xd5b138d8, 0xf6d72b58, + 0x9b6c224b, 0x8eb03e6d, 0xb9d355cf, 0xa1700371, 0xab6d1eb0, + 0xcffaa7eb, 0x97118a88 }, + { 0xcdecb5d8, 0xbf9c59a2, 0xa93a6866, 0x8083c81b, 0x04774fbf, + 0x24e0dd81, 0xa02070b4, 0xe779a3ca, 0x0fbfb781, 0x9d352fbb, + 0x3ef2a1c4, 0xa8b0d820, 0x14b3e501, 0xb858637b, 0x8a882ff2, + 0x5ba70a49, 0x3b06efa5, 0xa2730083, 0x102fee2a, 0xa42c02f4, + 0x8a0223a5, 0xe4e76299, 0x85c3fc72, 0xdba2ba26, 0xfe52eae7, + 0x554fe763, 0x270f45f6, 0x30b5405a, 0xa573387c, 0xd56a177a, + 0x4b71fa82, 0x17c0778d }, + { 0x2735e37b, 0x0e6dff1d, 0x656ec572, 0xc9884e56, 0x9ebba978, + 0xa2f5ac9d, 0xba09f3c4, 0x40fa4518, 0xf5b04377, 0x8c3fa177, + 0x967a2eca, 0xa1a1decd, 0x0528bd40, 0x768bca70, 0x18691c4a, + 0xf224952b, 0xe86d5fd5, 0x16e12c45, 0x37859a6a, 0x7a0d9157, + 0xa0ffce0e, 0x723f4309, 0xa96cc9a3, 0x5a8db79b, 0x1ad23a38, + 0x6dd12ae0, 0xe2bf5d84, 0x9ffec3a1, 0xa452ed66, 0xd6ce84e1, + 0x571fe4c6, 0x1219d5c8 }, + { 0x262969eb, 0x43eaa67f, 0x2f03e773, 0x3a3ab39d, 0x57bb0909, + 0xe6127e51, 0x8d150274, 0x0f82b0ed, 0xe580bdbd, 0xffffcad8, + 0xa9743e6b, 0x51d3d075, 0x8bac11d6, 0x1484bdb1, 0xeb24c388, + 0x95cd9990, 0x7fac67c6, 0x216a61d0, 0xa04e6b87, 0x4308f762, + 0xcba57cc8, 0x2865dd61, 0xd234a07a, 0x3c296b0d, 0x3a0793f9, + 0x76f92839, 0x0be29ece, 0x70b57e1f, 0x7e626f42, 0x1314a82f, + 0xd657f230, 0x2c8d7ab2 }, + { 0x0825e4d6, 0x67cf5892, 0x6ef83b44, 0xdf51eaa5, 0x1310108d, + 0x63e665d8, 0x8dd0963f, 0x229f89f5, 0x9df6436a, 0x8c4b14dd, + 0xd45ebba7, 0x99dae469, 0x5a4df381, 0x118aab77, 0x29e37feb, + 0xda8978bd, 0xaca2d7ef, 0x69ced5aa, 0xc67d6a8a, 0x6c98d05d, + 0x77f84a34, 0x7474bf0d, 0xed8cd59a, 0xd4428b2e, 0xd1d398fb, + 0xb0fd1cd5, 0x94a20b11, 0x596013db, 0x1b404c44, 0x96eb705a, + 0x4b09d958, 0x2299d277 }, + { 0xc64397e6, 0x5b9cd58d, 0xbf6dd31e, 0xac198f1e, 0x3e9f1db2, + 0x5866d8e1, 0x8fcdc68c, 0x405ae287, 0xe53c01fd, 0xa4b280cd, + 0x411db5f6, 0xdc963f2d, 0xbec4f8a0, 0xed5d5189, 0x916ee98b, + 0x336fd13d, 0x042df48e, 0x6925b1b3, 0xace0074e, 0x0cf56291, + 0x25317e95, 0xe8d38b48, 0x821c446b, 0xc7ad1d2b, 0xf0b65934, + 0x71c44135, 0x52ca0d50, 0x971b736f, 0x27b46c26, 0xaf9ffa57, + 0x1936618e, 0x21ac6779 }, + { 0x2d7fbcd2, 0xab420e3f, 0x97bdfc18, 0x12722473, 0x4df5d4b4, + 0x492033f8, 0x3807b7d3, 0x6fcd4236, 0xb33c3625, 0xdfc19b09, + 0xa0f22814, 0x13d6f375, 0x037c19b8, 0x70978a59, 0x0ff27b9c, + 0x4f398997, 0x615a4389, 0xfc0e1a45, 0x3e602f74, 0xffa3496a, + 0xb261ca1c, 0xc3f1c431, 0xee0164cd, 0x612211db, 0xe7f7be9f, + 0x30463ee4, 0x92c2e1bb, 0x015f7e78, 0x24483a56, 0x663d88d6, + 0x0e62d9d8, 0x0e8ec1e7 }, + { 0x8a0878dd, 0xa88ccc29, 0x6640071a, 0x99ac175d, 0xa5173617, + 0x90344820, 0xdd58a315, 0x316d023e, 0x88d221a1, 0x30785bd4, + 0x959c48e3, 0xb74b3de7, 0x4c67a771, 0x42ee0382, 0xe0b91453, + 0x59ef6cdd, 0x9b237e91, 0x7830ae28, 0x495d8325, 0xe1847a4c, + 0xd0773666, 0x67b1217e, 0xa294a325, 0x58192c86, 0x864d8326, + 0x76aa0f56, 0xf4b13e5b, 0xe2a2bd12, 0x1b6b73fd, 0xd850c1c0, + 0x5d103635, 0x653a795f }, + { 0x50dcb199, 0xcfe28985, 0x7fa02b60, 0xb35b8e5e, 0xc97603d0, + 0xbca7d7c3, 0x27f131b5, 0xb0e5288d, 0xe2b12d52, 0x3aa704de, + 0x1db725c7, 0xe206b1d8, 0xc5d1b113, 0x0b12839a, 0xdb45d763, + 0x14f970cb, 0xb2125e8e, 0xc997f93e, 0xee7daa26, 0xbd75739c, + 0x1fef20e9, 0x46ecbd3f, 0x7c6a42b1, 0xf994a114, 0x27fb0fd1, + 0xd289eb4f, 0x9a40da4b, 0x11186d31, 0xfb9d7976, 0x083f65a5, + 0xd444675e, 0x30dfc47b }, + { 0x9eaadfe8, 0xbcfc5ae2, 0xb4d4e812, 0x25027e54, 0x8b533561, + 0xab0702df, 0x56a6a214, 0xa2b9c204, 0x3059068e, 0xb1a3df7a, + 0x9883110f, 0xa3514b21, 0xc4b78e1c, 0xb7be2336, 0x3e2f6984, + 0x17073ce6, 0x2ddf7ac6, 0x86e114a6, 0x07d7c3c8, 0x276192bf, + 0xeb1ae289, 0x5da69e0b, 0x25184939, 0x983af175, 0x407a3aa0, + 0x9ac52a4d, 0xae0fe218, 0x1535c7da, 0x397f2501, 0xe16fe872, + 0x54c212cf, 0x572a591f }, + { 0x09a5553a, 0x49668419, 0x327733bc, 0x3f054318, 0x3eefd690, + 0xf9ceb4b2, 0xf22126d4, 0xbd3cbf9b, 0x2fed9578, 0x6d9671c0, + 0xca0306d8, 0xbba597ce, 0x3d674fe5, 0xb705ed61, 0x67f33f76, + 0xf1d3622b, 0x11cb8c31, 0x15bcf3c6, 0xe53d1aa9, 0xa38467dc, + 0xf908ab43, 0x902fe929, 0x8d15767a, 0x6e3e499d, 0x90afd07b, + 0x8142db5c, 0x6c8b190e, 0x120c6fbc, 0x24919a4e, 0x80c86553, + 0xd8c82c3c, 0x65c2cbe1 }, + { 0xa660bb63, 0x684cda20, 0x86e86245, 0x27dc3b0a, 0x6ba0eed7, + 0x76472cf6, 0x679dd158, 0x79c162e5, 0x08452d44, 0xb6884277, + 0x413f579e, 0x829bc6b3, 0x95011770, 0x92ea15ec, 0x47738183, + 0x5e34e300, 0x73e1d2f1, 0x8c3ca349, 0x229bd3de, 0xa5c4f1dc, + 0x94ef7ed3, 0x783eff1b, 0xdfae7a1a, 0x46db738d, 0x1a099852, + 0x4353d72e, 0xa0dcf4ab, 0x2533ad58, 0x0e7888b9, 0xd8055016, + 0x3ba77f66, 0x831440d5 }, + { 0xf611b2da, 0xf43e2e32, 0xd0fa46ac, 0x5d066e29, 0x820b3c0d, + 0xe897f3e8, 0x1d3e44f0, 0xc45c28e6, 0xdfd27a66, 0x929d7f66, + 0x101e8517, 0x735b860a, 0x3de078dd, 0xea3fce98, 0x638ce11a, + 0xc9977db5, 0x48536b3b, 0x0488382f, 0x64cadfc6, 0x7e0c7a3c, + 0x82147b71, 0x3cd17f7f, 0x1b411e3e, 0xe95663cc, 0x985fb46d, + 0x5739ac8f, 0xbcf119ca, 0x385399cd, 0xe15a2815, 0x4a985a70, + 0x6d5f4566, 0x504c3a8a }, + { 0xb8fa53c7, 0x00b55283, 0x509474e3, 0x985cff38, 0x437ce25f, + 0x234d241c, 0xe5a129ed, 0x29832430, 0xaabcc674, 0x6ad38956, + 0x7ee81ee1, 0xa2dc001d, 0x670b2702, 0x4c23c6b6, 0xa6e8a3bb, + 0xb35e567e, 0xa69673ea, 0xbc70b3ce, 0xe6e28eac, 0x85a7a9c3, + 0x5537b7da, 0x2ae684de, 0x6de937dc, 0x5ecac3e5, 0xf8430422, + 0xbf2ea6c9, 0x77fdc520, 0x38caf7d0, 0x69f56add, 0xc27af0b1, + 0xc71d21d2, 0x496e4699 }, + { 0x9fa93467, 0xba14fc82, 0x0eb2a614, 0xc2e37684, 0x4833e09b, + 0x659bcfaf, 0x3686bdcc, 0xbc859752, 0x81f3216a, 0x40bfd080, + 0x17c081b8, 0xc463bda6, 0xbb04793b, 0xbd01fa86, 0x2cd640c5, + 0x5a21ece6, 0x2203d5c4, 0x97bf6a54, 0x951167b7, 0xceb40edc, + 0x765ba268, 0xd67aacaf, 0xaeab51f9, 0x8ba0d9e9, 0xb0d6863a, + 0xc14b215e, 0xe5f06952, 0x354cdcdb, 0xcb3744b5, 0x4f2b5ccf, + 0x13037fe8, 0x13389173 }, + { 0x45003cd1, 0xee680640, 0x44ae2ac6, 0xfdac17bc, 0xde8e5314, + 0x4bcd419f, 0xc7cea95c, 0x81e34eb9, 0x38f37e01, 0xbb57762d, + 0x260990c8, 0xecc4cfb0, 0x50a34a7b, 0x0bc493f9, 0x543304ef, + 0x68074172, 0x6bc8aa2a, 0xaec0fcb2, 0x3b45fea5, 0x9e7a9b46, + 0x55fbdbac, 0x4bb2952e, 0x0485dff4, 0x50f0c0a6, 0x4dea4796, + 0x02c5104d, 0x695e3a02, 0xd2cefa09, 0x6da1f345, 0x4c8102b4, + 0xf3833fbd, 0x422eb573 }, + { 0xa6ad3f47, 0xac592eb6, 0x9714ba0e, 0xb0861f6d, 0x07281459, + 0x57c1e919, 0x64ea5803, 0xcf7c94e2, 0x54b12723, 0x725376ac, + 0xdafb736a, 0xf2a6ba41, 0xcba03cdc, 0xc89e8920, 0x5b0fd3ad, + 0xf2e20cb4, 0xd66059fe, 0x26ea5a54, 0x889df8bc, 0xee63fa8b, + 0x66a3f2bf, 0x40f1c7e1, 0x747312e1, 0x09febc9c, 0x727999ff, + 0x7d19b9c2, 0xb7fd2b05, 0xa9fbbb4c, 0xa0da2dc6, 0xcfba27d7, + 0x2c252582, 0x368541cf }, + { 0x22799d37, 0x510d3c9e, 0xacfa333a, 0x1b677de5, 0x080f795b, + 0x4e6ae18f, 0xafc8dfc2, 0x69b53c2a, 0x0e842dc2, 0x797541b6, + 0xac067fe8, 0xd5a6f2af, 0xbd07d877, 0xd0208a03, 0x654be2f2, + 0x34b473f0, 0xf515e23e, 0xe67c102a, 0x2ac1af48, 0xb00dbf9d, + 0xb6a13d00, 0xe264fa41, 0x97e94c11, 0x1669786a, 0x86a586f4, + 0x09d8cf2d, 0xc7f927e9, 0x073bf869, 0x2241a566, 0xb8977880, + 0x22261334, 0x59a5bf59 }, + { 0x81347191, 0xe9d1c91e, 0xeb969972, 0x186c1abc, 0xa9d46a7f, + 0x07888767, 0xdaa7d397, 0xda93cfcc, 0xd91b9aa0, 0x08bee9f1, + 0xf8dd3c6c, 0x8267fd78, 0x94228100, 0xf93860d0, 0xdadb47fb, + 0x6a6a71aa, 0xa6156f8a, 0x9caa06b7, 0x39848bc9, 0xaa1b05e0, + 0x2aaa9135, 0x36ddc237, 0xb13f3bd1, 0x77e7e079, 0x4acc5f4d, + 0x8d0b5cbe, 0x984cfd36, 0x04da45f8, 0xd3d3e0f8, 0xf14ef618, + 0x43eb799c, 0x467564c1 }, + { 0xb6fff5d7, 0x8d725904, 0x92dc4752, 0x037f33af, 0x6d20b8aa, + 0x9095d575, 0x43baec39, 0x32235fc1, 0x68a2b9b0, 0xa2feb4af, + 0x94d35c61, 0x61c50318, 0xea877486, 0xac92b6a2, 0x011bc6f3, + 0x8eb48b15, 0xc79edcb2, 0xa28fe128, 0xa5d2a006, 0x9f71bc0c, + 0x2f15b850, 0xf3167732, 0x7a036218, 0xfe8d728c, 0x4f81e09e, + 0x068f39cb, 0x7b7c50d9, 0x1773f016, 0xed6a1e03, 0x0d0f7adb, + 0x4ee984d5, 0x8a0dee16 }, + { 0x47366e6f, 0x504991bf, 0xe86c3005, 0xb8084d9f, 0xa40cce36, + 0x14c4c751, 0x3f1961e2, 0xbbb46aa6, 0x40445e43, 0x56a785f9, + 0xc91e215f, 0xdb8d1b57, 0xc7ee808d, 0x6a8e453e, 0xbbaa1e8c, + 0xc0367ef8, 0xe3e18109, 0x310d91f1, 0x7e20a2c3, 0xf97cfd0e, + 0x554cc277, 0xf1e80c84, 0x7b628403, 0xe89bbc1d, 0x3fe0a17c, + 0x7778a966, 0xc1f00073, 0x9e9db19f, 0xb6f6bed2, 0x2ce7fe7d, + 0xee97ce23, 0x7b04b5d2 }, + { 0x82c5faf8, 0x5b546bc7, 0x8eb81097, 0x1a734c5e, 0xe77851e0, + 0x3d566861, 0xe956d51f, 0x833a1013, 0xc3c3c37c, 0xc7351731, + 0xe0c148ec, 0x607738fb, 0xe1bbef41, 0x2ec6f0bb, 0xcfa51857, + 0x0aa2ac6e, 0x66e3adf0, 0x072902d7, 0xc622d6e3, 0xcd4d5089, + 0xa6dd802f, 0x3ae21b23, 0x33886372, 0xe5465a55, 0xa8d81822, + 0xd85119a0, 0x3786977a, 0x4f14d032, 0x9c7b272c, 0x515b081c, + 0xc99be31c, 0x1c6a95a4 }, + { 0xc2821363, 0xa6b14ad5, 0x4d17de1c, 0x829c1823, 0xccade848, + 0xaef5d2c4, 0x82489e27, 0xf412ab39, 0xf081d927, 0x92c9c098, + 0x75cbad1f, 0x6f87bdf4, 0x1a1d9fb1, 0xf4aadab8, 0xb75f3b76, + 0x475a7923, 0xdbbba8fe, 0x99dd0ad6, 0x4b70ab45, 0x836f6164, + 0x34bd9af1, 0x2a464881, 0xba9abda3, 0x5c91226e, 0xe65625fb, + 0x4cec8709, 0x0818e4be, 0xd4b3919e, 0x14f6879c, 0xa5c09c84, + 0x30a864c9, 0x72708a02 }, + { 0xf34a466c, 0x4f33c0b1, 0x7f9d45ba, 0xa1bae09c, 0x0e28785c, + 0xd70f0fee, 0x90880881, 0x824c7146, 0xbb043da3, 0xe2416c2a, + 0xcec6f432, 0x733da713, 0xc9793e1c, 0x2b590649, 0xb35c9365, + 0xdb62d5b0, 0x3e5c1b2a, 0x355eb6e2, 0xbb16b515, 0xcfe8b5ce, + 0xf709691c, 0x9e081869, 0x61a85bd5, 0xc865f9fb, 0xfae103f7, + 0xf169d3cc, 0x73467e9d, 0x9525c473, 0x43695113, 0x7db55c0b, + 0x73265d21, 0x7491c74c }, + { 0x80d2b94d, 0x312ed5bf, 0xba4b260b, 0x1b8ac633, 0xd62219a1, + 0xac86c58c, 0xaeb82c8e, 0x317ccf6b, 0x59ef9ced, 0x2dfb29ee, + 0xe42bcd5a, 0xdaa7d898, 0x5974b201, 0x93e295c8, 0xd9fc5adc, + 0x69e75784, 0x012aa3ba, 0xd6c4709f, 0xc85d3cb9, 0x1fda9f37, + 0xd3dd4abd, 0xe5487e25, 0x0b3ba22e, 0x00fd4b01, 0xc6e8dcbb, + 0xcb591493, 0xbce68664, 0xb7329fab, 0x68906b76, 0x6829d1c2, + 0x74176841, 0x8bcfd3e5 }, + { 0xd3c8c314, 0x06882734, 0x11870833, 0x95f0b2f1, 0xc068ba16, + 0xb937f7c3, 0x77924787, 0x5365e0d8, 0x1f992227, 0x15527e5e, + 0x27dffd4f, 0x0a069648, 0x2f586389, 0xd58b3df2, 0x6af20ead, + 0x83446b89, 0x50746257, 0x09d7970b, 0x4022a691, 0xd9e8d206, + 0x671ec379, 0xd1e5f8af, 0x057fe91e, 0x6f542509, 0x52890418, + 0xf14dda81, 0x1db932ad, 0xbd78010e, 0x905a9378, 0x3e18d1e4, + 0xbd37ab49, 0x53cadcf7 }, + { 0x5e53d0ff, 0x1bb5edf7, 0x888abf67, 0xd886606c, 0x12206d15, + 0x6491b0f8, 0xe22b6a33, 0xb3018345, 0xb173b317, 0xaba6794b, + 0x7dc9e595, 0x8c1e5867, 0x239624d1, 0x4e106482, 0xda55dd53, + 0x61752e59, 0x9e42879c, 0x018b4eab, 0x491f2bed, 0xcaf6784b, + 0x1e79429e, 0x3dcdb9d2, 0x10f26224, 0x36941485, 0xa650ec5c, + 0x106f190a, 0xb69a9760, 0x7542a5ae, 0xc32d1046, 0x69bd75e9, + 0xbf8c62b1, 0x90849964 }, + { 0x5a93c661, 0xb1390cf6, 0x9db5f056, 0x18486264, 0xa51a1788, + 0x92a93a9d, 0x6772de9a, 0x1b0cbb8f, 0x7c71487c, 0x6e67febd, + 0x4e62423e, 0xf9b4382d, 0xbb5a42f8, 0x96fda50e, 0x6089a4f2, + 0xc921b337, 0x875ec516, 0x49d32d7b, 0xc410124b, 0xbd86d2ca, + 0xc421fb7a, 0xf6862209, 0xf6b7de33, 0x3e1949ab, 0xe93c9268, + 0xcdee18f0, 0x08dc4cc0, 0xd4edbd5e, 0x73580d22, 0xc2b75be4, + 0x468cd7e8, 0x3d7f6ffa }, + { 0xdffbd5d1, 0xea7b290c, 0x970338df, 0x9d759da6, 0x90feedc9, + 0x56680b08, 0x42dce68e, 0xbc690af5, 0xb2ae4d82, 0x8519df2b, + 0x7f195b60, 0x5612467f, 0xd83c21f4, 0x659a342c, 0x55651633, + 0x55771bf5, 0x548ba562, 0x5fc68935, 0x9492f23a, 0xb5419203, + 0x9c9c6017, 0x567528e3, 0x511e6019, 0x3f064ed4, 0x1d16a555, + 0x303f9eb9, 0x2254abee, 0x3e18c4fd, 0xfd434e7c, 0x40994d6f, + 0x6dde74e6, 0x8fb12d3f }, + { 0x293cb7a4, 0x6c6381a2, 0xb87b7e4d, 0x453e09f0, 0x078ac3ef, + 0x4f212823, 0x578cae91, 0xe89ffad0, 0x716ba4dd, 0x4a2b696a, + 0xf6f580a0, 0x14681a14, 0x4c2f1307, 0x1358f97b, 0x2932fb89, + 0x87896996, 0x268a5af7, 0x29dd850a, 0xfe239f83, 0xaf771f6d, + 0x4f47499d, 0x5f20fd2e, 0x867ca0e9, 0x9b643e77, 0x375981ec, + 0xe7858ecd, 0x19ab1c97, 0xbe946a59, 0x06ff3453, 0x4f9303a2, + 0x75d237b1, 0x3fcc6731 }, + { 0xdf21f920, 0x509debd5, 0xc1401b90, 0xfaf70e1f, 0x95a64aaf, + 0x2429cbfd, 0x2c37a122, 0xf2120855, 0x7deb926b, 0x1d4c93f4, + 0x9fb3f1dc, 0x12f3e4c0, 0x5b51bc46, 0x56085a59, 0xf10fdbd2, + 0x2a2f5d62, 0xdf0cb3c2, 0x60dd62cf, 0x6b0f254b, 0x154424a3, + 0x564612b7, 0xc3a5a05d, 0xa1f5249c, 0xbebe30cf, 0x7e62a188, + 0x24ec6903, 0xaf429939, 0x75f0fbac, 0xb3fa8685, 0xd41345dc, + 0xc7151c34, 0x645146fd }, + { 0xba1924f9, 0xecec633a, 0x006326e1, 0xbba6f136, 0x7e50fc17, + 0x203757ac, 0xef3d8e00, 0xca531919, 0x51dc5a74, 0x9545a6aa, + 0xd31412b8, 0x6e21d58f, 0x7bb1d000, 0x01bc3005, 0x6ed1a9c3, + 0xf1789c69, 0x9858fa48, 0x7af2d35f, 0x8197be85, 0x434d09b9, + 0x29aa265d, 0x1dc07755, 0xc058fa80, 0xcad03be7, 0x54ba14ce, + 0x92d70a9f, 0x6c050a74, 0x6dc78505, 0x4d005dda, 0x2a7ca4a9, + 0xabfb9f2e, 0x448d3d72 }, + { 0x29b33989, 0xdc56f145, 0xa9ae815a, 0x868351bc, 0x4b074414, + 0xb3f45613, 0x3cd9f33b, 0x955ce42a, 0x5ff6e4a3, 0x13ade4ec, + 0xa50eaa91, 0xd3aac715, 0x5666efdf, 0x0c61ec99, 0xf6a4470a, + 0x108a28b8, 0xe54844c9, 0x402ef584, 0xd0e2f337, 0xb825b162, + 0xb46f7cbc, 0x3dcd131f, 0x96f2fd89, 0x208178ec, 0x25928c78, + 0x4d8c5d67, 0x9963c459, 0x285a33df, 0xd92a309f, 0x72497175, + 0xcb7019a5, 0x76881479 }, + { 0x91767eed, 0xba43a114, 0x92bf65db, 0x5e11b9ad, 0x03a5e21a, + 0xe8a22ce0, 0x2a335415, 0x63604421, 0x4a9ead62, 0xc2c563b4, + 0xa0b2aee5, 0x4bc06264, 0x8bf2e1d7, 0x75b8d575, 0xd08a265d, + 0x1cff0ee7, 0xb0b712a7, 0x17914e1d, 0x4b18692d, 0xc35925d0, + 0x56cce815, 0xde253f4c, 0x9fff0e3a, 0xa479241c, 0xddabed19, + 0x50b9d06e, 0x59fae506, 0x67135260, 0x532ce180, 0xf37600fb, + 0x5e5a8626, 0x670eb01c }, + { 0x73cdbb43, 0xdf73c0af, 0x7f2431ad, 0xcf08ecc5, 0x2a1a3845, + 0x91780541, 0x9224ddf1, 0x69a104f2, 0xbeac7eff, 0x4352f38d, + 0x7c2d1322, 0xfc3b3b4e, 0xb5e4b476, 0xa69e9430, 0x975a46f0, + 0x7d932340, 0x5d64eece, 0x8093899e, 0xdb2345e9, 0x7b821250, + 0x7f4b796b, 0x23552932, 0x4bb90b1f, 0x2ee9cc15, 0x9112f7d6, + 0x1fa9c8f5, 0x1cbaae32, 0x2d0f2f98, 0x0075166a, 0xb77f0366, + 0x635dff27, 0x504852e7 }, + { 0xa2f392fa, 0x2f0f3ce5, 0xec6c9078, 0x326c076a, 0x84baaaf6, + 0xad01de92, 0xcbe8e993, 0xb01b16d3, 0x2d950908, 0x71305c24, + 0x3853af38, 0xc66fd617, 0xd3c429a0, 0x7735140e, 0x1fabf027, + 0x8a31b12a, 0x058b3177, 0xa0530002, 0xa9c7deb9, 0xabffd9fc, + 0xe8667d30, 0xd05ef69b, 0xe9a9e13f, 0x2f3a7308, 0xb91eae9c, + 0x3f4c9a19, 0x618ce6c4, 0x50d0cee7, 0x5240f8b0, 0xfb24dc40, + 0xf7e90cc4, 0x992fe151 }, + { 0x38f197aa, 0x4454db31, 0x87872f98, 0xa4ded69d, 0x44f0a828, + 0x97b427b0, 0xa31e48c6, 0x9821e1ae, 0xdd98efec, 0xe38cb09f, + 0x480cb3ae, 0x20b84fa8, 0x47475573, 0xba5bb4a8, 0xcd50e96b, + 0xa9be080a, 0xef103550, 0xc4451e9c, 0xc441325c, 0x626ee75f, + 0x38a5e33d, 0x6eea5e98, 0xa2b0abd2, 0x7321beb9, 0x9b6082a9, + 0xca92e484, 0x992bcc2a, 0x1dc8168a, 0x9c8eb9fb, 0x134ecf4b, + 0x4c5b71e0, 0x5a68bfa8 }, + { 0xff0a2bfb, 0xb4ff3b45, 0x5502f8b0, 0xd105fff9, 0x5b1c0c26, + 0x14de5885, 0x0d3b9d04, 0xed16865b, 0x026d3917, 0x2f5a2453, + 0xf4db3c0e, 0x6a22f493, 0xe2418f2e, 0x4871548a, 0x509bef61, + 0x6ab363a8, 0xb8cbbbec, 0x91ca1e3a, 0x4011a396, 0x71e0dc98, + 0x0d5ca577, 0xff982e0a, 0x81897bc1, 0xeb40b045, 0x085ad5e7, + 0x4bc24a46, 0xa6337b7c, 0xd15c8fa0, 0xbef1628f, 0x56ce6ef7, + 0x9f5ef439, 0x78acfdf9 }, + { 0xf8520189, 0x45bf7f15, 0xc77f61c4, 0x954202a0, 0xdfa22e1b, + 0x39edc6b9, 0x1f4a3487, 0xd2d60267, 0x4814cc52, 0xcd933929, + 0x05e9f123, 0xde76a124, 0xae36b6f7, 0xe2306ea0, 0xb83a58e0, + 0x53815218, 0xa041231a, 0x9862bb76, 0xbf31be71, 0xe8da253c, + 0x37de861f, 0x2dfc5332, 0x90ae4890, 0xf25c93f6, 0x8baa6ed2, + 0x66bcb8f0, 0x908b4a29, 0x6f10ae0f, 0xb061c949, 0x8cb4b48c, + 0xd075a366, 0x0ad92d73 }, + { 0xc2ca548a, 0xbfb95fed, 0x80cd89ab, 0x4778c620, 0x3466c280, + 0xbe99154b, 0xd4be8902, 0xea3be093, 0x13e681ed, 0x847b7995, + 0x02f40161, 0xf22a8f4b, 0x4aeb7fe8, 0x3ef2cb4d, 0xb3aed5f6, + 0x9adc5151, 0x98c31163, 0xec1ccfd1, 0xa3d7d88f, 0xdc2ac17b, + 0x46421097, 0x08fa64d3, 0x94b90bcf, 0x5ebf80b7, 0x0b50a9eb, + 0x1b78b4ba, 0x279aa66b, 0x1a4fe934, 0x075b3ced, 0x8ef4dcaf, + 0x70a6e9ae, 0x95bbd8a0 }, + { 0xe614bbd0, 0x59f92495, 0xb823e363, 0x7567a887, 0xfc1bd6a7, + 0xe247c9ec, 0x8e835c42, 0x2bfaaf47, 0xaade066a, 0x314ef4e0, + 0x5c16d336, 0x072baa63, 0xe2f0e389, 0xfa429c71, 0xbd07d90f, + 0xcac1e5d0, 0x514f5c04, 0x69ff35ea, 0xc0554ec1, 0x893053fc, + 0x2a35947f, 0xab1d86b7, 0x2aebe487, 0xe29fb060, 0xdfb9cf21, + 0xa0a10d6d, 0xf20dfcf5, 0xad147059, 0xb8867a2a, 0x480dc66f, + 0xc125a919, 0x375a884f }, + { 0x1217f7ea, 0x178cbe2e, 0x875c6dab, 0x1a161e2a, 0x1bdb1a54, + 0xf7707ec0, 0xe4fd73ca, 0x678864a0, 0xd13a0d86, 0xbaebc664, + 0xc8d30668, 0x40325f99, 0x2f1c5950, 0xb93ed9c9, 0x541e0667, + 0xfdf36763, 0xb91a6763, 0xfd97fbb0, 0x6079c9a0, 0x26aa69ea, + 0x1eaa8c47, 0xc7303c80, 0xafa63c55, 0xdec75c81, 0x4fd12adb, + 0x01cdcde2, 0x1968838a, 0x9fe0dda7, 0x38415379, 0x66bb093b, + 0x08cb84ec, 0x268d818b }, + { 0x41580555, 0x73dae358, 0x473d103b, 0x4fc32e67, 0xbeccc1ab, + 0x240c1013, 0xb24ee9de, 0xda4099f2, 0x9fa8e066, 0x37b0cb5b, + 0x6438d7ee, 0xb5ae04e4, 0x2b720140, 0x7f7d3164, 0x339e4a78, + 0x86ef4edb, 0x3a7d8375, 0xa5e77eed, 0xbd707c2e, 0x883fad37, + 0x0f979189, 0x816b633a, 0x2e7a208e, 0xe24c028a, 0x4435516a, + 0x1171fe3c, 0x4f5f2bf5, 0x3eb93b33, 0x01b53a56, 0x8419ed4b, + 0x056ca44b, 0x8b02735c }, + { 0xe1019195, 0xb89bb464, 0xf3fc28c1, 0x1de4c026, 0x2bfc3b21, + 0xac120e6e, 0x91bdf92f, 0xec71bc5a, 0x0d995bc9, 0x485d7ab4, + 0xe6491ffe, 0x97c6768e, 0xafbce265, 0xd9552d19, 0x8e1b76c2, + 0xbae6c7fe, 0xd7e3ad1b, 0x167d8281, 0x5e989734, 0x3e149af9, + 0x8a0c8182, 0xd1f0024c, 0xc3006c0d, 0xf571ffdb, 0x58773d4c, + 0xb32ecf7e, 0xfd3540d8, 0x5822a782, 0x04365042, 0x5ab45c3f, + 0x4b4d85fe, 0x400e3aa0 }, + { 0x5e46e4a2, 0x47321649, 0x24136074, 0x37a2ed64, 0xc60ec77d, + 0x659223b1, 0xe5e0ac2e, 0x5e13aac3, 0xc5107ab7, 0xda17c41b, + 0x73c253db, 0x65b22ec9, 0xa5012296, 0xff3867b8, 0x0621a99b, + 0xfed660d5, 0xc89fc3f5, 0xa3c28506, 0xf16451a7, 0x3ed350b9, + 0x67cb586f, 0x27c3e032, 0x967185b1, 0xc807c779, 0x4a13009b, + 0x09c157d4, 0xadaf1f4d, 0x362f7647, 0xf3a6a198, 0x4a42b9ac, + 0x8da6e039, 0x131c3da2 }, + { 0xa7da83ba, 0x4a785ff1, 0xd04f4436, 0xf415b425, 0xec03f812, + 0x7c0899bd, 0x80f5f4a2, 0xc58d411a, 0xfda251b9, 0x3d32d610, + 0xcd3b2f32, 0x99bb4504, 0xf4c2083c, 0x198c444b, 0x730e83fd, + 0x60c261af, 0xcb02db90, 0x060ca4df, 0x9df1e7c8, 0x0ff7838b, + 0xc4c690c9, 0x6b79cf97, 0x5d75f154, 0x131514d7, 0x1cb0e8ff, + 0xa7c074f1, 0xb2c17615, 0xb920aac1, 0x44aa0ff0, 0xde8098ad, + 0x34545ce9, 0x71d1a46a }, + { 0xfa1b382e, 0x76178f76, 0x772dda0d, 0xa0d8ecc3, 0xc5d4d130, + 0xaa5aab2a, 0x8d72622c, 0x27d38ba4, 0xca3bed06, 0xc5410db6, + 0x793ceccf, 0xf637a588, 0x6e65e3d7, 0x1f65dafd, 0x60a45641, + 0xc3b44a85, 0x4f78540b, 0x0f47b3a8, 0x5e4d60f6, 0x824fdadd, + 0x17d3b6d5, 0xd8ccf90c, 0x325fc13a, 0x008eabdf, 0x3648fab9, + 0x3e90d716, 0x24c52d4b, 0x3964ff3a, 0x533d0acb, 0xb95cc416, + 0x1167f521, 0x6cd2699f }, + { 0x12f4f3ac, 0x2d8c0b3b, 0x99d1bdfb, 0xb03dcfe2, 0x30f37326, + 0x540034f8, 0x7c5a8c82, 0x22dd6893, 0xcd8f1442, 0xeb7093d0, + 0x585742f2, 0x892795a7, 0x087adadd, 0xe15f282c, 0x16ab7b5e, + 0x7bbdc749, 0xa58acbb4, 0xd30fe40b, 0xe2bac39b, 0x0de417eb, + 0xc61a04bc, 0x4b4b19a6, 0xf2735569, 0x9338c34d, 0x30ab196f, + 0xe8f03742, 0x6c88c965, 0xfa2efcb8, 0xc7eeb826, 0x19eee274, + 0xda345dc2, 0x327c063f }, + { 0x5b47cd53, 0xab399eff, 0x1943aefe, 0xbbe9869d, 0x1402a866, + 0xe64ecc7b, 0xb1c25a16, 0xc3e7c2aa, 0x022de271, 0xc4216b79, + 0x366d6a5f, 0xe58dfcc8, 0xda813336, 0xd159509e, 0x130bfb7c, + 0x370400f2, 0x93b48780, 0x1be4e059, 0x39f3cd22, 0x0623a1fe, + 0xeecb4f87, 0x72aa22b2, 0x6c27b83b, 0x1af4c496, 0xda5fa5bf, + 0x7a42a94b, 0x48b01af2, 0x9afba822, 0x3670112c, 0xeb6b9d2a, + 0xc0df6856, 0x020f19d1 }, + { 0xa4dbba20, 0x37051a86, 0xdb1de5c5, 0xb618ebc6, 0xe6525840, + 0x9a780a19, 0xd2bccc4d, 0x9440302d, 0x10285a24, 0xe9ff023d, + 0x3a486268, 0x3b937ee3, 0x4cd61147, 0xe37ee2f2, 0xa3d057cf, + 0x79fbbfd3, 0xccddefce, 0x5fba16d3, 0x5b231727, 0x916058ec, + 0x720c3adb, 0x47699ebe, 0x8b4f6bba, 0x26274386, 0xf18a0770, + 0x54b0092a, 0xacca1160, 0x99d090eb, 0x0c888f60, 0xf757e1ff, + 0xb0050544, 0x79e72720 }, + { 0x2820a239, 0x632acf25, 0xaae6b310, 0xb1a3974e, 0x48c0a1df, + 0xd61fd6ba, 0x5a3ee7aa, 0xd2453c39, 0xb980446d, 0x548455a0, + 0xde16676f, 0x9f29d97b, 0x789375a1, 0xf252ca0c, 0x7743a985, + 0xe961af3e, 0x66cdbd8d, 0x70c79c56, 0xcbc538f9, 0x14a3854e, + 0xa126851c, 0x58daa73a, 0x2a9f558c, 0xe9b5bb45, 0xfbd15e05, + 0x37af7f83, 0x38a1939d, 0xa4487927, 0x9511a056, 0xe428b2b5, + 0x7015846d, 0x001d3ce3 }, + { 0xe145b1d7, 0xd6be36b9, 0x009c5664, 0xf3e3938a, 0xe7c0f6db, + 0x2e562e7d, 0xc343f539, 0x951044e6, 0xd90897b1, 0xa5ab62b8, + 0x512f797c, 0xb1a1f70b, 0x750f28e4, 0x91cdd754, 0xffb8165d, + 0xb4c80e2f, 0x594d02b3, 0x65ed39c7, 0x56833edc, 0xcc12a49d, + 0xf3693a18, 0xe73694bc, 0xfcd2c404, 0x34cc134a, 0x11d40194, + 0x071bd5fc, 0xfc585e46, 0x05759047, 0x790b7a04, 0xb3280360, + 0x40afc684, 0x4bb8c6fc }, + { 0xfd0f8796, 0x3120e2dd, 0xb133c9de, 0x6968a40d, 0xa9369c6e, + 0xfea366c0, 0x6007273b, 0x37e5b6d6, 0x8cb81439, 0x39e4ecf0, + 0x9febc005, 0x487fe9cd, 0x0199b53c, 0xeb8af444, 0x293519eb, + 0x2f124e3b, 0xc82c9c16, 0x860c218a, 0x709dc590, 0xacd1d6f2, + 0x36d50529, 0x5696d545, 0x59120bfc, 0xc03f5df9, 0x10ffa690, + 0x99a3e88d, 0x6c432827, 0xd4f9cfa5, 0x9a135d89, 0x2e8fea9e, + 0xb6a77e78, 0x3699a881 }, + { 0x1eb1c64d, 0x5bca3372, 0xf1d28154, 0xe9cf3a2d, 0x6537106f, + 0xb7e2e9b3, 0x4f7cbf4d, 0x06c17151, 0x2058b37f, 0xcbde416e, + 0x8834e9c5, 0x82c53a7e, 0xe9ac3a75, 0x94dbdfe2, 0xc5e67c02, + 0x795ec6cb, 0x1426a80d, 0x8c23c25f, 0x6a8d4f9f, 0xee2cd20d, + 0xd3b7c235, 0x838daa54, 0x3d7a4d52, 0xb9e08ec0, 0x781cb473, + 0xca9475e9, 0x5ec31caa, 0x7271f39e, 0x82535187, 0x1df08e9f, + 0x208aff8b, 0x4f3a4b03 }, + { 0x1ed095f8, 0x0f7b8107, 0xda226d4e, 0x23e37fa6, 0xafb36d1d, + 0x8b0f9852, 0x07d8e311, 0xb114634e, 0xe3e0f16e, 0xb9634a97, + 0x421eec37, 0x2454bb9c, 0xd72b21c1, 0xb4ecd5db, 0x6df20d7c, + 0xf9603868, 0xdf86e0a2, 0x9f5359fd, 0x5ac488aa, 0xc43d54fa, + 0xd1049df4, 0x56d714ab, 0xb020607a, 0x13152b3e, 0x7a02325e, + 0x49be1c18, 0x52ae84db, 0x44f24f4a, 0x0b5a7b80, 0x9e525c03, + 0xa6d179fd, 0x6d874446 }, + { 0xbe9a42f5, 0xd29d07aa, 0x3781ccc8, 0x1fd5316c, 0x9dc69ea1, + 0x71a75a6d, 0x88fee91a, 0x4e19e0df, 0xf8d44f12, 0x99c2b4dc, + 0x31ae94e4, 0x05f6df92, 0xcf28ccc2, 0x27fba876, 0xf57f7ceb, + 0x6e1a0f01, 0xf3fd3b74, 0xe03f1f34, 0x42c1d213, 0xa0edc4a7, + 0x7deb8580, 0x5caac270, 0xaf0848bc, 0x0f5d791f, 0x07ac759d, + 0x17f514ad, 0x904fc531, 0x95a39734, 0x7bb70f3d, 0x95a4aca9, + 0xff9c5609, 0x3cf384c9 }, + { 0xce1fc9e3, 0x700506ba, 0x676b0399, 0x49721742, 0xe72bf7b3, + 0x2b4a1b8d, 0x79b209f7, 0xca8602a8, 0xce26a8e1, 0x90580b90, + 0xfe24f39a, 0x1ef339b7, 0x629362e1, 0xb6c5d991, 0x577b24f4, + 0x51174e1a, 0x05e451e9, 0xf380fcb5, 0x148321bd, 0xf4d97afb, + 0x747e5d2a, 0x099806bb, 0xbe99a608, 0x85525d65, 0xd455e820, + 0x264828d9, 0xd8560a65, 0x8c8c5405, 0x71030770, 0x3c67e73c, + 0xee73df26, 0x2b248850 }, + { 0x8541159f, 0x2173cde6, 0x4fb410b2, 0x78224c18, 0x1f2ca1c7, + 0x07a28619, 0xa8b23e40, 0x52c207d6, 0xa6b2344a, 0x071a0210, + 0xb5ed2945, 0xdb0e587c, 0x810fcc6c, 0x6c56b8ef, 0x62d843b9, + 0x1248c58f, 0x74c66975, 0x4b90363d, 0xe66c66f6, 0x6348f7f2, + 0xc126bcbe, 0xb2f9d441, 0x73ce49e8, 0xac07f2a3, 0xe81b0df0, + 0x52486758, 0x1d4621d1, 0xa108b54d, 0x74414a1c, 0x17261ece, + 0x6a3ac215, 0x938b3bcc }, + { 0xe4ded340, 0xa9e4a16b, 0x80e88036, 0x8e65fb2a, 0xdcd73acb, + 0x97089606, 0xaaa657a9, 0x1c3a0434, 0x49101b06, 0xf304fc58, + 0xda0bb64c, 0xe60fb61a, 0xf5542df5, 0x818c2aec, 0x56f76d5f, + 0x74020576, 0x92533d97, 0xb566b790, 0x74d6eb5f, 0xae4655e5, + 0xa55b44b7, 0x60f7a1b5, 0x93747ea5, 0x7970179b, 0xf2dace56, + 0x8ae7e0e8, 0x84e83c06, 0x98474607, 0x15307341, 0x24e8c9ed, + 0xd9e89d6b, 0x6cff58a5 }, + { 0x03e51f68, 0x508c01b0, 0x1d2fe7d6, 0xe1d1f225, 0x09bd8805, + 0xf7998d0b, 0x03e415b7, 0x255e907a, 0x607d9798, 0xd148467d, + 0x9b453896, 0x055c3b1e, 0x809f50f4, 0x35001013, 0xd0233fdc, + 0xfbbb2fa6, 0xff1820b8, 0x0b680b0a, 0x38d317e0, 0xb1d404dc, + 0xccc8c7df, 0x133d5444, 0x6ec13f84, 0x7fa847e6, 0x046e2e48, + 0xc33f83d8, 0x4863b3ac, 0x3c627fc5, 0xeb936af7, 0x5f67f8aa, + 0x31b79327, 0x5fe4ac8f }, + { 0x8b6f401e, 0x581aa4bf, 0xad5c7ed4, 0x05db12a3, 0x6fb07b4a, + 0x7b018726, 0x9c22bcd4, 0xfdd11f04, 0x69371c95, 0x5454a7d4, + 0x99a46eaf, 0x066c55fb, 0x7fef96d0, 0x18637c7c, 0x6b83e95c, + 0xbafc1d34, 0x00bb42dc, 0x55c38593, 0x34e7e712, 0xdd8dec2b, + 0xb184cee8, 0x69c9cfb0, 0x49a27864, 0x8dcc0c42, 0x2010f2e7, + 0x290d95f2, 0x6977a420, 0x86e254c9, 0xeb2abdad, 0x20931c89, + 0x121c0548, 0x81377164 }, + { 0x9c5a8edf, 0x6266b25e, 0x1078a7ad, 0x6e1388c2, 0x4876eedf, + 0x5f02737d, 0x62744617, 0x242fa7f9, 0xb385382a, 0x3e2cfbd9, + 0x02f71bef, 0xbadad7b1, 0x677d0a92, 0x562abcfa, 0x51fdff34, + 0x573ebd17, 0x7c250c78, 0xd7f65852, 0xc47ca896, 0xe0cf16ee, + 0x67622c9e, 0x8ccd79b0, 0xf8f2c075, 0x31fc5882, 0xa6008515, + 0x9232b37e, 0x82e8c5ba, 0x4d7bb361, 0xd2f146fe, 0xbf24735c, + 0x9cd2db98, 0x79c280ee }, + { 0xf2b48122, 0xbdcc8203, 0xb04ac48e, 0xa8c04916, 0x9fc4885e, + 0xacf064dc, 0x82c1001c, 0xab838997, 0x676de250, 0x7339e721, + 0x8e1ab820, 0x17aa5aea, 0x6bc14b2e, 0x24d28ca0, 0x816b6230, + 0x570c5bb7, 0xcee6b606, 0x6c51235c, 0x183eae42, 0x1b2bf89f, + 0x9c66274b, 0x3e3af3c6, 0xb51e38bc, 0xe0b04426, 0x73e40e3b, + 0x26dbc58e, 0xb5be5be4, 0x3f9dd578, 0x52c8f408, 0x9fd9f791, + 0xa9e3ff4f, 0x758073a4 }, + { 0x8691ca22, 0x7d27b057, 0x13a2a1b6, 0xf206bfd6, 0xac795413, + 0xe84bd385, 0x75536607, 0xc5d18a2a, 0xc8a0e24c, 0x2e166de7, + 0x3c474dbd, 0x56d5750c, 0x1366843a, 0xdef444c1, 0xcf4b8432, + 0x14646e53, 0xa9fd9783, 0x4bc0d030, 0x297ee203, 0xbda4c824, + 0xfd7be6c7, 0x3d0b10bf, 0x08c7f3ff, 0x2d216476, 0xb4fd4c45, + 0x06e52599, 0x49e9e104, 0xfbab9fa1, 0x8661d32d, 0x9342a7fa, + 0xfaf66aa8, 0x3f3e3458 }, + { 0x951597aa, 0x51ec35af, 0x49df64eb, 0xb677d4ac, 0x9bf4eff5, + 0x0276cd9c, 0x515a2935, 0x423eca49, 0xfd9bb9c3, 0x8a696553, + 0xede1f09c, 0xf99ee9df, 0x199e5f98, 0xb8fa2956, 0x35292c32, + 0xb7638758, 0xfc40e81b, 0x8734eddc, 0x65457d95, 0xd82d5e9f, + 0x30c78d2b, 0xc8ee323e, 0xc1433d67, 0xe77b2e4c, 0x3c8314ae, + 0x56d9f807, 0x2a0e2f63, 0x441eede2, 0x6c48295e, 0x1e9e17ed, + 0x34c294ef, 0x640d20c4 }, + { 0x3284d513, 0x4e9a0b8e, 0xf315053a, 0x074c3545, 0x45acd52a, + 0xb36e7407, 0x1de50db7, 0xd80bdcfc, 0x2549fc46, 0x8d9d47dc, + 0x303f07a8, 0x29b6ef13, 0x6d4ad4c2, 0x4e461aca, 0xfc9f1b73, + 0xca8e351d, 0x57460e65, 0x8bc4094d, 0x0f32d367, 0xb6302b33, + 0x285742e8, 0x69a074b6, 0x876c29c3, 0xdfe52b11, 0x912bd17a, + 0xf39e4609, 0x349aa639, 0x8ee40d66, 0xc72e05c1, 0xb968902a, + 0xc0d92816, 0x0f9c1ca8 }, + { 0x67433df3, 0x1ebbaab3, 0x15d3628c, 0xb6aa5347, 0x97f0c5cc, + 0x13a320d8, 0x65e408f9, 0x72c918cb, 0xd5373451, 0x4b638854, + 0x0b4dca09, 0x731399a3, 0x0a3b1326, 0xcf256730, 0x6608b388, + 0x5ea60dfa, 0x7b290dfd, 0x58ad74b0, 0xd7694f9b, 0x83202789, + 0xb6630fb1, 0x48593db8, 0xc65e3eaf, 0x3db47f70, 0x3e7263f8, + 0x63949c91, 0xe6e6ff33, 0x9b9acec6, 0x098a8240, 0x34bd9ba7, + 0x45d36ec5, 0x7e31c12f }, + { 0x0dfd2dd7, 0xbe281d68, 0x24ab61d8, 0x1efacb00, 0x94431f97, + 0xb9c3005f, 0x959cb3bc, 0x660c8dfa, 0xcffbb406, 0xfdd5fc30, + 0x7969a10d, 0x7a4631be, 0xde13fd1b, 0x336e309e, 0xfc947076, + 0x76b3bfad, 0xdcc72223, 0xfa91925d, 0x156c4ee1, 0x741f0d73, + 0x0e2b3747, 0x4f64ee41, 0xefc4d93c, 0x86be92d3, 0xfc4fbb2e, + 0xc53b7e03, 0x337ca1bb, 0xac196cf5, 0x7e23ba60, 0x4de41a30, + 0x326d5357, 0x1a219c45 }, + { 0xaa4db0bc, 0xfdcf7ef8, 0x7b6c9963, 0x2e231806, 0x3d8a192f, + 0xc2639067, 0xffdc7771, 0xc0cec2e2, 0xa2fc0edb, 0x997c8e35, + 0x82cc6043, 0x78e10ec1, 0x2b0c8120, 0xfd0de2cb, 0x69e57f8e, + 0x4d6c457f, 0x5b53f1c3, 0x953e69b2, 0xc4f89cb8, 0x422a330a, + 0x95566be6, 0x92ff2329, 0x437442d1, 0x73cd502d, 0xbea69403, + 0xf04ce590, 0xf8030662, 0x6ac1537e, 0xb6d0bf93, 0xe02bcf77, + 0xbc90192f, 0x17aaa999 }, + { 0x8e55db2e, 0x0d3d5643, 0x3b946851, 0x835dee43, 0x5b88462f, + 0x1a1440e5, 0xea17e27c, 0xa6ff3b35, 0xdd95f7a9, 0x23f99c36, + 0xbdd672cf, 0x7217fdd9, 0xdd2045c0, 0xf400ac1e, 0x4ff06b25, + 0x94b55c87, 0x0e4a49be, 0x0a44a0e5, 0xb43b6813, 0xe8925e91, + 0x214f96c5, 0x78bedde1, 0x0f97fa97, 0x0f456a4c, 0xa5bfd267, + 0xa28fd86b, 0xbe7608ef, 0x3b4b2d8f, 0x226474bc, 0xfbd5ff8c, + 0xa5f3b24a, 0x6b282af0 }, + { 0x6341a595, 0x78fc025f, 0xa445e28c, 0x591c38d6, 0xeb446842, + 0x72bd6e3d, 0x75547833, 0x3f9466d3, 0x083e16c4, 0x911414d3, + 0x95a7acb4, 0x145d9466, 0x8fd2fb64, 0x102ddf09, 0x0bfd87b1, + 0x2a2b2d2d, 0x59455088, 0x69e9be5c, 0xa80245de, 0xee378bf4, + 0xb2306b0e, 0x80b0bd68, 0xc2be9f3d, 0x76a545c6, 0x4802c245, + 0x429d167b, 0x2b412dfb, 0x13e64427, 0xee8d9762, 0xb664f529, + 0x54706ebf, 0x6d4f5d23 }, + { 0x00ba9f88, 0x35c8f2b6, 0x7bb6d0bf, 0xfdc807e0, 0xb3b81e5b, + 0x0a126d42, 0xa7ac781e, 0x335ce6ce, 0xf37dcba6, 0x3e308e6f, + 0x63c96487, 0x028dca62, 0x8818434d, 0x72eba57e, 0x79b78a26, + 0xa9e3d59f, 0x2f07aea3, 0xd2f0a7dd, 0x24d05f74, 0xe0fe4678, + 0x0116deb6, 0xb2085170, 0x58f37580, 0x9c2a5e92, 0x74070bb3, + 0xe78bd7a5, 0xb9977d90, 0x551fc872, 0x40db81b4, 0x6eda93c4, + 0xd65d34ad, 0x4aaf0b4f }, + { 0x3514c7af, 0x9bef2506, 0xbc181ead, 0xb09e7dad, 0x8fa3ec58, + 0xef3cae87, 0x173b8685, 0xd8dbfab5, 0x921d32dd, 0xb2490fc0, + 0x8bd9c466, 0x4eef386b, 0xa061dbdb, 0xc1cdd52f, 0x25bc04db, + 0x64de989a, 0x85728636, 0x06f9836b, 0x8be44aa0, 0x11a5a804, + 0x097018c7, 0x16dede4e, 0xb2c11fb1, 0x72aec577, 0xa721ecd9, + 0x144dade1, 0xd6ebf3a9, 0xf99c526b, 0x1c2e14d7, 0xa1d4165b, + 0x82bc6337, 0x8b2cbd39 }, + { 0x8a52e991, 0x28ec1bf2, 0xcf9d42ec, 0x0ba202f6, 0xc634ea45, + 0x8307d130, 0xc5762b9c, 0x3fc257b3, 0x487c2a2d, 0xbd3298d1, + 0xa319488a, 0xca14f1a7, 0x06ba06d2, 0xc70ca93b, 0xee405e89, + 0x9aa3f4b3, 0x35deeae7, 0xcc64eeb3, 0x03bf1d4c, 0xd155f578, + 0x45616bfd, 0x041ec0b5, 0x086e33f6, 0x23df80e6, 0xf0243cf5, + 0x399a79c8, 0x874ccd58, 0x86c2824e, 0x8fc5c831, 0x220eeaec, + 0x7dbe3670, 0x57e28304 }, + { 0xfbcdf666, 0x6e60b698, 0x8bebb1d2, 0xbdd06a99, 0x80498436, + 0x4044adba, 0x522bc88d, 0xd76bf75e, 0x28423b20, 0x655c4b9b, + 0x53398a72, 0x65c0f492, 0x0ca37601, 0x76d4f2b7, 0x2030fa5a, + 0x46989925, 0xb6054705, 0x96b37e87, 0x53de1b2f, 0xef96f731, + 0xad54ef05, 0x5ecbbc8c, 0xa93617b0, 0xeb289d0a, 0x7cba217d, + 0x3ac0fbd5, 0x19d4a2d7, 0xd0d3cb56, 0xc91d6063, 0xe8bee9d4, + 0x696ffda6, 0x4f12e037 }, + { 0x15f1a610, 0x4ccfa422, 0x3786519a, 0x804a5c55, 0x73838134, + 0x1246a454, 0x4b284e2a, 0xfa15b484, 0x146d1320, 0x36464c65, + 0x70a8a0fa, 0xfb6ba88c, 0x93c4804e, 0x74e7cee7, 0xb95ae16a, + 0x8c34d22c, 0xf9c1d4dd, 0x9d9ed89f, 0x32025371, 0x61a0866d, + 0x9bd6444a, 0x45b232b2, 0xf277bab1, 0xf888e92c, 0xa9448b02, + 0x73e69c6e, 0x5b521ecb, 0x1a496ea9, 0x5858afb2, 0xa8f78ea7, + 0xb1266f91, 0x83d2333e }, + { 0x67b478d7, 0x1c633288, 0x50a2fc9c, 0xa1ee1ae1, 0x18d2241b, + 0x05b6ab30, 0x893cd696, 0x69f1f288, 0xa8117a87, 0x159d6660, + 0x70e73d77, 0xe8120119, 0x93f55f0a, 0x528fef00, 0xd854dfb2, + 0xb3978db8, 0xf45d9fbb, 0xd6b43ef6, 0xd5bee397, 0x17de4bfe, + 0x6bf76dad, 0xa01e0f59, 0x3d40754c, 0x28b2280e, 0xf8e86ef3, + 0x8edb6122, 0xb7d1e586, 0x8226b6af, 0x2f40a55b, 0x46353215, + 0xc5a31621, 0x7362f13e }, + { 0x73c0c430, 0x792eb27c, 0xa51c3657, 0x8cc0a65f, 0xd2194f1b, + 0x50a5cece, 0x814b4947, 0x18945688, 0x4b6fbbf4, 0xbbf0a81a, + 0xf0aa8608, 0x376f4f58, 0x3987795e, 0xd9361d68, 0xe3a8d0d5, + 0xb6510cd8, 0xb6c1a455, 0x63e2fdbf, 0xaec891f9, 0x2c91154e, + 0xff568f64, 0x0eb1e715, 0x2f2b399e, 0xe7af9cd7, 0x89f0bf0b, + 0x1fc39bac, 0x90983695, 0xf0861d92, 0xda0a20a8, 0xd9b16f02, + 0xa38c0ead, 0x2f10693f }, + { 0x0c06ded2, 0x07a6ce91, 0x2fd9087b, 0xf974842f, 0xa9f635a6, + 0xe468bfd6, 0x1ed60626, 0x04b61891, 0x369ee548, 0x1fb2f89f, + 0xdc96a201, 0x9cbd1113, 0x10d633ac, 0x6759acfe, 0x8faa629e, + 0x64ba66fc, 0x47f38283, 0xa686ae49, 0xd59cda99, 0x828c3a05, + 0x08ea2f6e, 0x7c7afb14, 0xaf3953c8, 0x2551c8e4, 0x9daa9e4f, + 0x5b53d279, 0xad6f1940, 0x1eff68d4, 0x96437cdb, 0x2775dbdd, + 0x4fe7a043, 0x985f83e4 }, + { 0xeaf45294, 0x89603c16, 0xc24b5751, 0x70131160, 0x39d6b52d, + 0x4c112018, 0xed943340, 0x7079cf02, 0x74f41b68, 0x0c5b028b, + 0x9c8ac1e1, 0x3dc3f076, 0xf8b24f0e, 0x5ac5eea3, 0xe34c5c22, + 0xee6684ba, 0x9abc452a, 0xa5259e63, 0xe9df45cc, 0xb07d2cd1, + 0x1a443cfa, 0x07019c93, 0x92c003b3, 0x68fddaa9, 0x0d8cbc2e, + 0x2d9f179c, 0x1e781ca7, 0xbbf15a6f, 0x50dcc799, 0x54d779d5, + 0x0fe962f1, 0x0c88e540 }, + { 0xe8f44357, 0x84f71a6a, 0x3a3cab6a, 0xf75b4bf6, 0x5aebc680, + 0x334c9d9e, 0x8a753ef2, 0xcecaf084, 0x075e3c8e, 0xe28014c1, + 0xf74f8d3a, 0xbb9d5a38, 0xb80e32ae, 0x75988464, 0xf2bc3792, + 0x7b328e6f, 0xeed0e197, 0xebbb1faf, 0x5a33065a, 0x674eac95, + 0x922dbce8, 0x8c19fd8f, 0x987b907a, 0x8c17ae85, 0x3b3a2cd7, + 0x89f33627, 0xfa87772f, 0xebaea019, 0x3a25ced6, 0x4e5de499, + 0xaf110715, 0x8e2560b8 }, + { 0x3141aba6, 0x56d3746c, 0xbab2cf9e, 0x45a1079f, 0x9cdd27c7, + 0xb6382831, 0x9dfd950e, 0x22237632, 0x3a9408ff, 0x1e0b15cd, + 0xb1160118, 0x49a80200, 0xa383bba7, 0x2719db5d, 0x651046d5, + 0x6078340a, 0x97523b1f, 0x8929d4de, 0x8e0a28ab, 0x4040345c, + 0x0adf09c7, 0x61275ac2, 0x2331d611, 0xb41ab265, 0x5391ca50, + 0x230cc77c, 0x8f922315, 0x88be0c92, 0x92fd9a29, 0xfef3d92b, + 0x8324f2e5, 0x59005f22 }, + { 0x3c4c1c74, 0x6bb1750c, 0xe966fb79, 0xbe73aac0, 0x66c5973f, + 0x85a75d92, 0x3a8656b6, 0x8c97f932, 0x50446cde, 0x2b7043b1, + 0x3ff3897f, 0x548916f7, 0xb18b72b2, 0x913dd01c, 0x488c0de6, + 0xd0a751f1, 0x8558ca58, 0x19175714, 0x44a663da, 0x97714301, + 0xb0e08618, 0x2df190ac, 0xf39ead9c, 0x0080fc0c, 0x17382da1, + 0x0085ac6e, 0x3262a338, 0xe9791851, 0xb43bae8d, 0xe4495936, + 0xd783df6e, 0x57a78e26 }, + { 0x40dbddd8, 0x161b346f, 0x9410c3ac, 0x2b49a927, 0x1886cf3b, + 0x8c542783, 0x33b93deb, 0x72df3232, 0x40df579d, 0x9c8d59f5, + 0xc20ef500, 0xe5d7a67d, 0x67f08643, 0xc46b3918, 0xad96adc3, + 0xecfa2445, 0x0c4544d0, 0x658f589b, 0xe08417d7, 0xe6ec9301, + 0xc454e288, 0x6ca5ef6a, 0xac0f462d, 0x4191048f, 0x08d8a036, + 0x852407d8, 0xf6d35b7e, 0xb4c533a7, 0x8f6ada87, 0x3251e412, + 0x81c472e8, 0x1ca370c5 }, + { 0xa801b68a, 0x94bd5171, 0xfd1998b3, 0x7312879c, 0x41163202, + 0x4905aabf, 0xf5b01fdb, 0xb5fe87f4, 0x9cda128b, 0x78de523a, + 0xc7bd31f7, 0x0bf161a1, 0x23904c35, 0xb5decfd0, 0xe188f12d, + 0x224b2882, 0xf99dae74, 0x0dd2801d, 0x08cd1cd2, 0xcad467b5, + 0xc0867e39, 0x6c311c3d, 0x2b425072, 0x71a11720, 0x2efd9003, + 0x83bf464e, 0x1dbd3b03, 0x53d0448a, 0xe6265baa, 0x32db52f4, + 0x4c33ac79, 0x2584b34c }, + { 0x2aeec688, 0x3cb86389, 0x45fbe523, 0xa5e740ba, 0xfd60b5f8, + 0x422e71f7, 0x4874913d, 0x455d185c, 0xfa17d80d, 0x04c2bb36, + 0xac054524, 0x3f271854, 0xa8b9a657, 0x76dd3045, 0x62ee7cc8, + 0x2e42c3e1, 0x4df6c7d0, 0x00266706, 0xdc7cb488, 0x5927dd51, + 0x187897e0, 0x6b3faabe, 0xf2d5737c, 0xfe6ad22e, 0xff51a9ff, + 0xafb60269, 0x69807baa, 0xe1c83545, 0x951ca49a, 0xacddb6ff, + 0x3f9ab085, 0x7e811374 }, + { 0x830a88b1, 0xad722a8b, 0xce1117e1, 0x91918ea8, 0x0409b47d, + 0x3e02d0b8, 0x6c46d1d3, 0xb53812d3, 0xe589669c, 0x2fd09db0, + 0x15b0cd5e, 0x9845cd06, 0x2386c453, 0x0c1c155a, 0xf5ff43cb, + 0xda774de5, 0xe391c0cd, 0xbb076b98, 0x5004f286, 0x97d71eff, + 0xaeec0bfe, 0x23e0b46c, 0x32a1ad94, 0xe4538667, 0x396da422, + 0xfe0c9f81, 0x63db2bfe, 0x6376c1a2, 0xba56fa91, 0x001c7918, + 0xdf8485a6, 0x436b8c64 }, + { 0x8ab764bc, 0x88117e9d, 0xa077df84, 0xdfa61e94, 0x0c18eebd, + 0x5a7765d3, 0xfc9451dc, 0x548916af, 0x071a347a, 0x01a52e33, + 0xb23b41df, 0x633b95de, 0x43c8c286, 0xdd7d68c9, 0x18d97068, + 0xe4f9d41e, 0x8c92799d, 0x79908b90, 0xd47394a3, 0xe614148e, + 0xcd51e53f, 0xe5018517, 0x0243dcb6, 0x5060075e, 0x17954405, + 0xe5dcde62, 0x537da5ff, 0x6f7c90e1, 0x0768cb66, 0x1df7aae4, + 0x6dbe95e1, 0x5266ca9e }, + { 0x1386b3db, 0x84ddee6d, 0x7c38e540, 0xf9e4af5a, 0xeb04f49d, + 0xb3418440, 0xfde5a4fd, 0x2138a1e8, 0x30257cfc, 0x3e6e6924, + 0x19fd70c1, 0x3519c6e3, 0x86c31ff0, 0x8f34e174, 0x940ce1e8, + 0xf1e298fd, 0x14960d7c, 0x6fb8cb1d, 0x2b2f3bff, 0x207c1347, + 0x146ef8ff, 0x899a20b4, 0x7bd3e220, 0x7dec362b, 0x626bea27, + 0xa975044e, 0x4fb4cb67, 0x0f32b449, 0x1fc6703a, 0xc17a0920, + 0x9cd84a2b, 0x41f325b9 }, + { 0xce2843a4, 0x312ed513, 0x00728afc, 0xe748498e, 0x4d864ce5, + 0xa8ef2822, 0xa620083b, 0x34064704, 0x4bed338d, 0x5905e1d9, + 0x063e7b38, 0x2a578cb5, 0x289e7bb9, 0x98276d96, 0xf17b7341, + 0xdfe2dc47, 0x1dac8944, 0x5923521f, 0x23400aa7, 0x3db6d28d, + 0xa761ba43, 0xc647705e, 0x9bfd07dd, 0x8947ba6d, 0x242ca8fd, + 0x00f2e3ac, 0xeb8c3468, 0x49ef4670, 0xd9aa18fd, 0x7db3d37b, + 0xe58cea9e, 0x56b30fb6 }, + { 0xcd80a428, 0x07ecdcaa, 0x8732c891, 0x7af922dc, 0x3ada441f, + 0x20d88798, 0x924b008a, 0x3bed9a44, 0xb2e81c3a, 0x2123533c, + 0x65f807d3, 0xc34e4075, 0x1f2faecb, 0x0bfaefa5, 0xade8a88d, + 0x78b634a5, 0x94392a91, 0xc4e0b7f8, 0x90bb1cd8, 0x30922377, + 0xf87204ae, 0xdea9b4fa, 0x85d3cd83, 0x3edf81f5, 0xc6523a79, + 0x58f88c51, 0x17c0d969, 0xe472fb8b, 0xdccf7f07, 0x899081e5, + 0x58bdd146, 0x1353cc57 }, + { 0x39bf6e18, 0x28a56497, 0x649b89c7, 0x59e8b5a2, 0xdce8b8e7, + 0x8d9434a0, 0x2047040c, 0xd935bf51, 0x6a7b8e82, 0x2ab3a164, + 0x27f81294, 0xf1583ed6, 0x72d67297, 0x8416a7e0, 0xcd39e42b, + 0x49685d86, 0x958ddbad, 0x8a797fc7, 0x155ce6de, 0xa558f928, + 0xf8a36235, 0x75f4e570, 0x52877ae5, 0xbc69cfc0, 0xa6b16ebd, + 0x8f4193a9, 0xbb1cc1f1, 0x8d1df43c, 0x5a21e789, 0x723a830e, + 0xf451df58, 0x3ec2185d }, + { 0x1f0bc2d7, 0xb9d4c7d7, 0x6e51d412, 0x6982c6cc, 0xa09f80f6, + 0x92e02d93, 0x047ae09c, 0xb7dd2d25, 0x37f351f9, 0x3503149f, + 0xc77850be, 0x69d49ce1, 0x12f0d2c8, 0x60242acb, 0x7bc28b9d, + 0xba188c56, 0x06bc0550, 0x8e406121, 0x8d7d4329, 0xb0d84b1f, + 0xd38951e0, 0xb4a67ae7, 0x8bc97607, 0xb527c57b, 0x5497aa72, + 0xbc93c5f3, 0x39bdd666, 0x5f1de8cc, 0xe9d447a3, 0x3087dc5c, + 0xa211abe5, 0x89b356b6 }, + { 0xdfdcc837, 0xed6db0af, 0xa871b7a9, 0x0fb80baa, 0x1c1d4b72, + 0x413abfc9, 0xadac9e5c, 0xf5b56bf7, 0x8b8657a3, 0x5664a2da, + 0x0e41d94e, 0x11b04f72, 0x37433658, 0x63e11d26, 0xf426daea, + 0xee628ece, 0xcb162dc2, 0x011619c9, 0x87648643, 0x9cf5817f, + 0x5584bc86, 0xe1bb9702, 0x00bf7928, 0x2cc27cef, 0xdc60eee5, + 0x4ef3a80e, 0x87adc2f9, 0x7e1202be, 0x8a0d4f52, 0x656f18e0, + 0x57c5d126, 0x39c4f10d }, + { 0xe88aecd3, 0xb3a9b68c, 0xa518aa9d, 0x555b0918, 0x4bd4ee54, + 0xedc1cdad, 0x02068d84, 0x79b68b67, 0x811ac72d, 0x7dac80d0, + 0xa81a0a78, 0x6d1e6d35, 0x3bd16283, 0xc841e9ea, 0x894c4444, + 0xa7bc1775, 0xf1aa1202, 0xf2b63725, 0xc7d4c556, 0xbec7767e, + 0xd46ff51b, 0x2817ebb3, 0x73f7e339, 0xfde5be8d, 0x5aed24c4, + 0x44c6c977, 0xb6e579cf, 0x0b9a1707, 0x9069fbcc, 0xcff16478, + 0x49152b00, 0x414b542d }, + { 0x606e173b, 0x33c31e58, 0x90e6713a, 0x5b7f4e1b, 0xdebb20af, + 0x425fb512, 0x05120e70, 0xc788c617, 0x9013e4ec, 0x3ef05602, + 0x81c6e6d7, 0x9f9d35ac, 0x9450690a, 0xe131e88f, 0x44af082e, + 0x708f9b32, 0x1ba2aea9, 0xb2e4d66c, 0x740db29c, 0xaf1f4a6e, + 0xd1843007, 0x74ab9248, 0xed556a6c, 0x13338ef8, 0x270d17a6, + 0xf48e623e, 0x9608f5bf, 0x3c7362fa, 0x444e8515, 0x43977874, + 0xe00b8b2a, 0x52678d6a }, + { 0xdf36aeb4, 0x5dff1c59, 0xa92bc0ab, 0x52d6653c, 0x927a5f81, + 0x0e03f496, 0x2dfd491f, 0x8509d414, 0xa571f89b, 0x258c2c52, + 0x93334485, 0x2bd61804, 0x3f7d9e09, 0x1a33e94f, 0x2c1bf906, + 0xfab418d3, 0x5aa5695c, 0xf39c490e, 0xf6d2d7ff, 0x0e41196e, + 0x0f7948a9, 0x3ecd4075, 0xd3053b4f, 0x4b58f9b2, 0x5d9974c9, + 0xb8ee842a, 0xbf22f682, 0x23a59c1d, 0xc8efcea6, 0x045ac614, + 0xc10ceedd, 0x7040ba5b }, + { 0x515a1a96, 0x2c364f81, 0x184327e0, 0x31a63503, 0x1ad93d4f, + 0x0a096650, 0x273b6173, 0x9d7694f1, 0xd2cda9d2, 0x8886d876, + 0x2814c177, 0x1e01a742, 0x8667696b, 0x3492276b, 0x5b25f006, + 0x2fd4f0c6, 0xfb294c4a, 0x6527349f, 0xde1d336f, 0xc1fe0d8a, + 0xe7e3860e, 0xaf9a23e8, 0xb774c31e, 0x97d2b721, 0x4365784a, + 0xfac3e582, 0x70f4eaa3, 0xff2dff4e, 0xfe873248, 0x3d281e1a, + 0x0bd1c9c1, 0x9043a6d6 }, + { 0x766c7937, 0x1511a0fe, 0xabbc3be3, 0x1b2ded5c, 0xe00888ac, + 0x2ac160cc, 0x616200f3, 0x928754bd, 0x34a2ea06, 0xb801c83d, + 0x9cbe106f, 0x8ad7a03a, 0xcedfcd94, 0x996b0822, 0xe4069880, + 0xc3c3463a, 0xf597f663, 0xfb12ea4d, 0x40c92af9, 0x2c8d3834, + 0x4e8da154, 0x79bc85c6, 0xdb4e801a, 0x95771fa2, 0x1e3579b2, + 0x7bd2c138, 0xffaad078, 0xe45c75df, 0xb73eac46, 0xb0760a3c, + 0x3a125f35, 0x26362b48 }, + { 0xeefc3e89, 0x25c68d28, 0x69e9ee71, 0x2d0ee877, 0xaf5e4b75, + 0x8b07bb86, 0xcb86b333, 0xdb709072, 0xff552bac, 0xfd3d20ea, + 0x4c0da1e9, 0xa5eeb2b1, 0x44f97145, 0x391f688a, 0x1e06d485, + 0x21fbd310, 0xbea9cd49, 0x45e4f2a5, 0xa7bf21da, 0x7b60d464, + 0x054d5471, 0x193f88c8, 0xbee0f2e9, 0x5ace53d1, 0xc1439273, + 0x92c26563, 0x96c6b5ee, 0x9c86e0b2, 0x09ff59ba, 0x452fe231, + 0x555c935e, 0x2e952b20 }, + { 0xd75f886e, 0x2a846bca, 0xd43dfc58, 0xe68a5dbe, 0x007b1b86, + 0x103e45b6, 0x355ff2b5, 0x580e2ec9, 0xa263ecc9, 0xbc702f26, + 0x181e5e33, 0x2835b386, 0x6c122076, 0x025113ec, 0x7fbd856d, + 0xa5c26e3a, 0x9d6ebcb1, 0x8ef83fb3, 0xa44d2fa8, 0x7aaa53f2, + 0x53b1fa97, 0x7c14ef33, 0x17559a30, 0xff604a11, 0xb09377e0, + 0x2bcd96b0, 0xdb2f0273, 0xa5c14896, 0xeb53ef06, 0x1c0a84c9, + 0x30378e4b, 0x1236d017 }, + { 0xc084373b, 0xd7481c8f, 0x646097ae, 0x29ae4768, 0x613bc34b, + 0x1300dfa0, 0x934bc2b0, 0x3712714c, 0x0e2be7e2, 0x86524629, + 0xed010800, 0x554fbb9f, 0x42314576, 0xf0ec0b38, 0x330a3282, + 0x65baf594, 0x706ef817, 0x3bdde1a8, 0xba7530e9, 0x7d2c727d, + 0x74cc95cb, 0xbb0c5d66, 0x2438906d, 0xb3fcd365, 0xd14658f3, + 0x19881941, 0x6c97f0e9, 0xe616f555, 0x4b9ec7ea, 0x353c2d85, + 0x620cb56e, 0x02a48014 }, + { 0x506ccd38, 0x11d6d23d, 0x9059baa6, 0x229a1c54, 0x69d011c5, + 0x717c9c27, 0xd828937d, 0xe87e1b46, 0x83835083, 0xf5d63bbb, + 0xaadac258, 0xf0a7b427, 0x9f154d1f, 0x99ab26bd, 0x8ec955fd, + 0xdec0ffbf, 0x49fcb880, 0xee957c67, 0x1e0114de, 0x32395dee, + 0x369f46c7, 0x192a64b7, 0x91eb2599, 0x43044660, 0xa2e8c3da, + 0xbe2da887, 0xc3556d18, 0xa44e2c25, 0xb55f75f3, 0x31390414, + 0x8f217fe0, 0x1d8bde6f }, + { 0xa2028924, 0x03cd39f8, 0xb06ecb9f, 0x6e54f19c, 0xd6f05846, + 0x862bbcb7, 0x5a060776, 0xdbe06716, 0xb10fec10, 0x9397c97a, + 0x6f1bb65c, 0xf4213826, 0xa672ba38, 0x414deccb, 0xf88b05e6, + 0x594d4d43, 0xac94d4d1, 0x7993f57a, 0xbfb17638, 0x74fc2a6a, + 0xb6fc655a, 0xd8196b5b, 0xee8d2139, 0xdc375c84, 0x360d3a26, + 0xb9b00a02, 0xdeb93b87, 0xb36ed35c, 0xcc83209e, 0xf565b28b, + 0xc61013c1, 0x349c6943 }, + { 0x4de6c88a, 0xd1b39444, 0x4700207e, 0xd5c2c471, 0x21c2b780, + 0xb6f458a2, 0x0850993e, 0x749f7564, 0xbaef0c18, 0x400ba579, + 0x737c70f0, 0x2d742938, 0x21467ebf, 0xc5a8e2ec, 0x5337f453, + 0x243a666e, 0xed0bd50a, 0xc991f1c7, 0xf4bd1f91, 0x3a7f3e90, + 0x5f0e129b, 0x96089e8a, 0x07389635, 0xd0d3a177, 0x27182ac9, + 0x9cf842d5, 0x0817c5c2, 0x21195299, 0x87255769, 0xa32f327e, + 0x89c2d8fa, 0x056587ab }, + { 0x1ce4733d, 0x008562ed, 0x98e51444, 0x5faff7cb, 0xa9ab46b9, + 0x5f03021f, 0xb61a8c13, 0x89494c5e, 0x36b35976, 0x57c95036, + 0x2ac2d2f6, 0x6be84c8f, 0x9bd2703e, 0x0e5b34d8, 0x7e872abb, + 0xc4ad918f, 0xc4052ee1, 0xc2a89e9f, 0x3190b51e, 0xc2caee3f, + 0x6fff254f, 0x58fd1437, 0x883e0972, 0x6f3c0d68, 0x0fb15438, + 0x63d0a0e9, 0xf6caae00, 0xc438764b, 0x3f1d0f6c, 0x815f1565, + 0xb86cdbde, 0x1b87f2ed }, + { 0x2b0b15b1, 0x35792bbb, 0xce6ba779, 0xa3e4b5a7, 0xdd8f3779, + 0xfbacffd9, 0xc298d1ef, 0x005450bd, 0xc47031c6, 0x0e3f5556, + 0x95d68066, 0x0770f07a, 0x2d1052c2, 0xce3e84e0, 0x7aa8cc54, + 0xb050791e, 0xba3223a3, 0x4d621e73, 0x39632990, 0x87b9b94d, + 0x7eb8056d, 0x8df9cb47, 0xedfca0cc, 0xe2430de8, 0x9712a0ca, + 0x374bf416, 0x88848a99, 0xbe3f3c77, 0xc4a3e59e, 0xb22b87b1, + 0x3e95bc23, 0x8e0227c4 }, + { 0x3210964d, 0x000e22a8, 0xff056eeb, 0xdccd5df5, 0xdaf1ead7, + 0x02173a1f, 0x67cdcae3, 0xd02833e0, 0x8bdcc90c, 0x1cc574cb, + 0x3224b4f5, 0x86eca714, 0xbb3f8298, 0xd00e603a, 0x0c1a8deb, + 0xb98ece1b, 0x378c261d, 0x228a46e4, 0xa6165e5d, 0xc6f9dd0d, + 0x4b7ef0e2, 0xb3ae3899, 0xbda9f306, 0x3a3c16b3, 0x38a084db, + 0x5e9a26d3, 0x5394e950, 0x528e5993, 0x4ea206bc, 0x848ecb11, + 0x40545d6e, 0x14b15ab5 }, + { 0x664c59a2, 0x0f6d86c9, 0x60fd7aa5, 0x3dfe2be1, 0x9072cb8e, + 0x33f9b569, 0x8176a7e0, 0x5f2325d9, 0x4587080b, 0x79a0d4e7, + 0x0d5d4e05, 0xa4ee0def, 0xc87b28e1, 0xc0ad9ffa, 0x3f09b4ee, + 0xd6f18d2f, 0x292e9d87, 0xcc896ae7, 0x6094763c, 0xca88953d, + 0x18fbf9fa, 0xdbee97a8, 0x4b63d701, 0xdf20e0e9, 0x47ea722f, + 0xcbba6e30, 0x612b571f, 0xce57e1ca, 0x009a55f5, 0x1e16ac76, + 0xc4389e2e, 0x742bbed8 }, + { 0xc1dc2c73, 0x23ea86dc, 0xc1643abf, 0x4bbbfd5b, 0x24d8ca1f, + 0x07f8fa1f, 0x8cb5cac7, 0xde68a6e0, 0x54e66a7d, 0x7d54c64b, + 0xa9b7ad78, 0x789dba22, 0xe364ab94, 0x4d88d540, 0x1f72e011, + 0xc8c2e02d, 0x46e2a278, 0x4c826057, 0x4b187c7d, 0xe6c35bb3, + 0xeb8fe0c9, 0xed8b3dfe, 0x7d11e415, 0xb6bc34e8, 0xb865c7f9, + 0xb3908bbf, 0xe1ecc17c, 0x717d1ce6, 0xf7cdd69b, 0x151e3308, + 0xb5c94124, 0x97bd5a14 }, + { 0x81e82861, 0xe01c62fe, 0xdd42c40e, 0x703d4b6d, 0xe65e91e5, + 0x7e52e55b, 0x5abbbfdd, 0xb8b49374, 0xc72a45f4, 0xb4f15f52, + 0x550f29d8, 0xce8435a8, 0x582de75f, 0x9df76b9b, 0xa20c8b96, + 0x52e84c5f, 0x0a8a0af4, 0xaf77d2d1, 0xca6013c3, 0x0389bbd8, + 0x26f8305f, 0xb0d9b9ba, 0x0cec8b9a, 0xf053e848, 0xffabda18, + 0x4d63367a, 0xa6424c2a, 0x50f53be4, 0x864fba2e, 0xf892c58c, + 0x48cc5469, 0x317c6d31 }, + { 0x2cb7d42b, 0x0c3525b0, 0x310facae, 0x55240bc9, 0xff20408f, + 0x8d5d2022, 0xe0c10ea0, 0x6b01402f, 0x718eb23d, 0x7fbef68a, + 0x41252a19, 0xa0146b5a, 0x110e0d6e, 0x59afce48, 0x022de181, + 0xe9a1d27f, 0xdc3f49da, 0x6db96d16, 0xefbe4008, 0xfc1ae3f5, + 0xeccbc11c, 0xf9d70641, 0x525f8636, 0x49022279, 0xc2763c30, + 0x3769796a, 0x1d90630b, 0x9cc3483c, 0xee3d3f17, 0x451651f0, + 0x9da0b8fd, 0x6ae59739 }, + { 0xbff4d2ee, 0x57b13bc7, 0x30b173d8, 0x20754229, 0x0794936c, + 0xb6254bd5, 0x5efd55be, 0x1d5f232a, 0x4e0c3389, 0xc06f4a85, + 0x8e61f944, 0xcf2c5b59, 0xfd5f87b7, 0xc564861f, 0x5a2afa4c, + 0xee261fb1, 0x2d97a774, 0xb0ff7226, 0xd6cf007a, 0x1a89ae22, + 0xd346f214, 0x28880534, 0x97b6497e, 0x8fe73bff, 0xfa2afffc, + 0x8a8595b2, 0xf151a726, 0x9ef9cf3e, 0xe744b82b, 0xa84ee5f1, + 0xbc63fe72, 0x6649048d }, + { 0x1e8b760d, 0x91b7bb78, 0x25aadaa0, 0xd47b0bd8, 0xfab5226f, + 0x81493d9f, 0xbffc148e, 0x4a6dd226, 0xa29be3db, 0x5a032f8a, + 0x34b0ab0b, 0x318dbc70, 0x7d654868, 0xdcccbfb5, 0x9c581e46, + 0x8506ab37, 0x2830ece2, 0x09136a6e, 0xcf6c80c7, 0x48b79356, + 0xef6b1e86, 0xfa176377, 0x83f0f1c9, 0x2c9c1cc1, 0x16abeddd, + 0x96f0526d, 0xa93b0de4, 0x3e0e98e2, 0x0f13873a, 0x6f2d7ada, + 0xf3fa49ec, 0x4eb93b5c }, + { 0xe11fae32, 0xbd89f7e5, 0xc4023f51, 0xd13d74f5, 0x491c3f6f, + 0x1b0014df, 0x555279b7, 0x1d849a57, 0x05ba0068, 0xbb9e8897, + 0xc13ca2ca, 0x82222419, 0xfd33676f, 0xafbbb685, 0x75878a2a, + 0x931c3f52, 0xef3d5173, 0x12aeefef, 0xbd8a6878, 0x189a5cc8, + 0xd99f0c16, 0x82cffdb3, 0xa19d48b6, 0xbf565406, 0xe9c6c4e0, + 0x5605e223, 0x86804172, 0x53e781de, 0xc7001cc8, 0xcdf5c90b, + 0x7c043f68, 0x2b582d93 }, + { 0x81abc2ae, 0xa1165c82, 0xe2b69eca, 0xa73380f5, 0x07fff66f, + 0xc097b3d2, 0x54776506, 0x5d603826, 0xb57fa21c, 0xdcbac9f3, + 0xc98dbdd5, 0x78750db4, 0xd9eff32a, 0x85e21103, 0x2f11c41c, + 0xceed172c, 0x9e348c09, 0xa8e39264, 0x831eddfb, 0x71cb936b, + 0xf50864a3, 0x915c3d06, 0xe93acfcd, 0xfe8e33cd, 0xb3f2f7aa, + 0x4bee10d7, 0xeb7cee9a, 0xc1d8eb48, 0xfa574afd, 0x4fa49ce3, + 0x862db4c0, 0x78615109 }, + { 0x7ae72c21, 0x3fe3f480, 0xfd0f0da5, 0x631aa144, 0xf8c3a454, + 0xc76ee1e8, 0x51b4f1ab, 0x379ae094, 0xd7cdbb24, 0x2a3a4397, + 0x82bd5fcd, 0x7a14cffe, 0xf427ef5a, 0xbbe4ed12, 0x284d3ccf, + 0x9b0a43ee, 0x8eec6e1e, 0x57b78b93, 0x67b8e87b, 0x18d404e4, + 0x34374c20, 0x0c8adc05, 0x5428deb5, 0x64373605, 0xc3afa2cf, + 0xb4d80ec0, 0x3aa956f9, 0x6d51f93c, 0x84161c68, 0x9f9a28ab, + 0x6bc9c025, 0x540b6bb7 }, + { 0x321d315d, 0x04e1734c, 0xd86e05d0, 0x4ef56612, 0xbba8cd81, + 0xeafae145, 0xacdc789a, 0x1fb07a49, 0x5877570f, 0x6a21e9ad, + 0xb9bc53de, 0x2e4a837e, 0x1d6298eb, 0x436db293, 0xea362f45, + 0x43afbc78, 0xaabf6585, 0x2a973d97, 0x0c924d60, 0xdce7dabe, + 0x7cadf0e9, 0xf69d98f0, 0x75020538, 0xe0b505a1, 0x4461cd29, + 0x3db7d1a3, 0x5e20e818, 0xe1c28776, 0x52dd50f6, 0x2ca25867, + 0x92e0388c, 0x897cab14 }, + { 0x0d8bab8a, 0x59ed3813, 0xa438200a, 0xc11d364c, 0x40581415, + 0x0687bf2c, 0x7ac89674, 0x86ad0d3a, 0xb97411a0, 0x44928105, + 0xf383371c, 0x74984b11, 0x0d1a831e, 0x70d2ed84, 0x6c912fe0, + 0xd883628b, 0x14fa88d2, 0x44f8f7fb, 0xcf0ac93e, 0x564f2a4d, + 0xa6c24fa6, 0x82f629aa, 0xbf6cd949, 0xab906ba3, 0x20a5182d, + 0x2c822e67, 0x30eb93a5, 0x2ff47dac, 0xfff673aa, 0xdc62c4a4, + 0x476b0ec5, 0x64b00763 }, + { 0xb3c9a404, 0x1e3f533e, 0xb7ef9952, 0xb1db7f73, 0x6c253693, + 0xc7f13e29, 0x0738eed4, 0x7ce7f4c4, 0xce26cad0, 0xccfd3b33, + 0x01ec5cf1, 0xd8784935, 0xdc084e01, 0x3f8fc09d, 0xc39b5acf, + 0x217cab32, 0x9ef5551c, 0x42daf0bb, 0xe1217a95, 0xfbc76f56, + 0xc237002a, 0x80178b12, 0xb070a293, 0x0b52c39f, 0x576ca964, + 0xe3925153, 0x19d68e36, 0x25559424, 0x09e50e84, 0x291fb82c, + 0x6618ed8c, 0x7dd22ea6 }, + { 0x49cbb3bf, 0x7ffe844b, 0x5562fb25, 0xde0cc704, 0x9f5a845a, + 0x1e6ee537, 0xe51277fc, 0x956d7f26, 0x30635718, 0x2c75d4b9, + 0x96957f34, 0x39a14892, 0x82e5742b, 0x8cf4eb32, 0x83247b72, + 0x6b0d3ddd, 0x201a4237, 0x67a9f633, 0x1414a485, 0x416403c1, + 0xb6f6a916, 0x60afd447, 0xdac6f790, 0x95f94930, 0xbd3b9d82, + 0x685ff94b, 0x51cadf0f, 0x5c8f98fc, 0xb13b7489, 0x9559c88a, + 0x5f18fcc8, 0x31377c66 }, + { 0x7dcfb35f, 0x35c5de09, 0x01cc36f8, 0x2dccca9f, 0x7576cb63, + 0x7e93e85d, 0xf7b4b375, 0x0c2dd48a, 0xb09a19b5, 0x9d95cd4f, + 0x71bfe607, 0x752ed159, 0x2596dad2, 0x439880cf, 0x69e90a6f, + 0xe52efb53, 0x03d3e60a, 0x44097663, 0xa95070e0, 0xfcf364fa, + 0x05624dd2, 0xd8f993b6, 0x00d5e467, 0xb35a9824, 0x0c8f4524, + 0xe289d024, 0x648a0179, 0xef45423c, 0x587edabd, 0x3a5fd695, + 0xa11e5271, 0x3dacc50c }, + { 0x6499ae4c, 0xcb3e4f94, 0x7053c527, 0xa46dcbe1, 0xbe782e8a, + 0x807f5ce9, 0xd8481e45, 0xb6c64d28, 0xaa286fd0, 0xf35e4518, + 0xdf1cdb49, 0xf7b7b9ba, 0xaec23eaf, 0xf3fb6210, 0xb9bfd2fb, + 0x0a9ba385, 0x8807f3a0, 0xe51a0d53, 0xb17b2842, 0x7ab24404, + 0xf9dd9f0a, 0x6fd57687, 0xf3e9df64, 0xcd1efdb4, 0x60df194d, + 0x5dd2df7a, 0xe069df05, 0xbed3f2c3, 0x23248a31, 0x469b7561, + 0x694744f7, 0x866949e1 }, + { 0x3f4ab07a, 0x3a9a0da5, 0xf54a6fbf, 0x2cd6f333, 0xb23cf290, + 0x0c92e921, 0x848e3d58, 0xc9581c3e, 0xd3b218ab, 0x93af1fbd, + 0x066cb4d7, 0x38598ea1, 0x990c03a0, 0x5001394e, 0x7d0877b5, + 0x3b664b1e, 0xd74c7091, 0xd79db1bb, 0x4e2d5dd0, 0x852d4435, + 0x3329db82, 0x0d2b841b, 0x7b96d480, 0xfa844eb0, 0xc295dc46, + 0x37a50569, 0x94f7ec4e, 0xc2d38373, 0x5b083177, 0xdc3884ff, + 0x8b1fa598, 0x574352b8 }, + { 0x0d5d7ce9, 0xed2193f7, 0x0b487eaf, 0x3c19fd26, 0x7be65fd0, + 0x7c44ab59, 0x78270d56, 0xdd9da860, 0xbaa70198, 0x8a84ec00, + 0x285985df, 0x2ec27e49, 0xde2028d8, 0x996ccaf0, 0x61c2201d, + 0x4e7648c7, 0x091c19eb, 0xa96335bc, 0xf0d6782b, 0x253a3a69, + 0xd2946493, 0x3f204340, 0x099f6873, 0x444521a1, 0x6996011a, + 0x5fcbcc09, 0xf853a94e, 0x3884d5d8, 0xd3b6a3a1, 0x2418c624, + 0x06ae3c4f, 0x3e431af2 }, + { 0x83d381f1, 0xf967d939, 0xd0c033c3, 0x36501aae, 0x54410768, + 0xbf3af4d0, 0x5093a6d3, 0xa86d1598, 0xd92f2900, 0x43ae0741, + 0x36f0b755, 0xfeb2afa6, 0xaa456d6f, 0xd090a6a3, 0xaefdb646, + 0x336a4fda, 0x1a942f7d, 0xfd1bfe44, 0x851ee41e, 0x7fc2a3ed, + 0x11e935c5, 0x4f1c9686, 0x53bbb343, 0xcd577666, 0xad896c2a, + 0xf26931ba, 0x86bbfa41, 0x8a0fbbd1, 0xa203cef1, 0x1c3d7d82, + 0xe2664d35, 0x6dad3f15 }, + { 0x12ec35a1, 0xd1940b7d, 0xe7dfb128, 0x6219c5b6, 0xf13321d5, + 0x2cc278c6, 0x33c58eb6, 0x5e76904a, 0xd9903c43, 0x15090f55, + 0xc3d96a19, 0x061bc926, 0x8c0acba7, 0x974a9f03, 0x7198b21b, + 0x7a414021, 0xf8958c6f, 0xb069599d, 0xbebd0129, 0x517f2f1d, + 0xdf3a8dc3, 0x1109a613, 0x672375c5, 0x08e58448, 0x9383d2d3, + 0x56590ba4, 0x0bff837c, 0xfc3ee7c6, 0x27d2d55f, 0xc87a5390, + 0x5f517a3f, 0x2438e9d4 }, + { 0x8815af3c, 0xc4a45308, 0xf3c9bed5, 0xe55f1a32, 0x97b65ddf, + 0xaef1cdc9, 0x12e51eb5, 0x61c61d94, 0xe63f2490, 0xbd0dac54, + 0xd0b3e231, 0x6f14429c, 0xf1da6010, 0xf737c3c2, 0x6bbc4fb1, + 0x7150e04b, 0x1be281cb, 0x205b4c89, 0xd7701f5b, 0xf1b4633c, + 0x2a513490, 0x8b33ef46, 0x68f1f7f2, 0xddb47c73, 0xbd416b67, + 0xf4ada511, 0xff795bb3, 0x9d2a97cd, 0x96200e67, 0x00a8b7b2, + 0xafe30e01, 0x13f39011 }, + { 0x7bd0c827, 0x3dd296ef, 0x4a29ff46, 0x506110f3, 0x1c9a515a, + 0xf8793068, 0x268bca77, 0xde8d8045, 0x998045df, 0xcbb83024, + 0x68c0e584, 0x3f90d710, 0x263b6062, 0x2a838ca8, 0x535c5d0b, + 0x293bb5e7, 0x56415110, 0xceea99d5, 0x1bbda005, 0xfe311ad0, + 0xa4d8d018, 0x2497e0bf, 0x1cf2b866, 0x33dd77a0, 0xd8c4ba8b, + 0xbc075b73, 0x722b7bc9, 0x298466d4, 0xcbda1b0b, 0x17a7ce24, + 0x680703b6, 0x458d4b6b }, + { 0x4d54d8b2, 0x8a26a20e, 0x4d320a0d, 0x05a5696e, 0xf994f700, + 0x698b5858, 0x2f6549a8, 0x7a4adc3c, 0x3694d00d, 0x1812e819, + 0x730402bd, 0x46b9b000, 0xa1b36410, 0xe10a1449, 0x99230220, + 0xeae95ea5, 0x1b4820c3, 0x3efc2e9b, 0x85c9eb8a, 0xfe5b5cb5, + 0x97847064, 0x21ae0319, 0x8f27d49f, 0x68ef0b70, 0x2f72556b, + 0x3259ef18, 0x624db01a, 0x00ae0457, 0x5668f95c, 0x628e3b06, + 0xb6fbbf91, 0x5f13f5fa }, + { 0x3a9b0dc6, 0x7c6ed9ae, 0x6f883ec8, 0xaea1bde9, 0xea8b3677, + 0xea66bf88, 0x9a66e3ab, 0xdefa6abc, 0x68217ffd, 0xc4d3317b, + 0x290df05c, 0xf741c8f2, 0x7d11674e, 0x1f0fdf17, 0xc35989ca, + 0xfdf0ece7, 0x6b9c482d, 0x0eed92df, 0x55bf1ca7, 0x73713e66, + 0x25cec99c, 0x90acb290, 0xe803e69c, 0x37c9e3a2, 0x17713a1a, + 0x7c0a3c53, 0x6f5a174d, 0x350dc565, 0x05f802f6, 0x11625a44, + 0xa37ba4a2, 0x2196495d }, + { 0x13142680, 0x00cb2fd3, 0x65d14cf4, 0xab9e91d7, 0xdfe2669e, + 0xc6a0ceab, 0x0ae22bc5, 0xbeefce58, 0xcb6ec250, 0x3c2b7986, + 0xd738f1ff, 0x84adb1a2, 0x516ec8ec, 0x9709bc28, 0x8e8f7db5, + 0xf3693129, 0x95b197f9, 0xc48efc6b, 0x9aaaa404, 0x9ff10952, + 0x144154b0, 0x2c3c8cbd, 0x427f3435, 0x33ef7bc3, 0xd21897c1, + 0x04a17940, 0x6ce548a0, 0x5aa0c47d, 0x3d56fa62, 0x2971cea7, + 0x04475f08, 0x93ad0eb0 }, + { 0x988a9963, 0x7a0b6967, 0x6515e8dd, 0x61e477f7, 0x3b6b50f2, + 0x6274e386, 0xd33922de, 0x63a9b8d5, 0x687a5b3d, 0x3c38d3fb, + 0x1302e323, 0x18f6f09c, 0xe02fcccf, 0x254c05c3, 0x26e662f7, + 0xc04ed0b7, 0x143fe079, 0x1d5646b8, 0xc9016c8c, 0xef8a9448, + 0xf823d797, 0xe5674c4b, 0xbccde451, 0x0586f72f, 0x4417eade, + 0xc5fc88d5, 0x576e588d, 0x2b952209, 0x5844d1f9, 0x4408dd42, + 0xea41c034, 0x73f8c3f0 }, + { 0x5df763dd, 0x89534fc8, 0x3ac71836, 0x3b1427f3, 0x6e8f15a0, + 0x0db5be17, 0xcb20888e, 0x1d390944, 0x857caea6, 0x7804c9ad, + 0x519f7bf3, 0xaa584428, 0x293aa8cf, 0x626eecf1, 0xea36a015, + 0x749e0d98, 0x3321edcd, 0xefff6dae, 0x28b791cc, 0x963deea6, + 0x2d16e361, 0xa14e0552, 0xb15ae206, 0xa2e058fc, 0xfca325e4, + 0x0f268745, 0x21341a8a, 0x7cf9d407, 0x7caa51b8, 0xdfed25d9, + 0xadbedd75, 0x0108ae39 }, + { 0xa9e88f63, 0x54d178f3, 0xab0c7325, 0xaa05b11e, 0xe261d8a6, + 0x773a53e6, 0x8d0b91c8, 0x24db7dae, 0xe9bb004d, 0xde10b073, + 0x54e3090b, 0xfc8befe7, 0x0cc69c89, 0x16af0599, 0x9d59511a, + 0xddc83803, 0x46c5dafc, 0xc3f65b99, 0x1ee0a599, 0xfbbe4be8, + 0xfb3a9b17, 0x88891e36, 0x445dad00, 0x0c9aad75, 0xd5097e1f, + 0xdffc46ab, 0xac85a4e1, 0x8848089b, 0xa0c45233, 0x348bb42f, + 0xeb13c1df, 0x807c06d8 }, + { 0x98ee0ef6, 0x00a969ec, 0x8bb7b7af, 0xba9d5483, 0xa02f8fdb, + 0x24484c92, 0x8b70557c, 0x7bdb201a, 0x60ad1af2, 0xe59343e4, + 0x998c95fb, 0x53a9a942, 0xda861d3b, 0x974db3de, 0xed399c0e, + 0xce1525c9, 0xf72109bd, 0x89b56881, 0x998211a4, 0x08ff7d15, + 0xef0f275a, 0x5df76b3a, 0xfa2f358b, 0x93f180f7, 0xc39b0634, + 0xaac4ffcf, 0x17583b53, 0x2692c626, 0xb55399fc, 0xb2fdfa36, + 0x99607a61, 0x16424c6c }, + { 0xdd2744a9, 0x5dd65c55, 0xfe3af418, 0x2544c1c2, 0xefe8b089, + 0x32c82e99, 0xa9df691a, 0x30b7ab25, 0x9be99674, 0x98384550, + 0xcaf2d122, 0xbcecd258, 0xbcc77272, 0x88ae4098, 0x4b8efa0c, + 0xd4396141, 0xed64d12c, 0x44ff67b9, 0x2e7f3404, 0xa9e655e4, + 0x45b0e9eb, 0x3d16fc45, 0xf03ded28, 0x474a3e14, 0xacccb85c, + 0xa3c9adff, 0x7253a51b, 0x3dfe6bc1, 0xfb5831b1, 0xdddaf4b9, + 0xa4f4478a, 0x5544e602 }, + { 0xbaa80b4f, 0x897c5313, 0x63bdc8ef, 0x0122716f, 0x7b42c5a8, + 0xae2742db, 0x0883308c, 0xe9d9e1e9, 0x2d341ab1, 0x352c8c3f, + 0xed945870, 0x163d0500, 0xc290d9d8, 0x8349dd73, 0x1f6c7d29, + 0x2053c5e0, 0xcb42033c, 0x83107446, 0x09d09af1, 0x76c88bd2, + 0xb2794681, 0xd0f70e6e, 0x19b1b540, 0x720b59de, 0x22994b43, + 0x80b7ecdc, 0x2dec53cf, 0xc1a4cdce, 0x1ed60f42, 0xdd7d3edd, + 0xe241d261, 0x5735995c }, + { 0xa0237056, 0xdc4ba3fb, 0x33ab3388, 0x6856c164, 0x271ec612, + 0xc01eebbd, 0xe3031bec, 0xabdeb033, 0x6118a1f5, 0x4eee4419, + 0x5b600f33, 0xec497421, 0x08868773, 0x1b7185cf, 0x7c1b7dfd, + 0x7b0c46cd, 0x4a4c5e89, 0xd143b2da, 0xbb1ff94d, 0xdb9a5984, + 0xc9cf3465, 0xac3904e4, 0xeace64c9, 0xf8729bc0, 0x768ad99a, + 0x5cc22821, 0x8a9540c2, 0xbbd3b081, 0x049a6917, 0xe468ed5f, + 0x3ec45ef0, 0x885486df }, + { 0x4bdff464, 0x6a942c93, 0x25a7b451, 0x3db2719f, 0x325be324, + 0xccb0070b, 0x19fe3339, 0x2055a31b, 0x241ee8ff, 0xaca69ae8, + 0x55ef8def, 0x7607dd08, 0x1a1b73c6, 0x9e24960f, 0x71d36810, + 0xbcb0e8a2, 0x6885e6b9, 0x29e11aa2, 0x185eae19, 0x98b5d0ab, + 0x0f81f91c, 0x1a0b96e4, 0x994fc503, 0x4d0e8bcf, 0xf119d6e0, + 0x33d81697, 0xaaa4ce0c, 0x29083287, 0xc91ff9d7, 0xc5dd4d3e, + 0xd4ab962d, 0x31cecfe8 }, + { 0xfc8b21e8, 0x437bfd9a, 0xb19436df, 0xe5dd32b3, 0x921c36a0, + 0xfe5902d4, 0xa3d0fa90, 0x8e9de84d, 0x5bb523bd, 0x9663e6ad, + 0xaecd6975, 0x9800a23f, 0xb4fbb59c, 0x1009c0d9, 0xc9d20ff1, + 0x839aa7bd, 0xecd6fa3d, 0xf502f66d, 0xc5516ca9, 0x480ed4fb, + 0x6c742ac4, 0x65ffa5f6, 0xff3252f8, 0x2b7c7945, 0x75d9cb3d, + 0x72fefc05, 0xd6d6f1d2, 0x11b0863b, 0x9a6a4ec3, 0x5d8f3cf0, + 0xda2547b3, 0x6961b46a }, + { 0xcb35e2ac, 0xd07b587e, 0x57af14d9, 0x1ed5546b, 0xdb28a04c, + 0xeca17a5b, 0x709d54f0, 0xa1f91d44, 0x9c6f400e, 0xa6e719fd, + 0xfb8ce190, 0x4e4b88ed, 0x246e3fd2, 0xf9781edd, 0xb655af5d, + 0xd67120e6, 0x93413ca7, 0xda782d1d, 0x9707fa21, 0x697e20a2, + 0x54e84123, 0x1eb51f32, 0x36051f9f, 0x2e254d9e, 0x73ce5be9, + 0xddaec42b, 0xcd3f794f, 0x89a9a32e, 0x0781aad9, 0x1964e22f, + 0x53755212, 0x6a63a90c }, + { 0x3d7acbbb, 0x76554e00, 0xb74f6108, 0x2c01668a, 0x388c519b, + 0xe4a29672, 0x3eb94d4f, 0x01667714, 0x0cd6d2f6, 0x086a3cdf, + 0x7b370f7f, 0xf8658021, 0x5a4d3e7c, 0x658880c1, 0x5ba3f4a1, + 0xd6ed5816, 0x5ca471dd, 0xabcc7813, 0xe844a576, 0x809bf074, + 0x6ea502ea, 0xa53a81b3, 0x0e021ed3, 0xc20b9307, 0x8617f165, + 0x8c27f892, 0x8235cd0b, 0xa5476446, 0x82552961, 0xffc89ffd, + 0xd151d90e, 0x51ed4a22 }, + { 0x449701b4, 0x37d6963a, 0xbb27caf2, 0xea8d91a3, 0xb572965f, + 0x3ef9be15, 0xdb50bf7d, 0x75a7a055, 0xce643b9b, 0xfd67480e, + 0x6ceb5d5e, 0xf2a60d2d, 0x5ed7c897, 0x68fc320c, 0x28ce685f, + 0x41c53cf6, 0x7106615e, 0x0e29711f, 0x23500ecc, 0x7a872138, + 0x6c29fe48, 0xaf0a9260, 0xe1ef9712, 0x93df3f2a, 0xd2d169bf, + 0x0d5f6fb1, 0x74a9793c, 0xeb7afe26, 0xe9f49256, 0x4173d94a, + 0x2b8b5ce5, 0x2d6951bc }, + { 0x904e222e, 0xdd007d9f, 0x86f4e109, 0x333f248f, 0x8f429eee, + 0xd4994e8b, 0xcfc77518, 0x29573415, 0x0b0f42f1, 0x6e7fea3a, + 0xc2743519, 0xc795cb7d, 0x711e71a0, 0x820a8f66, 0x2b874f55, + 0x83d95d9c, 0xe70e1627, 0xd4b64d78, 0x8b92a742, 0x924353f5, + 0x447b5e6d, 0x322048b1, 0xbcf931a0, 0x0bad730c, 0xa7af2268, + 0x75c4d089, 0xb83b93f9, 0x464904c1, 0x165b3aee, 0xa24eba02, + 0xe08cc5f0, 0x65c48e78 }, + { 0xde222c22, 0x1a1c73ce, 0xfcea23b4, 0x5683d8cd, 0xb2143b06, + 0x0301cb14, 0x59fcec77, 0x284adf8f, 0x31204cef, 0xfb1c581c, + 0x94735107, 0xf54d3eee, 0x4d3188c0, 0xdbf67f0b, 0x10f18d12, + 0x76a3f2d1, 0x07d3e013, 0x3809fa28, 0x25e7ece0, 0xf06f0a46, + 0xb2895d2e, 0xd82867ed, 0x08b0553a, 0xe106f489, 0xef245445, + 0xe2280fa6, 0xa8d9a3cb, 0x402d5785, 0xd438ba2d, 0xf63dd9ff, + 0x7a6b226f, 0x36b5cd2c }, + { 0x545679a7, 0x87ff4e20, 0x4520c750, 0x64d80b41, 0x9b459cd8, + 0x90a357fa, 0xc85af1a3, 0xa19eaf39, 0x8d935a5e, 0x0d475d79, + 0x781a678a, 0x74501983, 0x0cc2e810, 0x74839779, 0x2f412244, + 0xc6a21d11, 0x36a51a37, 0x8d0e85f9, 0xeaa74df8, 0xff50151e, + 0x93cf99c4, 0x14e182a7, 0x376a9ab6, 0x45593df1, 0x522389ff, + 0x18f73caf, 0xf7445e8a, 0xd27cc960, 0x39a51dc8, 0x0692f4c5, + 0xdb39bfd8, 0x08d7c144 }, + { 0x3ecca773, 0x809c0d96, 0xd48c2156, 0x87ea9192, 0xdb6bd641, + 0xf0eccd74, 0x2a678cdf, 0x77312374, 0xd1587b7e, 0x7a966d8b, + 0x6130a4c6, 0xf3c1a101, 0x5fce17bd, 0x7cc6e838, 0xa8de7aa4, + 0x95e95bb8, 0x898308e3, 0x3fe1e8b5, 0xe347694a, 0x0197243e, + 0xbb0cd2bf, 0xf3fe9c42, 0x0f9b2b49, 0xb5905264, 0xc7367d1f, + 0x4c385e8b, 0xb5ee147b, 0x1d3050ae, 0x04004ad9, 0x8e2c3879, + 0xbab70202, 0x5f2aa8ee }, + { 0x1266524b, 0xe208d464, 0xd0a19f66, 0xb7bf3880, 0xda106ebf, + 0xa5aa685e, 0xe642dd46, 0x0a69e8d3, 0xc682e4d6, 0xef349c61, + 0x0fcb534c, 0x26f6ee3b, 0x05eb67b8, 0x7daba127, 0x18be05f6, + 0x2babb27e, 0x8e2d85d1, 0x959afcba, 0xe2d9d386, 0xedcf2d1a, + 0x1ea6f06e, 0x59dc52e6, 0x866e5ae8, 0xc28278b4, 0x02bcd3c7, + 0xd9ff0340, 0x784be82f, 0xe884ac76, 0x83c9f224, 0xa3164980, + 0xb46ff949, 0x62501a98 }, + { 0xad264086, 0x563f7d9a, 0xa5e0e4bd, 0xca6a33db, 0x8c8d3d67, + 0xe8253002, 0x46e64b19, 0xa288dac8, 0x20aa4536, 0xfa3c9197, + 0xed553eac, 0x8130c9b0, 0x2ea8abd3, 0x622806e0, 0xceccfe77, + 0x52fbf54d, 0x4f0d1b70, 0xbd9a8e31, 0xd59b1741, 0x519d2133, + 0x9a6fea8a, 0xfd74101c, 0xb5c4eb10, 0xd1acf7a0, 0x91f9da5e, + 0x78499b73, 0xc0dea586, 0xabaa4c49, 0xa1f3531a, 0xcc9c5f73, + 0xfd3fc665, 0x497b15fe }, + { 0xf45568e9, 0x8a56cbaa, 0xc7192a6f, 0xf491a0fe, 0x9ab2539a, + 0xdbb03dd3, 0x4ac37da9, 0xc86522f8, 0x02a0f5b4, 0x8c8cdba2, + 0xa29c539f, 0x8109fc75, 0xca90f02e, 0x9cd06d31, 0x3e216dbf, + 0x8f31f044, 0xba3ebd91, 0x99aa68ac, 0x42c007f4, 0x2a80d0d2, + 0x86a9b7ce, 0xdd8dffbf, 0xd6308edc, 0x405d3e84, 0x068012ca, + 0xdafa33fe, 0xedea1071, 0xc2eebd13, 0x2ff637e6, 0xb7ae7e5c, + 0x9e514cb7, 0x18d46a6c }, + { 0xa78b7802, 0x868cbb22, 0x497cbaf4, 0x0745ddb2, 0x42ae8add, + 0xc4eb2f3e, 0xb4ceb4e4, 0xac0abcda, 0xa325fd40, 0x2e0d8325, + 0x13ac7345, 0x6cfe0571, 0xb14171b9, 0x7407a788, 0x6da7a52b, + 0x70eb0603, 0xd85176ac, 0xab0b36f9, 0x7c2954f3, 0x14109d29, + 0xdcd705ad, 0x370de9c8, 0x7bb5e751, 0x3f0db5cd, 0xa06e708c, + 0x45f93d41, 0x7e93050d, 0x10d54f8a, 0x5a38fef9, 0x69e6f8e4, + 0xd3f62e40, 0x55044601 }, + { 0x06cb9cc9, 0xd1c5c910, 0x41d00014, 0x542074d7, 0x11236fb8, + 0x7cd8663e, 0x29ad5f82, 0x39721ffe, 0x2951fc83, 0x1d21fbfa, + 0x400d144f, 0x1cde06e7, 0x91792e6b, 0x9042596b, 0x29ad5166, + 0x3365c8e5, 0x9aeefe98, 0xe2220e85, 0x70c2aee3, 0xbcb53189, + 0x9ff100bc, 0x477ca3db, 0xf532973f, 0x27074176, 0x9a2bd01b, + 0xa12118ac, 0x3dd79f93, 0xf3425209, 0xc6f5d7db, 0x563a8ff7, + 0xd7b0ec4f, 0x0da313fc }, + { 0x15aa2557, 0x37125a8c, 0x00893e9c, 0xca21d70c, 0x67b8a823, + 0x48713994, 0x7cb0042a, 0x0d3e9a74, 0xc9e2ce18, 0x2d2bf4ff, + 0x049aeac2, 0xd5531a0d, 0xf03d0660, 0x4d29a616, 0x1f1b7f00, + 0x473d50d6, 0xca3de50c, 0x3af0ecbb, 0x09c28f27, 0xe2959bea, + 0xf8704664, 0x6d7c2ea0, 0x731083ef, 0xadfae4e1, 0x941c2554, + 0x50940c26, 0xa1162d03, 0x44167410, 0x1e82290e, 0x620230d8, + 0xdb414acc, 0x63630be8 }, + { 0x8a7d2e41, 0xbf8d5222, 0xeb62f879, 0x49e75823, 0x6c402d89, + 0x1b4d33dd, 0xde2c59ad, 0x883e04d6, 0x49b9dc38, 0xbf3f38f4, + 0xb4b70c4c, 0x9d997d18, 0x13cea045, 0x1f69b20c, 0x58e2606d, + 0xca3d7025, 0x261d1b79, 0x3d4fd977, 0x5a1436fa, 0x56aeafa8, + 0xbb443c07, 0x369b3e98, 0xe558f6be, 0xfce5186c, 0xf8ac8f89, + 0xeb0cd478, 0xd5e5aa72, 0x68074f37, 0x68544eb0, 0x295845c0, + 0xf16688ed, 0x306a9871 }, + { 0x634ec136, 0xbc451e9d, 0x0e6f658f, 0x1edf27ca, 0xc0db4120, + 0xa9be0152, 0xc5bfee67, 0x87b6ef20, 0x9a2d6023, 0x35283238, + 0xc7afb899, 0x60e564d8, 0x0ac9c2de, 0x4af22bc0, 0x82a9d22b, + 0x28e6f631, 0xf532701b, 0xc075c701, 0x82075f91, 0xf6d418f8, + 0x1beaa511, 0xf9fa628d, 0x6e72a13d, 0x551e7a17, 0x77f4c01c, + 0x9306215b, 0x93c9d588, 0x71aba731, 0x58e57cd4, 0x6443ebe0, + 0xe8103e37, 0x2833ac41 }, + { 0x8da5ec5c, 0x7e564b86, 0x1c08db24, 0xac3d9da8, 0x8c57a728, + 0x9d7c1f0b, 0x9d343dc2, 0x3512afe7, 0xfdc60339, 0xb438e4cf, + 0xdcfa1941, 0x7d5a2700, 0x27320449, 0xd5f323f8, 0x1393c6e6, + 0x1b87a58e, 0x04baa431, 0xecb68bd1, 0x4722b4d7, 0xc09c1c5a, + 0x206b5faa, 0xf42faa97, 0x9976327e, 0xe1dcbcd6, 0x087787d9, + 0x655ba9e4, 0xde5c0191, 0xbd59c757, 0x0bcf3538, 0x673020ed, + 0xa49d6303, 0x120cd454 }, + { 0xcab0f9ee, 0xebfdb8f4, 0x2cce58ee, 0xbc003ef0, 0x5a8d0665, + 0x9b6a6841, 0x9b957774, 0x642ed3a6, 0x4721ab5c, 0x3de487f0, + 0x21a4f0d3, 0xef2ff380, 0x29dbddcd, 0xbd16f558, 0x0e93dff2, + 0x2ef05b4b, 0x0bc9aec1, 0xde1faa12, 0xd467fa92, 0x66dae2c2, + 0x5eb33e34, 0x758daf64, 0x8f0103cb, 0xa67ad9f6, 0x9be02430, + 0x151f693a, 0xeb4054bc, 0xd5698496, 0x7019336e, 0x8ef1677e, + 0x7fdeea3e, 0x021cfd16 }, + { 0xdf5c36f3, 0x5c73715f, 0xd64ad254, 0x703bde37, 0xf2cf7713, + 0x55368d10, 0x0f3993c8, 0x1e5ec7b7, 0x304ae4ca, 0xfdb16776, + 0x3d3bb18b, 0x0d8f717e, 0x66343d5a, 0x5267073f, 0x156008b5, + 0xfaeb52ef, 0x224a470f, 0xb97ad5f9, 0xed2ab51a, 0xaf86e391, + 0x9974302c, 0xdc0c7e57, 0xfd0ae28a, 0xc88fa817, 0xbf8ed59c, + 0x807c22df, 0xeb128bb6, 0x5dedc231, 0xa20595a3, 0x71edcd9c, + 0xc73cf78e, 0x07265b46 }, + { 0xbd66232f, 0x73dd99f0, 0xc4027716, 0xc59aaf89, 0x5b860fc4, + 0xaf826dfa, 0x7a943f3b, 0x239ea8aa, 0x523c428d, 0x0e0e1b1a, + 0x6973b95a, 0x55ea0e3a, 0x2557753b, 0xea399caa, 0x06957b1f, + 0xf8adf72f, 0x3bd34302, 0x0389f341, 0xf8a43a97, 0x333f27d0, + 0xadaf796f, 0xcd9c0c08, 0x49c12aa2, 0x6dcca49b, 0x7a0ac6e9, + 0xdd88deee, 0x0644080e, 0x8f47575d, 0x0cc2f4bd, 0x6e9d667d, + 0x31d1496c, 0x36c5754b }, + { 0xf323d84b, 0x9120046e, 0x7e789c4f, 0xa6991122, 0x921b8055, + 0x4b0eaf4e, 0x8079974e, 0x6339844a, 0x740f8c79, 0xc905466a, + 0xcd6def49, 0x1c18d0f7, 0x4b23e4ba, 0x5297da6b, 0xc41800c5, + 0x1c09dff3, 0x37ef6777, 0x6c49075b, 0x50513ded, 0xa94c3a40, + 0x6b0b1705, 0x3d6742e9, 0xc48af5ae, 0xc0784494, 0xc95822de, + 0x40c01532, 0xc164d94f, 0xa2ddade5, 0xa2975eb5, 0xfc8a8ac9, + 0x1946944e, 0x06fbf861 }, + { 0x3f45aa97, 0x2d65338e, 0x1d040feb, 0xd83b58c8, 0x0fdef8b9, + 0x05fef59b, 0xe4d7417c, 0x7beb071a, 0xb30a1a23, 0x982b61f5, + 0xfb65bd03, 0x4c5f2a2a, 0x5cbf6bf3, 0xe40abc9d, 0xf06612a5, + 0x422c326d, 0x9571ae28, 0xc921e69d, 0x23d3434e, 0x7c88b10b, + 0x9da07933, 0x96d2e957, 0x3619cf4d, 0x833d46a1, 0xd95eefa1, + 0xd9d19653, 0xa03e8f0e, 0x2a7d8411, 0x04bb5ab1, 0x5e642953, + 0x1f0fa9ea, 0x5e9ca0fd }, + { 0x197c5dc4, 0x5bd54571, 0xe78a95a2, 0xe2da40bf, 0xffdb0eb2, + 0x65fb9efc, 0x0d17467c, 0xe952dc2c, 0xc758c6a3, 0xc1fc9c7b, + 0xd4034a9a, 0xfc79562c, 0x61f64b56, 0x26e36fbe, 0x1e84728b, + 0x6adc4b9e, 0xa8f9ac8a, 0x7f165fd3, 0x03e3e013, 0x7bc93a45, + 0x656478e3, 0xeacc5513, 0x064ddc77, 0xd3391717, 0x76936914, + 0x75b318dc, 0x362424a6, 0x69b1f1c7, 0x49955f34, 0x8cc2045b, + 0xc6836af8, 0x940622b3 }, + { 0x0d997973, 0x4710ccb7, 0xd3f8f115, 0x3b29625d, 0x5b97abd5, + 0x8cf0c4d5, 0x673e14a5, 0xc6321e0a, 0x3d262246, 0x0541af9d, + 0x6fc83b11, 0xde6d8754, 0xf01652a4, 0x47e97da8, 0xad9802b6, + 0x0f82b3a6, 0xae9c44b2, 0x69aa4075, 0xced2bf77, 0xaf3f5de2, + 0x497a40da, 0x1ef1ea8a, 0x3c23ba9c, 0x2e0f8608, 0xf190a2c8, + 0xd8a998a4, 0xcfde3368, 0xe2b49c8c, 0xbde6bd71, 0xb9f49824, + 0x785bedb6, 0x80bb1664 }, + { 0xfd145cb5, 0x05e575fe, 0xac5e6883, 0x155ee561, 0x8793b273, + 0x461e70cf, 0x133b2338, 0x9f1553de, 0xa2a7ba07, 0x2fb9e0c3, + 0x3e7086fa, 0xc3bfd6a8, 0x8bb4cb93, 0xb6ba8500, 0x76f82dbd, + 0x0b66d789, 0x54eb49ff, 0x7d5a6ff6, 0x1f20b322, 0xcd65d237, + 0x54e29cdc, 0x79ea49c2, 0xcb118ff9, 0x64975963, 0xcc58000b, + 0x969598dd, 0x110c779c, 0x95107918, 0x63b85a35, 0xedfc1548, + 0x41212350, 0x077ba5ea }, + { 0xcdd86f61, 0x0b3a38d3, 0x0502a0ab, 0x43121445, 0x806d0272, + 0x1912edc5, 0x8a32f10f, 0x01dc1f98, 0x0e80c760, 0xbb1d31d1, + 0xf464e8b3, 0xd46ec7e5, 0x9abf49ee, 0xd569af36, 0x2cdade77, + 0x9d286ea7, 0x45ad5920, 0x2be7020d, 0x6299ae7f, 0xabe5236e, + 0xd3f55c07, 0xc93179bd, 0x52350e80, 0x8138995a, 0xaff07586, + 0x0901265c, 0xf4739653, 0x5b3c81b2, 0x9bc77d21, 0xbaf7581d, + 0x4591a2e2, 0x6b2006df }, + { 0x965b1bc1, 0xb2fe50a8, 0x962bb4fd, 0x931f536a, 0x000e7f99, + 0xd5718d33, 0x53d5125e, 0x84728f25, 0xd2125caf, 0x4f8a6184, + 0x357f679e, 0x54f1a701, 0x1531c05a, 0x70a9f40c, 0x6fa8b775, + 0x10d0cb97, 0x9dc12ce9, 0xb476f41e, 0x2755f894, 0x5c8d7a75, + 0x625741a4, 0xd6c12e10, 0xc917b16c, 0x262a6fb8, 0x38d6b0a0, + 0x24d116e6, 0x32c38e83, 0x849540c0, 0x66868afc, 0x855b911c, + 0xbd26b550, 0x53217ea6 }, + { 0x259f52b4, 0xfc840473, 0xe621146c, 0x968da9cb, 0xcacbd26e, + 0x964eb85e, 0xe4a54344, 0xab7daa2d, 0x381a4ff7, 0x6dc3b848, + 0x41c815ef, 0xa07a96b3, 0xc3d4b1e1, 0xc4fae9e8, 0x42ce9ea8, + 0x0f938d1e, 0x35cc052f, 0xa727dacc, 0xe9a06f07, 0xc81e01c9, + 0x4a6d65a1, 0xa9e08dcb, 0x6044a9a6, 0xf8e2d173, 0xf2bd295b, + 0x99893dd0, 0xf9781b12, 0xa08d3379, 0x61830ac2, 0x64bd6001, + 0xd9adbeef, 0x0386931e }, + { 0xd09885a5, 0xd0d7abb3, 0xe355bb07, 0xed9d2b67, 0x536ebaed, + 0x3bc238cf, 0x699ce4d6, 0x61ca2e78, 0x111594cd, 0x354ff447, + 0x03316ad2, 0x55cbe709, 0x49fff5c4, 0x418679fd, 0x0f9c6c40, + 0x75bacd75, 0x2972721a, 0x677edc88, 0xe5ef502f, 0x82596887, + 0xbf320e0e, 0x459e9367, 0x8bbdccb2, 0x81ce36ef, 0xb766863d, + 0x1ba097fc, 0xd58c6db8, 0xcd3a21d6, 0xb4a8748b, 0x0e4967cd, + 0x15041c20, 0x2caaf749 }, + { 0x6ed20424, 0x44f98006, 0x22471545, 0xb3e4ea23, 0x781a8c86, + 0x268ed1a5, 0x7ae5b70b, 0x48d0ab75, 0x356d3982, 0x6ca8b320, + 0x2df31fa4, 0x9ce8e681, 0xd925dcf2, 0xb909d232, 0xf56723de, + 0x302c8f78, 0xabac96f9, 0x11725d69, 0x57d1a170, 0x656a47ca, + 0xc18a2be7, 0x6bb5d511, 0xad50d9d9, 0xb56e45f1, 0x70b05518, + 0x36e886e2, 0x09d8ff91, 0xc7c71f3d, 0x9350361e, 0x65a1bbe2, + 0x45fe3bd8, 0x86d7f532 }, + { 0xb0bf719a, 0x99f16eb6, 0x8bc3d913, 0xb6975098, 0x26cd01b4, + 0xfae50e52, 0x90898d1c, 0xd3e3ac54, 0x887ec666, 0x4da3b9db, + 0xfbea45b8, 0x58300644, 0x8355b058, 0x369f3bd9, 0x579bcc13, + 0x0fb239a8, 0x6e2bd811, 0x4f5b4539, 0x24198fd2, 0x007f3baf, + 0x8837d51d, 0x68a676db, 0xeae75b16, 0x68eeea62, 0x3db6083c, + 0x5ffe5f94, 0x7d836c5a, 0x52c94d0f, 0xcbc1ff85, 0x5a4c3c6f, + 0x86c0b4dd, 0x682a55e3 }, + { 0x587495aa, 0xc8f235a4, 0x34c7245d, 0x2276026c, 0xb75a46e3, + 0xd6ae0cc5, 0xecc3e5e7, 0x890d3965, 0x14296629, 0x1b13342f, + 0x8a877227, 0xc89927e6, 0x2324a68b, 0x1543f27e, 0x49cdc21a, + 0x6c447684, 0x1452d0ac, 0x9bc7fd4f, 0xff4b045c, 0x2cc30a31, + 0x852f7611, 0x415d46a0, 0xc6fdd7a6, 0xad737052, 0x7b4c7c91, + 0xdcecc3ab, 0x7688d70c, 0xd2cdf01b, 0xe40d3905, 0x054f2542, + 0xfefe4dcd, 0x02227fa6 }, + { 0xb751948b, 0x1805efd9, 0xfdfd225d, 0x8efeed46, 0x4f2c8b22, + 0xcb128e09, 0x96f7c5e5, 0x9d1090bf, 0xb4cbeca0, 0x0959d044, + 0x8e08cb04, 0x21c955f9, 0x68fa4fce, 0xbc1f279d, 0x0710ae9a, + 0xb021e14e, 0x881167f4, 0x64d16e9f, 0xbbc9f1a5, 0xf5a5c22e, + 0xe3420eea, 0x5f3716df, 0xd5c4e843, 0x971eb915, 0x28ffba81, + 0x64fc55fc, 0x7dd37578, 0x3427e54d, 0x15ebc7d0, 0x446e6a62, + 0x29269778, 0x547e249a }, + { 0xa1ffda27, 0x4706868a, 0x7955cf50, 0xb4e6cdcc, 0x0a63f3d8, + 0xf65151e1, 0x9de5e70a, 0x5b4127ea, 0xf9342823, 0x3d2c09ba, + 0xaa2f7d51, 0x18c99d83, 0xddeec025, 0xa0c5bb1d, 0x03dcf1ce, + 0x7ffddf84, 0x616fdeda, 0xe57e4d29, 0x7932a1f0, 0xd2456569, + 0x3191d4e3, 0x7475e0e8, 0xc220218b, 0x3479bea1, 0x8bcb2505, + 0xfceb5c90, 0x3c6132e6, 0x1c685cea, 0xbfe6c1eb, 0xc42dc745, + 0xd2b08eea, 0x45a41cc0 }, + { 0x4dbbf0e1, 0x3ea9b2c7, 0xa17cf70e, 0x41ff962f, 0x5eeb4c66, + 0xdc1ea758, 0xa9beb17e, 0x4f5412d2, 0xa285741a, 0x2c9e4f52, + 0x984fd11f, 0x93df7da4, 0x0df3184e, 0xb2afbddc, 0x2421e375, + 0x96323d25, 0x49df781e, 0xc87be1e4, 0x3d589bea, 0x145601ed, + 0x28fff6dd, 0x0f0bd9bd, 0x8a0f298c, 0x2d3259d4, 0xd88e6944, + 0x362d7a77, 0xb6ac2af6, 0xa84c06b6, 0xd087da02, 0xba850ac9, + 0x42ee40c8, 0x128763c9 }, + { 0xacbac178, 0x29a80f07, 0x34b08f6e, 0x7cc20044, 0x70feded2, + 0xe9631d14, 0x86615767, 0xb2115da3, 0xcb088548, 0x7c75f5c4, + 0x9a2e8e03, 0x5b29d213, 0x8b881752, 0xfe9fda66, 0xc1de7ebc, + 0x3f1d8d88, 0x03218123, 0xb476565e, 0xb1c995f3, 0x07365561, + 0xb13eb71b, 0x2160cb18, 0x99b3a0eb, 0x7e8da513, 0xb20fcd74, + 0x5e8ca1f9, 0xb4126d72, 0x6a7e0067, 0x68bb637f, 0x1e8204b7, + 0xfc4f74d2, 0x75e96bcc }, + { 0x0d19716e, 0x189d1fdc, 0x7c384525, 0xdf585058, 0xea987d2a, + 0x64a846d1, 0x6c07150f, 0x12b6bf83, 0x4d6fd5b7, 0x91d85d46, + 0x4f53f55f, 0xa9788836, 0x81509129, 0x60083bd8, 0xea876f48, + 0xa7672683, 0xc15b2489, 0xe80b2e7a, 0x42d1d992, 0x985ef8d2, + 0xcf3de492, 0x9c57b029, 0xb1487627, 0xfe02f83c, 0x8ae5b687, + 0xaeba4fe4, 0x5d6b8196, 0x8a86f09b, 0xa16e523d, 0xd88f566b, + 0xba268949, 0x309a6e9a }, + { 0xbdfbe97a, 0xef27ee50, 0xb8c50c4d, 0x1a5fe70f, 0x7fe09f5c, + 0xcc7beb01, 0xbed36cc5, 0x8fa15a85, 0x7550ed3a, 0xc0c3acdb, + 0xeb908681, 0xc581ef87, 0xc49d5ccb, 0xa15b3362, 0x1fa264e8, + 0x0fbb1714, 0x8e1eee88, 0x267f8d8f, 0x21c2b63d, 0xd31ccfd6, + 0x53be7efd, 0x924dbe7d, 0xdb2a358a, 0xd42e877f, 0x75d68ac1, + 0xcf9673c7, 0x714fea55, 0xe35978fd, 0x5769b202, 0xeeb36653, + 0xd7593789, 0x0458258a }, + { 0xa042dbdf, 0x5df71a74, 0x5779dfa2, 0x2d405857, 0x0d2e6657, + 0x0e66cba7, 0xca2e892e, 0x285d6745, 0x0f0e6b5f, 0xf56a8def, + 0xa30767c3, 0xe0ee851d, 0x43346b9c, 0x98c05658, 0xd6b3c742, + 0xb35fce26, 0x39777e00, 0xc0895bff, 0xe7b6d886, 0x83c8f6a6, + 0x4f02904b, 0xbee14843, 0x2e84ec34, 0x7f74915b, 0x96d10991, + 0xbaaf663c, 0xe41facc0, 0x004b8757, 0x6f86c029, 0xa2b880e5, + 0x95b77358, 0x53f4a3e0 }, + { 0x89fc48e7, 0x11bb08ce, 0xafab5aeb, 0xba60c577, 0xa0c1cb5a, + 0xf06bcbf8, 0x79757cb6, 0x7d2efaea, 0x76319160, 0xe26d90b1, + 0x2b77b7a9, 0x42aa1ab6, 0x285df2bf, 0x38eec0cd, 0xf3a8f7f0, + 0xd35947f5, 0xfc1cb5b5, 0x97c8dc0e, 0xc45845cf, 0xfeb8cca0, + 0x249e26f2, 0x16e8d989, 0x483ed89a, 0x7c264e6d, 0x51d91073, + 0x13a3f145, 0x305e99f0, 0x8501562e, 0x6908d563, 0xaaf98d74, + 0xd723d236, 0x0a99e653 }, + { 0xabbc0559, 0x23536f46, 0x9aa1a160, 0xc163067b, 0x0c1681b5, + 0x229fd229, 0x1378e907, 0x61254be1, 0xab793a2d, 0xc60ff57a, + 0x466552db, 0xa6f2df8b, 0x8c170a36, 0x9ad31893, 0x29b74d9a, + 0xc5cd9abe, 0xf7848523, 0xcf747273, 0x0d0e3063, 0xc126a93a, + 0x4248e3d8, 0xfe2021e3, 0x8323ddfa, 0xd97343ee, 0x332639e7, + 0x9f768775, 0x75325548, 0x9650fc31, 0x3eebf7ea, 0xb595dbd1, + 0x010fcbc0, 0x3a95cb45 }, + { 0x39d7ff2e, 0x954e68cb, 0xc1d5c48f, 0x8dd1cb4b, 0x7169438a, + 0x02a92c77, 0x91cad8ce, 0x7965c0b0, 0x32cd08d2, 0x0c5798ab, + 0xa6902bda, 0x1a5bc3c3, 0x5186d218, 0x545d0925, 0xd27e64db, + 0xf0077cdb, 0x8cd092da, 0x0157caa4, 0x24532ab3, 0x2a2fa3a0, + 0x41ccaba3, 0xa5fb639b, 0x4744aee6, 0x01702dc1, 0xcdba93da, + 0x485bb436, 0x329784f1, 0x93597f66, 0xdad672c3, 0x5d713c1d, + 0x030b7245, 0x366d222e }, + { 0x573ea5b2, 0xd50b4875, 0xa90da44d, 0x0fce401b, 0x7a1a0310, + 0x7b53fa65, 0xcf114460, 0x722a80a5, 0xa538bf49, 0x0b8ebf05, + 0xd32acd21, 0xae141147, 0x7b5ad07d, 0x6692712c, 0x3f48ca07, + 0x6dc5fee7, 0x2b8a78d8, 0x98ed1499, 0xdd2f1759, 0x4e8b3145, + 0x5f971b8e, 0x43408de1, 0xadf1b368, 0x055ea6dd, 0xe5932b7e, + 0x4bb76e73, 0xd30893fd, 0x44287153, 0x0661bfda, 0x173dccd2, + 0x79defd25, 0x9072ba99 }, + { 0x9620ea39, 0x474de4dd, 0xc831cee8, 0xfbf1649f, 0xcd3a9c43, + 0x0b0e8bb1, 0x3f3df1d5, 0x6a38286f, 0x8f0ec9b3, 0x4ed072b3, + 0x729c09e3, 0xa6e4c987, 0x8ad12242, 0xea3e8ac6, 0xfbdfa5ba, + 0x6ae0e22b, 0xb0a0f592, 0x56171ecf, 0x6b871f8d, 0x33b2886d, + 0x35e11bda, 0x6b19bea9, 0x7f0f153f, 0x4d815a40, 0x7d6c02ee, + 0x7e608d97, 0xb6a88f46, 0x7e8f23d9, 0x439d1654, 0x26ac9652, + 0x35546c29, 0x8d92c6bd }, + { 0xabeb0ff7, 0xb3e0d7ce, 0x3e0e42f8, 0xfbe35254, 0xde808499, + 0x57d1b226, 0x1cd44bc3, 0x9ece2e1f, 0x435cfee1, 0x1245adbc, + 0xf93f581c, 0x874ee840, 0xbda0b947, 0x916a779c, 0xfa57ae0a, + 0xabcc815a, 0xf0a621b0, 0x97adec2d, 0x81f90bdc, 0xbe6a502b, + 0x53bde63d, 0x54bf9de1, 0x78884c25, 0xa88fdabf, 0xcbbb5470, + 0x30aa52b1, 0x29053ef5, 0xf805396c, 0x8dd827ea, 0x8d43d898, + 0x5c1ae5c0, 0x4e4bec17 }, + { 0xfcc09676, 0xbf8483a2, 0x19ea9a94, 0x457c4a3f, 0xd702a5dd, + 0xa6852ef3, 0x843fe7d8, 0xe7915fd2, 0x16e35158, 0x644bba98, + 0x9ed746f0, 0x8d1b95d0, 0xb90af0b5, 0x47704581, 0xd4fd135e, + 0x0bd4bc6b, 0xb4e833a5, 0xa6dce067, 0xff56a9a1, 0x2c0e8f30, + 0xec2c63fe, 0xa9c80800, 0x98f508a8, 0x449c20a5, 0x3292813a, + 0x02b94cb3, 0xec7e81a2, 0x647e3d28, 0xb4877677, 0x72e67d1a, + 0x6f9ded24, 0x7a4aa3f5 }, + { 0xe27a0045, 0x559ef1ba, 0xb242cb50, 0xdc812d4f, 0x39cf8d24, + 0x23a478e4, 0x9b3f9c54, 0x97544fc5, 0xaffa1fcf, 0x5ac68132, + 0x34a2c83b, 0x74f8fee0, 0xcd3f4bb7, 0x96cc640f, 0xb0512ea6, + 0x775dce9d, 0xcdce381e, 0x67dca19d, 0xa9d3fe55, 0xc1eeb3f3, + 0x1a19274f, 0x38e0bf42, 0x28d69b12, 0x15992fb4, 0x9fd09df8, + 0x48fcebde, 0xb41ab5df, 0xdc9dfa4f, 0xc0a269c5, 0x0cbd7dc8, + 0xf7f0ade1, 0x60282a7b }, + { 0xdceea2e7, 0x7c07e538, 0x3c42061d, 0x38a322c8, 0x4f1f6516, + 0x676828f9, 0xc7776a10, 0xf21b69fb, 0xb5e6b405, 0xc63a3417, + 0x91a7b642, 0x4c99f258, 0x2cad1440, 0x38692ca8, 0x00869bcd, + 0xf1e82ffe, 0x16fe466a, 0xc30b714e, 0x19019138, 0x5fb742f9, + 0x0fa516ae, 0xe90166d0, 0xd8c73a43, 0x5550f7ac, 0xfbc5c372, + 0x2d6a407d, 0x68cc39ed, 0xe47a7539, 0x4a5fbe70, 0x3fd286d9, + 0x23c6b942, 0x5f4ae9c7 }, + { 0x53f4d561, 0xd96a2dda, 0x16da1992, 0x286d45d0, 0xfdd4b051, + 0x449a01fb, 0x9f2195ea, 0x25488a0d, 0xa37661b3, 0xc4151b0a, + 0xf9e5ee02, 0xb98c471e, 0xa8658817, 0xa4bca86e, 0x7a68fc0a, + 0xbbcadb87, 0x6b7366a9, 0x88b34649, 0x15661c2d, 0x32ee98d4, + 0xc901420c, 0xf5b3b4c6, 0x2f2752af, 0xa2352735, 0x510e4d9c, + 0x2f64ce73, 0xaca4aa80, 0x939a7f26, 0x401aa503, 0x9cd3e291, + 0xdc46afd2, 0x92a01423 }, + { 0x1c2f7dbd, 0xe9f24be1, 0xb7d527fa, 0xda8c900f, 0x8648f128, + 0x963e25bb, 0x48141941, 0x9ab713e2, 0x7a6756fb, 0xe87f7d01, + 0x058d90bd, 0x274dd85e, 0x82566abd, 0x823fee7a, 0x74240195, + 0x9f6230d7, 0xacb5e46e, 0x04579f2c, 0x16a4c87e, 0x2a226263, + 0xd99b0857, 0x9ca19a43, 0xe488789e, 0x86dc2ba3, 0x9406c3bd, + 0xf960b5b9, 0x8960957e, 0x6f2c428b, 0x161c515b, 0x90748706, + 0xaa88cb9b, 0x0fc8fe1e }, + { 0xfeb90f2d, 0x68ae1bed, 0xa48b1559, 0xf393bb3c, 0xf64e9635, + 0x2be62f9c, 0xf8be75c2, 0x354c2410, 0x5e6f7529, 0xbd7ea703, + 0x162cab31, 0xc264868e, 0xc860f3ff, 0xb1391e70, 0x1d89837e, + 0xdf367c75, 0x2bf32941, 0xe150b6b4, 0x78c1318f, 0x95e8f46e, + 0xa2c4b160, 0x2b3f1dab, 0x701afbf3, 0xc6ccf5ce, 0x5e8874c5, + 0x3ad27530, 0x5dc6dcbe, 0x39285e51, 0xd99892dd, 0x3c954d86, + 0xdfd3789f, 0x2d0ba862 }, + { 0xb472e1af, 0xeacd8ee8, 0xb76abbcc, 0xeb354eae, 0xd0d93fbd, + 0x9b520bf8, 0xfe6fc706, 0xfccd60d7, 0xa4ee2f39, 0xa9353dde, + 0x9a81e51e, 0x5eb0925e, 0xd1366777, 0xee334da1, 0xd5354d69, + 0xc1d28c9f, 0x92a5ed54, 0xb9771755, 0xb7f70d81, 0x5d3e367f, + 0xa933ae7a, 0x7be7eeca, 0xe23cfbb7, 0x264cf1f9, 0x89497681, + 0x0d129f4a, 0x09b6235b, 0x705375a4, 0x48a376da, 0xccf64c75, + 0x4d41dbfc, 0x963c8712 }, + { 0xde36a814, 0xbae290cb, 0x733b12b5, 0x9bdb0195, 0xf77fe0e1, + 0x0ebad867, 0x29720cea, 0x0a7d19fd, 0x9029ec72, 0x434d7651, + 0xbb51911e, 0x856aff17, 0xd80a7f60, 0xd0a25d9a, 0xf848c106, + 0xffca86af, 0x43ad749c, 0x53e8bdf9, 0xe3e696bb, 0xfb9e0284, + 0xeeee4215, 0x3eb6630a, 0x2ecf3c63, 0x9d8fbb9e, 0x4e00c0c0, + 0x71da4ffa, 0x5d57beac, 0xb296be59, 0xa8cec7ef, 0x1751fbad, + 0xff55d7bd, 0x2d03eb3c }, + { 0x04f2ec1d, 0xeb16925f, 0x0d147ee2, 0xa878f276, 0xaad9d9e0, + 0x442df604, 0x3f71035b, 0x891df44b, 0x8cb95d5b, 0xc28272b3, + 0x5ee8ed23, 0x6f14efb5, 0x13b0f3e3, 0xf3c4460f, 0x6bd7335e, + 0x889f9bd7, 0xf755ba6e, 0x889ee771, 0xed219b6c, 0x626984fe, + 0xec2ee411, 0x2d44c737, 0x63efcd37, 0xb94385a2, 0x6637826b, + 0xd909321b, 0x3ee6b7a7, 0xc24f8a79, 0xa7cf61b7, 0xa3ca8d24, + 0xc54bacd9, 0x842e40c1 }, + { 0xa661d843, 0x5a268ed6, 0x4f5b30cd, 0x02328cca, 0x1311e177, + 0x16e6fed1, 0xc6695967, 0x690decb4, 0x57b2e280, 0xbdac5bf6, + 0x1efe42d0, 0x827f82ca, 0xca5fca2f, 0xc554ec0a, 0xdde45506, + 0xac5276c1, 0xe3077513, 0xb7f4cb08, 0xcc8797cc, 0x8caf6d9a, + 0x0d9332d2, 0xd5964814, 0x285a409f, 0xcc6ae297, 0x6223d093, + 0x7773c2a5, 0x5128fc09, 0x2d5266ac, 0xbc31fe6c, 0xa596b7cb, + 0xcac91328, 0x0e63319a }, + { 0xf0360ac2, 0xb5cd2fad, 0x285e605a, 0x86b660de, 0xe25b9b14, + 0x82c6cf10, 0xaa9ac554, 0x9d5fa38d, 0x526c070e, 0x3dfcf1b8, + 0x3fccc52d, 0x0379a96b, 0x0bfcc7f5, 0xe3659c29, 0x69d3e6a1, + 0x5b1a3db5, 0x9b7b42d5, 0xb41528b5, 0x9c22a006, 0x934defa4, + 0x9b4ce3b6, 0x90f38018, 0xb3abaf32, 0xb073bc04, 0xff8389e2, + 0x27a5a222, 0xffa5a35b, 0x0b7a9d51, 0x28e1a7c2, 0x4939ecef, + 0x1872705a, 0x88839da2 }, + { 0x701ce29a, 0x56b66c30, 0x58981d50, 0x3acaf126, 0x105f9f21, + 0xd4dafc0c, 0x373e3d13, 0xfee571e6, 0xfa2ee3ca, 0xe7269c86, + 0xdd20385a, 0xf5cca64a, 0x3000e9ac, 0x217f2757, 0x0e7273ef, + 0xc934db47, 0x355b6776, 0x4294f4f7, 0x6fc05180, 0x1faa36b9, + 0xb052190b, 0x8f88b1db, 0xe9eaef52, 0x35791b90, 0xdb681b90, + 0xf37fb2eb, 0x4415c369, 0x39d0a51d, 0x1d2e21c9, 0xfc59cca7, + 0xa1f50c26, 0x64128cfe }, + { 0xe8f5b0b5, 0xf03678a2, 0xd340f059, 0x5c7e249c, 0x93ca7cec, + 0x41440441, 0xbc83af98, 0x075ca346, 0xfaa8bbb0, 0xf39f0033, + 0xf38230f7, 0x3d18f0ed, 0xd448f345, 0x78dff00c, 0xd51aa475, + 0x849228c0, 0x30c928d1, 0xdd4e2708, 0x8f12cfd3, 0xc66ba686, + 0x88b3a206, 0x091049db, 0x016dae01, 0xd865d059, 0xe253e37d, + 0x4599e905, 0x7ce9871b, 0x322cf0c2, 0x174a132e, 0x014f54da, + 0xbdabcbda, 0x93634a09 }, + { 0xa9a2e304, 0x62826b27, 0xc1a4c124, 0xc57e1866, 0x22381710, + 0x913ab832, 0xa9847cfe, 0x7e9b6b85, 0x2b5f46fd, 0x29655cf1, + 0x8038e66d, 0x7295572b, 0x6fa95eab, 0xe4cba601, 0xb9deda81, + 0xbbc11071, 0x3f1cf61e, 0x97f0009a, 0x373e0cfb, 0x5372777b, + 0xd139d63b, 0x302f909c, 0x4f87d78e, 0x1ed672da, 0xb4048763, + 0x362077a3, 0x9dcc22b2, 0xc408c32d, 0x26deeee7, 0x4b4c5bf2, + 0xbc06357e, 0x266cb467 }, + { 0xb56363e8, 0x6faa4154, 0x3c1aa4db, 0x4b4fd078, 0x2b9e6597, + 0x14358dde, 0xfa004b84, 0x5b34ae3e, 0xf19911a6, 0xcf44b2ec, + 0xa536bf78, 0x55caa833, 0x8870dc95, 0x606e1eb9, 0x09f3511d, + 0xe3c3287d, 0x9d5cf364, 0x68b2f4eb, 0x63ab8c9e, 0xc154e892, + 0xc36ab611, 0x1548828e, 0xa1b7d120, 0x0932bfcb, 0x5315b8d7, + 0x7ee7b5bc, 0xf7473ac1, 0x782fd0d1, 0x3c8f2af3, 0xbcb029a8, + 0x52454ee1, 0x4b1d5a1b }, + { 0x63d52c0c, 0x12fe5174, 0x188c099d, 0x3735525e, 0x360e3956, + 0x5c621563, 0xacfa5a43, 0x88b3f1ca, 0x797e8107, 0x90123a0a, + 0xb15e080a, 0xba31f6b5, 0xfca3dada, 0xd7de5e12, 0x0df511c8, + 0x3287361b, 0x65757d4e, 0x7cc800d4, 0x5207ec91, 0x10810f3d, + 0x30eea0e3, 0x0d4e56f1, 0x3ea5a2ec, 0xbbf7ee13, 0xbe6abbd0, + 0x6fc07762, 0x120bf619, 0xc831fdce, 0xb622d42a, 0xe07439fa, + 0x508e4b27, 0x8186b93f }, + { 0x09312867, 0xc619d154, 0xbfaf7db4, 0x7e042c05, 0x1f5f5dda, + 0xc1cf1668, 0xa4fc3d82, 0x50aa5057, 0xce68b8fe, 0xed30ed65, + 0xbeb4d644, 0xecb01c0b, 0x831c0497, 0x7b5dc444, 0x9b7d9b1c, + 0x351e6a00, 0xd9477c91, 0x4bb863b9, 0x05d4110a, 0xaba65891, + 0x43580b7a, 0x30086cf4, 0x90be357e, 0xb139c076, 0x27b5214e, + 0x12bfff1a, 0x22c3ab57, 0x79cfc6d7, 0xf34a9bfa, 0x4743de57, + 0xc9ee2b2a, 0x0bf97e97 }, + { 0xdda19e96, 0x96ec4ec8, 0x6c306e8b, 0x54ce18ea, 0x65f6918a, + 0x7e83612b, 0x0d9a0d99, 0x1ac6f68b, 0x62fdcc09, 0x98a697a4, + 0x95bc3e13, 0x65ce25f1, 0xb3939730, 0x1896ecda, 0x32f12806, + 0x9eb81a0f, 0x1d2dc7df, 0xd3d7416e, 0xad473599, 0xe22c7976, + 0x9f5ef439, 0x3de37a9a, 0x9e69d94e, 0x6b7ac0ab, 0x0a9d0bc8, + 0xe6bfa9e0, 0x5676f120, 0x576a870d, 0xfeaac23f, 0x3bd91bb4, + 0x3e40aabb, 0x8fe5482c }, + { 0xce9a4d1e, 0x85ae67c2, 0x4f1d2038, 0x4c3eb803, 0x25d06192, + 0x5c6c8f3a, 0x308fb41c, 0x803de0ad, 0xe71c294e, 0x9961f5bc, + 0xf02eb0da, 0xdc62078d, 0xb64ae8b6, 0xc87ef515, 0x50b4d18f, + 0x69679f1e, 0x52199f43, 0xc5c009a1, 0x0f640a5f, 0xa7d484be, + 0x23dab566, 0x4c918bb1, 0x64275d2c, 0xa67c114c, 0xcad2ded6, + 0x95a913b9, 0x6b4b5c8d, 0x189ed18b, 0xb42d3bf6, 0x4aeb6206, + 0xbbc8bc3f, 0x3928c669 }, + { 0xdacb4b64, 0xde4bea4a, 0xf26179a1, 0x03f62a44, 0x7a9112a4, + 0xf3aac94e, 0xd36f331e, 0x90448fbd, 0x407b85c4, 0x426042bc, + 0x2121b77b, 0x5ad8a596, 0x67cee984, 0x31674a4f, 0x4e3b2f0d, + 0x7fae8bbe, 0xa7c930eb, 0x681df6dd, 0xc259d0d4, 0xadeefa98, + 0xbea1c1fd, 0x1b14d9e6, 0x21d405d1, 0x3baadc8b, 0x73892754, + 0xf01dff93, 0xf071cde4, 0x81c35b3e, 0x9150d0d9, 0x1704d2e1, + 0x355134f6, 0x6ccc888f }, + { 0x7ad7504c, 0xf8d36f0e, 0xf7959ddd, 0xbca3265f, 0xfede67aa, + 0x0dcd1ede, 0xbaebf32f, 0x1276f4ce, 0x014edcfc, 0x6825a6e6, + 0x99ad8eb7, 0x0b8c1a82, 0x09b8ce1e, 0x312024a9, 0x9cbd351a, + 0xcb8fd98b, 0xfab1e8be, 0xa4841378, 0x3973cacf, 0x17ed0f5d, + 0x259d5254, 0xa17e1484, 0x74b91393, 0x53d5b843, 0x1aca3ce9, + 0x8f792b21, 0xc8c0f815, 0x035ff110, 0xad4ed7bd, 0x6afa6357, + 0xb26faef9, 0x2f151980 }, + { 0x29d2d439, 0x0c8631da, 0xbc039955, 0x121fbbc2, 0x6c05b75b, + 0x3e5a9792, 0xb6ce47ec, 0x6d6cf4c0, 0x9d88c658, 0xbaaa1767, + 0xf3355a17, 0x031db9e7, 0x0aef5a85, 0x8381e3d8, 0x15a31bdf, + 0xc71db290, 0x9498fd7d, 0x638f6b74, 0x13beeef6, 0x44edf3f9, + 0xf4ab67b3, 0xe6173271, 0xfd22df11, 0x3a202c70, 0x205c4e92, + 0xf7be0389, 0xa8eb9920, 0x1c219085, 0xbeb54aaa, 0x6c805ce8, + 0x0ac58d65, 0x354b05b7 }, + { 0x7a9170e9, 0x7171e236, 0x4cad50cd, 0x01eec42d, 0x3cddccfb, + 0xffbe824f, 0xa66cae1a, 0xa73e8ce3, 0x965c7d01, 0xb7138a7f, + 0x5c3d971e, 0x00058e3f, 0x2ff0a72b, 0x52591ac3, 0xbbbce76f, + 0xa32fb5bc, 0xa9f81a18, 0xf3241ab8, 0xeca68630, 0xf31d3332, + 0x4482f13b, 0x847af9fc, 0xa4681be2, 0x6196e217, 0xe55efcf9, + 0x9938f932, 0x70acc705, 0x3e7dacb8, 0xcf09fac2, 0xd41be893, + 0xae3523a1, 0x48dc55c4 }, + { 0xa5092193, 0x8e623826, 0x6898970c, 0xe46ec362, 0x25c9eb41, + 0x2f1356af, 0x83c7d245, 0x41780640, 0x97d00e38, 0x982def67, + 0xa512151c, 0x382eb6e7, 0x8af58869, 0x154e1077, 0x8a51cf02, + 0x18707075, 0x71313c58, 0xcdeba9f7, 0xba155904, 0x5d67b973, + 0x1d0d7b3a, 0x851c9f4b, 0x8b8af2cd, 0x19f29d71, 0x986b8d62, + 0xcb94ccff, 0xb93b9c33, 0x8725e24b, 0x66e38c68, 0x405ce4c5, + 0x0b6dc021, 0x5f6a8edd }, + { 0x8f9a8690, 0x83704ca5, 0x2f76a407, 0x3f369766, 0x69201028, + 0xfbc12d8c, 0xbce3a4cf, 0x4cd58f16, 0x04aab26d, 0x7804664a, + 0x4ea457a8, 0x005cfbba, 0xb8a59794, 0x537951b3, 0x4fe1f739, + 0x4ca2b9e4, 0xdf325797, 0xe4428acd, 0x0ea243db, 0x648da342, + 0xf43ce01e, 0xcce6562b, 0xf27db490, 0x840f0421, 0x8bfb7cf0, + 0x156ccb70, 0x5a8797d3, 0x9b33480d, 0x9eb814bb, 0x2e12e07a, + 0xca7f87ac, 0x1ca65072 }, + { 0x2b9d25a0, 0xfbb321cf, 0x40a746db, 0x66affdca, 0x59e368b5, + 0xc1c1530e, 0x7d80068f, 0x56ed1ea4, 0x5647dd68, 0x9b74d8fe, + 0x89b78da8, 0x1d96b507, 0x8bbe3391, 0x39b75243, 0x0d858c5f, + 0xef8d443e, 0x9646aa34, 0x4dd2db49, 0xe667543c, 0x7fad3bd1, + 0x68980985, 0xd0d710c0, 0x49facaba, 0x9f7aff32, 0x14f9a192, + 0x055dec1c, 0x1fb307a1, 0xaca66399, 0x35ffff64, 0xac44fd91, + 0xcbad3cee, 0x462cafb6 }, + { 0xde3237dd, 0x1660a647, 0x82b87404, 0x95f735cc, 0xddfa55f8, + 0xf7879f59, 0x726b914a, 0x15ef043e, 0x1c93e298, 0x1875393d, + 0x6ef18331, 0xa1a2be74, 0x25a9a12b, 0x4e7e8dfc, 0xa9c3917f, + 0xdfefc97d, 0x0a2ebe41, 0xbc875d03, 0xa732d1cc, 0x0f75d235, + 0xd9baa6d3, 0x06fee7fe, 0x65f48576, 0xaa784fab, 0x513f83c0, + 0x23155e22, 0x3e8f9d13, 0xd2fb7718, 0xb546eafd, 0x2a291503, + 0x6cd93608, 0x1293c98c }, + { 0x49d53b77, 0x72781251, 0x96eafac7, 0xa6ab403d, 0x4a36b711, + 0xb7d7c7db, 0x87e771c1, 0x8238c708, 0x33b37522, 0x495f6abf, + 0x8c87530d, 0xb0b0289c, 0xe77b111a, 0xca83cb86, 0xa1bd189e, + 0xbe1c0fb8, 0x1ae9d7c7, 0x58cfb2fb, 0x4940c3e8, 0xd05c23c5, + 0x74ad9107, 0x16e79e41, 0x064e7142, 0xa0a47f05, 0xfdfd614f, + 0xc6929cd4, 0x3946988b, 0xedb2584c, 0xe46f8fb1, 0x73e4b5f3, + 0x68ea94ba, 0x53b79aa1 }, + { 0x44bbb6a1, 0x216fafce, 0x67821728, 0xd3a5bba0, 0xa9dd939a, + 0xef1e4b30, 0xf19efafe, 0x022eaf3d, 0x7b4ec014, 0xfed5abce, + 0x512c6738, 0x64968ee6, 0x29fe89a2, 0x23119869, 0x47397c05, + 0x0d539d8d, 0x234596c4, 0x6400bc54, 0x5346611d, 0xb9287f58, + 0xc9d5da0f, 0x04099903, 0xc83af2a8, 0xe5ef4997, 0x328151e1, + 0xc89dc01b, 0x58401104, 0x150fb4a9, 0xf3872c9d, 0x40a6f7d5, + 0x56c2e833, 0x8290d6d1 }, + { 0xd8546946, 0xf84637c6, 0x69ec57fa, 0xda134a39, 0xd789007e, + 0xd42359a4, 0x0dc7b809, 0xb42557fe, 0x2d6784a9, 0xe62ae52d, + 0x0bcadb5f, 0xa2714ca6, 0x33aafca5, 0xcc208de6, 0xed967811, + 0x2380ed5c, 0xdb321660, 0x6e6b55e9, 0xa675235a, 0x1bead02c, + 0xb33fa0e1, 0x51cc6ef9, 0xf06a2a08, 0xfd223e26, 0xec47b3cf, + 0x00f332e1, 0xa0aa984e, 0x459f297b, 0xee952e14, 0x6fa1d969, + 0x304fabb0, 0x506ef1ab }, + { 0x35bff163, 0x11b4eb27, 0xea9fa984, 0x7130b96f, 0x9deb27ce, + 0x66aceb3f, 0x9dd1c3d5, 0xa2daf1a5, 0xa73075aa, 0xf5090a7e, + 0xe3071b58, 0x36a6af39, 0xdf73ad9c, 0xa28d633d, 0xbdc89a16, + 0xdd354cac, 0xd4dcbc3c, 0xdfea3423, 0x379d92d1, 0x6eec74d2, + 0x8eed6765, 0xe14a456f, 0xfa8feb1f, 0xfabe7743, 0xb98fcbc7, + 0x1404ccf8, 0xf71a706e, 0x6ccd2fbf, 0x4d85c678, 0xdaaf3fdb, + 0x15200344, 0x415b7dbf }, + { 0x7d8377a7, 0x97010586, 0xcb803272, 0x068a3d68, 0xf03a4c32, + 0xfd67d289, 0x93c8f290, 0x4bc7095d, 0xe9e5a2b8, 0x712fa13c, + 0x0feb9f3b, 0xfc6ac6c6, 0x6e0e54c2, 0x0cda36d9, 0x86320a01, + 0x45499751, 0x97f00f11, 0xf9318c91, 0xe6936508, 0x01dc4c3f, + 0x85f068aa, 0x769a2ef9, 0xa2b5511c, 0x3522cef0, 0xb4122e05, + 0x006965ed, 0xc175d43f, 0xfce0fafc, 0xec831d59, 0x525dc9bd, + 0xaf58879d, 0x1ec314f1 }, + { 0x2c8310c2, 0x0663feef, 0x457e3f74, 0xaa7e14da, 0xe5346887, + 0x392b10fc, 0x637ec2c5, 0xcde4a38f, 0xb542f8df, 0x50773320, + 0xf7de1711, 0x341302f9, 0xae4b9bc6, 0x018b1c63, 0xdd2f9e6f, + 0xf001c46e, 0x26eccfa0, 0xd3bb0a97, 0x7746e0c7, 0xa931b99d, + 0xf5875aec, 0xe0c8b6f7, 0x96939c82, 0xbb32f17c, 0x3de5a664, + 0x765135d2, 0x52abfa6b, 0x71936cb4, 0x2dc105de, 0xad5cc08f, + 0x7fff5788, 0x17e91d12 }, + { 0xb7e051ca, 0xbe92ced3, 0x19c776d4, 0xc644d4fd, 0x0086784b, + 0xc8ab4b52, 0xce9d6b31, 0x3ea66227, 0xd289e9c7, 0x395249a3, + 0xd12a19ee, 0x54509e65, 0x8c365aec, 0xa7bd4692, 0x77963e0e, + 0x354997e4, 0xb599732d, 0x0d765957, 0x91d4a3b6, 0x99584aeb, + 0x1deb3e28, 0x6e653ea4, 0x572571df, 0xca7c98ed, 0xb18ae1f9, + 0xf301a38f, 0x63f7b97e, 0x1629f7c2, 0xafc4a0d5, 0xdf242282, + 0x3ddd0c01, 0x118f3b4b }, + { 0x7ad4762b, 0x74a0a0a8, 0x8c58d175, 0x1aef84da, 0x4cf76d86, + 0x16ff4960, 0x7e60d98b, 0xc0be8786, 0x3ecc1dba, 0x83637ffb, + 0x5dd6147a, 0xc244a609, 0x5b0846e5, 0xa3e17834, 0xe77a4c05, + 0x735eb686, 0xdf758695, 0x5bc18b4f, 0x1bdfe52f, 0x15618d0b, + 0x00715ba1, 0x878ecc0d, 0xc2dd617f, 0x1dbdbd1a, 0x21b61710, + 0x21d2b631, 0x44f593c2, 0x22ce8a79, 0x44f17024, 0x3b9b536a, + 0x8d03e727, 0x01d0a67c }, + { 0x1e46533c, 0x7b964236, 0xfb88c2ae, 0xe9477990, 0xa42c4a18, + 0x019b5d16, 0xd83c7a45, 0x7135e81d, 0x4cb663e3, 0x74a69bdd, + 0xe76c0d63, 0x7b67ecdb, 0x11e68da6, 0x03d54521, 0xd2e8650a, + 0x596cceb5, 0x2af03b37, 0xcd572dfd, 0xfabd5952, 0x52364ba1, + 0xb4ed8569, 0x7f47d456, 0xc950d5d4, 0x5ad8b572, 0x486e2f84, + 0xcadd2dfa, 0xc56bb044, 0xdd527b43, 0x997c08e6, 0xc9adba24, + 0x7da6320f, 0x1b625b06 }, + { 0x4fd8446d, 0x44dfaa7b, 0xaf6febeb, 0xc01b2f01, 0xfe8838b5, + 0xbf444388, 0xbba9758b, 0xf33c434f, 0x87156bc9, 0x2b971cba, + 0x1f49098b, 0x6b245e5c, 0x2b41c5dd, 0x87dcb534, 0x34d852d7, + 0xdb1f80c6, 0x2433da34, 0x6d6e3258, 0x3f7df0c2, 0xf6682065, + 0x360cb365, 0xc4ca567c, 0x9826656a, 0x321faac2, 0xbf069768, + 0x13f5ca6f, 0xa7076639, 0x15397921, 0x8400736e, 0xbdf14328, + 0x19fc948d, 0x333eca96 }, + { 0xac775d81, 0x23337948, 0xd41dbbca, 0x38c2518f, 0xbcfce948, + 0x623c7a4f, 0x54703fe7, 0xaad36236, 0x13fb3b5b, 0x2b3a13a4, + 0x7f5c01f0, 0x5db3565a, 0x52359661, 0xd72408dc, 0x1d616e91, + 0x5a17f8e5, 0xcb25b999, 0x90c16eeb, 0x3393743e, 0xf35e8cf1, + 0xe54b64a7, 0x987da74a, 0x65cd449d, 0x557b322a, 0x37e7b15d, + 0x765082a5, 0xf2cd134f, 0x4d25c742, 0x4ccf0746, 0xae9d9c07, + 0x8728d135, 0x72fc2110 }, + { 0xf96004c8, 0xa906b203, 0x458055ff, 0xd83f95cf, 0x55f35909, + 0xd77d5867, 0xe550c8ee, 0x4a9ea6fb, 0x55a06081, 0x91c8cca9, + 0xbce82062, 0x4a1fee78, 0x9a3df85e, 0xeb9ade06, 0x7d3de666, + 0xfbbdcf0c, 0x5d336d51, 0x228a391b, 0x5c2ffc3c, 0x760f8d28, + 0x2f7b165b, 0x1ee48de3, 0x56177040, 0x03803d84, 0x9deff9a0, + 0xe573f648, 0xa17e35a4, 0xe1a2738e, 0x8840a6c6, 0x238ef17c, + 0xb11ed92d, 0x480946f8 }, + { 0xfd71f119, 0x84c747a8, 0x53eb3695, 0x19e65c5e, 0x6298587a, + 0x0e2f6786, 0xab18d6f4, 0x48a48899, 0xc630b8c0, 0xa1a99024, + 0x2caaf892, 0x84975096, 0xe20fd624, 0xc8869aba, 0x6c2b7dd4, + 0x3b72b04d, 0x0992f7d0, 0xe2775eb6, 0x7d06e684, 0x0089c06e, + 0xe4bbd007, 0xcb3b4361, 0x4ba846e4, 0xa1ae666b, 0x46464d9e, + 0xc01c2eb2, 0xc1f8539f, 0xf86f2be6, 0xcf68afc7, 0x16e8e8ae, + 0xc7386902, 0x8dab61fd }, + { 0xd54d1d45, 0x42a5c903, 0xff4f9ba2, 0xacd4297e, 0x34d478b4, + 0x2d88b520, 0x08c4621a, 0x35b2ba2b, 0x34865402, 0xd3d239bb, + 0x911f32e6, 0x1de76aed, 0x3f06fdc2, 0x877f8bcf, 0x9ec51502, + 0x802714c1, 0xa590700d, 0xa10444eb, 0x31dcc957, 0x8694229f, + 0xb8169fed, 0x5ece77ab, 0x2caf080e, 0x55be8a15, 0xcbd7cef1, + 0x3eb21b14, 0x67b97ee1, 0x9def7ad1, 0x118f690c, 0xe03ca879, + 0xf99b29e7, 0x6f77e62d }, + { 0xe40bbf59, 0xa271bded, 0x6401aad6, 0x177ba453, 0x73541cd1, + 0x1755e035, 0x4b71b02f, 0x3465b466, 0xa813359f, 0x22eb7113, + 0x6f38eac7, 0x9792a8fd, 0xff3bf3b5, 0x11aa012f, 0xf85c3fbf, + 0x99aafabf, 0x06c0cc42, 0x91e0a2ef, 0x773b7b3a, 0x314d5d57, + 0xd669840a, 0xae5e2e76, 0x2e5a8be6, 0x86136073, 0xc1cf5580, + 0xee6d7578, 0x68bed102, 0x2344e00f, 0x8184f0eb, 0x799d7886, + 0xc3d2cf80, 0x63819c91 }, + { 0x7884b073, 0xca5392e1, 0xeb1267ea, 0x9ec3a1fc, 0x907038a7, + 0x3d07f5f0, 0xe4c47b70, 0xcb2ac07c, 0x1bf96b91, 0xf96664ee, + 0x2aea4fbf, 0xebf57589, 0xfade6500, 0x5aabf391, 0x171d1204, + 0xc5b3376f, 0xa0d3d81a, 0x1ff60c51, 0x976a844b, 0x10b2cfe7, + 0xbda6125a, 0xe131cc9a, 0x4ebd453e, 0xe0fc16d3, 0x504b6bc1, + 0xc0d0319a, 0x0a2f8cab, 0xe43a0be7, 0x55e49b47, 0xc80afeec, + 0x8265d7ee, 0x67d48d12 }, + { 0xea2d56d6, 0x068d59a7, 0x27480a63, 0xd71abd0e, 0xae7366cd, + 0x6bd11db0, 0x07204ebc, 0xfbb639ca, 0xf77e6293, 0x89a242e7, + 0x75ba8c3d, 0xdee7ca2b, 0x64a2f9a8, 0x472ddc3d, 0x7561a010, + 0x84229df4, 0xc5b649d4, 0x95f62c85, 0x4dc927cd, 0xfdd56b1b, + 0x5ee60596, 0xfe8bb120, 0xabf29401, 0x3efcaa50, 0x10d1c184, + 0xd4900d0f, 0x28b01df5, 0x2cf113a9, 0x1f0e43f5, 0xa3d7ebc3, + 0xe8384dc7, 0x27950e38 }, + { 0xe1d0fa79, 0xeab21ff0, 0x048b5de9, 0x4b9fd033, 0x2fe374cb, + 0x4c934689, 0x4eb21f6b, 0xbb4827fa, 0xa925e7e7, 0x46716f79, + 0x7dd4c531, 0x1442bf36, 0xd2e96ddf, 0x2073954c, 0x8502aa89, + 0x4e0141ae, 0x8eef6cc9, 0x8ee00e1a, 0x5880cdaf, 0x55ce8491, + 0x69628046, 0xff3aba5c, 0x5d15dfbf, 0x335cc4f8, 0x9f684f25, + 0xa7f0440c, 0xbb1e5bd8, 0xae80453f, 0xff2225ab, 0xa1c99813, + 0x79b25d71, 0x54ff7884 }, + { 0xde40b068, 0x27c6ee30, 0xe6f3a51e, 0x9226465b, 0xfa3b21f6, + 0xe24a4604, 0xc0418115, 0x50a5a5ad, 0x8df90d2b, 0xe3285441, + 0xdcb0c00f, 0xbb74e58f, 0x4a2c08e3, 0xc68f1b3b, 0x0ccd9ec9, + 0x339df081, 0xb786ea9f, 0x915362dc, 0xc955aead, 0x28945e31, + 0x8b6a6c6b, 0xd6a2c01d, 0x3678a427, 0x069e82dc, 0x28c9302c, + 0x17875500, 0x9fa101e6, 0x8acda965, 0xee30b286, 0x4e4e4573, + 0x3f1830fe, 0x8adbad85 }, + { 0x0969d524, 0x060ae11f, 0xf39bcc79, 0xf42fdaf7, 0x7cc1fcc2, + 0x3cec6766, 0xe2336d4f, 0x456b9cf2, 0x8e1c0f7f, 0x6aa1f5de, + 0x0984fb0e, 0xcdbc2ad2, 0x1b464b28, 0x4090cfa6, 0x1243f3ef, + 0x40d86f30, 0xcd5e87e7, 0x95b16ccc, 0x3026cd41, 0x403f168c, + 0x816c0730, 0xdbe386cb, 0x58407a1d, 0x14eb86f3, 0x1717e1af, + 0xf588b4f8, 0x66cbc96c, 0xb75c41a6, 0x027e71c1, 0xf342c1aa, + 0xc0945e5f, 0x73930036 }, + { 0x22cdaf42, 0x954f757d, 0xf4181aab, 0x788b591d, 0xf5514f25, + 0x8b986819, 0xf18fd5bc, 0x69642e08, 0x022ceb91, 0x92b305d1, + 0x6a4f6985, 0x1715903e, 0x61179cae, 0x4bd7d69d, 0xd29c01aa, + 0xdacdfd5d, 0xd91108cc, 0x705ddd5a, 0x64ac8f15, 0x434ac7b1, + 0xb524632f, 0x61a514e1, 0x731fc447, 0x45b9e61b, 0xe0961b31, + 0xcf561348, 0x73eaf223, 0x9c28a967, 0xaa7c99d3, 0x5bd10182, + 0xe42965e2, 0x8bc6ec4a }, + { 0xe7f2a32b, 0xd096e5c0, 0x09388a30, 0xff54800c, 0x401e360c, + 0x06fe437c, 0xbb6054a6, 0x6655fc9c, 0x8457aa6e, 0x510e1860, + 0x2b29b2b7, 0xa0acfca2, 0x51b7da61, 0x732483e3, 0x6be6c8ca, + 0xe31471ee, 0x8b65c9a1, 0xe565431c, 0x48d65cbb, 0xfc9ac3b9, + 0xae9b2aa8, 0xd308fc21, 0xaa60aa6a, 0xd6a7df0d, 0x982fc0d4, + 0x2844d96a, 0x5847a4d7, 0xab012c2c, 0xdceb8955, 0x2b3c8f71, + 0xbe9c7e15, 0x8e85437d }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 32]; + sp_digit tx[2 * 32]; + sp_digit ty[2 * 32]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 32 * 2; + ty = td + 5 * 32 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 32); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 32); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_32(tx, ty, t); + sp_1024_proj_mul_qx1_32(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_32(tx, tx, t); + sp_1024_mont_mul_32(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_32(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + /* t1 = px + py */ + sp_1024_mont_add_32(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_32(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_32(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_32(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_32(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_32(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_32(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_32(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_32(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + + sp_1024_mont_inv_32(t1, p->z, t2); + sp_1024_mont_sqr_32(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_32(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 32); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 32; + sp_digit* pz2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* l = t + 8 * 32; + sp_digit* ty = t + 10 * 32; + + /* v = v^2 */ + sp_1024_proj_sqr_32(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_32(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_32(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_32(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_32(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_32(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_32(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_32(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_32(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* h = t + 8 * 32; + sp_digit* r = t + 10 * 32; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_32(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_32(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_32(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_32(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_32(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_32(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_32(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_32(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_32(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_32(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_32(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_32(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit qx_px[2 * 32]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_32(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + qx_px = td + 8 * 32 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + + sp_1024_mont_add_32(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 32] >> (i % 32)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_32(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_32(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* h = t + 8 * 32; + sp_digit* r = t + 10 * 32; + + /* h = p.z^2 */ + sp_1024_mont_sqr_32(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_32(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_32(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_32(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_32(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_32(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_32(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_32(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_32(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_32(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_32(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_32(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_32(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_32(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_32(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_32(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_32(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_32(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_32(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_32(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_32(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_32(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_32(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_32(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_32(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_32(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_32(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_32(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_32(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_32(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_32(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_32(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 32; + sp_digit* pz2 = t + 2 * 32; + sp_digit* rx = t + 4 * 32; + sp_digit* ry = t + 6 * 32; + sp_digit* l = t + 8 * 32; + sp_digit* ty = t + 10 * 32; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_32(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_32(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_32(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_32(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_32(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_32(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_32(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_32(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_32(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_32(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_32(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_32(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_32(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_32(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_32(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_32(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_32(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_32(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_32(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_32(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_32(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_32(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_32(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_32(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_32(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[64]; + sp_digit (*pre_vy)[64]; + sp_digit (*pre_nvy)[64]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit pre_vx[16][64]; + sp_digit pre_vy[16][64]; + sp_digit pre_nvy[16][64]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_32(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2); + pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2); + pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2); + pre_p = (sp_point_1024*)(td + 56 * 32 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32); + sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32); + sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_32(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_32(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_32(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 32; + sp_digit* t2 = t + 2 * 2 * 32; + sp_digit* l = t + 4 * 2 * 32; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_32(l, py, p1024_mod); + sp_1024_mont_inv_32(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_32(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_32(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_32(t2, t1, p1024_mod); + sp_1024_mont_add_32(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_32(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_32(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_32(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 32); + XMEMCPY(cr, t2, sizeof(sp_digit) * 32); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_32(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 32; + sp_digit* c = t + 2 * 2 * 32; + sp_digit* l = t + 4 * 2 * 32; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_32(l, cx, px, p1024_mod); + sp_1024_mont_inv_32(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_32(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_32(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_32(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_32(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_32(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_32(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 32); + XMEMCPY(cr, c, sizeof(sp_digit) * 32); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_32(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 32; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_32(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_32(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_32(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_32(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 32]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 32 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 32 * 2); +#endif + + sp_1024_point_from_ecc_point_32(p, pm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_32(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_32(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_32(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_32(c, c, t); + sp_1024_mont_map_32(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_32(c, c, &pre_p[j/2], t); + sp_1024_mont_map_32(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_32(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_32(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_32(c, c, neg, t); + sp_1024_mont_map_32(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_32(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_32(c, c, t); + sp_1024_mont_map_32(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(neg, 1, NULL); + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[64]; + sp_digit (*pre_vy)[64]; + sp_digit (*pre_nvy)[64]; +#else + sp_digit t[6 * 2 * 32]; + sp_digit vx[2 * 32]; + sp_digit vy[2 * 32]; + sp_digit pre_vx[16][64]; + sp_digit pre_vy[16][64]; + sp_digit pre_nvy[16][64]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_32(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 32 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 32 * 2; + vy = td + 7 * 32 * 2; + pre_vx = (sp_digit(*)[64])(td + 8 * 32 * 2); + pre_vy = (sp_digit(*)[64])(td + 24 * 32 * 2); + pre_nvy = (sp_digit(*)[64])(td + 40 * 32 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_32(p, pm); + sp_1024_point_from_ecc_point_32(q, qm); + + err = sp_1024_mod_mul_norm_32(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_32(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 32); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 32); + sp_1024_mont_sub_32(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 32); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 32); + sp_1024_accumulate_line_dbl_32(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 32); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 32); + sp_1024_proj_mul_32(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_32(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_32(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 32); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 32); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 32); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_32(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_32(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_32(vx, vy, t); + sp_1024_proj_sqr_32(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_32(vx, vx, t); + sp_1024_mont_mul_32(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 32, 0, sizeof(sp_digit) * 32); + sp_1024_mont_reduce_32(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_32(c, 1, NULL); + sp_1024_point_free_32(q, 1, NULL); + sp_1024_point_free_32(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_32(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] | + a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] | + a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_32(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[32 * 4]; +#endif + sp_digit* t2 = NULL; + int32_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 32; + + sp_1024_sqr_32(t1, point->y); + (void)sp_1024_mod_32(t1, t1, p1024_mod); + sp_1024_sqr_32(t2, point->x); + (void)sp_1024_mod_32(t2, t2, p1024_mod); + sp_1024_mul_32(t2, t2, point->x); + (void)sp_1024_mod_32(t2, t2, p1024_mod); + (void)sp_1024_sub_32(t2, p1024_mod, t2); + sp_1024_mont_add_32(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_32(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_32(t1, p1024_mod); + sp_1024_cond_sub_32(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_32(t1); + if (!sp_1024_iszero_32(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 32, pX); + sp_1024_from_mp(pub->y, 32, pY); + sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_32(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[32]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 32, pX); + sp_1024_from_mp(pub->y, 32, pY); + sp_1024_from_bin(pub->z, 32, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 32, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_32(pub->x) != 0) && + (sp_1024_iszero_32(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_32(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_32(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_32(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_1024_ecc_mulmod_32(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_32(p->x) == 0) || + (sp_1024_iszero_32(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_1024_ecc_mulmod_base_32(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_32(p->x, pub->x) != 0) || + (sp_1024_cmp_32(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* WOLFSSL_SP_ARM_CORTEX_M_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_dsp32.c b/wolfcrypt/src/sp_dsp32.c index 38d6dc721..b132e5a40 100644 --- a/wolfcrypt/src/sp_dsp32.c +++ b/wolfcrypt/src/sp_dsp32.c @@ -1,6 +1,6 @@ /* sp_cdsp_signed.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 0e7ba1132..88dce14fa 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -1,6 +1,6 @@ /* sp_int.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -68,8 +68,8 @@ This library provides single precision (SP) integer math functions. * WOLFSSL_SP_PPC Enable PPC assembly speedups * WOLFSSL_SP_MIPS64 Enable MIPS64 assembly speedups * WOLFSSL_SP_MIPS Enable MIPS assembly speedups - * WOLFSSL_SP_RISCV64 Enable RISCV64 assmebly speedups - * WOLFSSL_SP_RISCV32 Enable RISCV32 assmebly speedups + * WOLFSSL_SP_RISCV64 Enable RISCV64 assembly speedups + * WOLFSSL_SP_RISCV32 Enable RISCV32 assembly speedups * WOLFSSL_SP_S390X Enable S390X assembly speedups * SP_WORD_SIZE Force 32 or 64 bit mode * WOLFSSL_SP_NONBLOCK Enables "non blocking" mode for SP math, which @@ -77,6 +77,11 @@ This library provides single precision (SP) integer math functions. * called again until complete. * WOLFSSL_SP_FAST_NCT_EXPTMOD Enables the faster non-constant time modular * exponentation implementation. + * WOLFSSL_SP_INT_NEGATIVE Enables negative values to be used. + * WOLFSSL_SP_INT_DIGIT_ALIGN Enable when unaligned access of sp_int_digit + * pointer is not allowed. + * WOLFSSL_SP_NO_DYN_STACK Disable use of dynamic stack items. + * Used with small code size and not small stack. */ #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) @@ -91,7 +96,7 @@ This library provides single precision (SP) integer math functions. sp_int* n = NULL #else #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) /* Declare a variable on the stack with the required data size. */ #define DECL_SP_INT(n, s) \ byte n##d[MP_INT_SIZEOF(s)]; \ @@ -161,7 +166,7 @@ This library provides single precision (SP) integer math functions. sp_int* n[c] = { NULL, } #else #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) /* Declare a variable on the stack with the required data size. */ #define DECL_SP_INT_ARRAY(n, s, c) \ byte n##d[MP_INT_SIZEOF(s) * (c)]; \ @@ -202,7 +207,7 @@ This library provides single precision (SP) integer math functions. while (0) #else #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) /* Data declared on stack that supports multiple sp_ints of the * required size. Use pointers into data to make up array and set sizes. */ @@ -2355,7 +2360,7 @@ void sp_forcezero(sp_int* a) } #endif /* !WOLFSSL_RSA_VERIFY_ONLY || !NO_DH || HAVE_ECC */ -#if defined(WOLSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \ +#if defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_DH) || defined(HAVE_ECC) || \ !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) /* Copy value of multi-precision number a into r. * @@ -2364,7 +2369,7 @@ void sp_forcezero(sp_int* a) * * @return MP_OKAY on success. */ -int sp_copy(sp_int* a, sp_int* r) +int sp_copy(const sp_int* a, sp_int* r) { int err = MP_OKAY; @@ -2385,7 +2390,7 @@ int sp_copy(sp_int* a, sp_int* r) } #endif -#if defined(WOLSSL_SP_MATH_ALL) || (defined(HAVE_ECC) && defined(FP_ECC)) +#if defined(WOLFSSL_SP_MATH_ALL) || (defined(HAVE_ECC) && defined(FP_ECC)) /* Initializes r and copies in value from a. * * @param [out] r SP integer - destination. @@ -2404,7 +2409,7 @@ int sp_init_copy(sp_int* r, sp_int* a) } return err; } -#endif /* WOLSSL_SP_MATH_ALL || (HAVE_ECC && FP_ECC) */ +#endif /* WOLFSSL_SP_MATH_ALL || (HAVE_ECC && FP_ECC) */ #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ !defined(NO_DH) || !defined(NO_DSA) @@ -2481,7 +2486,7 @@ int sp_cond_swap_ct(sp_int * a, sp_int * b, int c, int m) } FREE_SP_INT(t, NULL); - return MP_OKAY; + return err; } #endif /* HAVE_ECC && ECC_TIMING_RESISTANT && !WC_NO_CACHE_RESISTANT */ @@ -2602,6 +2607,12 @@ static int _sp_cmp(sp_int* a, sp_int* b) #endif ret = _sp_cmp_abs(a, b); #ifdef WOLFSSL_SP_INT_NEGATIVE + if (a->sign == MP_NEG) { + /* MP_GT = 1, MP_LT = -1, MP_EQ = 0 + * Swapping MP_GT and MP_LT results. + */ + ret = -ret; + } } else if (a->sign > b->sign) { ret = MP_LT; @@ -2686,7 +2697,7 @@ int sp_is_bit_set(sp_int* a, unsigned int b) * * @return The number of bits in the number. */ -int sp_count_bits(sp_int* a) +int sp_count_bits(const sp_int* a) { int r = 0; @@ -2724,7 +2735,8 @@ int sp_count_bits(sp_int* a) #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \ !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) || \ - (defined(HAVE_ECC) && defined(FP_ECC)) + (defined(HAVE_ECC) && defined(FP_ECC)) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Number of entries in array of number of least significant zero bits. */ #define SP_LNZ_CNT 16 @@ -2996,7 +3008,8 @@ int sp_cmp_d(sp_int* a, sp_int_digit d) #endif #if defined(WOLFSSL_SP_INT_NEGATIVE) || !defined(NO_PWDBASED) || \ - defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || (!defined(NO_RSA) && \ + defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || \ + ((defined(WOLFSSL_SP_MATH_ALL) || !defined(NO_RSA)) && \ !defined(WOLFSSL_RSA_VERIFY_ONLY)) /* Add a one digit number to the multi-precision number. * @@ -3104,25 +3117,33 @@ int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r) { int err = MP_OKAY; + /* Check validity of parameters. */ if ((a == NULL) || (r == NULL)) { err = MP_VAL; } else { #ifndef WOLFSSL_SP_INT_NEGATIVE + /* Positive only so just use internal function. */ err = _sp_add_d(a, d, r); #else if (a->sign == MP_ZPOS) { + /* Positive so use interal function. */ r->sign = MP_ZPOS; err = _sp_add_d(a, d, r); } else if ((a->used > 1) || (a->dp[0] > d)) { + /* Negative value bigger than digit so subtract digit. */ r->sign = MP_NEG; _sp_sub_d(a, d, r); } else { + /* Negative value smaller or equal to digit. */ r->sign = MP_ZPOS; + /* Subtract negative value from digit. */ r->dp[0] = d - a->dp[0]; + /* Result is a digit equal to or greater than zero. */ + r->used = ((r->dp[0] == 0) ? 0 : 1); } #endif } @@ -3146,25 +3167,32 @@ int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r) { int err = MP_OKAY; + /* Check validity of parameters. */ if ((a == NULL) || (r == NULL)) { err = MP_VAL; } else { #ifndef WOLFSSL_SP_INT_NEGATIVE + /* Positive only so just use internal function. */ _sp_sub_d(a, d, r); #else if (a->sign == MP_NEG) { + /* Subtracting from negative use interal add. */ r->sign = MP_NEG; err = _sp_add_d(a, d, r); } else if ((a->used > 1) || (a->dp[0] >= d)) { + /* Positive number greater than digit so add digit. */ r->sign = MP_ZPOS; _sp_sub_d(a, d, r); } else { + /* Negative value smaller than digit. */ r->sign = MP_NEG; + /* Subtract positive value from digit. */ r->dp[0] = d - a->dp[0]; - r->used = r->dp[0] > 0; + /* Result is a digit equal to or greater than zero. */ + r->used = 1; } #endif } @@ -3439,7 +3467,8 @@ static void _sp_div_10(sp_int* a, sp_int* r, sp_int_digit* rem) #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ defined(WOLFSSL_HAVE_SP_DH) || \ - (defined(HAVE_ECC) && (defined(FP_ECC) || defined(HAVE_COMP_KEY))) + (defined(HAVE_ECC) && (defined(FP_ECC) || defined(HAVE_COMP_KEY))) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Divide by small number: r = a / d and rem = a % d * * @param [in] a SP integer to be divided. @@ -3487,7 +3516,7 @@ static void _sp_div_small(sp_int* a, sp_int_digit d, sp_int* r, #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) -/* Divide a multi-precision number by a digit size number and calcualte +/* Divide a multi-precision number by a digit size number and calculate * remainder. * r = a / d; rem = a % d * @@ -3557,7 +3586,8 @@ int sp_div_d(sp_int* a, sp_int_digit d, sp_int* r, sp_int_digit* rem) #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ defined(WOLFSSL_HAVE_SP_DH) || \ - (defined(HAVE_ECC) && (defined(FP_ECC) || defined(HAVE_COMP_KEY))) + (defined(HAVE_ECC) && (defined(FP_ECC) || defined(HAVE_COMP_KEY))) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Calculate a modulo the digit d into r: r = a mod d * * @param [in] a SP integer to reduce. @@ -3958,7 +3988,8 @@ int sp_sub(sp_int* a, sp_int* b, sp_int* r) ****************************/ #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ - (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) + (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) || \ + defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) /* Add two value and reduce: r = (a + b) % m * * @param [in] a SP integer to add. @@ -4002,7 +4033,8 @@ int sp_addmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r) FREE_SP_INT(t, NULL); return err; } -#endif /* WOLFSSL_SP_MATH_ALL || (!WOLFSSL_SP_MATH && WOLFSSL_CUSTOM_CURVES) */ +#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_CUSTOM_CURVES) || + * WOLFCRYPT_HAVE_ECCSI || WOLFCRYPT_HAVE_SAKKE */ #if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) /* Sub b from a and reduce: r = (a - b) % m @@ -4142,7 +4174,7 @@ static int sp_cmp_mag_ct(sp_int* a, sp_int* b, int len) #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) /* Add two value and reduce: r = (a + b) % m * - * r = a + b (mod m) - constant time (|a| < m and |b| < m and positive) + * r = a + b (mod m) - constant time (a < m and b < m, a, b and m are positive) * * Assumes a, b, m and r are not NULL. * @@ -4193,7 +4225,7 @@ int sp_addmod_ct(sp_int* a, sp_int* b, sp_int* m, sp_int* r) /* Sub b from a and reduce: r = (a - b) % m * Result is always positive. * - * r = a - b (mod m) - constant time (a < n and b < m and positive) + * r = a - b (mod m) - constant time (a < m and b < m, a, b and m are positive) * * Assumes a, b, m and r are not NULL. * @@ -4482,7 +4514,7 @@ int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem) if (r != NULL) { sp_set(r, 1); #ifdef WOLFSSL_SP_INT_NEGATIVE - r->sign = aSign; + r->sign = (aSign == dSign) ? MP_ZPOS : MP_NEG; #endif /* WOLFSSL_SP_INT_NEGATIVE */ } done = 1; @@ -4491,11 +4523,14 @@ int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem) /* a is greater than d but same bit length */ if (rem != NULL) { _sp_sub_off(a, d, rem, 0); + #ifdef WOLFSSL_SP_INT_NEGATIVE + rem->sign = aSign; + #endif } if (r != NULL) { sp_set(r, 1); #ifdef WOLFSSL_SP_INT_NEGATIVE - r->sign = aSign; + r->sign = (aSign == dSign) ? MP_ZPOS : MP_NEG; #endif /* WOLFSSL_SP_INT_NEGATIVE */ } done = 1; @@ -4681,7 +4716,7 @@ int sp_mod(sp_int* a, sp_int* m, sp_int* r) { int err = MP_OKAY; #ifdef WOLFSSL_SP_INT_NEGATIVE - DECL_SP_INT(t, (m == NULL) ? 1 : m->used); + DECL_SP_INT(t, (a == NULL) ? 1 : a->used + 1); #endif /* WOLFSSL_SP_INT_NEGATIVE */ if ((a == NULL) || (m == NULL) || (r == NULL)) { @@ -4693,13 +4728,13 @@ int sp_mod(sp_int* a, sp_int* m, sp_int* r) err = sp_div(a, m, NULL, r); } #else - ALLOC_SP_INT(t, m->used, err, NULL); + ALLOC_SP_INT(t, a->used + 1, err, NULL); if (err == MP_OKAY) { - sp_init_size(t, m->used); + sp_init_size(t, a->used + 1); err = sp_div(a, m, NULL, t); } if (err == MP_OKAY) { - if (t->sign != m->sign) { + if ((!sp_iszero(t)) && (t->sign != m->sign)) { err = sp_add(t, m, r); } else { @@ -4744,7 +4779,8 @@ int sp_mod(sp_int* a, sp_int* m, sp_int* r) int k; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; - #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && defined(WOLFSSL_SP_SMALL) + #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used * 2]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -4820,7 +4856,8 @@ int sp_mod(sp_int* a, sp_int* m, sp_int* r) int k; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; - #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && defined(WOLFSSL_SP_SMALL) + #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used + b->used]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -4897,7 +4934,8 @@ int sp_mod(sp_int* a, sp_int* m, sp_int* r) int k; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; - #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && defined(WOLFSSL_SP_SMALL) + #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used + b->used]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -7676,7 +7714,9 @@ int sp_mul(sp_int* a, sp_int* b, sp_int* r) } /* END SP_MUL implementations. */ -#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) +#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFCRYPT_HAVE_ECCSI) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Multiply a by b mod m and store in r: r = (a * b) mod m * * @param [in] a SP integer to multiply. @@ -8013,7 +8053,7 @@ static int _sp_exptmod_ex(sp_int* b, sp_int* e, int bits, sp_int* m, sp_int* r) #endif /* Ensure base is less than exponent. */ - if (_sp_cmp(b, m) != MP_LT) { + if (_sp_cmp_abs(b, m) != MP_LT) { err = sp_mod(b, m, t[0]); if ((err == MP_OKAY) && sp_iszero(t[0])) { sp_set(r, 0); @@ -8113,7 +8153,7 @@ static int _sp_exptmod_mont_ex(sp_int* b, sp_int* e, int bits, sp_int* m, sp_init_size(t[3], m->used * 2 + 1); /* Ensure base is less than exponent. */ - if (_sp_cmp(b, m) != MP_LT) { + if (_sp_cmp_abs(b, m) != MP_LT) { err = sp_mod(b, m, t[0]); if ((err == MP_OKAY) && sp_iszero(t[0])) { sp_set(r, 0); @@ -8248,7 +8288,7 @@ static int _sp_exptmod_mont_ex(sp_int* b, sp_int* e, int bits, sp_int* m, sp_init_size(tr, m->used * 2 + 1); /* Ensure base is less than exponent. */ - if (_sp_cmp(b, m) != MP_LT) { + if (_sp_cmp_abs(b, m) != MP_LT) { err = sp_mod(b, m, t[1]); if ((err == MP_OKAY) && sp_iszero(t[1])) { sp_set(r, 0); @@ -8524,7 +8564,8 @@ static int _sp_exptmod_base_2(sp_int* e, int digits, sp_int* m, sp_int* r) #endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */ #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) + defined(WOLFSSL_HAVE_SP_DH) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m * * @param [in] b SP integer that is the base. @@ -8586,8 +8627,8 @@ int sp_exptmod_ex(sp_int* b, sp_int* e, int digits, sp_int* m, sp_int* r) if ((!done) && (err == MP_OKAY)) { /* Use code optimized for specific sizes if possible */ -#if defined(WOLFSSL_SP_MATH_ALL) && (defined(WOLFSSL_HAVE_SP_RSA) || \ - defined(WOLFSSL_HAVE_SP_DH)) +#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \ + (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) #ifndef WOLFSSL_SP_NO_2048 if ((mBits == 1024) && sp_isodd(m) && (bBits <= 1024) && (eBits <= 1024)) { @@ -8670,7 +8711,8 @@ int sp_exptmod_ex(sp_int* b, sp_int* e, int digits, sp_int* m, sp_int* r) #endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH */ #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) + defined(WOLFSSL_HAVE_SP_DH) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m * * @param [in] b SP integer that is the base. @@ -8767,7 +8809,7 @@ static int _sp_exptmod_nct(sp_int* b, sp_int* e, sp_int* m, sp_int* r) sp_init_size(bm, m->used * 2 + 1); /* Ensure base is less than exponent. */ - if (_sp_cmp(b, m) != MP_LT) { + if (_sp_cmp_abs(b, m) != MP_LT) { err = sp_mod(b, m, bm); if ((err == MP_OKAY) && sp_iszero(bm)) { sp_set(r, 0); @@ -8844,7 +8886,7 @@ static int _sp_exptmod_nct(sp_int* b, sp_int* e, sp_int* m, sp_int* r) /* Sqaure until we find bit that is 1 or there's less than a * window of bits left. */ - while ((i >= 0) || (c >= winBits)) { + while (err == MP_OKAY && ((i >= 0) || (c >= winBits))) { sp_digit n2 = n; int c2 = c; int i2 = i; @@ -8980,7 +9022,7 @@ static int _sp_exptmod_nct(sp_int* b, sp_int* e, sp_int* m, sp_int* r) sp_init_size(t[1], m->used * 2 + 1); /* Ensure base is less than exponent. */ - if (_sp_cmp(b, m) != MP_LT) { + if (_sp_cmp_abs(b, m) != MP_LT) { err = sp_mod(b, m, t[0]); if ((err == MP_OKAY) && sp_iszero(t[0])) { sp_set(r, 0); @@ -9275,7 +9317,7 @@ int sp_mul_2d(sp_int* a, int e, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used * 2]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -9384,7 +9426,7 @@ int sp_mul_2d(sp_int* a, int e, sp_int* r) #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_int_digit* t = NULL; #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - defined(WOLFSSL_SP_SMALL) + defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_DYN_STACK) sp_int_digit t[a->used * 2]; #else sp_int_digit t[SP_INT_DIGITS]; @@ -11664,7 +11706,8 @@ int sp_sqrmod(sp_int* a, sp_int* m, sp_int* r) * Montogmery functions **********************/ -#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) +#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) /* Reduce a number in montgomery form. * * Assumes a and m are not NULL and m is not 0. @@ -12060,7 +12103,8 @@ int sp_mont_norm(sp_int* norm, sp_int* m) return err; } -#endif +#endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH || + * WOLFCRYPT_HAVE_ECCSI || WOLFCRYPT_HAVE_SAKKE */ /********************************* * To and from binary and strings. @@ -12075,7 +12119,7 @@ int sp_mont_norm(sp_int* norm, sp_int* m) * * @return The count of 8-bit values. */ -int sp_unsigned_bin_size(sp_int* a) +int sp_unsigned_bin_size(const sp_int* a) { int cnt = 0; @@ -12115,9 +12159,29 @@ int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz) int j; int s; + #ifndef WOLFSSL_SP_INT_DIGIT_ALIGN for (i = inSz-1,j = 0; i > SP_WORD_SIZEOF-1; i -= SP_WORD_SIZEOF,j++) { a->dp[j] = *(sp_int_digit*)(in + i - (SP_WORD_SIZEOF - 1)); } + #else + for (i = inSz-1, j = 0; i >= SP_WORD_SIZEOF - 1; i -= SP_WORD_SIZEOF) { + a->dp[j] = ((sp_int_digit)in[i - 0] << 0); + #if SP_WORD_SIZE >= 16 + a->dp[j] |= ((sp_int_digit)in[i - 1] << 8); + #endif + #if SP_WORD_SIZE >= 32 + a->dp[j] |= ((sp_int_digit)in[i - 2] << 16) | + ((sp_int_digit)in[i - 3] << 24); + #endif + #if SP_WORD_SIZE >= 64 + a->dp[j] |= ((sp_int_digit)in[i - 4] << 32) | + ((sp_int_digit)in[i - 5] << 40) | + ((sp_int_digit)in[i - 6] << 48) | + ((sp_int_digit)in[i - 7] << 56); + #endif + j++; + } + #endif a->dp[j] = 0; for (s = 0; i >= 0; i--,s += 8) { a->dp[j] |= ((sp_int_digit)in[i]) << s; @@ -12238,7 +12302,7 @@ int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz) return err; } -#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) +#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) /* Store the number in big-endian format in array at an offset. * The array must be large enough for encoded number - use mp_unsigned_bin_size * to calculate the number of bytes required. @@ -12260,10 +12324,10 @@ int sp_to_unsigned_bin_at_pos(int o, sp_int*a, unsigned char* out) return ret; } -#endif /* WOLFSSL_SP_MATH_ALL */ +#endif /* WOLFSSL_SP_MATH_ALL && !NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY */ -#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ - defined(HAVE_ECC) +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + defined(HAVE_ECC) || !defined(NO_DSA) /* Convert hexadecimal number as string in big-endian format to a * multi-precision number. * @@ -12336,9 +12400,9 @@ static int _sp_read_radix_16(sp_int* a, const char* in) } return err; } -#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || HAVE_ECC */ +#endif /* (WOLFSSL_SP_MATH_ALL && !NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) || HAVE_ECC */ -#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) +#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) /* Convert decimal number as string in big-endian format to a multi-precision * number. * @@ -12395,10 +12459,10 @@ static int _sp_read_radix_10(sp_int* a, const char* in) return err; } -#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */ +#endif /* WOLFSSL_SP_MATH_ALL && !NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY */ -#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ - defined(HAVE_ECC) +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + defined(HAVE_ECC) || !defined(NO_DSA) /* Convert a number as string in big-endian format to a big number. * Only supports base-16 (hexadecimal) and base-10 (decimal). * @@ -12430,7 +12494,7 @@ int sp_read_radix(sp_int* a, const char* in, int radix) if (radix == 16) { err = _sp_read_radix_16(a, in); } - #if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) + #if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY) else if (radix == 10) { err = _sp_read_radix_10(a, in); } @@ -12442,7 +12506,7 @@ int sp_read_radix(sp_int* a, const char* in, int radix) return err; } -#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || HAVE_ECC */ +#endif /* (WOLFSSL_SP_MATH_ALL && !NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) || HAVE_ECC */ #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ defined(WC_MP_TO_RADIX) @@ -12491,6 +12555,7 @@ int sp_tohex(sp_int* a, char* str) i = a->used - 1; #ifndef WC_DISABLE_RADIX_ZERO_PAD + /* Find highest non-zero byte in most-significant word. */ for (j = SP_WORD_SIZE - 8; j >= 0; j -= 8) { if (((a->dp[i] >> j) & 0xff) != 0) { break; @@ -12500,8 +12565,10 @@ int sp_tohex(sp_int* a, char* str) --i; } } + /* Start with high nibble of byte. */ j += 4; #else + /* Find highest non-zero nibble in most-significant word. */ for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) { if (((a->dp[i] >> j) & 0xf) != 0) { break; @@ -12512,6 +12579,7 @@ int sp_tohex(sp_int* a, char* str) } } #endif /* WC_DISABLE_RADIX_ZERO_PAD */ + /* Most-significant word. */ for (; j >= 0; j -= 4) { *(str++) = sp_hex_char[(a->dp[i] >> j) & 0xf]; } @@ -12660,16 +12728,16 @@ int sp_radix_size(sp_int* a, int radix, int* size) } else { int nibbles = (sp_count_bits(a) + 3) / 4; - #ifdef WOLFSSL_SP_INT_NEGATIVE - if (a->sign == MP_NEG) { - nibbles++; - } - #endif /* WOLFSSL_SP_INT_NEGATIVE */ #ifndef WC_DISABLE_RADIX_ZERO_PAD if (nibbles & 1) { nibbles++; } #endif /* WC_DISABLE_RADIX_ZERO_PAD */ + #ifdef WOLFSSL_SP_INT_NEGATIVE + if (a->sign == MP_NEG) { + nibbles++; + } + #endif /* WOLFSSL_SP_INT_NEGATIVE */ /* One more for \0 */ *size = nibbles + 1; } @@ -12835,7 +12903,8 @@ int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap) #endif /* WOLFSSL_KEY_GEN && (!NO_DH || !NO_DSA) && !WC_NO_RNG */ #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \ - !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) || \ + (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) /* Miller-Rabin test of "a" to the base of "b" as described in * HAC pp. 139 Algorithm 4.24 * @@ -13230,10 +13299,11 @@ int sp_prime_is_prime_ex(sp_int* a, int t, int* result, WC_RNG* rng) } #endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_HAVE_SP_DH */ -#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ - defined(WOLFSSL_HAVE_SP_DH) || (defined(HAVE_ECC) && defined(FP_ECC)) +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* Calculates the Greatest Common Denominator (GCD) of a and b into r. + * + * a and b are positive integers. * * @param [in] a SP integer of first operand. * @param [in] b SP integer of second operand. @@ -13251,6 +13321,7 @@ int sp_gcd(sp_int* a, sp_int* b, sp_int* r) err = MP_VAL; } else if (sp_iszero(a)) { + /* GCD of 0 and 0 is undefined as all integers divide 0. */ if (sp_iszero(b)) { err = MP_VAL; } @@ -13337,12 +13408,13 @@ int sp_gcd(sp_int* a, sp_int* b, sp_int* r) return err; } -#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_SP_RSA_VERIFY_ONLY) || - * WOLFSSL_HAVE_SP_DH || (HAVE_ECC && FP_ECC) */ +#endif /* WOLFSSL_SP_MATH_ALL && !NO_RSA && WOLFSSL_KEY_GEN */ -#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) +#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* Calculates the Lowest Common Multiple (LCM) of a and b and stores in r. + * + * a and b are positive integers. * * @param [in] a SP integer of first operand. * @param [in] b SP integer of second operand. @@ -13362,6 +13434,10 @@ int sp_lcm(sp_int* a, sp_int* b, sp_int* r) if ((a == NULL) || (b == NULL) || (r == NULL)) { err = MP_VAL; } + + /* LCM of 0 and any number is undefined as 0 is not in the set of values + * being used. + */ if ((err == MP_OKAY) && (mp_iszero(a) || mp_iszero(b))) { err = MP_VAL; } @@ -13393,7 +13469,7 @@ int sp_lcm(sp_int* a, sp_int* b, sp_int* r) return err; } -#endif /* !NO_RSA && WOLFSSL_KEY_GEN */ +#endif /* WOLFSSL_SP_MATH_ALL && !NO_RSA && WOLFSSL_KEY_GEN */ /* Returns the run time settings. * diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index f9ebbfe32..c51d73769 100644 --- a/wolfcrypt/src/sp_x86_64.c +++ b/wolfcrypt/src/sp_x86_64.c @@ -1,6 +1,6 @@ /* sp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -60,12 +60,15 @@ extern void sp_2048_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); */ static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_2048_from_bin_movbe(r, size, a, n); } - else { + else +#endif + { sp_2048_from_bin_bswap(r, size, a, n); } } @@ -87,7 +90,8 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -121,7 +125,9 @@ static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -162,12 +168,15 @@ extern void sp_2048_to_bin_movbe(sp_digit* r, byte* a); */ static void sp_2048_to_bin(sp_digit* r, byte* a) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_2048_to_bin_movbe(r, a); } - else { + else +#endif + { sp_2048_to_bin_bswap(r, a); } } @@ -184,16 +193,13 @@ extern void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b); extern sp_digit sp_2048_dbl_16(sp_digit* r, const sp_digit* a); extern void sp_2048_sqr_32(sp_digit* r, const sp_digit* a); -#ifdef HAVE_INTEL_AVX2 extern void sp_2048_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b); -#endif /* HAVE_INTEL_AVX2 */ -#ifdef HAVE_INTEL_AVX2 extern void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a); -#endif /* HAVE_INTEL_AVX2 */ #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +extern sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b); +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -202,7 +208,8 @@ extern void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a); */ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -212,12 +219,11 @@ static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**64 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } extern void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b); #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -extern sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b); /* r = 2^n mod m where n is the number of bits to reduce by. * Given m must be 2048 bits, just need to subtract. * @@ -243,8 +249,8 @@ extern void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, sp_digit mp); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_16(r, a, b); sp_2048_mont_reduce_16(r, m, mp); @@ -257,8 +263,8 @@ static void sp_2048_mont_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_16(r, a); sp_2048_mont_reduce_16(r, m, mp); @@ -267,6 +273,27 @@ static void sp_2048_mont_sqr_16(sp_digit* r, const sp_digit* a, const sp_digit* extern sp_digit sp_2048_cond_sub_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a, sp_digit b); extern void sp_2048_mul_d_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_2048_word_asm_16(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_2048_word_asm_16(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -286,6 +313,7 @@ static WC_INLINE sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -329,8 +357,10 @@ extern int64_t sp_2048_cmp_16(const sp_digit* a, const sp_digit* b); static WC_INLINE int sp_2048_div_16(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[32], t2[17]; - sp_digit div, r1; + sp_digit t1[32]; + sp_digit t2[17]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -383,7 +413,8 @@ static WC_INLINE int sp_2048_div_16(const sp_digit* a, const sp_digit* d, sp_dig * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_2048_mod_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_2048_mod_16(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_2048_div_16(a, m, NULL, r); } @@ -406,13 +437,14 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(33 * 32) + 32]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -499,34 +531,34 @@ static int sp_2048_mod_exp_16(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 16); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -572,8 +604,8 @@ extern void sp_2048_mont_reduce_avx2_16(sp_digit* a, const sp_digit* m, sp_digit * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_avx2_16(r, a, b); sp_2048_mont_reduce_avx2_16(r, m, mp); @@ -588,8 +620,8 @@ static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_di * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_avx2_16(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_avx2_16(r, a); sp_2048_mont_reduce_avx2_16(r, m, mp); @@ -615,13 +647,14 @@ static int sp_2048_mod_exp_avx2_16(sp_digit* r, const sp_digit* a, const sp_digi sp_digit td[(33 * 32) + 32]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -708,34 +741,34 @@ static int sp_2048_mod_exp_avx2_16(sp_digit* r, const sp_digit* a, const sp_digi if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 16); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -771,7 +804,7 @@ static int sp_2048_mod_exp_avx2_16(sp_digit* r, const sp_digit* a, const sp_digi } #endif /* HAVE_INTEL_AVX2 */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -788,7 +821,7 @@ static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m) sp_2048_sub_in_place_32(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ extern sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp); /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -800,8 +833,8 @@ extern void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_32(r, a, b); sp_2048_mont_reduce_32(r, m, mp); @@ -814,8 +847,8 @@ static void sp_2048_mont_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_32(r, a); sp_2048_mont_reduce_32(r, m, mp); @@ -824,6 +857,27 @@ static void sp_2048_mont_sqr_32(sp_digit* r, const sp_digit* a, const sp_digit* #if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) extern sp_digit sp_2048_cond_sub_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_2048_mul_d_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_2048_word_asm_32(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_2048_word_asm_32(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -843,6 +897,7 @@ static WC_INLINE sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -886,8 +941,10 @@ extern int64_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b); static WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[64], t2[33]; - sp_digit div, r1; + sp_digit t1[64]; + sp_digit t2[33]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -940,7 +997,8 @@ static WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_dig * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_2048_div_32(a, m, NULL, r); } @@ -959,8 +1017,10 @@ extern sp_digit sp_2048_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b static WC_INLINE int sp_2048_div_32_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[64], t2[33]; - sp_digit div, r1; + sp_digit t1[64]; + sp_digit t2[33]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -1017,7 +1077,8 @@ static WC_INLINE int sp_2048_div_32_cond(const sp_digit* a, const sp_digit* d, s * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_2048_div_32_cond(a, m, NULL, r); } @@ -1041,13 +1102,14 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(33 * 64) + 64]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -1134,34 +1196,34 @@ static int sp_2048_mod_exp_32(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -1208,8 +1270,8 @@ extern void sp_2048_mont_reduce_avx2_32(sp_digit* a, const sp_digit* m, sp_digit * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_2048_mul_avx2_32(r, a, b); sp_2048_mont_reduce_avx2_32(r, m, mp); @@ -1224,8 +1286,8 @@ static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_di * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_2048_mont_sqr_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_2048_mont_sqr_avx2_32(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_2048_sqr_avx2_32(r, a); sp_2048_mont_reduce_avx2_32(r, m, mp); @@ -1252,13 +1314,14 @@ static int sp_2048_mod_exp_avx2_32(sp_digit* r, const sp_digit* a, const sp_digi sp_digit td[(33 * 64) + 64]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -1345,34 +1408,34 @@ static int sp_2048_mod_exp_avx2_32(sp_digit* r, const sp_digit* a, const sp_digi if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 32); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -1422,16 +1485,15 @@ static int sp_2048_mod_exp_avx2_32(sp_digit* r, const sp_digit* a, const sp_digi * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[64], md[32], rd[64]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; #else - sp_digit* d = NULL; + sp_digit a[32 * 5]; #endif - sp_digit* a; - sp_digit *ah; + sp_digit* ah; sp_digit* m; sp_digit* r; sp_digit e = 0; @@ -1451,28 +1513,20 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 32 * 2; - m = r + 32 * 2; - ah = a + 32; - } -#else - a = ad; - m = md; - r = rd; - ah = a + 32; #endif if (err == MP_OKAY) { + r = a + 32 * 2; + m = r + 32 * 2; + ah = a + 32; + sp_2048_from_bin(ah, 32, in, inLen); #if DIGIT_BIT >= 64 e = em->dp[0]; @@ -1569,9 +1623,9 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -1595,17 +1649,17 @@ int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm,const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { -#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) - sp_digit a[64], d[32], m[32]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[32 * 4]; +#endif sp_digit* a; sp_digit* m; -#endif sp_digit* r; int err = MP_OKAY; @@ -1633,7 +1687,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, } } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, NULL, DYNAMIC_TYPE_RSA); @@ -1644,10 +1698,9 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) a = d + 32; m = a + 64; -#endif + r = a; sp_2048_from_bin(a, 32, in, inLen); @@ -1661,14 +1714,16 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 32); - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(d, 0, sizeof(sp_digit) * 32); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) #endif + { + /* only zeroing private "d" */ + ForceZero(d, sizeof(sp_digit) * 32); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; } @@ -1693,18 +1748,15 @@ extern sp_digit sp_2048_cond_add_avx2_16(sp_digit* r, const sp_digit* a, const s * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[32 * 2]; - sp_digit pd[16], qd[16], dpd[16]; - sp_digit tmpad[32], tmpbd[32]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; #else - sp_digit* t = NULL; + sp_digit a[16 * 11]; #endif - sp_digit* a; sp_digit* p; sp_digit* q; sp_digit* dp; @@ -1732,33 +1784,23 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 32 * 2; q = p + 16; qi = dq = dp = q + 16; tmpa = qi + 16; tmpb = tmpa + 32; + r = a + 32; - r = t + 32; - } -#else - r = a = ad; - p = pd; - q = qd; - qi = dq = dp = dpd; - tmpa = tmpad; - tmpb = tmpbd; -#endif - - if (err == MP_OKAY) { sp_2048_from_bin(a, 32, in, inLen); sp_2048_from_mp(p, 16, pm); sp_2048_from_mp(q, 16, qm); @@ -1825,22 +1867,19 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, *outLen = 256; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpad, 0, sizeof(tmpad)); - XMEMSET(tmpbd, 0, sizeof(tmpbd)); - XMEMSET(pd, 0, sizeof(pd)); - XMEMSET(qd, 0, sizeof(qd)); - XMEMSET(dpd, 0, sizeof(dpd)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 16 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; } -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */ #endif /* WOLFSSL_HAVE_SP_RSA */ #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ !defined(WOLFSSL_RSA_PUBLIC_ONLY)) @@ -1860,17 +1899,19 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = 32; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 32; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -1883,14 +1924,16 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 32; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -1917,10 +1960,13 @@ static int sp_2048_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -1980,10 +2026,12 @@ static int sp_2048_mod_exp_2_avx2_32(sp_digit* r, const sp_digit* e, int bits, sp_digit* norm; sp_digit* tmp; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -2022,34 +2070,34 @@ static int sp_2048_mod_exp_2_avx2_32(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } sp_2048_lshift_32(r, norm, y); - for (; i>=0 || c>=6; ) { + while ((i >= 0) || (c >= 6)) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -2103,10 +2151,12 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, sp_digit* norm; sp_digit* tmp; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -2145,34 +2195,34 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } sp_2048_lshift_32(r, norm, y); - for (; i>=0 || c>=6; ) { + while ((i >= 0) || (c >= 6)) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -2220,11 +2270,13 @@ static int sp_2048_mod_exp_2_32(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[64], e[32], m[32]; + sp_digit b[64]; + sp_digit e[32]; + sp_digit m[32]; sp_digit* r = b; word32 i; #ifdef HAVE_INTEL_AVX2 @@ -2269,6 +2321,7 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, sp_2048_to_bin(r, out); *outLen = 256; for (i=0; i<256 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -2288,10 +2341,13 @@ int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[32], e[16], m[16]; + sp_digit b[32]; + sp_digit e[16]; + sp_digit m[16]; sp_digit* r = b; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -2329,7 +2385,7 @@ int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_2048 */ @@ -2345,12 +2401,15 @@ extern void sp_3072_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); */ static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_3072_from_bin_movbe(r, size, a, n); } - else { + else +#endif + { sp_3072_from_bin_bswap(r, size, a, n); } } @@ -2372,7 +2431,8 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -2406,7 +2466,9 @@ static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -2447,12 +2509,15 @@ extern void sp_3072_to_bin_movbe(sp_digit* r, byte* a); */ static void sp_3072_to_bin(sp_digit* r, byte* a) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_3072_to_bin_movbe(r, a); } - else { + else +#endif + { sp_3072_to_bin_bswap(r, a); } } @@ -2469,13 +2534,9 @@ extern void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b); extern sp_digit sp_3072_dbl_12(sp_digit* r, const sp_digit* a); extern void sp_3072_sqr_24(sp_digit* r, const sp_digit* a); -#ifdef HAVE_INTEL_AVX2 extern void sp_3072_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b); -#endif /* HAVE_INTEL_AVX2 */ -#ifdef HAVE_INTEL_AVX2 extern void sp_3072_sqr_avx2_24(sp_digit* r, const sp_digit* a); -#endif /* HAVE_INTEL_AVX2 */ extern sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b); extern sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b); @@ -2484,16 +2545,12 @@ extern void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b); extern sp_digit sp_3072_dbl_24(sp_digit* r, const sp_digit* a); extern void sp_3072_sqr_48(sp_digit* r, const sp_digit* a); -#ifdef HAVE_INTEL_AVX2 extern void sp_3072_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b); -#endif /* HAVE_INTEL_AVX2 */ -#ifdef HAVE_INTEL_AVX2 extern void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a); -#endif /* HAVE_INTEL_AVX2 */ #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -2502,7 +2559,8 @@ extern void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a); */ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -2512,7 +2570,7 @@ static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**64 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } extern void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b); @@ -2542,8 +2600,8 @@ extern void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, sp_digit mp); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_24(r, a, b); sp_3072_mont_reduce_24(r, m, mp); @@ -2556,8 +2614,8 @@ static void sp_3072_mont_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_24(r, a); sp_3072_mont_reduce_24(r, m, mp); @@ -2566,6 +2624,27 @@ static void sp_3072_mont_sqr_24(sp_digit* r, const sp_digit* a, const sp_digit* extern sp_digit sp_3072_cond_sub_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a, sp_digit b); extern void sp_3072_mul_d_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_3072_word_asm_24(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_3072_word_asm_24(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -2585,6 +2664,7 @@ static WC_INLINE sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -2628,8 +2708,10 @@ extern int64_t sp_3072_cmp_24(const sp_digit* a, const sp_digit* b); static WC_INLINE int sp_3072_div_24(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[48], t2[25]; - sp_digit div, r1; + sp_digit t1[48]; + sp_digit t2[25]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -2682,7 +2764,8 @@ static WC_INLINE int sp_3072_div_24(const sp_digit* a, const sp_digit* d, sp_dig * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_3072_mod_24(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_3072_mod_24(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_3072_div_24(a, m, NULL, r); } @@ -2705,13 +2788,14 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(33 * 48) + 48]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -2798,34 +2882,34 @@ static int sp_3072_mod_exp_24(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 24); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -2871,8 +2955,8 @@ extern void sp_3072_mont_reduce_avx2_24(sp_digit* a, const sp_digit* m, sp_digit * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_avx2_24(r, a, b); sp_3072_mont_reduce_avx2_24(r, m, mp); @@ -2887,8 +2971,8 @@ static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_di * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_avx2_24(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_avx2_24(r, a); sp_3072_mont_reduce_avx2_24(r, m, mp); @@ -2914,13 +2998,14 @@ static int sp_3072_mod_exp_avx2_24(sp_digit* r, const sp_digit* a, const sp_digi sp_digit td[(33 * 48) + 48]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -3007,34 +3092,34 @@ static int sp_3072_mod_exp_avx2_24(sp_digit* r, const sp_digit* a, const sp_digi if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 24); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -3070,7 +3155,7 @@ static int sp_3072_mod_exp_avx2_24(sp_digit* r, const sp_digit* a, const sp_digi } #endif /* HAVE_INTEL_AVX2 */ -#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ +#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) /* r = 2^n mod m where n is the number of bits to reduce by. @@ -3087,7 +3172,7 @@ static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m) sp_3072_sub_in_place_48(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ extern sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp); /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -3099,8 +3184,8 @@ extern void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_48(r, a, b); sp_3072_mont_reduce_48(r, m, mp); @@ -3113,8 +3198,8 @@ static void sp_3072_mont_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_48(r, a); sp_3072_mont_reduce_48(r, m, mp); @@ -3123,6 +3208,27 @@ static void sp_3072_mont_sqr_48(sp_digit* r, const sp_digit* a, const sp_digit* #if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) extern sp_digit sp_3072_cond_sub_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_3072_mul_d_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_3072_word_asm_48(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_3072_word_asm_48(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -3142,6 +3248,7 @@ static WC_INLINE sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -3185,8 +3292,10 @@ extern int64_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b); static WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[96], t2[49]; - sp_digit div, r1; + sp_digit t1[96]; + sp_digit t2[49]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -3239,7 +3348,8 @@ static WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_dig * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_3072_div_48(a, m, NULL, r); } @@ -3258,8 +3368,10 @@ extern sp_digit sp_3072_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b static WC_INLINE int sp_3072_div_48_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[96], t2[49]; - sp_digit div, r1; + sp_digit t1[96]; + sp_digit t2[49]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -3316,7 +3428,8 @@ static WC_INLINE int sp_3072_div_48_cond(const sp_digit* a, const sp_digit* d, s * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_3072_div_48_cond(a, m, NULL, r); } @@ -3340,13 +3453,14 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(33 * 96) + 96]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -3433,34 +3547,34 @@ static int sp_3072_mod_exp_48(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -3507,8 +3621,8 @@ extern void sp_3072_mont_reduce_avx2_48(sp_digit* a, const sp_digit* m, sp_digit * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_3072_mul_avx2_48(r, a, b); sp_3072_mont_reduce_avx2_48(r, m, mp); @@ -3523,8 +3637,8 @@ static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_di * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_3072_mont_sqr_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_3072_mont_sqr_avx2_48(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_3072_sqr_avx2_48(r, a); sp_3072_mont_reduce_avx2_48(r, m, mp); @@ -3551,13 +3665,14 @@ static int sp_3072_mod_exp_avx2_48(sp_digit* r, const sp_digit* a, const sp_digi sp_digit td[(33 * 96) + 96]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -3644,34 +3759,34 @@ static int sp_3072_mod_exp_avx2_48(sp_digit* r, const sp_digit* a, const sp_digi if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 48); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -3721,16 +3836,15 @@ static int sp_3072_mod_exp_avx2_48(sp_digit* r, const sp_digit* a, const sp_digi * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[96], md[48], rd[96]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; #else - sp_digit* d = NULL; + sp_digit a[48 * 5]; #endif - sp_digit* a; - sp_digit *ah; + sp_digit* ah; sp_digit* m; sp_digit* r; sp_digit e = 0; @@ -3750,28 +3864,20 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 48 * 2; - m = r + 48 * 2; - ah = a + 48; - } -#else - a = ad; - m = md; - r = rd; - ah = a + 48; #endif if (err == MP_OKAY) { + r = a + 48 * 2; + m = r + 48 * 2; + ah = a + 48; + sp_3072_from_bin(ah, 48, in, inLen); #if DIGIT_BIT >= 64 e = em->dp[0]; @@ -3868,9 +3974,9 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -3894,17 +4000,17 @@ int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm,const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { -#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) - sp_digit a[96], d[48], m[48]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[48 * 4]; +#endif sp_digit* a; sp_digit* m; -#endif sp_digit* r; int err = MP_OKAY; @@ -3932,7 +4038,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, } } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 4, NULL, DYNAMIC_TYPE_RSA); @@ -3943,10 +4049,9 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) a = d + 48; m = a + 96; -#endif + r = a; sp_3072_from_bin(a, 48, in, inLen); @@ -3960,14 +4065,16 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 48); - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(d, 0, sizeof(sp_digit) * 48); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) #endif + { + /* only zeroing private "d" */ + ForceZero(d, sizeof(sp_digit) * 48); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; } @@ -3992,18 +4099,15 @@ extern sp_digit sp_3072_cond_add_avx2_24(sp_digit* r, const sp_digit* a, const s * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[48 * 2]; - sp_digit pd[24], qd[24], dpd[24]; - sp_digit tmpad[48], tmpbd[48]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; #else - sp_digit* t = NULL; + sp_digit a[24 * 11]; #endif - sp_digit* a; sp_digit* p; sp_digit* q; sp_digit* dp; @@ -4031,33 +4135,23 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 48 * 2; q = p + 24; qi = dq = dp = q + 24; tmpa = qi + 24; tmpb = tmpa + 48; + r = a + 48; - r = t + 48; - } -#else - r = a = ad; - p = pd; - q = qd; - qi = dq = dp = dpd; - tmpa = tmpad; - tmpb = tmpbd; -#endif - - if (err == MP_OKAY) { sp_3072_from_bin(a, 48, in, inLen); sp_3072_from_mp(p, 24, pm); sp_3072_from_mp(q, 24, qm); @@ -4124,22 +4218,19 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, *outLen = 384; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpad, 0, sizeof(tmpad)); - XMEMSET(tmpbd, 0, sizeof(tmpbd)); - XMEMSET(pd, 0, sizeof(pd)); - XMEMSET(qd, 0, sizeof(qd)); - XMEMSET(dpd, 0, sizeof(dpd)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 24 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; } -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */ #endif /* WOLFSSL_HAVE_SP_RSA */ #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ !defined(WOLFSSL_RSA_PUBLIC_ONLY)) @@ -4159,17 +4250,19 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = 48; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 48; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -4182,14 +4275,16 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 48; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -4216,10 +4311,13 @@ static int sp_3072_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -4279,10 +4377,12 @@ static int sp_3072_mod_exp_2_avx2_48(sp_digit* r, const sp_digit* e, int bits, sp_digit* norm; sp_digit* tmp; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -4321,34 +4421,34 @@ static int sp_3072_mod_exp_2_avx2_48(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } sp_3072_lshift_48(r, norm, y); - for (; i>=0 || c>=6; ) { + while ((i >= 0) || (c >= 6)) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -4402,10 +4502,12 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, sp_digit* norm; sp_digit* tmp; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -4444,34 +4546,34 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } sp_3072_lshift_48(r, norm, y); - for (; i>=0 || c>=6; ) { + while ((i >= 0) || (c >= 6)) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -4519,11 +4621,13 @@ static int sp_3072_mod_exp_2_48(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[96], e[48], m[48]; + sp_digit b[96]; + sp_digit e[48]; + sp_digit m[48]; sp_digit* r = b; word32 i; #ifdef HAVE_INTEL_AVX2 @@ -4568,6 +4672,7 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, sp_3072_to_bin(r, out); *outLen = 384; for (i=0; i<384 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -4587,10 +4692,13 @@ int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[48], e[24], m[24]; + sp_digit b[48]; + sp_digit e[24]; + sp_digit m[24]; sp_digit* r = b; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -4628,7 +4736,7 @@ int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) return err; } -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* !WOLFSSL_SP_NO_3072 */ @@ -4644,12 +4752,15 @@ extern void sp_4096_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); */ static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_4096_from_bin_movbe(r, size, a, n); } - else { + else +#endif + { sp_4096_from_bin_bswap(r, size, a, n); } } @@ -4671,7 +4782,8 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -4705,7 +4817,9 @@ static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -4746,12 +4860,15 @@ extern void sp_4096_to_bin_movbe(sp_digit* r, byte* a); */ static void sp_4096_to_bin(sp_digit* r, byte* a) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_4096_to_bin_movbe(r, a); } - else { + else +#endif + { sp_4096_to_bin_bswap(r, a); } } @@ -4763,13 +4880,9 @@ extern void sp_4096_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b); extern sp_digit sp_2048_dbl_32(sp_digit* r, const sp_digit* a); extern void sp_4096_sqr_64(sp_digit* r, const sp_digit* a); -#ifdef HAVE_INTEL_AVX2 extern void sp_4096_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b); -#endif /* HAVE_INTEL_AVX2 */ -#ifdef HAVE_INTEL_AVX2 extern void sp_4096_sqr_avx2_64(sp_digit* r, const sp_digit* a); -#endif /* HAVE_INTEL_AVX2 */ /* Caclulate the bottom digit of -1/a mod 2^n. * @@ -4778,7 +4891,8 @@ extern void sp_4096_sqr_avx2_64(sp_digit* r, const sp_digit* a); */ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) { - sp_digit x, b; + sp_digit x; + sp_digit b; b = a[0]; x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ @@ -4788,7 +4902,7 @@ static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho) x *= 2 - b * x; /* here x*a==1 mod 2**64 */ /* rho = -1/m mod b */ - *rho = -x; + *rho = (sp_digit)0 - x; } extern void sp_4096_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b); @@ -4807,7 +4921,7 @@ static void sp_4096_mont_norm_64(sp_digit* r, const sp_digit* m) sp_4096_sub_in_place_64(r, m); } -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ extern sp_digit sp_4096_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp); /* Multiply two Montogmery form numbers mod the modulus (prime). @@ -4819,8 +4933,8 @@ extern void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_64(r, a, b); sp_4096_mont_reduce_64(r, m, mp); @@ -4833,8 +4947,8 @@ static void sp_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_64(r, a); sp_4096_mont_reduce_64(r, m, mp); @@ -4843,6 +4957,27 @@ static void sp_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* #if defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) extern sp_digit sp_4096_cond_sub_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_4096_mul_d_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_4096_word_asm_64(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_4096_word_64(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_4096_word_asm_64(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -4862,6 +4997,7 @@ static WC_INLINE sp_digit div_4096_word_64(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -4905,8 +5041,10 @@ extern int64_t sp_4096_cmp_64(const sp_digit* a, const sp_digit* b); static WC_INLINE int sp_4096_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[128], t2[65]; - sp_digit div, r1; + sp_digit t1[128]; + sp_digit t2[65]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -4959,7 +5097,8 @@ static WC_INLINE int sp_4096_div_64(const sp_digit* a, const sp_digit* d, sp_dig * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_4096_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_4096_mod_64(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_4096_div_64(a, m, NULL, r); } @@ -4978,8 +5117,10 @@ extern sp_digit sp_4096_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b static WC_INLINE int sp_4096_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[128], t2[65]; - sp_digit div, r1; + sp_digit t1[128]; + sp_digit t2[65]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -5036,7 +5177,8 @@ static WC_INLINE int sp_4096_div_64_cond(const sp_digit* a, const sp_digit* d, s * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_4096_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_4096_mod_64_cond(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_4096_div_64_cond(a, m, NULL, r); } @@ -5060,13 +5202,14 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, sp_digit td[(33 * 128) + 128]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -5153,34 +5296,34 @@ static int sp_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -5227,8 +5370,8 @@ extern void sp_4096_mont_reduce_avx2_64(sp_digit* a, const sp_digit* m, sp_digit * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_4096_mul_avx2_64(r, a, b); sp_4096_mont_reduce_avx2_64(r, m, mp); @@ -5243,8 +5386,8 @@ static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_di * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_4096_mont_sqr_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_4096_mont_sqr_avx2_64(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_4096_sqr_avx2_64(r, a); sp_4096_mont_reduce_avx2_64(r, m, mp); @@ -5271,13 +5414,14 @@ static int sp_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digi sp_digit td[(33 * 128) + 128]; #endif sp_digit* t[32]; - sp_digit* rt; + sp_digit* rt = NULL; sp_digit* norm; sp_digit mp = 1; sp_digit n; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -5364,34 +5508,34 @@ static int sp_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digi if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } XMEMCPY(r, t[y], sizeof(sp_digit) * 64); for (; i>=0 || c>=5; ) { if (c >= 5) { - y = (int)((n >> 59) & 0x1f); + y = (byte)((n >> 59) & 0x1f); n <<= 5; c -= 5; } else if (c == 0) { n = e[i--]; - y = (int)(n >> 59); + y = (byte)(n >> 59); n <<= 5; c = 59; } else { - y = (int)(n >> 59); + y = (byte)(n >> 59); n = e[i--]; c = 5 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } @@ -5441,16 +5585,15 @@ static int sp_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digi * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em, + const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[128], md[64], rd[128]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; #else - sp_digit* d = NULL; + sp_digit a[64 * 5]; #endif - sp_digit* a; - sp_digit *ah; + sp_digit* ah; sp_digit* m; sp_digit* r; sp_digit e = 0; @@ -5470,28 +5613,20 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, DYNAMIC_TYPE_RSA); - if (d == NULL) + if (a == NULL) err = MEMORY_E; } - - if (err == MP_OKAY) { - a = d; - r = a + 64 * 2; - m = r + 64 * 2; - ah = a + 64; - } -#else - a = ad; - m = md; - r = rd; - ah = a + 64; #endif if (err == MP_OKAY) { + r = a + 64 * 2; + m = r + 64 * 2; + ah = a + 64; + sp_4096_from_bin(ah, 64, in, inLen); #if DIGIT_BIT >= 64 e = em->dp[0]; @@ -5588,9 +5723,9 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); #endif return err; @@ -5614,17 +5749,17 @@ int sp_RsaPublic_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm,const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { -#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) - sp_digit a[128], d[64], m[64]; -#else +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* d = NULL; +#else + sp_digit d[64 * 4]; +#endif sp_digit* a; sp_digit* m; -#endif sp_digit* r; int err = MP_OKAY; @@ -5652,7 +5787,7 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, } } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, DYNAMIC_TYPE_RSA); @@ -5663,10 +5798,9 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, #endif if (err == MP_OKAY) { -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) a = d + 64; m = a + 128; -#endif + r = a; sp_4096_from_bin(a, 64, in, inLen); @@ -5680,14 +5814,16 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } -#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 64); - XFREE(d, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(d, 0, sizeof(sp_digit) * 64); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) #endif + { + /* only zeroing private "d" */ + ForceZero(d, sizeof(sp_digit) * 64); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; } @@ -5712,18 +5848,15 @@ extern sp_digit sp_4096_cond_add_avx2_32(sp_digit* r, const sp_digit* a, const s * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when * an array is too long and MEMORY_E when dynamic memory allocation fails. */ -int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, - mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, - byte* out, word32* outLen) +int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm, + const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm, + const mp_int* qim, const mp_int* mm, byte* out, word32* outLen) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit ad[64 * 2]; - sp_digit pd[32], qd[32], dpd[32]; - sp_digit tmpad[64], tmpbd[64]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* a = NULL; #else - sp_digit* t = NULL; + sp_digit a[32 * 11]; #endif - sp_digit* a; sp_digit* p; sp_digit* q; sp_digit* dp; @@ -5751,33 +5884,23 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, err = MP_VAL; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, DYNAMIC_TYPE_RSA); - if (t == NULL) + if (a == NULL) err = MEMORY_E; } +#endif + if (err == MP_OKAY) { - a = t; p = a + 64 * 2; q = p + 32; qi = dq = dp = q + 32; tmpa = qi + 32; tmpb = tmpa + 64; + r = a + 64; - r = t + 64; - } -#else - r = a = ad; - p = pd; - q = qd; - qi = dq = dp = dpd; - tmpa = tmpad; - tmpb = tmpbd; -#endif - - if (err == MP_OKAY) { sp_4096_from_bin(a, 64, in, inLen); sp_4096_from_mp(p, 32, pm); sp_4096_from_mp(q, 32, qm); @@ -5844,22 +5967,19 @@ int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, *outLen = 512; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { - XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); - XFREE(t, NULL, DYNAMIC_TYPE_RSA); - } -#else - XMEMSET(tmpad, 0, sizeof(tmpad)); - XMEMSET(tmpbd, 0, sizeof(tmpbd)); - XMEMSET(pd, 0, sizeof(pd)); - XMEMSET(qd, 0, sizeof(qd)); - XMEMSET(dpd, 0, sizeof(dpd)); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (a != NULL) #endif + { + ForceZero(a, sizeof(sp_digit) * 32 * 11); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } return err; } -#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* SP_RSA_PRIVATE_EXP_D | RSA_LOW_MEM */ #endif /* WOLFSSL_HAVE_SP_RSA */ #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ !defined(WOLFSSL_RSA_PUBLIC_ONLY)) @@ -5879,17 +5999,19 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = 64; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -5902,14 +6024,16 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 64; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -5936,10 +6060,13 @@ static int sp_4096_to_mp(const sp_digit* a, mp_int* r) * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod, + mp_int* res) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -5999,10 +6126,12 @@ static int sp_4096_mod_exp_2_avx2_64(sp_digit* r, const sp_digit* e, int bits, sp_digit* norm; sp_digit* tmp; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -6041,34 +6170,34 @@ static int sp_4096_mod_exp_2_avx2_64(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } sp_4096_lshift_64(r, norm, y); - for (; i>=0 || c>=6; ) { + while ((i >= 0) || (c >= 6)) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -6122,10 +6251,12 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, sp_digit* norm; sp_digit* tmp; sp_digit mp = 1; - sp_digit n, o; + sp_digit n; + sp_digit o; sp_digit mask; int i; - int c, y; + int c; + byte y; int err = MP_OKAY; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) @@ -6164,34 +6295,34 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, if (c < 0) { /* Number of bits in top word is less than number needed. */ c = -c; - y = (int)(n << c); + y = (byte)(n << c); n = e[i--]; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)(n >> c); + y = (byte)(n >> c); n <<= 64 - c; } sp_4096_lshift_64(r, norm, y); - for (; i>=0 || c>=6; ) { + while ((i >= 0) || (c >= 6)) { if (c == 0) { n = e[i--]; - y = (int)(n >> 58); + y = (byte)(n >> 58); n <<= 6; c = 58; } else if (c < 6) { - y = (int)(n >> 58); + y = (byte)(n >> 58); n = e[i--]; c = 6 - c; - y |= (int)(n >> (64 - c)); + y |= (byte)(n >> (64 - c)); n <<= c; c = 64 - c; } else { - y = (int)((n >> 58) & 0x3f); + y = (byte)((n >> 58) & 0x3f); n <<= 6; c -= 6; } @@ -6239,11 +6370,13 @@ static int sp_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, * returns 0 on success, MP_READ_E if there are too many bytes in an array * and MEMORY_E if memory allocation fails. */ -int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, - mp_int* mod, byte* out, word32* outLen) +int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen, + const mp_int* mod, byte* out, word32* outLen) { int err = MP_OKAY; - sp_digit b[128], e[64], m[64]; + sp_digit b[128]; + sp_digit e[64]; + sp_digit m[64]; sp_digit* r = b; word32 i; #ifdef HAVE_INTEL_AVX2 @@ -6288,6 +6421,7 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, sp_4096_to_bin(r, out); *outLen = 512; for (i=0; i<512 && out[i] == 0; i++) { + /* Search for first non-zero. */ } *outLen -= i; XMEMMOVE(out, out + i, *outLen); @@ -6298,19 +6432,23 @@ int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, return err; } #endif -#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ +#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */ #endif /* WOLFSSL_SP_4096 */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC #ifndef WOLFSSL_SP_NO_256 /* Point structure to use. */ typedef struct sp_point_256 { + /* X ordinate of point. */ sp_digit x[2 * 4]; + /* Y ordinate of point. */ sp_digit y[2 * 4]; + /* Z ordinate of point. */ sp_digit z[2 * 4]; + /* Indicates point is at infinity. */ int infinity; } sp_point_256; @@ -6382,50 +6520,10 @@ static const sp_digit p256_b[4] = { }; #endif -static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), &(sp), &(p)) -#endif - - -static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - +extern void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_256_sqr_4(sp_digit* r, const sp_digit* a); +extern sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b); /* Multiply a number by Montogmery normalizer mod modulus (prime). * * r The resulting Montgomery form number. @@ -6510,7 +6608,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -6544,7 +6643,9 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -6580,7 +6681,8 @@ static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) * p Point of type sp_point_256 (result). * pm Point of type ecc_point. */ -static void sp_256_point_from_ecc_point_4(sp_point_256* p, const ecc_point* pm) +static void sp_256_point_from_ecc_point_4(sp_point_256* p, + const ecc_point* pm) { XMEMSET(p->x, 0, sizeof(p->x)); XMEMSET(p->y, 0, sizeof(p->y)); @@ -6607,17 +6709,19 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = 4; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 4; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -6630,14 +6734,16 @@ static int sp_256_to_mp(const sp_digit* a, mp_int* r) r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 4; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -6698,7 +6804,7 @@ static void sp_256_mont_sqr_n_4(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P256 curve. */ static const uint64_t p256_mod_minus_2[4] = { @@ -6784,7 +6890,6 @@ extern int64_t sp_256_cmp_4(const sp_digit* a, const sp_digit* b); #define sp_256_norm_4(a) extern sp_digit sp_256_cond_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); -extern sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b); #define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4 extern void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m, sp_digit mp); @@ -6794,7 +6899,8 @@ extern void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m, sp_digit mp); * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*4; @@ -6831,7 +6937,7 @@ static void sp_256_map_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) } extern void sp_256_mont_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); -extern void sp_256_mont_dbl_4(const sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_256_mont_dbl_4(sp_digit* r, const sp_digit* a, const sp_digit* m); extern void sp_256_mont_tpl_4(sp_digit* r, const sp_digit* a, const sp_digit* m); extern void sp_256_mont_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); extern void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); @@ -7037,7 +7143,8 @@ static void sp_256_proj_point_dbl_4(sp_point_256* r, const sp_point_256* p, sp_d * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_4(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*4; @@ -7340,8 +7447,8 @@ static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_4(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -7434,8 +7541,8 @@ static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, cons * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* p, - int n, int m, sp_digit* t) +static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, + const sp_point_256* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*4; @@ -7446,6 +7553,7 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* sp_digit* y = r[(1<x[i]; @@ -7462,7 +7570,10 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* /* W = Z^4 */ sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); sp_256_mont_sub_4(t1, t1, w, p256_mod); @@ -7470,14 +7581,14 @@ static void sp_256_proj_point_dbl_n_store_4(sp_point_256* r, const sp_point_256* /* B = X*Y^2 */ sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); - x = r[(1<y); + sp_256_norm_4(negy); sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); sp_256_proj_point_add_4(rt, rt, p, tmp); } @@ -7781,19 +7894,18 @@ static int sp_256_ecc_mulmod_win_add_sub_4(sp_point_256* r, const sp_point_256* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } #ifdef HAVE_INTEL_AVX2 +#define sp_256_mod_mul_norm_avx2_4 sp_256_mod_mul_norm_4 extern void sp_256_mont_mul_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m, sp_digit mp); extern void sp_256_mont_sqr_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* m, sp_digit mp); #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) @@ -7814,7 +7926,7 @@ static void sp_256_mont_sqr_n_avx2_4(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ /* Invert the number, in Montgomery form, modulo the modulus (prime) of the * P256 curve. (r = 1 / a mod m) @@ -7885,13 +7997,18 @@ static void sp_256_mont_inv_avx2_4(sp_digit* r, const sp_digit* a, sp_digit* td) #endif /* WOLFSSL_SP_SMALL */ } +extern sp_digit sp_256_cond_sub_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +#define sp_256_mont_reduce_order_avx2_4 sp_256_mont_reduce_avx2_4 + +extern void sp_256_mont_reduce_avx2_4(sp_digit* a, const sp_digit* m, sp_digit mp); /* Map the Montgomery form projective coordinate point to an affine point. * * r Resulting affine coordinate point. * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) +static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*4; @@ -7905,7 +8022,7 @@ static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* /* x /= z^2 */ sp_256_mont_mul_avx2_4(r->x, p->x, t2, p256_mod, p256_mp_mod); XMEMSET(r->x + 4, 0, sizeof(r->x) / 2U); - sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod); + sp_256_mont_reduce_avx2_4(r->x, p256_mod, p256_mp_mod); /* Reduce x to less than modulus */ n = sp_256_cmp_4(r->x, p256_mod); sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - ((n >= 0) ? @@ -7915,10 +8032,10 @@ static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* /* y /= z^3 */ sp_256_mont_mul_avx2_4(r->y, p->y, t1, p256_mod, p256_mp_mod); XMEMSET(r->y + 4, 0, sizeof(r->y) / 2U); - sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod); + sp_256_mont_reduce_avx2_4(r->y, p256_mod, p256_mp_mod); /* Reduce y to less than modulus */ n = sp_256_cmp_4(r->y, p256_mod); - sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - ((n >= 0) ? + sp_256_cond_sub_avx2_4(r->y, r->y, p256_mod, 0 - ((n >= 0) ? (sp_digit)1 : (sp_digit)0)); sp_256_norm_4(r->y); @@ -7927,6 +8044,11 @@ static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* } +#define sp_256_mont_add_avx2_4 sp_256_mont_add_4 +#define sp_256_mont_dbl_avx2_4 sp_256_mont_dbl_4 +#define sp_256_mont_tpl_avx2_4 sp_256_mont_tpl_4 +#define sp_256_mont_sub_avx2_4 sp_256_mont_sub_4 +extern void sp_256_div2_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); /* Double the Montgomery form projective point p. * * r Result of doubling point. @@ -8089,37 +8211,37 @@ static void sp_256_proj_point_dbl_avx2_4(sp_point_256* r, const sp_point_256* p, /* Z = Y * Z */ sp_256_mont_mul_avx2_4(z, p->y, p->z, p256_mod, p256_mp_mod); /* Z = 2Z */ - sp_256_mont_dbl_4(z, z, p256_mod); + sp_256_mont_dbl_avx2_4(z, z, p256_mod); /* T2 = X - T1 */ - sp_256_mont_sub_4(t2, p->x, t1, p256_mod); + sp_256_mont_sub_avx2_4(t2, p->x, t1, p256_mod); /* T1 = X + T1 */ - sp_256_mont_add_4(t1, p->x, t1, p256_mod); + sp_256_mont_add_avx2_4(t1, p->x, t1, p256_mod); /* T2 = T1 * T2 */ sp_256_mont_mul_avx2_4(t2, t1, t2, p256_mod, p256_mp_mod); /* T1 = 3T2 */ - sp_256_mont_tpl_4(t1, t2, p256_mod); + sp_256_mont_tpl_avx2_4(t1, t2, p256_mod); /* Y = 2Y */ - sp_256_mont_dbl_4(y, p->y, p256_mod); + sp_256_mont_dbl_avx2_4(y, p->y, p256_mod); /* Y = Y * Y */ sp_256_mont_sqr_avx2_4(y, y, p256_mod, p256_mp_mod); /* T2 = Y * Y */ sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); /* T2 = T2/2 */ - sp_256_div2_4(t2, t2, p256_mod); + sp_256_div2_avx2_4(t2, t2, p256_mod); /* Y = Y * X */ sp_256_mont_mul_avx2_4(y, y, p->x, p256_mod, p256_mp_mod); /* X = T1 * T1 */ sp_256_mont_sqr_avx2_4(x, t1, p256_mod, p256_mp_mod); /* X = X - Y */ - sp_256_mont_sub_4(x, x, y, p256_mod); + sp_256_mont_sub_avx2_4(x, x, y, p256_mod); /* X = X - Y */ - sp_256_mont_sub_4(x, x, y, p256_mod); + sp_256_mont_sub_avx2_4(x, x, y, p256_mod); /* Y = Y - X */ - sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_avx2_4(y, y, x, p256_mod); /* Y = Y * T1 */ sp_256_mont_mul_avx2_4(y, y, t1, p256_mod, p256_mp_mod); /* Y = Y - T2 */ - sp_256_mont_sub_4(y, y, t2, p256_mod); + sp_256_mont_sub_avx2_4(y, y, t2, p256_mod); } /* Double the Montgomery form projective point p a number of times. @@ -8129,7 +8251,8 @@ static void sp_256_proj_point_dbl_avx2_4(sp_point_256* r, const sp_point_256* p, * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, sp_digit* t) +static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*4; @@ -8145,7 +8268,7 @@ static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, sp_digit* t) z = p->z; /* Y = 2*Y */ - sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_dbl_avx2_4(y, y, p256_mod); /* W = Z^4 */ sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod); sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod); @@ -8158,15 +8281,15 @@ static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, sp_digit* t) { /* A = 3*(X^2 - W) */ sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(t1, t1, w, p256_mod); - sp_256_mont_tpl_4(a, t1, p256_mod); + sp_256_mont_sub_avx2_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_avx2_4(a, t1, p256_mod); /* B = X*Y^2 */ sp_256_mont_sqr_avx2_4(t1, y, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(b, t1, x, p256_mod, p256_mp_mod); /* X = A^2 - 2B */ sp_256_mont_sqr_avx2_4(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_4(t2, b, p256_mod); - sp_256_mont_sub_4(x, x, t2, p256_mod); + sp_256_mont_dbl_avx2_4(t2, b, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t2, p256_mod); /* Z = Z*Y */ sp_256_mont_mul_avx2_4(z, z, y, p256_mod, p256_mp_mod); /* t2 = Y^4 */ @@ -8179,35 +8302,35 @@ static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, sp_digit* t) sp_256_mont_mul_avx2_4(w, w, t1, p256_mod, p256_mp_mod); } /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_sub_avx2_4(y, b, x, p256_mod); sp_256_mont_mul_avx2_4(y, y, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_4(y, y, p256_mod); - sp_256_mont_sub_4(y, y, t1, p256_mod); + sp_256_mont_dbl_avx2_4(y, y, p256_mod); + sp_256_mont_sub_avx2_4(y, y, t1, p256_mod); } #ifndef WOLFSSL_SP_SMALL /* A = 3*(X^2 - W) */ sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(t1, t1, w, p256_mod); - sp_256_mont_tpl_4(a, t1, p256_mod); + sp_256_mont_sub_avx2_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_avx2_4(a, t1, p256_mod); /* B = X*Y^2 */ sp_256_mont_sqr_avx2_4(t1, y, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(b, t1, x, p256_mod, p256_mp_mod); /* X = A^2 - 2B */ sp_256_mont_sqr_avx2_4(x, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_4(t2, b, p256_mod); - sp_256_mont_sub_4(x, x, t2, p256_mod); + sp_256_mont_dbl_avx2_4(t2, b, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t2, p256_mod); /* Z = Z*Y */ sp_256_mont_mul_avx2_4(z, z, y, p256_mod, p256_mp_mod); /* t2 = Y^4 */ sp_256_mont_sqr_avx2_4(t1, t1, p256_mod, p256_mp_mod); /* y = 2*A*(B - X) - Y^4 */ - sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_sub_avx2_4(y, b, x, p256_mod); sp_256_mont_mul_avx2_4(y, y, a, p256_mod, p256_mp_mod); - sp_256_mont_dbl_4(y, y, p256_mod); - sp_256_mont_sub_4(y, y, t1, p256_mod); + sp_256_mont_dbl_avx2_4(y, y, p256_mod); + sp_256_mont_sub_avx2_4(y, y, t1, p256_mod); #endif /* Y = Y/2 */ - sp_256_div2_4(y, y, p256_mod); + sp_256_div2_avx2_4(y, y, p256_mod); } /* Add two Montgomery form projective points. @@ -8420,8 +8543,8 @@ static int sp_256_proj_point_add_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, - sp_digit* t) +static void sp_256_proj_point_add_avx2_4(sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) { const sp_point_256* ap[2]; sp_point_256* rp[2]; @@ -8447,7 +8570,7 @@ static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, sp_256_norm_4(t1); if ((sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) != 0) { - sp_256_proj_point_dbl_4(r, p, t); + sp_256_proj_point_dbl_avx2_4(r, p, t); } else { rp[0] = r; @@ -8485,9 +8608,9 @@ static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, /* S2 = Y2*Z1^3 */ sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); /* H = U2 - U1 */ - sp_256_mont_sub_4(t2, t2, t1, p256_mod); + sp_256_mont_sub_avx2_4(t2, t2, t1, p256_mod); /* R = S2 - S1 */ - sp_256_mont_sub_4(t4, t4, t3, p256_mod); + sp_256_mont_sub_avx2_4(t4, t4, t3, p256_mod); /* Z3 = H*Z1*Z2 */ sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); @@ -8496,14 +8619,14 @@ static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(x, x, t5, p256_mod); - sp_256_mont_dbl_4(t1, y, p256_mod); - sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t5, p256_mod); + sp_256_mont_dbl_avx2_4(t1, y, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t1, p256_mod); /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_avx2_4(y, y, x, p256_mod); sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(y, y, t5, p256_mod); + sp_256_mont_sub_avx2_4(y, y, t5, p256_mod); } } @@ -8514,8 +8637,8 @@ static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, * n Number of times to double * t Temporary ordinate data. */ -static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point_256* r, const sp_point_256* p, - int n, int m, sp_digit* t) +static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point_256* r, + const sp_point_256* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*4; @@ -8526,6 +8649,7 @@ static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point_256* r, const sp_point sp_digit* y = r[(1<x[i]; @@ -8538,26 +8662,29 @@ static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point_256* r, const sp_point } /* Y = 2*Y */ - sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_dbl_avx2_4(y, y, p256_mod); /* W = Z^4 */ sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod); sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(t1, t1, w, p256_mod); - sp_256_mont_tpl_4(a, t1, p256_mod); + sp_256_mont_sub_avx2_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_avx2_4(a, t1, p256_mod); /* B = X*Y^2 */ sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod); - x = r[(1<y, p256_mod, p256_mp_mod); /* H = U2 - U1 */ - sp_256_mont_sub_4(t2, t2, t1, p256_mod); + sp_256_mont_sub_avx2_4(t2, t2, t1, p256_mod); /* RS = S2 + S1 */ - sp_256_mont_add_4(t6, t4, t3, p256_mod); + sp_256_mont_add_avx2_4(t6, t4, t3, p256_mod); /* R = S2 - S1 */ - sp_256_mont_sub_4(t4, t4, t3, p256_mod); + sp_256_mont_sub_avx2_4(t4, t4, t3, p256_mod); /* Z3 = H*Z1*Z2 */ /* ZS = H*Z1*Z2 */ sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod); @@ -8637,21 +8765,21 @@ static void sp_256_proj_point_add_sub_avx2_4(sp_point_256* ra, sp_point_256* rs, sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(x, x, t5, p256_mod); - sp_256_mont_sub_4(xs, xs, t5, p256_mod); - sp_256_mont_dbl_4(t1, y, p256_mod); - sp_256_mont_sub_4(x, x, t1, p256_mod); - sp_256_mont_sub_4(xs, xs, t1, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t5, p256_mod); + sp_256_mont_sub_avx2_4(xs, xs, t5, p256_mod); + sp_256_mont_dbl_avx2_4(t1, y, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t1, p256_mod); + sp_256_mont_sub_avx2_4(xs, xs, t1, p256_mod); /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ - sp_256_mont_sub_4(ys, y, xs, p256_mod); - sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_avx2_4(ys, y, xs, p256_mod); + sp_256_mont_sub_avx2_4(y, y, x, p256_mod); sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod); sp_256_sub_4(t6, p256_mod, t6); sp_256_mont_mul_avx2_4(ys, ys, t6, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(y, y, t5, p256_mod); - sp_256_mont_sub_4(ys, ys, t5, p256_mod); + sp_256_mont_sub_avx2_4(y, y, t5, p256_mod); + sp_256_mont_sub_avx2_4(ys, ys, t5, p256_mod); } /* Multiply the point by the scalar and return the result. @@ -8675,53 +8803,52 @@ static void sp_256_proj_point_add_sub_avx2_4(sp_point_256* ra, sp_point_256* rs, static int sp_256_ecc_mulmod_win_add_sub_avx2_4(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td[33]; - sp_point_256 rtd, pd; - sp_digit tmpd[2 * 4 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 t[33+2]; + sp_digit tmp[2 * 4 * 6]; #endif - sp_point_256* t; - sp_point_256* rt; + sp_point_256* rt = NULL; sp_point_256* p = NULL; - sp_digit* tmp; sp_digit* negy; int i; ecc_recode_256 v[43]; - int err; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) - err = sp_256_point_new_4(heap, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 33, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * + (33+2), heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif - if (err == MP_OKAY) { + rt = t + 33; + p = t + 33+1; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod); + err = sp_256_mod_mul_norm_avx2_4(t[1].x, g->x, p256_mod); } if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod); + err = sp_256_mod_mul_norm_avx2_4(t[1].y, g->y, p256_mod); } if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod); + err = sp_256_mod_mul_norm_avx2_4(t[1].z, g->z, p256_mod); } if (err == MP_OKAY) { @@ -8777,6 +8904,7 @@ static int sp_256_ecc_mulmod_win_add_sub_avx2_4(sp_point_256* r, const sp_point_ XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256)); } sp_256_sub_4(negy, p256_mod, p->y); + sp_256_norm_4(negy); sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); sp_256_proj_point_add_avx2_4(rt, rt, p, tmp); } @@ -8789,14 +8917,12 @@ static int sp_256_ecc_mulmod_win_add_sub_avx2_4(sp_point_256* r, const sp_point_ } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } @@ -8809,7 +8935,7 @@ typedef struct sp_table_entry_256 { } sp_table_entry_256; #if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Add two Montgomery form projective points. The second point has a q value of * one. * Only the first point can be the same pointer as the result point. @@ -8916,6 +9042,10 @@ static void sp_256_proj_to_affine_4(sp_point_256* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 6 + * 64 entries + * 42 bits between * * a The base point. * table Place to store generated point data. @@ -8925,26 +9055,30 @@ static void sp_256_proj_to_affine_4(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_4(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_4(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); } if (err == MP_OKAY) { @@ -8989,9 +9123,10 @@ static int sp_256_gen_stripe_table_4(const sp_point_256* a, } } - sp_256_point_free_4(s2, 0, heap); - sp_256_point_free_4(s1, 0, heap); - sp_256_point_free_4( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -9003,8 +9138,10 @@ extern void sp_256_get_entry_64_avx2_4(sp_point_256* r, const sp_table_entry_256 /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 6 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^42, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -9018,17 +9155,19 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -9036,27 +9175,30 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=42; j<6 && x<256; j++,x+=43) { + x = 42; + for (j=0; j<6 && x<256; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 43; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -9070,8 +9212,10 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, rt->infinity = !y; for (i=41; i>=0; i--) { y = 0; - for (j=0,x=i; j<6 && x<256; j++,x+=43) { + x = i; + for (j=0; j<6 && x<256; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 43; } sp_256_proj_point_dbl_4(rt, rt, t); @@ -9097,33 +9241,41 @@ static int sp_256_ecc_mulmod_stripe_4(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ #ifdef FP_ECC #ifndef FP_ENTRIES #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_256_t { + /* X ordinate of point that table was generated from. */ sp_digit x[4]; + /* Y ordinate of point that table was generated from. */ sp_digit y[4]; + /* Precomputation table for point. */ sp_table_entry_256 table[64]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_256_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_256_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_256_inited = 0; #ifndef HAVE_THREAD_LS @@ -9131,9 +9283,15 @@ static THREAD_LS_T int sp_cache_256_inited = 0; static wolfSSL_Mutex sp_cache_256_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_256_inited == 0) { @@ -9241,7 +9399,7 @@ static int sp_256_ecc_mulmod_4(sp_point_256* r, const sp_point_256* g, const sp_ #ifdef HAVE_INTEL_AVX2 #if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Add two Montgomery form projective points. The second point has a q value of * one. * Only the first point can be the same pointer as the result point. @@ -9271,7 +9429,7 @@ static void sp_256_proj_point_add_qz1_avx2_4(sp_point_256* r, const sp_point_256 sp_256_norm_4(t1); if ((sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) != 0) { - sp_256_proj_point_dbl_4(r, p, t); + sp_256_proj_point_dbl_avx2_4(r, p, t); } else { rp[0] = r; @@ -9303,9 +9461,9 @@ static void sp_256_proj_point_add_qz1_avx2_4(sp_point_256* r, const sp_point_256 /* S2 = Y2*Z1^3 */ sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); /* H = U2 - X1 */ - sp_256_mont_sub_4(t2, t2, x, p256_mod); + sp_256_mont_sub_avx2_4(t2, t2, x, p256_mod); /* R = S2 - Y1 */ - sp_256_mont_sub_4(t4, t4, y, p256_mod); + sp_256_mont_sub_avx2_4(t4, t4, y, p256_mod); /* Z3 = H*Z1 */ sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); /* X3 = R^2 - H^3 - 2*X1*H^2 */ @@ -9313,14 +9471,14 @@ static void sp_256_proj_point_add_qz1_avx2_4(sp_point_256* r, const sp_point_256 sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t3, x, t5, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(x, t1, t5, p256_mod); - sp_256_mont_dbl_4(t1, t3, p256_mod); - sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_avx2_4(x, t1, t5, p256_mod); + sp_256_mont_dbl_avx2_4(t1, t3, p256_mod); + sp_256_mont_sub_avx2_4(x, x, t1, p256_mod); /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_256_mont_sub_4(t3, t3, x, p256_mod); + sp_256_mont_sub_avx2_4(t3, t3, x, p256_mod); sp_256_mont_mul_avx2_4(t3, t3, t4, p256_mod, p256_mp_mod); sp_256_mont_mul_avx2_4(t5, t5, y, p256_mod, p256_mp_mod); - sp_256_mont_sub_4(y, t3, t5, p256_mod); + sp_256_mont_sub_avx2_4(y, t3, t5, p256_mod); } } @@ -9348,6 +9506,10 @@ static void sp_256_proj_to_affine_avx2_4(sp_point_256* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 6 + * 64 entries + * 42 bits between * * a The base point. * table Place to store generated point data. @@ -9357,33 +9519,37 @@ static void sp_256_proj_to_affine_avx2_4(sp_point_256* a, sp_digit* t) static int sp_256_gen_stripe_table_avx2_4(const sp_point_256* a, sp_table_entry_256* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; +#else + sp_point_256 t[3]; #endif - sp_point_256* t; sp_point_256* s1 = NULL; sp_point_256* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_256_point_new_4(heap, td, t); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); + s1 = t + 1; + s2 = t + 2; + + err = sp_256_mod_mul_norm_avx2_4(t->x, a->x, p256_mod); } if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod); + err = sp_256_mod_mul_norm_avx2_4(t->y, a->y, p256_mod); } if (err == MP_OKAY) { - err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod); + err = sp_256_mod_mul_norm_avx2_4(t->z, a->z, p256_mod); } if (err == MP_OKAY) { t->infinity = 0; @@ -9421,9 +9587,10 @@ static int sp_256_gen_stripe_table_avx2_4(const sp_point_256* a, } } - sp_256_point_free_4(s2, 0, heap); - sp_256_point_free_4(s1, 0, heap); - sp_256_point_free_4( t, 0, heap); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -9433,8 +9600,10 @@ static int sp_256_gen_stripe_table_avx2_4(const sp_point_256* a, /* Multiply the point by the scalar and return the result. * If map is true then convert result to affine coordinates. * - * Implementation uses striping of bits. - * Choose bits 6 bits apart. + * Stripe implementation. + * Pre-generated: 2^0, 2^42, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) * * r Resulting point. * k Scalar to multiply by. @@ -9448,17 +9617,19 @@ static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point_256* r, const sp_point_256* const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit td[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_256 rt[2]; + sp_digit t[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* t; - int i, j; - int y, x; - int err; + int i; + int j; + int y; + int x; + int err = MP_OKAY; (void)g; /* Constant time used for cache attack resistance implementation. */ @@ -9466,27 +9637,30 @@ static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point_256* r, const sp_point_256* (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; } -#else - t = td; #endif if (err == MP_OKAY) { + p = rt + 1; + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); y = 0; - for (j=0,x=42; j<6 && x<256; j++,x+=43) { + x = 42; + for (j=0; j<6 && x<256; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 43; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { @@ -9500,8 +9674,10 @@ static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point_256* r, const sp_point_256* rt->infinity = !y; for (i=41; i>=0; i--) { y = 0; - for (j=0,x=i; j<6 && x<256; j++,x+=43) { + x = i; + for (j=0; j<6 && x<256; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 43; } sp_256_proj_point_dbl_avx2_4(rt, rt, t); @@ -9527,18 +9703,17 @@ static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point_256* r, const sp_point_256* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return err; } -#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * @@ -9602,31 +9777,34 @@ static int sp_256_ecc_mulmod_avx2_4(sp_point_256* r, const sp_point_256* g, cons * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[4]; +#endif int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_256_point_new_4(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 4, km); sp_256_point_from_ecc_point_4(point, gm); @@ -9642,17 +9820,119 @@ int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_256_point_to_ecc_point_4(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[4 + 4 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (4 + 4 * 2 * 5), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_4(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 4; + + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(point, gm); + sp_256_point_from_ecc_point_4(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(point, point, k, 0, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_4(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(point, point, addP, tmp); + else +#endif + sp_256_proj_point_add_4(point, point, addP, tmp); + + if (map) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_map_avx2_4(point, point, tmp); + else +#endif + sp_256_map_4(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_4(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } #ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 6 points combined into a table of 64 points. + * Distance of 43 between points. + */ static const sp_table_entry_256 p256_table[64] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00 }, @@ -9977,6 +10257,11 @@ static const sp_table_entry_256 p256_table[64] = { /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^42, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -9995,6 +10280,11 @@ static int sp_256_ecc_mulmod_base_4(sp_point_256* r, const sp_digit* k, /* Multiply the base point of P256 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^42, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -10045,7 +10335,8 @@ static const uint8_t recode_neg_4_7[130] = { */ static void sp_256_ecc_recode_7_4(const sp_digit* k, ecc_recode_256* v) { - int i, j; + int i; + int j; uint8_t y; int carry = 0; int o; @@ -22057,35 +22348,41 @@ static int sp_256_ecc_mulmod_add_only_4(sp_point_256* r, const sp_point_256* g, const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit tmpd[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 rt[2]; + sp_digit tmp[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* tmp; - sp_digit* negy; + sp_digit* negy = NULL; int i; ecc_recode_256 v[37]; - int err; + int err = MP_OKAY; (void)g; (void)ct; (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) - err = sp_256_point_new_4(heap, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; -#else - tmp = tmpd; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif - negy = tmp; + + if (err == MP_OKAY) { + negy = tmp; + p = rt + 1; + } if (err == MP_OKAY) { sp_256_ecc_recode_7_4(k, v); @@ -22118,6 +22415,7 @@ static int sp_256_ecc_mulmod_add_only_4(sp_point_256* r, const sp_point_256* g, } p->infinity = !v[i].i; sp_256_sub_4(negy, p256_mod, p->y); + sp_256_norm_4(negy); sp_256_cond_copy_4(p->y, negy, 0 - v[i].neg); sp_256_proj_point_add_qz1_4(rt, rt, p, tmp); } @@ -22129,16 +22427,19 @@ static int sp_256_ecc_mulmod_add_only_4(sp_point_256* r, const sp_point_256* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return MP_OKAY; } @@ -22181,35 +22482,41 @@ static int sp_256_ecc_mulmod_add_only_avx2_4(sp_point_256* r, const sp_point_256 const sp_table_entry_256* table, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 rtd; - sp_point_256 pd; - sp_digit tmpd[2 * 4 * 5]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* rt = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 rt[2]; + sp_digit tmp[2 * 4 * 5]; #endif - sp_point_256* rt; sp_point_256* p = NULL; - sp_digit* tmp; - sp_digit* negy; + sp_digit* negy = NULL; int i; ecc_recode_256 v[37]; - int err; + int err = MP_OKAY; (void)g; (void)ct; (void)heap; - err = sp_256_point_new_4(heap, rtd, rt); - if (err == MP_OKAY) - err = sp_256_point_new_4(heap, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) err = MEMORY_E; -#else - tmp = tmpd; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif - negy = tmp; + + if (err == MP_OKAY) { + negy = tmp; + p = rt + 1; + } if (err == MP_OKAY) { sp_256_ecc_recode_7_4(k, v); @@ -22242,6 +22549,7 @@ static int sp_256_ecc_mulmod_add_only_avx2_4(sp_point_256* r, const sp_point_256 } p->infinity = !v[i].i; sp_256_sub_4(negy, p256_mod, p->y); + sp_256_norm_4(negy); sp_256_cond_copy_4(p->y, negy, 0 - v[i].neg); sp_256_proj_point_add_qz1_avx2_4(rt, rt, p, tmp); } @@ -22253,16 +22561,19 @@ static int sp_256_ecc_mulmod_add_only_avx2_4(sp_point_256* r, const sp_point_256 } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { - XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - } -#else - ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(rt, 0, heap); return MP_OKAY; } @@ -22295,31 +22606,33 @@ static int sp_256_ecc_mulmod_base_avx2_4(sp_point_256* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[4]; +#endif int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_256_point_new_4(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_256_from_mp(k, 4, km); @@ -22334,12 +22647,108 @@ int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) err = sp_256_point_to_ecc_point_4(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P256 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; + sp_digit* k = NULL; +#else + sp_point_256 point[2]; + sp_digit k[4 + 4 * 2 * 5]; +#endif + sp_point_256* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (4 + 4 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_256_point_free_4(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 4; + + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->x, addP->x, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->y, addP->y, p256_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_256_mod_mul_norm_4(addP->z, addP->z, p256_mod); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, 0, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(point, point, addP, tmp); + else +#endif + sp_256_proj_point_add_4(point, point, addP, tmp); + + if (map) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_map_avx2_4(point, point, tmp); + else +#endif + sp_256_map_4(point, point, tmp); + } + + err = sp_256_point_to_ecc_point_4(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -22357,7 +22766,7 @@ static int sp_256_iszero_4(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ extern void sp_256_add_one_4(sp_digit* a); extern void sp_256_from_bin_bswap(sp_digit* r, int size, const byte* a, int n); extern void sp_256_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); @@ -22370,12 +22779,15 @@ extern void sp_256_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); */ static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_256_from_bin_movbe(r, size, a, n); } - else { + else +#endif + { sp_256_from_bin_bswap(r, size, a, n); } } @@ -22418,44 +22830,49 @@ static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_256 inf; -#endif -#endif - sp_point_256* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; + #else + sp_point_256 point[1]; + #endif + sp_digit k[4]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_256* infinity = NULL; #endif - int err; + int err = MP_OKAY; + #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif (void)heap; - err = sp_256_point_new_4(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_256_ecc_gen_k_4(rng, k); } if (err == MP_OKAY) { @@ -22492,15 +22909,14 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_256_point_to_ecc_point_4(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_256_point_free_4(infinity, 1, heap); -#endif - sp_256_point_free_4(point, 1, heap); return err; } @@ -22516,12 +22932,15 @@ extern void sp_256_to_bin_movbe(sp_digit* r, byte* a); */ static void sp_256_to_bin(sp_digit* r, byte* a) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_256_to_bin_movbe(r, a); } - else { + else +#endif + { sp_256_to_bin_bswap(r, a); } } @@ -22538,15 +22957,16 @@ static void sp_256_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 p; - sp_digit kd[4]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_256* point = NULL; sp_digit* k = NULL; +#else + sp_point_256 point[1]; + sp_digit k[4]; +#endif int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -22556,18 +22976,19 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, p, point); + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -22585,31 +23006,47 @@ int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, *outLen = 32; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(point, 0, heap); return err; } #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -extern sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b); -#endif -#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -extern void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b); #ifdef HAVE_INTEL_AVX2 extern void sp_256_mul_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b); #endif /* HAVE_INTEL_AVX2 */ #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) extern sp_digit sp_256_sub_in_place_4(sp_digit* a, const sp_digit* b); -extern sp_digit sp_256_cond_sub_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_256_mul_d_4(sp_digit* r, const sp_digit* a, sp_digit b); extern void sp_256_mul_d_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_256_word_asm_4(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_256_word_4(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_256_word_asm_4(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -22629,6 +23066,7 @@ static WC_INLINE sp_digit div_256_word_4(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -22663,8 +23101,10 @@ static void sp_256_mask_4(sp_digit* r, const sp_digit* a, sp_digit m) static WC_INLINE int sp_256_div_4(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[8], t2[5]; - sp_digit div, r1; + sp_digit t1[8]; + sp_digit t2[5]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -22717,14 +23157,14 @@ static WC_INLINE int sp_256_div_4(const sp_digit* a, const sp_digit* d, sp_digit * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_256_mod_4(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_256_mod_4(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_256_div_4(a, m, NULL, r); } #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) -extern void sp_256_sqr_4(sp_digit* r, const sp_digit* a); #ifdef WOLFSSL_SP_SMALL /* Order-2 for the P256 curve. */ static const uint64_t p256_order_minus_2[4] = { @@ -23100,12 +23540,86 @@ static void sp_256_mont_inv_order_avx2_4(sp_digit* r, const sp_digit* a, } #endif /* HAVE_INTEL_AVX2 */ -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_s_4(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int64_t c; + sp_digit* kInv = k; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(k, k, p256_norm_order); + else +#endif + sp_256_mul_4(k, k, p256_norm_order); + err = sp_256_mod_4(k, k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(k); + + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_inv_order_avx2_4(kInv, k, tmp); + else +#endif + sp_256_mont_inv_order_4(kInv, k, tmp); + sp_256_norm_4(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(x, x, r); + else +#endif + sp_256_mul_4(x, x, r); + err = sp_256_mod_4(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(x); + carry = sp_256_add_4(s, e, x); + sp_256_cond_sub_4(s, s, p256_order, 0 - carry); + sp_256_norm_4(s); + c = sp_256_cmp_4(s, p256_order); + sp_256_cond_sub_4(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_mul_order_avx2_4(s, s, kInv); + else +#endif + sp_256_mont_mul_order_4(s, s, kInv); + sp_256_norm_4(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 256 bits] from binary * r = (k.G)->x mod order @@ -23140,8 +23654,8 @@ typedef struct sp_ecc_sign_256_ctx { int i; } sp_ecc_sign_256_ctx; -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; @@ -23159,13 +23673,10 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 32U; } - sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_256_from_mp(ctx->x, 4, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_4(rng, ctx->k); @@ -23193,6 +23704,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_256_cmp_4(ctx->r, p256_order); sp_256_cond_sub_4(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_4(ctx->r); + + sp_256_from_mp(ctx->x, 4, priv); + sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); ctx->state = 4; break; } @@ -23249,6 +23763,9 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -23281,30 +23798,23 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*4]; - sp_digit xd[2*4]; - sp_digit kd[2*4]; - sp_digit rd[2*4]; - sp_digit td[3 * 2*4]; - sp_point_256 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 4]; + sp_point_256 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_256* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int64_t c; + int err = MP_OKAY; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -23312,44 +23822,34 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, (void)heap; - err = sp_256_point_new_4(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 4; - x = d + 2 * 4; - k = d + 4 * 4; - r = d + 6 * 4; - tmp = d + 8 * 4; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 4; + k = e + 4 * 4; + r = e + 6 * 4; + tmp = e + 8 * 4; s = e; - kInv = k; if (hashLen > 32U) { hashLen = 32U; } - - sp_256_from_bin(e, 4, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_256_from_mp(x, 4, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_256_ecc_gen_k_4(rng, k); @@ -23364,7 +23864,7 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, 1, heap); else #endif - err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, NULL); + err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -23375,58 +23875,19 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_256_cond_sub_4(r, r, p256_order, 0L - (sp_digit)(c >= 0)); sp_256_norm_4(r); - /* Conv k to Montgomery form (mod order) */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_256_mul_avx2_4(k, k, p256_norm_order); - else -#endif - sp_256_mul_4(k, k, p256_norm_order); - err = sp_256_mod_4(k, k, p256_order); - } - if (err == MP_OKAY) { - sp_256_norm_4(k); - /* kInv = 1/k mod order */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_256_mont_inv_order_avx2_4(kInv, k, tmp); - else -#endif - sp_256_mont_inv_order_4(kInv, k, tmp); - sp_256_norm_4(kInv); + sp_256_from_mp(x, 4, priv); + sp_256_from_bin(e, 4, hash, (int)hashLen); - /* s = r * x + e */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_256_mul_avx2_4(x, x, r); - else -#endif - sp_256_mul_4(x, x, r); - err = sp_256_mod_4(x, x, p256_order); + err = sp_256_calc_s_4(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_256_norm_4(x); - carry = sp_256_add_4(s, e, x); - sp_256_cond_sub_4(s, s, p256_order, 0 - carry); - sp_256_norm_4(s); - c = sp_256_cmp_4(s, p256_order); - sp_256_cond_sub_4(s, s, p256_order, 0L - (sp_digit)(c >= 0)); - sp_256_norm_4(s); - /* s = s * k^-1 mod order */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_256_mont_mul_order_avx2_4(s, s, kInv); - else -#endif - sp_256_mont_mul_order_4(s, s, kInv); - sp_256_norm_4(s); - - /* Check that signature is usable. */ - if (sp_256_iszero_4(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_4(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -23440,20 +23901,24 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_256_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_256_point_free_4(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 4); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -23463,6 +23928,147 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, extern void sp_256_mod_inv_4(sp_digit* r, const sp_digit* a, const sp_digit* m); extern void sp_256_mod_inv_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_256_add_points_4(sp_point_256* p1, const sp_point_256* p2, + sp_digit* tmp) +{ +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp); + } + else +#endif + sp_256_proj_point_add_4(p1, p1, p2, tmp); + if (sp_256_iszero_4(p1->z)) { + if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_proj_point_dbl_avx2_4(p1, p2, tmp); + } + else +#endif + sp_256_proj_point_dbl_4(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_calc_vfy_point_4(sp_point_256* p1, sp_point_256* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifndef WOLFSSL_SP_SMALL +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mod_inv_avx2_4(s, s, p256_order); + } + else +#endif + { + sp_256_mod_inv_4(s, s, p256_order); + } +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mul_avx2_4(s, s, p256_norm_order); + } + else +#endif + { + sp_256_mul_4(s, s, p256_norm_order); + } + err = sp_256_mod_4(s, s, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(s); +#ifdef WOLFSSL_SP_SMALL +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_inv_order_avx2_4(s, s, tmp); + sp_256_mont_mul_order_avx2_4(u1, u1, s); + sp_256_mont_mul_order_avx2_4(u2, u2, s); + } + else +#endif + { + sp_256_mont_inv_order_4(s, s, tmp); + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + +#else +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_mul_order_avx2_4(u1, u1, s); + sp_256_mont_mul_order_avx2_4(u2, u2, s); + } + else +#endif + { + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(p1, u1, 0, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_4(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(p2, p2, u2, 0, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_256_iszero_4(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_256_add_points_4(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 256) @@ -23481,8 +24087,7 @@ extern void sp_256_mod_inv_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { @@ -23501,8 +24106,9 @@ typedef struct sp_ecc_verify_256_ctx { sp_point_256 p2; } sp_ecc_verify_256_ctx; -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; @@ -23517,7 +24123,7 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_256_from_bin(ctx->u1, 4, hash, (int)hashLen); - sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->u2, 4, rm); sp_256_from_mp(ctx->s, 4, sm); sp_256_from_mp(ctx->p2.x, 4, pX); sp_256_from_mp(ctx->p2.y, 4, pY); @@ -23575,57 +24181,33 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_256_iszero_4(ctx->p1.z)) { - if (sp_256_iszero_4(ctx->p1.x) && sp_256_iszero_4(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<4; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->u2, 4, rm); err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_256_mont_sqr_4(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int64_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int64_t c; /* Reload r and add order. */ - sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->u2, 4, rm); carry = sp_256_add_4(ctx->u2, ctx->u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -23633,22 +24215,23 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_4(ctx->u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -23656,185 +24239,63 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*4]; - sp_digit u2d[2*4]; - sp_digit sd[2*4]; - sp_digit tmpd[2*4 * 5]; - sp_point_256 p1d; - sp_point_256 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[16 * 4]; + sp_point_256 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_256* p1; sp_point_256* p2 = NULL; sp_digit carry; - int64_t c; - int err; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif + int64_t c = 0; + int err = MP_OKAY; - err = sp_256_point_new_4(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 4; - u2 = d + 2 * 4; - s = d + 4 * 4; - tmp = d + 6 * 4; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 4; + s = u1 + 4 * 4; + tmp = u1 + 6 * 4; + p2 = p1 + 1; if (hashLen > 32U) { hashLen = 32U; } sp_256_from_bin(u1, 4, hash, (int)hashLen); - sp_256_from_mp(u2, 4, r); + sp_256_from_mp(u2, 4, rm); sp_256_from_mp(s, 4, sm); sp_256_from_mp(p2->x, 4, pX); sp_256_from_mp(p2->y, 4, pY); sp_256_from_mp(p2->z, 4, pZ); -#ifndef WOLFSSL_SP_SMALL -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_256_mod_inv_avx2_4(s, s, p256_order); - } - else -#endif - { - sp_256_mod_inv_4(s, s, p256_order); - } -#endif /* !WOLFSSL_SP_SMALL */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_256_mul_avx2_4(s, s, p256_norm_order); - } - else -#endif - { - sp_256_mul_4(s, s, p256_norm_order); - } - err = sp_256_mod_4(s, s, p256_order); + err = sp_256_calc_vfy_point_4(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_256_norm_4(s); -#ifdef WOLFSSL_SP_SMALL -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_256_mont_inv_order_avx2_4(s, s, tmp); - sp_256_mont_mul_order_avx2_4(u1, u1, s); - sp_256_mont_mul_order_avx2_4(u2, u2, s); - } - else -#endif - { - sp_256_mont_inv_order_4(s, s, tmp); - sp_256_mont_mul_order_4(u1, u1, s); - sp_256_mont_mul_order_4(u2, u2, s); - } - -#else -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_256_mont_mul_order_avx2_4(u1, u1, s); - sp_256_mont_mul_order_avx2_4(u2, u2, s); - } - else -#endif - { - sp_256_mont_mul_order_4(u1, u1, s); - sp_256_mont_mul_order_4(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_256_ecc_mulmod_base_avx2_4(p1, u1, 0, 0, heap); - else -#endif - err = sp_256_ecc_mulmod_base_4(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_4(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_256_ecc_mulmod_avx2_4(p2, p2, u2, 0, 0, heap); - else -#endif - err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_256_iszero_4(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp); - if (sp_256_iszero_4(p1->z)) { - if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { - sp_256_proj_point_dbl_avx2_4(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - else -#endif - { - sp_256_proj_point_add_4(p1, p1, p2, tmp); - if (sp_256_iszero_4(p1->z)) { - if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { - sp_256_proj_point_dbl_4(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 4, r); + sp_256_from_mp(u2, 4, rm); err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); } @@ -23845,7 +24306,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_256_from_mp(u2, 4, r); + sp_256_from_mp(u2, 4, rm); carry = sp_256_add_4(u2, u2, p256_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -23853,26 +24314,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_256_cmp_4(u2, p256_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, - p256_mp_mod); - *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (sp_256_cmp_4(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p1, 0, heap); - sp_256_point_free_4(p2, 0, heap); return err; } @@ -23886,34 +24347,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) +static int sp_256_ecc_is_point_4(const sp_point_256* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*4]; - sp_digit t2d[2*4]; + sp_digit t1[4 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 4; - t2 = d + 2 * 4; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 4; sp_256_sqr_4(t1, point->y); (void)sp_256_mod_4(t1, t1, p256_mod); @@ -23933,10 +24386,9 @@ static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -23949,16 +24401,23 @@ static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* pub = NULL; +#else + sp_point_256 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_256* pub; - byte one[1] = { 1 }; - int err; - err = sp_256_point_new_4(NULL, pubd, pub); if (err == MP_OKAY) { sp_256_from_mp(pub->x, 4, pX); sp_256_from_mp(pub->y, 4, pY); @@ -23967,7 +24426,10 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) err = sp_256_ecc_is_point_4(pub, NULL); } - sp_256_point_free_4(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -23983,50 +24445,51 @@ int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[4]; - sp_point_256 pubd; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_256* pub; + sp_point_256* pub = NULL; +#else + sp_digit priv[4]; + sp_point_256 pub[2]; +#endif sp_point_256* p = NULL; - byte one[1] = { 1 }; - int err; + const byte one[1] = { 1 }; + int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_256_point_new_4(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_256_point_new_4(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } -#endif /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 256) || + if (((mp_count_bits(pX) > 256) || (mp_count_bits(pY) > 256) || ((privm != NULL) && (mp_count_bits(privm) > 256)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_256_from_mp(pub->x, 4, pX); sp_256_from_mp(pub->y, 4, pY); sp_256_from_bin(pub->z, 4, one, (int)sizeof(one)); @@ -24040,12 +24503,11 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || - sp_256_cmp_4(pub->y, p256_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_256_cmp_4(pub->x, p256_mod) >= 0) || + (sp_256_cmp_4(pub->y, p256_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -24062,12 +24524,10 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) #endif err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_256_iszero_4(p->x) == 0) || - (sp_256_iszero_4(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_256_iszero_4(p->x) == 0) || + (sp_256_iszero_4(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -24080,22 +24540,20 @@ int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) #endif err = sp_256_ecc_mulmod_base_4(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_256_cmp_4(p->x, pub->x) != 0 || - sp_256_cmp_4(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_256_cmp_4(p->x, pub->x) != 0) || + (sp_256_cmp_4(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_256_point_free_4(p, 0, heap); - sp_256_point_free_4(pub, 0, heap); return err; } @@ -24119,36 +24577,38 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 4 * 5]; - sp_point_256 pd; - sp_point_256 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 4 * 5]; + sp_point_256 p[2]; +#endif sp_point_256* q = NULL; int err; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_256_point_new_4(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_256_point_new_4(NULL, qd, q); + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_256_from_mp(p->x, 4, pX); sp_256_from_mp(p->y, 4, pY); sp_256_from_mp(p->z, 4, pZ); @@ -24174,13 +24634,12 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(q, 0, NULL); - sp_256_point_free_4(p, 0, NULL); return err; } @@ -24199,28 +24658,31 @@ int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 4 * 2]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 4 * 2]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_256_point_new_4(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -24246,12 +24708,12 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_256_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, NULL); return err; } @@ -24266,32 +24728,44 @@ int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 4 * 4]; - sp_point_256 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_256* p; - int err; + sp_point_256* p = NULL; +#else + sp_digit tmp[2 * 4 * 4]; + sp_point_256 p[1]; +#endif + int err = MP_OKAY; - err = sp_256_point_new_4(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_256_from_mp(p->x, 4, pX); sp_256_from_mp(p->y, 4, pY); sp_256_from_mp(p->z, 4, pZ); - sp_256_map_4(p, p, tmp); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_map_avx2_4(point, point, tmp); + else +#endif + sp_256_map_4(p, p, tmp); } if (err == MP_OKAY) { @@ -24304,12 +24778,12 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_256_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_256_point_free_4(p, 0, NULL); return err; } @@ -24322,34 +24796,26 @@ int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_256_mont_sqrt_4(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 4]; - sp_digit t2d[2 * 4]; + sp_digit t1[4 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) { err = MEMORY_E; } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 4; - t2 = d + 2 * 4; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 4; #ifdef HAVE_INTEL_AVX2 if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { @@ -24418,10 +24884,9 @@ static int sp_256_mont_sqrt_4(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -24437,34 +24902,25 @@ static int sp_256_mont_sqrt_4(sp_digit* y) */ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 4]; - sp_digit yd[2 * 4]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 4]; +#endif sp_digit* y = NULL; int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 4; - y = d + 2 * 4; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 4; sp_256_from_mp(x, 4, xm); err = sp_256_mod_mul_norm_4(x, x, p256_mod); @@ -24504,10 +24960,9 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) err = sp_256_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -24518,9 +24973,13 @@ int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) /* Point structure to use. */ typedef struct sp_point_384 { + /* X ordinate of point. */ sp_digit x[2 * 6]; + /* Y ordinate of point. */ sp_digit y[2 * 6]; + /* Z ordinate of point. */ sp_digit z[2 * 6]; + /* Indicates point is at infinity. */ int infinity; } sp_point_384; @@ -24558,8 +25017,9 @@ static const sp_digit p384_norm_order[6] = { #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) /* The Montogmery multiplier for order of the curve P384. */ -static sp_digit p384_mp_order = 0x6ed46089e88fdc45l; +static sp_digit p384_mp_order = 0x6ed46089e88fdc45L; #endif +#ifdef WOLFSSL_SP_SMALL /* The base point of curve P384. */ static const sp_point_384 p384_base = { /* X ordinate */ @@ -24583,6 +25043,7 @@ static const sp_point_384 p384_base = { /* infinity */ 0 }; +#endif /* WOLFSSL_SP_SMALL */ #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) static const sp_digit p384_b[6] = { 0x2a85c8edd3ec2aefL,0xc656398d8a2ed19dL,0x0314088f5013875aL, @@ -24590,50 +25051,10 @@ static const sp_digit p384_b[6] = { }; #endif -static int sp_384_point_new_ex_6(void* heap, sp_point_384* sp, sp_point_384** p) -{ - int ret = MP_OKAY; - (void)heap; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - (void)sp; - *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); -#else - *p = sp; -#endif - if (*p == NULL) { - ret = MEMORY_E; - } - return ret; -} - -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* Allocate memory for point and return error. */ -#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), NULL, &(p)) -#else -/* Set pointer to data and return no error. */ -#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), &(sp), &(p)) -#endif - - -static void sp_384_point_free_6(sp_point_384* p, int clear, void* heap) -{ -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) -/* If valid pointer then clear point data if requested and free data. */ - if (p != NULL) { - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } - XFREE(p, heap, DYNAMIC_TYPE_ECC); - } -#else -/* Clear point data if requested. */ - if (clear != 0) { - XMEMSET(p, 0, sizeof(*p)); - } -#endif - (void)heap; -} - +extern void sp_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_384_sqr_6(sp_digit* r, const sp_digit* a); +extern sp_digit sp_384_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_384_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b); /* Multiply a number by Montogmery normalizer mod modulus (prime). * * r The resulting Montgomery form number. @@ -24643,34 +25064,25 @@ static void sp_384_point_free_6(sp_point_384* p, int clear, void* heap) */ static int sp_384_mod_mul_norm_6(sp_digit* r, const sp_digit* a, const sp_digit* m) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - int64_t* td; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t = NULL; #else - int64_t td[12]; - int64_t a32d[12]; + int64_t t[2 * 12]; #endif - int64_t* t; - int64_t* a32; + int64_t* a32 = NULL; int64_t o; int err = MP_OKAY; (void)m; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); - if (td == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = td; - a32 = td + 12; -#else - t = td; - a32 = a32d; -#endif + a32 = t + 12; a32[0] = a[0] & 0xffffffff; a32[1] = a[0] >> 32; @@ -24746,9 +25158,9 @@ static int sp_384_mod_mul_norm_6(sp_digit* r, const sp_digit* a, const sp_digit* r[5] = (t[11] << 32) | t[10]; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (td != NULL) - XFREE(td, NULL, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -24771,7 +25183,8 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #elif DIGIT_BIT > 64 - int i, j = 0; + int i; + int j = 0; word32 s = 0; r[0] = 0; @@ -24805,7 +25218,9 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) r[j] = 0; } #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r[0] = 0; for (i = 0; i < a->used && j < size; i++) { @@ -24841,7 +25256,8 @@ static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) * p Point of type sp_point_384 (result). * pm Point of type ecc_point. */ -static void sp_384_point_from_ecc_point_6(sp_point_384* p, const ecc_point* pm) +static void sp_384_point_from_ecc_point_6(sp_point_384* p, + const ecc_point* pm) { XMEMSET(p->x, 0, sizeof(p->x)); XMEMSET(p->y, 0, sizeof(p->y)); @@ -24868,17 +25284,19 @@ static int sp_384_to_mp(const sp_digit* a, mp_int* r) r->used = 6; mp_clamp(r); #elif DIGIT_BIT < 64 - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 6; i++) { r->dp[j] |= (mp_digit)(a[i] << s); - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; s = DIGIT_BIT - s; r->dp[++j] = (mp_digit)(a[i] >> s); while (s + DIGIT_BIT <= 64) { s += DIGIT_BIT; - r->dp[j++] &= (1L << DIGIT_BIT) - 1; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; if (s == SP_WORD_SIZE) { r->dp[j] = 0; } @@ -24891,14 +25309,16 @@ static int sp_384_to_mp(const sp_digit* a, mp_int* r) r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; mp_clamp(r); #else - int i, j = 0, s = 0; + int i; + int j = 0; + int s = 0; r->dp[0] = 0; for (i = 0; i < 6; i++) { r->dp[j] |= ((mp_digit)a[i]) << s; if (s + 64 >= DIGIT_BIT) { #if DIGIT_BIT != 32 && DIGIT_BIT != 64 - r->dp[j] &= (1L << DIGIT_BIT) - 1; + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; #endif s = DIGIT_BIT - s; r->dp[++j] = a[i] >> s; @@ -24939,7 +25359,6 @@ static int sp_384_point_to_ecc_point_6(const sp_point_384* p, ecc_point* pm) } extern void sp_384_cond_copy_6(sp_digit* r, const sp_digit* a, sp_digit m); -extern void sp_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b); extern sp_digit sp_384_cond_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_384_mont_reduce_6(sp_digit* a, const sp_digit* m, sp_digit mp); extern void sp_384_mont_reduce_order_6(sp_digit* a, const sp_digit* m, sp_digit mp); @@ -24952,14 +25371,13 @@ extern void sp_384_mont_reduce_order_6(sp_digit* a, const sp_digit* m, sp_digit * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_6(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_6(r, a, b); sp_384_mont_reduce_6(r, m, mp); } -extern void sp_384_sqr_6(sp_digit* r, const sp_digit* a); /* Square the Montgomery form number. (r = a * a mod m) * * r Result of squaring. @@ -24967,8 +25385,8 @@ extern void sp_384_sqr_6(sp_digit* r, const sp_digit* a); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_6(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_6(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_6(r, a); sp_384_mont_reduce_6(r, m, mp); @@ -24992,7 +25410,7 @@ static void sp_384_mont_sqr_n_6(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ #ifdef WOLFSSL_SP_SMALL /* Mod-2 for the P384 curve. */ static const uint64_t p384_mod_minus_2[6] = { @@ -25099,7 +25517,8 @@ extern int64_t sp_384_cmp_6(const sp_digit* a, const sp_digit* b); * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*6; @@ -25135,7 +25554,6 @@ static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) } -extern sp_digit sp_384_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b); /* Add two Montgomery form numbers (r = a + b % m). * * r Result of addition. @@ -25183,7 +25601,6 @@ static void sp_384_mont_tpl_6(sp_digit* r, const sp_digit* a, const sp_digit* m) sp_384_cond_sub_6(r, r, m, 0 - o); } -extern sp_digit sp_384_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b); extern sp_digit sp_384_cond_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); /* Subtract two Montgomery form numbers (r = a - b % m). * @@ -25404,7 +25821,8 @@ static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_d * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_6(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_6(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*6; @@ -25708,8 +26126,8 @@ static int sp_384_proj_point_add_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_6(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -25802,8 +26220,8 @@ static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, cons * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* p, - int n, int m, sp_digit* t) +static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, + const sp_point_384* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*6; @@ -25814,6 +26232,7 @@ static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* sp_digit* y = r[(1<x[i]; @@ -25830,7 +26249,10 @@ static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* /* W = Z^4 */ sp_384_mont_sqr_6(w, z, p384_mod, p384_mp_mod); sp_384_mont_sqr_6(w, w, p384_mod, p384_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); sp_384_mont_sub_6(t1, t1, w, p384_mod); @@ -25838,14 +26260,14 @@ static void sp_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* /* B = X*Y^2 */ sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); sp_384_mont_mul_6(b, t2, x, p384_mod, p384_mp_mod); - x = r[(1<y); + sp_384_norm_6(negy); sp_384_cond_copy_6(p->y, negy, (sp_digit)0 - v[i].neg); sp_384_proj_point_add_6(rt, rt, p, tmp); } @@ -26149,19 +26573,18 @@ static int sp_384_ecc_mulmod_win_add_sub_6(sp_point_384* r, const sp_point_384* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(rt, 0, heap); return err; } #ifdef HAVE_INTEL_AVX2 +#define sp_384_mod_mul_norm_avx2_6 sp_384_mod_mul_norm_6 #ifdef HAVE_INTEL_AVX2 extern void sp_384_mul_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b); #define sp_384_mont_reduce_avx2_6 sp_384_mont_reduce_6 @@ -26175,8 +26598,8 @@ extern void sp_384_mont_reduce_order_avx2_6(sp_digit* a, const sp_digit* m, sp_d * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_mul_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b, - const sp_digit* m, sp_digit mp) +static void sp_384_mont_mul_avx2_6(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) { sp_384_mul_avx2_6(r, a, b); sp_384_mont_reduce_avx2_6(r, m, mp); @@ -26192,8 +26615,8 @@ extern void sp_384_sqr_avx2_6(sp_digit* r, const sp_digit* a); * m Modulus (prime). * mp Montogmery mulitplier. */ -static void sp_384_mont_sqr_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* m, - sp_digit mp) +static void sp_384_mont_sqr_avx2_6(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) { sp_384_sqr_avx2_6(r, a); sp_384_mont_reduce_avx2_6(r, m, mp); @@ -26218,7 +26641,7 @@ static void sp_384_mont_sqr_n_avx2_6(sp_digit* r, const sp_digit* a, int n, } } -#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */ /* Invert the number, in Montgomery form, modulo the modulus (prime) of the * P384 curve. (r = 1 / a mod m) @@ -26305,13 +26728,15 @@ static void sp_384_mont_inv_avx2_6(sp_digit* r, const sp_digit* a, sp_digit* td) #endif /* WOLFSSL_SP_SMALL */ } +extern sp_digit sp_384_cond_sub_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); /* Map the Montgomery form projective coordinate point to an affine point. * * r Resulting affine coordinate point. * p Montgomery form projective coordinate point. * t Temporary ordinate data. */ -static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, + sp_digit* t) { sp_digit* t1 = t; sp_digit* t2 = t + 2*6; @@ -26325,7 +26750,7 @@ static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* /* x /= z^2 */ sp_384_mont_mul_avx2_6(r->x, p->x, t2, p384_mod, p384_mp_mod); XMEMSET(r->x + 6, 0, sizeof(r->x) / 2U); - sp_384_mont_reduce_6(r->x, p384_mod, p384_mp_mod); + sp_384_mont_reduce_avx2_6(r->x, p384_mod, p384_mp_mod); /* Reduce x to less than modulus */ n = sp_384_cmp_6(r->x, p384_mod); sp_384_cond_sub_6(r->x, r->x, p384_mod, 0 - ((n >= 0) ? @@ -26335,10 +26760,10 @@ static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* /* y /= z^3 */ sp_384_mont_mul_avx2_6(r->y, p->y, t1, p384_mod, p384_mp_mod); XMEMSET(r->y + 6, 0, sizeof(r->y) / 2U); - sp_384_mont_reduce_6(r->y, p384_mod, p384_mp_mod); + sp_384_mont_reduce_avx2_6(r->y, p384_mod, p384_mp_mod); /* Reduce y to less than modulus */ n = sp_384_cmp_6(r->y, p384_mod); - sp_384_cond_sub_6(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + sp_384_cond_sub_avx2_6(r->y, r->y, p384_mod, 0 - ((n >= 0) ? (sp_digit)1 : (sp_digit)0)); sp_384_norm_6(r->y); @@ -26347,6 +26772,11 @@ static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* } +#define sp_384_mont_add_avx2_6 sp_384_mont_add_6 +#define sp_384_mont_dbl_avx2_6 sp_384_mont_dbl_6 +#define sp_384_mont_tpl_avx2_6 sp_384_mont_tpl_6 +#define sp_384_mont_sub_avx2_6 sp_384_mont_sub_6 +extern void sp_384_div2_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* m); /* Double the Montgomery form projective point p. * * r Result of doubling point. @@ -26509,37 +26939,37 @@ static void sp_384_proj_point_dbl_avx2_6(sp_point_384* r, const sp_point_384* p, /* Z = Y * Z */ sp_384_mont_mul_avx2_6(z, p->y, p->z, p384_mod, p384_mp_mod); /* Z = 2Z */ - sp_384_mont_dbl_6(z, z, p384_mod); + sp_384_mont_dbl_avx2_6(z, z, p384_mod); /* T2 = X - T1 */ - sp_384_mont_sub_6(t2, p->x, t1, p384_mod); + sp_384_mont_sub_avx2_6(t2, p->x, t1, p384_mod); /* T1 = X + T1 */ - sp_384_mont_add_6(t1, p->x, t1, p384_mod); + sp_384_mont_add_avx2_6(t1, p->x, t1, p384_mod); /* T2 = T1 * T2 */ sp_384_mont_mul_avx2_6(t2, t1, t2, p384_mod, p384_mp_mod); /* T1 = 3T2 */ - sp_384_mont_tpl_6(t1, t2, p384_mod); + sp_384_mont_tpl_avx2_6(t1, t2, p384_mod); /* Y = 2Y */ - sp_384_mont_dbl_6(y, p->y, p384_mod); + sp_384_mont_dbl_avx2_6(y, p->y, p384_mod); /* Y = Y * Y */ sp_384_mont_sqr_avx2_6(y, y, p384_mod, p384_mp_mod); /* T2 = Y * Y */ sp_384_mont_sqr_avx2_6(t2, y, p384_mod, p384_mp_mod); /* T2 = T2/2 */ - sp_384_div2_6(t2, t2, p384_mod); + sp_384_div2_avx2_6(t2, t2, p384_mod); /* Y = Y * X */ sp_384_mont_mul_avx2_6(y, y, p->x, p384_mod, p384_mp_mod); /* X = T1 * T1 */ sp_384_mont_sqr_avx2_6(x, t1, p384_mod, p384_mp_mod); /* X = X - Y */ - sp_384_mont_sub_6(x, x, y, p384_mod); + sp_384_mont_sub_avx2_6(x, x, y, p384_mod); /* X = X - Y */ - sp_384_mont_sub_6(x, x, y, p384_mod); + sp_384_mont_sub_avx2_6(x, x, y, p384_mod); /* Y = Y - X */ - sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_avx2_6(y, y, x, p384_mod); /* Y = Y * T1 */ sp_384_mont_mul_avx2_6(y, y, t1, p384_mod, p384_mp_mod); /* Y = Y - T2 */ - sp_384_mont_sub_6(y, y, t2, p384_mod); + sp_384_mont_sub_avx2_6(y, y, t2, p384_mod); } /* Double the Montgomery form projective point p a number of times. @@ -26549,7 +26979,8 @@ static void sp_384_proj_point_dbl_avx2_6(sp_point_384* r, const sp_point_384* p, * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) +static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, + sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*6; @@ -26565,7 +26996,7 @@ static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) z = p->z; /* Y = 2*Y */ - sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_dbl_avx2_6(y, y, p384_mod); /* W = Z^4 */ sp_384_mont_sqr_avx2_6(w, z, p384_mod, p384_mp_mod); sp_384_mont_sqr_avx2_6(w, w, p384_mod, p384_mp_mod); @@ -26578,15 +27009,15 @@ static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) { /* A = 3*(X^2 - W) */ sp_384_mont_sqr_avx2_6(t1, x, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(t1, t1, w, p384_mod); - sp_384_mont_tpl_6(a, t1, p384_mod); + sp_384_mont_sub_avx2_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_avx2_6(a, t1, p384_mod); /* B = X*Y^2 */ sp_384_mont_sqr_avx2_6(t1, y, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(b, t1, x, p384_mod, p384_mp_mod); /* X = A^2 - 2B */ sp_384_mont_sqr_avx2_6(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_6(t2, b, p384_mod); - sp_384_mont_sub_6(x, x, t2, p384_mod); + sp_384_mont_dbl_avx2_6(t2, b, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t2, p384_mod); /* Z = Z*Y */ sp_384_mont_mul_avx2_6(z, z, y, p384_mod, p384_mp_mod); /* t2 = Y^4 */ @@ -26599,35 +27030,35 @@ static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) sp_384_mont_mul_avx2_6(w, w, t1, p384_mod, p384_mp_mod); } /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_sub_avx2_6(y, b, x, p384_mod); sp_384_mont_mul_avx2_6(y, y, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_6(y, y, p384_mod); - sp_384_mont_sub_6(y, y, t1, p384_mod); + sp_384_mont_dbl_avx2_6(y, y, p384_mod); + sp_384_mont_sub_avx2_6(y, y, t1, p384_mod); } #ifndef WOLFSSL_SP_SMALL /* A = 3*(X^2 - W) */ sp_384_mont_sqr_avx2_6(t1, x, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(t1, t1, w, p384_mod); - sp_384_mont_tpl_6(a, t1, p384_mod); + sp_384_mont_sub_avx2_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_avx2_6(a, t1, p384_mod); /* B = X*Y^2 */ sp_384_mont_sqr_avx2_6(t1, y, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(b, t1, x, p384_mod, p384_mp_mod); /* X = A^2 - 2B */ sp_384_mont_sqr_avx2_6(x, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_6(t2, b, p384_mod); - sp_384_mont_sub_6(x, x, t2, p384_mod); + sp_384_mont_dbl_avx2_6(t2, b, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t2, p384_mod); /* Z = Z*Y */ sp_384_mont_mul_avx2_6(z, z, y, p384_mod, p384_mp_mod); /* t2 = Y^4 */ sp_384_mont_sqr_avx2_6(t1, t1, p384_mod, p384_mp_mod); /* y = 2*A*(B - X) - Y^4 */ - sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_sub_avx2_6(y, b, x, p384_mod); sp_384_mont_mul_avx2_6(y, y, a, p384_mod, p384_mp_mod); - sp_384_mont_dbl_6(y, y, p384_mod); - sp_384_mont_sub_6(y, y, t1, p384_mod); + sp_384_mont_dbl_avx2_6(y, y, p384_mod); + sp_384_mont_sub_avx2_6(y, y, t1, p384_mod); #endif /* Y = Y/2 */ - sp_384_div2_6(y, y, p384_mod); + sp_384_div2_avx2_6(y, y, p384_mod); } /* Add two Montgomery form projective points. @@ -26840,8 +27271,8 @@ static int sp_384_proj_point_add_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r } #endif /* WOLFSSL_SP_NONBLOCK */ -static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, - sp_digit* t) +static void sp_384_proj_point_add_avx2_6(sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) { const sp_point_384* ap[2]; sp_point_384* rp[2]; @@ -26867,7 +27298,7 @@ static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, sp_384_norm_6(t1); if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { - sp_384_proj_point_dbl_6(r, p, t); + sp_384_proj_point_dbl_avx2_6(r, p, t); } else { rp[0] = r; @@ -26905,9 +27336,9 @@ static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, /* S2 = Y2*Z1^3 */ sp_384_mont_mul_avx2_6(t4, t4, q->y, p384_mod, p384_mp_mod); /* H = U2 - U1 */ - sp_384_mont_sub_6(t2, t2, t1, p384_mod); + sp_384_mont_sub_avx2_6(t2, t2, t1, p384_mod); /* R = S2 - S1 */ - sp_384_mont_sub_6(t4, t4, t3, p384_mod); + sp_384_mont_sub_avx2_6(t4, t4, t3, p384_mod); /* Z3 = H*Z1*Z2 */ sp_384_mont_mul_avx2_6(z, z, q->z, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(z, z, t2, p384_mod, p384_mp_mod); @@ -26916,14 +27347,14 @@ static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, sp_384_mont_sqr_avx2_6(t5, t2, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(y, t1, t5, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t5, t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(x, x, t5, p384_mod); - sp_384_mont_dbl_6(t1, y, p384_mod); - sp_384_mont_sub_6(x, x, t1, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t5, p384_mod); + sp_384_mont_dbl_avx2_6(t1, y, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t1, p384_mod); /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ - sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_avx2_6(y, y, x, p384_mod); sp_384_mont_mul_avx2_6(y, y, t4, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t5, t5, t3, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(y, y, t5, p384_mod); + sp_384_mont_sub_avx2_6(y, y, t5, p384_mod); } } @@ -26934,8 +27365,8 @@ static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, * n Number of times to double * t Temporary ordinate data. */ -static void sp_384_proj_point_dbl_n_store_avx2_6(sp_point_384* r, const sp_point_384* p, - int n, int m, sp_digit* t) +static void sp_384_proj_point_dbl_n_store_avx2_6(sp_point_384* r, + const sp_point_384* p, int n, int m, sp_digit* t) { sp_digit* w = t; sp_digit* a = t + 2*6; @@ -26946,6 +27377,7 @@ static void sp_384_proj_point_dbl_n_store_avx2_6(sp_point_384* r, const sp_point sp_digit* y = r[(1<x[i]; @@ -26958,26 +27390,29 @@ static void sp_384_proj_point_dbl_n_store_avx2_6(sp_point_384* r, const sp_point } /* Y = 2*Y */ - sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_dbl_avx2_6(y, y, p384_mod); /* W = Z^4 */ sp_384_mont_sqr_avx2_6(w, z, p384_mod, p384_mp_mod); sp_384_mont_sqr_avx2_6(w, w, p384_mod, p384_mp_mod); + j = m; for (i=1; i<=n; i++) { + j *= 2; + /* A = 3*(X^2 - W) */ sp_384_mont_sqr_avx2_6(t1, x, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(t1, t1, w, p384_mod); - sp_384_mont_tpl_6(a, t1, p384_mod); + sp_384_mont_sub_avx2_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_avx2_6(a, t1, p384_mod); /* B = X*Y^2 */ sp_384_mont_sqr_avx2_6(t2, y, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(b, t2, x, p384_mod, p384_mp_mod); - x = r[(1<y, p384_mod, p384_mp_mod); /* H = U2 - U1 */ - sp_384_mont_sub_6(t2, t2, t1, p384_mod); + sp_384_mont_sub_avx2_6(t2, t2, t1, p384_mod); /* RS = S2 + S1 */ - sp_384_mont_add_6(t6, t4, t3, p384_mod); + sp_384_mont_add_avx2_6(t6, t4, t3, p384_mod); /* R = S2 - S1 */ - sp_384_mont_sub_6(t4, t4, t3, p384_mod); + sp_384_mont_sub_avx2_6(t4, t4, t3, p384_mod); /* Z3 = H*Z1*Z2 */ /* ZS = H*Z1*Z2 */ sp_384_mont_mul_avx2_6(z, z, q->z, p384_mod, p384_mp_mod); @@ -27057,21 +27493,21 @@ static void sp_384_proj_point_add_sub_avx2_6(sp_point_384* ra, sp_point_384* rs, sp_384_mont_sqr_avx2_6(t5, t2, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(y, t1, t5, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t5, t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(x, x, t5, p384_mod); - sp_384_mont_sub_6(xs, xs, t5, p384_mod); - sp_384_mont_dbl_6(t1, y, p384_mod); - sp_384_mont_sub_6(x, x, t1, p384_mod); - sp_384_mont_sub_6(xs, xs, t1, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t5, p384_mod); + sp_384_mont_sub_avx2_6(xs, xs, t5, p384_mod); + sp_384_mont_dbl_avx2_6(t1, y, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t1, p384_mod); + sp_384_mont_sub_avx2_6(xs, xs, t1, p384_mod); /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ - sp_384_mont_sub_6(ys, y, xs, p384_mod); - sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_avx2_6(ys, y, xs, p384_mod); + sp_384_mont_sub_avx2_6(y, y, x, p384_mod); sp_384_mont_mul_avx2_6(y, y, t4, p384_mod, p384_mp_mod); sp_384_sub_6(t6, p384_mod, t6); sp_384_mont_mul_avx2_6(ys, ys, t6, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t5, t5, t3, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(y, y, t5, p384_mod); - sp_384_mont_sub_6(ys, ys, t5, p384_mod); + sp_384_mont_sub_avx2_6(y, y, t5, p384_mod); + sp_384_mont_sub_avx2_6(ys, ys, t5, p384_mod); } /* Multiply the point by the scalar and return the result. @@ -27095,53 +27531,52 @@ static void sp_384_proj_point_add_sub_avx2_6(sp_point_384* ra, sp_point_384* rs, static int sp_384_ecc_mulmod_win_add_sub_avx2_6(sp_point_384* r, const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td[33]; - sp_point_384 rtd, pd; - sp_digit tmpd[2 * 6 * 6]; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 t[33+2]; + sp_digit tmp[2 * 6 * 6]; #endif - sp_point_384* t; - sp_point_384* rt; + sp_point_384* rt = NULL; sp_point_384* p = NULL; - sp_digit* tmp; sp_digit* negy; int i; ecc_recode_384 v[65]; - int err; + int err = MP_OKAY; /* Constant time used for cache attack resistance implementation. */ (void)ct; (void)heap; - err = sp_384_point_new_6(heap, rtd, rt); - if (err == MP_OKAY) - err = sp_384_point_new_6(heap, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 33, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * + (33+2), heap, DYNAMIC_TYPE_ECC); if (t == NULL) err = MEMORY_E; - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; -#else - t = td; - tmp = tmpd; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } #endif - if (err == MP_OKAY) { + rt = t + 33; + p = t + 33+1; + /* t[0] = {0, 0, 1} * norm */ XMEMSET(&t[0], 0, sizeof(t[0])); t[0].infinity = 1; /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_384_mod_mul_norm_6(t[1].x, g->x, p384_mod); + err = sp_384_mod_mul_norm_avx2_6(t[1].x, g->x, p384_mod); } if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_6(t[1].y, g->y, p384_mod); + err = sp_384_mod_mul_norm_avx2_6(t[1].y, g->y, p384_mod); } if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_6(t[1].z, g->z, p384_mod); + err = sp_384_mod_mul_norm_avx2_6(t[1].z, g->z, p384_mod); } if (err == MP_OKAY) { @@ -27197,6 +27632,7 @@ static int sp_384_ecc_mulmod_win_add_sub_avx2_6(sp_point_384* r, const sp_point_ XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384)); } sp_384_sub_6(negy, p384_mod, p->y); + sp_384_norm_6(negy); sp_384_cond_copy_6(p->y, negy, (sp_digit)0 - v[i].neg); sp_384_proj_point_add_avx2_6(rt, rt, p, tmp); } @@ -27209,14 +27645,12 @@ static int sp_384_ecc_mulmod_win_add_sub_avx2_6(sp_point_384* r, const sp_point_ } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); if (tmp != NULL) XFREE(tmp, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(rt, 0, heap); return err; } @@ -27228,8 +27662,8 @@ typedef struct sp_table_entry_384 { sp_digit y[6]; } sp_table_entry_384; -#ifdef FP_ECC -#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Add two Montgomery form projective points. The second point has a q value of * one. * Only the first point can be the same pointer as the result point. @@ -27336,6 +27770,10 @@ static void sp_384_proj_to_affine_6(sp_point_384* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 6 + * 64 entries + * 64 bits between * * a The base point. * table Place to store generated point data. @@ -27345,26 +27783,30 @@ static void sp_384_proj_to_affine_6(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_6(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_6(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); } if (err == MP_OKAY) { @@ -27388,14 +27830,14 @@ static int sp_384_gen_stripe_table_6(const sp_point_384* a, XMEMCPY(table[1].x, t->x, sizeof(table->x)); XMEMCPY(table[1].y, t->y, sizeof(table->y)); - for (i=1; i<8; i++) { - sp_384_proj_point_dbl_n_6(t, 48, tmp); + for (i=1; i<6; i++) { + sp_384_proj_point_dbl_n_6(t, 64, tmp); sp_384_proj_to_affine_6(t, tmp); XMEMCPY(table[1<x, sizeof(table->x)); XMEMCPY(table[1<y, sizeof(table->y)); } - for (i=1; i<8; i++) { + for (i=1; i<6; i++) { XMEMCPY(s1->x, table[1<x)); XMEMCPY(s1->y, table[1<y)); for (j=(1<z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 63; + for (j=0; j<6; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 64; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { - sp_384_get_entry_256_6(rt, table, y); + sp_384_get_entry_64_6(rt, table, y); } else #endif { @@ -27487,16 +27938,18 @@ static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); } rt->infinity = !y; - for (i=46; i>=0; i--) { + for (i=62; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<6; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 64; } sp_384_proj_point_dbl_6(rt, rt, t); #ifndef WC_NO_CACHE_RESISTANT if (ct) { - sp_384_get_entry_256_6(p, table, y); + sp_384_get_entry_64_6(p, table, y); } else #endif @@ -27516,32 +27969,41 @@ static int sp_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(rt, 0, heap); return err; } +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ #ifdef FP_ECC #ifndef FP_ENTRIES #define FP_ENTRIES 16 #endif +/* Cache entry - holds precomputation tables for a point. */ typedef struct sp_cache_384_t { + /* X ordinate of point that table was generated from. */ sp_digit x[6]; + /* Y ordinate of point that table was generated from. */ sp_digit y[6]; - sp_table_entry_384 table[256]; + /* Precomputation table for point. */ + sp_table_entry_384 table[64]; + /* Count of entries in table. */ uint32_t cnt; + /* Point and table set in entry. */ int set; } sp_cache_384_t; +/* Cache of tables. */ static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +/* Index of last entry in cache. */ static THREAD_LS_T int sp_cache_384_last = -1; +/* Cache has been initialized. */ static THREAD_LS_T int sp_cache_384_inited = 0; #ifndef HAVE_THREAD_LS @@ -27549,9 +28011,15 @@ static THREAD_LS_T int sp_cache_384_inited = 0; static wolfSSL_Mutex sp_cache_384_lock; #endif +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) { - int i, j; + int i; + int j; uint32_t least; if (sp_cache_384_inited == 0) { @@ -27658,8 +28126,8 @@ static int sp_384_ecc_mulmod_6(sp_point_384* r, const sp_point_384* g, const sp_ } #ifdef HAVE_INTEL_AVX2 -#ifdef FP_ECC -#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Add two Montgomery form projective points. The second point has a q value of * one. * Only the first point can be the same pointer as the result point. @@ -27689,7 +28157,7 @@ static void sp_384_proj_point_add_qz1_avx2_6(sp_point_384* r, const sp_point_384 sp_384_norm_6(t1); if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { - sp_384_proj_point_dbl_6(r, p, t); + sp_384_proj_point_dbl_avx2_6(r, p, t); } else { rp[0] = r; @@ -27721,9 +28189,9 @@ static void sp_384_proj_point_add_qz1_avx2_6(sp_point_384* r, const sp_point_384 /* S2 = Y2*Z1^3 */ sp_384_mont_mul_avx2_6(t4, t4, q->y, p384_mod, p384_mp_mod); /* H = U2 - X1 */ - sp_384_mont_sub_6(t2, t2, x, p384_mod); + sp_384_mont_sub_avx2_6(t2, t2, x, p384_mod); /* R = S2 - Y1 */ - sp_384_mont_sub_6(t4, t4, y, p384_mod); + sp_384_mont_sub_avx2_6(t4, t4, y, p384_mod); /* Z3 = H*Z1 */ sp_384_mont_mul_avx2_6(z, z, t2, p384_mod, p384_mp_mod); /* X3 = R^2 - H^3 - 2*X1*H^2 */ @@ -27731,14 +28199,14 @@ static void sp_384_proj_point_add_qz1_avx2_6(sp_point_384* r, const sp_point_384 sp_384_mont_sqr_avx2_6(t5, t2, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t3, x, t5, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t5, t5, t2, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(x, t1, t5, p384_mod); - sp_384_mont_dbl_6(t1, t3, p384_mod); - sp_384_mont_sub_6(x, x, t1, p384_mod); + sp_384_mont_sub_avx2_6(x, t1, t5, p384_mod); + sp_384_mont_dbl_avx2_6(t1, t3, p384_mod); + sp_384_mont_sub_avx2_6(x, x, t1, p384_mod); /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ - sp_384_mont_sub_6(t3, t3, x, p384_mod); + sp_384_mont_sub_avx2_6(t3, t3, x, p384_mod); sp_384_mont_mul_avx2_6(t3, t3, t4, p384_mod, p384_mp_mod); sp_384_mont_mul_avx2_6(t5, t5, y, p384_mod, p384_mp_mod); - sp_384_mont_sub_6(y, t3, t5, p384_mod); + sp_384_mont_sub_avx2_6(y, t3, t5, p384_mod); } } @@ -27766,6 +28234,10 @@ static void sp_384_proj_to_affine_avx2_6(sp_point_384* a, sp_digit* t) } /* Generate the pre-computed table of points for the base point. + * + * width = 6 + * 64 entries + * 64 bits between * * a The base point. * table Place to store generated point data. @@ -27775,33 +28247,37 @@ static void sp_384_proj_to_affine_avx2_6(sp_point_384* a, sp_digit* t) static int sp_384_gen_stripe_table_avx2_6(const sp_point_384* a, sp_table_entry_384* table, sp_digit* tmp, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 td, s1d, s2d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; +#else + sp_point_384 t[3]; #endif - sp_point_384* t; sp_point_384* s1 = NULL; sp_point_384* s2 = NULL; - int i, j; - int err; + int i; + int j; + int err = MP_OKAY; (void)heap; - err = sp_384_point_new_6(heap, td, t); - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, s1d, s1); - } - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, s2d, s2); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); + s1 = t + 1; + s2 = t + 2; + + err = sp_384_mod_mul_norm_avx2_6(t->x, a->x, p384_mod); } if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_6(t->y, a->y, p384_mod); + err = sp_384_mod_mul_norm_avx2_6(t->y, a->y, p384_mod); } if (err == MP_OKAY) { - err = sp_384_mod_mul_norm_6(t->z, a->z, p384_mod); + err = sp_384_mod_mul_norm_avx2_6(t->z, a->z, p384_mod); } if (err == MP_OKAY) { t->infinity = 0; @@ -27818,14 +28294,14 @@ static int sp_384_gen_stripe_table_avx2_6(const sp_point_384* a, XMEMCPY(table[1].x, t->x, sizeof(table->x)); XMEMCPY(table[1].y, t->y, sizeof(table->y)); - for (i=1; i<8; i++) { - sp_384_proj_point_dbl_n_avx2_6(t, 48, tmp); + for (i=1; i<6; i++) { + sp_384_proj_point_dbl_n_avx2_6(t, 64, tmp); sp_384_proj_to_affine_avx2_6(t, tmp); XMEMCPY(table[1<x, sizeof(table->x)); XMEMCPY(table[1<y, sizeof(table->y)); } - for (i=1; i<8; i++) { + for (i=1; i<6; i++) { XMEMCPY(s1->x, table[1<x)); XMEMCPY(s1->y, table[1<y)); for (j=(1<z, p384_norm_mod, sizeof(p384_norm_mod)); XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); y = 0; - for (j=0,x=47; j<8; j++,x+=48) { + x = 63; + for (j=0; j<6; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 64; } #ifndef WC_NO_CACHE_RESISTANT if (ct) { - sp_384_get_entry_256_avx2_6(rt, table, y); + sp_384_get_entry_64_avx2_6(rt, table, y); } else #endif { @@ -27915,16 +28400,18 @@ static int sp_384_ecc_mulmod_stripe_avx2_6(sp_point_384* r, const sp_point_384* XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); } rt->infinity = !y; - for (i=46; i>=0; i--) { + for (i=62; i>=0; i--) { y = 0; - for (j=0,x=i; j<8; j++,x+=48) { + x = i; + for (j=0; j<6; j++) { y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 64; } sp_384_proj_point_dbl_avx2_6(rt, rt, t); #ifndef WC_NO_CACHE_RESISTANT if (ct) { - sp_384_get_entry_256_avx2_6(p, table, y); + sp_384_get_entry_64_avx2_6(p, table, y); } else #endif @@ -27944,17 +28431,17 @@ static int sp_384_ecc_mulmod_stripe_avx2_6(sp_point_384* r, const sp_point_384* } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) XFREE(t, heap, DYNAMIC_TYPE_ECC); - } + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(rt, 0, heap); return err; } +#endif /* FP_ECC | WOLFSSL_SP_SMALL */ /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * @@ -28018,31 +28505,34 @@ static int sp_384_ecc_mulmod_avx2_6(sp_point_384* r, const sp_point_384* g, cons * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, - void* heap) +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[6]; +#endif int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_384_point_new_6(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 6, km); sp_384_point_from_ecc_point_6(point, gm); @@ -28058,17 +28548,120 @@ int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, err = sp_384_point_to_ecc_point_6(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(point, 0, heap); return err; } -static const sp_table_entry_384 p384_table[256] = { +/* Multiply the point by the scalar, add point a and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[6 + 6 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (6 + 6 * 2 * 6), heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 6; + + sp_384_from_mp(k, 6, km); + sp_384_point_from_ecc_point_6(point, gm); + sp_384_point_from_ecc_point_6(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_avx2_6(point, point, k, 0, 0, heap); + else +#endif + err = sp_384_ecc_mulmod_6(point, point, k, 0, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_proj_point_add_avx2_6(point, point, addP, tmp); + else +#endif + sp_384_proj_point_add_6(point, point, addP, tmp); + + if (map) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_map_avx2_6(point, point, tmp); + else +#endif + sp_384_map_6(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Striping precomputation table. + * 6 points combined into a table of 64 points. + * Distance of 64 between points. + */ +static const sp_table_entry_384 p384_table[64] = { /* 0 */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, @@ -28078,1280 +28671,325 @@ static const sp_table_entry_384 p384_table[256] = { { 0x23043dad4b03a4feL,0xa1bfa8bf7bb4a9acL,0x8bade7562e83b050L, 0xc6c3521968f4ffd9L,0xdd8002263969a840L,0x2b78abc25a15c5e9L } }, /* 2 */ - { { 0x298647532b0c535bL,0x90dd695370506296L,0x038cd6b4216ab9acL, - 0x3df9b7b7be12d76aL,0x13f4d9785f347bdbL,0x222c5c9c13e94489L }, - { 0x5f8e796f2680dc64L,0x120e7cb758352417L,0x254b5d8ad10740b8L, - 0xc38b8efb5337dee6L,0xf688c2e194f02247L,0x7b5c75f36c25bc4cL } }, + { { 0xa54768dab1b43eefL,0x13e41f47e14fda22L,0x774df203faef6863L, + 0xf795a034bd7471b3L,0xf0958718b47de2e9L,0xc92f7888e1160cffL }, + { 0x86ded97b0146c790L,0x015918f5480a4b7bL,0x05588920424e8459L, + 0x37455914eecf8b2bL,0xe7d3df1fb968a6faL,0x07a0ffd6bad0719fL } }, /* 3 */ - { { 0xe26a3cc39edffea5L,0x35bbfd1c37d7e9fcL,0xf0e7700d9bde3ef6L, - 0x0380eb471a538f5aL,0x2e9da8bb05bf9eb3L,0xdbb93c731a460c3eL }, - { 0x37dba260f526b605L,0x95d4978efd785537L,0x24ed793aed72a04aL, - 0x2694837776005b1aL,0x99f557b99e681f82L,0xae5f9557d64954efL } }, + { { 0xda37cd535c54db6fL,0x0e37890a91f06c5cL,0x1730ef7be7ae7db5L, + 0x2b3dcd51ff045f54L,0xf5db3c3c72cc8451L,0x3165d6efcf0c185cL }, + { 0x177c4f6bf5958d78L,0xcb29d22f8d676a9fL,0x3bcf0068792ac96dL, + 0x60d1c6b719df5641L,0x426e412a68a099f8L,0xf9ca0c5c9f74d52bL } }, /* 4 */ - { { 0x24480c57f26feef9L,0xc31a26943a0e1240L,0x735002c3273e2bc7L, - 0x8c42e9c53ef1ed4cL,0x028babf67f4948e8L,0x6a502f438a978632L }, - { 0xf5f13a46b74536feL,0x1d218babd8a9f0ebL,0x30f36bcc37232768L, - 0xc5317b31576e8c18L,0xef1d57a69bbcb766L,0x917c4930b3e3d4dcL } }, + { { 0xf186d6bcc88d568aL,0x872bc4c7528535ddL,0xc9e7432edfe64dc3L, + 0xd9fc4832d795ea57L,0xf4ffdb81c845af2bL,0x66d7e7882b670517L }, + { 0xa7c1be04d7b7a1c6L,0xbed88479d5b2a249L,0x62ff8aba03f2ef6dL, + 0x60ecaac420dc701dL,0x9f4b559f4ff10119L,0x0582c9313cd54fd0L } }, /* 5 */ - { { 0x11426e2ee349ddd0L,0x9f117ef99b2fc250L,0xff36b480ec0174a6L, - 0x4f4bde7618458466L,0x2f2edb6d05806049L,0x8adc75d119dfca92L }, - { 0xa619d097b7d5a7ceL,0x874275e5a34411e9L,0x5403e0470da4b4efL, - 0x2ebaafd977901d8fL,0x5e63ebcea747170fL,0x12a369447f9d8036L } }, + { { 0x394fb84de86e3f64L,0xfe4a36e7ff13314eL,0xa1e44b14dc261ec2L, + 0x3924e50a7420408fL,0x637e330242ed7626L,0xeb657b10fd711ba4L }, + { 0xc16d01c5340949bbL,0x30e043267f1f42c7L,0xe7465819b056d872L, + 0x3386f1c6886fb3dbL,0x5be463a5be56f774L,0xa96fd3b74694e15aL } }, /* 6 */ - { { 0x28f9c07a4fc52870L,0xce0b37481a53a961L,0xd550fa180e1828d9L, - 0xa24abaf76adb225aL,0xd11ed0a56e58a348L,0xf3d811e6948acb62L }, - { 0x8618dd774c61ed22L,0x0bb747f980b47c9dL,0x22bf796fde6b8559L, - 0xfdfd1c6d680a21e9L,0xc0db15772af2c9ddL,0xa09379e6c1e90f3dL } }, + { { 0x95dd5ee5a98b4254L,0xea328205aa845e67L,0x98640fb5a1e36348L, + 0xd1bc5c251add5ee7L,0xc3158a423d11b799L,0x5feb68ed47c83d54L }, + { 0x7c5a1204963a207bL,0x2f2b2c7eee4671f8L,0xb63d291cd42867a6L, + 0x0b073620139530f4L,0xbe149492abb05b99L,0x21417da455accd2aL } }, /* 7 */ - { { 0x386c66efe085c629L,0x5fc2a461095bc89aL,0x1353d631203f4b41L, - 0x7ca1972b7e4bd8f5L,0xb077380aa7df8ce9L,0xd8a90389ee7e4ea3L }, - { 0x1bc74dc7e7b14461L,0xdc2cb0140c9c4f78L,0x52b4b3a684ef0a10L, - 0xbde6ea5d20327fe2L,0xb71ec435660f9615L,0xeede5a04b8ad8173L } }, + { { 0x9408555e9e5eba15L,0x416250137b7572c5L,0xfa53ee50bfff6ea7L, + 0x3d682de1e7b178c3L,0xb3e8769dec329f53L,0x1ab8c82e9eb524f4L }, + { 0x5bbd538dde2f1eb9L,0x1d1b0bea2b19c51eL,0xf785f9b98cb06eeeL, + 0x5cff29c6f58f21d5L,0x44aaa52245cbaef3L,0xd60c19427de40246L } }, /* 8 */ - { { 0x5584cbb3893b9a2dL,0x820c660b00850c5dL,0x4126d8267df2d43dL, - 0xdd5bbbf00109e801L,0x85b92ee338172f1cL,0x609d4f93f31430d9L }, - { 0x1e059a07eadaf9d6L,0x70e6536c0f125fb0L,0xd6220751560f20e7L, - 0xa59489ae7aaf3a9aL,0x7b70e2f664bae14eL,0x0dd0370176d08249L } }, - /* 9 */ - { { 0x4cc13be88510521fL,0x87315ba9f724cc17L,0xb49d83bb353dc263L, - 0x8b677efe0c279257L,0x510a1c1cc93c9537L,0x33e30cd8a4702c99L }, - { 0xf0ffc89d2208353fL,0x0170fa8dced42b2bL,0x090851ed26e2a5f5L, - 0x81276455ecb52c96L,0x0646c4e17fe1adf4L,0x513f047eb0868eabL } }, - /* 10 */ - { { 0xc07611f4df5bdf53L,0x45d331a758b11a6dL,0x58965daf1c4ee394L, - 0xba8bebe75a5878d1L,0xaecc0a1882dd3025L,0xcf2a3899a923eb8bL }, - { 0xf98c9281d24fd048L,0x841bfb598bbb025dL,0xb8ddf8cec9ab9d53L, - 0x538a4cb67fef044eL,0x092ac21f23236662L,0xa919d3850b66f065L } }, - /* 11 */ - { { 0x3db03b4085d480d8L,0x8cd9f4791b287a7dL,0x8f24dc754a8f3baeL, - 0x482eb8003db41892L,0x38bf9eb39c56e0f5L,0x8b9773209a91dc6fL }, - { 0xa31b05b27209cfc2L,0x4c49bf8505b2db70L,0x56462498d619527bL, - 0x3fe510391fac51baL,0xfb04f55eab4b8342L,0xc07c10dc04c6eabfL } }, - /* 12 */ - { { 0xad22fe4cdb32f048L,0x5f23bf91475ed6dfL,0xa50ce0c0aa66b6cbL, - 0xdf627a89f03405c0L,0x3674837df95e2d6aL,0x081c95b6ba42e64eL }, - { 0xeba3e036e71d6cebL,0xb45bcccf6c6b0271L,0x67b47e630684701dL, - 0x60f8f942e712523fL,0x824234725cd47adcL,0x83027d7987649cbbL } }, - /* 13 */ - { { 0xb3929ea63615b0b8L,0xb41441fda54dac41L,0x8995d556b5b6a368L, - 0xa80d4529167ef05eL,0xf6bcb4a16d25a27fL,0x210d6a4c7bd55b68L }, - { 0xf3804abb25351130L,0x1d2df699903e37ebL,0x5f201efc084c25c8L, - 0x31a28c87a1c68e91L,0x81dad253563f62a5L,0x5dd6de70d6c415d4L } }, - /* 14 */ - { { 0x29f470fd846612ceL,0x986f3eecda18d997L,0x6b84c1612f34af86L, - 0x5ef0a40846ddaf8bL,0x14405a00e49e795fL,0x5f491b16aa2f7a37L }, - { 0xc7f07ae4db41b38dL,0xef7d119e18fbfcaaL,0x3a18e07614443b19L, - 0x4356841a79a19926L,0x91f4a91ce2226fbeL,0xdc77248c3cc88721L } }, - /* 15 */ - { { 0xd570ff1ae4b1ec9dL,0x21d23e0ee7eef706L,0x3cde40f4ca19e086L, - 0x7d6523c4cd4bb270L,0x16c1f06cbf13aa6cL,0x5aa7245ad14c4b60L }, - { 0x37f8146744b74de8L,0x839e7a17620a934eL,0xf74d14e8de8b1aa1L, - 0x8789fa51f30d75e2L,0x09b24052c81c261eL,0x654e267833c565eeL } }, - /* 16 */ { { 0x378205de2f9fbe67L,0xc4afcb837f728e44L,0xdbcec06c682e00f1L, 0xf2a145c3114d5423L,0xa01d98747a52463eL,0xfc0935b17d717b0aL }, { 0x9653bc4fd4d01f95L,0x9aa83ea89560ad34L,0xf77943dcaf8e3f3fL, 0x70774a10e86fe16eL,0x6b62e6f1bf9ffdcfL,0x8a72f39e588745c9L } }, - /* 17 */ + /* 9 */ { { 0x73ade4da2341c342L,0xdd326e54ea704422L,0x336c7d983741cef3L, 0x1eafa00d59e61549L,0xcd3ed892bd9a3efdL,0x03faf26cc5c6c7e4L }, { 0x087e2fcf3045f8acL,0x14a65532174f1e73L,0x2cf84f28fe0af9a7L, 0xddfd7a842cdc935bL,0x4c0f117b6929c895L,0x356572d64c8bcfccL } }, + /* 10 */ + { { 0x984a6aed6420bc66L,0x6d90e0e0896a24a6L,0xe0adb93a18713003L, + 0xf00d424c1a8369fcL,0x636ebf14712ae802L,0xee39ff8ebe9d739aL }, + { 0xb330dd3e94f6d1dcL,0x6ba6780eb7731cf8L,0x4e569408198be5a2L, + 0x6639523b0193a22cL,0x6978cc9d91aa1455L,0x62062d8f329f9763L } }, + /* 11 */ + { { 0x7159107d80efff78L,0xf8ed5f8e8e4c39d5L,0x64a2265cc15e679cL, + 0xfc514e17a6d96c81L,0x59c86545f093e0a8L,0x804b0a588b5a336aL }, + { 0x94c32118cb9dcbcaL,0x2deb0e385d45251dL,0xd1092b0986869572L, + 0x073bf838fb2e9f97L,0x76b6d7d6de700fcbL,0xd2a6d110f2ddce5fL } }, + /* 12 */ + { { 0x6da7ccd0229de19eL,0x5050d45df0aa039dL,0xf9f01d68d9e7a861L, + 0x6d8b9f2000aa05f2L,0xae3d9698742cd4d9L,0x43e477abd560c394L }, + { 0x73d594991cb6dd81L,0x689162b2fac3f62eL,0xd6187ca864d1d0d5L, + 0xe8421a0d2f067457L,0x9b266acbea7c3a8dL,0x707e0e6e44df5cb3L } }, + /* 13 */ + { { 0x604b2a1a026511a0L,0xd4f6cf16256f4076L,0x7d823347b315a642L, + 0x8f805833786aa438L,0x9883df85f04bb4b3L,0x02bc10305bba6d84L }, + { 0xfe39a024a72c03acL,0xa980db635f2dbfd0L,0xcd53149f4f259ec6L, + 0xe969079b43f53f97L,0xd3849fdb42f9f27cL,0xd2cfd3f842653dc9L } }, + /* 14 */ + { { 0xbf69fe6a6abe7d80L,0x4932288192bb50e2L,0xc9e2f7fb61e8b18dL, + 0x24c74788f6c82421L,0xe79e5e3011c0b244L,0xd6612c70e0484571L }, + { 0x7863ff927ef82d17L,0x692790feb0a1b01cL,0xa2d6ffb5afe51546L, + 0xacdb43f26cf550c6L,0x3b3243dfaecfaf8fL,0x9557335ac233bcd9L } }, + /* 15 */ + { { 0x25e08c8faff5b387L,0x112c11e2d06208ceL,0x61031c1765234214L, + 0xba06f5550514764dL,0xfaacf6f39bd197d0L,0xe4b032321464a57fL }, + { 0x00c19adfe35dcd69L,0x81b75730a1c2646cL,0x47baa4fee0c50e32L, + 0xe9297832bcaddb3bL,0x1768d2f9d712c6cfL,0xfcef29fdb82e9eeaL } }, + /* 16 */ + { { 0xdbe04c3044ce3ad8L,0x995fbb1b4ce8aad5L,0xdbf8b54670911457L, + 0x9e683b5b3f7a1757L,0x7b89a08a9c7bd62cL,0x448865a40b3fc97eL }, + { 0x0ac9abfc3bb01e94L,0xa07760421e756124L,0x0aa6c335d9deed97L, + 0xe270580f72603e08L,0x70857a946c783bb2L,0xa0047774caa929aeL } }, + /* 17 */ + { { 0x56211190a353e889L,0x052917c3190eb198L,0xadfd85b03eee3d12L, + 0xde1d761779fd9c91L,0x05be51b7bf500159L,0x271f07178fcb87f1L }, + { 0x02673e273a75ac71L,0xb1b7246eda12da8dL,0xb25647928f5fb8c0L, + 0x0a22cbe1063b1d7fL,0xb0d7a7365649976eL,0x8f8e6e289e96b15dL } }, /* 18 */ - { { 0x7ecbac017d8c1bbaL,0x6058f9c390b0f3d5L,0xaee116e3f6197d0fL, - 0xc4dd70684033b128L,0xf084dba6c209b983L,0x97c7c2cf831dbc4aL }, - { 0x2f4e61ddf96010e8L,0xd97e4e20529faa17L,0x4ee6666069d37f20L, - 0xccc139ed3d366d72L,0x690b6ee213488e0fL,0x7cad1dc5f3a6d533L } }, + { { 0x8fc113f98312351cL,0xe837b9e0c5eff002L,0x7cb9ef074dad72fcL, + 0x18a8d43eb5eb7ee3L,0x2cf3ae844925efdbL,0x376e9e857756ec6aL }, + { 0xf77a79c8a3e3705fL,0x2d590b7d6c5fbab3L,0xa59713e27a4766c3L, + 0xb5da6a6861544174L,0xadb04a8adab1fe76L,0x03b6138d375143b4L } }, /* 19 */ - { { 0x660a9a81da57a41fL,0xe74a0412ec0039b6L,0x42343c6b5e1dad15L, - 0x284f3ff546681d4cL,0xb51087f163749e89L,0x070f23cc6f9f2f13L }, - { 0x542211da5d186e14L,0x84748f37fddb0dffL,0x41a3aab4db1f4180L, - 0x25ed667ba6402d0eL,0x2f2924a902f58355L,0x5844ee7cfa44a689L } }, + { { 0x20d88a80c1bfa043L,0x88806999672583ceL,0x195a89eaaea9b605L, + 0x0b9b4e8532bac07bL,0x8279965683868df6L,0x83c58afab52711a9L }, + { 0xb895c13d1c869283L,0x00f98d046206dde6L,0x76caaa22884bf311L, + 0x22b2137f995b29a5L,0x7f645809b098b07bL,0xa540c8a6050e2552L } }, /* 20 */ - { { 0xfab086073f3b236fL,0x19e9d41d81e221daL,0xf3f6571e3927b428L, - 0x4348a9337550f1f6L,0x7167b996a85e62f0L,0x62d437597f5452bfL }, - { 0xd85feb9ef2955926L,0x440a561f6df78353L,0x389668ec9ca36b59L, - 0x052bf1a1a22da016L,0xbdfbff72f6093254L,0x94e50f28e22209f3L } }, + { { 0x47980509e562d904L,0xe736f89d031e112cL,0xbc6bfb0765d8ae25L, + 0xe9ed4cc4ca459646L,0xf540e90e2fff67ffL,0x836280eb1a314e11L }, + { 0xa710b25041610627L,0xefc22b1573a9f9a2L,0x60f20789456498c0L, + 0x417920438052f4e7L,0x5c850903d5c0e80dL,0x52df5275bf1d8815L } }, /* 21 */ - { { 0x90b2e5b33062e8afL,0xa8572375e8a3d369L,0x3fe1b00b201db7b1L, - 0xe926def0ee651aa2L,0x6542c9beb9b10ad7L,0x098e309ba2fcbe74L }, - { 0x779deeb3fff1d63fL,0x23d0e80a20bfd374L,0x8452bb3b8768f797L, - 0xcf75bb4d1f952856L,0x8fe6b40029ea3faaL,0x12bd3e4081373a53L } }, + { { 0x25539de98ece218dL,0xb36574a8dca420baL,0x9d1812680e0d07feL, + 0xea79a5f5ad3ed34fL,0x8b739ad57c9277cfL,0xd88659886ee9a930L }, + { 0xaf07bfb621591a3eL,0xe0138c6508f3524fL,0xd3128f1297ee315eL, + 0x67f8641e21045f63L,0x3e1a96b140c73a2dL,0x8976b70305f51122L } }, /* 22 */ - { { 0xc023780d104cbba5L,0x6207e747fa35dd4cL,0x35c239281ca9b6a3L, - 0x4ff19be897987b10L,0xb8476bbf8022eee8L,0xaa0a4a14d3bbe74dL }, - { 0x20f94331187d4543L,0x3215387079f6e066L,0x83b0f74eac7e82e1L, - 0xa7748ba2828f06abL,0xc5f0298ac26ef35fL,0x0f0c50708e9a7dbdL } }, + { { 0xdeaf635731960db4L,0x680b054e5948d7f7L,0x0841e40fd272bb5cL, + 0x94d37db26e36117dL,0xaf2d001547f63ec8L,0x82665cdc47493309L }, + { 0xfe90e844abbe3851L,0x8357709afb79bc0cL,0x811a64d2b6bcc044L, + 0x1937c988882b3415L,0xe8b28724e267b271L,0x84d1eed0af89ed33L } }, /* 23 */ - { { 0x0c5c244cdef029ddL,0x3dabc687850661b8L,0x9992b865fe11d981L, - 0xe9801b8f6274dbadL,0xe54e6319098da242L,0x9929a91a91a53d08L }, - { 0x37bffd7235285887L,0xbc759425f1418102L,0x9280cc35fd2e6e20L, - 0x735c600cfbc42ee5L,0xb7ad28648837619aL,0xa3627231a778c57bL } }, + { { 0x52b8234f54c894a7L,0xfe54146fa2d11b70L,0x6412b5eb0aab6097L, + 0xa62499906a13a9daL,0xd2b1eb50adc448caL,0xe7ab51f9b115ab92L }, + { 0x4638ee62e76551d8L,0x74c3c1e1afe9c98dL,0x59000ad060d77322L, + 0x0a4b105ba06adc9aL,0xcdaeb4a496a6f616L,0x8c79c4a1864b49dcL } }, /* 24 */ - { { 0xae799b5c91361ed8L,0x47d71b756c63366cL,0x54cdd5211b265a6aL, - 0xe0215a5998d77b74L,0x4424d9b7bab29db0L,0x8b0ffacc7fd9e536L }, - { 0x46d85d1237b5d9efL,0x5b106d62bfa91747L,0xed0479f85f99ba2dL, - 0x0e6f39231d104de4L,0x83a84c8425e8983fL,0xa9507e0af8105a70L } }, + { { 0xc09c32d1c0b1bf15L,0x005d510f88d74e44L,0x031f9a9afc2c089eL, + 0x08aac7294ba183f0L,0xf227a7ceaf2245ebL,0xb4ec33cbb3a864ffL }, + { 0xdb76decd570a24f3L,0xea59387a12283a9eL,0x81b7c569341ef9a4L, + 0xad7c98bd8d77833aL,0x2182133b49ca80ffL,0x1de1d456085802b7L } }, /* 25 */ - { { 0xf6c68a6e14cf381cL,0xaf9d27bdc22e31ccL,0x23568d4daa8a5ccbL, - 0xe431eec0e338e4d2L,0xf1a828fe8f52ad1fL,0xdb6a0579e86acd80L }, - { 0x2885672e4507832aL,0x73fc275f887e5289L,0x65f8027805610d08L, - 0x8d9b4554075ff5b0L,0x3a8e8fb109f712b5L,0x39f0ac862ebe9cf2L } }, + { { 0xeead25b2e1c02860L,0xb2ae43694ff42d2eL,0x4b39a2ddfd61c1b0L, + 0x29c826ea968718a5L,0x877fdf15d9751a0aL,0x00b321dfb54affdfL }, + { 0x3c7c0778d4d5dbf7L,0x858a0fdccfc47423L,0xbd8e6544185b3063L, + 0xa22c3ef62da46a04L,0x5c2d84016a6c0ce1L,0x260246eddd6329aeL } }, /* 26 */ - { { 0xd8fabf784c52edf5L,0xdcd737e5a589ae53L,0x94918bf0d791ab17L, - 0xb5fbd956bcff06c9L,0xf6d3032edca46d45L,0x2cdff7e141a3e486L }, - { 0x6674b3ba61f47ec8L,0x8a882163eef84608L,0xa257c7054c687f90L, - 0xe30cb2edf6cdf227L,0x2c4c64ca7f6ea846L,0x186fa17ccc6bcd3cL } }, + { { 0x71753fc00c6463f6L,0x7ec14c015c6c9e33L,0x28b9ab9441ce6153L, + 0x3a1ac251a6702c8dL,0x2b124bc49ed6cb1fL,0x7a11c4be4fc7383fL }, + { 0x1414913509fac991L,0xf7c188d3cb1ee336L,0x754bc47391c3f406L, + 0x71d34587cad39500L,0x213dd1a7dd0399a1L,0x8457a8f671d05899L } }, /* 27 */ - { { 0x48a3f5361dfcb91eL,0x83595e13646d358aL,0xbd15827b91128798L, - 0x3ce612b82187757aL,0x873150a161bd7372L,0xf4684530b662f568L }, - { 0x8833950b401896f6L,0xe11cb89a77f3e090L,0xb2f12cac48e7f4a5L, - 0x313dd769f606677eL,0xfdcf08b316579f93L,0x6429cec946b8f22bL } }, + { { 0xa921ca662e9c06d3L,0x1d8974e89ba6521fL,0xbb465c775f79f791L, + 0x8f983f083a3954c8L,0x8492f8398b3935dcL,0x2b87d9c290c04426L }, + { 0xcec76ea403e60a28L,0x648e9830aa631308L,0x7b542f791eb86b73L, + 0xfc8cc9a3150d854dL,0x2be86940bfcc83feL,0x2e58a13ac88c7585L } }, /* 28 */ - { { 0x4984dd54bb75f9a4L,0x4aef06b929d3b570L,0xb5f84ca23d6e4c1eL, - 0x24c61c11b083ef35L,0xce4a7392392ca9ffL,0x865d65176730a800L }, - { 0xca3dfe76722b4a2bL,0x12c04bf97b083e0eL,0x803ce5b51b86b8a5L, - 0x3fc7632d6a7e3e0cL,0xc89970c2c81adbe4L,0x3cbcd3ad120e16b1L } }, + { { 0x19249a8fd1bc237fL,0xdec1c6a563505555L,0xc8256977bad2a93bL, + 0x78533659fc598170L,0x888a6578ee7e53cbL,0x28783b0e33766db3L }, + { 0xcf791e56e42c28f2L,0xfbf8dde8f9c37f4cL,0xf0ffaf1712c05395L, + 0xd27d21e9daf2f012L,0xf90432da9a7be009L,0xa459c036a8012f28L } }, /* 29 */ - { { 0xfbfb4cc7ec30ce93L,0x10ed6c7db72720a2L,0xec675bf747b55500L, - 0x90725903333ff7c3L,0xc7c3973e5075bfc0L,0xb049ecb007acf31bL }, - { 0xb4076eaf4f58839cL,0x101896daa2b05e4fL,0x3f6033b0ab40c66eL, - 0x19ee9eebc8d864baL,0xeb6cf15547bf6d2aL,0x8e5a9663f826477dL } }, + { { 0x4d99a7cac8b1c6d4L,0x8088818825c899c0L,0xbd27e9be2ebdeb3dL, + 0x73c3e0aa054e77c1L,0x180c848498534ce5L,0x750d52f754ffa9cdL }, + { 0x5f26eeb16f702f4cL,0x427fc6e4cc76d8f4L,0x93126b8d026b631dL, + 0x5356b93917e145a7L,0xc79ca872c0be7c84L,0x3fca7cad4b615fb7L } }, /* 30 */ - { { 0x69e62fddf7fbd5e1L,0x38ecfe5476912b1dL,0x845a3d56d1da3bfbL, - 0x0494950e1c86f0d4L,0x83cadbf93bc36ce8L,0x41fce5724fccc8d1L }, - { 0x05f939c28332c144L,0xb17f248b0871e46eL,0x3d8534e266e8aff6L, - 0x1d06f1dc3b85c629L,0xdb06a32ea3131b73L,0xf295184d8b3f64e5L } }, + { { 0xed48fe78d0241021L,0x252b14a0142f7f8eL,0x19ab85c6db573a09L, + 0x546c3960f3df906fL,0xc688f4b22c810ea8L,0xbccf0cca5ff9e108L }, + { 0x34f4609e3f2cc69bL,0xf3b1efe414afe4f4L,0x5d809cef37a8ef74L, + 0xa8d1978a176ba328L,0x75dde11fdf59ecb9L,0x34eeeaffa9916ee2L } }, /* 31 */ - { { 0xd9653ff736ddc103L,0x25f43e3795ef606fL,0x09e301fcfe06dce8L, - 0x85af234130b6eebfL,0x79b12b530ff56b20L,0x9b4fb499fe9a3c6bL }, - { 0x0154f89251d27ac2L,0xd33167e356ca5389L,0x7828ec1fafc065a6L, - 0x0959a2587f746c9bL,0xb18f1be30c44f837L,0xa7946117c4132fdbL } }, + { { 0xe7f603f248e83c85L,0xa94a539cfa581815L,0x5a61a596dba360b7L, + 0x6cc51dd16a77ef79L,0x4ff36ae0fdbceb9dL,0xfcff65323e8a9c07L }, + { 0x0ba0ce5436d4d0b8L,0x98087a452464efc2L,0xd456843bcc1a2ba7L, + 0x677384a53853e04cL,0x625d32d56c7971deL,0x86882509f724b331L } }, /* 32 */ - { { 0xc0426b775e3c647bL,0xbfcbd9398cf05348L,0x31d312e3172c0d3dL, - 0x5f49fde6ee754737L,0x895530f06da7ee61L,0xcf281b0ae8b3a5fbL }, - { 0xfd14973541b8a543L,0x41a625a73080dd30L,0xe2baae07653908cfL, - 0xc3d01436ba02a278L,0xa0d0222e7b21b8f8L,0xfdc270e9d7ec1297L } }, + { { 0xc20fb9111a42e5e7L,0x075a678b81d12863L,0x12bcbc6a5cc0aa89L, + 0x5279c6ab4fb9f01eL,0xbc8e178911ae1b89L,0xae74a706c290003cL }, + { 0x9949d6ec79df3f45L,0xba18e26296c8d37fL,0x68de6ee2dd2275bfL, + 0xa9e4fff8c419f1d5L,0xbc759ca4a52b5a40L,0xff18cbd863b0996dL } }, /* 33 */ - { { 0x00873c0cbc7f41d6L,0xd976113e1b7ad641L,0x2a536ff4238443fbL, - 0x030d00e241e62e45L,0x532e98675f545fc6L,0xcd0331088e91208cL }, - { 0xd1a04c999797612cL,0xd4393e02eea674e2L,0xd56fa69ee19742a1L, - 0xdd2ab48085f0590eL,0xa5cefc5248a2243dL,0x48cc67b654383f41L } }, + { { 0x684a681892a5eeeaL,0x1f5b193242a09264L,0x30bd8695d98a2f34L, + 0x6e775e019a8601fcL,0x8126bdc24ca956f8L,0x149e73d9e5595daaL }, + { 0x876428401f851e83L,0x4b8863dbd3a7c4a0L,0xe1e43b3d8c95d7d9L, + 0x7f1e307ea60fd528L,0xbf2fa5d134341610L,0x11ad4a8181c502d3L } }, /* 34 */ - { { 0x4e50430efc14ab48L,0x195b7f4f26706a74L,0x2fe8a228cc881ff6L, - 0xb1b968e2d945013dL,0x936aa5794b92162bL,0x4fb766b7364e754aL }, - { 0x13f93bca31e1ff7fL,0x696eb5cace4f2691L,0xff754bf8a2b09e02L, - 0x58f13c9ce58e3ff8L,0xb757346f1678c0b0L,0xd54200dba86692b3L } }, + { { 0xc7df022e782dd401L,0xd15aa9a9a7bcc543L,0x6aa42774b94df1d0L, + 0xab2660c30592a13eL,0xaf4e40809ffc40c7L,0x01152c8d9cd52b10L }, + { 0x649de1d99034a33aL,0x2b9d0ef0d758abfcL,0xdddd0bc2d458adddL, + 0xe5366ac9c09837f8L,0xa003abbb7b1ae35fL,0x880062887ab1fddeL } }, /* 35 */ - { { 0x9a030bbd6dda1265L,0xf7b4f3fce89718ddL,0xa6a4931f936065b8L, - 0xbce72d875f72241cL,0x6cbb51cb65775857L,0xc71618154e993675L }, - { 0xe81a0f792ee32189L,0xef2fab26277dc0b2L,0x9e64f6feb71f469fL, - 0xb448ce33dfdaf859L,0x3f5c1c4cbe6b5df1L,0xfb8dfb001de45f7bL } }, + { { 0x6b6c8f055288f1b4L,0xba05407c033738b4L,0x26cac3a941a955e3L, + 0x28f1692f8e0e0601L,0x2032cb36842c4887L,0x6adeba457d76b20fL }, + { 0xd282c2ce654c6f5cL,0x30584ca5be9ba4f1L,0x45d766a01b2c528bL, + 0xe918bad7c0c6f8ccL,0x1e050b2a0560f070L,0x4fc95de12d6dd010L } }, /* 36 */ - { { 0xc7345fa74d5bb921L,0x5c7e04be4d2b667eL,0x47ed3a80282d7a3eL, - 0x5c2777f87e47b2a4L,0x89b3b10008488e2eL,0x9aad77c2b2eb5b45L }, - { 0xd681bca7daac34aeL,0x2452e4e526afb326L,0x0c88792441a1ee14L, - 0x743b04d4c2407adeL,0xcb5e999bfc17a2acL,0x4dca2f824a701a06L } }, + { { 0x2bb26072150191d5L,0xea2617618108dcf6L,0x4dfa1303e6083c63L, + 0xfa4e0709e2876fb8L,0xf901fed0b1668763L,0xf01c53aeb82c967aL }, + { 0xb43e59d39ed827e8L,0xb58e157e57774eefL,0x57ee54e31b83dceeL, + 0x3d896f32613aa922L,0x69d40667b5c7bfc5L,0xd402b5cb77a2c0d8L } }, /* 37 */ - { { 0x68e31ca61127bc1aL,0xa3edd59b17ead3beL,0x67b6b645e25f5a15L, - 0x76221794a420e15eL,0x794fd83b4b1e872eL,0x7cab3f03b2dece1bL }, - { 0x7119bf15ca9b3586L,0xa55459244d250bd7L,0x173633eacc6bcf24L, - 0x9bd308c2b1b6f884L,0x3bae06f5447d38c3L,0x54dcc135f341fe1cL } }, + { { 0xabeb70127d3c9923L,0x412ada8dd7ecb93aL,0xeb64dc910b71ae2fL, + 0x52ef537aa9ab061aL,0x0863970fc1b55faeL,0xfaff5fb9b1182dbdL }, + { 0x5551d6fed0abaa17L,0x7bb3e02072d641f6L,0x939d7793aa9d288cL, + 0x1450f8bf9078e2c2L,0x24ccd102a086b6aeL,0x57d1796f6a3f8a5fL } }, /* 38 */ - { { 0x56d3598d943caf0dL,0xce044ea9225ff133L,0x9edf6a7c563fadeaL, - 0x632eb94473e8dc27L,0x814b467e3190dcabL,0x2d4f4f316dbb1e31L }, - { 0x8d69811ca143b7caL,0x4ec1ac32de7cf950L,0x223ab5fd37b5fe82L, - 0xe82616e49390f1d9L,0xabff4b2075804610L,0x11b9be15875b08f0L } }, + { { 0x1023120683ce1f76L,0xd16d4b9f03ee406fL,0x9d39c39883caa4b7L, + 0x875732f5ce299b93L,0x1e6a425d2f121f4aL,0x4b1f1d835d8c3279L }, + { 0xe655f58856dd6a6cL,0x23f106475843fd34L,0x932b7d942bad6ce2L, + 0x70a0580e6772a52eL,0x3240118ac88537afL,0x9ccb2ca9d2407224L } }, /* 39 */ - { { 0x4ae31a3d3bbe682cL,0xbc7c5d2674eef2ddL,0x92afd10a3c47dd40L, - 0xec7e0a3bc14ab9e1L,0x6a6c3dd1b2e495e4L,0x085ee5e9309bcd85L }, - { 0xf381a9088c2e67fdL,0x32083a80e261eaf2L,0x0fcd6a4996deee15L, - 0xe3b8fb035e524c79L,0x8dc360d91d5b08b9L,0x3a06e2c87f26719fL } }, + { { 0xa6a40db8710f2324L,0xb3567518c2a8a09aL,0x8816442841b5650aL, + 0x2a352ed27570ba50L,0x23ee46b94c85d77eL,0x643aceffd858a8c3L }, + { 0xe067908de3f02e82L,0x8d5869f2ffb8cf81L,0x4713f0820bc8ad7eL, + 0xe1ee44c780057c40L,0xb34395087d2cf34eL,0x4307b0e10336a207L } }, /* 40 */ - { { 0x5cd9f5a87237cac0L,0x93f0b59d43586794L,0x4384a764e94f6c4eL, - 0x8304ed2bb62782d3L,0x0b8db8b3cde06015L,0x4336dd535dbe190fL }, - { 0x5744355392ab473aL,0x031c7275be5ed046L,0x3e78678c21909aa4L, - 0x4ab7e04f99202ddbL,0x2648d2066977e635L,0xd427d184093198beL } }, + { { 0xe9c1e45746e4d003L,0xa23978c394332057L,0x0e2f300829575db6L, + 0x50a51ff490441e9eL,0x38ce3ed0508d4a07L,0x6a997411cfd7224eL }, + { 0x4d147c31da6b1e1dL,0xedf604b2da8a3547L,0x7a1b8cf0d5e9ceedL, + 0xd74e501213544e6aL,0xcc49f8da4ad968f9L,0xfb87e604cc69ada9L } }, /* 41 */ - { { 0x822848f50f9b5a31L,0xbb003468baadb62aL,0x233a04723357559cL, - 0x49ef688079aee843L,0xa89867a0aeb9e1e3L,0xc151931b1f6f9a55L }, - { 0xd264eb0bad74251eL,0x37b9b2634abf295eL,0xb600921b04960d10L, - 0x0de53dbc4da77dc0L,0x01d9bab3d2b18697L,0xad54ec7af7156ddfL } }, + { { 0xde79409bdf166882L,0xd645b836d46cc527L,0xda4a02f3b6c3eb28L, + 0x845e3c5900e7cf86L,0x733bdc9b604c6d80L,0xe3a1244b847acd97L }, + { 0x421312d6d128842cL,0x81f71feaa1c598efL,0xc619465545eaf796L, + 0x1ffb85121f338b6cL,0xe7aed7106632f064L,0xf8d1ffb7f5b6e510L } }, /* 42 */ - { { 0x8e74dc3579efdc58L,0x456bd3694ff68ddbL,0x724e74ccd32096a5L, - 0xe41cff42386783d0L,0xa04c7f217c70d8a4L,0x41199d2fe61a19a2L }, - { 0xd389a3e029c05dd2L,0x535f2a6be7e3fda9L,0x26ecf72d7c2b4df8L, - 0x678275f4fe745294L,0x6319c9cc9d23f519L,0x1e05a02d88048fc4L } }, + { { 0x7d3f031f3eace851L,0xef43ab7025923624L,0xbae811881af6cdecL, + 0xb7e93b49ea862112L,0xe35a4fc6af23aba2L,0xc52e1fc0aecc593eL }, + { 0xbffa292428148b99L,0xd08040fc89e3d795L,0x7da320032db47b3aL, + 0xe78b44e5a0eb7aa3L,0xd1648ec8f0ec090bL,0x4048dba7740fe871L } }, /* 43 */ - { { 0x75cc8e2ed4d5ffe8L,0xf8bb4896dbea17f2L,0x35059790cee3cb4aL, - 0x4c06ee85a47c6165L,0xf98fff2592935d2fL,0x34c4a57232ffd7c7L }, - { 0xc4b14806ea0376a2L,0x2ea5e7504f115e02L,0x532d76e21e55d7c0L, - 0x68dc9411f31044daL,0x9272e46571b77993L,0xadaa38bb93a8cfd5L } }, + { { 0x6fddb89fa00a14acL,0x844f991508aa06e7L,0x6d5ac4a9f76aca7dL, + 0xfba1ba85e9fa4d51L,0x159633bbb2ea0fc7L,0xa2eb0e4b76ba2854L }, + { 0x8a858155c11f5398L,0x30a96e535e8ea044L,0x696210c197e05a47L, + 0x86e55f9415036f4bL,0x0c93ea9c6a96d9d7L,0xb7ba506179eba3daL } }, /* 44 */ - { { 0x4bf0c7127d4ed72aL,0xda0e9264ba1f79a3L,0x48c0258bf4c39ea4L, - 0xa5394ed82a715138L,0x4af511cebf06c660L,0xfcebceefec5c37cdL }, - { 0xf23b75aa779ae8c1L,0xdeff59ccad1e606eL,0xf3f526fd22755c82L, - 0x64c5ab44bb32cefdL,0xa96e11a2915bdefdL,0xab19746a1143813eL } }, + { { 0xd305c733cd94d7b2L,0x9ea33e363e7955b2L,0x78a98855bc73812fL, + 0xfb1b791d48a3a9a0L,0x6e5107ee04014aafL,0x0412b2c00ea07de0L }, + { 0xdd3a2408ddcaca68L,0x5d18e69ae3344f29L,0x3ce65481f9017408L, + 0x50abb4568cbd64fbL,0x442fa5098916a9ebL,0x16b3ddc7c538c410L } }, /* 45 */ - { { 0x43c78585ec837d7dL,0xca5b6fbcb8ee0ba4L,0x34e924d9d5dbb5eeL, - 0x3f4fa104bb4f1ca5L,0x15458b72398640f7L,0x4231faa9d7f407eaL }, - { 0x53e0661ef96e6896L,0x554e4c69d03b0f9dL,0xd4fcb07b9c7858d1L, - 0x7e95279352cb04faL,0x5f5f15748974e7f7L,0x2e3fa5586b6d57c8L } }, + { { 0x6757dbfd25e331abL,0x0efde50ba3eaafbcL,0x1cd46222d531d29cL, + 0x1b713ca93561cb2bL,0x7d07334bfb5bc99dL,0x95dba43e885a417dL }, + { 0x1c9c3f3f77823a59L,0x43533ba83220cb7fL,0x1b918bc182e3e401L, + 0x66a039aacd3fec87L,0x1d39dbb02dad36d5L,0x554025959dc04be4L } }, /* 46 */ - { { 0x42cd48036a9951a8L,0xa8b15b8842792ad0L,0x18e8bcf9abb29a73L, - 0xbfd9a092409933e8L,0x760a3594efb88dc4L,0x1441886340724458L }, - { 0x162a56ee99caedc7L,0x8fb12ecd91d101c9L,0xea671967393202daL, - 0x1aac8c4aa4ccd796L,0x7db050361cf185a8L,0x0c9f86cd8cfd095aL } }, + { { 0xdf39920847744933L,0x4264f7ea82524dd6L,0xdb57ec08e5182c6dL, + 0x2d6778e705c5e7bfL,0x3f37793f96f53ea2L,0x6472cbae05c47e48L }, + { 0x9e6dd60fbf78067cL,0xa2817ec2cef34088L,0xde4715b8168edde9L, + 0x6c57105146bf31e1L,0x98113fbbc4272bc0L,0x03bb7922cc3b90c3L } }, /* 47 */ - { { 0x9a72814710b2a556L,0x767ca964327b70b2L,0x04ed9e125e3799b7L, - 0x6781d2dc22a3eb2aL,0x5bd116eb0d9450acL,0xeccac1fca7ebe08aL }, - { 0xde68444fdc2d6e94L,0x3621f42935ecf21bL,0x14e2d54329e03a2cL, - 0x53e42cd57d3e7f0aL,0xbba26c0973ed00b9L,0x00297c39c57d2272L } }, + { { 0xe0f23be157d88fefL,0x4125c55b0ca27a01L,0xeadf527e14a71262L, + 0x1f2e803ccc4e9a04L,0x32e07b47d68c4fcfL,0x1577fab79db5070bL }, + { 0xd786d6e57831990aL,0xf64ff4b154fbde40L,0x4bac5b034f9450aeL, + 0x06ae25e055116af9L,0x33d84ea2d7b4fcfcL,0x44a92e73569c3b9eL } }, /* 48 */ - { { 0x3aaaab10b8243a7dL,0x6eeef93e8fa58c5bL,0xf866fca39ae7f764L, - 0x64105a2661ab04d3L,0xa3578d8a03945d66L,0xb08cd3e4791b848cL }, - { 0x45edc5f8756d2411L,0xd4a790d9a755128cL,0xc2cf096349e5f6a0L, - 0xc66d267df649beaaL,0x3ce6d9688467039eL,0x50046c6b42f7816fL } }, + { { 0xf5bdccbabad0cb7fL,0x370f43ca958edd05L,0x3dd8232b04904a26L, + 0x3f8106682f4458e8L,0xdfcb67b99b3ace7eL,0x54e42f2d3e1241fcL }, + { 0xe30f3fb0db889300L,0x4ca0184b483e51fcL,0x5a32d097a638dac6L, + 0x567a2b5ec62a1db0L,0x2a756ba3c446456cL,0x6919026dd9f8d5c0L } }, /* 49 */ - { { 0x92ae160266425043L,0x1ff66afdf08db890L,0x386f5a7f8f162ce5L, - 0x18d2dea0fcf5598fL,0x78372b3a1a8ca18eL,0xdf0d20eb8cd0e6f7L }, - { 0x7edd5e1d75bb4045L,0x252a47ceb96d94b7L,0xbdb293582c626776L, - 0x853c394340dd1031L,0x9dc9becf7d5f47fdL,0x27c2302fbae4044aL } }, + { { 0x7f6493fc4fec874aL,0x8bb8a674d47a0770L,0x90bad2a652bd4f0cL, + 0x16badbe2f5733b07L,0x93be07cf93a1f802L,0x1e37a01541c395f7L }, + { 0xfe2c0fd6216582b3L,0xdcd98bc81627180dL,0x41e037268e8c9f1eL, + 0x93dbc22cfe8f45afL,0x5728c8a6ff45e059L,0x4f2f15cfca4a98cdL } }, /* 50 */ - { { 0x2d1d208a8f2d49ceL,0x0d91aa02162df0a2L,0x9c5cce8709a07f65L, - 0xdf07238b84339012L,0x5028e2c8419442cdL,0x2dcbd35872062abaL }, - { 0xb5fbc3cbe4680967L,0x2a7bc6459f92d72cL,0x806c76e1116c369dL, - 0x5c50677a3177e8d8L,0x753739eb4569df57L,0x2d481ef636c3f40bL } }, + { { 0xdbe2ec5d656e7d76L,0x84ad1b4bae2757bbL,0xc9297e7a0d4fec75L, + 0xfcc673eecad3ba87L,0xb0f77621dfd1671aL,0x5c386e449704a8c7L }, + { 0xce78f03f3e29256dL,0x0b185938c3a6ed2fL,0x7b1e2fae7824819bL, + 0x5a85d7f1f2d9313cL,0x238bd27973595b0fL,0x5fbf6b675c1cd2dcL } }, /* 51 */ - { { 0x1a2d39fdfea1103eL,0xeaae559295f81b17L,0xdbd0aa18f59b264aL, - 0x90c39c1acb592ee0L,0xdf62f80d9750cca3L,0xda4d8283df97cc6cL }, - { 0x0a6dd3461e201067L,0x1531f85969fb1f6bL,0x4895e5521d60121fL, - 0x0b21aab04c041c91L,0x9d896c46bcc1ccf8L,0xd24da3b33141bde7L } }, + { { 0x84d1ffb88a3e2412L,0xf01605926515f2feL,0x0e26ea9889905340L, + 0xbfd7a1b7203bd3d4L,0x5301273a88ea0bdaL,0x2f424475b28dd43eL }, + { 0x31014a2b33c28afaL,0xffbdea0c01e220eaL,0x681c64e8460b81d5L, + 0xdbe6f7286a91e1d5L,0x068bf36332619ad5L,0x4946291f27976c74L } }, /* 52 */ - { { 0x575a053753b0a354L,0x392ff2f40c6ddcd8L,0x0b8e8cff56157b94L, - 0x073e57bd3b1b80d1L,0x2a75e0f03fedee15L,0x752380e4aa8e6f19L }, - { 0x1f4e227c6558ffe9L,0x3a34861819ec5415L,0xab382d5ef7997085L, - 0x5e6deaffddc46ac2L,0xe5144078fc8d094cL,0xf674fe51f60e37c6L } }, + { { 0xa081a9462068e4b0L,0x1a8f5df609bfdad0L,0x5fbba5bcef28dd35L, + 0xa3e60d4f031ff71eL,0x2d47689b702ca18eL,0xd283f247c9b8e66bL }, + { 0x63e65dd7859ea140L,0x123da61f42aacdc3L,0xa8a9e893336f680cL, + 0x1cc4e12ac23d43acL,0x421e80d586a1fff8L,0x833d60d543deecc9L } }, /* 53 */ - { { 0x6fb87ae5af63408fL,0xa39c36a9cd75a737L,0x7833313fcf4c618dL, - 0xfbcd4482f034c88dL,0x4469a76139b35288L,0x77a711c566b5d9c9L }, - { 0x4a695dc7944f8d65L,0xe6da5f65161aaba8L,0x8654e9c324601669L, - 0xbc8b93f528ae7491L,0x5f1d1e838f5580d8L,0x8ccf9a1acea32cc8L } }, + { { 0x3c25b57c29014f8fL,0xa19fcb1e35d8e122L,0x916c0e3ceda32ac8L, + 0x9a23d289f36b6096L,0x5099038439a39871L,0xdc5b77b661c64196L }, + { 0x5a7d9917942bf2b6L,0xd21853934f41cf6dL,0x90ff1016fcc45c2fL, + 0x9891093deb8938aaL,0xe3c49b1baac4e6e9L,0x0f21a1d1d7a8e91eL } }, /* 54 */ - { { 0x28ab110c7196fee2L,0x75799d63874c8945L,0xa262934829aedaddL, - 0x9714cc7b2be88ff4L,0xf71293cfd58d60d6L,0xda6b6cb332a564e9L }, - { 0xf43fddb13dd821c2L,0xf2f2785f90dd323dL,0x91246419048489f8L, - 0x61660f26d24c6749L,0x961d9e8cc803c15cL,0x631c6158faadc4c9L } }, + { { 0x3a808e336f364b7eL,0x6a96d1b8bfa17359L,0x3387ec8552b36545L, + 0x2fde350af712180cL,0x9219d6f4703a2183L,0x8ba27e0086457946L }, + { 0x7446bca0ed80a9afL,0xbaf78b6f7203637aL,0x0304129d497c9d0fL, + 0x6df1e0356a883b68L,0x93ea2bb5e8018c47L,0xc86fd77cdb46443cL } }, /* 55 */ - { { 0xacf2ebe0fd752366L,0xb93c340e139be88bL,0x98f664850f20179eL, - 0x14820254ff1da785L,0x5278e2764f85c16eL,0xa246ee457aab1913L }, - { 0x43861eb453763b33L,0xc49f03fc45c0bc0dL,0xafff16bcad6b1ea1L, - 0xce33908b6fd49c99L,0x5c51e9bff7fde8c3L,0x076a7a39ff142c5eL } }, + { { 0x8de865d255dc2427L,0x74f7f83d6f72d126L,0xee1111786c7e665aL, + 0x272a8b3dddf44f12L,0xad3546449164eb4fL,0x2ffbdb586859d68fL }, + { 0xbefd36c509701865L,0x63c256162c983d01L,0x15a7ba0b2eb68703L, + 0x3318a82b5bb0fafcL,0x8e930fa9a0804f38L,0xb7459eb6be60ed1dL } }, /* 56 */ - { { 0x04639dfe9e338d10L,0x8ee6996ff42b411bL,0x960461d1a875cef2L, - 0x1057b6d695b4d0baL,0x27639252a906e0bcL,0x2c19f09ae1c20f8aL }, - { 0x5b8fc3f0eef4c43dL,0xe2e1b1a807a84aa9L,0x5f455528835d2bdbL, - 0x0f4aee4d207132ddL,0xe9f8338c3907f675L,0x7a874dc90e0531f0L } }, + { { 0xace01c514260b948L,0x04a6080f49210f78L,0x0d1eef6b2241b00dL, + 0x85a25069ef63912aL,0xcc96c4ec13dd8bc2L,0x90f14d1140d7e234L }, + { 0xae33f18ca69c8dc3L,0x76921f2a9adfa431L,0x18158ccf048c9f49L, + 0x90bcf7fbfb8fb345L,0x0d50b4dc38b3ff5dL,0x3914ea0b59ef84a8L } }, /* 57 */ - { { 0x84b22d4597c27050L,0xbd0b8df759e70bf8L,0xb4d6740579738b9bL, - 0x47f4d5f5cd917c4fL,0x9099c4ce13ce6e33L,0x942bfd39521d0f8bL }, - { 0x5028f0f6a43b566dL,0xaf6e866921bff7deL,0x83f6f856c44232cdL, - 0x65680579f915069aL,0xd12095a2ecfecb85L,0xcf7f06aedb01ba16L } }, + { { 0x4929d3f9d4e37cf3L,0x622183d1b24c24c0L,0x65cec0675f904d34L, + 0x65f9931a8a6f76faL,0xeed975b0e73282f2L,0xa045552a5e1625fdL }, + { 0xfd6b3e02f8fe8e42L,0x5f9f40256203907cL,0x8307eedb42b2c264L, + 0x2fb3ee719f757e92L,0x4502f2ecdc157ea8L,0xd976e7755d1cc0d5L } }, /* 58 */ - { { 0x0f56e3c48ef96c80L,0xd521f2b33ddb609cL,0x2be941027dc1450dL, - 0x2d21a07102a91fe2L,0x2e6f74fa1efa37deL,0x9a9a90b8156c28a1L }, - { 0xc54ea9ea9dc7dfcbL,0xc74e66fc2c2c1d62L,0x9f23f96749d3e067L, - 0x1c7c3a4654dd38adL,0xc70058845946cee3L,0x8985636845cc045dL } }, + { { 0xe46fb9a28fe1946eL,0xe91df3ed63bdde6eL,0x2e995306e9c28432L, + 0x7b3a6fe10988235bL,0xc55199f077f92a71L,0x47dd034853cb7950L }, + { 0xead52de2b727a6d1L,0xb87c9f75eea9c8daL,0xf3e2f3280d944f21L, + 0xce82734edd751eddL,0xfb83225ce616cedcL,0x15850e4b4a31eb49L } }, /* 59 */ - { { 0x29da7cd4fce73946L,0x8f697db523168563L,0x8e235e9ccba92ec6L, - 0x55d4655f9f91d3eaL,0xf3689f23aa50a6cdL,0xdcf21c2621e6a1a0L }, - { 0xcffbc82e61b818bfL,0xc74a2f96da47a243L,0x234e980a8bc1a0cfL, - 0xf35fd6b57929cb6dL,0x81468e12efe17d6cL,0xddea6ae558b2dafbL } }, + { { 0x92c4b6d50196ad3aL,0x0205ea484e1205e4L,0x8e08a97c0afc5affL, + 0xda8687c6727827ebL,0x2eace83106e398aaL,0x3a086c0f6d69e4e8L }, + { 0x5ff9b7aaf286e62aL,0xc428503962aae55eL,0x4ebd4258d9530a3fL, + 0x57ea313a8afc7fcbL,0x6d30a67522c18879L,0xd3c00cc994afb659L } }, /* 60 */ - { { 0x294de8877e787b2eL,0x258acc1f39a9310dL,0x92d9714aac14265dL, - 0x18b5591c708b48a0L,0x27cc6bb0e1abbf71L,0xc0581fa3568307b9L }, - { 0x9e0f58a3f24d4d58L,0xfebe9bb8e0ce2327L,0x91fd6a419d1be702L, - 0x9a7d8a45facac993L,0xabc0a08c9e50d66dL,0x02c342f706498201L } }, + { { 0x53ee47c5dee0d48bL,0xbd9e84ad9dfa2397L,0x2d581e12f81ba5e2L, + 0x26269f4f132cd325L,0x9e6224df58860a5fL,0x9306c607ff55522aL }, + { 0xb48af6d4146950e5L,0x09920ed00436805eL,0x3a1bc276cdce7eaeL, + 0x55ba728ac39a425eL,0x6a04d4e6d961d03eL,0x13891c66736e684aL } }, /* 61 */ - { { 0xccd71407157bdbc2L,0x72fa89c6ad0e1605L,0xb1d3da2bb92a015fL, - 0x8ad9e7cda0a3fe56L,0x160edcbd24f06737L,0x79d4db3361275be6L }, - { 0xd3d31fd95f3497c4L,0x8cafeaee04192fb0L,0xe13ca74513a50af3L, - 0x188261678c85aae5L,0xce06cea89eb556ffL,0x2eef1995bdb549f3L } }, + { { 0x7c75175a04cd04d6L,0xb76f9bd909c27a17L,0xa0cff6d408e5fe36L, + 0xc9097695dcd5ef90L,0x26bea24585e28054L,0x658e03c61580f068L }, + { 0x0da9f75e811eed27L,0x086e5e04aca0d2eeL,0xd4c157faa53a6787L, + 0x2e9266d2b40a595cL,0x8f1cb52698fa0820L,0x32a74240a1aef514L } }, /* 62 */ - { { 0x8ed7d3eb50596edcL,0xaa359362905243a2L,0xa212c2c2a4b6d02bL, - 0x611fd727c4fbec68L,0x8a0b8ff7b84f733dL,0xd85a6b905f0daf0eL }, - { 0x60e899f5d4091cf7L,0x4fef2b672eff2768L,0xc1f195cb10c33964L, - 0x8275d36993626a8fL,0xc77904f40d6c840aL,0x88d8b7fd7a868acdL } }, + { { 0xeb42e3d91ae86e7cL,0xd6956c8ce04a5026L,0x4c0b8b980f4302ebL, + 0xde43c938b37211fdL,0x9fa6a158e7090f80L,0x5f3c9afc73c47fb6L }, + { 0x2dc4f109f850a4d0L,0x56e63a4b6fd49d6aL,0x8e80a0694cbff048L, + 0x18d8b8cf2284afb0L,0x61dd086dc89363a1L,0x034c2202c37342a4L } }, /* 63 */ - { { 0x85f237237bd98425L,0xd4463992c70b154eL,0xcbb00ee296687a2eL, - 0x905fdbf7c83214fdL,0x2019d29313593684L,0x0428c393ef51218eL }, - { 0x40c7623f981e909aL,0x925133857be192daL,0x48fe480f4010907eL, - 0xdd7a187c3120b459L,0xc9d7702da1fd8f3cL,0x66e4753be358efc5L } }, - /* 64 */ - { { 0x070d34e116973cf4L,0x20aee08b7e4f34f7L,0x269af9b95eb8ad29L, - 0xdde0a036a6a45ddaL,0xa18b528e63df41e0L,0x03cc71b2a260df2aL }, - { 0x24a6770aa06b1dd7L,0x5bfa9c119d2675d3L,0x73c1e2a196844432L, - 0x3660558d131a6cf0L,0xb0289c832ee79454L,0xa6aefb01c6d8ddcdL } }, - /* 65 */ - { { 0xba1464b401ab5245L,0x9b8d0b6dc48d93ffL,0x939867dc93ad272cL, - 0xbebe085eae9fdc77L,0x73ae5103894ea8bdL,0x740fc89a39ac22e1L }, - { 0x5e28b0a328e23b23L,0x2352722ee13104d0L,0xf4667a18b0a2640dL, - 0xac74a72e49bb37c3L,0x79f734f0e81e183aL,0xbffe5b6c3fd9c0ebL } }, - /* 66 */ - { { 0xb1a358f5c6a2123fL,0x927b2d95fe28df6dL,0x89702753f199d2f9L, - 0x0a73754c1a3f82dcL,0x063d029d777affe1L,0x5439817edae6d34dL }, - { 0xf7979eef6b8b83c4L,0x615cb2149d945682L,0x8f0e4facc5e57eaeL, - 0x042b89b8113047ddL,0x888356dc93f36508L,0xbf008d185fd1f32fL } }, - /* 67 */ - { { 0x8012aa244e8068dbL,0xc72cc641a5729a47L,0x3c33df2c43f0691dL, - 0xfa0573471d92145fL,0xaefc0f2fb97f7946L,0x813d75cb2f8121bfL }, - { 0x05613c724383bba6L,0xa924ce70a4224b3fL,0xe59cecbe5f2179a6L, - 0x78e2e8aa79f62b61L,0x3ac2cc3b53ad8079L,0x55518d71d8f4fa96L } }, - /* 68 */ - { { 0x03cf292200623f3bL,0x095c71115f29ebffL,0x42d7224780aa6823L, - 0x044c7ba17458c0b0L,0xca62f7ef0959ec20L,0x40ae2ab7f8ca929fL }, - { 0xb8c5377aa927b102L,0x398a86a0dc031771L,0x04908f9dc216a406L, - 0xb423a73a918d3300L,0x634b0ff1e0b94739L,0xe29de7252d69f697L } }, - /* 69 */ - { { 0x744d14008435af04L,0x5f255b1dfec192daL,0x1f17dc12336dc542L, - 0x5c90c2a7636a68a8L,0x960c9eb77704ca1eL,0x9de8cf1e6fb3d65aL }, - { 0xc60fee0d511d3d06L,0x466e2313f9eb52c7L,0x743c0f5f206b0914L, - 0x42f55bac2191aa4dL,0xcefc7c8fffebdbc2L,0xd4fa6081e6e8ed1cL } }, - /* 70 */ - { { 0xb5e405d3b0ab9645L,0xaeec7f98d5f1f711L,0x8ad42311585c2a6eL, - 0x045acb9e512c6944L,0xae106c4ea90db1c6L,0xb89f33d5898e6563L }, - { 0x43b07cd97fed2ce4L,0xf9934e17dd815b20L,0x6778d4d50a81a349L, - 0x9e616ade52918061L,0xfa06db06d7e67112L,0x1da23cf188488091L } }, - /* 71 */ - { { 0x821c46b342f2c4b5L,0x931513ef66059e47L,0x7030ae4366f50cd1L, - 0x43b536c943e7b127L,0x006258cf5fca5360L,0xe4e3ee796b557abfL }, - { 0xbb6b390024c8b22fL,0x2eb5e2c1fcbf1054L,0x937b18c9567492afL, - 0xf09432e4acf53957L,0x585f5a9d1dbf3a56L,0xf86751fdbe0887cfL } }, - /* 72 */ - { { 0x157399cb9d10e0b2L,0x1c0d595660dc51b7L,0x1d496b8a1f583090L, - 0x6658bc2688590484L,0x88c08ab703213f28L,0x8d2e0f737ae58de4L }, - { 0x9b79bc95486cfee6L,0x036a26c7e9e5bc57L,0x1ad03601cd8ae97aL, - 0x06907f87ff3a0494L,0x078f4bbf2c7eb584L,0xe3731bf57e8d0a5aL } }, - /* 73 */ - { { 0x72f2282be1cd0abeL,0xd4f9015e87efefa2L,0x9d1898066c3834bdL, - 0x9c8cdcc1b8a29cedL,0x0601b9f4fee82ebcL,0x371052bc7206a756L }, - { 0x76fa109246f32562L,0xdaad534c17351bb4L,0xc3d64c37b3636bb5L, - 0x038a8c5145d54e00L,0x301e618032c09e7cL,0x9764eae795735151L } }, - /* 74 */ - { { 0x8791b19fcbd5256aL,0x4007e0f26ca13a3bL,0x03b794604cf06904L, - 0xb18a9c22b6c17589L,0xa1cb7d7d81d45908L,0x6e13fa9d21bb68f1L }, - { 0x47183c62a71e6e16L,0x5cf0ef8ee18749edL,0x2c9c7f9b2e5ed409L, - 0x042eeacce6e117e1L,0xb86d481613fb5a7fL,0xea1cf0edc9e5feb1L } }, - /* 75 */ - { { 0x6e6573c9cea4cc9bL,0x5417961dafcec8f3L,0x804bf02aa438b6f6L, - 0xb894b03cdcd4ea88L,0xd0f807e93799571fL,0x3466a7f5862156e8L }, - { 0x51e59acd56515664L,0x55b0f93ca3c5eb0bL,0x84a06b026a4279dbL, - 0x5c850579c5fae08eL,0xcf07b8dba663a1a2L,0x49a36bbcf46ffc8dL } }, - /* 76 */ - { { 0xe47f5acc46d93106L,0x65b7ade0aa897c9cL,0x37cf4c9412d7e4beL, - 0xa2ae9b80d4b2caa9L,0x5e7ce09ce60357a3L,0x29f77667c8ecd5f9L }, - { 0xdf6868f5a8a0b1c5L,0x240858cf62978ad8L,0x0f7ac101dc0002a1L, - 0x1d28a9d7ffe9aa05L,0x744984d65b962c97L,0xa8a7c00b3d28c8b2L } }, - /* 77 */ - { { 0x7c58a852ae11a338L,0xa78613f1d1af96e7L,0x7e9767d25355cc73L, - 0x6ba37009792a2de6L,0x7d60f618124386b2L,0xab09b53111157674L }, - { 0x95a0484198eb9dd0L,0xe6c17acc15070328L,0xafc6da45489c6e49L, - 0xab45a60abb211530L,0xc58d65927d7ea933L,0xa3ef3c65095642c6L } }, - /* 78 */ - { { 0x89d420e9df010879L,0x9d25255d39576179L,0x9cdefd50e39513b6L, - 0xe4efe45bd5d1c313L,0xc0149de73f7af771L,0x55a6b4f4340ab06bL }, - { 0xf1325251ebeaf771L,0x2ab44128878d4288L,0xfcd5832e18e05afeL, - 0xef52a348cc1fb62bL,0x2bd08274c1c4792aL,0x345c5846877c6dc7L } }, - /* 79 */ - { { 0xde15ceb0bea65e90L,0x0987f72b2416d99cL,0x44db578dfd863decL, - 0xf617b74bac6a3578L,0x9e62bd7adb48e999L,0x877cae61eab1a1beL }, - { 0x23adddaa3a358610L,0x2fc4d6d1325e2b07L,0x897198f51585754eL, - 0xf741852cb392b584L,0x9927804cb55f7de1L,0xe9e6c4ed1aa8efaeL } }, - /* 80 */ - { { 0x867db63998683186L,0xfb5cf424ddcc4ea9L,0xcc9a7ffed4f0e7bdL, - 0x7c57f71c7a779f7eL,0x90774079d6b25ef2L,0x90eae903b4081680L }, - { 0xdf2aae5e0ee1fcebL,0x3ff1da24e86c1a1fL,0x80f587d6ca193edfL, - 0xa5695523dc9b9d6aL,0x7b84090085920303L,0x1efa4dfcba6dbdefL } }, - /* 81 */ - { { 0xfbd838f9e0540015L,0x2c323946c39077dcL,0x8b1fb9e6ad619124L, - 0x9612440c0ca62ea8L,0x9ad9b52c2dbe00ffL,0xf52abaa1ae197643L }, - { 0xd0e898942cac32adL,0xdfb79e4262a98f91L,0x65452ecf276f55cbL, - 0xdb1ac0d27ad23e12L,0xf68c5f6ade4986f0L,0x389ac37b82ce327dL } }, - /* 82 */ - { { 0x511188b4f8e60f5bL,0x7fe6701548aa2adaL,0xdb333cb8381abca2L, - 0xb15e6d9ddaf3fc97L,0x4b24f6eb36aabc03L,0xc59789df72a748b4L }, - { 0x26fcb8a529cf5279L,0x7a3c6bfc01ad9a6cL,0x866cf88d4b8bac9bL, - 0xf4c899899c80d041L,0xf0a0424170add148L,0x5a02f47945d81a41L } }, - /* 83 */ - { { 0xfa5c877cc1c90202L,0xd099d440f8ac7570L,0x428a5b1bd17881f7L, - 0x61e267db5b2501d7L,0xf889bf04f2e4465bL,0x4da3ae0876aa4cb8L }, - { 0x3ef0fe26e3e66861L,0x5e7729533318b86dL,0xc3c35fbc747396dfL, - 0x5115a29c439ffd37L,0xbfc4bd97b2d70374L,0x088630ea56246b9dL } }, - /* 84 */ - { { 0xcd96866db8a9e8c9L,0xa11963b85bb8091eL,0xc7f90d53045b3cd2L, - 0x755a72b580f36504L,0x46f8b39921d3751cL,0x4bffdc9153c193deL }, - { 0xcd15c049b89554e7L,0x353c6754f7a26be6L,0x79602370bd41d970L, - 0xde16470b12b176c0L,0x56ba117540c8809dL,0xe2db35c3e435fb1eL } }, - /* 85 */ - { { 0xd71e4aab6328e33fL,0x5486782baf8136d1L,0x07a4995f86d57231L, - 0xf1f0a5bd1651a968L,0xa5dc5b2476803b6dL,0x5c587cbc42dda935L }, - { 0x2b6cdb32bae8b4c0L,0x66d1598bb1331138L,0x4a23b2d25d7e9614L, - 0x93e402a674a8c05dL,0x45ac94e6da7ce82eL,0xeb9f8281e463d465L } }, - /* 86 */ - { { 0x34e0f9d1fecf5b9bL,0xa115b12bf206966aL,0x5591cf3b1eaa0534L, - 0x5f0293cbfb1558f9L,0x1c8507a41bc703a5L,0x92e6b81c862c1f81L }, - { 0xcc9ebc66cdaf24e3L,0x68917ecd72fcfc70L,0x6dc9a9308157ba48L, - 0x5d425c08b06ab2b2L,0x362f8ce736e929c4L,0x09f6f57c62e89324L } }, - /* 87 */ - { { 0x1c7d6b78d29375fbL,0xfabd851ee35d1157L,0xf6f62dcd4243ea47L, - 0x1dd924608fe30b0fL,0x08166dfaffc6e709L,0xc6c4c6930881e6a7L }, - { 0x20368f87d6a53fb0L,0x38718e9f9eb4d1f9L,0x03f08acdafd7e790L, - 0x0835eb4472fe2a1cL,0x7e05090388076e5dL,0x538f765ea638e731L } }, - /* 88 */ - { { 0x0e0249d9c2663b4bL,0xe700ab5b47cd38ddL,0xb192559d2c46559fL, - 0x8f9f74a84bcde66dL,0xad1615233e2aced5L,0xc155c0473dd03a5bL }, - { 0x346a87993be454ebL,0x66ee94db83b7dccdL,0x1f6d8378ab9d2abeL, - 0x4a396dd27733f355L,0x419bd40af53553c2L,0xd0ead98d731dd943L } }, - /* 89 */ - { { 0x908e0b0eec142408L,0x98943cb94114b310L,0x03dbf7d81742b1d7L, - 0xd270df6b693412f4L,0xc50654948f69e20cL,0xa76a90c3697e43a1L }, - { 0xe0fa33844624825aL,0x82e48c0b8acc34c2L,0x7b24bd14e9a14f2bL, - 0x4f5dd5e24db30803L,0x0c77a9e7932da0a3L,0x20db90f274c653dcL } }, - /* 90 */ - { { 0x261179b70e6c5fd9L,0xf8bec1236c982eeaL,0x47683338d4957b7eL, - 0xcc47e6640a72f66aL,0xbd54bf6a1bad9350L,0xdfbf4c6af454e95aL }, - { 0x3f7a7afa6907f4faL,0x7311fae0865ca735L,0x24737ab82a496adaL, - 0x13e425f115feb79bL,0xe9e97c50a1b93c21L,0xb26b6eac4ddd3eb5L } }, - /* 91 */ - { { 0x81cab9f52a2e5f2bL,0xf93caf29bf385ac4L,0xf4bf35c3c909963aL, - 0x081e730074c9143cL,0x3ea57fa8c281b4c5L,0xe497905c9b340741L }, - { 0xf556dd8a55ab3cfbL,0xd444b96b518db6adL,0x34f5425a5ef4b955L, - 0xdda7a3acecd26aa3L,0xb57da11bda655e97L,0x02da3effc2024c70L } }, - /* 92 */ - { { 0xe24b00366481d0d9L,0x3740dbe5818fdfe2L,0xc1fc1f45190fda00L, - 0x329c92803cf27fdeL,0x7435cb536934f43eL,0x2b505a5d7884e8feL }, - { 0x6cfcc6a6711adcc9L,0xf034325c531e21e1L,0xa2f4a9679b2a8a99L, - 0x9d5f38423c21bdffL,0xb25c781131b57d66L,0xdb5344d80b8093b9L } }, - /* 93 */ - { { 0x0d72e667ae50a2f5L,0x9b7f8d8ae4a861d1L,0xa129f70f330df1cbL, - 0xe90aa5d7e04fefc3L,0xff561ecbe72c3ae1L,0x0d8fb428cdb955faL }, - { 0xd2235f73d7663784L,0xc05baec67e2c456aL,0xe5c292e42adbfcccL, - 0x4fd17988efb110d5L,0x27e57734d19d49f3L,0x188ac4ce84f679feL } }, - /* 94 */ - { { 0x7ee344cfa796c53eL,0xbbf6074d0868009bL,0x1f1594f7474a1295L, - 0x66776edcac11632dL,0x1862278b04e2fa5aL,0x52665cf2c854a89aL }, - { 0x7e3764648104ab58L,0x167759137204fd6dL,0x86ca06a544ea1199L, - 0xaa3f765b1c9240ddL,0x5f8501a924746149L,0x7b982e30dcd251d7L } }, - /* 95 */ - { { 0xe44e9efcc15f3060L,0x5ad62f2ea87ebbe6L,0x36499d41c79500d4L, - 0xa66d6dc0336fa9d1L,0xf8afc4955afd3b1fL,0x1d8ccb24e5c9822bL }, - { 0x4031422b79d7584bL,0xc54a0580ea3f20ddL,0x3f837c8f958468c5L, - 0x3d82f110fbea7735L,0x679a87787dffe2fcL,0x48eba63b20704803L } }, - /* 96 */ - { { 0x89b10d41df46e2f6L,0x13ab57f819514367L,0x067372b91d469c87L, - 0x0c195afa4f6c5798L,0xea43a12a272c9acfL,0x9dadd8cb678abdacL }, - { 0xcce56c6be182579aL,0x86febadb2d26c2d8L,0x1c668ee12a44745cL, - 0x580acd8698dc047aL,0x5a2b79cc51b9ec2dL,0x007da6084054f6a0L } }, - /* 97 */ - { { 0x9e3ca35217b00dd0L,0x046779cb0e81a7a6L,0xb999fef3d482d871L, - 0xe6f38134d9233fbcL,0x112c3001f48cd0e0L,0x934e75763c6c66aeL }, - { 0xb44d4fc3d73234dcL,0xfcae2062864eafc1L,0x843afe2526bef21aL, - 0x61355107f3b75fdfL,0x8367a5aa794c2e6bL,0x3d2629b18548a372L } }, - /* 98 */ - { { 0x6230618f437cfaf8L,0x5b8742cb2032c299L,0x949f72472293643aL, - 0xb8040f1a09464f79L,0x049462d24f254143L,0xabd6b522366c7e76L }, - { 0x119b392bd5338f55L,0x1a80a9ce01495a0cL,0xf3118ca7f8d7537eL, - 0xb715adc26bf4b762L,0x24506165a8482b6cL,0xd958d7c696a7c84dL } }, - /* 99 */ - { { 0x9ad8aa87bdc21f31L,0xadb3cab48063e58cL,0xefd86283b07dd7b8L, - 0xc7b9b7621be7c6b4L,0x2ef58741015582deL,0xc970c52e299addf3L }, - { 0x78f02e2a22f24d66L,0xefec1d1074cc100aL,0xaf2a6a3909316e1aL, - 0xce7c22055849dd49L,0x9c1fe75c96bffc4cL,0xcad98fd27ba06ec0L } }, - /* 100 */ - { { 0xed76e2d0b648b73eL,0xa9f92ce51cfd285eL,0xa8c86c062ed13de1L, - 0x1d3a574ea5191a93L,0x385cdf8b1ad1b8bfL,0xbbecc28a47d2cfe3L }, - { 0x98d326c069cec548L,0x4f5bc1ddf240a0b2L,0x241a706229057236L, - 0x0fc6e9c5c68294a4L,0x4d04838ba319f17aL,0x8b612cf19ffc1c6fL } }, - /* 101 */ - { { 0x9bb0b5014c3830ebL,0x3d08f83c8ee0d0c5L,0xa4a6264279ba9389L, - 0x5d5d40449cbc2914L,0xae9eb83e074c46f0L,0x63bb758f74ead7d6L }, - { 0x1c40d2eac6bb29e0L,0x95aa2d874b02f41eL,0x9298917553cb199aL, - 0xdd91bafe51584f6dL,0x3715efb931a1aaecL,0xc1b6ae5b46780f9eL } }, - /* 102 */ - { { 0xcded3e4b42772f41L,0x3a700d5d3bcb79d1L,0x4430d50e80feee60L, - 0x444ef1fcf5e5d4bbL,0xc660194fe6e358ffL,0xe68a2f326a91b43cL }, - { 0x5842775c977fe4d2L,0x78fdef5c7e2a41ebL,0x5f3bec02ff8df00eL, - 0xf4b840cd5852525dL,0x0870483a4e6988bdL,0x39499e39cc64b837L } }, - /* 103 */ - { { 0xfc05de80b08df5feL,0x0c12957c63ba0362L,0xea379414d5cf1428L, - 0xc559132a54ef6216L,0x33d5f12fb9e65cf8L,0x09c602781695d663L }, - { 0x3ac1ced461f7a2fbL,0xdd838444d4f5eeb8L,0x82a38c6c8318fcadL, - 0x315be2e5e9f1a864L,0x317b5771442daf47L,0x81b5904a95aa5f9eL } }, - /* 104 */ - { { 0x6b6b1c508b21d232L,0x87f3dbc08c2cba75L,0xa7e74b46ae9f0fafL, - 0x036a0985bb7b8079L,0x4f185b908d974a25L,0x5aa7cef0d9af5ec9L }, - { 0xe0566a7057dcfffcL,0x6ea311dab8453225L,0x72ea1a8d23368aa9L, - 0xed9b208348cd552dL,0xb987967cc80ea435L,0xad735c756c104173L } }, - /* 105 */ - { { 0xaea85ab3cee76ef4L,0x44997444af1d2b93L,0x0851929beacb923fL, - 0xb080b59051e3bc0cL,0xc4ee1d8659be68a2L,0xf00de21964b26cdaL }, - { 0x8d7fb5c0f2e90d4dL,0x00e219a777d9ec64L,0xc4e6febd5d1c491cL, - 0x080e37541a8f4585L,0x4a9b86c848d2af9cL,0x2ed70db6b6679851L } }, - /* 106 */ - { { 0xaee44116586f25cbL,0xf7b6861fa0fcf70fL,0x55d2cd2018a350e8L, - 0x861bf3e592dc286fL,0x9ab18ffa6226aba7L,0xd15827bea9857b03L }, - { 0x26c1f54792e6acefL,0x422c63c8ac1fbac3L,0xa2d8760dfcbfd71dL, - 0x35f6a539b2511224L,0xbaa88fa1048d1a21L,0x49f1abe9ebf999dbL } }, - /* 107 */ - { { 0x16f9f4f4f7492b73L,0xcf28ec1ecb392b1aL,0x45b130d469ca6ffcL, - 0x28ba8d40b72efa58L,0xace987c75ca066f5L,0x3e3992464ad022ebL }, - { 0x63a2d84e752555bbL,0xaaa93b4a9c2ae394L,0xcd80424ec89539caL, - 0x6d6b5a6daa119a99L,0xbd50334c379f2629L,0x899e925eef3cc7d3L } }, - /* 108 */ - { { 0xb7ff3651bf825dc4L,0x0f741cc440b9c462L,0x771ff5a95cc4fb5bL, - 0xcb9e9c9b47fd56feL,0xbdf053db5626c0d3L,0xa97ce675f7e14098L }, - { 0x68afe5a36c934f5eL,0x6cd5e148ccefc46fL,0xc7758570d7a88586L, - 0x49978f5edd558d40L,0xa1d5088a64ae00c1L,0x58f2a720f1d65bb2L } }, - /* 109 */ - { { 0x66fdda4a3e4daedbL,0x38318c1265d1b052L,0x28d910a24c4bbf5cL, - 0x762fe5c478a9cd14L,0x08e5ebaad2cc0aeeL,0xd2cdf257ca0c654cL }, - { 0x48f7c58b08b717d2L,0x3807184a386cd07aL,0x3240f626ae7d0112L, - 0x03e9361bc43917b0L,0xf261a87620aea018L,0x53f556a47e1e6372L } }, - /* 110 */ - { { 0xc84cee562f512a90L,0x24b3c0041b0ea9f1L,0x0ee15d2de26cc1eaL, - 0xd848762cf0c9ef7dL,0x1026e9c5d5341435L,0x8f5b73dcfdb16b31L }, - { 0x1f69bef2d2c75d95L,0x8d33d581be064ddaL,0x8c024c1257ed35e6L, - 0xf8d435f9c309c281L,0xfd295061d6960193L,0x66618d78e9e49541L } }, - /* 111 */ - { { 0x571cfd458ce382deL,0x175806eede900ddeL,0x6184996534aba3b5L, - 0xe899778ade7aec95L,0xe8f00f6eff4aa97fL,0xae971cb5010b0c6dL }, - { 0x1827eebc3af788f1L,0xd46229ffe413fe2dL,0x8a15455b4741c9b4L, - 0x5f02e690f8e424ebL,0x40a1202edae87712L,0x49b3bda264944f6dL } }, - /* 112 */ - { { 0xd63c6067035b2d69L,0xb507150d6bed91b0L,0x1f35f82f7afb39b2L, - 0xb9bd9c0116012b66L,0x00d97960ed0a5f50L,0xed7054512716f7c9L }, - { 0x1576eff4127abdb4L,0x6850d698f01e701cL,0x9fa7d7493fc87e2fL, - 0x0b6bcc6fb0ce3e48L,0xf4fbe1f5f7d8c1c0L,0xcf75230e02719cc6L } }, - /* 113 */ - { { 0x6761d6c2722d94edL,0xd1ec3f213718820eL,0x65a40b7025d0e7c6L, - 0xd67f830ebaf3cf31L,0x633b3807b93ea430L,0x17faa0ea0bc96c69L }, - { 0xe6bf3482df866b98L,0x205c1ee9a9db52d4L,0x51ef9bbdff9ab869L, - 0x3863dad175eeb985L,0xef216c3bd3cf442aL,0x3fb228e3f9c8e321L } }, - /* 114 */ - { { 0x94f9b70c0760ac07L,0xf3c9ccae9d79bf4dL,0x73cea084c5ffc83dL, - 0xef50f943dc49c38eL,0xf467a2aebc9e7330L,0x5ee534b644ea7fbaL }, - { 0x20cb627203609e7fL,0x0984435562fdc9f0L,0xaf5c8e580f1457f7L, - 0xd1f50a6cb4b25941L,0x77cb247c2ec82395L,0xa5f3e1e5da3dca33L } }, - /* 115 */ - { { 0x023489d67d85fa94L,0x0ba405372db9ce47L,0x0fdf7a1faed7aad1L, - 0xa57b0d739a4ccb40L,0x48fcec995b18967cL,0xf30b5b6eb7274d24L }, - { 0x7ccb4773c81c5338L,0xb85639e6a3ed6bd0L,0x7d9df95f1d56eadaL, - 0xe256d57f0a1607adL,0x6da7ffdc957574d6L,0x65f8404601c7a8c4L } }, - /* 116 */ - { { 0x8d45d0cbcba1e7f1L,0xef0a08c002b55f64L,0x771ca31b17e19892L, - 0xe1843ecb4885907eL,0x67797ebc364ce16aL,0x816d2b2d8df4b338L }, - { 0xe870b0e539aa8671L,0x9f0db3e4c102b5f5L,0x342966591720c697L, - 0x0ad4c89e613c0d2aL,0x1af900b2418ddd61L,0xe087ca72d336e20eL } }, - /* 117 */ - { { 0x222831ffaba10079L,0x0dc5f87b6d64fff2L,0x445479073e8cb330L, - 0xe815aaa2702a33fbL,0x338d6b2e5fba3215L,0x0f7535cb79f549c8L }, - { 0x471ecd972ee95923L,0x1e868b37c6d1c09fL,0x2bc7b8ecc666ef4eL, - 0xf5416589808a4bfcL,0xf23e9ee23fbc4d2eL,0x4357236c2d75125bL } }, - /* 118 */ - { { 0xfe176d95ba9cdb1bL,0x45a1ca012f82791eL,0x97654af24de4cca2L, - 0xbdbf9d0e5cc4bcb9L,0xf6a7df50ad97ac0aL,0xc52112b061359fd6L }, - { 0x696d9ce34f05eae3L,0x903adc02e943ac2bL,0xa90753470848be17L, - 0x1e20f1702a3973e5L,0xe1aacc1c6feb67e9L,0x2ca0ac32e16bc6b9L } }, - /* 119 */ - { { 0xffea12e4ef871eb5L,0x94c2f25da8bf0a7aL,0x4d1e4c2a78134eaaL, - 0x11ed16fb0360fb10L,0x4029b6db85fc11beL,0x5e9f7ab7f4d390faL }, - { 0x5076d72f30646612L,0xa0afed1ddda1d0d8L,0x2902225785a1d103L, - 0xcb499e174e276bcdL,0x16d1da7151246c3dL,0xc72d56d3589a0443L } }, - /* 120 */ - { { 0xdf5ffc74dae5bb45L,0x99068c4a261bd6dcL,0xdc0afa7aaa98ec7bL, - 0xedd2ee00f121e96dL,0x163cc7be1414045cL,0xb0b1bbce335af50eL }, - { 0xd440d78501a06293L,0xcdebab7c6552e644L,0x48cb8dbc8c757e46L, - 0x81f9cf783cabe3cbL,0xddd02611b123f59aL,0x3dc7b88eeeb3784dL } }, - /* 121 */ - { { 0xe1b8d398c4741456L,0xa9dfa9026032a121L,0x1cbfc86d1263245bL, - 0xf411c7625244718cL,0x96521d5405b0fc54L,0x1afab46edbaa4985L }, - { 0xa75902ba8674b4adL,0x486b43ad5ad87d12L,0x72b1c73636e0d099L, - 0x39890e07bb6cd6d6L,0x8128999c59bace4eL,0xd8da430b7b535e33L } }, - /* 122 */ - { { 0x39f65642c6b75791L,0x050947a621806bfbL,0x0ca3e3701362ef84L, - 0x9bc60aed8c3d2391L,0x9b488671732e1ddcL,0x12d10d9ea98ee077L }, - { 0xb6f2822d3651b7dcL,0x6345a5ba80abd138L,0x62033262472d3c84L, - 0xd54a1d40acc57527L,0x6ea46b3a424447cbL,0x5bc410572fb1a496L } }, - /* 123 */ - { { 0xe70c57a3a751cd0eL,0x190d8419eba3c7d6L,0xb1c3bee79d47d55aL, - 0xda941266f912c6d8L,0x12e9aacc407a6ad6L,0xd6ce5f116e838911L }, - { 0x063ca97b70e1f2ceL,0xa3e47c728213d434L,0xa016e24184df810aL, - 0x688ad7b0dfd881a4L,0xa37d99fca89bf0adL,0xd8e3f339a23c2d23L } }, - /* 124 */ - { { 0xbdf53163750bed6fL,0x808abc3283e68b0aL,0x85a366275bb08a33L, - 0xf72a3a0f6b0e4abeL,0xf7716d19faf0c6adL,0x22dcc0205379b25fL }, - { 0x7400bf8df9a56e11L,0x6cb8bad756a47f21L,0x7c97176f7a6eb644L, - 0xe8fd84f7d1f5b646L,0x98320a9444ddb054L,0x07071ba31dde86f5L } }, - /* 125 */ - { { 0x6fdfa0e598f8fcb9L,0x89cec8e094d0d70cL,0xa0899397106d20a8L, - 0x915bfb9aba8acc9cL,0x1370c94b5507e01cL,0x83246a608a821ffbL }, - { 0xa8273a9fbe3c378fL,0x7e54478935a25be9L,0x6cfa49724dd929d7L, - 0x987fed9d365bd878L,0x4982ac945c29a7aeL,0x4589a5d75ddd7ec5L } }, - /* 126 */ - { { 0x9fabb174a95540a9L,0x7cfb886f0162c5b0L,0x17be766bea3dee18L, - 0xff7da41fe88e624cL,0xad0b71eb8b919c38L,0x86a522e0f31ff9a9L }, - { 0xbc8e6f72868bc259L,0x6130c6383ccef9e4L,0x09f1f4549a466555L, - 0x8e6c0f0919b2bfb4L,0x945c46c90ca7bb22L,0xacd871684dafb67bL } }, - /* 127 */ - { { 0x090c72ca10c53841L,0xc20ae01b55a4fcedL,0x03f7ebd5e10234adL, - 0xb3f42a6a85892064L,0xbdbc30c0b4a14722L,0x971bc4378ca124ccL }, - { 0x6f79f46d517ff2ffL,0x6a9c96e2ecba947bL,0x5e79f2f462925122L, - 0x30a96bb16a4e91f1L,0x1147c9232d4c72daL,0x65bc311f5811e4dfL } }, - /* 128 */ - { { 0x87c7dd7d139b3239L,0x8b57824e4d833baeL,0xbcbc48789fff0015L, - 0x8ffcef8b909eaf1aL,0x9905f4eef1443a78L,0x020dd4a2e15cbfedL }, - { 0xca2969eca306d695L,0xdf940cadb93caf60L,0x67f7fab787ea6e39L, - 0x0d0ee10ff98c4fe5L,0xc646879ac19cb91eL,0x4b4ea50c7d1d7ab4L } }, - /* 129 */ - { { 0x19e409457a0db57eL,0xe6017cad9a8c9702L,0xdbf739e51be5cff9L, - 0x3646b3cda7a938a2L,0x0451108568350dfcL,0xad3bd6f356e098b5L }, - { 0x935ebabfee2e3e3eL,0xfbd01702473926cbL,0x7c735b029e9fb5aaL, - 0xc52a1b852e3feff0L,0x9199abd3046b405aL,0xe306fcec39039971L } }, - /* 130 */ - { { 0xd6d9aec823e4712cL,0x7ca8376cc3c198eeL,0xe6d8318731bebd8aL, - 0xed57aff3d88bfef3L,0x72a645eecf44edc7L,0xd4e63d0b5cbb1517L }, - { 0x98ce7a1cceee0ecfL,0x8f0126335383ee8eL,0x3b879078a6b455e8L, - 0xcbcd3d96c7658c06L,0x721d6fe70783336aL,0xf21a72635a677136L } }, - /* 131 */ - { { 0x19d8b3cd9586ba11L,0xd9e0aeb28a5c0480L,0xe4261dbf2230ef5cL, - 0x095a9dee02e6bf09L,0x8963723c80dc7784L,0x5c97dbaf145157b1L }, - { 0x97e744344bc4503eL,0x0fb1cb3185a6b370L,0x3e8df2becd205d4bL, - 0x497dd1bcf8f765daL,0x92ef95c76c988a1aL,0x3f924baa64dc4cfaL } }, - /* 132 */ - { { 0x6bf1b8dd7268b448L,0xd4c28ba1efd79b94L,0x2fa1f8c8e4e3551fL, - 0x769e3ad45c9187a9L,0x28843b4d40326c0dL,0xfefc809450d5d669L }, - { 0x30c85bfd90339366L,0x4eeb56f15ccf6c3aL,0x0e72b14928ccd1dcL, - 0x73ee85b5f2ce978eL,0xcdeb2bf33165bb23L,0x8106c9234e410abfL } }, - /* 133 */ - { { 0xc8df01617d02f4eeL,0x8a78154718e21225L,0x4ea895eb6acf9e40L, - 0x8b000cb56e5a633dL,0xf31d86d57e981ffbL,0xf5c8029c4475bc32L }, - { 0x764561ce1b568973L,0x2f809b81a62996ecL,0x9e513d64da085408L, - 0xc27d815de61ce309L,0x0da6ff99272999e0L,0xbd284779fead73f7L } }, - /* 134 */ - { { 0x6033c2f99b1cdf2bL,0x2a99cf06bc5fa151L,0x7d27d25912177b3bL, - 0xb1f15273c4485483L,0x5fd57d81102e2297L,0x3d43e017c7f6acb7L }, - { 0x41a8bb0b3a70eb28L,0x67de2d8e3e80b06bL,0x09245a4170c28de5L, - 0xad7dbcb1a7b26023L,0x70b08a352cbc6c1eL,0xb504fb669b33041fL } }, - /* 135 */ - { { 0xa8e85ab5f97a27c2L,0x6ac5ec8bc10a011bL,0x55745533ffbcf161L, - 0x01780e8565790a60L,0xe451bf8599ee75b0L,0x8907a63b39c29881L }, - { 0x76d46738260189edL,0x284a443647bd35cbL,0xd74e8c4020cab61eL, - 0x6264bf8c416cf20aL,0xfa5a6c955fd820ceL,0xfa7154d0f24bb5fcL } }, - /* 136 */ - { { 0x18482cec9b3f5034L,0x962d445acd9e68fdL,0x266fb1d695746f23L, - 0xc66ade5a58c94a4bL,0xdbbda826ed68a5b6L,0x05664a4d7ab0d6aeL }, - { 0xbcd4fe51025e32fcL,0x61a5aebfa96df252L,0xd88a07e231592a31L, - 0x5d9d94de98905517L,0x96bb40105fd440e7L,0x1b0c47a2e807db4cL } }, - /* 137 */ - { { 0x5c2a6ac808223878L,0xba08c269e65a5558L,0xd22b1b9b9bbc27fdL, - 0x919171bf72b9607dL,0x9ab455f9e588dc58L,0x6d54916e23662d93L }, - { 0x8da8e9383b1de0c1L,0xa84d186a804f278fL,0xbf4988ccd3461695L, - 0xf5eae3bee10eb0cbL,0x1ff8b68fbf2a66edL,0xa68daf67c305b570L } }, - /* 138 */ - { { 0xc1004cff44b2e045L,0x91b5e1364b1c05d4L,0x53ae409088a48a07L, - 0x73fb2995ea11bb1aL,0x320485703d93a4eaL,0xcce45de83bfc8a5fL }, - { 0xaff4a97ec2b3106eL,0x9069c630b6848b4fL,0xeda837a6ed76241cL, - 0x8a0daf136cc3f6cfL,0x199d049d3da018a8L,0xf867c6b1d9093ba3L } }, - /* 139 */ - { { 0xe4d42a5656527296L,0xae26c73dce71178dL,0x70a0adac6c251664L, - 0x813483ae5dc0ae1dL,0x7574eacddaab2dafL,0xc56b52dcc2d55f4fL }, - { 0x872bc16795f32923L,0x4be175815bdd2a89L,0x9b57f1e7a7699f00L, - 0x5fcd9c723ac2de02L,0x83af3ba192377739L,0xa64d4e2bfc50b97fL } }, - /* 140 */ - { { 0x2172dae20e552b40L,0x62f49725d34d52e8L,0x7930ee4007958f98L, - 0x56da2a90751fdd74L,0xf1192834f53e48c3L,0x34d2ac268e53c343L }, - { 0x1073c21813111286L,0x201dac14da9d9827L,0xec2c29dbee95d378L, - 0x9316f1191f3ee0b1L,0x7890c9f0544ce71cL,0xd77138af27612127L } }, - /* 141 */ - { { 0x78045e6d3b4ad1cdL,0xcd86b94e4aa49bc1L,0x57e51f1dfd677a16L, - 0xd9290935fa613697L,0x7a3f959334f4d893L,0x8c9c248b5d5fcf9bL }, - { 0x9f23a4826f70d4e9L,0x1727345463190ae9L,0x4bdd7c135b081a48L, - 0x1e2de38928d65271L,0x0bbaaa25e5841d1fL,0xc4c18a79746772e5L } }, - /* 142 */ - { { 0x10ee2681593375acL,0x4f3288be7dd5e113L,0x9a97b2fb240f3538L, - 0xfa11089f1de6b1e2L,0x516da5621351bc58L,0x573b61192dfa85b5L }, - { 0x89e966836cba7df5L,0xf299be158c28ab40L,0xe91c9348ad43fcbfL, - 0xe9bbc7cc9a1cefb3L,0xc8add876738b2775L,0x6e3b1f2e775eaa01L } }, - /* 143 */ - { { 0x0365a888b677788bL,0x634ae8c43fd6173cL,0x304987619e498dbeL, - 0x08c43e6dc8f779abL,0x068ae3844c09aca9L,0x2380c70b2018d170L }, - { 0xcf77fbc3a297c5ecL,0xdacbc853ca457948L,0x3690de04336bec7eL, - 0x26bbac6414eec461L,0xd1c23c7e1f713abfL,0xf08bbfcde6fd569eL } }, - /* 144 */ - { { 0x5f8163f484770ee3L,0x0e0c7f94744a1706L,0x9c8f05f7e1b2d46dL, - 0x417eafe7d01fd99aL,0x2ba15df511440e5bL,0xdc5c552a91a6fbcfL }, - { 0x86271d74a270f721L,0x32c0a075a004485bL,0x9d1a87e38defa075L, - 0xb590a7acbf0d20feL,0x430c41c28feda1f5L,0x454d287958f6ec24L } }, - /* 145 */ - { { 0x52b7a6357c525435L,0x3d9ef57f37c4bdbcL,0x2bb93e9edffcc475L, - 0xf7b8ba987710f3beL,0x42ee86da21b727deL,0x55ac3f192e490d01L }, - { 0x487e3a6ec0c1c390L,0x036fb345446cde7bL,0x089eb276496ae951L, - 0xedfed4d971ed1234L,0x661b0dd5900f0b46L,0x11bd6f1b8582f0d3L } }, - /* 146 */ - { { 0x5cf9350f076bc9d1L,0x15d903becf3cd2c3L,0x21cfc8c225af031cL, - 0xe0ad32488b1cc657L,0xdd9fb96370014e87L,0xf0f3a5a1297f1658L }, - { 0xbb908fbaf1f703aaL,0x2f9cc4202f6760baL,0x00ceec6666a38b51L, - 0x4deda33005d645daL,0xb9cf5c72f7de3394L,0xaeef65021ad4c906L } }, - /* 147 */ - { { 0x0583c8b17a19045dL,0xae7c3102d052824cL,0x2a234979ff6cfa58L, - 0xfe9dffc962c733c0L,0x3a7fa2509c0c4b09L,0x516437bb4fe21805L }, - { 0x9454e3d5c2a23ddbL,0x0726d887289c104eL,0x8977d9184fd15243L, - 0xc559e73f6d7790baL,0x8fd3e87d465af85fL,0xa2615c745feee46bL } }, - /* 148 */ - { { 0xc8d607a84335167dL,0x8b42d804e0f5c887L,0x5f9f13df398d11f9L, - 0x5aaa508720740c67L,0x83da9a6aa3d9234bL,0xbd3a5c4e2a54bad1L }, - { 0xdd13914c2db0f658L,0x29dcb66e5a3f373aL,0xbfd62df55245a72bL, - 0x19d1802391e40847L,0xd9df74dbb136b1aeL,0x72a06b6b3f93bc5bL } }, - /* 149 */ - { { 0x6da19ec3ad19d96fL,0xb342daa4fb2a4099L,0x0e61633a662271eaL, - 0x3bcece81ce8c054bL,0x7cc8e0618bd62dc6L,0xae189e19ee578d8bL }, - { 0x73e7a25ddced1eedL,0xc1257f0a7875d3abL,0x2cb2d5a21cfef026L, - 0xd98ef39bb1fdf61cL,0xcd8e6f6924e83e6cL,0xd71e7076c7b7088bL } }, - /* 150 */ - { { 0x339368309d4245bfL,0x22d962172ac2953bL,0xb3bf5a8256c3c3cdL, - 0x50c9be910d0699e8L,0xec0944638f366459L,0x6c056dba513b7c35L }, - { 0x687a6a83045ab0e3L,0x8d40b57f445c9295L,0x0f345048a16f5954L, - 0x64b5c6393d8f0a87L,0x106353a29f71c5e2L,0xdd58b475874f0dd4L } }, - /* 151 */ - { { 0x67ec084f62230c72L,0xf14f6cca481385e3L,0xf58bb4074cda7774L, - 0xe15011b1aa2dbb6bL,0xd488369d0c035ab1L,0xef83c24a8245f2fdL }, - { 0xfb57328f9fdc2538L,0x79808293191fe46aL,0xe28f5c4432ede548L, - 0x1b3cda99ea1a022cL,0x39e639b73df2ec7fL,0x77b6272b760e9a18L } }, - /* 152 */ - { { 0x2b1d51bda65d56d5L,0x3a9b71f97ea696e0L,0x95250ecc9904f4c4L, - 0x8bc4d6ebe75774b7L,0x0e343f8aeaeeb9aaL,0xc473c1d1930e04cbL }, - { 0x282321b1064cd8aeL,0xf4b4371e5562221cL,0xc1cc81ecd1bf1221L, - 0xa52a07a9e2c8082fL,0x350d8e59ba64a958L,0x29e4f3de6fb32c9aL } }, - /* 153 */ - { { 0x0aa9d56cba89aaa5L,0xf0208ac0c4c6059eL,0x7400d9c6bd6ddca4L, - 0xb384e475f2c2f74aL,0x4c1061fcb1562dd3L,0x3924e2482e153b8dL }, - { 0xf38b8d98849808abL,0x29bf3260a491aa36L,0x85159ada88220edeL, - 0x8b47915bbe5bc422L,0xa934d72ed7300967L,0xc4f303982e515d0dL } }, - /* 154 */ - { { 0xe3e9ee421b1de38bL,0xa124e25a42636760L,0x90bf73c090165b1aL, - 0x21802a34146434c5L,0x54aa83f22e1fa109L,0x1d4bd03ced9c51e9L }, - { 0xc2d96a38798751e6L,0xed27235f8c3507f5L,0xb5fb80e2c8c24f88L, - 0xf873eefad37f4f78L,0x7229fd74f224ba96L,0x9dcd91999edd7149L } }, - /* 155 */ - { { 0xee9f81a64e94f22aL,0xe5609892f71ec341L,0x6c818ddda998284eL, - 0x9fd472953b54b098L,0x47a6ac030e8a7cc9L,0xde684e5eb207a382L }, - { 0x4bdd1ecd2b6b956bL,0x09084414f01b3583L,0xe2f80b3255233b14L, - 0x5a0fec54ef5ebc5eL,0x74cf25e6bf8b29a2L,0x1c757fa07f29e014L } }, - /* 156 */ - { { 0x1bcb5c4aeb0fdfe4L,0xd7c649b3f0899367L,0xaef68e3f05bc083bL, - 0x57a06e46a78aa607L,0xa2136ecc21223a44L,0x89bd648452f5a50bL }, - { 0x724411b94455f15aL,0x23dfa97008a9c0fdL,0x7b0da4d16db63befL, - 0x6f8a7ec1fb162443L,0xc1ac9ceee98284fbL,0x085a582b33566022L } }, - /* 157 */ - { { 0x15cb61f9ec1f138aL,0x11c9a230668f0c28L,0xac829729df93f38fL, - 0xcef256984048848dL,0x3f686da02bba8fbfL,0xed5fea78111c619aL }, - { 0x9b4f73bcd6d1c833L,0x5095160686e7bf80L,0xa2a73508042b1d51L, - 0x9ef6ea495fb89ec2L,0xf1008ce95ef8b892L,0x78a7e6849ae8568bL } }, - /* 158 */ - { { 0x3fe83a7c10470cd8L,0x92734682f86df000L,0xb5dac06bda9409b5L, - 0x1e7a966094939c5fL,0xdec6c1505cc116dcL,0x1a52b40866bac8ccL }, - { 0x5303a3656e864045L,0x45eae72a9139efc1L,0x83bec6466f31d54fL, - 0x2fb4a86f6e958a6dL,0x6760718e4ff44030L,0x008117e3e91ae0dfL } }, - /* 159 */ - { { 0x5d5833ba384310a2L,0xbdfb4edc1fd6c9fcL,0xb9a4f102849c4fb8L, - 0xe5fb239a581c1e1fL,0xba44b2e7d0a9746dL,0x78f7b7683bd942b9L }, - { 0x076c8ca1c87607aeL,0x82b23c2ed5caaa7eL,0x6a581f392763e461L, - 0xca8a5e4a3886df11L,0xc87e90cf264e7f22L,0x04f74870215cfcfcL } }, - /* 160 */ - { { 0x5285d116141d161cL,0x67cd2e0e93c4ed17L,0x12c62a647c36187eL, - 0xf5329539ed2584caL,0xc4c777c442fbbd69L,0x107de7761bdfc50aL }, - { 0x9976dcc5e96beebdL,0xbe2aff95a865a151L,0x0e0a9da19d8872afL, - 0x5e357a3da63c17ccL,0xd31fdfd8e15cc67cL,0xc44bbefd7970c6d8L } }, - /* 161 */ - { { 0x703f83e24c0c62f1L,0x9b1e28ee4e195572L,0x6a82858bfe26ccedL, - 0xd381c84bc43638faL,0x94f72867a5ba43d8L,0x3b4a783d10b82743L }, - { 0xee1ad7b57576451eL,0xc3d0b59714b6b5c8L,0x3dc30954fcacc1b8L, - 0x55df110e472c9d7bL,0x97c86ed702f8a328L,0xd043341388dc098fL } }, - /* 162 */ - { { 0x1a60d1522ca8f2feL,0x61640948491bd41fL,0x6dae29a558dfe035L, - 0x9a615bea278e4863L,0xbbdb44779ad7c8e5L,0x1c7066302ceac2fcL }, - { 0x5e2b54c699699b4bL,0xb509ca6d239e17e8L,0x728165feea063a82L, - 0x6b5e609db6a22e02L,0x12813905b26ee1dfL,0x07b9f722439491faL } }, - /* 163 */ - { { 0x1592ec1448ff4e49L,0x3e4e9f176d644129L,0x7acf82881156acc0L, - 0x5aa34ba8bb092b0bL,0xcd0f90227d38393dL,0x416724ddea4f8187L }, - { 0x3c4e641cc0139e73L,0xe0fe46cf91e4d87dL,0xedb3c792cab61f8aL, - 0x4cb46de4d3868753L,0xe449c21d20f1098aL,0x5e5fd059f5b8ea6eL } }, - /* 164 */ - { { 0x7fcadd4675856031L,0x89c7a4cdeaf2fbd0L,0x1af523ce7a87c480L, - 0xe5fc109561d9ae90L,0x3fb5864fbcdb95f5L,0xbeb5188ebb5b2c7dL }, - { 0x3d1563c33ae65825L,0x116854c40e57d641L,0x11f73d341942ebd3L, - 0x24dc5904c06955b3L,0x8a0d4c83995a0a62L,0xfb26b86d5d577b7dL } }, - /* 165 */ - { { 0xc53108e7c686ae17L,0x9090d739d1c1da56L,0x4583b0139aec50aeL, - 0xdd9a088ba49a6ab2L,0x28192eeaf382f850L,0xcc8df756f5fe910eL }, - { 0x877823a39cab7630L,0x64984a9afb8e7fc1L,0x5448ef9c364bfc16L, - 0xbbb4f871c44e2a9aL,0x901a41ab435c95e9L,0xc6c23e5faaa50a06L } }, - /* 166 */ - { { 0xb78016c19034d8ddL,0x856bb44b0b13e79bL,0x85c6409ab3241a05L, - 0x8d2fe19a2d78ed21L,0xdcc7c26d726eddf2L,0x3ccaff5f25104f04L }, - { 0x397d7edc6b21f843L,0xda88e4dde975de4cL,0x5273d3964f5ab69eL, - 0x537680e39aae6cc0L,0xf749cce53e6f9461L,0x021ddbd9957bffd3L } }, - /* 167 */ - { { 0x7b64585f777233cfL,0xfe6771f60942a6f0L,0x636aba7adfe6eef0L, - 0x63bbeb5686038029L,0xacee5842de8fcf36L,0x48d9aa99d4a20524L }, - { 0xcff7a74c0da5e57aL,0xc232593ce549d6c9L,0x68504bccf0f2287bL, - 0x6d7d098dbc8360b5L,0xeac5f1495b402f41L,0x61936f11b87d1bf1L } }, - /* 168 */ - { { 0xaa9da167b8153a9dL,0xa49fe3ac9e83ecf0L,0x14c18f8e1b661384L, - 0x61c24dab38434de1L,0x3d973c3a283dae96L,0xc99baa0182754fc9L }, - { 0x477d198f4c26b1e3L,0x12e8e186a7516202L,0x386e52f6362addfaL, - 0x31e8f695c3962853L,0xdec2af136aaedb60L,0xfcfdb4c629cf74acL } }, - /* 169 */ - { { 0x6b3ee958cca40298L,0xc3878153f2f5d195L,0x0c565630ed2eae5bL, - 0xd089b37e3a697cf2L,0xc2ed2ac7ad5029eaL,0x7e5cdfad0f0dda6aL }, - { 0xf98426dfd9b86202L,0xed1960b14335e054L,0x1fdb02463f14639eL, - 0x17f709c30db6c670L,0xbfc687ae773421e1L,0x13fefc4a26c1a8acL } }, - /* 170 */ - { { 0xe361a1987ffa0a5fL,0xf4b26102c63fe109L,0x264acbc56c74e111L, - 0x4af445fa77abebafL,0x448c4fdd24cddb75L,0x0b13157d44506eeaL }, - { 0x22a6b15972e9993dL,0x2c3c57e485e5ecbeL,0xa673560bfd83e1a1L, - 0x6be23f82c3b8c83bL,0x40b13a9640bbe38eL,0x66eea033ad17399bL } }, - /* 171 */ - { { 0x49fc6e95b4c6c693L,0xefc735de36af7d38L,0xe053343d35fe42fcL, - 0xf0aa427c6a9ab7c3L,0xc79f04364a0fcb24L,0x1628724393ebbc50L }, - { 0x5c3d6bd016927e1eL,0x40158ed2673b984cL,0xa7f86fc84cd48b9aL, - 0x1643eda660ea282dL,0x45b393eae2a1beedL,0x664c839e19571a94L } }, - /* 172 */ - { { 0x5774575027eeaf94L,0x2875c925ea99e1e7L,0xc127e7ba5086adeaL, - 0x765252a086fe424fL,0x1143cc6c2b6c0281L,0xc9bb2989d671312dL }, - { 0x880c337c51acb0a5L,0xa3710915d3c60f78L,0x496113c09262b6edL, - 0x5d25d9f89ce48182L,0x53b6ad72b3813586L,0x0ea3bebc4c0e159cL } }, - /* 173 */ - { { 0xcaba450ac5e49beaL,0x684e54157c05da59L,0xa2e9cab9de7ac36cL, - 0x4ca79b5f2e6f957bL,0xef7b024709b817b1L,0xeb3049907d89df0fL }, - { 0x508f730746fe5096L,0x695810e82e04eaafL,0x88ef1bd93512f76cL, - 0x776613513ebca06bL,0xf7d4863accf158b7L,0xb2a81e4494ee57daL } }, - /* 174 */ - { { 0xff288e5b6d53e6baL,0xa90de1a914484ea2L,0x2fadb60ced33c8ecL, - 0x579d6ef328b66a40L,0x4f2dd6ddec24372dL,0xe9e33fc91d66ec7dL }, - { 0x110899d2039eab6eL,0xa31a667a3e97bb5eL,0x6200166dcfdce68eL, - 0xbe83ebae5137d54bL,0x085f7d874800acdfL,0xcf4ab1330c6f8c86L } }, - /* 175 */ - { { 0x03f65845931e08fbL,0x6438551e1506e2c0L,0x5791f0dc9c36961fL, - 0x68107b29e3dcc916L,0x83242374f495d2caL,0xd8cfb6636ee5895bL }, - { 0x525e0f16a0349b1bL,0x33cd2c6c4a0fab86L,0x46c12ee82af8dda9L, - 0x7cc424ba71e97ad3L,0x69766ddf37621eb0L,0x95565f56a5f0d390L } }, - /* 176 */ - { { 0xe0e7bbf21a0f5e94L,0xf771e1151d82d327L,0x10033e3dceb111faL, - 0xd269744dd3426638L,0xbdf2d9da00d01ef6L,0x1cb80c71a049ceafL }, - { 0x17f183289e21c677L,0x6452af0519c8f98bL,0x35b9c5f780b67997L, - 0x5c2e1cbe40f8f3d4L,0x43f9165666d667caL,0x9faaa059cf9d6e79L } }, - /* 177 */ - { { 0x8ad246180a078fe6L,0xf6cc73e6464fd1ddL,0x4d2ce34dc3e37448L, - 0x624950c5e3271b5fL,0x62910f5eefc5af72L,0x8b585bf8aa132bc6L }, - { 0x11723985a839327fL,0x34e2d27d4aac252fL,0x402f59ef6296cc4eL, - 0x00ae055c47053de9L,0xfc22a97228b4f09bL,0xa9e86264fa0c180eL } }, - /* 178 */ - { { 0x0b7b6224bc310eccL,0x8a1a74f167fa14edL,0x87dd09607214395cL, - 0xdf1b3d09f5c91128L,0x39ff23c686b264a8L,0xdc2d49d03e58d4c5L }, - { 0x2152b7d3a9d6f501L,0xf4c32e24c04094f7L,0xc6366596d938990fL, - 0x084d078f94fb207fL,0xfd99f1d7328594cbL,0x36defa64cb2d96b3L } }, - /* 179 */ - { { 0x4619b78113ed7cbeL,0x95e500159784bd0eL,0x2a32251c2c7705feL, - 0xa376af995f0dd083L,0x55425c6c0361a45bL,0x812d2cef1f291e7bL }, - { 0xccf581a05fd94972L,0x26e20e39e56dc383L,0x0093685d63dbfbf0L, - 0x1fc164cc36b8c575L,0xb9c5ab81390ef5e7L,0x40086beb26908c66L } }, - /* 180 */ - { { 0xe5e54f7937e3c115L,0x69b8ee8cc1445a8aL,0x79aedff2b7659709L, - 0xe288e1631b46fbe6L,0xdb4844f0d18d7bb7L,0xe0ea23d048aa6424L }, - { 0x714c0e4ef3d80a73L,0x87a0aa9e3bd64f98L,0x8844b8a82ec63080L, - 0xe0ac9c30255d81a3L,0x86151237455397fcL,0x0b9794642f820155L } }, - /* 181 */ - { { 0x127a255a4ae03080L,0x232306b4580a89fbL,0x04e8cd6a6416f539L, - 0xaeb70dee13b02a0eL,0xa3038cf84c09684aL,0xa710ec3c28e433eeL }, - { 0x77a72567681b1f7dL,0x86fbce952fc28170L,0xd3408683f5735ac8L, - 0x3a324e2a6bd68e93L,0x7ec74353c027d155L,0xab60354cd4427177L } }, - /* 182 */ - { { 0x32a5342aef4c209dL,0x2ba7527408d62704L,0x4bb4af6fc825d5feL, - 0x1c3919ced28e7ff1L,0x1dfc2fdcde0340f6L,0xc6580baf29f33ba9L }, - { 0xae121e7541d442cbL,0x4c7727fd3a4724e4L,0xe556d6a4524f3474L, - 0x87e13cc7785642a2L,0x182efbb1a17845fdL,0xdcec0cf14e144857L } }, - /* 183 */ - { { 0x1cb89541e9539819L,0xc8cb3b4f9d94dbf1L,0x1d353f63417da578L, - 0xb7a697fb8053a09eL,0x8d841731c35d8b78L,0x85748d6fb656a7a9L }, - { 0x1fd03947c1859c5dL,0x6ce965c1535d22a2L,0x1966a13e0ca3aadcL, - 0x9802e41d4fb14effL,0xa9048cbb76dd3fcdL,0x89b182b5e9455bbaL } }, - /* 184 */ - { { 0xd777ad6a43360710L,0x841287ef55e9936bL,0xbaf5c67004a21b24L, - 0xf2c0725f35ad86f1L,0x338fa650c707e72eL,0x2bf8ed2ed8883e52L }, - { 0xb0212cf4b56e0d6aL,0x50537e126843290cL,0xd8b184a198b3dc6fL, - 0xd2be9a350210b722L,0x407406db559781eeL,0x5a78d5910bc18534L } }, - /* 185 */ - { { 0x4d57aa2ad748b02cL,0xbe5b3451a12b3b95L,0xadca7a4564711258L, - 0x597e091a322153dbL,0xf327100632eb1eabL,0xbd9adcba2873f301L }, - { 0xd1dc79d138543f7fL,0x00022092921b1fefL,0x86db3ef51e5df8edL, - 0x888cae049e6b944aL,0x71bd29ec791a32b4L,0xd3516206a6d1c13eL } }, - /* 186 */ - { { 0x2ef6b95255924f43L,0xd2f401ae4f9de8d5L,0xfc73e8d7adc68042L, - 0x627ea70c0d9d1bb4L,0xc3bb3e3ebbf35679L,0x7e8a254ad882dee4L }, - { 0x08906f50b5924407L,0xf14a0e61a1ad444aL,0xaa0efa2165f3738eL, - 0xd60c7dd6ae71f161L,0x9e8390faf175894dL,0xd115cd20149f4c00L } }, - /* 187 */ - { { 0x2f2e2c1da52abf77L,0xc2a0dca554232568L,0xed423ea254966dccL, - 0xe48c93c7cd0dd039L,0x1e54a225176405c7L,0x1efb5b1670d58f2eL }, - { 0xa751f9d994fb1471L,0xfdb31e1f67d2941dL,0xa6c74eb253733698L, - 0xd3155d1189a0f64aL,0x4414cfe4a4b8d2b6L,0x8d5a4be8f7a8e9e3L } }, - /* 188 */ - { { 0x5c96b4d452669e98L,0x4547f9228fd42a03L,0xcf5c1319d285174eL, - 0x805cd1ae064bffa0L,0x50e8bc4f246d27e7L,0xf89ef98fd5781e11L }, - { 0xb4ff95f6dee0b63fL,0xad850047222663a4L,0x026918604d23ce9cL, - 0x3e5309ce50019f59L,0x27e6f72269a508aeL,0xe9376652267ba52cL } }, - /* 189 */ - { { 0xa04d289cc0368708L,0xc458872f5e306e1dL,0x76fa23de33112feaL, - 0x718e39746efde42eL,0xf0c98cdc1d206091L,0x5fa3ca6214a71987L }, - { 0xeee8188bdcaa9f2aL,0x312cc732589a860dL,0xf9808dd6c63aeb1fL, - 0x70fd43db4ea62b53L,0x2c2bfe34890b6e97L,0x105f863cfa426aa6L } }, - /* 190 */ - { { 0x0b29795db38059adL,0x5686b77e90647ea0L,0xeff0470edb473a3eL, - 0x278d2340f9b6d1e2L,0xebbff95bbd594ec7L,0xf4b72334d3a7f23dL }, - { 0x2a285980a5a83f0bL,0x0786c41a9716a8b3L,0x138901bd22511812L, - 0xd1b55221e2fede6eL,0x0806e264df4eb590L,0x6c4c897e762e462eL } }, - /* 191 */ - { { 0xd10b905fb4b41d9dL,0x826ca4664523a65bL,0x535bbd13b699fa37L, - 0x5b9933d773bc8f90L,0x9332d61fcd2118adL,0x158c693ed4a65fd0L }, - { 0x4ddfb2a8e6806e63L,0xe31ed3ecb5de651bL,0xf9460e51819bc69aL, - 0x6229c0d62c76b1f8L,0xbb78f231901970a3L,0x31f3820f9cee72b8L } }, - /* 192 */ - { { 0xe931caf2c09e1c72L,0x0715f29812990cf4L,0x33aad81d943262d8L, - 0x5d292b7a73048d3fL,0xb152aaa4dc7415f6L,0xc3d10fd90fd19587L }, - { 0xf76b35c575ddadd0L,0x9f5f4a511e7b694cL,0x2f1ab7ebc0663025L, - 0x01c9cc87920260b0L,0xc4b1f61a05d39da6L,0x6dcd76c4eb4a9c4eL } }, - /* 193 */ - { { 0x0ba0916ffdc83f01L,0x354c8b449553e4f9L,0xa6cc511affc5e622L, - 0xb954726ae95be787L,0xcb04811575b41a62L,0xfa2ae6cdebfde989L }, - { 0x6376bbc70f24659aL,0x13a999fd4c289c43L,0xc7134184ec9abd8bL, - 0x28c02bf6a789ab04L,0xff841ebcd3e526ecL,0x442b191e640893a8L } }, - /* 194 */ - { { 0x4cac6c62fa2b6e20L,0x97f29e9bf6d69861L,0x228ab1dbbc96d12dL, - 0x6eb913275e8e108dL,0xd4b3d4d140771245L,0x61b20623ca8a803aL }, - { 0x2c2f3b41a6a560b1L,0x879e1d403859fcf4L,0x7cdb5145024dbfc3L, - 0x55d08f153bfa5315L,0x2f57d773aa93823aL,0xa97f259cc6a2c9a2L } }, - /* 195 */ - { { 0xc306317be58edbbbL,0x25ade51c79dfdf13L,0x6b5beaf116d83dd6L, - 0xe8038a441dd8f925L,0x7f00143cb2a87b6bL,0xa885d00df5b438deL }, - { 0xe9f76790cf9e48bdL,0xf0bdf9f0a5162768L,0x0436709fad7b57cbL, - 0x7e151c12f7c15db7L,0x3514f0225d90ee3bL,0x2e84e8032c361a8dL } }, - /* 196 */ - { { 0x2277607d563ec8d8L,0xa661811fe3934cb7L,0x3ca72e7af58fd5deL, - 0x7989da0462294c6aL,0x88b3708bf6bbefe9L,0x0d524cf753ed7c82L }, - { 0x69f699ca2f30c073L,0xf0fa264b9dc1dcf3L,0x44ca456805f0aaf6L, - 0x0f5b23c7d19b9bafL,0x39193f41eabd1107L,0x9e3e10ad2a7c9b83L } }, - /* 197 */ - { { 0xa90824f0d4ae972fL,0x43eef02bc6e846e7L,0x7e46061229d2160aL, - 0x29a178acfe604e91L,0x23056f044eb184b2L,0x4fcad55feb54cdf4L }, - { 0xa0ff96f3ae728d15L,0x8a2680c6c6a00331L,0x5f84cae07ee52556L, - 0x5e462c3ac5a65dadL,0x5d2b81dfe2d23f4fL,0x6e47301bc5b1eb07L } }, - /* 198 */ - { { 0x77411d68af8219b9L,0xcb883ce651b1907aL,0x25c87e57101383b5L, - 0x9c7d9859982f970dL,0xaa6abca5118305d2L,0x725fed2f9013a5dbL }, - { 0x487cdbafababd109L,0xc0f8cf5687586528L,0xa02591e68ad58254L, - 0xc071b1d1debbd526L,0x927dfe8b961e7e31L,0x55f895f99263dfe1L } }, - /* 199 */ - { { 0xf899b00db175645bL,0x51f3a627b65b4b92L,0xa2f3ac8db67399efL, - 0xe717867fe400bc20L,0x42cc90201967b952L,0x3d5967513ecd1de1L }, - { 0xd41ebcdedb979775L,0x99ba61bc6a2e7e88L,0x039149a5321504f2L, - 0xe7dc231427ba2fadL,0x9f556308b57d8368L,0x2b6d16c957da80a7L } }, - /* 200 */ - { { 0x84af5e76279ad982L,0x9bb4c92d9c8b81a6L,0xd79ad44e0e698e67L, - 0xe8be9048265fc167L,0xf135f7e60c3a4cccL,0xa0a10d38b8863a33L }, - { 0xe197247cd386efd9L,0x0eefd3f9b52346c2L,0xc22415f978607bc8L, - 0xa2a8f862508674ceL,0xa72ad09ec8c9d607L,0xcd9f0ede50fa764fL } }, - /* 201 */ - { { 0x063391c7d1a46d4dL,0x2df51c119eb01693L,0xc5849800849e83deL, - 0x48fd09aa8ad08382L,0xa405d873aa742736L,0xee49e61ee1f9600cL }, - { 0xd76676be48c76f73L,0xd9c100f601274b2aL,0x110bb67c83f8718dL, - 0xec85a42002fc0d73L,0xc0449e1e744656adL,0x28ce737637d9939bL } }, - /* 202 */ - { { 0x97e9af7244544ac7L,0xf2c658d5ba010426L,0x732dec39fb3adfbdL, - 0xd12faf91a2df0b07L,0x8ac267252171e208L,0xf820cdc85b24fa54L }, - { 0x307a6eea94f4cf77L,0x18c783d2944a33c6L,0x4b939d4c0b741ac5L, - 0x1d7acd153ffbb6e4L,0x06a248587a255e44L,0x14fbc494ce336d50L } }, - /* 203 */ - { { 0x9b920c0c51584e3cL,0xc7733c59f7e54027L,0xe24ce13988422bbeL, - 0x11ada812523bd6abL,0xde068800b88e6defL,0x7b872671fe8c582dL }, - { 0x4e746f287de53510L,0x492f8b99f7971968L,0x1ec80bc77d928ac2L, - 0xb3913e48432eb1b5L,0xad08486632028f6eL,0x122bb8358fc2f38bL } }, - /* 204 */ - { { 0x0a9f3b1e3b0b29c3L,0x837b64324fa44151L,0xb9905c9217b28ea7L, - 0xf39bc93798451750L,0xcd383c24ce8b6da1L,0x299f57db010620b2L }, - { 0x7b6ac39658afdce3L,0xa15206b33d05ef47L,0xa0ae37e2b9bb02ffL, - 0x107760ab9db3964cL,0xe29de9a067954beaL,0x446a1ad8431c3f82L } }, - /* 205 */ - { { 0xc6fecea05c6b8195L,0xd744a7c5f49e71b9L,0xa8e96acc177a7ae7L, - 0x1a05746c358773a7L,0xa416214637567369L,0xaa0217f787d1c971L }, - { 0x61e9d15877fd3226L,0x0f6f2304e4f600beL,0xa9c4cebc7a6dff07L, - 0xd15afa0109f12a24L,0x2bbadb228c863ee9L,0xa28290e4e5eb8c78L } }, - /* 206 */ - { { 0x55b87fa03e9de330L,0x12b26066195c145bL,0xe08536e0a920bef0L, - 0x7bff6f2c4d195adcL,0x7f319e9d945f4187L,0xf9848863f892ce47L }, - { 0xd0efc1d34fe37657L,0x3c58de825cf0e45aL,0x626ad21a8b0ccbbeL, - 0xd2a31208af952fc5L,0x81791995eb437357L,0x5f19d30f98e95d4fL } }, - /* 207 */ - { { 0x72e83d9a0e6865bbL,0x22f5af3bf63456a6L,0x409e9c73463c8d9eL, - 0x40e9e578dfe6970eL,0x876b6efa711b91caL,0x895512cf942625a3L }, - { 0x84c8eda8cb4e462bL,0x84c0154a4412e7c8L,0x04325db1ceb7b71fL, - 0x1537dde366f70877L,0xf3a093991992b9acL,0xa7316606d498ae77L } }, - /* 208 */ - { { 0x13990d2fcad260f5L,0x76c3be29eec0e8c0L,0x7dc5bee00f7bd7d5L, - 0x9be167d2efebda4bL,0xcce3dde69122b87eL,0x75a28b0982b5415cL }, - { 0xf6810bcde84607a6L,0xc6d581286f4dbf0dL,0xfead577d1b4dafebL, - 0x9bc440b2066b28ebL,0x53f1da978b17e84bL,0x0459504bcda9a575L } }, - /* 209 */ - { { 0x13e39a02329e5836L,0x2c9e7d51f717269dL,0xc5ac58d6f26c963bL, - 0x3b0c6c4379967bf5L,0x60bbea3f55908d9dL,0xd84811e7f07c9ad1L }, - { 0xfe7609a75bd20e4aL,0xe4325dd20a70baa8L,0x3711f370b3600386L, - 0x97f9562fd0924302L,0x040dc0c34acc4436L,0xfd6d725cde79cdd4L } }, - /* 210 */ - { { 0xb3efd0e3cf13eafbL,0x21009cbb5aa0ae5fL,0xe480c55379022279L, - 0x755cf334b2fc9a6dL,0x8564a5bf07096ae7L,0xddd649d0bd238139L }, - { 0xd0de10b18a045041L,0x6e05b413c957d572L,0x5c5ff8064e0fb25cL, - 0xd933179b641162fbL,0x42d48485e57439f9L,0x70c5bd0a8a8d72aaL } }, - /* 211 */ - { { 0xa767173897bdf646L,0xaa1485b4ab329f7cL,0xce3e11d6f8f25fdfL, - 0x76a3fc7ec6221824L,0x045f281ff3924740L,0x24557d4e96d13a9aL }, - { 0x875c804bdd4c27cdL,0x11c5f0f40f5c7feaL,0xac8c880bdc55ff7eL, - 0x2acddec51103f101L,0x38341a21f99faa89L,0xc7b67a2cce9d6b57L } }, - /* 212 */ - { { 0x9a0d724f8e357586L,0x1d7f4ff5df648da0L,0x9c3e6c9bfdee62a5L, - 0x0499cef00389b372L,0xe904050d98eab879L,0xe8eef1b66c051617L }, - { 0xebf5bfebc37e3ca9L,0x7c5e946da4e0b91dL,0x790973142c4bea28L, - 0x81f6c109ee67b2b7L,0xaf237d9bdafc5edeL,0xd2e602012abb04c7L } }, - /* 213 */ - { { 0x6156060c8a4f57bfL,0xf9758696ff11182aL,0x8336773c6296ef00L, - 0x9c054bceff666899L,0xd6a11611719cd11cL,0x9824a641dbe1acfaL }, - { 0x0b7b7a5fba89fd01L,0xf8d3b809889f79d8L,0xc5e1ea08f578285cL, - 0x7ac74536ae6d8288L,0x5d37a2007521ef5fL,0x5ecc4184b260a25dL } }, - /* 214 */ - { { 0xddcebb19a708c8d3L,0xe63ed04fc63f81ecL,0xd045f5a011873f95L, - 0x3b5ad54479f276d5L,0x81272a3d425ae5b3L,0x8bfeb50110ce1605L }, - { 0x4233809c888228bfL,0x4bd82acfb2aff7dfL,0x9c68f1800cbd4a7fL, - 0xfcd771246b44323dL,0x60c0fcf6891db957L,0xcfbb4d8904da8f7fL } }, - /* 215 */ - { { 0x9a6a5df93b26139aL,0x3e076a83b2cc7eb8L,0x47a8e82d5a964bcdL, - 0x8a4e2a39b9278d6bL,0x93506c98e4443549L,0x06497a8ff1e0d566L }, - { 0x3dee8d992b1efa05L,0x2da63ca845393e33L,0xa4af7277cf0579adL, - 0xaf4b46393236d8eaL,0x6ccad95b32b617f5L,0xce76d8b8b88bb124L } }, - /* 216 */ - { { 0x63d2537a083843dcL,0x89eb35141e4153b4L,0x5175ebc4ea9afc94L, - 0x7a6525808ed1aed7L,0x67295611d85e8297L,0x8dd2d68bb584b73dL }, - { 0x237139e60133c3a4L,0x9de838ab4bd278eaL,0xe829b072c062fcd9L, - 0x70730d4f63ba8706L,0x6080483fd3cd05ecL,0x872ab5b80c85f84dL } }, - /* 217 */ - { { 0xfc0776d3999d4d49L,0xa3eb59deec3f45e7L,0xbc990e440dae1fc1L, - 0x33596b1ea15371ffL,0xd447dcb29bc7ab25L,0xcd5b63e935979582L }, - { 0xae3366fa77d1ff11L,0x59f28f05edee6903L,0x6f43fed1a4433bf2L, - 0x15409c9bdf9ce00eL,0x21b5cdedaca9c5dcL,0xf9f3359582d7bdb4L } }, - /* 218 */ - { { 0x959443789422c792L,0x239ea923c958b8bfL,0x4b61a247df076541L, - 0x4d29ce85bb9fc544L,0x9a692a670b424559L,0x6e0ca5a00e486900L }, - { 0x6b79a78285b3beceL,0x41f35e39c61f9892L,0xff82099aae747f82L, - 0x58c8ae3fd0ca59d6L,0x4ac930e299406b5fL,0x2ce04eb99df24243L } }, - /* 219 */ - { { 0x4366b9941ac37b82L,0xff0c728d25b04d83L,0x1f55136119c47b7cL, - 0xdbf2d5edbeff13e7L,0xf78efd51e12a683dL,0x82cd85b9989cf9c4L }, - { 0xe23c6db6e0cb5d37L,0x818aeebd72ee1a15L,0x8212aafd28771b14L, - 0x7bc221d91def817dL,0xdac403a29445c51fL,0x711b051712c3746bL } }, - /* 220 */ - { { 0x0ed9ed485ea99eccL,0xf799500db8cab5e1L,0xa8ec87dcb570cbdcL, - 0x52cfb2c2d35dfaecL,0x8d31fae26e4d80a4L,0xe6a37dc9dcdeabe5L }, - { 0x5d365a341deca452L,0x09a5f8a50d68b44eL,0x59238ea5a60744b1L, - 0xf2fedc0dbb4249e9L,0xe395c74ea909b2e3L,0xe156d1a539388250L } }, - /* 221 */ - { { 0xd796b3d047181ae9L,0xbaf44ba844197808L,0xe693309434cf3facL, - 0x41aa6adec3bd5c46L,0x4fda75d8eed947c6L,0xacd9d4129ea5a525L }, - { 0x65cc55a3d430301bL,0x3c9a5bcf7b52ea49L,0x22d319cf159507f0L, - 0x2ee0b9b5de74a8ddL,0x20c26a1e877ac2b6L,0x387d73da92e7c314L } }, - /* 222 */ - { { 0x13c4833e8cd3fdacL,0x76fcd473332e5b8eL,0xff671b4be2fe1fd3L, - 0x4d734e8b5d98d8ecL,0xb1ead3c6514bbc11L,0xd14ca8587b390494L }, - { 0x95a443af5d2d37e9L,0x73c6ea7300464622L,0xa44aeb4b15755044L, - 0xba3f8575fab58feeL,0x9779dbc9dc680a6fL,0xe1ee5f5a7b37ddfcL } }, - /* 223 */ - { { 0xcd0b464812d29f46L,0x93295b0b0ed53137L,0xbfe2609480bef6c9L, - 0xa656578854248b00L,0x69c43fca80e7f9c4L,0x2190837bbe141ea1L }, - { 0x875e159aa1b26cfbL,0x90ca9f877affe852L,0x15e6550d92ca598eL, - 0xe3e0945d1938ad11L,0xef7636bb366ef937L,0xb6034d0bb39869e5L } }, - /* 224 */ - { { 0x4d255e3026d8356eL,0xf83666edd314626fL,0x421ddf61d0c8ed64L, - 0x96e473c526677b61L,0xdad4af7e9e9b18b3L,0xfceffd4aa9393f75L }, - { 0x843138a111c731d5L,0x05bcb3a1b2f141d9L,0x20e1fa95617b7671L, - 0xbefce81288ccec7bL,0x582073dc90f1b568L,0xf572261a1f055cb7L } }, - /* 225 */ - { { 0xf314827736973088L,0xc008e70886a9f980L,0x1b795947e046c261L, - 0xdf1e6a7dca76bca0L,0xabafd88671acddf0L,0xff7054d91364d8f4L }, - { 0x2cf63547e2260594L,0x468a5372d73b277eL,0xc7419e24ef9bd35eL, - 0x2b4a1c2024043cc3L,0xa28f047a890b39cdL,0xdca2cea146f9a2e3L } }, - /* 226 */ - { { 0xab78873653277538L,0xa734e225cf697738L,0x66ee1d1e6b22e2c1L, - 0x2c615389ebe1d212L,0xf36cad4002bb0766L,0x120885c33e64f207L }, - { 0x59e77d5690fbfec2L,0xf9e781aad7a574aeL,0x801410b05d045e53L, - 0xd3b5f0aaa91b5f0eL,0xb3d1df007fbb3521L,0x11c4b33ec72bee9aL } }, - /* 227 */ - { { 0xd32b983283c3a7f3L,0x8083abcf88d8a354L,0xdeb1640450f4ec5aL, - 0x18d747f0641e2907L,0x4e8978aef1bbf03eL,0x932447dc88a0cd89L }, - { 0x561e0febcf3d5897L,0xfc3a682f13600e6dL,0xc78b9d73d16a6b73L, - 0xe713feded29bf580L,0x0a22522308d69e5cL,0x3a924a571ff7fda4L } }, - /* 228 */ - { { 0xfb64554cb4093beeL,0xa6d65a25a58c6ec0L,0x4126994d43d0ed37L, - 0xa5689a5155152d44L,0xb8e5ea8c284caa8dL,0x33f05d4fd1f25538L }, - { 0xe0fdfe091b615d6eL,0x2ded7e8f705507daL,0xdd5631e517bbcc80L, - 0x4f87453e267fd11fL,0xc6da723fff89d62dL,0x55cbcae2e3cda21dL } }, - /* 229 */ - { { 0x336bc94e6b4e84f3L,0x728630314ef72c35L,0x6d85fdeeeeb57f99L, - 0x7f4e3272a42ece1bL,0x7f86cbb536f0320aL,0xf09b6a2b923331e6L }, - { 0x21d3ecf156778435L,0x2977ba998323b2d2L,0x6a1b57fb1704bc0fL, - 0xd777cf8b389f048aL,0x9ce2174fac6b42cdL,0x404e2bff09e6c55aL } }, - /* 230 */ - { { 0x9b9b135e204c5ddbL,0x9dbfe0443eff550eL,0x35eab4bfec3be0f6L, - 0x8b4c3f0d0a43e56fL,0x4c1c66730e73f9b3L,0x92ed38bd2c78c905L }, - { 0xc7003f6aa386e27cL,0xb9c4f46faced8507L,0xea024ec859df5464L, - 0x4af96152429572eaL,0x279cd5e2e1fc1194L,0xaa376a03281e358cL } }, - /* 231 */ - { { 0x078592233cdbc95cL,0xaae1aa6aef2e337aL,0xc040108d472a8544L, - 0x80c853e68d037b7dL,0xd221315c8c7eee24L,0x195d38568ee47752L }, - { 0xd4b1ba03dacd7fbeL,0x4b5ac61ed3e0c52bL,0x68d3c0526aab7b52L, - 0xf0d7248c660e3feaL,0xafdb3f893145efb4L,0xa73fd9a38f40936dL } }, - /* 232 */ - { { 0x891b9ef3bb1b17ceL,0x14023667c6127f31L,0x12b2e58d305521fdL, - 0x3a47e449e3508088L,0xe49fc84bff751507L,0x4023f7225310d16eL }, - { 0xa608e5edb73399faL,0xf12632d8d532aa3eL,0x13a2758e845e8415L, - 0xae4b6f851fc2d861L,0x3879f5b1339d02f2L,0x446d22a680d99ebdL } }, - /* 233 */ - { { 0x0f5023024be164f1L,0x8d09d2d688b81920L,0x514056f1984aceffL, - 0xa5c4ddf075e9e80dL,0x38cb47e6df496a93L,0x899e1d6b38df6bf7L }, - { 0x69e87e88b59eb2a6L,0x280d9d639b47f38bL,0x599411ea3654e955L, - 0xcf8dd4fd969aa581L,0xff5c2baf530742a7L,0xa43915361a373085L } }, - /* 234 */ - { { 0x6ace72a3a8a4bdd2L,0xc656cdd1b68ef702L,0xd4a33e7e90c4dad8L, - 0x4aece08a9d951c50L,0xea8005ae085d68e6L,0xfdd7a7d76f7502b8L }, - { 0xce6fb0a698d6fa45L,0x228f86721104eb8cL,0xd23d8787da09d7dcL, - 0x5521428b2ae93065L,0x95faba3dea56c366L,0xedbe50390a88aca5L } }, - /* 235 */ - { { 0xd64da0adbfb26c82L,0xe5d70b3c952c2f9cL,0xf5e8f365f7e77f68L, - 0x7234e00208f2d695L,0xfaf900eed12e7be6L,0x27dc69344acf734eL }, - { 0x80e4ff5ec260a46aL,0x7da5ebce2dc31c28L,0x485c5d73ca69f552L, - 0xcdfb6b2969cc84c2L,0x031c5afeed6d4ecaL,0xc7bbf4c822247637L } }, - /* 236 */ - { { 0x9d5b72c749fe01b2L,0x34785186793a91b8L,0xa3ba3c54cf460438L, - 0x73e8e43d3ab21b6fL,0x50cde8e0be57b8abL,0x6488b3a7dd204264L }, - { 0xa9e398b3dddc4582L,0x1698c1a95bec46feL,0x7f1446ef156d3843L, - 0x3fd25dd8770329a2L,0x05b1221a2c710668L,0x65b2dc2aa72ee6cfL } }, - /* 237 */ - { { 0x21a885f7cd021d63L,0x3f344b15fea61f08L,0xad5ba6ddc5cf73e6L, - 0x154d0d8f227a8b23L,0x9b74373cdc559311L,0x4feab71598620fa1L }, - { 0x5098938e7d9ec924L,0x84d54a5e6d47e550L,0x1a2d1bdc1b617506L, - 0x99fe1782615868a4L,0x171da7803005a924L,0xa70bf5ed7d8f79b6L } }, - /* 238 */ - { { 0x0bc1250dfe2216c5L,0x2c37e2507601b351L,0xb6300175d6f06b7eL, - 0x4dde8ca18bfeb9b7L,0x4f210432b82f843dL,0x8d70e2f9b1ac0afdL }, - { 0x25c73b78aae91abbL,0x0230dca3863028f2L,0x8b923ecfe5cf30b7L, - 0xed754ec25506f265L,0x8e41b88c729a5e39L,0xee67cec2babf889bL } }, - /* 239 */ - { { 0xe183acf51be46c65L,0x9789538fe7565d7aL,0x87873391d9627b4eL, - 0xbf4ac4c19f1d9187L,0x5db99f634691f5c8L,0xa68df80374a1fb98L }, - { 0x3c448ed1bf92b5faL,0xa098c8413e0bdc32L,0x8e74cd5579bf016cL, - 0x5df0d09c115e244dL,0x9418ad013410b66eL,0x8b6124cb17a02130L } }, - /* 240 */ - { { 0x425ec3afc26e3392L,0xc07f8470a1722e00L,0xdcc28190e2356b43L, - 0x4ed97dffb1ef59a6L,0xc22b3ad1c63028c1L,0x070723c268c18988L }, - { 0x70da302f4cf49e7dL,0xc5e87c933f12a522L,0x74acdd1d18594148L, - 0xad5f73abca74124cL,0xe72e4a3ed69fd478L,0x615938687b117cc3L } }, - /* 241 */ - { { 0x7b7b9577a9aa0486L,0x6e41fb35a063d557L,0xb017d5c7da9047d7L, - 0x8c74828068a87ba9L,0xab45fa5cdf08ad93L,0xcd9fb2174c288a28L }, - { 0x595446425747843dL,0x34d64c6ca56111e3L,0x12e47ea14bfce8d5L, - 0x17740e056169267fL,0x5c49438eeed03fb5L,0x9da30add4fc3f513L } }, - /* 242 */ - { { 0xc4e85282ccfa5200L,0x2707608f6a19b13dL,0xdcb9a53df5726e2fL, - 0x612407c9e9427de5L,0x3e5a17e1d54d582aL,0xb99877de655ae118L }, - { 0x6f0e972b015254deL,0x92a56db1f0a6f7c5L,0xd297e4e1a656f8b2L, - 0x99fe0052ad981983L,0xd3652d2f07cfed84L,0xc784352e843c1738L } }, - /* 243 */ - { { 0x6ee90af07e9b2d8aL,0xac8d701857cf1964L,0xf6ed903171f28efcL, - 0x7f70d5a96812b20eL,0x27b557f4f1c61eeeL,0xf1c9bd57c6263758L }, - { 0x5cf7d0142a1a6194L,0xdd614e0b1890ab84L,0x3ef9de100e93c2a6L, - 0xf98cf575e0cd91c5L,0x504ec0c614befc32L,0xd0513a666279d68cL } }, - /* 244 */ - { { 0xa8eadbada859fb6aL,0xcf8346e7db283666L,0x7b35e61a3e22e355L, - 0x293ece2c99639c6bL,0xfa0162e256f241c8L,0xd2e6c7b9bf7a1ddaL }, - { 0xd0de625340075e63L,0x2405aa61f9ec8286L,0x2237830a8fe45494L, - 0x4fd01ac7364e9c8cL,0x4d9c3d21904ba750L,0xd589be14af1b520bL } }, - /* 245 */ - { { 0x13576a4f4662e53bL,0x35ec2f51f9077676L,0x66297d1397c0af97L, - 0xed3201fe9e598b58L,0x49bc752a5e70f604L,0xb54af535bb12d951L }, - { 0x36ea4c2b212c1c76L,0x18f5bbc7eb250dfdL,0xa0d466cc9a0a1a46L, - 0x52564da4dac2d917L,0x206559f48e95fab5L,0x7487c1909ca67a33L } }, - /* 246 */ - { { 0x75abfe37dde98e9cL,0x99b90b262a411199L,0x1b410996dcdb1f7cL, - 0xab346f118b3b5675L,0x04852193f1f8ae1eL,0x1ec4d2276b8b98c1L }, - { 0xba3bc92645452baaL,0x387d1858acc4a572L,0x9478eff6e51f171eL, - 0xf357077d931e1c00L,0xffee77cde54c8ca8L,0xfb4892ff551dc9a4L } }, - /* 247 */ - { { 0x5b1bdad02db8dff8L,0xd462f4fd5a2285a2L,0x1d6aad8eda00b461L, - 0x43fbefcf41306d1bL,0x428e86f36a13fe19L,0xc8b2f11817f89404L }, - { 0x762528aaf0d51afbL,0xa3e2fea4549b1d06L,0x86fad8f2ea3ddf66L, - 0x0d9ccc4b4fbdd206L,0xcde97d4cc189ff5aL,0xc36793d6199f19a6L } }, - /* 248 */ - { { 0xea38909b51b85197L,0xffb17dd0b4c92895L,0x0eb0878b1ddb3f3fL, - 0xb05d28ffc57cf0f2L,0xd8bde2e71abd57e2L,0x7f2be28dc40c1b20L }, - { 0x6554dca2299a2d48L,0x5130ba2e8377982dL,0x8863205f1071971aL, - 0x15ee62827cf2825dL,0xd4b6c57f03748f2bL,0xa9e3f4da430385a0L } }, - /* 249 */ - { { 0x33eb7cec83fbc9c6L,0x24a311c74541777eL,0xc81377f74f0767fcL, - 0x12adae364ab702daL,0xb7fcb6db2a779696L,0x4a6fb28401cea6adL }, - { 0x5e8b1d2acdfc73deL,0xd0efae8d1b02fd32L,0x3f99c190d81d8519L, - 0x3c18f7fafc808971L,0x41f713e751b7ae7bL,0x0a4b3435f07fc3f8L } }, - /* 250 */ - { { 0x7dda3c4c019b7d2eL,0x631c8d1ad4dc4b89L,0x5489cd6e1cdb313cL, - 0xd44aed104c07bb06L,0x8f97e13a75f000d1L,0x0e9ee64fdda5df4dL }, - { 0xeaa99f3b3e346910L,0x622f6921fa294ad7L,0x22aaa20d0d0b2fe9L, - 0x4fed2f991e5881baL,0x9af3b2d6c1571802L,0x919e67a8dc7ee17cL } }, - /* 251 */ - { { 0xc724fe4c76250533L,0x8a2080e57d817ef8L,0xa2afb0f4172c9751L, - 0x9b10cdeb17c0702eL,0xbf3975e3c9b7e3e9L,0x206117df1cd0cdc5L }, - { 0xfb049e61be05ebd5L,0xeb0bb55c16c782c0L,0x13a331b8ab7fed09L, - 0xf6c58b1d632863f0L,0x6264ef6e4d3b6195L,0x92c51b639a53f116L } }, - /* 252 */ - { { 0xa57c7bc8288b364dL,0x4a562e087b41e5c4L,0x699d21c6698a9a11L, - 0xa4ed9581f3f849b9L,0xa223eef39eb726baL,0x13159c23cc2884f9L }, - { 0x73931e583a3f4963L,0x965003890ada6a81L,0x3ee8a1c65ab2950bL, - 0xeedf4949775fab52L,0x63d652e14f2671b6L,0xfed4491c3c4e2f55L } }, - /* 253 */ - { { 0x335eadc3f4eb453eL,0x5ff74b63cadd1a5bL,0x6933d0d75d84a91aL, - 0x9ca3eeb9b49ba337L,0x1f6faccec04c15b8L,0x4ef19326dc09a7e4L }, - { 0x53d2d3243dca3233L,0x0ee40590a2259d4bL,0x18c22edb5546f002L, - 0x9242980109ea6b71L,0xaada0addb0e91e61L,0x5fe53ef499963c50L } }, - /* 254 */ - { { 0x372dd06b90c28c65L,0x1765242c119ce47dL,0xc041fb806b22fc82L, - 0x667edf07b0a7ccc1L,0xc79599e71261beceL,0xbc69d9ba19cff22aL }, - { 0x009d77cd13c06819L,0x635a66aee282b79dL,0x4edac4a6225b1be8L, - 0x57d4f4e4524008f9L,0xee299ac5b056af84L,0xcc38444c3a0bc386L } }, - /* 255 */ - { { 0x490643b1cd4c2356L,0x740a4851750547beL,0x643eaf29d4944c04L, - 0xba572479299a98a0L,0x48b29f16ee05fdf9L,0x33fb4f61089b2d7bL }, - { 0x86704902a950f955L,0x97e1034dfedc3ddfL,0x211320b605fbb6a2L, - 0x23d7b93f432299bbL,0x1fe1a0578590e4a3L,0x8e1d0586f58c0ce6L } }, + { { 0x1ae0c4e11c718580L,0x303f48a6bf99a0bfL,0xa5551e4491ae219fL, + 0xdc41d9bd55a05287L,0xd5aa73e36872b123L,0x6fd94b0ce6395bf6L }, + { 0xbb95fdbac00afbc1L,0x9cd96208497cac10L,0x8adbd8c1ca51afeaL, + 0x94fedafbf3bc5f5fL,0x29c0217bdf9f5371L,0x5c13eb4bd9024634L } }, }; /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -29370,6 +29008,11 @@ static int sp_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * + * Stripe implementation. + * Pre-generated: 2^0, 2^64, ... + * Pre-generated: products of all combinations of above. + * 6 doubles and adds (with qz=1) + * * r Resulting point. * k Scalar to multiply by. * map Indicates whether to convert result to affine. @@ -29385,6 +29028,18117 @@ static int sp_384_ecc_mulmod_base_avx2_6(sp_point_384* r, const sp_digit* k, } #endif /* HAVE_INTEL_AVX2 */ +#else /* WOLFSSL_SP_SMALL */ +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_6_7[130] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static const uint8_t recode_neg_6_7[130] = { + 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, 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, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to perform. + */ +static void sp_384_ecc_recode_7_6(const sp_digit* k, ecc_recode_384* v) +{ + int i; + int j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<55; i++) { + y = (int8_t)n; + if (o + 7 < 64) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 64) { + n >>= 7; + if (++j < 6) + n = k[j]; + o = 0; + } + else if (++j < 6) { + n = k[j]; + y |= (uint8_t)((n << (64 - o)) & 0x7f); + o -= 57; + n >>= o; + } + + y += (uint8_t)carry; + v[i].i = recode_index_6_7[y]; + v[i].neg = recode_neg_6_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +extern void sp_384_get_entry_65_6(sp_point_384* r, const sp_table_entry_384* table, int idx); +extern void sp_384_get_entry_65_avx2_6(sp_point_384* r, const sp_table_entry_384* table, int idx); +static const sp_table_entry_384 p384_table[3575] = { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 0 */ + { { 0x3dd0756649c0b528L,0x20e378e2a0d6ce38L,0x879c3afc541b4d6eL, + 0x6454868459a30effL,0x812ff723614ede2bL,0x4d3aadc2299e1513L }, + { 0x23043dad4b03a4feL,0xa1bfa8bf7bb4a9acL,0x8bade7562e83b050L, + 0xc6c3521968f4ffd9L,0xdd8002263969a840L,0x2b78abc25a15c5e9L } }, + /* 2 << 0 */ + { { 0xc8229e55783dde91L,0x8e6c8f2e022b53f0L,0x3504e6f0ff9d48a1L, + 0xda821495f0687f50L,0x9c90a4fd2de4b506L,0xdb93b776427460c3L }, + { 0x42ea84633140bfdaL,0xe8e8e4a8c2aaccd8L,0x15e4f18bdc588258L, + 0x09f1fe415172bad9L,0x070d430900b0e684L,0xe34947f7123df0c2L } }, + /* 3 << 0 */ + { { 0x05e4dbe6c1dc4073L,0xc54ea9fff04f779cL,0x6b2034e9a170ccf0L, + 0x3a48d732d51c6c3eL,0xe36f7e2d263aa470L,0xd283fe68e7c1c3acL }, + { 0x7e284821c04ee157L,0x92d789a77ae0e36dL,0x132663c04ef67446L, + 0x68012d5ad2e1d0b4L,0xf6db68b15102b339L,0x465465fc983292afL } }, + /* 4 << 0 */ + { { 0x0aae8477ebb68f2cL,0x30594ccbee0421e3L,0x2e4f153b0aecac46L, + 0x078358d4736400adL,0xfb40f647d685d979L,0xcfeee6dd34179228L }, + { 0x54f3e8e79b3a03b2L,0xe74bb7f17bfec97eL,0x8e3e61a34c542ad1L, + 0x147162d30418c693L,0xe607b9e33820017dL,0x50946875303df319L } }, + /* 5 << 0 */ + { { 0xbb595eba68f1f0dfL,0xc185c0cbcc873466L,0x7f1eb1b5293c703bL, + 0x60db2cf5aacc05e6L,0xc676b987e2e8e4c6L,0xe1bb26b11d178ffbL }, + { 0x2b694ba07073fa21L,0x22c16e2e72f34566L,0x80b61b3101c35b99L, + 0x4b237faf982c0411L,0xe6c5944024de236dL,0x4db1c9d6e209e4a3L } }, + /* 6 << 0 */ + { { 0x7eb5c9317d56dad8L,0xcb2454b339d3413aL,0xec52930f580d57f2L, + 0x2a33f6661bdf6015L,0x4f0f6a962b02d33bL,0xc482e189f0430c40L }, + { 0x3f62b16ea7b08203L,0x739ac69d5b3d4dceL,0x8bd4bffcb79e33b0L, + 0x93c9e5f61b546f05L,0x586d8ededf21559aL,0xc9962152af2a9ebaL } }, + /* 7 << 0 */ + { { 0xdf13b9d17d69222bL,0x4ce6415f874774b1L,0x731edcf8211faa95L, + 0x5f4215d1659753edL,0xf893db589db2df55L,0x932c9f811c89025bL }, + { 0x0996b2207706a61eL,0x135349d5a8641c79L,0x65aad76f50130844L, + 0x0ff37c0401fff780L,0xf57f238e693b0706L,0xd90a16b6af6c9b3eL } }, + /* 8 << 0 */ + { { 0x23f60a05dd9bcbbaL,0x9e336de5ae9b587aL,0x1c5c2e7193d7e30fL, + 0x1d9aebd64f3ddb37L,0x1c7b5fe116b66423L,0x5db4f184349cd9b1L }, + { 0x0d2cfe83e6655a44L,0x836dbb36b7e55e87L,0x701754bf7d8686e4L, + 0xe9923263a42dbba2L,0x7008d943c48ecf0eL,0x3c0c6dd70d27ef61L } }, + /* 9 << 0 */ + { { 0x2f5d200e2353b92fL,0xe35d87293fd7e4f9L,0x26094833a96d745dL, + 0xdc351dc13cbfff3fL,0x26d464c6dad54d6aL,0x5cab1d1d53636c6aL }, + { 0xf2813072b18ec0b0L,0x3777e270d742aa2fL,0x27f061c7033ca7c2L, + 0xa6ecaccc68ead0d8L,0x7d9429f4ee69a754L,0xe770633431e8f5c6L } }, + /* 10 << 0 */ + { { 0x845539d3c8d99c02L,0x2a15a9a6e58d6787L,0xe9f6368eab225fa3L, + 0x54a612d7eb32cabeL,0xc2f646025c4845ecL,0xa91a5280db1c212eL }, + { 0xbb971f78e67b5fceL,0x03a530eb13b9e85cL,0x592ac0ba794eabfdL, + 0x81961b8ccfd7fd1dL,0x3e03370a47a9b8aaL,0x6eb995bec80174e8L } }, + /* 11 << 0 */ + { { 0xc7708b19b68b8c7dL,0x4532077c44377abaL,0x0dcc67706cdad64fL, + 0x01b8bf56147b6602L,0xf8d89885f0561d79L,0x9c19e9fc7ba9c437L }, + { 0x764eb146bdc4ba25L,0x604fe46bac144b83L,0x3ce813298a77e780L, + 0x2e070f36fe9e682eL,0x41821d0c3a53287aL,0x9aa62f9f3533f918L } }, + /* 12 << 0 */ + { { 0x3db8477270313de0L,0xd4258cc55d970420L,0x03aced26c8edfee1L, + 0xf67eb42235d77d83L,0x523c40dbcf9ab45cL,0x627b415f9c35b26dL }, + { 0xfacc45e48be55ed8L,0x80d60af627aa651aL,0x8c79848fd0e102acL, + 0x40c64a4e66bed5afL,0x0329eab1f7942f0eL,0x0c6e430ef9c4af3dL } }, + /* 13 << 0 */ + { { 0x9b7aeb7e75ccbdfbL,0xb25e28c5f6749a95L,0x8a7a8e4633b7d4aeL, + 0xdb5203a8d9c1bd56L,0xd2657265ed22df97L,0xb51c56e18cf23c94L }, + { 0xf4d394596c3d812dL,0xd8e88f1a87cae0c2L,0x789a2a48cf4d0fe3L, + 0xb7feac2dfec38d60L,0x81fdbd1c3b490ec3L,0x4617adb7cc6979e1L } }, + /* 14 << 0 */ + { { 0x5865e5018f75244cL,0xd02225fb01ec909fL,0xca6b1af8b1f85c2aL, + 0x44ce05ff88957166L,0x8058994c5710c0c9L,0x46d227c432f6b1baL }, + { 0xbe4b4a9003cb68e5L,0x540b8b82730a99d1L,0x1ecc8585e11dbbbfL, + 0x72445345d9c3b691L,0x647d24db13690a74L,0x4429839ddefbadf5L } }, + /* 15 << 0 */ + { { 0x446ad8884709f4a9L,0x2b7210e2ec3dabd8L,0x83ccf19550e07b34L, + 0x59500917789b3075L,0x0fc01fd4eb085993L,0xfb62d26f4903026bL }, + { 0x2309cc9d6fe989bbL,0x61609cbd144bd586L,0x4b23d3a0de06610cL, + 0xdddc2866d898f470L,0x8733fc41400c5797L,0x5a68c6fed0bc2716L } }, + /* 16 << 0 */ + { { 0xda6e8a7f7c33ed91L,0x992afb5b0ecdd2d8L,0x37cf65517917652aL, + 0x317b63ea2887d5ffL,0x37065f5313bdc3faL,0xa10896aa435abaa1L }, + { 0x9b21615fefabca26L,0xeb07ddea230cf00dL,0x914871dc154d410fL, + 0xb333bdfbc88ee148L,0x51c305c6a72d1967L,0x659db48181ef2513L } }, + /* 17 << 0 */ + { { 0x8903e1304b4a3cd0L,0x3ea4ea4c8ff1f43eL,0xe6fc3f2af655a10dL, + 0x7be3737d524ffefcL,0x9f6928555330455eL,0x524f166ee475ce70L }, + { 0x3fcc69cd6c12f055L,0x4e23b6ffd5b9c0daL,0x49ce6993336bf183L, + 0xf87d6d854a54504aL,0x25eb5df1b3c2677aL,0xac37986f55b164c9L } }, + /* 18 << 0 */ + { { 0x5dfee73ce5b82700L,0x198fd3f0f38f6662L,0x3bd1c8f62edb0dbdL, + 0x55a96a6879909f08L,0x68a2324355671693L,0x57505d8d67497030L }, + { 0x8a60717f75c64513L,0x54b867b7f78aa7deL,0xc266eb8441129858L, + 0x6ffcfc7ca4cfd9bbL,0x9bdd6a092945a757L,0x91700b247eb1be63L } }, + /* 19 << 0 */ + { { 0x82a2ed4abaa84c08L,0x22c4cc5f41a8c912L,0xca109c3b154aad5eL, + 0x23891298fc38538eL,0xb3b6639c539802aeL,0xfa0f1f450390d706L }, + { 0x46b78e5db0dc21d0L,0xa8c72d3cc3da2eacL,0x9170b3786ff2f643L, + 0x3f5a799bb67f30c3L,0x15d1dc778264b672L,0xa1d47b23e9577764L } }, + /* 20 << 0 */ + { { 0xad610a2d94a70ec1L,0xcd96f20591e71d16L,0x713466708cbaffc7L, + 0xf78cff0cd467f03aL,0x98ca8dd42d96c936L,0x1d1cdf7b5f223465L }, + { 0xe27a189460d4db60L,0x25f546ab321828ffL,0x9933fb25dccd4df3L, + 0x422da643ffe6132bL,0x5e01b72b4718bbc7L,0xab9dd81052ebfb01L } }, + /* 21 << 0 */ + { { 0x08265e510422ce2fL,0x88e0d496dd2f9e21L,0x30128aa06177f75dL, + 0x2e59ab62bd9ebe69L,0x1b1a0f6c5df0e537L,0xab16c626dac012b5L }, + { 0x8014214b008c5de7L,0xaa740a9e38f17beaL,0x262ebb498a149098L, + 0xb454111e8527cd59L,0x266ad15aacea5817L,0x21824f411353ccbaL } }, + /* 22 << 0 */ + { { 0x4f595351262bb775L,0x981b788d16f325b8L,0xccd57831927ed783L, + 0xc382472ebe0e1fdbL,0xfd7a8b13f0681fcaL,0xe082882d69059095L }, + { 0x4d1c3049faa71fdcL,0xf9d62fd9c9576c69L,0x7b1ab489cbf837b7L, + 0xc764edf840d0fcf7L,0x50fc847215809cddL,0x671d69c98fcd8418L } }, + /* 23 << 0 */ + { { 0xd1b4e74d12e3683bL,0x990ed20b569b8ef6L,0xb9d3dd25429c0a18L, + 0x1c75b8ab2a351783L,0x61e4ca2b905432f0L,0x80826a69eea8f224L }, + { 0x7fc33a6bec52abadL,0x0bcca3f0a65e4813L,0x7ad8a132a527cebeL, + 0xf0138950eaf22c7eL,0x282d2437566718c1L,0x9dfccb0de2212559L } }, + /* 24 << 0 */ + { { 0x259f272cfab816a7L,0x20c1b8e0d809afcdL,0x540c045a409c930bL, + 0x563361909bd5c2f7L,0x38076e8fca77d74fL,0x4f13f901fc55723fL }, + { 0x890932d7bd3d10c3L,0x98d82ad1da247ec8L,0xdf5579fa4bea82ddL, + 0xe8277439a0f9ad3aL,0x1395a87966a4e904L,0x150808e625a302c9L } }, + /* 25 << 0 */ + { { 0x1e93722758ce3b83L,0xbb280dfa3cb3fb36L,0x57d0f3d2e2be174aL, + 0x9bd51b99208abe1eL,0x3809ab50de248024L,0xc29c6e2ca5bb7331L }, + { 0x9944fd2e61124f05L,0x83ccbc4e9009e391L,0x01628f059424a3ccL, + 0xd6a2f51dea8e4344L,0xda3e1a3d4cebc96eL,0x1fe6fb42e97809dcL } }, + /* 26 << 0 */ + { { 0x6423197d2afd473dL,0xb0391b37897b93f5L,0x6efedb8023bf0b90L, + 0x808497b7b0bba4a7L,0xf14b309f03fa90f2L,0x37a45bdb091cbb80L }, + { 0xedda4ae48a8f5dcbL,0xdb3f422d95e16d6eL,0x25c7b9146f5f24c7L, + 0x5d512df99d42a727L,0xbf2c0862697c08fdL,0x47d98a9df092241cL } }, + /* 27 << 0 */ + { { 0xa04482d2467d66e4L,0xcf1912934d78291dL,0x8e0d4168482396f9L, + 0x7228e2d5d18f14d0L,0x2f7e8d509c6a58feL,0xe8ca780e373e5aecL }, + { 0x42aad1d61b68e9f8L,0x58a6d7f569e2f8f4L,0xd779adfe31da1beaL, + 0x7d26540638c85a85L,0x67e67195d44d3cdfL,0x17820a0bc5134ed7L } }, + /* 28 << 0 */ + { { 0xc76afaa373b64643L,0x4169b4117b3c1220L,0x550e0bee8ff22c6fL, + 0x8fb0c597a4da3e15L,0xd8232f8b4e492aa8L,0x55be5764d37da1a2L }, + { 0xf1bc89b628e77f9eL,0x9ff769c4875fee0fL,0x184bd4733ad6983aL, + 0xc48ee6f3b033c112L,0x792377fbf8eb8319L,0x05cdca3fe7988176L } }, + /* 29 << 0 */ + { { 0x019d6ac5d3021470L,0x25846b66780443d6L,0xce3c15ed55c97647L, + 0x3dc22d490e3feb0fL,0x2065b7cba7df26e4L,0xc8b00ae8187cea1fL }, + { 0x1a5284a0865dded3L,0x293c164920c83de2L,0xab178d26cce851b3L, + 0x8e6db10b404505fbL,0xf6f57e7190c82033L,0x1d2a1c015977f16cL } }, + /* 30 << 0 */ + { { 0x6a7a3464d0cbcea0L,0x76aad8b813126388L,0x519b9fd50a183232L, + 0x15f9abe1feb6b100L,0x7002990485ba4143L,0x92cea8f4c4360dd8L }, + { 0xdc6c5d1dc12748a1L,0x1846eefcdd3eb156L,0x3117dd04d47a41dcL, + 0x96c21b29f6a167f2L,0xf569446a27555692L,0x941292e500f88cb2L } }, + /* 31 << 0 */ + { { 0xa39c89317c8906a4L,0xb6e7ecdd9e821ee6L,0x2ecf8340f0df4fe6L, + 0xd42f7dc953c14965L,0x1afb51a3e3ba8285L,0x6c07c4040a3305d1L }, + { 0xdab83288127fc1daL,0xbc0a699b374c4b08L,0x402a9bab42eb20ddL, + 0xd7dd464f045a7a1cL,0x5b3d0d6d36beecc4L,0x475a3e756398a19dL } }, + /* 32 << 0 */ + { { 0xad852b878c0a64a4L,0x0d784cf208f779d5L,0x1896b9fcc651b1ddL, + 0xba8953d612e8dc87L,0x3a9865baa631cfb0L,0x5dd2a4a0626b3d79L }, + { 0x1148bc72687c20bbL,0xa372dfc2f2a52bfdL,0x77315f9e9448fd08L, + 0x4bcb06f00a2377b6L,0x73b42725b35b4ff0L,0xc510ad93aabca99fL } }, + /* 33 << 0 */ + { { 0x61333a382fb3ba63L,0xdf330d9d5b943c86L,0xbbc7c7ee955ef3afL, + 0xda631fc160f09efbL,0x68af622641d5c400L,0xcc9e97a46c833e9dL }, + { 0x7fd73e8e3a625e76L,0x13bf6124c209e55eL,0x08467cea48b90b91L, + 0x8a416eb9bb6f0abaL,0x6fcc93a1b8c31072L,0xa7fd2b619057dad7L } }, + /* 34 << 0 */ + { { 0x80b309dd2ada5bf4L,0x0648c2cd2d668c41L,0x45700722abb9102fL, + 0x9d6ac102b4e25201L,0x7ec2bc1cd50b3e6dL,0xcdb55e6ba07b7caeL }, + { 0xebcbda0786da3943L,0x470ddc68f8a57f48L,0x9e1418a4554557c3L, + 0x02d00cfb8a76b2d6L,0x03c050a061520726L,0xa964eefbfdadd24eL } }, + /* 35 << 0 */ + { { 0x58a5b5433720ec9bL,0xbb3800d52d7c2fb4L,0x4a508620dde6bd0aL, + 0x65f16273a02583fdL,0x832bd8e34fc78523L,0xd6149f75e9417bc6L }, + { 0xfeb026e93deeb52aL,0x0ce18088a55e0956L,0x50018998988092a2L, + 0x22f19fab28f35eeeL,0xac8a877f52ccd35cL,0xb13a8ad830e23f26L } }, + /* 36 << 0 */ + { { 0xf216aa2531238ed0L,0x4a13260770b1b757L,0xa39180d45c2c7ce1L, + 0x9f82b7fbab52606cL,0x6f01faee26946e78L,0x1608643883061d37L }, + { 0x597edf370fb077bcL,0x1d11bc5ed6e28138L,0x10209418c167fd20L, + 0x6a3258ec33f55675L,0xdf33eed7b73401b1L,0xf699887b806085b7L } }, + /* 37 << 0 */ + { { 0x0202d57de44f61a3L,0x4027704bb5630ef2L,0xa129e2dff5b54a5dL, + 0xacb60a7597482b86L,0x9261ede87ef27114L,0x1eba28f3defc58b5L }, + { 0x6c91c0c98be5589eL,0x2f1643d514594beeL,0x2ea912435d2ca034L, + 0xb50649a894047d1fL,0x284fcbb5638ca337L,0xfa0e07b7fe85bf85L } }, + /* 38 << 0 */ + { { 0x4703cd85891f8ffeL,0x018843c01c0d7702L,0xf3d752f5ad6cbeacL, + 0x479ecf018173fb32L,0x6b464412bc9a48c7L,0x47ba96091da7b147L }, + { 0x91af26eaabc13488L,0x87c183c3e1a0e06cL,0xdae2479844956b93L, + 0xf300e1c648347f9aL,0x129be314974320a4L,0x1f466694520618f2L } }, + /* 39 << 0 */ + { { 0x7d894f80506e0e42L,0xd984244a8e3d2c46L,0x6d7edf642b7f006fL, + 0x36a1cd6dde9b6230L,0xc9985040b76c0665L,0x587df4d6b89b1fc2L }, + { 0x4c0638476a71ae7aL,0x7b2b0ab3e8294747L,0x345c553ab53153b8L, + 0xb646e453436d9fe2L,0x1a95355f1cd60340L,0x2d7bc128074968fbL } }, + /* 40 << 0 */ + { { 0x6048c6949399c38aL,0x43a53ff21beb359eL,0x86fcfe4760be3ebcL, + 0xae78bc3a3134216cL,0x3b021cf316d7a9adL,0x51c4b1b36a4d6e81L }, + { 0x54b9cd8db593d816L,0x1df8cc84a69ea3a3L,0x98ff87f7370eb744L, + 0x63a00a0a60e0aa2aL,0xdbb22c9ddeb46e6cL,0xdfd92b6da914bb01L } }, + /* 41 << 0 */ + { { 0xad148e87bca6d14cL,0x41dfd24d456a201eL,0x73a82933a80d68f3L, + 0x89746c8d852ca035L,0xe3bc778895fd71aeL,0x8764cd2cda92245dL }, + { 0xa2fe2c4782eb23e2L,0x5ac762e00f3c9d6eL,0x57860ce121646f31L, + 0xbdc9d6c34f9f589aL,0x679952c7d193272eL,0x82ea702eeb18f1c5L } }, + /* 42 << 0 */ + { { 0x18ef56cd5d76b881L,0x31b22efc5df46c66L,0x4b21c4f3eb6c7e62L, + 0x3fd72a308f234c86L,0xe983e169ffff96c7L,0x7438b4933c1e593cL }, + { 0x863a23a3a553e8e3L,0x0d959ba9796d9129L,0x25d0caaeda1eadf4L, + 0xe739fb61eaa67763L,0x50029568472a7175L,0xdb6829c2f002bb6eL } }, + /* 43 << 0 */ + { { 0x37fa935500846d44L,0x09112fc50578bc8cL,0xdad9f5b239c4943dL, + 0x7314f5f0416dbd86L,0x5cf095a901fefb56L,0x35178bad22dab393L }, + { 0xcf79fc1b36baf1a7L,0x1b7ee42d749e5498L,0xbce78aa9ede314bbL, + 0xaaf8e0f6bd0628dfL,0xa974b09415cbf948L,0x8f3f1f63c9632b78L } }, + /* 44 << 0 */ + { { 0x1c5f0e5b36a400d3L,0xae97af8bf240b30aL,0x767b4ad7f8f99b51L, + 0xd50a288981ea36c2L,0x04ce2a21986c5ce6L,0x9c7e7754a320d352L }, + { 0xc3336331bbad8346L,0x7cc82a4df1698fb2L,0xc680176505c7ad6cL, + 0x47678afb27dda8e5L,0xade6096d02e543aeL,0x5fb28e322a1dd73bL } }, + /* 45 << 0 */ + { { 0xd4c411564fddda5bL,0xd4af65c673ad9112L,0xffe8e0bb39eb8f59L, + 0xb0040c0e8d6fcf13L,0x99e1c0c61f2bb599L,0x9c94c858b2ac3405L }, + { 0x8f8878d76eeed85dL,0x62b2f54351fcca3fL,0xeb3b44a9e5b56918L, + 0x16f96676b7234e93L,0x17477722bd2af19eL,0x42eb2979db83a485L } }, + /* 46 << 0 */ + { { 0xa618d7479fc4f435L,0x9f24fba649ddd10eL,0x60976b01b472d789L, + 0x9266634957719f54L,0xd9c79db800541257L,0x374aa9069481ed0dL }, + { 0x60efb1147fdc2d7aL,0xa1590c30ecf58643L,0xd7a198a4185a849cL, + 0x19ab802314eb4ab9L,0xc82d5998ec090d06L,0xfc539eb3e259c7dbL } }, + /* 47 << 0 */ + { { 0x6f888f7df0c668caL,0x65c788785f0dc66cL,0xbfb185125f5b07a0L, + 0x780abff7d878acd0L,0x504f21b1570cf950L,0xea5b37c5da233371L }, + { 0x487ae8bd22437ed1L,0x9c701758249cf9b7L,0xf86562a898fb34ffL, + 0xdfeea1a265e0fc91L,0xeef006912e20fc23L,0xac9dfec7dfa72a8bL } }, + /* 48 << 0 */ + { { 0x3ccf806ab35bf6cfL,0x2d368d48e7f30c2bL,0x4f504e06ea52bef9L, + 0x40d01ff53a7d2f3cL,0x62e5c5d3e73a1bc9L,0x66e4794bae7d7400L }, + { 0x3d30625e5ffef312L,0x4580609da766ddf1L,0x5c3ca10d04bab985L, + 0x2605ca009da2a2caL,0x48eab00eb5c9462cL,0x271e42a12624a583L } }, + /* 49 << 0 */ + { { 0xfa5c3aef697136c6L,0x8ea5af63a5ea6fb8L,0xa669156542e365a4L, + 0x47c56c115b6e3386L,0x1197832bcea03f56L,0x0b470bb250e4ea9eL }, + { 0x3113c74313b25712L,0x8d6c174ed2497d48L,0xfc4486ee49c9ebe8L, + 0x2487edd57f82bdd3L,0x771e64415b57be2fL,0x2d1cc518e28b2bdbL } }, + /* 50 << 0 */ + { { 0xa96763d2fba32d1fL,0x172cfe4ecb5af900L,0x510bd675cb2ec3f1L, + 0xbeabb91ac3c90051L,0x9cbf755b46f97ac7L,0xa820e8303a5d50d1L }, + { 0x83a9f17e308c4545L,0xdf7dc7053048461aL,0x6124642f0f32b151L, + 0xc1b444139333e405L,0x6f7bfa7e13a4f7d6L,0x6f58fa8b7181c2a1L } }, + /* 51 << 0 */ + { { 0x2c4ccac72070ac8dL,0x1947c0caec4a22b8L,0xa5e0fb598c5a78d9L, + 0x464ae8d241a84de7L,0x3dba16e9daaabc27L,0x16634a504f35cb3cL }, + { 0xadc18bf9b16ec84fL,0x324d067e7359dd35L,0xdaeac0c3570543f0L, + 0x0b2240003c887d36L,0xc69489e2373f1a0dL,0x518b047dcbaa0d97L } }, + /* 52 << 0 */ + { { 0x8f6468656f9201b9L,0x8a944b316b326232L,0x5687d1dca6ccfd35L, + 0x0bedaa85e5377c00L,0x252b48f5cd8d7d77L,0x4b820d9b31d83660L }, + { 0xa9e5af3ccae07f15L,0x0a8930fc1208b9faL,0x6d0a166ced3c3b7aL, + 0x90e2aead7f78aaf8L,0x222465866e5ede76L,0xc5cc339dcba1fd4bL } }, + /* 53 << 0 */ + { { 0x3b1bddc6fbde49efL,0xdaed7c268a0915ccL,0x0b0110610f0422a2L, + 0xcf485c74a7c54b16L,0x642ec4e615c3aae2L,0xa8ba8f10e0f383eaL }, + { 0x2a2054b495618501L,0xebec6442089efa8bL,0x5786a19a4e2fa83eL, + 0xd2c71ad139069963L,0xadc93d9a481765e2L,0xedf2e3eb7ecc9485L } }, + /* 54 << 0 */ + { { 0x11853add834e6c54L,0xab2f15202175fbf4L,0xcff00bd23c9b5a41L, + 0x075134ebabd64a6aL,0x48c075daaadd6150L,0x4576a6497cb89442L }, + { 0x340a767034adeda3L,0x8dbb571c77fcd1f4L,0x0bf879d693b44ea6L, + 0x1ae1dd97d13444bbL,0x6e9e86bb7b1eb77aL,0x420eb673906a2949L } }, + /* 55 << 0 */ + { { 0xbcab5f60069f3367L,0xfd6622bc1718ec3cL,0xa4fb7867e3a142d6L, + 0x6078d8bf085faeb3L,0xfa5cbfda60f4554fL,0xb3fcd5d1690cd408L }, + { 0x4ebdee7d281f7884L,0x82af23aa180a63a7L,0x8de3107c3d079f61L, + 0x17c6b5cbbe2334f8L,0x6a91e73997d0fa06L,0x7460257314ceeed4L } }, + /* 56 << 0 */ + { { 0x483350a5ebb8cdadL,0xd4215b4fc7a8baa1L,0x8b6fc785e692fdd2L, + 0x2629ba4fd1deca25L,0xe9981ea6820da79fL,0x7772a913e6436cc1L }, + { 0xd141235c553fb41dL,0x28179e6cc852f64bL,0xb623a1aeeb8cc21cL, + 0x05826192490bb572L,0x56fefff326f349ceL,0x31ff648e0f88b82dL } }, + /* 57 << 0 */ + { { 0xb14ba61cf97f865cL,0x73bae4c1694b8b0dL,0xa14967dfac4bbf62L, + 0x1e9dd1509bf446e0L,0xc052f3eb1c99ceefL,0x814d7fa07a78c189L }, + { 0xa101a483ab74b05dL,0x7788c258a1737b65L,0x0d60bab7e809a13cL, + 0x8f427bc473c81d5bL,0xd2e130552952c1fcL,0x0a823b9a4b26df63L } }, + /* 58 << 0 */ + { { 0x941c5c257d0be180L,0x341cf9d9c46785afL,0xdab9dc0015b0fa13L, + 0xa58db4ea4f96af4fL,0x9e9520bf57acc87aL,0x104cec0666ac72e0L }, + { 0x9f3f7baa1929e675L,0xb8b4ac9ffa80380aL,0xb5f157aa569b57d8L, + 0xe11699e909fa58a1L,0xc08595e35548fbeaL,0x2b51995f794da901L } }, + /* 59 << 0 */ + { { 0xaf467ce227bf64c9L,0xdfca6897f929974cL,0x64473b595c322738L, + 0x96a917cf1ed0e315L,0x3703435b0de64db9L,0x9ba039679267b646L }, + { 0xdf0c2aae3a522fbeL,0x41bdb741b335eff0L,0xaccf2edd7b059703L, + 0x6fb34b3028463cceL,0x96d9ba0bd9e3ca19L,0xff336f12504655c1L } }, + /* 60 << 0 */ + { { 0xc711d5d1c425543eL,0xa61fada6fb4f60e8L,0x0402d5c4eb809f85L, + 0x84b7c2fed74cccd4L,0x61bba736a55b5277L,0x95bb80cece47968cL }, + { 0x09f92adc16eb7b95L,0xf0e0f4f7e682aa29L,0xacd70b86ad2a20fcL, + 0xbb45a51f948a8375L,0x29fc3b284892e676L,0x8dd21bf0b4ea4f51L } }, + /* 61 << 0 */ + { { 0x48da1fd3fc60a6e0L,0x54fb5a34222241e8L,0x6035e34f772ae080L, + 0x5ff77ff2332982d0L,0x2366467300fe51fdL,0xc93ea049ef6ba006L }, + { 0x6640f1177d381266L,0x394d32cd6ae9f4acL,0xe6a7885370d303ebL, + 0x0dda19ffe5275767L,0xb0a6c77201466d23L,0xc4cc11451fc69829L } }, + /* 62 << 0 */ + { { 0x49a04dc0f5acf772L,0x1e659730c1fb476eL,0x0c7d749907dbb9afL, + 0x03b9f1cebfec21daL,0xd194b7054b14d117L,0xcb4c0a54561fedf2L }, + { 0xaf623d3f21da4d42L,0x5f5e9b1fd630c145L,0x65609e59d9ff0abaL, + 0x3d2508922ba9239bL,0xcac324ec82c4faa7L,0x0902cc23149446b8L } }, + /* 63 << 0 */ + { { 0xc5c0e6d7aaed89c0L,0x6ce8ead6149a1896L,0x7a50f7458c949f8fL, + 0xcd7e35f76e2b71aaL,0xf6159e519a049f7aL,0x1c9bf0b0f1e52d1eL }, + { 0x3bb6c1f518202c80L,0x8d3a5f621ecd7b1aL,0x3bb034e888d17f19L, + 0xdc89bd4997d4048dL,0xf5af7b8e3735df22L,0x52bb3712a0a689e8L } }, + /* 64 << 0 */ + { { 0xed4de4f88e89b258L,0x957c980f297a9a37L,0xe04b3d30f8a0580dL, + 0xa309199dca57b7bdL,0xfc8e87cf3be44d56L,0x4f5d5ab6d1b30e5cL }, + { 0xb213c6a030a9325bL,0x0fd1c52df091bc01L,0xfe51bbbf1090fedeL, + 0x6d97cabc301fe259L,0x3ee127895ecd3fe8L,0x888b708b9404ca51L } }, + /* 0 << 7 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 7 */ + { { 0xe484fd9f8258030fL,0x0f4fa5eff21af80aL,0xc0dd449e7c1c3984L, + 0xf313389118eb5195L,0x0336aab8777a16d2L,0xa6661cc4c241720aL }, + { 0x678db970a7efacd0L,0x228968656461e382L,0x5d85a0e4a022c7a4L, + 0xb01f1e0434a02a6bL,0x2657eedda5791ce3L,0x239dcab2a277ac5bL } }, + /* 2 << 7 */ + { { 0x9a7a5b426ae54da1L,0xcfcadaab7040b022L,0x7539438e3d9f0e61L, + 0x013c6719e328c2e2L,0x7f4a706ccccbf891L,0xa335ab82735a2d28L }, + { 0x46694ef03d984124L,0x0e0bdfabc166b337L,0x9d54ed8b423d47e4L, + 0x8075a8cbf44c9180L,0xd4f5b184abe9b384L,0x424dd00b41abdc75L } }, + /* 3 << 7 */ + { { 0x99a710b1400f1d87L,0xec3ca386ee47be8bL,0x3a00dcad37168feeL, + 0x1a69d6741765a0dfL,0x85233afe917c4909L,0xa3aa97a4e9bd6210L }, + { 0x01010526310885f3L,0x21c5de3fb5007b08L,0x5df0c6efee8ddabdL, + 0x5d17d45a0f6dfdefL,0xb73d831a251c9f79L,0x397779e6cb1df19dL } }, + /* 4 << 7 */ + { { 0x5e2cb07fd7801edfL,0xf9fa2c0b3adc065aL,0xa296c53fd4de1f25L, + 0xd408060c838f7169L,0x68e19d7b2e8a6ce7L,0x2cc6e06c94b58671L }, + { 0x93d02a07c1cb6151L,0xa10fb4cf35003126L,0x6aa069f51aa3bc4eL, + 0x0e44fbf0dd09b142L,0xe264f343832e5945L,0x5dca2adc1fc166acL } }, + /* 5 << 7 */ + { { 0x5f63e391d7afb4c6L,0x85208bcd2bcb4a76L,0x10022d53c3da8fd7L, + 0x607538c007e50047L,0xdbdb0e7212793242L,0x8e6b9f6135eb668fL }, + { 0xbe5632887e1da455L,0x5e73e1a06e544e82L,0x0c28a5d29a2da4deL, + 0x62b30a8822326300L,0x470764f16013086eL,0xcbe2c34cd3ef5fbbL } }, + /* 6 << 7 */ + { { 0x9ee4f522b0f6c604L,0x5b8a689d52736e58L,0x0d5f396db7edb07cL, + 0x09b3457c2e829063L,0xf1d28188f83495daL,0xba2511e6cce559b8L }, + { 0x17cbaf57d8f90669L,0x3ba19a1c514eacf0L,0x298208995145b8fdL, + 0x92cb5da81a33b1a7L,0xca49fe334c5149e9L,0x5c499b661772b4c0L } }, + /* 7 << 7 */ + { { 0xb98266b132508180L,0xf5008b926719d49dL,0x50c513f98069ffe6L, + 0x99ceb828a7c6f38eL,0x375b8a8225e2a436L,0xb8197f6c416c073dL }, + { 0x01663a25eadf09ddL,0xfa2ca1571d7ff230L,0xf3b65b2545284aa4L, + 0x144dbefe648bd565L,0x6095ed8ab4c24e35L,0xe1f1fa3696ff2020L } }, + /* 8 << 7 */ + { { 0x56ad7582a0eb176aL,0x085b5a366e19aa00L,0x85f2c6ffe2c8b036L, + 0x55c6d357fcd7336bL,0xb1ecc56d22a46acdL,0x8e0f976736277ac7L }, + { 0xa4ed11e901878921L,0xd38355667f4fb650L,0x5fdaba45266158aaL, + 0x6f0b27fd89e0dff0L,0x32ef7ae2eb6b02d0L,0x2f145871cc1b46e1L } }, + /* 9 << 7 */ + { { 0xc7698dfd4b449cfeL,0x78aacb7bd1517720L,0xaf0f6ef574cd5f32L, + 0x026f1826f17954e3L,0x33ef67ab2453185bL,0x82f0fcc90a420c0fL }, + { 0x5b444b3645f154b1L,0xb27c4ece70d17f90L,0x6417e0d039282194L, + 0xebfb5fa001aa4f4fL,0x9cc5d0b573932754L,0xe8b56699704ffd85L } }, + /* 10 << 7 */ + { { 0xc112733b9d4075dcL,0x349281c187737549L,0xbb7d8e0181009785L, + 0x7640a3e2bfe16c4fL,0x4e34813ec1d9f810L,0x61985fbc8d2605d7L }, + { 0x2a544cd8e3f66442L,0x48879af56a7c9e94L,0x9e6157bacec18a7eL, + 0xa555fc9511b882d6L,0x4305a4dd04f86563L,0xc58ed7631d0fd96eL } }, + /* 11 << 7 */ + { { 0xaaeec0f9b726e2edL,0x243ba6614493d146L,0xd799c3408980a9fbL, + 0x886e4f44ed060f57L,0x52126b82c1f83f6eL,0x8b4978441df301ceL }, + { 0xeb2a98abcdc4e434L,0x87dec119474e2c77L,0xcbbc613092eb1528L, + 0xb0b0bcf7c454f37eL,0x404d97a7e1a919d3L,0x26d1baa825e62c30L } }, + /* 12 << 7 */ + { { 0xf04145e82d2696b3L,0xaffb66acf4fb2928L,0x9ffcba4e12aa299fL, + 0xcc5ec24991b3b517L,0x9edcd4616f81c747L,0x0a96090a77a883ebL }, + { 0x9b0bab58a2aa4badL,0x76359a5e8f9b84e7L,0xfe8cd81e438a9d43L, + 0xf40e2b5e25ca8b3cL,0x4254030067bc720cL,0x883002a46b2446a3L } }, + /* 13 << 7 */ + { { 0x4b43bd3206c3aa7bL,0x83ca2db60a470b08L,0x07c1036c06f22f37L, + 0x312e04d7bbb46ed2L,0x6a1d70a40193e5f6L,0xc69720e8ba8a3f38L }, + { 0x2c003429468a04b1L,0x885c43bfbc83fe25L,0x65a65259393e00e8L, + 0x7154c7ac2af17741L,0x682224d331dda744L,0x6183dd8bc80b57f5L } }, + /* 14 << 7 */ + { { 0x80e1cd16c496089aL,0x7a59f4c06ec2000fL,0x67a019d509ddce06L, + 0x52573e3e70c4b032L,0x16d253e14d3ba57eL,0xa43c6d42162504f7L }, + { 0xa237bbf952ff95e4L,0x81187e659acb7273L,0x4b13531a1f384daeL, + 0x39067f3398125165L,0xe98fb141672dccc1L,0x594baca0a75e27b5L } }, + /* 15 << 7 */ + { { 0x85e12293c205465bL,0x57bbcfb1b71cbe44L,0x201ed45c1bc85881L, + 0xccbc39d5ccbe7dacL,0xc509b77f9277f310L,0x171b603aca1b70efL }, + { 0x9b99605504d2dbbeL,0x986d6323451c918dL,0x75ad922f63c6fb03L, + 0x69e2cca49630182fL,0x1389a2b7f7b34d1fL,0xa66a80323d4f7c7fL } }, + /* 16 << 7 */ + { { 0xe65245cef6e9f82cL,0x9e234dfff6da7b5aL,0x5677c121bad2c806L, + 0xc52dec32060fcf24L,0x78d070675d78cccaL,0x630002ea1bc8b6fbL }, + { 0xc5cb86beeb2e99aeL,0xf13981e78551d16fL,0xfbb7cdf2c92a70d7L, + 0x5a9ff1f1f53cd2a1L,0xfdbe6b7a984f1139L,0x4403d046a470a9f1L } }, + /* 17 << 7 */ + { { 0xdf8c9325efcc63faL,0xe0d35cd966563147L,0x140b9a8bc144d7b9L, + 0x492bfbd70c17c75fL,0x3cbc2b644c5c4d8bL,0xfecfaf47ff8a3328L }, + { 0xaf341aa179b8c3d5L,0x5e72713ff04f29e6L,0x652219fb9f5b6fb6L, + 0x9deeba3f0764460fL,0xb8c2bfa5fa069d0fL,0x5d3e6fefe57be3e2L } }, + /* 18 << 7 */ + { { 0x52c9b94decd84cacL,0x34c2d0ad446dc59bL,0x5563701d951878ceL, + 0x92e2fc1c843c9b1cL,0x2309a5f13dfc7a98L,0xdaf117dc0c57a156L }, + { 0x5739190d359fb843L,0xd433e9bb4b88e3a8L,0x4d6bb0e2c47a1f45L, + 0x511eaa33d7b59627L,0x42ef82c5e389e532L,0x641a0bdcd75f4c08L } }, + /* 19 << 7 */ + { { 0x3ae32dbdc7e30cc3L,0x0c970135af5d0ea3L,0x8fc38e50bd9a0528L, + 0xdb0506791bfa634aL,0xf3514fbd245cb0dcL,0x3a3c8c6982319ddeL }, + { 0x92136baf6426632fL,0xabc3e24aabdd5641L,0x8ccae1429cc004baL, + 0x6c9834d8b3ee0d66L,0xa807ab63e1f7e8d7L,0xb4598e2a220aea7cL } }, + /* 20 << 7 */ + { { 0x19821469d678d1a3L,0xf9fa42e60df2f58dL,0x1177daf49f284ba0L, + 0x6dd2ad3d2a201dafL,0x667b0e383d427075L,0x39b76d1d4212b65aL }, + { 0xc6720ae0bf3612fcL,0x72559d98775f8137L,0x466e8e4476c48a09L, + 0xa05f8eb07fb5428aL,0x7fa1fbce5e36b7d3L,0x13bab84f8d1fdcd1L } }, + /* 21 << 7 */ + { { 0xf1876140ed6f3524L,0x47171ee5cb94b2adL,0x56d836abcb8de844L, + 0x346e80890d3b4271L,0x0110df1fdabf6a02L,0x6850fba1f571cb92L }, + { 0x490cd9af6209f064L,0x41f32d5f1cf5636cL,0x558bb7ddc328f9dcL, + 0x44abd0b9d32e3e4dL,0x2c42a5607fc2ff0eL,0x8b1dc5e12c9931f5L } }, + /* 22 << 7 */ + { { 0x6a35f6efdca1ce69L,0x04216d3184de3658L,0x3c3010df732f31b1L, + 0xe4421a872c1444b8L,0x17c987a3c59c1ccbL,0xd67159dba297df1bL }, + { 0xd13aa7a0bc96041dL,0x686d7b77f44c3d8fL,0x6c2e505f09b2b933L, + 0x8c04eb8256161b34L,0x61785cb4b344bec6L,0x60b4d06cbf8b0b45L } }, + /* 23 << 7 */ + { { 0xe5b055481883c1bcL,0xd5bc37684597b8afL,0xa71ae49adb2fae11L, + 0xc1ac1b3e050327f0L,0xd990b2a668f3cb1aL,0x566e5175b74a3228L }, + { 0x348d382957909fe3L,0xe849dd8dd03c2374L,0x4f31a278150fb5b4L, + 0xbfe265cf168c0798L,0x2737c156ce6a34beL,0x4478d6ae4aa6b73fL } }, + /* 24 << 7 */ + { { 0xb5b16cd48d040c69L,0xfdaba315f95a2dc4L,0xc9fef34961ce4704L, + 0x5fe87a0ddbb53ed6L,0x3f0ccc7973d70f93L,0x4601d1bc46724a1aL }, + { 0x5c4a15ae24f08565L,0x5eda1e8aaa577320L,0xe31ebb35bb32d307L, + 0xcdc6f13bdc770a0eL,0xbe3ae514c434c2f8L,0x57c7fdf63a0ef0d1L } }, + /* 25 << 7 */ + { { 0x85165ea2d71c01a5L,0x3935171c99a29e59L,0x2aa1b5837d326190L, + 0xb1d702f8e79f3959L,0x94100c65c6ddffd0L,0xd1d56d626a9c54c6L }, + { 0x5c93b4cf7ce12b66L,0xfc28574bb32a90caL,0xcd654a96e755969cL, + 0xa06f436cd1bec664L,0x9b27c110ffb6f3e6L,0x529b77d317b476c4L } }, + /* 26 << 7 */ + { { 0x04c3d9e162ccecd4L,0x6050bc1221cb59a1L,0xb33847543cbb7e07L, + 0xef2201ac4cf1be50L,0x99c3dda42d2ac886L,0xad19cb0ab776eff3L }, + { 0xd326dd7f5a3d9036L,0x9fe56af2e5b27667L,0x3d849fc072cea4d1L, + 0x262a0cbcd6aa9e3cL,0x8286211885401b09L,0x8ec71d4b98fe8047L } }, + /* 27 << 7 */ + { { 0x9b769cc43c6b2de7L,0x433d4c26acb13b6dL,0x52878f517530ef4fL, + 0xd0e7ce94b0c5354aL,0x5b094d461d92dbc1L,0x75f681449e4ffb31L }, + { 0xb9b9e97351b9d1e1L,0xc147ba4698661569L,0x2a06f4cb7a239309L, + 0xd5cb5ad420928958L,0xbde0283bd5bdf5c6L,0xb91664a082e43c18L } }, + /* 28 << 7 */ + { { 0x8fc0cfa6e51d078aL,0x431d9dd5744ca779L,0x37a4f3120e96e887L, + 0x9c3624fa03ea5144L,0x47d5ecda0b1127f4L,0x018ad424807cf96dL }, + { 0x58ba530f586b16b9L,0xec7271ed72f47883L,0x8d2918da0281ac88L, + 0x6d0f14ef002330c9L,0x1a90a01591dc35caL,0xeb8e71e9c81607dcL } }, + /* 29 << 7 */ + { { 0x2eab9c5ee6d01fd3L,0xe030e6d23fa77f57L,0xff41311877edc0e9L, + 0x7817766bb47ca351L,0x70c987e36cb15abaL,0xc3c867ace19c5aa4L }, + { 0xc24ec23ea05c3810L,0x3965a165c4f0f350L,0x52af99cf7c0d8e5bL, + 0x2d95d23c106e0b12L,0x27507b297f6d44d3L,0x33da846858b191f9L } }, + /* 30 << 7 */ + { { 0x8e5785629aa664e0L,0xf3a1cfc329a97c9bL,0x91ce3b404037bd09L, + 0x34c447b07f9f2482L,0xebe360164010c2a6L,0x7b8b9b3afdc0a861L }, + { 0x0e60c49199c4ff9fL,0xf1cf53b1053e703bL,0xabeae550dd974a16L, + 0x28ac5a34994ea50eL,0x9384617d27329793L,0xd04db83ddad0aec7L } }, + /* 31 << 7 */ + { { 0xcb0ec2bd4b1537bcL,0xd0de683cbac6569bL,0x0688dbee5c96afb7L, + 0x7c7d192f3324ab6fL,0x1455b1e6165fe655L,0x32d135a1ccfe9e1cL }, + { 0x05a80a2af9e1a86fL,0xdc946c70479c71f1L,0xf8b9ad985aaa0ff3L, + 0x78cf198ef195bbceL,0xadbc082dfcee6b59L,0xe6e1fa844cd19e25L } }, + /* 32 << 7 */ + { { 0xeb06571c0f547ebaL,0xf292c38d6246c0dcL,0xa185966726eed224L, + 0x8d9e56e46100e387L,0x470506b9dc6298d1L,0xb19e084cf3350ad0L }, + { 0x83eb62a812abd898L,0x70f152cc2222342cL,0xb089e880e1bd4a82L, + 0xd4d1e70fcaf3b3fcL,0xd0b1ec6395ffd65cL,0x79f27f3a9b184ebbL } }, + /* 33 << 7 */ + { { 0xb4a7435231a3e816L,0xba8a0af2fd4ada3aL,0x1622289dd8fed2e4L, + 0xb71e579e31d3745cL,0xb090650704a50576L,0xc98b5f20123f900fL }, + { 0x3799ee82d3587b21L,0xafdd6dc79d9abe55L,0x4053ee2aba64b9d7L, + 0xa816246657b3f258L,0xd9b5c4c4690b1169L,0x32c1d3afd091d158L } }, + /* 34 << 7 */ + { { 0xff5a9c58de97d0d7L,0xec086138feede4acL,0x55b14035ebf47cecL, + 0xc0b3e061c619fe18L,0x5644c092ead4ebe9L,0xa1a4f7a41e5e0a61L }, + { 0x8698da06d179219cL,0x86f560bc3f88f732L,0x6ad10b3f1e34a23dL, + 0xd4326bb71307ede6L,0xc93cd2a19b3045adL,0x5a0b733dd8a5160aL } }, + /* 35 << 7 */ + { { 0x68ef87cdeaedf10dL,0x5ce97a07bed10cb6L,0x9b8dbd896ed762c1L, + 0x1a72b05333c1dcd8L,0x6718eff90f97cfa6L,0x02f886e57dda698bL }, + { 0x9db378a8c724f4c7L,0x5b55b8383fa6548aL,0x9935a70ecb24bdf9L, + 0xf5da6936e9de8ae0L,0x3b3a10a79b0c4bcfL,0xe4e6a6e86361c492L } }, + /* 36 << 7 */ + { { 0xb37fc581c634a8f8L,0x06f06c93de1d01acL,0x0f2dac8452fed4ccL, + 0x1673c81bda53f81fL,0x963e500e61e11c94L,0xe86ff87e2144d55fL }, + { 0x343ddf389bbaec76L,0x16a13527806df1edL,0x1361b5ac0a9edd65L, + 0xf20507fe33c0124fL,0xdf64ec1e4e8e0d18L,0x3f6a42e27860a8f2L } }, + /* 37 << 7 */ + { { 0xe6db1c43d38266a7L,0x55bee1a3adec0d4dL,0xe41c403ed56d2f9dL, + 0x5fb703f24d3cd93cL,0x4d7ae8c53d2a7ccaL,0x65c8ac50ffa5fff2L }, + { 0x128814ec264dfa80L,0x08d1372ea642513fL,0xfc5ea1615343a57bL, + 0xc70a6f2f9a2f3f3cL,0xfe61c499df4963f1L,0x2b711eee5cea1508L } }, + /* 38 << 7 */ + { { 0xfc3e9fb252f9a4f3L,0x8bbeeff32180cd36L,0x274312dbd6438c99L, + 0xbd30984a55612a57L,0x344006d609381db3L,0xd9b696f62bcac509L }, + { 0x481e4ea3bef646d0L,0x213033d430561b68L,0xf46bf9a05453f623L, + 0x2af3c4a46d848d97L,0xc35e55a543efa02eL,0x8da254342462874dL } }, + /* 39 << 7 */ + { { 0x1f7fda656a12b927L,0xf628cfac876b9303L,0x1904a0b5d0d0d0b2L, + 0x46d486f6f2894b1dL,0xd35cb5610d243bfeL,0xe759579b851a568eL }, + { 0xb99572e2c1aeda5cL,0x872e16fb1c54cd1eL,0xf5ec9e42a60fdc40L, + 0x59b03a6201a4b019L,0x9c5e7f87e272e064L,0x6240282f24c918a2L } }, + /* 40 << 7 */ + { { 0xc2467f9ab92a9a13L,0x0c3ee8eb6add349aL,0x59250eda45e99644L, + 0x22ce0635c8a2df27L,0xec7b643e312e8698L,0x334ccf2eaebd1587L }, + { 0x0c1c68736bca2900L,0x00beb4c209826cb1L,0x12dbb586cde6b725L, + 0x8d7cee6c66dfed41L,0xc38deba2014de4c8L,0xa3ba6ec76248442dL } }, + /* 41 << 7 */ + { { 0x870be3ebef38abf3L,0x6e0cf541f74dc605L,0x499976bcda4bc168L, + 0x5513c6122548b3b8L,0x5b9a054c3f647360L,0xa47f9f8bde929154L }, + { 0xa2ae9ccbb8ec35b4L,0x934c5c0a4d9857e3L,0xc9dd66cc4b4f01ffL, + 0x42a1afa2e5b5e147L,0xc284e464f3d9b380L,0x67845404e21bbe63L } }, + /* 42 << 7 */ + { { 0x9ec1ed3342ec772dL,0xa77e1ecf5501609bL,0xb059e214a02906f8L, + 0x35b2ebceb28e4d14L,0xb8453ec22cf036eaL,0xe621234b2518fe75L }, + { 0x079d7d11f03cd158L,0x357492f91b2f011aL,0x3c2186da0661992aL, + 0x7adc1c0fe5df978aL,0x88d329db5300cdccL,0xd915c2444c0d644dL } }, + /* 43 << 7 */ + { { 0x1b9797a8f0ff03f6L,0x00dafe43f41c9284L,0x1e565c33f2bdc817L, + 0x63b77ad9784b1a5dL,0x3304540e74aa6079L,0x630524f3d7181d2bL }, + { 0xb4fe5fcca2804658L,0x1e48e50b9e393a6eL,0xb5bccd49397a94a5L, + 0x95394743eef17accL,0x4d67ba5226dd1687L,0x80965c3432349d9fL } }, + /* 44 << 7 */ + { { 0x1d70669e49f1216eL,0x8645472fa5fca474L,0x9242e8ddfc400357L, + 0xe7ac31548623996fL,0x37b9e68ce61aecb5L,0x7d2e10fdb997e4c9L }, + { 0xc0cb59a6c2086dc9L,0xb38e2032d7952172L,0x78eaecf6eebac939L, + 0xece490b42f5dbaaeL,0xdb17501dcdc32565L,0x59bd392ab133bf99L } }, + /* 45 << 7 */ + { { 0x71554fae07de21a7L,0x3dd66b8bcc42db25L,0x9da85c0f0636e9a4L, + 0x61fef273904930d8L,0xcc8f527b73369e81L,0x4207dfab7caeacd8L }, + { 0x99e5d1404fc763d7L,0x5cc6a3739f4e8947L,0x9ef14ec1cde33eaeL, + 0x25eb3aa8095872d2L,0x0db8268d7d9e6dd9L,0x38846510c2ccfe92L } }, + /* 46 << 7 */ + { { 0xce6197e822d0a502L,0x69df7f8e09d45970L,0x0274f48b7eb4718dL, + 0x47461334a8c22b75L,0x89cebf17bf25b9abL,0x57c042f6fdfea412L }, + { 0xb19c338644346b96L,0xdba17de06ba014c4L,0x6697687a5f844d69L, + 0xf16dee4c1a66c6faL,0x7f916e47fdafd0d7L,0x1c3842d2340f158cL } }, + /* 47 << 7 */ + { { 0x417c9ab760efab2aL,0x1745d5c2f0065f75L,0x1a7d86f2ed71b350L, + 0x6d4d504feee5c850L,0x4ae7ee0da657b859L,0x1f72ded53c302a3fL }, + { 0x08779fdae7b22e51L,0xb04c1c0446d90bfdL,0x4dc97219712f96d0L, + 0xb15e8c0041a6be82L,0x384a02cca3804090L,0xcea45861babd1ee5L } }, + /* 48 << 7 */ + { { 0x3c686079d42aeb95L,0xc162e5e985e3ea0fL,0x34cf58611bbb2455L, + 0x7650de1d8773b064L,0x3b7562c6d2bab35dL,0x83191b4433d0741bL }, + { 0x4b604db03a6bd9cfL,0x87cd84db074aed21L,0x02a042d2d4f91f9cL, + 0x5a5d52e5e42c2a67L,0x31291acd1d5f216aL,0x9c3971bccd6203c8L } }, + /* 49 << 7 */ + { { 0xec931d6599e9ec3fL,0xe9d780c64bd554d9L,0xa580534502eca45cL, + 0x84701f1ac1276ca3L,0xcb7ba786d5f9438bL,0xf3a27508c85f663aL }, + { 0x044df512118c9421L,0x1109fd431039871bL,0x7865443de2378386L, + 0x7a5e2d49e70297abL,0x112763ca6824d2b3L,0x8a05f2c90e84bba5L } }, + /* 50 << 7 */ + { { 0xde3bfdebff044924L,0xd7f2a5181a0458f9L,0xc03df0c00139d557L, + 0x7a958c60cd3ad0d4L,0xec9f2f9759a43584L,0x5e0fbba950d8b4b6L }, + { 0x5fbc5e3888245837L,0x17235805a267a54aL,0xdc24a508db55d65bL, + 0x431e4d5623c704d1L,0xb1f85b2277585f9cL,0xb288f25ed0b1c374L } }, + /* 51 << 7 */ + { { 0xd8fd5b405a37c029L,0x5c9d827fe4d37effL,0xe024d7952e046275L, + 0x0661277f913c55c6L,0x21ee10eb904b3679L,0x32c582e066778adfL }, + { 0xc353ab1fba8d17daL,0x1d4ab06b5658ea17L,0xb908cb88a2d70bb4L, + 0xfc215909a98daaebL,0x7aea6c8777000e24L,0x19e0acbe38446e20L } }, + /* 52 << 7 */ + { { 0x1bc3803e2f98532bL,0x39d0c3258754d142L,0xa7b035c5d739eaefL, + 0xd36ddeb8fbfdea2dL,0x7df72a94bdf64f2aL,0xab4ad6b880bc3c47L }, + { 0xdf386df3877fa482L,0x4b94260470519bc3L,0xa3399d91d20e1e04L, + 0x7f5208b797cf58ccL,0x528f6a2814424c00L,0x83d74730bd900d10L } }, + /* 53 << 7 */ + { { 0x501c657f34ded7f1L,0x9071027e12fa53bbL,0x395e16aedff079ccL, + 0xea95dc84770ac4b2L,0x4d2aa60a41355974L,0xe04effa507f12473L }, + { 0x38ca98385cd1c738L,0x3c067a0b683c0dbaL,0x55ad2dec67589842L, + 0xe51550f7dfdae3c8L,0x21a56717214d51aeL,0x75b6a4a012a0fdcdL } }, + /* 54 << 7 */ + { { 0xd63605266a4ea95bL,0x180f72d403e67090L,0x7faf4529751c8c9fL, + 0x1ab7b50d00e4252aL,0xc0e69adf34811274L,0x5c4c83495e99c6ccL }, + { 0xcc9467f29a9e02a9L,0x5402c2da5c4fc719L,0x1dff8c5d3f6d5bddL, + 0x88a7d27a2c653c3cL,0x067f31183a050dc7L,0xca0f7dafc4f0236eL } }, + /* 55 << 7 */ + { { 0xa09306e9ca177c3bL,0xea84f03ed0552a4dL,0x7ae9024f3c00d359L, + 0xe189ebc33aa619faL,0x4adeefac8354579bL,0x90168ef9699db1ebL }, + { 0x75319141ad87490aL,0x7b48fe7629c1bf84L,0x00ae82c7a2235f2aL, + 0x6292c9cf68562b59L,0x0b6500943935ca20L,0x39f22cb027f33addL } }, + /* 56 << 7 */ + { { 0x92e4c851aa1ef488L,0x4f91fc22846528a9L,0xaa2f5d2d5dc13a84L, + 0xba06aa68f1072d4dL,0xf4f3b17c5e3a2ba9L,0xff36a5355e4dde77L }, + { 0xe8ef143aae17dddcL,0xcc82631ba1fcd4ecL,0x97db807ec7d3963bL, + 0xe4aff04521d85ce2L,0x2d6480e674667392L,0xc8ce97f3a55d0b3fL } }, + /* 57 << 7 */ + { { 0x1a32b8457962a675L,0xd78efd71723d217dL,0x9b03d6573b41a2c5L, + 0x1116f33589a380b1L,0x2c0359af931ee15bL,0x8a53744f239ba4c4L }, + { 0x4801397dc78cdc83L,0xc43b9f0434ae4453L,0x9cc8f6cec356a35bL, + 0xd5a74c2a648b39e6L,0xa54d668c0d5e78fbL,0x36257047cfcb8f6aL } }, + /* 58 << 7 */ + { { 0xabeef3461549c215L,0xfec59db2ce4aee45L,0xa1743a0f5305df83L, + 0x9d598abdf211bacfL,0xd14609dd52a513fdL,0xd3dc446be00d4ad0L }, + { 0xbd8883e9b272211aL,0xe991e57757879fd6L,0x5a093d372b732171L, + 0xdd901071f55f18dbL,0x87f04c0034fecfd1L,0x2c07df27c94f6a5bL } }, + /* 59 << 7 */ + { { 0x518e3ced1c17df0cL,0xf8971149ff5dbc4eL,0x5fec8bfe0ac9d27cL, + 0x41d68852489eed7dL,0xf48ef4bf3c3c4725L,0x3b8d9eee7681eceaL }, + { 0x7743ededdaae4bdcL,0xb9665ef5d1bcf697L,0x9d77f535471bb958L, + 0xb5db5b96d752b2ddL,0x2cd3c919c368982dL,0xf8297660e9cff6d7L } }, + /* 60 << 7 */ + { { 0x39e7da1028946a2eL,0x4e628a96c3a76f7cL,0x43b8b808e9f6000aL, + 0x86cbd25ca48bbb79L,0x5ce825e273092951L,0x43a6031df0cbee32L }, + { 0x6d685a594923485dL,0x8d4483ed81a17f47L,0xf61d329bbc379719L, + 0x9deef7d0f6596ee8L,0x0314a572541b1222L,0xe2b34d387ea7d376L } }, + /* 61 << 7 */ + { { 0x05ff6faa31f43d37L,0xfb83f23211b801f6L,0x238792d519b223a4L, + 0x28edadcce004f601L,0xf77747b3bdeb7597L,0x2178dbe21e6575d4L }, + { 0xd48ec49842870ba2L,0x7733661d15dca6dfL,0x08212e2f83393416L, + 0xffa1bfe2614c545cL,0xfaf4ab8494254145L,0xd8f9eb48000d250cL } }, + /* 62 << 7 */ + { { 0x9ff4f289a66132a2L,0xc54fb8001e098994L,0x09d3cd6624cc2471L, + 0x6d0f74167838e14bL,0x7438cd2dc540cbdaL,0x193b16817d6fa8b4L }, + { 0x487a7dedab33c6f3L,0x625eb8cf02f5aa09L,0xd8039682501323bdL, + 0x9de122e38e216951L,0x40a8fbde0711c51aL,0xf192b5c283a474c3L } }, + /* 63 << 7 */ + { { 0x3782cbda57e04e9cL,0xec639886e41b30dfL,0x4cd14afd12d2f686L, + 0x0aa093ee8b768113L,0x6cfc12cdad598f9dL,0xe4a62f1194bcce0fL }, + { 0xd5035fab150ad4f2L,0xb3cd4871ae2e8da4L,0x49c9e78271ad9c3dL, + 0xdcafeb34825690cdL,0xc05fb7a38c246f85L,0xefe16be3a82cc013L } }, + /* 64 << 7 */ + { { 0xd42777314c14ee0eL,0xda8146d15e881c3fL,0x6b0746b099f1867cL, + 0x1ec73d72602dd4ccL,0x27fae51538081120L,0x6a677bdc2f8b2f2dL }, + { 0xb924af64d60544e9L,0x1439e183dcfc6b16L,0x4e88e9ae068565acL, + 0x8a3dbd25a9a4f146L,0xdb4a3e483f93f734L,0xb1971c058f1d33bcL } }, + /* 0 << 14 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 14 */ + { { 0x721bb8363a7f43c3L,0xab5b3108c12dca0fL,0x9cc9a78934853870L, + 0x78b604a7af598c4fL,0xd370375e476f27c8L,0x9f0415b80b15cba5L }, + { 0x2bcfd9a4d400dc1fL,0x2a6fe03b4bc62dddL,0xb05a6464a211b19fL, + 0xce059d419990b504L,0x011c5f87d94951d3L,0x13cec08900d9c7b0L } }, + /* 2 << 14 */ + { { 0xf365419f9b280fd9L,0x13e3b12746365672L,0x8a91c165c41880aaL, + 0x3eb27a97f9712fbdL,0xa6587aec76c55678L,0x7c3a04b702cd79cfL }, + { 0xfc878f9cda712eb8L,0x076e61170fca3e02L,0x09a184d8caf6df5eL, + 0xd32bf232aabcde75L,0xf601d0de03de597aL,0x85d2b5fcc5da2858L } }, + /* 3 << 14 */ + { { 0x3075a7636c888df8L,0x6305c20472e21527L,0x6b1d683e8798aad9L, + 0x0d09624680706369L,0x91db5e7f7b854739L,0x0e63cc6e02d72332L }, + { 0xe929e3ea1f7ff6ccL,0xd53a18a145595925L,0x867916cb93af8be1L, + 0x757e9f56c5c305eeL,0x3f9071c75c83063cL,0xccc0f92d7f6d5bb7L } }, + /* 4 << 14 */ + { { 0xb6029961ae899afaL,0x8eedd66e681b6e1bL,0x82db693b4df3e5b1L, + 0xb5131488a0c3e357L,0xbfb01ff3ccb2f577L,0x28ea947027a72cc3L }, + { 0x26170928e39e325eL,0x42d4876b84f80188L,0x0bec6a634c872d76L, + 0xa0a7cc90b14d9c9fL,0x8a32d2c44f6c7778L,0xe7cd346e3b889a4cL } }, + /* 5 << 14 */ + { { 0xab35a14f5a4a3753L,0x1d0d5a142bbbd563L,0x54cfffc5998d4514L, + 0x1c02f381a77ed59bL,0xe4a7a6ab21c9c190L,0x50059df54a9adb60L }, + { 0x2d0383ba34bd7008L,0x894889bedf1a4f41L,0xe541c62612ac407dL, + 0xcc0e417964c3b62bL,0xdb8ca1f33a0978b2L,0x4ef45a2d287e8c6cL } }, + /* 6 << 14 */ + { { 0xea95b5c9437f2efbL,0x67d3e9b58e52ce8eL,0xfb33102488ff5455L, + 0x883ec9fcc3101dedL,0x056218e20ca5f1f9L,0x4c9b2483bccc65d8L }, + { 0x13199b26123db2ecL,0xbc1d82479aff90dbL,0xc4a9311d367516f6L, + 0x3b40c867cb6e90d6L,0xff674ff84034415cL,0x2787db45a1821e7eL } }, + /* 7 << 14 */ + { { 0xacc263fcadeb8508L,0xb52ebcd719854c90L,0x3d54e7805f2ce0aaL, + 0x2fc056a97e02e760L,0x47e7173e32da5f93L,0x1d468de3fa893134L }, + { 0x9adc877dd73396b5L,0x430826afeeb00c82L,0xfde2c3da96a673caL, + 0x467575ad33e43f9cL,0xc3b2c3a1ec1df2f0L,0xf0348e6f2252a8a6L } }, + /* 8 << 14 */ + { { 0x860ef794609683acL,0xf0631ad39af1c522L,0x322c83662ee7f522L, + 0x58ccd95f54122af0L,0x7454880c2bbb2d80L,0xea173d8286d8d577L }, + { 0xd5a3057cea1cc801L,0xfd08d482bbb2a189L,0x26aac99ec3c512f8L, + 0xc3eac036556d891eL,0x866c3aa7bf9f6112L,0x7c4c8fb9c144f7e9L } }, + /* 9 << 14 */ + { { 0x989eef73a9109d83L,0xbe43bd378edd17dfL,0x14a63abd1b17029bL, + 0xfd14ae365ff76860L,0x689dd0a6b8730632L,0x01eb37f147342f9aL }, + { 0x619bab45e6c446a3L,0x93d26fc97abddba4L,0xda6c120486ffa4cdL, + 0xc608937548758279L,0xaf074ea3034a7230L,0xf220244b82ce176dL } }, + /* 10 << 14 */ + { { 0xc0c1eb0f8343f5ddL,0xa205e66a0126fa2dL,0x37530a3244fd8be4L, + 0x3c7af6f696ab64cfL,0x1f04305076657202L,0x2c59d31c828f3fb1L }, + { 0xa61cba51e7f5926eL,0xb2de427391ebeb81L,0x976f2c34bb855476L, + 0x0c6c02c3269e4f86L,0xc69bed8fe2e01fffL,0x19aa421c480bf7b4L } }, + /* 11 << 14 */ + { { 0xb32e8e229affa929L,0x69ebb533bb7db327L,0x10ac3360a8a8d088L, + 0x066cffa7c485517fL,0x2393e74c12b8eebaL,0xb3a8825a596c8412L }, + { 0xe2b99fc3bc8b6b92L,0xd7716da085ca802dL,0x92f6693f4de5101fL, + 0xe8b0442304be34eaL,0x05b44ef648324966L,0xa89d9499413df57fL } }, + /* 12 << 14 */ + { { 0xad0d24c7b617206bL,0xb8be483f9dd13f59L,0xa55134ff7655aa29L, + 0xa3d103857a5e217eL,0xfbb9eeb53a21b295L,0x1de71555c84a136dL }, + { 0x7579398e0b7487b3L,0xc6ca9575a14dce87L,0x99b32e1e46452257L, + 0x99d54955479d8f2cL,0xc2a8a6a1930b80efL,0x58d9db81656c850bL } }, + /* 13 << 14 */ + { { 0x0c8fe2e04d89b43aL,0xe4d923e77a04e492L,0x49ecb701617df01cL, + 0x6d80f249bff9a819L,0xf01e604acb7f86c1L,0xd6d3a6664b7f1455L }, + { 0x657801c19188fb17L,0x339d79450dc92875L,0xca798cf57ec0b757L, + 0xc0808852a62301c2L,0x2dda13558266c908L,0x22bcde8f5e55da21L } }, + /* 14 << 14 */ + { { 0x6c85a0eda682508cL,0x8350b515edcce6c8L,0xa84a67656f95898dL, + 0x55b0ae971e419847L,0x11115c6edd6a885dL,0x6f0beaf64fb174a4L }, + { 0xaaae44b2815af3afL,0xcf0697b9927a2c1cL,0x37639d62d7d645eeL, + 0x157b7eda2effec37L,0xb55e50759b9c66e6L,0x33a66a1f85f597ecL } }, + /* 15 << 14 */ + { { 0x8260c5339b49bb46L,0x3f3df9d6437cac27L,0xd0723229d972d2a8L, + 0xe544a216d0dd92abL,0xeea4a0f5a03588f6L,0x54006166b218dec0L }, + { 0x0fae2be85778113bL,0xbb9618d68d570227L,0x3ba87360297a47aaL, + 0x9483a8399a76dd6eL,0xa803edaf6eb061b7L,0x6790050cf8067cf4L } }, + /* 16 << 14 */ + { { 0x171898aa8f7782b6L,0x8b7a706b499b3a81L,0xbc0e835ffdb2c1baL, + 0x4ee30281591f5aafL,0xfd71de3bcc272c6aL,0x532800c46e93f68aL }, + { 0x35ee08048365c576L,0x6c2bcc94cd4c0221L,0x49f37ff5957b2ff6L, + 0x315d8e7e5ec029c0L,0x33230602ef324c12L,0xf5847f9b966b2578L } }, + /* 17 << 14 */ + { { 0xed88aa550bf098d0L,0xbc9888fd75f90180L,0x9040919207713428L, + 0x38922bbc1a1f71ddL,0xa430fb65bfbf0f55L,0xa258b9ba867c1998L }, + { 0xa7f69b03b7294c58L,0x2ec0c5de84dbc1e5L,0x41c9e5207dba8d62L, + 0x545573f1795d8285L,0x1c24a375d3075041L,0x687e1cc8fb6b88dcL } }, + /* 18 << 14 */ + { { 0xc29b123e1453b1e1L,0xefb0778820059b44L,0x15554ade9291671eL, + 0xeb5a1980429dea37L,0xf96dacbb6c4b867dL,0x4f5563d6abab4d68L }, + { 0xb5b0ecffcbe76297L,0x5a22996a51d6bd43L,0x0088ec95b7e5cfc6L, + 0x4863a5a1fe373e05L,0x42b7925bc244d93dL,0x85bad13540117113L } }, + /* 19 << 14 */ + { { 0x01725fbe8201fae2L,0xee4d7d382dc34bbbL,0xaddf878afd7c35bdL, + 0x56522d5865536719L,0x595c3dd8f772d4cfL,0xd87c5b6045af30b9L }, + { 0x9cc20b9de7992d5dL,0xdfd53d58d56f1964L,0xaf2947bdc7d42a68L, + 0x9322b73dd19e8ad3L,0xa73a9e843243a6d7L,0x9c7dc57992c203d3L } }, + /* 20 << 14 */ + { { 0x86283e21f9daa551L,0x47fd23f81f696f1bL,0x7d029b1bb9784a9aL, + 0x7c7798bea0c0acb5L,0x41241c716d7c682bL,0x11c6c1131d33c2b0L }, + { 0x5d469ca23565cf32L,0xa949f022bad4bdbfL,0x3d054cc2a13cf4cdL, + 0x13bd21669e3ce279L,0x01bc70e68a4beafcL,0xb39e351d8aba087eL } }, + /* 21 << 14 */ + { { 0x92efa2ebfa6cb068L,0x934209b29235050bL,0xc446ee28d5000c05L, + 0xd4e51912862fb7ecL,0xa53940f111193db0L,0x5f2ef2aa82a7fc57L }, + { 0x1a6b30ecb0210f49L,0x4ab1dac73899548aL,0xb116cc3186737a03L, + 0x56cb33809ebfa5b6L,0x8ac3b61fdfd918b2L,0x65867e3ca102e1feL } }, + /* 22 << 14 */ + { { 0x26072a5d82357232L,0x3762764e9f0fd2f1L,0x9c5813f60c16733eL, + 0xea2e0e03718951d4L,0xae195bd469e63818L,0x241a4afcfa2f9a6eL }, + { 0x0e97519f9165d59aL,0x416bd37358e5af1bL,0xc4e811288197b7ecL, + 0x4145be2c9c6ba0d0L,0xc82cb2a17d40b98aL,0xc3c28487bccfa8b8L } }, + /* 23 << 14 */ + { { 0x920949a810476d2fL,0x5b387bbe2502c026L,0xd1d61a9acd7f026bL, + 0x81003d7ceea9a3f8L,0x6191c15fba5b78aaL,0xacbed41e30ad7befL }, + { 0x1427f1fd6740f72cL,0xb4b5e7c93c475735L,0x6a374d1773029d5dL, + 0xc1e4bfdacd622400L,0x670b9e36c2686dccL,0x1bb236e08dd4085dL } }, + /* 24 << 14 */ + { { 0x84aa863ea4ee10a1L,0x24d805a687919ccdL,0x553f3206b5c399b2L, + 0x775b92173cc109bdL,0x25c01263fe384088L,0xa3c4418bd5f743cfL }, + { 0x3d69705ddf91f1f0L,0x547d46269ebddad1L,0x0198ab1a2626cebdL, + 0xaf8320f285b1afe8L,0xb9c0968ce17e6efdL,0xfedc75c290215bb6L } }, + /* 25 << 14 */ + { { 0x1d375f7dcee34c76L,0x2295f8dbaa486096L,0xd18577928285cb84L, + 0x53fe6bd5e8c46c3bL,0x6f6cb6c068ba071dL,0x654ab4e8964e0f1bL }, + { 0xc70857a9edf6aa40L,0xc313c7852fd26360L,0xd705a86a995998d9L, + 0x413d35efd6989c8dL,0xddc0b2070df131bbL,0x21f64be59c7d70f8L } }, + /* 26 << 14 */ + { { 0x8061d340143ff74dL,0x59e94fc6a23aa7b3L,0xf7c79a0b914c3b81L, + 0x5a836211702c6ae7L,0x2570d63c718123c3L,0x7e86d11ec9f5ce3cL }, + { 0x80f03f9717bcce3bL,0x073975b1465a7446L,0x29f66de7cb357aceL, + 0xe87bd12c04894fb0L,0xfc501a2651a0b5aeL,0x20a3170c02207a3bL } }, + /* 27 << 14 */ + { { 0xaab1f0fa2785a18eL,0xa50192fdb37c657aL,0xe7073b27f0c8a908L, + 0xf3e0451b2c82fce1L,0x8237e128c290240fL,0xc1c631621bbf66cdL }, + { 0x9bbcc2afb6639b7cL,0x07643d299bf0e0c6L,0xf7f070c7671c5be5L, + 0xb09a423a9870ac6aL,0x324503506656cda2L,0x4f404be80584abc2L } }, + /* 28 << 14 */ + { { 0x3ee52d8f5fe63bd4L,0x09f8405c7a7da77cL,0x35ce95c61881a757L, + 0x0a8cf9d9c13e3707L,0xe71258d548d2d3f6L,0xcf4fd6910bbe7c0dL }, + { 0xbd6496e1fb9479f1L,0x711c669aab8cb3a2L,0xcbe8501358cfdfb4L, + 0x655c902b59275b4aL,0x7e0ff05b20f722baL,0xcb00031d42b17aadL } }, + /* 29 << 14 */ + { { 0xc568cee0cef0ae1dL,0x1b3422ca7a55aae0L,0x8dcce5058bb536b8L, + 0x12df74bee92759c9L,0x029abaf02ef962c4L,0x5d30b4359bb1240fL }, + { 0xc62fe8e7d03a850eL,0x67da35b5b08dcab6L,0x6f4d4e75e8ca1131L, + 0x53d6fbf81bd5bf97L,0x596d850ceaa0b2c6L,0x32e918240e8d39b5L } }, + /* 30 << 14 */ + { { 0x3360ff11d54bf1a4L,0xbab994cb5c79494bL,0x953ad553757d7771L, + 0xf17f14f068b58ed5L,0x223615317523c422L,0xf0f05f965ebf0d49L }, + { 0x3386676549182267L,0xf87eccc1ad71c3ebL,0xd7708e18913d8dcaL, + 0x27fe27e1b193eef9L,0x33376365cc45e65dL,0x599b4778d700ac20L } }, + /* 31 << 14 */ + { { 0xb118f73509ebb3c5L,0x7299c7844d0d36efL,0x409ef9cde10b249fL, + 0x040f91d0156401b9L,0x6b9fa5b107467a49L,0x2ede334334415300L }, + { 0x0b3abc9c0edc8055L,0x58f850958ca04aa2L,0xeb0d3202e568b6a6L, + 0x5e57bb1a159dce4cL,0x8d3780e03b68641eL,0x78eb21a0d9f50517L } }, + /* 32 << 14 */ + { { 0xda643272ed068028L,0x86b52135a91fb87fL,0x23865a7c35b43943L, + 0x6ac015884606bbf2L,0x9660ab721559fb9aL,0x1fcb09e73ce2f1a5L }, + { 0x62af29ab793d2f0cL,0xad5aaef53aee7efcL,0xee9f29b744c11037L, + 0xb2a19cf1d36c2571L,0xb87d88e265b552b7L,0xd8b4f172beb253d4L } }, + /* 33 << 14 */ + { { 0x6776241470c50124L,0x157c591f57d0eb9bL,0x99e1e2d769b4bcc2L, + 0x81c2b923a9d94ed3L,0xbdd9294fecbf3becL,0x3825c29a4c4fb135L }, + { 0x431d9f26e915cc2eL,0xc4fb48afec1a4835L,0x97f426c09ada831dL, + 0x0be0cf81d5c48eddL,0x166ee4243d02771fL,0x810bb518b09de508L } }, + /* 34 << 14 */ + { { 0x9f4dd8185038ba67L,0x5ff1572801111ed1L,0x900d44f163de4d57L, + 0xa36c1a67d5db5e67L,0x2f01142e2bf5cea7L,0x1519ae1f59aefbf4L }, + { 0x7b963d1f6d989fcaL,0xa5bb3cb85fce44e1L,0x61087c9672fd3285L, + 0xfb2fc6c1c597ef26L,0x5548e25c81e70a6aL,0xa6c53d67a229d7bbL } }, + /* 35 << 14 */ + { { 0x9d11a26ab9678e36L,0x8142106fbe07b082L,0x3c31548b322fda75L, + 0xa87215ceb7299565L,0xb5229b119ea80113L,0x7221a40f43ae700eL }, + { 0x1ad48de8cc00aef7L,0xc4573660d266daa8L,0x1cb020a65761657bL, + 0x9e799be24588c895L,0x3d209df968561484L,0xa0fb323295fec6d8L } }, + /* 36 << 14 */ + { { 0x9292138a3acde05fL,0x7b23f51a50f9e7f0L,0x6ad891a1af59b585L, + 0xbd394db79654da39L,0xcb8c47315f7c6edbL,0x367bbb5d6d2d6e5aL }, + { 0x8df2c759f51dd55eL,0xce0924d8e6c3517dL,0x49c46188097a8072L, + 0x47169f40980170a7L,0x56198937b96df7ebL,0x09572534531fb3b6L } }, + /* 37 << 14 */ + { { 0x04c18873d2eef240L,0x5752cce75106879cL,0x4b7fbe6bd9736e37L, + 0x7c7f1de4c85990afL,0x0cda6f07a2324ca7L,0x0894eafa4d80c28eL }, + { 0x24bd95890ae7e6d9L,0x050d526aaba494a3L,0x4b05455ee583fb5dL, + 0x3b5fb27c6049bb23L,0xc7c9da6ecb5b411eL,0xc1f2528ebc38336dL } }, + /* 38 << 14 */ + { { 0x8b177119d62ff4b1L,0xb0c02e2783150269L,0xdbeee1f8428f9e51L, + 0x2a55661225ff00dbL,0xb4ebcf98cd0d526aL,0xc69f721fc0efa6abL }, + { 0x0ceeceb516e29d31L,0x0bf4510127d1c530L,0xad942f1f42a7383dL, + 0x2cf389eb03b8fa98L,0x1aa647651ec6acf0L,0xf7ac647c202433b9L } }, + /* 39 << 14 */ + { { 0x880bfb2caa7fcbf4L,0x18c2b739731cd693L,0xd093ada3ae39b46eL, + 0xd48a288796c6fb7cL,0xed7c405daf96bbfcL,0x6b63b9ee256335e4L }, + { 0xfd4795ec7ee8e89cL,0x4f3fa1ccb07320d6L,0xe16c594206b0078dL, + 0xb8c95b563a0b2914L,0x2b5b5ab42b337970L,0xcf612b4cb9f75ea9L } }, + /* 40 << 14 */ + { { 0xbfe63081596eecd6L,0x20eb6fb0a3a194fbL,0x4497ec2b8751a73eL, + 0xf90e9e4cf88ba0e5L,0xd5a9c5d55974eca2L,0x9fc120ade4f3e171L }, + { 0x9ae058a633330640L,0xbda3227855bc8aaaL,0x7851cdbc1c9688a9L, + 0xf68d7d9e1d950edfL,0xc89c645074e06425L,0x62406f3b6116d386L } }, + /* 41 << 14 */ + { { 0x1094390070e509fdL,0x0a8e3db09af61ad1L,0xa487a61538d7aa57L, + 0xa9d56bc5ed020b3bL,0x7ed2294f638b35f8L,0x53d6870dc95fb42eL }, + { 0x85e828494c2207d7L,0xf88831baf0556be9L,0x64a547979fe416c3L, + 0xd61b652e779bebaeL,0xd3f43e2f2c0ccce6L,0xd5119f341f680ab7L } }, + /* 42 << 14 */ + { { 0x466f42a1191938bdL,0x95ec31c036f1dae5L,0xa7f350d2feaa8b55L, + 0x66434577555c505cL,0x0c668e73f55d1ca4L,0xd6af5ba4a7bd7449L }, + { 0x581e14ac1a79d8c9L,0x9761d9763054e915L,0x928e7415d69220a6L, + 0xc5bf4bb405bc4a22L,0xad033b7c45d52313L,0x4e67962c75d66dc7L } }, + /* 43 << 14 */ + { { 0xc60e17b2e2300049L,0x731c2fa54107f308L,0x848f6db7cc2982b3L, + 0xf251c21085275d38L,0xf5cac5b2128c8a96L,0x3c012933405b27f0L }, + { 0x9b0a61520b8b15b7L,0xb1c32dc691fa4548L,0xbe7b7654f366d677L, + 0x7e1f33277147a660L,0x11e31a0eeae310bcL,0x3edef63c1b86b525L } }, + /* 44 << 14 */ + { { 0x6f7e7259c6334c8cL,0xe34cba49b4f2333bL,0x157bf099211d08c5L, + 0x9e39c5442988a4daL,0x796ed9f17a998311L,0x3f4da896d8d349e6L }, + { 0x8ab75656fab28acaL,0x3e215d5342d14b21L,0x50008fd7bec23301L, + 0xd6ee4853446e2c56L,0x203ff1c880da14bcL,0x27a4bfbbc333ba74L } }, + /* 45 << 14 */ + { { 0x745e69dfb3d54e52L,0x1ab2a03e7c405cbfL,0xda71141e0bc431b5L, + 0xb3a47e71aafa7c19L,0x5329594fa88a4905L,0x489b5928973aba07L }, + { 0xbe31a4d37350ad6dL,0x177e5285478a42a4L,0x45a101bf848eba6aL, + 0x4287dfd949936d31L,0xbc4c491dc82823c9L,0x87c816aaeb8b8055L } }, + /* 46 << 14 */ + { { 0x66f5337cf309ced6L,0x897cbcb9eb5ed3cbL,0xeffb601762c35fd5L, + 0xb4b702f081fd31f3L,0xd5203833f66f6120L,0x1d2d5ef318a84d91L }, + { 0x22f9fae70edb3857L,0x034197b3cef00765L,0x16d8c6b493643908L, + 0x90ac59e16c51708bL,0xbed18da32edffd9dL,0xc90ac893e750df1eL } }, + /* 47 << 14 */ + { { 0x4a0af827bdb07e48L,0x5588631e131f46ebL,0xda550ce1e503169dL, + 0x0e16b540f2cf2f14L,0xea19a70dc79930abL,0x5654aa5fa8925651L }, + { 0x2f1a14906104f9c7L,0x98420d6c654cf319L,0xf967467f3ca96df3L, + 0x6abe4e32dee1fc07L,0x913bdf2bbd07d17cL,0xf96f70eda8ef9068L } }, + /* 48 << 14 */ + { { 0xa0096d10b7f8286aL,0x493e88563015be8dL,0xa221d57c17f70125L, + 0x4f932f4fe425eb77L,0xf0fa00df78ddfe95L,0x68165f257866f01fL }, + { 0x01345af4b1693425L,0x3fc8d3a6bad5603fL,0x4269006f0bf46cf5L, + 0x96e3b6b77e340ce9L,0x2a4bda69df7c68b7L,0x9649d8b91b6574c2L } }, + /* 49 << 14 */ + { { 0x98f55e59112ef290L,0xa5516c3568909cdaL,0x40407393235165f1L, + 0x6eeeae510991970cL,0xae79ce1faaa6d26fL,0x8bc719b441d43f67L }, + { 0x4a7af92a39cc89a3L,0xf6d14f9a85c8ab12L,0xb9bfca97eb8d4851L, + 0x926b8155cd52b2f3L,0xdd17dbd48fa94f9fL,0xaf68726447cac5cbL } }, + /* 50 << 14 */ + { { 0x39d7c1729517c2c0L,0x6f795181166e2f50L,0x9f6ecb5dc0ad8b54L, + 0xb480afac8e75ce4bL,0xf51569203dd5ad07L,0x87c855e73799b80dL }, + { 0xea8c34d9538ebc9eL,0x67bebb6a957b303aL,0xc6511b7b4dfc6d7bL, + 0x9a40cf5885b02ee1L,0xf4fffbbdecc59a6fL,0xe85a7c115cebfbcaL } }, + /* 51 << 14 */ + { { 0xffa0118c4a33265cL,0x4c4051d583e0bb83L,0xcde22f8d7007d078L, + 0xae9ebbc2932cba29L,0x297c2252f7a82223L,0x662814f41a09fbdaL }, + { 0x3bfd965640be805aL,0xe49901e592acce09L,0x4e201930bbb6bb43L, + 0xfe94eb4dcc018aa2L,0x454d8c611dcf97a5L,0x11d8e3a230f1011dL } }, + /* 52 << 14 */ + { { 0xe745ee2c36cc8b1bL,0xb40c94e6e328c813L,0x4144aecd8bd107b9L, + 0xc35567890ea88fd2L,0x017460e30492a810L,0x0c63cd4410b8bea1L }, + { 0x9123e9a3c890f74cL,0x940fe6590cea499cL,0xbe306232c82e1bdeL, + 0x40544f6bc041d7ecL,0x46de1f3b477a7dafL,0x336551f6951f1295L } }, + /* 53 << 14 */ + { { 0x2a61217a09b3b9a1L,0x0736704635b71125L,0xfddbf1933df24d57L, + 0x33ddabcb4592d748L,0x2fa9ff8a25309e3aL,0xdca2dd2892a0e76aL }, + { 0x706350255dfbd02cL,0xe01c2553b6306b8dL,0xb14132905e91ddecL, + 0xf45221866f6de6fbL,0x2d48d001b440319aL,0x926e9b64fe67f843L } }, + /* 54 << 14 */ + { { 0x5580401264e2c160L,0xe154925a9a6c256bL,0xce2df32922260b79L, + 0x74824410c546d756L,0x2a1d0a5f79887083L,0xa2c040c5da3f7d48L }, + { 0x74058ecbc14f96b8L,0xe69c09d73415e476L,0xe5a93bb47a443fc0L, + 0xe1bb24800c31d7b0L,0x4701d669f4ab0610L,0x0ad815841eeb23e9L } }, + /* 55 << 14 */ + { { 0x823cd737d72b5925L,0xee09efb9fa38cb06L,0x6828dced4a21e81eL, + 0xab67b37bf365e481L,0x3995edd2b5a7c630L,0x4c24ac8806930b7cL }, + { 0xfd7264d36dedce0eL,0xdcab1e333e76fe1aL,0x6b40889a89a94f97L, + 0x7a1fd432b2a3b0e3L,0x121efaea3ffe933eL,0xa81f6c6f843c3553L } }, + /* 56 << 14 */ + { { 0x26301455e5488aceL,0xdf39099881a20dc7L,0xac7d6049ee06c7f3L, + 0x547e8df33f248fe7L,0x5fc4b74213743dceL,0xa97721bc4c398630L }, + { 0x6b7877cc258aea47L,0x1cedce562d5c28d6L,0x7e930e419428d66eL, + 0x42c80757b97faf54L,0x091fe5ab3812e632L,0x2c29fd42e2e359bbL } }, + /* 57 << 14 */ + { { 0x2d9e65a61d7b990aL,0x8a9ab4bee2a8a6a9L,0x8658c36985e3eea6L, + 0xf352787df0de0b23L,0x872db1de1161aa92L,0xf2648c972190acbfL }, + { 0x9a34f1d09de72e41L,0x13860f846c086516L,0x2e9211b824127c21L, + 0x4e1623bba3697c37L,0x41d71f1df579c733L,0x33f0ebf7ca9f68aeL } }, + /* 58 << 14 */ + { { 0x9b51f4ca9f5a40c2L,0x38b59573682e2132L,0x5765e89dc556998cL, + 0x102fe894698a4a8cL,0x0bbcae977c6964d6L,0x8548f2c6dd7bb12cL }, + { 0x32c11ed9e49848d9L,0x1ee1b525135aefc2L,0xade5d14e812a5e4bL, + 0x0e122e7e15bb167bL,0x321594d4ec5c3594L,0xbcea8723a7c02afeL } }, + /* 59 << 14 */ + { { 0xdbf91edcaf87c75aL,0x9710003266582706L,0xb10cb32b1133a7b3L, + 0x70f5d71767e068daL,0x8d937e56b8e0c9a2L,0xd8a2652ee2a9afd7L }, + { 0x94d6cae9cc90c6ccL,0x3512f3abe94f68ffL,0x931ea6f09331ad40L, + 0x71621013daa3d4f1L,0x591c40bfb668a992L,0x5494cc174c6868e5L } }, + /* 60 << 14 */ + { { 0x7981826070ececc7L,0x8cc0b6e071cfc0e1L,0x998df6590276a6bcL, + 0xffb5bec11a43be05L,0xb93b1543f2beb640L,0x337703d456f3719bL }, + { 0xce74c17cd40a7375L,0x6aef79cab1aece94L,0xc5bdfb388876d218L, + 0xf71ce9cccea91445L,0x471cdbd1ed6e5f5dL,0xe0cc79cf10e56c08L } }, + /* 61 << 14 */ + { { 0x2b17e181794ebe48L,0x6111c897f28cdd32L,0x4d59199062dfeee5L, + 0x7b9d070241b14904L,0xa1ad534d5fea4804L,0xc08915d953b16c22L }, + { 0xa57c883e8ac9ddedL,0x589474dcda1d1bf0L,0x31cbf32ce9aa8e7dL, + 0x2abe9b60f0930d84L,0x604731b0cbdd031aL,0xbc35b1e4e9e1b3c1L } }, + /* 62 << 14 */ + { { 0x39300d55efeff954L,0xa9cf57f34fe9cffdL,0xe3315321b15aebbdL, + 0x26354c57b840b080L,0x2c690488476abf35L,0xa7303fe6d480cf33L }, + { 0xa50865295706c3b1L,0x4c26034eed0b2342L,0xf08d67be9ae9c452L, + 0xd4dbb9f5046c7d0dL,0x4435f1a3f9e5393bL,0xf47aae68cd4d5de8L } }, + /* 63 << 14 */ + { { 0xce9e5ddc06d5f48bL,0x22c1cd3e0ef642baL,0x2ad48eb9e9b8a960L, + 0x330074883ce26679L,0x495e62428d2de642L,0xcba5bf37e03b1a77L }, + { 0x9382c92de716624dL,0x410d212350a33e4fL,0xe55ee116e953e7edL, + 0x27e9a0584b840616L,0x560a5e4939473bd8L,0xbc1e795b382f3a95L } }, + /* 64 << 14 */ + { { 0x31bdb48372876ae8L,0xe3325d98961ed1bfL,0x18c042469b6fc64dL, + 0x0dcc15fa15786b8cL,0x81acdb068e63da4aL,0xd3a4b643dada70fbL }, + { 0x46361afedea424ebL,0xdc2d2cae89b92970L,0xf389b61b615694e6L, + 0x7036def1872951d2L,0x40fd3bdad93badc7L,0x45ab6321380a68d3L } }, + /* 0 << 21 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 21 */ + { { 0xc5cf8997ce0b5b72L,0x350adde19d7154baL,0x8139681e307b254aL, + 0xcc87fb5775cd94d7L,0x90e7027478684954L,0xc4fdf4c095ceb991L }, + { 0x91bbc0ab8762c84cL,0x5e09e226ce09e8adL,0x1cb83d704b93d45fL, + 0xe2299024f541da1fL,0x3eef7ce14b7ffd10L,0x53ee63bbb3fc1b9aL } }, + /* 2 << 21 */ + { { 0xe5004e8003682f59L,0xccdb9cb7f642ac0fL,0x405f50d1bd869f77L, + 0xecffa54de7ebea2cL,0x3354dc22d87620baL,0x01bb2988b1c01ff4L }, + { 0xd9370076e16477fdL,0x45303d2a2e71ba4bL,0xc0de76273291e5c5L, + 0x5cfebd87f0a7ca55L,0xde1162809e592a30L,0xdd26e577a78ebce4L } }, + /* 3 << 21 */ + { { 0x1e9b23b9ff1735a8L,0xc3bf3d5b2b0e4b7bL,0xd4cc00fe59b7721cL, + 0xd5c36f9c9e2f4cebL,0xdeca06bac90af70eL,0x42676f12416ee799L }, + { 0x0d7afe1b6f748c6fL,0x0b7a6de539c39d55L,0x11e43d6ee6eaed18L, + 0x5baf8602496087e0L,0xf833634fb1a3a66eL,0x25098c8a79398677L } }, + /* 4 << 21 */ + { { 0xe141e763d4720770L,0xb9739e70ddb3b450L,0x46e6cde496131446L, + 0x0458a5d5cb6c2ef7L,0xb7747634532f9fd8L,0xf62d372116544457L }, + { 0xbfacb4ded3100854L,0x70788a31b39d3f62L,0x9b543220f22d92e4L, + 0xaa4590f655723258L,0xc7b6730e01ddb8bcL,0xae252cf869e1e7bdL } }, + /* 5 << 21 */ + { { 0xc618cf0ddd4b8d8dL,0x471cda8640dcfbfbL,0xba0dd7ac08882ce6L, + 0x58e5d2f56cd336e7L,0xcdda8301af096540L,0xf6d268463cf31600L }, + { 0x6150cd982197efd5L,0x4440fbfa55fb0877L,0xca31871c90757f1dL, + 0xc4a1faacbdd756c8L,0xc9d4ac1bcbb8421eL,0x3c0c2914b17c43beL } }, + /* 6 << 21 */ + { { 0x46fdb65caa6fe9eaL,0xe0d48e5e05494cd9L,0x5adef5704afbf837L, + 0xc96ba4b91c9e2cadL,0x1e8158f7054a158cL,0x47be73209e38b88dL }, + { 0x9b99971e6d2993ecL,0xac9b0bfadf980eccL,0x9da09642d96ca391L, + 0xd67105369bf4305cL,0x40cc1adfa0dfafaeL,0xe27e32f8a209699bL } }, + /* 7 << 21 */ + { { 0xeaaddeb836e87d82L,0xc12587a71ffd7210L,0xf93d2f5c731f6838L, + 0xb96594e8f7097a65L,0x08d6717ab016e8d3L,0x9c378de81984d825L }, + { 0x627d41e7cb2a0c26L,0x1f447501c697ceb1L,0x8dc40831c760550bL, + 0x70ad48707fac97b0L,0x5ac7f22e7021c170L,0xa6f730e4929d5931L } }, + /* 8 << 21 */ + { { 0x7d27d71fd186cb09L,0x67cb7f4e3bc213c7L,0x418cafeb6075b2cfL, + 0xc0d691e6d93a06f7L,0xc16a95259dd001b9L,0xa0583230026f17b9L }, + { 0x4c1041b07845900bL,0x2874079147a22aaeL,0x8d08efd62c1758e9L, + 0x9cc6f207e6c3229aL,0xec69e902082d8924L,0x9cfa1deaf331dfe7L } }, + /* 9 << 21 */ + { { 0x7b5ab2afbce81cd9L,0xd25fa34b12028b49L,0xf9d65e6b63a659beL, + 0x6f88f1ddfffb943cL,0x38eb0d02b871cd5fL,0x732afedc558ad949L }, + { 0x4093ab05367d424eL,0xf73b23ad29de1be7L,0xce1c0093e7a50181L, + 0x6d05cbbe1e412cb9L,0xd3c1148b773a394cL,0xe04b5fdd38e50316L } }, + /* 10 << 21 */ + { { 0x1793535b8d0ce0f4L,0xe9b054b1ab73f7daL,0xd82a3ac1ee7bc6e2L, + 0xb28ad846b847f39eL,0x40975fa2fc10c012L,0x8de998619aafe68eL }, + { 0xa73f442584878534L,0xbe3118cb7a36a0d7L,0x3763a49e8fa37fc9L, + 0xf3f8ef82361f32b9L,0xea66f9978c1aebc4L,0x88600d648d9d024cL } }, + /* 11 << 21 */ + { { 0x11f842ca150a3325L,0xbae115c3185a385fL,0xddf9643637561bb0L, + 0xecea0cd9a4115fe4L,0x297720665893a694L,0x837e6880df408cfbL }, + { 0xfeb8f511e0a7fb68L,0xd21869dfa062b60fL,0xe2b60f46ca6a5e72L, + 0x64bbec184931d188L,0xfb09c90fe3ef3378L,0x67cbeffacd767337L } }, + /* 12 << 21 */ + { { 0xd35832381b289f6eL,0x10dac54a0aeb3bcaL,0x4df1c08d6692339aL, + 0x2968edec20054647L,0x34072618d74235a4L,0x00b4a7ae71d6064aL }, + { 0x23a8900e25c23f8fL,0xda0cb7fad7d0f1b5L,0x266211c56c8ecdbbL, + 0x0a4351b97bc27e4dL,0x98d54c97fc234258L,0x5ba534071e1a4dfaL } }, + /* 13 << 21 */ + { { 0xf07cfcdd77f083bdL,0x89bcae29d46712c6L,0x2089c3ab0f09bb8bL, + 0x3ede5a2a6b9a4028L,0x27ee18fe013066deL,0xc2bebbb416fcdda3L }, + { 0x6b3926af3a87cd68L,0xf52f0ef9f9a7b831L,0x4a39660a1ffc01b2L, + 0xe98f718d91aa6719L,0x8b0626f111d48e8dL,0x4a6a2e5b2bd93db3L } }, + /* 14 << 21 */ + { { 0xc3ddb6123ef24470L,0x98b66569bb3f99edL,0xccc537153a97a015L, + 0x0d9a6b4d04937b8cL,0x854d081ad9a575f7L,0x347bf0c0127fbd90L }, + { 0x6baa47a5c30987f1L,0x164b390dbfd0b503L,0x6672d1afe6a1f565L, + 0x9a50ee5828d5bb14L,0x2e23ab480d0226fcL,0x33eb052365cdbdbaL } }, + /* 15 << 21 */ + { { 0xa32d1a27d904eb73L,0x6fcad8d0c43c978dL,0x8cf1e7a19c0842f5L, + 0x2a6fa6d800328ae2L,0xa5905f67a1e3b06dL,0x458c8badaa8df96aL }, + { 0xee5b20c0b0d4b89bL,0x352ae0c4815c1af8L,0x546a7d7e6dd73b70L, + 0xa99882225f753229L,0xa38eb5d7efde47e2L,0x8290aaed92635ab1L } }, + /* 16 << 21 */ + { { 0x8ec4335fabe7c60eL,0x01f198c10a6a9fb5L,0x3ff96de001141ab6L, + 0xb21acc2c2eca98a1L,0x6154849010fdf648L,0x2c01a99cd1403e8bL }, + { 0xf1a35f306fa509d7L,0xf7715fe3e3f08e9fL,0x89c26c077fc9a752L, + 0x8d2535fe420d48a0L,0x80ec5ddd52fe2e73L,0x041b8df071704f39L } }, + /* 17 << 21 */ + { { 0x96882074659a0a12L,0xdb0d63032a6bb752L,0x2a1fb2d740c2194dL, + 0xeb6b45ba2c184444L,0x10ee44368c179d33L,0x906d0e509391917fL }, + { 0x11bead88ca3bcba2L,0x25914dae4253fb99L,0x0445b31013c25404L, + 0x2a2eac6d515f53baL,0xa746a1d662bf0a11L,0xc7576a4c6573c4f1L } }, + /* 18 << 21 */ + { { 0xec159ed060c5bee9L,0x80282ff007746414L,0x8d53f05f40a97a54L, + 0xc92d8789f5d4eedeL,0x1edd798132344c09L,0x3bb9a444a92c7b36L }, + { 0xbf130f5cdd6c8903L,0xd270e7cf676fcab9L,0xac49744bdc5ae6f9L, + 0xbd0ccfcb40e39281L,0x222efa16a981b3f7L,0x92bcd2d700aeeadfL } }, + /* 19 << 21 */ + { { 0xecfdb91489c73e10L,0x83a5168becffe79cL,0x6a0d57c123e97ffbL, + 0x774121ca4b130cc3L,0x8556fdc5486967a6L,0x1249448d5fe4a7f5L }, + { 0x8c2c14440e93c114L,0xcde258573bc68985L,0x697ba7b0952758a2L, + 0x0d962b377aee19e3L,0xdb31fe8582c4c640L,0x6ecfaf36c89b4b85L } }, + /* 20 << 21 */ + { { 0xf1e8c5a0e06b40eeL,0xa55909fe59836af3L,0x77a13be8a3a4ed95L, + 0x47408650bbbcde0aL,0x95b455c2b4fba7b7L,0x4983f5ca4321117aL }, + { 0x37bab5d1e18d304fL,0x0edf3733f1d29206L,0xe23e4db4dab91670L, + 0x602a5265923ab7c4L,0x53ee98c6eb920a03L,0x1b592b626f25489cL } }, + /* 21 << 21 */ + { { 0x66c981d9d3543689L,0x20500cd7bb8f53bdL,0x807d43605179af77L, + 0x7280a7b27c286404L,0x75a74e630976a65fL,0x2ba9ad9df11c3bdfL }, + { 0x23f38f950ec6c760L,0xcad599102b858cc1L,0x4d9adb7efec23c19L, + 0xbabb6e45095e85c5L,0xfab66a97e5dac2e4L,0xcde4b15a08baf1f4L } }, + /* 22 << 21 */ + { { 0x148aad3207089d6aL,0x3ab5b0790303c267L,0x7d13995bc3153026L, + 0xeba27c192287f305L,0x5faa453367ae45bdL,0xbbb561db2f4e9488L }, + { 0x254d8977c8493163L,0x60d468fc5c544164L,0x0b6309a3a2758037L, + 0x8480e16b1f9add24L,0xf1d99fd2902ec661L,0xd32df254cb6dd6f4L } }, + /* 23 << 21 */ + { { 0x9a17f5c3610178b9L,0x75dded80bada5aadL,0x158249c23dbeb289L, + 0x1d0671cac300cf49L,0xa1649bd0886902f2L,0x79b0d6ed7d13be62L }, + { 0x78253e7549e2327aL,0x5629cc509af110ecL,0x4373a20059f8765cL, + 0x739f33289d9c5f3aL,0x3c7d5cfe9a5f997eL,0xf044d90d0559357eL } }, + /* 24 << 21 */ + { { 0x20aa15d97ab838e6L,0x6cefdd5a0c827ed1L,0xe2f205caef579e8fL, + 0xad27e38b325981bfL,0x087b8284c3438be8L,0x2095dfcf422360d9L }, + { 0x87cdf5ad76d096bfL,0xf1b97ce1e022adc3L,0xa71240c189104665L, + 0xeb5a175c9c1578e8L,0xbd66910ad150ffa2L,0xac277af811459a28L } }, + /* 25 << 21 */ + { { 0x7db4df62417fb54dL,0xf6c1e7f04dfb7c05L,0xfdcbd3777aa8ceb5L, + 0x0364b3bd89c24333L,0x8a721718fdd3dcafL,0x9a6015dcec2848f1L }, + { 0xd6571930d35ad1a9L,0x154a929199369196L,0xf3be7e228e514732L, + 0xfa3eef28b7fd3aacL,0x0bc3b2a69f60d298L,0xf6327920febfca58L } }, + /* 26 << 21 */ + { { 0x3b9de1baf8dc6030L,0xacc4224a2107fd1eL,0xa7d32fe86dcef0d2L, + 0x353d5e88dd83fb28L,0xd552c3ce50bfb0b2L,0x69bc0e686cc8ee7dL }, + { 0x965c0ca21d9c74d9L,0x5cd163a406ac3ecdL,0x57910a828e98b581L, + 0x1d0fa7523d992afbL,0x862d3184e7d12701L,0xab6a288c6c7d161aL } }, + /* 27 << 21 */ + { { 0x04caa9caf4f2b3e9L,0xcdb896141af43dd4L,0xb09444fd4e74ee8bL, + 0x9428849fec05d35cL,0xe29bb0e94765c0e5L,0x138c45f176d25d2eL }, + { 0xbf041131a0184d83L,0xaf321573991ddc4cL,0x058760a8ef31df7dL, + 0xe0b94b57f80dcf5fL,0x75572221850a4a6eL,0xc735580c104a4a1fL } }, + /* 28 << 21 */ + { { 0x9ba102f1a6b735daL,0xe073232edfbe7d06L,0xa8ac24ba57266a16L, + 0x07458ea42d5c4bb0L,0xfbdd0f0574868e1bL,0x73fa612a3921fe7aL }, + { 0x26f6714b0b32d8e2L,0x7a3cb2b48bceb95eL,0x756a68c6290f204aL, + 0x148fbb787fdf2b7eL,0x639ece6c57fe0da0L,0x315aee1e9a92b7e7L } }, + /* 29 << 21 */ + { { 0x22dc170769d10661L,0x8d89cd1c71fd40f7L,0xa22f11bfa2545040L, + 0x1247d019d44c2446L,0x8d17daaba08235c7L,0x7e6863b9fae7874dL }, + { 0x6d57431c0490d338L,0xc1459e61809d1f9aL,0x4eb14dce95b64852L, + 0x8d3a04e6a7b5a861L,0xfed631ee7bfa24a7L,0xf8f86f27af11723bL } }, + /* 30 << 21 */ + { { 0xb43b14146e63c833L,0x497a5f98c1ec160aL,0x112223de83eb3709L, + 0x293964a88d100b9bL,0x6db1d1931e3b2db3L,0x264bc83d71eced39L }, + { 0x8418eb43aa89c967L,0x51d41bff76f8620aL,0xa4017ee5cc416467L, + 0x1cc527231e216e36L,0x76ba536ce8069a6fL,0xa239b54acb77b981L } }, + /* 31 << 21 */ + { { 0xa05f2dbc37544476L,0xf18dbcd71b797f65L,0xc78131376d50cd5eL, + 0x2b509a4d6dee11daL,0xfc0f0584beba1b6aL,0x3282624a9d53bd6bL }, + { 0xa0944e5c16b7187bL,0x468a79b8aa2f99e9L,0x32e4644b38bc4ed9L, + 0x5bc375d7e7cf71feL,0xe18e3c0956617861L,0xbce9ccbce69255bfL } }, + /* 32 << 21 */ + { { 0x498808edc65fafceL,0x3676a7cc4e806bc3L,0x796e25f176c6b964L, + 0x1aced64bac474261L,0xa62470fc29a460c1L,0x77501dce5e751e48L }, + { 0xcc00053b6d9e3641L,0x2b5bc4ae9a3f5a0bL,0xddaccc2e3f9ca178L, + 0xad33f34a0b80d1b0L,0x6a76df9364642225L,0xc145f36f778e761bL } }, + /* 33 << 21 */ + { { 0x377fc5ac575e74f6L,0xfefeb2327736739fL,0x62ba076a9fc2d5c5L, + 0x6f3c6084baf0269aL,0xce2917688fa7c145L,0xa60bb8905b3f2333L }, + { 0xa811055dd900095aL,0x92d95e7b385bd4f2L,0xba54f444d33c2a43L, + 0xc1b131327d12754fL,0xdcdb54821556f5e3L,0x55377fc539ca4b94L } }, + /* 34 << 21 */ + { { 0x455f65d1a0cbee78L,0x554eccb566225edbL,0x306400b47a4e014fL, + 0xef3e02eb7b67025aL,0x7d4efbaa997a633aL,0xd43c6eb8672c90b2L }, + { 0x0ed2d88d7519da07L,0x864377854b9d51e8L,0xd5900a2e2e3ab57cL, + 0xc02f046b69bb0a39L,0x06d825a6bff12faaL,0xa12e5b0d5d3ac267L } }, + /* 35 << 21 */ + { { 0x1716be5ba10508b4L,0x8706acbe7e37fbebL,0x3881f54e44e3d127L, + 0x54e20622a864d77dL,0x26a194616b83325eL,0x0d57be814c15a8f4L }, + { 0xb10c0cd07b53b476L,0x3d016ea097d39c64L,0x4d7df7c15315bdadL, + 0x6fe5a1acf060cf4dL,0xd5e3d05396846b79L,0xebc878f79e3c8028L } }, + /* 36 << 21 */ + { { 0x5b849ed8d0d193acL,0xe983abf773950501L,0x5ca162770854a569L, + 0xb0b284d26904bdceL,0x9c769d269d4fadecL,0x98e5e9b912677284L }, + { 0xd9246836b557f2cfL,0xbd47433069d46374L,0xbce8b27b9b063a22L, + 0x08da2eca37c5ba26L,0x9e742de8d4b26479L,0x643b752c102aa36cL } }, + /* 37 << 21 */ + { { 0xb72fae566fad22d5L,0x1e921426cf2fd62bL,0x9f31293d4c225102L, + 0x78d43a621975afbbL,0xce2787303cfee30eL,0xb88590d77a82613eL }, + { 0x42f86567560b932aL,0xc2d98915a7c9ed68L,0xe70e41fb349a9750L, + 0x7e7fdd2c79f9582bL,0xf3d6ab07da737c0bL,0xba247c0b9f3cf823L } }, + /* 38 << 21 */ + { { 0x4bebaf153dffdbd3L,0xc37d4a04fcc967a6L,0xeabab9aca0435a65L, + 0xf23d1d58f9ae9c52L,0xce229a798cc8f7b6L,0x4a61e6ebf5e11e61L }, + { 0x770e1dc6b20f2d8bL,0x199d20e8cfb9e820L,0x9fd709c4c381a22bL, + 0x6f53a358b1d52a98L,0x4b1a018c66f511faL,0xc7d2d49375d3a666L } }, + /* 39 << 21 */ + { { 0x3b2db5e5550791d3L,0x034ed5665bbb686eL,0xf019f161e033e3eeL, + 0x33198653acd2f0b5L,0x368d89e41ee8273cL,0xa7ac3b507f26daffL }, + { 0x73d8d7df006c0037L,0x98b5937de73cf271L,0xc3bc340be917247dL, + 0x799ea890e45f37afL,0x27be0f5a25e8dd2fL,0xd70ec41c3bb16923L } }, + /* 40 << 21 */ + { { 0xd30302352679072fL,0x73dfdc0f95dad4c8L,0x53649b575c4630f1L, + 0x60197fc08d098d74L,0x9c295d54647f5cbcL,0xfa5f1bc6c0813efcL }, + { 0xf6e08007d2e49417L,0x4f7d4b3dab579569L,0x7af3e08e11d9b388L, + 0x073ec38a5db61c65L,0x9b480cb89db4dc4dL,0x9be2ce7e372fa82aL } }, + /* 41 << 21 */ + { { 0xd87c0b55ed1b6d83L,0x3b47443adfae29cdL,0x16c5b0e52147bfdeL, + 0x98812fd0663cbdbcL,0xe3cea04955ffe911L,0xfc1e9d9cc5df31caL }, + { 0x7ffa90f9902c4ab1L,0x2cf973c3669a857fL,0x89243cfc94b109adL, + 0x222d6fdb536ee544L,0xa48b1b15fd488c22L,0x7120e3f0f318ba27L } }, + /* 42 << 21 */ + { { 0xfbb8a3cd47813054L,0xa2d7255d462ac3f3L,0x341bc10babdfa7adL, + 0x01efa884ceb9ea50L,0x30fa0f903f5bd09cL,0x8aa309453abd108aL }, + { 0x0ab7fe23f9ecab6fL,0x0585f72a5ec032bcL,0x686a7d71cf9f4fcdL, + 0x096bbf04f769be8dL,0xa309931250b64584L,0x67be53402e216060L } }, + /* 43 << 21 */ + { { 0x4e14fa6eef252e90L,0x2ca968579b7db6f2L,0xf80772e3653f1662L, + 0x4f89e666cd28bb05L,0x7fa800cc77eef62eL,0xa3f6ef5963b2f3e2L }, + { 0x438d564bc81e600aL,0x8978912de14c1434L,0x33732892ea695891L, + 0xaf6aef0b1dc8caceL,0xcbf9580b7c509cb1L,0x2db9fbc11ed6fbdfL } }, + /* 44 << 21 */ + { { 0x408805a1fa7052bdL,0xe4eb27f75f825c13L,0x0a0cc8fa37ee34a7L, + 0x737b99a40c59156fL,0x78c2a5d8e1b55c30L,0x89d70b62bcbb2196L }, + { 0x07ad36911e862a0fL,0xaa1c9118c41cc693L,0x7e6f544c4e1f7359L, + 0xa5f4f5891bf9474fL,0xa711efd9ef56df82L,0x0428edb7e3de91fcL } }, + /* 45 << 21 */ + { { 0x67f403610905be0fL,0xffe68b80c12178bcL,0x41bef79ec6a673aeL, + 0x347e8ba81bc77376L,0xd49956d60e589da2L,0xadd54508fed84dabL }, + { 0x18868a4a462749f4L,0x2048cd88ed323e71L,0x7b27932aa28d1f02L, + 0x3cf6107412e4ddccL,0x0f6198631360ecc5L,0x40e5e08b1330d33bL } }, + /* 46 << 21 */ + { { 0x79b68071e3ad573bL,0xcb070412723966f5L,0xf4610fd1964b453fL, + 0xfdc9dbbc8bcee838L,0x3e191f3bb5ca4f20L,0x90d85084c02e0af0L }, + { 0x4e3f57a70ee64025L,0x63f339acdea07a5cL,0xf255b5045eb4081aL, + 0xe42bd241b4cbb0bbL,0xafa58985ff68c5c3L,0xd36cf7175b55e6e5L } }, + /* 47 << 21 */ + { { 0xf2b06f4b95d37e50L,0x7da1d2af3747c79eL,0x18a37dad6ad0092cL, + 0x9f4a6f081a8f207bL,0xeb1fd3f2cf0fed15L,0xfb9911e4384eb46bL }, + { 0x5f07c680b87cb035L,0xc49935d189e1531aL,0x718f6bd09ea02056L, + 0xadafb67b18a4ca31L,0x26cb0f368477f396L,0xec7775df62ec2172L } }, + /* 48 << 21 */ + { { 0xdffb03aec10b43aeL,0x39b1266e9433a54bL,0x4c262521b19fe0dbL, + 0x0ec1e54f3d5c7feeL,0x2856510b05e68e1eL,0x49382c1edc80b8a6L }, + { 0x80a509312471bdd5L,0xe8cde18581974aa9L,0xca6112ee28235c52L, + 0xd28a0eb8301f9653L,0x22b11e26e11fcdf8L,0x97e6fc5de4d735f3L } }, + /* 49 << 21 */ + { { 0x7fc264d35b253506L,0x1a11dd9cdfe2be8fL,0x2cbcf79c711185a3L, + 0x2208200a46806ddcL,0xf2764b6524e75d8aL,0x71a71bcdfcb43c25L }, + { 0xddd0cd3586a895caL,0x5ec28b469e2caf5dL,0xeb749df9f6614957L, + 0xdae1dd77eddd371fL,0x7ce493b556dde554L,0xc1627c06d6e5653cL } }, + /* 50 << 21 */ + { { 0x7926553cdea7472aL,0xe1e9480d3ba7f351L,0x242a641b1b6a2fe5L, + 0xf4af10091f790122L,0x5a2e2f95967810a0L,0xf1eaec6e2ed57598L }, + { 0x34a32da96b9f2421L,0xdc32daa8dd820372L,0x8b2539fc37a067ecL, + 0x2a495112820969ffL,0xea7c1829a699c283L,0xb4a1083dc2c58cbbL } }, + /* 51 << 21 */ + { { 0x1bcc30812e59d7a4L,0x557be0b2fac34690L,0x5b2868db673254faL, + 0x62e150a49e1302c3L,0xe29e9b445772138eL,0xc76bf4fd7ccb31daL }, + { 0x8d687bbb34c905c9L,0xf4f207030786eeb2L,0xe56a494c38deb469L, + 0x759e75e2cc6bbfa8L,0xb11903aaa59eb766L,0x3f6928c5c68b3bf8L } }, + /* 52 << 21 */ + { { 0x27fa09ebcdded185L,0x763b655c36d090e3L,0xbc586674dd864c93L, + 0xa1f84ff34c7074b8L,0xdf5261d17cf08435L,0xc57860f6fbdaff3fL }, + { 0xfa49af22252d7f08L,0x2367bf8c8db5f89fL,0xad6443ce6dade92dL, + 0xdc5265138d1af3f1L,0x62a282ecc720ce46L,0x1769b74c9808b416L } }, + /* 53 << 21 */ + { { 0x4ee11333ec598f02L,0x4613ba038c7eaad5L,0x48e0bfe61b1ccd1dL, + 0x6e115b6b507b705aL,0xc4d38e4992874d89L,0x30460a066dc59fc4L }, + { 0x75de8dcba0f7ea87L,0xba96718125101367L,0x9d7b03314a742660L, + 0xb4ca381d8c304133L,0xb87b896d65846055L,0x8dd96f0513d381dfL } }, + /* 54 << 21 */ + { { 0x43716f0c3e25b7b3L,0x00caad210aeb5d75L,0xbfee232559a6cb66L, + 0x06c1d812ad059aaaL,0x42d0af57c8bcc046L,0x37968ef70e409a85L }, + { 0xc5c3812ee3be328eL,0xaaa74bf166547ad7L,0xb292af92a15a0db1L, + 0xc0645385e5d5cdbcL,0x2dcf4ca937ec2c28L,0x3f75d089f0cb1694L } }, + /* 55 << 21 */ + { { 0x7e71fba26c0204d3L,0x6191ad249a40b4aeL,0xe2c7ab6bdda24cecL, + 0x5a8fc77e95b26a2dL,0xa6d8b2e43f1c7e44L,0x42d485e4e0a0e08bL }, + { 0x8697386ed7e3b896L,0x5b960d76ee7e58caL,0xda950e9a3fce610cL, + 0xb85c7842803c67dbL,0xed8a53535e62ff2aL,0xfe6b0e2c4d674e7fL } }, + /* 56 << 21 */ + { { 0x46a2a08be26d822eL,0x63537bc689d6d6deL,0x28c556a2b3df9fbcL, + 0x81d3161eb121d512L,0x4e27ce0b123bc86cL,0x1ebadb85bfb240d1L }, + { 0x86edb71a1156314dL,0xf8ac56fd113961bdL,0x2f6bc6d8067f586fL, + 0xf558b8833fe8e532L,0xe9433e2321a7997fL,0xb86f039c87e53b9bL } }, + /* 57 << 21 */ + { { 0xc022a16d78329681L,0xc3da7bf76b1226d5L,0x47ef18daa85c69e3L, + 0x4614f0ee45cecdbaL,0x9126fc2640f19d1eL,0xcdecb2693f5ca09aL }, + { 0xb62a831257a020e3L,0x5f9a8ddc8330d472L,0x37e58ab3eb208a24L, + 0xe64ed285ee4b8687L,0x752fa22a74a82625L,0xa67e24609b25fbafL } }, + /* 58 << 21 */ + { { 0x89e3d770e6b94044L,0x50f50d1675a1a8c9L,0xe73c51d95344c139L, + 0x97a8dd8411723e9bL,0xba0663c57de5dcf2L,0xf26eee6c3a6b588fL }, + { 0x6275b2a9211b989eL,0x32ab4b311608f16eL,0x9e47b2943fdde5b5L, + 0x63c50a50614bae9eL,0xffe4ef05e31c05e7L,0x2fea9142b7db4ba7L } }, + /* 59 << 21 */ + { { 0x27f286db0874c6f6L,0x26de6376e6ec0054L,0x56458a082ca84fc7L, + 0x07bcd4011fccf1b2L,0xb8548e74bae6f486L,0x0ea5857a0de2964fL }, + { 0x8e8df866e50fd2a4L,0x3b07d1a8710fc74aL,0x3e4cc4f5a1fe92b9L, + 0x7380d0836e52d244L,0x4d75e1c12796278bL,0x9eb279258d33f4d5L } }, + /* 60 << 21 */ + { { 0xce7abd1ba225f084L,0x696e1eaff803ee75L,0x66f2789989415775L, + 0x14df21a29eb4991eL,0x012a6413fe2a0769L,0x022cf1c8626f421cL }, + { 0xd4644d0460ab4299L,0xa43cc1732a8d453fL,0x7c4ab8c20ed14031L, + 0xd5854b98e14605f7L,0xd9a98c51fa7ff2cdL,0x7dbe8cbc46baf2c0L } }, + /* 61 << 21 */ + { { 0xf26574593c42ae9eL,0x7c3e5c13bbc289fcL,0xb815fe3fe096e7bfL, + 0x3eb67095da54264eL,0xbf5ca7c4ff3f8128L,0x8fc4a3f865db4dd4L }, + { 0x3af47b17ee382cfdL,0x8854132fd95520f4L,0x3387b11d33c5588eL, + 0x5d7eb66c0c662f93L,0xcad581933b18885eL,0x8d1c069a6f23c209L } }, + /* 62 << 21 */ + { { 0xa9498fb5212ee678L,0xa8824b696ade4a39L,0x422c074e0a406cc2L, + 0x7d38de650a2beef0L,0x482d16f81eed5bbfL,0x1c882006f18380a1L }, + { 0xf90f6c2bb98445e2L,0x36aa980b2c738d70L,0x4caff65b6785ad58L, + 0x1c282becf95863f8L,0x59ad267c5350b79fL,0x53ea042721cedec9L } }, + /* 63 << 21 */ + { { 0x5cc362909fa3481cL,0x1321acdd7292ac86L,0xcc30550378f4d6abL, + 0xf7917237e7d9154eL,0x591e5ba81fb39377L,0x0a387e4f7c541c76L }, + { 0x99685212a38570cfL,0x5cce35c8624cd61bL,0x375c68133aed79d0L, + 0xf72d4b068197e487L,0xcd672f7d129775c5L,0x944ef37f1cd768f6L } }, + /* 64 << 21 */ + { { 0x9c66a32becc5f6daL,0xe4ff40431719ba2cL,0x8c6cfab721e716efL, + 0x32c8fccb96ed74e6L,0x475890dd0b110c83L,0xdfada95f5cb4eefeL }, + { 0x9d7b89a693240fe1L,0x6afdb2d0210b776fL,0xc3f0b55bca7a7d52L, + 0xa6e56a0655d04585L,0x818e221c4257acc5L,0x05207b63fcb8d39eL } }, + /* 0 << 28 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 28 */ + { { 0x0a74da82d8ada6ccL,0xc6b98a3cbea55457L,0x896c26bb57c2f5acL, + 0x981e2f72845d45e4L,0xca152b877e9a7d36L,0x49666d457b582e8fL }, + { 0xea3b9bda49fc20b9L,0x5bcbc84a7c71f153L,0xd346fc5d5748a654L, + 0x7ac2f217622665eeL,0xbb5efe7fb6f16e27L,0xb1810a70644c9dc8L } }, + /* 2 << 28 */ + { { 0x98d089819bc5917bL,0x9f90885d187fac5dL,0x651b18287cfc13dbL, + 0x2d606e4c8655a658L,0xba64d3c563c91b71L,0x36c7d7d8b82a5090L }, + { 0x2d1dff02cab1d598L,0xa95788d7be78f90dL,0x1ac2ee6b0ea1fe01L, + 0xc100b60cd5c1273cL,0x4496084ceae603e7L,0x7fcaaf5f77c2fdfbL } }, + /* 3 << 28 */ + { { 0xa93fec0861b06e05L,0x0bebc26b7dfe6802L,0xc00b45a5cce5662fL, + 0x2e8a0a7f83a9a4a9L,0x6e0cdebbc0bbeb63L,0xc56a20fe63ccd80fL }, + { 0xfc10fa08b51f1f89L,0x4848392020ad9243L,0xfda69cc66bf53af8L, + 0x474b7440f10bb6c9L,0xcda9db3b1e7625e1L,0xe2f62c1e1dc7f3cbL } }, + /* 4 << 28 */ + { { 0xe8e3225a6abdd842L,0x8c85f18f3b367b02L,0xf147a4219f42edb9L, + 0x6d4bc00d0d411d4dL,0xa1a13a2770014bb4L,0xb896d97bfa10166fL }, + { 0xb2a1dfa70c302c6dL,0x0a24bd5d808a63a4L,0x8409a3a2f88c7359L, + 0x071f3838347726a0L,0xd18a551c27507bb9L,0xe0c4cc34b359b167L } }, + /* 5 << 28 */ + { { 0xeaaaf4602a44610fL,0x94d330b10392ac47L,0x989b9b673fe123f1L, + 0xe2ca56ddd8fd0129L,0x77d6d0cd624982a4L,0x55d4b2c371e1fec7L }, + { 0x3e9a04a0360e013cL,0x1d227ea9c9cde585L,0xac2b08e24fed8f86L, + 0xa1d1357ce199e8dbL,0x7cf06ec8e99cc964L,0xd9bc3a7fd85ec63bL } }, + /* 6 << 28 */ + { { 0x7d111c67017c633cL,0xadd9e9bd7d128a9cL,0x4cd8730c6db857e9L, + 0x3c9c03e9f4b46d12L,0xd42f0242a78472dcL,0x3fc0bcb2260841bbL }, + { 0x6332b11a8783f828L,0x65229d2af7be37ddL,0x402f28eee7e8944aL, + 0x3d1bab505ab28372L,0x6944e82cad5e1ff3L,0x65a94c0de8c75729L } }, + /* 7 << 28 */ + { { 0xa151dcbc2f7f3633L,0x4305312a98969226L,0x947afc00604d46e1L, + 0xc3c9d57572f3e28cL,0xce4c1cbd14b1cd1dL,0x8fe9a81df80dea45L }, + { 0x50920f3a9685f603L,0x51d380f00b80d89eL,0x19978ba13f798e32L, + 0x1294aaa6c5edde47L,0x280002c2be714a1eL,0xd998669ef212603cL } }, + /* 8 << 28 */ + { { 0xa44f6ef880e9d9f3L,0xaa7621e91d14d618L,0xcb0e4ed80eaf6671L, + 0x2bf485f8181514a2L,0x74670e180a2927eaL,0xe1b5461612c14645L }, + { 0x4068c0742a67ed61L,0xd10c7a57739063caL,0x391b651d698b2816L, + 0xf310d1696da14fa8L,0xa089be6bd8a578b1L,0xa314b3a844389ad7L } }, + /* 9 << 28 */ + { { 0x688ce85068fd73ecL,0x2cfb41040db1f500L,0x5d943b8d5b9bbc41L, + 0x861867f5403f3973L,0xc331110a2c766363L,0xb28a6bc153aaceeeL }, + { 0x2ab6e7aaadbee7a4L,0x316ca45c2f2b9569L,0xcac646e561d2428aL, + 0x6fd28dadc7cb6291L,0x2e28f68741e20ff4L,0x8cfe90eebd189d34L } }, + /* 10 << 28 */ + { { 0x09b8ed53339da6adL,0xe40727af26f54b8eL,0xc4a105979990fdb2L, + 0xb808656b5108236aL,0xb4411363aa4bd584L,0x19e90149288a0328L }, + { 0x5795d8a8fb0592f8L,0x313c68833213c929L,0x62eecb5b48f79d47L, + 0x3afcfdbab29ca224L,0x0072847d40075b08L,0x078eef3dd1fe0c8fL } }, + /* 11 << 28 */ + { { 0x719b51f20ca20aaeL,0x01ad630824b47b92L,0xd32460c2d3c807deL, + 0x8497786b0a1785f5L,0x8bd521355d714ee5L,0xc267724ed00f741eL }, + { 0xe5578dca9c266820L,0x97ff60085b62d484L,0x84c70e92e3bd1869L, + 0x412759e34dfa679fL,0x6bccc33fce497e18L,0xfb92405669056198L } }, + /* 12 << 28 */ + { { 0x664ff05368ed0760L,0xc3cdc99138fae9feL,0x3fe057aaf1f30a86L, + 0xbae990222d08c72aL,0x4f5faf3f6f09e13fL,0x44461a4413d26b29L }, + { 0xc2504c1bf95418edL,0x12766ea7db3ff26cL,0x2f956e9507a22399L, + 0x2716e70f5a00cdd3L,0x80c020140e9fba99L,0xbe587ac30519875dL } }, + /* 13 << 28 */ + { { 0x5e4bb6b83b23d2a1L,0x819a7c7705c9888cL,0x59e4c48ad0fec7f7L, + 0x4b212b21d6bb71abL,0x370cb90bcbf213f2L,0xf1ea07e0817549b0L }, + { 0x20e3115351a37b92L,0x30f9e70158d444c0L,0x7ac3a37b0b791ab7L, + 0xe456fd475265e4cfL,0x3e3f27ca29580ae8L,0x5d68a40daa2a1654L } }, + /* 14 << 28 */ + { { 0x14203d8720cbb917L,0x284e0c9db2a7424eL,0x99eb2911cefe7139L, + 0xa709c50f42925411L,0xa5a7543e5c79a13aL,0xe262025c6f45f023L }, + { 0x3966fd18828b9f40L,0xc660846913693115L,0xd7dfbcf644373027L, + 0x8e73fe6bbade7645L,0x88267c7b1de0dbd8L,0x1231ac99ce4e8c9eL } }, + /* 15 << 28 */ + { { 0xfd928bd90ba99806L,0x799ac97d1a864172L,0x5436a8cd129682b9L, + 0x4bcacda54e96fecbL,0x453af995c5db1451L,0x8fd382e07073b98fL }, + { 0x17165b8a644a7bbdL,0xd17d2d80b6118620L,0x2a4bf1b2c8cd1bcfL, + 0xdc7aad959ccc119aL,0x6d34084c3bcdbeadL,0xcbc5c5557e0663c8L } }, + /* 16 << 28 */ + { { 0xba86aec170128295L,0x83a09b65c12f35ceL,0x8978ff0789df2f80L, + 0x85750cfd97a773d5L,0x806bb730fc3f35f6L,0x04503422fed868c9L }, + { 0xdc0fcde086ffdbaeL,0x8f4297e11860f43bL,0xfefb7d028d3ad6cdL, + 0x5c652b5997293550L,0x32e12942ed5cfbbaL,0x06192aaf98800d22L } }, + /* 17 << 28 */ + { { 0x9bb8cf660002f389L,0x217219af51505913L,0xfea1388999ef8797L, + 0xad1b2383235597c4L,0x85ffabb70a3e3536L,0xd8235d9da00c725aL }, + { 0xfa9b0f4ba704dac0L,0x99d76ddc2f57fb9aL,0x5ed3683b18428507L, + 0x9e42bc54435307f2L,0x3167de67b4f36896L,0x8a0f99a0d539d713L } }, + /* 18 << 28 */ + { { 0xf0b92b8a4642d9b2L,0xce97828a3f50c883L,0xa33d62936f0b1194L, + 0x23417e0f3692f5b5L,0xc79b9491fb0b95bdL,0x5410e8c95e836b2aL }, + { 0x2b84078d29798fc7L,0xa8732e78d6628695L,0x39da93f898c766aaL, + 0x0797832d305e464bL,0x246069ab163f9f4bL,0xb867dcef53fb6170L } }, + /* 19 << 28 */ + { { 0x949c63730ced5c37L,0x6f8cd6e4fdb6464eL,0xbea902ae2e056dd4L, + 0x43871371fa0d560cL,0x162128e9e9ec2208L,0x84deda5c25060c6aL }, + { 0xa8a8a27c14160ed1L,0xf24bf3dda33b53cdL,0xd12038a976a6d272L, + 0xe64d6384ee8f2b15L,0xc404d580d3e91d69L,0x62cdb886a4888d17L } }, + /* 20 << 28 */ + { { 0xccf0fb423c9eb0caL,0x8703c6694aa03b40L,0x44c735a74001af07L, + 0x9616dd932e874ed1L,0x5c2e8520474ba621L,0xddf13cd3fa93d8b4L }, + { 0xd68c9b4575df1b67L,0x4cd242288f80d389L,0x0f1a16bcc09f47fcL, + 0xc414dc6a9cd4842aL,0xbb0fa94f1f353c6dL,0x405124551950d073L } }, + /* 21 << 28 */ + { { 0xbfe176f2dfb520a6L,0xf51917bced96d0abL,0x8131985078b11135L, + 0x6397f1288f006a55L,0x9877f30e576b5132L,0xe0cd103bec781571L }, + { 0xb4bf74e5bcfd5046L,0x04333aa4be9cc561L,0xc6dd1dbc1e066ca1L, + 0x03c926e1d3718e62L,0x13bf83d404309072L,0x79649ba0ba28ac51L } }, + /* 22 << 28 */ + { { 0xcb1a73c55abfe8a1L,0xe9e2e220deae1d92L,0x2d953d00514befaeL, + 0x74024df9b7940bcaL,0x9a2cad0cd13f4a3aL,0x8790b699360795fcL }, + { 0x63957f3b5e9982eaL,0x491bf3155b7d256eL,0x5708bd4dd23324e7L, + 0x9f11ddd397c4c8c2L,0x1823762f5b7f5162L,0xc45a3976cbfc9dd2L } }, + /* 23 << 28 */ + { { 0x806134cd30731f5cL,0x04522c23487c778cL,0x99b6e6a1651640a5L, + 0xe2d20ed87e9898d1L,0xcad25762069e56d9L,0xd4184f6e29ddfc7bL }, + { 0x1017badcc1aeaa34L,0x7d3700e7f3c62e08L,0x203dcf8d5e42399bL, + 0x05986c66b72795c7L,0x0b56ad9cc0925f02L,0x1f0e895bfe0e3bd3L } }, + /* 24 << 28 */ + { { 0x935b9e244d2edd5fL,0xfeb46fb5efb287b8L,0xa51700a3f5018b92L, + 0xc328beba23864e2aL,0x113b5c9a995f70c1L,0xc0b11c22da1b5d51L }, + { 0x9b99b907f4a360cbL,0xf4ee9995adf0b094L,0xf67c7cf2f94b3f0eL, + 0x664a51a1dcaf10ccL,0xa3709ccce937a669L,0xea97bace4862f098L } }, + /* 25 << 28 */ + { { 0x62c7dd9ed537ed6bL,0x8a82ae7ccc168feeL,0x96fcf8d19d00a4a9L, + 0xfeef6ec205096874L,0xc828c68969f4485fL,0xdc4903a6322563f0L }, + { 0x5339cad7d3280a32L,0x42ae434909ff15cfL,0x94cdb7790bbb6af4L, + 0x480f8a5515721529L,0xc2f9c4dc0ff28eb2L,0x9d2a405e1ff6e3d5L } }, + /* 26 << 28 */ + { { 0xfeebe7d29309e729L,0xd322c38aa30a4eb9L,0x18cb0ce12f4f5c8eL, + 0x08a073a04262105eL,0x6ca92585933f888aL,0xf4a080c903ca1489L }, + { 0x5e678c7949c8daf0L,0xcd6ef6ba5abfcf82L,0x61faba612a4fc564L, + 0x7cacb3dcee0b306eL,0x9fcfafadb5aae2a9L,0x193e841c4b8fb04bL } }, + /* 27 << 28 */ + { { 0x4db6f5f07ed99ce4L,0x1257bd9c2456059bL,0x546c764b43d3590eL, + 0x6d5062adebba72d6L,0x6858f04e2e8d99fcL,0x46554047b4eeee5fL }, + { 0xff433f63535f2da3L,0xd76777542b76d2e8L,0xeb6be9c88e838a3fL, + 0xb7a2d2c1145f8bf4L,0xf3ba128703bb278aL,0xd88cd51530c4a1a4L } }, + /* 28 << 28 */ + { { 0x51758334c942a3f5L,0x7cc01e8832182ba6L,0x772af25774de4fe6L, + 0xb1b3c448e9667bf8L,0x71cb27388079caf6L,0x48890c641d823a40L }, + { 0x47a5887b0e9edbdaL,0x916dfb0cbe089e5aL,0x3185090e1eb42ddfL, + 0x3c7eaa13b7f3af26L,0x940ed8c79e9963b2L,0xd85e77db3426ac10L } }, + /* 29 << 28 */ + { { 0xf21b47bfd7bbbfa1L,0xf757cb309ea0ea77L,0x6df7f53783b2a6dbL, + 0xb0808cf99eb8ed81L,0xc526bb6b64edb3b6L,0x24f1612068f72d82L }, + { 0x3e2e6af8f01cee94L,0xd2e01f947847ca60L,0x079dac3539e68ac2L, + 0xc30720b270cedeaaL,0x2f97f968fa6bf057L,0x2dba403babf6a743L } }, + /* 30 << 28 */ + { { 0xed99932452c802f1L,0x99f6864c5cb78b2eL,0x8f8a0a709b9c3693L, + 0x0b931016e2f598bbL,0x7edbb1b3a614fc15L,0xa0321b50e79f74c2L }, + { 0x834f3ee994bfa457L,0x5ffa9613006907b4L,0xa37e9b83d779b46cL, + 0x7a21743cf33b791eL,0x6646b89dcc28a011L,0x9b975ef8e2ba76f8L } }, + /* 31 << 28 */ + { { 0x166c7151ec72cbfcL,0x3d1f2450c9e519ceL,0xfdcc648e7efc0fa1L, + 0x3f5f90cf6db6d516L,0x8a5dd3df145830f8L,0x4d9938da4e5858e6L }, + { 0xe598f9d4dede1584L,0x2de5a26cf5c8f4e4L,0x495b750f364e20f6L, + 0x29291c445b718188L,0xe560d9ee3733ce27L,0x99b9d27d5b9d206cL } }, + /* 32 << 28 */ + { { 0x162cdf342efffd95L,0x92111fdad59086e8L,0x4478d114454eb977L, + 0x8ce403d8dea38a67L,0xd459633b7435728aL,0x3a7be4e3a63b0504L }, + { 0x0c74066b335dba3eL,0x4e8fb1d7c6ea6ee5L,0x3398b588a99690edL, + 0x4949517c3ad77562L,0xf9824f09cbbb60eeL,0x9fdcafdf85660becL } }, + /* 33 << 28 */ + { { 0x368bea127aa62889L,0x6096730506e1046fL,0xe69be05e564f219cL, + 0x064b9d7c01eab75cL,0xf16ccc9e0152981dL,0x708827acb178a3deL }, + { 0x320f6a8a93248b89L,0x532acc568084908eL,0xe494cd1f6ab586d3L, + 0x59c74cacabbdcde3L,0x3ccf84a62259abeeL,0x6657d1fad96bd141L } }, + /* 34 << 28 */ + { { 0x5d3a8252aa0a9dcdL,0x540e037af97fe26aL,0x4cbb768ca3f68f56L, + 0xf9608732652d7058L,0x5fae0f9f72cea8b9L,0x1a7edfd97d980da5L }, + { 0x9f00ee611791c34dL,0x6c95404c2bc25810L,0xabb1089e043a9faeL, + 0xe36fe9e1a7881ae0L,0xf163dc460fc04e9dL,0xb6955f2f129c7940L } }, + /* 35 << 28 */ + { { 0xa22ebfc7c23bcd94L,0xa653b119684fe9f2L,0xe469e28646b59d70L, + 0x0720daf3dad96b47L,0x5066df7871288c07L,0x7648d7d82905b5a2L }, + { 0xc6ab9c5c0a30a65aL,0xa00539f34930712aL,0x6a64738c7e894bdeL, + 0xd7f3a7459e8eafdfL,0x652a58ff8ce9f7b2L,0x7c9d02e4cb3782bdL } }, + /* 36 << 28 */ + { { 0xf26bd8618875d9e8L,0x22e2380dbea9c273L,0x5f15183791995508L, + 0xb97f40a6648aa1c6L,0x7478f5f83977d848L,0x21e876ae35b57de6L }, + { 0xf620b180a93fc7f6L,0xf49bd07e1b148996L,0xfb0857261c4f60e1L, + 0x6a6653af7ad6b84dL,0x913a2d022e05b686L,0x94746629407dda9aL } }, + /* 37 << 28 */ + { { 0xc662b0f68a97c714L,0x69fbf7d1b8fbbb02L,0xf3bb5a9c5cdff85dL, + 0xfade6eb036ee44f3L,0x6eb4b8266d0905c8L,0x6ab3e4a4391a34d6L }, + { 0xf490046478e7bdb1L,0x8bcd4bf23272c400L,0xdf9a81b78d2c9573L, + 0xb9a0ea166af43695L,0x3298a5d071fe768aL,0x53eeeb4333e87bd2L } }, + /* 38 << 28 */ + { { 0x87cdbfe6bb531d08L,0x384bcd0357957992L,0xc654e2c942008cffL, + 0xd12b50285002e06aL,0x41a34286a67db410L,0x31a109d99d6b2c01L }, + { 0x14d642da2ed35f38L,0xa06a846048ffd04fL,0x8291190cbdbeef68L, + 0xc8106239e43bb0c9L,0x4d7aa992c4bea448L,0x107b86efba3dd9b5L } }, + /* 39 << 28 */ + { { 0x3d870c3144fc1cd3L,0x34409eec0085e7b3L,0x67d5c1340d0395e6L, + 0x9c30dedae3f36689L,0x988ac951d268cc91L,0xdb05825bd2c9dfdfL }, + { 0x30ccc3b75d349fd5L,0x63383c0f60c3a79bL,0x4f45c81732c71964L, + 0x456679642fef028cL,0x82454c12cf4053f0L,0x7c1310fbed8077f0L } }, + /* 40 << 28 */ + { { 0xb8465d16da684157L,0xdadde1abb238faaeL,0xe2cd45e7c6b9bea8L, + 0x7251d4a15cf413d5L,0x615cea8baae1765bL,0x75aa831813f36885L }, + { 0x7d5b0bf7b8767cc1L,0xec38a8ff8022968cL,0x034805b62a07faebL, + 0x916f9eb033b7321eL,0x34963633c0c577ceL,0x8ee07efdabb8d3ceL } }, + /* 41 << 28 */ + { { 0x498606fc2d15a409L,0x2398e109d5fdcb60L,0x8ed8fcbc36540c3cL, + 0x94404e2bc1db3193L,0xe62b808b28db1c38L,0x545b60871ad1d686L }, + { 0xe8bf6489740f4264L,0x7ee76fe71809505cL,0xaa95b8c86f45a011L, + 0x9bd6111b55c715c3L,0xc5c736bc33165913L,0xf1e8cdf282f6c7a9L } }, + /* 42 << 28 */ + { { 0xeb09e7fa949d05b5L,0x49394c1b8d014014L,0x644874d73eb7abd7L, + 0x89c666e5679d2a01L,0x6ea98cbbd315bc8eL,0xd919142a37fa5a26L }, + { 0x042fbac56d0239b6L,0xbff2b086837c510fL,0x21e4d279d9883ed7L, + 0x6416e0239713c2b2L,0x3742c6d14ea05144L,0xff591d8fd5b00fb2L } }, + /* 43 << 28 */ + { { 0x0ae21b83c138ed42L,0xf1b0895a2ff30df8L,0x4d5d634d9559c6e1L, + 0xfd02f3a3098e5c4aL,0x7bc6b63152bb211dL,0x498a68fffb69f0ecL }, + { 0xd6fd5f443e69b479L,0x5ea1877d8c740d2eL,0xfaaff5f0ca605f02L, + 0xb3022f9839a03f5bL,0x3feb7c13aa253725L,0x119097a89dc33a73L } }, + /* 44 << 28 */ + { { 0xa0bd6c0da8a29345L,0xc676b6c55d7f5ef9L,0x303b6d7c20ad7259L, + 0x06542a19d8fe09a7L,0x5a06653ca959014aL,0xf45fd79a5bcfe0cbL }, + { 0x29058d984e583468L,0xf1bd25e60cd7afc0L,0x2a88246ef7dbe54cL, + 0x680eaff835e0ef3dL,0x5942c97f726e59b9L,0x43e971398d5c0825L } }, + /* 45 << 28 */ + { { 0x6656b318f7378bf8L,0xf9a838df182f1a29L,0x0d62dc5ede475756L, + 0x97564544585bcab5L,0x3e99f44c857a13cfL,0x8c3a0a940cbdde00L }, + { 0xa7be375833dd2d24L,0x629040f1bbb1c7eeL,0x0bb2ced27f0eab7aL, + 0xb86f1e1e9f474277L,0x60539a544a14ac4eL,0x9860f986aa90977fL } }, + /* 46 << 28 */ + { { 0x143fdef1fe944aacL,0xfd6700fdd24f606cL,0x5dad2e41737404a9L, + 0xb16c5d42953abdccL,0x132b5cd995be01c9L,0x2bf605d86fd01c6bL }, + { 0xed62526c8803881dL,0x3429579201788c26L,0x553f8e0f8d62ab25L, + 0x3b2df9cf9850ff9bL,0xb320ec40acb513b3L,0x86d61c988875dfe7L } }, + /* 47 << 28 */ + { { 0xe5fbda4daab3cc32L,0x556fcd2535d469a0L,0x414673d91c02fb7bL, + 0xc14ee9fd8bfe6a4cL,0x8ba0959d1133d9f3L,0x086a7c94e94338ddL }, + { 0x92c2f484cdd5a1b9L,0x97bb21f6ea0e0f9eL,0x99756b285411da59L, + 0x4b79c4663be739b3L,0x73502d3e706078fdL,0x6bb794100da7aea4L } }, + /* 48 << 28 */ + { { 0x2daddb11a406d4d7L,0xb02b5da5a2a33d81L,0xb73ce82721a6aa89L, + 0x10919587467506deL,0x0927724c428d8daaL,0x0ede991f7c17adfdL }, + { 0x8518dab1bf7ddb3dL,0x04b091c42a54e1b8L,0x5943c37f89e7a398L, + 0x8e63f5e8e273f6f3L,0xc6d0352b83143d22L,0x30e43182ebd1628eL } }, + /* 49 << 28 */ + { { 0x9bc5af5aedf58e50L,0x31a3beeeb0d51722L,0x5789fcf98cd467aaL, + 0x85d974897793faafL,0xcf09224ecc18f367L,0x4f293783ec7957b4L }, + { 0xb044c854c0be350cL,0x027caaf72a63996cL,0x5341b3f3cb85de2fL, + 0x0d261d80b106359aL,0xf63bfe7a8456af12L,0xa954c4400174c82cL } }, + /* 50 << 28 */ + { { 0xaf752854b02aceb3L,0x000c5c4222c194b3L,0x7e953b78ebd2e61aL, + 0x44dd61b4b9d68960L,0x282ef4216d454ed1L,0xffed862aa402ca61L }, + { 0x5fffddeed3e189e2L,0xf36379990daffe3dL,0x1b09a625857a8a00L, + 0x3e64ff63c1ced62aL,0x9acc484d10b63647L,0x5a470aef3afc8675L } }, + /* 51 << 28 */ + { { 0xe21acfec09ebdbaeL,0x512c66a729b064faL,0x15c08e1191835db7L, + 0x78fff5d665203a4aL,0x99259d961c73615cL,0x85b444b9f36024bbL }, + { 0x4909772df16932deL,0xcc4a526899a3863bL,0xe54557bd2ebff8faL, + 0x1a9b05b709bee4c1L,0x0d2ce396bdb2b785L,0xbd15bcec8ce7ef40L } }, + /* 52 << 28 */ + { { 0x606658a99991167eL,0xb8773e1572c4b43dL,0x6cb364cde025abceL, + 0xafa58e9b0c5a653eL,0xa7e35a54134a68bfL,0xcb831d42ba4d9db6L }, + { 0xae37348ede83ef97L,0x4ac64a6a62ddd553L,0x5feb5e0d715bb6b4L, + 0xf876efae043424b2L,0x7b56a291ad91a9efL,0x817c7053356f3adeL } }, + /* 53 << 28 */ + { { 0x0dbd99249e88115fL,0xecb57472bc568c61L,0xfa4f4a47c1058746L, + 0xb19006014d92c079L,0xe693577091026a8cL,0xebde8e65eefe8740L }, + { 0xe8bc6b3480a93b35L,0xc1c8fc0635518beeL,0xf7f4b448a47cdd36L, + 0xe4d040e0db4f3e42L,0x025fbdfb88345042L,0xfe6cc10f3fbe045dL } }, + /* 54 << 28 */ + { { 0x63ba344a1c20cb4fL,0x55f11c207e8cccf6L,0xe66e1641b5b1046cL, + 0x51cf6dbe758a460bL,0xe786a81e91bb5101L,0x6f4a976209cd4365L }, + { 0xe88b4d03fc565022L,0x46006d0ebfdf8ec6L,0x10a3e85781f4e635L, + 0x28ea91360a4a2e82L,0xf890ea9e757b38dcL,0x89c6789261312e2aL } }, + /* 55 << 28 */ + { { 0x8ce54e2a65d9fc54L,0x4776c1f13bfc0c09L,0x5d15fced99476b22L, + 0x2c5399bc1142dc7bL,0x6faef9d96c6ad87bL,0x4f238e48ca5126cbL }, + { 0xbc7136d607849dc2L,0xc840ccb1e30377a8L,0x30e0f0373a371bafL, + 0x5b8eef9bdfce4735L,0x1662184e514bb217L,0x010ebb8579e0918dL } }, + /* 56 << 28 */ + { { 0x3d6e8d6d8dff7dffL,0x6b6c194ad5be4ad1L,0x57b93f2db6fcd08bL, + 0x99f09948f3761f23L,0x4062f3d6ac8b018fL,0x4b58ac05a27af72cL }, + { 0x4abcc81504d0cdfdL,0xa50043e0bda4b02fL,0xe11297e527a9c083L, + 0x2b2d8d529779c5b3L,0x3de3d330dfdecfedL,0xfe2487caae7fc522L } }, + /* 57 << 28 */ + { { 0xc510bb0b7e7a66ceL,0x54a3e0111332f2c3L,0x6331badedc885f5cL, + 0x1a73c8aedc47d8b2L,0xc657edbb95d4e933L,0x30994aa335dc3ccdL }, + { 0x832d586fafe5be42L,0x3392b07ad44de522L,0x1bcea9a62982450cL, + 0x8237bf2b3709f75bL,0xfa4f2501ea9d03f0L,0xcf492df7bdacd276L } }, + /* 58 << 28 */ + { { 0x2d0f7f28af4ecf83L,0xc2863ae4d48229efL,0xc989ff3d7001268dL, + 0x7f07adb6ba225adeL,0x1564c1db450a15ddL,0x3bfea98c6524d417L }, + { 0xee3cd3ef2cc20833L,0x055c569dba767b1aL,0xef2eaf51351b1279L, + 0x4e02b1d163b809d2L,0xf0e943d00a14c115L,0x2bb3bc3f32f55210L } }, + /* 59 << 28 */ + { { 0x8f577dd79ed385ffL,0xdbcf0548a1fdcac6L,0x38555497c2352ff2L, + 0x33e2ed85eb9edab2L,0xbe4bd6db9e649ecbL,0xea3668f72c6e7488L }, + { 0x841627b8f4b91b7bL,0x2d61a0f7d487c7a7L,0x1932b198142d1dc2L, + 0x06dbb39a1a792783L,0x5be16e570bede1faL,0x4d3b197bdffceb55L } }, + /* 60 << 28 */ + { { 0x1c2fc5088f7a83e5L,0xa7c56233b9970c92L,0x949c71738bafa66fL, + 0x1e299b2d5bbb0490L,0xb9a79e7c18fcb9e8L,0xe6372ce69cb5cc50L }, + { 0x114fc628f465c6aaL,0xc55395208cb797f6L,0x7df94ed7a73ad211L, + 0x41eb8e1f8e0cd008L,0xb028725a004cbb0dL,0x1340186d372c1656L } }, + /* 61 << 28 */ + { { 0x5162886c203a829aL,0x60dbd8d464416392L,0x60589a51b5a10685L, + 0xa79ca259113476a8L,0xbf4f71100d7b37dcL,0x1a1b3fdf78bbb029L }, + { 0x2954d3454799a0bdL,0x7459eac788c256efL,0x61ac72653800707cL, + 0xd861f7764cc84f7dL,0x29f4e5bf84faae3aL,0x7975c9555aa1236cL } }, + /* 62 << 28 */ + { { 0x65f28419238c3c84L,0xf07d83ed90f1ecd1L,0x10307e1bf6567704L, + 0xa94dddb389d17845L,0xaa56f72788f39175L,0x01cf57e2a7aa55f7L }, + { 0x98f4340e77f21e8cL,0x8cd3e0a2adb036c0L,0x5c49ebf4af6b46ddL, + 0x312a2c32455f6897L,0x52fb4f488b517f06L,0xb0f373d442beff4bL } }, + /* 63 << 28 */ + { { 0xd9694bd9af44f9ceL,0xaf2cfbbc1ee29f43L,0xaf352b1c880f80ddL, + 0x3fdabd2142297787L,0xf5a2acc21c7916b3L,0x6154b3f2cc0d85f0L }, + { 0xb9ff2bea0bc58e86L,0x359eb0750561c3d1L,0xbb5a318fb93be593L, + 0x34af9320bff0b3b3L,0x3cbe89341d967c37L,0xd08e5f46a8e9a750L } }, + /* 64 << 28 */ + { { 0x4074ee27978029bbL,0xa9394bdabae0d0c0L,0xaa01d53972cecb4bL, + 0x4b0cf1279a7dd9c4L,0x3e3e3f165bc787cfL,0xdf48f7e1942de53fL }, + { 0x0cc69719567b9d0eL,0x631e33158d0d2750L,0x9fedc1e292314a09L, + 0x7547d22614a1adcbL,0x405561a48662b86aL,0x149fa2b1f5480b7dL } }, + /* 0 << 35 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 35 */ + { { 0x923d0b44bda4aaa7L,0xced14ce4fee29f7bL,0x1656be009cf5b87dL, + 0x13a37d0d1d61103dL,0x1d705880fb652393L,0x870a31bbed712ed8L }, + { 0x15ad02e6ad7c21e3L,0xf004e447c36c2831L,0x56aa376cba2b3ffdL, + 0xc3be2b2f9745443cL,0x47c8a870eb903660L,0x976c303e6c6c192dL } }, + /* 2 << 35 */ + { { 0x148bd39cf4fb80d4L,0x469b208cfff04e65L,0xf397fbe2ce548415L, + 0x441e5c2c87fdde9fL,0x6366b49ffee9c179L,0x38d02bd32938dc71L }, + { 0x26d450fac49c5444L,0x4569f95d2b23d3d7L,0x5f68bf4d298fd876L, + 0xe86df047544768b6L,0x40b69a32f8491267L,0xcbf3adf9f917c71aL } }, + /* 3 << 35 */ + { { 0x32498d4d8125489cL,0x965e8d07a5a46ae0L,0x6cea5e47e96a7e29L, + 0xf78293a4668039ffL,0x62548a96f63edd32L,0xe8e6af95a83e8256L }, + { 0x76e60c3b0db6263bL,0xa1ee4b0621b3d668L,0xa17dbf8b9e49b0b5L, + 0x4b29ba127eb366fdL,0x5e0ed781d29b565fL,0x8cb50d53199b36f9L } }, + /* 4 << 35 */ + { { 0xa66c703529aa3150L,0xd038a5ab479e61fcL,0xdee33e96b5ab5410L, + 0xd068929c7c57d123L,0x0839a208f1d6ad37L,0x8f523dab123f8178L }, + { 0xb3e5e524a67d3840L,0x88bda75e52eb59dfL,0x513a0ab7389f2dd3L, + 0x3197a145890bba6fL,0x61add75b6f66bf09L,0x5c9dfc154eef1722L } }, + /* 5 << 35 */ + { { 0x66dc285007769b1bL,0xe07fb7414d71fac4L,0x5ae688a6c2abbe60L, + 0x08ae92fadcbfd296L,0xbc291256b43044d1L,0x0e1d71ed9fcdf213L }, + { 0xf0c5b28102485685L,0x5d3f9302e3f68f42L,0xbbbfac50ffe4f036L, + 0xb5b5f26174fdba44L,0x4ebe1d070d746760L,0xbb0f7812c37f04b7L } }, + /* 6 << 35 */ + { { 0x810b6ab36df1199dL,0xc229308bb4f293b7L,0x3cf838dd89897750L, + 0x3e391e4e7a336c9aL,0x70148337176f89c0L,0x54b15bacbc4f1e22L }, + { 0x32b104f92c0f2885L,0x2c39cefa67034f2aL,0xb8310437bf178ac1L, + 0x722299f5c99370d5L,0x0a493cf0332b93a8L,0x00e0ab41a420f719L } }, + /* 7 << 35 */ + { { 0xf25925434cab24daL,0x52be9bbce7c3b9c5L,0xaab7a8b64660d1a0L, + 0x09738b819a9600f4L,0x58f0c86637de9e3cL,0x0aea5cc15db31f4fL }, + { 0xe480406f499868beL,0x0d8fc7f0f6913a44L,0x7282364435f2e14eL, + 0xb147b31045e37a93L,0xb1e7aa5bf15c1af7L,0xa8685068b03e7713L } }, + /* 8 << 35 */ + { { 0x21feb7fc21c34c2bL,0xab6a553addb0140eL,0x03a6557624b04e6fL, + 0x2531f186342cb0adL,0x088c4d54a24f6426L,0x9a0ee15c06a873eaL }, + { 0xdbe0253fd33bc748L,0xdad3339f5db8ac9eL,0xeaaf368173e65901L, + 0x71f1fab2ccbfa504L,0xb7b845224b0e163eL,0xe0fca8373c779f3bL } }, + /* 9 << 35 */ + { { 0x710988eb46baf373L,0x8cceb935b57d5018L,0x1864603fa45fdf17L, + 0x3dcaae73ef48e6d0L,0xadd9420b590322c5L,0x947783e39b135f67L }, + { 0xfde763688bf5049fL,0xf00e4c182caa4023L,0x4d3b0f23d355b3d6L, + 0x181fabcc20d5799dL,0x29499b40ab2ad0afL,0xf6e66328f9a938aaL } }, + /* 10 << 35 */ + { { 0xcd7b3c42bcbe922dL,0x2fe02b3b95dd1a5cL,0xeb66bcbd24ef5c38L, + 0x7edcc21ce579c309L,0x7b19d49116f6c900L,0x36019ecdb6317c2cL }, + { 0x554ba55391d9001cL,0xa5e30b9814f31e44L,0x3d1fe33bffda4032L, + 0x5dfec4782306675cL,0xbe59305e000c91e7L,0x3c4e52a325a6b879L } }, + /* 11 << 35 */ + { { 0x02fcc14ec5ea88acL,0xca29bb6d56d093b6L,0x876aeda90e6fe94dL, + 0xfa11a142d7225a9dL,0xfea3ca053d03fed8L,0x435854c6c54d5962L }, + { 0xd770737454a6dfd5L,0xb8960017a3e55d02L,0xd4015a0c04d65c3eL, + 0x397f93d1e98a1204L,0xb0efa2e55f3ed850L,0x18f244698a3ec67bL } }, + /* 12 << 35 */ + { { 0xa35802f5d62cd9f9L,0x0ca9c15d4148436eL,0x261a991d472b9d21L, + 0xd81a1ed6a2f8e875L,0x942f213a699b6d63L,0x041a12fc0ae57758L }, + { 0x61191c82bd70aabbL,0x3776eb8bee4c23b3L,0xabe23e8652511222L, + 0x66dd967d30dabb91L,0x77650c597ed27424L,0x08ea2ebdab25a050L } }, + /* 13 << 35 */ + { { 0xa410ba3ab6cb5a02L,0x6eb40d15d07c5c6bL,0x0de81e9107dcc811L, + 0x996f46eb2631b7afL,0x5a350ba75b7a22f3L,0xf42b24e7634159afL }, + { 0x07bae0abc30952fdL,0x3488cda2d644e0b0L,0x23ae40d0e2111e12L, + 0x650af54ec80cdb56L,0x0f33a30b7d4aa2a8L,0x4e8d3e98442a00e8L } }, + /* 14 << 35 */ + { { 0xa624ab3759a8bc95L,0x4b7e3fa61c971228L,0xe8229c4273aa694bL, + 0x0cc31029779288abL,0xf8eff30f57575e0eL,0xee5e01947d52803eL }, + { 0x32d87e558a78f632L,0x48a06031e454904eL,0xaa2cb8dd16c6e626L, + 0xadd098ac2c140452L,0xd25f285d2d3031b1L,0xfb5fbbe175b59543L } }, + /* 15 << 35 */ + { { 0x2297041fd7a21503L,0xfe7738c2657f03f0L,0x994a8deb168fa34aL, + 0x0c772e02a53c4fdbL,0x67f835d150124cd3L,0x0e0d26356993cbbeL }, + { 0x9857ed845257f11dL,0xdc23a728ac556942L,0xf0e1bb29deb32a7fL, + 0xb8c3c43fee0d70f4L,0xc294b0efc60ad214L,0xa4d438dc679067caL } }, + /* 16 << 35 */ + { { 0x520b0bb905c755e4L,0xa2c2c59bf89f0048L,0x85c1c73a73c23975L, + 0x6e4dec49783aabbaL,0x69f0c69bb0463155L,0x61a42b949c97b17bL }, + { 0x55af24a945d331a3L,0x4b0e63f8f5fe81fdL,0x4034283d708671c4L, + 0x200ddab35fd9001aL,0xe45f28e4342eaf3bL,0x3e8375b41ba936c4L } }, + /* 17 << 35 */ + { { 0xcde014bbc613b1faL,0x5ad97babcdf992c2L,0x9fe05b9fea13e2d8L, + 0x93b553e290c4031fL,0xd62bc0818c727bebL,0x284fb61f888306caL }, + { 0xa63f8dcd1101abd6L,0xfe02dc120e962b27L,0xab169958115301e7L, + 0x8822f954462209baL,0xb3ba3e721198428aL,0x9a73ed38d74c88f8L } }, + /* 18 << 35 */ + { { 0x7db497e17da2f887L,0x0995648b683f3507L,0x50e3ff74f5935bd2L, + 0xdec083e2708c88dcL,0xbcc3bc3125129bccL,0x7a3fd7a80a407b41L }, + { 0x46ab826c25e0ab93L,0x28e891ec54944cfcL,0x637be168f55c6cbfL, + 0xfa34e9942a65216eL,0xd23e99afe3a43c84L,0x6d09d189e6fd958bL } }, + /* 19 << 35 */ + { { 0x8aa6ca1381bbd283L,0x3a0633f4ee167a15L,0x7f297c8b9e3b18e6L, + 0xbead8a50c71fea64L,0xa11b2fdd457aebbfL,0xd7fc286f85bc7bd2L }, + { 0x2922ae5bad1c9d9dL,0xa07741c2ef9ac174L,0x24dab2d457fa8f9fL, + 0xd7078d946116a870L,0x4b45107834117a37L,0x19a4dd21c73c857dL } }, + /* 20 << 35 */ + { { 0xa2f9b4e4bac5d14bL,0x9f904a3eb8699164L,0x63585978fec79b4fL, + 0xbcc9b60ebff45cd8L,0x2e515592a5d63de5L,0xc47a048c3bcc637aL }, + { 0x0523810643aba777L,0xf6818e4c77e67aacL,0x9d5827d238f962b3L, + 0x28a904c6a003988dL,0xc06bc833551f4575L,0x61f6bcc2221cffefL } }, + /* 21 << 35 */ + { { 0xf7cfbbe5055a5623L,0x1f8af775e66d2a5bL,0x0cac440268831d8cL, + 0xd25185890d0e6f2fL,0xf17838a3182f90f1L,0xefdf6f20737f163dL }, + { 0xc3198af0542242e9L,0xf77c3d28209efb0bL,0x1df6d0da8de7be08L, + 0x22ef7367901a6590L,0xfa9b4af44b776d27L,0xdc49102c88ace4f6L } }, + /* 22 << 35 */ + { { 0x60c7d148bafa9cc9L,0x0afc5fe2516b87fbL,0x02e20acff795ff60L, + 0xd1ba069151f32975L,0x8547e7f757be2399L,0x4bdf6abfa0d1b33eL }, + { 0xc793832fa06077f9L,0xad55cccb2d874993L,0x5e217b27314387d8L, + 0x744d7b06e7f2ec4cL,0x761aa86d24fa58b1L,0x41400d9657dd313dL } }, + /* 23 << 35 */ + { { 0xd17f68da759d20f0L,0xc141ca6827b7eaa7L,0x3796db8bdaff5c66L, + 0x067119dca1e5220bL,0x174f11777158ddbbL,0xa80365d8cf8bf75eL }, + { 0x0a79f74933567f05L,0x8c2826123c99bb4fL,0xe448c2bdcd6ae726L, + 0x1ae05aac2ad4b0e0L,0xf90dddcb16442420L,0x37465a1ea75c28e3L } }, + /* 24 << 35 */ + { { 0xf58e05c53178468fL,0xa17c8b868328a2efL,0x1bb22cb44ce0c2f8L, + 0x1ab807b51aab9089L,0x2aafa8c91e76fafdL,0x58cdf95fb4801546L }, + { 0x2c1e4ef8d5d699f1L,0x1583a2aa4cd433bdL,0x571dcaec7f4f9b10L, + 0xf62b696b27156c5eL,0x77d2443448820bb9L,0x94e4cfcc11dd3e55L } }, + /* 25 << 35 */ + { { 0xc3fd1feac00e6c7fL,0xf4e42ddabd322507L,0x1ce3e0da023469ebL, + 0xf81769d2d788b1c2L,0x505cec4c62353342L,0xd4049907ba759922L }, + { 0x9ff98f06618ee939L,0xfa63b3606bd55f31L,0x3fcce488cc4d2515L, + 0xeb6e92e91d629e19L,0xcae4190bff892af7L,0x3e7b780dca80cb44L } }, + /* 26 << 35 */ + { { 0xbc923fdfaf54b58bL,0x2aef31d88767acdeL,0xfbebb8f07f28a3d4L, + 0xce5feafe694fe977L,0x606afb0ac9da1ee5L,0x559866a0b74f7c42L }, + { 0xd935191fdc85f22cL,0x5c3002d7c8ce3240L,0xecd278c198452214L, + 0x665b3176821a3606L,0xce05a914baf26fb7L,0xa178860b60e4e8b8L } }, + /* 27 << 35 */ + { { 0x135c82b55000cc19L,0x34537edf8b2c55b4L,0xfcb6aac2b37acc8cL, + 0xa882e25e8ce8d7f5L,0x531756e98c7ff1eeL,0xdcdaced9ad6312b0L }, + { 0x309a469b7f3aef9dL,0xf306e32588d8772fL,0xe7e6f3abd4dc0d90L, + 0x816b01ae49878940L,0x1cb084e84ba5e2c8L,0x395af25b005d08b3L } }, + /* 28 << 35 */ + { { 0x3832cfd59093efcaL,0x3fda8380ed8b34d7L,0x874ec122e2bd4004L, + 0x3761e9c44270b9ccL,0x6eb2fb1166e640d5L,0x2a45ad23e6dfd0fdL }, + { 0xdcb3272bf8dd082cL,0x7d84341f17486485L,0x0f46b1fda4ca2644L, + 0x81a1ab1e82baf37dL,0xbb1d72713b322f65L,0x1571e326f4038252L } }, + /* 29 << 35 */ + { { 0x4e00aa41d9acdec7L,0xb2b701bf9f80dff4L,0xc366ce97d5e71e0eL, + 0x28c2b4e9ed09255bL,0xef54a1a535086ba6L,0xee2e43f2a1c8b39eL }, + { 0x346f22f5d9143a78L,0x71fc5c06f1053377L,0x1789f7644737b5bfL, + 0xc9f83ee8b0df2648L,0xf91a29e9073ee793L,0x18eb801e3ab450a1L } }, + /* 30 << 35 */ + { { 0x1c3df0914085f0b6L,0xc60c47f5cede211bL,0x7bdead8650b6e857L, + 0xc68645be2cf9aad6L,0x8d970a94d01540f6L,0x9346f253782ec6a1L }, + { 0x3da31263c1b23981L,0x53076158dbabfb68L,0x22947b9f743dfba4L, + 0x872e60061c56f47aL,0xe973d81c2b3b8417L,0xb98216184b1fed56L } }, + /* 31 << 35 */ + { { 0x29fa699b8873de48L,0x64f9e1124932447fL,0x4fb0e009e4c20d43L, + 0x748a0cdf78016262L,0x4891badb7bd23ea8L,0xf1300a437f56368cL }, + { 0x178efa9de8f1f8bbL,0xc31cdb4098a31dd6L,0xc2d5bfbad2c43f9cL, + 0xf377e2cc8678d990L,0xd42d274808d19833L,0x2d72fd4de5ad5e63L } }, + /* 32 << 35 */ + { { 0xb083ba6aec074aeaL,0x46fac5ef7f0b505bL,0x95367a21fc82dc03L, + 0x227be26a9d3679d8L,0xc70f6d6c7e9724c0L,0xcd68c757f9ebec0fL }, + { 0x29dde03e8ff321b2L,0xf84ad7bb031939dcL,0xdaf590c90f602f4bL, + 0x17c5288849722bc4L,0xa8df99f0089b22b6L,0xc21bc5d4e59b9b90L } }, + /* 33 << 35 */ + { { 0x44e6089f006e422dL,0xb4a99bc45b029c6eL,0xd14bd00e6f289edcL, + 0x8ebbedfa25c50773L,0x5bdad80851d3ade5L,0xe4e70c3094727960L }, + { 0x29b759e863ab2622L,0xe20ad36b134d5982L,0x27c8387f4070e06eL, + 0x9fae222556593896L,0x299a0f0c3b199172L,0x476fe70977a39ca4L } }, + /* 34 << 35 */ + { { 0xc91a3d2ef4d0d8a4L,0x450193a819e05a78L,0x0e59e0b89eec69eeL, + 0x2ba20f00138fbf46L,0x5c9fea780e8ae694L,0x62c81c8cc6b73372L }, + { 0x2a1df446ff0997a2L,0x929364ab692bb930L,0x4c4a956436cb618cL, + 0xc55020a0526be5dbL,0x151f18a02c64c026L,0x2ec5becd61724143L } }, + /* 35 << 35 */ + { { 0x139c7d788713439bL,0x46f7bd4b1e19b1caL,0x74259a28b47977d7L, + 0x89a912cb8ab1817aL,0x4428e45f06419142L,0x11b9c4836b34a2d5L }, + { 0xb613563a29487118L,0x81f4502ab6249a60L,0xe28685843d4ddecfL, + 0x138c97297bd250dfL,0x733f2201aaac4593L,0xee6b85ad5d061887L } }, + /* 36 << 35 */ + { { 0xbff288ed74006fd8L,0x388c5a34ded657eeL,0x47d400a2d61a2995L, + 0x54c684af1eba1f65L,0xd1ba6975b1b4452bL,0xb23dda26f2f8283aL }, + { 0x6bff7acf86803147L,0x839571e5e8ea5923L,0xc89e1048dbc4ccc5L, + 0x1fa0221120102232L,0xbf7b8f902d4e4406L,0x14c5de43576aba0eL } }, + /* 37 << 35 */ + { { 0x6c55807bfd2f9b11L,0xb01d9f7239e338efL,0x94f6531135628879L, + 0xae51cf0b0ec6f5b4L,0x387223cfd36b9719L,0xeeb02cc6f2fb192cL }, + { 0x867611ec43c9e89cL,0x5b15785f97930887L,0xb792b88b57ab078bL, + 0x0c54de110bdc03cdL,0x5785811a30d0eee3L,0xb73bb98436b88b00L } }, + /* 38 << 35 */ + { { 0x0d0ba3c06fba6f94L,0x7f7e0f5cf29713c2L,0xa8cce53ba6b94d6cL, + 0xbea99382df40fd27L,0xb3ff1c56bcd4f8b2L,0x19124644418f108fL }, + { 0x6fc5260727c26f18L,0xbc5e23d682c7c8f9L,0x12aa5e8e099b8cb3L, + 0x9d94d88614c579f9L,0x5c629d7a47395f32L,0x9cd280633efbbea0L } }, + /* 39 << 35 */ + { { 0xf0bbf8e88edb7b56L,0x9a76ad71adeb43ccL,0xd99a92528643e982L, + 0x6468ff05cf17f5b5L,0xe6589476d56b985eL,0xdca4273cbe446b3dL }, + { 0xd430e3a47b9dbac1L,0xe075c00f4cfe735dL,0x3ba43fef12395845L, + 0x6895f0c3dcb49ce9L,0xd868006aa92843dbL,0x968a8ceec0d5bc9eL } }, + /* 40 << 35 */ + { { 0xc0387b57f440fe92L,0xce8bad38e291c443L,0x022052e5f9e88be0L, + 0x6f949fe261615c9cL,0xf4874e2d84725fc1L,0x06fb244b73a394ebL }, + { 0xb70553c678208bd8L,0xab1829c028704d28L,0x1453ee1a807b160bL, + 0xa1da80c34649d33aL,0x072e02e056c32ee1L,0x79baa98f3f590646L } }, + /* 41 << 35 */ + { { 0x1613a710b0fef3f2L,0x9ae438012edeec54L,0x07824d08579c3130L, + 0xc2beaf806ba2b1fbL,0x7df3c459fc9e85e5L,0x8debf613dbd63acbL }, + { 0x2774ab78f04f3526L,0x36e7ff55a5285219L,0xf2adccaf4ab04c77L, + 0x14add3d8aa43fbfeL,0x387e4965e3026ac4L,0x154801a1c77391ddL } }, + /* 42 << 35 */ + { { 0x28687291933bc404L,0x6a13b0cc9ba35fa8L,0xd3d1746931c5d126L, + 0x1c81ce5df9727cfbL,0x14f66be860b464eaL,0x0bbdefb8c10ea9f6L }, + { 0x5679a0e5e8d06c95L,0x380161d83dbfd6e3L,0x6cdd31f20523e6d1L, + 0x2ff419e0c4b4c439L,0xc7439153e217782cL,0xb1b74383f6dc5d95L } }, + /* 43 << 35 */ + { { 0xcf0d1d2d03746e38L,0x8476c982916e077eL,0x93de41516dfdc6d3L, + 0x15010d26b78cf13fL,0xbab5a5de97cb08c0L,0x37f0673014a31939L }, + { 0x777c709f6819b0f4L,0xe3c2d2f7114a32e7L,0xf0227e19ec047092L, + 0xe1416f34b817e1e1L,0x4d7db41419c6c3f6L,0xf12a13a9d01aecb1L } }, + /* 44 << 35 */ + { { 0xa09e68e61f023abeL,0xbc432449aae2d6c8L,0x61e22f727cb683dfL, + 0x0b5bbc0fd81a0e89L,0x18ea4e774581f128L,0x28df9961cd70a12aL }, + { 0xb0d3b19f8b8bc10bL,0x0805d1439844e7f8L,0xe3ed3d40675ab6a9L, + 0x026d1200f75e2859L,0x1802457b8bb10969L,0xf94c62b3eadab8caL } }, + /* 45 << 35 */ + { { 0x518e9c4220d03ce7L,0x6c44676187811010L,0x07ff38f99d9be611L, + 0x5c2bac105cf0cfd2L,0x4e5cc677d5881c2dL,0x02dc395f08e39281L }, + { 0xc3ef99142044f4e9L,0x0203508c20c8c831L,0xd1276c030e0524c9L, + 0x5525c0af5402f999L,0x5c9a43aa49c2371bL,0x6d7b6700d28cbb59L } }, + /* 46 << 35 */ + { { 0xdec3ab0f7bae55e1L,0x6bae4baf56152625L,0x1d597c0c839b5d6aL, + 0x243692a966b3b169L,0x37f2ca8eb01c6d34L,0x5baa355aae5c05baL }, + { 0xe0b84c28af384b13L,0x6a2c9386667cd513L,0xc361a75d78319608L, + 0x0c317ac596ca528dL,0xe243aa8672f0a5e0L,0xedcf9f5fa1d1677eL } }, + /* 47 << 35 */ + { { 0x88e5cf3f74a0a7d2L,0xa25a3883cac23d4fL,0x7be2fc2ba6eb3d72L, + 0x188be28d391326cdL,0xeca6aa726f3db24fL,0x237cd6f70b9a11a1L }, + { 0xafeca5436fecffeaL,0xa32291510e6d18f3L,0x46699e2500dd8b76L, + 0x5edb4b1a331eaa12L,0xecf6d8a472ce0658L,0xd91af8da6b80e9e2L } }, + /* 48 << 35 */ + { { 0x7af5da7b63ec62d4L,0x74dc387261dbdee2L,0x7d08dbd360b519a4L, + 0x4e785f79459ef257L,0xe3e7d5a485fa9e7fL,0xea60c815e9b5665fL }, + { 0x2e570d18c209caf9L,0x7bae108371818d1eL,0x5db42a0a398d749aL, + 0x149740ff4f555604L,0x72e4f06bbcee0abdL,0x0ecc0cb581ad0830L } }, + /* 49 << 35 */ + { { 0x43550eea0a34451dL,0x8b0b97e9c3aa33e3L,0xdd974528da22dbdeL, + 0x0337c64dabff3ed2L,0xb50da9e9230cc211L,0x931f891c004d17d0L }, + { 0x8b7f9ccbff366019L,0x5483938033d76a4bL,0x52fceec1950ef740L, + 0x5b19b50cd18125d1L,0xbbb661f55b9011c7L,0xfbf0ec747beda7fdL } }, + /* 50 << 35 */ + { { 0xebca6bbec047276bL,0xcda078e05c3018c5L,0x4620dedda223af10L, + 0x962f389ad02fd60cL,0x901fab93baab3894L,0x5ecbbd7506eab11eL }, + { 0x865dc95e62203b9cL,0x04a599844acf85edL,0x877e94647607236eL, + 0x09592a5684609563L,0x6535176ace76d699L,0x44f2d997ce8812e9L } }, + /* 51 << 35 */ + { { 0xa09c9ab62285b330L,0x6058d94a9b145627L,0x7b4b4141da3c3571L, + 0xc9347a16033b665cL,0x95e9b4f01a33d052L,0x35520f3cd46c67b1L }, + { 0x24938cb136042a9aL,0x5eeaec9de73b7354L,0xed47914931f08616L, + 0xb0187b2b713a2114L,0x03c49947e3b76d73L,0x79b5778a2e94fc7eL } }, + /* 52 << 35 */ + { { 0x6bb19d2162de1ccfL,0x3810bdb3339162c2L,0xeb56c72b6aa09df6L, + 0xac66c58d1d415050L,0x922cd7e74ad9cc85L,0x09e3585f91168090L }, + { 0xffc9a98d31b918a6L,0xc273e186c73c7513L,0xd506753f12a77342L, + 0xe288a471e5edd613L,0x0f358d310cacf05eL,0xfbadfa2d9a63fcfcL } }, + /* 53 << 35 */ + { { 0x020e282989cf155bL,0xa1fa6eaac7f481edL,0xba422e09c5c89724L, + 0x43da4df7cad8186eL,0x1bea459cba3ca738L,0xe9f0afdd0c64bc9bL }, + { 0x4c3b3b8e3592686eL,0x7e6938a7b43ea3f7L,0x8e01a54e7ba7dad8L, + 0x33ecd36ea9c68839L,0x1abd6e125e7e993bL,0x29947e126531feb6L } }, + /* 54 << 35 */ + { { 0xb0fe9b7912a193a0L,0xfa19ad4be4bbd264L,0xd5bf0e5409918851L, + 0xd07d8e5729cf45b0L,0x228e67cc7744259dL,0x786ea24843ed0fc4L }, + { 0x7f700231873cd08dL,0x394db4a70ef49109L,0x699047c06a8197f7L, + 0xf5b168443021ff8fL,0x4c8bb55026621cabL,0x6f28b013065208f1L } }, + /* 55 << 35 */ + { { 0x2fb3a7601f809545L,0x8006902ae93849c6L,0x37cc848c9bd9e1bcL, + 0xf4cd31559d0f6340L,0x357772ac4baef442L,0x0f46d0f77d533f1bL }, + { 0x4121411fd9c12bd0L,0x304083dedb70e364L,0xff6b7a1ccecbeb3dL, + 0xb444b5972aadc899L,0x29ec79bfdb8b3731L,0x864d8d917fbd8982L } }, + /* 56 << 35 */ + { { 0xa79feacac241c5bfL,0xc86df4c017861e6dL,0xaecd1722a699282eL, + 0xcce5e345a0464190L,0x0a79c23deca4f6d4L,0x64603ff16a6e7967L }, + { 0x02e24234aa7312c2L,0xa9e1fc7791a1b587L,0x1daef29f94526a4bL, + 0xa7db710a62ead861L,0xb387fec78869446bL,0xee2171015db19f08L } }, + /* 57 << 35 */ + { { 0x79a0feabe64fb245L,0x5799eea096a4e94cL,0x2592e7a333b063a6L, + 0x2cac3c2ef1063574L,0xb9cea04a7f4755d4L,0xb8e40abaa0bf858dL }, + { 0xe1723d963ffa32a3L,0x6547b4402701eb1eL,0x16ec552a4da9b337L, + 0x75f7f4a8fe0555eeL,0xf97e465014f1c2b2L,0x5495fce3d9ccf8a2L } }, + /* 58 << 35 */ + { { 0xffd160fb62c1b457L,0x62efe01fc4d91f7fL,0xc54f75b5208dd413L, + 0x089514d3e78124d0L,0x752a9ae8c2945054L,0x466636fbdbffa78bL }, + { 0x32936281a265949eL,0xd657c0f084b4d11fL,0x199d8641af455a47L, + 0x1eb24cc7dbd9852aL,0xd2ce80f856bfbbafL,0x1b31b23ceb862890L } }, + /* 59 << 35 */ + { { 0xc866d2a5fcd5aaf4L,0x4ac2b7f57e21250eL,0xa78cd3cbc50b4a92L, + 0x2485c3435a5c541bL,0x555db4dc7ef371eeL,0xcd9d6d9c1304f782L }, + { 0xae86a22974b4d57aL,0x68c93bc8dd4cdd8fL,0x7b95411098b9fd49L, + 0x0dd480b9399d8d4bL,0x0e27be29f2665c52L,0xce8a1ef9d920a5c8L } }, + /* 60 << 35 */ + { { 0x10a6bd0cfc0395b9L,0xe30bf6d06a5e8107L,0xc8aa2483167930d4L, + 0xee75885006e7e1c2L,0x4ee64cfcedcb7788L,0x9498e9bbf2f1d7ecL }, + { 0x084d2350ae0fcdb4L,0x4398ee677f4d25ccL,0xc1ddca395db85bfaL, + 0xefd4819747961197L,0xbd16037f2265195cL,0x1c61a6fc56daae6dL } }, + /* 61 << 35 */ + { { 0x640cf6b17f7c8c50L,0xdffddf2209d44051L,0x837275314e3c038eL, + 0x3164d1875aa8d8a1L,0xb37590bcfceb1066L,0x5e4fab4200d489f6L }, + { 0xc1e5dca3f8105ea2L,0xfdd1b0751c7f8679L,0x571d7dd14f14ac54L, + 0x84cc453155cfb741L,0x49d0b1be48823448L,0x8365f1f3f798b5d9L } }, + /* 62 << 35 */ + { { 0x9f2409cb6a564a3cL,0x9266799ae5134e54L,0x39aa3697fac47921L, + 0xdf3db1f32c0b4dbdL,0xfa37a085f096ec03L,0xb99cfe05afaa0f3fL }, + { 0xc9e00e43df458860L,0xbeb7e60ace2bb0b0L,0xdfe2be57cac8d7e0L, + 0x6ec03d799162b2ffL,0xdfe3a6225d1122dcL,0x9f04dcc8b6014310L } }, + /* 63 << 35 */ + { { 0x30471bf9b42ba5c0L,0x19073fd0c9d26763L,0x92817e8059c1017cL, + 0x29248f743da195b3L,0x029d7e7be928767bL,0xf1a3a08a049a0080L }, + { 0x8ec4f3e6e20c1d68L,0xae815a11f3ad30feL,0xdd0a6083f76f43afL, + 0x197d29fe49465bebL,0xf1a40ae996316f4bL,0xec47d65e59bafbc0L } }, + /* 64 << 35 */ + { { 0x6f57752951c2bb65L,0x4a0c1c284b874bdbL,0x19a1842778b96c6dL, + 0xa674f9922f593505L,0x5abeeec46b7209d6L,0x42d15d0147cf5fffL }, + { 0xe24509b7b49e3b4eL,0x81be939c639ee6e8L,0x7f7daf595761e8e3L, + 0xed5cfcb8d420a288L,0x365b29eb7a0ff696L,0x7d14680599a1ac8fL } }, + /* 0 << 42 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 42 */ + { { 0x9ee1ec3aadcdaa68L,0xd98c498fdcbb6548L,0x32b9737588102ac0L, + 0xdd296cf9c08527f4L,0xb74f8145fae3dfbeL,0x84131eb96cd7cc4fL }, + { 0xa0f2fe7a927ff15bL,0x6b0ade4deee1a4b4L,0x6e7df2d40eeb90a7L, + 0xe2f46e20be4de684L,0xcd28feba3fdd06bcL,0x8e4205aee6d6d9f6L } }, + /* 2 << 42 */ + { { 0x35d47426f78d33efL,0x4af25db28440c42cL,0xbd6a15e22e91bf5eL, + 0xe366a84cc08b6b1aL,0x759c122f55b97de8L,0xecec558f08a03f29L }, + { 0xdcc9fca2ea9d2060L,0xb3e49b8e9f361fe1L,0xdeae39029b59cd04L, + 0xf532ede06f5e5bd4L,0x84fbeeb936099f4dL,0x73576b1f088d2052L } }, + /* 3 << 42 */ + { { 0xee43828c6b512bc6L,0xf73dc9f550b91e60L,0x68f23f30f5dbde6bL, + 0xaf2fe9e3ddd15e00L,0xfbf34dae86578d49L,0x689796556c130010L }, + { 0x137a5fc309942897L,0xff1f0bfe9959f06dL,0x2dd0a04abd7ee14bL, + 0x59c46072e54e2161L,0xf470bdaeea7518adL,0xce556e4340c471cdL } }, + /* 4 << 42 */ + { { 0x2ba8c79022b25f2eL,0xf4670a511af0f4a8L,0x6842f36a2fc2451eL, + 0xfc5c9558bb91e1e3L,0x035d1dfcc3ead762L,0x3d0721cb031e5556L }, + { 0x3af0cc813af18a2eL,0x7888cee2bd11a363L,0x80c3de0a6ade1d12L, + 0xe8c3a5bd93b2dcb5L,0xe3adbd7c90a2214dL,0xfe8646d51192948dL } }, + /* 5 << 42 */ + { { 0x9214cd4bf1c7ed94L,0x4887c7c63738f386L,0xa72ba72bf623e542L, + 0x3c52a464f67d6004L,0xcdb6171d09b9a4ffL,0xe5eb77d160aba627L }, + { 0x7aa9836f39d6afdcL,0xa3fa3a520e0a1e18L,0xe90bd925dee3a4c4L, + 0x47e8eeafd9a94dcfL,0x34302a4921e16feaL,0xe32a62eb8ae23949L } }, + /* 6 << 42 */ + { { 0xd1d70db31df1d1f2L,0x22ebc9bd9fec1f42L,0xde5ac585d11d3205L, + 0x0e4584ab282d4d6eL,0xc87607928f78b85bL,0x48a85682af1fbb6dL }, + { 0x64d012ceae0947bfL,0xab792bbf25e22366L,0x250d40d4a3a030deL, + 0xe9b49f0877e26b9cL,0xe7d30c828c0f2249L,0x2b77b40b97c676a2L } }, + /* 7 << 42 */ + { { 0xa89144b89efc8fe2L,0x23625c36e13b79c9L,0x4fdea1d3a047ad35L, + 0xd0b0ee0d4ae78e01L,0xc224b3f3eac4e606L,0x4360e8acfa41bd81L }, + { 0xb2c69238062437e7L,0x86ce8de0decd1245L,0x2ce4be3dfa9d07bdL, + 0xfd09aa853d268d06L,0x4cd874264a162aafL,0x1b28f72e9d45e849L } }, + /* 8 << 42 */ + { { 0x65026297ba958101L,0xbeb4adf98eef151dL,0x623763a460c8bbf7L, + 0xfa8f5ad78b2a7120L,0xfd744bdf085497e7L,0xf9b6f97e2ba35618L }, + { 0x0cebfe9df8a15e86L,0x47a6d01329576088L,0x655817a3fcf19627L, + 0x30ab44f7c2f11261L,0xbb001c9dddf2c850L,0xb45c7eff073260c3L } }, + /* 9 << 42 */ + { { 0x609a02d031716f88L,0xdff6246c45421ce4L,0x544f3162142838d9L, + 0x8842dcbe36b57d38L,0x2818919c57f561e2L,0x87f5acca318373aeL }, + { 0x42773fb72edf1501L,0xff92c38648e9d8a3L,0x21a81668ccd5a860L, + 0xbac5cf837328cee1L,0x7441f749ddc53a05L,0x987d3a1cb5abe243L } }, + /* 10 << 42 */ + { { 0x3b7c44f8fb90e50fL,0xeafeda047cc384fbL,0x9a33e377de65e34eL, + 0x303f568095094a58L,0x4c0f2e932292809cL,0x920c9c12160b30f2L }, + { 0x31d14e1414b268d4L,0x9964173f1eadb1dcL,0x8e22b362eccb0f39L, + 0x81dccdf83bf9ece1L,0x8e2fda43a40503b1L,0xdb647ac13e112199L } }, + /* 11 << 42 */ + { { 0x9c23216f096c21adL,0xae259a6d41fa37f2L,0xefe0a8c9efe96f6aL, + 0x5631701dd6a27744L,0xed8d0219b3017563L,0xbe2723bca0867a0cL }, + { 0xe02bcb56687b62cfL,0xf26c0f77b96f66a9L,0x43e46251fd16fa3bL, + 0x206a180a44033302L,0xcfa96b556121888eL,0x50567a7789dabe7fL } }, + /* 12 << 42 */ + { { 0xb08fb1175cf3e702L,0x7379b1978023df0aL,0x73aefc7b6f954966L, + 0xc0fb886f76bd243cL,0x871eacc5ce09d5a8L,0x9f55b0a4e773f049L }, + { 0x92945c84415d725dL,0xcd57391f0112ad84L,0x4762bc1d0509d73fL, + 0x15cf97f10f1af175L,0x1f855695328c160fL,0x32cb87263b439f0cL } }, + /* 13 << 42 */ + { { 0xb27e344ae6361abdL,0xa53690eb474027a8L,0x500db02d683a8ef4L, + 0x547ecd17819df66cL,0xc35cd4cc91360e21L,0x6ea003a16026dfedL }, + { 0x45e77cda22395207L,0x1e8e103f91264683L,0x130f2d2b3bd6328eL, + 0x6ae25c819af8973dL,0x6b0f90a0d32d7134L,0x0280a95755c62195L } }, + /* 14 << 42 */ + { { 0x23781958cd8bb5aeL,0xe3d30c5417dd827aL,0xf974e0076bedf762L, + 0xd8154b6273264accL,0xf10fd9bb167b9396L,0x967c5acbe9652a0cL }, + { 0x46775025a28fa76cL,0x17ac7cb32ece9d3cL,0x5fd8968ce04a833eL, + 0x96ed5b49fcd20a43L,0x1d209e85289f9c68L,0x4d7473518ce51950L } }, + /* 15 << 42 */ + { { 0x6f5c8f3475214c1eL,0x3d5560bae192d11eL,0xd8a63ff0d7af2e6fL, + 0x5fb858be9069fe09L,0x83956dcd8cc663f9L,0x52d30c3b838bce30L }, + { 0xf354f6d75569122aL,0xfcef54d1fa68f566L,0xc75b01e79020dfe9L, + 0xaac66895774b952bL,0xb2a58a299468cebeL,0xa994a3b487c81a42L } }, + /* 16 << 42 */ + { { 0xfa7d1236e2319f38L,0x9ba1a1c0a551d3feL,0x9ea27288beb1282bL, + 0x1c069efa07fee8a9L,0x5749c7b55870fee9L,0xbedca76fafcec6faL }, + { 0xa3f8f1b14c63c5e2L,0xaa1bb15694758ac3L,0x753329a9b59dc06eL, + 0xfa8e5f5b98a92c38L,0x6b6f46fd3c2b4662L,0x716f41a1ec04c6c6L } }, + /* 17 << 42 */ + { { 0xa882aa6389201dffL,0x3441fde55bfcde3fL,0x220cca60cb543f54L, + 0x2af1cb29d764d74bL,0x47ae56d0517617c6L,0x05b98dee0342bf55L }, + { 0x214f4b11b4e28cfaL,0xa6ebcdf5093691ffL,0xe49ca185f61d29acL, + 0xd304ac40fd8c9018L,0x196161a0f889b7c7L,0x3b704d52dcfc6c91L } }, + /* 18 << 42 */ + { { 0xb405aff88886500aL,0xd88008bebeeabe24L,0x9457cdf30bc931b2L, + 0x8e5fd378f4c5aac1L,0xdec408107bc2bb98L,0xf86424c598b16f6eL }, + { 0xb6af27b634df75d8L,0x1bd3082125943a31L,0x51176cfcec993c24L, + 0xcfc1433accbd192dL,0x324a5e1e2993be83L,0x34169fc1d06215adL } }, + /* 19 << 42 */ + { { 0x41aa181ad260133aL,0x627dbe0346e236d2L,0x717fba9cfb8cc72bL, + 0x6e21d03d69bbc9e7L,0xd903e845241abdecL,0xd17879fa3c20cb6eL }, + { 0xe6141bd463a360b8L,0xa784a651e86cdcb9L,0x80fe8dd11f9147fdL, + 0x641241c6de155420L,0x1caef32ba71f3546L,0x28c3a51a79fdf82aL } }, + /* 20 << 42 */ + { { 0xaa16c27a84a3d033L,0xc207a4990c11c9caL,0x7ae2d193aae87c9cL, + 0x125ab459916d634eL,0x02ded714cfa65b4bL,0x6efe84944e212e22L }, + { 0x97c48a1888766168L,0x663ccc9dd9c85b9aL,0x6fe8b77b2652f501L, + 0x1daa602d078efd38L,0x35885364dbcb8299L,0x25bd1826b8240626L } }, + /* 21 << 42 */ + { { 0x6621d504af748cb6L,0x3940e5e08dacbf89L,0x9fdd8eeaf546daffL, + 0x18fc70d4b42f9507L,0x09bc4af9a3fcc42cL,0x9199b08f4165304cL }, + { 0x039d45bed3d0e9eaL,0x0963ede2a6464c2bL,0x77f47a62b5215830L, + 0x3a0ce54c3e540cdeL,0x34cf6031b2be8f77L,0xeb143e60201083efL } }, + /* 22 << 42 */ + { { 0x21404da5442467a1L,0xe73047597f7023e0L,0x836439a8213ff492L, + 0x105fe0e37ca0fc37L,0x73835ac85b303c34L,0xe29d830e0057ac8cL }, + { 0x457d083e3b5f41bdL,0x228b26c357341890L,0x8e8f194c4109bf9dL, + 0xd032cf2b6e4a39e3L,0x012e9515d88f9292L,0xd1a4cd32e957e163L } }, + /* 23 << 42 */ + { { 0xec56b72f4ab23680L,0x7cb58e727f22217eL,0x6e98647bd045d18dL, + 0x2b7c9caa9a73b956L,0xc414eabef120122aL,0x45d9036bb6e1b134L }, + { 0xe963c88388abd93fL,0x257f3b619180cb9aL,0x915fee5cb6ca7abdL, + 0x2166402cdb7b1bb1L,0x636f85f6541614e4L,0x81f91a1849d9e527L } }, + /* 24 << 42 */ + { { 0x0430af7759b11c7aL,0xf71cc5b1d4f47acaL,0xe1a7905f12e9190fL, + 0x1c689b7012db9e14L,0x6bdd3dc90abaeeacL,0x97f1c244504f0319L }, + { 0x874afd61a7a54b51L,0xd4604ecbe3d979b8L,0x0d33eee1ebf4aab1L, + 0xa3631cac1aa49fe6L,0x0d8340fbf2217cfdL,0xf6373284423b7e77L } }, + /* 25 << 42 */ + { { 0xc6cdb5ba6f7972d7L,0x7ac7d438907d281eL,0x9160a8f5c01044ddL, + 0x3d74d7eac19ba8f9L,0xf7c7f93f112433e5L,0x2ab355a2012236d3L }, + { 0x1168ce913009447eL,0xbefde8dba26e3458L,0x6f9837db49ec8169L, + 0xb4d1e35c86782931L,0x41440a76d711e5f4L,0x8fc7a5aeacb5cd89L } }, + /* 26 << 42 */ + { { 0x73719fe8286e8aa5L,0xff8663419982a4a4L,0x684511702fb2db95L, + 0x4f1c0eab01d80ea1L,0x2bc50da5530af14eL,0x00d1d5b506071a95L }, + { 0xdb618990a6b374b1L,0x06ad90084e79ebe5L,0x281d01a424a63b70L, + 0x87dbd6d5348625fbL,0xdc90f0bef576b1a9L,0x1a9ef270987747a3L } }, + /* 27 << 42 */ + { { 0x135e416ed651b9b0L,0xe55f7f104a5e7979L,0xe55df2550f0729d2L, + 0x666f2744e33ada22L,0x4968bb982cbcb4a8L,0x7ad4e7811028dd81L }, + { 0x0e59f0dcd7ca8b60L,0xd71628cdd2a600b2L,0x7eaf6d308b0af99cL, + 0x6224b6452900105cL,0xe0513f4388650f12L,0x2a63822a6f6c5234L } }, + /* 28 << 42 */ + { { 0xf8c07373078a045eL,0x998b2d52a81724d2L,0x2b97faf1a6305a28L, + 0x5bc61f67f3e0f93dL,0x7238583cd7aeb8c1L,0x851ecc4b39f5f24bL }, + { 0x1cc8b4689992c20cL,0x73168a863c8553dbL,0x1b9a5f95ba2641adL, + 0x87a0c362ce9d565bL,0x07fb51b2e1eedc62L,0xdb300ac6a973903dL } }, + /* 29 << 42 */ + { { 0x789ca390f33e8516L,0x6a7f594cdee7f1caL,0xb4b6b9ca988005a6L, + 0x14f7b4806cad024bL,0x682a86285a576b68L,0xf188c74e40e1984dL }, + { 0x3584b5e6bf6f19c6L,0xa350b1d2b7467bf3L,0x3b3bb966aa3d1266L, + 0xebbd2c782804d8a3L,0x91a272d36a9caf4eL,0x553ada4158fa7041L } }, + /* 30 << 42 */ + { { 0xb564a0d9807e30a8L,0xaba07b1534a637ccL,0x010e76c5840d8e37L, + 0xb6dcb9ac95f6765eL,0x2f5f8fe103b3ec08L,0x10c5a24fb48363efL }, + { 0x5ddacb2709c4dc1eL,0x8e2884b1e03bafc5L,0x84d56df3cfc2d599L, + 0xc8e2da84ab78ec0dL,0xace4663f900084c6L,0x98d9a1df5d49f42eL } }, + /* 31 << 42 */ + { { 0xb10ca6eea690d9c8L,0x0b8b39efd5e0d490L,0x2685d320e63807d4L, + 0xca40d0ee83116ce2L,0xe1e1434fca51b48dL,0x178a91afeddde4a9L }, + { 0x64f59e3fd0dace59L,0x57b33c26278b1820L,0x2ca13b041550875aL, + 0xb21f675a4e0db4aaL,0x2bbb3edb0216d3c8L,0x7f39955b96ec8017L } }, + /* 32 << 42 */ + { { 0x78a53b5a9563e3bbL,0x19c75eb286af355cL,0x3520f427019a6f8eL, + 0xde6fcad6dc3ad0baL,0xfec96e4f79745b7cL,0x5e566bbdb133f2dcL }, + { 0x50088a2b26561be7L,0x16275b4cc5fddfc7L,0xf21332ff23ae4b9dL, + 0x8cbc659e85246712L,0x27fa9c8df50b515eL,0x25ecf745494ac8b7L } }, + /* 33 << 42 */ + { { 0x7cb130e0837ab43fL,0x8a1f00127b9f6c17L,0xbf827f6d17fa5e12L, + 0xc181b1264914a231L,0x8ce70fb6986288a8L,0x9832863fcd1c276eL }, + { 0x738e99819622ecd1L,0xdfc1b43cb73807abL,0x7254b4cf1b673290L, + 0x2d689f38fb20f902L,0x86460de83c34960eL,0x8453896aed8f62e0L } }, + /* 34 << 42 */ + { { 0x9f74efc606f4904cL,0xa280e4c26d3bc556L,0x974f9bdb75975ee2L, + 0x1bc0e7fb6dacde9fL,0x2a110d4c49649375L,0x045432c09090d834L }, + { 0x84295a20195083cbL,0x92ea17cac7dcf71bL,0x3acced0be70be8c7L, + 0x3703dfc007e28816L,0x37fbf2d1e869fb8eL,0x8c6b0bbef9c35ff8L } }, + /* 35 << 42 */ + { { 0x04a991812f1d2778L,0x0d78573685b91ae0L,0x8c32d6046a5252a0L, + 0x12b043131a0df85eL,0x40c4db631ee669b6L,0x0f499408f18f5f9cL }, + { 0x0dcdefabbfe9a187L,0xbd371c45ca650d7dL,0x33819eb00a36748bL, + 0x82d1af1f29034844L,0x301f906d96257b2fL,0x862728ea9395c666L } }, + /* 36 << 42 */ + { { 0x33a2194f40175152L,0x0f7ddc1dbb13f08bL,0x7c08860850b54274L, + 0x7ebb2c11e41f0795L,0xf915683fbe20d37fL,0xcbcc14889daacec5L }, + { 0xfb02c20fea459050L,0xe964d76ad5815aa3L,0x0e009be9496bbf2dL, + 0x8233690eb42d0f7fL,0x98ee83d49168eb0eL,0x34c3b6f3621fa292L } }, + /* 37 << 42 */ + { { 0x29555d79b0221994L,0x1dd689dd4c9e8f29L,0xcb83ed2c853f5261L, + 0x04b1475e0d9b0670L,0xa28b15e7df2ec34eL,0x094409b5e60a168eL }, + { 0xe4b9fd0e16ed42fdL,0x02f97e84a138f2f6L,0x91dc216ce13520dfL, + 0x59564eda7a245e5dL,0x825278be8478befaL,0x69daadd20328c4d1L } }, + /* 38 << 42 */ + { { 0x6ffade389995db43L,0x88974055790f4b92L,0x082e5add525d19e1L, + 0x002c414897bd9931L,0x3f093b3b5461cff7L,0xafc95b0042b8d3f2L }, + { 0x0a8f7687a993155dL,0x1edfdf616c2bb58aL,0xb5be2d4fc44049e4L, + 0x6fd505bb8dfdf4e7L,0x5386f02a41af5871L,0x8178817569121027L } }, + /* 39 << 42 */ + { { 0x1deada722706171eL,0x1baf4c9aee773c6cL,0x458efac06977d673L, + 0x1f2c2f38646e29b5L,0x36ece91a53323300L,0xab51a49bc4d598e8L }, + { 0x7802760ed8e41d8aL,0x2996f790587425a5L,0x227165b73ca21bedL, + 0x0d9e5c5283536ec3L,0x6232f2e089701806L,0xc55e80a2894e2577L } }, + /* 40 << 42 */ + { { 0x437b7224641e3bd1L,0x84e39f7980a58460L,0x68e5292709759523L, + 0x0176a3ace77f5904L,0xde92fb15e151e242L,0x79965c9aeb1438d4L }, + { 0x318a810a596700b9L,0xa8a6ec57c2198cbeL,0xd7709aaabf030fd2L, + 0xb432023472f5d326L,0xc9945214b03bce50L,0x0bc06d9bd4ecba09L } }, + /* 41 << 42 */ + { { 0x30630eefaadf21b4L,0x94896f68042fb57aL,0xe678fc3eb312e7daL, + 0x325cd2bc5c94c991L,0xd4eece20bea4e518L,0x9d9d65e925eab2abL }, + { 0x5439c348676454e8L,0x9eb68953be1e48ccL,0xbeea9da27b625a31L, + 0xbd82c6ee48cc200eL,0xba9fc94444b9dc77L,0xb31bdebe1eb9283aL } }, + /* 42 << 42 */ + { { 0x1ac1a09d07abf58bL,0x7372e532b5770f9dL,0xe1716687c12fe180L, + 0xd91f4d36c715009eL,0x5d8885cfd6fe1cd3L,0xc0ab5a13aea65e52L }, + { 0xa5fe05a0838e5e05L,0x590cc325971fb33fL,0x3bd8234a4653bf57L, + 0xb83300373708c1aaL,0x27453d3b0e84e8fdL,0x9dd3f05399cf918fL } }, + /* 43 << 42 */ + { { 0xaf6f26c3a36468a3L,0xcab875f28d9fc8deL,0x0209b1ad52f4479dL, + 0xc9941cb5459542cdL,0x91603260a0212b68L,0x98018317345673edL }, + { 0x2b02a35ef98b810fL,0x15953f78b714fb32L,0xf9f9c61eb71a4b4aL, + 0x959b1473a8505b7aL,0x331d32cb4c6ec97cL,0xb1d2dd44e49f189aL } }, + /* 44 << 42 */ + { { 0xdfb0508345c0a2acL,0xd13790035eacfb2fL,0xe9872d766a2e126cL, + 0xd2a89cbd39a02d27L,0xf45baf72d754b7c2L,0x37985ef8c6c61bafL }, + { 0xbbcd3ef2da1c46b1L,0x5af5dda43a355d83L,0x9f7ce4281d67a984L, + 0xf19526926fa33654L,0x2abccb55567b3b71L,0x1b3704f3300cf29fL } }, + /* 45 << 42 */ + { { 0x9dcfaf21712af69cL,0x26de8fb05291cd70L,0xc778294742072171L, + 0x889b9fbc8c617e24L,0x5971e60cc2926862L,0xdd8e70bddc022533L }, + { 0xc783e1e30a369db0L,0x37f562ab07b2bb92L,0x5043f3d40c060f44L, + 0xa9650f47a3e17ac4L,0x3b8cd7ad18010ceaL,0xeed5de39969849e7L } }, + /* 46 << 42 */ + { { 0xf93c3ccb6044ade6L,0xd14a13f8fd376746L,0x1fc20e6fd718a98eL, + 0x9f63c6673e31573eL,0xe99b7693a8e0c66cL,0xdad4615c1e5b5f5dL }, + { 0xcbdb7200ac98f5a3L,0x31414469668ab045L,0x82e92df9bacf0ac7L, + 0xa61f4e8371bfdf94L,0xce8cb699d1bc5deeL,0x42da8ac72f2f837cL } }, + /* 47 << 42 */ + { { 0x0b6252fc32a4e8a0L,0xac1e457dd7170402L,0x76faaffeb121e40fL, + 0xd2dc3cb84ddebd9aL,0x303e47cf362348a1L,0xe37e824a829d9806L }, + { 0x419cc2cc7c2ec135L,0x3eab37024cecfdceL,0xf0c9f19088403d18L, + 0x73c8984daf61b6a3L,0xa2d44d9e00c232a1L,0x61fdf4883cf1cecdL } }, + /* 48 << 42 */ + { { 0xa1972c2196fffb94L,0xbe04093099d7633bL,0xb116ff407e23d66eL, + 0xcb12b2bb949a19f1L,0x75df10ee79e49e91L,0xa3bf90764890bcf4L }, + { 0xcbaa76a609a30252L,0x17c224a90ee5728eL,0xcbc56e5cf4f3f4cbL, + 0x8a07110f4fe868a5L,0x23289f2125e110a2L,0x0289c12bd7693c45L } }, + /* 49 << 42 */ + { { 0x4a9c6f8bea96a0f4L,0x78262a3499e3aaa3L,0x513a8e2028b2634bL, + 0x5ba40287d85d74b0L,0x5702d11d440fcbbfL,0x1933c88a0df91fbdL }, + { 0x642247909a0aff2aL,0x85dc2ca13734398cL,0x1009884fd7aa787aL, + 0xc666a62a0e73f4f5L,0x491bb941cce66210L,0xda8e896bcd173443L } }, + /* 50 << 42 */ + { { 0xdc9b37a7c6e32022L,0x158cd4bb342a148aL,0xd62d371cf06287a0L, + 0xba027eb6e9fe0a01L,0x8e7c6f5372017d09L,0x13c5d6ce9381d9c7L }, + { 0xbd0bc2d46e32f045L,0x52cf0f2554ab7f2aL,0x2e674e50085643f2L, + 0x77bc15aef1662819L,0x57f9e3c4f2ebe66eL,0x839aaebadd284956L } }, + /* 51 << 42 */ + { { 0x752bc171ed9d735cL,0x76d96d3419ad5c26L,0x9549ad3e25c1d83aL, + 0x8f6fed53cd460d20L,0x04504f7c7b619b69L,0x68265559c566f393L }, + { 0x5e39e108804598edL,0xace859b01f4538edL,0x4b8503070c85e5daL, + 0x9f087821abcd4ecaL,0x126d3850c8d0def4L,0x66971fe5263457b2L } }, + /* 52 << 42 */ + { { 0xa82ac9983a4bc15bL,0x28697435c930e4f1L,0x191ebdb6b0c9cef3L, + 0xff05f8e875748872L,0x5b86940237343b20L,0xa7bce94beedfe44fL }, + { 0xfc271e2778f4e1fdL,0x652c5a187734db66L,0x108f61c87efc9a9cL, + 0x01db328970ed1dc1L,0x2bc509afd249f61cL,0x0d2e6b4cfeed393dL } }, + /* 53 << 42 */ + { { 0x691199d77a477295L,0x1f0679a661746b75L,0xf3a51493c9f936d7L, + 0x1fcb336a445af5f6L,0x9880cdebb94ce08fL,0x784fa04a22a6b57aL }, + { 0xc85fe18caa97c3bbL,0x27294a3baabe9b50L,0x9418a5b7b673c915L, + 0x686cd97a15dceed5L,0x6d1c9dc70f22ae6aL,0xed88e02dc02212d3L } }, + /* 54 << 42 */ + { { 0xa62c358dcf616234L,0x85402ffad40aae7cL,0x315ce9f151a7614aL, + 0x6f7e796f5d0c7d7dL,0x73bf57faf3444d22L,0xb5e71e7a224b77c0L }, + { 0x94c40681541ee741L,0x40c97253d6837e1bL,0x1058fe7bb1f1c742L, + 0x3206256f9b24d65cL,0x0abb12a78169ba8dL,0x01fcdb7beae85db9L } }, + /* 55 << 42 */ + { { 0x868f294309fdbd8aL,0xd9c11e7ebdd6c274L,0x3be4d8e7fdcb4fb7L, + 0xcd8c40ad17305d10L,0xf12c97642abde5eaL,0xc9e16d8256776e80L }, + { 0x279c0248df05235cL,0x4bdd8b136d8e4b89L,0xab8bbe8d7c47d2c5L, + 0x12ba8b9e255c665cL,0xd585ce64d140a518L,0x55947e69eb4d353dL } }, + /* 56 << 42 */ + { { 0x06ba6db1f184c91fL,0x3c0a348a45fd0382L,0x0d535b6e4434b527L, + 0x7bbfa2c8692bae0bL,0x5c59a08ebe7fe51cL,0xbaa7d2be36e80cb8L }, + { 0x8a42d8d1bed3cae8L,0xd9e0bc0d15ff4962L,0xe51fce93644c75ffL, + 0x40222561b9392d63L,0x8ab1d286023b4787L,0xfa85c220a1b3190dL } }, + /* 57 << 42 */ + { { 0x294845c28ed1d81eL,0xc0402af2dbe7fdbaL,0xbb56d86d67abe6a1L, + 0x2e61f65b2ed330e4L,0x2893eaebffdf0fd1L,0x06cff97a75fb77dcL }, + { 0x2911ebac1c90fe64L,0xd9c40d77e5ee3458L,0xf5b8b1d4b355f191L, + 0x5be71a4ef365bc6bL,0xe2db432f5277b244L,0x3272a28327235b87L } }, + /* 58 << 42 */ + { { 0xe5105755e6b16cbfL,0xba9fb47b536a49f0L,0x03ac0c10c75ad751L, + 0x9090bc328a2d65a0L,0xcecc7202852b3d23L,0xd214f70128f67958L }, + { 0x379899b1f3695cabL,0x8f3d02e9bd3342c2L,0x9870a7f9e24e7bc1L, + 0x7277e115f723893eL,0x6932ceef0f6f1936L,0xd0bf06dde171306dL } }, + /* 59 << 42 */ + { { 0x815cabeb17832ce7L,0x65afc856a2a4864cL,0x9fe4ae1aa4939a4dL, + 0x7005cbd90729a3c0L,0x887f0cca791e8ad6L,0x55cad97a85aca45aL }, + { 0x3e89d294493c7dcfL,0xf4ae5277ae8ed154L,0x507a3fd0a08fbcdbL, + 0x4df3c552f86677fdL,0x6529f9ace3a82131L,0x09efe1fba53a7c67L } }, + /* 60 << 42 */ + { { 0xbbcfa42d21fe8f67L,0x82983012de2be980L,0x88bb9704aa8e17a0L, + 0x100ad5e784772203L,0x2867168965479d29L,0x0334f9c5c2d9d5d3L }, + { 0x49032c1a83a6cf83L,0xc257b0901dad479aL,0xf64177dea7e3636cL, + 0xb2b5747874a315abL,0x210b11cda170ccbcL,0x80509b7480d80177L } }, + /* 61 << 42 */ + { { 0xe98ad30696993a74L,0xa7dc8330f0484940L,0xc30319fdd61b83d0L, + 0x76e2755809873771L,0x33f4f43ecaedda98L,0x68d5ffe3639c8d3eL }, + { 0xe3cf3b850059b2d9L,0x7f3ecb2f6a3d057eL,0xb569c24b9b8b7466L, + 0xeed92f2ac38ccd58L,0xc16a4e8ce765a2f7L,0xa3a7b6552de9cb38L } }, + /* 62 << 42 */ + { { 0x496de6fa0640df83L,0xa4e500a36c77c97dL,0x45609036947aed3cL, + 0x0edb9422423fc5d8L,0xd0c01b2e68f70746L,0xae44ae0e6d77f3a3L }, + { 0x7cc7e90635adba9cL,0x107a3b46a8413303L,0x9e3eeab98916817eL, + 0x1a99dab86fb74601L,0xb4e8466c1064b039L,0x249149146fcbadeeL } }, + /* 63 << 42 */ + { { 0x89643fa624798452L,0x179b3bd76ee52833L,0x343096e54430c6b3L, + 0x589dba3323461536L,0x59073225c3433575L,0x540f9ce317d80d42L }, + { 0xcd04b14d3aea6c82L,0x9be179b0efc9f455L,0x0ad6fb0791e57cbaL, + 0x33894fa262706b10L,0x2cbc270886bf6926L,0x2cf067e64ea48c6bL } }, + /* 64 << 42 */ + { { 0x298647532b0c535bL,0x90dd695370506296L,0x038cd6b4216ab9acL, + 0x3df9b7b7be12d76aL,0x13f4d9785f347bdbL,0x222c5c9c13e94489L }, + { 0x5f8e796f2680dc64L,0x120e7cb758352417L,0x254b5d8ad10740b8L, + 0xc38b8efb5337dee6L,0xf688c2e194f02247L,0x7b5c75f36c25bc4cL } }, + /* 0 << 49 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 49 */ + { { 0x36c9dbbefda8520eL,0x573507ce6ae3ea98L,0x1ab38db696a8f9f1L, + 0xe031d2356b01e6bcL,0x10466ae68afc4adaL,0x3b35df41ed9c44e4L }, + { 0x61272c12c7bd99e8L,0x6a4ae7b4805afd79L,0xf4c47a910ecc49ebL, + 0xeb95dfeccbe84d5cL,0x43f3b71c8ee497d7L,0x2547af524c6fece4L } }, + /* 2 << 49 */ + { { 0xe323ed0cced45039L,0x04ce0b67a90aa713L,0x9c092f06e8d68e4eL, + 0xd8f5555ad0742e5dL,0xe2d175bf00d3df92L,0x8ca55f154f71aeabL }, + { 0xd1762d72642d391dL,0x0dfdd3c2aec466bdL,0x2caacb4c6281f2a7L, + 0x635ba4703603e53aL,0x94a9811d49fecf29L,0x3a42cf09466bf361L } }, + /* 3 << 49 */ + { { 0xe63fbb10b5356889L,0x5995a0a92e73aba2L,0x5cea30677afd4bf7L, + 0x4494e39dfd37120dL,0x8c572c7249d718a7L,0xfe159c275fa305fbL }, + { 0x751c217fc276c40fL,0x44d0643c45e40857L,0x9a996e6efe7a6486L, + 0x1a4f6d10f53b0e47L,0x651390ecd15fd593L,0xe0c1181d739ee9eeL } }, + /* 4 << 49 */ + { { 0x0f05710b11bccf2fL,0x7113085a7aec1bc6L,0x137da67a46b8d0e2L, + 0x454b89fc698b78ccL,0xf2a6e1de258a9393L,0x5f1804e716488e69L }, + { 0x7c6c550215b3bf35L,0x3b0e09a5b05c2ec1L,0x4b9de30e92f15247L, + 0x09d4ca9327e70a0aL,0x9c8b16340d149363L,0x54a8287cce642137L } }, + /* 5 << 49 */ + { { 0x3a05e7d5ca2af43fL,0x068953f975009801L,0xd6c8a76c06740141L, + 0x7e1df1038a831fa9L,0xfe06e2bae39046f3L,0xda5264a0e1807c29L }, + { 0x1be4ffedff5d4808L,0x299d6537c52be83cL,0x1b38adba11834a9cL, + 0x6074a60b1248fd42L,0xd9a0bd2e041b5430L,0xf222ba84a7b76b03L } }, + /* 6 << 49 */ + { { 0x49ecd6f3346a764eL,0xe46847f14105e657L,0xce9cb2b57550f608L, + 0x45f1a1f7f4cf062eL,0xcdb19a112c27d38aL,0x36d375b284e50b19L }, + { 0xf43691540dba6405L,0x4c9dc863040354dcL,0x7229e70ea24d09cfL, + 0xe72aa86c7cf6831bL,0x487fb68425392838L,0xe88bed04430b9b47L } }, + /* 7 << 49 */ + { { 0x9f77b8c5d1164788L,0x45bcd4c1d7b5c5dcL,0xed22ecf3d88c2357L, + 0x330272ad07de1cf8L,0xd9749f7f4ca13a48L,0x4964ce5d1383ce08L }, + { 0xc033d516b0d0dbb3L,0x056ae73bf51943c3L,0x495cf7e057105e88L, + 0x08ced52e56462560L,0xe9578aa713ca1a7dL,0xe9b045c5a9717f7eL } }, + /* 8 << 49 */ + { { 0xf8a8499b666fa8a8L,0xd0f9401571bba84aL,0xb85e1b1d515e1328L, + 0x88a2636ba941e788L,0xa045241d2b5dd8d8L,0x161be476332f0350L }, + { 0x96c4b205a18fac6bL,0x5cbe8d5e73fc5337L,0x6fc33fc6d00b6029L, + 0x07a914ee89aa3b79L,0x35353eb7a4d4dd00L,0xc026bdc0673e8956L } }, + /* 9 << 49 */ + { { 0x1e551f9bce0b6f8cL,0x1fe7ea4618495e1dL,0x3f6f28742dc0e878L, + 0xb778c12844c43f20L,0xbddc28eb8a250230L,0xd8571a4aac6c3d17L }, + { 0xb9dcaec9730c8a1eL,0x512cee9993fbcf87L,0x0df3a1379bafe001L, + 0x8530e501e2a2b9bbL,0x6d38ba8995ebf91fL,0x704b81a7792cef7aL } }, + /* 10 << 49 */ + { { 0xccda372167103852L,0xf78d22470c54de53L,0xebd16036afa44aa5L, + 0x7b88024864a24ab9L,0x86b38e961c2bc78eL,0xd0aa0d058d63b295L }, + { 0x24912955c62fcbf1L,0x77a68156b9ac435cL,0x432401c71b360b26L, + 0x091f19f34c58ef8cL,0x3a4a61f483d46c9dL,0xad0e5c72e8d616cdL } }, + /* 11 << 49 */ + { { 0x668d598ad1666826L,0x6ffed334fba0ba63L,0xe71e3359d7cddc30L, + 0xa9c15c2d9fb9998eL,0x6966d350612230b9L,0xbca3ed23ae4fe0edL }, + { 0x537cac1b3caa3edfL,0x4f4a737ef33c180cL,0xf8d8f796f8807a7bL, + 0x5c7cf072d1aab3e2L,0x7f0ccb9dfff736e4L,0x71bf0732ef11266aL } }, + /* 12 << 49 */ + { { 0x33b029bccdaa6831L,0x2548552d4c1f9cedL,0x35f1a002dece1c8cL, + 0xc6b87fd7acc23aa5L,0x0b8bb275bab029a4L,0xf07bc06730bfb42dL }, + { 0x1688ff5d1f69ce9dL,0xeedb7b5edb10585eL,0xb7a88cf0d432c197L, + 0x20731bdd015a350aL,0x5fa1835463223f5cL,0xe392e1318024693fL } }, + /* 13 << 49 */ + { { 0x61ada737c3449cb3L,0x071062504ca876ffL,0xcd98a39001d1403eL, + 0x197c845096ded881L,0xd060160568cacebbL,0x7e1b37d1dc3ddff4L }, + { 0xfdc1bcb5d1725e92L,0x11cbe941bf0856d2L,0x63fd35d050199657L, + 0x208a1047b9790d10L,0x52790ce61af4301dL,0x75e6d83beff28b69L } }, + /* 14 << 49 */ + { { 0xdfaeea0a0154731eL,0x9e53419de15a0388L,0x2ad6a83c25a992c8L, + 0xa2ba020fe125501aL,0x894ebaf8d4dd04dcL,0xd48cb95850765559L }, + { 0xf9b58d0980dec92bL,0x2a0e11659da299d7L,0x3c081853efe9cb11L, + 0xb9f3b702a511c5e0L,0xa8f7a25f70486180L,0xc0358b25591b3e2fL } }, + /* 15 << 49 */ + { { 0x00333fa6fa806947L,0x7e4dcfb3504b3e19L,0x8326b0acad4a5dfdL, + 0x9ffc65eac7b12e49L,0xed3b7c0258d16eeeL,0x79fccfb434a4222eL }, + { 0x4a8070a0e556357fL,0x554fe2c9ec97769eL,0xcc405a57da691714L, + 0x12927897856f590eL,0xd4805b93ba198dcbL,0x2649be2e4b18444bL } }, + /* 16 << 49 */ + { { 0xf36e8398eaddf274L,0xe41553a16a5e4ddbL,0x36ab07464efc5b0cL, + 0xb211e59ad316c434L,0x2515ec9f16ccf839L,0x6ecb746503dc6a07L }, + { 0x842b7275c65c1b07L,0xf7ceeec535750ab6L,0x967d711ccef5255dL, + 0xcd3bfb075108cb92L,0xe50c0d8aec1b9740L,0x9e8d56611a9e6308L } }, + /* 17 << 49 */ + { { 0xfcb12ba3aae18c46L,0xb55e959c6e21d463L,0xf720d19f4a4f6f21L, + 0x1c2ff60ed4320c5fL,0x4ce5e1ac1a1b40b8L,0xfdebfb81ff6fb9a0L }, + { 0xd6c37d8a9c67c07eL,0x55167952012fc09fL,0x5dc722b52c306c4dL, + 0x1efad8d2bc1f65e1L,0xa1478f3da52556ecL,0x54cbfb884a795dd5L } }, + /* 18 << 49 */ + { { 0x84f8ea13ccb8a36aL,0x5f7aeeffa05709a2L,0x4942d04e60574f37L, + 0x855b13e9e048b400L,0x747e4067a6b59c09L,0xc349fb05074d3990L }, + { 0x398e6afaec2c7e03L,0xce361865ec2d5a4cL,0xfc04bf8eb6f57d22L, + 0xf0e0b84c759ce6c6L,0xb65141235ee7e528L,0x8ca144bdf5c0f9b9L } }, + /* 19 << 49 */ + { { 0x5868449bc6e0124eL,0xdd65ffc1e68ad5eaL,0xe126665f4f577466L, + 0x8ade5cee2defe8deL,0x7c1cf7f07beddf87L,0x0e0e066a362c5956L }, + { 0xac2aff4e15563b47L,0xa28ab875620d1299L,0x91f67b3fd8caa497L, + 0x91bef53394fc08a3L,0x0fa27d9cd99918f5L,0x205b6c1f60b67bd9L } }, + /* 20 << 49 */ + { { 0xc1370daef6a58536L,0x6f2e5b37c56b0ae9L,0x5511d68292f6b6a3L, + 0x2e9e5034ae575249L,0x3e5a32f81d14bed7L,0xa346a86f75efd17aL }, + { 0x4f2510a60309fd7aL,0x689ecd74d0b1425eL,0x9e9bebe19f771e24L, + 0x20188045adc5b48cL,0xe49811b6b845230bL,0x420855ec5a8687f8L } }, + /* 21 << 49 */ + { { 0x705a9ab30aa1a423L,0xcb01466fb49830c4L,0x1db1768581a75897L, + 0xcaacb855e341f157L,0x9b13cd497a0d3c38L,0x119b4d47e177fcb3L }, + { 0x0d8f7c2639788712L,0xbda0f3180642bd4aL,0xdd4bd88bd4616239L, + 0x9a3ecf978df1b895L,0xd0d54caf4a6dc07fL,0xa7ed6bfb31810203L } }, + /* 22 << 49 */ + { { 0xe650e49abae1b94dL,0xb6b162e6e3199794L,0xdc706859b4ec0480L, + 0x28b618c24b1a06caL,0x0929a001403acdc2L,0x796dfd972da3aefdL }, + { 0x16389072ef4c1673L,0x600d8bd7fc94a4f5L,0xf003214de5f386a9L, + 0xa7af0499e62cbb48L,0x750a3b00de82bad5L,0x6c615b838e7dc8eeL } }, + /* 23 << 49 */ + { { 0xe1916cb4eae432e5L,0x81f3e48acc193889L,0x54d58685ba922a4fL, + 0xeffcc528bf11b76bL,0x2f70d38f8171c971L,0x547ce8ccb3a5669aL }, + { 0x3acd91b878e6d0beL,0x372dbf2c689c2913L,0x9fceb5bbd0aae543L, + 0xc601f9622830a977L,0xd55e74509f874dffL,0x77ff8ab4822878caL } }, + /* 24 << 49 */ + { { 0x283eec26d71543a6L,0x98fa08bea7627841L,0x269a83b827ad302dL, + 0x225f2f12bde3fdd0L,0x046fcf380130b3a6L,0xea733c1ac3ed9043L }, + { 0xf870f14d70aa08d1L,0x643d18b834391e0bL,0xf3e1d5f4847be772L, + 0xa9498223d0ed73a0L,0x6933ccf014b3babbL,0xc2439ae437f08f70L } }, + /* 25 << 49 */ + { { 0x503414d0f2cb5475L,0x51b9497cb24cbf9eL,0x57359dee2f4c7746L, + 0xee7125c3f3118a94L,0x2f0db706e4ea33d6L,0x885e8c3eddff7f63L }, + { 0x752f594b628432f0L,0xcfadea7779852e2bL,0x4f733b8ba2ba4b7fL, + 0x163c8c2e530f763eL,0xf95a7b57ff05a7e9L,0xd4768d242d7be01fL } }, + /* 26 << 49 */ + { { 0xb643f4e0f88d049bL,0x5e0ac1fb12682fcfL,0xeaf7874d9f981c8fL, + 0x9c2adfd2b1af779dL,0x9a7abeaddaa8c275L,0x09ad552124cacec4L }, + { 0x069cd5c40ead1646L,0x5186bf190a6157d1L,0xcc222a9396503506L, + 0xfeaa7bdebd29686eL,0xb0d65b0da7257c8dL,0xc31c0a8898aa227fL } }, + /* 27 << 49 */ + { { 0x5495f21c9fe88a48L,0x01f580ac590c1966L,0x1ad433ba39810166L, + 0xecbc67003a5187f6L,0x38d36c3bd4216887L,0x49653585e27b615cL }, + { 0x2a70a1d9e773db7eL,0xe36d967a63c1c048L,0x51cba60d26d15862L, + 0xb633839fd5a6b746L,0xa6a756a2ec1fc364L,0x37fef8d24cfccb6fL } }, + /* 28 << 49 */ + { { 0xb4b7651f5be1d45bL,0x0425200a7f0cf680L,0x200d12b48960be95L, + 0x02fdd1a14945b193L,0xedd70e3e27d046d8L,0xc1cc086a83f14e12L }, + { 0x1580e72b2629396eL,0xc87439dbf9ed73c1L,0x5debdf30a90c5128L, + 0x0b6c020e9fbe14efL,0x168da56a0149a0b0L,0xc66a4dbd79c58ac6L } }, + /* 29 << 49 */ + { { 0x6ecd9c41596b8890L,0xd25172fe210d9613L,0x1ce8abf872b97aa5L, + 0x355899d610faa675L,0x003b69adf4ddf011L,0x6736cd40ec2d1af9L }, + { 0x8069a0ad4f85ac72L,0x5c31d68b5836cfd3L,0x8e9486eaa5ec1473L, + 0x8e175c4a1468cebdL,0x58b3d2b1ffaf2f77L,0x4fd21681a17a3e00L } }, + /* 30 << 49 */ + { { 0x800aec84330b8e2eL,0x1a2c033e335837bfL,0xf1a91551fe6f6dd9L, + 0x326c42b21de7360aL,0x300e740b7b66f9d5L,0x53bcc70068ce95d4L }, + { 0xc9e225ac3d80f228L,0x64b2ad4e6977dfdbL,0xac863b0801f23221L, + 0x0517a648df11e5f7L,0xbf7aedcb68d11050L,0x2607e33777b3029cL } }, + /* 31 << 49 */ + { { 0xcb1955e44f4706b2L,0x0821d4663acaed1fL,0xbe822db07f8b43deL, + 0x3d11573f9b1c83a1L,0x6c052118201eab83L,0x294c5060dfe340d7L }, + { 0x994a4bde0644005bL,0xf1519f3258fa0552L,0x9077bf5bd4d0d39bL, + 0xebde1ff0e6204ea0L,0x58a68e09829130a7L,0xda64eb8596961bb6L } }, + /* 32 << 49 */ + { { 0x1afa6aa6206add5dL,0x66cfbbae150ea4c9L,0x07fb920b5d36da4fL, + 0x144d51f9291e774fL,0x26c2c134f40d87a8L,0xc8cf3524a932f1a0L }, + { 0x35bb2a425aeb0bdeL,0x5cfcc1dac4be960aL,0x5c40cabfaa1838edL, + 0xea0c05ffe2855f1fL,0x931ebb02fd525934L,0x31a7b78f16246fd4L } }, + /* 33 << 49 */ + { { 0xbe055fead42b36aeL,0x733a05ed819ddf8eL,0xa00fa0a15c9a6102L, + 0x0ed363273c0af634L,0x5b5a62b4d5970a32L,0x9d7557dfca954cd8L }, + { 0x30314f0c6daf871bL,0xaa7c42a96267b2abL,0xc5d1f0d6132bc62dL, + 0x77ac94df7ed26084L,0x0d256fdada34e1f6L,0xf0259d1caa4b4dd6L } }, + /* 34 << 49 */ + { { 0xf576c69e86ccb00bL,0xc870c07f5781803eL,0x91d4c0c6b1869e56L, + 0x9c2729397d940416L,0xdad33f73c4d0269bL,0xe2baf5b8838c9198L }, + { 0xd8bb9613218414e4L,0x5e9f7b67c980ca07L,0x1e2d4e63165079fbL, + 0x6ae5b17f983b3fadL,0x1e66b8380c24e22dL,0x80cdaec2136e0be8L } }, + /* 35 << 49 */ + { { 0x98cb12d93fc277f4L,0x81def3ee160b8743L,0xa1f07ebb11711fb6L, + 0xba17dd15a95b3ba0L,0xb25f1c78bc158f33L,0x1bb83cf27841e8bcL }, + { 0x57ad928abf49233cL,0xc94fd746bdad3f2aL,0xf7c716ae4a4c6600L, + 0xdd0e3117060a78b4L,0x85e8851a860764b0L,0x3342d974bce0d787L } }, + /* 36 << 49 */ + { { 0x2bc4e37a719793feL,0x1543af2aa68ceea3L,0xc99cb391aabdea45L, + 0xc890e546f0b8eea7L,0x8b75b91feb4173d7L,0x9d52d04bef46f637L }, + { 0x0929f25d878ff734L,0x7377235fb6c43342L,0x657835cf6eca900cL, + 0x7b752665098bb5e2L,0x320d09b6b8a61442L,0xec4f8182cf5b8023L } }, + /* 37 << 49 */ + { { 0xfc5f8feffc788160L,0x7d552625f73f48a3L,0x4eea435145c02498L, + 0xb5f5de5bf8f8af26L,0x78f1c499067b1610L,0x6e0d1b14eac18a29L }, + { 0xf8be2f6c052af916L,0xd8cee5668876af81L,0x99a27ec31577bd90L, + 0x3ac529d242919f4fL,0x1215428c7fc05dd4L,0x99ef01e450f67e87L } }, + /* 38 << 49 */ + { { 0x145902629d671094L,0x7fef49c166ce858bL,0x2a7ea540c2f21eadL, + 0x1226b04fc1d5a636L,0x4fb54e4e535efb9bL,0x6c51cdb91d72bed3L }, + { 0x94162e44938efaf6L,0x166013cfaf6f5697L,0xfa9495bddf95f9c6L, + 0xc05441cb0d7f8406L,0x7e5c89763a233ca6L,0xbc75dc6493fe8e42L } }, + /* 39 << 49 */ + { { 0xe1885cf128ed669eL,0x6e9f40dfb428b3cdL,0x412388a61626f8d0L, + 0xb8201f047cbcd192L,0x642ecfad70ba644bL,0xd43be1cb43c76bb7L }, + { 0xafafffc388f4bd51L,0x8c40e2787052eea6L,0xc1a84e866a4c8776L, + 0xf0201f292fe7075dL,0x132f80e4576af421L,0xe0831b7f4731dddbL } }, + /* 40 << 49 */ + { { 0xecfabd2742dbb68aL,0xad43a2c43eb546d1L,0xcf4e64ccfe2691c9L, + 0xe3889e258347566aL,0x48da354885b8c733L,0xcb7fe0679d9c9f57L }, + { 0x8c26a8d668223280L,0xc1e8ff623065705aL,0x181ca70a3f8db9f8L, + 0x25aa6450e758213eL,0xa4898f9169b2653eL,0x5e5c9fb4ccd8303aL } }, + /* 41 << 49 */ + { { 0x640b6946b03aa213L,0x6b99e84d00c068f7L,0xed4f1d2d99c5c461L, + 0xcec88724b20eaffaL,0xdf2b79a95dbbc32cL,0x2f7397054f3a1c5bL }, + { 0x1594a54946eb52edL,0x55f11aad39c4c43eL,0x0fcdb331f46500f2L, + 0x0d66be885ceb8dbfL,0x4d977349886dbbf1L,0x238f4617797d1b41L } }, + /* 42 << 49 */ + { { 0xfc8c7320721034d4L,0x48b389db60264280L,0xac246988649cbd88L, + 0xb7f52891a50bb658L,0xc0a812e50a7f279dL,0x6593175967fb2cffL }, + { 0xd31a77c6661ab439L,0xabadcea00ceb4aceL,0x201d98f6a3702dddL, + 0xcec1e83e7c9463aeL,0xc64e44fbc55e6856L,0x421f3e3148aa0d81L } }, + /* 43 << 49 */ + { { 0x4f0b251871a07c6dL,0xbfe652edaf3a2fbdL,0x5f68dc667bc2053fL, + 0x445df84f6040a7cdL,0xbdda2132180dc0a9L,0xd8627401d6c7a92fL }, + { 0xba350cb190cd2c73L,0xaf4c1e5929886ab4L,0xee8fdff2d677399cL, + 0x3ce35c6edaecf83fL,0x44df0a300f114062L,0x1b633b4647f29868L } }, + /* 44 << 49 */ + { { 0x48483f6af58ae2c1L,0x70ba34635e1cce49L,0x5f7a1c6d33907532L, + 0xa0fab701875a5f3fL,0xf2e8b0ff85d387e1L,0x0076aa68ff349689L }, + { 0x6e392b02747e2fffL,0x5e1ea320e788d577L,0xba705bd7713a0b03L, + 0x04ef192f2dc2cbc5L,0xa5a14eed38aef8a2L,0xf9682bbe30a268faL } }, + /* 45 << 49 */ + { { 0xc04f2cf540244a00L,0x00c90c3bb8dc0ad2L,0xac5b1060601d76f6L, + 0xad97c5c1a7ff84ecL,0x7919a06dd2328101L,0x62d5b7a4ca8a69c5L }, + { 0x75607148de5a2cc9L,0x1afff7f79a75fd24L,0xe62efc8083a22367L, + 0xad08258a10e05e36L,0x22666e06c0e4b549L,0x15f62c613f4c48c2L } }, + /* 46 << 49 */ + { { 0x751affadc7b8da09L,0xc052109dbd8e45d5L,0x7d11aaad87c14560L, + 0xa0410b2a6b690121L,0xcabad9853e10a103L,0x4d19bd3e785f1bfeL }, + { 0x8f32c6b84b6167a4L,0xb21d4ec297b4f546L,0x2e26df99c008f7c7L, + 0x63825597eb347720L,0x6a05b375afe39fc8L,0x19790b92131201a3L } }, + /* 47 << 49 */ + { { 0x149347ff7780729eL,0x076b4edc62e2dd48L,0xbf0de9d7cdcec866L, + 0x9d75deab8fa1e18cL,0x10931716eecb1f4fL,0xa8765dd3a385eb7fL }, + { 0xfd26f39c4d70651cL,0xc501caf48834c723L,0x1d263a83a65e5093L, + 0x57ee2fb96f709deaL,0xdae3dcc645091321L,0xba0665a906a60a48L } }, + /* 48 << 49 */ + { { 0x517d13b1784d0621L,0x2db4ef27d77b84beL,0x6e2e26866d752aaaL, + 0x95da9fa1cab02667L,0xbe8d91ad423163c3L,0x8f3d59dba69953c9L }, + { 0xf728b1d2d6e635aeL,0x5c4c177deeea663eL,0x97a900a82e75d9c2L, + 0x136c6b1e3ad09defL,0x4bab14a6dd8a2be8L,0xa4ee903025cf1447L } }, + /* 49 << 49 */ + { { 0x05f93697a5235c12L,0x434f91026943a0d0L,0x92696b701a4d3169L, + 0x0a9da44b8c3b1ee5L,0x327f9f79d295521bL,0xf605cb83afd8aa40L }, + { 0xe3bd4ab5d365fb37L,0x6c6a470ce984ea2dL,0x7ad01e6b392af60dL, + 0xbef2dffd5ff8ee6bL,0x4e56deb722efc2ebL,0x1b90570ae14ff270L } }, + /* 50 << 49 */ + { { 0x70718d8e333cd9e2L,0x858c880c6b03a371L,0x5b7f69a5926a3dd4L, + 0xedbed135572f420fL,0x740a21e6332aaa09L,0x665aff63fecf1e3dL }, + { 0xd884a3c1214490e9L,0xed70c29a63cdab1fL,0xc92dfa58786e274bL, + 0xa5395591d7fd529dL,0xacdf81ac3b95b61fL,0x07f801df40cb45a0L } }, + /* 51 << 49 */ + { { 0x4f863ad59230d44fL,0xd176d2764a099825L,0x4a6868745a43a7d8L, + 0xbcab3548fff3e8dfL,0x15028cfccab2c7e6L,0xad077a8874a91fb2L }, + { 0x015700d39eee3e32L,0x524ef9c7386e489aL,0x3be1771b60285f8bL, + 0xe4a5353cf9c33beeL,0x0aa0f2ab244ad683L,0x04e846f98a4c0ed6L } }, + /* 52 << 49 */ + { { 0x326a204790f55f13L,0x194d24db53017b29L,0xa26db785cd4368c3L, + 0xd58943e8238d7518L,0x8e06f8cc3527387eL,0xebc6dc9e071846d4L }, + { 0xbfc08dccc541e098L,0x3dcf0713e4fbc9a4L,0x44e9ba7869fedb43L, + 0xd867cf784fa012a0L,0xc618b2b88733ddf2L,0x4149fd48a737fd5cL } }, + /* 53 << 49 */ + { { 0x5c4c2183179b1928L,0xc54d315d0439876cL,0x07d22792f7495bceL, + 0xd378185e3bc32c4aL,0x8539aab65b31c5c9L,0xc72b1ac640dffb35L }, + { 0x46bb918a2e8d6ae2L,0x102c49f9e8a1d7a1L,0x7c622793cd2764d3L, + 0x5bbc6f023c7aafcaL,0xa41f383bcff71b4dL,0xc8a0e1a9aa99bf83L } }, + /* 54 << 49 */ + { { 0x323aad4991d6b8f3L,0x91b678c0f3d9154eL,0xc141e2424ce74f67L, + 0xb7c38aef65659ca0L,0x5b5f89b174a937e1L,0x739fad71abc55012L }, + { 0x315ed44ccee5f4fbL,0xb0731455360a61eaL,0x39235ff0ee93ce5aL, + 0x6352556fd203baf9L,0x3c22dc6a0ea06b93L,0x195638cb591bbfa0L } }, + /* 55 << 49 */ + { { 0x8bd5a15359ad0688L,0x827e82d8a7323070L,0x9ea55b3af70686e5L, + 0x511c8c3f34c2d054L,0x9364d28aa14a3c61L,0xc4dff9c461374139L }, + { 0x947c3ec9a39c01c0L,0xead11d42108440bbL,0xcc6d893569677f79L, + 0xb1d632710b9b4823L,0x2cec325e63b154e0L,0x45e97c3814a85b9cL } }, + /* 56 << 49 */ + { { 0x11b59f3e92acd14cL,0x188c1bb1d7aea098L,0x5cadf0a19365958fL, + 0x8fef04fcca0b1b0eL,0xbcb4d9fb0c274a5eL,0xe97eb41cba78427eL }, + { 0xc49f0bc55cf06378L,0x2681f12a281b669dL,0x200e9e583f796b81L, + 0x5bbea92b17964262L,0x86b3c15756db0039L,0xe4477c5eead482baL } }, + /* 57 << 49 */ + { { 0x1340e22c050fc1faL,0xd5cc5445bd062615L,0x03ad31601f494b03L, + 0x612919142af1b95eL,0xdb31a06d53705ac5L,0xf590433ad07ae464L }, + { 0xed52363421bbbd72L,0x1f032ad2f1cc7842L,0x212b1d5536a7164aL, + 0xc2cedab7dd973183L,0x29aeeee05e74ada3L,0x579984d8bb666836L } }, + /* 58 << 49 */ + { { 0xbbe5db83e13d34d3L,0xbae5ae959a8a3344L,0x55d2f0ac797d6e35L, + 0x75e78c017cd0abb0L,0xb757f72cbad96294L,0xe52493895d556f25L }, + { 0xc02293538e7675dbL,0xc363c5255c8beec5L,0x7ac23c0b7c87ee00L, + 0x9c5f22b4a7de93f8L,0xc6f0ea64d9644b5fL,0x3fa718d4d161f87eL } }, + /* 59 << 49 */ + { { 0xe8496c463f356cf8L,0x25b5b8742da1b81cL,0xa35ec06330efa9c9L, + 0x7497d85ffdaeb348L,0x312ad677e83f49d7L,0xcb5c346cfe8aece3L }, + { 0x19d7332d61cd4ebcL,0xb03dece0d0967141L,0x47dcb81af5455addL, + 0xbef0e70389ca68d4L,0xf7abbeb9c987400fL,0xbda81c65a1521da1L } }, + /* 60 << 49 */ + { { 0x535f3e4b86882341L,0x5af1c6322e22600fL,0x0403b6e0584a13abL, + 0xa64de86661f59ce9L,0xd22106f738501b92L,0x2932f808ab6ffd04L }, + { 0x8da4cc6e232967f2L,0x4b8fdd9ef3644670L,0xe8cb6ef31e0c51bcL, + 0x20b7b734230c6897L,0x5009176453d9339aL,0x5f5c8c67ca637277L } }, + /* 61 << 49 */ + { { 0x23e333d467232358L,0x3c2807bdea037380L,0x9439cc4626f1dc2fL, + 0x8c87dde53ac29173L,0x601b7245766897a1L,0x9e0b1a4559350e3cL }, + { 0x0818b6cb301db407L,0xbdc4584676b6fbf3L,0xeeca553431bdd954L, + 0x1dfabc033f9be3bfL,0xdf0415dc68851bd8L,0x33be32a67aa9dfa8L } }, + /* 62 << 49 */ + { { 0x8c9017dd4b4e4b5eL,0x02f435dd7b892b2eL,0xe9af9efd292e0f2dL, + 0xa32124c75c4d315dL,0x5c6fde76b31a390dL,0xf1fdcefaa6e46d3eL }, + { 0x5f39dbfe9e9e84b6L,0x574d647d19aab6b7L,0xd5a234cdad1a2987L, + 0xeab841c7dab59c81L,0x5155898db3137b90L,0xc52e9ddd06db2fd0L } }, + /* 63 << 49 */ + { { 0x8617f0d490660ff7L,0x00d73d108b35743eL,0x433e42d68a6ca67eL, + 0x575ecb9beab5cff6L,0x4c64bcddf258960aL,0xb8ffb7f32c23405dL }, + { 0xa98c06691261b0c7L,0xf2701f4a6b9bf7c6L,0x3abe44c41c68efc3L, + 0xdb5ac9cbf12c7a25L,0xf5b4616651120981L,0xf8058f7074d518f3L } }, + /* 64 << 49 */ + { { 0xcd92906c6d6ae962L,0x628356159807d881L,0x0d6929781fdc1915L, + 0x45d01a8c269d611eL,0xe7bd1e709665b00aL,0x086385349bcaa388L }, + { 0x8f189e882dd24299L,0x5f643392b82fb270L,0xca65bf16c633b111L, + 0xc6adc9c9d6f1dac8L,0x0df2c293a3c3381dL,0xdd6ae97d8388cd12L } }, + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 56 */ + { { 0xffdbd0eb3863db02L,0x8b8256832f57e10fL,0xc11acead35e7a3a2L, + 0x4998cf8c67833028L,0x8f3a346b844c7976L,0x0a9d872cdb9b1a1cL }, + { 0x8735dabcb98d445dL,0x93790d80305fa0a9L,0x7c0add49d267a01aL, + 0x2b46c913ffa20d11L,0xf2acef26d8ab2d4aL,0x71b701b93d926080L } }, + /* 2 << 56 */ + { { 0xe9d2a98a5133de8eL,0x37083b60b81b8b00L,0xf399325dceaf86aeL, + 0x03b17c888f161525L,0xd8ac35c984211b9dL,0x220837849050ca48L }, + { 0xa818c44bc9fab832L,0x8882bccee5aea7daL,0x633aaf35f8715b04L, + 0x5463e1b99d8829a9L,0xb18df52d84a820f1L,0x9d5ef891d096675dL } }, + /* 3 << 56 */ + { { 0xd54e2c7cac60496dL,0xc06d5e5d04cd50a4L,0xcb4105e8e60f7f59L, + 0x705db308427483adL,0xf73ba98bf2bff383L,0xa945611a0220e6e9L }, + { 0xc01c46b8d957e12bL,0x458897b7acb1f371L,0xf738dc0bfa3403e6L, + 0x098bc687d2202896L,0xec0c217a5f882e5eL,0x8f25af77a1f4eb13L } }, + /* 4 << 56 */ + { { 0x2615c78259ee4124L,0x4dc2824c76532b4bL,0x9c3b1d771c84a04bL, + 0xb6fc203fcb9f9e34L,0xbed65464c64f7846L,0x04f520a2eb004248L }, + { 0x5c0177274a58fd22L,0x25958482c10d9472L,0xb78c6666aceb0e3aL, + 0x18d3c188fc046f0aL,0x7f3e2f301baa9595L,0xa574f8cd8a2844e8L } }, + /* 5 << 56 */ + { { 0xc899eba381c2d81fL,0xb27267d6f3f0a431L,0x607c8629da55568eL, + 0x6b5472282b1dc1d9L,0x23232311c9c001ffL,0x207a2eb2488f8b85L }, + { 0x3867ac9adac37a28L,0xa36d14d32584a5f0L,0x7398c647a74488ffL, + 0xf6ed920fbe087640L,0x72beddc76319a571L,0x55c2cd826a244aebL } }, + /* 6 << 56 */ + { { 0xb7da79c625f8a53bL,0x6b950bdfd331ad8eL,0x3481b7b54aa36d18L, + 0x6efeaf88ed0e3091L,0xeb017bddc993074cL,0x8431a6d6529dd654L }, + { 0xf5177231bd069585L,0x6d753b103ce85096L,0x194d82d34ca26741L, + 0xeaeffe15adcd1650L,0x4dcec3d9af7758b7L,0xf5fdf6664cc2c819L } }, + /* 7 << 56 */ + { { 0x94bdc7f4a9810744L,0x464195daf045d859L,0x27e2dab0d654cb57L, + 0x1d4e1e537a491956L,0xa1ef570c31d5d099L,0x01cd21ee295f3de7L }, + { 0x8681b00db8249038L,0x17c31bce93781b71L,0x4324e90c6a1b5748L, + 0x44f9324c1222e554L,0xe30ba10fffd53dd0L,0x2e5817a8b48eeef0L } }, + /* 8 << 56 */ + { { 0xa349bb66c8fccaa9L,0x7888755f31a53ee7L,0xa6e1d891c18d3750L, + 0x9985aa4dae8d2bfbL,0x8baec9ae31b33078L,0xee68295a98750e94L }, + { 0x0d834bf8d6ddf305L,0xab33dff39762126cL,0x0c22faaa0c51d098L, + 0x32404042b887a10fL,0x31f6a614248bed32L,0x311f86301ce0d662L } }, + /* 9 << 56 */ + { { 0x5c95cf080d844b0dL,0xe09a8352c98650c9L,0xc1b106c5d089058eL, + 0x2b3cf101eb0c6107L,0x1993fdba3ce6ee18L,0x7234eb6425fc4d24L }, + { 0x8345acfe05f46dfeL,0x07fccf68a2d87d38L,0x14494cea85da7852L, + 0x8737500acecdd9f1L,0x72b1490ca39068ffL,0xce28271acfa4469aL } }, + /* 10 << 56 */ + { { 0xc872326f55c6c00aL,0x6a5f0fa3f912decaL,0xf4ef0ca5a7d1bdb1L, + 0x1dee685b37dc6bebL,0xdad4cf52f1b09b88L,0xc7199f0277f1db84L }, + { 0x7099ef00a3f00491L,0xd8fbbbfa6d8804e3L,0x2a00b8e50ae1e360L, + 0x8a8c9d03fe9be5dfL,0x06e0585b8b1faf6fL,0x19542ee7ae29c502L } }, + /* 11 << 56 */ + { { 0x36cad867e2aa1c5eL,0x7ef21e51317f9078L,0x68efbb84c82e925fL, + 0x973b36769fe751e0L,0x09c4e0c1177d36a7L,0x9c0b7e048a753c5eL }, + { 0x8414cdab15ccad5cL,0xeea2134ed50c1678L,0xd9c1dae8f6585d5fL, + 0x82fd04ab4e5c3d96L,0x868cddf7da3812d3L,0x32a65aeafda07e68L } }, + /* 12 << 56 */ + { { 0x73292e6a60720858L,0xe046a79953160855L,0xf74d56c9ed3b94c1L, + 0x0e371167c67863e1L,0x19b3a9f43f6636cfL,0xe624798d898a25b0L }, + { 0x2ed1fc4dfde2cd6eL,0xd9a7ab519fd15ee5L,0xb6b8d551c487b1cdL, + 0x9fec705ae8936c54L,0x4b779dde1a50e094L,0xfb5100c2c3a4ef5bL } }, + /* 13 << 56 */ + { { 0xb35a7b102704c525L,0x8a77fa5b44276cbcL,0xb4a9cd235ff1a12cL, + 0xc74a017c88a37997L,0x84e26eea9af37476L,0x8a6b8c0e7bbf737bL }, + { 0x90ab7c948f05bd3eL,0x31749075464f3a2cL,0x32f7873c1dcfbd25L, + 0xc0af73d343bc2054L,0x556c4798171d825eL,0x2c84b5b6081542f8L } }, + /* 14 << 56 */ + { { 0xa5907e5c59ab2507L,0x12b86e04cf7df60eL,0x0a14bed18af4bc50L, + 0x462863b20c11bac5L,0x98dde284126958dcL,0x8877e7695625eb29L }, + { 0x869f7214f4fe19e5L,0x29867e51ec0f8c1aL,0xbf498bc078b85f03L, + 0x9dda400e8973a94eL,0x8d8b998ae6e51b1aL,0xedb0957c557ac00eL } }, + /* 15 << 56 */ + { { 0x84b6d5143b7d43f2L,0xcb84c823afb7a2b9L,0x892e8c4c56d2b161L, + 0x52ea7426214fdc0aL,0x07f3d57679763557L,0x9f95fd585a828bb3L }, + { 0x2c7f03d550e14019L,0xab723de7d7eae7b3L,0x4c08189317f4ea6eL, + 0x64cc5bc0ec367246L,0x73077b5ddf11c3b7L,0xfa34b540e08eb4bbL } }, + /* 16 << 56 */ + { { 0xac6dbdf6edc9ce62L,0xa58f5b440f9c006eL,0x16694de3dc28e1b0L, + 0x2d039cf2a6647711L,0xa13bbe6fc5b08b4bL,0xe44da93010ebd8ceL }, + { 0xcd47208719649a16L,0xe18f4e44683e5df1L,0xb3f66303929bfa28L, + 0x7c378e43818249bfL,0x76068c80847f7cd9L,0xee3db6d1987eba16L } }, + /* 17 << 56 */ + { { 0x254ed267050f46f1L,0x36786ff864daa83cL,0xb4a89efc802a3ae6L, + 0xe0027b3486b77d59L,0xb7147905f48d0de6L,0x00733ca710cf7c60L }, + { 0x87efbe387b3ab776L,0x3db10898de9730f4L,0x61f21e1386b7a40dL, + 0x5541873648455b6aL,0x0de378f9a88587deL,0x42dead7a766d18f1L } }, + /* 18 << 56 */ + { { 0x42b8ef51e15ad876L,0x498886e5082e110aL,0x3144e8c964edbd73L, + 0x4b08cf86f79e6724L,0x42d06d53ddfdb6a5L,0x4c9dce336d8b1f33L }, + { 0xbb8913ae4be29e97L,0xe944c922166fdcc4L,0x83913b963c494e9bL, + 0x529d57ac633a0018L,0x632a7cfd242e7d9cL,0xf0e2434dd9b51d08L } }, + /* 19 << 56 */ + { { 0x74768ab044ff52cdL,0xa590ac7eead09902L,0xdc408c53f52c0f5fL, + 0x614a22d6f853efbfL,0x61f391c425126427L,0xb61adcfcbf462fbbL }, + { 0x7b753aaaaffdbe78L,0xce12b2247bea939dL,0xca21f73e95baf09bL, + 0x2a82915e43ca9ebeL,0x67ba04f57936a38cL,0x1c1964f1616b0b87L } }, + /* 20 << 56 */ + { { 0x4dc628c67cb2ec48L,0xc896f99c0cb1e9d2L,0x399ac2e85cc6134bL, + 0x5ac36de184ba73d0L,0x66a334a3e1803832L,0x394af7ea59b770c1L }, + { 0x3df19e55b46f793eL,0x97aaec84bf770a95L,0xf52068b8f8c54408L, + 0xb6f7649f49e05f0fL,0x54d8db0583360826L,0x24748fdf71af722fL } }, + /* 21 << 56 */ + { { 0x68f4dd4956c29111L,0x391ac9910dac9352L,0xb0a8a54206dc9d58L, + 0xb5058ed8fbe70330L,0x8b5e9d4076b593bfL,0x769fb99cd7f2b261L }, + { 0xcdcbb60ec67cce8aL,0xe01a5d5d75da36dfL,0x7e831d0ef7c6e5cbL, + 0x0f6bf54bccdeef00L,0xed49ad3998ba4d8dL,0x8d512c83614d70c2L } }, + /* 22 << 56 */ + { { 0xc1910b2545b4f6e5L,0x54c6ee8489fb712dL,0x80b6fd47f5747ba2L, + 0x3d81e7efd6d4f856L,0x8b9e87418031f1bdL,0xc591d451f2327316L }, + { 0x4830d9971e0f1c1fL,0xeabe29bd86e92024L,0x2f2053a1b8c68d7eL, + 0xff4eb9e879d00ad6L,0xa0c93249f4b4cd89L,0xe127d9d3cb9e0761L } }, + /* 23 << 56 */ + { { 0xeb947df3492d73ebL,0x5474817b0d32c2ddL,0xeb01bef7a9440e93L, + 0xf604581d8085d1f8L,0xf69daa189f69ec8aL,0xc79ac48e71748716L }, + { 0x5141c75ad4beef28L,0xf7dfaf89901c44a6L,0x7bcbe4812e81ed85L, + 0x57ed0e6f0c5a4423L,0x7cf189651cec85a5L,0x8ddfe8a5beef12b0L } }, + /* 24 << 56 */ + { { 0x60ee08b46bc0b979L,0xa31cfd961aba7f4eL,0x66c05a6358bedf51L, + 0x2ae6ec3854df9266L,0xe7dbda332771b08aL,0x44455d312a09fb28L }, + { 0xaaba39171cec98a5L,0x9b2b12258cb543d0L,0xf47a9cd16af6495aL, + 0xe207f3aac6cd8a16L,0xf98952878ae828b6L,0x37e2475725844053L } }, + /* 25 << 56 */ + { { 0x7c8137d8f93723a2L,0x78fa2e03cf552846L,0x3becd2627d11977eL, + 0xdbc8e9b34e9a700eL,0xb2c7798d20decdccL,0xecae57179523bb6dL }, + { 0xc0fec0677fa2f633L,0xe270b10702aab6a8L,0xda280b374dcc797bL, + 0x50a163b86c42945dL,0x4a3fd6bd363e44ceL,0x0aa7e33d38bca4e6L } }, + /* 26 << 56 */ + { { 0x19c7f098a693d0aaL,0xb79d84244bd22a29L,0x19d91d12a9b3c2ebL, + 0x2ae96bfdde735665L,0x2f9c9a773d8a85bcL,0xa74bdd46cbab80f5L }, + { 0x25a2486cdd9f70f0L,0xada155c9754513d5L,0x8aecd7db4c3e9494L, + 0x9c3951ad2cf6665eL,0xd35780d44a9ec29eL,0x064983964cfd7821L } }, + /* 27 << 56 */ + { { 0x23407aac0834f890L,0xad7b7b5599bb065fL,0x3254aa7e4ba2b4ccL, + 0x37f37fd1663f9213L,0x0c72c3111c5a51d4L,0x6e6df84b9989820bL }, + { 0x576a320e1ae2f321L,0xa5fc617c3c62888eL,0xc4f1be4df6c40362L, + 0x01b21892dbfaa5b3L,0x6fc0442390b9a5e3L,0x22a70c8791495c30L } }, + /* 28 << 56 */ + { { 0x365e1382183aee81L,0xe9f2245275d289c8L,0x543cb5c7b70962e2L, + 0x853971711cea2e37L,0x8b31cf530adfc82cL,0xf9a458bf3b67c705L }, + { 0x13b1cb3334a9b3a8L,0xa4325b403732f6b5L,0x39e997ba04e9df8eL, + 0x24c0d6ebf1d542f8L,0x9cb3f1abd82901bbL,0xbbaef37a4cb34763L } }, + /* 29 << 56 */ + { { 0xc4881080b08dd648L,0x21869be8f1fe4e15L,0x63e158b112501ea3L, + 0x48a909ce32408693L,0x77fd2cf062b24495L,0xf7d1e134db9322a5L }, + { 0x4c02c8bcbdb19eedL,0xe03cd00e8a20b335L,0xe04271c530632562L, + 0x549e5dba603e1681L,0xf01b38f95503b61fL,0x244c81920b3fb785L } }, + /* 30 << 56 */ + { { 0xb423030c4b0c7247L,0x242d409f149f8cbcL,0x6094885e9c1f518eL, + 0x6d299dffe04d97ebL,0x152d05bb09903069L,0xf5656895fe235dddL }, + { 0x801e7f736b22ac0eL,0x73aa6df46ba6dc97L,0xba498bc0d66e5d8cL, + 0x8054e17d36b8c78eL,0x241bd2e21137fdf1L,0x8e79a943b97dec15L } }, + /* 31 << 56 */ + { { 0x94e617abeb64269eL,0x39aef936b410ae02L,0xdbb744c325fcc976L, + 0x5072bfab38a5b366L,0x3998aefea3f5d715L,0x0bdbf555a74e281dL }, + { 0x50d2feece24dd239L,0x835925ef46324c5cL,0x53c4eece7a4dad08L, + 0x340fef207c358d83L,0x9e2189da30f04396L,0x2bc748d727e322cfL } }, + /* 32 << 56 */ + { { 0x1238e097ae658422L,0xb4631ddb568df55fL,0x451254e7f74c5c50L, + 0x238b16d28805813bL,0x23987b28925e7a6eL,0x93b72e2d2a1a10bcL }, + { 0x944c784d05e44b7fL,0x7d70fd098c8e3120L,0x6bf1ab2aead45716L, + 0xd5f8f0e631c04205L,0xac062526a10b8881L,0xa1a83cf0fe5505a8L } }, + /* 33 << 56 */ + { { 0xe1e05ff89ea47326L,0x88219a1ffbfc7f61L,0x9cbd0b387dcd3008L, + 0x751d03847671a68eL,0xd73ed70d28e0387fL,0xf66f9cfea9485256L }, + { 0xac68aae1ae153e0cL,0x92eb6542e81b1282L,0x9617d45464541adfL, + 0x81b4d94a9d489e95L,0xafd5cd4620f31ba0L,0x35700392e5a38941L } }, + /* 34 << 56 */ + { { 0x52296be3b71ea9c4L,0x82b05a43424cadf9L,0xb6d329e8842699e3L, + 0x9dfb91bf9370f2c1L,0x0188b738994ecc71L,0xa9a7b03b5ce8b100L }, + { 0x99198b2a25c33035L,0x772795a7e21895d5L,0x37dafa4c42173e01L, + 0xd37f03933ab27d91L,0xf3500a7d2afad1f3L,0xa433b5fd87eac06eL } }, + /* 35 << 56 */ + { { 0xdc193cb5243a97bfL,0xe367f27ff5715184L,0xc4bb95c6fd9120c6L, + 0xd2bd176bbc5f7ba2L,0xf2c0f86de966c1deL,0xc69ab26e811e70cfL }, + { 0x95756460e87c55f0L,0x6b62ab136a59c832L,0x6e971c6c128448a0L, + 0xca72482e91ea44a3L,0x2602d4795dca0f8bL,0x8dadd3e25519433bL } }, + /* 36 << 56 */ + { { 0xfe0553be23246f68L,0xccc1d774d8ad4128L,0xbec668d8cc155edaL, + 0x7a80e9b44231506cL,0x579cb5f42aa1740aL,0x3a61b84fd8b35a2bL }, + { 0x0478c05ba3b519f8L,0xf518ac09acfe39aeL,0xabc15e9076c956e6L, + 0xff35db67dd55d268L,0xbe066679bdbba89fL,0xf7385df12062b845L } }, + /* 37 << 56 */ + { { 0x279d7ffdfc12078dL,0xeb14155eb8f302e9L,0x5f1b11e165b3c14dL, + 0x08510b461bd36b3fL,0xa7f5b2ffc9d73b4fL,0xe5e831557aa09e40L }, + { 0xbed67135cc3d88d8L,0x7b2775f7017a43d2L,0x9ce22ff24c58cb64L, + 0xab88d04849ede1eeL,0xcac13762da63daa8L,0x70662331b1dbfc4eL } }, + /* 38 << 56 */ + { { 0xe4f7022200a8a9adL,0x8d1bbab7d42fffcbL,0xe024970e368ad5edL, + 0x231ef631b4c0c9f8L,0xb47ca0386760b411L,0xe1f297ff179e6d44L }, + { 0x2e5ec77d3e071736L,0x90e20be915b29c93L,0x33961b6dbb7e7237L, + 0xa854df5b42176851L,0x67d223e4a8f4bac8L,0x5464a46f0dee39fcL } }, + /* 39 << 56 */ + { { 0x525a553b32230b65L,0x7bbde6b816bb6a4eL,0x2f5bc6d229f12292L, + 0x5d86858045fbcff9L,0x6ce4fb249f932964L,0xd7cd175098e05ef6L }, + { 0x794b0248e1366d8eL,0xa37afa66332098a0L,0x2dcc1888d9aac70cL, + 0xa01ba83ec15b9fb8L,0xd34ddf851df4b59cL,0x92289e954f829510L } }, + /* 40 << 56 */ + { { 0xdec879d51c9d09f1L,0xdfa9e7d61b371576L,0x8c705c7937fb3410L, + 0xd770153e1f2a02bfL,0x208fc8f18043ba69L,0x58aebe6e25aa3453L }, + { 0x191b69e512941f03L,0x27dbb050d7966e0eL,0xa5196bb7d16bc20bL, + 0x5b6bae47f22b30b2L,0xbddcabda8ce7b419L,0x6e3cfd373b9f5a39L } }, + /* 41 << 56 */ + { { 0x605d4b83330c07f8L,0x4dbe47646a0ed45fL,0x1e715823d7e4163dL, + 0xe337a67dcea3306dL,0x55abf0684f18a604L,0xaaf69d5ea9f57370L }, + { 0xddd09e8129784840L,0x17fd42b9a4fff5e9L,0xe99859e55acee616L, + 0x41d691203b927ed5L,0x35cc99675168f505L,0xfc311c24431d7d60L } }, + /* 42 << 56 */ + { { 0x415f7f0da581c54dL,0x67c678244509f31fL,0x36fb92eb988f449dL, + 0x22d41b1a94181fe4L,0xacc68410df896026L,0x4a10e46f9ccc4df6L }, + { 0xf805a1191969cf2dL,0x7230a26b32ad355cL,0x9d200562e9abd845L, + 0x2db90c3b5cb55349L,0x80b59daa29bcc42cL,0x81272ebc53d32149L } }, + /* 43 << 56 */ + { { 0x6aaf15f27756bcffL,0x5391bc009b645589L,0x46cc4480a6fc61a0L, + 0x6fde9d53293d676dL,0xd6c35628d7618399L,0xdda13a0853daac23L }, + { 0xb6e6c20c0fe7995dL,0x32eb3468d8d41d55L,0x8927d508c19c5995L, + 0x3907eeed3c229e66L,0x509af79f27972057L,0x8a7f44f750e2f170L } }, + /* 44 << 56 */ + { { 0xb91ffd21c87b3fe1L,0x0fe8389b34fe2825L,0xe22d45d74bf4c8cdL, + 0xb575ae4cd6d8308aL,0xa7fa552e82994ba8L,0xfb67a86fecb08870L }, + { 0xc3bebdf8e6dabcb1L,0xef18b357b5bcf114L,0xed518499a4b8eca5L, + 0x0fec83c5df16ed99L,0x5d353a5856b5649eL,0xc858c1d1cec900e0L } }, + /* 45 << 56 */ + { { 0x7a65d2660d85e627L,0x96170bb90bc010a3L,0xaa6e0055da030ad9L, + 0xa75ab280ff4e4a8fL,0xec14e68c0be864a3L,0x05424b9cc17723b6L }, + { 0x9ed54bb218ca85d6L,0x035edc14b78b34bbL,0xc116914929617416L, + 0x0a00e0086cb0d801L,0xba40f1207d4a638fL,0x54b1e8cc9d8bd0e9L } }, + /* 46 << 56 */ + { { 0xbbab4ab54c88db57L,0x68dbee6f9ee9558aL,0x31b988e140da802fL, + 0x9d117c37e90b2221L,0x443ae099025b66c7L,0x8568bd6f2538a654L }, + { 0xf806d8636720df01L,0xe390adf2b649ad8fL,0x7851f8e039d1c315L, + 0x8185ae1a5e650f1bL,0x3dccfc4c9b562532L,0xae99ae835f427c40L } }, + /* 47 << 56 */ + { { 0x99542ca7564c7ad5L,0x682eace49a96f25dL,0x2d01b2488d933a6cL, + 0xf96916ddb8604277L,0xad3259d12e4d7419L,0x9085251fc26981e5L }, + { 0x848219363d2ec970L,0x723ea6a5392351c7L,0x3fae69a55e5448c8L, + 0xf6eee650dfb03d49L,0xe2e1df1ef8c58715L,0xc603b61f1a369206L } }, + /* 48 << 56 */ + { { 0xcbbd8576c42a2f52L,0x9acc6f709d2b06bbL,0xe5cb56202e6b72a4L, + 0x5738ea0e7c024443L,0x8ed06170b55368f3L,0xe54c99bb1aeed44fL }, + { 0x3d90a6b2e2e0d8b2L,0x21718977cf7b2856L,0x089093dcc5612aecL, + 0xc272ef6f99c1baccL,0x47db3b43dc43eaadL,0x730f30e40832d891L } }, + /* 49 << 56 */ + { { 0x7f3a3e5f4447ed08L,0xa6302f7bf94d49d0L,0x94fd2ad33b2abc46L, + 0x98ffc01fe4249c1dL,0x6f3a53bf8db4549fL,0xfbae12df25566cceL }, + { 0x63fc92d3c2e84d15L,0xc355b46c4f5abdebL,0xb50b43a05678d0cfL, + 0xf4d4b0b15681d628L,0xc9f11d63fb3bac7dL,0x444b748cda461eb1L } }, + /* 50 << 56 */ + { { 0xafe9adafc9845a07L,0x484a9eb9df6a1305L,0xec32f0bdb0f111dbL, + 0x742b41cddc7b100cL,0x5a7ea89d23c5f849L,0x1ea8801fa298aa82L }, + { 0x183e1750cb001f26L,0x66ec5daa49da5bbbL,0x8071ff322d05ab57L, + 0xaea9e694e1944e0eL,0xc993754437b85438L,0x2c2467b4faaf4f22L } }, + /* 51 << 56 */ + { { 0x38f87acce602c278L,0x72c79590515854dfL,0x9d466a765e7e2f6dL, + 0xe5f6704772081935L,0xb4b56288ad958812L,0x7f4d9e1395b08242L }, + { 0xb38d0ddb962f0f6bL,0x969d4327e5f76463L,0xf7c7c799f6ac01f8L, + 0x494066673e6ff230L,0xa81fa10dc7e9c1b6L,0x2fcf26bf8093c2d3L } }, + /* 52 << 56 */ + { { 0xcca6e9cfa754256bL,0xfdd79280347723f7L,0x8179d6f52d69c6bdL, + 0x156a53fa94cc8567L,0xb819d70324655f28L,0xf86872e2ebfb198bL }, + { 0xb158e73939ccd668L,0x655db8248de67826L,0x54399a79c621cf3aL, + 0xc55900d498a09c9dL,0x5423edbf20278b3aL,0x06a625b280ba89cbL } }, + /* 53 << 56 */ + { { 0x0f152d69869c4f68L,0x0ed4205a9f0068fcL,0xda68af4f25d4490eL, + 0x715fcc60745c00afL,0x70ab559aad63dff1L,0x7d0a7b6a9b8a37ebL }, + { 0x82ab7a068bca8498L,0x4f012fb4297d954aL,0x8b139e6ed5f6a4b7L, + 0x597316e4b856ac26L,0xeb64b5894387367aL,0xcc92eeabbacb7e74L } }, + /* 54 << 56 */ + { { 0xb53560e968fdcf87L,0x4ed638bd3cbd0887L,0x57f3f38f6080d1cdL, + 0x50370e0c1e4e3ae8L,0x14c87fad184a1ecfL,0x3d06f78d0af7b2ceL }, + { 0xd9370e24fd595621L,0x1e462483c9fbb559L,0x1ee5d81ca0aa5c0aL, + 0xdb2524557419564dL,0x782ba91b57585be7L,0xb2d14bcc5c431c72L } }, + /* 55 << 56 */ + { { 0x9cb9de6fd62ebed6L,0xb7f23b1916c6d571L,0x69b4a8dfa8b307b5L, + 0x78a7f74e19dc7e39L,0x423405152f47c94bL,0xf1c2a5bc31ff2d82L }, + { 0x98c1c3f7b145387eL,0xdd9d24d885e635ccL,0xeaaececa07397bc4L, + 0x6bf6a8469b0cd4c6L,0x68052950680dbd05L,0x81a071b60ce07df9L } }, + /* 56 << 56 */ + { { 0xf3fa8bec0c61d5a5L,0x98f772fc0dedaa77L,0x45a382161146d42bL, + 0xebef5d4a58821ebdL,0x21498af30c1f0e6aL,0x3d8699144758014aL }, + { 0x6f2276ecb625c7e0L,0x68d6a144fb55d708L,0x0bc836e0ad56b494L, + 0x72b6d8850f58ef70L,0x0e0be2887bd7c1d1L,0x70549a879c277d39L } }, + /* 57 << 56 */ + { { 0x39a445d2dbb2bb75L,0xda2a211b1ac42cd1L,0x934bee9a8e4cf8f9L, + 0x5d0dde6a24801bc1L,0xb2d4261d23da4ea7L,0x5fa9059a7187cde8L }, + { 0x49298bb651f05f9aL,0xff0c4a0422a7bee4L,0xf466232da6a29be3L, + 0xff2e157a995c1904L,0x3a4ee4537b31bdffL,0xb4a736d7e41f6eeaL } }, + /* 58 << 56 */ + { { 0xaed55c123fa96c0eL,0x8f90803f6e08adf2L,0x349e5807015b7cb4L, + 0xdb3f05e314656b3cL,0x9289bbecde8b2d9aL,0x3cad12e0c7f28356L }, + { 0x7a68fa54959fe89aL,0x2e7135d0a77f956fL,0xa0285cbabbe35884L, + 0xc547ffe7131ab269L,0x82a902bebe33b425L,0x5a793a790c71b02aL } }, + /* 59 << 56 */ + { { 0x2bb2a929c645c6eeL,0xfc6cbd471e651728L,0x4ec3f630c07af98fL, + 0x118231588e4a8ad5L,0x99a2b5de1303f68aL,0xcc280b182ec9b8f7L }, + { 0x3d7b406ad7298d55L,0x63941bceb9f83957L,0xfeeb132c463a64c6L, + 0x243a2e2bf76a6c8bL,0xae72bf2fdad18d64L,0x774423431987a4caL } }, + /* 60 << 56 */ + { { 0x06de549d78dc1526L,0xa27fc0c1f52c5766L,0xee5ff3d8e9485b1eL, + 0x7af2fbc64bc530dbL,0xa266d6c810f9dc58L,0x866abeed8bfa4d74L }, + { 0x50356d7fcb7c7018L,0x4ae502e07c962af2L,0xb98b449cf011990cL, + 0xfcc8446b59e8535fL,0x25964ab0088776ebL,0x3848aba2ab6cfe8eL } }, + /* 61 << 56 */ + { { 0x9f2c62cbe14a2c5dL,0xcd182e386b113f03L,0x2275ad4f525a15aaL, + 0xd5b7d1d9eb373133L,0xd3c47b9b07929822L,0x60b043cd8fa8e8e0L }, + { 0x603a3403d3958f57L,0xefa36ad67b79c263L,0xfe33dd9f3742ac39L, + 0x30f40b3bb249f9bbL,0x9d2902d20a3b2e7fL,0x173f7d1a899684f0L } }, + /* 62 << 56 */ + { { 0xdcbeff5bf33bdff0L,0x963ae65ee9684a3bL,0xe03586882bcd272bL, + 0x756695068942f107L,0x14319d19262e422fL,0x5c0ef45a2265b294L }, + { 0xeb897bd8a9f64203L,0xa3b259d742b1640bL,0xdc34ee2dce66355cL, + 0x2fab125eb4e13438L,0x1b93a820443420b7L,0x79c46f97b4ba8382L } }, + /* 63 << 56 */ + { { 0xafd8cb2006e55b9cL,0xc88f38ea2530a11aL,0x628d10bfe4efe221L, + 0x00df0da42a8d983fL,0xed45860508a2fce0L,0xcd7882b86a01efecL }, + { 0x93ebd86c7efcbf7bL,0x578f9fe7e3db504aL,0x3c584008aa5e83e8L, + 0x5bf38b4ca8368754L,0xcb4a9cf905c05ca7L,0xf77ab684c634f28fL } }, + /* 64 << 56 */ + { { 0xac92ee1537d83369L,0xc968c187fecec65cL,0x29a7ca876e7a3265L, + 0x0f2b7e7a8456c9afL,0x7471824e9754326fL,0x498687bf364d2ec8L }, + { 0x86d8aacd3c6ee351L,0x01ee6823f6f41e85L,0x9805fc881d79f7ebL, + 0x377ac3a40040547dL,0xd39215d461b4e90bL,0x2547416e4c5fd81bL } }, + /* 0 << 63 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 63 */ + { { 0xa10292b907a6fbf8L,0x292c1a203fa6235bL,0x7a36f18f73ad7a1fL, + 0x8b2c7b0c5897b11fL,0xf7b9a272cb664c61L,0xb6d366af8f81e22cL }, + { 0x3b99b2118e342bbaL,0x03ce158bb06ced2bL,0x3af1175d001db74bL, + 0x526f08467159cb8aL,0x6a3c6e1febde4601L,0xfad5963b8c232eacL } }, + /* 2 << 63 */ + { { 0xa54768dab1b43eefL,0x13e41f47e14fda22L,0x774df203faef6863L, + 0xf795a034bd7471b3L,0xf0958718b47de2e9L,0xc92f7888e1160cffL }, + { 0x86ded97b0146c790L,0x015918f5480a4b7bL,0x05588920424e8459L, + 0x37455914eecf8b2bL,0xe7d3df1fb968a6faL,0x07a0ffd6bad0719fL } }, + /* 3 << 63 */ + { { 0xf13f55e619f6ebccL,0x63720df2a266b368L,0xdbcc937f3bf1a890L, + 0xd3faff625f326fa4L,0x8b33bae9019730d0L,0x7879782af9961795L }, + { 0xec7e75bc93735e44L,0xfbbf6d225d5702d0L,0x26b6e1d53bc2ddc5L, + 0x00345bf714941d10L,0xdd719676a745c77cL,0x2869b11881c523dbL } }, + /* 4 << 63 */ + { { 0x2566021f98d23f6fL,0xfb883e1234ca97caL,0x34e047a5d9f51b69L, + 0x0b50d91df8efa646L,0xc2bbcbb2971f584fL,0x4136f0e40907c91cL }, + { 0xa7ebeb0de735cc48L,0xa7d1bedce113c8faL,0xc04d9a073f5c962aL, + 0x95c155e53ff74a2fL,0x923c65a53df0749dL,0x10d5f81227ae35d0L } }, + /* 5 << 63 */ + { { 0xc08cf7a1a128747dL,0xeb34a1c02eca6776L,0xff6e7cdfb596491aL, + 0x17024305eddd8bbcL,0xab92b54cf3c46414L,0x2a995b7759134eb8L }, + { 0x97525904e48cb259L,0xeac065ed1e1da01aL,0x16cab74a14c5bf38L, + 0xcd3e2516c14eda8fL,0x3ff38094a8de7a9eL,0xb7340214359d653eL } }, + /* 6 << 63 */ + { { 0x4d37c2663e7a369aL,0x092dc32c3ae62c55L,0x566da2e928ca9d67L, + 0xa9771c1a79beb236L,0xaf6b97a976f801e7L,0x3afd62e771259358L }, + { 0xc23a5e32cd541e77L,0xae4c90a301660ff9L,0x3f3a233b1911ccf2L, + 0x93e4664cfa3b3aceL,0x4bdc14832d4c5f5cL,0xfe03d3c36abf13c0L } }, + /* 7 << 63 */ + { { 0x9649468631b26990L,0x55222e9fe3fd62f4L,0xc8eaba742ee74b8eL, + 0xfa43617834d198efL,0x475b688e892748f5L,0xc6eb426541b9822dL }, + { 0x535695bebdae951fL,0x45e69033e909cce4L,0x40354e72b1829154L, + 0x1005ee6d5c56c3cfL,0x61b36a754a3fec51L,0xae644f3872f2f56eL } }, + /* 8 << 63 */ + { { 0xd5469c7becee6e87L,0x056180bc33a4c917L,0xf881ca21a16caa7aL, + 0x221de182e6cc7f39L,0x10d61ab531378723L,0xfb763bd9520c9660L }, + { 0x145214cd0d6b1541L,0xd9f7ff2dd70223e7L,0x9fce59e30cb1fe69L, + 0x2e6e77fa3e299fe7L,0x3a0cf652d5af78cfL,0x50cc42c53e852159L } }, + /* 9 << 63 */ + { { 0xd2536452b8da85a2L,0x5c15dabe331197daL,0xf5a89366aecccec9L, + 0x8f998baf2d8352fdL,0xb10e6c80f56159d2L,0xf61ceff379eb9affL }, + { 0x05bcb93d1c4283a2L,0x4e1abc521d8cd941L,0x898c9a49b46b343dL, + 0xcf352f3c6e423ae6L,0xb1db207f6fd42c89L,0x08f36a1edab295b4L } }, + /* 10 << 63 */ + { { 0xebbe18b7ed31fabaL,0x046e248dd74971d3L,0x3ddf5a2a0b24f97bL, + 0xf9a400c262fc6124L,0x9ad9b0bc6b03b73aL,0x9fa97c56153c8fdeL }, + { 0x1b6477da00b73ea7L,0xec59f64a21b2f3f3L,0x4428712895306955L, + 0x4b5db01db9e77579L,0x237edf0bde05e0d1L,0xac904b01855332f5L } }, + /* 11 << 63 */ + { { 0x6a37fc505cf708c5L,0x8de4dd7c30497ceaL,0x6978648161b8bf39L, + 0x3cb303375d7362eeL,0x0e24d09237ed25e6L,0xd474f3dc2f69ce20L }, + { 0xe15d98a0edb40541L,0x5e4a87c91466f464L,0xc3cefc9eb68923cbL, + 0x66f10920f22c9de2L,0x3c18f9ea9a51b3f2L,0x706237bef40e6204L } }, + /* 12 << 63 */ + { { 0x0791dfa1df764716L,0x31bf68768c66da07L,0x49f25b77ccedf4f3L, + 0x05170ccd5d965c05L,0x37d9521bd49e6727L,0x1548251286a00176L }, + { 0xdab444936c00eb48L,0x102c6b95e00c5c5dL,0x43660c3e4c2506baL, + 0xb2fb26165ec6f132L,0xccc4221a99ac7691L,0x05b29758a576deb5L } }, + /* 13 << 63 */ + { { 0xee84fe05a5731e27L,0x3251ded005713149L,0xbfeeaf3c7c5e7260L, + 0x3db0b6b2f048907aL,0x38728debb4a6b923L,0x853997d9d1142e10L }, + { 0xc636e3874b641cd1L,0x69b10f43c629f4f7L,0x6f10a95c7deddd0fL, + 0x85b5a7a317f56374L,0x28cd59435c329333L,0xb37621f7d1e476a1L } }, + /* 14 << 63 */ + { { 0x3a17f86d48341ba2L,0x558ef6e8ba6375bcL,0xa86ea3f0927935e2L, + 0x2f43742ac04d4fb0L,0x32a30bce38769421L,0x5a6d6a62d8d3912fL }, + { 0x34154b19c20e3fd9L,0xe95d3843fc85f907L,0x26cfbe0f9f7a13c0L, + 0x50d50b3a531736e5L,0x81849773b2cfa2c2L,0xc81523e63ba8ae5fL } }, + /* 15 << 63 */ + { { 0xac9b0573c2f899caL,0xd9c4fc1ff747ef78L,0xbc205571c7714e62L, + 0x726bbf311919f8c8L,0xfff68adaaedc0450L,0x9f4bc0b9f4001089L }, + { 0x5d10a660fc5dcfeeL,0x1ea644fbaa9f25adL,0x4f5cf102e5a144d4L, + 0x4275b6021521f249L,0x9c62750522d8bcdeL,0x3ebbfc5bb7df57afL } }, + /* 16 << 63 */ + { { 0x4a873076ad8c49b7L,0x891598ce7146575fL,0xc1d3042f427ea198L, + 0xdc592111ed259219L,0x0abdbd16234850caL,0x26b9412643b6fe8dL }, + { 0xd3c79d1736a1cfe9L,0x576386219a2b3bafL,0xa736535d5a98bf65L, + 0xacb3b7ddab2cdb2bL,0x37d3743adaaf89eeL,0xf19d9aba0b348532L } }, + /* 17 << 63 */ + { { 0x013b49753e09dc4bL,0xe548f7bc2d034deaL,0x65ffcd710b861c72L, + 0x80f4d7a2e07dac01L,0xd1889dcf56c1a8b1L,0x14ad62d4789b133bL }, + { 0x082e3c082e80532bL,0x0562a7d80b9d17e2L,0x4f8613095d57e2a7L, + 0x79f21d7255f93514L,0x22c4f68c595c0f33L,0x91d9bd5ba22c0c33L } }, + /* 18 << 63 */ + { { 0x30539655b29eff74L,0x7ba206ebe723167cL,0xe20c3ce488110a02L, + 0x52b406b97c124481L,0x050111c68c74a728L,0x3d594a6bc57cd9feL }, + { 0xd4b2a271e5f952d9L,0x7e52d63b080da0c9L,0xa6463d65f53a6cffL, + 0x9ebcffcfcc678e26L,0xa657f27b2f2b9424L,0x850bd2b871da5c9aL } }, + /* 19 << 63 */ + { { 0x9f3c395b7d4e1a14L,0x2f99aa23bd7301efL,0x50eee34e3017f166L, + 0x88c951ff4c9cbb4dL,0x90c0422ad8dda2f4L,0xe8361775d49cae19L }, + { 0x654db0d250da6138L,0xe4ada30ee03c34a3L,0xde0d3787832ccf4bL, + 0xd1bf435641b94c86L,0x347531c37db87eb5L,0x6942e7e30fb51863L } }, + /* 20 << 63 */ + { { 0xafad01a0d93c54b2L,0x659bff9695536c49L,0x7b91aac2b9734c15L, + 0x55c7f08224e02f59L,0xebcb71e73a26e551L,0x5b7225f76c6343ebL }, + { 0x021c48fb17d5e775L,0x57536a42bd859c87L,0x24852cc0ae2b63e9L, + 0x21515020c0ce0ef1L,0x2ac7336c8fed825eL,0x4bc87feea0152819L } }, + /* 21 << 63 */ + { { 0x7f9813e94b82bbd5L,0xc01f14624e697d08L,0xf02d9eb293de010eL, + 0x290c503c50db5ea8L,0x339341f033edb639L,0x962abf5f7cd7f6c1L }, + { 0xbb1041ae95fb9e8cL,0xb8c9f9d6dbd8525fL,0x8658a54f0f5244b2L, + 0xe9326e455b84eea8L,0x9ebdfe4f54f11de8L,0x3c90b0cedc740440L } }, + /* 22 << 63 */ + { { 0xde6973e22683ad60L,0x35fe4650eebceb58L,0xbcdbbabf7c719a33L, + 0x8bce8111c076ca95L,0x8f7176deeb6bd711L,0xd04e9769d240a56fL }, + { 0xdef7d8fac8e218daL,0x04cff5976df28152L,0x2a1af6e24bd1cca2L, + 0x9397014edcb911e2L,0xa251339038677b96L,0x0dc48a8fb61b462dL } }, + /* 23 << 63 */ + { { 0x42eab6610197a8d2L,0xdc4a557ade082468L,0x4cf68d6090495f66L, + 0x6dba8de79032929eL,0x304b38cc827b5d7bL,0x8e57275cf32f5063L }, + { 0x4b555a0337280c95L,0x49c1e532ef8ddd18L,0xa2d8eed45459adc1L, + 0x2b353217bba3cf41L,0x11f3c90cefe8f005L,0xb3367fa0d55916c4L } }, + /* 24 << 63 */ + { { 0xe7c396d64654712cL,0x1fa5ea507a26e994L,0xaa98768709012b83L, + 0xf1ef9792e9b17e98L,0x2c22bcb06dc2db10L,0xae42ddf6ed4be80eL }, + { 0x672080f62e743405L,0xa15a7f975b7821d1L,0x0cd912f247adbf07L, + 0x6919c0dcb6c4ae8fL,0x62b13edd14c6253cL,0x66f35919f8032287L } }, + /* 25 << 63 */ + { { 0xc992f6fe05f3b31fL,0xcdcf59b56a3d4522L,0x69901b3815df24b8L, + 0x4b9874029f6153b3L,0xeb09cbc1bca86176L,0xbe78cd7d446289c4L }, + { 0xd4aced42b933fd58L,0xe0dc6f306a326de3L,0x4bef32960542a5f8L, + 0x3eb8d14106f537c3L,0xbb45a994b6f0d0a9L,0x340c025d3f4a01b8L } }, + /* 26 << 63 */ + { { 0xdfcb3255fa371ffbL,0x3fb4a22c92bb6b01L,0xd96efc1605396353L, + 0x2ce2228ce5d2bc25L,0x59483843212c7eecL,0xdca7173882996047L }, + { 0x44dad56d8de87b1dL,0x622f88910b6222d5L,0x1abbc501d5d3a9ccL, + 0xdbed73a5ebe52e80L,0xa7f785b1c98c56efL,0xa32471d3d343aeacL } }, + /* 27 << 63 */ + { { 0x65d39f8ae510cee9L,0xcc60cd118dc5e825L,0x3b6ac6627ed7198aL, + 0x5d7fc001f33edc87L,0x0218ffc453e978eaL,0xecb762e57bdfcf16L }, + { 0x8e7122047966b202L,0x1c502404e6b99602L,0x0acb73f1131cc36dL, + 0x81d1132ed4369a1eL,0xbca89fe8377271a4L,0x1353a883262a2e18L } }, + /* 28 << 63 */ + { { 0x2713b58c9d628e1dL,0x3729960afaa8ba1eL,0xc3438130ab53bc93L, + 0xcef9eda5e9c165e7L,0x9bacd1c3fd02650bL,0xbb300334540ece72L }, + { 0x21f5a5d3d9c4f0edL,0x1ba32e4ff7c19269L,0x8f073beb2cf320fbL, + 0xb49766c45599646fL,0x68180d6649e4f200L,0x8203d8aeeaeddb36L } }, + /* 29 << 63 */ + { { 0x7b19780fdbbbf57eL,0xc094d6d9c2207635L,0x241898ac6bb652d6L, + 0xb61b25724923ce29L,0x26ecd97508000048L,0xd08c54e5f5f96b8fL }, + { 0x19019968c1604cc5L,0xa9940e9edc3f31b9L,0xbad2d245c3614a9aL, + 0x7d3cdb2d411e63b3L,0x88d842c3223638ffL,0xbc5427d0cfba2b48L } }, + /* 30 << 63 */ + { { 0xe6d78b7f60085b20L,0x0aa1d62bf318d226L,0xaaa4391df6461e64L, + 0xb15ee4a7213c949bL,0x183f043be4bd3dbbL,0xa1a87996ca49f456L }, + { 0x6030ed2ef6ed22bbL,0xa2002784fab7f7a2L,0xfc40914dd850cdbaL, + 0xe63edc4c7df80ba3L,0x8fa35ab57b27ddfbL,0x3bdaec795096ea04L } }, + /* 31 << 63 */ + { { 0xf33cc5ee452881ddL,0x89c144a38966d47fL,0xbfa8395149156a93L, + 0x0069bff358707b05L,0x2caf814cca12a0b5L,0x1ea71ce71794450aL }, + { 0x08fd2b1c63d22a26L,0xdb08594eb3876737L,0xf459049a57b3669bL, + 0xf64ecaeefee0d4ccL,0x9da2177c63f233a4L,0x042fcca84e54f053L } }, + /* 32 << 63 */ + { { 0xa68295da2caf088bL,0x23d6439a5c8709feL,0x8deba0cffe0c3df0L, + 0x5b4d037b3cd00a1aL,0xe9edc429aa0f9088L,0x6f5827e35847def7L }, + { 0x9739d03d306ad966L,0x7c6b18afaed51d04L,0xdc3d34ff1759060aL, + 0x029e9aa9a7e94dbbL,0x2a3cdfa0f7e8b7f3L,0x42f87bf0bbd8f6f4L } }, + /* 33 << 63 */ + { { 0xe36941004ef8cf5dL,0xcb4dbddf4d8bb768L,0x0610858e828c717eL, + 0xb4cf22cb2bf53239L,0x938e49f16a3e7a71L,0x1dbbb837e73c7a10L }, + { 0x26ea3108db1b58d0L,0x1ca340abad2929faL,0x1d4601938ecb1f6aL, + 0x060543510424fd93L,0xdbfc403f0303dc50L,0x142ad48dfc0f4007L } }, + /* 34 << 63 */ + { { 0x8a8258eee6a52970L,0xf2d13a33a3882954L,0xd312768c38d48e32L, + 0x78a70e03e9369eb8L,0x02ba8d2b69228d48L,0x7f957a33b3bfeb28L }, + { 0xafb22cd20ab2d0bfL,0x335304ccf8cd44d9L,0x0587a6f256009a3dL, + 0xc0bc7278023b2530L,0xe85f2ec5f37c6727L,0x045f156003f5a081L } }, + /* 35 << 63 */ + { { 0x6d71a45274ec55c2L,0x0d064bdfed33da75L,0x1aa4d77ab503afc6L, + 0xec08340c5cb136e7L,0xf096fed6ed11d9faL,0xf232d1b82f81e148L }, + { 0x71cc9b78ae9b3374L,0xd80ce28668bcc1baL,0xe8f4bd170274926cL, + 0xa7ac120f100da329L,0x9f071c6352a482f2L,0x76d85a8e842d6ef1L } }, + /* 36 << 63 */ + { { 0x516f138bed210253L,0x5ec2fa324433461aL,0x0dbe2c66cdaf1280L, + 0x086b91e59fbf3318L,0xfb0223ee399a1ca6L,0xd6f86d9b0db5b20fL }, + { 0xec02bca25752d618L,0x952fafcaaf69f3f1L,0xf304cb7533c4d294L, + 0x78085727dac65608L,0x22f302ef840a4466L,0x33fb889dc371c31fL } }, + /* 37 << 63 */ + { { 0x4aa2f1c36abdcdf4L,0x80963f8251da8d8cL,0x5647a356ac008cf0L, + 0x40a78c45fc10452fL,0x2a3b9da1ca2d6a31L,0xa4d177760f0db94fL }, + { 0xcfd600d9939941acL,0x256e44c142c3fd25L,0x85bccd42ab3f9d41L, + 0x83e93e44d018298cL,0x569f54d474a5fb37L,0xad2c613af2ffcf8dL } }, + /* 38 << 63 */ + { { 0xc63e6f7c22d515abL,0x3fabfef42ad30174L,0xf13a0126b1c65411L, + 0xe269e956dce87183L,0x44136834a83e0249L,0x554e731831958850L }, + { 0xd287755696569aeeL,0x5af275e9274bf4dfL,0x7056f958197dbfdfL, + 0x699f5a672169811cL,0xd9a857d92c1c7c3aL,0x62cf7431843bdac1L } }, + /* 39 << 63 */ + { { 0x974fcf5529d0c948L,0x104d7df0693c5379L,0x4f851c397dadfb28L, + 0xcd5bc87c233c02c8L,0xf7fa16e82c8c1c04L,0xed42de484dc18a19L }, + { 0x213db3a5b4366736L,0xf6eb5c9517da3d1dL,0x4d04ef1213b304ecL, + 0xba7bd9afaf74e164L,0x956a5f7bab319f50L,0xe733891ce2a4932dL } }, + /* 40 << 63 */ + { { 0xaa4711f54f890542L,0x862421d9eba822c4L,0x2f667179848280fcL, + 0x4de16d87c201ed75L,0xd20e1399c5e61b5dL,0x3f7114b49ed67ec7L }, + { 0x561fd4979b5a88f9L,0xb202eb86d84db2c1L,0x67d8fb90c8637d3dL, + 0x3d1d78a1032b1853L,0xe07bf775ef1af9acL,0x691e1deea57d6adaL } }, + /* 41 << 63 */ + { { 0xe236e42b2a6045fcL,0x4a6b7be7613f1c5eL,0x14136ccbf57b1aefL, + 0xc3a8a6b9c7b34813L,0x63b0998c5f5cee69L,0x311bfe2c3481a229L }, + { 0x4dd2325ff0aba408L,0x1b8a3f739a2fdff6L,0x4845cde0dbafe0d2L, + 0xd092bb22cd37b02dL,0x35436f9d600fe0efL,0x63c580cb065f379eL } }, + /* 42 << 63 */ + { { 0x38f98360f48948b5L,0x1a1d67a97ae3ad67L,0x79966318ab91b44aL, + 0xb69a75b8dfea0b1eL,0xbb18e5fa05d4d71dL,0x80a14dfe03b1280aL }, + { 0xe549c8f14c17cf7fL,0x91da31098969b5c4L,0x1e3e8f08ccfc1732L, + 0xf1cfb3ad0c85444eL,0x6854b52a628bebbeL,0x8a5e2d85075f04d3L } }, + /* 43 << 63 */ + { { 0xd428f75c5aaa1da4L,0xf192162dd224691bL,0xc30f5ccfd3a50718L, + 0x82e2b585e9e0f738L,0xc7fb4dc15cf3fd23L,0x8a52eb37e4e2b37dL }, + { 0xd5bb892bf1702cd4L,0x64b8ccd056b92a51L,0x98ab053f8988e2e6L, + 0xd56b34022f104643L,0xf09017be073886d7L,0x0283e9eebf6eaea0L } }, + /* 44 << 63 */ + { { 0x834701da3801c65dL,0x5bb35c48955aa27dL,0x0ef0f375db7ad387L, + 0xd25e337f06cd1d53L,0x757a1f9d90cd91deL,0x1604f153d61bbd60L }, + { 0x6a01e8cf8bb95dc4L,0x34b7be6275bbdb13L,0x0a96b3a121e9b029L, + 0x25615c3b2946df44L,0x5eda7d1919d04842L,0x08317975fba84668L } }, + /* 45 << 63 */ + { { 0x4a4dd7bf2bb5fba0L,0x0ebc07f3c84c2304L,0x054f2e448daa5099L, + 0xbf8949da3ec362f1L,0x2e4a677c1d7d73f5L,0x405e3ad24dc70fbeL }, + { 0x2958e956c7e46fb3L,0x34e0d7f1b2522e5dL,0xc44b95e25e371e3dL, + 0x62e348a4d91baea4L,0x8d9e89e24c09e110L,0x8cb886f6b1c1e356L } }, + /* 46 << 63 */ + { { 0x66b16f6033e8683dL,0x3435ab2560b41c5eL,0xd5b89f51d452e049L, + 0x4b5253a73aac0092L,0x01cae436f9d2e2c2L,0x789de14637e8ce97L }, + { 0x8f50541701a1c2e8L,0x8c77dbdd798a8404L,0x5a264906b6e91e68L, + 0x36761ccc3c6aafe2L,0x5809baa37e50f9e7L,0x0b50904e28fac969L } }, + /* 47 << 63 */ + { { 0xb6360372308785eeL,0x0c9913a68cf10e55L,0xe82b0f470e67c99aL, + 0x0bf2d24825399082L,0x7aa3edfca86fe16eL,0xf534ec4e731a4956L }, + { 0xb71d5d4eff26e993L,0x320eb7ac7bd58ef3L,0xe5e4c5f30cafd658L, + 0xeb6b8e0a21a06cedL,0x037d0faf6f76acb1L,0x39c76a6ed6f13f81L } }, + /* 48 << 63 */ + { { 0x12474bd8a55a3a4dL,0xe326aaf19e471af4L,0xf201a9308caadaa6L, + 0x546821f835304341L,0x7fe452c3088353e1L,0x8f1ff628fc82566aL }, + { 0x49526f46d99f8967L,0xb19c80c0a4009690L,0xeccf97591cbc0716L, + 0x2e13ae2caf4cbc8bL,0x12b0df13f32e29adL,0xa2005d6e0b1565f0L } }, + /* 49 << 63 */ + { { 0x9260321bde788968L,0x4aaf1752886ccc74L,0xf94ae636c06b1d9bL, + 0xf0c858854954ae43L,0xaaa735866c42a104L,0xcab59d914e782db7L }, + { 0xfd12f9ee01ff3a1fL,0x35eb6104b546d3c5L,0x97d839e075ca1425L, + 0xa77712f452428003L,0xf5dda4e8bd9f30e2L,0x0c3ab97091d6f540L } }, + /* 50 << 63 */ + { { 0x58734b3ca68716ccL,0xacdcfdd2acfb5719L,0x97074bac7084cf23L, + 0xf8d4f285d0c81b66L,0x5ea926e2ef541e44L,0x65a8e25da2c04e0fL }, + { 0x67e2380f06258485L,0xdc00f2ed9691a57dL,0xd37b23fd6b80274eL, + 0x57f1604f2fe10aecL,0xcc21a4aeffb33ceaL,0xf33a344bf75eaa02L } }, + /* 51 << 63 */ + { { 0x24ca6fc56969f55cL,0x6fe18be29a7a9753L,0x5e9a7ed36af8da90L, + 0xf6c261b7ed493388L,0xbe9ac24beef2b77fL,0x0357ab559f244e49L }, + { 0x5f7953375f1b5b9bL,0x27dfdecaa9bc503dL,0x0b2091b55c0e3ee9L, + 0x1f4f7866d68cb87fL,0x336c2c127a442a9cL,0x88267fd1d3f2ab78L } }, + /* 52 << 63 */ + { { 0xdb891eedd06014e0L,0x69685d6103e9970aL,0x3a612db402838113L, + 0xc1cd7b3adcdef0b0L,0x612b299da41d6c1eL,0x982161ed0ed386a0L }, + { 0xb36bbe2f3ea1bf1eL,0x0d8c3752ceb2a5ecL,0xc02cd7f6ec03bdddL, + 0xa87977c152631d9eL,0x7b546cc37e398d7eL,0x5b1218a804845671L } }, + /* 53 << 63 */ + { { 0x52cd86c68a62f0a0L,0xc437c2af4d29c896L,0x722a337a45aebfe3L, + 0x03b13844d8a9de8bL,0x41a005bb8510aae9L,0xf42399ffc63af92cL }, + { 0x004d29cfcd93390eL,0x472de98741dcfa34L,0x2c71ae744e7cdcc4L, + 0x11a5c2f8409816ccL,0x320ca246a96cef60L,0x72de4287f3d57621L } }, + /* 54 << 63 */ + { { 0xe3e7a3eb3771a0aeL,0x781156e9b6dd5304L,0xbaee3a8323e31e6aL, + 0x66d1569a08985bf0L,0x56161e202d75cba3L,0xf9c23c102a944de4L }, + { 0x27ac8f454e129ea5L,0x8b991ba788050aaaL,0x600c96ffa5d052f6L, + 0x0fbe944df244984bL,0x3801026fa204c36aL,0xc4bfa1994d55a584L } }, + /* 55 << 63 */ + { { 0x11b200c6a32f5c81L,0xc4ab4cf43eabe341L,0xa21468f06f339f5aL, + 0xf20c2c5a729438aeL,0x3e68031e3a067c3dL,0x3962a92f062c8371L }, + { 0x389b22835b000f3dL,0x98f3b679250b8666L,0xe283c2b4eea91464L, + 0xd35b14de1e1f4c08L,0x9ae72567d79d8683L,0x2c37b162a3b2a840L } }, + /* 56 << 63 */ + { { 0xfa3e43e56cb173d1L,0x2502258d4591b5a5L,0xae8c4b558ca9682aL, + 0x8cb1ffb4ec81a288L,0xd11ae888bfc84fd1L,0xa3b083a0d774577cL }, + { 0x119b41c11da9afc5L,0x44bc77622934e22bL,0xa04694f37c639d6cL, + 0xd5e1ce5732c5b8eaL,0xd507c39b9749e8b6L,0x16cc0b5755255b63L } }, + /* 57 << 63 */ + { { 0x66fe7a39c4955e7aL,0x25b0b3e5bb11a1baL,0xb82c2cdefc573bf3L, + 0xed33c0e8281a3927L,0xd068c8901ad799d4L,0x052801ec9cbc73edL }, + { 0x614e4aba0faf5c5dL,0x50d7b0a89f66d391L,0x7bdfbf5fc18e88a8L, + 0x1fc93e1f4380d2a2L,0x8241dd5f27d952d0L,0x44944d9c3a3f79d5L } }, + /* 58 << 63 */ + { { 0x808e2693c0edcf36L,0x4725b5aa87c254c0L,0xd1e464644d317973L, + 0x3e59efc2393049d2L,0xa4c9f340d3e0d17dL,0x69b40727abdf3022L }, + { 0xa1d85395317058c8L,0x2cec2a040cfa7c13L,0xe3c16f7634236cd1L, + 0x566b403a3e52fe3eL,0xfd6065bdd6923cb6L,0xe769a89a5019f94eL } }, + /* 59 << 63 */ + { { 0x9b1f6e9042a1cce9L,0xc6c870270511f865L,0xc924caa72a3c29f6L, + 0xcb674fb068e604f8L,0xe997b0b8330c2dedL,0xf5b315a04ddab219L }, + { 0x6fa1dde6575d3ac3L,0x32ad27f735e65e56L,0xfe723ec2e81b1ce4L, + 0x149983f8985d7286L,0xa1d350a0492ecc9aL,0x12a51f8c36a0707aL } }, + /* 60 << 63 */ + { { 0x71e5df78614f6f37L,0x5cf0e08da0b80beeL,0x1f8dae171e32051fL, + 0x54ae365d83bc233bL,0x97ea005b1b84aaa6L,0xf4766d9264c75139L }, + { 0x9b93bbf241215701L,0xb18f042d8cf8a865L,0x5dfb96dd0867556fL, + 0xe9fafbb8597fd6a1L,0x729b2f50fe48bbc6L,0x2cf85f6b7f37ff9bL } }, + /* 61 << 63 */ + { { 0x3e7c871024d197f2L,0xb635595bafe9c29cL,0x302f4fff194e084cL, + 0xd497ce7c18edf332L,0x4081c7aa062672a4L,0xe886a5b28afa97daL }, + { 0xa7e922b5786e1bfeL,0xabd9a18bbd7ffb7aL,0x1f4f5b9356341b58L, + 0x1726484344969ab1L,0xc4a0b557e668a479L,0x5ad1c062bf4f3343L } }, + /* 62 << 63 */ + { { 0x4ff86eb693d2b958L,0x4513fe1b784f628bL,0x45f4712573b5bb80L, + 0x25aa3d36c987bb15L,0x12b1e65bb48163f0L,0x9d0cb4aa9801592bL }, + { 0x02c0c2aa3718bc98L,0x79b03df99c306353L,0x097d8d8daee5144cL, + 0xebed60774621d7abL,0xa8edf06e4b52e72cL,0x40c86f181dbca7d2L } }, + /* 63 << 63 */ + { { 0x65c7144a5e84482aL,0xba6f92644d4f7553L,0xf4dfe807d9c2524eL, + 0x1333dd7c054403b1L,0x44557e880156451fL,0x5dbda4d80824c813L }, + { 0x59e204959857fec6L,0x42f4068f1b1eeb99L,0x067c3aa21d59bde9L, + 0xa9c4c3eeef27419aL,0x99fc994b2ec87652L,0x4f1607581578a996L } }, + /* 64 << 63 */ + { { 0xcd8c2ec9378ef62bL,0x7f4a3c5491a7c4b9L,0xe12386d4db83e1abL, + 0x9a792032bb549bb5L,0xaf81cba62807c0f1L,0xd4ad7d87abf2008eL }, + { 0x9d7a72307e9ad6cdL,0xb30636b08b517b2aL,0x47c324daec900516L, + 0x408cd0d37193eb30L,0x8f0bcce2d315c655L,0x540ad4e0869d6c22L } }, + /* 0 << 70 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 70 */ + { { 0x4b5e753ddae0ff8bL,0xe55c83e4da3d97b5L,0x4034d75f42fa905bL, + 0x89b85edac33e462bL,0x31f413c3058de3bbL,0x66c01c806ba75391L }, + { 0x3f500202373e28deL,0x5090b33b4b9be739L,0x7297aa10efa2adddL, + 0x3e8ccdbe1a6566aaL,0x4dfda07fd7b4f214L,0xa659bd1e7cb1cae7L } }, + /* 2 << 70 */ + { { 0x31796c2387d11691L,0x02991ea2a9de506cL,0x4ff0cb716cb0c301L, + 0xdd0cdbd7d1702ca9L,0x470a26c8e1a02a90L,0xb705b7bad7054625L }, + { 0xfadc2e86d4a1a268L,0x0fd9764668e9f923L,0x042b5ebb2951a8feL, + 0xe4af9d0364197a76L,0xdd2c6bb3249c1b5dL,0x60af89bdf01932b1L } }, + /* 3 << 70 */ + { { 0x4374145d41afcd64L,0x98b72d6049d21198L,0xc0ff394bdfde8a41L, + 0xed1112e5ee1ff7a5L,0x87a920e8cb5036fcL,0x437123f62deb225eL }, + { 0x37e527afb9ad8c58L,0x3e3c9998abfaef38L,0xb656bcc550b2b4e2L, + 0xfacc8a193bf5699dL,0x98cec74fe616307aL,0x34af333dd3ef8babL } }, + /* 4 << 70 */ + { { 0x9ded9b0d744ec273L,0x5bdfe5472e79e4d5L,0x94f3aaf539393728L, + 0x22136862a438413eL,0x449286da373c7de3L,0xa709d85d29aa1540L }, + { 0x1bd13e410284a4f6L,0x37b54d69f0799c8bL,0xd43b558f6bcd0cb2L, + 0xf5757c0e9e610369L,0x15c80b23c16e0651L,0xacb2cf64001820aaL } }, + /* 5 << 70 */ + { { 0x0629e4ddeec37f48L,0x3f7556a2da7de716L,0xcacd8f27661662bcL, + 0x65d8bc2ceaf01690L,0x83ac66477c39c893L,0x353f60dbf59440e1L }, + { 0x2597b0d6852c575aL,0x410885f73a40c2b3L,0x953ab3472fcc2488L, + 0x9f753e5eef4cc6d8L,0xfc32bb4d97f69e63L,0x461c1b0c87e8c264L } }, + /* 6 << 70 */ + { { 0x2bea7e75ac4b62f5L,0xcf255dcdc6297871L,0xdd88db8781b25c72L, + 0x77ad90b3b617dc04L,0x65ee13820ed4a7d6L,0x4c08df9cd9644c8fL }, + { 0x072d3784525a023fL,0x1aef69cefce399fbL,0xb07fd78ed7f29044L, + 0xa3754e1443043fa7L,0x97bdae92ff9fe4d9L,0xad63ba6a700fe6b8L } }, + /* 7 << 70 */ + { { 0xa571929ba1ca17dbL,0xce7a12f545e146b8L,0x39df1446d9eb426dL, + 0x1e48b3f8dc27f268L,0xa2d7dfa1ff548455L,0x750068b86ef1cc82L }, + { 0x4d699306667fce62L,0x98540b9d131c5412L,0xf8a62cd347c580b0L, + 0x2b55460f73795005L,0x3206c0257b8db337L,0x2280934bd0dda5a2L } }, + /* 8 << 70 */ + { { 0x10a8aabd2352478cL,0x599d9dfa1364c40fL,0xa009df1a076945a2L, + 0xf869152c03861f02L,0xc405226e9f866a3cL,0x93bd737d8b41ecbbL }, + { 0xb5c9ed1033901eedL,0x90e4ce8f99312b80L,0x1a9ef22e57589279L, + 0x83ef607d7fe2d6aaL,0xf2da84543473dbfaL,0x14f36d3a57879066L } }, + /* 9 << 70 */ + { { 0x2c780f220ea3ce34L,0x240a211e4b8aac72L,0x7a266e5dc2625a99L, + 0x1cb15d3e3b30c878L,0x8cd8ccab0e1b21d3L,0x53c64279adc1a6b3L }, + { 0xe60d15b960bf708dL,0x6e431c1b0cb5ad4bL,0xec874c3e82033111L, + 0x88054a1d9141eae5L,0x98438a5addf53a28L,0x168f0b0ffa12c657L } }, + /* 10 << 70 */ + { { 0xd621ce26629d7a57L,0xbf571de7cc1f8af1L,0x2c5cfaf9304adaa3L, + 0x950addbd3f283b49L,0x622dc27cee6d1cd1L,0x26d920041f0863fbL }, + { 0xe243b2a2a41ec585L,0x0dbd9adf2bea6235L,0xcb083c4d6f0820f5L, + 0x809ecbafd5493931L,0x9647067414b7ffa8L,0x2cdfe22e53fc2224L } }, + /* 11 << 70 */ + { { 0xc8b1333c7cd74a06L,0x7d5ac4dc271006bfL,0xe9377d9fc14e0e56L, + 0xaa8651db7a92ab1fL,0x77cee8145fc11fb5L,0x1e7c5ca027870b14L }, + { 0xdeef4b3f6f959698L,0x7c59f26e5daa9bdaL,0x4d0d5aecfd312368L, + 0x5247a6f3b738de68L,0x1c4e8ba990c04807L,0x0554b41bcce126caL } }, + /* 12 << 70 */ + { { 0x3df98ea9a81cc26aL,0x982ed56883b2c6f3L,0xc9cbd1b5ea6d6976L, + 0x3f9f23197e25ffbcL,0xbca8e0567da6280eL,0x7abd316635cda713L }, + { 0x46ef321d740ae011L,0xb17f6c75db214a33L,0x37b73b4b51de4044L, + 0x5bccf3ccccd9ba8dL,0xa2ca080dd0f7045bL,0x79caf90668cf4dccL } }, + /* 13 << 70 */ + { { 0xcc3605a9a7b07d22L,0x4370eb18b4ebe4e7L,0xbe393039248867c1L, + 0xc8e4851ecb1a75ffL,0x215f3fbe39cb6da4L,0x6f2102eee41f9a34L }, + { 0x61d484abdfae7c27L,0xf5143bd26f1260fcL,0xa70b6c067514bcccL, + 0xe71ca833d23506f5L,0xe2f50ba8eae03a8eL,0x2ac3b50883c33359L } }, + /* 14 << 70 */ + { { 0xe94b930f3655cabdL,0x6ef6aac4a342443cL,0x2feb8005bae255daL, + 0x4625a15cac6e2095L,0x75c6311d0ec76c1eL,0x896a07409b81c6f2L }, + { 0xbad3e2f9073378bbL,0x2984a10629266ec0L,0xa68a5351a788010aL, + 0x321aa113017cd052L,0xecfb61752f34db5cL,0xfe080cedca2b51dfL } }, + /* 15 << 70 */ + { { 0xba29690803360c88L,0x3fb087c036311812L,0xec5fb10ad9ff6a48L, + 0x52f7077f207dd8e1L,0x8e65cfb844c02fbcL,0x4f4fcde2fbf4bfd5L }, + { 0xd1ff54156cc74320L,0xf989d544f68b036aL,0xafedc2db973bd9beL, + 0x7bdc35694785e26aL,0x0df36796751ae9baL,0xfebde691ccdabd95L } }, + /* 16 << 70 */ + { { 0x3499b44bc77488ccL,0xde000e01aa8f3c10L,0x30140406c1f517d7L, + 0xd4b3c8eb82a174e8L,0xc8835b13af2c9b3aL,0x2cd7626e443716f4L }, + { 0x336c4f4b9c22de71L,0x9dd2b277f2529f60L,0x6ffba2dc828c34d3L, + 0x257a345c34d0d1f7L,0xbc1eff056ca4fbceL,0x05b335620768349fL } }, + /* 17 << 70 */ + { { 0xb142febb692e076aL,0x10cfaa6b9a654721L,0x5b7ba30c8d4917c1L, + 0x44be3089dfe4056bL,0xb7530ae6ae6307f4L,0x47c519c45b5f381fL }, + { 0xa80648d8c3078009L,0xfde72e30dcb021b4L,0x8a89a51bdc2659e8L, + 0xb9e0efa6306adefcL,0xc671c060c754a7bfL,0x703c698e18f14248L } }, + /* 18 << 70 */ + { { 0x25c86ad43c47783aL,0xb1f94a9650f85a4dL,0xb9472e3ac023a02fL, + 0x91033d1b26f0fcdfL,0x95d775c1ab7b4ee3L,0xbe17daffdf3a5cb7L }, + { 0xaeaecd2ce78395f6L,0x0e3abb0953b5da8cL,0x5f729f858ee774afL, + 0x1acccfb3aeca7a6eL,0xd066fccb37e4af11L,0x24c832ab84fc3259L } }, + /* 19 << 70 */ + { { 0xca547b680ca4864eL,0xea40fe17c7d49f27L,0xb5e68bab87227475L, + 0x6ba2bfaf8ce485f7L,0x4d2747acb72684f4L,0x5fabffc670aa6087L }, + { 0x2d4ded5679c67c9dL,0xaf3b4eedc8a4f22fL,0xbef6128ebfa6ca86L, + 0x7ce412bbd4381632L,0x518e6ecfe670d99fL,0xaba6518dfa5f426bL } }, + /* 20 << 70 */ + { { 0x5ebdc79cd41b2401L,0xf0cd8598c498e0f1L,0x93f6efe79c8b7f7dL, + 0xb2f1e40ac469aa57L,0x882f0e943433c455L,0x0add72adaea0712aL }, + { 0xb13578c399af96d0L,0x43c28dc621177663L,0x83aca2d854e09133L, + 0xae03943cc6ad8532L,0xce0a61917104f75cL,0x7dec8786f9838c37L } }, + /* 21 << 70 */ + { { 0xb0b41b8ec5abaef9L,0x43f59aee8ff5d1f2L,0xe58f78c9234d3d34L, + 0x0e1948d029a7f49eL,0x722f8e54c6cd8941L,0x75a4ebcfbaf24424L }, + { 0xec8954982d7dc6d9L,0x8df2feee5261e4e2L,0xdf2820b825dfb96eL, + 0x4b89c4dcff651949L,0x27c871a527bacbe1L,0xfdc70cf7329a52bcL } }, + /* 22 << 70 */ + { { 0x37d58766fdb3f3fbL,0x49d9a762ad64fa66L,0xf80423918cfdbbc2L, + 0x22e60ca36400f7eeL,0xfab8ea7568210629L,0x91267753963e5b6fL }, + { 0x5988d7f56b8e7ec9L,0xe43e762a5899e718L,0x842dbdcc40ae8b99L, + 0xa7ced3f19869739fL,0x1ccc1e8a6d54b9f5L,0xaa3a91adbd32e710L } }, + /* 23 << 70 */ + { { 0x306d662c6d4c255fL,0xf32aa48101fa367cL,0x29a71e02f16b3197L, + 0x653f7d88513a6079L,0xde93d6e74541b4adL,0x4d284acd8c54d3b1L }, + { 0xfc9d462be106ed07L,0x6e3818d07e355468L,0x2ad523859400c515L, + 0x287af41d5ecd3b52L,0x1162162351e1fb02L,0xd696d01f17bd4584L } }, + /* 24 << 70 */ + { { 0x9db114e3715aa8daL,0x596c2dc25c2fee22L,0x04df016bd2f3080eL, + 0x0cb3f7cfb9b72037L,0xadb877c7814fe2abL,0xb2d5ec5c37761ec1L }, + { 0xb5d6068e55d45831L,0x5fab1dffb7c52c04L,0x39b4aa5457d36d41L, + 0xec1de467423cc8cbL,0x280e02dafda6566dL,0xc70c3c383ca55f55L } }, + /* 25 << 70 */ + { { 0x27a866e7c6b03391L,0x980b0a42bfa32fc0L,0xd27856910c105df7L, + 0xf3def8c77103a2b3L,0x6c4ff04bdffea913L,0x57b1003e121140ddL }, + { 0xf47bb2826d0e3170L,0xa44d6ab1e6abdfedL,0x67114b8a2a4b69d1L, + 0x7605714d52d7c65cL,0x3734795ef60b81deL,0x277f9816ebf91959L } }, + /* 26 << 70 */ + { { 0xe57c2ed902b3b70bL,0xcec67da99dbc076aL,0xcaf66725b0644881L, + 0xdea4f6608a3a3f96L,0x5215f097609df5ceL,0x6d828267010193e3L }, + { 0x5971ff31a156565bL,0x44f7e4037b64e465L,0x2145ea9ab5486d75L, + 0x47b04066758e7ec5L,0xc181833a9c93cbe9L,0xcac07a9fe8443292L } }, + /* 27 << 70 */ + { { 0xead7cd3d041326e8L,0x721785f26092e605L,0x760864024ba91a6fL, + 0xb7b9b9fa335e8522L,0x6ba9c85387bb3ea9L,0x9c9f1f6f89b2ae0fL }, + { 0x952bb995aae2014dL,0xf8e74d80c538cfa1L,0xb21ca840b55b7e72L, + 0x22565ec4ad982191L,0xf9547aa1f569c537L,0x8d3cb14648596bcaL } }, + /* 28 << 70 */ + { { 0x340d77c2f3b6cbc6L,0xe09ae22c80f4f690L,0x3e915b028b74d32cL, + 0xae7101ca3cc1117eL,0x3c36152b526c5939L,0xdad8aedbd3ec0caaL }, + { 0x34de058e351bde13L,0x2fa75fd4582726d1L,0x27c030efc214ac0eL, + 0x2a216d1cc7100acbL,0x3b730043309097b7L,0x162ada747afd8aafL } }, + /* 29 << 70 */ + { { 0x43893d328c216eacL,0x475a3466349d7334L,0xf9f259866114fbc4L, + 0x96a22d2f0410b54eL,0xc60b69a53f3d951aL,0x152416e7fb400ddeL }, + { 0x3904dd2e8f682dbfL,0x5459272368383eeaL,0x0092554ee8c998faL, + 0xc80f28512c602ce9L,0xab2f8533b197386fL,0x8c302dbc91094b32L } }, + /* 30 << 70 */ + { { 0x853d994eea2026d9L,0x18734b04a1b927d7L,0xd4815747ce88d009L, + 0x0265742f01b856bfL,0x05fd8b1e205d4e15L,0x0f4c8be0f1da4808L }, + { 0x2652b76c456d62abL,0x0d3d1a29cbb8d818L,0xf350487453048509L, + 0xe393ef54e89ae4a5L,0x19ed8f0cc4b1306cL,0xfd72388da1aabd6dL } }, + /* 31 << 70 */ + { { 0x8a7e1494289e6aa7L,0xc69223e65c955385L,0x2bcbad5c087b8c7aL, + 0xc08008a531fed020L,0x9d38f5b2dc117c3bL,0xd84158bee4ad6b36L }, + { 0x2c2583eb92fe5b21L,0xebc847bf557ce949L,0x4c1b54ff4fc0fd57L, + 0xe437eba325ff2f8cL,0x79a4c3cb383caa3dL,0x38a34856e08356edL } }, + /* 32 << 70 */ + { { 0x5d7afe9a10fa53ceL,0xe2415b501ff49021L,0xe39a067dc6523492L, + 0x3458527527557f5dL,0x756b8d86930e9f9dL,0x88df6219040d52d8L }, + { 0x606eb60b5362b045L,0xd179818c9e383cbeL,0xa6215748e068d293L, + 0x73fbdca22fce158dL,0x9cfee07dcb183c8fL,0xc0bf2beba5e03c98L } }, + /* 33 << 70 */ + { { 0x36702d091bf9acc2L,0x1efceaebc9c9dddfL,0x31f9f5599b9afc1aL, + 0x359d4ff33e61a0e4L,0x33b3a707f3772327L,0xd990af318ac1c7ceL }, + { 0x5ee060b7e736ad45L,0x83dbe8b2f653ac2aL,0x30a1e38b407f054bL, + 0x0ec6c70bd9326ac9L,0xeb37ad09d7358ab4L,0xaf36143030551ef3L } }, + /* 34 << 70 */ + { { 0x7b05d8e56edd5c74L,0x268edfac5443acbdL,0x73e0d693ce1ee52cL, + 0x67c67914120a1270L,0x54a897cb6f1c5007L,0xe817914a8d540dbaL }, + { 0x85c1fa1958fc091bL,0x4f4989f4cf2698feL,0xbb2d5091168c08b4L, + 0xa6143388768cdd46L,0x69ec7a265e62ddc5L,0xc08749ae2654f4b2L } }, + /* 35 << 70 */ + { { 0x0a9882b37409bdbeL,0xfad3899cf8b6543eL,0x01c183f9f7e9893fL, + 0xe6438cf708ac9a25L,0xec22dc81aa0f2794L,0x3b641c02aa277a09L }, + { 0x686b1fbd0975c891L,0x4f7e1b680070ce2bL,0xdc343dd7487e3f1dL, + 0x8825d9c230f35abaL,0xda5a77a413b91384L,0xf09d958459e405faL } }, + /* 36 << 70 */ + { { 0x76b242b31cf2ab8eL,0xceb190e697edb12bL,0xd39b41b7089fc439L, + 0x6ee54e750892be51L,0x128fbcfcde414849L,0x4462539007fce5faL }, + { 0x9d12e04513709b9bL,0xc2c49737d95b22a3L,0x0bcd670be4b34d6cL, + 0x78d7b8cd768d7c8aL,0x7cf9382e16a0f402L,0x9b84311d17238fa2L } }, + /* 37 << 70 */ + { { 0x6b7faaf8c19b849bL,0x24aa5d54a5bec317L,0x991aeb14e7c06172L, + 0x52dc7da883e65aebL,0xda8998497696dd56L,0x3844a54e94cea131L }, + { 0xc9fb72ac55f69169L,0xe2f7bfc821893ab6L,0x44220c2edc4057f9L, + 0x9f4f0c3812d5fedeL,0x5725b2b05c913be6L,0xfa08c56c02d8668fL } }, + /* 38 << 70 */ + { { 0x9aff9f0c009b3e1dL,0xed7936d97a3c8c8fL,0x0bc8e46fdefbd340L, + 0x7b508ef231540ba4L,0x9bcd9108005388f2L,0xa25cfa07c089f35dL }, + { 0x9ec7cf81733bccfcL,0xf8a1993a249006d6L,0x1e68981a96d81923L, + 0x27b6199adce834d6L,0x2ddccfcfacffb035L,0xf62d7a534fe0126cL } }, + /* 39 << 70 */ + { { 0xc800c1d5af76895bL,0xc86db45c43f2a94eL,0xf77322fbdbb144cbL, + 0xb2607dc8f7da8df6L,0xaf666055b6cc1047L,0xf1db6416375619d4L }, + { 0xf6103c8c4b0fbd9eL,0xea8e979fb4f5b85aL,0xb0307d41fd16f61eL, + 0x26bf96c58cadf61eL,0xb56c53a3bd348a61L,0xd1a5aa4f8a01388dL } }, + /* 40 << 70 */ + { { 0xa29d231edda802baL,0xde8d0d510ec3c1e2L,0x0ee56eae117033bdL, + 0x4dc9491998bf860cL,0xa08919cd775cd56fL,0x609a30dc1332bfc2L }, + { 0x2c337f181a41db0dL,0x27fb0072c974824bL,0x34292c1bfaf28976L, + 0x242fcd73ef8c4fccL,0x553723b27473c603L,0xb2191ee9a06a0bc1L } }, + /* 41 << 70 */ + { { 0xd10b7b7c10bf3427L,0x16f9ebc505321572L,0x057692f6db5fde44L, + 0xf45d4d268f047704L,0xe3f8784e25584db0L,0x753764cb9f548980L }, + { 0x4239bd4858f5360dL,0x9dc993da98296063L,0x0fbb0c419ffd05b9L, + 0xa6a87d50610c3493L,0x99f5669df10f18abL,0x5a03f02ba4224a18L } }, + /* 42 << 70 */ + { { 0x3c6839e5bf733207L,0xc2f380899c6d106bL,0x43155630e39a7559L, + 0x28d6cb546f2b8d34L,0x19738cdf09183c75L,0xa71ec595dcee5a08L }, + { 0x8e9c1cc3c70db659L,0x1333d7b38beff6a6L,0xb263d91e036a5aa8L, + 0x72728714ee4f858bL,0xd65fcffbb885ceecL,0x08193f585aaaac96L } }, + /* 43 << 70 */ + { { 0x264006e1b53b4c8dL,0xd3748c0bdea2f9ceL,0x019408d34e580011L, + 0x381bcc70b1342807L,0xb904a17191eb1a0aL,0x13ddf3af6151a1cdL }, + { 0x13827129bc228909L,0x3378b4834cdbebd9L,0x25806f7ed56635c1L, + 0xd1a3fb1c54327e55L,0xb2b8895c69d94817L,0x0779752d7150c16cL } }, + /* 44 << 70 */ + { { 0x228437506ce71a1fL,0x39c6fd9abf0956a5L,0xd34a4be8c8d29ce5L, + 0x41dc15356fbf8fb0L,0xdce277034c950de0L,0x1ad7192f90c75c28L }, + { 0x5b3df71e27766767L,0xba85ec629ca80b5fL,0xfadae6e5095938d8L, + 0x5ce3ffc24d286159L,0x60f771fdc7b977e5L,0x7a764991b38c0c70L } }, + /* 45 << 70 */ + { { 0x3e4440b7469f6406L,0xdba02dea247657bcL,0xa551a570a46227e5L, + 0x278bd5a06e58b15cL,0xbbc5f8edc53eb694L,0x50e6bf5b855a2c7cL }, + { 0xa80af271d231f3b9L,0x6c22008bc139b010L,0x04e9a337ba1e27e1L, + 0xcfb75909677a28ccL,0x95c59b55f967af35L,0x70d24fe88d3c6ddbL } }, + /* 46 << 70 */ + { { 0x0117cabbaedcb5a3L,0xb70a95d52e7bc67aL,0xdc2e07d1ad7e7cffL, + 0xf507941825b9a6b4L,0xf953a962bc8b2f61L,0x390a630d181fda94L }, + { 0xc833598d1fbdd233L,0x0213e633ac4763dfL,0xe822febbcabd2713L, + 0x522864e71d2a409eL,0x49d778a81f904f3aL,0x0dd980e15912be0aL } }, + /* 47 << 70 */ + { { 0x97f993f46621ff1cL,0x3bdcc1ea7d30ef87L,0x931c624585386384L, + 0xd17a7b6a8cb593e3L,0x1b25176da0912f55L,0x323cf7ac2faa4d72L }, + { 0xababa6c58683a7f8L,0xa99ebbda4a71606cL,0xb5375f6b0cd8fd0cL, + 0xce43e2e08ae372b7L,0x957af3cb9e69c105L,0x167c4fca772d0c74L } }, + /* 48 << 70 */ + { { 0x0934812574503f05L,0xcd6a64b217bf8ab4L,0x791e72fa1fd4057dL, + 0x033abed8f0697964L,0x1085ac930d58690cL,0x8acd49d69c8874cfL }, + { 0x929e4c39ff1a5286L,0x9704e80ff28395abL,0xfa69fce54c3d9f8dL, + 0xdeb56555fc83a6c4L,0xd375fa037dc04c5eL,0xab2f12f156a58cdcL } }, + /* 49 << 70 */ + { { 0x381d144f8119fa7dL,0xda3aa4a73c6cf64eL,0x3db4cf0a74cc1520L, + 0xe8148941c1cf3514L,0xbc6c7398a22977daL,0x75e26d4982bbdc63L }, + { 0x17a626a4c9594c3cL,0x766fc21a60d71273L,0x547331241c7653a3L, + 0xdbe3a9f1502617a8L,0xe41acd19a33d622dL,0x4d24cbd5e15d69d6L } }, + /* 50 << 70 */ + { { 0xdde0a062dbbb9d08L,0xb5676d14153211e7L,0x747247f6f97b1468L, + 0x93a6de79b2ada501L,0xf9d4e652518ce913L,0xefb0de76702b82fcL }, + { 0x2c54ffd9d68961fbL,0xa6a2d1a384f04f81L,0x88167488d74b91adL, + 0xf20bba56a7d73a78L,0x9af1df5ae1afc672L,0xd79ded4543c26afeL } }, + /* 51 << 70 */ + { { 0x24011535a223c19bL,0x38b55f0a19c719f3L,0x369f86b4d343ce98L, + 0x6516fca318288db7L,0xad32d4699e4aa0a4L,0xb6c80dd50480429cL }, + { 0x890d73f3b659b787L,0x2d1f888be15362aeL,0xd26a84bf7a9d8c3bL, + 0xd79b764460bc6435L,0xecd0272f07b0abadL,0x3ab2390382d7c63cL } }, + /* 52 << 70 */ + { { 0x3ec1874496d87afbL,0xb02425b5aeea74b1L,0x47cfacea954bb89eL, + 0xd8d6ff40cd26918aL,0xf2dbcbb19fd4dea6L,0xc481a4fe370fea30L }, + { 0x60df9f99a334a5a1L,0xeacebd61e6fbc823L,0x21932e6ba0140a5cL, + 0x6504deb051206cceL,0xaa4b43a350560eecL,0xaf965e7b6535123bL } }, + /* 53 << 70 */ + { { 0x25ce17e7be01690fL,0x82bd07fc216f7549L,0x26f98cddac6e021cL, + 0x815367ff3403972eL,0x01b1cf87cd89d71dL,0xe777db14ae24f544L }, + { 0x8081a692f628a076L,0x663adf4498b98423L,0x4a31e0bfbfb25b73L, + 0x5b42f193427be5b2L,0x24b1369118ae7408L,0xf13654a6e9998e84L } }, + /* 54 << 70 */ + { { 0xf8ec0a9e1b64a70aL,0xa1042bbb45fc54dcL,0x3ac4a936b7cbec0bL, + 0x0c2db54708eb7d93L,0x3f16e7c961ae36d2L,0xde25381b4611083aL }, + { 0xc1680ae3cf5edeb7L,0x7c86d74ce2b3398eL,0xa3ec4cde9945710dL, + 0x303d28ce864e3b4fL,0xd5b9730012956ac7L,0x9ad973be3c0763b2L } }, + /* 55 << 70 */ + { { 0x526c03ba1979515aL,0xe6492299cde06e58L,0x2215e3fb93ec91d0L, + 0xa086161bf783b7caL,0x89e39ff44ef0015eL,0x42c6ccc595e90587L }, + { 0x7577d689a81ec775L,0x272e4578daf4d896L,0x6d43c717cf01d7aaL, + 0x583814cffd5253d6L,0xee692f0666f7a3b9L,0x54048fe4e99bc633L } }, + /* 56 << 70 */ + { { 0x2afba531c0b9171aL,0x687dbe4cf2d75c55L,0x7c1c73f7fa17ba3dL, + 0x7886dd45063787eaL,0x14f59a18abd0a109L,0x1819df3c873bb66cL }, + { 0x76c969dfe01183f5L,0x486a120b1a78b6bcL,0xdfd702fac5686aa4L, + 0x2f74157bf3457569L,0x66c8c73e01964800L,0x0a2f6114def25ca0L } }, + /* 57 << 70 */ + { { 0x841838a8227220dfL,0x39eb77e2cd45ff3bL,0x7140aa47f5a060cdL, + 0x9fae5937b55bc3a6L,0x243390ea09b711c4L,0x69db2ace867a3eedL }, + { 0x14ee853a152860b0L,0xe3389c4edae0dae9L,0x4fa55ed1248a496aL, + 0xda6803e00ef304bbL,0xd19f48bcd04c2823L,0xe76b8d82a61773d1L } }, + /* 58 << 70 */ + { { 0x2e3a6332f7ae9a8aL,0x89f1576f78a12a00L,0x9597b2b245ab254dL, + 0x2017d6306309a625L,0x0385c02719adbe9fL,0x26c84f2014606336L }, + { 0x3808a31a3584dd47L,0x0fd2bd1b4e1da791L,0x70c2827fb894be27L, + 0xac97e84547d1faecL,0xa63c56fe9b01c835L,0x19c3b18067ca7507L } }, + /* 59 << 70 */ + { { 0x975dbe423a07930bL,0xf03fc9da8f7975f3L,0x94209a2522662e65L, + 0xf5b20e6b9619dcdbL,0xa95e2188ed5ee020L,0x2301e35abe7fb828L }, + { 0x4216b05b9caa0bceL,0x0534eef625cdec7bL,0x81f5c5f8613aa24bL, + 0x8705662951451a5fL,0xffafb623df15645dL,0xe19276fe79c497c5L } }, + /* 60 << 70 */ + { { 0x461bb6e1d118ef5cL,0x277e378d1f4bf653L,0x3b4138849ccaab1cL, + 0xa5979a3ecea9c61fL,0xdc2a23c09dbfe67dL,0x5f7e32f5335cb2d7L }, + { 0xeefe71a87accbd69L,0x65d961341df58e12L,0x17bafa56538145d8L, + 0x2a723472695df807L,0x132b5320394ec082L,0x96219e617d0ed426L } }, + /* 61 << 70 */ + { { 0xf08ee7071ec12e08L,0xb9a51fc40c4917aaL,0x1aa9b778aa085b77L, + 0x3b3e40d72e62193aL,0x3700217fdc211bb4L,0xed03eaf4fbea2fdcL }, + { 0x82e00364c55111e0L,0x3be15019e3cbc07cL,0xf142d230055b597bL, + 0xf68837b1a063deb9L,0xf1368df622e72e40L,0xfc712c67ab522f37L } }, + /* 62 << 70 */ + { { 0x02ca4c0dc3c8ee2fL,0x1962366a0d75f552L,0x6354ab90a43c43e7L, + 0x9f46429f7668d14eL,0x70ffaa6d0ca59472L,0x231fdb485a95ad7eL }, + { 0x82ae5f0acb2ebd5dL,0x2dc8417ce51b1d3bL,0x5052133a2fb456dfL, + 0xad3b4cf2bad61a16L,0x59f283a48d76344dL,0x5f15465772b18fdcL } }, + /* 63 << 70 */ + { { 0xe0ef0c3cc73a7131L,0x8a4e0cdd43ea81fdL,0xceb5fcb8d6d6ce6eL, + 0x941179893535781dL,0x20f5e952b37d4531L,0x5e77f33364c25699L }, + { 0xb6645e8fa6d3ff57L,0x6dac30cb5b9bfdc0L,0xb29648e73ebb655aL, + 0xe1bf3f4005ebc1d1L,0x1b12288514025fdcL,0xe15fab026c5adaabL } }, + /* 64 << 70 */ + { { 0x86230934f14a99d9L,0x1cf9c66e97c1c092L,0x01e186ba6f595ed3L, + 0xd3291c3de2284a58L,0x03dee2311b9e5e25L,0xf2e9b4ad15cc9f53L }, + { 0x4fba15679770c29dL,0xbf7d673650c4ae2fL,0x86901eb92532d015L, + 0x4396fd784e7455deL,0x2fbcea8fbcf811c9L,0x3981ad15ae952b37L } }, + /* 0 << 77 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 77 */ + { { 0x6bd2c54d4cb89afaL,0xe78c8bfa36527751L,0x27f52654e3eee747L, + 0x56f205839598d907L,0x5f91c2d027cb3712L,0xc501819fa3e33c5bL }, + { 0x248490aa4eded738L,0xde7ac94427789065L,0x20138b3d74f7d38bL, + 0xae791f602fb60214L,0x6b4fb300bd033d4eL,0xc69c25d9bdfd1f17L } }, + /* 2 << 77 */ + { { 0x0c3d2056be21a890L,0x1c1ffbfb8fcfba99L,0x1b68a98b1fbf56caL, + 0x56fd85ff396e31cdL,0xd2ca58444382c03bL,0xc442030a7d3ef917L }, + { 0x4129a731426afafaL,0xacff17ff5eaae9c6L,0x9e854180653f3b23L, + 0xe65a1a149ee066bdL,0x3420084e362ea5feL,0x6fe58801c7911e2eL } }, + /* 3 << 77 */ + { { 0x43f0ae676c4be6a0L,0xabc6a17a504bffebL,0xd5be6c25dbb4492eL, + 0x7efc9ee884bff97fL,0x54fbd9d7062da2e2L,0x1befeb61c6d2ac32L }, + { 0x14cf6dc0cbafef5bL,0x8e640e4771d12192L,0xd0566543d9a16800L, + 0x9cc2ade9beb1e28dL,0xcbfeb45038e65833L,0x3852eaacd0f5acb2L } }, + /* 4 << 77 */ + { { 0x5e930d65c4650b85L,0xbe96b2ae6350da54L,0xcfac4f7efa08bd49L, + 0x277e8456a6e10f64L,0x41be3067407ac162L,0xcfd1d03252a9b68bL }, + { 0x8d8d216a9c337e0bL,0xace044dc4e1b9cf5L,0xad9a4102c60d54c3L, + 0xb09420f028815187L,0x881179c60b3b8e59L,0x872685ed5b09aba1L } }, + /* 5 << 77 */ + { { 0x26d43085ee64924eL,0x5eb54d1c4bd6a77fL,0x69a69ccfd1ca022fL, + 0xaad92723a3342720L,0x51e27b54421d836cL,0x15e83917fc72a1adL }, + { 0x183e75d14ddea73eL,0x73fe3b9fbafcecfeL,0x0197e0925daefd64L, + 0x2fa89f60f85b8249L,0x95411aafd23cd465L,0xb7dbe7485d9a459eL } }, + /* 6 << 77 */ + { { 0xab146c207dfc66eeL,0xa7250dcebb6869efL,0xaeba44439d7ad5f8L, + 0x919f877ec48059f0L,0x780ecd232c6b5c11L,0x586daa8e38625f8dL }, + { 0x46a46c789911c031L,0xf56f74fc65303d34L,0x825bb06d4f384eabL, + 0xd147719ad6aa2bc2L,0x745fd7460750e1acL,0x2ef411494b3ec757L } }, + /* 7 << 77 */ + { { 0xdb24cd1af10ea702L,0xf393de57461f8ebdL,0xf56f414e5cfaefecL, + 0x758c8d854690230cL,0x6740c974433d2594L,0x69d92a620aa6bb20L }, + { 0x17be342e9b0bb191L,0xc1cd309fdbf5c97bL,0x089134df8998140aL, + 0x33809a7e82afcb85L,0x409d2a481db47b21L,0x1d54e86ccdb1bccfL } }, + /* 8 << 77 */ + { { 0x22313dee5852b59bL,0x6f56c8e8b6a0b37fL,0x43d6eeaea76ec380L, + 0xa16551360275ad36L,0xe5c1b65adf095bdaL,0xbd1ffa8d367c44b0L }, + { 0xe2b419c26b48af2bL,0x57bbbd973da194c8L,0xb5fbe51fa2baff05L, + 0xa0594d706269b5d0L,0x0b07b70523e8d667L,0xae1976b563e016e7L } }, + /* 9 << 77 */ + { { 0x47de66da62a200a6L,0x67b0ce0d65186fb7L,0x8e8f0248238d23a2L, + 0x5a44a886c1114a6eL,0x36383e5be8ec166bL,0xd36077d8ca7d2e43L }, + { 0x332f98267c45e8c6L,0xcec2ba1355d968faL,0xdca664a84a56f7abL, + 0x954652467b03621aL,0x471f66259b6e55d4L,0x401a6a5efb0714e4L } }, + /* 10 << 77 */ + { { 0x2fee0c6d6046896eL,0xde64c4e0466a90efL,0xb0c9755a55395f3aL, + 0xdfe2dfd6ae3879d6L,0x979853c2d656c53dL,0x58bb6121757f381fL }, + { 0xdfae5707980db8b8L,0x6d4c7cd7d7752f7fL,0xdfb77382c5dacfccL, + 0xd0fca93104177fbbL,0x9ef6d3e4b67891ffL,0xb599dfcb26024609L } }, + /* 11 << 77 */ + { { 0x79bf86761cc06935L,0x6bbc2d3fd44fe6bdL,0x092678c486f9f728L, + 0x05631aaf54c3fe18L,0x217adbbe95eec92fL,0xdcdbfdfb955bcba3L }, + { 0xf938779c01bafb04L,0x67f599e73ab755e0L,0x793b591fb00c1315L, + 0x7ea2dbae3f2d0909L,0x05436dce46614955L,0x02b988888060d145L } }, + /* 12 << 77 */ + { { 0x795df21ba1ebf7c0L,0xa98f2466681b5da4L,0xea18a2ab413b507dL, + 0x9243326688324aa8L,0x2b91dcc2f74d83edL,0x95054b471f411a13L }, + { 0x50869778e3c621f2L,0xb950f3a9427faf54L,0x8949bf7dae29f080L, + 0x7c16cd020ef3a3c8L,0x7883c719b122cd0aL,0xa2cad71fc03bd749L } }, + /* 13 << 77 */ + { { 0x60c794125b3ad53bL,0x91c62ac783981a98L,0xa6f30f473dcd7196L, + 0x55417e7598b4c589L,0x2ce067cb345b89bbL,0x4787f0db71936e38L }, + { 0x208cb360331d7de3L,0x4b0347aa15022254L,0xc66e58865e8af235L, + 0xdefed4c591a68080L,0x0b8dbd336eeb47a1L,0xb6d44d36f732c8d2L } }, + /* 14 << 77 */ + { { 0xce0b1700d3aa7741L,0x13cc58a90df0cefcL,0xa96149c7da3a1816L, + 0xd387d361561277fbL,0x2294f77cf2c363c6L,0xc8d19d51355a8a93L }, + { 0x926dd80092affccbL,0x70c59253686afd1eL,0xe4826f2370c4d8b5L, + 0x948d43dba2226c34L,0x6ffed99e2a097aaeL,0x80e7a99a2ce18037L } }, + /* 15 << 77 */ + { { 0x070c3f39b7f01551L,0x21b249434512844eL,0x46e33e16e2e2a68cL, + 0xd79daf0ca549dcb0L,0x634fa53966a7b9bfL,0xe856d0a8702990f4L }, + { 0x246e5858e466abdbL,0x3f3ad441edfc851eL,0x9ab3db2c2e397554L, + 0x6c5b1a39b5cabd32L,0x695649b2427c5cefL,0x6179fa0f82ab4f68L } }, + /* 16 << 77 */ + { { 0x022aa09d236b71dcL,0xb1ce6a0ea65a7640L,0x317344c5b38b417aL, + 0x29a74cdb436451ecL,0xd898eb6ca8b1c876L,0xf0134f99b74eeffdL }, + { 0x0d9eab64225d71f7L,0x9679b453ceb3cc2dL,0x37c894ce14dbff2fL, + 0x3704d34927065280L,0x9ee435d8ba29a0cdL,0x675bea1409c11c4fL } }, + /* 17 << 77 */ + { { 0xa8454e2b63263ee1L,0xf4c8a384cc42ffc3L,0xb260754916bf086cL, + 0x610d299cfa46a481L,0x21777897ce41a4d1L,0xdfc04bb321573cdeL }, + { 0xac7d9433ced06177L,0xfdce0356a281b9ceL,0x22abd67970d48fc7L, + 0x1e4ebf7750514178L,0x7f0869ef21a255c8L,0x80ae565c29bf477cL } }, + /* 18 << 77 */ + { { 0x607cfaa1a38a18a2L,0xb29ae9c760bd3f91L,0x4991432d76a4c22dL, + 0x4fe8dcd380e75452L,0x7aeea8150925ed79L,0xa0cc6823b7abca08L }, + { 0x647b164fb0a555dbL,0x60545cd3d6076f3bL,0x7e801133807a2045L, + 0x74b2200743ac7e22L,0xdfb58fd1716d3e5dL,0x369ad09947772c45L } }, + /* 19 << 77 */ + { { 0xb6c5dc0635ba2007L,0x6543c6307921115fL,0xa7e5a662eb6c493cL, + 0x728159f54a0b8d6dL,0x8cb07ef1b943fa72L,0x4a2c5cc923c46a98L }, + { 0xea078b478c26221eL,0x68ef5015ce2be601L,0x3048b5de5239f8d2L, + 0x00a98cd419bbe0e5L,0x0a34161caa94a375L,0x879a9a7aac8a411aL } }, + /* 20 << 77 */ + { { 0x2d968968e3f6217fL,0x60b781ad1fb91fc9L,0x44ce23514a84e6ecL, + 0xe8f5627d00a3d089L,0x45211a094a980480L,0x11029b7263274860L }, + { 0x44601cfcae0477aaL,0xa05a67df269ca043L,0x9dc3938fb758fbd0L, + 0x43d5d89abaa35f8cL,0xa38dfa1f2ab3436aL,0xa29653bc529b7061L } }, + /* 21 << 77 */ + { { 0x6ab2e32b982cd162L,0xdd690ed7794d6da0L,0x8fee0b461862f33eL, + 0xbf9aeee210d244fdL,0xe485aac27dbb57d7L,0x7f7ee4bc0ff23849L }, + { 0xfb3c6255171ba49eL,0x089b9986133e45deL,0xb6c033106d04b924L, + 0x216af9223ea88efcL,0xe646a49b5fd52347L,0xbb495d2ee404b86bL } }, + /* 22 << 77 */ + { { 0xe24934ba07fd5fcfL,0x4840e1a6a1027598L,0x4c2294d245eead89L, + 0x7717bb604fda652dL,0xe809c21878370655L,0x417853499151e578L }, + { 0x8bfe121cede554c7L,0x96037a33952c153cL,0x80458ed86a5b30f0L, + 0xba331cf9ca28472aL,0x31b5f463e6c177aaL,0x68c5dc9183ec14fcL } }, + /* 23 << 77 */ + { { 0x8b78d2bff13dc6a5L,0xacd7e0902285c2a2L,0x6aa7866cb47e9427L, + 0x7c2483474d9fa3f2L,0x2e668396f0661aafL,0xf491cd6d08cacae4L }, + { 0x772a131158f9a617L,0xf372dcd6b2011823L,0x790a5ae54e6bd2a9L, + 0x035ff238fee0c8c9L,0xcbbe828cb0b8c53dL,0x9edba1a40af83ca1L } }, + /* 24 << 77 */ + { { 0x2fde4893fbecaaaeL,0x444346de30332229L,0x157b8a5b09456ed5L, + 0x73606a7925797c6cL,0xa9d0f47c33c14c06L,0x7bc8962cfaf971caL }, + { 0x6e763c5165909dfdL,0x1bbbe41b14a9bf42L,0xd95b7ecbc49e9efcL, + 0x0c317927b38f2b59L,0x97912b53b3c397dbL,0xcb3879aa45c7abc7L } }, + /* 25 << 77 */ + { { 0x62ecc0cc429bdc1fL,0x6a8000add447c01bL,0xc2dd42354f23e5d2L, + 0xe6c1790a01b4a0dcL,0x2497e53c24393079L,0x0a113afeb2a00faaL }, + { 0x96c1bd5011151480L,0xded805425aad86dbL,0x639f24cb76720e92L, + 0xf17703b7d825eb92L,0x10f8924e82d2657eL,0x6edc843c627c5236L } }, + /* 26 << 77 */ + { { 0x472226adf80911c2L,0xfb50c3a5e087a3d8L,0xb194551441848a6fL, + 0x61f4fbba9f17504bL,0x8c59b2c48e33924bL,0xa7641127ac7a8608L }, + { 0x79feb7fc164a2330L,0x9e0fd67253a44e7aL,0x9c5c973081953c30L, + 0x25d6932c3f6342f8L,0x29e8b7664b574a69L,0x02f90a46a5de3639L } }, + /* 27 << 77 */ + { { 0xe2d1e2a3465ab77bL,0x2ca0f6a3cf45823cL,0xa1b12306dbdce9d8L, + 0x820470e7b4b39ca0L,0xe48956c76e847681L,0xc8ed8fc8fbf6970dL }, + { 0x52cb109419ba40aaL,0x08136d091efbaaa2L,0x99dd1ad27d71e1c4L, + 0x10001f97a3a59a3bL,0x79d229e460e4cad9L,0x6d443d8756732312L } }, + /* 28 << 77 */ + { { 0x8d6b28b4d7cfe9f0L,0x6ee5407a4dce4904L,0x7acee5e7ba0b67f6L, + 0xd4cf6bd2abf447aeL,0xc085e8e2e7330268L,0x23edbd5a145689d8L }, + { 0xd2ae9bd21d7b0e7bL,0x3196410ec4fe6ecbL,0x964bef26ec2cd59dL, + 0x09c6d07dd5e0bf03L,0x379f131ea65b646bL,0x0439c37964849830L } }, + /* 29 << 77 */ + { { 0x8afc9a5eae562537L,0xde81bbaab2d4172aL,0xa272c6d53db07247L, + 0x08b903ffd86ec6f8L,0x3373041f835aa84aL,0x02e8ecfdc8f18f48L }, + { 0xed6b2784ccc11e64L,0x03e45e15842a8292L,0xfcfcc54b653b86efL, + 0x9678fe7ed9ea2f91L,0xee5bf4584efceafdL,0x188e49d59fcc4be9L } }, + /* 30 << 77 */ + { { 0xeb0098cf67a224f8L,0x14e486c90991108dL,0x0dad68314b397687L, + 0xf2a4f6cb9d089000L,0x3fcc8803509f7376L,0xdbdf06dddb5d6f8fL }, + { 0x2cbf342806ef3e46L,0x4a4bd5eee432ca41L,0xdcb8bdb70e2d391dL, + 0x941b9a4ec1710ac3L,0x25cea4333d62c34aL,0x9136e5cd881a70b7L } }, + /* 31 << 77 */ + { { 0x9bfdb9b310c3ed1eL,0xc9a225ec0cd146c3L,0x1fec4316573c4414L, + 0xe11a408f2fa8323cL,0x198c760ac3e988bcL,0x3f8a5a1caf0fda3cL }, + { 0x91e89f11f6e78264L,0x3cee0165264eebfdL,0xf9412b049898eaa0L, + 0x3c67991a382e46e3L,0x8d833d7a80acd219L,0x746a696c9d233f20L } }, + /* 32 << 77 */ + { { 0x8b3269a2714a10e8L,0x64cef040a4a2727eL,0xbc5ac714e428865cL, + 0x531dd17ffdaba094L,0x86d2405718d657f2L,0xe807b0d92f99dbbfL }, + { 0xc428a80f6848ef88L,0xb3ef0709d0b73ce5L,0xa752691922a5d255L, + 0xbfe6392318a18586L,0x28a0c772fcf633b3L,0xad22b4ec3f3c5298L } }, + /* 33 << 77 */ + { { 0x8b6a2f1ae6c40f85L,0xf0f44c54f44cf3f0L,0xda635b687b25d4b6L, + 0xee59c00f8cdc9d5dL,0x36509f58cc4876afL,0xe37564484e2c550cL }, + { 0x20f965b565974809L,0x26481694e3fe3a63L,0x6778b20becd272eeL, + 0x9b6bbf39c9072853L,0x4f61f192b0436bdeL,0x98bf7dafd0221263L } }, + /* 34 << 77 */ + { { 0xa06a4b56e0442513L,0x6537e117dd513547L,0x89e38ccd2a654224L, + 0x2fe734bd005ee292L,0x54d6933498cfece0L,0x85de5c9d85a79bf2L }, + { 0x21e072bdcd3da6a9L,0x7a5d707b8c16b8a1L,0x43654d0142d04cd4L, + 0x07d589b94a88c151L,0x5bfe9ea2df726b52L,0x877c46ffcf728e4eL } }, + /* 35 << 77 */ + { { 0xe338f606fa009c33L,0xce596aafa351fe32L,0x8ae0e06123968387L, + 0xcdaaaa9465c98e2dL,0xec6b8a818acb9355L,0xc2c67e7facbee162L }, + { 0x7068df85517df4beL,0xc34a6ecb7c5c076aL,0xf4193aab6250f0baL, + 0xe0cd2f3fa6c9ea47L,0x23a57ccc6488135aL,0x044d73e6c12b842eL } }, + /* 36 << 77 */ + { { 0x9d8a78808078c8bdL,0x6ea07982076d44f1L,0xc58fc94eeb3bfda0L, + 0x0b9e72200dd11b13L,0x8bd58e3aa74a005dL,0x7a30aeda115b7d33L }, + { 0xeb0037e6ef2491ffL,0x0fa2d1a7fb39ecbcL,0xb75aac645ac598f7L, + 0x2c3c103341f61b42L,0x5a330bf01f7eb885L,0x1c96124d33d5e27bL } }, + /* 37 << 77 */ + { { 0x3f157ea1b28d1640L,0xa41c98f2c96806ecL,0xef261c3bb099566bL, + 0x11d88be30aa23f1eL,0x9a721a2c47ed1540L,0x214cb5b0e4431563L }, + { 0x36a95c20250f6b19L,0x6b44f01d30eb0249L,0x141777dc5c67e2beL, + 0x6926b32ebbe7bb63L,0xb72fd3bf756cbae7L,0x226661a279dfb835L } }, + /* 38 << 77 */ + { { 0xc25a44e3300b8f91L,0x08aa9d5691ad1a78L,0x130c561ffdd2a064L, + 0x36f0b4608c05f94eL,0x748166e158a351b3L,0xe408976147d40ed6L }, + { 0xa0ba5e5d1b2e3400L,0x94aea3b6687f6492L,0xf4975167ea262235L, + 0x8014e81143e800d6L,0x635a3c516e5df6dcL,0x71207caf2eb20366L } }, + /* 39 << 77 */ + { { 0xc00364013638e940L,0x24baf83bbb70e3cfL,0xc08a99b865dca079L, + 0xc070152e0d40622bL,0x44880b191697468aL,0xcf95519bfebc1644L }, + { 0x7bdc41d7911a74efL,0xb88180314ad83219L,0x53c523185ad49f95L, + 0x4e59a29f6d112b66L,0xb2707b9c7515de9eL,0x8322492c150c9bdbL } }, + /* 40 << 77 */ + { { 0xcd81bdcf24359b81L,0x6fd326e2db4c321cL,0x4cb0228bf8ebe39cL, + 0x496a9dceb2cdd852L,0x0f115a1ad0e9b3afL,0xaa08bf36d8eeef8aL }, + { 0x5232a51506e5e739L,0x21fae9d58407a551L,0x289d18b08994b4e8L, + 0xb4e346a809097a52L,0xc641510f324621d0L,0xc567fd4a95a41ab8L } }, + /* 41 << 77 */ + { { 0x966f961d46ff607bL,0x7e52ad9bb29278c3L,0x5b9b84b9bc6835b8L, + 0x00e4a35ad834701fL,0x53aa139866b8f484L,0xc397f087de063112L }, + { 0xb811a9a24e81b980L,0x8d9c38ef8d680c4eL,0x0a7e66ef1c8db33aL, + 0x1c7e636bf4e17483L,0x25c0a690ae9acf11L,0x5b0a435985966d63L } }, + /* 42 << 77 */ + { { 0x3d4a4ee0a3bb186fL,0x84de7765082c283bL,0x499bf10a8fc8baddL, + 0x85191faa2db59e7bL,0xc5964c20ccc587a2L,0xfa59313b9cf52cfeL }, + { 0xe614ce878da8cf4eL,0x7d8aa381d60e91b6L,0x054dfc4a0d5c0a8dL, + 0xbcd89aef28a15c79L,0x2af1121efecbc916L,0x6aa49bcb44f30755L } }, + /* 43 << 77 */ + { { 0x7953c7ec7b7dc4cdL,0xb709542edbdd99baL,0x7a2afc3eb30b5c70L, + 0x7669020fcd0cc804L,0xb57c1d949fade8f7L,0x5ae7d78cb2eef81bL }, + { 0xdd5457edca354c1bL,0xa531d85c8f5ac058L,0x5fdca829009e0aabL, + 0x8df732f6f2bced0fL,0x3ee658627faf57d5L,0xf7a265735c2f3bc2L } }, + /* 44 << 77 */ + { { 0xe1ce7f3725a64849L,0x760847744da790f0L,0x4638f287cf5f319fL, + 0xe36f3c5308c3786fL,0x07042ce1985513cbL,0xfb955cbf73d9cf3aL }, + { 0x3e68a2cacde0774bL,0x321f49b76dc2c816L,0x9bfed81fd76c4d3bL, + 0x985b34fefd49fa62L,0x2a3de945ebb8fa9fL,0xcaa616f0405da5afL } }, + /* 45 << 77 */ + { { 0xf3fa1924bc6d86f1L,0xbcf9d3cbb41dde67L,0xf96431168057ef19L, + 0x09315fc52177ef64L,0x1ae99958fcf594a7L,0x7c4baeefaa4dd788L }, + { 0xff1ed168a2bb1bf3L,0x9c697d19b4a651c5L,0x5fe29bcc0df8c999L, + 0x16446aa446c45428L,0x3a51398061700e83L,0xf34133593f034bc9L } }, + /* 46 << 77 */ + { { 0x9cc126b8cbf28cbfL,0xf3f8aa7c1e6d63ffL,0x533e48d2b7f80225L, + 0x8fea0d204749d781L,0xd8ea614b326f8185L,0x9cf3e07753c541abL }, + { 0x09040b60d95c9367L,0xc1b19940f5eabd9dL,0x80b0793cd8f8bd1eL, + 0x95fafd6fadff120cL,0x071b1841ce155f8bL,0xa85dfc8cd29d9d9aL } }, + /* 47 << 77 */ + { { 0xf38e0fdea761048aL,0xd9d5a22c88a93773L,0xbd58470841a99bddL, + 0xa31ef1edebb412e0L,0xd5c4fd5a0274ea16L,0xaaf215f380c1f0f8L }, + { 0xe842a4537d3dfd08L,0xb5c877ae5a904548L,0x3dadd2eb9c6ddbebL, + 0x7f97c541e84e54d9L,0x6183b6ce1b8d8829L,0x2a20c212f50534a5L } }, + /* 48 << 77 */ + { { 0xc8c9b0ae7176dd90L,0xa95604542917d487L,0xb03b7946e62c508eL, + 0x60425926e9fe2321L,0x73b10bba80c1d136L,0xc30a847d9d218c9cL }, + { 0x6ed0c8ef2073859fL,0xa176eabf432dd97fL,0x3078096ab9e96167L, + 0xb28f0e6cc473e377L,0xb44e4995683a3bc8L,0x483512eed3523796L } }, + /* 49 << 77 */ + { { 0x7ff5827f22adab31L,0xa7e859ad43ee005aL,0xfc2387f402c9629eL, + 0x6f39e84add12b107L,0xd1378037c097d3daL,0xc677b554d70d107fL }, + { 0xec15469fe4943084L,0x1f0b13b19d412b76L,0x3b3b49b48a265a31L, + 0x45f28cc7dbe97ff2L,0x33f0e31f4efa0f0aL,0x6b22b99e37a5591bL } }, + /* 50 << 77 */ + { { 0x0a751d3eae0538e1L,0xd51b039af14135e9L,0x92eae0f6e8bdf562L, + 0xf253bd5c66557b17L,0xc1ff9054ef26b81bL,0x9d586d39eafd711eL }, + { 0xd2b05d3d4f431502L,0x847d727f5823cfe5L,0x2c4e236a8e99840dL, + 0xa407e2d87c5981c6L,0x989dd28c69ca34b5L,0x2e8ec6b09fe586e7L } }, + /* 51 << 77 */ + { { 0x43161b5c40bda312L,0x8fd476b8a10fbb2fL,0x84cbf7579e5d9a4bL, + 0x19bb5926a9a31956L,0x66ed993aea9db48aL,0xd7897780ffb0361eL }, + { 0xb031e035adfa3661L,0x1be83caf2296b4d8L,0x8802c98b0024cc48L, + 0x73adb0c0bac1aa5eL,0x17df92e1bef75b41L,0xd753e99903d800bbL } }, + /* 52 << 77 */ + { { 0x24940b868733c1c1L,0xf5dd77ce2ac072e1L,0xc248ad6bf7bdb8d2L, + 0x423e0cc9d9a8b926L,0x4318d600e6da05dcL,0x3e557e08ca27dfc9L }, + { 0x8dc551cdc5dc822bL,0x160da94cbc8fb392L,0x4ffebd2aa6d4d363L, + 0x8190c17db1ce15a6L,0x1abcd1361e9dc500L,0xae3a477c9ee52a47L } }, + /* 53 << 77 */ + { { 0x67ab01575ed80bdfL,0xc77067b69aeb4a86L,0xe6e26abdf7880a93L, + 0x782248db1e43049cL,0xa902c41016d78616L,0xc6fa899fbf309f15L }, + { 0x81e1532d672d951bL,0x84280ba386556a0dL,0x83190bfb55199078L, + 0xbc11e8c25a1c4691L,0x8ac60c7f21152509L,0x4211923ec775dcd0L } }, + /* 54 << 77 */ + { { 0xa63b33f6746418acL,0x62085e0eb7359443L,0x3b43ea7b5fb598dbL, + 0xf4a0f4442b365528L,0x7f4d2ff3eb55a5ddL,0x012cd591f189eadeL }, + { 0x3fbdad99f58c8f84L,0x71dc1b0093bf34dfL,0xfb63f09ce062a588L, + 0xd5f0f0ad6f24b66fL,0x940e23c91813cd9dL,0xeff8580b55f241dcL } }, + /* 55 << 77 */ + { { 0xb30719d8b7fb5f3aL,0x8f74305b43275030L,0x2fdb613bf23628bbL, + 0x75d9868ad945ccdcL,0xbfae46f4f0b73348L,0x48ad8bafe26679b3L }, + { 0x3aeb4743d0b389bdL,0xd2463ca37916297eL,0x3a6f37c820f52fd1L, + 0x7bfade4495ffa348L,0x1e3f6282a25cb79cL,0xac3320d5229bd2a3L } }, + /* 56 << 77 */ + { { 0x261578c7d57c8de9L,0xb9bc491f3836c5c8L,0x993266b414c8038fL, + 0xbacad755faa7cc39L,0x418c4defd69b7e27L,0x53fdc5cdae751533L }, + { 0x6f3bd329c3eea63aL,0xa7a22091e53dd29eL,0xb7164f73dc4c54ecL, + 0xca66290d44d3d74eL,0xf77c62424c9ea511L,0x34337f551f714c49L } }, + /* 57 << 77 */ + { { 0xd1f879197700d61cL,0x21728fe49a89dc22L,0xdd3a475be6d93642L, + 0x3f8554d6e095363fL,0x4b8b712463e1bb11L,0x75db57e6c6da541dL }, + { 0xfdeb9e46ac8342fdL,0x8ab4875114905993L,0x48150a06b2efd023L, + 0x9f5f513df415bff5L,0x39b1234eee9d7915L,0x735570a7dda66da5L } }, + /* 58 << 77 */ + { { 0x3a79a1756e3d4ec1L,0xde0ee6c79936b689L,0x37a7d9ec7fb84ee0L, + 0xe82810d38fe1f44fL,0xbe433c7253049e9eL,0xe72ef4f5fb49e274L }, + { 0x525b72094b4ad28dL,0x37bfb857164f5f0cL,0x60327e31ac68d566L, + 0xdb027619bb71f137L,0x8abc8026abb6e829L,0x99702ff15e838117L } }, + /* 59 << 77 */ + { { 0x974be1d30696f1a5L,0xf884616dd3832430L,0x6997c37ce9dce1acL, + 0xf4bad00e2e5cfbc4L,0x7727adf8e327a9a4L,0x15315bf16aeeb305L }, + { 0xe697c0af09fbffceL,0xe4291f7589f86a5fL,0x765f1904487b12f9L, + 0x752c58a5b7f8ca88L,0x9f9563d473716bf7L,0x48803cdbfd032783L } }, + /* 60 << 77 */ + { { 0xa0d935ce9050c5cdL,0xc1e062d03e9b902aL,0x212d0e5dc3054c00L, + 0xdc9c3f2de70ad96bL,0xa2182ffbc2742144L,0x4680d472a716993fL }, + { 0x9852bb00677f3756L,0x2bb3d78435e6213fL,0xadfdbfe07377fdc7L, + 0x41db795d708afddfL,0x6848cef57727ed86L,0xb24e416aa6c1dd1aL } }, + /* 61 << 77 */ + { { 0x36d76f2f2edc95c2L,0xbdf2a67810b0670fL,0x49fc8c43b63877a1L, + 0x23182ed3a87c8615L,0x94c21da96c011a44L,0x3bc0b86860d3c162L }, + { 0xca6a158244815192L,0x4bd1ce04fd97b78bL,0x1d0074cddc750023L, + 0x40cf8233cdfb0c7cL,0xe4e28aa8bbbfbf3dL,0x72656155b6eec7d2L } }, + /* 62 << 77 */ + { { 0x5b1be65b912b364dL,0xe6369ca1e0335426L,0x249740d58420e7daL, + 0xff13a26f1ac1acf4L,0x0ecee744b9634fb2L,0xbaa77d57d664ceb1L }, + { 0xadfa7625914f3f7eL,0x17c75e99bbcffe16L,0xcf557911d64aedb0L, + 0x8a4b7b49c3644ba0L,0x115240401eb7bb97L,0xb823c21a70fc7b5eL } }, + /* 63 << 77 */ + { { 0x45db2c038727c0fcL,0xf5aeeb7bbae2c896L,0xfad1cc32eed15b82L, + 0x65d4440a8609b00eL,0x35698d956b4dbd25L,0x861615bd0f6cda68L }, + { 0x578efdaa8aec1e99L,0x87ddae76fcf67480L,0x5ff5a1304669ccb0L, + 0x5fd2f31a0b98ee60L,0xccad491a3cc4c003L,0x6dcf25bbccbc46e0L } }, + /* 64 << 77 */ + { { 0x93a62e7cfa43699cL,0xdad738901bc422d9L,0x265e3cbb10cc9544L, + 0x28cceb062f37154cL,0x6b79b0713bf2e08bL,0x88e025df3ab39091L }, + { 0x50a8d04d126522bdL,0xeabbc1b7b779bacfL,0x3db4336ac21cc62eL, + 0x4747f0a36fc00450L,0x067cbf1c544b2d95L,0x2480b7d8fd2be7a7L } }, + /* 0 << 84 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 84 */ + { { 0x0233e423d52eb122L,0xc28483521154b0c9L,0x2ca09cef6349e35bL, + 0x3b70afc3ded2ec54L,0xc813474d52dded3dL,0x2d3f21bf12f00ee0L }, + { 0xa0908f7692f215c6L,0xb97d60e94e9c0440L,0x84ad10c134b6a8e0L, + 0x6f37fd956e7c163eL,0x7caae8c8d057e0c3L,0x534f52c2553721a2L } }, + /* 2 << 84 */ + { { 0xa354c1de72a041b2L,0xe83df25929d1330aL,0x676610999d532bbdL, + 0xb7c2f4cf52011751L,0x6945d34ff659e35eL,0x6217d20ba1303b7bL }, + { 0xa200ddba25751badL,0xa74a729001d3566dL,0x3018445faa82b46fL, + 0xc3e6a3acfccedc1bL,0xe86ae8703353e29fL,0x1c8085bbfd7e8547L } }, + /* 3 << 84 */ + { { 0x728c8e145d1a678fL,0xf944da572ac89a2dL,0x3016c2da4796df72L, + 0xf6d79e4e00a55efcL,0x4fced269526b1cb8L,0x4a93e47791f165a9L }, + { 0x528b8572f84f90d3L,0x3b30376e5e725561L,0x4f903520e07bb990L, + 0x07ddb97f4ea8ae6bL,0x29c01e70b3b735bbL,0x825c7f6e5000dd4aL } }, + /* 4 << 84 */ + { { 0x306b63e3b4dcea78L,0x4b10209213636935L,0x36bb68898bdeddeaL, + 0x9331655d67a329acL,0x14c7fe26ba92ccceL,0x4e7d6929be0519b4L }, + { 0x0dc39dbd164d50e2L,0xd4c430a0b1679cc5L,0xc7f78818fa8682baL, + 0x43396eadb60aad97L,0x751784d7ff2c64ccL,0xd37928be866af43eL } }, + /* 5 << 84 */ + { { 0x3742b61e0475f547L,0x48b2a2c2477722acL,0xf52c6787abce3401L, + 0x4749711ea4cb41b4L,0x7ce0dfb03fca817eL,0x1c1e3bf996e85048L }, + { 0xcd65250e40faa8e9L,0xa8edce7017d9b93aL,0x73523cb2b4dd5619L, + 0x15ba773abb5379f5L,0xcc5e62d6c0a847baL,0x7efe5c7c04d852deL } }, + /* 6 << 84 */ + { { 0xf0a69e685a91c9aaL,0x0304d20105c13197L,0x773a3ab7cd14af1dL, + 0xc0b88edd558d555dL,0xeb12d197d2e63dd6L,0x4a8e849fbcd9cdb3L }, + { 0x06432985965eaa14L,0x453d93861a5a6f43L,0xbd28f6164171b9bcL, + 0x37781639bbfcf90aL,0x1f93898f3a36084dL,0x1fefd8b7dd00ca75L } }, + /* 7 << 84 */ + { { 0x3b8d8e495e456124L,0x967ed511967c17b7L,0x1d72430c2aad8c67L, + 0xe8c5d506b82c1673L,0x989978868a0fb41dL,0xa9d478f70f81234fL }, + { 0xa0c941cf44cc0614L,0xc033c99024ad30f5L,0xaa7de296101f89aeL, + 0x4cadd8e3ca6a3227L,0x3b4db51f2764ec0cL,0xcbfe70fc09256db4L } }, + /* 8 << 84 */ + { { 0xb9207dbc2b2f1bccL,0x6afd6871a3e83ef7L,0x49924e5534ba150bL, + 0x2935ebf1dfec9972L,0x34bf5e94b76f870dL,0x22d0f32b4c20385cL }, + { 0xc78ac1728ccc8e72L,0x7b45b8220ccecb0aL,0x76c67ee4cfb4b8baL, + 0xecfaefb2cd8724b6L,0xe9bc3d67340bc1efL,0xed40b2b9ca5541b5L } }, + /* 9 << 84 */ + { { 0x5d1bd16518f8e17dL,0x754986b7405f822bL,0x420b1b24d8753fafL, + 0xab038e0608ff680cL,0x33621a0fa3649f49L,0xe24b84db78918eb6L }, + { 0x0e669672c8bf4168L,0xcb7fab33171eab20L,0xa097d2cc4808be42L, + 0x4f4e395f5842b80bL,0xddcb1e51a579145cL,0xa635d0cdf330ae0cL } }, + /* 10 << 84 */ + { { 0x9b8a3eb3069e6432L,0x43aaa7fc721397f7L,0x46e23c6ca7e83a71L, + 0x71b261d593fa3c25L,0x4a47a1050f523a72L,0x31919e898dcad752L }, + { 0x4c8b06e70c5dd2adL,0x677ec5f38bdc55e7L,0x4372d55dcb1b5828L, + 0x7bf054c1f04dd321L,0x4e8c1a992e44584eL,0x6807803751d35d78L } }, + /* 11 << 84 */ + { { 0xa6d78a3d754377feL,0xcc17c26ac72ae5e6L,0x2f0ab93b1c05fc24L, + 0x1645c369d64c9d40L,0x7c37b12c563e7e9bL,0xb70d292d58b477cbL }, + { 0xc283aca993a2d5a6L,0x759e9118354c183fL,0x8a031f6fdd8f4125L, + 0xfa8b17ad56edbe3aL,0x6e0f96eb63c651ffL,0x40361942b5085541L } }, + /* 12 << 84 */ + { { 0x25ae349981d311b3L,0x8640f52a3b16037bL,0xac0839941d947065L, + 0x3723c75ee2e693d2L,0x65040a51b66f429eL,0x7f582b0b035a3a53L }, + { 0x20eca9e10a166da6L,0x45b37e202c4cc565L,0xeab882957a8a96e3L, + 0x99e771dab60a1a1bL,0x2cdd778c23b03965L,0x8d4d7a7291052478L } }, + /* 13 << 84 */ + { { 0xb57b345e4ff33506L,0xc1a3092a31d23fc3L,0xc16b501e905e1f58L, + 0xa36a3b1f29067b85L,0x7cfabd23c214dd5aL,0xbd5f7ab726ad949eL }, + { 0x8f64595987363816L,0x49c1a3e679d12d59L,0xcc8f3e2c32d771abL, + 0x008d900e6bde16d1L,0x60428a0f60165966L,0xd4f8d9eda7383ab9L } }, + /* 14 << 84 */ + { { 0xa52d3c2d7e8f73b5L,0x86d8063351842657L,0x58f01253b3949ebaL, + 0x97689f15e79367d0L,0x918bf9a30d820328L,0x2d4bc99441c959dfL }, + { 0x37392f6e8c16ee54L,0x9f726d58e6f0849bL,0x497de1e4b8208f08L, + 0x60c51233d51a29b3L,0x0f61fb03c9e1d465L,0x09494bd0fbe2613cL } }, + /* 15 << 84 */ + { { 0x100ef5d0a2bd7bd4L,0x89efecf5f45e2a66L,0x63bc210b653786bbL, + 0xc7748dba0a0e47c4L,0xaf8122ae110d1ba0L,0x6695bfbf797c78bfL }, + { 0x9b0e6fb1d7dbff69L,0x106799703f53040eL,0x22d9ed52fcaf4ed1L, + 0x1e27bafdcc1b2d4cL,0x839f9c019f1c88e6L,0x1112fe541321ad66L } }, + /* 16 << 84 */ + { { 0x4f293478154d0f99L,0x1b82320dd07a24b3L,0x1bf7c94f64d55f6fL, + 0x4489b57d725c5125L,0x3aa4d43ab1b6a091L,0x054842bdcf7a60faL }, + { 0xaa918a4d2aeb4cb6L,0xcbdaff99ac7d317bL,0xed0e00a16812a03cL, + 0xb09acf270b0a1e4bL,0xc73a41f7ac28386bL,0x43134dbdf4cd1321L } }, + /* 17 << 84 */ + { { 0xe5f746af6e001a20L,0xdc975b02d6a9925fL,0x6d13e266e57f9100L, + 0xe013661396a9c4c9L,0xb483162850a66d45L,0xe3b0f96d4ee8439aL }, + { 0xf2a2c08d3e074501L,0x987b2b6b2be498e4L,0x605aad24a15b815aL, + 0x5bf2186f8529ad68L,0x1413b3d7885ad25dL,0x3de23959807efaabL } }, + /* 18 << 84 */ + { { 0x08336ffed8c33924L,0x15b56cbf5140b253L,0x38dcd310306caedbL, + 0x04ecd49647944afdL,0x1280d23f68a48f95L,0xf414220434363c6eL }, + { 0xd0a397eacaa8717fL,0xb51a1669c3994b80L,0xa02eed916c56808bL, + 0xc3ab55c583545c3cL,0x8b835820fd26114aL,0xe0cfa4a6ffff324cL } }, + /* 19 << 84 */ + { { 0x4db4bfb788b45f19L,0x130252bbe0d5fd16L,0xe44c97b22808bff6L, + 0x885e4555b03405caL,0x3b7ce036be9af81eL,0xebe17cf58c552276L }, + { 0x6eb946c977f4158fL,0x36c23a9c74a5e642L,0x466ff55f2e70a453L, + 0x327fd5fd28ea7af7L,0xc96bfbec6e658256L,0xaf194fe8c0a3b932L } }, + /* 20 << 84 */ + { { 0xcf63d27951c0d95eL,0x3b170a0bac86a014L,0xc21eaaa9881095e1L, + 0xed2fda116069a3ebL,0x536264b9bd2f1c5aL,0x819e1cffde312c2cL }, + { 0x6c30f983dfd6ce38L,0x2f32cc4c980b439eL,0x9fab10b63b9c03b2L, + 0xdfebe34e011ab74aL,0x587360e3b80963f6L,0x3db1f6108692e352L } }, + /* 21 << 84 */ + { { 0xf262f2379765908aL,0x76f8d0017d03cdcbL,0xdbcadfb22f35de21L, + 0x88d5bf592a73815aL,0xc4f4e3b02b1bab82L,0xf5cce885b9635dcbL }, + { 0x110a785875a416dbL,0xfe7e6c360adb01feL,0xa02642c01374d779L, + 0x9010758753bb5898L,0x0c764ed2a363fcf2L,0x24a2a5541700e551L } }, + /* 22 << 84 */ + { { 0x63a094c5fe3d070bL,0xf769b91988515eb1L,0xafe86e1450d1131dL, + 0x6bf277886774d3d4L,0x7231d699ffd805d0L,0x05132e5b6304116eL }, + { 0x3d5e255be34ce5bcL,0xfd9c3bd0c95e3089L,0x22a24023b83cbac9L, + 0xfb6d2b6fb0b3b98aL,0x74af1115f7e36fcdL,0xcfe15eaff9da3bf0L } }, + /* 23 << 84 */ + { { 0xb242ffd61da39f60L,0xd0ed946320cac1b3L,0x9ebd5e46e25f809fL, + 0xc7df7e5a07f5aa4eL,0x5eea38d791a5f85dL,0x6240f01d6080442fL }, + { 0x72ec0a5e251d866fL,0xd3e4acbebf2c0037L,0x0d4f47c90fd962d7L, + 0xece7c047b8de2dfbL,0x841050b96df17f0fL,0x567c3df7e933a4d5L } }, + /* 24 << 84 */ + { { 0x266d2c1cbb2fcdaeL,0xb538d4a252be93f2L,0x774c88ba73bd0094L, + 0x65283a9b81a7e042L,0xe1438bbfd0381625L,0x450e1f644d0db206L }, + { 0xb38ae9ef4e60fc4aL,0x14ce87e112719817L,0x831d41ec570303f0L, + 0x7172917028850444L,0x2077ea32ccd609f5L,0x091d1166cd273fdcL } }, + /* 25 << 84 */ + { { 0xaf5916f49412edcbL,0x9ccc0dc08f01b2d9L,0xbed1fdd42dd737c8L, + 0x29d26cab95a21501L,0xff38bf18c70f1364L,0x0bdb055876879b06L }, + { 0x706031e2a14164d8L,0xe229fce1fc39648bL,0x5ebc640878e97c8bL, + 0x26039bda822de18fL,0xab992da4b9f090d7L,0xf409432d53eb438eL } }, + /* 26 << 84 */ + { { 0xdf216dd84b2ca517L,0xb3eec4b9c6b74c4dL,0xf564e6c81c14e77bL, + 0xcde25f1c2c2c9395L,0x7e31f7a5049fcc83L,0x6913707b9284c753L }, + { 0xb92a6f2458e6eb5fL,0x85b0cab595148292L,0xeaad036d7449be92L, + 0x2f6a2888eb94a702L,0xd7d8773d47d59fb0L,0x612d257303c0bf25L } }, + /* 27 << 84 */ + { { 0x805ece910ea742f6L,0x54486a6ffb5dba94L,0xaceb0eebbae52f76L, + 0x2200fd85e98794f0L,0x44bd993ef305af19L,0x28f256738eb8baceL }, + { 0x5d3fabbadc5f9c18L,0x4338f79c1b003ed1L,0xaf4b0566bc20c65aL, + 0xded9407c3045d1bbL,0xe8713d7506391eb2L,0x557d62c971307365L } }, + /* 28 << 84 */ + { { 0xb872a10584d2c3bbL,0x44bca57139196026L,0x857327d84e352e5dL, + 0xa6c6004ad925f99fL,0x48aaf266bab79eadL,0x213ad923adab2a3fL }, + { 0x3be29b6df371cc48L,0xe732b9062385c9f4L,0x562e0be123f0a84eL, + 0xbb6b017228c4b0dbL,0x71a93ae5f4c6d8beL,0x76b8bb16551f1fe9L } }, + /* 29 << 84 */ + { { 0xd028d9b5242002c2L,0xea105054823783caL,0x01cf8a491d45c34fL, + 0x1035835e42457869L,0x0a95049661cc1e05L,0x9dce5bd3b439afc2L }, + { 0x8552f02003b18e4fL,0x4973e3bde6144805L,0x29fb98d8d8514c4eL, + 0x0ce0e8d83ca27b39L,0x7aaf3f5284bbc6caL,0x0572bf40d78c7c5bL } }, + /* 30 << 84 */ + { { 0xbbfaaa94c39926a8L,0xb9a59fdb60a138aaL,0x217a1aa2947e30e9L, + 0xcac988c9c52c9fffL,0x5676473a3bae3c39L,0x7d84b353857f04c9L }, + { 0xdeded30cdd324e24L,0xf07c678a9c242899L,0x956d05538cb64f3bL, + 0x9d34e2f5502cb2b0L,0x99e1054a51dd03b3L,0x86b8bfa54d60a593L } }, + /* 31 << 84 */ + { { 0x3dcd2df9c8870c4eL,0x7cfdd05f1699cd0fL,0x19e9ccf027e79e0fL, + 0x56e997027b85d75eL,0x407b5b74ccadcf9cL,0xc961a336297dda7aL }, + { 0x350c34d56d12d17bL,0xe37de9a93bc6afe9L,0xd2c7339e0d641d3fL, + 0x2700f39cf7dfa063L,0x2916f9ad8ddef077L,0xffec6230547cdbebL } }, + /* 32 << 84 */ + { { 0x10a53b90754d15e9L,0x6cde9a0c5f4c7218L,0x740d513fabef2b96L, + 0xff6cc47cd3f802fdL,0x1be6825beb0627afL,0xdb21ede55886c2dcL }, + { 0xb6cfb2c6f5daaed7L,0x68b61aa8fae29a9cL,0x7a1e16f53a5a485bL, + 0x16b60b92e7b2223eL,0x332f33d836a13a9bL,0x4567c313876cd1a2L } }, + /* 33 << 84 */ + { { 0x7663402de62014a2L,0xbffe1e7fc4efd224L,0x2080eb02c38f766dL, + 0x6c95529ba9641db9L,0x24dc13a5c68de8e5L,0xca219b3fbbc3016bL }, + { 0xb83450e310b634e0L,0x8cd26d775b097a34L,0xb912c34564c9884fL, + 0x3d1f28be5bd75f1eL,0xdcba2b479466ea59L,0x4077e017ca9948e3L } }, + /* 34 << 84 */ + { { 0xb4b2c65df91c7972L,0xabe915496b689013L,0x4eb7afa8d506333bL, + 0xc2f2ac1d648e7c0aL,0xc6bc96b1213cc243L,0x0b827c2189e44025L }, + { 0x2e866601cadee87dL,0x8ee85356b4719ce3L,0xefda7427b4fc0081L, + 0x0d5c33c4c802c92dL,0x4c8635ab58515f01L,0x9d7ed87edd0ab04fL } }, + /* 35 << 84 */ + { { 0x9a660794cda4cadfL,0x70784fff2484a3b3L,0x8ed664ad2de7de13L, + 0xbaff5937030d906eL,0x884407034ab43a4fL,0x86dfdd53ee09795bL }, + { 0xcffa6852fb0e889cL,0xd94373e1e8c9fb95L,0xecc0ea249b0e3ac1L, + 0xe88eda6eaa89e492L,0xbb049803da19207cL,0xfbb0c3874bbb5be6L } }, + /* 36 << 84 */ + { { 0x3e2bdd9b5a5f6b4dL,0x30cf4762ab005a55L,0x8736f5188bacd78cL, + 0x8a5a647b09dc21fdL,0xfba40c38ca06c1fcL,0x63d53fb64a4e1524L }, + { 0xe77d07a19a2bd706L,0x54144ea7bbe30e86L,0x8eb606220bd955a4L, + 0xf689cc80b3c26cafL,0xc70fe95c9fefcbbfL,0x67f9e8e2495b5bdeL } }, + /* 37 << 84 */ + { { 0x04361e6b2e4d2cf9L,0xdbd3cc13ade11ba7L,0x93dc1d1df47d8ae0L, + 0x7d46bba6fbb2d65dL,0x797ea0df92e97abdL,0x09eb3975a712e8cdL }, + { 0x9ab3a54e0380cf8fL,0xcd1a9574c96710b1L,0x6abcd1a1dc13dbfaL, + 0x1be0db71c2ee67f9L,0xee8ec8d0c2ac89a5L,0xbc363f407da201f5L } }, + /* 38 << 84 */ + { { 0xc86c049bbbef377cL,0x43df6f3703de56a7L,0x01eced2b558e516fL, + 0x18fca0bdb43c1cc0L,0xd8c6f7ff62121c68L,0xb2f1f1ac36f90713L }, + { 0x5f876328ea1bbd95L,0x9f22dd535ac4ce8cL,0x7e052acc7df88002L, + 0xedf21fb7068d46a4L,0x349130a21d7d0220L,0xcccc79beaaa68eebL } }, + /* 39 << 84 */ + { { 0x9c955b5eb4100632L,0x8d6dd2d3ccd99a0eL,0x700f827c265dd397L, + 0x5540bc0cfc85a2c1L,0x6d4b8e7adfb81661L,0xfbfe1ebe1d5c1485L }, + { 0x322c2883c9dc1b6cL,0xc7c897cdfd7e0f34L,0xe70b0586030e41aeL, + 0x4263e06e26a728b7L,0x0ee2b93392387542L,0xae708ccaf6220511L } }, + /* 40 << 84 */ + { { 0x05ff8b9cbc15ae37L,0x94dc2e85d06d62edL,0xea1d1c8b4b02607dL, + 0x1fc202a224da757cL,0xbd5180bb35440e69L,0x0263dd51698ee7a5L }, + { 0xbe93f27654013d74L,0xa7c041c464e81695L,0xbb170ac13ba5336fL, + 0x1aadf302af84dfa1L,0xeda58747c960788fL,0xb456070e5eefc35eL } }, + /* 41 << 84 */ + { { 0xa905d421800ed69aL,0xdb8a643813622898L,0xd003affbdaab0769L, + 0x467bc051f0aed9d3L,0xed1e6951b11085d3L,0x7a1d1152d3f54fc5L }, + { 0x8cb243b6dc8dd008L,0xf9c690d1f409210dL,0x9a3195399461aee0L, + 0xf580724dbc2e4de0L,0x52f648e4e759556fL,0x235a79f2697885d6L } }, + /* 42 << 84 */ + { { 0xb293d3fe8220ceb2L,0xace20e7e049a33a9L,0xa584ad52af4198d6L, + 0x49c5cde64aa0a5c6L,0xc4f7877ecee2e664L,0xe1557968bb98ed87L }, + { 0x69b0cd713066000dL,0x1af188cbc7399f29L,0x5b88b85c306188a3L, + 0xcffa28eb4097182dL,0xdb01149ec80d0aa9L,0x9f8e6d59402bc397L } }, + /* 43 << 84 */ + { { 0xa646077bd5b97d37L,0x618df84461cfbd95L,0x3a9fe2f447c62894L, + 0x7f2760eb4e0f1612L,0x50c08fdb36e5acf1L,0xac799584675d2aabL }, + { 0x3eba6f54917dd606L,0xf585fa5075119ed9L,0xb047abfca32016bcL, + 0x61c03e51aca118f0L,0xef9fcc526dc13766L,0xd849eca5e8a3fb72L } }, + /* 44 << 84 */ + { { 0x11ac1ff4147faf46L,0x5dd8913882b818f4L,0xe439f66fb15fe5a2L, + 0xadf913a5fe8fb45aL,0x3dc708404a6bbdb0L,0xe8e1204da4af4ac5L }, + { 0x4be549318ba70502L,0x945d9a765883b39bL,0x99cb1c721a76198bL, + 0x96fbed479a7949e2L,0x30ee96ebf0299bc4L,0xb7dc5e76d3dd160cL } }, + /* 45 << 84 */ + { { 0x85eca39b0c88d5feL,0x96000863af9e0158L,0xbb13f99c4509590eL, + 0x50033c18034e2499L,0x1e9346f87b86cb33L,0x917d88b4aca548e0L }, + { 0x0c422c2e9e2a7e15L,0x6751c95c5e37fb06L,0x631361b8c40d21b7L, + 0xe231858ec9958deeL,0xae86abc54d9936e3L,0x60c78d1137bf9213L } }, + /* 46 << 84 */ + { { 0xa0bcb7c6283190a9L,0x36c884ffc53fe76eL,0x071d4acab23f0865L, + 0xd44e3c20e14a82f5L,0x704dadd8968d28bbL,0xb40d2b948e88ad61L }, + { 0x4a29142ff3de62f8L,0xdd071910bd7292a8L,0x5b12c32d5b3571c9L, + 0xe9886262943c6aecL,0xc49b7506cb1e0a33L,0x87f6c2d3de95886cL } }, + /* 47 << 84 */ + { { 0x44ba232e010f465cL,0xb82486c69ac91d38L,0xcd1a6bf75de743f5L, + 0xe050232838acbc4bL,0x8de9c29631fb87b5L,0x9c8029250450c4efL }, + { 0x19ee1607635e64a6L,0xeff5478c69ed7f8eL,0x311201a027001c21L, + 0xfc0382a78beb55ecL,0x494b623ce9dea7f8L,0x926a3f756767f769L } }, + /* 48 << 84 */ + { { 0x802f495cee46f99bL,0x0f3ad0ee43b91cbbL,0xeaf3b294e9b3f0f6L, + 0x82cc760033cbdcd1L,0x1a5642278e83fce5L,0xcf1b2edaffa0e4ccL }, + { 0x7d93e9769b1f5706L,0xe4eb843cf873d68eL,0xcb53dd79eafe5f35L, + 0xcbbed8f0fcaafabbL,0x570472705f053efeL,0x2c71a95f1ebfeb7aL } }, + /* 49 << 84 */ + { { 0x02d4717ddd7a5499L,0x3bc8bdcb9966236bL,0x13f08015fd27be15L, + 0xe05236f6baaff392L,0xf73bab3f7b4cc522L,0x8ad26d4552ccc027L }, + { 0x79f8e79e9e9ccd7fL,0x8011b92aab2f22d9L,0x6aef576e729662e5L, + 0x7d5194d05e568f55L,0x2947d63a1a40860bL,0xe9890f1440305b54L } }, + /* 50 << 84 */ + { { 0x8085614c0fa9602eL,0x9ee1b9b26651c4ffL,0x65dd9c94ec048f1bL, + 0x10b4a62f6d6c0fd7L,0x61469fb7d391dcd2L,0xdf751399edc3d431L }, + { 0xe3901315c913acbbL,0x31581d7a90976644L,0xf20809634aee5cecL, + 0xaa716eafe5408c5dL,0x9e356989b9a60ad7L,0x2d6e7733a6a3c977L } }, + /* 51 << 84 */ + { { 0xd6d99f54f19b8464L,0x3322a0b8a0be5c3bL,0x6cff730557e98725L, + 0x786709c7953a357dL,0x3864d278a1013652L,0xf7471f111738f6e6L }, + { 0x0377a923984c465aL,0x4a24b9e14ba970e2L,0xe53dd9f21c01d248L, + 0xf422b754fbffc0d5L,0xae25dc0ec6a956b0L,0x3c3fef96ce806445L } }, + /* 52 << 84 */ + { { 0x6a69d207b5906d71L,0xf3c757ed8964e1b1L,0xdae255af5f98821fL, + 0x6c801ed4db1af96aL,0xd12430343d109b86L,0x4b2aa65fa091f98dL }, + { 0xd9bb4c2132dcb5f9L,0xe5a5979bf190a1e0L,0x0861e5de40117a91L, + 0x8753c9adc39120e4L,0xfdcb09f4aeb4a18fL,0xdbda38746bd1fd08L } }, + /* 53 << 84 */ + { { 0x1bd8e8c0304f7045L,0x8ffcf24eedbd2dd0L,0x13c9441de6ae4dadL, + 0x5efb70aab418c02dL,0x9d0fede1b8cf6949L,0x613545cf41f5aec0L }, + { 0x4e3342244b98bddeL,0x7d0c11110fd8aaf9L,0x30c2bedcdfb8643cL, + 0x875d386aa83e493fL,0x85b32632d6cd0825L,0x9f1ef3a01445507dL } }, + /* 54 << 84 */ + { { 0x2b70440e54f6b8d9L,0x355e692430eddda5L,0x354e7cfbc9199910L, + 0x7e8933bfdc7de946L,0xc5692fa981b9eaabL,0x2eb58fff98cf5f21L }, + { 0xd0d8f9bb96b19d59L,0x779aad414d1a6285L,0x0cee1a9b5eb87c49L, + 0x676e36ff786c4c81L,0x6618c8f112d34964L,0x2061186dd03e9562L } }, + /* 55 << 84 */ + { { 0xa5ae40977da39b54L,0x98e4d1d9f1d40635L,0x40d97af126154fc6L, + 0xf18041d4e9ae28c3L,0xdca9487555978c61L,0x4aaddec43638b9b6L }, + { 0x1e615a2eab925f91L,0x5cfbbe9ded8a50faL,0x0f26d3ffb2034aa1L, + 0xb2f9cee2c4813646L,0x2195af47957b6709L,0xa55dac537e7fc45fL } }, + /* 56 << 84 */ + { { 0xe44a8ed7630816b2L,0x5fb9b643cca34310L,0x07826148a3b5d2e2L, + 0x0f890db16e65c2efL,0xe9feebe288283844L,0x8e56c6760368a9f4L }, + { 0x8f0cc9c93e4ce874L,0x646ede9b09f1beffL,0xe92d6bda014e3d19L, + 0x27e620c5520c921fL,0xfd9b2ae1eed78555L,0x68684615816a603eL } }, + /* 57 << 84 */ + { { 0xcf54e9e89ded00c7L,0x8dff0130abbf7765L,0xf12773fb10c5f8d0L, + 0x7435ac767382e4eaL,0x93092b16f61d443fL,0xc1554fa846eb45cdL }, + { 0x0896852c30957ca5L,0xc0d91e3effe60944L,0xce8aee57a1b7c75eL, + 0x4d24f07007cd1a9eL,0x3d8e381094456b11L,0xed6fba6b9dbc9d0dL } }, + /* 58 << 84 */ + { { 0x1b1de3ed8b5b8f82L,0xf542399d64252363L,0x23f34cccd206f26fL, + 0x54c48d9fbd941d6fL,0x3859eb56202e757bL,0xedcb4729ae0eaf7aL }, + { 0xf08753c512360fceL,0xf37ece765f697cd4L,0x073cae01c98a7c8bL, + 0x6e298559df664bdaL,0xe8cefd27194b103cL,0x56301e2a811f6a71L } }, + /* 59 << 84 */ + { { 0x8103c6053d3fe586L,0x472885b3999bb4caL,0x3759d2d492a2834aL, + 0xaa4eb3acd46cca1bL,0xcb99aaba633e579dL,0xf9369b033d6dc569L }, + { 0x55fdb1fe8398c067L,0xd7aab8b47e6826ceL,0x7f5497bd8b525561L, + 0x2e0e1e9c2cd0e3beL,0x3142a6e2c47caf5aL,0xe78cb1840f4b802fL } }, + /* 60 << 84 */ + { { 0x0a1577baf455f6bcL,0xaeeea79094df32b3L,0x1af3ba0f6bbb15ceL, + 0xaab92a74e8522659L,0x84087a8f7efa0a4fL,0x83c6991b84596065L }, + { 0x11f7829d29fbb626L,0x32b04b2f86031974L,0xf3a5b8722c1291deL, + 0x2ffcc97e8bd2be43L,0x575400d10a206f7cL,0xbb4583de0befbce6L } }, + /* 61 << 84 */ + { { 0xd448eafaab983fd7L,0x2622336c7a18a7e0L,0x36632e221c274b3cL, + 0xe64e8f89bf086fcfL,0x1dced08fef72ebd9L,0x61249c25ea295d31L }, + { 0x7433743d3755632aL,0x9d766243ff32ed08L,0xc36e816a977b1d9aL, + 0x1069fc0820ccec81L,0xbd4af7bef65a0cd8L,0xd04127fc92e31836L } }, + /* 62 << 84 */ + { { 0x39560937ea57ca46L,0xe1f2b7198229d346L,0x462b28d4dd02dcbfL, + 0x510fce98a333d609L,0x795fbd38fefa05beL,0xd6e34c231bcb029dL }, + { 0xf33291fc838f7ec3L,0x2a01a1f5f16e7247L,0xf9737722c0bcb3cdL, + 0xc53ef57ecc8a6c77L,0x219372afc750f1a7L,0x3e6a97c3d14e60bcL } }, + /* 63 << 84 */ + { { 0x87278f062db3d752L,0x64c65f5cd106b7a8L,0x04ccc14d41ee7aebL, + 0x72d1189e71952b60L,0x2e88f851080e9ea8L,0x625a6d32913e8df4L }, + { 0xd943de73900ee95dL,0x6c12b3b3ecb8b3a0L,0x6209daf2c9b141e8L, + 0x81c02f71412da959L,0x222d17b747278f65L,0xaa338805789138e1L } }, + /* 64 << 84 */ + { { 0xa896d28e4aea3fa2L,0xc6137a456db06ee9L,0x1bbafe8c06fb15ccL, + 0x2daab2961cdffdadL,0x984defc8e1119b3aL,0x9cd44c3cde2a25a3L }, + { 0xa7f54ece54ed6d73L,0xd283017f50907054L,0x69130efc6a3b9442L, + 0x5d17f1276785163bL,0xc019911b172b1d0aL,0xa19c745f7e3e093cL } }, + /* 0 << 91 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 91 */ + { { 0xe185bdc2ab83d932L,0x0a75845dd7c4e754L,0x1f6f3397c3fe5695L, + 0x6c9f3a5f61f6a04fL,0x3c0f9d4bb390a92bL,0x9e3336b74793b454L }, + { 0x91ad0c341472f06bL,0x4110047a892cbdd7L,0xfa24d90565d53c83L, + 0xd63e58334176007dL,0x741089fd2cd1623cL,0x6b3d92022685d345L } }, + /* 2 << 91 */ + { { 0x1d510157c9cb7f6dL,0x532a077346ab7372L,0x2ea07e2fc6dde9e2L, + 0xceed9ad937d5bb1fL,0x3121994b98cc6e28L,0x67d2fbb567ad8fc4L }, + { 0x34707fb3dc9f195dL,0x6a601f481fd5a013L,0xfe939b8d81ef6cb5L, + 0x5c51e8ab1223a9a1L,0x8f6d7993db74cf37L,0x0b81c5b7972808e1L } }, + /* 3 << 91 */ + { { 0xcb4e85123bf921afL,0x28fc6332532e81d3L,0x682d8637f69f907dL, + 0xbd9fa8f45f759a16L,0x091ea9fa51f03716L,0xd685a14132c630e9L }, + { 0x7600c9ac3d249cf4L,0x687e2022002cd2b5L,0x7ec205ab55334058L, + 0x9d0d86b13ecf1368L,0xb3fc17a7fc7baf6dL,0x57939961361c91cdL } }, + /* 4 << 91 */ + { { 0x0db33228010c0754L,0x10635ffa8eca7c59L,0x6efd85380e8a38faL, + 0xc1812ea5769360d8L,0x505723dc76f27ef5L,0xd0358e02f35af2e8L }, + { 0x9f7bb7fed99419eeL,0x87c66e83430a0e2dL,0x01187549773eaf7fL, + 0x05bbbba489d51bdaL,0x52cabb06640ccde6L,0x0d5cb557e7ff387dL } }, + /* 5 << 91 */ + { { 0x709d61ca10e06f1aL,0xaa1e9fc578eba75cL,0xf85d062f914b2cfcL, + 0xe73b3baf9089d85cL,0x4ac05feac4a284b9L,0x92c78a433acb7268L }, + { 0x7b5586f8ee45bb4dL,0xc39a0d0e6ac0a9e7L,0xe4bbe3d54d6f9ab8L, + 0x1489463f1fd46a08L,0x3ba3182529dba364L,0x94f000d68138511bL } }, + /* 6 << 91 */ + { { 0x70187dfbc39c1cefL,0xa785216e0c50c71eL,0x30188b816a6c0d60L, + 0xeaeda67d6a27e97bL,0x4a5192826ba389aaL,0xb96c7c7ea2bf1273L }, + { 0x8ff10657267fe714L,0xdff4a271996d91b7L,0xe34ba3e11dc7aed4L, + 0xc457048b38853d61L,0xe89825db1ccbf658L,0x68c7b4556b255eddL } }, + /* 7 << 91 */ + { { 0xdc14cb2a74871e18L,0x017b1340fcb8974aL,0xea5cb0546e93c20fL, + 0xa7c078ada9e2ad1fL,0xa37207d4beb26838L,0xcd8b3b25de7ee8eeL }, + { 0xdca6606a2801a7ffL,0xad2fedcf0f8af3faL,0xf27d30b49b530c05L, + 0x071fc1c36b2a4613L,0x363aaa99b72cea9fL,0x7a33ed8f3d350374L } }, + /* 8 << 91 */ + { { 0xc377b373bb20fabfL,0x68d3aa52f986b847L,0xd9c2f2adf39b6894L, + 0x1bbff106bd6da22eL,0x3f7e5b8e7e09678eL,0xad6a87897ed3ee78L }, + { 0x689e6b31af9807b9L,0xeca87778bd1f6ef2L,0x17d3277edda78c54L, + 0xe686caccefb65cb7L,0x758aa1ab19a30f0cL,0xb40df97fb11f071eL } }, + /* 9 << 91 */ + { { 0x43b379f71a54cd32L,0xd61fe6c948817fa8L,0x6d7b0acc49ab7a6cL, + 0xee23b4a0eb6bb45fL,0x340da1f1a2bda931L,0xfdff68411750ea8dL }, + { 0x890346b8a96c7df8L,0x551993aed4fafc31L,0x2830b98890de711fL, + 0x4d23863cfb5b5286L,0x327161a0d636d67cL,0xf99dded9733e1725L } }, + /* 10 << 91 */ + { { 0x0bef2d2517da64c9L,0xb94dfc85470bbc15L,0x2c2417cedd4af7aeL, + 0x52b5b3bbc8e88ca4L,0xc00328c44f20d154L,0x024290f730af5d4bL }, + { 0xe8bacbebeefc7350L,0x89eed6ebb72abd15L,0xb67d1da61d9e7030L, + 0x2ddefcbc0e70a331L,0x7d09bc6d61e32577L,0xc2073cc95b52e979L } }, + /* 11 << 91 */ + { { 0x585939298b806bfaL,0x608ddfbfbce6a08aL,0x674545a08eb27b54L, + 0x4b57a947c8fba762L,0xcf960113cbd8c683L,0x7b5a479a4fef1937L }, + { 0xe26eb960450e97f1L,0xf04b36b9d8605a37L,0xb208c832ee5af2b3L, + 0x3578d3a71fa337e3L,0x22547fca93509939L,0xd93dcb50e848508aL } }, + /* 12 << 91 */ + { { 0xd40f36e6276f2576L,0xd37455c46405cfe4L,0xe34094d7cc51dbaeL, + 0x20f93f0f0edf8bf9L,0x534b75aa23b5e165L,0x438e4dd1dc1b73a8L }, + { 0x9dd48c413bddb435L,0xc49867a0996b4932L,0x4212f8a2a9ffa0daL, + 0x8d5236c4d94ed9bdL,0x81bec489f169cb19L,0x71cc1d7e6104edfcL } }, + /* 13 << 91 */ + { { 0x31a94a7f22771941L,0xa277284b39867dc3L,0xc66bd88b1a52f0f1L, + 0xd2e2707b1aa21ee8L,0x78e4f280248d61e2L,0x33df48c7596a31f9L }, + { 0xb9bf2baab1bb1e89L,0xe1bbcdb4038f10e2L,0x81f674a877b89305L, + 0x8b2ec6ee16f08a86L,0xa07239c29db97ceaL,0x9f4ae6647ef8ecbcL } }, + /* 14 << 91 */ + { { 0x9cb21b57012eaba3L,0xcfce54821347a83aL,0xe3f3a67100d7b34bL, + 0xd4bcb3d1a6c1b0c3L,0x6ebd26fb9f3c3e31L,0xd01746532dc79be8L }, + { 0xe7cf9a0ad4156cfdL,0x2757cb0416face21L,0x8b0e320e69e1f08bL, + 0x2a8caf9b946f83d7L,0x6daff0ba98a399adL,0xb4dfea0938ed6086L } }, + /* 15 << 91 */ + { { 0x90ed8b41e2bcf8ceL,0xa464972be8dcc1a6L,0x5a3d0b80ba496081L, + 0xb636435569f85ac8L,0x0a2765b1a25bdd8aL,0x87a6c18f0d1516bcL }, + { 0x9344081ae3b01522L,0xcef8e12e608f0145L,0x6f3566a52155e7deL, + 0xcfc1be9c4d033a3eL,0xfc836eeaab97bf98L,0xbdf53718ba7dd059L } }, + /* 16 << 91 */ + { { 0x16f3708b953b9223L,0x0d3780f8770e7cf3L,0x97a615b227bb71a8L, + 0xa8b9a864162f8b55L,0x80ee8362d91e3fb9L,0xb2009a09f83a4ff6L }, + { 0x07a7873ac1696281L,0x17ff00c223095ddcL,0x427f683d860d60baL, + 0xea9959271f87d32aL,0xb2ac69faa050319dL,0x30c362b9d2d0b9ceL } }, + /* 17 << 91 */ + { { 0xe05c6a88783508b6L,0xa5569c8ee1779a78L,0xa1e0ca30cc1e84ceL, + 0x12ecb540337cca76L,0xafb5e2fb344d729fL,0x558db4e132c8f80bL }, + { 0x5aa3c39523128383L,0x9f04757cee1ee2fbL,0x41132bd215356deaL, + 0x4e9af313ae07ca78L,0xdfc14c0100c6b589L,0x54fdb4f3dc16a1f1L } }, + /* 18 << 91 */ + { { 0x71e663c234938279L,0x9a8f5ccdb05630f4L,0xd91ead12aad70096L, + 0x2b19b27e9e46cf72L,0x93348c7038e3932dL,0xeab6c03a5c7617b4L }, + { 0x57c13a97538eab27L,0x2624d17b2f5872f7L,0x77b63d9104b00f8eL, + 0x2e0582473c89db0fL,0x5d367277937d0d8aL,0x28c19068df60c252L } }, + /* 19 << 91 */ + { { 0x9867bc3d38cd6020L,0x5f341d8c5986f76cL,0x108a3c0d0dab2e32L, + 0xd127a7f989ab3654L,0x9d5018f468505cecL,0x51204da0a8fc94a4L }, + { 0x1751f30cf6da9840L,0xafe6a8d955ed1f74L,0x270a5d1180165ac5L, + 0x739f63e05de1e17bL,0xaa95f30735d2b566L,0xf20dd093650236a9L } }, + /* 20 << 91 */ + { { 0xd648dd79ee45d4b1L,0x0ceeaa64c2bc2f0aL,0x695f3a3f491a2862L, + 0x4c07e2e0ce497e3dL,0x5c53879969c766c2L,0x3f856a2e4c4a7c14L }, + { 0xbf8a6d81038032a9L,0xbeaadd7f45b7c960L,0x78b22e85d50b9d26L, + 0xac1c56fa7eaefe26L,0x21fbce54fc69f13dL,0x37be1b47512a3708L } }, + /* 21 << 91 */ + { { 0x12845d55689429afL,0x7e20f0f9082c8ac8L,0xe1615340249773b6L, + 0xf66c39638d0f35afL,0x4a20ce6d67d27093L,0x1d462f08e55802caL }, + { 0x66f209849ff4dd67L,0x6b86f8d8271c57b3L,0x8701a5cde766b85bL, + 0x50737ac2eea5fbfaL,0xb46ebb42a702f3d6L,0xf853091d999258bcL } }, + /* 22 << 91 */ + { { 0x0ce992198c9e7869L,0x653006be525c4adaL,0x783620e4330c402dL, + 0x185a6ac833b728b5L,0xa297c4a99d390886L,0x547d1db5db4b8123L }, + { 0xccf12f071acdb039L,0xe89c5866078ddc28L,0x3460cbb1e52c383fL, + 0x7a4d1beaad25b82cL,0x21e243fdb429be1bL,0x5aa85c25bdc0d798L } }, + /* 23 << 91 */ + { { 0x76cf73b9c0db9d16L,0x45e57cdc1970ace6L,0x3c6f5314c54a109aL, + 0xe32306f7da47cbfbL,0xb3787bdf93e76516L,0x68aa80084c6d4e22L }, + { 0xd9246ddcb3d37be7L,0x6de2bb4d7000f1abL,0xda02568b67e4751dL, + 0x3ed7a5615c7f88f4L,0x5f05c828ca5116caL,0x139cc5772a2ebb9aL } }, + /* 24 << 91 */ + { { 0xc983afb64cb8d897L,0x7f05e954b14cc152L,0x587fe71e0f4d02f5L, + 0xaaa43167531b0cd8L,0xf69452727a26def9L,0x7ecf1e563bab50e2L }, + { 0x04b6f5c94c6f20abL,0xbc6cec2b893b497bL,0x79e89567c9dc548aL, + 0xa39a0a567a40b749L,0xf1531e2644bd4efaL,0x14cdd759057c7c70L } }, + /* 25 << 91 */ + { { 0x30c49847d6d51bbbL,0x70b744feecdc6aeaL,0x38cdf36fe8671744L, + 0x5834286b8cf6461fL,0xf3414f7b2c09d632L,0x58425e4d5debb923L }, + { 0x8bd79117a6b96c6bL,0xecf9802680f56fa8L,0x5ae917d7e6dcbbf8L, + 0xf2d80fb169240a4bL,0x005ac47596e3aa3aL,0xe5196a3463536aa9L } }, + /* 26 << 91 */ + { { 0x5fb02929811d42bdL,0xd7d1b956289929b4L,0xfd3546947e531627L, + 0xa37c9b1e58c2b2e2L,0xf30ed0f902bf499bL,0x3fe80d240eb6df36L }, + { 0xf96270e57b148672L,0x47362483647f48d8L,0xc279ece6c29bc59cL, + 0xc05c1d9ffdd7e628L,0xef8fc92e17568a7eL,0xd65fe5a9ec0e7f00L } }, + /* 27 << 91 */ + { { 0x0ad31de68c93f010L,0x151b1405945ec54cL,0x325d132c3db6997cL, + 0xbed9cb3a335531e7L,0xa83932c34a578610L,0xd905abbf6f721147L }, + { 0x6dd45af086d1d919L,0x2b2ee3090195e91bL,0x3dc30d5edb70d257L, + 0xfb04b014481bde1aL,0xc2ac3ec82de2debeL,0xc9f161e090db691eL } }, + /* 28 << 91 */ + { { 0x8041f112afefdee1L,0x8cab3c86b891f668L,0x1f18774e2b61e754L, + 0xf0d81b2459df567cL,0x2cc25da41c95e1ecL,0x315b1b1ac735d39eL }, + { 0xd0a9b9fb010734cfL,0xeefc0398c79386daL,0x49ce859b11fb1917L, + 0x3d66fd6baf167239L,0x2522b0ef1fea6175L,0x1a27657d3ec4a52dL } }, + /* 29 << 91 */ + { { 0x89ec003abb2ca05dL,0x2290b5f403195ec6L,0x9989bd925f6b95b5L, + 0x1d6e6b2fad409cd9L,0x41f9b9ce3bfe7364L,0xb240f89570ec096cL }, + { 0xf8725a58b8d5a5d6L,0x3bfec6f1c581930dL,0xc93e290356235c98L, + 0x82af4269c7cdcb5cL,0xeb13fa40eea6fe91L,0x9247050097c80acdL } }, + /* 30 << 91 */ + { { 0x48dc23534ded5b58L,0x1b69590756e707caL,0xbbcb73927ec7794fL, + 0x3714dfa6e50dbcc8L,0x4f8083c8f27ec5d7L,0x6358d2273bc8c3e4L }, + { 0xe0c2a0e7656cf184L,0x3996e0a24244d801L,0xa46767b54e543c01L, + 0xbf55776d965f1e2fL,0xeb66845e6bc872eeL,0x6a73fef1b441895cL } }, + /* 31 << 91 */ + { { 0x21602e432b26bbf2L,0x6092d570d1bfd7e2L,0x2b48d74a30b38d1fL, + 0x4aab113c67c53791L,0xa6acbd3df57be611L,0x53b6509ebd3aae7eL }, + { 0x047e5ab4d8751f49L,0x978ed11b0cf25652L,0x763553d2153619c7L, + 0xc7e85e93d824d943L,0xb82cc9781048a7ebL,0x7beb9166e39cc777L } }, + /* 32 << 91 */ + { { 0x24480c57f26feef9L,0xc31a26943a0e1240L,0x735002c3273e2bc7L, + 0x8c42e9c53ef1ed4cL,0x028babf67f4948e8L,0x6a502f438a978632L }, + { 0xf5f13a46b74536feL,0x1d218babd8a9f0ebL,0x30f36bcc37232768L, + 0xc5317b31576e8c18L,0xef1d57a69bbcb766L,0x917c4930b3e3d4dcL } }, + /* 33 << 91 */ + { { 0xf6625ac0b9a038e8L,0x954056eb2a921e56L,0x7135295aeac07bc6L, + 0xedde9c39f1ba0ea8L,0x628324026b592655L,0x4603177aefb8aa66L }, + { 0x63e5ea16406a6c28L,0x5897fdee1c758382L,0x515e49fd415533c9L, + 0x0a0dd627d6701b21L,0xd7c06db1c93a312eL,0x4fe95e3da33d8df7L } }, + /* 34 << 91 */ + { { 0xf113d92c3336edc5L,0x0a201f3e8ce47278L,0x57492feb5c52562fL, + 0x18b73800f29da837L,0x2262089f649a1ee8L,0x076b07657c99bf48L }, + { 0xa95050bc09bfad20L,0x5aeaa9088c7e713cL,0x264283ed3cda06ccL, + 0x5d574b116079b43dL,0x0071495cced10a84L,0x97441fb0570d3063L } }, + /* 35 << 91 */ + { { 0x340831072b228335L,0x84ea0aba50fbd43dL,0xafde6098b3ec91e4L, + 0x4fd293ca1091ad93L,0xee085e23552a785bL,0x437d799ed7057200L }, + { 0x41f735628a611ff4L,0x707a7cb5d2ef6254L,0xa9a8f00092a30686L, + 0x901cc8e60cea8d1dL,0x1fbc9ca6d6da2ddcL,0x61bcee2176489604L } }, + /* 36 << 91 */ + { { 0x5f6ef134781a7f53L,0xbac4cf47b10a9d16L,0x48148ba110e69f4eL, + 0x40594360a9c615f0L,0x3141817ddfb3fc58L,0xb9579a9263c38d83L }, + { 0x0544b1bb6373b9aeL,0x718a5fb7007c8185L,0x48d4a4f77cfa392aL, + 0x9c16cb825d44ba38L,0xc83d2df42a8fa83fL,0x835aacccc08fef0cL } }, + /* 37 << 91 */ + { { 0x09ce1818af09fefdL,0xd1d2f95f5dd9d687L,0x94ed08b5495c4eaaL, + 0xd1afff464a0b95d2L,0xd51ba2b455347a75L,0x413126295e3866edL }, + { 0xeef2d7e3cdd37660L,0x50e6fbdfec2fe50dL,0x9d071e18a664e2eeL, + 0xe70e1d9ed6a8f467L,0x576d0cc4e13afc19L,0x67ced86da0efc220L } }, + /* 38 << 91 */ + { { 0xa26968cb26a963daL,0x461d1ab5cecbd96bL,0x8eaa1834b3e38516L, + 0x1e92730f05d2cd2bL,0x91112026b07cbf92L,0x26eb815062374314L }, + { 0xa904f1d08ab1b9d1L,0x52006594692b1905L,0xc9cc90ca6ba4717dL, + 0x4bd7300aaad1c74fL,0x67ba07a4c21c5832L,0xdebfd810fa56a1a8L } }, + /* 39 << 91 */ + { { 0x3bc5aaf484539b6bL,0x6ca9ac0c0d1249aeL,0xb59da22db4ee30c8L, + 0x6e62553e57149c9cL,0x46db0089786333cdL,0xe1e2ae523e4c12ceL }, + { 0xf828d2b537b3fd82L,0x31844a9d03af654cL,0x85dd8daaea5a4677L, + 0x0db99b8f3432e82fL,0x99383b874866e1b6L,0x52310054e325b0c2L } }, + /* 40 << 91 */ + { { 0x737cd387044854f9L,0x488b2fd667eb29c2L,0xe71d9bb7258c5a80L, + 0x21afb486ac71048eL,0x0252b540d4d39296L,0xe3e52cb87839d8fdL }, + { 0x5cb1100667ea0afbL,0x207637d1de82b12bL,0x77920933e93bcfcdL, + 0x65197f5df32f636dL,0x82179527b6c41411L,0x7696a479f410c989L } }, + /* 41 << 91 */ + { { 0x78307cd80e8d576cL,0x10d3b950fd9d6044L,0x2c2f9e2bf4b20445L, + 0x961343c72c5c7ea7L,0x931c52a0af640e61L,0x45557391470d420bL }, + { 0x4096a997317f4d26L,0x15210801cceb9be5L,0x228102195ff0759dL, + 0xc388a2d21d265932L,0xceb79d01e86dd99bL,0x23e8fc7b3311dcb3L } }, + /* 42 << 91 */ + { { 0x1a7d0e091d7743eeL,0x18720797d53e4a8dL,0x78465f1ea04dbaa1L, + 0xd4f064da9ce65723L,0xc0e7c035b496e8d4L,0x25657d2e6bb2f9ebL }, + { 0x45576ab49f4b6cb5L,0x83983c70ba33d6dfL,0xf699e84d1eca62a4L, + 0x35528636a13f5c31L,0x6a1b56b01f6b1739L,0x7906eccc6ea87942L } }, + /* 43 << 91 */ + { { 0x4e584a4fec1204a5L,0xd96b00e845a5b311L,0xea11fb03030badccL, + 0x9b2141b2a825a89aL,0x18bbc30bf8b2450dL,0x87bd93916513b2cdL }, + { 0xb3dbde552f0b304dL,0x762f3dd7c3c4817bL,0xe51e1733edd3fdd8L, + 0xddad4c515d8219a2L,0xf5a8c0b8796b6877L,0x34563a8989bf65c8L } }, + /* 44 << 91 */ + { { 0x93e2e3a2881c106eL,0xa227cc49fe82afd8L,0x6fee74a4748e81f3L, + 0xb212e8eaa5dd966cL,0x68d270efdc7d8883L,0xef2f3966fe757e9eL }, + { 0x0340098b7466881eL,0x7ab98a0575884bbfL,0x24783467a472f62fL, + 0xc73cb49f988637d9L,0x2b5e9d27dfb710c9L,0x503f9a2f788fcb18L } }, + /* 45 << 91 */ + { { 0xcba6f4631a52b729L,0x8874582cc8be34cfL,0x98a08e246a9a1eaaL, + 0x77094319d5693f71L,0x575a0938a8504e5cL,0x3f59910c226f888eL }, + { 0x5c3587990aeeb1f1L,0x7c32821d3613bbc5L,0x66f288e7cc17db95L, + 0x6f3221998724ac94L,0x4e3fa38981db3751L,0xa6e798c8420403baL } }, + /* 46 << 91 */ + { { 0x56672f2e2cbea2e8L,0xd1a02df9128bd636L,0xff6a3bc6d47a0025L, + 0x24124f30d38d0b42L,0x89ac3b8dda63df29L,0xf26d72994d0b6458L }, + { 0xfff0445f7d6880bcL,0xface90f52be76351L,0xbf10c6b8ebffb74fL, + 0x0e53c533a1fba003L,0x037baf09112f4980L,0xb8ae6312be960954L } }, + /* 47 << 91 */ + { { 0x8397b60917270d4aL,0xb4d0c38700e4caeaL,0x69c52bb3f4c58f86L, + 0x06e0e01157b1fd41L,0xc5dc2f25627873a2L,0x9af848ca0ae53974L }, + { 0xb5c957c06ad18335L,0x93b564154ef09e7bL,0xb5ba282450e2c5ccL, + 0x63f003a567d7b68bL,0x0bcb0dc820bcbca3L,0x8803b1ffe3d4296aL } }, + /* 48 << 91 */ + { { 0xff41d51faae4bfd4L,0xcf50b14117c44facL,0x078b808e657a1ea4L, + 0xc5aac1a893c00c55L,0xcb99cfd0cc4d1c0fL,0x1d1048933fa123a6L }, + { 0x49646059023ca92fL,0x5833e326f3982134L,0x2e0d4bc9c5781cddL, + 0x5f7f84ed8d5e75f5L,0xb6655f1fe1e8a383L,0xcc18514c296e4943L } }, + /* 49 << 91 */ + { { 0x5d3e5f8d8a407ff0L,0x9c713c8c7b42b11cL,0x7433a9921e387806L, + 0x5272b92a98cb43acL,0x6261dfc1b1018149L,0x229d2ba5d3b4adf4L }, + { 0x1f52e72989f0905fL,0x965e062925d4c79cL,0x42edaeeb33e6c016L, + 0x5ec492e8af1709adL,0xaad39616c5763619L,0x85a659098c666860L } }, + /* 50 << 91 */ + { { 0xec8fe7dc86009df6L,0x42dd3c37871b20a6L,0xe4388c920db643e4L, + 0xcc5dfdd481e06dbdL,0x3f1a3c6458ca7500L,0x987d7caa22c04e9dL }, + { 0xd0c91072bc5717e2L,0x3f605fd2e77e5509L,0xa1cc1404c0c3e95eL, + 0x4afaa9fdc6d0edd0L,0x2f3aba4e0d7d882dL,0x3f1f0349796c5ac0L } }, + /* 51 << 91 */ + { { 0x5dac93982eeb82e8L,0x2fe5ffb57536ce1eL,0x2bb120ac6926cfceL, + 0xe54ff20f2236dbf0L,0xaaf0d31edf8c5a87L,0x5262fb9fc8f5df7aL }, + { 0x0f833760467092bcL,0x50fa223d0a8dc0afL,0xd6a4847d35406966L, + 0xd17d6ce003b7f56bL,0x8067d8e2ee2d64bdL,0xe33e51bb9fa4fe9bL } }, + /* 52 << 91 */ + { { 0x52aa210770248e4eL,0x30cf7e773b6bf709L,0x36961c7b788e1836L, + 0xbe49de5f7595af2bL,0x86b49b619cbcba78L,0x1947db3790cf1117L }, + { 0x7d3f599de14b4287L,0x14546993f0ca62ebL,0x0f6c8872d0abde7aL, + 0x1531ceeaafe2260fL,0x36449624ae5ecf96L,0x6cfa12a5840bdc19L } }, + /* 53 << 91 */ + { { 0xb092ad68c1d612b5L,0x9f6052507af5c37dL,0xf48aa7c6c702b673L, + 0x380144215cd29c3bL,0x7b09e407121867ecL,0xf71443d391e59047L }, + { 0xea51e1a6b6d16a51L,0x041fa7650f33e2ccL,0x3a6d50c73750dce3L, + 0xeebf5c2e97cb7a7dL,0x2530de228f39e771L,0x9af217c18f37f863L } }, + /* 54 << 91 */ + { { 0x38793fd0c683085cL,0x49cc5934dc436d16L,0x94c708e4175e770eL, + 0x41bfb65d059c2682L,0xf6b83eb75f004ddeL,0xe1881929f6864410L }, + { 0xfaa77fe0b438f937L,0x97a856069997e90dL,0x78366a9108de889aL, + 0x6c28ef64553229cdL,0xfce82c2fe9381854L,0xae98117146f70bb1L } }, + /* 55 << 91 */ + { { 0x3f77410e9aacedd8L,0x0e34bd7d453813e4L,0xc5818436825d6b0dL, + 0x0e30f037b4d0ac73L,0x70f6bc9b69b559c5L,0x68d3d71eaed15484L }, + { 0xd0254e5414fbae1eL,0x6ddaad42ae0d3df6L,0xefb91a545a6e98d0L, + 0xde3fcefc854ee5fdL,0xb2f0f3a1dfa2a8a0L,0xb656f97ad00ded3aL } }, + /* 56 << 91 */ + { { 0x01acfa7e0a90e37fL,0xf47e5946366d0ba0L,0x8e37db7b54c11845L, + 0x5742d8bd50a62064L,0x27dc9a33ed6d096cL,0x2246d73016deb724L }, + { 0x203c08da2c8f1a85L,0x210cda3a56fea379L,0xea6b1bbf2bf9ed67L, + 0xe5a1e5552395cc4bL,0x458a7e19de2d6b2fL,0xa7199a86734942a3L } }, + /* 57 << 91 */ + { { 0x53684c23d44cad85L,0xd23613f8940779a5L,0xf485c7a3940bd34cL, + 0x64c66a1f3f673b5eL,0xec29c76f1d6dd63cL,0xe10f56272f191435L }, + { 0xc054f9a7325d5759L,0xe6740d3f974edaf5L,0x2723ac6103f3b640L, + 0x0a2315a4576e0bbeL,0xf8156e1e4a3ec903L,0xa307bc249bbc8c52L } }, + /* 58 << 91 */ + { { 0x78579ca212a1687aL,0x208b7494268a02a2L,0x61708a002c1c5243L, + 0xca366915a760461eL,0x0e9038fe3ca1e167L,0x2cfd6fe3a58e2c57L }, + { 0x97c16e34fe79a49cL,0x1575244ef08e4037L,0xc1407fa08e2283edL, + 0x38ae77621b057919L,0xcec574a5e68a366dL,0xafdfdce03eff00d4L } }, + /* 59 << 91 */ + { { 0xdad0dca9162d80c6L,0x554141f8b888ea0fL,0x1e471b24d4036218L, + 0xafca22cfb36102d0L,0x437c51bff280dfa8L,0xc2c8bc8b50c9c30cL }, + { 0xe7bacc372a9fdf6dL,0xd01dc65cf0472f2dL,0xaca59cf983d7be3eL, + 0xf7c935425d9ec484L,0xc22046c6015a08a1L,0xa71b3c64cecdf816L } }, + /* 60 << 91 */ + { { 0x4b7d0b277abe7856L,0xe566f4567acdb39cL,0x70c6cdf20047ae7dL, + 0xd27f831233ed0392L,0x498f0ad0358a429dL,0xed97c4668e6ee95dL }, + { 0x3d11cd69f3018515L,0xedd460344c1b367bL,0xd75660e3b3ac8ec6L, + 0xc80dfc0fa541e6e1L,0x80026f005c091a6eL,0x62b86784c426f2bbL } }, + /* 61 << 91 */ + { { 0x417408e529ee8eb4L,0xe92f18c2917f9951L,0x1f471f0eb38b6210L, + 0x53cb14264df240f3L,0xeaf7fc0067c29b25L,0xbbf46fd3d99cb613L }, + { 0x05cd552eb465b50dL,0x136b8e675e136733L,0xd7d50f61ccf61776L, + 0x90187ec5a32b01f4L,0x21548ec523ba232aL,0x6c8266c0748e558aL } }, + /* 62 << 91 */ + { { 0x762f413d7650470dL,0x9b4af5d018c9ad5dL,0x85fe90460ea625a0L, + 0x4af4511b2200cadbL,0x4c16980defec2921L,0x42ae5d5d60dbe1a0L }, + { 0x0785260bbb2ceb1bL,0xd181ea3242f1fb7bL,0xc34f02b13a47672bL, + 0xb0bc79f770e58634L,0x6e7967098a8509aaL,0x05870e6f3c3e6d44L } }, + /* 63 << 91 */ + { { 0x46d4fef752f7c595L,0x5f35083a8a07819cL,0xbba477ca591233ddL, + 0x4e66309358e307deL,0x65c3e2b9ef827537L,0xcf7b7adb09ee9adaL }, + { 0x00a82d4b5f5e1434L,0xd6aecb8032e50afcL,0xffdce7ce6b034271L, + 0xa95d96ae036d5058L,0x61582ae24cb7d60bL,0x6a10577474139c1bL } }, + /* 64 << 91 */ + { { 0x53ebbaaeb475d8f3L,0x3d6ea31cff76bedaL,0x3c15f25d340986b4L, + 0xc5925d2e3365312aL,0xc35d3ee251641f96L,0x11eb2f75984128e4L }, + { 0xb41a21a83d04bc99L,0xf2d286006436c3d0L,0x4ffcf4c0faf5663cL, + 0x889d285a0a62c9dcL,0x0908665acb2d60c5L,0xe2f19c590a131be5L } }, + /* 0 << 98 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 98 */ + { { 0xc0de60f5091354ffL,0xd7cc38bba1bd1975L,0xf4122aa8e734e2dfL, + 0x08f40f63ef773db6L,0x0a7e9484ce2d71c5L,0xcc79173378a3f825L }, + { 0x0cac7a5bb47beec9L,0x1cbea0e4a3f7b5b6L,0xecf19a90d3e18145L, + 0x0d1b062a0aadf689L,0x42299f1ff3f0acf7L,0x63a645395ac252b9L } }, + /* 2 << 98 */ + { { 0x44bfd1665c1d4586L,0x46434e198d1d86d6L,0xe50fcf81c3936683L, + 0xc9b4eb068b08680fL,0xf90882c52832aab0L,0x42823cefecbf5ddaL }, + { 0xfd4d51c744ae08f0L,0xb54a08f1bbd21c1cL,0xb72953dbfb187c34L, + 0x166f7f26f8ed037fL,0xd2b1077a097bad45L,0x47794cdc790dd808L } }, + /* 3 << 98 */ + { { 0xfadb2ac4bac8b691L,0xf0c5a0361579c4d1L,0xa192474f79019224L, + 0x8c7a64574117a323L,0xe58122dd84d970a9L,0xc475893c0bf77208L }, + { 0x9518412f1bd45c95L,0x75bd0a72283f7a3bL,0xa9e871605fb7e6f1L, + 0x14d3c944df67acedL,0xbceea947d0348c22L,0x5331c192d021aba4L } }, + /* 4 << 98 */ + { { 0xa05c751cd1d1b007L,0x016c213b0213e478L,0x9c56e26cf4c98feeL, + 0x6084f8b9e7b3a7c7L,0xa0b042f6decc1646L,0x4a6f3c1afbf3a0bcL }, + { 0x94524c2c51c9f909L,0xf3b3ad403a6d3748L,0x18792d6e7ce1f9f5L, + 0x8ebc2fd7fc0c34faL,0x032a9f41780a1693L,0x34f9801e56a60019L } }, + /* 5 << 98 */ + { { 0x35df68ae1a504405L,0xe41d69508fc755b9L,0x420dc1cda6297243L, + 0x3011646b913fb68fL,0xc4b630465e141a27L,0x943b3b3bbd91fe5fL }, + { 0x3ca17d6b50c31708L,0xce88b5e74ffa8c71L,0x8b60038f4dacd2bcL, + 0xdf654d723c13cf9bL,0xb5353e281d871b40L,0xc2d27919226663d3L } }, + /* 6 << 98 */ + { { 0xa028d2fa9b87715fL,0x7cdd9b4a453625bdL,0xc8afb1890be3dacfL, + 0x40289a3a274c4e2eL,0x7f5f9f7677c6bbadL,0x577c0935bdfeaccaL }, + { 0x5f838f0404281989L,0x8650a974ebfa410dL,0x414fab6dcd56dea6L, + 0x6995cae292eed440L,0x3b474d27ab146e15L,0xe24262b2e9938f84L } }, + /* 7 << 98 */ + { { 0x649e18fba34fb18bL,0xa4883af898cc69d3L,0xff46285f3fd56e37L, + 0x2e28ccc4557c0c04L,0x8388dee821a9b46bL,0x0fd4fb807ba3a6deL }, + { 0x1d8e9da7c62bb315L,0xfa7bd70d06e44230L,0x2840122063320438L, + 0xeefabd47d06c0654L,0xf4387b08d4c8c10fL,0x8f2694624ff2142cL } }, + /* 8 << 98 */ + { { 0xa4b957d262c36887L,0xaf15a485fc24cff8L,0x11575e80a271d9e0L, + 0x0fff68d44b9367e5L,0xf55ba6732279779fL,0x9d72cca6d4d68f68L }, + { 0x01474ab1590ffe4cL,0xd20f44e1074d634bL,0x63903a8336111d25L, + 0x37342a5fab531cefL,0xd3c93fe7702ed867L,0x05d143696279f7e1L } }, + /* 9 << 98 */ + { { 0xcddf64873e942b27L,0x9e29835a2bc21472L,0x924c2bfb2d2195e3L, + 0xdf4a3cd38eca6d9bL,0x7fe6acd1c5be60c3L,0xa3abee9cfc38025fL }, + { 0x014f0d992f449934L,0x8d72657a78860127L,0x92514cb948d84cfcL, + 0x8bd4ac503aadd70cL,0x3c96ee00136620d7L,0xa0caeeb54efc5e57L } }, + /* 10 << 98 */ + { { 0x7a65cdf5bd200ed6L,0x72dc1b5f0e4b1c68L,0x9c09576a6ddf540bL, + 0x358dcd122b169da2L,0x6466f0e81639b734L,0xa1429a6ef14c6eb6L }, + { 0x4b3d781943221168L,0xfe3d2fdaf3b74fceL,0xb22bcec2ae26014bL, + 0xa8900e7ace7e789cL,0x9db9af67220bce88L,0x1f86d2e4fb8ee34dL } }, + /* 11 << 98 */ + { { 0x6f8e1c0bf8c65293L,0x66f44ea04d7a5dfbL,0x2c3cacac741fdc1fL, + 0x72e58aae239f5f16L,0x50dbaf192f72d8c8L,0x24ee526628c97b95L }, + { 0xdb5f7827ab3ecb17L,0x2c567337669b05c5L,0x78c97eb8ff76ccdcL, + 0x1de1b4a3f8d2c990L,0x5b183974e6138df5L,0x61b74177aa1a1019L } }, + /* 12 << 98 */ + { { 0xb398290cf0db3751L,0x01170580ba42c976L,0x3e71aa2956560b89L, + 0x80817aac50e6647bL,0x35c833ada0be42daL,0xfa3c6148f1baba4eL }, + { 0xc57be645cd8f6253L,0x77cee46bc657ad0dL,0x830077310defd908L, + 0x92fe9bce899cba56L,0x48450ec4bceffb5aL,0xe615148df2f5f4bfL } }, + /* 13 << 98 */ + { { 0xcc14267f6be1860dL,0x3de7f48b4ffedea1L,0x8252694e5b776b87L, + 0x478c877890dd427fL,0x913e19a675a21357L,0x882f2d5ac078bd79L }, + { 0xf442752184c565dcL,0xd772147e3ac3ed26L,0xf21abc752fa216b6L, + 0xab1804ad305ff0dfL,0x10d89a07920c977bL,0x0a2240dc4fda6075L } }, + /* 14 << 98 */ + { { 0x7068e6b98653bfadL,0x16b0da9b8f4397e8L,0x77b953b4946bb9c6L, + 0x08366ad749b036f5L,0xd219117b26a3913dL,0xbe3607949a5460d2L }, + { 0x1a4acf6dfadd462eL,0x1f7de879c32f3550L,0x11117132669c9b2eL, + 0x1deea7d1c87ca216L,0xa88c90c748a058d2L,0x0d8e6afff403ef36L } }, + /* 15 << 98 */ + { { 0x21f6c96c1ad77f33L,0xb5da9d34992e7807L,0x17fc994ba7192adfL, + 0x59f204fcbcc3f8b2L,0x3f4a970f10bd22f5L,0x42936bfcbaa1188dL }, + { 0x6239fea5eb985837L,0x5fde15e0b33d1158L,0xe0bbe9b800cf90b2L, + 0xf2c6d8b16b2b68a8L,0x58c331cd0f3a2341L,0xe951c48910dab1a4L } }, + /* 16 << 98 */ + { { 0xdccf68bccbaf4685L,0xb333e464270a2bccL,0xe43ae199254dd3e3L, + 0xe8526e26ddce5c84L,0x52bad815ea0b4258L,0x67c12c1b094574c4L }, + { 0xa5362fcb861545b7L,0x3e904c35c2b2eb62L,0x0f9312b5eeffc2cdL, + 0x5475657b14de4e5bL,0x746e67d4f0233fa5L,0xb5157d7f35471ec2L } }, + /* 17 << 98 */ + { { 0xcbaf92265315e83aL,0xcc6e9a972f15ff37L,0xcac446dde8c87fb1L, + 0x5fa37a5c672d7f92L,0xe66efc07b1380425L,0x2d8ed2e32c8e59ebL }, + { 0x8e3ab80461743725L,0xe59a87f825493349L,0xf6995fe16062fe7eL, + 0x5d7f8a646e8de27cL,0x4a5ecbbbebe084f2L,0x99fc5ea93f863156L } }, + /* 18 << 98 */ + { { 0x1ddede1b495fdc2eL,0x3dfcf56b039d6339L,0x54c423806a56c492L, + 0xe6bfd184def6446fL,0xfaa2fa123ac841beL,0x503e319a4f9330a4L }, + { 0xd9305d4654ad427eL,0x68d23497d95dfcc8L,0x2d935aad1e9602f5L, + 0xd7e74bf2e33174a9L,0xc8e4a0b17225e2b5L,0x5db7187cbcda5221L } }, + /* 19 << 98 */ + { { 0x9a0e0908b0ec0b27L,0x28894b2edd759131L,0x0107bb592b9d6f02L, + 0x318921deeea022f7L,0xa1a00f5882c73390L,0x877833129551b381L }, + { 0xff866039a3a9dd22L,0xa59235ffdf0fc09eL,0x530c2fe61ca647f4L, + 0x77b1ea2860f9428bL,0xeef2a9e6bba4bbabL,0xdbdbe037204f5ea3L } }, + /* 20 << 98 */ + { { 0xf55edabb90b86166L,0x27f7d784075430a2L,0xf53e822b9bf17161L, + 0x4a5b3b93afe808dcL,0x590bbbded7272f55L,0x233d63faeaea79a1L }, + { 0xd7042beafe1eba07L,0xd2b9aea010750d7eL,0xd8d1e69031078aa5L, + 0x9e837f187e37bc8bL,0x9558ff4f85008975L,0x93edb837421fe867L } }, + /* 21 << 98 */ + { { 0xf87a92375b2e5fa6L,0x88571e4452a3a605L,0xf85e9a330c8f5f55L, + 0xf99886c599dc2c97L,0x5866329d065261daL,0x9011f13912dd434cL }, + { 0x0cc67d535284c555L,0xf8f715274a4032caL,0x4b002683a9524bcaL, + 0x3c3c12910f63a7baL,0xd19e173e9124eb8cL,0x3431c51c54b7d85aL } }, + /* 22 << 98 */ + { { 0x7103ab4ae11cc85bL,0x2064ca41789cf87eL,0x592850ead5f13a08L, + 0x56b9ff066212e096L,0xa106455d6efa7445L,0x3e62aac92343c5efL }, + { 0x7edbf70dcb8ddf7dL,0x27f00a4a5f2687e4L,0x7d4ce32e44a08d11L, + 0xe97f0910890a57f1L,0x792597fb912cb027L,0x1fa7a1d2ad3492dfL } }, + /* 23 << 98 */ + { { 0xbf4e161c3cfad317L,0xda4e6bffa1998bc8L,0x6534ef622e890b99L, + 0xd10a3b24d272cc42L,0x3f81b0e5f1194dabL,0x8919caefec549c5cL }, + { 0x847ef47f68f5633dL,0x01cd59975468f4afL,0xc38bce29b6727408L, + 0x56a1cd1ea4c84268L,0x31a493f406b81088L,0x4461ce8531b37e73L } }, + /* 24 << 98 */ + { { 0x3503d9371f23a0d8L,0x64c598a8c321dde0L,0x67f101ef5b52e0f0L, + 0xb6b5b4c2f955b5faL,0xb5f03d53880e0569L,0x121c3ac1c99393efL }, + { 0x90755bd657330666L,0x70ae5793d4d71d3dL,0x326ffd519e9ce792L, + 0x1b772d7396ccfa14L,0x652710f4874a22deL,0x72768469db210342L } }, + /* 25 << 98 */ + { { 0xb2d85722b3413d7fL,0x4e41362092e55ea5L,0xad1a20c7ff7b3409L, + 0x743b31c0c6f98cbeL,0x1b5b0b5adab3810aL,0x628d9b212cea0428L }, + { 0xa3e24294b0335ba0L,0xa9c0e139487530a7L,0x54199640072e70eeL, + 0x0977586e64c0d563L,0x393878451c5cce35L,0x57acd85631ce1eeeL } }, + /* 26 << 98 */ + { { 0x63081bcf9b8d9f3aL,0xb09fe52b6f94e3e9L,0xc232e5d1e39c092bL, + 0xd61ddcccf5f072e4L,0xcdb3b4189a26a93cL,0x0c010c048de6f5c9L }, + { 0xad2473a5d238e823L,0x4120ab3632029ca0L,0xd6632edb639bb8ddL, + 0x3383f077a8b32fe4L,0x8afcbce5eacfbe80L,0xe28236212d2fff74L } }, + /* 27 << 98 */ + { { 0xccf2a24a0eb3829bL,0xdd8fe4421eae0751L,0xb685b073c9598d91L, + 0x025214ce8b308785L,0x11c3fb11d6433acdL,0xe40cf39c81794024L }, + { 0xa167651b1c0b1f54L,0x350cf3eb0bbde983L,0x69c93dd0b2a88c48L, + 0xf13afc37bee80b26L,0x0be7d05d776345e2L,0x1ccbc8ba7645b02bL } }, + /* 28 << 98 */ + { { 0xaa6489df83d55b5aL,0xea092e4986bf27f7L,0x4d8943a95fa2efecL, + 0xc9baae53720e1a8cL,0xc055444b95a4f8a3L,0x93bd01e8a7c1206bL }, + { 0xd97765b6714a27dfL,0xd622d954193f1b16L,0x115cc35af1503b15L, + 0x1dd5359fa9fa21f8L,0x197c32996dfed1f1L,0xdee8b7c9f77f2679L } }, + /* 29 << 98 */ + { { 0x2aa349975442c668L,0x4c5137130cd74444L,0x4f87be0f449300ecL, + 0x13e07b552bae04fdL,0x6aa575d11f75acf6L,0x4502e9e9852848a9L }, + { 0x3c246d38889666fcL,0xb6c0292b7c100867L,0x618f234aa2a280e0L, + 0xf983c834669afe62L,0xc51a15105d900a1fL,0x7d7ce31bc952f419L } }, + /* 30 << 98 */ + { { 0xe3dbb7483c3388dfL,0xc26a7d042c32f139L,0xc1b48180ed938dcdL, + 0x785b964d42e4c01cL,0x507cd16aa1f75e28L,0xfaabff8d1f323caaL }, + { 0xc6bc47ceadd5b649L,0x997dc0ee3c0aed28L,0xcef0c89bf3666cfeL, + 0xd8d7dfb426482ea7L,0x5f00e432d2348484L,0x09549b5a1dc66aa6L } }, + /* 31 << 98 */ + { { 0x702e450ef8464b1eL,0x52d20765a061c4c6L,0xe1c930b26519bfc6L, + 0xa9c0c8c6d17ea02dL,0x52bfc60ddac62461L,0xc325568f7c5f9a55L }, + { 0xe7413df9eb44b9d7L,0x461682265837e0d1L,0xfcb9628c15aa0c89L, + 0x83d6d0eebb57c6a3L,0x17bb82a56829c9fbL,0x342fe91c496861e0L } }, + /* 32 << 98 */ + { { 0x58d6998e171c1439L,0xfd4a98f401feedecL,0x420b2a0165739fceL, + 0x5c5db30822f7a073L,0x016c547805042f00L,0x5fc73ce2a12413d9L }, + { 0x8ceb2d70e932aa17L,0xb4d66b670537afafL,0x2638d012339c146bL, + 0x02fbb7b628ac0555L,0x7fcb0c8162d46e63L,0xeaa9ff4f066d088eL } }, + /* 33 << 98 */ + { { 0x45f53090b8b22c29L,0x155b8f8111e70d5aL,0x5ec118b25d3a7d83L, + 0xfe4c7eb39c4ddd1aL,0x8cdfb753f226d869L,0x20bb870779fc646bL }, + { 0x3c8c1d7a25d1308cL,0x5a976ae47116f347L,0x6af949a60faf9690L, + 0x7e6718fc07f3472fL,0x16ec7b45267b17cbL,0x80744641cebe1bd7L } }, + /* 34 << 98 */ + { { 0x45eded7ab2a5c8e3L,0x4308485969a0681bL,0x89b7510d90910e8bL, + 0x1c622d04d2066d92L,0xdc3b434bcd2f0d7cL,0x98bcb83b476ea5a3L }, + { 0x9195431d3dbf2be5L,0xfec7efd969275ac5L,0x6a4364f556a7da4dL, + 0xaf701bc579c177ccL,0xb77ef33e9ffc2a47L,0x2bc59331cc23c4e4L } }, + /* 35 << 98 */ + { { 0xedf4a85b9d43c51fL,0xc0afbcb6b59a7244L,0x3ede2f25626e0ca8L, + 0x45836582270f674dL,0x83c47048bf06d267L,0xbb1e994f3c68314eL }, + { 0x50d79cb4f2fe6c8fL,0x1a1d8aecdf7600f5L,0x216f5d2bef4e4857L, + 0x41361a90bdffb9e9L,0x8040f5c173d2f9caL,0xe6665f0dd1e9be4dL } }, + /* 36 << 98 */ + { { 0x5405179f394fd855L,0xc9d6e24449fdfb33L,0x70ebcab4bd903393L, + 0x0d3a3899a2c56780L,0x012c7256683d1a0aL,0xc688fc8880a48f3bL }, + { 0x180957546f7df527L,0x9e339b4b71315d16L,0x90560c28a956bb12L, + 0x2becea60d42eee8dL,0x82aeb9a750632653L,0xed34353edfa5cd6aL } }, + /* 37 << 98 */ + { { 0xb112fd7b36386e2dL,0x358e974a6a634bd7L,0x509814737faf640aL, + 0x1036bdacef39b3aeL,0x410c6448db5aceb0L,0x914671305bbebe92L }, + { 0x83fabd54e9e009e4L,0xb2da8eea9994d16cL,0x9d73da6356997acdL, + 0xea9158b97ec1b844L,0x8e6a6e3129714795L,0x23e98f57131243f9L } }, + /* 38 << 98 */ + { { 0x7105f727552664dcL,0x97cbfb6c5c589c8cL,0x1a7b110a70fc59b3L, + 0x46c39f2cc754c69dL,0xcda0e2c067b1f17cL,0x35fe45fab7ede210L }, + { 0x6b3ecb7d82e78b40L,0xa90eed4fdbc07241L,0xa73797895aacd533L, + 0x28120ba5f4fa89a2L,0x9c1fc09ee3055006L,0x71e665efc51653a4L } }, + /* 39 << 98 */ + { { 0xcf782247d28b5059L,0x15bef4cb1b89eb06L,0xbc182ed6bcb4afeaL, + 0xcf5b6dfde0e32b77L,0xeb61aff9d9446052L,0x5846f171c4bfc0abL }, + { 0x61d5ae1c6fc68422L,0xa282c56846e870afL,0xdb4859d16bca8fbdL, + 0xd4cd416e97caf135L,0x11217fa9c3debd59L,0x27702da6370758ddL } }, + /* 40 << 98 */ + { { 0x8273db992d189057L,0x4d1b05fce1b5f8ccL,0x5fec7c830a7c32d1L, + 0x28ddaf28ea9b4d45L,0xb6bb62aca2fc58beL,0xfc65b7aa4a41852dL }, + { 0x6e7651941c9e6045L,0x3acabf28fc116257L,0xc9d5e8054b5a4ba8L, + 0x9a072259cbdcf1ebL,0xc67cf643439fc8fcL,0x917ef6f8b4333aa8L } }, + /* 41 << 98 */ + { { 0xee6123cca6411227L,0x91372d080ee882bcL,0x2c30a840a638a4faL, + 0x1867421321e83d4fL,0xc6afa4cfc3fb9925L,0x19aec276e4fdc73fL }, + { 0x1ffec4510cf4e610L,0xac57292ede22d429L,0x62844d78e6cacbc1L, + 0x0eafcc554d2e497cL,0x39f1acc8e780f600L,0xfcf8d914fcff8c6aL } }, + /* 42 << 98 */ + { { 0x0734ab43ff2152d0L,0xe52c5dee930fea54L,0x9cac7efe940bddbfL, + 0x30d2610ddbd43391L,0x4beeb865921c124dL,0xa19fe6a4fca219fcL }, + { 0x588395628755cc47L,0xa7f301241324f2d1L,0x4fe38ee3b1ec5aacL, + 0x3583542eb16413ceL,0xfa92e2191733b7eeL,0xc0f30ba32b2001a4L } }, + /* 43 << 98 */ + { { 0x706b02c3febc7968L,0x6e45dc90c96a6b64L,0x34e5f890f95aa4c7L, + 0x8ae64d487683b855L,0x0fbb9c4a62e03ebaL,0xb32a965ce2cab115L }, + { 0x4a7084a8b33102b4L,0xe7fd9db3ebd1bd6aL,0x2fcb233cc7f32b61L, + 0x365896d5f2549734L,0xa3f18bfd25c7a1c4L,0x382950ef212b8daeL } }, + /* 44 << 98 */ + { { 0x82154d2c91aecce4L,0x312c60705041887fL,0xecf589f3fb9fbd71L, + 0x67660a7db524bde4L,0xe99b029d724acf23L,0xdf06e4af6d1cd891L }, + { 0x07806cb580ee304dL,0x0c70bb9f7443a8f8L,0x01ec341408b0830aL, + 0xfd7b63c35a81510bL,0xe90a0a39453b5f93L,0xab700f8f9bc71725L } }, + /* 45 << 98 */ + { { 0xee2b773e4ed17990L,0x499e83623faab7feL,0xa3925e2f71abb9efL, + 0xfee50406ce3b4a69L,0x71a15070bc10f803L,0x5b01e4a2c7bab10aL }, + { 0x806c590d99e51e36L,0x34adbaf6a7f88d5aL,0xd4a93ce9f6b30ac3L, + 0x39d2cf40dc33fdfbL,0x13e676f1d5e4e7ddL,0xbaa72ab9199690fbL } }, + /* 46 << 98 */ + { { 0x85017690e51b47daL,0x25919b58a2b476ceL,0x6f692de103ec5d55L, + 0xd6cf8ee5d022dcebL,0xaf3225238ba7076eL,0x917b373728c902d5L }, + { 0xac75fddc3fdf8590L,0xe83d9bbb64fc304cL,0x13550de2971f659aL, + 0x70bee07ee12b7bebL,0x9989d2fa0a855646L,0x8b6043aca576b3a1L } }, + /* 47 << 98 */ + { { 0x1bfd4f92fadf9017L,0x1e4509aa737bc67cL,0x88278c3699af1ffaL, + 0xbc47536f4678e22bL,0x69914cdb1b07c823L,0x56fc28ab97277358L }, + { 0x092d28efe752d2f7L,0x6a8286a691da62c5L,0x86b702778033c632L, + 0x57ef284e7672f41fL,0x9101ed302e54007bL,0x53e94cfed25d8d19L } }, + /* 48 << 98 */ + { { 0x311ebba2fc37efedL,0x8a6a42d660cfd6bcL,0xb4051b3af2a4871eL, + 0x66ce77b8c2f0ebf0L,0x84abc9480ad28477L,0xc82e5c6263d9d11aL }, + { 0x99ffc70c007dcf93L,0x5e974edfd964c822L,0x0fee3572513085e3L, + 0xbe67a88046ce8444L,0x136ceeb806d17129L,0x0da512ae662d86fdL } }, + /* 49 << 98 */ + { { 0xeae827d989e687ddL,0xb025f0723bdbdd9dL,0xfbddcecec3a575aaL, + 0x3fab33c1f80d12cbL,0xd0232142b32f0381L,0xf00e74bd3b6c3132L }, + { 0xb7c1311e0e44deffL,0xf3d790ae29b04d6bL,0x3d3744b846f72957L, + 0xc0890fb6ab2f13e6L,0xa669a34324461f0cL,0x35c9677ddd72fcb7L } }, + /* 50 << 98 */ + { { 0xc257ed518060a28fL,0x3a9d7e1cc72fafebL,0xa304a5e8332f435aL, + 0x96969bc234ccf343L,0x2aae4d8e7702ba84L,0x37f15631f203a7eaL }, + { 0xc0000f24c9666405L,0xa98eb834a537fb89L,0x8c0564cf7e36dd1aL, + 0xb5ca507b4e89615cL,0x9bfa209a9d80ef92L,0xe2ec1879a83f02e8L } }, + /* 51 << 98 */ + { { 0x73b4573c11dfdea9L,0xe5f208ee5c8cc81fL,0x5c240d3c769adf12L, + 0xbd3f8f33550c53acL,0x98171d16bb4f43acL,0xaf19d5fe84db9e13L }, + { 0xc589be0d2e53345eL,0x3184b540f114f6f3L,0xa35ed77e4946090fL, + 0x427b860afd3108fcL,0x7d0848c3867df76bL,0x353539e2a32ec485L } }, + /* 52 << 98 */ + { { 0x9401aec2b9f00793L,0x064ec4f4b997f0bfL,0xdc0cc1fd849240c8L, + 0x39a75f37b6e92d72L,0xaa43ca5d0224a4abL,0x9c4d632554614c47L }, + { 0x1767366fc6709da3L,0xa6b482d123479232L,0x54dc6ddc84d63e85L, + 0x0accb5adc99d3b9eL,0x211716bbe8aa3abfL,0xd0fe25ad69ec6406L } }, + /* 53 << 98 */ + { { 0xee174af2df740edcL,0x1bd8382c09233f0aL,0x34a7450e7d343006L, + 0x92259ddd3d463e61L,0xcd0bfe6fedbc3af2L,0x39627c4cfc8770f4L }, + { 0x7b7c688ddbabdf2bL,0xf459f0e64bef3558L,0xfa0e87becc88f7c8L, + 0x67beabac5fcc80feL,0xbdae52bfadeba16fL,0x4751724c5af5c9bbL } }, + /* 54 << 98 */ + { { 0x5627e0d016332364L,0x33839376fc57f01bL,0xe7fc2c489528e434L, + 0xa0ee39acb52b3757L,0xe49e383ee42e4832L,0xabfefdbb31359afbL }, + { 0x5dedb6f3b99ee196L,0x38abe58bc16aac17L,0xa300a1333ec06a07L, + 0x00e68eadc90d4659L,0x60412e8a8000a773L,0x6099b6a6a5830c94L } }, + /* 55 << 98 */ + { { 0x85364bd10d340c80L,0x14b89462be64bc9fL,0x16429134b542faa0L, + 0x0d4cf3ce73683e2bL,0xf9a3e443cb73ab7bL,0xa4c2d0afbb156b0dL }, + { 0x826123921bc77675L,0xaf2aad4a5f26c238L,0x6f6f5d9aef4656bdL, + 0x0e20425f90901f3eL,0x0e30bfef9943a673L,0x6cefc62847415a28L } }, + /* 56 << 98 */ + { { 0xe7acaa8457e0105dL,0x3c06d3bd3851fd57L,0x23cf3c612a9c631bL, + 0x13888aaa33863bf8L,0xf2396355717783eeL,0xf21e1a4836b300e1L }, + { 0xa734cb3b9d27b4cbL,0x0a7effed796e34b6L,0xfc5864773615cc7aL, + 0x1f98ed7788844a21L,0xd6e289407ad4c7bdL,0xa00d64ebe9331c7eL } }, + /* 57 << 98 */ + { { 0xcc6ce7dee1c1e159L,0x77982e4f03df6b56L,0xbd8307d1b82b5ebfL, + 0x43e25358ed881b82L,0xddba4f418e0eb034L,0xbe326c36f919800cL }, + { 0x97d03da7af52dfaeL,0x153bb17af4bf81c5L,0x29bbb9bed7ff322cL, + 0x7a7bd8c7232cca47L,0x7474c199c2830f03L,0x9f464a06f0065fc4L } }, + /* 58 << 98 */ + { { 0xca505cb553b876bfL,0x6fc27f553662cb5fL,0x891cbef432cb1636L, + 0x339743f16e27e2d9L,0xde76538f21dc4837L,0x9cea05020efe241cL }, + { 0x97b8deb65888d9acL,0x4d3c28cba4b6cc56L,0x88ca828f840910b3L, + 0x2e5727cfbfde6793L,0x05a4138302bbae6cL,0x2e72fd653fa8e23bL } }, + /* 59 << 98 */ + { { 0x5b88c5ae6d17fe02L,0xc9b14810d6dbe104L,0x170b8659873be863L, + 0xdc5946a6ae9111b4L,0x4cfa5f022819a4cdL,0x7653d06ae213bb7dL }, + { 0x324c41baabd7ee74L,0x4219968cdd1608f1L,0xa5e104704adc1561L, + 0x964a53ea5e16d818L,0x00ebd1d4980f4bd2L,0x23cbb80d3518144dL } }, + /* 60 << 98 */ + { { 0x0d5c1769df85c705L,0x7086c93da409dcd1L,0x9710839d0e8d75d8L, + 0x17b7db75ebdd4177L,0xaf69eb58f649a809L,0x6ef19ea28a84e220L }, + { 0x36eb5c6665c278b2L,0xd2a1512881ea9d65L,0x4fcba840769300adL, + 0xc2052ccdc8e536e5L,0x9caee014ac263b8fL,0x56f7ed7af9239663L } }, + /* 61 << 98 */ + { { 0xe6ece4b5dae76820L,0xd428354e95feec03L,0x43517722f8871f7bL, + 0x313fde11e84d0b7cL,0x7f02824b1cae0a45L,0xf9f560c1d6646bc4L }, + { 0x124d88bc903a0608L,0x950e8320370c7ff2L,0x29e6da714090a72dL, + 0xbc5a108c54547d89L,0x809330cd3e484deaL,0x1b04a8088bb00f0cL } }, + /* 62 << 98 */ + { { 0x2425c59c03e0a528L,0x49de96f425c2be3aL,0x30b52686fff4b610L, + 0x2ce573b0f2e5f7b1L,0x4ec05f07b606f0e6L,0xf2040886366ecbf4L }, + { 0xc7fd993460d404d3L,0x8a064992fc12227dL,0x9c6d64ec215492b1L, + 0x2793bd0903463ec1L,0x49523ebab7376e80L,0xb138dfbd35b14fd6L } }, + /* 63 << 98 */ + { { 0x5ed097b0df7363adL,0x21319edba5696d91L,0x17c46519c5d5313dL, + 0x341d46576c6cccedL,0x60d80713692bc704L,0x9477b6e907fb8e13L }, + { 0x2965720b532e0c6dL,0x2767b4ee87831d79L,0x3e2e67abd4b5ef14L, + 0x45ee89b5d2598521L,0xfc8f1e3ee6441648L,0x75c4db57567ed090L } }, + /* 64 << 98 */ + { { 0x17e3d0b8713b8541L,0xf372b048c6b5e839L,0xf8ef0261d0bb1848L, + 0x9b804ceec71a3bbeL,0x00b7d171542a88aeL,0xf2b8ed10e9097b9eL }, + { 0xdbad9f122c0a009aL,0x245fc1e9205fb1bfL,0xa8a4834fb83debf5L, + 0xc3ee226d637e449bL,0xe3070d93cab82664L,0x24b8094db37320e8L } }, + /* 0 << 105 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 105 */ + { { 0xb506b7b925059699L,0x349fd83f01ab02e5L,0x64b729ad3789281eL, + 0x69ae8f81f9af4561L,0x007befe156f91860L,0xb578c566edc250fbL }, + { 0x1c16d75a67ae4801L,0x04c35a7ea1d3f592L,0x5dc97da936881f89L, + 0xaddb603103a5b1eaL,0x7eb515b13e153a0fL,0xdc3a92192b4a1ee2L } }, + /* 2 << 105 */ + { { 0xe7365f9e512cc92aL,0x9efdcf8b5172a654L,0xbfb389ac8e611fc3L, + 0xce778fd5699c227dL,0xdc1f47b63ff2ef17L,0x2ae0f68302672ed4L }, + { 0x51c63806a8e879cbL,0xd3dfecf03909f526L,0x375b3d13e00e12a2L, + 0x91f9f750bf8df325L,0xf1ea0e421df5f21aL,0xaed73e7f32c60584L } }, + /* 3 << 105 */ + { { 0x03b07fb5e0728e6dL,0x9e0469201012234eL,0x272e644935637644L, + 0x2b6ad1c2a55bcadfL,0x86c527765c71c6afL,0xa25bd60bc1678806L }, + { 0x0cae829476bb32f8L,0x389ce4e633e03cb2L,0x504df8337513dfb6L, + 0x4260ee8e1b351ddaL,0xa473c5d9dbaf7cd0L,0x22cb7cb471e390fdL } }, + /* 4 << 105 */ + { { 0x1d9aa9fa26caebd8L,0x6b64686926b7a673L,0x7ebed6a17f167b47L, + 0x324c13f85bd9153dL,0xe9ea5b734c682ba6L,0x2961da7d7e3ff6e2L }, + { 0x1ed2b05001a83dadL,0xb232951dc4a2f60aL,0xafcea5d3d68b8ec6L, + 0x21dc058d1c6ce0d2L,0x0043de75e719410cL,0x4edd792ce15cf534L } }, + /* 5 << 105 */ + { { 0x0f45245f3babe09eL,0x0959326fa9f2fac5L,0x7629e7fb5cc136e5L, + 0x208bd5a6e48b7eb0L,0x637891d6b75a85cbL,0xf0ad9d8d9f27b57eL }, + { 0x437b6944e0454b05L,0x022c51d702ed3592L,0x0f79e2bd0dc0a769L, + 0x54ace1fdd9b81f9bL,0x38611d66f95ea8dcL,0x52443ca8f0e6147bL } }, + /* 6 << 105 */ + { { 0x857d68558bc272d0L,0x4583eeeeb5be2485L,0xb83586dafe0152ecL, + 0x8b0eb223e830294aL,0x757582b6a5b0e880L,0x5140c0169cca7fffL }, + { 0x07a00782e9228f12L,0xb96e2b5dd4973080L,0x3cceb9a6e88efbe6L, + 0x9955b63073fcdd25L,0x04f26ab02805d470L,0x90b38299424da086L } }, + /* 7 << 105 */ + { { 0x73f1ae48f4f6c5b4L,0xee5af13d4a477f01L,0x274614a2ddb93d52L, + 0x90b0c563c320aaf5L,0xee2303c8ef990b0bL,0x00d028e73061f140L }, + { 0xff705011cb3d8eafL,0xae1d990862594f4cL,0x22a27cecdafea438L, + 0xa78e12d5c5962ea9L,0x5bbe9d878e65f9cfL,0xa222580cf47cefa6L } }, + /* 8 << 105 */ + { { 0xf7aaa732959abb9eL,0x1222ad0a2ebf80b9L,0xa1a417372e0c286eL, + 0x3b6685025da3472dL,0xbc0d116b7576f2a2L,0xfdbcad95a36a27d4L }, + { 0xcdb3f4749d54f7eeL,0xe2e0f5f98a5643a3L,0xc70d11b969d4f171L, + 0xdf96d1366cca4ef7L,0x570693db2fc6afdfL,0x5059e67b567504daL } }, + /* 9 << 105 */ + { { 0x2c8107d47fe632a2L,0xfc46c745ede7bff8L,0x2d3b12864650025bL, + 0x815ef3cbe74cd65fL,0x5431b01ba256f01cL,0xe832ff1139915cfaL }, + { 0x2c106de607d7af84L,0x67303b786d4753e7L,0x5f886ffa6d75c8deL, + 0x932a6c20967131cfL,0x5bc94a9170aebbb0L,0xa85b3044fd56e06dL } }, + /* 10 << 105 */ + { { 0xc904558ae7eba799L,0x46b6031bb2fa7331L,0x6620e2b50653675cL, + 0xd1373a357d2218f7L,0x0f4b3ca3af55a5e7L,0x50774160714e70c2L }, + { 0xacc63d1469188455L,0x89a795fe043b8b30L,0xac2fd66ce1e4b9cfL, + 0xac7927021bf67f26L,0xb9513f0d1143d437L,0x02198050811f2931L } }, + /* 11 << 105 */ + { { 0x6d4acdba7b480776L,0x8b518cd466dffeb5L,0x8826c99451918859L, + 0xd2b6a7a038fad835L,0xd315417a6929a870L,0x05d85252c5a769e1L }, + { 0x2fa06335ec0d091eL,0xb0cc337287768c88L,0xacbda5ba58a2eb9dL, + 0x2a404fc976b7b057L,0x073abb71838c6135L,0xbdf89b135cfc4f3cL } }, + /* 12 << 105 */ + { { 0xd00eb9c53508675fL,0x92ec76a4a117dc95L,0xf58d6f85334ca15cL, + 0xeeb522169cee0544L,0x3eb9847ff21457c2L,0x547908bc5524c60dL }, + { 0xb5b49d225198709bL,0x718abce6324abc67L,0xdab8ff2f4abd54baL, + 0x98be59e67184d444L,0x45b74b54babeb4b0L,0xd8d8bb30ff71a5acL } }, + /* 13 << 105 */ + { { 0x8aedf7e28ec13e6fL,0x8b952620d950792dL,0x36e9dac204918f59L, + 0x5e49a5a2d3dd47edL,0xb17455bee863c2bdL,0x8caac6a9326a0d66L }, + { 0xb6c3f5e427bb72e1L,0x17566c9dee5fe09bL,0xfd6bbcc25e3db64dL, + 0xd437d07a3189319cL,0xad00dfc4cd3166a5L,0xab75927b0bd63003L } }, + /* 14 << 105 */ + { { 0xa7672a39afc43be8L,0xefc49015c72f97aaL,0x81c63c050e48f2edL, + 0x62f39f32833a22ccL,0xf7a3480172c0c0c4L,0x4711cd41a4158538L }, + { 0xa3c99a4d1d15f2f3L,0x4b82c1c17bee1b47L,0xc7d60b489d199f10L, + 0xd1d1f03d5f16fa95L,0x96c780c932fbeaf2L,0x0662e250376ff106L } }, + /* 15 << 105 */ + { { 0x728e334678571c8fL,0xd0a886b56cb339d3L,0xf4ea33380a5671baL, + 0x43823401a64850a4L,0xa7729cd533117b9dL,0x4dd457602b78cffbL }, + { 0xbe0571115a67d812L,0x7ec6cf925105a3fcL,0x5dbcb4bc0ccafeecL, + 0xa7587f15803092f8L,0x67ee61d5a884efadL,0xd4ced554ca47d9caL } }, + /* 16 << 105 */ + { { 0x02c6b6083b03dcbcL,0x2b20149e3b9d868aL,0xaf5ab01d4f57eb0cL, + 0x59935b94d750e515L,0x32721b408f89ad68L,0x673bd755a7e3ceffL }, + { 0xbd462fd8ef3b3393L,0x991422640e59a120L,0x4162da619263fa61L, + 0x2ed1f2deb6488eb3L,0xb0bd37a8725680c4L,0x17218bf029ec27b0L } }, + /* 17 << 105 */ + { { 0x444071ff84ff1ebcL,0x4b4171e87f789cbdL,0x4a832cca2db4e8daL, + 0xe229ffb6dc209c05L,0x9efbfd7eb5f0b3f4L,0x65e07fe774fbbe6bL }, + { 0x2892c8ac627b9d41L,0x01a20eb94297e7a9L,0x2f54e88646f29860L, + 0xc425accc188798ecL,0x6137251c85c80580L,0x6cc0f9c4f386581eL } }, + /* 18 << 105 */ + { { 0xf677bdd11cb61a7bL,0xfca1faf8932d6113L,0x1d5bbf97a531bbe2L, + 0x3d5e4860c849fc47L,0x388943cd95fe4da2L,0xffb7d5e073add43fL }, + { 0xc3166ae828fcc058L,0x89dc7faae0d6f6e4L,0xe6daf1a6f527ca01L, + 0x500a703a56ef1d8dL,0x3573d0a3fc914df4L,0xd780e745ef8dc2a4L } }, + /* 19 << 105 */ + { { 0x90a8f3380500afbcL,0x8c303270838ccf6fL,0x82cbdc98458254c6L, + 0xc2f24d03b367ddbcL,0x5d3daa0d6c882354L,0x824d313d376599d0L }, + { 0x6e5075df7b9dd1b6L,0x6871a3d4d69c9828L,0x8b3762f59cffa148L, + 0xf2184f67eef8c656L,0x437630c296a1537eL,0x92a0667c4cbf8249L } }, + /* 20 << 105 */ + { { 0x6e929912ef619478L,0xe7ddaf255ffc5939L,0xb71133cf96dbbca5L, + 0xee8bd53f17da5104L,0x7601ce6adc49be68L,0xa1ca3b3cc63f2a87L }, + { 0xebf388c2a0de1668L,0xa0f6c38dd0ec6bd7L,0xc8e0875ddac451ddL, + 0x179fbbe5a5afce85L,0x0727095673bfb06bL,0x992afcd047622925L } }, + /* 21 << 105 */ + { { 0xe3b0122624f262c3L,0xaa7a0925dae30b22L,0x36104c95a96a18f9L, + 0xdc6090f5539b6740L,0xd70270ba11040a88L,0x53997b57ea3342feL }, + { 0xaaf1d47d63393e4fL,0x9db8aa3fe8a99625L,0xed571a32c3926e1cL, + 0xd6e898526e565346L,0xb3984bbd873b2589L,0xaeb7bf3f3f5f68e1L } }, + /* 22 << 105 */ + { { 0x75a4a19a79ded4a8L,0x1368e269f688177dL,0xa24d67118581e23aL, + 0xae63d5a6746b3830L,0x0c68d3e314017304L,0x521a5e7de4d45dc9L }, + { 0x69d9adfaf77ca616L,0x1f8d37f4bfda67f3L,0xa2833ba1027e771dL, + 0xae49b00367141a63L,0x04e6f282ed6f1968L,0x65d7d88f060f9157L } }, + /* 23 << 105 */ + { { 0x5dc3137b512e4026L,0x43e189595d6ac980L,0xdb7dfef39eac06a4L, + 0xa8f3e2aea09b0650L,0x80a8594c575e047aL,0x9eba41bcf0c58bf3L }, + { 0xdc04cc7679812341L,0x716050eaeed1be66L,0xe559782099b77be8L, + 0xe543aef055183ad5L,0xbbddfb814c08a959L,0x6e54d86eb5368e8bL } }, + /* 24 << 105 */ + { { 0x170f8a74e7aba263L,0x6b4e1d7b986b151aL,0x5f65bd224b08921aL, + 0x1017ae3de6caca3aL,0x613f36b626cb9d5bL,0x8a1e2f2ded19d99bL }, + { 0x52c915a5c3c519c2L,0x3c9a33305902fa08L,0x2cd7f7c206a51a12L, + 0xfed60db66e0197ceL,0x4e5b2bb7d971b04cL,0xebebeebf2f45ab13L } }, + /* 25 << 105 */ + { { 0x43b10a0673220e06L,0xdf93af67777cf022L,0x830195efbeea9ed4L, + 0x0a36b71812353c9bL,0x520e2e8d1ec8c488L,0xdc985ffaadac5e16L }, + { 0x0ebac566f3f58ed7L,0xc7747562a2cd13a2L,0x6a5b4cbce3901864L, + 0x66634acaa374b634L,0x45e000877f4680dcL,0xb783d01f9fdbe92aL } }, + /* 26 << 105 */ + { { 0xcf6d51be36e1c05bL,0xf59b6665e1da0ad8L,0xaa8bfb9d727a701bL, + 0xb1680942e26e268bL,0x09d41407e518661bL,0x8b0dfbfb3757a993L }, + { 0x34ecb09f6cb33380L,0xfcd77efede342bf6L,0x9f8fa6c6e476c5eaL, + 0xde30410fb6257416L,0x416ea101bbd47b91L,0x86ebd19e4aeede80L } }, + /* 27 << 105 */ + { { 0xfe7562e00818226bL,0x922d8fe662b46275L,0x6216698b491adc2eL, + 0x5bdf7a59f6a38f2eL,0xc0640bf937710dfcL,0x06ad30a9df687f48L }, + { 0xc561dc7d3eb66e6dL,0x7444ac83d08616c3L,0xebfcccee84984618L, + 0x35a03bafbb15eb51L,0x7c907f9fc17a5de2L,0x2e48ddb5814634dfL } }, + /* 28 << 105 */ + { { 0xe466d7a7ea51a37aL,0x5203e990cdf97186L,0xf700953096c84ba0L, + 0x4e32fbe65f89d1adL,0xe530349aa9be221eL,0x0f7f9c2e50b31508L }, + { 0xa6796f5c3af5a574L,0xe220f6daa2a2df89L,0x99ec4811d8b65510L, + 0x4dfdac69ed373b27L,0x663f46b1bb55114cL,0x44236350d167e032L } }, + /* 29 << 105 */ + { { 0x1382e90ba65f6a57L,0x3557ab88e5c903e1L,0xcc0cc77f032067beL, + 0xdd8da09f67797328L,0xeb2979d45114c09bL,0xaaca95bcc4eb598eL }, + { 0x651a7ce5a2b776fbL,0xc20fe9315312ffc1L,0x842957357dcf479fL, + 0x022ba6e2ee5cc0a7L,0x6d27e37185b0ba5cL,0xe6f212bdbcd5f2c1L } }, + /* 30 << 105 */ + { { 0xb0c2ce87a9088f95L,0x47ec07e0acb11d2fL,0xfe84fba0d30ad231L, + 0xaa98e35f18a08eb1L,0x36adc3f2f6a27510L,0x622d202751fac4fcL }, + { 0x4be765cabb9b6ffcL,0x934193571cbfcbeaL,0x83542d9cbef14402L, + 0xf27504954612b4b4L,0x91aff597bb988ba6L,0x229031e51d61f6f9L } }, + /* 31 << 105 */ + { { 0x6b04a446ea29e65cL,0x9b6247a696c48a99L,0x95aa162f60c83930L, + 0xe387f544e30821eaL,0xbe1cdab306c51b7eL,0x40175d151fc7b8f8L }, + { 0x89df5ff36384d331L,0x02eb9aa4fe1aaf5eL,0xf24155f789675704L, + 0xbd2e8cdd87f72f4cL,0x2856b3c46de30f01L,0x2356f0a3ecf8af25L } }, + /* 32 << 105 */ + { { 0xfb09e7564bd044efL,0xdbc9fcdfbb964fb3L,0x451c5b01cdb1f4f5L, + 0xb02f9068f1dd1cf0L,0xd4765e7c0c687e41L,0x89b64981d1967bd3L }, + { 0x06a0e4ecf0439d65L,0x564c387da5abbcecL,0xc1e9d01ac651d806L, + 0x5e6ebd830618a96cL,0x9ce1aacec54ad8ceL,0xe5248a089953f90fL } }, + /* 33 << 105 */ + { { 0xd65f3b909b6ab239L,0xbc259a6d9ea8bf80L,0xc10d5c235944f964L, + 0xbd6b3f6f61eeac6fL,0xc4ef2d8383e92858L,0xb80d5ab0a3736bfeL }, + { 0x27bebd1176695c40L,0x4de92348ea4f5720L,0xd70d93e6070b892aL, + 0xfce03d0be626d5abL,0x2525e8ea81014bedL,0x6fa3df16a70e2799L } }, + /* 34 << 105 */ + { { 0x42b8350a7bbc41caL,0xd7861ad49af59bc9L,0x2453d07c5644d328L, + 0x2b92643ad7c8ec43L,0x7c14d3c7cd5f1fd2L,0xcee050463d373c7fL }, + { 0x17ff60bd0ab2b35bL,0x473925e0dbb7f655L,0xdbaa015aff3ee023L, + 0xbc1ff6d6087ecfbfL,0xc44e1c8c5fc66ca2L,0xc60a193850d6b257L } }, + /* 35 << 105 */ + { { 0x5ff44f3ed8f0983cL,0x9de50da0bb82cc15L,0x504f82ec94757c44L, + 0x72a4fc9dc8a07028L,0xd4d6e4cec3d5e64cL,0xc6148fe780008568L }, + { 0x71ba3fc525ef66d6L,0x969cc8694f6589f6L,0x5016c8c2d934ab25L, + 0xa78382f6959e8881L,0x28bcb8bea20eee18L,0x055ba80b37edd7c8L } }, + /* 36 << 105 */ + { { 0xbe389fef9c98ca3cL,0xdc3ab23b910370e5L,0x866cb37d5e8eb20dL, + 0x2f951ca9c1e32fc8L,0x54ef6ab15fe24e6cL,0x6038b5efcfcb8cfbL }, + { 0x362e076b6eec196dL,0x47bb3aefd398b505L,0x9f3128eb343711ccL, + 0x8dda2fa8d28e3269L,0x908c52c7eda48846L,0x65fb3a05d53b0917L } }, + /* 37 << 105 */ + { { 0xeae35c02ed711239L,0x16ab943fa97db2d7L,0x9770bb578f3b0599L, + 0xa88ffb95956d04f3L,0x3b937af5f4dcf6ffL,0x311ef2cc0bc41f56L }, + { 0x00e9214a2860ea2aL,0x2a64b18a7bd12d8fL,0x20a5b9da6a2b9dbcL, + 0x5c16a412fe1b8edaL,0x6fc306af7b9db98bL,0x964c35de25dc9363L } }, + /* 38 << 105 */ + { { 0x81f4739e6df16589L,0x2ea2fff11f8b8ac4L,0x3baff03d33e02c36L, + 0x7f07526874d77660L,0xa442d7fa758eed7dL,0x584cbe9866625864L }, + { 0xeed35d579d167ff6L,0x56627c2e3c7bf84fL,0x908df5aedd011153L, + 0x2694e54d242fc055L,0x25beed9a2f2d60c3L,0x29d3f22fe2ee5293L } }, + /* 39 << 105 */ + { { 0x14940dbc178f9859L,0x6e6e35b7329ec4a2L,0xd1f198096707db4aL, + 0x6eb310b79fe4233aL,0x8f92556eb41e1d8cL,0x2ab28e231d7ce522L }, + { 0xc5d0f5dfdd5c4d68L,0x3f5146d825101083L,0x3a04aa53de9ee4cfL, + 0xcf36f1e3d9357f64L,0x05a1896444889f68L,0x1096c87aa96a4137L } }, + /* 40 << 105 */ + { { 0xfa4b6697a8352657L,0xf5696452cad6ec30L,0x10aaba60986c84ffL, + 0x49bdfff4dae014e1L,0xe2a810bd0abc0e46L,0x1dc5b81462d1dd5fL }, + { 0x15d2f2c723bb4561L,0x5ac7b6421818e30cL,0x40c6b6f94c545f5bL, + 0x5875b6b2f99241e8L,0xfa3e88a9d6708293L,0x1c936920ad6d9344L } }, + /* 41 << 105 */ + { { 0x6516f6210e18ec42L,0xb967eb43df8c26bdL,0x624ee27e69addc2aL, + 0x34019d6339063252L,0xb317fdd3dcd99d7aL,0xc3d566825d314caaL }, + { 0x04992df3367506b8L,0x13e4ab2e547262b7L,0x35f130352e287d3eL, + 0x92e0a276211304d9L,0x94e7129417133d22L,0xb35302275fd71a28L } }, + /* 42 << 105 */ + { { 0xe1d9273c9ae60111L,0xe86aeac3d01243ecL,0xc7257b27fa5989f5L, + 0x57737dc89807d3ccL,0xe1ef78526937551aL,0x74ab9edb15dd2d58L }, + { 0xbc47b23cc59962fbL,0x376ff30fd3bba76dL,0xaf0035872788ab98L, + 0x1e475c68619b472cL,0xd79984c89c6a9835L,0x5ceafba510219a94L } }, + /* 43 << 105 */ + { { 0xc25ae81155d238d9L,0xf2a21fce4ba4456fL,0x4ebe44d0bd1a440cL, + 0xe821687f83d958beL,0xb4ce63423ba09f9dL,0xf271435d139048bcL }, + { 0x2a3db37c99c6412eL,0x50cba09ccb36dbd0L,0x9e5231aef6e65cf8L, + 0x48e9105d90118a6bL,0x2d58d372368144cbL,0x48702d59928575baL } }, + /* 44 << 105 */ + { { 0xc71ce040d1c9204cL,0x8ad09d7373f7686eL,0xbcc6d88dc6fcf31dL, + 0x22a0b71aaf428ad3L,0x7767944847721255L,0x2b720c7e316b808fL }, + { 0x3128a7cc5ed45b8bL,0x9744c6c0f79fa1c7L,0x738e94efd22728d7L, + 0x8a652496fff8f874L,0x0e4a5ade566c9751L,0xfcde62db64e3199bL } }, + /* 45 << 105 */ + { { 0xb068ec91aa63f5fcL,0x547e7e471a29ddfbL,0xe3e5de42b17b8e5dL, + 0xb5c84f27264d1361L,0xa68d10a426432715L,0x4f31e81c23e48e1dL }, + { 0xe32bea6116dbe185L,0xfaeab7256d1d34feL,0x0ee437cef3a8ca7bL, + 0x2b8657a2f458446bL,0x8779a3d4c52e3dcaL,0x243d7d0e71654165L } }, + /* 46 << 105 */ + { { 0xc4a346b2de23afe2L,0xf8e00f790fac7ba4L,0x22393604ab76b7d8L, + 0x109233d7a06efba8L,0x5bf89334c7bf56a4L,0x27ed4a28135d4cabL }, + { 0x07851ad2e32ca02fL,0x41b7ffa630c97f29L,0x383b3716e4457ccdL, + 0x6ce8645b0b43a50fL,0x73c82018fc5b907bL,0x79a1467381bbcf0dL } }, + /* 47 << 105 */ + { { 0xcf5331d35e092e41L,0x7e0b9fdeb43e3c15L,0x842a971182841f82L, + 0x2d837c810cb9d1ecL,0x6aff6d6873095ddeL,0x2a7f6f40c9478ef3L }, + { 0xb6e8ac80a9976e39L,0x3853fa5474e40024L,0x664b159a6d87c1d9L, + 0xaaedf4b4b20b5d11L,0x8a1ac277c5819de1L,0xf10276dc6450b97eL } }, + /* 48 << 105 */ + { { 0xa8d7901c7c16c09bL,0x628ff3be42e1948bL,0xb905d7c504e4bce1L, + 0xdfbf9c4e5ab0696fL,0x0f4e6e2ab6db9cd5L,0x4857e570482e40feL }, + { 0x5ccd9b421c3beed4L,0x171b085fae51a947L,0xcebe0dbe59065754L, + 0x4d052d3a461c1620L,0x396bac422fe541a7L,0x8e714cdb70bf32d8L } }, + /* 49 << 105 */ + { { 0xed82f15e6ca1cdcbL,0xc5ae5cde51b9a9cbL,0x3b2f78cec70c475eL, + 0x0f22d10b4243c675L,0x1db96885facac4c6L,0x2fb7884817df2f2cL }, + { 0x25fb9f4e990f3104L,0x1416733ecefa14f7L,0x3a33828384a5dc24L, + 0x6d75d3d02564288cL,0xf7bea8b69b93e62aL,0xa5ea8695349f1740L } }, + /* 50 << 105 */ + { { 0x38feea7115e711b8L,0x129aea564accd3eaL,0xc53e54c412b23539L, + 0xb15bf11a2b280c59L,0x5ea76f5782d44df5L,0xea79f833d4ac1af8L }, + { 0xe547deba08330c6dL,0xbaa89422663ef402L,0x17263762d215a5f5L, + 0xb9509a19c02b5f9eL,0x9bb99fcb025caaccL,0x43f4494b25f24089L } }, + /* 51 << 105 */ + { { 0xe55e592c98563c70L,0x4e62ace5d013c82aL,0xb6025ac16fcf7380L, + 0xac4a8157cfdff8b9L,0x1fa181344497acf6L,0xdcdf05c0ef09d3e9L }, + { 0x7a65490d83d8e716L,0x2aee0b35e98c46feL,0xe62381dc7d6d4035L, + 0xc7162b78203975c0L,0x1079d8b6aad2c021L,0xe3e1cb4370c98838L } }, + /* 52 << 105 */ + { { 0x3ca01799f04dd97aL,0xd6d1d41d3f9e03f3L,0xac2713eda55fa375L, + 0x2bd440556a89a5e5L,0x8582d98458f5c269L,0x7f9b3527fb31fc27L }, + { 0x23f91951d810580dL,0x99303919360a3debL,0xfaf10326b5e1eea8L, + 0xf96feb4838ba5ac8L,0x1508b1002a639622L,0x0766a1019dc93c78L } }, + /* 53 << 105 */ + { { 0x0c79d40679a0290cL,0xc09bca0c57eb7a00L,0xf7274ffc163c1dcdL, + 0xd64ec461bb2c83c4L,0xff3b83efe9ee350bL,0xa490157d01882c72L }, + { 0x626e1f3d3312310bL,0xd2097e03cdd5d62cL,0x705c3fcadbf659c5L, + 0x2dc1d7cc810fa413L,0x6313192ad67d58a8L,0x6e1e5bc3597f63a6L } }, + /* 54 << 105 */ + { { 0x6100535ea0d42639L,0xb126e939d921369dL,0x2d4c826e4999e42cL, + 0x159063c6f62f77e7L,0x063c42914e632555L,0x8d3ee387b35d8220L }, + { 0xbd951cff9b2bac3eL,0xd9b943f1bc248755L,0xeee7017ad3a6074cL, + 0xbcb9e0e6b0872a21L,0x26d80e0949dff656L,0x2ad7d4e335fbf620L } }, + /* 55 << 105 */ + { { 0x6ce5840df7f9503fL,0xb96f82996abf4f6bL,0xf71f33853ab55fcdL, + 0xe347e891e83a8109L,0x12c5dcdeeb48f0faL,0xb0f02553cd7183a9L }, + { 0xa7d74862c414f01fL,0xbea40c5cae369360L,0xbe9785e5022d5192L, + 0x1a3224a50d318251L,0x4d7200093fcbceebL,0x1fd71167c2976f6dL } }, + /* 56 << 105 */ + { { 0x03c88a8566d2ee47L,0xee8e5c34455ee428L,0xd90a3d393870d90eL, + 0x2fd78d14f2fdb976L,0x9472a6066a312a30L,0xea68e2283484af2fL }, + { 0x7cf25951ac9e5cf2L,0x024f07ee37a28e95L,0x5d479379e563a2bdL, + 0xe87b50a4b46e93d8L,0x9128fc11f137285cL,0xe46efdf77c67d7e6L } }, + /* 57 << 105 */ + { { 0x4050036c7cb0b9a1L,0x8560750c1161d7fdL,0x4d293a521b247ba9L, + 0x4b25e54c8f1b9d31L,0x91c89139c5baa0aaL,0xa2f75f9f2202b7e2L }, + { 0x6c0915dd4d2d1388L,0x575d90f703717fd7L,0xd90c059b03e0626dL, + 0x7004305ba4239e8cL,0x39fb4e2e989775e6L,0x20c31fc8d8a239c6L } }, + /* 58 << 105 */ + { { 0x4de318054ab51b84L,0x4a68443c6aa00707L,0x2c3637f05b317f3bL, + 0xb8ea6f87c0fc14a7L,0xcd0cb4fca2cc6af8L,0x6b5fc899317083fbL }, + { 0x1b8f160956e6dfa1L,0x698299ed92b77d20L,0xdb84ab7f14fc3fc1L, + 0x944666a35d5fe625L,0xe9a3448d7e064ab0L,0x53f62fa01abe1440L } }, + /* 59 << 105 */ + { { 0x04bc8a2bc8c676b8L,0x502a73144a577562L,0x494d01f11ff01f9dL, + 0xfe648df164d98f70L,0x80bed0d849719dd3L,0xb77a8f09c231e190L }, + { 0xc8aa8daecc011818L,0xf313be4f5918814eL,0xf28fcb74488b5bfeL, + 0x71e23b19b3345c98L,0x1cfb7c0596eba9beL,0xa88e73b941c61971L } }, + /* 60 << 105 */ + { { 0xdc7050459cfd4295L,0x1cc9648eedeea59eL,0x88f4af1c0e9ca92dL, + 0x45d0b53f69689317L,0xa122a6dd41c04186L,0x9df54c3a277fba1aL }, + { 0x1efc55a5017eb9ccL,0xb253f7b661d1ecd4L,0xd03f8ec6acfb7854L, + 0xf641e5f49f338dbaL,0x6b6a680a3a3addbcL,0xe80babb5b5cd058eL } }, + /* 61 << 105 */ + { { 0xb48da67307873319L,0x53309cdf3bf5db9bL,0x1bc510e64ee9dd11L, + 0xbb8e529a7388950aL,0xc9c0ce3c7f6e6175L,0xd75753f88a290784L }, + { 0xfebdd94ba80acc08L,0x942cdfebdc846b30L,0xbb64799f6ca7099fL, + 0x40f03362d1326fa8L,0x95b2d9db97b62e9eL,0x5ad9ce165301d9aaL } }, + /* 62 << 105 */ + { { 0xaa5fead9dfc59ef1L,0xc1348e98b2cc1e9aL,0x83dd617e77bda968L, + 0x0fdcc0837c8997dfL,0x9206ae234cc62b01L,0x88aec92f417678dfL }, + { 0x9d399af791fb8920L,0x399eebd13e8a22a0L,0x32f3bba735bebdf3L, + 0x354c1c5004c2f32aL,0xc2d6b5514052c926L,0x16a1f71f656a7eebL } }, + /* 63 << 105 */ + { { 0xd7a755bc14a8c57bL,0xa97b901341ebec55L,0x88b88459143a1a9bL, + 0x7aa178cc7e19e3e0L,0xb8359634635dfb65L,0x63fd26c7c169e28aL }, + { 0x89d9090d953272f5L,0x63e571196383845aL,0x0e26c0cf886a1f1fL, + 0xda56332db7057a29L,0x6b5d303f7a459c6fL,0x3c351b771bb704c3L } }, + /* 64 << 105 */ + { { 0xda2b0725bb296c27L,0x1f22ffa4d341171bL,0xc721e35a5b132756L, + 0xe5695e84fadb6907L,0xbc5a3bf4c283f546L,0x9182cb3edde128aeL }, + { 0x179c7fa66592e05eL,0x1e604790f38e8586L,0xaf7e83bea16bad55L, + 0x6f41231e9137ecd8L,0xac87543d8f30d1abL,0x630a9d87b1ee0ee8L } }, + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 112 */ + { { 0x359cbfa05e4f1914L,0x6992cd48d922176aL,0x2fd5e90f630cbcb5L, + 0x2b0f61306ddbf238L,0x5070970a3af753e6L,0x433d009441727016L }, + { 0x2eb15b3b9dca97e2L,0x3a7379cd00d96875L,0x0d4374aee930a75cL, + 0x3cd36046849e7727L,0x9ac3117e336a19ffL,0x2d1373c9433ddc04L } }, + /* 2 << 112 */ + { { 0x985dcb43e4362d67L,0xecb860c2a939bea4L,0x40597f3055fbf1d5L, + 0xb6d166bf43fcd98aL,0x5932570915ec99caL,0xe05ae3b9c5bdd370L }, + { 0xc18f78270c7b943bL,0x84bde9c64dd572ccL,0x5d50a89df478e56bL, + 0x242c2f4864d29053L,0xcda12c6161cf7e0eL,0xf8b6890eac8d1d40L } }, + /* 3 << 112 */ + { { 0x7a9a9dd7b6b11af8L,0xac4c50dd16a42f8fL,0x1550267b6726c324L, + 0x12cfb2fd7f841afbL,0xa41b19052f046430L,0x8f5f5373b7d786cbL }, + { 0x7b61b39c729e09fbL,0x07a5415f2626da4cL,0x65d6efb84a348905L, + 0xf377862cf2e864b9L,0x3c94000dab96cdb2L,0x2176321a8efef0f6L } }, + /* 4 << 112 */ + { { 0x8c558000c1c1bc68L,0x9e48a67a83fd6ca6L,0xacf0d75ceb7a35cbL, + 0x0fbdce4cf0a93110L,0x82b2d13a9cc50c85L,0x696fd259cef70d6fL }, + { 0x1cc9be2e457b88c2L,0x0d58b34b1f04c0bcL,0x52bd479f195a532bL, + 0x769fe6ca1ab3605cL,0xba6a63e48a24c1e0L,0x86dea46299da5d7aL } }, + /* 5 << 112 */ + { { 0xdf2a6cecd24790f3L,0x37bfbba7b87ca06dL,0x7c8a7e4c0de8a6aaL, + 0x5c806b94be7b8f5dL,0xccca1c714fda3e7eL,0x3c1cbaf9cff788e5L }, + { 0x17a081a9565d0464L,0xc4eb995713ed1b82L,0x0d7c90549e4cfac7L, + 0x6fb74c629d53a200L,0x65b9ed6d5f977a8bL,0xe2279cec0ba2e7c4L } }, + /* 6 << 112 */ + { { 0x8435e2962d4412dcL,0xa36cbfef972350d8L,0xe2fe6e6fece5cb15L, + 0x6f249b095336f7ffL,0x5801feb9908ee267L,0x7649a837fc8f217bL }, + { 0xfc1adc3ea0ebc808L,0x1ef06bec94f08075L,0x4afb5404cc1d9b72L, + 0x75cabd61a1f2c5a4L,0x2bd797e1cd08f195L,0x4f1b5cdecbea0f49L } }, + /* 7 << 112 */ + { { 0xe9759aa9e7aa87e2L,0x2d54a5fbe5909f55L,0xe49a59aa2c80bb61L, + 0xdb89e21230c9b328L,0xf42b9adb004ebffcL,0x4471b983479678e4L }, + { 0x0dde5b0e97709e2dL,0x2f35c653a12bdb85L,0x9f8d7a5cd8c8285cL, + 0xd7cde5971d156206L,0xdbe765d7a8e126bcL,0x2e645b6de3f4e60bL } }, + /* 8 << 112 */ + { { 0x509abccb65682820L,0xfbfa1d094ff86137L,0x1ae371bd640bc2f6L, + 0xa155c2978f546c68L,0x8858cadcc08b8cbfL,0xafac5b0a1d96948bL }, + { 0x919cb22682e25016L,0xd147df4ab064ffc3L,0x25dd0f1ab4abe560L, + 0xc6bbe6369cb75bd1L,0xbb367cf947a778e4L,0x5714aa4dbde524b3L } }, + /* 9 << 112 */ + { { 0xce3c8218e61b1439L,0x8be5a9cb67f79d28L,0xb1bd1386d5164b35L, + 0x0bc24d96b9adbac7L,0xbcee4f0ec7482414L,0xac15b5b66ca5d49dL }, + { 0x79caa999f20f9a50L,0x89bfd652a911308cL,0x972fe26d15245a7dL, + 0xd44d0f6e1d0d2939L,0x6749beaedd439057L,0x02627a6ad4b6f416L } }, + /* 10 << 112 */ + { { 0x7e882e8cb437b791L,0x9afde25afbe334cfL,0x60184381da52f9fbL, + 0x935d33a1001df73cL,0x38f303df080682e5L,0xd9cf2c1f4e9a29b2L }, + { 0x889d265e00d9208eL,0xfc1cc2221fd8e817L,0xdd14f1a2ec71428aL, + 0xe81cc4f9d9e973aaL,0x26a154963696468cL,0x0620fe6409d546acL } }, + /* 11 << 112 */ + { { 0x06ed3e64166be92fL,0xe1da6e27c51ea53eL,0x784f2514acb2b245L, + 0xc544e50f8e24077fL,0xad449938c5c01787L,0x5d9ef8d527d41dd7L }, + { 0x37114064e15d4a96L,0x7f0c92aa1dd45321L,0xc1f11d56b9c72ee5L, + 0x91f3b3f7a78e6d3aL,0x0cf440b0c9488cf7L,0x14d3defd93df403aL } }, + /* 12 << 112 */ + { { 0x3fa4ea0225aa1d44L,0x22c68e17f74a6a3aL,0x351bcb80f489e72dL, + 0xdabdf118be0268edL,0xa3bf9e1984d2cd16L,0x318506a2d67393a4L }, + { 0xb0c6b2d8615ed517L,0x42ac507c3dcba0f9L,0x60570dfb51235e30L, + 0xc677628dedb033e4L,0x0290c22766e61f76L,0x1d8450d09888943fL } }, + /* 13 << 112 */ + { { 0x1b8f5ed7155a3daeL,0xc9d2433aa46ed72bL,0xe99c7fe38ca361fbL, + 0x606b08c19626fe7bL,0xe6447257c0ea792aL,0x5839e2c62e1156f3L }, + { 0xb73135dd5eab6d41L,0x200f2e488ef63584L,0x4c73885ddda1c49eL, + 0x8d606a75b5428ee9L,0x2a73cc7aa62699dcL,0x484a58941c6c8de5L } }, + /* 14 << 112 */ + { { 0x2365b4150decae0cL,0x9c8567ece8583741L,0x35d6cfae6d8842a7L, + 0x4e6c98e6dd0db8e4L,0x584524e767b34d02L,0x786ea52f554c6117L }, + { 0x8952ce169320725fL,0x8eb7f91854c4c8f2L,0xdd34f77afc799251L, + 0x76b8c3173e05d37fL,0x664cbddcebb4d365L,0x31ba98b90dfa1a98L } }, + /* 15 << 112 */ + { { 0xf113a7bd651c186fL,0x417bd7373737a50aL,0xddb40d201b858249L, + 0x62a60745345f5b45L,0xf0a03f5c2d4e221eL,0xcafde67cc64621a2L }, + { 0xbbbfaebcbc3c06c3L,0xadaf9a16b8383dc0L,0xcd21aa308f343ea2L, + 0x64cefec0d890128dL,0x2ed9b8f763b44054L,0xc0a49e2917c0ffcfL } }, + /* 16 << 112 */ + { { 0xc6307399166915dfL,0xb35545bc5da8a26eL,0x8e0126aae3a99321L, + 0x0fbfdf76da9308d1L,0x2163ed6b6168e505L,0x71f3d0087500d8bdL }, + { 0xf57159605ac13f65L,0xc1cd9a6755172d5bL,0x6b225f7e53d84c65L, + 0x9c031269025029daL,0x54c1edfa17d89aedL,0x5b0238786b435150L } }, + /* 17 << 112 */ + { { 0x96d69db1146abf28L,0xc924454924d221dbL,0x7881951c137bdfe1L, + 0xde2d490dda51f789L,0x6033c2c34b0a1e0aL,0xbe214d8c08dac13eL }, + { 0x3d5abfa9a5a1d055L,0x3433060f6fe02a62L,0x88608c7ba37f2833L, + 0xfd2da6f0e74dd6c1L,0x27c22c17fe000000L,0x04a1f15bcfbde005L } }, + /* 18 << 112 */ + { { 0x01204485f340b522L,0x588a9e1c9367a099L,0xb3d1a4b466005913L, + 0x522ac504d55cc36fL,0xa6c80e511b72eabaL,0x15025a7acaaa89b5L }, + { 0xc9166912bec1a986L,0xe78e9642f19044cfL,0x230d51ab4756908aL, + 0x6795942aac04cb90L,0xcd2cc9eca2a92818L,0xfccead967cf52961L } }, + /* 19 << 112 */ + { { 0x32fa291d52ccf481L,0xbb137ef901ac0eafL,0x13ce2183011746abL, + 0x7e64248677bfea0aL,0x67cbba0e5e7e5032L,0xc900998a1f2b69fbL }, + { 0x62ddd91aab3256afL,0x1f0f216911d7996fL,0xab2f2d540e4dd4feL, + 0x05b577a92ec64ec3L,0x8071e88708ef233aL,0x9be1f8d60e649a5cL } }, + /* 20 << 112 */ + { { 0x5f78334137732664L,0x625b85dc840b6f8eL,0x7dcb3d256cdf0959L, + 0x87a5ae19d4ce1845L,0x43bf0721b0dc016aL,0x6569ad52f6a5f6f3L }, + { 0xa2697f15560ab87aL,0x4c6fd1a0060dcd57L,0x652a7732c3167f56L, + 0xe355fef05294a5e0L,0xf7b3177dcc59c562L,0x511c96dddccf4b1fL } }, + /* 21 << 112 */ + { { 0xec768f587622c0b9L,0x7c9eb5490416afe7L,0x3c3d87f55795433eL, + 0x74eff3cba4611446L,0xb2c79249dc7037d3L,0x70062ebd8bb1fc42L }, + { 0xbd0d3532a4ad91c8L,0x42411c139f5ee0c3L,0x11c4ee91132470cbL, + 0x496438979fb2a135L,0x4c1df7e0ce2ec891L,0x689cda57e16f7413L } }, + /* 22 << 112 */ + { { 0x3b42838a2a0030a1L,0x3f37587ae05ba56eL,0x6382a86f44c16650L, + 0x6c1bc67da6f9f136L,0x7d152d907ada0f41L,0x9115319d5c40c0f5L }, + { 0x1143028632f58e3aL,0x5dcf7ec7eda5c5a2L,0xf04404a9f334a0b2L, + 0x75e0b4a84ec2cbd5L,0x86e89728d079dbf0L,0x796700799a99c605L } }, + /* 23 << 112 */ + { { 0x98456a79b1d2a3fdL,0x4e8ba91e6dd789e9L,0x8e0bfa33a435226eL, + 0x42bea2f48cfea5ccL,0x5ca5fb0321b14602L,0x73faac5826877b13L }, + { 0x0ddb6ea203905ebbL,0x67bc35f1698cd7abL,0x24da47d85d9af735L, + 0x1a2a7c1dd786000eL,0xb35fb29e23ccaceaL,0x1c063466bf1f51a7L } }, + /* 24 << 112 */ + { { 0x1e7ae1601e94d949L,0x177dc53ee78e6221L,0x8af29d8f7aeb9882L, + 0x2d9a60fd9e3f3906L,0x6979fcd6df962156L,0xdd2fe5887e1e54b8L }, + { 0x9cccf31076643453L,0x94ece1a84e0643d0L,0x745449cbc111d8cfL, + 0x872afa4ae6cfbd97L,0x5c27b7ca10dfb34eL,0x505e62bc533480feL } }, + /* 25 << 112 */ + { { 0x6dd2007363141676L,0xdb099810c5c4c657L,0x2bbbcbaf8c369f32L, + 0x339e3ded08794178L,0xcc362a32315c4cd7L,0x5d288ff37dbce794L }, + { 0xafd05d104d0cb6c6L,0x3a6dcee9d386c7dfL,0xa207dc17e311ee74L, + 0xc5794286abdc751cL,0xf45136e5d889b985L,0xb25e84638d8f32a3L } }, + /* 26 << 112 */ + { { 0x8711ebfd1dc32f77L,0xfc0e851f3933d758L,0x90b679fd64a859f3L, + 0x0914a975ef37a81eL,0xcef80495d675c502L,0x862d3b65be18c403L }, + { 0x0d53f957305b4aa2L,0xe404f2570e5bcb47L,0x833a8644854b6b63L, + 0x5709f53b99f8d3d9L,0xc400dc1f13893effL,0x75ca01714c65086eL } }, + /* 27 << 112 */ + { { 0xdaaf8e76eeceb904L,0xbce9ca54b9e31f92L,0x4442d0c88d06a58fL, + 0x5966e1e5eda0ee34L,0x043125f058edc555L,0x44d0311749cf0931L }, + { 0x292aea12a99ae5c2L,0x1e9be1702a2bade4L,0x003ec2826b21b444L, + 0xc158f3cffc41d601L,0x25a839f4c4b3f4c7L,0x4a36bec399e64264L } }, + /* 28 << 112 */ + { { 0x829bbe7e04e6bda7L,0xc52b64ded3e667dbL,0x98aa40ecaa2fc128L, + 0x2c6997d011fbef94L,0x70ca76aa97c8167eL,0x558f8ce7b1083886L }, + { 0x5c621e35d250f064L,0x757710f8f535b2c7L,0x5d118d8faa69ee95L, + 0x02ffe667b27cd9deL,0x65711ac7d13e51fcL,0xdbbf16278cb1a1c7L } }, + /* 29 << 112 */ + { { 0x3c2fcbceeab0bb77L,0x569d6c7e4e1b17adL,0x22e06899b0518730L, + 0xf8466d9d19f809e9L,0x372e254288359d10L,0x8074483532d5bb82L }, + { 0xc88727d566060945L,0x08e9246572a0d38fL,0x84ca145c9f84a861L, + 0x8363463c1c004212L,0x9debab72bd3ad87eL,0xce68c150a988e65dL } }, + /* 30 << 112 */ + { { 0x1c172e5ea71dbae0L,0xf7794eb19b80bf40L,0x3007c5705d7d2829L, + 0xa8d44d6fcc97cf00L,0x093a9784f6abea6bL,0x2ac4a67564cca46fL }, + { 0x14fcc56350d8fc8bL,0x53133983a11ccd07L,0x7cf09bf68e6b8f26L, + 0x49f864d57b06e3adL,0xd526a765c373fc6dL,0x7af297c6151305d5L } }, + /* 31 << 112 */ + { { 0x18f941bfcf7c1eb5L,0xda10720a130163b7L,0x3c4894f46bd9bb34L, + 0x7575087bc8ca64f1L,0x68c424852c8f3798L,0x986214eecf0e5839L }, + { 0x3723b713df2b0b90L,0xd81560d5d229bf8aL,0x0204ae5ff993078eL, + 0x55206d9186a14833L,0x8c7d09181557fc96L,0xe2cd5dcdddba9705L } }, + /* 32 << 112 */ + { { 0x009ef80aae238fa1L,0xb41d9b24486af6b5L,0xab4455ed685add95L, + 0x18f323f672c7dac8L,0xe7009790e372f168L,0x4d5bcba6067bea99L }, + { 0xf15bdbcc51a2a9a9L,0xde7e4f742fac9169L,0x2fd62c304bdbec36L, + 0x8b3ea93d1b3ac6c7L,0xce1c8e5c9c293889L,0x19664dda11564f8bL } }, + /* 33 << 112 */ + { { 0x207a738245406afaL,0x7c1c398d1675bc91L,0x2ae99d8ba1bb7a43L, + 0x63f134e8c5e176e5L,0x4a624a1c48364268L,0x471974f1de65c5deL }, + { 0x44932063ea90b0cfL,0x13ba5019d8fd7e30L,0x6281f71348510422L, + 0xdaba3f14bc1a523aL,0x333e5eff924cc5cdL,0x861ab150e9113d1dL } }, + /* 34 << 112 */ + { { 0x332d308dd9b9461cL,0x3e9b4a95b7014261L,0xc557f608c2beeb5cL, + 0x9ee927187c8531d6L,0x55ff3dfcc0002ff0L,0xed96119eccd9b325L }, + { 0xd779ba03fb92416bL,0x63b75d351416be79L,0x793cb1fbfc9ad27fL, + 0xcc762a5b87f1bc59L,0x6e7a23389bbb07d8L,0x99b6e278aa7bfa44L } }, + /* 35 << 112 */ + { { 0xeb142de02bcce03eL,0xcac04711577565e2L,0xa949c7350ab07328L, + 0x8f15874cd7d347ebL,0xade8c67a696dc9f3L,0x039e6b7c66a7bcadL }, + { 0x1260bd4acb8cb9d2L,0xdbf05496d4801bcfL,0x6b37a4d30ffb845eL, + 0xc3968fe150b50889L,0x261e82f4525c6a7dL,0x539f634912aad50bL } }, + /* 36 << 112 */ + { { 0xcb1a9d2ceae4d774L,0xfdec2ca998a0775cL,0xa538acbd0eab9e25L, + 0x6901ebfd04dd34b0L,0x998ab679ed4c6409L,0x69b1d7ee0235b865L }, + { 0x4f2e6e5723ac3be6L,0x2b2072aed4a00479L,0x5c12fcdc2ce2f059L, + 0xfc688c45ac329db8L,0x16d377a51f539427L,0xebe4e2cfa08ed9aeL } }, + /* 37 << 112 */ + { { 0xb394214715d60238L,0x60d8909bbe9d4febL,0x013827b78654e16cL, + 0x465b3078824fc55aL,0x361e6523e3fcd6c0L,0x2ef44d80ef88b307L }, + { 0xdca7809fbeb2db77L,0xe649d591da97468aL,0xad6079b77c28ff0aL, + 0x6a21ce1ac4897775L,0xde876f7b5a592fd5L,0xced421a585a1dd36L } }, + /* 38 << 112 */ + { { 0x9793bdf6a045a442L,0xdb3c60472713ed37L,0x9929d32261344a0bL, + 0xfb48c2dc831af45cL,0x730226df53a8a077L,0x3a5baf8a18876559L }, + { 0x99736e7d8e11f9edL,0x3e7663dd0c09dddfL,0x368a29ed89b8a23dL, + 0x5443d7f5d3a68663L,0x0b84b464c6302455L,0x235c6eb5cf088847L } }, + /* 39 << 112 */ + { { 0x13307013b8de0a3aL,0xfb10e919f592fd9eL,0xd09e5b2571401ec7L, + 0x6e8091c11d94cf0aL,0xb7d79fc74193b129L,0xb842a3695f2c05e5L }, + { 0xcf6fc6cbccdc7614L,0x77d6408180102a3aL,0xde4b9304f30c3488L, + 0x4fd9f8d89bd08e48L,0x58ac01245963b063L,0x1f11335c747fac66L } }, + /* 40 << 112 */ + { { 0x5f266f13175418b2L,0x6bd7a86903a626f9L,0xc7b532304a6f11caL, + 0xa216b056bfc8ccedL,0xa274d5d8b288cb7cL,0x6fc4a35d924897adL }, + { 0x1ea532eb81fc6940L,0x2fcd817e2acbbc45L,0x45eee93f67814fa3L, + 0x3b3da48c1229e035L,0xd049a976efd8e3d7L,0x8087dff7bf81f314L } }, + /* 41 << 112 */ + { { 0x9ccd802fbddea807L,0x08a64e86d93b97f6L,0x422c0f5602f04e3cL, + 0x25aecab133900990L,0xcdb2c5c15d4b4d2fL,0x849a6b1f5f43e42eL }, + { 0x4689b815446e7361L,0x49abaf6ca681fba0L,0x304d84b18289a564L, + 0xa6529d430b779df3L,0xca926da67b51b195L,0x3640dde5c829ae84L } }, + /* 42 << 112 */ + { { 0x747235495424e1d0L,0x3861ae65c85af64fL,0xc56ff12baab902c2L, + 0x9aeb9e154fbf264eL,0x14e3c13942ca40d2L,0x6c26da41c1ba0250L }, + { 0x97a6031df51a0967L,0x88fea7710e623393L,0xcafae4c778574eefL, + 0x2c4c281198119f28L,0xd190fc749276d971L,0x843f4baf9273f01cL } }, + /* 43 << 112 */ + { { 0x1b2d643de50ad79dL,0x1ceaee7ed3075486L,0x13a003f3ec287aabL, + 0x09a4a825e8c7aeddL,0x93babe5ad1d4c05cL,0x8115bfec95ab084cL }, + { 0x629e8e0a289ebb8aL,0x923167a9bd992f77L,0x440edf75ae16ce72L, + 0xa67dd37b0a0019d4L,0x174b341978b0df8dL,0x010746a5ad6e4c60L } }, + /* 44 << 112 */ + { { 0xed05e4bf8342da4aL,0x36d881f3b565f0f2L,0x3fbd04e1411e627fL, + 0x40ac13cb0411889aL,0x9f6006cab5b25fd6L,0x0e79d377e31404ccL }, + { 0x9fd6474a5af3ea01L,0x89d7ddcb2a27d905L,0x2c1beebada12e71dL, + 0x3ecb11e1833eb7deL,0xa348b2f6600eb1faL,0xc227192183f2657fL } }, + /* 45 << 112 */ + { { 0x2cfaf519e32ba792L,0xa99113d7f929b512L,0xd347f7d18f554e19L, + 0x18f0374f098a2ad8L,0x073855acc174e0b9L,0xf155c6c009324c23L }, + { 0x3388c39605d1e427L,0x144356a9d39221d1L,0xe3d4ffed492a84adL, + 0x519c65e6d1e53c29L,0x334f470a2813c717L,0x69aa0a1de0a400e7L } }, + /* 46 << 112 */ + { { 0xd8689c9c39e70b62L,0x2b87157e6cd86fe6L,0x53d55de887c0f35dL, + 0xb2d7141de09aa44bL,0x3499553084fe7c21L,0x4550096c16b19be0L }, + { 0xb0a8ce05b856dac0L,0x570223450e211887L,0x8d4a7431aca17401L, + 0x96bf439857400a0eL,0x1e849d365ffd5f34L,0x7e70f6253a6d23acL } }, + /* 47 << 112 */ + { { 0x511ad0024b4ecd64L,0xd2287a28f37bf796L,0x801d2c2dcbc1f22dL, + 0xf0d3a6944df568c8L,0xa7fec550af6836b0L,0xa27dd6e887a426c7L }, + { 0x2f730e5b59c6b695L,0x9df438ee93ee2b36L,0xc4def9eaf2cfc4c6L, + 0x82ddcca0a209814bL,0xb2e1de4f6dc916d3L,0xc6798e7453f81a55L } }, + /* 48 << 112 */ + { { 0x77faac22bd366155L,0x13cc4038282f11b5L,0x31ad1dd45fbd35abL, + 0x7e0de9da45d6d40eL,0xa16c5f1939749ef6L,0x761cd6cf85691cf2L }, + { 0x156536ad4d59b802L,0xee98dc4187c4b11dL,0x165a1eacd35088fcL, + 0xce8a733538fb995cL,0x34d0d3313293b3a5L,0xfcf548ca8b570e79L } }, + /* 49 << 112 */ + { { 0x4c4bddca99e8cb05L,0x2b900ed017c5be91L,0x0ba0201b40adbfc1L, + 0xb5098cf8534595ecL,0x356e23ff80f56f69L,0x8b3fa12e748555a0L }, + { 0x9063437677b8ebdbL,0xe3eb33fdf040b6a8L,0xcc5b699539b611ceL, + 0x20171523c693be7eL,0x5c4364d760849cf0L,0x30f3376372c4d303L } }, + /* 50 << 112 */ + { { 0x0757295022a8c8e0L,0x6e05715866ca81ecL,0x7e8e36890f804bc9L, + 0xcba813a191b99207L,0x3f11f7abe50ab65fL,0xaefe5479b6d05954L }, + { 0x48dd59a1eff5cf18L,0xa623b738bda11ecdL,0x586e755818870f08L, + 0xb2c471a50e38ba1aL,0x5b21c42c69ce8032L,0xaf040e6c7943d78eL } }, + /* 51 << 112 */ + { { 0x6364714c4852f979L,0x7ed7aa310700cd35L,0x9021e46d9376733cL, + 0xf2b65ed3b6de8d03L,0x0e3d00c16652346cL,0x6630fcb75d27e2d0L }, + { 0x69cc20ded79a1c20L,0xa6d77163be3745e6L,0xab36946379aacf14L, + 0x8bdffbf1b935a1daL,0xda8eb343b63096f6L,0xf61988f13c966345L } }, + /* 52 << 112 */ + { { 0x06f684ffd31f390eL,0xa1467be560ec98a8L,0x7cbdd03eaa80fddeL, + 0x0ae4d114e204ded1L,0xb8ebeb29a004c3e2L,0xd93cd70726009581L }, + { 0x3ff2ee49f1b9d3ccL,0x0e69e5ac753526ccL,0x8cb2243e8b13f47bL, + 0xe2c5ae8d7fbfc5aeL,0x8e9af723394a45d8L,0x0b1114dbd92ab8d0L } }, + /* 53 << 112 */ + { { 0x937d9d2a73f9ff5bL,0x07c8c147de0fd740L,0x3880ead73639b680L, + 0x879d6f836558cc89L,0xf32e14b975bc8c84L,0x278ea5e4bcf6f8cdL }, + { 0xd9f25ea94baca6cbL,0x676e4bdd44d0ceb2L,0x98042ac190868974L, + 0xdf227f370711b658L,0xcd6d29b46ef0e4f8L,0xd04f5bf88f817e92L } }, + /* 54 << 112 */ + { { 0xc7d62be78354f4ffL,0xd6fd9d590ac4d9b6L,0x13fbed772b50ab82L, + 0xc4c5be374362b766L,0x5d67bfdd6c59d059L,0x10c93cceac02f34cL }, + { 0x3bec1f3b72e35ca4L,0xb1cfade159f4820bL,0x679edbcf80fae051L, + 0x6762f5ba6671737cL,0x28b425db3fe77970L,0x4bd6d2ebe778aaaeL } }, + /* 55 << 112 */ + { { 0xdcbe0018aecd5ae8L,0x7f178b7aedb2a7b0L,0xedb5c805b427179cL, + 0x25fb6a084ba080fbL,0xeb6365165f1b263dL,0x814c520092acb04aL }, + { 0x936f97a988d94b88L,0x6d54f1768b45e4b7L,0x6321e3bdb0cc515cL, + 0x9118d0318eb5be13L,0x5be9188a8c574e96L,0xcdad43f3f281f19dL } }, + /* 56 << 112 */ + { { 0x7be5946ea85af34aL,0x420593c9da6fb0e0L,0x40b83c00987f9246L, + 0xac35f4e9a15d192bL,0x1979bd33776a678cL,0x0a7d973e8f6068d3L }, + { 0x71d322e87e6298feL,0xbb23a29936af9b65L,0x14e2b9706644c50cL, + 0x5f7f207373570bd3L,0x40215c569055538bL,0x91372e64365500c9L } }, + /* 57 << 112 */ + { { 0x2763961a303ef488L,0xc357c32fbf865ec3L,0x32ca1a943663e409L, + 0x9d9040217de506a9L,0x1f56e144249028bcL,0xd76402e61c5c7cecL }, + { 0x98dcac65b0dd9d4fL,0x887f6e97532facf6L,0xc0d5d2a123c2cfbeL, + 0x0566bd59d18d8b1aL,0x67404eb1297a071eL,0x10f24d9b26529285L } }, + /* 58 << 112 */ + { { 0x34808f5ca479ef4eL,0x60effdea9ff10abfL,0x471a077cdae34e0eL, + 0xf34df9562f9d1408L,0x4f8bbffbe46961b7L,0x6a80b0276336a6f4L }, + { 0x28e57309ca92e5dbL,0x27fbb139ce31cb10L,0xcea87ae28d24334bL, + 0x3781f438de6db765L,0x3328fc09edaf054bL,0xa8acdbcfa94396f8L } }, + /* 59 << 112 */ + { { 0xa05b72aa83a79820L,0x3210863ccdeeaedcL,0x192d5fdcb76fdabbL, + 0x25ec4568f10c17a7L,0xbd51e31fca556920L,0x8ab534f26a7e40f7L }, + { 0x2ecb28c041145d5bL,0x4e95843df9038557L,0x65605d17d783699cL, + 0xf728cb1178bddf7aL,0x2d823ae8bee2a60cL,0x02030edb8eb48325L } }, + /* 60 << 112 */ + { { 0xfe517758aa04facfL,0xa5216df44c421615L,0x4d87767d4f133b52L, + 0xdae81b7699757264L,0x53c1a0e3e3ad4323L,0x2c565bbd53b401bcL }, + { 0x94d2354fcd54a0e1L,0xf43d0f053f1a02a7L,0x52e7ee4af660b949L, + 0x563ec009bc208df4L,0x58c0b975bf21c4b1L,0x29a8e5adeb029e52L } }, + /* 61 << 112 */ + { { 0x4c07b3e4283bdd75L,0xcd94d2a385dd6177L,0xc1ab8a5cab097530L, + 0x90301468a5fd9ff7L,0x2a3e5b4064d0932dL,0x77e3b67e435e1c0fL }, + { 0x3b5d261c14f7bb4dL,0x1d67a760bab7bfc9L,0x507aad46d799621bL, + 0xf44567b5f4f3c3b9L,0xfaa97a3eae2bb6b2L,0x7d373b163594e2c9L } }, + /* 62 << 112 */ + { { 0x29ef2da9a15e6ea0L,0xf411e20dcd168689L,0x34944975049a4b24L, + 0x0effc2dfe035cd24L,0x5d77178b0a954cf7L,0x3504bc357ab2d8c0L }, + { 0xc3405000ec32219cL,0x00442630421a5a3cL,0x0548505c7f49819aL, + 0x6bdb281fc805d0e8L,0x03cb57ac97484e09L,0xcf0926da58a14cc1L } }, + /* 63 << 112 */ + { { 0x0715055cc85610a7L,0xd2642935fa6ca505L,0x87ef95128c361749L, + 0x89cd669a8c8156d2L,0x5cdcd266ed60d7ceL,0x99ccc96df59fb53fL }, + { 0x82400f4655df7f73L,0x2b6aa1d9af34f742L,0xa6cbca79c398aa8eL, + 0x7697bdea02b7325eL,0x1cb036b94fde4a79L,0xfe11ff96307fb964L } }, + /* 64 << 112 */ + { { 0x6a3a23279af0a75cL,0xf832a8159f1f250dL,0x17030c3322a82d3fL, + 0x24bf18ea14cbc835L,0x319dc4cab2da2727L,0x481df3606d020d4aL }, + { 0xaeebdd8a7fc22ba5L,0xbd0515c6a91e28abL,0xfc8a2978595f361dL, + 0xe60dd96c1ae8fa3cL,0x19c2109aa5341575L,0xfd6e92bb06a0ee48L } }, + /* 0 << 119 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 119 */ + { { 0x2e32f896cde5e785L,0xcd55ae7ab9db8f31L,0x278db1ad8f832885L, + 0x271d9078adcbd933L,0x2208fae34a64f863L,0x974046e039c89365L }, + { 0xcb46f272b3cd0cd3L,0x31f34e1a74e59edcL,0x3421d316edd50418L, + 0xb1d8a064cabe36edL,0xdb13e560362efcdaL,0x567c2b6cc71eb3eeL } }, + /* 2 << 119 */ + { { 0x2af8ed8170d4d7bcL,0xabc3e15fb632435cL,0x4c0e726f78219356L, + 0x8c1962a1b87254c4L,0x30796a71c9e7691aL,0xd453ef19a75a12eeL }, + { 0x535f42c213ae4964L,0x86831c3c0da9586aL,0xb7f1ef35e39a7a58L, + 0xa2789ae2d459b91aL,0xeadbca7f02fd429dL,0x94f215d465290f57L } }, + /* 3 << 119 */ + { { 0x94c3938b4c9324feL,0x0dea07003fe78a0eL,0x57ab9daa019e7dc6L, + 0xb0d7b14a9925b79fL,0x3c9a638b937a5daaL,0x3b14fd0de62943adL }, + { 0xbaafb635ed3ae4b5L,0x3060a090b2bcfaa2L,0x389d9e7f7aa8f217L, + 0xd7f987c6e9310a65L,0xec0927f993b69c0aL,0x9335e9102381a247L } }, + /* 4 << 119 */ + { { 0xc08550024b950889L,0xee99dbfe8ce24da0L,0xdda71d964318e860L, + 0x01d3d39604fe9b85L,0xda4bc065e25e7e20L,0xd3a50b87e076c81cL }, + { 0x5b9f821931e5f494L,0x6a140527a6a1b821L,0xf52683e4d8dd159bL, + 0xca9c888720b18043L,0x73c040fa08a0d8f5L,0x92e482e8179525c4L } }, + /* 5 << 119 */ + { { 0x8b9f650f3e776590L,0x41ba807f47703a5dL,0x8cc1a550fe907078L, + 0xd70cb76c8f00b84bL,0xcaee21566f3e6780L,0xfd6a51f595c2d03eL }, + { 0x2c897c5556ffa08fL,0x08589a6563d13d54L,0x6a1eed4287bbacf7L, + 0x66aed4f5ee709d78L,0x67c925bf1178ecabL,0x6870f4c8a29cf747L } }, + /* 6 << 119 */ + { { 0x37ed2be51cfb79acL,0x801946f3e7af84c3L,0xb061ad8ae77c2f00L, + 0xe87e1a9a44de16a8L,0xdf4f57c87ee490ffL,0x4e793b49005993edL }, + { 0xe1036387bccb593fL,0xf174941195e09b80L,0x59cb20d15ab42f91L, + 0xa738a18dac0ff033L,0xda501a2e2ac1e7f4L,0x1b67eda084d8a6e0L } }, + /* 7 << 119 */ + { { 0xe3a67b2d5e12e708L,0x3a4772e2ce48f234L,0x78f9dbc334794271L, + 0x9880053a3e6a61e7L,0x031c30b87c0f6e59L,0x8113df6cf7b972f8L }, + { 0x3625bdce18ee148cL,0x72c2b8efdb885158L,0x4c73c80c9a7f0df3L, + 0xbc2dd8a507b92470L,0x5a33e4dfdb005677L,0xc699cf5ea5ca9dd3L } }, + /* 8 << 119 */ + { { 0x3a828904a4d2313eL,0xbf4946b192e66888L,0xc574898ae5fa19d2L, + 0x0b13dbb65e1c5fa4L,0xf11343ba7c390fc2L,0x35b1418fd7d32187L }, + { 0xc92cb1bb83e7fe7bL,0x0b969455d78365c4L,0xda69dfe5672f2af7L, + 0x9c62d7b430932441L,0x165672ad94af02d6L,0xd2cc734dcde81c22L } }, + /* 9 << 119 */ + { { 0x6353420218d07dd6L,0xc7c0c8f128a3cb4eL,0xa41d4c55d7929131L, + 0xf1aaab3445d21f63L,0xd69a59545ec3e9feL,0x209732c1b8ddea2fL }, + { 0x368b9c59e1936916L,0xb011c662ab1f8585L,0xcce30a25474e57b4L, + 0xb79c76df7049c61dL,0x984739950ccf165bL,0x7c6f4ab40ce897baL } }, + /* 10 << 119 */ + { { 0x1d27efce1080e90bL,0xa28152463fd01dc6L,0x99a3fb83caa26d18L, + 0xd27e6133b82babbeL,0x61030dfdd783dd60L,0x295a291373c78cb8L }, + { 0x8707a2cf68be6a92L,0xc9c2fb98eeb3474aL,0x7c3fd412a2b176b8L, + 0xd5b52e2fc7202101L,0x24a63030f0a6d536L,0x05842de304648ec0L } }, + /* 11 << 119 */ + { { 0x907d88035a8432bdL,0x89232a5a2638fe30L,0xa120eecbe2089014L, + 0x3a5208cb5a2c9e97L,0xe163d29a3449eb4eL,0x3df984530eaba88fL }, + { 0x55d3b9afa1547443L,0x316aae18f2a60ceeL,0x64d0fd30d6e11a5aL, + 0x65de345808ef6002L,0xcede56fab4a3d1deL,0xa5bfa8d9a4bc1588L } }, + /* 12 << 119 */ + { { 0xd45e350133f4d416L,0xbb40233a4bf9131eL,0x1532a088e302483aL, + 0x3475e8b82c2485c0L,0x08f9ea56969cdbe6L,0x31928645253cd738L }, + { 0x1cf323a4ac9836beL,0xdf647ccf02b6e4deL,0x9a31e84fc06f3d09L, + 0xd326b86e39efe6d9L,0x77e3e1df14ac4decL,0xf2d5917af3e0c582L } }, + /* 13 << 119 */ + { { 0xf88238f1376216b2L,0x8c7522db7d15f653L,0x50aa7a74a21f74d8L, + 0xf7a964c8bc9e1a0cL,0x33ea64251387ca6bL,0xda84fe74e7be16a6L }, + { 0xdf0462d727867aaaL,0xeb7f0ab8ae6be1b3L,0x21abe5a5d9bdec8bL, + 0xdbb99199ac4bed1bL,0xf65c19d935d13c0dL,0xf966e22e4df74056L } }, + /* 14 << 119 */ + { { 0x67477cdc30577ac9L,0x51dd9775244f92a8L,0x31fd60b9917eec66L, + 0xacd95bd4d66c5c1dL,0x2e0551f3bf9508baL,0x121168e1688cb243L }, + { 0x8c0397404540d230L,0xc4ed3cf6009ecdf9L,0x191825e144db62afL, + 0x3ee8acabc4a030daL,0x8ab154a894081504L,0x1fe09e4b486c9cd0L } }, + /* 15 << 119 */ + { { 0x7b4e65ebae4219adL,0x2e424c441184a0d3L,0x10eeb898d32e179bL, + 0xadf05e2d8afa9a6dL,0xecd6c18bbeccd5f1L,0xe592115c39ac53e8L }, + { 0x9ccf231ac8c7b9b6L,0x1848b4fe678774bcL,0x2050856386782b91L, + 0xb7caf7cc74dc6018L,0xe80805485cf9273aL,0x9609897b246b4851L } }, + /* 16 << 119 */ + { { 0xe92b56c002cf37fdL,0xa75bbcb0f71b34deL,0x7754d0ef50f5c482L, + 0x850a9ef611fa89feL,0x97d74b1bba4ea7d8L,0xfc757c25aab7ba2eL }, + { 0x06f30ab0f2a67fddL,0xb10aba1412e72af8L,0x47580bca7a2e053dL, + 0x85795598dcf0e14cL,0xc3596781d6f55310L,0x8ab251b74c9b7e18L } }, + /* 17 << 119 */ + { { 0xdc56cff85279e5cfL,0xa33a6765fdbdf1adL,0xc122c0eee5077a4bL, + 0x44c3b190a98ab643L,0x334a6868b991d197L,0x598bbf185d6a0488L }, + { 0xd028bfdc5a0e6f96L,0xfd1a37f5e11c57b6L,0xe1240a3003f82183L, + 0x6afae98c390d8536L,0x554a42dcc244b181L,0xa3d422d75f4cb4b6L } }, + /* 18 << 119 */ + { { 0x512f82f9d113450bL,0x5878c9012dbc9197L,0xdb87412be13f355bL, + 0x0a0a4a9b935b8a5eL,0x818587bdf25a5351L,0xe807931031e3d9c7L }, + { 0x8b1d47c7611bc1b1L,0x51722b5872a823f2L,0x6f97ee8a53b36b3eL, + 0x6e085aac946dd453L,0x2ec5057de65e6533L,0xf82d9d714bb18801L } }, + /* 19 << 119 */ + { { 0xf113abe17d48bfe7L,0x51d77fa5213facecL,0x27bb373f21269089L, + 0x31e9850e7b188989L,0xd20a15f41d50a1c6L,0xb4887ed9d9746367L }, + { 0x8920a7e2325f19c5L,0x691352358ad74492L,0x713d1471d19a76a2L, + 0x952cb9e5873ab310L,0x5b359d1ffa8eb8cfL,0x55aab5ad8b9c9e7cL } }, + /* 20 << 119 */ + { { 0x4ab138504dbb8798L,0x0e7980d772d04cd2L,0x1755c5660b3271c6L, + 0x8414efb09d9d1468L,0x61a586301795ce66L,0xb6a8b393232924a1L }, + { 0xa992f0ceae031bd6L,0x6747fb5f2915acc1L,0x03daa26693e9c0d2L, + 0xc18fa3645400d554L,0xaf04ff8d9497e895L,0x86c3cfc250b6b339L } }, + /* 21 << 119 */ + { { 0xdf26f6605b26122cL,0xeb6c188c4d6b80ccL,0xae2efe59ccec172bL, + 0x5cdcd958f3f7d693L,0xa2ac2594c5f993f0L,0xb96ad8cf3f7cb591L }, + { 0x7e2f88f8446abbabL,0x3d1a5eb6f6051f2bL,0x7d882e82ad6f49daL, + 0xe32918e3c4e7bbffL,0x442a32789be81150L,0xa1d34da1bd14557eL } }, + /* 22 << 119 */ + { { 0xad81fa938ba5aa8eL,0x723e628e8f7aa69eL,0x0ba7c2deef35937cL, + 0x83a43ec56decfb40L,0xf520f849e60c4f2dL,0x8260e8ae457e3b5eL }, + { 0x7ce874f0bf1d9ed7L,0x5fde35537f1a5466L,0x5a63777c0c162dbbL, + 0x0fd04f8cdad87289L,0xca2d9e0e640761d5L,0x4615cff838501adbL } }, + /* 23 << 119 */ + { { 0x60c7e16cdf66a95cL,0x25b1078d5d0bd644L,0x77f8d872bd933e31L, + 0x5c4c382de2e1536cL,0x5b3b37c09295ee0dL,0xf94698d4ecce42b6L }, + { 0x947ef80c4db8f2c7L,0x34661f7dc70dd82fL,0x17b288a7f2311006L, + 0x1f1171a66815e1caL,0x0f71f66ce80d6235L,0x858c665a87fa5a59L } }, + /* 24 << 119 */ + { { 0x376b2a7f04e1e6e3L,0xea0dcb70a31774b4L,0xfc7fe4cc5cbdec2eL, + 0x8568499df03f459eL,0xe9fd8fb28b78900eL,0xd33c6e30e431bf97L }, + { 0xd904b8f5c896e766L,0xa8f577cf82748cefL,0x93dd921b87e044b3L, + 0x23d79837f76eebe9L,0x5e0a7493e569feebL,0xd0797549414dddb6L } }, + /* 25 << 119 */ + { { 0x9bf04f567781556aL,0x30be1e8953ebf7c6L,0x6f4899cf713fe432L, + 0x4f641fb7c9ef741fL,0x03560819002cc010L,0xfa51f8f7b4bbd339L }, + { 0xe09c5ef77f1dea5cL,0x39cb20d97255fec5L,0x407746862ea38859L, + 0x68ca598ecd7a29f3L,0xb8025dd67a9db4d9L,0x4feaeeaed9dfe491L } }, + /* 26 << 119 */ + { { 0x9422789b110b4a25L,0x5c26779f70ad8cc1L,0x4ee6a748ec4f1e14L, + 0xfb584a0d5c7ab5e0L,0xed1dcb0bfb21ee66L,0xdbed1f0011c6863cL }, + { 0xd2969269b1b1d187L,0xf7d0c3f2afe964e6L,0xe05ee93f12bb865eL, + 0x1afb7beeed79118eL,0x220af1380f0fe453L,0x1463aa1a52782ab9L } }, + /* 27 << 119 */ + { { 0x8cf42aa26b99ca6aL,0x696850242f091dbaL,0x9d887e6ad7d3270aL, + 0x627754fd5c9b735eL,0x3b8735a811d95df6L,0x74debd8b52443251L }, + { 0x1f8dd5b66181583eL,0xbd0ca92c8b570a9cL,0xc373a61a71ae3274L, + 0xf4b2c88d1c4c16cdL,0xd3e6ec3baf33efabL,0x8c54d2721bf6f0d0L } }, + /* 28 << 119 */ + { { 0xfd9e3542bfe5b1a7L,0xb42d2a4175938ceaL,0x74688a153befb760L, + 0x8daeeaa22e33dbe7L,0xc9c1ea083e677801L,0x68ecf4e434effe1eL }, + { 0x927700ccd294c321L,0x9e2e723de940afc5L,0xbcfac07a7cf6cd43L, + 0xa009ef94d1006bc3L,0xa02016b0373d13e3L,0x4e097adbabae5822L } }, + /* 29 << 119 */ + { { 0x7535175d48752720L,0xf51086ee850bdf07L,0xce322c33cb4c3f4dL, + 0xd863f7edb28965fbL,0xfe46a4e9885e4afaL,0x58b5c871136d7ddaL }, + { 0x126eddaf6ed07824L,0x084ce962844fcbb8L,0x9ac0787157dfb4c5L, + 0x97451fcc4d6b5910L,0x9f14b1ce0843c9c6L,0xf737f6c0a0e18596L } }, + /* 30 << 119 */ + { { 0x7c139d56d7dbe5f9L,0xfc16e6110b83685bL,0xfa723c029018463cL, + 0xc472458c840bf5d7L,0x4d8093590af07591L,0x418d88303308dfd9L }, + { 0x9b381e040c365ae3L,0x3780bf33f8190fd1L,0x45397418dd03e854L, + 0xa95d030f4e51e491L,0x87c8c686e3286ceaL,0x01c773bf900b5f83L } }, + /* 31 << 119 */ + { { 0x0028dcae855a0b90L,0x74c1e36026f0d718L,0x34f80e3ca059f144L, + 0x85b5d8e3f2bfe1b4L,0xe124601f453de099L,0x8b164ad6221b3efdL }, + { 0x636f45ebbe004ab0L,0xa23093e99f231a8aL,0x48e05e8e2287b992L, + 0xefec5e5b4477cb8bL,0x45a65afa8ba0231bL,0x92d38bd88b1af6baL } }, + /* 32 << 119 */ + { { 0x8db8b78cc898b8bcL,0x686896da502940cdL,0x67e50f022dde2e3cL, + 0x2e2461f38cbf406cL,0x32182781e1f7ff60L,0x26934b05e30e2688L }, + { 0x95adc204fc4494f6L,0x4c7f30c5161b7499L,0xd5caf060b7341737L, + 0xed93187fd128d46cL,0x3f2819cb20fc1e04L,0x48c4086f2b7f70a1L } }, + /* 33 << 119 */ + { { 0x45693c00a92ca9faL,0x046b218d63bd525dL,0x40f1d6cc6b1d6a68L, + 0xfc5807c5c54dc1f0L,0x2875d4d98b5690f6L,0x7a753543d0f72a83L }, + { 0x01f2c35ae28b5309L,0x38fb5f121bcef323L,0xd6ea6896256a9bffL, + 0x4380fb2c44d65badL,0xb587d641c3556fb6L,0x74c5ec1905167f32L } }, + /* 34 << 119 */ + { { 0xdabe347578673b02L,0x4f0f25cef6e7395eL,0x3117abb9d181ad45L, + 0x4b559f88aa13de0bL,0xfd8efe78ea7c9745L,0x080600475dd21682L }, + { 0xc0f5de4bd4c86ffcL,0x4bb14b1ef21ab6a2L,0xacb53a6cf50c1d12L, + 0x46aac4505cc9162eL,0x049c51e02de240b6L,0xbb2dc016e383c3b0L } }, + /* 35 << 119 */ + { { 0xa1e3cb2255b7f121L,0xc9183b13dd01db7dL,0xfe26aa801469dae6L, + 0x7318df7fd9ecfe2bL,0xade0a24d56dd4acfL,0x6e521c2222d1ba14L }, + { 0xa039800a40afa1deL,0x9c7da49d5c6af72aL,0xf7ae921cd3fcc7c6L, + 0x76af2407dcab63e2L,0xdc1618dbb6dd49ceL,0xebc65c4d362cc88bL } }, + /* 36 << 119 */ + { { 0xd847939132202bd3L,0x1dacde87d6631ac1L,0x99d2e71f905a94f4L, + 0xd3c21f5a7e67dd7fL,0x3605c28e3c43cf23L,0xb6cd5ac74d3b3070L }, + { 0x8bf748ba246298d7L,0x9e939fbd0f053664L,0x3bb3e7b8cc303783L, + 0x359bd3e56189c417L,0x299d0ce1f609ae34L,0xd7221cc7b9ca801dL } }, + /* 37 << 119 */ + { { 0xb7c823506b73c5a6L,0x7fea0d95fefee640L,0x6d5dd775f68b6be6L, + 0x4a5576147cbfa333L,0x6cad79c2fcd9b17dL,0x49aec3d405c4dd35L }, + { 0x3b1f3754c3792470L,0x351ef2ccbe00cffcL,0x44a248916a71f45eL, + 0x1e7a6013b8640d08L,0xf0f476154efcd556L,0xc82171444fe15dd3L } }, + /* 38 << 119 */ + { { 0xa3c56ad28e438c92L,0x7c43f98fb2ceaf1aL,0x397c44f7e2150778L, + 0x48d17ab771a24131L,0xcc5138631e2acda9L,0x2c76a55ef0c9bac9L }, + { 0x4d74cdce7ea4bb7bL,0x834bd5bfb1b3c2baL,0x46e2911eccc310a4L, + 0xd3de84aa0fc1bf13L,0x27f2892f80a03ad3L,0x85b476203bd2f08bL } }, + /* 39 << 119 */ + { { 0x85f9b301218642acL,0xb3f3b36f8728ef66L,0x4a833bea2ebb8181L, + 0x7d3bca9d8541a662L,0xd3be6d0ac5a0ecffL,0xaf52a2a9528da950L }, + { 0x4b431910131f72caL,0xe2708d36933d5550L,0x195340a469abf146L, + 0x84ca66e4e4e2e131L,0xd9402ca7e16c39bfL,0x5beedce343ca6041L } }, + /* 40 << 119 */ + { { 0x87c5915395523a22L,0x56686f525ac5146eL,0x9ec69ec718ccf766L, + 0x13f36d4ff6e21a4aL,0xa0841e94098691f4L,0xbd9d52d2bd91dd2eL }, + { 0xa8765981b3fa43eaL,0xb0cd17cd600b9761L,0x02dd9d71b5abe842L, + 0x63df33a63689a53bL,0xab4b85bb9d9baad7L,0xce2d31c1eb74e549L } }, + /* 41 << 119 */ + { { 0x8d69a654f2472426L,0x91a4b6a3ff7aeff0L,0x51dd8e76fdcc7cb4L, + 0x5f7d42a273731cd7L,0xc127401aa99c9d9aL,0x8ede9330c92561d7L }, + { 0x86057a56784c3cf2L,0x8afcf32cb5a7755eL,0xa0a5b561c71cd3d9L, + 0x0a5d805e36d3f5a4L,0x25a39acd7432a384L,0xd574a6b7b226e9ecL } }, + /* 42 << 119 */ + { { 0xab1cb818567af533L,0x273b4537bac2705aL,0x133066c422c84ab6L, + 0xc3590de64830bfc1L,0xea2978695e4742d0L,0xf6d8c6944f3164c0L }, + { 0x09e85f3dc1249588L,0x6c2bb05d4ec64df7L,0xd267115e8b78000fL, + 0x07c5d7aec7e4a316L,0xcb1187ba4619e5bdL,0x57b1d4efa43f7eeeL } }, + /* 43 << 119 */ + { { 0x886e3f30b29f5916L,0xa419d2c6625f29a0L,0xb4f89fc49bf07dc4L, + 0x86c137a1a165ed88L,0x6fa241a9e5d6280dL,0x08be9b0cd11576f2L }, + { 0x5735aeb7e376b03dL,0xf4639e6d182ce9b9L,0xb6948499cc688f57L, + 0xfde146636552009eL,0x3eeeae350a2e8553L,0x50447f1b659dfe2eL } }, + /* 44 << 119 */ + { { 0xefccd67ed15c33c0L,0x33393846146d5e96L,0x015e97da9ca7354eL, + 0x729b69bac143e795L,0xd4440ecfd4c5d0e2L,0x78c042bb697a80e7L }, + { 0x9361ad1d08602f75L,0xaa354166af489794L,0xe60e5a274966d3cdL, + 0x8346995e2394f9f3L,0x2de33256590f6a15L,0xb14427bb43298ac1L } }, + /* 45 << 119 */ + { { 0x38fee83a74680d2cL,0xd8019e5c0e700c8dL,0xcfaf5614475da1b8L, + 0x11893fc58f0159e3L,0x4c101127553813c2L,0xd273055208f82a6aL }, + { 0x8728834c74a3ce9aL,0x66b939a891906488L,0x42ac7c07b88d36bcL, + 0x663d7411d989bb72L,0x650e5d6eb284c066L,0x052b7f6710d8f124L } }, + /* 46 << 119 */ + { { 0x3618891fc8176a96L,0x62c4b084e5808b97L,0xde5585464dd95d6eL, + 0x27a8133e730b2ea4L,0xe07ceec36af318a0L,0x0acc1286ce24fd2cL }, + { 0x8a48fe4add4d307cL,0x71a9ba9c18cde0daL,0x655e2b66d5d79747L, + 0x409fe856a79aedc7L,0xc5a9f244d287e5cfL,0xcce103844e82ec39L } }, + /* 47 << 119 */ + { { 0x2a8cb0a56ad833c5L,0xe8fab8b844962dd6L,0x31166fd63ee1dfefL, + 0x3aba85a1e1230449L,0xf9f8da66bd1f502eL,0xe4a72d82e3c17ccaL }, + { 0xfa3d661d6070d587L,0x51d10b73c33ed08aL,0x3b0f515cb29f2d0bL, + 0xd82a11d7e1986e91L,0xcf24f81a2201f05bL,0xa94ec1e0d25f8417L } }, + /* 48 << 119 */ + { { 0xc7807daa081ed51dL,0xb7dfabf0e5d2d963L,0x3f78ae2e80d386d0L, + 0xd66275254bbfd04bL,0x238c8eb76d074f92L,0xfe51ec8a5bc5f9b5L }, + { 0x6ba47430cc03177bL,0xe72efda6400b29e0L,0xb905701becbffe88L, + 0x5c61bdb47cf89933L,0xf1eb3084c914aa6aL,0xa3ead71e8245998bL } }, + /* 49 << 119 */ + { { 0xc58ee3013c7eb5a9L,0x02c177220a1172baL,0x8620118394c7c5b3L, + 0x66292bc4e1668debL,0xf51b48f4caf39937L,0x9cca60f43eaea578L }, + { 0xf8e8004a5c2adccaL,0xce7ceeb1ebf49ac7L,0x36346357371d1c54L, + 0x8799e408d99ff07dL,0x3226181d8c3b2cbfL,0x3b4ff42ba437c2c6L } }, + /* 50 << 119 */ + { { 0x00675ba7f25d364cL,0x7a7f162968d36bdfL,0x35ec468aa9e23f29L, + 0xf797ac502d926e6cL,0x639ba4534b4f4376L,0xd71b430f51ff9519L }, + { 0xb8c439ec2cf5635cL,0x0ce4c8d181980393L,0x4c5362a964123b15L, + 0x6e0421e0ffdcf096L,0x624a855f10d1f914L,0x7d8f3ab7614dcd29L } }, + /* 51 << 119 */ + { { 0x235ba8b565868390L,0x853c9346ea936e81L,0x967ff132700bb25aL, + 0xb26d9778561a136cL,0x8b775c4fe3f7e41dL,0xae8f6b2ebd390b2cL }, + { 0x80959adc4fc7224dL,0xd9c913c12eaccf8cL,0xa9a278c79e96f769L, + 0xbc6be3038f26856dL,0xb039caf295d04cdeL,0x42ba0510a91bf5dcL } }, + /* 52 << 119 */ + { { 0x77870665cfbe0653L,0xab84c4b3523d814dL,0x72839d8897cd2bc0L, + 0xb966e521d25b1476L,0x4255d18451fd86a0L,0xadaf9b76dd54be7aL }, + { 0xada6ff627f285e0bL,0xb76e26f46d42400bL,0x1d9fe676958bee25L, + 0xfcd7be9edb59965cL,0x897a90834bcf6e75L,0x64b26f02aabd21e8L } }, + /* 53 << 119 */ + { { 0xee46626beb1a8ce6L,0x2de20371b672fc49L,0xa0fb11b8bd2d9256L, + 0x5b49f70ac2a8dcd4L,0x98935fc9e5dc0ee3L,0xaddbae423bc00993L }, + { 0xbd0bd9e19207f0e9L,0xe86c5365b393bcdcL,0x32184c832d0a9282L, + 0x8fe996d1df34532eL,0x3b33f151c6f45172L,0xd9def9a7b84545e4L } }, + /* 54 << 119 */ + { { 0xd9219adab3493ce0L,0x971b243a52f09ae5L,0xc16c9bf8e24e3674L, + 0x026d408dce68c7cdL,0xf9b33dd9358209e3L,0x02d0595df3b2a206L }, + { 0xbf99427160d15640L,0x6da7a04e15b5466aL,0x03aa4ed81cadb50dL, + 0x1548f029129a4253L,0x41741f7eb842865aL,0x859fe0a4a3f88c98L } }, + /* 55 << 119 */ + { { 0x66bb66f5f56b17ccL,0xdce0bf2cba8958f8L,0xd814318f9ff85781L, + 0x41dce823edd1ad96L,0x71bb754bb59c6580L,0x9c5efb70de594c3bL }, + { 0xf7b4ce5eb0053788L,0x9c26b0342770b6deL,0xe6967b1c8d131e8fL, + 0xfda0efdccf21bf28L,0x2366d47e09cbeeacL,0x62e9ee556629680eL } }, + /* 56 << 119 */ + { { 0xdaff980ff8e06359L,0xb4e0c9e2ead8a883L,0xe3e262023da6e94fL, + 0x37410ed03303c9d6L,0xc044d77b91fb5d82L,0x3559d9ac9ea34d26L }, + { 0xf51a120be21beda5L,0xdd2eef8a3f7befa4L,0x46a26ccd8c79fca1L, + 0x3fb21a682a046572L,0x3624a47adad7c7c9L,0xb9b77ffd4b4174f5L } }, + /* 57 << 119 */ + { { 0xae19a097c9f8c462L,0x477be49917a9d8a9L,0x4a0c41c9d2154c45L, + 0x39313aba1b0d985bL,0x3a70f65cc051b643L,0x0725dabf2d0be160L }, + { 0x29eefc94a69867d4L,0x6acc4cd49d02bce2L,0x0606ab725d4dca50L, + 0xcce81133bfecdcbaL,0x604df3def23b2239L,0xa644b430d20a7529L } }, + /* 58 << 119 */ + { { 0x80de085a05fd7553L,0x4a4ab91eb897566bL,0x33bcd4752f1c173fL, + 0x4e238896c100c013L,0x1c88500dd614b34bL,0x0401c5f6c3ba9e23L }, + { 0x8e8003c4d0af0de5L,0x19b1dfb59d0dcbb9L,0x4a3640a9ebef7ab6L, + 0xedafd65b959b15f6L,0x8092ef7f7fb95821L,0xab8dd52ece2e45d1L } }, + /* 59 << 119 */ + { { 0x43f9a415259ac609L,0xcd6c7aaa0ff5722cL,0xb4689e75b29973caL, + 0x78a43571b690c0acL,0x90dc4ac0a6d3ba1fL,0x38af00a2b773932aL }, + { 0xc13aebdda5e2c9edL,0xfab3a128cf3fed2dL,0xb3b7d29d32eb8ccfL, + 0x9ae1430b6986db5cL,0x35d18edf5365c21eL,0x88f8356e038471ccL } }, + /* 60 << 119 */ + { { 0x45587a7c0794dad2L,0x660833899e9c1cdcL,0x60e7ae4ad242a6b9L, + 0xb5f96b521009df3cL,0xc2d405092e30445aL,0xfa53ba4ec250a29eL }, + { 0xf6a247855d98c6ceL,0xf873653c207dd110L,0x2aebc3c6c634cbd0L, + 0x84b8016ce5cdbafeL,0xbda81fcace00b206L,0x837dc69484b55f2cL } }, + /* 61 << 119 */ + { { 0x61bdc5cab308f1f0L,0x7763c97d8898d3c2L,0xc02324e60434de23L, + 0x7f5c565e4ba696e9L,0x06f27a3e66914b66L,0x64a975ee05052cf5L }, + { 0x98b2f703bb38b14eL,0xbacbd113371e495cL,0xe54451acdd14cc9dL, + 0x8575cfdf87d141b3L,0xbd183a03d0996091L,0x947555579360264cL } }, + /* 62 << 119 */ + { { 0xd1f2d6b8b9cfe6bfL,0x6358810b00073f6fL,0x5fce5993d712106eL, + 0x5ee6b2711c024c91L,0xd0248ff5453db663L,0xd6d81cb2adb835e8L }, + { 0x8696cfecfdfcb4c7L,0x696b7fcb53bc9045L,0xab4d3807dda56981L, + 0x2f9980521e4b943bL,0x8aa76adb166b7f18L,0x6393430152a2d7edL } }, + /* 63 << 119 */ + { { 0xc89db4eb4595ca55L,0x48921c735f1a73a2L,0xfc513c904afe7cbaL, + 0x6d3f988bff8322eeL,0x17d0d4f0e59b7cdcL,0x292f4757f4bb5588L }, + { 0x3037e11151c14623L,0x3e113343dce98277L,0x0be229341e20dc8fL, + 0x0ebd1fbfcd6ff82aL,0x304bd69ed01fa90fL,0x402a457577f1862fL } }, + /* 64 << 119 */ + { { 0xd74d09c10ece13aeL,0x5e59d9e057a6bd95L,0xdb1ccfdce132b940L, + 0xa0e5309c843d3c66L,0x1fbd03a5f9cb3ef4L,0xcdc9ef0a00ea5177L }, + { 0x1ebf5a15cb784a6bL,0xa67382af8a0d109aL,0x3256c37aa0d34d15L, + 0xee40efa50fca43afL,0xc299bbd4b9841bdeL,0x6df68f603bef4a0bL } }, + /* 0 << 126 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 126 */ + { { 0xe01295fdd9d7c50aL,0xaf31b4ea67f8ef0dL,0x2ec9689f9eaf8eb7L, + 0x327b96c5c622acc5L,0xae918f81b2757f2aL,0x74927d684fd6606eL }, + { 0x09bb7fce18574215L,0xfea383bce8e68b72L,0xdf2a6f125fb47511L, + 0xbe88faa18e399520L,0x0166d57e3fb1c3a2L,0x5907ef2fe525f81fL } }, + /* 2 << 126 */ + { { 0xdefe3a7b8a37f660L,0x7898db8c858f5765L,0x7366c26a73d1f9b4L, + 0x35d5d718237ae8b7L,0x3efb20feb4478259L,0xccd0fed7aa545ee3L }, + { 0x750edd05ed22d152L,0x4f8020f9ee20d4c6L,0x16e60f370a9e29dcL, + 0x9cf0a136bfbec7f6L,0xb430a34b2e47e143L,0x2e2560bbc6cdd1a9L } }, + /* 3 << 126 */ + { { 0x799352dae4161a65L,0xe5cf7ad856253ce6L,0xf606bf796de32775L, + 0xddc0f3a357fce8dbL,0x1075fc2316cf4a47L,0x078f0e04b27c5ad8L }, + { 0x9fc477953f7100aaL,0x3ac489254673ffa2L,0xb8263f42f9cd8348L, + 0x5bdfde3068cc92d5L,0x2250927b1ac37f9cL,0x26ec8328b33da359L } }, + /* 4 << 126 */ + { { 0xf186d6bcc88d568aL,0x872bc4c7528535ddL,0xc9e7432edfe64dc3L, + 0xd9fc4832d795ea57L,0xf4ffdb81c845af2bL,0x66d7e7882b670517L }, + { 0xa7c1be04d7b7a1c6L,0xbed88479d5b2a249L,0x62ff8aba03f2ef6dL, + 0x60ecaac420dc701dL,0x9f4b559f4ff10119L,0x0582c9313cd54fd0L } }, + /* 5 << 126 */ + { { 0xea9da8f012bbaeb6L,0x3fba06b18c9f8360L,0xc11bd7abb28c0ac3L, + 0x1e05af2faa8a01bdL,0xae1e99c5f000b1c3L,0x93ee806453d79930L }, + { 0x5728089e4c4f5513L,0x755351f3b1f70b76L,0x187ac651675f77efL, + 0x5cf7bfb553067d84L,0x629290838174b5c0L,0x720e20798d5be74dL } }, + /* 6 << 126 */ + { { 0xab8cc09ff5eb9ad1L,0x97a4de76132edbfeL,0xa2e11c548baf6347L, + 0xcee54229683cfcf6L,0xe1e993b8dcfc6555L,0x333bf16abe9df066L }, + { 0x5207e093060d62dfL,0xfa32324d69b0f5faL,0xef16fbcfd3243d2dL, + 0x540a2e59f04f8e45L,0xb5e70f9c48317bbaL,0x00dbe9b25b35baa1L } }, + /* 7 << 126 */ + { { 0x0eaed675ebb512eeL,0x347e0756058efbd5L,0xadf792ca296d3d47L, + 0x57f00c0a4654d012L,0xa1e08a04bccc5803L,0x610677f05b2f11d1L }, + { 0x0d9393d7b81acfd2L,0xb258e1570587c219L,0x372a1857b4ceba47L, + 0xe1ce8bb53ecc1c5dL,0x7efdf301922cecd0L,0xcab8cb170d8aa653L } }, + /* 8 << 126 */ + { { 0x31954a5679d05497L,0xc12520b6fe76d4d8L,0x8c433ec5e37ef1d2L, + 0xcd0f203575bc3b66L,0x3723f145249cd98bL,0x1356e0d2ea3b42a3L }, + { 0xf607fee0f174c7b5L,0x318afc5e0127be39L,0xd47b5d74cea5417fL, + 0x6891940a10fca22bL,0x5cea41332b635e8bL,0x93db2ed6b5934fefL } }, + /* 9 << 126 */ + { { 0xf87cfaaac8972b7dL,0x2b8f9874e090800fL,0xdb88cd4f52efde36L, + 0x7b977f6e80776de8L,0xd047fc8ffb4b19c4L,0x33f3e43578b8135fL }, + { 0xb4cdb352da33eff8L,0x217f9e2deb89d325L,0x1bb5a004c99feec5L, + 0x98ce5a7fdb45c845L,0x458904681d87e964L,0xb9253873d151ad80L } }, + /* 10 << 126 */ + { { 0x5d7c767de39edca9L,0xe4a700e7a7f8de0cL,0x5816e1f93c9eec33L, + 0xa975c933d32fe465L,0x979beff968466a5eL,0xe308c135cc067721L }, + { 0xe0e733b41839b88dL,0xda3e3e6c298dc2ebL,0x414c3f0e8fb70e3eL, + 0x5ebaefa7ed7ca91cL,0x5c283310ae3b0f3eL,0x20353d5df3b1d44eL } }, + /* 11 << 126 */ + { { 0xd50767a9790325feL,0xe2ceddb9358c50eeL,0x60be64bdbbf03ae5L, + 0xe70c7e90f053328fL,0x6ba6af9e51543f0aL,0x470941f3b413e069L }, + { 0x0b569fd4ddf63d13L,0xf94b22634a2125d6L,0xaa45ab62a5c1acedL, + 0x2b797175defa5a30L,0x3eb30067ead1d440L,0xcadb54e90b691af2L } }, + /* 12 << 126 */ + { { 0x365a4a431630b133L,0x9ecef631068d7863L,0xa330c8b4b7205a6fL, + 0x4858eab357df815cL,0x6e522afaf1a92674L,0xa7cff3d9f41365d7L }, + { 0x00dd34615a0e4626L,0xa695feff48f9d094L,0xf427103f7c082301L, + 0x14a2a1876b092b71L,0x210f632130037a33L,0x21cca09639340e14L } }, + /* 13 << 126 */ + { { 0x58355ba0f60ad6c1L,0xc63fbcff56022afaL,0xa6a770d54e7ef19fL, + 0xf42b2024a09e9378L,0x153aa3200330f774L,0x268aaee55dc02c97L }, + { 0xa7e13b42828f7ab7L,0xc0ccce09c303bfcaL,0x23169daae3ccb6ddL, + 0xf7f763fd786774e9L,0xb15a5ef150021488L,0x52f408fd5f3ea885L } }, + /* 14 << 126 */ + { { 0x53e84021177346c2L,0x4ee451dde20af475L,0xd7642453c14f393eL, + 0x7eaa215331662516L,0x1217a1b4c1d486c9L,0x7d32427569860f20L }, + { 0x3813c95f14c2837eL,0xb8f0713d4e0c056aL,0x398c218cf6dec37bL, + 0x5bfa2eefa4ad1eedL,0x53cb0fd29f97a05dL,0x59fa132f6a9f492bL } }, + /* 15 << 126 */ + { { 0x6d5dff381fc2c16aL,0x5dec7ae2b1fe149eL,0xa9eed62c85088ceaL, + 0x5878fdf7996174baL,0x2cf65bb935517a73L,0x80844bcacff96d13L }, + { 0x0f55c8bfed53f49dL,0x35815fb0fbd8cec6L,0x23e7d5c53b6fa7d9L, + 0x3ee04c0146ce1733L,0x180e25553f5c4a27L,0x61263ea7280e6363L } }, + /* 16 << 126 */ + { { 0xb1f4fead41b959b5L,0x6edb53a9e71890c0L,0x48b47efe2e28aa2aL, + 0x70dad2e9b3151d67L,0x87a8178b436a3460L,0x0f86f9f5801f7af7L }, + { 0xfab462e3a982fc14L,0xe29126bacb03e978L,0xb4696b3fe6681282L, + 0x3bd9910a6a3fdc1dL,0x4409128449e37dacL,0x3b4bfabccf605fb3L } }, + /* 17 << 126 */ + { { 0x605fae7ece9d1372L,0xb2623a79f9b7e06eL,0xfab9b2742d37357eL, + 0xffdf9246461417f3L,0xc04b15d7bdd0e922L,0x767bcee54b2dbc0eL }, + { 0x74c4ea4ed45efc88L,0x32d3d85491a534a8L,0x88967078554b2691L, + 0xe8256015e336a410L,0x166469624b9f978bL,0xb433f06ca104f01fL } }, + /* 18 << 126 */ + { { 0x8906d815457e1e82L,0x96abb1aa4c8a2c68L,0x2e63f37927ab2fb1L, + 0xe092e15f5446dfaaL,0xa3a3f0926615c65cL,0x8b31116747c3f259L }, + { 0xfe2038782e5c658cL,0x38903cf526215773L,0x0039fca7237f1bd4L, + 0x75dbcc016058ff17L,0x67ee6226a65aeb9eL,0x96999fa75cedcba5L } }, + /* 19 << 126 */ + { { 0x04c6fd475ac4d191L,0x0067e474c825a897L,0x4a37c931404810c5L, + 0x072d30e5c4a56380L,0xbaf3428dc897ba23L,0x9899935b53724382L }, + { 0xda5cc13ff4d41a62L,0x063047a0c6271baaL,0x49790bdc5cf48302L, + 0xd8c34e5384c5a9abL,0x6cf28e83db5bc36aL,0x430dbb1497da9d42L } }, + /* 20 << 126 */ + { { 0x59470e49c37acc2eL,0xc9e0f73611b85596L,0x47613c1e0fb30eccL, + 0x1fbeffa3b62892f1L,0xddfeef49f8eefa16L,0x6f82acd9daeff719L }, + { 0xff1872cdacb41007L,0x06fe556c82d64c6dL,0x52a63a387695218aL, + 0xa0d413a720802b88L,0x233f1f3118f4a473L,0x22ef7d6fc9d7da4aL } }, + /* 21 << 126 */ + { { 0xeba1db6910dad9abL,0xddb62dacde3a5a42L,0x209c472cfdf5ad86L, + 0x14a7ee4b37214540L,0xcaf70ce08339c9dfL,0xa95744554eb9189bL }, + { 0x90d7f241e9b39189L,0xf5edfd09af7f3eddL,0xc9a3444deb7ed52aL, + 0x30d9e2f80085d9d1L,0xeb412daa4dc24fefL,0x55c0000b27786649L } }, + /* 22 << 126 */ + { { 0xa9f34fa9518118e5L,0x430db0a51a22e790L,0x64b443a5d5a16ca1L, + 0xaa3b64f4d8adbe45L,0xb49435fae0f0873aL,0xb8d67ce4a635d1e3L }, + { 0xad843f8a8a612b29L,0xa416ec7fd84a210aL,0x8b4dc6930984b23fL, + 0x29a1b71b24640dcfL,0x8f2d7507911892adL,0x0ce384105bd4d518L } }, + /* 23 << 126 */ + { { 0x1e1bef926c42e1bcL,0x91259dd60e04d449L,0xc029961e8875d346L, + 0xfde51012a9e38f43L,0xdeaa1dc18892643aL,0x67e3b913217e08d8L }, + { 0x889a28c269b92b7eL,0x004c0f87b7446c21L,0xea812f67a2f98e77L, + 0x42fc7bbe22c40b8cL,0x5e7f5f5a8722e381L,0xf8f209d932099e41L } }, + /* 24 << 126 */ + { { 0x867379134a2965f5L,0x34724dcde67b3546L,0x2efe185ee92c712dL, + 0x8b908f86c201e327L,0x3ab5528894f6b078L,0xb9b2b784ce0a5bf3L }, + { 0x5eab37ac879f6a41L,0x74271f672f2360f3L,0xf3a3edff304f1cf9L, + 0x8992ecd8f6fd3e90L,0xff24d7c69f16e5edL,0x0844ab25def9a5c4L } }, + /* 25 << 126 */ + { { 0x35cbf2191e14f235L,0x9ef33f3c4cdc1b46L,0xfd5cedd0299f7f13L, + 0xf57b9bbf99379e17L,0xae25d3e3cd3d59a8L,0x72f9fc84f58cb31eL }, + { 0x87950fd84c94b63bL,0x15b52b4f7a4560a8L,0x382d36ec943e44baL, + 0x567ce2e9337b0f11L,0x8136e9ce2fa44901L,0x7e43a7289b15eeaeL } }, + /* 26 << 126 */ + { { 0xd1c8ed8814fb95f4L,0xc302e0aa29602659L,0x67abcce005cd67baL, + 0x7a234cc022f8ae25L,0x7074face39f44e4fL,0x84a08afc7a9d3fb2L }, + { 0xfd149c88f56c1f32L,0x5b12cc15219e494aL,0x242fc50c9ea3c0e3L, + 0x196cdba555b23034L,0xfd8cfa5e87b75206L,0x915e706488d55f47L } }, + /* 27 << 126 */ + { { 0xb59480ba876145beL,0xd8f8fbbe8e1075ddL,0x0ba10292b5d9baf0L, + 0x3a4b7f65e39a8754L,0x1b3a044c0f3c6520L,0x6b8b3397b1dff4f8L }, + { 0x40cef2285c182eb3L,0xbef82aec1b1cb92fL,0x5c4d2bfc2a97c5dfL, + 0x41d2a046536ad077L,0x94ef34a8c497505dL,0x14e9aef48e0b35ffL } }, + /* 28 << 126 */ + { { 0x2edaaaaaacaf1f3fL,0x9e3af72c80ebcc10L,0x3542fc42bcb1618fL, + 0x6c04ec246709d851L,0x5fe9768ea9af4ce0L,0xe739d50eeb6ebe2eL }, + { 0x7b7da4ac876586e0L,0xb0869f1d64f5f956L,0x7f691c51fd563c80L, + 0xea990d6926c775e1L,0x2cd96f1321b58889L,0xbc8074720f1aac2cL } }, + /* 29 << 126 */ + { { 0x8e1fa5f8eb3283cdL,0x0107a3ba20e69342L,0xf99a511cb045b8dfL, + 0x172d0c8933b51876L,0xb11efc2b9636d0f9L,0x16b2197c41570483L }, + { 0x49df27edacfdfd1aL,0xd9d2cedc366b9b28L,0x0289a75cab028c0fL, + 0x522f567a4879464fL,0x3313728225f64030L,0xfa28cb1558d6753fL } }, + /* 30 << 126 */ + { { 0xe5252210c6cd33f0L,0x6ba7f51f3f085202L,0xd2a87fb38f52e312L, + 0xa5e082cff25f35efL,0x786a93c2b9df2f20L,0x68c7e1299a19bf27L }, + { 0x13a971ab8d710915L,0x3ca4f8c6939443c6L,0x8554699c70522446L, + 0xdf42b7768e14e6bcL,0xc7969fa5f7f3dadeL,0x135b6b77350ded88L } }, + /* 31 << 126 */ + { { 0x39e54aa472546076L,0xc0003f7f13e312beL,0x71106a4ffea91274L, + 0x3868f957819851cfL,0x713b96e75c85bbc6L,0xfda8c2df610403a8L }, + { 0x0ea806c3a008cf78L,0x0ef9708353c0d1bdL,0x536950211e592838L, + 0xea3773d5e9023982L,0x6eee3c0d4195754cL,0x95df7b568c4bead3L } }, + /* 32 << 126 */ + { { 0x57edf71edf9a9f18L,0xbf834240627a0b79L,0xb37aba1aa6934160L, + 0xd45b3d2c5e639a54L,0x62c6b9ad70bce957L,0x16bc35a75d7e87f3L }, + { 0xb021698266b4a982L,0xb56050dd0e51c9bcL,0x15aa692b478e4b91L, + 0xdd67cf29be3fe25aL,0xf1ef75b006bdd4a8L,0xf71a285b41df627aL } }, + /* 33 << 126 */ + { { 0xba6be58993032120L,0xea6dd691db99740eL,0xad8679463154648dL, + 0xd1a36f4c28c0668cL,0x09a28c234dd76e88L,0x93fef0c7dc665bb7L }, + { 0xa78dfeb4860a0016L,0x06d2f868e21a9e02L,0x333a25a38486ade7L, + 0x12aa13130e398a80L,0x04a44a5848d5b3e3L,0xe59293d47a7ec12eL } }, + /* 34 << 126 */ + { { 0x6cdfb5faea2c1632L,0x6799cfcd7865f931L,0x4e1e5d25bf420a7cL, + 0x7d4597db05d22ddaL,0x7548db12fceda1e1L,0xb4523ccdcb473578L }, + { 0x3d8dbad0ff889f03L,0xc591bb1118a9a222L,0xfac2b914a2cfcc57L, + 0xbb67601abec9d9bfL,0x18dff42ceb55218dL,0xb36ef9ba7d2b6320L } }, + /* 35 << 126 */ + { { 0x5b007ad1f3edf67dL,0xfaee9cada25fcfafL,0x18fc784a4d62e5c2L, + 0x98deda878acb5f8eL,0xe9cfd10a6f888d8fL,0xbb0d729b053db2efL }, + { 0x7b09fa4f2aecece4L,0x3f72187cd4c44cc3L,0xf646aba05b8175a5L, + 0xf213caeba5686ca7L,0xf5ce777badc5d40dL,0x15ff85d660eb9357L } }, + /* 36 << 126 */ + { { 0xcdd18aee24e6df19L,0xa08ab968bbb3303eL,0xd5eb039cbab4f1a3L, + 0x040d03a8fa7a48d1L,0x767c0ed23d66628bL,0x0c6bd388b1a6809aL }, + { 0x793aff3f029eeb91L,0x6db32d13bca798a8L,0x6aef5c1cc3816cf7L, + 0xcfb25ea45fd2cd2aL,0x0715a7899f8e3312L,0x4a9ad4782a6b1a6bL } }, + /* 37 << 126 */ + { { 0xa9f360a5d134c919L,0x10dba223dcfd0715L,0x7444b191dc9b4394L, + 0x9a16a971e2f288e0L,0x0d05c511f6a49999L,0xca34eae26b65e956L }, + { 0x692febc418a83b76L,0xf3468c7b0b5f3511L,0xd8d3ce48b8e1ed80L, + 0xbe8c5c302a6de231L,0x9c0468b74e680d8bL,0x773ebb63f57b88d3L } }, + /* 38 << 126 */ + { { 0x9c2c33a5b726729dL,0xa86ab4ea5db2af56L,0xe987c5e3b0a36ffeL, + 0xa6dba84da5fe8bdaL,0xe1fefa4b8ff617a5L,0x561cdb88a91ad714L }, + { 0xeb58f7fce145ddc0L,0x7b0e560a29c5ad50L,0xf8d6626593da0e76L, + 0x7769b479db39fb92L,0x9149f1e3a3c49033L,0xb706057f3ac49c35L } }, + /* 39 << 126 */ + { { 0xa678ba3fa527d157L,0x922aab268856a8b2L,0x936d3e85690b4771L, + 0xed78dccee114e472L,0x9694ccb1d315fbc1L,0x8b1cf4482822d968L }, + { 0x336e670c4aca5441L,0xece24fb58f0e2824L,0x28d1578d05b758adL, + 0x0a1be96a40c3f019L,0xed1586e30b659cd6L,0xdef180009f860dd6L } }, + /* 40 << 126 */ + { { 0xc2885af90fe0f372L,0x2c756bef5fa6b808L,0x52b7f7b6068926bfL, + 0xc9399c1ddb143b68L,0x0e77c689e4c61211L,0x7d01e37f15ad7fa0L }, + { 0x712fc61f188b2a01L,0x103685ec55a4100eL,0x721f9c02e5fdce96L, + 0x61c8a0c5e784397bL,0x34d478351c686ed2L,0xc697c89cd155bbe9L } }, + /* 41 << 126 */ + { { 0xc26dbc34f06a2cffL,0x4f10297631a80712L,0x758e33eda7c54effL, + 0x44b5e4ff3682d103L,0xef05034722a05e6cL,0x9170365c48ff372fL }, + { 0xee49b61d66a15a71L,0xb5fd487995c2045dL,0x5940487160ad67caL, + 0xdcd2d5f586388c40L,0x0b41a8e54cbd1f71L,0x8152c17040236ae0L } }, + /* 42 << 126 */ + { { 0xf05b99d0995e9809L,0x036248a70295fceaL,0x7b70cf8f558e6ec4L, + 0xe882639c7c48ce34L,0x4cc86feaf4f47d38L,0x976799cf6d81aef1L }, + { 0xdb202bfe8043cb43L,0x4c761cc5cef4f017L,0xe124bbc161f0c89eL, + 0x77d1cbf55b5a3d20L,0x26e549fcff346940L,0xc6040a4c2325466bL } }, + /* 43 << 126 */ + { { 0x1ed4d238e940e32aL,0x29d99c20139efcd6L,0x4cb7ef50c172b412L, + 0x8a9c438931957225L,0x5d8872af60be4612L,0x7bffbb1be7e79e0eL }, + { 0x75bd89c1fc7d4e66L,0x723f9ae86bcc0379L,0x88f673b599c1b827L, + 0x8d45d139ecf5148fL,0xf12e605ff97ad1e0L,0x567dec052f09c370L } }, + /* 44 << 126 */ + { { 0xfb33b987b0be5055L,0x9864f903bcce94dbL,0x99b8da36aea9d09bL, + 0x19e326113b622d3dL,0x6abde501dc38f903L,0xb1fe3f1867cb2161L }, + { 0xb053ec831e08cd7cL,0xba503b563298d32fL,0x220e98c8c2a79e86L, + 0x66ac99511e1cba68L,0xf9520e1e644ab527L,0x3f222b9b4eb8abf3L } }, + /* 45 << 126 */ + { { 0xae0cf2ff705cfc45L,0xf9d5dfb65a0449b1L,0xd0300b2cd4697fe0L, + 0x4ac80d7e4dc665b0L,0x84fbd38d72c1677cL,0xea8306f08e683a0cL }, + { 0xe2381e65a469e337L,0x36b565d0b3ec173fL,0xc67689c700f3007aL, + 0x9f0108992abcc81fL,0x867a5f8dbb9bf584L,0xef789cdd5a436b38L } }, + /* 46 << 126 */ + { { 0xf8cdc9ecee11fa1bL,0xa78c73ed4c90edb9L,0xf6703453bbbddb82L, + 0xd268b4e23020e294L,0x214cdd54958eb8cdL,0x2acbd31d4d7214e5L }, + { 0xf7c60c89cc733351L,0xb8c5cc642fa201fdL,0xaae1ca7f4c2acb10L, + 0xf7e33be56d7f598fL,0x982c012fd920c3c8L,0xaa98a69b86751ef1L } }, + /* 47 << 126 */ + { { 0xf5f548eb915ed5cdL,0x657ca09ce30f448bL,0x8750c4a44a30850dL, + 0x1b329c4108edb075L,0x8c261df8ccbcdaeeL,0xa81720bbedd44638L }, + { 0x602fc21f0b91ee05L,0x6241265db7e8bc28L,0x1daefe5b106ac444L, + 0x93fe5bd42c9deae2L,0xedc229e17f1ba35cL,0xd99244977e0da1f9L } }, + /* 48 << 126 */ + { { 0x3176a43ab7a3ce87L,0x9fa09e975f130e73L,0x971cc37b9368e156L, + 0x2cabf535b8981792L,0xaec2862e4d0f0bc0L,0xa1a48c183ce8c100L }, + { 0x288f4e694af2eae9L,0x778845f21f9339bdL,0x1ef5fdfd17dfaa6aL, + 0xc784117e3483a6fcL,0xe8c82f05f3c5c19eL,0xf39b3c1d1da87ab6L } }, + /* 49 << 126 */ + { { 0xa2539d4cc4ac73e9L,0x0308f91891488ba1L,0xa3e72f4459fae934L, + 0xb6bbcc37f8c9c402L,0x345a2debc6edee3eL,0x0352f023b0df87b5L }, + { 0x67c9e7b8818c4f8dL,0x3a8714cc70f44977L,0x37b96e1295066bfaL, + 0x617d9737c95d7f70L,0x60bb06ef759a360aL,0x97689b3f34f59fe1L } }, + /* 50 << 126 */ + { { 0x17d0667fb2dd1febL,0xbfb92fe48862b2ccL,0xcfa0c8e9d5438a69L, + 0x7bdbd4b1d9cf9ef5L,0x7616acddf373c87eL,0x0603d2b0cf8fd5b6L }, + { 0x6a80f25d46e31aacL,0xea8c0ad0fd424755L,0x9e2e5a5b3ffd5a2fL, + 0x8882d271f3b143caL,0xe6fc9ad7904e1740L,0x98d1620af428ad20L } }, + /* 51 << 126 */ + { { 0xc8c991a63292054aL,0xc90b11618ce93455L,0xdfa32238e200d1c6L, + 0xa9c578d5303004b3L,0x9dd2c3881609e5f8L,0x068ec35d24b69108L }, + { 0x47e8183b2d1a3b7fL,0x6200d70efe3db580L,0x76012f3fafc089b0L, + 0xba06dbf4bddea8a2L,0xd83b4af5da01a49bL,0xa3d4334ce16e87e6L } }, + /* 52 << 126 */ + { { 0xb2fff4035b43e58fL,0xe80bd5740727be41L,0x048a59cbf9b52541L, + 0xb79084e7f38d0b47L,0x763b0c95938935d7L,0x7cfc6180336b8735L }, + { 0x118d2a6f929b0200L,0x7e5789775a31948cL,0x9085999326009509L, + 0x330533a33ad633c6L,0x28bdb910733f4c3eL,0x82c88f148fdca27cL } }, + /* 53 << 126 */ + { { 0x1c346bb04ef444e7L,0x40a50060e6c22e57L,0x5eb02aa6c7a773b4L, + 0xd748a0a0d23b190eL,0xb6ff7f02cfedb7dfL,0x3f8fb35b30f8bb4aL }, + { 0x245b1c232dc31174L,0xa1e156579af25f59L,0x1ad1a2315e2393daL, + 0x9430ed2dfd7c7073L,0xc4161d4f580fbc0fL,0xa2bebd3fa0f1dadcL } }, + /* 54 << 126 */ + { { 0xace743b6baff35ebL,0x84ac3ce8ac6f38f8L,0x81d41297106b44f5L, + 0x33f6bbbbaed20aa3L,0xae4dd66ceb420ee5L,0x87553aac994f0777L }, + { 0x26275ebff1e3647dL,0x3b574c4fd9eeb474L,0x58fe2a16929721c5L, + 0x748480df932030d0L,0x3a30032641bb5f68L,0x0797fad92c06d1adL } }, + /* 55 << 126 */ + { { 0x65356242c7caa811L,0x780fe23f4506bbd7L,0xa741a51042407c02L, + 0xb8ccd27f5ef9eac3L,0x137f4a573ecf5766L,0xd495be0d15936fdbL }, + { 0x5a419656109c93f3L,0xd2f7b65dcb12affdL,0x2305a070ff830421L, + 0x6d00f1e9684d5a6fL,0x3de9d1de91aa391fL,0x0b5148c10acb6de9L } }, + /* 56 << 126 */ + { { 0x209fa6e68ca7ec95L,0x17808b0c107a1047L,0x99bbeb5edfd270cbL, + 0xe3d57c1dc25e2d6eL,0xb90b0c107ba1237aL,0xa7e1b8dc4a0d6856L }, + { 0x97d5b46136a9a07eL,0x931251e9125ea29cL,0x4177fd10fc8868a8L, + 0x1d3538b7b7cdcdf4L,0x889008c8ed3ff9dfL,0x30573ad2229b9413L } }, + /* 57 << 126 */ + { { 0x11596662924d413fL,0xe797d0a70e5d7bf1L,0xaa05dcd28452ee62L, + 0x6e10e77f5d5ddf1cL,0x46b72cda5fbd184aL,0x3adc1edb5b25c0c6L }, + { 0x640de5b05c732e3aL,0xa7d4f0f5c6739747L,0xbc11978d1426527cL, + 0x979276eccbee0053L,0xc44347a7304e8811L,0x016c01e11f5ececdL } }, + /* 58 << 126 */ + { { 0x78b2f1a15ee57666L,0x28060d1576a2c09eL,0xaf0cb38df632a5deL, + 0x93ce93eea284cd43L,0xe3670d0af35dc1f5L,0x3b8deea527971072L }, + { 0x3b88b1158eea4303L,0x43ff3b22aabde038L,0x8d69e180c813d623L, + 0x218f5b853aa7a08eL,0x6ee1544adf74f239L,0x0d7abf20fb8772f7L } }, + /* 59 << 126 */ + { { 0x1d881d4eb7716840L,0xdf83a03b86bdef07L,0xd534c4e4dc7ee69bL, + 0x1169f1cc6e264c79L,0x85c812d1b7690d17L,0xcc3164adec5f2ed1L }, + { 0xb91a14180674e87eL,0x5dfaa279969188fbL,0x434acad5e242b969L, + 0xa51b5c63751c4e51L,0xaa9089b7874f9aa2L,0x8758f9e51b8397e5L } }, + /* 60 << 126 */ + { { 0x422ad88e57fd35feL,0xd4564b96b99a11cbL,0x78939992238baebbL, + 0xe66ddcaf4b30a709L,0x00873d5f7812ea50L,0x7317f9dc6784aabcL }, + { 0xf94afbdbe0608ba4L,0xfff893618896d745L,0xa3348af5cad62808L, + 0x13ed4507f349f51bL,0xa73d4bec1186324eL,0xf0b48189a20022d2L } }, + /* 61 << 126 */ + { { 0x87d117858b8efa4cL,0x724439d6e9c2ee6aL,0x33ab2a03606fa0c8L, + 0x6ede5b55f9779d87L,0x858b7dd0759445cdL,0x33683c817a5ef23aL }, + { 0x0f093175221c3443L,0xedcf2aaf889195a5L,0x9f189ebc814abec7L, + 0x6a64999c40235b9eL,0xf98dc212984438ebL,0x97e2d102ba86e7caL } }, + /* 62 << 126 */ + { { 0x337b9cbce3db0718L,0x1f2f55833d1796feL,0xa522b76f68c2a69dL, + 0x4c1da7cf5375cb22L,0x690a2e7f50bb0d7fL,0xa734d4756689b6eaL }, + { 0x918592d5867ca0a3L,0x64d1c147c4d15e28L,0x4d8c3e22656f8219L, + 0x5e028bb2170f59c3L,0x41e8b84449875858L,0x1d928cc90c599178L } }, + /* 63 << 126 */ + { { 0x736dee2cf44db09cL,0xfb5035c07257b4e5L,0x3e3a7bf6bf0b702aL, + 0x4910a0165f257c0fL,0xd80b891d98437b4eL,0xf9e55d55076d8587L }, + { 0x4e4ed7a79b4fcf4cL,0xaaf417f5581acfe3L,0xb1ae2a7ca3b3f920L, + 0xa666bb6263ee4781L,0x2fba297e63684f04L,0xd6e662658d83bd6bL } }, + /* 64 << 126 */ + { { 0xa58a27c58a541be6L,0xaf66949954fd7683L,0x2431826600079a25L, + 0x113f6fcf2606caf5L,0xf6ff2be316cb28c8L,0x8f7fc60e3c17caa6L }, + { 0x8ea577e07d35e26cL,0xc3e744c0f0628903L,0x4b28eff4592a57eeL, + 0x76e1f87c5e3f67b2L,0x40d7a676fb008902L,0x68a9dc764b6e6b7eL } }, + /* 0 << 133 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 133 */ + { { 0x76e2751a12575913L,0x2c6059914a5f8c4aL,0x58322dfb71fba662L, + 0x228aec085e0886afL,0x8d83b6276aee544cL,0x338f5fb6e29f9639L }, + { 0x1ba4cfe0bf5e19faL,0x2eea84c5b9e4f8f6L,0x7e0eed58cee95d92L, + 0x2d29282abe535540L,0x866638b607a9a1f4L,0x915999776ab8dc82L } }, + /* 2 << 133 */ + { { 0xa16c79cfaf4d260bL,0xfe853f6cfab3c3c8L,0xb8bd6aa0c2f47e68L, + 0x277d590f2c9b4914L,0xb6d1c810097242a8L,0xcf2f3d8e45f75512L }, + { 0x2176162b74a20c3bL,0xeee8bcb82b2bcddaL,0xfcf8c0d1a503aee7L, + 0x5d1f94a57af4dd78L,0x8f0bc1a62ab43be4L,0xd22dbf16ba9e071bL } }, + /* 3 << 133 */ + { { 0xbf87f30e3790b47cL,0xd3d3f1e25ab52ae8L,0xd5fd32bd50ec0ba3L, + 0x7de8fe0ae60d1e72L,0x52d77fe0e14ff2d3L,0x9b6937db55ca47e4L }, + { 0x39e3d19f53e94fa3L,0x8d962a4fbd7827e4L,0x3bd70c7afe92c6cfL, + 0xa3fbc06869a82904L,0xe263f00ed96d1d9eL,0xe6c9781f75c0c24bL } }, + /* 4 << 133 */ + { { 0x705bfe37b4e814b3L,0x22f0de61702013c6L,0x811e77a9bc456797L, + 0x4f52c4e617081a2fL,0x87405d819fe1640eL,0x53fa82b7707711d7L }, + { 0xdc6fff830ee4aea6L,0x8413e22ffd60373dL,0x0ecb66bea9cf3eadL, + 0x7418372e87139b8bL,0x6aaccf295e42b4d7L,0xb6dc592531fc932eL } }, + /* 5 << 133 */ + { { 0xf1c8d00de460fe00L,0x5692bfee528da7c6L,0x9e4dd700ac8620dfL, + 0xcc43e73d9d6fe740L,0xc94060d3e76dcba2L,0xfcdf8ba6d398914fL }, + { 0x540942e7502f8587L,0x5def85040de058fbL,0x63e0c7855292b0c8L, + 0xe90405282e558983L,0xe25727a16baf4a31L,0xb9bf28f0acf64d7cL } }, + /* 6 << 133 */ + { { 0xc7c8364f09d26382L,0xe16988737bf32d9fL,0x97bac2feb726391cL, + 0x521426364a7c0b57L,0xe3e596482cdec222L,0x4ee7238cf44e0a98L }, + { 0xa6d05a21f61cfea8L,0xa1059fb7efe6a26fL,0x482a65b342416fa4L, + 0xdc5727e1c71e7a94L,0xe6b0fb6ec4767f1eL,0x3d0d626d6510599eL } }, + /* 7 << 133 */ + { { 0x59f5df1b2a8f9f78L,0x6bb161d992257e60L,0x2cf060beb7b2eb14L, + 0x98e72799aec169b0L,0xdde683927045fdb9L,0xee5e0aaf461b27e8L }, + { 0x80250c744c0ee047L,0xdd3881f597f0677bL,0x0ea56921a4459b6cL, + 0xf7793cee26df8d7dL,0x33bfa09be42d1913L,0x9f0636f74ccf5139L } }, + /* 8 << 133 */ + { { 0xfa3b4c8eb88ee8f9L,0x1f288e60b521ab57L,0x06aa39562e8c4d8cL, + 0x4981c3e5cf89935bL,0xbdbd0c4745fa071eL,0xa78f831c496073beL }, + { 0x09a72986a4e5c001L,0xac527731709cb728L,0x9a64b5b3988f2781L, + 0x6ac9440d73b1719dL,0x58ad54c7e3d2e807L,0x1c1574488f06742bL } }, + /* 9 << 133 */ + { { 0x3220a099a5e437e6L,0x11a1b1734dc5bdaeL,0x1ad9e736b64c9b8bL, + 0x82b6a3d4ce40acadL,0x54e1eef8915aaa8aL,0xff19be481f3a1f54L }, + { 0xadc4c5250b64a2b6L,0x6637bc8e12caf63dL,0x970d08b01206a661L, + 0x97c9b9bde57cf6c2L,0x228ee4712b89b7b7L,0xfeed19ca837cb79fL } }, + /* 10 << 133 */ + { { 0xcd36c981a816f4d4L,0xc99316c27712a72bL,0xd32cb20339e671aeL, + 0x79ff1889f67f6215L,0xf9fe7448cd08e91eL,0xdc9b277776f3e605L }, + { 0x8af30c2e7c1609a6L,0xed3224a3e54cdd0bL,0xe73f56ded1dea6acL, + 0xb836eb783e37a390L,0x9f0dcdb2c78a0510L,0xc37e67a39e6109f0L } }, + /* 11 << 133 */ + { { 0xab419eb852e0d552L,0x86c76ef8ae3d06ebL,0x219662b4f7c6342fL, + 0x2820299e548f6717L,0xc4d0d47a8a2aeebaL,0x4c98069895536593L }, + { 0x3644e55ff42cd505L,0xe109b64ae47e0b0bL,0x91f520a6c89788aeL, + 0x35f6dc577699087aL,0x3484f5b6b77deb8dL,0xc22a63a47f3c09e6L } }, + /* 12 << 133 */ + { { 0x6b5b7b2a75c953b2L,0x927ed77ca7f1cd5bL,0x2e8c53994cba0e5eL, + 0x03aeb14a3f4a941bL,0xedbad9a0a1385c8aL,0x925a49c167fd2258L }, + { 0xe7e368ee3365ffedL,0xcc4aad2dd106eb87L,0x4ce908daa980b53bL, + 0xd3f4954016929ac8L,0x613c804dd5c05c32L,0xa42290ccd7973344L } }, + /* 13 << 133 */ + { { 0xe7437974c464c24fL,0x70c04156d36bdfecL,0xd94c80fcb2d5d96fL, + 0x4a1fcf19d2cfea9cL,0x443478592f6df796L,0x0c908d0159743bd2L }, + { 0x78949087d165a62bL,0x6c3f9021632f4e1cL,0x3917b925a94bb004L, + 0xe153ef092b3f87e3L,0x6aee1027ea706338L,0x953ab2959733bd02L } }, + /* 14 << 133 */ + { { 0xad49cad49855d008L,0x23442cf94b273d85L,0x3a3c8752e3dd8f65L, + 0x0ca5d24bedf84ed0L,0x3d0580938b4f8f96L,0x1cea59acf9b9ae03L }, + { 0xf17cbbe23a06567eL,0x49cf5294f090338fL,0xcf8cbe0da93562c1L, + 0x66683f21b986b71cL,0x3c96750cc87c9e10L,0x38e62db63dcf2f32L } }, + /* 15 << 133 */ + { { 0x807a519047f99946L,0x49e03dcf01615a37L,0xe813287c99590bf6L, + 0xc9caf30ddb62835cL,0x0733c49d4df78781L,0x4fde30fd4815d3adL }, + { 0x2809b853f9a2610dL,0xf2b139b9dc050142L,0x52a40a413c23a4edL, + 0x9333086b0a104df2L,0x04a90c11e2a65950L,0x4c6a15c4dc24341aL } }, + /* 16 << 133 */ + { { 0x33952177a98cf218L,0x841d9e1f579ee53aL,0x1084d61e0a285bd5L, + 0x3935a84e71171b1cL,0x8ac2433cf29b29f9L,0x5dd868b56dd1e9bdL }, + { 0x88da04788d102390L,0x1140735a657400d1L,0xa792a25f9d5b19e1L, + 0x9ee015cb6a27fa79L,0xea3bf8b57ba16a8eL,0xc5f0cc26c15fde67L } }, + /* 17 << 133 */ + { { 0x033708d2e02e9feaL,0x2b588d1e222f437dL,0x998442d6c6b47013L, + 0x4033d62fb8ac1fc6L,0x9b8fd348877c726cL,0x1a2125fa5bea5a49L }, + { 0x04a2c1d680b8afd9L,0x3d52c9d2a40195c1L,0x56b204e6655c0b30L, + 0x55ee14ef520b3464L,0x23fc52e6b5bdd96bL,0x445cfd7a56f4b269L } }, + /* 18 << 133 */ + { { 0xc8985c2c5fee6426L,0x8be749496bb7bb8dL,0x12967576659363b4L, + 0xd1b6ded9b969b221L,0x586f28929819fc04L,0xec6b03e5addd6307L }, + { 0x3f0e96cad4da6627L,0xc866c95c14860d00L,0xb038867c9725f9a8L, + 0x60cd3afa1caf2547L,0x6f2cc04411dddfafL,0x49551f249d0af0faL } }, + /* 19 << 133 */ + { { 0x04a68337177e2e7cL,0xe20b21c0adb79464L,0x9b30d3437e42ae4dL, + 0xac7a01d7f86c5767L,0x3ea34e385381db5cL,0x3005a0c39235f5bcL }, + { 0x853eb43167b4a5c5L,0x92f26a35584e4b8aL,0xa3d25e5879bb470fL, + 0x7963d90a5eacbb13L,0x08ca7969212e3aefL,0xb5ec6582df92bfffL } }, + /* 20 << 133 */ + { { 0x2e152d95ee2c3290L,0x8437df2e4a9ceda4L,0x4151754e3c7ebfd1L, + 0x556c59a888f80aeaL,0x8d099c5d8de44dbcL,0x9ecce7fc77abeeccL }, + { 0x5e0a0f383aa311cfL,0x99ff1eecb8f2bff5L,0x5ae0b483b5dcf488L, + 0x11212c4591483a02L,0x99fe0738312134a1L,0x3b855db0a72745efL } }, + /* 21 << 133 */ + { { 0xb70bf73230261470L,0x8c9b7c4bc74a180fL,0x4c648aef88a9d9acL, + 0x3d9f7540a10f98bfL,0x8ec2a3a3120d55f5L,0x1707c1b0baa5a600L }, + { 0xacba8da9103f2f0bL,0x96926dc0c7194236L,0x00358df7584499dcL, + 0x74c27d0e538c0a15L,0xc675d079de960a77L,0x575b042e89f41f6bL } }, + /* 22 << 133 */ + { { 0xd17d99529703d919L,0xb25ecc411477faebL,0xa5c66a58a9aea2fcL, + 0x83754d683accb00cL,0x6a9ae76a25901044L,0xe437981b2565e035L }, + { 0x441ec0d96f45fa01L,0x35e40d126a697636L,0xba2fbab59bb3c2fcL, + 0xc038be03e94b245fL,0x366b4bcc0c1672eeL,0xa14a2c10f1ce6d55L } }, + /* 23 << 133 */ + { { 0xef32d94febe1dfe2L,0xdbf53d4271494ea6L,0x72dc5fad24cf0c2dL, + 0xa9247adc66dbc21bL,0xe31ff66ab130da59L,0x8cb97c09e86ab63aL }, + { 0x204020e2f59ebb80L,0x56f6d8b7cfd0f965L,0x7522a692b1518dadL, + 0x8e7c999f5f231e2eL,0x2eff5904b4406177L,0x8440cee87bfe2363L } }, + /* 24 << 133 */ + { { 0x37f50e43892c8eecL,0xf06a2f047d85a7e2L,0x3916af85e1d11150L, + 0xf56e852f6785ae1cL,0xbf8c72adae6ada8cL,0x1fcd53e3e13285b2L }, + { 0x5327920cbd56d348L,0x82a394fb445658a8L,0xa71328573caf3792L, + 0xb15ab34b550ffe1cL,0x818980666a5d4e4fL,0x0bda153b2f854f9dL } }, + /* 25 << 133 */ + { { 0xf664f44407aa3d00L,0xcf8901664704e2d6L,0x1802f662f8c2fc8dL, + 0xd52496b8a47f0da6L,0x37f71d8c75001c8eL,0x7ad8e8c29cad3ba7L }, + { 0x666afc25825515f7L,0x3a871c76a729e498L,0x5dc21f1108479e3eL, + 0x78ff145966c4331eL,0x8d01e2352dd3deb2L,0xc68445e9dbc91fc3L } }, + /* 26 << 133 */ + { { 0x8f2d9aae98ea13f6L,0x3e75ba40ab97bfb0L,0x14dd24e635e1fe35L, + 0x14abb0735f88d9b9L,0x74b2c6a801d4fcd6L,0x4905dfe7744a09bbL }, + { 0x349348c077cd538aL,0xdec247f5f7b6d035L,0x737e248dc455d417L, + 0x608a5529b6fe5d92L,0xce0ba0bccd7dca64L,0x022bcb18c21175c6L } }, + /* 27 << 133 */ + { { 0x79fe5372881b120aL,0x4878428aae98aeeaL,0x5c6a7f7d09511acbL, + 0xb7be08de3b046481L,0xfb91990b8b35f13bL,0xab734f604ebdd374L }, + { 0x3d4955f1197690e1L,0xfc82767c7b376dc4L,0x7cf3db85b8c659c7L, + 0x4cfb6f4b03202723L,0x8b79311746141d27L,0x94c6ee67867292c4L } }, + /* 28 << 133 */ + { { 0x77a31009722730feL,0x93707ac4d5cdd297L,0xa290be39d3811e8cL, + 0x831a9b9592a5cdb7L,0xc74cda84e7342270L,0x964661903f48affcL }, + { 0xb0496cca5520b0f0L,0xc8742cd9bae930ffL,0x3a30737aeaea703aL, + 0x0a8e6fb7fb758854L,0x9ab9523e6796f4d1L,0x36e6c05dfdf7140fL } }, + /* 29 << 133 */ + { { 0x4c8ec1a3ccedff1fL,0x8fc58987ca74bd5fL,0x70a6b71cf768abcdL, + 0xb9971cf5ed60a02dL,0xbb2aedc8af2f9a41L,0x4ebf90c76032c98aL }, + { 0x8e69b4c4d3752262L,0x350f201474ba8e8aL,0x7a164f6724d0052dL, + 0x5aeb80db61d7eee0L,0x626a6c9da63583bdL,0x6246637fc3f2196dL } }, + /* 30 << 133 */ + { { 0x2077dfa1817d444bL,0xdda9c7fcdf855b15L,0x577603be04b31d38L, + 0xc6beacae7a140cabL,0x8cd9dc019ecbed91L,0x6ea8591295ae114eL }, + { 0x6fb29a33fd47f1b5L,0x6203bca6223cb96aL,0x2459d85a7c1a3580L, + 0xbab5922d6410a3c0L,0x543be274cc7750f8L,0x1a653e1c42baea3aL } }, + /* 31 << 133 */ + { { 0x616abd271dbeeea7L,0x0684c14fe2189d8aL,0x0d2bf3687354d862L, + 0x8b0cfc06a8bdcb0bL,0x187147b49661e548L,0x07509bc358edde6dL }, + { 0x7b2a33bca78c2782L,0x5f41b8379ec5fa24L,0xa6df5de574539201L, + 0x3510f650093f8f7eL,0xe4d1c06ed14aaa71L,0x4d1b1ca2b0470581L } }, + /* 32 << 133 */ + { { 0x3b62315064ef6a95L,0x97645381aaa5b792L,0x4bc2c31c56471100L, + 0x4a0e73bb1bae8d2aL,0xbfc0770a8df1f76aL,0x5089916fa7bb16caL }, + { 0x2afe5b1cf31fe82eL,0x0b06831df0119977L,0x97caa333a1af2a82L, + 0x93cb92c5dafed6cdL,0x09553e7e92c3b2e3L,0x3d9c4b7d61af2956L } }, + /* 33 << 133 */ + { { 0xe56c89b06910185fL,0x1cd06d19ac47667cL,0xb35e6ae5fe41a4ffL, + 0xdc2fbaf959e8be08L,0xa9e6df08f8cec40bL,0xcab91f8ffe63ad2cL }, + { 0x1e3bd193ca2cc678L,0xe1830cae06bb40f2L,0x3b8b33d6d69985abL, + 0xb6b7e8433895d8a8L,0xec3882909fbf6b31L,0x012bec2ac37d64cfL } }, + /* 34 << 133 */ + { { 0xff2e88fd33941b4bL,0xa2d9730a8d85cccaL,0xa23f8cfa16f7d7a1L, + 0x82013193d39a250eL,0x3b119882ca0fd8a8L,0xcff642ac1a438706L }, + { 0xe4a3a95f65e5688cL,0xb2a6c836c31243d2L,0x1b7ec5d2194d1f42L, + 0x51ab34f814e4f7a2L,0xa3e3f135d3583ca0L,0xbca6ecbade9b91f2L } }, + /* 35 << 133 */ + { { 0xc85820c3002f07caL,0x090365320e00dca7L,0x0f3b3166f4e4d8c2L, + 0xe694eb4479460f00L,0x50d0ed14c15e04ecL,0x8c9998abcc86e3bcL }, + { 0xb82581624aefa561L,0x6351aca610050c0eL,0x4e60399acc8d2342L, + 0x96da3af7f633dc88L,0x1af763ec09202348L,0x76b0e49d3f0d5f76L } }, + /* 36 << 133 */ + { { 0xd83f574a08f84746L,0x48fc9715ca07f5f8L,0xb3d5d0d2dcc51638L, + 0xc2a5e3356153bdcdL,0x8242cd9a8aa4ef74L,0xe71ba25b0bdaa0d0L }, + { 0x4342d4bba4ff172dL,0x81db10dffc1341a2L,0xdd93dd877dacb140L, + 0x6f8a4e81d12d347fL,0x0d4e7e461bc369beL,0x3ce10a771fafd0c5L } }, + /* 37 << 133 */ + { { 0x2fdaa3bb8cb896a3L,0x2fb82dfd913bb303L,0x5d814a50ba9ca09aL, + 0xc3de6aa426112215L,0xd0d5c98b25a0c9fdL,0x54004b3e0eaae4a8L }, + { 0x410e2cc209358663L,0xf7e3d08a501c4ef5L,0x3d86434dd334aa19L, + 0xf70ea577772fc0cdL,0xa0eded5aa607c4f2L,0xba0bf1bc36222b2dL } }, + /* 38 << 133 */ + { { 0x8d901e759632c4d6L,0x0ed9a7ebbbd94698L,0xfd2169dbbf7bcbc1L, + 0x2b4d168d5b302c66L,0xd42f9dd73e65f24dL,0x73e0c22c0eed0022L }, + { 0xf9091588f5d2dcfbL,0x81c7c01eb8715b78L,0x2be06165dde6a9d6L, + 0x64b5902dcacd6ca2L,0xdcd510d70159d3bcL,0x5b71995b42b5e30aL } }, + /* 39 << 133 */ + { { 0xa9c474eae7a211edL,0xc7bcdd20d8170f76L,0xd9aa8d9734a15487L, + 0x26235292933c16b6L,0x289d47d5d8238fc0L,0x39f10fb3ae27ca16L }, + { 0x822e187f1c016ae1L,0x8e93b15f2be46859L,0xe2ba61a60b0a055bL, + 0xd8f33ddecb8de893L,0x016652d6379657efL,0xf4eb08f9e7d9eab8L } }, + /* 40 << 133 */ + { { 0x5559dd31e67145b6L,0xf2d905b45b2427e7L,0x0d840fabcaf57d0cL, + 0x9625866578742ab6L,0xc85482ad409c1c8eL,0xdca2a058adaa6167L }, + { 0xec26ad9a0c8885fdL,0x1b93b8a22a600cb2L,0x340aa7fc2539986bL, + 0xd7674876a23dee41L,0xa948a9292e1a9837L,0x9ae67d2a71438da9L } }, + /* 41 << 133 */ + { { 0xe753114a8d6a98f5L,0xb2d7d1e1f6ad93e4L,0xfbcfe0cf1935714dL, + 0x9dc2d293e859e729L,0x674c170889a703f2L,0x87744b0252063099L }, + { 0xa1721de04b25966bL,0x059292573a285fcaL,0x5b02ca39e8ce75e0L, + 0xbfdf0fb939e57da4L,0x554378cd6388a964L,0xc53fc5c8f853d7faL } }, + /* 42 << 133 */ + { { 0xcd3b60e352f51554L,0x6292fafab44ad7eeL,0x670561c79513741fL, + 0x95defdf3b9ba16a7L,0x6c0beac1adae36cdL,0xef05c24a3e8aabd6L }, + { 0x74208a02b23efc25L,0x71930e02c22172d1L,0xbdb1f1c6f5ccbffbL, + 0x358b483c504d9cb3L,0x48b5887a9a48a4baL,0x289256b4e48f09e7L } }, + /* 43 << 133 */ + { { 0x671bf1eebc2f256aL,0x530faa653984ca7eL,0x0a6d18955c05da6eL, + 0x219de918118fe96cL,0x289b9645bb7eded4L,0xe905c4729588f006L }, + { 0x56d0cd9ac9d61133L,0x8879550079a4f743L,0xd05e910199c2aff3L, + 0x7e91f7c985e52c8bL,0x7fd02f83b5c5d473L,0x4b43b6453c59330aL } }, + /* 44 << 133 */ + { { 0xeac6f447d56bdf1fL,0xb22e8425c2b502ffL,0xe1cc9d3dfca5a501L, + 0x8192bc29b64baf39L,0xeb2c901a52ce849eL,0x7f5f38b11dd506f1L }, + { 0xfb3684b10f0a1d68L,0x16c4aacde9240ff8L,0xffa682435a4d8995L, + 0x27264ab554e4c95dL,0x9aa40cdc4f34ffaaL,0xcb8a30a35fd818eeL } }, + /* 45 << 133 */ + { { 0x912f0a7dfa88792fL,0x2ad9249f5090716eL,0x4b828a6fb96e6e31L, + 0xe805f0588d7f2095L,0x72e95cb956e00978L,0xc95354667651815fL }, + { 0xc877181a08df5b53L,0xae055dd8779c3302L,0x3f9e6dd90b4e68d2L, + 0xdeb15f1308fbb2f8L,0x5f129c1cc5802a96L,0x7482e4af3cc51022L } }, + /* 46 << 133 */ + { { 0x98904777ab695f56L,0x6dc472c18989e518L,0x6749d25c82031d40L, + 0x5c465922c36202f1L,0xb3b5b9aff31fe542L,0x855263bdf98bc09dL }, + { 0x40ee01747eb4789fL,0xd64ae0d4de4e92bcL,0xbaea76a38995e69fL, + 0x3f22b2e3d972751eL,0x5a197daa2461f1b4L,0xbd15682a5097b93eL } }, + /* 47 << 133 */ + { { 0x7f251143534f8547L,0x213baf14222a161aL,0xae993737ad1e6005L, + 0xdc70867ff8b1cc7eL,0x41e880f3bb22e11bL,0xe36f54cbd2d6bc45L }, + { 0xa42e819d4d65ae97L,0xdc57be4de8592604L,0x8a89777fabe73b50L, + 0x435fedec72e26f5bL,0xe8d3cd8251ec79f0L,0x9574d6ea67f407b0L } }, + /* 48 << 133 */ + { { 0x39038863f7f35053L,0x421a17f3328787d2L,0x38aa682ef3d8310fL, + 0xb52d41e8f4123153L,0x4fbef3dd7026310bL,0x0c6bd7adf6ff5692L }, + { 0x3831c6b2a9be5d0cL,0xb5c9ae85e8d328b8L,0x76d26abc6516bba4L, + 0xc237f9a5446d35a8L,0xb2b16c0ff012a8d0L,0xddf2b7fe0ee0315bL } }, + /* 49 << 133 */ + { { 0xf401366a7dd4243fL,0x7db92881f434ba76L,0x5b5bacd737ffc502L, + 0xa53fe0e802cb994eL,0xf6db539ffb00cb96L,0x0bb288b379878966L }, + { 0x275c108c0c3d4b7fL,0xe57222d267236ba2L,0xc754d31890683aa1L, + 0x883a41ef2345460fL,0x8e6b7ce8b572fd14L,0x7649c29237d21925L } }, + /* 50 << 133 */ + { { 0x46302515c4af281fL,0xe2a9633c3513ea87L,0x1175276fb3e96864L, + 0xda377e32f4ed1228L,0xacf223a1fa6be904L,0xf442c41abc01057bL }, + { 0x83d766c38a69db33L,0x933dd0974cef397cL,0x094b21b575fe43cdL, + 0xf16ee57ab3141dd5L,0x4a8d0d6cb981d196L,0x6bd246c3730075deL } }, + /* 51 << 133 */ + { { 0xd9ae9faa91eab3f7L,0x8520bebba2bcdfc1L,0xc681d5a0ee94353aL, + 0x980871dd316ee7acL,0x7d70b82bcb401c4eL,0x150706c1bc6885efL }, + { 0x11709bbed3d8663aL,0xad69df943ace1806L,0xf889daef1a36f12cL, + 0x6ba376b2560bb749L,0x5342cd7a0d95f8b9L,0x5d14201273b4554aL } }, + /* 52 << 133 */ + { { 0xbb85b640056ad6c2L,0x7c51ef96ac074372L,0x1c7ce31cf10b43fcL, + 0x08e4101b26f4d3a4L,0xd18511c43968459fL,0x00e20c3fd6d07839L }, + { 0xd5bcd598e4fcdc11L,0x99e9a4d0c877f6a2L,0x9c5dd9d0bd491646L, + 0x83918f609bfd7a1aL,0x4bc130cd7e2b95a3L,0x668825fbfbc31c83L } }, + /* 53 << 133 */ + { { 0x7e8947bd5568b75cL,0x43419ecbdab8f822L,0xeb52a83a7b8fa996L, + 0xbc674ff32d1a32c6L,0xdc086f84ce405eeaL,0xebe3e087f8918ddfL }, + { 0x476099ecdb152bc4L,0x0cb491c52d3718c3L,0xa7c49cd69da8517fL, + 0xc736fcf51ab8fbadL,0xa00b403ba24fe115L,0x01f6e5bfd976f549L } }, + /* 54 << 133 */ + { { 0xef8e12edf15ad86eL,0x216be9828c20441dL,0x10ccd4f85c45e821L, + 0x8a12f6037c9745e9L,0x56212b09da6f1b2fL,0x5a81d69338115f05L }, + { 0x5aead3330a4405a8L,0x7024a76c03221eddL,0x9c101d0250e6a610L, + 0x6bcb22ffc1b6d54aL,0xf96cef62cf787e89L,0x9c9bde7b79341d83L } }, + /* 55 << 133 */ + { { 0xe9c61fa744058dc9L,0x59efcc8f1581d690L,0x1ea73467513aba4bL, + 0xf0fda8a69d03d72aL,0xcc1f3f22c6f30a01L,0xb632daa3ddf8dea8L }, + { 0x58563188fe8e2f89L,0xf053b9f67b45cf5eL,0x1ab51b07f9bda4b1L, + 0x37850e9789dc0050L,0x1bf5e41e8f6a1daaL,0x4abb4f82d94c0fd8L } }, + /* 56 << 133 */ + { { 0x817d77b106a9ad54L,0x3a999d7d89a25ecaL,0xd3ac4107da68b768L, + 0x6904bcddbebc4c4dL,0xb0d2103ca53d39e9L,0xdba86bd230a5e950L }, + { 0xb09256804f52208eL,0x37c3156a28495b2cL,0x2389ab34c15855aeL, + 0xc14dfd963017194fL,0x420e07191146b838L,0x1a9f909b8fb4b6fcL } }, + /* 57 << 133 */ + { { 0x73af3d1fa24985f4L,0x4fa27db444a1f9a8L,0x6deb02455cfbfa45L, + 0x4803e0342813c996L,0x24715fe80e4116ddL,0xa2e8258d38d8e902L }, + { 0x3321e112dd7d8ebfL,0xab8d5b2b272ee6a4L,0x2994fac34eb10fd9L, + 0xe007d0a4a9c611ccL,0x29db5aa974d194e3L,0x9e76e3ddcf7409b9L } }, + /* 58 << 133 */ + { { 0xf12a3eeab577f6b9L,0xe666e002b6db2206L,0x95aa0d03375229b4L, + 0xebd05140ef0772beL,0x9d5b5e9e48580b17L,0x960906b3a77ceceeL }, + { 0xca869663e50422f8L,0x150e844199d481b2L,0xadd97d7c3418b00dL, + 0x9908a23e68244f02L,0x5357ea61d3eac131L,0x0af5423d9778902dL } }, + /* 59 << 133 */ + { { 0x11aa3582d8e62251L,0x108ec170aa1560a5L,0x8423663e2b5b6ea9L, + 0x3f4ad292d8718329L,0xf8e3e7bd04f8daadL,0xed310c3a11b81211L }, + { 0x718db302edac9282L,0x7866f1c1e434544bL,0x1052133c568b195aL, + 0x8ca61965c0e37cbbL,0xdd28fbd32cfac1c2L,0xf4062b33dce29660L } }, + /* 60 << 133 */ + { { 0x2926ef17dd63404dL,0x0e89c4d41399cc68L,0x6507fedef7ec20b8L, + 0x1ac084ff88c751d6L,0x31bc08bedefe29e6L,0xd42199714f0692c5L }, + { 0x4d6ee74236069bc0L,0x3868ef6aff80f3d7L,0x6df02d7c5a9c6f4bL, + 0x2c3096bb101abf69L,0x0c2b01ec8eaacaebL,0x65914c20eb2e687aL } }, + /* 61 << 133 */ + { { 0x78d5ab7b34a8173eL,0xa34b72ac9230c3b2L,0x379453e13538b39dL, + 0x1764c4420f3789b0L,0x5b4bbe77a3f2ba4eL,0x3bd35b796f86338dL }, + { 0xf2fcdf04f02fa7e3L,0x6b4522f420d23feaL,0x966fb8fa01be16a5L, + 0xf2a56e96e0d705feL,0x494aa4553872e429L,0x68432d9181921587L } }, + /* 62 << 133 */ + { { 0x0ae47d1e3dba277aL,0x54607ac99832d90cL,0xd4cec32eecbcdeacL, + 0xe54b3033b9ccdfa9L,0x5b3a8a56fb920449L,0x831ec8f955eefd3aL }, + { 0x59ba32a3a02dca96L,0xb421e4b01decf837L,0x52e70a88a88636d2L, + 0x3b75ed073086667eL,0x7a4a46b3b877cd6bL,0x3825c80b59c99207L } }, + /* 63 << 133 */ + { { 0x3bc3f0e069bdc53fL,0x7e0bd730d9d7def4L,0x71a577e6844ede6bL, + 0x06d47f4981705712L,0x83bdb1a6ef108ea6L,0x853a3ce0c8a8ff41L }, + { 0xa6f114b8f408ec44L,0xe0ce4267e2d72d33L,0x405f6ddda2a0b613L, + 0x22ce3daa8d253ad3L,0x2fd738094aa1de25L,0x28a2001b27363597L } }, + /* 64 << 133 */ + { { 0x13722ab079ed523aL,0x33b29bec249d5624L,0xd3d0f467f76fdaf7L, + 0x7ce072f912ddfd9aL,0xce918a5747bdefd3L,0x14d38ab4750e5315L }, + { 0x08bbb20e3346f647L,0x428b917f05b26894L,0xc8fb5c21ca865ba6L, + 0xee6e41e02e6e8e6fL,0xd00ae6214c608b60L,0x659756396ff685cdL } }, + /* 0 << 140 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 140 */ + { { 0xbbccce39a368eff6L,0xd8caabdf8ceb5c43L,0x9eae35a5d2252fdaL, + 0xa8f4f20954e7dd49L,0xa56d72a6295100fdL,0x20fc1fe856767727L }, + { 0xbf60b2480bbaa5abL,0xa4f3ce5a313911f2L,0xc2a67ad4b93dab9cL, + 0x18cd0ed022d71f39L,0x04380c425f304db2L,0x26420cbb6729c821L } }, + /* 2 << 140 */ + { { 0xca07923c0eb008c8L,0xab79402d9985912eL,0x41e379e83cb02510L, + 0xfabac005beb383efL,0x24d12d9a1076dd0dL,0x95afd46fb208f127L }, + { 0x9cc38a60b1031e46L,0x93e21e977009f6bcL,0x6f6360d98ac219efL, + 0x1edaab3faf284c80L,0x9c3b5281019e366aL,0x6475c579bc9e9726L } }, + /* 3 << 140 */ + { { 0x26bd07d6bdfbcae8L,0x10b5173fdf01a80aL,0xd831c5466798b96cL, + 0x1d6b41081d3f3859L,0x501d38ec991b9ec7L,0x26319283d78431a9L }, + { 0x8b85baf7118b343cL,0x4696cddd58def7d0L,0xefc7c1107acdcf58L, + 0xd9af415c848d5842L,0x6b5a06bc0ac7fdacL,0x7d623e0da344319bL } }, + /* 4 << 140 */ + { { 0x8410d8298d85a25aL,0x48ee01354af81a14L,0xae460d0d18c25348L, + 0x5d0279a07eb035a3L,0x87e7c1289a114414L,0x17c08a8ec0744f79L }, + { 0xb7b2b4f1025cdbe3L,0x9a74f15d82d1af60L,0x124a7395b51ee685L, + 0xf2937c4bf6122422L,0xb4ec133207f1a7ffL,0xad801112f886032eL } }, + /* 5 << 140 */ + { { 0x4c0d78060c9d3547L,0x993f048dcf2aed47L,0x5217c453e4b57e22L, + 0xb4669e35f4172b28L,0x509a3cd049f999f8L,0xd19f863287c69d41L }, + { 0xe14d01e84c8fded0L,0x342880fdeafd9e1cL,0x0e17bff270dc2bf0L, + 0x46560b7bc0186400L,0xe28c7b9c49a4dd34L,0x182119160f325d06L } }, + /* 6 << 140 */ + { { 0xdd4eb3d07bb5346eL,0x9a46ad01382e7db7L,0x1200285ddc1973c7L, + 0xfd342beaa0046b98L,0xd19173491219a7fcL,0x5383d319b7caffe5L }, + { 0xea5a0c4e2e0fa118L,0x1cc2de3ca5457b28L,0x5b2a16dc6046eeeaL, + 0x1755e1fecc8e64b1L,0x51e4946e9e7faddaL,0xf805422ffcbf4ec2L } }, + /* 7 << 140 */ + { { 0x46d70888d7e02e18L,0x7c806954d9f11fd9L,0xe4948fca4fbea271L, + 0x7d6c7765bd80a9dfL,0x1b470ea6f3871c71L,0xd62de2448330a570L }, + { 0xdaecddc1c659c3a7L,0x8621e513077f7afcL,0x56c7cd84caeeef13L, + 0xc60c910fc685a356L,0xe68bc5c59dd93ddcL,0xd904e89ffeb64895L } }, + /* 8 << 140 */ + { { 0xf877e8c6bd08ffafL,0x24718fefaf23012fL,0x19ff269f2b004cfeL, + 0x8adc5d7795450f8bL,0x688ce8bce2a7d458L,0x74d7445b97bd7fdcL }, + { 0x1b9f4ad641e6abadL,0x6652ed05f00e4bf5L,0xabee1f7e71d83d86L, + 0xe693c76d25ffc219L,0x1c9a84afc873f553L,0x84d2718766d77a55L } }, + /* 9 << 140 */ + { { 0x75d874fb8ba7917aL,0x18fa7f53fd043bd4L,0x212a0ad71fc3979eL, + 0x5703a7d95d6eac0eL,0x222f7188017dead5L,0x1ec687b70f6c1817L }, + { 0x23412fc3238bacb6L,0xb85d70e954ced154L,0xd4e06722bda674d0L, + 0x3ea5f17836f5a0c2L,0x7e7d79cff5c6d2caL,0x1fff94643dbb3c73L } }, + /* 10 << 140 */ + { { 0xe566dc057e5f7121L,0xccac74e22ed07bc3L,0xaabfdfcdc70401b4L, + 0xac9fc4496254e0dbL,0x358d885f11c7de05L,0xb8e6a4a9d60772b4L }, + { 0x884272a5cfe917ceL,0xdfbe98689a3d347aL,0x06b90848c9d1baccL, + 0xc4ccedb6db8c6288L,0x892878b979e5683eL,0x1b521829243273e3L } }, + /* 11 << 140 */ + { { 0x916e19d0f163e4a8L,0x1e6740e71489df17L,0x1eaf9723339f3a47L, + 0x22f0ed1a124b8dadL,0x39c9166c49c3dd04L,0x628e7fd4ce1e9accL }, + { 0x124ddf2740031676L,0x002569391eddb9beL,0xd39e25e7d360b0daL, + 0x6e3015a84aa6c4c9L,0xc6a2f643623eda09L,0xbeff2d1250aa99fbL } }, + /* 12 << 140 */ + { { 0x099369c4bf0c6fbeL,0x976f78b2fe7d5727L,0x32feb503d18267a9L, + 0x162c41501a7dd0feL,0x3141e37726b8e969L,0x50497a643b53a94aL }, + { 0x96159f41607b4cfcL,0x1999b7042f111babL,0x3254987c760f2eaeL, + 0x5308075b841014faL,0xc634127e4e7adad8L,0x32a70a6059ffbfe6L } }, + /* 13 << 140 */ + { { 0x1feef7ce93ee8089L,0xc6b180bc252dd7bdL,0xa16fb20b1788f051L, + 0xd86fd392e046ed39L,0xda0a36119378ce1dL,0x121ef3e7a5f7a61dL }, + { 0x94d2206192d13caeL,0x5076046a77c72e08L,0xf18bc2337d2308b9L, + 0x004db3c517f977b1L,0xd05ae3990471c11dL,0x86a2a55785cd1726L } }, + /* 14 << 140 */ + { { 0x7279c369a1f857e6L,0x029d30ef27fb373aL,0xe82cbc806827358bL, + 0x2bfe09aaa18f57abL,0x63bf3145e5503492L,0x7ea15beafb28ee43L }, + { 0x8e6d428f5eec91b8L,0x215e03e9611b1799L,0xb995737161d476deL, + 0x2320c764e76726a5L,0xc5de88178e5e26f5L,0x24aae0699161e0b7L } }, + /* 15 << 140 */ + { { 0xb8d9b28672107804L,0xb5a7c4133303b79bL,0x927eef785fa37dedL, + 0xa1c5cf1ead67dabaL,0xaa5e3fb27360e7c7L,0x8354e61a0a0c0993L }, + { 0x2ec73af97f5458ccL,0xde4cb48848474325L,0x2dd134c77209bc69L, + 0xb70c5567451a2abeL,0x2cd1b2008e293018L,0x15f8da7ad33c0d72L } }, + /* 16 << 140 */ + { { 0x5584cbb3893b9a2dL,0x820c660b00850c5dL,0x4126d8267df2d43dL, + 0xdd5bbbf00109e801L,0x85b92ee338172f1cL,0x609d4f93f31430d9L }, + { 0x1e059a07eadaf9d6L,0x70e6536c0f125fb0L,0xd6220751560f20e7L, + 0xa59489ae7aaf3a9aL,0x7b70e2f664bae14eL,0x0dd0370176d08249L } }, + /* 17 << 140 */ + { { 0x5dc386d0a8790657L,0xa4fdf676bc4d88bbL,0x1b21f38f48bc6c49L, + 0xcdcc7faa543a7003L,0xea97e7aa8c9cf72cL,0xa6b883f450d938a8L }, + { 0x51936f3aa3a10f27L,0x0170785fdecc76bfL,0x7539ece1908c578aL, + 0x5d9c8a8e0f3e8c25L,0x8681b43b9e4717a7L,0x94f42507a9d83e39L } }, + /* 18 << 140 */ + { { 0xaeac64c96f089b59L,0xecfdc92b65f9d762L,0xddde5024f750daffL, + 0x82c01c1c0f707e73L,0xc70aa9d4ee20adb5L,0x27f6799dbeb0e60fL }, + { 0x918ad262520aa514L,0x2bb1362f8d13eae0L,0x21b60b46a9d1d43bL, + 0xf449e2d4767ab86eL,0xf42b09948a5a496eL,0x3b26006b853f2a3bL } }, + /* 19 << 140 */ + { { 0xbbe11ca8a55adde7L,0x39e6f5cf3bc0896bL,0x1447314e1d2d8d94L, + 0x45b481255b012f8aL,0x41ad23fa08ad5283L,0x837243e241d13774L }, + { 0x1fc0bd9dbadcaa46L,0x8df164ed26e84caeL,0x8ff70ec041017176L, + 0x23ad4bce5c848ba7L,0x89246fde97a19cbbL,0xa5ef987b78397991L } }, + /* 20 << 140 */ + { { 0x364d5dfda6140b89L,0x30e4a48efdc9105dL,0x13f6276018a47151L, + 0x18ad84cfa17a2853L,0x5f315c93988cb37bL,0x90f9cb701af64ce3L }, + { 0x020c67db029b6ffdL,0x8989ccc62ce3528dL,0x9bb4f9844d00ee63L, + 0x0b052413a70b4ca9L,0x7dee36dcc96b4a07L,0x226db70ea7888508L } }, + /* 21 << 140 */ + { { 0x111af1b74757964dL,0x1d25d351ddbbf258L,0x4161e7767d2b06d6L, + 0x6efd26911cac0c5bL,0x633b95db211bfaebL,0x9bedfa5ae2bdf701L }, + { 0xadac2b0b73e099c8L,0x436f0023bfb16bffL,0xb91b100230f55854L, + 0xaf6a2097f4c6c8b7L,0x3ff65ced3ad7b3d9L,0x6fa2626f330e56dfL } }, + /* 22 << 140 */ + { { 0xcd9b76b6a92f4e61L,0xa464f5225a00d902L,0xb64774e68a583f92L, + 0xc7dc2030bee842a8L,0x594743ea5d2f27ddL,0x4c0ed28ef3c54609L }, + { 0xd763346d4b1dfb93L,0x8ea291dde1bed2eeL,0xf26d4adbd6d34ae1L, + 0x74b8d24e54ea3529L,0xe20490e150062077L,0xf67b7a9092d6c19cL } }, + /* 23 << 140 */ + { { 0x3d28bf2dffccfd07L,0x0514f6ffd989603bL,0xb95196295514787aL, + 0xa1848121c3db4e9cL,0x47fe2e392a3d4595L,0x506f5d8211b73ed4L }, + { 0xa2257ae7a600d8bbL,0xd659dbd10f9f122cL,0xdb0fdc6764df160fL, + 0xff3793397cb19690L,0xdf4366b898e72ec1L,0x97e72becdf437eb8L } }, + /* 24 << 140 */ + { { 0x67bf4c98e11df408L,0x8e105c66d299b156L,0xfde3922e901b63c7L, + 0x7fd57218c184ac91L,0x6dd2ea5cebcdc105L,0x1c4956c0aef7653fL }, + { 0xd6fac6429c1c11a1L,0xeda44f663d230d5dL,0xecca2241e6902ccbL, + 0x85962a1f2700870fL,0xc5ca32c97864a291L,0xe55e974af6c8d3d9L } }, + /* 25 << 140 */ + { { 0x81dcea271c81e5d9L,0x7e1b6cda6717fc49L,0xaa36b3b511eae80dL, + 0x1306687c3cd7cbb3L,0xed670235c4e89064L,0x9d3b000958a94760L }, + { 0x5a64e158e6a6333cL,0x1a8b4a3649453203L,0xf1cad7241f77cc21L, + 0x693ebb4b70518ef7L,0xfb47bd810f39c91aL,0xcfe63da2fa4bc64bL } }, + /* 26 << 140 */ + { { 0x0af51a2025f7b355L,0x35fc45d58d8081bfL,0x0cf3036d0ab30d16L, + 0x2bd47f919109cf76L,0x8be09360ec7f12beL,0x99fc291be8dcdca9L }, + { 0x385b89868135b12fL,0x272ac288f4ec52dcL,0xe7ca370cce09b043L, + 0x94655816251f4c4eL,0x5c1dea972d40a755L,0xe8977234a4b10406L } }, + /* 27 << 140 */ + { { 0x82c1c684eaa66108L,0xe32262184cfe79fcL,0x3f28b72b849c720eL, + 0x137fb3558fee1ca8L,0x4d18a9cde4f90c4eL,0xc0344227cc3e46faL }, + { 0x4fd5c08e79cda392L,0x65db20db8adc87b5L,0x86f95d5b916c1b84L, + 0x7eda387117bb2b7cL,0x18ccf7e7669a533bL,0x5e92421cecad0e06L } }, + /* 28 << 140 */ + { { 0x240fde37b21b2632L,0x6b878ae68ca0f16fL,0x072d9ded0bc32ebeL, + 0x8c2552bc29840743L,0xb58327b003b34f8aL,0xa51598ea71dabbfdL }, + { 0x337361f7d4f461c6L,0xae88972dda1de4b2L,0x9ec86d7ade7e8c2eL, + 0x607de383f23f19e0L,0x0cb144c27d234103L,0x00878a228f0c3411L } }, + /* 29 << 140 */ + { { 0x26063e124174b08bL,0xe621d9be70de8e4dL,0xaea0fd0f5ecdf350L, + 0x0d9f69e49c20e5c9L,0xd3dadeb90bbe2918L,0xd7b9b5db58aa2f71L }, + { 0x7a971dd73364caf8L,0x702616a3c25d4be4L,0xa30f0fa1a9e30071L, + 0x98ab24385573bc69L,0xcbc63cdf6fec2e22L,0x965f90edcc901b9bL } }, + /* 30 << 140 */ + { { 0x265f7236e22b29caL,0xe36c3c3daa62691aL,0x73410e6ed2e1bad1L, + 0xa182a579a5743cecL,0x2ca67274c22b0453L,0xc698fe35546e52e6L }, + { 0x60b3a519890e9155L,0x24312c3c2b91dbc3L,0xa6d45050282911d9L, + 0x3781933efd249e1eL,0x2e0cbb93e26d023aL,0xfb479267bf27687aL } }, + /* 31 << 140 */ + { { 0xd53b592d71e15bb3L,0x1f03c0e98820e0d0L,0xce93947d3cccb726L, + 0x2790fee01d547590L,0x4401d847c59cdd7aL,0x72d69120a926dd9dL }, + { 0x38b8f21d4229f289L,0x9f412e407fe978afL,0xae07901bcdb59af1L, + 0x1e6be5ebd1d4715eL,0x3715bd8b18c96befL,0x4b71f6e6e11b3798L } }, + /* 32 << 140 */ + { { 0xaff4782231cb94c9L,0xf1b5a0b7803c1af4L,0xbeb85f8d2ef696a9L, + 0x8ce5baab4fa94fcaL,0x0a32f96200d41a43L,0x0f69ad5774f6e772L }, + { 0xbe0221af6ccb5157L,0xcb83969a2a4f91ffL,0x78ff85d6a7e49f39L, + 0x63006589cb5d3c63L,0xe8e4383596eb65f5L,0x79f59da9ff8adbdfL } }, + /* 33 << 140 */ + { { 0x3cc0df125df9b6ecL,0x3c18f44e286d6ef1L,0x55a3939e517d0f7dL, + 0x42626a32607e97bbL,0x6168e7b2e26ad78aL,0xdcf8e74b9145583aL }, + { 0xa7c541a52db84a71L,0x680532c7119210a6L,0x3252035d0a3315e5L, + 0x06dc2d5befe7c8b6L,0x940175894e720570L,0xb16e635f2f6a3ec6L } }, + /* 34 << 140 */ + { { 0x0bd0ed3803e13ce1L,0x44a148bb5868069cL,0x2a79ab57aa5095e6L, + 0x943416faffffcf22L,0x98434e8756a1365cL,0x2493315d196dc354L }, + { 0x1f89d911b79a3a1eL,0x937140a841dfdd23L,0x05ad36e43b220b8bL, + 0xff5e810333594e3aL,0x3119775f893edb80L,0x1fad811627eee584L } }, + /* 35 << 140 */ + { { 0x55c4377e204f30b9L,0x63550549a1ebd2bdL,0xdd86ee0c5e44f5f1L, + 0x8b9d1d9b5d84d999L,0x9ea95a58dda7a075L,0xa465b4a50977e81fL }, + { 0xcb491e5558421fadL,0x4617f31c280709d6L,0x5e2751c382e0195dL, + 0x698155856f8eefd1L,0x6702166cd16dc160L,0xfc14545c84c85b2fL } }, + /* 36 << 140 */ + { { 0x27c961f6e8fc35abL,0x1e0c26923a596fe7L,0xc75c7cb804351be8L, + 0xfb92bfeb1c425d80L,0xb01d1c909f0bde61L,0x273d1f0c512f7817L }, + { 0x4375000df0d71796L,0xc1655874cf53d529L,0xe157b358abddc21cL, + 0xb0f91e3e40cedc30L,0x48e26c7272260452L,0x9794a6bf0713f667L } }, + /* 37 << 140 */ + { { 0x78befaede72c6f0dL,0xc80584210bb2a3ceL,0xcee67a5d52748e21L, + 0x08d4a9e8de8ed124L,0xc0393271b5fb9514L,0x39b1df6b20942000L }, + { 0x831fd8cfc3d961afL,0x1bb097e3e752daceL,0x279b3924cf2c8143L, + 0xa9f8a939b8f5cad9L,0x2b566813bfb8009cL,0xab37ee1df58f0927L } }, + /* 38 << 140 */ + { { 0xc17f21f5134d8bd8L,0xc75fc638a90a9a1aL,0x032a6f382a22527bL, + 0x3c77a72bd20fefb2L,0x559d8a52196e2921L,0x760a3a2c9afcb6caL }, + { 0xa3bf5802f162d871L,0xb6b367a5c594d2adL,0x4d440c523daa48dbL, + 0xb2a8acafd5b2c18aL,0x50d85d6adc349ddaL,0x3c2e67718a707475L } }, + /* 39 << 140 */ + { { 0x8254a39d5e1656cdL,0xff457dcaa595e153L,0xf0ddc1936bf62398L, + 0x45e1f91a558f9337L,0x8a424d9d91480b33L,0x019f0a412bf61189L }, + { 0x66badaa6d49e7b98L,0xb0674512dad636faL,0xc767eceff4c49695L, + 0xbe16e6b5ddc80ea0L,0x2bd0bb87febd1ba6L,0x69c9f485fe60eb32L } }, + /* 40 << 140 */ + { { 0x08cf7d82bff4b684L,0x6abbf429ac4a9329L,0x2454c15ab0c8e0ffL, + 0x4782035a70bdb03dL,0x89ff6a41448199cdL,0x07969c9ffd0bf1e5L }, + { 0x19d1cc6a83406dc9L,0x4054cab9b4980267L,0xf0f5594e1887d258L, + 0x039249e4e09dd987L,0x2b0cd4f9857ddb1eL,0x54ceb29fd8418075L } }, + /* 41 << 140 */ + { { 0x562693d30843729fL,0xd703202122648488L,0xd7c40e82ec6d0799L, + 0x8eacb2496eb6fb6bL,0xddf7074885a5ec47L,0xd70524bf891d5de5L }, + { 0x4d17c237c4d01055L,0x4793c6e4b4203cc0L,0xf247d0df1d1bf37aL, + 0x406994fa93b007feL,0x4062c29902940092L,0xedc0d949f558c1e8L } }, + /* 42 << 140 */ + { { 0x9fb3630606ab1fc5L,0x2726c1acc0de4e26L,0x8b2fb5130ec7b070L, + 0xf3581a6907bacd4aL,0x97db622c164bf5a5L,0x8103517962327e3eL }, + { 0xad3637b0b1d635c2L,0xb894adf949832ec3L,0x0ab5381725685b12L, + 0x73ceb46069720ce8L,0xdbd1b68ef5e445dfL,0x57659059c8961eb8L } }, + /* 43 << 140 */ + { { 0xbd1272a5f73a7cfcL,0x30d3c078de0828e1L,0x5dc0244e1a8f36a1L, + 0x87c80cdf585ec2acL,0x46c88d277944584cL,0x588d14d8b2dbe1a9L }, + { 0xb42327a7afe7d55aL,0x58add8f98775409eL,0xa45db2fd10590c68L, + 0xb98e10bca972b84dL,0xbf5c0ee0a737aeb6L,0x26424f3def199fa1L } }, + /* 44 << 140 */ + { { 0xb7bb774603c4cd27L,0x5bfe638ad9723678L,0x47d8b4c24a04d064L, + 0xdba309383faa45d7L,0xb0fb4308b39dd043L,0x5eeaa33f23ebfa1dL }, + { 0xaa5a0ce0ba100837L,0xae025cf6d7667d17L,0x610baf5df480cf99L, + 0x8ba0039ead025771L,0x0ff4f75174785f24L,0x910736ef8b7c30b7L } }, + /* 45 << 140 */ + { { 0x0496b77ac04b7e7fL,0x6f7ea5bbdf8163a1L,0x87a8e8f18f415876L, + 0x6e5b6f2e3ee22085L,0x5ae860ca6f529471L,0xc54c8667eb624447L }, + { 0xdd06be3de1c7766aL,0x8a8e48ecd2189d23L,0xa4076d3564245444L, + 0xc4973a5deb651a4bL,0x3b3e2fd52c4f2747L,0xe9a16a24abde2ecbL } }, + /* 46 << 140 */ + { { 0xb7f146b890973714L,0x2277873f288ed67fL,0xe6da9d9ee5182317L, + 0xa446f9d3562475b3L,0xc5291f9756755d91L,0xe762c5f3c104c2b6L }, + { 0x542f90b3dde83d53L,0x758aaddddace5f42L,0x1c8b9775e673f002L, + 0x8899c11f74ec42bdL,0xfd9e300a2dbc0dedL,0x6de1c8e4d281f6adL } }, + /* 47 << 140 */ + { { 0x5ddafb1b2a2f98cbL,0x8dc2bdc429ec504fL,0x27c51b3cc9f43826L, + 0xcfd609fccacf5becL,0x642ff85c30dd9f71L,0xcab498e5b6b00ffdL }, + { 0x9c7ef286652ca743L,0xda291ae0ab95d7aeL,0xe6f4d2badfbff466L, + 0x34afffef9835d482L,0x41a2cfc050db295cL,0x51a08859e6ee400eL } }, + /* 48 << 140 */ + { { 0xf6fd26cc487925bdL,0xd9b751eef5ef44e9L,0x694a788be372817eL, + 0x85f3dc1ae8c90c31L,0x8c90c6bf15aa0ce5L,0xb52a5d83f01bb223L }, + { 0xbdae01dddf9c3315L,0x941fa6b663ddfc56L,0x50ddff4ec2548f24L, + 0x54a49868d12802a7L,0xcd922fb6404d9240L,0x88d7f41f957f6d1aL } }, + /* 49 << 140 */ + { { 0xbfd0a17e4c4c87cdL,0xc6c76ebb10b614bfL,0x721d8b4fd1c594a9L, + 0x1ff70b2daff65d09L,0x2698f57ce50ad026L,0xf4ac3f5627a92e38L }, + { 0x1114d3392c143ba0L,0x7fafa6b97f8e9b0bL,0x506f11edd82a2500L, + 0x4df1087fe0ad9ca2L,0x85509ad9fdfecaa2L,0x733c4f8293bd022dL } }, + /* 50 << 140 */ + { { 0x3b9de3494233d6cdL,0x9a360917a8f55d63L,0xbe79cdfd90662136L, + 0xbb3d8fd7cbf3f02aL,0x5d0d4eb81d61e485L,0x85b485215484cd65L }, + { 0x77580c810fc5cbb1L,0x4b36441bd8e70ff2L,0x50ccdec1b2107a8bL, + 0x6b7f97c945a45893L,0xb818859b9572a173L,0x864dc632d94bd9beL } }, + /* 51 << 140 */ + { { 0x13bb6b113fee0074L,0x4c02520ed1059617L,0x5beb793ccf71f07aL, + 0x15a8d28d46d4c54bL,0x9889a8948b89fab6L,0xd00fdcb492623b75L }, + { 0x1c7963572939a84cL,0x4b85d94d6221a244L,0xcc66b5bad1fd506dL, + 0x866271042a06ca91L,0x4295fc6a49bb18c1L,0x05a81eea341d93e4L } }, + /* 52 << 140 */ + { { 0x895dbf20df8111ccL,0xec8297be2906fb2aL,0x4ddd6f22b94c3f53L, + 0xec55cc738ecbd552L,0x549d3145ef343a0bL,0x9b19220c3b4858d8L }, + { 0xd5bbf954bd0c2f11L,0x9cacae0cce8c221fL,0x87e6cbc1f6a3dbc5L, + 0x7ce5c9b6e37ebcb2L,0x654339ef50eb3c8fL,0xeac7f343f3674f55L } }, + /* 53 << 140 */ + { { 0x723969a3dd8d5580L,0x4f6dd5c4a30edd79L,0x5b29f3f5a4d7ed53L, + 0xe17a12bd11869af9L,0x63d01e02dc4c4c1cL,0xb43b904466a691e9L }, + { 0xab58d45ad1bbbcbeL,0x1e9b166322e8a57bL,0x88b6d3bb6684cdd9L, + 0xb944dee1ddaf3976L,0x70a4a121c347c41fL,0x7e93fa26fd1c217fL } }, + /* 54 << 140 */ + { { 0x5df68a1b584da350L,0xf378c367d72cd093L,0x5908ac0033dc31a6L, + 0x89bb976b7ca65b9cL,0xefdadfe237dcf670L,0xce22b5ba0011f3e7L }, + { 0x94d2c115b7d27bc7L,0x2e6763498761afbfL,0x3c0477829eb8185fL, + 0x634c8c5531f7635fL,0xf8fb5494d4d0fc53L,0x5a905615530ee2c3L } }, + /* 55 << 140 */ + { { 0xd28e59a0940c9809L,0xc208ae4f01b9f39fL,0xae1cb420b3630002L, + 0x739950501289d72bL,0xec24392805fcbd8eL,0x5b592df51f843891L }, + { 0x0d7602303f59f374L,0x32b6e643cae9f3ecL,0x94a25696e3dcc436L, + 0x657ae6aa8a059dadL,0x0df91017edd1505eL,0xfb1ae06f7b518d81L } }, + /* 56 << 140 */ + { { 0xf5bd119ad84c8a53L,0x36c5410f26928a6dL,0xf340f2bc0eb42b83L, + 0x8d93a66cffeffe84L,0xff59141d64310b9eL,0x2d509d7aaf69e00fL }, + { 0xf0f034ae1390628dL,0xf9089c720c38b563L,0x7462988e4e8df0daL, + 0xe6041dcaa7985905L,0x86295326d3b7274cL,0x5c8bf249075aa31aL } }, + /* 57 << 140 */ + { { 0xb08d098b9e423b93L,0x8ae94622029d192bL,0x05335f68fd67f1c4L, + 0xf3cb831f6e8c1e57L,0xf84a7a54a50a776bL,0x99930a48dc49c28bL }, + { 0xdac2ef8f1b833418L,0x87a4ca7829fda2f2L,0xf47f23079c0e9e7bL, + 0xebc1c2de46aeb3c7L,0x544f76836408bfc4L,0xa01b094b86c6cd44L } }, + /* 58 << 140 */ + { { 0x8e81bd1c06841f10L,0x3fc24a346c045063L,0xbb2be2dc85bc7ebfL, + 0x32523efbc341fe12L,0x1ac9f6b116508a41L,0xb6b7fa1df6ac4426L }, + { 0x2614c995fb685157L,0xe452b94dace46bbcL,0xccda1adabc453b4aL, + 0x32d32574fb4fac48L,0x7e43920c9d7d90fdL,0x9d6e959417a08456L } }, + /* 59 << 140 */ + { { 0x2c90f95bdb1f005dL,0x801089a2e16444a3L,0x2f2944ed7a724ad8L, + 0x0dfdd065de135e95L,0x510ab3eaafed3817L,0xdba075380855fbb5L }, + { 0x905f78bda10dde49L,0x63786348956a4057L,0x3d420ff0441530aeL, + 0x7a9968bfd1488ff0L,0x97479bfbca4dce2eL,0xf371985356f76255L } }, + /* 60 << 140 */ + { { 0x8102fa85bbda55a7L,0x6cbafe0de96c5eb3L,0x517720eb26aa52c7L, + 0x0ee110a98c030e47L,0x5a058569d4afe2c1L,0x29965b44262bbc0dL }, + { 0xda017ec04996daf5L,0x1781e7b84dfb810cL,0xdbe148350c8a5cf6L, + 0xd151055dd92ff62eL,0x5e4f48ba2932a708L,0x77e163d95f28bb43L } }, + /* 61 << 140 */ + { { 0xf6c5998c48bc9bc9L,0xb25ae99e2db132d7L,0x17f29131fb934e7dL, + 0x31b96a79d7fb5430L,0x3fad00391971cabaL,0x7f809e56cf3d5e33L }, + { 0x1a4f705a9ede6055L,0x3cab6c6149c2d054L,0xb616adc47945b589L, + 0x842b8652f342ee03L,0xa22fc6a67bc36a4eL,0xffdfee262c89a4fbL } }, + /* 62 << 140 */ + { { 0xac6b2727dab13b10L,0x8b4fa7807351ac35L,0x48243c245692808aL, + 0x724897f01fbc5d24L,0xb635fe5e2c69bd93L,0xab26453338d5d5b2L }, + { 0x368b2c07bc578c97L,0x94e02c9226fecf25L,0x768de4d41f473908L, + 0x58feaadee445d405L,0x1f1380d6e42a2218L,0x2904b4542154dd5eL } }, + /* 63 << 140 */ + { { 0x4e28b938ca2ec0f3L,0xd4af48d795b1c113L,0x33ffb9c222f2275aL, + 0x2a734af97b57b2e0L,0x1555ba38d08a45d3L,0xd0cae6c57a05837cL }, + { 0xed04c869c4e78884L,0xa7ba74726f3d56d3L,0xdb7b831ef6d68485L, + 0x225798677e7d0a4dL,0xd2d702a94c3eef8cL,0xdaba503869a83e29L } }, + /* 64 << 140 */ + { { 0x082ea61d10eeed24L,0x7c9d5ade143fd59dL,0x7d33df962e54f5cfL, + 0x340b0d36e39dc6abL,0xd97a8b848d179b13L,0x88184bb0288d388cL }, + { 0x2237e507e116ae6dL,0x3e97b063211b2cf0L,0x645f8bcb42be7459L, + 0xce2b0f54de2176b6L,0xaf570a09d1e2f09cL,0x110adf5657fdc001L } }, + /* 0 << 147 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 147 */ + { { 0x158bfe27bcb6db29L,0x967212410054d963L,0xf07b153b8e71aca1L, + 0x5e67698171b11643L,0x77b7dd7dd04e2f90L,0x07814aa6f0dcf109L }, + { 0xd3bab2a4fe1d0b1eL,0x50abba31be69e691L,0x54fe99afc6f53cd9L, + 0x071f2a4f628039e4L,0xf1f44181b183aa16L,0xdf0138e05010f6f9L } }, + /* 2 << 147 */ + { { 0xb1e365019c77ca60L,0xfe084a2301018e14L,0xbf451d2ca4bfdcecL, + 0xd210892fb29cdcfeL,0x5b12bcd894514871L,0xd03ca18c1809b1e3L }, + { 0x09b243115858e4eaL,0x37b30d50e57524b4L,0xcef0a16b5de334b5L, + 0xfe0bd1e20b116076L,0x54e4b48289ae2bf4L,0xfbcc5e1a68c8a937L } }, + /* 3 << 147 */ + { { 0xa5023e1364be0f56L,0x6a7310e00046f45cL,0xe0af09aeec8700d3L, + 0xdea5fb7ceb2d38f0L,0xc038eae6859852e6L,0xd515fb4c8c34f04cL }, + { 0x546b778e1488c207L,0x8cf4f1146258d8baL,0x474e60d85182c96cL, + 0xcd0387303dbde757L,0x387232f876ab01ffL,0x277614f628231392L } }, + /* 4 << 147 */ + { { 0x309b1eb33ef5a413L,0xa7607981a81f43fbL,0x87c2b81ebf8a894cL, + 0x27a40bce0d293293L,0x7f4c315be4bf3714L,0x03fdc14e01236895L }, + { 0x319c88f8dff053feL,0x146bb448ea3fa121L,0xfcc2a05df0dd1380L, + 0xc8d55b024acba9faL,0x871358de5927313eL,0xfd1d81d317ce294aL } }, + /* 5 << 147 */ + { { 0xa135970c7361138aL,0xd67eddb5b7d50260L,0x313c6e9bc4d5311bL, + 0x4f503bf28423e5b4L,0x17dc4b6f44f3fe83L,0x15b7bdb9ccf1bbcdL }, + { 0x0ce4d64ea11b9896L,0x050b0edebbb6b0eaL,0x85531293bf5db990L, + 0x9db3b964520d095eL,0xb45ec235bd2d4e88L,0xf88a9e6215ee5ba1L } }, + /* 6 << 147 */ + { { 0x10777189c1a21254L,0x7d8d3966ca593a6cL,0x261ab515120380e6L, + 0x453c858fe13577d1L,0xb1f6bb58f3862db1L,0xf8ff48b8b9529e1cL }, + { 0x03f63a417b60b400L,0xdc248d96bba66b3bL,0x8423048b756e5af2L, + 0x4d978ed31c984befL,0xa06242995ba00f3eL,0x0bed7b454f4d19e7L } }, + /* 7 << 147 */ + { { 0x9ef52e3d6524f389L,0xc5b157c5f6ac19eeL,0xdca7a72ab5d42f7aL, + 0x2d2e8d72fa0051dbL,0x3a6ff9243f4a4f60L,0x0ae997af340e7977L }, + { 0x33dd395e269db4e9L,0xf95c3683616b9dc3L,0xb86a066122d516a7L, + 0xd50c582cad913df8L,0xac8b8efef550afbfL,0xf34fcab01d88728cL } }, + /* 8 << 147 */ + { { 0xd3797831ff63ae69L,0xa753de02ce4c7eafL,0x2ff7a6a611a4e339L, + 0x904f86f05328043aL,0xe29d31c012e9f7ddL,0x8825a639c0a51904L }, + { 0x070c2696ebfc2cc7L,0xc03ce643c5f7a943L,0x5b970d0c12c8a1f5L, + 0x572aaaa1ab352a83L,0x63df45a90c5eb0c7L,0x95c951e1d4977599L } }, + /* 9 << 147 */ + { { 0xf5aefd5572ba3741L,0x7ab81965f5fe816dL,0x597d15d546752cefL, + 0xaa79a0822a3c142bL,0x038ddfdd3af5dfe9L,0x9f4dc166755c9e07L }, + { 0xf34224dfb9165297L,0x96e7ff6e4e3fd907L,0x5d7f3c821727beb6L, + 0x7098493dd6af73ceL,0x6b9358fbe00dfa4dL,0xefb2634a96e74870L } }, + /* 10 << 147 */ + { { 0xe35daffe2e4c6299L,0x1f9e33935915cd16L,0x93f05a40f009a48aL, + 0xa4a801fd308a81c6L,0x75e5dc467e885426L,0xf0bc7d5d4629ff05L }, + { 0x356b879bdbd812c2L,0xdb5eb60001629849L,0x11c9856eec2dd55aL, + 0x20f0443880f0c804L,0xc0b5e3e21801b217L,0x7ceba67d6ea097b8L } }, + /* 11 << 147 */ + { { 0x7a1bc5d85d08d3f0L,0x9ecce2a8385ef3a8L,0xae93d42b3c1b2927L, + 0x81a3a60719ce9447L,0x8d6b2d3d0eda597cL,0x5baabad60eea6dc5L }, + { 0x2cb372642741608aL,0x3b1148d6f0202a01L,0x6e85272f52931f5dL, + 0x49bf47596a2e601aL,0x5ec0418443279ddcL,0x7d052cac6ec080ddL } }, + /* 12 << 147 */ + { { 0x01c2df8d3bb02d0eL,0x874e43afe26f388dL,0xe198341c8360fa6aL, + 0xe67f8092c52bb2d6L,0xf944dc63a02efba5L,0x9a9c02d92c12332aL }, + { 0x39684f6ca8cb6bd5L,0xbcc1828e26bc9535L,0xb7fb8eb646594725L, + 0xbb4f5f05793c32ddL,0x3ef3c33845f94b55L,0x228e0e7d09eac277L } }, + /* 13 << 147 */ + { { 0x80d9bd388aeae732L,0x2be676dccbeb6443L,0xef4d056bded9ad31L, + 0xc4fea44f349e5d0eL,0xb66c35d28d95db86L,0x210c3d4aae9f5d3aL }, + { 0x5c0c5b9c1582982bL,0x50a529be93aed9a4L,0x88f769a384c77818L, + 0xc0970b4269776a3eL,0xbf3e5ee022a1cad4L,0x705c0b29b80187eeL } }, + /* 14 << 147 */ + { { 0xefd26dca727cacdeL,0x6290fedb5fcdb147L,0x9f108a89e1830a96L, + 0x7e8e36813e039a02L,0x1747b3e9256fbb3bL,0x5aa0ebffabb3b2f1L }, + { 0xcac5818c9fbb9b49L,0x037d66114a94b74eL,0x4081fd4d7a548536L, + 0xfe2d8e79aa364507L,0xe86ce00ea81a5f81L,0x77b95e9477a9bdb4L } }, + /* 15 << 147 */ + { { 0x3eadfde5bf06a49eL,0xca88828b33787c62L,0xde6f765022070f63L, + 0xcb4e54dc438f649aL,0x24957c77169727d0L,0xa2e7781cdd2a92a3L }, + { 0x17a1d7ddc38885f4L,0xb75716717605c408L,0xfdbbcffc8a2323f5L, + 0x11666bd2c955456cL,0xf8b94fa2517f27f5L,0xe101927fee002499L } }, + /* 16 << 147 */ + { { 0x2c5b0e42bca07a42L,0xbe57f3597a0dffa1L,0xace485959aa90727L, + 0x32be886af658699bL,0xce75d6c6da3b18e6L,0x9d563e4f69caf667L }, + { 0xc17c66cf065eb772L,0xfbe123814df9f6efL,0xceb80041623db4efL, + 0xe75615b2c74762e1L,0xade8a5438671c52fL,0xb713c401cacaf2ecL } }, + /* 17 << 147 */ + { { 0xc740669ab01b20dcL,0xd873f3f1abecc3f3L,0x0d8290402db73d1cL, + 0x147aaafb99198d33L,0xca66e755d4e7d7e4L,0x8747298cb2cb752bL }, + { 0xd9d58d29c43762aaL,0xa3801a4a15e45d57L,0xa747fa3f454eaf2aL, + 0x26c79cdd0c067c77L,0xf15404cea24fe6b4L,0xe2add5ec77fec1c9L } }, + /* 18 << 147 */ + { { 0xc45064dbd71a7744L,0x1900bb8f04a6f3cbL,0xd592585a76c2dd6cL, + 0xabbbd6d862b95d26L,0xb0db482b1d2e180aL,0xf459430184c9dea5L }, + { 0xd30b162a6e5ec460L,0x90838e57e4b35476L,0xab4b7c80f9356687L, + 0x72c2c009719f347aL,0xd5d01fcf920d187dL,0x47426f1e0afe06abL } }, + /* 19 << 147 */ + { { 0xe6473aeaafb2f584L,0xd5395475c44ab7a2L,0xcba2c240bc27e864L, + 0x201735cc742c1c9bL,0x8cb4886951263febL,0xb52706ba4fd2cd5bL }, + { 0x028445755a2dec94L,0x978e79d6a4be7b6dL,0x5a68d8103c4742f8L, + 0x9c917f48b301ad64L,0xa6a7d5bd684a6ea6L,0x251d61327c978749L } }, + /* 20 << 147 */ + { { 0xdc7e39ee0ae2a7caL,0xcdd3c235e6b7dee9L,0xf9624c299368c8a3L, + 0x2086bc904b21951fL,0xf7990a1f57e0e6a3L,0xf170dd75e686da8cL }, + { 0x4a82719a06da9714L,0x3a78e35e24274685L,0x1c3965e1c67712f8L, + 0xc6c26eb62f164e3aL,0x1129a467381fb91fL,0x896022108443ffddL } }, + /* 21 << 147 */ + { { 0x25e561bd808c4ff9L,0x08c9f2758c0cf1c7L,0x9af6165b59599115L, + 0x59f06a4bb4b415f7L,0x3a9d8ca5236e2650L,0xc8fa3bc61b48ebdfL }, + { 0x5e1896193404846eL,0x6d1d803b378a5a46L,0x672fe2bab812d5dfL, + 0x3ec27a7f04c6ddc1L,0x9c5ff08c0cee3357L,0x9f465babae8d37d3L } }, + /* 22 << 147 */ + { { 0x0057f60756a0b6bbL,0x46a6e9949c1e24daL,0x1c283f859baaf618L, + 0xd75e731be878a354L,0xf9db13388bf2ca71L,0x0f14adeea9022f59L }, + { 0x309f04aa6c14666fL,0xe6cec2aa552d2da7L,0x9f27eaba218d8659L, + 0x9b3165d3c268561eL,0xc7e3afcb90ae19efL,0xb840170bcb329e68L } }, + /* 23 << 147 */ + { { 0xf6b9a32fab95aa95L,0x1a1e06c387e1c3c5L,0xcfb7ecc5317f1c2bL, + 0x12953ce7999d2bcdL,0xcaf5f0229e3c5a01L,0x0c9db571305ac94cL }, + { 0xa423d26cafbc860aL,0x82fbbd3dfe98409dL,0x455aa9926652ac17L, + 0x6916e7d6f9428029L,0xdcfbd65099822714L,0x5de152a13f3c72d2L } }, + /* 24 << 147 */ + { { 0xe6d039ef467eb167L,0xa7e0959d74696cf9L,0xf3a19b9d7078d8a0L, + 0x5d4ec99c07cdc6f6L,0x4842d0f98386eed8L,0x48f5ab80545fc0d5L }, + { 0x8906fc626d39c2f7L,0x1c050d691bf5366aL,0xac506c579f54d0d6L, + 0x9a356a6ef9e4b94cL,0x62632c5108a75e61L,0xfc1b9fa5c6951dc2L } }, + /* 25 << 147 */ + { { 0x84ba4069d034ec62L,0xd55b42f6f169349eL,0x78dce88d17de2b22L, + 0xdadae679204ec730L,0xfad5ec6b5357f5e5L,0x330bba18ccc0d0afL }, + { 0x8419755c4a566c71L,0x29c56c5fbfe57083L,0xe42a7c52598cad77L, + 0x9d81623f5fcf1dc0L,0x978eb12864615869L,0xc837262a9c2a6f35L } }, + /* 26 << 147 */ + { { 0x917747f99ee0628bL,0x5d711303566cf048L,0x206d53f15b77f58dL, + 0xe104bc12667a86ddL,0x158f8d253505380fL,0xf5b32ad4616e821eL }, + { 0xdb67191a3cdfe797L,0x61b58589147e1756L,0xb7927e12625d0efcL, + 0x48d999d008bca937L,0x335c6f5b7b02689bL,0x4f0994a9d8149b7eL } }, + /* 27 << 147 */ + { { 0xe7ba0870df6ae3beL,0x661373f0166cd7d9L,0x369d361d8627f3fcL, + 0xca06d544cf6ceb36L,0xc819e0ea34b5d425L,0x80c1ab716ffd2827L }, + { 0x3fb8c0b520b4161cL,0x3647e67b3734b87eL,0x9c3a14b203e6c9cbL, + 0x320ed1c1c3620486L,0x6d77d46b5286a22fL,0xbd6036c1bc74a266L } }, + /* 28 << 147 */ + { { 0x125951a52e6d5433L,0x7d672aee6a6013d4L,0x6ed23f2560831997L, + 0xb0e219ae438c75c3L,0x6851dd4bace91d00L,0x84704f7d30f19991L }, + { 0xd744cb32d0107170L,0x15f51a63b0cb6796L,0xe14712cf5a5807d8L, + 0xff89f0c5dbfd612cL,0x0c314718bd021483L,0xf9ccd3b11b4b76d5L } }, + /* 29 << 147 */ + { { 0x36121d0909b6398fL,0xd9ad591369069016L,0xd3a08c8469cdcfebL, + 0xd92ae9b2b03e1e4cL,0x1620c549e9b6284bL,0x5860431227ab9432L }, + { 0x4e1d3134aa314da8L,0x89207aad70910cbcL,0xacee236badff9190L, + 0xe6390f7cf6eb6df2L,0x0dfc5a5cffa91d75L,0x3474104aa0e7f48dL } }, + /* 30 << 147 */ + { { 0x00b75b851871749cL,0x063b748ea00faa20L,0xa516e09f90257503L, + 0x9ffc43981c800098L,0x49f011f871b00fa1L,0x6fc80517443268bfL }, + { 0x2802e2bf24a24acaL,0x96fdc71edde88ab9L,0xe3eff1f997e661a4L, + 0xae5c34e13cb321f8L,0xf863263e301c8ba0L,0x3c3eeb7b093e186cL } }, + /* 31 << 147 */ + { { 0xc0f51229e7aa3325L,0x3abde561fa93ec80L,0xd7e5317f4e6df2b2L, + 0x4eefcc76bc832652L,0x9dce52905d054a1dL,0xee2939da2a6f52e2L }, + { 0x8faa1d3e092b5422L,0x77f55f7f9ca6338cL,0x6dadad8f6546d37aL, + 0x0ef4922ef3bf7cb1L,0xfcf41c23200ccc57L,0x591e208362aa0372L } }, + /* 32 << 147 */ + { { 0xa933aaf7a4886619L,0x9ec1915f4af13c7fL,0x25a9dff8854de496L, + 0xa8b31d9b247bec15L,0x468a25c84661e58dL,0x8989c046786a0707L }, + { 0x282db8cabb66922eL,0x73bf240d45ca29ffL,0xa2c40faaeaeda06eL, + 0x69632929add94b47L,0xc72354f6b0069076L,0x8d197fbf7878e92cL } }, + /* 33 << 147 */ + { { 0x7bd8195662267b63L,0x9352be73894a4ed8L,0x62568211d0bfdfdbL, + 0x7974999285698b05L,0x897ccd584412ea21L,0xe4cc4ddcb2f25225L }, + { 0x808539bdb4a1d924L,0x619fee34bdebf750L,0x47ed5b3473aea42aL, + 0x91e07a9b94ba376aL,0x218f6885edb27e08L,0x4feb09e6c4214344L } }, + /* 34 << 147 */ + { { 0x24bf9fbbf3e4bc93L,0x8973b72471151bfcL,0x8e33b753a85eb707L, + 0x13eba76e50adc461L,0xe445e8e144dd9d2fL,0x8729ec22b1592a0fL }, + { 0x9a13bf315ec24808L,0xe6ae840c2e95cabbL,0x634f3416e28cdf4aL, + 0x34d3349b9278cd7bL,0xd74990c542b912b5L,0xaf94b104b2430c71L } }, + /* 35 << 147 */ + { { 0x6d26cd01580b15a5L,0x5af25c06dcd849aaL,0x05b00800ffef39f8L, + 0x8cc59e06f9e0208bL,0x920f69540bc19bf9L,0xc06c4df97faa5ddeL }, + { 0x9a26a3f4770351d4L,0xda015bd3443f40d9L,0x1afd829c740f1942L, + 0xb108a8a6566e6158L,0x118e50a9a35e5d37L,0x94cac90eab72a3b3L } }, + /* 36 << 147 */ + { { 0x01f7968e60cb465cL,0x4efeffb796e0af3aL,0x6f9016e7066ad6aaL, + 0xa8ae30e88743aa97L,0x7b77d3e0b7d55766L,0xe1773661c6b3fadeL }, + { 0xa52fa7bc88f5270bL,0x4de08cb39f7f811cL,0x6021536f9bc34254L, + 0x47bd18cf4068e3d2L,0xc91bc312ce16889dL,0x468659ea929b71f5L } }, + /* 37 << 147 */ + { { 0xa5a2a3b3225b532aL,0x5ed77864167f7874L,0x2b5d475037ae42d7L, + 0x9bd62f14433b243fL,0xe8dca1b2eea90992L,0x1ce44e53ef5e0624L }, + { 0xd92c7bf61d3d7173L,0x83c1e65424c19a94L,0x59dce036eafe8941L, + 0x23478c50d81014b0L,0xb89214bbe65a18e9L,0xf9fd325ea05d9fb6L } }, + /* 38 << 147 */ + { { 0x2c4bbee73965ed81L,0x58b6a8766c1a47beL,0x7c8d94f71a67dfabL, + 0x865c9e42ac6ae9e4L,0xa63a0e42a3114c18L,0x7432c6c92bcf8169L }, + { 0x1927723c7532bd7aL,0x20b75c7201e5781eL,0x1963e16919d57f9cL, + 0x05427a3cb10e3798L,0x31bbc661cebc82a9L,0xdd88383ac3862997L } }, + /* 39 << 147 */ + { { 0xa0ef513d4adce457L,0x942aea7df9f906d8L,0xe52a2bb5fe22c5a3L, + 0xfd9fff1f8dec9ca1L,0x19b0e7a27913f99aL,0x58c45dd205660e97L }, + { 0x6722c47ff06d3c2dL,0xe4927a002a4d127fL,0xdc647c1ef40f46a1L, + 0x538c8cda7ab7a21bL,0x90227d6cc8015ae8L,0xe62f52dc2d4ec8a5L } }, + /* 40 << 147 */ + { { 0x69a9ebd8a83bbb88L,0xcbab0b5a29f98875L,0x325e487e4e7611f0L, + 0x90aa24b1d955cc3bL,0x840e70a13c264d53L,0x15bcf88bad7f4f81L }, + { 0xe47552cc2cf0df0aL,0xcb99973379205ea9L,0x25dc58bd10d5ca45L, + 0x0947d7151228b978L,0x9a0204da4f2c7c4aL,0x4377ea4a4690052cL } }, + /* 41 << 147 */ + { { 0x35da16d16bc7d7afL,0x098c4b0271de4ac2L,0xdaa2407c3655dd94L, + 0x5136884c90380d70L,0x3f47052e762f61abL,0xf715107a8dcd6ddfL }, + { 0x862a4a6e5d76615aL,0x2b546e1b2128a6f9L,0x5297a3cf40490672L, + 0xef2cbdf1b9c765a6L,0x52e71cb4426562baL,0x34d0e3237a84f9b1L } }, + /* 42 << 147 */ + { { 0x6cd4098d74e7c67bL,0x3bf4193123d2b418L,0x598710ad682135ccL, + 0x26ccbfe0172d648cL,0x0c4918c5d84dc9afL,0x346e8b6385065417L }, + { 0xcbc7f2efd353219fL,0x93637eea3c4e4863L,0xb18fc69c2dbbd39bL, + 0x20614dd45a4b5b0cL,0xcdac0383547adce3L,0xedcdd64842ac8be3L } }, + /* 43 << 147 */ + { { 0x76ac6c94b4559439L,0x09090af620319667L,0xef433d73a742e3beL, + 0xb7ec99eb7cbd7090L,0xcde2579dcb782be1L,0x2a2fb807e75552fcL }, + { 0x083f9e982f1eee15L,0xe20f65c167779c98L,0x73c044ff5f23e998L, + 0x5fce594269488208L,0x3e4ca86ccace7ba3L,0x5e3f43b8f32c1acaL } }, + /* 44 << 147 */ + { { 0x3ab171a237b42b60L,0x6501afcc4f20e50dL,0x4f9e22413e3a4298L, + 0x3c5834d9be3b3d3cL,0x9607b8cb9be25af0L,0xcc5f6b6f81c723a5L }, + { 0x11b9b5d199227bacL,0x2bc5dd9f322cc499L,0x0c3884a0cdbc3a55L, + 0x018a8ebefd4f004aL,0xa858ee7ce08741d9L,0xb5bbfa2b5d69b3ffL } }, + /* 45 << 147 */ + { { 0x57069b4a1b0611b3L,0x24b5421c89da55d7L,0x6433c29dcf9b2fb2L, + 0xda9382c67869a1cdL,0x67fbb7a343514903L,0xb3429e35e8b224f8L }, + { 0x4058ef1e7ac51191L,0x56283b0cfd4e6114L,0x4eff0caca16fadd1L, + 0xe6088db7b6ee634eL,0x94e68bd0ca7bd1b7L,0x0e98796b965ff86eL } }, + /* 46 << 147 */ + { { 0xf3176014bbd74a95L,0x5dfe36b51bc6c763L,0x4c463aa27d3d0366L, + 0xcbd7106cff3b113bL,0x2d660f5a0b6edee3L,0x92d79c864db04c30L }, + { 0xfd1067cfd2236e55L,0x1ae21f2d90925a83L,0x8419072ca952c451L, + 0x2f268b473d946980L,0x04831991b709ab5aL,0x0d622a70bf72efd6L } }, + /* 47 << 147 */ + { { 0xec468aecf0440b85L,0xaae6041369cea78eL,0x5a88145d12a30f40L, + 0x438c6e3f37a52bfcL,0x41bf603894749b6eL,0x3d38b86267edc2d1L }, + { 0xe379125a020a32abL,0x68a6b13a198c3944L,0xed1fb3258be252d2L, + 0x76dc8df6e15c37cfL,0x5a6592cb6453b542L,0x372b1998b3347c65L } }, + /* 48 << 147 */ + { { 0x015c325eb8e79179L,0xf4fc61335b57dce6L,0x27a51e5d78d6858fL, + 0x13babcab4dd5f180L,0xfaa19cb1847e499eL,0xe2688ae608aaea61L }, + { 0xe20d7edce86100d5L,0xa9b0d46bed2fedacL,0x5e99cc0c1d357dedL, + 0x4c1263ab723cac89L,0xad5f3e6ff15e22f4L,0xf25f3950d77dae65L } }, + /* 49 << 147 */ + { { 0xf3814fdba1c6fb06L,0xbfde395d8d71559aL,0x6e4b2b1c07e00f72L, + 0xac0d1aef1e12b111L,0xa4041ea0387dc52cL,0x8004ef4893c80d7dL }, + { 0xb311b5c29a770d6eL,0xd4a340bbaf41a540L,0xe96d1dbd9a5391ccL, + 0xcd4b19fb45ebf6ffL,0x142556a5dcb6dbe8L,0xf68968ff092f898aL } }, + /* 50 << 147 */ + { { 0x540a2e35c854356eL,0x6d0eab45f5002153L,0xb8f542bd9a6c488cL, + 0xd572d282c6201f12L,0x260bc62781a3eedaL,0x508621af06eaa5beL }, + { 0x754eeb205eadc8d5L,0xfe33248f42d4b0dbL,0xf44a1c7ac5529222L, + 0x9079ccb574396eeeL,0x6c4bc87db9cbdc41L,0x1ee8982431ee3f18L } }, + /* 51 << 147 */ + { { 0xb64fc90ed811f25aL,0x310214a2c82c8f68L,0xee559209b5052420L, + 0x6055c5b45c1bf95eL,0x414f7c8dedce3bc7L,0xd3438b8a66d3cfb4L }, + { 0x687b9f70d3935eeeL,0x553b15ddd3e179f1L,0xccc9961e21ff232bL, + 0x3729ac207d322041L,0xf1537630094907c9L,0x3e87f4f903153dccL } }, + /* 52 << 147 */ + { { 0x2c21e48c7dae4b17L,0xe842930a07ca1575L,0x3a3d6d361cc47ab4L, + 0x749dba405fcd07bcL,0x55a538a6f306a498L,0xe85c60be633d42bcL }, + { 0x777595f2dafa94a7L,0x1c690529a0400ef6L,0x41485f886bfa23bbL, + 0xdead14a1256d9204L,0x74f1a820bbda2f9fL,0xc86554f65fe54284L } }, + /* 53 << 147 */ + { { 0x03ee764b978ad2dbL,0xec253b0f01c9282dL,0x028e7873fb26c425L, + 0x3e1da0436504ba10L,0x68369881531961f1L,0x0365ea56ee435146L }, + { 0xf5505ae80c00a6b4L,0xc1ac097403f34fe3L,0x7327b391b5922f68L, + 0xe561cedd1845ef9bL,0xaa82258c6a44b29dL,0x23e39cedc4d56159L } }, + /* 54 << 147 */ + { { 0xf5a07dedd14a3ce3L,0xeda454ec9c47615fL,0x01d6b1562775730fL, + 0x3ec02f95fe4d93f4L,0x335806e4dcbd0ceaL,0x3f498d1b51a19d96L }, + { 0x9949c853374b7210L,0xb255d34b25980320L,0x3b681db4307b513eL, + 0x4137053add10a78aL,0xd9c0f2728dcaae0cL,0xcbeb6b7216031955L } }, + /* 55 << 147 */ + { { 0xd1b13e72c709af4cL,0xb4b99796c12f27fcL,0x9e56569a05e2c06eL, + 0xd8c880631212ba12L,0x8da1a6704e7f8fe4L,0x3bbb314f875bb39eL }, + { 0xc56ef7088fbc8a3fL,0x39b3cef2300d21bbL,0x5e755398458e347eL, + 0x9f7b84b16c1b2162L,0x278ffd26b08d0c52L,0x7c8a442a9ec7febfL } }, + /* 56 << 147 */ + { { 0x3c0e2b9737e8e6b2L,0xa2037913575da8b7L,0xeedf0a75b925cbb2L, + 0x4f28ec1bc561b405L,0x368fb2742901931cL,0x52b54eee2f26221fL }, + { 0x381845b6247812a9L,0xf9bcc9619115a0dfL,0xef127dfecb84d25bL, + 0x4256afe5fa10e0a7L,0x0c08a532353a15ebL,0xbbd15b176a91e61eL } }, + /* 57 << 147 */ + { { 0x3c573b2655574ae4L,0xd3f12e8f2c0be823L,0x5954b69fde9ce60eL, + 0xc433991bcedfd1eaL,0x35696716718e950bL,0xce4318664e9cc107L }, + { 0xee16b6347359991cL,0x8f05851b1818a113L,0x257a228c3b494b59L, + 0x4239f98e156f91f6L,0x2382157c72efdcc4L,0xc82b652cff7b7ac1L } }, + /* 58 << 147 */ + { { 0x072eee036b7a9a38L,0x42a680cbaef9b327L,0x67311eb8b56fb35eL, + 0xf320acf3c7de3776L,0x09c89cc3ed15e895L,0x368501713232345cL }, + { 0x5a5fe1104822f90eL,0x64f7ef18c6077b89L,0xbbc5748c8bdfb971L, + 0xdf5488334b6209deL,0x02268bf676e7f595L,0x1c7971b447779e75L } }, + /* 59 << 147 */ + { { 0x90d308b495c9497fL,0x277535b782c903f6L,0x443cd37fc5d7b4c3L, + 0x48ebf0acfcaff8a7L,0x8ee8c79e579f25f6L,0xb825ccd8360ffd90L }, + { 0x6327be1599fe4be2L,0xc94c68cf59ec2909L,0x0dbf8d4456660ce7L, + 0xbb31989b5d510edaL,0x43c8c365c4a2e601L,0x100de78314dcf793L } }, + /* 60 << 147 */ + { { 0x635ee0f3d33ac52aL,0x609c328dd1970e1aL,0xf28ddf0a09426902L, + 0x2a94d4decbbcbbe8L,0x15890cf4ab7ecf5cL,0xb14a405df2dd4135L }, + { 0x64659a4fa6d01554L,0x1d1b2c43cc966f9bL,0xb02ee871df0e48b3L, + 0x0bd13e47f4dc3ebaL,0xb4763547bb4fc529L,0x868650044068ab72L } }, + /* 61 << 147 */ + { { 0xe3d60dfac22bda56L,0x021411ba6be2f502L,0xc1dd4d55b35e750fL, + 0x708b62cd4d5e1648L,0x234a80c6347b8b8dL,0x53b6fa80f3ba912dL }, + { 0x4041b8007b92c92bL,0x636c12524b6dbceaL,0x4ea250d08a1aa141L, + 0x9ffa7e35a2ae7be0L,0x765c809cd2844e61L,0x5bcabd922d56de12L } }, + /* 62 << 147 */ + { { 0x48d594e522205fbdL,0x79c78f1c0862eb11L,0x02a3becdf7798099L, + 0xbfe574a8b1ef2ae5L,0x1bfb7779c4781f34L,0x7211dfcf044da23cL }, + { 0xe4c3fd7dc3686ef9L,0x14c6e5b5e74210f7L,0xc40a0a0275ab746fL, + 0xd2033594621f6369L,0x6bdbbe3d66241d44L,0x014b089ee47f00e9L } }, + /* 63 << 147 */ + { { 0x93e3a89108e65849L,0xf90a376ba1a712fcL,0x6555d6dff1a48fcdL, + 0x984ec5c86a763e90L,0x7a7fe565e55d6b14L,0x12550fe809b2e8b7L }, + { 0x21736c048e41210eL,0x72ae44d448ce08f6L,0x02755a2871fecc50L, + 0x379da24beb485ee5L,0x394cb7ba66d7b659L,0x49fc9d60ab638c33L } }, + /* 64 << 147 */ + { { 0x854b05846150771aL,0x35fdd9b4d9ca9868L,0xec8293894c32fc71L, + 0x882fad4c9ec8f90dL,0x2d39990dc6c7b9c0L,0x7fbc201bd71a25e5L }, + { 0x6b852e655166da7dL,0xc6bde23a3d8c6e36L,0x370011545857f048L, + 0x746621fc1ccb9bc8L,0x97e44e63612bb853L,0xabc3b450758da4edL } }, + /* 0 << 154 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 154 */ + { { 0xd25f650804926a41L,0x7236b475514045daL,0x0b36031108b9b08bL, + 0x16477aff3fe92e91L,0x6e5f6cb103189ddcL,0x81ff008ec698a38fL }, + { 0x02a09218c93adb23L,0x71fcecd3445d8faeL,0x55a15eac8fd6b76cL, + 0x1e37ec3611ef96b4L,0xd1b3b3fc30e433b5L,0x4951873351d174c3L } }, + /* 2 << 154 */ + { { 0x7914213db8c9f82eL,0x7a3e4e38fc038e90L,0x6edae5a126a34238L, + 0xe566bf50701ce8c7L,0x3562e87555656e02L,0x48325ebfb4e8efbfL }, + { 0x5f10a50466505ec3L,0xd8b9834b8da78aecL,0x49d1fc25cc2f2e40L, + 0xe973bb1caf5718c1L,0x9b8825dad2d6b890L,0x7de7885ee2f00f12L } }, + /* 3 << 154 */ + { { 0xfb0fa0e6494fe64fL,0x4ea468b59a907f37L,0x9bb6d672cbabb7ccL, + 0x523c7c6ea5be2b38L,0x4065adbb361c2e41L,0xffa1299925c13172L }, + { 0x0eb29793f80d5e2dL,0x862fe1ae8e4efeffL,0xd485483e948895c4L, + 0x513977300d80d5bfL,0xb4731ffc348782f2L,0x42543c76e1a7f6aaL } }, + /* 4 << 154 */ + { { 0xe37211be7ef79898L,0xa810387721344d16L,0xfdcd7e26a1b9f8b4L, + 0x5641e45d7d7f72d5L,0x5377c1bec449c920L,0xd3edcb0cefc7b2a1L }, + { 0xc657a9ffe14b42fcL,0xc8f858c800831b07L,0x6bfcd1bcd020eaa8L, + 0x17534b0a3f6860c7L,0x8ce5722284c7c806L,0xa1d40eaf2bd7456bL } }, + /* 5 << 154 */ + { { 0x28b88cbb1a7093caL,0x09275152080a85ebL,0x0bee7d979c1dcc32L, + 0x43698f5f5ed033a5L,0x4f142867b0f0acc1L,0x6e6202ecf62960deL }, + { 0xe95a607ff005b671L,0xfeee8ea060cae478L,0x456bb6e90e8ec6e5L, + 0xc1c0319a9d088a59L,0x29c6898bbe3d2379L,0xd7049b2af8a8628fL } }, + /* 6 << 154 */ + { { 0xe0c93007c9aa57eeL,0xebb2d47b8895a604L,0xb8aebc49c4fd6ffeL, + 0x2c06e1e573f300b6L,0xa019070d81628b8bL,0x2db1690bbaf8c1eaL }, + { 0xb3fce6c8cc94ccd2L,0xf301463885bcdf4fL,0xb1e62616e2f82c32L, + 0x85581e2468295a54L,0x0f2e2ff5bf51f8faL,0x940716f1155c1f6fL } }, + /* 7 << 154 */ + { { 0x15b2dd270c6bd5f1L,0x07b5bd91eb086d0eL,0xe701742e97c5f5caL, + 0x3ce5f3f6eea06ea6L,0x51a81a6aa9cee784L,0x2bd404c1c7182fa7L }, + { 0x27deca74d5b8bde4L,0x2c1931c595385e4aL,0x04fcb34e3a79d65fL, + 0xdf3357edad1babceL,0x8bc628ffa31af476L,0x42ce1d91e5cc9e78L } }, + /* 8 << 154 */ + { { 0xaed02b6b4e623856L,0x7a6d2bef3e1d74cbL,0x82226ec4654e7c30L, + 0x008ac003e7034bfdL,0xe343c5407fd6b555L,0xca1b29071b429d44L }, + { 0xe0702a339c3ceea2L,0x48079aa9732694c3L,0x7e6d72f6d4652401L, + 0xd92655ed35f60043L,0xa0dbaac6273e8cc4L,0x0bb8f0f93c3ffb40L } }, + /* 9 << 154 */ + { { 0xc3134781a91940b2L,0x37579fc9e9b90620L,0xa506227a08acd6f1L, + 0x603ecce0270da73cL,0x8a53b67d7fdd70cfL,0xe29b7df299640bd6L }, + { 0x7bb4fa877569105dL,0x6ee80ae8567bb5e9L,0xf394bd02baccabefL, + 0xe854b3a6309c944fL,0x1271a131f06246e9L,0xbc1c205531580147L } }, + /* 10 << 154 */ + { { 0xb41b87b6c95cd23bL,0xb99714ba55e371a4L,0xb138ee8f6f571cebL, + 0x09c42be480146ec7L,0x275ee21eee9aa125L,0x0cef4d6f3a878b59L }, + { 0xd436eb1ca801068dL,0xe2c5448c762b8a80L,0x243beee1f3640ecaL, + 0xf979458b32bbba7aL,0x6bc26cfea63407d3L,0xd3b6e132392dd1d3L } }, + /* 11 << 154 */ + { { 0x123ae65005d0072fL,0x9f101624f0656bbeL,0x762bd4f4344e283fL, + 0xd1f70d5161b6863bL,0xcd99382592ef9a38L,0x53aaa0c3ac2bf9bbL }, + { 0x13904fb521ef9a43L,0x0470a8ba2beb8f44L,0xf3733943fcfe9ecdL, + 0x10b8881a79d776dcL,0x89b94c67b82b7139L,0x7af5147aeb962922L } }, + /* 12 << 154 */ + { { 0xbc06ecab3de4ba2eL,0xf51ca0639e491bcdL,0xa6fc6fa0453c94beL, + 0x5460f943ed1a6731L,0xeb11656a4ec3f1fbL,0x2fcb2cabff1e7d4eL }, + { 0x595264678fea2286L,0x838117a34e0bee38L,0x7bdf588824fd2ce5L, + 0x13df0c839f2c2925L,0x1bf621e6dee97f30L,0xb43b2558ebea6641L } }, + /* 13 << 154 */ + { { 0xf49a97d80a33b97cL,0x4e68d71512ab9bcaL,0xc0d361c04bdb65a3L, + 0x5fba9fb86cfb0cafL,0x222e12ca2a716589L,0xaea01502731f5099L }, + { 0xf322ddf7e97b37f1L,0x050e82a5e55c844dL,0x01ef972ba11d664bL, + 0xab30502882c737b6L,0x43aa811185e39769L,0x766a9350937c1456L } }, + /* 14 << 154 */ + { { 0x246c86608e729329L,0x39fcc41dd693dac8L,0x48a65b54c062a6c0L, + 0x368a57706a5a3101L,0xd143600f47ed1988L,0x48466d92a764ce3dL }, + { 0xb05006135a22cb6bL,0xf1d77247edea070cL,0xb1ddd151617f2464L, + 0x7905069828b83fd9L,0x021abb26d70bf93eL,0x590b3c42ab5a5e1eL } }, + /* 15 << 154 */ + { { 0xe86c737b728b8438L,0x21f45a22acf1dd66L,0x6f29f2d7abd4de3cL, + 0xa223154576d4435eL,0xad902927f5fcafadL,0x272cceeb04f30557L }, + { 0xc2e4e0017ebbb2d6L,0x73954580bb873ec3L,0xadf5ec7ac7fa9088L, + 0xc036da0464006dd7L,0x9c3545b5e8274f69L,0x6e153c2552325f50L } }, + /* 16 << 154 */ + { { 0x5906a35c1cfb991fL,0xb62a4f80740a7744L,0x65c8ac9136f84763L, + 0xf73b3debbe0f1dd3L,0x40358868a2d26c21L,0xd907e90a76792ae7L }, + { 0x3ecea167668c3d5fL,0x731068f26754b49cL,0x6db891090e006243L, + 0xd29106e6dd94681bL,0xb40b8694a85a3de2L,0xc80c7bf1936b86ccL } }, + /* 17 << 154 */ + { { 0xd735de6b91f7c76aL,0xd89aa1d4b054837aL,0x47c1a397271e94c4L, + 0x8d91f3f9dcb7c071L,0x4cf9be2db4cc209dL,0x4fb6842ec08190d4L }, + { 0x926423a1d7b2aaedL,0x5bbfc08957a1cb44L,0x44438c56021defb3L, + 0x8b9a2b1ba09863cfL,0xc9d5c170e37e339fL,0xa8994d5dabb18c7aL } }, + /* 18 << 154 */ + { { 0x003d45d011913575L,0x866cb2dd87e1186bL,0x692f630146b69a22L, + 0xd296a55c8174c1d1L,0x77ef6fbe9f17af00L,0x6b588be93aa922e1L }, + { 0x99ecb44f033e6dd7L,0x32edea2c1d22b7cdL,0x3122b027ba7006f3L, + 0x8950054bbb6ebc5cL,0x4f6d606182dab805L,0xc12055181bae5f1bL } }, + /* 19 << 154 */ + { { 0xeca71515ad7edd2dL,0x3f9c330e9bf56567L,0xd0b62d6749104bb1L, + 0xde92596410cc8d89L,0xc7a083f4287fc898L,0x8ba176e712d15d2bL }, + { 0x2cee62f7b4c8c4c1L,0xc15966c2ef79aeb2L,0x9b449522427c11a6L, + 0xcc850028eb49b2fcL,0x0966a06d3a22720dL,0xfd511944a1e78c8dL } }, + /* 20 << 154 */ + { { 0x28d33e79e08c180fL,0x768c7794f6aec9ceL,0x5a749f3bce683c5bL, + 0x717629d98371fe75L,0x5e828fc057712c1dL,0xb46c6ed17e4c61aaL }, + { 0x5d927bad5bccf95cL,0x55d6fc80d72f68ecL,0x560a99a398591dc2L, + 0xc885fe8a4836664cL,0xd18acd4226d79298L,0x05e4cd17185df1d7L } }, + /* 21 << 154 */ + { { 0x9c1e5db3ab34fbbeL,0x0d4b1e742f7eaa94L,0x106b0b5c86de1289L, + 0xd2c6c1aab691a830L,0x2e55cff9b9717593L,0x4522b37d075e5e95L }, + { 0xc6ee67ea3abfeb96L,0x35844bbd890b04eaL,0x0246545a55d6f65bL, + 0xc66bad2b13594e25L,0xaff4c6b35d6aa7d1L,0xebb7d2b5a3f42a84L } }, + /* 22 << 154 */ + { { 0xebc60e21fcc83355L,0xc94dbc02d9119b77L,0xceb05a312f18ae9aL, + 0xa8462962b8f69016L,0x58dde5a48f67b5f4L,0xb8bdf9c9af3c234dL }, + { 0xe95c069f80e85df8L,0x9d525e1bab3aa0e5L,0x73c8a92f76276d8bL, + 0x7feb4abd163530efL,0x8ca949b35ef5ad73L,0xe129431e2e3d057bL } }, + /* 23 << 154 */ + { { 0xa263d726c129d188L,0x89da948e9d526adbL,0xc7319a5a6b8a9149L, + 0xd85d382d8816f421L,0xfad69eb1844032eaL,0xf668901a4233122fL }, + { 0x246cc0de210ddea0L,0x26d8ccb70bc07dbaL,0xfc1b558470e6708cL, + 0x853802b775fa0b44L,0x215ccb88bb75a5b2L,0xff50f0cf24e60054L } }, + /* 24 << 154 */ + { { 0x9d8a925b60dec308L,0xb72e3efa6b3ea363L,0x4f53ca6ddfb534b8L, + 0x4e64874c6dd78a32L,0x336e5b46c2a146d5L,0x07c76d6398395201L }, + { 0xa4c095228fe3e815L,0x887e659d3221cc26L,0x0ff92f64c36286ecL, + 0x57b1b903c3ebb08cL,0xc6bdc9b665f00c30L,0x826242269a46d36eL } }, + /* 25 << 154 */ + { { 0xe054597768bbf4f6L,0x17bb77edb6e2cc19L,0x0cc551d89ae950f7L, + 0x3490778d761763a4L,0x1c36044a32647ceeL,0xa6e083223f9d2938L }, + { 0xea392a153a656a51L,0x4d51161ba083cb54L,0x15c01e792c690757L, + 0xc7bf5d7c5cc62636L,0x1b00cddab2ccd76aL,0x68f49fa995313f8cL } }, + /* 26 << 154 */ + { { 0xc782c16c1a0b619aL,0x8643d42bbe316086L,0x49d2966bc0daa421L, + 0x080b1cafb7b487e0L,0x1d33bb53144de273L,0x8bafce2d6faf7ed9L }, + { 0xdafbe3cf408d4636L,0xf10527df7ee8835bL,0xe1123f3ee2e75522L, + 0xb388c64bebe27d60L,0x2cb38dc1e3f1f55eL,0x57ff8e43e34524d8L } }, + /* 27 << 154 */ + { { 0x557dc1cbea28398bL,0x34d5709a208996b9L,0x94470993e97a3306L, + 0x0343320772b117f3L,0x66c4e442f056525fL,0x27753c526d11dd35L }, + { 0xf0aa7658b26a70d7L,0x95608b19543cd7ebL,0x618b2e17bac19156L, + 0xe7e42948cae64ba1L,0x2016a9d59657ec93L,0xa38f67e03d7ea46cL } }, + /* 28 << 154 */ + { { 0xd67dc92b85653dc8L,0x8e0970af0bc93ab9L,0xb6f09baa8b87c0afL, + 0x5a8a903052760ef4L,0x2e2ae7561047bf85L,0xd049078f85bd4e74L }, + { 0xced11ff83729f708L,0xdd21cbebd91068a6L,0x83d488ff24b3e911L, + 0x6e166fda1afd2196L,0x66a912114f0d2128L,0xd11078ed05c9f39cL } }, + /* 29 << 154 */ + { { 0x69aef6f919c64bddL,0xe7d4f909598ab592L,0x48952e280e55124fL, + 0x637693f6290b558bL,0x3afb2e7b421e60e9L,0x00d1dbac79aac8a9L }, + { 0x45156c5cc08563d5L,0x8cc201be4519c881L,0x2e36c0d7bd616581L, + 0x595fe0164ee16dffL,0xeebec40ae4889c65L,0x23b6dfd7d35b94e7L } }, + /* 30 << 154 */ + { { 0xd87003d3bdbdf0cfL,0xe9750b5b56c298f1L,0xc256c3a2b73ad05dL, + 0xe0779a192ee94279L,0x31d8b3c6279626a3L,0x469056bb90163bc8L }, + { 0xe6aeabc623755853L,0x9fffdfe2896a6f4cL,0x15c1ce78a36cf41bL, + 0xd4c8c025eee41941L,0xf7a917ee7653be9dL,0xfa3cba9659d52222L } }, + /* 31 << 154 */ + { { 0xa02f08586d8c610fL,0x9819c563ad4af3cfL,0x085d4439b95d17eaL, + 0x9df256ea616f532aL,0x5e9c5419cebd249cL,0xdd5ffbf451062a22L }, + { 0xb8910ea5c8b33577L,0x5e8b7ff7ff8e63d7L,0x5e4f3926b24e230dL, + 0x163eb51eacd851d7L,0x9bda95f2ea2aef8eL,0x3d6887755aefa290L } }, + /* 32 << 154 */ + { { 0x913f92075f8ab132L,0xd5b6792c5c14080fL,0xefab4e2c787c3594L, + 0xa55d465fe7b7b7ddL,0x921aaad834e28e6aL,0xc4f3a35e12d6a7bcL }, + { 0x109803c46115a5aeL,0xc023098ce709f9a1L,0x1a8c8bdb99c5bb66L, + 0x1cd1c2b6bc7c2da7L,0x50189c975f927eefL,0x493823d1229f9410L } }, + /* 33 << 154 */ + { { 0x34ec4dc840dedfb0L,0x1109ddb93aa89063L,0x93d9db278c218bb9L, + 0x07131b6e0b6007ddL,0xf90570ddcc4690f0L,0xa6a9a634afa26a59L }, + { 0xbd0c25194292e2b7L,0x92b99706a6d44b7eL,0x89481adf4942c03bL, + 0xff5e56b98a0c30d5L,0xdfd8939591c80fafL,0xed9d140840663594L } }, + /* 34 << 154 */ + { { 0xcc22db55c41e42fcL,0xc90ec77e4c9f2411L,0x419b9f46e4c02557L, + 0x156ed30ccee45c60L,0xf2c1340a72e4a938L,0x4a9cda8a204775a8L }, + { 0x900fd58713952b75L,0xa82ec2b812461145L,0x9f1875d41db68028L, + 0xaaa6af31308475acL,0xa11f379442d4b884L,0x1f1fcbe3d087882aL } }, + /* 35 << 154 */ + { { 0xa32d5a80a292fbecL,0xe0b10099d7091eabL,0xcb99bf7b4bfe6956L, + 0xfd806d4c61955461L,0x7124b1bf931066fdL,0x29fad019649ccbf7L }, + { 0xd1fe7911049609e7L,0xb568e167592f93c1L,0xabe7d10398ba066cL, + 0x0cd22c9668d7ac2cL,0x0ccd0c21427522d3L,0x97ba199ba503b4a4L } }, + /* 36 << 154 */ + { { 0xa0f2da0c78a2cbf7L,0xd1611acbd163d80dL,0x1af6ee1bf2cd3795L, + 0xc4993e08307d6105L,0x84c3b8f8560b5f12L,0x4f52c56347869733L }, + { 0x8fd9e3f728d28bc6L,0xdbf34576e5d44bd9L,0xf7e3a6da10d14cb5L, + 0xb93870990fe051ffL,0xf6363a48f15d43d5L,0x4bc358fcf434d1acL } }, + /* 37 << 154 */ + { { 0x35bac9471eae6dacL,0x4244697e39d6fe97L,0x16ec7f64fe017230L, + 0x393856d10493823cL,0x0782fbb55b7cbbfeL,0x4c399e3f5820f9f9L }, + { 0x86311cd9c08fe816L,0x057d4cbbc3ac958bL,0x63f09d484bdb0531L, + 0xab0b582b0b89ea02L,0x19c52243beb30331L,0xafa64f25ca87ff6dL } }, + /* 38 << 154 */ + { { 0x0d28a67859b1f4aaL,0x79b04589c52d40f4L,0x443b7fa5219303d9L, + 0x5be78d9663972eceL,0x0ccb969e7d984869L,0x7d8738077f81916fL }, + { 0x3502b3e426d9f292L,0xda1de7a82c90b612L,0x5605f5dc434f27c0L, + 0xa50d3328df89c616L,0x5a80cf84e7082731L,0x2c89e4b6f7ce953aL } }, + /* 39 << 154 */ + { { 0x7a46cd0d01fdf1e6L,0x86868e74e8690fbeL,0xf038771d8a8fc3b2L, + 0x30135b3084303d90L,0xa7ecb9ded562d20bL,0x7a6d1f37884cd233L }, + { 0xa30ca0bb07dfad3bL,0x1690d6018e09fa7fL,0xe582449f6c744551L, + 0x0b0030a21b935d17L,0x6b46681272bdb78cL,0xe40d4e5f56d4f328L } }, + /* 40 << 154 */ + { { 0xa29978fc62a8b8b4L,0x4cc216310fa130a9L,0xe4b51c6bf15e04c8L, + 0x453cf4d23f815420L,0x1257c751c6282b9dL,0xcd15b03c8af1af36L }, + { 0xe3596240514ef6e8L,0x72a6691708ab83d9L,0xca0a62d710e44b2dL, + 0xcde068128a9b8a8dL,0xd492b261ba470875L,0x5c7ea67cc6d7aeb8L } }, + /* 41 << 154 */ + { { 0x6acd945fc0995487L,0x06d5b2e47abac4fbL,0x42cddd75aaf3d12bL, + 0xca7d2363de1b9632L,0xbb1a1990dfbbb30fL,0xb0beb43139fd7bd4L }, + { 0x9ceb36884fa796e7L,0xb4d2bc4ba3266ab8L,0x79bda9d6e02df012L, + 0x414636bbf6faf7c4L,0x0a6603b9d1ab23f9L,0x2bc60c848db14f7bL } }, + /* 42 << 154 */ + { { 0x1b36ef27007ff90fL,0x394fe8095111399dL,0xaf4f246cb758e748L, + 0x794e4b151a7139a2L,0x40869a49eb527db3L,0xf2e15106f46d1b34L }, + { 0x46619f0352ac96e6L,0x40f556de49caf0c4L,0xa36b11d693072befL, + 0x871919b4ab2dad50L,0xf44b8084792dcefdL,0xe051823dbc31b021L } }, + /* 43 << 154 */ + { { 0x56293d8dcfd7432bL,0xdedf8dfd1d5f72c4L,0x743f4a71ae604fb4L, + 0xfb35ab43730caf7fL,0xcaacce6b20fc2167L,0x21ec3a0daa8ac71aL }, + { 0x4fdf5890c21ac9baL,0xbdc41ecfd6149328L,0xb1ac4d519b381c55L, + 0xc4cc08fd63f10a98L,0x2b9f0d3a4913a671L,0x9ce9949cbc36a952L } }, + /* 44 << 154 */ + { { 0x5049a7d3f758b1b2L,0x60beb74f14ab97b8L,0xdfc47828a9ff8ad3L, + 0x303a0cde8bb99766L,0x53f4b45a43b9a7a6L,0xe467aec8ca6e8c43L }, + { 0xb8e7db7b3f573855L,0x5fee5a5481e760f1L,0xe928b23385b0fed4L, + 0x72f02728ebae0b7cL,0xe32abf70bb5897d3L,0x103e8b859c572995L } }, + /* 45 << 154 */ + { { 0xf321278c2dc1a02cL,0x06ca03865dd09f91L,0x3c28640b7bac9e7aL, + 0xe3a7f9b527b1a011L,0x9137ad0407ccedd3L,0x3a2976a8cb6b447aL }, + { 0xab1c39248225c1ecL,0x30703f108f9022a8L,0x212f0f1bb0b2a64bL, + 0x76ad924b3e73862fL,0x47253a5c84842ac8L,0x33a03a17755af95eL } }, + /* 46 << 154 */ + { { 0x97c371fc5a274b61L,0xc7362cdbb14c680bL,0xa8cdd929efbd49afL, + 0xdfb2d5f075325f06L,0xf62d10e2b905531bL,0xbdfbfd8462ed0c3aL }, + { 0x252061599d07d2daL,0x1376775152491224L,0x165637057413313cL, + 0x642a7911a2b88eb1L,0x42d9dc6806ffe363L,0xe81d3403017bcc9fL } }, + /* 47 << 154 */ + { { 0xa68ce9db93d57f06L,0x4d1fa86a31dba07dL,0xf11603178c4822abL, + 0xc2243680633c26f5L,0x6b4e91cd10f1da80L,0x4358155734827d78L }, + { 0xbf54e87400c19817L,0xf52b94c4f2bad957L,0xcc85de8144e71756L, + 0x4f7d8ca365b7a8c2L,0xff76efa579d7c36eL,0x50a444025952932aL } }, + /* 48 << 154 */ + { { 0x87c0ef84172784bdL,0x023128267a5f2d07L,0xeae5c0cec9901fa3L, + 0x6ea74133a11144e5L,0x740c3d2ed8e89beeL,0x88e06131f9bb1801L }, + { 0x47f253754356fd51L,0x8e2ca6ce38e45ea1L,0xf0afe990c2ef8066L, + 0x91b7263d8ea03d0fL,0x37b01664880ca591L,0x61306f09790c8ed7L } }, + /* 49 << 154 */ + { { 0x084c4f92b24a5736L,0xf3d01da90a3c3859L,0xd37c47ed7468b812L, + 0xeb539a939567c798L,0xd852f502acfdc072L,0xd8e5454996245975L }, + { 0x42ec3948db5e323dL,0xdbebd1c7002d3fadL,0x9cc5db55d7c62d0aL, + 0x22af02388afa4c07L,0xbdcb68fc6979eb74L,0x33763dd544dc11baL } }, + /* 50 << 154 */ + { { 0x4734465f87c2e496L,0xbafe4fb4eb7d82c4L,0x940b168521837f17L, + 0x790d7041345a66c3L,0xe9973cfd65ea596cL,0x45fc95df058b3350L }, + { 0xc63bf91405d08638L,0x36e6af6476465a92L,0x7fe09193f1eb3701L, + 0x364f64f06468e2aaL,0x83108431f7129cc9L,0x3ac117205606bf94L } }, + /* 51 << 154 */ + { { 0xe6a85c7d34dcecd9L,0xc14437fe338cdc1aL,0xa5eeb471b3a9233eL, + 0xf230947c71349a62L,0xe704a95686308ebbL,0x0ef4d4da4a362a8dL }, + { 0xae9be4394b634c67L,0xf736c07c569f0039L,0x7356f3010f5f07d9L, + 0xc86c4000823c9cecL,0xc43b3489951ab5faL,0xa7a3b3a6b46bb659L } }, + /* 52 << 154 */ + { { 0xb1d6cb737337af87L,0x09a59a6908638c3cL,0x4ecc3fd25d94c727L, + 0xa7b57269e274ba87L,0x909cd824a61a0590L,0xcbe63cfe3c11751dL }, + { 0x9574de8347c46efaL,0xee334cda539b7e03L,0x245bc6a2e3ef3599L, + 0x13a570fee88d0da7L,0x88ede26d90ef4a21L,0xa0c5953b01fccebcL } }, + /* 53 << 154 */ + { { 0x855ff0f7657121c2L,0x18754814f94c7402L,0x720f1e3c32ce8340L, + 0x7ecd080ee8e49d3dL,0x2838e642f0bee412L,0x69cad618209f8e60L }, + { 0x5730f2dba983a4cbL,0x74957697f43896a1L,0x68de04373dc55d4aL, + 0xa2fbb915628698bbL,0xc8279c975cace19dL,0x7df557465fd52bc0L } }, + /* 54 << 154 */ + { { 0x1cb1c2f378c3f521L,0xa425f99b63116c7dL,0xc86b48c36f7c0e71L, + 0x9e92e82dc76a73ddL,0x8c0414657e7d6df8L,0x99e7884d38c02d8eL }, + { 0x6c53c0cfb78a7e50L,0xcbcb5114481d60ebL,0x1eed68ed035b4441L, + 0xdc95269f755f18efL,0x3ad7f32a3fe51f12L,0x981782d017296245L } }, + /* 55 << 154 */ + { { 0x7743ef2655fcd15eL,0xa73944a4d07f3cc0L,0x3161d6a32438cf14L, + 0xad193a9b14e8938aL,0xe1de190e872dac01L,0xb165da2fc4795b10L }, + { 0x1eb89d519e155bfeL,0xc8b97d94c9c552d5L,0xea7d3edb108c4c82L, + 0xafb60b29c10acbb5L,0x331b316b82c7b642L,0xa53c4b3d719fa342L } }, + /* 56 << 154 */ + { { 0xc8dc34f36b3bcbdfL,0x952d337b24d72806L,0x28b8ec817e56e8c8L, + 0x98e78abdbe861aebL,0x521773ddcf3bd040L,0x582ffcb2b7ca45d2L }, + { 0x70962c0a04202ac8L,0x31b6ac909f29381fL,0x3b4cd403355715a7L, + 0xffbbd1a7399a071cL,0xac669b08e50f02d7L,0x0f568c89b2cf0565L } }, + /* 57 << 154 */ + { { 0x2d2afc2daae7e637L,0x840e47c782a818efL,0xfe26a67c879f2451L, + 0xd41d289810f54247L,0x36040f4877119f14L,0x741859a983f240ccL }, + { 0x15f9607a8fa720c8L,0x8eb70f6df7b8e32dL,0x755394229b98d670L, + 0x80a4a127750c4e62L,0xbe88d03195ca3a50L,0xfadeb53dc6411eb6L } }, + /* 58 << 154 */ + { { 0x19f29da06b824028L,0xa5cfd12b7bd354a7L,0x1cb5d74caeb59b3aL, + 0xec9a8ccc47211999L,0xd7f2a1c17852f167L,0x134629209a1859cdL }, + { 0xdd65f7ac9e3a339fL,0xccaa968075437831L,0x25772f9b7f502bb0L, + 0xa64cd12f6fa0aa66L,0xd2f46ac62af2c3d4L,0x58433d963f262a2fL } }, + /* 59 << 154 */ + { { 0x747757c6715ba7e6L,0xc01b73c1f9cbefd2L,0xf1d96de501bbc017L, + 0xad554e91a1087f55L,0xd9b74be65a6cc716L,0xad2f2c0320317019L }, + { 0x42ef19c207893532L,0x7f3624c40858fdc1L,0xc104bde7078936c6L, + 0x99af706682b5f95eL,0xa40e02625a13a9a0L,0x6c0251c40a318574L } }, + /* 60 << 154 */ + { { 0xedb3abb1fe36eed2L,0xbb2cc1e6a038298aL,0xfa0ac06fe5adc3beL, + 0x7cbcef3eae73ebe1L,0x41596590cd676b87L,0x6cc8c0ae214391d7L }, + { 0x826e2e16fcb3f244L,0x1ed7837e1be22058L,0x83052d0d1a9912b3L, + 0xa2cb410c8ac3dbf5L,0x279d555a7faa6bc7L,0x870e7132f52b439cL } }, + /* 61 << 154 */ + { { 0x5957428e385308d3L,0x49ba20b3bfdae187L,0x4e1281c3adb44defL, + 0xebe93dc4e75c6cf9L,0x81d1d1cff675fc6eL,0xbe01bcecfe0e371cL }, + { 0x713f294d336bc7caL,0x1beb1508e26a1903L,0xbb5feab4b6819961L, + 0x28bede2741bfc7efL,0xb0a5108bb3365719L,0x81a8c9255ccd21a3L } }, + /* 62 << 154 */ + { { 0x4f3d90af2bea6870L,0xfebb0de2ca26ca46L,0x109d96e5d58bd9d2L, + 0x4b42928cd9882c8aL,0x5238cb7a8c73adcaL,0x9d79d72a4adfc913L }, + { 0xba58929d1f0bf201L,0x0b7790a505f52baeL,0x361949aae45fda0bL, + 0x21b2d006af3f732cL,0x1ed05dc33aa84bf8L,0x2322b7f72405980cL } }, + /* 63 << 154 */ + { { 0x4a38b5b2c7151e42L,0x1d5dd94894550168L,0xf2adeb5b7b3d1d93L, + 0xe15c42fa36661a89L,0x7d55a3f27a3aee90L,0xbe1b5c39d9d350a4L }, + { 0x9c4d6fa2610f16b8L,0x7b96051da60fb18eL,0x539762fa496c018bL, + 0x048ffa39168a8f22L,0x33486ccada1c0a58L,0xe216d6be9fd687a1L } }, + /* 64 << 154 */ + { { 0x11a8fde5f0ce2df4L,0xbc70ca3efa8d26dfL,0x6818c275c74dfe82L, + 0x2b0294ac38373a50L,0x584c4061e8e5f88fL,0x1c05c1ca7342383aL }, + { 0x263895b3911430ecL,0xef9b0032a5171453L,0x144359da84da7f0cL, + 0x76e3095a924a09f2L,0x612986e3d69ad835L,0x70e03ada392122afL } }, + /* 0 << 161 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 161 */ + { { 0x3ee0a31c6754f492L,0x02636c6b96769ff5L,0x90a64f4ff0fbfa96L, + 0x513f054efafea65aL,0x796ba7479cf4b9f9L,0x3198c068932a9590L }, + { 0x93af8a65549ee095L,0xb8b6f72ca212760fL,0x23bc71e9c1a46c8fL, + 0x000643af4c9bca72L,0xb6d967c7848cea30L,0xe06b6b4e73312ec2L } }, + /* 2 << 161 */ + { { 0x52ec99561d85a725L,0x0f9be000f3208012L,0xe881337c6dcc7816L, + 0xe4e7b6d9791f7cf1L,0xfaa717aa59885a42L,0xb1bbb5c7f9c01e41L }, + { 0xcf208d58a0361880L,0x24426e4020afa350L,0x7261871b264ce04aL, + 0x66be4a86cd42026aL,0xc5397b77829f99feL,0xffe4a6bc24578e2bL } }, + /* 3 << 161 */ + { { 0x0733667af822d5f9L,0xd7f81b9e18339700L,0x7ca29b27a7bc265fL, + 0x9fefa698eb4f0c7aL,0x7b6f351301f27630L,0x72f0f152fcfb1133L }, + { 0x9928d9d05c81eb14L,0xa16ac36bed8ff6cbL,0x7fbd1acbe041bef3L, + 0x7d25159af8d99854L,0x2ec3a7d8db5a0dc5L,0xd86fc4cc87e3e933L } }, + /* 4 << 161 */ + { { 0xba8418f34c20e15fL,0x7eed2494fb54404eL,0x4e6438d7bce1e82dL, + 0x9e489b3eb397915bL,0xa9baea9ffb4cf659L,0x8bc5b2ba42ef4affL }, + { 0xae3fb5337e62a188L,0xcd648493496e8e35L,0x89728e28defe047bL, + 0x63a8c679d24e60feL,0xadacbf92470f710cL,0xd470aeb95e198d3cL } }, + /* 5 << 161 */ + { { 0x8e3807dd7a3e874aL,0xc4edb45b89ac3a99L,0x9ba9cdaf4bfd77d2L, + 0x31d33f59b540fffcL,0x404c87790c60028bL,0x7f89da7189688c81L }, + { 0xdd3390e5504b862bL,0xdf1e721be937efe3L,0x5833d0df63e6036fL, + 0x7712527a385fbab4L,0x6347236bd210c0d4L,0x12d7733c8d238e2dL } }, + /* 6 << 161 */ + { { 0x0ecb0723302e943fL,0xd180ca1e4a443e78L,0x39e7891123dd2c9eL, + 0xfa2a440401fe50bbL,0x4678e7ed154d39d1L,0x64ddaee1af513e01L }, + { 0x6d4c615a634904daL,0x937c6326ba5c900cL,0x70658f5feb6c8582L, + 0x2a04fd51f3d65166L,0xcefe7472b676eb47L,0xd3565a71f597d887L } }, + /* 7 << 161 */ + { { 0x299520f4e5dcba80L,0x522ad4b52b758045L,0x54eabe27193b36d4L, + 0xda4d3bff45e9e442L,0x44cb9252637311f3L,0x4cd620a971338ebfL }, + { 0xec908157cc9524fbL,0x2731a11ba8c955d7L,0x72a5e0545cb94009L, + 0x7eee8f3b9126cfe8L,0xc71e29203dd5d5ceL,0xe886f91a22069494L } }, + /* 8 << 161 */ + { { 0x294d29550db962c0L,0xd6994ef46d523ab0L,0xfa1a7f9158f95037L, + 0xb137981164420c94L,0x2b686e1e093caea8L,0xdef10944f9e1c340L }, + { 0xcd1beecf611d9bf5L,0x34696c50a1b5267bL,0xcecbc7192dfc2b16L, + 0x2cdb955dcee7e854L,0x9fefc321f2635cc8L,0x276d2e4f2936f7d3L } }, + /* 9 << 161 */ + { { 0xa9de8b87d38e86b2L,0xe0c2f232780d2fb9L,0x742d7fe9449e78b1L, + 0xc6946b7ef29efe3bL,0xbd59bcf985de7456L,0xb070ebfadb492e64L }, + { 0x5cda7ac8a0ff7c15L,0x6e0c0062c4f435c9L,0x4d8e5395974d4be8L, + 0xa0a0c5984e6d1681L,0x5debadbea14cbda0L,0xe176a772ae30b167L } }, + /* 10 << 161 */ + { { 0x25df81bce7b19019L,0x3058081aa6f45519L,0xccafbccabb3de1d7L, + 0x2b794710c515b1b0L,0x74b81bf87168d9ddL,0x92d5e462ec00571eL }, + { 0x865e29efdc670943L,0x2350537c7f6299c0L,0x9fdf787ea947c6f8L, + 0x9601cb21cabe0f8bL,0x2899d5f49313b000L,0x4873bc9f66a9e8e2L } }, + /* 11 << 161 */ + { { 0x2829add72f163a26L,0xf96dd91156909488L,0xc16d185f769ccb59L, + 0x13c4b566e9c6da4fL,0xfd68110bc423ac34L,0x64911819cfaa9fb6L }, + { 0xad7c7d2b12dd07e5L,0xbf7eea90abc19a50L,0x1db70ed108d6c57aL, + 0x01da2b41446deeabL,0x163a5a5fa4f6a367L,0xca9f4bcca10c8a53L } }, + /* 12 << 161 */ + { { 0x2132c32e68206a00L,0x20bc1bb483bab6d9L,0x99fa3be2bc4ef156L, + 0xe515cd05ebbd6c33L,0x9c06d7670d2c8ebcL,0x2fa7f3b68a79c884L }, + { 0xa4dad16a9137df25L,0xc4da20f833598c21L,0x32f5d9e3867cb117L, + 0x8f00fb54da7cf533L,0x428cf9e3870ef3b4L,0xa8b6c754521b8428L } }, + /* 13 << 161 */ + { { 0xe9b297be7be5e610L,0xd09f63c304b49303L,0x9110a9b381ebb814L, + 0xc32af8986bf19586L,0x5c4939571da2280fL,0x89e85cb41becc5f5L }, + { 0x1068cb528f1a396eL,0x49dde483440a6144L,0x51280400b5d6aaf0L, + 0x0e8ac4a53e8ea21aL,0x32f4a91d92582420L,0x5eb09649bc35e408L } }, + /* 14 << 161 */ + { { 0xea3a2f0c32f235f8L,0x8281bfe5bf4a8256L,0xf44e1319577b9e1fL, + 0x31732d1bab2d9ac7L,0x6e7682eff375c5cdL,0x7069fbaf0913ed09L }, + { 0x693257dcf690cb94L,0x576a85b2dfa6e07bL,0x72e00515447fe4e4L, + 0x00af617509a2cd8bL,0x05a61365902ae75fL,0x8310b16db5ecb690L } }, + /* 15 << 161 */ + { { 0x4d22c79cb00fd8f5L,0x432b09844c9ed8b2L,0x43da93b2a85b3f0aL, + 0x0522df2ac4163655L,0x2ea7210b77214019L,0x8280099b7051a9a3L }, + { 0xcd0a829bb11b9e80L,0x9bda76c7246ee656L,0x1ece801bad70a0faL, + 0x4f8162f096721d79L,0x341faae58e7c3b0aL,0x6914420b12e57cf4L } }, + /* 16 << 161 */ + { { 0x4962c02167141724L,0x5f81eabeabe7762fL,0x78549a79dd189c3fL, + 0x47675cdd6ce517a7L,0x5102294e32d6bb97L,0xb19500c66ed1a029L }, + { 0x3efb54e8b16a206cL,0x7dbdcc250dc135b8L,0x955bc2948967fb04L, + 0x373615c9be04e909L,0xf1fcf820111efad6L,0x8530f97d6fd2e97aL } }, + /* 17 << 161 */ + { { 0xdfff3aceb3b513d3L,0x569f9d42fdaed4c5L,0x8615a9cf71cdec34L, + 0x2e700c34ceeedc56L,0x9047d770a48d0682L,0x3fc845780ee5893fL }, + { 0xaaaf3d90ab5b432bL,0xc846365184cb412cL,0xd215030d928ec9bdL, + 0x237a710045b97accL,0x0f533045ff791353L,0x093a0d21a1899bf6L } }, + /* 18 << 161 */ + { { 0x5da20568b4bcee44L,0x878025840f5bd27dL,0xc76b965c1c06dbccL, + 0x89ea2cceb1492616L,0xaefc8746b460c4bdL,0x679e6edb994d1756L }, + { 0x4ff93a4a271f3218L,0xae496faf3b970a74L,0x062df3a7ba6c44f2L, + 0x1ede93021990ede1L,0xa797899af9a1e2adL,0x9b1bcf6d82599120L } }, + /* 19 << 161 */ + { { 0x63a38a51bd04f6ffL,0x2ddc958bffafb91aL,0x198895cdb19b2b08L, + 0x1bb494246f65b797L,0xf75df140f157b79eL,0xa188dc873d599990L }, + { 0x8b926eecaeac83c2L,0x55fe56f03b82900fL,0x10eb6dd33b11d061L, + 0x8b44c14c3aec5877L,0x294b83e8b486e651L,0x469e552f79524b3fL } }, + /* 20 << 161 */ + { { 0x69386f451a746ed1L,0x4319649bcc14bac3L,0x006292b3b647cefcL, + 0xc771b7cda20e2a37L,0x838714d2396bf329L,0xf263e66759c0823dL }, + { 0x7ee258f0725e3ecbL,0x37638f9934218254L,0x4d57db246fc6d0f6L, + 0x8c85ad7322c2dd47L,0x2300a9129c59cf13L,0x63971b0bee08c1bcL } }, + /* 21 << 161 */ + { { 0x180032d98c2e7698L,0x07d4d364a851f2faL,0x0070bbdeb50b5986L, + 0xba05ee28274eee7dL,0x28843675b0f482e5L,0xdcc9c09ff82b2229L }, + { 0xae0273e7f061df73L,0xa3856b6644e3a740L,0x4b13b141527b80ceL, + 0xfd83b7f0e1b7dabdL,0xa3b5a2f1536c04c3L,0xfd09c77bb29e2bf3L } }, + /* 22 << 161 */ + { { 0x05fe64c5436e7c2dL,0x5b9f0b83ebb1ee26L,0x13dcbfed2977d6f5L, + 0xbd16c6b7db552375L,0xaaeacc2342da342dL,0xe427d2ee0cfec89dL }, + { 0x3097ac7b038b280cL,0xa2b79d623aab3c43L,0x9771fff4a40f585aL, + 0xf50974e0b15aa16cL,0x114e51137a847284L,0x574ba8efb4fbe083L } }, + /* 23 << 161 */ + { { 0x3c8dfa3b05e37e4aL,0xeaf691b47408352aL,0x2e1ce9863c9a8610L, + 0x8d024a814acfb35fL,0x3766aa2184ba6baaL,0xc336f82eb91f5a27L }, + { 0xe2d46985412ab7b4L,0x397f0411ded6de53L,0x067241c3544768fdL, + 0x9206d3839b71e023L,0x8571fe1e3f51c3c9L,0x0abdb52e3ba345abL } }, + /* 24 << 161 */ + { { 0x85e1e4abd5281f9bL,0xc7e517ddc653b0c8L,0xc0b84da1a717e034L, + 0xf1a63b280f1bf3dfL,0x47b74201aba6fd41L,0x9cf3da633518fcabL }, + { 0xe12511fb23bb6e77L,0x13b2cb4438679d79L,0x20e0fb10db5665c0L, + 0xb5448a33b99f4d5aL,0xcb1847ad46b7dbceL,0x41f156b8fdcadb87L } }, + /* 25 << 161 */ + { { 0xd09b746793c8b2a8L,0x36c760204357f251L,0xa965d1771ac04cf1L, + 0xca49d59427740f18L,0xbba973ed76c53b33L,0x7f8c2d264c17d867L }, + { 0x389afbbb00966b80L,0x92f2097a55988387L,0x316a85393a47c746L, + 0x259ae094ac3a3a30L,0x337f1d3f0d61ee3cL,0x02d5a60ca9d928ebL } }, + /* 26 << 161 */ + { { 0xd9f370e42af77d78L,0xf9cb8d588bfa692fL,0xdc8a4c24fc9203d5L, + 0x499b6fda3b8138f4L,0x051a61f19118d3b8L,0x89207fa2cb251fb6L }, + { 0x32247676bbb0e12dL,0xaa1c59822900bce2L,0xe7beff9c7df4f6c1L, + 0x595fd551757c1449L,0x2fe91299650e8961L,0x2db30033f480bf30L } }, + /* 27 << 161 */ + { { 0xe796c05d110c4d7fL,0x12f87395d4af6817L,0x849cd9e6b5512cb8L, + 0x23b8d0a4adb71290L,0x28cc808bee64339fL,0x3072d46fcc27fd1cL }, + { 0x8d9183af47f675d2L,0x9959aa9102c84561L,0xdff7591708216e03L, + 0x868c237abd01b2f0L,0x4c00c229a53e639fL,0x2c0667fb07d69862L } }, + /* 28 << 161 */ + { { 0xb4d2324f9470e571L,0x3af515979ca353e5L,0x479a3a796ae5778bL, + 0x387958a7fb1d9c91L,0x4e606558cf91edc6L,0x428384ca495a3b00L }, + { 0xa49f67da10f7146fL,0xbda553e08e25f80fL,0x21b034c4cb919bc6L, + 0x1fb454bfa7930462L,0x1fb2ac9b255d7fd8L,0x491cceff8b197e6aL } }, + /* 29 << 161 */ + { { 0x0a0e0cd91f5a179fL,0x699d872713841e78L,0xfa93f774fc47f9cfL, + 0x8fd0019c02933131L,0x128efed95aa46834L,0xe20226fdf080cb8dL }, + { 0xf7b05fc3000445dcL,0xcc818da1f52f5ddbL,0x0fa803d07299267aL, + 0x99cf0ab4f9f172a0L,0xb5dd3c36b08d03a3L,0xfafa550ea1c2f73dL } }, + /* 30 << 161 */ + { { 0xdda52c89d2da4e36L,0x0348948d5c333386L,0xe3a5be8b37917590L, + 0x42488ae238e4aaacL,0xa6ecb5be7a44eb6aL,0x3bfd640ea9b27b56L }, + { 0x23b8d107bd05946aL,0x01018c45bb8034bdL,0x1ffc958cd2e058fbL, + 0xeadc93953fd43516L,0x0659b83ea0491dbcL,0xc36115008cdee521L } }, + /* 31 << 161 */ + { { 0xc0f3761c034b0a6eL,0x2c4ce5481fb66b85L,0x7a5d3143410698abL, + 0x4bc07a795d59e8c5L,0x176a10eb4d19ba85L,0xa8a68c5526dae045L }, + { 0x7eed57fb21625985L,0x33ef04ae16c62e63L,0x78d0acd4562454bcL, + 0x5878d7f2a44a1608L,0xa51a423a0cf11971L,0x1934e3f2f21fd6ecL } }, + /* 32 << 161 */ + { { 0x3f2b5bd4b4805410L,0x201ca7a9f96c5ee7L,0x532ef2db94256fe1L, + 0xacbfc459318ddb03L,0x2375f9fd5f24c8e1L,0xd27c479b370783dbL }, + { 0x1bd461e856541ae6L,0x78f054a77f7ea49aL,0xc9f8777d8845f315L, + 0x81aed29697fc92c7L,0x9f2f8d7949929540L,0x7531e78bff5ebfe0L } }, + /* 33 << 161 */ + { { 0xd4710d5a16ba6a11L,0xb172d8a0e056d27aL,0x01879d2b8301e5c0L, + 0x100c3e706f6a3396L,0x4a33d4a4e4e1cab1L,0x48016f0f08017d74L }, + { 0xbde9e0f18cec4fb8L,0xd8604899eb15c26dL,0x17ac5d884a21f615L, + 0xb8f1e7060cb0cddfL,0x0ead85644a0d51c2L,0x7bff69bdfd6bafa5L } }, + /* 34 << 161 */ + { { 0x028acd1cb6b73820L,0xc931f4bc815047a8L,0x22c6159f1ede2c60L, + 0x571dd40c99a4820fL,0xbaf08be0b450f472L,0x6475536aeb5bb639L }, + { 0x033568e4d984d0c7L,0x2ab7dd4885e910d4L,0xb0d76698d0c632ebL, + 0x954d00f3e3c34a46L,0x53e8772de651bc5eL,0x4910b07b6e3564f6L } }, + /* 35 << 161 */ + { { 0xe1550b37e758fcf6L,0xfea2446f763120abL,0x5db50b38124f80e6L, + 0x5cc28a7830c3301aL,0xa935846fd950d5b9L,0xae3e87f2ce43ebe3L }, + { 0xf033b25b7d0776a5L,0x941d186e882c5916L,0x0430c4503d6d4f7dL, + 0x4e0641c0726f30ccL,0xdfcdbd1626c66c27L,0x43c4590ceb00e495L } }, + /* 36 << 161 */ + { { 0xd8cbdd8b70435ca2L,0xede7fb3675af3a63L,0x6c1fa971090b36bcL, + 0xdd2292eb85455ed2L,0xf9c3889c7fbe5041L,0x2ec87c15506d605fL }, + { 0x2691b0a28b099c25L,0x27961c8b89944e21L,0x8e9e18a5147f5304L, + 0x6a82e35baf7dce25L,0x6745339c32a4bbc4L,0xe0bf0e0ee026676aL } }, + /* 37 << 161 */ + { { 0x3c6fd1ab352a43fbL,0xe57e7f8cbd68dbffL,0xa4a5b74e9ea30f41L, + 0xacea695d2d5a3a34L,0x183be19adc8fe4d3L,0x22fce6281b9f9d1cL }, + { 0x8b1ae75da5d35bc9L,0x213face52c673f82L,0xa879851d6568d549L, + 0x327c59937f8d8112L,0x56b982e2a7869b71L,0xc77afa6110bb8086L } }, + /* 38 << 161 */ + { { 0x1dcd57541ccadbe8L,0xd2d8c36512b37773L,0xc1a7a5b7d50e8680L, + 0xab1a00b3e19d155eL,0x58f4bcce7a9776b8L,0x1c02df3320d9d7aaL }, + { 0x24f00d31db8cea6fL,0x2680b029d4aa0785L,0xf3db2889c48587f5L, + 0x1811dd2521a7fabaL,0x5836964bbf820746L,0x3b118bab97aca83eL } }, + /* 39 << 161 */ + { { 0x14babe6321d76845L,0xf7b4c662c60f5934L,0xbf212c4434de5b23L, + 0x57c478a35bdf0a35L,0xddecc21535dc8714L,0x1609b7401571e91aL }, + { 0x41998697ba45b40aL,0x6ef382d468cf383aL,0x77a24c1488c0ec9cL, + 0x0a5e245297b377a4L,0x2b9d72bf18f9804bL,0xa4c21326f51ddaacL } }, + /* 40 << 161 */ + { { 0x397049f4c785c7baL,0xa87db27da1decf9dL,0xce6d5ec1e7862c0cL, + 0x17a98db834350bf1L,0x6ceccd8030ec8d74L,0x4790cc07bcab4aa8L }, + { 0x4378b1feb4f771a8L,0x3c54588b404dfcbbL,0xbddf0faa8d60f86dL, + 0x987583da3573271aL,0xb0afe4ec4b8f8032L,0xb5c44605b69d03f6L } }, + /* 41 << 161 */ + { { 0x7f69e8bfed7d4230L,0xfe54dca7d8ee8cbeL,0x6ec2b75f71b72d99L, + 0x97e2b30f8dd8338fL,0x9916dcdbbc75bf05L,0x22f4291aad5c114cL }, + { 0xb6af2e86f9ba5c98L,0xdd7d738dfd6fc5d8L,0xce7af7d544649034L, + 0x2979be5cd163b098L,0x5acd51858db8d84cL,0x82b0e4a5ca64d1c0L } }, + /* 42 << 161 */ + { { 0xf27f5f4f480ef46dL,0x2f49f44fcba811f7L,0xef40508d43961b6cL, + 0x0f6778e8df9fb37fL,0x97aff7e8446864b5L,0x29aeb86d4d264e1eL }, + { 0x48baa1984901daacL,0x91ade9db02b483cdL,0x00952a61cdb6abc4L, + 0xa1a51250de7f22c9L,0xe6adfaacc19ec8d5L,0xa7d2f066fc39838dL } }, + /* 43 << 161 */ + { { 0xfbe20a8e270bcf2fL,0x9882e7a0c35c60f9L,0x74d8e63f560e716aL, + 0xdc689649bae281e2L,0xd454571036d9b680L,0x0a0f1c681740ca0bL }, + { 0x228dd692dadf3782L,0x6ab0bede632d6e56L,0xae2f5535e1b7add3L, + 0x2ce1c6fece308fa6L,0x7a11b255db881355L,0x903007107bee5bb7L } }, + /* 44 << 161 */ + { { 0xdd55c21a9f1a57d6L,0xc9e1dcf9f6043ee3L,0x0385e3f36747e2baL, + 0x6511555a932e55b5L,0x7f4053b3700e73f6L,0x23adf65d992916a2L }, + { 0x4664bf231bfc40a3L,0x8400e8f27974d63fL,0xb70f104dcff08198L, + 0x4c44382f4d1710afL,0x5593a751374ec807L,0x6af17e84462c6112L } }, + /* 45 << 161 */ + { { 0xc1ad3eb7b8f1f38dL,0x74bb37c88d462e67L,0xd127b6e6246b0388L, + 0x3054aaf0824defffL,0x4e981d2e487809aeL,0xba76b7b805ead528L }, + { 0x0a167834a7a32c6dL,0x3451ee930268c370L,0xab4da0971b625d09L, + 0xdb94f9aa304e60b4L,0xf3bea685ab50c663L,0x8d929a0142d4c11eL } }, + /* 46 << 161 */ + { { 0xfce03e6eaa911497L,0x32cba5cf546ab5ecL,0x631123d0b1a71e10L, + 0x49f3a80906bcdeafL,0x783373bcfc538ca5L,0x3590890ee4b47edaL }, + { 0xb5c84fff39ab2df0L,0xf681be9ac737b24fL,0xf37bbc68b2b0052cL, + 0xd9f03cf6fde04d93L,0x23171bc2e43803e3L,0xeda51460040de801L } }, + /* 47 << 161 */ + { { 0x0e09a74d0bccf0d7L,0xfb429a675b58037aL,0x1f2660d2200b89ccL, + 0x489b332e04efc617L,0xb53d4f65f38ceeb4L,0xeaaf759546c4aa4aL }, + { 0xc6cff1fa714b9f97L,0x6a647072ec0dd5b7L,0xcbf59eb1637384bcL, + 0x043003cd2240993cL,0x134cab640497f9afL,0xcdb44a4ca9fcc655L } }, + /* 48 << 161 */ + { { 0xbd9a66d6543b3e41L,0x2948c0a62ae73774L,0xa75151dfef38e9b3L, + 0xa3348ae5754fb3fbL,0x1218fa8f13069b72L,0x532bb0510835dfafL }, + { 0x2121a98edf2be3c6L,0x85980de69e5199bcL,0x1b23a4be1a1eb6eeL, + 0xb5c48b92adeb3ae5L,0xeebd305dedea2b45L,0x20543f04c37198eaL } }, + /* 49 << 161 */ + { { 0x9eb2d599fa727a5dL,0x27cce415105643ccL,0x2face9e8c06035deL, + 0x967f70e4c5d916cfL,0x477224ece7cdc451L,0x70a3de4ea9a34198L }, + { 0x84ebd23a62628f21L,0x517cbb6097f55e75L,0xa4dc8d8ccbfaa795L, + 0x821d53c1a9c17b12L,0x04e94aea5124d5a4L,0xc72432c083efbc58L } }, + /* 50 << 161 */ + { { 0xb7a2090999f73a42L,0x019bf3a630db0901L,0xcf0c2a7281cfde4fL, + 0xf656a2117b0b04f8L,0x88cedc1896043e90L,0x4482c3786ae4c551L }, + { 0x169f25d3dc70c774L,0x0f8cc86cb552fbe4L,0x17d0556b88d2f3eeL, + 0xf5af9d6ff864ba64L,0xcd509d82f93dbf7fL,0xf00c76f51b98df35L } }, + /* 51 << 161 */ + { { 0x19fbeb37856e35a3L,0x1788055c88f36390L,0x9da657f165361c9fL, + 0xc9f327b7e35a36b1L,0xdc388bcb04b9174fL,0xa79bf7d3349a87c8L }, + { 0x865958b202289b24L,0x4096845ecebc4686L,0x1127085b42ce096dL, + 0x56f31d12735241bfL,0xe2239ab543b89a15L,0x477cc5b3a6a1f0f2L } }, + /* 52 << 161 */ + { { 0xc44c81525d54607fL,0xe742a6f35c9ab491L,0x50df96d9be8c2ed5L, + 0x3aa8c9b4e7f5cc4fL,0x577d534c3f12e8b5L,0x03f9573da33a57b1L }, + { 0x9172e1aec5c0c895L,0x64fa9822a2e19442L,0x17db2388178a10d5L, + 0xe75a6bdc2755ed55L,0x6a6d9dc3f9188333L,0xdd93a3b83eda0c41L } }, + /* 53 << 161 */ + { { 0x353d1f4bad0d960fL,0x6fbf4355846e07dcL,0x2156ae3c3a1bb429L, + 0xfa95a260442e6e21L,0x659a856ac2b31d7dL,0x9b56cd6563ecb2d0L }, + { 0xac9ec96823a787b7L,0x4102d82e320742deL,0x470ee0ea50a422a2L, + 0xd3ca8414af386491L,0x28d8994b1a0d8192L,0xe601e4e2b3f117dfL } }, + /* 54 << 161 */ + { { 0x906c071c4e9ab844L,0xeb1a5806f085a058L,0x2f14c3ac176e2f59L, + 0xfc1a3020bd19f909L,0x5e67d789ac060e45L,0x75dd23a7b707084eL }, + { 0xb9dec51a07e89974L,0x50c9cd0b38f97f3dL,0x368b0f53e14cd6fcL, + 0xea4c7f8b81ab93b2L,0x774ca31d1b7aeb66L,0x94c14607288f51a9L } }, + /* 55 << 161 */ + { { 0x18c41b62fe32b90aL,0x2e11c7e6be96e1aaL,0x72832e8c428b9d81L, + 0x93f63cc0058ca451L,0x603f18af7cc827f1L,0x31c8b8fee038eb26L }, + { 0x21158b24411cb335L,0x48dbbed70d9e953dL,0x445e244e4d62615cL, + 0x2f5309ac28ef4922L,0x12ee44c60d4dc305L,0x7dc0363f56f7677aL } }, + /* 56 << 161 */ + { { 0xf73471b5ef349ec5L,0x014dae75565aa6c7L,0x57cb497dae082cefL, + 0xdfcbf2b5c3e563bcL,0x22149c0fd1125f95L,0x529f419b425bc019L }, + { 0x049476deaee2094cL,0x3490c0490cbbb583L,0x56c5c62d1256424fL, + 0x0a118ee541bc66faL,0x0d8e9ff8296ada14L,0x34356e8b0134f8c5L } }, + /* 57 << 161 */ + { { 0x5e41ebd6eb28f97cL,0xe054a055d6a393f8L,0xc0a19e38db6555e3L, + 0x1b40c80fbabf4f9bL,0xfca17ae2780d5107L,0x89ae096f379701feL }, + { 0xd79be295b53ebb0cL,0x3112d3a5942b2247L,0x6c1f44d30de10f30L, + 0x2a17fffb0041f800L,0x13082de044552d55L,0x319aa9c0cd11c85aL } }, + /* 58 << 161 */ + { { 0x63ea1a6ae760373bL,0x00f2addd11742d8cL,0x46b17c9cafdd38eaL, + 0xf4121c5a4c7e78d7L,0xbeb70ef90048e4f0L,0x0b60c2b6bf7f7348L }, + { 0x4bbadf7632969689L,0xcb6a8a20e12708e4L,0xc43ad55b5638eb7aL, + 0x4a72b02b3d27bf7aL,0xecc95d92e5a54c30L,0xae52514bacc45d53L } }, + /* 59 << 161 */ + { { 0xbf5a2b5132d1f651L,0x6a2a74116e438838L,0xfa6353dd6c067d61L, + 0xf6918622b96ba12fL,0xf0fa254d45f595f3L,0xa0f0cb4b92f680a0L }, + { 0xf13ba734463e3f27L,0x7e3d4eb1a32d7f9aL,0x348baaf26f6502dfL, + 0x8021a9977b830e5eL,0x503f38ca55caf601L,0x27dde9e8f4bb74b6L } }, + /* 60 << 161 */ + { { 0xfd5a49310eb63b3cL,0xdb9f1a1510175713L,0x044d42c23e11c321L, + 0x5561f2e9b7961e8fL,0x70b3f7557ec7c597L,0x5dd9671235aed561L }, + { 0xc6cdc78ee1bcc2b1L,0xebcf6f87f1117aa5L,0xef470e0ae3669f78L, + 0x87b13e0fd38e0fe8L,0x01bff01439c755c7L,0xa66f2521c37529f8L } }, + /* 61 << 161 */ + { { 0xac56a8b223f78e49L,0x908c4be58708f0b5L,0xa63aa4191536f6b0L, + 0x8c08578fe5a95771L,0x5d2d1d6b9c2ae8daL,0xf3e4ef12f1527cc4L }, + { 0x46c1ac13920a90bcL,0xc0bc661d28ba758fL,0x9114e016585ef450L, + 0x8ab6a1f6e899a032L,0x57d4089606b658baL,0x2ef87621eb83235fL } }, + /* 62 << 161 */ + { { 0x033a4d4c4ebdc925L,0xff239a3efe1b346cL,0xd7ab2fb388d03949L, + 0x56ce2e41bd6e8e4dL,0x3826aff0e55da68dL,0xc9c7ba7451267f98L }, + { 0x5264a48ae6710c7cL,0x3635f1d4e7605975L,0x53a1849a94be903cL, + 0xe4fc3617128d5859L,0x7686804d7e4dd785L,0x6f04942d2dbcfe4fL } }, + /* 63 << 161 */ + { { 0xe80b7f5562927d6eL,0x92b98c350c0cc89fL,0x9522896d15117facL, + 0x7a224db5fdd3ffcdL,0x9502ecd8fbfc8908L,0x4e1dc71ac593105eL }, + { 0x052aade62f0536dfL,0x0c7cc371f324268aL,0xe7c62f2ccd843bb4L, + 0x77d48fa36df2c231L,0xb2c29803cb8f68c4L,0xad7ccf519bb9fddeL } }, + /* 64 << 161 */ + { { 0xd0960bd80fab968cL,0x6899e4faae028db0L,0x975ccc77a9850916L, + 0xb41bd531e5f81554L,0xbdf8ab57c8cff2c8L,0xea306a01f5822be3L }, + { 0x1f0ac0e7befbdbbeL,0x72f4b0e960519f87L,0x22bd8b82e3cc86abL, + 0xc43bde8d2b2beaeeL,0x8168781e412617ffL,0xc5610627b7ee7096L } }, + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 168 */ + { { 0x0869457a01a8eb44L,0x522239857a7bedd7L,0x2c04b0c600057505L, + 0x468be6e80b09adebL,0x2f3bf32b6f81474fL,0xf54f949da712ccceL }, + { 0x292cee424cdd8f2aL,0x3d9fdf6b9c221be1L,0xe54da66156f47b2aL, + 0x2ca76835840b5d1bL,0xb52adb6a8a6e8cf6L,0x8b416a6bdade153eL } }, + /* 2 << 168 */ + { { 0x65f7d2c18565afc9L,0x764c897170fa7b82L,0xe268634c986436f2L, + 0x6334d8d133356165L,0xf17164269ec7957dL,0xae834331b8093983L }, + { 0xedb1fe5cd2dfcce7L,0x6195b86368463e5cL,0x746e5f4da691b665L, + 0x61171291e1e2727eL,0xbb4aa8f16f27b029L,0x1037657d7f42c197L } }, + /* 3 << 168 */ + { { 0x2af8bdfa970f96adL,0x19d09a6dd0c86e6dL,0xd57fd5ced7046d2eL, + 0x5ea025f7d545fd33L,0xe2ccb6f43161ffd7L,0x3ca5286209406242L }, + { 0xf3536d60b5c90905L,0xd086e3b9d5b290f6L,0xfd15b06a5cc55444L, + 0x61b0febf9a9e2a66L,0xdc3c0576653dfd02L,0x357774230a8ab51fL } }, + /* 4 << 168 */ + { { 0xfe19901b0d5b855aL,0x5facb9552f745022L,0x92fd012556c4ce5cL, + 0x23172d65938c89abL,0xa71f8a33aaa587b1L,0x511a3745b55c9c50L }, + { 0xec005f6a7185086eL,0x6dfc2761f894c6abL,0x98a4d67f9e26361fL, + 0x7f0a2b2321389c25L,0xd158820795ffbceeL,0x4d6b29ab9f36a888L } }, + /* 5 << 168 */ + { { 0x5ffec1d78c04bc6eL,0x35f052d16ca0dde2L,0xfbe3844c649c850bL, + 0x450263e610fa337dL,0x44f7c8f40280773dL,0x27de5d3ce896966cL }, + { 0x2587f47598d0378dL,0xbd49c97f4e4f6e49L,0x9e902f667071543aL, + 0x03398aae06577b74L,0x030926d6910bee13L,0x5576575bffa92cecL } }, + /* 6 << 168 */ + { { 0xe4ee33460562cd7eL,0xd1d385a3f01ba45eL,0xd817ca667ce11848L, + 0xda222cddcb69c7eaL,0x74ac74709d680afeL,0x3770357cd9596ca8L }, + { 0xdff57da7f7759bd6L,0x090426be20d5c726L,0x71c0ba28b7fbc1b0L, + 0x60faab1c13d4ed0fL,0x6fbe3567ea3a2ef2L,0x0dd3835c4e577dffL } }, + /* 7 << 168 */ + { { 0x9b758b512ce27e38L,0xe4148475a39855e3L,0x4669b3c39ee88a77L, + 0x3f36a671105e1ec0L,0xd0f30e5d9e88ea13L,0x6346df15baecbaadL }, + { 0xec65be65cf4c6510L,0x843efca194e1989fL,0xf7195d29942ce52bL, + 0x12201877d3ce28d4L,0x9c962aa1a97fc904L,0xc4fedb3465c5a55eL } }, + /* 8 << 168 */ + { { 0xeccb421ed0a701a5L,0xad4cb9a5b60cd286L,0xd344da9e05a53972L, + 0x3a8035e07bc99feaL,0xe0214485c0f77bf5L,0x50ada30ee54df78aL }, + { 0xdef45af64ec2d576L,0xa05d61845f9a8678L,0xa9b17db1c337e017L, + 0x026a4f66b84671d5L,0x606142343b7d696dL,0x71ed9aaf81cfd22aL } }, + /* 9 << 168 */ + { { 0x62805305695a3f30L,0x6ce27626e28e8fe0L,0x507386af6a54f410L, + 0xf8c5f738cd5c7effL,0x3ab2db9e347e85d7L,0xf5b635b0b2161b68L }, + { 0x99009791be2e80caL,0x6dff3030c13910ddL,0x2beeca057ee8700aL, + 0x12616fb11ac7e09dL,0x38c9ef9f9037c2e4L,0x39181fbf9c140344L } }, + /* 10 << 168 */ + { { 0xcdd6aee47aa54433L,0xf5ecb432b80336f5L,0x690bb949a1380829L, + 0x219d659ca9c9d720L,0x74abf2dd7e5a3260L,0x405ee136025c55d1L }, + { 0xc5c592cb1cc878a8L,0x119a38be88b31ecfL,0x4fb00f82e94e39e7L, + 0x66bf72e59412c068L,0x9337c8f30821142aL,0x477216340c24ab67L } }, + /* 11 << 168 */ + { { 0xa6c7953457fe953eL,0xd70d3d2f3c76ae58L,0xe1e047b52c531c84L, + 0xc71f3a9973735602L,0xd70bdb0f7ba0628eL,0x280fdd4e0e3e3c0cL }, + { 0xb5a3f5823e414e26L,0x55b2eda8f44dee7eL,0x8e1d024b2f5dd828L, + 0x21f054eb3b1bfdf9L,0x3d3ae74cc554e1cfL,0xa0a5863ffc42ec16L } }, + /* 12 << 168 */ + { { 0x1b76a3c5439ada39L,0x818829cf89236ae5L,0x2277cb7a750f8129L, + 0x44aa462a4d46502bL,0x7a12e1e164f06dc8L,0xb9a3300dba5630cfL }, + { 0xd2cc8d9c55b05f4bL,0x6d0b0b88a700be7aL,0xa7be99699617500cL, + 0x2b5b8deac03f8a50L,0x712f703e785b3dfdL,0x96a5a60accf93950L } }, + /* 13 << 168 */ + { { 0x9838155fbf9f72c6L,0x3ab3cb602c10e57dL,0x7ac228ef14bcd75eL, + 0x2c167e15027923fcL,0x678869d1267471c7L,0xeba35e857ec3582cL }, + { 0x22d290a9a3478eb3L,0x542092ca1309aa14L,0x8bb5c69be2e5d3acL, + 0xf83c5a0a81652736L,0x9cc576227280cd6dL,0x6653436f3b0f49a1L } }, + /* 14 << 168 */ + { { 0x7ad1f1bab497d900L,0x9d0512236c9dd5d7L,0x0ed27e5bffed3df8L, + 0x659028a775d2fa72L,0x69bd68154581f377L,0x142c2088e2faf671L }, + { 0xf9c1b8a499b000ffL,0xf31d01b18f408d3aL,0xa7aa142f42b9d35bL, + 0xeb8aa74ba0495da2L,0x824cc32a59a1da45L,0x3f1fbe0ff5173374L } }, + /* 15 << 168 */ + { { 0xec9071a634238c30L,0x6dd6c38b88a0f423L,0x3adace72992e7977L, + 0xc90b941b1ae5166eL,0x052aa3e9e3e43a68L,0xe9b1976da733a950L }, + { 0x0e1ca28e5ff6c9dbL,0xd1bd4350387409a2L,0x5943cc7089155117L, + 0x8e85794f5feae20cL,0x0d118fd669768ccbL,0xc647179d53120895L } }, + /* 16 << 168 */ + { { 0xfeb984b3ee828fbaL,0x8273f830e2bd188cL,0x177ef97e3ca0a99fL, + 0x76d4796dacc000acL,0xbad0fa6eb140f51aL,0xb275656706ebc810L }, + { 0xf89eb78fa18cb32fL,0xcfc37eaea65285b0L,0xe2b29cfbb25e9d1bL, + 0x9388ea8fb4e7aef3L,0xee606c12e267e845L,0x6b103c549f5806d7L } }, + /* 17 << 168 */ + { { 0xb9a40e78e31fd643L,0x648cc34a97950a34L,0x85c5ca405900be55L, + 0x2e519cf12abb843bL,0x6f9d0a7f27436edcL,0x2f569c9d6694f363L }, + { 0xf6d1b325f6f1bd24L,0x01103c0d4044b353L,0x2d3ce56f3138b549L, + 0x5379bcf71c28bc5bL,0x6768220d08ac00d1L,0x973f92ff0152746cL } }, + /* 18 << 168 */ + { { 0x5e992944b37b0486L,0x0a334b92001fa124L,0x6653cded9c9ab466L, + 0xd512612fabac4da9L,0x636bf431c502b860L,0xfca1c0c2c3d20db2L }, + { 0x7073f293f85c40c3L,0xfaabc77acfba9eddL,0x58842eb97f9b570dL, + 0xe8cd4f53702aec24L,0x8975f4e6e08113a1L,0xcc0d7f17767bedd6L } }, + /* 19 << 168 */ + { { 0x5163bb51ae315a65L,0xf82ec4cdbe405348L,0xffd381a46b1801a4L, + 0x33f9b8ad2f6ba570L,0xd88c58a58ecc0000L,0xc0b9a639cfdad25eL }, + { 0xc78cb70fe3bd808aL,0xf54b86e573ce5eadL,0x111208ed5610a761L, + 0xba3579b0e3c8e27aL,0xbadd918c63b85bb7L,0x9e10da0b71bcd972L } }, + /* 20 << 168 */ + { { 0xf418e3f63766f2aeL,0x4a3ad3c8053ef1c1L,0xd01e5b5b560db262L, + 0xa583edc7c02bf4c3L,0x7c9f706052f318d3L,0x0852556f1f5e1ffeL }, + { 0xe1c70aa7feb0e63cL,0x59f0a3f989a8c058L,0x4aa4cf021ffc0adeL, + 0xbb880e4138a78632L,0x35b0f7596f28f096L,0xf9c4fe17d5757d7dL } }, + /* 21 << 168 */ + { { 0x160303ded896adf7L,0x19a46b6c6beb8930L,0x33dfd962f010f74bL, + 0x03b699cc00e5610fL,0x17487b7595078dfeL,0x63bc614253f3479cL }, + { 0x43f3d994858d5b8bL,0x383349349483c0ffL,0x47c917a67977142bL, + 0xdc50fb80df7eead4L,0x4e3a1d3fb5b82be1L,0x091af8796d7317b7L } }, + /* 22 << 168 */ + { { 0x783e5066af151a9aL,0xec0a9c175466df17L,0xdecd12310174b0adL, + 0x654af66a3b2aaa45L,0x849d64e5b1fcdd11L,0x7e8e2ae6d05af56cL }, + { 0x12e887b7318a6184L,0x42d1445554ed59d8L,0x2eafeb48ee54ddc5L, + 0xd1f9e6b980c94a8eL,0x5ea691e3263696c0L,0x7f42f3796e03eed3L } }, + /* 23 << 168 */ + { { 0xeeb8accfd69b82b9L,0xb4c4988ae0b61d73L,0xb78becf19df9b59eL, + 0x13274f6236440c93L,0x33d287f5697d5a77L,0x391fe6129af4053eL }, + { 0x986c42b21c16e858L,0x23f5d1dffe04125aL,0x2f57ccb3af9541ffL, + 0xe5b4eec70f1a8bafL,0xaad23ce7646c1b6fL,0x69495ee5a6ff96abL } }, + /* 24 << 168 */ + { { 0x78b8879cfd6376ebL,0x22a76461c01e1edbL,0x6a44be39369cf0c4L, + 0x6653670d5ae54539L,0x257bd7516fb43ad0L,0xb3ac371512baffddL }, + { 0x48659d617548eabbL,0xd8f931f80cd468cbL,0x98f0241549e3b531L, + 0x90b0d71670df011fL,0x26d73c54ab98f066L,0x06591ec988475d5eL } }, + /* 25 << 168 */ + { { 0x6fa72e3518f18e71L,0x6c04fe2d8123ff14L,0xc48cb53a197481a9L, + 0xf059db349860e48cL,0x35e8341ace46ca7dL,0x880f4ea4b0400f7dL }, + { 0xb4c5ea9acc9cc40aL,0x6522c768e2555fa3L,0x95207f39ea2c32e6L, + 0x7b6fc09fa8be60e1L,0x772b829f29902652L,0xb7936b90af6a48dcL } }, + /* 26 << 168 */ + { { 0x409e3b1109758457L,0x59dd0a8c1dea73d9L,0x528906a58fb18a01L, + 0x6fa55967a17ffb33L,0x9523cc3d50edbcb2L,0x35600b3e44d43541L }, + { 0xc3a7d22c8f87dbc0L,0x5514c967c1b225abL,0x78e5701988304a74L, + 0xe9b417ba35f3b54dL,0xb72a243c48eea230L,0x4e173eaf291ee52dL } }, + /* 27 << 168 */ + { { 0x79b854ca2127c795L,0xd9457d8f86657844L,0xf8c9e6ef186668e8L, + 0x84c8855df913c2f6L,0xf207d36ad641cc12L,0x7be9b5736105ce0aL }, + { 0xe72cce1974ec078dL,0xc4f47413d09950c3L,0x640bf6eb3974554eL, + 0xf880dcfb844497baL,0x3744626999bbcfacL,0xcf1712f4316f4d64L } }, + /* 28 << 168 */ + { { 0x627f6328412b84c3L,0xd427e977a04545d2L,0x5b0145bc104f25c2L, + 0xa6931c4f2ac7ad62L,0x407611431f8d42f5L,0xfda5a76be7f8a0b3L }, + { 0x4f1ca5cffe0946b9L,0x6def7b9fbeb2d427L,0x984bd4bbc9a0d136L, + 0xb9a778235b3af1c1L,0x04ee66ae38ac2087L,0x63374ed926d9dbb9L } }, + /* 29 << 168 */ + { { 0x68088e9c3983deb9L,0x2c95ecaa2ed99988L,0x371af002917f200dL, + 0xff33aa5dbb4ff0dcL,0x1dd5fcf2e47bbd6eL,0x1624b973e75f73ecL }, + { 0xf6ce0e9db9722af3L,0x8bde5b8818226fcbL,0x243753fc5b5da478L, + 0x3b53e0e3bdf88daeL,0x59f8c86f325cedb2L,0xabd4076d70fb9681L } }, + /* 30 << 168 */ + { { 0x1996761db8759af1L,0xfb85cdd8e4a705f5L,0x2ea7aa0b35111725L, + 0x23245d4157a17f4bL,0xcbdb650e0d00eb9dL,0xb40823d9e23a4a3cL }, + { 0x041bfb67229163f8L,0x020ad3c16d47b83dL,0x3bc8975d344c8ebfL, + 0x287efd06d91ff408L,0x1ca5d75a2059106bL,0x4ff27af3b90c5d66L } }, + /* 31 << 168 */ + { { 0x416b7c61ded914e8L,0x1aeee7d007ad4237L,0x59d5852476c2b7a4L, + 0x427a102c98665f29L,0x8504aa8d2a1aefe4L,0xef2dbeadc183a736L }, + { 0x5cb5f222f533358cL,0xf2ebb47d36b0d678L,0x1de4a0e7f2c2cf99L, + 0x62613994ea95a161L,0x68a86f4012d66ed4L,0xeb12fe75b2af52f3L } }, + /* 32 << 168 */ + { { 0xcf947c0644ba39e6L,0xf5d5216cedfe78d7L,0xd00115c05f1835c9L, + 0xdf084152d8c79d90L,0xc0c3a6846db5f791L,0x40514451749b18cdL }, + { 0xd314b7d5734df3f1L,0xbccdd3f07f541415L,0x97ed5af06855a942L, + 0xea84ae9ee9d02ab9L,0xb87e90343238a5d0L,0xd12d25c3650a0eabL } }, + /* 33 << 168 */ + { { 0xc3747c584f9d2c34L,0x493a0adc95429c92L,0xf9b5916238a679ebL, + 0x04d500a16bac07f7L,0x8938f4f96a809676L,0x44ecbbf0c5b25a4dL }, + { 0x3b68705504768400L,0x6a432e14b4db3907L,0xff82fb56ad375d2bL, + 0x87f59f97944210c2L,0x2b680b2051445242L,0x1e0986466cd75962L } }, + /* 34 << 168 */ + { { 0xdd2eea82672e5a4cL,0xb05ef9ebccc68d94L,0x626ce368a3fa4215L, + 0x6e376f67fe46bd46L,0xaed7a0bc33c4f169L,0x4a92c6093af5c4fdL }, + { 0x6615245fa690fb49L,0x571d2d870d64f04dL,0x6a45df34641ce79bL, + 0x045ddbd02655d316L,0x2b6c574db4fbc42aL,0x41545fbc5b2dbbb8L } }, + /* 35 << 168 */ + { { 0x484996b97d8f1eb7L,0xf72f3a8110bd1585L,0x418e00e7b67eb27fL, + 0x354e56c97877c18fL,0x7f11f5040a8b37f9L,0x66591146ff58764dL }, + { 0x816ac849ed0bfc38L,0x85eaa6350a50a99eL,0x7fa62d9c5bf4995aL, + 0x77840d5003413385L,0xe4f023bde83f9fa1L,0x2c5f8e1d9cfa7578L } }, + /* 36 << 168 */ + { { 0x1473b55b86a515a9L,0xa9e3230a3b337c64L,0x7e8bf9049db668f1L, + 0x1db2c25ef27f9fc9L,0x0c1086072d9e467eL,0x4505579aa3f00d52L }, + { 0xe2ad661b240400a7L,0x8022294c11af4874L,0x29e9037078bba8e8L, + 0xbf0fbf08f6baca04L,0x2e46d2b74101fab0L,0x66065490c61089e6L } }, + /* 37 << 168 */ + { { 0x18b01aa935dde51dL,0xa7496997a7d044b8L,0xcd9c467f44c23d2dL, + 0x96211b86659e4a5bL,0xa2a9000f3e17b717L,0x7af9c312dd90459aL }, + { 0xf0d6c24394547203L,0xa76a23dbd77cc691L,0xe1b7fce10ef364deL, + 0xe08c1d0bb689c810L,0xb75bfacb0a43ca02L,0x1b7afea5408ac99aL } }, + /* 38 << 168 */ + { { 0x3b1abdb85a4a8a23L,0x8f52060c4d68bcf2L,0x7408306a00ab3146L, + 0x652ae3064b86b775L,0x276a14a0b0695b00L,0xcf8af11f1b771254L }, + { 0x3fafcc63b91118b3L,0x6c49000a73bacebcL,0x53852d084e3f3d6eL, + 0x78977e91fdfccca1L,0xe843cbca6ae9ea5eL,0xa99831896bb8271bL } }, + /* 39 << 168 */ + { { 0xf77b0a7387534a6cL,0xfff419f2f5b0c6dfL,0xde3c3b33357205eeL, + 0x867eb3a23c8ec9d6L,0xd28bed3263a99b18L,0xf5fc17e4c1573146L }, + { 0x30cf41e5821641feL,0x84b1970e225ab57fL,0x6bf707325a1e8ba0L, + 0x7bfb3bbce3cf38d6L,0x9f362787a661e876L,0x6d9137c86c0a16fdL } }, + /* 40 << 168 */ + { { 0x2131ce5b09f8a1cbL,0x7b373ed28ab129e2L,0x463cc8d677c1292aL, + 0xa9b7cf6594ffe9c5L,0x129125ceb99bfc4fL,0x819b42849820d323L }, + { 0x3f70976376541a41L,0xfd679ae5e32c7a7bL,0xc39a208df65b6b3cL, + 0x1c22ebc050002745L,0x268f19dde2bcd202L,0xfeac809c9c3d4266L } }, + /* 41 << 168 */ + { { 0xc5ad8903af14f8a1L,0xdfcd207c3993c99cL,0xf65f8260c7c1fd57L, + 0xa1573b3d41be66fdL,0xeeeb9ea476690f79L,0x6a6338437129849dL }, + { 0x22eeb38623a7bfcfL,0x258fc0743393e894L,0x008efb477ce9602aL, + 0x4bf127b699c7b279L,0x150da482fa1bfd7fL,0x7b84744d293754dbL } }, + /* 42 << 168 */ + { { 0x3af9919db2183277L,0x7f5990fb4f6182ccL,0x17603db034f716d2L, + 0x6b79f6538f135ad5L,0xad9189e68092d128L,0xa5f3ab8efc6628c1L }, + { 0xa36b978e84b6d30fL,0xf2a7e1c64c001f26L,0x2acbdfd676e79beeL, + 0x71b5faec86f6d6c6L,0x23d9b7c849b0e5d7L,0x36ea518212fd4cccL } }, + /* 43 << 168 */ + { { 0x14a4af0f59df1cf9L,0x37f8641dfd7cd2b4L,0xfb6aa5d0244434b2L, + 0xb85f8c8b5d5bbd63L,0x833e76baedb92f97L,0xbcd9d7b50d7a2dc2L }, + { 0xb233f07ff0e0f06cL,0x453f10c4fcc06efcL,0xa4e8f306128a167dL, + 0xbd6df4690d0c09cbL,0x2b5db66b7168ecc6L,0x7ec02c77f29bcecfL } }, + /* 44 << 168 */ + { { 0x0746783787dcdbdbL,0x4cce33be320493d8L,0x9ab08cbe713c7746L, + 0xd6f0c1de9c6dc5cbL,0x194005382ac03761L,0x3fc11f38d0547be5L }, + { 0x66b378ce819fe3fdL,0x6a590acc3700fe7eL,0x4c976a728924b396L, + 0xa5006d8d70b9b250L,0x2fdce1b212b85f9cL,0x5858f7ce495f8f1cL } }, + /* 45 << 168 */ + { { 0x3f2b5e295de2948eL,0x84554eaae1a4a962L,0xb4e55f1293db9addL, + 0x9260e3eb61b22484L,0x22a898997b1a6d10L,0x571bcd3af58d1ce3L }, + { 0xd62db0edecc88a76L,0x88352f634af2cf53L,0x8d279316b61c73adL, + 0x7f898e09ec74d6abL,0x39b2b0c05412a81bL,0x623a5ea30644b6a4L } }, + /* 46 << 168 */ + { { 0xe876b53bdb0f6565L,0xd0dc323c4650204bL,0x0e4af31b0201643fL, + 0x486173207e8a0e6cL,0xe09183d457643a1cL,0x3c55bcb5ae8359b1L }, + { 0xa06078cb7b467835L,0x4d3a35d901b6bb3cL,0xd4f1d8233963fd31L, + 0x9c1b06093d4cce05L,0x55e368d5da550340L,0x50c3feee12c4b7b3L } }, + /* 47 << 168 */ + { { 0x6de0fcdaf0f97e84L,0x1f225d818dfbc0ebL,0xe27a42efcd2c51d9L, + 0xeff56879c0cb033cL,0xe700cb87c82e38d4L,0xc89a02d589d244caL }, + { 0x0b464846ad9c718bL,0xf8d5ee1f8de96d61L,0x2cc33c3dfbfd0960L, + 0x3ef549f0e199b6fbL,0x29f83f686c1597b3L,0x54ca37a3731712ffL } }, + /* 48 << 168 */ + { { 0x357540ab903ff177L,0x225280b8276af514L,0x33d273ac14d7fed3L, + 0xfef6b9ffd186ee3dL,0xa94c207101a7b1d9L,0x4ea3627450bc8bc2L }, + { 0xc68959c9fa98a918L,0x8f5ecceec7bdc262L,0x7a73a4fce6861310L, + 0x19bcac90c828330fL,0x73e3b66f7ef74fdbL,0x60f7698352d8f2f4L } }, + /* 49 << 168 */ + { { 0xda57f1a65645cb9bL,0x3d5d3190f0840240L,0x6a0c6ab101bce275L, + 0x38993676ad23128aL,0x54f7b5d7ea0da248L,0xfee930b38b04ccb8L }, + { 0xadb9034e2cf3bf1aL,0x0488b71ae9b608daL,0xa3e51e303bd1172cL, + 0x56dffa5844993c1bL,0x6b3211fa4cdcaf10L,0x223b2a43834d4e17L } }, + /* 50 << 168 */ + { { 0xb31f934134e43ed1L,0x895c99973c6b7f58L,0x360021084c465126L, + 0x7eb0bf6b095df89fL,0xde3b2fa3ac534af6L,0xd9dd9f55c22477caL }, + { 0xf52cfffc2092e355L,0x4ba071ac8d8bffc6L,0xafb61137abefe750L, + 0x2887d0e4cb62210bL,0x0eb2be515f4fc157L,0x8c993039438fa2f7L } }, + /* 51 << 168 */ + { { 0xfd2a61093efae008L,0x60fa269552f57cafL,0x3591e64f481c36c1L, + 0xdc2b9993c908a87aL,0x76bd4dea5bffb50dL,0x913a0458f70fb0f5L }, + { 0x45ea6c4c097bbfc3L,0x3ebe29d3fa9e90c1L,0xc69532426479c087L, + 0xdd1d24509abc7a4eL,0xa497b072d0fc7791L,0x477d71f9388ab90cL } }, + /* 52 << 168 */ + { { 0xab3578047e03a14eL,0x0f4f28688caf673fL,0x919e661e66530425L, + 0x28da445c91ba47c5L,0xd6d0537566c394feL,0xfe1864a302e8ae91L }, + { 0xd34baca2a753aec4L,0x43b7ffe7a2c8d292L,0x496659eb04efb8f1L, + 0x310ec2a9e0252dfdL,0x98173d2f9168a80eL,0xa3e018d631497255L } }, + /* 53 << 168 */ + { { 0x39ee6439ddfa0ffcL,0xaea6f882c1d1d54dL,0x688feff654a65059L, + 0x17ee5aaa37f25ebaL,0x6c9b4f2932b345f2L,0xb883c0c75b4d62ebL }, + { 0xaf33e4ae3135aa7eL,0x28a7572c924146a2L,0x67dc5dd37e77ae8bL, + 0xe11cd9c5ff39b601L,0xa86f090b5e6f364aL,0x76f7517500b84247L } }, + /* 54 << 168 */ + { { 0x26d3a3e3fbae20ddL,0x5e9b73cee1dd2b25L,0x7008aefb0235d5b0L, + 0xa92af4ed2aaf208dL,0xab786c9bb1132040L,0x43250e6c9a91269dL }, + { 0x00a15294c9be00ceL,0x2d5782df1698dd42L,0x3f980bbe76e3d6e3L, + 0x5b602647496650fbL,0x461edc3271aca61bL,0x2516ab6c9805a01bL } }, + /* 55 << 168 */ + { { 0xb468fcf2967e2216L,0x97b840679ae47d05L,0xfcafaebc5cc15209L, + 0xaf7f6c8ccc83c3d4L,0xa74d4cd5cfa47e0fL,0xd8a51615474cb8b1L }, + { 0x4815ef52591462a6L,0x9c5b2cf74deb41ddL,0x39cb450b7e99d620L, + 0xfe8cacbaa7772019L,0x98b98210577dc69dL,0x5e02b90072423a96L } }, + /* 56 << 168 */ + { { 0x3266c887d9d9284aL,0x690f818b73646ab7L,0x67315ec6af7fc33bL, + 0x181e61abc30b1ccbL,0x1b81e6cd105a9e1cL,0x62a15daf5078b9bbL }, + { 0x74f9840f6fa8cc65L,0x356b777443388573L,0xba0f7d0506b3fd46L, + 0xb0ac864c92b4fdadL,0xcdeac253ef192cdeL,0x0c24810bc313b4a7L } }, + /* 57 << 168 */ + { { 0xfbcd4f77e748de9bL,0xb7d28cdfc25dcc94L,0x32f937a92e033c43L, + 0xb6289636d9da1f7aL,0xd774e97dd287865fL,0x8d013739e6243bf8L }, + { 0xee7ec1f856b9601dL,0x429017666afc90caL,0xc42d960ad2bef9afL, + 0x654ece7f5b430bf6L,0x02878c7f221440f4L,0xe575aa6474a4e1a5L } }, + /* 58 << 168 */ + { { 0xc96e763e71a449f9L,0xdeda66311a349fb0L,0x6f896aef3c4e8f44L, + 0x71ffe2d2e9eb36a3L,0xcbee21ab8f908a29L,0xaeb695f85be98708L }, + { 0xb6023803de61e1a9L,0x59f1ec96065ecca3L,0x2a1229f3637d0741L, + 0x5a9bca2c69441afeL,0xfc6daedbbbeaeed6L,0x950034954e2e31e0L } }, + /* 59 << 168 */ + { { 0xe59a827339859da4L,0x8720429fa7431a84L,0xfcab26e17ee3457cL, + 0xc13c1125da3b7833L,0x0bb1043fbc0b0da1L,0xdc2726ea84b526e8L }, + { 0x34049278a213a188L,0x400bb4a00a1a2553L,0x00e3eb25c92df398L, + 0xc0b7113f9c36a6ddL,0x719d185001e274bdL,0x86f08f2dcde338aaL } }, + /* 60 << 168 */ + { { 0xef8c40bf1adb09b7L,0x2efeb49c0b74992aL,0x3f0f8a412b79957fL, + 0x08927bfe87a06873L,0x1f63a4109288cb9aL,0x8c66fb70df2b373aL }, + { 0x98da4712980facaeL,0x15ce5b17d819d026L,0x097571a5749a671aL, + 0x85a40804894dd269L,0x3e89c13c34cb6797L,0x2d19d5e4d07119a4L } }, + /* 61 << 168 */ + { { 0x903eee85d90da9a7L,0x67723582de5ddbf9L,0xacf6898ad394eeeeL, + 0xa700fb8fabdb94f3L,0x1bcc4f947ac5624fL,0xee5cccff7e3b8ec5L }, + { 0x87d64d4d98e5a1baL,0x78727fc1ad9c4409L,0x55b4159b82310db7L, + 0xaff4eecea58d10efL,0x6d2ec94c11c958afL,0xf129bd1043db33faL } }, + /* 62 << 168 */ + { { 0xe1f6d71ed42eebf8L,0x46f825b9541ac0b2L,0xb01031b693ae2ab1L, + 0xfa4e1c357c589556L,0x65fb2504d273d1bbL,0x589d735447642bddL }, + { 0x7a5776adcf5e2d53L,0xab5c3544e5feda7eL,0x48e8442d32dea96cL, + 0x5f3e9c9e64d293daL,0x3f2df6a16b972a00L,0xfba58f5fa273832fL } }, + /* 63 << 168 */ + { { 0x5c9fe89240e9ce34L,0xfd9fb296633495d7L,0x0ae3c18a8c76cd7aL, + 0xb5ede1e3a6b77012L,0x5ac7a9d5a285822dL,0xe41de7da71ffe07bL }, + { 0x585f7e101b1bb4c5L,0x482794be74153077L,0x66f1c9d5a3e2a34bL, + 0x491d48f7c749830fL,0x3c0f3bcd5416d2bdL,0xaa3baada90b04986L } }, + /* 64 << 168 */ + { { 0x58225208ecbafb80L,0x4f212035aa73d6deL,0x1224e45562fe86dbL, + 0xa8c8a4782dc5b2f1L,0x8a957b8dc3096555L,0x6a3248b0b1591452L }, + { 0x1e563c58cb604c18L,0x32808cb59bf1045eL,0xf8f62de99462e7a2L, + 0x6b3dfe91c2489214L,0x6c1d8fc42174639cL,0xdfca11b8ef88d4b5L } }, + /* 0 << 175 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 175 */ + { { 0x5a4a5ce418690ad0L,0xd0f788e0fe27f51aL,0xd459388e4efe9a30L, + 0x3a45c11aef9d074bL,0xf68ab50b93ab9cb0L,0x62fbc397ecd9a566L }, + { 0xbfb79b7fcc587a7eL,0xfcf4d66f92870baeL,0x4f31aa21877390f0L, + 0x2de0c645e314cfb5L,0x56d904f6238eab12L,0x4d104a42ccb4d4f6L } }, + /* 2 << 175 */ + { { 0x3eb83a8729358cd3L,0xad741295b9c6d430L,0x57b8c77a53abe4e9L, + 0x0a14673ebb9feb82L,0xc0a6cbf7f26f922eL,0x213de299a32e526cL }, + { 0xca417e677b6ca858L,0x8d6ae0f7fc2e0900L,0x2bae0e7a62e135ddL, + 0x962bdcaea7ee82c7L,0x573d7f6ae5776c74L,0x9c4de6496ffbefebL } }, + /* 3 << 175 */ + { { 0x8c962fc809335d38L,0x26d1bc81eb38d176L,0xe1aeb295c47711edL, + 0x0812b9926cbe3e4eL,0xeecacaf90ab9805dL,0x82fefbaa3521a0adL }, + { 0x3a6948c0e2c31b9dL,0xb7d3905be82daf2bL,0xbd3ac90e25a34c37L, + 0x55afd99b61453063L,0x56d87cd190b99303L,0xc9bf82dd97ddb0a3L } }, + /* 4 << 175 */ + { { 0xcbc0bb1968916917L,0x0bbb9f921094bf88L,0xf62cb350d3806442L, + 0xe4d2f1cc397a7602L,0xa54bd48e43987d82L,0x77b6f8314f0a19faL }, + { 0xfa0c9a456e766443L,0x995ae0fff51ba70bL,0x8e242c5b9cbd8d33L, + 0x1671eb0813d97956L,0xccae388f40da55faL,0x97cc48faf376dce5L } }, + /* 5 << 175 */ + { { 0x1c2919bbe8c91718L,0x9dbb727a5097bde3L,0x23f87ae7f8ea2fb2L, + 0xe1bfffdcba310121L,0x5938c50c75329669L,0x716c63e00549855cL }, + { 0xe091b0c9654814f0L,0xa20535d10e43daeeL,0x16ce68b2593ddd04L, + 0x7813a49af59900bdL,0xef0d3eecd3e5d232L,0xe7d12cc40ee3fd4dL } }, + /* 6 << 175 */ + { { 0xe54d92cdef01fc5fL,0xc46c2ab8dda2e25aL,0x7c907fd2849f6142L, + 0xbb11dd2dacd0202dL,0xa4913a701d92d19aL,0xe9a26ae0cf610677L }, + { 0xfff1e1d5538943c5L,0x5943dcc4a47b2204L,0xcafcf33a92cabf71L, + 0xd571e13ce329d1adL,0x7626ad237a9a0e4cL,0xf0aa0d9f130d7f86L } }, + /* 7 << 175 */ + { { 0x09df3a4419e6aa7eL,0xe27ad0475841b1cdL,0x02d2a69fbde75934L, + 0xb0e05e53fd9ba435L,0x4732d88ae008c16eL,0xdebc4777ea72110dL }, + { 0xccb7d9932e3143adL,0x674f3753ea8cd06aL,0x56012a7a051562cfL, + 0x961df68425f74cd6L,0x26630e71214d8a95L,0x584e8d6365d92f84L } }, + /* 8 << 175 */ + { { 0x8a89daefebc5557cL,0x7ca71403275e1649L,0x48d923775b80bb4aL, + 0x0a587c52a45b3626L,0xdaff503cc75bfe91L,0xd845d3e6116d07d7L }, + { 0x6b5a4715a51eeca2L,0x34ac02bd74481991L,0x8f076cfc595abf8dL, + 0xc9de4ce9ed0391ceL,0xaaaad03ae1fcabd3L,0x8d48ec0087b199edL } }, + /* 9 << 175 */ + { { 0xbd0f2653ae5dd482L,0x59f968dd060032dcL,0x6bea33e067283310L, + 0xccce88cc012aa50cL,0xbb6d7f2f66838f46L,0xb764c95f05ec9bcbL }, + { 0xd097b60451477ccaL,0xc2fbda7b82b20a85L,0x75fe07a424e9ca8dL, + 0xfc4fa8240cc40d01L,0x0b17d5f90c0e95f7L,0x285e6e8a6e1e46dcL } }, + /* 10 << 175 */ + { { 0xb0641d09bc9b2654L,0xf9fcc2e68aa8fa35L,0xd12a5b4b00d5ec6eL, + 0x9be1a1115569d89aL,0x9c0566deffac7208L,0x7a9fd4ff7034edf1L }, + { 0x636aeb6b9571c375L,0x60d05aec55cdf187L,0xf4e2f898734e9d2fL, + 0xdaf742195ccdc6bcL,0x9d39249f608a4f28L,0xb5f1bb5e8820e2c3L } }, + /* 11 << 175 */ + { { 0xd02e9936d9589548L,0x8f1bf5755341402fL,0x1535a443057300aaL, + 0x3062478e65d29324L,0x4203351fc656a3f3L,0xbeb21b516569c4ffL }, + { 0x8113ce70e1f0f263L,0x59d1293903f9320cL,0x95061255d08f8936L, + 0x8be3c0f997d4b705L,0x0259742e827837c2L,0xf55ea28d95c65cdaL } }, + /* 12 << 175 */ + { { 0x62024812603dc3dcL,0x25dc5337efd67b57L,0x86b3eb38d7f033fdL, + 0xee3226b232646d6fL,0x8c4825f6f1dae596L,0xd2303055a5bcb8e5L }, + { 0x904a53493c0baa76L,0xe60f6125e08646a7L,0xaf6a329f21d45f89L, + 0xf20ad88a06605546L,0xcf7a0e9619a93d14L,0xf1eabcc891c97174L } }, + /* 13 << 175 */ + { { 0x72b76e9e8f02af51L,0xac94cbf1d580f95aL,0x2e9cd74801d854a4L, + 0x4ed4e9061f08a1bcL,0x0a2b28419d2bd936L,0xbf86350051c89ddaL }, + { 0x9407b0e7e3f00bf5L,0x6b1f71ff28b57ac1L,0xc1dfe03fcd28801fL, + 0xf3d83d64afa55309L,0x47aafba28af8f76fL,0x54eed45f6604b2e9L } }, + /* 14 << 175 */ + { { 0x59edd2640f3e541fL,0x318674b582b76ba8L,0xbf4a0d304e7f0716L, + 0x36fc0e4119b88200L,0x91db560240da801eL,0x638371ad2c72c2c7L }, + { 0xfe960c25d5822da7L,0x7a7571d14a7415e1L,0x5a6480febccc1576L, + 0x72f4e5e5c3c88f47L,0x224e7e749a7bd8ecL,0x3ebbf52c7631455eL } }, + /* 15 << 175 */ + { { 0xae3c2bc08608ab37L,0x35e3da8c39f336b6L,0x7413664281f44511L, + 0x21ce7c511d8506e7L,0x9b6718b3846165f1L,0x9e455007f5cabf6aL }, + { 0xec582a0e02611073L,0x269aa18d83bf042eL,0x7c54fb7c86306757L, + 0x453336021b948fafL,0xd3a5c508b7025d73L,0xcd6e555b428471e4L } }, + /* 16 << 175 */ + { { 0x42c9fad511a224e6L,0x6b6aeb8b69b2ac26L,0x0cf4c7fdb149854bL, + 0x4a7d90002fc359ebL,0x9ff0c3ea29ec8603L,0x157ae7859b24ee14L }, + { 0x638c809a8979e9bbL,0x347dfb2e7869d8c5L,0x2fb1e0f8a07ea547L, + 0x1e580d32aecdec3fL,0xbbf895730f74025bL,0xeb94d71bdd529164L } }, + /* 17 << 175 */ + { { 0x8670812a35d03250L,0x2f68343f1984cd59L,0x5fe890caf1ff97ecL, + 0xd47fff536f764b2aL,0x70fa44a4f8f7077bL,0x7b287efcb2c7fe02L }, + { 0x0718e70806dedcdeL,0x37193c827172c0f6L,0x47ad55f67b7f28a5L, + 0xaf83c4fe9c71a96fL,0x2d6075587c490626L,0xe647de1b933e9033L } }, + /* 18 << 175 */ + { { 0xdc5909e3f1687d4cL,0x4fe3be46d431c5a7L,0x28c41a035f9807beL, + 0x2c4203fd12f1f8daL,0x13f12da450a19620L,0xc32f881eae2e9835L }, + { 0x56328ef7622587d0L,0xcf785f038f209f66L,0xb562ea70a2697748L, + 0xa762289055598769L,0x9842bfa8fbf41fd3L,0x304c3057fa401ba0L } }, + /* 19 << 175 */ + { { 0xb8d685d1c56bc716L,0x1eceb18f1fccc358L,0xf94bedc82034cabdL, + 0xa9acaf11ad003472L,0x6fea0a55ad0786c6L,0x60f7f9a9581f6f52L }, + { 0xc4736494400bcca5L,0x221d8f8a3606b047L,0x533756fb6339c7fdL, + 0x1e068e987510c1a4L,0x9bf9abb6ededfa09L,0x96895ce548d54775L } }, + /* 20 << 175 */ + { { 0xc995b0171552c477L,0x6f92a95252351781L,0xa9d4bb6c4da25dafL, + 0x2b02828e3cf6aab7L,0x5f4febed11fa4d0bL,0x42f0e61ea12d9d37L }, + { 0x1ceef875d24610d0L,0xa7c85c485d4eeceeL,0x33fcfa3b79340a49L, + 0x3671e563b00b3491L,0x871f74e493eade0fL,0x1ed095182c546f3eL } }, + /* 21 << 175 */ + { { 0xc003b709a9a5c68eL,0x9441e7b26c84310aL,0x7ec3b652dd90f7c5L, + 0x17e601685b526324L,0xc5f77fee479573aeL,0xe89beed18453fe7eL }, + { 0x259a2b0364540cadL,0x8c2f13322b9a8053L,0x1db53ab7304940edL, + 0xcf780c5d1612763dL,0x2edd7285e19b62f9L,0x20ddc9874abdd7a5L } }, + /* 22 << 175 */ + { { 0xa70aa6781250954bL,0xe4a2f7cf2930f3edL,0x3e3dd26666fd719aL, + 0x500166cf792ff463L,0xeccd32cd75cf00a6L,0xb65f46a5c4526e56L }, + { 0xfc3a99c360aa8cd7L,0xe04a18b31290b20fL,0x957139a218cb9326L, + 0xf6b352ce11fc04a5L,0x9314b80778534e64L,0xd4a265c52d8f5015L } }, + /* 23 << 175 */ + { { 0x7078b4820dca1fd5L,0xec3192daeed504baL,0x144183332d06a63eL, + 0xaff9f7bd69c01ac1L,0xc5fb50475b74308fL,0x37846eeaa67e7ef4L }, + { 0x0fcea663976b931bL,0xd3407d42bb345b71L,0x925afc36a2deb11bL, + 0x12c271092207db49L,0x237500002e1c8fbeL,0x41427e0763f771cfL } }, + /* 24 << 175 */ + { { 0x9dafbe96491ddae9L,0x92c60b897741da5fL,0x1185b001b866ab14L, + 0x7a43b9cfca7f2f81L,0xaaeb5efc6ee8fdfcL,0x1f7cc70022beba9dL }, + { 0xa212724722e3e7cfL,0xb98dde1e9e723477L,0x87832183ac89706bL, + 0xdfb92ac1ff72f1d5L,0x5877fe6daade3804L,0x7ddde4a79170b9acL } }, + /* 25 << 175 */ + { { 0xdb147da0b7df600fL,0xbef5374660a8b100L,0xb4c7e404a1330d14L, + 0x152c6ae754f96693L,0x08884fecb25fd94dL,0x8ec186048ba59001L }, + { 0xdc245c0c9f8e77fcL,0x2be5aaebc0f0a83dL,0xd15bdecd1fd13525L, + 0x46b603f0821c9224L,0x6b335a7daf6dc128L,0x4cead4f94dc6b5bbL } }, + /* 26 << 175 */ + { { 0x239cccd8179fac91L,0xffa076063829d42eL,0x75b8589cbd42a0ecL, + 0x012f5e80d7f2292cL,0xdcee7efd99c14665L,0x4925256d23650737L }, + { 0x847c86ecf3cc64afL,0xdd34a75feabc04fcL,0xc2f73b3ac6a1f710L, + 0xe16e317565cbf6fcL,0x9cccffee351461d9L,0xe3d635543b4fe4b9L } }, + /* 27 << 175 */ + { { 0x6e27de1176ece8f1L,0x3ca873a79d5a3cb7L,0x7d65cdff7e424482L, + 0x023e5bcf69372216L,0xae601c2f2ffeb5a6L,0x8c8888cbde130b33L }, + { 0xcb8309485700ecc4L,0x5a1902ef9dfe1891L,0xe01f5fc558198380L, + 0x9d5d1c476c59f973L,0xacc64c98e34cc41fL,0x057d81f03065d870L } }, + /* 28 << 175 */ + { { 0xf3a1a9797aeefd73L,0x3fb166a09537abf7L,0x39e8c469d4c37607L, + 0x3efc85650e3f034eL,0xc955c2dff9c25655L,0xd6ce96ec260fa449L }, + { 0x5383a8b831d8e6d4L,0x3aed2e761a3595dbL,0xbd269c39e22a0f45L, + 0x4c82238694a7a83cL,0x362f08055731bd0cL,0x7dc1e7ee0527be95L } }, + /* 29 << 175 */ + { { 0x606ffedfd41ce228L,0xb87608d0ceb21740L,0x6fa23c0794a4354aL, + 0x587a7c54d5061d84L,0x75678bdb16b823ccL,0x2d2163c94ec818afL }, + { 0xa80b1e4e22c6fcaeL,0xc07cebee4d2a4b65L,0x64f303c7a895e2c9L, + 0x750079f5a768a2e6L,0x0665502c2d423133L,0xaf33176715135cdcL } }, + /* 30 << 175 */ + { { 0xda8f7878c715abf4L,0xc62292a5a5830c4dL,0xfcd30f7e4b46acb9L, + 0xb931f1ee39a73db2L,0xf838a5c84ee1afb0L,0x15609b57c202a921L }, + { 0x2e21871620bbba58L,0xe1d2fa14ae2615cdL,0x0a4dcf3543946185L, + 0x2e80d804730d2490L,0x5e43dc17794246b6L,0x7b3588c8dcb3be9bL } }, + /* 31 << 175 */ + { { 0x3e74f09c1bb8e6e2L,0xac587847584dba0dL,0x926415593f843324L, + 0x0033257729f3ed18L,0x4b7164e5d0089537L,0xc50542793e54c9a0L }, + { 0xbae7ff9808e58162L,0xc0707d03c1aa2fd9L,0x43524f717714dca8L, + 0xa202a0707255b169L,0x0a7867ab4249b2e0L,0x03f748656d6ec5e9L } }, + /* 32 << 175 */ + { { 0xfa2db51a8d688e31L,0x225b696ca09c88d4L,0x9f88af1d6059171fL, + 0x1c5fea5e782a0993L,0xe0fb15884ec710d3L,0xfaf372e5d32ce365L }, + { 0xd9f896ab26506f45L,0x8d3503388373c724L,0x1b76992dca6e7342L, + 0x76338fca6fd0c08bL,0xc3ea4c65a00f5c23L,0xdfab29b3b316b35bL } }, + /* 33 << 175 */ + { { 0xd2437a52eddd4b72L,0xe2cec2abf051b831L,0x845af98e482a4ea4L, + 0x75758ccfa43cae82L,0xa76733429260ea35L,0x77845b02b1dd602aL }, + { 0xb78bc4c047d5c450L,0xcb1f444550ad371bL,0x6bc01293d71cc417L, + 0x8538f638c1fcb367L,0x5d01d35919b313f3L,0xcd6b55bfcf67f6acL } }, + /* 34 << 175 */ + { { 0xc28000d6e3b03290L,0x4dd5064a5f2ddbcdL,0x4916f830338a1414L, + 0x3ffb8381aca74c22L,0xec073ee8e680f548L,0xa34e0693a0430cc3L }, + { 0xc6baf20dca03e6e7L,0x2a30df6e835fb88dL,0xbf3c9e9cc2092d6bL, + 0x391cb25c17bc2433L,0x9b7de7126c205c0aL,0xf25e1494cd2a5e62L } }, + /* 35 << 175 */ + { { 0x05ae44e9d21fdc9aL,0xc520657fce40ebbaL,0x6b8e25431270cb59L, + 0x24e6f9bff7f096d0L,0xc6ded76a3ed81f52L,0x729d05e75f7df798L }, + { 0x99e2636fe5468eb1L,0x6f3abd4c00419facL,0xfc61117a9cc41e09L, + 0xb16f106baa399a51L,0x05603bc845e52713L,0x612658aca5c36107L } }, + /* 36 << 175 */ + { { 0x107573b96defe8f4L,0x9a9edf0570545313L,0x5df43df0e54e8272L, + 0xac91bae8eeb4ae90L,0x241d54bd26006ab1L,0x0ba118a6c031de7dL }, + { 0x376214671f500d4fL,0xbbd6b318bc3596e4L,0x4b5532c85992277aL, + 0xb15165da16a4728bL,0xbd7986d45140abdfL,0xf4fe16df7386f38aL } }, + /* 37 << 175 */ + { { 0x8c5d305696aeee65L,0xe52e500ea79991dcL,0x3af4a3ef343fdde9L, + 0xc6d0389b248ad10cL,0xc3dbdb3f5014de53L,0x606b1352310a0cd8L }, + { 0x65af3f8479bde08fL,0xa6c7d968d82ab682L,0x7262c07d202a6508L, + 0xd0231bb64cd75fe0L,0x58a34ca5dcb1f7fbL,0xcc8b21b21b8cf7a1L } }, + /* 38 << 175 */ + { { 0x4cd6e61be824653dL,0xfa02c0c9f253dd65L,0xab198e41b1e84cedL, + 0x89ce6aff1928be7cL,0xf2a83f4895afb956L,0x5b5f195ddc73f3a5L }, + { 0x44220ff79328317bL,0x03d62cb7f5239616L,0x0e908d34b5d49415L, + 0x050b7651c1f7e665L,0x3610167089e1a98bL,0x564abb3418eb7644L } }, + /* 39 << 175 */ + { { 0x400b363b2eecacf6L,0xe2ae5bee1ed9fb9aL,0x23374b11831e99c6L, + 0x0a8382d82cb9de95L,0xf95b8e052dc02291L,0x63b05a0d2f752257L }, + { 0x9ec16f84b60d9df4L,0x6ed683ac3bda5171L,0x7206450813acca39L, + 0x6024af3cf8871ba1L,0xbf88040e2f9a4d56L,0x001054149fb100e5L } }, + /* 40 << 175 */ + { { 0xd52c606375ccd2e3L,0x4fa8e4df56ce654aL,0xcd905c9bce581d23L, + 0x51ce0eab24ff75eaL,0x1c1c0831432c6e5fL,0xb83307aec02f0e86L }, + { 0x0b7a0274fe2ee821L,0xae7dd7729c3d69faL,0x54745da5931ed75fL, + 0xc276d96f18caba13L,0x142571dd26dd9792L,0xc522dac16c0e3167L } }, + /* 41 << 175 */ + { { 0xa86fa630197b5b97L,0x749ea479fa21c176L,0x520c0e4871ce7101L, + 0x5c53d9ebe30a0b0aL,0xdc71b629ceb570feL,0xa30fc3d11fa3699eL }, + { 0x741321b579cbbfa4L,0x205ea0aae8d18119L,0x94556e92fc62e0eeL, + 0x5ba78d4e042b9c3cL,0x14de84103fa24a56L,0x6e57a9fbd6557bceL } }, + /* 42 << 175 */ + { { 0x2a5e716ff103d9c9L,0xda2f7e5cb9cd27ecL,0x317f74b8e047e5cbL, + 0xf1f496d33a4413feL,0x1a480a9cb8cc9fdeL,0x502b52d7575208d4L }, + { 0xf14fe00cd19c49a3L,0xf5c2367b269be5a9L,0x966a524f12d42690L, + 0x2786ff714dd03b95L,0x6fa1f891d69bf68dL,0x0f3d77579f67b3bfL } }, + /* 43 << 175 */ + { { 0x230c8d00c966c638L,0xde5c9e8e54673305L,0x618b0dd561bc99faL, + 0x669618048f3cb5c0L,0x7c653ca507141ba5L,0x454d54ff32ba155aL }, + { 0x82665a307df3e39fL,0x15eb1a65ca19cbb7L,0x4e7632a617330ab3L, + 0xc69235295a3221b4L,0xe23ee9382eb58e9dL,0xb320aa8e23bcf88cL } }, + /* 44 << 175 */ + { { 0x6ba15fe607a7ecf8L,0x93127926f831cc91L,0xfde2dbf41ff6264fL, + 0xdf7f22018413fdb2L,0xdd81d11487f66260L,0x87907f0e4a87133dL }, + { 0xeac1032cb1d47e23L,0xe2603119125a0918L,0xba680392f2259208L, + 0xb7c7f8ebf9bf06b7L,0x875a380fa56ba57cL,0x05a88a97460c939cL } }, + /* 45 << 175 */ + { { 0xfb2871b7d0dc771eL,0xd12b21fcbaf358c9L,0x30dbd412df616c16L, + 0x291bd90f9345e16bL,0x92f7534b8ee6bb6dL,0x7ebc5b0eb1c901a0L }, + { 0xc9e9c76151e1881aL,0x5ca52152756bfecbL,0xb0a9f5cb6affd506L, + 0x4c12f965669feb3eL,0x01d84b9ea6f1c529L,0x3870fa27e8433c92L } }, + /* 46 << 175 */ + { { 0xe4e9e72495bb5db0L,0x86babe3ffd616958L,0xc1520c280f93c1cbL, + 0xe393ded539cab777L,0x031a2af3e86a6ca3L,0xb26a19101e8466eeL }, + { 0xb16b746dbb64fd81L,0x4e96f0b65a97d50eL,0x7a12a611a793fac2L, + 0x8d729847db6482aeL,0xdd050ce812e72ce5L,0x915041366c54299aL } }, + /* 47 << 175 */ + { { 0x9e8018c06b63c4beL,0x49dde0c8fce47904L,0x1668de9c9bae36cdL, + 0x8dfb0d5f80ed18aeL,0xfd6739a791e1949dL,0x80353c9f8053d7d6L }, + { 0xa611699bdea54710L,0x5eacf16e6c6c1f5bL,0x5212fbd3c920323eL, + 0xaf75db75848d085fL,0xb58564b1babb45b8L,0xefa1958938bc491dL } }, + /* 48 << 175 */ + { { 0x0a43a76c2f95a081L,0x27eaf2bc38b1c395L,0x6ba3222c63da1d80L, + 0xd95ae17e6a78ce09L,0xa72d9812508f03b3L,0x9f36d02efa8ed359L }, + { 0x1716d1dcd5118f96L,0xd116339f489bbc53L,0x272153ef6f7e1d3dL, + 0xcb4a9e739e308d22L,0xcfa9d88b615a3646L,0x8b69bd6cde454569L } }, + /* 49 << 175 */ + { { 0x33ae0fec2b8f41feL,0xc45aac500762c46bL,0xa03bc6ddf228ec44L, + 0x82cb78cfea3d48c2L,0xbe7a02ed27126795L,0x1a44d1f830b3e3ddL }, + { 0xb414edc73be7b58cL,0xb3e6c7ce331bcbc9L,0x9f6fd0f2903b3508L, + 0x260c8b5736cc2930L,0x8581a05d0d59278dL,0xfac1817b189b3005L } }, + /* 50 << 175 */ + { { 0xbf4d4640cc9a69c3L,0x07b39b5d67d262dfL,0xcd4a6a4579526d6cL, + 0x4a04c430538143caL,0x6c3341b86639e3b0L,0xd490cab5ab7216d4L }, + { 0xedda2b64a2a93161L,0x04e309de644a06f3L,0x7cad728a8c4495fbL, + 0xe1744f3871dd61f4L,0x39cbd782e3201618L,0xbd66e1850ca18ab4L } }, + /* 51 << 175 */ + { { 0x69d8237f87dcb8beL,0x3f9a485b090e0237L,0x535371e1f117a1c5L, + 0x0d5ef52675430c29L,0xcb9c150898fdd18dL,0xc7c1a7b4108d9383L }, + { 0x6ba9fb4d98064eedL,0x07d205a9a3df31c8L,0x7a0be62e9be5da37L, + 0x03b21b1255a9e2c2L,0x3f4792263de80449L,0xb0160ee1ae3bf31cL } }, + /* 52 << 175 */ + { { 0xa22c084a7a3f8c5eL,0xeb7fe23f3ef30511L,0x161ca862819fa38aL, + 0xe5f014156d45762aL,0x37da6bb95718b789L,0xfcb682bbd837f453L }, + { 0xc49c7397275e5974L,0xbe908df5a1ed0925L,0x3dcd694615a13ea0L, + 0xdbe652e32596fa76L,0x6a3bcc93c55d376cL,0xa2f7611933a0f02bL } }, + /* 53 << 175 */ + { { 0xdfff9b9c6ed061ffL,0xa36aef2dec32b16cL,0x9f3b7ab6da61572dL, + 0x96e72a027ac2dac9L,0xb0e36e023aaf4fcdL,0x5f32a620503004cfL }, + { 0x6c91dacbadcd649aL,0xb25deea21ac02a32L,0x211a421ffb914c2cL, + 0x1ddbd60e149fde1dL,0x91c4cc0d7ce86ad3L,0x8be6f031b9ed909cL } }, + /* 54 << 175 */ + { { 0x62e773c4a0cb50ffL,0xe54fdbdd2e903681L,0xed2bce9e21c12ca9L, + 0x13aa4748c072bae6L,0xb290c0ad475f290eL,0xcbbc3f9b56698a85L }, + { 0xfb37611b1b7fff76L,0xe62a842260bc2e36L,0xb6a36c783bb20fd4L, + 0xdec045418dd69509L,0x67648b7798a1ad2aL,0x4fa2005d078fdea3L } }, + /* 55 << 175 */ + { { 0x757f249416307553L,0x865af9d0de6bcb49L,0x3943031a07b0104cL, + 0xe5fdb46168da2d33L,0x4937d614b5432b48L,0xb3fbbf2c0a29a5e5L }, + { 0xe7d3b12b8de89887L,0xc1a43c24e41258c3L,0x91ac7eabf7d9efe4L, + 0xfd90de0088385cb3L,0xead102e37674c39fL,0x7b9a2cc4fff118c5L } }, + /* 56 << 175 */ + { { 0x11f92678a1e598f5L,0xde8052491fbb882aL,0x3730b3261154d0aaL, + 0x0e279827da521670L,0xa03c8c702336f8c0L,0xae50e64ff0bd66d6L }, + { 0xfbfd665f7af4f681L,0x237a4f4e5c8d5680L,0x6527611ba409064fL, + 0x1f4eff6a99db9a94L,0x4a55d96ae53ba177L,0xd9dec234f002368aL } }, + /* 57 << 175 */ + { { 0xbb837d0ad193ebc0L,0xab1e3eccd09b24caL,0x229f36d81d848777L, + 0xee895edf0ab68c98L,0x67fc65f4dce31b92L,0x777ebe585db96c26L }, + { 0xca0893ae6047d0d6L,0x71a2ca0b550d6905L,0x35426866eac4c2e3L, + 0xb4d7e78e0c1b8eb0L,0x03cb0a9a84b384e4L,0xd8a99a5c7f7115b6L } }, + /* 58 << 175 */ + { { 0x07db8bfa5f25a74eL,0x97dd568a3dd8e706L,0xcf4c02a32fb59efaL, + 0xe2ae502616b291e4L,0x5499f3b20f9c10cfL,0x59abdcf5a7297ec7L }, + { 0xcec282671f4a3646L,0xc10ae0971e065cb1L,0x172f886319dbbaebL, + 0xb0c27f7d73dd068aL,0x764d185495086ceaL,0xb89923c732de9a97L } }, + /* 59 << 175 */ + { { 0xacd499ca093345e2L,0xfbdb3895f3c23800L,0x2584f8ca02f0fadbL, + 0x9f5dc96ec2f35eddL,0x4dd102ca1ba0266dL,0x13ee9c8aa9f26fabL }, + { 0x9e7467fa2a1e61daL,0x999764b6850191c5L,0xd053a575b70dd8dcL, + 0x697b856fd7065eb7L,0x9d5bb6aa695b4914L,0xc5cdd170e65001f1L } }, + /* 60 << 175 */ + { { 0xe87cf622e93495f0L,0x347b09c6bb43a802L,0x2a38f3b7a4e3ac34L, + 0x13353b959751c1c4L,0x753ec3ecb3947985L,0x3bf856dc12d3fa90L }, + { 0xbf4f6fa5ec35dbe0L,0xd099a15bf3b4fcf2L,0xb348462fbfe7245bL, + 0x508324b352a2d4f4L,0xec4bae05feee1315L,0x468fa9e404496618L } }, + /* 61 << 175 */ + { { 0xc57673257d5e7a94L,0x40c05da604cefc01L,0xba1fd6c6b921c681L, + 0x0d3e09f9c104cedfL,0x4b7cd83cc6586416L,0xb747d7f9adfa7bfaL }, + { 0x833f8e24a42be782L,0xd5f0421d06b2471fL,0xac87b17c22e4b84eL, + 0x85af6b063a10c7bbL,0x4e557cbf66e88e2aL,0xaff21b66d3751e40L } }, + /* 62 << 175 */ + { { 0xdbab25f4c4464538L,0x3c36560ba93d7f74L,0x8b9b15d39f86f410L, + 0x1237e35b0a1db237L,0xc9dad97994f49677L,0x390a3d8f15dff99eL }, + { 0x0a74dfaef82c19edL,0x3f8e958589c2dc55L,0x763448ce94a8e729L, + 0xc6349398625f0517L,0x1ca5f9e7523dd700L,0x45aa25317fe638dbL } }, + /* 63 << 175 */ + { { 0xe91af601aad04ed7L,0x6f86f323e897df2eL,0xf8c259564c7a0ab8L, + 0x6e793f3633845d15L,0x08937ef5e583d043L,0x92dafa5824d1fd96L }, + { 0x6458ae2a86c9aedbL,0x271823a026a4252fL,0xb119fe4c5a57ef16L, + 0xf41e13943a507289L,0x0cbf1da6bd1aa499L,0xa177ac9dc2465a51L } }, + /* 64 << 175 */ + { { 0x14f962e404a8313dL,0xc6e3e7c45f1f5a26L,0x2c0e11c079e777beL, + 0xa1705efb4657c31bL,0x02688fd23c494de3L,0x75664a84412a8718L }, + { 0x878fc7ad7a422f8aL,0xe5d581df7419bd0aL,0x7c813c4c704b70c0L, + 0x98553da87323c008L,0x4f63cec663089f1aL,0x9626d6fa9655d291L } }, + /* 0 << 182 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 182 */ + { { 0x10586ea7507f8b27L,0x1510deb9a261f7d7L,0xa42fc4d7dfbfa352L, + 0xbf38c3821e1c2291L,0x46e40ef60e11760aL,0xc24f6061dcb974d7L }, + { 0x755b105ba7619027L,0x8004bf09b8ffa759L,0xa630d0b00945db60L, + 0xa160ac9cf2809e1cL,0x38fc1113dc6c95c5L,0x01f540985d52574fL } }, + /* 2 << 182 */ + { { 0xcda68a7e698ee21cL,0xc7414d196a5e725eL,0x483be2dadce20b91L, + 0x7de1601cfc69dca6L,0x4bec17aaac4f9891L,0xe8741dd18d479a56L }, + { 0xc623cb8dac23a286L,0xe20a96b5166133f0L,0xda9bb7c030dcde61L, + 0xf84ea3273a1733fdL,0xd7afb6c3e82fac31L,0x37ea7d35d3897449L } }, + /* 3 << 182 */ + { { 0x120649b20370327bL,0x0e76555acd48cdc6L,0x4ed54decca01db03L, + 0x7be21319ac601d22L,0xf711661901b6576eL,0x7839fa064e73537fL }, + { 0x169d43ace46e860aL,0xde6d658c3078eed9L,0x8df731395032142bL, + 0x6be199b09b3c76c7L,0xc2f385f6f8bbffe5L,0x848df7f3d5ffd28cL } }, + /* 4 << 182 */ + { { 0xa189f30fc6a6d6d1L,0xdd674d3669665ab8L,0x307c9ec37d8da76dL, + 0xb3e1d006c1ea7c10L,0xc15e20b3b88c62d4L,0xb0000ec50bff3b3aL }, + { 0x9e330eb19ff9aa5cL,0x8663f9fddf578877L,0x157d3cb002e1eb2aL, + 0x638f297bf525e4d4L,0xa20f833234a3dff1L,0x748ea86b45a9c051L } }, + /* 5 << 182 */ + { { 0x978ed3abe664c066L,0x3f4a8e0d668361eaL,0x0ba610c753a25231L, + 0xa8b5b864189143c6L,0x0d7ccefca2841fc2L,0xa80dd8f3f8fea1e1L }, + { 0x2c24af232e19028cL,0x0e332b77919decaeL,0x44eae977f6089c76L, + 0x25e04dae53722e9aL,0xdd6f8b1f71ac4db0L,0x7c5b6ffd075e7bc4L } }, + /* 6 << 182 */ + { { 0x4c6299a7a1de1cc7L,0x362d293c02d9445bL,0x08f24df0399a9494L, + 0x33307792e37a1851L,0x1cc5e448760f680dL,0x70a6a8164a2efbefL }, + { 0xee939681246fc671L,0xfa7a26d1f70a9c14L,0xfae5ca89b826aab5L, + 0x6b8932c7e48176f9L,0x379f89bd9841c8e1L,0x46141d2fdb674190L } }, + /* 7 << 182 */ + { { 0xf4408485b4619d3aL,0x34b4f18160b4f44eL,0x369edc1b3532caf0L, + 0x2d0471ec6771abc2L,0xca4129311013266dL,0x02e636af617e2024L }, + { 0x1f93d60d3c69696cL,0x6aba7f2a1b99a172L,0x896873e1bf435ce6L, + 0x9649f08215b71e40L,0x730bedcfa02b024fL,0xb17e9cbd8df60bfbL } }, + /* 8 << 182 */ + { { 0xfe9fdde8bc266ee3L,0x91668688ba18e6c7L,0xa65349acddde6f6eL, + 0xc53c29c97e54356cL,0xee15ad945709f73cL,0x033b3940e5429277L }, + { 0xf52035cdd0c3475aL,0x9c5bef4d93f1f1f0L,0x26e0b0ceca319bd4L, + 0x4e7eb67b6951fd8dL,0xac3a6f4395c34d6fL,0x1f2769e600f60b59L } }, + /* 9 << 182 */ + { { 0x95188c136c4d0bedL,0x377a04901b5271e7L,0x60db30226a540165L, + 0x4be61fda3310c5b9L,0xbbb4fbe93f8bbf16L,0x5232fb46ac12f77fL }, + { 0x8d6f75ab255b569cL,0x09cc854d3bd39650L,0xec17a6e74b557c3eL, + 0xd6949f9d5c3d149fL,0x9a17a440494b18b2L,0xc10cb9d5d4a024acL } }, + /* 10 << 182 */ + { { 0x4520be6b8eddc97bL,0xeb8f2c317391f948L,0x18fcbbd772369418L, + 0xb8950ee217246882L,0x6b1e4b7a382e82c2L,0x9e2bb1eb7ea4c447L }, + { 0x5202d913c3c5bc54L,0x53ea78cd21352716L,0x7bd53ffb36e6b4ecL, + 0x8325bdf817387196L,0x33b2cd8af94d6a73L,0x206bdec5e13db4bcL } }, + /* 11 << 182 */ + { { 0x6e27ce2609c98c86L,0x8f87ec4c958002c2L,0x00b6897064ab26edL, + 0xd2b4037282e5e129L,0xbeae654c78c48327L,0xc0632b4341a54107L }, + { 0x7b1fc7f001562313L,0x01cd1b5c1fd6a56cL,0xa199a69835e71626L, + 0xb02b2692635fbcffL,0x1c0c4200a0632386L,0x637164f8d6c670e7L } }, + /* 12 << 182 */ + { { 0x2c47010d18e30ee3L,0xb7d4b1dbfdd5f040L,0x5c8abe509d930f6dL, + 0x6bcf875d5f56cf04L,0x1f6456c0062f1fc1L,0xc79597805304d710L }, + { 0xd76452e4db85dcecL,0xd531f73fa0cbf90cL,0xb5ae9fc89021bde6L, + 0x505c6b9f4babfae0L,0x99d943c17ea61fd6L,0x6ef4766159bf125aL } }, + /* 13 << 182 */ + { { 0x3a48020daa0b0a5dL,0x4a32d4d658bad0dfL,0xe013dbde2e4340ecL, + 0x99efac69a5fc51f3L,0x26acf7a669ee64c6L,0x36672d6566fdc9f2L }, + { 0x77426caedcb879feL,0x0166194676e3be96L,0xb6fe4709b2dac331L, + 0x1f3d8a63678ff3ebL,0x711c0ea447bd5865L,0x5fbe38e87c080adeL } }, + /* 14 << 182 */ + { { 0xd0891b2df4e61379L,0xea2c7ceb9941c391L,0x1441a2d099677e8aL, + 0xc29d88c8abcb3669L,0xecb1a21a06ce9bd9L,0x0663fa7cf5b11fc6L }, + { 0x440a5a1c0c44c2c8L,0x08d71bc39fdded3cL,0x62b53ca512d33d2eL, + 0x3fb8640e005e8adfL,0x2a9acaefaa2673a5L,0x356ae6f6695f8448L } }, + /* 15 << 182 */ + { { 0xcf3c9b318496d935L,0x7e849aff8ceefc78L,0xfc06a46e7a5d692dL, + 0x87248699e89463afL,0x4dc55e5e8e17af3cL,0x3378832fe41ec54cL }, + { 0x7578d6192816f87dL,0x505845612806d3cdL,0x7354f1022754c3d7L, + 0x61ca6cac08d64863L,0xecde4969eb9954ecL,0xe0c211b4a1a5dae0L } }, + /* 16 << 182 */ + { { 0xbd10b8bffb787270L,0x4f0b1566e43aaab6L,0x9a18be5ec0c90781L, + 0x3677f4c71ad167ceL,0xccb254e2a68c1c56L,0x392493e6e2c4d275L }, + { 0x44958cb1d5b63617L,0x178f141a4caa4e7cL,0x7445a767a2ffdbd5L, + 0x0e789c99b0b6c22dL,0x3ff8b6565dc92b2eL,0x1623e5c3eca98782L } }, + /* 17 << 182 */ + { { 0xcb013ff62c5c50daL,0x5e5550b70b256dd6L,0x38249ee1bfd47036L, + 0x984daee275379fbfL,0xfb35304588c6bc7fL,0x32379c955f9683aeL }, + { 0xbcb4ac531b5a8626L,0x1057d2a3bbaa0deaL,0x114ef8a7ffa8efb7L, + 0x553a34566da90cbaL,0xa2ced0b21a365fe6L,0xcec4d64bb1ccdb57L } }, + /* 18 << 182 */ + { { 0xe0312b66b81fe0eeL,0x11e0493b892c7b21L,0xb6a1d76e624ce73bL, + 0x38768ec0cd75cb6aL,0x425b091f2032c271L,0xa88d39f55b5d8338L }, + { 0x1496b9ed1916be43L,0x14468e3054549f3cL,0xd429c2c47248e206L, + 0x21a1c212fc9e892aL,0x0feb5822640c984dL,0x0cabfb472b7c0c66L } }, + /* 19 << 182 */ + { { 0xcda1c4cd1cc5a20fL,0x33d66a893f67814bL,0xbba50d5360ce82edL, + 0x9d34dc4d70553a53L,0xc926f498a8a1442fL,0x9dfe3cbccbb43feaL }, + { 0xd25887434fd3e4efL,0x7443a9a9a371d894L,0xb53e6afaa22bb4f9L, + 0xcef3fa347dfc9da4L,0xd079ded047403836L,0xc6c97c36d39aa93bL } }, + /* 20 << 182 */ + { { 0x6618fcae534f6370L,0x1635580da1a864a2L,0x90ad39947d7ce552L, + 0xbf8c45895257f24bL,0x5a9499202098768cL,0xec1eb621bb6d8830L }, + { 0xfae8f161f1f9ac16L,0xfc9184ca35704c99L,0xa72b1ea9139ea04fL, + 0x82229a912e39e1d8L,0x4153bf3e479c7bc2L,0x83325be4c5541825L } }, + /* 21 << 182 */ + { { 0x358a91badbea81d1L,0x4d1947d7c669c7a9L,0x4ca6d8f18eedbfcaL, + 0xf9eda237069b3b93L,0x9e1217e5a35ea963L,0xb7e16f08ab960c77L }, + { 0xf440d825fb313db7L,0x804c5262101c5424L,0xd236a0edab3c4f7aL, + 0xf8bdb2b1c2682459L,0xfaa7aacaf46c4d70L,0xcf6ce4adae83dd7cL } }, + /* 22 << 182 */ + { { 0x2c7756bcbd452842L,0x2c47593cd1783fd8L,0xa4f41583a7527697L, + 0x2fddafbbd1049934L,0xc087f3db6c71063fL,0x8f5a85c4c9b3ef6cL }, + { 0xbe178bc966a975d0L,0x2e2d825b94066514L,0x061dd919e0d42ba4L, + 0x964fdcfb227ca011L,0xcb915b2973d7ba7aL,0xaa7f2fa72af8338aL } }, + /* 23 << 182 */ + { { 0xbdbb3440734e8984L,0x8b9b7acb3d6f547aL,0xfc4f48ea0e76a07cL, + 0x49758a9f97da0c23L,0x13f4254a26958261L,0xdf1fdca2adb3ef57L }, + { 0xfafba40d699460e6L,0x71b2de39cd5c94c4L,0x52d76b76c21cdf0eL, + 0xbe75960760f3dfa3L,0x519d4fcb7078f5e0L,0x4bd8ca7f5191e1b3L } }, + /* 24 << 182 */ + { { 0xfadf9be978207cefL,0x97d5ba569cb5718eL,0xcbad24ec2f995393L, + 0x6236a26861203303L,0xe4bafc336589a4beL,0x6cba77185e23fa82L }, + { 0x8ccbc5774583e65aL,0xe5d88bca4bc2f415L,0xe6bc2d5841df8dd1L, + 0xec24e1d914d31fcdL,0xacaaf13efc26010bL,0x7e1da447e01b92f3L } }, + /* 25 << 182 */ + { { 0x2b3477ec1a29de39L,0x30a5c2190a8720eaL,0xf593ec729775bad0L, + 0xaaf607792af7dbbeL,0xaace90d4c7cc7b59L,0x6eadf21d40509cf4L }, + { 0xb9a5f138096d00fcL,0x3896d42625b206a0L,0x0f28f0f09dcaa5dcL, + 0x2ef6f9f9a8186106L,0xd212710fe25b4d04L,0x0cc6d2878b9847b2L } }, + /* 26 << 182 */ + { { 0xe7407327cdfb2baeL,0x06745198510c3039L,0x8a913ba74da758e9L, + 0xc882e7bb1a4797abL,0x0f0d8eb5dd7b375dL,0x90ac5223dcff3f3fL }, + { 0x8443b7cabbe341a3L,0xa7cba7f22f173bbcL,0x04669ff830e5c327L, + 0x0edd0eac09b777fcL,0x2a70898bd71e0cb2L,0x881c48929bd983bfL } }, + /* 27 << 182 */ + { { 0xe4847c654e7603f4L,0x826cd33c0bbea366L,0x95727caf2c4ced28L, + 0x580313dedb8ac1e8L,0x6745673701363cb0L,0x540c35ec0ff13cc9L }, + { 0x878c86fe3c4fc263L,0x4d81f8aed14e7c78L,0x6f7cf97e8355ef22L, + 0xa2aadbc848a0aef8L,0xe0200ecf4fc3c61bL,0x7e58e6e0c8094ab1L } }, + /* 28 << 182 */ + { { 0xc52789bbf2d3bdc6L,0xd38673fc3b23d7a0L,0x8b6df95aacafbbfaL, + 0x37afdcbdc7f6eb6dL,0x57775bdd6cb4c9d7L,0xc34e5a2711007453L }, + { 0x903e5ba1b5faf98eL,0x811e142a9d4a8a45L,0x046d18932d7ac9e4L, + 0xe2fe9d1543ce66a8L,0x44b5beb4d4956410L,0x7c5f1b9ebb147f72L } }, + /* 29 << 182 */ + { { 0xd51033f48312b074L,0xc98fe29456f898d7L,0xa8d6433be8eeebbaL, + 0x50bf170976fdbb84L,0xdd95f89d43c14baeL,0x13f9c7366307bca5L }, + { 0x3cd12e2855e7bc8fL,0xe2d7482c3a52581cL,0x12a2c6c7b59eeb8cL, + 0xf98f79124ae87ffcL,0x41eb808e80d7bf65L,0x589970f2015e20adL } }, + /* 30 << 182 */ + { { 0x200a764a6333b070L,0xa0acd8ecdf0d20d7L,0xbc1c589953269941L, + 0xed7c9192b439eca8L,0x057c50eeb789f0cdL,0x31dc2d36a9c794a3L }, + { 0xe3f2d38dd58ef984L,0xdb250da69235b084L,0xc2ff1b49da05b500L, + 0xf2ea6cc50387c539L,0x8250353a3d1004cfL,0x69103201aed0bf97L } }, + /* 31 << 182 */ + { { 0x495cd7fc878e97f8L,0x6397fa8b61120b1dL,0x20b9afddc8708907L, + 0x84f55bb97be2ee80L,0x996fcb9d8d075b5dL,0x2e94d95ead858627L }, + { 0xf786143e77113ebaL,0x6fec684f7b3fdb28L,0x4be44fb211d10d07L, + 0x4b3478e2372f16b6L,0xec8d61614697ca58L,0x097d241c3a45f335L } }, + /* 32 << 182 */ + { { 0x6f6a6104899ef333L,0x95496f6d39067165L,0x42fd9a6ab51989e5L, + 0x1b60ce0f68f5b168L,0x97324d8756f7fe67L,0x443812f7676815a8L }, + { 0x265ee994685a7260L,0x342c7b2f6c6515f0L,0xe909232334b4adb0L, + 0xddcd233e1e5a8d18L,0x3dc5b27c5f4f6456L,0x9664533a7f421d9bL } }, + /* 33 << 182 */ + { { 0xa55e8ab09a35f4aeL,0xf908fb35ebbadf5dL,0xf885d61b35fee31aL, + 0xb8047f4f82728fdbL,0xa6fe454d33c5bc34L,0xdc5266332ef52e54L }, + { 0xb2f524a931581251L,0xb9eeec91aba760f4L,0xa95d396624a9b423L, + 0xfd52f4d29d3d75acL,0x82719e78834d4c33L,0xeeca71fb3840ca62L } }, + /* 34 << 182 */ + { { 0x984658940f4c60e0L,0x3929d4c645ce7c0cL,0x7846d6c19c4f9b89L, + 0x2c38a9b20fbc695bL,0xeeb4799ad73d4bb2L,0x7c16e5ba4e3b5520L }, + { 0x11ce92e51cf310d2L,0x0910dcc91e037725L,0x159fcef85fc5af9fL, + 0x4944f8ee1dcb3ca5L,0xf5d9f8c0b9a4516fL,0x452f0fa2f1cfa6e0L } }, + /* 35 << 182 */ + { { 0x59b15b61c634aab2L,0xcca0742a620df0b6L,0x791d95720d345276L, + 0xb775b790cd3854baL,0x944e591a256c26fbL,0xc5fda2d0b8fe17d9L }, + { 0x7dba5830c0aff69dL,0x46f7164b0f7c6d60L,0xd767cd58549eeb83L, + 0x4498b4f51ff2da7cL,0xeef2caf8fc594b0eL,0x88dc39ec5f0a95b1L } }, + /* 36 << 182 */ + { { 0x1a57d3e1b3fe597eL,0x1a3ad06d18d1b6f0L,0xf70f27b32e4a4617L, + 0x55e8a0479a75b4adL,0x0b24d5beede15d86L,0x2b3c41d0fb2f56b5L }, + { 0xf6cf36aab1d36456L,0x418a72fe1d8ff434L,0x64149a0d156746bbL, + 0xae65897c4e3a26d6L,0xb75e87d21e68eefdL,0x5b81e0b01cb27c91L } }, + /* 37 << 182 */ + { { 0x2c3fa19b34b90671L,0x369c9e9aa7c9aae3L,0xd89dc03f3d236ad0L, + 0x280c47b9588ace95L,0x0ad071be57f25a96L,0x36ce641d8296279cL }, + { 0x321778128595511dL,0x51878842b52cb227L,0x720df7ab4156b413L, + 0xccc71e10fed25819L,0xc878554e3fde679bL,0x9c50ecbe3b565d48L } }, + /* 38 << 182 */ + { { 0xb2d66f1ffe23ba35L,0x82339e2914b273a4L,0x454a5f0b58c2be97L, + 0x0ebadaa68488ac1fL,0x3c635442517e9af1L,0xa87044c3a5b9fe2bL }, + { 0xb8214dbdb505ae0bL,0x05a9bfad60bf4393L,0xb7b64b42428a49ceL, + 0xcad71866bd2283f1L,0x5bcfe7fce33a3a22L,0x018a2121fd6c73c3L } }, + /* 39 << 182 */ + { { 0xc4471fb02510a1c7L,0x542e73bd2c1c35c1L,0x0bc8bcc4f028a46aL, + 0xdf87cd2bb5610f25L,0x0845e4d1df42b41fL,0xc0523e3593aba84dL }, + { 0xc9161e8ed14887b0L,0xa96f9b3aa68c235dL,0xba1427a46f94d5b5L, + 0x6a5fdbbc858e00f3L,0x8170bad6abfaf661L,0xb4b9dc0ec9f4abedL } }, + /* 40 << 182 */ + { { 0xc48bc829ff7543c0L,0xc0bda14c4d72bfaaL,0x2f470ec703be0af1L, + 0xc70f1e8e92d37eb4L,0x08abdd98418f410fL,0xe38c74ab35386176L }, + { 0x9c07cfdd8c00426cL,0xba74c310a998f1adL,0x76b45140b7d2dda8L, + 0xa52b5e584948330eL,0x9b7332348d8efb26L,0x5d1763735d19a312L } }, + /* 41 << 182 */ + { { 0x46950a441d38ade1L,0x377fdf593058c7a2L,0x5e2fa1681aa129f6L, + 0x2eae63dbc5fe1745L,0x9616fee275545475L,0x4073a79c8627b2cbL }, + { 0xf1ec69ea9a5198e4L,0xe9a906aebd2821d5L,0x193a9387bc22625bL, + 0xca468d717b6c67ccL,0xb4d11cb360f17a73L,0xcd801a0e3df1cabbL } }, + /* 42 << 182 */ + { { 0x1b80b9c386cf5a12L,0xa5bcd3a016349cfdL,0xcee36e8f00d1edb5L, + 0x9566e10a5b7bf29bL,0xd0db98cfd4ff0a0cL,0xb516605e7fe427d0L }, + { 0x099066c18e614e25L,0x63537fbbabe78647L,0x5601a8b420117e1aL, + 0xfd125e2f06df05acL,0xa7fcbd420948daeaL,0x55ad4ee28ff03220L } }, + /* 43 << 182 */ + { { 0x18d71671da2c6332L,0xb38bf94f98ee4e23L,0x9b90bf72ecc579e8L, + 0x5af93aab1bf6b8c5L,0xdad6e7909342613eL,0x5a1d49dc710ad0ccL }, + { 0x2013ed8801468036L,0xb8bd31cf2f0f6f9fL,0xf025eb2aaac961a6L, + 0x1e201f659e1adb43L,0x2755f3aeac7e5132L,0x72d8e1d0f5205d31L } }, + /* 44 << 182 */ + { { 0x80bba9170319fec4L,0x4ba44600aaef6debL,0x83285b613594f325L, + 0x8879183753b5765aL,0x651b4c6adaf1b02dL,0xccc17578825f609aL }, + { 0x0b4076b39fddc6ffL,0x286e2daddf2fa874L,0x46c45233c413b648L, + 0x4fa46969b7cfe0abL,0x835786f3e04f5e5bL,0x526292a90ce3f707L } }, + /* 45 << 182 */ + { { 0x9928e9eb83f17723L,0xc38d5de26c2306aaL,0x3dd3f371558b3989L, + 0xfa4b194877154d39L,0x89f437e4b89f5448L,0xd5531444a6437c9bL }, + { 0x65a6874092537cd4L,0x5f6d72281246fb09L,0x0db0b3be58539e37L, + 0x1f0dd43df50f4143L,0x1aa12daec215aab3L,0xf82820fb7fe7b225L } }, + /* 46 << 182 */ + { { 0x32c6bf5e56cb520dL,0x74dc46c41569fa1aL,0xcbee46391ba52541L, + 0x5e2f511a50ec4575L,0x90165e35032b6f53L,0x2b8f1f8a5544c780L }, + { 0x95baef65c6b50147L,0x4e9db41946b7fde6L,0xe2463226f7afa6feL, + 0x4d70932235409eb4L,0x8faad8937c20aa0aL,0xc8c95a85abc1ab65L } }, + /* 47 << 182 */ + { { 0xd5f54ce676d1f996L,0x55957500e595a0eaL,0x9b62e1fd92c72af4L, + 0xb4803bc3069bf052L,0xb7cdf59c686ebd16L,0x2d1fa780655ac6d2L }, + { 0x6c306d3edca404f5L,0x24e9d7a9a7b5fa9aL,0xe4c080ddc533c701L, + 0x71d16b63425e29e3L,0x81c00db32d993e49L,0xb59f87f577902ecaL } }, + /* 48 << 182 */ + { { 0x43b58def987cf64aL,0xc95b16c63d4bcd4eL,0x5d1b1373bcd9b923L, + 0xaf560542522e052bL,0xc2ff8f7583800352L,0x11723aa17fe2a4eaL }, + { 0x28de7668e94bd9bdL,0x0ce80e0f874018a5L,0x0fe3755d8d43e726L, + 0xa78296acf9b075c5L,0x76d58d9882207423L,0x5c5bc6971db99205L } }, + /* 49 << 182 */ + { { 0x9cbecc969e2aea70L,0x1a3fd38d7e4f2a84L,0xdc35e3c84b95e560L, + 0xd5e912a5aa21d2e2L,0x037866628d8cd601L,0x4b726855f2bb35e6L }, + { 0xa45a827a0d763ea2L,0x17d6e5ea057bceecL,0xdab2381d09a2a2a0L, + 0xf1880617e9aa76dbL,0xb86444dbb184c5ecL,0x23a0e4b767da7c23L } }, + /* 50 << 182 */ + { { 0x2d94a6f030df736bL,0xd1ce20050b3be2bdL,0x201352b55e288cc1L, + 0xdbd3dc57779644a7L,0x9f258b16d191db2bL,0xd83c827fd1c123efL }, + { 0x74c5126e17f04f0aL,0x06008f14966e620fL,0xa4406ba80aaa9e37L, + 0x27323f797faf87eeL,0x43380a672b1206a1L,0xab1ed1cfaf15ebedL } }, + /* 51 << 182 */ + { { 0xa3d2bad9bb22cc74L,0xfe6591a80e2b9221L,0x8c94c974d3cb4eefL, + 0x772694266beb6451L,0x2942737a010986e4L,0x920c9dda59c1ace3L }, + { 0xd31af336da61e1d3L,0x973997a118021018L,0x50a6c8425710575dL, + 0xd61d47c9ade9d8a0L,0x90abe8f8a85f458fL,0x23cc28a3ac4d474bL } }, + /* 52 << 182 */ + { { 0x283d5bb63e052e69L,0x149ac3d01bd300e4L,0xb4c7b96ce0582ccaL, + 0x66102883428cb7d7L,0xd3eea16b500958dfL,0xe1b6a74f74674893L }, + { 0xe3b284be3fb0522bL,0x74b0fe2dea983a60L,0xd4328e5c81e465d8L, + 0xecb534c7403173b3L,0x1721e22774144d34L,0xb7273c6aa88a5141L } }, + /* 53 << 182 */ + { { 0x0ea24ac64018877dL,0x265cbfe42acf249aL,0x811c17e61837d63aL, + 0xff453f5d6b3adf1aL,0x7add0621a3031529L,0x62105dc838af1d27L }, + { 0x2cd31a899b56ec62L,0x5f524be5ede7bbceL,0xc485b2ff66a044f5L, + 0xae28f5dc87a7b274L,0xd41989a93415b6c5L,0x3051ca44c9c43ad1L } }, + /* 54 << 182 */ + { { 0xc22046bcfb50bf2eL,0xee22fb7b78f7c548L,0x5c41c6bc2b5b4563L, + 0x56da674a8bf9259cL,0x3732f77433d8d4c7L,0xa90bf0472741046aL }, + { 0x5ee7f4396288c2e0L,0xa7a1fec99ae621c6L,0x523c0569b76e955cL, + 0xda0c2b378d1e8601L,0x9010bc349559b56dL,0x8d2fab0917b8d9b8L } }, + /* 55 << 182 */ + { { 0xb2caf938281b021cL,0xc61f3abf1404b0abL,0x24203e1cea26d902L, + 0xc84f07e10d34906fL,0x8ba3d589f0cf7520L,0x86b54f6d9a2a90caL }, + { 0x9f87234f3d77a667L,0x328941966e3fa8d0L,0x0921b4a6e994d49aL, + 0xe77e9f8b8b3495cbL,0x9e5b74798da1fe56L,0xcbc09ce7b070591eL } }, + /* 56 << 182 */ + { { 0x583ee7dfe3b7e746L,0x0b6659e4a4fab3a8L,0x34ee02751946db5dL, + 0x5ae3c0ba1a12eecaL,0x36756ed44ccb83e7L,0x973b0861a80eaf3aL }, + { 0x969e38f46982ca90L,0x9a9bcd10018d01fcL,0xb540e9533272476aL, + 0xcf91dd0a75ab7002L,0x2c7d363f39ceb983L,0x4369c221974747c7L } }, + /* 57 << 182 */ + { { 0x32c5b289642be172L,0xe5cc452e697e6a30L,0x344935e10aa6841fL, + 0x9eb2dc4faad907a7L,0xaf77d029e121d0c0L,0x2bcddeb08bb073b8L }, + { 0x3584dee5e40653fdL,0xe853b6337605f214L,0x4723f0add4bab900L, + 0x16dddd27fbf91322L,0x1f96d7e610c525b2L,0xdfba535200c998abL } }, + /* 58 << 182 */ + { { 0x701e8ab819df9ed7L,0x1a6d74c13e2159d1L,0xe82127e0fc61a470L, + 0xaa2e5f33dd15316fL,0x92b6ea927c42c081L,0xfd470a298522aef4L }, + { 0x0c54a067e5ccf152L,0x60c113eda1a079b5L,0xdd501a8389d6e6b9L, + 0x3dbf20d219792456L,0x633cd2b710bf70edL,0xace5327a0aa8e5e8L } }, + /* 59 << 182 */ + { { 0xed79a2de3b2a8a4aL,0x02851125cbf095c4L,0x6817ecd1880fd3bbL, + 0x72acb6ff066adfe0L,0x04fd696d66ce8257L,0xb644f098dc81958fL }, + { 0xcab55d1525218005L,0x1184b0a64de70465L,0x6248e1157aa96b53L, + 0xe30958630516ac32L,0x19f80cc0d07084ceL,0xfdf7ca2efde86c28L } }, + /* 60 << 182 */ + { { 0x9a8857568bc1783eL,0xb373e5a0a7cf2ee3L,0xdeb162fde46cc503L, + 0xd5d334601074ef35L,0x0030f98eea159a90L,0xc5ffbdde64e50d98L }, + { 0x85a6486a48195b26L,0xdbf56597b1b9f2d6L,0x5df2352ab8613aebL, + 0xc425807ebd0189a9L,0xcf5a34d4fa1f4f7bL,0x233e26c7628fd2ceL } }, + /* 61 << 182 */ + { { 0x6c4dd28313a1e482L,0x24bfc23bf803f1ceL,0xb8e795b2f426832fL, + 0x636d2d63b13fcb5fL,0x2dbca0b214a508ecL,0x1948c957c1ff2b70L }, + { 0xc9d7cd4ae3135c7aL,0x1bf41de75d7cfe18L,0xfff9428f2f6cd5fbL, + 0xa25d3e8294d640edL,0xecdea1583e4fec66L,0xff3b2b1555530798L } }, + /* 62 << 182 */ + { { 0x483565313178cbc6L,0x085a31143f3a1ff0L,0xee2a58b11dc7054eL, + 0xa9ce7c113287d5e6L,0xd283d22c8fa263a1L,0x9160bb8be77ff147L }, + { 0x21dabddf918caf34L,0x6921e987ad1a9f13L,0x47e45c7d3ba0ad41L, + 0xeaac63192bd18585L,0xb88881060818034aL,0x2d8e9c1b60be0a45L } }, + /* 63 << 182 */ + { { 0xad3e46af32f4625aL,0x5c2f95dd88371d5fL,0xfc7a9adef2415ac6L, + 0x77a23c424ad85440L,0xce7c63712f4dd730L,0xd65bdc45a5c9f380L }, + { 0x763d3990cf11ee6eL,0x7b2a927a9ffc522aL,0x65ccf351deead5c5L, + 0xef1fa99cce4d076bL,0xdb6f5cca6708ba8fL,0x361525a0f3bac7ffL } }, + /* 64 << 182 */ + { { 0xbfc40c30f893a2caL,0xdf96980e0623bad1L,0x4fd7b54dc027511cL, + 0xf4799284cf3484ceL,0x655ab811069beea5L,0x52588bc87392e280L }, + { 0x522e7b404f0c17cbL,0xc0d88acac705e9b2L,0x9cf1b95877f3913fL, + 0x3e06b9267dd52514L,0x992e920e2908cbcaL,0x13baced26d6ed529L } }, + /* 0 << 189 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 189 */ + { { 0x8a46c911bfc6c637L,0x8dc3d699e4fa4fe6L,0xd4ba64f15cf8e4c9L, + 0x01b3908a01cb3488L,0x69b1fa5d38bd7dedL,0x92ad483818b2eae1L }, + { 0x619324beb33955b6L,0xc7f373355c8a6df7L,0xa397f42e925b3f69L, + 0x32169a495f7e4d11L,0xc0fa9a548d0d9f01L,0xf52a1f2289d8f2e5L } }, + /* 2 << 189 */ + { { 0x9c0d5231ba8e0a52L,0x94d0509e93e465d7L,0x67df90dd98515454L, + 0x223e8b9c8dbfb46aL,0xf39529a36d757ce3L,0xffec9175b4648296L }, + { 0x330749e8f78aae7bL,0x19e5549645f93cc3L,0x8c320b3494083aa8L, + 0x1161f5a321e321c6L,0x0980deedde3e7892L,0x605aa9196ad76cccL } }, + /* 3 << 189 */ + { { 0x71191262062312e3L,0x84c82a94691f46faL,0xad4b344bdda57f44L, + 0x674b758ac4f0cfd2L,0x3bc058a077543efdL,0x3d7c765756618d06L }, + { 0x95107c744dba9e44L,0xe59c3180cfdf1923L,0x5dbeaf35e3f1d63cL, + 0x012029c643ab8726L,0x4f588a4ea256c6fdL,0x14a01b7a3e5d2e30L } }, + /* 4 << 189 */ + { { 0x73fa3508180660f7L,0x4cae013e2d24936fL,0xf64a549f58493d98L, + 0xd9ceae0adc79f602L,0x6569e37bd1512b84L,0x11e4c022151c9151L }, + { 0x075678c2b55c5813L,0xb26cdb5809d3cb16L,0x6334dca3a57fb969L, + 0x0ed90820223dc3ceL,0x74f9c3aebd11e277L,0xaeefed3679c0b8e2L } }, + /* 5 << 189 */ + { { 0x22195e48e57ac6a0L,0xba77c58214bd1913L,0x265f96b4323349b5L, + 0xc183196ea124d497L,0x99f1f78d2466d82eL,0x185a18bfc6263afcL }, + { 0x29a3d5b686cf8908L,0x81f3bc00f680511dL,0x5f6ffc81661d015aL, + 0x31c2ff64cd5eb082L,0xc3c37ad672776042L,0x49438769d9c6ac75L } }, + /* 6 << 189 */ + { { 0x0e2fc74c2a24c385L,0x836a474034679278L,0x25518f16817e2c41L, + 0x8b573a8eb4b7d3c1L,0x012797f94ab56adfL,0x9e0e56d0fa2ab690L }, + { 0x009ba1ee1c9f6f08L,0x8ebf4aac2f412e9eL,0xb143122a1cfb4e02L, + 0x988cf0eccbf2b783L,0x44a7ed9657f5be97L,0xbdcad87251804147L } }, + /* 7 << 189 */ + { { 0x969fcd982f60d1a0L,0xf0f4c9b2ef06b3ebL,0x8c6438cb49ec8f92L, + 0x746107773f1653daL,0xf7cbc899b574576aL,0x758de9008494795cL }, + { 0x73045065ab22cf9fL,0x9893653c9ff13e98L,0x6e8860264a58d64dL, + 0x387d6cc34e3bf554L,0x82a49da4a42b0008L,0xb28bd9b71b0b1c47L } }, + /* 8 << 189 */ + { { 0x378205de2f9fbe67L,0xc4afcb837f728e44L,0xdbcec06c682e00f1L, + 0xf2a145c3114d5423L,0xa01d98747a52463eL,0xfc0935b17d717b0aL }, + { 0x9653bc4fd4d01f95L,0x9aa83ea89560ad34L,0xf77943dcaf8e3f3fL, + 0x70774a10e86fe16eL,0x6b62e6f1bf9ffdcfL,0x8a72f39e588745c9L } }, + /* 9 << 189 */ + { { 0x97e6400574103b65L,0xdad518d6db50ac66L,0xaf96065961077d1bL, + 0x1335de0a5baab1f5L,0xd404db749e444a1cL,0xd3124c5027d5fe2fL }, + { 0x1f20c68a0bd49e9dL,0x44405e6aad6a1654L,0x287d565193c362a9L, + 0x301ec6a2e76661bfL,0x4900f9b54c6f9927L,0xca3dbc3464bf3909L } }, + /* 10 << 189 */ + { { 0xa96955b9b1bafbc4L,0x8dcb55a7646ece39L,0x2b62784feb00e541L, + 0x462f9d7d2693249bL,0x8b264697794c189dL,0xded6ff5563354e69L }, + { 0x7c8ea441eed1089fL,0xe355f75c1462f461L,0x87b691f61210fd5bL, + 0x7291bffb6983cb27L,0x9ed83afc92800095L,0x307a3dc81f24d923L } }, + /* 11 << 189 */ + { { 0x9f79814a45faaa0cL,0xc64a7ac93bb1b07eL,0xaad6ff897f2ad506L, + 0x43da948300b83699L,0x6a702b8d6617956dL,0xfcb1035a7981052bL }, + { 0x094acd48cb230926L,0x3c3249d05da96800L,0x934088079d7208c8L, + 0xe4f04014d738a48dL,0x49bc5f0bf18b06c2L,0xf854285f596b9befL } }, + /* 12 << 189 */ + { { 0x7cec60ead7804b2fL,0x0064464345c11441L,0x3c6de88b769cd685L, + 0x34709186c7f01232L,0xd9eef41eedd2bd0dL,0x3bafcccde427faa9L }, + { 0x33e5350ec07e701aL,0x9cb2eb47a87c1fd1L,0x9fa9a7790d5f5b28L, + 0xa2e7076b07ea2e53L,0x72f4da325c169cf4L,0xb7f192947e751588L } }, + /* 13 << 189 */ + { { 0x1a3b217d2f6d700dL,0xcbbe9349ed335d55L,0x428adbfb53ff169aL, + 0xbd74385214793b47L,0x2224e2569d9460a2L,0x8408600809982ac0L }, + { 0xae6c6f9934447242L,0x63c78b2b9b51fb67L,0x381c948a389593d4L, + 0xf4cdd09f6e79ee72L,0xc658428ba185a0b6L,0xcd7562a786fe4c6fL } }, + /* 14 << 189 */ + { { 0x47eb133532dd7a30L,0x9d058169a9db654dL,0x375c59df6e7a2b1aL, + 0x55d37c677a35f29fL,0xc78a3678493c4cdeL,0xe5f0e2d68d83e31bL }, + { 0xf7927002e9777bf9L,0xdd559324a5afdfc7L,0x077c6c48b81c08ccL, + 0xba1c98ccaa2ef694L,0x06c6c9544c02dd46L,0x211e50f37dd3145eL } }, + /* 15 << 189 */ + { { 0x7f985fa8a96aea53L,0x811f94dc480b38d4L,0x91fdd510f3d40c68L, + 0xc156312ccd763693L,0x24b544c3640057dbL,0xd7d5d4f5ad3b5a1bL }, + { 0x5e235a1e26cda8a4L,0x0cf7b7cd1d2c6f17L,0x17b1ccf0908d3107L, + 0xf32f2a06f555eb5cL,0x274f7c2cb3c278c6L,0xcf1eaf296af1b44dL } }, + /* 16 << 189 */ + { { 0x2a5f8ecf06616d0dL,0xca9b1cb8c7deb373L,0x9de31cedc59c4301L, + 0x1e0f40b10111d998L,0xd29d229f960d5b95L,0x10563249d1dabab8L }, + { 0x7b225cc9a05ecac9L,0xb02e689678f3b8a0L,0x009b52a1f5fb06b2L, + 0x8a575d3f842b9081L,0xfddb48afe9272512L,0xd39b8f1d0b452cb7L } }, + /* 17 << 189 */ + { { 0xb6efc7e167ba9cd3L,0x5a642c288e4f62a6L,0x214a63da364378edL, + 0x582c59944121c53cL,0x840277facc9a728fL,0xc6db3529f8f72d39L }, + { 0x9c5cc2760aca9955L,0x8558a58db8b6dcd6L,0x709226acf0701f24L, + 0x6ce95b21ed248b40L,0x32ea565b5487934aL,0xa75a688496f9ddd1L } }, + /* 18 << 189 */ + { { 0x0d6b9c7c67e09987L,0x261a564d0761ad52L,0xec4621749f60925bL, + 0x83ee0c1218529b03L,0x72972467fbcfff74L,0x37fc074c6abc4bfbL }, + { 0x8b6015bd54e65e89L,0xde8583eb991583cbL,0x379548e1b4d2c62aL, + 0x88024a9a9b24a5e5L,0x633aa869fc03abfcL,0xa27657b98fa35283L } }, + /* 19 << 189 */ + { { 0xb340993c5727e344L,0x2379f51d4f3295d5L,0xa5de3efce2929734L, + 0x7d2e2c82d8717e3eL,0x8f24abb67180db1fL,0xa5060d648a4ed876L }, + { 0x8d39e3a2761110d6L,0x38d30c93a3bb5b66L,0x07774ac3c12fb741L, + 0x7d4ae5a55f4425beL,0xb9848a2afa704922L,0xed9ab68c4cd00812L } }, + /* 20 << 189 */ + { { 0xde9703b461d9e770L,0x02d4091def4653efL,0xefd229aa576eb5e1L, + 0xc0b0b243f77eb987L,0xb11309b2eefe8f71L,0xfeeacf2f68478044L }, + { 0x8dfd8e8643ac3dd7L,0xc0a24181b07f95c3L,0x551ca09624be161cL, + 0x6cb2c1d4b098cdc3L,0xbfc74e9be74f84f8L,0xe58e14d9067e3388L } }, + /* 21 << 189 */ + { { 0xda121aae0ef98506L,0x435f28c6328e636eL,0x64b2170a720d40a3L, + 0x3ddb0e61cd24a844L,0x111442478797c7adL,0x624e7f73d589dd37L }, + { 0x3e7e0ed0a8efdd25L,0x8de031f116509a5aL,0x1330cff5873488c2L, + 0xa80c60b3342ecf75L,0x9d3742c8e62550ceL,0x8ec9b229e46475f9L } }, + /* 22 << 189 */ + { { 0x9eca6f94f025baa6L,0xb2db0741bcf9c741L,0xf8e2aab590bb8f56L, + 0x4772903208762829L,0x067a0c5ae2a266c8L,0x22b104c771b7d7d0L }, + { 0x4a48cd6953e406dbL,0xb85e44d524f0070bL,0x6168262fe10133ffL, + 0xdfc02315e4874e8fL,0x20dba2d7ca317e3bL,0x441c56d2e1d2c0c3L } }, + /* 23 << 189 */ + { { 0x9ebd10d6c444a2fcL,0xda7683e3f18ac11aL,0xdd42ed990fe8e59fL, + 0x9c867debee068909L,0x32df043fccc77aa3L,0x377423ce4aaa45acL }, + { 0x960940524a90c535L,0x48bfe83347d1799cL,0xe8cd1a55ccabd174L, + 0x2ee0a276682145c3L,0x4249297e8d606c00L,0x22021ce2fd7af6d3L } }, + /* 24 << 189 */ + { { 0xae10069e808dc4b1L,0x64df30e18fb3ba73L,0xbbe4caf27ebaad0bL, + 0x5907bf373dd6119cL,0x0a723dff9dfceefeL,0x59bff4ddf7cffc7eL }, + { 0x7bc95fa26a6f43c2L,0x9001d1d53ca0e2b3L,0x316a7ecd27b3335bL, + 0xbf08e6727b8d7d49L,0x4b209f93c619058fL,0x4c0ca01e59d8f9eaL } }, + /* 25 << 189 */ + { { 0x3c1e7f45bad772b1L,0x20f6f1732544af67L,0x14f491f9a7d6544dL, + 0x1451cc8e6acea162L,0x20c8ffa5d234ab89L,0x4b59bce1f5cd1002L }, + { 0x99da4c0ee63027acL,0x6290cb963fc1f75eL,0x3a51774524c4d85cL, + 0x3bf9929c1fd144e7L,0x9bcb97467068294bL,0xcb0b3e5d2e61a022L } }, + /* 26 << 189 */ + { { 0x18c452c4cae69c3bL,0xf45690acef0f00faL,0x3b363aa04f66a5ccL, + 0x9dd41c0a47718c52L,0xfa219d7e7e5cd370L,0x5d384db7b2196dfbL }, + { 0x5e14749b90b4d46bL,0x55796656d9db9481L,0x3bf13d0ac8cf353eL, + 0xb89a28a6a95c485aL,0x568fa3d05da29783L,0x4aa008eed182b1a4L } }, + /* 27 << 189 */ + { { 0x4f38667a179639e1L,0xca492d50ba7c7a16L,0x191e4a3478fe9dcdL, + 0xa3cddb2f03fc70b8L,0x57d90a90a751ec9fL,0xcf88357457a50cd6L }, + { 0x69abd86d7cc58687L,0xc73a00408466bc6cL,0xfbb99c755c495208L, + 0xdd5f1ab9c13347b8L,0x9ae6fb92060b93efL,0xd6bb56a3588e5369L } }, + /* 28 << 189 */ + { { 0xf7e1ed3bb09fa8f3L,0xbb4fe6f71da5be9eL,0xcbab0e01f4d1ba21L, + 0xb732741076a5f326L,0xd94d2349206092afL,0x739f3cd0728e0e4dL }, + { 0x568644aaf81fd823L,0x510cff6b6110e2f6L,0xef4cf1ac566c3598L, + 0x2c26f17162aae69bL,0x1e4360468964a2a5L,0x83c0bbf63e472c50L } }, + /* 29 << 189 */ + { { 0xc198c07064b2955aL,0xc32d41e1d8d43284L,0xfb6f0e2c9f4fc13eL, + 0xf4d5b60b41c61889L,0x5c79f500beb36946L,0x328b22408ca4beabL }, + { 0x64058e916697617eL,0x6bdf7409f43f7390L,0xf2afd208f5bd8512L, + 0xc0000aa0bd1ad6d6L,0x38b8e03bd9f6c1c2L,0x0a34680d665a2d06L } }, + /* 30 << 189 */ + { { 0x79c04804aabd965aL,0x9581aab443d0b660L,0x59bff0035ba71d23L, + 0x212ecd58b6a0cd80L,0x29bdcd33bf1ea5d6L,0x59fd2ff477a002e1L }, + { 0x3c9d21308d9cd247L,0x790e9dbcb1786da3L,0x967ee5e714464d04L, + 0xd6f7ebbd2b5373afL,0x1c0b22d539768d40L,0xdfb54983913f6cc3L } }, + /* 31 << 189 */ + { { 0x5c9808b78a42e002L,0x5cdb2b070f732854L,0xdc92b1676d6d4579L, + 0x789dbb8ebcc22c54L,0xd76b2d40716eb28fL,0x5cbaadea004affd8L }, + { 0x5d4d84dd08fcfe12L,0xd0f1d7ee20d4b893L,0xc98d77dfbbb90db6L, + 0xbce9a5a2b1e29a22L,0x71a6835d0b54e100L,0x0199594a55b1ac68L } }, + /* 32 << 189 */ + { { 0x167ec88a51b3f1ceL,0x19756ee0420024c8L,0x10f2e2443877e634L, + 0x6321bf2603462cb3L,0x1dbd10ee9d3afceeL,0x0726f5f22ca17dcdL }, + { 0x094652660bacf018L,0xc92a9f2de1feb969L,0x0043b0f95e1c5912L, + 0xa09b94d1757d3a63L,0x533956529fdef1e0L,0x9826886cd4fedd41L } }, + /* 33 << 189 */ + { { 0xd22bcbee51964ceeL,0x3ed80af3b0eea46eL,0x263cfa026b854aafL, + 0xfa4ad481b9ca3b51L,0xf8c569a0b4451297L,0xeafb78f8f48059a3L }, + { 0x86a9e3c037093acbL,0xcfb3bb63275ef52eL,0xc4672d3c7c924f03L, + 0xa87350871691be3bL,0xf124f3a52be289b7L,0xf45052dc6b80b6c1L } }, + /* 34 << 189 */ + { { 0x79c99f99a010db6dL,0xe83088a74ee93fc2L,0x76e8376d836b1a7dL, + 0x8cab091c4e24e127L,0x5c98a00f7283cd21L,0x1beaf4a084997647L }, + { 0x2cfb55b8d934088dL,0xca24052cee724d5fL,0x5d6e9db5bba84289L, + 0x133414b26fb26d72L,0x3e844eb9cb12a503L,0x5eac12dab53d6496L } }, + /* 35 << 189 */ + { { 0x79a098812cc6698bL,0x6d44e7577f383e02L,0x1969f93785b5f732L, + 0x3061f62792acecccL,0xa9428d60cc2a4752L,0x69a472af2cf58626L }, + { 0x63fde53cabd347d7L,0x138b5b6a1aed4fd3L,0xd93fce1f2bd48519L, + 0x957fe302e49cc436L,0x9b51657a2e21ad5fL,0x3b5c4cb6acbd3af6L } }, + /* 36 << 189 */ + { { 0xdcfa78b096dda000L,0x5b60dfe5be2303bdL,0x7a6bbd34c7c6ad6fL, + 0xd45c9cb57012b97dL,0x9a049e36812e1662L,0x723bc0b66a5483aeL }, + { 0x7fc03b6ad1c82e81L,0x02ddd6d2b23f6818L,0xe8914b2d30dae39aL, + 0xf4f0ae392f692056L,0x198a31bd45f1390eL,0x917ce4f4f542565eL } }, + /* 37 << 189 */ + { { 0xde39a4e6ca447864L,0x95a028f9f0b131ccL,0xba77ac314a39c4f7L, + 0x0c24d09614857939L,0xdeea56edfbfaa0fbL,0x79aa342f4c920bf1L }, + { 0x50228f48c7e9dc62L,0x0fd9d1dee0f0fba3L,0x3fc03993cd703f6bL, + 0x229a3bf4c5ff39fcL,0xa7456aa484f9cb20L,0xb01bb5a7d12fd7d9L } }, + /* 38 << 189 */ + { { 0xfb390be4539519d7L,0xbaa98a2a6ad44d22L,0xafd19a75ef89de1fL, + 0x1afaef2971e27781L,0x18b297d79887739fL,0x8fcff6048e6da42eL }, + { 0x17bfc1717e861a36L,0x1467800537a8843bL,0x2bc47afdeb16065dL, + 0xcc038e2fbab7b4fdL,0x9d8fc42a3eb9be7cL,0xfc2f0b295928da63L } }, + /* 39 << 189 */ + { { 0xa4e33ca261c14fbdL,0xebafe73fc0a87f99L,0x22fdf1d1f5abf7f4L, + 0xfc1da26549a6b956L,0xfd8c48e5be25dd72L,0x9fd6520ad31a25aaL }, + { 0xe0167d4ffd14dbbaL,0x8838d2ba7370153cL,0xe5f7d69b133fdda1L, + 0x31acbf8de1749b60L,0xc14ec9e2107558dbL,0xb06d0252b99553acL } }, + /* 40 << 189 */ + { { 0x34590975ed424438L,0x7c03ce744d11a200L,0xcc939a286ec406eeL, + 0x8d214276fee5454dL,0x66a0e1a56b257f70L,0x93761a8a006fb85eL }, + { 0xc44f9df2aa70b65aL,0x1dac524f91d9e2e8L,0x5894a8224fca1a81L, + 0x8586e418f3ed85bfL,0xd494dfb202899b5bL,0x7ea9f222ecb8e371L } }, + /* 41 << 189 */ + { { 0xd93ee716b0958516L,0xa91f39db3eb86888L,0xb472c1e2ac92105eL, + 0x4d88a307429ca094L,0xd3fd88027a8e87e1L,0x40c4cd50126a2cf2L }, + { 0x046ce3bf11cf2046L,0x412678ee05691999L,0xea0c78168d3a2921L, + 0xd24ae89924f3c66eL,0x2c4457f00bd144e9L,0x82005b4fd7a52270L } }, + /* 42 << 189 */ + { { 0xf1b3ec32924340e0L,0xe5430ea3b33a05abL,0xbf43b031807629b7L, + 0x53c9407d57014039L,0x6e67b52f2f195ce2L,0xc8cc645f1e48d8c1L }, + { 0xf2234275c08f2122L,0x9cfe3c74c2f233e0L,0x235e6b349c4e0af9L, + 0xb4e8ef5770de39d8L,0xba573a727f73d0a9L,0xe12c506a18587ed2L } }, + /* 43 << 189 */ + { { 0x6b9669c59cf3e4f6L,0xa472d5dbff677559L,0xde845b0c877e5590L, + 0x9f7ef5802d0e2350L,0x87ea99d4e78c1096L,0x213243e9abb68028L }, + { 0x0172c81595e71abaL,0xc2592a762ca34c65L,0x50749aee9dc286dcL, + 0xe37d10884055de3eL,0x3e5a93bb90d652baL,0x0cbb7a08c32aa3e6L } }, + /* 44 << 189 */ + { { 0xe0bf3d8a026c43cfL,0x091956cfeb702508L,0xfcd486c9a6b3203aL, + 0x94a6d52f365460ceL,0xefeb5400563bec77L,0xbe6baa9619b2659cL }, + { 0x116f71c34bf21a00L,0x83d1c99a86d21871L,0xff1ba96aca0bd547L, + 0x5eb0acf741b94afbL,0x1be5d66fb1aaad14L,0xb8ececc5e6cd6d4fL } }, + /* 45 << 189 */ + { { 0x65f6e29dec7d4de8L,0x082fa0560e938c79L,0x4cda3fc925a02f04L, + 0x77dbcf0d3bac5cadL,0x625f9bd859145bdbL,0x98b7fd64553a11f3L }, + { 0x621bfbe387dd8a45L,0x6519421d1c35176bL,0x89eabac6d5ead4c7L, + 0x45c68bfe54acfbd5L,0x87cd244a84f30b68L,0x83b5f6b27b39275cL } }, + /* 46 << 189 */ + { { 0xd43b1d3c0ed0ade8L,0xd60b1ae7640e7d37L,0x965489e6f88e06e5L, + 0x35398ac89653417dL,0xed1e89ac02cfcfc5L,0xd127f68dbb6f2bfeL }, + { 0xa569c59fe22bb079L,0x7933f14e4ca8e9deL,0x68b4964a30033c3eL, + 0xab438cf88f069045L,0xa64f3a1516163059L,0xf40499c14576fe42L } }, + /* 47 << 189 */ + { { 0x361c28da052567f7L,0x8a2c6aafe0db84b6L,0xa79eb10cabbc87d3L, + 0xeaf7bfff4141b3acL,0x90bba4a953aacaf8L,0xda577661c35f9564L }, + { 0xb2550d0dd4487a5fL,0x69d43c5199638269L,0x6d16973f7a1f8ac6L, + 0x3dfb2253c71e4a4aL,0xafd836aefa36168cL,0xba72fd1faae6dacdL } }, + /* 48 << 189 */ + { { 0x690c0cfeb449d1e2L,0x4a5e150b1b8e1577L,0x22508042204d98a6L, + 0xc87a97f5bad2eb08L,0xd307c59ed25823eeL,0x6ed083580df8b3f6L }, + { 0x280ae344314e7016L,0x6a55be876ef4e889L,0xea930e5a24d04e38L, + 0x0269d9a7309830fcL,0x41dc8f0ae4afeebcL,0xfd1bc660f14ee02dL } }, + /* 49 << 189 */ + { { 0xf81cc943631da366L,0x2e821eb85ab1a2caL,0x339e9e4765433883L, + 0x3dc14370e1f60c71L,0xbd6c79bebc25b506L,0x2bd3ad51a8a639f0L }, + { 0x7c168f13c700a293L,0x64fef4fc28b4ce88L,0x3ccdc3080c329c6aL, + 0xbfd78932b76a9452L,0xf0c123fbc684f4b5L,0x8bfad06432305ed6L } }, + /* 50 << 189 */ + { { 0x208a668feea1a9ddL,0x8af75caeab903f09L,0x356208b449265292L, + 0x57b24ebe53faced4L,0x9c8aaa7303694920L,0x1c06ef5ad2f90179L }, + { 0x794ead99df92de87L,0xad900c4e7a73fe9aL,0xdb66b9ae715d9f66L, + 0xd19dc46db1bc2950L,0xb0a5af5c24c82c0aL,0x7d83f950371d0ec7L } }, + /* 51 << 189 */ + { { 0x716071e3abd37656L,0xaa22858be6cab564L,0x6793a66f5aec00ccL, + 0xe2ea5401e025da6dL,0x3998ea5d2eb0059cL,0x4ff6f442e39abb77L }, + { 0x703eabdabdb6e0f9L,0xa33e6deb38522433L,0xe23c13f6ca83c2acL, + 0xcfb8e57c0cac836fL,0xd0f84bde7692714cL,0xb4fc3b01f3f41d29L } }, + /* 52 << 189 */ + { { 0x67842ab4d8f358a5L,0x70cab57540e2fb69L,0xdebc3046e5c458e4L, + 0xc3574cf47eb004d5L,0xbac261a1c86f20f9L,0xc1bcb661deccf7fcL }, + { 0x5b3b96dec5574e9dL,0x07b878b3e151fb0fL,0x2f2d126cd38bd5f2L, + 0x06c951e8319597c9L,0x5529be4424ed0027L,0x82dcacc2ba8d7acbL } }, + /* 53 << 189 */ + { { 0xc37eef0149311e82L,0x3d07aaad401d010cL,0x934e039e53417831L, + 0x70775653da895ec3L,0x206b80af625cbe49L,0x9e2a4ee1e53ccb36L }, + { 0xebeace45c8ca6ff7L,0xadb19bd9925302deL,0x951bfcc497dee154L, + 0xd09882da79b60e1fL,0xb1e9cf0cda5f2516L,0xc2b697295e4def97L } }, + /* 54 << 189 */ + { { 0x74ce542d04f860e6L,0xdc8adf8fa3c48075L,0xe19852232063f76fL, + 0xf651c9fd5cd9ff61L,0xd4cbea69bab39ea0L,0xb6d4749b28fe3443L }, + { 0xaa7747ec65e960ebL,0x1a1b7b65e132a213L,0xfa52901f402a50d4L, + 0x3e4d2da68d43700fL,0xbfc7322937d45181L,0x68a812f9008bb845L } }, + /* 55 << 189 */ + { { 0x226d4d233e4cbf5dL,0x36359f52576243e8L,0x032af38a39a1999eL, + 0x9b59120a687eb228L,0x85c56b78e68e1498L,0xa7a14bd4849d03d1L }, + { 0x9e7177b345c4c3f1L,0xad7e4975183bd846L,0x42418d9a42f69dc2L, + 0x218e8f8e4f52cac6L,0xafafa7649f1f3214L,0x32f6f72b747f7592L } }, + /* 56 << 189 */ + { { 0xefca7f7ba6c53c1bL,0xcb4bb33c524457a0L,0xc9eab87fe57d08dfL, + 0x48c01c2a7d9a1967L,0x11c97ed97dc27492L,0xd8c644861cf1f639L }, + { 0x541f8c0d8156576cL,0xdf5c8dff2384e299L,0x9806935ba6be190dL, + 0xec6c5de764494b4eL,0xf04e2d4cb83c00b6L,0x379af438c0b84f15L } }, + /* 57 << 189 */ + { { 0x64e6289d92bbc1f8L,0xe88b78c5a0620121L,0xd01bac79a0fbc373L, + 0xa2e7986af098f07cL,0xfcac4dbcc5911218L,0x2e2bf56db337ed26L }, + { 0x878d9819e89a73c6L,0xa7df4f5768df46d2L,0x74bf7e2f4b3c9568L, + 0x2f2b187aebcce535L,0x544f18139a4c2be3L,0x3a5fe300a5938f0eL } }, + /* 58 << 189 */ + { { 0x901a14cd70aa91aaL,0xf0b6e1ec7f0b0a70L,0x6fd1ee0156a8bf9cL, + 0xe7e53c6693fbdadbL,0x18ebae68e17de706L,0xf4107457ebecf636L }, + { 0x77a85ea4a9f6c696L,0x3ea193e17dd9e3adL,0x9497e0a9f151c8abL, + 0xcc9237497a1dbf14L,0x2e36740e8f9be59fL,0x1b1c7d7c4a249e51L } }, + /* 59 << 189 */ + { { 0x7a45af2242cdcc53L,0x3061d91b8682832dL,0x85e080f6c375030fL, + 0x3ea6dcd1418440c7L,0xe0559870d14b6537L,0x36619215d178b45eL }, + { 0x48a4b452dcb85a34L,0x79cf4529bd5504bdL,0x506215e9e9c34c8eL, + 0x961f74b6dbd00e2fL,0x473d1397cbc84ddbL,0x6c64f870a8d67cb5L } }, + /* 60 << 189 */ + { { 0x519a6edb91a9b99eL,0xc0ea29e0f19221eeL,0xde83e0f77dc193b2L, + 0xa7b33b6044be16f6L,0x7edcb49406c8e8d7L,0x9f9dbb86392c0ef6L }, + { 0x09aefe035726bd5eL,0x782d8350c4e80b7cL,0x14e41a49186b80e9L, + 0x9af13703499ef97fL,0x5752877f2cbcc336L,0xdd0f8583d2df624dL } }, + /* 61 << 189 */ + { { 0x1cd2be3f32f6b0a4L,0xfd5da4a90114bca5L,0xc322a6a198a39a66L, + 0xca411eeb10d64384L,0x7c5d3ed0c72d8b6eL,0xf20c76697481309fL }, + { 0xaa4e45dca155872dL,0x66e41d54b87c1e51L,0xbe2fe5e6a6bfe6b6L, + 0xf60ca33a08a4d3e7L,0x45c1ec8c7211b48cL,0xdf44d3b573b78f7bL } }, + /* 62 << 189 */ + { { 0x21eda67429a1e6acL,0x33118990422ce5aaL,0x236aa9ec27326810L, + 0xc42dff9e3be7b318L,0xbe4601281690755fL,0xa395509d8c1c60c6L }, + { 0xa36de79d05b991d2L,0x55f516a3632882d4L,0x4c8c5a4296d1d493L, + 0x56199648533cda6dL,0xf9c6897a603bbfeeL,0xae835160f9857cc4L } }, + /* 63 << 189 */ + { { 0x700bad58d6aa9618L,0x2ad7069c05d54c73L,0x7f3ff5992f6a8495L, + 0x39de751ee26e6720L,0x39126d97d4cecf54L,0x353e00e21523aca4L }, + { 0xee905af017a33178L,0xa30173d31daf2642L,0x24cbbcc728f9169dL, + 0x4e65bb13a7039e69L,0x004a11859121e44eL,0xd4efa5b91c1e60beL } }, + /* 64 << 189 */ + { { 0x2e75a26eec65b53eL,0xfeb630b270552fb3L,0x53dfd057ee7d8e4aL, + 0xb959110d8994f449L,0xb4a16596bb538367L,0xa70917bdef82f29cL }, + { 0x5a76430043bba6aeL,0xee207476cfbc194aL,0xc7eab23803a4184bL, + 0x60c67ef20f7fcd62L,0x41e05799dfa8a0c6L,0x5d7d05e604d352b0L } }, + /* 0 << 196 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 196 */ + { { 0xc97c01eb436b59f5L,0x1d15aca7ef1848abL,0xdba1ce807fa7d3c2L, + 0x69e6f96e81060874L,0x6e3e0df74d7eeeadL,0x8a3b5e85b0c87f3dL }, + { 0xc55ae3dbc8a23914L,0x5cdc2a92bf6d27d9L,0xa6008c591de7860aL, + 0x8202f8b66e546731L,0x652f2d07aa1e45d4L,0x146f214f6df5415aL } }, + /* 2 << 196 */ + { { 0x041c706cce5fb4d9L,0xddc78cb3b22a79a7L,0x7dc4cd27839e9d5aL, + 0xdfc9db83bf3c4c06L,0x85b8094138b7bd22L,0x1007dea2d0f4c2daL }, + { 0xd7b34006c633fba0L,0xa8880acf4476e55fL,0xa340b2c275236685L, + 0x5ddd05510113a85fL,0x7dfc7ab29cb32704L,0x9a334a33dabf22ffL } }, + /* 3 << 196 */ + { { 0x2fbce9bed7d1146bL,0xcec9e5d8b3980bd2L,0x48ea45939f4cbaf0L, + 0x56c540092574a3bdL,0x84a39630e792c39aL,0xe5c690f8eef81343L }, + { 0xf996760f17655bc9L,0x6009c2156c0c191cL,0xa0ca12e6966d7027L, + 0x92a6d5d52e6f7c63L,0x46809d269bd13eadL,0x3c11fa7967aac681L } }, + /* 4 << 196 */ + { { 0x3fc9b3cfabe2cc87L,0xfd8d64e3514e77feL,0x2003a58afe1ad535L, + 0xcec4be38cb39149fL,0x4d578c99bdedf470L,0xcd35d7a33a356519L }, + { 0x7a762f278b078d6bL,0x3b6891ed31ae2701L,0xdc0e817f270c508eL, + 0x5a7be2049fdb29c8L,0xfa1a0be3cb2711d3L,0x5865f55f3786a0c2L } }, + /* 5 << 196 */ + { { 0x1d0af6b52f641cffL,0xa932adeb3648c4a0L,0x67641951b1ea8fc4L, + 0xc0b90064b1fae482L,0x7012642f6623477bL,0x1cddc0245bf019ceL }, + { 0xca1f4675c2c32737L,0x11525a5e97d6b18cL,0x9c034ef2d3868de9L, + 0x0533d921044e0c18L,0xba6cf14ecb5e38c3L,0x438309f3509d7053L } }, + /* 6 << 196 */ + { { 0xe164268ec4ff9f0bL,0x6c8e9349e6c36e63L,0x734f979478ab17f3L, + 0x46d468de0179ed0eL,0x7e68f006dfa26867L,0xe4d4a85de3d0485dL }, + { 0x0913a1d7f84c0f8fL,0x4095c8c025a9c9cdL,0xeeb1a79e49eadd08L, + 0x433f5e417dd8f954L,0x70a6281430bb26d0L,0xad94d8f6ff5e8e29L } }, + /* 7 << 196 */ + { { 0x6a352b579e32c0a4L,0x5274a08277ec7a40L,0xee1f7c7a240e6dc5L, + 0x85d5be62d313b4a9L,0x1522c5d25c01a405L,0xcfa08aab960afd5aL }, + { 0xa3cb77f38e8a93dcL,0xaacb16766d1c98c7L,0x84090c7d3b93fa9dL, + 0xc77f1ee13c0383adL,0x461c93b776f7a220L,0x66d63a1d04ac0bfcL } }, + /* 8 << 196 */ + { { 0x3c7d6b644751207fL,0x65e1f96ae440c1a2L,0x8ed15d20aa0eaa1eL, + 0xe944ad2fc0eab490L,0x71525aa1f6d9f260L,0x5cd14c8816146ba3L }, + { 0xf940190814a41275L,0x3bb7ea742288618dL,0x6a4e1c37cab1060aL, + 0x357fe4d0c8cac96fL,0x97a8b8ab6a2466ecL,0xb6e83fdb9c01be70L } }, + /* 9 << 196 */ + { { 0xa55a7142cb09a69cL,0x0a39fa12896a9c24L,0xa7131a001f6c9c82L, + 0xdacbfae97509c912L,0x3793d4ef4232eb57L,0xb63d9fc0da02ac15L }, + { 0xf1ce48a09ab37492L,0xa388dbb5cf9ddedbL,0x7224ef47fd7b2aa4L, + 0xdfe18be82fd35ae0L,0x2286ae7b90a2e98dL,0xd06cfd71e0d3c2daL } }, + /* 10 << 196 */ + { { 0x7825df5c948663a4L,0xc8c093adeb4ec9ddL,0x677c51ebc1505989L, + 0x8c28421524041f43L,0x0f63f15ac9ef610bL,0xcb98841d257678c5L }, + { 0xc0560066c52c64acL,0xaf7417db954180e4L,0x935c08876fe1f0e7L, + 0x8fe556ba46d03a88L,0xec44271484a0c4a7L,0x431f8e8395be9544L } }, + /* 11 << 196 */ + { { 0xc1fc18cb3101ce6cL,0xff753902048e52fcL,0x768299554e58e21eL, + 0xac990acc32856d44L,0xaac4d5dc9f8a9da8L,0xca1740fdd4be9e8aL }, + { 0x59250846892d8bdaL,0x45f45cad19c97c71L,0xf29e2724e6ba5c87L, + 0xe441134473f6a778L,0x9f4f9027a0f278faL,0x11bb7ce02bdcef71L } }, + /* 12 << 196 */ + { { 0x0cc553bb9b3fd7ceL,0x2e0ff43ce103b562L,0x96c01f0328222a3fL, + 0x7dcc5593c10171c0L,0xc677366a4b3e5858L,0x872d4396bde4eebdL }, + { 0x5d0c5f3a7f83c0b6L,0xbf4274dcf7ba33d9L,0x1df6e4811a635f83L, + 0x24e2e8347d807292L,0x792203a8eee1e676L,0x20475f907ef4e8a4L } }, + /* 13 << 196 */ + { { 0x1b4db0579e37cd0dL,0x61b95bc9ebccdf79L,0x7d98d8537a57d7adL, + 0x58a3d639709b0194L,0x45fbd4417ce5bc31L,0x7684b71b5b3c856aL }, + { 0xb311f8f85bb6bd1aL,0xaeb8e44711eda59bL,0x1ad5b35fbf269cffL, + 0xc69651b4a0e2a640L,0x3713803bd83ad8b2L,0x613ca3af0e4b353cL } }, + /* 14 << 196 */ + { { 0x3ac59b1fff8cf495L,0x3f3726866b04c4dcL,0x2cdddf90da325f0cL, + 0x3ae79666444cabe5L,0x8222f6d6c7484b1fL,0x61fb08929ae328b9L }, + { 0x279aae392c575c0eL,0xac694019948508bfL,0x4931cc55b84056f1L, + 0x75927a688b50ad1dL,0x47ba72e945584371L,0xbea7e62ea79fe5e5L } }, + /* 15 << 196 */ + { { 0x990a6767faddc25dL,0xcd7650eb114eaf17L,0xf9d1d6409a44cda3L, + 0x70996b6871fb091aL,0x630ae9754ff80816L,0x59a9dc2f987b20e7L }, + { 0x9a39588ef65fbbc7L,0x71f4c8e598e7c78cL,0xad2f5a0138cd40acL, + 0x3c68fe575a837332L,0x7af44087155e6b4aL,0xd66f4cf8e99e31f2L } }, + /* 16 << 196 */ + { { 0x5b0b5d692a7aecedL,0x4c03450c01dc545fL,0x72ad0a4a404a3458L, + 0x1de8e2559f467b60L,0xa4b3570590634809L,0x76f30205706f0178L }, + { 0x588d21ab4454f0e5L,0xd22df54964134928L,0xf4e7e73d241bcd90L, + 0xb8d8a1d22facc7ccL,0x483c35a71d25d2a0L,0x7f8d25451ef9f608L } }, + /* 17 << 196 */ + { { 0x81e304c903b37e31L,0x21781e57925a6491L,0x4ecbad144b9250d9L, + 0xb395914345cae8feL,0xb894a39dbf775d4fL,0x8a2c1090d307e272L }, + { 0x49dfcee9408bf3cdL,0x08f0f33195b573dfL,0x23eb8a0b214bcd3bL, + 0x425e1cde7ccc4d82L,0x53f64095ac113d2bL,0x377a6cb3d88e0761L } }, + /* 18 << 196 */ + { { 0x9cd08431d360ae16L,0xbf5a73d211281e82L,0xfe25aadfcc34ff33L, + 0x8874984b84e3af16L,0x8dd38b596a65a2a7L,0x6c91112c68a26926L }, + { 0xb765168637554f46L,0x79558f04c78bf29bL,0x8bb14b1f03012b9dL, + 0xed7d03f9a0886ba3L,0x9a436ec3c2a93baaL,0x601babb740db0c78L } }, + /* 19 << 196 */ + { { 0xa7395eef391821d0L,0xb299378fc8b7b1e2L,0x53a37e3b7f3a58d4L, + 0x7d06fa4e3188c5adL,0xe65a94c063dd7462L,0x4daf74f39cfde2b0L }, + { 0x98f986b4fbe7198dL,0x8e96b1ee88176bffL,0x5f309f64eb91641eL, + 0x46bfe3352ffdca19L,0x1ea1bbe7ac8fbc08L,0xde8ca618b00f88eeL } }, + /* 20 << 196 */ + { { 0x0757ee852005631fL,0x60f484ea9d70cc3bL,0xaf131d246b011041L, + 0xe40711a1062e2e17L,0x05ccf1b94c27e2c2L,0x29e9910e43d43758L }, + { 0x54daa550ed000e45L,0xf00a312295d3674cL,0xdb006fe743ec424eL, + 0xbddf5473536162d2L,0x7b8a24b579d433bdL,0x3127a46f282297d3L } }, + /* 21 << 196 */ + { { 0xcd964573cd0585a7L,0x9c2fd35605b684aeL,0x7f600f4de4a47ec5L, + 0xcb4bcdf085fdd4feL,0x5b292292b4dcf5d1L,0x923c4331df33a2b8L }, + { 0x0fe13edfd6c1e73aL,0x0b35adc6c370821bL,0xa70061b08d405282L, + 0x98efb3fc6457af81L,0x8806ee7136e1041dL,0x8b56657faaaf0731L } }, + /* 22 << 196 */ + { { 0xe68b669189cb38d1L,0x250f59233456ed5dL,0x8928f1fe16188290L, + 0x8b24b1f734a837d4L,0x268c8c57d945d0b1L,0xa4190ceae002b3abL }, + { 0x4596e76e56dd74b1L,0x647c17871c307789L,0x0b945c7243b13a6cL, + 0x4904669552a58ee2L,0x7547a6b46e25b7e4L,0x8bc26f49e2b1b140L } }, + /* 23 << 196 */ + { { 0x95b3f4e75196d614L,0xc075bcfd5ea18aadL,0x15dc9dd41ae71f42L, + 0x75a769f289543f86L,0x06032d9ec392b4c4L,0xd6cc5c717d4df83bL }, + { 0x111fc63427ad6680L,0x770dfe7f781bda48L,0xabacb082fc0afb5cL, + 0xe3a463e771dca197L,0x390f21a89635b275L,0x3d3474b24ae094a6L } }, + /* 24 << 196 */ + { { 0x48f5588853666241L,0xb9fee3d39e6a068dL,0x8c50e3af0275e82dL, + 0xd490cf2dcab34005L,0x20b11f86bf0584c8L,0xd49714c18179e559L }, + { 0x89647b178ded6686L,0x6c4bac8cf16c93d4L,0x5401e4f8076ff71bL, + 0x577e73acb1ef9b0cL,0xa1b87e0ea46e7880L,0xab8d8bbb54fd28a7L } }, + /* 25 << 196 */ + { { 0x220161f0741396fcL,0xae14ce5817da16ecL,0x766e415bb828b19aL, + 0x1b3b239e610c7aabL,0xf1c7df4992d53419L,0x57e4cee59442c6cbL }, + { 0x546f73b5f85d33d3L,0x195116c74e041703L,0x5a71a96a5d668df5L, + 0x0adb7b16fe56c658L,0xf6be923deb563532L,0xa65ed113f2d45f4dL } }, + /* 26 << 196 */ + { { 0x8c6742e5bccd3be6L,0x5f0f7fdd378de702L,0x41236fec334aabb8L, + 0x4b15815b7e9d8aa9L,0xbb816e46e1c235bbL,0x8591cc45176c2fe0L }, + { 0xef00e3981d7104b1L,0x761d2c244012398bL,0xe4984f4ae81af247L, + 0xf923bb80c144dc64L,0xd51f27dd83988de3L,0x0ad5438d995dbbddL } }, + /* 27 << 196 */ + { { 0x0532790bd148314dL,0xb4862d9d5b6b4ad1L,0xab65bfc45beb3ac6L, + 0x72eac92d99331822L,0x2e09a69a6127632cL,0xaa1eaf0791ef9141L }, + { 0x79b923fe754ff12aL,0x19395a97f9a467ffL,0x7dcc91d49ef5cc4eL, + 0xb9019ff198a84090L,0x62616ed6d5bfd083L,0x95cbf9442b328615L } }, + /* 28 << 196 */ + { { 0x22ef6f606374afbeL,0x70e19fad26348f5cL,0x8bcd51a845f98ac6L, + 0xeeef7f7026b7ba04L,0x33aa0644544edcb9L,0x22d89a1244974c71L }, + { 0xecd08f5d0f8d90a5L,0x495a0403cf03513bL,0xe924feea27953ba9L, + 0xdfbe1f93eb5e7975L,0xd3c105a1285865dfL,0x87b8b6360886fc87L } }, + /* 29 << 196 */ + { { 0xc2da6d7a219d44f8L,0xe66364c555a9d970L,0xfb0936258611738aL, + 0x916fbfa844f7f35dL,0x7a4e0451774b1e2bL,0x7adaab9e80375e65L }, + { 0x2272b95c8ffdfda9L,0x41644b619ad42b25L,0x157026817f0c98fdL, + 0x25d4a00fffba1d85L,0x52e684c6c6c5545aL,0xba85bf2adabb7df5L } }, + /* 30 << 196 */ + { { 0x89a5b69dd282b12fL,0x63864e7ba7d28277L,0x36ac74d08c21f920L, + 0x7cfd291713a2f8d3L,0x50b63122c2ef5022L,0x23d454328ed33339L }, + { 0xf8696b2dc4880048L,0xb9605bd5792dcb6cL,0x4cdb5fc26fdeeb9bL, + 0x58ee2837f1a7f35eL,0x8956359ae2985ccfL,0x0cc6c4ab2c94cb32L } }, + /* 31 << 196 */ + { { 0x2fcac7d161a8254aL,0xc396583a05389aceL,0xc6f069cc3872ee52L, + 0x76f0e5b407180f5fL,0xc8b23b7a2dee0d6fL,0xc77b242613bf8fb2L }, + { 0xa8c625e66d5ae411L,0xc0c40a75b0723adfL,0xdee0ba8f380d9c67L, + 0x38b86a3b19920f24L,0xff2191b7d910e9cdL,0x8d01786734181894L } }, + /* 32 << 196 */ + { { 0xa704016022ec7eddL,0x19124972cc9c8ee8L,0x697f301f2ccb9417L, + 0x3ee877646f00d8aaL,0x2b5afaf88138a017L,0xf152b14c832d7543L }, + { 0x27c27ce2383052f9L,0x4746c5b5e1dae11bL,0x92dc5ac75b752008L, + 0xcf382e01e84fe5f1L,0x90e034197d5929ceL,0xafee3abb15ca3ffaL } }, + /* 33 << 196 */ + { { 0x299e0c5507f0e3a7L,0x75dac5c46cdebb44L,0x340b5479183c7e42L, + 0xfb1b03dd702672d4L,0x68f7222ec07cf89dL,0x67a471e422e7a8a4L }, + { 0x79dd4627b9ada93aL,0x774c53771c8ecca5L,0x95191e1a59db2e65L, + 0x3f6947f270abeeceL,0xb4934fe0885e4e00L,0xd082e49901728c2aL } }, + /* 34 << 196 */ + { { 0x86cd8083aaa82329L,0x74f0c5786e579dfcL,0xc2b68c4e3b436545L, + 0x8e66c648469d4a81L,0x4c5b05c5bef62bb0L,0xe558ff020bb6f865L }, + { 0x9f8ccb16f356a124L,0x1bb28d7c1279f8f4L,0x9b885f0ca8fc4e08L, + 0x2ec4cf69859d90eeL,0x9bef3c4d86d3b9d1L,0x5a98ce73eaad8d53L } }, + /* 35 << 196 */ + { { 0x6c716b179711b5d2L,0x396a4a4cb386c1d0L,0x5845f6861c157c12L, + 0xdcad516262c15d4eL,0xb6e0a6a02dadb218L,0xe4f6d5e5a342e785L }, + { 0x1eeea548c78980e9L,0x363c31be00a32adaL,0x01481fb7e660b445L, + 0xcbb61552999c1f5cL,0x20a73942f361d12aL,0x67fb89a11b8b4b3eL } }, + /* 36 << 196 */ + { { 0x1d57d639eb00e26fL,0xbeb198906985c10bL,0x38cd95a337b9b76aL, + 0x3b1d12e30304c87dL,0xdf42dc6f4734e191L,0x1ed1d9e397841989L }, + { 0xfb60e333859b577bL,0xfb026d16ed3db987L,0xa216b0e46f7855c8L, + 0x9501bae3539ebdf6L,0xd95a4a32dc8a1f6fL,0x76cb0b6b45307deaL } }, + /* 37 << 196 */ + { { 0x5607ab62a844b579L,0x8d3ed3db94f67d9fL,0x95390de8a9929b04L, + 0x4a6f6f7cc85397f3L,0xec5b73eff26eab04L,0x2543190b045699f9L }, + { 0x9a4896138cdbb723L,0x0e081e5b7a1c638bL,0x20f292c6596a7b1dL, + 0xa14d849794477dd3L,0xeeeca98064b0de1dL,0x75fdbae92c5135dcL } }, + /* 38 << 196 */ + { { 0x1202b5752b076f5bL,0x5ca1247edbd6c420L,0xb45ff9bfd8ccc5c6L, + 0x680fcfb28e061baaL,0x5a6e6342122a4212L,0x0ad12abc312fea8aL }, + { 0xd1dd8ae5665dc7b1L,0x30494dfdd9a22454L,0xc8aa9bc9da55ed09L, + 0x6ec643031b74b119L,0xf54574716b604639L,0xe2a214e59f8d83ceL } }, + /* 39 << 196 */ + { { 0xca698de5f5c96e8aL,0x352c89a3fd941919L,0x0e3de0a909812f23L, + 0xa74ba91667702fefL,0x6acfaa5a3863d479L,0x28d8932bb6bb15cbL }, + { 0xc62155704ba9718dL,0xc67a3eafa1edd692L,0xc86eeedaab31aa74L, + 0x2064ea632deb79c3L,0x813b84f51ff01adbL,0x994b9437458a1835L } }, + /* 40 << 196 */ + { { 0x1013c4f4fde3f7ccL,0xbad5415a838699b6L,0x2a8b4eac64cacc78L, + 0x3d10f949bf75d233L,0x5a9f7782fc84e55eL,0x209a18345ea7b274L }, + { 0xa66cb6d4f9e8d374L,0xf898d9479a20080eL,0xe7e4b91b1272df4cL, + 0x5b8507cc5dd136bbL,0xbe4b5262372a8e05L,0xa0cb170c2aa4a47bL } }, + /* 41 << 196 */ + { { 0x469180a38378217fL,0xd960bdde85ef6d61L,0xcc4e737d6654aa84L, + 0x28d440016ae51d69L,0xf13a0d9ac6187196L,0xe60851b392160f65L }, + { 0x41d98cf61cac48d1L,0xf37f003d1b57f2cbL,0x4829c60bce272603L, + 0x45991d4adcbdddc1L,0x17e591fe74601bf3L,0xf8a36b4fb3fe856cL } }, + /* 42 << 196 */ + { { 0x4410b773fe480323L,0x42ae32e3ea2f8b57L,0x6578a64b2886b9d9L, + 0xafcfa5fe4241ec91L,0xa7fa5afc16b4ef24L,0x4a6594bbbc16b610L }, + { 0xcb5845515e264fb6L,0x4b89955e2b9c3c70L,0x530426be21e11c1eL, + 0xb707abe9c9dab34dL,0xb5aab0bf5931cd78L,0xab6a2585f0ccfcdaL } }, + /* 43 << 196 */ + { { 0xe75761f716afd216L,0x8ff1cea3b8a4f008L,0x04b8b65e69889d77L, + 0x679bf7a586ad9fb5L,0xbe49be0b4c22b86bL,0xcc8905a16c026c1dL }, + { 0x17464e7e59ec1983L,0x50cb62832a03afe0L,0x8dadaf456ce4df91L, + 0x26cf59d1e0df6fddL,0x6ecc66119adaec45L,0x1be42e744ef67dacL } }, + /* 44 << 196 */ + { { 0xa01cb3bacb1957b9L,0x053693ccf50694c9L,0xf8a887ad527f3aedL, + 0x2f1a80ece9bf06f0L,0x74baeaa57d0eec9fL,0xce8e8b9ab0641cabL }, + { 0x91d1e84d128a1804L,0xbdcfcaec2d5fa43cL,0xfc5cff124106fa6dL, + 0x2ae3ffab01588ac1L,0xe9dcc9b44c067052L,0xd8e3d74bafa7d4c3L } }, + /* 45 << 196 */ + { { 0x64a134296d7b277bL,0x487080d8e9a50637L,0x02e5fe901c6c061bL, + 0x8fdaafc8ecabeb11L,0xb1e3960110720b13L,0xe7304bf77081f41eL }, + { 0x78a10af8c26f5cf8L,0xf52cbc155c032c15L,0x95a3c4558c0c2091L, + 0x1797b407abba6f79L,0x87c0cd05a96a3062L,0xdf75e2805f04a7e2L } }, + /* 46 << 196 */ + { { 0x47161e1f82779cd6L,0xa95afa08c8158458L,0x2cbefdbc40a80742L, + 0xd86e0bfaca420c9fL,0x08f5f8c29c79427eL,0xe8f88361da4d0d9eL }, + { 0x2195174d3eb78d14L,0x889b32c9ed6caecfL,0x1e679749c3c83ed3L, + 0xc27a8c84eddf8a29L,0x4a21af3af8e09f40L,0xf4b9797f1eb3b9b3L } }, + /* 47 << 196 */ + { { 0x58c2405baa44f11dL,0x86ffaa37ac0f7257L,0x373623cc4070f6e3L, + 0x142e62f9a36c73b3L,0x43bab2dd36a143fbL,0x4fbeb0b7aa50375cL }, + { 0xf9cc2e7b1f862294L,0x95a9be3c0abdcaa8L,0x70f050225cda074eL, + 0x152659db43e6bc89L,0x1790148727c6e01aL,0x544069354e083c21L } }, + /* 48 << 196 */ + { { 0xcb51f03954ebc926L,0xe235d356b8d4a7bbL,0x93c8fafab41fe1a6L, + 0x6297701da719f254L,0x6e9165bc644f5cdeL,0x6506329d0c11c542L }, + { 0xa2564809a92b4250L,0x0e9ac173889c2e3eL,0x286a592622b1d1beL, + 0x86a3d7526ecdd041L,0x4b867e0a649f9524L,0x1fe7d95a0629cb0fL } }, + /* 49 << 196 */ + { { 0x028bc25096c54946L,0xace5e7ad0f5fb7eeL,0xc820d7513350ab02L, + 0x4ae1f6d99c8d7635L,0x03d1f83a98e1ed80L,0xf014d45d5ad14550L }, + { 0xeb8f2c328cd6d0b6L,0x090a8f71770f586fL,0x1a8219f93eb7d3b7L, + 0x0d610d9febfc26dcL,0xfdb49980aa330297L,0x6396f218d81b3fbbL } }, + /* 50 << 196 */ + { { 0xb4ea3102eacb7b9bL,0x4aefb43d72af1d6eL,0x9a1a912d249a51d6L, + 0xddd0a5744d5e3a1fL,0xe252114708aa1f69L,0x4b235efe9de89d5dL }, + { 0x6fae47420d7f1aa7L,0x0434ae2ff200e13aL,0x75143dc192508b57L, + 0xc441a768055e177aL,0x84cd7adf2f142b2dL,0x56484f4161d9ad5aL } }, + /* 51 << 196 */ + { { 0xe3e9d0881beecd14L,0x4bd12b179093ab18L,0xa6908ddbc925d5dbL, + 0xfdc5f740832d1474L,0x1a35623696f831afL,0x0e39086808cde8c9L }, + { 0xab1c7cbda2206b32L,0x84d299c8b93ccf1fL,0x380fa432dabb6542L, + 0x59f01b5177c2cb3dL,0x9785c47b6e56c4bbL,0x047acc813a3f2b1aL } }, + /* 52 << 196 */ + { { 0x724210e61e42b4a7L,0xa8d536afe2dd968cL,0xc69936e683582c60L, + 0xd031f1abdd5d7f68L,0x7d31dcae8c4180d4L,0x117985f622bca188L }, + { 0x3b0a982537e38dc2L,0x1663fdc5896fe4b4L,0x55d18cc7fd707372L, + 0xfac2d7a40d2d8470L,0x994763391b04b1f6L,0x87cfbb5ee0bd72e4L } }, + /* 53 << 196 */ + { { 0xeac6a72ad5dd2841L,0xf1aa32524277e152L,0xe6c44e9b6ef7e947L, + 0xd03309fc54095378L,0x6fc5fb9ccdd06947L,0x10ed0e76d1e9a968L }, + { 0x42d5ab02dfb77b17L,0x4c54c381a53de8ccL,0x5fb4c256f2b1b5d8L, + 0x17d5ab28e12ed054L,0xd7c96ce1139da42aL,0xb32f63859919f459L } }, + /* 54 << 196 */ + { { 0x4bf5788312f4b0b3L,0xcd69d82ef46735faL,0xc397c8f9a1baa0efL, + 0xfce184c0fd1be398L,0x15021775fa54580eL,0x10bc85468f54397cL }, + { 0x6009a691eaa9d711L,0xc9c6a42fb7846417L,0xe9c305685627817dL, + 0xa1be66ff92abd5daL,0x9317838fcdea11c0L,0xace94ddcc85e7aa5L } }, + /* 55 << 196 */ + { { 0x3ef37821d4079bf4L,0xff78abebfcbdc3d0L,0x117414bc4733ea34L, + 0x7f181a3b9f50d0feL,0x9ea5f94eda897ea7L,0x01a996ceee8314ceL }, + { 0x0cac3c8b420e988dL,0x7ad66ac4bed3294aL,0x6bbf6dd800b62445L, + 0x590a57017a2fb4fdL,0xbf3b4e529ac11d81L,0x1bd453020d60c710L } }, + /* 56 << 196 */ + { { 0x8a43bba0902c32d8L,0xd8c69b74a3955e42L,0x413bf25d79c64afbL, + 0x3c39837584ac94cdL,0xfbfa9c53a08ccf5aL,0x9d8ac945e9d791d4L }, + { 0xfb9bb89e5e7a2553L,0x1442612bb039dd24L,0x8250ffe0a2e2344aL, + 0x5eae8b396426b985L,0xa1657768484741deL,0x05e52d4ac73cdf8cL } }, + /* 57 << 196 */ + { { 0x61c2417995c5e767L,0x7456380c3bdfef62L,0x62763f43d206cbb1L, + 0x1996e2c657871e44L,0xd0dbd290f220c06dL,0x6778e1e5d87743eaL }, + { 0x40e54caf16b8f046L,0xe834a1cb6bed77daL,0x7240befa3e9457c4L, + 0xd1b638dbac96cedcL,0xd1d7e814c9c0cd8cL,0xc73beaf14d38258eL } }, + /* 58 << 196 */ + { { 0xf1a6d776c05f40feL,0xb98c19b1c21ce471L,0x700b0bab7f9689eaL, + 0x861513a56f1d2e6eL,0xb7558b2292fe4456L,0x2d8f860704c66a25L }, + { 0x10ba7d6a7998347dL,0x72bf56093983b98dL,0x8d873c4f89238292L, + 0x5db0dca9a5e3c944L,0xf81fe37e0925aef0L,0xed6a13a4e4daae25L } }, + /* 59 << 196 */ + { { 0x49e2372711c3a930L,0xbf2ede34f5293b8eL,0x0abeeb3ca8e1cc9aL, + 0xb1db299440205cbcL,0x3252d29e52fb01d4L,0xa0b080c57dc91095L }, + { 0xb56fdae622a9ceb9L,0x6c3c3463b31f6f27L,0xcb510ec2ae3bd22aL, + 0x1efcd77b0b3db475L,0x1094bcc5ca766f9cL,0x688e940dfea48297L } }, + /* 60 << 196 */ + { { 0x3d95d26a99cde27aL,0xed608a89b99344f4L,0x7a70a8f09c0ab25cL, + 0x7740953c496552d8L,0x4da4ca0f4a366adcL,0xbf475c1b33274d4fL }, + { 0x5ac1d8288811b869L,0xed62e7b4d23446d4L,0x67d78571a0eab287L, + 0xa74ae3e98b0acc4dL,0xa63f91d64077c236L,0xe2c3f82a818a6889L } }, + /* 61 << 196 */ + { { 0x2bde7037b1d5fbeeL,0x477a4b51a80b92f2L,0x195ae0e06606b504L, + 0x7aaf3de57497785aL,0xb5581ee9290c5ef9L,0xcb303c30360c8ec2L }, + { 0xfb056f901b1fb602L,0xa38bc9f59931b7ceL,0xb0b74aeab2f453a8L, + 0x9a0e2ebf668cd68aL,0x8b7e0d73d7db7842L,0x21f29b74d1fa5433L } }, + /* 62 << 196 */ + { { 0x38321d7c4e11f824L,0x04dcd3a3e4a816e9L,0x382968ed07e09612L, + 0x6f7b2dbfa370e1d1L,0x5a8472348675d730L,0x88d974b0e59e984fL }, + { 0x89f7e2bce3f9e429L,0xd478eacfe3aebac2L,0x8df9f281ebef3488L, + 0xcbcb9fbeab5543b3L,0x2c8d19b0203f59e2L,0xbb98e4495287b0fcL } }, + /* 63 << 196 */ + { { 0x16c45f709aab81d7L,0x0f1310851795a4b7L,0x3c63d43af0ecd732L, + 0x22e2d1988628b683L,0x7d7482bab641d6d4L,0x6baef4a2ab69891aL }, + { 0x10989097e63c00d2L,0xbfd42ab0d93794ccL,0x9a1935f3e4165a41L, + 0x359701b35b600ca7L,0xbe7d69f983d1b54bL,0x99b0f35e3729bd4aL } }, + /* 64 << 196 */ + { { 0x11dd860e1c6d03b0L,0x30c1700809eec660L,0xd4f8aff635c0192fL, + 0x96a727b1e3a4a900L,0x1426daffde78c8baL,0xfacaa9bd8d1527c4L }, + { 0x0c0d5234cd072989L,0x1936c20d918550b5L,0x4828bee43d914fb3L, + 0x8324ea38f3ba26a6L,0x027590f3a94eb26fL,0xfd354295acd957bfL } }, + /* 0 << 203 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 203 */ + { { 0x3ede2484da756624L,0xb22da2ab73b13062L,0x56069e93962a667bL, + 0xc931266b130f2ceaL,0x4bd6a6fca7366a66L,0x23f30563aa5ac3b1L }, + { 0xa025d0efd7c2b26fL,0x597ce7d862129bc7L,0x4809927f2b3057f2L, + 0xb001c10a1499f884L,0x309d141c30b9a653L,0xadddce7dbf659d05L } }, + /* 2 << 203 */ + { { 0xa6c32900af2825c1L,0xb37c46c1d223a04eL,0x691e7d39063de7eaL, + 0x998df4e710daf9bdL,0xc7085b9e718b5d7aL,0xd41abcc816b3d4b8L }, + { 0x4dfce693f9bc4041L,0x383677ed659ec7a8L,0x2c1904bf4491fb34L, + 0x7c1bf1114552451cL,0x6562cc2c3c5e5e40L,0x1ecaa2a1fe0e4372L } }, + /* 3 << 203 */ + { { 0x9657d08ca9cb9ecbL,0xf69662363b75be69L,0x396a9344a31c2b8cL, + 0x1c50b1269767bc1fL,0x597223d0d1417e03L,0xe165ed5a12137153L }, + { 0x8bce29f926a24098L,0xc428a1fbe99e7bf8L,0x6fd4c906eea7f1d9L, + 0x94275713fceb2e05L,0x3555448b741dbd94L,0xc50e85459faffd4dL } }, + /* 4 << 203 */ + { { 0x84c3630bf3087bc8L,0x152691e674be6e26L,0x5abd125ff61af001L, + 0x69bca56fbfea3525L,0x384af19900e0cb6eL,0xb0b13cfed00475a6L }, + { 0xedafde495e394049L,0xd988b558daf2add6L,0xf14cf97a6c8ffcc9L, + 0x4d6cec23e5a9cc5cL,0xb0d678f88a104e05L,0x80a7fcba9fb527c1L } }, + /* 5 << 203 */ + { { 0x9ae12b902af1ffceL,0x082f30b95a30521dL,0x974099bdc304014bL, + 0xab1e27e444ccb6e5L,0x72db8f42290387a1L,0x3d1a461040f3ce18L }, + { 0xe939a3f2634ba10fL,0xe70a9cf517254c56L,0xd0f8692fa08ec3c5L, + 0x77edefcc7a7cbdf8L,0x04c4b18ebdf90f0bL,0xa890436a8aa36a59L } }, + /* 6 << 203 */ + { { 0x8618ffa79e30f8a0L,0x9961390cd12699bbL,0x5b1b0d744f61edfeL, + 0x33df67d9eb7a476fL,0x7f1a767ea92ee99bL,0xfab400e32223a2ccL }, + { 0x16f376f2f534dc3dL,0x6f36eaefcec17905L,0x8dc1516ca58765deL, + 0x893408262260ed6bL,0x060eb0afcf4b29baL,0x9cd0a9f11d252bbaL } }, + /* 7 << 203 */ + { { 0xd3c2a6a8ca413693L,0xcc56a8e932d5714cL,0xc72b73683c0da165L, + 0x5d236660db44e616L,0xa83b2ecce5c73667L,0x9d292f298aea900cL }, + { 0x67121215aaa2a7eaL,0x57dae96abf889191L,0x63bf7a81d296ae68L, + 0x9bf518758fd496c4L,0x5b4382fbc2f7308cL,0xf1215dfc9632aad7L } }, + /* 8 << 203 */ + { { 0x0d6cadbfc22137d2L,0xb5db59d3628a3298L,0x3b433c734ab19507L, + 0x4fc53405660086b3L,0x770ae903a1eb0f43L,0x31b5857ef6b5b58dL }, + { 0xe206e141d392868eL,0x8be6956f4b31de04L,0xcfbfca2f47449e07L, + 0xebaef25639fef8e1L,0x959e37b8c16fc80cL,0x8bb4bdd2e911d61bL } }, + /* 9 << 203 */ + { { 0xecfb851380fc41f3L,0xb0dc8823931843c4L,0x59decd6c1b93df03L, + 0x954103b72511e252L,0xe372f86a0f759de1L,0x04f5afd38f6f9ef3L }, + { 0xbd8e60affcba2e7cL,0x9b1cb1ed092315b0L,0x5f9e20a03fd05e36L, + 0xfcdcc44ded95f25eL,0x6baf401b6ac79cb5L,0xfe1a5a856894f651L } }, + /* 10 << 203 */ + { { 0x014a0907e51c6673L,0x28118ccd3e6e6a91L,0xdbbb7c4dc999acc0L, + 0x01b771075e7ab1e3L,0xa33fefbfcd8fb11eL,0x1df5b61fc0b8a5c2L }, + { 0x774dc2674478c5c6L,0xbfe1add422fb91a1L,0x5ac4dc694d9c8461L, + 0xbf6e002a1e772c5fL,0x4922120e0b83fe91L,0xa7747f4b3efbadceL } }, + /* 11 << 203 */ + { { 0x4b955beaddaf2e82L,0x3775ecde90fdc68aL,0x579c34f91713e763L, + 0x6c27f504fa509d74L,0xef6df04a3f8dbf4bL,0xc39f2e28b3ad7104L }, + { 0xe54042b3a5973cffL,0x4e594427f111f3d9L,0x53c7a2ba155fce57L, + 0x7b3c1c60e6e1d21fL,0x5e12db8d308ddf4dL,0x2c3c5e77a00e8976L } }, + /* 12 << 203 */ + { { 0xc483d4b24343bbf8L,0x42aca2e18a0fc95eL,0x5165df6fcbab1fb0L, + 0xeb284370f6cdfc0cL,0xab565c00994320fcL,0xc0d157fd62133e80L }, + { 0x7850cda55b69644aL,0xe37ae76a806ec8b8L,0xd14b805cc2c82eddL, + 0xcb5468b6cf244539L,0x97d43ee825dbe92dL,0x1442243689fb8f1eL } }, + /* 13 << 203 */ + { { 0xcfc8a945f361dc08L,0x383a5336491dc3abL,0x77580587c35cd376L, + 0x6604248ae2426904L,0x47c56025ffeb9d26L,0xc301edd8bae5d983L }, + { 0x7c6511a9e2e5cf33L,0xdc52c1dd221d41acL,0xdbdc8acada47503bL, + 0x01b406864bcedbbaL,0xca9cb9fd2d5496d5L,0x5768e0edb17e8400L } }, + /* 14 << 203 */ + { { 0x421afbe0431cb760L,0x9ae9ff985203e69bL,0x56cacf4db1a2705aL, + 0x6a3a4136d128bcd5L,0x2411c4b866191ad8L,0x39f26e1a15b45d24L }, + { 0x4cc82459c64ed153L,0x5c7a0dd58195b452L,0x9c88bb1c69f6298dL, + 0xfe567b031933fdb5L,0x8a6aea71881308c3L,0xc1268b55a2f0adfaL } }, + /* 15 << 203 */ + { { 0x312b777c1231c557L,0x3984f71be9971115L,0x0266b58294cc2d4bL, + 0xc3058419cdf5e5c1L,0xab3a1ae477bbf0d8L,0x7c2173a6d21603daL }, + { 0x61cca8cc747b092bL,0x70f77a53e376506aL,0x742c20692f1ccc85L, + 0xb1f2ceca2dc8844bL,0x5a73cff83a096c10L,0x28acb67d5c19cd11L } }, + /* 16 << 203 */ + { { 0xd7bf2ac6a0a85236L,0x2921b55c7194c46dL,0x162fabaa9afa9762L, + 0x7b7f1664b62b36abL,0x77b9f797296a84e9L,0xfcc1ad657dbd843dL }, + { 0xc6e9c1e1cd77b7f6L,0x9cf0e272917067c9L,0xfa7fa93d3bfa90bfL, + 0x55846fe9d050e46aL,0x473b9a0d35c56256L,0xadd29e332b656a65L } }, + /* 17 << 203 */ + { { 0x4698137f46fb8ae3L,0xb11a595f7b1c062dL,0x4a043b99ff023ef7L, + 0x2836d64d8ef0fa4dL,0x4067dbee8ea44a98L,0x9d1739c9f00ff4e1L }, + { 0xcbcf12fe133d2703L,0xd2923424016037cfL,0xda7543d68be5f666L, + 0x587d1920ac5e1847L,0x14662476f79e3462L,0x0120a1d8c810a1f3L } }, + /* 18 << 203 */ + { { 0xa4fc828ab18f9bb1L,0x06de4c9da27a787aL,0xfbb7c7d7b1b3a12bL, + 0xa7052b94b8583128L,0x173ec2d2e7b02fd8L,0x4b724682c776c664L }, + { 0x46ed9be5673183e5L,0x312191e83bd17c60L,0xe3ed6326efd56a9eL, + 0xb3ebc44c943a2278L,0x7ef62ba9ec9cf589L,0x754be6d389832cd7L } }, + /* 19 << 203 */ + { { 0xccb4b369dc992b32L,0x0ef84cc0922cee22L,0xda0058f1fc56e9e1L, + 0x208c57943f23632bL,0x3589a7338f77a82bL,0xee6cfa2c76ee99bdL }, + { 0x88cffafc418f7993L,0x0dde3f05f4be56d6L,0x5d088382a0472bf5L, + 0x872ca5aabd58d05dL,0x9c467c62e8f91f17L,0x38ab1b348c6b91ffL } }, + /* 20 << 203 */ + { { 0x926c2552ebc69b0bL,0x953a850fd4c7432eL,0x0ee85e14b9359035L, + 0x8b10b01abde090a5L,0xb2878dcaec423943L,0x2571a178f70bde20L }, + { 0x24ed159af5ebeee5L,0x60c202af043f6539L,0xdaaa76f4c8d4ffc3L, + 0x2fc1f1ba06eda10fL,0xddf159ee88ded556L,0xcfa71782e67b1ec4L } }, + /* 21 << 203 */ + { { 0x2596ee7409d3ed60L,0xd42551f474a46e37L,0x2e46a92e21061c90L, + 0x236299fa73ad22eaL,0xacdccd5214393ac2L,0x9a572130b56b4d5bL }, + { 0xddfc31781835e70bL,0x5dac0671d542048dL,0x2b0768d7a6dce17cL, + 0x6d447d4206c55342L,0x6b55b21525548478L,0x24e6483518d5310dL } }, + /* 22 << 203 */ + { { 0x3c58c5ea9b037c66L,0x08d0648e0d5c6ec5L,0x1bf90c53a4fa3f5aL, + 0x660cf61740381205L,0x63fd03081d44af3fL,0xe22b9c1a77175de7L }, + { 0x0b6044fc3556fc9dL,0xaefb6804fb55318eL,0x77045bce5c46e1ebL, + 0x29c4a3bc76e8f93aL,0xdf8aec699d697f5dL,0x5bd9552845a89080L } }, + /* 23 << 203 */ + { { 0x1bd61fbdc5756910L,0xcfcc6d5adeaca40dL,0x292867885dd80ac1L, + 0x7effe328d621c0a6L,0xc64ebb91ab22a2b5L,0x8954ab330c44a456L }, + { 0x7552a0b460e26218L,0x2e81d3a94136adbaL,0x96dc2451610d665eL, + 0x30859c62ab04e03fL,0xdb3726fd4c31fa3fL,0xbf4954d1d962a7c4L } }, + /* 24 << 203 */ + { { 0x31521f66d5d826b0L,0x0a63695240787844L,0xc0a3bd059c8f934eL, + 0x12c57dd42f0ce835L,0x847f6a9967064213L,0x1c9e1a7aa88bd71aL }, + { 0xc4060eb2171e8407L,0xdf78d8dfed106780L,0xa3d28ceb0d704729L, + 0x4f8e523246ca3912L,0x09e9f852017791f4L,0x594006631e6ea97dL } }, + /* 25 << 203 */ + { { 0xdd26fb79444827feL,0xbf78e076d3f5fa6bL,0x46d486e81a5475b5L, + 0x43e325a5faabc3f8L,0x1fef6b6ba6795d0cL,0x40e040666644d631L }, + { 0x16207bb9676c3322L,0x677c1c235811706bL,0xb686252e994e2a95L, + 0xa359e2a51b6f6a3eL,0x6d8f06cfb124f019L,0x3bcf778246266c42L } }, + /* 26 << 203 */ + { { 0xeaa3426b8eb929aaL,0x090924f2327bb35dL,0x4d23ba1276da394fL, + 0x05d98e56adecd43fL,0x83c7169f6b4af795L,0xc22560a7c8f26ae8L }, + { 0xb43aecc2d01ab5d8L,0xe7bcdc1f7257d7d1L,0x6f32d77650de3318L, + 0x6d736b279bf02c0aL,0x9534fa5865319235L,0x5a6a38493cfbeb3cL } }, + /* 27 << 203 */ + { { 0x3ddcb65828c50956L,0xb335f336bf1bdb4cL,0x7c18d2d0ac3b6194L, + 0x8748654bca324d11L,0x7c9c58dac2e85f94L,0xf1930a56d4f4f957L }, + { 0x9cacbdbbe410fee8L,0x0e292c2178e1312aL,0x6845b293906a6270L, + 0x842ded0f00c5401eL,0x747cd08f35e3ff9bL,0x8405540af48227feL } }, + /* 28 << 203 */ + { { 0x547b0d9583939224L,0x3a0823ff1e026769L,0x6016671525bd43acL, + 0xb6cf475e18ba5f64L,0xa22f9c92c8b6d09dL,0x730553683ccf50abL }, + { 0xa6de248eee6deefeL,0x32aaf8b2acc3ca20L,0x0e254c5bad44e674L, + 0x8aa73e6535f95f98L,0xe622600160a2dc1eL,0xdf9482109109020aL } }, + /* 29 << 203 */ + { { 0x7b24d7b056190aafL,0x0115cbdd0563b377L,0x5688526ca7ba4975L, + 0xd2971e28aee3100dL,0x57a6ff8a6fa24f61L,0x9cb571c4d8603be7L }, + { 0x09c01564a2cce6d5L,0x14f0902b89884939L,0xd71a5ff8a072ffecL, + 0xee7848b8fefeab69L,0x7b52a9577e40895aL,0xd1576be7e8c61be2L } }, + /* 30 << 203 */ + { { 0x4c4d454849d77b8eL,0x431f942f6a4c982dL,0xc8633d051cb39ce8L, + 0x23421f8caf516f9bL,0xc9db25d2aac876fbL,0x9f2669c5d882760eL }, + { 0x59dc4bf4c47d4bfaL,0x99ed0024c475f93cL,0x269d1ca4ebe07d37L, + 0x49ce3bdbbf88b1faL,0x515044053361e4ccL,0x207f0048735b3c96L } }, + /* 31 << 203 */ + { { 0x835fe90b5a516e82L,0x26f1f2a7abfcb383L,0x3dae65a8609c4ac0L, + 0x70b01d6e91f4054eL,0x22da015b581e3159L,0x2ad34f99329d1ebfL }, + { 0x7385aad60d09b845L,0x4cbafb0b0adf42f7L,0xd8727d26c02398cdL, + 0x58c261f590549db5L,0xd49b12e48ea70310L,0xb31eea047ef89773L } }, + /* 32 << 203 */ + { { 0x372798f02893f2f7L,0x4f62bfac9e5030caL,0x5e64f9a98a1e2567L, + 0x5870254ce70391c8L,0x2def81a341f02458L,0x25d4e4dc1d087bedL }, + { 0x3557d07d4fe24a13L,0x6da49186dc3112bcL,0x08c8c5675f73ba50L, + 0x5309050b9c7c6706L,0x2ab67da3bd985072L,0x9bafa8b1e5df4e96L } }, + /* 33 << 203 */ + { { 0x5acdcd216f77738eL,0x340710746cb67a3eL,0xd68c55cf4bf76bf7L, + 0x64c159200b4deda8L,0x1021d38ae242b1e0L,0x615f1f033bd3d95bL }, + { 0x2ae0245cc300c9c5L,0x3549605ba88d63e2L,0xfe0dd65ad5038849L, + 0xe67abfec63c6e4aeL,0xccd08ba528153bdfL,0x9be9f5bced4d76bbL } }, + /* 34 << 203 */ + { { 0x30fe00bb6e8423deL,0xe16ce94784e4d005L,0xaf0f8c283fed764cL, + 0x05ef9bf67d92b1efL,0xbf6570d4eb481da7L,0x39349e30468494ebL }, + { 0xe32b99a63fb36907L,0xd92386da2d35e71bL,0x74af8b79166a973dL, + 0xa0a177f94f72de6bL,0xfff3e19d5dd6c660L,0x15310d4d4b0d54f0L } }, + /* 35 << 203 */ + { { 0x692a561f15c15a11L,0x25abe85f26ca3ddbL,0x50fef4444caffa5fL, + 0x58472cfbed3f4aadL,0x7e9178f0092d2b83L,0x3afd364ff8dfaaa7L }, + { 0x4686ee5cbbf813a8L,0x6a62687d937cbae4L,0x56f22558a9b7b6c9L, + 0x9af1beae9c189e25L,0xfac4ad9f4d41f79eL,0xdecb57431f9c7a40L } }, + /* 36 << 203 */ + { { 0x3ac662895c02f173L,0x6a110e3876d566e5L,0xd9cc14e2b9577e26L, + 0x6f3d5df9fdfe617eL,0x8fac740f352bb2caL,0x50bc8a0cc28e6310L }, + { 0x6e572fc477ac93f7L,0x56277377605bb8e9L,0xad6d0637402b8c55L, + 0xdab377914509eda7L,0xae770abc0854e91bL,0x523bd278742b3de8L } }, + /* 37 << 203 */ + { { 0x8ede0eea2aa0da2eL,0x7015ee6e90cfeb90L,0xef33f3efd6b3227aL, + 0x6e332f1712ef9f4bL,0xcaa089898e7f9fe9L,0x001482ef8fa71529L }, + { 0x2522637907a5019aL,0x807faf01bed40fc9L,0x426002ab56710e12L, + 0xcdfffbc18d3949e6L,0xcc03f27861284379L,0xcd7dc2026d5edc82L } }, + /* 38 << 203 */ + { { 0x94f84d57cff31148L,0x9c567c7f6bf2a313L,0xc82e62353149ad8fL, + 0x81f69703c2a5d513L,0xb54e6fc756eea9acL,0x6799c7957c3aae62L }, + { 0x78e89c1edb280515L,0x3c5693066ac42925L,0xd984c86dab063cc4L, + 0x61754b5151d44ae3L,0x23af8ec0cebeef0fL,0xff67170bc618fe8aL } }, + /* 39 << 203 */ + { { 0x123b567195b58447L,0x7397316ad43aabd2L,0xcb65d69d9ddc7979L, + 0xf98be7bd91150e08L,0xa5388c79fc0ae5c7L,0xb115690215ed9074L }, + { 0xc2d01b9227e9afdeL,0x80d705ec2095a6ebL,0xbea901c7fab23079L, + 0xced8b2772346d712L,0xad5c45a92542a0ffL,0x87b2e4ac0455e90fL } }, + /* 40 << 203 */ + { { 0xc2cbd64417fecb90L,0x61616eb3b32dffdbL,0xdc4485a29f5d2095L, + 0xf78911246553371bL,0x4f06ba18bf9b20afL,0x136d4f291a2c4df1L }, + { 0xc04aca34fb8b685fL,0xeec83c20f2b657bbL,0x4da5d70a5925a36aL, + 0x8060874172ff2965L,0x2e0dd9ff9f352620L,0x5f0afa6746d1a7a8L } }, + /* 41 << 203 */ + { { 0xb76c722762c1e582L,0xbce1eb164ffefd05L,0xa574a9fe169e53fbL, + 0x77bf92b0c001628eL,0xd998172c04d60440L,0x62f35199ceae6bf7L }, + { 0xd81a563e93f1ff84L,0x5a7a0b4211598ad0L,0x884f2ca5ff11f3f8L, + 0x99f5aac2f3ac66cbL,0x58497c01f489c5afL,0x11277bc39566521cL } }, + /* 42 << 203 */ + { { 0xfb9670c26a770385L,0x5da887e1e9682174L,0x31fa9d6bedf922f3L, + 0x8de8814cf7a98d1eL,0x3935b9b27a019f08L,0x1f59d6f3ea6173caL }, + { 0x8732f39d5c638a66L,0x981a1b7a3d48d3e5L,0xea451b381ee0ab37L, + 0x31a8e9abf2708356L,0xa491944ee86cbfc1L,0xd747a885a97ddfcaL } }, + /* 43 << 203 */ + { { 0xa3460236aefd304aL,0xaac80f43c58719a0L,0x7d635c17d3ca5b1aL, + 0x986ac0a62119976aL,0x0d8a6e39f2538d36L,0x6a02af2f31849d5dL }, + { 0xecb6ef8f6719d4deL,0x6dd71ab674ff8880L,0x0d40ec0e9d225d93L, + 0x304cd88adf381d24L,0x2d6787380c5571fbL,0x03c23f547c03af94L } }, + /* 44 << 203 */ + { { 0xa995a95bf46aace5L,0x44ede5379eaa630aL,0x421f3b3500336e3bL, + 0xbf897478cf47c9edL,0xf360ae32259e0827L,0x04e0e3e82e6a9f6bL }, + { 0xb26eae5fa9136702L,0xd6cb15a1853674b4L,0xf81276e2748bcbc9L, + 0x7fc02e220a4ca1d7L,0xf650f48ecd82f330L,0xf4ea7c1dabaa8859L } }, + /* 45 << 203 */ + { { 0xe9f090b935caae35L,0xe04dff188dcf1e6bL,0x81b7de5eb8032e04L, + 0xba0d0b4e4b1e8070L,0xaa82dc8ad1a2aeb3L,0x5855ed1ded26f229L }, + { 0x8bce967ed1955233L,0xe6ed07f356ac7532L,0x4227c7fdbf0eff2dL, + 0xb1f4785fa5e213e4L,0xeedad0733ac30f4bL,0x503619889cf1e686L } }, + /* 46 << 203 */ + { { 0xeb252116ba5da79eL,0x51cc937edb691345L,0x1d5fec14077458c1L, + 0xaa304f7ba0808e6fL,0x4bed89f5abec4c09L,0xc67293cbd1a3b798L }, + { 0x0905f7d342122672L,0x83675b2da0d3a277L,0x7f422b7024bf5bcaL, + 0xe2144c6910495acfL,0xdac1c357a6a6ab5eL,0xd1a3b951c8b1d472L } }, + /* 47 << 203 */ + { { 0x0821017d60c0c248L,0xa17ce97a8540bdc8L,0xe0576ea986e6f45eL, + 0x1453268bf152c6eeL,0x1ea1937138edbed5L,0x970ad9c002343c23L }, + { 0x3a08a859af8a97afL,0x20caf7cab570d738L,0x6d82d863e2a89455L, + 0x30eb8d0724c76844L,0xb31d58c8d32b79f1L,0xe5df7cb9fe63e93cL } }, + /* 48 << 203 */ + { { 0x1ccd44ff95c746ecL,0xe18914b510405763L,0x50ed644321a3a927L, + 0x4f96a1b143ef8e8fL,0x7f5645e577952bf8L,0x4bc5c7ab66dbdf15L }, + { 0xacc1612623930a08L,0xbf5ed482504cf9b6L,0xdeb7a798d71ecbd7L, + 0xf62e63b14a4dd859L,0x668809a7daf714d9L,0xdd836382f3a4329eL } }, + /* 49 << 203 */ + { { 0xac0ef2cf383e038bL,0x848e3c1f91135098L,0x19e5a3ee3f15b241L, + 0x2d01f1a2dbea2ad2L,0x44ec32a799cb0bdfL,0x3e66fed4eab4d856L }, + { 0x3162a75af45c8656L,0x53ab74245a37ca4fL,0x1b81f1dc360bb395L, + 0xa7eb222e2b8a5267L,0x163bb0c804b0bcaaL,0x1cac5bc0ef5c417dL } }, + /* 50 << 203 */ + { { 0xb95e2d85e81d9e43L,0x8a92acdd1418f6d8L,0x5429140110ee43d7L, + 0x32a2933c625838dfL,0x801d57dd3d485868L,0x33bba67258af765dL }, + { 0x545fe2583f520eecL,0x900ed51a32d71974L,0xf21fefe6df3ed77cL, + 0x2f0df28c9deb2d81L,0x90898dd780856fb7L,0xeba82159bbba4771L } }, + /* 51 << 203 */ + { { 0x83ecc8f374df3780L,0x432e9807d3a89728L,0x3461c5297b5cb6e0L, + 0xee307c19030c25cbL,0xd72b60c7391ee616L,0x0c07bf462e9b4384L }, + { 0x9d791b0bd44acd49L,0xf3b3411c9f3b33caL,0x1bf55cb97f9b455fL, + 0x77e01607600f0a91L,0xdab95bf26bb7e977L,0x30d0f591fe4633e5L } }, + /* 52 << 203 */ + { { 0x894bdbd9c48f3ad5L,0x687ff8de09e167f6L,0xf06104a930371c43L, + 0x82fd34b7ce84dd10L,0xae122deb66ce5abdL,0x31f041d2fc4a90b2L }, + { 0x2589535c9a01c607L,0x231bcc85695bd7abL,0xc67c306262e3a31dL, + 0x31be44757af3e186L,0x1a2077a388efa7f1L,0xffe53e22815fad1aL } }, + /* 53 << 203 */ + { { 0x4ce41f69a3ee310bL,0x38fb07d09bf311ddL,0x5fd284d660985bd4L, + 0x2fe99a19e04d3dffL,0x21a352520b3ad853L,0xb0808a89012aa69cL }, + { 0x98219cf718c7c301L,0x429e08fc91254db8L,0xface2e53c41d54d0L, + 0x180651242decb2d7L,0xa9f65e3f26a9191cL,0x1dadd3deed42831cL } }, + /* 54 << 203 */ + { { 0x81ce91dd6327460aL,0x4cc880a0e2f22af0L,0x81aa9bb46a6d36f3L, + 0x8ad516741dd10657L,0x212267854253b30aL,0x530d1f6a8f161dd6L }, + { 0xe7eeb4c7e9ab63aeL,0x84f225bfb72d250eL,0xc81cb984458a8dc7L, + 0x39fbbe3bda68c1afL,0x8c6c99b3083cafd9L,0x4700ba37eb07d40bL } }, + /* 55 << 203 */ + { { 0x8980dd7cd8dcc7b4L,0x0179e9bc7ad18f8dL,0xa9e4fa6a08c60f0aL, + 0x4f0d76fa3cc7dd36L,0x53339e4c51a0e67eL,0x1acdaf24cebd80cbL }, + { 0x5aaebffcb5264b96L,0x3ebebb22858df87aL,0xb2f4c1cb092a95a1L, + 0x34932d51841b1a63L,0xe0631aab49074a2fL,0x71525c4fe3b7fd61L } }, + /* 56 << 203 */ + { { 0xdd15591366229776L,0x84093730f7882064L,0x6dddcb14e50ee337L, + 0xa8e6ec597a1f7e81L,0x8467f998f3738a6aL,0x70fcc6bcad3f1840L }, + { 0xf82eb4be723b3f4bL,0xf0f3935406beec1bL,0x1b181ea37ddcb539L, + 0x9c82c4faad6a81b9L,0xcc5ea5435c612c2bL,0x63ce7571bb258d6fL } }, + /* 57 << 203 */ + { { 0xc6c110ecd3b9416aL,0x254403ea024f63e5L,0x92d2965b68aa4a66L, + 0xa08bfaafbaed92aaL,0xe2194cd701ad3eb4L,0x7ba66e1da7552847L }, + { 0xf68c90ee44eb9bbbL,0xabe38c5c5f6438daL,0xe16d4aa68c38a6a1L, + 0xc2f8691bf6294db4L,0x9248492fba64da6fL,0x850c6a6865a3d6b7L } }, + /* 58 << 203 */ + { { 0xa794308d2599a1f7L,0x06bbefce3e72b328L,0x24f2c6f5420f6ae1L, + 0xedf67defaae894c0L,0xf66396eb2e8e9821L,0x21fbf5f7a701c8ceL }, + { 0x7fbb192401732f26L,0x3d0063a944f57696L,0xd6bcb1c3513dd8f7L, + 0x1fbb11b2c9f8c033L,0x122f94b17b57b3eaL,0x08edce19d24626c0L } }, + /* 59 << 203 */ + { { 0x06aa75398c3a1e9cL,0x3512ec3c1a08c7caL,0xfad0dddac5a92e6aL, + 0xa98059ee3b9022fdL,0xd67b6723103fbda5L,0xc1df32904762c170L }, + { 0xfd99ee58c734f81dL,0xa8de2a4b478b8a4fL,0x9e3ed58fb4b557c6L, + 0x14d353c571abd10cL,0x10ea798fe3fd4475L,0x157e16f97627f4d5L } }, + /* 60 << 203 */ + { { 0x1b5888550b96547fL,0x4539c9c065d1a59dL,0xd6c95fea26e15084L, + 0xf84ad9e286b96242L,0x92f57d6d451a5486L,0x0215cfcb06a9e87eL }, + { 0xe05b10eaf66e46f3L,0xe7b0e72f655a0642L,0x035032677b117f43L, + 0xf5b78105779ea4a1L,0x28ee00faa4adac77L,0x1ea67d716a93a2b1L } }, + /* 61 << 203 */ + { { 0x4b68a01cd6b3387eL,0xc79582a9e7c4c99aL,0xa4ad6429029fc3bcL, + 0xf260ad946b83c7adL,0x81360618b09c3b8eL,0xf66e00ccc661ba2bL }, + { 0xd064537de29a69e7L,0xe2764d389bb4095bL,0xa3f57eb0f2efdea7L, + 0x72c214f27ed3ac00L,0xf8cfa59de392e32bL,0xa5d995124ad99928L } }, + /* 62 << 203 */ + { { 0xd069a9971dec038dL,0x64401a3fd0b59bf0L,0x33eff74ce7ec5e85L, + 0xfef5a1c50d35b207L,0x731cfc17e766bc43L,0xf994c0d01328b6cbL }, + { 0x4f2a5eaa2d3cc024L,0x7f83c57036a6fa14L,0x915a126d65f71dbdL, + 0x588fdd68acfb54ebL,0x7de9d37b7f57b2afL,0xca52d27170e071ebL } }, + /* 63 << 203 */ + { { 0x9b9211ada283322cL,0x30c6fa27b7124c9fL,0xda8f88a7474cbf5fL, + 0xc2414ee338203749L,0xe5c65cc26b767731L,0x8bdb52952753781cL }, + { 0xc8fe770be051cd30L,0x6370ecc4f046aa97L,0x03c83c1cfa287e66L, + 0x935bd2052bccef4dL,0x87b2a49646012036L,0xbce6a91de3e6d6aeL } }, + /* 64 << 203 */ + { { 0x7be81fb126882c6cL,0xe2d5a251ecd25498L,0xbb3d40e27a8d1678L, + 0x1806c67ad520811eL,0xadd4bb6686f65d23L,0x3a62b1b3e20e23d7L }, + { 0x208b47006548b3ebL,0x0497f09ab7ec2809L,0xbd3964f8121c37e2L, + 0xd35ef301a598efbbL,0xbd76a276c5eef966L,0x64700a7f0af64e46L } }, + /* 0 << 210 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 210 */ + { { 0x169474a2d3812087L,0x9de300da6698ca7aL,0x8589de922ede425bL, + 0x50e03fea6df8a890L,0x0d8a5c1c4ba8b8e3L,0xf273aa673fffb91aL }, + { 0x21cf054475fc8236L,0x6ceafacf9799c242L,0xc3237eaed0962c81L, + 0x43d6ac34213f6004L,0x45e619b2d4148b6bL,0xfafa18b5ea5fb80aL } }, + /* 2 << 210 */ + { { 0x9a8580aa2f063b51L,0xa83c8ff71c216613L,0xb4da0970be07f781L, + 0x0ac2a260712f7b7cL,0xc9b8ee84436a7b97L,0xd758c20d11fb2f62L }, + { 0x5daabed9f170b799L,0x018d2fddc46bc387L,0x82d6b5b7d96cfb8eL, + 0x4d7d0d9344d9e843L,0xfa2a9ea991e7da3cL,0x8230c1a3d531b253L } }, + /* 3 << 210 */ + { { 0x82412f525ec31754L,0x42f462c89d32e890L,0x1e7b58cece897ff2L, + 0xcfef785241164628L,0x34ee0422d8bb22efL,0x6e0d44ac7d32f01bL }, + { 0x968251655a3cc196L,0xa26724dc99eb23d3L,0xdb575fafa75f7252L, + 0x778e333062a3e5b1L,0x8689884e84cccc80L,0x9883cd19b645502dL } }, + /* 4 << 210 */ + { { 0x4cc41f2834220e26L,0xb5937c6da49749c4L,0x705366640fa1ca24L, + 0xeeb40f3b91e5edafL,0xcdf98235f1d3de14L,0xa65e5b7eff018c43L }, + { 0xaa3228e7acee3a6eL,0xb63a6289e08f4ff1L,0x90e90425650b2daaL, + 0xe4a8cad26d875f17L,0xc212029c9ce8a46eL,0xce0512835ed7cfb5L } }, + /* 5 << 210 */ + { { 0xb0df226159b79436L,0x82bd0dafa195be26L,0xbc99a94b3398c317L, + 0xbeb44c903c96ee31L,0x3c39ad81664d2e46L,0x081787520a3e0585L }, + { 0x9a054b6b413e269aL,0xbe58891d98c3b62eL,0xe7fa4c4de5734974L, + 0x8ac535f4d0a846a8L,0xea0f95f1a651339cL,0xa255274fd96aa239L } }, + /* 6 << 210 */ + { { 0xe23b7b229534047eL,0xbd70aea83a3bd625L,0xf44b05fe238db60bL, + 0x9c46fb140293abcfL,0x12cab5d3bfd8875bL,0x1f38d4aa12dd0c65L }, + { 0x4bed41572adf9805L,0x3f87da928a56609dL,0x10b93363da02c903L, + 0x7ecc726621ce4786L,0x8ae366851e3da5bfL,0x196040ffd3edee12L } }, + /* 7 << 210 */ + { { 0x4805841fe81508e8L,0xe2a578d3a4808642L,0x6bbf10accd0b2555L, + 0xc5071effaf5cde28L,0x665e75439a7124a9L,0x157c11edc1437981L }, + { 0x2019367d7aeddd8bL,0x74a1e104386e3b8aL,0xe72d429bfbe09a42L, + 0xaca96fd9061b862eL,0xbb2d2bc8122595f8L,0xc90c6503c509d644L } }, + /* 8 << 210 */ + { { 0xadb5966fcff05adaL,0x8ed26c025c57284eL,0xa76e73e244693a95L, + 0x14da74355982bbd3L,0x46e982cd5d2ca132L,0x8f39074024938e76L }, + { 0x749206b30a89b09aL,0x429653c793b4a1e5L,0xbee3d1567025bb7cL, + 0xe23f0e1e19555c9eL,0x0dec3837751639baL,0xb36cb84405d43bd0L } }, + /* 9 << 210 */ + { { 0xae76a96e74f90b6eL,0x5fa8e94824c6789cL,0x2b3584bb03abbb81L, + 0xe19ce47c5c451f72L,0x35792fbad619ac7aL,0xfa0282a250059bf4L }, + { 0x562bfd14dabe692fL,0x1aaf542c47eeb6c2L,0x392d5bba045d0360L, + 0x4e7bb31bd80fe998L,0x08f62ef31111e14dL,0x4de917b04e9ee1b8L } }, + /* 10 << 210 */ + { { 0x8b9d2d5867166271L,0x658db4ea142bab7cL,0xdf84932fa4ad2849L, + 0x04b113355f6f86a7L,0x2de6b29c50cfcea7L,0x46d8f68a9be6a3a3L }, + { 0xfb88cda7af0204afL,0x3ece449126029d72L,0x69fef1e23f946dfdL, + 0x708532fb01ef7bb5L,0x78d5053deb3795a2L,0x819a63206b36d57bL } }, + /* 11 << 210 */ + { { 0xca07e0c1e509d19eL,0x6c7e42c39f6281b1L,0x0e2ff43977b66728L, + 0x1d740e7880e76251L,0x6bfae4c631a0eb23L,0xd78ca917aa9b0b3bL }, + { 0xe140c662991e1781L,0x6e396b5f0dd3cfeeL,0xf0a1d1976ce7f6c7L, + 0xbe10f8efd5b01564L,0x865cbd54101a5194L,0xf665885266861dedL } }, + /* 12 << 210 */ + { { 0xe4e52e865b28f7daL,0xeb43a6809a58683fL,0x73b951bfb49f2b38L, + 0x7b6cb7db3f8097cfL,0x9dfb8d0b328fbf05L,0x491635a5ebce6211L }, + { 0xa31a152390fdd577L,0x334120df1cd2f39cL,0x1d22834e6b563876L, + 0xfd91b30d10ee5a28L,0x3d7a282d59aee4eaL,0x36814c6b73300a76L } }, + /* 13 << 210 */ + { { 0x7b584add6621c251L,0x98da669d4233aba3L,0x4d652b7933aa2065L, + 0x901bcfb8df7b4ed4L,0xb2ce587948012f81L,0xc18e2cd63cb71b88L }, + { 0xadb0f2bdff86279dL,0x46d9e5d65bd15866L,0x11b1fb3ec635a4c0L, + 0x8bcd0ad201b1006aL,0x0f6f7502cbab210bL,0xd6cc3e560d6b3995L } }, + /* 14 << 210 */ + { { 0xa54a6420137264c5L,0xa6ef0e78f9c2e45eL,0xba8b5a73d58d850cL, + 0xc0209ed86ef6fc3eL,0xe39dd0f391f7518aL,0x74697b8942b3eda6L }, + { 0x2dccac36abfc9150L,0x80e4fba298b2f5a5L,0xe0e56fd2771018d5L, + 0xa31fd1684c22bb94L,0x8b0998f71a66ef21L,0xed483e55b5a53ddbL } }, + /* 15 << 210 */ + { { 0x95db1c0ef23978ebL,0x80ad1612f04011f4L,0xe76bd1824d7ae83dL, + 0x841d6e668fc3bd60L,0xb68e80796875e2d0L,0xe3965efcd5d9dee7L }, + { 0xc488bb7e58930931L,0x52f4de19a907aa24L,0x39aebbdd321cc197L, + 0xd2f5b1f967de5c66L,0x60f1a8c28efe3e76L,0xf40604a0af988831L } }, + /* 16 << 210 */ + { { 0x78b5c14c0acb5935L,0xd9ec715c4311d3beL,0xffa22ab209e1759eL, + 0x5a86263db4b2f68cL,0x71e77c516b5be7f4L,0xfb5bea3a19844f6dL }, + { 0x2519d0060890ffabL,0x426a03f0f0329ef0L,0x2c6d74a685b3c2a9L, + 0x9306f68fc294f449L,0x552e77c22c69fb46L,0x7c7337ad10bb9886L } }, + /* 17 << 210 */ + { { 0x61f8a505d2b9f25bL,0x1d33aafe4c8645ffL,0x26f3fab7bcd333e5L, + 0x8ff4fc51be95e40fL,0x11cd52c6b55bdd5aL,0xf2b4782a22d43de8L }, + { 0xfe66e399a4c0e1c4L,0x26c6d7fc17954032L,0x44c700f97f20d2caL, + 0xdf67c3927187cdc7L,0xe11a98f9da36414cL,0x0bc5763a04052276L } }, + /* 18 << 210 */ + { { 0xe75b564bcf95451bL,0xd5ed760cc01aac32L,0xccf14dc5980d2c06L, + 0x235b5034ce2a5c0cL,0x64dc86aa05fa6780L,0x1d2ea4877385590dL }, + { 0xb18696f636c3174eL,0xf530487b608215b4L,0xa073d0750a123172L, + 0x8ca24b5afde8666aL,0xd6dd589a9b716dc1L,0xcab7ea504a721d4aL } }, + /* 19 << 210 */ + { { 0x34dee42c1592ebceL,0x5b0eba2e417636d3L,0xba178703a97d7356L, + 0x16f6119f4123e8cfL,0xd2906a53ef179fa6L,0xac5530606b7ed572L }, + { 0x82a25857b600f5c8L,0xb1dc1309973d516aL,0x6d53a967245c6e34L, + 0x7ce90bf4f670b879L,0x727ad4129732b6ebL,0xf00fb0054411dfd5L } }, + /* 20 << 210 */ + { { 0xeba7daad2b14da6fL,0x8274d1a8cee90515L,0x985c18f885bdbc82L, + 0x86555ff094d43909L,0xb0b1b2b6539e108bL,0xa4f32c66c0bf1313L }, + { 0xbd4777c162080e0bL,0x73039da8dadfb23dL,0x85bc57374a27f1ddL, + 0x9a8ae24eeaaa58abL,0x161cb2f5e876fac2L,0x54d457e46636e377L } }, + /* 21 << 210 */ + { { 0x409b17487bece8c3L,0xee36a1d3b49f5c90L,0x8ed9eb2a619ecefcL, + 0xc50a917798ab7bb1L,0x1eb247cceee2ccffL,0x07a9566f084a0f69L }, + { 0x59bda805a7cbee61L,0xf588124ca4e7ecd7L,0x0f7d8c3dde5eed54L, + 0xd98894ddefcb791fL,0x2fd80439ab309d7dL,0x0c8bf15d3e6cf756L } }, + /* 22 << 210 */ + { { 0x076a19c70e68a69dL,0x4d01c94b24b3854fL,0x9f38c5eeea8a85b8L, + 0xea80422d9a56f9c3L,0x10d9ceec9ad36735L,0x42194df742261173L }, + { 0xc7332e70c285d22dL,0xf3a3d4be592ff9b0L,0x2fe712f7f59846abL, + 0xd6de5201e4362677L,0x16ce8f1d4f30006bL,0x1f3c324d11dba5edL } }, + /* 23 << 210 */ + { { 0xa5af9e1c0cb4335cL,0x00a46bc0f3d0dbe5L,0x852a18c99d734817L, + 0xc12d54a9986c0102L,0x184b407063ffe60dL,0xe05182437d99d723L }, + { 0x8d3886cb20ef7647L,0x7e9c618017b1ce8fL,0x194baf260f176141L, + 0x978015d3b4694945L,0x2603be2f1c135e8eL,0xbc0f5e72ba074e0aL } }, + /* 24 << 210 */ + { { 0x1674b959cfe7bcebL,0x62e1279fe7b66a28L,0x3962a32dc67c3648L, + 0x4949617368d720a6L,0x4e81df85a957a5b2L,0x28b5c45753123c0fL }, + { 0x5091dd347e239c67L,0x10b9c3f6160ef925L,0x5e7720f52c119dbeL, + 0xd584ae76c94d609aL,0x476c63ba86dccd1fL,0x70103a1a32508c6eL } }, + /* 25 << 210 */ + { { 0x64f4f4ee90a17a16L,0x31165bee7cb22fb7L,0x31da800b924825b0L, + 0xc2c169db0551e47cL,0xf9ca5e0e0d583789L,0x5e4fbdb53cd42f2cL }, + { 0x6ade1fce1d81000bL,0xa105df391d6603e5L,0xd659094da3139f95L, + 0x363a882851d01444L,0x13cd7cbb2dece086L,0xaeea2aa96ab9020aL } }, + /* 26 << 210 */ + { { 0xdcb31a931081405fL,0x200090dcf1326ecbL,0x773fe49cde99f0ddL, + 0xf6a7cb67fac2c511L,0x95c93429b40b014dL,0x967708d4198dd723L }, + { 0x74591cc184b90062L,0x2539ef20691d2550L,0x7d7290765a5d86c7L, + 0xa81f085475c6fdacL,0x103186d1c0f0d5cfL,0x5ae582e07eb3b8d9L } }, + /* 27 << 210 */ + { { 0x7df39eb2f9f3456cL,0x1e7ad4587be12020L,0xaee54df11fedfb79L, + 0x98f3a0879bf1dfe6L,0xdf958d371d13fb71L,0xa745249717dc809dL }, + { 0x9f2ec9dd02d4eb90L,0x9db5686e48b0c7a0L,0x7d064cbf72532eb0L, + 0xe204d56593a71a9cL,0x0c912346f1aecdecL,0x894224a3d25d243dL } }, + /* 28 << 210 */ + { { 0x6bbf77cb5a508291L,0x2af81442d35db82cL,0x357feb1a2b9febf8L, + 0x74240a81a25330ceL,0x7a9ab575b4917998L,0xa60288d5eda3ef5cL }, + { 0x360410d30aea9569L,0xef66acb5b9bf8c16L,0x7baeb466cc381b57L, + 0x024a98b8247a4904L,0x6e70b4c3e3c58130L,0x276e2420ae8a56d2L } }, + /* 29 << 210 */ + { { 0x3b4a25222c57f1f3L,0xf43d352ba8d1f53bL,0x169fb3cce198b03cL, + 0x92172ca923235a6eL,0x90b5953683f996e5L,0x32b1a34cb5ab11a0L }, + { 0xb944e4b7b9001351L,0x1084de3d28ab5cb2L,0x60f1dc93c70ec63dL, + 0x790e1d496cfa10f9L,0x79bcc2277c3cd865L,0x95007ac24fd31fd0L } }, + /* 30 << 210 */ + { { 0x6b5d8db5f75e17b5L,0xc5ab42961b45a230L,0x586f097b7486832aL, + 0x1ec456c14f289757L,0xd11773bb57b04a20L,0xc84dfacd0821d3dfL }, + { 0x580da8cd586e399cL,0x58c1355ae3bbec57L,0x0a476934d594a2e5L, + 0x0490ffd537e99427L,0xd41348386a4d8c4eL,0xd62cccb3c83d6e28L } }, + /* 31 << 210 */ + { { 0xe6071a3d57c9e219L,0x88728c47a93f38dbL,0x0426848b50eb1a01L, + 0x9df36972cada9a09L,0xf2ad4a2d4f494ec4L,0xae26577de1f34993L }, + { 0x72ec08cde3618d7aL,0xd1fb89013ea90c46L,0x915936173b94f996L, + 0x8703357705387745L,0xf1961ff818fd5199L,0x7f0b58d34c2aeed1L } }, + /* 32 << 210 */ + { { 0x3313a9d544b133d9L,0xdb85c25d2da910ddL,0xc0fdef915e4dd5cdL, + 0x902a2a93c565dd67L,0xd8eba4dc7fed05acL,0xd453995ce157dae9L }, + { 0xd655d0b3f250cb55L,0x4194a09e86119222L,0x5b7e525a0652872bL, + 0xaf7968efe68c0ddbL,0x2ec02930f51cb31cL,0x237f3ae4f2be071eL } }, + /* 33 << 210 */ + { { 0x696d84910dc943a1L,0x1f24fd7d9fe1d7d5L,0xea38c9e349413ad7L, + 0xe223996607c1cecaL,0x62094496ea7bd8dcL,0x9aba5bc7236dd525L }, + { 0xa138ed5851631b6fL,0xed724f20902f109aL,0x3ab594cccb28f1e8L, + 0x3424213b5916dae7L,0x07e5a6df18479651L,0x4c51f2e1c5b48e29L } }, + /* 34 << 210 */ + { { 0x6306564b6591a811L,0x734b2619fd463a13L,0xa795d0569d8019d8L, + 0x103d85004ffe5858L,0xe1962c31adab8484L,0x326b3351b2015dccL }, + { 0x2ad52b852ff36c73L,0x5874652308682fcaL,0xf544e162ea37824eL, + 0xd4a6b45ec208ce7cL,0x52d09045d2559ef2L,0xde1dfbbe57ebca65L } }, + /* 35 << 210 */ + { { 0x3a94aec3bb793f9aL,0xd0af44d4b5352511L,0x1d3f1c130b8930cdL, + 0x016cab225a729e0cL,0x092a7c11e31b549aL,0x80c462ed90ebfea4L }, + { 0x3dcb9606e5e4ae09L,0xad150903ab59a450L,0x1b58210c6c944727L, + 0x26599f6024572a80L,0xfce0ad40c0445075L,0xedca1ada54c4037dL } }, + /* 36 << 210 */ + { { 0x794593303801b021L,0xb19bb405c9a4cde4L,0xe20091667f9cdee9L, + 0x762c684f7636d30eL,0xbf2b29f20c215831L,0x4c0d1b651853fe90L }, + { 0x196ccb3157defc94L,0x9f3d66b7f6b9cc44L,0xb2328a0eea439deeL, + 0x82b3808d7b140e5bL,0x986210dd88e4a35cL,0x9b171fc838a2b7a7L } }, + /* 37 << 210 */ + { { 0xdc80e3ae91517233L,0xa219f65dc6f20d29L,0xd348a3d8be093f56L, + 0x63c233774d33113bL,0x587fd56257f2ce9bL,0x82cf3e3a4e9061c0L }, + { 0x0e41f59bee8dd928L,0x7a5641be8aaef52dL,0xa852a171984ff476L, + 0x3c37fd1c047457b6L,0x7f00d665972d4793L,0x29dab0fd97b27966L } }, + /* 38 << 210 */ + { { 0xb1d119c91e9d07c0L,0x2f973a09432c86afL,0x3505b6f05ded5546L, + 0x21814b958687f973L,0xc104d7fad3794ae9L,0x81614d707ea91311L }, + { 0xb7f3e6b600677961L,0x53fceb8bc0e6a90dL,0xa3a7485699ed4fb6L, + 0x07ad488421d4807bL,0x527b1ae6004e0c03L,0x437f306215146393L } }, + /* 39 << 210 */ + { { 0x917b4cf463e12603L,0x79e0b7363f838ecdL,0x57de4b3328b4f37eL, + 0x3085e4887f58fcfaL,0xb9301c4e958a3bc6L,0xef8d10578b044eddL }, + { 0x2123d284d6391459L,0xdfcc2be5e196d765L,0xb58216268184b993L, + 0x13e21d03937c6048L,0x39eb3d38460d11fdL,0xf8ef123e5bb23c30L } }, + /* 40 << 210 */ + { { 0xa6f8b354666eb2f0L,0x7fbf6d91f9c7b16eL,0x9b360814161b5e0bL, + 0x13726fbd921511a4L,0x37aa1b8013833a11L,0x53f01183407b9889L }, + { 0x8a83ea3fd147da9fL,0x25279241db0ad0b1L,0x78353bccd1a8d9aeL, + 0x1e33c10e271f7f0eL,0x136d9e7e9e67adc5L,0x11dcef95cc56ff8dL } }, + /* 41 << 210 */ + { { 0xae530580d84ba919L,0xac2e43ceb6d3ecd5L,0xf97b1afda4bc6a2dL, + 0x180d66d5bdfa96a0L,0x935b8a7d1ca12bf5L,0x1d4409a79e678225L }, + { 0xdd85bf4b19a2163cL,0xe34197bcddeeb22bL,0x1e33fc3e1210cde9L, + 0xc96212a98b9b5d0aL,0xa3ae81f303e4a12bL,0x531a7148ea262807L } }, + /* 42 << 210 */ + { { 0xf11ac5fd4ace8006L,0x898a388133c499a5L,0xcf27ab9f1d3368ffL, + 0xfb6019606cbd6e54L,0x5373c2a901fb58b6L,0x1489f5037cd1b888L }, + { 0xb3f0e0b85a238131L,0xd0e11e6e670858bdL,0x897f1584b65768f8L, + 0x9252aa72013b1f2dL,0x185842af0a1a5f8bL,0x49a978373d681a70L } }, + /* 43 << 210 */ + { { 0x8b65c6d23396eaf3L,0x2191764e50b9392fL,0x7a2363b72dcf6d0aL, + 0xa6a52402f0591553L,0xfaba81cd5ff7a071L,0xd6be926ae43e37aeL }, + { 0x7b34c578ccaacef2L,0x2bc5d248d5eec9b1L,0x9447aab3014c0048L, + 0x767309a3c02d54d0L,0x408c6eee1f92297dL,0xf7ad95f40072a2d4L } }, + /* 44 << 210 */ + { { 0xd0051ab940ee5098L,0x4861b2461d8311deL,0x6b7796e0f31e860fL, + 0xde8b243acfd543e3L,0xef9d0957a0161843L,0x70fd43ecefefcbaeL }, + { 0xd47392541931a5a6L,0x42e253300342623aL,0x90b33edd52ffbf5fL, + 0x0affda4ca015a550L,0x8716376b77e59672L,0x39d84b33fc0e9448L } }, + /* 45 << 210 */ + { { 0x71b55e7ea0415173L,0x5d0b5e01b10f3cd5L,0x0c35a1b63e3f9d84L, + 0x3c68cb5db794ba37L,0xa73356f0dfd6c999L,0xc59ed0650e5e221aL }, + { 0xc59443a90cd7d577L,0xa354296e283015a8L,0x202aee3ba7477107L, + 0x59f361392ee80330L,0xc52bdfaae875a886L,0x8ca39d9d07637e97L } }, + /* 46 << 210 */ + { { 0x95be10b8f3a1611dL,0x6db370f0d1f992c1L,0xb964029de8124b40L, + 0x618b26aadfc90473L,0xac65c9916f6d5553L,0x10d5b0f0a0a6fde8L }, + { 0x4bff23122d164911L,0x876db39d1f7293b1L,0xa2d3cd549de47789L, + 0xd8ca4f6eabc9a28eL,0x0bb3145fca7b5467L,0x4dce66338b37bf62L } }, + /* 47 << 210 */ + { { 0xcdd8ec4dec1b8d36L,0xf76258d888003e0cL,0x35a114e7262723f9L, + 0x12933142abb34bcaL,0xf55b84514c188a3bL,0xa0cfdb2c0ada78b6L }, + { 0xaf0b62f6ed36781cL,0x0c619486ea7e1ca1L,0x11fae38689162fc3L, + 0xe9bd7ae694828e92L,0x081c3acda84cedb9L,0xb34ceca8787a67e0L } }, + /* 48 << 210 */ + { { 0xd1b2af2f2bca651bL,0x2211e4f97404bc78L,0x787b1cc8fc5068f2L, + 0x73d6da299fcbb3f5L,0x6867fb7707d2142fL,0x36f277ae116ad6bdL }, + { 0x81c86073a7534943L,0x67188488c4033c7aL,0x13a8415ccc568123L, + 0xbc01db07f3f475deL,0x90b8af2e3aaeee1aL,0x320c4880175fa55bL } }, + /* 49 << 210 */ + { { 0x263afd7d2fcafc9aL,0x9b0c30ebcc9405d6L,0x713fdd27d6720896L, + 0xb07f8ec5f7df4a02L,0x05d62e5147ddd4e1L,0x6278227b8ae3b80aL }, + { 0x2ef5c81b0d4ab658L,0xe6ad5925016a434bL,0x6c0e30a2b85d8037L, + 0x254830037a9cd869L,0x78da543b2cc48c8aL,0x3a65b54e3edca4dbL } }, + /* 50 << 210 */ + { { 0xaf2a06c3d54b0072L,0x81621ebfaf0310c5L,0x6bd1fe41a8a7a9ecL, + 0x942cf6ba03e74289L,0x2a25f0f59f9822e8L,0x16654b13062edd3eL }, + { 0x2345a0b19de373cdL,0x425a59f80c0744acL,0xc6738fe96f0d620aL, + 0xaa479ef8ed67c1a9L,0x52540af87765b194L,0x17a3bd3bf2b96455L } }, + /* 51 << 210 */ + { { 0x5b1a1f075f01e608L,0x3c696f4e87b821c5L,0x4358a5243129700fL, + 0xfc9816a14be9d001L,0x905de48166744b96L,0x2ca5f8d8eeda3945L }, + { 0xb30eeb1aad207f4eL,0xbd113b2dbc66e6f7L,0x1b6c5c6cebaef81dL, + 0x6b3863998bfaf32bL,0x5f9f2a2432a83dffL,0xe8cc190e26ea39d1L } }, + /* 52 << 210 */ + { { 0x51e05f7d450535fbL,0xa5f5181effbe389fL,0xdf178fffaa2d5514L, + 0x89358810e51da035L,0x206e324f664d399cL,0xc148ae74c4477d4eL }, + { 0xe0c8d4377d6f38d5L,0x327aad6d8c8133e9L,0xa685a889d21cac4dL, + 0x1217c68d0ceb5770L,0xa4a09612d21f1d50L,0xab64b4dd889676afL } }, + /* 53 << 210 */ + { { 0xf263062aee202007L,0x95e90bbda2359019L,0x57740eb39f34e691L, + 0xa5f4fd0f355bef37L,0x484b97fb439f091dL,0x642776fe53ac871dL }, + { 0x5c8f9b1e494e0eddL,0xbc62c971ae25a6d7L,0x01981994a7d90290L, + 0x3cec43524602cdc1L,0x4bd29f5a14403ae2L,0xafaef08b921328d2L } }, + /* 54 << 210 */ + { { 0xd33e754a53ef149dL,0x82243def548034e6L,0x99c29a9b23ea2dcfL, + 0x724e4b5d214848afL,0xe43d4438dcf85b9aL,0xaf7241ea9d7b20dfL }, + { 0x60a10c30069edb1bL,0x1aaddd5e9874f484L,0xfc784ac073085538L, + 0xc998afe54d69703aL,0xb71f6fd7bf52139fL,0x28f994c46a45b089L } }, + /* 55 << 210 */ + { { 0x85084ec2eebd9e0bL,0x73e489c6cb9f1929L,0x91e47fd7ebe10e55L, + 0xeed6a3a1486a2704L,0xf63deae7e124d6e2L,0xca958204b48b3834L }, + { 0xe69cb5bb13185b44L,0x56be0e05868d97d0L,0xc48cb1e50181e64dL, + 0xfaa012ddfc7827cdL,0xf535b1c83488352fL,0xd1cce04e9fbf42d4L } }, + /* 56 << 210 */ + { { 0xa54436b6ba3403ffL,0x1fe4b1ecdcbc4822L,0xb3b351004c6846e2L, + 0x360278048d1cac7cL,0x9eff87327e86d5d1L,0x7f435326ba21993aL }, + { 0xb51a9da5adc24224L,0x111c19fcc8c14a71L,0x05aa2c86ab77e011L, + 0x81edc338ce72744dL,0x20fa8f528d882bc3L,0xc61c3e639d1696f3L } }, + /* 57 << 210 */ + { { 0xa66674ca0f41637cL,0xa01d08ac418487daL,0x2ce4258b6b593194L, + 0xd755220645024db4L,0xffb3366f626732ceL,0x802878f370ba2f1aL }, + { 0x80a3f41659b77372L,0xfbb411631a04b19cL,0x7d575112a346d265L, + 0x6c30421ffff87d4fL,0x1b62b93fdcb05f02L,0x98ba4397b72649e3L } }, + /* 58 << 210 */ + { { 0xcca45c1d135a7eb5L,0x2623e629b048126bL,0xada7326e926980f0L, + 0x64f334c276bf796eL,0xf0751596b4a562a8L,0x0baa14486f9d0079L }, + { 0x6c394aa32205ea70L,0x635b9d2d556172e9L,0xf418fe0cfd37b53bL, + 0xcf5fe2ac56b9791cL,0x9d855e67911c68ddL,0x9e40f75f734b57d8L } }, + /* 59 << 210 */ + { { 0x32c42482b5b8f846L,0xdefec599b61cc3cfL,0x4c3460996506a9b5L, + 0x0d9475a0263a6142L,0x1753cd92c80a6713L,0xc015412f420cf67eL }, + { 0x1c33f01b6a88d12bL,0xa49f038ef522f7d0L,0x232343decd25f260L, + 0x479bc742d6a833c3L,0x2f2ab294cee07b83L,0x02e69a143dec38b3L } }, + /* 60 << 210 */ + { { 0xbf7fea3aee1fee16L,0x31fb342ce0cde85bL,0x9a232ea51575924bL, + 0xc3132e6cbcc4cf26L,0xbc5b7a7102499a58L,0x3064a3b904d99836L }, + { 0x6f17475ff8b3bad1L,0xaeeb90c429271790L,0x7f442a13f8eca53dL, + 0x6d641eea08882274L,0x8dff43bf88ffaebaL,0xaa92827f5840b198L } }, + /* 61 << 210 */ + { { 0xf5ce3fca26d803acL,0x6927ddd9d4e1b6b5L,0xb509b5c609f48bc0L, + 0x2bc5d1749e35975aL,0xfba3024af570c98bL,0xeba15980aa27d6b0L }, + { 0x95abc07290abd2daL,0xd0e30e99232035cfL,0x3dc4e1bcd3f0ecb1L, + 0xa5a8c6e556de9d17L,0x878c7403ab73bd18L,0x5cce39260c474b0aL } }, + /* 62 << 210 */ + { { 0x86a3f001e93b6ee6L,0xa28984474fb3203aL,0xbca0d71e9b3550adL, + 0xc225759d0396d796L,0x208b9a02cbd949d8L,0x15b21ec9a550d2ddL }, + { 0x64aaed6a2a7dcffaL,0xb8cc7575ed5b6b47L,0x2b4a3aff022dbce3L, + 0xe85d690b86f51861L,0xe26a6c3d578f4d5fL,0x706d770a70e7ae76L } }, + /* 63 << 210 */ + { { 0x822467eb579c91a6L,0xe98a471531599272L,0x7baf0e9f1078d497L, + 0xd13f270e25fe439cL,0xae9d58adc0d95395L,0xc3beb60827693037L }, + { 0x4d9c4cf397f797e5L,0x4e26167db26d2e9dL,0x06092d5e86a167efL, + 0x9827a21128dceb29L,0x30423344552a55ccL,0xae07b37f3fa437afL } }, + /* 64 << 210 */ + { { 0x9b23ab4e94d0864fL,0x46356266009c9fc1L,0xdbe99e51e798edf9L, + 0x38547449307675c7L,0x23ffaf55628c0fb6L,0x56ccd2a31698c372L }, + { 0x39f45a578347ce95L,0xe0aaec744f2c6118L,0x2a89079e4af138fcL, + 0xb86371ea2ee4ecc0L,0x076d256a06bbf92fL,0x9073adb8ae3c4c51L } }, + /* 0 << 217 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 217 */ + { { 0xba2e9543743c15d9L,0x7d5812db1c99c984L,0xf94db95145bdc19eL, + 0x951d00ae382e77bdL,0x9940a5fbb220b29aL,0x6908d50e58fc91f1L }, + { 0x682e42eadd0940feL,0x2124e23aa1d32009L,0xbe15810016294d05L, + 0xaea13fe32e326d68L,0xc0dfe1ef15e64fceL,0x32dbc0b5b8237a8aL } }, + /* 2 << 217 */ + { { 0x6ee65a08c36d3f25L,0x7b6c811fe393e4d4L,0xc4a2cc382876e523L, + 0xab7aba26d3bf53aaL,0x5bf00871db7f290cL,0x3cb1cd131ee6d5bdL }, + { 0x4cafb218de998adaL,0xa1ecf36af6319101L,0xa1fe785520b281ccL, + 0xe457198e64d9c65eL,0xa3d1a6d0c5a0e67bL,0x69ddbc3290cc468aL } }, + /* 3 << 217 */ + { { 0xd4ee3f7f6dadc46fL,0xa1f3dc925d7febd6L,0x4c0bee1363ebab5bL, + 0x70e32d77005ec237L,0x302fc73dc52fb006L,0x1af84c0a8f159899L }, + { 0x42a5478f0686232aL,0xb4fc56348a308687L,0x042c4970c8378f0dL, + 0x70c195758e2c86c5L,0x61a95e6884c7c767L,0xd96a8216d6fb43a8L } }, + /* 4 << 217 */ + { { 0x0c62fd2d543c1255L,0x71ea9c6fef361a27L,0x76b0933dcef3f9e3L, + 0x51b1ec2d9889ffa2L,0x9e84b2ba9a3c88d2L,0xc8996b961913e52fL }, + { 0xbafc5e94cee43e36L,0xd9898d2470c658b7L,0x4e9bcc41bed17108L, + 0x0db5b7336c7a41c8L,0xd4be07a7795369cdL,0xb899f92f7bd3a934L } }, + /* 5 << 217 */ + { { 0x1fffcbc010e15fafL,0x8447bdb8910245acL,0x857d521e86476901L, + 0xcd1d5f87369ccfe9L,0x560b3277b3f1dbf1L,0x4ac02a1a47ea4266L }, + { 0x29ac98b6a8a929eeL,0x020ec6db5e5e70c0L,0xb0be38ba21291be6L, + 0xcbe9d362bdba40deL,0xc585450571535a89L,0xc21839de3d7a3235L } }, + /* 6 << 217 */ + { { 0x831541b39805497aL,0x2ceb5ac879c414cbL,0x86601fa616d2eb82L, + 0x373d19079338ce8eL,0x98151a90c1f5c87aL,0x966ebde6048a538cL }, + { 0x5c4a8c5ae180ff7cL,0x6d9065dff996d994L,0x4e0dd86e2460ab91L, + 0xfbe8b3ff309a8f5eL,0x33d7cb35856f7218L,0x62b2200a1ac59f2aL } }, + /* 7 << 217 */ + { { 0xb36ad750a460e53fL,0x727006d60df0f7b0L,0x6ca3ac348ee96a11L, + 0xb04f6ae930e75d1bL,0x9957738a3a24e9eeL,0xc0117a7d16521e18L }, + { 0x79fcea8872ad7e27L,0xcbe2c2d37281e3b5L,0x31915f1cc391fc60L, + 0x1c1c0082a13a92e1L,0x362663cc7ddca7acL,0x8021aad689689d35L } }, + /* 8 << 217 */ + { { 0x3f2eff53de1e4e55L,0x6b749943e4d3ecc4L,0xaf10b18a0dde190dL, + 0xf491b98da26b0409L,0x66080782a2b1d944L,0x59277dc697e8c541L }, + { 0xfdbfc5f6006f18aaL,0x435d165bfadd8be1L,0x8e5d263857645ef4L, + 0x31bcfda6a0258363L,0xf5330ab8d35d2503L,0xb71369f0c7cab285L } }, + /* 9 << 217 */ + { { 0xc19db6f05890e1cbL,0xc21587edfcac8d05L,0xa9e88798d86730edL, + 0xee3e6ee2c27441cfL,0xadb2c63ea23af57fL,0xb524b7da29ff5977L }, + { 0xab1ed847d3e4739dL,0x6592a0131cbfb581L,0x1f519c6ea1798195L, + 0xfe837a814c324a4dL,0x74fec4a85c813abcL,0x7b3b5351dce539b0L } }, + /* 10 << 217 */ + { { 0xb886a0c50c99e321L,0x4063d19576e924e9L,0xc03cca041a659dcbL, + 0x1e01abbc1bd3dab0L,0x9d7cf04fe9141cd8L,0x5f87dfa73ef58d85L }, + { 0xa579e76388d764b8L,0x381dec6a74b9e5b3L,0x354221f99a4c9a67L, + 0x8c2556d33f529346L,0xced3642bb4349eb7L,0x1527cec7fef5c92cL } }, + /* 11 << 217 */ + { { 0xf2e42ef7785ecd51L,0xca3438cf33d9c0d2L,0xeef9ec08c1c097f3L, + 0x9e438fa746682aa7L,0x53d0144531a7eefbL,0x04431241e6998a0bL }, + { 0x2c1bb2bd55bc7febL,0xed99e7afb44d4943L,0x7f37bc4a3c77d21eL, + 0x866c0978398e3997L,0xed7462305bde12b8L,0x24796f7c7194fd1fL } }, + /* 12 << 217 */ + { { 0x7e4450cd5e83d570L,0x0113cab242b394e7L,0xdf4062a08ee24413L, + 0xf8a0fd4931227510L,0x06b798f4b80f0d23L,0x33f17673b72bffa8L }, + { 0x4638602b5de9f490L,0xbe3a65834d905654L,0x446e0afaf406772cL, + 0xef68dfd7b4ec908aL,0xa6be004966ab5ebfL,0x56049360ff376531L } }, + /* 13 << 217 */ + { { 0xb47202b760b6ce82L,0x8129c1befe05e9faL,0xcb70cbdde861de07L, + 0xcf35fbc5af16b6d9L,0x60071beec9916116L,0x3aaa496ed057e63cL }, + { 0x1cb0bb12c356f065L,0x12dccccef4de0d26L,0xe3f59cf67ccc0d48L, + 0xd66f10b3d9569e26L,0x95f4d7e79d1853ccL,0x10313dfdbf651d5aL } }, + /* 14 << 217 */ + { { 0x779b55062a3d9774L,0x3785db08e0554291L,0x9b3a4eb8546c69dcL, + 0xfe36824dd22d8fc8L,0x037d9ac9471132a1L,0xc895e332a01e1c28L }, + { 0xe535ede71b5e2845L,0xdc90cd7c568743deL,0x3292b40b4691d367L, + 0x911fad21b4f16a4bL,0xb3c5f0eb455d018dL,0x2eb2def669033748L } }, + /* 15 << 217 */ + { { 0xfd1297a4307aa8fbL,0x021f242177952146L,0x17cc2d6f0ba72feeL, + 0xa265095d01a3a733L,0x2e12c2e7a07d5f8bL,0x27bb60341202224cL }, + { 0xb58b3fab8185dc12L,0x83467b977700f166L,0x98242e227ff9e1ccL, + 0x96b2a4d9f4b28f1dL,0x64113c3865ed82eaL,0x7dc9ab732ee160e8L } }, + /* 16 << 217 */ + { { 0xf16938f514c5969bL,0xde2e3cf0944b2271L,0x2d5095530b6490d6L, + 0x8432fef1a28a296aL,0x6f254dd08d26415cL,0x3780eeadd50c2865L }, + { 0x4f5bc455665b8794L,0xef31fb9e56cb7018L,0xbab8dd6e65e59340L, + 0x676baca2a56dc2eaL,0x38eea06beaa90e05L,0x26e64224174bada0L } }, + /* 17 << 217 */ + { { 0x309e9fbe109cdb79L,0xc2ed3566977d0e4eL,0x2891f30be6b944aeL, + 0x514bd4cf5022e070L,0xae9a22a98726a661L,0x1114a0c8c1916b06L }, + { 0xe1b4f8339795adecL,0xcc0f3824ed4dbf8cL,0x432c93c878096a66L, + 0xb9450e9da7d2ad83L,0x294b0c192c1e35ebL,0x791427038be5a953L } }, + /* 18 << 217 */ + { { 0x4d215132881faf35L,0x52171a5ceec736a8L,0x4788813e1ba561d5L, + 0x9ca022a7d35e399cL,0xbfcaab926c4b8d7eL,0xde62b2c007c7ec40L }, + { 0x7b46c2d96bb54e10L,0x2ce02e5a7d31e85aL,0xb757b699cd776c12L, + 0x08f122552c81b71bL,0xaca91e058aa6b02aL,0x35cf7bd37209279dL } }, + /* 19 << 217 */ + { { 0x24b5bc7086a04b9aL,0xd4d4c640612e0fbcL,0xb19ea7fcf732589aL, + 0xa18b6f4081fc63cbL,0xddd7211d84d88fe2L,0x7e8db6f72963130cL }, + { 0x8772908c500c491fL,0xa3bf747783fd8a41L,0xca54d0d34e3e9fe9L, + 0x9969471866b030d5L,0xc2f5fb98b1fd6736L,0x58d5a851d103fa45L } }, + /* 20 << 217 */ + { { 0xe4c16fcda97a5decL,0xcc4333092f1dd4b8L,0x8cac9da985d334dcL, + 0xb4deff204cda5a0cL,0x59eea4c9be70b1b9L,0x161e73a2ec5b7b58L }, + { 0x584c5e098b7fb4a6L,0x697fb795a3f7dd08L,0xc9e15f754bd4ba2cL, + 0x66d04f47c83df783L,0x0c03c2452efedf63L,0xa76a08c94a87dbb4L } }, + /* 21 << 217 */ + { { 0xde4e18c2da669a50L,0x0629350a480fb520L,0x84b3e68b7cac0748L, + 0xab718a12da3e1e9eL,0x3f5c5489cc26aed3L,0x81c6b6d42a57ab3bL }, + { 0xc4ded8ce15d23825L,0x2d753e6a20c6eb43L,0xbaa120ec555f3a83L, + 0xc72f9d3877e93abaL,0x4ce297d0373317cfL,0xf42b3e954845bc1fL } }, + /* 22 << 217 */ + { { 0xbf162c19d7480e46L,0xa7f45ea76403bf0fL,0x250e936c6c51cef8L, + 0x97ba086f1cd24b64L,0x271a22364cfb2889L,0x2685c98804dc4b48L }, + { 0x843bb75ac877f6a1L,0xe10cd5c799d5c7bcL,0xbe65eea1db60606aL, + 0x9019a9a7a10d0d74L,0x5614c0b987c62e5eL,0xaab2308d38240d05L } }, + /* 23 << 217 */ + { { 0xc908c6929a772e03L,0x73441df703928ce9L,0x36141b5bcf111c12L, + 0xf6b9e2f16c7c3e5dL,0x1f245a77722c5b57L,0x07e3f364635f65e0L }, + { 0x1aab7abf272597d8L,0x03954428d4fe8e71L,0x7dd58036ecae1b5cL, + 0x9b97c2f28c85b0f0L,0x68ed3dc6ace011e9L,0x8e4ab5ca1744a774L } }, + /* 24 << 217 */ + { { 0xe6a19dcc40acc5a8L,0x1c3a1ff1dbc6dbf8L,0xb4d89b9fc6455613L, + 0x6cb0fe44a7390d0eL,0xade197a459ea135aL,0xda6aa86520680982L }, + { 0x03db9be95a442c1bL,0x221a2d732bfb93f2L,0x44dee8d4753c196cL, + 0x59adcc700b7c6ff5L,0xc6260ec24ca1b142L,0x4c3cb5c646cbd4f2L } }, + /* 25 << 217 */ + { { 0x37daf7fd5a96d915L,0x1bba82e6d16a1332L,0x7558b642ce1135d0L, + 0xc9fcd6ce3abc5915L,0xc3762a20b93ad4d3L,0xef0cdb45e4e74f82L }, + { 0x809b91dcd26fbab6L,0x1264f72ea9b53697L,0x264699ffd7c827f1L, + 0x16d4f094d8c4976fL,0x244c90cd997df2caL,0x58eb3b1c76f77b3cL } }, + /* 26 << 217 */ + { { 0xb99e2dde1ed04268L,0x94247d202497b83fL,0x0c6c21d1fb833507L, + 0xa01e682fafab9c39L,0x4938108f4d84c3d5L,0x70b68c75347652d1L }, + { 0x458e814740e17747L,0xca752a14c3f8bb03L,0xaa537b4d8598d044L, + 0xeec3febb7ff102e0L,0x10ef3cad247fe4baL,0xe4de5b1b5673ac39L } }, + /* 27 << 217 */ + { { 0xbca2931378d0bb1aL,0xfcc237068e5c3fe4L,0x0f9d6b11dd0d67a3L, + 0x9aec22faae14bbd8L,0x75f8d86e5bda7184L,0x6bcad95759aeb4c1L }, + { 0xbb1224a5990a9309L,0x00edc04ef7193f45L,0x870c1647c17cbff7L, + 0x9855513c65031caeL,0xe5a2e2ded852b607L,0x540a4141e5671e25L } }, + /* 28 << 217 */ + { { 0xfb0e2f2e4d5efff4L,0xbf3b96e73a143fd6L,0xa18a037f18579946L, + 0xae02fd4ce48c8a51L,0x1cb139288745c177L,0x4991594a28c47832L }, + { 0xdce3b1d2fd51c1a2L,0x4e707213314cb09dL,0x5312de95ee323449L, + 0x4925c4e789389866L,0x2438fd9e28ca17acL,0x58fd2aad872dc0acL } }, + /* 29 << 217 */ + { { 0x75bcf0ef54ddedaeL,0x3cc75fc6f9077493L,0xc91b78df60f6b874L, + 0x7687a1d0622634c1L,0x57fdef4f82cabf32L,0x544819218e2671e5L }, + { 0x526cbb27a3c37afbL,0xe0db88340d1aec76L,0xa034badb73cdef1cL, + 0x165cdfad6281f26bL,0x5c90d4d1ce24a71aL,0xc404af1125f297a7L } }, + /* 30 << 217 */ + { { 0x6b21a0ea2fd5df44L,0x2da8dc6cb36e5b1dL,0xa683e08ac3688655L, + 0xfc5fbad3454bf878L,0x9d2fb9f12f73b749L,0x4612cf42f920b37dL }, + { 0x23da6b697035794dL,0x2763828adff7c198L,0xd320660522dd7eedL, + 0x6829994cd1316e68L,0xd732bc8f62831ed9L,0x69c6972c9303d789L } }, + /* 31 << 217 */ + { { 0xf5901854b0dcc28aL,0x81c92c1fcd18e579L,0x91a412ebc4b8e1cdL, + 0x35f00725891d6ab8L,0x10d6bad8ad7aa63dL,0x8cda809d09df2b47L }, + { 0xe856cfbfa489c233L,0x7ea921addf1ecf5aL,0x884cc717fd724c37L, + 0xe278f2457377136bL,0x240b142d9f3dc9ecL,0x80a384961139a645L } }, + /* 32 << 217 */ + { { 0xa35e411c2cb40964L,0xdd7d4f4cc331a3d6L,0x7c7c859e89a66f2bL, + 0x9908c37e0def8ecdL,0x8274124e344947b7L,0x0d279f7b568b0ce8L }, + { 0xe5291961866091ecL,0xb056e3bf3a08acc7L,0x60fb39e156bd3a7dL, + 0xe56a34d6268f8562L,0xb3a1fe1613fd8293L,0x6a41e1a967537fcbL } }, + /* 33 << 217 */ + { { 0x95c2bbfe021fc932L,0xc7e3399db2af7e0cL,0x1224bf06122670f7L, + 0xc9e4513ffcc1fe85L,0x8c82371ddb50fa7eL,0x017c5498bb76e4b5L }, + { 0x5467926c7fa89f61L,0xa4a65606f3a1204cL,0x22133acfa64b2e59L, + 0xab7896bce1247662L,0x75d35fb661780c9eL,0x99199644a91b33faL } }, + /* 34 << 217 */ + { { 0xf799c4638471104eL,0x43c122dd8b91c351L,0x9db6498616dc06f7L, + 0xf7e534410ebcf250L,0xa702c0f18373f9bbL,0x6ed8d39a1024e14eL }, + { 0x92913e436cabd9c4L,0xba906ef40dde6283L,0x06835e914a3972d8L, + 0xfbba3c7dfd99c4feL,0xf843e6f1b950909aL,0x7ec9866df5160b4eL } }, + /* 35 << 217 */ + { { 0x68f75bab06722bd4L,0xdeca718813066eeeL,0x4d658fa11152b8c6L, + 0xfae01e657257c9e2L,0x999445f923e4189cL,0x2cbe272cef6f0b1aL }, + { 0x5f60d9d735fff303L,0x4ca7a54696235360L,0xf506201598758f1fL, + 0xba81e7ad1dbaecbfL,0xd326e063c687425dL,0x8c46fa4b193484c5L } }, + /* 36 << 217 */ + { { 0xa97149cf3c1f5f12L,0x17b04a3d143d72b6L,0x174195ff17449a22L, + 0x851803960b136adfL,0x8d87d21f9a7adb22L,0xf9c9fc85a8f46d49L }, + { 0x7839f453a7ed1b7dL,0xe19d80ace9067ba5L,0xc387a6a0e41b8d6eL, + 0xd11611e1241d287aL,0x2561ed02636240beL,0x3bd8c57df0fba033L } }, + /* 37 << 217 */ + { { 0x7b5caacd3ea8ec1cL,0x221770e944624802L,0xafb1a4df5a32468aL, + 0xdec20eb62e295525L,0xe1cd4fb9e309c92dL,0x0331b9c0e7256005L }, + { 0x987d4c55246f2fddL,0xa392d27367f70f8fL,0xccba11994e214e5fL, + 0x789f0e4c9943562cL,0xf502ec237235c86bL,0x67403523987746d6L } }, + /* 38 << 217 */ + { { 0xdd02ced216c97e7cL,0x578d6912dc3347baL,0x760260da2134e993L, + 0xf96643dff34fb26aL,0xec214b767ea3285dL,0x19b135d4117733d1L }, + { 0x29a0e0636b037168L,0xb5df2bb95d1285eaL,0x5a2d3297796f0cc4L, + 0xfcee639f2090e0b9L,0xba11e8a4d93c091dL,0x5b6fc501492250e5L } }, + /* 39 << 217 */ + { { 0x6019d207263929d8L,0x9821d6e81f164aa2L,0x8f1b33f8d4924236L, + 0x389e482fb72de1b1L,0x398785a862554c10L,0xed31cf8408469265L }, + { 0xf9b99e158a09f334L,0x9ddfd4eba83df391L,0x28a5cdf4caa4f7d5L, + 0x32b9e3c68f68fd49L,0xbce64b93b6f52209L,0x72649c6fea7c4bdfL } }, + /* 40 << 217 */ + { { 0x8a15d6fea417111fL,0xfe4a16bd71d93fccL,0x7a7ee38c55bbe732L, + 0xeff146a51ff94a9dL,0xe572d13edd585ab5L,0xd879790e06491a5dL }, + { 0x9c84e1c52a58cb2eL,0xd79d13746c938630L,0xdb12cd9b385f06c7L, + 0x0c93eb977a7759c3L,0xf1f5b0fe683bd706L,0x541e4f7285ec3d50L } }, + /* 41 << 217 */ + { { 0x73bc200cfdd5504eL,0x73322fbf3825b0c3L,0xbf8bf1edd35c24d2L, + 0x54eba9f52e2bc29eL,0x80ffb5fff3aa841bL,0xbc676f62cc188be9L }, + { 0x2e2f79290383f0dcL,0x886c647e0d42059bL,0x673f0ea113eb7019L, + 0x630da63f3f9cd771L,0x2597592b3a0a42b2L,0xfd21fb21b83b8673L } }, + /* 42 << 217 */ + { { 0xd39ebb9fd2b34df5L,0x622bd0c3db873666L,0x546cc7f77b52738fL, + 0x0323cdd1c156c52eL,0x78b00818b5950f19L,0x8065a86a562bec17L }, + { 0x0b42eb1427ca5a49L,0x1791eaf1a457ac04L,0x3a2c93a6b2631402L, + 0x28b9cd6fcacec5dcL,0x6a0a8826d4535a3dL,0xeb08a884a83fcdcbL } }, + /* 43 << 217 */ + { { 0x16bae8925a940b6dL,0xfec394c1789562f0L,0x54349605ea412ea1L, + 0xccd57783cd18e2cbL,0x394bea1a1c813e61L,0xf11c566ff249dd67L }, + { 0x2cd679c112207f37L,0x7780918e83d16012L,0xe8bdbef4646c9987L, + 0x6e1882e5082dbbffL,0x811dd74777abe4acL,0x5bbbb740668380adL } }, + /* 44 << 217 */ + { { 0x0969263a7321c39dL,0xbd13b28bab7aefcaL,0x10e431f205377165L, + 0xbbb2a7d009442c57L,0xf935bc2d9cd156b7L,0x66c3d55e42406686L }, + { 0x4c529b76d20bdc50L,0x112e0f004d1c9f24L,0x414f1c65ed38dbc3L, + 0x63ade49c4eea65caL,0xbefd8af5fab697e8L,0x727bd3b45cc3b209L } }, + /* 45 << 217 */ + { { 0xb89d450a957925f4L,0xcb39b69c6e1e60f3L,0x55396e61ae3fffa3L, + 0xe89d97962986fdceL,0x5521d6b787fcd037L,0x6c20b2b0ec718024L }, + { 0xb1e0964bad6529c9L,0xe1bdaba3bc38493bL,0x6a9cf9d6f19b4690L, + 0xa2d035f7054466dcL,0x37df7fc07fa65c9fL,0x045b0b36106ef822L } }, + /* 46 << 217 */ + { { 0xe4fc833eda5c9577L,0x22afb5addfbbca7cL,0x215de02eb902e8d9L, + 0x215e4c900f1a6cb5L,0xf6d7e4a9d59e146cL,0xcd0c6c6e4912eb8cL }, + { 0xe0616976eae22897L,0xe2279d9f5d809d19L,0x2da1b7b3e282b2e5L, + 0x19327068ebf058b7L,0x9b23df0f5934492eL,0xabeb464fb1752d68L } }, + /* 47 << 217 */ + { { 0x6e754efc00d03f9bL,0x64aed0bd38b94393L,0x9d084ba16df2f6dfL, + 0xfe383a56c6abe8f3L,0xd23c6ca2bc7bac13L,0xde8ef161e326b691L }, + { 0xbb4e853342f96925L,0x1391974f6601dc73L,0x3a545ffb700480cdL, + 0x4d379c538884e214L,0x0fe40f66f713e900L,0xc7f202cbfff783ffL } }, + /* 48 << 217 */ + { { 0x89e48d8bc6bb5e5fL,0x0880ede01ea95a10L,0x60f033d7302c0daaL, + 0x15e4578a048eefe3L,0xfd6dec89b0a72244L,0x1f7cd75e309489cdL }, + { 0x7cdcc2a0e9aba7fdL,0xd18dc5c7f28ba00fL,0xa6300a455812b55fL, + 0x8fa5c4152ca31d8cL,0x36aa3c234f3a5b5aL,0xd128739ec86cf4e0L } }, + /* 49 << 217 */ + { { 0x7ac4712f660598aaL,0xe3f00c28aaba6261L,0xb71ac42e1a9b639bL, + 0x19674c28f69958d0L,0x3983abfec4e5c60fL,0x67f4583a5de58f9fL }, + { 0x83e0bbbaf7278c06L,0xd1883aaa19c5f96bL,0x8ec0f2848b3128afL, + 0xc88e07f49166e04cL,0xa515a9e44e3995c9L,0x0680a306b757ec2bL } }, + /* 50 << 217 */ + { { 0x5673b61e6d6f3aedL,0xcd1275e29524fd2dL,0xa8844f08cde12134L, + 0xeca3eb27b8366e0cL,0x5ce49d498bbe04b4L,0x0b7ab7a02882b056L }, + { 0x12fddcb840fee142L,0x99b7920b2895df5fL,0x35dd8d5a5829bb19L, + 0x271c6a4c46ee8dfbL,0xae09ba7536b594e4L,0x45502d0e1ae12c22L } }, + /* 51 << 217 */ + { { 0xa9e1b19ad95e0110L,0x6a419f8b2383280dL,0x6c35e8e16eb602a6L, + 0x966e0f44d71beeeeL,0xfc5cbdc0c8915585L,0xdce1c36583133b89L }, + { 0x3fbdd24289e6a35cL,0x8cd24d1760ff9dc3L,0xb9708c2729dd493fL, + 0xabbf39803cf807caL,0x62689ffe5410c80aL,0xf133928be8b31d13L } }, + /* 52 << 217 */ + { { 0x3645a1910d4bfc83L,0xa564ac85f2114b63L,0xf0647034cc6d9314L, + 0xb58e96d331d80285L,0x8b8222d9e269c964L,0xdee12adcd204b214L }, + { 0x82d2bfbae1d0a6e6L,0x4fd69d2e9da964eaL,0x1605d9e3200b3ac0L, + 0x5ab2886266d133eeL,0x938411c9f72f5353L,0x9fcdcb3a7d40dee7L } }, + /* 53 << 217 */ + { { 0xd65c1d6c501eb835L,0x37374dd14a0e5861L,0xa13f1070505f1fdeL, + 0xedd76943d1351805L,0x0f9501953673091dL,0x0dec24e308aa62f2L }, + { 0xec4962e7f50efefeL,0x0acccbdc9d227293L,0xc6c95d29d84fd828L, + 0xa4b214c540578ca4L,0x06963d3ba4d41991L,0xeb8c14c2fde0034cL } }, + /* 54 << 217 */ + { { 0x3d46a2317460e00fL,0xedce1c7dacce513cL,0x3d7b6f388cfdce74L, + 0x870082baacfa61deL,0xa86efef862ff847dL,0xc146218368c11d11L }, + { 0xb296eede9d21be2aL,0x9dc54e9e761451cfL,0xed1bb1fd53107f7bL, + 0x41f9efdb676bfbe4L,0xcdf43b904feb9a1eL,0xe81fcb6409d98782L } }, + /* 55 << 217 */ + { { 0x00639fa8642789c3L,0xf8e893a03c101e43L,0xc55439302730e33bL, + 0xe2967d30460970e2L,0xb33f1976ceacc128L,0x9bb0f896235e8c4cL }, + { 0x523f7bbb2fbbbc97L,0x127728a5dab215c1L,0x95dd23ca7ed6ab74L, + 0x69f1219feacf4ba8L,0x5ed12355e875dd6fL,0x7aa732dc95565bdeL } }, + /* 56 << 217 */ + { { 0x9a0e153581833608L,0x5cce871e6e2833acL,0xc17059eafb29777cL, + 0x7e40e5fae354cafdL,0x9cf594054d07c371L,0x64ce36b2a71c3945L }, + { 0x69309e9656caf487L,0x3d719e9f1ae3454bL,0xf2164070e25823b6L, + 0xead851bd0bc27359L,0x3d21bfe8b0925094L,0xa783b1e934a97f4eL } }, + /* 57 << 217 */ + { { 0x0a700190a5e41f7bL,0x2173e68dae9045b6L,0x28e9ac53f1669974L, + 0xcb00ff99d4b9fd98L,0x09c7b907ebe90d1bL,0xbf401f20385744c1L }, + { 0x0bb7ea7ae1292c18L,0x82aa43120b58f171L,0x5aa97bb2e3102d77L, + 0x1a71e7c570178b35L,0x9bbb9ade6ab76f59L,0x32da60c9dea7bcacL } }, + /* 58 << 217 */ + { { 0x3c3f113ab3726680L,0x27be1c406f5b5ab2L,0x5f51f684f6864a39L, + 0xfaf84229a60c4f39L,0xa788612d01df18c9L,0x65c9fd14951d5ea3L }, + { 0x4b2153cdaeeaf44fL,0x6b9e977ba567781fL,0x4dbca3609dbf3e39L, + 0x1ad43ad4fc65d7ddL,0x70a7a5e13d8dcf0cL,0xc11b1f4688b91e4dL } }, + /* 59 << 217 */ + { { 0x1ef5695b0868ad28L,0x09c9c06c2e3a9176L,0x2f2c19672c358e86L, + 0x4ff1af54da22d7e7L,0x5ea6716840fa2270L,0xd164b6874d31a3e9L }, + { 0xec036bb4345103d9L,0x6c6a130f26e17156L,0x2c491063d872b0d6L, + 0xa66be18c4123d04cL,0x8593de34a33fa919L,0x620d2970f025b880L } }, + /* 60 << 217 */ + { { 0xc194cc1664baf040L,0x8038f31fcc01f35cL,0xfcc82fa0ed2079c7L, + 0x1eb7571190d39b9cL,0xf1a89043c108e069L,0x10633334c020880fL }, + { 0x492a494086e262f8L,0xaa0208173383f1a7L,0xfbb4e5ba6d99cc07L, + 0xd6ccdc5cbde40478L,0x9e0b9d5867ee92c7L,0x5204bab7653eb14bL } }, + /* 61 << 217 */ + { { 0x721f44f0ef90c9bcL,0x6ebbecd8d55e653bL,0x9af325df6ccc5d5dL, + 0x265f0f6d827bd1aaL,0xb82453213487ea4bL,0x1642be42af6ba8d0L }, + { 0xb8c4168d4140e5f8L,0xdf5e32c13545d107L,0xf1301b9c2db68318L, + 0xb22e20472bf3c067L,0xf40af49ee56ba514L,0xf4090e795575f363L } }, + /* 62 << 217 */ + { { 0x980de58b1746f6bdL,0xa9e1f0089eb9511cL,0x8f53c6fd1bbdba34L, + 0xe6a867a6a1a41706L,0xd4cc48a5d2e48256L,0xd580559e05cb19d6L }, + { 0xc8983311e6466ae0L,0xeab62080174df01dL,0x710ebd184a0441d1L, + 0x0af69d9a9f653d0eL,0xef3a2510d789c932L,0xb5959cb992fbd39aL } }, + /* 63 << 217 */ + { { 0xdbbdd5fdccb1cc9bL,0x660110b98a26d874L,0xfa80d8b60fb9ff2cL, + 0xfeb5cd6b95040da7L,0xb526ae0c7366cf25L,0xf49d85fce3566146L }, + { 0x3b4107e699f505e5L,0x3c2d618f4302bbaeL,0xdaa09d150b199866L, + 0x3b65cb88c395abf5L,0xd2af1dedbd5ac4eaL,0x0586f5a5276533d1L } }, + /* 64 << 217 */ + { { 0xd927283013575004L,0x01a330d620b2275eL,0x58b9207f450db713L, + 0xae95338423e16d95L,0x4f10c6d4e60e349cL,0x541d03ecfeb122bcL }, + { 0x22548cd22c648211L,0x5c2dc84cd01354f5L,0xa1c6f912b6167b3cL, + 0x6967bab27902d2baL,0xebbe0b0836de34baL,0x6985b33a4b79625eL } }, + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 224 */ + { { 0x9e857f33771560abL,0x4ae1ba22250f109dL,0xf8538d68ff4f6566L, + 0x35380f15ac339148L,0xfef0bfdd5ddfc12fL,0xf706c6bf1387d93eL }, + { 0x618ce77d5357e131L,0xf0921744236478c4L,0x24eaf06e00dc0da5L, + 0x049113be07603cc7L,0x5cf489088f6963c7L,0xbe5eb9e6ede4a300L } }, + /* 2 << 224 */ + { { 0x77e486f85d066c15L,0x0c05b6c24ed5307dL,0x322b28ab7df36628L, + 0x2d14d1316704dcd6L,0xd359977af29a3567L,0xc29bb132ec96d3b6L }, + { 0xfd6e400ae6bfa701L,0x03db99244c7e5101L,0x62d81c7d9b8533afL, + 0xefa638c28de66eb8L,0x7405a9d7e86784eeL,0xafaa74efa6c22223L } }, + /* 3 << 224 */ + { { 0x6909994f0572e536L,0x9d22f9157fed8954L,0x1505ca05884aaca9L, + 0xe4b6530996995a98L,0x30e00a5ed02c000eL,0xb9032350236e7b09L }, + { 0xe696f09e14f6c7bfL,0x2126b6277dc18d06L,0xa9ada7b401e1e2a4L, + 0x9630acb69d2d025aL,0x9fab2c6ed84ffeb1L,0xc1d0db26ab7584f6L } }, + /* 4 << 224 */ + { { 0xf9b2dba4b9d36e91L,0x5fb4f6cefda9b2c4L,0x7692a4f33b8104eeL, + 0x5da885b0e4e1896eL,0xc2a30fec73d2aa36L,0x7d06e6af86f60bcaL }, + { 0xbc8bf16d87287887L,0x6c3dd86a3d701becL,0x8e79e2f37e35610aL, + 0x981139f482f9d71cL,0xf8997ec424e62733L,0x330d989aa3518061L } }, + /* 5 << 224 */ + { { 0x6cf0e6ef9b7e3cc9L,0xb465be6b0320acbdL,0x02777783856111dcL, + 0x3a1d36f0c0e9f2b0L,0xfcf4f6365e7fe507L,0x36bf41827fa7c8f1L }, + { 0x09a02de8b0f4ce56L,0xa0bbf65ca9cdb353L,0x7211a9654b7f4e35L, + 0xa6b2ba79805b58bdL,0x418302c20957860cL,0x3c17ec02f99f9d58L } }, + /* 6 << 224 */ + { { 0x4e6ef410ca89fbadL,0xe0fc53ba53933b78L,0xa4f03403fd41d143L, + 0x3a507177e0774c37L,0x078e8c568ec7484aL,0xfb73c6b6fbb3f66bL }, + { 0x169c94753bfbdff6L,0x44d286060a232243L,0x3e8e968508303114L, + 0x7a9797b8fad0def2L,0x0ad14404efc1c8daL,0x6daae4e921ced721L } }, + /* 7 << 224 */ + { { 0xfde0d1b4cbfd18abL,0xa3c9917595850f83L,0x16d3ad79c9eb9de3L, + 0x2707ec8b0ffbcdacL,0xd7e6750fa220287cL,0xe51baf059c2e155aL }, + { 0x3018c309871e10faL,0x074f08e3f23221c2L,0x1aa323aecf15a4afL, + 0xf085d69cc1b8cca0L,0x47a3eaccb143a969L,0x56a04522f3a98430L } }, + /* 8 << 224 */ + { { 0xc7e9ddef88dd2dc2L,0x2c21a99819a0c0b5L,0x6bc0746db239bb82L, + 0xc811a8eb28ea1341L,0x5f714ca71d1309b0L,0x79eabd20d4eb9b34L }, + { 0xe0e5afdcdf0fb30fL,0x1b01a16d8c0814c6L,0x670e1e7b84334366L, + 0xc8c38f9a0eed1116L,0xf914fae2619bbd50L,0x1ed062cb51c1995aL } }, + /* 9 << 224 */ + { { 0xce64d065b711b4e9L,0x32760c2eefc4d25eL,0x9e5916caa6292c7bL, + 0xa90d40bff2a47deeL,0x90dc6681604933d2L,0x707270c60115cf42L }, + { 0x55b601ff6fe583abL,0xdd2fe842a039dafeL,0x602d8de34c2d3357L, + 0x7cc979bca7ab9014L,0x4b8dcf7e60118797L,0x7f1f2a04cbfaad32L } }, + /* 10 << 224 */ + { { 0xd4e60e15cb583422L,0xc6b1ef90320f296fL,0x0714bad0d9bfc834L, + 0x5ee2ca8c9050e2c2L,0x074a8ca824f7cf1dL,0xb975024910df8516L }, + { 0xecee8ab7c2636d2cL,0x308e5af13b4b7bbdL,0xfed4f27eee2ae021L, + 0x7cd4bb192065253bL,0x6b21a3f84de525b4L,0x0f10e7bdac27fddbL } }, + /* 11 << 224 */ + { { 0xb4f02d9dbb3bf37aL,0x69590395978aacc1L,0xdf99b1309c3def3fL, + 0x5c66391e12be0bceL,0x30ab382cb5eaf100L,0x9b84b2b4e0352249L }, + { 0x0c22e4e1af14e85aL,0xc29d3c592286ea0cL,0x6c7f8b6a40758aebL, + 0x7a91adccde68fd0bL,0x4d8554fec8e8fd4aL,0x9fa863d5bb5621e5L } }, + /* 12 << 224 */ + { { 0xd5068487870e29cbL,0xf9420b85fc52d5cbL,0x50c3265a496d000dL, + 0xe605414a166bd6b4L,0x4de8d724c62b2a6cL,0x16af06f2a1a11048L }, + { 0x5406bde945f43c4cL,0x5e15bf6c751ad18eL,0xa846e665b6a59587L, + 0xcdb28a7d1816ac55L,0x899b3551819b73f8L,0x2d46297bbc848d08L } }, + /* 13 << 224 */ + { { 0x76f5aedd44af60a1L,0xf7bd3b4651d1efd8L,0xdfbf3c6439a9721eL, + 0xf927fbf0ee9d2ab3L,0x628e9258c7e0779dL,0x062cb2fe4cf1dccfL }, + { 0xb2ff57dde2278f00L,0x3f0e140a2d199ca3L,0xe7161304342c0a9cL, + 0xe7ca734f0bdbe131L,0x7d070270870057d8L,0xf6f1a65daaa55860L } }, + /* 14 << 224 */ + { { 0xdc4cc720299127beL,0x5b34e762faab8165L,0x2289b2f7b39c120dL, + 0x687a78d06e52b913L,0xd2a091dd2a3ea6a5L,0xc61eced638eab329L }, + { 0x652231ea7887ff2bL,0x77a568750479db4eL,0x1ef471c8d43c5722L, + 0xf82bf436f3764c34L,0x962af4050445cafeL,0xed8b227f5ff47259L } }, + /* 15 << 224 */ + { { 0x30e045f4a73c3da0L,0x13d2527df36c6346L,0x3dffe56d3836fb9bL, + 0x9518276617c5d2bfL,0xa0ef38724dd0b240L,0xb45e19ebc39c675aL }, + { 0x65202bc603e95445L,0x41e2f0d19a2ec9dcL,0x51c719cf2a0d762bL, + 0x3bfb9729ecc6b9f8L,0xda8271705a261640L,0x65c2bbbcaeee5f3fL } }, + /* 16 << 224 */ + { { 0xde849cd1d89594abL,0x00e2d2b10ec4fb3aL,0x3fbd9e3dabe92fbaL, + 0x785414d43324900aL,0xdaead1abde20904eL,0xb493e121aa5f1ba8L }, + { 0xd60a4f2d6eaea0dcL,0x394746b56fca8596L,0x163dc78934efa243L, + 0x3067dccf216a8d8cL,0x116b6534a901617bL,0x8c4bd099bbabe51eL } }, + /* 17 << 224 */ + { { 0xbb9eb22a97ebad53L,0x791d4f90666f1428L,0xa3a896e06c5d5569L, + 0x322d566fdefbc26cL,0xaa581a083c039c26L,0x82d899be62790f0bL }, + { 0xeff4bb9a43a0c2f7L,0x60515c10a01df2c4L,0xdd1455a849312160L, + 0xc8a15052c4292265L,0xdb2970f97f68d081L,0x29c825b892594c4dL } }, + /* 18 << 224 */ + { { 0xc8c2df45ac3a082cL,0xc353d074c8d4c40eL,0xb214f9c05a3c2de7L, + 0x504bc42cf86b0214L,0xc82df5cbd1922a58L,0x40887948a5bc3267L }, + { 0x04bcd21788ba8bb2L,0xe21b3e7f046fd401L,0x8419c338616af5cfL, + 0x7f24760baedfce9dL,0xded8035bddbd519aL,0x1f1fb0d71693faabL } }, + /* 19 << 224 */ + { { 0x7a88376766117f71L,0x8d4e37815d261599L,0xc900e6dff770b193L, + 0xb7d1c06b12e9dda7L,0xa86d173a717cb0faL,0xa138b7ba51dfbeacL }, + { 0xe84468c57360a27cL,0x4acf8b412e9b82a2L,0x85fa386cb121d6faL, + 0xc794d9f283e6169cL,0x7b4cd3fc8c9293acL,0x3096ad868d082719L } }, + /* 20 << 224 */ + { { 0xbb067b49d02ffcf6L,0x7cedf8f93e657299L,0xc3829961406bbfe3L, + 0xefe4b5aa37c12472L,0x7dc01cf9fec7dee8L,0x70a9db2389472f50L }, + { 0x29c269f8b31bf737L,0xa26deac3ae3fa7dbL,0x0046e91233caca41L, + 0x3bf4bc8ab6e78b55L,0xca83bc6cd9eb5ef1L,0x73f25c62c0c5deffL } }, + /* 21 << 224 */ + { { 0x117bb83d3ff7d803L,0xe91098c539c56c0aL,0x7bf72fe91e347fa0L, + 0xa66201a31e174941L,0x1d069d4d6846a06bL,0x721cdbbdcda59bcfL }, + { 0x17d6683a17652893L,0xee1b28f505be2530L,0x2e70558697a69062L, + 0xd4b5798682b56c36L,0x1ccc5be09082e781L,0x42e0e429d6b05e30L } }, + /* 22 << 224 */ + { { 0x697dc47d44b4aae8L,0xb3525cc0782c331cL,0xff71cca40bd7c78cL, + 0x5f3d776610c0ab69L,0xbdc10267e2ba07e3L,0xc656f75ce6373f6eL }, + { 0x9e2938b4b5607b62L,0xa65017d410b0a0f7L,0x8dad31195cc6ac25L, + 0x00f8f2d18ba5d1e6L,0x608137bc43305aefL,0xddad34bbdcb81cb1L } }, + /* 23 << 224 */ + { { 0x9e46b17c20c78a64L,0x28db365d5c48e678L,0xbe4c3b8eac6ba470L, + 0xee737236b6617b28L,0x81c5b94a4f3422bcL,0x4d44c33076faa922L }, + { 0xd7a09a719be38835L,0x99d024e1410b382dL,0x103b67c36b15012eL, + 0x02b6e094d9808da4L,0x4f5d938a0a7f2fcdL,0xa43058b7e4c5073bL } }, + /* 24 << 224 */ + { { 0xe133d941b1f82ca5L,0x2af8b98bfdf115bfL,0xdc6179c857aaa6f3L, + 0xabaa83e9130ade06L,0x7836b6fb0e8bffd1L,0xc479751ffa103703L }, + { 0x0ff3c1299c89963bL,0xe64072560b84c24fL,0xa92a4ea2f34f6bc9L, + 0xba45b3053197989bL,0xd12b5a0199243aabL,0x3015772c442af625L } }, + /* 25 << 224 */ + { { 0x5362ac737e0a5c36L,0xc731132a8c4fbc07L,0x0ef7468d7ca0d4d0L, + 0xc43afef835d25de0L,0x096bde6a3fa1209bL,0x21f57eb566846236L }, + { 0x878b585cf04d23d7L,0x737f7e527315ed56L,0xb716462c811afdd1L, + 0x4d223734a571a3cbL,0x56460e2fa7db2c60L,0x0684d72c61f97485L } }, + /* 26 << 224 */ + { { 0xd95fca81e6f065c5L,0x45e886d5fc8655deL,0x3580957727cff79eL, + 0x92a39a34625877d9L,0xdda02684dfee17eeL,0x6354f871986f635bL }, + { 0xb3a6e9edd409c182L,0xf0b1c8d9c4fbbb3aL,0x28721c019b77adedL, + 0x3c356df1bf94f028L,0xff221bd229a81f1aL,0x20edf2e856b20b0dL } }, + /* 27 << 224 */ + { { 0xb8c636db31ac60c2L,0xf3830e72bd987402L,0xfe63957c30e6b969L, + 0x3508e67989eb2bc4L,0xc0837f8c9a987e3bL,0xd1d0ce7b3f9b2ef4L }, + { 0x08d8f99441fe62baL,0xe73f79d7e17669d4L,0x8801fabaee6d68feL, + 0x4ef814891a508a88L,0xcc851bb71fbc4512L,0x69f728704680b88aL } }, + /* 28 << 224 */ + { { 0x97fff124835fda9eL,0xa79ceb2f0bc68512L,0x70ba93d1a2fc3995L, + 0x62bd28ab9e51c5eeL,0xb95fa624d5bbbaa9L,0x0654dc458c1f571eL }, + { 0xb9a4edc665a45ed6L,0xbf5ed1bc21ad0612L,0x74adc1a1b1a3551bL, + 0x3dfa3dc8dbbd6cefL,0xce5dd40b2fa3afd2L,0x14894e0f30a746caL } }, + /* 29 << 224 */ + { { 0xe4544006ada9bf7dL,0x9e123b709b75770dL,0x903628d557cea95aL, + 0x6429e00c9e8cef6bL,0xafa2cce77b1adaa2L,0xf2f5771e15e488daL }, + { 0xda44962269820874L,0x5b20ef1b6e0fef81L,0x3150a8699507b4faL, + 0x901897add191de20L,0xf459da31c41dbb2dL,0xc2516dd077146754L } }, + /* 30 << 224 */ + { { 0x7e729c58b8ca2a2cL,0x0f32ea1ecaac04afL,0x47267f13bdd549e3L, + 0x35b9440690be3b50L,0xad0f2bb14b27f670L,0xd7e5874e92341803L }, + { 0x7dc841cf1f9ec462L,0xebeff994512b2a42L,0x22998a7f320dc858L, + 0xf08eb5c719946f59L,0x228c8dcda68ea75eL,0x40dc6dc37b20dee5L } }, + /* 31 << 224 */ + { { 0x23f40e331dd722adL,0x0a441bf4c54fc48fL,0xed6c026548b75f84L, + 0xc2d3972f3e0fff2bL,0x889b44c4db09b7d9L,0xeb6ccc6541a6a562L }, + { 0x5ef1162e8f04e03aL,0x25e2ea895d8102c5L,0x37b71631154644d5L, + 0xa9a1a8320446b1bbL,0xe3f58daefb342b20L,0xc6d19decb6d292c3L } }, + /* 32 << 224 */ + { { 0x929454f6b3952db4L,0x412142ec4d3f69f5L,0xf5b0a7c5ee25c0b0L, + 0x7d3372ff2e752295L,0xd6dadc7d6eacac68L,0x5f0076cca96a8e3cL }, + { 0xea831db671725b3aL,0x4a286c89c29ab454L,0x5ff817e572e3c00cL, + 0xb022e25d2a5fb6baL,0xb611c5bcbb392476L,0x062c14dc190485a0L } }, + /* 33 << 224 */ + { { 0x44730047ffdc9a7eL,0x44949bdcf078d5bbL,0x8c1a3e4bc486e2b1L, + 0x53088ba20801402cL,0x6e20a7cfeac83daeL,0x4407ea8436ec5443L }, + { 0x564fb733853f79d8L,0x59ea819afe809670L,0x1ac62174f1ec7e91L, + 0x0d7e065566a0b8c9L,0x0c4d072482958221L,0x80db0297a60f984eL } }, + /* 34 << 224 */ + { { 0x380823e7f3359d47L,0x8a60fb05f5efd39cL,0x78a940669425487dL, + 0x1da6abc3f199c67cL,0x7df00b2165f0a6b1L,0xdc0dea58017b1231L }, + { 0x9c529db079f4f22fL,0xc7043be3e5dd92b5L,0x10153ffb43661331L, + 0x51c459bf6ff02e8fL,0x451483bfa43aa005L,0x3313f903199cd1baL } }, + /* 35 << 224 */ + { { 0x2f66587e62e1ef1bL,0x942d4c739e3ae33fL,0x4a27ead5c0ab9c1eL, + 0x368d8dd89ca91b06L,0xb3f0cf92c4b6ed34L,0x28cc332673e62557L }, + { 0x2649e5527910986bL,0x635dcf9cdda049abL,0xbbde12f625d3f201L, + 0x5200c3d0a9384443L,0xd996573d51eb3c10L,0xb093c1792b8cd7e5L } }, + /* 36 << 224 */ + { { 0x15cd1d1cc3fe6fa4L,0xf260a739e2c3c686L,0xf7c2270eb08c65dbL, + 0x9ada2cb6ff69d971L,0x65fbbcac212bff0cL,0x40157d075646a735L }, + { 0x101d2b7d55de9e45L,0x0db580e83118b763L,0x3203baca8322a9cdL, + 0x2a3137ef22cac14dL,0xcc9092e291a14128L,0xbb269f6d98cc368fL } }, + /* 37 << 224 */ + { { 0x7c8946002ad7f66fL,0x6a8328bb99b438a7L,0x86d06fbbdb440d86L, + 0xb74ffe2d20ac5a42L,0xc3a6f01d91b1c82bL,0x606f8ce71d5efbddL }, + { 0x8c49c43a6338c99fL,0x50657f7216da7cb7L,0x7f204c8b84f22d9bL, + 0xa2612d80ca76978dL,0x80080d868a3e8e96L,0xd8841a1ac0bff9afL } }, + /* 38 << 224 */ + { { 0xc2a734cb962fa060L,0x2baa26c580a17874L,0xe27b21110b44efe6L, + 0xdc1244e531d2154cL,0xfcd86d4116c7742bL,0xf45230df32503138L }, + { 0x94a790f4812cf0afL,0x0ab2df23da3f24d7L,0x0c764df181571d54L, + 0x989ff71c68d68f74L,0x9896fe62cda535b3L,0xfe0502e05f4fa41bL } }, + /* 39 << 224 */ + { { 0xf1ffe852c2f58cf6L,0x2ec46d2546d64576L,0x95bfec93d602c51aL, + 0x349c58bf3907b766L,0x59cb12bb9b94bdfbL,0xfa95da9515dfcd87L }, + { 0x731a8535e1543bfbL,0x14844aeeca14187cL,0x0d73e58aba1f4928L, + 0xbb71009fc6bb67f2L,0x5e7c0e988b4142b9L,0x4866b5095f08f58bL } }, + /* 40 << 224 */ + { { 0xc8295c2fa234de87L,0x1cd7f3fd878e77dbL,0x309c1fefa2155b6cL, + 0x2a9bcfd9484afddeL,0x87ef7a56cc999775L,0x34336cb1970aa188L }, + { 0xd45eb83cc3e16ba1L,0xf9d72c72b9c1695bL,0xff117458cb980742L, + 0x438a7fcb67af836aL,0x5ffad086eb9a6c40L,0xdbd3e518513922a3L } }, + /* 41 << 224 */ + { { 0xde241983e42021b7L,0xaa70e834542873c1L,0x99c9d35f9daf2b99L, + 0x0bf712d549b40780L,0x202d9969d9ab6e97L,0x7f3382dac4932106L }, + { 0x1eb5f5d40849e319L,0xc1bdd1179f659546L,0x628ddd3d2329f977L, + 0x5944611d363ee601L,0x7b7a631463d5bd4dL,0xaf6c51a5631d21ecL } }, + /* 42 << 224 */ + { { 0x2d8f9e1db4100182L,0xa08ae2fe4f3d2c03L,0x7548c430589e99f8L, + 0x0f5ccee2aede8af9L,0xa21ace3343b34b25L,0xb120c569dee102e6L }, + { 0x1cb103ed36f13699L,0xf71ff0dfc91e8cb4L,0x88f141079b22460dL, + 0x050af75af509366aL,0xeec8a310fb179bc6L,0x069e7331c26efef6L } }, + /* 43 << 224 */ + { { 0x3e2a9c713be9cdabL,0x8f235d6f73ac08e6L,0x3de28a6b28832dabL, + 0x7d08b9f31ee82d6dL,0x67c3b88f915ddda9L,0xba8f18cc0f7c81a3L }, + { 0x38cebc31ca3c0936L,0x745f71aa7816a6e3L,0x00cb85a91a95fcd3L, + 0xb92742c6577dc22cL,0x1afdaab592029cbeL,0x0bb43c91278d3f7cL } }, + /* 44 << 224 */ + { { 0x3d77059d3ba02d27L,0x58e28671440b2d3dL,0xe2d4235726636fbcL, + 0xcc448a52c54605d5L,0x73c2902efc0269a6L,0x28a15ed57ea8c26bL }, + { 0xf666587a0cfc1a34L,0x8374f2cc1ae0377cL,0x5dca6ae828417437L, + 0x15a6d54c94bc87ffL,0x5bf187bbb344796cL,0xc629c14889574b2dL } }, + /* 45 << 224 */ + { { 0x06d43c6d87748b63L,0x2489a957a7f232edL,0x7aa9174afa407c3fL, + 0x8c8b8fd933a762e0L,0xe2e8f1e7adbe94a3L,0xd1e0c8c2bb723045L }, + { 0xcafd8f483df092d8L,0xbc89caebb174025cL,0x97595c5649f20c98L, + 0x6e520a968a77acefL,0xc3dbd3107a52a4e6L,0xf51db5a91284ff27L } }, + /* 46 << 224 */ + { { 0x406465742c74cb2cL,0x44eeb9e546c33df0L,0xd2a9f16ecb4c50b2L, + 0x68f912a01906a6ccL,0x2b81296d95211e94L,0xddb2988ec8575839L }, + { 0xb74d990d33b180c0L,0x290185567d319c48L,0xd3d2e40dac8de56fL, + 0x9ad42a60461f30e6L,0x265e4715292a0faaL,0x56c2626c8ac3b2a5L } }, + /* 47 << 224 */ + { { 0xb7580f2fd468adb8L,0x8e1fbf0388a6a587L,0x1b8c40ed8f4f6cddL, + 0x337414f56817b2b1L,0xd877ebafb744d563L,0x59eed3c6df5e18b2L }, + { 0x365e148dd33afa01L,0x82e70adc665702cdL,0xccd77955a5e390ebL, + 0xd86c343accc90cb2L,0x23bd948d6cd8a33bL,0xb1fc140cdc43a8cbL } }, + /* 48 << 224 */ + { { 0xefda99d9ce11b02eL,0x9017bd4a3f820083L,0x8b9e6cd1ad14ac6fL, + 0x1239ee331f413880L,0xd98e93d993dd7fb9L,0xc280d252894fcb12L }, + { 0x33a9201a5230b5eeL,0xc6aeee256e41de26L,0x845051280d0a320aL, + 0xc20551db4b607b53L,0x6e63c766ea228c2eL,0x883321aeac48f25cL } }, + /* 49 << 224 */ + { { 0xa5173910e15a530aL,0xaa2c88b83ac38ab2L,0xcbfbd31ec6a6ba9eL, + 0x0fa126cb49ed182dL,0xd6b38897cfc53c85L,0x98d5f6bacb9c2f41L }, + { 0x6694e8e5cbd150e9L,0xd470ef226a1fc551L,0x57a63765d5ea1c0aL, + 0x95f5eb4318078139L,0xbeaba00585d3e0dbL,0x6bbf010fd314dec7L } }, + /* 50 << 224 */ + { { 0x5941229729ee46d3L,0x39e5aaa0e66bdfabL,0x9ff1575001c815e1L, + 0x709706211f2de195L,0xaac904a968aa571aL,0x9cbefacd8f7625f9L }, + { 0xadfd215dfce3a501L,0xc04d09ddf20651b4L,0x688c1421d17b25f2L, + 0x3efde5d40073247cL,0x999b7f3a7432c699L,0x33c76487703fea50L } }, + /* 51 << 224 */ + { { 0xc720aeb10af6e1faL,0x1564b8d8e8771dc6L,0x5983eb44673d8ef2L, + 0x5dabb2070679ac65L,0x51a854cdbcdb681eL,0xe2b186a9364a3cb1L }, + { 0xfa189eff7222208bL,0xf7161d86477666f9L,0x0ffcc3e6192d1df5L, + 0x1523508e39cf5a4cL,0xf5e98687c43ecce8L,0xbf17b63261450309L } }, + /* 52 << 224 */ + { { 0x63293cb8adfbde28L,0x5df78fb3c6b18ec4L,0xad10da4ffd27e50dL, + 0x60202b357ade5c9aL,0x67b9d253c6c8c8b5L,0xdbacffefbc2b30bdL }, + { 0x508ff8a67494b1edL,0x87ef48be3769728fL,0x74d4f180ef98d036L, + 0xc5d9ef531799e8a9L,0x726d22206e850162L,0xd86d3414239f6b38L } }, + /* 53 << 224 */ + { { 0xfdde327b3e1f1b96L,0xb6272e94bb58615dL,0x2881350cfc2d8a47L, + 0xfcbe87031142ab9bL,0xaa5fccd0f48c7f97L,0x606be6ed29a74ba0L }, + { 0x545409ba3afc598bL,0x4779f54aa7d23f5dL,0x2811c0829d68e38eL, + 0x5b4646bd3f9c5842L,0xbcd3aa492586219aL,0x7345799313642e3fL } }, + /* 54 << 224 */ + { { 0x9a61f240ab638788L,0x519742162b0a8449L,0x9a5ec31d43b2abfbL, + 0x6f3075740563c9c9L,0xe465f7793ffa198fL,0x8876c5772957418eL }, + { 0x10e3d09c976e5875L,0xd66d334e592c2409L,0x3f0d5727b39b7897L, + 0x17ca7ad1e37fd300L,0x221d8436da530871L,0x4df38e4179d6b350L } }, + /* 55 << 224 */ + { { 0xe805096338b7a2cdL,0x9874cc734b8f05cdL,0xfc0821791b74a790L, + 0xe18a92f3293049a6L,0xabd525694dfdc13aL,0xb928cc300d843466L }, + { 0x12750aec348dc7c0L,0x3c8e205d87f12dbcL,0xa2c71091e0bdbd81L, + 0x895b56a0c1c1871cL,0x68dd7414b4c850f9L,0x45a948ecbe806596L } }, + /* 56 << 224 */ + { { 0xa88dbfe0f4fe35f4L,0x32de3a1c84283011L,0x8a3777bc39caea33L, + 0x673630dee4d49959L,0xf3ef842c59070317L,0x33e4bb031fab88a9L }, + { 0x88e4538e98ce8bc2L,0x870c2eb81a235c6bL,0x71f62c5640df0e92L, + 0xdb43b853f9627486L,0xfde9fcaa95cc473bL,0xe4c5b4bb4b677b11L } }, + /* 57 << 224 */ + { { 0xa6ebd946dd4091f8L,0xf0e11886dcf0741bL,0xd6267674d9533601L, + 0x571926506f74e49cL,0x18269c2f891d6717L,0x350a7869b45ddb53L }, + { 0x79ea6a4ac8f62777L,0xbad33c4cae7edec9L,0x14bed149ad7e5578L, + 0xb2f4190ba91af4fcL,0xbbd6f68be71dfd3bL,0x23fd3dc8f2fb7a21L } }, + /* 58 << 224 */ + { { 0x5e0f89e598fd044dL,0xb77180d97cc30e97L,0x64fbfb747f82a12dL, + 0xbeebb9ca77629636L,0xe164549feba83845L,0xe65a964a7079519dL }, + { 0x8b1bcc08ca88157cL,0x466399c3f7483338L,0x6e2726414b9efdc6L, + 0xff8c7027be922e96L,0x9baebf7d48374f59L,0x2a84a23ac18ee18bL } }, + /* 59 << 224 */ + { { 0x337484e0dca4b3b3L,0x82137cb9f5b27d3fL,0x12ae1d11bbf4c806L, + 0xa1e2873f2880c078L,0x9e6bd909058b9a0fL,0xacc5656d2dba5fb9L }, + { 0x7fe5467853fd2ce3L,0x2aa4af35452439efL,0x329989a5904ffc67L, + 0x007ea4c8520fd31bL,0x58988e2551816b44L,0x644f2469d8f186eaL } }, + /* 60 << 224 */ + { { 0xcd4d1a9e8890722fL,0xfa0b826b74142916L,0xa494dfa817ba8041L, + 0x3fb73e736de2b6c2L,0x156a6cf4344b57a7L,0xb197c8621e205448L }, + { 0xf453e348c214acf7L,0x665d7083e9061a73L,0x5ed59ec5ce9868a3L, + 0x9bab305f6ad777faL,0x752c490b35315de8L,0xabcfa35b5d5aaf26L } }, + /* 61 << 224 */ + { { 0x4059fc2f914d618dL,0x88e55ce6108380fdL,0x0c22b21bee61a4c1L, + 0x435ecbdb04788627L,0x3f8a5ec7a9f72788L,0xa31eff8a732d5d97L }, + { 0x119b6bf9d48d0af9L,0xde6d1de5af70a043L,0xac075ffd3368db4aL, + 0x23a33ec94a58603dL,0xd43ad120fe181a89L,0x386b90ed42f0b006L } }, + /* 62 << 224 */ + { { 0x8096824bf9bf1a24L,0xcdf69abc8260ebd7L,0xaf93b34de9ab190bL, + 0x676351ff841cbba0L,0x3db704d3eb6d6c60L,0x3b1b893fc09aebfdL }, + { 0xc06b9bfdbfc69f15L,0x28b1ffb8e9c688c6L,0x1607bc68d3c16455L, + 0x07d56bcc6d16d937L,0xac28e69f318afd9aL,0x7f4afeb7e77263b6L } }, + /* 63 << 224 */ + { { 0x796a530ab935875aL,0xd6700ec89dd1e51cL,0xc30301df4d9320e4L, + 0xe23090f357157f87L,0xdd3f68a74029113eL,0x566afc6de2709936L }, + { 0x830f952edbff8926L,0xe207eae5c7a39d27L,0x9210b3dfd9494592L, + 0x3be25582d8460831L,0xec2496575d58edd9L,0xebe8426fefd24738L } }, + /* 64 << 224 */ + { { 0x0372678dc419b0aaL,0xf95031d8c13fdf17L,0xebaebca4b79594c3L, + 0xe587850baf3b75cfL,0x534183ac2c1e09c6L,0x3f5b0bfdc08204cdL }, + { 0xdac2cf06e297cc77L,0x5e47d9c6d0487084L,0xf6f509f490b0f6c2L, + 0x3ffc3cd6c2c62207L,0xbb21eb1132ff1887L,0x2116a023e62ccc6fL } }, + /* 0 << 231 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 231 */ + { { 0x406a7e2116960728L,0xd03923f85597d8c4L,0xd4402eff020748eeL, + 0x7827442af39b58dbL,0x77e3f2768d8cfb04L,0xf6eb49c8e45a978fL }, + { 0x9db0829949247f6aL,0xce71a74706669fe5L,0xe434ce47b82775f5L, + 0xe84995ef63910016L,0xa35e8b971e47792fL,0xc779cb3d7c6aaeb9L } }, + /* 2 << 231 */ + { { 0x1fa064cfaf31ea1dL,0x2a9547a848e8d974L,0xda8102a1fa9d9453L, + 0x786aecabdc6bd7eaL,0xcaf91e3bca2f6044L,0x67d86ea78573f208L }, + { 0xd309fce9c505ae24L,0x67ddc5b17f86eb8eL,0x57791ae0f3d53056L, + 0x26b053f00d1fd61eL,0x91c962c0045ebfa6L,0xe95246de076ed979L } }, + /* 3 << 231 */ + { { 0x156eaf570746d174L,0xa2d4a83dcda35250L,0x60a9f48c0290fa02L, + 0x9855d26d5c33b4acL,0x06e379c697eb1c30L,0x4f2e2dbe6e219664L }, + { 0x6b7448f829006065L,0x237a1f31115062a9L,0x5c635a90ad92cb24L, + 0x2e857f8c2eed977eL,0x3d512df7856dc88aL,0xbde85263e597a27bL } }, + /* 4 << 231 */ + { { 0x49f24994e7c03ce4L,0x274a8c132aed9ba3L,0x897b9103d5e91bc0L, + 0x63db1efbcb404f68L,0x70efd9d842f7fc02L,0xd6e02921c6a230afL }, + { 0x8d5b199f11ae0a56L,0xc98287dece33da6aL,0xde583d34504dd889L, + 0x03756001f823686fL,0xf19ab86f95fc73dcL,0x300406c693f12f42L } }, + /* 5 << 231 */ + { { 0x2f73595f7759701cL,0x8dc2069a6fe0e0d9L,0xb7de7114c286a65dL, + 0xfecc429e84c0e487L,0x51061a2c14344c07L,0x4d70972596869e37L }, + { 0x8b02781f2be9403bL,0x6cb6aa02de3ab5d9L,0xb013508eff6bdc9aL, + 0x568d2e84e5438c58L,0x7b35a979e4206c3bL,0x0bb793c0b17a8bc7L } }, + /* 6 << 231 */ + { { 0x3f896ca9fa4dd561L,0x4b9a98abd2de2ecbL,0xd0741632600e4e2aL, + 0x87c7db5f69e702d5L,0x1f5a3b8053e0df2bL,0xe1e24b49f443dfbaL }, + { 0xeb90e2305eef3a1dL,0x8f3fc8a6d38f73fcL,0xfb1e8299a5aa335aL, + 0xd78504cd4197b32aL,0x0e7a79cc6755918eL,0xc7c98ae2883b1c72L } }, + /* 7 << 231 */ + { { 0x1a12727c03d2beccL,0x810a37dfc6741372L,0x44ac483fb7049f39L, + 0xab73e5e7a36fc614L,0x298d453feeff8aebL,0x2127dd167e1b586bL }, + { 0xeadc5c54e07bd60cL,0x67cdae00f5e2d2e2L,0x03fe0446c9d2f10aL, + 0x0784098795e38ed2L,0x5d348a7ce1a6306eL,0x4903f1b6562f5463L } }, + /* 8 << 231 */ + { { 0xbf66baa5b44b1d0cL,0xbbed18eda44f8edaL,0x80bc32abeaaa466cL, + 0x605b7897e5f2733bL,0xe9e7e3a1a2531afaL,0x25d66db33deb8369L }, + { 0x36212ea3b2f25d10L,0x52d6b3f4a08d303eL,0xefa54b31444e9e9fL, + 0x9c2229a169530c1bL,0x68feb9854b79bdd1L,0xd570e84f8b984cc3L } }, + /* 9 << 231 */ + { { 0xe141b86bde0560a3L,0x858bf4cdb2264bd1L,0x526fb104fabe5359L, + 0x95f9c43f185b8a70L,0xf8e3a3eb2d1f75e9L,0x71826067d93bc6b9L }, + { 0xf360e01799692f49L,0x00f4fd16c2dc3dd5L,0xeb7f40498b9454d3L, + 0x5cb0f3c426c3b393L,0xe8ab4e4357bdc4d7L,0x9abe36b00c123d67L } }, + /* 10 << 231 */ + { { 0x1df8d98c57b168fdL,0x042fd731b45da94eL,0xa54d64f91703e143L, + 0xa12198be9de0ab4cL,0x160e06241ddc4e0fL,0x15cae64a6695891fL }, + { 0x808565e70c2b2081L,0x6de4a393cc65040cL,0x6682cd934bac1768L, + 0x62e7ac2ca5be965fL,0xd33f6f8ad7a38e90L,0x9cafc4635b8b516eL } }, + /* 11 << 231 */ + { { 0x0541a391b685c547L,0xe86d35e091765999L,0x65aa03c51db4a2ecL, + 0xba53470e6b1c4784L,0x4f848cc8cceca1faL,0x89d0db0b8b18e350L }, + { 0xd03e452a7840d734L,0x6cebfa790ca24215L,0x288b4569e8f1d9e8L, + 0x18e405af8927ce0cL,0x5aad57e51abfb4c8L,0xbbd99091a197ed1eL } }, + /* 12 << 231 */ + { { 0xf041e421aa44f3e2L,0x47ed9e8eae6fd2b7L,0x4fea93751128ed62L, + 0x041a1c1acec6eae6L,0x1f32359415a65daeL,0x741fea0a0154e8e8L }, + { 0x309e9f289c32e224L,0x457d4ffa902ce57bL,0x7bb54dd5692420c2L, + 0x193a41aec4fa1a6aL,0x35f5f3b43d779e77L,0x31e84371046ebb8cL } }, + /* 13 << 231 */ + { { 0xe75a7c1d9d7e5551L,0xb73c987611635e3bL,0x3b07a071e09d29b3L, + 0x0a3cc0acc623023cL,0x15ec4a7a1e2ceb33L,0x09a01968c70eb27fL }, + { 0x2e5bb53c369d145aL,0x4c93330d9b7fb506L,0xbb10a2f358013308L, + 0x3d9da0c4e0b85fd4L,0x8b39c992ce0dc79bL,0x7e6d18b0bec905faL } }, + /* 14 << 231 */ + { { 0x3a5a366ea1554376L,0x0e1687c052a6ed9dL,0x3e16e4aafe5355beL, + 0x6d8bac03ced67666L,0x403eb33ed9344003L,0xd7b9ec0d333ab20cL }, + { 0x9fce1986d64c272cL,0x9d52d64bb1e23843L,0x8e689611921a58e5L, + 0x8f5f115620d5c61aL,0xb17f612fadc81b4eL,0x36e2db30e562f779L } }, + /* 15 << 231 */ + { { 0x98d0bcead01f8634L,0x6e9ba675bc5f825eL,0xfac2d3aa05e938c1L, + 0x434b712fb9c66adfL,0x81c29163a9a61d36L,0x80eade933be8eea9L }, + { 0x10fc6d75c04c45a8L,0xa2c9aa58fb9e8702L,0x9142afaeb200428bL, + 0x4fa28c8520eccf38L,0x3b5f63308209b3e7L,0xf74206ca8cd74accL } }, + /* 16 << 231 */ + { { 0xd6a4d25c845f26e4L,0x71e554ce1b039dffL,0x942059731cdedfc0L, + 0x0c4e385603d6502fL,0x981a4fc5e15ce8c8L,0x85d1b0f17aca30b7L }, + { 0xf2037ef777bb9e43L,0xc52804f4e87ae187L,0x9c98a23c71f3e4e3L, + 0xa73c8b89f47b504bL,0xb9e33f54023233aaL,0xf2bcfc17f92c9f68L } }, + /* 17 << 231 */ + { { 0xb3c1bc26707fc6ebL,0x0bb585b75ef6dac6L,0x70af297f5f707063L, + 0x3d86a8fa967a0ad8L,0x510dae4d4f956cc6L,0x1dbcb2e883c01ad0L }, + { 0x0e480cd28bfbb5edL,0x76498f813025fca2L,0xc015064ec5446cadL, + 0x4ddfe2af3616f51aL,0x76b0d690e6750b31L,0xc4502c050073f263L } }, + /* 18 << 231 */ + { { 0x9120912bb3081e59L,0x6c73c4a2f908b364L,0x408af8c94de763d6L, + 0x3d9e83084000add2L,0x65d197fddcb5a5a2L,0xbfd29f0b2bd82bb0L }, + { 0xa1243e63bdfe09e7L,0x91d90b54d556188cL,0x977dd4a18bc872fcL, + 0xa8e6e7bef4ea7805L,0x12c53bd80a467365L,0x9d7abca493b7f0a4L } }, + /* 19 << 231 */ + { { 0x5faf453a40eeb93eL,0x6801e0d1f1fe9307L,0xe92505d39ea9b800L, + 0x7e911f8108eb58c8L,0x5da7ffcc098143eeL,0xe023262056876057L }, + { 0x5354045bbfa99a91L,0xee660bbebb346841L,0x1dbf5c7cecb3099fL, + 0xe79c78d6a125d753L,0x2a356f10706fc013L,0xe50c50b725f88ebdL } }, + /* 20 << 231 */ + { { 0x663ca92723ca903aL,0x8a64a4dec7681937L,0xe3ec0966a2baa42fL, + 0x688328d7a2906226L,0xc2821e9c94790fd8L,0x7a295b62157501cdL }, + { 0x032cd57d3675c2f3L,0x91d66a57f42e6f95L,0xd75056961e97dcd0L, + 0x7e8ba3ed7d8b6f52L,0x8ddb72c420b0dccaL,0xe09e53bb6aea2d55L } }, + /* 21 << 231 */ + { { 0x3815b1028a009f19L,0x4f76d609f5418c34L,0x7a35cb332a9eabd9L, + 0x018d6c54ce89e886L,0xe00b99e859c9fab6L,0x4f10a0d9aaf6e7b8L }, + { 0xee51f8f0e722fce1L,0x03e8b63179bccac0L,0x66e540c26f327d2fL, + 0x31df4a35d22377e4L,0xba5b0029d5c71cedL,0x6a3e20553ed6aeeaL } }, + /* 22 << 231 */ + { { 0xe932d1aaaffc47ebL,0x75c9d4d8513f85a3L,0x50886fcdf9419cb0L, + 0x756a7d7d49081e9eL,0xe45fff1fe14aff77L,0x022b4ac339846230L }, + { 0xefc3e8dbe89adc78L,0x921bb1538c09ccecL,0xe4dc6aa17826d461L, + 0xa53aa6cefac8f0f4L,0x5d4e4d53954192c5L,0xda721828c722780fL } }, + /* 23 << 231 */ + { { 0x978609c67e4933daL,0x49fd5c5d2539c807L,0x072a911c6330373fL, + 0x40cfa61838177579L,0xf9a7aa4c81c51596L,0x7ba8e7a5b346724dL }, + { 0x79298c06d26ee66dL,0x243323702a9c2792L,0x585e8b9eb6aab53eL, + 0xa39596c6e14bee4eL,0x89b2758828a76dbfL,0x889fba0aa00dc1adL } }, + /* 24 << 231 */ + { { 0xd55a3eaf0a9a8ba4L,0x13b1406b2a8cd215L,0xcb44589a93943e1aL, + 0x91b5e3493a671a47L,0x488654f8efbe0256L,0x448bee4b392ba5e8L }, + { 0x228f478137e762caL,0xe21a2ca7e71b6c47L,0x0e809fe94900fcefL, + 0xb05e1db2815f6c76L,0x8cdf28815fa6fa0cL,0x2ed55c1c586fec8fL } }, + /* 25 << 231 */ + { { 0x7c3842eba210d4d9L,0xd656154e5f69a69bL,0x9e11c6db1f3a0483L, + 0xb0314a5e5a217444L,0xe17a274e34f4e54fL,0x6e41c20a9f79d6abL }, + { 0xd010d789dffef6dfL,0x704937f17e8915f0L,0x5072bf063d3460fbL, + 0xa30814ed5f08429dL,0xe5faf476207d2708L,0x46e56e14af448339L } }, + /* 26 << 231 */ + { { 0x5a049c8f94af3a35L,0x9ae89160d8b75bbcL,0x8b026d867ff40c5eL, + 0x90e54aa4fbddfd06L,0xc85349e7ee418640L,0xbf71e454beb7801bL }, + { 0x63f5e068ad912e83L,0x6252a4a4ada5341bL,0x25114b87b44529abL, + 0x9b80bea9eadb4f13L,0x7f071c0cfe050052L,0x4c9cd33418612061L } }, + /* 27 << 231 */ + { { 0xc6f50ed03c768ff6L,0x5b994b58b6de126aL,0x807ad19e2a1ac05aL, + 0x012fcb9ddfc66ad7L,0xf8706d5fefeb7d07L,0x132aa6697bfc5337L }, + { 0x56bd874310e28d18L,0x33bc53d96e9f8e26L,0x5885b63b152758edL, + 0xb8b1bd5e757e1471L,0xdbc689458c0d406cL,0xa664de3bfc605a11L } }, + /* 28 << 231 */ + { { 0x04df415ea6d4b6c2L,0xb8e33e71d254d2d4L,0x179df4f48b84c588L, + 0x8a2a0683d435793aL,0x6147a5a911eecec0L,0x0b8389793a0196ccL }, + { 0x855059ce81805693L,0x37babf9f3b27872fL,0xa2ac78b1769be5c3L, + 0x16260f0c0a8d267bL,0x31f48c42388266c1L,0x58fee495ead1f238L } }, + /* 29 << 231 */ + { { 0x5753ee0fc048300dL,0x307dfd57e048abc4L,0xc18bdfeca3ba6c56L, + 0xfb2d8daf10495489L,0xd93aebd4e0fd2d13L,0x4736efaf0518a5faL }, + { 0xa8ee4995eaa9fc77L,0x2620f08e008adc03L,0xf03981839f06991aL, + 0xd47b1eabe25a4f4cL,0x669cf09c79f95484L,0xf30191584a0f8b96L } }, + /* 30 << 231 */ + { { 0x047b0f0124b240a1L,0x959915dd46cecf58L,0xedf2e74b72980ca1L, + 0x6b7b7b4ef2cad32aL,0xf9f01c9d0b9ded1cL,0x009d3a5825e77e0aL }, + { 0x62314ab411a39c1cL,0xb3b0c5b2ad557b74L,0x6dbb75dd961619fcL, + 0xb8f2d198c934e1e0L,0x4401507542eb7fd5L,0x3a8552efea1be435L } }, + /* 31 << 231 */ + { { 0x08e3f0e2217de9abL,0x6bdec27bb6b4f789L,0x5b160334685af8e0L, + 0x31e651cc61738f6fL,0x37224bc4631989c0L,0x2dc8006ad39f9c4dL }, + { 0x2a5d585056c3d84eL,0xb2ef06cc5cc79193L,0x246d92869eaa50e7L, + 0x8cacbf7cea6a7cadL,0x109bddc629465ce6L,0xad2f492fb5744947L } }, + /* 32 << 231 */ + { { 0xba03ba3b7b3b336dL,0xe57ce50928c9c55dL,0xf96b8cfe4f0f60b2L, + 0xb908d77e6fcccd96L,0x7208ef7de79dd17aL,0x739095333ec3d048L }, + { 0x9c5ad2da1163fe78L,0x4e2a8685cd4a15c2L,0xac999449470eb938L, + 0xfaaf27fbee7d772fL,0xfbe402abd0b7ad09L,0x704d4f0e57db00a9L } }, + /* 33 << 231 */ + { { 0x8f2f736c6330607fL,0xaf4acf66c975432bL,0x838fd8cabd1dec99L, + 0x347088aa7c3d0499L,0x28008757e835ea86L,0x43e2fb30c03e1aa1L }, + { 0x06c66dabf0d10da1L,0x25d7aa1867321158L,0x215e483811dc063fL, + 0xd52dee1e288362f2L,0x790989a1fe300a0aL,0xe0452fa5f163e1ccL } }, + /* 34 << 231 */ + { { 0xd3eab3ae25e7c044L,0xa3712d11b6d22325L,0x5e3835999e8237ddL, + 0x2549047c9dc93a5fL,0x24b07617b546a113L,0xa50359ed2e7b82fdL }, + { 0xbbc3eb5889964effL,0x93d490b60d7ae172L,0x68cd6b3f774ac0e6L, + 0xf98f1df035e02fc6L,0xfd2625c560857c16L,0xd68f25e845dd06f6L } }, + /* 35 << 231 */ + { { 0x40dcb41018c1b3d8L,0x8af9a0bf954cc170L,0x9c40a17d5af27d6dL, + 0x6b20fa7d7137d35aL,0x7c46f6aaf07f5adfL,0x7caa6e3cafc2f780L }, + { 0xef03332694dfb637L,0xd8f330b38d0ac73cL,0xacbf571255d40a9fL, + 0x1b4ffafa3f4fde0eL,0xa17488e09fe6b04fL,0xd27808a103957cfcL } }, + /* 36 << 231 */ + { { 0x85e1de1e96569e6dL,0xc9545920d7ae52f9L,0x04ebc797bcd62008L, + 0xe142d0bc04a24db0L,0x5ed44b0d40e9fa80L,0x39fd679a48ddaba3L }, + { 0x91aba967ce7ee095L,0x76de8d3a0e97d0f4L,0x92e7a107a221785fL, + 0xb028f67e734283ffL,0x987f644168af2f42L,0x0ad882369d7f7102L } }, + /* 37 << 231 */ + { { 0xc5289301642f7d3cL,0x53ea584de508c45aL,0x86eb66e949337336L, + 0xa56d59d668fbc13aL,0x44c464ffe9e51562L,0xe5280ecd8200a27fL }, + { 0x92e2a9334cc73f23L,0xf59780325e7b858cL,0x399bd41e90d4b2efL, + 0x4faecb8bd0ead86aL,0x6ead9c530ce48b14L,0x941b4807ef74700cL } }, + /* 38 << 231 */ + { { 0xea281be94d522b69L,0xb6855d45694a08bcL,0x7c47ddc7aa7f4d28L, + 0x2028e22b6c36bba5L,0x206b63430c2dee0aL,0xfeb0b3dae68fdcd8L }, + { 0x6dda02a44603db5cL,0xa705d0defd786a39L,0xd356f6a426aadd38L, + 0xd34acb7d95ef6a00L,0x073ea16e14846402L,0x2cf7a82ab2df8bc5L } }, + /* 39 << 231 */ + { { 0x8fdcd309bffd7240L,0x6843dd76386e459bL,0x222fa67c0dee5740L, + 0xa3801343620d7d83L,0x96dfdbffe21b4af3L,0x017bd3d3dadd04beL }, + { 0x1b6adba2bca18337L,0x191b86f1300ed35aL,0x103a380cd73bbadaL, + 0xc2f3172f36f95dacL,0xa01a10e220767bf4L,0xda882ca6989ad766L } }, + /* 40 << 231 */ + { { 0x5bbc748b9cc47708L,0x16d796054026c772L,0xefc3ce3ea053df6bL, + 0x30ea7eab0713752fL,0x15b491b9dfd524b7L,0xa751d82010bcd34cL }, + { 0xf30c708abbd5da72L,0xf0c55aa86d16bd51L,0x1754060ba6215d84L, + 0x3a48d2cbb863542bL,0x992e8340261d8c45L,0x4096f65be8fd2113L } }, + /* 41 << 231 */ + { { 0x5532411e1045d8cfL,0x2d2f8d6b52bea60fL,0xa850b61825c556c2L, + 0x6547892fe8965d13L,0xa7bd4527184d0cffL,0x0e7f7daec25ba558L }, + { 0xfcfaf7b234343889L,0x9d6a23aeb82ba1d7L,0x2859023b60514faeL, + 0x4d51aeddc82da6b7L,0x6a060dc38273cd00L,0xf2f8923d78478c29L } }, + /* 42 << 231 */ + { { 0x0baa35154f08b278L,0x26baf331e57297c8L,0x3fef65cc04e27c13L, + 0x0f910ee0ca8430b6L,0xa27c5f5c2c445251L,0xc780142dccf3c637L }, + { 0x47dc4192e0f3fbbbL,0xf4d12bd6f2a91a33L,0xc1eb18b206352685L, + 0x111cc07f5b3db096L,0xbce0cddbcb95c815L,0x6b0bae7e14d28563L } }, + /* 43 << 231 */ + { { 0x40d16b7705897177L,0x4772a643953915adL,0xc6cfc1d23cabc7a9L, + 0x0641e96df80536c3L,0x6c297cd6be4c5454L,0x509a837c9c00216aL }, + { 0x17455153c01ce9a5L,0xee76da8a40b825e8L,0x1757a59cd23a37acL, + 0x5adcfbd10958248aL,0x043314525d01549bL,0x831f725ab0c42176L } }, + /* 44 << 231 */ + { { 0x28704bdcdf7d537bL,0xbcae2c15fa88f42cL,0xab32eecd3866ac4fL, + 0x446754a2128c4a7fL,0xc69309c1739ef781L,0x216e9f43bd160d81L }, + { 0xe0efa3ec6fefc0aeL,0xd179225086a604f5L,0xe43e13e260418c0fL, + 0x6f605146f100b9b7L,0x6c39828a6e994093L,0x99558f4706c019e9L } }, + /* 45 << 231 */ + { { 0xf541b3cd28df49eeL,0x0be75ef5cec2660fL,0xe73d18bb620c81f1L, + 0x42e81fef3c775c53L,0xd0a9dcdcbc012ed7L,0x570f5a1b8f292a58L }, + { 0x51f302e74c030819L,0x42e1903f50bb8a5bL,0x6d8105a98536e7d0L, + 0x66e2fdf1c1ca766dL,0xecaf4a316c5927fdL,0x347803cf96a14565L } }, + /* 46 << 231 */ + { { 0x794d90ab425d3a7fL,0xcae9008d93ecbe48L,0x211e38c3bd5f11b3L, + 0x6020ed2a6db1c1d7L,0xaa5695064437f020L,0xb2b93424235f4d6fL }, + { 0xa84a3c1d66ab2a3eL,0x171f9325712a14e0L,0x4a43cd6744d958d0L, + 0x53bea85ee95dc3cbL,0x1fba008769f2009dL,0xf0fbc48f31c13eb4L } }, + /* 47 << 231 */ + { { 0xefa3dea85fb2227aL,0x0160b031e098a97bL,0x92a554e3553377b1L, + 0x7b58c26258ccaac8L,0x666400171c3e0a47L,0x40e45f90ae2d7d8aL }, + { 0x660df3441ee18103L,0x5515cd66e9b64e55L,0xede93c59de059b3aL, + 0x874a0c90ca0e7acaL,0x840188abc8b1daa0L,0x9d49a02601e148a7L } }, + /* 48 << 231 */ + { { 0xe93ee31ae12b4e64L,0x2ab8e378662d17f4L,0x2544bd9969516582L, + 0x7bf80e4b2e1e5485L,0xf30f0b14729d9361L,0xb3ffb5d18268d40fL }, + { 0x34605055ac193a63L,0x9e5ca9a9f8e04d69L,0xcbbeebc1085ecbb2L, + 0xda03b75bf340eac4L,0x3bf9468a84436462L,0xdfa8b4c80f26f20cL } }, + /* 49 << 231 */ + { { 0x2e6520714aa497e2L,0x2b9358fd7ecd223cL,0x96efcbdc4f828e86L, + 0xa0f76679d2f096c9L,0x3887bef70690b78aL,0x2e7d9cae1a01b10dL }, + { 0x8b0cdf0e5656e5d0L,0x0a6ca92d48d3ec2cL,0xdcacbdd3b49e2ab8L, + 0x4d087ee0d7485e87L,0x4987078292cc57a7L,0xa1776bd47bb38b8aL } }, + /* 50 << 231 */ + { { 0x60c113bdb711e087L,0x28694ff4e257e115L,0xf81d5e054c18d716L, + 0xd1c04b67eb0af843L,0x16e6e46e40d8907dL,0xb73c3de91dd34d22L }, + { 0x9d7f282519825f92L,0xdf5d33edba486ce6L,0x288fafac21c223d3L, + 0x21c4df016d05007fL,0xccd9626b197c5badL,0x3a91743902c91b36L } }, + /* 51 << 231 */ + { { 0x6f950922340ebed2L,0x9e796894beddf06bL,0x5a8ea337cd9d7a07L, + 0x1c5dee115bd182ddL,0xba87dd1ae0c79b9dL,0xb16169f3b9002931L }, + { 0x68098da138c62518L,0xea7bf413417fdc6fL,0xa500a320b6fdf768L, + 0x7870c71c4550c202L,0x0874fd9f6121afb2L,0x49f0fd0cab7d0b6fL } }, + /* 52 << 231 */ + { { 0x7af3de47f6b7fedaL,0x19b8a51ba30b2296L,0x16886446150a0af8L, + 0xdada5aeeb2a4ecbbL,0x77105de8e8de3888L,0xc54d352c7d763f77L }, + { 0x754984ae72ff499aL,0x3de4b2785a5a25f4L,0x5df75ece818512a4L, + 0xd4fc8093ca7ccf3dL,0xff9bdf544a49f4fdL,0x45d23e77de0a5840L } }, + /* 53 << 231 */ + { { 0x8ef88682ca85a586L,0x12038785bff64885L,0x99670d8ac98cf695L, + 0xf7dc3dca6c3d5832L,0x1e836a59fd3e64d1L,0x8dbb13addd426c1aL }, + { 0x21867f0690f59314L,0x7adb6f707da5ce5dL,0x662422ae0da28987L, + 0x75a1486466766a41L,0x2d42bede6c8937b6L,0x559e168dff0c474cL } }, + /* 54 << 231 */ + { { 0xa07fdaa25af635feL,0x01d67fb36a0c8fd9L,0xa226f8dac9eb8d8aL, + 0x0795c27ce7fcfd0dL,0x84556c0553578294L,0x92b30a84b3e57574L }, + { 0xc8eb6ac0ca5dc890L,0x061a0a195c8b7d8aL,0x60f3351923177c06L, + 0x780755917d01bf6cL,0x63ec8a4421f48422L,0xddfcb2c0d804c7b0L } }, + /* 55 << 231 */ + { { 0xb186daffdb2e385aL,0x7589c9cd43aac848L,0x9b474a411fb053d7L, + 0x2f79556be1ada6c8L,0x694badc54d7d9ce8L,0x31ac06a84921f546L }, + { 0xacaf91c165666233L,0x6ea97c8ee45b62b3L,0x9c8f3fa66f0096c6L, + 0x2db7da39ac68f8baL,0x0ad2da0f19a3d1b2L,0x08c96b0ff80d426eL } }, + /* 56 << 231 */ + { { 0x07d63f07257d20b5L,0x25475a304e8c62caL,0x2469d661789ac15cL, + 0xd0d2ba1b3aae86a4L,0xc716202a4458dab6L,0xa011ca5ec4d5f90cL }, + { 0x53ce0273ca2430c9L,0x61040ecf96da6946L,0x6847dd034247c99cL, + 0x0c500b4519defda5L,0x263316db365796d4L,0xff9b99e7b982d89cL } }, + /* 57 << 231 */ + { { 0x725fc8f911591738L,0xe6c16db3f4030f65L,0x66c7622d441b6b17L, + 0xad8e4b9c69d93786L,0x732d597473093a4dL,0xa2136d85228f103bL }, + { 0x84f1d9397bcf76e0L,0x971a4c55e2531411L,0x9816371d15920fa7L, + 0x5515cbc594bbc17cL,0x8b8c76e859d52722L,0x3bfe618e9a240652L } }, + /* 58 << 231 */ + { { 0x18981da25cd1f7c3L,0x198a91bb09b22c3eL,0x48d11aafb23d71ebL, + 0xddaa6e071d31782aL,0xca7b812a39125babL,0xd89dcd825d963539L }, + { 0xc7012ed9e5a89eafL,0xbcf0d4c4af0ce61fL,0x6f65a246e6a9f404L, + 0xae6a489d51c1302bL,0xab43a2bcfc5ea651L,0xfdb73470293b1e58L } }, + /* 59 << 231 */ + { { 0x8e860629f5c9d835L,0xf91a0b5d04efe37dL,0xaa2acb55b1956d3dL, + 0xe295b30fb5bb48ddL,0xdfad64a7e8275e6fL,0x1e203bb7d41beeaaL }, + { 0x4aa2fd5836e64f60L,0xfb0b92a706e01818L,0x68e386d60d29ff89L, + 0x617981bc1802840aL,0x6d68ccf7ceb124f5L,0x19193c483b120ddaL } }, + /* 60 << 231 */ + { { 0x4d02098b8b5d9d67L,0xecb580503148dc75L,0x561545107d898600L, + 0x0213ef782d8be728L,0x4123671b1f11d90bL,0x8b9ff1b654c291beL }, + { 0x139ba95e52db185bL,0x83be41d0997b3eb4L,0x4a950c9a41e2e288L, + 0xdca0290c48916145L,0xf1eb9327cd073e77L,0x384ec5ddbd4f4ccbL } }, + /* 61 << 231 */ + { { 0x7e538f9036f4b7b0L,0xeb54e9e4ca25008eL,0x0054a07bf8af6eb2L, + 0xd96b712f5e3f61e9L,0xf01da03e29aa496dL,0xedbbc2d7d00faf95L }, + { 0x178c5bbd104f4dd3L,0x5cbd4783aa11b0d0L,0x4433fe6156eecea2L, + 0xdcc01bdcada7991aL,0x89ca41ba1addfa5bL,0xad64ee097a65ee64L } }, + /* 62 << 231 */ + { { 0x05a8a58d7e276915L,0xee28f77bf1582bf6L,0x6f308349285bd210L, + 0xb8b8ec47ab877186L,0x0436930e0ddb857fL,0x20a9973e5346b800L }, + { 0x756ab9b5848dd5b9L,0x33a220cfa12370ebL,0xdbd87c391f3d0386L, + 0x90c6879075429844L,0x5cc1a9736193f021L,0xf0b80f6543d46e24L } }, + /* 63 << 231 */ + { { 0x45e5f57bf79f5116L,0x14f02b229bcd30ecL,0xd989ee5426a39a1dL, + 0x497ad3c3d5854b85L,0xb61c15e50154364fL,0x5979941f502107d5L }, + { 0x0b99f087195934f6L,0x1f852baa605fbf71L,0x68ec80e47206f65bL, + 0x0392af1cea5bc3c0L,0xcebe56f81cb1d6bdL,0xdc6279d90f80b6b9L } }, + /* 64 << 231 */ + { { 0x10c082a63fc14a85L,0x59389ebc1c0b14c4L,0x785d935b4cb291a7L, + 0xfc2ae15313e9ce08L,0x3146fabf4df6f1c4L,0xa2a4a457c87dd24cL }, + { 0x85fdd8771deb49bbL,0x2b7843709b055934L,0xc81d05013e7e0297L, + 0xb56ddd1fb92df904L,0x4612df9f295ddccbL,0xc24bd4cf0e27cf1dL } }, + /* 0 << 238 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 238 */ + { { 0x7830460fd1944d1bL,0xc56f08e784350af2L,0x73bee2aa307d9c78L, + 0x1b02af1b5aad8b6cL,0x5e31882703848db5L,0x4785958bf230f476L }, + { 0x4ea6535d4f80e25dL,0x9958c9c7d23c7f72L,0x4c197b332fd33cabL, + 0x24c7b0b1c566914fL,0x956ce3c371952d3bL,0x8735694bfabae5f2L } }, + /* 2 << 238 */ + { { 0xca9872e1597bd10eL,0x6725cc9a4aed951fL,0x96b17cb84e05b280L, + 0x97987146fa234d45L,0xba78949ebb35a7d8L,0xb82e9b9f6fc59384L }, + { 0xa303e54a70f165c7L,0xfd6bb0dcb9c2cad9L,0xe57e2de8ee722045L, + 0xa05c106563e27035L,0xaa38e86602d2fe6fL,0x78e02fa8ee2f6aadL } }, + /* 3 << 238 */ + { { 0xd6256e7c62c627c2L,0x5571edfc3cbb10dfL,0xfedec45771cca8f4L, + 0x2e26ac5f8483eed6L,0x8e8c0671173508c2L,0xfd9f25d50f39bf76L }, + { 0x1cb080c3094cc1b1L,0xd367ca8c113e6552L,0x4ae2ca36bedb511cL, + 0x0de0c3e34707eeb6L,0x204cc610239d3097L,0xb235dbf0adb00383L } }, + /* 4 << 238 */ + { { 0xc0426b775e3c647bL,0xbfcbd9398cf05348L,0x31d312e3172c0d3dL, + 0x5f49fde6ee754737L,0x895530f06da7ee61L,0xcf281b0ae8b3a5fbL }, + { 0xfd14973541b8a543L,0x41a625a73080dd30L,0xe2baae07653908cfL, + 0xc3d01436ba02a278L,0xa0d0222e7b21b8f8L,0xfdc270e9d7ec1297L } }, + /* 5 << 238 */ + { { 0x9704cdc6a9c26f4fL,0x96808107908a6756L,0x73be47d40f1def2bL, + 0xd32c11d619215394L,0x1a59b9541842c2f2L,0xd64a70bb52c94807L }, + { 0x32b08c3e9dd262b3L,0x54d2cdc4440315a0L,0x671b3139425ace14L, + 0xd418542f2c7518e4L,0xce5e1712cc1bbdaaL,0xb3268403131f98adL } }, + /* 6 << 238 */ + { { 0xce4b39874e39e87dL,0x8e60a901966f4603L,0x1b95e4fd73c4a679L, + 0xae87f845b004310eL,0xcd50aedf815684c5L,0xa56805d343c77e38L }, + { 0x9a429abcf0588403L,0x77dd1a02009e699dL,0x27ad38fb52a417d6L, + 0x62591579fd8f6d00L,0xccb12126ea58f822L,0x3a009e76760a3ccfL } }, + /* 7 << 238 */ + { { 0x17688d3410023b42L,0x9bc8bd6f7cfadb6eL,0xe4cdf89f460aa255L, + 0xf709740a99eb21f8L,0x1ea8115cbd460bacL,0xbf7bafe8ac7e6629L }, + { 0xf8dc02bb096de741L,0x982f7becd2f6a583L,0xd971589a0f92bfeaL, + 0x662793afc02acbaaL,0x1b0f7d5eb771574eL,0xd9f71c4c66985cdaL } }, + /* 8 << 238 */ + { { 0x4f120aa7e2a07891L,0x9158bab3a25d3225L,0xc96bac5ecfe5f7a8L, + 0xd4e73d59bbf3cec6L,0xed8d233560361cd5L,0x9b1a252c562f444cL }, + { 0xbd37d3cfc70f23c2L,0xf13b3b6ea52ea19eL,0x7e35535a3d2f41edL, + 0x0353b52ee8b1743eL,0x31d89dfd7b5a2765L,0x2b7ac6848d9ea8b8L } }, + /* 9 << 238 */ + { { 0x3613afb361bd36b3L,0x85171aef3e0339eaL,0xdaf0c280c833abe6L, + 0xde566372e4500f09L,0x487dbef84a5bda73L,0x5cc00564e6e3f324L }, + { 0xbdf148cfb96abd01L,0xf8dbeda5ba9306ffL,0x05774d1a5ac0b828L, + 0x73ddc3248cf4a56dL,0xabc5af5232dc6125L,0x15ad6d2573294d7bL } }, + /* 10 << 238 */ + { { 0x7b5bbe51bd6086deL,0x7fbc95303816cee6L,0x60ac14fab3354bf6L, + 0x2b2abe43c9a6e793L,0x6ffae7342e19664bL,0x1d0e38b90064bd95L }, + { 0xc1303ba3fa9f23beL,0x6d5f4ea5d8f0a46cL,0xf8f472517a270649L, + 0x126c13ae723a5a0dL,0xe4d0a19e5e21273eL,0x18076170e83abb8cL } }, + /* 11 << 238 */ + { { 0xc21dc6946b771809L,0x2501f25600f85b8aL,0xb3a21dc347382df8L, + 0x25ede3c239dee18dL,0x39709b9db29b770cL,0x6eb314d510fa9c5aL }, + { 0x79140b1f508f5e59L,0xcce9f7cedeff2816L,0xa153c050400bc8a1L, + 0x052e03c4ff2c127fL,0xf8ffff1f841a03adL,0xc0c2626345896fb5L } }, + /* 12 << 238 */ + { { 0x06a67bd29f101e64L,0xcb6e0ac7e1733a4aL,0xee0b5d5197bc62d2L, + 0x52b1703924c51874L,0xfed1f42382a1a0d5L,0x55d90569db6270acL }, + { 0x36be4a9c5d73d533L,0xbe9266d6976ed4d5L,0xc17436d3b8f8074bL, + 0x3bb4d399718545c6L,0x8e1ea3555c757d21L,0xf7edbc978c474366L } }, + /* 13 << 238 */ + { { 0x905ad4bf3023ec1eL,0x8cc101ca16081c1eL,0xe0d47ec79cb74127L, + 0x1be5f86725da2dd4L,0xcba2ee4507ebac2eL,0xcee26667e22d87d1L }, + { 0xfc339af1c7c409ecL,0x112af9b47b7ef32fL,0xcc3e07898b821999L, + 0x4234433c222b3478L,0x55bcc87ddbce50c0L,0xcb6141cd7816f642L } }, + /* 14 << 238 */ + { { 0x8ae24e6b67f38eecL,0x61adae20ea14bc0dL,0x32737584c480c3fcL, + 0x44f61b79812ee744L,0xc8f607d5fe06d5d2L,0xfeaeb2bcea45267eL }, + { 0xe004522bb92c909eL,0x5171fe360ab3e854L,0x659936fe63ebc481L, + 0xdde6dbbff76649d4L,0xb38c160fe2295d0eL,0xba608b7e1e8f5c1bL } }, + /* 15 << 238 */ + { { 0x55616c4c86c2cb9cL,0xcfa8b484173526faL,0x096a09d90039a4c9L, + 0x6ccb4964f300a73bL,0x42dd78ac66819855L,0xa7c532c10941599cL }, + { 0xd15905f0b630220bL,0x9f4893ca5637e103L,0x768c09bf8a2115abL, + 0x5091f4399c52755bL,0x4ad1c0f6d38e7c50L,0xf6e6b2d054eb4439L } }, + /* 16 << 238 */ + { { 0x73457010c46db855L,0xccb68c43dd579fb8L,0x705b0e8c9c25fe5bL, + 0x40f36ea182dd0485L,0x3d55bc8527ac2805L,0x15177c6fad921b92L }, + { 0x51586cd55ab18cabL,0xf51b5296cbb4488cL,0xbb4e605e84f0abcaL, + 0x354ef8e3772dd0daL,0x7f1a8f795e4e1d41L,0x93461f09de5d8491L } }, + /* 17 << 238 */ + { { 0xe186b0b09cd7d54aL,0x0451cb0dd4303760L,0x90a8b0f84b38f082L, + 0x2357f03700b04fffL,0x8a4669f86d81dbd3L,0x2a5cb6f6bd94842aL }, + { 0xa13d19c4c498a572L,0xb7b8fe10cd937a76L,0xf8df355ed9842244L, + 0x64fc9d62b077c8feL,0xd4b2c3cce9dd337eL,0x7c63799ad3784edaL } }, + /* 18 << 238 */ + { { 0x39fe6673a780fd38L,0x8bc8d026a4b4cfa8L,0xcc339850801c44bcL, + 0xb5d80c4bc2dca07dL,0x745ffb5d91f1408bL,0xb55588f89017d1e7L }, + { 0xafef3cf1c3d76a1eL,0xe3a6e8058e1367ebL,0xd09ea1e2a642d2bbL, + 0xf303c613216e63e5L,0xe699e51cc98908e6L,0x835d4cefafeac3c2L } }, + /* 19 << 238 */ + { { 0xd1cbe55ee5000eceL,0xc1a074b01ff0f474L,0xc6681f48d7ffb89bL, + 0x7c68011d48d0bb4dL,0xf305627bdcef5e07L,0x0f0e0c36323ee3fbL }, + { 0xc5c6b61355f5f185L,0x6e4de5af52d6cc84L,0xa64ea548889fe8bfL, + 0xc4c5e4104d28350eL,0xef944a8f7dd3072dL,0x7ed579fa13356185L } }, + /* 20 << 238 */ + { { 0xec72c6506ea83242L,0xf7de7be51b2d237fL,0x3c5e22001819efb0L, + 0xdf5ab6d68cdde870L,0x75a44e9d92a87aeeL,0xbddc46f4bcf77f19L }, + { 0x8191efbd669b674dL,0x52884df9ed71768fL,0xe62be58265cf242cL, + 0xae99a3b180b1d17bL,0x48cbb44692de59a9L,0xd3c226cf2dcb3ce2L } }, + /* 21 << 238 */ + { { 0xe646281876ba99afL,0x1d53bd27818b5992L,0xc55e135d67e1d81bL, + 0x32b9e37023e211feL,0x91ea63dc130b1176L,0xd7e1cc51a34fbb3cL }, + { 0x5363fd962fee934dL,0xd19c50ba0b8fd289L,0x21257825a11c27b6L, + 0x19159a966792c1ccL,0x0ccc3cac39a08fbaL,0x841cb58a45512d8eL } }, + /* 22 << 238 */ + { { 0xae8532c3224ab492L,0x8bc92c85f6acd0ddL,0xc071ba92b796d21dL, + 0x1290162943797a3bL,0x8f4c5fb5ec950329L,0xfab6f950cf0578e3L }, + { 0xb7b8d211bb6aa75cL,0xb06279dc3d1147f9L,0x060db1a7591820cdL, + 0x0e691a412830f356L,0xac00664224b8bc33L,0x579f9c052f17441eL } }, + /* 23 << 238 */ + { { 0xd8b9dcd50c4cb7edL,0x2f59d64c7619cdf4L,0x7e83d18e284bc6f9L, + 0x49af25123e415166L,0x90388976ccd64d11L,0x4708fffdfe2580b6L }, + { 0x7a8d25ff17dd4d8bL,0xba7785fefd71355bL,0x7cceb111b9789cc6L, + 0xa8fd782ee98d6b78L,0x8d1b7fb66135d4a2L,0x78c2267d35e382beL } }, + /* 24 << 238 */ + { { 0xf38995589311182cL,0x1bee4c4bb657a7b7L,0x0b1c4fd32df8d1a7L, + 0xf16bcc2376d3fbbfL,0xd5888916f4fd52bcL,0x3de6cfb4d5cde1f0L }, + { 0x764ffffdd4a07dfdL,0x5e674426e2642182L,0x34f64762ccd57b85L, + 0x2233a4c329351062L,0xdf076095d9c642f3L,0xac917a2c59f0df34L } }, + /* 25 << 238 */ + { { 0xe588d5a8cf2f7d4dL,0xb45923ee86798c14L,0xffefd323f0623572L, + 0x24dd7019005f605aL,0xb9e833053a6edaecL,0x039ed04949923a44L }, + { 0x0f83a74360789fd2L,0xb4f91a8e9b001515L,0x37b856664261ad9eL, + 0xc291caa68b92b7afL,0xfa0f8a5e67ba28e0L,0x362a6808c5eefb98L } }, + /* 26 << 238 */ + { { 0x8aee939cc64e4ab3L,0x3baac0a844621bb2L,0x9094a09629da9bc3L, + 0xa92dc70806d2314fL,0x45c1cd0e34235918L,0x51aeb007c34021a4L }, + { 0x58267735a3492237L,0xe8d494bd375eb21bL,0x664dacf5a395bf8bL, + 0x2ef1feb612cec40eL,0x90c5f43fa7141e5bL,0x93e80dd03855169fL } }, + /* 27 << 238 */ + { { 0x2e550006211b2fb3L,0x8c82e59d6cab73baL,0x011bb2fb2bd326b9L, + 0xfbd519ff1e0efd69L,0x0fb2f266320cec7fL,0x879e28c03518fac3L }, + { 0xd0887775e01294eaL,0xf6e60efd1df5bb0aL,0xb2a5d3a404d04a96L, + 0x915eaa29a4f3500fL,0xcb6c03f70db6bde4L,0xfee081a405f30cc1L } }, + /* 28 << 238 */ + { { 0x9580cdfb9fd94ec4L,0xed273a6c28631ad9L,0x5d3d5f77c327f3e7L, + 0x05d5339c35353c5fL,0xc56fb5fe5c258eb1L,0xeff8425eedce1f79L }, + { 0xab7aa141cf83cf9cL,0xbd2a690a207d6d4fL,0xe1241491458d9e52L, + 0xdd2448ccaa7f0f31L,0xec58d3c7f0fda7abL,0x7b6e122dc91bba4dL } }, + /* 29 << 238 */ + { { 0x24e2801364ca563dL,0x6f06fde270f8f91eL,0x9abcca1bd2a65c0fL, + 0xc5728ffca5aa1e40L,0x654f0f56eb9d3e45L,0xe04ada2394161a0cL }, + { 0x001b25626ddbc960L,0x253b447aef93504dL,0x895ce21e2d6dc894L, + 0xefb987381c1b63deL,0x6adb6eecde8b806aL,0x9ea3884e0240e7bfL } }, + /* 30 << 238 */ + { { 0xe8387f68411ad563L,0x98a962eacc5f157bL,0x8093a8d296090321L, + 0x240a73083790052dL,0x6cb4a7382e7dcedfL,0xda65bf8481a60e8cL }, + { 0x420ce478c66c70aaL,0x0e7959ec42da3021L,0x44bc9d3c7e35aa20L, + 0x36e49d764e9df39bL,0x7281073a9b286287L,0xd9a068422524b62dL } }, + /* 31 << 238 */ + { { 0x00d6e0312546247eL,0xcc2851020fdaebdaL,0xb8a453f15601006fL, + 0x0afaa3f138be7068L,0xc87acb442c6cd9f1L,0x10dd5d031ffd5fbcL }, + { 0xbae0b62fddacbbd0L,0x1daadc18446bf2e2L,0xaeaf15317ef0facdL, + 0xe7b92b76c941808fL,0xda59af2ae6d0dffeL,0x1c09b783e612b888L } }, + /* 32 << 238 */ + { { 0x3bd258d8775f516fL,0x4bedebd5c715927fL,0x5b432512e3f966a0L, + 0x338bfca7709d0c2dL,0xd142cc1049658259L,0xfabc6138636b8023L }, + { 0xa9ef94014d4ef14dL,0xd5917ac1c54c570cL,0xfd2f63c55cb64487L, + 0xbae949b11cea475bL,0xa45446031e67a25fL,0xa547abc1dc6a7a6aL } }, + /* 33 << 238 */ + { { 0x6c7b4cf344b880b0L,0x29da87760a388eaeL,0xf434d173fe9617c9L, + 0xaf67cc2ea47abf28L,0xe211ad37249d0eb4L,0x88d156e538bce76fL }, + { 0x60320c6dd58fa585L,0x7b352c39ebf09a7bL,0x9305dae8a31ce734L, + 0x70c35be89361cc3bL,0x6b8b71f8bcd14255L,0xd1b7963572a457a7L } }, + /* 34 << 238 */ + { { 0xd8d04787ef8849e1L,0x58adf044148375e5L,0x5b613ac476623232L, + 0xbd274d2f95d7e359L,0xd97acbd271576bb6L,0xd20bb2c34c7fc4b7L }, + { 0xe15465315f837664L,0xddac59b5fb4ce79aL,0x33fef5214fb36e08L, + 0x0467811045108b22L,0x0de6c7766dbe57bfL,0x456d765a25fea77bL } }, + /* 35 << 238 */ + { { 0x4d9838a32922b715L,0x3cd9fc0a6a7bb3a7L,0xb1bf28fc2247e916L, + 0x92dd22006f206a16L,0x8ea87d67b51256caL,0x2c535730b5a4bf17L }, + { 0x34da42505f584954L,0x72326fb8fefca748L,0x40fd9d09da2844a2L, + 0xaadaf71c412da037L,0xa62329a9aa6f884aL,0x1b6165e6726a8f8cL } }, + /* 36 << 238 */ + { { 0x2a2dedafb1b48156L,0xa0a2c63abb93db87L,0xc655907808acd99eL, + 0x03ea42affe4ac331L,0x43d2c14aeb180ed6L,0xc2f293ddb1156a1aL }, + { 0x1fafabf5a9d81249L,0x39addead9a8eee87L,0x21e206f2119e2e92L, + 0xbc5dcc2ed74dceb6L,0x86647fa30a73a358L,0xead8bea42f53f642L } }, + /* 37 << 238 */ + { { 0x39de72e225e62213L,0xd885c406a03a58adL,0xa63964b527e76458L, + 0x93f83239637c0becL,0x8c9e29b4ba556e65L,0x7d746448a6183182L }, + { 0x6dee01aa09a8eb37L,0x97289f2e757ffa96L,0x367ec50fb4785102L, + 0x200f77cdb3d07cd8L,0xadc7c000a581946eL,0xa2dba5e52c0b32aeL } }, + /* 38 << 238 */ + { { 0x95a5a7f0b203f75fL,0x9b574cfcb5df11f0L,0xbf5fe3f2dba4b4e6L, + 0x347a7bd7d0987125L,0x858dea6b09377a2aL,0x87cb1e66eea85d5fL }, + { 0xe7619b666146a0c6L,0x0012585a8a0bc101L,0x738e6589ea0ce92aL, + 0xf23547979a39b3f0L,0x666f3f5d6dc81167L,0xe569cc82fb06b0b3L } }, + /* 39 << 238 */ + { { 0xef0e64399c7677d5L,0x052bf027efc398c2L,0xa5d253cc515e4198L, + 0x7b915f07a71ce047L,0x56880ea2e177dbf6L,0x735dc74f0b5741d9L }, + { 0xa108632f0161a0acL,0x0c68765705e7e09eL,0x694e651e211709e0L, + 0x334e15e51d879a41L,0x6191d34260c2a603L,0x3a8ce0e6224234d7L } }, + /* 40 << 238 */ + { { 0x158d814db12c4bb1L,0xe52f75d22f0cf4faL,0xf106023e6141b59cL, + 0x5eb8b8ebbeb9d941L,0x1dd3972990cf579cL,0xb273252e69ee6efaL }, + { 0xe43a3c593e9947a0L,0xd605124f6c19dd01L,0x8090fdbd05c578b0L, + 0x8e6c535a622ff18cL,0x3600b0c257d12071L,0x6d026e5c78d001d7L } }, + /* 41 << 238 */ + { { 0x6e515f3608e33ad5L,0x3e320c5283512d9bL,0x171ab26a5ca1c452L, + 0xfb3061e874c97139L,0x7944644c9cacf3aaL,0xedc724f03687cfceL }, + { 0x7252d7590db9b5beL,0x625f17ed0eeaf1d4L,0x6b0b4e5e82e3c58bL, + 0xf03d7bcef0f2ecc3L,0x4cbaa878139a7580L,0x982e471672203e07L } }, + /* 42 << 238 */ + { { 0xa533f574e335d60dL,0x102b66fb2aa6855fL,0x7a57420c49946287L, + 0xe3bb702286f393c2L,0x1892642d04a41c49L,0x2c47ba38d44969feL }, + { 0x9068650444388ef1L,0xd94f6f131eaf6b54L,0xf81d8782f0b872e8L, + 0x7ced5924d013f6eaL,0x76ef63d307cd721cL,0x888646b36cba783fL } }, + /* 43 << 238 */ + { { 0xd2c858157ec1660cL,0x6c8988a3ee73763cL,0xd6cc562d5e80aaeaL, + 0x48f399d975768c58L,0x3189bf68af50c1c3L,0xa3f8d2df27dc372fL }, + { 0x99d6b416b8c7c529L,0x531707944406b1e6L,0xafb57933e3ac044fL, + 0x530ad3bab2548505L,0x791a290a977590caL,0xb0d07228646fd1fbL } }, + /* 44 << 238 */ + { { 0x636225f591c09091L,0xccf5070a71bdcfdfL,0x0ef8d625b9668ee2L, + 0x57bdf6cdb5e04e4fL,0xfc6ab0a67c75ea43L,0xeb6b8afbf7fd6ef3L }, + { 0x5b2aeef02a3df404L,0x31fd3b48b9823197L,0x56226db683a7eb23L, + 0x3772c21e5bb1ed2fL,0x3e833624cd1aba6aL,0xbae58ffaac672dadL } }, + /* 45 << 238 */ + { { 0x86d2f71530cf85afL,0x8e1b053cf7e634e0L,0xe79592f43a4e466dL, + 0x26752e8506985331L,0xfd098e83dff73363L,0xaa158e2c505ffbc0L }, + { 0xe45fa1cba0fe759cL,0x6e2f5989bc0d1491L,0x4a804eacae7210a9L, + 0x0e252f758a63f67bL,0x0d7600cf362a7df7L,0x795069bf6d5b2b18L } }, + /* 46 << 238 */ + { { 0x25f9f0fc0649613bL,0x109521f05d3005d9L,0xcce1c5b41feba4c2L, + 0x6a27cfafacda6021L,0x37ff83303ab6382eL,0x53c7ccb715ca79f3L }, + { 0xdffa6c9633611dd4L,0x7555cfd4352d3916L,0x2354bec62cbd44f7L, + 0xaf0044c54b0b500cL,0xe4835df7ce9aade1L,0x14e57f6bcb218644L } }, + /* 47 << 238 */ + { { 0xb5e26899b1c22bd8L,0xde12b0b51aaf3460L,0xc269595c31ee049fL, + 0x8c7513c88a73ed74L,0x8273018450cd009eL,0xb2cd2dec4d130b5fL }, + { 0x1a9015521971a189L,0x6ce23544c6f39bc3L,0xd76133aa9467badeL, + 0xf91173cc071ee7a4L,0xe54d8f44b8267c73L,0x5725e0676dc9aee6L } }, + /* 48 << 238 */ + { { 0x00e0a003daff1807L,0xcb9d155992c94fd0L,0x3c2b5c3dcebbf905L, + 0x9c799ec7d338afa9L,0x60b9908c4e2cfcccL,0x4bfe1a57ae3c6f92L }, + { 0x480d310efb116150L,0xa1ed6c31e3e7888eL,0x841a11d9720b5196L, + 0xcc337d178adff37dL,0x08c668265faa86c5L,0x945c90d49dfcc7adL } }, + /* 49 << 238 */ + { { 0x0fcc0854f2b3622fL,0x3a9e218ab6833f04L,0x209125d4ee8fc062L, + 0x98b2c628a3c3bf2eL,0x7e051fda83ca6a6eL,0x81afd3933d87981cL }, + { 0x8f3beaff4baf556eL,0x0f1b27fdcc7e66c7L,0xbf0b08f59f4a4461L, + 0x8eb739fa141985e5L,0xdb5b46112da43947L,0x63bf81cbe5cabfddL } }, + /* 50 << 238 */ + { { 0x355e40d398ff85afL,0x19f2f3c2b08f836bL,0x0a62d254737cb5f7L, + 0x5d0ef7d9f8c50d82L,0x773a399ebbd70eb7L,0xac357974a70bea8bL }, + { 0x1de5a45cb3b5d794L,0x67c58b52a48b55b7L,0x724f56f4b02ebc8bL, + 0x03dc71e3154ad508L,0x9bcd3939cc84428aL,0x7fdba978158c4a0eL } }, + /* 51 << 238 */ + { { 0xac08e06e65b93d44L,0x2397625a5358c691L,0xfbc9285a8516e31aL, + 0x38ce0d3544ffe25eL,0x13381dd16414072bL,0xf782fddc170ecb4eL }, + { 0x78c71a716f815259L,0xb725870573659a85L,0xd37678008712d968L, + 0x153d8aee3eda5006L,0xda4fd94818f1439eL,0x6384135352dbfdf8L } }, + /* 52 << 238 */ + { { 0xce92224d31ba1705L,0x022c6ed2f0197f63L,0x21f18d99a4dc1113L, + 0x5cd04de803616bf1L,0x6f9006799ff12e08L,0xf59a331548e61ddfL }, + { 0x9474d42cb51bd024L,0x11a0a4139051e49dL,0x79c92705dce70edbL, + 0x113ce27834198426L,0x8978396fea8616d2L,0x9a2a14d0ea894c36L } }, + /* 53 << 238 */ + { { 0x06d57f2920514206L,0x61394b863a2cc1ebL,0x0ffdf49a86c7b2c1L, + 0x65334e9349f58f13L,0x180b10b8c08dfb05L,0xec352adef6c95b7aL }, + { 0xf9801dc0c4bde0faL,0x428c77f0dabf0c66L,0x2a7d1bb0c2eb80d4L, + 0x81774172fdb56fabL,0x7507481f1d965515L,0xee0693bb8ebfadebL } }, + /* 54 << 238 */ + { { 0xf4589418ac56a031L,0x21f3dec6f2718a10L,0x0ed08d9690f28b6fL, + 0x2624bd7a35c3a6a3L,0x1b3f02e8bba795f2L,0xe629b5aa3977fd17L }, + { 0x66c8cd7691e8df1aL,0xf36c4e2c1b2b5542L,0x7f6b742f7dff66a7L, + 0x00bc68b8242e0fc2L,0xdff5c73360119d9bL,0xe726260fb5c4dddfL } }, + /* 55 << 238 */ + { { 0x0242fa358eeaa549L,0x2d081bcf8abc93c6L,0xaa31813c55551d40L, + 0x1cf21c1271db3aecL,0x5a6dede7203880d9L,0x389c63cabe4aaa9aL }, + { 0xff4db7d4bf28086fL,0xd89c039b33146844L,0xc2b32bf06df6f790L, + 0x7f4e836b9f22fecaL,0x3f64d0fa0af51572L,0x681a1f5bc67aa565L } }, + /* 56 << 238 */ + { { 0x9f9ac9608e2941a6L,0x43e7ff902fc4fe1eL,0x5ec413596033e041L, + 0x5ce791c46f6ff0f3L,0x8d134b899d907343L,0x7bd15c7786304df2L }, + { 0x2cd2ebc777c4a913L,0xcd86a39d45f07153L,0xe7e12d2e88bc423bL, + 0x478e814b0b3163f4L,0x78bd9c8abe8ec766L,0x6a5763e87709ce48L } }, + /* 57 << 238 */ + { { 0xb503ac624329d7f4L,0x3a900374488e3ce4L,0x8a11addab0d8dc97L, + 0xbea3ea2c0873bdf8L,0x0f57130115bc7adeL,0xbc98d2070b2b69a0L }, + { 0xaefc4047639d182dL,0x0e6db26feb3c44eeL,0xaf0f8b392a68a48dL, + 0xde65a6b36bf1e593L,0xe48f8fc989dbd38aL,0xad18a43bd8d285b3L } }, + /* 58 << 238 */ + { { 0x249d86007e9d48c8L,0xec6109ba109a54bbL,0x64f688af5ac65ad4L, + 0xb12c85b4be1796baL,0xcc258d31c9940da0L,0x59590853ff2f151bL }, + { 0x9e9edc4d401c5d1dL,0xdd9ad117f230b458L,0xc2c752ac962334b6L, + 0x3fab66ce27327e6cL,0xa363d3643816a47eL,0xa6fc57bec180bbdeL } }, + /* 59 << 238 */ + { { 0xd72dd5893ff345d5L,0xf87c17ae41e1d287L,0xadadbf525964d55fL, + 0xecc7f27af8b07db1L,0xa2dacfce6f2aa320L,0xc7936da72aa3f228L }, + { 0x2e9e6058fa504b87L,0xf2df43279d0f0634L,0x90d5ee22a4b768c5L, + 0x1ea9bf0b5b46ea84L,0x792370f45cc41770L,0xfd17823176c1a3f5L } }, + /* 60 << 238 */ + { { 0x4f1e1254604f6e4aL,0x4513b0880187d585L,0x9022f25719e0f482L, + 0x51fb2a80e2239dbfL,0x49940d9e998ed9d5L,0x0583d2416c932c5dL }, + { 0x1188cec8f25b73f7L,0xa28788cb3b3d06cdL,0xdea194eca083db5aL, + 0xd93a4f7e22df4272L,0x8d84e4bf6a009c49L,0x893d8dd93e3e4a9eL } }, + /* 61 << 238 */ + { { 0x4c124a904190257aL,0x09002f52347e517bL,0x2e9b69a1e5760993L, + 0xbaa49e53e26672bcL,0x9468fc3bf7820190L,0x637bccfe1f955328L }, + { 0x16fd33f26e0aa088L,0x9391550757b2b2adL,0x85e98842e9a0ace2L, + 0x8e2bd52b4fa787afL,0x8a86bd85644aeeacL,0x63490956c2814734L } }, + /* 62 << 238 */ + { { 0x5e902fb3063b3517L,0x0cd006cae5a65212L,0x597bd7804591c4bcL, + 0xd853d81be17c1d3dL,0xbc4bf68156e5d24fL,0xbc801615d26b5ce5L }, + { 0x1ffa5cd5caeecbe7L,0x16ec32a4b0203156L,0xaaad43269a857672L, + 0x0606ebf9189c6f6dL,0xb90730bd57e476f2L,0xed8d82b1d492fb05L } }, + /* 63 << 238 */ + { { 0x69a2a9b6ff824814L,0xe7b716e7c35c5da3L,0xb6781a5e9a5fde1aL, + 0x08bf695dc072e1b5L,0xaadf71462590a817L,0x490297f9c755c83aL }, + { 0xbd9fad6191c29990L,0x87b3abc226b6cb9dL,0x6975d59865fd0b64L, + 0x0fdc5267f4257158L,0x9f3e10585877bbdeL,0xb7f4cfb04297a2d1L } }, + /* 64 << 238 */ + { { 0xd699ea2d8d095606L,0x3cd080c51e0ddd3aL,0x46604bad66a8b35bL, + 0x0c779b624233fccbL,0x578458acbfd3cf0cL,0x6820f66596bf57afL }, + { 0xa9724245bf1f302cL,0xbbde24da277a6c3eL,0x0980a5b8c6be8c14L, + 0x6230e3ec774d62c4L,0xda1467d84fbde24bL,0xd9d68d07cc862204L } }, + /* 0 << 245 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 245 */ + { { 0x67c516347378f90dL,0xbc201a7966647082L,0x77fcc8dc9ee450cfL, + 0x8dd2b318b41a3e2fL,0xdf6a935e93bf0689L,0x75edabf3a92e5464L }, + { 0x49afcd9f604d208aL,0x372f0ea7d465ca48L,0xcdbd8ad2c7ea7810L, + 0xfe61571e550822b2L,0x744a4f9386606adcL,0x6beb3c9cd9d4e110L } }, + /* 2 << 245 */ + { { 0x1fef389ce700b9f2L,0x63029466425bc8abL,0xbd770a1437f04a33L, + 0xc7438e29d0169369L,0x6b265742e2377cc3L,0xdf24bf96c369fa4fL }, + { 0xdfdbcf470ad94e08L,0xd101b8617f75a7dcL,0x5574a0b82a9c483cL, + 0x0563fe942de43228L,0x58ca0e8aead1fabeL,0xdc3d9a8466023966L } }, + /* 3 << 245 */ + { { 0x383bda07c3fd20e5L,0x9619b1df5c29449bL,0x6f3c717d369f39bfL, + 0x1bb593d11a5a3900L,0xd0f07ecc2aec6c2bL,0x9d72eb2a4240b202L }, + { 0x35342f6cc50e4a0cL,0x701b46626b93bf61L,0xfcd6eb09ccb6a888L, + 0xabb7a6f785aa42c5L,0x952f8824aa4e5895L,0x49860db85c406582L } }, + /* 4 << 245 */ + { { 0x3667a7203955812bL,0x0d73483b284d1dacL,0xe084535efc62f791L, + 0x5bc1652b389faf7fL,0x40cf51683a71b7f6L,0x8a4b19fad4f39703L }, + { 0x823e754a2a8eff13L,0xf01b2021bffa5afcL,0x5639ee027225b319L, + 0x7533bc86fc282f16L,0x710009d2c69f61aeL,0xe30c499dbf65e803L } }, + /* 5 << 245 */ + { { 0x0da7ac1b734b4ec3L,0xf47fc1d012a2afbeL,0xbbbc99be87dce4a2L, + 0xf7264b4edd5c6378L,0xe9409305f618ffdcL,0xafadda9bd1846ac1L }, + { 0xe734f9d0a21850d4L,0x199cb44f8722a316L,0xcfe8704b38cae89fL, + 0x2db1e56b6b151b57L,0x116ca5cf69ce7b2cL,0xe9b8625f57de97c8L } }, + /* 6 << 245 */ + { { 0x18811bd5af247c49L,0xbc180793e124dbdaL,0xed978d3a21234fc4L, + 0x516dd9a70616ae15L,0x8f80677774e430b8L,0x9094256906e8fc49L }, + { 0x4ca03fb5a4e61235L,0xb91de709b617f361L,0x0898d82d0ed08bc3L, + 0x2bd712368cb08146L,0x45b92d45e213176dL,0x05894791f2bf5b9cL } }, + /* 7 << 245 */ + { { 0x0d79cb892695ea2bL,0x2cb0f8dfc88e538aL,0xc1b8dc3da80f36feL, + 0xd756fa6684f00cc2L,0xa6f1cdec9cb9efb2L,0x5c3f15a8a6a21818L }, + { 0x9a7ee3516995d09fL,0x88885463d70434bfL,0x18cecc6d4f7d5d33L, + 0x3f0138866b353bd1L,0x53bf798b0d9ad368L,0xeffd465a28dbc3eeL } }, + /* 8 << 245 */ + { { 0xeb29e44cb5d98ac1L,0xe47e57f80e227a4fL,0xd09c04943d2bf688L, + 0x3ab7799a47428dd2L,0xdc558d6be9aafac8L,0xc042c4cd87f9f6e0L }, + { 0x93842bcd89fb4693L,0x62dbc82f7068fbf7L,0x164552687e6d47b5L, + 0xab304b7a4c37eeeeL,0xdbb3d4e13fc412ceL,0x4f65dad0a726a2c8L } }, + /* 9 << 245 */ + { { 0xb25e01b2605cdaeeL,0x74abec55bc57969dL,0x9c57bfabcdd9d41aL, + 0xa3330e3f4a9e32a3L,0x5929a0d8e5792fd8L,0x830b4ea271ea2cdeL }, + { 0x80065ac1fd06d246L,0xa2b416e632e64a25L,0x3950bde7c0c927a9L, + 0x9951f3bd679d9b8cL,0xc235a274651b6855L,0xbfe5e08e5ad97bc1L } }, + /* 10 << 245 */ + { { 0x4409a5b6744ae145L,0x5e83fa0b7f620908L,0xfc489bec2e140aa0L, + 0x5805a462e3cae337L,0xe56e9ff7c2211c21L,0xb722f2b40c955362L }, + { 0xb098a32f41371f33L,0xe6cceceabb4923d6L,0x1cfbe2b3d82a311cL, + 0xcf9428936b98f917L,0xd60dc62492ef848cL,0x34af446e5adb5228L } }, + /* 11 << 245 */ + { { 0x0eb7e743796ce1caL,0x138653e5d851377cL,0x69c7c86f2b11c8e0L, + 0x878ec1decdf2b205L,0x03e6688aae0e8562L,0x20810666935a36a8L }, + { 0xc8ab7c7f26635c50L,0xe75cdb06744a21dbL,0x4e26f32fd720e198L, + 0xa1c6395ad8cded81L,0xb75dc6ea6ce4fc04L,0x71750b33004623b5L } }, + /* 12 << 245 */ + { { 0xbdef84077e60c447L,0x88570f712a65accaL,0xef3d4a400bb6aa79L, + 0x5c9d189060212976L,0x80179ea21d96c43cL,0x3f002e6d53d2948eL }, + { 0x14b2cc9149d78183L,0x7a549c71b496c279L,0xf4beac3f44995f6dL, + 0x5a34239800bc78feL,0xa874dc1b60e42da0L,0x3a984010cf5824d5L } }, + /* 13 << 245 */ + { { 0xe514ee06dfb9760cL,0xb8862d7577b8951fL,0x0144676ef8ee1141L, + 0x49561a3002eb3e82L,0xb3541c154ff9f897L,0x1670edf0a7a99791L }, + { 0xd41d603564aea7f9L,0xf66ffd092b3463b4L,0x0784e015c3b26fb6L, + 0x88edce33ec46f8c8L,0x1b1e25a3b6381011L,0xbfaadc03ff95ab97L } }, + /* 14 << 245 */ + { { 0x727a59fe0c7be4e1L,0x75a7d5e3f58ced15L,0x146fc0d990f569e7L, + 0x94dbccd2b7f1dc54L,0x0df1ef90b75bf232L,0x2943a082a2568190L }, + { 0x75f2f80d67837b06L,0x07e3506f24b44b6eL,0x7c30829ad0d2231bL, + 0x9ce577ca93277abfL,0xa19d1868b17549ecL,0x0ad6ff5525e8c4d7L } }, + /* 15 << 245 */ + { { 0x16b38dfe1c24d075L,0x3acd4c36992959f6L,0xdaf2fe88ac2da7abL, + 0x76e8ff0e89644935L,0xb8547c26e85f7076L,0x9f149faa1cdea7ceL }, + { 0x181a60729e125d84L,0xc4aef9fa18751ce6L,0x451c84660e00f00aL, + 0x662b3e7ac4e3e6b8L,0x57b7114ec6b64507L,0x07aeb1980b37fb70L } }, + /* 16 << 245 */ + { { 0x79d88e004516234aL,0x98dd3cb931f9cedaL,0xb528000fce7d606eL, + 0xc773557e2fa27fd3L,0x55b53dd3e19436afL,0x675084b3e10b64c7L }, + { 0xe583266556d56374L,0xf8f7fd2a307e2e60L,0x7b93bf537af3e3dcL, + 0x94fafa2cf47d298cL,0x94c2ff9a21121369L,0xa41de95f33468ff6L } }, + /* 17 << 245 */ + { { 0xebbafd4720f25aa7L,0xe2becad71ac444bfL,0x323356a092a944b8L, + 0x32feccc0c9a3cec9L,0x15ec3aaf5f9e96c1L,0x852142b5c12c8e62L }, + { 0x098ffcbf2b6865f1L,0xcca470e8733d7741L,0x0f8c0f5271945bf5L, + 0xfb654f6a08068827L,0x3a9e7d742a0e2829L,0xb90742b04b687763L } }, + /* 18 << 245 */ + { { 0x145afb651fdb2a7bL,0x93315b684eff5eadL,0x0cad1d20e40ca999L, + 0xda9b517a379a8173L,0xacb665780ca018cdL,0x1e9d919f481969b4L }, + { 0x5c9a058d68130364L,0x872e26620a62ce5dL,0xca598848acaabe54L, + 0xdabfcee18aa048a0L,0x16198d034ac52a57L,0x72eb5ec632b6d102L } }, + /* 19 << 245 */ + { { 0x13f2e1726a0c96e0L,0x55aed9e02d6b6f05L,0x3c919ba3bdce76c0L, + 0x647a525ffdda39aaL,0x5c0dbecc01a9011fL,0xa537ba8d9fd9dcefL }, + { 0x8472e375cff62467L,0x57672311ed5adf05L,0xd1e178dc6a423de3L, + 0x3ebcfe18d3ad3ca4L,0xb8f341d7ae802c11L,0x3f14c424ecdfdb7bL } }, + /* 20 << 245 */ + { { 0x381e0a136e4d2e42L,0x2f2a4ee183c0d752L,0x50d4647fc8e6532eL, + 0x7e210aeeb4e7495dL,0xfd147710bcd142a6L,0xddddb07b06429213L }, + { 0x63e06fc64548a6b8L,0x05d9b825904f92a6L,0x4b63fdbf9988ee79L, + 0x6cfa412f9b3366bdL,0x0dd5fe3dc8c61f51L,0x3ec77027be8e047eL } }, + /* 21 << 245 */ + { { 0xea7d01cfc7d81791L,0xfa6c0fe6e2264afdL,0x53c7eea363651291L, + 0xe58f8411f2d90f92L,0x4919b4c61faf0e14L,0x0c7dcd07148e98a0L }, + { 0xf9ef44cebc8bd43dL,0x3acfb6686f83cfb4L,0x34130e18f883693cL, + 0xda9ed2ae2d236c3eL,0xf54da64cc75cabdfL,0x1c3df906cc01722bL } }, + /* 22 << 245 */ + { { 0x686796c68d8f2286L,0xe0efaf9334d7cd1aL,0x84f9237c93b23708L, + 0xcb50cc8ee47f5161L,0x498b81e71f597821L,0x3c3f33e1a491079fL }, + { 0xee300c6dc69d1bc8L,0x279760e734778389L,0xe00ac0eb2bb8ed78L, + 0x9bf9a10e765c8b5dL,0xc7e95c0cf8c1e909L,0x3721300ae6e63ea5L } }, + /* 23 << 245 */ + { { 0xc03ad784d8dfd7aaL,0x671384a64b065a2eL,0x9b21e9e7bed74e87L, + 0x153b606cf889f75bL,0x7345c62a2aab6562L,0x270e4f445960cb4cL }, + { 0x515909fb885f0f88L,0xe43ee4f7067a7928L,0x5f906fc8fc182e56L, + 0x297ad5770641d0d1L,0xdcc45aa1d1b188b4L,0x8c817fb2ef062a39L } }, + /* 24 << 245 */ + { { 0x91e8c992044637f0L,0x01f7838827ee8e8fL,0x7c5e3f6dd095f5b9L, + 0xed7522fcddf3cad2L,0x80bb87056c57aacfL,0x495480b00cc5ff51L }, + { 0x964def7f04da2565L,0x8b0d0fe3afa72140L,0xcc75192584de66a1L, + 0x9acaf7fe075f07c5L,0x6505c2f81eeade93L,0xa2f35aa00e3cf58fL } }, + /* 25 << 245 */ + { { 0x1ad38a2d80548b22L,0x4d6120df47a37b3aL,0x6d64ef8c23e33cb7L, + 0xa1b5f51723c14ca6L,0xd2cdd425039a8e83L,0xa0a359ae229dd2dbL }, + { 0xde0788166c2779afL,0xd960453362d2abc2L,0xc5c48b20707c0e4dL, + 0xe452debd691c5407L,0x35c37ca882b0a299L,0x5b263014da3cde7bL } }, + /* 26 << 245 */ + { { 0xde34fa4586330487L,0x8391248153f61e6bL,0xd3f8fe742d04958dL, + 0xdade250f6df77d09L,0x3a3a16175649d9ebL,0xf9b77847a23abc74L }, + { 0x31d45db63b2e2c8aL,0x311ecc24f61a7bf4L,0x206029f9c56eab17L, + 0xb9d9ff35878c672eL,0x0d268c160fbf2d91L,0x2474b527a45f58d0L } }, + /* 27 << 245 */ + { { 0xad8e84be8436beaaL,0x8f07eee4209eb5d3L,0x47cba1d83ee61bddL, + 0xa081f21f72018544L,0x5dffddf493d88d16L,0x539a79efcac3952aL }, + { 0x990af57791bc452eL,0xb139d7d5012f5c6aL,0xf818c9f3fb180417L, + 0xeeb2d08475566152L,0x287571253f5d4ec9L,0x5a26505daa959798L } }, + /* 28 << 245 */ + { { 0x6536834e11b0f7b6L,0xcaa5271aad46c10cL,0xb5b6ead1fab43763L, + 0x25bf402ff7f7d8fdL,0xf33fb223e19374b4L,0x183ae9b75f348172L }, + { 0x1783c235078862a0L,0x9981a6c33cd368fcL,0xf58d2274fd627f9fL, + 0x37ac9c265c5e71cfL,0x167c8d047b0f157eL,0x24f522f8eefc7d85L } }, + /* 29 << 245 */ + { { 0xd25aeab3926cc973L,0xb3e2cffbdfc2cfbeL,0xdd259ed1de742b6cL, + 0x9d77c94e7b98bf81L,0x90f9067cb0ead3d1L,0x148f2a192a93fec1L }, + { 0xbae3c543c2850153L,0x0d330d758910422eL,0x06f80a9efa670474L, + 0xac6cee9f038431a3L,0x4900d17f5c22ee99L,0x62de04aa275a9774L } }, + /* 30 << 245 */ + { { 0xb6eefcc55f87fb35L,0x9766873b4371415aL,0x308337bd16b058bbL, + 0x6d5b1ddae1ac3884L,0x9307aa0835c4630aL,0x22cfcc0c23e91988L }, + { 0xbeb3814c37db0207L,0x19ab212fc4bbaf5bL,0x0801a1cf21abf22dL, + 0x9e6862cb3bd07332L,0xaa12ba0e4319929aL,0x0da45831f540f97dL } }, + /* 31 << 245 */ + { { 0x67d8ac9484bbf927L,0x7dd04e4e4ea01d33L,0x24ea6386f13def66L, + 0xa8a1acbe28f7f5f0L,0x5f578ffecc84c93bL,0xda8fe295f4ad116aL }, + { 0x4b610ae48483347dL,0xcac5c5596255f9e4L,0x19a0e043abcfe47bL, + 0xcd0cc9493966784eL,0xcc59a36743279291L,0xaa504087802961b6L } }, + /* 32 << 245 */ + { { 0xbe45d81a1b270599L,0x50696e7d97d6c603L,0x63c5a516b078ea89L, + 0x9f3efe41b4464764L,0x84580e24101e5232L,0x00850a1ac8ae8220L }, + { 0xbff4077ded55c404L,0xd74de734f2e7bf50L,0x4df4eef207e1c03dL, + 0x4ab3d0396e654d58L,0xb20056cd086f1596L,0xe4d08a278acd7cd5L } }, + /* 33 << 245 */ + { { 0x5510cebfe354510aL,0x48925b9349998c9bL,0xa05fc961e6d707a0L, + 0x85bf38f866ebc93bL,0xea637045254e615dL,0xae25e2e740d8459aL }, + { 0xa98583176efafd1dL,0x863931fd5a51c4b6L,0x3810d732d4221708L, + 0x959a2f70762a30f3L,0x7bdbaff9420ad3acL,0xba41b20bebdfe90eL } }, + /* 34 << 245 */ + { { 0x5e4d3280d3171eb9L,0x3fb715851bc65c5bL,0x6558962a901a899cL, + 0x78b7cd3e7851462bL,0x21228419ca8f6495L,0xfd8d8f9b2d8be765L }, + { 0xe5e90b92bc562144L,0x4f1f7ca1ae3243edL,0xd20178cd0985f4e4L, + 0xe5be263304253cbdL,0x1e34141c0d348fadL,0x0073fa0dad0eef45L } }, + /* 35 << 245 */ + { { 0x922ddb84d403f20fL,0xf7bccbb54681def7L,0x81a1200f6b580442L, + 0x64901025dc2f9884L,0x3746675aabe78edaL,0x3e750369aa6f005aL }, + { 0x140477ceeb00658fL,0xc76a320ccf89be62L,0x00761f21658c127fL, + 0x669186dfb8b6b03cL,0xbcdf1c36dcb26a2aL,0x94a7aba5da876a56L } }, + /* 36 << 245 */ + { { 0x1872f65c26163265L,0x9fbaf44fda52ad9cL,0xbec7addeeda47d38L, + 0x6a04dc3078094f9cL,0x2c73b8f15f4498e1L,0x504909efd4fcfcb4L }, + { 0x747efbc6b6b3a63bL,0x856e276de0dadd96L,0xa22459aaae3be3a4L, + 0x9ef59e732294a854L,0x0717d4e5d0e36205L,0x5a6afa3eb734cdf4L } }, + /* 37 << 245 */ + { { 0x6bd8fd330e938950L,0x8b26d7fa0f20c4f3L,0xd29a1121e0604d4eL, + 0x23d1cae60711c191L,0x460af39d51914cb2L,0x9cd04208547463c1L }, + { 0xeb80d70e493b7a0bL,0x182568869171652bL,0x9f3007ad76ca8b21L, + 0xf9bdeb4664ac10c4L,0xdaddd584284ae80cL,0x5c7ea28a0022abfbL } }, + /* 38 << 245 */ + { { 0xaef75aa7dc3c897eL,0x98bab5852e6432a8L,0x522b383d83fb0ee5L, + 0xe0d8620f056a8589L,0xd63525dd39352633L,0x74362bbfaeb985dbL }, + { 0x11419f4e8c0f17feL,0x3ca918b0494ba972L,0x39f2bc3c6e074e25L, + 0x3bb66618fbbf0d60L,0xee60c8f88579fecbL,0x916f3fe92a9b905fL } }, + /* 39 << 245 */ + { { 0x14ed31b6482b668dL,0x8e3e10db5b65978bL,0x72ff92eee8011bafL, + 0x5183d0bde1143531L,0xdb628188f9c740d1L,0xd23cb9c57570e3d2L }, + { 0x9e893cacd2745832L,0x49762940ef4a2b31L,0x02f6f892324361bfL, + 0x332e089dd7a881bfL,0xe9303153f788f52dL,0xcd6d15564e7f1bd7L } }, + /* 40 << 245 */ + { { 0x8caa623d408b62b7L,0xa58aa0b0c0272b41L,0x089af856ee285bfdL, + 0x77b461f6d0674ecdL,0xbaa9d9b38d6f6612L,0xa8f26e12590669f8L }, + { 0xb164340c5ebb5e28L,0xfdc11f7401ea89a8L,0x73c03b9176e4346eL, + 0x6a678eb17caad5fcL,0x103ff0790a87803dL,0x25d6fd2af7430a94L } }, + /* 41 << 245 */ + { { 0x72cc0aba66116d84L,0x642c88681039c0fcL,0xaeded9e6d96a7423L, + 0x4ff4163ccc5fea03L,0x180e4d3616483ec5L,0xefde910a7f6332c1L }, + { 0x8042696283367060L,0x4edce3e8c28af356L,0x2452e4de965139daL, + 0x15129fd9547477a1L,0x7f628b5ed80998cdL,0x7c56d44541054b54L } }, + /* 42 << 245 */ + { { 0x4c3f81184d3d9da9L,0x332072f9e1e71487L,0x8cbf7284759ef371L, + 0x3d13d85cb98ce007L,0x507b467f980f4fd5L,0x9853b98bc74fdfdaL }, + { 0x94b81534993f5e19L,0x316b761beeca71adL,0x09820a2331c04080L, + 0xc71a9bd4420e3114L,0x569f813822ea67ddL,0xe3ec5d2b3a41b079L } }, + /* 43 << 245 */ + { { 0x6085b24a19bb6f27L,0xc2f18e8f64dcb82dL,0x8ff89ed91fd3888dL, + 0x9fbe31db0e525a5bL,0xd52dfb5df0527573L,0x90288a3f703193c3L }, + { 0x87bb5d30bb1ce380L,0xb6c9a4c9f0dcf59aL,0xcbc52966aeb86e7aL, + 0xd151178a9a1636eeL,0x48342994e4b48c74L,0xe5bced925af80bc2L } }, + /* 44 << 245 */ + { { 0x106882534918179cL,0xdeb69dde08143b36L,0xfb3c527b992363faL, + 0x11d05e93e9393832L,0xe3249558383a0f59L,0x2d0f3e11c234ab5dL }, + { 0xd50a30d95c599ae7L,0x6d7abc6ce9f98316L,0x3d190629060ab6ddL, + 0xfd58473c81d69afcL,0x841193d24b782d62L,0x4f72696da771226bL } }, + /* 45 << 245 */ + { { 0x288895d056e467a5L,0x78166a95e025a5b3L,0x89df640e895835dfL, + 0xdc2b61f483dcbc50L,0xbeaa7363110dd6a0L,0x2346a2a5e7fdbe3fL }, + { 0x379ae5fb6947a9c4L,0x9dcf01956370a372L,0x34c3c6c3d70d9a24L, + 0x98ee14b7fe6a3d0aL,0xdd37708bba8ce5baL,0x785adb86a15c3672L } }, + /* 46 << 245 */ + { { 0x4c93de89c5ff194aL,0x56aef366fdc94109L,0xc8cb2a0c5b0b23d4L, + 0xd73f1cef587ada16L,0x7138315a364b1463L,0x43940ef59f6bd411L }, + { 0xad068e490f4a533fL,0xe8a772a33c7dac91L,0x74b815fc107998b8L, + 0x4b8fa9db92699ee7L,0xfb2de4bf4cbb023dL,0xe5833a390f67c29cL } }, + /* 47 << 245 */ + { { 0xe985acae7fc4fa91L,0x7730e38ec66c4282L,0x4b971449f4bda67dL, + 0x55261be02b001f47L,0xccde0c7126d0d8e6L,0xa7ac56fd701f6febL }, + { 0x2488b28552642a53L,0xeada397c58fcfabbL,0xa3fc0452b679b0e3L, + 0xd0ef09ffec2e921aL,0x9fcfd991575fb70aL,0xf4adcbbb366cb10dL } }, + /* 48 << 245 */ + { { 0x517075af5faa0cb7L,0x400a22c1efaf68f4L,0x320ce9493b86f639L, + 0x511565717f296bf4L,0x0919607a96108276L,0x4fcc39a02f035900L }, + { 0x5d13de7cefb73f3fL,0x19d725c5081c38e3L,0xf1b28089c0f58697L, + 0x2adcd1a30ca7ca20L,0x96c07f42c21e1be5L,0x94d28cacbaa0aba0L } }, + /* 49 << 245 */ + { { 0x0ff4983fd64cfa4bL,0x2c49c4918c55942cL,0x6093eb7f98eb20baL, + 0x1b33296a060497baL,0x32776a53c92d7b47L,0xf367e6b25241de3dL }, + { 0x711119813b65228eL,0x2e5dc541e1394451L,0x940a4a0f98ef33e5L, + 0x1a395be32cd4315dL,0x4d49469f3c2e20e1L,0x5384f4b95c314f95L } }, + /* 50 << 245 */ + { { 0xdda2f3a0a256813fL,0x4363d190ee6cbae0L,0x61f4d607930d0094L, + 0x6767ff4817021739L,0x8450091bd2c5fadbL,0x144d02fe870710a8L }, + { 0x73f45d9035524b7bL,0xccc7856b04615373L,0x0eb5cd436f081dfcL, + 0x9c433cbfe3a70d59L,0x9ee70f509818349aL,0x16de27347241c634L } }, + /* 51 << 245 */ + { { 0x02a24c5cc47f7db6L,0x519242cd33d60e1cL,0x543f39cf7244a636L, + 0x4ae15d698deb181eL,0xbaec81ef44261806L,0xe5cb18bb5fbf13abL }, + { 0x7534787a032158e7L,0x770e1e34da0d9a6aL,0x251bfa7158f9baccL, + 0x12663214c8d39905L,0xb7bfa81b39c3d64aL,0xd6d439ffe3ee296cL } }, + /* 52 << 245 */ + { { 0x192ecf72d0aa048fL,0x23af774063e40c0fL,0xe4d98e41d804d367L, + 0xd868cc885405bfc3L,0x96909a5b6f6ece88L,0x16b05ad2bae60dabL }, + { 0x7382a1dbde621949L,0x569bb6c9c47cf6dcL,0x892da43e1f2d098bL, + 0x6bd959b9bfa25649L,0x90617c419cb48f9eL,0x36059b73f110b22dL } }, + /* 53 << 245 */ + { { 0x1817b140791af82aL,0xf4a44cde042870c5L,0x60b8414ab5c0405aL, + 0x3b00f5ddf4dc4a9cL,0xa61aa0cfea81dd5bL,0xd43c37422554907dL }, + { 0x3fa264a620569ecdL,0x2cc69c2ba5a46190L,0xecd4f6d3dddd072eL, + 0x41083b72dda8de01L,0x4bc047f110d6f156L,0x7164b432cac3203aL } }, + /* 54 << 245 */ + { { 0x7e7e08f401d45bfeL,0x04f9c9ed0e2d17e2L,0x3213556fa55bc148L, + 0xc58983c734449f0eL,0x463217afaf2bb219L,0xe08a51a2f8fba72dL }, + { 0x2f44991e974d51f0L,0x15f2171f3f12af56L,0xbcc919de24cf01f3L, + 0x9ea371f269399bd0L,0xae8a8eca3ccf4574L,0xf0535b83ae499429L } }, + /* 55 << 245 */ + { { 0xe9ad8928f72305e3L,0x4144b6b9fce1295cL,0x672732a0c3487eb9L, + 0xf19d09a6147f70b8L,0xf45f6a11362a7684L,0x84ce4f25adfbbdadL }, + { 0x31e4bb0ac3403b48L,0xefc861b9b478ab38L,0x3323df44a8320c49L, + 0xa2838aa1ed4f14abL,0xc80e30cc63bf7df7L,0xdd2d5ef9f15ec5ffL } }, + /* 56 << 245 */ + { { 0x3027c1698d6f8572L,0x89326850111e64d7L,0xe6eb6cd31b8b0179L, + 0x0d2d27ea6dd5a4a7L,0x41682c0007c82f11L,0x5a01c54c81075022L }, + { 0xf3903f51fe7220d0L,0x75daeaba1f8e66b2L,0x1b625eed470bd3b2L, + 0xa46398a7e85a6293L,0x8ff6ef8c805ad640L,0xb3430f6795bfa3a5L } }, + /* 57 << 245 */ + { { 0x55d31765bc9341b7L,0x6530526ba312d125L,0x57ad29c02e9eb238L, + 0x31658a8282292155L,0x4d3417b169301639L,0xb38d6199e48c3d1bL }, + { 0x4399d5ddcc5202eeL,0x4b1c293a5076cc08L,0xa46e87f5824171b0L, + 0x16f75919e4cb40e9L,0xd086562dac35d85bL,0xc2b41ad532713f5dL } }, + /* 58 << 245 */ + { { 0x2da6d2ca3248f02aL,0xae49d2fc675de73dL,0x4abb1a65cfbfee63L, + 0xc6cea22cf1246350L,0xdd510cf82d3faec5L,0x8b7d1b0865e7460bL }, + { 0xc5b39c802737b182L,0xeee61e0d8963c709L,0x9cf9da61793e7179L, + 0x630637e52a295ba6L,0x18b85c9fa3881ba2L,0xca091a9464a94fe2L } }, + /* 59 << 245 */ + { { 0xcb68739f0bdec121L,0xf4907b3cd3811dabL,0xcf1b079b8c5d7707L, + 0x9ef9002d2fc6a56bL,0xc4c9d069809e8b64L,0xaf86a3db90d0eef4L }, + { 0x30a52f994b24a04aL,0x03bcd7a958574ed0L,0x330ce8a1a5b52b8bL, + 0x632b3c2d5e6a8ed9L,0x7b080a2c18369382L,0x12173e5f65187ce1L } }, + /* 60 << 245 */ + { { 0x027f654feabe8ef1L,0xd9d327e481a51834L,0x9215df61980faa43L, + 0x76b4f8003ba045c1L,0x8f3ce587f400732cL,0x0abe1f34f133a3caL }, + { 0x2ec690526de4f504L,0xa297cee4cb7ff026L,0xa31a76e3cadaefe1L, + 0xb701391e1173a958L,0x0a4279b08c8768f1L,0xd58927c12f8ede03L } }, + /* 61 << 245 */ + { { 0x71ea38454e630b0aL,0x4f696b59119263abL,0x9e7cb293f9cbab69L, + 0xa448d591c60ea8d2L,0x5021d4ef7d89eb52L,0x1a1ea5e3787663b1L }, + { 0xa95af4eb05bedc8eL,0xfe72effcc2fba411L,0xa88b79bb19a2c6bdL, + 0xbed948fac84c78eeL,0x022dcf3d5ee7455eL,0x0c39c3689f56accbL } }, + /* 62 << 245 */ + { { 0xe0e818a8b77c9de2L,0x0dbaea885e07f77fL,0x6ece83b97b1f96f0L, + 0x3c02e59631733a5dL,0x44bcdfcdd14828ffL,0x2791ca54b66f6107L }, + { 0x1a051c5a6198f24dL,0x9cd5f09a17627301L,0x64323392004a0cb1L, + 0x75d6819b3cc13e05L,0xf5cab2874a58768cL,0xbe090e83e3ca9332L } }, + /* 63 << 245 */ + { { 0xd639e0f3ab9b278dL,0x57f3f8cafa2407b4L,0x6720549f6c11f6abL, + 0x6ad1c608e784308bL,0x62c31e4a196babbbL,0x764b4deed1d36447L }, + { 0xf44efcefaf4407bcL,0x7c1f45dbb3ca82a3L,0xf43e4a8773b952b3L, + 0x145cd2d6ff478bbeL,0x11ef2df450c8e708L,0xa2af06f044491734L } }, + /* 64 << 245 */ + { { 0x8cd6c9f7c90b13f5L,0xec0c187d52a9d469L,0x9c0db0f589b8ad2bL, + 0x692a8db70d9c999dL,0xa407fd03c9f84ab4L,0xa5742fd1cc9a906cL }, + { 0x4813a765c8e72867L,0x9c65943de2e9a10fL,0xca6bf2934fa0a23eL, + 0x1dfa3af7cb1f8d7aL,0x28036f5498d10c53L,0x7bfbcaf20e012c13L } }, + /* 0 << 252 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 252 */ + { { 0xa53f1a104ec177f6L,0x4a2ef9aa3faa5ca8L,0x30efed8532976d13L, + 0xcf5ada165ee692d1L,0x3ceda69d259e7cc1L,0x2aae29e99baab472L }, + { 0x7ee5baef737cc8bcL,0x1717af747fe68dedL,0x9e5c8ddacfdaff63L, + 0x575c8db9cec07693L,0x9afc8ae0fdfb509dL,0x27836d3685651697L } }, + /* 2 << 252 */ + { { 0xa7342f9517eb9264L,0x9264a6a00a8a6eefL,0x50e48bf07471c384L, + 0x729e5ab130827f34L,0x17199191ea779c23L,0xd13ab8539fa9fd58L }, + { 0x7d5799373b1d773eL,0x65f8e7c6d196c3dfL,0x253f7d51e8541725L, + 0x107a793dec720355L,0x1c14d0566aa16268L,0x9dc5fca38bbb231bL } }, + /* 3 << 252 */ + { { 0xf5689c5e12b09f53L,0xc1da32e19e87ff7dL,0x1af879d012eaa533L, + 0xdba775e6d9271e94L,0x60f8507310e63c34L,0x445f3e21a686a24bL }, + { 0xed5ca8fa15bc277eL,0x9839198a364ab7abL,0xe2ee39426d90a7d4L, + 0xe5b3e4cbccd37e76L,0x9013bd08f1412e0fL,0x82f5c532ce999048L } }, + /* 4 << 252 */ + { { 0x61d0e01bf3fe3441L,0x674e52332af47609L,0xd4a4e224b362902dL, + 0x45923c129e0a5d16L,0x4fc2bdd495e580e9L,0x6d1d974ca8c3d954L }, + { 0xaeff1135d0bbeaaaL,0x013ab5b31baafc9eL,0x80907d3eab8f9f31L, + 0xaf2c12166d566c15L,0x0082daba952e6fa7L,0xa46710032df9e03aL } }, + /* 5 << 252 */ + { { 0x91b379c63223d561L,0x8cb7b8cce203417cL,0xd0f44208176b3b81L, + 0xd18c2118aaba5cd3L,0x4aed5c9770794f9fL,0xfc540dc4f4c33894L }, + { 0xb8e6798a0153a8a8L,0x6537dcdf43c4b0c0L,0x1b7eef39ab557397L, + 0x175e3934b7103105L,0x943abf4a82ac89e4L,0xeb1a61f957ffcdb8L } }, + /* 6 << 252 */ + { { 0x99c2b4cd66476227L,0x576a4b0662850cd3L,0x067bb66b5a352b7aL, + 0x3c7d6fc43ec757edL,0x2f69291cb9d36adcL,0xc7c0f3257c9143a4L }, + { 0x768c3c400627fee2L,0xc214d81da8fde577L,0xd86e4b025299ea1aL, + 0xbe46b7e91a2d4005L,0xaf865a169317fa60L,0xfbc3268fcdce2fbeL } }, + /* 7 << 252 */ + { { 0x66fcba52d8fbe900L,0x9f16434c861b3e33L,0xa371b97241b4305fL, + 0xb2d858ce25b6af89L,0xbab07d53275f9e8cL,0x3b5951f8d525bef8L }, + { 0xebf79e3ca1755b0aL,0x4e6256e7b467b1c2L,0x7dbd8b66cba1a659L, + 0x88ea40138b1eb8b6L,0x210ac1b38fa6436aL,0xe93e22c23df40e33L } }, + /* 8 << 252 */ + { { 0x5f79f0df1fd64063L,0xd2d39dd381e118ecL,0xd631a68e11571c5bL, + 0x6d072b4e2474faf7L,0x5e043a6d862a924aL,0xcae58bd8b0fc8d7aL }, + { 0xf54bb7f3b1351f28L,0x4588b6280413275eL,0x81459f4c5909ec04L, + 0xd28cda25abd16460L,0xbb676d018db1c69eL,0xc0056e2dac5036f4L } }, + /* 9 << 252 */ + { { 0x1ce187bf323169baL,0x1dfaef8661ab5073L,0x1893dc7b2ae468b5L, + 0x0748ec86123848d4L,0x0d2877b46a96eb12L,0xb6063e75e9322495L }, + { 0x1cb17189d7d1828fL,0xde41f11944d1b318L,0x7ce0f87610f0b74dL, + 0x2c7c91ee7a98f86bL,0xb641418e750f3ea1L,0xae2cd2e280094054L } }, + /* 10 << 252 */ + { { 0x9f6c6ed598d8e086L,0xa9ad63ca2d3fad85L,0x055b8323fe016926L, + 0x039fbe287b3a8d68L,0x544a8bf5fb6b315aL,0x04b122fb647fed85L }, + { 0x1e9807fa98085b1aL,0xb78a36a771c12696L,0x4ccc1a2cdc22f95bL, + 0x6ff4997d54d1e818L,0xecb5bdc2f08c22dcL,0x6e07e2c146a27762L } }, + /* 11 << 252 */ + { { 0x602077aceaaec565L,0x9dacf68224568aeeL,0xa490fc1e9cfcce26L, + 0xb2ac94b3303218baL,0xc0208604ab33f9aeL,0x801663b6e39a6668L }, + { 0x1defbb42961b0927L,0x688b445e83e318b3L,0x34fe2830c11648e8L, + 0xed56e99360066dfaL,0xa5f30f9a07671eccL,0x02c40260a3222e8dL } }, + /* 12 << 252 */ + { { 0xfb2a11b4ea347db9L,0x2360667e03350681L,0x1aa6e720a02a1261L, + 0xac2bd2eba110bb21L,0x8ab2f9063c9b4568L,0x5f46263d5ace1f17L }, + { 0x97067801eae704c8L,0x35d2637ea715d313L,0x24cdc3d0c77573daL, + 0x6f97cd07e2562b2aL,0x27bcd62d5afb29e4L,0xc38ac1c55d29f5d3L } }, + /* 13 << 252 */ + { { 0xd9c38ba47c88f46aL,0xdd07c4d79946ebe4L,0x908731dcce0e5417L, + 0x43088d11e145839bL,0x9d37419d07b61543L,0x440cdbcd2c3c7c4cL }, + { 0xa6a6fed673216db4L,0x15ce171a198cd32bL,0x198c256974e6a085L, + 0x5fec853f3dc2a714L,0x329250bdd5923068L,0x1d82373c9f6195caL } }, + /* 14 << 252 */ + { { 0xa8e17be53777b2aeL,0x534e3a3bcc284224L,0x7f34ce458192cfa1L, + 0x0009a72966d0e03aL,0xc42053ba524ce1fcL,0x834e98fe6d092e58L }, + { 0x400c65a1c8b0f751L,0x268bfe6f107965ebL,0x0f141c0332e0bc69L, + 0x33bc6e64597a2264L,0x039a4ae9454a0d6bL,0x2cb0bf550b07ddaaL } }, + /* 15 << 252 */ + { { 0x69056cbe63769bb3L,0x710a67d385044d35L,0x971ccbdeea855332L, + 0xd655163a0fd0d210L,0x619c3f9adbb8a8b9L,0xd156f73d49a014e2L }, + { 0xd04ea0a5a129a598L,0xc9c04da6fa2f12eaL,0xc0ed654ae98b3187L, + 0xa254eef6a82f9ec4L,0xe537695fa386a72fL,0x170f1ed4a74eb453L } }, + /* 16 << 252 */ + { { 0xdbe04c3044ce3ad8L,0x995fbb1b4ce8aad5L,0xdbf8b54670911457L, + 0x9e683b5b3f7a1757L,0x7b89a08a9c7bd62cL,0x448865a40b3fc97eL }, + { 0x0ac9abfc3bb01e94L,0xa07760421e756124L,0x0aa6c335d9deed97L, + 0xe270580f72603e08L,0x70857a946c783bb2L,0xa0047774caa929aeL } }, + /* 17 << 252 */ + { { 0xf99a63c5e8c4a440L,0xc7fd1d1419d65168L,0xfb6c21d696d5e80bL, + 0xa4a7304944b833beL,0x093728d5127b1599L,0x9046cbe2c89e7195L }, + { 0x21e2863c146a80d3L,0xb1ac7e1bdd559c13L,0xbe5ba65c72c39063L, + 0x7da5feb87722cbc7L,0x122615d0f17c02c5L,0xd44f477179e5fcb6L } }, + /* 18 << 252 */ + { { 0x0d913830e2d28da9L,0x0465920a8a164385L,0x79959ce1b0ad65d5L, + 0x6c94690759a966d6L,0x4ccb0e5e832c24feL,0xa8c5bee5d6af2a10L }, + { 0x264dcc118c5791fdL,0x719f23ac5b58ce85L,0xfbff8a2f8e54b029L, + 0x0c9240be864e959cL,0x8f7c21733c37c665L,0xfda848d9f164d354L } }, + /* 19 << 252 */ + { { 0x203ea731f35d11f6L,0x90610383f9f9001bL,0xb9d3c302ed97e6f2L, + 0x4c529736c9a67e6cL,0x2e440b1781f6597dL,0xcc798f5616aabf20L }, + { 0x490f50642832ffc5L,0x585e462a7a19b125L,0x99d73e391b06d98bL, + 0xb817e97aab696d7bL,0x9df2f65ac28dffeaL,0xa48dad47045fddd7L } }, + /* 20 << 252 */ + { { 0x2878c20d62e5fc09L,0x419ed2ece7f012abL,0x3bbc853fbaa21e7eL, + 0x412bc3c54844c009L,0xc4b150508b012199L,0x9d160f4c310d5fbfL }, + { 0xcb61b69214f60becL,0x436348c064092943L,0xce8c136e3185cde0L, + 0x97b034f68be5dd85L,0x7697adf92701631aL,0x2ddd86361fa6e8a0L } }, + /* 21 << 252 */ + { { 0xde8c2c963e9ff7faL,0xfdf1e25d8b75bbeaL,0x28ba3be59c146264L, + 0xfc1df52e81fcb0c9L,0xf9341c43af3ba66aL,0xe81c22470d72188eL }, + { 0x2ff00f1069c62b9dL,0x1077962e71498d24L,0xdf35b17ecc34ece7L, + 0x3516c33687eab2daL,0xe71cf7ddc72b7911L,0x6c9233d92c286c56L } }, + /* 22 << 252 */ + { { 0x7ce6389d162754d7L,0x8f03eff514e0d8e5L,0x9fd2c896ef402e31L, + 0x4a4bf70a2195b0e6L,0xe6043a383c8d82dcL,0xd86b647e8bed7c65L }, + { 0x21bc56f4a4c87660L,0x8c99d6270c05564cL,0xd6b82e9014050ee2L, + 0x09bf6a3eb6b11f0bL,0x9704b36731dcd6b1L,0x871c85c85e3d44caL } }, + /* 23 << 252 */ + { { 0x93024430e5236badL,0x4c5872728b883d1aL,0xc265b94bba68d3bbL, + 0x7d8fc82a648d9b7eL,0x57086e6e75ac264cL,0x4b8a157102fc9ec8L }, + { 0x83ae238e86849a9bL,0x2eaad9b8a69acccfL,0x2d82c029d44eaa39L, + 0x8f5b9ed833d7a556L,0x05c83328eea8b609L,0x537069efc3c96005L } }, + /* 24 << 252 */ + { { 0x292f8874b25c4d4aL,0x54961fd87e79f526L,0x949a1fae008c6ec9L, + 0x6ae82f0d525524fdL,0xd1f6f4ef2edbcb1aL,0x41617a6d977ddffbL }, + { 0x6ae38fb71baf0668L,0xa79ea228d538ab3cL,0x70babb05fc44e273L, + 0x247384fbbca85910L,0xdc0e069b6a564959L,0x37a9c5521a7438adL } }, + /* 25 << 252 */ + { { 0xaf2c87828a4b7251L,0xcb5ebfd3c1bc7f72L,0x160b77e560579615L, + 0x297412e3c10f067cL,0x5ad0681ef7df86c8L,0x2e8c63529b3e3afbL }, + { 0x32372cc74cfd3266L,0xb7abc8baa820f8b5L,0x857d545519f34baeL, + 0x5c055ce920ed65beL,0x1d8a59ca537ad6b7L,0x1135adcf7ad88633L } }, + /* 26 << 252 */ + { { 0x47e6ed9530034df1L,0x1839f488321bed8dL,0xb6b67d452ac8a9f9L, + 0x2fe1efc6182e4a63L,0x2da34bde0c1185c7L,0x6e5d1621edfdf9aeL }, + { 0x3bae9db77120804cL,0xf094b0676d986ef3L,0x029c9246853e24ceL, + 0x3abacb1b25a82463L,0x58777e1389c5616aL,0xaedd003b5aeed714L } }, + /* 27 << 252 */ + { { 0x7494e4319da5fb0dL,0xc684d74bee3fd6f3L,0x12fc899403a87d91L, + 0xc4c55e692d6e3931L,0x63e1255896336788L,0x36c297a5f78371fdL }, + { 0x4cd3f9c4a63b313eL,0xd2825e17c543e507L,0xd37e36d06a4e64d0L, + 0xab9559ec11872774L,0xaf168b34880a5d00L,0xb0c916a10c0c3f42L } }, + /* 28 << 252 */ + { { 0xd389397c834eaa9fL,0x2271ea0d2a5532aeL,0x5e59a23ae1f92e9eL, + 0x9f179b8c1f7b91f5L,0x2a1c10028de2dc8bL,0x6ac83e58787a276dL }, + { 0x0facd4756d9d1571L,0xcceaae5e4bf118e2L,0x4e8008b7620fbecbL, + 0xff633fef7a1474cbL,0xfbefea80ce377357L,0xebb9a9460feb7724L } }, + /* 29 << 252 */ + { { 0x0bab441ae9803b71L,0x309ef14684e2e21eL,0x17ccd5b6851b6519L, + 0x8b5e7e300126f470L,0x0560cb9d847eca03L,0xc45850bf11ade256L }, + { 0x08603f5c3c33dbbdL,0x21887bc9708ae545L,0x3bd25ad480014ffcL, + 0x5eb0f89fd3a64409L,0xbca2726b4c3dd83dL,0x611afd2fe4259797L } }, + /* 30 << 252 */ + { { 0xd9cb4233c4f4e0e5L,0xcfc0576818e49029L,0x8e9c8360526f05a1L, + 0x8e83037aa56d6c3dL,0x33507065c47e6742L,0x5ca2c8d8788b5da3L }, + { 0xf355cee9cfb0b6feL,0x0e86fd73973ddafdL,0x27fc6c56d44fd889L, + 0xc9ab416ff7d93f3cL,0x778c3f160d063d62L,0x175e5d920b5085ddL } }, + /* 31 << 252 */ + { { 0xd62406873be63d8cL,0xe8c93b93b80059a6L,0x33bba7dfe065854fL, + 0xcb26543f36b34e45L,0xc17ee58dd2d0c3d5L,0x69752f49bae1bcadL }, + { 0x87e31b429b20106aL,0xc520424b06734eb5L,0x993240afa896d17eL, + 0x5238851bc2762a62L,0xce399f9d506d7dbfL,0xa4822d23040cc7d4L } }, + /* 32 << 252 */ + { { 0xf071c9878fa06859L,0x0083e5311a52390bL,0x845eb12a61483bc2L, + 0x17471d801caf6dd6L,0x7b603616ddc21b92L,0xd38fe0f6b992536dL }, + { 0x433f0652297c25a4L,0x03d4d8fcb1c4bf41L,0xdf617386a9adf49bL, + 0x4bfeb3992cb2944fL,0xbf288427b3d9c076L,0x17818c3e965b4576L } }, + /* 33 << 252 */ + { { 0xfbcff79f6df360c9L,0x342f9ded2bd94c22L,0x2dc5f999283f2300L, + 0xbea18d9893cc3330L,0xc197176269a7da4eL,0x72de17ee93ce69a3L }, + { 0x6c354a6184170a91L,0x031ce0debe47ef92L,0xbf256fd418658739L, + 0x0395088a0d037d9aL,0x61179c42c5a05970L,0x0d5a9f7db8b6ab64L } }, + /* 34 << 252 */ + { { 0x18be1d605a44a8dcL,0xb512d945f1d18ee0L,0xd2e1f6623af39ec0L, + 0x440469136c223676L,0xe7a860836a60a4d8L,0xaefcfc2dc7e09d3bL }, + { 0x175817fad685c9b7L,0xe20b6c9e4b9d0557L,0x9212e7bb51fe560dL, + 0x748aafb7608b53c4L,0x86186d4fd9b06850L,0x4cc6041376512c08L } }, + /* 35 << 252 */ + { { 0x2d5be3b00c127e46L,0x8c6f38fad9b04e47L,0x49c444098736f31bL, + 0x5469ae47f53aa908L,0xd84856f3492fd120L,0xd04b1fa20725e199L }, + { 0x50c2e80a8e7056f2L,0x415db04c9ba2e259L,0x8e4c56ae2eb201e0L, + 0x449e4d9e5082ce94L,0xb5ff077a7345459dL,0x96d10f1e07330e72L } }, + /* 36 << 252 */ + { { 0xac77126e3b3094b7L,0x7c1e7673bdcb616fL,0x90491f8176993114L, + 0xf17c08a8cc8da63bL,0x972a3bffaa050364L,0xdef45b7f65a9cd57L }, + { 0x105ec5ba2b9b889eL,0x7066821150f7a61eL,0x11daa9dbb1d63a40L, + 0x6065451007790568L,0xfaa219cebc2b6d2aL,0xb1b8ace93e5163dcL } }, + /* 37 << 252 */ + { { 0xf8042ae2859b0f22L,0xd8a5d3a200d8bb8cL,0xe85c596189faae14L, + 0xb7d636f906611c0aL,0x35b68bbdd2bc8957L,0xc86f5be5b7cf558cL }, + { 0xb602a00369c17e74L,0xc39479cfd8a1fc01L,0x6dca5c81f733237eL, + 0x9c8cefd41b2e2cccL,0x2e32a323caacb4b8L,0xf7406874ad639090L } }, + /* 38 << 252 */ + { { 0xea3a358e24c1bbfdL,0xfd32af33571400aaL,0x2ec3d44da413949aL, + 0xa0d8594a7bd121f8L,0xb32997a1d6b6153fL,0xa0f48d98b9469c6eL }, + { 0x236b7a18fba15481L,0x49dee3bd98ff970fL,0xbc27ac7a7ee97875L, + 0xd1acf2be28ac6279L,0x92e7ef02514c8328L,0xb2d7a8304f48b497L } }, + /* 39 << 252 */ + { { 0xcaad0554d95946a9L,0x992268c973ed1281L,0x6c0b1edf7b1b25e1L, + 0x4de2d9f81d6e73dbL,0xe12a4f1c5a2950a9L,0xe0cdf7af36ac18fdL }, + { 0x16e7332d1abcc9f5L,0x4dccc1505bac1c75L,0x1b48bbc141f8c231L, + 0x3702cc2693692a4aL,0x9e9e53dd311c5dabL,0x27bc006cfe5d9fd3L } }, + /* 40 << 252 */ + { { 0x2bb798ff689f43efL,0x5813e4415f26ec54L,0x51f64c495005c929L, + 0x60e213a54b42e417L,0xc152844262cc3734L,0x6ecd6c3b09d994e1L }, + { 0xa6e72f7183dd047fL,0x3836f663b0019803L,0xbcf1265b257493cbL, + 0x59b15ff09e62d78bL,0xaac5ed5b6cb92ecfL,0x37e6ad7d9662651cL } }, + /* 41 << 252 */ + { { 0x04743bf8b224f6c9L,0xec04b641ae33b1caL,0x6301f51623a76fccL, + 0xf1aa954675e15fe9L,0x878c64ecd95c1972L,0x033df5ee3ba7578aL }, + { 0xe5e9ff7c47f4721fL,0x9b3d93fa03eef7e9L,0xcd0be6ad573deaa6L, + 0xf377570f3bbc8a16L,0xffdc04c161c37393L,0xd9eee46dd26d659dL } }, + /* 42 << 252 */ + { { 0x33f933604d4b7317L,0xee44b3e02fe482ebL,0x5a96870480f1fde5L, + 0xdfd6293b5510952fL,0x2abdc1989cc0af6aL,0xe608e2769ff45aedL }, + { 0xf408670e3247e796L,0x3144153535fe07c4L,0xa941f96e2870053dL, + 0xbe908795ef6383adL,0x82b620a63560fdf0L,0x2c1cc1ae135de5c8L } }, + /* 43 << 252 */ + { { 0xa829397c727e5988L,0x305659bac6239b1bL,0x9b13701200392cb0L, + 0x4eb1ddf376091862L,0x68b64b19202bdd8aL,0x56c427c5228071e4L }, + { 0x354b1beac3375accL,0x94a45b4e54e1194bL,0xf528df0178095edbL, + 0x6fb0867146fb9ec8L,0x977efc84c555bd48L,0x8230d6f7c268a20dL } }, + /* 44 << 252 */ + { { 0x003d4004b8d81c0bL,0xd3d5048f4168a407L,0x7748ecacc6675bd9L, + 0x9dba4539e2612cf4L,0xa5ebbccfd8770b8fL,0x206b4a9aadd90558L }, + { 0xe446ed9c81b5c103L,0xcd2434184d2199dcL,0x0840f6eacb0d70d5L, + 0x6fbbf1b43107367bL,0xde9444f7d29335c8L,0x33ef004c66252eb6L } }, + /* 45 << 252 */ + { { 0x10eac97aa5a6546aL,0x6129392fe231f95cL,0xfd41bda100e2aae3L, + 0x5b1f93299d8c6288L,0xf1d2fc9246b7df40L,0xbc6fbacfc5df62bbL }, + { 0x64885d924b5af011L,0xe4f3ade883461896L,0x644ce7a7a4a62e43L, + 0x74c9d145337b2730L,0x69d714840f83222aL,0xbfbc594ec27c0fdbL } }, + /* 46 << 252 */ + { { 0x3263c0517ed92916L,0xc039b94884e3f519L,0x54aa433ede89de6dL, + 0x92f76292c0971a03L,0x8457b2312550a2e8L,0x46ab1f0f11cfcd9aL }, + { 0xd97b95c1c6d53077L,0xe8db11d159550599L,0x2092c81385ea4b32L, + 0x149b6b2cb7ced408L,0x2ada6fa482b9b22fL,0x53a5576a25877963L } }, + /* 47 << 252 */ + { { 0xa1e2c2a8195ad455L,0x65e90a3de7f61038L,0xb01eaa52ec623680L, + 0xfad0f9f110302efaL,0x9e544b5449274409L,0xfc9037de8c3a0925L }, + { 0xbcf196fcfd139cdaL,0x0a1f747c4f6a2cdcL,0x580a9abab879fe3eL, + 0x08a20f1c5ee74778L,0x7c9be7de464c5271L,0xa4a1972918e85a09L } }, + /* 48 << 252 */ + { { 0xce23a19aa17e560cL,0x6491b95f62550e2bL,0xc72000121d15a005L, + 0x15fde735f4355a1fL,0x3849761f607f7807L,0xcbe322d018204691L }, + { 0x75756e4ea95e8e91L,0x365959fe817a9b8eL,0x631232763d4ce3dcL, + 0xa769d2fef1d66e00L,0x8624ddbac28829e6L,0x03274297d2df06efL } }, + /* 49 << 252 */ + { { 0x2ad21bdadf3b1368L,0xf4f9d5270b3001abL,0x10182c5557ecb528L, + 0xe00db71565372a5bL,0x2018e0ed74f2bd83L,0xa11b47066175efb4L }, + { 0x3172264722d565cfL,0xb20c27ab2f0faac9L,0x4ca2982a6260f995L, + 0x3850ef89b7085c6fL,0x5b4a6e235f0d45a3L,0xde562df9b7523682L } }, + /* 50 << 252 */ + { { 0xb34ecab233bb63f6L,0xe6cd56a202944c4cL,0x2690cc39489a8d88L, + 0xcdfe368a4fe612dbL,0x23069ca5e9e9f7adL,0x7b87105cc07d742bL }, + { 0x5114645a8b58ea8eL,0xd31fb4821829e8aeL,0x5e235d95c4b28520L, + 0x2a1cda885c2292d2L,0x95d77447ee925b6aL,0xeec419a3df18845dL } }, + /* 51 << 252 */ + { { 0xb8903f10be9ffa75L,0x8bf7fc786432dcc3L,0xcf3f7cf15d028549L, + 0x7684baf29846f2d9L,0x4c580edbe9e063deL,0x0ac5c3edf2d70321L }, + { 0xb9ba10e184c5d96dL,0xbb854b39d7aaabafL,0xe29d66964793c87aL, + 0x7b0fe1d448285ae5L,0xa143454df0121733L,0xa286eb043aa5ddc8L } }, + /* 52 << 252 */ + { { 0x8e4dcfc88c93bc5fL,0x9f96d60a1b233295L,0xae5262e91d447dcbL, + 0xafe58396541d46c4L,0x3e733c2636ff8f80L,0xcb36a37748b81037L }, + { 0x9bcbfa9fc406ef17L,0x57a6e28006fb128aL,0xd86b44db9a771eb1L, + 0xc7ce106e62545a4dL,0xec6818a6b254c908L,0x4b8d3fc550feb342L } }, + /* 53 << 252 */ + { { 0x8faa39c8b609ef4cL,0x0209b3a7d8225cceL,0x11254c211feffc0fL, + 0x64930dcdc1e42ad3L,0xf5b058eb1cbb39fcL,0x2f870e3341cb5065L }, + { 0x61b3611cf7663f95L,0x981890b637941996L,0x00c42b0908dd6854L, + 0xac42af5de17da075L,0xaf3a394c282b8d53L,0xb53b3b245d8bab96L } }, + /* 54 << 252 */ + { { 0xe17c9d98d90f0c83L,0xdd4aa8ac6d984408L,0x94b6fc50f71aef46L, + 0x2e6b5d24f0a2009eL,0xcb9d9cd17d8d75e4L,0x5e732a5b962a1708L }, + { 0x9d774f1c7fd01089L,0x56bc35aded95094bL,0x6844220bb9c797d4L, + 0x40021d8e90ace48fL,0xddc769c5701baad0L,0xe23e8f9e333ac2deL } }, + /* 55 << 252 */ + { { 0x6cf6faf6e92e42bdL,0x759dc78b0d1e6a0eL,0x18fd55ff11532759L, + 0x04a306d7e9af0c07L,0xd7febf615ef7f82eL,0xaa04f1dca65cae01L }, + { 0xb084407c16442bc2L,0x17ab4f74f874f10aL,0x236368d40fb6cea7L, + 0x451ea8206f66813dL,0x4a61097b1760e6ecL,0xa8655cfba01bdd2aL } }, + /* 56 << 252 */ + { { 0x52fced3116f01d7bL,0x88c6b172daf046aaL,0x1a189403fe7a338eL, + 0x39741ecd61798b1eL,0x6a47b0712934b879L,0x3b1a5dd1828d1e9dL }, + { 0xd4bd48487f35a7efL,0x71774b5bc1eebaf8L,0xa86471e5d55344baL, + 0xfbf145f17b8a483aL,0x70f9b214aa53802cL,0x995af93010b066e1L } }, + /* 57 << 252 */ + { { 0xd2714b97aadf25ceL,0xb95c54162a7643f1L,0xae7dc619ba2f1939L, + 0x30e5d013b0db537eL,0xfcd1a456753f0813L,0x19f7117cef62925cL }, + { 0x40a22e35423d3c56L,0xb0271e9926a5534dL,0xc19f703cc76c9a1eL, + 0x9b8fe585560bee08L,0x48c7797d3cc772aeL,0xabd2148e10bd6393L } }, + /* 58 << 252 */ + { { 0x046fb36cc34a7ba2L,0xd42e56d42a61a8a6L,0x16b8fd2d3d4b1184L, + 0x6f9e85a26da29888L,0x1ff7324bdd683c49L,0xdb3746db27bb8e2aL }, + { 0xa7e586e684be7f99L,0xfbd0c0ee61740d6bL,0xb80509bab2071320L, + 0xb5bf09fea3f03641L,0xe872cd854971e39fL,0x9bed91c0ce2b2db2L } }, + /* 59 << 252 */ + { { 0x85177e7ca6bad7b2L,0xd5b1f0901425b611L,0x6b5f16223c4bfa24L, + 0xde34a692def66d8aL,0x96c0663ee8a1b7a0L,0x43eb91ed459c8bbbL }, + { 0x6cc7e78b7d3d8b92L,0x3c9da7efe0338ba8L,0x18d7ab00e21360b4L, + 0x0785ca897f9df01aL,0x5bcfb8302220f1efL,0x8c61a3bfa52bbf42L } }, + /* 60 << 252 */ + { { 0x4dcc3b82196c21d2L,0xef0e0e1e61071fd8L,0xa2a28c3b35a013f7L, + 0x7550d3d7f6b58f80L,0x0f1fc9d58101742bL,0x027874f055982d5dL }, + { 0x5a10b98c629bc409L,0xa28a1b2baf494679L,0x84afdbe1b96578d8L, + 0x201a8062d427238bL,0xe321ee2d89fffdb0L,0x0b304de4fb89f171L } }, + /* 61 << 252 */ + { { 0x5d8e16c0d7700dfdL,0x336e30fa24260211L,0x7ba72067ad557ce2L, + 0xcb388c3169621e0dL,0xcf6b7d813dbf7ba3L,0x7bfe43a91cbd216aL }, + { 0x6c40516adcffe0b5L,0xe77507f083b7ea33L,0x5b5cda074ba1fc8eL, + 0x46860dd296c6d2c6L,0x4716114f0eb5013cL,0x05bd136898c3642cL } }, + /* 62 << 252 */ + { { 0x7fac263852ca5d3bL,0x35e5d8d0f5a2a596L,0x4c7129210011a394L, + 0x400168f7a9c417e0L,0x220994b447b77b44L,0x01a7580af548c0adL }, + { 0x59870c2afe292ad7L,0xdda35a1a2abf8e7cL,0xa3082dc4f16d0c7cL, + 0xd4dcd5f38557c9e8L,0x38d45cc6ba7f0f99L,0xdefc0b1da7c18157L } }, + /* 63 << 252 */ + { { 0x5db2ed891c43e426L,0xeed247709adf4a50L,0x0b5e19765c8b90e1L, + 0xe9db695ffa18542dL,0xc16d3bfb8d043dc5L,0x5c5feb44f11d3430L }, + { 0xd44e3d57365593c0L,0x1338f26c8796edb5L,0x789b325e051ca644L, + 0xaa93b75d1579c2bbL,0xa39a8ec57842c0b2L,0x84225134550ddf11L } }, + /* 64 << 252 */ + { { 0x9ec1159727a28f9dL,0x96f2c44bb847cd83L,0xacf794e131fca111L, + 0x438b917896076f45L,0xad71035b51732588L,0x2db32f32a5d910daL }, + { 0xefaad0e8fe1cc184L,0x6f0360b52e00bbedL,0x99402426474ce326L, + 0xd53b687a2aa270daL,0x96c8bb78d78fa6ebL,0xd07f3bba6e699411L } }, + /* 0 << 259 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 259 */ + { { 0xfe1f11ad389283baL,0xc87e20b60cd91b22L,0x99d0015a3c5babf8L, + 0x7e795b4d5929ea0aL,0xc9cf68331dfb7b7eL,0xc1c07346a64992e8L }, + { 0x0b7e0dd89889746dL,0xa89d7b461c43ea4aL,0x64023cf034f02b96L, + 0xf7dd410a5662f0c8L,0xa3bb6088a1058ccaL,0xedb25dc34e7801edL } }, + /* 2 << 259 */ + { { 0x140a0f9fdd93d50aL,0x4799ffde83b7abacL,0x78ff7c2304a1f742L, + 0xc0568f51195ba34eL,0xe97183603b7f78b4L,0x9cfd1ff1f9efaa53L }, + { 0xe924d2c5bb06022eL,0x9987fa86faa2af6dL,0x4b12e73f6ee37e0fL, + 0x1836fdfa5e5a1ddeL,0x7f1b92259dcd6416L,0xcb2c1b4d677544d8L } }, + /* 3 << 259 */ + { { 0xb6f8d615a033cccdL,0x6aabb87cad75e31fL,0x30a03029a4646d1bL, + 0xfad497e6e6547805L,0x4b9d45c3ba291f12L,0x0f74909bca059918L }, + { 0xdece1fb0b5a181b7L,0x973f74413be1f21bL,0xcc919af36b06839aL, + 0x14427886ad57101fL,0xc63a79882bbc8022L,0x04cf807426742ccaL } }, + /* 4 << 259 */ + { { 0x279fd119da1c29abL,0xbd0688022b30d40cL,0xd8f57da4da44105dL, + 0xb1814b7a28223fe1L,0xcf2fd241e06f2d2eL,0x99003a0201dfde06L }, + { 0x876a31affded7e4bL,0x1efaf8272f725094L,0x5117d608493a6a0aL, + 0xdcec8088a88c03e7L,0xeae1d352ea916897L,0x8cdc28106e8b2c57L } }, + /* 5 << 259 */ + { { 0x52fb8e6f7041b903L,0xd7fc4b5b2ad368a3L,0xf16c61d2f890136fL, + 0xeee859dfbb52a90bL,0x1651b16b3f8396cdL,0xfbced93eb6462918L }, + { 0x1cb3126c4b6bfaa0L,0x65dfc76cc7c8fd16L,0x225b9c21bb46a3c9L, + 0x6c3457577f64f9ffL,0x6f65fadd57c297ecL,0x72a630eae5c5bbbdL } }, + /* 6 << 259 */ + { { 0x0254486d9c213d95L,0x68a9db56cb2f6e94L,0xfb5858ba000f5491L, + 0x1315bdd934009fb6L,0xb18a8e0ac42bde30L,0xfdcf93d1f1070358L }, + { 0xbeb1db753022937eL,0x9b9eca7acac20db4L,0x152214d4e4122b20L, + 0xd3e673f2aabccc7bL,0x94c50f64aed07571L,0xd767059ae66b4f17L } }, + /* 7 << 259 */ + { { 0x25cb1f44f4fefeeeL,0xe1a6b6c8bce660c7L,0xd25459a00d2118e4L, + 0x716532dafedf8f98L,0xaeff37d492cfb480L,0x45919f7da1453c41L }, + { 0x5100afe08d8836a6L,0x2ec20fd7b35d4fe0L,0xce8eefd1c00b7d66L, + 0x922d535d6b82c7ccL,0x5eb38f3fddd8d80aL,0x7eae5305213ae465L } }, + /* 8 << 259 */ + { { 0x09f8bb0654e93c1eL,0xb0045884ad81e27cL,0x26ebc7b6076e13ebL, + 0xbda0b5535d5ac07fL,0xbcb8132248ab69e6L,0xd3847d2e1c0f21faL }, + { 0x7a466528c834d740L,0x6c67a79ae0823ff2L,0x85dd11864c1d7cb8L, + 0x096f849f2d081301L,0xb4f503dd8a5ea0f0L,0x71ee0889d1bf69b2L } }, + /* 9 << 259 */ + { { 0xd7a5f9feaa074b9eL,0xbeda44032fd2468bL,0xca3956309c35ffcaL, + 0xb02a1f592de68348L,0x946b0250903b35c7L,0xe9984f24634e9c91L }, + { 0x4f70d22fe7303041L,0xf8a05d7fb68b0051L,0x0ce7af4fab5006afL, + 0x1011d1644a6bb502L,0xdf959199da4ad1a6L,0xc468cddf1e146f24L } }, + /* 10 << 259 */ + { { 0x40336b12dcd6d14bL,0xf6bcff5de3b4919cL,0xc337048d9c841f0cL, + 0x4ce6d0251d617f50L,0x00fef2198117d379L,0x18b7c4e9f95be243L }, + { 0x98de119e38df08ffL,0xdfd803bd8d772d20L,0x94125b720f9678bdL, + 0xfc5b57cd334ace30L,0x09486527b7e86e04L,0xfe9f8bcc6e552039L } }, + /* 11 << 259 */ + { { 0xffd4fd775b5c7501L,0xc43e409ee0600e93L,0xd2a18cba7d522993L, + 0xbc2e14dc17c84d1cL,0xe84deb43c1eee29dL,0xe65326f08d691cbfL }, + { 0x89760cdd77b726afL,0xb91c302a577b30acL,0xc6a742906e145891L, + 0x95bf3e913be85cc7L,0x2ec0285b9815e0edL,0x5b4be6da8aa3ec95L } }, + /* 12 << 259 */ + { { 0x4ab7a22c02a2d1e6L,0x967e19a31371d5a4L,0x20f59f95078de336L, + 0xfd28fa36f7869245L,0x1de42581cbf1d96fL,0x2e0127d7366e1f0fL }, + { 0xbc65fa9d2258c741L,0x1f2f3356dd6d65f8L,0x06384f3a4a0822a9L, + 0x1c81332bfd05a0aaL,0xbfb12361d95ee3ceL,0x180aaf0642016d00L } }, + /* 13 << 259 */ + { { 0x329ff57bf08c171eL,0x6cd8122a543af2a9L,0x5209a3d65b2f8d96L, + 0x0285b128ba90c881L,0xeb5971ef61b43c8fL,0xf1ec473ccfd759b8L }, + { 0xd2a79fb712d58e1eL,0x695f4877fdb6497bL,0x8bf5a4251f1a0f24L, + 0x3e79a0dea5c8a189L,0x9c8ada35908b7ae3L,0xd8b8622c5000f772L } }, + /* 14 << 259 */ + { { 0x3b75c45bd6f5a10eL,0xfd4680f4c1c35f38L,0x5450227df8e0a113L, + 0x5e69f1ae73ddba24L,0x2007b80e57f24645L,0xc63695dc3d159741L }, + { 0xcbe54d294530f623L,0x986ad5732869586bL,0xe19f70594cc39f73L, + 0x80f00ab32b1b8da9L,0xb765aaf973f68d26L,0xbc79a394e993f829L } }, + /* 15 << 259 */ + { { 0xdd01a72b6024f09fL,0x192c8254378d12e1L,0x03ec536bf5d8b8d0L, + 0xb0c4c01873806514L,0x7d3c5f5614d202b6L,0x7c2a7c5c6febb3e2L }, + { 0xf2fa07d4f9f2b562L,0x6f717b003ba2a4faL,0x1ff95d598f452226L, + 0xe4b3f6ba867c1cf1L,0x907a648a5d0944ecL,0x1ed480007f64f9b9L } }, + /* 16 << 259 */ + { { 0x0a159f6295b3287dL,0xb18f875948cecad0L,0x6d1ab8ee1661a23fL, + 0xcae7f40ec95c41b3L,0xbc3d20407c51eb56L,0xa7527283e8754250L }, + { 0x815610561f9e668aL,0xb8aa7296900f5912L,0xabdbc1bf6af2a00cL, + 0xe9a942542d0a56c0L,0x4774a7b77bc8959eL,0x0a837ff019cef2f3L } }, + /* 17 << 259 */ + { { 0xd9c3f4ea3c696c76L,0x3aff88caea5878bbL,0x2b01171b09dda122L, + 0xa61d5ca0f599cad4L,0xba0c19bef49772c7L,0x8ee9acc25001f977L }, + { 0x15fd3a172549a25aL,0x8f1a25d82263bc97L,0x372b88434db4af00L, + 0xa613b31f4f912925L,0x7d83041a0b64efd9L,0x897c521ca7d5f6a8L } }, + /* 18 << 259 */ + { { 0x9c441043f310d2a0L,0x2865ee58dc5eb106L,0x71a959229cb8065cL, + 0x8eb3a733a052af0fL,0x56009f42b09d716eL,0xa7f923c5abcbe6adL }, + { 0x263b7669fa375c01L,0x641c47e521ef27a2L,0xa89b474eb08ffd25L, + 0x5be8ec3ff0a239f3L,0x0e79957a242a6c5aL,0x1dfb26d00c6c75f5L } }, + /* 19 << 259 */ + { { 0x04c6a90ae75c82afL,0xe9183100f2488abdL,0xef4b378b111a46baL, + 0x77ad9ef502eaa62eL,0x61229a6205e81570L,0x06e26a2db474c367L }, + { 0x0bb2ea7e7113f2d4L,0x8ddc6f887f101386L,0x93fe2d7ef4de63abL, + 0xc3d038278f44e271L,0xe9f9f48ea94e641aL,0xb84b817b4962467dL } }, + /* 20 << 259 */ + { { 0x36f3a3d8a084fae6L,0x759835899a9b0d95L,0x70722186cc80fcb6L, + 0xf28ed0c796d84c04L,0x95a32263ffb63f90L,0xdd7d60a098766034L }, + { 0xe193a31f1d5c387cL,0x6c5eca7eb8310f8bL,0xfe61d523c083ff47L, + 0x90c832dbcb2944e9L,0xa9f3f293593334b7L,0xe6cde2e12d7d1c33L } }, + /* 21 << 259 */ + { { 0x5637d16b065096b9L,0xee3a2ad04770d39eL,0xae605cb56aa94587L, + 0xc2d71dae9b600c6eL,0x672ef30d76a87e0aL,0x74d5bebe567e0817L }, + { 0x38f591310eb8ca48L,0x92b74866031e099fL,0x654858ca785f77eeL, + 0x264b6b7b830be443L,0xb167203d57103903L,0xa73d5d545ce2b21aL } }, + /* 22 << 259 */ + { { 0x2fd97b9b9dfbf22aL,0xdec16cc85643532dL,0xdf0e6e3960fee7c3L, + 0xd09ad7b6545860c8L,0xcc16e98473fc3b7cL,0x6ce734c10d4e1555L }, + { 0xc6efe68b4b5f6032L,0x3a64f34c14f54073L,0x25da689cac44dc95L, + 0x990c477e5358ad8aL,0x00e958a5f36da7deL,0x902b7360c9b6f161L } }, + /* 23 << 259 */ + { { 0x5e8eb8f0636a77efL,0xe14290f8970c3a7fL,0xfe6f6acdfa1784c0L, + 0x98671d33de6a46b3L,0xe7fd88722ae5a76eL,0xed971ecbae4f7d60L }, + { 0x1d90dbd88461b895L,0x3f979ab4bfaaac13L,0xe06ccba1dbd3379aL, + 0xb53b04ba108c4487L,0xe42609dd38d2730dL,0x0638fe82e81c4594L } }, + /* 24 << 259 */ + { { 0xbd079cf1f144b6ccL,0x7f86e29bb4f4a764L,0x5b08b290f21f9cbfL, + 0xada0c85b75e3aeb9L,0xd0789f8b6666c2dfL,0xcf5d8a8cd71ec2ecL }, + { 0x6f7780c3e7e4364bL,0xdd9a652985d2eb75L,0x8222f66bd952a38eL, + 0x9dd5f7eb27260a29L,0xce49b34457947178L,0xaa215f82cdda7e39L } }, + /* 25 << 259 */ + { { 0xcb91619d1419a50fL,0x44a22eac65dc4c84L,0xc199f93701a92405L, + 0x3749a33198045324L,0xf1676e8abc57764dL,0x922f9460a00c33eeL }, + { 0xfde98e63d3766db4L,0xae08a82efd5ffb6aL,0x6a9834537c0c6ae7L, + 0x0e9a919a54f34cdbL,0xf37a95e8fd88d765L,0x927427d4228a1affL } }, + /* 26 << 259 */ + { { 0x454ab42c9347b90aL,0xcaebe64aa698b02bL,0x119cdc69fb86fa40L, + 0x2e5cb7adc3109281L,0x67bb1ec5cd0c3d00L,0x5d430bc783f25bbfL }, + { 0x69fd84a85cde0abbL,0x69da263e9816b688L,0xe52d93df0e53cbb8L, + 0x42cf6f25add2d5a7L,0x227ba59dc87ca88fL,0x7a1ca876da738554L } }, + /* 27 << 259 */ + { { 0x277c833f57c7bf99L,0xbbb84d1d0b301f02L,0x11435cb20713a92bL, + 0x8ae509702d02862bL,0x4edc66bdaa7b0660L,0x5bc0d893d6382c91L }, + { 0x7992c5d3b94a6343L,0x1cfee04147b19345L,0x57963034964ed646L, + 0xd7af0cac3de7b0e9L,0x5123dd8d481b940aL,0xe1d23ad8ad7d3567L } }, + /* 28 << 259 */ + { { 0xaa44b2863004db31L,0x86f43d7ad43e4430L,0xdc4874cdb0b0240dL, + 0x79986a23adc45a06L,0xbb275b443cee4631L,0x21daee8a63a217aaL }, + { 0x1e7c5397d7b25c02L,0xe677d3cbc5e668faL,0xc7c84e28ed51b4bfL, + 0x7ca19e99923e5408L,0xc6f8a595c3f832e7L,0x2d0a789c5fb049a3L } }, + /* 29 << 259 */ + { { 0x49702e622b82b466L,0x365d4f6afb8fe508L,0x2f5234e044884733L, + 0xcd527f345dd0a3d5L,0x371b02544bf4033eL,0x7d84ad677e3212e0L }, + { 0xaf48fd79e69d6b81L,0xd126f83a7a44bfc6L,0xbb8d2b57b2cc4e93L, + 0x5f62a3d5eb60ec5fL,0x7b37da33aa76c824L,0x7593d06b89a682dbL } }, + /* 30 << 259 */ + { { 0x3fa5c1051cac82c4L,0x23c760878a78c9beL,0xe98cdad61c5cfa42L, + 0x09c302520a6c0421L,0x149bac7c42fc61b9L,0x3a1c22ac3004a3e2L }, + { 0xde6b0d6e202c7fedL,0xb2457377e7e63052L,0x31725fd43706b3efL, + 0xe16a347d2b1afdbfL,0xbe4850c48c29cf66L,0x8f51cc4d2939f23cL } }, + /* 31 << 259 */ + { { 0xc342ed50dd305573L,0xe3055013de86c6c8L,0x0ae84d9776deedc4L, + 0xe8e70cbfd1274b52L,0x4bb51dce32e87f7fL,0x32de3672f3748177L }, + { 0x528af91681722d55L,0x459af071a5f2ce91L,0xf6883bbdc685a670L, + 0x398657f9eeb836b8L,0xa08a793eb9278bd7L,0xe786426bcc09e408L } }, + /* 32 << 259 */ + { { 0x114a25c844922386L,0xdd084d446d4e8b57L,0xc49b68411e7bd7deL, + 0x5b0359fad6da54dbL,0xa6e6e5f93f0da321L,0xb65ec55cd640a87eL }, + { 0xc1a4f6ceae64020eL,0x91e29cd2088e1337L,0xf44ceb8e3c0a631cL, + 0x0205b11db756445fL,0x04844e845bc8880eL,0xb630ddc0b85e00d3L } }, + /* 33 << 259 */ + { { 0xac512659c6ee46b6L,0x0c92e402ca82b384L,0x81d79049194fba3aL, + 0x9b68376c36b42b32L,0x6dc1c80cf6b410b0L,0x509fbe9196b2b328L }, + { 0x988fedd6fdc783b1L,0x9f34cd87436ed055L,0x29f243648bb8809fL, + 0x6962ca24b8dc8b68L,0x076cb7b931963ff9L,0xb609ad792b915093L } }, + /* 34 << 259 */ + { { 0x169e025b219ae6c1L,0x55ff526f116e1ca1L,0x01b810a3b191f55dL, + 0x2d98127229588a69L,0x53c9377048b92199L,0x8c7dd84e8a85236fL }, + { 0x293d48b6caacf958L,0x1f084acb43572b30L,0x628bfa2dfad91f28L, + 0x8d627b11829386afL,0x3ec1dd00d44a77beL,0x8d3b0d08649ac7f0L } }, + /* 35 << 259 */ + { { 0x4aeb3f870af947c6L,0x9ac9ff2791d090c1L,0xeaaa7e0fcf698277L, + 0x737ccc2ff09d6155L,0xd5d4bde86753cc31L,0x3b9063477146d4a3L }, + { 0x75106d8959e32369L,0x7a8ee281645999b3L,0x9184fb5cfc3f675aL, + 0xaeebd0423ad4e239L,0xcff8f73e12f449d1L,0x2771bec17339eb4bL } }, + /* 36 << 259 */ + { { 0xf783db44e6674091L,0x57d0eed31e12a3b7L,0x62d2762af3474f91L, + 0x3d122edf0562af71L,0xaf78dbf77f4bbcbbL,0x8fbbbd97e55f0654L }, + { 0x77e117b004bac36eL,0xbbf6bd463ec582aeL,0x553acd10017eb463L, + 0xfc521187fdfd820bL,0x73211103089b6829L,0x9d3fe7ad7e01e5c0L } }, + /* 37 << 259 */ + { { 0x12a8b7ac04c6babfL,0x7b23210557d2cf63L,0xe03831868f21ad0dL, + 0xd14c2b95acdc2184L,0xe7bd19fcadc9bae1L,0xe2dbabf2edea5c71L }, + { 0x009a3ab78f3f4266L,0x159691e17f8ff74fL,0x5ae666aa22f40f41L, + 0x72fcdc88512387bbL,0xa74e8fb841516c92L,0xd9cee7833b15bf07L } }, + /* 38 << 259 */ + { { 0x00a93daa177513bfL,0x2ef0b96f42ad79e1L,0x81f5aaf1a07129d9L, + 0xfc04b7ef923f2449L,0x855da79560cdb1b7L,0xb1eb5dabad5d61d4L }, + { 0xd2cef1ae353fd028L,0xc21d54399ee94847L,0x9ed552bb0380c1a8L, + 0xb156fe7a2bac328fL,0xbb7e01967213c6a4L,0x36002a331701ed5bL } }, + /* 39 << 259 */ + { { 0xd76b43661c8bd222L,0x041c2b87b97e5b19L,0x7b80f8d7b47c4282L, + 0xfec3d476d0dbc7d3L,0x84aa69712753a830L,0xe5f336079ec85e26L }, + { 0xa425d60cfe2374b3L,0xf88b90f14d953af2L,0x80370e7857ca6c43L, + 0xe07d07176f4d6d7eL,0xe60639401e61ab85L,0x171a2bf632a4c829L } }, + /* 40 << 259 */ + { { 0x38e4168d4f8b5073L,0xf1ddc53fc521849cL,0xd2bf515bab917df1L, + 0xab76b71a697d45c1L,0x20fdc6c7cb566a9dL,0x3843bf838a031cf4L }, + { 0x9a2d89a58a028b04L,0x52f3cb1922a908cdL,0xb5df9c2b7b8723baL, + 0x5142f51060374a3dL,0x949b719800bd9f30L,0x4b7cda16c9b86959L } }, + /* 41 << 259 */ + { { 0x22a32c50d154fc49L,0xe12242de66357eb7L,0x67571eb89f19ef9fL, + 0x2ed01f28b92b20e1L,0xd4fd6efb6cd439c0L,0xc4036cfc03b057fbL }, + { 0x605fab271cc48da5L,0x3cbd7a071416a3e7L,0x9cfe7161714bf173L, + 0xbd03d786a77eb0f8L,0x1423516678b8f5ccL,0xecc56e02f0523f3fL } }, + /* 42 << 259 */ + { { 0x20b1632addc9ef4dL,0x2a35ff4c272d082bL,0x30d39923f6cc9bd3L, + 0x6d879bc2e65c9d08L,0xce8274e16fa9983cL,0x652371e80eb7424fL }, + { 0x32b77503c5c35282L,0xd7306333c885a931L,0x8a16d71972955aa8L, + 0x5548f1637d51f882L,0xb311dc66baba59efL,0x773d54480db8f627L } }, + /* 43 << 259 */ + { { 0x2be2f1d67d64ddbbL,0x3afc2fad6edd7e04L,0x9a57c16d9e797442L, + 0x1efecfde9c16769bL,0x86523c3571b2940aL,0x1a9b30035825d17cL }, + { 0xa25e99beeefc4d7cL,0x8521b49fb50df9eaL,0x10bd2309bd8f3b06L, + 0x1f892e95ea82e80cL,0xf741621c93585741L,0x95687594f5e5087aL } }, + /* 44 << 259 */ + { { 0xbcdd3a3146f684c5L,0xbc8be436f700b0cdL,0x33005e370de75b7dL, + 0x527a8a2c3bd820caL,0x5e44854446997e4cL,0x40921fd93c3dafb0L }, + { 0xf3873a8ab7390d9bL,0x30999855495ba2fbL,0x005164f0813c8c76L, + 0x05bb04d7fe8da60cL,0xee7c38d503224ad1L,0x172018d615785ce5L } }, + /* 45 << 259 */ + { { 0xaaf786c0f6442534L,0x3f1344c1e56b44a5L,0x31199702ed073a36L, + 0x1f8ba0ec3df17e33L,0xf3e7b63493ceee0aL,0x568bdf39490fc4beL }, + { 0x364bdd11b1e1c439L,0xa1aa317ae5a63c82L,0xb12697034c02ee46L, + 0x0bc6d92e7eb64374L,0x87538fe740ed83f1L,0x862450abda74892aL } }, + /* 46 << 259 */ + { { 0x59b1b1347a62eb3bL,0x0f8ce157cceefb34L,0x3fe842a8a798cb2bL, + 0xd01bc6260bf4161dL,0x55ef6e554d016fdbL,0xcb561503b242b201L }, + { 0x076ebc73af4199c1L,0x39dedcbb697244f7L,0x9d184733040162bcL, + 0x902992c17f6b5fa6L,0xad1de754bb4952b5L,0x7acf1b93a121f6c8L } }, + /* 47 << 259 */ + { { 0x293ff71acc51318fL,0x69437a2e614149cfL,0xb12ea4613b48b348L, + 0x2f58020321f6cf90L,0x2e865f77178b53fbL,0xf4774d29231909a8L }, + { 0x0433e66bc4d8b703L,0x4fb6256b907097cfL,0x44a2a7fe004470f7L, + 0x7d3ebbb46dc5f10aL,0xe9b3af288f5526b4L,0x4bc0d9db1107bd75L } }, + /* 48 << 259 */ + { { 0x4865c0ffc0391d0bL,0x70d31470176740ffL,0xf44ca9a1ed506d00L, + 0xfaac86f6c981153aL,0x713ddaf4e3f86940L,0x64ec27093fc39de9L }, + { 0x04d413acac9a26b5L,0xde2052eebb21664bL,0xa6e04de8957b4f20L, + 0xd185b640d5487618L,0x1668b6a46fed1707L,0xeed37894c435ac3dL } }, + /* 49 << 259 */ + { { 0x1fa08a16f69cdfbbL,0xabba54dd0bf735a1L,0x37848c6a68a5cc20L, + 0x08e23c52a969298bL,0x48240306f965bddeL,0x48492deaf90bcff5L }, + { 0x416b9005bd994e22L,0xa6ce214ce6429f16L,0x5aaeec21f43f86d4L, + 0x202db9b7a0b1979fL,0xb2d97b4fdd7ae6d5L,0x4fedb6b9e12f04a1L } }, + /* 50 << 259 */ + { { 0x7a56867c325c9b9aL,0x1a143999f3dc3d6aL,0xce10959003f5bcb8L, + 0x034e9035d6eee5b7L,0x2afa81c8495df1bcL,0x5eab52dc08924d02L }, + { 0xee6aa014aa181904L,0xe62def09310ad621L,0x6c9792fcc7538a03L, + 0xa89d3e883e41d789L,0xd60fa11c9f94ae83L,0x5e16a8c2e0d6234aL } }, + /* 51 << 259 */ + { { 0x9c8e64869c85df60L,0xa84692a681e26100L,0x0350e1209c739462L, + 0xb6da4ebf99fa1f63L,0x857b534055e2bcd4L,0x7f4001dbdb209cf7L }, + { 0xbfa320378757800cL,0x2d56821fa6a562b5L,0xe56d810b6c3e775cL, + 0xeba244a6ba757f86L,0xb7ca8dbf80a17cb3L,0x8cbff4a22b7db57cL } }, + /* 52 << 259 */ + { { 0x650c31da9dff967dL,0xecd1e0f77ed949dbL,0xa7ff9becb20196fdL, + 0x5085c68d1e6259aaL,0x5759a166871a71e9L,0xba15e24c2b4d3bd2L }, + { 0x22c4f75912c51998L,0x6038fb0a7c8a9400L,0x64827d9c09625dacL, + 0xd8ce10c96ec4fb64L,0xe417ac30095686ccL,0x1e624aa88c723f44L } }, + /* 53 << 259 */ + { { 0x872d3dc953387fbaL,0xaaa0e1b4317ec17bL,0xa12b45519efb728cL, + 0x0b43907d45a3491eL,0xb7fa83befa4a239dL,0xbecdae00b59a4f3cL }, + { 0xe4e4c7c393407d23L,0x8278f336cf1d3cd8L,0x73dc9356610570a3L, + 0x5579653d688d933fL,0x208b96be5881d760L,0x4752a645d12f57bbL } }, + /* 54 << 259 */ + { { 0x87ec053da9242f3bL,0x99544637f0e03545L,0xea0633ff6b7019e9L, + 0x8cb8ae0768dddb5bL,0x892e7c841a811ac7L,0xc7ef19eb73664249L }, + { 0xd1b5819acd1489e3L,0xf9c80fb0de45d24aL,0x045c21a683bb7491L, + 0xa65325be73f7a47dL,0x08d09f0e9c394f0cL,0xe7fb21c6268d4f08L } }, + /* 55 << 259 */ + { { 0xe02aca87d4bba3cbL,0xd40ac486652fb181L,0xa1dcfe7ffaa3f999L, + 0x116323e0e9eded09L,0xaa3a0f0f07629d4fL,0x9f8e49f5e0dc53adL }, + { 0xbae96096742af22bL,0x6d7e24dd518862dbL,0x5c91ba30bb333cd7L, + 0xda8df051e65319b0L,0x2b9305ce9b3e43dbL,0xbf1d0e98fe783571L } }, + /* 56 << 259 */ + { { 0xf629fb233809aa31L,0xb3b66d77650bd2b8L,0xcb643126bd325d57L, + 0x29f46272ed41fa03L,0x374e734f406ef56cL,0xbb9ecd36da7428eeL }, + { 0x069694a61c06325aL,0x852b2912e40b9e8cL,0x6504bc90cc3d9695L, + 0xf1af43587e38707aL,0x552127dc239a0781L,0x0d1b3a6e8fe76173L } }, + /* 57 << 259 */ + { { 0x207e41f31d681018L,0x8883a6e417a7d540L,0xffc48332bc983c31L, + 0x729c4110c6b3de67L,0x5ef4680ad69a2499L,0x4544b58fe7afb2e7L }, + { 0xf5a2fb13480e063dL,0x8797357382054197L,0x5dd38cf7131d2df7L, + 0x635e91b8a9366742L,0xbd87a407e0d703c5L,0x6cc37be247251f16L } }, + /* 58 << 259 */ + { { 0xc4ccab956ca95c18L,0x563ffd56bc42e040L,0xfa3c64d8e701c604L, + 0xc88d4426b0abafeeL,0x1a353e5e8542e4c3L,0x9a2d8b7ced726186L }, + { 0xd61ce19042d097faL,0x6a63e280799a748bL,0x0f48d0633225486bL, + 0x848f8fe142a3c443L,0x2ccde2508493cef4L,0x5450a50845e77e7cL } }, + /* 59 << 259 */ + { { 0xaa129c0ddc428c57L,0xfe619b75aea19047L,0xd6287ecf12ea77aeL, + 0x4e6d070fdf7ce104L,0xd0df6788f097c79cL,0xd1c1f8a6ad8b1d07L }, + { 0x53eceba296519e66L,0x71670de3d6274109L,0xd2f21ea03f7a82b8L, + 0x41efbe939c8e45a5L,0xb5b153436ada3edfL,0x32ba22aca90038f8L } }, + /* 60 << 259 */ + { { 0xe1d195fad0cbe947L,0xd1fe0c4ef2ef1b72L,0x1451a0b206003fffL, + 0xda653fa08239341cL,0x5f834372f2508d75L,0xaeb245f507faeac3L }, + { 0x3eb3285b65fdf4ddL,0xfb335c0e84085970L,0x600ad6cae5efc0deL, + 0xc9c9f8910cf83e82L,0xf880ff84ad8cc14cL,0x54816725a016aae6L } }, + /* 61 << 259 */ + { { 0x22ce565ce1124375L,0x30ff1dc5edd968c9L,0x62d74c54e9148534L, + 0xf003f0d35de42774L,0xaf9448e6e57f8842L,0x55d5c9a3c5ff761bL }, + { 0x7da9398cc4c5edd8L,0x9643424e4ea0e099L,0x497eed480634fcb4L, + 0x09ffe2d07dea57cfL,0x30673ba73530a094L,0xfdbf8f24a251cff3L } }, + /* 62 << 259 */ + { { 0xd0f4e24803112816L,0xfcad9ddbccbe9e16L,0x177999bf5ae01ea0L, + 0xd20c78b9ce832dceL,0x3cc694fb50c8c646L,0x24d75968c93d4887L }, + { 0x9f06366a87bc08afL,0x59fab50e7fd0df2aL,0x5ffcc7f76c4cc234L, + 0x87198dd765f52d86L,0x5b9c94b0a855df04L,0xd8ba6c738a067ad7L } }, + /* 63 << 259 */ + { { 0xf9ae5fcedb877020L,0xd84ad42f703e5d09L,0xa6a5cc1fbfaed17eL, + 0x2099409829362fe9L,0x9f863bb0dd299c2dL,0x82bd3f61fa632197L }, + { 0xd3b14097ebe7ff51L,0x7c9e6ec4c719a6bcL,0xd3b46f3d70a51db6L, + 0xc8fa2f0692eb8243L,0x68e1f56e02155139L,0x0c35d135fd3b893dL } }, + /* 64 << 259 */ + { { 0xe76894c3ae7ce296L,0x87737ee2a6cafc34L,0x566dfcfbe55cd1e6L, + 0x5421a9f23a7ad5b9L,0xa005838a4687a4efL,0x3837219a23a2c423L }, + { 0x4b7800128a82cd1bL,0x401c07bec728b588L,0x2b5f69e937ced8f3L, + 0x306b621d8c1e1eaaL,0x8acbbe71d389cc4dL,0x922fa665f4ab7774L } }, + /* 0 << 266 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 266 */ + { { 0x2df6f242d35c2d80L,0xf65a99a93493ce97L,0x9e80232b372bcc87L, + 0x26ba13b86e428cc5L,0x2526ef1f13a1b763L,0xcef3edcddc97c5f3L }, + { 0x4954867fbde16b73L,0x9817813d368ff6cbL,0x7e39fa69be143027L, + 0x12329463cf54f28bL,0xcf0991dc7597c2daL,0x0cda396952e07099L } }, + /* 2 << 266 */ + { { 0x412f64a3f303955dL,0xe92bdca9bd692593L,0xfbe6cdc2c2e964e0L, + 0xe9a3b1fd0011cb01L,0x6c30762dcf228f23L,0x1270b84abe9199a1L }, + { 0x732711dfe3c9cbb1L,0xa3aabe37d91d9513L,0x8ee08ba0c6eceba7L, + 0xb1711531f3c3d31dL,0x65060b633c716948L,0x046b4ea12ff2caddL } }, + /* 3 << 266 */ + { { 0x25d1124fbab220c6L,0xcd1423c861524e3eL,0x75e4f45f0434fb51L, + 0xb5180a8f5180ab2bL,0x144e214e5b22e388L,0x6b16dad192263054L }, + { 0x3ea7590740863566L,0x372d5abddada3b46L,0xb3ff5a3a893d210fL, + 0x39f8d1ce5e29f3dcL,0x559186ce68200e82L,0xf48764541202cb66L } }, + /* 4 << 266 */ + { { 0x6f178dbf8b540904L,0x0264bccd8720472aL,0xa6e8b4b459b46611L, + 0xafce8267c72b4a58L,0x21142175a45985adL,0xd23401dfe649d733L }, + { 0x6bf42fe085dc7720L,0xc5c8ab9440e3f2f5L,0xb0c8a58acd029197L, + 0xa73ff329215492e1L,0x895c545eb1b5a5f0L,0x6dbc24456fcaf49bL } }, + /* 5 << 266 */ + { { 0x25ef32d60f2d76a3L,0x540650b9af4a7d46L,0x8979a4b8d991d7f4L, + 0xdaa706c299202400L,0x8a729680f19d281dL,0xde25bdc44ec44de2L }, + { 0x0fc50832c2054496L,0xfee72fb60aaf2941L,0xc8263e64b82ed4f0L, + 0x91a8cb736f49055cL,0xb7585458f2bb515cL,0x03d2b23ab855e6c6L } }, + /* 6 << 266 */ + { { 0x09ec1e3dcfd3f182L,0x1f1c30b5adae7af9L,0xf3a33f7c6b454164L, + 0x0318926f94647c4fL,0x8e37bdd787db14ecL,0x811cbd342ab364d3L }, + { 0x1dd1e5077c2b369dL,0x7a57bc46a28056bdL,0xfca5be4b089efe44L, + 0xb3bd84d76dc1290eL,0x40d7af098793e6aeL,0x4e08e11fa3723942L } }, + /* 7 << 266 */ + { { 0xca3709ad899ffebbL,0x1a87377877c00602L,0x5ff40c2aa99b4af0L, + 0x680464e5a80e870cL,0xd2f7f04494e10b1dL,0xee9b206c4e9aa1a7L }, + { 0xb536d67596cbe950L,0x841856899e8305f3L,0xae1b669c369fa255L, + 0x62e260267233e1eaL,0xac05c5136aa60c24L,0xdfc6814fd2691677L } }, + /* 8 << 266 */ + { { 0x8baef5df0a02b0fbL,0x58a2b06bc2b92b02L,0x268558d754c8267aL, + 0xf924f795ccf70393L,0xe3763f30f68ee021L,0xc1e856f05c01ba4bL }, + { 0xcc01a3e9722b6bffL,0xd2be4623ed5b3b02L,0x1ab3512e6c45e33fL, + 0xa978fe484ef433f6L,0x23e2ea018e21f5afL,0x49647d8811524a40L } }, + /* 9 << 266 */ + { { 0xd50abc94f5d3f437L,0xbf2ffcc546b7b738L,0x0bf53571f80edda5L, + 0x167908d4ab90ba5fL,0xad445b102303cf00L,0x9b537d4fb9e59406L }, + { 0xfac5e27cf43049a8L,0x05ccb32ebf9db100L,0xe662eeac4d1b535fL, + 0xbf21d6d78d27ca90L,0xb960bf652a684981L,0xe16bdaee49236475L } }, + /* 10 << 266 */ + { { 0x47a5958f92ad4720L,0x12c33193da3bf809L,0xf16493147da6d32cL, + 0x42eb4e687102deebL,0x0f8c4ce283088c86L,0xedf91c3bd693c9a2L }, + { 0x8a18a4761e8c310cL,0x5e8757c5dc3db0e8L,0xc48b820ef76a0affL, + 0x690d788d5c71e596L,0x2b0a00857cfe770dL,0x440ba06bd46505f0L } }, + /* 11 << 266 */ + { { 0x503f77906087d4d0L,0xc7243aeda1ebfb04L,0x203f0563ad8f14bdL, + 0xc20013b7cad73fcaL,0xbace8b323741a708L,0x0b376ff731bdeb56L }, + { 0x820b7f1282c22e57L,0x0c08133117830562L,0x306d178a8d0d30c2L, + 0x36a6efd1467a1510L,0x558fea1af55b7b97L,0x1e9152b784e546eeL } }, + /* 12 << 266 */ + { { 0x92a7fbcdac3ce531L,0xeb85f7f059498d99L,0x8e45db2d02a8feb5L, + 0x176c0cb2728cecbeL,0x33fcfbb0d1837662L,0x426e192dd6f2882cL }, + { 0x75a0f3450a2c9899L,0xd815dc6066148f9dL,0xf4ea90cefa0453afL, + 0x5108858ff54c96fbL,0x86b46b5731f77afcL,0x59df021f6bf7e2fcL } }, + /* 13 << 266 */ + { { 0x48d67f73dab6c0f4L,0x70cfc26cf0d49ef3L,0x25c95a68a65cce7bL, + 0x29a05632cf6ad228L,0xbcc2fb5a1a8128f5L,0x360d82a48c9defe0L }, + { 0x1c5c5d628d1531d8L,0x58fc4b9a149f6b4cL,0x8097cf56a3b625adL, + 0x8821ead7fd8e0e35L,0xb96c2b880d9e1df0L,0xfbf55ba72a243accL } }, + /* 14 << 266 */ + { { 0xef32e94d70e0d8fcL,0x33ec93dc6d63e65fL,0x134532fb1dc7156fL, + 0x98fb5b0c0e8d85b4L,0x05c28df9b64f7861L,0xa7e73afa4160e1a2L }, + { 0xbfe60a9b785f6e4bL,0xfcf998f12fec9ec5L,0xf673b8d15c12a44aL, + 0x85df3bc736d189a5L,0x4480a189dd83f6e0L,0x3216317ef3d3ab44L } }, + /* 15 << 266 */ + { { 0x221c1b7ffd3d7532L,0x40939c318bb4e719L,0x75182ce602f8f74eL, + 0xf508d6415395f9d8L,0x88fc89ea1fc81977L,0x861d8d0bcc8dc7d3L }, + { 0xd76e4f0cec07b0e2L,0xb0a4e2aa5819b99bL,0xa67bed0366a9c935L, + 0xce7c8241d2781f91L,0xe7c5c22512af0abdL,0xd1067dbcfde7de16L } }, + /* 16 << 266 */ + { { 0xe1d42d94d087b788L,0xfbfb221aba0e176aL,0x5f6698e783686966L, + 0xbb5e159474a30dbfL,0xef86bb5bcfd20230L,0xf055a1c5403b8f8bL }, + { 0xf249aac8d9d85ea7L,0x7318f7bc3d200198L,0x3b80960cefca9a90L, + 0xf28e33888f449c4bL,0x0cdfc61bf0cfe09eL,0x3b169c638b22cd26L } }, + /* 17 << 266 */ + { { 0xf4f13a49b81b45b0L,0xb77a67be3003fe1bL,0x70e648a318d52c97L, + 0x701ba8a1ee17ce93L,0x58a0ce0cf672226aL,0x2fcad147cebc3294L }, + { 0xf5cd118a104e8f68L,0x0015bc0bd15358e6L,0x75f0d28f1c662df4L, + 0xcd54f443a3e038f4L,0xa83507610804c717L,0x5fce0ce3f03bad08L } }, + /* 18 << 266 */ + { { 0x4c2e2bffa180a71cL,0x067f3e3baff551b9L,0x007610f1afa43e12L, + 0xe8a9ae79ef7b9a1cL,0xa558ef6cf9d3b397L,0x8d5229884f172f34L }, + { 0xafa906332d425e05L,0xc62c3914207b0bd8L,0xc84d197c059f7d66L, + 0x6cc1d8ce421a9172L,0x1d44a46929a7ebe3L,0x96ca4d0171c3c8b1L } }, + /* 19 << 266 */ + { { 0x31302e094d369fd6L,0x62fe210cf1b62d27L,0x496ac173bb37578cL, + 0xb4d3d065aa0907e0L,0x02317db27c822875L,0x60a01580f241ebc7L }, + { 0x81a5d5244e4f37d0L,0x5286f7289c3f2555L,0x14c8c7549a73ff08L, + 0xd8236689ff478877L,0xf62d426b08e09f00L,0x2ba1833c67a96517L } }, + /* 20 << 266 */ + { { 0x7013d596831f464aL,0xe57185fdd3cf6ca2L,0xbba7898e35915f51L, + 0x9fbe5f139fd967d4L,0x0aba8344d173558fL,0x4c0dd30dffeb6beaL }, + { 0x928f68cc5110e40fL,0x1589a327a58b6d60L,0x09b5c4e06abb0ac9L, + 0x01ef3f8a68957627L,0x55dbe9f79f4045a4L,0x91976aeeef178ac3L } }, + /* 21 << 266 */ + { { 0xd9c20a69b85e46d9L,0x1bda1163cdbda686L,0x5c0717f6c02427a9L, + 0x2a976c104d2a48afL,0xea276b15921a02e5L,0xf055b980ddb6315cL }, + { 0x0ab85663825f00efL,0x95377fd42053a392L,0xc51c245e23f463e8L, + 0xe1ae1e5da24c981fL,0xd6a0b44d9f5cfdbaL,0x1205754023c16002L } }, + /* 22 << 266 */ + { { 0xfe464ce116ac9150L,0xfd629551173ee9e8L,0xd0623ab1781696cfL, + 0x7a07cedd58529fa9L,0x831b4a9d449c33a0L,0xb7b7b72417b171a8L }, + { 0x0e1ff931f5a9aa41L,0xd43f33dfe356ba47L,0xd2abfc77f003b5d2L, + 0xc2909150882c0313L,0x83823f6c7ee111a6L,0x9d7a2d82f59cb72dL } }, + /* 23 << 266 */ + { { 0x52e712549b33f6fdL,0xd4d9b73f5c414babL,0x9834943177e93a9bL, + 0x848b53c99f283fc9L,0x86e48b6234c787efL,0x8b498e1cb3166045L }, + { 0xb2259559e5e456ddL,0x0316069fa2c2ca8cL,0x9a70e29ef6524ecfL, + 0x2477ffc9bfff600dL,0x80a9a5e081869e1cL,0x84f887e70a78f6a0L } }, + /* 24 << 266 */ + { { 0x7f89c2c40c9f23eaL,0x8fb025d4d6ec2b2aL,0xbe70e48b12d9f811L, + 0x703ac1bdc7a43dd0L,0xa4309a2c2118ca3aL,0x5a95d7b301943012L }, + { 0xd9597d87811f6c73L,0xf82e801596079992L,0xfcf8760df1561aa9L, + 0xe1e0306e2d91ee39L,0x99979031e0bbcb6dL,0x49259e54cfcc8746L } }, + /* 25 << 266 */ + { { 0x0de49373a38fb6dbL,0xda9e9036d6bf0a7dL,0xc99fe05fcba221c4L, + 0x45b51edd4cb730f8L,0x312670a3b064e142L,0x60dd1edecddb9ddeL }, + { 0x94be613b9291d75dL,0xbc49861ca00b9831L,0xccec7a08230320bdL, + 0xd1de7bd80ff967b1L,0x5a1164f105fda7e3L,0x864cfc4ce3004538L } }, + /* 26 << 266 */ + { { 0x06f76165385095a7L,0x3c73ac918514b2e0L,0x8ac1120a04b2dac0L, + 0xed6a74174382d5b3L,0x852a5a7864a32d50L,0x7ef5b84bbdc721acL }, + { 0x73dd18980480d271L,0x755b23e04ab0b11dL,0x2e78238982391e5aL, + 0x4957b5c948923446L,0x4ab9318f6921c1fdL,0x8e455abd3e46607bL } }, + /* 27 << 266 */ + { { 0x5c41aafbaf25d6b6L,0xe351f1df916b63f6L,0xe28e9ba98a6efd65L, + 0xcbca736356afe7b0L,0xa77d6077f7384e6aL,0xcc9ad74a738a90abL }, + { 0xe1071caa2333dc2cL,0x4415691000dfc2cbL,0x0ce43c16afd89eefL, + 0x0cfbb8767b812045L,0xe6da40fa6d916fc7L,0xe404b3436302af21L } }, + /* 28 << 266 */ + { { 0x4073f246d9915433L,0xc0149d5672e06203L,0x0abb06c18fcec6a1L, + 0x3a7d1295d75a73f1L,0x65fd8700f18c9488L,0xc3cc0b27732f7741L }, + { 0xd15d8c8025a261caL,0x518233510dc1fee5L,0x981607c7120e1266L, + 0x0e486b11f42cc9fdL,0xe606c16c01a888cfL,0x079dd0b31ea23249L } }, + /* 29 << 266 */ + { { 0x19c62d3c58624305L,0x44974c41b73eae15L,0x2df48b6dd023231aL, + 0x6a82c197c6fad2d0L,0x55758764c623fdceL,0x29f533fbadcebd90L }, + { 0xcfbe4155cfff7336L,0xb18415c7bfb609fcL,0xc23395ad8d411a6cL, + 0x25aebbcf0c92de60L,0xf4d3b1ebc5ccf268L,0x9646b4a79ac85de3L } }, + /* 30 << 266 */ + { { 0x0f423f3013d6cb61L,0x239b2baa66674aceL,0xa6f2ba39eda69340L, + 0xdbbd20eb43e6918cL,0xe6ce84a3e5e7248cL,0xd9184bb5e04c580cL }, + { 0xe4b76d96a0738aedL,0x98662b6090d480a8L,0xfb14bec72610b6c5L, + 0xdfcb01f6bb65837cL,0xd7f0b6ad4a97fb21L,0xe6d84f4bad59b2ceL } }, + /* 31 << 266 */ + { { 0xa79085eb1f7e921aL,0xe2737a08d0aeb41fL,0xa96d7e8169ead959L, + 0xbed1731b733b7c6aL,0x7768e32df508a48aL,0x6f73a08651ccc97aL }, + { 0xb7f94a4b9122db73L,0x1cd17ca257ec947eL,0x7c83fe278f8445f1L, + 0x661f5d82b520fe34L,0x495354942233d364L,0x0bf7abe663925ca2L } }, + /* 32 << 266 */ + { { 0x923e948c203bb368L,0x58e37a2b231a80e0L,0x345a011a6df27debL, + 0xba6784c1d57f4ca2L,0xf01b3703114196e9L,0x981a63eb1aab426dL }, + { 0x2ffdc97851770c1cL,0xddd19da6efa722fcL,0x5ca1c01216f09c1eL, + 0x612021de5b9cc0b6L,0x910e10e95e150569L,0xacace9dce2ab93eaL } }, + /* 33 << 266 */ + { { 0xf66601a7aae13423L,0x940bcd2882cf3308L,0x55de590974f632bdL, + 0xf677d9d4f183faeaL,0x54026b2828ab364cL,0x2a5353dc743469edL }, + { 0x15f02aadd46871d5L,0x4b3ec89b5a2100d1L,0xca85c3681eb9c381L, + 0x145cc7fd50e78466L,0x75fdac98c4b4cdf3L,0xb7cb9170796136f4L } }, + /* 34 << 266 */ + { { 0x6e89c0df54827957L,0xafb26b6d05805250L,0x0c0dc4ea37343465L, + 0x2d3c8b873daca876L,0x733b23d9554a2cd8L,0xd4f2936a6a04d38dL }, + { 0x0937611686f90d9aL,0xcd854d3211425591L,0xbaf9d4cab55b4bf3L, + 0x47259b95144676c2L,0x765cc4b55d7d2835L,0x36e47a8882b2cbafL } }, + /* 35 << 266 */ + { { 0x2070db373af8c96dL,0x4c2db2623b70e976L,0x7ed4d1e9c01f404aL, + 0x04a52764b39d2e07L,0x06e4a7984ebe3ac3L,0x35c9c1f68d7645a7L }, + { 0x2e0b48c75e9c295dL,0x5d44fafaf78e0717L,0x2fc27eba04213067L, + 0x9f3fb2ff2ab0f0e6L,0x374b32fd0c730af6L,0x06ec846129583945L } }, + /* 36 << 266 */ + { { 0x583a3272230be37eL,0x4d3298951c55f593L,0x3b3a2d8a350f0334L, + 0xec830170b25498abL,0xd65847d9b3a01571L,0x4605e739663f86fcL }, + { 0x971b8e115c4bf502L,0x651d179571a892b0L,0x57930832d2d1a4f9L, + 0xf97010745b09a4c4L,0x76b023e55ec2d1a6L,0x8648b8bcf49e1329L } }, + /* 37 << 266 */ + { { 0xc5a8884d6d5c7411L,0xad32aa97d098e2f2L,0xf99569e945d8ad00L, + 0x35801c1c0a232776L,0xe426fd65fb1a2cb2L,0x874b559ecb26ae10L }, + { 0xfa67c2ddf44461b8L,0xc58f8d229418e17cL,0x5998197169908eddL, + 0x8a4a14b8a1f78300L,0x4814c36e61f7fbc5L,0x0389dcc716a1c7adL } }, + /* 38 << 266 */ + { { 0x777e308fc072cf71L,0x4a2d66928c807ed5L,0xa4fe074124842689L, + 0xa3c2a867151ed7b1L,0x52ef24f24d22ee35L,0xe684ac76499053ddL }, + { 0x0b7c223b0582cb86L,0xa6c18539bb81f713L,0xb472da7f66d2aab9L, + 0x3592ab7b7916d4e5L,0xed651a05770c49a1L,0x7b879da1c0256420L } }, + /* 39 << 266 */ + { { 0x82eeaa1496f83e29L,0x586f3e8de5cae8eaL,0xb671eddbb298eb5aL, + 0x41efea86dd0da080L,0xfe9af019564a382eL,0xb2f370463027693bL }, + { 0x65466e5018789c0fL,0x5b0870ac2ebfe89eL,0x9093f416a59f3a53L, + 0xab0cd17251864c77L,0x8e3aa9864481457bL,0x46cfd207896346a5L } }, + /* 40 << 266 */ + { { 0x473bdac887cb6ae0L,0xbd3001b3f155c32bL,0x109643c20026e8a5L, + 0xc4f5f6cc188a568eL,0x630aecf64d2758e0L,0x4549949955b91872L }, + { 0xb10f19d4b6a09df6L,0xc537a4bb37f26d01L,0xd29f505c4d19a293L, + 0xf388a5d2cbb09b17L,0x462efffc6811a49bL,0x8a1cbc40b2f3aef2L } }, + /* 41 << 266 */ + { { 0xf7d94342b7b42998L,0xcdfd6e43629089abL,0x622e8d3cf7932661L, + 0x4818adca0b14b257L,0xcc1dcd1ccdb486bbL,0x58b6cb7ecce8b358L }, + { 0xca36c0b4e640cebeL,0xcc5598942d25f742L,0xdf4f2a9ed754d3eaL, + 0x072eb5e5f44a8604L,0xfa7b1a03cd5ca1c5L,0x6b6b4967d4779eceL } }, + /* 42 << 266 */ + { { 0x0f0233df8665f6f2L,0x8cd887463bd40f39L,0x23a41596eedf8d3aL, + 0x3f50e3f0b5ef5455L,0x935b24e0a50cd358L,0xfdd0e940d362a9a7L }, + { 0x6b00a6d154371aabL,0x2e707c4e1204bcf8L,0xb4d2d2dc30233f88L, + 0x470c3201783e58efL,0xf53987865ac21a16L,0x278487d626c3513eL } }, + /* 43 << 266 */ + { { 0xab5ac4df7d40427aL,0x0c4fb23b66ebdcedL,0xb02f8632b87df612L, + 0xebbd2e7f1801700cL,0xdd11de725b675e5bL,0x2adfb20662d7210fL }, + { 0xe3ba7c0e28667b70L,0x3e190a438fe31c22L,0x57908f2bc3390733L, + 0xe9e8714ccb6fefbbL,0xabba506dfd51c513L,0xd50f979f6b798860L } }, + /* 44 << 266 */ + { { 0xdf224cea1eed2b0bL,0x10205f438814572bL,0x8b99d85c02eb9b6cL, + 0x7a8a3d146c63a672L,0xc8822c6c96f45695L,0x0530f619c7f532f5L }, + { 0xb981e182310f8355L,0x49318290f201444cL,0xeaa4c406f9b76d19L, + 0x960fa2c7534a91c1L,0xf98966d1522b7d9dL,0x66912542c757dbd6L } }, + /* 45 << 266 */ + { { 0xe265972e1fe73a1aL,0x77e234c2987a1a34L,0x1814bdfe8c5789c0L, + 0x908f55c7df2ca0d7L,0xec207eb2a6a50ceeL,0x63cfeaffee916760L }, + { 0x808a758bf466a1b8L,0x2a48112d8383b0afL,0x5238922ef1a4ca6aL, + 0x5c422786778de666L,0xf5a8c6b5d2f549ecL,0xcac5d0c5242bbc9bL } }, + /* 46 << 266 */ + { { 0x33e0e005b34dbf06L,0x7bbdbe1e1fb341dbL,0x443fde882bab5425L, + 0x9db5bf1a86b57cdfL,0x72c535c309a93848L,0xf7aa9432b5f216ceL }, + { 0xc17dc7ae0242308dL,0xf1cb5dc5db0e4c0cL,0xb9d16d58a2b7112eL, + 0x486cda07ee4494b5L,0xeb46ab545d431adbL,0x3261dc5181ab565aL } }, + /* 47 << 266 */ + { { 0x476a4bfaa2a8a081L,0x43c5f841394f851bL,0x659baa591f5b22ddL, + 0x49a786aa65f680efL,0x091bd21608fcb9d8L,0x13f6953d984fe1f1L }, + { 0x7b5d9f4b6d6d40a3L,0x2f135dcf0d458d54L,0x2da18c3d3a71204aL, + 0x3d93edb97a3486d6L,0x026fec7261846af9L,0xa62197bcd5200dcdL } }, + /* 48 << 266 */ + { { 0x0cdd83725070e0a9L,0x7c5ad562ec550783L,0x9652b8474f3b8d2bL, + 0xfdd60d93e6e98d73L,0xd51cae2ca3479d0bL,0x11b93b6dee05c006L }, + { 0x9d72b82d8a3b40d5L,0xc6e996fea7d24855L,0x420672f7398603deL, + 0xd551b34a9a1af2ceL,0xdeb8c1d913bdce0cL,0x56ca926debbeba7aL } }, + /* 49 << 266 */ + { { 0xf63ec096bb85ca8aL,0xc149664173bc52f2L,0xba792560c02fc808L, + 0x9a6043e3533c6523L,0xa9d78f0aa8564390L,0x7fef67e494614bc7L }, + { 0xb4091b8fd389234dL,0x5913368e82db1d08L,0x178f7df0981cc6caL, + 0x19b1f2be725ec048L,0x852aad85012f9c44L,0xb07cac0dc894e777L } }, + /* 50 << 266 */ + { { 0x1c1709d02c7e0767L,0xec1013234d70b117L,0x95c57e678beb8e05L, + 0xdbf29e2e1133fa4aL,0x917f4a6c5139e020L,0xcf0be5098399735dL }, + { 0x83014c169c878b4aL,0xe0c14d2cf789b84fL,0x222aba39165a4aafL, + 0xe135f2b384441391L,0xb6f1cf7e19c3ee07L,0x2f918da9f810499eL } }, + /* 51 << 266 */ + { { 0x026ee35816bb2bddL,0x8c8953f8566d8470L,0xf0cd746d0fc63932L, + 0xddf3e54f060a07a3L,0x8da877a643b4e92dL,0x7ffd839dfdc9e34aL }, + { 0x5c3527445df04d9aL,0x3c5eb576b69f84e0L,0xf73cae300848d993L, + 0x3438f2bea0fe7fdbL,0xd4e7511f0eaf0168L,0xa7ffd167c768386aL } }, + /* 52 << 266 */ + { { 0xbb91877acfc74bb0L,0xbe742182a060a71eL,0x116e5a626ed7786cL, + 0x0a496b1bea669e56L,0x3a012174b8f02e6eL,0x6add760c106174f4L }, + { 0xaf2606e05e0292cbL,0x7800a495c7b7bad0L,0xca02c9320a1c5954L, + 0x904f23c6b245ad57L,0x28d6cc2172934de5L,0xbb7ed903283752cdL } }, + /* 53 << 266 */ + { { 0xc80288125e58122dL,0x7a5c65f1c4b089caL,0x4ddfd3663b980faaL, + 0xe8129f7f96a909a0L,0xc177aa042221ffacL,0xaf444ef78ff46e81L }, + { 0xa627f3d76b154996L,0x0f06fa7b115e2a5dL,0x2532b85d43fdb775L, + 0xb6d96b32eaacfb58L,0x898766304f834382L,0xfd2ffde9d5636b92L } }, + /* 54 << 266 */ + { { 0x318cf974973757d0L,0x12882d0a94ac73a2L,0x1fb74a53bc250843L, + 0xc612569eccd8d47dL,0x74cff8789d5f7c8cL,0x54e0e475375a7366L }, + { 0xe8322d23d0f57cd4L,0xb6ec5666d95a6e0fL,0xc8374b254a4bd084L, + 0x9459181b349d93ebL,0x7011f0a61368b9a8L,0xed57a19137eb2833L } }, + /* 55 << 266 */ + { { 0xd245d180fa5f79acL,0x44c331f35b41fcb3L,0x13188b6e27ee6c0eL, + 0x54ce984b23fdc742L,0x66d4e1303c81c213L,0x432174030ecb6fd8L }, + { 0xbbeb09fe111ae08bL,0xb22ca6b42e2df05cL,0x0e9d01dd0fec9be9L, + 0x9ac4523dfd2fc4abL,0x3d9e98c8fdc059f5L,0xd52e6dfb2d2cbde7L } }, + /* 56 << 266 */ + { { 0x80d7ef8598100f17L,0xb9795c7112db3f3aL,0x44473659296a7c44L, + 0xa46810f21e5bf539L,0x5621241814ee1e3bL,0xea8284e209931822L }, + { 0x424c613e42ac1e42L,0xe84a80afbccf9466L,0x21a8cdcc45132204L, + 0x9505a4148d58da62L,0x773e09837b3f47aaL,0x0ad0cc91e109bc6dL } }, + /* 57 << 266 */ + { { 0x98e2509bb527b250L,0x2dd30c824a9c762bL,0x54025da4cb2a00a2L, + 0x88ed00ff04d8e0e9L,0x5699890219ab1fadL,0x92fffc41697b0226L }, + { 0xb481d1ee7d08a39bL,0xea773f7f82be0803L,0x967e848a6de8ec6dL, + 0x6ea1e46380293472L,0x941cded72e988de3L,0x85f96b23399da6b5L } }, + /* 58 << 266 */ + { { 0xabd86572f1a62473L,0x9ec25d0bec274738L,0xd27d1a8c2052d4ccL, + 0x1f2a2a9ba95de3f0L,0xe3b8652ea2c91bcaL,0x1a4f6900822175deL }, + { 0xd9405d4662475a44L,0x4ecbe06cfe55c587L,0x30f8d199a4ac2f35L, + 0x2a5defd8d3c12844L,0x6d0fd9d673fe9b7eL,0xb0ae1019adf1a196L } }, + /* 59 << 266 */ + { { 0x6c9a378c30734f5eL,0xdf04359f6aaf7b42L,0x244422fc16f87409L, + 0x81dfb15b08bcd67cL,0x24b7d083a5e4a8e0L,0x557183410431786fL }, + { 0xc8feeb8c33f3ec2eL,0x360098cb2be371a0L,0xf4f3d992bdb874ceL, + 0x47b432ed87af8471L,0x5c4b1dbdf87535deL,0x6bb6d6dd8301f660L } }, + /* 60 << 266 */ + { { 0xafa9338759769f77L,0xe6c710cb49e502b3L,0xe6fd7b8d1514da98L, + 0xb5924c63aedf93caL,0x4cc36795c112b37bL,0x0ee30ce3231def42L }, + { 0xe1f436e7daf8a37eL,0xed54b7f56efa184aL,0x09ad65752c0dfe63L, + 0x5ed9da43ca530b38L,0xea2fa192ae156274L,0xbf096c54a4429edaL } }, + /* 61 << 266 */ + { { 0x41401b98f54490cfL,0x361a24a143b21183L,0xf0176431b6570f0cL, + 0x851bfe9d05c8bd3aL,0xe44f4ba74611e1b9L,0x587677dc28bf2c27L }, + { 0x3e3b67886d85341fL,0xad65a69468aa381bL,0xd269dc711aecf19bL, + 0xb94b64a2d98e6a2cL,0x6004b569a94661a0L,0x81713a8e689181d5L } }, + /* 62 << 266 */ + { { 0x55b1901d3649638eL,0x2e9929c416abaf64L,0x2d2b160ee9cd0090L, + 0xb5ef6525f55f13ccL,0x447aacbe11c3e8a5L,0x2c54e602630cf4c4L }, + { 0x3f6d99fc641d8eb3L,0x35386c1384877912L,0x7195db8973f31b6fL, + 0x63297cb2d3a22085L,0xa627593833fe97cbL,0x2f9a6f0da1eaef0aL } }, + /* 63 << 266 */ + { { 0xb70d7683c63d6dd3L,0x60ea781084acedf1L,0x7646260c40d62cd0L, + 0x687000b456142a6aL,0xce3c4728ccb9177bL,0x45377d059928c509L }, + { 0x75cc40bb1a78af0dL,0x43a1661cc69e59fdL,0xf9bbcbf8044a943cL, + 0x934fd40d7c372080L,0xb6edae96cb2eb940L,0xa02bb5fd6e063cc9L } }, + /* 64 << 266 */ + { { 0xac58c9e09db9ca19L,0xd308ea5d390054d0L,0x32ef4afc2cc42529L, + 0x08bd48b397c2bdf9L,0xac8a7803a849e19aL,0xcd51c0da75c31496L }, + { 0x733dc7def0e2d49fL,0x7c9caad1b44b8cc5L,0x6d9c5b0847be21a8L, + 0xfab0fdc55ebf426fL,0xd60748caf94e9e5bL,0x3072e59269366089L } }, + /* 0 << 273 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 273 */ + { { 0xb06c17a3f0ef77c5L,0xc144e7846df6bf59L,0x2440ae990038aeb2L, + 0x83bf711b58b402caL,0xb8763e00b577732aL,0x509e91eff651a932L }, + { 0xbe02ab9d00ac109eL,0xfbcb426c8dfd78f1L,0x7ed272f64283f80fL, + 0x098cf0572365da5eL,0xd90e6f1805dc6bebL,0x09ef177fcf7b9d72L } }, + /* 2 << 273 */ + { { 0x6f101762eeb791c4L,0x0d942184df261effL,0x2c58e2aaac1dc827L, + 0x51410e89f835a1b6L,0x981333a7629915a4L,0x371891b60c14148dL }, + { 0x4d20b3d3c0904446L,0xdda7ecc8949776d8L,0xa664b68c2a2645f7L, + 0x7a6bc857add082eaL,0xe7467dc63e5ff206L,0x40a6c34004e2dfccL } }, + /* 3 << 273 */ + { { 0x3d0efae3106ba1a1L,0x9c717ca192d7be5aL,0xa5cb5a253f00eeeeL, + 0xc2f9258cd86161ceL,0xd2b0865f5c4a389aL,0x8c06d7689b1f2159L }, + { 0x5a758a612753107fL,0x5ab6449d0a539c19L,0x88655a4949d301c8L, + 0x129647e61c4bb89bL,0x06f0665ec360259cL,0xcdba2f0b066197d1L } }, + /* 4 << 273 */ + { { 0xa235456903744726L,0xd2169e6dd8d275acL,0xab0c247b132c5689L, + 0x129a5c9dcc4760bbL,0x03eba46726ae821bL,0x67a33fda3df1cf83L }, + { 0x010813cfb8421b7aL,0x7b0f507098cd6d76L,0x907320b31fe4b600L, + 0xda3bfeb398dd3239L,0x23f1ed1641abb34cL,0x01b30f29946f85f1L } }, + /* 5 << 273 */ + { { 0x97c5f1c7d3970d9fL,0xd051c518ac8e6227L,0x3f67b3958e87edacL, + 0x3a5cbd287b9e4c17L,0x58c009e65671841dL,0x7bc5bddb518b3b39L }, + { 0xe7a8a6335e74a614L,0xf92e4c226ed89a92L,0xd0d6e80a118e663dL, + 0x33dba4f9dcbb4aecL,0x1d4cb3141f917417L,0xd8b17bfa3b0c5859L } }, + /* 6 << 273 */ + { { 0xc0fa0d21a093c3e0L,0xad34c41439e902a2L,0x81c8cd7599bc928bL, + 0xf7f8be14cdbbe4d8L,0xe46268b5c2339529L,0xcdc54e348283ba7dL }, + { 0x4c5cf62778904fe1L,0x056678c11b45e4d2L,0xb555ad6ad265abc2L, + 0xb8f8ca3f830306efL,0x48c8764681c20e1dL,0x5bb0a529737a7944L } }, + /* 7 << 273 */ + { { 0xbd4c2bfc9cf6fc5fL,0x888885140577af66L,0xb5aa2f05f9e3f7c5L, + 0xbd477bae64de6007L,0x1da5dcc9747e1224L,0xc2293d1732a15f5dL }, + { 0x4dd9daed029d6cbaL,0xf51362d62cf299c7L,0xe1a4b5c4279cd1e1L, + 0x4b129a5ea89acfffL,0x8292228ece1c8744L,0x5a440fa04fd12c86L } }, + /* 8 << 273 */ + { { 0x285248309666f8eaL,0xd579b3dfeff6502bL,0x3a66fa9900e4f78aL, + 0xfd8a65bb54a3f7a3L,0x505d3f631965a79aL,0x9524972c1891469aL }, + { 0x78367cbc3354da3aL,0xbfe1fe3de4941c6eL,0xe41bb3f6f5af173eL, + 0x57cb03ca5ca36597L,0x27f86cb87b99f795L,0x5cae6514ad4dcef1L } }, + /* 9 << 273 */ + { { 0x4b43f0aef1743346L,0x1700581944324c46L,0x86c77197e3603fcaL, + 0x230d516f4a6858aaL,0xee965b4ee7c56f7fL,0x4f4ed301dcefb75aL }, + { 0x610b138c4a740b23L,0xda3996a83ffc3599L,0x930698fcb2d1c304L, + 0xd55bdcd3702bf80dL,0xdf767c419e334726L,0x975352a9d0e819b6L } }, + /* 10 << 273 */ + { { 0xc117353b5e816653L,0x0c87bebe820641d5L,0xee588c6d9ecd29a1L, + 0xacdfe622c70edf9bL,0xe8b8024cebae414bL,0xd0c426dc9bd7ceccL }, + { 0x715cbc2efe735ce7L,0x8376edebc5e7017aL,0xe9b37efc07990dd5L, + 0xc89e384ed8d75238L,0xbc594d218438ffb3L,0xbe77e4d4d3628473L } }, + /* 11 << 273 */ + { { 0xc53720cdd1b4f3baL,0xb8ac3b4fadf2a330L,0xcef037f5fe179e70L, + 0x2743b382589d9147L,0x77a094d624423d58L,0x9e34c2e62a23d372L }, + { 0x641ea760983a5893L,0x2211e6a49a81548eL,0x56578a1a48735310L, + 0xedb91e03a57faa83L,0x4e14d5649b133629L,0x341f3ef957e82ff7L } }, + /* 12 << 273 */ + { { 0x4952a350d87a86c9L,0x08ed7da7034f45f9L,0x1e9ff8272bd716d0L, + 0x2471fd15f1d9331fL,0x0c708362d7370b75L,0xaddedde6fc1a1051L }, + { 0xf4475288db27b186L,0x5be4d46b3760bc11L,0xe44435d906d47ee1L, + 0x865cf7c8d0b7c8a2L,0xdb412be08d31a252L,0x4b90a9322f24d71cL } }, + /* 13 << 273 */ + { { 0x71b84eed8f7a3ab9L,0xf41d7edb2dc18004L,0xe408156dcc4a02cfL, + 0x0be155a25cd906caL,0xbf4b0f6991516399L,0x2ea85d434a7ff94dL }, + { 0xf199b31da26e9974L,0xc584df250b805ae3L,0xd4e7e8597a3634daL, + 0xf553f07770db4be9L,0x1cb1056fbf0dafa3L,0x235281b2a817d6edL } }, + /* 14 << 273 */ + { { 0xc3304e9260d2b80bL,0xab24dac9a38753bdL,0x40373d04cc1ebbf8L, + 0xa5a162d3437e68d2L,0xc8018b1257e8db12L,0x0c99c6de9bb52643L }, + { 0xafef0ff6ee24e63bL,0x329c46264bea9a14L,0x1b17d2e6effae4f9L, + 0xd25b93aaee300afdL,0xe83bfdcba0d62da4L,0x5e919538fd787740L } }, + /* 15 << 273 */ + { { 0xf5bbb4fe196c38e7L,0xe0011deca5c75baaL,0x2e29fe59b835aa49L, + 0xee22e2864230f17fL,0x8774214ff94c1060L,0x35bcca38e6d4c126L }, + { 0x18d984dbb7c9d255L,0xb1d5515c9b63dc4fL,0x425360f12a0cb854L, + 0x038c7f2317a1e286L,0x5e6b12ce951f18b2L,0xabfbde5ea65b1de3L } }, + /* 16 << 273 */ + { { 0x38a49bf555f0ad9fL,0x1a84c6b8f3618639L,0x5f709eca01b2f7c2L, + 0xc479a6505be8359fL,0x6b6a22bfd6646b3fL,0xcce78878cc5b711bL }, + { 0x8e7dbc63b446cc63L,0x231bd027218f800fL,0x2d3a7e04030271ebL, + 0xb08b5978e22fb3c7L,0x860d62789be0d46cL,0x253a31c21d49a915L } }, + /* 17 << 273 */ + { { 0xab4dbdf36ebc28e5L,0x56d5fec527be58b5L,0x6e9375d3cf3fd509L, + 0xfffea897ca4ddf48L,0x0a9542ae6a3757c5L,0xb9069a2e7d93911dL }, + { 0x3e74ac5f3dc967b8L,0x99c38796ea8f5a21L,0x27797b97a6ddea53L, + 0x9501e1c561dfcc1bL,0x568d3abe448e95c5L,0x021f8f4c0e7c186bL } }, + /* 18 << 273 */ + { { 0x98aa1f7a6e44f63dL,0x6451b170cb597ec9L,0xc0f6ee8721e13b78L, + 0x36c3b9c751cfd003L,0xc31718ed2f610040L,0xdddabc6688c48009L }, + { 0x5626f090a8369e4fL,0x0eccb1c06004a968L,0x2f0448035da2f1a4L, + 0x5390b6dd3846a726L,0x5c4caffea24f3083L,0x3c9baac8c4842995L } }, + /* 19 << 273 */ + { { 0x58c5fd1205c7a75dL,0xa98007fd10866935L,0x91369e874acd567eL, + 0xb7e05dc322c6145aL,0x24c949b4d949d8b2L,0xc5c574a590a6a437L }, + { 0x4306f0334798d1d5L,0x82af09f4520e01b3L,0x53fab41b81247f00L, + 0x3096ccf44ea93cbfL,0x9665e039f13ff09eL,0xb623f8b158e036d9L } }, + /* 20 << 273 */ + { { 0xbad6b669376bdc3fL,0xc4a8e7bc23a9ff38L,0x3f54d8c4555fb0a3L, + 0xfb3d5e1d2b23db1bL,0x6379f78af0d7eba9L,0x36004febfa0beffaL }, + { 0xdf0a373c334ff01aL,0x10314749dff12a1cL,0x1d52ddc7f184c1b3L, + 0x79431663ab02d404L,0x1a6488c17f4d3795L,0x3363660f7cca9102L } }, + /* 21 << 273 */ + { { 0x1e4595c6db3e57d9L,0x49e3d3d9bfb94ec5L,0x4c720de1a4f12881L, + 0x91a08340b06c64e6L,0x8e5c72f0ef0857deL,0x2c9b4cbc09bb76fcL }, + { 0xd4262fe4b0bba8bfL,0x64c5fa1439fcd07bL,0x518da4de62904ceeL, + 0x626182ebae4c9717L,0x900fe9f806351622L,0xf74aaa2241f9e4d7L } }, + /* 22 << 273 */ + { { 0x9d2c02839fabb29bL,0xb27ac46e172348cfL,0xddc6fb63de1f64b2L, + 0x532dc953bb097c87L,0xc7f5180cdaa34e27L,0xf96e4ad755438893L }, + { 0xc0b2eba324f54a0bL,0xeba396ce5b50d12eL,0x80b3a7f699772783L, + 0xe2fa82ff3ff7df4aL,0x55375369a2359baaL,0xa28388ed856c05bbL } }, + /* 23 << 273 */ + { { 0x4432fe8495a2d064L,0x4c6380747fec6057L,0xc33705bb33cfb533L, + 0x5e7fb7c976991cfeL,0x73d249bdb3ac1b6eL,0x963964c896aeddccL }, + { 0x8c1abe0e56b71636L,0x6ebb841f38693cd1L,0x00ef6a7b60e7cf67L, + 0x29ecded2c258bcb9L,0xb2d566a5e40fd26aL,0xa2910f4ed512abffL } }, + /* 24 << 273 */ + { { 0x56d6515604dc109cL,0xcd740cc809c1d307L,0xef9e049f10dfaeadL, + 0x19750b3ae30b70b8L,0x11ed860015c6a562L,0x53bdf97e12097026L }, + { 0x79559d056c0d908fL,0x8f1d75bab506d527L,0xd6fd7323ae8fb3c4L, + 0x834639c9a4111f88L,0xfc69a029a310a683L,0xa4467bbb255f2e9aL } }, + /* 25 << 273 */ + { { 0xa809a063e9e3953fL,0x09242dc960dc53fdL,0xa48f52d00080c436L, + 0x762a585dad2eb70dL,0xc6d52f047a3c6aa2L,0x1b6979dcbe60899cL }, + { 0x7a07af246d760794L,0xa5b1f912ef5c1118L,0x36367e4375bb329eL, + 0x594f349029e6bddbL,0x13cdc4aaa4a4f1edL,0xa7c3ff97b687a69dL } }, + /* 26 << 273 */ + { { 0x1e79881146f7c4c0L,0x25730855946abf8eL,0x1741fdeeaac2031eL, + 0xef34715b72ea60b6L,0x378eb680350ddcfbL,0xe72ac880ec237141L }, + { 0xb173251fff125bf8L,0x37ffb0cf4999b6daL,0x9eeb91a8817779f6L, + 0xa9edff0ae93ed1f3L,0x31f2ca241d7772d6L,0xd25c3f3b97f67b92L } }, + /* 27 << 273 */ + { { 0xb6c4144381478e46L,0x7b53d46350cf8795L,0xe96e7cb9ca5bf2d2L, + 0xc8fa39c695ac9ba6L,0x8ab037d12efc83d1L,0x0ccacbcc94bc2536L }, + { 0x45e7c7c774038e13L,0x47d5b7292f5e344eL,0x2e0ffb2cb1eed282L, + 0xfe88d3a88d5d0b37L,0x804b612e2487d971L,0x6f316d66c95d08faL } }, + /* 28 << 273 */ + { { 0x5f0a58a8a3526fecL,0x849c171b02f028c1L,0x34d77ce856a5d3b5L, + 0x9701621754d5a92bL,0x0cce35c12cc5b70bL,0xd9d5a00ae83f1f4aL }, + { 0x064223f826a0368bL,0x328a9f6940e16452L,0x3a6ac093d305ad2cL, + 0x759d9a16beba7c44L,0x86021de7637ce7c8L,0x276bed61cc80c1ccL } }, + /* 29 << 273 */ + { { 0x5d4a529ef9822e60L,0xc6f2702006edd801L,0xb2511d84efa3d8d6L, + 0x38cfba656a4c6598L,0x31a5779765c067a9L,0xcee558f387d2ca0aL }, + { 0xf22345cff844260aL,0x29b6352a63d2ae75L,0x59dad0ab6cc9f2bdL, + 0x615ad3599ae1bcb3L,0x3a29a237f692f42bL,0x543771c40f26163aL } }, + /* 30 << 273 */ + { { 0x427437e7d722576cL,0xc9d7ac7abb548ef5L,0x72f00f28c331a9e0L, + 0x5d9327b564949b48L,0xea75f3b54e2bb808L,0x28acdea068678f8bL }, + { 0xe9e787b20878223fL,0x213f47ff7e7b0a11L,0x5e967d39f277a3f7L, + 0xe6651015d2006de4L,0x49b87e4bc44eb1e0L,0xf461bb76222cd3a2L } }, + /* 31 << 273 */ + { { 0xd6b9341fde60d963L,0xb1a8dd0d5319a930L,0xc4f18dc0aa6b20b5L, + 0x787de2e7f23f4401L,0xc15b38eb28047029L,0x0bffc0b55c99d51aL }, + { 0xf0310f39740b5798L,0xf69ea1064ed8d3bfL,0x545a54d79f6722aaL, + 0xe5a9dee3af4017c2L,0x45efa2ec4a659592L,0xc5d64bedbed4e245L } }, + /* 32 << 273 */ + { { 0x66797f56bbe4bddaL,0xb92a369eda51b1a2L,0x18eef4a531adb034L, + 0xcf1cb5ee5d185cfcL,0xf596a59bbd53c27bL,0x1e1dd6f569002569L }, + { 0xd9433e797687e48aL,0x7d8d24c20cbcb9ceL,0x233cd7ed65d68ecdL, + 0x201bbe09fb2aded8L,0x987f4975ac9b750eL,0x949da385337f7f25L } }, + /* 33 << 273 */ + { { 0x31439e35b95fd11dL,0xf97e8fa4b691fb77L,0xcfdc02956d4ac378L, + 0xd31bc3b0d1a617c8L,0xd857098204bd015bL,0x30cca6efd6198f0dL }, + { 0x6a52650a805964edL,0xb656d7abd060eeb3L,0x5267f37ed38a9218L, + 0x5f28a2ecd3d6a193L,0xb7dc6e916d0d9c9eL,0xa7f84e4b219d45c6L } }, + /* 34 << 273 */ + { { 0x550ef2713398c3dfL,0xfe184954307631a8L,0x02cef50606e5cde4L, + 0x9687a39c10f11703L,0x02c35937acb10b97L,0x835b00fd13e3d219L }, + { 0x5828678b584d1abaL,0xbe55fb9cc9b40568L,0xe5a4a90e8fe19e84L, + 0x91e24c9248989b77L,0x094f9e7ae3d5f4fcL,0xfe9bdfb9759029b5L } }, + /* 35 << 273 */ + { { 0x43b1f8b9c1de72e9L,0xcbc8e0d4a3bdb164L,0x5c45d3dfbcc2e5bdL, + 0xb5137b69247bef53L,0x6d889f5673794e3cL,0x43e2fc9b1e2dfdc1L }, + { 0xda15dc5da995d3adL,0xa0db9f5ec43d86e0L,0xc42a144bcaac3bbfL, + 0x3c855fb174c43eddL,0x0731f33152688272L,0xc1f23e5643d7762aL } }, + /* 36 << 273 */ + { { 0x00c2ee1c9c7de99fL,0x28a7461d15e50391L,0x1bdc0e32a1c77952L, + 0xe98242c4d53d640dL,0x1a4724d2cf153c7dL,0x194e5dccba477d46L }, + { 0x871c8cfe3a0d4ccdL,0x62010af09af451fbL,0x9b354f9e6ddec75cL, + 0xe5db0a5d680e3511L,0x183d1270d247745bL,0x9910867aeecf52dcL } }, + /* 37 << 273 */ + { { 0xa970903e8bc2003aL,0x0f8bcfa4a3cf29bcL,0x7054f69e683a7ddaL, + 0x53928bf1ece30167L,0x2588bdf1ffffea87L,0x01683b5ed7172ad4L }, + { 0xa0ac85379de7e713L,0x217bcdfe9b0442bcL,0xba46b8f64d4adb3eL, + 0x320580990a9f8ecdL,0x0173b7bea504bdc5L,0x15321aeb82b1606fL } }, + /* 38 << 273 */ + { { 0x4f349e5f6e39d625L,0x37cbd935b80760d6L,0xb8657ee14b1e84c2L, + 0x502954064cb84bdeL,0x66d678cce8d23ef5L,0xcba173713ec3b79cL }, + { 0xed7ab3e526e3cee5L,0x34c68c516c44ef0cL,0xd704e724f8fdd226L, + 0x2fa0d2dd3a9b40a7L,0x373c5c70a23be590L,0x0beb611bda9f7f7dL } }, + /* 39 << 273 */ + { { 0xef506531913bc31bL,0x31210c5f8c320074L,0xb42faf19b861acc1L, + 0x26f09b89e041e774L,0x23fec89822f84c93L,0x9f8b9d708ec590bfL }, + { 0x604d7d2952644790L,0xb77e3136a2339c53L,0x17f1d7a920f2fc09L, + 0x8c6435d9e6bb96eaL,0x5cafeb5f3711b8a7L,0x1ec6c4edfa23ca24L } }, + /* 40 << 273 */ + { { 0x6fb6b7bc0410ca0bL,0x0e16eed2b3c13935L,0x98ad89d8316ff531L, + 0x4800ee179894d65fL,0x034ea3c448280170L,0x8126d12dc30be537L }, + { 0x43c2d27e5120e525L,0x96a5d498ee65df90L,0x654540105eaef29aL, + 0x1d8f07a17b678fc7L,0x54bc6f737b301270L,0xe58a8102e9473365L } }, + /* 41 << 273 */ + { { 0x1fa3a458aaaf79f6L,0x1d14ff613a1b7c64L,0x32c7da68f22ddb3cL, + 0x7b2345ac58cff63fL,0x214e6d9dce3c3af9L,0x36fba0b78b6691deL }, + { 0x69fd813cee1a30abL,0x50daffe91adf6215L,0x55b34de692871a84L, + 0x437f1b4b7ff3ea1aL,0xc3258ca580ff1c23L,0xdc220ffbc6d0b822L } }, + /* 42 << 273 */ + { { 0x93e56b47ad910b37L,0x8cbce4815d20d236L,0x25b50cac5872d763L, + 0xb50aa752d8505696L,0x02075e6d6f42b533L,0xf0b34a178f8d8352L }, + { 0x59f2feda5234531bL,0xb23e1da1751127c8L,0xe1f65e08b6759ccdL, + 0x47d8631c352e9500L,0xab10d299c13feb16L,0xf9e916a3e5c6a220L } }, + /* 43 << 273 */ + { { 0x55899ffdc06f1b65L,0x4f9ec6e011899630L,0x0df97edc50a29319L, + 0x5c4a10ea5e66f0adL,0xea7b4497aa3d14e9L,0x484d8f64d22cc470L }, + { 0xd7fd252240a61a0bL,0xebd9f49d42d04a79L,0xf18ba2ec312ddb99L, + 0x687273ec2dce1351L,0x68d8b052d0220e57L,0x2c0ecd6b05a7e3dcL } }, + /* 44 << 273 */ + { { 0x460c29904ac6cf02L,0x01482cfa420a35b7L,0xf793933a34680972L, + 0x2cd1f50017e2367bL,0x2411c3523944f060L,0x3d58b97411c06b05L }, + { 0x4552e369cddebb3bL,0xe1c38aec009aeab9L,0x9d34737c353b6e4fL, + 0xf2c99e2cb16d7b0cL,0x57029fa47bbba6a2L,0x0565d1bcd13ef64dL } }, + /* 45 << 273 */ + { { 0x93a50cc7eb0112a9L,0xa0d4419984a59bdbL,0x04b9538c82d01160L, + 0xdb1d33e163a8d5a3L,0xa710beff08d3effeL,0xc2f37326f9bf02f4L }, + { 0x606b6b5555d26856L,0xf528d22a427fe3d7L,0x31b20fac84fb5086L, + 0x27129aa592f7e7bcL,0xd88f0d4f44171b33L,0x9b045c897915ede1L } }, + /* 46 << 273 */ + { { 0x0b15ebebcbe014d6L,0xa4f1504e68d24086L,0xbcf475c979d7c8b6L, + 0xd61b92a8d00a6890L,0x78e096742ee24533L,0x6fe9fe6099656101L }, + { 0xc9542f53e5e63e28L,0x59ec39e12edf3a80L,0x8fe57ffe24ad9280L, + 0xbae0671bf4b9b024L,0x76e36c14d5816ae9L,0xe53256d4805f8688L } }, + /* 47 << 273 */ + { { 0x006956bfcf9e545bL,0x7829ed13e8fa2ee4L,0x1b108d77d4dd6f85L, + 0xf51217bb17045f1aL,0x48c4802986141bd6L,0x8d59b995f8820213L }, + { 0x8439949ffc298a9eL,0x967fdcb278188d77L,0x5bbdfd296f35c711L, + 0x25b37e5df8e62607L,0x18f5c4251795cccaL,0x260f075af0e35ff5L } }, + /* 48 << 273 */ + { { 0x3561b3fea329deb1L,0xfdca0e34f1c3c3e4L,0x4374831347fb79d6L, + 0xa7f497e1c48002edL,0x86221cce2c44dcb0L,0x65e3f04643785e06L }, + { 0x9ee9061fdf4cf461L,0xc7479e8cf022d27aL,0x1d8de85b76f7f52bL, + 0x39a713c90fd6c65fL,0xf74ca067711f8a39L,0xad1119ad8ebc640aL } }, + /* 49 << 273 */ + { { 0x43d9bcba57ec124eL,0xbce6aed98cc29801L,0x1dbb88c72632e757L, + 0xe88f49e891f550e5L,0x056f67da7b6e1b05L,0xa503271082a027bbL }, + { 0x8471fa55c91844a9L,0x882f25b628479daaL,0x96f606dfa9c23504L, + 0x6a42d307fb7fa83dL,0x531c8a5cea310e34L,0x7e2d20565b2e42f0L } }, + /* 50 << 273 */ + { { 0x547047862e8c467eL,0x26f5efc690e52377L,0x762d8f767f6e71afL, + 0x5fc1bd13917ff587L,0x487f6c63fb696a60L,0x889a1dcc3afd2aebL }, + { 0x7407d0a0adcf4b35L,0x8f6c9aef91024ecfL,0x3384f1c03e5d9da0L, + 0xf87acb00b846d122L,0x6d86aebddceb383aL,0x6a5a90cda8f2d076L } }, + /* 51 << 273 */ + { { 0xddff7aa3feb71de1L,0x431e106be44644a9L,0xafe96f8ed5190b4bL, + 0x31a4dfe40ab42a27L,0x0e2d0cc435762eccL,0x7c928cd91fefb256L }, + { 0x5f33c775daeb94f9L,0xa7a91f8894c239b7L,0x6bf418fb4deda3c9L, + 0x91ad6e99eefd4f99L,0x7aae05559c25448fL,0xfb7ed9df487b4deaL } }, + /* 52 << 273 */ + { { 0x59753bf68ba85dffL,0xec8b82efd1c89bceL,0xd7f1a651b8b6a683L, + 0x9c329bf36f84416dL,0xaecbf4b9e68db225L,0x94ec3b0f5a614d23L }, + { 0xbcb6672593a9543dL,0x90c46c46f19132edL,0x4767c73c950b080fL, + 0x0b9b143e971fd9e5L,0xbce6886f8ec8c68dL,0x167b0f8ad47f512eL } }, + /* 53 << 273 */ + { { 0x51517f9481819dd9L,0x2c2640a0fdd7cef9L,0x59283faabf98b8ffL, + 0x39713768a46ad877L,0x13d9c0e6834dcf0cL,0x38c85473cc7acaddL }, + { 0x7b58c7666971a512L,0xbe46a58c2a38e57eL,0x3d26d0a06972e213L, + 0x2341769b63cd0aabL,0x4a293dd0e86307eeL,0x8d1e338d264c81a1L } }, + /* 54 << 273 */ + { { 0x66eb8beab2d5b430L,0x50b4af4382136220L,0x6644e673e79d0b5bL, + 0xe64cdf10f9fa7610L,0xf1dea591132ff33dL,0x07791ab6b926c725L }, + { 0x6c41b4f383f60e02L,0x54bc9049977519c3L,0x618a6f3c2aef73a4L, + 0x42cfc9d26fa4ca2bL,0x2784db71a39a215dL,0x378071655cc85253L } }, + /* 55 << 273 */ + { { 0x9cc3ada3554a7f23L,0xa822f9f21c3d0003L,0xb1654da7303123f7L, + 0xbe33e388f0d8c4a1L,0xd8919c79be4366e8L,0x5a41c92cfe292117L }, + { 0xc4b02d0678c325c2L,0x89eaf4356d511c4aL,0x726fb6d65fda70a0L, + 0xaf7949a0183abdf1L,0x3410915d26f8f929L,0x36b3aeb281f0f83dL } }, + /* 56 << 273 */ + { { 0x1942c2ffcd74009dL,0x71c4d5f5e9c286a4L,0xf3c152b5771a5972L, + 0x4cfb1e74363c2048L,0xcd2ce8249ddb8da2L,0x5d97c8e0a5ee443dL }, + { 0x6fa84b3d68d7b3d5L,0x97eaa76d9ce14ec3L,0x2e4571368e13869dL, + 0x39ac6a0c96f0f8a1L,0xe24458ac42d93dc0L,0x7eb3689d5f60bec9L } }, + /* 57 << 273 */ + { { 0x75592736bce6ebe3L,0x84001a886777bd90L,0xe82739774a31ca6bL, + 0x6906baf0a8e0dd38L,0x92af56d0848d0c92L,0x7ae700c6501326d0L }, + { 0xce418817470339a9L,0x4354d7928e448dfeL,0xc8f593afa48e3148L, + 0xdd5fee34db1a96b2L,0x5974e81e357960c2L,0x7326bf016306fdabL } }, + /* 58 << 273 */ + { { 0x74183618de017cd9L,0x939c7975dcfe6dbfL,0xcad9f8a108ec41e5L, + 0xd9edb91d391afcddL,0xadf1f18c7c4a3f03L,0x0566d3e8ab477304L }, + { 0x32ae20464c19c62cL,0xfa15fdcb252c8c4eL,0x2ed4767e91de2794L, + 0x622e4f38507f8067L,0xd647242bc68ac330L,0x0650e0a9fc1ccf29L } }, + /* 59 << 273 */ + { { 0x6ecd68a086085cc3L,0xb463f4c165c0cc54L,0x3182cc5c480bc57dL, + 0x8f16f2038e6d9267L,0x8c92e446df0d0ee9L,0x7da6001ba4d09789L }, + { 0x596390ff976ee9d0L,0x12b8f9dee4c0fd5fL,0xad08673f297b10f2L, + 0xc8e9097c7b524a51L,0xd494f0d3009cf47cL,0xf535c07abcdd1b68L } }, + /* 60 << 273 */ + { { 0x29544fe8588360ecL,0xa1aa9b9fffb550eaL,0xe1f6cf994af4d28dL, + 0x723d48b00c6fd477L,0xf51f1b2f5c81b252L,0x88ec11c04f5a33eeL }, + { 0x7747f0432cd72de4L,0xcca69b0ad71c92c1L,0x9455d86e4e8cc763L, + 0xc9e0aa1bc08444e0L,0x93803b68e8fffa63L,0xc296af292d781b7dL } }, + /* 61 << 273 */ + { { 0xb1891a2b17329e31L,0x87c2a49056e36717L,0x8c2a50fafd26d8b3L, + 0x017e4e417e3c5a5fL,0xbeb4fad0506c382eL,0x5d3e8b16fc281ec9L }, + { 0x407f7598890e57a0L,0xda855e8b340cd6d6L,0xb9393129ff388d54L, + 0x41113ffdcf355d9eL,0x31d3bb09b357c28dL,0x975bdf00fd39e481L } }, + /* 62 << 273 */ + { { 0xbfb0c87e10a1b4f2L,0xfaf51153dc2fcc04L,0xd2588e39d6b98d81L, + 0x5de5b0eb4953133dL,0x6b65d8135b959ed6L,0x864511dc02eb45bdL }, + { 0xb1dcb4d3d7ce20bdL,0x917bcd0987587230L,0x0935790f83a79453L, + 0xdc65862e54b35d76L,0x4cd2332ba6d1eeeaL,0x0706fcd030d315b5L } }, + /* 63 << 273 */ + { { 0x7c91adb3adf2d8d1L,0xfe1549c24a212fd3L,0x8a7cc285c33213b3L, + 0x26643cfd3e56d17bL,0xcc007c15684c872fL,0x485643e009e554f3L }, + { 0x7f5e9a6ec6569206L,0x252b5393c2f596d6L,0xf7eef1dbbf9cdea5L, + 0x611ee7334dffab46L,0x8d93802a805e976cL,0xd07c0ac6f85c939cL } }, + /* 64 << 273 */ + { { 0x514cc1dcb08d2d0eL,0x4e6b379e30e93536L,0xf0e422ac2fc9230fL, + 0xaa50a1ad92e23e21L,0x70ac46d8676d1ac0L,0x698b9991f9f54493L }, + { 0x59a6b86a8649519fL,0xc1f11ad6e3511da4L,0xd3d9cff13192968cL, + 0x13e700b40b342dd8L,0xfd5dc7bb3b1da441L,0x02426e7c2c883760L } }, + /* 0 << 280 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 280 */ + { { 0x9e9af3151c4c9d90L,0x8665c5a9d12e0a89L,0x204abd9258286493L, + 0x79959889b2e09205L,0x0c727a3dfe56b101L,0xf366244c8b657f26L }, + { 0xde35d954cca65be2L,0x52ee1230b0fd41ceL,0xfa03261f36019feeL, + 0xafda42d966511d8fL,0xf63211dd821148b9L,0x7b56af7e6f13a3e1L } }, + /* 2 << 280 */ + { { 0x3997900ecc8998d6L,0x8fa564b7baa60da1L,0x71bf5b0a661f3c57L, + 0x44b13388aab1292bL,0xcbe80cb9d4d993f2L,0x0b19b4c92203f966L }, + { 0xbc82a6520080f259L,0x870ebc08ad96dea3L,0xa388c7e7502f0003L, + 0x9c704ef056a38f73L,0x93cde8a73487d9b0L,0x5e9148b0ec11a1f3L } }, + /* 3 << 280 */ + { { 0x47fe47995913e184L,0x5bbe584c82145900L,0xb76cfa8b9a867173L, + 0x9bc87bf0514bf471L,0x37392dce71dcf1fcL,0xec3efae03ad1efa8L }, + { 0xbbea5a3414876451L,0x96e5f5436217090fL,0x5b3d4ecd9b1665a9L, + 0xe7b0df26e329df22L,0x18fb438e0baa808dL,0x90757ebfdd516fafL } }, + /* 4 << 280 */ + { { 0x63f27a25a748b8f5L,0x68c8f3ec2cd246c4L,0x5d317cd965f9ce38L, + 0x162c92e0635ba300L,0x5259f64ffe343662L,0x4a6b2b668e614ac8L }, + { 0x97fb55bb01177c3bL,0xfb586c21a705cb01L,0xa57e732578061824L, + 0x892f6b386c1e6306L,0xf12e4c072367b14cL,0x580d5fe2c83a48c5L } }, + /* 5 << 280 */ + { { 0x1e6f9a95d5a98d68L,0x759ea7df849da828L,0x365d56256e8b4198L, + 0xe1b9c53b7a4a53f9L,0x55dc1d50e32b9b16L,0xa4657ebbbb6d5701L }, + { 0x4c270249eacc76e2L,0xbe49ec75162b1cc7L,0x19a95b610689902bL, + 0xdd5706bfa4cfc5a8L,0xd33bdb7314e5b424L,0x21311bd1e69eba87L } }, + /* 6 << 280 */ + { { 0x6897401cea2bafb3L,0x7b96ecc215c56fe4L,0xe511b32939e2b43bL, + 0x39522861bf809331L,0x815f6c1dc958f8f4L,0x2abbdf6bc213e727L }, + { 0xeb09ae59c39bc01fL,0xffe3b831676b56a5L,0x8f4815a2a20f86c6L, + 0x748a17669aa30807L,0xf1f46a211b758878L,0xbd421fe76f6fc3d7L } }, + /* 7 << 280 */ + { { 0x75ba2f9b72a21accL,0x356688d4a28edb4cL,0x3c339e0b610d080fL, + 0x614ac29333a99c2fL,0xa5e23af2aa580affL,0xa6bcb860e1fdba3aL }, + { 0xaa603365b43f9425L,0xae8d7126f7ee4635L,0xa2b2524456330a32L, + 0xc396b5bb9e025aa3L,0xabbf77faf8a0d5cfL,0xb322ee30ea31c83bL } }, + /* 8 << 280 */ + { { 0x300b04840d6ded89L,0x0b1092cbc3ab55edL,0x17d9c5420cc10a74L, + 0x7f637e84eff9d010L,0xd732aa1e27aa1285L,0xedb97340e2a77114L }, + { 0x62acf1585ef4dfb0L,0x1e94fc6eba1d7b81L,0x88bec5d22e6eb2dbL, + 0xaec272028d18263dL,0x4b687353e4bbd6acL,0x031be3510ff7e4c0L } }, + /* 9 << 280 */ + { { 0x048813847890e234L,0x387f1159672e70c6L,0x1468a6147b307f75L, + 0x56335b52ed85ec96L,0xda1bb60fd45bcae9L,0x4d94f3f0f9faeaddL }, + { 0x6c6a7183fc78d86bL,0xa425b5c73018dec6L,0xb1549c332d877399L, + 0x6c41c50c92b2bc37L,0x3a9f380c83ee0ddbL,0xded5feb6c4599e73L } }, + /* 10 << 280 */ + { { 0x6c00f388f086d06cL,0x17ee45035add0cf4L,0xf96984c707caf89cL, + 0x9d49d667648ed5e9L,0x3ef95015a0164881L,0x39e28e447d9c651fL }, + { 0xb13ad24059f37780L,0x08cee349b9522225L,0x9245ee6f2ba1b214L, + 0x12bedaa9a886d8d2L,0xe139ae08fcb8186fL,0x99203fb6fc2ef864L } }, + /* 11 << 280 */ + { { 0x14d34c210b7f8354L,0x1475a1cd9177ce45L,0x9f5f764a9b926e4bL, + 0x77260d1e05dd21feL,0x3c882480c4b937f7L,0xc92dcd39722372f2L }, + { 0xf636a1beec6f657eL,0xb0e6c3121d30dd35L,0xfe4b0528e4654efeL, + 0x1c4a682021d230d2L,0x615d2e4898fa45abL,0x1f35d6d801fdbabfL } }, + /* 12 << 280 */ + { { 0x3c29284764c9323dL,0x40115a890491f77dL,0xec141ade2d7a05f5L, + 0x0c35e4d9222a5f9fL,0x5ea51791442a3e9bL,0x17e68ecee51b841eL }, + { 0x415c0f6cd6ae9174L,0xe6df85f89ffd7595L,0x65fc694f8dedf59cL, + 0xc609503efee92718L,0x57d2592e97d565aeL,0xb761bf157e20862bL } }, + /* 13 << 280 */ + { { 0xa636eeb83a7b10d1L,0x4e1ae352f4a29e73L,0x01704f5fe6bb1ec7L, + 0x75c04f720ef020aeL,0x448d8cee5a31e6a6L,0xe40a9c29208f994bL }, + { 0x69e09a30fd8f9d5dL,0xe6a5f7eb449bab7eL,0xf25bc18a2aa1768bL, + 0x9449e4043c841234L,0x7a3bf43e016a7befL,0xf25803e82a150b60L } }, + /* 14 << 280 */ + { { 0xd443b26582376117L,0xb91087c11a1beb0dL,0x3fe62a6545cc5951L, + 0x49c754bce6e472d5L,0x7e60bb8177c424ebL,0xbcd4088e830cbb97L }, + { 0x3da5c94eba26df7bL,0x508b4f55f72b4338L,0x409c5c7469ad7784L, + 0x82e5f1b0fdf44d6aL,0x10654a1ceed2766fL,0xef1e65faa6e83f4aL } }, + /* 15 << 280 */ + { { 0xe44a2a57b215f9e0L,0x38b34dce19066f0aL,0x8bb91dad40bb1bfbL, + 0x64c9f775e67735fcL,0xde14241788d613cdL,0xc5014ff51901d88dL }, + { 0xa250341df38116b0L,0xf96b9dd49d6cbcb2L,0x15ec6c7276b3fac2L, + 0x88f1952f8124c1e9L,0x6b72f8ea975be4f5L,0x23d288ff061f7530L } }, + /* 16 << 280 */ + { { 0xa6e19d0a5f56dc3cL,0xe387e2690b88326aL,0xef7380950ee527a4L, + 0x78b7174b7c4278a6L,0xc133d867e70798ffL,0x9d0fef759e9230caL }, + { 0x7431eef01a955ab9L,0x3772e7038868d922L,0xf7a4306a8d6af3f7L, + 0x633bb5a0bbec076aL,0x6d07623e7a257ca3L,0xffb5e16521c00663L } }, + /* 17 << 280 */ + { { 0xebfe3e5fafb96ce3L,0x2275edfbb1979537L,0xc37ab9e8c97ba741L, + 0x446e4b1063d7c626L,0xb73e2dced025eb02L,0x1f952b517669eea7L }, + { 0xabdd00f66069a424L,0x1c0f9d9bdc298bfbL,0x831b1fd3eb757b33L, + 0xd7dbe18359d60b32L,0x663d1f369ef094b3L,0x1bd5732e67f7f11aL } }, + /* 18 << 280 */ + { { 0xfab0ce2bee1ae33dL,0x7bf9f90b4c5692e3L,0x131a4374d776d6caL, + 0x6ba40908a2b135afL,0x5c4ab997e1334bf8L,0x9eb442d07af584e9L }, + { 0xd764c506786391c1L,0x07f24c6bbcf6ab3aL,0xf73c7924fad8e1bbL, + 0x79f624acb7583623L,0x2b032021b44c14d3L,0x7cc0ae8dbf58ff99L } }, + /* 19 << 280 */ + { { 0x3c7fb3f5c75d8892L,0x2cff9a0cba68da69L,0x76455e8b60ec740bL, + 0x4b8d67ff167b88f0L,0xedec0c025a4186b1L,0x127c462dbebf35abL }, + { 0x9159c67e049430fcL,0x86b21dd2e7747320L,0x0e0e01520cf27b89L, + 0x705f28f5cd1316b6L,0x76751691beaea8a8L,0x4c73e282360c5b69L } }, + /* 20 << 280 */ + { { 0xe4d7c8b88929c133L,0xe5f96bef92a813c7L,0xdb8ab0af71c18e09L, + 0x0db6ff287dae63b4L,0x54d1fac49a1eaa73L,0xadbcfdf59180c980L }, + { 0xd3220f300b584314L,0xa24e4d1cca3697c7L,0x4ade8c7fa44f8067L, + 0xbd8bc81aca21ac17L,0x303a2f9fc1d361cfL,0x55648b65c71cf031L } }, + /* 21 << 280 */ + { { 0x46bcc0d5fd7b3d74L,0x6f13c20e0dc4f410L,0x98a1af7d72f11cdfL, + 0x6099fd837928881cL,0x66976356371bb94bL,0x673fba7219b945abL }, + { 0xe4d8fa6eaed00700L,0xea2313ec5c71a9f7L,0xf9ed8268f99d4aeaL, + 0xadd8916442ab59c7L,0xb37eb26f3f3a2d45L,0x0b39bd7aa924841eL } }, + /* 22 << 280 */ + { { 0x6f8135c7ce89e8daL,0x21ac20d9d6b5948eL,0x1dc4d48b31cefd7eL, + 0x3d34bc2a4a347926L,0xadcd11be8f614fd6L,0x77148b08a8ea116aL }, + { 0x7afc75fcfce1d3f5L,0xa9e0557d7d9a8ea3L,0x640cb5850cc864ecL, + 0x5811ba842eb332c7L,0xb6c10b6efdb668c4L,0x24d8b10f99f5f6c7L } }, + /* 23 << 280 */ + { { 0xd811eb32e03cdbbbL,0x12055f1d7cc3610eL,0x6b23a1a0a9046e3fL, + 0x4d7121229dd4a749L,0xb0c2aca1b1bf0ac3L,0x71eff575c1b0432fL }, + { 0x6cd814922b44e285L,0x3088bd9cd87e8d20L,0xace218e5f567e8faL, + 0xb3fa0424cf90cbbbL,0xadbda751770734d3L,0xbcd78bad5ad6569aL } }, + /* 24 << 280 */ + { { 0x391fa3cd8d075ec5L,0x54d45020c84c81e5L,0xdead561a79fad87cL, + 0x0ab3c8544e7ffc48L,0x5967f8ebff02706cL,0x8860de795d31ec98L }, + { 0x7476459c6c8a1c25L,0x8d9c484082f16117L,0x5c1b13b33b413429L, + 0x1962a435601b5906L,0x78b9d382e006929dL,0x1924e979e5897b16L } }, + /* 25 << 280 */ + { { 0xcadb31fa7f39641fL,0x3ef3e295825e5562L,0x4893c633f4094c64L, + 0x52f685f18addf432L,0x9fd887ab7fdc9373L,0x47a9ada0e8680e8bL }, + { 0x579313b7f0cd44f6L,0xac4b8668e188ae2eL,0x648f43698fb145bdL, + 0xe0460ab374629e31L,0xc25f28758ff2b05fL,0x4720c2b62d31eaeaL } }, + /* 26 << 280 */ + { { 0xef1001dfbdb22e61L,0x1626bd9af384bbf5L,0x33f42d385fe8ae07L, + 0x59646c42b7218d21L,0x5e27210e6a016f5dL,0x3e9ecf07094481c3L }, + { 0xf91609c1f50cc2dcL,0x8bf8c05ad0d43633L,0x9d508972e74ab746L, + 0xb625887a33f628b7L,0x557bd493e733952fL,0xd35f450b8981dcfbL } }, + /* 27 << 280 */ + { { 0x4603cdf413d48f80L,0x9adb50e2a49725daL,0x8cd3305065df63f0L, + 0x58d8b3bbcd643003L,0x170a4f4ab739826bL,0x857772b51ead0e17L }, + { 0x01b78152e65320f1L,0xa6b4d845b7503fc0L,0x0f5089b93dd50798L, + 0x488f200f5690b6beL,0x220b4adf9e096f36L,0x474d7c9f8ce5bc7cL } }, + /* 28 << 280 */ + { { 0x531c43cdb63f3d28L,0x01289772429708dfL,0xb0ee772ccdb60078L, + 0x4131f5cd5f1a6e72L,0xd9d0f8c6a0da0112L,0x58efddd204e957b1L }, + { 0x18857c0c32840c31L,0x00825340c4068b2cL,0x0a9217a771ff8800L, + 0x69b19e6415530b80L,0xa28e274ee125e3f2L,0xb471a91bc9bfc846L } }, + /* 29 << 280 */ + { { 0xfed8c058c745f8c9L,0xb683179e291262d1L,0x26abd367d15ee88cL, + 0x29e8eed3f60a6249L,0xed6008bb1e02d6e1L,0xd82ecf4ca6b12b8dL }, + { 0x9929d021aae4fa22L,0xbe4def14336a1ab3L,0x529b7e098c80a312L, + 0xb059188dee0eb0ceL,0x1e42979a16deab7fL,0x2411034984ee9477L } }, + /* 30 << 280 */ + { { 0x01d04fe04ce2d199L,0xf434bcfd0517c7ebL,0x82f3aca4a7659a94L, + 0xf436a7781ff015c9L,0xf5143391d6223e5cL,0xba66c6a2ecb5c340L }, + { 0x080f158a4b23a041L,0xb401094cb699acafL,0x1c57626c677491dbL, + 0xfb39e317d42d86dbL,0x19e2ca804f6b3354L,0xe919c4c3c1d41ef3L } }, + /* 31 << 280 */ + { { 0xd65246852be579ccL,0x849316f1c456fdedL,0xc51b7da42d1b67daL, + 0xc25b539e41bc6d6aL,0xe3b7cca3a9bf8bedL,0x813ef18c045c15e4L }, + { 0x5f3789a1697982c4L,0x4c1253698c435566L,0x00a7ae6edc0a92c6L, + 0x1abc929b2f64a053L,0xf4925c4c38666b44L,0xa81044b00f3de7f6L } }, + /* 32 << 280 */ + { { 0x35ae891bbb71e9b0L,0x1f6ce6ca522b77f0L,0xc2dab3cae63745c4L, + 0x55b8c185f218d139L,0x6ab039c889f3b0e2L,0xd9e25bfdc644c3faL }, + { 0xc8496f203e2ed47bL,0xc395ec028d67e17cL,0x5c67839292114918L, + 0xe962e52fef73f345L,0x3818baf354fcfb22L,0x4d75d65d9d4bc911L } }, + /* 33 << 280 */ + { { 0x10078824eb7ff5fdL,0x50c65328735ef75fL,0xdfc04d53ec980ba2L, + 0x4bfb260f2d519cf5L,0x1f03dff15c854667L,0xd1ad2231badb625cL }, + { 0x986064d0be9f7f03L,0xe5ff93e5c13f7d0dL,0x02682a1896e26a17L, + 0xc421567c817ec3cdL,0xb740652352615c25L,0x6800a8335d135eebL } }, + /* 34 << 280 */ + { { 0xde57575b17d8ec5cL,0x72e2257578aeb9bbL,0xce73fa7731605c27L, + 0x2f286b79ae77436cL,0x5e78fbb77f4e6997L,0xb03c888e474f23a7L }, + { 0x4bb302a3e38927ceL,0x39c6de5f6e1514ceL,0x9daa0ad349b2ddbdL, + 0x98fd2377d683dffdL,0xbefa4ae5933476edL,0x4ad53d01173f49edL } }, + /* 35 << 280 */ + { { 0xdfafc70e44b89837L,0xe0104b9c4935fa88L,0x7625d9d92fd702e2L, + 0x27461e6549af2219L,0x4a279383ad3f36edL,0xd87e246b9204e857L }, + { 0x8d832190ab1727d9L,0x59205cd82182e291L,0xb96a1d15a6513613L, + 0x1c7de3cc49cc8ddcL,0x637ea26af17ab785L,0xc098bb7a09a3ba58L } }, + /* 36 << 280 */ + { { 0xfb5383cc31bd4f68L,0x6fd5aee3d96a1899L,0x4e39d6eb01d5430eL, + 0x12679565ca5a2848L,0xa399e83f062b44fbL,0x3ee2432f3c166682L }, + { 0x57229c841de47708L,0x40a5d0cbba528a61L,0x4bae36be8239e7baL, + 0xddac65a2f8087427L,0xfd516d1a3cc61266L,0xc89542b5bcef98b1L } }, + /* 37 << 280 */ + { { 0x3fc8d1b2d49cc0eaL,0xfc591f7f7bca4d23L,0x5f48e27c41fefdf3L, + 0x5ca1d08a1039419dL,0xd450c1bddc8042ceL,0x6760e23fb436fc4bL }, + { 0xc5642797c06bb34bL,0xb787cd53fde06d4dL,0x2926360ccbf144b0L, + 0xb63756f4dce32421L,0x0878deab774abc4aL,0x2d97c7919a4e142aL } }, + /* 38 << 280 */ + { { 0xf58389ff105c818eL,0xfa29f1eb585fa7f0L,0xb6da09b5917e8924L, + 0x1375c3047e7a3f49L,0x9b4792b289cfa1c0L,0x92094a8535571cc7L }, + { 0xf986ccf6051e5e50L,0x55ea34d601df6babL,0xe65989eed1363333L, + 0xd94bbd918c84e20aL,0x9a4f71dc49e39b8aL,0x6d9fe495927d633eL } }, + /* 39 << 280 */ + { { 0x30b295f01fdc29e2L,0x71415daae2c2fab4L,0x205e957683c312beL, + 0x893c69fefab48afcL,0x8108f3f994ca2fdbL,0x37c860c314f99296L }, + { 0x1009a6d2e990ed34L,0xd5350c36ac26b611L,0xd03161102ce23d91L, + 0x82bb476e62189343L,0xe255965160ef0cbdL,0x6bab3f53cf5d2311L } }, + /* 40 << 280 */ + { { 0xcaa3b7a592fa460fL,0x92bb46b804dff174L,0xcd6949b3cf926a1fL, + 0x01f95e5559d1bb18L,0x21f90c08d4518f3cL,0x325dbfe920ee8bf5L }, + { 0xd0136f3feafb919eL,0x941190cc8e0ebcabL,0x599e91a287b557aaL, + 0x7fac4887dcbde1c7L,0x1dad481905a07040L,0x640493978b03d593L } }, + /* 41 << 280 */ + { { 0x65521bb85ebd3685L,0x16c68e79665d1619L,0xd6ab56bbc52b14c8L, + 0x312f1fb4c6d3067dL,0x5afef4f3d50587c0L,0xa3e79e94ace6e2feL }, + { 0x52c7fa0825f12a1eL,0x9c1c1ea20dec9f3dL,0xc418d4232e87a036L, + 0xa0a19fbb0283752fL,0x52e0a8830b804506L,0xc67fc71b3f7de2a1L } }, + /* 42 << 280 */ + { { 0x4d062d3d7dad8ca9L,0xb78c81581cf59756L,0xaccb38f8c6b5d9fcL, + 0x83436d3f7ddc66eaL,0x37115b6033adcb87L,0x49b74bd45a8b09abL }, + { 0x7b8bdb81675ae43bL,0x5284f5b3f0476428L,0x8f1521e7db38b0c7L, + 0x792ef9dea0c4b2f6L,0xa15880a162159fc6L,0x70b999e372b09b63L } }, + /* 43 << 280 */ + { { 0x6f47787d4e8ffde7L,0x19e9434574495a10L,0x8da6d55784f5be33L, + 0x110844811884e325L,0x621734c5a9f030baL,0x25cd0544d0e63f63L }, + { 0xea6729687e936833L,0x08297af784a34442L,0xb77dc3a342f9ed3eL, + 0x9f8908c8258e8d4fL,0xb8281bfc3299ba4bL,0x1f6412920a09849cL } }, + /* 44 << 280 */ + { { 0xd5d51e60ee9a7708L,0x2e8ab3effd2cfe78L,0x0af5c3bac8e71273L, + 0xbfd1b94091041652L,0x4c7c86ab52ce4582L,0x3ab72feff1d9bc29L }, + { 0xae89c3d51e1974b3L,0xd859c7ef70433caeL,0x762064c77edd1398L, + 0xc0b6a6b6072064a4L,0x3ba43b059bb1b3d0L,0x20f9aa85e47d79bbL } }, + /* 45 << 280 */ + { { 0xd1a45415c2d001cfL,0x40f3f05d848a480fL,0x03708da0ce554d5bL, + 0xd7090557c80f4254L,0x7e57d29907743393L,0x7db8a5e10f2f5903L }, + { 0xd0466a0b14e8ff8bL,0xa3c38f49e0cf88b0L,0xde47262e329f71adL, + 0x56b2a7935da6d0a1L,0x22e1f9b880ef44b0L,0xb9b96c617b2b6d4bL } }, + /* 46 << 280 */ + { { 0x3235bc494c500ee1L,0xce0f0b54da4a4f35L,0x628cb91c337ac7b7L, + 0xd8a6d4cd88a26e9dL,0xdcf40cba96e44349L,0x073a0f75b54e3fa9L }, + { 0xc9b95d29ca44e6e8L,0x42ad9afa2315f4beL,0xdf13a5ddf78617c7L, + 0x40aeb346d196504bL,0x9317d6f33d1fef90L,0xf94d308fe1708a79L } }, + /* 47 << 280 */ + { { 0x45bc768608835815L,0x700d93bc5798c507L,0xae3415b85362a822L, + 0xdbce01b33883d21dL,0xb9df7efbe56fb2aeL,0x5ed57d9427d341c0L }, + { 0xdc26916e7ee4dfa0L,0xcdb06a17147c075fL,0x0198b6a7fa9e7a63L, + 0xc9876c786355b62bL,0x9f4b8f12f565279dL,0xa03aeb619cb6ddb6L } }, + /* 48 << 280 */ + { { 0x3a35938779493f3dL,0x128301a91f06a9c0L,0xfcce0f82899d204cL, + 0x4ca41589158780b5L,0xc28f1bb73c4edd4fL,0xe08e48a87a6aec34L }, + { 0x6d4783dfd447c55eL,0xe7c2ecc857803027L,0xb7b8c2bcdf6d7f91L, + 0xf0a8d4700f356ca3L,0x229894bfdeb8e964L,0x555c9d40d3aa70e1L } }, + /* 49 << 280 */ + { { 0xa899a252e0ace851L,0x74b716c9bb9d8476L,0x2ba0bb00571bb175L, + 0xee01a9bf7ac2b619L,0x74f0b6d3502ee575L,0x7fdd7856cc45f810L }, + { 0x68c0beb1c0ae384dL,0x21955de8fe63d58fL,0x1b98e3951c08bbd2L, + 0x5ddaf7e9638701b3L,0xefc264f1b1242d62L,0xa9b8de5c81292443L } }, + /* 50 << 280 */ + { { 0xf0d713b7131a3bf1L,0x690ae8c147e9f09fL,0x1dc92a5f8cd8bf1eL, + 0xdf98927ad61f5445L,0x729b5469ae795eabL,0x939b391c5265675aL }, + { 0x5d916c6c7bd7e97aL,0x7c2a3de5d514e72bL,0x0660758379e9915fL, + 0x0554d5e543a4d2c7L,0x37eb7f82ca5bca41L,0x90e41b71b640109dL } }, + /* 51 << 280 */ + { { 0xfdd403b0e6f769aeL,0xa67f97f6906a7981L,0xc86c49be6aa83c6dL, + 0x6177820677ab6d8fL,0x60f77c49916933b2L,0xfa33c528fcb3fe39L }, + { 0x102ffca0783cb589L,0x6a37a394a96ce10eL,0xd17bf1f89eb4695fL, + 0x2a7623af2a53116eL,0x10601afe83af2e60L,0xceebada2582a1704L } }, + /* 52 << 280 */ + { { 0xcbfb50fa57004c05L,0x0d545f0ea7bea436L,0xb7e30eb77071e269L, + 0x435b3df73b845896L,0x48ba27f0b246365eL,0x9fbe883341344f12L }, + { 0xb763df280a87ef33L,0x4f9339d70b5288beL,0xc02770d6e722e3beL, + 0x6c69bfd918e32f03L,0x20c5c05e74c2845cL,0x09fa0928d6f9279dL } }, + /* 53 << 280 */ + { { 0x82f43866962fccc1L,0x92bc5f82278c9762L,0xc979a68b39a39a08L, + 0xfcae204b97c5a298L,0x78f55c7908676082L,0x210e036447c7b09dL }, + { 0x24512cef47d87769L,0xb4b0fdd7e4b53f4fL,0xc2a263fff6818efdL, + 0xfa160dc1985bc93fL,0x7b7f82961bf44affL,0xd6c75fb2a6407cdfL } }, + /* 54 << 280 */ + { { 0xea0b6ec35741c57bL,0x9b148c2668ba5fd0L,0x6206025166461969L, + 0x0726919f8cfc618eL,0xf66ac684c1954bcbL,0x160ad0260273adb4L }, + { 0x0ec10cffe6f6aac3L,0x232fc7adb4f64d98L,0x0707cb6e73564063L, + 0x76daa2c5487a29acL,0xe4ffd6e335768176L,0x4ab87262464d126eL } }, + /* 55 << 280 */ + { { 0xdbc1d21c553f05efL,0x16e950d0dc115e4cL,0xa727059a354480a5L, + 0x32df221efd6711f1L,0x06f9bc2e5c8aa9fcL,0x9f2449a67b15522cL }, + { 0xac14774bf498ee00L,0x02b5979f3ec7e0a2L,0xdce96e06e1e00abdL, + 0xd7a1bf5a1e00e8a9L,0x19b30fd3a8f42042L,0x29b08eb7e7c507ebL } }, + /* 56 << 280 */ + { { 0xe91477d3a66b2f3aL,0xf50d3bdfc4deb7f5L,0x19bf2857a1e45e44L, + 0x1c104e3270a2126aL,0x4636b4894357b9f5L,0xf65e5aa0962d684aL }, + { 0xfcc83a5fb7b52893L,0x8451d02b08adbd4dL,0xf0fb410c19f7a896L, + 0x6b90b0faff36caeeL,0x111710d0f5af8966L,0x00a4cfafbd2b8c59L } }, + /* 57 << 280 */ + { { 0xad9f11cb817bd227L,0xe4733a1465d27b5fL,0xeda46e8dbcf76526L, + 0x8db309ecad57a5a9L,0x4a863ec07f1487a8L,0xb0453ed210f1c4c1L }, + { 0x9b4df78af2dbfd76L,0x62af38b21525e18cL,0xe6bd0b0ade2c7f65L, + 0xad62bfb70b27fad4L,0xd21fd4346d6a8a5fL,0x07b606703e401a5eL } }, + /* 58 << 280 */ + { { 0xdd14c891e34b192cL,0x6ddfcc793aed3e36L,0xc89c3e6dc49a92e2L, + 0xa61954fd6fcf1ce9L,0x420c39a9bd297157L,0x57c20a8a406d3f2fL }, + { 0x7ccda02263faf545L,0xb01814a96cca4388L,0x88baf1dce5fb1fd0L, + 0x9e1183cfa0bae755L,0x3fe540badbc243c2L,0xe50d52305aeb26a3L } }, + /* 59 << 280 */ + { { 0x10145b3d52726a98L,0x7236036869e333fcL,0xce9a409323a6f608L, + 0x61c121dcddd11095L,0x3349b30a0d39f1daL,0xd07df9d4e3485e93L }, + { 0xb4c500a561159e84L,0xbc74918100561c03L,0x8f27e9f3904ad807L, + 0x7272786a0108ed01L,0xcf36a5d9c9365dd8L,0xe052fc9d7f859d87L } }, + /* 60 << 280 */ + { { 0x0e6cd863da97e11eL,0x5b058c6852a818a1L,0x7768c5e73de760b3L, + 0x898b7f608dfb4142L,0xd48130977efec180L,0xd7196cd758279538L }, + { 0x67c451fb816858a1L,0xbf0e88912ac699b2L,0x21fa74effcb126a5L, + 0x1f9dc10123b8df5aL,0x38aefff921136ffcL,0x3408874c47cb395aL } }, + /* 61 << 280 */ + { { 0xded9035213054567L,0xc61d0628c58c633dL,0x73ff2589f31143c3L, + 0xc43594ff0871b05cL,0xcf662dd64db0edf2L,0x6bac019d8d1f33b0L }, + { 0xcaa37cd8bb379461L,0x9b077a6934fc0269L,0x421e716788ecedf2L, + 0x2d422f95073284cdL,0x9a353114bbb2409cL,0x99e8c7a0dcbb79e7L } }, + /* 62 << 280 */ + { { 0xfca254cba21c40f0L,0x4945c838e0f4a032L,0x99318ff3fd6cb7fdL, + 0xc631e0644a85e726L,0x2e3ca11d9359e8cfL,0x433a0e5c06acf935L }, + { 0x665c54c996b37ea9L,0xe78865c4c2d52b81L,0x68596f6ffb27850aL, + 0x7e7272221277995eL,0x602b0f5c197344c2L,0x81ff2ad620a9ec11L } }, + /* 63 << 280 */ + { { 0xb2ce6cbe7c4c464fL,0xd7c11ef5741a4b1fL,0xf3f987f621a7eb17L, + 0x6b2812ef79f4e274L,0x3a0117ae38a7d5ddL,0x5d8c75a9cfab6bb5L }, + { 0x3827c04052394166L,0x897eb181e00e621dL,0x6693817f8aa19361L, + 0x67cac329959d81a8L,0x21e7133869a7ca51L,0xa02fd11269a46a87L } }, + /* 64 << 280 */ + { { 0x7f1f985c022ea83aL,0x90a22662a7584e7fL,0xb40a930a5188fcf6L, + 0x3fad79aba3a82904L,0x7bee8d22f3151027L,0x79a1a838c2c3e17bL }, + { 0x1fbe06e933cc3509L,0x629c56aa9abd5ccaL,0xfff290ec2d9cf7a5L, + 0x5d0dedaa9bd062c5L,0x080344abd7d35381L,0x0848373af5cf9edaL } }, + /* 0 << 287 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 287 */ + { { 0x31d31f7a7a0c0bc0L,0x7a37a84ab251d2bfL,0x1793362e52f04d67L, + 0x5808e70921c7b651L,0x33fe9123ed6f47f6L,0xdeb1dde958f71405L }, + { 0x821d3045ae56b472L,0x9f61f761e02043adL,0x932ddb145b2048a9L, + 0x17d989fed7811330L,0x032ae4cb128fd85fL,0x8f1956b47d1ef434L } }, + /* 2 << 287 */ + { { 0x070d34e116973cf4L,0x20aee08b7e4f34f7L,0x269af9b95eb8ad29L, + 0xdde0a036a6a45ddaL,0xa18b528e63df41e0L,0x03cc71b2a260df2aL }, + { 0x24a6770aa06b1dd7L,0x5bfa9c119d2675d3L,0x73c1e2a196844432L, + 0x3660558d131a6cf0L,0xb0289c832ee79454L,0xa6aefb01c6d8ddcdL } }, + /* 3 << 287 */ + { { 0xe5d473dc7521f457L,0xe9ef09bda00be577L,0xf6d0965fb6eaa640L, + 0xeb49486875726560L,0x452116d528817302L,0xf0424fdbfbde3597L }, + { 0xd6096da3bb454915L,0xde48280841422141L,0x7a1351972d19fac0L, + 0xdc9a5ec421393f6fL,0xcabcc1e3eb2c8adaL,0xd436643142d8c4f2L } }, + /* 4 << 287 */ + { { 0x0ed1082f89e4e449L,0xdb1fb471833f2378L,0xa35fef0eece77352L, + 0x76adaa464bf0c426L,0xfbab929aa011b2fbL,0x6f475d5b9d8cc4d3L }, + { 0xbe6d7f2174351480L,0x2d1362d193e4a7aeL,0xc7e2cba5106ceaabL, + 0xfe94528a45258697L,0x7109b17d075945b0L,0xfd395b2ccae17f7aL } }, + /* 5 << 287 */ + { { 0xdf534b80dece6d4dL,0xcfaa60a28737af46L,0x7d76a921b9ba3d56L, + 0x61490bd199338721L,0xc514e950ed25cfbdL,0x5041fbb2dc09b8b1L }, + { 0x2410310d46fbcbf0L,0x2c46bcd14f7e8aa4L,0x08ce31f5d0d5fe1dL, + 0xb11efdbebeac3c97L,0x406e1d05b01633e9L,0xde48cdba766391adL } }, + /* 6 << 287 */ + { { 0x68550299845e12c9L,0x979b5406361d027fL,0xf601d2b4a8e92e70L, + 0xfd02799f0cc9fca9L,0x89f99ca013bc2e96L,0x22a12c0bff9db9b8L }, + { 0x6ae7084a32efcea8L,0x5ddd3ee9a24b9376L,0x394d92a4e0945e8fL, + 0xddab6752ecea36f6L,0x650b74d60d18a069L,0x37f91cebad650860L } }, + /* 7 << 287 */ + { { 0xe3e559bd9d839b3aL,0x50e8d4e9719de3c7L,0xf7bb377cea70b986L, + 0x63753cace1b2707dL,0xeb239a870e585c4aL,0xec40a379b0e32380L }, + { 0x836ebcefc86d6685L,0x703c296a70d18b76L,0x47e2c004b94aa268L, + 0x33ef7d0cbaf14d61L,0x74aa00fcd315c72cL,0xf23c789eccf5d75aL } }, + /* 8 << 287 */ + { { 0xfc1faedc310404a8L,0xea339148d3bcb128L,0xf00485456416defdL, + 0x75de7770c58653e7L,0xdd2dcbebe2f6f99eL,0xa4380ef4d159ac07L }, + { 0x45dd713ce4173608L,0x44919b61446a6789L,0x3f73756b6b962b38L, + 0x3cb9f53bbffd3f0cL,0xd723c40b7f08ebaeL,0x998a9b170c3cddbaL } }, + /* 9 << 287 */ + { { 0x261c9fe6f21ae889L,0xa589147edf3cb243L,0xd09452f71976deecL, + 0xf80ee8bf2497f6b2L,0x0b5f1b19eee697d4L,0xce9b6b680de48ab7L }, + { 0x3ad3bbc4bbf29546L,0x544406a697f51becL,0x51d44dfac2e2e75cL, + 0xcfc8625d3da3f634L,0x0845ace6a1f5995dL,0x11850d8bf3b65c55L } }, + /* 10 << 287 */ + { { 0xa804b2f089ef2489L,0x06a2a805fb22f7d6L,0x31baf4fd353970beL, + 0x3481c8b712854a91L,0xb0424eecf3971398L,0x748ef3820f4ed94aL }, + { 0x92b74ad026722164L,0x23f71d5831b1302fL,0x6741b28070a5f0c9L, + 0x46c12cfb9f5101caL,0xe7014d7901d0f81eL,0x129bd87ad758c288L } }, + /* 11 << 287 */ + { { 0x6c43d8307b00cd09L,0xb794cb012141eb00L,0x95fe13a75cf23ec5L, + 0x3de5ad7b8f2c799eL,0xa378434a025de83bL,0x07f681bba3a14a3cL }, + { 0x8fa0b5d2983ba419L,0xe477bf361781bf08L,0x5b8162845e8ce6bdL, + 0xb36a78ee199ec8eeL,0x444fc01a6062d5d1L,0xc026ab4586ee9ac2L } }, + /* 12 << 287 */ + { { 0x6a565269a3e0c5b3L,0xaab7ec7104c6ae54L,0x0bda11a7d8c6ddb8L, + 0xb7ebfafb2332347bL,0xcf791881e99dff48L,0x81600214dc357c83L }, + { 0x2a264f8931d7495bL,0x8ca430004ec885a7L,0x6d478260bb47d417L, + 0x544de4ec3d817032L,0xac7150a9dc05f901L,0xffef225775c0963cL } }, + /* 13 << 287 */ + { { 0xacb83aadb65296f8L,0x04c96c3e18151422L,0x8913311e7a9f126aL, + 0x3baeaf8010b74e8aL,0x253c9dcbb7410105L,0x30a13e42da2d5437L }, + { 0xde31fd5533a2065eL,0xde2caf1ffe099595L,0x54c762fe795076b5L, + 0x8beb51fe635ed402L,0x369603c1e5c3d2a6L,0xc5083f0700a472b5L } }, + /* 14 << 287 */ + { { 0x58805ca8d2eaf294L,0x910d085ed7d5abb8L,0xf9cbc9a1349cfecfL, + 0x67bc7b417800a980L,0xe7e6dbc0f6847e9dL,0x7a0f22c4af379c48L }, + { 0x80b6fc04b1d2822fL,0xa1cae656d8517a70L,0xd2d11ed14e9dc24bL, + 0x48d74f173fab87e6L,0x1feca5af50c630aeL,0x263e04cc62d0620aL } }, + /* 15 << 287 */ + { { 0x7dd330ca16b2a52aL,0x25133c614157ae5bL,0xe6ee0e4edd606b2fL, + 0x700840423f2b59a7L,0x58d27587d03f54eaL,0x62ebc668d34605e9L }, + { 0xa764392ab3155e07L,0xf0810f3e3c6ae6c8L,0x1b32e5ae94614cd4L, + 0x45b49262b9cbf481L,0x0034db795b3d1184L,0x463237825b1b9ab9L } }, + /* 16 << 287 */ + { { 0xf6377e3bf6ba1469L,0xc334fb6c09c832d3L,0x7f85ac42c21c0cf1L, + 0x7a3e31c9857d8edbL,0x2eb1076327b77ed6L,0x2bfbbdbc38dae10bL }, + { 0xed7c6fb17bae3b4fL,0xc5911d9f36d04e6fL,0x4dc435504569e72fL, + 0xaa82fb97bedae3abL,0x06d37bef4f27e463L,0xd0dbce6df0c35a11L } }, + /* 17 << 287 */ + { { 0x4482c7b704414726L,0x72c9cb5b26d23eabL,0x3747b8cefd5cb171L, + 0xe4ecabc300312ffaL,0x5909f29b9cf10a38L,0x209bc3f4b8d0e5acL }, + { 0xd34c84db60fac147L,0xd64dea89f8938c89L,0xb18285f8b815267cL, + 0x719a7e355a2437d1L,0x45f8d9dab769c5a2L,0x2d0e4281a412cfccL } }, + /* 18 << 287 */ + { { 0x23c14c43d8f6e236L,0xb14be0d28ee39386L,0xd3c55814262dd390L, + 0xa1b40401e1f23d0bL,0x1377b07c61534375L,0xfe4e3eb116f6d95eL }, + { 0x17b1af0040b4386cL,0x2dc657a837ca3851L,0x6862ca92ef976731L, + 0x9f0c380ba4118d3bL,0x23bf793977c1aa94L,0xaadee0612bc27d4bL } }, + /* 19 << 287 */ + { { 0xfa5e4cb6f1847a9aL,0x0e13a60cba6f07f1L,0x68d9db450ac86498L, + 0x44b02de3920ff013L,0x43724c2d84b46078L,0xb3686ee81f951b93L }, + { 0x019b3e77d712fe85L,0x313e7b7497dfb295L,0x7d883ed826d50e37L, + 0x64815565d32562ddL,0x2f9e48bed7b3e2f2L,0xc97cf156dcb93450L } }, + /* 20 << 287 */ + { { 0x0573d9963ab4c707L,0xee5d87691420fdf1L,0x41873aa55e2b9c12L, + 0xe09290456810bf08L,0x4ff4143fccbe4bbfL,0xd0e5a74969328301L }, + { 0xab5912621c4b73beL,0x550ea0633f3edf99L,0x8a77633734c93db1L, + 0x5c51d3f832b21521L,0xcee9f604713feea0L,0x0d6f8a5a7bf4268eL } }, + /* 21 << 287 */ + { { 0xc415d467009a0cffL,0x32dd46ef55960242L,0x4ccc6f676d6a81b0L, + 0xa860bcb6b2571d81L,0x7e74150991f9b6c9L,0x9a96b2f9d3a0592aL }, + { 0xcc3d821071248929L,0x586062daf1cb0f52L,0x18d993483d48b6c1L, + 0x667f17949f4e612aL,0xf1d7a77ffb3a12e9L,0xf7586397f5753220L } }, + /* 22 << 287 */ + { { 0xb87d5ce2722f405fL,0x24d1f993d7c6a322L,0x09d837291e0d8113L, + 0x70b5cdbf89a6cbc3L,0xdfb3ee16fb2c9607L,0xf0acc1163465c7c6L }, + { 0x10cef4b707e6659bL,0xc280c4331fde9940L,0xc8b5e9819a2d3f25L, + 0xc36faa763f7f68c1L,0x17878bfa8d54e281L,0x8fda8b359c42c5a2L } }, + /* 23 << 287 */ + { { 0x2aa1366305d22d7dL,0xee77da6eb0c62a12L,0xff8f99c5bacad876L, + 0xcbe33479f8a0f0baL,0x4c69bd7f4a232c8aL,0x760ce3fd485d3f48L }, + { 0x0b286a59268d7411L,0x2dd746b6589819b9L,0xe017a53060ce76f2L, + 0xe4407828d642a7f0L,0x12761e51b6badaecL,0x4f4f286b78d07257L } }, + /* 24 << 287 */ + { { 0x43c78835661019ecL,0x68e916b124e66d29L,0x02c0f3a224094671L, + 0xab6f1c05d0f17d86L,0x6d3bac72a22d4264L,0xd7b8f152f6e5fafeL }, + { 0x95627c6339447eb3L,0xfd15901879e1ff93L,0x39277c835ad80806L, + 0x758aafc90d7c7b74L,0x605ad8ca4cb8bec9L,0x6a90085c5741828aL } }, + /* 25 << 287 */ + { { 0xbc11d3d559cdebfeL,0x75c31b4531b2796eL,0x8d11e18a07b1055eL, + 0xcf522c1fb2d2986dL,0xc994c377eafcbec6L,0x840d27ebc0c0e2f0L }, + { 0xd4124d17859550d3L,0xeea6047aba21b2b6L,0xbd2a036e335a2854L, + 0xd8703d6b207ac2e5L,0x09d2244a94a34bbbL,0xd6b9481417ec6f44L } }, + /* 26 << 287 */ + { { 0x7d8ddca252aa7ff2L,0x0985e47d6953b9a2L,0xed328993dfff63ccL, + 0xbfeca5327cfa6ee5L,0x7535a871b1e6a010L,0xb0052764303c2ec5L }, + { 0xd39c72102fedb0daL,0x7ee2b384e1001505L,0xb638a1b1c82a7e1cL, + 0x1b94a47b4573fd7dL,0xef2bca7792cb2b88L,0x49ad6e97a75b21efL } }, + /* 27 << 287 */ + { { 0x591bdd0d8f4093abL,0xa2c63f1ba1322343L,0x5e548f71b32a4331L, + 0x9930891c5e7f3c14L,0xb2b2406e54c27043L,0x7ffe3e5ef1281af8L }, + { 0xc31ba363900742d1L,0xf24c8ae1e61ee209L,0x687c56b7beed46f4L, + 0x0b63e47895682562L,0x9117cf4c0c8a45a8L,0x0744a86824c20748L } }, + /* 28 << 287 */ + { { 0x9ac777993acb39ddL,0xd1d3ecddbb7c6a8aL,0xa5271c9e7a75159cL, + 0xa6ffb41f2c276e4dL,0xc526556e0bb9a955L,0xa32e1352233b7774L }, + { 0x103f124bc2cf09aaL,0x1816d1eff10bae5aL,0xc5f9197ee8837629L, + 0x064d5dcb13b1b76bL,0x109c70748d0fe0b1L,0xbb4e9743fce5f6e1L } }, + /* 29 << 287 */ + { { 0x4636f36d3ef05af6L,0x3695267b3e498920L,0xd59830285d773fc8L, + 0x939591245d3cc515L,0xc3f52a9569134370L,0xc9d0db7af8848992L }, + { 0xcd1be9bf15906eeeL,0xa95d25fb916d576fL,0x08de893be152fb62L, + 0x65d743658ab1e35cL,0xd6d97057fef14ac1L,0x67ad47b9574508c7L } }, + /* 30 << 287 */ + { { 0x1b403c4f1470433eL,0x6f8cb19257e53eecL,0x87b5b93df0cce4f5L, + 0xfefaa5008c566f77L,0xf6aa8066db71517bL,0x9f01b036d67f5952L }, + { 0x9524306faaeb40dfL,0x5cb2e8e1421350a6L,0xa57d05ea3d69040cL, + 0xd0ff12a1b9bbdcd8L,0xed64d3259e3e19bbL,0x29509c0fed0a490dL } }, + /* 31 << 287 */ + { { 0xc94191e7a607c050L,0xb918a096b98d3d4eL,0x97413dbce3f253f3L, + 0x8476c03cdc6d8418L,0x50247d1d2402202dL,0x077476225f8097c5L }, + { 0x1457ab609b71c6d6L,0x9ff312c447cf0c94L,0x954dce23ee79d2bcL, + 0x3ba2b1a4a0da6e48L,0x363df36f532be9f6L,0x816642ddc742c7d4L } }, + /* 32 << 287 */ + { { 0x6edf5561ff8b1fbeL,0x614b788ef6eac0c0L,0x7699ae56d8d66d29L, + 0x5f81602ae9d58eb2L,0xd0c04874faf9176dL,0x4b3a0046523153b1L }, + { 0x9690930ff6315883L,0xa81c0b44a60ca92dL,0x2d0e725873bcba90L, + 0x57efe72de902e329L,0x3fcd598676bc27b9L,0x492adf0393940c09L } }, + /* 33 << 287 */ + { { 0xf2ab8e22973a4b6bL,0x6a96f2ef6ad73ce7L,0xad5e22547235e929L, + 0xfab3e4a9bc6c3b76L,0xf69fb2062dc950d0L,0xd863ca9049478ff2L }, + { 0xec669f122749fabbL,0xe1d28bdc71a6d279L,0x766ee6458372942dL, + 0xd118b90480ade5ccL,0xedcfb0a72293740bL,0xa3ee3a67f16b29cbL } }, + /* 34 << 287 */ + { { 0xc29fb53e118a0c7dL,0xea7a1017193b834cL,0x678072a2cec93ecbL, + 0x9054d6b72475dedfL,0x4a7d477342ee616cL,0x05cec7f8680f8a43L }, + { 0x39c491d496915870L,0xe07a2b1d8746edeeL,0x1d8ed3c83566e7fcL, + 0xc7d744e5e002298bL,0x8a0acec99c0e6388L,0xb2daac39ebf48fe3L } }, + /* 35 << 287 */ + { { 0x773ad1cb8e133d97L,0x1e29f5a2872523d3L,0xa2a742293a09c1ffL, + 0x809e6d284369ca06L,0xf22e521a7fe148caL,0xbaaf90c383ef9578L }, + { 0x65aa9b54d633b2d5L,0xe55f2ce29a2994a8L,0x8a0af446e67e0b85L, + 0xb9714de9c1f062c8L,0x1f4047dd2a3aa1d7L,0x39658ea965179222L } }, + /* 36 << 287 */ + { { 0x0322b29a57fbc5cfL,0xf55af7863078be9cL,0xd4b186e6ecb59f79L, + 0x50f5fe746d950733L,0xaf8a1898a9f90d02L,0x483801a742d6d9bfL }, + { 0xf0a0af145ec09c0eL,0x85af0e6188383360L,0x404b295e42592235L, + 0xb3199d63c596493cL,0x7aadacdb194abb80L,0xac84563ec1c845c6L } }, + /* 37 << 287 */ + { { 0xd78d1dae5336e58dL,0xa3f36e0bc5ff354fL,0x8421f95e5d1ed78cL, + 0xff4c16019f360c43L,0xd5efa09f8bb582a1L,0x0ece005aefb39652L }, + { 0xce8bb58036c2c940L,0x11f8f74bcd1ae8ccL,0x923c350b57a2f2b3L, + 0x2438e3213c86faacL,0xe76129503e230776L,0x35c73d415e6158e2L } }, + /* 38 << 287 */ + { { 0x8ffda4643672507aL,0x76301be7dd91327aL,0x42720bb0958860bfL, + 0xedc0b8945ad4f455L,0x2fb553201bfbeb4dL,0x22a425bda1c6494dL }, + { 0xfb927a85de0e7f52L,0xb84a82cf49a4b6a1L,0x8afd0546b640fe0fL, + 0x23b78fbed2fc15cbL,0xeab469c26742a49fL,0x308e453fe277c7cdL } }, + /* 39 << 287 */ + { { 0x60ce0f55af7b14aaL,0xf2577fbe5cf5a2caL,0x7bb9521fabf3bb41L, + 0x68b6409def00287aL,0x700bf423bfaf9391L,0x98e6c3017d637300L }, + { 0x342ed4870ce28aeeL,0xad8b8dc383b059dbL,0x1b8a892b85d0a485L, + 0x553c4fad6b7a7d3aL,0xf5692acc198d0379L,0x6004ebb3ce932f00L } }, + /* 40 << 287 */ + { { 0x6895dbe2f820c195L,0x3787a5003f6c7b40L,0xdc718243ac1e90f3L, + 0x352f8c91ba5d0870L,0xf3d1c53eec0112b5L,0x08a0782f6b84f64aL }, + { 0xd659e6358eedd5d4L,0xfc30df6c29537276L,0xbfb09978a1755ce0L, + 0x227f7b12aa2b4187L,0x828730b9226539d2L,0x9051a37cb2472c95L } }, + /* 41 << 287 */ + { { 0x430c2a45d0a0ddabL,0x916aa68926a6291fL,0x9db5510268dff24fL, + 0xa22121c1850a7aabL,0xd43416194e2d9670L,0x7ef2cb9415cf7636L }, + { 0x2cd6ddf6bf97b27dL,0xac5676b625aba9c0L,0x3ca96f7ec4ee110fL, + 0xc6900abd08e7ebb4L,0xcd3942fbdcb91135L,0x62d6b6f6a8ad56e2L } }, + /* 42 << 287 */ + { { 0x1ec7f2410828d35fL,0xd94c2a926ccae554L,0xdf4227273c36ecedL, + 0x2facd6d89fa6582bL,0xed43247ed349d3beL,0x1d59d55d1db6fcc6L }, + { 0x2b5074b1ee1bea38L,0x025496aac9c21a8fL,0x57dd7fa1d1d817edL, + 0x57b5572aead03124L,0xdc024be87314616dL,0x5bb5b23c10f6e38eL } }, + /* 43 << 287 */ + { { 0x643cb9cd53812134L,0x016a11e8092ff9b5L,0x227f3dfbfcde37bfL, + 0x01b9bcebe8a8fc6dL,0x7009ae45e1da0dd6L,0x193b6f519e2908f3L }, + { 0x28656302230db5feL,0xb0a730c41aaeee73L,0x028320ab387addc8L, + 0x92165d909a92488cL,0xb0b2f8f09066c95cL,0x0fa55db564007634L } }, + /* 44 << 287 */ + { { 0xbff4fe0844284b10L,0xc7e3f8da19c2f775L,0xdcd97e54a45ab746L, + 0xf53158a9540ee8a5L,0xfd19068728c4aa74L,0xa3447e30648fa2e1L }, + { 0xa6794670c374cedcL,0x605629c258204248L,0x1b86f8e6f7d8db3dL, + 0x1e8ffe8bff0f38c9L,0xe4a556b8e274c82bL,0xb31406c94c0076d6L } }, + /* 45 << 287 */ + { { 0x198999821e555a0cL,0x831e923fbc196442L,0x8b294623f682e135L, + 0x79ba90c01743c6e1L,0x74f8dbafeff5ed22L,0xe4c3257d5c010835L }, + { 0x9cf94a208f9ec66bL,0x9fe9da3ddc303c43L,0xa53870be0cb716daL, + 0xc322ffaa2aef881dL,0xb9ff76ff0fcd5580L,0xdcc125d49ebb1d7dL } }, + /* 46 << 287 */ + { { 0x747b6b6ddecaf88eL,0x1a32f8ba368cc7caL,0x52a3a00f60d84fd7L, + 0x60052af507adacf7L,0x8b7bf25650b8de16L,0xb8b2acf8194926baL }, + { 0x4bda72c81d1ef524L,0xe350f73288993f96L,0x63fee4e2e08c5d39L, + 0x1f2cd9cd5db46904L,0xbf11ac311668d3bcL,0x8eaa064371d721aeL } }, + /* 47 << 287 */ + { { 0x33cfdcb3e14210feL,0x4abad5ec4946aa01L,0x14b42417a8cb53b3L, + 0xeebb0d70238d4edfL,0x8c9d87fdb5bdb30bL,0x3cc680f17c928b33L }, + { 0x4b2b2358757c2607L,0x51a70a33c1c8dedfL,0x62a26d776b22d113L, + 0x2f4acd62ef3b4f5eL,0x403e91bf6ed00636L,0x219ba3577bf74d3cL } }, + /* 48 << 287 */ + { { 0x7de743e2b39317b8L,0x9205d4472d372acfL,0x8226fc303eeb0012L, + 0xab2a3e052af74be6L,0xbe4767804af91ac0L,0x98497c710ca36bf4L }, + { 0x74fdf7cd8d6dedb4L,0xb50778eea0fc5919L,0x5d5ec33f2fcd7c63L, + 0x667b81937f33cde0L,0xce48ae4b38364d44L,0xb8578963223ed67eL } }, + /* 49 << 287 */ + { { 0x3e5688e46bfd7adeL,0xb3f1eb051b80bd4bL,0x8626c4cafe3de456L, + 0x8846bc714b7e5444L,0xa54c7cff689e8a67L,0x8c3ea61f43eadcf6L }, + { 0x924f17d6fde15178L,0x45319eb705c08d2dL,0x6d55775d9f85dcbcL, + 0x2aaf9f7405278280L,0x574a13e77b617153L,0xe7fa921ae8b15bebL } }, + /* 50 << 287 */ + { { 0x9dd54056514e343aL,0x8d9116dff12aa25fL,0x5322ec38e3397844L, + 0xe1843921571036a1L,0x2cde0a48650beb19L,0x41ad4a7e4f259728L }, + { 0xf314fceeee6448b2L,0x80006b2aff0e81f5L,0xb5ee5524d51d229aL, + 0xeba6d733128e900bL,0x79278cb8030f391aL,0xb24bcd63a9a5f9fbL } }, + /* 51 << 287 */ + { { 0xed867a7b37d10743L,0xd57d2d8df510023eL,0x4d500e4c737e0a50L, + 0xcfa119900ecbf795L,0x3ac126b89373bdaaL,0xb06324fb735449a1L }, + { 0xfe321df5cd79de70L,0x52d625dbfd07c6d4L,0x88ff505a3d628e51L, + 0x120350fab044d725L,0xf718b20ad02f9515L,0x766698630bbea1b2L } }, + /* 52 << 287 */ + { { 0x6293e0ff50d9bda1L,0xe7259ada433b4dd3L,0x39aee63e821cee67L, + 0x4d707c7144b10739L,0x42b9e0f69bd6efc3L,0x7d71edcc0717a61dL }, + { 0xe7df9e56d1e5a5bcL,0x7895b638ddde509bL,0x6fc597b3d2a6a822L, + 0x022da65d96d2a8abL,0x95541ce7cff45c72L,0xa5bb7799e649800fL } }, + /* 53 << 287 */ + { { 0x7472e4c963676cd5L,0x2836b1d52687f376L,0x1460b664f732a51aL, + 0x7c4541f22a214ae1L,0x743a524d107d6622L,0x9c64e3ff082fc015L }, + { 0x9341f3fc8e0d13bdL,0x9946043e529554edL,0x6fbbbcda5798d6ccL, + 0x3bfad5fb242115c5L,0x1f46bd1945ab793cL,0xd9383bcf3b42f81aL } }, + /* 54 << 287 */ + { { 0xe4ff888f820a13b5L,0x7cd18b3eaf1bfbbbL,0x3fb7f681bd4e4dd5L, + 0xaba364c287d46c40L,0x44e209ab659b3498L,0x5e071a272dde85c1L }, + { 0x8a029b1fb969c790L,0x51bab9f0c6fd1c22L,0x9ee9b047b83eb0c1L, + 0xda0b39439e5b2c35L,0x0cb30625f20ca425L,0x8e4dbd013d25c2c9L } }, + /* 55 << 287 */ + { { 0xe7aa41a96b8f7599L,0xe97ff24a3f556ad5L,0x10e07713dd6a9329L, + 0xaf464b18c4d06a93L,0x9b8e5145a1ccc85fL,0xa256680bd0487ca6L }, + { 0x420b60bf815652f1L,0xeaf09eff5bb45b6fL,0xa31e875f8845a557L, + 0xb035ee09eebe0911L,0x1402d1d86531c356L,0x24aeeaf0b630f75aL } }, + /* 56 << 287 */ + { { 0x4b20d1829567f5f4L,0xde7e814918f02b34L,0xc9a4be7becff9dd7L, + 0xe2f70bbe9812fd3fL,0x471bf90c9c889263L,0xb60d01b53e61f5bfL }, + { 0x258c7f89d22d855bL,0x35ef5c15b75a7d4fL,0x26d8e1dab247f27dL, + 0xcf1361998d0f7757L,0x312447803f8e894dL,0x8d2a20bae1a3d47dL } }, + /* 57 << 287 */ + { { 0x6447cc97f08a0417L,0xd98ea6837afee809L,0x81426d20bf7990aaL, + 0x848bd6223526ad26L,0xb6cdc5b4fe1f3381L,0xe7e10bc7a26189ecL }, + { 0x25a9f7cf57464e6bL,0xf90c1aa12c86ddf0L,0x2126ed530124705fL, + 0xf384e7e5b58e6341L,0xb2dfeb0a12207e57L,0x72875c55e0e23287L } }, + /* 58 << 287 */ + { { 0x37579c3eb954b7a4L,0xf0291f8f3f2ea608L,0xde68104f90a85ed2L, + 0x6a35fea9e1088788L,0xe8d5517470d15d00L,0x0bc72de552467f90L }, + { 0x2ded3293297be2b8L,0x76c53e5761ddc65bL,0xae4b2b5015562d6aL, + 0xfe7cdd329e0aeb79L,0x98ef4c518dd474ecL,0xfca56ffb0076b23aL } }, + /* 59 << 287 */ + { { 0x120adcba6f60309aL,0x41e46edeca8ab2c7L,0xd68aa4c529b79ce0L, + 0x21a21f8d7a3b11fdL,0xea68dc4739d0809fL,0xd4faa71a27973044L }, + { 0x65b42172810be134L,0xb2dafa6c793aee92L,0x951e9f6f1f78f7dcL, + 0x2affc70a17fdba97L,0x4f0f4c51dcaa2789L,0xfde1951c9e703980L } }, + /* 60 << 287 */ + { { 0x80826a196488d9d8L,0xfa452795f3ad867aL,0xdd9bf8f5bd4e6674L, + 0x324386227e8e3ee5L,0x7af4c605dff05c96L,0x79efb6f9541cbbd2L }, + { 0xeb5ff62675e78961L,0x5318c4c30be43d7aL,0x02df456daa4a0562L, + 0x4d6002d88a916a81L,0xf0dbc349f68eced2L,0xfd75d4d5ec8c3fddL } }, + /* 61 << 287 */ + { { 0x6c15d903544378f3L,0x0a9bc9d735ea3c77L,0x9d9066408caa4acbL, + 0x9ba27502402be833L,0x1ed4123f8773fd7bL,0x236364ba190eac92L }, + { 0xd6287f17f8383ee1L,0x75b7b0b5d9739582L,0xeb6cd50d0292806eL, + 0x216f36dc43448409L,0xec136f8cb6c4958aL,0xfa805ab49ef7810eL } }, + /* 62 << 287 */ + { { 0x5c6448f70d00b29aL,0xaa134b87124cd55dL,0xc2c6b269d94b72d9L, + 0x0f0dd472412f76d8L,0xb4cf3c1873f6571aL,0x6aed00218b9218ffL }, + { 0xa55b74eaa0c9dde9L,0x59b952125b4c8fccL,0xbc9873ea4ddc367bL, + 0x26b369ba0fd30421L,0x71763a45e446f4fcL,0x67e800edaff54707L } }, + /* 63 << 287 */ + { { 0x4de97de1126b4919L,0xd631d908883ea109L,0x37c77d729f6ec50cL, + 0x910932e6df718c7dL,0xa798406855028d0fL,0x21b09540a6119a26L }, + { 0xb837cceced4b4962L,0x3c83f4bdba66002aL,0xa067aa3d2ac41124L, + 0xa64bff30d08dc360L,0xa22778a5c108d3abL,0x7f732064aac4dee4L } }, + /* 64 << 287 */ + { { 0xc68b641ec795a2c7L,0x4fe559b15a4d6647L,0xeda98cbad89ce668L, + 0x15f84dc06c269d8eL,0xf0eb685ecbf34023L,0x3668c530c032634aL }, + { 0x2e3d7fffe4531f59L,0xe627030685494d06L,0xf02cabcfa3e050dfL, + 0xccd2da67c001dcd9L,0x50aa3723066d2d52L,0xdb0756507224a41fL } }, + /* 0 << 294 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 294 */ + { { 0x04418b5965b55050L,0xa8a797c3d324aa67L,0x5f87e22c7c65a6d9L, + 0xaac710651dbeffe4L,0xff619d64bd3cc05cL,0x9a29c966e65c92c4L }, + { 0x23af2b21dad7fcbdL,0x4950a767153b817fL,0xc34a7efac6478c55L, + 0x57cde95af6cd140eL,0x64b74575f5a0db2eL,0xd4b5ea5275d7fb76L } }, + /* 2 << 294 */ + { { 0x284050628e72aafbL,0x655bf3538ea8bf00L,0x789d944405547f7bL, + 0x7fa445ed3441e472L,0xfeb198254a44ce87L,0xccb5f12c129aed14L }, + { 0x22b05de3af94fb34L,0x7422a040d3f03199L,0xfba252caa83f7f08L, + 0x0f6ad6e6cefaa757L,0xe1ad18716517d806L,0xd16dc8ed8e9d97adL } }, + /* 3 << 294 */ + { { 0x0208092a0e3dca68L,0x9a49bdccd1a09971L,0xe5194181aefab9c1L, + 0xc1c9690a0076f47cL,0xd7499e95b486c2fbL,0x83a69e43d4b72e00L }, + { 0x75f2838a2d1a6c2bL,0x57a24c69751f6366L,0xd956ee08626cc684L, + 0x434cadd7e6ce3249L,0x3d4eaececfe289bfL,0xbbd53b961b8aafddL } }, + /* 4 << 294 */ + { { 0xcbb99194a3736eb6L,0xdd5161cd36dcf470L,0xd50b24aab6ab6c03L, + 0x419d2810bc41f4b7L,0xe2e88d7a295496cfL,0x350713f2f2457ac0L }, + { 0x838e4a360427e2aeL,0x7631472a4d974e5aL,0x9fa3ab1c7a5c5fdcL, + 0x324798cdde34cb8dL,0xbfa5a9d0889105feL,0xd05dad34fd0df249L } }, + /* 5 << 294 */ + { { 0xb47c1d47d6a3a1baL,0x99bb7e6572f65bd5L,0xf251794578abfda2L, + 0x827f2aba3e3e3420L,0x436ee73250e2de70L,0x5c9ac6dc10eca926L }, + { 0x2ec67465181f5e18L,0x1e8f32fcc6c83d02L,0x9dd3aeaf3953bd81L, + 0xca955f4b07086daaL,0x7b4b6f3fd14eaa88L,0x562e75f1148d826fL } }, + /* 6 << 294 */ + { { 0x536e5657cb419fc3L,0xe8c208bc1d271dd1L,0x6a3713bd22d2b9adL, + 0xa4c761a7471d808dL,0xd93aafb67e6dca35L,0xc46c0ae38f55ca32L }, + { 0x55dc0de7a78bfca0L,0xe9cfb3013407d0caL,0x777e2a60b3256c14L, + 0x32b2238c6d8fee02L,0xe8b3539646e43ee8L,0x310bc1ba247985ddL } }, + /* 7 << 294 */ + { { 0xbb9bce6810168f49L,0x32edc368717445e3L,0xb0b5a04426aa3ff2L, + 0xc671f1fcd166542bL,0x3142864df61d2523L,0x11b2dfc7b0c67410L }, + { 0x2e031a05c99690a5L,0x4782fb749fb7bae8L,0xeac2cd506b7175acL, + 0x2e116782bef2313aL,0x67992027241c4d2dL,0xf8aa0e09a6952d9fL } }, + /* 8 << 294 */ + { { 0x9974759c581f9d3cL,0x9e76a970e5cb1973L,0x8afec58ec64941caL, + 0x2d7c57fa01d05575L,0xc07c74cc5c448db5L,0xa52474ce01bb1440L }, + { 0x93162d9700115bbbL,0x483b6147fd7480f9L,0x4f28c57e6af18dedL, + 0x36faed8f174a3089L,0x702dbd64a3dd6265L,0x86a9c43f6adc0d7bL } }, + /* 9 << 294 */ + { { 0x9d4d4b3c795eb646L,0x727e2aa17485839cL,0xb50018a5aa9250baL, + 0x5a15808d1ba716adL,0xb1748d580ff91cebL,0x0131bcff76144b6dL }, + { 0x23fea4a58dcccffaL,0xe8eddb5ceb64caaeL,0x011a65971c3c5e66L, + 0x7723dfba377a8f6cL,0x00167c71dee2f651L,0x3e89ddf5ee0e4325L } }, + /* 10 << 294 */ + { { 0xa3510710b9de7b63L,0x9f364ad14019c9dfL,0x5b66a5d79b5bdce3L, + 0x2b2f695178b1b385L,0x3e4783d33cfa9f99L,0x1af517506bd6bcf4L }, + { 0xf9c0686a81d8d7efL,0xdc0f22ec37c068d3L,0xe1b8665393545fafL, + 0x37ca8501a8a52881L,0x07ac5c8a5603e359L,0x98fb2bab542cc937L } }, + /* 11 << 294 */ + { { 0x96326ec323da6b81L,0xdb48a5e1f90a6f83L,0xbb141660f640a0fdL, + 0xb51609375b92f5c2L,0xaaabd54c997244e4L,0xbeb8ab2f859bb92cL }, + { 0xcac7c5dda4be476bL,0x7093faea7f58c1b2L,0x3167a2c45c6ad412L, + 0xabd86bc9544fb9a7L,0x571296a72448c363L,0x4da64cd9c6cd4621L } }, + /* 12 << 294 */ + { { 0x4981be690c5bbd3eL,0xb047df0a185fdb55L,0x3168e05074cff00cL, + 0x111150a1b52c7f9cL,0x0db2ed84a51c7986L,0x7d991630e61272adL }, + { 0x7443d93628de14ddL,0xfdf31f41a5daed5fL,0x71e0ef4e866b5e40L, + 0x05c57a45b965a670L,0x85bdb58c70e1aa77L,0xe4d1fe2a9df3ce32L } }, + /* 13 << 294 */ + { { 0x6ff2b1a1772c3796L,0x9b88c1178e186fe8L,0x342ba11f4312af31L, + 0x9a93a4d1a86ae2b6L,0x496d5f219d59e3feL,0xce519a7d6924acdcL }, + { 0x6fdef82327c46e44L,0xab5504c34d31c9bdL,0x6fa52bca71693677L, + 0x31221119033c80f7L,0xdb2cb49dc0a22f91L,0x4962d58f9b4aeb5eL } }, + /* 14 << 294 */ + { { 0x5d4618982f722563L,0x11d22b39567db14cL,0x9a8f004e6779cd40L, + 0x0812ae3d5473ecd5L,0x4ed828624e6c296aL,0x2d9ce40c064ee61fL }, + { 0x4856d586d8a9eb1eL,0x2ddd6b125d1b5e3aL,0x0ab5eec0382fba3cL, + 0x302018dffcf4a9c8L,0x7b4e6fd2ab3cdedbL,0x266c246a8f64cb1dL } }, + /* 15 << 294 */ + { { 0x55bad54bd6dc35e8L,0xa43d72ff38642612L,0xe39a191609bc85ddL, + 0xc9d4bc9b0f85d3baL,0x84cd12b61367a70cL,0xf4ebc0e04937bb2dL }, + { 0xd083145949dc027bL,0x110751601cf29970L,0xa443a29c0b76b4c0L, + 0xee5b8d0ca0de3249L,0x368aa3259002e7d6L,0xeb48afdc6182e2e4L } }, + /* 16 << 294 */ + { { 0xc41e4aedf5c3af59L,0xa0284ad06de9a78aL,0xf5eaab7b8ed812d2L, + 0x7801fbb81afb58b8L,0xbe5cdba671efcc3aL,0xe31a0e3ccd10cb91L }, + { 0x882e821e85dc0bc6L,0xd3ad070fbb32e506L,0x3afede2bd8a0f038L, + 0xe20a117c857fd3a0L,0xebaa2aa43060f767L,0x6524aa0d2b9d1da1L } }, + /* 17 << 294 */ + { { 0x86aeca0ffd81174dL,0x19bc6ee60c6eefc8L,0xc85f7f2ea91f0e19L, + 0x09b9276ad2354dc8L,0xb62adee0542a669aL,0x8354ad1a88097445L }, + { 0xe67d2834df9984a1L,0x2330c8cfa64b2864L,0x309dcdeb39e7b54aL, + 0xbbba4737a18cf5eaL,0x47511b1d92861a8eL,0x99d4bd673286d404L } }, + /* 18 << 294 */ + { { 0x9cc5847c88cffe33L,0xff726b0f6e8eb6c1L,0x9bb2ca161bc45d8eL, + 0xe7903009a6d8a5a6L,0x4f089cc047db2201L,0x4135884de6b5928aL }, + { 0xb1a86a0ae5c017cfL,0xb1d9bf6db0a393dfL,0x33d9c1c628bb3277L, + 0xcb05b67b45b582ceL,0xa72585fcf33792c5L,0x78b7c5e8a7d1ed84L } }, + /* 19 << 294 */ + { { 0xbb83b446b1b4a091L,0x66440b3d9603d875L,0xd1931f33c2b45d1aL, + 0xb8b67f20098d4cccL,0xa3583818790f208aL,0xe01194bec4a3e88fL }, + { 0x29301bb192e8b150L,0x1795cabe9448ee60L,0x377d8f9752500c48L, + 0x474e73d65a457e79L,0xce0a50ef30159027L,0xfe69abaafbb2c214L } }, + /* 20 << 294 */ + { { 0x70e478fb9346df25L,0x01dc0c2eb4a4ada5L,0xaec82b005be36ea7L, + 0x82618b8f6717e06aL,0x2db1f6d4008f1977L,0x4e493f3b16b390d1L }, + { 0xfe86fd4d990a75ebL,0xa1cf7f99783f6076L,0x6cbb23e70c049158L, + 0xd05be7e5ed456235L,0x601374069bd836efL,0x94ec964432e5f604L } }, + /* 21 << 294 */ + { { 0xd96e4d920fc48c7bL,0xa2e29660f66e491cL,0xb92d850601146906L, + 0xa43f4803afe346d6L,0x27885d98700b6bccL,0x90662e9f595d8de2L }, + { 0xefa7f261f70d1007L,0xfe8a8be3fc72531aL,0x3b3f7541f1aa8d93L, + 0xb31bea258215966bL,0x15faa4acf35d2be8L,0x0a5f95e786c9a45fL } }, + /* 22 << 294 */ + { { 0x3361e1ce3d87bfa8L,0x92f235e78dcca4f0L,0xc8084cb4be323fd1L, + 0x3fd481a5c24c6d16L,0x9b1bd9402cea81baL,0xf50911910c5aa59fL }, + { 0x4cd8c9eff81d5e2aL,0x5ad000131550bff4L,0x29d47b9f8cc32e55L, + 0x66e3e6f111694eceL,0xd5edf7017950dd7eL,0x9ccb10960f6350c6L } }, + /* 23 << 294 */ + { { 0xc31e47ff95e784e4L,0x7ad0dfd63fa14241L,0xc91482092dab896eL, + 0xe9a114cccb9bb463L,0xedce9e6f16cb16afL,0x0ee2ce0607508893L }, + { 0x1aedb80ce31c0f54L,0x235d4591512658ccL,0x9029fad2a38583f1L, + 0x95b1e1ddebef898eL,0xeb2f21809efabef3L,0x458c4338b10e9cbbL } }, + /* 24 << 294 */ + { { 0x09db138d18f2470cL,0x63bd2290f613658fL,0x0bb647794feebab9L, + 0xfce4aee17fdb1e71L,0x7d5c0c61a7f1f65dL,0x46405b618d02d6cdL }, + { 0x7cac04856fdcb0d0L,0x85224c4b2f8ec5afL,0xb5879a59db0aa864L, + 0x75f391b8ff94f8b5L,0xa6c994ae49c97f8eL,0x4d968fadd690b232L } }, + /* 25 << 294 */ + { { 0x1e436df6e11a616aL,0x9eb49c76bdb932a8L,0x207d2fe90e6591aeL, + 0x6e05acc8233ac034L,0x464dd321f3d04d32L,0xd4ba4889af43c171L }, + { 0x0808e5207120fab9L,0xb9e4726c3fbac672L,0x5dd1c13b9d7d883bL, + 0x1c091808771f1edbL,0x76988d1c75eac1a5L,0xb0fcd3a893a67be8L } }, + /* 26 << 294 */ + { { 0xf5cd290a67e0b4e7L,0xaa6fa6807c1594b6L,0xebedfbd7b63270beL, + 0x574b410ba369bfeeL,0x431cba5a020ea888L,0xd3a3102f56c71d47L }, + { 0x4894bfe0a90a853aL,0xd78bd98b5f9c4b6bL,0x9b1324f6d900c5c1L, + 0xc65c944d718c2147L,0xf661de6ba987f634L,0x0315e69f172628d8L } }, + /* 27 << 294 */ + { { 0xb12e0ab8aac7ab64L,0x8ce877abb06cf9cfL,0x39b694b40bb11fb4L, + 0x0c2428369b0d8850L,0x6bc9a033ccd50c6eL,0xaa2e77739a1e8fb3L }, + { 0xa7d8be09608e2e9cL,0xeb4cef0542b9f458L,0xa7268c9b985f66fdL, + 0xd60eeab27acf4968L,0x02eb2db3b6e5621eL,0x82fb4abfad8236c4L } }, + /* 28 << 294 */ + { { 0x07c60c7522ea5f1cL,0x35beae34a36bee4fL,0xa8b00a09dcba8997L, + 0xa77f1f3a802ce50cL,0x6c4050df2a2144b0L,0xf79bfa96ab1b10dbL }, + { 0x9025d470433a9b1cL,0xaf3e391790d9eec8L,0xbcad2d629ae2d535L, + 0x7a152829eff0f6a9L,0xe87345cd925fa5a0L,0x6ce007200e84039cL } }, + /* 29 << 294 */ + { { 0xc65acf36c3d095d2L,0x9192c5fe72427e6cL,0xcb84c43c3fa8b90dL, + 0x2f458fe965e15b23L,0xd8bf193731469f11L,0x1ccd8bb93638cc3eL }, + { 0xa067022f78e35577L,0x382e6af730ee676dL,0xf197adc2f6d135bfL, + 0x06360834c9a1cf58L,0x413813f7930371beL,0xf7461d04f5dcaccaL } }, + /* 30 << 294 */ + { { 0xdae449c007f6a05aL,0xbc1b84f55bf26c9eL,0xe3b3f9edb1c13820L, + 0x5442ad5b4090598bL,0x794ef65613749e4dL,0xde809180948b71c5L }, + { 0x4c72dc7de203c5b5L,0x8902b0971b349fc4L,0xa899bedb225a1569L, + 0xeb7da73de6ff3f53L,0x6ee8e1607c0be37bL,0x9ee667d2a31bf943L } }, + /* 31 << 294 */ + { { 0xbc91031108b6fb2bL,0xa5e0ab3e25e06a55L,0x16ff0705360f1698L, + 0x71c0aa7487e72a67L,0xa1f1497b355c75e8L,0x179b67bffa6bbcd7L }, + { 0xc9db6590b6738583L,0xf77660c4d87e72bdL,0x0ee2e7b3f13abc2dL, + 0x0cdf5a37a4d922b6L,0xaa8af2d596c853a4L,0xdc452af4e0092356L } }, + /* 32 << 294 */ + { { 0x5017e145db81146dL,0xc7d2086d45c54db8L,0x2541059dfa98234aL, + 0x4bf344d99985af98L,0x39737ed67b5b7b1cL,0x8e24691987c411adL }, + { 0x2fad8cedb877a75fL,0xe42352df17e60ee2L,0x1a53d856404043f7L, + 0x6c1f07a5863927a1L,0x38d3a4f4b6892121L,0xf4c1092001976c8fL } }, + /* 33 << 294 */ + { { 0x541732a70224214aL,0x61617b515cb2d019L,0xc560c24bcb4fc6b2L, + 0xd0ad737943670d99L,0x08cdd32eb83112a8L,0xbe57493d7e29810fL }, + { 0x7834124899d4523fL,0xae1a5857cc8e5fb7L,0xf8b62a59b8454efaL, + 0x7c63c900ab0f4729L,0xeef9243d72dd0f5fL,0x6b865dfbad766386L } }, + /* 34 << 294 */ + { { 0xd11536eefee626b8L,0x1d2471dd8077b5d4L,0x7db062debdb9a4dbL, + 0xfcc62c0ab9f808ebL,0x619b54c6ef392bc7L,0x81e146fc51b9f5c9L }, + { 0x0343807c7bbd52b3L,0xe024a9f1572125c5L,0xf8b886d86c57cb31L, + 0xcb92aa7d5398a318L,0x4ce0870d2410ef34L,0x1a40c103f8366683L } }, + /* 35 << 294 */ + { { 0x46485baa7bb78552L,0xc0f685f23e6a3f0fL,0xd24970b5fb3cc0ecL, + 0x0d1f380e7bf91feeL,0xf0f7fcafe7624351L,0x27cb99bc697a8055L }, + { 0x55be14685cdc7560L,0xf006927927ba7f93L,0xb0c25c759fdd0e70L, + 0xda82e73785818253L,0x7d40d86946304c51L,0xe06ea6fdcc18ba58L } }, + /* 36 << 294 */ + { { 0x99d37ade6b65e17aL,0x61ca538e38ce217cL,0xd3ea83f68ebb89edL, + 0xce6611eb4b02964eL,0x0ec7cc2f5c0a8e44L,0xa985b0c2974240a4L }, + { 0x7a3abb6c42ee5b0fL,0x55f049a0cb2eddadL,0x69348b027c44a60cL, + 0xcabc65191974a8c7L,0xd9def4bc07b91a35L,0x684a2d71b93b34c3L } }, + /* 37 << 294 */ + { { 0x21c37d21f48f274cL,0x2de96b4da082a098L,0x82520e0ca606b6a6L, + 0xf76c9ec6e1050b81L,0x248c5efbd1ce149dL,0x5a36ae1e9a909790L }, + { 0x8790b09bec8b43afL,0xd592dce560ff709cL,0x726d699724cc8e21L, + 0x61e37bef5e2cb745L,0xd55a68c26eff3ba0L,0xd47f02659ad265c0L } }, + /* 38 << 294 */ + { { 0x3e6351ef3932ef94L,0x65625878db5d64e6L,0x118a688e091ec7b7L, + 0x2a95072abdf60b88L,0x5200703540dc0afeL,0x59c3d90b6fc1cbffL }, + { 0x5622b1b21dfb1a7fL,0xdcb0344834d92243L,0x18fccfa86d7d36c4L, + 0x5d43a14181341761L,0xef375542eaaee79dL,0x4e4667216999d399L } }, + /* 39 << 294 */ + { { 0x1bca97aa9d3c6b9eL,0xb4bb4f95095cb250L,0x4f2c216a996fb52aL, + 0xc4d01916f379790cL,0x510882a4359df53dL,0x6457d76a671d6a8fL }, + { 0x0ded2623061f7d64L,0x3cb4f38f1ce7dcf2L,0x0d86313a224ffa88L, + 0xba8a15012b99aeb3L,0x2fb92183d69f72b5L,0xd3b9d6daf1fdb8f0L } }, + /* 40 << 294 */ + { { 0x5d573a3a0b6320aaL,0xf9ac8ccf289b6700L,0x8bad05cd8f28dd72L, + 0xe2eabd446b62c306L,0x60f70353906ef302L,0x147cdd0c367a768eL }, + { 0xea9d871635a9e846L,0xdd71e80aa8684430L,0xa56a5ccd530768a8L, + 0x59d241270a3e42f6L,0x707cbaf0faa367d1L,0x5419b14f52a0cbd0L } }, + /* 41 << 294 */ + { { 0x625bf4e6d991d842L,0x56b95a56a81daaaeL,0x2101137c9911bdadL, + 0x1141b0a1bbded1c2L,0x85deb889d1df8d43L,0x51e3e17edac3e376L }, + { 0x5d31639381fb19f8L,0xd1cb634b92eed2c4L,0x72a6ed7b943746dfL, + 0xd55f55fb22b85e00L,0x255b025804193aabL,0xd0b94c5d86a78c96L } }, + /* 42 << 294 */ + { { 0x121c15d859c3556aL,0xabe25c21864380dfL,0x2de101832627f78cL, + 0x19988e4b4bcf4a0cL,0x4ed3aad8a2f9cb52L,0x50f8cef5b2b257e1L }, + { 0xab0b000c49f7f596L,0x6cb997471fb9c471L,0x331974b95fefb8f4L, + 0x57cf97578e2e0e5cL,0xa82a8d06174a626cL,0x40ef371b03e80567L } }, + /* 43 << 294 */ + { { 0xfea713e1324cbab8L,0x738885e61897e7baL,0x8234ed08126aaa13L, + 0x4f66467661ed1548L,0x61fdc2aa172c432bL,0x78eade7c9ebf0a29L }, + { 0xd50ae7156aa104a9L,0x977d7a605536df98L,0x024014bdc9eb983cL, + 0x75d53c0585e21649L,0xc181d67098404cffL,0xe00f5f5dfdb3f05aL } }, + /* 44 << 294 */ + { { 0x3cfe2987d10542b1L,0x5935e0dc29f5b006L,0xce5932d6d83344f2L, + 0x67aab7ad9800a6d5L,0x3ef2b0e765073619L,0xc381a99454aa9ccaL }, + { 0xbf069577d4011571L,0x33b70c5d4d1ce997L,0x801ba41c758c9b1bL, + 0x6c2dd5ec36968958L,0x31820ca087921665L,0x0b7f0d337ca55668L } }, + /* 45 << 294 */ + { { 0x0b099a5afce6c55fL,0x91d1caca408dd628L,0x42a5181165449db1L, + 0x540935b040715d49L,0x8feabc5433b00823L,0x7107c06240c2485fL }, + { 0x13f307ac4fea64e4L,0xae4ec4a713a04327L,0x8297be380eff71f5L, + 0x3434286f1ecd0b2eL,0x4d7a5456a3e9d625L,0x657f950b6a0d04e2L } }, + /* 46 << 294 */ + { { 0x2237f78ecebadb15L,0xa1184339da01f9e2L,0x542c3354ef37abd1L, + 0xbec90883de982d70L,0xbacdbb9c457d3024L,0xf1d167c19840ea52L }, + { 0x9ed827d8433bd3cdL,0xf4e5b4231102fdf3L,0x2038c92fb63d6056L, + 0x490cb0188eb9ae35L,0x776331b87c75ffc8L,0xafbe7c6a3fe2e400L } }, + /* 47 << 294 */ + { { 0xf668460c9176a02dL,0xa843a70011d322a2L,0x6424f0e8a8c5d1c8L, + 0x0b45a1ab1bc440e5L,0x3b740cb11c3e391cL,0x5aaa89c4d5850e1bL }, + { 0x77739ee6d632c592L,0x171fd350fffe373cL,0x6a648fcdbd7e83beL, + 0xd98650c6b619f4d5L,0xa4e4ae5438dea07cL,0x10001f5afe0bf5c1L } }, + /* 48 << 294 */ + { { 0x31cb896b57dfc732L,0xc6b74a1edc323e91L,0xd24a41d0f11b04f6L, + 0xb609a26dab8f7159L,0x96d84b372adbec34L,0x154f5307d24ae7f6L }, + { 0x36dd3243e10eb34cL,0x055d3b714f6dbbd3L,0x30b1efde36d0c561L, + 0x3846925ce9bffd15L,0xaf401286aa99ba07L,0x3a191267fd48b839L } }, + /* 49 << 294 */ + { { 0x67145f18e42a26cfL,0x580857fa491122d7L,0xa4e2db8dd03b5071L, + 0x47a39a0d3e379882L,0xb6bfe4b35970766dL,0xe40f4daea8bce767L }, + { 0x38f199a7e812a217L,0x1407f98d97eec7caL,0x25d6f750236a41a0L, + 0x644327340e811ee6L,0x84d5d9c9dddd6e5cL,0xc1b6ef13c44cae4eL } }, + /* 50 << 294 */ + { { 0x79879d4f6714e8daL,0xce409617a17abd07L,0x6f2b14d008a6e685L, + 0x817d467409b5e150L,0xa1181873eb51b966L,0x573ba855da6b9544L }, + { 0x836ec3e5c4a37013L,0xb8da1bbe93fded69L,0xdb5bb6f16edff4c1L, + 0xff30b837f1657d36L,0xa20cf000223270b9L,0x29d60562d44a57cfL } }, + /* 51 << 294 */ + { { 0x0d6f36b9b98b029dL,0xc4cd72d07a371233L,0x23bd419e4f95cd4cL, + 0x2c95b0a2b80d1e13L,0x0f76e62f7edfbef1L,0xd077194dd303a470L }, + { 0xd6e20e7cd1b50934L,0xf4201fca2dfeb806L,0xa57dc150bced28faL, + 0xa84d621be3172301L,0x119768fe9aa14d6dL,0x34f1ae864b363253L } }, + /* 52 << 294 */ + { { 0x2fc83aa3afabd13dL,0x521b745f53c45a27L,0xc6f345a660c18225L, + 0x9609076eb5faa47aL,0x8bdd97fd535388fbL,0x8f5f3bd6e7fd7e87L }, + { 0x6de4454c1c8e1d5aL,0x8d61ca3b2b35e823L,0x93b66fce4672d30eL, + 0xcb9d601721d09ec5L,0xef98137fb1de06eaL,0x45e212758b051877L } }, + /* 53 << 294 */ + { { 0x117b89e9ee6e35f7L,0x2ad205aadd203ed9L,0x3f6c950c0689bd4dL, + 0xaba1e4b342f20742L,0x67464b793e22f0d1L,0x74436dfdbe0ad6c1L }, + { 0xc4a6e964c1470ac7L,0x853ad39b361da35bL,0x261c6fd6a187a6abL, + 0x08d7e89d59fb860eL,0x158e2697e8f88299L,0xf3f1f6f34b04a8ecL } }, + /* 54 << 294 */ + { { 0xbdfb8d006b562705L,0x76dbc217ed9f2aaeL,0x62f713778cfd02ddL, + 0xa05eed177a5d27e1L,0x60082379a006983aL,0x312af914bf7c2c05L }, + { 0x7d163fe76c8500fdL,0x722a35299d4d0dbcL,0x9b4c5c3539f93a78L, + 0xb193734c34c7ec06L,0x457db178cda87a84L,0x088dae087f816e0cL } }, + /* 55 << 294 */ + { { 0x746e73055896ac5dL,0x1d8326c21a7b69f1L,0x695197743132a40dL, + 0x3899f8a03f58720fL,0x2c3070a5df0b7fb2L,0x49bc59f2acb839e3L }, + { 0xf7d5d3f66b8f5a9aL,0x704ed893a4c3b570L,0xbafde26cab591c03L, + 0xc447dac83388a62bL,0xda80991d4416acfeL,0x1625c9151e729d69L } }, + /* 56 << 294 */ + { { 0x3104e59e6b843647L,0x4eccb42720bad138L,0xa575b8e150efd6a9L, + 0x68a6b7055a6e4729L,0x670306798f5b2a22L,0xb2cfcf81df9253bfL }, + { 0x9c3eeb19b8f81c39L,0x082ca86c986b4dfeL,0x1f64eca250250d8eL, + 0xbf26bcfb67f0c713L,0xbc5d0e2a49b609cdL,0x175acb34e6aa3c76L } }, + /* 57 << 294 */ + { { 0x5237d7368c53aae2L,0x2a88098bbdbc0b10L,0x18f1af11cec6db6bL, + 0x12c23392c4e08b3bL,0x23b652bf3eab43f3L,0xb79feb949f3dca0dL }, + { 0xb71e311d2b24e0d9L,0x85e48aede37a0f90L,0x93e8a0e753200b6dL, + 0x5d44b87226bf3a30L,0x466c31d1d0496b98L,0xabec12f7dd39874fL } }, + /* 58 << 294 */ + { { 0x58bc23928ca41326L,0x0744ba8524aa5067L,0x900e7e9baaf80bb2L, + 0x510bd122aff38fe1L,0xf90dd6a1002b277bL,0x829379dc81bf7df2L }, + { 0x5443b8736372d502L,0x124c2abab5b6f9a2L,0x88b237a4d6020c14L, + 0x3542215108f7a498L,0x39e84240e6234eb1L,0x43d721dfcc5827eaL } }, + /* 59 << 294 */ + { { 0x43e7597234658dcbL,0xed936b96bdf3a7caL,0x74acb7f60f1923abL, + 0x6a52b28cc007995bL,0x5abf2909a560fbf4L,0x79d571dd256bf1a8L }, + { 0xa8d51082e4c3281dL,0xc0d6f8aa0b9fdd38L,0xd589f2c57ac30640L, + 0x6abb8faf07635c58L,0x2af1b083d7520b0dL,0x18b9f6c893b951fdL } }, + /* 60 << 294 */ + { { 0x32e678b4c1ba956bL,0x9e8b137248f32982L,0x9b380a118a8f262aL, + 0x5c2d6ce0807f6d1aL,0xe99c2e909f1b3fa2L,0x6a0c9e4a7c4bb836L }, + { 0x30d80329ee8dac83L,0xabcf7b76b60bd5fbL,0xc589a0c8c14d56d4L, + 0x9e40af665de24d43L,0x932f4070230f8331L,0x96bba1c19b87948dL } }, + /* 61 << 294 */ + { { 0x8b83af0c4efaae9aL,0x25e55686770c85cdL,0x0beda54fede0c999L, + 0x6c5749398d249a2eL,0x520ac2ba2f476146L,0x162e482de95b05acL }, + { 0x2d3d19b6c73a32daL,0x945e5e3c33fd2c48L,0x361d9770a36b4ee8L, + 0x8aed760d014cacb3L,0xae66e5de5ae302c7L,0xb5fd5959b5d4d6a4L } }, + /* 62 << 294 */ + { { 0x25df58ff147da470L,0x1b3941ec3f4e3e98L,0x7543b1227aee3587L, + 0xb7bc2b31b4a28218L,0x8628b5400bb3224fL,0xe3e7644d373222e6L }, + { 0xb4e3269299244dc9L,0xe72c679d49781bcdL,0x894d9eb0bb6f0700L, + 0x4a08cdbc443c3639L,0x52c4d04e5baeb02cL,0x53f550ffb5f93552L } }, + /* 63 << 294 */ + { { 0x2b908f693c1f524fL,0x59fd6ae7090970ceL,0x595e15721eb9ec29L, + 0xa55adbd6fbc4f04cL,0x575a2344bcc38bf8L,0x89397944f2b659b7L }, + { 0xc77532a18c87fe8bL,0xa5a75677de4c9eefL,0x2e3d873a0e4a1704L, + 0xe18ff4fcc4d02aa1L,0xd842074275573a79L,0x0fcb532115296dcbL } }, + /* 64 << 294 */ + { { 0xbcc88422c2ec3731L,0x78a3e4d410dc4ec2L,0x745da1ef2571d6b1L, + 0xf01c2921739a956eL,0xeffd8065e4bffc16L,0x6efe62a1f36fe72cL }, + { 0xf49e90d20f4629a4L,0xadd1dcc78ce646f4L,0xcb78b583b7240d91L, + 0x2e1a7c3c03f8387fL,0x16566c223200f2d9L,0x2361b14baaf80a84L } }, + /* 0 << 301 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 301 */ + { { 0x7a1a522b246dc690L,0xb563cbe14b61ab70L,0x41bb4abe3d4ac4abL, + 0xc52950b337f996e8L,0x01d991e679727761L,0x35de93bd978fd7d2L }, + { 0x86bad5e65706d336L,0x10844155e7f26c20L,0x58ffeb7705757453L, + 0xbb1861293939df77L,0xbfdd394a6a78ea0fL,0x907ff0546e33e1d3L } }, + /* 2 << 301 */ + { { 0xa7f295320df93b34L,0x855934f25c14df30L,0xd2f54ce9efae348cL, + 0x5acb931cac52758dL,0x287b3e18d22961a4L,0x42a5516d748f8fe1L }, + { 0x1b62b341877224caL,0xaff58db3d30a4aa7L,0xbad78dadbe8da847L, + 0x85fa710954f18276L,0xe2cc9d287c4bfdadL,0xbb131f762c75f237L } }, + /* 3 << 301 */ + { { 0xcdcdd7d703844670L,0x79ec59afb4a23f91L,0x5923c569c00ce5c3L, + 0x099c17ffc589d0c7L,0x0335eeea89fa6fe6L,0x916bcacaa4e868c4L }, + { 0xb7037325fb687bd5L,0x57d6bca79853b564L,0xdf3132efd5e26d28L, + 0x7ed994b8de919cbeL,0x12df67cd6fbbb18dL,0x516e07c06baff508L } }, + /* 4 << 301 */ + { { 0xf2ec9ef597e833e4L,0x97bdef9734ec7e41L,0x90e2b2387d2ac6e3L, + 0xcf682b120318a3b7L,0x7fe76089ea84a7a0L,0x85c489f916546d05L }, + { 0xf987118f6abdda05L,0x675cf998aa4b95fcL,0x544c7774888a7e8cL, + 0xbd2647ba63ec5831L,0xb479cea3fd2fe985L,0xa042134528d163e8L } }, + /* 5 << 301 */ + { { 0xd93506a4e5947c6fL,0x4340d76a39b81d08L,0x741aee5917930d30L, + 0xfea3d99a18fdb81cL,0x1088ff6b289bcb07L,0xc6b45602b7c082c6L }, + { 0x50e2baab453d8d69L,0xda9bf561e893e183L,0x0af25f86b29a284dL, + 0x0e92e67473e01380L,0xe173a0e32be00e59L,0x402d2f3dada8954aL } }, + /* 6 << 301 */ + { { 0xca9cb3890399721dL,0x03ad9f4aa3291479L,0xd85b5df56dee003dL, + 0xe1fa7b0264a4f83aL,0x01c4cbfdb73f7324L,0x707010d45cf2ddf4L }, + { 0x3c6df430b12e02f8L,0x921a290185531489L,0x302fc77c91d1022cL, + 0xc3733ec0342d8f3fL,0xb83bc75f6195a665L,0x4a14b9e7a79f8027L } }, + /* 7 << 301 */ + { { 0x9f0e5428e2a57359L,0xc690a3c714998c16L,0xd73c3ca2de37e07eL, + 0x2ddf91b8dba0bc0dL,0x69d834b27570ae71L,0x2ac8bed4735195a6L }, + { 0xcd8c51ff3b1fcc5cL,0x7aa8cf4e1ba6863fL,0xebb69e72ae70f428L, + 0xa29409dfaa9e936dL,0x43f6ee805a332b9bL,0x0de49efac2eab0a9L } }, + /* 8 << 301 */ + { { 0x04baa1762310333eL,0xdc75e35f7b9bad46L,0xc4a6031dc6cd6108L, + 0xba2534d030bf87a5L,0x7ebc6e2131e497ccL,0x8a2a82b4851fd665L }, + { 0x9ecae0116d5faf40L,0xfa3a6d7f96956ecbL,0x39e8a9c22fa52782L, + 0x74c93801236d442eL,0x8b21ba23b1c289ceL,0x7f3e221b25c769cfL } }, + /* 9 << 301 */ + { { 0xed800e4d08aa4dfdL,0xf524b107d8105bc7L,0x8c4addc9ab07fc03L, + 0x2b0f038d26a71b4cL,0x5055c471a83d19a7L,0xc6c5ecba27e20a5bL }, + { 0xdbad26b7aaeaa017L,0x4e3abc20d2493554L,0x626310143a0c15bfL, + 0xbafcc06798cec55cL,0x9204e17ce6f87607L,0x8f1c10eed9302c05L } }, + /* 10 << 301 */ + { { 0x53680ce08afe59b9L,0x36a3cec75665022dL,0xb3a5091654490b50L, + 0x803d383f0838f0aeL,0x65531a008005ba2eL,0xb7fa6b4a1241a17dL }, + { 0x9aaec449b17e07bcL,0x19b7d9113d190dd0L,0x79da42457fa5e7feL, + 0x725bd045598ad850L,0x49f96cc45f94ee82L,0x114bbcbf03850eefL } }, + /* 11 << 301 */ + { { 0xf566a287d43a6db8L,0xffb8944b2aeb120cL,0x3e7099427e294c1aL, + 0xce122b126c31214eL,0xe59b280c2a21282dL,0x03916e2ba01a4fc6L }, + { 0x56e65da29f5e409cL,0x374d3dfe7f5c3e11L,0x150684fc13967e2cL, + 0xfbed4f5bdf4bc38eL,0x5973c67182e54b82L,0xcd36c873363f307bL } }, + /* 12 << 301 */ + { { 0xcb42c5617c3805d4L,0x0e74e75c3b43a8b3L,0xfd58f864369f579dL, + 0xf471aa774a3dfe97L,0x2e0dbb51ab37bd2fL,0xc4704487729c887bL }, + { 0xcb7958a9cff32948L,0x3e36de368505e71fL,0x2232fd2dd38ccfbfL, + 0x6f3c502042005175L,0xd1280a3e306fb63bL,0xef7abd792e368ee9L } }, + /* 13 << 301 */ + { { 0x29c5712d56ffcac3L,0x20307670e1a8e0eeL,0x676a23c26356aea0L, + 0xb9c17e3f432f15d5L,0x0008512e287c5705L,0x6ae2704bc5f7ccfeL }, + { 0x6a200db709a13b60L,0x24fb1e9241043271L,0x2e455e9741b766a2L, + 0xa11ff26fbe056684L,0x3cfb8a64ad9178ceL,0x5786978d5d675b79L } }, + /* 14 << 301 */ + { { 0xf4cf2c8e6070a72cL,0x0bd73aecabc3251cL,0x1af44eff17539f67L, + 0xec3ee99e44e8d8f7L,0xba698f6a279afdf7L,0xe871accfb771d4a1L }, + { 0xbf92963d8bb0f264L,0x817b1fcfb10716bdL,0xf57580786b23076dL, + 0x994ff3c535a994cdL,0x05d984e82604847eL,0xd728e292fc9f2e43L } }, + /* 15 << 301 */ + { { 0xa44bf023b900b696L,0x1f82fe54037bb770L,0xa6d12f820717e747L, + 0xf154ac51e3b83029L,0xfbd343128cf3984dL,0x7f734beaa76c72c2L }, + { 0x05c5b443114548b9L,0x4ce414f396af4132L,0x1474c0b79d080a7aL, + 0x865827c6497366a3L,0x34760c457816a0a8L,0x6da2474c15d2a176L } }, + /* 16 << 301 */ + { { 0x761e10e2ca114c4aL,0xe39d121d894301b3L,0xa0870ff43dbc6fcaL, + 0x97651286cbe0ba8aL,0x47d46075c0f1ff6aL,0x18669c843abeb5b6L }, + { 0x1234c80ead8d9309L,0x1ccbe4d51f6f97ffL,0x399a2d41d82ab780L, + 0x8a03afafde426e50L,0xa2bcb109ca6dde77L,0x840e13b00618f5ecL } }, + /* 17 << 301 */ + { { 0x9552a8184929f7eaL,0x514e9ce9acc61766L,0x03159a525a219015L, + 0x5efeebfa14eace54L,0xe8a3736f853da94dL,0x3a0f334ff45e8a32L }, + { 0x71ebab39c9dc65c9L,0x6ef37f49d7c24f39L,0xde3d45f8b24a9383L, + 0x7193bbb80c218869L,0xa1bdfd30c0f7b6beL,0x82b2c4c5c1d9206aL } }, + /* 18 << 301 */ + { { 0xf9d9b678b197099fL,0xfa8548c4c15b2bbeL,0xa36f17fbdd2817beL, + 0xb35597021732d1edL,0xba145100744f3955L,0x7c274633344b43a3L }, + { 0x9b0ee7c8686b65a5L,0x438eaf4823f0e973L,0x79a658a7288c5019L, + 0xf6d938c546d04413L,0xe39bf9a6a6cb9853L,0x880d5b83801b70ddL } }, + /* 19 << 301 */ + { { 0x8f23f00303825482L,0xc4a9f214a6b35023L,0xf0905573794e7de0L, + 0x7ff790144dd68979L,0x8d9c14942959beffL,0xdb34474f82282e48L }, + { 0x423bdfa281fde794L,0xfc31e3e792a8810bL,0x19d316ba8bae4eceL, + 0xddcf30b7159c1386L,0x997968a38e7d69dfL,0xcf67ae9aa6b21be0L } }, + /* 20 << 301 */ + { { 0x877866a3697b4dd0L,0x32a872f4e76481aeL,0x300387bad609cc04L, + 0xc761ae79d74566d4L,0x9fd3e5bff22e2d24L,0x363ef5bf1c46bc0dL }, + { 0x121b25bce299a690L,0x7932471dc2d32b7eL,0x7f89692e94bb4272L, + 0xaf9cc4111a3ce076L,0xaf02ea22ea02e452L,0x43154e581d19dc60L } }, + /* 21 << 301 */ + { { 0xd9389e05e25dbe97L,0x3a8689b162b3afe3L,0x4d5556467014953bL, + 0xd6894c42af5ba9bcL,0x4b233690b3bacaa6L,0x0fc8ad07fc191181L }, + { 0xcd3a1e4df0764f39L,0x18a47233d79567f1L,0xf0f9eb765f921f79L, + 0x7f3d814d19d12a7fL,0x5e48cc36ff33a995L,0x9589679b8960331eL } }, + /* 22 << 301 */ + { { 0xa2ff78bb477d7226L,0x3216fcc085e04a8bL,0x7c594f81e4c3c24aL, + 0x075eefaa029d6ef6L,0x5ae51000493ab006L,0xcdfcc6939ab165efL }, + { 0x50b7eee276073bfaL,0xee52d55b3b60cdb4L,0xc7f7b3af45027275L, + 0x01d5444ac15b2ecbL,0xdf56f8c12a61d1e1L,0xcf032e7e4992e1bcL } }, + /* 23 << 301 */ + { { 0xc8a4dfbf15b6d8d5L,0xcb34e0e4e87ff88dL,0x6dc95befa6ebbff6L, + 0x2a55ca1372ff2cc0L,0x3c4c0f3c6a62588fL,0xa8de444ece156917L }, + { 0xced7c4523e55eba1L,0xa109b7949f05820eL,0xa021717e0e6c318dL, + 0xa0156b8d0b308f5bL,0x3c65ab9daa6634baL,0x1666e650e2839e0eL } }, + /* 24 << 301 */ + { { 0x0d27500f9ebe3c40L,0xeb9ac1022b700fcfL,0xee7578f8610763e3L, + 0x6e56078f47ef08feL,0xa8d03a7f047d04c0L,0x2143606f27cc8aa3L }, + { 0x6b08eb383b004721L,0x1f505c0dc4e36bb6L,0x6f9b869ae3f10ba9L, + 0x3bfb9833e500e846L,0x6d975557b9171b1aL,0x7af9cf4f18fa0045L } }, + /* 25 << 301 */ + { { 0x35bfb51b3b35836dL,0xc834e59003b0fba6L,0xbe6e17d378937ce0L, + 0x2f796f7c4daa9aa8L,0xd7896a0ad310eba9L,0xda258ab05ea4056aL }, + { 0x2d872d2170626628L,0xc9b26d7c2ee433f0L,0xb176220ee72f7491L, + 0x4869adcd895e9b52L,0xd37540e4d3a6d786L,0x024aff303a86b44bL } }, + /* 26 << 301 */ + { { 0x5e78606bd8424b90L,0xc83a5af9ebc9c9fdL,0x8d5b63740b65ada7L, + 0x4d01d6a221fca70fL,0x8ed7787ba1838061L,0x29901318f4a1716eL }, + { 0xc4d260527f25fd2dL,0xa66dc0a98b5147e0L,0x4355e26c269d726fL, + 0x1284fecce3a27644L,0xc9aa6cf7f98e1d0aL,0xa25ac1be3ff560c9L } }, + /* 27 << 301 */ + { { 0x5bbb87ded64d103eL,0xcb53a2f24d20fb37L,0xf8a9c2993a46b892L, + 0xb552910ca793aa9dL,0xd09e5bea51ef0806L,0xb57a0568e0c3817fL }, + { 0x9ca67c5f4e85598fL,0x04f6361fb0336008L,0xf028231b580afa5aL, + 0x8d938c0ef2bba03cL,0xa5984c1f894f37d3L,0x62ead7f4af695ac5L } }, + /* 28 << 301 */ + { { 0xf897de9213a48775L,0x505e21681b0041bbL,0x9f5533aad598ebb7L, + 0xd552ae1e1e87b2fbL,0xbb35a6319b736f5aL,0x391ce7dcc3a4c54aL }, + { 0x4c677d87f90124d6L,0x2ceebe51a9292210L,0x8882ae3133c63951L, + 0x8222c6482d44c9d0L,0xb97511420d607658L,0x3a999028b85f5997L } }, + /* 29 << 301 */ + { { 0x7b23f424eabb3f68L,0xa622a3ba4294750eL,0xb382b118e535b446L, + 0x7dbab9ee5fab292cL,0xcfabbfb037fe2f8eL,0x2283d7606670925bL }, + { 0xd18e90715be9d07fL,0xe191daa7d257745dL,0x86d59808df915e35L, + 0x87f68d5987370b6bL,0x76b9d255f945ac1eL,0xdcf9e8f2dc94ddbdL } }, + /* 30 << 301 */ + { { 0x004f1db65b986506L,0x5da683c32b0d22acL,0xf2afd1d85ee0c71aL, + 0x3b99a78a8f2ad25bL,0x8145d2ffd1c0cb69L,0x4511dc4e4009a536L }, + { 0x5539e8b8a5cb0c13L,0x4f8fd0186aae4603L,0x15dde4476d2365f3L, + 0x7cb887f7380df270L,0x815343a6a741b88aL,0x81a085e4bf99e7e1L } }, + /* 31 << 301 */ + { { 0x37d0460fd647fbd6L,0x2ccc7b01b9541f89L,0xec0e8826877a1b2fL, + 0x54d9e611cd462979L,0x016e8458453dcce6L,0x99b5dbed20ea6a24L }, + { 0x64072ec778550386L,0x279fbd9959d02307L,0x7f2ca27e9183bfebL, + 0xa191d6e8bb5132f5L,0x2b9f6163ba49ee68L,0x5a58a11fa3ee1672L } }, + /* 32 << 301 */ + { { 0x15d47e52ec645a62L,0xabe0ddb38d6d4423L,0x51226a3070cddb11L, + 0x63a253d32b5a8db7L,0xe8be4d1fbef37d65L,0x41e625d9c0920b91L }, + { 0x08b713a8d9d040ecL,0x467fb08dc450cdbaL,0xa8975877917ee393L, + 0x294792e91528cd12L,0x4512dc8c37daf6aaL,0xa83becc9197a99b9L } }, + /* 33 << 301 */ + { { 0x1b7bfdb118815b20L,0x1aa602e8629b81b9L,0x11e6df9d199aa5abL, + 0x1a521728bef9296aL,0xeba3e03b89e127e7L,0x6e69893553dffcf2L }, + { 0x24355785101615e1L,0x126b4c5282e42593L,0xe344ddd85c23144bL, + 0xc73a49b3746c0ca2L,0x1ec2432be6f63f9bL,0x6080ba870243120bL } }, + /* 34 << 301 */ + { { 0x6ab2936a4c3e946aL,0x8de2e0ae3ab052f0L,0xcaf8c35eea109739L, + 0x21d69383032418c8L,0xefab535ae7ee60faL,0x1a3a1be794b44fabL }, + { 0x0842aaa5eb911cbbL,0x789c2b7e0286862dL,0x8bff708715c0b148L, + 0x71100d79d8d7faf7L,0x47caa89a6dfa0c8fL,0x82385cf44b546332L } }, + /* 35 << 301 */ + { { 0x4f5d8c35e4b814fbL,0xe534b7be6a427f92L,0x468fb2819ca1d37aL, + 0x8c1c86347949961cL,0xf9d00305db0f7f19L,0x77534b3a976f7102L }, + { 0x94ecb7933f530710L,0x072f6fc7a916827aL,0x9247acdecc926f8eL, + 0x0d4a8997281d0a50L,0x659712669f353507L,0xd4730a15fde80a6bL } }, + /* 36 << 301 */ + { { 0xde68ca25bd37b630L,0xcfa9d32ca899d623L,0xaaeab905937c9ba8L, + 0xcb261334348ed39dL,0x8d12531fc77e1512L,0xfb7934b6213b63d1L }, + { 0xc6a6fb0096a13f19L,0xe940f3aac8f88d6aL,0x014c7f95c3d2829dL, + 0xc33d87e9fff01f41L,0xbf9c3c23c5cdcb4bL,0x8b8c0afe5d5be5c1L } }, + /* 37 << 301 */ + { { 0xe4f84bf12aac2c23L,0x5bde1744f823f90fL,0x65ffefbc02d5bbe2L, + 0x385aff9332a3b756L,0x3813f2b362abfdacL,0xbbb444cb0a144325L }, + { 0x0cf9d137ec625be1L,0x86b8fcd4c143816bL,0x03f7a9d060ac32d8L, + 0x0428daf9366165b6L,0x6ef94260d2a806d0L,0x94a100a598134bb5L } }, + /* 38 << 301 */ + { { 0x4b68325ca4a34cb5L,0x74f41f7639fada89L,0x34bf397236e593e7L, + 0x0cc75d461c6179c4L,0xe62d5ba577d711e5L,0x7bec1be7876964c7L }, + { 0x768f35d13809fc73L,0xfe55a9a57dcf1703L,0x86405336e69d3390L, + 0x68f5ea2d00bfc544L,0xd4cf822b4834b2d8L,0x77dc1ac22b0d3ad6L } }, + /* 39 << 301 */ + { { 0x45603dfa0337f57aL,0x50623184344b6968L,0x3fb9957ef160d9aaL, + 0x40eef1697c8db44fL,0xa8f394e98bf71121L,0xa55ecf3b86a920f5L }, + { 0x1f3c1f22bb0822e6L,0xb3c2f21357747a3eL,0xfbdb4465bef56f08L, + 0xa9844890a46ac73fL,0x3fd564a5bde3652aL,0x008cc1a97c653c82L } }, + /* 40 << 301 */ + { { 0xcfebe027ca0a98d5L,0x946b0d9aa8914697L,0x00f89d16725ebd08L, + 0x94c6f2b07a584e8dL,0x095ac9cc911cab58L,0xfc9c3b499c4073c8L }, + { 0x265919b0c7233aa8L,0xe6c0c7f474be5217L,0x6db597f1815a70a9L, + 0xdd9e4a101c5fd35aL,0x38b8e35112d52a8bL,0x5d0ed83f2ef20fabL } }, + /* 41 << 301 */ + { { 0x4f47e10a6c96b43eL,0xe406ab39f3d744deL,0x1caf45d83c893b01L, + 0x4f089452a7582ea6L,0xc02f58cd62b5a868L,0xf6532017c2a9aa7bL }, + { 0xf0d8bf6f32b01bf2L,0xfeec5f68a97246f3L,0xb2ead70a1aa7c238L, + 0x1a1d6f77ad83e05aL,0x4b7110533dca7e9aL,0x44a89fb85f96e5adL } }, + /* 42 << 301 */ + { { 0x86a7ebe0f02461f3L,0x6a7a9cc6862282c9L,0x7f8857944a97e48bL, + 0x191244cd20662db2L,0x8d85175183489311L,0xfbcb17b0f934c1fdL }, + { 0x33b4d86e032a7bb3L,0xa99864cb573f5c28L,0x49fe8e799c4f12cbL, + 0xe34c32e32c8bb49cL,0x5888421e962d6d9bL,0xa317c2d1bf1be44dL } }, + /* 43 << 301 */ + { { 0x3454c424cc1dcbbfL,0x67e61434aac98717L,0xfecd8125cc2d3044L, + 0x2032be70df7f8891L,0x04c5a0c81028059cL,0x6563dc8c76ade6b7L }, + { 0x9ff3815192f460aeL,0x8c2c3c632d54785dL,0x1fa99d8e43eabf60L, + 0xd75d9559383be317L,0xc9ef068e3dfc908eL,0x2217c8c1959d3e6cL } }, + /* 44 << 301 */ + { { 0x5828d71bf2e5f345L,0x8b756075929fe375L,0xca625ec12c43a6d1L, + 0x08cd01f53b31e127L,0x56c622619cfc1be2L,0x093ea207b3a6caeaL }, + { 0xdf53b20970b42dc9L,0x2d2dfdf2235f4aa0L,0xcaac3b3598786c94L, + 0x1ce1f893b4998150L,0x40341c41526a98bdL,0xef39e97eedce5288L } }, + /* 45 << 301 */ + { { 0x08cd60d461ea4256L,0x8031748b9461f861L,0x9c96e1f9019c7908L, + 0x7e6e08f4e46bcf7dL,0x8e8408f123ffa986L,0x0bee857ed467288bL }, + { 0x702fa8536e36fcceL,0x3bb25fa905a89edeL,0x642105f4e96866ceL, + 0x6a5207cc16e37536L,0xcb6a96d1372a3e06L,0xb1c7c85a1da6bc6dL } }, + /* 46 << 301 */ + { { 0x0bb97497a97a3316L,0x9416659ce402a800L,0x79656970503a2314L, + 0x0070a7eef8007c50L,0x8093cd4372624892L,0x4c0ee444f9b96830L }, + { 0xc7c10b9fe300c49bL,0x97f5f90a5f7baf99L,0xf04a5a7cfaa064deL, + 0xd5b01fa6b0c111fcL,0x4d12d6fb65d8a2b7L,0x807a381c27770e2fL } }, + /* 47 << 301 */ + { { 0xcd1aeeb43b6a9c22L,0x7fbdc6c19d71dcd0L,0x9bb43b6e6221669eL, + 0x1b76f2bf526f8a00L,0xaeba54302efdf661L,0xe1f623e745537bbdL }, + { 0x340966ae067c5f4aL,0xe2cdb27e4799b2aeL,0x9aeec5989b8458e0L, + 0x1d0588487655b632L,0xa5ffe5897abd70b1L,0x84db43db6721054eL } }, + /* 48 << 301 */ + { { 0x3b21dc1f538d92d8L,0xc80b22b3c005aa86L,0xf536e5d30da87d65L, + 0x4ce10edf0cd999a0L,0x8949181450e08f5dL,0x77fd8f2e526647e6L }, + { 0xcb207ee9250099fdL,0x03c7d1abfd6aa078L,0x7d4940d225e0cf15L, + 0xb688b311067fa052L,0x89308326a98b2e21L,0x3ee4cc2b72311eabL } }, + /* 49 << 301 */ + { { 0xec49fc4e06d255b2L,0xabd0c002fb309d28L,0x97490ff08c601c3cL, + 0xe17102fd58042cd6L,0x861411f11416ebc3L,0xfb31ce455c6c630cL }, + { 0x0a24d561c6cc5e9bL,0x80bec25c9a7c1524L,0x8003494fbe53e50dL, + 0xe89b75e28633c559L,0xafb1f6d6763b3360L,0x0e7e58c52bf70cd3L } }, + /* 50 << 301 */ + { { 0x72322d26aab6c9b5L,0x953e43d0070d7d08L,0xe2dd5444954645c3L, + 0xc5de051cb276ca86L,0x195d454439158c74L,0x26e2cf9fb90a8f97L }, + { 0x774baec15b217a76L,0xdba4bc63f94172baL,0x96ddaa4022e20037L, + 0xfe1ce4aac111af69L,0x6f6d3c428ad6dacaL,0xe59257d8376cdefeL } }, + /* 51 << 301 */ + { { 0xf2cabe73184d44ecL,0x4bf744d60bb08687L,0x10cb9e9209865d58L, + 0x3a63fe414ea221e0L,0x8f595e5892961becL,0x1b8ad036855d186cL }, + { 0x75dd5f70086542abL,0x8b357e087bddbb6bL,0x22de89f06e829a06L, + 0x44ca8b64ecc6cc26L,0xd02fa871a5ddebb6L,0x6adf1d0c6a60a0e3L } }, + /* 52 << 301 */ + { { 0x0102775982e4f5c3L,0xac8eac172c014fc4L,0xa0cd26e85bd843eaL, + 0x9b0431ec056d4b1fL,0x89df7db58eb9c55bL,0xf17f917298fc9b9eL }, + { 0x2cf1e4a78e6b770fL,0x0d6ef9e2b842fe52L,0x40b4ddb76c578172L, + 0x6630657627533b9eL,0xf8d8661eb50ce390L,0x6ceba0aa16577df7L } }, + /* 53 << 301 */ + { { 0x6dff66c19ec8ac93L,0x6261295bfdf6fe7dL,0x9ad1536fcf9fbbb2L, + 0x5cfa30a92a6d6d31L,0xb3bcf1b0296224dcL,0x42e4b410608371daL }, + { 0xd6bad6dac32945fdL,0x0fab7d1dc0c031a1L,0x054df9599b192d32L, + 0x29830094ea78052fL,0x8d73ffce03f2ce45L,0xc14c7012f9d840ebL } }, + /* 54 << 301 */ + { { 0xdf74522e74ce5c21L,0xf864cbac930c4b92L,0xfe0d2358eb0fbe9cL, + 0x10b31736a5cf765aL,0x185bbbe96a9c95c6L,0xcb14d694e5362993L }, + { 0x3f5c921da5332e61L,0x0820b32bd244cc98L,0xdaf09f24d7c32062L, + 0xb2241c9ad5959a1cL,0x16bb89a3226127ddL,0x0b46e3f03723d04dL } }, + /* 55 << 301 */ + { { 0xa38b1a796975230aL,0x25c6db8c3991b5ceL,0x0d89c3fe9c1bf52aL, + 0xe186e293cd8f9f8cL,0x777bb327e6ec37afL,0xa974132a0ae31c7eL }, + { 0xfb9918305c50f089L,0x4a653d6999497954L,0x5055c690774e8a26L, + 0xf94ffbae3815d67aL,0x99d74f5e74ea4481L,0x3b352a327d477151L } }, + /* 56 << 301 */ + { { 0x2a62804172fb61e9L,0xa9bfa73ab13d053fL,0x4a2cdaa3c647fcb9L, + 0xe1a9e91f4952d3a4L,0xbc1b3d8011e2e2c3L,0xe58ef59c18e4340eL }, + { 0xeb8696ff1cf859b8L,0x5b0f5cc4ee918cf4L,0xa471d6ce6c1e905cL, + 0x4e13d6091ed2e8cbL,0x52951509c77c8c91L,0x0926dad8e234884eL } }, + /* 57 << 301 */ + { { 0xb168a6c36e3aa3d7L,0xbd0086ea5ad9142fL,0xbc4da0293c24fe23L, + 0x7ed3b34808b90de6L,0x7a7a2259e33b0df9L,0x483b389c9c3a173dL }, + { 0x02080c626334a061L,0x61944965b020cfbeL,0xece528e9ede88ecfL, + 0xcdf3e2fc99389758L,0xb21470cb7a3fb92fL,0x717cfbe083937e21L } }, + /* 58 << 301 */ + { { 0xfac97f2910e3e93fL,0x1505c7d2f1101b88L,0x7cea978823bc0d11L, + 0x27ead95d45045667L,0x711bc4dcd17ea199L,0xe3f93fb522f3142dL }, + { 0x31b05e6ad7233d64L,0xac28e6c154e7c9d5L,0x892b6366716d273cL, + 0x1622230470da8a48L,0xc85bbe6070d560b3L,0x555e6de987fd38a0L } }, + /* 59 << 301 */ + { { 0xac593f746ed50680L,0x89bdeabbcb01cfd3L,0xfa43158ead35524dL, + 0xb2393726e8d66ca0L,0x248c67c2c36bb495L,0x27d4b0b85c933625L }, + { 0xdbb1364a78c8bb4bL,0xdcf4b1e13486ef0eL,0x554f95cec498b2c9L, + 0x2b76da29811a2329L,0x750c10271a10d941L,0x07045eae375b01b6L } }, + /* 60 << 301 */ + { { 0xd3fb9bef82621500L,0x09b18748f0f647a6L,0x186bed054c357e73L, + 0xd58281f0a85f3174L,0xdcf2e0bb91ded0e9L,0xe77faad126894faaL }, + { 0x6843c160bc3a3c4bL,0x7f8058944c76592dL,0xc53be0883ec05e95L, + 0x318d8ce7cce0c822L,0x6d615f1b4c761dbaL,0x0115824c46ff47e0L } }, + /* 61 << 301 */ + { { 0x1815391cf8d0b74bL,0x903ad8fd797625dfL,0xad1ca24d3983100eL, + 0x0883fd415572ff15L,0x0e9e572cadeb4e56L,0x800bad6f7d0e25c4L }, + { 0x52a394b44c7e2f03L,0x5150c01398f2c416L,0xf4ab35c68ce503c4L, + 0xa0ad209a41b4beeeL,0x050c52c80189706fL,0x86780a924049e913L } }, + /* 62 << 301 */ + { { 0xa398529c74ded2a1L,0x5e7248f52d7ea6e5L,0xbeb250bc28c2225aL, + 0xf7068fc0b40f4843L,0x62098aed839b7290L,0x947087e293ddfec4L }, + { 0x81ba8c8824d71004L,0xa877f443bf4813c2L,0x3cf5f473ca4751bcL, + 0x2533890e633cc635L,0xb358f7781e6d9465L,0x50693deaa7801dc7L } }, + /* 63 << 301 */ + { { 0xaf306f56cbebedf6L,0xdd733be7837acb84L,0xc767237afcff0b9bL, + 0xdf948f12e555bee9L,0x86b85657826dc76dL,0xa4bac032e702b1c0L }, + { 0xdf3544bba81bb117L,0x69c20dff34f4f0aaL,0x846b78577050d98dL, + 0xde0ef0403c70120cL,0x4483872c12c3bd64L,0x870b758550acebacL } }, + /* 64 << 301 */ + { { 0x37be5d3f68d7dfcfL,0x97bdbd49b945e6f2L,0x165a24b59d1569e7L, + 0x254aaf59b4e293abL,0x3c751fbd6fb7c0a4L,0x14eda4ba5018cb18L }, + { 0xacb3b8971b5f6aedL,0x6d10be441e4b6b78L,0x245d7258621df6d7L, + 0x2af0e283185f0e2aL,0x1e7edc818fddbd81L,0xbd1e6c72c538d02aL } }, + /* 0 << 308 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 308 */ + { { 0x6858b674844626a2L,0x610cd40f0cbba6a6L,0x324e674e29d9194dL, + 0x2dc6fdf6dcb30a51L,0x3f3ecb77528aa549L,0x0721f8f923ffaa92L }, + { 0xd8efcbd627a77538L,0xf4e642bfd6162c9cL,0x04f2b0b74cf4a16fL, + 0xbc0bb49fbbf335fdL,0xc6b6e5bd5a928c36L,0x981b01f4d893dd45L } }, + /* 2 << 308 */ + { { 0xfb083c2af810465bL,0xb66a8de902ce0deeL,0x6e4130e747a81b95L, + 0xcd704dc658a98737L,0x842ae329592829c9L,0x99bedc34be20dd63L }, + { 0xabee8e55d53b2df4L,0x6ce657586010b37cL,0x781f39b2467112b9L, + 0x6f06058fbe341038L,0x5effdca512a2f8beL,0xaa9bdad7af34466eL } }, + /* 3 << 308 */ + { { 0x3933b4c1575782aaL,0x610d3ba25c66e501L,0x52fd3c0f0b7e019dL, + 0x7f8e5ddfa48715d6L,0x0879c5defa39be53L,0xe32c886c56f01cdcL }, + { 0x71b2dcbb1726779cL,0x6caaff052c6aa84cL,0x6af94846640b2d74L, + 0x78a10710049a2cbeL,0x41a1ce67ac2ab0f1L,0xd160b7faa76d8438L } }, + /* 4 << 308 */ + { { 0xab86639e9c216137L,0x45a12fb882b18d64L,0xb5734418d763f0bbL, + 0xd2cc332211a9802cL,0xe41d7db881269b8aL,0x91072fc12ecfa355L }, + { 0x59d6912504ce306fL,0x916d9d4da131b86dL,0x84478b6b8a739738L, + 0xe86ad7d91cc83ae3L,0xbc9b2084797ccd97L,0xc1e94af4694944c6L } }, + /* 5 << 308 */ + { { 0xbbb6725b5c82c857L,0x72c66c3f140b561eL,0xab65dd0664bcb2d5L, + 0x755e848a780d5c1bL,0x84e6f686a3a61e6eL,0xd84bf486bd100b4bL }, + { 0xb34fdf846354e899L,0xcbc312da55ec5654L,0x3c2cc881f9a125f0L, + 0xb1fcce564aeadf8eL,0xbdfc54c0c46bf0c2L,0x11d7ea4f09d281beL } }, + /* 6 << 308 */ + { { 0xe1aa844b1601940eL,0xd22221821797e84fL,0x3025aba65ddcb5d1L, + 0xac8cdaba38009c6aL,0xb9ee07b46e261ee5L,0x84069bc106ab8430L }, + { 0x7a36b46278b9b112L,0x2d91ed2c08e77879L,0xae4ef469341275a1L, + 0xf7cb393f1c7cf858L,0x83c00eafd192af3dL,0xa81697a7a1e15176L } }, + /* 7 << 308 */ + { { 0x687d0980f9bfd795L,0x9a7539377ad882bcL,0x641407fabbcde5b3L, + 0x12ec9d216ed103a5L,0xf858c7851fa6ee22L,0x329b61bc818f2c11L }, + { 0x4720d42ad9d48b30L,0x3f61c66082a66766L,0x99aff25533723e4eL, + 0xd6c67ce3d3260b62L,0x63a6fc9d86391c33L,0xc002433a31de2381L } }, + /* 8 << 308 */ + { { 0x585edee3895c0318L,0x775e142f45e8205bL,0x3bd7924fd85ad31fL, + 0x2e7d8f919124bffaL,0x885397c044c62868L,0xc0c2dff47fda9f5dL }, + { 0xd302582ec14e693dL,0x53d6e33a6cec31baL,0xb0216b5b63653c06L, + 0x8f08a1ad9c70dad4L,0xccf014aaffbba93dL,0x900b0d2ca33f12b7L } }, + /* 9 << 308 */ + { { 0x4960ccb6e9824c45L,0x3c5a9b74c7e4cd06L,0x1e78cdfe37cfec62L, + 0x8cd49ca80da56a05L,0x5ba51217dca05707L,0x0d1f6e459d66c960L }, + { 0x7178089467f9c82bL,0x342e4a5b18974c55L,0x16263f18f9b32fdaL, + 0x844b5a02935b3636L,0x9c5abd51c139ea58L,0xf54c69428beef953L } }, + /* 10 << 308 */ + { { 0xbe51552d6d2dedd1L,0x6bc86dc1cd997093L,0xc9b600c4418f03b8L, + 0x4ea4e857e7a9208aL,0x7aac3d96883b639bL,0x4127ed0735d2f4bfL }, + { 0xf5f6310d76bd792aL,0x3da9b6a5fa223d0cL,0xd75f88075a041b79L, + 0xf3261457e4dd58f6L,0x4f0f5b18b0d9a51bL,0xf5aeedc1b8c84f9fL } }, + /* 11 << 308 */ + { { 0x1e08d6a81375620eL,0xed9a4fbae1f62c24L,0x0d3bb90381ab5de2L, + 0x885781f0df1b6a13L,0xc3fb9f97e1c7de7eL,0xf12e4bcf9372b033L }, + { 0x9bc3cf4dd5868448L,0x89465649552016adL,0xeea40cf92a8b2c23L, + 0x57d720ee3af98886L,0x97b14c0b72db853dL,0x65d10f42f23504deL } }, + /* 12 << 308 */ + { { 0x0dd2395e9b8cfa41L,0x50e203abd4f92a44L,0x7280aff16630023bL, + 0xfcce59dc07de820eL,0xa686be05bc8189adL,0xac4b59bfaac70b7eL }, + { 0xd2c0070e7a3c71acL,0x1d550add35ac1c47L,0xd42b6389fb881c1bL, + 0x57ca3fccd0dafd42L,0x909e8284be26ccc9L,0x1abe7595a002235cL } }, + /* 13 << 308 */ + { { 0x02562f1c6b1878daL,0x52a2cd069fce0ee6L,0xf25b35bdeb16199aL, + 0x0320c326a75fb01eL,0x2006d7587de2d46aL,0x6f9d0e256842b459L }, + { 0x70a89562a68b5482L,0x9653726e1ab35865L,0xbda3cebbd8f849adL, + 0xe2f8d9e60b6fc51dL,0x9c3fd51246104400L,0xbbd260c9bab5d34eL } }, + /* 14 << 308 */ + { { 0x1f5094703cbc1df1L,0x9f752a663f962634L,0x98089d2ca2435048L, + 0x05256acb0e755318L,0x91a21f707f3845f4L,0x473ac1e0d68c8fcfL }, + { 0x57ee51417f2ff0c9L,0x959a84f32013c48bL,0xe701f13c4c111ee5L, + 0x70219eee86db5763L,0x385f890cdb0782e5L,0x81fb64b2fea04d2eL } }, + /* 15 << 308 */ + { { 0x61b4bf7eeaa07bd9L,0x49832879afe544c0L,0xf788e97f54eb4d80L, + 0x78351b41338af327L,0x3a631bba77cb8057L,0xeb9a6f23f218e4ceL }, + { 0xbd4a0dcf025b6453L,0x2aad6a467b876222L,0xaee94361215c42cfL, + 0xf8d1fd5de496cddeL,0x3c3af08022d0fe06L,0xb3d5dde0d09cc3f7L } }, + /* 16 << 308 */ + { { 0x1e34781aa6a1913dL,0x9a8f32287d0adc38L,0xfc185ccc28af85baL, + 0xc923d78b3ae9ba11L,0x7d494d7ea7bdb313L,0xf774dfa5af8f8b87L }, + { 0xc178ccc116e863b8L,0x2d472f2aa8899691L,0x608747cc80a50372L, + 0x8147aa90e6f90197L,0x4683d4c978c2f216L,0x8323652c552f3b51L } }, + /* 17 << 308 */ + { { 0x7d6bff984dc9149fL,0x79879e1f499b443dL,0xf4ec65232aff2a1dL, + 0x6cf3c97f27253aa1L,0x95b9471eefe6f72cL,0x3959bd816c8457daL }, + { 0xe2870635cf112073L,0x84e44933ec12174fL,0x67a592deedf434edL, + 0x0c93cdae2897d0e0L,0xe344ecf463c89730L,0x28098b7567a1133fL } }, + /* 18 << 308 */ + { { 0x62e96dc7a12a0cd8L,0x09d7c6f0f02a3d87L,0x9d9fd51233f8929dL, + 0x1231952dab376555L,0x6ef6823c8e3d2d63L,0x7ad2e5405a01c12fL }, + { 0xd1bfaec479af6fc8L,0x4555fedfdad97daeL,0x0e6d3f0155750bdeL, + 0xd37ed9f0056f6128L,0xf1fdf91c65fe6ff7L,0x3ece19ae92d05e43L } }, + /* 19 << 308 */ + { { 0x07d2075e750fc5d0L,0xdc2b03f6a07ca45cL,0x0248d87552efef7fL, + 0x2dfdaf3f744e727eL,0xbef861b8d9b2bcacL,0x5e6363f0baf394c7L }, + { 0xe8f23bbec973934cL,0xb43d619a50ea324dL,0x2bd5e0075842d6cfL, + 0x5c5af62217646e90L,0x5d95d8fd222ec05eL,0xc9adabb45bd67c31L } }, + /* 20 << 308 */ + { { 0xa5c08e8bcc2c9a2aL,0x70e1b4058baaf0fcL,0xf29e1e5c9e36e50cL, + 0xa3d9080080f258c5L,0xc9ceac25ecad4498L,0xcb73130fca32f3feL }, + { 0x2dbe620c48b3863dL,0x8c52727f14ff53bfL,0xb60b22a86b45e9b8L, + 0x81e05bc0f6483c5dL,0x217caa6bcd542972L,0xffab716afa780778L } }, + /* 21 << 308 */ + { { 0xaef1278b0ba5a344L,0x253be7ad2d0c3947L,0xce58bf0fe5408f09L, + 0x867b0d6fe21228f4L,0x815abb5dca61e691L,0x0da28f58f3e94434L }, + { 0x5b0fd178ca4cee2bL,0x8989604240b13224L,0x8e2fe19616c251a7L, + 0x7b3381cb11b17162L,0xc73d96a427ef2c0dL,0x76b7fcf36899c135L } }, + /* 22 << 308 */ + { { 0xcaee3387cad8b585L,0x58446c1ad59d8777L,0xb8755fa540888d8cL, + 0x7868510654428813L,0x7bd21629136e2b59L,0x249903a6998254a3L }, + { 0x2cc73a751f8fd813L,0x4b1a64576d4f3a70L,0xea2aa620b2e7a0fbL, + 0x77c8cb98202f6ddcL,0x68ba9d261e3851cfL,0x936fe8cbfe02e6efL } }, + /* 23 << 308 */ + { { 0x8b84121bda75aba3L,0x4440272d74602c33L,0xb8110b2a1e8a8ab0L, + 0x4de462e9391cf47dL,0x9173d756519b9ab4L,0x3df52d13ba8d5dc7L }, + { 0xd7a822eaa418b01fL,0x58be2b076585f7d8L,0xaa814fde00fb449fL, + 0x6b8260fc7da43c5dL,0xaecbfb442351ba9cL,0x9cbe3d199f8db60aL } }, + /* 24 << 308 */ + { { 0xe5d3e0d80d7410d6L,0xcfa9ed742be432c9L,0x60044434a85a0686L, + 0x93b357166ad6918aL,0x1a3c3e6d051762beL,0x80813589b0ab32d6L }, + { 0x64214b92aad403fdL,0x684befc14d3fb746L,0xaca5a51479515046L, + 0xacdba03472e84485L,0x61aa2834287d9e97L,0x07a515a5cad222e7L } }, + /* 25 << 308 */ + { { 0x8f631b17bc04e9c5L,0x017527212c515161L,0x4358d8e9ee7769a5L, + 0x18f0aed0b59dba1bL,0x035c6bb644973218L,0xa49a4cbcfb3897e6L }, + { 0xd2a0b7505841ab18L,0x8fe952dca6d2d43dL,0x2d30add69a71d0ecL, + 0x0cb84c402c5d440aL,0x33f3cf7c7c47846bL,0x88703c65bc8e8b3dL } }, + /* 26 << 308 */ + { { 0x3c3db9419474059cL,0xcfbf13ad72820ae8L,0x3f84300c51c37d62L, + 0x0f78adc45529d333L,0xa19be46482e34cfcL,0x9ed07ee011c98376L }, + { 0x5113e660b5b6f6beL,0x56f2d2b37a5bc818L,0xd99290c61c2c822cL, + 0x39c026b8b27aafceL,0x8692150b12ef7c76L,0xa55426d1c6de9e16L } }, + /* 27 << 308 */ + { { 0x889aa8ee3465358fL,0x5885ee29afbefa70L,0x05f9dbd290b6ff58L, + 0xc74be0d09b5e02afL,0x4b7da27ea6b29d44L,0x2ad60aefcf68eeddL }, + { 0x2ba942b3388c81c5L,0xda8badcc368e2e62L,0x33e95ac87a9e8511L, + 0x37453bbae72008b3L,0x3e1f181195eceea0L,0x719f550c7b19a417L } }, + /* 28 << 308 */ + { { 0xb03093068af19670L,0xd784125a34c6bf0fL,0x0b425ee0255a8396L, + 0x91076433fb541162L,0xc4d8188586f47a0eL,0x3b767d54fd7bc7c1L }, + { 0x98b405d3bee196e9L,0x4ef9c511edaccf4aL,0x5a6deb6503f4f1a6L, + 0x4a22ca641b4c5104L,0x2cce36679145ce41L,0xd05187523206810dL } }, + /* 29 << 308 */ + { { 0xa5746e07f7e11342L,0xb50e390f2e2ddca0L,0x3847749bcb288bc2L, + 0x6ff43ec646ee679bL,0x343b3fe2c5257b02L,0xc0f57f509b823eb7L }, + { 0x5ce3d2c8aff42c7dL,0x984c9b99c3c76f3fL,0xc8559f58b8823b92L, + 0x883ac8064ce4338cL,0xecf8aac3389d8ebbL,0x9edaec10b40bfb16L } }, + /* 30 << 308 */ + { { 0x0ed8a07cafb04e5eL,0x7e95ed898f6bc911L,0x6a4ed37113dcc222L, + 0x9aa3a43296f07c7dL,0xe819a80b9b338e4dL,0x65fc2778278f53b5L }, + { 0x788408e9024163b3L,0x159de8bb7de54f06L,0xc953e21281239dccL, + 0xacb5ea2c6dd62ce9L,0xf56ac93b753f4ab3L,0x2a1a09b5eacc39a6L } }, + /* 31 << 308 */ + { { 0x89dcbf021c5f4cb9L,0xc0fbe7ce210f98ffL,0x3dc3c743b897cdf2L, + 0x931f9dbb5d02c43fL,0x0ea9f164f74db981L,0x504938874af9f53aL }, + { 0x86bd3ed62531b8aaL,0xcc1fb6dddcfca2a3L,0x24b0cbf2b97abaa9L, + 0xd81ad35c9073f19eL,0x4dde5dc05db7fd5cL,0xce410880e3ac9b63L } }, + /* 32 << 308 */ + { { 0x29d81538037bebadL,0x76e52c73d9e0b78cL,0xaa4ace6e8783d1fdL, + 0x9c14ebddf0e3c126L,0x0eb1c08d6eca4b71L,0xd10c6b961c91df35L }, + { 0xdb8119bbe81bb84aL,0xf784d3c117e3ceefL,0x053c916835436f81L, + 0xeb41ccbb9b18d212L,0x93b3fb43b1bc3497L,0xd85a7c758c1ced81L } }, + /* 33 << 308 */ + { { 0x90b606b2fc9958e6L,0xd39965b6f94234b9L,0xf4a86f1676f4dd03L, + 0xd6a7ba54470f0f7aL,0xa1b85c0ca86fce7fL,0x2b50f14e574c4cfdL }, + { 0x4aff867d80e783bcL,0x031092eb61f78fc4L,0x8ad0d7486fe0af1fL, + 0xb56b1a1a0cdfa574L,0x586c916a56466e12L,0x427e5946d09a9d1bL } }, + /* 34 << 308 */ + { { 0xdd0e3ca276d1b2e5L,0x07dea7e48b4cb3a6L,0x62a63cc7fc4a0f0aL, + 0x048478ef5ea2eccfL,0xa77eae472e34c1a9L,0x7a2120751bfa5dc6L }, + { 0x0c1fbbecabc233ffL,0x6255fd91dee18d7fL,0xd6da39aec38462ebL, + 0xd86bc3194be435f9L,0x23567d64291c606fL,0x6b85038af67051adL } }, + /* 35 << 308 */ + { { 0xbe79e1b1eef4ae7cL,0xa45668dc42fb7357L,0xcdb3b3ee2d497a36L, + 0x6ef724e6c5f8d861L,0x7e8834523802a324L,0x641b3a81aba90442L }, + { 0x13bec555ae4c2544L,0x340d34f927d172ceL,0xfcfd933bd92f558cL, + 0x57d8e300d5a669bdL,0x9f745ce71883049bL,0x19690a31e261f9ceL } }, + /* 36 << 308 */ + { { 0x004105c3811af84aL,0x01307934a7934a0fL,0x179fd49b9b3226a1L, + 0x195d9e5cde6834b4L,0xfbb79dc00e6051bdL,0x354273ed367f4487L }, + { 0x4afa9d4574fb892dL,0x03ae905ea1b7f3bbL,0xea32cd5d592f6122L, + 0xa758eed2f1103301L,0x9dde4238c59d1cc8L,0xe2760bcc51022a42L } }, + /* 37 << 308 */ + { { 0xfed7077b7a7134a8L,0xe65b4eaefe0cf05aL,0x130de76be626841bL, + 0x499934ca300117fcL,0xce74885d4e186b5cL,0xd352d0d2029bee7bL }, + { 0xd86c448c857a38ecL,0x8139eb50a956da9eL,0xa036de4a93ce7131L, + 0x3f9eba375041c9d4L,0x8c24408e548f74fbL,0xa74053fde942bf8fL } }, + /* 38 << 308 */ + { { 0x64cb00f586ff10acL,0xd1eebc4c9cbba8d8L,0x427fad8af3157125L, + 0x9f8eb84cf7523b0bL,0xbdd082bf2e6dc29cL,0xfe40623823d3c315L }, + { 0xad5df7fb546d9dd4L,0x83cadc4b8e42f3c7L,0x7c90502c36876485L, + 0x4f33eccda35bb6d2L,0xdf7571383a79b9baL,0xd250b7d2e6ddafaaL } }, + /* 39 << 308 */ + { { 0xa52a7595504417a1L,0x540f70b014683af9L,0x5f0d1560f27a9620L, + 0xccad06444b2147c9L,0x92223275e52c8eccL,0x30d6b52b7cfedb7bL }, + { 0x2161f8bb9bb5b844L,0x075b9db87033586cL,0x5748d512c8c5189aL, + 0x95d76a950f0aab91L,0x91f85aaed0ce9c56L,0xeab8cd9b8434e695L } }, + /* 40 << 308 */ + { { 0x54f84d70d377d7b0L,0xb745d1903344bc4eL,0x1c693ed08f33aa53L, + 0x990ed45f8bfbee7fL,0xad620c9fe9b258fbL,0x465ccb101a54bf46L }, + { 0x5330a0d3ebc40951L,0x34423e8ca405da61L,0xeef1ce78b83043b6L, + 0x99678f22ac06d182L,0x9213f57d1802f14cL,0xf8549616adf11fdaL } }, + /* 41 << 308 */ + { { 0xc6ca95476c66fa6eL,0xcae41345bdd5b16dL,0xd72a41a4ef022783L, + 0x810f4615b2d5154aL,0xfddc469e6d333af9L,0x3154ccbb02d2bf38L }, + { 0xb33d5c59fc1a0bdfL,0xd8c3f8743c971fb3L,0x5e47ec01114e68b2L, + 0xa440a83fe9baa164L,0x353d01c397c26b35L,0xfaabf5dff03b7672L } }, + /* 42 << 308 */ + { { 0xdc2a97651e22de2eL,0x91eef436b6cd3b6dL,0xff099200f99ac721L, + 0x20faacfed4f89e8aL,0x91bb24373fcfe45cL,0xb7a152897b6d3ff6L }, + { 0xfee966c0ef94332aL,0x944728473c81b942L,0x831d36dfab1a553fL, + 0x244bc8393023cca1L,0x3f4a49d57e7be940L,0x4159aa9d7b71c0e0L } }, + /* 43 << 308 */ + { { 0xfc25fcab5b16ee64L,0x44f807e06841acd2L,0x5f43cfedf59c3f06L, + 0x9279c8110c5b59a7L,0x825df117194b80beL,0xe2c18880d27d6fa7L }, + { 0xc9aab2e66a333721L,0x1665b6f55b034c1cL,0xf28fffd13df9796cL, + 0x23caca87bbefb8a2L,0xfc556d575f7510f0L,0x41990ce8552dafd0L } }, + /* 44 << 308 */ + { { 0xf31796d2b6e392e1L,0x199d624893b3395eL,0xef14c7c212f9b763L, + 0x721ebf2143edb7a5L,0xa40b88945e96f3baL,0x8770608c4cff8394L }, + { 0x990c99ae8d0def0eL,0x292b26dfa15a5649L,0xa98fda2c91ca89d7L, + 0x916cb1b4973e5f5fL,0xa2823f13a72de0bbL,0x415f7bd28cd3219dL } }, + /* 45 << 308 */ + { { 0x5cfde16a9fc0e90fL,0x61bda4caac6c15d3L,0x5935e48e2a79d928L, + 0x31213c7c82f986eaL,0x170dc539bcc4c0dfL,0x2e0d29406f11823cL }, + { 0xd2dbecac80fe659eL,0x98b7f46b8399d8b8L,0x259f975abb204589L, + 0x65f3073cd5c52a46L,0x0f4c007805dc7fc4L,0x16c49d403031a8ffL } }, + /* 46 << 308 */ + { { 0x95705b15359816d5L,0xce0c4379d0641ed7L,0xb3f0d8321e8a448eL, + 0x8bea060873e2d711L,0x5a85fb2f6a040c03L,0x7c19a2185bcebd4aL }, + { 0x2b10a87aa31cffddL,0x4fc728fa9a5814a2L,0xedabb0dc63bdd2ceL, + 0xdb90173f96bdaa40L,0x543c4f01527ff659L,0x5dbff7ad0a33b251L } }, + /* 47 << 308 */ + { { 0xeef30ea55e636f5dL,0x8df2d4040bccc4ddL,0x8b0d6f35ef1afe9fL, + 0xbd288e6ef8f86f6aL,0xbc68817ebda45411L,0x8a6f50070faf9e7bL }, + { 0x6158c57a53d4050cL,0x6d5a3af165b2252cL,0x10f62839f450886aL, + 0x8b9ac19b1df85080L,0xc160c1567553ed58L,0x2195ab29cb449cd9L } }, + /* 48 << 308 */ + { { 0x521f4af73ed03d5fL,0xe3461f66eaf9064cL,0xad099ab7ae03777fL, + 0x541cadcdb65f73ffL,0x53430463a86059b9L,0x8ff88fe5043e9f82L }, + { 0xd515f4c7e42cde45L,0xf7f3dec3f41c3269L,0x7bed53567ef1b8ffL, + 0x8782b45f1295b5feL,0xab54ebaa03917627L,0x8516beb28787ed9fL } }, + /* 49 << 308 */ + { { 0x24b2b95b113940daL,0x8c24d8d3f9c6e6d1L,0x7c584170eddaaf29L, + 0x249267171efd01aeL,0x692cf8f40cd0f2d5L,0x0bf82e142f960244L }, + { 0x6dbcb6162dabe927L,0x76d826d20aa1eed3L,0xe4492fb3be98af99L, + 0xd4f27cbea50dd711L,0xb7796efe2d8085daL,0xf2d42519ec4e8ec2L } }, + /* 50 << 308 */ + { { 0x3fbaf46dccc3c261L,0x773c240c1b646e80L,0x151a711f363b6a5bL, + 0x3c8680b1c53b5b59L,0x8ee6795f9fb234b6L,0xab7840aa2f673211L }, + { 0x0a1a0ff3224a8184L,0xcab87319c71bb575L,0x7a9e9daa8125668fL, + 0xdc607b016c4cff5bL,0xa54cb4c792e5c760L,0x977e4c93d99e4655L } }, + /* 51 << 308 */ + { { 0x87d4ff71ebe95680L,0xa2093915e5adaac7L,0xd5bbbdade32f5d9aL, + 0x5d61056cf328a4e1L,0x61fcdb0f353f565bL,0xb7b8ba004efab5caL }, + { 0xb5bbcfa410f05eabL,0x483ae9221f09a105L,0x17d94ca44bbf4753L, + 0xf734a8cdbbdc9a94L,0xc7f01a4244e81e2dL,0x60c3e777b3ba8033L } }, + /* 52 << 308 */ + { { 0xba7df5a965b68624L,0x30b4d6ed6e7d58bbL,0x67e52341dbb81762L, + 0xd697ab1b0deeac1dL,0x01d15e8e5577ea92L,0xbb12d72498fb38daL }, + { 0x302faa6d4e04908dL,0x66cf6cb909b90a9cL,0xcd665dbd98d96736L, + 0xf7d3c528b86f3af4L,0x4844c7541d8b07f4L,0x2a77d7b91eaf7dc0L } }, + /* 53 << 308 */ + { { 0x8a36c9b57fceaa87L,0x5110912b553c7ad3L,0x4aa51166d5eca67cL, + 0x05740dcf07a5eb58L,0xeaafb3e3396857a4L,0x1ae9571bba8d62d9L }, + { 0x2736975500272434L,0x2c74325c59872fbbL,0xd1d8291709dda11aL, + 0x2a5334eb4683e8a1L,0x22cdd088e3481df0L,0xab1c5f5b4fddc546L } }, + /* 54 << 308 */ + { { 0x1966aa0515f46174L,0x495901bd2a074050L,0xda5b0cdebba902baL, + 0xc47c518a684325bfL,0xa5df133ec4d9d6d9L,0x3771f465fbf7d31aL }, + { 0x0a73718c02b05d1aL,0x1107cd45534237a2L,0x582cfd2980f5d897L, + 0xf51a0a88dab0269eL,0xfdea51cfea1a22faL,0x3c9a0d247a13a324L } }, + /* 55 << 308 */ + { { 0xcc330f58c42f1ce6L,0x8e1fb7df534efc38L,0x2a37208f5fa5a01fL, + 0xc06d8447369bdbb6L,0x0b1ea5161a3e36e7L,0xfb4a48366ff9abbeL }, + { 0x5989c2d524419909L,0xdeaa6136f1d5b1caL,0xac6003b04ba760f1L, + 0x3a6d5422059081beL,0x96c7fa9df797e22dL,0x67c2f77fa9f3addcL } }, + /* 56 << 308 */ + { { 0x53e59f251d70eb73L,0x8aed17afe69d0525L,0x26ddc17864413768L, + 0xa7c8d40f5e48c349L,0x29ad92d187ff01fbL,0x8f4e1b3b965b2de1L }, + { 0xb83cfadf1446eca2L,0x7432bda4e609d416L,0xcf97e8a3f1c7de69L, + 0x45899bd832f55f07L,0x41a6811751175738L,0x89eeb115b8efff21L } }, + /* 57 << 308 */ + { { 0x9dcda4f3723fc25eL,0x710de79fb5d954deL,0x095ffbf1f0b7d129L, + 0x419a2a5e32651179L,0x7b249135827d4268L,0x9dccc98d909fbfb4L }, + { 0xcb4b0cb016554ab5L,0xb2fc635f6d84b255L,0xa7f8f3f553512b87L, + 0xc72633f300ec778bL,0x4e07d91a4f1841a9L,0x2a1adbbdcb4f478cL } }, + /* 58 << 308 */ + { { 0xe31333093bb794fdL,0x34c68bac33b3be44L,0x953fa2c412172b7aL, + 0xa9afc12d4fdde6ffL,0x30b5302ae9c7804cL,0x4a1746c702119e68L }, + { 0xc4d0c7d323e2ec51L,0xbc821f217143d613L,0x8f41251a673e203dL, + 0xfa32c06aac2ca4c3L,0xf4343f2799a7c431L,0x8f7d489e6b96d959L } }, + /* 59 << 308 */ + { { 0x183311763f6278f9L,0x4fcc5b653593cdd5L,0xb09b5880e643f83dL, + 0x0f130a3d2c78466eL,0x926d7c3d2b1c1ebcL,0x7217f875662ed4ecL }, + { 0x2d3be028d81cdad3L,0xb2a04e3507a38019L,0x8da8cddfc9a3097eL, + 0xbaa67f60ddb20228L,0x698fc1c407f04de8L,0x6f0e1d6d7e86db6dL } }, + /* 60 << 308 */ + { { 0x54a01e60936c3ebaL,0xf326fe96ec01b12cL,0xcdfaf00366e4de2eL, + 0xc53dba07392fd0a8L,0x00d9b80f6ec46004L,0x84d59be83ba63f8dL }, + { 0xbac4ea439dea6062L,0xb4b4845badd568caL,0xa6ca3d34d225e2d0L, + 0xce72955db50070a2L,0x56e5c91321c78b68L,0x888eb198999488a3L } }, + /* 61 << 308 */ + { { 0x65bead3c1c2de335L,0x0ecdc057b18a6778L,0x821b836983e57ea8L, + 0x84c80b574a5c11dcL,0x0b6432822ac9ad27L,0x8e09a7f344fe943fL }, + { 0xe510f47daa92dc94L,0x8bb0b5cc6a1666a3L,0x55315bcc24645380L, + 0xe3acbed113dcf7a1L,0xff99c90e3c9a1610L,0xfbe9aa1bc326e1f5L } }, + /* 62 << 308 */ + { { 0x5040bea56827b6e3L,0x1049e004d935eb24L,0xa15f9a07ba9bde68L, + 0xda430c55e6087e70L,0x30ed69af8e84b7c8L,0x8498514eac9d6a72L }, + { 0x69c783d64cb27e79L,0xe55d31a09647a572L,0x0479e8b2fbfb82e8L, + 0x3e845922b52f08c0L,0x252f755f0dbca622L,0x6219778389ddfee8L } }, + /* 63 << 308 */ + { { 0x175264893ca1461fL,0x54c432f92b6476bfL,0x0e0be36a530795f9L, + 0xb9896dacca583429L,0xe4af98239d4e6085L,0xa38b7c4b4a7422ddL }, + { 0x74643ef47163e421L,0x74c28314895ee61aL,0x637c79c20d62b657L, + 0xb232ec619bf2b3afL,0x27bdbfb4b2d5992eL,0xcc6e424c49afb181L } }, + /* 64 << 308 */ + { { 0x5255508c11c92f34L,0x9a346cf3a294d382L,0xd9765eea3095205bL, + 0xfea2ed702c470ef7L,0xf5e8a0fc9c40bf0aL,0xb572390ee4137a16L }, + { 0xb91753712bf2f545L,0x2c2d0f4c58cd9cc7L,0xbea6bce902385486L, + 0x46208408a8bc3a94L,0x64a87a2a3ac45044L,0xe40da33c7df70151L } }, + /* 0 << 315 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 315 */ + { { 0xee9e25d939161b8aL,0x8763f2a2e2eead91L,0xd2fc1157d2d91300L, + 0xe7597e2fffcbe50fL,0x4be3814fe11d376eL,0x1eab3d7edbf14562L }, + { 0x38a107c0c0ad183aL,0x829766267c753bbfL,0x18014e09caebd481L, + 0xb28c331bf9ace60dL,0xe8fba04f211cb8e7L,0x41c4b797e42dc65eL } }, + /* 2 << 315 */ + { { 0x009dc2f4c3e88580L,0x4a405be899db1fb5L,0xc89bfaa2ec5d91feL, + 0x461be9a0f160afcbL,0xfdd084bb7d7566b5L,0x795275e8e48099a2L }, + { 0x1b461fc9fe9815dbL,0x576214cd73627bbcL,0x3246332d9f09a206L, + 0xbde4c0c36941d6efL,0x44ef03fdf387f5f6L,0x99c8ac0157b63400L } }, + /* 3 << 315 */ + { { 0xaa512f202f6e4301L,0xef668a5fbf94a1ccL,0x08713c3015861b88L, + 0x49d47551c99bb2b6L,0x6db5f812e2f0258eL,0x70c9b299998d7435L }, + { 0x46168e1c5d176ae0L,0xec3306e4f730ec30L,0x49439df3ab69c15dL, + 0x1040408bea0143e4L,0xb48ab8eabc549b0aL,0x4aa38bbf10f89223L } }, + /* 4 << 315 */ + { { 0x7e4851599598f49aL,0xbdac3d5e9629305bL,0x20de0dafa6fbabfbL, + 0x04f015838f09fff7L,0x5a0562976a06994fL,0xf51dac8f6e3ccd33L }, + { 0xc087ef9c3af507b8L,0x525ab76e6a5c6663L,0x4fc04814d916ee93L, + 0x3369c978d23d140bL,0xb0fcd70f1662028fL,0x2ca77de2e1e28adbL } }, + /* 5 << 315 */ + { { 0x838acd1bc512bc71L,0xac06d6bddc18afd0L,0xc991c1e39ec45f4bL, + 0x667c5e89cc27c68eL,0x0e059b04ed07f829L,0xceccf1d4cec4b3a7L }, + { 0x3d9c2dc9b953f9a1L,0x4be2f7e72d599b16L,0x1a2054b197256c26L, + 0xcf66fa478b4fdfebL,0x896cc1b38134d7efL,0xa17264cad41dadbcL } }, + /* 6 << 315 */ + { { 0xe3ccfe8e37627e56L,0x00733a867b6b21a6L,0x3f13e2cbb605c427L, + 0x5ee12395b0d80992L,0x4dcaea94b9991381L,0x4cfed7ee8c4c4b6eL }, + { 0xd7aad54b7f7f45dfL,0x2229407fb3809bf8L,0x6eb31eee68048fd9L, + 0x693842dfd57225fcL,0x3e62cd85a88dfd3fL,0xc6307d53d5462cf1L } }, + /* 7 << 315 */ + { { 0x2d15615ef344f5fdL,0xe0ba6a8aa7f23989L,0xbbfc58041c84e3f2L, + 0x22ffeaae6f4ba826L,0x1e9bf27494292682L,0xc768f89146c02af9L }, + { 0x894127d6177cdafaL,0x8d0523da2acdc791L,0x71ada9aedc78c3c4L, + 0xf21dbbb92c532a01L,0x0c797d5eacb20fdaL,0x1ff99d7616cf57b0L } }, + /* 8 << 315 */ + { { 0x99b5f150493c1d64L,0x3422b656fb74075eL,0xe7493900ff19bf24L, + 0xc82e5b80260925edL,0x3398d340c0ea1eafL,0xe7de2ba11287121eL }, + { 0xea6dfb0b87847031L,0x73bed0a1566af2f2L,0xe26678bf12012999L, + 0xb5369e4d32e5cebcL,0x2304eac86d181e32L,0xafdbd9543d364addL } }, + /* 9 << 315 */ + { { 0x5b1a53ca75da4189L,0xa90485802eb4862bL,0x319424092783ad6aL, + 0x15a4c5e11a9e025eL,0x841bc53313837199L,0x6e9d3e14e642954aL }, + { 0xf4a02bbdd436ec5cL,0x62fe177bc6d6ad53L,0xedbf1e4eac86425aL, + 0xff9359c8d9f752f5L,0x79c685d92d7ad656L,0x8d82c0c4fdde9052L } }, + /* 10 << 315 */ + { { 0xf55f868e702f640dL,0xe459aa9b1dedda11L,0xbec0ff9bbb5ba193L, + 0xf7325c4957724703L,0x5ab8f06323e0e4fbL,0xfbf02e91ecb0fd7cL }, + { 0xcc72e8daa2e5fa31L,0x47de252832cb53cfL,0xbfa646e64252763cL, + 0x7a769efeb8d81de3L,0xf5ec70031e772f00L,0x049bea9a2729aa5eL } }, + /* 11 << 315 */ + { { 0xe987ba54759090d6L,0x904d6901619ef08bL,0x9e16d1382024a6fcL, + 0xb6f0459ba9f3b7e4L,0x1f2a530817ee069aL,0x99403b2e2be31049L }, + { 0xba1663c6bfb2f288L,0xf829195cc7a92b41L,0x89b915ee8ae621b1L, + 0x3fbbb1e150f8ea92L,0xb1fe7f978c901ddcL,0x16d1f62cbbc69ca4L } }, + /* 12 << 315 */ + { { 0x51f19bb3fda072dbL,0xa815459fe3f7e0a2L,0x5f7cde2f987112caL, + 0xdc51d948759de2cbL,0x9d05c410ed49bd98L,0xf063ab99364341fdL }, + { 0xd7869d68d1aa0a11L,0xc20291065d862d01L,0x7f258180c2591073L, + 0x7b90fc7a6ebc4ebcL,0x5565390f3dda1d68L,0xae77fca8a44e4493L } }, + /* 13 << 315 */ + { { 0x97564e4847c49ee8L,0xc56bb5a9ab4ebef5L,0x80d969417b4f86bcL, + 0xa594b4e541026cf0L,0xd56c89965a89ece9L,0xbcf609316a0f922bL }, + { 0x702596161103475cL,0xb1224fb58a2a2abbL,0x0a437a03715cd61bL, + 0xcbe2d2b2739921edL,0xf3b1b5e9385541c4L,0x5d0984f4ae010520L } }, + /* 14 << 315 */ + { { 0xb4a2742dcfd9295eL,0x9cd36774ae929cd0L,0xb15fadccdd7fcf4fL, + 0x0b1fa2b337d4fcc6L,0x242c7b26f01c7ab7L,0x2be8131b50574cc9L }, + { 0x6ee50f42bd89a03cL,0xc7f6ff8f005e7765L,0x04d13af18420501bL, + 0xc22e092b1b6e7d2aL,0xa393be7ee9516f80L,0xa2593652b80bb5b5L } }, + /* 15 << 315 */ + { { 0x5caa5da68b23bebbL,0xa1ad33e81fdbbdf4L,0x18dc93cf4e5c1de0L, + 0xc3e6addb5bd9e178L,0xf30d517e7cb8cd03L,0xbb84ce54f1abc417L }, + { 0x0774b64c67699659L,0x228005b9b7d4a401L,0xd8c2ec5b80b2d3d2L, + 0x419c4cd93450ba7fL,0x520ae681789286a6L,0x24b67ea9aa8bcfbbL } }, + /* 16 << 315 */ + { { 0x9e41b9b70f74808fL,0x2d835dae0c061bdbL,0x67e50c8cf272346cL, + 0xc98a5ef5def57493L,0xc2dea8afa02676fcL,0x59508de26ace4659L }, + { 0xc2b707aada6cd733L,0x6c1f226a4be7bfb9L,0x5b580fa2a778c20bL, + 0x272c3a1d57af166bL,0xe47a64a9ca78ce62L,0xd12db7d771d35087L } }, + /* 17 << 315 */ + { { 0x6a37ac5a2ada7e64L,0x664594de04e35dbdL,0x3a82f748ffdbf300L, + 0x4525ddf155975f5dL,0xcfe5a76bbdf2035fL,0x1693a99f0fcbda84L }, + { 0x5bdb76856a297cdeL,0xdb9ad0cef1d1009aL,0x9e9dae1caf902a00L, + 0x7e36f79f271a0a50L,0x688a0f41a2a2f652L,0x33d2178613722e40L } }, + /* 18 << 315 */ + { { 0x2f4abaff356f4ca1L,0xa2e419422d13be2bL,0x58d72e2f3d7db731L, + 0xafc2f505cd455649L,0x8a0794cd1583705cL,0x4a43066288ffe8e7L }, + { 0x2c0c031d135c8e7cL,0x8ecd9ed76b371b41L,0x17cc1ad9563843eaL, + 0x9603987cfc6b810fL,0x6e291ed7f0d9498dL,0x8c69ae62e1a4058dL } }, + /* 19 << 315 */ + { { 0x934666dd40680b5aL,0x37a9c6ac91e762f6L,0xa0a10533e4d26e7eL, + 0xd811d558ade18237L,0x6e2918ed411b121fL,0xbd9352b93c24a52eL }, + { 0xe31569ccb811ec4fL,0x3b5b977553f7d097L,0xa0d9ebfd7198e959L, + 0x63e10ab13f0a942cL,0x65b8b87f8ea55897L,0x935ea3c129aa0212L } }, + /* 20 << 315 */ + { { 0xe14dd3708ba8a3dfL,0x49c1fc3750a645b6L,0x3f0db6a32252ff87L, + 0xea2ac3c4a34ad040L,0x97a37936decf9f0fL,0x810f02326f7f92ffL }, + { 0xd96c2641184e9c88L,0x08c4cd333d5ab12eL,0xa938d8c3eda80fdfL, + 0xf2dded68bfccc054L,0x4b3da61ede36ac9cL,0x2c266df8347ef904L } }, + /* 21 << 315 */ + { { 0x4653cbfbe3443739L,0x53ea14dd8dd85382L,0x2f6d0513f26ba2fbL, + 0x374d9bee51269be1L,0xf976cdb243f1f612L,0x68b47bf7b5f171b8L }, + { 0x726e93dc7095f377L,0xe6f18c57b59fcfb8L,0xffb56a4023d9eb60L, + 0x678c9508447caf79L,0x4cec83e459740ce0L,0x820ab7eff4d7d58cL } }, + /* 22 << 315 */ + { { 0x88eac51c8e376fe4L,0x096e70c49ef465b6L,0xb35265852004969eL, + 0xbd581669d29cc63dL,0x88094298745b6919L,0x317e386c12e7d67fL }, + { 0x33848bb2e3d6f4daL,0xbace887f2a0ca785L,0x83b32feb197e67a7L, + 0x2b58535ade9c851bL,0x3e428b19c38beaa9L,0x784aa3d174f26de1L } }, + /* 23 << 315 */ + { { 0x10c5f1e5b292efd6L,0x47d92b88ddc96103L,0xc8743717e5e802e0L, + 0x47781ba8008dbb2dL,0x7abcd3acf02360fdL,0x673e2b05e9142308L }, + { 0x501db7c76db93818L,0x285ced71f33dbda3L,0x30aa5fb5cdba4b44L, + 0x93d536c2df0445b0L,0x28a77bfa10196091L,0x26b9f668e38c4c7fL } }, + /* 24 << 315 */ + { { 0x98c3a697c0909659L,0x35c3b0f297d847aeL,0x67d9f71273a7a5a8L, + 0x28e83651b47bed08L,0xfca9e849567b3410L,0x5fa9a6ded291fe1fL }, + { 0xd79682421976a995L,0xcff5bb36a0261383L,0x34166ef962e9922bL, + 0xd816b0342d433139L,0x3b62d3589c4b99c3L,0x8521f917104f7cc4L } }, + /* 25 << 315 */ + { { 0xc35a5c7874e09962L,0x1c340269e1690418L,0x2ed61ab4dca0de49L, + 0x2570d29ede2534ffL,0x9077691bc5143c88L,0xaa249a4a346f3ec1L }, + { 0x57e4f1e104de76b3L,0x206859c3f415b99dL,0xdac6f415f9a15eb1L, + 0x2bf456d00a9501bcL,0x1ceb7dc41ef91323L,0x19c1fa8c3cb8afb0L } }, + /* 26 << 315 */ + { { 0x7761d8fc6f7b6eafL,0xdc439bfdcc0575e5L,0x33853d91f1ff4383L, + 0x6da20e4b75dc1254L,0x25a53b581969a1d3L,0xb40df56723311968L }, + { 0xac150a297dd6aaebL,0xfe6865ce2a3ba337L,0xea05d97cf71013feL, + 0x0ab3cf008053c65aL,0x7cd38b647bab4869L,0x788cb867204cc6a5L } }, + /* 27 << 315 */ + { { 0x253a041e36e88e48L,0x1610f836b86297fdL,0x379d3da109334bb9L, + 0x62de4308777fa7a9L,0x604a46bd6dfefd1dL,0x9e4740ae314eed76L }, + { 0x40ec32e12efde5ccL,0xa5b841bdd92c1faeL,0x01852e23dec68e16L, + 0xc76173b88b55b2c2L,0x4609f350377d5e77L,0xe9c4167ffd67c6b2L } }, + /* 28 << 315 */ + { { 0x52732a0a4b0fc112L,0xe654744e9d125dddL,0x9f76cf7e269beee7L, + 0x2fb8bf32ff80a2f0L,0x1bcef16262b7153bL,0xdedc255a43a4201eL }, + { 0xb1b30b91acbd8a37L,0x147fae6f240adc8fL,0x5558702cb39bf39bL, + 0x171e58803e1eb997L,0x095bf301ed7c79b4L,0x29f1dbffeef752f4L } }, + /* 29 << 315 */ + { { 0xcbb2506e7535c370L,0x40ee37ec7ab20106L,0x74f502d4caca3675L, + 0x167e778db57c0364L,0x7726715b13fa3dccL,0x76097791f42e0c3aL }, + { 0xe1d990c3379dd41aL,0x432454d785c8f5e2L,0x1f90c59562ac45e4L, + 0x63e156998ffe0c09L,0xc3bb8c29d42bf0a6L,0x027d5a86ecca4cfcL } }, + /* 30 << 315 */ + { { 0xaf8ca08b20492da0L,0x37b1fa1547508667L,0xc9fc925b96077958L, + 0xb78c83c19ecac8b4L,0xd9d953a17c05a67fL,0x970ee229b9ebcaaaL }, + { 0x689cad7f55dc989eL,0xf02f05bc66c941fcL,0x8d00516281e23d8bL, + 0xfe603ffc8caebcc3L,0x592860bff303153bL,0x9ec1d5ab3344e524L } }, + /* 31 << 315 */ + { { 0x7e374b7b0f922941L,0x44b3f00174466c92L,0xcb3eb28c3c2fe678L, + 0x91079467bb9bf05bL,0x0d268749de2dcbe3L,0xb6383ba4c5204680L }, + { 0xd50269f4951d3c71L,0x9209a2d53ffbf2e0L,0x2f6496258110f811L, + 0x08fc9fbb0b31e275L,0x697960ea1faec287L,0xae95e4a8c5420ad4L } }, + /* 32 << 315 */ + { { 0xc20fb9111a42e5e7L,0x075a678b81d12863L,0x12bcbc6a5cc0aa89L, + 0x5279c6ab4fb9f01eL,0xbc8e178911ae1b89L,0xae74a706c290003cL }, + { 0x9949d6ec79df3f45L,0xba18e26296c8d37fL,0x68de6ee2dd2275bfL, + 0xa9e4fff8c419f1d5L,0xbc759ca4a52b5a40L,0xff18cbd863b0996dL } }, + /* 33 << 315 */ + { { 0x1304bd65ff0e8fbfL,0xa249adb53343deecL,0x20635fa9826e1293L, + 0x6283f098b7bddaadL,0x0d0a7820bc96fed6L,0xcd7605d47de0b9bdL }, + { 0x4f0a9751586f9eb6L,0x2f6dde5556b2521bL,0xb7efccbd76264c6fL, + 0x7df9cd35b2613621L,0xc334c8f924a2ff4fL,0x914f472a0b13b604L } }, + /* 34 << 315 */ + { { 0x89092cbc5f6bb241L,0x8b4dadacca123b83L,0x9ba420eecd2dbaa2L, + 0xf269d1982dd6ef2fL,0x29f68d03809b338dL,0x18cf8675958ae927L }, + { 0xc179d4b2bffac33aL,0x5356ffc1522695e1L,0x453474986d039c90L, + 0xcba0e0fc5a675530L,0xf369b7ab98a0c70cL,0x51f82173d508c254L } }, + /* 35 << 315 */ + { { 0x5f98e5aae8490374L,0xdd84a7506ca52a68L,0xb6904ff8a9244f56L, + 0x4c908c0362a5502fL,0x70ff1e01a8df73b3L,0x573a37f20df382caL }, + { 0x5df73cf8c7dd1209L,0x965ad402abfbcd79L,0x61a633a59e67af24L, + 0x0953c83cc64203f7L,0xe14f58f9a1fd8dcdL,0xb5ea722887a5fadeL } }, + /* 36 << 315 */ + { { 0x55466aa1d896c2f9L,0xd03ade059831fb31L,0xc46711547d968dfbL, + 0x8ade0c97bce2fdb9L,0xb408c7457f6d843eL,0xb1bbe028a709cf63L }, + { 0x1dbd25383ba4fe36L,0x1438d322dc1f2720L,0x1c3c46b9c37694deL, + 0xe57133dc3997e650L,0x754c171e422b95bcL,0x29c47f0da209c7bbL } }, + /* 37 << 315 */ + { { 0xe520480823822d0dL,0x745fe7aae3eab177L,0x6f0f4a7e808500edL, + 0x9383c632200c2bf0L,0x6f3130d7be22d432L,0xed7713d465511061L }, + { 0xff84bc04049067acL,0x33c2be61d56210e1L,0x57d63f885ac04f01L, + 0xc2fbb773284fb49dL,0x46422426e1f349adL,0x3cb627c465863455L } }, + /* 38 << 315 */ + { { 0xea06cbe9a1edcfccL,0xb0438e198aff46ecL,0xa93fb88ba450240dL, + 0xfc4a370021b6b45dL,0x2503aa5d82a21241L,0x7533f1d7f540d3b7L }, + { 0xd7a58a679277538aL,0x466d981a539c347dL,0x46f1682bf26488c2L, + 0xee2b4976318282e4L,0x8fe5e5b85a94409dL,0x40ca43a7b1a4fc28L } }, + /* 39 << 315 */ + { { 0x0ed4414c901e48d7L,0xdcabb46418340890L,0xd50bf12f20998781L, + 0x498a90232a596ffdL,0xcc877212b43f456cL,0x98d9d531f796c4fcL }, + { 0x061e3b31977c11b9L,0xe56bc6f00a00c822L,0x756e62c96887ea43L, + 0x29129d53859ec944L,0x42342589146c1fbeL,0x2f2cd4bdd1884196L } }, + /* 40 << 315 */ + { { 0x3d3815d645d94a24L,0x4cd9fe1139f3e6e2L,0x8c7b8dae8e7eb572L, + 0x7e69faf40f7deecdL,0x0e54b3c0387e97ddL,0xd12e473175a1b6b1L }, + { 0xb7163632c664f92aL,0x86ab4ea88d94e55bL,0x37212aef1133dcbdL, + 0x0c6c7fc6dfc0d47aL,0xacbcb077aa9e1ccaL,0x43cf50a726ef7fb6L } }, + /* 41 << 315 */ + { { 0xc0eb003c54d7bac5L,0x89780aea2b770baeL,0x13a194e8076bb29cL, + 0xb863585046f8aa90L,0x79ebc6066df515f0L,0x25ea422dd1ead000L }, + { 0x16b03b8106c89b71L,0xa964da878ad9fff7L,0x2c96dc6b2e7b9072L, + 0xf71788978c93f6bfL,0x4c7ecef912688648L,0xed7b4a577c663be0L } }, + /* 42 << 315 */ + { { 0x5b7cdd0ad74a20d2L,0x273184f48bcdd2f5L,0x4d8d3b4ce3ac03f7L, + 0x0e2ff518a02cc60cL,0x9c006ad8b6fa606fL,0x401606caccf627a0L }, + { 0xe7429a6f7b967844L,0xe4e5d1c1bc8ac8beL,0xc050f89ff4f46638L, + 0xd23a3eb452f918c9L,0x4528e4e202944b49L,0xeb345a689268719dL } }, + /* 43 << 315 */ + { { 0xf4fbd190ccec4c27L,0x7e042c8722674e8fL,0xbc79835ae8b33439L, + 0xc7923b8fad2124d1L,0x0ece42272c72542aL,0x02d638e2b9264875L }, + { 0xbdf9fba1904e7683L,0xcbbc0e0aac934377L,0xea154d99459ec213L, + 0x87db3f66c3023e2eL,0x7f9262d518de83a8L,0x432fef4f3524400aL } }, + /* 44 << 315 */ + { { 0x3b5566d7938a395bL,0x920dc1111f256c82L,0xcee7f231a059c8f8L, + 0xdc3da434d48b3179L,0xb1e819e913f78de6L,0x94a21bb01f9819deL }, + { 0x8ef14a96f302a94dL,0x9f897e1a079fff9eL,0xff9a4e0e54122af0L, + 0xac6a6cbef0b7f1c7L,0xfd15d9756401df3dL,0x500531a323a0b7b6L } }, + /* 45 << 315 */ + { { 0x12e22a012da0c724L,0xa0a837f3b80cba90L,0x89df9a3e2a9b5434L, + 0xf3299f64925840acL,0x0cc78a3a125b3dc1L,0xa4ea6203c723d647L }, + { 0x5cee8068d369522cL,0x3e479803432d5e87L,0x86e809363ad8126bL, + 0x93e871c9cf89d85dL,0x892e4710286c9010L,0xa075a6d3ec3a1792L } }, + /* 46 << 315 */ + { { 0x095768bc7dfddf6eL,0xc4e331b4e63c4e60L,0x1179808104f28a2aL, + 0x415e33e1bee48983L,0x7fe8050144af7eb7L,0xdf6c423b2f28fbfdL }, + { 0xd10886db007a2b56L,0xea578b286613f26dL,0xd18a9d1c2b90a815L, + 0xd4c6e8b2675c2c8dL,0xff973df5788bf2d6L,0x4fbeb6210d7e611bL } }, + /* 47 << 315 */ + { { 0xcfab317671674fa8L,0x78038a1afef7089eL,0x3109736aa27b5b55L, + 0x1b31325fc0193518L,0x3afd21a8be19b5f0L,0x548196a2d8028eabL }, + { 0x15b0d6d2a94e6be0L,0x1552ffb67afd5dd6L,0x49b1150d89bed9eeL, + 0x2c59b0bfb0d1444cL,0xab265d7eb695a900L,0xa24d0788a1dd1ef4L } }, + /* 48 << 315 */ + { { 0x4e913e1131e325ccL,0xe92f7c8f2a65fe01L,0x8e61a80d5857aae9L, + 0x2c36923d53104397L,0x5b0911d6b36d5379L,0x76eb9b56b1207ae0L }, + { 0xb5cd11646723c4aaL,0xa6bec13b98891a11L,0x09af8be29d806056L, + 0x7da8d29ecc1fc0e6L,0x231cc00e2aa8791dL,0x2ded362c042171c2L } }, + /* 49 << 315 */ + { { 0x26eb2ac96afa51d2L,0x83485eff13c04ce8L,0xdedb48718072d8dcL, + 0x4da1771d8ac3d411L,0x2d8f99ef849c6c0bL,0xea65f6bc2b5882e4L }, + { 0x60a90f58fd671216L,0xb9f3e2058af33bedL,0x29c41ec92bf02916L, + 0xcdf15b1de5ddeae8L,0x67f9ad163109e99dL,0xb9b5585f517d25e1L } }, + /* 50 << 315 */ + { { 0xae016b4811b3e20bL,0x5ccf3cf1e5164179L,0x1281ff8efe9fd47cL, + 0xb85438038e61bdf2L,0x694e42feba5856a0L,0x53f7e09759b32aa1L }, + { 0x5b9848e9c341a531L,0x9a5fb85025952b73L,0x9d5fe0dea6f82c5eL, + 0x9216a8ca44090933L,0x3e986d4bc3272875L,0xc20534f8f3512e42L } }, + /* 51 << 315 */ + { { 0x718124a1033495a6L,0xc4f28a746834851fL,0x91186d80e1baaa77L, + 0xca4e13222a761e95L,0x7b6b8322582ddee2L,0x75d396c6c3c70c6bL }, + { 0x075dcd6b54c75102L,0x3669b97c0b92622cL,0x621154e6f0cd45adL, + 0x7ff0029ff381a6d3L,0x3d37e750a726f84bL,0xc4f79202874de604L } }, + /* 52 << 315 */ + { { 0x215018fdec26297dL,0xaa06fd0bbf35d225L,0xe5fb438cab40bc17L, + 0x6a0ab335acb7f4c5L,0xbe1f4de4187a8e6cL,0x651deba961f7e842L }, + { 0x2b30b0046f629aedL,0x63bdbf8e2218f107L,0x21a21aa5f9ca8bbdL, + 0xa88cd9138304f7e1L,0x23594fc6c5e6f9d4L,0x4d4db41a6682fc06L } }, + /* 53 << 315 */ + { { 0xca2317b0428dcb40L,0x9a7bd387288b5eeeL,0xd62da6d0a060584bL, + 0x601a3d6ce8f10251L,0x65718f0584885319L,0x5a87b1c2a1bc252dL }, + { 0x27ae8015a37b05d5L,0xa624af9c98394605L,0x988220050ba4565dL, + 0xb93395c9da2613deL,0xcef9a880edcaa74eL,0x7b2ef0fe0976687eL } }, + /* 54 << 315 */ + { { 0x094f20588e5c6b80L,0x6e5a5f52846eabebL,0x9eaef2d7370a9345L, + 0x12d6f20687c19719L,0x0d2494ab9c44076cL,0x15ccc737de9309a6L }, + { 0x8eeb8faf94ca6587L,0x7dc9a4fe3fe363f5L,0xf02f6e03b3b08270L, + 0x31adbe77daf15507L,0xc0fb2814343bb4efL,0x724007519bdc1d91L } }, + /* 55 << 315 */ + { { 0xd301525c1677fcb7L,0x11b7141bfb6b0dc1L,0x01f4950eb2163b70L, + 0x34c758c6ed3c0025L,0xd1b1c7573a5196cbL,0x7926f0a42fa19c66L }, + { 0x107e5d32b1c47233L,0x0fe50b00cacbdaa0L,0xf45dd7e8e213397aL, + 0xca6b2de9eaa1db7dL,0xbf234b55dd09c2eeL,0x10db87d1a1db37f3L } }, + /* 56 << 315 */ + { { 0xaff57c87de0572ecL,0xc0745250826246c4L,0x523910fc700ef250L, + 0x8c23aa5793faa067L,0x87f7c7198e7dcf75L,0x45ef4adb46695227L }, + { 0x0ffe09d196ceb1e0L,0xfb72a05790f3383aL,0x62d26e5e07c220d9L, + 0x03e19605766b1e64L,0xa774669458c17fb7L,0x9a851d828e7acfa9L } }, + /* 57 << 315 */ + { { 0x150e936f4baea8efL,0xeb5328d68239dfe4L,0xe064fd95b5f987adL, + 0x13d3803d52e7313dL,0x0e9738f5b215317dL,0xb6dd60a7974be106L }, + { 0x00fa92bd6bac81d0L,0xdee050f9e7cb2338L,0xd7943d4f9075745eL, + 0x07cc4170819cfd9aL,0x21b7e0b04aef1468L,0xd7520b77aef07b1dL } }, + /* 58 << 315 */ + { { 0x126c012681097c49L,0x95339f9475c02669L,0xec3fc15b100115ecL, + 0xea5c8e9c49fb787eL,0x63168108bd3fbc19L,0xdbf2430541573590L }, + { 0xcaa3a69686dbc847L,0x2c464fcb70d76739L,0xdd9e0bcd69e2fd74L, + 0x4ae92cc01652728dL,0xafe3e24812b060cdL,0xf3776c6ff951a38dL } }, + /* 59 << 315 */ + { { 0xe4ab1c417af22e76L,0x35a8addf038840dbL,0x95ba3e3dafd0d7b2L, + 0x2a7bf827f84417a3L,0x0bc177c729bf5a83L,0x29ef7f8bd09905a3L }, + { 0x1df34fb1385e6c69L,0x079bc0fcf99e0d19L,0xcd2dbbc4f30eb5c7L, + 0x2d364701afa7447bL,0x3c7bfa087a791ef9L,0xe21508c8e71166d0L } }, + /* 60 << 315 */ + { { 0x0b204c9ac746ec60L,0xdd5efe2718b93b24L,0x484474e0ce15332eL, + 0x690be23d05a308b7L,0xeea3abfcb0f7081aL,0xaff69f36cd8e8720L }, + { 0x5dadd080d951329cL,0x060c379c8cae67c2L,0x8e284705b20851baL, + 0xacc8d8a0e5df0e85L,0x8c024e789463544dL,0x15a9a3f08003076cL } }, + /* 61 << 315 */ + { { 0x095e284899e0ecb5L,0x61e9d5893415c1bfL,0xb1207d3017f5c585L, + 0x75f73f1d04e97243L,0x868551aa77bd50d8L,0xd530e0cc197f7d84L }, + { 0xdd6ab731ea9fb71bL,0x26e5b52e2cf9510cL,0x4fba03ff11a88911L, + 0x6608b634e921e323L,0x4baf22f836d46a1fL,0xb8bced501bc7ace0L } }, + /* 62 << 315 */ + { { 0xaee397fa327d9bbaL,0x9a45e7a2d832e3dbL,0xccb43a730582ae33L, + 0x457b3271d4093b12L,0x409caea6370bd663L,0xa5019f25657f693aL }, + { 0x5851c78a16478fe7L,0x5e09ace7ddf17dd5L,0x89ca68da0763656cL, + 0xb92d3321e2bad2d0L,0xdd5642098422f6bcL,0x4a6ea69946c04923L } }, + /* 63 << 315 */ + { { 0x7ba1f48579120405L,0x6c136597898be69cL,0x1e75e1586dcacc38L, + 0x3d3cb58b65ee4cbeL,0xbccee7a308db0caeL,0xee8bff34e77edfb7L }, + { 0x123bc3f036f60cf7L,0x3b1dc9e779bb4c78L,0x036a8049fe5f0d85L, + 0xc4de23d318f66f39L,0x593cf51e3c436c16L,0xd4d40e906769584eL } }, + /* 64 << 315 */ + { { 0xf6827150844eefc5L,0x002e82c44515ef68L,0xa46c8f55c51916c4L, + 0x98c3524b61ee081fL,0x5ab7f2c2ad64872aL,0x0b503ff07e555faaL }, + { 0x802e0d23b4c58d29L,0x122890402fd917feL,0xb56d19087af20d26L, + 0x8d619e216be50784L,0x10fdbb721372b851L,0xf2c1673e4935576eL } }, + /* 0 << 322 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 322 */ + { { 0xd97a9b1451a135f6L,0x6d16aaf597b4df14L,0xc57160c254818818L, + 0x4dbdeab61d59be44L,0xb93a9dad81f2b247L,0xe2868cf5ecbcab33L }, + { 0x5e1ce82883a86711L,0x29a9ca2f29c55428L,0xe716273a2d82b0dfL, + 0xb017f5f6ac8ff52fL,0x7563e79970ea7ccdL,0x5fedf0a63f0e674bL } }, + /* 2 << 322 */ + { { 0xa7f8501488d7b3fbL,0x3b5ec513ec78386eL,0xc6586b8a2ad5053dL, + 0x88c09a43fbcebe43L,0xde7f2a4a20054f16L,0x63daba80bbbb147fL }, + { 0x087e48f37d352b55L,0x997e32a08317ab79L,0x8ae802ff7f27cac7L, + 0xb01a131c37b1f6e1L,0x3f0d4c2e9a6d1deaL,0xe06114fce7ceef80L } }, + /* 3 << 322 */ + { { 0x311df84c359590bfL,0xf907d69ddf6ca4b4L,0x876fd36782f22c64L, + 0x64c4d14d9713e68cL,0xd431858d6b07f539L,0x39dfea3384990283L }, + { 0x6afb8cf080cf6498L,0x327056bcde060e9eL,0x5103ce4a49a71086L, + 0xfc94be75cdf853abL,0x2bfb105f8ca579cdL,0x02d19c3a50454b41L } }, + /* 4 << 322 */ + { { 0xaa03b474cde121c7L,0x74a648cb55e52c76L,0xb286ef86f37b57bcL, + 0x95b797eb2a6371d2L,0xa489ef894077ccbdL,0xf46ade048e99ca6dL }, + { 0x5cf9e23723242d03L,0x33c7d32acb708390L,0x329523b6ba7ba477L, + 0xd406ab8757de30bfL,0xaa10e4a21536ca01L,0xdcec94f4dfa7aac5L } }, + /* 5 << 322 */ + { { 0xb5839fa424700097L,0x82fe2251759eb8beL,0xec5f34bd5f104a39L, + 0x7f3da509ed1cf49eL,0x62fe425244621c76L,0x2118b68dc7bba926L }, + { 0xb0ac18009ea4b7e7L,0x33b21ca1fcc83f56L,0x1856161208458096L, + 0xba0e6aa95650f3feL,0x918d427231006f05L,0x955f3951b1066473L } }, + /* 6 << 322 */ + { { 0x0cb41ada3c59ee1fL,0x38b2465861d1633dL,0xde863b47d03e9452L, + 0x2bfab5b41548d45bL,0x580af6272ccb7528L,0x6744c7cb13c04327L }, + { 0x5eca3ab339cc5075L,0x51dbfc7b6d243f62L,0xd64d84b7981ee3ceL, + 0xf639a03db4f2bc63L,0x8a411c36a317a1b6L,0x51edc4c0ed34eb3aL } }, + /* 7 << 322 */ + { { 0x01511b8a9d6fce5eL,0xb5c7b33f89a2875cL,0xa88e720e2fd79b67L, + 0x5337034404229e94L,0x40bb7e7ec94af25cL,0xc11501b99183a7b3L }, + { 0x29a4d81fcec3cc7bL,0x143976fdd75b8febL,0xac8dad2cfa261ad0L, + 0xb14793006a2db8a8L,0xd4981293929c4a12L,0x5703506fb6eef856L } }, + /* 8 << 322 */ + { { 0x762a5eec1f5a9609L,0xfe4f5f6a765b337fL,0x0fd534aeaa4f964aL, + 0xcf46648ed6526f01L,0xbc62a54a18d71d72L,0x48d94f2a4f8488eaL }, + { 0x62c40de7a0c72a86L,0xd73ac51a725dd2efL,0x3a51d7466ab19096L, + 0xf07bea4b2dd1ad3dL,0x2a0ec4672ef88078L,0x92598cb3664e435dL } }, + /* 9 << 322 */ + { { 0xd49f753012fbc44aL,0x769a4fc941c51d91L,0xeb1ed485981fd6a9L, + 0x90a4b3cad7daf430L,0x4bbffd5c75d07405L,0xd998a096da671888L }, + { 0x0514ad4b6e10976cL,0x5d40328aab11d9ecL,0x86de976bfa180702L, + 0x259ca429f6f8a4b7L,0xe08970f05772eb4fL,0xca428fa1b5feb7a7L } }, + /* 10 << 322 */ + { { 0x9f3d76ae35af4a88L,0x0b92f48a242af3e6L,0xd4f8a37b7165d261L, + 0x30e1fa8b2b917832L,0xd26f821f8fdfc06aL,0x75359bcf3669d1a2L }, + { 0x0ba3bcebb638331aL,0x8d02c0996c73b62bL,0x2a8c078d8c4f63a5L, + 0x55458ccaa312c282L,0x901ea0ea5eaaad9dL,0x03665da20e39eba1L } }, + /* 11 << 322 */ + { { 0x79a30b82da9affceL,0xafb188567204a29dL,0x2e64e6105a8ed24aL, + 0x6bf3695a9e44aa24L,0xc22320690c77fa6cL,0x20b3c69531524429L }, + { 0x91e60caad6e0f847L,0xf0fa30c4542d6b57L,0x56a3a66bff98ceffL, + 0xec44f0b72c9507a2L,0x4ef13008c37e17e4L,0xc819ae81cda21355L } }, + /* 12 << 322 */ + { { 0x17c563be1cac0b58L,0x889cfcecb8491347L,0x591d49ac4cd1bfc0L, + 0xd4465510d4e53d3bL,0xca95ccf6ad079a6eL,0xce391389b5ea6eb4L }, + { 0x600ccc9ca48b6447L,0x20d0c7dbc20d56a8L,0x5f27edc569c6c6e7L, + 0xb3fc0f4a586abcdcL,0xdbfdf3f985dbc5b6L,0xfba1cf254ea80fe0L } }, + /* 13 << 322 */ + { { 0x38d6267e427a9075L,0xd1df12006d63ea4cL,0x9887a99881407b57L, + 0x41accae4688e9f0eL,0x33c63c9e10886dc3L,0xf8332ac57574a033L }, + { 0x7d77d41f4c636d00L,0xf6f4ca28add70d4bL,0xbe496330c0ee111dL, + 0xa4de7670b74bc69dL,0x683a93d369e5eabdL,0x4c5461c710963bd5L } }, + /* 14 << 322 */ + { { 0x9bbc99b59310424cL,0x6f4bce534568e290L,0x21373f5bc1572fd6L, + 0xe5ecd5b6a28b4394L,0xd56968f646ef7bacL,0xcbce8614726cc043L }, + { 0xb2fa6101d0a49bd8L,0x65eaa7725a7b41c3L,0x10d7515296e5ae18L, + 0xec8f4639af389838L,0xac660d81bccaff25L,0x3c546ba931734025L } }, + /* 15 << 322 */ + { { 0x81b13d3ee098c584L,0xf8eb4e41fa3460caL,0x1bb889d1f0b905e3L, + 0xd158ebe939a3faafL,0x7ad0f829cf09735eL,0xc89611963aa8b3beL }, + { 0x522327781be516cbL,0x9118d851ee88d911L,0x35ad130f0bf2a62cL, + 0xf35bcf1b39c05087L,0x73b992c3bce42949L,0x93ce50b95b42744dL } }, + /* 16 << 322 */ + { { 0xee6e7006b515fff5L,0xaedf6e3913258ed5L,0x373adf7dfc45111bL, + 0x0c7535b1875c23c8L,0x2a7e04f897039d49L,0xd76787ae9afd1a06L }, + { 0x049dd38591b6dc89L,0x8f0c8ad0932dab78L,0xdce057b9925498c2L, + 0x7b9c9bd2da25daa3L,0x6d0b70a3d4decb7dL,0x099a218303df76efL } }, + /* 17 << 322 */ + { { 0xbfaf4b848c5520a2L,0x36fa343fc6741e50L,0xadcc36dcbd5211c4L, + 0x2cae5a8514bf0578L,0x8fee4d403fe4171eL,0x2acd2756624d0daeL }, + { 0xaf99a323623aa9cbL,0x120cd2038c8191e2L,0x2073e8884068d993L, + 0x144851ac579bbf88L,0x54d458a4ee29fa34L,0xb7704255e5e5d676L } }, + /* 18 << 322 */ + { { 0x02f6e396617dc4bdL,0xbc48c42961497feeL,0xb27487fe0b4d22d7L, + 0x33d6b1161d0b0aabL,0x5e21cebad31278e5L,0xf7119a50dacd8f27L }, + { 0xe47eff2cc8ab54acL,0x7c7ccd3bbbe16c9cL,0xc056d817c584bafcL, + 0x868ead2b97790d9cL,0x8fea6eea1a58126aL,0x67d323640fab2640L } }, + /* 19 << 322 */ + { { 0xee1a958ffa14b58eL,0x900644f9760b54e3L,0x97fa6fa451579d09L, + 0xa7351c3b26e7f95aL,0xc3546595aadfd139L,0x07b7ef48f14f1e6dL }, + { 0xc8d100ec4d139608L,0xf98609b2d8741228L,0xf0890d9d33030d3eL, + 0x893b874fe28ed106L,0x5439b7aff7bb558aL,0xe68a3adba71a2261L } }, + /* 20 << 322 */ + { { 0xff54e8bc8acd597bL,0xdae781e94682b8c6L,0xb2265bc4ed1fae2dL, + 0xa5e23c29ea983db1L,0x4af5f55909851454L,0xffe9538836eb4506L }, + { 0x4c72b2d1c2247b8fL,0xb179573331a67505L,0xb1aa8ad4e19c9c25L, + 0xb9cfea953e8b8004L,0x07782d788ac747fdL,0xe23e547fce9d9e41L } }, + /* 21 << 322 */ + { { 0xbc6b0088fd9e8e72L,0x7e51aa5dc6453462L,0xe8615fb9c8b1725bL, + 0x031f0d2a5a371c9bL,0xb9db0a647441d8aeL,0x0dd0446e9d5783c5L }, + { 0xb3b7be2381720779L,0x49a8ecbb6cc5a610L,0x165c626152cd016cL, + 0x5fcd657da3f6ae6aL,0x30497fbc9f6988dbL,0xd734927936a73fe7L } }, + /* 22 << 322 */ + { { 0xb30ddd0e388562b4L,0xc485506b1f61067fL,0xf0da517684947c84L, + 0x04830cedeb067f33L,0x05084c8262404b76L,0xe7e7efad7996707cL }, + { 0xc2a6a57fc78b9a7eL,0x4e55fd8c7bfbf308L,0x204e7c44d1386117L, + 0x979ecd5a4e56595eL,0x3bfc790853707b85L,0x2c3a41c59fcc5b7aL } }, + /* 23 << 322 */ + { { 0xcdbfd951ed6e2671L,0xb72c42ee135f6b96L,0x38c8d1ca40bbb789L, + 0xf6fa984cda03f270L,0x76dc5a19ed88deb9L,0xa8c88f2a9985bcd7L }, + { 0x2b0d3b66c6628a44L,0xdf679b6a2b311954L,0x30a363c25f851b07L, + 0x78a5d242aecdb9cdL,0x42d7ca82a968b4e6L,0xb188e99af2efb94fL } }, + /* 24 << 322 */ + { { 0x779905b6d8948f95L,0x3c7085b591cd0206L,0xce9af0aa679096dbL, + 0xfdf04f10f558913cL,0x05300cb06f24a2e2L,0xf9d9a2f25d581b35L }, + { 0x855c8de96a713751L,0xc9ac24bc0e0c0dfbL,0x67612a4197740d65L, + 0x7588a52744c9360dL,0x928ac910325cc880L,0xa74abdafacdd3188L } }, + /* 25 << 322 */ + { { 0x98d80359e7c5fbc7L,0x6abc82b7047c61d5L,0x8d8f5fbd58f2fd49L, + 0x321f2426ccb0a4dfL,0x379f10e2e96cac24L,0x34c0444130666763L }, + { 0x8dd3972043632c61L,0xb2bbe2eec19f98eeL,0x00d5a467c464dfa3L, + 0xa44ceb19a85b6fecL,0x88bf80ddc9b1fa77L,0x7e5123c8e6dda98fL } }, + /* 26 << 322 */ + { { 0xf73ad540b75a6b88L,0x57bcf1cc08487cc1L,0x00358de735cd0c27L, + 0x86d469a2573df808L,0x4884cd5684716abfL,0x0157687fa7da61d7L }, + { 0x8efd8acda732c2cfL,0xb6c9bf7198677236L,0x3d1f01826d46c473L, + 0xafa65fd82f497476L,0x535ee757e54f17daL,0x432b5878fe7aaef6L } }, + /* 27 << 322 */ + { { 0xf091c4ff3370e118L,0xabf011ee118d4b8eL,0xb489c4b7a13c7279L, + 0xc2dd44e93bfb19feL,0x10b68e92c5d859dcL,0x57935fc39249205eL }, + { 0xb97e63b06c929bf4L,0x98cb08a739a25097L,0xb13f17c15eeedf15L, + 0x1e27a85c240884feL,0xda1515ad9b601298L,0xe01251fd4ce36c3eL } }, + /* 28 << 322 */ + { { 0x3774af36ba6aca8aL,0x562fcfb1340e6a03L,0xde45205ec1187539L, + 0xf3b114418799c22eL,0xfd53f681e8b0842eL,0x45a0039066d36d64L }, + { 0xa2c3391d353eb1e7L,0xf9d9fcc55840eddaL,0x4df1fa4a6ab8ab4aL, + 0x2b0cd34bd841a623L,0x52441d79b10b189aL,0xfd86d3c2fa025da7L } }, + /* 29 << 322 */ + { { 0xe28f3bab5872204bL,0x6f87cbaf0ba35c66L,0x783e85c03d877c60L, + 0x376e5e2df132df52L,0x213d53a9bc2cd6faL,0x2e2a573008a13174L }, + { 0xc0988fa9ba15290fL,0x51d81b9485456f81L,0xfe371f32a0ef5b80L, + 0x9aca060ff129171bL,0x0b02b39e0e402e65L,0x8e6bce1eae9c209cL } }, + /* 30 << 322 */ + { { 0xb0cb0f0c532f78c8L,0x83113e752d133635L,0x3f64aad5123dc64bL, + 0x4d3201c85aee8c59L,0x265905dbe75e8642L,0x9d1d277805f9a759L }, + { 0x84778aead9e2a07eL,0xc747cc3a9c0aed31L,0x10d1b4e87af2dc61L, + 0xf58a6bd8af0bf23cL,0x83836c2352e1ee75L,0x88c4d1c6d899062dL } }, + /* 31 << 322 */ + { { 0x27eb26a3f3842d98L,0x90f712b69da68159L,0xd11177052676f05bL, + 0xdf603446073bf994L,0x28ad2b498bfcbb7cL,0x6916c6e2e5e1266cL }, + { 0x37d516996e98d62bL,0x155d8ef749634968L,0x0676ea286a1b2222L, + 0x1dc3f8d71566cb3bL,0x95fb3f177dc6aecbL,0x092f4c8120807b13L } }, + /* 32 << 322 */ + { { 0x3c6c5618b9d926c2L,0x7e14c3ae4a9099f9L,0xb3259c90ae2fb830L, + 0xf7cc6e43ec31a504L,0x83bb13c6126230bdL,0x5a1f4313ff1dae3aL }, + { 0x0cc6c1a549b0b65bL,0x67fa836a274a84c2L,0xd454c75fe604a58dL, + 0xceadfd912491f872L,0x6c5575da9ce116a5L,0xfaa4903fb24a4481L } }, + /* 33 << 322 */ + { { 0xc9ade1497c4579f8L,0xdad7eff3be316db0L,0x4ff3abc613fce23dL, + 0x09103a75da708e56L,0x4cf139fa8ab52827L,0x0f82219b8f251a68L }, + { 0xd19719c7dea33388L,0xa482548423085413L,0xbb63cb43f8eb4b18L, + 0xeec33735f3b88079L,0xee79d331de3ddb97L,0x56fc93090e5acf8aL } }, + /* 34 << 322 */ + { { 0x951a780bcef9c5bbL,0xc37d442ddb35bf11L,0x8e2a0e7d64a776b0L, + 0xbf461becc652cf34L,0x3970eb603194f918L,0x2768daedb3bda869L }, + { 0x8e81257557b24bf2L,0xae05e2db38dd69cbL,0x0adab288cee2f522L, + 0xc7a0e1f148234f13L,0x285f6ee36728c9e9L,0xb9ae7b9fc4541e19L } }, + /* 35 << 322 */ + { { 0xfd90c5c1f6422b56L,0xd9fc8cce4dfdb947L,0xf3566dc4d088588eL, + 0x25dd9e27f22682e6L,0xb077392119b0a532L,0x54da228c0d05a9f9L }, + { 0x0f7fda40986f60d4L,0xb6dafff6c9b112feL,0x7eb99e1a4abfdfcaL, + 0xed499eb9389611caL,0xf230d6d6f251477bL,0xc09d328c227ecc92L } }, + /* 36 << 322 */ + { { 0x9b21ef6c16cdcfeaL,0x233be0c3694edecfL,0x110243df7c49c931L, + 0x03a59a2ea3113ed1L,0x6470f721023c9a77L,0x7d1640c88e9ff099L }, + { 0xc21488316f2c7b37L,0x9e1c9e1dac6eebc7L,0x6af65a671109ca9cL, + 0x8379fdd9cc6f80d9L,0x33f74ade7e666a4fL,0x07ac728b7be081a5L } }, + /* 37 << 322 */ + { { 0xa3df31a312354705L,0xffc8fdfc1aec1bd7L,0xd9dd39c112cc342cL, + 0x8077a57e37bf43fcL,0x0f037ce49cb8751eL,0x5740f6b5b805b530L }, + { 0xd26422704e2b5b93L,0x114bb1f02dc158efL,0x71881767a9bec3d1L, + 0x1174386d266d95cfL,0xa373d7ea7cdd4461L,0xaf4f7b40d814a33eL } }, + /* 38 << 322 */ + { { 0x0db94a18f79761beL,0x263e2acb5717b98cL,0x78c28d8182567b0eL, + 0xce1b366b893c35b4L,0x1e20b1bc0d6907a7L,0xd6f123474b973588L }, + { 0xfb945471f717e91bL,0xef85653cb027bd4dL,0x048e9e1df07dc0e1L, + 0xc494aa9cc163b83dL,0xfaec72d3021b4fa5L,0x5c63c30fc9869fe6L } }, + /* 39 << 322 */ + { { 0x2dfa058d510d8d86L,0x772fad416a89aa0cL,0xdf55d15cd586f23dL, + 0x7d96b7a989b604f6L,0x352fe049a38d821bL,0xfc56b8df4fbb5795L }, + { 0x264122b4b3d5dd0bL,0x89317f4a980177d9L,0xc060ab4a13e2aeecL, + 0xc2676725e2cafc87L,0x78863cf45eb1df3cL,0x2e1572dc0ab1a715L } }, + /* 40 << 322 */ + { { 0x7a8a898d5a4703aaL,0xc59933ea1cd6f9d6L,0x703265f5d28124cdL, + 0xe1c1bee10178d1feL,0x9ff31cd4241262e9L,0x9174a939a3c9f80fL }, + { 0x0f7a3d2dbc2a62eeL,0x0454051c62f1b3acL,0x83502c9ea2421254L, + 0xb4fa51fcb684199bL,0x257e9e2bc5e36a44L,0x14efeed597d8647fL } }, + /* 41 << 322 */ + { { 0x09bddbc28f2b12baL,0x8af83a779b7f1c14L,0x88f9b4d3bcc934bbL, + 0x8d8312df8d072340L,0x2ee105bc615989dcL,0x6044fa00de3bab08L }, + { 0x98c499d603cc86ffL,0xf0b48aa7c5068033L,0xdaa536d2c96606d8L, + 0xef905aa2bc6a843eL,0xb6f108ee8ac620ecL,0x0dec7dfbb6dd66f9L } }, + /* 42 << 322 */ + { { 0xb9157d4ab0fe18a8L,0x139bbcbc68cc7a70L,0xd546a06d7dea2914L, + 0x8db142d4a01cc59aL,0x127ce2d9aa09fcdfL,0x3950a5a63bfef8deL }, + { 0xf41ef6d42527522aL,0x4b4e6f107e6fb19cL,0x2a2735d1345788c5L, + 0x87963e1ee72a7ae3L,0xb58d8934fc443360L,0x93552692b16b6f2eL } }, + /* 43 << 322 */ + { { 0x70591a849518f0c7L,0x5c282b6fc67c438fL,0xdbf61b6b100facc1L, + 0x3c5d969f2bf2a5beL,0xe1a0c6cbab980c70L,0x70f4981c680619fdL }, + { 0xc6905d7cc65be256L,0xde3340fbb5c27acdL,0x17be9d182c1b3fbcL, + 0xd584e4f96fb00b1dL,0xac5dc14eb819646fL,0xf5c3279a3242935bL } }, + /* 44 << 322 */ + { { 0xfdb13b31be970ebaL,0x119b1c08b0bfadc2L,0xed62f35e21875542L, + 0x73c8f9b0349a6d12L,0x8c35d8f8bd1622c0L,0x501b9d288b6521a0L }, + { 0x377f8fa1c918b2d5L,0xe2a9580cd0239ef9L,0xee24f4f0371d7bebL, + 0x4cc697a669231b47L,0xa55193c8dc4c5a07L,0xd4e51e1db0ab8507L } }, + /* 45 << 322 */ + { { 0xcb811c27265f267fL,0xb85593aa9e2688f4L,0x57a1969dd76bf364L, + 0xc29946c9014483a2L,0x5bdd72490915bddeL,0xba6d13ff22746ae4L }, + { 0x524121e0d25f6b7bL,0x9011309e0d68a3f9L,0xf25e89ccdb91c66cL, + 0xae79cad781df593aL,0xef8c6bec4f103231L,0x832659c3e038f02eL } }, + /* 46 << 322 */ + { { 0xd58eeece37761959L,0xba6d8ab5b328f084L,0x3911e6ae324a6706L, + 0x299921c8ad139296L,0xb81a3fe4f6b8d9e1L,0x2680c46f5ef06a6cL }, + { 0xab9cdf368611d63cL,0x6c9fa5b3cc0a5da8L,0x712356a3da4d4412L, + 0xc1707a10cd3f550dL,0x5c25b2f3ce468303L,0xe4be20bffa546b6aL } }, + /* 47 << 322 */ + { { 0x797a2919515ee1dfL,0x65dd5991119dc9d3L,0x82e8201b41e4c5ffL, + 0xd27b35130d3dd45aL,0x9ba590c5b13b2dd7L,0x0f15b35282992935L }, + { 0xef39971e227e4e46L,0xb74c524b2786fd6dL,0xe09c28ec71b1579eL, + 0x0d1418e285f6a935L,0x173265448719fbe7L,0xfe3b1d831200b35dL } }, + /* 48 << 322 */ + { { 0x6e96a8195cecb21fL,0x3a58d8b2d8beecaeL,0x93c3cbb0c0c715a8L, + 0xfb06f977541759b7L,0xf25ba095771c3d2cL,0x7560446ea3bfd322L }, + { 0x7cd99f35a015cb4fL,0xa0e541960786f235L,0x0f868f768b8e291aL, + 0xc8260b0b2f95050bL,0xaf38376ef4c0a462L,0x2b3c0f3b98a3395dL } }, + /* 49 << 322 */ + { { 0x99d4529efed6a724L,0xc6f1b084071d8d31L,0x6c48062ba097da1fL, + 0x1dd10493301c1d74L,0x5288f194f554cbccL,0x77b1b81f39dd42c7L }, + { 0xeb1f2d53a007a6d8L,0x43bed54e05648d75L,0x1a85326f29801a1eL, + 0xcb9a91a4f564d78aL,0x4f38fc7893f071deL,0x920117d8aeeeb5adL } }, + /* 50 << 322 */ + { { 0x709b5904b35cba78L,0xef0c321021b11d3dL,0x38f07eec46844b18L, + 0x2e79f99934870a55L,0x9e9df80400d7b924L,0x857a95625cafba4bL }, + { 0xef8ab68f4adfea6fL,0x4a83bfc16ea764e1L,0x21f4c75475e8d874L, + 0xa3597f526ecdf5d1L,0x9d3a4766eff2e1e6L,0x9872db39e5e6ae81L } }, + /* 51 << 322 */ + { { 0x42d9f39e99bb9a10L,0xe617263ce35e4852L,0xb3f8ace1a06b71d0L, + 0x861520de6419d9d1L,0xc2c521cf37b1fe38L,0xd537001b9edf9936L }, + { 0x92614b9f39af94e7L,0xd2003f2e25286664L,0x249d04aeb836d4b1L, + 0x3c6c192ab26df88cL,0x6e0b25442c72ec0eL,0x69d7f6d7497f03dcL } }, + /* 52 << 322 */ + { { 0xbb5a95f6293cc00fL,0xb202a82a65fb729eL,0x819c26aa12e35774L, + 0x70cd5237c2b3f0b2L,0xa752224a89b2c5ccL,0x71c09cbd0ec89df5L }, + { 0xb849e352bab45d24L,0x290f0307d313f461L,0xf083031cee885e9dL, + 0xdf42a973a60bf2faL,0xe39f2118d4842999L,0x8b54cf1d0508febeL } }, + /* 53 << 322 */ + { { 0x8942b4df0d846a3cL,0x18db708662b6605cL,0x6549e019fafa6508L, + 0x85d97fce43ef9443L,0xe9f13da373485de4L,0x5743297bb0f46e8dL }, + { 0xc52781bb70908255L,0xcd88a48a6bc6e666L,0xf857caa5eb4f54d1L, + 0x32dc925320974dfaL,0x6dc79fad965146e6L,0x24e3a8d2edc1f747L } }, + /* 54 << 322 */ + { { 0x1993fa650e81671fL,0xc6acd9f3dd1a1e4fL,0x227edd1a7bf36f1cL, + 0x4ad2478370867ca3L,0xed0254f758b9a7c2L,0x63fe279a7013a5a4L }, + { 0xa65787ee232e6a88L,0x5faceda487161d5cL,0x36e351b603d64c37L, + 0xaa265f1de9e30871L,0xbf3432f521e6f66bL,0x69d68c068621289dL } }, + /* 55 << 322 */ + { { 0xd2bd143ea0807eeaL,0x474ad99582568efeL,0x0fcd6bba7d482c5fL, + 0xf83e6f15e2628f4eL,0x314508252210e41cL,0x8f0a9402f47de776L }, + { 0x7f20bc562ee4d1e0L,0xed4157de791aa7a7L,0xbe443399be2dee9aL, + 0xb461643371625f13L,0x1be21ba8771f55c6L,0x04b3035a300fc187L } }, + /* 56 << 322 */ + { { 0x0952b888b9d0bdf0L,0x3973763c8ce32fb7L,0x221f0ba56dd860c7L, + 0xbb7a27feb16ac501L,0xf113b194bc8fe58fL,0x18f3297a65839ffbL }, + { 0xa2d4eb7c8dc30003L,0x3fb4b4878e334479L,0xa4f32c651a8310e3L, + 0x944cd644f78f46acL,0x14e40c4af96fb91fL,0xc31402bd4ddf6e72L } }, + /* 57 << 322 */ + { { 0x9eb2c9e51ff0ab88L,0x0a29fc0695cc3436L,0x3f4b4ebdbd298127L, + 0xeb8ad8b52ef56848L,0x6159700f5b211ff6L,0x8fb98f2fc3a67bc0L }, + { 0x5c5998ffbd195b66L,0xea99d6767e44a64bL,0x314316e4bafd1471L, + 0xb5f48757cc8c0e77L,0x922a91d15b259ac8L,0x2458279cf9fc4e4eL } }, + /* 58 << 322 */ + { { 0x945c5a3c6aac3e97L,0x5cbdfad9a266ad50L,0xa3e38114fe59f5ceL, + 0x1ca1cfdace3ae206L,0xbe1f15e12a84cfdcL,0x682514726a12ec3fL }, + { 0x48409f871f57341aL,0x632c369e8461bf7fL,0x1c96fc87d8865ed4L, + 0x1727934ae1ffc51aL,0xa60f0ebb6d71f51dL,0xb6c354052e411888L } }, + /* 59 << 322 */ + { { 0xc7b3d3bb72a77726L,0x04b9bdfbbdb03d78L,0xdbdbaa7e2fe88db4L, + 0xc5848e58564710b6L,0x7bbd84863ec55713L,0x1b5aea5670183191L }, + { 0x95d91bb25340d9b7L,0x9a1462e4187a3252L,0x5cee9b8cec352fedL, + 0x7db8350137049284L,0xa1d2822cd3b714f3L,0xe4cf6d53c2e51da6L } }, + /* 60 << 322 */ + { { 0xdb2a2ac9a63f6f62L,0x4c0d2da695f20639L,0xa485a6adb475e177L, + 0xf6dad8b5aa93055fL,0xafcc1e954974bc52L,0x6686940224fcf32fL }, + { 0x10c138bfc103b013L,0xe74ea82bc6faba1bL,0xddb399c581824de5L, + 0xae797b70cdaad079L,0xc648e7ad6ea955e2L,0xd07c5c919be79db6L } }, + /* 61 << 322 */ + { { 0xf4b7a33b39d93befL,0x4be176f9659da9f0L,0xbf57d975f36642cdL, + 0xe10b452d16d5528cL,0x7c062421a6bdd74bL,0xc093e346e7aa1d9eL }, + { 0xb7cc38cc2f5c19ddL,0x9fc7f69b230c8790L,0x9b667acd5e3c5282L, + 0x1cade31144cd22ebL,0x53a0d702bb43a1e4L,0xb25868777906519eL } }, + /* 62 << 322 */ + { { 0x46e2415deb5003acL,0x05aee8855e8a6a0aL,0xbda9f162bbaf343dL, + 0x658b350b21853341L,0xaf6b4948ced47246L,0x1d454740723cd3bfL }, + { 0xc4b7ce3fe1aaef54L,0x619420daa35c9e24L,0x65d455b14eb7a52cL, + 0x2f9b700a4c961515L,0xa5b7b962d3aed448L,0x4e32a6d937851d3fL } }, + /* 63 << 322 */ + { { 0x2c4c1b2ed00f8cb9L,0xbf83ba500fd305aeL,0xb75bcf9f801a8e64L, + 0xd8ab465ccba76b29L,0xf5a2bcd74ea718f4L,0x81501d563b592ae0L }, + { 0x9734e4e26ae6bac5L,0xc4860b0eee304e5eL,0x8bd59b7b1d59f1acL, + 0x7c9497e8e799594dL,0x4bc6634c08292918L,0xc45583aa92619229L } }, + /* 64 << 322 */ + { { 0xc5ad791eb45a8002L,0x4a23fd68ba2d7a40L,0x673b9e4998544bc4L, + 0x934d8f55d273c360L,0x7fb48d0768a75a8cL,0x2e6201055e0fac97L }, + { 0xbe01655ff10ed580L,0xd21d52ae9e96731fL,0x74f830de53325138L, + 0xa7240331de9f3fc5L,0x96b25206a7e01fa5L,0x3fcfedee07eda4b4L } }, + /* 0 << 329 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 329 */ + { { 0x3e6e93818d5c039fL,0x809494228a8d2cc9L,0xf2d7c8b4b843ec06L, + 0x0055d882af8a23f1L,0xe848010ed3792335L,0x9b41a55f55e08e74L }, + { 0x956ea8e95de83059L,0xf159a9973263678eL,0x5f7b9271cca1b548L, + 0xd41d2281f1d0b7f1L,0xb187047b5c9963fbL,0x213ff6af02536cd8L } }, + /* 2 << 329 */ + { { 0xe51a95700d0fa76cL,0x67c7890e4d2e9c8eL,0xc6160fa2f974d2cbL, + 0xe00474f74c6a78deL,0xee916e510ac89d11L,0x1adad97af826f133L }, + { 0x3fc65d3f8d2d77f3L,0xda9420750ba6c300L,0x5237a82e0b9196b1L, + 0x4975e680a572b6f5L,0x41ea8b92b9bed2bcL,0xbe0ad7109826825eL } }, + /* 3 << 329 */ + { { 0x06f721d30a9ec81fL,0xf0359222034f3e78L,0xc5ca6b7a5a44ffd9L, + 0xc53e328915764390L,0x7f16917459747d7dL,0xc3a9981461f79122L }, + { 0x099f4e3a97aa46f7L,0xcb0570c9d70458a6L,0x270a43576b72f327L, + 0x9d6bb26cc33695bdL,0x60f9202126224902L,0x8eb0e108e1b0a51fL } }, + /* 4 << 329 */ + { { 0x8a390dca9fcaba39L,0x3879f0b4278d22b3L,0x77bbea69bc5e82f1L, + 0x71f02e2d4628d6f1L,0x6260790cf968e240L,0x1c7f3df5665270eeL }, + { 0x336395451a87b1c8L,0x2011fd214ffd9fb8L,0x69060f867807ed55L, + 0x1b0ac0119dfa452cL,0xbbdb25fe06d27c0dL,0x5c25d23aa60ef90cL } }, + /* 5 << 329 */ + { { 0xc08dc153d9f75d6bL,0x5c1f07e7a0330237L,0xb3e6fb677d67a5c9L, + 0xca949ed098f9faddL,0x48b16b2dd7720835L,0xfdb1b735fee4d341L }, + { 0x1a6b37b1debf3207L,0x5b3eeb1e3218c63aL,0xc19b57b504c23b30L, + 0x178bd3bb40669e2dL,0x74e57b26fb6b162cL,0xc3626931a0932b58L } }, + /* 6 << 329 */ + { { 0xd3eb69e4734b2e9cL,0x1c2754e2c35ff1b3L,0xa26681e69f3e8c51L, + 0x7892ad11a2cae737L,0x88b1da43cbd8bda6L,0x8a576942419d21c4L }, + { 0x7c124343c90f4545L,0xa5a8d93b26453baeL,0x9a4c08fd76ae72e8L, + 0xa08b82d97b064e94L,0x4f803ba083725330L,0x33672455865235f3L } }, + /* 7 << 329 */ + { { 0xf7a5e2f0a51e695fL,0x3099bf9484adf10bL,0xb2a03c0f22a3ff04L, + 0x30303a910acec674L,0xaccb2f3ca59522f8L,0x00ff4d88f273ba94L }, + { 0xf0056b4210e735ebL,0x3337279a7786e93bL,0xfecc77c44bb3c31dL, + 0x3385bf5be0e26a05L,0xa9454ab85f45fcbfL,0x41a4158346edb553L } }, + /* 8 << 329 */ + { { 0x1877dfd0c8110f1fL,0xea88f59d18db27c2L,0x9d089536c78e295eL, + 0xcbb5d55374a04cc5L,0xe3666006827f75edL,0x8557b81a61e7378cL }, + { 0x74170170ed223f48L,0x84197a6ed86ee829L,0xd75a30f8ac1c4a0fL, + 0xd7e7be0d3cd92824L,0x5ea0abdb1b5e86d4L,0x41146ae1b3b615efL } }, + /* 9 << 329 */ + { { 0x6d340fd3fabd376bL,0xb5066b1ccc169cb3L,0xa4148142d20ef8f1L, + 0x0c5d66fb461544d0L,0x84c7a232d67043d2L,0x4c0e77867e609af4L }, + { 0xb1e83f1af4619e4eL,0x40fca1a0b225d174L,0x39bb3a882e42fa4dL, + 0x04dfe833d2682205L,0x49016d9d685296f8L,0x2da587198b735155L } }, + /* 10 << 329 */ + { { 0x570deceb1ae5e9daL,0x5c079c70b73ead01L,0x522a30a6d2ce6639L, + 0x71dc5c3ff4056ac9L,0xd93c7a2dbaac149fL,0x5c3298b8f1844cebL }, + { 0x282adf408c23c0dcL,0xbe4981899b646f86L,0xe77c1950628da9e5L, + 0x38cc27baa1fd5a18L,0xb5579728aacdca52L,0x8d34fdb4c8e1ecbdL } }, + /* 11 << 329 */ + { { 0x563e0b8a7a7fa597L,0x6697c375bb7dd079L,0x95758ff6c6233951L, + 0xca07993fa2059c40L,0xc3065507ce2aaefcL,0x9faed33c6ea927d5L }, + { 0x0f8b48241207247eL,0x0044f6115eb2263aL,0xd7c9ce7c851596fcL, + 0x54729d523c69d424L,0x42cbdcca45876770L,0xc1e0e6ceeff2adcbL } }, + /* 12 << 329 */ + { { 0x323f2102adea7d6aL,0x035b354eb694b253L,0x66dc4e4a5b8a36c2L, + 0xb609222471795ca4L,0xd8c6d7eed300d80fL,0xf31f258db3b94954L }, + { 0x0f2eb679277ced5bL,0x0b16efa3eba40e3fL,0x400035070dca4f36L, + 0xd34c91cb59a9a3a1L,0x5e8fea3286da6408L,0xf237959f03f31728L } }, + /* 13 << 329 */ + { { 0x1d3173653412e8d3L,0x1d14cd1b09695abbL,0x9044adf2a2cda00cL, + 0x60a6ccd60b7ba011L,0x614b100417284b46L,0xfb3d84b9cf840203L }, + { 0xd65b3566532b068dL,0xc8c03996c2465150L,0xc9035c2df71c35f4L, + 0x350231a752222e21L,0x59440020451935b1L,0xd723a55cccfdd206L } }, + /* 14 << 329 */ + { { 0x1b5bc630bbaaedc6L,0xe7d25088b49cbb3bL,0x5622cbf70deb8cf0L, + 0x3b20803cd309c3baL,0x64c2e7deff45e2fcL,0xfa730ffb9aab84a5L }, + { 0xba83cc514edfb52eL,0xe05c0140748bbd69L,0x27bbb5f52254ec43L, + 0xca740989324c8c40L,0xa21488b1d26491b4L,0xe2753a1f69d8626bL } }, + /* 15 << 329 */ + { { 0xea04908f64dab001L,0x8ea1f127b4debb2eL,0x87adb69534f155a0L, + 0x41595cfcca8afe0bL,0xffef042f8763ba08L,0xb7b4865decd3e667L }, + { 0x2c46c97070c4c8a3L,0x1ab18c080403d206L,0x08b2d3c94b3df379L, + 0xc6a4c268a87a7166L,0x449bc61f5323b1f0L,0x8d4b7ced489ada74L } }, + /* 16 << 329 */ + { { 0x618ca06b8956146cL,0xd51f1e6f552cdecfL,0x981372cca3b6ce7dL, + 0xb44a68ee5f14bb57L,0xfc1167e96373abbbL,0x3d621f8b767d4c0aL }, + { 0xc6dcdfebf6ecc778L,0xddda926282d1fbddL,0x477501aabfcbf2f7L, + 0x0be7228a67aa8277L,0x5de7b8331daab9cdL,0xb88a4f9a262feb4aL } }, + /* 17 << 329 */ + { { 0x203a666c608fea53L,0xbf71f8fde8979c08L,0x3bd58feba22a3d2cL, + 0x596bfcf521f178a1L,0x6f207d89f84beffcL,0x8a7c6dbb18097607L }, + { 0x208f5e64a1c5c927L,0xd7d0e33478dc83c3L,0x5e9397261d4e30f5L, + 0xf3877242fa09a36cL,0x68e4338ae6a7b0feL,0xcf8cd131ac47b369L } }, + /* 18 << 329 */ + { { 0x28f18586936fb33fL,0x9809b2ab381bf7bbL,0xf6e16931eac3c252L, + 0x366d18335e151187L,0xe5b4c2357a3b6460L,0x693a9fa50a68bc91L }, + { 0xa35f104a6a7f8b6eL,0x3e5d6981688676c4L,0xc0c081b10651a609L, + 0x6df5da2dd77057c9L,0x8bb271bbc4602847L,0x322547b3c4bd07d8L } }, + /* 19 << 329 */ + { { 0x9b56b9444deb8158L,0x5f4b15a6da5eb70fL,0x120afa9514cb0126L, + 0x01f6d00d6bdd0d78L,0x73dd7c5c463b1ce6L,0xc770cf35df00a133L }, + { 0xb5db93a1247ff879L,0x1c12f3f0c70ecea1L,0x10168c4e5b59cc9cL, + 0x1e9e0f8a0e19efe5L,0x43987dc1cfd44b62L,0xb1d265c204814e2dL } }, + /* 20 << 329 */ + { { 0x8c283529233d39e4L,0x96300796c6092096L,0x2c549de55dde766cL, + 0x27e0b444b4151002L,0x802e5fc3f2f88f1bL,0x2af579c28ba1956dL }, + { 0x52edd04ed68196c7L,0x2e22e71474a202b0L,0x338948248bf66459L, + 0x8f0d8c259e39df55L,0xee4f109e6c5276d9L,0xc0c893f0c5dc0bf0L } }, + /* 21 << 329 */ + { { 0xa3081bc75b3f17e5L,0x299e7a0222e46b9dL,0x36184c98a9afa278L, + 0xee2043319095a8a1L,0xf5e54622cd5ac080L,0x08d649013fa844a4L }, + { 0xb20ddfc6d7fbb42bL,0x15130bdbd868a81eL,0x25e5fd2f32ff1a03L, + 0x907e3c01ca5288d3L,0x2f2f7496a1f6f96cL,0x831feefd38ab83d9L } }, + /* 22 << 329 */ + { { 0x06054c76f8482849L,0xc24b4a6a5fcca65dL,0x71c27e01a17ebda3L, + 0x1ffce0281be9dfb8L,0x3784c950ebc43854L,0xcf0ecc2dd5086510L }, + { 0x86d0fc3cbe24d8ebL,0x5bad01911f21788eL,0xe2c3bcb9c49b3a12L, + 0x66f82433f7d5992dL,0xf7cc5eb913969246L,0xe52defd48660a6daL } }, + /* 23 << 329 */ + { { 0xd6d6a42b102490deL,0x9e6532acf40d27d7L,0xcd1591cdf2a08bbeL, + 0x973e09f234eb47ccL,0xb3a5915add4fa316L,0xb36ca6ceac38218dL }, + { 0x73d370b3e58a0cafL,0xbc8fd39f07766be2L,0x3d5d9ef7c2ea7997L, + 0x22877500bbfcc1a7L,0xc54d0c6406e0547aL,0xf7bc1d2d564e9ef1L } }, + /* 24 << 329 */ + { { 0x7a9623b653fd1a04L,0x13bd35bf3a3b8500L,0xf8a5dec9e0f8e530L, + 0x88bcbe291d65dcd4L,0x09fe38036739541cL,0xebd04b7fe716a97aL }, + { 0xbd8e34df1e5ef7cbL,0xddfc4243d7c4fd6cL,0x0183d9053519411fL, + 0x63450996f7a3c483L,0x18283cea01355739L,0x8c1d72cf9aaa72f7L } }, + /* 25 << 329 */ + { { 0xffcd4b6f9be9ff57L,0x0bff01bb939327efL,0xde596626b5ed90e3L, + 0xc07464ff4379e17cL,0xefd3e2c470d31340L,0x78b2192f4e7df61bL }, + { 0x7cfe28def3faf2fcL,0xd2d1a994dd642f87L,0xa5d4fb1410b3377eL, + 0x2cb4978ead6fa00aL,0x5b6fe7a765fb3688L,0xc26c1b3336d5acdeL } }, + /* 26 << 329 */ + { { 0x551e1b4e8dc72468L,0x8a926cb2a7b2f1acL,0xb873e83b0fd12fadL, + 0xb6cde14fa4e7fb13L,0x81ae41415befc256L,0xffb0c636b4c7631cL }, + { 0x80f1408f8a2478feL,0xde6d051d44fa7605L,0x5a15b1f84d44a1e4L, + 0x1a0031c5a0daafe3L,0x304338dd597652a7L,0x6830dcc7f257f17aL } }, + /* 27 << 329 */ + { { 0x62fae4072fdc8ea4L,0xff77522fcbe76ee3L,0x5fa03a454fd2bae6L, + 0x774c635e8dc90431L,0x718081b62ddc4376L,0xf4901a2c03e7aec7L }, + { 0x5339a3109eb023d7L,0x15dd4f96366e35f7L,0x1f802d4a0e2d2e95L, + 0x8e5e9cb2fe1b1226L,0x175806f623a0de5cL,0x115a97db068c7bbdL } }, + /* 28 << 329 */ + { { 0x4a67ec76193aabbcL,0x3da6dec6d74761f9L,0x751720c90b35bb70L, + 0xe5e049058d9e0f8bL,0x3cd37c840858f29cL,0x7ff1abfbb881733eL }, + { 0xa0c2698b0c4f7694L,0xc736419296b95e4eL,0xcfa55c5537ece651L, + 0xa2bbd6ae7cb1e9e1L,0xcd2292b9a0eb0e8aL,0x8aba99e18d5030d0L } }, + /* 29 << 329 */ + { { 0xa3f508a498fa3d8cL,0x4d894cbf45bcff40L,0xbcdac17d0c095cc4L, + 0x397caa6f407c2ed8L,0x2195056b5f97b4a9L,0x41eb6e0e97434508L }, + { 0xbb5e4e4a73f211f8L,0x5e8e638f720a451cL,0x8470bc9e4974252dL, + 0xc487aae29f6a9a96L,0xaa66417101165deaL,0xc8af7172b603771bL } }, + /* 30 << 329 */ + { { 0xb7c74c58dc4a1d3eL,0xe3ec30160331ea39L,0x83afb271023c8712L, + 0xc2670d56c9c82680L,0xd426f350feca1061L,0xe8aee692ba6edc01L }, + { 0xc916fbe546e801d9L,0xcb001c377097286eL,0xfcf79d2678ee1328L, + 0xb05b0634b6a4afb3L,0x2ab327bb306da14fL,0xc11a0294ba5ff534L } }, + /* 31 << 329 */ + { { 0xcaa287c30f00dfcaL,0x9ca672930601cc7eL,0x435e883fb105d00fL, + 0xf9cddbf91238536aL,0xda604ccb45f558c3L,0x7e51d9d182f48366L }, + { 0xc1e8d50d7e8396c3L,0x58638b85edbb75e3L,0xe926aabe9b088d2eL, + 0x8103a34a428c41e3L,0x03e5e35d089deeedL,0x64969c6d93bb0b99L } }, + /* 32 << 329 */ + { { 0x7b7da028e19763ddL,0x662f54df8b98ff78L,0xc056d83c51f3dbd9L, + 0xe2f4d46fa91d085aL,0x31759c9ceb35262dL,0x624d0cf20c9dd29eL }, + { 0x108cf9bb1624b02dL,0xa241444e345531d6L,0xf69816b273d372b2L, + 0x126575a7d5415e53L,0x546bb4c1306b8b0eL,0x82bb0c124d54ea5eL } }, + /* 33 << 329 */ + { { 0x85b355304c397362L,0x218a3b0eeda72e19L,0xd8eae54461729c56L, + 0x3d9b4a62735b571dL,0x12f3ee775629e437L,0xa72f9809095e5378L }, + { 0x5420a641bbe6dd1eL,0x8121eb3d02f41fe9L,0x5698eaf945e7acbaL, + 0x8a5e1a89469c2f12L,0x801740e25b434e0fL,0xa4dbe1cc670f58bcL } }, + /* 34 << 329 */ + { { 0x2f1919df5819e9f2L,0x156489e7a62287a9L,0xed038deb20a0c2caL, + 0xf63ac2d5c5ab4fdcL,0xca2b648ce391ec06L,0x8258e3f45b047d2eL }, + { 0xb7dcff56fd17b40aL,0xa8ace11f4bed747eL,0x542d70d175018429L, + 0x6c568967951bb2e2L,0xce420f73bb0e089cL,0xdae9623ed13f8eb5L } }, + /* 35 << 329 */ + { { 0x2d561034009a41d3L,0xf078204f5734d3a1L,0x2b8973ff7408e71fL, + 0x07cb9f95aab9c533L,0x376c1f59d0b35fffL,0x4a756c7fe851b313L }, + { 0xdc690e9874dedeaaL,0x625b082f70cf3f5cL,0x44839b5803dfc301L, + 0x5835a6c3c520f618L,0x695425e3afdb68d5L,0xc04ce4c62db97ee7L } }, + /* 36 << 329 */ + { { 0xc1d9b27ecb5833e7L,0x9911909567a8a669L,0x9317f8c30ab9ee27L, + 0xfad65eb9f34551e6L,0x7725ec2e016504f6L,0xca492cb47ebbdfc1L }, + { 0x6d2a3c962706aa66L,0x53e6d650836d8ee2L,0x109496434bc84bf3L, + 0x8442ee826df7c0f1L,0x7ab2eb9918fe80c5L,0x6a8579b35cd2ea35L } }, + /* 37 << 329 */ + { { 0x96adba7706e80e68L,0xa8839d6a0fe580e1L,0x755227e337a31a9bL, + 0x40b5fc70e27ec051L,0xb900a11b29af222aL,0x8fea2e509dd84811L }, + { 0x4f844c8861b59ab3L,0x26739874560c0948L,0xb39f85ba0cc08828L, + 0xcdce2fca829082edL,0xbd17998eb4555dceL,0x827eae97a3608a9fL } }, + /* 38 << 329 */ + { { 0xa77087f4c98e17c4L,0x9fa12dadbe2985a5L,0xa68cabc94bdce4e2L, + 0x222a6fb6d3500913L,0x15e28fd5a9c0904eL,0xed31c63f7a91f825L }, + { 0x9cd9f3e56f2f35b0L,0xa2b14261923cab8dL,0x71a780516d8ccbeaL, + 0xf1fe532bdfa937b4L,0x6e3d7252539d0a74L,0x27ef2720814cd797L } }, + /* 39 << 329 */ + { { 0x8bd8341e6899b9bfL,0xc2ea111680865aedL,0x0cabb5cf13fed0e6L, + 0xa11e82c1e4ce70c0L,0xefe3d4eb99aba16aL,0xd774db4dd8df10c3L }, + { 0x72ee5c98bae14dbaL,0x9161d0b179b86e02L,0x1ba8b84585e5ba90L, + 0x3830148f17228bdfL,0x222499e2ba89b2a5L,0x5d50922cccd4f87eL } }, + /* 40 << 329 */ + { { 0x81dd074e4398751eL,0x87b11b480a3f3ebcL,0xb5afe1f0352b58f5L, + 0x6d2d94829c390eefL,0xd073f9a0f36a8d23L,0xa7c5abec466ebbe5L }, + { 0x968c04a60539f145L,0x52a3ad0c93f4d3d3L,0x98e196bb15c0970bL, + 0x2af28ea370ab8ddaL,0xb912fbda7a039fa9L,0x3dd8d87acbd02ff6L } }, + /* 41 << 329 */ + { { 0x849b2f0b4ee5ebb7L,0xfd1b015158bea2f9L,0x260a6b5bfbc530f9L, + 0x2b6c198d06776366L,0x6540793f8074c6d2L,0x1c722c259871be11L }, + { 0x8ce5241ce0560ce9L,0x3574db548096df0cL,0x1d9dd078b0fb8c98L, + 0x6049c7f25625a023L,0xd2c0853cb18d0dd0L,0x5e57bd71cd645f78L } }, + /* 42 << 329 */ + { { 0x8da9b831361ce377L,0x6496515b7dc06076L,0x870e7df3b8cba83eL, + 0x315ac0049f8f495bL,0x1a09dee576fe0978L,0xae7af621c18059a2L }, + { 0x2bc9dea404fac2afL,0xc630bd5021b90a79L,0xbded6b8628c0f9a1L, + 0x709d72c7be4fe93cL,0x3d1e2eed74b22303L,0xcdaf6b1d0e81dfcaL } }, + /* 43 << 329 */ + { { 0x42d004f3be8ec138L,0x5379a3063d617cfeL,0xcbbd274ec1a87d06L, + 0xb9967c5284c9df0dL,0x0238d715c421e288L,0x787ee6abd239639fL }, + { 0x746e4071adace009L,0x2e2545db61377666L,0x47cc241cf07deb1fL, + 0x0a0742f1847dee19L,0x50175dd06e59b0acL,0x95ce3065d2333a87L } }, + /* 44 << 329 */ + { { 0x65c33cf4ca5eba6eL,0xbc48b22e12c2f19aL,0x6c5bbde461fbdcb0L, + 0xe086202bbc503a00L,0xa9483799deecbb11L,0x9b2c0216279aff50L }, + { 0xc10fce1069f99456L,0x2b0051d5b7820d55L,0xd2de9cc32129b5a4L, + 0x711166d9e4f565d6L,0x7a8c3dfb88075f30L,0x6914edda224ac45fL } }, + /* 45 << 329 */ + { { 0xca481b6e4e1e3cabL,0xf390ed5f7e12d8b5L,0xcda82616dcd06247L, + 0xf7d791422cec8917L,0x0c2ea9fe2364e5deL,0x471b71ed21f98e3fL }, + { 0xbebd6a753b9aae94L,0xf9914c0b45f5d5a5L,0x07c823ca4b3dd18fL, + 0x0b8c09ab74ad2bafL,0x21048cf7c7376302L,0x080e4a00efb16ac2L } }, + /* 46 << 329 */ + { { 0x1699d711379e6c77L,0x9126d88c7427418eL,0xbb05797d825210acL, + 0xc0b611df315cb277L,0x90f82a9d61f69206L,0x39a79014f517228fL }, + { 0xd9f2def450e8a693L,0x88c1104381e9d71aL,0x28e20b56451f8a9dL, + 0xeaa794763e101231L,0x3f1ba0c56423e8c3L,0x2fe7ce4e3c6c558dL } }, + /* 47 << 329 */ + { { 0xd706ab9cc55b1a3cL,0x99c453663aa386f6L,0x348c8f743617676aL, + 0x5f3c49092b9ef7bcL,0x26969963ff5d4864L,0x1f952e03f5b490ffL }, + { 0x4007914e30cd5518L,0x3b38fd1e0b0e6513L,0xb25e0a81decbba43L, + 0xb7e77345a7d78431L,0xbb7bc23062467d4aL,0x616c1724598ad852L } }, + /* 48 << 329 */ + { { 0x5bcf287864e60ac2L,0xf70e78a455d53345L,0x88685de6707a7138L, + 0xa77646dcfb2041a4L,0x8608695289db3060L,0x08b7c4d8e27a1690L }, + { 0x4148d9373ca7fd81L,0x58c7440bff7698a8L,0x9d722d4db0391d14L, + 0x5683112462b0373fL,0x87b0363be9a9992cL,0x51870cd18853db84L } }, + /* 49 << 329 */ + { { 0x775086f481eb73b1L,0xddf02d0e4db4d236L,0xab3d637445b09e54L, + 0xb7ef92657e883a2eL,0x20e6ae8f7f42b4b3L,0x26a14629bc49d85cL }, + { 0xf0ee4e5ca4ed9ba3L,0x288c5b0793b0b721L,0x9c767a59e9917114L, + 0x3dde322015085ec5L,0x3176507f7ece24dbL,0x71e1995686cc47fcL } }, + /* 50 << 329 */ + { { 0x86dedf2e9b1ab85eL,0xf3330387c2d0593eL,0xf5e6143997e907a5L, + 0x1992569d8cd66e4aL,0x836b215e0869329eL,0x8b5c4891153ff215L }, + { 0xf6c52f1b609dcc15L,0xa3a5258c085722c3L,0x0a4e81501c378dfcL, + 0xa8997ddc739040aeL,0xb1c4417a7180a073L,0x618009bff1dbab34L } }, + /* 51 << 329 */ + { { 0xc276e23733ec753fL,0x196a1ccee112da60L,0xcc049e2b953211efL, + 0xa60e1aa711dcc43cL,0x091ceb49cdfed2ddL,0x8fe1c52e72c69037L }, + { 0xf66eac87a986ba11L,0x4917f822b273d90dL,0xf7ef04cc957befacL, + 0xf8a7ac1320b8aeebL,0x71f0db3dbe6af428L,0xcb0bf8ba566429c8L } }, + /* 52 << 329 */ + { { 0xf617674d2cbb40a8L,0x446ad46b4d11399aL,0x4d4246943076b6b3L, + 0x1b9e7d881c33ea9eL,0x8e1aa6716954589cL,0xf1099b26e221722cL }, + { 0xb18904f94917576eL,0x0512b21bb549058bL,0x12c89a64a209ad3cL, + 0x421f5e575557cc67L,0xb42e17371b5a17edL,0x427c6a621ff3230cL } }, + /* 53 << 329 */ + { { 0x74e75db02bfb49e4L,0x7685588d58cf18dfL,0xfbfe8f56398e27a9L, + 0xd2711ec365666b9fL,0x1df7714d2c59b787L,0x0f2c4b4c486f8fc0L }, + { 0x098ed315f847b688L,0x60c367e332a20ae2L,0x58f48cd6bba6dd13L, + 0xc41e31960616128aL,0x7f90dd69a3205005L,0x8e6ce9d23581c177L } }, + /* 54 << 329 */ + { { 0xcf2da6044a3b3618L,0xcfd27cc6b83f1814L,0x8cb45c0a6b9369a6L, + 0x1f11501633976ef1L,0x2654a1574afc708cL,0xb47f423860970498L }, + { 0x548be9389fd8536bL,0x454fde1673ff1ecfL,0x44657efae96be82dL, + 0xc8e7e96b555df813L,0x2a0b3f4a4fccb822L,0x2e0f36b114b6dfdaL } }, + /* 55 << 329 */ + { { 0x227ba88551cefcb8L,0x81e8f52e00071a19L,0x4afd5a5d170fee3eL, + 0xc8864e274e17ff05L,0x1d8c2083710ffa4dL,0x22529baa9839c46fL }, + { 0xad771341825a0a87L,0x34a3049edad7c56cL,0xf1f14e1712f3625fL, + 0x6103d1fabcd36dfbL,0x9f5ce7a949a7cf78L,0xa5a4e38a333cf634L } }, + /* 56 << 329 */ + { { 0x6c8e5a261d99492cL,0x6e5bab8e77f916a3L,0x9b014aad50ad6f39L, + 0x2a3933c51f107e26L,0x4b04395cc951bf73L,0xf8f683b4b0ef56dfL }, + { 0x28c9fcdd1905c84fL,0xb03604f14141feacL,0xb546f58e53ace23dL, + 0xee5fec4efe688f02L,0xd8b43f6d2e91406dL,0x75e44b21261764d9L } }, + /* 57 << 329 */ + { { 0x56905026e84e6549L,0x1dc1958c5b84b0b7L,0xcb477afba55d3c52L, + 0x6c67cf7bc1434094L,0x739da94d2ecb03edL,0x8c45e5ee778ca2fdL }, + { 0x66084f9712e2fe43L,0xee6a89e66c3289d1L,0x623b73abc5d1a215L, + 0xb0edfa31cbf45830L,0x8024dffbd7de3b1fL,0x2ddf805a27f25caaL } }, + /* 58 << 329 */ + { { 0xb4e5a5d5605d7341L,0xe7a7a4069a1d3465L,0x234783d66c60b1b0L, + 0xdd7ee2fb3b480129L,0xfd183240dbb7032fL,0xba2a97accaedc8c1L }, + { 0x1a1824d3b0185c9bL,0xddc0f82cd36edae3L,0xaf7bbcc03116b17dL, + 0xefc9095985f6e8e4L,0xc6bde428acb9c328L,0x69d80732cbf991a7L } }, + /* 59 << 329 */ + { { 0x455a23a465ecec1dL,0xcf0b2a221d9e9887L,0x0b43131e3fbb1cc9L, + 0xd4ece789bdad49b9L,0x370c2f9aedfa4d17L,0x7f6855be15163f17L }, + { 0x868a16f3735ecbd1L,0xd84527db08897c01L,0xcdbf5b18f2df294aL, + 0x8c500b1f12b99a2fL,0x929c58df2591e3b9L,0x314cb13714eae6cbL } }, + /* 60 << 329 */ + { { 0xd014cc6deda2479bL,0xd2586003f1a85fb5L,0xceb0611153cd207cL, + 0xe8c9fbfa647b3c16L,0x1f53e8e6ab7d6738L,0x06dcceabb060b5f3L }, + { 0x80e023b2ab770ccbL,0x83ca0a5f4cda70d2L,0x19f7f5dfea1caa2cL, + 0x769041414ffe884eL,0xfa4d93a3fca3c05bL,0xd381f527e88e1169L } }, + /* 61 << 329 */ + { { 0xa4553b3534914b85L,0x03968ddddc176f80L,0x095fb9531f258fa3L, + 0xda9d2df7a554bb6dL,0x012a30ed84926864L,0x3fea37b12aa219d2L }, + { 0x730d2c6d81cc6036L,0x96ea83c9ddd81991L,0xfab080dcef1678dfL, + 0x16e25c6bfb2fe230L,0xf083a2b298ef2fb5L,0x0c0d0767581feac0L } }, + /* 62 << 329 */ + { { 0xd464a6525bc81cc8L,0x513353adebfa99d0L,0xd1aa97c0be51245bL, + 0x0d37e590e4d20201L,0x7afc95cbb45c5c19L,0xdbd640cfb6a4ea8cL }, + { 0xffcc3ff2be9c5b78L,0x61cb76ac1b2865d1L,0xb145bb0011352d21L, + 0x69568e5ce550ac6dL,0x454a33043bf7ee0bL,0xa2fcf9b45dad3642L } }, + /* 63 << 329 */ + { { 0x2e2c8fb3f33eaca6L,0xae1c78b265f75366L,0xbdc601092280d2b4L, + 0xed8409b7b6f472f0L,0x69eafa4f439e09afL,0x3b9ca2ecaa2b1531L }, + { 0x59b2e8eb336e484bL,0x93ec3ecac5f0481aL,0xb01e690ad575157bL, + 0x811aebc262e9d767L,0x1b26c0e49a9065eaL,0x5712d2c969a18827L } }, + /* 64 << 329 */ + { { 0xdaa7fcc9f9474bb7L,0x3c82e74bafa5db2aL,0xfbf918c59894edceL, + 0x470c45eda9ac29a7L,0xdfd44f6fbc372f2cL,0x73a4790aa1e38d3fL }, + { 0x23d2400ba9674837L,0x3dad71bc136a92daL,0xc76a488148baa4abL, + 0x73227e4ebc26e6b0L,0xe732edcfe8ef5662L,0xfe96aa5f0c5662bbL } }, + /* 0 << 336 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 336 */ + { { 0x87c7dd7d139b3239L,0x8b57824e4d833baeL,0xbcbc48789fff0015L, + 0x8ffcef8b909eaf1aL,0x9905f4eef1443a78L,0x020dd4a2e15cbfedL }, + { 0xca2969eca306d695L,0xdf940cadb93caf60L,0x67f7fab787ea6e39L, + 0x0d0ee10ff98c4fe5L,0xc646879ac19cb91eL,0x4b4ea50c7d1d7ab4L } }, + /* 2 << 336 */ + { { 0xcfbcbc4a7db62b5aL,0x2919bf514ab45ddeL,0x735de05622322f91L, + 0xd2590bda7662ae23L,0x63d468fed82be7a6L,0xc84d0435695ea172L }, + { 0xc50f494120a6fccdL,0x2d613990620f44f1L,0x680ccd041fd25778L, + 0x25ddac444a3d0808L,0x41d8b738c4684cbaL,0x2611645f53963888L } }, + /* 3 << 336 */ + { { 0xb05cb834b0279be5L,0x2de7d0ebf08c5f93L,0xf023b5aaefa9e4f0L, + 0xb8061e5d9bd075ecL,0x7d2ba50f1aa41bfbL,0x8963f3e390865d96L }, + { 0x7f221a794713ec7aL,0xc83bc5178500b4c3L,0x085feb6af6ab1540L, + 0xfd141024dc87cd93L,0x3e196fdb3239dbf6L,0xb7cf3e16dbcd5364L } }, + /* 4 << 336 */ + { { 0x1466c9f5e03a2fb4L,0xb866c006862a58a2L,0x291e8c75b5865550L, + 0x1ddb7154e65862ccL,0x285153bc2b997167L,0xe2fce0e7954b6c19L }, + { 0x985d450616dc2937L,0xf7f14216ee41d9c3L,0x39e098dafa5fe5e5L, + 0x3fc26046f90f231dL,0xde5d5ced32afd0b5L,0xad688b1d60c09c18L } }, + /* 5 << 336 */ + { { 0x3720b1720f806b59L,0x1f696d47f224597bL,0x03c46e315b54eefcL, + 0x387e466472b0edaaL,0xfc59b03dee77476eL,0x86854e54607a7259L }, + { 0x1478bcee3e9320dcL,0x4aa825a88c9d87e4L,0x71272f72cf272ee0L, + 0x19e3a4a38bd885cdL,0x9af6415b376ba31cL,0x6394b5a7807b2b36L } }, + /* 6 << 336 */ + { { 0xdbfcfa75e572e06dL,0xafa019d08b7d5653L,0xcc6c851d67a19b60L, + 0xace88bf431ae1a67L,0x74554a6193d1e135L,0x51ba2cdd4211890aL }, + { 0x7cb326899e8d1f02L,0x29a6b8258b66ab99L,0x0a672c21766e72f3L, + 0x24bb718a880642e3L,0x425dc41d184d2b36L,0x96a1468e891024abL } }, + /* 7 << 336 */ + { { 0x3180789c26df7050L,0xe375a43e96cdfd31L,0x7951b895e99e922dL, + 0x987ea2503d0bbe80L,0x6d2f49f0e2fe79c0L,0xc9c2c636c2b18d2aL }, + { 0x707798f3d8c8620cL,0xc2d603dad5c6a0eeL,0x46cf1e32bc447940L, + 0x4dfc145938a845f3L,0x210083fe455e5d92L,0x6be989eaa1fedc3fL } }, + /* 8 << 336 */ + { { 0x72fc8198dacc038cL,0x5fdae1d9f1077bbdL,0x369198bbd99e3036L, + 0x6b68390a0efddfcaL,0x8c35f3e4f0914741L,0xd2bc54ecca7d7807L }, + { 0x564d991e3a8695d1L,0x5e1e14c81b0d937dL,0x51f30dab5d635893L, + 0x0427e346f944e49aL,0x1e0bf1b56a233bc0L,0x75b0ee6c617bf93eL } }, + /* 9 << 336 */ + { { 0xcd2db6797b1bbd75L,0x1ce5acecaac388b1L,0x715ab9f634c1fa9cL, + 0xa531e1b8e0815643L,0xa64511c692de769bL,0x8425126b785b8bc0L }, + { 0xc8d9320de72e155bL,0x9cf36dcd5600a04bL,0xbea8b0f4c6e1f7fdL, + 0x6f9af6349767d85bL,0xc3ea9fa4c403ecb8L,0x0af7be1ed60a0e70L } }, + /* 10 << 336 */ + { { 0x180afdcc20928729L,0xec2e90f436bce72bL,0xa8a8c54d8f48e48cL, + 0x9d0c6a355248109bL,0x8bdd819baa6c3ae3L,0x95e221a6dc0bebc1L }, + { 0x83e568eceb113737L,0xaa6d29c8a1a3a0a8L,0x0ebd5015c54fbda4L, + 0x692a84832a5c8b17L,0xa08e384b51836490L,0xf1904bfc37ded786L } }, + /* 11 << 336 */ + { { 0x2093335463919940L,0x34e4f27397ea3359L,0xbe64c5584d4156a5L, + 0x368a6c980497cf92L,0x59931a502288b8cfL,0x67d70ff8c36cf906L }, + { 0x4175562a8886126fL,0x46ecdd1d55114ffeL,0xd12876f94efde702L, + 0xb0c9333fc046d908L,0x8358b04a2cd6c180L,0xcbaf4612336d3c84L } }, + /* 12 << 336 */ + { { 0xd77d9cd4fe8dee55L,0x7a0f60c12e43fc84L,0xecc5cd746d5da126L, + 0xb5ac6fee2382a984L,0xd9db83e26ccd0feeL,0xaa4dbcba350717d4L }, + { 0xb3c0562c812ead77L,0xf7a995eea96cdd07L,0xd5419bf1ffeb4e67L, + 0xba0aa22e1226df29L,0xb8d0d7f4c1e333d1L,0x86fecca60a27388cL } }, + /* 13 << 336 */ + { { 0x9ea1d715dc579084L,0xc1e715dd0b1cf2a4L,0x624fa6e4926bf7d5L, + 0x5034c9d34f7b4e51L,0xc1b0ed7aba3a42a6L,0xd1847c28b73cdb77L }, + { 0xa4794bc36ae49ff0L,0x50b2d908b9144fa5L,0xad112c778f073479L, + 0x040499dd4b98f590L,0xd415d273152b5e30L,0xd3f4ff3f39054cabL } }, + /* 14 << 336 */ + { { 0x1e0318d5fff93451L,0x40b91fa9283e197eL,0xdebc5a28089ac579L, + 0xcf25f527e9d98537L,0x73f7818d4ae08f51L,0x397f2cb6a956c875L }, + { 0xb7d74ac57515436dL,0xc29a2ffd830664abL,0x02e273563cabe01bL, + 0x418417c103c78924L,0xd12994116535005eL,0x53fc391258f66295L } }, + /* 15 << 336 */ + { { 0x6b1fceac4d87dff4L,0xd31aef70f262f722L,0x894361782612da01L, + 0x1d3bdfa9963bc230L,0x9a46505ba7afa565L,0x662c2fc7a31db4ffL }, + { 0x33983a9ae5ef30c0L,0xb8c874ee723f085aL,0xfb5fbc860f279c05L, + 0xcd9cc376ad0a380cL,0xcb19d881fdfad736L,0x1c3d9734585167ddL } }, + /* 16 << 336 */ + { { 0xd23658c8d2e15a8cL,0x23f93df716ba28caL,0x6dab10ec082210f1L, + 0xfb1add91bfc36490L,0xeda8b02f9a4f2d14L,0x9060318c56560443L }, + { 0x6c01479e64711ab2L,0x41446fc7e337eb85L,0x4dcf3c1d71888397L, + 0x87a9c04e13c34fd2L,0xfe0e08ec510c15acL,0xfc0d0413c0f495d2L } }, + /* 17 << 336 */ + { { 0xf791c8196726ae9cL,0xc95c53f13cee0ca7L,0x816b37ae601b0802L, + 0xcf28a2371b854925L,0xdc4f6bc111d5d9f2L,0x222d6102df6862aaL }, + { 0x93d3fcc5c0053ee2L,0x1d30937fdf873eb7L,0x925a2c2527d098b9L, + 0x8564c199001cf28aL,0x87cb85ed748b8479L,0xd12d6b2b184c1020L } }, + /* 18 << 336 */ + { { 0xeaf36b865bddb3c8L,0xa4bab6e0099f18ecL,0xe22839208addee4cL, + 0x485307e053bb454eL,0xf981c80d362db12aL,0x012190355cb4b460L }, + { 0x62824680c78bd110L,0xf3e0b963d87df5f5L,0xd96de5e2758da525L, + 0xc6a810faa60956abL,0x913d5a7b8e3eb6dbL,0x27c581fbbc9e8c3cL } }, + /* 19 << 336 */ + { { 0x5edcd7dcb0c55d75L,0xaeb0b5c727838c23L,0x13d65db758c3fea0L, + 0xe821d853b36f1f15L,0x3435a4bc365e7703L,0xb890e52f3a04d292L }, + { 0x6a96ae92e7a823f3L,0x3960ecb0ca611036L,0x81638aff210cb460L, + 0x5f95793ce6b983d1L,0x0d5029ffa3ae1a8dL,0x54f749b492ca1229L } }, + /* 20 << 336 */ + { { 0xefe0a702537c4a5fL,0x322ff89c151d0e69L,0xcee88b48491b757cL, + 0x8e92cc15b5da77c0L,0x3138b90bf6af039dL,0xeb73edd2f3748d35L }, + { 0xf29f06435b8bb06cL,0x91ea9643560e4966L,0x013c274875acbcc8L, + 0xdb2d1d9703f1d40dL,0xed7aeef1fcac606eL,0x91395dcabff4b849L } }, + /* 21 << 336 */ + { { 0x952e4e21c8967f37L,0xdc9f71994bf85ec3L,0x6b01f3d00c141bd4L, + 0xc6601dec06c9ba55L,0x7d884fc0c4a5945eL,0xcab1de947e19d3baL }, + { 0x9ca6aff02e3c9c5eL,0x01e828a1445e4a8bL,0xf97165ae80d065c1L, + 0xe2195895881978a2L,0x4834501fc6b77acbL,0xbcf7545445d99f5fL } }, + /* 22 << 336 */ + { { 0xbfc9c5071e434ba6L,0x30768f646f2634adL,0xee3a7cec1caf9c0bL, + 0x27c4fd0bc232910fL,0x5c5813ee24ff4510L,0xe5e731af901f2ce6L }, + { 0x440ca2cf68f9aef3L,0x54ff9e837fa17587L,0x4d792db7982acc0bL, + 0x73c3863834846c98L,0x76cff95f8d6243d9L,0x5fa573399d015583L } }, + /* 23 << 336 */ + { { 0xe0419a6fb007e4cdL,0xc44ac4961f613529L,0x3408e15af18f82eaL, + 0x66bebd87d92d3b39L,0x1c563ee4f85d0c1eL,0xb31a8c891f7eb37dL }, + { 0x65c7bf8c458a056dL,0x9d2ba592f25b6f73L,0x1ac4f0bc94eeb39dL, + 0xa008b562d9a9ac29L,0xe7de714589d1c354L,0x420f5cf04c2e45d2L } }, + /* 24 << 336 */ + { { 0xe11cc2e117cc0d20L,0x9b4cc698d406fabfL,0x6f6e9b0cb8567c18L, + 0xa0dcda9c61b22b83L,0x4c8683fa79ee53abL,0x7d46b3f82f11f0c4L }, + { 0x91e74e482740aed8L,0x75afb62a056466e3L,0xc60bb430e8d0c16fL, + 0x36cf252522b4aae9L,0x3713f254aceb6dd2L,0xc2906379eb8c6fd9L } }, + /* 25 << 336 */ + { { 0x440da0369eb8b2deL,0x6c4d1a38462fbb19L,0xfd86930fb050f995L, + 0x2e5f1a8c954823a0L,0xe9122aefcb9f8e9aL,0xc9e923f2794be14eL }, + { 0xdaa5663dbf740c2aL,0xf3a7ecd6df75c915L,0xa047a07efa80015aL, + 0x846b4d27ea4a720bL,0x2389717e295845f4L,0xf56f77f6cbf2eabaL } }, + /* 26 << 336 */ + { { 0xaac4f6a7e67b6dcbL,0x59ccb836d51c5183L,0x78d19f452b7ccb20L, + 0xb32d4ffd5a619a1dL,0x86b11dbe5c4bd17eL,0xd983e839a9b52073L }, + { 0xfe9c0b92993455c1L,0x3a156676ea36006eL,0x578217fea907ca7aL, + 0xaa3c5489440a251fL,0x6760a166d7fdf3fbL,0x4a2fc54b4415c6fbL } }, + /* 27 << 336 */ + { { 0xaedf171dbe18bc16L,0x00febab2b2d026ffL,0x82b6d8890cdcca4aL, + 0x1b1e4c53445bc877L,0xc2174e10ed74285eL,0xced66cc02b243f6bL }, + { 0x73e9ff69c7b9a66eL,0xc4fe5caad5e4d121L,0xaef80d67402c5d1fL, + 0xd3b95a0f2f3dcaf9L,0x00cb6e798ceeea00L,0x1ee2ca8c436f35e1L } }, + /* 28 << 336 */ + { { 0x0b21c764a6db111fL,0x7c36dfde24c5721eL,0x53a0b6db66e2d428L, + 0x6f37bf728169d776L,0x9baf6385a68511c8L,0xeaef9c919b218151L }, + { 0x712cdd5bdd58d201L,0x50bcd0988d3f78c3L,0xfb6427b571fcb05eL, + 0x6245fe7cc4675aebL,0xb5b75b50fb767bdaL,0xc1d8b76ddd7a18fdL } }, + /* 29 << 336 */ + { { 0x6392686cbb52f636L,0xf10df7c41c46a5c1L,0xab7f88acc504a122L, + 0x2a179193fdb6a9d5L,0x2a7c7e4e2901f29cL,0x3ab41b80a2cc726eL }, + { 0x8f577fc31fb5e412L,0x65cba0aeff7c47faL,0xa79191697f45c04dL, + 0x2712fcaeb29a4c06L,0xf2a879e4099f76e3L,0xd333fabd98a22a04L } }, + /* 30 << 336 */ + { { 0x87a905e056ddf14cL,0xd36289cb95a1c633L,0x2fb251aa57f8f0f2L, + 0xbf9c72a9fb7907a4L,0xb4f9b6f3f771333dL,0x7b5ed437469ea10bL }, + { 0xe8cfa847fa5a8f93L,0x456395c945a4c9a9L,0xe20ffc39f7fac5a6L, + 0x8b07c9ff287a3c78L,0x117f306f67e66d0eL,0x97c8a6388b331e09L } }, + /* 31 << 336 */ + { { 0x1b3e04c26a98318fL,0x04d5ed5dd5a63b2bL,0x4098d09f3cebabecL, + 0x226bb70565a14306L,0x5bdce76fd962a94fL,0x47a66e96c40dedbcL }, + { 0xd514ae5bbedcfbb0L,0xa8c0fe40892f07e7L,0xcf78e224c9186f1cL, + 0x2499f68fe94329e0L,0x3ea3fae5ebbe3d2fL,0x681fca8bbc631de3L } }, + /* 32 << 336 */ + { { 0xb097b2c5c4e81268L,0x7ef175521d50ca8cL,0x638266e942099644L, + 0x43d059deff729073L,0xeebb5fe1148c3940L,0xb82e73d1daa8e925L }, + { 0xf43c78d8254380fdL,0x2beabc58fce37fa0L,0xcdd5a7d66b636357L, + 0x8b70a2ebe096a954L,0x011d5419d0afa2fcL,0x3e49eb6704fb095aL } }, + /* 33 << 336 */ + { { 0x5c73f69fb99abd8eL,0x0a7c36aacc1ed636L,0x9d2fe67e7f69a6cdL, + 0x04d015fd48c34b1fL,0xc50f88c17f84915fL,0xeee3e105a706fb24L }, + { 0xbd42861c734d0513L,0x544b6ef495408b60L,0x4526e680d40179beL, + 0x9f984c4140ab740bL,0xbed7baee67a02ab3L,0x09e3446862a9fb2eL } }, + /* 34 << 336 */ + { { 0xdf64ebcf28eedf59L,0x435531be73b5d9f4L,0x1990df01cf35d981L, + 0xa34d4fa9a2cc41b0L,0x9f643bd6b5a10b37L,0x90cae11158a6cd14L }, + { 0x2b0490701943d2f3L,0x2c9f8af4eda3fc20L,0x48c245c5f96e72f3L, + 0xb4505a3a861355deL,0x4dfab1b9be032112L,0x69c1a9195942de24L } }, + /* 35 << 336 */ + { { 0x761c2c356efcc891L,0xd06710d1fa376241L,0xc83a491c8a78b0fcL, + 0x0c0ee8d8af75b3eaL,0xe6d9d92e4532b587L,0xcb3b652d64eba138L }, + { 0x1cc504ca34ff5d2aL,0x207e7443d0eae0baL,0x94ad1676428382b1L, + 0xfcb5909992ec17c5L,0x7f99e1b5ce3b2e48L,0xa8c38c0fac9bc921L } }, + /* 36 << 336 */ + { { 0x5763ff1af4ba4711L,0x6aac1315bfaae662L,0x51b9c30ede4b5505L, + 0x50e63d1891b25d3eL,0x41938349e65ea695L,0x11260360f514dd15L }, + { 0x231f7f574a086eecL,0xa2c3237f55bd9ee1L,0x8afafa043e0705bbL, + 0x44607900e9fc754fL,0x7250929678519ce3L,0xe751c3a74d17708eL } }, + /* 37 << 336 */ + { { 0x0098a3254611d3dbL,0xbee52036dde82f67L,0xec432a62cdd50282L, + 0xae8a144e52f994f2L,0x027e9e60aa5c03fdL,0x1a49ce47821f55f7L }, + { 0x46fbbd6c4d10c0ffL,0xe14c82ff8c461df3L,0x95570f44aef902b8L, + 0xacaa04ec0eb7eb26L,0x3c8c86a8e738570fL,0xb87d47ccb77cc59cL } }, + /* 38 << 336 */ + { { 0x2f4f68377bbf7168L,0xd5b67947f03f7145L,0x2c6ca74d4cecfe22L, + 0x0e559b9f0a7d6fadL,0xdbcd039ff6b37f98L,0xaaf1f6edfa7a3877L }, + { 0x97b779f0f607316fL,0xe2185ccc72b99fd4L,0xd3f696bf2bdfe399L, + 0x20d9baf15e6c403cL,0xe5bbc1cb4c4f1216L,0xd1c0761a428838fcL } }, + /* 39 << 336 */ + { { 0x4f433b8abd08dd65L,0x27849a72773bd3c0L,0x62351b911854502eL, + 0x836580ffca24ce7dL,0xa5c224a39355258aL,0x8d33fb43e65db7f0L }, + { 0xe44d391edf49a825L,0xc28e0d9bd2f5d4bbL,0xf7208342efb61ae9L, + 0x43686b414dbce055L,0x7f7562d01800c062L,0x5031bd7c8b8ace99L } }, + /* 40 << 336 */ + { { 0xc183199375476a4fL,0xa6383a0055fc4367L,0x23a72dea98bf90c4L, + 0x67ee6f451045a947L,0x4e6518836920d0a2L,0x49132c9ac8042a04L }, + { 0xe249e46d5dfa9fc8L,0x6ff9eba1c60d1a11L,0xa4d9362d43490335L, + 0xe8fad79ade504480L,0x519e8d1bac43c951L,0x7e688047952d6f54L } }, + /* 41 << 336 */ + { { 0x135d677342e27f9eL,0xd58b98fb8fcc77e0L,0xf3bb847d7f64928bL, + 0x15ec841663176905L,0x83e75b6a0f755173L,0x4c3eff5c7a24de69L }, + { 0x289e9a45313bf61eL,0x01b15aadeafa2733L,0xae7fafe1d2cf501dL, + 0xd6fba525d5ac0b3eL,0x4bf48be0689bb20aL,0xa591843255bf610eL } }, + /* 42 << 336 */ + { { 0x0f019b64c5f8df0bL,0x112f06a979307310L,0x91dc57276d16102eL, + 0x34070a5be2651248L,0x0b9f35dbd3423044L,0xf29bb4a072b10ed1L }, + { 0x87071a9a07fb6388L,0x4246d532b7dbdb1eL,0x87db3d2285a039c9L, + 0x76620a5d42b030cdL,0xc798e3816a42d8ebL,0xdd97441ac441ef9bL } }, + /* 43 << 336 */ + { { 0xa9b004a0f08592c3L,0x984d17e5d069c54dL,0xc96f2132ccb87e81L, + 0x67fd082f3b1f9eccL,0xcdd0827ac4ff9feeL,0x9d1025070e04b7a6L }, + { 0x4ff3424177c67935L,0x4f2246f58efea5b9L,0x128085b12fbf7615L, + 0x9f111f65174b0575L,0x0b27d8e2f455cba5L,0xda20626b536054eaL } }, + /* 44 << 336 */ + { { 0x4a3df6de3761fa82L,0xb839d6babc56eb6cL,0xe41afc5e13977a26L, + 0x64022937fc0686d5L,0xa5d6dc19e2d681a2L,0x81afab3128f411b0L }, + { 0xc089aff74321a117L,0x32b0ae2657d18f89L,0x650aacd5f66aacd0L, + 0x7b317bf6b8d3f677L,0x2cd5789777ea82dfL,0x935be0f3c74e7509L } }, + /* 45 << 336 */ + { { 0x4387f8f602de9e59L,0x529c06f337589811L,0x6dbaab60bc9f06b4L, + 0x0063bc3db5f181faL,0x7bcb289969b906b3L,0xdca70d1331d1ea3eL }, + { 0xca65e546ee373e94L,0x13cd365c779f415fL,0x4183460e9d71cb08L, + 0x60f312726e35eaf7L,0x3d0c265f14bc5e0eL,0xe7a1b9af39ce618bL } }, + /* 46 << 336 */ + { { 0xc234c892f46aac36L,0x213076ada55983a9L,0x81f96142dcf335a1L, + 0xf21ceb724b22e311L,0xa12d6333dc053e1dL,0xe7808925a930732bL }, + { 0xb5a9eb81b1f1075aL,0xd13739c0f0a3e623L,0xbcd842e9ff2f24d5L, + 0x200cda381b16ff0fL,0x0a85ea521d6a6c54L,0xe1c0dc8756785463L } }, + /* 47 << 336 */ + { { 0x3287c8d39100f769L,0xb349ce8c052e8bcfL,0x5fdb952dd0d3e44bL, + 0x68715110d0639cc4L,0xc9a5fbaac8efc67eL,0x14ebb97da009aec5L }, + { 0xf0684e1ca1423e1eL,0xb282f2f56357fa17L,0xc2e79d3c5af78041L, + 0xe0ca9f4bd7d2ba8bL,0x20629f1e04dd84bfL,0x274ebccc3ee73228L } }, + /* 48 << 336 */ + { { 0xeb05c516156636c2L,0x2f613aba090e93fcL,0xcfd573cd489576f5L, + 0xe6535380535a8d57L,0x13947314671436c4L,0x1172fb0c5f0a122dL }, + { 0xaecc7ec1c12f58f6L,0xfe42f9578e41afd2L,0xdf96f6523d4221aaL, + 0xfef5649f2851996bL,0x46fb9f26d5cfb67eL,0xb047bfc7ef5c4052L } }, + /* 49 << 336 */ + { { 0xeadd123d385f2b36L,0xe3b14829ddf58569L,0xa4fdf0ec47c7e485L, + 0x93c0d8380623ea5fL,0xeb9c0a2c9e2661deL,0x8046fc69e72e0ca6L }, + { 0x6f439e5c7be1c918L,0xcd8fd2f92a9ffcdcL,0x7f134747420e939cL, + 0x8e880ef05ae283f9L,0x502c5c99f780a249L,0x68a529ab94bf9d68L } }, + /* 50 << 336 */ + { { 0x3cf994ed88c9d290L,0x9209f5610bb34d46L,0x8170b567b2bfa21eL, + 0xae87b6f7c62f86d4L,0xac6fc431d71bccebL,0x5f3a62ba83cf2970L }, + { 0x390262d1d943b10aL,0x8fc9a27f28aec573L,0xe59beb203e3069f9L, + 0xf3e7bd365e0812a7L,0xc29c8a433aceffa4L,0x015feecb41c25e2dL } }, + /* 51 << 336 */ + { { 0x5b6a4d6ca8e61f40L,0x35825d762f9a6e70L,0xd48f6d8d346a8b94L, + 0x12bea60889801a40L,0x5182192ad57115f6L,0xb5a8dc6b954c1b47L }, + { 0x084a5c71793b427eL,0xeb66d699f8de2a03L,0x9835b2fb8eb6d905L, + 0xb4229923c79dfe40L,0xa7c8aedddee34c0aL,0x12a00675337b0658L } }, + /* 52 << 336 */ + { { 0x38ca9f61d44aee32L,0xb2cd0f505484905aL,0x23ecb3a4d812e727L, + 0x9be645b874a3ac5dL,0xaa4a1d114bfa93b9L,0x5be5277d147072caL }, + { 0x623a4bd9ba0a6d93L,0x03419661dcf3d9b1L,0x9bffbe8231de1cf4L, + 0xbadfa2ab56a6af06L,0x9103f7256746f09cL,0x0cd5e956344a2688L } }, + /* 53 << 336 */ + { { 0x50a18ab1f40b0edeL,0xf963b76736e01032L,0xba2029b4d4f9a6deL, + 0x8baec9b85a8446b9L,0x7a4107e766fa8a92L,0x06e78bf99f6543d9L }, + { 0xdaa894b3a5043e86L,0x172858a8f4e6fe37L,0xff0265cc0844608dL, + 0x5db1a8f1d5def174L,0xdf9f8a698874fbedL,0xdd2292a977a274d6L } }, + /* 54 << 336 */ + { { 0x46f522196ad8d03dL,0xb63e0eaadaf8b0d3L,0xd667f0a66e29df38L, + 0x6e77432f96ef3b57L,0x78fe0872139ca180L,0x300a0c78d1e4af21L }, + { 0x650f32462148816aL,0x31ef1e883b4301a2L,0xa2222b25f18442fdL, + 0xb26b63066884291fL,0x977b6f7d713d88daL,0x3e8173248cd5f7f7L } }, + /* 55 << 336 */ + { { 0xd5687c9a9684771aL,0x797808e396cf65d4L,0x793d4eb6ea9ee562L, + 0x2359b991fd94defcL,0x4e75cdf03a8959adL,0x7a08566900ce7815L }, + { 0x5c61df5da699fc46L,0x02b62d4868da56d5L,0x8a6972d1eaea27d5L, + 0x727582b3c8e5d04fL,0x0ab2e6c2de87c408L,0xaa9a62e47b9ed157L } }, + /* 56 << 336 */ + { { 0x9c6247d631af03e4L,0xe5a59ad075f9ee90L,0x1da1d64f6ac4b5a6L, + 0xd2fbd169c521ec7dL,0x6d168015dfaa39f7L,0xe9bcf5b59c69d9d7L }, + { 0x3d1d3e6693ae2925L,0xcda60beae4bc73a3L,0xb2456adc954e2f3bL, + 0x5d312fdc02a8fe08L,0x7b37c00e0e497a0cL,0xbd1f3aafc2f8b148L } }, + /* 57 << 336 */ + { { 0x60f3bb27bc00d150L,0x159c5af42448affbL,0x4492b6bd2cfa563dL, + 0x7e58219683c833b8L,0x9f9ebdb20edfafa2L,0x93a7048f31a39a8aL }, + { 0x4172f74d50149d01L,0xff38fceec58b7588L,0x2e71ba9099f25353L, + 0xdf50fb440604e555L,0x7effa7ca8f3b5969L,0x3bbe8d49b836b8bfL } }, + /* 58 << 336 */ + { { 0xc18c375c29d08d49L,0xb04c0c29c1a681bbL,0x0c4acce9e74dd458L, + 0x1d6da95c85c920a1L,0xc67280d285387462L,0xeba99725e7e804adL }, + { 0x08f80e5a8811a138L,0x26f442138f2136e3L,0xf67f157c2d028cc9L, + 0xb436356d14cd7cbaL,0x1c9c610290281895L,0xf67f16ea48598bdbL } }, + /* 59 << 336 */ + { { 0xbf926a077a326266L,0x4045c18bef43cfc6L,0x6fad4cf56ce45553L, + 0x613ad2dc45a9abc8L,0x7b086ace8836eed8L,0x855857c213ad51d7L }, + { 0xa3b19c2d167664adL,0x422c548abbd2c452L,0x8cd3681f85928ef0L, + 0xe969e45c3ed435ecL,0xf76f2cce746c9aacL,0x514df58d1dd90e35L } }, + /* 60 << 336 */ + { { 0x9b66219c4d09cd36L,0x6c6fa570b54f0853L,0x95c268bcf29a8fffL, + 0xc8cf84bf5420c324L,0x5bfc975ebb61617aL,0x935cfe24e78f1bbaL }, + { 0xa6e2afe919d71ea1L,0x8a321e568c9b950eL,0x42dd9e28ec097826L, + 0xf06e600ef391633aL,0x94e5512b46acbe2eL,0xb0bca2cc61cc7a08L } }, + /* 61 << 336 */ + { { 0xcd361103e8b2d41dL,0x2d0d982cab0b5f13L,0x8158129618d55aecL, + 0xf1c28a71579caa03L,0x5ddedfd7e50b83faL,0x932d2c03222105d0L }, + { 0x48fd0ead75ada3f4L,0x29209d988c533a40L,0xc2acc587f2acf0c8L, + 0x05a8703ef689912fL,0x8f28953b9182995aL,0x1cbba2f20fb3eeeaL } }, + /* 62 << 336 */ + { { 0xa1472574180e5eb2L,0xde27569b93fc7b21L,0x3bb956816b9af8aeL, + 0x8a25fc0ee155f89bL,0x8aff018d825126b2L,0x6eda2f31906f0bdcL }, + { 0x19cbbecc4e8fbe4eL,0x04e0a4a40568d248L,0x6de2c002ff07b863L, + 0x6d388447e8d1595dL,0x6a193b70c2cfd10fL,0x00bd826ee6f6bf96L } }, + /* 63 << 336 */ + { { 0x2a0165a40a5b4d1dL,0x49c85ee904f12309L,0xc2d221031ded788dL, + 0x510ccbb3735bd89fL,0x92d2eaebd8eb0e1dL,0x6bda8e346e428c11L }, + { 0x44c01a1d361f7495L,0xddda8e97cc7a95bdL,0x95cbae30524a53baL, + 0x266d7192dacad45bL,0x8a42793f22fa4b99L,0xbb393cb5ed204904L } }, + /* 64 << 336 */ + { { 0x88e7ac8e168d5e60L,0x53abd5696188a98fL,0x3b96d52918be419aL, + 0x7e75e354c057621cL,0xcb1b709f5ce57e59L,0xe78befa2844f2463L }, + { 0x536081993276d4a0L,0x92636ade157f2024L,0x6dd0d348e0411414L, + 0x5b28e9504d73eeaeL,0x08439232690ed85eL,0xdde1a3496da14b58L } }, + /* 0 << 343 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 343 */ + { { 0x6cbd275739ed9ec9L,0x5db68a68fe5d4aa8L,0x177eaa0be4c58c7bL, + 0x603551ef0e488784L,0xc8eba131df916b0fL,0xd0dbceda159732e2L }, + { 0x55acca84b0834afaL,0xdbe98440b59ffbf5L,0x162a2c703bd3b202L, + 0x4c5e5d256ddd8ebaL,0x66e7844a77b1d93dL,0x1292bc0e110b9dcfL } }, + /* 2 << 343 */ + { { 0x1b66faabf9e89beaL,0xc81c5ddc3a441284L,0x1a82f3a0a675f7c8L, + 0x82884a2f30313a71L,0x7ac5d7b058aea9e6L,0x1954f075cd5ff05dL }, + { 0x7c29638d6178d270L,0x6af7f8ba19381929L,0xe85e3c47a17ae3a7L, + 0x91b107c77009e38aL,0xf3b777d8f1f9c52eL,0x5b7b74ff11b688a0L } }, + /* 3 << 343 */ + { { 0xe1e5b76914b87b2aL,0xee187f5d143a4ae1L,0xa9a38728908cb988L, + 0x2027b2ed4443d8daL,0x1c6b4813c0c98675L,0x509ea7d1323bd978L }, + { 0x43b16a587f4dc19eL,0x385f8be812940ae9L,0xa4ed64e57d59acadL, + 0x47e7abed51ca7f14L,0xead594b82bcce6b8L,0xa2bff60cfc03cf06L } }, + /* 4 << 343 */ + { { 0x4ae3d232c0385874L,0x83bda9e6cbf96d2aL,0xba73c769ec62fd6aL, + 0xd586ba7f62a4720cL,0x6497cd140cc1f491L,0x8b012b707b2ac571L }, + { 0xa65eabb6268fd705L,0x8caf100a1431873dL,0x25b31b84231457d7L, + 0xcab62f75901645c5L,0x2377d74db2f7b656L,0x4008277c2d33c95cL } }, + /* 5 << 343 */ + { { 0xa7be70c04bfeb784L,0x4633ddadc222ab44L,0x00e397d30f5924bdL, + 0x5446db3ae25b7b9eL,0x433ea2c4fa1dd048L,0xbb9ae36a1421321aL }, + { 0xf879069dc59fe8f6L,0xe0f2b8b4820bfee2L,0xcc6cf7c49cf239e4L, + 0x0e3545c207dc3122L,0x23b0f48b1d2c737bL,0x1c6b6d9cfc1137d4L } }, + /* 6 << 343 */ + { { 0x10105dfd101d2433L,0x64e009b58ab6d664L,0x122e68324e80fc07L, + 0x3b26e76287dc7da6L,0x7bc183de6d4728cfL,0xebfecf4f8bcdc129L }, + { 0x8b995cec265c66f5L,0x080572d7c4b0e942L,0x612e9e6b4da5b77dL, + 0x8ec048a96caf9161L,0xe3628ee2c7f45eb6L,0x0190b71bd85650e9L } }, + /* 7 << 343 */ + { { 0xccf79a81017fbd3fL,0xa852ca29c875bc66L,0xbb4cd90c0592f8e2L, + 0x2ee786f455b05c79L,0xe1a2b6baf382e6e7L,0xf2d6cf6e6d2e952eL }, + { 0x2f0b534abc9304fcL,0x1d63fd80795629a3L,0x42e70cd9322d8e03L, + 0x8a282cdfb057e36cL,0xd18a0c313ceb177bL,0x270e31569c58b890L } }, + /* 8 << 343 */ + { { 0xaae2f448ed001c43L,0x08ad1d9bcf4be493L,0x3262b2f482c1f372L, + 0x5521febd351a5f7fL,0xf8ec9190916c75a8L,0xf3c258c72728dfb8L }, + { 0x5dd4ff4f8af19574L,0xefddf5795d076b1cL,0x318b5b98ba8b777aL, + 0xd971d426fb7f8409L,0xed1465e8b0fd31dbL,0x80d24d4300f66347L } }, + /* 9 << 343 */ + { { 0xe8263e8012eb6baaL,0xc452c7581dde8c37L,0x5112af2840baa45dL, + 0x949b8a740793703aL,0x8ba78382e60e007eL,0x38cd110412823c99L }, + { 0xdeb0d555f86cf04bL,0xb2f20bfdfd9f6320L,0xff1d399d17c39502L, + 0x1340aedd1bdf0760L,0x36b2b43c88cc0c09L,0x5f3dba7e9ce285edL } }, + /* 10 << 343 */ + { { 0xcea0374a69ca5051L,0x19e060ad5294ae7aL,0xf6ce02361bb01f47L, + 0x2a5b28ba8c328b8bL,0x6991b1d8b253d630L,0x360afd40859455d8L }, + { 0xf5c6e1427c1f5946L,0x1eab83084cc8c391L,0x4eb4032f67e76ecdL, + 0x5bf14aa233898059L,0x0804a7c00e001b76L,0xe3866a93734cd134L } }, + /* 11 << 343 */ + { { 0xbe85177db72e5eadL,0x47c15fad59fd2463L,0x2cf5f07f4bd51f8eL, + 0x82f48288c2898713L,0xdb08aab4c8f753e8L,0x18a1f5c510f58eddL }, + { 0xaeb7bde366d0b94cL,0x04539620079fb6dfL,0x64d1aff2ebe8c4b9L, + 0x08d9ef431a10a101L,0xe326c7ec6c602789L,0xd8b1b3e7f6efc3d1L } }, + /* 12 << 343 */ + { { 0x5ba5288c1ae586a2L,0x044f1fc61b715821L,0xc1a9a997602f3c65L, + 0xc5c7512fe08c0223L,0x48a19c3c367e6f1dL,0xa9f2195dfb241597L }, + { 0x9f674a5fb5ba32a6L,0x275a060f0a312742L,0x5aeb8c4303d6f13eL, + 0x0fed575d917433fbL,0xe4a5ef9a59f53490L,0xa9f86145f315e616L } }, + /* 13 << 343 */ + { { 0x770d01ab2c1deef8L,0xca72f761f61b2a4eL,0xff686a4ceff9ee49L, + 0xd6b338d30d07000aL,0x885b4e8ce1050b10L,0xd6326179b2364b01L }, + { 0xceb2bafc672b298aL,0x7df8941aba628946L,0x9c94004ebc56b115L, + 0xde09cc2d7b12cdd2L,0x9c2dda163833ce43L,0x88da691a6265b59eL } }, + /* 14 << 343 */ + { { 0x7059c58669a03980L,0x91f2dfe4e88e1287L,0x96dcd9318d9633ccL, + 0xb2abc44f37bda148L,0xe31adb3feb8964dcL,0x7b07e015e316876cL }, + { 0x31732880ababd240L,0x5c37a667e95854a1L,0xb5b334c91d6f69adL, + 0xe613e5622c34e118L,0x8bbdbf5c5f5984edL,0x82ecfd95cf4f63a1L } }, + /* 15 << 343 */ + { { 0x813caa72ade4e3bfL,0x29055be8600c93c4L,0xcb346967e6e4ec1bL, + 0x39c1152d50ce992fL,0x4682c20e5ce62852L,0x04e9dcb7f4e45ed4L }, + { 0xda75355d7c0fa5bdL,0xe80f29b078949d91L,0x6214610130fb9e33L, + 0xe70cda8f325eececL,0x49217f74efca3e14L,0xd3c890b36bd7246aL } }, + /* 16 << 343 */ + { { 0x315ad7a47e5a59f4L,0x1c615bfc543c8b00L,0xe12f97a8baa56473L, + 0xf263db4446edcfcbL,0x47cf91d53c1a968eL,0x1a1165b4c15db875L }, + { 0x5d35e53a3479616aL,0x649f87b45c59958fL,0x5d3d11ea246da3d3L, + 0xc1ddfcc653f06820L,0x8169d7116610c00fL,0x15f16ba54bddc8c7L } }, + /* 17 << 343 */ + { { 0x307b040d9977713eL,0xc03f7787dee9e016L,0x761a5d03e12c354fL, + 0x8fa1a4141cc88904L,0x2e079008b7675e71L,0x649c789591d68d60L }, + { 0x63467e93c98f1c9eL,0x81931ac7fcc52703L,0x2060c89538e59af3L, + 0x8c12e002a87024c4L,0xfc881e69b3b8496aL,0x2b4e482e1e827081L } }, + /* 18 << 343 */ + { { 0xf80ed61a30fa7e86L,0xf2e5f324a15ec5d9L,0x139ca085ecba2d64L, + 0xd164ee5ff3f5cfd1L,0x758c0008e5cc3cc5L,0xd180c463ce8fa1f9L }, + { 0xe5dd27054adc6e61L,0x061e0c3c592c39e5L,0xec5a8d4a4e437781L, + 0x9e4c6f461e6d4540L,0x33ab232e2526e6eeL,0x3c551685ea282d9cL } }, + /* 19 << 343 */ + { { 0x59507a2162ce1459L,0x88b465d1c6a2cb30L,0xa5ef8b2b5c8ef7d4L, + 0x73145f4c4dc9a457L,0xabad3390d19186f2L,0x7036b424f9b78a7aL }, + { 0xf76f51bb16e04046L,0xecd1ece92b2b71efL,0xda8d82011900f2b9L, + 0xc2d3291b268d1bfbL,0xa6c1c79a2d176459L,0xb27e5d5885ee1b7bL } }, + /* 20 << 343 */ + { { 0xcf19fb2a1e548ef0L,0x8bb6dfa0cc694171L,0xeb1668ca5c5e390fL, + 0xf5a3485be1975263L,0x4edfc596442cc850L,0x9901f447f9627d74L }, + { 0x3a6b85c984d0413aL,0x1466366167de639cL,0x9fc9fdcf11705bbbL, + 0x6d066e2bbff2cf80L,0x38dedc2fdc3026fdL,0xad533a981b828538L } }, + /* 21 << 343 */ + { { 0xa7d51d862222dcb3L,0x52e2531cd1a6c525L,0x742b1234532126d8L, + 0x226043f24e9e77acL,0x02f270afb3a75b2bL,0x7ede5714d4a8dc0aL }, + { 0x24699e16b34fd97dL,0x4e5d785e8d417ad1L,0x273f5dd1ec307ecdL, + 0x742373863186955aL,0xf46805fde6afd38dL,0xae100ba424562906L } }, + /* 22 << 343 */ + { { 0xed9f434e5216636cL,0x242bd09bc5c1668fL,0x8bb747bd804f3d6eL, + 0xd66d8753c7c83dd2L,0xa71016c2584540b8L,0xd8b16210fdd41a90L }, + { 0x5eb5947e1b65be60L,0x1bf995e7616dbdc2L,0x71b7099abb7dbdd8L, + 0x53650d29079eec24L,0x6bdd1b0e8ebd86c8L,0x0a9658ed9a31624aL } }, + /* 23 << 343 */ + { { 0x3be2ce89b8cf4d55L,0xf9b3c501822cdcd9L,0x0cc8423010e12f3aL, + 0xee09031a3c580ec7L,0xf4c256a812f4b48bL,0x71a8323104018d0cL }, + { 0x69ad6d7babfcf13fL,0xfa79b457af658743L,0x249f32816001af58L, + 0x158430fcea127a64L,0x25a3e4549a9be713L,0x68ba3f0fcc6b5bb5L } }, + /* 24 << 343 */ + { { 0x6c75bc93b7bfa29eL,0xf86f22b218ef6d69L,0x90ce6a1536dcadf2L, + 0xf11f711c7ce50921L,0x0739ceda38a479e3L,0x840b825e6ec3dbc6L }, + { 0x7c36c0a59fa23481L,0xceb61fd170cb186dL,0xac6f7d3c26e4754dL, + 0x4076d3b5f317b385L,0x52f1bd723fd9e9c7L,0x6649d8b6bf316043L } }, + /* 25 << 343 */ + { { 0x5f03dcdcceb1e25cL,0xafff6561d50ff864L,0x17208b6f3a6bb787L, + 0x61d96c978e15abf2L,0xb1beb427991107b1L,0x436328475008aa3fL }, + { 0x8a326eeb3595febdL,0xa8e5a037ec60dc0dL,0x762ebd2a3159f062L, + 0x8ea005adbd1b0bd5L,0xd4d863cf696d4121L,0x2a07a637eacc9b9eL } }, + /* 26 << 343 */ + { { 0xf352e28b54a8ffaaL,0xa8317f089ce68b6eL,0x7deb148770cad820L, + 0x2411b382b2c3579dL,0x20b21ed214d36e66L,0xe7331bec353b9ff5L }, + { 0x5692636840dff0b3L,0x13356f7b646eff07L,0x1e6e6e4508c64091L, + 0x913b83f2ea0b920eL,0xb69e5f839f713aa1L,0x8e59d3794632a60dL } }, + /* 27 << 343 */ + { { 0x3594c0d3cdefc3dfL,0x9d850e2fd21cf9e7L,0x245322944e38263bL, + 0x597964610e43acb7L,0x13fad563bca9408aL,0xe52983dba985390cL }, + { 0x9c5e71e08c000a9dL,0xde6b0b2f800949e2L,0xc58032d131d94108L, + 0x36cd4099b31811e6L,0xa8d9bdeb3981d619L,0x06f644e03d4760c2L } }, + /* 28 << 343 */ + { { 0xdc2870f8243cfbd5L,0x000b71b31ab496f3L,0x53511a3f708f4507L, + 0xbd7bd0381949d835L,0x723a007d938f4db6L,0x5bc8679e2d04e9fdL }, + { 0x51ca5fd176ec7fc4L,0x86c4205c988f354eL,0x9042e76b2a0a4a90L, + 0x368f52a84ad44d2dL,0xddc2cab8912edfb7L,0xde74ccf5cde80199L } }, + /* 29 << 343 */ + { { 0x91b31fcbcaa3f1d2L,0xb8a29af1bcc99f53L,0xc5842b2695662f80L, + 0x13954262a4b4b396L,0xc1fac956a6acfdffL,0xbe37fa4dcf60b88bL }, + { 0xc7715493dffff3deL,0x06dfaceda1274350L,0x9dfcaffd7460fa94L, + 0x5f1d3a351e9c317dL,0x2fbf393d377b84ceL,0xb4d9bc8404b83635L } }, + /* 30 << 343 */ + { { 0x29871ce22855a74eL,0x5418f0dc98696474L,0xd8bc07d6b90d0498L, + 0x391012a79fdc0ea2L,0x271396949b09f60aL,0xa0a43dbf3371f0d7L }, + { 0xab5849422af8d992L,0x64cbd121409eb3faL,0xd36faf01766864fcL, + 0x69189faea2a83417L,0x3c24d85e3733b772L,0x125a915d2ee497adL } }, + /* 31 << 343 */ + { { 0xa8f9eb2abab3fa8cL,0x484584f654ab1e16L,0xee74e5aab21b34edL, + 0x3ce626ff4eb689f0L,0xd757f22b0006e5bcL,0x611505d024a25e65L }, + { 0x212df14c46382659L,0xd17898d78c73da0aL,0x5604a93e51421c2cL, + 0x76147f7603a580a1L,0x325b5c8ae5c34d09L,0x6ff28848db857152L } }, + /* 32 << 343 */ + { { 0x8002f4583e455a61L,0xafbafd375bea205aL,0xa8ced112fb93f735L, + 0x27cb6292196e3084L,0x72395bdd77e8c744L,0x02e018d8ee71f5ffL }, + { 0x7cfc14d9c1337a1dL,0x94e14c0ad7b4d86eL,0x66e50129d213738eL, + 0x7a905d91bc0b5ea3L,0x92cb630afca06700L,0x65e06d5cbf3a0821L } }, + /* 33 << 343 */ + { { 0x769ff9191e1cde66L,0x6ef257d1944a8786L,0x881437da4f75233eL, + 0x15266f3768665eafL,0x21fcccafc1777505L,0xe9513e1ab7fea0ddL }, + { 0x67806e9c53c8a735L,0x24be9a769b11ae2eL,0x928c1455045d2065L, + 0xea0395b53557f62eL,0x910d7cb4c7d3a450L,0xe849c853c634443dL } }, + /* 34 << 343 */ + { { 0x76c6e48d3b476f69L,0x28195cdffe694ee4L,0xa3a9a99e2d3aacc9L, + 0x0f68fe36b7f320d8L,0xca84a6c9889ce762L,0xc1eafac94901907dL }, + { 0xa28b9916208c9770L,0x6846e639f8403e57L,0x12fdf9fa1d179e3eL, + 0xb81e47c843d046dbL,0x700ad19468c14491L,0x136395cebbac51d7L } }, + /* 35 << 343 */ + { { 0x7452dfd4f775003bL,0xb38a2031f1a4765dL,0xef36c513a2888c68L, + 0x2039b168a2339fd3L,0xf74c24be2cc498e9L,0xbeeaca157b622e31L }, + { 0xda72e5a005f2fb8fL,0xab4a98f0568d5811L,0x231aa495fcb15e1eL, + 0xf981bd7f537023f1L,0x29d6eb2db367e5fbL,0x15247194b8cd452dL } }, + /* 36 << 343 */ + { { 0xa81e4a4e55c2369dL,0x394de01b60a0f544L,0x22acfd07a8906e17L, + 0xf59b37a6cc9bc4d0L,0xdd16a22c7ffec12fL,0x07decc2ad5976455L }, + { 0xc5019463abe1d122L,0x2bf0ac0ce318c92cL,0xfa50280ab2bfc47bL, + 0x53354fc5c7cf8bffL,0xaea1d293e20ca341L,0xec25ecda8b626244L } }, + /* 37 << 343 */ + { { 0x05c6f1c99a2f572bL,0xf13f8c7747987918L,0xccb406d74101fdffL, + 0x93cea27bee1abcf4L,0x32703ada8f5adca8L,0xceaecb5f76313a1eL }, + { 0xf1c558980b9620cfL,0x942c28b51046c388L,0xbed4e9dc5a07cf8cL, + 0x423b695a6c734b85L,0x1ce0a2392ac87737L,0x40f126ac4d1cc7d8L } }, + /* 38 << 343 */ + { { 0x63e3bb09ad9e132dL,0xaa2880c5c9e84778L,0x23de89ea06049834L, + 0x442d1df3554e23bbL,0x87214f9f08c5f124L,0x305d967a6beb4996L }, + { 0x01676f804409f827L,0x16992f73a50147f9L,0x77ee56796081b38aL, + 0x8c75d293290afd9bL,0xf9578bca813f0aceL,0x395212dd0e786ed6L } }, + /* 39 << 343 */ + { { 0x63475e65c21b0f48L,0x114f9af5326c2c63L,0xa897bc01310f768aL, + 0xcaf47a8fc1bf3f5aL,0xc023bb3718cb887aL,0x3572f633685652a2L }, + { 0x2dc4ea0d7523287cL,0xafd60b92a121a141L,0xb6b4bf6e085ca490L, + 0xf599f8f2e5351ecbL,0xe38c8eacddba3d60L,0x2540585f5be9e748L } }, + /* 40 << 343 */ + { { 0x313b66cafd8ba33eL,0x10bdb130fabe27ddL,0x1181334c125e2b8cL, + 0x0f4f198fdb6f94baL,0xf7000076ac3f5de9L,0x1a78813d9d6402aeL }, + { 0x3427f75dc8a9e758L,0xcdac8b34b01f791fL,0x922c36d12a9ebaf5L, + 0x195ea05fb0487cc4L,0xe33de901a808baecL,0x15e1d5ac57291d89L } }, + /* 41 << 343 */ + { { 0xfe52cd9cfdc7e2deL,0x3947e578da6dccf1L,0x0548d4b5738751e7L, + 0xc73fc23f4b52a5ffL,0xf38eb8ff1b066accL,0xe9a40d37a27b40f5L }, + { 0x723b0752a264ad77L,0xe5d0c4efdea83bf8L,0xf7301e3fafad27a0L, + 0x336b0d86298d09b3L,0x462766bdb2ef2fb7L,0xa5311241141a7607L } }, + /* 42 << 343 */ + { { 0x10adb987ee1f44a1L,0xd6ebd1c3e51c0152L,0x0cf1303f4dd3b9eaL, + 0xd06351b837a33a3aL,0xb5ce1d941cff1f0fL,0x326b3e055476e2bcL }, + { 0x90f76b5d3426b8ddL,0x77497380648042f1L,0x48684604f9f83902L, + 0x00275191180f197aL,0x36fd84ecde7ce932L,0x52b428e65391a268L } }, + /* 43 << 343 */ + { { 0xd2c1ccb0695c2851L,0xd722b84ff1c78f17L,0xaaa53d26fe52f2a4L, + 0x3057f4ed24742143L,0x951332a4a2aea258L,0xe5e4db6091096878L }, + { 0x71db9e48f0b9ef38L,0x7e4b25c1ac542c26L,0xb7250394dd021df5L, + 0xcdcc6118ee48e711L,0xbc324af1fcdd5db9L,0x71a664ef3e6de57fL } }, + /* 44 << 343 */ + { { 0x4e2a05c1c21cdd1fL,0x8a232097dd46e76aL,0x8b55313cd871b1d6L, + 0x976ce5f6af396bc4L,0xeb91527dafd381b1L,0x6cfd449014455ee2L }, + { 0x8723be9e1f274d1eL,0x1c63fd011999fa9fL,0x5f1726258049b6f8L, + 0xe18a3ecd99a51b4dL,0x329fc2c1b13d4e65L,0x94da252b0f18f300L } }, + /* 45 << 343 */ + { { 0x583adeb8b893316aL,0x69dce1efee5122deL,0xc5cacdf319b77627L, + 0x061fedee5e8aedd8L,0xd53fce220257dce1L,0x0e4124bdc781e069L }, + { 0xf097c697d44ed517L,0x7704e33e9a4e9019L,0xac245dc23e0088dfL, + 0x70e1176bb76102a3L,0x55261ab235e4dcaeL,0xc2ba59230ede3501L } }, + /* 46 << 343 */ + { { 0x6edf35f3af073b6dL,0x7ab4118107376eb0L,0x4ef3e65be7ff1c9aL, + 0x654ea359d2ac6d70L,0x2b41a7f67ffcd91fL,0xe5da0511e0a60e8cL }, + { 0x97fefd9756701b93L,0x7a4a827dd34afe15L,0x8bd6c2299090536cL, + 0x110156f217e510a0L,0xce62a26ec801ca6aL,0xa786e9b05522b64aL } }, + /* 47 << 343 */ + { { 0x3c73c2868f02f70bL,0x744a580d0eeca325L,0x58b7ca1733534669L, + 0xd7d17d77800b0270L,0x864e3509538b116aL,0xc7eda5dce4797818L }, + { 0xd6c00fbaf741f023L,0x718ed11131d022bcL,0x4586baf2f2ce39efL, + 0x1095729dcd9a09f8L,0xf5ff3f2d7652f5ddL,0x29d95a09dbb72722L } }, + /* 48 << 343 */ + { { 0x7b151b98e28fd10dL,0x8fc01ce81dd884cfL,0x1f0ffb5098d56c2cL, + 0xf9df1fa2b084606dL,0xf86232bfdc7d2008L,0xeae5cb8fd8751699L }, + { 0x70f0229883ed54fdL,0xb575283a86087697L,0xad2191350302e2c3L, + 0x1c09a0d6c4b57e01L,0x0f65e1e1c541b9fbL,0x85493d9bf4fe76c0L } }, + /* 49 << 343 */ + { { 0xecf595d6bc19db89L,0x32cdf31bd607e09bL,0xfaf93c636217e9faL, + 0xa9a1619884d37c72L,0xa2688a33bd929e8eL,0x2ce3442e2842b31bL }, + { 0x906ac09ab37184daL,0x93a1a54492587ea0L,0x1acfab1ec5b4ce7eL, + 0xd4788cac7131e80bL,0xb463d67bc8cf0e18L,0xa754ffb81f24067fL } }, + /* 50 << 343 */ + { { 0x634f8d6db04ea518L,0xe8c424b4c60108a7L,0x3553b6d11ef6f4bdL, + 0x1fe850dfbc0a8e1cL,0xa077055473a66e4aL,0x5417bd50da985b55L }, + { 0x3f99edcaed53259aL,0xd243f2d1b3d5ae6cL,0x70f404b8cb49e74eL, + 0xf6893edc51fec8f0L,0x3f3ac23871521335L,0x127c055436e39048L } }, + /* 51 << 343 */ + { { 0x459a96595ab6a5b5L,0x14ec172bb5ac2238L,0xe556f7061642ba57L, + 0xe18d92d2da35bad6L,0xe64f9bcdd5805c1fL,0xabb4e0243b297094L }, + { 0x95429e14b8b876f3L,0x27961a7d9c04bad0L,0x81c74cf57fa32b6aL, + 0xb035259ebb0f1f24L,0x828c42da2e773f8bL,0x06c996366ea73c24L } }, + /* 52 << 343 */ + { { 0x353718ce191c21ccL,0x08e6edf64ad6bd18L,0xc2bb0d6e4dc5b572L, + 0x328e19df88193daaL,0xccc9f6ab7211c958L,0x377d99ef58aae5c5L }, + { 0x40e2ecc91c823442L,0x036d6d528b0d36abL,0x2fe0cd7eda4d0ad3L, + 0xb8fc3c7ffc8af791L,0xdb7e44a42b201b20L,0xa5176004ebcf527dL } }, + /* 53 << 343 */ + { { 0x24d19ca6fed20bb6L,0x0c02db9841d634aeL,0xfb55998930310b8fL, + 0xf9d0818506c00c8bL,0x2b9983fb4742362cL,0x16ae9bfbdce1b6f3L }, + { 0x679057e6a161a419L,0xe1e80fe04db28bbaL,0x2ca0c869f06c9a98L, + 0x7b80c43bc448ffa4L,0x100f205cb7ef73f7L,0x29565a93a938bea7L } }, + /* 54 << 343 */ + { { 0x4d00c613e1e7a831L,0xc90021dc56d9ddf2L,0xbb80b8385286ccccL, + 0x156b05b771f5f09dL,0x120f47f47bc921f7L,0x6ea1715f8a65c50aL }, + { 0xa070c9f695aa8348L,0x96120fe273171f56L,0x10c7d592ebc69e4eL, + 0x73f6ba27c1c7ef52L,0x10f5b9cef8bb536dL,0x8bc82b225ce0220eL } }, + /* 55 << 343 */ + { { 0xac25749af4f3fa3bL,0x2376bcd76f50e4a0L,0x9c68fd1028b2332dL, + 0x130ed4d12130b66bL,0x91842d58038dfc9fL,0x4111e4cbc401a53dL }, + { 0x85532deafb5d9b16L,0x0c5657503025e3b1L,0x1340aa49b6cc0c31L, + 0x1cfdd7d68b7f71a0L,0xee911d7e8b6e548fL,0xcddf07f021456ebdL } }, + /* 56 << 343 */ + { { 0xe19b7576fa5256d2L,0x418d5425db3f8bfdL,0x00424869951a1719L, + 0x2383c7a8533b69b0L,0x166a38e2e67a86fdL,0xa6baa01c5876c435L }, + { 0x574ddc4584a208f5L,0x8cee30b826b18dbbL,0xeced99c1e9f6b30dL, + 0xb638d88da7d34beaL,0xa4836806069adedfL,0x62beb7ee7a07c593L } }, + /* 57 << 343 */ + { { 0xffc89d6de16d63b2L,0x4da3b04f5df40d2fL,0x3437da2ab48706d8L, + 0xc35290a1d677df03L,0xe54fc6567c5b6c8aL,0x84f052ff2c77314eL }, + { 0x59c33a99d968b4eeL,0x2424c5d0facce444L,0x022d7bfbf505307dL, + 0x5372518d00c142ffL,0xcc82d21aeefa787aL,0x3517f3c0473ef630L } }, + /* 58 << 343 */ + { { 0xaf576c307a8a437cL,0x15852131de3f2cc9L,0x96bbff4371759da5L, + 0x106934ec66f5257dL,0x712e7d0ba9cedae6L,0x5b0b876ddabf131bL }, + { 0x1605f3a8b741f94fL,0xe5d961c109305b04L,0x3fb97996346266c6L, + 0xaf4eafc0b3ec7458L,0x0aefa01abcd90b0cL,0x2b7723e3505ea305L } }, + /* 59 << 343 */ + { { 0xe5c6f37b43d12de3L,0xdc34fdad642baf26L,0x89d716d647268e1bL, + 0x50047b391df8d657L,0x40da6352c64470a7L,0x406e3bc97879824eL }, + { 0x9677b4c38b9ecc36L,0xc82bf16fd246788cL,0xbc9fa99cef5dda3dL, + 0x3050febf0e7b676aL,0xfbb1301a53e448afL,0x3239f20267c84d67L } }, + /* 60 << 343 */ + { { 0x5093950b724fb94dL,0x107822718117ff50L,0xdc9e34b59f5961d7L, + 0xfaa2fc012351a33eL,0xb9e0f1d9d5fc462eL,0x276a5b3bdd9c6914L }, + { 0xe6136d1775365ca5L,0x228b77e2a91eed68L,0x5cd6a269411e4770L, + 0xd8857b0e17590390L,0xe7094f3aa0d45fafL,0xe52d11dcf40693e4L } }, + /* 61 << 343 */ + { { 0xc873fdf565a0d2bbL,0x848244dbaa42c6cbL,0xa5d2d766ac50ba78L, + 0xc650cf4343f38ad7L,0x901cf122ea895d06L,0x3ec1b583cbf46321L }, + { 0x863dce6193c3db94L,0x902459202445bb4fL,0xae716052673385dbL, + 0x9266b0bfff830253L,0xd201095844375610L,0x9e008b9712cf8d71L } }, + /* 62 << 343 */ + { { 0x2b1b2a551448e73bL,0xa8486146b5f97da2L,0xcf24d8636c848202L, + 0xa3d6431c5e483407L,0x47a33db852edb78bL,0xb09256a37dad3826L }, + { 0x740222a74dfa2b26L,0x23f43bec2a8ebe04L,0x4081e512a8072f18L, + 0xe53f0d05751ad7e8L,0x100d0a17332361ecL,0x8a2122e9e0c3a152L } }, + /* 63 << 343 */ + { { 0x28be8affe7e6417aL,0x4e18b452d6a30763L,0x73ae410310d0d5f2L, + 0x5151fe80003625caL,0x45ebb636ba7a91ccL,0x50f4b49d994e7e31L }, + { 0x02eaeaa93ebac455L,0x7632c7dac830fb1cL,0x06fe1dde3bb0d765L, + 0x0d2f7623a6789d20L,0xabba46de01a43e9dL,0x2e822e08f27917f9L } }, + /* 64 << 343 */ + { { 0xe96c4aebe5f5b545L,0x10a85a002d4c43b0L,0xf86ad2f632f9151dL, + 0x05daf874302b99e2L,0x4299dbfa14fd3171L,0x27cbedd6812cfc62L }, + { 0x42e61536b8772164L,0x52eecef76a5423efL,0xc34c6c70548fffa3L, + 0x1fbed7777b6db825L,0x850bded44ef2989eL,0x3b8a542c815463eeL } }, + /* 0 << 350 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 350 */ + { { 0x9decf2173079fe2fL,0xc32ec5707c817f6dL,0xd5649ce8aeb36b92L, + 0xab9f77d158fb4dc8L,0x66b11fb6b52d60cfL,0xe217941deaaa4619L }, + { 0xf3522a9a1607c412L,0xea2eba4fc2a3d8c9L,0x267997c625e38722L, + 0xed5047b72d4595eeL,0xaaa41e5f55e5456cL,0x891e3d1278cfc6feL } }, + /* 2 << 350 */ + { { 0xa438634ed7357a51L,0x918f14cd18c04d59L,0x2ab4dedfac40dd56L, + 0x758e95ee4956a5deL,0xfc11e3945113f84dL,0x6d71b6736059f16cL }, + { 0xfd8e2236fb357c3fL,0xd7c8681232dca873L,0x02aeb1538ea13b44L, + 0xde1275d3013d3827L,0x470a7b7e659ca201L,0x862c83c55c77b351L } }, + /* 3 << 350 */ + { { 0xfc9b800f05084cfbL,0x1c4d4510496f23fcL,0xfea0003cc1d08465L, + 0xf0281da09af48a41L,0xa5c0d97144d32eedL,0x2613b73e023a2e31L }, + { 0x455013c87dc8ac1aL,0x581b13195958b3daL,0xd293f2f22290aaeaL, + 0xa068256496f6223bL,0x38fd18fa69410ef6L,0x74eaf35f2b2cf629L } }, + /* 4 << 350 */ + { { 0x281f6e58c7ff5b50L,0xbc67791ecf9cd114L,0xe29fa41afd89abd8L, + 0xfcb0b0b07984feefL,0x0b0928a6d9d20a64L,0x2fd385c46979ccd5L }, + { 0xce9c34c81fbe72e4L,0x69364344aad0135fL,0xd464635250946a5bL, + 0xb09a97c6f39f53b9L,0x1d47bc20dcbc8b64L,0xcda5c7bdd458b0d6L } }, + /* 5 << 350 */ + { { 0xad5b8c2887eff3b3L,0xa8a3917d9937833aL,0xbafdc493200c3b49L, + 0x9e27aac5972c6fbfL,0xfd292bb20518c97dL,0xa62126db33515a63L }, + { 0x9892a8bb1bcfc875L,0x93b066b7e0b674d1L,0xcde9b0087fd3d080L, + 0x1e285a8859401ae8L,0x4679e32982cfea96L,0x52406ea023e615d3L } }, + /* 6 << 350 */ + { { 0x27de61138b6e9462L,0xb8ade1dc473464bfL,0x911ad49394dacc08L, + 0xd036f28e44252cb1L,0x3865abf6d13dc20dL,0xcea487cdd528f0baL }, + { 0x14d77eaf4fc290feL,0x5106533bc5084101L,0x11001dc7cda9eccdL, + 0xb79ad4bc49fc4a78L,0x4f6369f54567f8a9L,0x64050aa2df7ab817L } }, + /* 7 << 350 */ + { { 0xffe057aade07f615L,0xf3f91b55342700bdL,0x294761e127a839f9L, + 0x6411a2b480eafe1cL,0x4900eb120737b80aL,0xa1134d10bb73264cL }, + { 0x0ebfad730ddbf7f1L,0x57bbe692cd1f73ecL,0x675931fca20f8944L, + 0x1950eefffad2ad19L,0x60d304029cdf88a0L,0x121af89e33fd2c6eL } }, + /* 8 << 350 */ + { { 0x763e3664295c4db2L,0x632fd676dbbaa92dL,0x62ab11a8c66b40e9L, + 0x06244698f384b708L,0xe7cdf3bd69197876L,0x9cc79c48064f8837L }, + { 0x95900a229486589eL,0x7953f6e72ff01639L,0x3f65fbbddd3e6e46L, + 0x84f52e06baa2e2a0L,0x1dc462a8e3852824L,0x9be69c3f7e4c032cL } }, + /* 9 << 350 */ + { { 0xa40afc3670977e01L,0x965f110da6c3b289L,0xc4952f87805a8491L, + 0xb36804b80b65e2d3L,0xd3f6f5ace8cf2b2bL,0x0f37a79da4b71938L }, + { 0xb2f810d9489ef671L,0x1feae0262df23cd8L,0x7412eee321a14e4fL, + 0x1458b8ad179d51faL,0x2156a90ee201509cL,0x39f29fca72605867L } }, + /* 10 << 350 */ + { { 0x231f70adb2e066e3L,0xf09db880bb477a19L,0xdfa0e503907e5c63L, + 0x12fe09f4f97022adL,0xdbf06f3620bce7ddL,0x0140e197f1371cbaL }, + { 0x917b6da464b0b4b0L,0x9a6f4d9b20fe3320L,0x0981d60ed66bdf87L, + 0xb430e4e062d3487cL,0xc3440fb934dc4a94L,0xe7972dda09a5e3c9L } }, + /* 11 << 350 */ + { { 0x29d6394093f47052L,0xadf04e70847e5937L,0xa0ef4fee731bab6fL, + 0x21de31956ee7d7bdL,0x99af4a8dbd716777L,0x9e15c983df4c569eL }, + { 0x2ec7bc0ce94401eaL,0xda1835ad85727722L,0x2b5862ce5dad81daL, + 0xb2be508188dddc2eL,0xa02482101414286bL,0xc52c436d8ea33f3fL } }, + /* 12 << 350 */ + { { 0xcc580ea73b24e776L,0x0f3a8b189d721d6eL,0x8665604fb23480cfL, + 0x95787cba34414689L,0x425d7c6f4d10a945L,0xb5ec2626b2f1cc78L }, + { 0x55da88858658de6bL,0xb50919d1e9aba03eL,0xc64881d7d99e417eL, + 0x1eeba5aabf28fba2L,0x20feb7b3504eff80L,0x9f5f9db650debfb7L } }, + /* 13 << 350 */ + { { 0x4eb94584230923dbL,0xba8611287b3a6929L,0x5aa7faa3ab1d6b31L, + 0x95c1e23916ae0966L,0x98674fd3a2fe2297L,0xa8da0ee53c42d488L }, + { 0x103cabace0740db0L,0xf0b860d45bf16882L,0x03cb0cdc289e48ceL, + 0x3c15d3759e52c7d5L,0x524f731998103ca2L,0x828ed65cc609ffebL } }, + /* 14 << 350 */ + { { 0x518f231b83dfb993L,0x4b0987db37c0826cL,0x0c34961cd5177eadL, + 0x9d882d3e452c92daL,0xbfeaf5588765bcedL,0x83957b62b9962295L }, + { 0x2d1d01757bb084cfL,0x04c4cfcde8cffcfcL,0x2f35e33d8d4536c1L, + 0xbebb31cbd83124cfL,0xe342bed2abb29019L,0x2af0fcde2692a0d3L } }, + /* 15 << 350 */ + { { 0xece5d865c7e3b29fL,0xe58106a4622839ddL,0xf5272d43f2969d76L, + 0x90c72c1b2a1a240fL,0x1e2aa0acaf15e14fL,0xfa2f1c7bf1b6b5a0L }, + { 0xfb5d343d880224a5L,0x47b88a84f91881c5L,0x140f5ee9dd142fe7L, + 0x4e76982e24b37c44L,0x6aaf61e9578b482bL,0x01950e22765bc4e2L } }, + /* 16 << 350 */ + { { 0x20ebf79ce8a2e8f0L,0xec040d0daca418a2L,0x016c07e78d630d2aL, + 0x20021d57fa605dcbL,0x6190f3e942d04705L,0x4e000df58974b7e6L }, + { 0x6710da6c5abcedacL,0xf31aa4965f95d37cL,0x192c4b8ba5830899L, + 0x171ab8c4ea7dbcddL,0x715f60818cdf1097L,0x0e0135bf205d10edL } }, + /* 17 << 350 */ + { { 0x070fbbe1687645c4L,0x4dd859c8c7e0261eL,0x749fa1e9fad54b60L, + 0xb35942f483cdc91fL,0xcef26d0018eeb83cL,0x4dddd5787462064fL }, + { 0x0420ed6e703e8740L,0x9087d805c180c7d3L,0x93807412828424f2L, + 0x8bcea69a6dcae236L,0x22aed9a2d1973c78L,0xe3d0f6f83328d690L } }, + /* 18 << 350 */ + { { 0x5ce5bc6da85a13acL,0x868f385c7f1dd71bL,0x15aa63a420c376c6L, + 0x7802fc9e749127dcL,0xfad59f8e67a98935L,0x6bc97b1d60c0fdf3L }, + { 0xd24caa7ebce87ee6L,0x8aa08bc27ba511f8L,0xe5ba94f47ba61c1cL, + 0x9fe9c343364d2d75L,0x8ee0468161273932L,0xab2f0dbe5e8c4861L } }, + /* 19 << 350 */ + { { 0x13239c0a8254ded6L,0x594182e61762f9cdL,0x6326369d480efa21L, + 0x7fee5afd33101382L,0x9e1ea59c4688bc0bL,0x7a3b1b8eae19c17aL }, + { 0xa8f8f8e5777aedf3L,0xe2d018bfc6bbdeacL,0x3625b03b54328db4L, + 0xda7540c8711ab8caL,0x7faa19fc46930a99L,0x61a5d1845b59a973L } }, + /* 20 << 350 */ + { { 0x4a6226f9f7092423L,0xfe6b7a6dec945231L,0xb44e2e60a1193cabL, + 0x2ce6393543dda270L,0x1a9e8a2138d64738L,0x863d151a9d843675L }, + { 0x98a1222ee2b14443L,0xbf8b32712826846fL,0x80475be555508801L, + 0xc39ccd917b38f064L,0xea31304de8e249f5L,0xa3b6891b4d42db74L } }, + /* 21 << 350 */ + { { 0xc0f1627a147e0f32L,0x59fb7f2f5e8822d8L,0x21d8be6371097441L, + 0xa6169f1b855543f5L,0x188c420645102ae3L,0x4c20a136131b674fL }, + { 0x05487c4d15999699L,0x8a82a130e6ba5542L,0x93a2119519ec0de9L, + 0x634d644cc8d0538aL,0xa90c5eeb3b6bbd60L,0xd59105125e4db926L } }, + /* 22 << 350 */ + { { 0x5140a7172119e821L,0xe5a2ca8cbc370a14L,0x0c17ad48a6db3398L, + 0xd7094545ed6fc82aL,0xcf32984dedb976d1L,0xcf04ac16cdf83a9bL }, + { 0x9bbea16b49775502L,0xb4855286452a6f35L,0x45cbc3b7a86f445dL, + 0x5972ec64763f5990L,0x14d0b9c0b780b2f0L,0xb120273456e707feL } }, + /* 23 << 350 */ + { { 0xbf6b76e1e41c43c6L,0x64ea1824db033acdL,0x7fc0399987c9406cL, + 0x9427585a51b371d3L,0x464f3559c9705e0aL,0x6639797ac8cb6ff6L }, + { 0x5104a72e842fbf01L,0x7cabb009fea7af74L,0xe42aa69b19a1db1cL, + 0xca9599a3a6a7ab69L,0xf31e4aaa1a70d770L,0x0fcc7f1b8a5ef098L } }, + /* 24 << 350 */ + { { 0x39a689bc281548baL,0x11aacfca138eabbeL,0xcf33108a8d29457bL, + 0x312612e014ed4b4dL,0xcbb21f345115625fL,0x4e7217de303a363bL }, + { 0xaeb0c8c0d137f67bL,0x4ff84a937bf78dfeL,0x7a022604683b37dcL, + 0xfa4ced77862b0847L,0x5a49bdc136d69390L,0x6d9dff06c0215314L } }, + /* 25 << 350 */ + { { 0xcb116e787b1320bbL,0x6310206258ed15fcL,0x1a7891a082c13108L, + 0x203d73d939eb4c93L,0x0485b8493c78c65aL,0x663897e93c935525L }, + { 0x9b79708088b41afbL,0xbd34d5134f2b649dL,0x0b4c156f62f6b652L, + 0x24125d1d6863dca7L,0x726a8bb2edb6638bL,0x2ec5deaf82aea7a2L } }, + /* 26 << 350 */ + { { 0x9fb22ca52a3706f1L,0x5a265b5279f5203eL,0xc8844f096fcbd426L, + 0x52a165f0ed8a3267L,0xff0b3a00dfdfcac5L,0x80167cf52de9e1c6L }, + { 0x9e9c4391b0b969c7L,0x279440c41e0dabf6L,0xaa535b8f85133e39L, + 0xef61e22234660228L,0x8ea81a41c386528bL,0xd0bb1f6e71a8c66aL } }, + /* 27 << 350 */ + { { 0x75a689bfa67ab0ecL,0x53eaad3e54843363L,0xdb71f81619a3ba98L, + 0x817257fdc244f33dL,0x8181c028c0fb3720L,0xc813c4651cb7bb39L }, + { 0xbc44c1e71b189585L,0xaedef8701eea3a29L,0xcdd828d7ccb5dc90L, + 0xd224f1774fd2e0f1L,0x2a4723b0e78883e6L,0x33bb05473128e260L } }, + /* 28 << 350 */ + { { 0x544874b71477473cL,0x253a455a3907385fL,0xb303afd631411ba1L, + 0x30047aa0466d6415L,0x3a1b676594d4c2deL,0xc265f1912860c7b1L }, + { 0xfe140a73688e7975L,0xf08a652bf37ce7deL,0x6c9f6df9f46f144eL, + 0xf7e7b95bc0defbc4L,0xfbc9a9697824c075L,0x9745d768d7773c39L } }, + /* 29 << 350 */ + { { 0x7170ab4699873dabL,0x765eb89b8952bc0fL,0xbe3fe2c4f78fd020L, + 0xde51f8579f194b70L,0xa625839e7cc68fbbL,0x50e59b49f7105097L }, + { 0x625294f3b82e287dL,0x98daa85288ca9d10L,0xfa0eb790b499d9bfL, + 0xe280de610382dba8L,0x3fd350e0e76a7d70L,0x1e5c2bebece5ba7aL } }, + /* 30 << 350 */ + { { 0x73e187e000ce469bL,0x21dc6268dbd717ceL,0xe9d63224ee564ef2L, + 0xa7553c854c4c444bL,0xdd409398f6a9b713L,0x902c9cff72f94d6fL }, + { 0x944edb33f50a36eaL,0xa48a5ae4cfb65a8aL,0xcb9a83b9ed82fddfL, + 0x9476090c209aa829L,0x66cd0cb1c7e2347bL,0x0f1fe07c86fa005bL } }, + /* 31 << 350 */ + { { 0x7c17a2e0c65e52b9L,0xa987f030615b8325L,0xa39b78aaa3d4dba8L, + 0x738ce26396e96e82L,0x313f7bb7f08f99cdL,0x29571b3cd1a1b7c1L }, + { 0x00c0e66c89ead6e5L,0x231de4ff19b9874dL,0xc9445296a4137755L, + 0x7b95f3ea336ea724L,0x7c0a222c49bfe5a0L,0xa265c41d782f8d4fL } }, + /* 32 << 350 */ + { { 0xd2db4d35c8d2bf7bL,0x52105d0981571d06L,0x447565cc723a57bfL, + 0xd98c3597d8ded62cL,0x0aeac6d9de2f1a9eL,0xd363b0b70a98d3b2L }, + { 0xd9708f0702ad9933L,0x9334677564f5809dL,0x499332cf49cda010L, + 0x546df74a858467e2L,0x8b84a55093748e8eL,0x9e88ef9706f09073L } }, + /* 33 << 350 */ + { { 0x1cdc6b4f673d9c55L,0x4300148a0c11743eL,0x2f924ce4c38b8c99L, + 0x5300ecc925f32459L,0xb9cd815004473c2cL,0xffee15498eebdcabL }, + { 0x42c292d54c537dbcL,0x32f6d8a293a133d0L,0x4da3a50c35dc41a6L, + 0xc16dee6a102f9ea4L,0x69a017a1f00d0bd6L,0x6a95ee1527acbc5eL } }, + /* 34 << 350 */ + { { 0x6c02c17adcb73b47L,0x10073a3454b70b07L,0x417ca218a7fe7a73L, + 0x6f81a38e4ab64b0aL,0x4e25301f8fa7fc44L,0x180f3e1b27d41e1eL }, + { 0x88925649ce1cfbf5L,0xae279fff2eedaeb9L,0xeac9b033eed426cfL, + 0xa8488f8aa1740d49L,0x6f748bc3711b5da7L,0xbb1c46fd23bbe135L } }, + /* 35 << 350 */ + { { 0x6b2f317b9da70c21L,0xebddc2b5c99dc82dL,0xf4a85d4c5c807d1eL, + 0x47a79b298a15ad6eL,0x02afb05befbda553L,0x34f3998e6941a669L }, + { 0xa4a413fb72deac14L,0x2bd9306c1941b899L,0xae023fa5788c1db8L, + 0x38cd6c42e1012bb6L,0x77ae298c13bd860bL,0x6312af9d63bb40cbL } }, + /* 36 << 350 */ + { { 0xbb7742f370fcad48L,0x6dcce7ff57d444acL,0xfc338485b6abc122L, + 0x03c1118caaf9060bL,0x095dc123cb997905L,0x2dfe24453dd9bee4L }, + { 0x9bffbbf9d45cdcdfL,0xc5b50babb4b26fe5L,0xe985754e87d31873L, + 0xb5b007f5a503d2e0L,0xe25c4eb620bb8357L,0xb6f00e50803fa8ddL } }, + /* 37 << 350 */ + { { 0x21cab682b8035f01L,0xec82f6ae301c96c1L,0xf25d6a0c1539a503L, + 0x94180ece1e35b449L,0x13fbc96f1ede3c57L,0xe4a63eac01d8e678L }, + { 0x3d1a745c068c6886L,0x0659d6ff233be378L,0x493d7a6f3244a214L, + 0xfa852b1b772bd953L,0xbf05cc0ce87db547L,0x28f497ccb30aacf9L } }, + /* 38 << 350 */ + { { 0xa92f28b88ea312ecL,0x9c702e953a3b5f1eL,0xf0a2f787583053edL, + 0xf99506f29cb41eceL,0x4c3b00b5c2b5c214L,0x59bb943717b8d5caL }, + { 0x9ccc7869af5e6b94L,0x6eb795a7f340d02cL,0x7fc613c80a09eca5L, + 0xdac14e61d155f16eL,0xda25c7fcccadb39eL,0x160fda8c9c7fe2b3L } }, + /* 39 << 350 */ + { { 0x8aa83310312ee9dcL,0x702ad7bc2af291bfL,0x3940f883ec915c5dL, + 0xdfb7e44f6fe07c64L,0xa7af875c72d09357L,0xb5df04f4f70b766fL }, + { 0x738af1bb96f8b10bL,0xab27b86735563f8eL,0x18fccbec2ebaf570L, + 0x94e9066dc1d7d59dL,0xa1e3518dc63373e4L,0x0722fd0f22d8306fL } }, + /* 40 << 350 */ + { { 0xcd42d2391be93e28L,0x93c11fcae2ea0d1cL,0x8acd0b17345984efL, + 0x3e3feaf350905d0dL,0x4124e89a6f35b49cL,0xafdd8d27a2bae979L }, + { 0xce1e814015ad5661L,0xb0f9296dde281bc6L,0x11e93935c31ea529L, + 0x1c4c3bd7ebb898ffL,0x7cb73fc76ccc32c2L,0x69e5307da3ac9b8bL } }, + /* 41 << 350 */ + { { 0x37bec50c8e5a9a8fL,0x7f0daba5055a1aa3L,0xa56bc577a1c00a74L, + 0x0656b6aeab88258eL,0x2959237fb88f0f0fL,0xffff63bb9ef15ca9L }, + { 0xd9a2909eb94ae6c0L,0x2506a1779b304c76L,0x5658fed3abdf17c8L, + 0x9c95765e0f90cc53L,0x80ffd7b38e74dc97L,0x97e032e6b8c73479L } }, + /* 42 << 350 */ + { { 0x7073ada11780b0c7L,0x6d4ce321f35f07d8L,0x27b26ee589f35e5fL, + 0x5af10ecd324349d4L,0xf9a0a9071b9bd956L,0x5dde968571350ba0L }, + { 0x678158f5b6400a5eL,0x93764a022842e0deL,0x71a17724057c9ff8L, + 0x04c4313c72f58c63L,0x07fdf15cc4e81260L,0xd6c25e82a509f1acL } }, + /* 43 << 350 */ + { { 0x4f8a719ae3cf3138L,0x7aac7f0d9b1a2e30L,0x3fe8dcb88c0c76d0L, + 0x34afed4ade0b5be0L,0x824e043cfdf7c28eL,0x5b700afce708e71bL }, + { 0x6c7fa728eeffc50dL,0x2488eee97ca62450L,0x25490cb59d969f4eL, + 0x8bbbac3d8bd629aeL,0x7e5213b56e75e171L,0x1385bff25324b23bL } }, + /* 44 << 350 */ + { { 0x364e7371c7d996d5L,0x053390bf8cc483aaL,0x69c23cf281e948d1L, + 0x65e45d618e822ec6L,0x9240ee412ed94568L,0xe0f33912510a84cbL }, + { 0xad42eb0f6ecabdadL,0xb35afdb4bc7e39f6L,0x4ee63cb10cb50316L, + 0x7ccfa14a2a27dc3fL,0x584328f0b4141347L,0x361b2614a23cd89fL } }, + /* 45 << 350 */ + { { 0xe70edc42ee93ec36L,0xec773e52bccc99efL,0x9b0367a0ce0816e2L, + 0x43baad458c6757e4L,0x5d25fa821fb7b01aL,0x65913e86bb6bc3fbL }, + { 0xb1f1fcab67fafef2L,0xe5ffd89c9e9261cbL,0x86f7b89ff29bb205L, + 0xa76ed6722db408b5L,0xd6f1ce5cf83f53a5L,0x9cb5cd26c2882d51L } }, + /* 46 << 350 */ + { { 0x03f6ca364b2582d0L,0x70345ae80f8116e4L,0xc2612cbfc562aba3L, + 0x9cdd127789898142L,0xea7f202c02d762ccL,0xa00c15da33662a74L }, + { 0xcb5cc621aa430b63L,0x6dd1482fb1550d67L,0xb27e7df46216f063L, + 0xfffe57408f49403aL,0x9403206cfc2bc9f9L,0x132504014593a578L } }, + /* 47 << 350 */ + { { 0x6b9c67e6076b2d5bL,0x54509f61883d31d1L,0x25905831fe051be5L, + 0xe6633c1be93608f5L,0x284afa7697480e6aL,0xb124e6063a06cc65L }, + { 0xcbcb2c2e2c608edaL,0x07a39d8f813795a2L,0xf27742a8bd108bbeL, + 0x7425519005b4e5b6L,0xa27620b2b0145a3bL,0x6e3d1210c0f42782L } }, + /* 48 << 350 */ + { { 0x0eeb9dc702ed3c24L,0xe7cb624dfb39fc44L,0xded105f581d4cceeL, + 0xaa675d0c46465cc3L,0x313f4fc99af0a81bL,0xd129819f227e6a72L }, + { 0xaa6b690340b16103L,0x3dba75b2fb4c2fdfL,0xc9feeea1e7c79c2aL, + 0x14f503104e024e75L,0x3704aaa8b5729449L,0x39ac6b0c24b86accL } }, + /* 49 << 350 */ + { { 0x7e25860735214575L,0x3baa75cb068c68c2L,0x93b6a33f10be8d33L, + 0xa88f3cc11ba06b10L,0xe70e7ec2a4f8fe72L,0x32fed39fd4835710L }, + { 0x16137edf3e6059b5L,0x57b1bb9fbb064775L,0x68d3f26dac98cfccL, + 0x89339bce7f9fd53fL,0x15b32212825e946fL,0x55b0a89bf92a0ef1L } }, + /* 50 << 350 */ + { { 0xf419d9becd3eed01L,0x851b31659851492fL,0xa9ac81a9c9b0a402L, + 0xf67bdf20122c09acL,0x9b26b131f442a030L,0xf7a548f517e72d1bL }, + { 0x9e0dbf852a7f505eL,0xaa8e7348c7e93ff2L,0x4efa7877134d8017L, + 0x48f476fc13e5fb0eL,0x552d0447154f4040L,0x8d5b166569b18f6aL } }, + /* 51 << 350 */ + { { 0x65ef443e63c90cfcL,0x3a0dfb8194ed3ad4L,0x75570ba710b5547dL, + 0x5e161fa498e84064L,0xf55dc5003c576f89L,0xe46bd28c7f530eabL }, + { 0x367607400109f9c1L,0xde7a997bb15e9598L,0x25386f307593c3d7L, + 0x680e3639def120b7L,0x43fab687aa6e213eL,0xce48861daa99cf3bL } }, + /* 52 << 350 */ + { { 0x93c2cf3e53ead820L,0xfca3b3564f4444e1L,0xeb6d82bfaac7a37dL, + 0x9c0915d4cf49947cL,0x771f9f7cc7edadaaL,0x51418e487b2df679L }, + { 0xad1b249173f28cf8L,0x8fe4fb7baecacd2aL,0x539764bdb20d0b77L, + 0xb0073685a6a4f808L,0x4c6f5602cf909196L,0x1ae89342d45e9e7dL } }, + /* 53 << 350 */ + { { 0xcf8aa4e5f007985eL,0x833ea882c325d2dfL,0xc1cbaaf5f9f326e8L, + 0xe779a4a9bf906c20L,0x29f475bbc923cf15L,0x6598d52a54055b74L }, + { 0x1001a5f1e4fbd4f9L,0xb4933d56cc74cc71L,0x45c04a50fed802baL, + 0xda140558052bd04cL,0x71c127d63dfbd563L,0xef2b85ba42ebaafcL } }, + /* 54 << 350 */ + { { 0x76569e44bc325891L,0x8f8a1487fa2604afL,0x07a8bacdbc90be04L, + 0xeb53b1087b2c9bb7L,0xcfdc78aaad3c7943L,0xd74807da3bfcd779L }, + { 0x642552417189257eL,0x28138e8d23cb9584L,0x0ce0b331476b888dL, + 0x6d9ceaa0f2a9bbe5L,0xb4f1185653b872efL,0xfa9e6fb222d06df6L } }, + /* 55 << 350 */ + { { 0x0d45565ce6eabd52L,0xaca75463f41a4559L,0xc3e4064a846eb291L, + 0x22ac04bc8613d2f2L,0x74cf6fac2364ce2cL,0x61bbaca8be4fce3cL }, + { 0x302e8117b24dc7b4L,0xa72ae24dd89a053fL,0x75b2023967de96e1L, + 0xbe51cfd2a9e6d1bdL,0x807a8e3d07c9259dL,0xcf3cd92e43cf6384L } }, + /* 56 << 350 */ + { { 0xc040412c754b8669L,0xbda7e0cde2c1d3b4L,0x2ac3b3d5ba29b9beL, + 0x98a415e3f63bf3abL,0x25aee93ed1776a16L,0x46db7347ec3bc968L }, + { 0x8e44180a02612d2bL,0x4e3dc4e82db990ffL,0x2050f58f5f7705dfL, + 0x7b41f5892672d845L,0xeb301603c96e4fecL,0x66ecd24e6cb16a6eL } }, + /* 57 << 350 */ + { { 0xd428e7e3d01edc1fL,0xef608062873fadf8L,0x05e7c80d5606965eL, + 0xb818d0c6a979f826L,0xe9b4c5c7c4793537L,0x7ef637225e83bb66L }, + { 0x825d89499fbb3a85L,0x557abf0396e34cabL,0xfc3db05b8040ad0cL, + 0xbdc8e907e305204eL,0xdfc1628d1c1637e1L,0x10841d2a947a78deL } }, + /* 58 << 350 */ + { { 0x99432df309c7b138L,0x288eef14593b1fc1L,0xf47f9fb21b55f0b4L, + 0x5cc20dd46788b9a5L,0x2e87fb4605e43a77L,0x08cf86be849c700aL }, + { 0x467ec61374680ce7L,0x44e5c8d45884aff8L,0x549f2ea86b33a1a9L, + 0x2ebf696a8b4a815dL,0xc1705b152a74323aL,0x930a9fde69745934L } }, + /* 59 << 350 */ + { { 0xbb11fe102d168ee9L,0xba4aea667f39e124L,0x139364b6fca2841fL, + 0x6feef5b13d359df1L,0x4fe89fe19787be92L,0xd4cea92e0f6b6aa9L }, + { 0x794006c0039bd8f5L,0xdce0eb5b0be647abL,0xf4a97f7d4e40c1d3L, + 0x78d19059d5f7254eL,0x464ddc1d0df22d8bL,0x990b0a39e0fc7628L } }, + /* 60 << 350 */ + { { 0x72f5a0f70ad3bb67L,0xabb15e3dce6396d8L,0x2ae94788463efba7L, + 0xe77b53b41fd4c512L,0x09921a1ca88606cdL,0x1b86b75608e980eaL }, + { 0x2def667af3d22731L,0xadebd3a39641b175L,0xc0f35509045da920L, + 0x8fbf85e4952b7ca9L,0x4ee7565023517a65L,0xd31eeea30e75a4a4L } }, + /* 61 << 350 */ + { { 0x6d9a5d3cc4508650L,0xe71fcf32d1a2ac1bL,0x784b9148d62ec2dbL, + 0x9a3d5d572088946aL,0xc488178757848c00L,0x2f50a62e0875c1e9L }, + { 0xbd23d4aedec0f2dfL,0xc9c28dd5188dad0eL,0xf87ef6460977ba29L, + 0x89ce8330ab03e4d7L,0x7dbec90dbcf1a5a9L,0x3ddc39c1f6c2a4d4L } }, + /* 62 << 350 */ + { { 0x8c0518c7618b787eL,0x6f226212b95734feL,0x3e6cab90c66e138bL, + 0x6e56d68037a7c0b8L,0x67a3c7df16f6acbbL,0x43df95107921bb92L }, + { 0x967846f6a0887d25L,0xf717017766908fcbL,0x1a8ec350267430d8L, + 0xebb46f1a25855c90L,0x73eb78cb396c1714L,0xf766957cdc081e43L } }, + /* 63 << 350 */ + { { 0x0700da846de27e73L,0xfac9dcfd78c35563L,0x01af330ccd073b09L, + 0x0bf5c3b1bb784ceeL,0xd3d9a9ff5d465498L,0x4836b065bde8bafbL }, + { 0xf5bf3316329b4cf5L,0x387388fc54a5275fL,0x73e880d8254af26eL, + 0x07ebcddc8d05311dL,0xe8b9965a4f46cec2L,0x4f07a4fa01b06069L } }, + /* 64 << 350 */ + { { 0xc0a40cac52133095L,0xfe1b22fd93c162bbL,0x8625898c34018741L, + 0x69c9f3f636d9e57aL,0x69d9d7f3378aa211L,0x6b03f897e7dca168L }, + { 0x24d49aebf997a48fL,0x1d984c67c149ac40L,0x667c1d01576f533fL, + 0x372eee199ef82eceL,0x577723c0c207c14dL,0x4225907a0eed37f6L } }, + /* 0 << 357 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 357 */ + { { 0xc61db977bc0e0903L,0xbaf6e4da645c32fbL,0xce89b8ca060b1adbL, + 0x41db448188e2c178L,0xba6339f3923bdd3cL,0xff25b818d29db42cL }, + { 0x3521116ee6d6b35dL,0x4e1bd283b22f16acL,0x9357c984bd79fe5dL, + 0x2eda73be9d45eee4L,0x1a50c59f6288e01fL,0x37baf64975018873L } }, + /* 2 << 357 */ + { { 0xc552c6c6097f322fL,0xdf59a3028bc06287L,0xc9ed375c19610b0cL, + 0xf0e7b4ebb051dad5L,0x7267a304c6556643L,0x0044f6d8c96dc1d8L }, + { 0xf0ed5f9af4fc3725L,0xbbaf9f2c9de8e1ffL,0xef5d66f4af5a4b4bL, + 0x0b5bed3d20644cf2L,0xf7e4543a75ae23c0L,0x696f60dc41325b66L } }, + /* 3 << 357 */ + { { 0x9949b33d2c20f868L,0xdb3aa790b5706250L,0x88ce71e788e17f2bL, + 0xd851baf2da9c0881L,0xe869c5ba86d8c9e9L,0x1af68d65a01425b6L }, + { 0xeae8b1c69bbd3963L,0xf34900b1ec087425L,0x14942910c374bb96L, + 0x3e13c45705487483L,0xe0e6fad435bc6ee1L,0xc7c38dc7b54d247bL } }, + /* 4 << 357 */ + { { 0x6d34bdf6ab463fa6L,0x7bb127b60093b9cbL,0x61d051135a3bfdd0L, + 0x4abab575f1296bddL,0x72da68494d2e9a7cL,0x90267bca8d11f03dL }, + { 0x478111223e9b310bL,0x8ffe91d31b1920cdL,0xec293ec67521898eL, + 0xf0cf026996c1da75L,0xb0dbd4c380f2c7b3L,0xe528175534e4baf8L } }, + /* 5 << 357 */ + { { 0x7ce1ce36189e2f1bL,0x36ca8fe3fa84ca41L,0x54cc2c13a6a568e4L, + 0x1967d9ed25a6d223L,0xf8d20c88537252afL,0x5a58936cac3d697cL }, + { 0xa2659671b0084ffeL,0x08a9e041ec25bb0eL,0x6bd405ed4074ccedL, + 0xaeebb470dacb5503L,0x6f18e32bd5448d3eL,0x0412973ba94cd45dL } }, + /* 6 << 357 */ + { { 0xd72fcc3742fb1cd7L,0xadfb8967c49c359dL,0x6dc988a55935bb0dL, + 0x3fb10981e3080802L,0x12c4494f3be161ceL,0x5a0e22d44b649dd0L }, + { 0x5c57cbfd62a85259L,0x7ad55b3c0e5ab7a2L,0xcd53564928de30e7L, + 0xce35e6e76867e6a7L,0x626810562f6716fbL,0xd8b4ff26a88d3bf8L } }, + /* 7 << 357 */ + { { 0x5949ddfa53abe7a9L,0x944a2ae0716f63a6L,0x90961922675d1f43L, + 0x36c41c12f5b55722L,0x85b8250f7782775eL,0x89a3a733748663beL }, + { 0xd4358450475d2d88L,0x4183f45e1beef8adL,0xee3bfe8b06ec8d58L, + 0x2e462b1609cc4d82L,0xf9cc307ec6148e1dL,0x70d3b2f77b1281a3L } }, + /* 8 << 357 */ + { { 0xc32730e8dd14d47eL,0xcdc1fd42c0f01e0fL,0x2bacfdbf3f5cd846L, + 0x45f364167272d4ddL,0xdd813a795eb75776L,0xb57885e450997be2L }, + { 0xda054e2bdb8c9829L,0x4161d820aab5a594L,0x4c428f31026116a3L, + 0x372af9a0dcd85e91L,0xfda6e903673adc2dL,0x4526b8aca8db59e6L } }, + /* 9 << 357 */ + { { 0xf0467111e854f886L,0xe228021d8dc6117fL,0x07ff954cac432e28L, + 0x373be2ef31d9b69bL,0xaa214d016fd61f0aL,0x27bb7932f950b029L }, + { 0x1caa914f967c97f0L,0xfb133ec0d548897dL,0x598514173cfad251L, + 0xd41d1da432d14208L,0x446c79f2cee424ceL,0x8b5272a175e839a5L } }, + /* 10 << 357 */ + { { 0x26b5e85d62f50c12L,0x8418cecf5ff562d5L,0x0d35b4d459be698eL, + 0xd79ca9ee93730d2eL,0x2414d99325627fe5L,0xe31dc5293fc64803L }, + { 0x5c9100d60d027a12L,0x9004ee36f2208db5L,0xe734b13b135d02bdL, + 0xf905c01a7bc09b60L,0x4eb51557b21b68fdL,0xe6e98bea8c583359L } }, + /* 11 << 357 */ + { { 0x14dbcf1a61dae7e6L,0x559a7b52ea0da075L,0x7391545d439d10d6L, + 0x187e00e675e617abL,0x453b546b5142355dL,0x9bdbddbc84bca97aL }, + { 0x742a699591e5035dL,0xcf86d3e1831209ddL,0x6fb66757f5f2a999L, + 0x2e360aeff0e71f2dL,0x6c6f71f2dc97114aL,0xef686b8b17c3a3dcL } }, + /* 12 << 357 */ + { { 0x7d07a61d13b5ea74L,0x7f4b7157c8afecd9L,0xefce9c89820b0298L, + 0xe85c4510e3888d59L,0x9cd3352001234b9cL,0xba2692c0fef767e8L }, + { 0xd2bea3d45b3ca353L,0x9ad478e5b51a704aL,0x1fc9bd0d9426f25bL, + 0x52f930bf864a1ba4L,0x559f36353765ff27L,0x548c7f0dae28479fL } }, + /* 13 << 357 */ + { { 0x6296d54f68b0df62L,0xace420ee9e6afdd4L,0xa20a510dfcd1812fL, + 0x488f113a8cd04a29L,0x1bee07640765cb70L,0x50bb5c446d0f44e5L }, + { 0x5ea842cb7e320ebfL,0xa6e0c1e6e795a7fbL,0x89cd1f765e7e79c9L, + 0x7436ec1e87ce6c5dL,0x1376222de28309f9L,0x9ed7d6fb7f01548aL } }, + /* 14 << 357 */ + { { 0x32e9740ae2fb0467L,0x3a7a32b3ec039d67L,0x630d8d346a425a7cL, + 0xc9af74ae418a7dd0L,0xc903576daf502870L,0x7e02b3b7e98cce5dL }, + { 0x0bfdee7a158f005bL,0x88eff4a363b91d59L,0xf23079728bfe3ed3L, + 0xc75536bce6b1fb4cL,0xf61a82e1a04d46fbL,0x771a8fedfddd52a5L } }, + /* 15 << 357 */ + { { 0xf5efc82065af5b94L,0xd618a9e8ce5535a2L,0x70cfb112cda6249cL, + 0x6986f00f9f217280L,0x41e46ce605faa951L,0x2abb39f3a3ad613cL }, + { 0x3e04b28b07671c94L,0x61d323ac53cdaf80L,0x2389875cbb9580f8L, + 0x64800835febb0b34L,0xdaebba99d0d21027L,0x0f1cebfc23288a7fL } }, + /* 16 << 357 */ + { { 0x51a033a5cecb916fL,0x2ac62f638d7de61cL,0x92eece49a42a266eL, + 0x87e037db82c4d11eL,0x875be1416fbae08aL,0xf348fe26c539478cL }, + { 0x51f8b907ff94c01eL,0xc46cc0e019695a9dL,0x2c74bd666c51b9c2L, + 0x635d3d24ee565de8L,0x6bd656638982c8c3L,0x5c345b79daf6a93cL } }, + /* 17 << 357 */ + { { 0xee7265ee93f081dcL,0xe8f90a6be03493f4L,0x4e8d10275328b0b8L, + 0x13bb82bb96fa0930L,0x764c2915d1f7d5a7L,0x1896c78f73476481L }, + { 0xe9a34ff267873b76L,0x8a9a719cfa0afda4L,0xce93d4cc9ccb715aL, + 0x9ba00f011495d1ffL,0x3131e6666df0e119L,0xe68e1815c902ac6bL } }, + /* 18 << 357 */ + { { 0x0ce4ae1044f4a2dbL,0xa8645e2310bcc5c6L,0x6d9728b5e489762fL, + 0xd365c12a9d46ad88L,0xedf484fee1a527aeL,0xfdf5c519e5be2bb1L }, + { 0x4706cc2870a3d4e3L,0x07c60129065f1506L,0x42e2e16478298553L, + 0xa56a2bd5bae646dbL,0x893bf45c61437e62L,0x97dbf9266c525900L } }, + /* 19 << 357 */ + { { 0x65c56764b52213c3L,0xa171ba9d97aefe9aL,0x5904e8c934336916L, + 0x727209b6ff187f05L,0xaf4e50525cb68a5bL,0xb46a6abadc4319feL }, + { 0xfd48d0d57890cd90L,0x5b0b68c7252942daL,0xc41023352b01887bL, + 0x582251eb5ad09a7dL,0xbd79b557e1312726L,0x9f5ee3788057db5cL } }, + /* 20 << 357 */ + { { 0xa30486a6666fdcc5L,0x5cb7f7ce84056f89L,0x0f8a6b96505636a5L, + 0xfeafdf97c6624ce2L,0x9dade91c55b8a7d6L,0x3d009219ca2b459fL }, + { 0x483549845a969337L,0x37d57cbd323c09adL,0x32a91e91e74b9e74L, + 0xdb4f18ff1c317c24L,0xf9f0daf342418667L,0x735a1eb946946667L } }, + /* 21 << 357 */ + { { 0xb395bfd1c8eaa54bL,0x8181d6262ee25219L,0xf4bf437b38d912f1L, + 0xf9f1161228a8b32eL,0xe359adacc2be5c61L,0x71557ea2971b60c9L }, + { 0xf071404b1b00cf1eL,0xb163c3608da3141fL,0xd9dedc07a8d51d98L, + 0x29e89ac5ac827b74L,0xc38cef633ef35dfbL,0x9abd281097d477f1L } }, + /* 22 << 357 */ + { { 0xb34e560f0e6d9646L,0x4fc05a0dc0ba033fL,0xc9f5e040ddc1bcc8L, + 0xf723b78ab92068cbL,0xd558f5912b5c7030L,0xb16bdec774ed778bL }, + { 0xc12aacc3b32980e0L,0x856e90411daaa32cL,0x34f7a28596429db4L, + 0xcc2c61ea415dcd04L,0xa0e192cb46b7d996L,0x5b7c845d55d87ce9L } }, + /* 23 << 357 */ + { { 0x9ba0a26fc0ee684eL,0x1b871ac353573254L,0x76a094bc5783e706L, + 0xe78bea66dcc01e8fL,0x7e20c5aedfb74e56L,0xbdc5314a8710f0e6L }, + { 0x2bcc7a0085f2233aL,0xc58dd45b8aba1575L,0xdd1c6b78e411b6d8L, + 0xbb8d19529d23d2eaL,0x5293f3cc0066c9cbL,0xb7d0d7b0249c6d93L } }, + /* 24 << 357 */ + { { 0x68fe359de23a8472L,0x43eb12bd4ce3c101L,0x0ec652c3fc704935L, + 0x1eeff1f952e4e22dL,0xba6777cb083e3adaL,0xab52d7dc8befc871L }, + { 0x4ede689f497cbd59L,0xc8ae42b927577dd9L,0xe0f080517ab83c27L, + 0x1f3d5f252c8c1f48L,0x57991607af241aacL,0xc4458b0ab8a337e0L } }, + /* 25 << 357 */ + { { 0x614c4bc273041ddfL,0x4fef1cf6364135aaL,0x2c9ac204ecf0e610L, + 0x75a302a991a6dce1L,0xa5899c96651ec9f9L,0x6c5384f64bcad1a6L }, + { 0xa41012e560f705ebL,0xfcf6512235e85d67L,0x2fdcfc235ced3638L, + 0xf834fac02deac34aL,0xf5a64ec510a8ad80L,0x843855e1a412c4feL } }, + /* 26 << 357 */ + { { 0x440dfebd76ca517aL,0x79924057c577eb59L,0xf1aea290d038a921L, + 0x77afb37fb0c95974L,0x48a5b9a715763d44L,0x713de85155c8683eL }, + { 0x250e8f8239d7e1deL,0xc5f1f61c8a2c846bL,0xf26ea6f9faafd017L, + 0x8ad26055f9d7cd35L,0xc980ba773b2df598L,0xe23b7eabd5e299a3L } }, + /* 27 << 357 */ + { { 0x5d37811464744605L,0xfab096990278c1f0L,0xc4d32b208448c344L, + 0x767a24d2d7d1df17L,0x842de148773ea0fdL,0x73d7dfbdff6e40b4L }, + { 0x3d61439283576d1cL,0x4820c435ec865519L,0xf99e84dd6bfa5e48L, + 0xeb18687a9d0d2adcL,0xc3b7369da7fd75d2L,0x7e332b5739f5f093L } }, + /* 28 << 357 */ + { { 0x0796a8b6ec13d2acL,0x19036c255677347dL,0x2f0d36eef527c827L, + 0x7c8a3d17ca61ed60L,0x3920bc68748cf7c2L,0x61835bdf9018b300L }, + { 0x9cf595c1689d5826L,0xdc547999fb51aea5L,0x11bb04120fc297c6L, + 0x88770df2b2f9fe0eL,0x99e031f5f6856a85L,0xbb59e8c7afe29c50L } }, + /* 29 << 357 */ + { { 0x714e784820dfc5f8L,0x35cde8ae2a2265bcL,0xf6b29ce4bfc32fecL, + 0xbd5e91f1918043a5L,0xd3766f8b60f8c218L,0x273c41935298904cL }, + { 0x0a76492d5d441fb5L,0x99cb3b1d164d9275L,0xb2be87c80ac7935eL, + 0xbd1a1b3f0962981bL,0x8a0c207b96d0df2dL,0x1bb1e505929752d9L } }, + /* 30 << 357 */ + { { 0xa574de94621b2705L,0x0d0ca1b73e3f2227L,0xbdc9ddf2e49bc2d8L, + 0xfbc7254309d314f0L,0xf5900cbb827e0b1dL,0x3994eadd8a7e8164L }, + { 0x2e7949793046f170L,0xde21ddc3c6883cc6L,0x9ea19d34bcd40da7L, + 0xb4334df8f01a9ae5L,0x801496ebce8c53c7L,0xc2a5e8527a4b0601L } }, + /* 31 << 357 */ + { { 0x435a6c512ecf62d2L,0x757cd8f6559a6a0cL,0x47833f815e4c0d40L, + 0x2d0b48047d960c6aL,0xf5474833473d5eb3L,0x70264154bf756b52L }, + { 0xcc46e58d940bfb7cL,0x2e0dd3a69c89d48aL,0x483f3ee19387df66L, + 0xb3097da4585d3600L,0x82d64b4d76411ef9L,0x0df7d95719682e87L } }, + /* 32 << 357 */ + { { 0x179c59cf210c3144L,0xfb613c5733eebbc4L,0xdda75cfdba0cf384L, + 0x94081a5b3a8fbafaL,0xb91de90a33384e0bL,0x7d1f8f4027aa2a45L }, + { 0x0747bcc162031148L,0xd2db8e39f324160bL,0x9c1ce3e9722484f0L, + 0x13a7ee5da62d1ddaL,0x77fd79343a963bceL,0xcd3d871783d2f21bL } }, + /* 33 << 357 */ + { { 0xc7c8eedc93a27196L,0x0832b0dfa8abe585L,0x31fe11e8d8adfb86L, + 0x1091601e9d50e4c7L,0x7931a284ac3d2ca4L,0x0f1464b6f3fc6641L }, + { 0x2ead94f3260f29a7L,0x914b8396d88a7696L,0x950be4bbe73d807dL, + 0x26d0115e5b3ad83dL,0x3de8a73146c22525L,0xe50825dac5fffff1L } }, + /* 34 << 357 */ + { { 0x716378cae4b98aa8L,0xacf8d67b59b746a9L,0x78f0b5eca65ce8ebL, + 0xe5997983523cfa35L,0x85bf5badbeba89e3L,0xc8052bbfcfd73b41L }, + { 0x0b3d77139fb311a3L,0x821a20e2d96f696fL,0x0f087e5744657c9aL, + 0x72031f281ecfea36L,0xd0765f333f32b010L,0x0412c69929c48643L } }, + /* 35 << 357 */ + { { 0x53d361b89f501481L,0x8970937717153c6fL,0xb52280b916bb8d8cL, + 0x5985cdc0b33dabd6L,0x35ba0cd9dca8ae72L,0xf55c6e7301bc4efdL }, + { 0x2106ed2f269577c4L,0x4cc34291bfe765b4L,0x9f4168ea812eb958L, + 0x02869228999ba5cdL,0xff91540d3ab27498L,0x9020e6e158e55a79L } }, + /* 36 << 357 */ + { { 0x1a5b15377f1c7cbdL,0x5b31930b7cc17c56L,0x5b91e1a492cc8cf5L, + 0x970e43deeca08bdeL,0x36424bfe0e2e963bL,0x2e49534968b1a489L }, + { 0xe350ca52d8e85a9aL,0x3cb9f599ae2cdd7cL,0x0ff35a0aa83215ecL, + 0x64cf57b81973a966L,0x128be6cd36b26702L,0x8067afbd5f65f7bdL } }, + /* 37 << 357 */ + { { 0x23d1f49215876c71L,0xafb21c1d41e7495bL,0xdb3ab62c2705885dL, + 0x20ff803f7ba216cdL,0x26cb190699c9ee55L,0x8280dc9c0fb05389L }, + { 0xadf55171df1020dfL,0xc044e9bcbd011b5cL,0xe21aaa60cbed2430L, + 0x5939fe583336df4dL,0xfa306816ff78c665L,0xba92ca8243eb18f2L } }, + /* 38 << 357 */ + { { 0x6f05e6241b7edb64L,0xc280105b6681f48fL,0xd1b94413f993dc9eL, + 0x84f24c01e46de412L,0x092017d54abbf7dbL,0xb73193a56f7b1b08L }, + { 0x22a7c5765195ae46L,0x81dd6b12610c28efL,0x61959874ad7bfcc1L, + 0x3ade0a77d15f8cf9L,0x124cef4d954db624L,0x0733bd7a5c247650L } }, + /* 39 << 357 */ + { { 0x52d7f9ddf1cee098L,0x538b7fa17a6a2ad1L,0x5f2294312911e75aL, + 0x71c337b7e6ef0271L,0x5e278a1267ee72d1L,0x7b348c756f33fea9L }, + { 0x7bb59f1a694bb928L,0x5783e43f292b258aL,0xe3b53ca77181f1d2L, + 0x028ba90e051c7d2eL,0x4bb06f9364789d76L,0xcf97fc4da228a7a7L } }, + /* 40 << 357 */ + { { 0x3dbb3fa651dd1ba9L,0xe53c1c4d545e960bL,0x35ac6574793ce803L, + 0xb2697dc783dbce4fL,0xe35c5bf2e13cf6b0L,0x35034280b0c4a164L }, + { 0xaa490908d9c0d3c1L,0x2cce614dcb4d2e90L,0xf646e96c54d504e4L, + 0xd74e7541b73310a3L,0xead7159618bde5daL,0x96e7f4a8aa09aef7L } }, + /* 41 << 357 */ + { { 0xdf5c2fa79111caacL,0x493ada25b04d2b3aL,0x5c4850bfa39a7872L, + 0xbeae16c067e07e93L,0x63bd7d390178358dL,0x7a7e56a1cfe0bcd0L }, + { 0x9ba7a4500816b666L,0xea6c70c8dae070dfL,0x84013756832c2b35L, + 0xa28e5dd08d3e9fc3L,0xd67665aac653c08fL,0xee54d7b6aa6bdff8L } }, + /* 42 << 357 */ + { { 0x99b870afadbd24baL,0xb34fa9083bee289fL,0x4a20f29bae836fa4L, + 0x4188ed5024b464c3L,0xfb93f48fc6c00297L,0x334b8689736186ecL }, + { 0xbf7f1c424e1016f1L,0xf95e6e59413ca088L,0x5878156c288912d8L, + 0x9e99199704c7ce69L,0x0f0c185d5d6520d1L,0x1ed2ece33fe6f498L } }, + /* 43 << 357 */ + { { 0x319fb249607cfd40L,0x5920056f62b40e28L,0x9ab4528058631ab5L, + 0xb527738f413452d2L,0xb2885e46b296e602L,0xb1dcf41a74824807L }, + { 0xca9d2b06b2ad2fc6L,0x500c5f11ad05eeceL,0xca94160f21f3db6aL, + 0x693adf4e262470d6L,0x1f4c62c5480b0cffL,0xb3ebf11f54c748e4L } }, + /* 44 << 357 */ + { { 0xc8ae4d2bb4ef93b3L,0x4967da7b99758d99L,0xd1483a1fe04db9baL, + 0xf5e657df3033474dL,0xdd9371c89db4b96fL,0xb5f288956044b259L }, + { 0xe8987a43b2ec27bdL,0xaabb1ae68fce67bcL,0x4518fa3eb2b97680L, + 0xa0142a13748591e1L,0xf9148ab96c2db557L,0x65592253e0e4f9e7L } }, + /* 45 << 357 */ + { { 0x21163809bccf41d8L,0x0eafed515b3f09d1L,0x3b5360d9d84b27f6L, + 0xee752fd04411d37aL,0x1cea3b5c6a3f5027L,0xb206e74d9454d9f6L }, + { 0x710715dab52af43dL,0x8175ca136e6c6463L,0xbdb123d39689144dL, + 0x569e6edd4d9c459fL,0x070f09a4f02e5b25L,0x691c23ef3d79a7b9L } }, + /* 46 << 357 */ + { { 0xc0c94165781356cbL,0xcb9fb705876a839bL,0xfe23f07e89db25feL, + 0x710f0fa3a52cec3bL,0xb0ab363073e0f037L,0x3b79a8167c9aa037L }, + { 0xdbc7f83ca1f13fe1L,0x8bd910c63d653a81L,0x2e54ad408c78d003L, + 0x0de02157a3e9ccf0L,0xe9081e8bf7670dfbL,0x6a2ad476c8647bc8L } }, + /* 47 << 357 */ + { { 0xaf58106ebf047836L,0xadc3245e195e5675L,0x75612e175290e051L, + 0x27b81bd869d46bb9L,0x9d4dad5b5417b5faL,0x19850d70fd024259L }, + { 0x987daa604b0a86b5L,0x5d5a5f9c0358a944L,0x9008682f48d2ff67L, + 0xc9db4d4b89e81cf9L,0x133516bc850eaae4L,0x0b5bfdc81da8bd19L } }, + /* 48 << 357 */ + { { 0x609deb162d8bcd6eL,0xe42f23a92591750dL,0x4a9f3132b378305cL, + 0xf101799869275f5eL,0x14be746761b089b5L,0x05f620d20c81b0c5L }, + { 0xca90a9c06cb8412eL,0xfe0f6a8915b1b0d5L,0x1b25ac9620c71988L, + 0xb971b61a390aedd0L,0x995214d779d8cd39L,0xd7fa135b65c6e11aL } }, + /* 49 << 357 */ + { { 0x5aaa98f875330325L,0xc900a7781f3541a6L,0x69bcf864174a3200L, + 0x3abc5ef71c46b3e2L,0xa53c9e4e47851b97L,0xc166a4e22acdc42eL }, + { 0x49e4e6fdb19b4678L,0x4fe02cb162b7da19L,0x575c61a6633153feL, + 0x49578b28a4f83b70L,0xc6840d063737532cL,0x93047d40480f55b9L } }, + /* 50 << 357 */ + { { 0x835be7417d930332L,0xa4d001bb2cd86fc4L,0xef141e30a6e3a24dL, + 0x4047620adc328d2eL,0x5c80a3bc9a5f1f12L,0x6cde5e4ca19b423cL }, + { 0xcdd5d7773ba0fa5cL,0xb96dbe62ea85c28eL,0x963c02245c804896L, + 0xb2a581abe5dd6b98L,0x28a908a2abc8dac4L,0x5834b212985fd18fL } }, + /* 51 << 357 */ + { { 0x02757b1f0fbe0c5dL,0x2d0d05a854ef99e2L,0x2bda526d0377ffa0L, + 0x58ca8b08925985afL,0x1fb7dbe727b69722L,0x322d7db5f1c57fe5L }, + { 0x4049c8bcfdf111f3L,0x0b4712974148b027L,0x34fcb1e58782dab0L, + 0x697dc9431665557cL,0x3ae30e2844659ba2L,0x479dbc2f118e7417L } }, + /* 52 << 357 */ + { { 0x10b10d86227e8607L,0xe83536281d1be36aL,0xe34068f9d952b0e9L, + 0x148eeb38fdb6ea99L,0x82657d605547e7ebL,0x9c35dc82a86155eeL }, + { 0x408f79262060a81aL,0xf2a79205a6282e8aL,0x10dbb58526e70e7cL, + 0xd636f8225df85d6cL,0x03202c027682b922L,0x31323940baf18500L } }, + /* 53 << 357 */ + { { 0x5882374401879796L,0x068943ccd1249281L,0x20dec1c12e1d6effL, + 0x5f4c2c070bdddecdL,0xc56d52b37ee724c3L,0x93bc2c7a559e25ddL }, + { 0x0c95d2e5f98a9940L,0xc570e96ada60a809L,0x94c4a964076233eeL, + 0x843c99627dbbc526L,0xe4075129d4cdc652L,0x0afff70561cb2698L } }, + /* 54 << 357 */ + { { 0x3ec1e3a5f607f893L,0xd476dd24054aaa8cL,0x2cb92280a93488abL, + 0xc8d1207710d1dc68L,0x564839b9bfb494e6L,0x7a13930ceabdfe56L }, + { 0x52f72a9724f9b183L,0x30ae4bc87e9c6fc3L,0x3d7d2765f35b8e6cL, + 0x701f3d89a665ba55L,0x98f2fe85c466111bL,0x338073600c1c0dadL } }, + /* 55 << 357 */ + { { 0x7dd106bab3a48d42L,0x7eac4690ebfc75aeL,0xdbf3547e68ef4ea3L, + 0x3629c438a1a5faa2L,0xac2aa55e653bfd97L,0xae5cc39752c3b8f9L }, + { 0x117380552853b626L,0xd5a955f224a0dfe2L,0xc4356ca25940233eL, + 0x73f7eda97994aedfL,0x2bfa76c693b185d9L,0x091cef91a0327108L } }, + /* 56 << 357 */ + { { 0xa8393a245d6e5f48L,0x2c8d7ea2f9175ce8L,0xd8824e0255a20268L, + 0x9dd9a272a446bcc6L,0xc929cded5351499bL,0xea5ad9eccfe76535L }, + { 0x26f3d7d9dc32d001L,0x51c3be8343eb9689L,0x91fdcc06759e6ddbL, + 0xac2e1904e302b891L,0xad25c645c207e1f7L,0x28a70f0dab3deb4aL } }, + /* 57 << 357 */ + { { 0xf5dafec85f102704L,0x2f3b6b6929f5b946L,0x84472c029d4c9979L, + 0xed49f3e6341f0150L,0x3ee3432eb3bb085fL,0x84c553183cbac42eL }, + { 0xbb358bd9dc4c7ffaL,0x0713917d2db356ccL,0xc73e9fd0670c7139L, + 0x87600c4c3581108eL,0x2ae731d7586af51dL,0x30630ad6614c126eL } }, + /* 58 << 357 */ + { { 0x15f8fba7712c0edfL,0x4a1f93baa2c363ceL,0xfabca37e8f2948a4L, + 0x652922e4dd765560L,0x2da78559220cb98bL,0xb797746a54b940c4L }, + { 0x8535fcfc591bb7faL,0x58857815c25376e3L,0xcd8db789da627557L, + 0x718072ca318512b7L,0x92266469813efd94L,0x3217649aafa85382L } }, + /* 59 << 357 */ + { { 0xd517b39e51c4bf28L,0x6614c16261f583a3L,0x79c72f414739ea59L, + 0x597e1c2ff76e80f8L,0x3a72b05e7b846f3aL,0x1849e5126c0a45a2L }, + { 0x79a6ea5b9d506d83L,0xc48e570219b7f46eL,0xc89c5047c524bb48L, + 0xafc1fdd99cb88cfdL,0xb07eaaa0b82056e6L,0x60f6544f05885df8L } }, + /* 60 << 357 */ + { { 0x9894ef75f39e2738L,0xac585d07b40db6ecL,0x07d9e938c4cfdb92L, + 0xda174933737f1a7fL,0xa4f1fb65484031a6L,0xa96d9f612c21b546L }, + { 0xaf981519d24ccee0L,0x238de6de9d53b571L,0x09afc481fd78c3ffL, + 0x4351715d9ea7f6fbL,0x91a02325b14a7320L,0xcd8958d8bbb6346aL } }, + /* 61 << 357 */ + { { 0x22ef4217452ae6a0L,0x3192309d9ced837aL,0x773585ed2ba43ee9L, + 0xa9b29d94f3379e81L,0x43838b3aa6835e44L,0x1afe27ab0c7b2336L }, + { 0xca1dc61683ecd230L,0xc9e8b95e6d235df5L,0x9667829b2af11adeL, + 0x27254b0fbe532148L,0xb50bc3c86d233f14L,0x30e0e450bb35d985L } }, + /* 62 << 357 */ + { { 0x8b3f79087b95cf32L,0x67c654b06272c619L,0x61160a9d22c0f46eL, + 0x1cce95721d2e36ccL,0x62bd951d3990db3cL,0xcf0005c8d9700d14L }, + { 0x304aff9c70116120L,0x1c919dd2b08d57ceL,0x841b058ec0c0c0b0L, + 0x7cfd4deb7af05aa2L,0x4fbd13c57b11ce5bL,0x03e07dc9f8259bebL } }, + /* 63 << 357 */ + { { 0xe9b37f569d0703e0L,0x7b5e0df5f83c215bL,0x7fbb40f0d3c21efcL, + 0x87a2ff119fb33620L,0x208b062bd1176635L,0x806bc549950d30efL }, + { 0x862de3a4ae2bf355L,0x917b06bacf9ef6e8L,0x55f1ec4cadacc178L, + 0xbcd679fc81d752fbL,0x9404d6ce65a00270L,0x25ce99e6000c6e1fL } }, + /* 64 << 357 */ + { { 0xa13f19b40f3ff12dL,0x57ee08b1019564aaL,0x00ec0c997044a6f4L, + 0xaf5665f8dca1075cL,0xded5ca3f0620ab0cL,0x9b2cb8c7a896deffL }, + { 0x032ab2b307df2345L,0x964d109ef1da3f88L,0x2286b6f725133304L, + 0x0d16d531977a4567L,0x00a66036f1abae4fL,0x5debab1d95f0103bL } }, + /* 0 << 364 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 364 */ + { { 0xf2cdae3196230a58L,0x47cf36b4f304e1eaL,0x9d14f25ad750b29bL, + 0x931b9c65dba15f3eL,0x34db169ebf9fe2ddL,0x8a89e47c52663433L }, + { 0x8859a4f8026ec31fL,0xeeb703eaa913ceeaL,0x74638d6a67ac4db7L, + 0x5c8ea7b2be25d755L,0x8a0f0a8738db10eeL,0x96a26bace890bcd3L } }, + /* 2 << 364 */ + { { 0x883533af64a5e869L,0xaaa778c26973ec23L,0x8f0b5fb546d0fcf3L, + 0x7e6b0a0a4ab05da7L,0xcd91a869c67b6614L,0x7de9f2ff6c6f7cf2L }, + { 0xc072a106d1ec14c3L,0x3f4b960642a128eeL,0x7378192c8f0ce946L, + 0xdf2e7b9fd1149441L,0x4fa17cb614ccf45aL,0x575680e945f03568L } }, + /* 3 << 364 */ + { { 0x0f4ca7803374f910L,0x5948ae98fedc5b5bL,0x4873625b4ef805afL, + 0xbddba22fc015c586L,0x7091b50aa41a8c93L,0x721dd3384c005f42L }, + { 0xf43d37462065f41dL,0xd16bae3e172512b3L,0x3efca10c8277068fL, + 0xd0c25d7b77513f00L,0xc0015cc12dc3af9bL,0xdf11a4ec94c6cadaL } }, + /* 4 << 364 */ + { { 0x8b70e94f8f458c68L,0x292726544160ecc7L,0xe22219ba4d3ef22fL, + 0x7f8a712a1999f948L,0x25575e96abfe7302L,0x21c6ffc6564a1af0L }, + { 0x045e9c667e8500daL,0xef7c3cf704ef8ea6L,0xdd23b825c3db161aL, + 0x05fb173aba33a906L,0x9a8b5ecb870e41f2L,0xf3d9db0bccc30d1dL } }, + /* 5 << 364 */ + { { 0xbed7d94ca1bf2c8cL,0xbb7f437cb8b719ddL,0x65416af6106834bfL, + 0xdade8a144c4f7448L,0x62227a1d881dfc06L,0x37bc7de58dc2b7bcL }, + { 0x4f11541712ce030bL,0x72439d8ac2a9e0d6L,0x98cc53aba0f1b961L, + 0x2f68011d48b0ec8eL,0x4bbc34679c72d034L,0x0320c1469c576e38L } }, + /* 6 << 364 */ + { { 0xd9243926e873ff0fL,0x2e2a5ab6f20b0e49L,0xa1bcfeee0e35f201L, + 0xd25be5f3196f23f3L,0x298c67f2ffc1d068L,0x77dae55c0c3d950bL }, + { 0x5e15ab998822c996L,0x52de2e6d83f60a98L,0xa9f82ec947a7e269L, + 0xf02af9a22ac22e49L,0xdfb3103fa706f090L,0x125599623cf8dcb0L } }, + /* 7 << 364 */ + { { 0x9f5f44fa666e278fL,0x53c88803f5582c78L,0xd7e8f258f9627f9cL, + 0x22499dc938fd51bdL,0xa9d7497c846a4a79L,0x791b8ead026ae250L }, + { 0x84d47d19db15ff63L,0xb58a82c0267b44b5L,0x9b2f138806a52e30L, + 0x3fc8da027f08953fL,0x22d074d292fcac08L,0xb9c7c3db701d73fcL } }, + /* 8 << 364 */ + { { 0xb7b8562588ad12b2L,0x81f5958b1e44b254L,0xb4ebddd5c91b8ffdL, + 0xef815ae155d38511L,0x98587d551b0da525L,0x1d41817734a9ebbdL }, + { 0x844811fb1e6057d7L,0x0c16977176e5976dL,0x4b268bb4f623789bL, + 0xb26ae5be40498058L,0xb47a5ded3c2b435aL,0xe15a684b8fceceb3L } }, + /* 9 << 364 */ + { { 0xd55407583353db48L,0x0e334ccac0c0b5e9L,0x679a935f270c48d3L, + 0x170693e436ef0e90L,0xc72fb12f9de59023L,0xaae13a0e9371697cL }, + { 0xe98ed704d8d56e4dL,0xc6de5384eb71f091L,0xba63adccc6d905a8L, + 0xc84e614d66e40dd4L,0x15dcf1a3fa0f55e3L,0x4e26ee3af157c7a1L } }, + /* 10 << 364 */ + { { 0x122a3eedd09dc3c8L,0x6a19907faefe0819L,0x057aafa1da325339L, + 0x138033bdd42a5345L,0x8ac206af1a065ebeL,0x0a46f5ae25c31ed6L }, + { 0x7fc577a9d7e379dbL,0xc6df694369dcee54L,0x4c167ba2a8336bc1L, + 0x0fbd9708f3a1339cL,0xc6b8c01f226f612fL,0x5d4ed789d51332e1L } }, + /* 11 << 364 */ + { { 0x67ead4e0f6a40814L,0x42fe051ca2ec9ae1L,0xc09f84395eba62cdL, + 0x7bb5ba0c9d8e7305L,0x85962d0db46f81abL,0xc7183752628b18ebL }, + { 0x7a1f023edf58ec0cL,0xf21bfdbaab6535dfL,0x12add590801d2481L, + 0x1fccd1e37a11520aL,0xf83caddd6fa8f8e2L,0x99e7256c24e58433L } }, + /* 12 << 364 */ + { { 0x26aa2c2e5a1abcd8L,0x2b16a12e9609d9d8L,0xe485a551a2bee00cL, + 0xfa28c30bf4f2292eL,0x99abef78b7358f1bL,0xda6b3cdf10a276a1L }, + { 0xbd3858b747c03f71L,0x4f0bf5f0b22d05d1L,0x2d80f5d28250f760L, + 0x060f9b278cd9666cL,0x6a6c40b0b1b014a9L,0x44537af38c440a9eL } }, + /* 13 << 364 */ + { { 0xce1c070a2275263dL,0x2723b3d149cea971L,0xedca02f5817001b6L, + 0x5c160e9349c946e4L,0x273b4952458a5265L,0xc7bcd7c610385173L }, + { 0x22cddfd17fb08b14L,0x959d5dfe10f73d01L,0x900f5f348e387351L, + 0x6d7381dfdadb8695L,0x8dff2b193aeafba6L,0xe4a8d6bd8adadc36L } }, + /* 14 << 364 */ + { { 0xb564cfd676faaca5L,0x8a6e3925920dd223L,0xee59a140a590a383L, + 0x9e29b552a1922ad9L,0x604367de60a0da63L,0xc498aca592c35fd0L }, + { 0x74135082250ed8a0L,0x5d109d1a6c7c3e77L,0xf9e2d84dc63dff94L, + 0xca50f5e4f7aa2b0eL,0x7cba9e87d543d389L,0xaf5fbbefd8fd1292L } }, + /* 15 << 364 */ + { { 0x3163e2e895bcc345L,0x4ceaaf2d80d9a931L,0x4d2dc44b2f621612L, + 0x2a5f60b86cc8ffd0L,0xf49038cf7e8c9434L,0xb580b8c508015b8fL }, + { 0x4283ec01d52af80bL,0xac9dc35f99076245L,0x38785f7bd64c3dd8L, + 0xca19c17623bf8915L,0xd778291370478260L,0xc1e48e6816e34149L } }, + /* 16 << 364 */ + { { 0x707656834fc11c3aL,0x53a9403166aac4d1L,0x2a935ef0a6db6169L, + 0x002927612032d599L,0xb5babb2d3a6f1316L,0x601a7dfadb26af51L }, + { 0x00c340131322d983L,0x45b062ec2bb507c5L,0xa1bbe2ed0f9b3656L, + 0xe17a5d4934031d18L,0xe3661047f8fe1224L,0x0e4f3b3d623c6cf5L } }, + /* 17 << 364 */ + { { 0xb335d83c7c3b8c3cL,0x01eb94f059359a67L,0x3a8359a6aef3ffa0L, + 0xb0270076ecd2d862L,0xc946b1610377e30eL,0x9a5506c282bd6ae1L }, + { 0x737bdad0218512dbL,0x449238633487fb13L,0x36026dd12a8e7907L, + 0xb67bdc80784811eeL,0x9f92cc2405c90646L,0x02c551554c370746L } }, + /* 18 << 364 */ + { { 0xffaac084ca45cccfL,0xaea5cc3d061ffe3cL,0x7c5d7c60b355f387L, + 0x4bbb2a0c99cba92dL,0x6b4ba3ef2f7768d6L,0xc7484ed2cc5f9c40L }, + { 0x5d4e92fc52b57a7eL,0xba9f16c4ca2c200bL,0xebe02a8a3797ccbaL, + 0xb6b3f42138c4133aL,0xad5d85b68153d033L,0x782d6ee85714f269L } }, + /* 19 << 364 */ + { { 0x4654991087f226ccL,0x97894d5fc7bfffcbL,0x94f67786b3cabb83L, + 0xa6abaa960d788dc4L,0x08ae72d61723738dL,0x5003f41d86704dfeL }, + { 0x67687c3d40fb0a3cL,0x6fdc98c9b43320aeL,0x0f22572fdeb08964L, + 0x05bb02a4c8002624L,0x4c5adb7f987c2991L,0x3f1c6dddef4e60cdL } }, + /* 20 << 364 */ + { { 0x7845b6969c0cf752L,0xb82d052b5a732acfL,0x7760564c1262877bL, + 0x29b3c57a8ecc7aa5L,0xb58eccb0df1ebbedL,0x86fc15443c3a3303L }, + { 0x44761ddf13060f0eL,0x5a3dacfd7371a5a8L,0x846f6faaf7cbc2bcL, + 0xf5e098b0368caabfL,0xe23ea10710c08769L,0xbc5df1db1563fcdaL } }, + /* 21 << 364 */ + { { 0x75647f6476638edbL,0xb76ceb04aad6e25bL,0x33c73367d9393a41L, + 0x8396726dc55f0feeL,0xe1cbd48e751b3d43L,0xb779c5bdf47141a3L }, + { 0x122b85434eab6097L,0xeabacf45e08c6fa4L,0xdb32eab7769f49cfL, + 0xf956976a04ac2cb4L,0xf55c6fcb5ea8e71aL,0xd72940dfbad47ea9L } }, + /* 22 << 364 */ + { { 0x65c3a54e142d8955L,0x5c6583cce7814f25L,0xbd5a07d8d924dc7dL, + 0x9f717bd9c28f6e8eL,0xa0c4ec4e3b6540a7L,0x3153bb2b142b3283L }, + { 0x53bf403c9b296946L,0x659a828ab1cdb6d2L,0xe9517d811369af19L, + 0xd8c7a0998990e7a0L,0xbaa9f59de535cd04L,0xbb0cc68e0f269551L } }, + /* 23 << 364 */ + { { 0x2b4a0e69d0cd5fc2L,0xeb8dd25981167a94L,0x356198ae61b73503L, + 0xb159ca12e5289d45L,0x99d71c97991765b5L,0xce3a3b6c198e10b0L }, + { 0xcf6ee0bcafbb512eL,0x4aadd1381e19b49aL,0xcf6a9cf3b4806f0aL, + 0x6aff0386ad688bb4L,0xea487c6e4f2e5065L,0xec200f4b56573b51L } }, + /* 24 << 364 */ + { { 0x3c00ac526a78c6e5L,0x9c61aca6defaa52cL,0x0034128939794a09L, + 0xe08910d141cd7c0aL,0xa58ffbb6a732e3bcL,0x87bf51ab91fe8fd8L }, + { 0xc4f4f2674a59e2beL,0xdeb512c7438071c8L,0xddf82842e9cd290bL, + 0x3e17311d6ae85fe0L,0x6e9236a9b41be881L,0xbb9ddf9853555ebfL } }, + /* 25 << 364 */ + { { 0x07d2df1162bb0e3aL,0xe74ce211ce469affL,0x9629d7d4756b5a83L, + 0x61d2a633aefd449eL,0xd39a6afe491e503bL,0x0f1568d14d2b2ed7L }, + { 0x8216304cd19611bbL,0x6df99bbeb27388daL,0x2b0f60c0b7a3b4beL, + 0xcff84c1c7dadf840L,0x470201e28a9f8a49L,0xcda3693c21afc717L } }, + /* 26 << 364 */ + { { 0xccc163ea09f3f0beL,0x9932b56f6a5b0a63L,0xf89fae919c69668eL, + 0x555f98215ce13021L,0x4b02693f37037aa9L,0xc4afee79bde50f35L }, + { 0x4b0919c202aa6c7aL,0x3166de2a991e15e9L,0x284baa3e7077fb38L, + 0xbb7a6416a116ddecL,0xe8c89547b7636772L,0xff9403620ef92c54L } }, + /* 27 << 364 */ + { { 0xcd183e8bd3ea4c3cL,0xc8ce2f2154b7ac32L,0x75387e04be960826L, + 0xaf878400f2e39f5dL,0x7fcefcd94fa628f7L,0x76eb621c34582cbbL }, + { 0x44e1f848f29d2496L,0x42aa36174ab4eb21L,0x43cead840c08b50aL, + 0xfa4ecf60dd44f7c2L,0x5ac9ffd59f817546L,0xec11567eabcc594dL } }, + /* 28 << 364 */ + { { 0xd5d81275e2ce6008L,0xc45bdf250b3b9d10L,0x15ab5da36cbc83e2L, + 0x85a18cf8c52a66cbL,0x77e202b8b042c047L,0xc4dc3de2e7e7997eL }, + { 0xfe9335b1995fa67aL,0x809e161d75b96a00L,0xfb03c2a5a0c3baeaL, + 0x5c7e0523888c2f77L,0xa8fda1c887ad10e2L,0x90484f78858a3577L } }, + /* 29 << 364 */ + { { 0xefc5aa2681bf26c9L,0xdbe91f606bf105bcL,0x0d70c4d4369dd3aaL, + 0x2b357b847af9bf66L,0x4293e9a01f27f163L,0xc846f67cb3eaeddeL }, + { 0x4556bb787da305dfL,0x4ecebf83a5a26bf9L,0x8e05af924c1bc430L, + 0x4f3bdaba70f80402L,0xccaccfd3cf204577L,0x8fdee135a0c42d1aL } }, + /* 30 << 364 */ + { { 0x49e41f0af9fde126L,0xec9600443613d3c2L,0x2c62a49d10421d3bL, + 0xe24024648131a0d8L,0x8a7ce188bdf794fcL,0x704dea7d4665b1b6L }, + { 0xbdb9c18e4d57c6baL,0x5288a053f669b3c0L,0xbf7d01b878a5e252L, + 0xb26cccf926b9cb7dL,0x14191a3284326c47L,0x460ff74791f8425bL } }, + /* 31 << 364 */ + { { 0xb9958c5397698b9bL,0xe1f74292c27f96ffL,0x172b0d50806da6bfL, + 0xaf3d889ddd38b97eL,0xe7a75ea409c688daL,0x1f0951b85c631b2aL }, + { 0xdad8b2adda1c111eL,0xbacb9cc832813338L,0x30b8336b10582abaL, + 0x0ff3d7549494e71cL,0x8d99be5cd663ed6dL,0x8eb412cf7073a941L } }, + /* 32 << 364 */ + { { 0x59367582bd27be7bL,0x92bf5bbc1ab2c596L,0x5d96351af6a27741L, + 0xeab94db87f929e0dL,0x865ba011043f1afbL,0x43acea125fb631ddL }, + { 0x192e0652b2fd1436L,0x44f22ff17b38d121L,0x7bcc228db7cae5f6L, + 0x02eaeccd6a828b03L,0x7c48a2ea91f301aaL,0x1e090717f5eb1a07L } }, + /* 33 << 364 */ + { { 0x4c7f41b4609c6818L,0x978c2a561c82b3c4L,0x68404f1d7f6ba836L, + 0x91e056d0c863aa7cL,0x0b24599ba2261804L,0x16e9060dcdd7596fL }, + { 0x42aa49434eff004eL,0xb99408690438f1e4L,0x28299e8581775712L, + 0x498998eb83be6877L,0x84273d9e91328a67L,0xb7e9076e9a87bc8cL } }, + /* 34 << 364 */ + { { 0xe8d204865e5aea08L,0xaa946076addc7ba0L,0xc0153a9bb6a5cabdL, + 0x622271bd4fbe43e0L,0x44de159cbd62e5cfL,0xefca41112b9b63f8L }, + { 0x30774d3cf5269928L,0x4fbb7ff84ac0c8b6L,0xe0611f1f8839106aL, + 0x5d4121204ffa4a64L,0x9552c123e86251c0L,0x57d029680efbdb14L } }, + /* 35 << 364 */ + { { 0xdf3f8e06d7aeacd2L,0x725b25fe4d0e7af3L,0x1794f0da5c17392dL, + 0xabc807dac977ff46L,0xd90e6c8f0d5ca66fL,0xaf8eb526c2d26d49L }, + { 0x4661962e8a8efa37L,0x2a2cbeade87ad53aL,0xa57d34b1ce3ff40fL, + 0x1190437dc6aa3067L,0x92c31e779db66b47L,0x86a8ee0f8e8a70d4L } }, + /* 36 << 364 */ + { { 0x7b65bb14de97229eL,0xad6e3fee4c6d35b8L,0xfcbbf6afbee3f5d8L, + 0xb51549ca4a438fe3L,0xe66e615d437d531dL,0x9ee793eabf168624L }, + { 0x796789b0f8878a84L,0x3d38950dd32ec2ecL,0x74c37196a638d45bL, + 0x35d318327aeedaf0L,0x082c44f046a001e5L,0x93fae5cf89886220L } }, + /* 37 << 364 */ + { { 0x8e585fea499b635cL,0x60afcb3566781e83L,0x06594d9267482257L, + 0xb9f6101128773448L,0xba9ef7102817fd2aL,0x494e05b2aad046c8L }, + { 0x65d804fc1614e265L,0x1b0884c6d97fe002L,0xd7d34f60875bcc2dL, + 0xf34725444b440852L,0x49386bfb95591325L,0xe3966f4ccf68a142L } }, + /* 38 << 364 */ + { { 0xa5f3bc6cea06320dL,0x1bf855c637ad6e7eL,0xce7ff06ec58befadL, + 0xcf0d22cf1c2c0478L,0xf53e473e75616621L,0x00539f8700829986L }, + { 0x45398355844866d3L,0xbade46a2d710bc63L,0x6b3da567d4e2641fL, + 0xff70185978fd963cL,0x2eefaabaa5bc18a6L,0x61eeca92eb64cd49L } }, + /* 39 << 364 */ + { { 0xdf7c7c0b4cd4c82fL,0x67a26a97188ab9dcL,0x58c5bd74dd189cebL, + 0x3e1e93a9bb6409f2L,0x0d18a8bca6bb744bL,0xad3eafb45328dcf0L }, + { 0xacd15db5e311dfe8L,0x13a1c10ac1e849bdL,0xfaaa7227e1e73aa5L, + 0xa4cd2400e33d4665L,0xb9be68d9d6d527b4L,0xfe282bc05efbfc40L } }, + /* 40 << 364 */ + { { 0x159b38e17f8fd522L,0xf3ea27b5755e2bd8L,0xfaa52efebf11ac90L, + 0xc2014b892cb9f6dfL,0xa711c179d8baa5d6L,0x5474c1ceb22c2f27L }, + { 0x3cbc74cb031d05d9L,0xddd97ca6c44e469aL,0x21b386a647db83e5L, + 0xd1431c7b7abc0595L,0xbc05d009a416a325L,0x1c29eb709da53e92L } }, + /* 41 << 364 */ + { { 0x7f1aaf98181ce8a0L,0xa890cd3b6caa5b6cL,0x5d78dfaa5fbeac66L, + 0x36c63cef3d3d4594L,0x6f89ac3ec36d117aL,0xce9095640fc90e27L }, + { 0xaa356b1ac127aa76L,0xfa42cc119d181455L,0xbe4622fcd27f5ab7L, + 0x58d924542c3d54f7L,0x78a84f6b07e93c24L,0x5bf7cd278bce9a46L } }, + /* 42 << 364 */ + { { 0x4bde9ce5f810db3bL,0xec4a74b7281552edL,0xf5b4fa5fee085bb0L, + 0xb07a62936192c8b2L,0x163ff0d1fb18d219L,0x8d4b5e1d8e0ce753L }, + { 0xbfa6211baebcbf50L,0x1ed6d4b4fecc19eeL,0xbf6d514b82393e94L, + 0x90b356c1711e7d6fL,0x87b28dc2f975139bL,0xc41900648d8bebe9L } }, + /* 43 << 364 */ + { { 0x3468af53e8d49368L,0xa0a07369ff825262L,0xfad134fd662958f7L, + 0x5be79c00ce900822L,0x4909a56c44bde5abL,0xc2e8c4df4862e335L }, + { 0xd5e9b9386e7e41f5L,0xd3828d424fe474afL,0x058b2723cef44adaL, + 0xc74ac74617eebe66L,0xc3e6e014bca4416cL,0x2e30bc88167c2e86L } }, + /* 44 << 364 */ + { { 0x68211ba4969c2c58L,0x7a34733977f218e4L,0x0237eb3696ea1d64L, + 0xdc97f94b7416f3caL,0x63aa82e476bf9e52L,0x4b88a32d388465baL }, + { 0x7322d9f44adc7579L,0x70c01c7fb24d28f6L,0xdf7f4213c7517ecaL, + 0x42c027f0a8db6d56L,0x2708360eb6c2f8baL,0xf20690d1c2dde09eL } }, + /* 45 << 364 */ + { { 0xf139c3e3bc6158ceL,0x19207b6a4c86b780L,0x55af3eb977c036b1L, + 0xd192686abd563ebdL,0x8bd0afb05550266dL,0xaaa7376d83bf81bfL }, + { 0x26aa74ae4a114541L,0xd92549dfbb6745ecL,0x6ad6a14ec6bbfbd0L, + 0x63fee75b411771f3L,0x111ae3101938e8b5L,0xce3e5e346c363756L } }, + /* 46 << 364 */ + { { 0x2a53c88ae0a45b56L,0x26367466da72228fL,0xdd65516edfdbb135L, + 0x5fe254e82d7e37bfL,0xc0f5cbe433ef39e3L,0x249b7e3ece85effeL }, + { 0x85951a5391ffba8aL,0x41117672c8dd5ec6L,0x7a74538d9dbb0761L, + 0x0b35fba0cfb06ddcL,0x8c36be4d1a0aca2aL,0xbf884a8e45848e1dL } }, + /* 47 << 364 */ + { { 0x191eef31788596c8L,0xa7413be65a2d0ef8L,0x30894fcc5c3c09e1L, + 0x6b0e429b2f72a333L,0xceea52a1e70470e2L,0xfc638b316b682db2L }, + { 0x31af73cd615f7f21L,0xb31663760094996eL,0x7ec37e33dfff756dL, + 0x38c50101d9b63a4cL,0xa517c6df192f18e4L,0xd674c53a841fb337L } }, + /* 48 << 364 */ + { { 0x4dd3bd842446fc6aL,0x4654b82ef25ab510L,0x1ad46998ba066896L, + 0xb7c679acad713bbdL,0xef9389aff7ca4fa5L,0x1b864105d68b6a1cL }, + { 0x3acfff604b6f5ea4L,0x81ef58f7b9e5a475L,0x5e2f6441c66ad734L, + 0x49f144c42fd3eb16L,0xbd7f22082e4e2117L,0x30865994417911a3L } }, + /* 49 << 364 */ + { { 0xc2f25d9e80d2adb5L,0xa0e77dc5242430feL,0x7f30e54b4f504e97L, + 0xdc114db4680ca2cbL,0xf76fae57adec4d89L,0x06f892eff313535fL }, + { 0x50af729a9a266407L,0xb0cbc4f0764dffd1L,0x153ff8f8d20c2e19L, + 0x27fa845a7388d22fL,0x26e08ef5d784e057L,0xccbe49ee53b5dfc0L } }, + /* 50 << 364 */ + { { 0x6fa8e5ff3082ceb5L,0x81f4dd02ef4850ccL,0x626b324456483f9aL, + 0xc0acbd8782e65652L,0xf9bef3117e23f93eL,0xc2474777c2310f6fL }, + { 0x6b4617704379fd64L,0x2f8fc599f18c3b14L,0x2287f1d0bd076aedL, + 0x9f8eac0fef366016L,0x517cd2e371fd845dL,0x0fc2f219a30c371dL } }, + /* 51 << 364 */ + { { 0xfea0464721c56ce8L,0x4f7b055b6a32a26bL,0xf8c8d93e487ed396L, + 0xe620b440855f4df9L,0xa3f6f21dea870c14L,0x0518225207dad127L }, + { 0xbdfb7b12c68ab5f6L,0x5f58bdd7fc68f296L,0x2df9cfc505e4fdc2L, + 0xed12a102379c282cL,0xd388362654d8de77L,0xaefb0f7fb01065afL } }, + /* 52 << 364 */ + { { 0xdc64f8d23d80d738L,0x7ae74ab1d95a1c6dL,0x4dba93a8dd46de0dL, + 0x271aeb870fddbd1dL,0x1bab6546e9e7ed31L,0xe6445d22efec8f37L }, + { 0xd927df1797a718a7L,0x738c2450351b1ceaL,0x3809e595d51a7422L, + 0x4f8d5ea58969456cL,0x74d9168421c9ad95L,0x59a69f8f4f796a11L } }, + /* 53 << 364 */ + { { 0x2542fcf1f07717aaL,0x032abb3f405a7717L,0xc757e6e294cade8cL, + 0xad4776adf2e84dd1L,0xb7e277243d5e397bL,0x173894a605f8921cL }, + { 0x0e3a78531f6afc3fL,0xf33732b8ad62482fL,0xa6b4e0f03e4cb6e9L, + 0x51ba565eda02264aL,0xd0afaa4600f3f376L,0xf5506a1e35252e93L } }, + /* 54 << 364 */ + { { 0x3574783b5ea1c662L,0x675894e514fadc8dL,0x64dd63935ac6ea7fL, + 0xa76c00dc77f16c96L,0xf73ef2c62eb9574cL,0xdd39a89a2e408008L }, + { 0xbef8c8c72bafa10bL,0xa31f030a074733f8L,0x5620dda5445b4b6dL, + 0x4e08fb0173040ab8L,0x0a279f38598ad48aL,0x03e8b55e2d40d775L } }, + /* 55 << 364 */ + { { 0xf49d4d54c20c8610L,0x1b1d70bbc0d62b65L,0x524d3a0c16285ce2L, + 0x0be553b08a0785b4L,0x9b93e5093c84975aL,0xbeac761160769465L }, + { 0xffaaffcb3331dd0aL,0xad0f01542d70fcf1L,0x65aaabab66fe24bcL, + 0x283edb562cab253eL,0x1659deca80383c87L,0x06de45fd83fc6d7cL } }, + /* 56 << 364 */ + { { 0x7bcb055d5f76c311L,0xdb2d05878e293aaaL,0xb15036e7207360b4L, + 0xbc38cc9f163f0ae4L,0x5a942f85a44d0a0eL,0xee8633a23f553a88L }, + { 0xf66b65c5c9bd4ee7L,0x7a4ca96a80b8ceefL,0x7b71cc55f6f08036L, + 0xc0408b198c41be7cL,0x885fd72f80860d93L,0x338a567be7f68b7bL } }, + /* 57 << 364 */ + { { 0xcba302e939d99b60L,0x2557b3d903b8faa0L,0x2a99cd6e9efc4461L, + 0x03ce3e08268f14a3L,0x59226a83b1c68a01L,0x81a18c69fe379976L }, + { 0xfdfc9f148af62557L,0x0cdf327140b2d4ebL,0xf99ff3ded26c6085L, + 0x2c138ffdf9b0273cL,0x393d6de6888dfbd3L,0x75903c68e5cc102bL } }, + /* 58 << 364 */ + { { 0x0c56d477b78a7b91L,0xbedff933c7c3ecf4L,0xe02da64223ead65aL, + 0xf7e7cc19a8162300L,0x3719fb8f2f3dbd03L,0x4f150cb8cff88c59L }, + { 0xa564c5eda7fcb233L,0x9b042870b6a41ca7L,0xf253b65ac1615f1aL, + 0x9ccb49a7b8aaff46L,0x38bbc5f7af0086fdL,0x688f7c2054a6d8a9L } }, + /* 59 << 364 */ + { { 0x3702c5e5d22a0892L,0xf17510a28d510809L,0x5c36dc68bfdab4e7L, + 0xf72c9357623a98e4L,0xc660fc5146624a0cL,0xf0b4983d3e64dd4cL }, + { 0x5cb98cc9a5ecf45eL,0x79759acdf5082a78L,0xfd0daf366e7321dfL, + 0xf61c54f7f1ebcacaL,0x782e5e74b8f665c4L,0xb1d54c2145d78c08L } }, + /* 60 << 364 */ + { { 0xb64f3b9bef1af123L,0xc86dc5ffe1b75401L,0xc3a76d81d928e989L, + 0x075005abff8ca002L,0xca6226325c3cd8b1L,0x017a97b2bd8f772aL }, + { 0x187eb635039c4757L,0x9eb7a9d1e905c6e5L,0xdacb98bfbc251cceL, + 0xe357c60e8704c639L,0x50563b8558fd987aL,0xb2f89c864cea5d4bL } }, + /* 61 << 364 */ + { { 0x3d13c0bfd32233faL,0x997c424145aceb7cL,0x77ff5a75ed2e9df0L, + 0xc4279aa23c91d085L,0x5a11a276ca0392c7L,0x928e06032daae653L }, + { 0x21fe225fc4046f85L,0x591fa82f512dbfb4L,0xb5b01a3f51aa53feL, + 0x900012ef7133befbL,0x24609da17130c15dL,0x3c4a09b33d2549faL } }, + /* 62 << 364 */ + { { 0xcdd3073d3ceabe32L,0x56e155bc5a848977L,0x07f4c7c6da48eef6L, + 0x00a2f9f79e021b38L,0xeb683e17ffc4bd6bL,0xa7d6b87592b7e240L }, + { 0x651d21de7e48836eL,0xf9c9ede775de3c75L,0x72cea748d90f2634L, + 0x29d8022283fc524aL,0x1e412b510dd044faL,0x1b9b332a76a04fdfL } }, + /* 63 << 364 */ + { { 0x4dc8421f06f49d8cL,0x6a3fd9a83f979e4cL,0x50b0e3760b51bd69L, + 0xec22f486a592313eL,0x5e4663ff8e8904d4L,0xde7b9e23f3362548L }, + { 0xa1ad270d1ab757abL,0xb91fd935a3089f6aL,0x1d6b1524a635f996L, + 0x8673f8e29c718c6dL,0x0e04360725932b9fL,0xb5d0447222ac239fL } }, + /* 64 << 364 */ + { { 0xdf0ae8df941948e3L,0x123fee901d010bcdL,0xde3717ca1dd28691L, + 0x0c1db879709b678eL,0x0288959a400acdc6L,0x66c691815ca2d03aL }, + { 0xe52534b3dbbb75deL,0xe914938c3de927cfL,0x1a9a34f873eece30L, + 0x0fb0c7bd642a6799L,0x375cc0cfeaa7e8a8L,0x75fb9eb5d00ec238L } }, + /* 0 << 371 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 371 */ + { { 0x9ca8cc9db72958ebL,0x3c8cd0db1014f562L,0x72115d53059b2bbaL, + 0x8fe7ac30730e5dc3L,0x4e67ef69841d8998L,0xfb6439ffc8ed37a5L }, + { 0x48164b3e26df84c4L,0x37d492ad365bc99eL,0xb7fd4643beed38ceL, + 0x993cfa9fa3e30b3dL,0xdcc5e7af01ddd484L,0x5edf3ac06840175dL } }, + /* 2 << 371 */ + { { 0x79768e9f51d33c11L,0xeec34505a4b24889L,0xc194821bbe0c67d7L, + 0x537a6a4a6909fdfcL,0xae6d705195ccdda7L,0xed4b722292b3926cL }, + { 0x2c5dd6af6b24a3d4L,0x9282ec39e4386095L,0xdd3c7388397a3bd3L, + 0x9d176c6a8baf59c2L,0xd5c6219e380ec958L,0x194fc11654e8e315L } }, + /* 3 << 371 */ + { { 0x0b7576f901ec1432L,0x84b30eecabc5f603L,0xdaaf7ba9f4a84b7aL, + 0x9e3a5daa3bb37a99L,0x56bd964880378cffL,0x2fdeeeb78e6ed856L }, + { 0x079014a73c81ac34L,0xf8de4004b4211c27L,0x0cee3df97fe4391eL, + 0x441aa7fb2fd2fc38L,0xeba7be864d1b575aL,0xca2fb5b7231c2d01L } }, + /* 4 << 371 */ + { { 0x0683349e463a8251L,0x97dc4f475103e72cL,0x47c7181050663b9eL, + 0xf327d1499733dac6L,0x03f55e4a292137c5L,0xccc6232ada59e1c7L }, + { 0xbaa8b4ddadc59cb8L,0x45370d35fe7486e4L,0x99a88c1db0322df9L, + 0x394440a7fd69954fL,0x9060473da5a29889L,0xc8ca43e32f04864aL } }, + /* 5 << 371 */ + { { 0xd5c7241add8b9644L,0x45a5f2d1993116d2L,0xbacacd4a823048dfL, + 0xa278fa042568547aL,0x3a4f2482bff72820L,0x1305d1a713e4314aL }, + { 0x9d84c33334ba28e3L,0x9995b5bb6a32fb41L,0xb0f75f3c520946d8L, + 0xd7c4b8b7de98aa63L,0xee5efcf3ba856b6bL,0x36af33683324ed66L } }, + /* 6 << 371 */ + { { 0x90762c1f5827fe2cL,0x20160f7aeaffda88L,0x7420849f5c47c645L, + 0xb08231956d72e748L,0xaeac683b8ee11773L,0x8c2a0a79fb5c550eL }, + { 0x6d986d696c07cc1eL,0x57269140ba8398b9L,0xd13e136fd94d5223L, + 0x1aa75419ed5b01c6L,0x7c2014b1408fcdccL,0x0680a985cffde5eeL } }, + /* 7 << 371 */ + { { 0x92fc9a3342c5a7eeL,0x8768614af9f0ed71L,0x1ea5f7ed87ebfb66L, + 0x296852ded361069cL,0x1cec6f1a0192498eL,0xbfd4858fa9cca3aaL }, + { 0xfba98c242ef240e8L,0xc8b500e4ab635d9fL,0x9f49c572913a3eddL, + 0xe6181f93d42b2d4dL,0xf96b5db26aa77fa3L,0xdfb2241fe43558d8L } }, + /* 8 << 371 */ + { { 0xc7d0abb2edee15a5L,0x72dc0105228cc4a1L,0xeb67defca80767deL, + 0x6fa174d871820908L,0x3215df485674d19aL,0xf944531a960a081aL }, + { 0x93ed7180ef2cce62L,0xb318edbfc8bcfc0dL,0x0909d56efe787e58L, + 0x5ae74fc98fe8b96fL,0x8fc342c435ab6811L,0x6fc6cc5c0b991e0cL } }, + /* 9 << 371 */ + { { 0xa8eaba6e291f689dL,0xfbfa9a2cdea0cba9L,0x5b1b4a21727bfa11L, + 0x3b69505fac59c8c4L,0xb06290c89368ddb2L,0x4181abc294bcc14aL }, + { 0xa19f65813e29d997L,0xab1ae8408864aac2L,0xb04a24300fcc9ae8L, + 0x3ca2428e1059e4dbL,0xe288731117e1e01dL,0x1f5d4164be56238fL } }, + /* 10 << 371 */ + { { 0xc600dd57354416d9L,0x6f5840991f829d6bL,0x2d7b0a27de43c1d6L, + 0x21bf3a9e616bdb16L,0x33ce767c96297953L,0x99bf97b69e4398b2L }, + { 0x4069cced8d441287L,0x52e0edd6bf01017dL,0x9981bf89c5394236L, + 0x07d9c079acb24e38L,0xd2e5e904a2da4735L,0x4c3c12162f1b6cd9L } }, + /* 11 << 371 */ + { { 0x1f28bd0de6f1c85cL,0x4a49d0864e6f3db6L,0xc9a8e70c4ef7d981L, + 0xde8abcf2682bc68eL,0xd0ef89a4a66cbee3L,0xfa03108432df7f0fL }, + { 0xe361e0f803594856L,0x1f423bafc985c77fL,0x50397b67010ee4acL, + 0x502f4a20c0a48e96L,0x260bed875435539eL,0xdae03cefa0391250L } }, + /* 12 << 371 */ + { { 0xfeecc6e83be5ba68L,0x3293dbda40445158L,0x48454e20e81879caL, + 0xd0ea9cb89c4a2712L,0xba8b6f33540749c3L,0x95e6d6e3e971df93L }, + { 0x4c2a1b13478a2eb5L,0x8b5f9af330b92170L,0xe6c60b5343573986L, + 0xb9f56a6a57040c00L,0x6de6489f6291a7b4L,0xa9a7784653bc3246L } }, + /* 13 << 371 */ + { { 0x0dd4172f9025411fL,0x978e952ac6129de8L,0x9afa974bc7ab7609L, + 0x7bd29a644e42f223L,0xc0232f5f3deb639bL,0xacce69d05f39a264L }, + { 0xdaee07cb3070b24cL,0xe3adc8556b532246L,0xae5935ce1e6ee4f6L, + 0xba9c4329ea018a45L,0xa1a4002e6b97ee9dL,0x98390aab8a9460cbL } }, + /* 14 << 371 */ + { { 0x828a9dbe67154a02L,0x57a3af981866aadfL,0x1558428089faa581L, + 0x2da092202dba2a1dL,0xa225f631df197ae6L,0x0abff5cf8f4ebabbL }, + { 0xbbadc9b3b98e5e4eL,0x7c7cc36e4509f98fL,0x072a6cc2759413f6L, + 0x7b39ea4121dd1222L,0xd6baf9e196ac2c73L,0xee38818c75d46296L } }, + /* 15 << 371 */ + { { 0x19befeacfa37c53fL,0x32c29b361f95c29aL,0x1d282db40d5aeafdL, + 0x8812b6c8f102a97eL,0x1cd4a23c8402f481L,0xbfdf7b6b8eddec81L }, + { 0xc8039ae0616b2654L,0xdc6f38acabd23a57L,0x2431c763f147dd44L, + 0x7c45ed50d795bc37L,0xdbc30ab9842022aeL,0x568f7d4ba1f05a43L } }, + /* 16 << 371 */ + { { 0x55671129542f4e90L,0x43bedccf0623d4cdL,0x7e21207ce99ca16bL, + 0x785fa1057c7a26b9L,0x33c28658c2c3ab00L,0xcce42a48d79cd59fL }, + { 0x9a674db4b8c3bc75L,0xea701d156904e3feL,0x990e722166bf2c6cL, + 0xba29affabd4c3791L,0xd98510cf20696ee1L,0x722ed471f93d26a5L } }, + /* 17 << 371 */ + { { 0x74e6c2624ba40f04L,0xf7ad1f159a63b3c2L,0xa89e8490ef75d482L, + 0xaf8e79b83bb5f5c4L,0xb094f8660c624d8aL,0xb571ce6613c69a60L }, + { 0xcbf9722d53787457L,0x97e24cf5c15d097fL,0xdba98bede99e034bL, + 0x8b6c171a57773590L,0x5d2b441cfe822efbL,0xb8c6dc57fc74ef1aL } }, + /* 18 << 371 */ + { { 0x37c70bdf7db1c03fL,0xd9368612964632abL,0xcf6368d742530338L, + 0xe56beecbb1d9522eL,0xb1caaf16bb6fba3aL,0xb7bd485ac8384d26L }, + { 0x4ba13818528d4372L,0x95c469bab9c5e8f6L,0x4e5cef0c4a370695L, + 0xb87c97ca663f9b07L,0xa9e1b388e5f3b79aL,0xc0416bb84c845a1bL } }, + /* 19 << 371 */ + { { 0x4483db00e4634d8dL,0x4d8d623d0a268bd8L,0x296f179c64e6d10aL, + 0x048f3a1cb6c7ff95L,0x60f8ad62c60c76d1L,0xa0a497610d028845L }, + { 0x10128387aea1b714L,0x81e5c75ca18bd98cL,0xac30d7361dac4200L, + 0xb83c1c12821380f1L,0xc8ca7c6afaaeb726L,0x13fb870dfead4cfbL } }, + /* 20 << 371 */ + { { 0x3921332a6b393648L,0x49ec6df649584f38L,0xa0fc013dce243a6cL, + 0xde5b16b5f8da8a00L,0xabcd0c0471ab1c9aL,0xff6594bc78b83305L }, + { 0x3546004b76c1900bL,0x87428fa236fb3186L,0xd2e464ce59cdeb49L, + 0x1260bd28faf6ec08L,0x1ada2f08d0c9d098L,0xe0b66299dea06396L } }, + /* 21 << 371 */ + { { 0x603d58167c1212e8L,0x95bb823fa4590144L,0xf239058a4bc3ba48L, + 0x21f2aa610db724b3L,0x29c706e8cd6792a2L,0xb143a84a634f01e6L }, + { 0x68f37382626ee80eL,0x56daa0e51fcd8c4aL,0xe01b52b39e5299a5L, + 0x2224513c3accdac7L,0xbb21c7d74acd435fL,0x039bc010bbcb948aL } }, + /* 22 << 371 */ + { { 0x5006c3a00848d6b7L,0x726b8648b28285aeL,0x7162e3c0277c5a87L, + 0x567f7ab02019c20aL,0x490c858fa551d5efL,0x0029a108d134a2bbL }, + { 0xa9e19284ef0aca3cL,0xbc399dc16e414f83L,0x5bdf85f86efa5a8eL, + 0x5291e1a674fe7c5fL,0x249ddf2acd7091dfL,0x71d4cb4c2e29fcf6L } }, + /* 23 << 371 */ + { { 0xc374acf4c1ded13cL,0x300d96132b69132cL,0x909ce34b055622d2L, + 0x26f033f6bad97809L,0x30987ebed1f7a220L,0x23147226db775b8cL }, + { 0x8d45c2c28d05ecfdL,0xeee0c679f0c1b419L,0x9f7df70d8c380da2L, + 0x4d49f3d130212a25L,0xa9602e8c64491ff3L,0x5ab91d223a254c49L } }, + /* 24 << 371 */ + { { 0xedd3291c9dac47a9L,0x02d64634fb5d396dL,0x2ce21bf163264c51L, + 0x0fdcc68e092c4724L,0x653acb286e3e4c2fL,0x2f9c77f12f1fa1edL }, + { 0xd91d4c3aa58afea2L,0x5a91b2ba7b0d8092L,0xd47e0f61f10a15fdL, + 0x01652d86f9c86edeL,0x1cc1b668d6006daeL,0x2763e36d24af68beL } }, + /* 25 << 371 */ + { { 0xaa5f387c2314a1adL,0xb8c00105e2647c74L,0x1f950dd8d6719178L, + 0xb7dae31de79881efL,0xf2d49aa2e45a615eL,0xb22dc098f17352afL }, + { 0xa4c438728ac23ba4L,0xedd6e4092c55e588L,0x1956b199022f5632L, + 0x18adcaa58c11bc50L,0xa0c11f6458b1cbf5L,0xd1204377f961ce1fL } }, + /* 26 << 371 */ + { { 0x35a2685bbb77f5dcL,0x1b5b79bbc08efa67L,0x4ebec6e6ea5f411eL, + 0x1800a21988c57793L,0x8d7397f2cbb13c96L,0xbc13ac35dc0327f4L }, + { 0x53ac05a6fd94b150L,0xd898fa600423e787L,0x802aad2c2a66b97fL, + 0xb604ac0692c62b03L,0x9f395d3a45911e7dL,0x5d38164128ae56b6L } }, + /* 27 << 371 */ + { { 0xa7d5a3afa5fb0decL,0x0d11c0cd5b27e02dL,0x8d854b53366c6cc9L, + 0x87ef4c140ad9a5f5L,0xaf7c2e6b0c5f8acfL,0x81fc22b69f010f1aL }, + { 0xe49e0c7e4e25ddb3L,0xd30bc860ef233d23L,0x0b63afb89fa41205L, + 0xd14b326c702fea93L,0x10ab93662c2a5fc8L,0xab35bab356cfff28L } }, + /* 28 << 371 */ + { { 0xdf0f79524130138bL,0x117e4628934c58afL,0x227be6867b6a4087L, + 0xe73fb2f3b8d298a3L,0xe32e89fda9bacb9dL,0xdd3be6130e9ea7e3L }, + { 0xd3d655ead4da2d1eL,0x153cce647833bb3dL,0x4a32a9f0b36da20cL, + 0x025768e5a69c4b27L,0xb0b5da379cf1fcecL,0xd0ecaba23aa3b99eL } }, + /* 29 << 371 */ + { { 0x9ab6dae0aaf6b398L,0x2d50f46b4f8e270cL,0x46c1e676fd7b7005L, + 0x4b8b203e32cf8be9L,0x0253ec899451bca9L,0xc3a7eab7f512b7a5L }, + { 0xf3bed3fdc5bd61a6L,0x5c0eb52f0a37ef8aL,0xb61aee11140894dfL, + 0x690607f9bec928f6L,0xba2b1db65148b45cL,0xbd309bf56619b652L } }, + /* 30 << 371 */ + { { 0x79d624c7a7b92932L,0xcd086bd7cc75e7a8L,0x3cddc1bbb48eab26L, + 0x10282df1f6791cfdL,0xffedb4fb1048f114L,0x937ed0e7c092d899L }, + { 0x045e4f60b84b6d20L,0xdd67bd36877ed915L,0x9bf8fede97617aa9L, + 0xa7ff9b0789cb8e1aL,0xc49e310e74f4e7d6L,0x12dde0fb3f62eafeL } }, + /* 31 << 371 */ + { { 0xe2e3dc4d50ba6e73L,0x31c19ebce6114f87L,0x8df0ffb01ffa99b5L, + 0x305142f1bfcf7fbdL,0x39931954ab88b782L,0x1952bbab43de3650L }, + { 0xb32ed678aa09e528L,0xa5150011acee68ffL,0x0307716a97b98b23L, + 0xb60c3edd4fc8d2b7L,0x91c81725b2b2f887L,0xf1dfc70ab9fb0288L } }, + /* 32 << 371 */ + { { 0xe7cf5bacbc579793L,0x11db7ddfd73f881cL,0x9c1a531d04fa8473L, + 0x399e84845780efdaL,0x6e9c12be4f62cb5aL,0xf21bdc4994a5df3bL }, + { 0x3c15fe1211da2a4fL,0xdea123bb23e631d1L,0x3ef76da4be294c90L, + 0x5cf21d5aa99b8398L,0x50679cf8751b9f6aL,0x4b3f3b9c54d0b7bfL } }, + /* 33 << 371 */ + { { 0x442dc0fd27174604L,0x5aa056efebc95895L,0xbb8cf9b54c96a2dfL, + 0xf43342d440f8618bL,0x58b0d00a8f89a8bcL,0x74d32dbc81f69f20L }, + { 0x5caf0910ab22a49eL,0xa0e9a677ff372f3cL,0xec90b5aef5c05066L, + 0xe2d98821b663f0e1L,0x388804bf50c7abc2L,0x2fbab16e97ba64d3L } }, + /* 34 << 371 */ + { { 0x09138c6071ed8d4eL,0x994d0fa991ef82b1L,0xe6089dbb931f3193L, + 0xb3b229d0aac23611L,0x52cf03fdacb8affeL,0xf64f9872bd99d6e2L }, + { 0x52ebb8b40186279dL,0x36a2349fb09efd7aL,0xa85b5d802225772aL, + 0xd2dc3c1547522562L,0x659297a666471319L,0x65913b608c8e7b68L } }, + /* 35 << 371 */ + { { 0xd54591f9a713f82eL,0x0ecfcffc6fae64b7L,0x7df9d7ea7287e218L, + 0x8b260162abe71460L,0xf75097efb12d48beL,0x82d5902482581904L }, + { 0xc5c0b5dc400d4288L,0xf6493c78190f768cL,0x1844b5f895bc9fccL, + 0x24afb04ba615bff9L,0x6c9638ee8bf51197L,0x38bce012b9ab9fcaL } }, + /* 36 << 371 */ + { { 0x087a2790494efdc0L,0x0b5f23c9e1645cb8L,0xa6e1d1e8193a99baL, + 0x0d324e67c0e0c026L,0xa86d993820d608b5L,0x48ddfbfd8d6944dfL }, + { 0x6aa07f90d371864eL,0x5cf727eef2060df5L,0x7694e02c9a7cf2d0L, + 0xe091982f6260f63cL,0xd2d481a72cae5da6L,0x045e3685ebcb4172L } }, + /* 37 << 371 */ + { { 0x1765632323c82633L,0x5de90578d590cdd3L,0x5cc5e7b9525caf0aL, + 0xdd9be80dd53e825aL,0x9ed28b29949073f3L,0xd15024156a6ce0bcL }, + { 0xbc34beeabf355f49L,0x73724878d2b210ccL,0xe47b7af911e8122dL, + 0x381a4cccdf53a9eaL,0xaa22c9b229e8a466L,0x7a05e2081a4fa093L } }, + /* 38 << 371 */ + { { 0x3dfb53521830d848L,0xea183d5cd2820590L,0xc83a65bcabbeb376L, + 0x5d9ca4d189bb9ac9L,0xb32217be137c900aL,0xcc40daebb0827afdL }, + { 0xc76130060c58b0afL,0x39f4ed8adf32389dL,0x04a586e2bc1fe9f6L, + 0xcf018c2abb50450eL,0x5072b8f016d55d0dL,0xc3c72e90d59e1dbdL } }, + /* 39 << 371 */ + { { 0xb3291b4e50b4e9f4L,0x79a2e8121b7b9e08L,0x81855db1ddd5f0adL, + 0x91fa12fc884392e5L,0x6373de02291c5694L,0x15c77432a7171428L }, + { 0x6016a06c1132df9eL,0xa4286939a0c21c8fL,0x70c5ebe26dca3f37L, + 0xc5278c510f115497L,0x8f5b07a35ce1953cL,0x4d75c1dc41f6ac0dL } }, + /* 40 << 371 */ + { { 0xfeac8e8ac24002e7L,0xa43892076643fa6aL,0x06e7ed63daa68b52L, + 0x8580bbd5d8c7b952L,0xb17ce22410c8fe9dL,0x40266bd379b88ceaL }, + { 0x32afc840dd63ffa5L,0xb4a3eb27a2280b83L,0x90528bf685897e28L, + 0xe4612391d231f941L,0xa7b3a2ccacb5c909L,0x2606844e5558d57aL } }, + /* 41 << 371 */ + { { 0x49ad52380519dd66L,0xe1b0b03b3c1470f4L,0x15e42792cd3a4852L, + 0x91c954b7388ba040L,0xe9fd8c7f857711f1L,0x8552d3d44b63a36dL }, + { 0xbf867fde230ffab0L,0x362a32a0793f885dL,0x687802cba11e0225L, + 0xd95b073b308c1972L,0x13b104aa6b3e5120L,0x60bef12333673f57L } }, + /* 42 << 371 */ + { { 0x4c4cc5561c8a5d9fL,0x5c6e1fd52b8a42c9L,0x73fd66c44ccfa024L, + 0x73c777563c50d038L,0x26964a68a5076758L,0xb14cdbfa7484d080L }, + { 0x24c499cf3f4b92ccL,0x40c8c0d84682daa1L,0xaa156edf785561beL, + 0x36718fb6de75af0aL,0x4d391cee03f5b180L,0xcf28d08a3100efc8L } }, + /* 43 << 371 */ + { { 0xbf1fc9fdd113a97bL,0x19cee87f5ff5ff3cL,0xfc140acf8f8213a3L, + 0xe70d50d546127d5cL,0x78cd24032faa7ac9L,0x409675f1c1808096L }, + { 0xaa7b6cd91765da93L,0xc0755b924f508d86L,0x09b8fb7640169a6eL, + 0x9ca977e52e7da664L,0xee1aab6c9a9616daL,0x54d740391ca0f4fdL } }, + /* 44 << 371 */ + { { 0xfe011830c37c7fc5L,0x0b2b965b2ee958c7L,0x99fd253588a43cf6L, + 0x6a73d62dbf8dc33aL,0xd53c0241a99247deL,0xb8186dccb4127f94L }, + { 0x86c4c274964cc3d3L,0x2f3f2742cbfa9429L,0x5b4bd23c5391abd3L, + 0x030b211bc5838fe2L,0xd2263dc4ae2e36fbL,0x45583a3ca0bf7280L } }, + /* 45 << 371 */ + { { 0x9ce7f43f1ed3f49aL,0xd8094c4afcdce20cL,0xd8b423d12b37b162L, + 0x332ce47c53d90a7dL,0xc686fc0c94a38ff2L,0xb44938d6c33d842eL }, + { 0x5ed14772cd9b0002L,0xffa5d063e800c655L,0x4511ec79ffcb6120L, + 0xb8c9de3f9da8e70dL,0x4d0759ca952b0ef7L,0x685f7005dfd88f4cL } }, + /* 46 << 371 */ + { { 0xcbdb755f1dbdc85dL,0x63d0d7047961be6aL,0xf65af35d8220a1b3L, + 0x8dcea7df77db51b3L,0x8cb2c5d14bfe8fbeL,0x740579bdee2f03e0L }, + { 0xa7eeea4ed3f0181fL,0xedbdfaa3c12ef399L,0xee3cc40f1c332118L, + 0xdae0995e731ef93fL,0x05165c6c0f24d954L,0xcbcc014219fca63aL } }, + /* 47 << 371 */ + { { 0xff24bcd842c7c110L,0xa5ddfffc56dc10c6L,0xb9937fcdaa1a09c5L, + 0x8e18ed5b852dd22fL,0xf24e43c7826fb5a7L,0x13989a43415c2c63L }, + { 0x71ad7c21d36ffe0bL,0x68b77701129df418L,0x1c5324cd9a8d424aL, + 0x2e2a2b1ba9bf46abL,0x7d0c04d19cd0ea12L,0x8b4186bf2f9869e8L } }, + /* 48 << 371 */ + { { 0x6c8d97e075a46271L,0x0fa0c4cd9dbed39fL,0xfb6da5e2de74ac6cL, + 0x041ce886c17c1ec5L,0xb42941a8d7419105L,0x79768eee002fdfd5L }, + { 0x64849afd88c8111fL,0xf425fe14814192d6L,0xe916e8640448fd7eL, + 0x31e224ad72ed351fL,0x73e6e6ac7c0183c1L,0x375657c621bf7cebL } }, + /* 49 << 371 */ + { { 0x093d8039114fd7b9L,0xb6bed3eb45c5e1c7L,0xb73ab7fe50fdbf14L, + 0x68d95e57af0cd23dL,0x5c260eacc7b750fbL,0x79bb142bb5358c26L }, + { 0x5aa9845158ace251L,0x04b2388637dbfef5L,0x1051172dc0532263L, + 0x686ee9e6294890d9L,0x092617b3bffd1609L,0xb4a50e50ea3836a4L } }, + /* 50 << 371 */ + { { 0x8bdb3886cdf950abL,0xe2bdc8d3d595dbd5L,0xd28211254ecc49f1L, + 0x946566081d3c2f24L,0x8124ad390c87df6dL,0x6020c322d16272baL }, + { 0x2150f7e694af134bL,0x38512401a1a14e33L,0x39a54386b1ff7304L, + 0xfaf1ffea078d8f0fL,0x7739ea99dea995bfL,0x3252e815c020816eL } }, + /* 51 << 371 */ + { { 0x1609832322f1bd8dL,0x6b02533cd4df163fL,0x25108619a8296363L, + 0x373bf9988f8c755cL,0xebfbc5b23b32542dL,0x7ada597688b9d360L }, + { 0x3914406ebd605f01L,0xe245ba48cb3a40b2L,0x11a1dc4ed3171f32L, + 0x4a10d5d26ffb5915L,0x9326b23e997460b6L,0x53ddfee92aa0c77cL } }, + /* 52 << 371 */ + { { 0x44f51dd51104ed7fL,0xfca4773e270f6135L,0xe36c8b266bc757f4L, + 0x2cf0515d6941c7a0L,0xdeab655d5fb16e2aL,0x75c28116cff7be07L }, + { 0xb24ca428abbbca02L,0x6aaeca9b1e7f8116L,0x4252f4c3510f0c81L, + 0x01462d856f3ff7fcL,0x4df702879d1c25e3L,0xddd47a1dbebd1559L } }, + /* 53 << 371 */ + { { 0xdffaef2c6f2e2611L,0xc2c2e6a41f29efa2L,0xa29bc3b75ebb40c9L, + 0x8473594bac31a2c4L,0x100d7d6a8604447aL,0x80318670794bbab9L }, + { 0x78979f72054dfc75L,0x94b4c17e55232511L,0xac44836b78b883c3L, + 0xc1f7e98168422328L,0x34fcdee68266747cL,0x18533b3f0475c011L } }, + /* 54 << 371 */ + { { 0xede6728e3bab17f0L,0xfcd9c96879b94302L,0x6410ae37544a677bL, + 0xeacbf6de1dcd0fdeL,0xdae70841e2f3ac0fL,0xeea2a9b6e41ba13bL }, + { 0x1b06aeae9349cdf0L,0x28571e3d33c0ea87L,0xceaf9dd46043e874L, + 0x32cbcc69fa6fea15L,0x7db75664e135aa11L,0x588d4458f816929aL } }, + /* 55 << 371 */ + { { 0xf70797d02b014160L,0x1ddf312d8d7c3263L,0x3bdd58f3c78beacbL, + 0x8bccd90101c71f77L,0x3c637f58166c1486L,0xb62c0aa45fd1a307L }, + { 0xa68db7b05f2544d4L,0xb9727946f860585aL,0x91565060a068412eL, + 0x1283d6d1ab536c42L,0x86c2a11c79caa387L,0x2687309b62bd7797L } }, + /* 56 << 371 */ + { { 0x525cd8849b711a38L,0xd413d82b8c95bf61L,0x19ecc14a36b82970L, + 0x65190ee6e3416342L,0xde9834c93066fcf7L,0x3b87b15e8302cd85L }, + { 0xec6f67a785268eb2L,0x5ab08b5af95aef07L,0xb5257f70adda86a5L, + 0x53e95ec4b934400aL,0x9611a632c33b870bL,0xd27929522723a3d5L } }, + /* 57 << 371 */ + { { 0xcd203b542c95b469L,0x89b140e768713ca6L,0x451646a165701050L, + 0xb97a582575e54715L,0x070fabaa93bb6a91L,0xe517e07a196421b3L }, + { 0xc8d741235f46e495L,0x920ee94fdf60eb8dL,0x885b86dd19564c3eL, + 0x6c9e973231670005L,0xb52eed1fe4893763L,0xa8f9fbd759157417L } }, + /* 58 << 371 */ + { { 0x0c41f2eb56517cafL,0x47778a92798cf8b0L,0x4232ab390dc60cecL, + 0x5de0b7e39e3eb6f1L,0xa2569d8571562511L,0x37b3c62a1ce1cec9L }, + { 0x312caccd8b3391aeL,0x6b22c9447dcbe533L,0xc890d22f4fefd4edL, + 0xd1504f7df007a64eL,0x117e4e595845d5bcL,0x999386c7723584e1L } }, + /* 59 << 371 */ + { { 0x02c396533bdadbd5L,0xc07325fda1fe704aL,0xf78d7e23350aa0c4L, + 0x9f09cf22ce50784cL,0xcdea9a6a1a6e8abcL,0x245fba06ee5a5e06L }, + { 0xf1fd3b9b4a3d0d7cL,0x24c65a131a4952c4L,0x40ea3ef37236b6f4L, + 0x60aa573d8f7addcfL,0xdd5ec47b0305577dL,0xd92dc5035deacea5L } }, + /* 60 << 371 */ + { { 0xc666f8f3fac2de80L,0xabb2b8aba8fa36a6L,0x1bd0ec8f12202b09L, + 0x88b184be6d17a3c5L,0x00d501fc670a77c1L,0xe1f94f1db3de1c7eL }, + { 0x953179cd2d6de8caL,0xa8873a5bb9263791L,0xd76433098d7ac5d1L, + 0x3d751cab4d2f8224L,0x7417b8262e5458eaL,0xf4eb3c669e454a8cL } }, + /* 61 << 371 */ + { { 0x65b0d7e9ae3284a2L,0x3d4770bb1e3cbb18L,0x217a0cdb808ea164L, + 0x9ed6d0f689810270L,0x62d9cc95f14139e1L,0x4d39eeef6a2c82a0L }, + { 0xecf319f40dcf14afL,0x62c95df6ab0fd145L,0xfe85014d22db0105L, + 0xc37756e6a652168cL,0x6ba9f6b370a67e9dL,0xe453fd0af18d8058L } }, + /* 62 << 371 */ + { { 0x265798acfe3bf4f8L,0xc1603abdc1183f63L,0x14e3952f1063e086L, + 0xdcb106d2910f0a78L,0x27c2aee2f454f625L,0xf16d83e60f463fe9L }, + { 0xaa5547207f5ae172L,0x42ea8fea9a2133eaL,0x9f3b33f6e9253e7eL, + 0x6224ef75d67af0afL,0x06f0ddfbb92d6cc9L,0x12e66e32656e9e9aL } }, + /* 63 << 371 */ + { { 0x1a93be3424ace7f0L,0xb993bcb9a56be2eaL,0x3b054afac33608d7L, + 0x36e782c3aea3d7e9L,0x54f1dda950e9b3adL,0x04dd021f55f51bb4L }, + { 0x9c76f7c0347bb352L,0x3d9a04ee2f1dc5fbL,0xea5e582ae80e06f0L, + 0xe523aab927e1e818L,0xe2f1960252d4904cL,0x1bfa8b03adecc51fL } }, + /* 64 << 371 */ + { { 0xc84f917203bdf6d6L,0xcfc4718769f60e03L,0xcdc4753ba05068eaL, + 0xa177ad14077777efL,0x0b7f54eb7e4cf44aL,0x4ee443f91860144eL }, + { 0x1279ed4d42bb6a93L,0x511137d7436c1b54L,0xebc958fab8cdb6ceL, + 0xbc4f93f4a0c7614aL,0xc5bd6cde7b2c6d8eL,0xecff7dd78d65f38aL } }, + /* 0 << 378 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 378 */ + { { 0xffec6674f65de0f5L,0x4043079cd23ad193L,0x31811365ee61bc95L, + 0x358bbd6e8948b6e2L,0x1cd9c342e31644beL,0xbab3aa8c60a8a7a7L }, + { 0xe065519fa375beb6L,0xf7d0b0414439990cL,0x8957c03b8517ae8aL, + 0xc96a040173750d6eL,0x4eb2e364b2aee6d7L,0x813054feed099114L } }, + /* 2 << 378 */ + { { 0xbb39a17a7c34f095L,0x7be330a822fbbe61L,0x6be6abe3b91f1482L, + 0xf972804fbd39a2bcL,0x06737e54f91d813eL,0xbd6066681a87cd4aL }, + { 0xbf88b2e5f538d56eL,0xb8206a8134afd68fL,0x7a93aedfa58af042L, + 0x8853cdf6ac0511b0L,0x9d7f416d067e2c19L,0x5d0bc923f9671d8aL } }, + /* 3 << 378 */ + { { 0xf3b6fd79dd3532a7L,0xf60262b5dbbb9e4cL,0xbf75bb57da4d6ac4L, + 0xf016adf1c094b38cL,0x9114cdd012def474L,0xdc74d638c785f143L }, + { 0xdea060d6a8d90bbbL,0x1f141878cbcd0d4cL,0x552685b79ddee1f5L, + 0x381dfc0c636ea6b6L,0x8c601615cb08f34fL,0x5b843830271041eeL } }, + /* 4 << 378 */ + { { 0x2e7d0a16204be028L,0x4f1d082ed0e41851L,0x15f1ddc63eb317f9L, + 0xf02750715adf71d7L,0x2ce33c2eee858bc3L,0xa24c76d1da73b71aL }, + { 0x9ef6a70a6c70c483L,0xefcf170505cf9612L,0x9f5bf5a67502de64L, + 0xd11122a1a4701973L,0x82cfaac2a2ea7b24L,0x6cad67cc0a4582e1L } }, + /* 5 << 378 */ + { { 0x139d9fef6bfc08e4L,0x4399615939ffcb3bL,0xaa299008a84ace07L, + 0xfce43e873cbb2b3fL,0x07b3e8b9191a320eL,0x3ec851d706c4d485L }, + { 0x03d8a672a4bb8477L,0xb6a5dcb213c31d5cL,0x58b79d01c439ab23L, + 0xdd6f8b5134f66137L,0xccb178a0b29be48cL,0x4c71b7aa4df8a1b2L } }, + /* 6 << 378 */ + { { 0x92bf8c4508359896L,0x77253434ae2c30f2L,0xf05086ec827e6cf8L, + 0x46d4729f1771c5d3L,0x92587306f37f0bedL,0xb82c99d2e7c30180L }, + { 0xee0141dcb1684841L,0x7fa984be994ddaf5L,0x5c583347165c238cL, + 0x1a1ad3eea5d78204L,0xcfed795f2736bce6L,0xa7a413318961204eL } }, + /* 7 << 378 */ + { { 0x87451ca71400851dL,0x3aace28e3573ecf6L,0x3a5902cee85717c5L, + 0xe4b51dd0c9f57944L,0x33cf684789a9d8aeL,0x2f6fb08031e6e769L }, + { 0x4bf3da323b78dad1L,0x2d73fef4e7809638L,0x84d76151965109abL, + 0xa2c932c9a2098f46L,0xb8c457c3bc17d1fcL,0x5ef2562d0c8012a4L } }, + /* 8 << 378 */ + { { 0x96a1e74f51e4de5eL,0x72913696e37f5006L,0x12449c4fbe35109cL, + 0x1fad8b304521d7e6L,0xc85eb23d57d00293L,0x4ebd334b35f68229L }, + { 0x7c5b86682df5acf1L,0xc2b4da6e5463de2eL,0x067b0456757cd570L, + 0xeaab81be3a1c866bL,0x72a6af75bbba88c0L,0xaed4dbde0ef567dcL } }, + /* 9 << 378 */ + { { 0x085e33cd9273818aL,0x8fb9294a8cf4e306L,0xaed46bbc35052bd1L, + 0x031febb3374661eaL,0x9386a35d4868dbb2L,0x381e5b521d3f2dddL }, + { 0xa938a3a5179617edL,0xb0fc99f49dc95af1L,0xf446dfa92b9dacbcL, + 0xbae262ae490c1969L,0x042707ffa7443354L,0x8dc0511f267d5c14L } }, + /* 10 << 378 */ + { { 0x8f0e1908fac2674dL,0xd86e85a483e43c26L,0x1f719f7036fb5a4eL, + 0x7ad61b8ca57dbcbcL,0xcf6ba7db0f63dc79L,0xb4315ab11afe8540L }, + { 0x0448e852425c4df3L,0xf51969ef8838a51dL,0xce98589b9eab87deL, + 0x55867b5645149689L,0x9b70bc8c60d2a624L,0xc158a2710b6dbd45L } }, + /* 11 << 378 */ + { { 0x0b262f808f1915f2L,0x64ba3bc73d501e01L,0x8ce2db1f4645152cL, + 0xf4a4f3afab047cdbL,0x1a7c4af600d31e7fL,0x0005bca678d1c0ecL }, + { 0xf5ed135f6fe5ebb0L,0xa299b1002ea9abdfL,0x4fa387e5fccb58f5L, + 0x105b9dd2fc657b72L,0x1494c6050dc3c22cL,0xf7468e8a92d281c7L } }, + /* 12 << 378 */ + { { 0x597a26ffb4dc8600L,0x264a09f3f9288555L,0x0b06aff65c27f5f6L, + 0xce5ab665d8d544e6L,0x92f031be99275c32L,0xaf51c5bbf42e0e7cL }, + { 0x5bb28b061e37b36dL,0x583fba6a8473543aL,0xe73fd299f93fb7dcL, + 0xfcd999a86e2ccad9L,0xb8c8a6df334d4f57L,0x5adb28dd9a2acc9bL } }, + /* 13 << 378 */ + { { 0xc760823646dd14f3L,0xc6d97d37e7a97f33L,0x05037f26de2f444aL, + 0x5267ded09aa9a5c0L,0xd1ef46340be2d841L,0x308b37a8d48b9574L }, + { 0x102f7878487bad5bL,0x1d5169d938b7c1efL,0x2d8adde62c39c75aL, + 0x71bfb8bc0b80f3bbL,0x126505999bff252fL,0xf99e952f24f8bd3bL } }, + /* 14 << 378 */ + { { 0x24496a8b7a8a6d47L,0x9fc75c0aec6afe43L,0x4200e00670744f15L, + 0xe2f87d5e2973be1dL,0x0f6c5993c82e2013L,0xe9ecf6ce198c99f0L }, + { 0xcbdf72058b37d828L,0xbef4b8c8325d1d93L,0x8e962ffbd0fbb134L, + 0xe4273a124bcffc61L,0x4f24ba23f3d93d73L,0x8f02df83bcfcb930L } }, + /* 15 << 378 */ + { { 0x985c8f4b0614348aL,0xca4ca7cd5a03c014L,0x5bdd4382a7b62effL, + 0x623d44b9e4a0bb42L,0x1f28862ef23931d5L,0x30568303868326beL }, + { 0x850d2a0d82e76f04L,0xf4dc02330ac4a153L,0x62b74879b1e70a9aL, + 0x7b32249baf3f0dbbL,0x2f50395d155eae92L,0x6d990c16f6f5c9a4L } }, + /* 16 << 378 */ + { { 0x3afdee277d221ab6L,0xecf10abc47bb619eL,0x340c8ee3ba4a3301L, + 0x1a6ea51a2a883b7fL,0x64f27976d5d7412bL,0x7fcf0ecc91251b6eL }, + { 0x5f3f8f41365b18b7L,0x38e48b96e2e13e58L,0xde3b73d6ad61b2cbL, + 0xf08398d5d542676dL,0xd373931e8e7d712bL,0x89325d7a7f96e023L } }, + /* 17 << 378 */ + { { 0xeb2e48c10bf4e94dL,0x00614bf206b7e166L,0x536c999ce295c451L, + 0x951f92186359cf06L,0xe2a938890afc827fL,0x63102e93ff029787L }, + { 0xab297c7d2ac89645L,0x7354df74928742bfL,0xc0934ca6c8604304L, + 0x36b7e9711cc2f3b4L,0x487ce890e10ee837L,0xe6aa9eabae2ae9e3L } }, + /* 18 << 378 */ + { { 0x6e7a578340517347L,0x7db868f3a950dfa2L,0x7fd7fd8eb3c2eff7L, + 0xae7b59c5fbe10a47L,0x5239b5c4109797d6L,0x3838356a53264b8aL }, + { 0x8df8454c320a8c5aL,0x67c86ef46958fa2cL,0xfe1aad846241a50aL, + 0x3df64ef5a06f3cf3L,0xde6af0ff83282fbdL,0x25ca45046cdbe5feL } }, + /* 19 << 378 */ + { { 0xa319340d6e6c0debL,0x101f055acb1b1cd5L,0x4bea31ad623e7e55L, + 0xc0c88af6aec23cd2L,0xca98c4364aaf2f73L,0x1969eca437dd1341L }, + { 0x6b03989f97866dc3L,0xafdc99532eaf5b08L,0x199ec0e93d6ea9c4L, + 0xc3d1069474f262e9L,0xa7e5670079911cf9L,0xc0213ec56844da05L } }, + /* 20 << 378 */ + { { 0x5adf3d9a111792b9L,0x1c77a3054f1e0d09L,0xf9fbce33a82d3736L, + 0xf307823e718c8aa3L,0x860578cf416ccf69L,0xb942add81ef8465bL }, + { 0x9ee0cf97cd9472e1L,0xe6792eefb01528a8L,0xf99b9a8dc09da90bL, + 0x1f521c2dcbf3ccb8L,0x6bf6694891a62632L,0xcc7a9ceb854fe9daL } }, + /* 21 << 378 */ + { { 0xfc9660a3c8808373L,0x84c5d6a71a50c560L,0x13fe0588ba057fe2L, + 0x29b0341dafb73ad1L,0x37b11137f15f0cd2L,0x84422ba89c2d7eb0L }, + { 0x0b595ac52554ef7fL,0xd7a8303f08b37a84L,0x908895a9e02d77fcL, + 0x70cdeb0c9f242a42L,0x535e8540116e2db8L,0xc88f0cf685c54d31L } }, + /* 22 << 378 */ + { { 0xf534f145e2290ebaL,0x3d081c0d7f15c9e3L,0x716574c5e9ae3da0L, + 0xbe6bd7b92c078aa8L,0xab8802bab8da8e68L,0x0c5be4a1ab204fb0L }, + { 0xad25c5ee0d3f12b3L,0x3929d0d78fc9b7a5L,0x9c6e2ce0bb5cd2fdL, + 0x855367c4924ec2d2L,0x6b532891e6550d3cL,0xab2bc89575ba5c99L } }, + /* 23 << 378 */ + { { 0xb56b035e2a0349adL,0xcfa41da6f89ce836L,0x9d86bcac8b5c43fcL, + 0xc77375da47644b07L,0x9e9c222607f4b670L,0x71d663c80482a61bL }, + { 0xb423e739ef237431L,0xf1cedf7e48832b5bL,0x09e0cb2a7ca7548bL, + 0x9b463559631b9850L,0x8a2bd7fed4dd03deL,0x46115292ae0c97d3L } }, + /* 24 << 378 */ + { { 0xe44e3f864b3759cfL,0x90cab0eb9d74e3f6L,0x1004254501c4e171L, + 0xc12df68cce52defbL,0xb1fae2fbf363100aL,0x5016c8533573235fL }, + { 0x8d4deb661d922e9bL,0x8a20d42317f84ef2L,0x324985835a4e118eL, + 0x5abfa961308772e9L,0x41c7611ff54e4876L,0xc1da40d31f5867b2L } }, + /* 25 << 378 */ + { { 0x4df02a7d3088aebcL,0x7dea27ea12487485L,0x2a773270df98069eL, + 0xea435fa0e9ceaf44L,0x08e952e365e5ebabL,0x972877d5c3511480L }, + { 0xef5685f859a04cd0L,0xe50abe68b8c7c796L,0xbbb792e2c3225f20L, + 0x7d9878e811c89153L,0x4b72a1e619354751L,0x7d5f05a3faa1be22L } }, + /* 26 << 378 */ + { { 0x61dd7692f27eed54L,0x8540213ea7a3f2f7L,0xe659cbd6ace07e13L, + 0x3a998cdcc8995cacL,0x0accb4a7922d3b25L,0x762b3406c6577d81L }, + { 0xa09db4f57e043740L,0x7f78e02d8cc9bc5fL,0x080a522673b98cd3L, + 0xb6d72f7ce6490808L,0x36815de2c724284aL,0xc27d13df98b867b5L } }, + /* 27 << 378 */ + { { 0xbfeffd5356adb6e4L,0xb5e8876c499a1455L,0x4771281390833f18L, + 0x5f49ef880115b9a5L,0xb041ec67cf575de5L,0x490753350b7e4afcL }, + { 0xad4dc4a15f0b9f24L,0x9dbb181edafad9a5L,0xa84431a6e6ed5198L, + 0x33ee16e27993eed6L,0xfdf76899c1e4f8b4L,0x868d06baff60e943L } }, + /* 28 << 378 */ + { { 0x46303171491ccb92L,0xa80a8c0d2771235bL,0xd8e497fff172c7cfL, + 0x7f7009d735b193cfL,0x6b9fd3f7f19df4bcL,0xada548c3b46f1e37L }, + { 0x87c6eaa9c7a20270L,0xef2245d6ae78ef99L,0x2a121042539eab95L, + 0x29a6d5d779b8f5ccL,0x33803a10b77840dcL,0xfedd3a7011a6a30fL } }, + /* 29 << 378 */ + { { 0x5d782a0778664144L,0xc1413da46682c779L,0x937a15f52a67b12bL, + 0x8ec00d9fc04d8cd5L,0x3f16d1ed3b5fe8d6L,0x24ad6b0ca28c8067L }, + { 0xdd1eecc532732b19L,0x62c4c2beab2fa785L,0x7d863f5b2ac0c238L, + 0xd686eb7239384e15L,0x3770e54d16bd75b2L,0xdcd9e4e8120b3881L } }, + /* 30 << 378 */ + { { 0xe3052838df5147e1L,0x87bc4d75b1baaa7cL,0x49b13eb95acc5572L, + 0x919081881990c13cL,0x5d43a4a6191cc808L,0x20b358444182aa55L }, + { 0x70d49a4a670b1fd1L,0xc6e6e061722e91e7L,0x8d130b3900c5ae9eL, + 0x5db7d06920f68ec5L,0x85b6c505470fbe13L,0x14101ec7326c4d38L } }, + /* 31 << 378 */ + { { 0xeef03450e10e8018L,0x75921e487576c3ddL,0x6c8e22676e97f5afL, + 0xd7323e01a856ae6bL,0x43a195425fed884fL,0x010865380377ba8fL }, + { 0x7cdbd06ac82a8f67L,0xc6fce58bf0fd4281L,0xae098b7f9e67bed0L, + 0x0c8d328bdd918524L,0xddf723ec0a11fb83L,0x210d6016e25a2073L } }, + /* 32 << 378 */ + { { 0x3c90a59f85adde98L,0x35414174e5269140L,0x9aca885c1a0d58e2L, + 0x77b9b6dd6816b009L,0x8e5c12139ee4718fL,0x60ad991e4e4eac45L }, + { 0xc00c35694d71f624L,0xacbf4eb25bc5fd2aL,0xcba1ffc75eaf3eaaL, + 0x5f99092d42a87e32L,0x2e7b49c76f7a882fL,0x5e9bfc5c29040512L } }, + /* 33 << 378 */ + { { 0xa31d3524b295958dL,0x9713a5e04894f486L,0xe8804ab3329a0b9aL, + 0xd4447c1b20eefa54L,0xf5b944c9040b7ad4L,0x9db0ee0b907f2cfdL }, + { 0x0b1a1f3a5384a999L,0x3137241ea8351764L,0xe0663b5ab29c3cffL, + 0x2b47ca0622d4deefL,0x4f952109f1172bcdL,0x1e7a7fca9b447bd4L } }, + /* 34 << 378 */ + { { 0xc9898355ecf2a473L,0x20d0c4740dcd66f6L,0x6459720f8eeefff5L, + 0xd9b625dcf9ce0cdeL,0xed3a6508ea56be90L,0x6847c20de211c90eL }, + { 0x36d86bed71a73ceeL,0x9222eab23023d16eL,0x3155874750209b4dL, + 0xcac8f277d145b831L,0x49cedc634470e754L,0x6c7c065add370f77L } }, + /* 35 << 378 */ + { { 0x46a95735f8171804L,0x1ff2549ec4c93476L,0xfb8a08285bb5202dL, + 0xaff5505f1070737aL,0x162aaad842f412c5L,0x02a37213fac8a477L }, + { 0x05ff9238932f08e2L,0x9be6a0b29fc66787L,0x373a9039db1e5a40L, + 0xe657e8c782d04913L,0xa2006f207e6ee867L,0xd7aa1d2378d82f9aL } }, + /* 36 << 378 */ + { { 0xfa070e22142403d1L,0x68ff316015c6f7f5L,0xe09f04e6223a0ce8L, + 0x22bbd01853e14183L,0x35d9fafccf45b75bL,0x3a34819d7eceec88L }, + { 0xd9cf7568d33262d2L,0x431036d5841d1505L,0x0c8005659eb2a79aL, + 0x8e77d9f05f7edc6aL,0x19e12d0565e800aaL,0x335c8d36b7784e7cL } }, + /* 37 << 378 */ + { { 0xdcac39d87c1d9f4dL,0x88322d8bc225ce6eL,0x5c240cefa3ef5202L, + 0xf60ce5d991f1d487L,0x8e857069e462cfa8L,0xa6e5585e996d2033L }, + { 0x709675a556281e6aL,0xcd90c140f907ebf0L,0x5343a0a2a3231eecL, + 0x74b1443214892291L,0xf8cb9c26a5325b8cL,0x1bb28be140089be5L } }, + /* 38 << 378 */ + { { 0x2bb6e7ec3092d0b2L,0xc7c9e5f1d27d1f31L,0xbac785aeac0939e3L, + 0x186d3d934f810d8fL,0xda296dacfe7d778fL,0x6189f5e41a991ea2L }, + { 0x098f794e9634363eL,0x04aaf59a88a4dccaL,0x09d718487196dfa8L, + 0xa447a31ed83044a6L,0x720cd3908d1363fdL,0x6f670479e22efa03L } }, + /* 39 << 378 */ + { { 0xaa452e81cdf60f9aL,0xf3dc472a8e2c58e9L,0x16ddefa50589fd01L, + 0xd56ec8f223a1656eL,0xcccb784f77921ca4L,0x9bace7adf8a7c0baL }, + { 0xc94ef3ef51f052e2L,0xa70c0579c34e7cb5L,0x3599817883ce8674L, + 0x033647c392a20951L,0xc828fcc77a21add6L,0x5a446de871ba27a5L } }, + /* 40 << 378 */ + { { 0x75cba9d530a3ada1L,0xb69e308bf8ae9565L,0x990e3425ca7b8369L, + 0x9f67567fe0a7ad0bL,0x76ed6fe718bd01b7L,0x282358aa2ff95cfeL }, + { 0x28d2ea41410f8841L,0x89d1533fccd67c81L,0x969bb272b6a7b8f9L, + 0x54f8664c26330782L,0xb89f3ae81dcd9164L,0x54d845b93d962c14L } }, + /* 41 << 378 */ + { { 0x08ba5b61fde4ca03L,0x39b1a9c697b17ee6L,0x885253779336b2b9L, + 0xe964dc9c9aabc3fcL,0x6aed101a5295e728L,0x30369ea0ee12356aL }, + { 0xe081e022c8e80e5eL,0x3a769ef0df9f47c0L,0x3b2f7aab5590750cL, + 0xd16c7a85a1a5e504L,0x9e528623e854d7cfL,0xaca079354468e419L } }, + /* 42 << 378 */ + { { 0xee521c0af93098bfL,0xf517c925b79aa0ebL,0x17779f5e7bbc58feL, + 0x093c3dc2769de891L,0xafbf32372a69ad0dL,0x33a95de702001e8cL }, + { 0x3b30afc73410a2b0L,0xb379a3f425bc7d9aL,0xf1c069251604a646L, + 0x04f0bb334fca052fL,0xe5cd9c39cab33871L,0xf259795816fa1b16L } }, + /* 43 << 378 */ + { { 0x291d65c801189d9aL,0xb16ca18bd8e94e49L,0x55f7680599440d4bL, + 0x55d40c1b2eb7f0fdL,0x752d98f6018d7c64L,0xa1cae78c7b491c4dL }, + { 0x898fc8c78f66b8d3L,0xbb48956a3ceecd27L,0xb8f9498dfaa9451fL, + 0x583b336aa5683ef8L,0x0deaa373e92656f4L,0x7f87b4412a9a0272L } }, + /* 44 << 378 */ + { { 0x8b2fc4e96484fd40L,0xee702764a35d24eaL,0x15b28ac7b871c3f3L, + 0x805b4048e097047fL,0xd6f1b8df647cad2fL,0xf1d5b458dc7dd67fL }, + { 0x324c529c25148803L,0xf6185ebe21274fafL,0xaf14751e95148b55L, + 0x283ed89d28f284f4L,0x93ad20e74cbebf1aL,0x5f6ec65d882935e1L } }, + /* 45 << 378 */ + { { 0x4b0c7d0c69c284cbL,0x907e4f38199c5176L,0x4ebfbda7cf3dab12L, + 0x675f12cca4fa74a9L,0x86628102bdf579e6L,0xf08cbfe771c4d061L }, + { 0x9dde390e03bc1cb9L,0xb6d0d48b4c727915L,0x7cad28c370c0b7bfL, + 0x8d978a8110d1e881L,0x1c071597924baeb1L,0x83c09192eb103fe0L } }, + /* 46 << 378 */ + { { 0x494dbd2665925506L,0xe239b1d404b6fc45L,0x38a1ec5ce16b874dL, + 0x1588c4712a3f012dL,0x5bd45adcdc6938b9L,0xe4c35c2244ab2fccL }, + { 0x87cbd9ff887108a2L,0x92a9c3b2144fd3eeL,0x3a0e55c7982a4928L, + 0xcaf679765bb0fddfL,0x04616318263ea256L,0x56eb022838caa901L } }, + /* 47 << 378 */ + { { 0x2f7de141a48da000L,0x323bd638835a4edfL,0xd2d9da967e155bd5L, + 0x717c302a766b69daL,0x5927968beb0f6ca5L,0xfd96bd168940c766L }, + { 0xf89f7539a334fd71L,0x4ba9cd8bd870954fL,0x7e639523a3d57aa8L, + 0x88f31e162314c0ceL,0xa836a6ad53b7e6e9L,0xd35a825190e43169L } }, + /* 48 << 378 */ + { { 0xb3984b176c0f3509L,0xf9fa4483d8b4d6bcL,0xf4ac2b677dec20d2L, + 0x67ef024eb3dbe034L,0x2dcc51180f94f4d7L,0x024cdcfd74a51393L }, + { 0xf1c0fead20e7abcbL,0xffc18f81d3a7414fL,0xb00ce5567062cb0bL, + 0xeccb0521817bc8d1L,0xa0c0fe6040411c15L,0x053113221defbe00L } }, + /* 49 << 378 */ + { { 0x74faca8a6af7e742L,0x6f206002d878a97aL,0xd69b7c83177305ffL, + 0x605e7a32d2e2bcf1L,0x65bd03584590bf03L,0xab3ae700d1a378c5L }, + { 0x037e79028a929b0dL,0x83625ae0a7c451c6L,0x82a18f03492b01d4L, + 0x12c6d168e67756b1L,0x1e704c3bd7924df1L,0x7708617f1989244eL } }, + /* 50 << 378 */ + { { 0x4c98c61d097bde48L,0x6a55edf1c354f433L,0x1ceee947c3f39212L, + 0x162cf27f36ba3cebL,0xd9f3982e3ec5f7ffL,0xd363e435d58d42d2L }, + { 0x2ee90d7bad36681dL,0xd916df56ebfbf51cL,0x61d94ed8d7c27fe7L, + 0x5010582e923c1acdL,0x89d23e8b6de52994L,0x0a4f9c10525dbccfL } }, + /* 51 << 378 */ + { { 0x7778fad7e65573e2L,0xa4af7a2d74986210L,0xd78ecebfec57d967L, + 0x9be8a33f67d61b2eL,0x6888444f98a9add7L,0x218e7fb1b71a25a4L }, + { 0xf75a6b795f46323bL,0x2f8610ad11a52cd9L,0x23692f85fc6837caL, + 0x3a37965f71fe847bL,0x29c25cc3fe3bdeeeL,0x68fefc83f624665aL } }, + /* 52 << 378 */ + { { 0xe222eba4a4dcefe9L,0x63ad235fec1ceb74L,0x2e0bf749e05b18e7L, + 0x547bd050b48bdd87L,0x0490c970f5aa2fc4L,0xced5e4cf2b431390L }, + { 0x07d8270451d2898eL,0x44b72442083b57d4L,0xa4ada2305037fce8L, + 0x55f7905e50510da6L,0xd8ee724f8d890a98L,0x925a8e7c11b85640L } }, + /* 53 << 378 */ + { { 0x8357d8bb460e77b2L,0xc749a6a77709a52bL,0x94035a1f0c82ab81L, + 0x15245ac616c11ef4L,0xbf3cd96c034d021bL,0xf79e2d39b2e8fac1L }, + { 0x387015194b6cf1bdL,0x341f9b53b3143bf7L,0xb2584aabdda9acf2L, + 0x16f34bdd553a8e68L,0x89d0c4c5da7830b3L,0x6cfe44c63f488c2eL } }, + /* 54 << 378 */ + { { 0xee536a26d4bcaa59L,0x5ea6a57c699397bfL,0xb28f476b59a7eb99L, + 0xa901f2551406ec90L,0x7b6e3e4d1f54ef38L,0x058ff1904c89c9a8L }, + { 0x5690fa10fca546ccL,0xfe98793145e14268L,0x6181fa1675362f5dL, + 0x3ebe84466964b9aeL,0x3e1957812ce0f969L,0xb33ea619b0195852L } }, + /* 55 << 378 */ + { { 0xeef402410ec537acL,0x1f72c1f8911316f6L,0xab4bb08268cc6678L, + 0x031fc087255e8c5eL,0x99c2ff0b948ac53bL,0x13db3201919c1870L }, + { 0xdec81fd312057a3cL,0xbdffa226ff7a44cbL,0x748d2e93d97167e2L, + 0x33a9fe40bd21effeL,0xe08e4213817ea560L,0x2221798b9f4337d5L } }, + /* 56 << 378 */ + { { 0xda828fe556467257L,0x5e9abf67d640c2a1L,0x0eed233cc25c696aL, + 0x72483dc5b3e1d84fL,0x30bf1ee34f114abcL,0xf58b321ed1f9bce8L }, + { 0xcb26564c97524f33L,0xdc2f105e1e453229L,0x9da43ceb72a982ddL, + 0xecf5649dfeef8862L,0xd8afda341fa2f06dL,0xf0d0ced355035432L } }, + /* 57 << 378 */ + { { 0xec22bb32205a5301L,0xe4d168e75b0b727bL,0x91217a6be34fe2e0L, + 0x03c6831675f0f139L,0xb21e275d8b991b29L,0x7f517c9c01f3f401L }, + { 0xbbe95d19e55e49faL,0xc5470808504514b1L,0xb88be15c7cc1367dL, + 0x242cb06bbfd24bacL,0x08647a158d2ab0baL,0x8f1fd1bd5716ed9bL } }, + /* 58 << 378 */ + { { 0xe787054518ba5236L,0x243622f9e8a47507L,0xe7d94f4697b97d7cL, + 0xb120589021649255L,0x8b5101310dd4e1d4L,0x1690687e164c44baL }, + { 0x65bb4d8cf100fef5L,0xfffffee70a684c3dL,0x2aa11707c463a975L, + 0xccaddeaf391ad03dL,0x4d2cda1c81cca7deL,0x9d3eaa58c5b0f8e7L } }, + /* 59 << 378 */ + { { 0x3d92ecc18f8802dfL,0x3024ce311a719461L,0x6bdf53fc46c1f31bL, + 0x4f4576a12c9c7744L,0xe1ee7508c3ff7356L,0xd4b25ed3883ebf03L }, + { 0x1dc46052420c3ac9L,0x376ebbfa11ecefa9L,0x36e175265e9693f5L, + 0xeb82b33740ed3143L,0x6960312ff19fa66aL,0xc7edb5db6c742e1bL } }, + /* 60 << 378 */ + { { 0x5bfa10cd1ca459edL,0x593f085a6dcf56bfL,0xe6f0ad9bc0579c3eL, + 0xc11c95a22527c1adL,0x7cfa71e1cf1cb8b3L,0xedcff8331d6dc79dL }, + { 0x581c4bbe432521c9L,0xbf620096144e11a0L,0x54c38b71be3a107bL, + 0xed555e37e2606ec0L,0x3fb148b8d721d034L,0x79d53dad0091bc90L } }, + /* 61 << 378 */ + { { 0x4b98cb69c5c8a182L,0x887071bbcac96dabL,0x03d42e96afc190c3L, + 0xbc2c3b8d7a813820L,0x1ee7797f6590d0ecL,0x4a95f7f3ad4777a4L }, + { 0x7a36de4e2a8d2736L,0x7f8c6751ad78dab6L,0xf9874bf6974c0a8eL, + 0x759fee1c8b53025aL,0x1b00fb28a2171c8bL,0xdf206f19be8f2e7eL } }, + /* 62 << 378 */ + { { 0xe6bbcf0bf8ed6302L,0x7734dc91f8fe7a42L,0x840210ee61ff9d1eL, + 0xbbf2d5477007f2e9L,0x0f17d421a6542ac0L,0x0b2d3d2ee01df4e9L }, + { 0x520e4fbb84f3703fL,0x8362f7b1431106b7L,0xdcfc96ae6e50d836L, + 0x2dfa176cc44153bbL,0xeef1c6710b09ffe2L,0x633a2ac888531d81L } }, + /* 63 << 378 */ + { { 0x29262b6d7636a78dL,0xdc504f01d3ce2967L,0xa441e5035bcf0e19L, + 0x8025224f7ad39d9aL,0x780ec65de871b792L,0x977b4bce597694b4L }, + { 0xe05eaeb87fe3ef11L,0x1cff87ac9748b10eL,0xb669c1d60c34153aL, + 0xf5da63e0f8f90368L,0x6f7f2fc47d31bf61L,0x37e9158235c16a0fL } }, + /* 64 << 378 */ + { { 0xcf17f9dc08d1be5dL,0xb55de4c8afdfeb23L,0xa69454ffe437b29cL, + 0x6628d789e27ee9e2L,0x56e3b975ee3af03bL,0x0083fe9c2f532d62L }, + { 0xcae15213e63e7511L,0xdb5384f386ed849cL,0x902ba959fa4d825fL, + 0xbad700d55ae17566L,0x16b2c5dc14c82eb4L,0xa4b057a736708ea7L } }, +}; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Pre-computed table containing multiples of g times powers of 2. + * Width between powers is 7 bits. + * Accumulate into the result. + * + * r Resulting point. + * g Point to scalar multiply. + * k Scalar to multiply by. + * table Pre-computed table of points. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_add_only_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 rt[2]; + sp_digit tmp[2 * 6 * 6]; +#endif + sp_point_384* p = NULL; + sp_digit* negy = NULL; + int i; + ecc_recode_384 v[55]; + int err = MP_OKAY; + + (void)g; + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + negy = tmp; + p = rt + 1; + } + + if (err == MP_OKAY) { + sp_384_ecc_recode_7_6(k, v); + + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + i = 54; + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_65_6(rt, &table[i * 65], v[i].i); + } + else + #endif + { + XMEMCPY(rt->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(rt->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + } + rt->infinity = !v[i].i; + for (--i; i>=0; i--) { + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_65_6(p, &table[i * 65], v[i].i); + } + else + #endif + { + XMEMCPY(p->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(p->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + } + p->infinity = !v[i].i; + sp_384_sub_6(negy, p384_mod, p->y); + sp_384_norm_6(negy); + sp_384_cond_copy_6(p->y, negy, 0 - v[i].neg); + sp_384_proj_point_add_qz1_6(rt, rt, p, tmp); + } + if (map != 0) { + sp_384_map_6(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 6 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return MP_OKAY; +} + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_384_ecc_mulmod_add_only_6(r, NULL, p384_table, + k, map, ct, heap); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Pre-computed table containing multiples of g times powers of 2. + * Width between powers is 7 bits. + * Accumulate into the result. + * + * r Resulting point. + * g Point to scalar multiply. + * k Scalar to multiply by. + * table Pre-computed table of points. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_add_only_avx2_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* rt = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 rt[2]; + sp_digit tmp[2 * 6 * 6]; +#endif + sp_point_384* p = NULL; + sp_digit* negy = NULL; + int i; + ecc_recode_384 v[55]; + int err = MP_OKAY; + + (void)g; + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + negy = tmp; + p = rt + 1; + } + + if (err == MP_OKAY) { + sp_384_ecc_recode_7_6(k, v); + + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + i = 54; + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_65_avx2_6(rt, &table[i * 65], v[i].i); + } + else + #endif + { + XMEMCPY(rt->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(rt->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + } + rt->infinity = !v[i].i; + for (--i; i>=0; i--) { + #ifndef WC_NO_CACHE_RESISTANT + if (ct) { + sp_384_get_entry_65_avx2_6(p, &table[i * 65], v[i].i); + } + else + #endif + { + XMEMCPY(p->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(p->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + } + p->infinity = !v[i].i; + sp_384_sub_6(negy, p384_mod, p->y); + sp_384_norm_6(negy); + sp_384_cond_copy_6(p->y, negy, 0 - v[i].neg); + sp_384_proj_point_add_qz1_avx2_6(rt, rt, p, tmp); + } + if (map != 0) { + sp_384_map_avx2_6(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 6 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return MP_OKAY; +} + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_ecc_mulmod_base_avx2_6(sp_point_384* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_384_ecc_mulmod_add_only_avx2_6(r, NULL, p384_table, + k, map, ct, heap); +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* WOLFSSL_SP_SMALL */ /* Multiply the base point of P384 by the scalar and return the result. * If map is true then convert result to affine coordinates. * @@ -29394,31 +47148,33 @@ static int sp_384_ecc_mulmod_base_avx2_6(sp_point_384* r, const sp_digit* k, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[6]; +#endif int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_384_point_new_6(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif + if (err == MP_OKAY) { sp_384_from_mp(k, 6, km); @@ -29433,12 +47189,108 @@ int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* r, int map, void* heap) err = sp_384_point_to_ecc_point_6(point, r); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P384 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; + sp_digit* k = NULL; +#else + sp_point_384 point[2]; + sp_digit k[6 + 6 * 2 * 6]; +#endif + sp_point_384* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (6 + 6 * 2 * 6), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; } #endif - sp_384_point_free_6(point, 0, heap); + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 6; + + sp_384_from_mp(k, 6, km); + sp_384_point_from_ecc_point_6(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->x, addP->x, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->y, addP->y, p384_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_384_mod_mul_norm_6(addP->z, addP->z, p384_mod); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(point, k, 0, 0, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_proj_point_add_avx2_6(point, point, addP, tmp); + else +#endif + sp_384_proj_point_add_6(point, point, addP, tmp); + + if (map) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_map_avx2_6(point, point, tmp); + else +#endif + sp_384_map_6(point, point, tmp); + } + + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -29456,7 +47308,7 @@ static int sp_384_iszero_6(const sp_digit* a) return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5]) == 0; } -#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ extern void sp_384_add_one_6(sp_digit* a); extern void sp_384_from_bin_bswap(sp_digit* r, int size, const byte* a, int n); extern void sp_384_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); @@ -29469,12 +47321,15 @@ extern void sp_384_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); */ static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_384_from_bin_movbe(r, size, a, n); } - else { + else +#endif + { sp_384_from_bin_bswap(r, size, a, n); } } @@ -29517,44 +47372,49 @@ static int sp_384_ecc_gen_k_6(WC_RNG* rng, sp_digit* k) */ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_point_384 inf; -#endif -#endif - sp_point_384* point; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* point = NULL; sp_digit* k = NULL; +#else + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; + #else + sp_point_384 point[1]; + #endif + sp_digit k[6]; +#endif #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN sp_point_384* infinity = NULL; #endif - int err; + int err = MP_OKAY; + #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif (void)heap; - err = sp_384_point_new_6(heap, p, point); -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, inf, infinity); - } -#endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC); + #else + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); + #endif + if (point == NULL) + err = MEMORY_E; if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); - if (k == NULL) { + DYNAMIC_TYPE_ECC); + if (k == NULL) err = MEMORY_E; - } } -#else - k = kd; #endif if (err == MP_OKAY) { + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + infinity = point + 1; + #endif + err = sp_384_ecc_gen_k_6(rng, k); } if (err == MP_OKAY) { @@ -29591,15 +47451,14 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) err = sp_384_point_to_ecc_point_6(point, pub); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) { + /* point is not sensitive, so no need to zeroize */ + XFREE(point, heap, DYNAMIC_TYPE_ECC); } #endif -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - sp_384_point_free_6(infinity, 1, heap); -#endif - sp_384_point_free_6(point, 1, heap); return err; } @@ -29615,12 +47474,15 @@ extern void sp_384_to_bin_movbe(sp_digit* r, byte* a); */ static void sp_384_to_bin(sp_digit* r, byte* a) { +#ifndef NO_MOVBE_SUPPORT word32 cpuid_flags = cpuid_get_flags(); if (IS_INTEL_MOVBE(cpuid_flags)) { sp_384_to_bin_movbe(r, a); } - else { + else +#endif + { sp_384_to_bin_bswap(r, a); } } @@ -29637,15 +47499,16 @@ static void sp_384_to_bin(sp_digit* r, byte* a) * returns BUFFER_E if the buffer is to small for output size, * MEMORY_E when memory allocation fails and MP_OKAY on success. */ -int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 p; - sp_digit kd[6]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_point_384* point = NULL; sp_digit* k = NULL; +#else + sp_point_384 point[1]; + sp_digit k[6]; +#endif int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -29655,18 +47518,19 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, err = BUFFER_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, p, point); + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (k == NULL) err = MEMORY_E; } -#else - k = kd; #endif if (err == MP_OKAY) { @@ -29684,12 +47548,12 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, *outLen = 48; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (k != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) XFREE(k, heap, DYNAMIC_TYPE_ECC); - } + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(point, 0, heap); return err; } @@ -29701,9 +47565,29 @@ int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, #endif #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) extern sp_digit sp_384_sub_in_place_6(sp_digit* a, const sp_digit* b); -extern sp_digit sp_384_cond_sub_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); extern void sp_384_mul_d_6(sp_digit* r, const sp_digit* a, sp_digit b); extern void sp_384_mul_d_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_384_word_asm_6(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_384_word_6(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_384_word_asm_6(d1, d0, div); +#endif +} +#else /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * * d1 The high order half of the number to divide. @@ -29723,6 +47607,7 @@ static WC_INLINE sp_digit div_384_word_6(sp_digit d1, sp_digit d0, ); return r; } +#endif /* _WIN64 */ /* AND m into each word of a and store in r. * * r A single precision integer. @@ -29759,8 +47644,10 @@ static void sp_384_mask_6(sp_digit* r, const sp_digit* a, sp_digit m) static WC_INLINE int sp_384_div_6(const sp_digit* a, const sp_digit* d, sp_digit* m, sp_digit* r) { - sp_digit t1[12], t2[7]; - sp_digit div, r1; + sp_digit t1[12]; + sp_digit t2[7]; + sp_digit div; + sp_digit r1; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -29813,7 +47700,8 @@ static WC_INLINE int sp_384_div_6(const sp_digit* a, const sp_digit* d, sp_digit * m A single precision number that is the modulus to reduce with. * returns MP_OKAY indicating success. */ -static WC_INLINE int sp_384_mod_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +static WC_INLINE int sp_384_mod_6(sp_digit* r, const sp_digit* a, + const sp_digit* m) { return sp_384_div_6(a, m, NULL, r); } @@ -29830,7 +47718,6 @@ static const uint64_t p384_order_minus_2[6] = { /* The low half of the order-2 of the P384 curve. */ static const uint64_t p384_order_low[3] = { 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU - }; #endif /* WOLFSSL_SP_SMALL */ @@ -29978,7 +47865,7 @@ static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_6(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_6(t2, t2); - if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_384_mont_mul_order_6(t2, t2, a); } } @@ -30132,7 +48019,7 @@ static void sp_384_mont_inv_order_avx2_6(sp_digit* r, const sp_digit* a, sp_384_mont_mul_order_avx2_6(t2, t2, t); for (i=191; i>=1; i--) { sp_384_mont_sqr_order_avx2_6(t2, t2); - if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + if ((p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { sp_384_mont_mul_order_avx2_6(t2, t2, a); } } @@ -30142,12 +48029,86 @@ static void sp_384_mont_inv_order_avx2_6(sp_digit* r, const sp_digit* a, } #endif /* HAVE_INTEL_AVX2 */ -#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_SIGN #ifndef SP_ECC_MAX_SIG_GEN #define SP_ECC_MAX_SIG_GEN 64 #endif +/* Calculate second signature value S from R, k and private value. + * + * s = (r * x + e) / k + * + * s Signature value. + * r First signature value. + * k Ephemeral private key. + * x Private key as a number. + * e Hash of message as a number. + * tmp Temporary storage for intermediate numbers. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_s_6(sp_digit* s, const sp_digit* r, sp_digit* k, + sp_digit* x, const sp_digit* e, sp_digit* tmp) +{ + int err; + sp_digit carry; + int64_t c; + sp_digit* kInv = k; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mul_avx2_6(k, k, p384_norm_order); + else +#endif + sp_384_mul_6(k, k, p384_norm_order); + err = sp_384_mod_6(k, k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(k); + + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mont_inv_order_avx2_6(kInv, k, tmp); + else +#endif + sp_384_mont_inv_order_6(kInv, k, tmp); + sp_384_norm_6(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mul_avx2_6(x, x, r); + else +#endif + sp_384_mul_6(x, x, r); + err = sp_384_mod_6(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(x); + carry = sp_384_add_6(s, e, x); + sp_384_cond_sub_6(s, s, p384_order, 0 - carry); + sp_384_norm_6(s); + c = sp_384_cmp_6(s, p384_order); + sp_384_cond_sub_6(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mont_mul_order_avx2_6(s, s, kInv); + else +#endif + sp_384_mont_mul_order_6(s, s, kInv); + sp_384_norm_6(s); + } + + return err; +} + /* Sign the hash using the private key. * e = [hash, 384 bits] from binary * r = (k.G)->x mod order @@ -30182,8 +48143,8 @@ typedef struct sp_ecc_sign_384_ctx { int i; } sp_ecc_sign_384_ctx; -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, + mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; @@ -30201,13 +48162,10 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W hashLen = 48U; } - sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); - ctx->i = SP_ECC_MAX_SIG_GEN; ctx->state = 1; break; case 1: /* GEN */ - sp_384_from_mp(ctx->x, 6, priv); /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_6(rng, ctx->k); @@ -30235,6 +48193,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W c = sp_384_cmp_6(ctx->r, p384_order); sp_384_cond_sub_6(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_6(ctx->r); + + sp_384_from_mp(ctx->x, 6, priv); + sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); ctx->state = 4; break; } @@ -30291,6 +48252,9 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W ctx->state = 10; break; } + #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + ctx->i = 1; + #endif /* not usable gen, try again */ ctx->i--; @@ -30323,30 +48287,23 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap) +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit ed[2*6]; - sp_digit xd[2*6]; - sp_digit kd[2*6]; - sp_digit rd[2*6]; - sp_digit td[3 * 2*6]; - sp_point_384 p; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 6]; + sp_point_384 point[1]; +#endif sp_digit* x = NULL; sp_digit* k = NULL; sp_digit* r = NULL; sp_digit* tmp = NULL; - sp_point_384* point = NULL; - sp_digit carry; sp_digit* s = NULL; - sp_digit* kInv = NULL; - int err = MP_OKAY; int64_t c; + int err = MP_OKAY; int i; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); @@ -30354,44 +48311,34 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, (void)heap; - err = sp_384_point_new_6(heap, p, point); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - e = d + 0 * 6; - x = d + 2 * 6; - k = d + 4 * 6; - r = d + 6 * 6; - tmp = d + 8 * 6; -#else - e = ed; - x = xd; - k = kd; - r = rd; - tmp = td; -#endif + x = e + 2 * 6; + k = e + 4 * 6; + r = e + 6 * 6; + tmp = e + 8 * 6; s = e; - kInv = k; if (hashLen > 48U) { hashLen = 48U; } - - sp_384_from_bin(e, 6, hash, (int)hashLen); } for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - sp_384_from_mp(x, 6, priv); - /* New random point. */ if (km == NULL || mp_iszero(km)) { err = sp_384_ecc_gen_k_6(rng, k); @@ -30406,7 +48353,7 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_ecc_mulmod_base_avx2_6(point, k, 1, 1, heap); else #endif - err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, NULL); + err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, heap); } if (err == MP_OKAY) { @@ -30417,58 +48364,19 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, sp_384_cond_sub_6(r, r, p384_order, 0L - (sp_digit)(c >= 0)); sp_384_norm_6(r); - /* Conv k to Montgomery form (mod order) */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_384_mul_avx2_6(k, k, p384_norm_order); - else -#endif - sp_384_mul_6(k, k, p384_norm_order); - err = sp_384_mod_6(k, k, p384_order); - } - if (err == MP_OKAY) { - sp_384_norm_6(k); - /* kInv = 1/k mod order */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_384_mont_inv_order_avx2_6(kInv, k, tmp); - else -#endif - sp_384_mont_inv_order_6(kInv, k, tmp); - sp_384_norm_6(kInv); + sp_384_from_mp(x, 6, priv); + sp_384_from_bin(e, 6, hash, (int)hashLen); - /* s = r * x + e */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_384_mul_avx2_6(x, x, r); - else -#endif - sp_384_mul_6(x, x, r); - err = sp_384_mod_6(x, x, p384_order); + err = sp_384_calc_s_6(s, r, k, x, e, tmp); } - if (err == MP_OKAY) { - sp_384_norm_6(x); - carry = sp_384_add_6(s, e, x); - sp_384_cond_sub_6(s, s, p384_order, 0 - carry); - sp_384_norm_6(s); - c = sp_384_cmp_6(s, p384_order); - sp_384_cond_sub_6(s, s, p384_order, 0L - (sp_digit)(c >= 0)); - sp_384_norm_6(s); - /* s = s * k^-1 mod order */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_384_mont_mul_order_avx2_6(s, s, kInv); - else -#endif - sp_384_mont_mul_order_6(s, s, kInv); - sp_384_norm_6(s); - - /* Check that signature is usable. */ - if (sp_384_iszero_6(s) == 0) { - break; - } + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_6(s) == 0)) { + break; } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif } if (i == 0) { @@ -30482,20 +48390,24 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, err = sp_384_to_mp(s, sm); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XMEMSET(d, 0, sizeof(sp_digit) * 8 * 6); - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } -#else - XMEMSET(e, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(x, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(k, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); - XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) #endif - sp_384_point_free_6(point, 1, heap); + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } return err; } @@ -30586,6 +48498,143 @@ static int sp_384_mod_inv_6(sp_digit* r, const sp_digit* a, const sp_digit* m) } #endif /* WOLFSSL_SP_SMALL */ + +/* Add point p1 into point p2. Handles p1 == p2 and result at infinity. + * + * p1 First point to add and holds result. + * p2 Second point to add. + * tmp Temporary storage for intermediate numbers. + */ +static void sp_384_add_points_6(sp_point_384* p1, const sp_point_384* p2, + sp_digit* tmp) +{ +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_proj_point_add_avx2_6(p1, p1, p2, tmp); + } + else +#endif + sp_384_proj_point_add_6(p1, p1, p2, tmp); + if (sp_384_iszero_6(p1->z)) { + if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_proj_point_dbl_avx2_6(p1, p2, tmp); + } + else +#endif + sp_384_proj_point_dbl_6(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } +} + +/* Calculate the verification point: [e/s]G + [r/s]Q + * + * p1 Calculated point. + * p2 Public point and temporary. + * s Second part of signature as a number. + * u1 Temporary number. + * u2 Temproray number. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_384_calc_vfy_point_6(sp_point_384* p1, sp_point_384* p2, + sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap) +{ + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifndef WOLFSSL_SP_SMALL + { + sp_384_mod_inv_6(s, s, p384_order); + } +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mul_avx2_6(s, s, p384_norm_order); + } + else +#endif + { + sp_384_mul_6(s, s, p384_norm_order); + } + err = sp_384_mod_6(s, s, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(s); +#ifdef WOLFSSL_SP_SMALL +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mont_inv_order_avx2_6(s, s, tmp); + sp_384_mont_mul_order_avx2_6(u1, u1, s); + sp_384_mont_mul_order_avx2_6(u2, u2, s); + } + else +#endif + { + sp_384_mont_inv_order_6(s, s, tmp); + sp_384_mont_mul_order_6(u1, u1, s); + sp_384_mont_mul_order_6(u2, u2, s); + } + +#else +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mont_mul_order_avx2_6(u1, u1, s); + sp_384_mont_mul_order_avx2_6(u2, u2, s); + } + else +#endif + { + sp_384_mont_mul_order_6(u1, u1, s); + sp_384_mont_mul_order_6(u2, u2, s); + } + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(p1, u1, 0, 0, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(p1, u1, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_6(p1->z)) { + p1->infinity = 1; + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_avx2_6(p2, p2, u2, 0, 0, heap); + else +#endif + err = sp_384_ecc_mulmod_6(p2, p2, u2, 0, 0, heap); + } + if ((err == MP_OKAY) && sp_384_iszero_6(p2->z)) { + p2->infinity = 1; + } + + if (err == MP_OKAY) { + sp_384_add_points_6(p1, p2, tmp); + } + + return err; +} + #ifdef HAVE_ECC_VERIFY /* Verify the signature values with the hash and public key. * e = Truncate(hash, 384) @@ -30604,8 +48653,7 @@ static int sp_384_mod_inv_6(sp_digit* r, const sp_digit* a, const sp_digit* m) * rm First part of result as an mp_int. * sm Sirst part of result as an mp_int. * heap Heap to use for allocation. - * returns RNG failures, MEMORY_E when memory allocation fails and - * MP_OKAY on success. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { @@ -30624,8 +48672,9 @@ typedef struct sp_ecc_verify_384_ctx { sp_point_384 p2; } sp_ecc_verify_384_ctx; -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, + word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, + const mp_int* rm, const mp_int* sm, int* res, void* heap) { int err = FP_WOULDBLOCK; sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; @@ -30640,7 +48689,7 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } sp_384_from_bin(ctx->u1, 6, hash, (int)hashLen); - sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->u2, 6, rm); sp_384_from_mp(ctx->s, 6, sm); sp_384_from_mp(ctx->p2.x, 6, pX); sp_384_from_mp(ctx->p2.y, 6, pY); @@ -30698,57 +48747,33 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, if (err == MP_OKAY) ctx->state = 9; break; - case 9: /* DBLPREP */ - if (sp_384_iszero_6(ctx->p1.z)) { - if (sp_384_iszero_6(ctx->p1.x) && sp_384_iszero_6(ctx->p1.y)) { - XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); - ctx->state = 10; - break; - } - else { - /* Y ordinate is not used from here - don't set. */ - int i; - for (i=0; i<6; i++) { - ctx->p1.x[i] = 0; - } - XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - ctx->state = 11; - break; - case 10: /* DBL */ - err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, - &ctx->p2, ctx->tmp); - if (err == MP_OKAY) { - ctx->state = 11; - } - break; - case 11: /* MONT */ + case 9: /* MONT */ /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->u2, 6, rm); err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); if (err == MP_OKAY) - ctx->state = 12; + ctx->state = 10; break; - case 12: /* SQR */ + case 10: /* SQR */ /* u1 = r.z'.z' mod prime */ sp_384_mont_sqr_6(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 13; + ctx->state = 11; break; - case 13: /* MUL */ + case 11: /* MUL */ sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); - ctx->state = 14; + ctx->state = 12; break; - case 14: /* RES */ + case 12: /* RES */ + { + int64_t c = 0; err = MP_OKAY; /* math okay, now check result */ *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); if (*res == 0) { sp_digit carry; - int64_t c; /* Reload r and add order. */ - sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->u2, 6, rm); carry = sp_384_add_6(ctx->u2, ctx->u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -30756,22 +48781,23 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_6(ctx->u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); } } break; } + } /* switch */ - if (err == MP_OKAY && ctx->state != 14) { + if (err == MP_OKAY && ctx->state != 12) { err = FP_WOULDBLOCK; } @@ -30779,183 +48805,63 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, } #endif /* WOLFSSL_SP_NONBLOCK */ -int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, - mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; -#else - sp_digit u1d[2*6]; - sp_digit u2d[2*6]; - sp_digit sd[2*6]; - sp_digit tmpd[2*6 * 5]; - sp_point_384 p1d; - sp_point_384 p2d; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[16 * 6]; + sp_point_384 p1[2]; +#endif sp_digit* u2 = NULL; sp_digit* s = NULL; sp_digit* tmp = NULL; - sp_point_384* p1; sp_point_384* p2 = NULL; sp_digit carry; - int64_t c; - int err; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif + int64_t c = 0; + int err = MP_OKAY; - err = sp_384_point_new_6(heap, p1d, p1); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, p2d, p2); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 6, heap, - DYNAMIC_TYPE_ECC); - if (d == NULL) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 6, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) err = MEMORY_E; - } } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - u1 = d + 0 * 6; - u2 = d + 2 * 6; - s = d + 4 * 6; - tmp = d + 6 * 6; -#else - u1 = u1d; - u2 = u2d; - s = sd; - tmp = tmpd; -#endif + u2 = u1 + 2 * 6; + s = u1 + 4 * 6; + tmp = u1 + 6 * 6; + p2 = p1 + 1; if (hashLen > 48U) { hashLen = 48U; } sp_384_from_bin(u1, 6, hash, (int)hashLen); - sp_384_from_mp(u2, 6, r); + sp_384_from_mp(u2, 6, rm); sp_384_from_mp(s, 6, sm); sp_384_from_mp(p2->x, 6, pX); sp_384_from_mp(p2->y, 6, pY); sp_384_from_mp(p2->z, 6, pZ); -#ifndef WOLFSSL_SP_SMALL - { - sp_384_mod_inv_6(s, s, p384_order); - } -#endif /* !WOLFSSL_SP_SMALL */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_384_mul_avx2_6(s, s, p384_norm_order); - } - else -#endif - { - sp_384_mul_6(s, s, p384_norm_order); - } - err = sp_384_mod_6(s, s, p384_order); + err = sp_384_calc_vfy_point_6(p1, p2, s, u1, u2, tmp, heap); } if (err == MP_OKAY) { - sp_384_norm_6(s); -#ifdef WOLFSSL_SP_SMALL -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_384_mont_inv_order_avx2_6(s, s, tmp); - sp_384_mont_mul_order_avx2_6(u1, u1, s); - sp_384_mont_mul_order_avx2_6(u2, u2, s); - } - else -#endif - { - sp_384_mont_inv_order_6(s, s, tmp); - sp_384_mont_mul_order_6(u1, u1, s); - sp_384_mont_mul_order_6(u2, u2, s); - } - -#else -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_384_mont_mul_order_avx2_6(u1, u1, s); - sp_384_mont_mul_order_avx2_6(u2, u2, s); - } - else -#endif - { - sp_384_mont_mul_order_6(u1, u1, s); - sp_384_mont_mul_order_6(u2, u2, s); - } - -#endif /* WOLFSSL_SP_SMALL */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_384_ecc_mulmod_base_avx2_6(p1, u1, 0, 0, heap); - else -#endif - err = sp_384_ecc_mulmod_base_6(p1, u1, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_6(p1->z)) { - p1->infinity = 1; - } - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_384_ecc_mulmod_avx2_6(p2, p2, u2, 0, 0, heap); - else -#endif - err = sp_384_ecc_mulmod_6(p2, p2, u2, 0, 0, heap); - } - if ((err == MP_OKAY) && sp_384_iszero_6(p2->z)) { - p2->infinity = 1; - } - - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_384_proj_point_add_avx2_6(p1, p1, p2, tmp); - if (sp_384_iszero_6(p1->z)) { - if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { - sp_384_proj_point_dbl_avx2_6(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - else -#endif - { - sp_384_proj_point_add_6(p1, p1, p2, tmp); - if (sp_384_iszero_6(p1->z)) { - if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { - sp_384_proj_point_dbl_6(p1, p2, tmp); - } - else { - /* Y ordinate is not used from here - don't set. */ - p1->x[0] = 0; - p1->x[1] = 0; - p1->x[2] = 0; - p1->x[3] = 0; - p1->x[4] = 0; - p1->x[5] = 0; - XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); - } - } - } - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 6, r); + sp_384_from_mp(u2, 6, rm); err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); } @@ -30966,7 +48872,7 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); if (*res == 0) { /* Reload r and add order. */ - sp_384_from_mp(u2, 6, r); + sp_384_from_mp(u2, 6, rm); carry = sp_384_add_6(u2, u2, p384_order); /* Carry means result is greater than mod and is not valid. */ if (carry == 0) { @@ -30974,26 +48880,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, /* Compare with mod and if greater or equal then not valid. */ c = sp_384_cmp_6(u2, p384_mod); - if (c < 0) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, - p384_mp_mod); - *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); - } - } + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (sp_384_cmp_6(p1->x, u1) == 0); } } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) - XFREE(d, heap, DYNAMIC_TYPE_ECC); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p1, 0, heap); - sp_384_point_free_6(p2, 0, heap); return err; } @@ -31007,34 +48913,26 @@ int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) +static int sp_384_ecc_is_point_6(const sp_point_384* point, + void* heap) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d = NULL; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2*6]; - sp_digit t2d[2*6]; + sp_digit t1[6 * 4]; #endif - sp_digit* t1; - sp_digit* t2; + sp_digit* t2 = NULL; int err = MP_OKAY; -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 4, heap, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif (void)heap; if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 6; - t2 = d + 2 * 6; -#else - t1 = t1d; - t2 = t2d; -#endif + t2 = t1 + 2 * 6; sp_384_sqr_6(t1, point->y); (void)sp_384_mod_6(t1, t1, p384_mod); @@ -31054,10 +48952,9 @@ static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, heap, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); #endif return err; @@ -31070,16 +48967,23 @@ static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is * not on the curve and MP_OKAY otherwise. */ -int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384 pubd; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* pub = NULL; +#else + sp_point_384 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; #endif - sp_point_384* pub; - byte one[1] = { 1 }; - int err; - err = sp_384_point_new_6(NULL, pubd, pub); if (err == MP_OKAY) { sp_384_from_mp(pub->x, 6, pX); sp_384_from_mp(pub->y, 6, pY); @@ -31088,7 +48992,10 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) err = sp_384_ecc_is_point_6(pub, NULL); } - sp_384_point_free_6(pub, 0, NULL); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -31104,50 +49011,51 @@ int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and * MP_OKAY otherwise. */ -int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit privd[6]; - sp_point_384 pubd; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* priv = NULL; - sp_point_384* pub; + sp_point_384* pub = NULL; +#else + sp_digit priv[6]; + sp_point_384 pub[2]; +#endif sp_point_384* p = NULL; - byte one[1] = { 1 }; - int err; + const byte one[1] = { 1 }; + int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_384_point_new_6(heap, pubd, pub); - if (err == MP_OKAY) { - err = sp_384_point_new_6(heap, pd, p); - } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY && privm) { - priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, - DYNAMIC_TYPE_ECC); - if (priv == NULL) { - err = MEMORY_E; - } - } -#endif /* Quick check the lengs of public key ordinates and private key are in * range. Proper check later. */ - if ((err == MP_OKAY) && ((mp_count_bits(pX) > 384) || + if (((mp_count_bits(pX) > 384) || (mp_count_bits(pY) > 384) || ((privm != NULL) && (mp_count_bits(privm) > 384)))) { err = ECC_OUT_OF_RANGE_E; } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - priv = privd; + pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } #endif + if (err == MP_OKAY) { + p = pub + 1; + sp_384_from_mp(pub->x, 6, pX); sp_384_from_mp(pub->y, 6, pY); sp_384_from_bin(pub->z, 6, one, (int)sizeof(one)); @@ -31161,12 +49069,11 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) } } - if (err == MP_OKAY) { - /* Check range of X and Y */ - if (sp_384_cmp_6(pub->x, p384_mod) >= 0 || - sp_384_cmp_6(pub->y, p384_mod) >= 0) { - err = ECC_OUT_OF_RANGE_E; - } + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_384_cmp_6(pub->x, p384_mod) >= 0) || + (sp_384_cmp_6(pub->y, p384_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; } if (err == MP_OKAY) { @@ -31183,12 +49090,10 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) #endif err = sp_384_ecc_mulmod_6(p, pub, p384_order, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is infinity */ - if ((sp_384_iszero_6(p->x) == 0) || - (sp_384_iszero_6(p->y) == 0)) { - err = ECC_INF_E; - } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_384_iszero_6(p->x) == 0) || + (sp_384_iszero_6(p->y) == 0))) { + err = ECC_INF_E; } if (privm) { @@ -31201,22 +49106,20 @@ int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) #endif err = sp_384_ecc_mulmod_base_6(p, priv, 1, 1, heap); } - if (err == MP_OKAY) { - /* Check result is public key */ - if (sp_384_cmp_6(p->x, pub->x) != 0 || - sp_384_cmp_6(p->y, pub->y) != 0) { - err = ECC_PRIV_KEY_E; - } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_384_cmp_6(p->x, pub->x) != 0) || + (sp_384_cmp_6(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (priv != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) XFREE(priv, heap, DYNAMIC_TYPE_ECC); - } #endif - sp_384_point_free_6(p, 0, heap); - sp_384_point_free_6(pub, 0, heap); return err; } @@ -31240,36 +49143,38 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 6 * 5]; - sp_point_384 pd; - sp_point_384 qd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 6 * 5]; + sp_point_384 p[2]; +#endif sp_point_384* q = NULL; int err; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_384_point_new_6(NULL, pd, p); +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { - err = sp_384_point_new_6(NULL, qd, q); + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 5, NULL, - DYNAMIC_TYPE_ECC); + DYNAMIC_TYPE_ECC); if (tmp == NULL) { err = MEMORY_E; } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { + q = p + 1; + sp_384_from_mp(p->x, 6, pX); sp_384_from_mp(p->y, 6, pY); sp_384_from_mp(p->z, 6, pZ); @@ -31295,13 +49200,12 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(q, 0, NULL); - sp_384_point_free_6(p, 0, NULL); return err; } @@ -31320,28 +49224,31 @@ int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 6 * 2]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 6 * 2]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif - err = sp_384_point_new_6(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 2, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { @@ -31367,12 +49274,12 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, err = sp_384_to_mp(p->z, rZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, NULL); return err; } @@ -31387,32 +49294,44 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, */ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) { -#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) - sp_digit tmpd[2 * 6 * 6]; - sp_point_384 pd; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* tmp = NULL; - sp_point_384* p; - int err; + sp_point_384* p = NULL; +#else + sp_digit tmp[2 * 6 * 6]; + sp_point_384 p[1]; +#endif + int err = MP_OKAY; - err = sp_384_point_new_6(NULL, pd, p); -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) + err = MEMORY_E; + } if (err == MP_OKAY) { tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, NULL, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) { + DYNAMIC_TYPE_ECC); + if (tmp == NULL) err = MEMORY_E; - } } -#else - tmp = tmpd; #endif if (err == MP_OKAY) { sp_384_from_mp(p->x, 6, pX); sp_384_from_mp(p->y, 6, pY); sp_384_from_mp(p->z, 6, pZ); - sp_384_map_6(p, p, tmp); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_map_avx2_6(point, point, tmp); + else +#endif + sp_384_map_6(p, p, tmp); } if (err == MP_OKAY) { @@ -31425,12 +49344,12 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) err = sp_384_to_mp(p->z, pZ); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); - } + if (p != NULL) + XFREE(p, NULL, DYNAMIC_TYPE_ECC); #endif - sp_384_point_free_6(p, 0, NULL); return err; } @@ -31443,46 +49362,31 @@ int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) */ static int sp_384_mont_sqrt_6(sp_digit* y) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; #else - sp_digit t1d[2 * 6]; - sp_digit t2d[2 * 6]; - sp_digit t3d[2 * 6]; - sp_digit t4d[2 * 6]; - sp_digit t5d[2 * 6]; + sp_digit t1[5 * 2 * 6]; #endif - sp_digit* t1; - sp_digit* t2; - sp_digit* t3; - sp_digit* t4; - sp_digit* t5; + sp_digit* t2 = NULL; + sp_digit* t3 = NULL; + sp_digit* t4 = NULL; + sp_digit* t5 = NULL; int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - t1 = d + 0 * 6; - t2 = d + 2 * 6; - t3 = d + 4 * 6; - t4 = d + 6 * 6; - t5 = d + 8 * 6; -#else - t1 = t1d; - t2 = t2d; - t3 = t3d; - t4 = t4d; - t5 = t5d; -#endif + t2 = t1 + 2 * 6; + t3 = t1 + 4 * 6; + t4 = t1 + 6 * 6; + t5 = t1 + 8 * 6; #ifdef HAVE_INTEL_AVX2 if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { @@ -31601,10 +49505,9 @@ static int sp_384_mont_sqrt_6(sp_digit* y) } } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); #endif return err; @@ -31620,34 +49523,25 @@ static int sp_384_mont_sqrt_6(sp_digit* y) */ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* d; -#else - sp_digit xd[2 * 6]; - sp_digit yd[2 * 6]; -#endif +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) sp_digit* x = NULL; +#else + sp_digit x[4 * 6]; +#endif sp_digit* y = NULL; int err = MP_OKAY; #ifdef HAVE_INTEL_AVX2 word32 cpuid_flags = cpuid_get_flags(); #endif -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 6, NULL, DYNAMIC_TYPE_ECC); - if (d == NULL) { +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 6, NULL, DYNAMIC_TYPE_ECC); + if (x == NULL) err = MEMORY_E; - } #endif if (err == MP_OKAY) { -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - x = d + 0 * 6; - y = d + 2 * 6; -#else - x = xd; - y = yd; -#endif + y = x + 2 * 6; sp_384_from_mp(x, 6, xm); err = sp_384_mod_mul_norm_6(x, x, p384_mod); @@ -31687,16 +49581,12287 @@ int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) err = sp_384_to_mp(y, ym); } -#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) - if (d != NULL) { - XFREE(d, NULL, DYNAMIC_TYPE_ECC); - } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (x != NULL) + XFREE(x, NULL, DYNAMIC_TYPE_ECC); #endif return err; } #endif #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 + +/* Point structure to use. */ +typedef struct sp_point_1024 { + /* X ordinate of point. */ + sp_digit x[2 * 16]; + /* Y ordinate of point. */ + sp_digit y[2 * 16]; + /* Z ordinate of point. */ + sp_digit z[2 * 16]; + /* Indicates point is at infinity. */ + int infinity; +} sp_point_1024; + +extern void sp_1024_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_1024_sqr_16(sp_digit* r, const sp_digit* a); +extern void sp_1024_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_1024_sqr_avx2_16(sp_digit* r, const sp_digit* a); +/* The modulus (prime) of the curve P1024. */ +static const sp_digit p1024_mod[16] = { + 0x666d807afea85febL,0x80c5df10ac7ace87L,0xfce3e82389857db0L, + 0x9f94d6af56971f1fL,0xa7cf3c521c3c09aaL,0xb6aff4a831852a82L, + 0x512ac5cd65681ce1L,0xe26c6487326b4cd4L,0x356d27f4a666a6d0L, + 0xe791b39ff7c88a19L,0x228730d531a59cb0L,0xf40aab27e2fc0f1bL, + 0xbe9ae358b3e01a2eL,0x416c0ce19cb48261L,0x65c61198dad0657aL, + 0x997abb1f0a563fdaL +}; +/* The Montogmery normalizer for modulus of the curve P1024. */ +static const sp_digit p1024_norm_mod[16] = { + 0x99927f850157a015L,0x7f3a20ef53853178L,0x031c17dc767a824fL, + 0x606b2950a968e0e0L,0x5830c3ade3c3f655L,0x49500b57ce7ad57dL, + 0xaed53a329a97e31eL,0x1d939b78cd94b32bL,0xca92d80b5999592fL, + 0x186e4c60083775e6L,0xdd78cf2ace5a634fL,0x0bf554d81d03f0e4L, + 0x41651ca74c1fe5d1L,0xbe93f31e634b7d9eL,0x9a39ee67252f9a85L, + 0x668544e0f5a9c025L +}; +/* The Montogmery multiplier for modulus of the curve P1024. */ +static sp_digit p1024_mp_mod = 0x290420077c8f2f3d; +#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY) +/* The order of the curve P1024. */ +static const sp_digit p1024_order[16] = { + 0xd99b601ebfaa17fbL,0x203177c42b1eb3a1L,0xff38fa08e2615f6cL, + 0xa7e535abd5a5c7c7L,0xa9f3cf14870f026aL,0x6dabfd2a0c614aa0L, + 0x144ab173595a0738L,0x389b1921cc9ad335L,0x4d5b49fd2999a9b4L, + 0x39e46ce7fdf22286L,0xc8a1cc354c69672cL,0xbd02aac9f8bf03c6L, + 0x6fa6b8d62cf8068bL,0x905b0338672d2098L,0x9971846636b4195eL, + 0x265eaec7c2958ff6L +}; +#endif +/* The base point of curve P1024. */ +static const sp_point_1024 p1024_base = { + /* X ordinate */ + { + 0x880dc8abeae63895L,0x80ec46c4967e0979L,0xee9163a5b63f73ecL, + 0xd5cfb4cc80728d87L,0xa7c1514dba66910dL,0xa702c3397a60de74L, + 0x337c86548b72f2e1L,0x9760af765dd5bccbL,0x718bd9e7406ce890L, + 0x43d5f22cdb9dfa55L,0xab10db9030b09e10L,0xb5edb6c0f6ce2308L, + 0x98b2f204b6ff7cbfL,0x2b1a2fd60aec69c6L,0x0a7990053ed9b52aL, + 0x53fc09ee332c29adL, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x75573fd71bef16d7L,0xadb9b5706a67dcdeL,0x80bdad5ad5bb4636L, + 0x13515ad7e9cb99a9L,0x492d979fc5a4d5f2L,0xac6f1e80164aa989L, + 0xcad696b5b7652fe0L,0x70dae117ad547c6cL,0x416cff0ca9e032b9L, + 0x6b598ccf9a140b2eL,0xe7f7f5e5f0de55f6L,0xf5ea69f4654ec2b9L, + 0x3d778d821e141178L,0xd3e8201602990696L,0xf9f1f0533634a135L, + 0x0a8249063f6009f1L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000000001L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +extern sp_digit sp_1024_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_1024_sub_in_place_16(sp_digit* a, const sp_digit* b); +extern sp_digit sp_1024_cond_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern sp_digit sp_1024_cond_sub_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_1024_mul_d_16(sp_digit* r, const sp_digit* a, sp_digit b); +extern void sp_1024_mul_d_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit b); +#ifdef _WIN64 +#if _MSC_VER < 1920 +extern sp_digit div_1024_word_asm_16(sp_digit d1, sp_digit d0, sp_digit div); +#endif /* _MSC_VER < 1920 */ +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_1024_word_16(sp_digit d1, sp_digit d0, + sp_digit div) +{ +#if _MSC_VER >= 1920 + return _udiv128(d1, d0, div, NULL); +#else + return div_1024_word_asm_16(d1, d0, div); +#endif +} +#else +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_1024_word_16(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + return r; +} +#endif /* _WIN64 */ +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_1024_mask_16(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +extern int64_t sp_1024_cmp_16(const sp_digit* a, const sp_digit* b); +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Number to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_div_16(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[32]; + sp_digit t2[17]; + sp_digit div; + sp_digit r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[15]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 16); + r1 = sp_1024_cmp_16(&t1[16], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_1024_cond_sub_avx2_16(&t1[16], &t1[16], d, (sp_digit)0 - r1); + else +#endif + sp_1024_cond_sub_16(&t1[16], &t1[16], d, (sp_digit)0 - r1); + for (i=15; i>=0; i--) { + sp_digit hi = t1[16 + i] - (t1[16 + i] == div); + r1 = div_1024_word_16(hi, t1[16 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_1024_mul_d_avx2_16(t2, d, r1); + else +#endif + sp_1024_mul_d_16(t2, d, r1); + t1[16 + i] += sp_1024_sub_in_place_16(&t1[i], t2); + t1[16 + i] -= t2[16]; + sp_1024_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_1024_add_16(&t1[i], &t1[i], t2); + sp_1024_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_1024_add_16(&t1[i], &t1[i], t2); + } + + r1 = sp_1024_cmp_16(t1, d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_1024_cond_sub_avx2_16(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_1024_cond_sub_16(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_1024_mod_16(sp_digit* r, const sp_digit* a, + const sp_digit* m) +{ + return sp_1024_div_16(a, m, NULL, r); +} + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_1024_mul_16(r, a, p1024_norm_mod); + return sp_1024_mod_16(r, r, m); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_1024_mod_mul_norm_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_1024_mul_avx2_16(r, a, p1024_norm_mod); + return sp_1024_mod_16(r, r, m); +} + +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Create a new point. + * + * heap [in] Buffer to allocate dynamic memory from. + * sp [in] Data for point - only if not allocating. + * p [out] New point. + * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise. + */ +static int sp_1024_point_new_ex_16(void* heap, sp_point_1024* sp, + sp_point_1024** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_1024_point_new_16(heap, sp, p) sp_1024_point_new_ex_16((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_1024_point_new_16(heap, sp, p) sp_1024_point_new_ex_16((heap), &(sp), &(p)) +#endif +#endif /* WOLFCRYPT_HAVE_SAKKE */ +#ifdef WOLFCRYPT_HAVE_SAKKE +/* Free the point. + * + * p [in,out] Point to free. + * clear [in] Indicates whether to zeroize point. + * heap [in] Buffer from which dynamic memory was allocate from. + */ +static void sp_1024_point_free_16(sp_point_1024* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if ((p != NULL) && (clear != 0)) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i; + int j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i; + int j = 0; + int s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_1024. + * + * p Point of type sp_point_1024 (result). + * pm Point of type ecc_point. + */ +static void sp_1024_point_from_ecc_point_16(sp_point_1024* p, + const ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_1024_from_mp(p->x, 16, pm->x); + sp_1024_from_mp(p->y, 16, pm->y); + sp_1024_from_mp(p->z, 16, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_1024_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 16); + r->used = 16; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 16; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i; + int j = 0; + int s = 0; + + r->dp[0] = 0; + for (i = 0; i < 16; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else { + s += 64; + } + } + r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_1024 to type ecc_point. + * + * p Point of type sp_point_1024. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_1024_point_to_ecc_point_16(const sp_point_1024* p, ecc_point* pm) +{ + int err; + + err = sp_1024_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(p->z, pm->z); + } + + return err; +} + +extern void sp_1024_cond_copy_16(sp_digit* r, const sp_digit* a, sp_digit m); +extern void sp_1024_mont_reduce_16(sp_digit* a, const sp_digit* m, sp_digit mp); +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_16(r, a, b); + sp_1024_mont_reduce_16(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_16(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_16(r, a); + sp_1024_mont_reduce_16(r, m, mp); +} + +/* Mod-2 for the P1024 curve. */ +static const uint8_t p1024_mod_minus_2[] = { + 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f, + 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14, + 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07, + 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b, + 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07, + 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13, + 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19, + 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04, + 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09, + 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06, + 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15, + 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14, + 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c, + 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19, + 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f, + 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b, + 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c, + 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f, + 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01 +}; + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_16(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 16]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 16); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_16(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_16(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 16); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_16(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_16(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_16(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_1024_norm_16(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_16(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + int64_t n; + + sp_1024_mont_inv_16(t1, p->z, t + 2*16); + + sp_1024_mont_sqr_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_16(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 16, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_16(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_16(r->x, p1024_mod); + sp_1024_cond_sub_16(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_16(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 16, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_16(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_16(r->y, p1024_mod); + sp_1024_cond_sub_16(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +extern void sp_1024_mont_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); +extern void sp_1024_mont_dbl_16(sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_1024_mont_tpl_16(sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_1024_mont_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); +extern void sp_1024_div2_16(sp_digit* r, const sp_digit* a, const sp_digit* m); +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_16_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_16_ctx; + +static int sp_1024_proj_point_dbl_16_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_16_ctx* ctx = (sp_1024_proj_point_dbl_16_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_16_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*16; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_16(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_16(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_16(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_16(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_16(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_16(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_16(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_16(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_16(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_16(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_16(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_16(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_16(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_16(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_16(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_16(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_16(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_16(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_16(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_16(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_16(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_16(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_16(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_16(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_16(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_16(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_16(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_16(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_16(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_16(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_16(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_16(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_16(y, y, t2, p1024_mod); +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_16(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*16; + sp_digit* b = t + 4*16; + sp_digit* t1 = t + 6*16; + sp_digit* t2 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_16(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_16(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_16(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(t2, b, p1024_mod); + sp_1024_mont_sub_16(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_16(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_16(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_16(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_16(y, b, x, p1024_mod); + sp_1024_mont_mul_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(y, y, p1024_mod); + sp_1024_mont_sub_16(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_16(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(t2, b, p1024_mod); + sp_1024_mont_sub_16(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_16(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_16(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_16(y, b, x, p1024_mod); + sp_1024_mont_mul_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(y, y, p1024_mod); + sp_1024_mont_sub_16(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_16(y, y, p1024_mod); +} + +extern sp_digit sp_1024_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_1024_cmp_equal_16(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) | (a[15] ^ b[15])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_16_ctx { + int state; + sp_1024_proj_point_dbl_16_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_16_ctx; + +static int sp_1024_proj_point_add_16_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_16_ctx* ctx = (sp_1024_proj_point_add_16_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_16_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*16; + ctx->t3 = t + 4*16; + ctx->t4 = t + 6*16; + ctx->t5 = t + 8*16; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_16(ctx->t1, p1024_mod, q->y); + sp_1024_norm_16(ctx->t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_16_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_16(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_16(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_16(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_16(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_16(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_16(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_16(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_16(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_16(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_16(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_16(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_16(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_16(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_16(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_16(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_16(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_16(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_16(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_16(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_16(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_16(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_16(t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_16(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_16(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_16(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_16(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_16(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_16(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_16(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(x, x, t5, p1024_mod); + sp_1024_mont_dbl_16(t1, y, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_16(y, y, x, p1024_mod); + sp_1024_mont_mul_16(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(y, y, t5, p1024_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_store_16(sp_point_1024* r, + const sp_point_1024* p, int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*16; + sp_digit* b = t + 4*16; + sp_digit* t1 = t + 6*16; + sp_digit* t2 = t + 8*16; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<16; i++) { + y[i] = p->y[i]; + } + for (i=0; i<16; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_1024_mont_dbl_16(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_16(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(w, w, p1024_mod, p1024_mp_mod); + j = m; + for (i=1; i<=n; i++) { + j *= 2; + + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_16(t2, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(b, t2, x, p1024_mod, p1024_mp_mod); + x = r[j].x; + /* X = A^2 - 2B */ + sp_1024_mont_sqr_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(t1, b, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_16(r[j].z, z, y, p1024_mod, p1024_mp_mod); + z = r[j].z; + /* t2 = Y^4 */ + sp_1024_mont_sqr_16(t2, t2, p1024_mod, p1024_mp_mod); + if (i != n) { + /* W = W*Y^4 */ + sp_1024_mont_mul_16(w, w, t2, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_16(y, b, x, p1024_mod); + sp_1024_mont_mul_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_16(y, y, p1024_mod); + sp_1024_mont_sub_16(y, y, t2, p1024_mod); + + /* Y = Y/2 */ + sp_1024_div2_16(r[j].y, y, p1024_mod); + r[j].infinity = 0; + } +} + +/* Add two Montgomery form projective points. + * + * ra Result of addition. + * rs Result of subtraction. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_sub_16(sp_point_1024* ra, + sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* t6 = t + 10*16; + sp_digit* x = ra->x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_16(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_16(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_16(t2, t2, t1, p1024_mod); + /* RS = S2 + S1 */ + sp_1024_mont_add_16(t6, t4, t3, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_16(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_1024_mont_mul_16(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(z, z, t2, p1024_mod, p1024_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_16(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(xs, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(x, x, t5, p1024_mod); + sp_1024_mont_sub_16(xs, xs, t5, p1024_mod); + sp_1024_mont_dbl_16(t1, y, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + sp_1024_mont_sub_16(xs, xs, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_1024_mont_sub_16(ys, y, xs, p1024_mod); + sp_1024_mont_sub_16(y, y, x, p1024_mod); + sp_1024_mont_mul_16(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(t6, p1024_mod, t6, p1024_mod); + sp_1024_mont_mul_16(ys, ys, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(y, y, t5, p1024_mod); + sp_1024_mont_sub_16(ys, ys, t5, p1024_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_1024 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_1024; + +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_16_7[130] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static const uint8_t recode_neg_16_7[130] = { + 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, 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, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to perform. + */ +static void sp_1024_ecc_recode_7_16(const sp_digit* k, ecc_recode_1024* v) +{ + int i; + int j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<147; i++) { + y = (int8_t)n; + if (o + 7 < 64) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 64) { + n >>= 7; + if (++j < 16) + n = k[j]; + o = 0; + } + else if (++j < 16) { + n = k[j]; + y |= (uint8_t)((n << (64 - o)) & 0x7f); + o -= 57; + n >>= o; + } + + y += (uint8_t)carry; + v[i].i = recode_index_16_7[y]; + v[i].neg = recode_neg_16_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Window technique of 7 bits. (Add-Sub variation.) + * Calculate 0..64 times the point. Use function that adds and + * subtracts the same two points. + * Recode to add or subtract one of the computed points. + * Double to push up. + * NOT a sliding window. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_win_add_sub_16(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[65+2]; + sp_digit tmp[2 * 16 * 6]; +#endif + sp_point_1024* rt = NULL; + sp_point_1024* p = NULL; + sp_digit* negy; + int i; + ecc_recode_1024 v[147]; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * + (65+2), heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 16 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 65; + p = t + 65+1; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_16(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t[1].y, g->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t[1].z, g->z, p1024_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[64] */ + sp_1024_proj_point_dbl_n_store_16(t, &t[ 1], 6, 1, tmp); + sp_1024_proj_point_add_16(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[ 6], &t[ 3], tmp); + sp_1024_proj_point_add_sub_16(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[10], &t[ 5], tmp); + sp_1024_proj_point_add_sub_16(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[12], &t[ 6], tmp); + sp_1024_proj_point_dbl_16(&t[14], &t[ 7], tmp); + sp_1024_proj_point_add_sub_16(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[18], &t[ 9], tmp); + sp_1024_proj_point_add_sub_16(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[20], &t[10], tmp); + sp_1024_proj_point_dbl_16(&t[22], &t[11], tmp); + sp_1024_proj_point_add_sub_16(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[24], &t[12], tmp); + sp_1024_proj_point_dbl_16(&t[26], &t[13], tmp); + sp_1024_proj_point_add_sub_16(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[28], &t[14], tmp); + sp_1024_proj_point_dbl_16(&t[30], &t[15], tmp); + sp_1024_proj_point_add_sub_16(&t[31], &t[29], &t[30], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[34], &t[17], tmp); + sp_1024_proj_point_add_sub_16(&t[35], &t[33], &t[34], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[36], &t[18], tmp); + sp_1024_proj_point_dbl_16(&t[38], &t[19], tmp); + sp_1024_proj_point_add_sub_16(&t[39], &t[37], &t[38], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[40], &t[20], tmp); + sp_1024_proj_point_dbl_16(&t[42], &t[21], tmp); + sp_1024_proj_point_add_sub_16(&t[43], &t[41], &t[42], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[44], &t[22], tmp); + sp_1024_proj_point_dbl_16(&t[46], &t[23], tmp); + sp_1024_proj_point_add_sub_16(&t[47], &t[45], &t[46], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[48], &t[24], tmp); + sp_1024_proj_point_dbl_16(&t[50], &t[25], tmp); + sp_1024_proj_point_add_sub_16(&t[51], &t[49], &t[50], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[52], &t[26], tmp); + sp_1024_proj_point_dbl_16(&t[54], &t[27], tmp); + sp_1024_proj_point_add_sub_16(&t[55], &t[53], &t[54], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[56], &t[28], tmp); + sp_1024_proj_point_dbl_16(&t[58], &t[29], tmp); + sp_1024_proj_point_add_sub_16(&t[59], &t[57], &t[58], &t[ 1], tmp); + sp_1024_proj_point_dbl_16(&t[60], &t[30], tmp); + sp_1024_proj_point_dbl_16(&t[62], &t[31], tmp); + sp_1024_proj_point_add_sub_16(&t[63], &t[61], &t[62], &t[ 1], tmp); + + negy = t[0].y; + + sp_1024_ecc_recode_7_16(k, v); + + i = 146; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024)); + for (--i; i>=0; i--) { + sp_1024_proj_point_dbl_n_16(rt, 7, tmp); + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024)); + sp_1024_mont_sub_16(negy, p1024_mod, p->y, p1024_mod); + sp_1024_norm_16(negy); + sp_1024_cond_copy_16(p->y, negy, (sp_digit)0 - v[i].neg); + sp_1024_proj_point_add_16(rt, rt, p, tmp); + } + + if (map != 0) { + sp_1024_map_16(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef HAVE_INTEL_AVX2 +#ifdef HAVE_INTEL_AVX2 +extern void sp_1024_mont_reduce_avx2_16(sp_digit* a, const sp_digit* m, sp_digit mp); +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit* m, sp_digit mp) +{ + sp_1024_mul_avx2_16(r, a, b); + sp_1024_mont_reduce_avx2_16(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_1024_mont_sqr_avx2_16(sp_digit* r, const sp_digit* a, + const sp_digit* m, sp_digit mp) +{ + sp_1024_sqr_avx2_16(r, a); + sp_1024_mont_reduce_avx2_16(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P1024 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_1024_mont_inv_avx2_16(sp_digit* r, const sp_digit* a, + sp_digit* td) +{ + sp_digit* t = td; + int i; + int j; + sp_digit table[32][2 * 16]; + + XMEMCPY(table[0], a, sizeof(sp_digit) * 16); + for (i = 1; i < 6; i++) { + sp_1024_mont_sqr_avx2_16(table[0], table[0], p1024_mod, p1024_mp_mod); + } + for (i = 1; i < 32; i++) { + sp_1024_mont_mul_avx2_16(table[i], table[i-1], a, p1024_mod, p1024_mp_mod); + } + + XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 16); + for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) { + for (j = 0; j < p1024_mod_minus_2[i]; j++) { + sp_1024_mont_sqr_avx2_16(t, t, p1024_mod, p1024_mp_mod); + } + sp_1024_mont_mul_avx2_16(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod, + p1024_mp_mod); + } + sp_1024_mont_sqr_avx2_16(t, t, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(r, t, a, p1024_mod, p1024_mp_mod); +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_1024_map_avx2_16(sp_point_1024* r, const sp_point_1024* p, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + int64_t n; + + sp_1024_mont_inv_avx2_16(t1, p->z, t + 2*16); + + sp_1024_mont_sqr_avx2_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + + /* x /= z^2 */ + sp_1024_mont_mul_avx2_16(r->x, p->x, t2, p1024_mod, p1024_mp_mod); + XMEMSET(r->x + 16, 0, sizeof(r->x) / 2U); + sp_1024_mont_reduce_avx2_16(r->x, p1024_mod, p1024_mp_mod); + /* Reduce x to less than modulus */ + n = sp_1024_cmp_16(r->x, p1024_mod); + sp_1024_cond_sub_16(r->x, r->x, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(r->x); + + /* y /= z^3 */ + sp_1024_mont_mul_avx2_16(r->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMSET(r->y + 16, 0, sizeof(r->y) / 2U); + sp_1024_mont_reduce_avx2_16(r->y, p1024_mod, p1024_mp_mod); + /* Reduce y to less than modulus */ + n = sp_1024_cmp_16(r->y, p1024_mod); + sp_1024_cond_sub_avx2_16(r->y, r->y, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +extern void sp_1024_mont_add_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); +extern void sp_1024_mont_dbl_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_1024_mont_tpl_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_1024_mont_sub_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); +extern void sp_1024_div2_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* m); +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_dbl_avx2_16_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_dbl_avx2_16_ctx; + +static int sp_1024_proj_point_dbl_avx2_16_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_dbl_avx2_16_ctx* ctx = (sp_1024_proj_point_dbl_avx2_16_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_avx2_16_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*16; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_1024_mont_sqr_avx2_16(ctx->t1, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_1024_mont_mul_avx2_16(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_1024_mont_dbl_avx2_16(ctx->z, ctx->z, p1024_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_1024_mont_sub_avx2_16(ctx->t2, p->x, ctx->t1, p1024_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_1024_mont_add_avx2_16(ctx->t1, p->x, ctx->t1, p1024_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_1024_mont_mul_avx2_16(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_1024_mont_tpl_avx2_16(ctx->t1, ctx->t2, p1024_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_1024_mont_dbl_avx2_16(ctx->y, p->y, p1024_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_1024_mont_sqr_avx2_16(ctx->y, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_1024_mont_sqr_avx2_16(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_1024_div2_avx2_16(ctx->t2, ctx->t2, p1024_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_1024_mont_mul_avx2_16(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_1024_mont_sqr_avx2_16(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_1024_mont_sub_avx2_16(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_1024_mont_sub_avx2_16(ctx->x, ctx->x, ctx->y, p1024_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_1024_mont_sub_avx2_16(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_1024_mont_mul_avx2_16(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_1024_mont_sub_avx2_16(ctx->y, ctx->y, ctx->t2, p1024_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_dbl_avx2_16(sp_point_1024* r, const sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_1024_mont_sqr_avx2_16(t1, p->z, p1024_mod, p1024_mp_mod); + /* Z = Y * Z */ + sp_1024_mont_mul_avx2_16(z, p->y, p->z, p1024_mod, p1024_mp_mod); + /* Z = 2Z */ + sp_1024_mont_dbl_avx2_16(z, z, p1024_mod); + /* T2 = X - T1 */ + sp_1024_mont_sub_avx2_16(t2, p->x, t1, p1024_mod); + /* T1 = X + T1 */ + sp_1024_mont_add_avx2_16(t1, p->x, t1, p1024_mod); + /* T2 = T1 * T2 */ + sp_1024_mont_mul_avx2_16(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* T1 = 3T2 */ + sp_1024_mont_tpl_avx2_16(t1, t2, p1024_mod); + /* Y = 2Y */ + sp_1024_mont_dbl_avx2_16(y, p->y, p1024_mod); + /* Y = Y * Y */ + sp_1024_mont_sqr_avx2_16(y, y, p1024_mod, p1024_mp_mod); + /* T2 = Y * Y */ + sp_1024_mont_sqr_avx2_16(t2, y, p1024_mod, p1024_mp_mod); + /* T2 = T2/2 */ + sp_1024_div2_avx2_16(t2, t2, p1024_mod); + /* Y = Y * X */ + sp_1024_mont_mul_avx2_16(y, y, p->x, p1024_mod, p1024_mp_mod); + /* X = T1 * T1 */ + sp_1024_mont_sqr_avx2_16(x, t1, p1024_mod, p1024_mp_mod); + /* X = X - Y */ + sp_1024_mont_sub_avx2_16(x, x, y, p1024_mod); + /* X = X - Y */ + sp_1024_mont_sub_avx2_16(x, x, y, p1024_mod); + /* Y = Y - X */ + sp_1024_mont_sub_avx2_16(y, y, x, p1024_mod); + /* Y = Y * T1 */ + sp_1024_mont_mul_avx2_16(y, y, t1, p1024_mod, p1024_mp_mod); + /* Y = Y - T2 */ + sp_1024_mont_sub_avx2_16(y, y, t2, p1024_mod); +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_avx2_16(sp_point_1024* p, int n, + sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*16; + sp_digit* b = t + 4*16; + sp_digit* t1 = t + 6*16; + sp_digit* t2 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_1024_mont_dbl_avx2_16(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_avx2_16(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_avx2_16(w, w, p1024_mod, p1024_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_avx2_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_avx2_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_avx2_16(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_avx2_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_avx2_16(t2, b, p1024_mod); + sp_1024_mont_sub_avx2_16(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_avx2_16(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_avx2_16(t1, t1, p1024_mod, p1024_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_1024_mont_mul_avx2_16(w, w, t1, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_avx2_16(y, b, x, p1024_mod); + sp_1024_mont_mul_avx2_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_avx2_16(y, y, p1024_mod); + sp_1024_mont_sub_avx2_16(y, y, t1, p1024_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_avx2_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_avx2_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_avx2_16(t1, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(b, t1, x, p1024_mod, p1024_mp_mod); + /* X = A^2 - 2B */ + sp_1024_mont_sqr_avx2_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_avx2_16(t2, b, p1024_mod); + sp_1024_mont_sub_avx2_16(x, x, t2, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_avx2_16(z, z, y, p1024_mod, p1024_mp_mod); + /* t2 = Y^4 */ + sp_1024_mont_sqr_avx2_16(t1, t1, p1024_mod, p1024_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_avx2_16(y, b, x, p1024_mod); + sp_1024_mont_mul_avx2_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_avx2_16(y, y, p1024_mod); + sp_1024_mont_sub_avx2_16(y, y, t1, p1024_mod); +#endif + /* Y = Y/2 */ + sp_1024_div2_avx2_16(y, y, p1024_mod); +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_1024_proj_point_add_avx2_16_ctx { + int state; + sp_1024_proj_point_dbl_avx2_16_ctx dbl_ctx; + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_1024_proj_point_add_avx2_16_ctx; + +static int sp_1024_proj_point_add_avx2_16_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_1024_proj_point_add_avx2_16_ctx* ctx = (sp_1024_proj_point_add_avx2_16_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_avx2_16_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*16; + ctx->t3 = t + 4*16; + ctx->t4 = t + 6*16; + ctx->t5 = t + 8*16; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_1024_sub_avx2_16(ctx->t1, p1024_mod, q->y); + sp_1024_norm_avx2_16(ctx->t1); + if ((sp_1024_cmp_equal_avx2_16(p->x, q->x) & sp_1024_cmp_equal_avx2_16(p->z, q->z) & + (sp_1024_cmp_equal_avx2_16(p->y, q->y) | sp_1024_cmp_equal_avx2_16(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_1024_proj_point_dbl_avx2_16_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_1024)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_avx2_16(ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 5; + break; + case 5: + sp_1024_mont_mul_avx2_16(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 6; + break; + case 6: + sp_1024_mont_mul_avx2_16(ctx->t1, ctx->t1, ctx->x, p1024_mod, p1024_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_avx2_16(ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 8; + break; + case 8: + sp_1024_mont_mul_avx2_16(ctx->t4, ctx->t2, ctx->z, p1024_mod, p1024_mp_mod); + ctx->state = 9; + break; + case 9: + sp_1024_mont_mul_avx2_16(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_avx2_16(ctx->t3, ctx->t3, ctx->y, p1024_mod, p1024_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_avx2_16(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_1024_mont_sub_avx2_16(ctx->t2, ctx->t2, ctx->t1, p1024_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_1024_mont_sub_avx2_16(ctx->t4, ctx->t4, ctx->t3, p1024_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_avx2_16(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod); + ctx->state = 15; + break; + case 15: + sp_1024_mont_mul_avx2_16(ctx->z, ctx->z, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_avx2_16(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 17; + break; + case 17: + sp_1024_mont_sqr_avx2_16(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 18; + break; + case 18: + sp_1024_mont_mul_avx2_16(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod); + ctx->state = 19; + break; + case 19: + sp_1024_mont_mul_avx2_16(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod); + ctx->state = 20; + break; + case 20: + sp_1024_mont_sub_avx2_16(ctx->x, ctx->x, ctx->t5, p1024_mod); + ctx->state = 21; + break; + case 21: + sp_1024_mont_dbl_avx2_16(ctx->t1, ctx->y, p1024_mod); + ctx->state = 22; + break; + case 22: + sp_1024_mont_sub_avx2_16(ctx->x, ctx->x, ctx->t1, p1024_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_avx2_16(ctx->y, ctx->y, ctx->x, p1024_mod); + ctx->state = 24; + break; + case 24: + sp_1024_mont_mul_avx2_16(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod); + ctx->state = 25; + break; + case 25: + sp_1024_mont_mul_avx2_16(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod); + ctx->state = 26; + break; + case 26: + sp_1024_mont_sub_avx2_16(ctx->y, ctx->y, ctx->t5, p1024_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + +static void sp_1024_proj_point_add_avx2_16(sp_point_1024* r, + const sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_1024* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_1024_mont_sub_avx2_16(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_16(t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_avx2_16(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_avx2_16(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_avx2_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_avx2_16(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_avx2_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_avx2_16(t2, t2, t1, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_avx2_16(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + sp_1024_mont_mul_avx2_16(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_avx2_16(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_avx2_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(x, x, t5, p1024_mod); + sp_1024_mont_dbl_avx2_16(t1, y, p1024_mod); + sp_1024_mont_sub_avx2_16(x, x, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_1024_mont_sub_avx2_16(y, y, x, p1024_mod); + sp_1024_mont_mul_avx2_16(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(y, y, t5, p1024_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_dbl_n_store_avx2_16(sp_point_1024* r, + const sp_point_1024* p, int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*16; + sp_digit* b = t + 4*16; + sp_digit* t1 = t + 6*16; + sp_digit* t2 = t + 8*16; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<16; i++) { + y[i] = p->y[i]; + } + for (i=0; i<16; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_1024_mont_dbl_avx2_16(y, y, p1024_mod); + /* W = Z^4 */ + sp_1024_mont_sqr_avx2_16(w, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_avx2_16(w, w, p1024_mod, p1024_mp_mod); + j = m; + for (i=1; i<=n; i++) { + j *= 2; + + /* A = 3*(X^2 - W) */ + sp_1024_mont_sqr_avx2_16(t1, x, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(t1, t1, w, p1024_mod); + sp_1024_mont_tpl_avx2_16(a, t1, p1024_mod); + /* B = X*Y^2 */ + sp_1024_mont_sqr_avx2_16(t2, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(b, t2, x, p1024_mod, p1024_mp_mod); + x = r[j].x; + /* X = A^2 - 2B */ + sp_1024_mont_sqr_avx2_16(x, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_avx2_16(t1, b, p1024_mod); + sp_1024_mont_sub_avx2_16(x, x, t1, p1024_mod); + /* Z = Z*Y */ + sp_1024_mont_mul_avx2_16(r[j].z, z, y, p1024_mod, p1024_mp_mod); + z = r[j].z; + /* t2 = Y^4 */ + sp_1024_mont_sqr_avx2_16(t2, t2, p1024_mod, p1024_mp_mod); + if (i != n) { + /* W = W*Y^4 */ + sp_1024_mont_mul_avx2_16(w, w, t2, p1024_mod, p1024_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_1024_mont_sub_avx2_16(y, b, x, p1024_mod); + sp_1024_mont_mul_avx2_16(y, y, a, p1024_mod, p1024_mp_mod); + sp_1024_mont_dbl_avx2_16(y, y, p1024_mod); + sp_1024_mont_sub_avx2_16(y, y, t2, p1024_mod); + + /* Y = Y/2 */ + sp_1024_div2_avx2_16(r[j].y, y, p1024_mod); + r[j].infinity = 0; + } +} + +/* Add two Montgomery form projective points. + * + * ra Result of addition. + * rs Result of subtraction. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_sub_avx2_16(sp_point_1024* ra, + sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* t6 = t + 10*16; + sp_digit* x = ra->x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_1024_mont_sqr_avx2_16(t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t3, t1, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t1, t1, x, p1024_mod, p1024_mp_mod); + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_avx2_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_1024_mont_mul_avx2_16(t3, t3, y, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_avx2_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - U1 */ + sp_1024_mont_sub_avx2_16(t2, t2, t1, p1024_mod); + /* RS = S2 + S1 */ + sp_1024_mont_add_avx2_16(t6, t4, t3, p1024_mod); + /* R = S2 - S1 */ + sp_1024_mont_sub_avx2_16(t4, t4, t3, p1024_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_1024_mont_mul_avx2_16(z, z, q->z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(z, z, t2, p1024_mod, p1024_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_1024_mont_sqr_avx2_16(x, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_avx2_16(xs, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_avx2_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(y, t1, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(x, x, t5, p1024_mod); + sp_1024_mont_sub_avx2_16(xs, xs, t5, p1024_mod); + sp_1024_mont_dbl_avx2_16(t1, y, p1024_mod); + sp_1024_mont_sub_avx2_16(x, x, t1, p1024_mod); + sp_1024_mont_sub_avx2_16(xs, xs, t1, p1024_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_1024_mont_sub_avx2_16(ys, y, xs, p1024_mod); + sp_1024_mont_sub_avx2_16(y, y, x, p1024_mod); + sp_1024_mont_mul_avx2_16(y, y, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(t6, p1024_mod, t6, p1024_mod); + sp_1024_mont_mul_avx2_16(ys, ys, t6, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t5, t5, t3, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(y, y, t5, p1024_mod); + sp_1024_mont_sub_avx2_16(ys, ys, t5, p1024_mod); +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Window technique of 7 bits. (Add-Sub variation.) + * Calculate 0..64 times the point. Use function that adds and + * subtracts the same two points. + * Recode to add or subtract one of the computed points. + * Double to push up. + * NOT a sliding window. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_win_add_sub_avx2_16(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[65+2]; + sp_digit tmp[2 * 16 * 6]; +#endif + sp_point_1024* rt = NULL; + sp_point_1024* p = NULL; + sp_digit* negy; + int i; + ecc_recode_1024 v[147]; + int err = MP_OKAY; + + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * + (65+2), heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 16 * 6, + heap, DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + rt = t + 65; + p = t + 65+1; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_avx2_16(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(t[1].y, g->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(t[1].z, g->z, p1024_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[64] */ + sp_1024_proj_point_dbl_n_store_avx2_16(t, &t[ 1], 6, 1, tmp); + sp_1024_proj_point_add_avx2_16(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[ 6], &t[ 3], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[10], &t[ 5], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[12], &t[ 6], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[14], &t[ 7], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[18], &t[ 9], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[20], &t[10], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[22], &t[11], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[24], &t[12], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[26], &t[13], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[28], &t[14], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[30], &t[15], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[31], &t[29], &t[30], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[34], &t[17], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[35], &t[33], &t[34], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[36], &t[18], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[38], &t[19], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[39], &t[37], &t[38], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[40], &t[20], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[42], &t[21], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[43], &t[41], &t[42], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[44], &t[22], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[46], &t[23], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[47], &t[45], &t[46], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[48], &t[24], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[50], &t[25], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[51], &t[49], &t[50], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[52], &t[26], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[54], &t[27], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[55], &t[53], &t[54], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[56], &t[28], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[58], &t[29], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[59], &t[57], &t[58], &t[ 1], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[60], &t[30], tmp); + sp_1024_proj_point_dbl_avx2_16(&t[62], &t[31], tmp); + sp_1024_proj_point_add_sub_avx2_16(&t[63], &t[61], &t[62], &t[ 1], tmp); + + negy = t[0].y; + + sp_1024_ecc_recode_7_16(k, v); + + i = 146; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024)); + for (--i; i>=0; i--) { + sp_1024_proj_point_dbl_n_avx2_16(rt, 7, tmp); + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024)); + sp_1024_mont_sub_avx2_16(negy, p1024_mod, p->y, p1024_mod); + sp_1024_norm_16(negy); + sp_1024_cond_copy_16(p->y, negy, (sp_digit)0 - v[i].neg); + sp_1024_proj_point_add_avx2_16(rt, rt, p, tmp); + } + + if (map != 0) { + sp_1024_map_avx2_16(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* HAVE_INTEL_AVX2 */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_1024 { + sp_digit x[16]; + sp_digit y[16]; +} sp_table_entry_1024; + +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_16(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_16(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_16(t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_16(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_16(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_16(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_16(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_16(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_16(t1, t3, p1024_mod); + sp_1024_mont_sub_16(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_16(t3, t3, x, p1024_mod); + sp_1024_mont_mul_16(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_16(y, t3, t5, p1024_mod); + } +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_16(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* tmp = t + 4 * 16; + + sp_1024_mont_inv_16(t1, a->z, tmp); + + sp_1024_mont_sqr_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_16(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_16(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_16(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_16(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_16(t, 128, tmp); + sp_1024_proj_to_affine_16(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_16(t, s1, s2, tmp); + sp_1024_proj_to_affine_16(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC | !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_16(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 16 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 16 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_16(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_16(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_16(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +/* Cache entry - holds precomputation tables for a point. */ +typedef struct sp_cache_1024_t { + /* X ordinate of point that table was generated from. */ + sp_digit x[16]; + /* Y ordinate of point that table was generated from. */ + sp_digit y[16]; + /* Precomputation table for point. */ + sp_table_entry_1024 table[256]; + /* Count of entries in table. */ + uint32_t cnt; + /* Point and table set in entry. */ + int set; +} sp_cache_1024_t; + +/* Cache of tables. */ +static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES]; +/* Index of last entry in cache. */ +static THREAD_LS_T int sp_cache_1024_last = -1; +/* Cache has been initialized. */ +static THREAD_LS_T int sp_cache_1024_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_1024 = 0; + static wolfSSL_Mutex sp_cache_1024_lock; +#endif + +/* Get the cache entry for the point. + * + * g [in] Point scalar multipling. + * cache [out] Cache table to use. + */ +static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache) +{ + int i; + int j; + uint32_t least; + + if (sp_cache_1024_inited == 0) { + for (i=0; ix, sp_cache_1024[i].x) & + sp_1024_cmp_equal_16(g->y, sp_cache_1024[i].y)) { + sp_cache_1024[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_1024_last + 1) % FP_ENTRIES; + for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_1024[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_1024_last) { + least = sp_cache_1024[0].cnt; + for (j=1; jx, sizeof(sp_cache_1024[i].x)); + XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y)); + sp_cache_1024[i].set = 1; + sp_cache_1024[i].cnt = 1; + } + + *cache = &sp_cache_1024[i]; + sp_cache_1024_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_16(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_win_add_sub_16(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 16 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_16(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_win_add_sub_16(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_16(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#ifdef HAVE_INTEL_AVX2 +#ifdef FP_ECC +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_1024_proj_point_add_qz1_avx2_16(sp_point_1024* r, const sp_point_1024* p, + const sp_point_1024* q, sp_digit* t) +{ + const sp_point_1024* ap[2]; + sp_point_1024* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*16; + sp_digit* t3 = t + 4*16; + sp_digit* t4 = t + 6*16; + sp_digit* t5 = t + 8*16; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_1024_mont_sub_avx2_16(t1, p1024_mod, q->y, p1024_mod); + sp_1024_norm_16(t1); + if ((sp_1024_cmp_equal_16(p->x, q->x) & sp_1024_cmp_equal_16(p->z, q->z) & + (sp_1024_cmp_equal_16(p->y, q->y) | sp_1024_cmp_equal_16(p->y, t1))) != 0) { + sp_1024_proj_point_dbl_avx2_16(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_1024*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_1024)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<16; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<16; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<16; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_1024_mont_sqr_avx2_16(t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t4, t2, z, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t2, t2, q->x, p1024_mod, p1024_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_1024_mont_mul_avx2_16(t4, t4, q->y, p1024_mod, p1024_mp_mod); + /* H = U2 - X1 */ + sp_1024_mont_sub_avx2_16(t2, t2, x, p1024_mod); + /* R = S2 - Y1 */ + sp_1024_mont_sub_avx2_16(t4, t4, y, p1024_mod); + /* Z3 = H*Z1 */ + sp_1024_mont_mul_avx2_16(z, z, t2, p1024_mod, p1024_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_1024_mont_sqr_avx2_16(t1, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_sqr_avx2_16(t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t3, x, t5, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t5, t5, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(x, t1, t5, p1024_mod); + sp_1024_mont_dbl_avx2_16(t1, t3, p1024_mod); + sp_1024_mont_sub_avx2_16(x, x, t1, p1024_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_1024_mont_sub_avx2_16(t3, t3, x, p1024_mod); + sp_1024_mont_mul_avx2_16(t3, t3, t4, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t5, t5, y, p1024_mod, p1024_mp_mod); + sp_1024_mont_sub_avx2_16(y, t3, t5, p1024_mod); + } +} + +#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL) +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_1024_proj_to_affine_avx2_16(sp_point_1024* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* tmp = t + 4 * 16; + + sp_1024_mont_inv_avx2_16(t1, a->z, tmp); + + sp_1024_mont_sqr_avx2_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + + sp_1024_mont_mul_avx2_16(a->x, a->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(a->y, a->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * width = 8 + * 256 entries + * 128 bits between + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_1024_gen_stripe_table_avx2_16(const sp_point_1024* a, + sp_table_entry_1024* table, sp_digit* tmp, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; +#else + sp_point_1024 t[3]; +#endif + sp_point_1024* s1 = NULL; + sp_point_1024* s2 = NULL; + int i; + int j; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + s1 = t + 1; + s2 = t + 2; + + err = sp_1024_mod_mul_norm_avx2_16(t->x, a->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(t->y, a->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(t->z, a->z, p1024_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_1024_proj_to_affine_avx2_16(t, tmp); + + XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024)); + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + + for (i=1; i<8; i++) { + sp_1024_proj_point_dbl_n_avx2_16(t, 128, tmp); + sp_1024_proj_to_affine_avx2_16(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_1024_proj_point_add_qz1_avx2_16(t, s1, s2, tmp); + sp_1024_proj_to_affine_avx2_16(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#endif /* FP_ECC | !WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * table Pre-computed table. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_stripe_avx2_16(sp_point_1024* r, const sp_point_1024* g, + const sp_table_entry_1024* table, const sp_digit* k, int map, + int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* rt = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 rt[2]; + sp_digit t[2 * 16 * 5]; +#endif + sp_point_1024* p = NULL; + int i; + int j; + int y; + int x; + int err = MP_OKAY; + + (void)g; + /* Constant time used for cache attack resistance implementation. */ + (void)ct; + (void)heap; + + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (rt == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 16 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = rt + 1; + + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + + y = 0; + x = 127; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 128; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=126; i>=0; i--) { + y = 0; + x = i; + for (j=0; j<8; j++) { + y |= (int)(((k[x / 64] >> (x % 64)) & 1) << j); + x += 128; + } + + sp_1024_proj_point_dbl_avx2_16(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = !y; + sp_1024_proj_point_add_qz1_avx2_16(rt, rt, p, t); + } + + if (map != 0) { + sp_1024_map_avx2_16(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (rt != NULL) + XFREE(rt, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_avx2_16(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k, + int map, int ct, void* heap) +{ +#ifndef FP_ECC + return sp_1024_ecc_mulmod_win_add_sub_avx2_16(r, g, k, map, ct, heap); +#else + sp_digit tmp[2 * 16 * 5]; + sp_cache_1024_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_1024 == 0) { + wc_InitMutex(&sp_cache_1024_lock); + initCacheMutex_1024 = 1; + } + if (wc_LockMutex(&sp_cache_1024_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_1024(g, &cache); + if (cache->cnt == 2) + sp_1024_gen_stripe_table_avx2_16(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_1024_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_1024_ecc_mulmod_win_add_sub_avx2_16(r, g, k, map, ct, heap); + } + else { + err = sp_1024_ecc_mulmod_stripe_avx2_16(r, g, cache->table, k, + map, ct, heap); + } + } + + return err; +#endif +} + +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r, + int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[16]; +#endif + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 16, km); + sp_1024_point_from_ecc_point_16(point, gm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_ecc_mulmod_avx2_16(point, point, k, map, 1, heap); + else +#endif + err = sp_1024_ecc_mulmod_16(point, point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Striping precomputation table. + * 8 points combined into a table of 256 points. + * Distance of 128 between points. + */ +static const sp_table_entry_1024 p1024_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0xbf9c7ec6e0162bc2L,0xddecc6e310a89289L,0x5d599df09e499d81L, + 0x9a96ea286d358218L,0x01aec7d370c5f8dbL,0xe72e49958cf5d066L, + 0xc2e7297d3e91d7f8L,0x8621db92da9f2f5aL,0x4b26c8675a5679edL, + 0x233385df2c56aac1L,0xb88e74d4c6a13f99L,0x1214b173ffa8ec11L, + 0xa0386a271f3f9fefL,0xbd9b1b4ec0e7b44eL,0xafe528dceecd3496L, + 0x8dfff96a1c49f80bL }, + { 0xb4a4753ac03c0c83L,0x68e69d18abcdcd75L,0xe3839b88f775b649L, + 0x803f949abf58f352L,0x5f702679bd0bc15cL,0x85bf5d168ff298c2L, + 0x3f6ebd98c6c7976eL,0x20618af445e3e1b4L,0x67d5598e54e64093L, + 0xb047283b504fed9eL,0x450cabfd70d87517L,0x47d628bf3f5addbeL, + 0x0037ef3078cb4ccaL,0x4e148d3c6b1c4908L,0xe256d3294fcfd837L, + 0x2aa1207bde3c01f3L } }, + /* 2 */ + { { 0xa95b6dae01900955L,0xa5dc9cc1ceb4656dL,0x50c78907e72fe95bL, + 0xa1ae5447a040c334L,0x911913707952ea6eL,0x54ff73436d097305L, + 0xa4db0074bda4d10fL,0xfd5306f191644070L,0x14b9fe738b24522cL, + 0x1468dad67849f762L,0x87b29a18b0dcd2e4L,0xadd7f1a15e1ad492L, + 0x9ac63a81dbba2a1aL,0x01379c5b81223379L,0xf402b2f0b0e53bc8L, + 0x8c3eb27f0bf13b61L }, + { 0x9a4ad3e1e513696fL,0x0350ba5c18c81ffaL,0x1e2fc1363c033d13L, + 0x53da6e7117a531bcL,0x42ec64901aed610dL,0xd33e8df7e99ff567L, + 0xe4aad73e3deed12aL,0xd983b465180f4debL,0x99365269502f30b4L, + 0x7e2799aba8918d7fL,0x0ffe84b6700fc79aL,0x7b4400d640bfd8c2L, + 0xc3a21d215d2641bdL,0x79839442c32621cbL,0xace6500bb1401e83L, + 0x7bf4163e251c4310L } }, + /* 3 */ + { { 0x1c174f88e3fd589eL,0xdb501790df974a03L,0xd09623e33e70549fL, + 0x8d091eff15924f34L,0xeef79cadf9b65ac5L,0xd2cc42623f69c2cfL, + 0x817d903252cd82bcL,0xacf4f4d9a5f1ddddL,0xd06126355011b6bdL, + 0x9f74490d2ed140c9L,0x64092e8c4db686d2L,0x225eef16776b0fccL, + 0x0e8c01e9df16aeb6L,0x6283674184bbd82aL,0x757574e28956e337L, + 0x9871edc6705a7f07L }, + { 0xbd0b76d5776535f7L,0x5214d6022635b3b8L,0xc0c25ad99d216f64L, + 0xfd4df3a75515bf75L,0x24a625bc5e9f1675L,0x3c35efb7406873e7L, + 0xef5c9a33bb2e5c4aL,0xa971b35e806b198aL,0x9f5c0ca5a3c690edL, + 0xa8d5dd898e1e2341L,0x4cecbcce955ad9e4L,0x2ecf4407248d3416L, + 0x1abb381145c0af6eL,0x3f4bee821c780fffL,0xd14df768c272ed57L, + 0x397ed10a371637adL } }, + /* 4 */ + { { 0xcf3e0bb2755c2a27L,0xd38e42f959585c44L,0x46b13e0f19285e60L, + 0xc3ecd0c076273d0fL,0x7800f085193c569aL,0xf04e74ab4351818aL, + 0x9258aa388496363bL,0x8456617cb8c894feL,0x8bc62aaa2af969a0L, + 0x66c2280b5a4668d9L,0xbc9df58ea992f4faL,0x5db0b7d93f401e99L, + 0xe0614fe1c4c38c0eL,0xd531151c2ccdf6b3L,0x1c7575ece143b618L, + 0x40247985df9398a4L }, + { 0xfba251788f055746L,0xc5ba00400ab1e6e0L,0xe1b194fbac292697L, + 0x771521195b4f4740L,0x250091d09bb7ba54L,0x7a674861b9a139a4L, + 0xba8413b3f353aa7eL,0xafe771922443ceeeL,0x14468d363847bbd0L, + 0x61f79ff63da4942dL,0x1563a1c1d425b456L,0x3c270fcd75ff4630L, + 0x42072090eb2802c9L,0x68f0cdcbc85c7004L,0xca4372fbfa032e74L, + 0x1a6fd1e6c8b79d80L } }, + /* 5 */ + { { 0x967a901a8d5116a3L,0x0b844394b2f5f47fL,0xe39ad45260ebaf3bL, + 0x1e1be61760ccfc0cL,0xac07e3d2cc3f53f2L,0xdd838e0e1ed11bb6L, + 0x454753071c15b0c2L,0x70dd4748920fe5b8L,0x1a20be2de471896dL, + 0x3c3fad8a59276c7cL,0x026a1cc3c886ee07L,0x9fdb6f376e831ac4L, + 0x26a35d1aac501d65L,0x0ae9890540da8574L,0x65dde0a4abd734e5L, + 0x29b7d4dc15614750L }, + { 0x44b3c2cbcbf4e20bL,0x1c3f548f58cc44c5L,0x39809b545b0cac1fL, + 0x0c0f02b500f80621L,0xe612b890066905e0L,0x8f158ed78350188cL, + 0xc01dc4583f5576b2L,0x29803272a45492e0L,0x77a5623a0ff92443L, + 0xd12a2b0029d0dc41L,0xb41254592780e87aL,0x1ebcf9030d53f272L, + 0xbae6ea4024301e8dL,0x1e5f3f2fa37d0798L,0x9342c31022b4126cL, + 0x5d0928025382497eL } }, + /* 6 */ + { { 0x583a2b7eff2f780dL,0x34d26820d7d76b1dL,0xe3c3284786f74aecL, + 0x0fd4221210823febL,0x227e417efb5e7bf4L,0x510d49b6a568f8cdL, + 0x53bce7d61781bbecL,0x9cfe3f222f3718b7L,0x7f44e89fd9de6c1fL, + 0xf1cc553f3fac9b55L,0x9d2d0846e6f300bcL,0x976c82a29f0ae6b1L, + 0xe63dbf5e24b8bbe0L,0x4cac7f45973a5aa7L,0xc6eb623784dd33c7L, + 0x0a26e434142fee5dL }, + { 0x8081339facaa9a08L,0x40f311055246ece1L,0x892c817061393747L, + 0x8d8d4103242f02e1L,0x482bfd203b5de98aL,0x89ef946b5abbe952L, + 0xb8d218b937698249L,0xd5268e8966617c7aL,0x962e75518b7d2b91L, + 0x2c5c7973fe8d67c3L,0x42e3150a2b017c51L,0x6f4e5ebcc1a29469L, + 0xa39910ce531c7083L,0xaf4f6eb4b77b9e50L,0x68cbb175da120ad0L, + 0x19497c61b92636ecL } }, + /* 7 */ + { { 0x6920b0c6417659a8L,0xc77ab9c792cb28ffL,0x55b67180b687797fL, + 0x4caf58c1e7759363L,0x5155bdb65561b186L,0x2e64e355780f4946L, + 0xeb0ac9b7229a8b20L,0x88594d782571bd60L,0x5dcc0939e3fa78f9L, + 0x7b8b48302ac2d379L,0x505fbf60b90f1444L,0xac610e813ce4b3c1L, + 0x39a4f27ad59b5c18L,0x5fa339737cea0222L,0xe578730b8dff1c7bL, + 0x96b91b8b517bf7a6L }, + { 0xc1a991f49aac087cL,0xce62f74e6cfdb28dL,0x08d6ff9a5f7600d6L, + 0xd781cd04f917f9c9L,0x7796f5f63de52dbfL,0xe7db64e02ed72180L, + 0x0f0876f66fa4137dL,0x3271ee643ca1f716L,0xcb9b20587c4ab8a3L, + 0xcba1710739481047L,0xdf9a190d598c5c37L,0x0cb6e72a6f20e125L, + 0xa3142204f4f2902dL,0x42d28cb97ce2dcfbL,0xdf261b8aa3d3c351L, + 0x73f3d315cffc249dL } }, + /* 8 */ + { { 0x5d86855be6fd3673L,0x309b70af9d214b7bL,0x8d332f90dcc46cd3L, + 0xe553c015595510deL,0x5746a09638c1251cL,0xcd7cea5b85cc1bc9L, + 0x4ffa1468002eba8fL,0x10a3cb7022fcd77cL,0xb6999dfbc4ea05e3L, + 0x3375a0d04efa756eL,0x4d90279edced5fd8L,0x48192403251fd56eL, + 0xe87633a482a4c5f1L,0x3170d1301b34105bL,0x93998b0f7247e578L, + 0x88934f64436ba1faL }, + { 0xf09f43b04713eabcL,0x4ca7dd91accdc517L,0x27daa63bef13ca7cL, + 0x8b2e5a7a2588184bL,0x0a8cb612d95dc269L,0x346975a2e1f2f14cL, + 0x1f29b8ede172935cL,0xc3cbfd6ed40bc1e3L,0xd3f46b3f132623daL, + 0xc115be6dfb0b7681L,0x5e31c34556da4344L,0xa7c63f18a8e43d98L, + 0x55cb20834bddb4eaL,0xb16a0c384a54f58cL,0x74eacca246fd69d9L, + 0x0d1898bb153548e1L } }, + /* 9 */ + { { 0x4ea73461e35ef043L,0x107b67d93496b564L,0xd62c173bd0f83a3cL, + 0xfad4b03851d29c35L,0x3f42882a71b1c1a4L,0x5d2bcf6654b43b9eL, + 0xc77b15aa2abdf543L,0x5cb38a80dabe3dc1L,0x15fda0aea481673bL, + 0x86996b4de7b90ebeL,0x84f87e252bc8f3d8L,0xaded03d637c4e424L, + 0xe5ede666d7a7afd8L,0x80dd95a2a1ccb93aL,0xa55cfd2546fba391L, + 0x2bdab1dc46f82e60L }, + { 0x7a4de22bfa6fed61L,0xca458aa5cc8dd94eL,0x3e372df1071222f5L, + 0x06a4b44fe5aff377L,0xbc2d0ba74a738e6dL,0x1a470e1d5f31f136L, + 0x77ff933ae102a911L,0x8b380a50310c7885L,0x9f3c0228783fc5acL, + 0xec66892544725d06L,0x878f0e165ac84221L,0x9a3af1afcfda6e8aL, + 0x0183ed3778cd2abaL,0x32cdbd60826d0eaeL,0xb3234661cbee6415L, + 0x353eb892b9c10120L } }, + /* 10 */ + { { 0xc8fdcad610b5521eL,0x1a11b44052e702f0L,0x6302680d8ffda49cL, + 0xcdb9654acbf36badL,0x7b58ce114c10a2d7L,0x1e5d1f7de630e7e0L, + 0x8cbe3d7d6760a813L,0xeb35866b6480d77fL,0x58728cf37f036219L, + 0xdd5865ed42a8a757L,0x283f1f1d906a2870L,0x79e23fa4a51f906bL, + 0xf2ac6e83543b20a8L,0x4f0b6379b81e7754L,0x57fbc0d4840016eeL, + 0x8da20771e621b67dL }, + { 0x3c855004ecce65ecL,0x76d10d1fb748185eL,0x64be7bca78797ad2L, + 0x43444db077e54aadL,0x17b6b0c9be0df0ffL,0x8fc4256c055086a4L, + 0xf952c43bfd74d5a3L,0x501e005a01c4edb8L,0xd5172dfc4a57e328L, + 0xdb40ce4e535d6ee3L,0xbaef1e5c0c650918L,0xe85145e7857561fcL, + 0xe468536a34a224c6L,0x69a8e2270ec0e0a2L,0xb3f52247242b03fcL, + 0x862f55e2c3bebd5fL } }, + /* 11 */ + { { 0x2d6a390f226049feL,0xcc92a578dcbbc9fbL,0xa52feca497634fb7L, + 0x2b340cb63dea5893L,0xa39f338a2a49e916L,0x26b2df3d949e41f3L, + 0xc71c7cdb065a7e40L,0x4a9b84a0468281a2L,0x63eeb503731eeecaL, + 0xe6d0913476cbb725L,0x0cf979a9b94a678cL,0xb44d8c3b808fd9f1L, + 0xe60da613e0afc5b9L,0x52dce7de3ea5be69L,0x3a5d6864dc1ee74fL, + 0x71ab28913bc80790L }, + { 0xcf618fc43b5b60adL,0x0afb5e304a0c3184L,0xd22381ccbc403302L, + 0x33cf8953db1c0c66L,0x9c994e4da6112a8dL,0xd7aae2c3d1967a86L, + 0xc28d54935b7acd29L,0x8075bd136c9a57fbL,0xc9c0373e9c8427f9L, + 0x2cbca18d193225f5L,0x73777d13442c018cL,0xebe5ed47fbb3a727L, + 0x70437d491962dc18L,0xf39c1e092dc08806L,0x03e9c6f715fff35cL, + 0x8d087bb65e360a65L } }, + /* 12 */ + { { 0xbe2123023fdc1844L,0x6eca27ef105eac56L,0x2183a606f168a348L, + 0x295f807de1d7a4cbL,0x7246a6327ef5d43eL,0xae143205c77025c7L, + 0x4bdfc7caf3484e3eL,0xec939895df52c075L,0x82e655f6d7a9cac0L, + 0x985dfe208baeddb0L,0x79c817e4527de731L,0x30ce0fbc313de1eaL, + 0x9df95b89cc4f6cbbL,0xf2aedf1ef5bb20cdL,0xfc1e0a891a8cfb01L, + 0x225ed34a63edb7ecL }, + { 0x3e13154dbabb1a85L,0xd3d8dae71e6a565aL,0xd3217d56ab4b100fL, + 0xd44d934eebc78e1aL,0x0215321b48e73d37L,0xbbc90bfa201e43cbL, + 0x3c23f1d027500905L,0x2a2e5000c86691a1L,0x08b2bad26065841cL, + 0x15d41caf30026b60L,0x1712c2f45276ce61L,0x01c4c3e715932ffbL, + 0x7894e13d6a74caf2L,0x02d6f5df0c0537a4L,0xa8fb7602c2b1c97eL, + 0x612b60e5d0887c7bL } }, + /* 13 */ + { { 0xefd495cfba245d6bL,0x5cf0cbb7a2ce3ff6L,0x24da2ac0dff5feeeL, + 0x90c914f8cf28c6a3L,0x72fdb50d4308a56bL,0x03dbf77913d72034L, + 0xcfa5ec91822ac9e9L,0x0dde73c83aea3e81L,0x545ba96266289139L, + 0xa52f648bca6acbd3L,0xff6f276e98a0683aL,0x2536d3aca378ed52L, + 0x353c2c54885ac1d9L,0xcaff52da00bc84a7L,0x3971f81c37684167L, + 0x0f7334e1d2d7986eL }, + { 0xafbb5c836596067eL,0x33e54e1938c19806L,0x8285d96739cb0dccL, + 0x2b53f43d424035f9L,0x38c531f8dfef9095L,0x90fbe8e4db0f571aL, + 0x9a0c1ed2a39ca787L,0x2fecc1d6606f2620L,0x9dc890b172b7cb4aL, + 0xc33ca6fbccbb7868L,0xd1b11082fe73ee49L,0x590b7d17fcb66c48L, + 0x9356b0a686e14573L,0x75d682c4053ead85L,0xb2ae55fac54d30fbL, + 0x67636a72f8aee949L } }, + /* 14 */ + { { 0x638063bcb91d6beaL,0xae263a2e923ecb96L,0x9d7b0992c627aca6L, + 0xc6ed001a77af9e7eL,0x9214accf24aafebbL,0xa3564b9678055a90L, + 0x00999b1ce027499dL,0xe413a4e1e46a06a5L,0xa05d13f62e51efe7L, + 0x35e87d349ba843beL,0x0a6338253183159eL,0x6023e8ba54601923L, + 0x9b107721b7fd1cf2L,0x46b5542bfdf2fd53L,0xb314f4f81c18af38L, + 0x086f987660ac8965L }, + { 0x767019548cbb9850L,0x6210b730a20d2c8cL,0x4084d0575335670cL, + 0x3ecdc5950324baeaL,0x607fc5f2c76ee9b4L,0xf393d00f440ffa64L, + 0xe01117962dc1463cL,0xf00b82519c7725e7L,0x35e607365bd1d186L, + 0xf3d8554c2cf72aacL,0xb4dd0fdeefa3497dL,0xd712268cf646ad11L, + 0x07c20afb9f7b8eadL,0x630969d4fc06dfe5L,0x76b7df1c7245549aL, + 0x681f9403e61ae810L } }, + /* 15 */ + { { 0x7cad5163c9a0623bL,0xdbf8295767fab8d4L,0x2ccab0ec81af7c7cL, + 0x469e38c8e966d5c2L,0x34430d52f0d4e41cL,0x426075a2a52b359cL, + 0x242dd3e333bd0127L,0xcda3f6359fed2341L,0x4df33730d7d52ffaL, + 0x5fff56f07640c3efL,0x4783c21c1bbde57cL,0xd8784a2aeb8bb336L, + 0x1ec7c533ead08405L,0x4b7f1423f9b62bd4L,0x5543145c7075d4afL, + 0x0c9de94aba60590aL }, + { 0x8ed7273595d5682bL,0x711c42832ec276edL,0xd1f4aed58b36a0d2L, + 0x62ab40c48498a88fL,0x58c8fc624480f451L,0x8bc8ca4bb79cffe2L, + 0x90ab583c701a359dL,0xaee31a733fd5d15dL,0x02a5597bc912333cL, + 0x1019cae4b6c3e3c2L,0xe513042c29938088L,0x0e00283df47c8199L, + 0x90d68e58f2a00e92L,0x69e2df41a775ae3bL,0xb8d2eca5871c30b2L, + 0x733dca0ebb1de396L } }, + /* 16 */ + { { 0xf5b495d04b59213aL,0xca6720398d70200eL,0x4bcb09a62b6771c1L, + 0x26adeed42b9eb0cbL,0xeb5447548cdba212L,0x0e1abfcdf08890d1L, + 0x52509963698e46b4L,0xe1bff0b082e9c138L,0xa189e4cd51099a71L, + 0x2360c9bcc9b91cc7L,0x9bd4d7dc137ec4beL,0xd0356521d1519f6eL, + 0xbf5f6d78cf832503L,0xe43010318deea2b4L,0xc3132494ef4c319cL, + 0x2ab3bd470f1fa7d7L }, + { 0x5753b680922c9fbbL,0x869e7dc80f16c6d1L,0x83445135bac16efcL, + 0x4326a3b4846d1d9bL,0xb517fee3b2d62c21L,0x6905afa20b292ad5L, + 0x2a57131a2cadac13L,0xcd904d8febdbca8dL,0xdfeda86f3f365fb2L, + 0x7097b208dc7eaa1cL,0x89a35a84a45e77c0L,0x417a062ccf5d118eL, + 0x3c0c04a81f6e99e8L,0xc44704b0ba7a087dL,0x6f8a27d13ea22ad2L, + 0x93a4b4164c27d229L } }, + /* 17 */ + { { 0xd4271bc11f1efb7aL,0xae4e68e633fccc0dL,0x9d9bc8f1b11f50a8L, + 0x5430398faf076089L,0x45e242fb443d0e03L,0x73ec2519f6e3d4c1L, + 0xab70f790ba9bad09L,0xde612ad5f9add10fL,0xb837e54e14e942b4L, + 0x175a56d3ddb8b68aL,0xe85b233c1ac2a408L,0xf8ff6c30f0c80f94L, + 0x4b7f3fb7898db4f9L,0xa2c6044f45a7dcddL,0xf3abb2f6fe3d3895L, + 0x342ce0d732ee7763L }, + { 0xeb261394cf491b1fL,0xdcaaeed71909e395L,0xdcc4055a9fe4dbeaL, + 0x17a6611d493d604dL,0xba445a3a1ce5ebefL,0xe82e2858e3989cb5L, + 0xb96f428283f58406L,0x99877b99a156cf55L,0xaf906a664e166a0eL, + 0xcea1d353b2976d13L,0xefc16f2736c61a01L,0xdb04c433b0f55d86L, + 0x3cb4b2698eb34c01L,0x38d07f782ae60280L,0x43ac3bcb43be3ec5L, + 0x455f4af3e156fd20L } }, + /* 18 */ + { { 0xc057f262754ec21cL,0x3eacd4c9e3a1ba38L,0x3a0210d1116c1fe9L, + 0xe4ea4e94eacc8ab6L,0x31c00c9aea6f32caL,0x5cb6239d86b975ceL, + 0x654d5d8ca14ea1e9L,0x230d31f45067fc8bL,0x48bb90cb6355fecbL, + 0x78f81ecedc172e8eL,0x288380a8cb006737L,0x19b02e01e162d012L, + 0x0e087a06c5af145cL,0xf04dc8b7b72dc354L,0xf70ef2148de3c066L, + 0x4f14824313009fb7L }, + { 0x5e004fce6e2055e2L,0x89e247ea86c32067L,0x4ebcbd955f9daaa2L, + 0xd15f212fceb7f63bL,0x5ecc5c1f863784a0L,0x53b3800b75760251L, + 0xeb9301c38a6a2954L,0x0f16ba18a13cdd19L,0x8313d251887c2d24L, + 0xf99235859a9413f6L,0x423405e6fe3fd7c5L,0x678aeb3416e0ee05L, + 0x1f3be7bb3fadaab0L,0x7901fa2c82884471L,0xc950db304d662ff6L, + 0x74d5d2d43c01170bL } }, + /* 19 */ + { { 0xa3002dc02b5bfe11L,0x0733410d52d321e7L,0x15920f659679ba89L, + 0x0e248c14685b236eL,0x8cfab594346f6040L,0x9f57afb740c717f0L, + 0x0dbab28c66044576L,0x0fa099689cdc3247L,0x41e02ae2c230ed05L, + 0x0d961554e45bef74L,0x9688a982ce4d7b6fL,0xfadefac75e62d22eL, + 0xaf1512a6bd2cba28L,0x78868e62be7c749fL,0x88048d81ae9f5a6bL, + 0x6b1a5442c5857a29L }, + { 0x9f5ab9ad43242066L,0x0afef1b52ccca2aeL,0xb1b43ec7988edc4eL, + 0x0d0c00f10341b0d5L,0x4d68b8f7b50aab37L,0x9a8e4e6ff3a64a99L, + 0x198338fb7f1a684eL,0x8bc0e748351a0f5cL,0x2cacf2cddac44515L, + 0xc14d39995e9ff76bL,0x54a01b3f16393055L,0x6ac3eea5888d8376L, + 0xb84d9a9a723277b1L,0x99132691e11dbbbfL,0x597717aeabb67178L, + 0x4c2135268bb14ac8L } }, + /* 20 */ + { { 0x2e6fe0a695532833L,0xabca228ed626d067L,0x22aef3d9649e73bdL, + 0x2083a87af03c4c0cL,0xe954e75d35169b45L,0x577509ee74506a89L, + 0x49cb276e2aeacf90L,0x08275d77fa409f91L,0x61eb6f3df0bbd6b9L, + 0x948202cbe4132704L,0x35f3fc21b1c498b1L,0x76c68ba8361fee59L, + 0xa18cbbd950e051f3L,0x2384a879318e7042L,0x292abead80dd1e8bL, + 0x65713c295c37c334L }, + { 0xdccca8e9ceb77b9aL,0x2f97e72723b69469L,0xc76abee6a01d6b28L, + 0x3925203d5abecdfeL,0x8944808229290d70L,0xf9931424b0314438L, + 0x04209df17cd447c3L,0x7c6f2059c855c827L,0xd97d786256c0e069L, + 0x5a9db6fe412d94c4L,0x19a64591994c41ddL,0x12348aa1c89e21a3L, + 0xd6904b50c6a03f0eL,0x55c15156a616feacL,0x4e36d1b57cc7693bL, + 0x6b0e996c3bae3c38L } }, + /* 21 */ + { { 0x32789fabcceced00L,0x3237e71ae5b7aa66L,0x87b2e2692ddebcdfL, + 0xb7245120b61dad8fL,0xe11e5e48d35f803cL,0xfb4df5d798e50f0dL, + 0x60ee68b4bcd2ab92L,0x98ab2f5c1ce3363dL,0x15ba39da7cd42647L, + 0x1a6572eb83f4fb3fL,0x0f77de88e56f08dbL,0x1743761e172562c2L, + 0xbe349ff88a58f0f4L,0xe04da71b84d1d6e2L,0x368f03429e9ff3b4L, + 0x4022a205678223f8L }, + { 0x527bbd0583847375L,0x3ae56b623f451af0L,0x6198f24d4b2c7f18L, + 0xee323f5b4525b98dL,0xa9d8d39a0e0884b5L,0xd005d7f6fb12c776L, + 0xd71c483e708bc154L,0x8ca6fd28742541bcL,0x0af3dccdf8397ddbL, + 0xb80d31253eccf243L,0xc743a10858d81b8dL,0x3f48eb2171391f68L, + 0x493aff8833bb657fL,0x1d15ed6607e47e31L,0x10159b11e08279f6L, + 0x312179cb24a6a956L } }, + /* 22 */ + { { 0xa94cc3ca07615ac2L,0x85865e64121ad581L,0xae47616fa7986b79L, + 0x395a40eb9d5e0f1dL,0xa91432643d9457eaL,0x8de6d6a3fa2865d9L, + 0x0771db961014ae8cL,0x77a7cce6976a87cbL,0xa7de42e1143a0f60L, + 0xe203cc09d993d934L,0x9201869398ec4c3dL,0xd77546d83a25df4bL, + 0x0ad9eb4762b02d6bL,0xfaaaf208d05a7189L,0x5238181f431221bbL, + 0x417d6c78733511eaL }, + { 0x3cbd81b70e91e9a8L,0x73340418c370d6b3L,0x825db10a8eaa2373L, + 0x8f2b09e46c7d6756L,0xe288ee9b94c33dedL,0xcd8426bb1695e3fbL, + 0xa6176c86dce9e888L,0x3f4c89226165e362L,0x514e411f6063fb09L, + 0x6907ac20c8f9e04cL,0xcef7469cdfd2ad61L,0xba30bae48452199aL, + 0x3068129312ac3462L,0x011be873c92d482dL,0xff4cbf89e8330995L, + 0x02189d52d1470a0aL } }, + /* 23 */ + { { 0x73e419dd92599c69L,0x5b94221b7fec32caL,0xb2bf9bd209bbfbfdL, + 0x61ea97a463ed895bL,0x6609146b3f486f79L,0xbd1c7a05fd141a39L, + 0xc79ec8cf83d64135L,0x7f8fd42f9883507bL,0xafcb53b717b3d027L, + 0x86658dcd67ca5a21L,0xa6a6c0accd149786L,0x16f3d70e34b95067L, + 0x371208e3df44958cL,0xd2dd64e6ec280212L,0x33b2c4ab30782c71L, + 0x7bbf8abd521176faL }, + { 0xbe9e4aafa78b981aL,0x788b4e36304ec828L,0x0c45cf393959dea3L, + 0x70a9bdd3240b39c7L,0x499cd7dd28383b7dL,0x30690b2e307a1026L, + 0x2262d598ee92f1b3L,0xc62d77deb4725a48L,0xa16f25bc7bc3aa0eL, + 0x62dd8b65d15ef7faL,0xd979221d0b96d68fL,0xb92885c3a00f1906L, + 0xfa476b9beb74c740L,0x217ddbb5c7576222L,0xc2782c305788504fL, + 0x860d096cf812716bL } }, + /* 24 */ + { { 0xfebc337d4d79bbf9L,0x5d53eab869f74f80L,0xff36a09533104d53L, + 0x2ab820da196f8b97L,0x961d3d1f75ce6909L,0xb197ec0404683754L, + 0xa68ce1bf93a6cb9bL,0x503456ffc5f021a3L,0xb50a2db18940ffdbL, + 0x77c50f8fef004209L,0xd635d17704965875L,0x725766d98bb8770aL, + 0x8e19b028a078e53eL,0x364d4ccaf9fc8378L,0x1a3df411f0dd39a0L, + 0x7e80e44203adf920L }, + { 0x4b5f8a57539a1ddfL,0xd248e7aeee486562L,0x1c7b491d816021e1L, + 0x2e7b871bfd36d2c4L,0xda38b5040aec00d9L,0xf28276126193f1b3L, + 0x69c3fe86fb1f78d6L,0x56c8b786e827ac33L,0x1687f6c73487c8f7L, + 0xab8f221719dee5bcL,0x04e8473fff399418L,0xf384c014a9027c80L, + 0x9967be9aaa1d2e28L,0x869686d3e065eef1L,0x737c6b08c7bd837cL, + 0x5dcab5d19e8bd863L } }, + /* 25 */ + { { 0x0784283a9a7d772bL,0x6b49e525e540959bL,0x546bb00886414ab5L, + 0xd44481629d74b2a9L,0x267890ad203b0b1bL,0x1e7a82bcc8d3f86bL, + 0x1352bfb5d85a83c7L,0xf29f16e3fad07ccfL,0xc02a63b841e0c43fL, + 0x904f22c56b379fefL,0x19d8a653b1244f26L,0x6635b6df3a28bdeaL, + 0x18b68851f6d455ceL,0x74ac28189cff3735L,0xad40f9df8b2cbdabL, + 0x08cc2d9eadc9d498L }, + { 0x2e6a6866c170c84bL,0xbb989e8b5a49a484L,0x7b0e00e0d04c8992L, + 0x55ad347861b3a423L,0x3c952450b0d01899L,0xe3922155e3100cb3L, + 0x19265b6ef03276d0L,0x0fe8595a76d42b53L,0x0a96dee0fc6353b6L, + 0x761e0dc8246f893eL,0x4ec902bef0a74cbaL,0x610086843fdfad9bL, + 0x5d6a60e44fdb6975L,0x3f53aac87ef7590aL,0xd29e6be012870a37L, + 0x991fadc155aa55b0L } }, + /* 26 */ + { { 0x82bc4b0fb4844ffeL,0x7392271460f8b871L,0x8ac000e24ce3f1f3L, + 0xf0d548b4163519ecL,0x7aaf842b88288b5fL,0x9e8b0c4c2bdc9a70L, + 0xa06d51524ba5fd67L,0xd0b1afa0f93cdec3L,0x280955badf89f8f0L, + 0x86cbe92deea32c92L,0x0cae3f993fe05be4L,0xf2607095fa6919aaL, + 0x0f54741e6e0f1b8bL,0x2aed1f7430ecf988L,0x9296f76b734991d7L, + 0x66cf8d28259f0fe9L }, + { 0x9b01905b226f5868L,0xc102e88c16909e9eL,0x2bd089164a37eb54L, + 0xf72253e8c9816323L,0x37f84e9d86bac53cL,0x2e352454afeaaaf7L, + 0x67c86f772ca0046eL,0x86bce50e6663372eL,0xf6a3a960b6950a04L, + 0x61f994d7fc1aba93L,0x1957c12bc1326e6eL,0x9b658fe42e56b005L, + 0x9cd297fc8592740cL,0x7654ce9b177f26a5L,0xaaa699dba79d2ebbL, + 0x5fca0c5a0ecb6448L } }, + /* 27 */ + { { 0xe26e25f3569a6663L,0x09597ee7e6aa4ca7L,0x25a4cda68d18b80cL, + 0x450602b522926730L,0x9af5f65007387209L,0xfeeedb3426733a53L, + 0x0f5ce76886572951L,0x872a360b8398ae9aL,0x60347a802b30f6c3L, + 0xd2113b231a162158L,0x6fd9cf92ee6c6decL,0x85f0a5a85cbcf9e6L, + 0xd7a5a6e42ba3fe84L,0xaafe672051ecd727L,0xe09c6bb2a2081a10L, + 0x657acbf0b973b0b4L }, + { 0x3130466fc274c8d4L,0x4276517630a994d1L,0x217258ca7079435fL, + 0x44850406eb897a06L,0xf38dfeee561ee130L,0x11f4facfaa1778bbL, + 0x765c6617b9abb9e9L,0xb135499bd8f10932L,0xc0eb6337a73b9159L, + 0xf2c1ccf16f7e8b6aL,0x5b32c03a187def53L,0x89ad1d49830b9c62L, + 0x1735eae32f10e538L,0xb1cbd9c29d5f55bcL,0x42428c47e539db0dL, + 0x3d2da412c852b3bbL } }, + /* 28 */ + { { 0x97702b6e871f2865L,0x56cb639f142920d6L,0x328522a045b58611L, + 0xf3943ad1f3b13812L,0xe6c2200a712206e8L,0xc2890e5aa34d59eaL, + 0xab52fd40f6b7f759L,0xf522c8de180bf567L,0x181e97b2accee396L, + 0xe0375819c4ea5cbbL,0x0d9985e8ab51d3efL,0xe26c96cabcb50fd8L, + 0xfb9d6b1397e1c80dL,0x582b1814f796357dL,0x89a7822107f4c7fbL, + 0x02aeef2dc0357e61L }, + { 0x2ba7926f2c7ec9beL,0x292f307e7258b201L,0x74e62a10c6fa6b4aL, + 0x80c08549e2bcc5abL,0xb4160db87bb8c073L,0xd5ef0529329f194dL, + 0x0eb8da146dda4a9cL,0x0b5d43d215ea23d1L,0x6cebef02fc34bfaeL, + 0xacd364d0848757a7L,0xc14013682d34cca3L,0x09ca67421d2d95e2L, + 0xc3fd1d6e786eaa28L,0x9eb1136da2965fecL,0x48871baac0779203L, + 0x6b446c014b15aeb0L } }, + /* 29 */ + { { 0xc819eb2e25e8fe80L,0x2b5f790698238a17L,0xd6f1e99681e41849L, + 0x58ad8ad698ea6d45L,0x5bae5ad4bfd02e40L,0x016dc327a812416dL, + 0x8b31a985a3347ca1L,0x0b4da61082a65391L,0x1cb91b2db48c35fbL, + 0x9e96817cd2aaf8c4L,0x1a630483cdfdcdc0L,0x7055936112b69254L, + 0x5fdcd712f8a2a097L,0x59ab623a35cc5281L,0x30c8ebe0932b6095L, + 0x8613424bb08e052fL }, + { 0x28902063b2231d8aL,0xb0f62329d9a61667L,0xaafa0fe7071a9f27L, + 0x6bcd8960603f047eL,0x118cca76fd92a1c3L,0x3414e62b71d483b6L, + 0xa123ccddba705262L,0x1a576437fd9b5c5aL,0xa5301bc24c8d0fa3L, + 0x96f0ad44102427cdL,0x0e6fb5e0d3aa6c02L,0xcd8c4880072a3996L, + 0x4dafca12840d3fadL,0x29f4ca3dde91d541L,0x0037c5988441734dL, + 0x86333a999ccfe57cL } }, + /* 30 */ + { { 0xd213a751ecf53b40L,0xcff2c6f22f78a542L,0x0f59f0e2f13ae56dL, + 0x91f8ccbf0e61748eL,0x0aadecb9d72c4145L,0x6b2ed8524c9cdcb7L, + 0x8e00b72c1eaffc70L,0x89b24285aa728102L,0xaa7ea7e0b679cafaL, + 0x5d2b8c264f0a6f6fL,0x7ed7b1730e804397L,0x5a93eb45c8573049L, + 0xc92bf5d40986e93eL,0x526b5a9c6a20c0afL,0x0adf47c9b99dc3afL, + 0x12b25fe2ba202cc9L }, + { 0x09b8d78a33eea395L,0xc7a93618f633fc5cL,0x7e821629270eceefL, + 0x524779b8c628ed0cL,0x91db5ca1a1d68939L,0x8626e18e586edc90L, + 0xfe023e8bfeb3f3bfL,0x6279fde10250171cL,0xe52ec7dc55e172deL, + 0x445e8695c6d4ca45L,0x42de3878bdbc10f1L,0x2b114de86fc3835eL, + 0x9faba4567e10b652L,0x4111d82a390e78feL,0x576b61c2aedf0acaL, + 0x216279a974accb74L } }, + /* 31 */ + { { 0xc14cdabf4047f747L,0x03ca233dc1315a1eL,0x59e7cbd340e5d0a7L, + 0x1fd0c4e9bb413869L,0x189d08b10f01fbd8L,0x50449c42a76b823dL, + 0x81c224a1398b00a1L,0x08084e4f8e8179e4L,0xfd8af994698e41e9L, + 0x1e30e37c5610bf2eL,0x4e6a043fa7d2790fL,0x9d96e60cb3195388L, + 0xe75f986d03799dfdL,0x3b4a8f11f8ff902fL,0xfa9453787588416eL, + 0x20683e3f9827535eL }, + { 0xcb582e26d0378878L,0x9e214c23a7945787L,0x13d000bf8f6688b3L, + 0x7548d4f540515270L,0x7113c15d40111f5dL,0x3bf5a526a8bff902L, + 0xbda6b0109b4945ccL,0x83dcc74ebc2f3a05L,0x2aef628443efdfa1L, + 0xd2e60ee9565c5bf4L,0x4f0fa10d592f243aL,0x6ae58b321bc3bf51L, + 0x813b086860576a74L,0x0bc023f84d73081aL,0x9fd03aa032dcee59L, + 0x5e416bf527d6c795L } }, + /* 32 */ + { { 0x24313760026cc23cL,0xf819aaeeb5b29058L,0xa92272f8c5d2ee17L, + 0x8048e7cbee5cc402L,0xdbc7d6ee77def07dL,0x61d69244f6af821eL, + 0x5f7966ed996cbb89L,0xf81b17ea96a155a4L,0xb2d9ef7003f3ed56L, + 0x5e6e5906e882a5b2L,0x86fa1072ae947180L,0x34d9fc51658c76f4L, + 0x9f603dc0cb035aa0L,0xb7b39feb75be6481L,0xca87554acf04a9efL, + 0x4ff682ec87b4fde3L }, + { 0x3125627fd0a10ad5L,0x7fd45c72968e6f45L,0x2981bd6b806a1163L, + 0xb92de1cdde5033e3L,0x3b44b45ebf4f8988L,0xca1b9896dae7e1dcL, + 0x52166e5a0778d878L,0x82d472bea5116847L,0xfbdd382af2895445L, + 0x22ed16025d6ec4c9L,0x3614eb1cb6552b02L,0x63c5df73a1e6210fL, + 0xe9160285021a74a7L,0xa44ca400c65cbd4dL,0x48cb187e0f15e299L, + 0x51eb818e3402507cL } }, + /* 33 */ + { { 0x1fc1d178b92100abL,0xdf2e3d609605b839L,0x12a7c255b71e59d0L, + 0x3f8b667514fcbe04L,0x0e8a393559fd06afL,0x5632650212020d07L, + 0x6696fcd1528e7be5L,0x6588514b0c7b7654L,0x0cd80f8c5912a5b5L, + 0x8bafef04f324cb7fL,0x6b53eecfc6da3d75L,0xedef48d831d1df2fL, + 0xf336b96573812b6dL,0xc82eae4aee626031L,0x300abd32d244f09bL, + 0x8b0af95531d9647fL }, + { 0xb770180a2e603544L,0x2b573ac3221acd9eL,0x3a17f66562407032L, + 0xad3e74adb89abc3dL,0x8a3d2e3ad793225aL,0x457bba04ef02564bL, + 0x8875652ffc2dd2b5L,0xd2905d15e67143e8L,0x6d884b4202e48d70L, + 0x06f99219c7636a57L,0xa8dc342135e378dfL,0x95c1d73d10c64a02L, + 0xcd6a4ececc157a66L,0xbadcc1c88e24a354L,0x8024f1b29839329dL, + 0x5363e5494da48ad0L } }, + /* 34 */ + { { 0x1f5523b7e23fc641L,0xfe54e72f86667063L,0x294a15f58e009d2fL, + 0xf203997f8c57f5e1L,0xa229724cb16d64dcL,0x697be4fd4baa2ffbL, + 0x3f507e460a6e8ed6L,0x0afe3a5d78508536L,0xeeef6cdd95408208L, + 0x701fd889f2c4237cL,0x496d883a5c385253L,0xe25c67ed72a212f1L, + 0x4b4167831ff78fcdL,0xe9967004c16f4146L,0xfa45c3a1c45b0697L, + 0x633340183fbd30c3L }, + { 0x39c9a0cca2fbbbceL,0x876f6e5caa0cb744L,0x9ce6010e3438ece3L, + 0x0aad148e13802d82L,0x9c3e5c609cd45a1bL,0x875cb8597bcfc1e0L, + 0xb19ff790d8584dd0L,0x2598b81ed81c2a2bL,0x118bdf2f02be07e3L, + 0x074fc8eeb9765ce9L,0x125e9d88b24f95aeL,0x3bb12cdc0c98f09dL, + 0x4a6aee07a0b74b27L,0x4723d2f9c08077ceL,0x959447d6bea8026fL, + 0x93a7075c16280b73L } }, + /* 35 */ + { { 0x26bbefe2715b27f9L,0xa935a5e22a280923L,0x5ddf23affd58a26aL, + 0x54c83e167c138694L,0x44799bc9892a2153L,0x4e6e47109b8d09f5L, + 0xc63af616d588ea68L,0x5e896706883ab1b6L,0x3c1393a03d209336L, + 0xd02f292192c23ddaL,0xab70cb7adcf6ea43L,0x12434ea8791559e1L, + 0x040680db6d70ff0bL,0x1a10fe522832ba45L,0xd69f9c08e5f0cb8fL, + 0x1a7422ac44b141fdL }, + { 0xc3a9dd2e9f40b675L,0x2a7c6603fcc71f39L,0x18939a611948e342L, + 0x8f3b6158ed0ab484L,0xa3aa7d97ee31ca6bL,0xbc1e865ef7a8db63L, + 0x315f8c092c7c62e4L,0xa260788f9f5c6d0fL,0xb18331294b6f3ec5L, + 0x73adbcd636b4d849L,0x66e14890bc699a9bL,0xbf3790d82a1175e7L, + 0x7f43605afc53ca4fL,0x577f6c4787ff6091L,0x827c7552600c82b6L, + 0x0944d6309d25599cL } }, + /* 36 */ + { { 0xcfdeb63ee6ab9620L,0xdff4fa6d786cd808L,0x145edd82456320b3L, + 0x2ae5f862c4943915L,0x9508e813b73b3f87L,0x3bd805f3e52f97a9L, + 0xf71b5c28c9829b62L,0xb394c70e86e0cefcL,0x534fb1a923bdb36eL, + 0xd64f5862dbe27e5aL,0xbae23df383ab6169L,0xdd6df1b127c828cbL, + 0x1901899f3a307a8aL,0x36cc8659811ddf66L,0xa3cb777479943b77L, + 0x7d89f3836fd86576L }, + { 0xf8564242c9f92b2bL,0x700c6a75c46e32bdL,0x93e768b77f99a5c5L, + 0xb6efe85803149568L,0xbbfe8a19c2ce6709L,0x721a3b1bee6ec493L, + 0x26eeeea9c371c28dL,0xd798115e15177e1dL,0xd7bf3bceb068a5a5L, + 0xdf8da22046d2b4b2L,0x3df0995b59be9dfcL,0xc96897bc77640b79L, + 0xce0cf4c25a2bd3c5L,0x16f45d6e89afe744L,0xb53f3acb3a8509bbL, + 0x449af81f63f2a6e6L } }, + /* 37 */ + { { 0xc2fcf132a16d9377L,0x9ab377b37e1a2f9eL,0x72e1a12e86d19ae5L, + 0xd2b12e66d013bbb1L,0x0972e055cb5f66baL,0xd11de1c0399eab50L, + 0xc1f314fdc65f5ec2L,0xfc3118418a9ff593L,0xdf73c1ece05246e6L, + 0xc28d13631625056dL,0x30a9dbd76fb25e19L,0x049ed244845cd2d7L, + 0xc779b83fd36e852dL,0x85a35fc7f68c8a83L,0x299bf1e1c95e8033L, + 0x0e8617c320891af5L }, + { 0x5372060267c81b5cL,0x2fa89dcde737873cL,0x2a7430b0a8144fd0L, + 0x3006c5a726208c83L,0x4e066660d8ea40f5L,0x9dd025f9896413a4L, + 0xbdf380cc46b9149fL,0x801566190a125cc2L,0x04d6a3b752793c37L, + 0xb60013746b7a62f2L,0xa9cfe268585d5978L,0xdcad0cb88395fe66L, + 0xbab468fc46b261f6L,0xca0ef5ef9d9d9218L,0xc507d4a85e452402L, + 0x6f4404f1326cf687L } }, + /* 38 */ + { { 0xa3e1920b4febd3ffL,0xca6234d8fdfd2bbaL,0xb7d1af2ae19a9829L, + 0x23de1610c6f5bc20L,0xe204dbf3daa39ca9L,0x2a2de9b86d8c70abL, + 0x272e0c377c9d370bL,0x80914c06e565510eL,0xb611e7a857cbb6b0L, + 0x076fc6efd8266a6eL,0xdfac34ee3095801cL,0x69ff40a2b9e24063L, + 0xa7ba31a9787aa5c5L,0x0e4d1fdf33c70cd2L,0x903e31326895f074L, + 0x905771f87fb671e2L }, + { 0x5199ba0da4062beeL,0x18e7238c94d7d9f9L,0xf53f29bc1e0922c0L, + 0xde9b2a81b12d855fL,0x649f3eed6d68ca29L,0x64adfc34c50c097fL, + 0x81964ab99db398a0L,0x00d59c477a587224L,0x09fea39674c5903aL, + 0x6aafd8ee15043dd0L,0xc5721a6e5f1ecc20L,0xb6d6a4830db9b7b4L, + 0x06ffc61766c8d52aL,0x3de241d6acc82a27L,0x0605f05227f2f7a8L, + 0x6a22953b6404deccL } }, + /* 39 */ + { { 0x92452d8f74fce389L,0x059634c02afa5564L,0x9377ccbbf0ed7825L, + 0x89f4045b37718e0dL,0x11074e7d9fa69a4dL,0x5d70bb077295b0baL, + 0xb22d54adf107ede6L,0x5c39a3d8a1a29c7bL,0x37236c02d795e3abL, + 0xf7282d002b589951L,0x5e2265be5790bee2L,0x91e0ea11a8e65ea2L, + 0x0e71a7086001cebdL,0x16900f5a2c1c5402L,0xc3b2d5c0357f6981L, + 0x528c9ea0619e3427L }, + { 0x1edc86b45f26c577L,0xf80747089438bd45L,0x2dfe1013792582a7L, + 0xe08eaca0de1e569fL,0x5f952efa9a55a356L,0xa4d80b53e4976216L, + 0xd2b65855cd5d71f2L,0x246704bf66cea3f0L,0x193f641f492323caL, + 0xa681855c9adb1325L,0x86d522ce2d19d652L,0x53609f105b82ed7bL, + 0x3b0f00948e150d29L,0x23ad8bfb0b13e891L,0xcbb1556cf794b449L, + 0x200f9093738bcf57L } }, + /* 40 */ + { { 0xf9b22fc58388387fL,0xcf26f17028e883c5L,0x447cab90d1b7973cL, + 0x8d5d4ea2f6ec9171L,0x2e16f498c30cdbc0L,0xdc92910c48623c2bL, + 0xeb1491b030dbc545L,0x631deb2e14de21b0L,0x04a210662fe830f4L, + 0xa4c6979c379c1f3fL,0x8a732b68fb06a795L,0x3a44327a1619dfa9L, + 0x91a307d38dbe2c9bL,0x939bc8d203989feaL,0x3daabaf20f4a331fL, + 0x5c307e98dd0f55dcL }, + { 0xbbc4e0c435b233daL,0xe3d2908522f6f985L,0x99dd2d21a8b02468L, + 0x978f40e9a96916e7L,0x0327d86c614bccedL,0x95e95502b290762cL, + 0x0ffd2197a879f2edL,0xc436513750e0bd33L,0x26c3148a0827c4c4L, + 0xc79812a83fcfc0b2L,0xc3d8d17e31928589L,0x8b572cfe8830f42dL, + 0x7cd9ff924b07f83fL,0x331ca9500a51148fL,0xd0c539684c59f9acL, + 0x1df16dfac1434785L } }, + /* 41 */ + { { 0xcc7bb4ac68bcacc3L,0x06ded34f430f58cfL,0xc59f9f4fd461855aL, + 0xf549199445c9f0bcL,0xdc5f7ec64375c892L,0x1b8708f13c85983aL, + 0xb32a5cc482fcd087L,0xefdcdc352d6b4c0fL,0x4bb24f048ac6fb2dL, + 0x5982d4f533906471L,0x162eb52fb83a3ac4L,0x7130df282337a223L, + 0xdce7b802cbc3dbd3L,0x8b3959592467ac0eL,0x21d3d2e81b56717eL, + 0x729a7f5046512617L }, + { 0x874ed1aa8420f90aL,0x6368e19e0fe4c855L,0xb62d4aaab0be74afL, + 0x76fcc4808ca60ca9L,0xf310b5a57645a867L,0x131bac9bddb1b24cL, + 0xef77d71d2dea5b44L,0x4706d21072fcc64eL,0x29b92691673d77f0L, + 0x22e00bf3e89e0663L,0x472d0cd374077d40L,0x3e21040d829232e2L, + 0x2f916dfb38dc8533L,0x48bbb59b14b8f667L,0x19de9f4ad44be19dL, + 0x7f6d3649232d9d5cL } }, + /* 42 */ + { { 0x3bd064de6e794819L,0x5a6b694ef82ebda1L,0x1f017fe0b91e2804L, + 0x190d31f307a43cd2L,0x6c26f226630433e9L,0xba488aa70abfdcb4L, + 0x418d9085a46411c0L,0x1b934fe6bffb5880L,0x75d1e237e200f849L, + 0xdf04d63fa55413dbL,0xe216ed75e23b3f77L,0xa05866cb0f91bd30L, + 0x84c395d97729c509L,0xec97e188452ab2d7L,0x8cb7c1f90093d686L, + 0x2d032395628f086cL }, + { 0xa81c94074a44b4c5L,0xb9846879cc702c98L,0xcb502287ceb0dc97L, + 0x303011266e3aa321L,0xc0ac8763e4c256c2L,0x65034d20e55b4845L, + 0xaa96a040f240f35bL,0x046d26d37cf7eedcL,0x62a5a8e13b810656L, + 0x86044b9783d70c2bL,0x2fbaff8859e4da8fL,0x929d901a5457f5d1L, + 0xd29e1eb2b531b757L,0x214dabdc9e4e9739L,0x5bd724fc4eaa9bd9L, + 0x734c12b31ef9bb9bL } }, + /* 43 */ + { { 0x98fe3c2e92f9b086L,0x4641b93eb3fd4544L,0x47ce208b5c02c65cL, + 0x8a52dca1c4f03242L,0xb5ec17d9679d29f6L,0x11d2fed09406f5f4L, + 0x260f63dc0d9ba811L,0xde2b056f15472a3fL,0x1b170d9f007290e6L, + 0xa2e23e8db6b5c8f9L,0x345a2839cf34c3eeL,0x9bdc54611b973ee2L, + 0x65bda6c2bb24d1c5L,0x97d52ba33c6141a1L,0x47bb16129d2eb201L, + 0x7c558a8721fbe49fL }, + { 0xb9485a523f350fecL,0x016678c56a38d4c0L,0x8ef346a20d5aa64dL, + 0xb85daa02d96da2e4L,0x845ec4ea4f647b3cL,0xc0d1a6ca0d5e946cL, + 0x41d8d1c14fa9f4abL,0x43972cc59c8b1303L,0x67e1f48d434ffbfbL, + 0x350ce93a819d2318L,0x49f530906ddef23fL,0x3c2e6cf9200cf12cL, + 0x42691cc1640432fcL,0xbfff74b472496b52L,0x44527c9f020a97beL, + 0x34cd7dca7b3c4348L } }, + /* 44 */ + { { 0xf031761a59e7fe87L,0xb1eae31a0047cd72L,0x27902e68fae30f62L, + 0xa666f48db71db143L,0x75ee66780e0038f4L,0x3b45ac6702bdd76dL, + 0x0d2fb828a0d6cd5cL,0x27ce7f1d9d8c5b11L,0x141fe0e4120b5e96L, + 0x95a1b984b9267c37L,0x5206e589d60312cdL,0x1867342eda549356L, + 0x374520b9070c74acL,0x2703cbb59557b0b3L,0xf621f59ca6ed8c14L, + 0x7ceb1cc2abf7b887L }, + { 0x0647a5bbdb7fd65bL,0xd8d45cc036c9457cL,0xc6da99db9e12718aL, + 0xed1dbbf4e93a7fb1L,0x4512c95cbd1566a1L,0x4861ba00dbc0c919L, + 0x3c6cc2989e7f5269L,0x671961500941aaaeL,0xbfcf5d0fc8c538e3L, + 0xad6e9929a25a551fL,0x9071098517ca0f26L,0x743b78eafa89ef7eL, + 0x39d5ea3171ab4549L,0x7442f3f3e6d1c36dL,0x25a683e0059d568dL, + 0x1f629a99227ced5cL } }, + /* 45 */ + { { 0x8925ddace45a1c3eL,0x72d2936541f7545fL,0x45622fcb37e7f828L, + 0x882345133e4c79d2L,0x5dffaf849c2645d6L,0x3078f4dd994802b9L, + 0x566927f09d339fa0L,0x9a500a1e9fd91dccL,0xce0081800ab0abd7L, + 0xd97135a38194e5dfL,0x9e87630798adf088L,0x3baf01b89a45a2a7L, + 0x6fed6154788b4399L,0x980e5722e77a997dL,0xaac90ffa2a378eedL, + 0x4a75fda28bd805a2L }, + { 0xd09a8fbb55e74cbcL,0x737738cefab18f25L,0x0fc23ad69764ec3aL, + 0xc5a7d35be7e0ad31L,0xe75e068ee481cc9bL,0xf0c2ea993d4aec34L, + 0xf1324fe80d4a63c4L,0x5dbb7c1699b0592cL,0x442d674da7e0f46bL, + 0x5a5d66c7a300faeaL,0xe83dc8213333ac83L,0x70ef812e8c408496L, + 0x96e1dcb699ef5fc1L,0x6e2b771b1734e862L,0x04629cdc583507d8L, + 0x5819f9ae23d8179aL } }, + /* 46 */ + { { 0xd99691216aa78811L,0xf64ee8f42103e7c3L,0xddf0107022b9e698L, + 0xe6001f9e4f582cdeL,0x24a608af2ecfac1aL,0x6ef4c78406393009L, + 0x5262eae6ebf72911L,0xddbd0af58c4ee5a0L,0x875aff90ecd87bc7L, + 0x2fddb34c6f24f114L,0x48104281e865f172L,0x95692426886c1b9aL, + 0x6f5f32089ef4231fL,0xaf587acfd0a7e82eL,0xd65719179ac395c8L, + 0x7459603c1364a750L }, + { 0x1c2475bff41ae519L,0x34401fb14af8f251L,0x70ddfcd2aefb2c3dL, + 0x9b2d385b51cdaf08L,0x8531c2568208bb19L,0x16c89df64c33f3f6L, + 0xc23cfa9924571769L,0x2339b51e86d010baL,0x08db0e8d22638313L, + 0xf769e17900fedeb7L,0x3fd96dcba3687ef1L,0xcd046b2391476475L, + 0xf3ff20640c45c8ddL,0xefd167bdb8343d78L,0x493ccb6d4b77ee90L, + 0x33025513b3cf7b45L } }, + /* 47 */ + { { 0x36f0046935eaaca1L,0x0c384b7589119102L,0xcb375665e6d2954cL, + 0xcb9199b9b1e9d6d7L,0x75852349c29c2757L,0x89cbd1bab8e738d0L, + 0x9b8dbe905923a427L,0xa237793e18fe1889L,0xa4271757a742e083L, + 0x8c4979d24eebd613L,0x40325054d4f2cf77L,0xa3b8a091958705deL, + 0x1b191bd933d999baL,0xbafefba43b0fee1eL,0xb3bad1843facdf14L, + 0x9328adb04387561cL }, + { 0xabe84e80f906b872L,0x705523a078262665L,0xd89c6a7e3398ccf7L, + 0x2fab551df55b5323L,0xa0578eca0554dea8L,0xef26523d375589cdL, + 0xd8fd6242864ad750L,0x93f27fc5178fe1feL,0x7b3e6f309df87422L, + 0x2862e49e3750d054L,0x7d90c6b25dc038a1L,0xc1a1ae2284db682bL, + 0x47f3dab79881930aL,0x30e6bd52baf3e0a4L,0x0680025bf62d25c5L, + 0x0aa1f3cfadd0d5e7L } }, + /* 48 */ + { { 0xa982219022a10453L,0xdd1eb91c2a03a10bL,0xafbb5d9596646f3bL, + 0xa58de344f38b6fc6L,0xce47c3e5b8cfca1dL,0xfcd8e16d0f70da04L, + 0xac44349bda262ed6L,0x9320d87bc56e2f8eL,0x9ce3ea0819138e58L, + 0xa5862dffa2b236c0L,0x6b0f9a5c8e7efb0dL,0x4b53432b16ac78ebL, + 0x6ff43105709b51afL,0x08e236f88f519628L,0x1f93f176eed403adL, + 0x559337e09636545eL }, + { 0x30ddf738d8fd807aL,0xf4e0ec9dab131222L,0x14a2f4db625afbc3L, + 0xd5b706049f12f895L,0xb46f3c23ac3044fdL,0x1b232d1ff540148fL, + 0x61b458f539b4e554L,0xf694b24a0dd70b75L,0x0fc64299289581d9L, + 0xc05d49beee5fe22dL,0x7af3447f6a18bf63L,0xe96a1dc27f1929d6L, + 0x6afe6028c1551e8cL,0x27dacaf32b5d4fa2L,0x4a1631bc545c2cb4L, + 0x930070f9b0c914d3L } }, + /* 49 */ + { { 0xd2f32c5e69a9bc05L,0x0a5c19c6589c4b73L,0x095c9e5e94665f9cL, + 0x8ab0f293bcfb4c39L,0xb90708771ddb7c31L,0x894e965866b38048L, + 0xf19a90cf606bd9bdL,0xcc1d58dfb6fd2d69L,0x886dcc4e461d8a69L, + 0xc455c277f9ce4831L,0x749a5996765f8a82L,0x2ffc668cc3badc8dL, + 0x380183969112cdabL,0xa98795c3b243c7cbL,0x8775f310010a2224L, + 0x043a2141587b5e14L }, + { 0x7bbe9dbc3a873752L,0xee1493f42f442feeL,0x981ca2c8c18c2181L, + 0x00ce3090e29769e7L,0xb4626ac8de768c5fL,0x33e9ce4634d7677eL, + 0xf89c2cade0fa94e6L,0x04f5cc1141f5b5bfL,0x2565f7362228c12cL, + 0xf1bf706a0c05cce5L,0x5d07ffffbe487c4fL,0x3ec43c09a499f1a4L, + 0x4f4e79bb98d94800L,0x8a335a16073f12f8L,0x4bb5eaf70f970d6dL, + 0x18d0747bf24d0ae8L } }, + /* 50 */ + { { 0x58d3c77c84601fafL,0xc9465be2af1c1f72L,0xff626798d116d806L, + 0x3996c0c6d5b0d93cL,0x2fa1ad755ec6723aL,0x966a814403ba5349L, + 0xdc4c94222ac34d8aL,0xddf471deed675865L,0xd8aca597953d528fL, + 0xb2e463b524ebf67dL,0x258248717e25b4d3L,0x23c5adba43159daaL, + 0x5458f9c683357540L,0xcf685da7f938b1a6L,0x981a4fdacefed231L, + 0x711093ed08bb5e59L }, + { 0x12aa3fc6401f161aL,0xf7358560974c5e87L,0x4aa252fb17b5df82L, + 0xb0b82b07a48e6299L,0x0023415729dd847dL,0xf1e54d004529c5a6L, + 0xcc1c539e6d98f538L,0x36162b5328d3abcbL,0x75a379382a84f0cdL, + 0xf717a81b4dee7484L,0x16cf35fb4c23bf1bL,0x7fd1c29f787e8b3eL, + 0xb7da7e6859b79ab0L,0x072100a085f6c60bL,0x31840159e7ed48b5L, + 0x17898bda4d9c97d4L } }, + /* 51 */ + { { 0xcd8483d8ae1b8cf8L,0x323d4b42e9a28856L,0x7633584f204a4bc2L, + 0x4e0b2228ca7a69faL,0x8afbda8bf757bab2L,0x85b240886cc5f9caL, + 0x47fb4813d41a95c3L,0x3f1bc53cc2aabe6bL,0xf22cda3f1ad1599dL, + 0x1b2ec081c31ea9b1L,0x048f304b01614ac1L,0xce31cee9c6afa7abL, + 0x55af76334140dc3dL,0x84b7ab37dce8abbaL,0x50de7648c7cf3efeL, + 0x73a88dcf15356ab2L }, + { 0x3f86828806e83b39L,0x477a44139f44037dL,0xf9058b0f17dbc841L, + 0x2db64f4f54d17549L,0xa23cea6af2307ffeL,0x393efd554f126261L, + 0x2f4e658a10f37f26L,0xa4437ce3f4ee1e35L,0x64ef42a7a93cde8bL, + 0x1debc9f4939aa901L,0x44223d6a3d7b5cd4L,0x789a6a11f88a3accL, + 0x56fb9df82c608a2dL,0xe79db8e3bbf56c06L,0x73c56af2668fa300L, + 0x52f32b17ae396a1eL } }, + /* 52 */ + { { 0x56f524c1e714f71aL,0xc1be12629add8519L,0xad9189d865cadbe3L, + 0xd88bf5c85a0fb649L,0x9efa6a9221d192d9L,0xe3fe83896f724b6fL, + 0xec3fae24b250119cL,0x4b6af9f62ae0d3c0L,0x8fceba0bd619624dL, + 0x7dc3092b2fdb6e3aL,0xc91da3763263cd29L,0x30c0761ef95c43bdL, + 0x89136400cdeb44d9L,0xfd7dce8443c0d31dL,0x78fec3b19871899fL, + 0x79e14d28efdf58c1L }, + { 0xe38222359bb40c55L,0x0a27202d0ed07a42L,0x48e6c1a94838c1f4L, + 0x2b5f24a7d864a78eL,0x7e7f140a0c6c55c9L,0xe62c104ace12d508L, + 0x9b0a1a7ec11b1e10L,0xfd8a275fafbb3dd5L,0xdff354fe9a3b6b30L, + 0x5a105d9e46602a01L,0x3d371b4d93bb65f7L,0xda5cbf0b0f82fdebL, + 0x4601229bde468545L,0x505e10b9c73d517eL,0x77cfa541672ff492L, + 0x0d8ec28a99566ce2L } }, + /* 53 */ + { { 0x014cf73ecbeee995L,0xb2eb88bcd491e80cL,0x615a6cadd9aba5d4L, + 0x2f7d46339304c84dL,0xba0501d28ab03c9aL,0xc8f723de91babb94L, + 0xc885f97750405772L,0xb5e1d2b3c7fcb094L,0x61ee7995df96c71aL, + 0xb8c8daab3464499eL,0xdb425ddd5f607932L,0x70251ca1b1243587L, + 0x26d7d3be9fc74340L,0x8c179310c902ac89L,0x72522c154559a74fL, + 0x86001e27c3734afcL }, + { 0x13b00ba5e7693947L,0x6478641e012c062bL,0xe1a438e0e85490a8L, + 0x5173dbbfd9574d5eL,0x9532eb8c9bd3ba61L,0x1f41bcb85f3ea075L, + 0xac1cc2478cbb92b9L,0x0f34648e1ef901b4L,0xdd929d1ed2b3b2eeL, + 0x470f1eabc3d75bfcL,0x5cdbc6f7139cf4d2L,0xcd86454df0424953L, + 0x1e07981247fcb383L,0xb9f209b417df930cL,0x4225fc31114ebc00L, + 0x020591cb347946c1L } }, + /* 54 */ + { { 0xe3003721275e0af4L,0x721141efe78a4a4bL,0x666cfcf6d1757485L, + 0x5fa1d737168e659eL,0x263e3e540e2842eeL,0xadecc3d4948bd5f6L, + 0x019de03d246b104aL,0xf8a9e903f343d818L,0xcb57ba4a5b0c0d31L, + 0x8246c50651e2765fL,0x80c5751f6519bf67L,0x5f05c200f2119a01L, + 0x7e6487b87821d4f4L,0x262f94aa261c3a06L,0x56cfe48972146052L, + 0x5119985fa1df05efL }, + { 0x5819497db18586c0L,0x004415d6c6eeaa62L,0x7c6a46b697cda28bL, + 0x9a149b287c194594L,0xb56369fa4ed3a506L,0x7092aa6643c94cb4L, + 0x55bce73aa9e9eee2L,0x34bb287077893509L,0x8af95fb006eb5326L, + 0x87cd03239638f485L,0x293762685ba75bf8L,0xf32d6f3d9d42d581L, + 0xa4cad57465c6d64dL,0x985f50fbb2cded41L,0xcf34ce0e9006a067L, + 0x59eaf26558a57f9aL } }, + /* 55 */ + { { 0x7b407efb6ec3876fL,0x780c6123f0f48648L,0x2abb56ffbf893039L, + 0x9592eaa045a91ab0L,0xce5b84d778811b82L,0x86a71a341f9f3fc9L, + 0xc17fdd86f0e7e13bL,0x88ed8297655a0880L,0x75d6dc7481d5e666L, + 0xeffc9df61d171797L,0x36ad4c8de3f79e1fL,0xdb15317d2046192eL, + 0x78c9fa7a274fda62L,0x04ec924f82dd9914L,0x059d1e383a64971cL, + 0x3b4450ea2620bbfbL }, + { 0x3db7a955c776dcdbL,0x35c4a57c81c8ba47L,0xae285003505760fbL, + 0xe3e80691b3aec353L,0x380335be47117be5L,0xe1c47e3a056ccf61L, + 0x253cfdeb33977916L,0x3decdfbaf5cb7ee1L,0xf3c9794f7cf4b704L, + 0x2401680c9ff81462L,0x4e440e11be3daa9fL,0xc5d0437769f91d8aL, + 0x4106c7a8cb5e9c5dL,0x191909a133b7d24dL,0xe893c8383764b4a2L, + 0x4a7fe30cc429b614L } }, + /* 56 */ + { { 0xe78f3a702455c7c5L,0x5b7636e870157754L,0xf32c45247623262cL, + 0x2c98b11e1bc780c7L,0xd48eaeac915ed877L,0xbb04d3c0199265f4L, + 0x6b52b19bcfa5200fL,0xc46a098193ea3fe8L,0xd82c733dba758059L, + 0xd324bbd61896aaccL,0xac09a2fcce8ecd51L,0x529918fd02fc44b3L, + 0xf0c45e4aaaa1784bL,0x35626340fe22085cL,0x53cbb676c50c7d61L, + 0x83fa1ea365126b23L }, + { 0x60ac86da10ccc646L,0x2ce0637f7b0451e9L,0xbbbcf6308a088610L, + 0x23c1901920349982L,0x707fc39cfc0bcda0L,0x7f4d1f151bd4fd7dL, + 0xd6a64e7444713bbbL,0x57bdc676c5ac9e60L,0x456c530337b61169L, + 0xd3451396dcf40a1dL,0xf3edec254997d2c7L,0x534ae9a4c2c4a739L, + 0x1401397e6a6ad2e2L,0x20769d4d23e95f81L,0xcee007c6de98fabfL, + 0x61409779931c51e0L } }, + /* 57 */ + { { 0x3ddb32db15156623L,0x68137fbcab7a67c2L,0x26011f506f19e3c2L, + 0x34218b0289924c61L,0x492a0b0fc6804c1cL,0xd65be706afaae6a7L, + 0x3b13d23e0d01be61L,0x44545b47f87f4c69L,0xd42236e204dc1aa3L, + 0x6135261d3c5161ecL,0x1eb46a63bd88bc07L,0x78c6d8361599d720L, + 0xf6955fe169baf0f3L,0x467eebd617072820L,0x2f1b8a2a3e3a340aL, + 0x636dac762d0b5f88L }, + { 0x94280db9b4c80af3L,0x9a189cd14e3892abL,0x26e702e0d1477ddcL, + 0xe91aee3868f9f14fL,0x2864f63a80baa0b2L,0xacd81f738b714a29L, + 0x30e1b870c5fe7cb6L,0x883ea1c3b10837fdL,0x2da279536b20489fL, + 0x3aeb2a6858a2da5fL,0xe2330bf203a8fa14L,0xb5c488b5dc70b1c4L, + 0x0a78c4d9299678f4L,0x233bd09825df675cL,0x37b5c0767b67d368L, + 0x2f6dbdfe4d0bef3fL } }, + /* 58 */ + { { 0x2f8472fd2e4da7c7L,0x708cfc91ae677932L,0x364af08a3dc268e2L, + 0x0f10dfe0799a2424L,0xef912d5871d58bffL,0x6bf35dfc988962e6L, + 0x28b96fa95f47ea0aL,0x734a79eaaad308c1L,0x957303379f437bbaL, + 0x002cbd8e6cf54f75L,0x47606dcfe7632eecL,0x404b5ecb53193104L, + 0x0ae0897c0acf729dL,0x89628b863bddf1deL,0xeced154ef87d7448L, + 0x5cb6e197458d5d4eL }, + { 0x98cef197008c75edL,0x7cf49d3ef6eeaaf8L,0x1d6f9e021875e96dL, + 0xfcec2cfedd9b0d8aL,0x38a61cfeb9576daaL,0x10003f3936a7dbb8L, + 0xb37c386823b814f4L,0x9fb66dcbb80e3153L,0x9e7e2eba059847a8L, + 0xa4ec63fd35a72770L,0x311f3d91fc9e0ed0L,0x3c1dc094d515baa4L, + 0x75a06ebca08cd4e3L,0xab6172382ed5eeaaL,0x2e82bbb0e1f52c1fL, + 0x2149d6305175d6e5L } }, + /* 59 */ + { { 0xee1a8e6f5f9311f6L,0xc97e3c9fbabc1f85L,0x4fa7c52eb494209aL, + 0x04c2f51c19774fe1L,0x5cefd1228555844fL,0xb53862a3b5873ab3L, + 0x768efdd6cbed19fcL,0xcdc12479ee58469aL,0x11237e313d80c09cL, + 0xdd74a290c044c28cL,0x9ee6517abd47e287L,0xc2421228ad0ffeefL, + 0x4273088f818d281fL,0xebc744bc43ec0de1L,0x5b26eccfb415bd73L, + 0x14e2f350cb07c26cL }, + { 0x548d2a104216946bL,0x6e801f077a4bd92dL,0x5996d0a343695160L, + 0x0f1b5c2f63a197c9L,0x79da3c4f061f77c9L,0x1c1cd63493ff7b22L, + 0x5e61b650a234123fL,0x826b34c5f284033cL,0x718b90e8c2f34214L, + 0xa5f35620ae806ec5L,0xa2fae345e324a9b4L,0x8c0bb95e8b53cb51L, + 0xc94f6ac2f9965778L,0x07ec607d6b9def32L,0x63bf1dbad0ed8f27L, + 0x58537e02dcb61e4fL } }, + /* 60 */ + { { 0x1f64b06464f80ba2L,0xe8e055e70559a45bL,0xc3262b34f1f4b634L, + 0xef4f7d5fde8c8482L,0x9d55dea0c30c780aL,0x1740afb9cfa1e693L, + 0x2cfe6a667460c34bL,0xf66959411187c1eeL,0x1382f2775f974d94L, + 0x1ca0ace4004549ebL,0xf8244b3fbabded02L,0xc36f4d064e3653eaL, + 0xeab9f0dcc55c5f83L,0xd93b9cefacebce90L,0x16658e7219061425L, + 0x4857835f82d7970dL }, + { 0xdcd525bcd2576210L,0x9f378aa7d51b5443L,0xfe97bf171bd83994L, + 0x930d0f63f38ac621L,0xaf8f2c17818408ccL,0x2692c87e260f53f6L, + 0x0ee45407db0a75e4L,0x0ec47ae5ffdb1b37L,0x769129dc7aa6a44bL, + 0xb6f932b22e40b75dL,0xe06764d095ef3b77L,0x28fd47f568bc63e8L, + 0xd18104949c0014c0L,0x90e2d3fdd7995d8eL,0xeb39a05d6c2a85afL, + 0x6c0277bda21f3128L } }, + /* 61 */ + { { 0xe41b7086b509e7efL,0x8842ec7b3d7f9f91L,0xcd285f945526b88bL, + 0x6e44e064051dd0abL,0x90198c10774f1cebL,0x6ecabe98123e661bL, + 0x4481113632f647d9L,0x1dd82b4526c52aeeL,0xd650907f939dc9d5L, + 0xbd5eeef2fcd455bfL,0x7815a4dd8d2e5d7cL,0x5ad4ec9288bc9f2aL, + 0xc6f10d0b57a3b322L,0xe8d0c1e720b9cbdbL,0x5a0b071a9b774ee8L, + 0x3067bc9af22fcf8fL }, + { 0xe0e589f2b7ca9326L,0x17a106fdb1224f63L,0xb2354521747a57bdL, + 0x2614982d62b0882eL,0x7f3af5444391ffcfL,0x1aaa337ba84e440dL, + 0x28ea37b0941bb071L,0xa957dcb42e4a7f54L,0xe7ab662c1a6ad5fbL, + 0xd135e381f7c36a20L,0x42e7980c9baa0b6bL,0x4237030c94e4671fL, + 0x24cc63ff8b0922e3L,0xd10d5279445a589fL,0xbb99d316a870ff6cL, + 0x390c83caa996c195L } }, + /* 62 */ + { { 0x50d3fa82ffc4a73fL,0x2665d6353bd53303L,0x80a06f8a264bb77dL, + 0x81c04a6e22d73d84L,0x2409cff50323b8aaL,0x31dce2178c4c4d5aL, + 0x374aa80e0c0f9c19L,0x0b25a38700186bb8L,0xd0b77a10aaf1487fL, + 0x15f39ad5ab498de1L,0x92e32da61aa0c116L,0x228e3dbd96e25ce8L, + 0xb57c88dc5e8646d1L,0x672b1164267b1c68L,0x5d0d807f600bdec5L, + 0x3ea4007d223e573aL }, + { 0xd76debd0a595d0a3L,0xa6bd76cbaff0b3b4L,0xbf2c154f9b1bdb97L, + 0x62b19ab44c714c71L,0xc9bf33b9221af663L,0x23d87c498c941ef6L, + 0x255804c3d79f0f6dL,0x6f1a10052a7acbc1L,0x5dab79d9550528afL, + 0xfd77a6f0c8d16213L,0x40508b6dde5e1029L,0xd95ac0f2f95da12bL, + 0x8860af71758a8ba1L,0x0b194c837160c8fbL,0xa40e6c80ce004d34L, + 0x09f82a176b14aaa0L } }, + /* 63 */ + { { 0x60abe588c21366dcL,0x729c0a4faf75daf9L,0x70501fd9acb93ed4L, + 0xb97e744e87a16d70L,0xa42e0a7a98e7361bL,0x1acdaff228b54cf3L, + 0xf087ccbbb7bd9078L,0xda6f3983663250e7L,0x66d693eebaf07c09L, + 0x79baf4c38cbaf157L,0x5a984e07dfca99d0L,0xab4d3247f26d8dabL, + 0x4d0be7017eba36f9L,0x37bb9e650e8dd216L,0x72aa4e24531c4f03L, + 0x77d1e984b753d85aL }, + { 0xd9373239d8e62367L,0x3361848bb9820cf1L,0x00c7e3445a9c97c4L, + 0x9a0ec9ae14f960fcL,0xcf41f0cf740474b5L,0xa5eede8fece065d5L, + 0xb1de5a4e9e808610L,0x17c44ae4ae0cf75dL,0x2fa563236b148d0bL, + 0x64fa740fd29ff2dcL,0xc605eb8a88cb212eL,0xf2c771ad6a863016L, + 0x6d6112e7607b4c17L,0xfe90ec0740d49785L,0x599be18be256e0e5L, + 0x4e6eabecca54adb0L } }, + /* 64 */ + { { 0x950323d3fb99cfe6L,0x7b09bc26c9334178L,0x64111e417cbdfb6fL, + 0x9114174489a75760L,0x4c633df910919cb0L,0x715fc7c7396bfd2fL, + 0x8ca195128cab62dbL,0x306724734db81aacL,0xe67a246bb4c4c54aL, + 0xd77ea0fabf229646L,0x5bed15f1fa5b5d70L,0xa5686da5c2f192f3L, + 0xdecac72a7f6690adL,0x0c4af2a2caa50b7dL,0xf44631c16049ad2fL, + 0x325d279604ecf056L }, + { 0xee11fb554848c144L,0x4e062925b6a7af32L,0x125b68e1369e0f9aL, + 0xad9bdae6ca53b21eL,0xf50d605c2e98ea1bL,0xbdb9e1539f2fa395L, + 0x4570e32de91532f5L,0x810698ae46a250d7L,0x7fd9546cad9d9145L, + 0xabf6772111e97a5eL,0xca29f7d5249f82e9L,0xa9c539a99851df63L, + 0xfd84d54b71d0e3e5L,0xd1e0459c041d2b56L,0xceb3eb6efd80096aL, + 0x19d48546e32a79d3L } }, + /* 65 */ + { { 0xfe19ee8fb540f5e5L,0x86d2a52f04e68d17L,0xd2320db0adbdc871L, + 0xa83ad5a8d03a7fc8L,0x54bf83c708bcb916L,0x092133ea2e51e840L, + 0xbce38424cb52dddfL,0xd5c7be4031063583L,0xc1ebb9df458e3176L, + 0xafb19639bc4dabbfL,0x36350fe4c05725a8L,0xac4a063484e1cd24L, + 0xadf73154c145b8deL,0x0aa6dd9eb3483237L,0xa3345c3dcbff2720L, + 0x1b3ace6cb4e453b0L }, + { 0x0343e5e990a8bdc5L,0xa203bf9d6306a089L,0x98489a358e48520eL, + 0xbd17debede7d1d06L,0x8fafa6d75f795d3fL,0xa4ceb630387b0a3fL, + 0xe0166b32ffddeafaL,0xa2fe20547e764e02L,0x55ab9824e871f304L, + 0xa2bd36bb952ec45eL,0x7b4c1484a90d20caL,0x5319f38775bcfb53L, + 0x34238a4a6982c4e5L,0xa2bb61c7a102921dL,0x1e061b64db3ab17eL, + 0x538ec33e192f0a14L } }, + /* 66 */ + { { 0x193496fea19b56cfL,0x663d77f47bb99acdL,0x8f04afa857d0a881L, + 0xcced3da2082835fdL,0x7e21faed5d82cec7L,0x6e175b99f8009c85L, + 0xd9c6e31b2d05a307L,0x96948d4a81487d82L,0x86ebd3f2d46f6655L, + 0x86851aa8773ccc49L,0x3e220f228b1640a6L,0x9f06e3a841a20b75L, + 0x2cfffe5e90ac0a6fL,0xf5a9b1da8ebeb3fbL,0x2587d9976e08e2c9L, + 0x6fd6029803e9f401L }, + { 0x54709f8d8eb7516aL,0x83058a74bdc598abL,0xd234dd9887e801ceL, + 0xfd0f9d90d17b8a96L,0xaa1e549f6e90f6abL,0x2496ff805a7ed55bL, + 0x0d9f657a6c254c19L,0x3cdea49cb8962575L,0xb685a3f02dff27deL, + 0x3c50e7fddb8bc04bL,0x904ff0ff987236b0L,0x494298fdbb0d5055L, + 0x34b3386de14be8d0L,0x7ad34e9c7c3d30d6L,0x1f2b32bde159fdd9L, + 0x84cfa23cc761e5c0L } }, + /* 67 */ + { { 0x13bc11eb8b99b964L,0x8e280c0a58e2fc47L,0x870fbc49d4c9a54bL, + 0x37a334a2bf6e20faL,0xee583d0dd7c88cfaL,0x05e029a8ef4af1daL, + 0x6d55e2340c2ef8a6L,0x61b6fdfe209e9b62L,0x3b1dad26bb8e080fL, + 0x5adbc1629392fc1aL,0x02ac0fe60aae3f4eL,0x8d99801ac2bf4d5bL, + 0x2333f93fc282fed2L,0x16dcb10cb52db33fL,0x09f90f84c55752e7L, + 0x287d4c51c84a0d8eL }, + { 0x5fa582010e9867daL,0x614589b31a874cdaL,0x005e27c5fbdee22eL, + 0xe357fef5e612bda8L,0x4e0dbedf2d3635f9L,0x62be70e46f125a86L, + 0xa09b98840d94a2e5L,0x7eb99a1528b5e5d1L,0x21b9416e751028b5L, + 0x1b137fd7e06d2cc4L,0x6fa1f517fea09845L,0x3ba1e966ffcecbd7L, + 0xd4c89a4a832f453eL,0x07b1e2afeca68fa1L,0xd0fb44534bd395a3L, + 0x0132a3dcd8ef9e13L } }, + /* 68 */ + { { 0xe53c7785576374c2L,0xe60526d184727040L,0x8a066dc8228ca044L, + 0x1fe1c1b2f1ce1313L,0x2aeec832cdeb0c5dL,0xa75966999cbf826fL, + 0xcd188e81de77a589L,0xe5ce0fe0118d1254L,0xa142a9840790b86aL, + 0xe28f043f39ac28ceL,0x4eef829087de5804L,0x83c31b32f639a8c5L, + 0xd70454a75887794fL,0xca635d5018b1b391L,0xcefea07631d9c795L, + 0x13cbee76b6f8aa25L }, + { 0x79cabe0f8d3f34f3L,0xbda9c31ca3617fe3L,0xb26dee23dd9426a1L, + 0xe9dd9627f29c9104L,0x033eb169e2c6cd3bL,0x8a73f492fcba2196L, + 0x92e37e0bb858c83cL,0xe4f2aca623b3fbb7L,0x8101fb1e64be00a2L, + 0x91a7826a948f6448L,0x414067b4907260e7L,0xf774aa50e30bb835L, + 0xf922ca80c999c06eL,0x6b8635b90ba08511L,0xbf936b5c25fa04f0L, + 0x4e0a1adae02e8967L } }, + /* 69 */ + { { 0x00ca66708ba29c4dL,0xc08240ce22988094L,0x21c5ca6716dda752L, + 0x689c0e45abbbfa34L,0x1d7545fd3ed28b72L,0x5f221198d7c56ab4L, + 0x4b3d8f7438759d65L,0x93490dfb8fe50b89L,0xb641f5d7e80eba16L, + 0x7b0da5eb79acb537L,0xab6b14970c1d5e5eL,0x2338e68da5da429aL, + 0xe010c4372f6d2f25L,0x226f16d26530f3a7L,0xefb0f7b6cbef08bcL, + 0x733e30d99f99c999L }, + { 0xecfe1582a42a38f9L,0xaec2d58e4730b500L,0x2ee2f2a7de976b2cL, + 0xf0539db5a969c1bbL,0x31954168fcecdb4aL,0xf2f7348ae7a8e902L, + 0x1d58d7cc3121541fL,0x5d25b75c2202ae52L,0xdea9965af40835a7L, + 0x3feb6a41529b4e46L,0x5c97fb6fbd27ad9bL,0xd87554c0261f900bL, + 0xb43031d904d5b19eL,0x33d5e9b8cb219b9cL,0x7a43d4923ee00bcfL, + 0x56facb39b79a5c0cL } }, + /* 70 */ + { { 0x019165a2a3018bfaL,0x100c6b249ffad984L,0xbbf1b1f655341a9bL, + 0xe6bd1d9725dc4cc9L,0x52850ed52bfffe60L,0x24e992cc7e5509abL, + 0xff6c502e4ceb59f1L,0x2f0b35731aa7d148L,0xe90c1ddde7e3aa46L, + 0xbaec9f45d1142880L,0x475cfd2665be5dd5L,0x83abb14e1febce13L, + 0x6aba482980942d30L,0x1e1b235d297e82c8L,0xb771cdbe50d8218dL, + 0x88599266d94d6cbbL }, + { 0x08847290155ccaf2L,0x8679ebc77c5b773eL,0xa88b2dd1b2dd08edL, + 0x960a180e87d475dbL,0x80fdb6b76694d02aL,0x3e8758c93f3f9e96L, + 0xbda3f6fa4ad836c4L,0x9400c58132fb387dL,0x25a785422550200fL, + 0x2a97c351776ecf18L,0x03ebf46e566db59aL,0x4743a28026545edaL, + 0xed169d84cf74ab44L,0xbaab931d88cb3f69L,0x70ae932cd8257196L, + 0x797224a6a0c09719L } }, + /* 71 */ + { { 0x632923f8441f3567L,0xc11c31682e24bf1dL,0x4b97726bb7671fffL, + 0x601746a77a5e1a22L,0x53dddea03addb417L,0x57867a3c7f59b846L, + 0xb012a98756cd7ff7L,0x1bd5fec9f19ba9a8L,0x750379a2f8306748L, + 0x7763445dab8c05d1L,0x5d7f441b7903f42aL,0xc011674da903e46dL, + 0x1b1d3c4dadd126c1L,0xa2752aac61455b40L,0x4da42a68555c356eL, + 0x3ff09c15d820852cL }, + { 0x4c0a1bcef9cb7784L,0xaec539bc2422f305L,0x5f40f9fd0c414aa7L, + 0xd3aa316cffd42bc4L,0x42f5a4c32f358e15L,0x00bdcd9ed6e27682L, + 0x069f789ff8a5eceeL,0x8078018e05e14f5dL,0x2bb3e4938b40c741L, + 0x5dbc8c1d7917f72dL,0xe0eea664cc57150cL,0xa25ecc5ac3fa8920L, + 0x3c21b0f51c797164L,0x8f09a2f2634ad16bL,0x8e730fc558391d9aL, + 0x47ef18054fdfae4cL } }, + /* 72 */ + { { 0x9965f3d13da285e4L,0xba7d4dba3a01e3f4L,0x4738413a61214ad0L, + 0xd3b7d53522397549L,0xa53dbdcf5a730b92L,0x3130d92b332d165dL, + 0x44a2854182f97ef4L,0xbf62221c44dce1b6L,0xbba138587e2a0ec9L, + 0x33f32c8dcbfad998L,0x409e5f3fb5fed44bL,0x5c328c65c66217bbL, + 0xb00db69ffcdf71a9L,0xa23c2a21b8920788L,0xf8ab28e63ae6464bL, + 0x1a6b6e9cb8de0861L }, + { 0xaf6ec2b606af77aaL,0x2e60f5cda887f065L,0x87d214009f498c56L, + 0xdb595b59fcbaaf4bL,0x0fb592a1271ab855L,0xa0ce10e5d4349b0cL, + 0x9d6187d8887d8c9cL,0x03ee95f9154bd6dbL,0x8fe532135d06c999L, + 0xf4a7bc30fb6a64d0L,0x3d22af0d66a4cb60L,0x16952cef5d37367cL, + 0x6f0ea734997d8e55L,0xb447c70f731732d0L,0x00ab3034a9cb3942L, + 0x79dd018028510fd0L } }, + /* 73 */ + { { 0x04e0033a3ac7424eL,0xdb06b68860fda4d0L,0x236a9766bcb772fbL, + 0x294a8e2bf297cda4L,0x4b0aab85db013c6eL,0x3d2aec988723a3adL, + 0x0cae32cd13c84a6bL,0x21888f5e70ec169eL,0x739633bd42a88262L, + 0x68ac792e7b60d9b8L,0x89f2b72210769fe1L,0x8f3fcfe6d24bed34L, + 0xd35efb88a3eb24aaL,0xddecfa3f484c706bL,0x7cc119a9929ece0dL, + 0x87e5ad458d405436L }, + { 0xba99aa9d7d1000a7L,0x8b94affcae823833L,0xc8229628dfb83dc5L, + 0x2f59fe11845a418dL,0xa8b970f85d417054L,0x8918c26572b71581L, + 0xe4ef477dc0d1dd17L,0xb50b4cf33afad7c0L,0x21baea7901870a5bL, + 0xc77087f9bb3a2868L,0x7857531e124a59cdL,0xed74c26f57f43239L, + 0xd5f5ae250164c94aL,0x6608b7e2f094bf74L,0xf4cdb5bafdceea32L, + 0x0b712519990cc045L } }, + /* 74 */ + { { 0x5a290ca188d5c64dL,0x0596d749a7492534L,0xa04b0d3d2a00e925L, + 0x082cd02ccaf7b66bL,0x912b50c2ecdded83L,0x813ce9deff31646eL, + 0x62ae70c7c75fff95L,0x6f6852e07e2a4615L,0x320fd7d003804fd1L, + 0xb1a2a4dd8218e8d9L,0x4918a6fbafc645d7L,0xfb080fa1e8d9fdbeL, + 0x33d4d08a4470b6eeL,0xd2ba20776d974ef7L,0x8ecb95a769dae5d2L, + 0x7a3f423a7d69596dL }, + { 0x362d2ca69a929387L,0xabdb7581cb1c1fffL,0xd892ec9f7e51b6cbL, + 0xee8d86323a4e131fL,0x4680e3f15bd87561L,0xe3a597e1d4e7e732L, + 0x3cc72b7c5581fefeL,0xf3e77f8aca8cae0bL,0xfcc7d7dc5e2fd4afL, + 0xdd3a455221355b79L,0x546b24f2a2c07177L,0x415b532d0689621fL, + 0x2be9af513f78163eL,0x27d63b9b33d7ed21L,0xab019ef296802943L, + 0x2da5fc551623faf4L } }, + /* 75 */ + { { 0x62429cf3c8a5c600L,0xa7a80c223fe33e7cL,0x9ffda7400a57ddcbL, + 0xd1ae156d925b0c74L,0x097a43f96b100eb0L,0x169e945cef943c81L, + 0xa1f734e51128cf24L,0x04387c4a419f0133L,0xc007868b01044024L, + 0xe5416abf90359cf2L,0xf9c76fee478d54e3L,0x66219da642a2173eL, + 0x61e031569fe30141L,0xa0ff5ce393ef247eL,0x811792ba072b6592L, + 0x855f021970c854d3L }, + { 0x61fbfb6c847314c4L,0x97906155eb45b96aL,0x7102e1466ba2afacL, + 0xed51f975ab949781L,0x9d2f5b17c110c4feL,0x7ac8ce70aff57667L, + 0xe7366a216eb244e7L,0xdd1bbcec551c65c7L,0xb525060ae1a859deL, + 0x7a0481748ba7d2e7L,0xe1a2c541ab8ea8c4L,0x6e7824c36fdff078L, + 0x79b49fc714874b04L,0x22ae337f06b1f733L,0x1c3521926f8fe6cfL, + 0x292236cf525d0797L } }, + /* 76 */ + { { 0xcdb8d80a7d8b29dcL,0xd17a202408ea648aL,0x7db12c5eae92be91L, + 0x1f347d18fda72fbcL,0x11374b409e760c6fL,0x7361e8f1d8e38d91L, + 0x7714be9d739ac1f4L,0xc1f9701cb4df5c4eL,0xd9138ed86f72cae1L, + 0x1c7fe1f76ad180c4L,0xf8c185be9e2dbf9cL,0x835db2697c70c44dL, + 0xf997cfeab0d15b5fL,0x5101445a61e6545eL,0x16b0688425184e5eL, + 0x7cfac3597521e7aaL }, + { 0x811821673c0bc53aL,0x84b5ede37e751367L,0x3ca255fda3657a18L, + 0x096abbf4ba1fdd98L,0x9ce8369fc5da77d8L,0xf27b9ae7aab342c5L, + 0x06c91bd6972059f1L,0xee0dab30914ecfe9L,0xbb647fbb93f53f12L, + 0x30c38a7affa57e0eL,0x517d06ef9f2ad607L,0x49728d87bb99dcc9L, + 0xb0034af1446080a1L,0xcc810c3f12b9c17dL,0x7225f14f772a22a0L, + 0x6ce3dc7f1ddf82bdL } }, + /* 77 */ + { { 0xc07cd835a4397830L,0x4dd9290cf4733306L,0xdd35d3a829989e8cL, + 0x79902559563d8152L,0xf278d911e87de61bL,0x9c7340c71024e35cL, + 0x2d4444614a0d0e59L,0x63e7608ff32626a1L,0x627a37e9c4c9baa9L, + 0x0c56dc5176fffd25L,0xcb6defc8cef2a1cdL,0xcbcc0d56efc559d9L, + 0xe45f3fc5041cb692L,0xcd05c239e5161e09L,0x2a731ee95c3b559cL, + 0x85151122a3d0a16dL }, + { 0x782d033586ff19e2L,0xc2c60daa1da28603L,0xb2e78cfe557c7eedL, + 0xa8f6f9841bc4e8b0L,0xcc1f9b4b3df35c67L,0x96e136034764462aL, + 0xbf910b977c7ae0b0L,0x27c7f30551435956L,0xc14db15cf631eae5L, + 0xa51d61427e69b34cL,0xdec828515fc12ff2L,0xfcceae13fb887162L, + 0xda332ac1de1488bdL,0xa20374e22ee3e74cL,0x597ea1a1f0ae069cL, + 0x8b1159f277bdec04L } }, + /* 78 */ + { { 0x4af71a442f961d30L,0xbdf968a87ac7248fL,0xd32df87cb1a906cdL, + 0x00c10e2604abf925L,0xb8711759b9f04d4cL,0x00d54e60939705daL, + 0xf7587433c9f80849L,0x2e9abade6a7a2375L,0x5676d47894ac17acL, + 0x4ca0525bc202d99cL,0x95b8bcadabfae73dL,0x2371ed383405991bL, + 0x2b69e47a458a99c3L,0x7cac0b182b78c866L,0x6ceaa79be0232c7cL, + 0x0bd86433588f7459L }, + { 0xdea1a8b47e734189L,0x52c5ac88cfe5fa17L,0x444a4d4e11437664L, + 0xc2522308af9e9750L,0x78b1d0c3d30c6b3bL,0x2edae5f04c6df477L, + 0x53131d9a2ee88dd7L,0xc4e380eeacc93e34L,0xd499b1aca8db0e8eL, + 0x77348c167f5d49d7L,0xc96632571556ccd7L,0x65ce0e8c2611d13dL, + 0x2c95fe66b5a2fdccL,0x266988328658faa1L,0xda87d1f431c32c98L, + 0x46650598fcd91907L } }, + /* 79 */ + { { 0x4c6c13cc6b4a5efaL,0xc481989b1d07b265L,0x10b966ce8bdc69c0L, + 0xf54cfaa22c2531d4L,0xcb5f1808cad0a100L,0xbeb52538ee5da449L, + 0xa6240085bedd83ccL,0xe792dacfd6255c78L,0x883719062062058fL, + 0x96615e83ed1658c1L,0x4b549b277d28d542L,0xeaf127db83b75df3L, + 0x4f60df6d17fbb942L,0xd08631dbf6f7c930L,0x17c38f986018789fL, + 0x0c43574ab9a9280cL }, + { 0x76eb324c1d20cad0L,0x90decb098c61108aL,0xa6e9d39c6f06d36dL, + 0x6cd978babc0da197L,0x5948b1c0507ac5ceL,0x2bd47164c5497eb5L, + 0x2a9c4c0f4d5914e3L,0x772c5046a759f03cL,0xe7d7328a69ac847eL, + 0xa8d57d0c3048b330L,0xe60034e040f7baceL,0x823d9193a85f1790L, + 0xa6e9b66c5c859736L,0x22ca2c7a679e1022L,0x00e7a19c09023fa4L, + 0x324999f12726d5b9L } }, + /* 80 */ + { { 0x667eaed67c834915L,0x9f77aa6abc5eb64dL,0x729ebcb625d62011L, + 0x0aee24f2699fd9c2L,0xe1eb58742b8d4f6cL,0x7f12710c14c976d6L, + 0x91390335f6d9ea65L,0x668b704906b50064L,0x65969a0e0876ee4fL, + 0xf901bf3f2f9d9360L,0xfb1a8651b499e3ceL,0x80b953fbf2dbcaaaL, + 0x312cc566973b06b6L,0x3534d9c33af36c64L,0xe4463a5210ffd815L, + 0x57ea2b4bf18c2b91L }, + { 0x00f5e1628aa0f2f2L,0x8c7e75c50e46bcaaL,0x97ab479aa4a2c42dL, + 0xb4f308ea14baa202L,0xa901bd146943cc2eL,0xbb125feeeed58804L, + 0x6502c8f99d180f7cL,0xe53539191580c61cL,0x7e27806927101ee3L, + 0x7a0a40a1faa72717L,0x32edce024c75b153L,0xda23660b538f1c22L, + 0x4d511e98be307d2eL,0x24276e409baee0b4L,0xa78c39277ff1f307L, + 0x60480b46ea7935c9L } }, + /* 81 */ + { { 0x31087d663872ece3L,0x5f29be7d955b70f8L,0xb50b4fc79cf95bb8L, + 0xbae3b58ddbffa621L,0x0e61d280e022ba5dL,0x78ae51174181449cL, + 0x0b132840cf555485L,0x800ed1b6b8ce0b0eL,0x35dffdd578d5de3dL, + 0xf7e4237469a56b47L,0xd5e323698d910ae7L,0xb6ff52a06313c7c7L, + 0x5a2fe20da92de9e5L,0x41b347d3d12110bbL,0xc5905edb40c16f23L, + 0x0774a0d39a8f88ccL }, + { 0x3ae181abe3b6c106L,0x4ebe163f8de150b7L,0xcf75b82f6f354836L, + 0xaa0d20633ac7ac16L,0x5c680668291722afL,0x73941e6111545553L, + 0x17127e38bf5de3f7L,0x32cfdf031afb41daL,0xc6893c9187bc8663L, + 0x75046744a62c9c99L,0x96866e2d962c1947L,0x489ec8df378cdf4cL, + 0x3a60709b3407fa32L,0xd37d2159551290d1L,0x9623d303bab92273L, + 0x081519542432014bL } }, + /* 82 */ + { { 0xf9236d89fb7b2108L,0x3ecc83ccad75f9aaL,0xf7c72b15b4e1da11L, + 0x552aeaef0315c362L,0x11e140edf272fe3fL,0x99d79bf687843ee8L, + 0xce6b54fd1d9bb25bL,0xb20b0e215b1bad74L,0x54a0214f5b84c90dL, + 0x459bbf52fca6cec9L,0xe363c48d9e4df76fL,0x3045f84ed64cf17eL, + 0x8402a167f62ada48L,0x2c9e1bf36a74ca01L,0xe8cf9d41f691c42dL, + 0x5abf2178c2c4b874L }, + { 0x4777966bf3b3bccdL,0x0047e0f0be3e0caaL,0xcb8383b38c7d5043L, + 0xe77e3baf946fd5fcL,0x79baa785e9ec0e87L,0xd83c557cc8a18d25L, + 0x9b96e5af25befcfeL,0x4f05d15e98c71b61L,0x081f991a77e62da1L, + 0x1c6ec781cbaa3821L,0x7522f65de54d9bfbL,0xf5d0557344ed1430L, + 0x3035b31f95cafddaL,0x47e67f436378f5bfL,0x029f7cad5270b9d9L, + 0x15ad15874d916a48L } }, + /* 83 */ + { { 0x00de2eceaa588ae4L,0x552ebc58a371a232L,0xd00ea93471230444L, + 0xafbfa67de4b1832dL,0x29216341b689e843L,0x1f96bbbd61f4e2e8L, + 0x9542068404c29dc5L,0xc7fe382742317fd1L,0xe0a0aec663483162L, + 0xfc2b94d10700184fL,0x07219973fe1fbd85L,0x648b6ab1fb074352L, + 0x23bbdaadc46e5392L,0x0db8dd1f00fa56ffL,0x104815eb866725f6L, + 0x3f9c4cca52e81963L }, + { 0xff36b29732ce637eL,0x81a15f2df5d25cddL,0x1a1d052d8b02ad97L, + 0x2e5f3bbccfbab3e9L,0x60d2cbd7614eeb75L,0xd4491843cd5a793aL, + 0x2242cf75cdba2144L,0xa20705e788b99766L,0x64e12cc0ec77e132L, + 0xb1c14df6b61a9b05L,0x8fd97f0474825b5aL,0x956048213da31223L, + 0xde4867274d30c70dL,0xbcab8f151c12ee69L,0x5dc638b4668d893dL, + 0x6479dad6223f574bL } }, + /* 84 */ + { { 0x569044f3b05f2b26L,0xb35a294a80b9f76cL,0x8839fe284290f6aeL, + 0x761cfb23026a5877L,0x768926b62e5ff9c3L,0xbae6cd200b11c576L, + 0xdc85775672a03efeL,0x0cae074ae1bad63aL,0x3fe491a1d709d99cL, + 0x76c5ded66501d9c1L,0x1da6eca1c32aeff7L,0x50849d55c57683e8L, + 0x9e392e9cdf98d847L,0xfad7982f64d9a564L,0xf7c3bdb7a37b98b2L, + 0x1fe09f94f0860497L }, + { 0x49a7eaae7648cc63L,0x13ea251167cfa714L,0xfc8b923c653f4559L, + 0xd957619b81a16e86L,0x0c7e804b3c864674L,0xfc88134a1616599aL, + 0x366ea9690a652328L,0x415329604bc9029eL,0xef9e1994ae2aad2bL, + 0x9e2a8c527f10bef5L,0x73dcb586c67bf860L,0xf61a43fa844cc25dL, + 0xd74e7eea74eb3653L,0xf3356706dd240f02L,0xeec7694cfd83bcb4L, + 0x4de95786db62526aL } }, + /* 85 */ + { { 0x4867d3153deac2f7L,0xa084778ab61d9a8eL,0xf3b76f960ab7b2d5L, + 0x00b30056cfdf4f79L,0xd0701e1531ab8f4bL,0x07f948d59c779d01L, + 0x7c994ebc82675371L,0x1104d4ee48bad4c0L,0x798ce0b5bfc9d058L, + 0xc7ca898d309fa80bL,0x0244f225acb33eafL,0xd51e8dfc5b2f3175L, + 0x3e49ba6ba4d7be34L,0x1760f4c7bda02b43L,0x37e36a7e4435275aL, + 0x1c94418be636980cL }, + { 0x43a2131309dc1414L,0x060765fc43c93537L,0x6ff3207adf5f79ceL, + 0x6f18b1fa85d4cfcaL,0xf5c4272e63e995abL,0x121a09e4a82b3002L, + 0x82b65d1b97147f16L,0x4993c20c20a7fe26L,0x99c9cb98e6716726L, + 0x5a02d673feb440a0L,0x3f3fa9e1251b4bc5L,0x75dbc474a05338eaL, + 0x3cb4044b7b09f6cbL,0x6767da1880434609L,0x97851422098ceac2L, + 0x611bfbb2b55235baL } }, + /* 86 */ + { { 0xbdbaa55ef00ad2a1L,0x29efa85e14a290d7L,0x3b4a4768e92b1694L, + 0x67111bcd11ec8130L,0x0e42570288bd27b2L,0xf28cf2a3d9a03c06L, + 0xbb7c8d2df318884aL,0xe2ea1462e3aaeb20L,0x3353580443b85d77L, + 0x81ee4482554ee9bdL,0xeb2eee9ee6aa198fL,0x7a5aa804c26c5944L, + 0xa0ef2da582ab167cL,0x5a2ab47602fe21a5L,0x169cb3b83370298eL, + 0x86e6c5440eb3aa8dL }, + { 0xede033210b793d9bL,0xf79fade11ddb5eceL,0xf73fda9268930b64L, + 0x06aad97dfe4fd1b2L,0x073a5b1d92a4dc88L,0x8af8cbd8bc976d75L, + 0x60b4abb163ce26c0L,0x9c8300a9dcb1fb06L,0x335a594cda95b3d3L, + 0x1f97d7d4b37eac87L,0xa3d2eba220eefaabL,0x3258c906f3e828c8L, + 0xc832616f85ab7781L,0x725971928c28b617L,0xcd7196bc3233b82dL, + 0x83867eb919fa126dL } }, + /* 87 */ + { { 0x774fe73e22474edbL,0x2a7663941a84e1aeL,0x270329ad9c6dd6e3L, + 0x00c4a41514f8bf5dL,0x3ce2ea37d2267b90L,0x1275301511d24faeL, + 0x7c14d854263a1b78L,0x20c8401b1ae0b206L,0xf32a011b081f49fcL, + 0x1e8123fb959c6df8L,0xa328dc7c800e1d06L,0x5876a37824259a9aL, + 0x23ada8b5b7ef6c37L,0x023f6b6ea93d4c9fL,0x89f5414dffb6389fL, + 0x4b26bba2e628b39eL }, + { 0xd30b1cb45d318454L,0x123b749fd7436cb6L,0x3110c726568a7461L, + 0xc85de1231c84fd1eL,0xa5f8d6e608403d55L,0x395b6e139b1fabf8L, + 0xfe6d68c33cfedce0L,0x1d90381f94b91110L,0xf0a8ea812dcc6eb7L, + 0x59e804137e90ca2bL,0xbeb5fc07c8a25c5aL,0x009c253a5d84663cL, + 0x00b15073910b6a7cL,0x8607da4c4108f8d5L,0x02c3d9c3cb901e65L, + 0x4d697bc52c9615c6L } }, + /* 88 */ + { { 0xe0db1ef0efa8fb40L,0x29021c5b5ba3989cL,0xa8d6fb15809d19dfL, + 0x6b787b734c1219e1L,0x6417e16814ef05e2L,0x449342db8f9796e2L, + 0x2f878a5ebf84421bL,0xe71916d7e94a4536L,0x9818bba3ae119693L, + 0xec674be95768804eL,0x0a26074cf8424f8aL,0xdbc93b9d466ce6abL, + 0xb3f15a98c920078bL,0x9d10fd0d3870f1a3L,0xa61241d9e4e785a7L, + 0x76ca87a1e6c8cd80L }, + { 0x4357fb56e02e48b7L,0xfbd14b13cc09e9c6L,0xdb5f243524069cf0L, + 0xf878165c2c3b01a9L,0xe549e7c4e6956dadL,0xf2fe9538bbd60b68L, + 0x952f856b059dc653L,0xd3f60225b377fe9bL,0x6a0c7328bfe908c4L, + 0xce6aa2d3bc8f5f2dL,0xf721344324425050L,0x17e1266a3d3b3ce5L, + 0x75b5e43fc1677512L,0x1592706237fb894aL,0x152607532be3e375L, + 0x27e7f2c66da3b7beL } }, + /* 89 */ + { { 0x638f65ade6a15883L,0xd4a7e68c66afdb33L,0x6207b6abd3f12de5L, + 0x1c6ff95037b87810L,0xc0d44cb264acf6d3L,0x163ac601f2be78c2L, + 0x1c63cc5a1636980eL,0x3e92cfe895c9349bL,0x7738e0d841ec7220L, + 0x6169d7642d5fa961L,0x2aa776c1c3e028e9L,0x93dc5646b16d5409L, + 0xa0b27fb5706df4d9L,0x9e991170ce9c6b97L,0xea8e42be53c85f40L, + 0x02e9643783246528L }, + { 0x91540addae78ea1fL,0x51a1b74d7b670e96L,0xf9936441f7006826L, + 0x8f97d6ea7d7520c7L,0x0faa6a0269ce12e1L,0x2590aca879208342L, + 0x7a48386375614436L,0x07c6149ef381408fL,0x733bf584d7853406L, + 0x8761b0109abbb6f7L,0xe4eb249ff528a09aL,0x08781ed82e00ae3cL, + 0x864c1b252178effaL,0xcc1e62a29d513a7eL,0xedb8b94e1919062fL, + 0x739f53da4f16527dL } }, + /* 90 */ + { { 0x7a5f4a88924adc5fL,0x95646c16a818f56dL,0x0ec491297795f954L, + 0x2b48753dd19c5400L,0x16fa236b205912b4L,0x6b3d65f3e87a4946L, + 0xa7174a01045fd066L,0xb635031312a5e140L,0xa79c4b44a96b8623L, + 0x7a339d659ab003d5L,0xc72f30c63826f31aL,0xb4e7390c6f7090cdL, + 0x59ac6c36906ebe24L,0x39a7f06dbba4505aL,0x839991e1c58c413aL, + 0x020c23ffa20e0e84L }, + { 0x120e4adaafc74661L,0x37bbcf63277fc065L,0x41049cf6b6dce799L, + 0x5b8d6b537b161ba1L,0x22218431a9610fb2L,0xde9ec9d1dfdde769L, + 0xd32bfa4d42d80630L,0x3885702a6244df4bL,0xcdedd1ed45592dfbL, + 0x0e1df45bfb4e01b8L,0x8f4bded286e215b0L,0x809354876a937e6aL, + 0x415278ba8130f723L,0xc6dc469238a821f8L,0x2207b119fd8b4f8aL, + 0x76e7bf53f9269cefL } }, + /* 91 */ + { { 0x5f12842827ebd187L,0x8d3320abb65aadbbL,0xb042765a72258695L, + 0xda3f33f98f0986abL,0x411807a7aebff503L,0x25c776ca825f71a5L, + 0xc0de7bedff7df24bL,0xda8b0f42165f1fb4L,0x5f3ff737731f3ae3L, + 0x4cd1d7e7193e0a52L,0x8df84aa3b6b3ba46L,0xba84b897aa1f3782L, + 0x6e7960cce7733ac7L,0x4d46d6ab50981a21L,0x1ec12c257cbb80edL, + 0x79e7ad272b96ef09L }, + { 0x3cd970dc8f30caaeL,0x85cabcf10a6ebef4L,0x63c1863ec714616dL, + 0x1c50db0b519e3a98L,0xf39b896364cb13d6L,0xdf67d81f22547b69L, + 0x7157abb9d67db0ccL,0xccca25ba889491b7L,0xf689207c7a27e0dcL, + 0x34ae8fbe0fd43281L,0xa5d91f735720ec09L,0xb2f61909cdfd7bedL, + 0x1ec102324a039e32L,0xd3c3d65edb0d8fdcL,0x32c916c84fe5005dL, + 0x7f8c37ac4c0bea94L } }, + /* 92 */ + { { 0x33ec1e5443ac05e5L,0xda4a4da4cd8d3825L,0x86d88c0b88bf9e2bL, + 0x34d71dd0b53811dcL,0x655040d2a3c3aba4L,0x2bc40949b61611beL, + 0x1c2d426e279a4fa0L,0x535a5aa23b065ac3L,0xdaa8a32fc52ea890L, + 0x5a5deca79fddad22L,0x911f05fd2ab3b26fL,0x5dace7dbf37cd81eL, + 0x0e0e44e790d16b8cL,0x15e68aede4f5894eL,0xafe04999fc92a74fL, + 0x1d7703aa970e7c2fL }, + { 0xa8a4c81d3f0062a9L,0xe31eb2b8d96a20baL,0x66dd98df864bd101L, + 0xba05f5924413b614L,0x51a67a0de9a555f8L,0xacc2f0972e4b52d1L, + 0xab5daaec7184ab23L,0xce08b43e7c7f691bL,0x520e530b76c427f4L, + 0x7d352069e423ebdcL,0x6b5e39e834df14ceL,0x3dcbf295446305acL, + 0x682cb2e1fe34cdc1L,0xd4ac45d1111f5afbL,0xc5ef63cd47f296f9L, + 0x0a2c40ec93c20871L } }, + /* 93 */ + { { 0x09bc384faf5747dbL,0x3bad6086c06ab86bL,0xa406882e9e7c1547L, + 0x2d5326d155977abfL,0x063a9a05da81deb0L,0x9a86e4a7524b6111L, + 0x1402f87a4ab2eb90L,0x7d0721d4d5c600baL,0x1a2fd9a9f289fdbfL, + 0xf5dce66decde6f07L,0x62171277dab9fa73L,0x6d2dc49f6c474babL, + 0xdc017e1f76eed033L,0xb97175c04da825d3L,0x6c297e3d54b05e43L, + 0x2efb454656c9c87eL }, + { 0xa4712b008b21c064L,0xd186fe424a70629eL,0x6435b3409b74f0afL, + 0x6965aa437ec9e629L,0xdda14673c4c60d08L,0x0b656670bf3057aaL, + 0x7f05e8403ce86f60L,0xc05073a904401a16L,0x16b1e638294e607eL, + 0x2078325269cf7046L,0x2941141be8ce7d3aL,0xd38ad8d37577053dL, + 0xdba68fb3caa6630dL,0xecbeaff1e9504350L,0x9f5166d51d2d760bL, + 0x337532ce462891e4L } }, + /* 94 */ + { { 0x3f1118533a00bb9bL,0x2d2ffbae45f66685L,0x9ae11a85d4aee24dL, + 0x18ba1e1b0341856eL,0xa9ac81782731349fL,0xc13dfd4a545715b5L, + 0xa5f7423c5daad2eaL,0x30a483b9535b76a7L,0x92e9ada4ff873e9bL, + 0x15662d84723a1055L,0xb935497b8edac4e0L,0x61b6441a39d8fa70L, + 0x1541d75640d1589fL,0x62994237f0a05f0aL,0xfd8b00346bb28908L, + 0x192a2b5dd4cd32bfL }, + { 0x63576628365ced07L,0x029f32fb05de1d1fL,0x6d17b9bcbf40a7aaL, + 0x1b1b2a089bb50a47L,0x9389abbb795a6278L,0x52cff60fb34fc19bL, + 0xf3ab9492387d8739L,0xa8f053e66920ccd6L,0x3ef2dd4b63a9b4f0L, + 0x9ab0ede151e82129L,0xafba0c0b0838bfa1L,0x2bd5a7ac9ffc11beL, + 0x058bfd9595cc0878L,0x686d48a3f8c2f0c6L,0xc33abaaf1d9b31baL, + 0x632e22893bc0c268L } }, + /* 95 */ + { { 0x1c851d2015a1cccaL,0x4efe290c7e522bc3L,0x0b741d5518eab053L, + 0xae656197bc85e217L,0xae13141e01cf8b29L,0x2e2cb59366948478L, + 0xeb57bb0fc31bd8aeL,0xdecef5d6c264e788L,0x6fa856cc9cb96d86L, + 0x2db16813279183daL,0xf03f3820383d796aL,0x58a456ff1d0c6fedL, + 0x255898058a6abd9bL,0x339f52c583f96f19L,0xcf6ded8fda7e9ea7L, + 0x68c3d9c15d1ccd45L }, + { 0x67e26265e6b392b7L,0xcec1d9bf775d9509L,0xe16abcd4d76514f7L, + 0xd86f59b20de72e1cL,0xa66e43cd1adfb033L,0xdb34434005e457ccL, + 0xb67a79165681daa2L,0xc32e7babf0114731L,0x066fe16ed3b1e961L, + 0x924e298ef63d26e6L,0x9bea0dd8541add6dL,0xef9500df9982f971L, + 0x5c876e63c5f076acL,0x55e12ae5b23d396bL,0x09efbb362ec6747aL, + 0x8f2055ee233286a5L } }, + /* 96 */ + { { 0x4a4ab9e3b82c1af0L,0xfc65e9e7f2cae264L,0x4feaac0a60187d46L, + 0x27d3f335e393b363L,0x9c9f7c00819bacceL,0x3f7418b5b8aa6611L, + 0xffa94557372aae95L,0x937d78048db38589L,0xd10c86df6f1fbc1cL, + 0x48aebd89a2f0a0ceL,0xae5d5fa2367439ebL,0x103a6a0b3f17d2d8L, + 0xf233f68a411d9894L,0x7fece8b3218b67a2L,0x0422540f2319bf06L, + 0x1292c8c9340d322eL }, + { 0xf5eb55870386463dL,0xd4bbc2b20371d97fL,0x1b3645710b819c5aL, + 0x0cbb42d6cf04ad41L,0x5d819c7666939ec1L,0x8745ac13a01847e7L, + 0x4f704b021c7232e4L,0x2c9e58a0acb05780L,0x9523b8b3b561e295L, + 0x3384df0079f9ba35L,0x78231fc21eaa9628L,0xa2eac54f8aea2b90L, + 0x8075ed7730d1c263L,0xacb44ed5fb339000L,0x92546ac2f011293aL, + 0x7c78762beb821764L } }, + /* 97 */ + { { 0xb8f7d6fb067902b6L,0xb2823a43d1735980L,0x062cfb1259741dddL, + 0x6e391b074033f95cL,0x3831d0a368589b8cL,0xe3474d49522290f2L, + 0x4dab14d6222e1f3aL,0x8f00fcde53f08d39L,0x559917ae707f28f5L, + 0x166aa0ba068e607cL,0x602713e7d7e1f824L,0x7c2555404d6a328fL, + 0x0d2e32649890cd2aL,0xf2207944eca0b20aL,0x5c98dc0752f4e09cL, + 0x69403504d84de81dL }, + { 0xf8b7b366e5407206L,0x1ecf54cf0d88fa8cL,0x6fefe548f7272e6fL, + 0xd653137281ab4468L,0x52cb5f0e4e474408L,0x9e426b3a6490737fL, + 0x2576c19b4980d071L,0x91f346280f272cafL,0x78e60a4f468f31c9L, + 0x8776a32990844d89L,0x8a55700cb951582bL,0xab1af36514b1adbfL, + 0x22ebff92fbd343efL,0x32f9fb01b7d81f34L,0xad850e06ba6b30e1L, + 0x6da9e027bc5f9546L } }, + /* 98 */ + { { 0x21eee4c25c9490ceL,0xa96ec4a30df68381L,0xe6c607e0a4a9368eL, + 0xd8b0492a4bc262f3L,0x0846a210460c34ffL,0xf7ff7a6428df33cdL, + 0x10c5504421827612L,0x9d25fce9149bcd01L,0x725611cdcfc613dcL, + 0x159f7e8897f51ce5L,0x3fa3bf314e8c08b5L,0xea15611575e7538fL, + 0xd1e0a95191c84020L,0x0d2268bacf02ad0aL,0xa04c6ac4058b8e5fL, + 0x773b40b9b3515912L }, + { 0x00ff2cdc3631cfd2L,0x14c4c2d3807737bcL,0xd600616a338a5270L, + 0xd0e3306db32cabdeL,0x336738eaa70b17caL,0xf2f4aa8d79f353eeL, + 0x712f6ad9576f3ad3L,0xe427985289b2bce0L,0x05d8f94dda92ca30L, + 0x9891d475d8492dd9L,0x3e06a5ca4d15e4bdL,0x4725d4eb254eabbdL, + 0x31394acec0ed513cL,0x7e0f9859bbfaae6cL,0xdc125546833fd137L, + 0x12b46385c56c4f75L } }, + /* 99 */ + { { 0x810dbebd932951deL,0x96959d425aa69c94L,0x5fc49c04ecb2f08dL, + 0xac74f0cc2250b82cL,0x96a439a53aec4e1dL,0xc33cab9a90499acdL, + 0x2fccde6654d9b3afL,0xf4af285c3863ae8bL,0x2373373e46febf88L, + 0x751d672c3c9ab7edL,0xc1c51130fe12020cL,0xad82402f52f3e56eL, + 0x3489ab7aa4a64a81L,0x0a1fb661d9f163f2L,0x17c69be10e553317L, + 0x61c1935e7d88d417L }, + { 0x2e722d9b3492ae43L,0x1ef89d950538f05aL,0xae77e588200aab63L, + 0x2872c120eba4b117L,0x5c2432c83a461cb8L,0x315b3434cb938f26L, + 0x05bf2ac58c4c7dc0L,0xd2e501dd596b378dL,0xa8506c9fcb890c30L, + 0x3d0af4617c361f0cL,0x21f7b7185a35cbaeL,0xbd1035f1f3fc0138L, + 0x74628af58b248edfL,0x8d6421d048c9cae0L,0x75e3da392ca18773L, + 0x27ad0df271d3db94L } }, + /* 100 */ + { { 0x9e3bda79305b5aedL,0x2c67d4a45998d6a7L,0xc855e1d30f7eb700L, + 0xc18a7e9e147d1c44L,0x3ea99618c89540edL,0xa53be20a7e6bfd20L, + 0xc9487e64ecc14437L,0x7297920734ef85c6L,0xfa0d4e71d5e1ebd5L, + 0xfda2b1e64d48d6b6L,0x782a1e0566e200d4L,0x2a3c70da5a5366a1L, + 0xfe3fbd2b1a473738L,0xd7ef8c067fe020e8L,0xec686fdeeacfb665L, + 0x5d9b5e276dd1542fL }, + { 0x3637c5a5cb3e472eL,0x2153d92730a1405eL,0x009992e5b4498558L, + 0x18f00ccdf39a0851L,0x26237c11b5c6c560L,0x418ed4081343540eL, + 0xfef7cbf07e7f3184L,0xecd92366bf48576bL,0x1b75be1abc94c91aL, + 0x8e1778de4a162276L,0xc52e57d3c5c6bcb8L,0x5cc382c75ab71858L, + 0xe12c2c283f6e39f9L,0x4c7e0ef2d62735fcL,0xe071deb1835a5996L, + 0x24f891cdcbb8c766L } }, + /* 101 */ + { { 0x24ef60bf6778c1e2L,0xff49c03d00d5be5cL,0xec11986e2f01a09fL, + 0x59a728a4ae096e58L,0xaabbcedb7077984cL,0xfb473bd2870ca5a5L, + 0x8c928c614de30e3dL,0x3fae7f9a4f67abcaL,0x83c2b2ebec21a9cfL, + 0xafa70d629cd9b5deL,0xadeaea59c60b18dfL,0xd5fef7be4049b54cL, + 0xfceebc766dd310e3L,0x7748efe38f6321ccL,0xfe9c32b118ee8af5L, + 0x863ac3cfd42df612L }, + { 0x0a36fca7b85a2fe2L,0xf3e70d08ee429dc6L,0x8c9ba209141c3944L, + 0x306a810667272a0aL,0xe69a1555f968bd06L,0xb86f7e47153c603dL, + 0x9706614aef56e4faL,0xc0dc36b898780b4cL,0x43657fe23a1d3263L, + 0x01f97a86435522c9L,0xd91897f6edfef679L,0xebbe31d46daa17a0L, + 0x6f17910085accfbdL,0xe0da6e328f9fc1deL,0x1c9d53dbe1e7142cL, + 0x3e3f1b1e8b86725aL } }, + /* 102 */ + { { 0xb7ea15c07b7fbf05L,0x992f11b61f1a3882L,0xc9ddd95ad1dcd1bcL, + 0x31f5b7faad0f7e8bL,0x2936e5ebfca7ab79L,0x30f417dc19a55be6L, + 0x1f6f4e4343cde554L,0x971f5e6582f044bfL,0x73c3b8e44288c408L, + 0x61aac59fb807f575L,0xa64ee2dd818b58f0L,0x6f7a0a6097a3b0d3L, + 0x8b85ecc80394b058L,0x9a059474bfb3517dL,0x89ad5977a79c3f06L, + 0x81208ed8700a8025L }, + { 0x1093509914c4ce37L,0xf34bb843a1aa48a6L,0x86007024580d58e8L, + 0x6db42c49b375b8baL,0xac365524ed3bde83L,0x5521e1b4649233b6L, + 0xbc7cc5d564dd946fL,0x9c14b035bfb5b6aeL,0x7f22ba180146c1a3L, + 0x0b62fbbc872214f5L,0x3acfd7f7b4921764L,0x5ff10da1cb4d6df1L, + 0x660e262062600a91L,0x7ac7da9d81d9167fL,0x6e8e260cb6e7a199L, + 0x44383fb880deb3c2L } }, + /* 103 */ + { { 0xe107f01de44f9af6L,0x36381a4d8cb1fa1cL,0xe65be3ecfb7dd493L, + 0xd0b8435a26a8839fL,0xee60f9153ec789d8L,0xe25fea502bcc5e1fL, + 0x0477c0c57e44a81cL,0x349e9f83230ba5b8L,0xdd42f32fde180dd9L, + 0x8b039eaf64a3d11cL,0x80ef884ebeb7083aL,0x288e60c4f12742cbL, + 0x44156cc5720a0262L,0xcd547de67253b77fL,0x9829a6eca6013a59L, + 0x8aee708f0d548445L }, + { 0x18f22d9c32c54409L,0xa9ebfa4675ebaac4L,0x90e2e92886284981L, + 0xd0201f6f6b3a8e0cL,0xc973016cbd77641eL,0xf926f2f070170575L, + 0x4984048ffec0ce01L,0xbf696211f319d304L,0x74b5c844c91a88c4L, + 0x4c40fbcee0030a82L,0xbed67525e4f6d521L,0xaf7e47cc29d67d1eL, + 0xfa307db8c21d3536L,0x56b6c46abbb29405L,0xf059a7e3033e805fL, + 0x970f61fe6096a5a0L } }, + /* 104 */ + { { 0x1bc53d231bec8e4aL,0x8809ac1435a6034cL,0x4ee081da509e464dL, + 0x496ae1fd8a488235L,0xa1ae9863325864b6L,0xbaca13e974cd069fL, + 0x3738cc58b1d8a6b4L,0x5fa71f58e76b9da4L,0xc919be88c7eb16fbL, + 0xf5c8f13fad4e429dL,0x4583b6712499f9edL,0xbce20115a10d8bd7L, + 0xf66d76055790bb7eL,0x9316aede482b78ddL,0xe0d8fb2d75f855faL, + 0x404b5b945a7dcca7L }, + { 0xf9ee682a517a15c7L,0xaae4cfbcef880202L,0xcee2c1395106a354L, + 0x5de60192170febe7L,0x589e39fd73d0c54bL,0x195c71358c9092b7L, + 0xcb7ed53f0a7bfe5fL,0x2bd9242af61cc979L,0x8d2ef16c5395f7d9L, + 0x0d4ac1ca70b32f09L,0xa587526d52d185c1L,0x2932b04a942d6195L, + 0xfe25a979a500b0acL,0x5fa1f4ae562fd230L,0x60f55af220da253cL, + 0x7faa11b583146002L } }, + /* 105 */ + { { 0xb0ba4f0c6e402149L,0x3584cc1d963cc119L,0x7740dc1aa6527476L, + 0x3f77ff75c95715f2L,0xb2f234ad3f89fb0eL,0x55159032ef9be3ffL, + 0xfc9fb21d04237e82L,0xeb2eff38a153ed93L,0x89d53ae010041d13L, + 0xcf2e545b7f1bd828L,0xdd4a27ce43953ea5L,0x00d2e5d4d85e75c8L, + 0xeb93ed62241be1c3L,0x1e53f25f0242032dL,0xb9957636c3a4e701L, + 0x14b63a52ed98febfL }, + { 0x7610b55371c43336L,0x19dfd4a623a4824bL,0x7b97a2e00286051bL, + 0x86abbb9c8f5f1edbL,0x67a57d779b67daadL,0x8ace506dcd5ffafbL, + 0x85da9f9589ac3c63L,0x081cbaa875a3d150L,0x03353d8fe9346ed2L, + 0xb2ab61f1a1f9a02dL,0xb0cb09373a659c71L,0xb7e0e30b4f5df8a1L, + 0x77c4c741eb7d5a1dL,0x8f046c9c728e5cf0L,0x32dd0bc7f7c171acL, + 0x02485873836d2655L } }, + /* 106 */ + { { 0xcd40dd2375a4cd8dL,0x132ca43397bcba78L,0x30c5cd84258d61f5L, + 0x0a7ec059da1e8e68L,0x07a8f1711d65d40aL,0x869e655ef4350d76L, + 0xb98ce6f05983ae42L,0x7b61391d9d8bebd0L,0x3a529e25b1ba5d49L, + 0x46f732e91f6b2cf6L,0xbd66ec6a3fa3b629L,0x397950ecc3ef0ed2L, + 0xee9008cb5f08b476L,0xfd6be425965a0e2eL,0x78ed513c1177bc87L, + 0x6798cedffe512daeL }, + { 0x49e3f8fd1b97c5c6L,0x39fbab3e78c3b33fL,0x4427441240f595baL, + 0x174225b95d7d4376L,0x880b3fcc79c44777L,0xdc3aca833296b245L, + 0x55913df71734e184L,0xa4db23d39c934472L,0xcebb3733d1420a11L, + 0xb9d20cf9f3608bdcL,0xa618acf630cfe13fL,0x75f06b315f30874cL, + 0x506efe7f9f0005a5L,0x8aaea78c01bfc9dbL,0xf9179255f78e7c41L, + 0x3ea7aed252e96395L } }, + /* 107 */ + { { 0x98617e045b06ae25L,0xbcac148dcb5750efL,0x91ea2f0e604c2ba2L, + 0x00c19f6b76b78975L,0x79b9b6d0651da181L,0xf3225bebc945705bL, + 0x30b435f35c005bf1L,0x440b4482bc24d86dL,0x2b8f0996d6373777L, + 0x65fd6c561c44b4dcL,0xe9405ee630906999L,0x19ff092408aa1ec1L, + 0xeef3246a3d2f2895L,0x016c3765bc746797L,0x62d2569fd0705f7eL, + 0x6a8ad39c05250044L }, + { 0xe45f020d46be7282L,0x9405afed21380f12L,0x4cdca5bdd5da6ad0L, + 0xc2d6f1847f8be61eL,0x20132953596b8178L,0x8d3b1e7b7a8df954L, + 0x757c61bb39572b4dL,0xd749b57b80cc3b56L,0x9590ff9337b3ffecL, + 0x39bbb653145dc94dL,0x70c1c6062335e573L,0x9c2e72d7f763febaL, + 0x4768e424cc61b732L,0x777d2fa6aa73f2caL,0xdee4dbaac5cb58cdL, + 0x1a1811799cfae1aaL } }, + /* 108 */ + { { 0x6f6ff62f77575ed0L,0x18f14fa97d1da99bL,0x2e72aefb69efd7f6L, + 0xc45ab4cbddc28633L,0xb0e20d48586c5834L,0xd397011a39775dd8L, + 0x0130c808f4134498L,0x2d408ebaf5115ed8L,0xc506a05c0260ded9L, + 0x9e5b736219cab911L,0x4cf508c6e8693a86L,0x4e71245fcc773617L, + 0x2f71aa1f95d89ca3L,0x4bba7c6a607bbc98L,0xf3a515e7212b7fd2L, + 0x7d2ddc759230f5a8L }, + { 0x3d05816d4ed2cae8L,0x4cf6bc7db9c00377L,0xc23e98e6646b08d4L, + 0xf9ee6c614b9c0180L,0xe11c9a13ef9179c1L,0xa5b6147e8ed9688aL, + 0x7afeb648d06670a7L,0xd670333c17685275L,0xa89dd96975f9e8f2L, + 0xbb57228d37a68adeL,0x21a05d5e454cb186L,0x4810158f063dd550L, + 0x92dd4f084cb6caf3L,0x70c4d8527854abe7L,0x845969dc6e729d76L, + 0x5a52f87ab1bf40baL } }, + /* 109 */ + { { 0xed019e9109ecacbdL,0x6544023d7b89bdeaL,0x7cc51f0b5707371eL, + 0x14832b0416c8e217L,0xb1aa668281259ab5L,0x6e100f9223e361d4L, + 0xe593eee9e3a95c2aL,0x699b6bbd16c10e26L,0xad4878739473a13fL, + 0xf1c14dc5b274987cL,0x57dc00752559e2e9L,0x8449849dc3d47ad2L, + 0x83df278add527793L,0x770e3ec8eefd5b99L,0x2ae5844676bd02a0L, + 0x17f027643e705ffeL }, + { 0xdda4010d29abea1fL,0x636b96952407ac4cL,0x96a601290433218bL, + 0xf221fc3b163d534aL,0x05ba15beccc20565L,0x1238e54d96285577L, + 0x1b144257878804d3L,0x96fbf304a89a9fe4L,0xc8a7f06c4be642b1L, + 0xdd1a20e86e2b085eL,0x8f7f27c2ff4a591dL,0xc17b0753a4a343b8L, + 0x684b1e88bb173d4dL,0x3accea443dc07bbeL,0xdb15c88d4c441d77L, + 0x0ef0309a53e5957eL } }, + /* 110 */ + { { 0x4fc25721fa8e5b60L,0x646938ad691c0bb2L,0xe46d4b760b0a2248L, + 0x863f9ac27de16877L,0x503bb6ef2721c630L,0xf8c199df0b67fb02L, + 0x78c1ed72e07abd39L,0xcf9deb7bb32f0ddaL,0xaff726f06c3c89f3L, + 0xb7008b2d1972225aL,0x8f5a61174f145f5cL,0x4e0e6f8c457c4f37L, + 0x8bbdaa441c453c64L,0x57be326da6e92c80L,0xa9bc3fd95d773561L, + 0x3d3b6cc6bb37b72aL }, + { 0x6e6f12cc9722c880L,0x3a1b6ae7286b6889L,0xba1cc09bad2fafecL, + 0xad64ad7a43bb8befL,0xa5af6a0097c3f4c3L,0x2afcb0d9c353a91bL, + 0xca13fcab69ccbf6bL,0x699a1391f2abc190L,0x2dbd554223a247e5L, + 0xe206180f95488d9aL,0xba9e7bff1244cc3cL,0x29297abe87d3a365L, + 0x4054fa38fa4ca5e2L,0xb390623d67be1b6cL,0x1fa67c5778f41a44L, + 0x2e946e43c7b544e7L } }, + /* 111 */ + { { 0x2980fddfc60934aeL,0x2c3e7eff164206d1L,0xf75e7f96416ed75aL, + 0xfac60cf35cd0b2dcL,0xddc4bece1faad87bL,0x753fa87c9849e5ddL, + 0xc5d516a32c1bf1aeL,0x565dbea814732b4bL,0x007ebe3ace48696bL, + 0x40ca74d6cdb97694L,0x3f5cd27065e4e7beL,0x74847c013aac4ebcL, + 0x6762e03443d6c3a1L,0x690d8c95467a076aL,0x768d78d61eda677dL, + 0x0997ce550181d8c2L }, + { 0x9297746c965a0b81L,0x48b58be6e5e12dfaL,0x5573b3c4715f437fL, + 0xe425e907b565c459L,0x4f43f5121582797cL,0xe5dafa6f8ea5474fL, + 0x2aeb8fbe13de04acL,0xed7f95f0e8a07c83L,0x3e012a6e662c09feL, + 0xbf96e9b8c742cf17L,0x8ea5759ae28a1c45L,0x475941b45cf4e2f3L, + 0x7dd3c02df901a019L,0xe7a4deea70916b2eL,0x50b272b52fa9b988L, + 0x96f9f09fd0917fe6L } }, + /* 112 */ + { { 0x78e8aac42c310a96L,0x32a98303f7a2a734L,0xc46ca83d23962207L, + 0xad131e6ed9541280L,0x5791fc5e2cabe911L,0x50cb77eb841b6c68L, + 0xaff93dea3d3c8878L,0x06541f1df1007bceL,0x4ee729c255cdf1fdL, + 0xe0f71317323e3972L,0xa2de7a41ad4d08c1L,0xa9912abfa35e22bfL, + 0xa050122b89b03325L,0x8b9e51f406514d4eL,0x423c7aad79d3e0abL, + 0x71998e2640b8fea5L }, + { 0x40140fcdceb6ed78L,0x653cf37718534516L,0x0450b65ae8d60dccL, + 0xce6c1a769dac55f8L,0x8a96a92dae05686cL,0x2fe4476212712562L, + 0x747bcb50a4f39425L,0xf0ec6ff2fc531fc2L,0xc97c344710fe9ff0L, + 0xfb4887839c792cffL,0x552c5248026fb019L,0x4001a29cd804c290L, + 0x742b5ad835c8ca73L,0xc3781f176ee5dfa0L,0xca6b85f03dfa4ab1L, + 0x8389941a0b0d32acL } }, + /* 113 */ + { { 0xc0f062a2de067dffL,0xd4f32690bcb80162L,0x98cd990d0707a2bdL, + 0x5afc63b8fae4a391L,0x684f1b7bb32ad814L,0xb0a2dce2f199dfb1L, + 0x2260e17f48f25848L,0x7393db00c2d5e862L,0x9e88f854338cf171L, + 0x0067942902acf522L,0x19157cb86835af3dL,0x2faa6f92b8a2614cL, + 0x04ff95f5134ec46cL,0xcf00626efb7a8135L,0x454b3d05b37a4704L, + 0x1fbfda312694ec25L }, + { 0xfdebb657c8f69c77L,0x92a8278ba3df88faL,0x463b5571c1fb78b4L, + 0xd2066a1a11c71a33L,0x10c88143089958b0L,0xb975c7e0cf9d67a6L, + 0xdaa5d20873037b8fL,0x5ee5005d40bf5861L,0x300e6ce77dba69a9L, + 0x893c3cb3c962cc74L,0x0ac986294cf84055L,0x0a7ef63a225c9d70L, + 0xfe184869b91e47e8L,0x1b9d7deb8c2f84beL,0x67788915c0e278bfL, + 0x4f9488cac426f19eL } }, + /* 114 */ + { { 0x610dfcd4dd51b8ceL,0x0857927836230e80L,0xedc7ff1c36599562L, + 0x905ead4be2cae877L,0xa1c325d9e7967608L,0x3e39edddbd38926cL, + 0xda92c8685f6f0a4eL,0xe16f800af47a0fa4L,0x50b4db5be5f60aabL, + 0x3665412f983853d3L,0x64b622509b79789cL,0xea5600584e0e72b2L, + 0xabbd4901e555c2bbL,0x378419a717292e11L,0x6e0b5aaae174218fL, + 0x688e06848f796b92L }, + { 0xcdfef641313b8f64L,0xaef11b7b942c7462L,0x067cfb775c0d8abdL, + 0x608ea5f0af4041a9L,0x23d5bd826935210fL,0x5ab904fc27917a08L, + 0x85dbb1fe45d22d21L,0xc3d5e5094d36159fL,0xaebb528e1d39b8f2L, + 0xdd5ca828f44acef0L,0x24209adf20c57a54L,0x5742b43378f95f44L, + 0xd11fa7d9a9337d37L,0xd66a0c09c64cfdb7L,0x56e55b8f9bb817ecL, + 0x1723c7e3e4c41265L } }, + /* 115 */ + { { 0x9a6486d8dc8b43f3L,0xfc3e0e6126409e68L,0x1889c437d9b46003L, + 0x3a8503356284ec7bL,0x5a3665c46a9dbaeaL,0x7bf6941de978933cL, + 0x1ed5a51069341490L,0x664a7b7a8cb8002dL,0x603f76e460ed0a59L, + 0xc3e06ba31f4ebf27L,0x296ced41f2c38a7fL,0x2ac18f79cf1db08aL, + 0xc919e882cde7a3b6L,0x15e77d29dbf68b06L,0x21978baa4e947cb5L, + 0x84bf542b7630993aL }, + { 0xc1decda9e364f21eL,0x0d6cf345012e557eL,0xba246848588f90e1L, + 0x9f6dda4be3b104b8L,0x6bf7a346e3aef57aL,0x210299fee8327ea9L, + 0xaa99f487da95e6c7L,0x24ff813ed2cdf645L,0xd1dbb2d28bd414b8L, + 0x065101afcafa1a61L,0x7d9f4b9a9cdebda4L,0xaf41b395e41039e4L, + 0xe3e9e6bac50adf42L,0x4f2133ae341e9e49L,0x4968c0f3cb157f23L, + 0x383f827bda068153L } }, + /* 116 */ + { { 0x2ec46a216583ff4cL,0x4e645a294ad709e7L,0xdc66e9cfc04ca12aL, + 0x82f128f49160a7e5L,0xbfb227b1569c762eL,0xf80c7963c2edb8e7L, + 0xa7dafe0649a0f688L,0xb7e417542d14b8ccL,0x3a0c5c5386de40beL, + 0xf0d052861db79331L,0xb902ce69fbfe071bL,0x61e46956210e9903L, + 0xfaef874ef703ebb8L,0xf668947edd5f78b6L,0x6fe865475af5ea3aL, + 0x3b121f1543f94625L }, + { 0x5b26e847659275e9L,0x47581cfd6d0fce50L,0x55f5cbfd8aa3f1efL, + 0x1e7be315e484e60eL,0xd8f1a20ffe9698e4L,0x25d46da97ab04784L, + 0xa526db75834cdb3eL,0x1fd408d98d08a009L,0xfc004b205b5ca816L, + 0x5b3e3bb365e4bbe8L,0xf50cc125759bb6efL,0xf05fa817c2fac737L, + 0x9ee102d2d273951aL,0x2a8e540bfecb3367L,0x673446fb2a6a515fL, + 0x5505e1d137290c83L } }, + /* 117 */ + { { 0x0c3014a1d15e68a6L,0x6f9f0b2664dd35e5L,0x18c3742d03ad67f9L, + 0x74818c0ed2c14484L,0xc51811690d41a3cbL,0x65c8c83fc49f3e9eL, + 0x9b260c612c279386L,0xf6086faeced04e9cL,0xa7b2ccebfd7c4758L, + 0x4b3c313390297fd8L,0xca8264e809701ac8L,0x9f976a87508b3762L, + 0x5d582714983a8dfeL,0x350d2669d9d598e9L,0x85cb89cb0f6fd348L, + 0x617d80d4a574317cL }, + { 0x4cef267e70022b67L,0x80536bb53768b94aL,0x3153a566d2784462L, + 0x49054d4438243919L,0x8d11e1725df78c4aL,0x9b252a71d5a1e35aL, + 0x07866c808171e31dL,0x0a8501db1b38a00eL,0x2ed932b8ce770236L, + 0xa2d776098edaf7d0L,0x3aee5dabb93006e9L,0xfaffc8c4bbfeb036L, + 0x077b96784e21b38bL,0x491fc59fdca8e069L,0x3f624f550e938471L, + 0x5156f5087cd1780bL } }, + /* 118 */ + { { 0x58234e220206e8d0L,0xf5f6f5d47f15af32L,0xafab7289d638950fL, + 0x66ec4d097d4495f4L,0xad890c5d68da80a9L,0xe4aa092064f8a36bL, + 0x799e257e0f4d5c5fL,0x44c677ae24495e31L,0x720387b3a5b8e352L, + 0x703790f475a287b9L,0x54895cc5c3c1f2f7L,0xb8680f9b41a7fa41L, + 0xfcd47458b00b008bL,0x149cc838ba6473cbL,0x78ed5f7aac9be19aL, + 0x5254599cb33765baL }, + { 0x08739679a21b54c4L,0x029ece2ab6497d9dL,0xf14f1a92c8488640L, + 0xae48dcffe9fa79d9L,0x14b911c246c208dbL,0x5ab0fbf2dae3f69eL, + 0x180ac87ed1edb838L,0x146fd718188586bbL,0x210eb6545467cbd0L, + 0xaa2394081667cfeeL,0xdb125c1ab73d1a60L,0xde685300881c1cbeL, + 0xfe34c71337c30232L,0xc6c6070e6f3c8d18L,0x07e365bab4af4e83L, + 0x22f0a7eddcf82b45L } }, + /* 119 */ + { { 0xe262791fea7f1b7fL,0x9c3d8c5ddcff09d4L,0x86c2a9c339c7dc58L, + 0x4dad40174276e8c0L,0x0a918f59e9fe1d56L,0xb8d796702aa810c9L, + 0xeb7a88364aa5cdc4L,0xfc4c23bbe7afa72eL,0x4dbb5c9e4ac86908L, + 0x37e390136a0c7e6fL,0x855d700149c218d2L,0xe475bc6794b324a2L, + 0xc98a8dc66287a071L,0x395a299b5fb4323cL,0xe186c3ee0c0389e9L, + 0x79f81e6f16734c46L }, + { 0x83f2c1f3364f3c4eL,0x536b2ac51367e14bL,0x44a6dcfc5933e43dL, + 0x34e5947510d961feL,0x08234ece7e3f2aaeL,0xcb92e00abdea7f25L, + 0x1efba4f0a791a124L,0xc2086fd21192d53aL,0xfec0d0fcb51c8af6L, + 0x48d1b2cadc0f1b5fL,0xb07a388f812dbe19L,0x40873a6adedbdd45L, + 0xbc2a1268d702589aL,0xbbf6e3a817e27b64L,0x73ee56636d386e85L, + 0x442ecd379de7c000L } }, + /* 120 */ + { { 0xb4cd1ae68a2f90a6L,0xf277d41d6f5ad0ccL,0x6a3828c4401d4b8eL, + 0xe817a134d8376631L,0x142b758df5e1124bL,0x25fbc69dfd6b95e4L, + 0xa30c9f5fd74a9e3eL,0x5ac0f163d89663ceL,0x32a9eef70ce6386dL, + 0x7a690ea5d8ed5544L,0x5de23ff09889427aL,0x75ad36a5eaaced58L, + 0x3514a6c1d3e18465L,0x3d9162c37f093910L,0x5c10add9e33d56e8L, + 0x85176b7306aa691eL }, + { 0xa32110fa28a21e38L,0x97b6379d5773d538L,0xd3697bbf2d020dc4L, + 0x59177593961833cdL,0x6d7045fae5fa8516L,0x3390f29a786ab5d2L, + 0xac0bda30dc4f5b70L,0xcca0240adcc615c6L,0x8e1f1702c5146d91L, + 0xceb472d0a72cef87L,0x848407080b669ba1L,0x79b08f9d7e61aa0aL, + 0x388160be4669560bL,0x23935c2d948eb71eL,0xd7fd83c09431590cL, + 0x8ab154bb6e5768b3L } }, + /* 121 */ + { { 0x28686003353c4a96L,0x4e5c60e8905cd835L,0xbd5913648f66f8ccL, + 0xb6b80b989faccf9eL,0xbc1c1faee32639e5L,0x2f6396d2278aadebL, + 0x00a796d01898202dL,0x18ab548f3a474835L,0xacd056c3b31b0e3eL, + 0x15ba68dd0164512dL,0x203836d94b03f3bcL,0xd64eca6bd8f206c5L, + 0x931a361e9f1779b6L,0xd82690fc52ab34a8L,0x342bb8e092922e22L, + 0x1bfcdd84e00b02a9L }, + { 0x310b9a4375a365d9L,0xd4ade15e08d8fb03L,0x9c9753d7d742df83L, + 0xcf7309d4de318742L,0x1228e2123360ace0L,0x1043d238f7669643L, + 0xfc2adbedf90f5a53L,0x41d64cb77b5f9397L,0x5200b30ac446d010L, + 0xc3c8642d231720feL,0xfcc0122db9aa2075L,0x856e3b12041eae47L, + 0x4586445568c876a4L,0x1a1c7842233606b1L,0x9b766d1f227757bfL, + 0x25b78a3bf7b9d4f1L } }, + /* 122 */ + { { 0x90835718156707ceL,0x9bdc23984314f90aL,0x017c885a8be57dbdL, + 0xd4bba225ad63a4b8L,0x5ce71b8615aacffdL,0x5f26647572954722L, + 0x0a80f1f74f0ad3ddL,0x010538a3fc352ed7L,0xf8a640454203c6caL, + 0x2b2c7a88330c73b4L,0xb3433ee602dcac1bL,0x2e0499cfed2b17c7L, + 0x9f8681a4bd6329c7L,0x3897994636fadc37L,0xdc5650c892b7895bL, + 0x70ab957065a51cf0L }, + { 0x46778ec47b585d93L,0xca6d3610a633fe4eL,0x21da154e4ea0311aL, + 0xaf22190bbd64002fL,0x9e633ac7d91cb7a9L,0xed13c31fee6837d7L, + 0xda4a07d71616ee8aL,0xd78a27323afcd616L,0xc06696e5ba14d694L, + 0x733754d74df58420L,0xe85e504e2778e3c9L,0x3055aa0c55b5a5c2L, + 0x313df5388a3acb5cL,0x5896acb52a088edaL,0xfc8842a084c85ddeL, + 0x5fec9f7951dde6beL } }, + /* 123 */ + { { 0x5ebc2c7cfe519f99L,0xe396bd80e5410353L,0xaded94028a3988f3L, + 0x1c03b735d601bda1L,0xfd30203614ce64acL,0x5837ebe901240290L, + 0xcaaea1a3a554097dL,0xdce73d25b0b88139L,0x35ed412becb090b9L, + 0x99029ff7d63dab3cL,0x555437d9062db071L,0x277d2f5642a4c11dL, + 0x477fa64524fc9109L,0x7b12e9b72799254dL,0x7ad2ae22d84c618cL, + 0x0a8d5663ce8ed195L }, + { 0x43ac51630a21fde1L,0xcfcf5dd66903d849L,0x6d2499ee5fdd6281L, + 0x4dedc6f077a49a34L,0x46bda2c02875c06fL,0xd0e0e0f6347b8046L, + 0x1058169b5e67836fL,0xc961912ade8a8042L,0xdf3fea0aa93b3d32L, + 0x9f138edb0c576bc5L,0x7971ad6ed8d37e47L,0xeab85739cce5e7cbL, + 0x88a4b4341d202b40L,0x5d842557e3a1fd26L,0x872fabd5b3a86f91L, + 0x95b934936aa4629fL } }, + /* 124 */ + { { 0x9998a70199f951deL,0x8fade596f058db45L,0x4d479c1ef3d03dd3L, + 0x6e928d5d33b141d3L,0x9a465800acfe8a40L,0xd108ad2fc1cefa3dL, + 0x64b96921e013726eL,0xb9b6a6b68e83bb9fL,0x29f1e6dc1242e544L, + 0xd3f8f6762f65966bL,0xa34dd0965e105b41L,0xd4e9139a16011e1cL, + 0xeea4dc682515541bL,0x6f8030acc822166dL,0xbdc7ae1d31d16124L, + 0x2e25ef51621afa7dL }, + { 0x2533cf8fdd8e7357L,0x333ba218eaceddb8L,0x68e3e31d0784d2acL, + 0x1c927f36f2804ae2L,0x01433d2277e7ad7eL,0x0b401cf0587f78a0L, + 0x9dfcf036aa0027aeL,0xc9e46c8b1d9a46b5L,0xaa6de4861f288d32L, + 0xdd56da2f1b8a043dL,0x346230e5f2d0bb56L,0x19f0b6e419defb56L, + 0x55ec37cd21d2c874L,0x3dbf0397b70e45b3L,0xf0862a8dac7ce852L, + 0x87979ea7e141f3d6L } }, + /* 125 */ + { { 0x9b7e7b3f7f1c747fL,0x151a4c1dc6e63369L,0x4273ff70b372dba0L, + 0xca6d2234d3ee54feL,0x12fc8e0cd33cae0fL,0x273285385dd6f10cL, + 0xc86f3fbdf01a9cf9L,0x5322677fe36cae91L,0x39a700332fefea44L, + 0x2c9ca328ce8af217L,0xc0256776f6a731f4L,0xc687b3df66a96813L, + 0x194aab128db2eda8L,0xde30dc5aeec4febdL,0xc052236a979241b2L, + 0x3ec98802c23d4c16L }, + { 0x0f9e760c4072f74dL,0xe78eb0deab594059L,0xdb3dea40c9b009c2L, + 0x47e875f038b59ae5L,0xf40eb4362b4daa06L,0x9a6a4f92090f3788L, + 0xefebe9afedbfaf8bL,0xf87f96a59867e256L,0x1e6fed2375ab6aebL, + 0x17f2782a3fdb13cbL,0x5102c71e70fa2621L,0x5d2b06ecfd4c0dbeL, + 0x537cc26830347297L,0x8dbf5e2b2b67e780L,0x2f633f3aba25da32L, + 0x3e9315e8efaec914L } }, + /* 126 */ + { { 0x9255cfa5239a9ea9L,0x20f3c6900be33a62L,0x759eeb4b9cb642bdL, + 0x3316c54600bae718L,0x874a76d5f3410f84L,0x123b502e90f129b6L, + 0xadc8f9a812851f1cL,0xf57b764a1b62408cL,0x116ec01f1a80777bL, + 0x746ecef21f0ddc5cL,0x3c49d47ce5a6a5a7L,0x1e15dbe706e955baL, + 0x629c0c79b45d79b0L,0x11278308778d1087L,0x22585dc78c6a22d7L, + 0x2ed02a0d0a682791L }, + { 0x530434164daa2682L,0x0e26d32b01359625L,0x449c834abd867097L, + 0x11a19d2bee77ae2eL,0x39bd529a3af6c169L,0x36cca5c05cd61054L, + 0x6370a59bdc6c0fe1L,0xca420d27b93d5135L,0xd8730d45554c451aL, + 0xebd258c996cdebf2L,0x0cb1b990a50f9a05L,0x69a8c97a7b0f0151L, + 0x2cc36d3411d217e1L,0xf117688a752f75e8L,0x1db01394a09b2a61L, + 0x14627844a9efd7ddL } }, + /* 127 */ + { { 0x6bca3aed232803cfL,0xc1e4398b9a96ff34L,0xcaf6757f74ab788bL, + 0xc3a53e007e68c04dL,0x5f969c195cb7cd20L,0xf28b65a6dc068bcaL, + 0xe3ca01d31d863032L,0x9b733b8187808e14L,0xb5d704d9efe618beL, + 0x276f3542b01b946dL,0xe057e19efbedddbfL,0x7d182f2b903275ceL, + 0x3cdc5f77880f7bc6L,0xd6f03d3f78476c14L,0x035f5557a9ba5072L, + 0x7acb57b6b4029628L }, + { 0xd241356944e6b07cL,0x451c4cc9e1c7345dL,0x407444d8e273b9fbL, + 0xfe496079b88e34fcL,0x77d184cff152776dL,0x6d1033b9c742299cL, + 0x29a0a68477bf2897L,0x59ffdf10ee8f0420L,0x4e17146c44bb56d6L, + 0x831d06c2fb9ae855L,0xb2cb82dbd93e7cd5L,0x83381c463c96b607L, + 0x06aed2517549e2a8L,0xef97891c774a21d4L,0xae9807c78675fbddL, + 0x6a5a05b96363516cL } }, + /* 128 */ + { { 0x92e71ea66a8f4f33L,0xf2fc6fc64dea8f4aL,0xd356252cfee88461L, + 0x59b0a83e08954d08L,0x5bd68c23468ab766L,0x40281357900f8d04L, + 0x181c19c052b867aeL,0x986a516918764c41L,0xcb01dfae13575d24L, + 0x17269ae5593677b7L,0xf6d1702546dc9b19L,0x8de68499c40097c8L, + 0x76df0032259c407bL,0x4091aad917d29d8bL,0xa7f46d214a7ab5f6L, + 0x688054b470ece48cL }, + { 0xf0d168aa51a5b86cL,0x2437e4d895777247L,0xae844076f1720329L, + 0x0a7ac87d9647a54eL,0x1e597a4b0405622cL,0xedefe5c6f0a79f2fL, + 0xaf3ef0c24d55156dL,0x917fb04eef047cf6L,0x3792799f54b62137L, + 0x875ea32f314be0b8L,0xe157c65b0c466b0cL,0xd28c90ce7e218978L, + 0xb90fc3bacde587afL,0xdd32d71c8b877bedL,0x3b432200ca8e10cdL, + 0x0021f419d94f6e53L } }, + /* 129 */ + { { 0x2191122c43519d26L,0xbdafac1d40a51845L,0xcc6f71e9548bb89fL, + 0x9ef3375c16844bf9L,0xe7789f79178e8d55L,0x04f599b61f8be1c5L, + 0x8088c99a2cbbde40L,0x8939a260893206c9L,0xa1ae4bfffcd30851L, + 0x664cb3fee08feafeL,0x61f38099ff14aabcL,0x0d8394cc2a841ef9L, + 0x75fad8ad17f01db6L,0x6fc345766debb773L,0x1e716b05a4252512L, + 0x7985588029e1ed9fL }, + { 0xa2cb3aaa95106473L,0x95fafa415a61da04L,0xfd3c9362539563c0L, + 0xbaa4809195312b87L,0x6c7e7582bf885c76L,0x70f6dab6230c78d5L, + 0x8ce3051c7747440dL,0x6dbebd14ffdb6186L,0xb0e041fa190e4096L, + 0xba10c4666ee62e2aL,0x93d57e2a74f333d6L,0x006aadc4fe7b9b66L, + 0xfaf72f6c06d2837dL,0x318cc5e6910741eaL,0x9c50260965692477L, + 0x95d823c31d0fb08dL } }, + /* 130 */ + { { 0x6aeebd86140528a5L,0xf268c2ba53979bc8L,0xb1bc9b8a4ec144abL, + 0x1efabb0d82a7d7edL,0xf12c70d14e0118d8L,0x31607168a1c1558eL, + 0x33e428b7e4b7e73eL,0x6317663783aec9ddL,0x5172ffbee12ac35cL, + 0x37df0bfbbc17b2a4L,0x4212f870741f812aL,0x3dcecbdbe2888f9cL, + 0xa9dc15aa756ca55dL,0xf31918ecb9028e41L,0x7ede02856aeadb03L, + 0x0e2708d578654f54L }, + { 0x2270cc53cde20f88L,0x9338272c5f5b1039L,0x5042e19e5dcb1dbfL, + 0x4b3de219b72d74c1L,0x16c49a8b2aaaaa55L,0x008443e5bba86ba6L, + 0xee6bcd7220cf1695L,0x59ffac6ba89abd11L,0x2831217bf115639dL, + 0xe4d28af2f34cba52L,0xf27f03e70727a906L,0x6842c79f69017766L, + 0xcb3469bd7a81123eL,0x48c0f346a42973b8L,0xfc5784a623990dbdL, + 0x0d3dab3bfb299678L } }, + /* 131 */ + { { 0x8f8376e6ce29c3ccL,0xcb0507ecf016cbc6L,0xdebff9965e394ce1L, + 0x24fc526f73c50d41L,0x4edd5a542d16ce3dL,0xbb37bdd991c13141L, + 0xe3442ef2e33a8606L,0x2ae90337c0629da8L,0x57faec64592ab331L, + 0x1a938997d82b857bL,0xad6c8cb9a3373176L,0x82595de29086751fL, + 0xa81e97fb18c17196L,0xe4f48a13bf697357L,0xa1387c2e5cb89f69L, + 0x530b4eeb5874b426L }, + { 0xe9f275a1bab7b5aeL,0xbb69dc4d03a57bf4L,0xc974dc4aa45c505bL, + 0x726369f3416ac402L,0x735e4e78aed985dcL,0x0548d879cdd446a1L, + 0x84ceb0699e16b02aL,0xf73f6fa4789b11a6L,0x6aa0c41fb2a4e784L, + 0xb1f7690293a9b697L,0x814cce00f03a8ab2L,0x64cb255b844d66c1L, + 0xb794e7d630952201L,0xe052d4e43da32271L,0x5278b2e708b6a4d9L, + 0x9094255280c6577fL } }, + /* 132 */ + { { 0xd269a14d0d5b4c2fL,0x2b8fc59b5c8a649cL,0x95becb3ab0e37d4aL, + 0xfda1a7689111037eL,0x5810e05a94e35322L,0xa24dcc12a178fafcL, + 0x5c2c63b28e3dce62L,0x995c3f179452c444L,0x35330ec342d45161L, + 0xa025a60ab4ef8129L,0x854932528bae9c13L,0x25d1a606e2e3caf8L, + 0xd44091ab3649bf47L,0xc7d0afbf704ec5f1L,0x27bd1d62bd8b3333L, + 0x50570111cfe616f5L }, + { 0xd0084acef534356bL,0x9df1de054b4b0fbcL,0x021afe05cee04dc1L, + 0x64bde688361b78e1L,0xa324fcc7ef78d38bL,0xfeb372ceeb0a5e4eL, + 0xef04fcb365811996L,0x7dce5d505eb0ab4eL,0x1e29b588238c586eL, + 0xde5e3197bcd80037L,0x8bf5e4514806b9cfL,0x4330968bd18e67abL, + 0x26a7d04ef9f63fadL,0xa1c7f123b5c18bb4L,0x485b848225dce22cL, + 0x8ff0b36fd540e79fL } }, + /* 133 */ + { { 0x99f2e2f43ff42cffL,0xa3c19f9d1c35317cL,0xdb749392aba1b545L, + 0x84232b054afa9a32L,0x0b855d46d7dcd436L,0x8ac35e2045cf9915L, + 0xd7cf22c7f001a218L,0x057d35aeed408305L,0x25a4a519553ccfcdL, + 0x5e56579393e2b939L,0xa20332b03422ec27L,0x9b09005e3ac53958L, + 0x628051a379e9b163L,0xb4a0dc09fc6618d6L,0x9e0e857f6748e7afL, + 0x71b28eeec577d63eL }, + { 0x4942b0cd99726bf8L,0x1290a3b91c208f3cL,0xfd7290e7b0598eaaL, + 0xc6a7791fa25a9128L,0x2d33db24c037d7daL,0xc21efeb070e2837bL, + 0xbf70d96ee3dae2a0L,0x43ed819185076027L,0x4aeb0aa84d4ad7e3L, + 0xbc75101fe8c5b74cL,0xdbfb2a6ead26ebddL,0xba8120686b78aa4eL, + 0xc94aa8f2e1159848L,0x0d10d9db3eba5c4eL,0xce7fec476318295aL, + 0x7294711a330d925aL } }, + /* 134 */ + { { 0xfce4590432bbd495L,0x330f4dd1be54973fL,0x006bee1d5d9c3f4eL, + 0x40ee607859ba7204L,0xc194fd3f42c2c768L,0xa0e76b12e9fe88beL, + 0x17cddddbec2b0210L,0x689d436b00811ec7L,0xa6a6ba37284be9e4L, + 0xabc395b2007d4114L,0xf8cdf9f30f11e744L,0xc5febec8e9396402L, + 0x8a751743eeb46285L,0x99bf8782c6e0d137L,0x3965e170beb292e3L, + 0x001c39d85801fd5fL }, + { 0xf4805cb9da4a0912L,0xd27cb76a4410bca4L,0xef3dcb8eec71d65bL, + 0x780fbb2b4816849aL,0xef6a7026a8b24635L,0x15625c8812c44e68L, + 0x624c232c4d7a74a8L,0x81a770374b1631e4L,0x04e4f7f1db917c2eL, + 0x1d0465fd1f61ed95L,0xb1048049cbde6e3dL,0x637ce0c1d7131fcfL, + 0x22e4dbc28ada4715L,0xf7530c5cace99726L,0xa0160dccee287450L, + 0x9132e670bb91af13L } }, + /* 135 */ + { { 0x8057efe27996099dL,0xb72344dba06e608cL,0xeb4a8740d0958588L, + 0xe53daf0679e5aee9L,0xc9560a9a908a2fadL,0x7f4be131107e706aL, + 0x6d5f3d9b2830246aL,0xa5f8e8da27cca3e6L,0xeb51dca64c28f292L, + 0x4cfa310ef31dfd78L,0x92e0c7c22ca073e5L,0x102f1694a40da683L, + 0x16bb07cc750d38fcL,0x703e83e2badae035L,0xea93c066b4d3c9ddL, + 0x7d0b03e579940ed1L }, + { 0x5fe7ea304dd94c63L,0x57ef01c5738b0b3aL,0x9534a78ca14e6b4bL, + 0x07622cdea5353276L,0xaf696a077c22d006L,0x733c18867d46b209L, + 0x9654ccbb626c2b4aL,0xa098d3a1a84f3c4cL,0x3596f9ed2d734b74L, + 0xdfd3021a5d551c90L,0xe2ba7d2f1ec5123fL,0xf9726925b2c1aa39L, + 0xd2e75d0ef8eb2927L,0xfaba712e19192a6fL,0xa606b43a9b83e50eL, + 0x31b1782fdab5de60L } }, + /* 136 */ + { { 0x878dba454034db92L,0xa39779018f34dc4dL,0x8d004f2edf754c33L, + 0xeaa5954acd563a88L,0xa29d6c89bb5ffad1L,0xa8adf655b0d8bdb8L, + 0xf7fb842d8cdbdb47L,0xb72e3a0380d3205bL,0xc335b0b27cac7ca9L, + 0xffc60bcbd8a5475dL,0x736f7719eba4d25fL,0x3d901c380c50fca6L, + 0x1fdacf7b80c01900L,0x75cf658f5681f84dL,0x57a7e6345cefbbc1L, + 0x6fc0fbe53e07ed1fL }, + { 0x496d116bb81b0e5fL,0xd82dd2a52ac853b8L,0x357e22d4327387f0L, + 0x3e332a84ba912c59L,0x8b71c64349d5dcc1L,0x0c982ee9438d85d3L, + 0x90b9553cbf7fcd4eL,0x2cb39bbc38fed5e3L,0xa2c67c9c5ac42903L, + 0xebf21217bf07da55L,0x55ac05ada0b9e4eeL,0x10bb12c28ee9e0c6L, + 0x5cf3aee548bb6e3fL,0x4ae7269c8b046e91L,0xcb266012aa0e553fL, + 0x701935a1a94c8fc8L } }, + /* 137 */ + { { 0xde58d41da4626deaL,0x25ef66ca15b9039fL,0x99a810a43164e65bL, + 0x9fe6daad748cfccfL,0x7ab9a6bd2f142fa9L,0xa4cba1685d471796L, + 0x12d30b366bc3a39bL,0x1f46a5dc8bf45076L,0xb868e5291421ac0eL, + 0x7a68620659bba1c4L,0x2b4b552eda698b90L,0x5039dcd4e5453707L, + 0x42a07a9e9e90165fL,0xa838fff3d7d45dfcL,0x41991e5a3b5ceb30L, + 0x6c961ec8969ca600L }, + { 0x703bdc1bc4e7eb46L,0xd6bac557596c7b48L,0x4f9917cd66afd74dL, + 0x56355105656ce6f3L,0x3d1fb50c32497175L,0xfda6783e63effb2dL, + 0xbd79f1f3eefaa2bdL,0xa4efbe5417af9ef7L,0x6cef64625a55b7a4L, + 0x116f32381a713304L,0xdb2a2a7fb95625a3L,0x6a0aa43a0b027e96L, + 0x458fe5d24832b3bcL,0x523418df5adfaac0L,0xc05a89cbc49e7f9aL, + 0x830883d869e24b53L } }, + /* 138 */ + { { 0x959b1c6202557389L,0x5fe5ce97adefc0bcL,0x893bbe7f8330f383L, + 0x27e0c6af16cfb81eL,0x6f64e65bd04428fdL,0x53de9245b79e6182L, + 0x08a313c1487e11caL,0x65cec3b9445bce93L,0x33bc0314d67ed49eL, + 0x69f36b2430782352L,0xd78e5daf93ad31d2L,0xf2682b70c780890cL, + 0x7015c34f9e45efe9L,0x135d4ba4e6cbafeaL,0x43a378a47e3fcc6cL, + 0x2376f97f96638f8cL }, + { 0x0a6e1ec0ae575b99L,0x7e14cb4f81b970dcL,0xf00a3824d3a73947L, + 0x0b4b9c81fb235a9dL,0x8d15115f5bf62944L,0xcfd35b431e165d7aL, + 0x5d12fea2b2ee3e3bL,0x629984a6f5182e7bL,0x4e43e2f3c365d08eL, + 0x9932709130f36e72L,0x698b4a00fd345401L,0x23c4fd0ebaf96dceL, + 0xa60ba0ae23675554L,0x51bdac2db0325784L,0x8ab4190a215464a1L, + 0x8c4616616bf10296L } }, + /* 139 */ + { { 0xeffca2582d1f36a5L,0x0eded2b2894c5f2dL,0x35a5cdb843ced84fL, + 0x290f8982db0e3b9bL,0xcce0eaf00719a112L,0xd0e657e439a362d6L, + 0x5516a55d62697e47L,0x269e1f778e636514L,0x5e3dedcbd50269bcL, + 0xecec2300441c57c5L,0xdb83f31cc705578dL,0x1bdefb731e489eabL, + 0x20b678cf395fcdb4L,0x908cf91cff9db001L,0xcbebc6f455f52cc8L, + 0x155ea622b4c61162L }, + { 0x94be2f1f876fa42eL,0xab5e87497fadeee7L,0x692e70f538c865afL, + 0x16e99b84df8059b0L,0x0ceb606e8b5a7ac9L,0xced233572d463d2bL, + 0x2d0f26232a9a09a0L,0x2529998c3861fbdfL,0x711888a7c1be310bL, + 0x9b1229c50d8aade3L,0xdbcf9b783b13533dL,0x3ca746f8ff029708L, + 0xa5a013a1da83ef88L,0x8e904d184ab28444L,0x2fe84b3dbcbd4abaL, + 0x8f570f24259058c3L } }, + /* 140 */ + { { 0xdeb66c8a2ca9c508L,0x2dc5bec269d6b780L,0x16d6126688ead600L, + 0x61841b9749d72614L,0x41e40e6cce472e6fL,0xada242641fa7a876L, + 0x45b9fd33cc3997a0L,0xb25e8fa97c15dcf4L,0x0124ceb212e9629dL, + 0x3a8c72c67db3d956L,0x8e2ded2b7c1a7844L,0x94ab09c66dd027ffL, + 0xf89a057d7e7a2bc6L,0xad8bf226cf70c763L,0x4cb268e7c8a26212L, + 0x3d171e87b2c44c1dL }, + { 0x382ac16e8ce49820L,0x24ee45e2c0c44dc9L,0x0ec6791273e858c4L, + 0x918cb25c46327cf9L,0x43e3876bc6159c1fL,0xb6b6e0e037545cb3L, + 0x64b839ab5d12347eL,0x72e09274a300d541L,0x26ab28e6881c1169L, + 0x4a580fffeb75a843L,0x0a5802ca359120dfL,0x7fee82d03209f4a3L, + 0xb518016b8e6a9380L,0xb99c6c70c2ee11caL,0x16105af1ab9d4ec7L, + 0x234e98f834cd9004L } }, + /* 141 */ + { { 0xff43520814db9cdaL,0x99cfdc4796adec90L,0x843aaa6faf458b6dL, + 0x3f1f7415743eaa31L,0x915e192e61735d81L,0x3441a22d0ac595d5L, + 0x704bbf67c044bc8dL,0x2f960471be23a236L,0xcc32638815d1d557L, + 0x9410230b76b1dd94L,0xf2e5439f0c1c8a67L,0x56b141ac833c910dL, + 0x467c999f865b84dfL,0x1b0251fa21f02b7bL,0xde5b526096216950L, + 0x6a2130e3ce3a1e93L }, + { 0xd21b67a04b3ca1a7L,0xaf42ed5300c0ce80L,0x22ccd368932cf07aL, + 0x36523a815c25c35aL,0xecdd39588dd04d06L,0x73da3502b2f93a3bL, + 0x4c5e0c3cd5e5b530L,0xef9f548613268777L,0xed87fefc1e742292L, + 0x6d9ac29ea24e5edeL,0x08abc9f033849f1aL,0xb09b229240f23905L, + 0x6791072c7f934353L,0x102a6381e6aeb550L,0x3ee0740996feb870L, + 0x34f06faa9c4d2830L } }, + /* 142 */ + { { 0x869dc79f2348f005L,0x9b5c5d71df4920b1L,0xfd1b57ca6dee64a4L, + 0x21b7f734e82a4fb4L,0x637cb834b9578366L,0xc934101b7d287d96L, + 0x1590f8ac0392ecabL,0x280dc3737f75f4e3L,0x8b36f50f6a61ac62L, + 0x74f58304a65568daL,0x80d792a9d930870aL,0x6d17b192fc8895ccL, + 0x498392fa4914939fL,0xaf36027dd41d5b9eL,0x452d79e25caa82b5L, + 0x764d47b1f4115d1aL }, + { 0x5df22303a2ee8b9cL,0x1b9f72d385dfcd48L,0x6b42b98310813a37L, + 0xe28c523b3de741f5L,0x0857625af303bb5bL,0x926f299aac9bf9afL, + 0x21beac080d445b34L,0x6a523a02d6ba2c0eL,0xe302a1b17fce2864L, + 0x4516a235e300c1eaL,0x4543736a7b4a9311L,0xd3c0b9e8c0cc89f7L, + 0x0481904f40ed88deL,0x4f269b563cb7fc70L,0x09a1d53a321b9738L, + 0x1c0dd9c3230a3810L } }, + /* 143 */ + { { 0xffaa1f67c46a7d9aL,0x64743334bedf91ccL,0x45833a7447a42f2eL, + 0x67980051241ffaa9L,0x70979a84335efe6bL,0x5f0613f5f08b2403L, + 0x6bb22fcd64f211dcL,0xe1b8b2a3a0572cfcL,0x19e0eb417950a14aL, + 0xe634bb293eb6cd4cL,0x31a04b25470a25ffL,0xa41f7ac9a3d15a0aL, + 0xefed85ecbf2fede9L,0x1f581f5f81b94a00L,0xaa3996b09ef4a15cL, + 0x52d8be39b06041bcL }, + { 0xbd1536f6fd631a2fL,0x91fae7f0b351a8dcL,0xd1a590c79b126212L, + 0x52d4875f2bd0f435L,0x9aedb6d392b0ea70L,0x0bd0abdcb83ab89eL, + 0x827a106289fe192cL,0x6566a960102a0bdaL,0xda083037ce036814L, + 0x30bed79f58639405L,0x972019b6dbca8df9L,0x89201286efdaa3f5L, + 0xb337b9965236b892L,0x11d3e38e28fc2e73L,0x70787f41880e8da3L, + 0x6cff6367dae4a45dL } }, + /* 144 */ + { { 0xbd3d0433f89a8bb4L,0x42144c3393b98f71L,0x82b616c803470a2dL, + 0x98fcc757e5da089eL,0x542354ef7bf5fda6L,0x1885c2539ebd34ccL, + 0x2e20b285bec5dd0dL,0xe71bbbe1782a1bcaL,0x959ded309b854ef0L, + 0x172499798997fa6aL,0x50cf8fa8d81f3c45L,0xa9a3b51760c11152L, + 0xc9b0ef7decf845eaL,0xc9339e23b9fed11bL,0xc93e9c5c28256080L, + 0x1d2c8217613ec1e7L }, + { 0x7381347d987cfc93L,0x047603bbf187f810L,0x3fa6bc9d1250ca31L, + 0x480091e0bb055bf3L,0xbdf95f1a3a3af87cL,0xe2687770140540abL, + 0x998df730d7fe045bL,0xb398135fb723bc2dL,0xac230f8c15ebec46L, + 0xe08e18305f5561c0L,0x7c0fbf4cda60a47fL,0x06e95c24e16d4bfcL, + 0x7416349574617e92L,0x397198694ae0c20eL,0xfe2693122131e2b6L, + 0x25486e360a537722L } }, + /* 145 */ + { { 0x618795ca53572806L,0xb2c89449656968e1L,0x149c2c973fb323aeL, + 0xfb15de26409bc7d6L,0xa90cda72c79121b3L,0x6d2fa14e204cabbbL, + 0xcbcda6f791604125L,0x25086261b435f947L,0xdb686c38c282eb10L, + 0x51016d62f1a791cbL,0x6b1c7ed161a2266cL,0x26780666271d74a6L, + 0xb5ffeda1824287a4L,0xcbe503ffbbe4f0f3L,0xd7f7f0beb9482a74L, + 0x751b2358088493f1L }, + { 0xd597b9d6e9c9be68L,0x1794b5c467d10c6cL,0xa88cdc3d7762b2f4L, + 0x6d94a63aa1b44e11L,0xfb0bbbb9aaa8eca8L,0xf4b0f2d0c963d87fL, + 0xb753062c5dc7075dL,0xfed726ac49933989L,0x5da6063857f9ccdeL, + 0x221c392a75f8c766L,0xcd264d955dc672caL,0x7004ff22b66ecc8dL, + 0xfb1aa9ae18a458baL,0xea9644df8babd653L,0xa9378e802ba0de7cL, + 0x144cc12dca2c6c75L } }, + /* 146 */ + { { 0x593a0a1d2989aa3aL,0xd83f228359e6e64dL,0xe938b0cbd32e732eL, + 0xf4c464c53c3cb249L,0x9750a5f8f89ea6acL,0x467e5bbf346cfc32L, + 0xc9bfab9d37b2b809L,0xf8eb74533b339c6dL,0x3fe01fbe3b766deeL, + 0xb3154254ef6aea27L,0x555c3df27be61b10L,0x70fb6d81dd818488L, + 0xda1af3a4bbe714f9L,0x575f20179d18f693L,0xdc08fc6b2465b839L, + 0x874ecf336b84a951L }, + { 0x624af83ebbb3f6beL,0xf578fbb908bb423dL,0x5623b0bad7873527L, + 0xc3659bd8a62e0442L,0x2903b167fe236f79L,0x55a430c6e53f26a6L, + 0x222547ae3ad712cfL,0xb73890d776eb272bL,0x95b4f70b3d628df9L, + 0x9f0e13b053eae4acL,0x5b4f5138e7f2174eL,0x75482cf998dbae17L, + 0x2b69bbde44518480L,0x4f279652cafef15cL,0xa0a3ef2bb6bcaf19L, + 0x31fb8581ce4c634fL } }, + /* 147 */ + { { 0x398306d1615cd607L,0x680c9faaaa32c3a6L,0xe87a705b7779131dL, + 0x1031013a36708b00L,0x814fa0e19445297fL,0x70c5583aa6a79b56L, + 0x03039cbf4b16bed4L,0x18a7ca8daaaaf8d3L,0xf33159e75cdb68a5L, + 0xdea0e738d23814faL,0xeb3527188d0f4f9fL,0xb0b76609dcdff032L, + 0x65ba8ea93d48338bL,0x18044d8255dd507aL,0x844a223e4a4a50b4L, + 0x9832300018e19e54L }, + { 0x28a2102757f3d5a6L,0xffce56486e8cadcdL,0x9590381b02551f3bL, + 0xb26cc64f935ebdf1L,0x60611291c083aa6eL,0xcd988a6688e4cf41L, + 0x581c3f73dd53b1b5L,0x78c804a977fc621dL,0x31874330fadca2faL, + 0xf7008da4c83ccf02L,0xc4122a1da79a4707L,0x9a8e0d3f4a915eb5L, + 0xa2de157dd0123660L,0x45ef43b265ead2a0L,0xd0a22ade188db285L, + 0x8abbe39e922e0caaL } }, + /* 148 */ + { { 0xb44469053a2d2f01L,0xd27c31935dc6685cL,0x6a908bbf1d74a027L, + 0x01da350f5b50ec1dL,0x1d3dd45e3f3c2e26L,0xf66e11d0b836ee92L, + 0x7e03908f474b979cL,0x19e7c5b998b87834L,0xa741d3febd3d1de9L, + 0x63c68e8d1ef6059bL,0x9b9ff9393674e247L,0x1d7d53e73e7e67f6L, + 0x698dc326aee9e248L,0x52f23edab3bd984cL,0xf95e31b06f8fe8a7L, + 0x0f15b4d0c3d0ba95L }, + { 0x8f2f6635790a8d85L,0x51bffbaee2595af1L,0xd15b7ec624b51287L, + 0x7639b6ab3234715dL,0x0cdd52992bc5441dL,0x54800ea4f6d05833L, + 0x21efd752f6d6e360L,0xc0b7ffe519290613L,0xb68a5825eea898cdL, + 0xecedba9222982266L,0x678a91b0bbd06bb2L,0xb2436dc04bb6b0cbL, + 0xcf7a99e7caf8ea98L,0xb92d0e6e71aa05bbL,0xbf8d0471f5993eb1L, + 0x515db37820385ddbL } }, + /* 149 */ + { { 0xee43eaaa6f5bef22L,0x952d269820348712L,0x1e4c484e7a3af6c6L, + 0x18d434c69a8c9403L,0x63e5d7415001899aL,0x5238dbbcfe8ea40cL, + 0xca6cc8d296798721L,0x73db6aee04acbde8L,0xbf69328db7f993ceL, + 0xa3f79bbfad45e334L,0x8c51ec937c1f1630L,0x4907325f9b00a6deL, + 0x49e6acb412d82bc3L,0x5901b36d0ec59fc9L,0xcb09b7109cf34e3bL, + 0x2de0487e1abf4c02L }, + { 0x18b722f38dd9d484L,0x833493937c77baccL,0x58dbb8f193d92b8aL, + 0x80d78d508e3fac25L,0xf0500981745f4a7dL,0xd072bfed877cc29dL, + 0x67abf8f2c30a89f8L,0x92c567ea9a0820d7L,0x425ab12e8a3a5738L, + 0xc162faebf055521bL,0xee1c4f26b94ea5e9L,0x1e4149943d71e546L, + 0x258183b843e8be1dL,0x44917c82ef9eae0bL,0x6813a45773874a30L, + 0x6f6ac071cc42f86eL } }, + /* 150 */ + { { 0xd38822ad4dd6e3b1L,0xfc78e1ccad620869L,0xe78438452cacde80L, + 0x121cc14aa8469fe3L,0x8e8f3da7e67e8ef2L,0xdb83d16e4d347448L, + 0x3ba1dd98798631f4L,0xdfab59770a4c4c17L,0x1f0a13063edc701fL, + 0x4649d6016cd8ff28L,0x2267230bbcc55bc9L,0x02a19c605760412aL, + 0xc719d5f1328faef6L,0x27cb969ef67eaad9L,0xf342530e719bafb5L, + 0x6e2c24ccff5a82cbL }, + { 0x6313024badaf8793L,0x944bccf1035c948eL,0xe9a066b7953500bfL, + 0x7991a9461d116765L,0x95addb2e9fd93c78L,0x05d2c037e92e5495L, + 0xcb145b189f03e5cfL,0x81ae48ca95aa1f72L,0x203f2702135a6e4fL, + 0x2bcef5a249b2a7d5L,0x0687a90002d7f2a3L,0x2f7d32286c6745b0L, + 0x3da8a87586507305L,0xbe38b8842e8dc58fL,0x6b48bf34dbf11185L, + 0x5af7fd0d97c08f91L } }, + /* 151 */ + { { 0x55f9b950f4a224a5L,0x41904574cc50273aL,0x34f81330643f1fd5L, + 0x996801bb0e50f783L,0x866d740389581712L,0xdb9a405da4091d36L, + 0xf1e379df16a46fe7L,0x8d04a93f83bf9168L,0xae4c833532b20bcaL, + 0x99d334b1f72a1c10L,0x8fbc9977d8195db4L,0xcaeb3dfffba14b5dL, + 0x60fef02276daf476L,0x4b948dfedb5b72f4L,0x5185c925b6dfb062L, + 0x27a9c3819609d4aeL }, + { 0x73c37346f12a93afL,0x028b707c5536634dL,0x8efa58d5498193d1L, + 0x4f83a5ccef21b69dL,0x05cbb0a3a788a0e2L,0x0103178165b13c98L, + 0xfea20e582b73784cL,0xdf9713a0e50361f2L,0x31449a0fd0cc22d9L, + 0x183752e77c5e2e1bL,0x6e44d6bdb67044cfL,0x012dde95733e177aL, + 0x68b4966908ee2c23L,0xd9bb05411f5f1949L,0x95182c716acd886fL, + 0x1c690694fbde9244L } }, + /* 152 */ + { { 0x5db67d173a880026L,0x89c4f0a0125d95f2L,0x290505513f6cb7a4L, + 0x3eb231d15cbbdca5L,0xf8cffc99972bcbd3L,0xcb4ef4d4ad55a03aL, + 0x944d47ca22867c2fL,0x96d885480ead1aa5L,0x76a57cf8cbc8b045L, + 0xdfe5844b005e55a0L,0x5e9e7e191d18a097L,0x957a26e852923c74L, + 0xd0867b797f5db339L,0x2553408e63bed0c8L,0x1596e5d5689ad23cL, + 0x7b8c13d6a504c339L }, + { 0x2fc43aad52fb6901L,0x1c0313f916ca253bL,0x1475830a515aadc6L, + 0xc93d19267f577dc2L,0x26e52e8ef723c0ddL,0x2f1e0eb83eb9f6daL, + 0x9979de82f180376dL,0x43e28ecbb0834939L,0x9a2d51dca39c38e7L, + 0x6e6063a9a8e3f6b5L,0x4cf1da3a4b9b3270L,0x6e5348a2d2f8915dL, + 0x5e75e3e050507912L,0xaeffce5720d383faL,0x1d6d53cc8fd2fb29L, + 0x0e3c3ef6696f4cd0L } }, + /* 153 */ + { { 0x3bc337c121ee1d83L,0x97e08f6d787b7788L,0xbf709fcc138fa4ceL, + 0xbaf77647a0348e58L,0x04f8babca55e672dL,0x0ed2919d7d5ec5ddL, + 0x8ce64bff33e99218L,0xac09fc5724b059afL,0x506831f9dc5e32baL, + 0x26a22677465af6a9L,0x3c5efe66c97f1ff8L,0x1515e0d6bc6087fdL, + 0xb1a39c5eaa8edc6bL,0x3dd816bb0e79ed29L,0x6cc13769bc3788b8L, + 0x463098e3c092a51cL }, + { 0x3a6408c7c8bd0fa7L,0xd1764311ce6bde49L,0xe315e108283ef7beL, + 0x8213cc7799b5d938L,0xaf7f158145a49a6bL,0xd00fdb0fe529e4d1L, + 0x55d38f77ce66c9d6L,0xb4f7ccc01bd4b952L,0x8d975b49af71f986L, + 0x12b59fcbcd64d00aL,0x1860e504a5a3bad7L,0x6d9760442b5c89f1L, + 0xfed0c6597a3e231fL,0x58114c33178cba92L,0xe2e74c066698e11eL, + 0x7f8fd093a348b85aL } }, + /* 154 */ + { { 0xf24592cac19428afL,0x192a1c813a308665L,0x42589812e30bbd7fL, + 0x10db0723836c6bb9L,0x9c7a41e9598e4987L,0x8aff179e6ead6f4bL, + 0x70f8f9b975862c44L,0x6b3b02376f21983eL,0x25d83e9b98e65152L, + 0x3b2d26a8d751218aL,0x9508281a9d6f1da6L,0x8df78d05a5a81f74L, + 0xd79ee559e4687471L,0x2060ca576787d8ccL,0x427a84ffa8476c95L, + 0x87b64c51e6435131L }, + { 0x87f46f654b30d3c4L,0xcdec4c5c23b4ef14L,0xb3b7476663ca4d68L, + 0x1df34269cf3fb56dL,0xd4f139c40fd7d46aL,0xa3b7c7c76a69a8bdL, + 0xee56b4c9cbadd7d2L,0xb28ff342ac942334L,0x0046fdfa786f1da3L, + 0xce5d149cb700c82eL,0xca30ef8150966597L,0x44a20609fcff4bddL, + 0x0f2f65e744925268L,0xe5b6552cd4021f38L,0x77ea9c2a042dbbd0L, + 0x8c95267cd9c062f5L } }, + /* 155 */ + { { 0x6655032e5fc1abb1L,0x2215af5412fe4743L,0xfd65756029f05ef5L, + 0xb0e73325dc191be9L,0x7ab3c65ec08639b0L,0x67507f511c3e6673L, + 0x638befc3c8615555L,0x5d0188cf42f0c4adL,0x843a301cd896186dL, + 0x045603f7b2c6741eL,0xf7545c0cfa3cd1d0L,0xf612affd4a40672eL, + 0x56197c9f45b9e8ddL,0xb453237d87922d74L,0xbf132e3a4b2d59bfL, + 0x8afa1b73b84a6a16L }, + { 0x6b3596eae793ac70L,0x4c94ef8eeef6dd10L,0x926b4fa270422e40L, + 0xc8c71dcee9e5d763L,0x352fcb70f512aadfL,0x1b7ba138a883975fL, + 0x57991390058c3b13L,0x9692092a97740fd1L,0x19ad945b160b0697L, + 0xbc63438810837ab2L,0x76ee11c4f174bb71L,0x6111bfc1ab1b80ebL, + 0xbc82bac870ec458aL,0xeee60127312d3325L,0xb4118b1ab240adc8L, + 0x672111912b5a093cL } }, + /* 156 */ + { { 0x91e99306f55cf9bfL,0x9b045308a46b96d9L,0xae3c1e1d9e7a65dfL, + 0x453cb151c731bcbbL,0x14be5227a4d58a61L,0x39dac92297c74cc2L, + 0x4d0f7a45822e00d6L,0xafeb1d51c62b03dfL,0xbb1dc3a4baa18b2dL, + 0x7f3c7178df2b74f0L,0xfcd328a6896b6a33L,0xe95ed4541dce055fL, + 0x97fbc76b6a4e2b87L,0xe5ec67f1fa59dce9L,0x052368accc0367c1L, + 0x7c86391654e4a3feL }, + { 0x55e94b5eca7388cfL,0x17cc0a60c0335d38L,0x9b69b78b616f85baL, + 0x705d02ef10122980L,0x565a6e801cfd0a79L,0xeb74a96d7d1ee352L, + 0x5c8832ed427b9dadL,0x96ea8528e6d5330fL,0x30d8862b18d24ee8L, + 0x9cd38ed59ff939f7L,0x690fc9a201060252L,0xc62d88b82303b3ffL, + 0xfc42d7a4dd52b469L,0x06f8dfa28cad2d93L,0x5023609060920438L, + 0x32582758fce855adL } }, + /* 157 */ + { { 0xeb20e45f359e8c60L,0xc71bb8a5364ca186L,0x02b15071dff8e110L, + 0x074e91d34c93e578L,0xc0326e00b829d0d8L,0x3c192258626a83faL, + 0x387a64d5fb29a09eL,0xcaaa3d34e5ac5c82L,0x8ed685e5ada2da29L, + 0x92720267eb29650eL,0xf7184b19763802f3L,0x23f5dd0edf6b1aeaL, + 0xbe1fa34725e6125dL,0xd6287f9d0c872a1aL,0x49aa93d2ac57c3afL, + 0x1a4e6a715bda7656L }, + { 0x1a126ede554d1267L,0x37f945331cd02b48L,0xd70af04cce31fb1dL, + 0xcf410b0b097dc012L,0x930e1d1736c7b6c5L,0x902fee41c6891085L, + 0x349ba4a779fb638fL,0xa16c5821acd6f8dfL,0xfb3b83c12e076aceL, + 0x6b8d033be501d14dL,0x0593d45220f2d2daL,0x3752526d99df1880L, + 0xca32351c9feb33a6L,0xd91343bc1f6ef456L,0xc74857db35b9dc8aL, + 0x856a7c9385b4e832L } }, + /* 158 */ + { { 0xa007d0020d0a5583L,0x2f1301ddeda4658aL,0x91c0796434d939beL, + 0xa0cb6780a70c0836L,0xc0b4df95be81e540L,0x6cbbcd345d4ac8b8L, + 0x57c52ed054756239L,0xcac2dca41805ceb6L,0x915ee6ab79344255L, + 0x366def3124c9a2a6L,0xbd3b962f8c12c674L,0xaab64f1b7dbb7c3bL, + 0x3c0e4553e22bb95bL,0x2408febac4c63b74L,0x3ca773122a4da631L, + 0x62889084c636da40L }, + { 0xa457fd538cb8d208L,0x7a8f8009543f06d4L,0xb66de154f2eff2abL, + 0xfddb28ebf72517e7L,0x0149fe66f9389d2cL,0x79e8773fd85b88ceL, + 0x452e090b0ba543f7L,0xdeb9b5cfb0b03fc0L,0x3113448a6c5ed77bL, + 0x3609f3cf8ffc0372L,0x2bc9c46d5c1b4c4aL,0xe66f3bf38fa59be9L, + 0x1396bf5fcdb02691L,0xf1ec59d4009f88f9L,0xc29034562ad9dfe3L, + 0x79d8122c5ada4d58L } }, + /* 159 */ + { { 0x14d4e4ceaa529507L,0x056a081474655d00L,0xc0d30a384f0fc474L, + 0x8a8203ea3443cb8eL,0x33c62fb097f1728dL,0x8a38dcfdb520ef52L, + 0xa0f90d5d7cac9d3eL,0x28a7b0bf873cea50L,0xd115ae3a6c6c41cbL, + 0xa35171daa13812c1L,0x25d4bba5624d507eL,0x91dad2897e98f42fL, + 0xffd6b1e996a41371L,0xd46c2125b69e5b77L,0xc7d2b42420c4f707L, + 0x2ab3af958142557aL }, + { 0x86ca074c6a5372a6L,0x728fb83e56292ba7L,0x745596dc77741cf5L, + 0x70b4cea1520ef49dL,0x1472fe3461e46472L,0xf4d6bd663fb8ac5dL, + 0x46e52cc9c10bc071L,0x28794efe371a3461L,0xa4850718276fe877L, + 0xedad57739bef5ab4L,0x24c2d9ff3f15c815L,0x188950e58f8395c3L, + 0xbae4099680b6a855L,0x4f53e22c8a8803e1L,0xaf233f61039d25eeL, + 0x07db2c35250409caL } }, + /* 160 */ + { { 0xc7f3b8db037d4703L,0xe83708dfc5f488b9L,0x1fba830f8471d402L, + 0xa55ee8d25a2faae9L,0xc2e5bf105404fc1eL,0x647d5027aa2d5651L, + 0x37a53c0c7ebaf5f9L,0x7adf0bb295b30abfL,0x5a62e1fed64c93baL, + 0x7ffc18c0e2ef4a78L,0x139dd9d94d2cd04fL,0x253fbab75ea0af02L, + 0x7c8100ea0fef9acfL,0x74c5384dc8615aa7L,0xcb28682d9fe52069L, + 0x08b6ca8fcf7dd759L }, + { 0xe04e5bea036c3b5aL,0x387261027f9f2b4bL,0xa9fca57029797c0fL, + 0x1656180b82879ea3L,0x153389bb607f0ddfL,0x99a1223c67b0e087L, + 0x0d1808ec9d897fc7L,0x9470711a916edf19L,0xf8f52f2b07217118L, + 0x5d8b29ffd18888b6L,0xef1e22c54cc6f900L,0xc4036165eb24877fL, + 0xfda9523335479525L,0xd622a4216861468aL,0x5d043b0774faba08L, + 0x2c337b020d31a7d2L } }, + /* 161 */ + { { 0x7b2305bcea22fa65L,0xbe183ef4d159f63aL,0x3473d87d3f35923fL, + 0xb27fb306c11d7753L,0x702e7e6b2a054cffL,0x3ce9f97caf185619L, + 0x835502434e7d51c5L,0xa63e3d82f356ac5bL,0x867b7caad7645131L, + 0xee85e6afa671fc9dL,0x3b985ede2b07cd77L,0x07d598b0ffda5193L, + 0xb10eca39a942dc36L,0x17f3dcee506218a9L,0x3d94e8d106b7d5caL, + 0x509b2634ed8831c9L }, + { 0xb1b9414e48caed54L,0x77a78c6ccbf51e97L,0xa4688c8d4de9b258L, + 0x0024137c91ee3d78L,0xa68f9234e30ee64cL,0x573255bc88190d78L, + 0x41e8e05fba80690bL,0x50038d84ec354f4cL,0xb18f02d6dfa52816L, + 0xc47f9007ccb63fdaL,0x29d480fbe98ae455L,0x4ac45d225d0e319dL, + 0xd06f3575026db719L,0x733b9e202c3587b9L,0x224839922c317727L, + 0x1592d5a754bb8752L } }, + /* 162 */ + { { 0x5778d9a2cf7453f0L,0xaffb899aed83c1f0L,0xae6506d3e0a82ba7L, + 0x32c84e1aea3d5081L,0x9ad528c0810aa38bL,0xb1fdb020bd37d041L, + 0x78d6cbe1d06ce41fL,0xd287f0f02e74b7f6L,0xf5cd2575c43bb022L, + 0x6d28f2f3f81a71b3L,0xe65bb1f5c633e7f4L,0x32e5fc1cc4fc580eL, + 0xcd55539fbb7b07a5L,0xb5a94471c3caaf3aL,0xb958bdf44cc22d2dL, + 0x1614bdbd77a2777cL }, + { 0x4c1f0230ed0ab04dL,0xae347b006e2082eaL,0x9f10bc63c42c5b5fL, + 0xb0539e6fde019935L,0xd89bd4e765dd0825L,0x92260fefbbceda16L, + 0x8aaa755ce62aca32L,0xed762fa95ec82c5fL,0x99e64c0118650768L, + 0x57dd6245c92e348cL,0x0db88a7731ea6d68L,0xef0012ab07b44736L, + 0xb9356b94171d70feL,0xe68b062803f891b0L,0x3a54a53ab79c20a2L, + 0x489656c7b00b0728L } }, + /* 163 */ + { { 0xe43649ba71353c25L,0x517f27a113f67e24L,0x10bd333a1c1eb9e3L, + 0x94e1c05c78e29bf9L,0x84fe7d974743f15dL,0x9c87490890da2df0L, + 0x82403fa753673be1L,0x7ebf5db41baea1b1L,0xcfe0ae3524180eadL, + 0x1d15873fc2f50c3fL,0x16851ad670661cd9L,0x802968d9a51e8c2cL, + 0xe7d1a9cde0161099L,0x2b153c89a8a7ea56L,0x6d41b78906e3c498L, + 0x082bb2e9d6769dcbL }, + { 0x6180ef46c4d6615fL,0xfc629dc101b9829cL,0xde222ec00fb264caL, + 0xc5457e0610ecc2c4L,0x95ce599f1eea2c4dL,0x0433fa728f9c5b2cL, + 0xee035462cd6310f9L,0x84c57c3bce2e2253L,0x6c8ec31a96d87e44L, + 0x30bfe393a452c5a7L,0xc592b140a047b235L,0x7bd8be18c018545eL, + 0x794e01075c178c46L,0x484719462e23005bL,0x2665e237622a54f3L, + 0x36451a46901c9042L } }, + /* 164 */ + { { 0x17802d1819893e71L,0xa1765d8b539a2082L,0xfc6aea012302ecfcL, + 0x8d4cf51b365bf59dL,0x87741d720d232a80L,0xac343eb318e80427L, + 0x553ecb2fe74739ecL,0xaeca79a81a8b07caL,0x089ff32256f4ab3aL, + 0x5e95d7293fa1d1f7L,0x260569aef62a9a16L,0x5e776232aa08ddc2L, + 0x93fabec31b7bb54aL,0x48a20956743d56e7L,0x749cdb12eb0ebeffL, + 0x705307a469b8fcf1L }, + { 0x7a8e4c04e488310bL,0x12726e325325cd7bL,0x5d0fd8b04983efacL, + 0x796e552c02ddb913L,0x0eeca3f777b9685cL,0x9b766e89b15f24a3L, + 0x7c2736d648efc979L,0x3d619685a8021c6cL,0xfe33e278a0b2f1eaL, + 0x95c69879b676d6b0L,0xa07473191af4e0beL,0xa2fab5f136c4ee55L, + 0x6938b8ff59e5f3b9L,0x1e114da439cafe6eL,0xc9595ec36a6ad120L, + 0x80f79bd057e62aecL } }, + /* 165 */ + { { 0x3cef42a760af09b3L,0x3c016ebd933dfe14L,0x720cf1e0ed85eaa8L, + 0xd4f5e99fceaa3bc9L,0x7216b9d2b7106f97L,0x65f34c36c9668ad2L, + 0xa8fb82bc5b0c651fL,0x20f42f1cf2fda4deL,0xeb31ab2cd21f659eL, + 0xb7a776c7a13d1618L,0xec44102238662be5L,0xc825da70cad08e0bL, + 0x99299079022c0180L,0x7623bda02aef9ffdL,0xde84f4f3f5c58b50L, + 0x5f5a5da4d824ff19L }, + { 0x5737257e7e8311dcL,0xdef94f51466cf136L,0xa73e1645b05ca21aL, + 0x38ea9b3c02e4ab37L,0x7760eac98579165bL,0xdffdd047c24b01a4L, + 0x188d4fd13fb95584L,0xfaac38b825548bdaL,0x1a79a6f059e9dcacL, + 0x983f720f09a2700fL,0x8cbba554fb8a7e48L,0x38a1996847a1fad5L, + 0x118565475abd6b5eL,0x75113d31f3716ec2L,0x1391e7814212907bL, + 0x5319c8010dc15889L } }, + /* 166 */ + { { 0x2320136e6b61c3afL,0x1d40f2de07b4bb68L,0x651dee7f380c97f0L, + 0xa978ba706a8c313aL,0x22c587d62011ca10L,0x48bba218ab1f445bL, + 0x8c5eaf07e50444e6L,0x5549f02a442fccf9L,0x2564746f3d80493dL, + 0x42d24f6179c04591L,0x1600fa18abdc8887L,0x5cb8600aded38f8fL, + 0xa4bf9b90923aeb46L,0xd63fee351e1c578aL,0xf3c9c5acebb9ea14L, + 0x3d13314df11a4ff0L }, + { 0xe5cc662db4513d1eL,0xde78a8c5d55952bdL,0xe8a37a3fe7f86d0aL, + 0xca2d12a47a04f0c5L,0x4c6696e42e25d06cL,0x52614698b2136071L, + 0xf4d2701b89f6e1cbL,0xaafd617780efd95eL,0xe6d73ac4c5bb6907L, + 0x49e874ac420db35aL,0x11631de4f2751fa0L,0xb29f7336a1fa2eddL, + 0x4c406864b7fd794dL,0x73cb21d3e22f92a6L,0xeae904e62043cc76L, + 0x67f28a9fb322c6adL } }, + /* 167 */ + { { 0x7c17b258ca148ab5L,0xb9a1976fb3c60051L,0xea260698c8f28df9L, + 0x87b2cc74e8d45017L,0x372573290578a422L,0x81d5ee2517bec732L, + 0xd7411fcf1d48bbc4L,0x46217e6b487f5cfeL,0xcb007ac541eb8e1bL, + 0xc41c57a6e05a00c8L,0x1f954d2bd2f9fa99L,0x370bd5db40941cadL, + 0xe487879c3829509dL,0x4c1375525ceca5eeL,0xe8ef7fa4fd3efb9eL, + 0x5ff091741bd1bdb2L }, + { 0x791912a4579c6632L,0xbb19a44fb8a20815L,0xf4f97b84535639d3L, + 0xe57e2bcbbc3c9bceL,0x122b3f2bf19e6410L,0x1f0189da1357d9adL, + 0x675573bb79e5ff66L,0x444e5c98ef2f3c4cL,0xd6f61e2004d10731L, + 0x0dfa366fac75d635L,0x9fc47c862c854f23L,0xc04ae43e0ad0850bL, + 0x5ce94f642f720c32L,0x67efae65a753bc9dL,0xc27d30d3b0373a63L, + 0x6681013a29721646L } }, + /* 168 */ + { { 0x1385d913e84509dfL,0xe978beddcf339376L,0x2df425d33423a148L, + 0x43fa0ae3ee8cb579L,0xf015369d31c4553cL,0x05cf08bbdfbf1d48L, + 0xadff4be69444244aL,0x01635f81a35dda33L,0x085c8949e76fab7cL, + 0x4bd7fcde16737783L,0xfd8cb52ca254f8d2L,0x62168a66413ec985L, + 0xf2db97417a9026ccL,0x3962ee5650e1e1b7L,0xbee0a346d3beffdeL, + 0x3b35b72f0bdfab1fL }, + { 0xbff8de9f535c3749L,0x23c1f20f8add9c48L,0xa975b37bc8f8f663L, + 0x2529e475e8f3ae49L,0xc32f10d51d5e2628L,0x5ac0d29767862f1dL, + 0x13c79338854cbe36L,0x48f004ef4b67e462L,0xfa37a150e5d10ee1L, + 0x4974778dd28288a0L,0x96830a66cfb73f4dL,0x9f44401307804952L, + 0x8233c7099760b694L,0x8340cca525b75c99L,0x3f62e40bc771f99cL, + 0x47d0a1ebcd95c685L } }, + /* 169 */ + { { 0x266f4fff652811f1L,0xeaacaa9362ef3002L,0x6c387a5550cba0caL, + 0xa350142a007f5467L,0xc7fd102a202f2673L,0x5daee57033dc6e65L, + 0x60682ec3064a63d9L,0x46cf0bb0462b251eL,0x0e030ca55da936e7L, + 0xc87a60f2434265b5L,0x9637b2bb69b4e8f5L,0x601fb58c7ad7770aL, + 0x1f2147f6ed3a15a6L,0x05b47d5e2995e961L,0xcb0ca9b383213a16L, + 0x8f4b614a4995a85cL }, + { 0x5aa8ec194b4eb3c1L,0x8c549ac420323a70L,0x00d493224f6cc6aaL, + 0x0e53b9bb45f9a5a3L,0xe46ef1100897abbbL,0xfe873e57d7acd7d0L, + 0x7cfccfe50f7cb588L,0x0ea53d65c85557d1L,0xfdd9eb447288f2e2L, + 0xab2dedfac0eb68a8L,0x5822147008603a0cL,0x6946468900feb06cL, + 0x804cf5bf25e5caacL,0xd85598589fc91ae9L,0xed9378b173c45eaeL, + 0x8f942d02524c9801L } }, + /* 170 */ + { { 0x1f1ec3028e845808L,0xc302bffab77abfc5L,0x26afd4b9f8d97dc7L, + 0x3d3a83c43aac594bL,0xe3b74bd1674d94dcL,0x4464b737caa5911cL, + 0x62925773871c2cd2L,0x419f24853b4440feL,0xdda6a0f3e052ad7dL, + 0x645280d6846c86c0L,0xa25689faf8324f42L,0xc74ad1e807cf117aL, + 0x5626dea08ddc9db7L,0x52620373966fc85dL,0xe0ad57c3f3b1eb53L, + 0x38300252949c1acbL }, + { 0xa0ef5a405e744723L,0xdb5bcf751ae08481L,0xabfad8ccfec1f76fL, + 0xfba5d831fab37fc6L,0xbe39e248c8fedb78L,0xa5cfad5fad93f310L, + 0x747fdb1e913d5c24L,0x052a47c94518b7f5L,0x9e208d6c7cfb4327L, + 0xb135cb9c70e538beL,0x363527595bb17916L,0xa2c078805b3106c7L, + 0xd2d42a06c209bb06L,0xb525b471d3c504adL,0xc9f4b368822ce034L, + 0x15f18796eb4185a5L } }, + /* 171 */ + { { 0x094dea060aee4684L,0x42b21f067cdbdbc8L,0xa439e149b1931319L, + 0xea4bdd4181a7dba6L,0xc62137063c2ae80fL,0xb58b096712823dc2L, + 0x7443d515832611b1L,0x2e16f83113c20384L,0x0ce204d62bd992d2L, + 0x499dbcd6f419388bL,0x492ded1d1d3778c7L,0x9d5bd74fc5ddae73L, + 0xd4813d52994b6259L,0x191d9cf60e86ca68L,0x562179eaf3e9c2acL, + 0x6146f1f39fee1238L }, + { 0xbd06d33e078e2aa6L,0x693af7f79dee9265L,0xd56e0f81daa40e84L, + 0x05fbbb889b9a407eL,0xdcf44adcede99519L,0x7f71f8d3092dba39L, + 0x675b5da54231774bL,0x7456a251a5f605ebL,0x9031d4af87a39a9eL, + 0xdb43000605b474bdL,0xbda5dbf2b665aa91L,0x5d1a3df56631eeb4L, + 0x028149ef62377c58L,0x2e1af4e9685d0bffL,0xe0ea087582a465deL, + 0x95543f9e06bd0050L } }, + /* 172 */ + { { 0xf7cbc6f485d7c6efL,0xcad8084d63b1bc24L,0xdf90ce88bf8cba62L, + 0x98e4b686b455c192L,0x6146b8d5774fc6edL,0x70e2389e7ae20077L, + 0x5241c47961c22529L,0x7d2215103884e5f5L,0xd6d20ce217e28273L, + 0xe3119f514f2674f8L,0x8545905570c011dbL,0xdfab75d9fcfb760eL, + 0x9546362a9e8c2a19L,0x4b6d3f8a4a7d4b27L,0xa5c87104ee5d698cL, + 0x6db434782ba296ffL }, + { 0x064864935c3f0d95L,0x8917db824e748895L,0xf73fdf626b2f3e44L, + 0xc60edc542b7f574bL,0xbe1c09a2af732723L,0x7d34669d7cad114cL, + 0x9646600a321aaff9L,0xb94e2bbaed0cd61cL,0x866e1a41dec4750eL, + 0xa1be990db1a89f58L,0xc39e4d6cf2759693L,0x11cfb780c0e0dddfL, + 0xf0afcd7fd99c8a41L,0xcebffadb6e1c3050L,0x4f3981b096d2c6e4L, + 0x07a791e72ae27a94L } }, + /* 173 */ + { { 0xe70e90471e9f0300L,0xe0253ad9bccdf904L,0x51c0289dff053078L, + 0xf1ef092eae893462L,0x2c90a91aa4846845L,0x1946eda0f1dad4b4L, + 0xf07650f333df67b2L,0xc6e988db0b15a014L,0x72e0c66eb542f0f9L, + 0x5d4b6311e0c0378fL,0x548badaaae86950dL,0x6801638db35f1c8fL, + 0x129e3216944d1ad4L,0x9951bac840471d32L,0x03cc29f385e94ddeL, + 0x6d6acc2e4543ecacL }, + { 0xeb999e9557b2d299L,0x3a2bcd9be3d721cdL,0x2e60384fbb4cb444L, + 0xae177709dc060faaL,0x74f0e6d38c987cdeL,0x9a237cf81076fbedL, + 0x69af15137983fbffL,0x6c3f7a1d323f9584L,0x3e21cacf6db64398L, + 0x7cd8134f96703d92L,0x0755898fb8393f76L,0x1b5b28bc2e825222L, + 0xb78799c17924aa7cL,0x1db378f281427a8aL,0xd5a451b1ff289492L, + 0x79d182123d3c46eeL } }, + /* 174 */ + { { 0x1a3edff9109d5589L,0xded52eb4029b4499L,0x13eb9d30b4b54adfL, + 0x4f9214c1a27bff67L,0x4c817ee767f0f460L,0xbadf8d83c3a50e28L, + 0xc5dc03c994026237L,0x5f29581b966647c1L,0x10b6a0898a0687f3L, + 0xae787cec31634517L,0x2001dba562e75188L,0x55d4e1a745e2c3fbL, + 0xbfcacdebb67d3395L,0xa1a0af9cbc6842eeL,0x50590a2b3e88580bL, + 0x73104491a784cdc8L }, + { 0x44ca2cdf2648d676L,0x9a85eca54f1b12b1L,0x1b9dac942980e1ebL, + 0xf30d37091ac8aa89L,0x73072ab7c719e195L,0xba518c822f703797L, + 0xac090e14ac0067f6L,0x0e6cfc708dcd2927L,0x4f5889e221e7da63L, + 0xb4aaa40b8371c7c6L,0x1f9dabe28f7878c9L,0xf78aed6bd84caf3fL, + 0x3c39dd079e0e1d92L,0x680be5fb122424dcL,0xf41b214d0bdc0099L, + 0x6a8f8fc95180c54fL } }, + /* 175 */ + { { 0x62a1ed6353235132L,0x1db233f159dba88bL,0x85625452291efdd8L, + 0xc7505297b25111aeL,0xb5921af91d701bd8L,0xb4d05d729774f45dL, + 0x6e3d4c5ef18e73ffL,0x897d985f899b3038L,0x8a9c30fbc89b1558L, + 0x3c92d1a34d13181cL,0x292e86ba2223320eL,0xcf2454c201ceed02L, + 0x27a45f74583f309fL,0x75a6102cad0fd1a3L,0xdb4f45d2cb9c7538L, + 0x4752d8c1db283fd7L }, + { 0x514d6cead5dff4d5L,0x74cd5fdb45a827f4L,0x1070a60c4fc7135eL, + 0xdec0bb781be5778eL,0x271e12cd58dc6b08L,0xb765089b54bc2496L, + 0x6ddf2c63619098acL,0xfd6ebac667528832L,0xeaa2d025c2508af1L, + 0x13c2cda84dcfc1f0L,0x1c7836a845510be0L,0x3904688d1a886801L, + 0x643132aaafaf2545L,0x496855772830a88dL,0x569491ca8744b470L, + 0x3a6518f375fb8552L } }, + /* 176 */ + { { 0xaaa8ed50224042a0L,0x6cb4e3b02452f1e6L,0xedca5f4c768211d8L, + 0x4e0fe3f9ef4d5d3fL,0x33a8e2a4522d46e5L,0x5998e21ff1446775L, + 0x1496c50ef592d01bL,0x69104c2f83a67739L,0x28670bcb472bbf00L, + 0x8ea883b2503177bdL,0xc5d8bc057d2712a2L,0x41ef9317b439c994L, + 0x9801d3a8dcda1affL,0xd686eeb57038f6fbL,0xe80c5cd0fbfbf820L, + 0x540ac363edc25817L }, + { 0xa71969a9fe7f43dfL,0xe66538082c1b9e4cL,0xad9677d8859c2917L, + 0xbaca954596aa4404L,0x0e9d855fff1297daL,0x1f61897b22aea7deL, + 0x96edccfd36f13f8eL,0x627d307016e200dfL,0x729f0736c98988a4L, + 0x95e25e6097f231d2L,0xaf7f221bf6048752L,0xd66826094019b299L, + 0x1d99de0926b4b1d9L,0xec47cf661acdd7a3L,0x4de9f2b36ebe15e9L, + 0x17db32ecfa16974fL } }, + /* 177 */ + { { 0x75ef69196cf40599L,0x7ea10dfb00c020eaL,0x3da5ae7bfcaaf679L, + 0x0d663ca388ddd678L,0x5a21f8fe255bcfcdL,0xe9c3f538e344bc7eL, + 0x35f62b1d548e0632L,0x654f242543c6e64dL,0xc755a7a626993627L, + 0xa3b7c5f7b0f41324L,0x05697f793a2180f3L,0x6cf85fb11e81675bL, + 0x6d3cdb35e53428f5L,0xe3aa159152d28b02L,0xa8470255f7a3fb78L, + 0x460bd01ba194445dL }, + { 0xbc34dc23c24d8077L,0x82f4b5804c720d2cL,0xa29da9116f5d1ffeL, + 0x578af52092783ce2L,0xe29f51abb5904af3L,0x46c570d7f7aa1190L, + 0x4a522fba571bddf0L,0xbf4e2a06ae89bb51L,0x799b35cc59f3444dL, + 0xc302836726cc2557L,0x94a4e985afcec177L,0xadaf7dcb7c36cbd0L, + 0xed31b78775d39077L,0x52d6904f2d3e24bcL,0xc5ca26691f95421bL, + 0x7d342c3c1734878dL } }, + /* 178 */ + { { 0xe5cf2c0a11fd127fL,0x66d36bb8119e4c5eL,0x621ab2526ef56ac3L, + 0x30cfeaeee5430675L,0x2ede27d2ac3e9619L,0x6413513af8fce671L, + 0x6159c61b075f4c3dL,0xd447efe959069d98L,0xaf8d6f68ea76aea9L, + 0xac5dc61b0f5bd164L,0xdbab446e1e88bb98L,0x618b8b161ba92320L, + 0xa0eafb3c78989865L,0x0c7abcc2c08b7e82L,0x10f09b6e20d160bbL, + 0x5be0afa68e4c63a7L }, + { 0x82ab6d381bbbf49cL,0x3e09ce498c0703feL,0xeca58b5de10f4263L, + 0xd9cc6581da5a4532L,0x07e18876f618f7b7L,0x0419a5e3250f7fe7L, + 0xbb1a9e90de6b86beL,0x584a7deb37359169L,0x38eb34895149db2cL, + 0x14546a33b0ebabb8L,0x0067f0b0c2f88a92L,0xbde0dfe70a2db019L, + 0xba51b06cc63e6f3eL,0xa19127b9e9206fadL,0xe4eb5e87fe80dc0aL, + 0x1e6fccf5d4de30aeL } }, + /* 179 */ + { { 0xb57dff66aa8ac924L,0x06e9ad31c298b3e8L,0xd140e32965fb080cL, + 0x7dab211d1d95c93fL,0x6d68d8428a180caaL,0x1a929408a20ded69L, + 0xa815175338df461fL,0xff5604ae60eae932L,0x901b9e497dae4c0bL, + 0x4573a97fde262e89L,0xed69d9a4f1084983L,0x8ffa022f64724f1dL, + 0xd5f1c2e4ea85a15fL,0x4c626ce901453794L,0x80440cd6bf0907ddL, + 0x4522d4615ddaa837L }, + { 0x8895f079ebfbe7c5L,0x30ea1ded84ef3446L,0x716a9eb6d4a1ab96L, + 0x1a4a5d2250a30c68L,0x5a16631c0043bbaaL,0xbd1075025010e5f5L, + 0xbffe3e9d3d8c0556L,0x31b30b1807772419L,0x90ff7ef084b82297L, + 0x00c37d75f21a18c3L,0x18d0a635565bb8f8L,0xbac1da2a45e3bcebL, + 0x1c38e90c23f0b08dL,0xf1ba1aa25fbc5ac5L,0x09d5256bdda71fc6L, + 0x346501a96d7e40baL } }, + /* 180 */ + { { 0x86be448ccc2b0f1dL,0xe3eb45c9ac4c3703L,0x5387f65d9fc96bbfL, + 0xcef3c4e95ae27fdaL,0xa008f7761bc18089L,0xf374a08422ca18a1L, + 0xee88284253b73371L,0xcb6fc6d87cc09354L,0x8489ec1b61496d6bL, + 0xa92c29b949e325c4L,0x15c6ca527bdec166L,0x95444eeedcea2813L, + 0x34683eb33a21154fL,0x8fb26f98d39061cfL,0xc3b08aa806c940bbL, + 0x7c1d42cfe554c96dL }, + { 0x766e703fdc110aa7L,0xab7b79d7f362e378L,0xd259c75d5aadca3cL, + 0x2a6eca7960be3373L,0xf4744a4b06c4e8ffL,0xb2842ccef3b705bfL, + 0x1a3af5aaae304b53L,0x7bbfa2011b2d31b8L,0xc4ba6eba4bee88d9L, + 0x2d3565ce565cb839L,0x24808696daf7ece8L,0x2c7ccce7e6959745L, + 0xefd6eb3ce94f9837L,0x0a33b4cf3811a326L,0x14203f43fffa93a6L, + 0x031e982873c31d90L } }, + /* 181 */ + { { 0x4fefecfc765a17ffL,0xa09f3888d1290a65L,0xbf265c46938da038L, + 0x4bb6145da169ad46L,0x33cf821423a62fe8L,0x562df571abc860a5L, + 0xbf2a90fa815c38c4L,0x45ba1d6e17eda875L,0x799d881a946fa5e1L, + 0x6c1be784b90f5a3bL,0x0910a37cb10ff52aL,0xc38c1fe4a4f4fd36L, + 0xc3180fc58e2d3ba0L,0x3e2ff050b17a6187L,0x3a00059b943a35c2L, + 0x494d3645a28cc51cL }, + { 0x398426b64ba021f8L,0xd14c9083796deb6cL,0x6d2e53957e36c762L, + 0x8f556eca751cf216L,0xdaca1e0019b24a19L,0x47887da44b20c2aeL, + 0x93ed4ccdff41a733L,0x8d717c445c7c0cd7L,0xcc48634a91bf7009L, + 0xa1f146f93b59bbafL,0xdd38bb39e5624f15L,0x96d41aad303f8443L, + 0x6b670f034bf104fcL,0x0503f9ed29706582L,0x768e1f47b34200f5L, + 0x3cfdcc5ebbd4c6f3L } }, + /* 182 */ + { { 0x536c2a86b523e13dL,0x1014a4582920d0a0L,0x3d52b478e7571296L, + 0x057460667eb51beaL,0x709f786187b0e919L,0x028aed88686888e8L, + 0x79a809d7d94afcd4L,0x50c6032fe2129af3L,0x75e4be72983c4082L, + 0x98331bbb7ab3be8eL,0xd31a032cb618c728L,0x36dd85a13f59c4a4L, + 0xdbece345ed4f61e2L,0xba7aaccd1e571715L,0x138c58da64a1ebd7L, + 0x89296d0f3d1aeea1L }, + { 0xb165288fcca82c97L,0x26c6c12d1427e8dcL,0x66a94f074c3edda9L, + 0x94600e1eeaa01ebeL,0x14abce7c30f5e86dL,0x741d7020cb456a31L, + 0xab05aa13279f42c2L,0x70b60fafd4238468L,0xa18efec1318d39e6L, + 0xeb07f1ac8920b318L,0x01e3cba8d8399e03L,0x65f8932e3c81a301L, + 0xae8bca7dccc667d8L,0xcee1ae79a268607cL,0x3182e64ccac0a12cL, + 0x9233a2f72b1a4c54L } }, + /* 183 */ + { { 0x717e8df60acbee17L,0x0f0959c25c24fcdcL,0x46f09887e54ffcb0L, + 0xb993decad285116bL,0x0bfaa4f8bba1fa51L,0x9c9249efd0f2183eL, + 0xf93cb35896847779L,0x284bfb7f2322d421L,0x40cc709ad42af009L, + 0xc69f22749bb1d615L,0x76f50b3a717c3c6aL,0x8b21e985bb9c5eebL, + 0x58fb19aea4783b5fL,0x04c86b9b52e1c3e7L,0xaca59092f2971ac8L, + 0x2bb26a6921ed8291L }, + { 0x98a3443515f81416L,0x086e72e7aaff5bb4L,0x3d1f64de0317261cL, + 0x31c0786c5c0a1cfeL,0x542ea4d8b3683401L,0x2f77273a1a39b4cdL, + 0x14fe7ee1cbef27f1L,0xee7fc09e16bb27dcL,0xc0dccc17410e5dc7L, + 0xa34667421943b3ddL,0x92934b603f31c1b7L,0x0186ded9c22c1070L, + 0xa37ee8ba799f966bL,0x0f3bfcb4249b0893L,0xbae614472e92d4deL, + 0x937cb3f8e196eb08L } }, + /* 184 */ + { { 0x57c0e77c16fbfdceL,0xea034cc9c98d4cc0L,0xe7606d7242572d20L, + 0x9861b55c0019a83cL,0x80ba2803f1597162L,0x0f4141dd05a0fd7bL, + 0x8865913b4b0daaa2L,0xe6685746aa3848ecL,0x16d15a5a3e0485d2L, + 0x81c0c7743b6905ddL,0xcec31b7d818af2baL,0x80d8f194d2b74b78L, + 0xca659db2543e2f28L,0x31b83a7d9fb07c1cL,0x86537fdc1f1048c0L, + 0x4d57bb0778586a11L }, + { 0xbc4b768a53b396b6L,0xbc8b24c493b51dacL,0x33e511eba30ae1b3L, + 0x893bbd95945147c5L,0x6cc86031179fe3ceL,0x34b0a1673f920bd4L, + 0xb32912eb6b256160L,0xbc69a2a49d168d83L,0xb4949e7aef0dd128L, + 0x2613419a872699e1L,0x06c58477bf21376bL,0xe55b1909a4f97147L, + 0x63d6eb757b9b745fL,0xb5365b2908df3c85L,0x0e257e4355fcfae3L, + 0x1067c118979f2aa8L } }, + /* 185 */ + { { 0xc845508432bf8883L,0x4755286a6fd06667L,0xd70b0f8f77c2335dL, + 0x678e60da2f4a2c94L,0xa468d8acd118acf5L,0xce93830bbf5b90d9L, + 0xea4b1c74ed4e9104L,0xac67316d27776ea4L,0xb98ad75c361bab12L, + 0xc323d48299122451L,0x26440220530a43aeL,0x3a44532e3292d5a5L, + 0xdb48694b5fecf1bcL,0xe4e0516ec667b8b8L,0xb3aa595fa4306adeL, + 0x7e4f7091f34e9725L }, + { 0x3f3816e9b7f70919L,0x765216ed16b003f5L,0x46c6cff4778c99e5L, + 0xe6a5abe830a51810L,0xef6f49e645e728dbL,0x6fdd73eacaccefd6L, + 0xec394e6f8c37f3f7L,0x73320802b6407fc3L,0x988e8f7a96625cbdL, + 0x832923637cabfb00L,0x258ba9df407f359aL,0xff01aee5ccbfae50L, + 0xfbeaeacefe251813L,0x9c69f16183f1cba1L,0x512c58ad9eadcdb5L, + 0x2ae49cd46ccce8bdL } }, + /* 186 */ + { { 0x1239b0e3c40849f2L,0x5136a4cda441098cL,0x61535a99e547f649L, + 0x92e4bdc47a9bbac6L,0x195a164653547af6L,0x85ecb3198b47a74aL, + 0x278553fc9de6a2b2L,0x471c038a0e2ba52dL,0x12ba1b8835bcba93L, + 0xd4bf50da6f31eca2L,0xd146e3f6802b32c6L,0x0c9c01313c64c8c4L, + 0xad30f12deed21297L,0x9b75bffb9c68530fL,0x23c0ad3e8918de51L, + 0x180e9d52a73771b7L }, + { 0xc316542f29ab77b0L,0xdd411d9cf7aee628L,0x044c0685353c2f40L, + 0x638dc7e44b0ae4cfL,0xa092418595fc266fL,0x639da671fd2feb7dL, + 0x56858ed55ea39798L,0x7a694f3158f3832aL,0xa94233c6d316d831L, + 0x2fcacb2630a35a7bL,0xfef8f7ddf1ff713bL,0x8b9b452559eee2f3L, + 0xd1b4f91b156d064aL,0x177866c22f5cfcfcL,0x12bc25663777eb41L, + 0x21ca6f3cd8ab85b4L } }, + /* 187 */ + { { 0x0e162b13a3e66635L,0x1ef20a2b2a9f76afL,0xab473a3046db3356L, + 0x0840bd777802bb8dL,0x5b6baf5ea699b44cL,0xc6e119001b2207f1L, + 0xe5de16a9790b0105L,0x22b12f15db67f004L,0x185fad458a025d25L, + 0xbccf6953df0a1142L,0x4c42129bf45034c0L,0x0f7404001c277bffL, + 0x6e440b4c280a9e18L,0x767de8f5842aa2b4L,0x3de20ab805e8d94fL, + 0x5aff585920227635L }, + { 0x805acd20a8458e40L,0x5a5557d8149732bdL,0xc70741315f1ca72dL, + 0x7f2e269c952b5323L,0x5c5925566494fadfL,0x153b7acd1a7d2666L, + 0xa6df063d86fe2865L,0x1e91db1357d53b6bL,0x9195bb89e93ead01L, + 0x3d71e1af2963bfe6L,0xfab2b9c288278886L,0x778366923b859b6fL, + 0x6e695174f7029dd1L,0xc79878767b984561L,0x64fb4f1d5907d849L, + 0x3eab7e1c88d8a977L } }, + /* 188 */ + { { 0xc73a94b652e5718bL,0xe3aefa54f4cee1e9L,0x654e9e63553eedeaL, + 0xf2541e1b5f3aca1aL,0xd71294890d083316L,0x7965af63fb7f950eL, + 0xd8fc9e0dc74e3e4aL,0xb4ee48d2eaf79ebcL,0xa458a86a8b7787e6L, + 0xd8c7621ff7cceaf0L,0x8228eeffdf67980dL,0x210d4742f9106727L, + 0x91f63501b07e3629L,0x441761c67971e29dL,0xc0ccc65f03a3b8a5L, + 0x3491da4f38e09544L }, + { 0x6706d046cb062eaeL,0xee7db7355d08776dL,0x80de8052292315d2L, + 0x40785662c402bbdbL,0x5f93525c26ed3337L,0x6cea14d67d568ed3L, + 0x916a118966888b1eL,0x0fbd52055dc71675L,0x833d1077e4575df2L, + 0x4e93100aec092335L,0x2f9e1d016cd85389L,0xeebd372543226368L, + 0x401d172b1ba4cfd7L,0x377dab9d574c5838L,0xaeaa695880d517deL, + 0x0c843dfd6ad15a18L } }, + /* 189 */ + { { 0x455811ffc9373300L,0x1c39332a99fdc300L,0xe19bb81c353cb655L, + 0x774b924a96a83d27L,0xcbfc8fcbb2ee3f1aL,0xaf278ec4010d56c7L, + 0x6fde682fe0abaf79L,0x7566d0727339aebfL,0xbd35ad5d71205db6L, + 0xb5bbe6947051c9d0L,0x577db480d3a3067cL,0x2c70ff54572d7530L, + 0xe8615aece06d853dL,0x71999ccb05abfb5dL,0xeeefc96bea0a8ed7L, + 0x2dcc469d35f6df69L }, + { 0xcca6cd06c65f0e77L,0xddcc7980bd71b14aL,0xb6221f8b3c93cc00L, + 0xddfcd5b3ae8cbf57L,0xbc92973f76f8e63fL,0xe9848a3406e132b7L, + 0x4cc59a03d51ec9e2L,0x9c9d32bb3a33081aL,0x0012105280e8466bL, + 0xc2b0032a1bbe7295L,0xdbfc657224938448L,0xe972a0ceb6bba0ffL, + 0xf60c0a4fc0a94802L,0xf62c41cc599d8bc7L,0x820c96ee312da0b8L, + 0x5a1a65dbcdbdf9fcL } }, + /* 190 */ + { { 0xbfba691a42485684L,0x613116b929c470c9L,0xb4b01971e62a0519L, + 0xf3245aa65ff499daL,0xc2ef87f4a5238effL,0xc16dc6bacc9d5515L, + 0x5a7f227e2dbdacacL,0x8dedaac4a9bbaecbL,0xff308a6d2e7c9885L, + 0x4c6f2fc2e6895593L,0x3655f285177e0611L,0xa63e8d06300b1beeL, + 0xbed0ce7913c17b54L,0xca4abe35c4974262L,0xf4b44a17bc4e4037L, + 0x5ae95099efe5fbd9L }, + { 0x122e5ee7804f7455L,0x341a499722066682L,0x97d24c317795e333L, + 0x12f4123ce48efcedL,0xe8738d9219fbc21cL,0xbb3bdc610663a3aeL, + 0x3603d8c28593a6dbL,0x926227f2e3c1ac75L,0xfea92ac05eaae519L, + 0x5b596f0bfd6812acL,0x3ce7e844fc2a82dcL,0x3840481a63522b27L, + 0x836088b152867895L,0x21ffb7cc26588688L,0x0ca331612f4a7cacL, + 0x4110667ea3edd298L } }, + /* 191 */ + { { 0x81830357c2d04b63L,0x3fc5a34df4929a18L,0xc73bf6da22d195dfL, + 0x14df2f89cb432473L,0x345afe5ce997f138L,0xd8e3f5f98b9604f4L, + 0xad7942e950c10ae5L,0xcefd5447eed25ff3L,0xbf68e51e0e73c0ccL, + 0x5b1ad591ab54fa4cL,0x8bbc110512b61c8cL,0xbb932913b5abf760L, + 0xdb1231be01e79649L,0xd0a83e91040ccbe7L,0x3dde426f90a96db9L, + 0x1cceb64534df11eaL }, + { 0x2d210c4f0c6d0f55L,0x6cadf61b9c673c9dL,0xdd7f9919a9ce3fbbL, + 0x135f494c93b063e4L,0x580bdb3c145a93beL,0x4d8723320f52ef7cL, + 0x74d876e88814bb6aL,0x4f6f723ac7a97deeL,0x7de2b8f03e3cd833L, + 0x6162f082ae720270L,0xe88ec2d4ddfa486eL,0xd965c8598d3a17c6L, + 0x62e59e543980171aL,0x0ab6285dbbef6b22L,0x3cf451954d48b203L, + 0x1f1752334ea25ea3L } }, + /* 192 */ + { { 0x808a765b3467ea91L,0x3f4632eefd2d9c45L,0x7b75dc6d9cf2bc6fL, + 0xefc8d240359813aeL,0x23ecb209e44cbd8dL,0x59ba10e321525622L, + 0xfa14d9343f1ee19aL,0xdf97c21bfb0c48f7L,0xc4e62890ea30d437L, + 0xb286e2a4651475c2L,0x291f01e4126672a5L,0x9c6fda5c31aab3b8L, + 0xb7277a5ae17d22ecL,0xbd88ed83914f0badL,0xd0b05d1b6a2392e1L, + 0x4cb8af9065893c2bL }, + { 0xa2b02057bb4b1953L,0x4ce08b44f597f6eeL,0x854f5d9b5e6412c8L, + 0x1913262db3cd4919L,0x902762e46e42bb5dL,0x8355c8e6d78e7f60L, + 0x8efaa82438b6c16cL,0xd0173790e550f618L,0x118af462e57d778eL, + 0xa16ad5e8715b4714L,0x900596c341dea4f9L,0x2a957c32280ca610L, + 0x2faee800374c65a1L,0xdb10512750080414L,0x8c1db931ff080fa1L, + 0x486a5c25d79878fcL } }, + /* 193 */ + { { 0x0521e213941b4f36L,0xbaacfb14f803b4f9L,0xfdf1e22e52a54ba8L, + 0xacfabbba8fe4796cL,0xae0788db58dbacb6L,0xdf98d736c19dfa51L, + 0x155c286a35a716eeL,0xbe7d46769c86461bL,0x50b6380f63a64a5eL, + 0x14b419149f609262L,0x0919a7d0a2dfc5b3L,0xc454da55cef466acL, + 0x93fa4a246986aaecL,0x5090b17171a49cedL,0x602f1d6cc1fa75adL, + 0x5d269f8978e4c054L }, + { 0x3a74030c14920419L,0x0845d86890968739L,0x81b994c4eeb70fa6L, + 0xabcaa06dd9fc5bcbL,0x06539427f58f8f2dL,0x35c85f67b1dc52aaL, + 0x5a7d8d722c911baaL,0x4041005caec2d834L,0xb5868a447a8e5347L, + 0x04ee180b8de512c3L,0x4daa66e5211168ebL,0xc0bd5dab2317cd8aL, + 0xa1d4185d61164df6L,0xacedca261dbad7c9L,0x0fe4b5ac09b02683L, + 0x8ac9995a26d9550fL } }, + /* 194 */ + { { 0xb2c8dc9b2640a39dL,0x21ff0b38ede0c9f9L,0x74f469bda1ecba0aL, + 0x8a902ccd080d0417L,0xe956fa32f4994604L,0x348f85cf9776ab15L, + 0xc21fc6ee0066f492L,0x35b1ebfefeeef367L,0x7804581c4613e5edL, + 0xcbdfe8e6ea6ba071L,0xddfcaa32950d73edL,0xc97479361da48889L, + 0xce867c8cdbaffbd1L,0xd267431f1cbaeae7L,0x68255045897912c8L, + 0x0c7c1ddcd7ea1e4dL }, + { 0x53aa30cc1ce963a7L,0x7352f64cc4c5fadeL,0x2b9aa2f82828afbfL, + 0x64273c56ca212107L,0xaadd765485a576dcL,0x6196ac3e90b5c77cL, + 0x20d43e9fd1aaf39bL,0xfc392062cd05cbc4L,0x141638724c0ff2fdL, + 0xcf32b8d82ae821e6L,0x5f58f9433fa7a3f0L,0xaebf1d2df644ca92L, + 0x0c0615631918a75fL,0x7989b5ed6b876118L,0xbf342445ad412441L, + 0x24ffc9ae1df633abL } }, + /* 195 */ + { { 0x89fcdc0593c7cb2bL,0xc1243b95590053fbL,0x601debcf6182343cL, + 0x364546ef66c18a63L,0xa5290701ec913287L,0xc35b8026f9788c31L, + 0x852b862a92d1f7d7L,0x1809cb050aa79728L,0x897d467ca3cb2005L, + 0xf20c77c09ef5b946L,0xc3372c42f2241984L,0xda053e0df35bb206L, + 0xbc26c6d0a9c140b5L,0x61cfcc0ccb56fb33L,0x1c3cf9ef299b3968L, + 0x89e4d3d140621ba4L }, + { 0xd35e80e7a45a9be3L,0xc4daa57807356fbdL,0x0186d62eb967bc2fL, + 0xa702679e47cd16e3L,0xca2f1c025f30ce9bL,0xf1205b461f864f50L, + 0x7fd6d79785061d66L,0x47edc4f68a08809eL,0x5dac04499a4d3ae2L, + 0xf844664a6d1f9da8L,0x9f30ce84d7a83a71L,0xe9382baceaac33f1L, + 0x1f033831948622abL,0xb037a4baf7681eb2L,0xd156a90899a1b5c7L, + 0x675d3e6fe6f1d0fbL } }, + /* 196 */ + { { 0xd9767ffd707193e5L,0xe478aa91810358e5L,0x5634f9ff328d8ef7L, + 0x913a0ee86dbbd9a7L,0x379b29687e215686L,0x903f410a89d9da38L, + 0xd9f8d7b91b1334d2L,0x9fe74229bd82efb5L,0xdb568b623803c778L, + 0x93e9a350d3d25344L,0x559c35b0724497e8L,0xc472d436a169e23bL, + 0x09864632cc5b4c69L,0x9f6d759d83c7f531L,0xa91cf1db1e497888L, + 0x5f7f92fe60af1a4bL }, + { 0xf18a1cc60545167eL,0x55ee2e02affa88e0L,0x24cdff51432a7bcfL, + 0x7382da42a7510866L,0xe894c11f40511af7L,0xaa4e4e312aaf1423L, + 0x8c3d36f0f63dd2aeL,0xfc5c9550d7660635L,0x0125373137ea7eabL, + 0x2a5cd59839b950f6L,0x95a0f60140e63442L,0x905e238ef2ac7045L, + 0x44bacc0e446b0f73L,0x4cd4206ec448578aL,0x367b1aaaa5bd7803L, + 0x25beced90a2b458dL } }, + /* 197 */ + { { 0x079a73820c33a8fbL,0xcfbf6cd10f25dc1dL,0x4ffc73f8c6d482b6L, + 0x3e51f18c07bf844aL,0xa7651236599162f0L,0xac59a74e14013811L, + 0x957a6865e55018a0L,0xe1ec51bde3ca09b1L,0xbc0c7eb3a960253fL, + 0xe83bfd147de03f84L,0xc0540ed152fbdb09L,0x6ba52eddcea15ec1L, + 0xf3d30ed54b261307L,0x9bd7bae8e8397206L,0xf20d8692096373aaL, + 0x0a616a4bc3b0bf63L }, + { 0x2075f3ed6e1339c9L,0x7afaa072bf8b00a6L,0xdfafec82bccd9b47L, + 0x4713158f00ca54c7L,0x449102f138bc31aeL,0xaf98f158310dfc8aL, + 0xc9ef207559e954d4L,0xe8021af9c527a0c4L,0x6e8012777a192023L, + 0x635f538c7fb02377L,0x5df1974fe8c9e951L,0x0287faed15cc9097L, + 0xfa0728f0f7a5115cL,0x90dbfbe60fac623dL,0xa8d40fd40311ba09L, + 0x876d154e07c6464cL } }, + /* 198 */ + { { 0xd3a4d6d2c2d3ea8aL,0x36be681ba842600eL,0xc53f100de4070672L, + 0xe3e5b6fe6a7d7a7bL,0x6e6994f95d5e1a83L,0x07cacd2276097c2aL, + 0x12d98dbaa6791011L,0xddfc4461102e0e24L,0x4815dbc2d493272aL, + 0x7e38e64ba9436696L,0x4960eb1a32b2bf90L,0xda457525d928e28bL, + 0x72f75b392a077c9eL,0x27760cbb7fd61d00L,0xaf235d1b0f4b1456L, + 0x3040c23be76d1700L }, + { 0xb10dc55b4efa9a70L,0xd4de414f53e86610L,0x3d95c11309f8a27fL, + 0x505109a506661d3cL,0xcaa2994a60eb513eL,0x3ee415371e7d338bL, + 0x4fd145fc4651e71fL,0x51bbf838cbc313b4L,0xb039e0781eb92150L, + 0xe8696b4414bf5ac7L,0x2d6671888be0d48cL,0xbe93b2f5dd8f2b6fL, + 0xc1dfd1e7eb8a7f8aL,0x862b3dd990f751c5L,0x1eb1ad58a32a74beL, + 0x5486d79a1ebbc9a2L } }, + /* 199 */ + { { 0xcb2e34ffa1359e13L,0x202d8dbf28196051L,0xe95e023d23564b5eL, + 0xfb1340b642f6ac12L,0x543ba852b653725dL,0x81aedcd68d2466adL, + 0xbf780224547c728bL,0x559f8a119569fb65L,0x505b7a62dfb22ec9L, + 0x071075409eed5e52L,0x9c899288299f6f11L,0xa7d692613db6f8c7L, + 0x30eb7fb3b3ca79a9L,0xcab99bb8fb2160b0L,0xd2012568d28b409aL, + 0x380f1b0f5ac45f8bL }, + { 0xc0b99e6be6a0068fL,0x4b67cf2ac8a73753L,0xa6c9a548b2faeb7cL, + 0x7f417f99340260c3L,0x8ee56855cc0f739eL,0xf08b510f780949daL, + 0xb1770fc28d5c6effL,0xb4f5abeefd96a7bbL,0xa07b1136f2665a2aL, + 0x2fb380a4b601dcf9L,0xcc803614162becc6L,0x3498fb96ee6b83b3L, + 0xea9b0fd6a8c17eebL,0x5834b5baa177efc2L,0x929044f55b110b3eL, + 0x4abeddedebd7285eL } }, + /* 200 */ + { { 0x3355e1b9700ef376L,0xd56e5d9a66cdabffL,0xb3dc257547e87646L, + 0x28f44b8a00f79369L,0x08c32b1ea0c52e29L,0x5a78de123729b392L, + 0x4184519ab26d239dL,0x23f6b4b7e0ce4a6bL,0x235f6f8aacb2a9f9L, + 0xbb8bc454e2064a59L,0x37efd0341bf3062eL,0x6bac683b94dff6f9L, + 0xc3364b1e8aa7fa06L,0x0616772ace0b3745L,0x46f08d08d1e3fb0fL, + 0x6a20abb318e132d3L }, + { 0xea8310166a85cbc7L,0xd0990946934f9aa7L,0xc2211088e778f1b3L, + 0x7ea4ff8f2247b799L,0xb3171d71454484ceL,0x294039494f98c364L, + 0x5da911f397df1458L,0xa6b5809309439116L,0x75f9509a174238bcL, + 0xfeb518218209758dL,0xae0c6021a47925d0L,0x0e946694af8a315eL, + 0xae7af8a36bad04b7L,0x44c15e7ff072447dL,0x5184668aa5456ffeL, + 0x45e353a7bf36b977L } }, + /* 201 */ + { { 0x7605676493092f71L,0xeb66b6c2f5b92d71L,0x9db3149be2c8b6c5L, + 0xf62f583a20c0363eL,0x688acd3303cd7097L,0x85d0c0f8ebb916acL, + 0x1bf7462c84c19b0eL,0xc76ed5f97c4a6ad1L,0xec8b88bad119f369L, + 0x59b8371bebe50b83L,0x0cc69508866706a6L,0x531c75a3f8373d2cL, + 0x4e1cd3a32a5a02fbL,0xe8274778da39a1d0L,0xedfc5bbb75da333eL, + 0x15941f24ca79bd36L }, + { 0x42e8c0f8a77dd512L,0xa91b59a71dc365f6L,0xe80d14cd08753862L, + 0x1624230dd272facaL,0xeea3ec164027cb5aL,0xc1700b59c1ef9f03L, + 0xd411c1270da3148dL,0x801ee448c4181af1L,0xedf285599e3a900bL, + 0x5d67b0bd0d09affdL,0xd839df968b370024L,0x3b6307e0e6f836b8L, + 0x5382e588bd3201c9L,0x636d8a6b7a1d02bbL,0x70b7db76968641e9L, + 0x6d17c34a118fad03L } }, + /* 202 */ + { { 0xcf608841c181c99bL,0xb65dc901c87bdcafL,0xb460b4473720dabeL, + 0x4c79c3965377515bL,0xd447f22e0a96c277L,0x0d9521302ac0f440L, + 0x8330b26bc90583adL,0xe25e977a928904a0L,0x1deaffd985c50b18L, + 0xcf4dbcb7a5ad5f6aL,0xcbcd0019c8a37ed5L,0x7846dd901e9850b6L, + 0x1ac8194ab0b8e605L,0xb972857134132f90L,0x4ce9f149f56ee28bL, + 0x1ab9b5a43e9e1d4eL }, + { 0x206dab92314fa7a3L,0xcc4af0f0478ff963L,0x4cce1713904d9fdbL, + 0xac20a2eb12c045feL,0x44fc5478fd8f6d7dL,0x886e72c5ca7b6ffaL, + 0x7fa4529b6fd6f758L,0x4df1d1b192a820d5L,0x3d812f9f2789f149L, + 0x9842f083aabb53d2L,0x2648539b2a03ab32L,0x631ce090b1512502L, + 0xe1294d15731f6bd5L,0xb229361d9436e634L,0x8c4281c43ca966afL, + 0x24b34956c21ab3edL } }, + /* 203 */ + { { 0x49bdcb86659824e2L,0x6dc4ce484e13e74cL,0xa4c01a266bbe1eeaL, + 0x47b2b8e71e3ec457L,0x7e8b15e02f5a8e4bL,0xe81eb6e6e333530dL, + 0xacba369e17a45202L,0x81241431d70e4c9fL,0xc190af4b3e12beb8L, + 0x5327052311f486fdL,0x9f6c41e129fb2bceL,0xbe6287ebb70f6c08L, + 0x1479850a3feb4477L,0xfcfdfb119bcf18bbL,0x925c292fda80d040L, + 0x212d65e57e3c5bf9L }, + { 0x23adb386ca15cf08L,0x4dfa4ac481e172ebL,0x9d1dbf934d42d0c0L, + 0xd9cf607374404dc7L,0x60508441e932bfcdL,0x9ae910ca1c682a98L, + 0x9528fc1841ac1cc0L,0xe6a120aedbbed630L,0x94e0e1ec30ccf250L, + 0xfe84ba54e58bbf2fL,0xc66d0b4f9faa4415L,0x0c58f1e7ecee7ce5L, + 0x7a1d43eb6fa6873aL,0x96c6c5a0399f1348L,0xe6ef9aaae6727ab7L, + 0x66afa5549a5c2447L } }, + /* 204 */ + { { 0xda5aaba8c980e91dL,0xa93cf5096ac98efaL,0xb0990e0a8da32662L, + 0x01d215300081453eL,0x2bb0d33e3d71de84L,0x465f6d803e19a012L, + 0x5902ff4c78a838e7L,0x74e2afb71931348cL,0xa49327579cfb057bL, + 0x761ea6423ad03f8fL,0xb7d4c24558ffa40aL,0xb5e9c0d977a87e30L, + 0xd1c5edbac9c84d26L,0xeca8839a3d1963a0L,0xbc6f2f35ebf6bf0dL, + 0x01ef06310d58abdfL }, + { 0x2bf903163ecdcbb0L,0x19e2d72827c1c955L,0x9e5270309575c930L, + 0x0dc1c5a996983930L,0xef9f80ff7cd082dfL,0xcd915075df97e051L, + 0xf286fffe9cc61b55L,0x352db38f80f24cc4L,0xed9b99ec36523ae3L, + 0x109a8ca810b104a9L,0xc2700fe7305203adL,0x2a2ee24e769400f5L, + 0xd595d399ee0c452cL,0x0ab75d6af7f02a41L,0x341080990db730b7L, + 0x0e4f5ffd5e8d1202L } }, + /* 205 */ + { { 0xbd1c64440ff14c38L,0x9a5b59faaece11f2L,0xaa4605a722af6330L, + 0xddc9f65a82af24eeL,0xf4ee4bfeeb9a1159L,0x2463d07674e84eafL, + 0x88cbe1e00e0baaceL,0x7ca568ead5fabdcbL,0xbd80d524c57eb99dL, + 0x9c46572ce9be9873L,0x918a1dcd7300b85eL,0x4922131240f54176L, + 0xf7e324ffb5b14236L,0x40dda5012434f16aL,0x08833421a133d97cL, + 0x33d411610876f020L }, + { 0x7531a36b9878e5ecL,0x5de3e32146918232L,0xd15f9a33d0a30464L, + 0x734c1b87aa173659L,0xac2094a2f925d4feL,0x43c965a1c262b0f4L, + 0x759c903e447d5cbcL,0x92af215e05239300L,0xfffb6d5f1f593f34L, + 0x65943b4bc3cddb5fL,0x9d03a29cbfdd5408L,0x8f7cda6b198d76c0L, + 0xc0790a22c0f27b59L,0xba557a848cb58ccfL,0x5922052d76c54fdcL, + 0x2d3de7aa47b6b466L } }, + /* 206 */ + { { 0xaade746265add3b7L,0xe5888f35abf24c2aL,0xd41549cae1a57d93L, + 0x0e22e18e2c76f7bfL,0x67f288eabe3202b3L,0xb79a66ba1d1d0f0aL, + 0x0e0ab7492881ad18L,0x7d424086c7adb0e9L,0x870c32c52842132fL, + 0x858477f158f9a09eL,0x422a9372ec025589L,0xbe428c5ca5098777L, + 0x45b7956457660058L,0x6c7fc631957f37cfL,0x8b7023ddd6316289L, + 0x47003bb65b1c12a6L }, + { 0xd99401c1c91c1c96L,0xaa5dcdf927a12970L,0x3ab92e17c3c29107L, + 0x26fce8f7a3fe4710L,0xb0d09d5e4ee998eeL,0xafa622048e3a41f8L, + 0xb1c012a5a26ca506L,0x2c6f734c99b57252L,0x1093d79f512f7fe1L, + 0x2f30906eacee19a6L,0x6bff8381056d1ea6L,0x61c75856eff35f21L, + 0x6e07e978c1ad2224L,0x2cca6ca16b20fde8L,0xab4d6d2d633fe81bL, + 0x73dff504b06a2ce6L } }, + /* 207 */ + { { 0x8b615805d8e20fb8L,0x7c6873e482b533f0L,0x5205f00156a854caL, + 0x87fec6accb369211L,0x1fa3c0ecc7f092b7L,0x5b36647ee845fe4cL, + 0xd4781e85f8b1f112L,0xc65268398b0f1a6fL,0xceeb8c6cdcb8eb92L, + 0x133f0ead8e5f6d52L,0x31883e23c8d934dcL,0x214ed5bd428ac45aL, + 0xf77ca492dbbfca85L,0xdf4113fe07e5ae13L,0x63e4a0d272ab05fbL, + 0x7544d0b77148f535L }, + { 0x4fe8d13480797aceL,0x216d6aa0af86d97eL,0xdbf0a688ef5a68fcL, + 0x18b26f459f9b2684L,0x52fefcfa8999d2fcL,0xd5af8d8262423955L, + 0x8f123469f63a3780L,0x2933454fdcd4feafL,0xba8018b7a73b5d09L, + 0x9af1f276e5552c18L,0xc5d4773dff26bb1cL,0x9ef4941006dd4f44L, + 0xad8f12f95f39ba49L,0x5767f6dcf66ca4f2L,0xba8773f17922f59aL, + 0x220081eac1e42d49L } }, + /* 208 */ + { { 0x3043d573ba37a0baL,0x05a431bcdd176df6L,0x03322cfcc42070f7L, + 0x5cabd30e67c2d109L,0x362c95decbf8bcfaL,0xd767d2777787b10bL, + 0x612c915e6ec05e64L,0x9e669631ce69c30eL,0x27c9dd8f682e2635L, + 0x79021f1295ffcc38L,0x06a8ee798a2adca2L,0x8e00e7844b5d500aL, + 0x87746fc78d80d6c5L,0x246053be915f10ccL,0x844e328b219f6fd8L, + 0x620541ac11bd3733L }, + { 0x0f7fd382509e5a29L,0x8748d7d0b432531eL,0x8f749354cd3883b9L, + 0xc6b8ac748bfbb17aL,0xa4616a6605f2d2c5L,0xb3d966251bcb1b83L, + 0xcf7531042fee265aL,0xc70d73fbdb225058L,0x1211d434f0c2d556L, + 0x862061d854b259b3L,0xffe4606dc42b3f7dL,0x4c5c8585e86a4949L, + 0x04ddcc8b160eedacL,0x1804ce67568e2420L,0x91f3855a42141656L, + 0x7f378198f932be97L } }, + /* 209 */ + { { 0x9a374bdadfa6639aL,0x0cbd48d402ab7391L,0x5c5ef23647031e2dL, + 0xb49ee2bcd0599d1fL,0xd285eb60e0d38443L,0xdbbea92f269392e8L, + 0x91455fbfb8bc538fL,0xae259ff1e469b768L,0xc1cecb1f41de5682L, + 0xc876f0719952d1aeL,0x1ce25181e7bf7446L,0xcb93ad86282ad2f1L, + 0x8fa3cd316ba4ef67L,0xfce68a04e507aa3eL,0xced74170a61bb608L, + 0x6de716b3f6ac10d0L }, + { 0xd4e58d04172d6dc5L,0xbed2cde66397c65cL,0x7ae77e180c9eb4e8L, + 0x5627546875fa2edbL,0x4b30324ea91e6738L,0x6023a856235c8b2eL, + 0x9df6d6c2a8f92887L,0xec2c185ff6f5e8b5L,0x7892e12b3ad5748aL, + 0x7aebb4f2d54aefbcL,0x14915448ee868821L,0xa26c5f71b1d9bd5bL, + 0xe5ccd1662ff00df7L,0xebc99f17b95b1deeL,0x909836163fe1f774L, + 0x51f90830bb3d25b0L } }, + /* 210 */ + { { 0x49376fa1f2922461L,0xdbb1b1c31650d0d1L,0x92b91c330dd8608dL, + 0x3e612c4b36b89906L,0xe1977b0bdf560052L,0xf8afff70636a2545L, + 0xcda7d27811723d8eL,0x0b0bc4bb81bde7baL,0x3cb080b2ed2a578eL, + 0x5bda0d0d171b2e02L,0xf6df38cf941bb9aeL,0x85dd81dbc14a65c5L, + 0x7f98c82dc19dd98eL,0xc613747f52206f93L,0x9e13a2c25f5bbe78L, + 0x5eed218e0aa34be7L }, + { 0xe156575401d4dc0bL,0xa1ae5f27f566bb07L,0xe985ebebb82225d5L, + 0x5f3ad21c1189ec6bL,0x17da518cecce4d9dL,0xc84a2d3ed6b65b59L, + 0x7f9881758ffa771cL,0x50d6ae122ac69a7aL,0xcb7f30b1c6e6846dL, + 0x8c023a605bd0bb13L,0x9a10fecdd73f2407L,0x8c5158cce5f0a996L, + 0xd26bf615bd8f5806L,0xaf32ea87915a46e1L,0xeaf74e810287d308L, + 0x8c14ba06a6264254L } }, + /* 211 */ + { { 0x0c877895b17ee201L,0xc05aa47188e57a77L,0x19c3e76397822456L, + 0x0be6f8c0c9c3ba1dL,0xfe85f4ffb4389ebeL,0x538bccce0ce7fbb6L, + 0x876eab2a65266c64L,0x5c9ac690cf9a3842L,0x9f5cf3b1ccc8f981L, + 0xfa17be6a9cf687deL,0xfcfc10fc83835c15L,0x086b0fdb150ef2ebL, + 0x9f97ecd9884a52e6L,0x416e6fa2b0cd1eb8L,0xe2bd15993ecc03baL, + 0x645c0a5deabb165eL }, + { 0xd94c420550aa7e31L,0xaec8df0c2f851da5L,0x996469093c726e6aL, + 0x72dbdc362619bf9aL,0x1b4260e0e253fbd5L,0x97c259fb8c709e06L, + 0xfabf7cbbcddaec5bL,0xb4d5e8b1e4b703e9L,0x1b06e56e0734efddL, + 0x02d4a4f91f55f8a5L,0x7f8608ba3f565c8dL,0x822f47d2816d1d94L, + 0x0cc361565ce7b136L,0xe46ee5ef31d04242L,0xb2a65f70683567f6L, + 0x27e9ff40d2fa6c91L } }, + /* 212 */ + { { 0x75251893d7e952e7L,0x15b30583c735bf18L,0x732b599296fe0491L, + 0x27451858806d2fcaL,0x71ab76a01b885ed9L,0xbdce9d976d9f55ecL, + 0x3da60b2048f2ba9cL,0x6977c086592b132bL,0xb6dca9cb099051d7L, + 0xd9c2ab23d188ae25L,0x9f469f3fe20aaf3dL,0xdbd1f7cf5aad74d0L, + 0x3d5efe5c22a9eb3bL,0x8c5edfa2137010c4L,0xada2217b57870260L, + 0x4feee5673dac9776L }, + { 0x30e18d52b5d3d780L,0x4dadb5d307166744L,0x320d386e5a742156L, + 0x5d8c290e8d6bbb86L,0x981a43232d263dd1L,0x33d0e7ca98984636L, + 0x5138784da519acb1L,0x832e3fabdddc81ffL,0xfc2785943199a43aL, + 0x5b4cabcf32743163L,0x9fa010bd74f94fa7L,0xc28a743d5694a627L, + 0xc1d2a888cb657a24L,0x7eef2503e86a25eaL,0xed11a5d304c561ffL, + 0x4fe818e79c9ede0eL } }, + /* 213 */ + { { 0x00252c9d7fc1c7ffL,0xa9bd419d9fa89ad1L,0xc93a124a4064e9ccL, + 0x384cbcb843942eccL,0x004c21fd8749695bL,0x69c81d9f421165bfL, + 0xe2325628dde01102L,0xec9374575a9b004dL,0xfb3346bff6dcfc21L, + 0xac4da64b4d372c7dL,0xcecb7ad3f20494e2L,0x562c41b5e867c150L, + 0x299395cec2b723d8L,0xc91adfc57ee53231L,0xe06f1161f10b6597L, + 0x81915529b74d3ffcL }, + { 0x8ec124316ed9d4eeL,0x3dffa154689aff01L,0x4aba349f2a89a3f4L, + 0x2db1e8e2d467efb2L,0x18dea354039102e2L,0x422ab853e52f082bL, + 0x7130a2c1ed36dd47L,0xca60e86d0295d1eeL,0xe6ac68087c7f5ad3L, + 0x0f83cecfde864658L,0x72e66c21461d1265L,0xfeef4150bd385099L, + 0x0f183f3aa6632289L,0x275454be792dc795L,0x2744c11b11367702L, + 0x7d06bcc7e8ea6ef3L } }, + /* 214 */ + { { 0x892859427090212fL,0x691b7d4c5521e844L,0x4c038422be2dbb92L, + 0x317721edbd81f880L,0xc136cbeeac89bc36L,0x4f71b60b7b8f004dL, + 0x269132d04e218ab8L,0xb0e2496ee6cc814dL,0x0b2ce31775fadc15L, + 0x82e3c08466d223c5L,0x9721caa64c612f8bL,0x59a751eba4b65355L, + 0x3433aad5c7d3d9d1L,0x1e61b9d2e80d4246L,0x149f655ffc673caaL, + 0x48b52b99d0f9cb92L }, + { 0xa3915399efdc05beL,0xde70db1813e095e9L,0x447862e9cddb3fdaL, + 0xa2b031621a009451L,0x4b27980c23920ea3L,0xac5394f1a23b8febL, + 0x163f72563e5616d4L,0xaa0ff93fb714219aL,0xd26f96d293d62474L, + 0xdd212ea87dcfe276L,0xab27bf2f47038d15L,0xe58c8325f418168eL, + 0xe3704222b32a989aL,0xa3694390bfc9f13bL,0xf16e26060d0684adL, + 0x17c0de879d8c76ecL } }, + /* 215 */ + { { 0xbca5f453dcc01958L,0x7d9459541ce88393L,0x5e6350a1561f5b6dL, + 0x291c3c867e2d36bcL,0xf6c7ed84a5ac3a6cL,0x7913c40bd98006cdL, + 0xf78bb0875671ec3bL,0x1c928f6eb43e89a9L,0xfdf28df3ae1ea1edL, + 0x62bba5b1b924b2b5L,0x491d27051a116e05L,0x08ec02b7167ed3e3L, + 0xe291cf7b5bc0b046L,0x30e501698c5d7f59L,0x0c7c350df5c799b7L, + 0x6862b9e20ac6e1d7L }, + { 0x56c6f4e79ffa1f64L,0xfed6a91aa1e24349L,0xe9a0ee0ccdb75232L, + 0xbfc90b370322d607L,0x29480ad2462fef87L,0xfc214969c2bfcf34L, + 0x6e5211e0a539e38fL,0x2a59ec2612a5149cL,0x195fe212d706b532L, + 0xf77fb108e99c8429L,0x74ceaea35dc80482L,0xa5a6030bbd92d298L, + 0xad42dca5aaea15eeL,0xd6ac3bc74987109cL,0xc64e1c40290af649L, + 0x5093fa2d51f8de6cL } }, + /* 216 */ + { { 0xc4cf32804c2d553bL,0xdc1abe223b966c29L,0x556a549c2296914aL, + 0xd8c9f8b5999976c9L,0xc22c57bd776e83f3L,0x4f2942ab7c85ec57L, + 0xef3407e56e2c61f5L,0xf005e8caf213db48L,0x470c853df32698c7L, + 0xe6f488d7cac0a54bL,0xb6bd6bed60b7501eL,0xf0103106714a4bd9L, + 0x5285bc3b6e098894L,0xec06741af5f92a00L,0x32f16426ef7ef24aL, + 0x12f9c44d6c77a438L }, + { 0x1951e96483313a1cL,0x98edd3da33c58b37L,0x4edbbf52c7ac4044L, + 0x866ca6f70dcb5ee8L,0xec0ae8f56dd422f8L,0x1077bc540661ec2eL, + 0x6d39913ad422523cL,0xd105e1e858e7cb3eL,0x47c9397fc979bb45L, + 0x3221d4a90997b592L,0x0ef628a3e8952fe7L,0xd08d58274e946241L, + 0x64cbed0f59780f40L,0x13d7c22708e110ecL,0xd186d8667679b1a3L, + 0x02f75e4e26ae1d18L } }, + /* 217 */ + { { 0x1b637ebf47f307d7L,0x6b644a6ad0141477L,0x82a33d652e05a80cL, + 0xc8f1a0f3fed07b31L,0xc09ee7f93696e597L,0xcdaa7ec3c7ffc01eL, + 0x549f88fef8f373b9L,0xc88d1961c3bb8989L,0xd92a4fe9dfcaa7b7L, + 0x12ff9ee23ae4ab20L,0xf5aea641f5ecb1a5L,0xe769237fe32fb47dL, + 0x96a5c42025d085c0L,0xdc91255826c755a2L,0x580b985f9bce9723L, + 0x72b1b56663961941L }, + { 0x9d708a08790e5558L,0x985360410689af80L,0xe85e7b8a42313b5fL, + 0xe6ba129255a49d1aL,0x5e76c4b0ac371b0bL,0x58504f39938e6e19L, + 0x8dd4142260ae9a21L,0xd8b04e9b968485ceL,0xf94c4ba5887efe43L, + 0x11268e67f11c5e73L,0x92623e28cf6b99c4L,0xf2d0aaa87a0a9662L, + 0xb266772a4ca02ed3L,0x68ee8e4e2d63b551L,0xcdebb2992e78b5b5L, + 0x5df19216e17225adL } }, + /* 218 */ + { { 0x20027e1e8df2e7e3L,0xb183cc68d8da07deL,0xce35ba694b4ae694L, + 0x896d97df3ca62e88L,0x3de4713b52efed2cL,0xd006c40e26bd084fL, + 0x1e9b71bbfc81923bL,0x9991c7b61aacc6b0L,0x650c93648f656840L, + 0x138561d187f47524L,0x610f2b11bffd3ca2L,0x96915faffa191418L, + 0x8f1236de955e5309L,0x613cbeeaa1872d79L,0x7f7b44ea66a2a48bL, + 0x452265c2e0a89c32L }, + { 0x4ad5ec7925430010L,0xcac786ffebd090c0L,0xa5f9f4ff20a9d3f5L, + 0xfcbf4112a3edc65fL,0x8824839c0cf3eb11L,0xb8dd6d4e8aa5b700L, + 0xe2271dfdb7568ab8L,0xe43ec373b744560eL,0x78eaf9261cf75296L, + 0x1809ae0e3fa96d9bL,0x0b312d2ddc25dfd5L,0x6b8f78b46bab7711L, + 0x069efc8db5ecf1e4L,0xc1952bae609fecaaL,0x43e302ed5f4dbde1L, + 0x14b02bf91e078555L } }, + /* 219 */ + { { 0x2c71c768b87e5b57L,0x0bcc78f7f531a557L,0x4ff93f8bf7597dc8L, + 0xb28e026d139e175fL,0x6b83b727cb94ca6cL,0x2eafe3b20079f7fcL, + 0x2aca54decf3bd170L,0x17c4133c6af0dc6cL,0xbea1e665ccf5e35eL, + 0xa6691a48345505c6L,0x2633abd0e6100b89L,0x966c6706c17d0388L, + 0x7aefffbe1a0cf90cL,0x4d847be7d0add64cL,0xd49bcdfbaea2aa46L, + 0x85e07e742cc7d0a5L }, + { 0x23aae0a60bc25bcaL,0x6e8e55f1e44f64ecL,0xe1e696d8b607b773L, + 0xaa90a746d3005909L,0x072b1ccd2cbc4990L,0x0d0fe6c6c68e2f5dL, + 0x920ec5f053e28ec9L,0x79b21fb4f0040cc1L,0xa7375bd3fcc4a2c7L, + 0xf5f5def9e1bac7ddL,0xdc315d7935c0f8d3L,0x7117c1702cacd318L, + 0x6f2823c4e926f71cL,0x38db58bbed02f39aL,0xe5b492317db69323L, + 0x0964039f8d49f430L } }, + /* 220 */ + { { 0x21774f1656999ebaL,0x3d8ee287b1de6305L,0xd81af726de0b2669L, + 0x374469393f8942a1L,0xbcf6b615ea03e13cL,0xd30c0c3594e273cfL, + 0x4fd33a56c6725c56L,0xa57534ada8be97a2L,0x799242a67c22a251L, + 0x4e51bdb59d0c5c49L,0xd7cd76ccc6a42768L,0x914097acd426bf59L, + 0x59404a2c66e9beb2L,0x4738fe985c96e3e9L,0xbcbb3e0eaad666d0L, + 0x626b0fd263bc5e56L }, + { 0x47217dbae1a1ec42L,0xaa6ae7dbab5acc50L,0xb7e1ab1e865331d1L, + 0xb84530703d30126fL,0x280649e0dee61851L,0x8806f4a3ea689544L, + 0x4bbe43adcb56f632L,0x036b9bdabcaff94fL,0x0d941e65bd0637beL, + 0x82179d44686f3abbL,0x1486912caad6afd6L,0x9a3b891eff7e1534L, + 0x88c426ceeb86fd96L,0xb56e6a81117928c3L,0x933e713596399e00L, + 0x09bbddd9a17b6ac1L } }, + /* 221 */ + { { 0x75e39c1de4fd3673L,0xf880d9d1a65c8e07L,0x4725c1dc7289c7feL, + 0x5b6735ee3529d200L,0xc1f8f2ed3c747af3L,0x5cf3998f912efdf5L, + 0xed72261849859c39L,0x23793a2f0e69795dL,0x8a6ab8d686b1d2a7L, + 0x00c815de22a882e4L,0xbe77d6fcf9db8d7eL,0x0886fb3202267547L, + 0xb62687d449c10edcL,0x9f1c3e177c83ed4cL,0xe6d5d7f05af366eaL, + 0x2eaa01b8d1efad24L }, + { 0x5e47fb701f357c74L,0x93085c4aa9e3b794L,0x4f0987336e85a905L, + 0xf53808ffbe0244c9L,0x91dddf93a3b5660dL,0x8b76377bf3b95ed6L, + 0x91b911b7bb3920d4L,0x7ccf08bf86a13cf3L,0x53ed8f97ea018e58L, + 0xb1ea434378c55194L,0x8e6adde9e0d2d5a6L,0xfc2b248f9b96259aL, + 0x96ebceaeeef17dddL,0xf694b443557f9c85L,0x48cd150f07d5bba8L, + 0x02d31de9b4c1986bL } }, + /* 222 */ + { { 0xa6bb9e1ede79499dL,0xf6ca8ff8fd0fc2adL,0xbec0f8e81a7d9356L, + 0xbc3d1c9fe8f06327L,0x805c72173b300bebL,0x00420a08413c181bL, + 0x9e9a167ef0ca9d01L,0x076c909d1aeeddd6L,0x64a1997f8e3a8a72L, + 0x3ce7f7a7a77b429eL,0xaac0fbf45c94d3e9L,0xf37694a7e6d48407L, + 0xf56679e2a91921e7L,0xf23fe0f3ee1dbbd6L,0xc7917566cbf9fa99L, + 0x965860f2e0f4d765L }, + { 0xe734702b7fa5f79cL,0x930bd4265af2d26dL,0x45bd8b986c73e0ceL, + 0x7dbe7bed4ee44a2dL,0xc129e024956c8a1aL,0x6fdc05ac77cdf80eL, + 0x70a6ba2b589ca59bL,0xfc484021999825afL,0x1d284b547a23f0b6L, + 0xb1da10a428a0a8afL,0xb1eb1b312b2af6d8L,0xf051443a33935ee3L, + 0x7a07eb268effa6ecL,0x16ee4086d662654cL,0x7a7bc5014549ee4cL, + 0x650810321fa98a52L } }, + /* 223 */ + { { 0x49f0e460b67ed9b2L,0x0cda0fd0c36d93d2L,0xbb5963e988c75e1cL, + 0x757bbe93614bc0c9L,0x9a9b88019a768605L,0xa8b7e2af48edc544L, + 0x9e77ed9eb51a5985L,0xdd025274ebbf024cL,0x598b62881545c636L, + 0x39bdaed04800dba0L,0x7fc2013981e2a23aL,0xdc66fd5c550cb4f2L, + 0xad27032fb52068c7L,0xc9a0bcae8169fa15L,0x60606f213a7ca8a2L, + 0x982950469862652fL }, + { 0x3e3746002e11c128L,0x80dfae5d0e6dca7eL,0xe44016e2d9552264L, + 0xf65f88f2880b7143L,0xca3d28d4526b881cL,0xf9c59dd1dfb86afeL, + 0x548860c24c74f958L,0xd06ea43c9cb69f4fL,0x5343c9ae7334ececL, + 0x5cc2ccd635329713L,0xa95ff4035f3a6c0cL,0x2e01a1ccb372653bL, + 0x31510fdfa250523dL,0xeee538e2a6227eb2L,0xeadfc8a0ca23cd10L, + 0x4b7e6e1b3e78f54bL } }, + /* 224 */ + { { 0x79c9076fdb5f928bL,0xe6250bb6b7347cecL,0x54b67798ac00ec41L, + 0x900d20ba9d9619c7L,0xed42c0d059e4343fL,0x3df39e85451935d7L, + 0x2639118264f701ceL,0xce8f2554e1f87aacL,0xfddd678965f91aaaL, + 0x96cd163fa324539fL,0x5c815f2c4bace995L,0xd78c8c2aa94f9ea5L, + 0x7ab2aff4ef24e455L,0xf0ed64091cddc26aL,0x954a420b00ca2822L, + 0x0611c4c5d3297658L }, + { 0xf192001ca9e81829L,0xded3332008a282ccL,0x0bfd7de18f9ded9bL, + 0x6793ac0db7889003L,0xbb00d91d3577a5ddL,0xe17a23a7802d3c2bL, + 0xff95f88cfb549014L,0x7cd1bf4bc71b6e07L,0x2e3b24a023588c8bL, + 0x9b5335b8a4112076L,0x2481c05ec4056d30L,0x55c7410ce916a1b5L, + 0xbbe03271850179f4L,0x15e6c177b3cd1208L,0x509a24c090cbfe50L, + 0x820795291c108566L } }, + /* 225 */ + { { 0x5d2d3cff1c7d353eL,0xd5e7eccd7de0ce3bL,0xb4b1075f6ca87635L, + 0xda8404e025f9ad3eL,0x6b963e89205cb5aeL,0x9e5ee0d809f221a1L, + 0xd64c85d9ea41aca4L,0x6a46c4e934442a34L,0xac6ff97e3cf655a4L, + 0x76565c1ee5417d7cL,0x681009a9eebf9c4cL,0x95b61d3988da6388L, + 0x6402b46af6b472c6L,0x1fde51650b7f1171L,0x94f8f273be0c05e3L, + 0x7487b036a88344a7L }, + { 0xa860e5759c3e2370L,0x19d58193f8048719L,0x3a0dbf3ca6e2f9aaL, + 0xb6c7e9596144719bL,0xa9049c74deffec21L,0x8ba064b23f50cebfL, + 0xb12822c049a1de15L,0xb654b7d9b1d527f2L,0xc470859d0ffd0430L, + 0x37c74a674f05446bL,0xe553251ba3add995L,0x4a3ed6cbe33533b5L, + 0x2f2f44d027e419ceL,0x2d84ee82a5d1b979L,0xcc76b123db6fa69fL, + 0x834f85c521fa3bddL } }, + /* 226 */ + { { 0x329347c12ce9b31aL,0x1d88522afe3fb3b7L,0x4bcefb4d52ff90fdL, + 0x53b173862b1a081dL,0x538c11ba2a411f08L,0x7895b93c141b603aL, + 0x2993b9aab10bd741L,0xccbbd04609912986L,0x669fafb0eea0aba5L, + 0xd484462235661897L,0x4a63b89c367ffa54L,0xcbad5d1d1c3478daL, + 0xc5339227aa6034f7L,0x0e6d705fe61b1391L,0xdd14b660f74ff515L, + 0x639d8b0a5332b54cL }, + { 0xfa423162162217cdL,0x2e0e4a2a811c28e6L,0x68d9ce1821766dc0L, + 0x51263739046a06efL,0x44eea231dde92101L,0x0607c8f2114298d3L, + 0x27f272ba63d957e9L,0xe7ce80cca5e8cae1L,0x5816ebe224f7a63fL, + 0x4dece5a789673e34L,0x13756a22536babd4L,0x644d61aee3bf77afL, + 0x60b2bf6e2bcf98bcL,0x3b0b59f329fa962cL,0xb0769a1aabb50023L, + 0x409031360c75402cL } }, + /* 227 */ + { { 0x84d2873a1670433fL,0xc9394df625493dfcL,0xeb05a19a80fcf89eL, + 0xe39e4310db297616L,0x50742dc9d9e63046L,0xf31ad8c81de9ca9eL, + 0x86aabf94fb7b1d0dL,0x36cda27a1b3c82d1L,0xfb1a2ef439702d84L, + 0x280bfddc46081299L,0xe4b2b48dd2396238L,0x2db2c2f37b3c9353L, + 0xd5b5b31712fb8a69L,0xf9b87a3b08180474L,0xd85909861e952578L, + 0x80668eedf37a2bc8L }, + { 0xe2edcd35b39a0249L,0xaf230cd4b2f8aeaeL,0x295b15e47223df05L, + 0xbb66982ae0e937f4L,0x019d2b728cbc9162L,0x5c512ae9cf49dca1L, + 0x11b491a7630f07b4L,0x48d4f34ca03874e9L,0xc1fd0ea644cb7433L, + 0x13f79ae1f95b30c3L,0x40362d4ded8b60acL,0x9e8314ff61ead81cL, + 0xed600dd4498c3d28L,0x5fcb1c19c2521702L,0x592329fc3a9c1f33L, + 0x046775481bde6ce9L } }, + /* 228 */ + { { 0xee3de56e39233c96L,0x868c409c80737eafL,0xacae11bd201abc68L, + 0x0f2cea9b2b486205L,0xe32387e16f19056cL,0xea75365aa5dc2a41L, + 0x76c29acc12b4be86L,0xa01fcab78d63294dL,0x81dbe88b0cab9f24L, + 0x76646e5bf414c054L,0xfe111893cb96b7aaL,0xb649f5b17664e097L, + 0xa196422e53fcf5a9L,0x5978c9bd0b7ff634L,0xb5feb38e3c229895L, + 0x038a49fb0833c456L }, + { 0x35e3818c13e93257L,0x14cebc9da612741bL,0x4f6e92497caac06bL, + 0x82278e333daa1116L,0xe7cc565e4de2034aL,0xbb7dc95f0a1ba630L, + 0x81dd9f2366956fbdL,0xc63e6319bb132dd6L,0x6e22b022fc241337L, + 0x238481937e8beb1cL,0x83b1994dd8c938acL,0xb54cfacaa6bb5644L, + 0x1a7cd44e06f91807L,0x1dd439bba8f8d9f3L,0x660c2a787f74a8e6L, + 0x4bb76e22121b5660L } }, + /* 229 */ + { { 0x7a151e8ae6354817L,0x33d494eaf038b438L,0x4c86c68885958986L, + 0x721538271dcbac12L,0xf487af8cc0edad06L,0xad33051fe500e5d6L, + 0x0a711b1bd6e47f55L,0xa68709a78c746ad5L,0x27f172626402f35eL, + 0xc6d08efafb30c130L,0x9ef1c041c06c7497L,0xd0c74ecedcc3e2daL, + 0x30c5f96e092e1073L,0x0f1393cf2aa12b74L,0x245840162107eb02L, + 0x8843d25f7b76f98bL }, + { 0x4e1501dcedb2a83eL,0xbcfe8fb02bb8d724L,0x09020659d925df62L, + 0x3c715dcf42ab6fc3L,0x73c05055a0f09dfdL,0x126745d8e3590aeaL, + 0x5382f4d876ff749eL,0xfc69feefa920c663L,0xde1602119fd711caL, + 0x4219c3bd9075c4d5L,0x3800cbd13ded6bf2L,0x8c7ea0eb6263a116L, + 0x35bd79587d264c37L,0x56e22e457159c98cL,0x71bf2a2dfa7373b5L, + 0x0503f9398935c949L } }, + /* 230 */ + { { 0x65addc6671dad4f6L,0x238e4889024bea1bL,0xfb76c8e2f605d3ddL, + 0x13d5f5deb0d96b89L,0xe0b5ba356601b2cbL,0xe37d491d83e3d254L, + 0xe8860423240c8ea7L,0x374182f3e91c99baL,0x26c2caf9a87ad919L, + 0x4b13040af574f295L,0x5b9bced1944000a3L,0x4ccc57be06df42e7L, + 0x22e8ec504bd1089dL,0x0c53177adddbb500L,0x690d31d29ecfeadbL, + 0x735778fe176668f9L }, + { 0x0f86ee3e843c1137L,0x3c1c42fa3f0b73cdL,0x0e75679d8ab20e3aL, + 0x6f95f1f416242faeL,0x7b88e11c39b092e4L,0x1629403e4c236ac0L, + 0x66105f412dac02e6L,0x74dc28a7862e0632L,0x2118ffb2f3b23c8dL, + 0x1182417c0745ffbfL,0x49b55a044c05711eL,0x2c665b74cefbe4deL, + 0x1cc4c01d97bf7107L,0xb2ca06dac54f0676L,0xfc599daa7450d0f8L, + 0x52e637a61a3182a1L } }, + /* 231 */ + { { 0x481700f16bebc6dbL,0x4a6b45dbf9503d92L,0xc715cd3c5d153919L, + 0x942a1c05e5ad2abcL,0x36a82433ab7b466fL,0xba413bedba13918bL, + 0x698a562490f4e6ceL,0xbb720da6f3f1f3caL,0x2116d41d63471ab3L, + 0xe00d2227303d3609L,0x7fd4cc00463ba69eL,0xac609e4d62845fd1L, + 0x63603b2c80adc9c7L,0xbf16fc9a45fafbcaL,0x41007f7fc4bc94abL, + 0x7c916b4fa74b1698L }, + { 0xc1026f9178bac2d4L,0x8a2e80982601a875L,0xad2f276e0073d640L, + 0x443610c4fcc1fb88L,0x5727b822ca6b291fL,0x0645532c88ec60fcL, + 0x51e48899ed9ad48bL,0x841b48b5f543f103L,0xa6ccb1bed591ceebL, + 0xfc4adf0f9dcf5a8bL,0x3a7ca020b347ddb4L,0xaa1accc2cb44c521L, + 0x773b68280527c0c4L,0xaa374c107023cf50L,0x733d10006b74c926L, + 0x1ff3916f77a8d07cL } }, + /* 232 */ + { { 0xaa218fe4f997939dL,0x3d4dfbbb791583b3L,0xb3a7b5da87f7560bL, + 0xa9c028015da92c98L,0xe1eb4aad46666f4aL,0x2eb17a5114ce9dd7L, + 0xf46a66a4ef8f3076L,0x900b45c6810e546eL,0xf7af22584baf04ddL, + 0x3cc1c8725c84d42fL,0x3093f2258e4c83deL,0x62fade41170d88b2L, + 0xe19612e4ac076e44L,0xf48d734632dd141bL,0xc1b1f759925e34daL, + 0x19ed1a56072b90c9L }, + { 0x9cf7fcde6c735473L,0xaab88e676003bc3eL,0x12187cbcfb199bb8L, + 0xbb7304419accccbdL,0x214aff3cb0f65459L,0x6aec81a36f926282L, + 0xaa82cb329f9d20b8L,0x82f3f90f5773cc90L,0x4af60e6bf62257e1L, + 0xf18b44bfbd4762dfL,0x3948b129db970753L,0xc6e920e97c22c18eL, + 0x393d620857be97adL,0xe8d7382c46b637f9L,0xf6625ccbf1fed1d5L, + 0x6f31e0f968681599L } }, + /* 233 */ + { { 0xc45afe5582b8f204L,0xac0441b6d358b54aL,0x7213e7bfacd5f5edL, + 0x1914c70b139bcd93L,0x714b458196dbcbb0L,0xe9297d351ed35d21L, + 0x8f6408376a3e1f20L,0x150a8a9d2f3cd705L,0xfb36e801dcdd9f6dL, + 0x5a54eb655cf56d82L,0x7610500c92aa5a21L,0xd10d0ae23b089f03L, + 0x491b2079c42b66e8L,0x4af1ae3d0eee8d48L,0x137e4c2841556f45L, + 0x875e330863d8a7e6L }, + { 0xdc80fddcaf6c0accL,0xd5ad1e66bb1e7c08L,0xdc717ae1828585adL, + 0xbdc54340275c7da6L,0xf4b4c852d26b9e15L,0x5f0a1fbf6a05fa50L, + 0xc6f81e47817bcb32L,0x2cbd432870ff2e1dL,0x8a24901667c7f7fcL, + 0xd045acb7b585a6c4L,0x2e972ad44666c057L,0xc74d87cfe6d7d63dL, + 0xf7067d870e274144L,0xb2ca157a8b2584aeL,0x495c5bfb75f0fdebL, + 0x5abb0581f386e009L } }, + /* 234 */ + { { 0x8be62d2bf0c97f57L,0x0fe04871962f28c7L,0xc548a46747b50abbL, + 0xf6b26e0344fa09edL,0xfd44c6e3ab05a96eL,0xedb0032c70e6ae82L, + 0x28bd402bd7e4899dL,0x43f2e9639b7c11c2L,0x0ec3fc0ece913716L, + 0x769b8bc902fd0f8cL,0x9d9cb3aa7cabc3acL,0xe88a889206924cc9L, + 0xa51461aa42609014L,0xc7f4aa8b962e79e0L,0x4ef0210a8b1b3e80L, + 0x705446801bfee4bcL }, + { 0xfab3d713121901c1L,0xe90a2627fead54aaL,0x64f6d285bc08ba23L, + 0x8d99301536ec227eL,0x99a16ab906c191abL,0x86b1cf5bf649ce2cL, + 0x5920675966be3a80L,0x18836279ccba2cf0L,0x2c157b87eff53486L, + 0xbfac98964b223af2L,0xcd0fd4f00aae7a57L,0xdaddb94063218a80L, + 0x3844bb79df88f14eL,0xc1b3e3d4b71ed9fdL,0x6c634a13d6205036L, + 0x6f56aecfb8680a6bL } }, + /* 235 */ + { { 0xb01dc803d9205c5dL,0x68955f7d67123929L,0x3debbffd9d9b6565L, + 0xb844395ed3b1acfeL,0x04328b216094eeffL,0x6631ffa822991febL, + 0x0dde66e6190dd075L,0x75b03c55e8577c05L,0x6c91ce5f91722407L, + 0x9a288a408ebb3a3fL,0x1d376f8a058a1396L,0xf3a594579a6e0676L, + 0x103029c57b71d288L,0x0843f428b44c30c0L,0xd8e6aff8730e0b9cL, + 0x7b6be8114ed644adL }, + { 0x3ec38e4a3d3aa54eL,0x10233943d83d509aL,0xf84aa621243955e2L, + 0x29104717f51d3d44L,0x62d2442c7eca4e37L,0x8c5a523d85fa55deL, + 0xc6f5ccda851da1b5L,0x044bcaa820001468L,0xf7501e68e01702e0L, + 0xf0819359e6a0acecL,0x33dda6adac0ef0b2L,0x97aeedc8fd964f01L, + 0x48dacd0e530b90d8L,0x4c5fad6fb84122ebL,0x2284ec1ed700a1deL, + 0x86f9a835dbca5474L } }, + /* 236 */ + { { 0x0e1d9055450cc69fL,0x50eb14bcc9edf98fL,0x1bb94e77ee7eba01L, + 0x5f7a6737998f8e53L,0x588384e31b16eef0L,0xbb928723d85c5e15L, + 0xfe51e345cbd952aaL,0xc5d0ee287e241674L,0xfdc146ef100182f0L, + 0x0f739e92e7f5be2cL,0x501ab3afb656bd3eL,0xb1552dde5168e289L, + 0x940dfe31b8ee104aL,0x42923603c4304475L,0x9306f114c460a913L, + 0x5bfa9faf03b51f86L }, + { 0x2a23f52c107b258eL,0x989e82bbd66341dcL,0x54a3ced8823cff1aL, + 0xf45b7794719b491fL,0x898c22182433dfb8L,0x0f9dd91cc49250eeL, + 0x50c2a2ae4fa17655L,0xf7aa1ce42c327f45L,0x13a15ad6583b1e41L, + 0x9aa0d5a5a1bfad9eL,0x9b1caa288e1fbdcdL,0xaf9283b6915f7f87L, + 0xc10e4e0c87e81a1eL,0x04fdca561080d296L,0x6acc961612755bd8L, + 0x1b1266aa828feedaL } }, + /* 237 */ + { { 0x4ebc0a00774ee49cL,0x776f6852cb6237d7L,0xfc0544ac5df938a3L, + 0xc3388ec8b6fbfbbdL,0x84ac8bcd745f2eaeL,0xa9c56609b1ece937L, + 0x656fb6ac7de8fa13L,0x5f8ded74a532b871L,0xab0d428baa889f09L, + 0x43b27f2810b7aec2L,0x26426e1efeecb34cL,0x44431b6b9e89c2dbL, + 0xaac4bc5d39211090L,0x926f73684fd81058L,0x452fa691471ef60eL, + 0x33517fdb218d7a23L }, + { 0xa9c33f46593c4a36L,0xac69d71836b1a9eeL,0x55a20c1d4277beecL, + 0x3e8ca24e7e4f179cL,0x57373369d46d88a2L,0x71ceb1cc730702f8L, + 0x8b184d9735eed574L,0x7f4517a20704cec2L,0x7f129d18d7062a53L, + 0x07a4571bb1d77e1cL,0x774ac3098350d8b2L,0x27b2919f61fab8efL, + 0xa7c4cc13b5dd801bL,0xe7e6255b1434591fL,0x349937b85a3592b3L, + 0x31fac63d30c77549L } }, + /* 238 */ + { { 0x2ee8cf1b04913fb6L,0x7e4013501769a6b3L,0x790ebb71783e61f0L, + 0x1e5107f9e27f2ffeL,0x124ba67fedaf89bfL,0x189200e1e58de68dL, + 0x962732a36df5abeeL,0x72cc37cfacbeb4aaL,0xb0c5fa96e93c5a76L, + 0x4c2a317cde63393bL,0x97f65e67830b2d6cL,0x4afc35041be5b96aL, + 0x0bf40a60730ce66dL,0x96a1ba799340d84fL,0x3ee1825407626b08L, + 0x01db35db7ab0cbf5L }, + { 0x6e0fbc2dac0efee2L,0x8406ebcdd71dbb45L,0xe72bde3e19b69abeL, + 0x49cb7e6137e01822L,0xcbb8c01c11458b4cL,0x420b4847687c5d63L, + 0x1847dfa1454c6776L,0xbede911dd1839d18L,0x1b9dc9c9278df046L, + 0x294bd62b881a336cL,0x7f09687993e77adcL,0x7ac9066543ce3ba7L, + 0x148695fd7764eefcL,0xe0c20f0b9ac465cfL,0x636e8d28a6e2cdb1L, + 0x7b6ba98cd755341dL } }, + /* 239 */ + { { 0xcb1d9e03c1881ab4L,0x19c25d55b3168c88L,0xa82d3d47282364ceL, + 0x95994390f161aa24L,0x7838bc00e1ebb2c9L,0x8fd5dfccbdec7a75L, + 0x4dd203c24ff7220aL,0x5ec173b30efeff48L,0x99f1d2b316428b35L, + 0xc06bd9e5056e813fL,0x929172bac0b319f1L,0x6ae0e384fd223b15L, + 0xbd01059e98d091edL,0x6b3168e4a654648eL,0x2211447f3375e798L, + 0x47e8101971eb4508L }, + { 0x7045d45abc8c290dL,0xa33d1355810fb33aL,0x2baf009246fbbf2fL, + 0xacff3f1b385c7cd9L,0xc5b150ece161985cL,0xc6ee0a7f2a888748L, + 0x9d888c8e5e88dcc8L,0x4dd735f2ccb86443L,0xcc1e13b73c40f6f2L, + 0xfc3a25fff3fed691L,0x4cb43b17257ee5c7L,0xaa654f93f32db135L, + 0x44f58d0a02dff2d3L,0x78e3f188a8ca6394L,0x39646ccef3e86697L, + 0x785b1902e0dce87bL } }, + /* 240 */ + { { 0xfcce2361a92f9a20L,0xb7bdca879d64540eL,0xd4739a851d00d7c5L, + 0x067ac8dc2e97c926L,0x2aea3ffe78da6a8bL,0x6828bf5463c51b69L, + 0x76f1c4797155141aL,0xf4bcbef63977d810L,0x75bc4949541bce7aL, + 0xe01f4066d17041a5L,0xd282d5bd87755eafL,0x6e2107dd59e7ae80L, + 0xaa56e166382ab36fL,0x65ee8ef6b9d1d634L,0x99a2160ace4ed844L, + 0x6557c367b7712c27L }, + { 0x561b0268d75b6e52L,0xb0813640118d0e89L,0xcff533306a2eb1aeL, + 0x4e4622266d090894L,0xbb351227b5fc1d48L,0x9365ea0757a3062dL, + 0x4caca37bd66e2dc5L,0x220d7d23b9095887L,0x9c0fd3938c4473bfL, + 0xadff370a6787da4fL,0xef0aebccd057f4b8L,0x205e744c1173f33aL, + 0xb8d1f0a5925a26b4L,0xa9364f49722fbbfdL,0xc891ae778227d284L, + 0x15c40d04a0e08ab4L } }, + /* 241 */ + { { 0x9baf169a2a0e18d1L,0x9971c0174c0327c2L,0xd81a323f7bc262ceL, + 0x2099db8d818ff379L,0x663f663d4cd3c330L,0xef5325c3011a0553L, + 0x9cd70bdcf980a470L,0xe64452d11c9ed070L,0xafbf43f4ac676e13L, + 0x97bec0a6ae85c2a5L,0x2faae550470490c4L,0x0ab97a87491e6ba9L, + 0x4055f537aafa9914L,0xfc95adbb36726557L,0x646343b9d119d6bfL, + 0x788e94a09d341e37L }, + { 0x053a6fe59c53461aL,0x75ec897e08e3b6edL,0xa8f5d2f30768d939L, + 0x9bd6bff6cc213d4fL,0x590c7b4105b0147cL,0x20a3628b7c7b8169L, + 0xc66a086e5bce78e9L,0x3dd4d2824dec1d8fL,0x890acf44c19dcce9L, + 0x6632d875d8435a7eL,0x590167c1ea6381b2L,0xb2259797f0dcc128L, + 0x91a612b446f8d463L,0x42185d78c15efa39L,0xdf55ec37119f6788L, + 0x91b19cc6780dea93L } }, + /* 242 */ + { { 0xebf2709dcb5d8b80L,0x03b96182fc35660eL,0xb873d991055ef969L, + 0xd1ea4b4de47c4342L,0xcc4b9244d54f8867L,0x93b1a2cafd8d77efL, + 0x068d24e7e8c1f563L,0x5f5fabb649973056L,0x83248c500542374fL, + 0xc36de2b53f38e913L,0xed07e8eb7bb680beL,0x964813d7d8f313b5L, + 0x7bb6a069afd2d392L,0xc06d848e0848a31aL,0x6867fb2fe4f0c325L, + 0x3c2ba834067343afL }, + { 0xab62d7759d3ad63bL,0x3f9cab9759e0eb1fL,0x70332a633885e117L, + 0xf22cafcee20b2f9eL,0xb529ba7e49eca947L,0x249542166228d88dL, + 0x80ea23ec39239561L,0x1b8907e7d4370644L,0x4b7fa455563e4e44L, + 0xcca9829eb2a4b0faL,0xd0a720a448060792L,0x8ccdda0c246991ceL, + 0x37a2325b348d086bL,0x566ed509f60aee13L,0x3d30e091147f253fL, + 0x1fa627a5c1073bd8L } }, + /* 243 */ + { { 0xa11222a242478fd4L,0xacf4c6f1670b2000L,0xf71bb04f8359c6deL, + 0x618e28297b93cdbcL,0x96e1bae3230db60bL,0xf17fd3b4965b3b29L, + 0xa58639c6bc7055ddL,0xc3ea92ed4b817d7fL,0x9082b2a6d23b08a4L, + 0x8471228adc17010eL,0x753b9e4620e89d97L,0xcf7e4f9703ff77c9L, + 0x6c3f82452bbe60e5L,0x9e432cbcb80e017dL,0x150a5acdc0a45edbL, + 0x67b8bd054798743eL }, + { 0xe66079b4f4797cf7L,0xe31c998ad03fde02L,0x5aa3763a54caaef1L, + 0x64d9a1fef7649711L,0x7ce0dc73af29b1a7L,0x6661b083fb66ca93L, + 0xbf4d74fe32fb6a78L,0x25f6ef09df00a561L,0x2bc4383f831d1159L, + 0x6d5cc10c536bde37L,0xd4945f9f882cc65bL,0x81f48f13451a99b8L, + 0x140161cd6bac11a4L,0x9d94d4edf18a4a0aL,0x65363165a467a824L, + 0x74297aa9a4c9aedfL } }, + /* 244 */ + { { 0xc49758a4e21124baL,0x99bd8198a87ffbd2L,0x45fbcdd13d6638a8L, + 0x94645ff815f7bf76L,0x5fa6736fc4e6d57eL,0x1eae647592e61db9L, + 0x79575c0ccbdf944aL,0xa3d1304725b31d74L,0x7881df224cab5ae6L, + 0x8dbfd2991a2887f2L,0x23d07590a26ac459L,0x2e589852d8661d4aL, + 0x37b5c13b8a0140f7L,0x0f94199e3fb3782aL,0x722aa0591bc14e90L, + 0x89aab7bad55bbb12L }, + { 0x8b345a96d656bdc7L,0x43bdc8afe176cd3bL,0xd69518b632d64c43L, + 0xfcf364a779b82b41L,0x907b344effb0cf82L,0xf3d0c83c5101287bL, + 0xe9f26a5934cd90efL,0xe5f5aaf207082b5cL,0x4eb72c75ece7c165L, + 0xe9590a81be986cd6L,0xfeef498fff1536aaL,0x04560243a8263d5eL, + 0x940be14f54ae872bL,0xbee7bcc9e3207686L,0xd496a27dc1bc4d7aL, + 0x002dc2975940ab46L } }, + /* 245 */ + { { 0xee533937b69d60c3L,0x260be552fe972755L,0xb11fb78dc0c725a6L, + 0x6982c27ecab2e7c2L,0x4bceedd9ee2322cbL,0x952b19ed122704f7L, + 0x2df4c285854a6165L,0xba40b5bf7b192485L,0xfcbca9500119f52aL, + 0x7467d1cbe5add86fL,0x9bf536fbd9d0f2c1L,0x3c296e34b8d4ebc9L, + 0x0495f8f405a81317L,0x8c59e8d673335f76L,0x0b53d324e0542122L, + 0x4d5645353c3bda73L }, + { 0x7322f8007e5c0877L,0x481b43e60ca9a764L,0x231f4f4ba2c12716L, + 0x09596857ed3136c2L,0xae82632238db30deL,0x652fad4099908ebcL, + 0x0b8d1814af0d231eL,0x2680c54b09cbc349L,0xfd4562f34bf3bf8eL, + 0x2985090b092b595fL,0xe6f39ca45e15fc34L,0x70175191bc378168L, + 0x906944b3845a4a87L,0xacc6d74a82a1541aL,0xadc9bab3b155c8b4L, + 0x1f2f89ce77306c62L } }, + /* 246 */ + { { 0x8253ef419affefdfL,0x05d7ece54cf9256bL,0x377002f2b444e483L, + 0xb189755fcba5471fL,0xc88483cbd5cbe015L,0x254f7c696a0b8429L, + 0x18850bd461f3f61dL,0x7ba210890a247157L,0x35abbc2ed92eeb0dL, + 0xfb56cabe965dec89L,0x9da23724bc55684aL,0xd8ba396f6a7a7492L, + 0xfcb90db72ef4ba46L,0xdd234fe09909b27aL,0xbdf3c16476f4366eL, + 0x09c8097f17e50d47L }, + { 0x6a04b14060050c07L,0xc29e831843a8e37eL,0xcb9429b2bb55e41fL, + 0xed2fea5a2ce60e3aL,0xdc7b1ff3db9d82f4L,0x48ebecc3687d37faL, + 0x79153e32ecb07539L,0x6a60054f57075692L,0x3871cd0c800759baL, + 0x17a7386f30922df1L,0x4e9fc59e83357b7cL,0x1d26b3a939415186L, + 0x912a0222d34db889L,0x6672fcf459fcdb71L,0x5a3f268d44ff3036L, + 0x6f113ed36911e16cL } }, + /* 247 */ + { { 0x52a9df591836f1c9L,0xfa6519f54232307dL,0x8406c7015ded285aL, + 0x0a1545caaf627f75L,0xae1111eeace0417dL,0xfb28bdf6a6113443L, + 0xde9ef0ab52dbcbcbL,0xe9dc181b7813e658L,0x0b1dabdb99127225L, + 0x5f0598e322814c59L,0x5c3b966ed934ee7eL,0x4eb84edab99ba4bfL, + 0xb2919a343c1b55e7L,0xa9addb4994aa860fL,0x1b7220dff6811ff6L, + 0x6636a23bd1a183e2L }, + { 0xdf5d5a2d20587283L,0x0b3822c9ef07fc5dL,0x1786bd550ef6de38L, + 0x163cf90725d1671dL,0x74bf971f1cdb1defL,0x5749e8300842fc4aL, + 0x0e2edbc727f854f7L,0xbb27bbdabce24acbL,0xc1b19cec05bed08dL, + 0xaada123ef7c904bcL,0x02429f1bd89982dbL,0x49d3616e65f6e632L, + 0xa3789fa8ee59fd32L,0x160ba3bafe9f29f5L,0x0f2d3b61af5378a0L, + 0x7aeecc7673c2a6f8L } }, + /* 248 */ + { { 0xf3a4757cdc43b0dbL,0x3d8a4e8598119cadL,0xf8095bf64616c156L, + 0x3e2a07bc4f533e97L,0xa982436739cfc5adL,0x18a6ba3acd68052cL, + 0xbd60e5908a1cec66L,0xae3841a502b1b695L,0x986dff12190a195bL, + 0x2df2beacad31fd9bL,0x7d893224cc728f7bL,0xc38ea7380cf0a992L, + 0xa8439a80586a44eaL,0xede7f7f01615f03cL,0x4824990827a1f885L, + 0x28ec4006b78a7645L }, + { 0xe1820c2ea2fe0009L,0xe11ba5d2f13874e9L,0x97522454c524db52L, + 0x4d4774267fede529L,0x01d3419a9b2500d4L,0xce08a4921869244bL, + 0xba169023dd1be1b9L,0x242c3e5432a301e0L,0x9b56f7ba70906788L, + 0xf0ad2a09c74a8cc4L,0x99cd1841d76f9439L,0xeddafe0b621fb60eL, + 0x056bee54bc397634L,0x4653f860ff7f0a84L,0x6bd4876f2011c0afL, + 0x134f4cc70c9525c3L } }, + /* 249 */ + { { 0x9621a3ece938dff4L,0x7d101a7b486a79a3L,0xf2c4ef97de950537L, + 0xf3184099e65d87dbL,0xb89c7ffb373b8cfaL,0x68baa505e842916eL, + 0xa790fd094ebea764L,0x679df6d4e592892bL,0x2023331cfcfed741L, + 0x0bf4efd29880ff21L,0x7ca78dddd0344501L,0x2cb09ecb342858c8L, + 0x9e5eb6dc2575487aL,0x50675a15ebcb0491L,0x09d2e74f7381d471L, + 0x6ea3782983d3d6f4L }, + { 0xc65c094b4e5cc40aL,0x7a2e3f6a1af37dfbL,0xef677e9df9026e44L, + 0xb7878c9593880f53L,0x4aa30b077f644aa9L,0xa0c516832f208c3cL, + 0x7c0277ae658d663bL,0xef0b3c38ae1d9130L,0x302f37a7695c3ea4L, + 0xe004c1c56a0c5e0dL,0x9fd495c420cbcf9fL,0x706d5b9d568a0e7cL, + 0x8b225dff59286454L,0x527d44658d9a709cL,0x47c558da87c08d68L, + 0x606ee6e6bb4ef07dL } }, + /* 250 */ + { { 0x02d99fc757c621f6L,0x292e40c17fe83d48L,0x1bdfc7a19ef199b0L, + 0x78a04102e62c7666L,0x16cda370e6738753L,0xbc81974d1e3a65afL, + 0x19742048f78fe209L,0xc83a058abf5981c6L,0xf26b24349c89702dL, + 0x988b2f1e9d1a678aL,0x472bf9b0ff29ae29L,0xa143e3981d7cf5ecL, + 0x9c9d7e45b268ddd8L,0x166cda555fc4ff76L,0x6044cdf0a4aa7673L, + 0x49dba6f7e9148707L }, + { 0x20e47fb2a758e37aL,0xaf6b31d72d8eaf66L,0x352ad5f96f9c2210L, + 0x0093f72790efc32bL,0x435c99dc41e4b264L,0xbfa878e005b15795L, + 0x99c520a40e673575L,0xca68259487eea759L,0x029f7b81f12a348bL, + 0xa547cc182aa2ce35L,0xa11d874bead5e2c5L,0x9af0349b55682cdfL, + 0xf86ebfea8bbe8e66L,0x3dab8782f55394abL,0x458bf797ebc8eb8fL, + 0x4890a7a49b7de78cL } }, + /* 251 */ + { { 0xd72996898da995f6L,0xd39eaae7ec6156efL,0x6959040c356a82d5L, + 0xb2046b21c135bcfeL,0xea720b640f595c78L,0x02824efae7c5fb40L, + 0x97d8fd4c0edb3bfcL,0x12f0290579f24ebeL,0x16fc47cf187ea6b9L, + 0xc219fd27789d5c23L,0x233a6b6c89263eccL,0x823634b28b6d30a6L, + 0xca352e25c9b33680L,0x9388d6ca40c77456L,0xf8e55b0b3c92065bL, + 0x5c17474b02439a76L }, + { 0xd888e7c28aaccab5L,0x18027836aaced05bL,0x185b877dccec0f65L, + 0x93cadc1c125c2882L,0x45df540a67fdc54cL,0x4f3c86e2c2788a33L, + 0x3e874469e3a0fa2cL,0xc59daa47273983cfL,0x3063c48b4a96d8a5L, + 0xc38d2bcfc2e58915L,0x90e78b8784e428c3L,0x900a292cf0c4fd53L, + 0xb7f92db7941e6005L,0x956792416ca53a1cL,0x35f6f31db1ab0fa7L, + 0x5d675eb47b58408cL } }, + /* 252 */ + { { 0xaeee1a77870c6025L,0xfc4a23b791a2dfcaL,0x7b0e60c4386b64c4L, + 0xd5d5b17de5ae72b1L,0x6dfc88ac9eefa212L,0x4feaefbed4038b96L, + 0x099ac3568e2d2eccL,0x548ea612012af207L,0x4ffed9db89c31218L, + 0x1c1e91c4e0e67331L,0x009bb64faf8300e0L,0x8780501c6773c3beL, + 0xe0cd6edec08219faL,0x7c055e07f81b06ffL,0x82b63f9ce080b36fL, + 0x02fccbaf0a9feca3L }, + { 0x9991d4d1b47cac61L,0x2e9d1687ab86e12cL,0x8c6855ec2b94f042L, + 0xca40051948e648e5L,0x9ba91fb2ef89ac57L,0x4f4192061be792cdL, + 0x82d221cbbd0f1e15L,0x062eb13bfc444019L,0xf3a97c3299790fdcL, + 0x4e796d946067a64bL,0xc46dd3006d23775aL,0x8672c4d5ed7f0f23L, + 0x821851dc3b4f63d7L,0x50a3ae0cd26273f2L,0x800e58fceac60f6fL, + 0x56f1e45613845545L } }, + /* 253 */ + { { 0x01ccb3f632c24f3bL,0x99eb1c7f06d817e6L,0x8dc640bb6aa26776L, + 0x7838affe0845d5e0L,0xf34fecb1f81a79a8L,0x6a2e282d3e6819b0L, + 0xc4b977ce8237a4b8L,0x0f46b3db87636439L,0xa465f54097970497L, + 0xd7e087628791be43L,0x00220b6c34198ec6L,0x57b38637093d94bbL, + 0x84012e1629d690b2L,0x02ec9db520aad1a4L,0xafee2fc685dc34e3L, + 0x911d193625500cf8L }, + { 0x13b1bd58f5e5af5bL,0xa7ca263b7b6a22a7L,0xab6bec4df3af2adcL, + 0x16651e59a04420bdL,0x3b448b3b4ba36c11L,0x3c62bfcdff424310L, + 0xde15c4a5f1a96cbbL,0xbe0ad8a1e4d1f980L,0x812bd14e36673a3aL, + 0x40303af69212acddL,0x8f6dab9c576095ceL,0x7df1882a107f5ca5L, + 0xb903e63c8896a3b0L,0xf5048544d863b3f0L,0x5e5019b9c09887deL, + 0x2be744fea0f53865L } }, + /* 254 */ + { { 0x054cd05f5b50f324L,0xb9b1eb241ea3c7a2L,0x4a858a5c7ff8e6b7L, + 0xd83902feec040882L,0x72b26494d0cba9bdL,0xd0176f90b29c9e1eL, + 0x05d4eb02cebadb81L,0x874405b1372b8bfcL,0x5c41288179ead190L, + 0xd44a3dd3ec2b48cdL,0x84499a773f4d5033L,0xb37b38cd564c3a09L, + 0x80e99497f42e803bL,0xc07b47a0b8f518b2L,0xc710e3c53568fde4L, + 0x735f542fcead0e7aL }, + { 0xcaa9a17138380039L,0xadfafe17f74d19c8L,0x92d4393eccbc1a8bL, + 0x3c5dbf39fe029705L,0x4552b5ab930e9b36L,0x7ee630322afd494aL, + 0x826a9ad73f02ac43L,0x98c5356299356298L,0x0c869f877342bb39L, + 0xd7510020e4f9b79aL,0x6361d1a4d34789a9L,0xf0ded5bacfa85637L, + 0x407ee73f88ac07e4L,0xfac7d03f09ef1cbdL,0x25d697cb4d475badL, + 0x1e984c9d14bd399eL } }, + /* 255 */ + { { 0xc76d05614850c817L,0xb08a5b193489812dL,0x7273d1545e58cbbeL, + 0x8900b5fa4be61e5aL,0xaa088691d7aeb8e1L,0xe66666afd35a3d4bL, + 0x38a2c19957ec7d3dL,0xa0648e8f668d6f5cL,0x1f9fc92c7adc1746L, + 0x23a116c0843065c3L,0x36370a2061e6ae69L,0x626c37362aa47e73L, + 0x540c25f2deff6d84L,0x9804824ccdbed2d4L,0x4b5bfce0039a9492L, + 0x6c474a5676942e01L }, + { 0x3aeb9a417d88e3a1L,0x105d3c88c484742aL,0xe59de8d13fe61131L, + 0x148f5b6b1a869e8bL,0x7a8abc59aa75d90aL,0x2f0c9bc762146013L, + 0x43faa747c3824cd9L,0x81763a186a5d0b92L,0xbbc341bc9bcbaebcL, + 0xe1813160f745d1ddL,0xa53ce52db75ce5f4L,0x15eae66cd50de4c2L, + 0x5ed8996c75d7656dL,0xe4ff5711c4ca552aL,0x215e985a3c5305b4L, + 0x6b258954fa1ba2ceL } }, +}; + +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_16(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_16(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * Stripe implementation. + * Pre-generated: 2^0, 2^128, ... + * Pre-generated: products of all combinations of above. + * 8 doubles and adds (with qz=1) + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * ct Constant time required. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_1024_ecc_mulmod_base_avx2_16(sp_point_1024* r, const sp_digit* k, + int map, int ct, void* heap) +{ + return sp_1024_ecc_mulmod_stripe_avx2_16(r, &p1024_base, p1024_table, + k, map, ct, heap); +} + +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply the base point of P1024 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[16]; +#endif + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 16, km); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_ecc_mulmod_base_avx2_16(point, k, map, 1, heap); + else +#endif + err = sp_1024_ecc_mulmod_base_16(point, k, map, 1, heap); + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply the base point of P1024 by the scalar, add point a and return + * the result. If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * am Point to add to scalar mulitply result. + * inMont Point to add is in montogmery form. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[2]; + sp_digit k[16 + 16 * 2 * 5]; +#endif + sp_point_1024* addP = NULL; + sp_digit* tmp = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC( + sizeof(sp_digit) * (16 + 16 * 2 * 5), + heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + addP = point + 1; + tmp = k + 16; + + sp_1024_from_mp(k, 16, km); + sp_1024_point_from_ecc_point_16(addP, am); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_16(addP->x, addP->x, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_16(addP->y, addP->y, p1024_mod); + } + if ((err == MP_OKAY) && (!inMont)) { + err = sp_1024_mod_mul_norm_16(addP->z, addP->z, p1024_mod); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_ecc_mulmod_base_avx2_16(point, k, 0, 0, heap); + else +#endif + err = sp_1024_ecc_mulmod_base_16(point, k, 0, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_1024_proj_point_add_avx2_16(point, point, addP, tmp); + else +#endif + sp_1024_proj_point_add_16(point, point, addP, tmp); + + if (map) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_1024_map_avx2_16(point, point, tmp); + else +#endif + sp_1024_map_16(point, point, tmp); + } + + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +#ifndef WOLFSSL_SP_SMALL +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* t = NULL; +#else + sp_point_1024 point[1]; + sp_digit t[5 * 2 * 16]; +#endif + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == MP_OKAY) && (table == NULL)) { + *len = sizeof(sp_table_entry_1024) * 256; + err = LENGTH_ONLY_E; + } + if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) { + err = BUFFER_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 16, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_point_from_ecc_point_16(point, gm); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_gen_stripe_table_avx2_16(point, + (sp_table_entry_1024*)table, t, heap); + else +#endif + err = sp_1024_gen_stripe_table_16(point, + (sp_table_entry_1024*)table, t, heap); + } + if (err == 0) { + *len = sizeof(sp_table_entry_1024) * 256; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#else +/* Generate a pre-computation table for the point. + * + * gm Point to generate table for. + * table Buffer to hold pre-computed points table. + * len Length of table. + * heap Heap to use for allocation. + * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is + * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise. + */ +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap) +{ + int err = 0; + + if ((gm == NULL) || (len == NULL)) { + err = BAD_FUNC_ARG; + } + + if ((err == 0) && (table == NULL)) { + *len = 0; + err = LENGTH_ONLY_E; + } + if ((err == 0) && (*len != 0)) { + err = BUFFER_E; + } + if (err == 0) { + *len = 0; + } + + (void)heap; + + return err; +} +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * km Scalar to multiply by. + * gm Point to multiply. + * table Pre-computed points. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* point = NULL; + sp_digit* k = NULL; +#else + sp_point_1024 point[1]; + sp_digit k[16]; +#endif + int err = MP_OKAY; +#if defined(HAVE_INTEL_AVX2) && !defined(WOLFSSL_SP_SMALL) + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(k, 16, km); + sp_1024_point_from_ecc_point_16(point, gm); + +#ifndef WOLFSSL_SP_SMALL +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_ecc_mulmod_stripe_avx2_16(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); + else +#endif + err = sp_1024_ecc_mulmod_stripe_16(point, point, + (const sp_table_entry_1024*)table, k, map, 0, heap); +#else + (void)table; + err = sp_1024_ecc_mulmod_16(point, point, k, map, 0, heap); +#endif + } + if (err == MP_OKAY) { + err = sp_1024_point_to_ecc_point_16(point, r); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); + if (point != NULL) + XFREE(point, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_16(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_16(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_16(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_16(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_16(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_16(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_16(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_16(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_16(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_16(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_16(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +static int sp_ModExp_Fp_star_x64_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 16]; + sp_digit tx[2 * 16]; + sp_digit ty[2 * 16]; + sp_digit b[2 * 16]; + sp_digit e[2 * 16]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 16 * 2; + ty = td + 5 * 16 * 2; + b = td + 6 * 16 * 2; + e = td + 7 * 16 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 16, base); + sp_1024_from_mp(e, 16, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 16); + sp_1024_mul_16(b, b, p1024_norm_mod); + err = sp_1024_mod_16(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 16); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_16(tx, ty, t); + if ((e[i / 64] >> (i % 64)) & 1) { + sp_1024_proj_mul_qx1_16(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_16(tx, tx, t); + + XMEMSET(tx + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_16(r, tx, ty); + err = sp_1024_mod_16(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Pre-computed table for exponentiating g. + * Striping: 8 points at a distance of (128 combined for + * a total of 256 points. + */ +static const sp_digit sp_1024_g_table[256][16] = { + { 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L }, + { 0x170a46d2335c1685L, 0xeac9e971e1007a58L, 0x40e8f3df43ca4a73L, + 0x2646f81582642475L, 0x3af49bb4b36576d1L, 0xd89e2d1472bf1afbL, + 0x27be882c2fd151e6L, 0xaddedc858f88717cL, 0xd6d859bf16ac6c6fL, + 0x0e741a1b2d8eae58L, 0x6faf7a0061c1f30dL, 0x66dbd09a9b67e096L, + 0x21f11c067d3b4f7dL, 0x6152ba02c727c98eL, 0xafd58891e86cb221L, + 0x59e93c6a6bd3baf4L }, + { 0xe54dd36f71dd4594L, 0xbbc9cc9f00aef1e6L, 0x9ea5a44ea19f6530L, + 0x8588aa993f520928L, 0x9753794c8f5c1418L, 0x118bd792c11399faL, + 0xb9bd3afdf5cb6ab5L, 0x813d1cb22ecb9652L, 0xfd45626740389813L, + 0x51f7119b4ac8431cL, 0xdd9f6a910a180eb6L, 0x13946d179f7bfa2eL, + 0x16f1863150a9d0d9L, 0x5f19c20d6f8373d3L, 0xbe85ac6a9b6a52b9L, + 0x63ef187b74f62e03L }, + { 0x7c376b7f016f45e7L, 0x1c1bdb572bec82f8L, 0x7392f741ce429b60L, + 0x6fdbf0a2c7afd81dL, 0xbda41b1f7241098bL, 0x5b407474bb60f8cfL, + 0x933e0d41b330bc4dL, 0xae182830733fa3beL, 0xa0ed299b0f5c6cd1L, + 0x7ff3354e3f9860c8L, 0xb136098615559c41L, 0xab0cb63c129f85cbL, + 0x682ecc4947685fbeL, 0x505e8ec2eb199633L, 0x90dcc794ddac2cdaL, + 0x4fe6791cf192da23L }, + { 0x94a423d505e8733cL, 0xcc845e651d5717c1L, 0x237c7e88e961b322L, + 0x0c4471c6db4181ccL, 0x00c875e2713bd721L, 0x9dfde9edb2c17b09L, + 0x430a6de5e88ceaf6L, 0xaaa7a61a7b81cea6L, 0xea52d026233f98d5L, + 0xb55efdd060689a9aL, 0x30cfa7ce5cac4aabL, 0xfa4db1148e950761L, + 0x309570c44e9a1e52L, 0x18c21f611a040170L, 0x555d1ffebe78d9d2L, + 0x04482a18561db297L }, + { 0xe7758ac273d486d8L, 0x8169f94661cdc1e7L, 0x723c99fc2188ab4fL, + 0xa0e54f02f3373630L, 0x560bee25bd8c2260L, 0x28fc307c4531bc60L, + 0xd6f21f1a7e44feb5L, 0xc8e4499c57128d37L, 0x963b053ed7b2ea45L, + 0x40c27a0432a3d222L, 0x5b51854d35459668L, 0x66e1a49fd73557e9L, + 0x0d267fd98692077aL, 0xfa1350d3e7342702L, 0x1a9c3f2568ccdb44L, + 0x833a0ff8dedbf89fL }, + { 0xa8c419c7ab376b76L, 0x3b7294f327d0f0ccL, 0xe56bb9e2a90c514dL, + 0x931ba51ea62575a6L, 0x56fee07b098c0a88L, 0x04be5aeeb4c16a2aL, + 0xe513350be6eb260bL, 0x339edad6a1d5c270L, 0xf366ed59e9dbadd1L, + 0x4213be882dd06ec0L, 0x22d639c8cb1187dbL, 0x1fec95e1d8a1058aL, + 0x03f73ea6a2b744f1L, 0x741fd51af4f05c0cL, 0x2e2df95a85f811a0L, + 0x692b3ce3eb24965fL }, + { 0x0ce6cb72d2a127b4L, 0x66a46ea58f92816fL, 0x43ecf46347a37616L, + 0x163d9a01e0ab96eeL, 0xc8145c6db2edbe8cL, 0x2f426cae4de4e665L, + 0x174d0b4074e252f9L, 0x54c240d77d2af831L, 0x581fa3973d652936L, + 0x05b9491ca09d4695L, 0x8c4e85335452643cL, 0x32d64331d4128327L, + 0x6447903870361f25L, 0x774191b189ef09f2L, 0xc0cf0aaf81de5fe0L, + 0x333e430af40042d6L }, + { 0x5df04de4cf26d3b7L, 0x57a77306b53f79beL, 0xa4013c5f1808b664L, + 0xef291ea485037360L, 0x1ffc9d7d0b061037L, 0xd9d04dd965c913bbL, + 0x948a37aff13b8587L, 0xb5443483fe3ee755L, 0x3fc21e7404631386L, + 0xb3a104e5cddeb58cL, 0x94fe18626572cd52L, 0xeb9a71a115aaa408L, + 0x8adc6fe5459ea462L, 0xbb18d1754aeb02a3L, 0xae1276362f7791d1L, + 0x10e8b31dd6bbd708L }, + { 0xb87f03e53ed9f1afL, 0x03ad247756676166L, 0x38dcd63074ce15b8L, + 0x1877e2b026b1e85bL, 0xb1654d171af99c15L, 0x9782e9e49382547aL, + 0x6dc7fc7c26d55ef5L, 0x9038f95d2fbeb54cL, 0xfe590dfe036c0357L, + 0xcfcb6eae4fdc3f7fL, 0xcb1fbc54f35e1a88L, 0x3c8e1db2da0a5568L, + 0x9a87393f5b6f5557L, 0x38646b32e7ac0a06L, 0xfd261c832a8495abL, + 0x6485524c0cdcc4bcL }, + { 0x1abfb3e2c4a6ff2aL, 0x2aa03fba35a6428aL, 0x884227f089aff742L, + 0x2337883aba5dbd93L, 0x38186ae9d2a182cbL, 0xb9f0764d49a01f05L, + 0x92411feb917b1e7aL, 0x700b1903570cbb5bL, 0x5d5181d5b914be7cL, + 0x135c44371981182dL, 0x32758d24574b9997L, 0xa650a8f5632d28b2L, + 0x24078bacfa383f09L, 0x6546a60c00a33d80L, 0xa4061c7a2df8b449L, + 0x1f76f3f2f234563cL }, + { 0x9aa2c14344c436b0L, 0x790705561f69c87aL, 0x35f3117b5f6db2dfL, + 0x85761f41ed56ba82L, 0xf831464f7d0afa48L, 0xa99f29153adce71eL, + 0xb27bf693116b7488L, 0xa98a5a8c9bb9443aL, 0x7f8780262ee5fde8L, + 0x3a6f93dd1812acb7L, 0xaf92a4ccdc84bc92L, 0x3c2562aff1d4995aL, + 0xfd9fc33c04ed899dL, 0xc028ca944ed2a538L, 0xd0f367bb049ea726L, + 0x04924ffb3d108e05L }, + { 0x06548e3dc673562fL, 0xd3b33025e2eae48cL, 0xe61fd32b5e1c6977L, + 0x424e20646ebe557bL, 0x767391c041d6e18eL, 0x4b8ebb8e14d7e95bL, + 0x4ae8b7d420991b8cL, 0xf8a0df66e01290d3L, 0xc97e24a3925e5f4eL, + 0x79a7b2cb1508272aL, 0xb40b072e25072661L, 0xdad9e1829062fa49L, + 0x8780a784f3c53bceL, 0x58a82b769f142799L, 0x08cd849cc1468426L, + 0x4dfce809c380ae35L }, + { 0x45069cb2d527b780L, 0xd52da015977930ddL, 0x10cc600be27d0263L, + 0x34102c26bb2d1b2bL, 0x4c652623554adf3cL, 0xd689138245f0ff47L, + 0x83fa8cc5ca916e7cL, 0x1e10f139d15c8d8aL, 0xf173dc2e81dc56b3L, + 0x7fcecb045c4ed9baL, 0x307fd7d847d01228L, 0x24a571539f3a532fL, + 0x59e9e81de2153c22L, 0xc562595de428a408L, 0xdc7daff89339bd23L, + 0x0d075908b8a06802L }, + { 0x870af2a7de085f2aL, 0x88fcd24fbe99b2e5L, 0x88c0d26159ca413bL, + 0x1f02a2e48559f851L, 0x83b96021f622da0dL, 0x5c05c2f56dca3615L, + 0x0148cf1c7910c682L, 0x392f2896272695beL, 0x883d0bb5a8d64ef6L, + 0xef0d22441cfcbc52L, 0xf5dafcec526117e5L, 0xb68612b9f04928e9L, + 0x283f744d393f2e2aL, 0xfbeed7ed700c1151L, 0xf2cde215a4360dfeL, + 0x24fa961c2f08535aL }, + { 0x0767db3f616df7f6L, 0x643057d8fbd90326L, 0x174daa906e82d544L, + 0x2284f345689643dbL, 0x18b191dfcc89a060L, 0xbab46af4d6c27d12L, + 0x5a57f486c9895145L, 0xc03214e9cc942f9eL, 0x273e1c8f41950158L, + 0x8ceb759f39ad43abL, 0x5e1b8b7fe50ee173L, 0xf635b1fc8f4d7d4eL, + 0x8eff77e3755603f3L, 0x201f61d17752fa60L, 0x94d7a03d4a6fb6e1L, + 0x371cc23dfc4f0114L }, + { 0x289b115dda90c351L, 0x6d196ebf364d9c06L, 0x77a89202f650b31bL, + 0xcc28c1646f57642fL, 0xdc4f7e3608100127L, 0x8836cd08dc4c807bL, + 0x1280f156e00240f2L, 0x3f9a6d7899cb3953L, 0x40a494d33a802038L, + 0x45697e91e87d3474L, 0x70d97d0726dde24aL, 0x06f6a58d7640c30eL, + 0x03c2c0e85ba6e6c6L, 0x330f6a7af1bc13e8L, 0x3e602e4fc9f4d78fL, + 0x92b6bca00c80fb7fL }, + { 0x2e3d5c835f00822eL, 0x0e825712b8b16f12L, 0x81c329c492b0a330L, + 0x6b4e32ada7cc1954L, 0x0bee9cee1bb1413fL, 0xedfb7baa4a92ca27L, + 0xcd472afaea3b9153L, 0xe8f09e7e00f0c0f9L, 0xa4e1d8725cdebb70L, + 0xfe2bae084a9b63b6L, 0xf40141b83fd58f65L, 0xd7ec5edaa3b62759L, + 0x9aaf6e67790e3088L, 0x215ad8301f277e31L, 0xe7db4b98cf33871cL, + 0x71ff62c94f02f89dL }, + { 0xaa4c71022a4a84d9L, 0xe2ee4acd5ebc71e6L, 0x3b11a8a5f1cd6578L, + 0x83f5ef9ffff120a5L, 0xa4c598e109e65033L, 0xe1e9f990ca044180L, + 0x8b832d46f59828c1L, 0x753f28a033af536bL, 0x92edc4b1b6d4f68aL, + 0xedde692a72ccd1f0L, 0xd3aa0f7dd2226432L, 0x38dbb63ea3d2661cL, + 0xf1e19fc6fdc37ddaL, 0x6c18b35084ef6b4cL, 0xe6a83fe9df1bba69L, + 0x40fd47e75f958273L }, + { 0x5b88b746267140a4L, 0x6dbbfc1eeab6f2fbL, 0xdd9ec88e69862548L, + 0x69beeba12eb6efc2L, 0xcfc2214a8ac8ff88L, 0x95d5c96eb5a21950L, + 0x93389c054171fb69L, 0x2d85d4521b468337L, 0x14d68a084113425cL, + 0xe52c0139ec6c2174L, 0x20cf0b97f730084dL, 0x1ac16a261f578aa3L, + 0x18b9fab3f9b6ae43L, 0x68d82111d854a695L, 0x0b334d98dffbe286L, + 0x5b1c1157e639338cL }, + { 0x90edaab172b6bb8fL, 0x8dc64ed202fc92c2L, 0xf42ba3c5fe694c73L, + 0x316dc65fcb54dce4L, 0xcb2d66a3632420dcL, 0x16e706e7056dcf94L, + 0x2809c764a4f32c9dL, 0xab18d830ea6edca8L, 0x4fd1ace681c65f57L, + 0x1f91651c7da12c10L, 0x0ac3bd66c7791a48L, 0xb6ad1cf4785e67a3L, + 0xe4d3fc44da0fd591L, 0xce1648016e1c6344L, 0x84de9cb833e50ab3L, + 0x963ab83aa756eef4L }, + { 0x944b47d8df4ea5a3L, 0x965688155cfe45feL, 0xd16e7d588a3c3564L, + 0x84e55b3ee7c99e15L, 0x3fee204df55071bcL, 0x71006f2904057dceL, + 0xfe8c390dbba75570L, 0x3645bcb63319adacL, 0x8189e8b07c20bfd8L, + 0x8e5509697d7d9578L, 0x037d1321b99f4e3bL, 0x011b2521a60cfb6aL, + 0x66594aaa837382daL, 0xc89b91fd83c1dc07L, 0x6b82b899076b9884L, + 0x443480fcbe45c558L }, + { 0xf8ffffb49114221aL, 0x4aec4f2e3e857a7aL, 0x42e2d0e40fa54787L, + 0xef3e6b31d6f96152L, 0xb2296537fbfe9b77L, 0xc2a9d0f2fb43a86aL, + 0x241284ed24572ac6L, 0xa3868917e721ba7bL, 0xdbef7c00c117a78dL, + 0x38149071d31605acL, 0xc2dada9e065a8ee9L, 0xd5b138d8c442be82L, + 0x9b6c224bf6d72b58L, 0xb9d355cf8eb03e6dL, 0xab6d1eb0a1700371L, + 0x97118a88cffaa7ebL }, + { 0xbf9c59a2cdecb5d8L, 0x8083c81ba93a6866L, 0x24e0dd8104774fbfL, + 0xe779a3caa02070b4L, 0x9d352fbb0fbfb781L, 0xa8b0d8203ef2a1c4L, + 0xb858637b14b3e501L, 0x5ba70a498a882ff2L, 0xa27300833b06efa5L, + 0xa42c02f4102fee2aL, 0xe4e762998a0223a5L, 0xdba2ba2685c3fc72L, + 0x554fe763fe52eae7L, 0x30b5405a270f45f6L, 0xd56a177aa573387cL, + 0x17c0778d4b71fa82L }, + { 0x0e6dff1d2735e37bL, 0xc9884e56656ec572L, 0xa2f5ac9d9ebba978L, + 0x40fa4518ba09f3c4L, 0x8c3fa177f5b04377L, 0xa1a1decd967a2ecaL, + 0x768bca700528bd40L, 0xf224952b18691c4aL, 0x16e12c45e86d5fd5L, + 0x7a0d915737859a6aL, 0x723f4309a0ffce0eL, 0x5a8db79ba96cc9a3L, + 0x6dd12ae01ad23a38L, 0x9ffec3a1e2bf5d84L, 0xd6ce84e1a452ed66L, + 0x1219d5c8571fe4c6L }, + { 0x43eaa67f262969ebL, 0x3a3ab39d2f03e773L, 0xe6127e5157bb0909L, + 0x0f82b0ed8d150274L, 0xffffcad8e580bdbdL, 0x51d3d075a9743e6bL, + 0x1484bdb18bac11d6L, 0x95cd9990eb24c388L, 0x216a61d07fac67c6L, + 0x4308f762a04e6b87L, 0x2865dd61cba57cc8L, 0x3c296b0dd234a07aL, + 0x76f928393a0793f9L, 0x70b57e1f0be29eceL, 0x1314a82f7e626f42L, + 0x2c8d7ab2d657f230L }, + { 0x67cf58920825e4d6L, 0xdf51eaa56ef83b44L, 0x63e665d81310108dL, + 0x229f89f58dd0963fL, 0x8c4b14dd9df6436aL, 0x99dae469d45ebba7L, + 0x118aab775a4df381L, 0xda8978bd29e37febL, 0x69ced5aaaca2d7efL, + 0x6c98d05dc67d6a8aL, 0x7474bf0d77f84a34L, 0xd4428b2eed8cd59aL, + 0xb0fd1cd5d1d398fbL, 0x596013db94a20b11L, 0x96eb705a1b404c44L, + 0x2299d2774b09d958L }, + { 0x5b9cd58dc64397e6L, 0xac198f1ebf6dd31eL, 0x5866d8e13e9f1db2L, + 0x405ae2878fcdc68cL, 0xa4b280cde53c01fdL, 0xdc963f2d411db5f6L, + 0xed5d5189bec4f8a0L, 0x336fd13d916ee98bL, 0x6925b1b3042df48eL, + 0x0cf56291ace0074eL, 0xe8d38b4825317e95L, 0xc7ad1d2b821c446bL, + 0x71c44135f0b65934L, 0x971b736f52ca0d50L, 0xaf9ffa5727b46c26L, + 0x21ac67791936618eL }, + { 0xab420e3f2d7fbcd2L, 0x1272247397bdfc18L, 0x492033f84df5d4b4L, + 0x6fcd42363807b7d3L, 0xdfc19b09b33c3625L, 0x13d6f375a0f22814L, + 0x70978a59037c19b8L, 0x4f3989970ff27b9cL, 0xfc0e1a45615a4389L, + 0xffa3496a3e602f74L, 0xc3f1c431b261ca1cL, 0x612211dbee0164cdL, + 0x30463ee4e7f7be9fL, 0x015f7e7892c2e1bbL, 0x663d88d624483a56L, + 0x0e8ec1e70e62d9d8L }, + { 0xa88ccc298a0878ddL, 0x99ac175d6640071aL, 0x90344820a5173617L, + 0x316d023edd58a315L, 0x30785bd488d221a1L, 0xb74b3de7959c48e3L, + 0x42ee03824c67a771L, 0x59ef6cdde0b91453L, 0x7830ae289b237e91L, + 0xe1847a4c495d8325L, 0x67b1217ed0773666L, 0x58192c86a294a325L, + 0x76aa0f56864d8326L, 0xe2a2bd12f4b13e5bL, 0xd850c1c01b6b73fdL, + 0x653a795f5d103635L }, + { 0xcfe2898550dcb199L, 0xb35b8e5e7fa02b60L, 0xbca7d7c3c97603d0L, + 0xb0e5288d27f131b5L, 0x3aa704dee2b12d52L, 0xe206b1d81db725c7L, + 0x0b12839ac5d1b113L, 0x14f970cbdb45d763L, 0xc997f93eb2125e8eL, + 0xbd75739cee7daa26L, 0x46ecbd3f1fef20e9L, 0xf994a1147c6a42b1L, + 0xd289eb4f27fb0fd1L, 0x11186d319a40da4bL, 0x083f65a5fb9d7976L, + 0x30dfc47bd444675eL }, + { 0xbcfc5ae29eaadfe8L, 0x25027e54b4d4e812L, 0xab0702df8b533561L, + 0xa2b9c20456a6a214L, 0xb1a3df7a3059068eL, 0xa3514b219883110fL, + 0xb7be2336c4b78e1cL, 0x17073ce63e2f6984L, 0x86e114a62ddf7ac6L, + 0x276192bf07d7c3c8L, 0x5da69e0beb1ae289L, 0x983af17525184939L, + 0x9ac52a4d407a3aa0L, 0x1535c7daae0fe218L, 0xe16fe872397f2501L, + 0x572a591f54c212cfL }, + { 0x4966841909a5553aL, 0x3f054318327733bcL, 0xf9ceb4b23eefd690L, + 0xbd3cbf9bf22126d4L, 0x6d9671c02fed9578L, 0xbba597ceca0306d8L, + 0xb705ed613d674fe5L, 0xf1d3622b67f33f76L, 0x15bcf3c611cb8c31L, + 0xa38467dce53d1aa9L, 0x902fe929f908ab43L, 0x6e3e499d8d15767aL, + 0x8142db5c90afd07bL, 0x120c6fbc6c8b190eL, 0x80c8655324919a4eL, + 0x65c2cbe1d8c82c3cL }, + { 0x684cda20a660bb63L, 0x27dc3b0a86e86245L, 0x76472cf66ba0eed7L, + 0x79c162e5679dd158L, 0xb688427708452d44L, 0x829bc6b3413f579eL, + 0x92ea15ec95011770L, 0x5e34e30047738183L, 0x8c3ca34973e1d2f1L, + 0xa5c4f1dc229bd3deL, 0x783eff1b94ef7ed3L, 0x46db738ddfae7a1aL, + 0x4353d72e1a099852L, 0x2533ad58a0dcf4abL, 0xd80550160e7888b9L, + 0x831440d53ba77f66L }, + { 0xf43e2e32f611b2daL, 0x5d066e29d0fa46acL, 0xe897f3e8820b3c0dL, + 0xc45c28e61d3e44f0L, 0x929d7f66dfd27a66L, 0x735b860a101e8517L, + 0xea3fce983de078ddL, 0xc9977db5638ce11aL, 0x0488382f48536b3bL, + 0x7e0c7a3c64cadfc6L, 0x3cd17f7f82147b71L, 0xe95663cc1b411e3eL, + 0x5739ac8f985fb46dL, 0x385399cdbcf119caL, 0x4a985a70e15a2815L, + 0x504c3a8a6d5f4566L }, + { 0x00b55283b8fa53c7L, 0x985cff38509474e3L, 0x234d241c437ce25fL, + 0x29832430e5a129edL, 0x6ad38956aabcc674L, 0xa2dc001d7ee81ee1L, + 0x4c23c6b6670b2702L, 0xb35e567ea6e8a3bbL, 0xbc70b3cea69673eaL, + 0x85a7a9c3e6e28eacL, 0x2ae684de5537b7daL, 0x5ecac3e56de937dcL, + 0xbf2ea6c9f8430422L, 0x38caf7d077fdc520L, 0xc27af0b169f56addL, + 0x496e4699c71d21d2L }, + { 0xba14fc829fa93467L, 0xc2e376840eb2a614L, 0x659bcfaf4833e09bL, + 0xbc8597523686bdccL, 0x40bfd08081f3216aL, 0xc463bda617c081b8L, + 0xbd01fa86bb04793bL, 0x5a21ece62cd640c5L, 0x97bf6a542203d5c4L, + 0xceb40edc951167b7L, 0xd67aacaf765ba268L, 0x8ba0d9e9aeab51f9L, + 0xc14b215eb0d6863aL, 0x354cdcdbe5f06952L, 0x4f2b5ccfcb3744b5L, + 0x1338917313037fe8L }, + { 0xee68064045003cd1L, 0xfdac17bc44ae2ac6L, 0x4bcd419fde8e5314L, + 0x81e34eb9c7cea95cL, 0xbb57762d38f37e01L, 0xecc4cfb0260990c8L, + 0x0bc493f950a34a7bL, 0x68074172543304efL, 0xaec0fcb26bc8aa2aL, + 0x9e7a9b463b45fea5L, 0x4bb2952e55fbdbacL, 0x50f0c0a60485dff4L, + 0x02c5104d4dea4796L, 0xd2cefa09695e3a02L, 0x4c8102b46da1f345L, + 0x422eb573f3833fbdL }, + { 0xac592eb6a6ad3f47L, 0xb0861f6d9714ba0eL, 0x57c1e91907281459L, + 0xcf7c94e264ea5803L, 0x725376ac54b12723L, 0xf2a6ba41dafb736aL, + 0xc89e8920cba03cdcL, 0xf2e20cb45b0fd3adL, 0x26ea5a54d66059feL, + 0xee63fa8b889df8bcL, 0x40f1c7e166a3f2bfL, 0x09febc9c747312e1L, + 0x7d19b9c2727999ffL, 0xa9fbbb4cb7fd2b05L, 0xcfba27d7a0da2dc6L, + 0x368541cf2c252582L }, + { 0x510d3c9e22799d37L, 0x1b677de5acfa333aL, 0x4e6ae18f080f795bL, + 0x69b53c2aafc8dfc2L, 0x797541b60e842dc2L, 0xd5a6f2afac067fe8L, + 0xd0208a03bd07d877L, 0x34b473f0654be2f2L, 0xe67c102af515e23eL, + 0xb00dbf9d2ac1af48L, 0xe264fa41b6a13d00L, 0x1669786a97e94c11L, + 0x09d8cf2d86a586f4L, 0x073bf869c7f927e9L, 0xb89778802241a566L, + 0x59a5bf5922261334L }, + { 0xe9d1c91e81347191L, 0x186c1abceb969972L, 0x07888767a9d46a7fL, + 0xda93cfccdaa7d397L, 0x08bee9f1d91b9aa0L, 0x8267fd78f8dd3c6cL, + 0xf93860d094228100L, 0x6a6a71aadadb47fbL, 0x9caa06b7a6156f8aL, + 0xaa1b05e039848bc9L, 0x36ddc2372aaa9135L, 0x77e7e079b13f3bd1L, + 0x8d0b5cbe4acc5f4dL, 0x04da45f8984cfd36L, 0xf14ef618d3d3e0f8L, + 0x467564c143eb799cL }, + { 0x8d725904b6fff5d7L, 0x037f33af92dc4752L, 0x9095d5756d20b8aaL, + 0x32235fc143baec39L, 0xa2feb4af68a2b9b0L, 0x61c5031894d35c61L, + 0xac92b6a2ea877486L, 0x8eb48b15011bc6f3L, 0xa28fe128c79edcb2L, + 0x9f71bc0ca5d2a006L, 0xf31677322f15b850L, 0xfe8d728c7a036218L, + 0x068f39cb4f81e09eL, 0x1773f0167b7c50d9L, 0x0d0f7adbed6a1e03L, + 0x8a0dee164ee984d5L }, + { 0x504991bf47366e6fL, 0xb8084d9fe86c3005L, 0x14c4c751a40cce36L, + 0xbbb46aa63f1961e2L, 0x56a785f940445e43L, 0xdb8d1b57c91e215fL, + 0x6a8e453ec7ee808dL, 0xc0367ef8bbaa1e8cL, 0x310d91f1e3e18109L, + 0xf97cfd0e7e20a2c3L, 0xf1e80c84554cc277L, 0xe89bbc1d7b628403L, + 0x7778a9663fe0a17cL, 0x9e9db19fc1f00073L, 0x2ce7fe7db6f6bed2L, + 0x7b04b5d2ee97ce23L }, + { 0x5b546bc782c5faf8L, 0x1a734c5e8eb81097L, 0x3d566861e77851e0L, + 0x833a1013e956d51fL, 0xc7351731c3c3c37cL, 0x607738fbe0c148ecL, + 0x2ec6f0bbe1bbef41L, 0x0aa2ac6ecfa51857L, 0x072902d766e3adf0L, + 0xcd4d5089c622d6e3L, 0x3ae21b23a6dd802fL, 0xe5465a5533886372L, + 0xd85119a0a8d81822L, 0x4f14d0323786977aL, 0x515b081c9c7b272cL, + 0x1c6a95a4c99be31cL }, + { 0xa6b14ad5c2821363L, 0x829c18234d17de1cL, 0xaef5d2c4ccade848L, + 0xf412ab3982489e27L, 0x92c9c098f081d927L, 0x6f87bdf475cbad1fL, + 0xf4aadab81a1d9fb1L, 0x475a7923b75f3b76L, 0x99dd0ad6dbbba8feL, + 0x836f61644b70ab45L, 0x2a46488134bd9af1L, 0x5c91226eba9abda3L, + 0x4cec8709e65625fbL, 0xd4b3919e0818e4beL, 0xa5c09c8414f6879cL, + 0x72708a0230a864c9L }, + { 0x4f33c0b1f34a466cL, 0xa1bae09c7f9d45baL, 0xd70f0fee0e28785cL, + 0x824c714690880881L, 0xe2416c2abb043da3L, 0x733da713cec6f432L, + 0x2b590649c9793e1cL, 0xdb62d5b0b35c9365L, 0x355eb6e23e5c1b2aL, + 0xcfe8b5cebb16b515L, 0x9e081869f709691cL, 0xc865f9fb61a85bd5L, + 0xf169d3ccfae103f7L, 0x9525c47373467e9dL, 0x7db55c0b43695113L, + 0x7491c74c73265d21L }, + { 0x312ed5bf80d2b94dL, 0x1b8ac633ba4b260bL, 0xac86c58cd62219a1L, + 0x317ccf6baeb82c8eL, 0x2dfb29ee59ef9cedL, 0xdaa7d898e42bcd5aL, + 0x93e295c85974b201L, 0x69e75784d9fc5adcL, 0xd6c4709f012aa3baL, + 0x1fda9f37c85d3cb9L, 0xe5487e25d3dd4abdL, 0x00fd4b010b3ba22eL, + 0xcb591493c6e8dcbbL, 0xb7329fabbce68664L, 0x6829d1c268906b76L, + 0x8bcfd3e574176841L }, + { 0x06882734d3c8c314L, 0x95f0b2f111870833L, 0xb937f7c3c068ba16L, + 0x5365e0d877924787L, 0x15527e5e1f992227L, 0x0a06964827dffd4fL, + 0xd58b3df22f586389L, 0x83446b896af20eadL, 0x09d7970b50746257L, + 0xd9e8d2064022a691L, 0xd1e5f8af671ec379L, 0x6f542509057fe91eL, + 0xf14dda8152890418L, 0xbd78010e1db932adL, 0x3e18d1e4905a9378L, + 0x53cadcf7bd37ab49L }, + { 0x1bb5edf75e53d0ffL, 0xd886606c888abf67L, 0x6491b0f812206d15L, + 0xb3018345e22b6a33L, 0xaba6794bb173b317L, 0x8c1e58677dc9e595L, + 0x4e106482239624d1L, 0x61752e59da55dd53L, 0x018b4eab9e42879cL, + 0xcaf6784b491f2bedL, 0x3dcdb9d21e79429eL, 0x3694148510f26224L, + 0x106f190aa650ec5cL, 0x7542a5aeb69a9760L, 0x69bd75e9c32d1046L, + 0x90849964bf8c62b1L }, + { 0xb1390cf65a93c661L, 0x184862649db5f056L, 0x92a93a9da51a1788L, + 0x1b0cbb8f6772de9aL, 0x6e67febd7c71487cL, 0xf9b4382d4e62423eL, + 0x96fda50ebb5a42f8L, 0xc921b3376089a4f2L, 0x49d32d7b875ec516L, + 0xbd86d2cac410124bL, 0xf6862209c421fb7aL, 0x3e1949abf6b7de33L, + 0xcdee18f0e93c9268L, 0xd4edbd5e08dc4cc0L, 0xc2b75be473580d22L, + 0x3d7f6ffa468cd7e8L }, + { 0xea7b290cdffbd5d1L, 0x9d759da6970338dfL, 0x56680b0890feedc9L, + 0xbc690af542dce68eL, 0x8519df2bb2ae4d82L, 0x5612467f7f195b60L, + 0x659a342cd83c21f4L, 0x55771bf555651633L, 0x5fc68935548ba562L, + 0xb54192039492f23aL, 0x567528e39c9c6017L, 0x3f064ed4511e6019L, + 0x303f9eb91d16a555L, 0x3e18c4fd2254abeeL, 0x40994d6ffd434e7cL, + 0x8fb12d3f6dde74e6L }, + { 0x6c6381a2293cb7a4L, 0x453e09f0b87b7e4dL, 0x4f212823078ac3efL, + 0xe89ffad0578cae91L, 0x4a2b696a716ba4ddL, 0x14681a14f6f580a0L, + 0x1358f97b4c2f1307L, 0x878969962932fb89L, 0x29dd850a268a5af7L, + 0xaf771f6dfe239f83L, 0x5f20fd2e4f47499dL, 0x9b643e77867ca0e9L, + 0xe7858ecd375981ecL, 0xbe946a5919ab1c97L, 0x4f9303a206ff3453L, + 0x3fcc673175d237b1L }, + { 0x509debd5df21f920L, 0xfaf70e1fc1401b90L, 0x2429cbfd95a64aafL, + 0xf21208552c37a122L, 0x1d4c93f47deb926bL, 0x12f3e4c09fb3f1dcL, + 0x56085a595b51bc46L, 0x2a2f5d62f10fdbd2L, 0x60dd62cfdf0cb3c2L, + 0x154424a36b0f254bL, 0xc3a5a05d564612b7L, 0xbebe30cfa1f5249cL, + 0x24ec69037e62a188L, 0x75f0fbacaf429939L, 0xd41345dcb3fa8685L, + 0x645146fdc7151c34L }, + { 0xecec633aba1924f9L, 0xbba6f136006326e1L, 0x203757ac7e50fc17L, + 0xca531919ef3d8e00L, 0x9545a6aa51dc5a74L, 0x6e21d58fd31412b8L, + 0x01bc30057bb1d000L, 0xf1789c696ed1a9c3L, 0x7af2d35f9858fa48L, + 0x434d09b98197be85L, 0x1dc0775529aa265dL, 0xcad03be7c058fa80L, + 0x92d70a9f54ba14ceL, 0x6dc785056c050a74L, 0x2a7ca4a94d005ddaL, + 0x448d3d72abfb9f2eL }, + { 0xdc56f14529b33989L, 0x868351bca9ae815aL, 0xb3f456134b074414L, + 0x955ce42a3cd9f33bL, 0x13ade4ec5ff6e4a3L, 0xd3aac715a50eaa91L, + 0x0c61ec995666efdfL, 0x108a28b8f6a4470aL, 0x402ef584e54844c9L, + 0xb825b162d0e2f337L, 0x3dcd131fb46f7cbcL, 0x208178ec96f2fd89L, + 0x4d8c5d6725928c78L, 0x285a33df9963c459L, 0x72497175d92a309fL, + 0x76881479cb7019a5L }, + { 0xba43a11491767eedL, 0x5e11b9ad92bf65dbL, 0xe8a22ce003a5e21aL, + 0x636044212a335415L, 0xc2c563b44a9ead62L, 0x4bc06264a0b2aee5L, + 0x75b8d5758bf2e1d7L, 0x1cff0ee7d08a265dL, 0x17914e1db0b712a7L, + 0xc35925d04b18692dL, 0xde253f4c56cce815L, 0xa479241c9fff0e3aL, + 0x50b9d06eddabed19L, 0x6713526059fae506L, 0xf37600fb532ce180L, + 0x670eb01c5e5a8626L }, + { 0xdf73c0af73cdbb43L, 0xcf08ecc57f2431adL, 0x917805412a1a3845L, + 0x69a104f29224ddf1L, 0x4352f38dbeac7effL, 0xfc3b3b4e7c2d1322L, + 0xa69e9430b5e4b476L, 0x7d932340975a46f0L, 0x8093899e5d64eeceL, + 0x7b821250db2345e9L, 0x235529327f4b796bL, 0x2ee9cc154bb90b1fL, + 0x1fa9c8f59112f7d6L, 0x2d0f2f981cbaae32L, 0xb77f03660075166aL, + 0x504852e7635dff27L }, + { 0x2f0f3ce5a2f392faL, 0x326c076aec6c9078L, 0xad01de9284baaaf6L, + 0xb01b16d3cbe8e993L, 0x71305c242d950908L, 0xc66fd6173853af38L, + 0x7735140ed3c429a0L, 0x8a31b12a1fabf027L, 0xa0530002058b3177L, + 0xabffd9fca9c7deb9L, 0xd05ef69be8667d30L, 0x2f3a7308e9a9e13fL, + 0x3f4c9a19b91eae9cL, 0x50d0cee7618ce6c4L, 0xfb24dc405240f8b0L, + 0x992fe151f7e90cc4L }, + { 0x4454db3138f197aaL, 0xa4ded69d87872f98L, 0x97b427b044f0a828L, + 0x9821e1aea31e48c6L, 0xe38cb09fdd98efecL, 0x20b84fa8480cb3aeL, + 0xba5bb4a847475573L, 0xa9be080acd50e96bL, 0xc4451e9cef103550L, + 0x626ee75fc441325cL, 0x6eea5e9838a5e33dL, 0x7321beb9a2b0abd2L, + 0xca92e4849b6082a9L, 0x1dc8168a992bcc2aL, 0x134ecf4b9c8eb9fbL, + 0x5a68bfa84c5b71e0L }, + { 0xb4ff3b45ff0a2bfbL, 0xd105fff95502f8b0L, 0x14de58855b1c0c26L, + 0xed16865b0d3b9d04L, 0x2f5a2453026d3917L, 0x6a22f493f4db3c0eL, + 0x4871548ae2418f2eL, 0x6ab363a8509bef61L, 0x91ca1e3ab8cbbbecL, + 0x71e0dc984011a396L, 0xff982e0a0d5ca577L, 0xeb40b04581897bc1L, + 0x4bc24a46085ad5e7L, 0xd15c8fa0a6337b7cL, 0x56ce6ef7bef1628fL, + 0x78acfdf99f5ef439L }, + { 0x45bf7f15f8520189L, 0x954202a0c77f61c4L, 0x39edc6b9dfa22e1bL, + 0xd2d602671f4a3487L, 0xcd9339294814cc52L, 0xde76a12405e9f123L, + 0xe2306ea0ae36b6f7L, 0x53815218b83a58e0L, 0x9862bb76a041231aL, + 0xe8da253cbf31be71L, 0x2dfc533237de861fL, 0xf25c93f690ae4890L, + 0x66bcb8f08baa6ed2L, 0x6f10ae0f908b4a29L, 0x8cb4b48cb061c949L, + 0x0ad92d73d075a366L }, + { 0xbfb95fedc2ca548aL, 0x4778c62080cd89abL, 0xbe99154b3466c280L, + 0xea3be093d4be8902L, 0x847b799513e681edL, 0xf22a8f4b02f40161L, + 0x3ef2cb4d4aeb7fe8L, 0x9adc5151b3aed5f6L, 0xec1ccfd198c31163L, + 0xdc2ac17ba3d7d88fL, 0x08fa64d346421097L, 0x5ebf80b794b90bcfL, + 0x1b78b4ba0b50a9ebL, 0x1a4fe934279aa66bL, 0x8ef4dcaf075b3cedL, + 0x95bbd8a070a6e9aeL }, + { 0x59f92495e614bbd0L, 0x7567a887b823e363L, 0xe247c9ecfc1bd6a7L, + 0x2bfaaf478e835c42L, 0x314ef4e0aade066aL, 0x072baa635c16d336L, + 0xfa429c71e2f0e389L, 0xcac1e5d0bd07d90fL, 0x69ff35ea514f5c04L, + 0x893053fcc0554ec1L, 0xab1d86b72a35947fL, 0xe29fb0602aebe487L, + 0xa0a10d6ddfb9cf21L, 0xad147059f20dfcf5L, 0x480dc66fb8867a2aL, + 0x375a884fc125a919L }, + { 0x178cbe2e1217f7eaL, 0x1a161e2a875c6dabL, 0xf7707ec01bdb1a54L, + 0x678864a0e4fd73caL, 0xbaebc664d13a0d86L, 0x40325f99c8d30668L, + 0xb93ed9c92f1c5950L, 0xfdf36763541e0667L, 0xfd97fbb0b91a6763L, + 0x26aa69ea6079c9a0L, 0xc7303c801eaa8c47L, 0xdec75c81afa63c55L, + 0x01cdcde24fd12adbL, 0x9fe0dda71968838aL, 0x66bb093b38415379L, + 0x268d818b08cb84ecL }, + { 0x73dae35841580555L, 0x4fc32e67473d103bL, 0x240c1013beccc1abL, + 0xda4099f2b24ee9deL, 0x37b0cb5b9fa8e066L, 0xb5ae04e46438d7eeL, + 0x7f7d31642b720140L, 0x86ef4edb339e4a78L, 0xa5e77eed3a7d8375L, + 0x883fad37bd707c2eL, 0x816b633a0f979189L, 0xe24c028a2e7a208eL, + 0x1171fe3c4435516aL, 0x3eb93b334f5f2bf5L, 0x8419ed4b01b53a56L, + 0x8b02735c056ca44bL }, + { 0xb89bb464e1019195L, 0x1de4c026f3fc28c1L, 0xac120e6e2bfc3b21L, + 0xec71bc5a91bdf92fL, 0x485d7ab40d995bc9L, 0x97c6768ee6491ffeL, + 0xd9552d19afbce265L, 0xbae6c7fe8e1b76c2L, 0x167d8281d7e3ad1bL, + 0x3e149af95e989734L, 0xd1f0024c8a0c8182L, 0xf571ffdbc3006c0dL, + 0xb32ecf7e58773d4cL, 0x5822a782fd3540d8L, 0x5ab45c3f04365042L, + 0x400e3aa04b4d85feL }, + { 0x473216495e46e4a2L, 0x37a2ed6424136074L, 0x659223b1c60ec77dL, + 0x5e13aac3e5e0ac2eL, 0xda17c41bc5107ab7L, 0x65b22ec973c253dbL, + 0xff3867b8a5012296L, 0xfed660d50621a99bL, 0xa3c28506c89fc3f5L, + 0x3ed350b9f16451a7L, 0x27c3e03267cb586fL, 0xc807c779967185b1L, + 0x09c157d44a13009bL, 0x362f7647adaf1f4dL, 0x4a42b9acf3a6a198L, + 0x131c3da28da6e039L }, + { 0x4a785ff1a7da83baL, 0xf415b425d04f4436L, 0x7c0899bdec03f812L, + 0xc58d411a80f5f4a2L, 0x3d32d610fda251b9L, 0x99bb4504cd3b2f32L, + 0x198c444bf4c2083cL, 0x60c261af730e83fdL, 0x060ca4dfcb02db90L, + 0x0ff7838b9df1e7c8L, 0x6b79cf97c4c690c9L, 0x131514d75d75f154L, + 0xa7c074f11cb0e8ffL, 0xb920aac1b2c17615L, 0xde8098ad44aa0ff0L, + 0x71d1a46a34545ce9L }, + { 0x76178f76fa1b382eL, 0xa0d8ecc3772dda0dL, 0xaa5aab2ac5d4d130L, + 0x27d38ba48d72622cL, 0xc5410db6ca3bed06L, 0xf637a588793ceccfL, + 0x1f65dafd6e65e3d7L, 0xc3b44a8560a45641L, 0x0f47b3a84f78540bL, + 0x824fdadd5e4d60f6L, 0xd8ccf90c17d3b6d5L, 0x008eabdf325fc13aL, + 0x3e90d7163648fab9L, 0x3964ff3a24c52d4bL, 0xb95cc416533d0acbL, + 0x6cd2699f1167f521L }, + { 0x2d8c0b3b12f4f3acL, 0xb03dcfe299d1bdfbL, 0x540034f830f37326L, + 0x22dd68937c5a8c82L, 0xeb7093d0cd8f1442L, 0x892795a7585742f2L, + 0xe15f282c087adaddL, 0x7bbdc74916ab7b5eL, 0xd30fe40ba58acbb4L, + 0x0de417ebe2bac39bL, 0x4b4b19a6c61a04bcL, 0x9338c34df2735569L, + 0xe8f0374230ab196fL, 0xfa2efcb86c88c965L, 0x19eee274c7eeb826L, + 0x327c063fda345dc2L }, + { 0xab399eff5b47cd53L, 0xbbe9869d1943aefeL, 0xe64ecc7b1402a866L, + 0xc3e7c2aab1c25a16L, 0xc4216b79022de271L, 0xe58dfcc8366d6a5fL, + 0xd159509eda813336L, 0x370400f2130bfb7cL, 0x1be4e05993b48780L, + 0x0623a1fe39f3cd22L, 0x72aa22b2eecb4f87L, 0x1af4c4966c27b83bL, + 0x7a42a94bda5fa5bfL, 0x9afba82248b01af2L, 0xeb6b9d2a3670112cL, + 0x020f19d1c0df6856L }, + { 0x37051a86a4dbba20L, 0xb618ebc6db1de5c5L, 0x9a780a19e6525840L, + 0x9440302dd2bccc4dL, 0xe9ff023d10285a24L, 0x3b937ee33a486268L, + 0xe37ee2f24cd61147L, 0x79fbbfd3a3d057cfL, 0x5fba16d3ccddefceL, + 0x916058ec5b231727L, 0x47699ebe720c3adbL, 0x262743868b4f6bbaL, + 0x54b0092af18a0770L, 0x99d090ebacca1160L, 0xf757e1ff0c888f60L, + 0x79e72720b0050544L }, + { 0x632acf252820a239L, 0xb1a3974eaae6b310L, 0xd61fd6ba48c0a1dfL, + 0xd2453c395a3ee7aaL, 0x548455a0b980446dL, 0x9f29d97bde16676fL, + 0xf252ca0c789375a1L, 0xe961af3e7743a985L, 0x70c79c5666cdbd8dL, + 0x14a3854ecbc538f9L, 0x58daa73aa126851cL, 0xe9b5bb452a9f558cL, + 0x37af7f83fbd15e05L, 0xa448792738a1939dL, 0xe428b2b59511a056L, + 0x001d3ce37015846dL }, + { 0xd6be36b9e145b1d7L, 0xf3e3938a009c5664L, 0x2e562e7de7c0f6dbL, + 0x951044e6c343f539L, 0xa5ab62b8d90897b1L, 0xb1a1f70b512f797cL, + 0x91cdd754750f28e4L, 0xb4c80e2fffb8165dL, 0x65ed39c7594d02b3L, + 0xcc12a49d56833edcL, 0xe73694bcf3693a18L, 0x34cc134afcd2c404L, + 0x071bd5fc11d40194L, 0x05759047fc585e46L, 0xb3280360790b7a04L, + 0x4bb8c6fc40afc684L }, + { 0x3120e2ddfd0f8796L, 0x6968a40db133c9deL, 0xfea366c0a9369c6eL, + 0x37e5b6d66007273bL, 0x39e4ecf08cb81439L, 0x487fe9cd9febc005L, + 0xeb8af4440199b53cL, 0x2f124e3b293519ebL, 0x860c218ac82c9c16L, + 0xacd1d6f2709dc590L, 0x5696d54536d50529L, 0xc03f5df959120bfcL, + 0x99a3e88d10ffa690L, 0xd4f9cfa56c432827L, 0x2e8fea9e9a135d89L, + 0x3699a881b6a77e78L }, + { 0x5bca33721eb1c64dL, 0xe9cf3a2df1d28154L, 0xb7e2e9b36537106fL, + 0x06c171514f7cbf4dL, 0xcbde416e2058b37fL, 0x82c53a7e8834e9c5L, + 0x94dbdfe2e9ac3a75L, 0x795ec6cbc5e67c02L, 0x8c23c25f1426a80dL, + 0xee2cd20d6a8d4f9fL, 0x838daa54d3b7c235L, 0xb9e08ec03d7a4d52L, + 0xca9475e9781cb473L, 0x7271f39e5ec31caaL, 0x1df08e9f82535187L, + 0x4f3a4b03208aff8bL }, + { 0x0f7b81071ed095f8L, 0x23e37fa6da226d4eL, 0x8b0f9852afb36d1dL, + 0xb114634e07d8e311L, 0xb9634a97e3e0f16eL, 0x2454bb9c421eec37L, + 0xb4ecd5dbd72b21c1L, 0xf96038686df20d7cL, 0x9f5359fddf86e0a2L, + 0xc43d54fa5ac488aaL, 0x56d714abd1049df4L, 0x13152b3eb020607aL, + 0x49be1c187a02325eL, 0x44f24f4a52ae84dbL, 0x9e525c030b5a7b80L, + 0x6d874446a6d179fdL }, + { 0xd29d07aabe9a42f5L, 0x1fd5316c3781ccc8L, 0x71a75a6d9dc69ea1L, + 0x4e19e0df88fee91aL, 0x99c2b4dcf8d44f12L, 0x05f6df9231ae94e4L, + 0x27fba876cf28ccc2L, 0x6e1a0f01f57f7cebL, 0xe03f1f34f3fd3b74L, + 0xa0edc4a742c1d213L, 0x5caac2707deb8580L, 0x0f5d791faf0848bcL, + 0x17f514ad07ac759dL, 0x95a39734904fc531L, 0x95a4aca97bb70f3dL, + 0x3cf384c9ff9c5609L }, + { 0x700506bace1fc9e3L, 0x49721742676b0399L, 0x2b4a1b8de72bf7b3L, + 0xca8602a879b209f7L, 0x90580b90ce26a8e1L, 0x1ef339b7fe24f39aL, + 0xb6c5d991629362e1L, 0x51174e1a577b24f4L, 0xf380fcb505e451e9L, + 0xf4d97afb148321bdL, 0x099806bb747e5d2aL, 0x85525d65be99a608L, + 0x264828d9d455e820L, 0x8c8c5405d8560a65L, 0x3c67e73c71030770L, + 0x2b248850ee73df26L }, + { 0x2173cde68541159fL, 0x78224c184fb410b2L, 0x07a286191f2ca1c7L, + 0x52c207d6a8b23e40L, 0x071a0210a6b2344aL, 0xdb0e587cb5ed2945L, + 0x6c56b8ef810fcc6cL, 0x1248c58f62d843b9L, 0x4b90363d74c66975L, + 0x6348f7f2e66c66f6L, 0xb2f9d441c126bcbeL, 0xac07f2a373ce49e8L, + 0x52486758e81b0df0L, 0xa108b54d1d4621d1L, 0x17261ece74414a1cL, + 0x938b3bcc6a3ac215L }, + { 0xa9e4a16be4ded340L, 0x8e65fb2a80e88036L, 0x97089606dcd73acbL, + 0x1c3a0434aaa657a9L, 0xf304fc5849101b06L, 0xe60fb61ada0bb64cL, + 0x818c2aecf5542df5L, 0x7402057656f76d5fL, 0xb566b79092533d97L, + 0xae4655e574d6eb5fL, 0x60f7a1b5a55b44b7L, 0x7970179b93747ea5L, + 0x8ae7e0e8f2dace56L, 0x9847460784e83c06L, 0x24e8c9ed15307341L, + 0x6cff58a5d9e89d6bL }, + { 0x508c01b003e51f68L, 0xe1d1f2251d2fe7d6L, 0xf7998d0b09bd8805L, + 0x255e907a03e415b7L, 0xd148467d607d9798L, 0x055c3b1e9b453896L, + 0x35001013809f50f4L, 0xfbbb2fa6d0233fdcL, 0x0b680b0aff1820b8L, + 0xb1d404dc38d317e0L, 0x133d5444ccc8c7dfL, 0x7fa847e66ec13f84L, + 0xc33f83d8046e2e48L, 0x3c627fc54863b3acL, 0x5f67f8aaeb936af7L, + 0x5fe4ac8f31b79327L }, + { 0x581aa4bf8b6f401eL, 0x05db12a3ad5c7ed4L, 0x7b0187266fb07b4aL, + 0xfdd11f049c22bcd4L, 0x5454a7d469371c95L, 0x066c55fb99a46eafL, + 0x18637c7c7fef96d0L, 0xbafc1d346b83e95cL, 0x55c3859300bb42dcL, + 0xdd8dec2b34e7e712L, 0x69c9cfb0b184cee8L, 0x8dcc0c4249a27864L, + 0x290d95f22010f2e7L, 0x86e254c96977a420L, 0x20931c89eb2abdadL, + 0x81377164121c0548L }, + { 0x6266b25e9c5a8edfL, 0x6e1388c21078a7adL, 0x5f02737d4876eedfL, + 0x242fa7f962744617L, 0x3e2cfbd9b385382aL, 0xbadad7b102f71befL, + 0x562abcfa677d0a92L, 0x573ebd1751fdff34L, 0xd7f658527c250c78L, + 0xe0cf16eec47ca896L, 0x8ccd79b067622c9eL, 0x31fc5882f8f2c075L, + 0x9232b37ea6008515L, 0x4d7bb36182e8c5baL, 0xbf24735cd2f146feL, + 0x79c280ee9cd2db98L }, + { 0xbdcc8203f2b48122L, 0xa8c04916b04ac48eL, 0xacf064dc9fc4885eL, + 0xab83899782c1001cL, 0x7339e721676de250L, 0x17aa5aea8e1ab820L, + 0x24d28ca06bc14b2eL, 0x570c5bb7816b6230L, 0x6c51235ccee6b606L, + 0x1b2bf89f183eae42L, 0x3e3af3c69c66274bL, 0xe0b04426b51e38bcL, + 0x26dbc58e73e40e3bL, 0x3f9dd578b5be5be4L, 0x9fd9f79152c8f408L, + 0x758073a4a9e3ff4fL }, + { 0x7d27b0578691ca22L, 0xf206bfd613a2a1b6L, 0xe84bd385ac795413L, + 0xc5d18a2a75536607L, 0x2e166de7c8a0e24cL, 0x56d5750c3c474dbdL, + 0xdef444c11366843aL, 0x14646e53cf4b8432L, 0x4bc0d030a9fd9783L, + 0xbda4c824297ee203L, 0x3d0b10bffd7be6c7L, 0x2d21647608c7f3ffL, + 0x06e52599b4fd4c45L, 0xfbab9fa149e9e104L, 0x9342a7fa8661d32dL, + 0x3f3e3458faf66aa8L }, + { 0x51ec35af951597aaL, 0xb677d4ac49df64ebL, 0x0276cd9c9bf4eff5L, + 0x423eca49515a2935L, 0x8a696553fd9bb9c3L, 0xf99ee9dfede1f09cL, + 0xb8fa2956199e5f98L, 0xb763875835292c32L, 0x8734eddcfc40e81bL, + 0xd82d5e9f65457d95L, 0xc8ee323e30c78d2bL, 0xe77b2e4cc1433d67L, + 0x56d9f8073c8314aeL, 0x441eede22a0e2f63L, 0x1e9e17ed6c48295eL, + 0x640d20c434c294efL }, + { 0x4e9a0b8e3284d513L, 0x074c3545f315053aL, 0xb36e740745acd52aL, + 0xd80bdcfc1de50db7L, 0x8d9d47dc2549fc46L, 0x29b6ef13303f07a8L, + 0x4e461aca6d4ad4c2L, 0xca8e351dfc9f1b73L, 0x8bc4094d57460e65L, + 0xb6302b330f32d367L, 0x69a074b6285742e8L, 0xdfe52b11876c29c3L, + 0xf39e4609912bd17aL, 0x8ee40d66349aa639L, 0xb968902ac72e05c1L, + 0x0f9c1ca8c0d92816L }, + { 0x1ebbaab367433df3L, 0xb6aa534715d3628cL, 0x13a320d897f0c5ccL, + 0x72c918cb65e408f9L, 0x4b638854d5373451L, 0x731399a30b4dca09L, + 0xcf2567300a3b1326L, 0x5ea60dfa6608b388L, 0x58ad74b07b290dfdL, + 0x83202789d7694f9bL, 0x48593db8b6630fb1L, 0x3db47f70c65e3eafL, + 0x63949c913e7263f8L, 0x9b9acec6e6e6ff33L, 0x34bd9ba7098a8240L, + 0x7e31c12f45d36ec5L }, + { 0xbe281d680dfd2dd7L, 0x1efacb0024ab61d8L, 0xb9c3005f94431f97L, + 0x660c8dfa959cb3bcL, 0xfdd5fc30cffbb406L, 0x7a4631be7969a10dL, + 0x336e309ede13fd1bL, 0x76b3bfadfc947076L, 0xfa91925ddcc72223L, + 0x741f0d73156c4ee1L, 0x4f64ee410e2b3747L, 0x86be92d3efc4d93cL, + 0xc53b7e03fc4fbb2eL, 0xac196cf5337ca1bbL, 0x4de41a307e23ba60L, + 0x1a219c45326d5357L }, + { 0xfdcf7ef8aa4db0bcL, 0x2e2318067b6c9963L, 0xc26390673d8a192fL, + 0xc0cec2e2ffdc7771L, 0x997c8e35a2fc0edbL, 0x78e10ec182cc6043L, + 0xfd0de2cb2b0c8120L, 0x4d6c457f69e57f8eL, 0x953e69b25b53f1c3L, + 0x422a330ac4f89cb8L, 0x92ff232995566be6L, 0x73cd502d437442d1L, + 0xf04ce590bea69403L, 0x6ac1537ef8030662L, 0xe02bcf77b6d0bf93L, + 0x17aaa999bc90192fL }, + { 0x0d3d56438e55db2eL, 0x835dee433b946851L, 0x1a1440e55b88462fL, + 0xa6ff3b35ea17e27cL, 0x23f99c36dd95f7a9L, 0x7217fdd9bdd672cfL, + 0xf400ac1edd2045c0L, 0x94b55c874ff06b25L, 0x0a44a0e50e4a49beL, + 0xe8925e91b43b6813L, 0x78bedde1214f96c5L, 0x0f456a4c0f97fa97L, + 0xa28fd86ba5bfd267L, 0x3b4b2d8fbe7608efL, 0xfbd5ff8c226474bcL, + 0x6b282af0a5f3b24aL }, + { 0x78fc025f6341a595L, 0x591c38d6a445e28cL, 0x72bd6e3deb446842L, + 0x3f9466d375547833L, 0x911414d3083e16c4L, 0x145d946695a7acb4L, + 0x102ddf098fd2fb64L, 0x2a2b2d2d0bfd87b1L, 0x69e9be5c59455088L, + 0xee378bf4a80245deL, 0x80b0bd68b2306b0eL, 0x76a545c6c2be9f3dL, + 0x429d167b4802c245L, 0x13e644272b412dfbL, 0xb664f529ee8d9762L, + 0x6d4f5d2354706ebfL }, + { 0x35c8f2b600ba9f88L, 0xfdc807e07bb6d0bfL, 0x0a126d42b3b81e5bL, + 0x335ce6cea7ac781eL, 0x3e308e6ff37dcba6L, 0x028dca6263c96487L, + 0x72eba57e8818434dL, 0xa9e3d59f79b78a26L, 0xd2f0a7dd2f07aea3L, + 0xe0fe467824d05f74L, 0xb20851700116deb6L, 0x9c2a5e9258f37580L, + 0xe78bd7a574070bb3L, 0x551fc872b9977d90L, 0x6eda93c440db81b4L, + 0x4aaf0b4fd65d34adL }, + { 0x9bef25063514c7afL, 0xb09e7dadbc181eadL, 0xef3cae878fa3ec58L, + 0xd8dbfab5173b8685L, 0xb2490fc0921d32ddL, 0x4eef386b8bd9c466L, + 0xc1cdd52fa061dbdbL, 0x64de989a25bc04dbL, 0x06f9836b85728636L, + 0x11a5a8048be44aa0L, 0x16dede4e097018c7L, 0x72aec577b2c11fb1L, + 0x144dade1a721ecd9L, 0xf99c526bd6ebf3a9L, 0xa1d4165b1c2e14d7L, + 0x8b2cbd3982bc6337L }, + { 0x28ec1bf28a52e991L, 0x0ba202f6cf9d42ecL, 0x8307d130c634ea45L, + 0x3fc257b3c5762b9cL, 0xbd3298d1487c2a2dL, 0xca14f1a7a319488aL, + 0xc70ca93b06ba06d2L, 0x9aa3f4b3ee405e89L, 0xcc64eeb335deeae7L, + 0xd155f57803bf1d4cL, 0x041ec0b545616bfdL, 0x23df80e6086e33f6L, + 0x399a79c8f0243cf5L, 0x86c2824e874ccd58L, 0x220eeaec8fc5c831L, + 0x57e283047dbe3670L }, + { 0x6e60b698fbcdf666L, 0xbdd06a998bebb1d2L, 0x4044adba80498436L, + 0xd76bf75e522bc88dL, 0x655c4b9b28423b20L, 0x65c0f49253398a72L, + 0x76d4f2b70ca37601L, 0x469899252030fa5aL, 0x96b37e87b6054705L, + 0xef96f73153de1b2fL, 0x5ecbbc8cad54ef05L, 0xeb289d0aa93617b0L, + 0x3ac0fbd57cba217dL, 0xd0d3cb5619d4a2d7L, 0xe8bee9d4c91d6063L, + 0x4f12e037696ffda6L }, + { 0x4ccfa42215f1a610L, 0x804a5c553786519aL, 0x1246a45473838134L, + 0xfa15b4844b284e2aL, 0x36464c65146d1320L, 0xfb6ba88c70a8a0faL, + 0x74e7cee793c4804eL, 0x8c34d22cb95ae16aL, 0x9d9ed89ff9c1d4ddL, + 0x61a0866d32025371L, 0x45b232b29bd6444aL, 0xf888e92cf277bab1L, + 0x73e69c6ea9448b02L, 0x1a496ea95b521ecbL, 0xa8f78ea75858afb2L, + 0x83d2333eb1266f91L }, + { 0x1c63328867b478d7L, 0xa1ee1ae150a2fc9cL, 0x05b6ab3018d2241bL, + 0x69f1f288893cd696L, 0x159d6660a8117a87L, 0xe812011970e73d77L, + 0x528fef0093f55f0aL, 0xb3978db8d854dfb2L, 0xd6b43ef6f45d9fbbL, + 0x17de4bfed5bee397L, 0xa01e0f596bf76dadL, 0x28b2280e3d40754cL, + 0x8edb6122f8e86ef3L, 0x8226b6afb7d1e586L, 0x463532152f40a55bL, + 0x7362f13ec5a31621L }, + { 0x792eb27c73c0c430L, 0x8cc0a65fa51c3657L, 0x50a5ceced2194f1bL, + 0x18945688814b4947L, 0xbbf0a81a4b6fbbf4L, 0x376f4f58f0aa8608L, + 0xd9361d683987795eL, 0xb6510cd8e3a8d0d5L, 0x63e2fdbfb6c1a455L, + 0x2c91154eaec891f9L, 0x0eb1e715ff568f64L, 0xe7af9cd72f2b399eL, + 0x1fc39bac89f0bf0bL, 0xf0861d9290983695L, 0xd9b16f02da0a20a8L, + 0x2f10693fa38c0eadL }, + { 0x07a6ce910c06ded2L, 0xf974842f2fd9087bL, 0xe468bfd6a9f635a6L, + 0x04b618911ed60626L, 0x1fb2f89f369ee548L, 0x9cbd1113dc96a201L, + 0x6759acfe10d633acL, 0x64ba66fc8faa629eL, 0xa686ae4947f38283L, + 0x828c3a05d59cda99L, 0x7c7afb1408ea2f6eL, 0x2551c8e4af3953c8L, + 0x5b53d2799daa9e4fL, 0x1eff68d4ad6f1940L, 0x2775dbdd96437cdbL, + 0x985f83e44fe7a043L }, + { 0x89603c16eaf45294L, 0x70131160c24b5751L, 0x4c11201839d6b52dL, + 0x7079cf02ed943340L, 0x0c5b028b74f41b68L, 0x3dc3f0769c8ac1e1L, + 0x5ac5eea3f8b24f0eL, 0xee6684bae34c5c22L, 0xa5259e639abc452aL, + 0xb07d2cd1e9df45ccL, 0x07019c931a443cfaL, 0x68fddaa992c003b3L, + 0x2d9f179c0d8cbc2eL, 0xbbf15a6f1e781ca7L, 0x54d779d550dcc799L, + 0x0c88e5400fe962f1L }, + { 0x84f71a6ae8f44357L, 0xf75b4bf63a3cab6aL, 0x334c9d9e5aebc680L, + 0xcecaf0848a753ef2L, 0xe28014c1075e3c8eL, 0xbb9d5a38f74f8d3aL, + 0x75988464b80e32aeL, 0x7b328e6ff2bc3792L, 0xebbb1fafeed0e197L, + 0x674eac955a33065aL, 0x8c19fd8f922dbce8L, 0x8c17ae85987b907aL, + 0x89f336273b3a2cd7L, 0xebaea019fa87772fL, 0x4e5de4993a25ced6L, + 0x8e2560b8af110715L }, + { 0x56d3746c3141aba6L, 0x45a1079fbab2cf9eL, 0xb63828319cdd27c7L, + 0x222376329dfd950eL, 0x1e0b15cd3a9408ffL, 0x49a80200b1160118L, + 0x2719db5da383bba7L, 0x6078340a651046d5L, 0x8929d4de97523b1fL, + 0x4040345c8e0a28abL, 0x61275ac20adf09c7L, 0xb41ab2652331d611L, + 0x230cc77c5391ca50L, 0x88be0c928f922315L, 0xfef3d92b92fd9a29L, + 0x59005f228324f2e5L }, + { 0x6bb1750c3c4c1c74L, 0xbe73aac0e966fb79L, 0x85a75d9266c5973fL, + 0x8c97f9323a8656b6L, 0x2b7043b150446cdeL, 0x548916f73ff3897fL, + 0x913dd01cb18b72b2L, 0xd0a751f1488c0de6L, 0x191757148558ca58L, + 0x9771430144a663daL, 0x2df190acb0e08618L, 0x0080fc0cf39ead9cL, + 0x0085ac6e17382da1L, 0xe97918513262a338L, 0xe4495936b43bae8dL, + 0x57a78e26d783df6eL }, + { 0x161b346f40dbddd8L, 0x2b49a9279410c3acL, 0x8c5427831886cf3bL, + 0x72df323233b93debL, 0x9c8d59f540df579dL, 0xe5d7a67dc20ef500L, + 0xc46b391867f08643L, 0xecfa2445ad96adc3L, 0x658f589b0c4544d0L, + 0xe6ec9301e08417d7L, 0x6ca5ef6ac454e288L, 0x4191048fac0f462dL, + 0x852407d808d8a036L, 0xb4c533a7f6d35b7eL, 0x3251e4128f6ada87L, + 0x1ca370c581c472e8L }, + { 0x94bd5171a801b68aL, 0x7312879cfd1998b3L, 0x4905aabf41163202L, + 0xb5fe87f4f5b01fdbL, 0x78de523a9cda128bL, 0x0bf161a1c7bd31f7L, + 0xb5decfd023904c35L, 0x224b2882e188f12dL, 0x0dd2801df99dae74L, + 0xcad467b508cd1cd2L, 0x6c311c3dc0867e39L, 0x71a117202b425072L, + 0x83bf464e2efd9003L, 0x53d0448a1dbd3b03L, 0x32db52f4e6265baaL, + 0x2584b34c4c33ac79L }, + { 0x3cb863892aeec688L, 0xa5e740ba45fbe523L, 0x422e71f7fd60b5f8L, + 0x455d185c4874913dL, 0x04c2bb36fa17d80dL, 0x3f271854ac054524L, + 0x76dd3045a8b9a657L, 0x2e42c3e162ee7cc8L, 0x002667064df6c7d0L, + 0x5927dd51dc7cb488L, 0x6b3faabe187897e0L, 0xfe6ad22ef2d5737cL, + 0xafb60269ff51a9ffL, 0xe1c8354569807baaL, 0xacddb6ff951ca49aL, + 0x7e8113743f9ab085L }, + { 0xad722a8b830a88b1L, 0x91918ea8ce1117e1L, 0x3e02d0b80409b47dL, + 0xb53812d36c46d1d3L, 0x2fd09db0e589669cL, 0x9845cd0615b0cd5eL, + 0x0c1c155a2386c453L, 0xda774de5f5ff43cbL, 0xbb076b98e391c0cdL, + 0x97d71eff5004f286L, 0x23e0b46caeec0bfeL, 0xe453866732a1ad94L, + 0xfe0c9f81396da422L, 0x6376c1a263db2bfeL, 0x001c7918ba56fa91L, + 0x436b8c64df8485a6L }, + { 0x88117e9d8ab764bcL, 0xdfa61e94a077df84L, 0x5a7765d30c18eebdL, + 0x548916affc9451dcL, 0x01a52e33071a347aL, 0x633b95deb23b41dfL, + 0xdd7d68c943c8c286L, 0xe4f9d41e18d97068L, 0x79908b908c92799dL, + 0xe614148ed47394a3L, 0xe5018517cd51e53fL, 0x5060075e0243dcb6L, + 0xe5dcde6217954405L, 0x6f7c90e1537da5ffL, 0x1df7aae40768cb66L, + 0x5266ca9e6dbe95e1L }, + { 0x84ddee6d1386b3dbL, 0xf9e4af5a7c38e540L, 0xb3418440eb04f49dL, + 0x2138a1e8fde5a4fdL, 0x3e6e692430257cfcL, 0x3519c6e319fd70c1L, + 0x8f34e17486c31ff0L, 0xf1e298fd940ce1e8L, 0x6fb8cb1d14960d7cL, + 0x207c13472b2f3bffL, 0x899a20b4146ef8ffL, 0x7dec362b7bd3e220L, + 0xa975044e626bea27L, 0x0f32b4494fb4cb67L, 0xc17a09201fc6703aL, + 0x41f325b99cd84a2bL }, + { 0x312ed513ce2843a4L, 0xe748498e00728afcL, 0xa8ef28224d864ce5L, + 0x34064704a620083bL, 0x5905e1d94bed338dL, 0x2a578cb5063e7b38L, + 0x98276d96289e7bb9L, 0xdfe2dc47f17b7341L, 0x5923521f1dac8944L, + 0x3db6d28d23400aa7L, 0xc647705ea761ba43L, 0x8947ba6d9bfd07ddL, + 0x00f2e3ac242ca8fdL, 0x49ef4670eb8c3468L, 0x7db3d37bd9aa18fdL, + 0x56b30fb6e58cea9eL }, + { 0x07ecdcaacd80a428L, 0x7af922dc8732c891L, 0x20d887983ada441fL, + 0x3bed9a44924b008aL, 0x2123533cb2e81c3aL, 0xc34e407565f807d3L, + 0x0bfaefa51f2faecbL, 0x78b634a5ade8a88dL, 0xc4e0b7f894392a91L, + 0x3092237790bb1cd8L, 0xdea9b4faf87204aeL, 0x3edf81f585d3cd83L, + 0x58f88c51c6523a79L, 0xe472fb8b17c0d969L, 0x899081e5dccf7f07L, + 0x1353cc5758bdd146L }, + { 0x28a5649739bf6e18L, 0x59e8b5a2649b89c7L, 0x8d9434a0dce8b8e7L, + 0xd935bf512047040cL, 0x2ab3a1646a7b8e82L, 0xf1583ed627f81294L, + 0x8416a7e072d67297L, 0x49685d86cd39e42bL, 0x8a797fc7958ddbadL, + 0xa558f928155ce6deL, 0x75f4e570f8a36235L, 0xbc69cfc052877ae5L, + 0x8f4193a9a6b16ebdL, 0x8d1df43cbb1cc1f1L, 0x723a830e5a21e789L, + 0x3ec2185df451df58L }, + { 0xb9d4c7d71f0bc2d7L, 0x6982c6cc6e51d412L, 0x92e02d93a09f80f6L, + 0xb7dd2d25047ae09cL, 0x3503149f37f351f9L, 0x69d49ce1c77850beL, + 0x60242acb12f0d2c8L, 0xba188c567bc28b9dL, 0x8e40612106bc0550L, + 0xb0d84b1f8d7d4329L, 0xb4a67ae7d38951e0L, 0xb527c57b8bc97607L, + 0xbc93c5f35497aa72L, 0x5f1de8cc39bdd666L, 0x3087dc5ce9d447a3L, + 0x89b356b6a211abe5L }, + { 0xed6db0afdfdcc837L, 0x0fb80baaa871b7a9L, 0x413abfc91c1d4b72L, + 0xf5b56bf7adac9e5cL, 0x5664a2da8b8657a3L, 0x11b04f720e41d94eL, + 0x63e11d2637433658L, 0xee628ecef426daeaL, 0x011619c9cb162dc2L, + 0x9cf5817f87648643L, 0xe1bb97025584bc86L, 0x2cc27cef00bf7928L, + 0x4ef3a80edc60eee5L, 0x7e1202be87adc2f9L, 0x656f18e08a0d4f52L, + 0x39c4f10d57c5d126L }, + { 0xb3a9b68ce88aecd3L, 0x555b0918a518aa9dL, 0xedc1cdad4bd4ee54L, + 0x79b68b6702068d84L, 0x7dac80d0811ac72dL, 0x6d1e6d35a81a0a78L, + 0xc841e9ea3bd16283L, 0xa7bc1775894c4444L, 0xf2b63725f1aa1202L, + 0xbec7767ec7d4c556L, 0x2817ebb3d46ff51bL, 0xfde5be8d73f7e339L, + 0x44c6c9775aed24c4L, 0x0b9a1707b6e579cfL, 0xcff164789069fbccL, + 0x414b542d49152b00L }, + { 0x33c31e58606e173bL, 0x5b7f4e1b90e6713aL, 0x425fb512debb20afL, + 0xc788c61705120e70L, 0x3ef056029013e4ecL, 0x9f9d35ac81c6e6d7L, + 0xe131e88f9450690aL, 0x708f9b3244af082eL, 0xb2e4d66c1ba2aea9L, + 0xaf1f4a6e740db29cL, 0x74ab9248d1843007L, 0x13338ef8ed556a6cL, + 0xf48e623e270d17a6L, 0x3c7362fa9608f5bfL, 0x43977874444e8515L, + 0x52678d6ae00b8b2aL }, + { 0x5dff1c59df36aeb4L, 0x52d6653ca92bc0abL, 0x0e03f496927a5f81L, + 0x8509d4142dfd491fL, 0x258c2c52a571f89bL, 0x2bd6180493334485L, + 0x1a33e94f3f7d9e09L, 0xfab418d32c1bf906L, 0xf39c490e5aa5695cL, + 0x0e41196ef6d2d7ffL, 0x3ecd40750f7948a9L, 0x4b58f9b2d3053b4fL, + 0xb8ee842a5d9974c9L, 0x23a59c1dbf22f682L, 0x045ac614c8efcea6L, + 0x7040ba5bc10ceeddL }, + { 0x2c364f81515a1a96L, 0x31a63503184327e0L, 0x0a0966501ad93d4fL, + 0x9d7694f1273b6173L, 0x8886d876d2cda9d2L, 0x1e01a7422814c177L, + 0x3492276b8667696bL, 0x2fd4f0c65b25f006L, 0x6527349ffb294c4aL, + 0xc1fe0d8ade1d336fL, 0xaf9a23e8e7e3860eL, 0x97d2b721b774c31eL, + 0xfac3e5824365784aL, 0xff2dff4e70f4eaa3L, 0x3d281e1afe873248L, + 0x9043a6d60bd1c9c1L }, + { 0x1511a0fe766c7937L, 0x1b2ded5cabbc3be3L, 0x2ac160cce00888acL, + 0x928754bd616200f3L, 0xb801c83d34a2ea06L, 0x8ad7a03a9cbe106fL, + 0x996b0822cedfcd94L, 0xc3c3463ae4069880L, 0xfb12ea4df597f663L, + 0x2c8d383440c92af9L, 0x79bc85c64e8da154L, 0x95771fa2db4e801aL, + 0x7bd2c1381e3579b2L, 0xe45c75dfffaad078L, 0xb0760a3cb73eac46L, + 0x26362b483a125f35L }, + { 0x25c68d28eefc3e89L, 0x2d0ee87769e9ee71L, 0x8b07bb86af5e4b75L, + 0xdb709072cb86b333L, 0xfd3d20eaff552bacL, 0xa5eeb2b14c0da1e9L, + 0x391f688a44f97145L, 0x21fbd3101e06d485L, 0x45e4f2a5bea9cd49L, + 0x7b60d464a7bf21daL, 0x193f88c8054d5471L, 0x5ace53d1bee0f2e9L, + 0x92c26563c1439273L, 0x9c86e0b296c6b5eeL, 0x452fe23109ff59baL, + 0x2e952b20555c935eL }, + { 0x2a846bcad75f886eL, 0xe68a5dbed43dfc58L, 0x103e45b6007b1b86L, + 0x580e2ec9355ff2b5L, 0xbc702f26a263ecc9L, 0x2835b386181e5e33L, + 0x025113ec6c122076L, 0xa5c26e3a7fbd856dL, 0x8ef83fb39d6ebcb1L, + 0x7aaa53f2a44d2fa8L, 0x7c14ef3353b1fa97L, 0xff604a1117559a30L, + 0x2bcd96b0b09377e0L, 0xa5c14896db2f0273L, 0x1c0a84c9eb53ef06L, + 0x1236d01730378e4bL }, + { 0xd7481c8fc084373bL, 0x29ae4768646097aeL, 0x1300dfa0613bc34bL, + 0x3712714c934bc2b0L, 0x865246290e2be7e2L, 0x554fbb9fed010800L, + 0xf0ec0b3842314576L, 0x65baf594330a3282L, 0x3bdde1a8706ef817L, + 0x7d2c727dba7530e9L, 0xbb0c5d6674cc95cbL, 0xb3fcd3652438906dL, + 0x19881941d14658f3L, 0xe616f5556c97f0e9L, 0x353c2d854b9ec7eaL, + 0x02a48014620cb56eL }, + { 0x11d6d23d506ccd38L, 0x229a1c549059baa6L, 0x717c9c2769d011c5L, + 0xe87e1b46d828937dL, 0xf5d63bbb83835083L, 0xf0a7b427aadac258L, + 0x99ab26bd9f154d1fL, 0xdec0ffbf8ec955fdL, 0xee957c6749fcb880L, + 0x32395dee1e0114deL, 0x192a64b7369f46c7L, 0x4304466091eb2599L, + 0xbe2da887a2e8c3daL, 0xa44e2c25c3556d18L, 0x31390414b55f75f3L, + 0x1d8bde6f8f217fe0L }, + { 0x03cd39f8a2028924L, 0x6e54f19cb06ecb9fL, 0x862bbcb7d6f05846L, + 0xdbe067165a060776L, 0x9397c97ab10fec10L, 0xf42138266f1bb65cL, + 0x414deccba672ba38L, 0x594d4d43f88b05e6L, 0x7993f57aac94d4d1L, + 0x74fc2a6abfb17638L, 0xd8196b5bb6fc655aL, 0xdc375c84ee8d2139L, + 0xb9b00a02360d3a26L, 0xb36ed35cdeb93b87L, 0xf565b28bcc83209eL, + 0x349c6943c61013c1L }, + { 0xd1b394444de6c88aL, 0xd5c2c4714700207eL, 0xb6f458a221c2b780L, + 0x749f75640850993eL, 0x400ba579baef0c18L, 0x2d742938737c70f0L, + 0xc5a8e2ec21467ebfL, 0x243a666e5337f453L, 0xc991f1c7ed0bd50aL, + 0x3a7f3e90f4bd1f91L, 0x96089e8a5f0e129bL, 0xd0d3a17707389635L, + 0x9cf842d527182ac9L, 0x211952990817c5c2L, 0xa32f327e87255769L, + 0x056587ab89c2d8faL }, + { 0x008562ed1ce4733dL, 0x5faff7cb98e51444L, 0x5f03021fa9ab46b9L, + 0x89494c5eb61a8c13L, 0x57c9503636b35976L, 0x6be84c8f2ac2d2f6L, + 0x0e5b34d89bd2703eL, 0xc4ad918f7e872abbL, 0xc2a89e9fc4052ee1L, + 0xc2caee3f3190b51eL, 0x58fd14376fff254fL, 0x6f3c0d68883e0972L, + 0x63d0a0e90fb15438L, 0xc438764bf6caae00L, 0x815f15653f1d0f6cL, + 0x1b87f2edb86cdbdeL }, + { 0x35792bbb2b0b15b1L, 0xa3e4b5a7ce6ba779L, 0xfbacffd9dd8f3779L, + 0x005450bdc298d1efL, 0x0e3f5556c47031c6L, 0x0770f07a95d68066L, + 0xce3e84e02d1052c2L, 0xb050791e7aa8cc54L, 0x4d621e73ba3223a3L, + 0x87b9b94d39632990L, 0x8df9cb477eb8056dL, 0xe2430de8edfca0ccL, + 0x374bf4169712a0caL, 0xbe3f3c7788848a99L, 0xb22b87b1c4a3e59eL, + 0x8e0227c43e95bc23L }, + { 0x000e22a83210964dL, 0xdccd5df5ff056eebL, 0x02173a1fdaf1ead7L, + 0xd02833e067cdcae3L, 0x1cc574cb8bdcc90cL, 0x86eca7143224b4f5L, + 0xd00e603abb3f8298L, 0xb98ece1b0c1a8debL, 0x228a46e4378c261dL, + 0xc6f9dd0da6165e5dL, 0xb3ae38994b7ef0e2L, 0x3a3c16b3bda9f306L, + 0x5e9a26d338a084dbL, 0x528e59935394e950L, 0x848ecb114ea206bcL, + 0x14b15ab540545d6eL }, + { 0x0f6d86c9664c59a2L, 0x3dfe2be160fd7aa5L, 0x33f9b5699072cb8eL, + 0x5f2325d98176a7e0L, 0x79a0d4e74587080bL, 0xa4ee0def0d5d4e05L, + 0xc0ad9ffac87b28e1L, 0xd6f18d2f3f09b4eeL, 0xcc896ae7292e9d87L, + 0xca88953d6094763cL, 0xdbee97a818fbf9faL, 0xdf20e0e94b63d701L, + 0xcbba6e3047ea722fL, 0xce57e1ca612b571fL, 0x1e16ac76009a55f5L, + 0x742bbed8c4389e2eL }, + { 0x23ea86dcc1dc2c73L, 0x4bbbfd5bc1643abfL, 0x07f8fa1f24d8ca1fL, + 0xde68a6e08cb5cac7L, 0x7d54c64b54e66a7dL, 0x789dba22a9b7ad78L, + 0x4d88d540e364ab94L, 0xc8c2e02d1f72e011L, 0x4c82605746e2a278L, + 0xe6c35bb34b187c7dL, 0xed8b3dfeeb8fe0c9L, 0xb6bc34e87d11e415L, + 0xb3908bbfb865c7f9L, 0x717d1ce6e1ecc17cL, 0x151e3308f7cdd69bL, + 0x97bd5a14b5c94124L }, + { 0xe01c62fe81e82861L, 0x703d4b6ddd42c40eL, 0x7e52e55be65e91e5L, + 0xb8b493745abbbfddL, 0xb4f15f52c72a45f4L, 0xce8435a8550f29d8L, + 0x9df76b9b582de75fL, 0x52e84c5fa20c8b96L, 0xaf77d2d10a8a0af4L, + 0x0389bbd8ca6013c3L, 0xb0d9b9ba26f8305fL, 0xf053e8480cec8b9aL, + 0x4d63367affabda18L, 0x50f53be4a6424c2aL, 0xf892c58c864fba2eL, + 0x317c6d3148cc5469L }, + { 0x0c3525b02cb7d42bL, 0x55240bc9310facaeL, 0x8d5d2022ff20408fL, + 0x6b01402fe0c10ea0L, 0x7fbef68a718eb23dL, 0xa0146b5a41252a19L, + 0x59afce48110e0d6eL, 0xe9a1d27f022de181L, 0x6db96d16dc3f49daL, + 0xfc1ae3f5efbe4008L, 0xf9d70641eccbc11cL, 0x49022279525f8636L, + 0x3769796ac2763c30L, 0x9cc3483c1d90630bL, 0x451651f0ee3d3f17L, + 0x6ae597399da0b8fdL }, + { 0x57b13bc7bff4d2eeL, 0x2075422930b173d8L, 0xb6254bd50794936cL, + 0x1d5f232a5efd55beL, 0xc06f4a854e0c3389L, 0xcf2c5b598e61f944L, + 0xc564861ffd5f87b7L, 0xee261fb15a2afa4cL, 0xb0ff72262d97a774L, + 0x1a89ae22d6cf007aL, 0x28880534d346f214L, 0x8fe73bff97b6497eL, + 0x8a8595b2fa2afffcL, 0x9ef9cf3ef151a726L, 0xa84ee5f1e744b82bL, + 0x6649048dbc63fe72L }, + { 0x91b7bb781e8b760dL, 0xd47b0bd825aadaa0L, 0x81493d9ffab5226fL, + 0x4a6dd226bffc148eL, 0x5a032f8aa29be3dbL, 0x318dbc7034b0ab0bL, + 0xdcccbfb57d654868L, 0x8506ab379c581e46L, 0x09136a6e2830ece2L, + 0x48b79356cf6c80c7L, 0xfa176377ef6b1e86L, 0x2c9c1cc183f0f1c9L, + 0x96f0526d16abedddL, 0x3e0e98e2a93b0de4L, 0x6f2d7ada0f13873aL, + 0x4eb93b5cf3fa49ecL }, + { 0xbd89f7e5e11fae32L, 0xd13d74f5c4023f51L, 0x1b0014df491c3f6fL, + 0x1d849a57555279b7L, 0xbb9e889705ba0068L, 0x82222419c13ca2caL, + 0xafbbb685fd33676fL, 0x931c3f5275878a2aL, 0x12aeefefef3d5173L, + 0x189a5cc8bd8a6878L, 0x82cffdb3d99f0c16L, 0xbf565406a19d48b6L, + 0x5605e223e9c6c4e0L, 0x53e781de86804172L, 0xcdf5c90bc7001cc8L, + 0x2b582d937c043f68L }, + { 0xa1165c8281abc2aeL, 0xa73380f5e2b69ecaL, 0xc097b3d207fff66fL, + 0x5d60382654776506L, 0xdcbac9f3b57fa21cL, 0x78750db4c98dbdd5L, + 0x85e21103d9eff32aL, 0xceed172c2f11c41cL, 0xa8e392649e348c09L, + 0x71cb936b831eddfbL, 0x915c3d06f50864a3L, 0xfe8e33cde93acfcdL, + 0x4bee10d7b3f2f7aaL, 0xc1d8eb48eb7cee9aL, 0x4fa49ce3fa574afdL, + 0x78615109862db4c0L }, + { 0x3fe3f4807ae72c21L, 0x631aa144fd0f0da5L, 0xc76ee1e8f8c3a454L, + 0x379ae09451b4f1abL, 0x2a3a4397d7cdbb24L, 0x7a14cffe82bd5fcdL, + 0xbbe4ed12f427ef5aL, 0x9b0a43ee284d3ccfL, 0x57b78b938eec6e1eL, + 0x18d404e467b8e87bL, 0x0c8adc0534374c20L, 0x643736055428deb5L, + 0xb4d80ec0c3afa2cfL, 0x6d51f93c3aa956f9L, 0x9f9a28ab84161c68L, + 0x540b6bb76bc9c025L }, + { 0x04e1734c321d315dL, 0x4ef56612d86e05d0L, 0xeafae145bba8cd81L, + 0x1fb07a49acdc789aL, 0x6a21e9ad5877570fL, 0x2e4a837eb9bc53deL, + 0x436db2931d6298ebL, 0x43afbc78ea362f45L, 0x2a973d97aabf6585L, + 0xdce7dabe0c924d60L, 0xf69d98f07cadf0e9L, 0xe0b505a175020538L, + 0x3db7d1a34461cd29L, 0xe1c287765e20e818L, 0x2ca2586752dd50f6L, + 0x897cab1492e0388cL }, + { 0x59ed38130d8bab8aL, 0xc11d364ca438200aL, 0x0687bf2c40581415L, + 0x86ad0d3a7ac89674L, 0x44928105b97411a0L, 0x74984b11f383371cL, + 0x70d2ed840d1a831eL, 0xd883628b6c912fe0L, 0x44f8f7fb14fa88d2L, + 0x564f2a4dcf0ac93eL, 0x82f629aaa6c24fa6L, 0xab906ba3bf6cd949L, + 0x2c822e6720a5182dL, 0x2ff47dac30eb93a5L, 0xdc62c4a4fff673aaL, + 0x64b00763476b0ec5L }, + { 0x1e3f533eb3c9a404L, 0xb1db7f73b7ef9952L, 0xc7f13e296c253693L, + 0x7ce7f4c40738eed4L, 0xccfd3b33ce26cad0L, 0xd878493501ec5cf1L, + 0x3f8fc09ddc084e01L, 0x217cab32c39b5acfL, 0x42daf0bb9ef5551cL, + 0xfbc76f56e1217a95L, 0x80178b12c237002aL, 0x0b52c39fb070a293L, + 0xe3925153576ca964L, 0x2555942419d68e36L, 0x291fb82c09e50e84L, + 0x7dd22ea66618ed8cL }, + { 0x7ffe844b49cbb3bfL, 0xde0cc7045562fb25L, 0x1e6ee5379f5a845aL, + 0x956d7f26e51277fcL, 0x2c75d4b930635718L, 0x39a1489296957f34L, + 0x8cf4eb3282e5742bL, 0x6b0d3ddd83247b72L, 0x67a9f633201a4237L, + 0x416403c11414a485L, 0x60afd447b6f6a916L, 0x95f94930dac6f790L, + 0x685ff94bbd3b9d82L, 0x5c8f98fc51cadf0fL, 0x9559c88ab13b7489L, + 0x31377c665f18fcc8L }, + { 0x35c5de097dcfb35fL, 0x2dccca9f01cc36f8L, 0x7e93e85d7576cb63L, + 0x0c2dd48af7b4b375L, 0x9d95cd4fb09a19b5L, 0x752ed15971bfe607L, + 0x439880cf2596dad2L, 0xe52efb5369e90a6fL, 0x4409766303d3e60aL, + 0xfcf364faa95070e0L, 0xd8f993b605624dd2L, 0xb35a982400d5e467L, + 0xe289d0240c8f4524L, 0xef45423c648a0179L, 0x3a5fd695587edabdL, + 0x3dacc50ca11e5271L }, + { 0xcb3e4f946499ae4cL, 0xa46dcbe17053c527L, 0x807f5ce9be782e8aL, + 0xb6c64d28d8481e45L, 0xf35e4518aa286fd0L, 0xf7b7b9badf1cdb49L, + 0xf3fb6210aec23eafL, 0x0a9ba385b9bfd2fbL, 0xe51a0d538807f3a0L, + 0x7ab24404b17b2842L, 0x6fd57687f9dd9f0aL, 0xcd1efdb4f3e9df64L, + 0x5dd2df7a60df194dL, 0xbed3f2c3e069df05L, 0x469b756123248a31L, + 0x866949e1694744f7L }, + { 0x3a9a0da53f4ab07aL, 0x2cd6f333f54a6fbfL, 0x0c92e921b23cf290L, + 0xc9581c3e848e3d58L, 0x93af1fbdd3b218abL, 0x38598ea1066cb4d7L, + 0x5001394e990c03a0L, 0x3b664b1e7d0877b5L, 0xd79db1bbd74c7091L, + 0x852d44354e2d5dd0L, 0x0d2b841b3329db82L, 0xfa844eb07b96d480L, + 0x37a50569c295dc46L, 0xc2d3837394f7ec4eL, 0xdc3884ff5b083177L, + 0x574352b88b1fa598L }, + { 0xed2193f70d5d7ce9L, 0x3c19fd260b487eafL, 0x7c44ab597be65fd0L, + 0xdd9da86078270d56L, 0x8a84ec00baa70198L, 0x2ec27e49285985dfL, + 0x996ccaf0de2028d8L, 0x4e7648c761c2201dL, 0xa96335bc091c19ebL, + 0x253a3a69f0d6782bL, 0x3f204340d2946493L, 0x444521a1099f6873L, + 0x5fcbcc096996011aL, 0x3884d5d8f853a94eL, 0x2418c624d3b6a3a1L, + 0x3e431af206ae3c4fL }, + { 0xf967d93983d381f1L, 0x36501aaed0c033c3L, 0xbf3af4d054410768L, + 0xa86d15985093a6d3L, 0x43ae0741d92f2900L, 0xfeb2afa636f0b755L, + 0xd090a6a3aa456d6fL, 0x336a4fdaaefdb646L, 0xfd1bfe441a942f7dL, + 0x7fc2a3ed851ee41eL, 0x4f1c968611e935c5L, 0xcd57766653bbb343L, + 0xf26931baad896c2aL, 0x8a0fbbd186bbfa41L, 0x1c3d7d82a203cef1L, + 0x6dad3f15e2664d35L }, + { 0xd1940b7d12ec35a1L, 0x6219c5b6e7dfb128L, 0x2cc278c6f13321d5L, + 0x5e76904a33c58eb6L, 0x15090f55d9903c43L, 0x061bc926c3d96a19L, + 0x974a9f038c0acba7L, 0x7a4140217198b21bL, 0xb069599df8958c6fL, + 0x517f2f1dbebd0129L, 0x1109a613df3a8dc3L, 0x08e58448672375c5L, + 0x56590ba49383d2d3L, 0xfc3ee7c60bff837cL, 0xc87a539027d2d55fL, + 0x2438e9d45f517a3fL }, + { 0xc4a453088815af3cL, 0xe55f1a32f3c9bed5L, 0xaef1cdc997b65ddfL, + 0x61c61d9412e51eb5L, 0xbd0dac54e63f2490L, 0x6f14429cd0b3e231L, + 0xf737c3c2f1da6010L, 0x7150e04b6bbc4fb1L, 0x205b4c891be281cbL, + 0xf1b4633cd7701f5bL, 0x8b33ef462a513490L, 0xddb47c7368f1f7f2L, + 0xf4ada511bd416b67L, 0x9d2a97cdff795bb3L, 0x00a8b7b296200e67L, + 0x13f39011afe30e01L }, + { 0x3dd296ef7bd0c827L, 0x506110f34a29ff46L, 0xf87930681c9a515aL, + 0xde8d8045268bca77L, 0xcbb83024998045dfL, 0x3f90d71068c0e584L, + 0x2a838ca8263b6062L, 0x293bb5e7535c5d0bL, 0xceea99d556415110L, + 0xfe311ad01bbda005L, 0x2497e0bfa4d8d018L, 0x33dd77a01cf2b866L, + 0xbc075b73d8c4ba8bL, 0x298466d4722b7bc9L, 0x17a7ce24cbda1b0bL, + 0x458d4b6b680703b6L }, + { 0x8a26a20e4d54d8b2L, 0x05a5696e4d320a0dL, 0x698b5858f994f700L, + 0x7a4adc3c2f6549a8L, 0x1812e8193694d00dL, 0x46b9b000730402bdL, + 0xe10a1449a1b36410L, 0xeae95ea599230220L, 0x3efc2e9b1b4820c3L, + 0xfe5b5cb585c9eb8aL, 0x21ae031997847064L, 0x68ef0b708f27d49fL, + 0x3259ef182f72556bL, 0x00ae0457624db01aL, 0x628e3b065668f95cL, + 0x5f13f5fab6fbbf91L }, + { 0x7c6ed9ae3a9b0dc6L, 0xaea1bde96f883ec8L, 0xea66bf88ea8b3677L, + 0xdefa6abc9a66e3abL, 0xc4d3317b68217ffdL, 0xf741c8f2290df05cL, + 0x1f0fdf177d11674eL, 0xfdf0ece7c35989caL, 0x0eed92df6b9c482dL, + 0x73713e6655bf1ca7L, 0x90acb29025cec99cL, 0x37c9e3a2e803e69cL, + 0x7c0a3c5317713a1aL, 0x350dc5656f5a174dL, 0x11625a4405f802f6L, + 0x2196495da37ba4a2L }, + { 0x00cb2fd313142680L, 0xab9e91d765d14cf4L, 0xc6a0ceabdfe2669eL, + 0xbeefce580ae22bc5L, 0x3c2b7986cb6ec250L, 0x84adb1a2d738f1ffL, + 0x9709bc28516ec8ecL, 0xf36931298e8f7db5L, 0xc48efc6b95b197f9L, + 0x9ff109529aaaa404L, 0x2c3c8cbd144154b0L, 0x33ef7bc3427f3435L, + 0x04a17940d21897c1L, 0x5aa0c47d6ce548a0L, 0x2971cea73d56fa62L, + 0x93ad0eb004475f08L }, + { 0x7a0b6967988a9963L, 0x61e477f76515e8ddL, 0x6274e3863b6b50f2L, + 0x63a9b8d5d33922deL, 0x3c38d3fb687a5b3dL, 0x18f6f09c1302e323L, + 0x254c05c3e02fcccfL, 0xc04ed0b726e662f7L, 0x1d5646b8143fe079L, + 0xef8a9448c9016c8cL, 0xe5674c4bf823d797L, 0x0586f72fbccde451L, + 0xc5fc88d54417eadeL, 0x2b952209576e588dL, 0x4408dd425844d1f9L, + 0x73f8c3f0ea41c034L }, + { 0x89534fc85df763ddL, 0x3b1427f33ac71836L, 0x0db5be176e8f15a0L, + 0x1d390944cb20888eL, 0x7804c9ad857caea6L, 0xaa584428519f7bf3L, + 0x626eecf1293aa8cfL, 0x749e0d98ea36a015L, 0xefff6dae3321edcdL, + 0x963deea628b791ccL, 0xa14e05522d16e361L, 0xa2e058fcb15ae206L, + 0x0f268745fca325e4L, 0x7cf9d40721341a8aL, 0xdfed25d97caa51b8L, + 0x0108ae39adbedd75L }, + { 0x54d178f3a9e88f63L, 0xaa05b11eab0c7325L, 0x773a53e6e261d8a6L, + 0x24db7dae8d0b91c8L, 0xde10b073e9bb004dL, 0xfc8befe754e3090bL, + 0x16af05990cc69c89L, 0xddc838039d59511aL, 0xc3f65b9946c5dafcL, + 0xfbbe4be81ee0a599L, 0x88891e36fb3a9b17L, 0x0c9aad75445dad00L, + 0xdffc46abd5097e1fL, 0x8848089bac85a4e1L, 0x348bb42fa0c45233L, + 0x807c06d8eb13c1dfL }, + { 0x00a969ec98ee0ef6L, 0xba9d54838bb7b7afL, 0x24484c92a02f8fdbL, + 0x7bdb201a8b70557cL, 0xe59343e460ad1af2L, 0x53a9a942998c95fbL, + 0x974db3deda861d3bL, 0xce1525c9ed399c0eL, 0x89b56881f72109bdL, + 0x08ff7d15998211a4L, 0x5df76b3aef0f275aL, 0x93f180f7fa2f358bL, + 0xaac4ffcfc39b0634L, 0x2692c62617583b53L, 0xb2fdfa36b55399fcL, + 0x16424c6c99607a61L }, + { 0x5dd65c55dd2744a9L, 0x2544c1c2fe3af418L, 0x32c82e99efe8b089L, + 0x30b7ab25a9df691aL, 0x983845509be99674L, 0xbcecd258caf2d122L, + 0x88ae4098bcc77272L, 0xd43961414b8efa0cL, 0x44ff67b9ed64d12cL, + 0xa9e655e42e7f3404L, 0x3d16fc4545b0e9ebL, 0x474a3e14f03ded28L, + 0xa3c9adffacccb85cL, 0x3dfe6bc17253a51bL, 0xdddaf4b9fb5831b1L, + 0x5544e602a4f4478aL }, + { 0x897c5313baa80b4fL, 0x0122716f63bdc8efL, 0xae2742db7b42c5a8L, + 0xe9d9e1e90883308cL, 0x352c8c3f2d341ab1L, 0x163d0500ed945870L, + 0x8349dd73c290d9d8L, 0x2053c5e01f6c7d29L, 0x83107446cb42033cL, + 0x76c88bd209d09af1L, 0xd0f70e6eb2794681L, 0x720b59de19b1b540L, + 0x80b7ecdc22994b43L, 0xc1a4cdce2dec53cfL, 0xdd7d3edd1ed60f42L, + 0x5735995ce241d261L }, + { 0xdc4ba3fba0237056L, 0x6856c16433ab3388L, 0xc01eebbd271ec612L, + 0xabdeb033e3031becL, 0x4eee44196118a1f5L, 0xec4974215b600f33L, + 0x1b7185cf08868773L, 0x7b0c46cd7c1b7dfdL, 0xd143b2da4a4c5e89L, + 0xdb9a5984bb1ff94dL, 0xac3904e4c9cf3465L, 0xf8729bc0eace64c9L, + 0x5cc22821768ad99aL, 0xbbd3b0818a9540c2L, 0xe468ed5f049a6917L, + 0x885486df3ec45ef0L }, + { 0x6a942c934bdff464L, 0x3db2719f25a7b451L, 0xccb0070b325be324L, + 0x2055a31b19fe3339L, 0xaca69ae8241ee8ffL, 0x7607dd0855ef8defL, + 0x9e24960f1a1b73c6L, 0xbcb0e8a271d36810L, 0x29e11aa26885e6b9L, + 0x98b5d0ab185eae19L, 0x1a0b96e40f81f91cL, 0x4d0e8bcf994fc503L, + 0x33d81697f119d6e0L, 0x29083287aaa4ce0cL, 0xc5dd4d3ec91ff9d7L, + 0x31cecfe8d4ab962dL }, + { 0x437bfd9afc8b21e8L, 0xe5dd32b3b19436dfL, 0xfe5902d4921c36a0L, + 0x8e9de84da3d0fa90L, 0x9663e6ad5bb523bdL, 0x9800a23faecd6975L, + 0x1009c0d9b4fbb59cL, 0x839aa7bdc9d20ff1L, 0xf502f66decd6fa3dL, + 0x480ed4fbc5516ca9L, 0x65ffa5f66c742ac4L, 0x2b7c7945ff3252f8L, + 0x72fefc0575d9cb3dL, 0x11b0863bd6d6f1d2L, 0x5d8f3cf09a6a4ec3L, + 0x6961b46ada2547b3L }, + { 0xd07b587ecb35e2acL, 0x1ed5546b57af14d9L, 0xeca17a5bdb28a04cL, + 0xa1f91d44709d54f0L, 0xa6e719fd9c6f400eL, 0x4e4b88edfb8ce190L, + 0xf9781edd246e3fd2L, 0xd67120e6b655af5dL, 0xda782d1d93413ca7L, + 0x697e20a29707fa21L, 0x1eb51f3254e84123L, 0x2e254d9e36051f9fL, + 0xddaec42b73ce5be9L, 0x89a9a32ecd3f794fL, 0x1964e22f0781aad9L, + 0x6a63a90c53755212L }, + { 0x76554e003d7acbbbL, 0x2c01668ab74f6108L, 0xe4a29672388c519bL, + 0x016677143eb94d4fL, 0x086a3cdf0cd6d2f6L, 0xf86580217b370f7fL, + 0x658880c15a4d3e7cL, 0xd6ed58165ba3f4a1L, 0xabcc78135ca471ddL, + 0x809bf074e844a576L, 0xa53a81b36ea502eaL, 0xc20b93070e021ed3L, + 0x8c27f8928617f165L, 0xa54764468235cd0bL, 0xffc89ffd82552961L, + 0x51ed4a22d151d90eL }, + { 0x37d6963a449701b4L, 0xea8d91a3bb27caf2L, 0x3ef9be15b572965fL, + 0x75a7a055db50bf7dL, 0xfd67480ece643b9bL, 0xf2a60d2d6ceb5d5eL, + 0x68fc320c5ed7c897L, 0x41c53cf628ce685fL, 0x0e29711f7106615eL, + 0x7a87213823500eccL, 0xaf0a92606c29fe48L, 0x93df3f2ae1ef9712L, + 0x0d5f6fb1d2d169bfL, 0xeb7afe2674a9793cL, 0x4173d94ae9f49256L, + 0x2d6951bc2b8b5ce5L }, + { 0xdd007d9f904e222eL, 0x333f248f86f4e109L, 0xd4994e8b8f429eeeL, + 0x29573415cfc77518L, 0x6e7fea3a0b0f42f1L, 0xc795cb7dc2743519L, + 0x820a8f66711e71a0L, 0x83d95d9c2b874f55L, 0xd4b64d78e70e1627L, + 0x924353f58b92a742L, 0x322048b1447b5e6dL, 0x0bad730cbcf931a0L, + 0x75c4d089a7af2268L, 0x464904c1b83b93f9L, 0xa24eba02165b3aeeL, + 0x65c48e78e08cc5f0L }, + { 0x1a1c73cede222c22L, 0x5683d8cdfcea23b4L, 0x0301cb14b2143b06L, + 0x284adf8f59fcec77L, 0xfb1c581c31204cefL, 0xf54d3eee94735107L, + 0xdbf67f0b4d3188c0L, 0x76a3f2d110f18d12L, 0x3809fa2807d3e013L, + 0xf06f0a4625e7ece0L, 0xd82867edb2895d2eL, 0xe106f48908b0553aL, + 0xe2280fa6ef245445L, 0x402d5785a8d9a3cbL, 0xf63dd9ffd438ba2dL, + 0x36b5cd2c7a6b226fL }, + { 0x87ff4e20545679a7L, 0x64d80b414520c750L, 0x90a357fa9b459cd8L, + 0xa19eaf39c85af1a3L, 0x0d475d798d935a5eL, 0x74501983781a678aL, + 0x748397790cc2e810L, 0xc6a21d112f412244L, 0x8d0e85f936a51a37L, + 0xff50151eeaa74df8L, 0x14e182a793cf99c4L, 0x45593df1376a9ab6L, + 0x18f73caf522389ffL, 0xd27cc960f7445e8aL, 0x0692f4c539a51dc8L, + 0x08d7c144db39bfd8L }, + { 0x809c0d963ecca773L, 0x87ea9192d48c2156L, 0xf0eccd74db6bd641L, + 0x773123742a678cdfL, 0x7a966d8bd1587b7eL, 0xf3c1a1016130a4c6L, + 0x7cc6e8385fce17bdL, 0x95e95bb8a8de7aa4L, 0x3fe1e8b5898308e3L, + 0x0197243ee347694aL, 0xf3fe9c42bb0cd2bfL, 0xb59052640f9b2b49L, + 0x4c385e8bc7367d1fL, 0x1d3050aeb5ee147bL, 0x8e2c387904004ad9L, + 0x5f2aa8eebab70202L }, + { 0xe208d4641266524bL, 0xb7bf3880d0a19f66L, 0xa5aa685eda106ebfL, + 0x0a69e8d3e642dd46L, 0xef349c61c682e4d6L, 0x26f6ee3b0fcb534cL, + 0x7daba12705eb67b8L, 0x2babb27e18be05f6L, 0x959afcba8e2d85d1L, + 0xedcf2d1ae2d9d386L, 0x59dc52e61ea6f06eL, 0xc28278b4866e5ae8L, + 0xd9ff034002bcd3c7L, 0xe884ac76784be82fL, 0xa316498083c9f224L, + 0x62501a98b46ff949L }, + { 0x563f7d9aad264086L, 0xca6a33dba5e0e4bdL, 0xe82530028c8d3d67L, + 0xa288dac846e64b19L, 0xfa3c919720aa4536L, 0x8130c9b0ed553eacL, + 0x622806e02ea8abd3L, 0x52fbf54dceccfe77L, 0xbd9a8e314f0d1b70L, + 0x519d2133d59b1741L, 0xfd74101c9a6fea8aL, 0xd1acf7a0b5c4eb10L, + 0x78499b7391f9da5eL, 0xabaa4c49c0dea586L, 0xcc9c5f73a1f3531aL, + 0x497b15fefd3fc665L }, + { 0x8a56cbaaf45568e9L, 0xf491a0fec7192a6fL, 0xdbb03dd39ab2539aL, + 0xc86522f84ac37da9L, 0x8c8cdba202a0f5b4L, 0x8109fc75a29c539fL, + 0x9cd06d31ca90f02eL, 0x8f31f0443e216dbfL, 0x99aa68acba3ebd91L, + 0x2a80d0d242c007f4L, 0xdd8dffbf86a9b7ceL, 0x405d3e84d6308edcL, + 0xdafa33fe068012caL, 0xc2eebd13edea1071L, 0xb7ae7e5c2ff637e6L, + 0x18d46a6c9e514cb7L }, + { 0x868cbb22a78b7802L, 0x0745ddb2497cbaf4L, 0xc4eb2f3e42ae8addL, + 0xac0abcdab4ceb4e4L, 0x2e0d8325a325fd40L, 0x6cfe057113ac7345L, + 0x7407a788b14171b9L, 0x70eb06036da7a52bL, 0xab0b36f9d85176acL, + 0x14109d297c2954f3L, 0x370de9c8dcd705adL, 0x3f0db5cd7bb5e751L, + 0x45f93d41a06e708cL, 0x10d54f8a7e93050dL, 0x69e6f8e45a38fef9L, + 0x55044601d3f62e40L }, + { 0xd1c5c91006cb9cc9L, 0x542074d741d00014L, 0x7cd8663e11236fb8L, + 0x39721ffe29ad5f82L, 0x1d21fbfa2951fc83L, 0x1cde06e7400d144fL, + 0x9042596b91792e6bL, 0x3365c8e529ad5166L, 0xe2220e859aeefe98L, + 0xbcb5318970c2aee3L, 0x477ca3db9ff100bcL, 0x27074176f532973fL, + 0xa12118ac9a2bd01bL, 0xf34252093dd79f93L, 0x563a8ff7c6f5d7dbL, + 0x0da313fcd7b0ec4fL }, + { 0x37125a8c15aa2557L, 0xca21d70c00893e9cL, 0x4871399467b8a823L, + 0x0d3e9a747cb0042aL, 0x2d2bf4ffc9e2ce18L, 0xd5531a0d049aeac2L, + 0x4d29a616f03d0660L, 0x473d50d61f1b7f00L, 0x3af0ecbbca3de50cL, + 0xe2959bea09c28f27L, 0x6d7c2ea0f8704664L, 0xadfae4e1731083efL, + 0x50940c26941c2554L, 0x44167410a1162d03L, 0x620230d81e82290eL, + 0x63630be8db414accL }, + { 0xbf8d52228a7d2e41L, 0x49e75823eb62f879L, 0x1b4d33dd6c402d89L, + 0x883e04d6de2c59adL, 0xbf3f38f449b9dc38L, 0x9d997d18b4b70c4cL, + 0x1f69b20c13cea045L, 0xca3d702558e2606dL, 0x3d4fd977261d1b79L, + 0x56aeafa85a1436faL, 0x369b3e98bb443c07L, 0xfce5186ce558f6beL, + 0xeb0cd478f8ac8f89L, 0x68074f37d5e5aa72L, 0x295845c068544eb0L, + 0x306a9871f16688edL }, + { 0xbc451e9d634ec136L, 0x1edf27ca0e6f658fL, 0xa9be0152c0db4120L, + 0x87b6ef20c5bfee67L, 0x352832389a2d6023L, 0x60e564d8c7afb899L, + 0x4af22bc00ac9c2deL, 0x28e6f63182a9d22bL, 0xc075c701f532701bL, + 0xf6d418f882075f91L, 0xf9fa628d1beaa511L, 0x551e7a176e72a13dL, + 0x9306215b77f4c01cL, 0x71aba73193c9d588L, 0x6443ebe058e57cd4L, + 0x2833ac41e8103e37L }, + { 0x7e564b868da5ec5cL, 0xac3d9da81c08db24L, 0x9d7c1f0b8c57a728L, + 0x3512afe79d343dc2L, 0xb438e4cffdc60339L, 0x7d5a2700dcfa1941L, + 0xd5f323f827320449L, 0x1b87a58e1393c6e6L, 0xecb68bd104baa431L, + 0xc09c1c5a4722b4d7L, 0xf42faa97206b5faaL, 0xe1dcbcd69976327eL, + 0x655ba9e4087787d9L, 0xbd59c757de5c0191L, 0x673020ed0bcf3538L, + 0x120cd454a49d6303L }, + { 0xebfdb8f4cab0f9eeL, 0xbc003ef02cce58eeL, 0x9b6a68415a8d0665L, + 0x642ed3a69b957774L, 0x3de487f04721ab5cL, 0xef2ff38021a4f0d3L, + 0xbd16f55829dbddcdL, 0x2ef05b4b0e93dff2L, 0xde1faa120bc9aec1L, + 0x66dae2c2d467fa92L, 0x758daf645eb33e34L, 0xa67ad9f68f0103cbL, + 0x151f693a9be02430L, 0xd5698496eb4054bcL, 0x8ef1677e7019336eL, + 0x021cfd167fdeea3eL }, + { 0x5c73715fdf5c36f3L, 0x703bde37d64ad254L, 0x55368d10f2cf7713L, + 0x1e5ec7b70f3993c8L, 0xfdb16776304ae4caL, 0x0d8f717e3d3bb18bL, + 0x5267073f66343d5aL, 0xfaeb52ef156008b5L, 0xb97ad5f9224a470fL, + 0xaf86e391ed2ab51aL, 0xdc0c7e579974302cL, 0xc88fa817fd0ae28aL, + 0x807c22dfbf8ed59cL, 0x5dedc231eb128bb6L, 0x71edcd9ca20595a3L, + 0x07265b46c73cf78eL }, + { 0x73dd99f0bd66232fL, 0xc59aaf89c4027716L, 0xaf826dfa5b860fc4L, + 0x239ea8aa7a943f3bL, 0x0e0e1b1a523c428dL, 0x55ea0e3a6973b95aL, + 0xea399caa2557753bL, 0xf8adf72f06957b1fL, 0x0389f3413bd34302L, + 0x333f27d0f8a43a97L, 0xcd9c0c08adaf796fL, 0x6dcca49b49c12aa2L, + 0xdd88deee7a0ac6e9L, 0x8f47575d0644080eL, 0x6e9d667d0cc2f4bdL, + 0x36c5754b31d1496cL }, + { 0x9120046ef323d84bL, 0xa69911227e789c4fL, 0x4b0eaf4e921b8055L, + 0x6339844a8079974eL, 0xc905466a740f8c79L, 0x1c18d0f7cd6def49L, + 0x5297da6b4b23e4baL, 0x1c09dff3c41800c5L, 0x6c49075b37ef6777L, + 0xa94c3a4050513dedL, 0x3d6742e96b0b1705L, 0xc0784494c48af5aeL, + 0x40c01532c95822deL, 0xa2ddade5c164d94fL, 0xfc8a8ac9a2975eb5L, + 0x06fbf8611946944eL }, + { 0x2d65338e3f45aa97L, 0xd83b58c81d040febL, 0x05fef59b0fdef8b9L, + 0x7beb071ae4d7417cL, 0x982b61f5b30a1a23L, 0x4c5f2a2afb65bd03L, + 0xe40abc9d5cbf6bf3L, 0x422c326df06612a5L, 0xc921e69d9571ae28L, + 0x7c88b10b23d3434eL, 0x96d2e9579da07933L, 0x833d46a13619cf4dL, + 0xd9d19653d95eefa1L, 0x2a7d8411a03e8f0eL, 0x5e64295304bb5ab1L, + 0x5e9ca0fd1f0fa9eaL }, + { 0x5bd54571197c5dc4L, 0xe2da40bfe78a95a2L, 0x65fb9efcffdb0eb2L, + 0xe952dc2c0d17467cL, 0xc1fc9c7bc758c6a3L, 0xfc79562cd4034a9aL, + 0x26e36fbe61f64b56L, 0x6adc4b9e1e84728bL, 0x7f165fd3a8f9ac8aL, + 0x7bc93a4503e3e013L, 0xeacc5513656478e3L, 0xd3391717064ddc77L, + 0x75b318dc76936914L, 0x69b1f1c7362424a6L, 0x8cc2045b49955f34L, + 0x940622b3c6836af8L }, + { 0x4710ccb70d997973L, 0x3b29625dd3f8f115L, 0x8cf0c4d55b97abd5L, + 0xc6321e0a673e14a5L, 0x0541af9d3d262246L, 0xde6d87546fc83b11L, + 0x47e97da8f01652a4L, 0x0f82b3a6ad9802b6L, 0x69aa4075ae9c44b2L, + 0xaf3f5de2ced2bf77L, 0x1ef1ea8a497a40daL, 0x2e0f86083c23ba9cL, + 0xd8a998a4f190a2c8L, 0xe2b49c8ccfde3368L, 0xb9f49824bde6bd71L, + 0x80bb1664785bedb6L }, + { 0x05e575fefd145cb5L, 0x155ee561ac5e6883L, 0x461e70cf8793b273L, + 0x9f1553de133b2338L, 0x2fb9e0c3a2a7ba07L, 0xc3bfd6a83e7086faL, + 0xb6ba85008bb4cb93L, 0x0b66d78976f82dbdL, 0x7d5a6ff654eb49ffL, + 0xcd65d2371f20b322L, 0x79ea49c254e29cdcL, 0x64975963cb118ff9L, + 0x969598ddcc58000bL, 0x95107918110c779cL, 0xedfc154863b85a35L, + 0x077ba5ea41212350L }, + { 0x0b3a38d3cdd86f61L, 0x431214450502a0abL, 0x1912edc5806d0272L, + 0x01dc1f988a32f10fL, 0xbb1d31d10e80c760L, 0xd46ec7e5f464e8b3L, + 0xd569af369abf49eeL, 0x9d286ea72cdade77L, 0x2be7020d45ad5920L, + 0xabe5236e6299ae7fL, 0xc93179bdd3f55c07L, 0x8138995a52350e80L, + 0x0901265caff07586L, 0x5b3c81b2f4739653L, 0xbaf7581d9bc77d21L, + 0x6b2006df4591a2e2L }, + { 0xb2fe50a8965b1bc1L, 0x931f536a962bb4fdL, 0xd5718d33000e7f99L, + 0x84728f2553d5125eL, 0x4f8a6184d2125cafL, 0x54f1a701357f679eL, + 0x70a9f40c1531c05aL, 0x10d0cb976fa8b775L, 0xb476f41e9dc12ce9L, + 0x5c8d7a752755f894L, 0xd6c12e10625741a4L, 0x262a6fb8c917b16cL, + 0x24d116e638d6b0a0L, 0x849540c032c38e83L, 0x855b911c66868afcL, + 0x53217ea6bd26b550L }, + { 0xfc840473259f52b4L, 0x968da9cbe621146cL, 0x964eb85ecacbd26eL, + 0xab7daa2de4a54344L, 0x6dc3b848381a4ff7L, 0xa07a96b341c815efL, + 0xc4fae9e8c3d4b1e1L, 0x0f938d1e42ce9ea8L, 0xa727dacc35cc052fL, + 0xc81e01c9e9a06f07L, 0xa9e08dcb4a6d65a1L, 0xf8e2d1736044a9a6L, + 0x99893dd0f2bd295bL, 0xa08d3379f9781b12L, 0x64bd600161830ac2L, + 0x0386931ed9adbeefL }, + { 0xd0d7abb3d09885a5L, 0xed9d2b67e355bb07L, 0x3bc238cf536ebaedL, + 0x61ca2e78699ce4d6L, 0x354ff447111594cdL, 0x55cbe70903316ad2L, + 0x418679fd49fff5c4L, 0x75bacd750f9c6c40L, 0x677edc882972721aL, + 0x82596887e5ef502fL, 0x459e9367bf320e0eL, 0x81ce36ef8bbdccb2L, + 0x1ba097fcb766863dL, 0xcd3a21d6d58c6db8L, 0x0e4967cdb4a8748bL, + 0x2caaf74915041c20L }, + { 0x44f980066ed20424L, 0xb3e4ea2322471545L, 0x268ed1a5781a8c86L, + 0x48d0ab757ae5b70bL, 0x6ca8b320356d3982L, 0x9ce8e6812df31fa4L, + 0xb909d232d925dcf2L, 0x302c8f78f56723deL, 0x11725d69abac96f9L, + 0x656a47ca57d1a170L, 0x6bb5d511c18a2be7L, 0xb56e45f1ad50d9d9L, + 0x36e886e270b05518L, 0xc7c71f3d09d8ff91L, 0x65a1bbe29350361eL, + 0x86d7f53245fe3bd8L }, + { 0x99f16eb6b0bf719aL, 0xb69750988bc3d913L, 0xfae50e5226cd01b4L, + 0xd3e3ac5490898d1cL, 0x4da3b9db887ec666L, 0x58300644fbea45b8L, + 0x369f3bd98355b058L, 0x0fb239a8579bcc13L, 0x4f5b45396e2bd811L, + 0x007f3baf24198fd2L, 0x68a676db8837d51dL, 0x68eeea62eae75b16L, + 0x5ffe5f943db6083cL, 0x52c94d0f7d836c5aL, 0x5a4c3c6fcbc1ff85L, + 0x682a55e386c0b4ddL }, + { 0xc8f235a4587495aaL, 0x2276026c34c7245dL, 0xd6ae0cc5b75a46e3L, + 0x890d3965ecc3e5e7L, 0x1b13342f14296629L, 0xc89927e68a877227L, + 0x1543f27e2324a68bL, 0x6c44768449cdc21aL, 0x9bc7fd4f1452d0acL, + 0x2cc30a31ff4b045cL, 0x415d46a0852f7611L, 0xad737052c6fdd7a6L, + 0xdcecc3ab7b4c7c91L, 0xd2cdf01b7688d70cL, 0x054f2542e40d3905L, + 0x02227fa6fefe4dcdL }, + { 0x1805efd9b751948bL, 0x8efeed46fdfd225dL, 0xcb128e094f2c8b22L, + 0x9d1090bf96f7c5e5L, 0x0959d044b4cbeca0L, 0x21c955f98e08cb04L, + 0xbc1f279d68fa4fceL, 0xb021e14e0710ae9aL, 0x64d16e9f881167f4L, + 0xf5a5c22ebbc9f1a5L, 0x5f3716dfe3420eeaL, 0x971eb915d5c4e843L, + 0x64fc55fc28ffba81L, 0x3427e54d7dd37578L, 0x446e6a6215ebc7d0L, + 0x547e249a29269778L }, + { 0x4706868aa1ffda27L, 0xb4e6cdcc7955cf50L, 0xf65151e10a63f3d8L, + 0x5b4127ea9de5e70aL, 0x3d2c09baf9342823L, 0x18c99d83aa2f7d51L, + 0xa0c5bb1dddeec025L, 0x7ffddf8403dcf1ceL, 0xe57e4d29616fdedaL, + 0xd24565697932a1f0L, 0x7475e0e83191d4e3L, 0x3479bea1c220218bL, + 0xfceb5c908bcb2505L, 0x1c685cea3c6132e6L, 0xc42dc745bfe6c1ebL, + 0x45a41cc0d2b08eeaL }, + { 0x3ea9b2c74dbbf0e1L, 0x41ff962fa17cf70eL, 0xdc1ea7585eeb4c66L, + 0x4f5412d2a9beb17eL, 0x2c9e4f52a285741aL, 0x93df7da4984fd11fL, + 0xb2afbddc0df3184eL, 0x96323d252421e375L, 0xc87be1e449df781eL, + 0x145601ed3d589beaL, 0x0f0bd9bd28fff6ddL, 0x2d3259d48a0f298cL, + 0x362d7a77d88e6944L, 0xa84c06b6b6ac2af6L, 0xba850ac9d087da02L, + 0x128763c942ee40c8L }, + { 0x29a80f07acbac178L, 0x7cc2004434b08f6eL, 0xe9631d1470feded2L, + 0xb2115da386615767L, 0x7c75f5c4cb088548L, 0x5b29d2139a2e8e03L, + 0xfe9fda668b881752L, 0x3f1d8d88c1de7ebcL, 0xb476565e03218123L, + 0x07365561b1c995f3L, 0x2160cb18b13eb71bL, 0x7e8da51399b3a0ebL, + 0x5e8ca1f9b20fcd74L, 0x6a7e0067b4126d72L, 0x1e8204b768bb637fL, + 0x75e96bccfc4f74d2L }, + { 0x189d1fdc0d19716eL, 0xdf5850587c384525L, 0x64a846d1ea987d2aL, + 0x12b6bf836c07150fL, 0x91d85d464d6fd5b7L, 0xa97888364f53f55fL, + 0x60083bd881509129L, 0xa7672683ea876f48L, 0xe80b2e7ac15b2489L, + 0x985ef8d242d1d992L, 0x9c57b029cf3de492L, 0xfe02f83cb1487627L, + 0xaeba4fe48ae5b687L, 0x8a86f09b5d6b8196L, 0xd88f566ba16e523dL, + 0x309a6e9aba268949L }, + { 0xef27ee50bdfbe97aL, 0x1a5fe70fb8c50c4dL, 0xcc7beb017fe09f5cL, + 0x8fa15a85bed36cc5L, 0xc0c3acdb7550ed3aL, 0xc581ef87eb908681L, + 0xa15b3362c49d5ccbL, 0x0fbb17141fa264e8L, 0x267f8d8f8e1eee88L, + 0xd31ccfd621c2b63dL, 0x924dbe7d53be7efdL, 0xd42e877fdb2a358aL, + 0xcf9673c775d68ac1L, 0xe35978fd714fea55L, 0xeeb366535769b202L, + 0x0458258ad7593789L }, + { 0x5df71a74a042dbdfL, 0x2d4058575779dfa2L, 0x0e66cba70d2e6657L, + 0x285d6745ca2e892eL, 0xf56a8def0f0e6b5fL, 0xe0ee851da30767c3L, + 0x98c0565843346b9cL, 0xb35fce26d6b3c742L, 0xc0895bff39777e00L, + 0x83c8f6a6e7b6d886L, 0xbee148434f02904bL, 0x7f74915b2e84ec34L, + 0xbaaf663c96d10991L, 0x004b8757e41facc0L, 0xa2b880e56f86c029L, + 0x53f4a3e095b77358L }, + { 0x11bb08ce89fc48e7L, 0xba60c577afab5aebL, 0xf06bcbf8a0c1cb5aL, + 0x7d2efaea79757cb6L, 0xe26d90b176319160L, 0x42aa1ab62b77b7a9L, + 0x38eec0cd285df2bfL, 0xd35947f5f3a8f7f0L, 0x97c8dc0efc1cb5b5L, + 0xfeb8cca0c45845cfL, 0x16e8d989249e26f2L, 0x7c264e6d483ed89aL, + 0x13a3f14551d91073L, 0x8501562e305e99f0L, 0xaaf98d746908d563L, + 0x0a99e653d723d236L }, + { 0x23536f46abbc0559L, 0xc163067b9aa1a160L, 0x229fd2290c1681b5L, + 0x61254be11378e907L, 0xc60ff57aab793a2dL, 0xa6f2df8b466552dbL, + 0x9ad318938c170a36L, 0xc5cd9abe29b74d9aL, 0xcf747273f7848523L, + 0xc126a93a0d0e3063L, 0xfe2021e34248e3d8L, 0xd97343ee8323ddfaL, + 0x9f768775332639e7L, 0x9650fc3175325548L, 0xb595dbd13eebf7eaL, + 0x3a95cb45010fcbc0L }, + { 0x954e68cb39d7ff2eL, 0x8dd1cb4bc1d5c48fL, 0x02a92c777169438aL, + 0x7965c0b091cad8ceL, 0x0c5798ab32cd08d2L, 0x1a5bc3c3a6902bdaL, + 0x545d09255186d218L, 0xf0077cdbd27e64dbL, 0x0157caa48cd092daL, + 0x2a2fa3a024532ab3L, 0xa5fb639b41ccaba3L, 0x01702dc14744aee6L, + 0x485bb436cdba93daL, 0x93597f66329784f1L, 0x5d713c1ddad672c3L, + 0x366d222e030b7245L }, + { 0xd50b4875573ea5b2L, 0x0fce401ba90da44dL, 0x7b53fa657a1a0310L, + 0x722a80a5cf114460L, 0x0b8ebf05a538bf49L, 0xae141147d32acd21L, + 0x6692712c7b5ad07dL, 0x6dc5fee73f48ca07L, 0x98ed14992b8a78d8L, + 0x4e8b3145dd2f1759L, 0x43408de15f971b8eL, 0x055ea6ddadf1b368L, + 0x4bb76e73e5932b7eL, 0x44287153d30893fdL, 0x173dccd20661bfdaL, + 0x9072ba9979defd25L }, + { 0x474de4dd9620ea39L, 0xfbf1649fc831cee8L, 0x0b0e8bb1cd3a9c43L, + 0x6a38286f3f3df1d5L, 0x4ed072b38f0ec9b3L, 0xa6e4c987729c09e3L, + 0xea3e8ac68ad12242L, 0x6ae0e22bfbdfa5baL, 0x56171ecfb0a0f592L, + 0x33b2886d6b871f8dL, 0x6b19bea935e11bdaL, 0x4d815a407f0f153fL, + 0x7e608d977d6c02eeL, 0x7e8f23d9b6a88f46L, 0x26ac9652439d1654L, + 0x8d92c6bd35546c29L }, + { 0xb3e0d7ceabeb0ff7L, 0xfbe352543e0e42f8L, 0x57d1b226de808499L, + 0x9ece2e1f1cd44bc3L, 0x1245adbc435cfee1L, 0x874ee840f93f581cL, + 0x916a779cbda0b947L, 0xabcc815afa57ae0aL, 0x97adec2df0a621b0L, + 0xbe6a502b81f90bdcL, 0x54bf9de153bde63dL, 0xa88fdabf78884c25L, + 0x30aa52b1cbbb5470L, 0xf805396c29053ef5L, 0x8d43d8988dd827eaL, + 0x4e4bec175c1ae5c0L }, + { 0xbf8483a2fcc09676L, 0x457c4a3f19ea9a94L, 0xa6852ef3d702a5ddL, + 0xe7915fd2843fe7d8L, 0x644bba9816e35158L, 0x8d1b95d09ed746f0L, + 0x47704581b90af0b5L, 0x0bd4bc6bd4fd135eL, 0xa6dce067b4e833a5L, + 0x2c0e8f30ff56a9a1L, 0xa9c80800ec2c63feL, 0x449c20a598f508a8L, + 0x02b94cb33292813aL, 0x647e3d28ec7e81a2L, 0x72e67d1ab4877677L, + 0x7a4aa3f56f9ded24L }, + { 0x559ef1bae27a0045L, 0xdc812d4fb242cb50L, 0x23a478e439cf8d24L, + 0x97544fc59b3f9c54L, 0x5ac68132affa1fcfL, 0x74f8fee034a2c83bL, + 0x96cc640fcd3f4bb7L, 0x775dce9db0512ea6L, 0x67dca19dcdce381eL, + 0xc1eeb3f3a9d3fe55L, 0x38e0bf421a19274fL, 0x15992fb428d69b12L, + 0x48fcebde9fd09df8L, 0xdc9dfa4fb41ab5dfL, 0x0cbd7dc8c0a269c5L, + 0x60282a7bf7f0ade1L }, + { 0x7c07e538dceea2e7L, 0x38a322c83c42061dL, 0x676828f94f1f6516L, + 0xf21b69fbc7776a10L, 0xc63a3417b5e6b405L, 0x4c99f25891a7b642L, + 0x38692ca82cad1440L, 0xf1e82ffe00869bcdL, 0xc30b714e16fe466aL, + 0x5fb742f919019138L, 0xe90166d00fa516aeL, 0x5550f7acd8c73a43L, + 0x2d6a407dfbc5c372L, 0xe47a753968cc39edL, 0x3fd286d94a5fbe70L, + 0x5f4ae9c723c6b942L }, + { 0xd96a2dda53f4d561L, 0x286d45d016da1992L, 0x449a01fbfdd4b051L, + 0x25488a0d9f2195eaL, 0xc4151b0aa37661b3L, 0xb98c471ef9e5ee02L, + 0xa4bca86ea8658817L, 0xbbcadb877a68fc0aL, 0x88b346496b7366a9L, + 0x32ee98d415661c2dL, 0xf5b3b4c6c901420cL, 0xa23527352f2752afL, + 0x2f64ce73510e4d9cL, 0x939a7f26aca4aa80L, 0x9cd3e291401aa503L, + 0x92a01423dc46afd2L }, + { 0xe9f24be11c2f7dbdL, 0xda8c900fb7d527faL, 0x963e25bb8648f128L, + 0x9ab713e248141941L, 0xe87f7d017a6756fbL, 0x274dd85e058d90bdL, + 0x823fee7a82566abdL, 0x9f6230d774240195L, 0x04579f2cacb5e46eL, + 0x2a22626316a4c87eL, 0x9ca19a43d99b0857L, 0x86dc2ba3e488789eL, + 0xf960b5b99406c3bdL, 0x6f2c428b8960957eL, 0x90748706161c515bL, + 0x0fc8fe1eaa88cb9bL }, + { 0x68ae1bedfeb90f2dL, 0xf393bb3ca48b1559L, 0x2be62f9cf64e9635L, + 0x354c2410f8be75c2L, 0xbd7ea7035e6f7529L, 0xc264868e162cab31L, + 0xb1391e70c860f3ffL, 0xdf367c751d89837eL, 0xe150b6b42bf32941L, + 0x95e8f46e78c1318fL, 0x2b3f1daba2c4b160L, 0xc6ccf5ce701afbf3L, + 0x3ad275305e8874c5L, 0x39285e515dc6dcbeL, 0x3c954d86d99892ddL, + 0x2d0ba862dfd3789fL }, + { 0xeacd8ee8b472e1afL, 0xeb354eaeb76abbccL, 0x9b520bf8d0d93fbdL, + 0xfccd60d7fe6fc706L, 0xa9353ddea4ee2f39L, 0x5eb0925e9a81e51eL, + 0xee334da1d1366777L, 0xc1d28c9fd5354d69L, 0xb977175592a5ed54L, + 0x5d3e367fb7f70d81L, 0x7be7eecaa933ae7aL, 0x264cf1f9e23cfbb7L, + 0x0d129f4a89497681L, 0x705375a409b6235bL, 0xccf64c7548a376daL, + 0x963c87124d41dbfcL }, + { 0xbae290cbde36a814L, 0x9bdb0195733b12b5L, 0x0ebad867f77fe0e1L, + 0x0a7d19fd29720ceaL, 0x434d76519029ec72L, 0x856aff17bb51911eL, + 0xd0a25d9ad80a7f60L, 0xffca86aff848c106L, 0x53e8bdf943ad749cL, + 0xfb9e0284e3e696bbL, 0x3eb6630aeeee4215L, 0x9d8fbb9e2ecf3c63L, + 0x71da4ffa4e00c0c0L, 0xb296be595d57beacL, 0x1751fbada8cec7efL, + 0x2d03eb3cff55d7bdL }, + { 0xeb16925f04f2ec1dL, 0xa878f2760d147ee2L, 0x442df604aad9d9e0L, + 0x891df44b3f71035bL, 0xc28272b38cb95d5bL, 0x6f14efb55ee8ed23L, + 0xf3c4460f13b0f3e3L, 0x889f9bd76bd7335eL, 0x889ee771f755ba6eL, + 0x626984feed219b6cL, 0x2d44c737ec2ee411L, 0xb94385a263efcd37L, + 0xd909321b6637826bL, 0xc24f8a793ee6b7a7L, 0xa3ca8d24a7cf61b7L, + 0x842e40c1c54bacd9L }, + { 0x5a268ed6a661d843L, 0x02328cca4f5b30cdL, 0x16e6fed11311e177L, + 0x690decb4c6695967L, 0xbdac5bf657b2e280L, 0x827f82ca1efe42d0L, + 0xc554ec0aca5fca2fL, 0xac5276c1dde45506L, 0xb7f4cb08e3077513L, + 0x8caf6d9acc8797ccL, 0xd59648140d9332d2L, 0xcc6ae297285a409fL, + 0x7773c2a56223d093L, 0x2d5266ac5128fc09L, 0xa596b7cbbc31fe6cL, + 0x0e63319acac91328L }, + { 0xb5cd2fadf0360ac2L, 0x86b660de285e605aL, 0x82c6cf10e25b9b14L, + 0x9d5fa38daa9ac554L, 0x3dfcf1b8526c070eL, 0x0379a96b3fccc52dL, + 0xe3659c290bfcc7f5L, 0x5b1a3db569d3e6a1L, 0xb41528b59b7b42d5L, + 0x934defa49c22a006L, 0x90f380189b4ce3b6L, 0xb073bc04b3abaf32L, + 0x27a5a222ff8389e2L, 0x0b7a9d51ffa5a35bL, 0x4939ecef28e1a7c2L, + 0x88839da21872705aL }, + { 0x56b66c30701ce29aL, 0x3acaf12658981d50L, 0xd4dafc0c105f9f21L, + 0xfee571e6373e3d13L, 0xe7269c86fa2ee3caL, 0xf5cca64add20385aL, + 0x217f27573000e9acL, 0xc934db470e7273efL, 0x4294f4f7355b6776L, + 0x1faa36b96fc05180L, 0x8f88b1dbb052190bL, 0x35791b90e9eaef52L, + 0xf37fb2ebdb681b90L, 0x39d0a51d4415c369L, 0xfc59cca71d2e21c9L, + 0x64128cfea1f50c26L }, + { 0xf03678a2e8f5b0b5L, 0x5c7e249cd340f059L, 0x4144044193ca7cecL, + 0x075ca346bc83af98L, 0xf39f0033faa8bbb0L, 0x3d18f0edf38230f7L, + 0x78dff00cd448f345L, 0x849228c0d51aa475L, 0xdd4e270830c928d1L, + 0xc66ba6868f12cfd3L, 0x091049db88b3a206L, 0xd865d059016dae01L, + 0x4599e905e253e37dL, 0x322cf0c27ce9871bL, 0x014f54da174a132eL, + 0x93634a09bdabcbdaL }, + { 0x62826b27a9a2e304L, 0xc57e1866c1a4c124L, 0x913ab83222381710L, + 0x7e9b6b85a9847cfeL, 0x29655cf12b5f46fdL, 0x7295572b8038e66dL, + 0xe4cba6016fa95eabL, 0xbbc11071b9deda81L, 0x97f0009a3f1cf61eL, + 0x5372777b373e0cfbL, 0x302f909cd139d63bL, 0x1ed672da4f87d78eL, + 0x362077a3b4048763L, 0xc408c32d9dcc22b2L, 0x4b4c5bf226deeee7L, + 0x266cb467bc06357eL }, + { 0x6faa4154b56363e8L, 0x4b4fd0783c1aa4dbL, 0x14358dde2b9e6597L, + 0x5b34ae3efa004b84L, 0xcf44b2ecf19911a6L, 0x55caa833a536bf78L, + 0x606e1eb98870dc95L, 0xe3c3287d09f3511dL, 0x68b2f4eb9d5cf364L, + 0xc154e89263ab8c9eL, 0x1548828ec36ab611L, 0x0932bfcba1b7d120L, + 0x7ee7b5bc5315b8d7L, 0x782fd0d1f7473ac1L, 0xbcb029a83c8f2af3L, + 0x4b1d5a1b52454ee1L }, + { 0x12fe517463d52c0cL, 0x3735525e188c099dL, 0x5c621563360e3956L, + 0x88b3f1caacfa5a43L, 0x90123a0a797e8107L, 0xba31f6b5b15e080aL, + 0xd7de5e12fca3dadaL, 0x3287361b0df511c8L, 0x7cc800d465757d4eL, + 0x10810f3d5207ec91L, 0x0d4e56f130eea0e3L, 0xbbf7ee133ea5a2ecL, + 0x6fc07762be6abbd0L, 0xc831fdce120bf619L, 0xe07439fab622d42aL, + 0x8186b93f508e4b27L }, + { 0xc619d15409312867L, 0x7e042c05bfaf7db4L, 0xc1cf16681f5f5ddaL, + 0x50aa5057a4fc3d82L, 0xed30ed65ce68b8feL, 0xecb01c0bbeb4d644L, + 0x7b5dc444831c0497L, 0x351e6a009b7d9b1cL, 0x4bb863b9d9477c91L, + 0xaba6589105d4110aL, 0x30086cf443580b7aL, 0xb139c07690be357eL, + 0x12bfff1a27b5214eL, 0x79cfc6d722c3ab57L, 0x4743de57f34a9bfaL, + 0x0bf97e97c9ee2b2aL }, + { 0x96ec4ec8dda19e96L, 0x54ce18ea6c306e8bL, 0x7e83612b65f6918aL, + 0x1ac6f68b0d9a0d99L, 0x98a697a462fdcc09L, 0x65ce25f195bc3e13L, + 0x1896ecdab3939730L, 0x9eb81a0f32f12806L, 0xd3d7416e1d2dc7dfL, + 0xe22c7976ad473599L, 0x3de37a9a9f5ef439L, 0x6b7ac0ab9e69d94eL, + 0xe6bfa9e00a9d0bc8L, 0x576a870d5676f120L, 0x3bd91bb4feaac23fL, + 0x8fe5482c3e40aabbL }, + { 0x85ae67c2ce9a4d1eL, 0x4c3eb8034f1d2038L, 0x5c6c8f3a25d06192L, + 0x803de0ad308fb41cL, 0x9961f5bce71c294eL, 0xdc62078df02eb0daL, + 0xc87ef515b64ae8b6L, 0x69679f1e50b4d18fL, 0xc5c009a152199f43L, + 0xa7d484be0f640a5fL, 0x4c918bb123dab566L, 0xa67c114c64275d2cL, + 0x95a913b9cad2ded6L, 0x189ed18b6b4b5c8dL, 0x4aeb6206b42d3bf6L, + 0x3928c669bbc8bc3fL }, + { 0xde4bea4adacb4b64L, 0x03f62a44f26179a1L, 0xf3aac94e7a9112a4L, + 0x90448fbdd36f331eL, 0x426042bc407b85c4L, 0x5ad8a5962121b77bL, + 0x31674a4f67cee984L, 0x7fae8bbe4e3b2f0dL, 0x681df6dda7c930ebL, + 0xadeefa98c259d0d4L, 0x1b14d9e6bea1c1fdL, 0x3baadc8b21d405d1L, + 0xf01dff9373892754L, 0x81c35b3ef071cde4L, 0x1704d2e19150d0d9L, + 0x6ccc888f355134f6L }, + { 0xf8d36f0e7ad7504cL, 0xbca3265ff7959dddL, 0x0dcd1edefede67aaL, + 0x1276f4cebaebf32fL, 0x6825a6e6014edcfcL, 0x0b8c1a8299ad8eb7L, + 0x312024a909b8ce1eL, 0xcb8fd98b9cbd351aL, 0xa4841378fab1e8beL, + 0x17ed0f5d3973cacfL, 0xa17e1484259d5254L, 0x53d5b84374b91393L, + 0x8f792b211aca3ce9L, 0x035ff110c8c0f815L, 0x6afa6357ad4ed7bdL, + 0x2f151980b26faef9L }, + { 0x0c8631da29d2d439L, 0x121fbbc2bc039955L, 0x3e5a97926c05b75bL, + 0x6d6cf4c0b6ce47ecL, 0xbaaa17679d88c658L, 0x031db9e7f3355a17L, + 0x8381e3d80aef5a85L, 0xc71db29015a31bdfL, 0x638f6b749498fd7dL, + 0x44edf3f913beeef6L, 0xe6173271f4ab67b3L, 0x3a202c70fd22df11L, + 0xf7be0389205c4e92L, 0x1c219085a8eb9920L, 0x6c805ce8beb54aaaL, + 0x354b05b70ac58d65L }, + { 0x7171e2367a9170e9L, 0x01eec42d4cad50cdL, 0xffbe824f3cddccfbL, + 0xa73e8ce3a66cae1aL, 0xb7138a7f965c7d01L, 0x00058e3f5c3d971eL, + 0x52591ac32ff0a72bL, 0xa32fb5bcbbbce76fL, 0xf3241ab8a9f81a18L, + 0xf31d3332eca68630L, 0x847af9fc4482f13bL, 0x6196e217a4681be2L, + 0x9938f932e55efcf9L, 0x3e7dacb870acc705L, 0xd41be893cf09fac2L, + 0x48dc55c4ae3523a1L }, + { 0x8e623826a5092193L, 0xe46ec3626898970cL, 0x2f1356af25c9eb41L, + 0x4178064083c7d245L, 0x982def6797d00e38L, 0x382eb6e7a512151cL, + 0x154e10778af58869L, 0x187070758a51cf02L, 0xcdeba9f771313c58L, + 0x5d67b973ba155904L, 0x851c9f4b1d0d7b3aL, 0x19f29d718b8af2cdL, + 0xcb94ccff986b8d62L, 0x8725e24bb93b9c33L, 0x405ce4c566e38c68L, + 0x5f6a8edd0b6dc021L }, + { 0x83704ca58f9a8690L, 0x3f3697662f76a407L, 0xfbc12d8c69201028L, + 0x4cd58f16bce3a4cfL, 0x7804664a04aab26dL, 0x005cfbba4ea457a8L, + 0x537951b3b8a59794L, 0x4ca2b9e44fe1f739L, 0xe4428acddf325797L, + 0x648da3420ea243dbL, 0xcce6562bf43ce01eL, 0x840f0421f27db490L, + 0x156ccb708bfb7cf0L, 0x9b33480d5a8797d3L, 0x2e12e07a9eb814bbL, + 0x1ca65072ca7f87acL }, + { 0xfbb321cf2b9d25a0L, 0x66affdca40a746dbL, 0xc1c1530e59e368b5L, + 0x56ed1ea47d80068fL, 0x9b74d8fe5647dd68L, 0x1d96b50789b78da8L, + 0x39b752438bbe3391L, 0xef8d443e0d858c5fL, 0x4dd2db499646aa34L, + 0x7fad3bd1e667543cL, 0xd0d710c068980985L, 0x9f7aff3249facabaL, + 0x055dec1c14f9a192L, 0xaca663991fb307a1L, 0xac44fd9135ffff64L, + 0x462cafb6cbad3ceeL }, + { 0x1660a647de3237ddL, 0x95f735cc82b87404L, 0xf7879f59ddfa55f8L, + 0x15ef043e726b914aL, 0x1875393d1c93e298L, 0xa1a2be746ef18331L, + 0x4e7e8dfc25a9a12bL, 0xdfefc97da9c3917fL, 0xbc875d030a2ebe41L, + 0x0f75d235a732d1ccL, 0x06fee7fed9baa6d3L, 0xaa784fab65f48576L, + 0x23155e22513f83c0L, 0xd2fb77183e8f9d13L, 0x2a291503b546eafdL, + 0x1293c98c6cd93608L }, + { 0x7278125149d53b77L, 0xa6ab403d96eafac7L, 0xb7d7c7db4a36b711L, + 0x8238c70887e771c1L, 0x495f6abf33b37522L, 0xb0b0289c8c87530dL, + 0xca83cb86e77b111aL, 0xbe1c0fb8a1bd189eL, 0x58cfb2fb1ae9d7c7L, + 0xd05c23c54940c3e8L, 0x16e79e4174ad9107L, 0xa0a47f05064e7142L, + 0xc6929cd4fdfd614fL, 0xedb2584c3946988bL, 0x73e4b5f3e46f8fb1L, + 0x53b79aa168ea94baL }, + { 0x216fafce44bbb6a1L, 0xd3a5bba067821728L, 0xef1e4b30a9dd939aL, + 0x022eaf3df19efafeL, 0xfed5abce7b4ec014L, 0x64968ee6512c6738L, + 0x2311986929fe89a2L, 0x0d539d8d47397c05L, 0x6400bc54234596c4L, + 0xb9287f585346611dL, 0x04099903c9d5da0fL, 0xe5ef4997c83af2a8L, + 0xc89dc01b328151e1L, 0x150fb4a958401104L, 0x40a6f7d5f3872c9dL, + 0x8290d6d156c2e833L }, + { 0xf84637c6d8546946L, 0xda134a3969ec57faL, 0xd42359a4d789007eL, + 0xb42557fe0dc7b809L, 0xe62ae52d2d6784a9L, 0xa2714ca60bcadb5fL, + 0xcc208de633aafca5L, 0x2380ed5ced967811L, 0x6e6b55e9db321660L, + 0x1bead02ca675235aL, 0x51cc6ef9b33fa0e1L, 0xfd223e26f06a2a08L, + 0x00f332e1ec47b3cfL, 0x459f297ba0aa984eL, 0x6fa1d969ee952e14L, + 0x506ef1ab304fabb0L }, + { 0x11b4eb2735bff163L, 0x7130b96fea9fa984L, 0x66aceb3f9deb27ceL, + 0xa2daf1a59dd1c3d5L, 0xf5090a7ea73075aaL, 0x36a6af39e3071b58L, + 0xa28d633ddf73ad9cL, 0xdd354cacbdc89a16L, 0xdfea3423d4dcbc3cL, + 0x6eec74d2379d92d1L, 0xe14a456f8eed6765L, 0xfabe7743fa8feb1fL, + 0x1404ccf8b98fcbc7L, 0x6ccd2fbff71a706eL, 0xdaaf3fdb4d85c678L, + 0x415b7dbf15200344L }, + { 0x970105867d8377a7L, 0x068a3d68cb803272L, 0xfd67d289f03a4c32L, + 0x4bc7095d93c8f290L, 0x712fa13ce9e5a2b8L, 0xfc6ac6c60feb9f3bL, + 0x0cda36d96e0e54c2L, 0x4549975186320a01L, 0xf9318c9197f00f11L, + 0x01dc4c3fe6936508L, 0x769a2ef985f068aaL, 0x3522cef0a2b5511cL, + 0x006965edb4122e05L, 0xfce0fafcc175d43fL, 0x525dc9bdec831d59L, + 0x1ec314f1af58879dL }, + { 0x0663feef2c8310c2L, 0xaa7e14da457e3f74L, 0x392b10fce5346887L, + 0xcde4a38f637ec2c5L, 0x50773320b542f8dfL, 0x341302f9f7de1711L, + 0x018b1c63ae4b9bc6L, 0xf001c46edd2f9e6fL, 0xd3bb0a9726eccfa0L, + 0xa931b99d7746e0c7L, 0xe0c8b6f7f5875aecL, 0xbb32f17c96939c82L, + 0x765135d23de5a664L, 0x71936cb452abfa6bL, 0xad5cc08f2dc105deL, + 0x17e91d127fff5788L }, + { 0xbe92ced3b7e051caL, 0xc644d4fd19c776d4L, 0xc8ab4b520086784bL, + 0x3ea66227ce9d6b31L, 0x395249a3d289e9c7L, 0x54509e65d12a19eeL, + 0xa7bd46928c365aecL, 0x354997e477963e0eL, 0x0d765957b599732dL, + 0x99584aeb91d4a3b6L, 0x6e653ea41deb3e28L, 0xca7c98ed572571dfL, + 0xf301a38fb18ae1f9L, 0x1629f7c263f7b97eL, 0xdf242282afc4a0d5L, + 0x118f3b4b3ddd0c01L }, + { 0x74a0a0a87ad4762bL, 0x1aef84da8c58d175L, 0x16ff49604cf76d86L, + 0xc0be87867e60d98bL, 0x83637ffb3ecc1dbaL, 0xc244a6095dd6147aL, + 0xa3e178345b0846e5L, 0x735eb686e77a4c05L, 0x5bc18b4fdf758695L, + 0x15618d0b1bdfe52fL, 0x878ecc0d00715ba1L, 0x1dbdbd1ac2dd617fL, + 0x21d2b63121b61710L, 0x22ce8a7944f593c2L, 0x3b9b536a44f17024L, + 0x01d0a67c8d03e727L }, + { 0x7b9642361e46533cL, 0xe9477990fb88c2aeL, 0x019b5d16a42c4a18L, + 0x7135e81dd83c7a45L, 0x74a69bdd4cb663e3L, 0x7b67ecdbe76c0d63L, + 0x03d5452111e68da6L, 0x596cceb5d2e8650aL, 0xcd572dfd2af03b37L, + 0x52364ba1fabd5952L, 0x7f47d456b4ed8569L, 0x5ad8b572c950d5d4L, + 0xcadd2dfa486e2f84L, 0xdd527b43c56bb044L, 0xc9adba24997c08e6L, + 0x1b625b067da6320fL }, + { 0x44dfaa7b4fd8446dL, 0xc01b2f01af6febebL, 0xbf444388fe8838b5L, + 0xf33c434fbba9758bL, 0x2b971cba87156bc9L, 0x6b245e5c1f49098bL, + 0x87dcb5342b41c5ddL, 0xdb1f80c634d852d7L, 0x6d6e32582433da34L, + 0xf66820653f7df0c2L, 0xc4ca567c360cb365L, 0x321faac29826656aL, + 0x13f5ca6fbf069768L, 0x15397921a7076639L, 0xbdf143288400736eL, + 0x333eca9619fc948dL }, + { 0x23337948ac775d81L, 0x38c2518fd41dbbcaL, 0x623c7a4fbcfce948L, + 0xaad3623654703fe7L, 0x2b3a13a413fb3b5bL, 0x5db3565a7f5c01f0L, + 0xd72408dc52359661L, 0x5a17f8e51d616e91L, 0x90c16eebcb25b999L, + 0xf35e8cf13393743eL, 0x987da74ae54b64a7L, 0x557b322a65cd449dL, + 0x765082a537e7b15dL, 0x4d25c742f2cd134fL, 0xae9d9c074ccf0746L, + 0x72fc21108728d135L }, + { 0xa906b203f96004c8L, 0xd83f95cf458055ffL, 0xd77d586755f35909L, + 0x4a9ea6fbe550c8eeL, 0x91c8cca955a06081L, 0x4a1fee78bce82062L, + 0xeb9ade069a3df85eL, 0xfbbdcf0c7d3de666L, 0x228a391b5d336d51L, + 0x760f8d285c2ffc3cL, 0x1ee48de32f7b165bL, 0x03803d8456177040L, + 0xe573f6489deff9a0L, 0xe1a2738ea17e35a4L, 0x238ef17c8840a6c6L, + 0x480946f8b11ed92dL }, + { 0x84c747a8fd71f119L, 0x19e65c5e53eb3695L, 0x0e2f67866298587aL, + 0x48a48899ab18d6f4L, 0xa1a99024c630b8c0L, 0x849750962caaf892L, + 0xc8869abae20fd624L, 0x3b72b04d6c2b7dd4L, 0xe2775eb60992f7d0L, + 0x0089c06e7d06e684L, 0xcb3b4361e4bbd007L, 0xa1ae666b4ba846e4L, + 0xc01c2eb246464d9eL, 0xf86f2be6c1f8539fL, 0x16e8e8aecf68afc7L, + 0x8dab61fdc7386902L }, + { 0x42a5c903d54d1d45L, 0xacd4297eff4f9ba2L, 0x2d88b52034d478b4L, + 0x35b2ba2b08c4621aL, 0xd3d239bb34865402L, 0x1de76aed911f32e6L, + 0x877f8bcf3f06fdc2L, 0x802714c19ec51502L, 0xa10444eba590700dL, + 0x8694229f31dcc957L, 0x5ece77abb8169fedL, 0x55be8a152caf080eL, + 0x3eb21b14cbd7cef1L, 0x9def7ad167b97ee1L, 0xe03ca879118f690cL, + 0x6f77e62df99b29e7L }, + { 0xa271bdede40bbf59L, 0x177ba4536401aad6L, 0x1755e03573541cd1L, + 0x3465b4664b71b02fL, 0x22eb7113a813359fL, 0x9792a8fd6f38eac7L, + 0x11aa012fff3bf3b5L, 0x99aafabff85c3fbfL, 0x91e0a2ef06c0cc42L, + 0x314d5d57773b7b3aL, 0xae5e2e76d669840aL, 0x861360732e5a8be6L, + 0xee6d7578c1cf5580L, 0x2344e00f68bed102L, 0x799d78868184f0ebL, + 0x63819c91c3d2cf80L }, + { 0xca5392e17884b073L, 0x9ec3a1fceb1267eaL, 0x3d07f5f0907038a7L, + 0xcb2ac07ce4c47b70L, 0xf96664ee1bf96b91L, 0xebf575892aea4fbfL, + 0x5aabf391fade6500L, 0xc5b3376f171d1204L, 0x1ff60c51a0d3d81aL, + 0x10b2cfe7976a844bL, 0xe131cc9abda6125aL, 0xe0fc16d34ebd453eL, + 0xc0d0319a504b6bc1L, 0xe43a0be70a2f8cabL, 0xc80afeec55e49b47L, + 0x67d48d128265d7eeL }, + { 0x068d59a7ea2d56d6L, 0xd71abd0e27480a63L, 0x6bd11db0ae7366cdL, + 0xfbb639ca07204ebcL, 0x89a242e7f77e6293L, 0xdee7ca2b75ba8c3dL, + 0x472ddc3d64a2f9a8L, 0x84229df47561a010L, 0x95f62c85c5b649d4L, + 0xfdd56b1b4dc927cdL, 0xfe8bb1205ee60596L, 0x3efcaa50abf29401L, + 0xd4900d0f10d1c184L, 0x2cf113a928b01df5L, 0xa3d7ebc31f0e43f5L, + 0x27950e38e8384dc7L }, + { 0xeab21ff0e1d0fa79L, 0x4b9fd033048b5de9L, 0x4c9346892fe374cbL, + 0xbb4827fa4eb21f6bL, 0x46716f79a925e7e7L, 0x1442bf367dd4c531L, + 0x2073954cd2e96ddfL, 0x4e0141ae8502aa89L, 0x8ee00e1a8eef6cc9L, + 0x55ce84915880cdafL, 0xff3aba5c69628046L, 0x335cc4f85d15dfbfL, + 0xa7f0440c9f684f25L, 0xae80453fbb1e5bd8L, 0xa1c99813ff2225abL, + 0x54ff788479b25d71L }, + { 0x27c6ee30de40b068L, 0x9226465be6f3a51eL, 0xe24a4604fa3b21f6L, + 0x50a5a5adc0418115L, 0xe32854418df90d2bL, 0xbb74e58fdcb0c00fL, + 0xc68f1b3b4a2c08e3L, 0x339df0810ccd9ec9L, 0x915362dcb786ea9fL, + 0x28945e31c955aeadL, 0xd6a2c01d8b6a6c6bL, 0x069e82dc3678a427L, + 0x1787550028c9302cL, 0x8acda9659fa101e6L, 0x4e4e4573ee30b286L, + 0x8adbad853f1830feL }, + { 0x060ae11f0969d524L, 0xf42fdaf7f39bcc79L, 0x3cec67667cc1fcc2L, + 0x456b9cf2e2336d4fL, 0x6aa1f5de8e1c0f7fL, 0xcdbc2ad20984fb0eL, + 0x4090cfa61b464b28L, 0x40d86f301243f3efL, 0x95b16ccccd5e87e7L, + 0x403f168c3026cd41L, 0xdbe386cb816c0730L, 0x14eb86f358407a1dL, + 0xf588b4f81717e1afL, 0xb75c41a666cbc96cL, 0xf342c1aa027e71c1L, + 0x73930036c0945e5fL }, + { 0x954f757d22cdaf42L, 0x788b591df4181aabL, 0x8b986819f5514f25L, + 0x69642e08f18fd5bcL, 0x92b305d1022ceb91L, 0x1715903e6a4f6985L, + 0x4bd7d69d61179caeL, 0xdacdfd5dd29c01aaL, 0x705ddd5ad91108ccL, + 0x434ac7b164ac8f15L, 0x61a514e1b524632fL, 0x45b9e61b731fc447L, + 0xcf561348e0961b31L, 0x9c28a96773eaf223L, 0x5bd10182aa7c99d3L, + 0x8bc6ec4ae42965e2L }, + { 0xd096e5c0e7f2a32bL, 0xff54800c09388a30L, 0x06fe437c401e360cL, + 0x6655fc9cbb6054a6L, 0x510e18608457aa6eL, 0xa0acfca22b29b2b7L, + 0x732483e351b7da61L, 0xe31471ee6be6c8caL, 0xe565431c8b65c9a1L, + 0xfc9ac3b948d65cbbL, 0xd308fc21ae9b2aa8L, 0xd6a7df0daa60aa6aL, + 0x2844d96a982fc0d4L, 0xab012c2c5847a4d7L, 0x2b3c8f71dceb8955L, + 0x8e85437dbe9c7e15L }, +}; + +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +static int sp_ModExp_Fp_star_x64_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 16]; + sp_digit tx[2 * 16]; + sp_digit ty[2 * 16]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 16 * 2; + ty = td + 5 * 16 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 16); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 16); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_16(tx, ty, t); + sp_1024_proj_mul_qx1_16(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_16(tx, tx, t); + sp_1024_mont_mul_16(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 +/* Multiply p* in projective co-ordinates by q*. + * + * r.x = p.x - (p.y * q.y) + * r.y = (p.x * q.y) + p.y + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * q [in] A single precision integer - multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_qx1_avx2_16(sp_digit* px, sp_digit* py, + const sp_digit* q, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = p.x * q.y */ + sp_1024_mont_mul_avx2_16(t1, px, q, p1024_mod, p1024_mp_mod); + /* t2 = p.y * q.y */ + sp_1024_mont_mul_avx2_16(t2, py, q, p1024_mod, p1024_mp_mod); + /* r.x = p.x - (p.y * q.y) */ + sp_1024_mont_sub_avx2_16(px, px, t2, p1024_mod); + /* r.y = (p.x * q.y) + p.y */ + sp_1024_mont_add_avx2_16(py, t1, py, p1024_mod); +} + +/* Square p* in projective co-ordinates. + * + * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2 + * py' = 2 * p.x * p.y + * + * px [in,out] A single precision integer - X ordinate of number to square. + * py [in,out] A single precision integer - Y ordinate of number to square. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_sqr_avx2_16(sp_digit* px, sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = p.x + p.y */ + sp_1024_mont_add_avx2_16(t1, px, py, p1024_mod); + /* t2 = p.x - p.y */ + sp_1024_mont_sub_avx2_16(t2, px, py, p1024_mod); + /* r.y = p.x * p.y */ + sp_1024_mont_mul_avx2_16(py, px, py, p1024_mod, p1024_mp_mod); + /* r.x = (p.x + p.y) * (p.x - p.y) */ + sp_1024_mont_mul_avx2_16(px, t1, t2, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * p.y) * 2 */ + sp_1024_mont_dbl_avx2_16(py, py, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Simple square and multiply when expontent bit is one algorithm. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success and MEMORY_E if memory allocation fails. + */ +static int sp_ModExp_Fp_star_avx2_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; + sp_digit* b; + sp_digit* e; +#else + sp_digit t[4 * 2 * 16]; + sp_digit tx[2 * 16]; + sp_digit ty[2 * 16]; + sp_digit b[2 * 16]; + sp_digit e[2 * 16]; +#endif + sp_digit* r; + int err = MP_OKAY; + int bits; + int i; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 16 * 2; + ty = td + 5 * 16 * 2; + b = td + 6 * 16 * 2; + e = td + 7 * 16 * 2; +#endif + r = ty; + + bits = mp_count_bits(exp); + sp_1024_from_mp(b, 16, base); + sp_1024_from_mp(e, 16, exp); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 16); + sp_1024_mul_avx2_16(b, b, p1024_norm_mod); + err = sp_1024_mod_16(b, b, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(ty, b, sizeof(sp_digit) * 16); + + for (i = bits - 2; i >= 0; i--) { + sp_1024_proj_sqr_avx2_16(tx, ty, t); + if ((e[i / 64] >> (i % 64)) & 1) { + sp_1024_proj_mul_qx1_avx2_16(tx, ty, b, t); + } + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_avx2_16(tx, tx, t); + + XMEMSET(tx + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_avx2_16(tx, p1024_mod, p1024_mp_mod); + XMEMSET(ty + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_avx2_16(ty, p1024_mod, p1024_mp_mod); + + sp_1024_mul_avx2_16(r, tx, ty); + err = sp_1024_mod_16(r, r, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#else +/* Perform the modular exponentiation in Fp* for SAKKE. + * + * Base is fixed to be the g parameter - a precomputed table is used. + * + * Striping: 128 points at a distance of 8 combined. + * Total of 256 points in table. + * Square and multiply performed in Fp*. + * + * base [in] Base. MP integer. + * exp [in] Exponent. MP integer. + * res [out] Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +static int sp_ModExp_Fp_star_avx2_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; + sp_digit* t; + sp_digit* tx; + sp_digit* ty; +#else + sp_digit t[4 * 2 * 16]; + sp_digit tx[2 * 16]; + sp_digit ty[2 * 16]; +#endif + sp_digit* r = NULL; + unsigned char e[128]; + int err = MP_OKAY; + int i; + int y; + + (void)base; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + tx = td + 4 * 16 * 2; + ty = td + 5 * 16 * 2; +#endif + r = ty; + + (void)mp_to_unsigned_bin_len(exp, e, 128); + + XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 16); + y = e[112] >> 7; + y |= (e[96] >> 7) << 1; + y |= (e[80] >> 7) << 2; + y |= (e[64] >> 7) << 3; + y |= (e[48] >> 7) << 4; + y |= (e[32] >> 7) << 5; + y |= (e[16] >> 7) << 6; + y |= (e[0] >> 7) << 7; + XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 16); + for (i = 126; i >= 0; i--) { + y = (e[127 - (i / 8)] >> (i & 0x7)) & 1; + y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1; + y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2; + y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3; + y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4; + y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5; + y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6; + y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7; + + sp_1024_proj_sqr_avx2_16(tx, ty, t); + sp_1024_proj_mul_qx1_avx2_16(tx, ty, sp_1024_g_table[y], t); + } + } + + if (err == MP_OKAY) { + sp_1024_mont_inv_avx2_16(tx, tx, t); + sp_1024_mont_mul_avx2_16(r, tx, ty, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_avx2_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* HAVE_INTEL_AVX2 */ +/* Perform the modular exponentiation for SAKKE. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res) +{ + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_ModExp_Fp_star_avx2_1024(base, exp, res); + } + else +#endif + { + err = sp_ModExp_Fp_star_x64_1024(base, exp, res); + } + + return err; +} + +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_16(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = px + py */ + sp_1024_mont_add_16(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_16(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_16(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_16(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_16(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_16(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_16(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_16(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_16(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + sp_1024_mont_inv_16(t1, p->z, t2); + sp_1024_mont_sqr_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_16(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 16); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 16; + sp_digit* pz2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* l = t + 8 * 16; + sp_digit* ty = t + 10 * 16; + + /* v = v^2 */ + sp_1024_proj_sqr_16(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_16(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_16(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_16(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_16(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_16(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_16(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_16(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_16(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_16(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_16(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_16(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_16(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_16(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_16(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_16(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_16(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_16(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_16(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_16(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* h = t + 8 * 16; + sp_digit* r = t + 10 * 16; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_16(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_16(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_16(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_16(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_16(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_16(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_16(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_16(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_16(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_16(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_16(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_16(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_16(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_16(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_16(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_16(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_16(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_16(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_16(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_16(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_16(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_16(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sp_Pairing_x64_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit qx_px[2 * 16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_16(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + qx_px = td + 8 * 16 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + + sp_1024_mont_add_16(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 64] >> (i % 64)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_16(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_16(vx, vy, t); + sp_1024_proj_sqr_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_16(vx, vx, t); + sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_16(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* h = t + 8 * 16; + sp_digit* r = t + 10 * 16; + + /* h = p.z^2 */ + sp_1024_mont_sqr_16(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_16(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_16(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_16(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_16(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_16(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_16(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_16(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_16(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_16(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_16(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_16(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_16(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_16(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_16(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_16(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_16(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_16(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_16(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_16(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_16(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_16(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_16(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_16(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_16(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_16(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_16(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_16(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_16(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 16; + sp_digit* pz2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* l = t + 8 * 16; + sp_digit* ty = t + 10 * 16; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_16(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_16(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_16(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_16(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_16(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_16(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_16(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_16(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_16(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_16(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_16(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_16(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_16(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_16(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_16(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_16(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_16(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_16(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_16(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_16(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_16(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_16(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_16(p->y, p->y, p1024_mod); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sp_Pairing_x64_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[32]; + sp_digit (*pre_vy)[32]; + sp_digit (*pre_nvy)[32]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit pre_vx[16][32]; + sp_digit pre_vy[16][32]; + sp_digit pre_nvy[16][32]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_16(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2); + pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2); + pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2); + pre_p = (sp_point_1024*)(td + 56 * 16 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16); + sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16); + sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_16(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_16(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_16(vx, vy, t); + sp_1024_proj_sqr_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_16(vx, vx, t); + sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 +/* Multiply p* by q* in projective co-ordinates. + * + * p.x' = (p.x * q.x) - (p.y * q.y) + * p.y' = (p.x * q.y) + (p.y * q.x) + * But applying Karatsuba: + * v0 = p.x * q.x + * v1 = p.y * q.y + * p.x' = v0 - v1 + * p.y' = (px + py) * (qx + qy) - v0 - v1 + * + * px [in,out] A single precision integer - X ordinate of number to multiply. + * py [in,out] A single precision integer - Y ordinate of number to multiply. + * qx [in] A single precision integer - X ordinate of number of + * multiplier. + * qy [in] A single precision integer - Y ordinate of number of + * multiplier. + * t [in] Two single precision integers - temps. + */ +static void sp_1024_proj_mul_avx2_16(sp_digit* px, sp_digit* py, + const sp_digit* qx, const sp_digit* qy, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + /* t1 = px + py */ + sp_1024_mont_add_avx2_16(t1, px, py, p1024_mod); + /* t2 = qx + qy */ + sp_1024_mont_add_avx2_16(t2, qx, qy, p1024_mod); + /* t2 = (px + py) * (qx + qy) */ + sp_1024_mont_mul_avx2_16(t2, t1, t2, p1024_mod, p1024_mp_mod); + /* t1 = py * qy */ + sp_1024_mont_mul_avx2_16(t1, py, qy, p1024_mod, p1024_mp_mod); + /* t2 = (px + py) * (qx + qy) - (py * qy) */ + sp_1024_mont_sub_avx2_16(t2, t2, t1, p1024_mod); + /* px = px * qx */ + sp_1024_mont_mul_avx2_16(px, px, qx, p1024_mod, p1024_mp_mod); + /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */ + sp_1024_mont_sub_avx2_16(py, t2, px, p1024_mod); + /* px = (px * qx) - (py * qy)*/ + sp_1024_mont_sub_avx2_16(px, px, t1, p1024_mod); +} + +#ifndef WOLFSSL_SP_SMALL +/* + * Convert point from projective to affine but keep in Montgomery form. + * + * p [in,out] Point to convert. + * t [in] Temporary numbers: 2. + */ +static void sp_1024_mont_map_avx2_16(sp_point_1024* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + + sp_1024_mont_inv_avx2_16(t1, p->z, t2); + sp_1024_mont_sqr_avx2_16(t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(t1, t2, t1, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(p->x, p->x, t2, p1024_mod, p1024_mp_mod); + sp_1024_mont_mul_avx2_16(p->y, p->y, t1, p1024_mod, p1024_mp_mod); + XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 16); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2 + * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 8 * p.y^2 * p.x + * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 + * p'.z = 2 * p.y * p.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_avx2_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 16; + sp_digit* pz2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* l = t + 8 * 16; + sp_digit* ty = t + 10 * 16; + + /* v = v^2 */ + sp_1024_proj_sqr_avx2_16(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_avx2_16(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_avx2_16(ty, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_avx2_16(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_avx2_16(t1, l, ty, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_avx2_16(l, t1, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_avx2_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_avx2_16(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_avx2_16(rx, l, t1, p1024_mod, p1024_mp_mod); + /* r.y = 2 * p.y */ + sp_1024_mont_dbl_avx2_16(ry, p->y, p1024_mod); + /* ty = 4 * p.y ^ 2 */ + sp_1024_mont_sqr_avx2_16(ty, ry, p1024_mod, p1024_mp_mod); + /* t1 = 2 * p.y ^ 2 */ + sp_1024_div2_avx2_16(t1, ty, p1024_mod); + /* r.x -= 2 * (p.y ^ 2) */ + sp_1024_mont_sub_avx2_16(rx, rx, t1, p1024_mod); + /* p'.z = p.y * 2 * p.z */ + sp_1024_mont_mul_avx2_16(p->z, p->z, ry, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_avx2_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_avx2_16(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = 4 * p.y^2 + * p'.z = 2 * p.y * p.z + */ + /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */ + sp_1024_mont_sqr_avx2_16(t1, ty, p1024_mod, p1024_mp_mod); + /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */ + sp_1024_div2_avx2_16(t1, t1, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x */ + sp_1024_mont_mul_avx2_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_avx2_16(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - 4 * p.y^2 * p.x */ + sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 8 * p.y^2 * p.x */ + sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod); + /* p'.y = 4 * p.y^2 * p.x - p.x' */ + sp_1024_mont_sub_avx2_16(ty, p->y, p->x, p1024_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_avx2_16(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */ + sp_1024_mont_sub_avx2_16(p->y, p->y, t1, p1024_mod); +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Calculations: + * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z + * r.y = (c.x - p.x * c.z^2) * q.y * c.z + * v* = v* * r* + * r = p.y * c.z^3 - c.y + * c'.x = r^2 + h^3 - 2 * c.x * h^2 + * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in] p ECC point - point on E(F_p^2) to add. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] qx_px SP that is a constant value across adds. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_add_one_avx2_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px, + sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* h = t + 8 * 16; + sp_digit* r = t + 10 * 16; + + /* r.x = (q.x + p.x) * c.y */ + sp_1024_mont_mul_avx2_16(rx, qx_px, c->y, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_avx2_16(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_avx2_16(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_avx2_16(h, t1, c->x, p1024_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_avx2_16(ry, p->y, c->z, p1024_mod, p1024_mp_mod); + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_avx2_16(t1, h, ry, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */ + sp_1024_mont_mul_avx2_16(r, ry, t2, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_avx2_16(rx, rx, t1, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_avx2_16(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = c.x - p.x * c.z^2 */ + sp_1024_mont_sub_avx2_16(h, c->x, t1, p1024_mod); + /* c'.z = (c.x - p.x * c.z^2) * c.z */ + sp_1024_mont_mul_avx2_16(c->z, h, c->z, p1024_mod, p1024_mp_mod); + /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */ + sp_1024_mont_mul_avx2_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* v = v * r */ + sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = c.x - p.x * c.z^2 + * r = p.y * c.z^3 + * c'.z = (c.x - p.x * c.z^2) * c.z + */ + + /* r = p.y * c.z^3 - c.y */ + sp_1024_mont_sub_avx2_16(r, r, c->y, p1024_mod); + /* t1 = r^2 */ + sp_1024_mont_sqr_avx2_16(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_avx2_16(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * h^2 */ + sp_1024_mont_mul_avx2_16(ry, c->x, rx, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_avx2_16(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c->x = r^2 + h^3 */ + sp_1024_mont_add_avx2_16(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * h^2 */ + sp_1024_mont_dbl_avx2_16(t1, ry, p1024_mod); + /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */ + sp_1024_mont_sub_avx2_16(c->x, c->x, t1, p1024_mod); + /* ry = c'.x - c.x * h^2 */ + sp_1024_mont_sub_avx2_16(t1, c->x, ry, p1024_mod); + /* ry = r * (c'.x - c.x * h^2) */ + sp_1024_mont_mul_avx2_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * h^3 */ + sp_1024_mont_mul_avx2_16(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */ + sp_1024_mont_sub_avx2_16(c->y, ry, t1, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static int sp_Pairing_avx2_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err = MP_OKAY; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit* qx_px; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit qx_px[2 * 16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + + err = sp_1024_point_new_16(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + qx_px = td + 8 * 16 * 2; +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + + sp_1024_mont_add_avx2_16(qx_px, q->x, p->x, p1024_mod); + + for (i = 1020; i >= 0; i--) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_dbl_avx2_16(vx, vy, c, q, t); + + if ((i > 0) && ((p1024_order[i / 64] >> (i % 64)) & 1)) { + /* Accumulate line into v and add P into C. */ + sp_1024_accumulate_line_add_one_avx2_16(vx, vy, c, p, q, qx_px, t); + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_avx2_16(vx, vy, t); + sp_1024_proj_sqr_avx2_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_avx2_16(vx, vx, t); + sp_1024_mont_mul_avx2_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#else +/* + * Calculate gradient of line through C, P and -C-P, accumulate line and + * add P to C. + * + * Both C and P have z ordinates to use in the calculation. + * + * Calculations: + * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z + * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z + * v* = v* * r* + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 + * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] c ECC point - current point on E(F_p^2) to be added + * to. + * @param [in,out] p ECC point - point on E(F_p^2) to add. + * @param [in,out] q ECC point - second point on E(F_P^2). + * @param [in,out] t SP temporaries (6 used). + * @param [in,out] neg Indicates to use negative P. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +static void sp_1024_accumulate_line_add_n_avx2_16(sp_digit* vx, sp_digit* vy, + const sp_point_1024* p, const sp_point_1024* q, + sp_point_1024* c, sp_digit* t, int neg) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* h = t + 8 * 16; + sp_digit* r = t + 10 * 16; + + /* h = p.z^2 */ + sp_1024_mont_sqr_avx2_16(h, p->z, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 */ + sp_1024_mont_mul_avx2_16(rx, q->x, h, p1024_mod, p1024_mp_mod); + /* rx = q.x * p.z^2 + p.x */ + sp_1024_mont_add_avx2_16(t2, rx, p->x, p1024_mod); + /* c.y = c.y * p.z */ + sp_1024_mont_mul_avx2_16(t1, c->y, p->z, p1024_mod, p1024_mp_mod); + /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */ + sp_1024_mont_mul_avx2_16(rx, t2, t1, p1024_mod, p1024_mp_mod); + /* c.y = c.y * p.z^3 */ + sp_1024_mont_mul_avx2_16(c->y, t1, h, p1024_mod, p1024_mp_mod); + /* t2 = c.z^2 */ + sp_1024_mont_sqr_avx2_16(t2, c->z, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 */ + sp_1024_mont_mul_avx2_16(t1, q->x, t2, p1024_mod, p1024_mp_mod); + /* t1 = q.x * c.z^2 + c.x */ + sp_1024_mont_add_avx2_16(t1, t1, c->x, p1024_mod); + /* c.x = c.x * p.z^2 */ + sp_1024_mont_mul_avx2_16(c->x, c->x, h, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z */ + sp_1024_mont_mul_avx2_16(r, p->y, c->z, p1024_mod, p1024_mp_mod); + if (neg) { + /* r = -p.y * c.z */ + sp_1024_mont_sub_avx2_16(r, p1024_mod, r, p1024_mod); + } + /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_mul_avx2_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */ + sp_1024_mont_sub_avx2_16(rx, ry, rx, p1024_mod); + /* t1 = p.x * c.z^2 */ + sp_1024_mont_mul_avx2_16(t1, p->x, t2, p1024_mod, p1024_mp_mod); + /* h = p.x * c.z^2 - c.x * p.z^2 */ + sp_1024_mont_sub_avx2_16(h, t1, c->x, p1024_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */ + sp_1024_mont_mul_avx2_16(t1, h, c->z, p1024_mod, p1024_mp_mod); + /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */ + sp_1024_mont_mul_avx2_16(c->z, t1, p->z, p1024_mod, p1024_mp_mod); + /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */ + sp_1024_mont_mul_avx2_16(ry, c->z, q->y, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 */ + sp_1024_mont_mul_avx2_16(t1, r, t2, p1024_mod, p1024_mp_mod); + /* r = p.y * c.z^3 - c.y * p.z^3 */ + sp_1024_mont_sub_avx2_16(r, t1, c->y, p1024_mod); + /* v = v * r */ + sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t); + + /* Add p to c using previously calculated values. + * h = p.x * c.z^2 - c.x * p.z^2 + * r = p.y * c.z^3 - c.y * p.z^3 + * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z + */ + + /* t1 = r^2 */ + sp_1024_mont_sqr_avx2_16(t1, r, p1024_mod, p1024_mp_mod); + /* t2 = h^2 */ + sp_1024_mont_sqr_avx2_16(rx, h, p1024_mod, p1024_mp_mod); + /* ry = c.x * p.z^2 * h^2 */ + sp_1024_mont_mul_avx2_16(ry, rx, c->x, p1024_mod, p1024_mp_mod); + /* t2 = h^3 */ + sp_1024_mont_mul_avx2_16(t2, rx, h, p1024_mod, p1024_mp_mod); + /* c'.x = r^2 - h^3 */ + sp_1024_mont_sub_avx2_16(c->x, t1, t2, p1024_mod); + /* t1 = 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_dbl_avx2_16(t1, ry, p1024_mod); + /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */ + sp_1024_mont_sub_avx2_16(c->x, c->x, t1, p1024_mod); + /* ry = c.x * p.z^2 * h^2 - c'.x */ + sp_1024_mont_sub_avx2_16(t1, ry, c->x, p1024_mod); + /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */ + sp_1024_mont_mul_avx2_16(ry, t1, r, p1024_mod, p1024_mp_mod); + /* t2 = c.y * p.z^3 * h^3 */ + sp_1024_mont_mul_avx2_16(t1, t2, c->y, p1024_mod, p1024_mp_mod); + /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */ + sp_1024_mont_sub_avx2_16(c->y, ry, t1, p1024_mod); +} + +/* + * Perform n accumulate doubles and doubles of P. + * + * py = 2 * p.y + * + * For each double: + * Calculate gradient of line through P, P and [-2]P, accumulate line and + * double P. + * + * Calculations: + * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2) + * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2 + * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y) + * v* = v*^2 * r* + * p'.x = l^2 - 2 * py^2 * p.x + * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y) + * p'.z = py * p.z + * + * Finally: + * p'.y = py' / 2 + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in,out] p ECC point - point on E(F_p^2) to double. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] n Number of times to double. + * @param [in] t SP temporaries (6 used). + */ +static void sp_1024_accumulate_line_dbl_n_avx2_16(sp_digit* vx, sp_digit* vy, + sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 16; + sp_digit* pz2 = t + 2 * 16; + sp_digit* rx = t + 4 * 16; + sp_digit* ry = t + 6 * 16; + sp_digit* l = t + 8 * 16; + sp_digit* ty = t + 10 * 16; + int i; + + /* py = 2 * p.y */ + sp_1024_mont_dbl_avx2_16(p->y, p->y, p1024_mod); + + for (i = 0; i < n; i++) { + /* v = v^2 */ + sp_1024_proj_sqr_avx2_16(vx, vy, t); + /* pz2 = p.z^2 */ + sp_1024_mont_sqr_avx2_16(pz2, p->z, p1024_mod, p1024_mp_mod); + /* t1 = p.x + p.z^2 */ + sp_1024_mont_add_avx2_16(t1, p->x, pz2, p1024_mod); + /* l = p.x - p.z^2 */ + sp_1024_mont_sub_avx2_16(l, p->x, pz2, p1024_mod); + /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */ + sp_1024_mont_mul_avx2_16(ty, l, t1, p1024_mod, p1024_mp_mod); + /* l = 3 * (p.x^2 - p.z^4) */ + sp_1024_mont_tpl_avx2_16(l, ty, p1024_mod); + /* t1 = q.x * p.z^2 */ + sp_1024_mont_mul_avx2_16(t1, q->x, pz2, p1024_mod, p1024_mp_mod); + /* t1 = p.x + q.x * p.z^2 */ + sp_1024_mont_add_avx2_16(t1, p->x, t1, p1024_mod); + /* r.x = l * (p.x + q.x * p.z^2) */ + sp_1024_mont_mul_avx2_16(rx, l, t1, p1024_mod, p1024_mp_mod); + /* ty = py ^ 2 */ + sp_1024_mont_sqr_avx2_16(ty, p->y, p1024_mod, p1024_mp_mod); + /* t1 = py ^ 2 / 2 */ + sp_1024_div2_avx2_16(t1, ty, p1024_mod); + /* r.x -= py ^ 2 / 2 */ + sp_1024_mont_sub_avx2_16(rx, rx, t1, p1024_mod); + /* p'.z = py * pz */ + sp_1024_mont_mul_avx2_16(p->z, p->z, p->y, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 */ + sp_1024_mont_mul_avx2_16(t1, p->z, pz2, p1024_mod, p1024_mp_mod); + /* r.y = p'.z * p.z^2 * q.y */ + sp_1024_mont_mul_avx2_16(ry, t1, q->y, p1024_mod, p1024_mp_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_avx2_16(vx, vy, rx, ry, t); + + /* Double point using previously calculated values + * l = 3 * (p.x - p.z^2).(p.x + p.z^2) + * ty = py^2 + * p'.z = py * p.z + */ + /* t1 = py^2 ^ 2 = py^4 */ + sp_1024_mont_sqr_avx2_16(t1, ty, p1024_mod, p1024_mp_mod); + /* py' = py^2 * p. x */ + sp_1024_mont_mul_avx2_16(p->y, ty, p->x, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 */ + sp_1024_mont_sqr_avx2_16(p->x, l, p1024_mod, p1024_mp_mod); + /* p'.x = l^2 - py^2 * p.x */ + sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod); + /* p'.x = l^2 - 2 * p.y^2 * p.x */ + sp_1024_mont_sub_avx2_16(p->x, p->x, p->y, p1024_mod); + /* py' = py^2 * p.x - p.x' */ + sp_1024_mont_sub_avx2_16(ty, p->y, p->x, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l */ + sp_1024_mont_mul_avx2_16(p->y, ty, l, p1024_mod, p1024_mp_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 */ + sp_1024_mont_dbl_avx2_16(p->y, p->y, p1024_mod); + /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */ + sp_1024_mont_sub_avx2_16(p->y, p->y, t1, p1024_mod); + } + + /* p'.y = py' / 2 */ + sp_1024_div2_avx2_16(p->y, p->y, p1024_mod); +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sp_Pairing_avx2_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[32]; + sp_digit (*pre_vy)[32]; + sp_digit (*pre_nvy)[32]; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit pre_vx[16][32]; + sp_digit pre_vy[16][32]; + sp_digit pre_nvy[16][32]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + + err = sp_1024_point_new_16(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2); + pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2); + pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2); + pre_p = (sp_point_1024*)(td + 56 * 16 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16); + sp_1024_mont_sub_avx2_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + sp_1024_accumulate_line_dbl_avx2_16(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024)); + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16); + sp_1024_proj_mul_avx2_16(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_avx2_16(pre_vx[i], pre_vy[i], c, + q, &pre_p[i], t, 0); + sp_1024_mont_sub_avx2_16(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod); + } + + j = sp_1024_order_op[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16); + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_avx2_16(vx, vy, c, q, + sp_1024_order_op[1], t); + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_vy[j], t); + sp_1024_accumulate_line_add_n_avx2_16(vx, vy, &pre_p[j], q, c, + t, 0); + } + else { + j = -j / 2; + /* Accumulate line into v and add P into C. */ + sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_nvy[j], t); + sp_1024_accumulate_line_add_n_avx2_16(vx, vy, &pre_p[j], q, c, + t, 1); + } + + /* Accumulate line into v and double point n times. */ + sp_1024_accumulate_line_dbl_n_avx2_16(vx, vy, c, q, + sp_1024_order_op[i + 1], t); + } + + /* Final exponentiation */ + sp_1024_proj_sqr_avx2_16(vx, vy, t); + sp_1024_proj_sqr_avx2_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_avx2_16(vx, vx, t); + sp_1024_mont_mul_avx2_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_avx2_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* HAVE_INTEL_AVX2 */ +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res) +{ + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_Pairing_avx2_1024(pm, qm, res); + } + else +#endif + { + err = sp_Pairing_x64_1024(pm, qm, res); + } + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +static int sp_Pairing_gen_precomp_x64_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sp_Pairing_precomp_x64_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_x64_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_16(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 16; + sp_digit* t2 = t + 2 * 2 * 16; + sp_digit* l = t + 4 * 2 * 16; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_16(l, py, p1024_mod); + sp_1024_mont_inv_16(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_16(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_16(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_16(t2, t1, p1024_mod); + sp_1024_mont_add_16(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_16(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_16(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_16(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 16); + XMEMCPY(cr, t2, sizeof(sp_digit) * 16); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_16(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 16; + sp_digit* c = t + 2 * 2 * 16; + sp_digit* l = t + 4 * 2 * 16; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_16(l, cx, px, p1024_mod); + sp_1024_mont_inv_16(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_16(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_16(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_16(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_16(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_16(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_16(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 16); + XMEMCPY(cr, c, sizeof(sp_digit) * 16); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_16(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 16; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_16(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_16(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_16(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_16(vx, vy, rx, q->y, t); +} + +/* Operations to perform based on order - 1. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pairs: #dbls, add/subtract window value + */ +static const signed char sp_1024_order_op_pre[] = { + 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9, + -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6, + -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8, + 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7, + -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6, + -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7, + -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7, + -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7, + -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6, + 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6, + -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6, + -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10, + 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7, + -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7, + 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6, + -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12, + 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8, + -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10, + -3, 1, +}; + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +static int sp_Pairing_gen_precomp_x64_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 16]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 16 * 2); +#endif + + sp_1024_point_from_ecc_point_16(p, pm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_16(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_16(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_16(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_16(c, c, t); + sp_1024_mont_map_16(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_16(c, c, &pre_p[j/2], t); + sp_1024_mont_map_16(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_16(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_16(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_16(c, c, neg, t); + sp_1024_mont_map_16(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_16(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_16(c, c, t); + sp_1024_mont_map_16(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(neg, 1, NULL); + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sp_Pairing_precomp_x64_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[32]; + sp_digit (*pre_vy)[32]; + sp_digit (*pre_nvy)[32]; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit pre_vx[16][32]; + sp_digit pre_vy[16][32]; + sp_digit pre_nvy[16][32]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2); + pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2); + pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16); + sp_1024_mont_sub_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + sp_1024_accumulate_line_dbl_16(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16); + sp_1024_proj_mul_16(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_16(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_16(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 16); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_16(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_16(vx, vy, t); + sp_1024_proj_sqr_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_16(vx, vx, t); + sp_1024_mont_mul_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef HAVE_INTEL_AVX2 +#ifdef WOLFSSL_SP_SMALL +/* + * Generate table for pairing. + * + * Small implementation does not use a table - returns 0 length. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + */ +static int sp_Pairing_gen_precomp_avx2_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; + + if (table == NULL) { + *len = 0; + err = LENGTH_ONLY_E; + } + else if (*len != 0) { + err = BUFFER_E; + } + + (void)*pm; + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Small implementation does not use a table - use the normal implementation. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sp_Pairing_precomp_avx2_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + (void)table; + (void)len; + return sp_Pairing_avx2_1024(pm, qm, res); +} + +#else +/* + * Calc l and c for the point when doubling p. + * + * l = 3 * (p.x^2 - 1) / (2 * p.y) + * c = l * p.x - p.y + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to double. + * @param [in] py Y-ordinate of point to double. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_dbl_calc_lc_avx2_16(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 16; + sp_digit* t2 = t + 2 * 2 * 16; + sp_digit* l = t + 4 * 2 * 16; + + + /* l = 1 / 2 * p.y */ + sp_1024_mont_dbl_avx2_16(l, py, p1024_mod); + sp_1024_mont_inv_avx2_16(l, l, t); + + /* t1 = p.x^2 */ + sp_1024_mont_sqr_avx2_16(t1, px, p1024_mod, p1024_mp_mod); + /* t1 = p.x - 1 */ + sp_1024_mont_sub_avx2_16(t1, t1, p1024_norm_mod, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) */ + sp_1024_mont_dbl_avx2_16(t2, t1, p1024_mod); + sp_1024_mont_add_avx2_16(t1, t1, t2, p1024_mod); + /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */ + sp_1024_mont_mul_avx2_16(l, l, t1, p1024_mod, p1024_mp_mod); + /* t2 = l * p.x */ + sp_1024_mont_mul_avx2_16(t2, l, px, p1024_mod, p1024_mp_mod); + /* c = t2 = l * p.x - p.y */ + sp_1024_mont_sub_avx2_16(t2, t2, py, p1024_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 16); + XMEMCPY(cr, t2, sizeof(sp_digit) * 16); +} + +/* + * Calc l and c when adding p and c. + * + * l = (c.y - p.y) / (c.x - p.x) + * c = (p.x * c.y - cx * p.y) / (cx - p.x) + * + * @param [out] lr Gradient result - table entry. + * @param [out] cr Constant result - table entry. + * @param [in] px X-ordinate of point to add. + * @param [in] py Y-ordinate of point to add. + * @param [in] cx X-ordinate of current point. + * @param [in] cy Y-ordinate of current point. + * @param [in] t SP temporaries (3 used). + */ +static void sp_1024_accum_add_calc_lc_avx2_16(sp_digit* lr, sp_digit* cr, + const sp_digit* px, const sp_digit* py, const sp_digit* cx, + const sp_digit* cy, sp_digit* t) +{ + sp_digit* t1 = t + 0 * 2 * 16; + sp_digit* c = t + 2 * 2 * 16; + sp_digit* l = t + 4 * 2 * 16; + + + /* l = 1 / (c.x - p.x) */ + sp_1024_mont_sub_avx2_16(l, cx, px, p1024_mod); + sp_1024_mont_inv_avx2_16(l, l, t); + + /* c = p.x * c.y */ + sp_1024_mont_mul_avx2_16(c, px, cy, p1024_mod, p1024_mp_mod); + /* t1 = c.x * p.y */ + sp_1024_mont_mul_avx2_16(t1, cx, py, p1024_mod, p1024_mp_mod); + /* c = (p.x * c.y) - (c.x * p.y) */ + sp_1024_mont_sub_avx2_16(c, c, t1, p1024_mod); + /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */ + sp_1024_mont_mul_avx2_16(c, c, l, p1024_mod, p1024_mp_mod); + /* t1 = c.y - p.y */ + sp_1024_mont_sub_avx2_16(t1, cy, py, p1024_mod); + /* l = (c.y - p.y) / (c.x - p.x) */ + sp_1024_mont_mul_avx2_16(l, t1, l, p1024_mod, p1024_mp_mod); + + XMEMCPY(lr, l, sizeof(sp_digit) * 16); + XMEMCPY(cr, c, sizeof(sp_digit) * 16); +} + +/* + * Calculate vx and vy given gradient l and constant c and point q. + * + * l is a the gradient and is multiplied by q->x. + * c is a the constant that is added to the multiplicative result. + * q->y is the y-ordinate in result to multiply. + * + * if dbl + * v* = v*^2 + * r.x = l * q.x + c + * r.y = q->y + * v* = v* * r* + * + * @param [in,out] vx X-ordinate of projective value in F*. + * @param [in,out] vy Y-ordinate of projective value in F*. + * @param [in] l Gradient to multiply with. + * @param [in] c Constant to add with. + * @param [in] q ECC point - second point on E(F_P^2). + * @param [in] t SP temporaries (3 used). + * @param [in] dbl Indicates whether this is for doubling. Otherwise + * adding. + */ +static void sp_1024_accumulate_line_lc_avx2_16(sp_digit* vx, sp_digit* vy, + const sp_digit* l, const sp_digit* c, const sp_point_1024* q, + sp_digit* t, int dbl) +{ + sp_digit* rx = t + 4 * 2 * 16; + + /* v = v^2 */ + if (dbl) { + sp_1024_proj_sqr_avx2_16(vx, vy, t); + } + /* rx = l * q.x + c */ + sp_1024_mont_mul_avx2_16(rx, l, q->x, p1024_mod, p1024_mp_mod); + sp_1024_mont_add_avx2_16(rx, rx, c, p1024_mod); + /* v = v^2 * r */ + sp_1024_proj_mul_avx2_16(vx, vy, rx, q->y, t); +} + + +/* + * Generate table for pairing. + * + * Calculate the graident (l) and constant (c) at each step of the way. + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * LENGTH_ONLY_E when table is NULL and only length returned. + * BUFFER_E when len is too small. + * MEMORY_E when dynamic memory allocation fauls. + */ +static int sp_Pairing_gen_precomp_avx2_1024(const ecc_point* pm, byte* table, + word32* len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_point_1024* pre_p; +#else + sp_digit t[6 * 2 * 16]; + sp_point_1024 pre_p[16]; + sp_point_1024 pd; + sp_point_1024 cd; + sp_point_1024 negd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* c = NULL; + sp_point_1024* neg = NULL; + int i; + int j; + int k; + sp_table_entry_1024* precomp = (sp_table_entry_1024*)table; + + if (table == NULL) { + *len = sizeof(sp_table_entry_1024) * 1167; + err = LENGTH_ONLY_E; + } + + if ((err == MP_OKAY) && + (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, negd, neg); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 16 * 2 + 16 * sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + pre_p = (sp_point_1024*)(td + 6 * 16 * 2); +#endif + + sp_1024_point_from_ecc_point_16(p, pm); + + err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod)); + neg->infinity = 0; + c->infinity = 0; + + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024)); + /* [2]P for adding */ + sp_1024_proj_point_dbl_avx2_16(c, p, t); + + /* 1, 3, ... */ + for (i = 1; i < 16; i++) { + sp_1024_proj_point_add_avx2_16(&pre_p[i], &pre_p[i-1], c, t); + sp_1024_mont_map_avx2_16(&pre_p[i], t); + } + + k = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024)); + + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + sp_1024_accum_dbl_calc_lc_avx2_16(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_avx2_16(c, c, t); + sp_1024_mont_map_avx2_16(c, t); + } + + for (i = 2; i < 290; i += 2) { + j = sp_1024_order_op_pre[i]; + if (j > 0) { + sp_1024_accum_add_calc_lc_avx2_16(precomp[k].x, precomp[k].y, + pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_avx2_16(c, c, &pre_p[j/2], t); + sp_1024_mont_map_avx2_16(c, t); + } + else { + XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x)); + sp_1024_mont_sub_avx2_16(neg->y, p1024_mod, pre_p[-j / 2].y, + p1024_mod); + XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z)); + + sp_1024_accum_add_calc_lc_avx2_16(precomp[k].x, precomp[k].y, + neg->x, neg->y, c->x, c->y, t); + k++; + sp_1024_proj_point_add_avx2_16(c, c, neg, t); + sp_1024_mont_map_avx2_16(c, t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + sp_1024_accum_dbl_calc_lc_avx2_16(precomp[k].x, precomp[k].y, c->x, c->y, t); + k++; + sp_1024_proj_point_dbl_avx2_16(c, c, t); + sp_1024_mont_map_avx2_16(c, t); + } + } + + *len = sizeof(sp_table_entry_1024) * 1167; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(neg, 1, NULL); + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * Sliding window. Start at bottom and stop when bottom bit is one. + * Subtract if top bit in window is one. + * Width of 6 bits. + * Pre-generate values in window (1, 3, ...) - only V. + * Table contains all gradient l and a constant for each point on the path. + * + * @param [in] pm First point on E(F_p)[q]. + * @param [in] qm Second point on E(F_p)[q]. + * @param [in] res Result of calculation. + * @param [in] table Precomputed table of values. + * @param [in] len Length of precomputed table of values in bytes. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int sp_Pairing_precomp_avx2_1024(const ecc_point* pm, const ecc_point* qm, + mp_int* res, const byte* table, word32 len) +{ + int err = 0; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td = NULL; + sp_digit* t; + sp_digit* vx; + sp_digit* vy; + sp_digit (*pre_vx)[32]; + sp_digit (*pre_vy)[32]; + sp_digit (*pre_nvy)[32]; +#else + sp_digit t[6 * 2 * 16]; + sp_digit vx[2 * 16]; + sp_digit vy[2 * 16]; + sp_digit pre_vx[16][32]; + sp_digit pre_vy[16][32]; + sp_digit pre_nvy[16][32]; + sp_point_1024 pd; + sp_point_1024 qd; + sp_point_1024 cd; +#endif + sp_point_1024* p = NULL; + sp_point_1024* q = NULL; + sp_point_1024* c = NULL; + sp_digit* r = NULL; + int i; + int j; + int k; + const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table; + + if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, pd, p); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, qd, q); + } + if (err == MP_OKAY) { + err = sp_1024_point_new_16(NULL, cd, c); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 16 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + vx = td + 6 * 16 * 2; + vy = td + 7 * 16 * 2; + pre_vx = (sp_digit(*)[32])(td + 8 * 16 * 2); + pre_vy = (sp_digit(*)[32])(td + 24 * 16 * 2); + pre_nvy = (sp_digit(*)[32])(td + 40 * 16 * 2); +#endif + r = vy; + + sp_1024_point_from_ecc_point_16(p, pm); + sp_1024_point_from_ecc_point_16(q, qm); + + err = sp_1024_mod_mul_norm_avx2_16(p->x, p->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->y, p->y, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(p->z, p->z, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(q->x, q->x, p1024_mod); + } + if (err == MP_OKAY) { + err = sp_1024_mod_mul_norm_avx2_16(q->y, q->y, p1024_mod); + } + if (err == MP_OKAY) { + /* Generate pre-computation table: 1, 3, ... , 31 */ + XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 16); + pre_vx[0][0] = 1; + XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 16); + sp_1024_mont_sub_avx2_16(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod); + + /* [2]P for adding */ + XMEMCPY(c, p, sizeof(sp_point_1024)); + XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 16); + vx[0] = 1; + XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 16); + sp_1024_accumulate_line_dbl_avx2_16(vx, vy, c, q, t); + + /* 3, 5, ... */ + for (i = 1; i < 16; i++) { + XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 16); + XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 16); + sp_1024_proj_mul_avx2_16(pre_vx[i], pre_vy[i], vx, vy, t); + sp_1024_accumulate_line_add_n_avx2_16(pre_vx[i], pre_vy[i], c, + q, p, t, 0); + sp_1024_mont_sub_avx2_16(pre_nvy[i], p1024_mod, pre_vy[i], + p1024_mod); + } + + XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 16); + c->infinity = 0; + j = sp_1024_order_op_pre[0] / 2; + XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 16); + XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 16); + + k = 0; + for (j = 0; j < sp_1024_order_op_pre[1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_avx2_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + + for (i = 2; i < 290; i += 2) { + sp_1024_accumulate_line_lc_avx2_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 0); + k++; + + j = sp_1024_order_op_pre[i]; + if (j > 0) { + j /= 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_vy[j], t); + } + else { + j = -j / 2; + /* Accumulate line into v. */ + sp_1024_proj_mul_avx2_16(vx, vy, pre_vx[j], pre_nvy[j], t); + } + + for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) { + /* Accumulate line into v and double point. */ + sp_1024_accumulate_line_lc_avx2_16(vx, vy, precomp[k].x, + precomp[k].y, q, t, 1); + k++; + } + } + + /* Final exponentiation */ + sp_1024_proj_sqr_avx2_16(vx, vy, t); + sp_1024_proj_sqr_avx2_16(vx, vy, t); + + /* Convert from PF_p[q] to F_p */ + sp_1024_mont_inv_avx2_16(vx, vx, t); + sp_1024_mont_mul_avx2_16(r, vx, vy, p1024_mod, p1024_mp_mod); + XMEMSET(r + 16, 0, sizeof(sp_digit) * 16); + sp_1024_mont_reduce_avx2_16(r, p1024_mod, p1024_mp_mod); + + err = sp_1024_to_mp(r, res); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + sp_1024_point_free_16(c, 1, NULL); + sp_1024_point_free_16(q, 1, NULL); + sp_1024_point_free_16(p, 1, NULL); + return err; +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* HAVE_INTEL_AVX2 */ +/* + * Generate table for pairing. + * + * pm [in] Point to generate table for. + * table [in] Generated table. + * len [in,out] On in, the size of the buffer. + * On out, length of table generated. + * @return 0 on success. + * Otherwise failure. + */ +int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table, word32* len) +{ + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_Pairing_gen_precomp_avx2_1024(pm, table, len); + } + else +#endif + { + err = sp_Pairing_gen_precomp_x64_1024(pm, table, len); + } + + return err; +} + +/* + * Calculate r = pairing . + * + * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q. + * + * @param [in] key SAKKE key. + * @param [in] p First point on E(F_p)[q]. + * @param [in] q Second point on E(F_p)[q]. + * @param [in] r Result of calculation. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other -ve value on internal failure. + */ +int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res, + const byte* table, word32 len) +{ + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_Pairing_precomp_avx2_1024(pm, qm, res, table, len); + } + else +#endif + { + err = sp_Pairing_precomp_x64_1024(pm, qm, res, table, len); + } + + return err; +} + +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_1024_iszero_16(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15]) == 0; +} + +#ifdef HAVE_ECC_CHECK_KEY +extern void sp_1024_from_bin_bswap(sp_digit* r, int size, const byte* a, int n); +extern void sp_1024_from_bin_movbe(sp_digit* r, int size, const byte* a, int n); +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n) +{ +#ifndef NO_MOVBE_SUPPORT + word32 cpuid_flags = cpuid_get_flags(); + + if (IS_INTEL_MOVBE(cpuid_flags)) { + sp_1024_from_bin_movbe(r, size, a, n); + } + else +#endif + { + sp_1024_from_bin_bswap(r, size, a, n); + } +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_1024_ecc_is_point_16(const sp_point_1024* point, + void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t1 = NULL; +#else + sp_digit t1[16 * 4]; +#endif + sp_digit* t2 = NULL; + int64_t n; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + err = MEMORY_E; +#endif + (void)heap; + + if (err == MP_OKAY) { + t2 = t1 + 2 * 16; + + sp_1024_sqr_16(t1, point->y); + (void)sp_1024_mod_16(t1, t1, p1024_mod); + sp_1024_sqr_16(t2, point->x); + (void)sp_1024_mod_16(t2, t2, p1024_mod); + sp_1024_mul_16(t2, t2, point->x); + (void)sp_1024_mod_16(t2, t2, p1024_mod); + (void)sp_1024_sub_16(t2, p1024_mod, t2); + sp_1024_mont_add_16(t1, t1, t2, p1024_mod); + + sp_1024_mont_add_16(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_16(t1, t1, point->x, p1024_mod); + sp_1024_mont_add_16(t1, t1, point->x, p1024_mod); + + n = sp_1024_cmp_16(t1, p1024_mod); + sp_1024_cond_sub_16(t1, t1, p1024_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_1024_norm_16(t1); + if (!sp_1024_iszero_16(t1)) { + err = MP_VAL; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t1 != NULL) + XFREE(t1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* pub = NULL; +#else + sp_point_1024 pub[1]; +#endif + const byte one[1] = { 1 }; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + sp_1024_from_mp(pub->x, 16, pX); + sp_1024_from_mp(pub->y, 16, pY); + sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one)); + + err = sp_1024_ecc_is_point_16(pub, NULL); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* priv = NULL; + sp_point_1024* pub = NULL; +#else + sp_digit priv[16]; + sp_point_1024 pub[2]; +#endif + sp_point_1024* p = NULL; + const byte one[1] = { 1 }; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + + /* Quick check the lengs of public key ordinates and private key are in + * range. Proper check later. + */ + if (((mp_count_bits(pX) > 1024) || + (mp_count_bits(pY) > 1024) || + ((privm != NULL) && (mp_count_bits(privm) > 1024)))) { + err = ECC_OUT_OF_RANGE_E; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap, + DYNAMIC_TYPE_ECC); + if (pub == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY && privm) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + p = pub + 1; + + sp_1024_from_mp(pub->x, 16, pX); + sp_1024_from_mp(pub->y, 16, pY); + sp_1024_from_bin(pub->z, 16, one, (int)sizeof(one)); + if (privm) + sp_1024_from_mp(priv, 16, privm); + + /* Check point at infinitiy. */ + if ((sp_1024_iszero_16(pub->x) != 0) && + (sp_1024_iszero_16(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + /* Check range of X and Y */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_16(pub->x, p1024_mod) >= 0) || + (sp_1024_cmp_16(pub->y, p1024_mod) >= 0))) { + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_1024_ecc_is_point_16(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_ecc_mulmod_avx2_16(p, pub, p1024_order, 1, 1, heap); + else +#endif + err = sp_1024_ecc_mulmod_16(p, pub, p1024_order, 1, 1, heap); + } + /* Check result is infinity */ + if ((err == MP_OKAY) && ((sp_1024_iszero_16(p->x) == 0) || + (sp_1024_iszero_16(p->y) == 0))) { + err = ECC_INF_E; + } + + if (privm) { + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_1024_ecc_mulmod_base_avx2_16(p, priv, 1, 1, heap); + else +#endif + err = sp_1024_ecc_mulmod_base_16(p, priv, 1, 1, heap); + } + /* Check result is public key */ + if ((err == MP_OKAY) && + ((sp_1024_cmp_16(p->x, pub->x) != 0) || + (sp_1024_cmp_16(p->y, pub->y) != 0))) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (pub != NULL) + XFREE(pub, heap, DYNAMIC_TYPE_ECC); + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_1024 */ #endif /* WOLFSSL_HAVE_SP_ECC */ #endif /* WOLFSSL_SP_X86_64_ASM */ -#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/sp_x86_64_asm.S b/wolfcrypt/src/sp_x86_64_asm.S index ca8c76d6e..b9cd89783 100644 --- a/wolfcrypt/src/sp_x86_64_asm.S +++ b/wolfcrypt/src/sp_x86_64_asm.S @@ -1,6 +1,6 @@ /* sp_x86_64_asm * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -26,6 +26,7 @@ #define HAVE_INTEL_AVX2 #endif /* NO_AVX2_SUPPORT */ +#ifdef WOLFSSL_SP_X86_64_ASM #ifndef WOLFSSL_SP_NO_2048 #ifndef WOLFSSL_SP_NO_2048 /* Read big endian unsigned byte array into r. @@ -122,6 +123,7 @@ L_2048_from_bin_bswap_zero_end: #ifndef __APPLE__ .size sp_2048_from_bin_bswap,.-sp_2048_from_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Read big endian unsigned byte array into r. * Uses the movbe instruction which is an optional instruction. * @@ -207,6 +209,7 @@ L_2048_from_bin_movbe_zero_end: #ifndef __APPLE__ .size sp_2048_from_bin_movbe,.-sp_2048_from_bin_movbe #endif /* __APPLE__ */ +#endif /* !NO_MOVBE_SUPPORT */ /* Write r as big endian to byte array. * Fixed length number of bytes written: 256 * Uses the bswap instruction. @@ -326,6 +329,7 @@ _sp_2048_to_bin_bswap: #ifndef __APPLE__ .size sp_2048_to_bin_bswap,.-sp_2048_to_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Write r as big endian to byte array. * Fixed length number of bytes written: 256 * Uses the movbe instruction which is optional. @@ -413,6 +417,7 @@ _sp_2048_to_bin_movbe: #ifndef __APPLE__ .size sp_2048_to_bin_movbe,.-sp_2048_to_bin_movbe #endif /* __APPLE__ */ +#endif /* NO_MOVBE_SUPPORT */ /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -3190,6 +3195,7 @@ _sp_2048_mul_avx2_16: cmovne %rdi, %rbx cmpq %rdi, %rbp cmove %rsp, %rbx + addq $0x80, %rdi xorq %r14, %r14 movq (%rsi), %rdx # A[0] * B[0] @@ -3258,7 +3264,7 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adcxq %r14, %r13 movq %r8, 120(%rbx) - movq %r9, 128(%rdi) + movq %r9, (%rdi) movq 8(%rsi), %rdx movq 8(%rbx), %r9 movq 16(%rbx), %r10 @@ -3335,7 +3341,7 @@ _sp_2048_mul_avx2_16: movq %r10, 96(%rbx) movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 + movq (%rdi), %r9 # A[1] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r11 @@ -3360,8 +3366,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r9, 128(%rdi) - movq %r10, 136(%rdi) + movq %r9, (%rdi) + movq %r10, 8(%rdi) movq 16(%rsi), %rdx movq 16(%rbx), %r10 movq 24(%rbx), %r11 @@ -3437,8 +3443,8 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r12 movq %r11, 104(%rbx) movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq (%rdi), %r9 + movq 8(%rdi), %r10 # A[2] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r12 @@ -3455,7 +3461,7 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[2] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) movq %r14, %r11 adcxq %rax, %r10 adoxq %rcx, %r11 @@ -3463,8 +3469,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r10, 136(%rdi) - movq %r11, 144(%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) movq 24(%rsi), %rdx movq 24(%rbx), %r11 movq 32(%rbx), %r12 @@ -3539,9 +3545,9 @@ _sp_2048_mul_avx2_16: adcxq %rax, %r12 adoxq %rcx, %r8 movq %r12, 112(%rbx) - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 # A[3] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r8 @@ -3553,12 +3559,12 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[3] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[3] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) movq %r14, %r12 adcxq %rax, %r11 adoxq %rcx, %r12 @@ -3566,8 +3572,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r11, 144(%rdi) - movq %r12, 152(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) movq 32(%rsi), %rdx movq 32(%rbx), %r12 movq 40(%rbx), %r8 @@ -3621,7 +3627,7 @@ _sp_2048_mul_avx2_16: movq 104(%rbx), %r11 movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 + movq (%rdi), %r9 # A[4] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -3642,26 +3648,26 @@ _sp_2048_mul_avx2_16: adcxq %rax, %r8 adoxq %rcx, %r9 movq %r8, 120(%rbx) - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 # A[4] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[4] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[4] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[4] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) movq %r14, %r8 adcxq %rax, %r12 adoxq %rcx, %r8 @@ -3669,8 +3675,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r12, 152(%rdi) - movq %r8, 160(%rdi) + movq %r12, 24(%rdi) + movq %r8, 32(%rdi) movq 40(%rsi), %rdx movq 40(%rbx), %r8 movq 48(%rbx), %r9 @@ -3723,8 +3729,8 @@ _sp_2048_mul_avx2_16: movq %r10, 96(%rbx) movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq (%rdi), %r9 + movq 8(%rdi), %r10 # A[5] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r11 @@ -3744,27 +3750,27 @@ _sp_2048_mul_avx2_16: movq %r8, 120(%rbx) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 128(%rdi) - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 + movq %r9, (%rdi) + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 # A[5] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r11 # A[5] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[5] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[5] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) movq %r14, %r9 adcxq %rax, %r8 adoxq %rcx, %r9 @@ -3772,8 +3778,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r8, 160(%rdi) - movq %r9, 168(%rdi) + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) movq 48(%rsi), %rdx movq 48(%rbx), %r9 movq 56(%rbx), %r10 @@ -3825,9 +3831,9 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r12 movq %r11, 104(%rbx) movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 # A[6] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r12 @@ -3844,30 +3850,30 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[6] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 - movq %r10, 136(%rdi) - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 + movq %r10, 8(%rdi) + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 # A[6] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r11 adoxq %rcx, %r12 # A[6] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[6] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[6] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) movq %r14, %r10 adcxq %rax, %r9 adoxq %rcx, %r10 @@ -3875,8 +3881,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r9, 168(%rdi) - movq %r10, 176(%rdi) + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) movq 56(%rsi), %rdx movq 56(%rbx), %r10 movq 64(%rbx), %r11 @@ -3927,10 +3933,10 @@ _sp_2048_mul_avx2_16: adcxq %rax, %r12 adoxq %rcx, %r8 movq %r12, 112(%rbx) - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 # A[7] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r8 @@ -3942,35 +3948,35 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[7] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[7] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 - movq %r11, 144(%rdi) - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 + movq %r11, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 # A[7] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r12 adoxq %rcx, %r8 # A[7] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[7] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[7] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) movq %r14, %r11 adcxq %rax, %r10 adoxq %rcx, %r11 @@ -3978,8 +3984,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r10, 176(%rdi) - movq %r11, 184(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) movq 64(%rsi), %rdx movq 64(%rbx), %r11 movq 72(%rbx), %r12 @@ -4009,7 +4015,7 @@ _sp_2048_mul_avx2_16: movq 104(%rbx), %r11 movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 + movq (%rdi), %r9 # A[8] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -4030,50 +4036,50 @@ _sp_2048_mul_avx2_16: adcxq %rax, %r8 adoxq %rcx, %r9 movq %r8, 120(%rbx) - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 # A[8] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[8] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[8] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[8] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 - movq %r12, 152(%rdi) - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 - movq 184(%rdi), %r11 + movq %r12, 24(%rdi) + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 # A[8] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[8] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[8] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[8] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r10, 176(%rdi) + movq %r10, 48(%rdi) movq %r14, %r12 adcxq %rax, %r11 adoxq %rcx, %r12 @@ -4081,8 +4087,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r11, 184(%rdi) - movq %r12, 192(%rdi) + movq %r11, 56(%rdi) + movq %r12, 64(%rdi) movq 72(%rsi), %rdx movq 72(%rbx), %r12 movq 80(%rbx), %r8 @@ -4111,8 +4117,8 @@ _sp_2048_mul_avx2_16: movq %r10, 96(%rbx) movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq (%rdi), %r9 + movq 8(%rdi), %r10 # A[9] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r11 @@ -4132,51 +4138,51 @@ _sp_2048_mul_avx2_16: movq %r8, 120(%rbx) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 128(%rdi) - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 + movq %r9, (%rdi) + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 # A[9] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r11 # A[9] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[9] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[9] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 160(%rdi) - movq 176(%rdi), %r10 - movq 184(%rdi), %r11 - movq 192(%rdi), %r12 + movq %r8, 32(%rdi) + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 # A[9] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[9] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[9] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r10, 176(%rdi) + movq %r10, 48(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[9] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r11, 184(%rdi) + movq %r11, 56(%rdi) movq %r14, %r8 adcxq %rax, %r12 adoxq %rcx, %r8 @@ -4184,8 +4190,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r12, 192(%rdi) - movq %r8, 200(%rdi) + movq %r12, 64(%rdi) + movq %r8, 72(%rdi) movq 80(%rsi), %rdx movq 80(%rbx), %r8 movq 88(%rbx), %r9 @@ -4213,9 +4219,9 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r12 movq %r11, 104(%rbx) movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 # A[10] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r12 @@ -4232,54 +4238,54 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[10] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 - movq %r10, 136(%rdi) - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 + movq %r10, 8(%rdi) + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 # A[10] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r11 adoxq %rcx, %r12 # A[10] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[10] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[10] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 168(%rdi) - movq 184(%rdi), %r11 - movq 192(%rdi), %r12 - movq 200(%rdi), %r8 + movq %r9, 40(%rdi) + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 # A[10] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r11 # A[10] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r10, 176(%rdi) + movq %r10, 48(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[10] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r11, 184(%rdi) + movq %r11, 56(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[10] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r12, 192(%rdi) + movq %r12, 64(%rdi) movq %r14, %r9 adcxq %rax, %r8 adoxq %rcx, %r9 @@ -4287,8 +4293,8 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r8, 200(%rdi) - movq %r9, 208(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) movq 88(%rsi), %rdx movq 88(%rbx), %r9 movq 96(%rbx), %r10 @@ -4315,10 +4321,10 @@ _sp_2048_mul_avx2_16: adcxq %rax, %r12 adoxq %rcx, %r8 movq %r12, 112(%rbx) - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 # A[11] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r8 @@ -4330,59 +4336,59 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[11] * B[6] mulx 48(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[11] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 - movq %r11, 144(%rdi) - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 - movq 184(%rdi), %r11 + movq %r11, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 # A[11] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r12 adoxq %rcx, %r8 # A[11] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[11] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[11] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 - movq %r10, 176(%rdi) - movq 192(%rdi), %r12 - movq 200(%rdi), %r8 - movq 208(%rdi), %r9 + movq %r10, 48(%rdi) + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 # A[11] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r11 adoxq %rcx, %r12 # A[11] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r11, 184(%rdi) + movq %r11, 56(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[11] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r12, 192(%rdi) + movq %r12, 64(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[11] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r8, 200(%rdi) + movq %r8, 72(%rdi) movq %r14, %r10 adcxq %rax, %r9 adoxq %rcx, %r10 @@ -4390,14 +4396,14 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r9, 208(%rdi) - movq %r10, 216(%rdi) + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) movq 96(%rsi), %rdx movq 96(%rbx), %r10 movq 104(%rbx), %r11 movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 + movq (%rdi), %r9 # A[12] * B[0] mulx (%rbp), %rax, %rcx adcxq %rax, %r10 @@ -4418,74 +4424,74 @@ _sp_2048_mul_avx2_16: adcxq %rax, %r8 adoxq %rcx, %r9 movq %r8, 120(%rbx) - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 # A[12] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[12] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[12] * B[6] mulx 48(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[12] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 - movq %r12, 152(%rdi) - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 - movq 184(%rdi), %r11 - movq 192(%rdi), %r12 + movq %r12, 24(%rdi) + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 # A[12] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[12] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[12] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[12] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r10, 176(%rdi) + movq %r10, 48(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 - movq %r11, 184(%rdi) - movq 200(%rdi), %r8 - movq 208(%rdi), %r9 - movq 216(%rdi), %r10 + movq %r11, 56(%rdi) + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 + movq 88(%rdi), %r10 # A[12] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r12 adoxq %rcx, %r8 # A[12] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r12, 192(%rdi) + movq %r12, 64(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[12] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r8, 200(%rdi) + movq %r8, 72(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[12] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r9, 208(%rdi) + movq %r9, 80(%rdi) movq %r14, %r11 adcxq %rax, %r10 adoxq %rcx, %r11 @@ -4493,14 +4499,14 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r10, 216(%rdi) - movq %r11, 224(%rdi) + movq %r10, 88(%rdi) + movq %r11, 96(%rdi) movq 104(%rsi), %rdx movq 104(%rbx), %r11 movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq (%rdi), %r9 + movq 8(%rdi), %r10 # A[13] * B[0] mulx (%rbp), %rax, %rcx adcxq %rax, %r11 @@ -4520,75 +4526,75 @@ _sp_2048_mul_avx2_16: movq %r8, 120(%rbx) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 128(%rdi) - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 + movq %r9, (%rdi) + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 # A[13] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r11 # A[13] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[13] * B[6] mulx 48(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[13] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 160(%rdi) - movq 176(%rdi), %r10 - movq 184(%rdi), %r11 - movq 192(%rdi), %r12 - movq 200(%rdi), %r8 + movq %r8, 32(%rdi) + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 # A[13] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[13] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[13] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r10, 176(%rdi) + movq %r10, 48(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[13] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r11, 184(%rdi) + movq %r11, 56(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 - movq %r12, 192(%rdi) - movq 208(%rdi), %r9 - movq 216(%rdi), %r10 - movq 224(%rdi), %r11 + movq %r12, 64(%rdi) + movq 80(%rdi), %r9 + movq 88(%rdi), %r10 + movq 96(%rdi), %r11 # A[13] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[13] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r8, 200(%rdi) + movq %r8, 72(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[13] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r9, 208(%rdi) + movq %r9, 80(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[13] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r10, 216(%rdi) + movq %r10, 88(%rdi) movq %r14, %r12 adcxq %rax, %r11 adoxq %rcx, %r12 @@ -4596,14 +4602,14 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r11, 224(%rdi) - movq %r12, 232(%rdi) + movq %r11, 96(%rdi) + movq %r12, 104(%rdi) movq 112(%rsi), %rdx movq 112(%rbx), %r12 movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 # A[14] * B[0] mulx (%rbp), %rax, %rcx adcxq %rax, %r12 @@ -4620,78 +4626,78 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[14] * B[3] mulx 24(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 - movq %r10, 136(%rdi) - movq 152(%rdi), %r12 - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 + movq %r10, 8(%rdi) + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 # A[14] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r11 adoxq %rcx, %r12 # A[14] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r11, 144(%rdi) + movq %r11, 16(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[14] * B[6] mulx 48(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[14] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 168(%rdi) - movq 184(%rdi), %r11 - movq 192(%rdi), %r12 - movq 200(%rdi), %r8 - movq 208(%rdi), %r9 + movq %r9, 40(%rdi) + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 # A[14] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r11 # A[14] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r10, 176(%rdi) + movq %r10, 48(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[14] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r11, 184(%rdi) + movq %r11, 56(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[14] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r12, 192(%rdi) + movq %r12, 64(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 200(%rdi) - movq 216(%rdi), %r10 - movq 224(%rdi), %r11 - movq 232(%rdi), %r12 + movq %r8, 72(%rdi) + movq 88(%rdi), %r10 + movq 96(%rdi), %r11 + movq 104(%rdi), %r12 # A[14] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[14] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r9, 208(%rdi) + movq %r9, 80(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[14] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r10, 216(%rdi) + movq %r10, 88(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[14] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r11, 224(%rdi) + movq %r11, 96(%rdi) movq %r14, %r8 adcxq %rax, %r12 adoxq %rcx, %r8 @@ -4699,14 +4705,14 @@ _sp_2048_mul_avx2_16: movq %r14, %r13 adoxq %r14, %r13 adcxq %r14, %r13 - movq %r12, 232(%rdi) - movq %r8, 240(%rdi) + movq %r12, 104(%rdi) + movq %r8, 112(%rdi) movq 120(%rsi), %rdx movq 120(%rbx), %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 - movq 144(%rdi), %r11 - movq 152(%rdi), %r12 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 # A[15] * B[0] mulx (%rbp), %rax, %rcx adcxq %rax, %r8 @@ -4718,89 +4724,90 @@ _sp_2048_mul_avx2_16: adoxq %rcx, %r10 # A[15] * B[2] mulx 16(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, (%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 # A[15] * B[3] mulx 24(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 - movq %r11, 144(%rdi) - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 - movq 176(%rdi), %r10 - movq 184(%rdi), %r11 + movq %r11, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 # A[15] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r12 adoxq %rcx, %r8 # A[15] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r12, 152(%rdi) + movq %r12, 24(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[15] * B[6] mulx 48(%rbp), %rax, %rcx - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 # A[15] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r9, 168(%rdi) + movq %r9, 40(%rdi) adcxq %rax, %r10 adoxq %rcx, %r11 - movq %r10, 176(%rdi) - movq 192(%rdi), %r12 - movq 200(%rdi), %r8 - movq 208(%rdi), %r9 - movq 216(%rdi), %r10 + movq %r10, 48(%rdi) + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 + movq 88(%rdi), %r10 # A[15] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r11 adoxq %rcx, %r12 # A[15] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r11, 184(%rdi) + movq %r11, 56(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[15] * B[10] mulx 80(%rbp), %rax, %rcx - movq %r12, 192(%rdi) + movq %r12, 64(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 # A[15] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r8, 200(%rdi) + movq %r8, 72(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 208(%rdi) - movq 224(%rdi), %r11 - movq 232(%rdi), %r12 - movq 240(%rdi), %r8 + movq %r9, 80(%rdi) + movq 96(%rdi), %r11 + movq 104(%rdi), %r12 + movq 112(%rdi), %r8 # A[15] * B[12] mulx 96(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r11 # A[15] * B[13] mulx 104(%rbp), %rax, %rcx - movq %r10, 216(%rdi) + movq %r10, 88(%rdi) adcxq %rax, %r11 adoxq %rcx, %r12 # A[15] * B[14] mulx 112(%rbp), %rax, %rcx - movq %r11, 224(%rdi) + movq %r11, 96(%rdi) adcxq %rax, %r12 adoxq %rcx, %r8 # A[15] * B[15] mulx 120(%rbp), %rax, %rcx - movq %r12, 232(%rdi) + movq %r12, 104(%rdi) movq %r14, %r9 adcxq %rax, %r8 adoxq %rcx, %r9 adcxq %r13, %r9 - movq %r8, 240(%rdi) - movq %r9, 248(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + subq $0x80, %rdi cmpq %rdi, %rsi je L_start_2048_mul_avx2_16 cmpq %rdi, %rbp @@ -4862,6 +4869,7 @@ _sp_2048_sqr_avx2_16: cmpq %rdi, %rsi movq %rsp, %rbp cmovne %rdi, %rbp + addq $0x80, %rdi xorq %r11, %r11 # Diagonal 1 xorq %r10, %r10 @@ -4957,7 +4965,7 @@ _sp_2048_sqr_avx2_16: movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 128(%rdi) + movq %r8, (%rdi) # Diagonal 2 movq 24(%rbp), %r8 movq 32(%rbp), %r9 @@ -5033,7 +5041,7 @@ _sp_2048_sqr_avx2_16: adoxq %rcx, %rbx # No store %r14 # No store %r15 - movq 128(%rdi), %r9 + movq (%rdi), %r9 movq %r11, %r10 # A[14] x A[1] mulxq 112(%rsi), %rax, %rcx @@ -5044,20 +5052,20 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r9 adoxq %rcx, %r10 # No store %rbx - movq %r9, 128(%rdi) + movq %r9, (%rdi) movq %r11, %r8 # A[15] x A[2] movq 16(%rsi), %rdx mulxq 120(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 136(%rdi) + movq %r10, 8(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 144(%rdi) + movq %r8, 16(%rdi) # Diagonal 3 movq 40(%rbp), %r8 movq 48(%rbp), %r9 @@ -5120,8 +5128,8 @@ _sp_2048_sqr_avx2_16: adoxq %rcx, %rbx # No store %r14 # No store %r15 - movq 128(%rdi), %r10 - movq 136(%rdi), %r8 + movq (%rdi), %r10 + movq 8(%rdi), %r8 # A[13] x A[2] mulxq 104(%rsi), %rax, %rcx adcxq %rax, %rbx @@ -5131,8 +5139,8 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r10 adoxq %rcx, %r8 # No store %rbx - movq %r10, 128(%rdi) - movq 144(%rdi), %r9 + movq %r10, (%rdi) + movq 16(%rdi), %r9 movq %r11, %r10 # A[14] x A[3] movq 112(%rsi), %rdx @@ -5143,20 +5151,20 @@ _sp_2048_sqr_avx2_16: mulxq 32(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 136(%rdi) - movq %r9, 144(%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) movq %r11, %r8 # A[14] x A[5] mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 152(%rdi) + movq %r10, 24(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 160(%rdi) + movq %r8, 32(%rdi) # Diagonal 4 movq 56(%rbp), %r8 movq 64(%rbp), %r9 @@ -5208,8 +5216,8 @@ _sp_2048_sqr_avx2_16: adoxq %rcx, %rbx # No store %r14 # No store %r15 - movq 128(%rdi), %r8 - movq 136(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[12] x A[3] mulxq 96(%rsi), %rax, %rcx adcxq %rax, %rbx @@ -5219,9 +5227,9 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r8 adoxq %rcx, %r9 # No store %rbx - movq %r8, 128(%rdi) - movq 144(%rdi), %r10 - movq 152(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 # A[13] x A[4] movq 104(%rsi), %rdx mulxq 32(%rsi), %rax, %rcx @@ -5231,9 +5239,9 @@ _sp_2048_sqr_avx2_16: mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 136(%rdi) - movq %r10, 144(%rdi) - movq 160(%rdi), %r9 + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 movq %r11, %r10 # A[13] x A[6] mulxq 48(%rsi), %rax, %rcx @@ -5243,20 +5251,20 @@ _sp_2048_sqr_avx2_16: mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 152(%rdi) - movq %r9, 160(%rdi) + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) movq %r11, %r8 # A[13] x A[8] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 168(%rdi) + movq %r10, 40(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 176(%rdi) + movq %r8, 48(%rdi) # Diagonal 5 movq 72(%rbp), %r8 movq 80(%rbp), %r9 @@ -5296,8 +5304,8 @@ _sp_2048_sqr_avx2_16: adoxq %rcx, %rbx # No store %r14 # No store %r15 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq (%rdi), %r9 + movq 8(%rdi), %r10 # A[11] x A[4] mulxq 88(%rsi), %rax, %rcx adcxq %rax, %rbx @@ -5307,9 +5315,9 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r9 adoxq %rcx, %r10 # No store %rbx - movq %r9, 128(%rdi) - movq 144(%rdi), %r8 - movq 152(%rdi), %r9 + movq %r9, (%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 # A[12] x A[5] movq 96(%rsi), %rdx mulxq 40(%rsi), %rax, %rcx @@ -5319,10 +5327,10 @@ _sp_2048_sqr_avx2_16: mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r10, 136(%rdi) - movq %r8, 144(%rdi) - movq 160(%rdi), %r10 - movq 168(%rdi), %r8 + movq %r10, 8(%rdi) + movq %r8, 16(%rdi) + movq 32(%rdi), %r10 + movq 40(%rdi), %r8 # A[12] x A[7] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r9 @@ -5331,9 +5339,9 @@ _sp_2048_sqr_avx2_16: mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 152(%rdi) - movq %r10, 160(%rdi) - movq 176(%rdi), %r9 + movq %r9, 24(%rdi) + movq %r10, 32(%rdi) + movq 48(%rdi), %r9 movq %r11, %r10 # A[12] x A[9] mulxq 72(%rsi), %rax, %rcx @@ -5343,20 +5351,20 @@ _sp_2048_sqr_avx2_16: mulxq 80(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 168(%rdi) - movq %r9, 176(%rdi) + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) movq %r11, %r8 # A[12] x A[11] mulxq 88(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 184(%rdi) + movq %r10, 56(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 192(%rdi) + movq %r8, 64(%rdi) # Diagonal 6 movq 88(%rbp), %r8 # No load %r13 - %r9 @@ -5384,8 +5392,8 @@ _sp_2048_sqr_avx2_16: adoxq %rcx, %rbx # No store %r14 # No store %r15 - movq 128(%rdi), %r10 - movq 136(%rdi), %r8 + movq (%rdi), %r10 + movq 8(%rdi), %r8 # A[10] x A[5] mulxq 80(%rsi), %rax, %rcx adcxq %rax, %rbx @@ -5395,9 +5403,9 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r10 adoxq %rcx, %r8 # No store %rbx - movq %r10, 128(%rdi) - movq 144(%rdi), %r9 - movq 152(%rdi), %r10 + movq %r10, (%rdi) + movq 16(%rdi), %r9 + movq 24(%rdi), %r10 # A[11] x A[6] movq 88(%rsi), %rdx mulxq 48(%rsi), %rax, %rcx @@ -5407,10 +5415,10 @@ _sp_2048_sqr_avx2_16: mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 136(%rdi) - movq %r9, 144(%rdi) - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 # A[11] x A[8] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r10 @@ -5419,10 +5427,10 @@ _sp_2048_sqr_avx2_16: mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r10, 152(%rdi) - movq %r8, 160(%rdi) - movq 176(%rdi), %r10 - movq 184(%rdi), %r8 + movq %r10, 24(%rdi) + movq %r8, 32(%rdi) + movq 48(%rdi), %r10 + movq 56(%rdi), %r8 # A[11] x A[10] mulxq 80(%rsi), %rax, %rcx adcxq %rax, %r9 @@ -5432,9 +5440,9 @@ _sp_2048_sqr_avx2_16: mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 168(%rdi) - movq %r10, 176(%rdi) - movq 192(%rdi), %r9 + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq 64(%rdi), %r9 movq %r11, %r10 # A[13] x A[10] mulxq 80(%rsi), %rax, %rcx @@ -5444,20 +5452,20 @@ _sp_2048_sqr_avx2_16: mulxq 88(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 184(%rdi) - movq %r9, 192(%rdi) + movq %r8, 56(%rdi) + movq %r9, 64(%rdi) movq %r11, %r8 # A[13] x A[12] mulxq 96(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 200(%rdi) + movq %r10, 72(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 208(%rdi) + movq %r8, 80(%rdi) # Diagonal 7 # No load %r14 - %r8 # No load %r15 - %r9 @@ -5473,8 +5481,8 @@ _sp_2048_sqr_avx2_16: adoxq %rcx, %rbx # No store %r14 # No store %r15 - movq 128(%rdi), %r8 - movq 136(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[9] x A[6] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %rbx @@ -5484,9 +5492,9 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r8 adoxq %rcx, %r9 # No store %rbx - movq %r8, 128(%rdi) - movq 144(%rdi), %r10 - movq 152(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 # A[10] x A[7] movq 80(%rsi), %rdx mulxq 56(%rsi), %rax, %rcx @@ -5496,10 +5504,10 @@ _sp_2048_sqr_avx2_16: mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 136(%rdi) - movq %r10, 144(%rdi) - movq 160(%rdi), %r9 - movq 168(%rdi), %r10 + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 # A[10] x A[9] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r8 @@ -5509,10 +5517,10 @@ _sp_2048_sqr_avx2_16: mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 152(%rdi) - movq %r9, 160(%rdi) - movq 176(%rdi), %r8 - movq 184(%rdi), %r9 + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 # A[14] x A[7] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r10 @@ -5521,10 +5529,10 @@ _sp_2048_sqr_avx2_16: mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r10, 168(%rdi) - movq %r8, 176(%rdi) - movq 192(%rdi), %r10 - movq 200(%rdi), %r8 + movq %r10, 40(%rdi) + movq %r8, 48(%rdi) + movq 64(%rdi), %r10 + movq 72(%rdi), %r8 # A[14] x A[9] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r9 @@ -5533,9 +5541,9 @@ _sp_2048_sqr_avx2_16: mulxq 80(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 184(%rdi) - movq %r10, 192(%rdi) - movq 208(%rdi), %r9 + movq %r9, 56(%rdi) + movq %r10, 64(%rdi) + movq 80(%rdi), %r9 movq %r11, %r10 # A[14] x A[11] mulxq 88(%rsi), %rax, %rcx @@ -5545,24 +5553,24 @@ _sp_2048_sqr_avx2_16: mulxq 96(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 200(%rdi) - movq %r9, 208(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) movq %r11, %r8 # A[14] x A[13] mulxq 104(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 216(%rdi) + movq %r10, 88(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 224(%rdi) + movq %r8, 96(%rdi) # Diagonal 8 # No load %rbx - %r8 - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq (%rdi), %r9 + movq 8(%rdi), %r10 # A[8] x A[7] movq 56(%rsi), %rdx mulxq 64(%rsi), %rax, %rcx @@ -5573,9 +5581,9 @@ _sp_2048_sqr_avx2_16: adcxq %rax, %r9 adoxq %rcx, %r10 # No store %rbx - movq %r9, 128(%rdi) - movq 144(%rdi), %r8 - movq 152(%rdi), %r9 + movq %r9, (%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 # A[9] x A[8] movq 64(%rsi), %rdx mulxq 72(%rsi), %rax, %rcx @@ -5586,10 +5594,10 @@ _sp_2048_sqr_avx2_16: mulxq 24(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r10, 136(%rdi) - movq %r8, 144(%rdi) - movq 160(%rdi), %r10 - movq 168(%rdi), %r8 + movq %r10, 8(%rdi) + movq %r8, 16(%rdi) + movq 32(%rdi), %r10 + movq 40(%rdi), %r8 # A[15] x A[4] mulxq 32(%rsi), %rax, %rcx adcxq %rax, %r9 @@ -5598,10 +5606,10 @@ _sp_2048_sqr_avx2_16: mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 152(%rdi) - movq %r10, 160(%rdi) - movq 176(%rdi), %r9 - movq 184(%rdi), %r10 + movq %r9, 24(%rdi) + movq %r10, 32(%rdi) + movq 48(%rdi), %r9 + movq 56(%rdi), %r10 # A[15] x A[6] mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r8 @@ -5610,10 +5618,10 @@ _sp_2048_sqr_avx2_16: mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 168(%rdi) - movq %r9, 176(%rdi) - movq 192(%rdi), %r8 - movq 200(%rdi), %r9 + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq 64(%rdi), %r8 + movq 72(%rdi), %r9 # A[15] x A[8] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r10 @@ -5622,10 +5630,10 @@ _sp_2048_sqr_avx2_16: mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r10, 184(%rdi) - movq %r8, 192(%rdi) - movq 208(%rdi), %r10 - movq 216(%rdi), %r8 + movq %r10, 56(%rdi) + movq %r8, 64(%rdi) + movq 80(%rdi), %r10 + movq 88(%rdi), %r8 # A[15] x A[10] mulxq 80(%rsi), %rax, %rcx adcxq %rax, %r9 @@ -5634,9 +5642,9 @@ _sp_2048_sqr_avx2_16: mulxq 88(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r9, 200(%rdi) - movq %r10, 208(%rdi) - movq 224(%rdi), %r9 + movq %r9, 72(%rdi) + movq %r10, 80(%rdi) + movq 96(%rdi), %r9 movq %r11, %r10 # A[15] x A[12] mulxq 96(%rsi), %rax, %rcx @@ -5646,21 +5654,21 @@ _sp_2048_sqr_avx2_16: mulxq 104(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r8, 216(%rdi) - movq %r9, 224(%rdi) + movq %r8, 88(%rdi) + movq %r9, 96(%rdi) movq %r11, %r8 # A[15] x A[14] mulxq 112(%rsi), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 232(%rdi) + movq %r10, 104(%rdi) # Carry adcxq %r12, %r8 movq %r11, %r12 adcxq %r11, %r12 adoxq %r11, %r12 - movq %r8, 240(%rdi) - movq %r12, 248(%rdi) + movq %r8, 112(%rdi) + movq %r12, 120(%rdi) # Double and Add in A[i] x A[i] movq 8(%rbp), %r9 # A[0] x A[0] @@ -5739,8 +5747,8 @@ _sp_2048_sqr_avx2_16: adoxq %rbx, %rbx adcxq %rax, %r15 adcxq %rcx, %rbx - movq 128(%rdi), %r8 - movq 136(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[8] x A[8] movq 64(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5748,10 +5756,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 128(%rdi) - movq %r9, 136(%rdi) - movq 144(%rdi), %r8 - movq 152(%rdi), %r9 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 # A[9] x A[9] movq 72(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5759,10 +5767,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 144(%rdi) - movq %r9, 152(%rdi) - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 # A[10] x A[10] movq 80(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5770,10 +5778,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 160(%rdi) - movq %r9, 168(%rdi) - movq 176(%rdi), %r8 - movq 184(%rdi), %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 # A[11] x A[11] movq 88(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5781,10 +5789,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 176(%rdi) - movq %r9, 184(%rdi) - movq 192(%rdi), %r8 - movq 200(%rdi), %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rdi), %r8 + movq 72(%rdi), %r9 # A[12] x A[12] movq 96(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5792,10 +5800,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 192(%rdi) - movq %r9, 200(%rdi) - movq 208(%rdi), %r8 - movq 216(%rdi), %r9 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq 80(%rdi), %r8 + movq 88(%rdi), %r9 # A[13] x A[13] movq 104(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5803,10 +5811,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 208(%rdi) - movq %r9, 216(%rdi) - movq 224(%rdi), %r8 - movq 232(%rdi), %r9 + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 # A[14] x A[14] movq 112(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5814,10 +5822,10 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 224(%rdi) - movq %r9, 232(%rdi) - movq 240(%rdi), %r8 - movq 248(%rdi), %r9 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq 112(%rdi), %r8 + movq 120(%rdi), %r9 # A[15] x A[15] movq 120(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -5825,12 +5833,13 @@ _sp_2048_sqr_avx2_16: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 240(%rdi) - movq %r9, 248(%rdi) - movq %r13, 96(%rdi) - movq %r14, 104(%rdi) - movq %r15, 112(%rdi) - movq %rbx, 120(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq %r13, -32(%rdi) + movq %r14, -24(%rdi) + movq %r15, -16(%rdi) + movq %rbx, -8(%rdi) + subq $0x80, %rdi cmpq %rdi, %rsi jne L_end_2048_sqr_avx2_16 vmovdqu (%rbp), %xmm0 @@ -6331,6 +6340,11 @@ _sp_2048_mul_32: #else callq _sp_2048_mul_16 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 784(%rsp), %rdx + movq 776(%rsp), %rsi + movq 768(%rsp), %rdi +#endif /* _WIN64 */ movq 792(%rsp), %r13 movq 800(%rsp), %r14 movq 768(%rsp), %r15 @@ -7059,6 +7073,10 @@ _sp_2048_sqr_32: #else callq _sp_2048_sqr_16 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 648(%rsp), %rsi + movq 640(%rsp), %rdi +#endif /* _WIN64 */ movq 656(%rsp), %r10 leaq 512(%rsp), %r8 movq %r10, %rcx @@ -7560,6 +7578,7 @@ _sp_2048_sqr_32: #ifndef __APPLE__ .size sp_2048_sqr_32,.-sp_2048_sqr_32 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -7720,6 +7739,11 @@ _sp_2048_mul_avx2_32: #else callq _sp_2048_mul_avx2_16 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 784(%rsp), %rdx + movq 776(%rsp), %rsi + movq 768(%rsp), %rdi +#endif /* _WIN64 */ movq 792(%rsp), %r13 movq 800(%rsp), %r14 movq 768(%rsp), %r15 @@ -8233,6 +8257,8 @@ _sp_2048_mul_avx2_32: #ifndef __APPLE__ .size sp_2048_mul_avx2_32,.-sp_2048_mul_avx2_32 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square a and put result in r. (r = a * a) * * r A single precision integer. @@ -8329,6 +8355,10 @@ _sp_2048_sqr_avx2_32: #else callq _sp_2048_sqr_avx2_16 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 648(%rsp), %rsi + movq 640(%rsp), %rdi +#endif /* _WIN64 */ movq 656(%rsp), %r10 leaq 512(%rsp), %r8 movq %r10, %rcx @@ -8798,6 +8828,78 @@ _sp_2048_sqr_avx2_32: #ifndef __APPLE__ .size sp_2048_sqr_avx2_32,.-sp_2048_sqr_avx2_32 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_2048_sub_in_place_16 +.type sp_2048_sub_in_place_16,@function +.align 16 +sp_2048_sub_in_place_16: +#else +.section __TEXT,__text +.globl _sp_2048_sub_in_place_16 +.p2align 4 +_sp_2048_sub_in_place_16: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq %rcx, 120(%rdi) + sbbq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_sub_in_place_16,.-sp_2048_sub_in_place_16 +#endif /* __APPLE__ */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -9075,77 +9177,6 @@ _sp_2048_mul_d_32: #ifndef __APPLE__ .size sp_2048_mul_d_32,.-sp_2048_mul_d_32 #endif /* __APPLE__ */ -/* Sub b from a into a. (a -= b) - * - * a A single precision integer and result. - * b A single precision integer. - */ -#ifndef __APPLE__ -.text -.globl sp_2048_sub_in_place_16 -.type sp_2048_sub_in_place_16,@function -.align 16 -sp_2048_sub_in_place_16: -#else -.section __TEXT,__text -.globl _sp_2048_sub_in_place_16 -.p2align 4 -_sp_2048_sub_in_place_16: -#endif /* __APPLE__ */ - movq (%rdi), %rdx - xorq %rax, %rax - subq (%rsi), %rdx - movq 8(%rdi), %rcx - movq %rdx, (%rdi) - sbbq 8(%rsi), %rcx - movq 16(%rdi), %rdx - movq %rcx, 8(%rdi) - sbbq 16(%rsi), %rdx - movq 24(%rdi), %rcx - movq %rdx, 16(%rdi) - sbbq 24(%rsi), %rcx - movq 32(%rdi), %rdx - movq %rcx, 24(%rdi) - sbbq 32(%rsi), %rdx - movq 40(%rdi), %rcx - movq %rdx, 32(%rdi) - sbbq 40(%rsi), %rcx - movq 48(%rdi), %rdx - movq %rcx, 40(%rdi) - sbbq 48(%rsi), %rdx - movq 56(%rdi), %rcx - movq %rdx, 48(%rdi) - sbbq 56(%rsi), %rcx - movq 64(%rdi), %rdx - movq %rcx, 56(%rdi) - sbbq 64(%rsi), %rdx - movq 72(%rdi), %rcx - movq %rdx, 64(%rdi) - sbbq 72(%rsi), %rcx - movq 80(%rdi), %rdx - movq %rcx, 72(%rdi) - sbbq 80(%rsi), %rdx - movq 88(%rdi), %rcx - movq %rdx, 80(%rdi) - sbbq 88(%rsi), %rcx - movq 96(%rdi), %rdx - movq %rcx, 88(%rdi) - sbbq 96(%rsi), %rdx - movq 104(%rdi), %rcx - movq %rdx, 96(%rdi) - sbbq 104(%rsi), %rcx - movq 112(%rdi), %rdx - movq %rcx, 104(%rdi) - sbbq 112(%rsi), %rdx - movq 120(%rdi), %rcx - movq %rdx, 112(%rdi) - sbbq 120(%rsi), %rcx - movq %rcx, 120(%rdi) - sbbq $0x00, %rax - repz retq -#ifndef __APPLE__ -.size sp_2048_sub_in_place_16,.-sp_2048_sub_in_place_16 -#endif /* __APPLE__ */ /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -9314,7 +9345,7 @@ _sp_2048_mont_reduce_16: movq $16, %r8 movq (%rdi), %r13 movq 8(%rdi), %r14 -L_mont_loop_16: +L_2048_mont_loop_16: # mu = a[i] * mp movq %r13, %r11 imulq %rcx, %r11 @@ -9477,12 +9508,17 @@ L_mont_loop_16: # i -= 1 addq $8, %rdi decq %r8 - jnz L_mont_loop_16 + jnz L_2048_mont_loop_16 movq %r13, (%rdi) movq %r14, 8(%rdi) negq %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else movq %r15, %rcx movq %rsi, %rdx +#endif /* _WIN64 */ movq %rdi, %rsi movq %rdi, %rdi subq $0x80, %rdi @@ -9499,6 +9535,7 @@ L_mont_loop_16: #ifndef __APPLE__ .size sp_2048_mont_reduce_16,.-sp_2048_mont_reduce_16 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -9605,6 +9642,7 @@ _sp_2048_cond_sub_avx2_16: #ifndef __APPLE__ .size sp_2048_cond_sub_avx2_16,.-sp_2048_cond_sub_avx2_16 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -9783,86 +9821,86 @@ _sp_2048_mul_d_avx2_16: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 24(%rdi) adoxq %r8, %r9 + movq %r10, 24(%rdi) # A[4] * B mulxq 32(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 32(%rdi) adoxq %r8, %r10 + movq %r9, 32(%rdi) # A[5] * B mulxq 40(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 40(%rdi) adoxq %r8, %r9 + movq %r10, 40(%rdi) # A[6] * B mulxq 48(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 48(%rdi) adoxq %r8, %r10 + movq %r9, 48(%rdi) # A[7] * B mulxq 56(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 56(%rdi) adoxq %r8, %r9 + movq %r10, 56(%rdi) # A[8] * B mulxq 64(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 64(%rdi) adoxq %r8, %r10 + movq %r9, 64(%rdi) # A[9] * B mulxq 72(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 72(%rdi) adoxq %r8, %r9 + movq %r10, 72(%rdi) # A[10] * B mulxq 80(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 80(%rdi) adoxq %r8, %r10 + movq %r9, 80(%rdi) # A[11] * B mulxq 88(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 88(%rdi) adoxq %r8, %r9 + movq %r10, 88(%rdi) # A[12] * B mulxq 96(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 96(%rdi) adoxq %r8, %r10 + movq %r9, 96(%rdi) # A[13] * B mulxq 104(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 104(%rdi) adoxq %r8, %r9 + movq %r10, 104(%rdi) # A[14] * B mulxq 112(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 112(%rdi) adoxq %r8, %r10 + movq %r9, 112(%rdi) # A[15] * B mulxq 120(%rsi), %rcx, %r8 movq %r11, %r9 @@ -9876,6 +9914,35 @@ _sp_2048_mul_d_avx2_16: .size sp_2048_mul_d_avx2_16,.-sp_2048_mul_d_avx2_16 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_2048_word_asm_16 +.type div_2048_word_asm_16,@function +.align 16 +div_2048_word_asm_16: +#else +.section __TEXT,__text +.globl _div_2048_word_asm_16 +.p2align 4 +_div_2048_word_asm_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_2048_word_asm_16,.-div_2048_word_asm_16 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ /* Compare a with b in constant time. * * a A single precision integer. @@ -10054,14 +10121,20 @@ _sp_2048_mont_reduce_avx2_16: pushq %r12 pushq %r13 pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp movq %rdx, %r8 - xorq %r14, %r14 + xorq %rbp, %rbp # i = 16 movq $16, %r9 movq (%rdi), %r13 + movq 8(%rdi), %r14 + movq 16(%rdi), %r15 + movq 24(%rdi), %rbx addq $0x40, %rdi - xorq %r12, %r12 -L_mont_loop_avx2_16: + xorq %rbp, %rbp +L_2048_mont_loop_avx2_16: # mu = a[i] * mp movq %r13, %rdx movq %r13, %r10 @@ -10069,32 +10142,29 @@ L_mont_loop_avx2_16: xorq %r12, %r12 # a[i+0] += m[0] * mu mulxq (%rsi), %rax, %rcx - movq -56(%rdi), %r13 + movq %r14, %r13 adcxq %rax, %r10 adoxq %rcx, %r13 # a[i+1] += m[1] * mu mulxq 8(%rsi), %rax, %rcx - movq -48(%rdi), %r10 + movq %r15, %r14 adcxq %rax, %r13 - adoxq %rcx, %r10 + adoxq %rcx, %r14 # a[i+2] += m[2] * mu mulxq 16(%rsi), %rax, %rcx - movq -40(%rdi), %r11 - adcxq %rax, %r10 - adoxq %rcx, %r11 - movq %r10, -48(%rdi) + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 # a[i+3] += m[3] * mu mulxq 24(%rsi), %rax, %rcx - movq -32(%rdi), %r10 - adcxq %rax, %r11 - adoxq %rcx, %r10 - movq %r11, -40(%rdi) + movq -32(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx # a[i+4] += m[4] * mu mulxq 32(%rsi), %rax, %rcx movq -24(%rdi), %r11 - adcxq %rax, %r10 + adcxq %rax, %rbx adoxq %rcx, %r11 - movq %r10, -32(%rdi) # a[i+5] += m[5] * mu mulxq 40(%rsi), %rax, %rcx movq -16(%rdi), %r10 @@ -10161,11 +10231,11 @@ L_mont_loop_avx2_16: adcxq %rax, %r11 adoxq %rcx, %r10 movq %r11, 56(%rdi) - adcxq %r14, %r10 + adcxq %rbp, %r10 + movq %r12, %rbp movq %r10, 64(%rdi) - movq %r12, %r14 - adoxq %r12, %r14 - adcxq %r12, %r14 + adoxq %r12, %rbp + adcxq %r12, %rbp # mu = a[i] * mp movq %r13, %rdx movq %r13, %r10 @@ -10173,32 +10243,29 @@ L_mont_loop_avx2_16: xorq %r12, %r12 # a[i+0] += m[0] * mu mulxq (%rsi), %rax, %rcx - movq -48(%rdi), %r13 + movq %r14, %r13 adcxq %rax, %r10 adoxq %rcx, %r13 # a[i+1] += m[1] * mu mulxq 8(%rsi), %rax, %rcx - movq -40(%rdi), %r10 + movq %r15, %r14 adcxq %rax, %r13 - adoxq %rcx, %r10 + adoxq %rcx, %r14 # a[i+2] += m[2] * mu mulxq 16(%rsi), %rax, %rcx - movq -32(%rdi), %r11 - adcxq %rax, %r10 - adoxq %rcx, %r11 - movq %r10, -40(%rdi) + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 # a[i+3] += m[3] * mu mulxq 24(%rsi), %rax, %rcx - movq -24(%rdi), %r10 - adcxq %rax, %r11 - adoxq %rcx, %r10 - movq %r11, -32(%rdi) + movq -24(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx # a[i+4] += m[4] * mu mulxq 32(%rsi), %rax, %rcx movq -16(%rdi), %r11 - adcxq %rax, %r10 + adcxq %rax, %rbx adoxq %rcx, %r11 - movq %r10, -24(%rdi) # a[i+5] += m[5] * mu mulxq 40(%rsi), %rax, %rcx movq -8(%rdi), %r10 @@ -10265,100 +10332,103 @@ L_mont_loop_avx2_16: adcxq %rax, %r11 adoxq %rcx, %r10 movq %r11, 64(%rdi) - adcxq %r14, %r10 + adcxq %rbp, %r10 + movq %r12, %rbp movq %r10, 72(%rdi) - movq %r12, %r14 - adoxq %r12, %r14 - adcxq %r12, %r14 + adoxq %r12, %rbp + adcxq %r12, %rbp # a += 2 addq $16, %rdi # i -= 2 subq $2, %r9 - jnz L_mont_loop_avx2_16 + jnz L_2048_mont_loop_avx2_16 subq $0x40, %rdi - negq %r14 + negq %rbp movq %rdi, %r8 subq $0x80, %rdi movq (%rsi), %rcx movq %r13, %rdx - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx subq %rcx, %rdx movq 8(%rsi), %rcx - movq 8(%r8), %rax - pextq %r14, %rcx, %rcx + movq %r14, %rax + pextq %rbp, %rcx, %rcx movq %rdx, (%rdi) sbbq %rcx, %rax movq 16(%rsi), %rdx - movq 16(%r8), %rcx - pextq %r14, %rdx, %rdx + movq %r15, %rcx + pextq %rbp, %rdx, %rdx movq %rax, 8(%rdi) sbbq %rdx, %rcx movq 24(%rsi), %rax - movq 24(%r8), %rdx - pextq %r14, %rax, %rax + movq %rbx, %rdx + pextq %rbp, %rax, %rax movq %rcx, 16(%rdi) sbbq %rax, %rdx movq 32(%rsi), %rcx movq 32(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 24(%rdi) sbbq %rcx, %rax movq 40(%rsi), %rdx movq 40(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 32(%rdi) sbbq %rdx, %rcx movq 48(%rsi), %rax movq 48(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 40(%rdi) sbbq %rax, %rdx movq 56(%rsi), %rcx movq 56(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 48(%rdi) sbbq %rcx, %rax movq 64(%rsi), %rdx movq 64(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 56(%rdi) sbbq %rdx, %rcx movq 72(%rsi), %rax movq 72(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 64(%rdi) sbbq %rax, %rdx movq 80(%rsi), %rcx movq 80(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 72(%rdi) sbbq %rcx, %rax movq 88(%rsi), %rdx movq 88(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 80(%rdi) sbbq %rdx, %rcx movq 96(%rsi), %rax movq 96(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 88(%rdi) sbbq %rax, %rdx movq 104(%rsi), %rcx movq 104(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 96(%rdi) sbbq %rcx, %rax movq 112(%rsi), %rdx movq 112(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 104(%rdi) sbbq %rdx, %rcx movq 120(%rsi), %rax movq 120(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 112(%rdi) sbbq %rax, %rdx movq %rdx, 120(%rdi) + popq %rbp + popq %rbx + popq %r15 popq %r14 popq %r13 popq %r12 @@ -10647,7 +10717,7 @@ _sp_2048_mont_reduce_32: movq $32, %r8 movq (%rdi), %r13 movq 8(%rdi), %r14 -L_mont_loop_32: +L_2048_mont_loop_32: # mu = a[i] * mp movq %r13, %r11 imulq %rcx, %r11 @@ -10970,12 +11040,17 @@ L_mont_loop_32: # i -= 1 addq $8, %rdi decq %r8 - jnz L_mont_loop_32 + jnz L_2048_mont_loop_32 movq %r13, (%rdi) movq %r14, 8(%rdi) negq %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else movq %r15, %rcx movq %rsi, %rdx +#endif /* _WIN64 */ movq %rdi, %rsi movq %rdi, %rdi subq $0x100, %rdi @@ -10992,6 +11067,7 @@ L_mont_loop_32: #ifndef __APPLE__ .size sp_2048_mont_reduce_32,.-sp_2048_mont_reduce_32 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -11178,6 +11254,7 @@ _sp_2048_cond_sub_avx2_32: #ifndef __APPLE__ .size sp_2048_cond_sub_avx2_32,.-sp_2048_cond_sub_avx2_32 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #ifdef HAVE_INTEL_AVX2 /* Mul a by digit b into r. (r = a * b) * @@ -11207,182 +11284,182 @@ _sp_2048_mul_d_avx2_32: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 24(%rdi) adoxq %r8, %r9 + movq %r10, 24(%rdi) # A[4] * B mulxq 32(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 32(%rdi) adoxq %r8, %r10 + movq %r9, 32(%rdi) # A[5] * B mulxq 40(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 40(%rdi) adoxq %r8, %r9 + movq %r10, 40(%rdi) # A[6] * B mulxq 48(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 48(%rdi) adoxq %r8, %r10 + movq %r9, 48(%rdi) # A[7] * B mulxq 56(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 56(%rdi) adoxq %r8, %r9 + movq %r10, 56(%rdi) # A[8] * B mulxq 64(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 64(%rdi) adoxq %r8, %r10 + movq %r9, 64(%rdi) # A[9] * B mulxq 72(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 72(%rdi) adoxq %r8, %r9 + movq %r10, 72(%rdi) # A[10] * B mulxq 80(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 80(%rdi) adoxq %r8, %r10 + movq %r9, 80(%rdi) # A[11] * B mulxq 88(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 88(%rdi) adoxq %r8, %r9 + movq %r10, 88(%rdi) # A[12] * B mulxq 96(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 96(%rdi) adoxq %r8, %r10 + movq %r9, 96(%rdi) # A[13] * B mulxq 104(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 104(%rdi) adoxq %r8, %r9 + movq %r10, 104(%rdi) # A[14] * B mulxq 112(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 112(%rdi) adoxq %r8, %r10 + movq %r9, 112(%rdi) # A[15] * B mulxq 120(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 120(%rdi) adoxq %r8, %r9 + movq %r10, 120(%rdi) # A[16] * B mulxq 128(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 128(%rdi) adoxq %r8, %r10 + movq %r9, 128(%rdi) # A[17] * B mulxq 136(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 136(%rdi) adoxq %r8, %r9 + movq %r10, 136(%rdi) # A[18] * B mulxq 144(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 144(%rdi) adoxq %r8, %r10 + movq %r9, 144(%rdi) # A[19] * B mulxq 152(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 152(%rdi) adoxq %r8, %r9 + movq %r10, 152(%rdi) # A[20] * B mulxq 160(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 160(%rdi) adoxq %r8, %r10 + movq %r9, 160(%rdi) # A[21] * B mulxq 168(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 168(%rdi) adoxq %r8, %r9 + movq %r10, 168(%rdi) # A[22] * B mulxq 176(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 176(%rdi) adoxq %r8, %r10 + movq %r9, 176(%rdi) # A[23] * B mulxq 184(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 184(%rdi) adoxq %r8, %r9 + movq %r10, 184(%rdi) # A[24] * B mulxq 192(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 192(%rdi) adoxq %r8, %r10 + movq %r9, 192(%rdi) # A[25] * B mulxq 200(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 200(%rdi) adoxq %r8, %r9 + movq %r10, 200(%rdi) # A[26] * B mulxq 208(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 208(%rdi) adoxq %r8, %r10 + movq %r9, 208(%rdi) # A[27] * B mulxq 216(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 216(%rdi) adoxq %r8, %r9 + movq %r10, 216(%rdi) # A[28] * B mulxq 224(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 224(%rdi) adoxq %r8, %r10 + movq %r9, 224(%rdi) # A[29] * B mulxq 232(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 232(%rdi) adoxq %r8, %r9 + movq %r10, 232(%rdi) # A[30] * B mulxq 240(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 240(%rdi) adoxq %r8, %r10 + movq %r9, 240(%rdi) # A[31] * B mulxq 248(%rsi), %rcx, %r8 movq %r11, %r9 @@ -11396,6 +11473,35 @@ _sp_2048_mul_d_avx2_32: .size sp_2048_mul_d_avx2_32,.-sp_2048_mul_d_avx2_32 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_2048_word_asm_32 +.type div_2048_word_asm_32,@function +.align 16 +div_2048_word_asm_32: +#else +.section __TEXT,__text +.globl _div_2048_word_asm_32 +.p2align 4 +_div_2048_word_asm_32: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_2048_word_asm_32,.-div_2048_word_asm_32 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ /* Compare a with b in constant time. * * a A single precision integer. @@ -11822,14 +11928,20 @@ _sp_2048_mont_reduce_avx2_32: pushq %r12 pushq %r13 pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp movq %rdx, %r8 - xorq %r14, %r14 + xorq %rbp, %rbp # i = 32 movq $32, %r9 movq (%rdi), %r13 + movq 8(%rdi), %r14 + movq 16(%rdi), %r15 + movq 24(%rdi), %rbx addq $0x80, %rdi - xorq %r12, %r12 -L_mont_loop_avx2_32: + xorq %rbp, %rbp +L_2048_mont_loop_avx2_32: # mu = a[i] * mp movq %r13, %rdx movq %r13, %r10 @@ -11837,32 +11949,29 @@ L_mont_loop_avx2_32: xorq %r12, %r12 # a[i+0] += m[0] * mu mulxq (%rsi), %rax, %rcx - movq -120(%rdi), %r13 + movq %r14, %r13 adcxq %rax, %r10 adoxq %rcx, %r13 # a[i+1] += m[1] * mu mulxq 8(%rsi), %rax, %rcx - movq -112(%rdi), %r10 + movq %r15, %r14 adcxq %rax, %r13 - adoxq %rcx, %r10 + adoxq %rcx, %r14 # a[i+2] += m[2] * mu mulxq 16(%rsi), %rax, %rcx - movq -104(%rdi), %r11 - adcxq %rax, %r10 - adoxq %rcx, %r11 - movq %r10, -112(%rdi) + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 # a[i+3] += m[3] * mu mulxq 24(%rsi), %rax, %rcx - movq -96(%rdi), %r10 - adcxq %rax, %r11 - adoxq %rcx, %r10 - movq %r11, -104(%rdi) + movq -96(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx # a[i+4] += m[4] * mu mulxq 32(%rsi), %rax, %rcx movq -88(%rdi), %r11 - adcxq %rax, %r10 + adcxq %rax, %rbx adoxq %rcx, %r11 - movq %r10, -96(%rdi) # a[i+5] += m[5] * mu mulxq 40(%rsi), %rax, %rcx movq -80(%rdi), %r10 @@ -12025,180 +12134,183 @@ L_mont_loop_avx2_32: adcxq %rax, %r11 adoxq %rcx, %r10 movq %r11, 120(%rdi) - adcxq %r14, %r10 + adcxq %rbp, %r10 + movq %r12, %rbp movq %r10, 128(%rdi) - movq %r12, %r14 - adoxq %r12, %r14 - adcxq %r12, %r14 + adoxq %r12, %rbp + adcxq %r12, %rbp # a += 1 addq $8, %rdi # i -= 1 subq $0x01, %r9 - jnz L_mont_loop_avx2_32 + jnz L_2048_mont_loop_avx2_32 subq $0x80, %rdi - negq %r14 + negq %rbp movq %rdi, %r8 subq $0x100, %rdi movq (%rsi), %rcx movq %r13, %rdx - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx subq %rcx, %rdx movq 8(%rsi), %rcx - movq 8(%r8), %rax - pextq %r14, %rcx, %rcx + movq %r14, %rax + pextq %rbp, %rcx, %rcx movq %rdx, (%rdi) sbbq %rcx, %rax movq 16(%rsi), %rdx - movq 16(%r8), %rcx - pextq %r14, %rdx, %rdx + movq %r15, %rcx + pextq %rbp, %rdx, %rdx movq %rax, 8(%rdi) sbbq %rdx, %rcx movq 24(%rsi), %rax - movq 24(%r8), %rdx - pextq %r14, %rax, %rax + movq %rbx, %rdx + pextq %rbp, %rax, %rax movq %rcx, 16(%rdi) sbbq %rax, %rdx movq 32(%rsi), %rcx movq 32(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 24(%rdi) sbbq %rcx, %rax movq 40(%rsi), %rdx movq 40(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 32(%rdi) sbbq %rdx, %rcx movq 48(%rsi), %rax movq 48(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 40(%rdi) sbbq %rax, %rdx movq 56(%rsi), %rcx movq 56(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 48(%rdi) sbbq %rcx, %rax movq 64(%rsi), %rdx movq 64(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 56(%rdi) sbbq %rdx, %rcx movq 72(%rsi), %rax movq 72(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 64(%rdi) sbbq %rax, %rdx movq 80(%rsi), %rcx movq 80(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 72(%rdi) sbbq %rcx, %rax movq 88(%rsi), %rdx movq 88(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 80(%rdi) sbbq %rdx, %rcx movq 96(%rsi), %rax movq 96(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 88(%rdi) sbbq %rax, %rdx movq 104(%rsi), %rcx movq 104(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 96(%rdi) sbbq %rcx, %rax movq 112(%rsi), %rdx movq 112(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 104(%rdi) sbbq %rdx, %rcx movq 120(%rsi), %rax movq 120(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 112(%rdi) sbbq %rax, %rdx movq 128(%rsi), %rcx movq 128(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 120(%rdi) sbbq %rcx, %rax movq 136(%rsi), %rdx movq 136(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 128(%rdi) sbbq %rdx, %rcx movq 144(%rsi), %rax movq 144(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 136(%rdi) sbbq %rax, %rdx movq 152(%rsi), %rcx movq 152(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 144(%rdi) sbbq %rcx, %rax movq 160(%rsi), %rdx movq 160(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 152(%rdi) sbbq %rdx, %rcx movq 168(%rsi), %rax movq 168(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 160(%rdi) sbbq %rax, %rdx movq 176(%rsi), %rcx movq 176(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 168(%rdi) sbbq %rcx, %rax movq 184(%rsi), %rdx movq 184(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 176(%rdi) sbbq %rdx, %rcx movq 192(%rsi), %rax movq 192(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 184(%rdi) sbbq %rax, %rdx movq 200(%rsi), %rcx movq 200(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 192(%rdi) sbbq %rcx, %rax movq 208(%rsi), %rdx movq 208(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 200(%rdi) sbbq %rdx, %rcx movq 216(%rsi), %rax movq 216(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 208(%rdi) sbbq %rax, %rdx movq 224(%rsi), %rcx movq 224(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 216(%rdi) sbbq %rcx, %rax movq 232(%rsi), %rdx movq 232(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 224(%rdi) sbbq %rdx, %rcx movq 240(%rsi), %rax movq 240(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 232(%rdi) sbbq %rax, %rdx movq 248(%rsi), %rcx movq 248(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 240(%rdi) sbbq %rcx, %rax movq %rax, 248(%rdi) + popq %rbp + popq %rbx + popq %r15 popq %r14 popq %r13 popq %r12 @@ -12347,6 +12459,7 @@ _sp_2048_cond_add_16: #ifndef __APPLE__ .size sp_2048_cond_add_16,.-sp_2048_cond_add_16 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -12453,6 +12566,7 @@ _sp_2048_cond_add_avx2_16: #ifndef __APPLE__ .size sp_2048_cond_add_avx2_16,.-sp_2048_cond_add_avx2_16 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Shift number left by n bit. (r = a << n) * * r Result of left shift by n. @@ -12471,107 +12585,116 @@ sp_2048_lshift_32: .p2align 4 _sp_2048_lshift_32: #endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + movq %rdi, %r9 movb %dl, %cl - movq $0x00, %r10 - movq 216(%rsi), %r11 - movq 224(%rsi), %rdx - movq 232(%rsi), %rax - movq 240(%rsi), %r8 - movq 248(%rsi), %r9 - shldq %cl, %r9, %r10 - shldq %cl, %r8, %r9 + movq %rsi, %rdx + movq $0x00, %r12 + movq 216(%rdx), %r13 + movq 224(%rdx), %rax + movq 232(%rdx), %r8 + movq 240(%rdx), %r10 + movq 248(%rdx), %r11 + shldq %cl, %r11, %r12 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 224(%rdi) - movq %rax, 232(%rdi) - movq %r8, 240(%rdi) - movq %r9, 248(%rdi) - movq %r10, 256(%rdi) - movq 184(%rsi), %r9 - movq 192(%rsi), %rdx - movq 200(%rsi), %rax - movq 208(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 224(%r9) + movq %r8, 232(%r9) + movq %r10, 240(%r9) + movq %r11, 248(%r9) + movq %r12, 256(%r9) + movq 184(%rdx), %r11 + movq 192(%rdx), %rax + movq 200(%rdx), %r8 + movq 208(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 192(%rdi) - movq %rax, 200(%rdi) - movq %r8, 208(%rdi) - movq %r11, 216(%rdi) - movq 152(%rsi), %r11 - movq 160(%rsi), %rdx - movq 168(%rsi), %rax - movq 176(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 192(%r9) + movq %r8, 200(%r9) + movq %r10, 208(%r9) + movq %r13, 216(%r9) + movq 152(%rdx), %r13 + movq 160(%rdx), %rax + movq 168(%rdx), %r8 + movq 176(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 160(%rdi) - movq %rax, 168(%rdi) - movq %r8, 176(%rdi) - movq %r9, 184(%rdi) - movq 120(%rsi), %r9 - movq 128(%rsi), %rdx - movq 136(%rsi), %rax - movq 144(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 160(%r9) + movq %r8, 168(%r9) + movq %r10, 176(%r9) + movq %r11, 184(%r9) + movq 120(%rdx), %r11 + movq 128(%rdx), %rax + movq 136(%rdx), %r8 + movq 144(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 128(%rdi) - movq %rax, 136(%rdi) - movq %r8, 144(%rdi) - movq %r11, 152(%rdi) - movq 88(%rsi), %r11 - movq 96(%rsi), %rdx - movq 104(%rsi), %rax - movq 112(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 128(%r9) + movq %r8, 136(%r9) + movq %r10, 144(%r9) + movq %r13, 152(%r9) + movq 88(%rdx), %r13 + movq 96(%rdx), %rax + movq 104(%rdx), %r8 + movq 112(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 96(%rdi) - movq %rax, 104(%rdi) - movq %r8, 112(%rdi) - movq %r9, 120(%rdi) - movq 56(%rsi), %r9 - movq 64(%rsi), %rdx - movq 72(%rsi), %rax - movq 80(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 96(%r9) + movq %r8, 104(%r9) + movq %r10, 112(%r9) + movq %r11, 120(%r9) + movq 56(%rdx), %r11 + movq 64(%rdx), %rax + movq 72(%rdx), %r8 + movq 80(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 64(%rdi) - movq %rax, 72(%rdi) - movq %r8, 80(%rdi) - movq %r11, 88(%rdi) - movq 24(%rsi), %r11 - movq 32(%rsi), %rdx - movq 40(%rsi), %rax - movq 48(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 64(%r9) + movq %r8, 72(%r9) + movq %r10, 80(%r9) + movq %r13, 88(%r9) + movq 24(%rdx), %r13 + movq 32(%rdx), %rax + movq 40(%rdx), %r8 + movq 48(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 32(%rdi) - movq %rax, 40(%rdi) - movq %r8, 48(%rdi) - movq %r9, 56(%rdi) - movq (%rsi), %rdx - movq 8(%rsi), %rax - movq 16(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 32(%r9) + movq %r8, 40(%r9) + movq %r10, 48(%r9) + movq %r11, 56(%r9) + movq (%rdx), %rax + movq 8(%rdx), %r8 + movq 16(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shlq %cl, %rdx - movq %rdx, (%rdi) - movq %rax, 8(%rdi) - movq %r8, 16(%rdi) - movq %r11, 24(%rdi) + shlq %cl, %rax + movq %rax, (%r9) + movq %r8, 8(%r9) + movq %r10, 16(%r9) + movq %r13, 24(%r9) + popq %r13 + popq %r12 repz retq +#ifndef __APPLE__ +.size sp_2048_lshift_32,.-sp_2048_lshift_32 +#endif /* __APPLE__ */ #endif /* !WOLFSSL_SP_NO_2048 */ #endif /* !WOLFSSL_SP_NO_2048 */ #ifndef WOLFSSL_SP_NO_3072 @@ -12670,6 +12793,7 @@ L_3072_from_bin_bswap_zero_end: #ifndef __APPLE__ .size sp_3072_from_bin_bswap,.-sp_3072_from_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Read big endian unsigned byte array into r. * Uses the movbe instruction which is an optional instruction. * @@ -12755,6 +12879,7 @@ L_3072_from_bin_movbe_zero_end: #ifndef __APPLE__ .size sp_3072_from_bin_movbe,.-sp_3072_from_bin_movbe #endif /* __APPLE__ */ +#endif /* !NO_MOVBE_SUPPORT */ /* Write r as big endian to byte array. * Fixed length number of bytes written: 384 * Uses the bswap instruction. @@ -12922,6 +13047,7 @@ _sp_3072_to_bin_bswap: #ifndef __APPLE__ .size sp_3072_to_bin_bswap,.-sp_3072_to_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Write r as big endian to byte array. * Fixed length number of bytes written: 384 * Uses the movbe instruction which is optional. @@ -13041,6 +13167,7 @@ _sp_3072_to_bin_movbe: #ifndef __APPLE__ .size sp_3072_to_bin_movbe,.-sp_3072_to_bin_movbe #endif /* __APPLE__ */ +#endif /* NO_MOVBE_SUPPORT */ /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -14700,6 +14827,7 @@ _sp_3072_mul_avx2_12: cmovne %rdi, %rbx cmpq %rdi, %rbp cmove %rsp, %rbx + addq $0x60, %rdi xorq %r12, %r12 movq (%rsi), %rdx # A[0] * B[0] @@ -14752,7 +14880,7 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adcxq %r12, %r11 movq %r10, 88(%rbx) - movq %r8, 96(%rdi) + movq %r8, (%rdi) movq 8(%rsi), %rdx movq 8(%rbx), %r9 movq 16(%rbx), %r10 @@ -14815,7 +14943,7 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r9 adoxq %rcx, %r10 movq %r9, 80(%rbx) - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[1] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -14830,8 +14958,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r8, 96(%rdi) - movq %r9, 104(%rdi) + movq %r8, (%rdi) + movq %r9, 8(%rdi) movq 16(%rsi), %rdx movq 16(%rbx), %r10 movq 24(%rbx), %r8 @@ -14883,7 +15011,7 @@ _sp_3072_mul_avx2_12: adoxq %rcx, %r9 movq %r8, 72(%rbx) movq 88(%rbx), %r10 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[2] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r9 @@ -14894,14 +15022,14 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r10 adoxq %rcx, %r8 movq %r10, 88(%rbx) - movq 104(%rdi), %r9 + movq 8(%rdi), %r9 # A[2] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[2] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r8, 96(%rdi) + movq %r8, (%rdi) movq %r12, %r10 adcxq %rax, %r9 adoxq %rcx, %r10 @@ -14909,8 +15037,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r9, 104(%rdi) - movq %r10, 112(%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) movq 24(%rsi), %rdx movq 24(%rbx), %r8 movq 32(%rbx), %r9 @@ -14961,8 +15089,8 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r9 adoxq %rcx, %r10 movq %r9, 80(%rbx) - movq 96(%rdi), %r8 - movq 104(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[3] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -14972,15 +15100,15 @@ _sp_3072_mul_avx2_12: movq %r10, 88(%rbx) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r10 + movq %r8, (%rdi) + movq 16(%rdi), %r10 # A[3] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[3] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r9, 104(%rdi) + movq %r9, 8(%rdi) movq %r12, %r8 adcxq %rax, %r10 adoxq %rcx, %r8 @@ -14988,8 +15116,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r10, 112(%rdi) - movq %r8, 120(%rdi) + movq %r10, 16(%rdi) + movq %r8, 24(%rdi) movq 32(%rsi), %rdx movq 32(%rbx), %r9 movq 40(%rbx), %r10 @@ -15029,7 +15157,7 @@ _sp_3072_mul_avx2_12: adoxq %rcx, %r9 movq %r8, 72(%rbx) movq 88(%rbx), %r10 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[4] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r9 @@ -15040,26 +15168,26 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r10 adoxq %rcx, %r8 movq %r10, 88(%rbx) - movq 104(%rdi), %r9 - movq 112(%rdi), %r10 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 # A[4] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[4] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r8, 96(%rdi) + movq %r8, (%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 104(%rdi) - movq 120(%rdi), %r8 + movq %r9, 8(%rdi) + movq 24(%rdi), %r8 # A[4] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[4] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r10, 112(%rdi) + movq %r10, 16(%rdi) movq %r12, %r9 adcxq %rax, %r8 adoxq %rcx, %r9 @@ -15067,8 +15195,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r8, 120(%rdi) - movq %r9, 128(%rdi) + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) movq 40(%rsi), %rdx movq 40(%rbx), %r10 movq 48(%rbx), %r8 @@ -15107,8 +15235,8 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r9 adoxq %rcx, %r10 movq %r9, 80(%rbx) - movq 96(%rdi), %r8 - movq 104(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[5] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -15118,27 +15246,27 @@ _sp_3072_mul_avx2_12: movq %r10, 88(%rbx) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r10 - movq 120(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 # A[5] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[5] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r9, 104(%rdi) + movq %r9, 8(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 112(%rdi) - movq 128(%rdi), %r9 + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 # A[5] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[5] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r8, 120(%rdi) + movq %r8, 24(%rdi) movq %r12, %r10 adcxq %rax, %r9 adoxq %rcx, %r10 @@ -15146,8 +15274,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r9, 128(%rdi) - movq %r10, 136(%rdi) + movq %r9, 32(%rdi) + movq %r10, 40(%rdi) movq 48(%rsi), %rdx movq 48(%rbx), %r8 movq 56(%rbx), %r9 @@ -15175,7 +15303,7 @@ _sp_3072_mul_avx2_12: adoxq %rcx, %r9 movq %r8, 72(%rbx) movq 88(%rbx), %r10 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[6] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r9 @@ -15186,38 +15314,38 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r10 adoxq %rcx, %r8 movq %r10, 88(%rbx) - movq 104(%rdi), %r9 - movq 112(%rdi), %r10 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 # A[6] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[6] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r8, 96(%rdi) + movq %r8, (%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 104(%rdi) - movq 120(%rdi), %r8 - movq 128(%rdi), %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 # A[6] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[6] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r10, 112(%rdi) + movq %r10, 16(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 120(%rdi) - movq 136(%rdi), %r10 + movq %r8, 24(%rdi) + movq 40(%rdi), %r10 # A[6] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[6] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, 32(%rdi) movq %r12, %r8 adcxq %rax, %r10 adoxq %rcx, %r8 @@ -15225,8 +15353,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r10, 136(%rdi) - movq %r8, 144(%rdi) + movq %r10, 40(%rdi) + movq %r8, 48(%rdi) movq 56(%rsi), %rdx movq 56(%rbx), %r9 movq 64(%rbx), %r10 @@ -15253,8 +15381,8 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r9 adoxq %rcx, %r10 movq %r9, 80(%rbx) - movq 96(%rdi), %r8 - movq 104(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[7] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -15264,39 +15392,39 @@ _sp_3072_mul_avx2_12: movq %r10, 88(%rbx) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r10 - movq 120(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 # A[7] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[7] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r9, 104(%rdi) + movq %r9, 8(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 112(%rdi) - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 # A[7] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[7] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r8, 120(%rdi) + movq %r8, 24(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 128(%rdi) - movq 144(%rdi), %r8 + movq %r9, 32(%rdi) + movq 48(%rdi), %r8 # A[7] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[7] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 40(%rdi) movq %r12, %r9 adcxq %rax, %r8 adoxq %rcx, %r9 @@ -15304,8 +15432,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r8, 144(%rdi) - movq %r9, 152(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) movq 64(%rsi), %rdx movq 64(%rbx), %r10 movq 72(%rbx), %r8 @@ -15321,7 +15449,7 @@ _sp_3072_mul_avx2_12: adoxq %rcx, %r9 movq %r8, 72(%rbx) movq 88(%rbx), %r10 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[8] * B[2] mulx 16(%rbp), %rax, %rcx adcxq %rax, %r9 @@ -15332,50 +15460,50 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r10 adoxq %rcx, %r8 movq %r10, 88(%rbx) - movq 104(%rdi), %r9 - movq 112(%rdi), %r10 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 # A[8] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[8] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r8, 96(%rdi) + movq %r8, (%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 104(%rdi) - movq 120(%rdi), %r8 - movq 128(%rdi), %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 # A[8] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[8] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r10, 112(%rdi) + movq %r10, 16(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 120(%rdi) - movq 136(%rdi), %r10 - movq 144(%rdi), %r8 + movq %r8, 24(%rdi) + movq 40(%rdi), %r10 + movq 48(%rdi), %r8 # A[8] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[8] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, 32(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 136(%rdi) - movq 152(%rdi), %r9 + movq %r10, 40(%rdi) + movq 56(%rdi), %r9 # A[8] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[8] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r8, 144(%rdi) + movq %r8, 48(%rdi) movq %r12, %r10 adcxq %rax, %r9 adoxq %rcx, %r10 @@ -15383,8 +15511,8 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r9, 152(%rdi) - movq %r10, 160(%rdi) + movq %r9, 56(%rdi) + movq %r10, 64(%rdi) movq 72(%rsi), %rdx movq 72(%rbx), %r8 movq 80(%rbx), %r9 @@ -15399,8 +15527,8 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r9 adoxq %rcx, %r10 movq %r9, 80(%rbx) - movq 96(%rdi), %r8 - movq 104(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[9] * B[2] mulx 16(%rbp), %rax, %rcx adcxq %rax, %r10 @@ -15410,51 +15538,51 @@ _sp_3072_mul_avx2_12: movq %r10, 88(%rbx) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r10 - movq 120(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 # A[9] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[9] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r9, 104(%rdi) + movq %r9, 8(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 112(%rdi) - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 # A[9] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[9] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r8, 120(%rdi) + movq %r8, 24(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 128(%rdi) - movq 144(%rdi), %r8 - movq 152(%rdi), %r9 + movq %r9, 32(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 # A[9] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[9] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 40(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 144(%rdi) - movq 160(%rdi), %r10 + movq %r8, 48(%rdi) + movq 64(%rdi), %r10 # A[9] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[9] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r9, 152(%rdi) + movq %r9, 56(%rdi) movq %r12, %r8 adcxq %rax, %r10 adoxq %rcx, %r8 @@ -15462,12 +15590,12 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r10, 160(%rdi) - movq %r8, 168(%rdi) + movq %r10, 64(%rdi) + movq %r8, 72(%rdi) movq 80(%rsi), %rdx movq 80(%rbx), %r9 movq 88(%rbx), %r10 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[10] * B[0] mulx (%rbp), %rax, %rcx adcxq %rax, %r9 @@ -15478,62 +15606,62 @@ _sp_3072_mul_avx2_12: adcxq %rax, %r10 adoxq %rcx, %r8 movq %r10, 88(%rbx) - movq 104(%rdi), %r9 - movq 112(%rdi), %r10 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 # A[10] * B[2] mulx 16(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[10] * B[3] mulx 24(%rbp), %rax, %rcx - movq %r8, 96(%rdi) + movq %r8, (%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 104(%rdi) - movq 120(%rdi), %r8 - movq 128(%rdi), %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 # A[10] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[10] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r10, 112(%rdi) + movq %r10, 16(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 120(%rdi) - movq 136(%rdi), %r10 - movq 144(%rdi), %r8 + movq %r8, 24(%rdi) + movq 40(%rdi), %r10 + movq 48(%rdi), %r8 # A[10] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[10] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r9, 128(%rdi) + movq %r9, 32(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 136(%rdi) - movq 152(%rdi), %r9 - movq 160(%rdi), %r10 + movq %r10, 40(%rdi) + movq 56(%rdi), %r9 + movq 64(%rdi), %r10 # A[10] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[10] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r8, 144(%rdi) + movq %r8, 48(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 152(%rdi) - movq 168(%rdi), %r8 + movq %r9, 56(%rdi) + movq 72(%rdi), %r8 # A[10] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[10] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r10, 160(%rdi) + movq %r10, 64(%rdi) movq %r12, %r9 adcxq %rax, %r8 adoxq %rcx, %r9 @@ -15541,12 +15669,12 @@ _sp_3072_mul_avx2_12: movq %r12, %r11 adoxq %r12, %r11 adcxq %r12, %r11 - movq %r8, 168(%rdi) - movq %r9, 176(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) movq 88(%rsi), %rdx movq 88(%rbx), %r10 - movq 96(%rdi), %r8 - movq 104(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[11] * B[0] mulx (%rbp), %rax, %rcx adcxq %rax, %r10 @@ -15556,69 +15684,70 @@ _sp_3072_mul_avx2_12: movq %r10, 88(%rbx) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r10 - movq 120(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 # A[11] * B[2] mulx 16(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[11] * B[3] mulx 24(%rbp), %rax, %rcx - movq %r9, 104(%rdi) + movq %r9, 8(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 112(%rdi) - movq 128(%rdi), %r9 - movq 136(%rdi), %r10 + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 # A[11] * B[4] mulx 32(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[11] * B[5] mulx 40(%rbp), %rax, %rcx - movq %r8, 120(%rdi) + movq %r8, 24(%rdi) adcxq %rax, %r9 adoxq %rcx, %r10 - movq %r9, 128(%rdi) - movq 144(%rdi), %r8 - movq 152(%rdi), %r9 + movq %r9, 32(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 # A[11] * B[6] mulx 48(%rbp), %rax, %rcx adcxq %rax, %r10 adoxq %rcx, %r8 # A[11] * B[7] mulx 56(%rbp), %rax, %rcx - movq %r10, 136(%rdi) + movq %r10, 40(%rdi) adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 144(%rdi) - movq 160(%rdi), %r10 - movq 168(%rdi), %r8 + movq %r8, 48(%rdi) + movq 64(%rdi), %r10 + movq 72(%rdi), %r8 # A[11] * B[8] mulx 64(%rbp), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r10 # A[11] * B[9] mulx 72(%rbp), %rax, %rcx - movq %r9, 152(%rdi) + movq %r9, 56(%rdi) adcxq %rax, %r10 adoxq %rcx, %r8 - movq %r10, 160(%rdi) - movq 176(%rdi), %r9 + movq %r10, 64(%rdi) + movq 80(%rdi), %r9 # A[11] * B[10] mulx 80(%rbp), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 # A[11] * B[11] mulx 88(%rbp), %rax, %rcx - movq %r8, 168(%rdi) + movq %r8, 72(%rdi) movq %r12, %r10 adcxq %rax, %r9 adoxq %rcx, %r10 adcxq %r11, %r10 - movq %r9, 176(%rdi) - movq %r10, 184(%rdi) + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + subq $0x60, %rdi cmpq %rdi, %rsi je L_start_3072_mul_avx2_12 cmpq %rdi, %rbp @@ -15674,6 +15803,7 @@ _sp_3072_sqr_avx2_12: cmpq %rdi, %rsi movq %rsp, %rbp cmovne %rdi, %rbp + addq $0x60, %rdi xorq %r10, %r10 # Diagonal 1 # A[1] x A[0] @@ -15745,7 +15875,7 @@ _sp_3072_sqr_avx2_12: movq %r10, %r11 adcxq %r10, %r11 adoxq %r10, %r11 - movq %r9, 96(%rdi) + movq %r9, (%rdi) # Diagonal 2 movq 24(%rbp), %r9 movq 32(%rbp), %r8 @@ -15797,7 +15927,7 @@ _sp_3072_sqr_avx2_12: adcxq %rax, %r15 adoxq %rcx, %rbx # No store %r15 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[10] x A[1] mulxq 80(%rsi), %rax, %rcx adcxq %rax, %rbx @@ -15808,20 +15938,20 @@ _sp_3072_sqr_avx2_12: mulxq 88(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) + movq %r8, (%rdi) movq %r10, %r8 # A[11] x A[2] movq 16(%rsi), %rdx mulxq 88(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 104(%rdi) + movq %r9, 8(%rdi) # Carry adcxq %r11, %r8 movq %r10, %r11 adcxq %r10, %r11 adoxq %r10, %r11 - movq %r8, 112(%rdi) + movq %r8, 16(%rdi) # Diagonal 3 movq 40(%rbp), %r8 movq 48(%rbp), %r9 @@ -15860,43 +15990,43 @@ _sp_3072_sqr_avx2_12: adcxq %rax, %r15 adoxq %rcx, %rbx # No store %r15 - movq 96(%rdi), %r9 + movq (%rdi), %r9 # A[9] x A[2] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %rbx adoxq %rcx, %r9 # No store %rbx - movq 104(%rdi), %r8 + movq 8(%rdi), %r8 # A[10] x A[2] mulxq 80(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 96(%rdi) - movq 112(%rdi), %r9 + movq %r9, (%rdi) + movq 16(%rdi), %r9 # A[10] x A[3] movq 80(%rsi), %rdx mulxq 24(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 104(%rdi) + movq %r8, 8(%rdi) movq %r10, %r8 # A[10] x A[4] mulxq 32(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 112(%rdi) + movq %r9, 16(%rdi) movq %r10, %r9 # A[10] x A[5] mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 120(%rdi) + movq %r8, 24(%rdi) # Carry adcxq %r11, %r9 movq %r10, %r11 adcxq %r10, %r11 adoxq %r10, %r11 - movq %r9, 128(%rdi) + movq %r9, 32(%rdi) # Diagonal 4 # No load %r12 - %r9 # No load %r13 - %r8 @@ -15924,55 +16054,55 @@ _sp_3072_sqr_avx2_12: adcxq %rax, %r15 adoxq %rcx, %rbx # No store %r15 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[8] x A[3] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %rbx adoxq %rcx, %r8 # No store %rbx - movq 104(%rdi), %r9 + movq 8(%rdi), %r9 # A[9] x A[3] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r8 # A[9] x A[4] movq 72(%rsi), %rdx mulxq 32(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 104(%rdi) - movq 120(%rdi), %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r9 # A[9] x A[5] mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 112(%rdi) - movq 128(%rdi), %r8 + movq %r8, 16(%rdi) + movq 32(%rdi), %r8 # A[9] x A[6] mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 120(%rdi) + movq %r9, 24(%rdi) movq %r10, %r9 # A[9] x A[7] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 128(%rdi) + movq %r8, 32(%rdi) movq %r10, %r8 # A[9] x A[8] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 136(%rdi) + movq %r9, 40(%rdi) # Carry adcxq %r11, %r8 movq %r10, %r11 adcxq %r10, %r11 adoxq %r10, %r11 - movq %r8, 144(%rdi) + movq %r8, 48(%rdi) # Diagonal 5 # No load %r14 - %r8 # No load %r15 - %r9 @@ -15988,146 +16118,146 @@ _sp_3072_sqr_avx2_12: adcxq %rax, %r15 adoxq %rcx, %rbx # No store %r15 - movq 96(%rdi), %r9 + movq (%rdi), %r9 # A[7] x A[4] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %rbx adoxq %rcx, %r9 # No store %rbx - movq 104(%rdi), %r8 + movq 8(%rdi), %r8 # A[8] x A[4] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 96(%rdi) - movq 112(%rdi), %r9 + movq %r9, (%rdi) + movq 16(%rdi), %r9 # A[8] x A[5] movq 64(%rsi), %rdx mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 104(%rdi) - movq 120(%rdi), %r8 + movq %r8, 8(%rdi) + movq 24(%rdi), %r8 # A[8] x A[6] mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 112(%rdi) - movq 128(%rdi), %r9 + movq %r9, 16(%rdi) + movq 32(%rdi), %r9 # A[8] x A[7] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 120(%rdi) - movq 136(%rdi), %r8 + movq %r8, 24(%rdi) + movq 40(%rdi), %r8 # A[10] x A[6] movq 80(%rsi), %rdx mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 128(%rdi) - movq 144(%rdi), %r9 + movq %r9, 32(%rdi) + movq 48(%rdi), %r9 # A[10] x A[7] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 136(%rdi) + movq %r8, 40(%rdi) movq %r10, %r8 # A[10] x A[8] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 144(%rdi) + movq %r9, 48(%rdi) movq %r10, %r9 # A[10] x A[9] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 152(%rdi) + movq %r8, 56(%rdi) # Carry adcxq %r11, %r9 movq %r10, %r11 adcxq %r10, %r11 adoxq %r10, %r11 - movq %r9, 160(%rdi) + movq %r9, 64(%rdi) # Diagonal 6 # No load %rbx - %r9 - movq 96(%rdi), %r8 + movq (%rdi), %r8 # A[6] x A[5] movq 40(%rsi), %rdx mulxq 48(%rsi), %rax, %rcx adcxq %rax, %rbx adoxq %rcx, %r8 # No store %rbx - movq 104(%rdi), %r9 + movq 8(%rdi), %r9 # A[7] x A[5] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 96(%rdi) - movq 112(%rdi), %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r8 # A[7] x A[6] movq 48(%rsi), %rdx mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 104(%rdi) - movq 120(%rdi), %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r9 # A[11] x A[3] movq 88(%rsi), %rdx mulxq 24(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 112(%rdi) - movq 128(%rdi), %r8 + movq %r8, 16(%rdi) + movq 32(%rdi), %r8 # A[11] x A[4] mulxq 32(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 120(%rdi) - movq 136(%rdi), %r9 + movq %r9, 24(%rdi) + movq 40(%rdi), %r9 # A[11] x A[5] mulxq 40(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 128(%rdi) - movq 144(%rdi), %r8 + movq %r8, 32(%rdi) + movq 48(%rdi), %r8 # A[11] x A[6] mulxq 48(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 136(%rdi) - movq 152(%rdi), %r9 + movq %r9, 40(%rdi) + movq 56(%rdi), %r9 # A[11] x A[7] mulxq 56(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 144(%rdi) - movq 160(%rdi), %r8 + movq %r8, 48(%rdi) + movq 64(%rdi), %r8 # A[11] x A[8] mulxq 64(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 152(%rdi) + movq %r9, 56(%rdi) movq %r10, %r9 # A[11] x A[9] mulxq 72(%rsi), %rax, %rcx adcxq %rax, %r8 adoxq %rcx, %r9 - movq %r8, 160(%rdi) + movq %r8, 64(%rdi) movq %r10, %r8 # A[11] x A[10] mulxq 80(%rsi), %rax, %rcx adcxq %rax, %r9 adoxq %rcx, %r8 - movq %r9, 168(%rdi) + movq %r9, 72(%rdi) # Carry adcxq %r11, %r8 movq %r10, %r11 adcxq %r10, %r11 adoxq %r10, %r11 - movq %r8, 176(%rdi) - movq %r11, 184(%rdi) + movq %r8, 80(%rdi) + movq %r11, 88(%rdi) # Double and Add in A[i] x A[i] movq 8(%rbp), %r9 # A[0] x A[0] @@ -16182,8 +16312,8 @@ _sp_3072_sqr_avx2_12: adoxq %rbx, %rbx adcxq %rax, %r15 adcxq %rcx, %rbx - movq 96(%rdi), %r8 - movq 104(%rdi), %r9 + movq (%rdi), %r8 + movq 8(%rdi), %r9 # A[6] x A[6] movq 48(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -16191,10 +16321,10 @@ _sp_3072_sqr_avx2_12: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 96(%rdi) - movq %r9, 104(%rdi) - movq 112(%rdi), %r8 - movq 120(%rdi), %r9 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 # A[7] x A[7] movq 56(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -16202,10 +16332,10 @@ _sp_3072_sqr_avx2_12: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 112(%rdi) - movq %r9, 120(%rdi) - movq 128(%rdi), %r8 - movq 136(%rdi), %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 # A[8] x A[8] movq 64(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -16213,10 +16343,10 @@ _sp_3072_sqr_avx2_12: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 128(%rdi) - movq %r9, 136(%rdi) - movq 144(%rdi), %r8 - movq 152(%rdi), %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 # A[9] x A[9] movq 72(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -16224,10 +16354,10 @@ _sp_3072_sqr_avx2_12: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 144(%rdi) - movq %r9, 152(%rdi) - movq 160(%rdi), %r8 - movq 168(%rdi), %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rdi), %r8 + movq 72(%rdi), %r9 # A[10] x A[10] movq 80(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -16235,10 +16365,10 @@ _sp_3072_sqr_avx2_12: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 160(%rdi) - movq %r9, 168(%rdi) - movq 176(%rdi), %r8 - movq 184(%rdi), %r9 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq 80(%rdi), %r8 + movq 88(%rdi), %r9 # A[11] x A[11] movq 88(%rsi), %rdx mulxq %rdx, %rax, %rcx @@ -16246,13 +16376,14 @@ _sp_3072_sqr_avx2_12: adoxq %r9, %r9 adcxq %rax, %r8 adcxq %rcx, %r9 - movq %r8, 176(%rdi) - movq %r9, 184(%rdi) - movq %r12, 56(%rdi) - movq %r13, 64(%rdi) - movq %r14, 72(%rdi) - movq %r15, 80(%rdi) - movq %rbx, 88(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq %r12, -40(%rdi) + movq %r13, -32(%rdi) + movq %r14, -24(%rdi) + movq %r15, -16(%rdi) + movq %rbx, -8(%rdi) + subq $0x60, %rdi cmpq %rdi, %rsi jne L_end_3072_sqr_avx2_12 vmovdqu (%rbp), %xmm0 @@ -16665,6 +16796,11 @@ _sp_3072_mul_24: #else callq _sp_3072_mul_12 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 592(%rsp), %rdx + movq 584(%rsp), %rsi + movq 576(%rsp), %rdi +#endif /* _WIN64 */ movq 600(%rsp), %r13 movq 608(%rsp), %r14 movq 576(%rsp), %r15 @@ -17235,6 +17371,10 @@ _sp_3072_sqr_24: #else callq _sp_3072_sqr_12 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 488(%rsp), %rsi + movq 480(%rsp), %rdi +#endif /* _WIN64 */ movq 496(%rsp), %r10 movq %rdi, %r9 leaq 384(%rsp), %r8 @@ -17617,6 +17757,7 @@ _sp_3072_sqr_24: #ifndef __APPLE__ .size sp_3072_sqr_24,.-sp_3072_sqr_24 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -17753,6 +17894,11 @@ _sp_3072_mul_avx2_24: #else callq _sp_3072_mul_avx2_12 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 592(%rsp), %rdx + movq 584(%rsp), %rsi + movq 576(%rsp), %rdi +#endif /* _WIN64 */ movq 600(%rsp), %r13 movq 608(%rsp), %r14 movq 576(%rsp), %r15 @@ -18144,6 +18290,8 @@ _sp_3072_mul_avx2_24: #ifndef __APPLE__ .size sp_3072_mul_avx2_24,.-sp_3072_mul_avx2_24 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square a and put result in r. (r = a * a) * * r A single precision integer. @@ -18228,6 +18376,10 @@ _sp_3072_sqr_avx2_24: #else callq _sp_3072_sqr_avx2_12 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 488(%rsp), %rsi + movq 480(%rsp), %rdi +#endif /* _WIN64 */ movq 496(%rsp), %r10 movq %rdi, %r9 leaq 384(%rsp), %r8 @@ -18586,6 +18738,7 @@ _sp_3072_sqr_avx2_24: #ifndef __APPLE__ .size sp_3072_sqr_avx2_24,.-sp_3072_sqr_avx2_24 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Sub b from a into a. (a -= b) * * a A single precision integer and result. @@ -19130,6 +19283,11 @@ _sp_3072_mul_48: #else callq _sp_3072_mul_24 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 1168(%rsp), %rdx + movq 1160(%rsp), %rsi + movq 1152(%rsp), %rdi +#endif /* _WIN64 */ movq 1176(%rsp), %r13 movq 1184(%rsp), %r14 movq 1152(%rsp), %r15 @@ -20168,6 +20326,10 @@ _sp_3072_sqr_48: #else callq _sp_3072_sqr_24 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 968(%rsp), %rsi + movq 960(%rsp), %rdi +#endif /* _WIN64 */ movq 976(%rsp), %r10 movq %rdi, %r9 leaq 768(%rsp), %r8 @@ -20910,6 +21072,7 @@ _sp_3072_sqr_48: #ifndef __APPLE__ .size sp_3072_sqr_48,.-sp_3072_sqr_48 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -21118,6 +21281,11 @@ _sp_3072_mul_avx2_48: #else callq _sp_3072_mul_avx2_24 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 1168(%rsp), %rdx + movq 1160(%rsp), %rsi + movq 1152(%rsp), %rdi +#endif /* _WIN64 */ movq 1176(%rsp), %r13 movq 1184(%rsp), %r14 movq 1152(%rsp), %r15 @@ -21869,6 +22037,8 @@ _sp_3072_mul_avx2_48: #ifndef __APPLE__ .size sp_3072_mul_avx2_48,.-sp_3072_mul_avx2_48 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square a and put result in r. (r = a * a) * * r A single precision integer. @@ -21989,6 +22159,10 @@ _sp_3072_sqr_avx2_48: #else callq _sp_3072_sqr_avx2_24 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 968(%rsp), %rsi + movq 960(%rsp), %rdi +#endif /* _WIN64 */ movq 976(%rsp), %r10 movq %rdi, %r9 leaq 768(%rsp), %r8 @@ -22683,6 +22857,7 @@ _sp_3072_sqr_avx2_48: #ifndef __APPLE__ .size sp_3072_sqr_avx2_48,.-sp_3072_sqr_avx2_48 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -23312,7 +23487,7 @@ _sp_3072_mont_reduce_24: movq $24, %r8 movq (%rdi), %r13 movq 8(%rdi), %r14 -L_mont_loop_24: +L_3072_mont_loop_24: # mu = a[i] * mp movq %r13, %r11 imulq %rcx, %r11 @@ -23555,12 +23730,17 @@ L_mont_loop_24: # i -= 1 addq $8, %rdi decq %r8 - jnz L_mont_loop_24 + jnz L_3072_mont_loop_24 movq %r13, (%rdi) movq %r14, 8(%rdi) negq %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else movq %r15, %rcx movq %rsi, %rdx +#endif /* _WIN64 */ movq %rdi, %rsi movq %rdi, %rdi subq $0xc0, %rdi @@ -23577,6 +23757,7 @@ L_mont_loop_24: #ifndef __APPLE__ .size sp_3072_mont_reduce_24,.-sp_3072_mont_reduce_24 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -23723,6 +23904,7 @@ _sp_3072_cond_sub_avx2_24: #ifndef __APPLE__ .size sp_3072_cond_sub_avx2_24,.-sp_3072_cond_sub_avx2_24 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -23965,134 +24147,134 @@ _sp_3072_mul_d_avx2_24: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 24(%rdi) adoxq %r8, %r9 + movq %r10, 24(%rdi) # A[4] * B mulxq 32(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 32(%rdi) adoxq %r8, %r10 + movq %r9, 32(%rdi) # A[5] * B mulxq 40(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 40(%rdi) adoxq %r8, %r9 + movq %r10, 40(%rdi) # A[6] * B mulxq 48(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 48(%rdi) adoxq %r8, %r10 + movq %r9, 48(%rdi) # A[7] * B mulxq 56(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 56(%rdi) adoxq %r8, %r9 + movq %r10, 56(%rdi) # A[8] * B mulxq 64(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 64(%rdi) adoxq %r8, %r10 + movq %r9, 64(%rdi) # A[9] * B mulxq 72(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 72(%rdi) adoxq %r8, %r9 + movq %r10, 72(%rdi) # A[10] * B mulxq 80(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 80(%rdi) adoxq %r8, %r10 + movq %r9, 80(%rdi) # A[11] * B mulxq 88(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 88(%rdi) adoxq %r8, %r9 + movq %r10, 88(%rdi) # A[12] * B mulxq 96(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 96(%rdi) adoxq %r8, %r10 + movq %r9, 96(%rdi) # A[13] * B mulxq 104(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 104(%rdi) adoxq %r8, %r9 + movq %r10, 104(%rdi) # A[14] * B mulxq 112(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 112(%rdi) adoxq %r8, %r10 + movq %r9, 112(%rdi) # A[15] * B mulxq 120(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 120(%rdi) adoxq %r8, %r9 + movq %r10, 120(%rdi) # A[16] * B mulxq 128(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 128(%rdi) adoxq %r8, %r10 + movq %r9, 128(%rdi) # A[17] * B mulxq 136(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 136(%rdi) adoxq %r8, %r9 + movq %r10, 136(%rdi) # A[18] * B mulxq 144(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 144(%rdi) adoxq %r8, %r10 + movq %r9, 144(%rdi) # A[19] * B mulxq 152(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 152(%rdi) adoxq %r8, %r9 + movq %r10, 152(%rdi) # A[20] * B mulxq 160(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 160(%rdi) adoxq %r8, %r10 + movq %r9, 160(%rdi) # A[21] * B mulxq 168(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 168(%rdi) adoxq %r8, %r9 + movq %r10, 168(%rdi) # A[22] * B mulxq 176(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 176(%rdi) adoxq %r8, %r10 + movq %r9, 176(%rdi) # A[23] * B mulxq 184(%rsi), %rcx, %r8 movq %r11, %r9 @@ -24106,6 +24288,35 @@ _sp_3072_mul_d_avx2_24: .size sp_3072_mul_d_avx2_24,.-sp_3072_mul_d_avx2_24 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_3072_word_asm_24 +.type div_3072_word_asm_24,@function +.align 16 +div_3072_word_asm_24: +#else +.section __TEXT,__text +.globl _div_3072_word_asm_24 +.p2align 4 +_div_3072_word_asm_24: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_3072_word_asm_24,.-div_3072_word_asm_24 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ /* Compare a with b in constant time. * * a A single precision integer. @@ -24348,14 +24559,20 @@ _sp_3072_mont_reduce_avx2_24: pushq %r12 pushq %r13 pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp movq %rdx, %r8 - xorq %r14, %r14 + xorq %rbp, %rbp # i = 24 movq $24, %r9 movq (%rdi), %r13 + movq 8(%rdi), %r14 + movq 16(%rdi), %r15 + movq 24(%rdi), %rbx addq $0x60, %rdi - xorq %r12, %r12 -L_mont_loop_avx2_24: + xorq %rbp, %rbp +L_3072_mont_loop_avx2_24: # mu = a[i] * mp movq %r13, %rdx movq %r13, %r10 @@ -24363,32 +24580,29 @@ L_mont_loop_avx2_24: xorq %r12, %r12 # a[i+0] += m[0] * mu mulxq (%rsi), %rax, %rcx - movq -88(%rdi), %r13 + movq %r14, %r13 adcxq %rax, %r10 adoxq %rcx, %r13 # a[i+1] += m[1] * mu mulxq 8(%rsi), %rax, %rcx - movq -80(%rdi), %r10 + movq %r15, %r14 adcxq %rax, %r13 - adoxq %rcx, %r10 + adoxq %rcx, %r14 # a[i+2] += m[2] * mu mulxq 16(%rsi), %rax, %rcx - movq -72(%rdi), %r11 - adcxq %rax, %r10 - adoxq %rcx, %r11 - movq %r10, -80(%rdi) + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 # a[i+3] += m[3] * mu mulxq 24(%rsi), %rax, %rcx - movq -64(%rdi), %r10 - adcxq %rax, %r11 - adoxq %rcx, %r10 - movq %r11, -72(%rdi) + movq -64(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx # a[i+4] += m[4] * mu mulxq 32(%rsi), %rax, %rcx movq -56(%rdi), %r11 - adcxq %rax, %r10 + adcxq %rax, %rbx adoxq %rcx, %r11 - movq %r10, -64(%rdi) # a[i+5] += m[5] * mu mulxq 40(%rsi), %rax, %rcx movq -48(%rdi), %r10 @@ -24503,140 +24717,143 @@ L_mont_loop_avx2_24: adcxq %rax, %r11 adoxq %rcx, %r10 movq %r11, 88(%rdi) - adcxq %r14, %r10 + adcxq %rbp, %r10 + movq %r12, %rbp movq %r10, 96(%rdi) - movq %r12, %r14 - adoxq %r12, %r14 - adcxq %r12, %r14 + adoxq %r12, %rbp + adcxq %r12, %rbp # a += 1 addq $8, %rdi # i -= 1 subq $0x01, %r9 - jnz L_mont_loop_avx2_24 + jnz L_3072_mont_loop_avx2_24 subq $0x60, %rdi - negq %r14 + negq %rbp movq %rdi, %r8 subq $0xc0, %rdi movq (%rsi), %rcx movq %r13, %rdx - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx subq %rcx, %rdx movq 8(%rsi), %rcx - movq 8(%r8), %rax - pextq %r14, %rcx, %rcx + movq %r14, %rax + pextq %rbp, %rcx, %rcx movq %rdx, (%rdi) sbbq %rcx, %rax movq 16(%rsi), %rdx - movq 16(%r8), %rcx - pextq %r14, %rdx, %rdx + movq %r15, %rcx + pextq %rbp, %rdx, %rdx movq %rax, 8(%rdi) sbbq %rdx, %rcx movq 24(%rsi), %rax - movq 24(%r8), %rdx - pextq %r14, %rax, %rax + movq %rbx, %rdx + pextq %rbp, %rax, %rax movq %rcx, 16(%rdi) sbbq %rax, %rdx movq 32(%rsi), %rcx movq 32(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 24(%rdi) sbbq %rcx, %rax movq 40(%rsi), %rdx movq 40(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 32(%rdi) sbbq %rdx, %rcx movq 48(%rsi), %rax movq 48(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 40(%rdi) sbbq %rax, %rdx movq 56(%rsi), %rcx movq 56(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 48(%rdi) sbbq %rcx, %rax movq 64(%rsi), %rdx movq 64(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 56(%rdi) sbbq %rdx, %rcx movq 72(%rsi), %rax movq 72(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 64(%rdi) sbbq %rax, %rdx movq 80(%rsi), %rcx movq 80(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 72(%rdi) sbbq %rcx, %rax movq 88(%rsi), %rdx movq 88(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 80(%rdi) sbbq %rdx, %rcx movq 96(%rsi), %rax movq 96(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 88(%rdi) sbbq %rax, %rdx movq 104(%rsi), %rcx movq 104(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 96(%rdi) sbbq %rcx, %rax movq 112(%rsi), %rdx movq 112(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 104(%rdi) sbbq %rdx, %rcx movq 120(%rsi), %rax movq 120(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 112(%rdi) sbbq %rax, %rdx movq 128(%rsi), %rcx movq 128(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 120(%rdi) sbbq %rcx, %rax movq 136(%rsi), %rdx movq 136(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 128(%rdi) sbbq %rdx, %rcx movq 144(%rsi), %rax movq 144(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 136(%rdi) sbbq %rax, %rdx movq 152(%rsi), %rcx movq 152(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 144(%rdi) sbbq %rcx, %rax movq 160(%rsi), %rdx movq 160(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 152(%rdi) sbbq %rdx, %rcx movq 168(%rsi), %rax movq 168(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 160(%rdi) sbbq %rax, %rdx movq 176(%rsi), %rcx movq 176(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 168(%rdi) sbbq %rcx, %rax movq 184(%rsi), %rdx movq 184(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 176(%rdi) sbbq %rdx, %rcx movq %rcx, 184(%rdi) + popq %rbp + popq %rbx + popq %r15 popq %r14 popq %r13 popq %r12 @@ -25037,7 +25254,7 @@ _sp_3072_mont_reduce_48: movq $48, %r8 movq (%rdi), %r13 movq 8(%rdi), %r14 -L_mont_loop_48: +L_3072_mont_loop_48: # mu = a[i] * mp movq %r13, %r11 imulq %rcx, %r11 @@ -25520,12 +25737,17 @@ L_mont_loop_48: # i -= 1 addq $8, %rdi decq %r8 - jnz L_mont_loop_48 + jnz L_3072_mont_loop_48 movq %r13, (%rdi) movq %r14, 8(%rdi) negq %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else movq %r15, %rcx movq %rsi, %rdx +#endif /* _WIN64 */ movq %rdi, %rsi movq %rdi, %rdi subq $0x180, %rdi @@ -25542,6 +25764,7 @@ L_mont_loop_48: #ifndef __APPLE__ .size sp_3072_mont_reduce_48,.-sp_3072_mont_reduce_48 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -25808,6 +26031,7 @@ _sp_3072_cond_sub_avx2_48: #ifndef __APPLE__ .size sp_3072_cond_sub_avx2_48,.-sp_3072_cond_sub_avx2_48 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #ifdef HAVE_INTEL_AVX2 /* Mul a by digit b into r. (r = a * b) * @@ -25837,278 +26061,278 @@ _sp_3072_mul_d_avx2_48: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 24(%rdi) adoxq %r8, %r9 + movq %r10, 24(%rdi) # A[4] * B mulxq 32(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 32(%rdi) adoxq %r8, %r10 + movq %r9, 32(%rdi) # A[5] * B mulxq 40(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 40(%rdi) adoxq %r8, %r9 + movq %r10, 40(%rdi) # A[6] * B mulxq 48(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 48(%rdi) adoxq %r8, %r10 + movq %r9, 48(%rdi) # A[7] * B mulxq 56(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 56(%rdi) adoxq %r8, %r9 + movq %r10, 56(%rdi) # A[8] * B mulxq 64(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 64(%rdi) adoxq %r8, %r10 + movq %r9, 64(%rdi) # A[9] * B mulxq 72(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 72(%rdi) adoxq %r8, %r9 + movq %r10, 72(%rdi) # A[10] * B mulxq 80(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 80(%rdi) adoxq %r8, %r10 + movq %r9, 80(%rdi) # A[11] * B mulxq 88(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 88(%rdi) adoxq %r8, %r9 + movq %r10, 88(%rdi) # A[12] * B mulxq 96(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 96(%rdi) adoxq %r8, %r10 + movq %r9, 96(%rdi) # A[13] * B mulxq 104(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 104(%rdi) adoxq %r8, %r9 + movq %r10, 104(%rdi) # A[14] * B mulxq 112(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 112(%rdi) adoxq %r8, %r10 + movq %r9, 112(%rdi) # A[15] * B mulxq 120(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 120(%rdi) adoxq %r8, %r9 + movq %r10, 120(%rdi) # A[16] * B mulxq 128(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 128(%rdi) adoxq %r8, %r10 + movq %r9, 128(%rdi) # A[17] * B mulxq 136(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 136(%rdi) adoxq %r8, %r9 + movq %r10, 136(%rdi) # A[18] * B mulxq 144(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 144(%rdi) adoxq %r8, %r10 + movq %r9, 144(%rdi) # A[19] * B mulxq 152(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 152(%rdi) adoxq %r8, %r9 + movq %r10, 152(%rdi) # A[20] * B mulxq 160(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 160(%rdi) adoxq %r8, %r10 + movq %r9, 160(%rdi) # A[21] * B mulxq 168(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 168(%rdi) adoxq %r8, %r9 + movq %r10, 168(%rdi) # A[22] * B mulxq 176(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 176(%rdi) adoxq %r8, %r10 + movq %r9, 176(%rdi) # A[23] * B mulxq 184(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 184(%rdi) adoxq %r8, %r9 + movq %r10, 184(%rdi) # A[24] * B mulxq 192(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 192(%rdi) adoxq %r8, %r10 + movq %r9, 192(%rdi) # A[25] * B mulxq 200(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 200(%rdi) adoxq %r8, %r9 + movq %r10, 200(%rdi) # A[26] * B mulxq 208(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 208(%rdi) adoxq %r8, %r10 + movq %r9, 208(%rdi) # A[27] * B mulxq 216(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 216(%rdi) adoxq %r8, %r9 + movq %r10, 216(%rdi) # A[28] * B mulxq 224(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 224(%rdi) adoxq %r8, %r10 + movq %r9, 224(%rdi) # A[29] * B mulxq 232(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 232(%rdi) adoxq %r8, %r9 + movq %r10, 232(%rdi) # A[30] * B mulxq 240(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 240(%rdi) adoxq %r8, %r10 + movq %r9, 240(%rdi) # A[31] * B mulxq 248(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 248(%rdi) adoxq %r8, %r9 + movq %r10, 248(%rdi) # A[32] * B mulxq 256(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 256(%rdi) adoxq %r8, %r10 + movq %r9, 256(%rdi) # A[33] * B mulxq 264(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 264(%rdi) adoxq %r8, %r9 + movq %r10, 264(%rdi) # A[34] * B mulxq 272(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 272(%rdi) adoxq %r8, %r10 + movq %r9, 272(%rdi) # A[35] * B mulxq 280(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 280(%rdi) adoxq %r8, %r9 + movq %r10, 280(%rdi) # A[36] * B mulxq 288(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 288(%rdi) adoxq %r8, %r10 + movq %r9, 288(%rdi) # A[37] * B mulxq 296(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 296(%rdi) adoxq %r8, %r9 + movq %r10, 296(%rdi) # A[38] * B mulxq 304(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 304(%rdi) adoxq %r8, %r10 + movq %r9, 304(%rdi) # A[39] * B mulxq 312(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 312(%rdi) adoxq %r8, %r9 + movq %r10, 312(%rdi) # A[40] * B mulxq 320(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 320(%rdi) adoxq %r8, %r10 + movq %r9, 320(%rdi) # A[41] * B mulxq 328(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 328(%rdi) adoxq %r8, %r9 + movq %r10, 328(%rdi) # A[42] * B mulxq 336(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 336(%rdi) adoxq %r8, %r10 + movq %r9, 336(%rdi) # A[43] * B mulxq 344(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 344(%rdi) adoxq %r8, %r9 + movq %r10, 344(%rdi) # A[44] * B mulxq 352(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 352(%rdi) adoxq %r8, %r10 + movq %r9, 352(%rdi) # A[45] * B mulxq 360(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 360(%rdi) adoxq %r8, %r9 + movq %r10, 360(%rdi) # A[46] * B mulxq 368(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 368(%rdi) adoxq %r8, %r10 + movq %r9, 368(%rdi) # A[47] * B mulxq 376(%rsi), %rcx, %r8 movq %r11, %r9 @@ -26122,6 +26346,35 @@ _sp_3072_mul_d_avx2_48: .size sp_3072_mul_d_avx2_48,.-sp_3072_mul_d_avx2_48 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_3072_word_asm_48 +.type div_3072_word_asm_48,@function +.align 16 +div_3072_word_asm_48: +#else +.section __TEXT,__text +.globl _div_3072_word_asm_48 +.p2align 4 +_div_3072_word_asm_48: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_3072_word_asm_48,.-div_3072_word_asm_48 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ /* Compare a with b in constant time. * * a A single precision integer. @@ -26724,14 +26977,20 @@ _sp_3072_mont_reduce_avx2_48: pushq %r12 pushq %r13 pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp movq %rdx, %r8 - xorq %r14, %r14 + xorq %rbp, %rbp # i = 48 movq $48, %r9 movq (%rdi), %r13 + movq 8(%rdi), %r14 + movq 16(%rdi), %r15 + movq 24(%rdi), %rbx addq $0xc0, %rdi - xorq %r12, %r12 -L_mont_loop_avx2_48: + xorq %rbp, %rbp +L_3072_mont_loop_avx2_48: # mu = a[i] * mp movq %r13, %rdx movq %r13, %r10 @@ -26739,32 +26998,29 @@ L_mont_loop_avx2_48: xorq %r12, %r12 # a[i+0] += m[0] * mu mulxq (%rsi), %rax, %rcx - movq -184(%rdi), %r13 + movq %r14, %r13 adcxq %rax, %r10 adoxq %rcx, %r13 # a[i+1] += m[1] * mu mulxq 8(%rsi), %rax, %rcx - movq -176(%rdi), %r10 + movq %r15, %r14 adcxq %rax, %r13 - adoxq %rcx, %r10 + adoxq %rcx, %r14 # a[i+2] += m[2] * mu mulxq 16(%rsi), %rax, %rcx - movq -168(%rdi), %r11 - adcxq %rax, %r10 - adoxq %rcx, %r11 - movq %r10, -176(%rdi) + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 # a[i+3] += m[3] * mu mulxq 24(%rsi), %rax, %rcx - movq -160(%rdi), %r10 - adcxq %rax, %r11 - adoxq %rcx, %r10 - movq %r11, -168(%rdi) + movq -160(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx # a[i+4] += m[4] * mu mulxq 32(%rsi), %rax, %rcx movq -152(%rdi), %r11 - adcxq %rax, %r10 + adcxq %rax, %rbx adoxq %rcx, %r11 - movq %r10, -160(%rdi) # a[i+5] += m[5] * mu mulxq 40(%rsi), %rax, %rcx movq -144(%rdi), %r10 @@ -27023,260 +27279,263 @@ L_mont_loop_avx2_48: adcxq %rax, %r11 adoxq %rcx, %r10 movq %r11, 184(%rdi) - adcxq %r14, %r10 + adcxq %rbp, %r10 + movq %r12, %rbp movq %r10, 192(%rdi) - movq %r12, %r14 - adoxq %r12, %r14 - adcxq %r12, %r14 + adoxq %r12, %rbp + adcxq %r12, %rbp # a += 1 addq $8, %rdi # i -= 1 subq $0x01, %r9 - jnz L_mont_loop_avx2_48 + jnz L_3072_mont_loop_avx2_48 subq $0xc0, %rdi - negq %r14 + negq %rbp movq %rdi, %r8 subq $0x180, %rdi movq (%rsi), %rcx movq %r13, %rdx - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx subq %rcx, %rdx movq 8(%rsi), %rcx - movq 8(%r8), %rax - pextq %r14, %rcx, %rcx + movq %r14, %rax + pextq %rbp, %rcx, %rcx movq %rdx, (%rdi) sbbq %rcx, %rax movq 16(%rsi), %rdx - movq 16(%r8), %rcx - pextq %r14, %rdx, %rdx + movq %r15, %rcx + pextq %rbp, %rdx, %rdx movq %rax, 8(%rdi) sbbq %rdx, %rcx movq 24(%rsi), %rax - movq 24(%r8), %rdx - pextq %r14, %rax, %rax + movq %rbx, %rdx + pextq %rbp, %rax, %rax movq %rcx, 16(%rdi) sbbq %rax, %rdx movq 32(%rsi), %rcx movq 32(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 24(%rdi) sbbq %rcx, %rax movq 40(%rsi), %rdx movq 40(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 32(%rdi) sbbq %rdx, %rcx movq 48(%rsi), %rax movq 48(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 40(%rdi) sbbq %rax, %rdx movq 56(%rsi), %rcx movq 56(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 48(%rdi) sbbq %rcx, %rax movq 64(%rsi), %rdx movq 64(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 56(%rdi) sbbq %rdx, %rcx movq 72(%rsi), %rax movq 72(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 64(%rdi) sbbq %rax, %rdx movq 80(%rsi), %rcx movq 80(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 72(%rdi) sbbq %rcx, %rax movq 88(%rsi), %rdx movq 88(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 80(%rdi) sbbq %rdx, %rcx movq 96(%rsi), %rax movq 96(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 88(%rdi) sbbq %rax, %rdx movq 104(%rsi), %rcx movq 104(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 96(%rdi) sbbq %rcx, %rax movq 112(%rsi), %rdx movq 112(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 104(%rdi) sbbq %rdx, %rcx movq 120(%rsi), %rax movq 120(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 112(%rdi) sbbq %rax, %rdx movq 128(%rsi), %rcx movq 128(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 120(%rdi) sbbq %rcx, %rax movq 136(%rsi), %rdx movq 136(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 128(%rdi) sbbq %rdx, %rcx movq 144(%rsi), %rax movq 144(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 136(%rdi) sbbq %rax, %rdx movq 152(%rsi), %rcx movq 152(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 144(%rdi) sbbq %rcx, %rax movq 160(%rsi), %rdx movq 160(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 152(%rdi) sbbq %rdx, %rcx movq 168(%rsi), %rax movq 168(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 160(%rdi) sbbq %rax, %rdx movq 176(%rsi), %rcx movq 176(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 168(%rdi) sbbq %rcx, %rax movq 184(%rsi), %rdx movq 184(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 176(%rdi) sbbq %rdx, %rcx movq 192(%rsi), %rax movq 192(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 184(%rdi) sbbq %rax, %rdx movq 200(%rsi), %rcx movq 200(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 192(%rdi) sbbq %rcx, %rax movq 208(%rsi), %rdx movq 208(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 200(%rdi) sbbq %rdx, %rcx movq 216(%rsi), %rax movq 216(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 208(%rdi) sbbq %rax, %rdx movq 224(%rsi), %rcx movq 224(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 216(%rdi) sbbq %rcx, %rax movq 232(%rsi), %rdx movq 232(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 224(%rdi) sbbq %rdx, %rcx movq 240(%rsi), %rax movq 240(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 232(%rdi) sbbq %rax, %rdx movq 248(%rsi), %rcx movq 248(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 240(%rdi) sbbq %rcx, %rax movq 256(%rsi), %rdx movq 256(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 248(%rdi) sbbq %rdx, %rcx movq 264(%rsi), %rax movq 264(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 256(%rdi) sbbq %rax, %rdx movq 272(%rsi), %rcx movq 272(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 264(%rdi) sbbq %rcx, %rax movq 280(%rsi), %rdx movq 280(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 272(%rdi) sbbq %rdx, %rcx movq 288(%rsi), %rax movq 288(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 280(%rdi) sbbq %rax, %rdx movq 296(%rsi), %rcx movq 296(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 288(%rdi) sbbq %rcx, %rax movq 304(%rsi), %rdx movq 304(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 296(%rdi) sbbq %rdx, %rcx movq 312(%rsi), %rax movq 312(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 304(%rdi) sbbq %rax, %rdx movq 320(%rsi), %rcx movq 320(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 312(%rdi) sbbq %rcx, %rax movq 328(%rsi), %rdx movq 328(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 320(%rdi) sbbq %rdx, %rcx movq 336(%rsi), %rax movq 336(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 328(%rdi) sbbq %rax, %rdx movq 344(%rsi), %rcx movq 344(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 336(%rdi) sbbq %rcx, %rax movq 352(%rsi), %rdx movq 352(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 344(%rdi) sbbq %rdx, %rcx movq 360(%rsi), %rax movq 360(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 352(%rdi) sbbq %rax, %rdx movq 368(%rsi), %rcx movq 368(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 360(%rdi) sbbq %rcx, %rax movq 376(%rsi), %rdx movq 376(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 368(%rdi) sbbq %rdx, %rcx movq %rcx, 376(%rdi) + popq %rbp + popq %rbx + popq %r15 popq %r14 popq %r13 popq %r12 @@ -27481,6 +27740,7 @@ _sp_3072_cond_add_24: #ifndef __APPLE__ .size sp_3072_cond_add_24,.-sp_3072_cond_add_24 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -27627,6 +27887,7 @@ _sp_3072_cond_add_avx2_24: #ifndef __APPLE__ .size sp_3072_cond_add_avx2_24,.-sp_3072_cond_add_avx2_24 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Shift number left by n bit. (r = a << n) * * r Result of left shift by n. @@ -27645,155 +27906,164 @@ sp_3072_lshift_48: .p2align 4 _sp_3072_lshift_48: #endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + movq %rdi, %r9 movb %dl, %cl - movq $0x00, %r10 - movq 344(%rsi), %r11 - movq 352(%rsi), %rdx - movq 360(%rsi), %rax - movq 368(%rsi), %r8 - movq 376(%rsi), %r9 - shldq %cl, %r9, %r10 - shldq %cl, %r8, %r9 + movq %rsi, %rdx + movq $0x00, %r12 + movq 344(%rdx), %r13 + movq 352(%rdx), %rax + movq 360(%rdx), %r8 + movq 368(%rdx), %r10 + movq 376(%rdx), %r11 + shldq %cl, %r11, %r12 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 352(%rdi) - movq %rax, 360(%rdi) - movq %r8, 368(%rdi) - movq %r9, 376(%rdi) - movq %r10, 384(%rdi) - movq 312(%rsi), %r9 - movq 320(%rsi), %rdx - movq 328(%rsi), %rax - movq 336(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 352(%r9) + movq %r8, 360(%r9) + movq %r10, 368(%r9) + movq %r11, 376(%r9) + movq %r12, 384(%r9) + movq 312(%rdx), %r11 + movq 320(%rdx), %rax + movq 328(%rdx), %r8 + movq 336(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 320(%rdi) - movq %rax, 328(%rdi) - movq %r8, 336(%rdi) - movq %r11, 344(%rdi) - movq 280(%rsi), %r11 - movq 288(%rsi), %rdx - movq 296(%rsi), %rax - movq 304(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 320(%r9) + movq %r8, 328(%r9) + movq %r10, 336(%r9) + movq %r13, 344(%r9) + movq 280(%rdx), %r13 + movq 288(%rdx), %rax + movq 296(%rdx), %r8 + movq 304(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 288(%rdi) - movq %rax, 296(%rdi) - movq %r8, 304(%rdi) - movq %r9, 312(%rdi) - movq 248(%rsi), %r9 - movq 256(%rsi), %rdx - movq 264(%rsi), %rax - movq 272(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 288(%r9) + movq %r8, 296(%r9) + movq %r10, 304(%r9) + movq %r11, 312(%r9) + movq 248(%rdx), %r11 + movq 256(%rdx), %rax + movq 264(%rdx), %r8 + movq 272(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 256(%rdi) - movq %rax, 264(%rdi) - movq %r8, 272(%rdi) - movq %r11, 280(%rdi) - movq 216(%rsi), %r11 - movq 224(%rsi), %rdx - movq 232(%rsi), %rax - movq 240(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 256(%r9) + movq %r8, 264(%r9) + movq %r10, 272(%r9) + movq %r13, 280(%r9) + movq 216(%rdx), %r13 + movq 224(%rdx), %rax + movq 232(%rdx), %r8 + movq 240(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 224(%rdi) - movq %rax, 232(%rdi) - movq %r8, 240(%rdi) - movq %r9, 248(%rdi) - movq 184(%rsi), %r9 - movq 192(%rsi), %rdx - movq 200(%rsi), %rax - movq 208(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 224(%r9) + movq %r8, 232(%r9) + movq %r10, 240(%r9) + movq %r11, 248(%r9) + movq 184(%rdx), %r11 + movq 192(%rdx), %rax + movq 200(%rdx), %r8 + movq 208(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 192(%rdi) - movq %rax, 200(%rdi) - movq %r8, 208(%rdi) - movq %r11, 216(%rdi) - movq 152(%rsi), %r11 - movq 160(%rsi), %rdx - movq 168(%rsi), %rax - movq 176(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 192(%r9) + movq %r8, 200(%r9) + movq %r10, 208(%r9) + movq %r13, 216(%r9) + movq 152(%rdx), %r13 + movq 160(%rdx), %rax + movq 168(%rdx), %r8 + movq 176(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 160(%rdi) - movq %rax, 168(%rdi) - movq %r8, 176(%rdi) - movq %r9, 184(%rdi) - movq 120(%rsi), %r9 - movq 128(%rsi), %rdx - movq 136(%rsi), %rax - movq 144(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 160(%r9) + movq %r8, 168(%r9) + movq %r10, 176(%r9) + movq %r11, 184(%r9) + movq 120(%rdx), %r11 + movq 128(%rdx), %rax + movq 136(%rdx), %r8 + movq 144(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 128(%rdi) - movq %rax, 136(%rdi) - movq %r8, 144(%rdi) - movq %r11, 152(%rdi) - movq 88(%rsi), %r11 - movq 96(%rsi), %rdx - movq 104(%rsi), %rax - movq 112(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 128(%r9) + movq %r8, 136(%r9) + movq %r10, 144(%r9) + movq %r13, 152(%r9) + movq 88(%rdx), %r13 + movq 96(%rdx), %rax + movq 104(%rdx), %r8 + movq 112(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 96(%rdi) - movq %rax, 104(%rdi) - movq %r8, 112(%rdi) - movq %r9, 120(%rdi) - movq 56(%rsi), %r9 - movq 64(%rsi), %rdx - movq 72(%rsi), %rax - movq 80(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 96(%r9) + movq %r8, 104(%r9) + movq %r10, 112(%r9) + movq %r11, 120(%r9) + movq 56(%rdx), %r11 + movq 64(%rdx), %rax + movq 72(%rdx), %r8 + movq 80(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 64(%rdi) - movq %rax, 72(%rdi) - movq %r8, 80(%rdi) - movq %r11, 88(%rdi) - movq 24(%rsi), %r11 - movq 32(%rsi), %rdx - movq 40(%rsi), %rax - movq 48(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 64(%r9) + movq %r8, 72(%r9) + movq %r10, 80(%r9) + movq %r13, 88(%r9) + movq 24(%rdx), %r13 + movq 32(%rdx), %rax + movq 40(%rdx), %r8 + movq 48(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 32(%rdi) - movq %rax, 40(%rdi) - movq %r8, 48(%rdi) - movq %r9, 56(%rdi) - movq (%rsi), %rdx - movq 8(%rsi), %rax - movq 16(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 32(%r9) + movq %r8, 40(%r9) + movq %r10, 48(%r9) + movq %r11, 56(%r9) + movq (%rdx), %rax + movq 8(%rdx), %r8 + movq 16(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shlq %cl, %rdx - movq %rdx, (%rdi) - movq %rax, 8(%rdi) - movq %r8, 16(%rdi) - movq %r11, 24(%rdi) + shlq %cl, %rax + movq %rax, (%r9) + movq %r8, 8(%r9) + movq %r10, 16(%r9) + movq %r13, 24(%r9) + popq %r13 + popq %r12 repz retq +#ifndef __APPLE__ +.size sp_3072_lshift_48,.-sp_3072_lshift_48 +#endif /* __APPLE__ */ #endif /* !WOLFSSL_SP_NO_3072 */ #endif /* !WOLFSSL_SP_NO_3072 */ #ifdef WOLFSSL_SP_4096 @@ -27892,6 +28162,7 @@ L_4096_from_bin_bswap_zero_end: #ifndef __APPLE__ .size sp_4096_from_bin_bswap,.-sp_4096_from_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Read big endian unsigned byte array into r. * Uses the movbe instruction which is an optional instruction. * @@ -27977,6 +28248,7 @@ L_4096_from_bin_movbe_zero_end: #ifndef __APPLE__ .size sp_4096_from_bin_movbe,.-sp_4096_from_bin_movbe #endif /* __APPLE__ */ +#endif /* !NO_MOVBE_SUPPORT */ /* Write r as big endian to byte array. * Fixed length number of bytes written: 512 * Uses the bswap instruction. @@ -28192,6 +28464,7 @@ _sp_4096_to_bin_bswap: #ifndef __APPLE__ .size sp_4096_to_bin_bswap,.-sp_4096_to_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Write r as big endian to byte array. * Fixed length number of bytes written: 512 * Uses the movbe instruction which is optional. @@ -28343,6 +28616,7 @@ _sp_4096_to_bin_movbe: #ifndef __APPLE__ .size sp_4096_to_bin_movbe,.-sp_4096_to_bin_movbe #endif /* __APPLE__ */ +#endif /* NO_MOVBE_SUPPORT */ /* Sub b from a into a. (a -= b) * * a A single precision integer and result. @@ -29031,6 +29305,11 @@ _sp_4096_mul_64: #else callq _sp_2048_mul_32 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 1552(%rsp), %rdx + movq 1544(%rsp), %rsi + movq 1536(%rsp), %rdi +#endif /* _WIN64 */ movq 1560(%rsp), %r13 movq 1568(%rsp), %r14 movq 1536(%rsp), %r15 @@ -30383,6 +30662,10 @@ _sp_4096_sqr_64: #else callq _sp_2048_sqr_32 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 1288(%rsp), %rsi + movq 1280(%rsp), %rdi +#endif /* _WIN64 */ movq 1296(%rsp), %r10 leaq 1024(%rsp), %r8 movq %r10, %rcx @@ -31364,6 +31647,7 @@ _sp_4096_sqr_64: #ifndef __APPLE__ .size sp_4096_sqr_64,.-sp_4096_sqr_64 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -31620,6 +31904,11 @@ _sp_4096_mul_avx2_64: #else callq _sp_2048_mul_avx2_32 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 1552(%rsp), %rdx + movq 1544(%rsp), %rsi + movq 1536(%rsp), %rdi +#endif /* _WIN64 */ movq 1560(%rsp), %r13 movq 1568(%rsp), %r14 movq 1536(%rsp), %r15 @@ -32613,6 +32902,8 @@ _sp_4096_mul_avx2_64: #ifndef __APPLE__ .size sp_4096_mul_avx2_64,.-sp_4096_mul_avx2_64 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square a and put result in r. (r = a * a) * * r A single precision integer. @@ -32757,6 +33048,10 @@ _sp_4096_sqr_avx2_64: #else callq _sp_2048_sqr_avx2_32 #endif /* __APPLE__ */ +#ifdef _WIN64 + movq 1288(%rsp), %rsi + movq 1280(%rsp), %rdi +#endif /* _WIN64 */ movq 1296(%rsp), %r10 leaq 1024(%rsp), %r8 movq %r10, %rcx @@ -33674,6 +33969,7 @@ _sp_4096_sqr_avx2_64: #ifndef __APPLE__ .size sp_4096_sqr_avx2_64,.-sp_4096_sqr_avx2_64 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -34711,7 +35007,7 @@ _sp_4096_mont_reduce_64: movq $0x40, %r8 movq (%rdi), %r13 movq 8(%rdi), %r14 -L_mont_loop_64: +L_4096_mont_loop_64: # mu = a[i] * mp movq %r13, %r11 imulq %rcx, %r11 @@ -35354,12 +35650,17 @@ L_mont_loop_64: # i -= 1 addq $8, %rdi decq %r8 - jnz L_mont_loop_64 + jnz L_4096_mont_loop_64 movq %r13, (%rdi) movq %r14, 8(%rdi) negq %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else movq %r15, %rcx movq %rsi, %rdx +#endif /* _WIN64 */ movq %rdi, %rsi movq %rdi, %rdi subq $0x200, %rdi @@ -35376,6 +35677,7 @@ L_mont_loop_64: #ifndef __APPLE__ .size sp_4096_mont_reduce_64,.-sp_4096_mont_reduce_64 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally subtract b from a using the mask m. * m is -1 to subtract and 0 when not copying. * @@ -35722,6 +36024,7 @@ _sp_4096_cond_sub_avx2_64: #ifndef __APPLE__ .size sp_4096_cond_sub_avx2_64,.-sp_4096_cond_sub_avx2_64 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #ifdef HAVE_INTEL_AVX2 /* Mul a by digit b into r. (r = a * b) * @@ -35751,374 +36054,374 @@ _sp_4096_mul_d_avx2_64: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 24(%rdi) adoxq %r8, %r9 + movq %r10, 24(%rdi) # A[4] * B mulxq 32(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 32(%rdi) adoxq %r8, %r10 + movq %r9, 32(%rdi) # A[5] * B mulxq 40(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 40(%rdi) adoxq %r8, %r9 + movq %r10, 40(%rdi) # A[6] * B mulxq 48(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 48(%rdi) adoxq %r8, %r10 + movq %r9, 48(%rdi) # A[7] * B mulxq 56(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 56(%rdi) adoxq %r8, %r9 + movq %r10, 56(%rdi) # A[8] * B mulxq 64(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 64(%rdi) adoxq %r8, %r10 + movq %r9, 64(%rdi) # A[9] * B mulxq 72(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 72(%rdi) adoxq %r8, %r9 + movq %r10, 72(%rdi) # A[10] * B mulxq 80(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 80(%rdi) adoxq %r8, %r10 + movq %r9, 80(%rdi) # A[11] * B mulxq 88(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 88(%rdi) adoxq %r8, %r9 + movq %r10, 88(%rdi) # A[12] * B mulxq 96(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 96(%rdi) adoxq %r8, %r10 + movq %r9, 96(%rdi) # A[13] * B mulxq 104(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 104(%rdi) adoxq %r8, %r9 + movq %r10, 104(%rdi) # A[14] * B mulxq 112(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 112(%rdi) adoxq %r8, %r10 + movq %r9, 112(%rdi) # A[15] * B mulxq 120(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 120(%rdi) adoxq %r8, %r9 + movq %r10, 120(%rdi) # A[16] * B mulxq 128(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 128(%rdi) adoxq %r8, %r10 + movq %r9, 128(%rdi) # A[17] * B mulxq 136(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 136(%rdi) adoxq %r8, %r9 + movq %r10, 136(%rdi) # A[18] * B mulxq 144(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 144(%rdi) adoxq %r8, %r10 + movq %r9, 144(%rdi) # A[19] * B mulxq 152(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 152(%rdi) adoxq %r8, %r9 + movq %r10, 152(%rdi) # A[20] * B mulxq 160(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 160(%rdi) adoxq %r8, %r10 + movq %r9, 160(%rdi) # A[21] * B mulxq 168(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 168(%rdi) adoxq %r8, %r9 + movq %r10, 168(%rdi) # A[22] * B mulxq 176(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 176(%rdi) adoxq %r8, %r10 + movq %r9, 176(%rdi) # A[23] * B mulxq 184(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 184(%rdi) adoxq %r8, %r9 + movq %r10, 184(%rdi) # A[24] * B mulxq 192(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 192(%rdi) adoxq %r8, %r10 + movq %r9, 192(%rdi) # A[25] * B mulxq 200(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 200(%rdi) adoxq %r8, %r9 + movq %r10, 200(%rdi) # A[26] * B mulxq 208(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 208(%rdi) adoxq %r8, %r10 + movq %r9, 208(%rdi) # A[27] * B mulxq 216(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 216(%rdi) adoxq %r8, %r9 + movq %r10, 216(%rdi) # A[28] * B mulxq 224(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 224(%rdi) adoxq %r8, %r10 + movq %r9, 224(%rdi) # A[29] * B mulxq 232(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 232(%rdi) adoxq %r8, %r9 + movq %r10, 232(%rdi) # A[30] * B mulxq 240(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 240(%rdi) adoxq %r8, %r10 + movq %r9, 240(%rdi) # A[31] * B mulxq 248(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 248(%rdi) adoxq %r8, %r9 + movq %r10, 248(%rdi) # A[32] * B mulxq 256(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 256(%rdi) adoxq %r8, %r10 + movq %r9, 256(%rdi) # A[33] * B mulxq 264(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 264(%rdi) adoxq %r8, %r9 + movq %r10, 264(%rdi) # A[34] * B mulxq 272(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 272(%rdi) adoxq %r8, %r10 + movq %r9, 272(%rdi) # A[35] * B mulxq 280(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 280(%rdi) adoxq %r8, %r9 + movq %r10, 280(%rdi) # A[36] * B mulxq 288(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 288(%rdi) adoxq %r8, %r10 + movq %r9, 288(%rdi) # A[37] * B mulxq 296(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 296(%rdi) adoxq %r8, %r9 + movq %r10, 296(%rdi) # A[38] * B mulxq 304(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 304(%rdi) adoxq %r8, %r10 + movq %r9, 304(%rdi) # A[39] * B mulxq 312(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 312(%rdi) adoxq %r8, %r9 + movq %r10, 312(%rdi) # A[40] * B mulxq 320(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 320(%rdi) adoxq %r8, %r10 + movq %r9, 320(%rdi) # A[41] * B mulxq 328(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 328(%rdi) adoxq %r8, %r9 + movq %r10, 328(%rdi) # A[42] * B mulxq 336(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 336(%rdi) adoxq %r8, %r10 + movq %r9, 336(%rdi) # A[43] * B mulxq 344(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 344(%rdi) adoxq %r8, %r9 + movq %r10, 344(%rdi) # A[44] * B mulxq 352(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 352(%rdi) adoxq %r8, %r10 + movq %r9, 352(%rdi) # A[45] * B mulxq 360(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 360(%rdi) adoxq %r8, %r9 + movq %r10, 360(%rdi) # A[46] * B mulxq 368(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 368(%rdi) adoxq %r8, %r10 + movq %r9, 368(%rdi) # A[47] * B mulxq 376(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 376(%rdi) adoxq %r8, %r9 + movq %r10, 376(%rdi) # A[48] * B mulxq 384(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 384(%rdi) adoxq %r8, %r10 + movq %r9, 384(%rdi) # A[49] * B mulxq 392(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 392(%rdi) adoxq %r8, %r9 + movq %r10, 392(%rdi) # A[50] * B mulxq 400(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 400(%rdi) adoxq %r8, %r10 + movq %r9, 400(%rdi) # A[51] * B mulxq 408(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 408(%rdi) adoxq %r8, %r9 + movq %r10, 408(%rdi) # A[52] * B mulxq 416(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 416(%rdi) adoxq %r8, %r10 + movq %r9, 416(%rdi) # A[53] * B mulxq 424(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 424(%rdi) adoxq %r8, %r9 + movq %r10, 424(%rdi) # A[54] * B mulxq 432(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 432(%rdi) adoxq %r8, %r10 + movq %r9, 432(%rdi) # A[55] * B mulxq 440(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 440(%rdi) adoxq %r8, %r9 + movq %r10, 440(%rdi) # A[56] * B mulxq 448(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 448(%rdi) adoxq %r8, %r10 + movq %r9, 448(%rdi) # A[57] * B mulxq 456(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 456(%rdi) adoxq %r8, %r9 + movq %r10, 456(%rdi) # A[58] * B mulxq 464(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 464(%rdi) adoxq %r8, %r10 + movq %r9, 464(%rdi) # A[59] * B mulxq 472(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 472(%rdi) adoxq %r8, %r9 + movq %r10, 472(%rdi) # A[60] * B mulxq 480(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 480(%rdi) adoxq %r8, %r10 + movq %r9, 480(%rdi) # A[61] * B mulxq 488(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 488(%rdi) adoxq %r8, %r9 + movq %r10, 488(%rdi) # A[62] * B mulxq 496(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 496(%rdi) adoxq %r8, %r10 + movq %r9, 496(%rdi) # A[63] * B mulxq 504(%rsi), %rcx, %r8 movq %r11, %r9 @@ -36132,6 +36435,35 @@ _sp_4096_mul_d_avx2_64: .size sp_4096_mul_d_avx2_64,.-sp_4096_mul_d_avx2_64 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_4096_word_asm_64 +.type div_4096_word_asm_64,@function +.align 16 +div_4096_word_asm_64: +#else +.section __TEXT,__text +.globl _div_4096_word_asm_64 +.p2align 4 +_div_4096_word_asm_64: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_4096_word_asm_64,.-div_4096_word_asm_64 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ /* Compare a with b in constant time. * * a A single precision integer. @@ -36910,14 +37242,20 @@ _sp_4096_mont_reduce_avx2_64: pushq %r12 pushq %r13 pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp movq %rdx, %r8 - xorq %r14, %r14 + xorq %rbp, %rbp # i = 64 movq $0x40, %r9 movq (%rdi), %r13 + movq 8(%rdi), %r14 + movq 16(%rdi), %r15 + movq 24(%rdi), %rbx addq $0x100, %rdi - xorq %r12, %r12 -L_mont_loop_avx2_64: + xorq %rbp, %rbp +L_4096_mont_loop_avx2_64: # mu = a[i] * mp movq %r13, %rdx movq %r13, %r10 @@ -36925,32 +37263,29 @@ L_mont_loop_avx2_64: xorq %r12, %r12 # a[i+0] += m[0] * mu mulxq (%rsi), %rax, %rcx - movq -248(%rdi), %r13 + movq %r14, %r13 adcxq %rax, %r10 adoxq %rcx, %r13 # a[i+1] += m[1] * mu mulxq 8(%rsi), %rax, %rcx - movq -240(%rdi), %r10 + movq %r15, %r14 adcxq %rax, %r13 - adoxq %rcx, %r10 + adoxq %rcx, %r14 # a[i+2] += m[2] * mu mulxq 16(%rsi), %rax, %rcx - movq -232(%rdi), %r11 - adcxq %rax, %r10 - adoxq %rcx, %r11 - movq %r10, -240(%rdi) + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 # a[i+3] += m[3] * mu mulxq 24(%rsi), %rax, %rcx - movq -224(%rdi), %r10 - adcxq %rax, %r11 - adoxq %rcx, %r10 - movq %r11, -232(%rdi) + movq -224(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx # a[i+4] += m[4] * mu mulxq 32(%rsi), %rax, %rcx movq -216(%rdi), %r11 - adcxq %rax, %r10 + adcxq %rax, %rbx adoxq %rcx, %r11 - movq %r10, -224(%rdi) # a[i+5] += m[5] * mu mulxq 40(%rsi), %rax, %rcx movq -208(%rdi), %r10 @@ -37305,340 +37640,343 @@ L_mont_loop_avx2_64: adcxq %rax, %r11 adoxq %rcx, %r10 movq %r11, 248(%rdi) - adcxq %r14, %r10 + adcxq %rbp, %r10 + movq %r12, %rbp movq %r10, 256(%rdi) - movq %r12, %r14 - adoxq %r12, %r14 - adcxq %r12, %r14 + adoxq %r12, %rbp + adcxq %r12, %rbp # a += 1 addq $8, %rdi # i -= 1 subq $0x01, %r9 - jnz L_mont_loop_avx2_64 + jnz L_4096_mont_loop_avx2_64 subq $0x100, %rdi - negq %r14 + negq %rbp movq %rdi, %r8 subq $0x200, %rdi movq (%rsi), %rcx movq %r13, %rdx - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx subq %rcx, %rdx movq 8(%rsi), %rcx - movq 8(%r8), %rax - pextq %r14, %rcx, %rcx + movq %r14, %rax + pextq %rbp, %rcx, %rcx movq %rdx, (%rdi) sbbq %rcx, %rax movq 16(%rsi), %rdx - movq 16(%r8), %rcx - pextq %r14, %rdx, %rdx + movq %r15, %rcx + pextq %rbp, %rdx, %rdx movq %rax, 8(%rdi) sbbq %rdx, %rcx movq 24(%rsi), %rax - movq 24(%r8), %rdx - pextq %r14, %rax, %rax + movq %rbx, %rdx + pextq %rbp, %rax, %rax movq %rcx, 16(%rdi) sbbq %rax, %rdx movq 32(%rsi), %rcx movq 32(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 24(%rdi) sbbq %rcx, %rax movq 40(%rsi), %rdx movq 40(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 32(%rdi) sbbq %rdx, %rcx movq 48(%rsi), %rax movq 48(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 40(%rdi) sbbq %rax, %rdx movq 56(%rsi), %rcx movq 56(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 48(%rdi) sbbq %rcx, %rax movq 64(%rsi), %rdx movq 64(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 56(%rdi) sbbq %rdx, %rcx movq 72(%rsi), %rax movq 72(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 64(%rdi) sbbq %rax, %rdx movq 80(%rsi), %rcx movq 80(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 72(%rdi) sbbq %rcx, %rax movq 88(%rsi), %rdx movq 88(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 80(%rdi) sbbq %rdx, %rcx movq 96(%rsi), %rax movq 96(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 88(%rdi) sbbq %rax, %rdx movq 104(%rsi), %rcx movq 104(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 96(%rdi) sbbq %rcx, %rax movq 112(%rsi), %rdx movq 112(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 104(%rdi) sbbq %rdx, %rcx movq 120(%rsi), %rax movq 120(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 112(%rdi) sbbq %rax, %rdx movq 128(%rsi), %rcx movq 128(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 120(%rdi) sbbq %rcx, %rax movq 136(%rsi), %rdx movq 136(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 128(%rdi) sbbq %rdx, %rcx movq 144(%rsi), %rax movq 144(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 136(%rdi) sbbq %rax, %rdx movq 152(%rsi), %rcx movq 152(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 144(%rdi) sbbq %rcx, %rax movq 160(%rsi), %rdx movq 160(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 152(%rdi) sbbq %rdx, %rcx movq 168(%rsi), %rax movq 168(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 160(%rdi) sbbq %rax, %rdx movq 176(%rsi), %rcx movq 176(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 168(%rdi) sbbq %rcx, %rax movq 184(%rsi), %rdx movq 184(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 176(%rdi) sbbq %rdx, %rcx movq 192(%rsi), %rax movq 192(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 184(%rdi) sbbq %rax, %rdx movq 200(%rsi), %rcx movq 200(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 192(%rdi) sbbq %rcx, %rax movq 208(%rsi), %rdx movq 208(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 200(%rdi) sbbq %rdx, %rcx movq 216(%rsi), %rax movq 216(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 208(%rdi) sbbq %rax, %rdx movq 224(%rsi), %rcx movq 224(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 216(%rdi) sbbq %rcx, %rax movq 232(%rsi), %rdx movq 232(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 224(%rdi) sbbq %rdx, %rcx movq 240(%rsi), %rax movq 240(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 232(%rdi) sbbq %rax, %rdx movq 248(%rsi), %rcx movq 248(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 240(%rdi) sbbq %rcx, %rax movq 256(%rsi), %rdx movq 256(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 248(%rdi) sbbq %rdx, %rcx movq 264(%rsi), %rax movq 264(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 256(%rdi) sbbq %rax, %rdx movq 272(%rsi), %rcx movq 272(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 264(%rdi) sbbq %rcx, %rax movq 280(%rsi), %rdx movq 280(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 272(%rdi) sbbq %rdx, %rcx movq 288(%rsi), %rax movq 288(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 280(%rdi) sbbq %rax, %rdx movq 296(%rsi), %rcx movq 296(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 288(%rdi) sbbq %rcx, %rax movq 304(%rsi), %rdx movq 304(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 296(%rdi) sbbq %rdx, %rcx movq 312(%rsi), %rax movq 312(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 304(%rdi) sbbq %rax, %rdx movq 320(%rsi), %rcx movq 320(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 312(%rdi) sbbq %rcx, %rax movq 328(%rsi), %rdx movq 328(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 320(%rdi) sbbq %rdx, %rcx movq 336(%rsi), %rax movq 336(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 328(%rdi) sbbq %rax, %rdx movq 344(%rsi), %rcx movq 344(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 336(%rdi) sbbq %rcx, %rax movq 352(%rsi), %rdx movq 352(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 344(%rdi) sbbq %rdx, %rcx movq 360(%rsi), %rax movq 360(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 352(%rdi) sbbq %rax, %rdx movq 368(%rsi), %rcx movq 368(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 360(%rdi) sbbq %rcx, %rax movq 376(%rsi), %rdx movq 376(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 368(%rdi) sbbq %rdx, %rcx movq 384(%rsi), %rax movq 384(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 376(%rdi) sbbq %rax, %rdx movq 392(%rsi), %rcx movq 392(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 384(%rdi) sbbq %rcx, %rax movq 400(%rsi), %rdx movq 400(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 392(%rdi) sbbq %rdx, %rcx movq 408(%rsi), %rax movq 408(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 400(%rdi) sbbq %rax, %rdx movq 416(%rsi), %rcx movq 416(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 408(%rdi) sbbq %rcx, %rax movq 424(%rsi), %rdx movq 424(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 416(%rdi) sbbq %rdx, %rcx movq 432(%rsi), %rax movq 432(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 424(%rdi) sbbq %rax, %rdx movq 440(%rsi), %rcx movq 440(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 432(%rdi) sbbq %rcx, %rax movq 448(%rsi), %rdx movq 448(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 440(%rdi) sbbq %rdx, %rcx movq 456(%rsi), %rax movq 456(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 448(%rdi) sbbq %rax, %rdx movq 464(%rsi), %rcx movq 464(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 456(%rdi) sbbq %rcx, %rax movq 472(%rsi), %rdx movq 472(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 464(%rdi) sbbq %rdx, %rcx movq 480(%rsi), %rax movq 480(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 472(%rdi) sbbq %rax, %rdx movq 488(%rsi), %rcx movq 488(%r8), %rax - pextq %r14, %rcx, %rcx + pextq %rbp, %rcx, %rcx movq %rdx, 480(%rdi) sbbq %rcx, %rax movq 496(%rsi), %rdx movq 496(%r8), %rcx - pextq %r14, %rdx, %rdx + pextq %rbp, %rdx, %rdx movq %rax, 488(%rdi) sbbq %rdx, %rcx movq 504(%rsi), %rax movq 504(%r8), %rdx - pextq %r14, %rax, %rax + pextq %rbp, %rax, %rax movq %rcx, 496(%rdi) sbbq %rax, %rdx movq %rdx, 504(%rdi) + popq %rbp + popq %rbx + popq %r15 popq %r14 popq %r13 popq %r12 @@ -37899,6 +38237,7 @@ _sp_4096_cond_add_32: #ifndef __APPLE__ .size sp_4096_cond_add_32,.-sp_4096_cond_add_32 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -38085,6 +38424,7 @@ _sp_4096_cond_add_avx2_32: #ifndef __APPLE__ .size sp_4096_cond_add_avx2_32,.-sp_4096_cond_add_avx2_32 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Shift number left by n bit. (r = a << n) * * r Result of left shift by n. @@ -38103,206 +38443,550 @@ sp_4096_lshift_64: .p2align 4 _sp_4096_lshift_64: #endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + movq %rdi, %r9 movb %dl, %cl - movq $0x00, %r10 - movq 472(%rsi), %r11 - movq 480(%rsi), %rdx - movq 488(%rsi), %rax - movq 496(%rsi), %r8 - movq 504(%rsi), %r9 - shldq %cl, %r9, %r10 - shldq %cl, %r8, %r9 + movq %rsi, %rdx + movq $0x00, %r12 + movq 472(%rdx), %r13 + movq 480(%rdx), %rax + movq 488(%rdx), %r8 + movq 496(%rdx), %r10 + movq 504(%rdx), %r11 + shldq %cl, %r11, %r12 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 480(%rdi) - movq %rax, 488(%rdi) - movq %r8, 496(%rdi) - movq %r9, 504(%rdi) - movq %r10, 512(%rdi) - movq 440(%rsi), %r9 - movq 448(%rsi), %rdx - movq 456(%rsi), %rax - movq 464(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 480(%r9) + movq %r8, 488(%r9) + movq %r10, 496(%r9) + movq %r11, 504(%r9) + movq %r12, 512(%r9) + movq 440(%rdx), %r11 + movq 448(%rdx), %rax + movq 456(%rdx), %r8 + movq 464(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 448(%rdi) - movq %rax, 456(%rdi) - movq %r8, 464(%rdi) - movq %r11, 472(%rdi) - movq 408(%rsi), %r11 - movq 416(%rsi), %rdx - movq 424(%rsi), %rax - movq 432(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 448(%r9) + movq %r8, 456(%r9) + movq %r10, 464(%r9) + movq %r13, 472(%r9) + movq 408(%rdx), %r13 + movq 416(%rdx), %rax + movq 424(%rdx), %r8 + movq 432(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 416(%rdi) - movq %rax, 424(%rdi) - movq %r8, 432(%rdi) - movq %r9, 440(%rdi) - movq 376(%rsi), %r9 - movq 384(%rsi), %rdx - movq 392(%rsi), %rax - movq 400(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 416(%r9) + movq %r8, 424(%r9) + movq %r10, 432(%r9) + movq %r11, 440(%r9) + movq 376(%rdx), %r11 + movq 384(%rdx), %rax + movq 392(%rdx), %r8 + movq 400(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 384(%rdi) - movq %rax, 392(%rdi) - movq %r8, 400(%rdi) - movq %r11, 408(%rdi) - movq 344(%rsi), %r11 - movq 352(%rsi), %rdx - movq 360(%rsi), %rax - movq 368(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 384(%r9) + movq %r8, 392(%r9) + movq %r10, 400(%r9) + movq %r13, 408(%r9) + movq 344(%rdx), %r13 + movq 352(%rdx), %rax + movq 360(%rdx), %r8 + movq 368(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 352(%rdi) - movq %rax, 360(%rdi) - movq %r8, 368(%rdi) - movq %r9, 376(%rdi) - movq 312(%rsi), %r9 - movq 320(%rsi), %rdx - movq 328(%rsi), %rax - movq 336(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 352(%r9) + movq %r8, 360(%r9) + movq %r10, 368(%r9) + movq %r11, 376(%r9) + movq 312(%rdx), %r11 + movq 320(%rdx), %rax + movq 328(%rdx), %r8 + movq 336(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 320(%rdi) - movq %rax, 328(%rdi) - movq %r8, 336(%rdi) - movq %r11, 344(%rdi) - movq 280(%rsi), %r11 - movq 288(%rsi), %rdx - movq 296(%rsi), %rax - movq 304(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 320(%r9) + movq %r8, 328(%r9) + movq %r10, 336(%r9) + movq %r13, 344(%r9) + movq 280(%rdx), %r13 + movq 288(%rdx), %rax + movq 296(%rdx), %r8 + movq 304(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 288(%rdi) - movq %rax, 296(%rdi) - movq %r8, 304(%rdi) - movq %r9, 312(%rdi) - movq 248(%rsi), %r9 - movq 256(%rsi), %rdx - movq 264(%rsi), %rax - movq 272(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 288(%r9) + movq %r8, 296(%r9) + movq %r10, 304(%r9) + movq %r11, 312(%r9) + movq 248(%rdx), %r11 + movq 256(%rdx), %rax + movq 264(%rdx), %r8 + movq 272(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 256(%rdi) - movq %rax, 264(%rdi) - movq %r8, 272(%rdi) - movq %r11, 280(%rdi) - movq 216(%rsi), %r11 - movq 224(%rsi), %rdx - movq 232(%rsi), %rax - movq 240(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 256(%r9) + movq %r8, 264(%r9) + movq %r10, 272(%r9) + movq %r13, 280(%r9) + movq 216(%rdx), %r13 + movq 224(%rdx), %rax + movq 232(%rdx), %r8 + movq 240(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 224(%rdi) - movq %rax, 232(%rdi) - movq %r8, 240(%rdi) - movq %r9, 248(%rdi) - movq 184(%rsi), %r9 - movq 192(%rsi), %rdx - movq 200(%rsi), %rax - movq 208(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 224(%r9) + movq %r8, 232(%r9) + movq %r10, 240(%r9) + movq %r11, 248(%r9) + movq 184(%rdx), %r11 + movq 192(%rdx), %rax + movq 200(%rdx), %r8 + movq 208(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 192(%rdi) - movq %rax, 200(%rdi) - movq %r8, 208(%rdi) - movq %r11, 216(%rdi) - movq 152(%rsi), %r11 - movq 160(%rsi), %rdx - movq 168(%rsi), %rax - movq 176(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 192(%r9) + movq %r8, 200(%r9) + movq %r10, 208(%r9) + movq %r13, 216(%r9) + movq 152(%rdx), %r13 + movq 160(%rdx), %rax + movq 168(%rdx), %r8 + movq 176(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 160(%rdi) - movq %rax, 168(%rdi) - movq %r8, 176(%rdi) - movq %r9, 184(%rdi) - movq 120(%rsi), %r9 - movq 128(%rsi), %rdx - movq 136(%rsi), %rax - movq 144(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 160(%r9) + movq %r8, 168(%r9) + movq %r10, 176(%r9) + movq %r11, 184(%r9) + movq 120(%rdx), %r11 + movq 128(%rdx), %rax + movq 136(%rdx), %r8 + movq 144(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 128(%rdi) - movq %rax, 136(%rdi) - movq %r8, 144(%rdi) - movq %r11, 152(%rdi) - movq 88(%rsi), %r11 - movq 96(%rsi), %rdx - movq 104(%rsi), %rax - movq 112(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 128(%r9) + movq %r8, 136(%r9) + movq %r10, 144(%r9) + movq %r13, 152(%r9) + movq 88(%rdx), %r13 + movq 96(%rdx), %rax + movq 104(%rdx), %r8 + movq 112(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 96(%rdi) - movq %rax, 104(%rdi) - movq %r8, 112(%rdi) - movq %r9, 120(%rdi) - movq 56(%rsi), %r9 - movq 64(%rsi), %rdx - movq 72(%rsi), %rax - movq 80(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 96(%r9) + movq %r8, 104(%r9) + movq %r10, 112(%r9) + movq %r11, 120(%r9) + movq 56(%rdx), %r11 + movq 64(%rdx), %rax + movq 72(%rdx), %r8 + movq 80(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r9, %rdx - movq %rdx, 64(%rdi) - movq %rax, 72(%rdi) - movq %r8, 80(%rdi) - movq %r11, 88(%rdi) - movq 24(%rsi), %r11 - movq 32(%rsi), %rdx - movq 40(%rsi), %rax - movq 48(%rsi), %r8 - shldq %cl, %r8, %r9 + shldq %cl, %r11, %rax + movq %rax, 64(%r9) + movq %r8, 72(%r9) + movq %r10, 80(%r9) + movq %r13, 88(%r9) + movq 24(%rdx), %r13 + movq 32(%rdx), %rax + movq 40(%rdx), %r8 + movq 48(%rdx), %r10 + shldq %cl, %r10, %r11 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shldq %cl, %r11, %rdx - movq %rdx, 32(%rdi) - movq %rax, 40(%rdi) - movq %r8, 48(%rdi) - movq %r9, 56(%rdi) - movq (%rsi), %rdx - movq 8(%rsi), %rax - movq 16(%rsi), %r8 - shldq %cl, %r8, %r11 + shldq %cl, %r13, %rax + movq %rax, 32(%r9) + movq %r8, 40(%r9) + movq %r10, 48(%r9) + movq %r11, 56(%r9) + movq (%rdx), %rax + movq 8(%rdx), %r8 + movq 16(%rdx), %r10 + shldq %cl, %r10, %r13 + shldq %cl, %r8, %r10 shldq %cl, %rax, %r8 - shldq %cl, %rdx, %rax - shlq %cl, %rdx - movq %rdx, (%rdi) - movq %rax, 8(%rdi) - movq %r8, 16(%rdi) - movq %r11, 24(%rdi) + shlq %cl, %rax + movq %rax, (%r9) + movq %r8, 8(%r9) + movq %r10, 16(%r9) + movq %r13, 24(%r9) + popq %r13 + popq %r12 repz retq +#ifndef __APPLE__ +.size sp_4096_lshift_64,.-sp_4096_lshift_64 +#endif /* __APPLE__ */ #endif /* WOLFSSL_SP_4096 */ #endif /* WOLFSSL_SP_4096 */ #ifndef WOLFSSL_SP_NO_256 +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_256_mul_4 +.type sp_256_mul_4,@function +.align 16 +sp_256_mul_4: +#else +.section __TEXT,__text +.globl _sp_256_mul_4 +.p2align 4 +_sp_256_mul_4: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $32, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 24(%rsp) + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 32(%rdi) + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 40(%rdi) + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + addq $32, %rsp + repz retq +#ifndef __APPLE__ +.size sp_256_mul_4,.-sp_256_mul_4 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_256_sqr_4 +.type sp_256_sqr_4,@function +.align 16 +sp_256_sqr_4: +#else +.section __TEXT,__text +.globl _sp_256_sqr_4 +.p2align 4 +_sp_256_sqr_4: +#endif /* __APPLE__ */ + pushq %r12 + subq $32, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %rcx, 24(%rsp) + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + movq %r8, 32(%rdi) + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + movq %r9, 40(%rdi) + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + movq %rcx, 48(%rdi) + movq %r8, 56(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $32, %rsp + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_sqr_4,.-sp_256_sqr_4 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_256_add_4 +.type sp_256_add_4,@function +.align 16 +sp_256_add_4: +#else +.section __TEXT,__text +.globl _sp_256_add_4 +.p2align 4 +_sp_256_add_4: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq %r8, 24(%rdi) + adcq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_add_4,.-sp_256_add_4 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_256_sub_4 +.type sp_256_sub_4,@function +.align 16 +sp_256_sub_4: +#else +.section __TEXT,__text +.globl _sp_256_sub_4 +.p2align 4 +_sp_256_sub_4: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + subq (%rdx), %rcx + sbbq 8(%rdx), %r8 + sbbq 16(%rdx), %r9 + sbbq 24(%rdx), %r10 + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + sbbq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_sub_4,.-sp_256_sub_4 +#endif /* __APPLE__ */ /* Conditionally copy a into r using the mask m. * m is -1 to copy and 0 when not. * @@ -38842,42 +39526,6 @@ _sp_256_cond_sub_4: #ifndef __APPLE__ .size sp_256_cond_sub_4,.-sp_256_cond_sub_4 #endif /* __APPLE__ */ -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -#ifndef __APPLE__ -.text -.globl sp_256_sub_4 -.type sp_256_sub_4,@function -.align 16 -sp_256_sub_4: -#else -.section __TEXT,__text -.globl _sp_256_sub_4 -.p2align 4 -_sp_256_sub_4: -#endif /* __APPLE__ */ - xorq %rax, %rax - movq (%rsi), %rcx - movq 8(%rsi), %r8 - movq 16(%rsi), %r9 - movq 24(%rsi), %r10 - subq (%rdx), %rcx - sbbq 8(%rdx), %r8 - sbbq 16(%rdx), %r9 - sbbq 24(%rdx), %r10 - movq %rcx, (%rdi) - movq %r8, 8(%rdi) - movq %r9, 16(%rdi) - movq %r10, 24(%rdi) - sbbq $0x00, %rax - repz retq -#ifndef __APPLE__ -.size sp_256_sub_4,.-sp_256_sub_4 -#endif /* __APPLE__ */ /* Reduce the number back to 256 bits using Montgomery reduction. * * a A single precision number to reduce in place. @@ -39021,6 +39669,13 @@ _sp_256_mont_add_4: andq %rsi, %r11 subq %rsi, %rax sbbq %r10, %rcx + sbbq $0x00, %r8 + sbbq %r11, %r9 + adcq $0x00, %rsi + andq %rsi, %r10 + andq %rsi, %r11 + subq %rsi, %rax + sbbq %r10, %rcx movq %rax, (%rdi) sbbq $0x00, %r8 movq %rcx, 8(%rdi) @@ -39065,6 +39720,13 @@ _sp_256_mont_dbl_4: andq %r11, %r10 subq %r11, %rdx sbbq %r9, %rax + sbbq $0x00, %rcx + sbbq %r10, %r8 + adcq $0x00, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax movq %rdx, (%rdi) sbbq $0x00, %rcx movq %rax, 8(%rdi) @@ -39111,6 +39773,13 @@ _sp_256_mont_tpl_4: sbbq %r9, %rax sbbq $0x00, %rcx sbbq %r10, %r8 + adcq $0x00, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + sbbq $0x00, %rcx + sbbq %r10, %r8 movq $0xffffffff, %r9 movq $0xffffffff00000001, %r10 addq (%rsi), %rdx @@ -39123,6 +39792,13 @@ _sp_256_mont_tpl_4: andq %r11, %r10 subq %r11, %rdx sbbq %r9, %rax + sbbq $0x00, %rcx + sbbq %r10, %r8 + adcq $0x00, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax movq %rdx, (%rdi) sbbq $0x00, %rcx movq %rax, 8(%rdi) @@ -39168,6 +39844,13 @@ _sp_256_mont_sub_4: andq %rsi, %r11 addq %rsi, %rax adcq %r10, %rcx + adcq $0x00, %r8 + adcq %r11, %r9 + adcq $0x00, %rsi + andq %rsi, %r10 + andq %rsi, %r11 + addq %rsi, %rax + adcq %r10, %rcx movq %rax, (%rdi) adcq $0x00, %r8 movq %rcx, 8(%rdi) @@ -39294,6 +39977,7 @@ L_256_get_point_33_4_start: #ifndef __APPLE__ .size sp_256_get_point_33_4,.-sp_256_get_point_33_4 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Touch each possible point that could be being copied. * * r Point to copy into. @@ -39327,9 +40011,9 @@ _sp_256_get_point_33_avx2_4: L_256_get_point_33_avx2_4_start: vpcmpeqd %ymm7, %ymm8, %ymm6 vpaddd %ymm9, %ymm8, %ymm8 - vmovdqu (%rsi), %ymm3 - vmovdqu 64(%rsi), %ymm4 - vmovdqu 128(%rsi), %ymm5 + vmovupd (%rsi), %ymm3 + vmovupd 64(%rsi), %ymm4 + vmovupd 128(%rsi), %ymm5 addq $0xc8, %rsi vpand %ymm6, %ymm3, %ymm3 vpand %ymm6, %ymm4, %ymm4 @@ -39339,14 +40023,16 @@ L_256_get_point_33_avx2_4_start: vpor %ymm5, %ymm2, %ymm2 decq %rax jnz L_256_get_point_33_avx2_4_start - vmovdqu %ymm0, (%rdi) - vmovdqu %ymm1, 64(%rdi) - vmovdqu %ymm2, 128(%rdi) + vmovupd %ymm0, (%rdi) + vmovupd %ymm1, 64(%rdi) + vmovupd %ymm2, 128(%rdi) repz retq #ifndef __APPLE__ .size sp_256_get_point_33_avx2_4,.-sp_256_get_point_33_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #endif /* !WC_NO_CACHE_RESISTANT */ +#ifdef HAVE_INTEL_AVX2 /* Multiply two Montogmery form numbers mod the modulus (prime). * (r = a * b mod m) * @@ -39369,11 +40055,11 @@ sp_256_mont_mul_avx2_4: _sp_256_mont_mul_avx2_4: #endif /* __APPLE__ */ pushq %rbx - pushq %rbp pushq %r12 pushq %r13 pushq %r14 pushq %r15 + pushq %rbp movq %rdx, %rbp # A[0] * B[0] movq (%rbp), %rdx @@ -39522,16 +40208,18 @@ _sp_256_mont_mul_avx2_4: movq %r13, 8(%rdi) movq %r14, 16(%rdi) movq %r15, 24(%rdi) + popq %rbp popq %r15 popq %r14 popq %r13 popq %r12 - popq %rbp popq %rbx repz retq #ifndef __APPLE__ .size sp_256_mont_mul_avx2_4,.-sp_256_mont_mul_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) * * r Result of squaring. @@ -39690,6 +40378,276 @@ _sp_256_mont_sqr_avx2_4: #ifndef __APPLE__ .size sp_256_mont_sqr_avx2_4,.-sp_256_mont_sqr_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_256_cond_sub_avx2_4 +.type sp_256_cond_sub_avx2_4,@function +.align 16 +sp_256_cond_sub_avx2_4: +#else +.section __TEXT,__text +.globl _sp_256_cond_sub_avx2_4 +.p2align 4 +_sp_256_cond_sub_avx2_4: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq $0x00, %rax + movq (%rdx), %r12 + movq 8(%rdx), %r13 + movq 16(%rdx), %r14 + movq 24(%rdx), %r15 + andq %rcx, %r12 + andq %rcx, %r13 + andq %rcx, %r14 + andq %rcx, %r15 + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq %r12, %r8 + sbbq %r13, %r9 + sbbq %r14, %r10 + sbbq %r15, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + sbbq $0x00, %rax + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_cond_sub_avx2_4,.-sp_256_cond_sub_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.text +.globl sp_256_mont_reduce_avx2_4 +.type sp_256_mont_reduce_avx2_4,@function +.align 16 +sp_256_mont_reduce_avx2_4: +#else +.section __TEXT,__text +.globl _sp_256_mont_reduce_avx2_4 +.p2align 4 +_sp_256_mont_reduce_avx2_4: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rax + movq (%rdi), %r12 + movq 8(%rdi), %r13 + movq 16(%rdi), %r14 + movq 24(%rdi), %r15 + xorq %r11, %r11 + xorq %r10, %r10 + # a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp) + movq 32(%rdi), %rbx + # mu = a[0] * mp + movq %r12, %rdx + mulxq %rax, %rdx, %rcx + # a[0] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r12 + # a[1] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r13 + adcxq %r8, %r13 + # a[2] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r14 + adcxq %r8, %r14 + # a[3] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r15 + adcxq %r8, %r15 + # a[4] += carry + adoxq %rcx, %rbx + adcxq %r10, %rbx + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp) + movq 40(%rdi), %r12 + # mu = a[1] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %rcx + # a[1] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r13 + # a[2] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r14 + adcxq %r8, %r14 + # a[3] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r15 + adcxq %r8, %r15 + # a[4] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %rbx + adcxq %r8, %rbx + # a[5] += carry + adoxq %rcx, %r12 + adcxq %r11, %r12 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp) + movq 48(%rdi), %r13 + # mu = a[2] * mp + movq %r14, %rdx + mulxq %rax, %rdx, %rcx + # a[2] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r14 + # a[3] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r15 + adcxq %r8, %r15 + # a[4] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %rbx + adcxq %r8, %rbx + # a[5] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r12 + adcxq %r8, %r12 + # a[6] += carry + adoxq %rcx, %r13 + adcxq %r11, %r13 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp) + movq 56(%rdi), %r14 + # mu = a[3] * mp + movq %r15, %rdx + mulxq %rax, %rdx, %rcx + # a[3] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r15 + # a[4] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %rbx + adcxq %r8, %rbx + # a[5] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r12 + adcxq %r8, %r12 + # a[6] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r13 + adcxq %r8, %r13 + # a[7] += carry + adoxq %rcx, %r14 + adcxq %r11, %r14 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # Subtract mod if carry + negq %r11 + movq $0xf3b9cac2fc632551, %r8 + movq $0xbce6faada7179e84, %r9 + movq $0xffffffff00000000, %rdx + andq %r11, %r8 + andq %r11, %r9 + andq %r11, %rdx + subq %r8, %rbx + sbbq %r9, %r12 + sbbq %r11, %r13 + sbbq %rdx, %r14 + movq %rbx, (%rdi) + movq %r12, 8(%rdi) + movq %r13, 16(%rdi) + movq %r14, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_reduce_avx2_4,.-sp_256_mont_reduce_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_256_div2_avx2_4 +.type sp_256_div2_avx2_4,@function +.align 16 +sp_256_div2_avx2_4: +#else +.section __TEXT,__text +.globl _sp_256_div2_avx2_4 +.p2align 4 +_sp_256_div2_avx2_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq $0xffffffff, %r9 + movq $0xffffffff00000001, %r10 + movq %rdx, %r11 + andq $0x01, %r11 + negq %r11 + andq %r11, %r9 + andq %r11, %r10 + addq %r11, %rdx + adcq %r9, %rax + adcq $0x00, %rcx + adcq %r10, %r8 + movq $0x00, %r11 + adcq $0x00, %r11 + shrdq $0x01, %rax, %rdx + shrdq $0x01, %rcx, %rax + shrdq $0x01, %r8, %rcx + shrdq $0x01, %r11, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_div2_avx2_4,.-sp_256_div2_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #ifndef WC_NO_CACHE_RESISTANT /* Touch each possible entry that could be being copied. * @@ -39726,10 +40684,10 @@ L_256_get_entry_64_4_start: movdqa %xmm10, %xmm8 paddd %xmm11, %xmm10 pcmpeqd %xmm9, %xmm8 - movdqa (%rsi), %xmm4 - movdqa 16(%rsi), %xmm5 - movdqa 32(%rsi), %xmm6 - movdqa 48(%rsi), %xmm7 + movdqu (%rsi), %xmm4 + movdqu 16(%rsi), %xmm5 + movdqu 32(%rsi), %xmm6 + movdqu 48(%rsi), %xmm7 addq $0x40, %rsi pand %xmm8, %xmm4 pand %xmm8, %xmm5 @@ -39749,6 +40707,7 @@ L_256_get_entry_64_4_start: #ifndef __APPLE__ .size sp_256_get_entry_64_4,.-sp_256_get_entry_64_4 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Touch each possible entry that could be being copied. * * r Point to copy into. @@ -39781,8 +40740,8 @@ _sp_256_get_entry_64_avx2_4: L_256_get_entry_64_avx2_4_start: vpcmpeqd %ymm5, %ymm6, %ymm4 vpaddd %ymm7, %ymm6, %ymm6 - vmovdqu (%rsi), %ymm2 - vmovdqu 32(%rsi), %ymm3 + vmovupd (%rsi), %ymm2 + vmovupd 32(%rsi), %ymm3 addq $0x40, %rsi vpand %ymm4, %ymm2, %ymm2 vpand %ymm4, %ymm3, %ymm3 @@ -39790,12 +40749,13 @@ L_256_get_entry_64_avx2_4_start: vpor %ymm3, %ymm1, %ymm1 decq %rax jnz L_256_get_entry_64_avx2_4_start - vmovdqu %ymm0, (%rdi) - vmovdqu %ymm1, 64(%rdi) + vmovupd %ymm0, (%rdi) + vmovupd %ymm1, 64(%rdi) repz retq #ifndef __APPLE__ .size sp_256_get_entry_64_avx2_4,.-sp_256_get_entry_64_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #endif /* !WC_NO_CACHE_RESISTANT */ #ifndef WC_NO_CACHE_RESISTANT /* Touch each possible entry that could be being copied. @@ -39833,10 +40793,10 @@ L_256_get_entry_65_4_start: movdqa %xmm10, %xmm8 paddd %xmm11, %xmm10 pcmpeqd %xmm9, %xmm8 - movdqa (%rsi), %xmm4 - movdqa 16(%rsi), %xmm5 - movdqa 32(%rsi), %xmm6 - movdqa 48(%rsi), %xmm7 + movdqu (%rsi), %xmm4 + movdqu 16(%rsi), %xmm5 + movdqu 32(%rsi), %xmm6 + movdqu 48(%rsi), %xmm7 addq $0x40, %rsi pand %xmm8, %xmm4 pand %xmm8, %xmm5 @@ -39856,6 +40816,7 @@ L_256_get_entry_65_4_start: #ifndef __APPLE__ .size sp_256_get_entry_65_4,.-sp_256_get_entry_65_4 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Touch each possible entry that could be being copied. * * r Point to copy into. @@ -39888,8 +40849,8 @@ _sp_256_get_entry_65_avx2_4: L_256_get_entry_65_avx2_4_start: vpcmpeqd %ymm5, %ymm6, %ymm4 vpaddd %ymm7, %ymm6, %ymm6 - vmovdqu (%rsi), %ymm2 - vmovdqu 32(%rsi), %ymm3 + vmovupd (%rsi), %ymm2 + vmovupd 32(%rsi), %ymm3 addq $0x40, %rsi vpand %ymm4, %ymm2, %ymm2 vpand %ymm4, %ymm3, %ymm3 @@ -39897,12 +40858,13 @@ L_256_get_entry_65_avx2_4_start: vpor %ymm3, %ymm1, %ymm1 decq %rax jnz L_256_get_entry_65_avx2_4_start - vmovdqu %ymm0, (%rdi) - vmovdqu %ymm1, 64(%rdi) + vmovupd %ymm0, (%rdi) + vmovupd %ymm1, 64(%rdi) repz retq #ifndef __APPLE__ .size sp_256_get_entry_65_avx2_4,.-sp_256_get_entry_65_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #endif /* !WC_NO_CACHE_RESISTANT */ /* Add 1 to a. (a = a + 1) * @@ -40022,6 +40984,7 @@ L_256_from_bin_bswap_zero_end: #ifndef __APPLE__ .size sp_256_from_bin_bswap,.-sp_256_from_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Read big endian unsigned byte array into r. * Uses the movbe instruction which is an optional instruction. * @@ -40107,6 +41070,7 @@ L_256_from_bin_movbe_zero_end: #ifndef __APPLE__ .size sp_256_from_bin_movbe,.-sp_256_from_bin_movbe #endif /* __APPLE__ */ +#endif /* !NO_MOVBE_SUPPORT */ /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 * Uses the bswap instruction. @@ -40142,6 +41106,7 @@ _sp_256_to_bin_bswap: #ifndef __APPLE__ .size sp_256_to_bin_bswap,.-sp_256_to_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 * Uses the movbe instruction which is optional. @@ -40173,183 +41138,8 @@ _sp_256_to_bin_movbe: #ifndef __APPLE__ .size sp_256_to_bin_movbe,.-sp_256_to_bin_movbe #endif /* __APPLE__ */ -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -#ifndef __APPLE__ -.text -.globl sp_256_add_4 -.type sp_256_add_4,@function -.align 16 -sp_256_add_4: -#else -.section __TEXT,__text -.globl _sp_256_add_4 -.p2align 4 -_sp_256_add_4: -#endif /* __APPLE__ */ - # Add - movq (%rsi), %rcx - xorq %rax, %rax - addq (%rdx), %rcx - movq 8(%rsi), %r8 - movq %rcx, (%rdi) - adcq 8(%rdx), %r8 - movq 16(%rsi), %rcx - movq %r8, 8(%rdi) - adcq 16(%rdx), %rcx - movq 24(%rsi), %r8 - movq %rcx, 16(%rdi) - adcq 24(%rdx), %r8 - movq %r8, 24(%rdi) - adcq $0x00, %rax - repz retq -#ifndef __APPLE__ -.size sp_256_add_4,.-sp_256_add_4 -#endif /* __APPLE__ */ -/* Multiply a and b into r. (r = a * b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -#ifndef __APPLE__ -.text -.globl sp_256_mul_4 -.type sp_256_mul_4,@function -.align 16 -sp_256_mul_4: -#else -.section __TEXT,__text -.globl _sp_256_mul_4 -.p2align 4 -_sp_256_mul_4: -#endif /* __APPLE__ */ - movq %rdx, %rcx - subq $32, %rsp - # A[0] * B[0] - movq (%rcx), %rax - mulq (%rsi) - xorq %r10, %r10 - movq %rax, (%rsp) - movq %rdx, %r9 - # A[0] * B[1] - movq 8(%rcx), %rax - mulq (%rsi) - xorq %r8, %r8 - addq %rax, %r9 - adcq %rdx, %r10 - adcq $0x00, %r8 - # A[1] * B[0] - movq (%rcx), %rax - mulq 8(%rsi) - addq %rax, %r9 - adcq %rdx, %r10 - adcq $0x00, %r8 - movq %r9, 8(%rsp) - # A[0] * B[2] - movq 16(%rcx), %rax - mulq (%rsi) - xorq %r9, %r9 - addq %rax, %r10 - adcq %rdx, %r8 - adcq $0x00, %r9 - # A[1] * B[1] - movq 8(%rcx), %rax - mulq 8(%rsi) - addq %rax, %r10 - adcq %rdx, %r8 - adcq $0x00, %r9 - # A[2] * B[0] - movq (%rcx), %rax - mulq 16(%rsi) - addq %rax, %r10 - adcq %rdx, %r8 - adcq $0x00, %r9 - movq %r10, 16(%rsp) - # A[0] * B[3] - movq 24(%rcx), %rax - mulq (%rsi) - xorq %r10, %r10 - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %r10 - # A[1] * B[2] - movq 16(%rcx), %rax - mulq 8(%rsi) - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %r10 - # A[2] * B[1] - movq 8(%rcx), %rax - mulq 16(%rsi) - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %r10 - # A[3] * B[0] - movq (%rcx), %rax - mulq 24(%rsi) - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %r10 - movq %r8, 24(%rsp) - # A[1] * B[3] - movq 24(%rcx), %rax - mulq 8(%rsi) - xorq %r8, %r8 - addq %rax, %r9 - adcq %rdx, %r10 - adcq $0x00, %r8 - # A[2] * B[2] - movq 16(%rcx), %rax - mulq 16(%rsi) - addq %rax, %r9 - adcq %rdx, %r10 - adcq $0x00, %r8 - # A[3] * B[1] - movq 8(%rcx), %rax - mulq 24(%rsi) - addq %rax, %r9 - adcq %rdx, %r10 - adcq $0x00, %r8 - movq %r9, 32(%rdi) - # A[2] * B[3] - movq 24(%rcx), %rax - mulq 16(%rsi) - xorq %r9, %r9 - addq %rax, %r10 - adcq %rdx, %r8 - adcq $0x00, %r9 - # A[3] * B[2] - movq 16(%rcx), %rax - mulq 24(%rsi) - addq %rax, %r10 - adcq %rdx, %r8 - adcq $0x00, %r9 - movq %r10, 40(%rdi) - # A[3] * B[3] - movq 24(%rcx), %rax - mulq 24(%rsi) - addq %rax, %r8 - adcq %rdx, %r9 - movq %r8, 48(%rdi) - movq %r9, 56(%rdi) - movq (%rsp), %rax - movq 8(%rsp), %rdx - movq 16(%rsp), %r8 - movq 24(%rsp), %r9 - movq %rax, (%rdi) - movq %rdx, 8(%rdi) - movq %r8, 16(%rdi) - movq %r9, 24(%rdi) - addq $32, %rsp - repz retq -#ifndef __APPLE__ -.size sp_256_mul_4,.-sp_256_mul_4 -#endif /* __APPLE__ */ +#endif /* NO_MOVBE_SUPPORT */ +#ifdef HAVE_INTEL_AVX2 /* Multiply a and b into r. (r = a * b) * * r Result of multiplication. @@ -40369,11 +41159,11 @@ sp_256_mul_avx2_4: _sp_256_mul_avx2_4: #endif /* __APPLE__ */ pushq %rbx - pushq %rbp pushq %r12 pushq %r13 pushq %r14 pushq %r15 + pushq %rbp movq %rdx, %rbp # A[0] * B[0] movq (%rbp), %rdx @@ -40459,16 +41249,17 @@ _sp_256_mul_avx2_4: movq %r13, 40(%rdi) movq %r14, 48(%rdi) movq %r15, 56(%rdi) + popq %rbp popq %r15 popq %r14 popq %r13 popq %r12 - popq %rbp popq %rbx repz retq #ifndef __APPLE__ .size sp_256_mul_avx2_4,.-sp_256_mul_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Sub b from a into a. (a -= b) * * a A single precision integer and result. @@ -40500,60 +41291,6 @@ _sp_256_sub_in_place_4: #ifndef __APPLE__ .size sp_256_sub_in_place_4,.-sp_256_sub_in_place_4 #endif /* __APPLE__ */ -/* Conditionally subtract b from a using the mask m. - * m is -1 to subtract and 0 when not copying. - * - * r A single precision number representing condition subtract result. - * a A single precision number to subtract from. - * b A single precision number to subtract. - * m Mask value to apply. - */ -#ifndef __APPLE__ -.text -.globl sp_256_cond_sub_avx2_4 -.type sp_256_cond_sub_avx2_4,@function -.align 16 -sp_256_cond_sub_avx2_4: -#else -.section __TEXT,__text -.globl _sp_256_cond_sub_avx2_4 -.p2align 4 -_sp_256_cond_sub_avx2_4: -#endif /* __APPLE__ */ - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - movq $0x00, %rax - movq (%rdx), %r12 - movq 8(%rdx), %r13 - movq 16(%rdx), %r14 - movq 24(%rdx), %r15 - andq %rcx, %r12 - andq %rcx, %r13 - andq %rcx, %r14 - andq %rcx, %r15 - movq (%rsi), %r8 - movq 8(%rsi), %r9 - movq 16(%rsi), %r10 - movq 24(%rsi), %r11 - subq %r12, %r8 - sbbq %r13, %r9 - sbbq %r14, %r10 - sbbq %r15, %r11 - movq %r8, (%rdi) - movq %r9, 8(%rdi) - movq %r10, 16(%rdi) - movq %r11, 24(%rdi) - sbbq $0x00, %rax - popq %r15 - popq %r14 - popq %r13 - popq %r12 - repz retq -#ifndef __APPLE__ -.size sp_256_cond_sub_avx2_4,.-sp_256_cond_sub_avx2_4 -#endif /* __APPLE__ */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -40636,14 +41373,14 @@ _sp_256_mul_d_avx2_4: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 @@ -40657,128 +41394,36 @@ _sp_256_mul_d_avx2_4: .size sp_256_mul_d_avx2_4,.-sp_256_mul_d_avx2_4 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ -/* Square a and put result in r. (r = a * a) +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) * - * r A single precision integer. - * a A single precision integer. + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. */ #ifndef __APPLE__ .text -.globl sp_256_sqr_4 -.type sp_256_sqr_4,@function +.globl div_256_word_asm_4 +.type div_256_word_asm_4,@function .align 16 -sp_256_sqr_4: +div_256_word_asm_4: #else .section __TEXT,__text -.globl _sp_256_sqr_4 +.globl _div_256_word_asm_4 .p2align 4 -_sp_256_sqr_4: +_div_256_word_asm_4: #endif /* __APPLE__ */ - pushq %r12 - subq $32, %rsp - # A[0] * A[0] - movq (%rsi), %rax - mulq %rax - xorq %r9, %r9 - movq %rax, (%rsp) - movq %rdx, %r8 - # A[0] * A[1] - movq 8(%rsi), %rax - mulq (%rsi) - xorq %rcx, %rcx - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %rcx - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %rcx - movq %r8, 8(%rsp) - # A[0] * A[2] - movq 16(%rsi), %rax - mulq (%rsi) - xorq %r8, %r8 - addq %rax, %r9 - adcq %rdx, %rcx - adcq $0x00, %r8 - addq %rax, %r9 - adcq %rdx, %rcx - adcq $0x00, %r8 - # A[1] * A[1] - movq 8(%rsi), %rax - mulq %rax - addq %rax, %r9 - adcq %rdx, %rcx - adcq $0x00, %r8 - movq %r9, 16(%rsp) - # A[0] * A[3] - movq 24(%rsi), %rax - mulq (%rsi) - xorq %r9, %r9 - addq %rax, %rcx - adcq %rdx, %r8 - adcq $0x00, %r9 - addq %rax, %rcx - adcq %rdx, %r8 - adcq $0x00, %r9 - # A[1] * A[2] - movq 16(%rsi), %rax - mulq 8(%rsi) - addq %rax, %rcx - adcq %rdx, %r8 - adcq $0x00, %r9 - addq %rax, %rcx - adcq %rdx, %r8 - adcq $0x00, %r9 - movq %rcx, 24(%rsp) - # A[1] * A[3] - movq 24(%rsi), %rax - mulq 8(%rsi) - xorq %rcx, %rcx - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %rcx - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %rcx - # A[2] * A[2] - movq 16(%rsi), %rax - mulq %rax - addq %rax, %r8 - adcq %rdx, %r9 - adcq $0x00, %rcx - movq %r8, 32(%rdi) - # A[2] * A[3] - movq 24(%rsi), %rax - mulq 16(%rsi) - xorq %r8, %r8 - addq %rax, %r9 - adcq %rdx, %rcx - adcq $0x00, %r8 - addq %rax, %r9 - adcq %rdx, %rcx - adcq $0x00, %r8 - movq %r9, 40(%rdi) - # A[3] * A[3] - movq 24(%rsi), %rax - mulq %rax - addq %rax, %rcx - adcq %rdx, %r8 - movq %rcx, 48(%rdi) - movq %r8, 56(%rdi) - movq (%rsp), %rax - movq 8(%rsp), %rdx - movq 16(%rsp), %r10 - movq 24(%rsp), %r11 - movq %rax, (%rdi) - movq %rdx, 8(%rdi) - movq %r10, 16(%rdi) - movq %r11, 24(%rdi) - addq $32, %rsp - popq %r12 + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx repz retq #ifndef __APPLE__ -.size sp_256_sqr_4,.-sp_256_sqr_4 +.size div_256_word_asm_4,.-div_256_word_asm_4 #endif /* __APPLE__ */ +#endif /* _WIN64 */ +#ifdef HAVE_INTEL_AVX2 /* Multiply two Montogmery form numbers mod the modulus (prime). * (r = a * b mod m) * @@ -40799,11 +41444,11 @@ sp_256_mont_mul_order_avx2_4: _sp_256_mont_mul_order_avx2_4: #endif /* __APPLE__ */ pushq %rbx - pushq %rbp pushq %r12 pushq %r13 pushq %r14 pushq %r15 + pushq %rbp movq %rdx, %rbp # A[0] * B[0] movq (%rbp), %rdx @@ -40883,6 +41528,7 @@ _sp_256_mont_mul_order_avx2_4: adoxq %rcx, %r15 # Start Reduction movq $0xccd1c8aaee00bc4f, %rbx + # A[0] movq %rbx, %rdx imulq %r8, %rdx movq $0xf3b9cac2fc632551, %rax @@ -40907,6 +41553,7 @@ _sp_256_mont_mul_order_avx2_4: # carry adoxq %rbp, %r8 adcxq %rbp, %r8 + # A[1] movq %rbx, %rdx imulq %r9, %rdx movq $0xf3b9cac2fc632551, %rax @@ -40931,6 +41578,7 @@ _sp_256_mont_mul_order_avx2_4: # carry adoxq %rbp, %r8 adcxq %rbp, %r8 + # A[2] movq %rbx, %rdx imulq %r10, %rdx movq $0xf3b9cac2fc632551, %rax @@ -40955,6 +41603,7 @@ _sp_256_mont_mul_order_avx2_4: # carry adoxq %rbp, %r8 adcxq %rbp, %r8 + # A[3] movq %rbx, %rdx imulq %r11, %rdx movq $0xf3b9cac2fc632551, %rax @@ -40994,16 +41643,18 @@ _sp_256_mont_mul_order_avx2_4: sbbq %rbp, %r15 movq %r14, 16(%rdi) movq %r15, 24(%rdi) + popq %rbp popq %r15 popq %r14 popq %r13 popq %r12 - popq %rbp popq %rbx repz retq #ifndef __APPLE__ .size sp_256_mont_mul_order_avx2_4,.-sp_256_mont_mul_order_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) * * r Result of squaring. @@ -41083,6 +41734,7 @@ _sp_256_mont_sqr_order_avx2_4: adoxq %rbx, %r15 # Start Reduction movq $0xccd1c8aaee00bc4f, %rbx + # A[0] movq %rbx, %rdx imulq %r8, %rdx movq $0xf3b9cac2fc632551, %rax @@ -41107,6 +41759,7 @@ _sp_256_mont_sqr_order_avx2_4: # carry adoxq %rbp, %r8 adcxq %rbp, %r8 + # A[1] movq %rbx, %rdx imulq %r9, %rdx movq $0xf3b9cac2fc632551, %rax @@ -41131,6 +41784,7 @@ _sp_256_mont_sqr_order_avx2_4: # carry adoxq %rbp, %r8 adcxq %rbp, %r8 + # A[2] movq %rbx, %rdx imulq %r10, %rdx movq $0xf3b9cac2fc632551, %rax @@ -41155,6 +41809,7 @@ _sp_256_mont_sqr_order_avx2_4: # carry adoxq %rbp, %r8 adcxq %rbp, %r8 + # A[3] movq %rbx, %rdx imulq %r11, %rdx movq $0xf3b9cac2fc632551, %rax @@ -41204,6 +41859,7 @@ _sp_256_mont_sqr_order_avx2_4: #ifndef __APPLE__ .size sp_256_mont_sqr_order_avx2_4,.-sp_256_mont_sqr_order_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ /* Non-constant time modular inversion. * * @param [out] r Resulting number. @@ -41431,6 +42087,7 @@ L_256_mod_inv_4_store_end: #ifndef __APPLE__ .size sp_256_mod_inv_4,.-sp_256_mod_inv_4 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 #ifndef __APPLE__ .data #else @@ -41534,15 +42191,15 @@ _sp_256_mod_inv_avx2_4: movq 8(%rsi), %r11 movq 16(%rsi), %r12 movq 24(%rsi), %r13 - vmovdqu 0+L_sp256_mod_inv_avx2_4_order(%rip), %ymm6 - vmovdqu 32+L_sp256_mod_inv_avx2_4_order(%rip), %ymm7 - vmovdqu 0+L_sp256_mod_inv_avx2_4_one(%rip), %ymm8 - vmovdqu 0+L_sp256_mod_inv_avx2_4_mask01111(%rip), %ymm9 - vmovdqu 0+L_sp256_mod_inv_avx2_4_all_one(%rip), %ymm10 - vmovdqu L_sp256_mod_inv_avx2_4_down_one_dword(%rip), %ymm11 - vmovdqu L_sp256_mod_inv_avx2_4_neg(%rip), %ymm12 - vmovdqu L_sp256_mod_inv_avx2_4_up_one_dword(%rip), %ymm13 - vmovdqu L_sp256_mod_inv_avx2_4_mask26(%rip), %ymm14 + vmovupd 0+L_sp256_mod_inv_avx2_4_order(%rip), %ymm6 + vmovupd 32+L_sp256_mod_inv_avx2_4_order(%rip), %ymm7 + vmovupd 0+L_sp256_mod_inv_avx2_4_one(%rip), %ymm8 + vmovupd 0+L_sp256_mod_inv_avx2_4_mask01111(%rip), %ymm9 + vmovupd 0+L_sp256_mod_inv_avx2_4_all_one(%rip), %ymm10 + vmovupd 0+L_sp256_mod_inv_avx2_4_down_one_dword(%rip), %ymm11 + vmovupd 0+L_sp256_mod_inv_avx2_4_neg(%rip), %ymm12 + vmovupd 0+L_sp256_mod_inv_avx2_4_up_one_dword(%rip), %ymm13 + vmovupd 0+L_sp256_mod_inv_avx2_4_mask26(%rip), %ymm14 vpxor %xmm0, %xmm0, %xmm0 vpxor %xmm1, %xmm1, %xmm1 vmovdqu %ymm8, %ymm2 @@ -41630,6 +42287,13 @@ L_256_mod_inv_avx2_4_usubv_sub_shr1: vpand %ymm14, %ymm1, %ymm1 vpaddd %ymm5, %ymm0, %ymm0 vpaddd %ymm4, %ymm1, %ymm1 + vpsrad $26, %ymm1, %ymm5 + vpsrad $26, %ymm0, %ymm4 + vpermd %ymm5, %ymm13, %ymm5 + vpand %ymm14, %ymm0, %ymm0 + vpand %ymm14, %ymm1, %ymm1 + vpaddd %ymm5, %ymm0, %ymm0 + vpaddd %ymm4, %ymm1, %ymm1 vpextrd $0x00, %xmm0, %eax vpextrd $0x01, %xmm0, %r8d vpextrd $2, %xmm0, %r10d @@ -41690,6 +42354,13 @@ L_256_mod_inv_avx2_4_vsubu_sub_shr1: vpand %ymm14, %ymm3, %ymm3 vpaddd %ymm5, %ymm2, %ymm2 vpaddd %ymm4, %ymm3, %ymm3 + vpsrad $26, %ymm3, %ymm5 + vpsrad $26, %ymm2, %ymm4 + vpermd %ymm5, %ymm13, %ymm5 + vpand %ymm14, %ymm2, %ymm2 + vpand %ymm14, %ymm3, %ymm3 + vpaddd %ymm5, %ymm2, %ymm2 + vpaddd %ymm4, %ymm3, %ymm3 vpextrd $0x00, %xmm2, %eax vpextrd $0x01, %xmm2, %r8d vpextrd $2, %xmm2, %r10d @@ -41703,14 +42374,19 @@ L_256_mod_inv_avx2_4_vsubu_sub_shr1: vpextrd $0x00, %xmm2, %r14d vpextrd $0x00, %xmm3, %r15d L_256_mod_inv_avx2_4_store_done: + movslq %eax, %rax shlq $26, %rcx addq %rcx, %rax + movslq %r8d, %r8 shlq $26, %r9 addq %r9, %r8 + movslq %r10d, %r10 shlq $26, %r11 addq %r11, %r10 + movslq %r12d, %r12 shlq $26, %r13 addq %r13, %r12 + movslq %r14d, %r14 shlq $26, %r15 addq %r15, %r14 movq %r8, %rcx @@ -41740,55 +42416,9 @@ L_256_mod_inv_avx2_4_store_done: #ifndef __APPLE__ .size sp_256_mod_inv_avx2_4,.-sp_256_mod_inv_avx2_4 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #endif /* !WOLFSSL_SP_NO_256 */ #ifdef WOLFSSL_SP_384 -/* Conditionally copy a into r using the mask m. - * m is -1 to copy and 0 when not. - * - * r A single precision number to copy over. - * a A single precision number to copy. - * m Mask value to apply. - */ -#ifndef __APPLE__ -.text -.globl sp_384_cond_copy_6 -.type sp_384_cond_copy_6,@function -.align 16 -sp_384_cond_copy_6: -#else -.section __TEXT,__text -.globl _sp_384_cond_copy_6 -.p2align 4 -_sp_384_cond_copy_6: -#endif /* __APPLE__ */ - movq (%rdi), %rax - movq 8(%rdi), %rcx - movq 16(%rdi), %r8 - movq 24(%rdi), %r9 - movq 32(%rdi), %r10 - movq 40(%rdi), %r11 - xorq (%rsi), %rax - xorq 8(%rsi), %rcx - xorq 16(%rsi), %r8 - xorq 24(%rsi), %r9 - xorq 32(%rsi), %r10 - xorq 40(%rsi), %r11 - andq %rdx, %rax - andq %rdx, %rcx - andq %rdx, %r8 - andq %rdx, %r9 - andq %rdx, %r10 - andq %rdx, %r11 - xorq %rax, (%rdi) - xorq %rcx, 8(%rdi) - xorq %r8, 16(%rdi) - xorq %r9, 24(%rdi) - xorq %r10, 32(%rdi) - xorq %r11, 40(%rdi) - repz retq -#ifndef __APPLE__ -.size sp_384_cond_copy_6,.-sp_384_cond_copy_6 -#endif /* __APPLE__ */ /* Multiply a and b into r. (r = a * b) * * r A single precision integer. @@ -42061,371 +42691,6 @@ _sp_384_mul_6: #ifndef __APPLE__ .size sp_384_mul_6,.-sp_384_mul_6 #endif /* __APPLE__ */ -/* Conditionally subtract b from a using the mask m. - * m is -1 to subtract and 0 when not copying. - * - * r A single precision number representing condition subtract result. - * a A single precision number to subtract from. - * b A single precision number to subtract. - * m Mask value to apply. - */ -#ifndef __APPLE__ -.text -.globl sp_384_cond_sub_6 -.type sp_384_cond_sub_6,@function -.align 16 -sp_384_cond_sub_6: -#else -.section __TEXT,__text -.globl _sp_384_cond_sub_6 -.p2align 4 -_sp_384_cond_sub_6: -#endif /* __APPLE__ */ - subq $48, %rsp - movq $0x00, %rax - movq (%rdx), %r8 - movq 8(%rdx), %r9 - andq %rcx, %r8 - andq %rcx, %r9 - movq %r8, (%rsp) - movq %r9, 8(%rsp) - movq 16(%rdx), %r8 - movq 24(%rdx), %r9 - andq %rcx, %r8 - andq %rcx, %r9 - movq %r8, 16(%rsp) - movq %r9, 24(%rsp) - movq 32(%rdx), %r8 - movq 40(%rdx), %r9 - andq %rcx, %r8 - andq %rcx, %r9 - movq %r8, 32(%rsp) - movq %r9, 40(%rsp) - movq (%rsi), %r8 - movq (%rsp), %rdx - subq %rdx, %r8 - movq 8(%rsi), %r9 - movq 8(%rsp), %rdx - sbbq %rdx, %r9 - movq %r8, (%rdi) - movq 16(%rsi), %r8 - movq 16(%rsp), %rdx - sbbq %rdx, %r8 - movq %r9, 8(%rdi) - movq 24(%rsi), %r9 - movq 24(%rsp), %rdx - sbbq %rdx, %r9 - movq %r8, 16(%rdi) - movq 32(%rsi), %r8 - movq 32(%rsp), %rdx - sbbq %rdx, %r8 - movq %r9, 24(%rdi) - movq 40(%rsi), %r9 - movq 40(%rsp), %rdx - sbbq %rdx, %r9 - movq %r8, 32(%rdi) - movq %r9, 40(%rdi) - sbbq $0x00, %rax - addq $48, %rsp - repz retq -#ifndef __APPLE__ -.size sp_384_cond_sub_6,.-sp_384_cond_sub_6 -#endif /* __APPLE__ */ -#ifdef HAVE_INTEL_AVX2 -/* Reduce the number back to 384 bits using Montgomery reduction. - * - * a A single precision number to reduce in place. - * m The single precision number representing the modulus. - * mp The digit representing the negative inverse of m mod 2^n. - */ -#ifndef __APPLE__ -.text -.globl sp_384_mont_reduce_6 -.type sp_384_mont_reduce_6,@function -.align 16 -sp_384_mont_reduce_6: -#else -.section __TEXT,__text -.globl _sp_384_mont_reduce_6 -.p2align 4 -_sp_384_mont_reduce_6: -#endif /* __APPLE__ */ - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - pushq %rbx - pushq %rbp - movq (%rdi), %r11 - movq 8(%rdi), %r12 - movq 16(%rdi), %r13 - movq 24(%rdi), %r14 - movq 32(%rdi), %r15 - movq 40(%rdi), %rsi - xorq %r10, %r10 - # a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp) - movq 48(%rdi), %rbx - movq 56(%rdi), %rbp - movq %r11, %rdx - movq %r12, %rax - shldq $32, %rdx, %rax - shlq $32, %rdx - addq %r11, %rdx - adcq %r12, %rax - addq %r11, %rax - movq %rdx, %rcx - movq %rax, %r8 - movq %rax, %r9 - shldq $32, %rcx, %r8 - shlq $32, %rcx - shrq $32, %r9 - addq %rcx, %r11 - adcq %r8, %r12 - adcq %r9, %r13 - adcq $0x00, %r14 - adcq $0x00, %r15 - adcq $0x00, %rsi - adcq %rdx, %rbx - adcq %rax, %rbp - adcq $0x00, %r10 - addq %rax, %rcx - adcq %rdx, %r8 - adcq %rax, %r9 - movq $0x00, %rax - adcq $0x00, %rax - subq %r8, %r13 - sbbq %r9, %r14 - sbbq %rax, %r15 - sbbq $0x00, %rsi - sbbq $0x00, %rbx - sbbq $0x00, %rbp - sbbq $0x00, %r10 - # a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp) - movq 64(%rdi), %r11 - movq 72(%rdi), %r12 - movq %r13, %rdx - movq %r14, %rax - shldq $32, %rdx, %rax - shlq $32, %rdx - addq %r13, %rdx - adcq %r14, %rax - addq %r13, %rax - movq %rdx, %rcx - movq %rax, %r8 - movq %rax, %r9 - shldq $32, %rcx, %r8 - shlq $32, %rcx - shrq $32, %r9 - addq %r10, %r11 - adcq $0x00, %r12 - movq $0x00, %r10 - adcq $0x00, %r10 - addq %rcx, %r13 - adcq %r8, %r14 - adcq %r9, %r15 - adcq $0x00, %rsi - adcq $0x00, %rbx - adcq $0x00, %rbp - adcq %rdx, %r11 - adcq %rax, %r12 - adcq $0x00, %r10 - addq %rax, %rcx - adcq %rdx, %r8 - adcq %rax, %r9 - movq $0x00, %rax - adcq $0x00, %rax - subq %r8, %r15 - sbbq %r9, %rsi - sbbq %rax, %rbx - sbbq $0x00, %rbp - sbbq $0x00, %r11 - sbbq $0x00, %r12 - sbbq $0x00, %r10 - # a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp) - movq 80(%rdi), %r13 - movq 88(%rdi), %r14 - movq %r15, %rdx - movq %rsi, %rax - shldq $32, %rdx, %rax - shlq $32, %rdx - addq %r15, %rdx - adcq %rsi, %rax - addq %r15, %rax - movq %rdx, %rcx - movq %rax, %r8 - movq %rax, %r9 - shldq $32, %rcx, %r8 - shlq $32, %rcx - shrq $32, %r9 - addq %r10, %r13 - adcq $0x00, %r14 - movq $0x00, %r10 - adcq $0x00, %r10 - addq %rcx, %r15 - adcq %r8, %rsi - adcq %r9, %rbx - adcq $0x00, %rbp - adcq $0x00, %r11 - adcq $0x00, %r12 - adcq %rdx, %r13 - adcq %rax, %r14 - adcq $0x00, %r10 - addq %rax, %rcx - adcq %rdx, %r8 - adcq %rax, %r9 - movq $0x00, %rax - adcq $0x00, %rax - subq %r8, %rbx - sbbq %r9, %rbp - sbbq %rax, %r11 - sbbq $0x00, %r12 - sbbq $0x00, %r13 - sbbq $0x00, %r14 - sbbq $0x00, %r10 - # Subtract mod if carry - negq %r10 - movq $0xfffffffffffffffe, %r9 - movq %r10, %rcx - movq %r10, %r8 - shrq $32, %rcx - shlq $32, %r8 - andq %r10, %r9 - subq %rcx, %rbx - sbbq %r8, %rbp - sbbq %r9, %r11 - sbbq %r10, %r12 - sbbq %r10, %r13 - sbbq %r10, %r14 - movq %rbx, (%rdi) - movq %rbp, 8(%rdi) - movq %r11, 16(%rdi) - movq %r12, 24(%rdi) - movq %r13, 32(%rdi) - movq %r14, 40(%rdi) - popq %rbp - popq %rbx - popq %r15 - popq %r14 - popq %r13 - popq %r12 - repz retq -#ifndef __APPLE__ -.size sp_384_mont_reduce_6,.-sp_384_mont_reduce_6 -#endif /* __APPLE__ */ -#endif /* HAVE_INTEL_AVX2 */ -/* Reduce the number back to 384 bits using Montgomery reduction. - * - * a A single precision number to reduce in place. - * m The single precision number representing the modulus. - * mp The digit representing the negative inverse of m mod 2^n. - */ -#ifndef __APPLE__ -.text -.globl sp_384_mont_reduce_order_6 -.type sp_384_mont_reduce_order_6,@function -.align 16 -sp_384_mont_reduce_order_6: -#else -.section __TEXT,__text -.globl _sp_384_mont_reduce_order_6 -.p2align 4 -_sp_384_mont_reduce_order_6: -#endif /* __APPLE__ */ - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - movq %rdx, %rcx - xorq %r15, %r15 - # i = 6 - movq $6, %r8 - movq (%rdi), %r13 - movq 8(%rdi), %r14 -L_mont_loop_order_6: - # mu = a[i] * mp - movq %r13, %r11 - imulq %rcx, %r11 - # a[i+0] += m[0] * mu - movq %r11, %rax - xorq %r10, %r10 - mulq (%rsi) - addq %rax, %r13 - adcq %rdx, %r10 - # a[i+1] += m[1] * mu - movq %r11, %rax - xorq %r9, %r9 - mulq 8(%rsi) - movq %r14, %r13 - addq %rax, %r13 - adcq %rdx, %r9 - addq %r10, %r13 - adcq $0x00, %r9 - # a[i+2] += m[2] * mu - movq %r11, %rax - xorq %r10, %r10 - mulq 16(%rsi) - movq 16(%rdi), %r14 - addq %rax, %r14 - adcq %rdx, %r10 - addq %r9, %r14 - adcq $0x00, %r10 - # a[i+3] += m[3] * mu - movq %r11, %rax - xorq %r9, %r9 - mulq 24(%rsi) - movq 24(%rdi), %r12 - addq %rax, %r12 - adcq %rdx, %r9 - addq %r10, %r12 - movq %r12, 24(%rdi) - adcq $0x00, %r9 - # a[i+4] += m[4] * mu - movq %r11, %rax - xorq %r10, %r10 - mulq 32(%rsi) - movq 32(%rdi), %r12 - addq %rax, %r12 - adcq %rdx, %r10 - addq %r9, %r12 - movq %r12, 32(%rdi) - adcq $0x00, %r10 - # a[i+5] += m[5] * mu - movq %r11, %rax - mulq 40(%rsi) - movq 40(%rdi), %r12 - addq %rax, %r10 - adcq %r15, %rdx - movq $0x00, %r15 - adcq $0x00, %r15 - addq %r10, %r12 - movq %r12, 40(%rdi) - adcq %rdx, 48(%rdi) - adcq $0x00, %r15 - # i -= 1 - addq $8, %rdi - decq %r8 - jnz L_mont_loop_order_6 - movq %r13, (%rdi) - movq %r14, 8(%rdi) - negq %r15 - movq %r15, %rcx - movq %rsi, %rdx - movq %rdi, %rsi - movq %rdi, %rdi - subq $48, %rdi -#ifndef __APPLE__ - callq sp_384_cond_sub_6@plt -#else - callq _sp_384_cond_sub_6 -#endif /* __APPLE__ */ - popq %r15 - popq %r14 - popq %r13 - popq %r12 - repz retq -#ifndef __APPLE__ -.size sp_384_mont_reduce_order_6,.-sp_384_mont_reduce_order_6 -#endif /* __APPLE__ */ /* Square a and put result in r. (r = a * a) * * r A single precision integer. @@ -42650,6 +42915,508 @@ _sp_384_sqr_6: #ifndef __APPLE__ .size sp_384_sqr_6,.-sp_384_sqr_6 #endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_384_add_6 +.type sp_384_add_6,@function +.align 16 +sp_384_add_6: +#else +.section __TEXT,__text +.globl _sp_384_add_6 +.p2align 4 +_sp_384_add_6: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq %r8, 40(%rdi) + adcq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_add_6,.-sp_384_add_6 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_384_sub_6 +.type sp_384_sub_6,@function +.align 16 +sp_384_sub_6: +#else +.section __TEXT,__text +.globl _sp_384_sub_6 +.p2align 4 +_sp_384_sub_6: +#endif /* __APPLE__ */ + pushq %r12 + xorq %rax, %rax + movq (%rsi), %rcx + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + movq 32(%rsi), %r11 + movq 40(%rsi), %r12 + subq (%rdx), %rcx + sbbq 8(%rdx), %r8 + sbbq 16(%rdx), %r9 + sbbq 24(%rdx), %r10 + sbbq 32(%rdx), %r11 + sbbq 40(%rdx), %r12 + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq %r11, 32(%rdi) + movq %r12, 40(%rdi) + sbbq $0x00, %rax + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_sub_6,.-sp_384_sub_6 +#endif /* __APPLE__ */ +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_384_cond_copy_6 +.type sp_384_cond_copy_6,@function +.align 16 +sp_384_cond_copy_6: +#else +.section __TEXT,__text +.globl _sp_384_cond_copy_6 +.p2align 4 +_sp_384_cond_copy_6: +#endif /* __APPLE__ */ + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + movq 32(%rdi), %r10 + movq 40(%rdi), %r11 + xorq (%rsi), %rax + xorq 8(%rsi), %rcx + xorq 16(%rsi), %r8 + xorq 24(%rsi), %r9 + xorq 32(%rsi), %r10 + xorq 40(%rsi), %r11 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + andq %rdx, %r10 + andq %rdx, %r11 + xorq %rax, (%rdi) + xorq %rcx, 8(%rdi) + xorq %r8, 16(%rdi) + xorq %r9, 24(%rdi) + xorq %r10, 32(%rdi) + xorq %r11, 40(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_cond_copy_6,.-sp_384_cond_copy_6 +#endif /* __APPLE__ */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_384_cond_sub_6 +.type sp_384_cond_sub_6,@function +.align 16 +sp_384_cond_sub_6: +#else +.section __TEXT,__text +.globl _sp_384_cond_sub_6 +.p2align 4 +_sp_384_cond_sub_6: +#endif /* __APPLE__ */ + subq $48, %rsp + movq $0x00, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + sbbq $0x00, %rax + addq $48, %rsp + repz retq +#ifndef __APPLE__ +.size sp_384_cond_sub_6,.-sp_384_cond_sub_6 +#endif /* __APPLE__ */ +/* Reduce the number back to 384 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.text +.globl sp_384_mont_reduce_6 +.type sp_384_mont_reduce_6,@function +.align 16 +sp_384_mont_reduce_6: +#else +.section __TEXT,__text +.globl _sp_384_mont_reduce_6 +.p2align 4 +_sp_384_mont_reduce_6: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp + movq (%rdi), %r11 + movq 8(%rdi), %r12 + movq 16(%rdi), %r13 + movq 24(%rdi), %r14 + movq 32(%rdi), %r15 + movq 40(%rdi), %rsi + xorq %r10, %r10 + # a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp) + movq 48(%rdi), %rbx + movq 56(%rdi), %rbp + movq %r11, %rdx + movq %r12, %rax + shldq $32, %rdx, %rax + shlq $32, %rdx + addq %r11, %rdx + adcq %r12, %rax + addq %r11, %rax + movq %rdx, %rcx + movq %rax, %r8 + movq %rax, %r9 + shldq $32, %rcx, %r8 + shlq $32, %rcx + shrq $32, %r9 + addq %rcx, %r11 + adcq %r8, %r12 + adcq %r9, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + adcq $0x00, %rsi + adcq %rdx, %rbx + adcq %rax, %rbp + adcq $0x00, %r10 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %rax, %r9 + movq $0x00, %rax + adcq $0x00, %rax + subq %r8, %r13 + sbbq %r9, %r14 + sbbq %rax, %r15 + sbbq $0x00, %rsi + sbbq $0x00, %rbx + sbbq $0x00, %rbp + sbbq $0x00, %r10 + # a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp) + movq 64(%rdi), %r11 + movq 72(%rdi), %r12 + movq %r13, %rdx + movq %r14, %rax + shldq $32, %rdx, %rax + shlq $32, %rdx + addq %r13, %rdx + adcq %r14, %rax + addq %r13, %rax + movq %rdx, %rcx + movq %rax, %r8 + movq %rax, %r9 + shldq $32, %rcx, %r8 + shlq $32, %rcx + shrq $32, %r9 + addq %r10, %r11 + adcq $0x00, %r12 + movq $0x00, %r10 + adcq $0x00, %r10 + addq %rcx, %r13 + adcq %r8, %r14 + adcq %r9, %r15 + adcq $0x00, %rsi + adcq $0x00, %rbx + adcq $0x00, %rbp + adcq %rdx, %r11 + adcq %rax, %r12 + adcq $0x00, %r10 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %rax, %r9 + movq $0x00, %rax + adcq $0x00, %rax + subq %r8, %r15 + sbbq %r9, %rsi + sbbq %rax, %rbx + sbbq $0x00, %rbp + sbbq $0x00, %r11 + sbbq $0x00, %r12 + sbbq $0x00, %r10 + # a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp) + movq 80(%rdi), %r13 + movq 88(%rdi), %r14 + movq %r15, %rdx + movq %rsi, %rax + shldq $32, %rdx, %rax + shlq $32, %rdx + addq %r15, %rdx + adcq %rsi, %rax + addq %r15, %rax + movq %rdx, %rcx + movq %rax, %r8 + movq %rax, %r9 + shldq $32, %rcx, %r8 + shlq $32, %rcx + shrq $32, %r9 + addq %r10, %r13 + adcq $0x00, %r14 + movq $0x00, %r10 + adcq $0x00, %r10 + addq %rcx, %r15 + adcq %r8, %rsi + adcq %r9, %rbx + adcq $0x00, %rbp + adcq $0x00, %r11 + adcq $0x00, %r12 + adcq %rdx, %r13 + adcq %rax, %r14 + adcq $0x00, %r10 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %rax, %r9 + movq $0x00, %rax + adcq $0x00, %rax + subq %r8, %rbx + sbbq %r9, %rbp + sbbq %rax, %r11 + sbbq $0x00, %r12 + sbbq $0x00, %r13 + sbbq $0x00, %r14 + sbbq $0x00, %r10 + # Subtract mod if carry + negq %r10 + movq $0xfffffffffffffffe, %r9 + movq %r10, %rcx + movq %r10, %r8 + shrq $32, %rcx + shlq $32, %r8 + andq %r10, %r9 + subq %rcx, %rbx + sbbq %r8, %rbp + sbbq %r9, %r11 + sbbq %r10, %r12 + sbbq %r10, %r13 + sbbq %r10, %r14 + movq %rbx, (%rdi) + movq %rbp, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq %r13, 32(%rdi) + movq %r14, 40(%rdi) + popq %rbp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_mont_reduce_6,.-sp_384_mont_reduce_6 +#endif /* __APPLE__ */ +/* Reduce the number back to 384 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.text +.globl sp_384_mont_reduce_order_6 +.type sp_384_mont_reduce_order_6,@function +.align 16 +sp_384_mont_reduce_order_6: +#else +.section __TEXT,__text +.globl _sp_384_mont_reduce_order_6 +.p2align 4 +_sp_384_mont_reduce_order_6: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 6 + movq $6, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_384_mont_loop_order_6: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0x00, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0x00, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0x00, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0x00, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0x00, %r15 + adcq $0x00, %r15 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq %rdx, 48(%rdi) + adcq $0x00, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_384_mont_loop_order_6 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else + movq %r15, %rcx + movq %rsi, %rdx +#endif /* _WIN64 */ + movq %rdi, %rsi + movq %rdi, %rdi + subq $48, %rdi +#ifndef __APPLE__ + callq sp_384_cond_sub_6@plt +#else + callq _sp_384_cond_sub_6 +#endif /* __APPLE__ */ + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_mont_reduce_order_6,.-sp_384_mont_reduce_order_6 +#endif /* __APPLE__ */ /* Compare a with b in constant time. * * a A single precision integer. @@ -42726,49 +43493,6 @@ _sp_384_cmp_6: #ifndef __APPLE__ .size sp_384_cmp_6,.-sp_384_cmp_6 #endif /* __APPLE__ */ -/* Add b to a into r. (r = a + b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -#ifndef __APPLE__ -.text -.globl sp_384_add_6 -.type sp_384_add_6,@function -.align 16 -sp_384_add_6: -#else -.section __TEXT,__text -.globl _sp_384_add_6 -.p2align 4 -_sp_384_add_6: -#endif /* __APPLE__ */ - # Add - movq (%rsi), %rcx - xorq %rax, %rax - addq (%rdx), %rcx - movq 8(%rsi), %r8 - movq %rcx, (%rdi) - adcq 8(%rdx), %r8 - movq 16(%rsi), %rcx - movq %r8, 8(%rdi) - adcq 16(%rdx), %rcx - movq 24(%rsi), %r8 - movq %rcx, 16(%rdi) - adcq 24(%rdx), %r8 - movq 32(%rsi), %rcx - movq %r8, 24(%rdi) - adcq 32(%rdx), %rcx - movq 40(%rsi), %r8 - movq %rcx, 32(%rdi) - adcq 40(%rdx), %r8 - movq %r8, 40(%rdi) - adcq $0x00, %rax - repz retq -#ifndef __APPLE__ -.size sp_384_add_6,.-sp_384_add_6 -#endif /* __APPLE__ */ /* Add a to a into r. (r = a + a) * * r A single precision integer. @@ -42810,50 +43534,6 @@ _sp_384_dbl_6: #ifndef __APPLE__ .size sp_384_dbl_6,.-sp_384_dbl_6 #endif /* __APPLE__ */ -/* Sub b from a into r. (r = a - b) - * - * r A single precision integer. - * a A single precision integer. - * b A single precision integer. - */ -#ifndef __APPLE__ -.text -.globl sp_384_sub_6 -.type sp_384_sub_6,@function -.align 16 -sp_384_sub_6: -#else -.section __TEXT,__text -.globl _sp_384_sub_6 -.p2align 4 -_sp_384_sub_6: -#endif /* __APPLE__ */ - pushq %r12 - xorq %rax, %rax - movq (%rsi), %rcx - movq 8(%rsi), %r8 - movq 16(%rsi), %r9 - movq 24(%rsi), %r10 - movq 32(%rsi), %r11 - movq 40(%rsi), %r12 - subq (%rdx), %rcx - sbbq 8(%rdx), %r8 - sbbq 16(%rdx), %r9 - sbbq 24(%rdx), %r10 - sbbq 32(%rdx), %r11 - sbbq 40(%rdx), %r12 - movq %rcx, (%rdi) - movq %r8, 8(%rdi) - movq %r9, 16(%rdi) - movq %r10, 24(%rdi) - movq %r11, 32(%rdi) - movq %r12, 40(%rdi) - sbbq $0x00, %rax - popq %r12 - repz retq -#ifndef __APPLE__ -.size sp_384_sub_6,.-sp_384_sub_6 -#endif /* __APPLE__ */ /* Conditionally add a and b using the mask m. * m is -1 to add and 0 when not. * @@ -42943,11 +43623,11 @@ sp_384_div2_6: _sp_384_div2_6: #endif /* __APPLE__ */ subq $48, %rsp - movq (%rsi), %rax - movq %rax, %r11 + movq (%rsi), %r11 + xorq %r10, %r10 + movq %r11, %rax andq $0x01, %r11 negq %r11 - xorq %r10, %r10 movq (%rdx), %r8 andq %r11, %r8 movq %r8, (%rsp) @@ -43101,6 +43781,7 @@ L_384_get_point_33_6_start_2: #ifndef __APPLE__ .size sp_384_get_point_33_6,.-sp_384_get_point_33_6 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Touch each possible point that could be being copied. * * r Point to copy into. @@ -43137,11 +43818,11 @@ _sp_384_get_point_33_avx2_6: L_384_get_point_33_avx2_6_start: vpcmpeqd %ymm13, %ymm14, %ymm12 vpaddd %ymm15, %ymm14, %ymm14 - vmovdqu (%rsi), %ymm6 + vmovupd (%rsi), %ymm6 vmovdqu 32(%rsi), %xmm7 - vmovdqu 96(%rsi), %ymm8 + vmovupd 96(%rsi), %ymm8 vmovdqu 128(%rsi), %xmm9 - vmovdqu 192(%rsi), %ymm10 + vmovupd 192(%rsi), %ymm10 vmovdqu 224(%rsi), %xmm11 addq $0x128, %rsi vpand %ymm12, %ymm6, %ymm6 @@ -43158,17 +43839,19 @@ L_384_get_point_33_avx2_6_start: vpor %xmm11, %xmm5, %xmm5 decq %rax jnz L_384_get_point_33_avx2_6_start - vmovdqu %ymm0, (%rdi) + vmovupd %ymm0, (%rdi) vmovdqu %xmm1, 32(%rdi) - vmovdqu %ymm2, 96(%rdi) + vmovupd %ymm2, 96(%rdi) vmovdqu %xmm3, 128(%rdi) - vmovdqu %ymm4, 192(%rdi) + vmovupd %ymm4, 192(%rdi) vmovdqu %xmm5, 224(%rdi) repz retq #ifndef __APPLE__ .size sp_384_get_point_33_avx2_6,.-sp_384_get_point_33_avx2_6 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #endif /* !WC_NO_CACHE_RESISTANT */ +#ifdef HAVE_INTEL_AVX2 /* Multiply a and b into r. (r = a * b) * * r Result of multiplication. @@ -43391,6 +44074,7 @@ _sp_384_mul_avx2_6: #ifndef __APPLE__ .size sp_384_mul_avx2_6,.-sp_384_mul_avx2_6 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #ifdef HAVE_INTEL_AVX2 /* Reduce the number back to 384 bits using Montgomery reduction. * @@ -43721,6 +44405,7 @@ L_mont_loop_order_avx2_6: .size sp_384_mont_reduce_order_avx2_6,.-sp_384_mont_reduce_order_avx2_6 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 /* Square a and put result in r. (r = a * a) * * r Result of squaring. @@ -43883,6 +44568,143 @@ _sp_384_sqr_avx2_6: #ifndef __APPLE__ .size sp_384_sqr_avx2_6,.-sp_384_sqr_avx2_6 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_384_cond_sub_avx2_6 +.type sp_384_cond_sub_avx2_6,@function +.align 16 +sp_384_cond_sub_avx2_6: +#else +.section __TEXT,__text +.globl _sp_384_cond_sub_avx2_6 +.p2align 4 +_sp_384_cond_sub_avx2_6: +#endif /* __APPLE__ */ + movq $0x00, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq %r10, 40(%rdi) + sbbq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_cond_sub_avx2_6,.-sp_384_cond_sub_avx2_6 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_384_div2_avx2_6 +.type sp_384_div2_avx2_6,@function +.align 16 +sp_384_div2_avx2_6: +#else +.section __TEXT,__text +.globl _sp_384_div2_avx2_6 +.p2align 4 +_sp_384_div2_avx2_6: +#endif /* __APPLE__ */ + movq (%rsi), %r11 + xorq %r10, %r10 + movq %r11, %r8 + andq $0x01, %r11 + negq %r11 + movq (%rdx), %rax + movq 8(%rdx), %rcx + movq (%rsi), %r8 + movq 8(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + addq %rax, %r8 + adcq %rcx, %r9 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq 16(%rdx), %rax + movq 24(%rdx), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdx), %rax + movq 40(%rdx), %rcx + movq 32(%rsi), %r8 + movq 40(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + adcq $0x00, %r10 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 16(%rdi) + movq 32(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 24(%rdi) + movq 40(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 32(%rdi) + shrdq $0x01, %r10, %r9 + movq %r9, 40(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_div2_avx2_6,.-sp_384_div2_avx2_6 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #ifndef WC_NO_CACHE_RESISTANT /* Touch each possible entry that could be being copied. * @@ -43892,21 +44714,21 @@ _sp_384_sqr_avx2_6: */ #ifndef __APPLE__ .text -.globl sp_384_get_entry_256_6 -.type sp_384_get_entry_256_6,@function +.globl sp_384_get_entry_64_6 +.type sp_384_get_entry_64_6,@function .align 16 -sp_384_get_entry_256_6: +sp_384_get_entry_64_6: #else .section __TEXT,__text -.globl _sp_384_get_entry_256_6 +.globl _sp_384_get_entry_64_6 .p2align 4 -_sp_384_get_entry_256_6: +_sp_384_get_entry_64_6: #endif /* __APPLE__ */ movq $0x01, %rax movd %edx, %xmm13 addq $0x60, %rsi movd %eax, %xmm15 - movq $0xff, %rax + movq $63, %rax pshufd $0x00, %xmm15, %xmm15 pshufd $0x00, %xmm13, %xmm13 pxor %xmm14, %xmm14 @@ -43917,16 +44739,16 @@ _sp_384_get_entry_256_6: pxor %xmm4, %xmm4 pxor %xmm5, %xmm5 movdqa %xmm15, %xmm14 -L_384_get_entry_256_6_start: +L_384_get_entry_64_6_start: movdqa %xmm14, %xmm12 paddd %xmm15, %xmm14 pcmpeqd %xmm13, %xmm12 - movdqa (%rsi), %xmm6 - movdqa 16(%rsi), %xmm7 - movdqa 32(%rsi), %xmm8 - movdqa 48(%rsi), %xmm9 - movdqa 64(%rsi), %xmm10 - movdqa 80(%rsi), %xmm11 + movdqu (%rsi), %xmm6 + movdqu 16(%rsi), %xmm7 + movdqu 32(%rsi), %xmm8 + movdqu 48(%rsi), %xmm9 + movdqu 64(%rsi), %xmm10 + movdqu 80(%rsi), %xmm11 addq $0x60, %rsi pand %xmm12, %xmm6 pand %xmm12, %xmm7 @@ -43941,7 +44763,7 @@ L_384_get_entry_256_6_start: por %xmm10, %xmm4 por %xmm11, %xmm5 decq %rax - jnz L_384_get_entry_256_6_start + jnz L_384_get_entry_64_6_start movdqu %xmm0, (%rdi) movdqu %xmm1, 16(%rdi) movdqu %xmm2, 32(%rdi) @@ -43950,8 +44772,9 @@ L_384_get_entry_256_6_start: movdqu %xmm5, 128(%rdi) repz retq #ifndef __APPLE__ -.size sp_384_get_entry_256_6,.-sp_384_get_entry_256_6 +.size sp_384_get_entry_64_6,.-sp_384_get_entry_64_6 #endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 /* Touch each possible entry that could be being copied. * * r Point to copy into. @@ -43960,21 +44783,21 @@ L_384_get_entry_256_6_start: */ #ifndef __APPLE__ .text -.globl sp_384_get_entry_256_avx2_6 -.type sp_384_get_entry_256_avx2_6,@function +.globl sp_384_get_entry_64_avx2_6 +.type sp_384_get_entry_64_avx2_6,@function .align 16 -sp_384_get_entry_256_avx2_6: +sp_384_get_entry_64_avx2_6: #else .section __TEXT,__text -.globl _sp_384_get_entry_256_avx2_6 +.globl _sp_384_get_entry_64_avx2_6 .p2align 4 -_sp_384_get_entry_256_avx2_6: +_sp_384_get_entry_64_avx2_6: #endif /* __APPLE__ */ movq $0x01, %rax movd %edx, %xmm9 addq $0x60, %rsi movd %eax, %xmm11 - movq $0x100, %rax + movq $0x40, %rax vpxor %ymm10, %ymm10, %ymm10 vpermd %ymm9, %ymm10, %ymm9 vpermd %ymm11, %ymm10, %ymm11 @@ -43983,12 +44806,12 @@ _sp_384_get_entry_256_avx2_6: vpxor %ymm2, %ymm2, %ymm2 vpxor %xmm3, %xmm3, %xmm3 vmovdqa %ymm11, %ymm10 -L_384_get_entry_256_avx2_6_start: +L_384_get_entry_64_avx2_6_start: vpcmpeqd %ymm9, %ymm10, %ymm8 vpaddd %ymm11, %ymm10, %ymm10 - vmovdqu (%rsi), %ymm4 + vmovupd (%rsi), %ymm4 vmovdqu 32(%rsi), %xmm5 - vmovdqu 48(%rsi), %ymm6 + vmovupd 48(%rsi), %ymm6 vmovdqu 80(%rsi), %xmm7 addq $0x60, %rsi vpand %ymm8, %ymm4, %ymm4 @@ -44000,15 +44823,145 @@ L_384_get_entry_256_avx2_6_start: vpor %ymm6, %ymm2, %ymm2 vpor %xmm7, %xmm3, %xmm3 decq %rax - jnz L_384_get_entry_256_avx2_6_start - vmovdqu %ymm0, (%rdi) + jnz L_384_get_entry_64_avx2_6_start + vmovupd %ymm0, (%rdi) vmovdqu %xmm1, 32(%rdi) - vmovdqu %ymm2, 96(%rdi) + vmovupd %ymm2, 96(%rdi) vmovdqu %xmm3, 128(%rdi) repz retq #ifndef __APPLE__ -.size sp_384_get_entry_256_avx2_6,.-sp_384_get_entry_256_avx2_6 +.size sp_384_get_entry_64_avx2_6,.-sp_384_get_entry_64_avx2_6 #endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#endif /* !WC_NO_CACHE_RESISTANT */ +#ifndef WC_NO_CACHE_RESISTANT +/* Touch each possible entry that could be being copied. + * + * r Point to copy into. + * table Table - start of the entires to access + * idx Index of entry to retrieve. + */ +#ifndef __APPLE__ +.text +.globl sp_384_get_entry_65_6 +.type sp_384_get_entry_65_6,@function +.align 16 +sp_384_get_entry_65_6: +#else +.section __TEXT,__text +.globl _sp_384_get_entry_65_6 +.p2align 4 +_sp_384_get_entry_65_6: +#endif /* __APPLE__ */ + movq $0x01, %rax + movd %edx, %xmm13 + addq $0x60, %rsi + movd %eax, %xmm15 + movq $0x40, %rax + pshufd $0x00, %xmm15, %xmm15 + pshufd $0x00, %xmm13, %xmm13 + pxor %xmm14, %xmm14 + pxor %xmm0, %xmm0 + pxor %xmm1, %xmm1 + pxor %xmm2, %xmm2 + pxor %xmm3, %xmm3 + pxor %xmm4, %xmm4 + pxor %xmm5, %xmm5 + movdqa %xmm15, %xmm14 +L_384_get_entry_65_6_start: + movdqa %xmm14, %xmm12 + paddd %xmm15, %xmm14 + pcmpeqd %xmm13, %xmm12 + movdqu (%rsi), %xmm6 + movdqu 16(%rsi), %xmm7 + movdqu 32(%rsi), %xmm8 + movdqu 48(%rsi), %xmm9 + movdqu 64(%rsi), %xmm10 + movdqu 80(%rsi), %xmm11 + addq $0x60, %rsi + pand %xmm12, %xmm6 + pand %xmm12, %xmm7 + pand %xmm12, %xmm8 + pand %xmm12, %xmm9 + pand %xmm12, %xmm10 + pand %xmm12, %xmm11 + por %xmm6, %xmm0 + por %xmm7, %xmm1 + por %xmm8, %xmm2 + por %xmm9, %xmm3 + por %xmm10, %xmm4 + por %xmm11, %xmm5 + decq %rax + jnz L_384_get_entry_65_6_start + movdqu %xmm0, (%rdi) + movdqu %xmm1, 16(%rdi) + movdqu %xmm2, 32(%rdi) + movdqu %xmm3, 96(%rdi) + movdqu %xmm4, 112(%rdi) + movdqu %xmm5, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_get_entry_65_6,.-sp_384_get_entry_65_6 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Touch each possible entry that could be being copied. + * + * r Point to copy into. + * table Table - start of the entires to access + * idx Index of entry to retrieve. + */ +#ifndef __APPLE__ +.text +.globl sp_384_get_entry_65_avx2_6 +.type sp_384_get_entry_65_avx2_6,@function +.align 16 +sp_384_get_entry_65_avx2_6: +#else +.section __TEXT,__text +.globl _sp_384_get_entry_65_avx2_6 +.p2align 4 +_sp_384_get_entry_65_avx2_6: +#endif /* __APPLE__ */ + movq $0x01, %rax + movd %edx, %xmm9 + addq $0x60, %rsi + movd %eax, %xmm11 + movq $0x41, %rax + vpxor %ymm10, %ymm10, %ymm10 + vpermd %ymm9, %ymm10, %ymm9 + vpermd %ymm11, %ymm10, %ymm11 + vpxor %ymm0, %ymm0, %ymm0 + vpxor %xmm1, %xmm1, %xmm1 + vpxor %ymm2, %ymm2, %ymm2 + vpxor %xmm3, %xmm3, %xmm3 + vmovdqa %ymm11, %ymm10 +L_384_get_entry_65_avx2_6_start: + vpcmpeqd %ymm9, %ymm10, %ymm8 + vpaddd %ymm11, %ymm10, %ymm10 + vmovupd (%rsi), %ymm4 + vmovdqu 32(%rsi), %xmm5 + vmovupd 48(%rsi), %ymm6 + vmovdqu 80(%rsi), %xmm7 + addq $0x60, %rsi + vpand %ymm8, %ymm4, %ymm4 + vpand %xmm8, %xmm5, %xmm5 + vpand %ymm8, %ymm6, %ymm6 + vpand %xmm8, %xmm7, %xmm7 + vpor %ymm4, %ymm0, %ymm0 + vpor %xmm5, %xmm1, %xmm1 + vpor %ymm6, %ymm2, %ymm2 + vpor %xmm7, %xmm3, %xmm3 + decq %rax + jnz L_384_get_entry_65_avx2_6_start + vmovupd %ymm0, (%rdi) + vmovdqu %xmm1, 32(%rdi) + vmovupd %ymm2, 96(%rdi) + vmovdqu %xmm3, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_get_entry_65_avx2_6,.-sp_384_get_entry_65_avx2_6 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ #endif /* !WC_NO_CACHE_RESISTANT */ /* Add 1 to a. (a = a + 1) * @@ -44130,6 +45083,7 @@ L_384_from_bin_bswap_zero_end: #ifndef __APPLE__ .size sp_384_from_bin_bswap,.-sp_384_from_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Read big endian unsigned byte array into r. * Uses the movbe instruction which is an optional instruction. * @@ -44215,6 +45169,7 @@ L_384_from_bin_movbe_zero_end: #ifndef __APPLE__ .size sp_384_from_bin_movbe,.-sp_384_from_bin_movbe #endif /* __APPLE__ */ +#endif /* !NO_MOVBE_SUPPORT */ /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 * Uses the bswap instruction. @@ -44256,6 +45211,7 @@ _sp_384_to_bin_bswap: #ifndef __APPLE__ .size sp_384_to_bin_bswap,.-sp_384_to_bin_bswap #endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 * Uses the movbe instruction which is optional. @@ -44291,6 +45247,7 @@ _sp_384_to_bin_movbe: #ifndef __APPLE__ .size sp_384_to_bin_movbe,.-sp_384_to_bin_movbe #endif /* __APPLE__ */ +#endif /* NO_MOVBE_SUPPORT */ /* Sub b from a into a. (a -= b) * * a A single precision integer and result. @@ -44326,62 +45283,6 @@ _sp_384_sub_in_place_6: #ifndef __APPLE__ .size sp_384_sub_in_place_6,.-sp_384_sub_in_place_6 #endif /* __APPLE__ */ -/* Conditionally subtract b from a using the mask m. - * m is -1 to subtract and 0 when not copying. - * - * r A single precision number representing condition subtract result. - * a A single precision number to subtract from. - * b A single precision number to subtract. - * m Mask value to apply. - */ -#ifndef __APPLE__ -.text -.globl sp_384_cond_sub_avx2_6 -.type sp_384_cond_sub_avx2_6,@function -.align 16 -sp_384_cond_sub_avx2_6: -#else -.section __TEXT,__text -.globl _sp_384_cond_sub_avx2_6 -.p2align 4 -_sp_384_cond_sub_avx2_6: -#endif /* __APPLE__ */ - movq $0x00, %rax - movq (%rdx), %r10 - movq (%rsi), %r8 - pextq %rcx, %r10, %r10 - subq %r10, %r8 - movq 8(%rdx), %r10 - movq 8(%rsi), %r9 - pextq %rcx, %r10, %r10 - movq %r8, (%rdi) - sbbq %r10, %r9 - movq 16(%rdx), %r8 - movq 16(%rsi), %r10 - pextq %rcx, %r8, %r8 - movq %r9, 8(%rdi) - sbbq %r8, %r10 - movq 24(%rdx), %r9 - movq 24(%rsi), %r8 - pextq %rcx, %r9, %r9 - movq %r10, 16(%rdi) - sbbq %r9, %r8 - movq 32(%rdx), %r10 - movq 32(%rsi), %r9 - pextq %rcx, %r10, %r10 - movq %r8, 24(%rdi) - sbbq %r10, %r9 - movq 40(%rdx), %r8 - movq 40(%rsi), %r10 - pextq %rcx, %r8, %r8 - movq %r9, 32(%rdi) - sbbq %r8, %r10 - movq %r10, 40(%rdi) - sbbq $0x00, %rax - repz retq -#ifndef __APPLE__ -.size sp_384_cond_sub_avx2_6,.-sp_384_cond_sub_avx2_6 -#endif /* __APPLE__ */ /* Mul a by digit b into r. (r = a * b) * * r A single precision integer. @@ -44480,26 +45381,26 @@ _sp_384_mul_d_avx2_6: mulxq 8(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 8(%rdi) adoxq %r8, %r9 + movq %r10, 8(%rdi) # A[2] * B mulxq 16(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 16(%rdi) adoxq %r8, %r10 + movq %r9, 16(%rdi) # A[3] * B mulxq 24(%rsi), %rcx, %r8 movq %r11, %r9 adcxq %rcx, %r10 - movq %r10, 24(%rdi) adoxq %r8, %r9 + movq %r10, 24(%rdi) # A[4] * B mulxq 32(%rsi), %rcx, %r8 movq %r11, %r10 adcxq %rcx, %r9 - movq %r9, 32(%rdi) adoxq %r8, %r10 + movq %r9, 32(%rdi) # A[5] * B mulxq 40(%rsi), %rcx, %r8 movq %r11, %r9 @@ -44513,6 +45414,35 @@ _sp_384_mul_d_avx2_6: .size sp_384_mul_d_avx2_6,.-sp_384_mul_d_avx2_6 #endif /* __APPLE__ */ #endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_384_word_asm_6 +.type div_384_word_asm_6,@function +.align 16 +div_384_word_asm_6: +#else +.section __TEXT,__text +.globl _div_384_word_asm_6 +.p2align 4 +_div_384_word_asm_6: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_384_word_asm_6,.-div_384_word_asm_6 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ /* Shift number right by 1 bit. (r = a >> 1) * * r Result of right shift by 1. @@ -44689,6 +45619,9134 @@ L_384_num_bits_6_done: .size sp_384_num_bits_6,.-sp_384_num_bits_6 #endif /* __APPLE__ */ #endif /* WOLFSSL_SP_384 */ +#ifdef WOLFSSL_SP_1024 +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mul_16 +.type sp_1024_mul_16,@function +.align 16 +sp_1024_mul_16: +#else +.section __TEXT,__text +.globl _sp_1024_mul_16 +.p2align 4 +_sp_1024_mul_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $0x80, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 24(%rsp) + # A[0] * B[4] + movq 32(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[4] * B[0] + movq (%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 32(%rsp) + # A[0] * B[5] + movq 40(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * B[4] + movq 32(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[4] * B[1] + movq 8(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[5] * B[0] + movq (%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 40(%rsp) + # A[0] * B[6] + movq 48(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[1] * B[5] + movq 40(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[2] * B[4] + movq 32(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[4] * B[2] + movq 16(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[5] * B[1] + movq 8(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[6] * B[0] + movq (%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 48(%rsp) + # A[0] * B[7] + movq 56(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[1] * B[6] + movq 48(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B[5] + movq 40(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[3] * B[4] + movq 32(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[4] * B[3] + movq 24(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[5] * B[2] + movq 16(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[6] * B[1] + movq 8(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[7] * B[0] + movq (%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 56(%rsp) + # A[0] * B[8] + movq 64(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * B[7] + movq 56(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[2] * B[6] + movq 48(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B[5] + movq 40(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[4] * B[4] + movq 32(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[5] * B[3] + movq 24(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[6] * B[2] + movq 16(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[7] * B[1] + movq 8(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[8] * B[0] + movq (%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 64(%rsp) + # A[0] * B[9] + movq 72(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[1] * B[8] + movq 64(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[2] * B[7] + movq 56(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[3] * B[6] + movq 48(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[4] * B[5] + movq 40(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[5] * B[4] + movq 32(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[6] * B[3] + movq 24(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[7] * B[2] + movq 16(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[8] * B[1] + movq 8(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[9] * B[0] + movq (%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 72(%rsp) + # A[0] * B[10] + movq 80(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[1] * B[9] + movq 72(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B[8] + movq 64(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[3] * B[7] + movq 56(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[4] * B[6] + movq 48(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[5] * B[5] + movq 40(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[6] * B[4] + movq 32(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[7] * B[3] + movq 24(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[8] * B[2] + movq 16(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[9] * B[1] + movq 8(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[10] * B[0] + movq (%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 80(%rsp) + # A[0] * B[11] + movq 88(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * B[10] + movq 80(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[2] * B[9] + movq 72(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B[8] + movq 64(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[4] * B[7] + movq 56(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[5] * B[6] + movq 48(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[6] * B[5] + movq 40(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[7] * B[4] + movq 32(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[8] * B[3] + movq 24(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[9] * B[2] + movq 16(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[10] * B[1] + movq 8(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[11] * B[0] + movq (%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 88(%rsp) + # A[0] * B[12] + movq 96(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[1] * B[11] + movq 88(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[2] * B[10] + movq 80(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[3] * B[9] + movq 72(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[4] * B[8] + movq 64(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[5] * B[7] + movq 56(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[6] * B[6] + movq 48(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[7] * B[5] + movq 40(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[8] * B[4] + movq 32(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[9] * B[3] + movq 24(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[10] * B[2] + movq 16(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[11] * B[1] + movq 8(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[12] * B[0] + movq (%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 96(%rsp) + # A[0] * B[13] + movq 104(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[1] * B[12] + movq 96(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B[11] + movq 88(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[3] * B[10] + movq 80(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[4] * B[9] + movq 72(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[5] * B[8] + movq 64(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[6] * B[7] + movq 56(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[7] * B[6] + movq 48(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[8] * B[5] + movq 40(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[9] * B[4] + movq 32(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[10] * B[3] + movq 24(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[11] * B[2] + movq 16(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[12] * B[1] + movq 8(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[13] * B[0] + movq (%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 104(%rsp) + # A[0] * B[14] + movq 112(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * B[13] + movq 104(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[2] * B[12] + movq 96(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B[11] + movq 88(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[4] * B[10] + movq 80(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[5] * B[9] + movq 72(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[6] * B[8] + movq 64(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[7] * B[7] + movq 56(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[8] * B[6] + movq 48(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[9] * B[5] + movq 40(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[10] * B[4] + movq 32(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[11] * B[3] + movq 24(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[12] * B[2] + movq 16(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[13] * B[1] + movq 8(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[14] * B[0] + movq (%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 112(%rsp) + # A[0] * B[15] + movq 120(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[1] * B[14] + movq 112(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[2] * B[13] + movq 104(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[3] * B[12] + movq 96(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[4] * B[11] + movq 88(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[5] * B[10] + movq 80(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[6] * B[9] + movq 72(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[7] * B[8] + movq 64(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[8] * B[7] + movq 56(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[9] * B[6] + movq 48(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[10] * B[5] + movq 40(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[11] * B[4] + movq 32(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[12] * B[3] + movq 24(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[13] * B[2] + movq 16(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[14] * B[1] + movq 8(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[15] * B[0] + movq (%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 120(%rsp) + # A[1] * B[15] + movq 120(%rcx), %rax + mulq 8(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B[14] + movq 112(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[3] * B[13] + movq 104(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[4] * B[12] + movq 96(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[5] * B[11] + movq 88(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[6] * B[10] + movq 80(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[7] * B[9] + movq 72(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[8] * B[8] + movq 64(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[9] * B[7] + movq 56(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[10] * B[6] + movq 48(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[11] * B[5] + movq 40(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[12] * B[4] + movq 32(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[13] * B[3] + movq 24(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[14] * B[2] + movq 16(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[15] * B[1] + movq 8(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 128(%rdi) + # A[2] * B[15] + movq 120(%rcx), %rax + mulq 16(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B[14] + movq 112(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[4] * B[13] + movq 104(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[5] * B[12] + movq 96(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[6] * B[11] + movq 88(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[7] * B[10] + movq 80(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[8] * B[9] + movq 72(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[9] * B[8] + movq 64(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[10] * B[7] + movq 56(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[11] * B[6] + movq 48(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[12] * B[5] + movq 40(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[13] * B[4] + movq 32(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[14] * B[3] + movq 24(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[15] * B[2] + movq 16(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 136(%rdi) + # A[3] * B[15] + movq 120(%rcx), %rax + mulq 24(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[4] * B[14] + movq 112(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[5] * B[13] + movq 104(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[6] * B[12] + movq 96(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[7] * B[11] + movq 88(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[8] * B[10] + movq 80(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[9] * B[9] + movq 72(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[10] * B[8] + movq 64(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[11] * B[7] + movq 56(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[12] * B[6] + movq 48(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[13] * B[5] + movq 40(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[14] * B[4] + movq 32(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[15] * B[3] + movq 24(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 144(%rdi) + # A[4] * B[15] + movq 120(%rcx), %rax + mulq 32(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[5] * B[14] + movq 112(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[6] * B[13] + movq 104(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[7] * B[12] + movq 96(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[8] * B[11] + movq 88(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[9] * B[10] + movq 80(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[10] * B[9] + movq 72(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[11] * B[8] + movq 64(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[12] * B[7] + movq 56(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[13] * B[6] + movq 48(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[14] * B[5] + movq 40(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[15] * B[4] + movq 32(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 152(%rdi) + # A[5] * B[15] + movq 120(%rcx), %rax + mulq 40(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[6] * B[14] + movq 112(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[7] * B[13] + movq 104(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[8] * B[12] + movq 96(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[9] * B[11] + movq 88(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[10] * B[10] + movq 80(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[11] * B[9] + movq 72(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[12] * B[8] + movq 64(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[13] * B[7] + movq 56(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[14] * B[6] + movq 48(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[15] * B[5] + movq 40(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 160(%rdi) + # A[6] * B[15] + movq 120(%rcx), %rax + mulq 48(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[7] * B[14] + movq 112(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[8] * B[13] + movq 104(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[9] * B[12] + movq 96(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[10] * B[11] + movq 88(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[11] * B[10] + movq 80(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[12] * B[9] + movq 72(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[13] * B[8] + movq 64(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[14] * B[7] + movq 56(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[15] * B[6] + movq 48(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 168(%rdi) + # A[7] * B[15] + movq 120(%rcx), %rax + mulq 56(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[8] * B[14] + movq 112(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[9] * B[13] + movq 104(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[10] * B[12] + movq 96(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[11] * B[11] + movq 88(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[12] * B[10] + movq 80(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[13] * B[9] + movq 72(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[14] * B[8] + movq 64(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[15] * B[7] + movq 56(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 176(%rdi) + # A[8] * B[15] + movq 120(%rcx), %rax + mulq 64(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[9] * B[14] + movq 112(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[10] * B[13] + movq 104(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[11] * B[12] + movq 96(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[12] * B[11] + movq 88(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[13] * B[10] + movq 80(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[14] * B[9] + movq 72(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[15] * B[8] + movq 64(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 184(%rdi) + # A[9] * B[15] + movq 120(%rcx), %rax + mulq 72(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[10] * B[14] + movq 112(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[11] * B[13] + movq 104(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[12] * B[12] + movq 96(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[13] * B[11] + movq 88(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[14] * B[10] + movq 80(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[15] * B[9] + movq 72(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 192(%rdi) + # A[10] * B[15] + movq 120(%rcx), %rax + mulq 80(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[11] * B[14] + movq 112(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[12] * B[13] + movq 104(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[13] * B[12] + movq 96(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[14] * B[11] + movq 88(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[15] * B[10] + movq 80(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 200(%rdi) + # A[11] * B[15] + movq 120(%rcx), %rax + mulq 88(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[12] * B[14] + movq 112(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[13] * B[13] + movq 104(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[14] * B[12] + movq 96(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[15] * B[11] + movq 88(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 208(%rdi) + # A[12] * B[15] + movq 120(%rcx), %rax + mulq 96(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[13] * B[14] + movq 112(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[14] * B[13] + movq 104(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[15] * B[12] + movq 96(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r10 + movq %r8, 216(%rdi) + # A[13] * B[15] + movq 120(%rcx), %rax + mulq 104(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[14] * B[14] + movq 112(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[15] * B[13] + movq 104(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r8 + movq %r9, 224(%rdi) + # A[14] * B[15] + movq 120(%rcx), %rax + mulq 112(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[15] * B[14] + movq 112(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %r10, 232(%rdi) + # A[15] * B[15] + movq 120(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r8 + movq 56(%rsp), %r9 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r8 + movq 120(%rsp), %r9 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_mul_16,.-sp_1024_mul_16 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_sqr_16 +.type sp_1024_sqr_16,@function +.align 16 +sp_1024_sqr_16: +#else +.section __TEXT,__text +.globl _sp_1024_sqr_16 +.p2align 4 +_sp_1024_sqr_16: +#endif /* __APPLE__ */ + pushq %r12 + subq $0x80, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %rcx, 24(%rsp) + # A[0] * A[4] + movq 32(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + movq %r8, 32(%rsp) + # A[0] * A[5] + movq 40(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[4] + movq 32(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 40(%rsp) + # A[0] * A[6] + movq 48(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[5] + movq 40(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[4] + movq 32(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 48(%rsp) + # A[0] * A[7] + movq 56(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[6] + movq 48(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[5] + movq 40(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[4] + movq 32(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 56(%rsp) + # A[0] * A[8] + movq 64(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[7] + movq 56(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[6] + movq 48(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[5] + movq 40(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[4] + movq 32(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 64(%rsp) + # A[0] * A[9] + movq 72(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[8] + movq 64(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[7] + movq 56(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[6] + movq 48(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[5] + movq 40(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 72(%rsp) + # A[0] * A[10] + movq 80(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[9] + movq 72(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[8] + movq 64(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[7] + movq 56(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[6] + movq 48(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[5] + movq 40(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 80(%rsp) + # A[0] * A[11] + movq 88(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[10] + movq 80(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[9] + movq 72(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[8] + movq 64(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[7] + movq 56(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[6] + movq 48(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 88(%rsp) + # A[0] * A[12] + movq 96(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[11] + movq 88(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[10] + movq 80(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[9] + movq 72(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[8] + movq 64(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[7] + movq 56(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[6] + movq 48(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 96(%rsp) + # A[0] * A[13] + movq 104(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[12] + movq 96(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[11] + movq 88(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[10] + movq 80(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[9] + movq 72(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[8] + movq 64(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[7] + movq 56(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 104(%rsp) + # A[0] * A[14] + movq 112(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[13] + movq 104(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[12] + movq 96(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[11] + movq 88(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[10] + movq 80(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[9] + movq 72(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[8] + movq 64(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[7] + movq 56(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 112(%rsp) + # A[0] * A[15] + movq 120(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[14] + movq 112(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * A[13] + movq 104(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[12] + movq 96(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[11] + movq 88(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[10] + movq 80(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[9] + movq 72(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[8] + movq 64(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 120(%rsp) + # A[1] * A[15] + movq 120(%rsi), %rax + mulq 8(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[2] * A[14] + movq 112(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[3] * A[13] + movq 104(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[12] + movq 96(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[11] + movq 88(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[10] + movq 80(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[9] + movq 72(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[8] * A[8] + movq 64(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 128(%rdi) + # A[2] * A[15] + movq 120(%rsi), %rax + mulq 16(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[3] * A[14] + movq 112(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[4] * A[13] + movq 104(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[12] + movq 96(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[11] + movq 88(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[10] + movq 80(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[8] * A[9] + movq 72(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 136(%rdi) + # A[3] * A[15] + movq 120(%rsi), %rax + mulq 24(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[4] * A[14] + movq 112(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[5] * A[13] + movq 104(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[12] + movq 96(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[11] + movq 88(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[8] * A[10] + movq 80(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[9] * A[9] + movq 72(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 144(%rdi) + # A[4] * A[15] + movq 120(%rsi), %rax + mulq 32(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[5] * A[14] + movq 112(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[6] * A[13] + movq 104(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[12] + movq 96(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[8] * A[11] + movq 88(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[9] * A[10] + movq 80(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 152(%rdi) + # A[5] * A[15] + movq 120(%rsi), %rax + mulq 40(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[6] * A[14] + movq 112(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[7] * A[13] + movq 104(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[8] * A[12] + movq 96(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[9] * A[11] + movq 88(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[10] * A[10] + movq 80(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 160(%rdi) + # A[6] * A[15] + movq 120(%rsi), %rax + mulq 48(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[7] * A[14] + movq 112(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[8] * A[13] + movq 104(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[9] * A[12] + movq 96(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[10] * A[11] + movq 88(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 168(%rdi) + # A[7] * A[15] + movq 120(%rsi), %rax + mulq 56(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[8] * A[14] + movq 112(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[9] * A[13] + movq 104(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[10] * A[12] + movq 96(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[11] * A[11] + movq 88(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 176(%rdi) + # A[8] * A[15] + movq 120(%rsi), %rax + mulq 64(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[9] * A[14] + movq 112(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[10] * A[13] + movq 104(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[11] * A[12] + movq 96(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 184(%rdi) + # A[9] * A[15] + movq 120(%rsi), %rax + mulq 72(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[10] * A[14] + movq 112(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[11] * A[13] + movq 104(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[12] * A[12] + movq 96(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 192(%rdi) + # A[10] * A[15] + movq 120(%rsi), %rax + mulq 80(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[11] * A[14] + movq 112(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[12] * A[13] + movq 104(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 200(%rdi) + # A[11] * A[15] + movq 120(%rsi), %rax + mulq 88(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + # A[12] * A[14] + movq 112(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + # A[13] * A[13] + movq 104(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + movq %r9, 208(%rdi) + # A[12] * A[15] + movq 120(%rsi), %rax + mulq 96(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[13] * A[14] + movq 112(%rsi), %rax + mulq 104(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0x00, %r9 + movq %rcx, 216(%rdi) + # A[13] * A[15] + movq 120(%rsi), %rax + mulq 104(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + # A[14] * A[14] + movq 112(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %rcx + movq %r8, 224(%rdi) + # A[14] * A[15] + movq 120(%rsi), %rax + mulq 112(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0x00, %r8 + movq %r9, 232(%rdi) + # A[15] * A[15] + movq 120(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + movq %rcx, 240(%rdi) + movq %r8, 248(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r10 + movq 120(%rsp), %r11 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + addq $0x80, %rsp + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_1024_sqr_16,.-sp_1024_sqr_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mul_avx2_16 +.type sp_1024_mul_avx2_16,@function +.align 16 +sp_1024_mul_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mul_avx2_16 +.p2align 4 +_sp_1024_mul_avx2_16: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + movq %rdx, %rbp + subq $0x80, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbx + cmovne %rdi, %rbx + cmpq %rdi, %rbp + cmove %rsp, %rbx + addq $0x80, %rdi + xorq %r14, %r14 + movq (%rsi), %rdx + # A[0] * B[0] + mulx (%rbp), %r8, %r9 + # A[0] * B[1] + mulx 8(%rbp), %rax, %r10 + movq %r8, (%rbx) + adcxq %rax, %r9 + # A[0] * B[2] + mulx 16(%rbp), %rax, %r11 + movq %r9, 8(%rbx) + adcxq %rax, %r10 + # A[0] * B[3] + mulx 24(%rbp), %rax, %r12 + movq %r10, 16(%rbx) + adcxq %rax, %r11 + movq %r11, 24(%rbx) + # A[0] * B[4] + mulx 32(%rbp), %rax, %r8 + adcxq %rax, %r12 + # A[0] * B[5] + mulx 40(%rbp), %rax, %r9 + movq %r12, 32(%rbx) + adcxq %rax, %r8 + # A[0] * B[6] + mulx 48(%rbp), %rax, %r10 + movq %r8, 40(%rbx) + adcxq %rax, %r9 + # A[0] * B[7] + mulx 56(%rbp), %rax, %r11 + movq %r9, 48(%rbx) + adcxq %rax, %r10 + movq %r10, 56(%rbx) + # A[0] * B[8] + mulx 64(%rbp), %rax, %r12 + adcxq %rax, %r11 + # A[0] * B[9] + mulx 72(%rbp), %rax, %r8 + movq %r11, 64(%rbx) + adcxq %rax, %r12 + # A[0] * B[10] + mulx 80(%rbp), %rax, %r9 + movq %r12, 72(%rbx) + adcxq %rax, %r8 + # A[0] * B[11] + mulx 88(%rbp), %rax, %r10 + movq %r8, 80(%rbx) + adcxq %rax, %r9 + movq %r9, 88(%rbx) + # A[0] * B[12] + mulx 96(%rbp), %rax, %r11 + adcxq %rax, %r10 + # A[0] * B[13] + mulx 104(%rbp), %rax, %r12 + movq %r10, 96(%rbx) + adcxq %rax, %r11 + # A[0] * B[14] + mulx 112(%rbp), %rax, %r8 + movq %r11, 104(%rbx) + adcxq %rax, %r12 + # A[0] * B[15] + mulx 120(%rbp), %rax, %r9 + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adcxq %r14, %r9 + movq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 120(%rbx) + movq %r9, (%rdi) + movq 8(%rsi), %rdx + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %r11 + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + # A[1] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 8(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 16(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 24(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 32(%rbx) + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + # A[1] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rbx) + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + # A[1] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rbx) + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + # A[1] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq 16(%rsi), %rdx + movq 16(%rbx), %r10 + movq 24(%rbx), %r11 + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + # A[2] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 16(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 24(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 32(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 40(%rbx) + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + # A[2] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rbx) + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + # A[2] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rbx) + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + # A[2] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, (%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq 24(%rsi), %rdx + movq 24(%rbx), %r11 + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + # A[3] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 24(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 32(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 48(%rbx) + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + # A[3] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rbx) + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + # A[3] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rbx) + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + # A[3] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq 32(%rsi), %rdx + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + # A[4] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 32(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 56(%rbx) + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + # A[4] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rbx) + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + # A[4] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rbx) + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + # A[4] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 24(%rdi) + movq %r8, 32(%rdi) + movq 40(%rsi), %rdx + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + # A[5] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rbx) + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + # A[5] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rbx) + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + # A[5] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, (%rdi) + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + # A[5] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq 48(%rsi), %rdx + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + # A[6] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rbx) + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + # A[6] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rbx) + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + # A[6] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 8(%rdi) + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + # A[6] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq 56(%rsi), %rdx + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + # A[7] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rbx) + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + # A[7] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rbx) + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + # A[7] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + # A[7] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsi), %rdx + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + # A[8] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rbx) + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + # A[8] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rbx) + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + # A[8] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 24(%rdi) + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + # A[8] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 48(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 56(%rdi) + movq %r12, 64(%rdi) + movq 72(%rsi), %rdx + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + # A[9] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rbx) + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + # A[9] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, (%rdi) + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + # A[9] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 32(%rdi) + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + # A[9] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 48(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 56(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 64(%rdi) + movq %r8, 72(%rdi) + movq 80(%rsi), %rdx + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + # A[10] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rbx) + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + # A[10] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 8(%rdi) + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + # A[10] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 40(%rdi) + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + # A[10] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 48(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 56(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 64(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) + movq 88(%rsi), %rdx + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + # A[11] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rbx) + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + # A[11] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + # A[11] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 + # A[11] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 56(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 64(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 72(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + movq 96(%rsi), %rdx + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + # A[12] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rbx) + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + # A[12] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 24(%rdi) + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + # A[12] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 48(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 56(%rdi) + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 + movq 88(%rdi), %r10 + # A[12] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 64(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 72(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 80(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 88(%rdi) + movq %r11, 96(%rdi) + movq 104(%rsi), %rdx + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + # A[13] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, (%rdi) + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + # A[13] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 32(%rdi) + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + # A[13] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 48(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 56(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 64(%rdi) + movq 80(%rdi), %r9 + movq 88(%rdi), %r10 + movq 96(%rdi), %r11 + # A[13] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 72(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 80(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 88(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 96(%rdi) + movq %r12, 104(%rdi) + movq 112(%rsi), %rdx + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + # A[14] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 8(%rdi) + movq 24(%rdi), %r12 + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + # A[14] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 16(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 40(%rdi) + movq 56(%rdi), %r11 + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 + # A[14] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 48(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 56(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 64(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 72(%rdi) + movq 88(%rdi), %r10 + movq 96(%rdi), %r11 + movq 104(%rdi), %r12 + # A[14] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 80(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 88(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 96(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 104(%rdi) + movq %r8, 112(%rdi) + movq 120(%rsi), %rdx + movq 120(%rbx), %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + # A[15] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, (%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 8(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + movq 48(%rdi), %r10 + movq 56(%rdi), %r11 + # A[15] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 24(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 32(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 40(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + movq 64(%rdi), %r12 + movq 72(%rdi), %r8 + movq 80(%rdi), %r9 + movq 88(%rdi), %r10 + # A[15] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 56(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 64(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 72(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 80(%rdi) + movq 96(%rdi), %r11 + movq 104(%rdi), %r12 + movq 112(%rdi), %r8 + # A[15] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 88(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 96(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 104(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + subq $0x80, %rdi + cmpq %rdi, %rsi + je L_start_1024_mul_avx2_16 + cmpq %rdi, %rbp + jne L_end_1024_mul_avx2_16 +L_start_1024_mul_avx2_16: + vmovdqu (%rbx), %xmm0 + vmovups %xmm0, (%rdi) + vmovdqu 16(%rbx), %xmm0 + vmovups %xmm0, 16(%rdi) + vmovdqu 32(%rbx), %xmm0 + vmovups %xmm0, 32(%rdi) + vmovdqu 48(%rbx), %xmm0 + vmovups %xmm0, 48(%rdi) + vmovdqu 64(%rbx), %xmm0 + vmovups %xmm0, 64(%rdi) + vmovdqu 80(%rbx), %xmm0 + vmovups %xmm0, 80(%rdi) + vmovdqu 96(%rbx), %xmm0 + vmovups %xmm0, 96(%rdi) + vmovdqu 112(%rbx), %xmm0 + vmovups %xmm0, 112(%rdi) +L_end_1024_mul_avx2_16: + addq $0x80, %rsp + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size sp_1024_mul_avx2_16,.-sp_1024_mul_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_sqr_avx2_16 +.type sp_1024_sqr_avx2_16,@function +.align 16 +sp_1024_sqr_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_sqr_avx2_16 +.p2align 4 +_sp_1024_sqr_avx2_16: +#endif /* __APPLE__ */ + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + subq $0x80, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbp + cmovne %rdi, %rbp + addq $0x80, %rdi + xorq %r11, %r11 + # Diagonal 1 + xorq %r10, %r10 + # A[1] x A[0] + movq (%rsi), %rdx + mulxq 8(%rsi), %r8, %r9 + # A[2] x A[0] + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 8(%rbp) + movq %r9, 16(%rbp) + movq %r11, %r8 + movq %r11, %r9 + # A[3] x A[0] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[4] x A[0] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 24(%rbp) + movq %r8, 32(%rbp) + movq %r11, %r10 + movq %r11, %r8 + # A[5] x A[0] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] x A[0] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 40(%rbp) + movq %r10, 48(%rbp) + movq %r11, %r9 + movq %r11, %r10 + # A[7] x A[0] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] x A[0] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 56(%rbp) + movq %r9, 64(%rbp) + movq %r11, %r8 + movq %r11, %r9 + # A[9] x A[0] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[10] x A[0] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 72(%rbp) + movq %r8, 80(%rbp) + movq %r11, %r10 + movq %r11, %r8 + # A[11] x A[0] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] x A[0] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 88(%rbp) + movq %r10, %r13 + movq %r11, %r9 + movq %r11, %r10 + # A[13] x A[0] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[0] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, %r14 + movq %r9, %r15 + movq %r11, %r8 + # A[15] x A[0] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, %rbx + # Carry + adcxq %r11, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, (%rdi) + # Diagonal 2 + movq 24(%rbp), %r8 + movq 32(%rbp), %r9 + movq 40(%rbp), %r10 + # A[2] x A[1] + movq 8(%rsi), %rdx + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] x A[1] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 24(%rbp) + movq %r9, 32(%rbp) + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + # A[4] x A[1] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[5] x A[1] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 40(%rbp) + movq %r8, 48(%rbp) + movq 64(%rbp), %r10 + movq 72(%rbp), %r8 + # A[6] x A[1] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] x A[1] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 56(%rbp) + movq %r10, 64(%rbp) + movq 80(%rbp), %r9 + movq 88(%rbp), %r10 + # A[8] x A[1] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] x A[1] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 72(%rbp) + movq %r9, 80(%rbp) + # No load %r13 - %r8 + # No load %r14 - %r9 + # A[10] x A[1] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r13 + # A[11] x A[1] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r10, 88(%rbp) + # No store %r13 + # No load %r15 - %r10 + # No load %rbx - %r8 + # A[12] x A[1] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[13] x A[1] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq (%rdi), %r9 + movq %r11, %r10 + # A[14] x A[1] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # A[15] x A[1] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # No store %rbx + movq %r9, (%rdi) + movq %r11, %r8 + # A[15] x A[2] + movq 16(%rsi), %rdx + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 8(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 16(%rdi) + # Diagonal 3 + movq 40(%rbp), %r8 + movq 48(%rbp), %r9 + movq 56(%rbp), %r10 + # A[3] x A[2] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] x A[2] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 40(%rbp) + movq %r9, 48(%rbp) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[5] x A[2] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[6] x A[2] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 56(%rbp) + movq %r8, 64(%rbp) + movq 80(%rbp), %r10 + movq 88(%rbp), %r8 + # A[7] x A[2] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] x A[2] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 72(%rbp) + movq %r10, 80(%rbp) + # No load %r13 - %r9 + # No load %r14 - %r10 + # A[9] x A[2] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r13 + # A[10] x A[2] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r8, 88(%rbp) + # No store %r13 + # No load %r15 - %r8 + # No load %rbx - %r9 + # A[11] x A[2] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[12] x A[2] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq (%rdi), %r10 + movq 8(%rdi), %r8 + # A[13] x A[2] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r10 + # A[14] x A[2] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # No store %rbx + movq %r10, (%rdi) + movq 16(%rdi), %r9 + movq %r11, %r10 + # A[14] x A[3] + movq 112(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r11, %r8 + # A[14] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 24(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 32(%rdi) + # Diagonal 4 + movq 56(%rbp), %r8 + movq 64(%rbp), %r9 + movq 72(%rbp), %r10 + # A[4] x A[3] + movq 24(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] x A[3] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 56(%rbp) + movq %r9, 64(%rbp) + movq 80(%rbp), %r8 + movq 88(%rbp), %r9 + # A[6] x A[3] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[7] x A[3] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 72(%rbp) + movq %r8, 80(%rbp) + # No load %r13 - %r10 + # No load %r14 - %r8 + # A[8] x A[3] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r13 + # A[9] x A[3] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r9, 88(%rbp) + # No store %r13 + # No load %r15 - %r9 + # No load %rbx - %r10 + # A[10] x A[3] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[11] x A[3] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + # A[12] x A[3] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # A[13] x A[3] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # No store %rbx + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 + # A[13] x A[4] + movq 104(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 + movq %r11, %r10 + # A[13] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq %r11, %r8 + # A[13] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 40(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 48(%rdi) + # Diagonal 5 + movq 72(%rbp), %r8 + movq 80(%rbp), %r9 + movq 88(%rbp), %r10 + # A[5] x A[4] + movq 32(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] x A[4] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 72(%rbp) + movq %r9, 80(%rbp) + # No load %r13 - %r8 + # No load %r14 - %r9 + # A[7] x A[4] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r13 + # A[8] x A[4] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r10, 88(%rbp) + # No store %r13 + # No load %r15 - %r10 + # No load %rbx - %r8 + # A[9] x A[4] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[10] x A[4] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + # A[11] x A[4] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # A[12] x A[4] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # No store %rbx + movq %r9, (%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + # A[12] x A[5] + movq 96(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[12] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 8(%rdi) + movq %r8, 16(%rdi) + movq 32(%rdi), %r10 + movq 40(%rdi), %r8 + # A[12] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 24(%rdi) + movq %r10, 32(%rdi) + movq 48(%rdi), %r9 + movq %r11, %r10 + # A[12] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq %r11, %r8 + # A[12] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 56(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 64(%rdi) + # Diagonal 6 + movq 88(%rbp), %r8 + # No load %r13 - %r9 + # No load %r14 - %r10 + # A[6] x A[5] + movq 40(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r13 + # A[7] x A[5] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r8, 88(%rbp) + # No store %r13 + # No load %r15 - %r8 + # No load %rbx - %r9 + # A[8] x A[5] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[9] x A[5] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq (%rdi), %r10 + movq 8(%rdi), %r8 + # A[10] x A[5] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r10 + # A[11] x A[5] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # No store %rbx + movq %r10, (%rdi) + movq 16(%rdi), %r9 + movq 24(%rdi), %r10 + # A[11] x A[6] + movq 88(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + # A[11] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[11] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 24(%rdi) + movq %r8, 32(%rdi) + movq 48(%rdi), %r10 + movq 56(%rdi), %r8 + # A[11] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[9] + movq 104(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq 64(%rdi), %r9 + movq %r11, %r10 + # A[13] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 56(%rdi) + movq %r9, 64(%rdi) + movq %r11, %r8 + # A[13] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 72(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 80(%rdi) + # Diagonal 7 + # No load %r14 - %r8 + # No load %r15 - %r9 + # No load %rbx - %r10 + # A[7] x A[6] + movq 48(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[8] x A[6] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + # A[9] x A[6] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # A[10] x A[6] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # No store %rbx + movq %r8, (%rdi) + movq 16(%rdi), %r10 + movq 24(%rdi), %r8 + # A[10] x A[7] + movq 80(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 + # A[10] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[6] + movq 112(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 + # A[14] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[14] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 40(%rdi) + movq %r8, 48(%rdi) + movq 64(%rdi), %r10 + movq 72(%rdi), %r8 + # A[14] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 56(%rdi) + movq %r10, 64(%rdi) + movq 80(%rdi), %r9 + movq %r11, %r10 + # A[14] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) + movq %r11, %r8 + # A[14] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 88(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 96(%rdi) + # Diagonal 8 + # No load %rbx - %r8 + movq (%rdi), %r9 + movq 8(%rdi), %r10 + # A[8] x A[7] + movq 56(%rsi), %rdx + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # A[9] x A[7] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # No store %rbx + movq %r9, (%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + # A[9] x A[8] + movq 64(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[15] x A[3] + movq 120(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 8(%rdi) + movq %r8, 16(%rdi) + movq 32(%rdi), %r10 + movq 40(%rdi), %r8 + # A[15] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 24(%rdi) + movq %r10, 32(%rdi) + movq 48(%rdi), %r9 + movq 56(%rdi), %r10 + # A[15] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq 64(%rdi), %r8 + movq 72(%rdi), %r9 + # A[15] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[15] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 56(%rdi) + movq %r8, 64(%rdi) + movq 80(%rdi), %r10 + movq 88(%rdi), %r8 + # A[15] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 72(%rdi) + movq %r10, 80(%rdi) + movq 96(%rdi), %r9 + movq %r11, %r10 + # A[15] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 88(%rdi) + movq %r9, 96(%rdi) + movq %r11, %r8 + # A[15] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 104(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 112(%rdi) + movq %r12, 120(%rdi) + # Double and Add in A[i] x A[i] + movq 8(%rbp), %r9 + # A[0] x A[0] + movq (%rsi), %rdx + mulxq %rdx, %rax, %rcx + movq %rax, (%rbp) + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r9, 8(%rbp) + movq 16(%rbp), %r8 + movq 24(%rbp), %r9 + # A[1] x A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 16(%rbp) + movq %r9, 24(%rbp) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + # A[2] x A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + # A[3] x A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 48(%rbp) + movq %r9, 56(%rbp) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[4] x A[4] + movq 32(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 64(%rbp) + movq %r9, 72(%rbp) + movq 80(%rbp), %r8 + movq 88(%rbp), %r9 + # A[5] x A[5] + movq 40(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 80(%rbp) + movq %r9, 88(%rbp) + # A[6] x A[6] + movq 48(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r13, %r13 + adoxq %r14, %r14 + adcxq %rax, %r13 + adcxq %rcx, %r14 + # A[7] x A[7] + movq 56(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r15, %r15 + adoxq %rbx, %rbx + adcxq %rax, %r15 + adcxq %rcx, %rbx + movq (%rdi), %r8 + movq 8(%rdi), %r9 + # A[8] x A[8] + movq 64(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + # A[9] x A[9] + movq 72(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdi), %r8 + movq 40(%rdi), %r9 + # A[10] x A[10] + movq 80(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 + # A[11] x A[11] + movq 88(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rdi), %r8 + movq 72(%rdi), %r9 + # A[12] x A[12] + movq 96(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq 80(%rdi), %r8 + movq 88(%rdi), %r9 + # A[13] x A[13] + movq 104(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[14] x A[14] + movq 112(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq 112(%rdi), %r8 + movq 120(%rdi), %r9 + # A[15] x A[15] + movq 120(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq %r13, -32(%rdi) + movq %r14, -24(%rdi) + movq %r15, -16(%rdi) + movq %rbx, -8(%rdi) + subq $0x80, %rdi + cmpq %rdi, %rsi + jne L_end_1024_sqr_avx2_16 + vmovdqu (%rbp), %xmm0 + vmovups %xmm0, (%rdi) + vmovdqu 16(%rbp), %xmm0 + vmovups %xmm0, 16(%rdi) + vmovdqu 32(%rbp), %xmm0 + vmovups %xmm0, 32(%rdi) + vmovdqu 48(%rbp), %xmm0 + vmovups %xmm0, 48(%rdi) + vmovdqu 64(%rbp), %xmm0 + vmovups %xmm0, 64(%rdi) + vmovdqu 80(%rbp), %xmm0 + vmovups %xmm0, 80(%rdi) +L_end_1024_sqr_avx2_16: + addq $0x80, %rsp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + repz retq +#ifndef __APPLE__ +.size sp_1024_sqr_avx2_16,.-sp_1024_sqr_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_add_16 +.type sp_1024_add_16,@function +.align 16 +sp_1024_add_16: +#else +.section __TEXT,__text +.globl _sp_1024_add_16 +.p2align 4 +_sp_1024_add_16: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + adcq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + adcq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + adcq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + adcq 120(%rdx), %r8 + movq %r8, 120(%rdi) + adcq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_1024_add_16,.-sp_1024_add_16 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_sub_in_place_16 +.type sp_1024_sub_in_place_16,@function +.align 16 +sp_1024_sub_in_place_16: +#else +.section __TEXT,__text +.globl _sp_1024_sub_in_place_16 +.p2align 4 +_sp_1024_sub_in_place_16: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq %rcx, 120(%rdi) + sbbq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_1024_sub_in_place_16,.-sp_1024_sub_in_place_16 +#endif /* __APPLE__ */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_cond_sub_16 +.type sp_1024_cond_sub_16,@function +.align 16 +sp_1024_cond_sub_16: +#else +.section __TEXT,__text +.globl _sp_1024_cond_sub_16 +.p2align 4 +_sp_1024_cond_sub_16: +#endif /* __APPLE__ */ + subq $0x80, %rsp + movq $0x00, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %rax + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_cond_sub_16,.-sp_1024_cond_sub_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_cond_sub_avx2_16 +.type sp_1024_cond_sub_avx2_16,@function +.align 16 +sp_1024_cond_sub_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_cond_sub_avx2_16 +.p2align 4 +_sp_1024_cond_sub_avx2_16: +#endif /* __APPLE__ */ + movq $0x00, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + sbbq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + sbbq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + sbbq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + sbbq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + sbbq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + sbbq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + sbbq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + sbbq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + sbbq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + sbbq %r9, %r8 + movq %r8, 120(%rdi) + sbbq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_1024_cond_sub_avx2_16,.-sp_1024_cond_sub_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mul_d_16 +.type sp_1024_mul_d_16,@function +.align 16 +sp_1024_mul_d_16: +#else +.section __TEXT,__text +.globl _sp_1024_mul_d_16 +.p2align 4 +_sp_1024_mul_d_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0x00, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0x00, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0x00, %r9 + # A[15] * B + movq %rcx, %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 120(%rdi) + movq %r9, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_mul_d_16,.-sp_1024_mul_d_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mul_d_avx2_16 +.type sp_1024_mul_d_avx2_16,@function +.align 16 +sp_1024_mul_d_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mul_d_avx2_16 +.p2align 4 +_sp_1024_mul_d_avx2_16: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 8(%rdi) + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 16(%rdi) + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 24(%rdi) + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 32(%rdi) + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 40(%rdi) + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 48(%rdi) + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 56(%rdi) + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 64(%rdi) + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 72(%rdi) + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 80(%rdi) + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 88(%rdi) + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 96(%rdi) + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 104(%rdi) + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 112(%rdi) + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 120(%rdi) + movq %r9, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_mul_d_avx2_16,.-sp_1024_mul_d_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef _WIN64 +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +#ifndef __APPLE__ +.text +.globl div_1024_word_asm_16 +.type div_1024_word_asm_16,@function +.align 16 +div_1024_word_asm_16: +#else +.section __TEXT,__text +.globl _div_1024_word_asm_16 +.p2align 4 +_div_1024_word_asm_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq %rsi, %rax + movq %rdi, %rdx + divq %rcx + repz retq +#ifndef __APPLE__ +.size div_1024_word_asm_16,.-div_1024_word_asm_16 +#endif /* __APPLE__ */ +#endif /* _WIN64 */ +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_cmp_16 +.type sp_1024_cmp_16,@function +.align 16 +sp_1024_cmp_16: +#else +.section __TEXT,__text +.globl _sp_1024_cmp_16 +.p2align 4 +_sp_1024_cmp_16: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $0x01, %r8 + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_1024_cmp_16,.-sp_1024_cmp_16 +#endif /* __APPLE__ */ +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_cond_copy_16 +.type sp_1024_cond_copy_16,@function +.align 16 +sp_1024_cond_copy_16: +#else +.section __TEXT,__text +.globl _sp_1024_cond_copy_16 +.p2align 4 +_sp_1024_cond_copy_16: +#endif /* __APPLE__ */ + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + xorq (%rsi), %rax + xorq 8(%rsi), %rcx + xorq 16(%rsi), %r8 + xorq 24(%rsi), %r9 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + xorq %rax, (%rdi) + xorq %rcx, 8(%rdi) + xorq %r8, 16(%rdi) + xorq %r9, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 + xorq 32(%rsi), %rax + xorq 40(%rsi), %rcx + xorq 48(%rsi), %r8 + xorq 56(%rsi), %r9 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + xorq %rax, 32(%rdi) + xorq %rcx, 40(%rdi) + xorq %r8, 48(%rdi) + xorq %r9, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + movq 80(%rdi), %r8 + movq 88(%rdi), %r9 + xorq 64(%rsi), %rax + xorq 72(%rsi), %rcx + xorq 80(%rsi), %r8 + xorq 88(%rsi), %r9 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + xorq %rax, 64(%rdi) + xorq %rcx, 72(%rdi) + xorq %r8, 80(%rdi) + xorq %r9, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + movq 112(%rdi), %r8 + movq 120(%rdi), %r9 + xorq 96(%rsi), %rax + xorq 104(%rsi), %rcx + xorq 112(%rsi), %r8 + xorq 120(%rsi), %r9 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + xorq %rax, 96(%rdi) + xorq %rcx, 104(%rdi) + xorq %r8, 112(%rdi) + xorq %r9, 120(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_cond_copy_16,.-sp_1024_cond_copy_16 +#endif /* __APPLE__ */ +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_reduce_16 +.type sp_1024_mont_reduce_16,@function +.align 16 +sp_1024_mont_reduce_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_reduce_16 +.p2align 4 +_sp_1024_mont_reduce_16: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 16 + movq $16, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_1024_mont_loop_16: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0x00, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0x00, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0x00, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0x00, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0x00, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0x00, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0x00, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0x00, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0x00, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0x00, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0x00, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0x00, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0x00, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0x00, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0x00, %r15 + adcq $0x00, %r15 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq %rdx, 128(%rdi) + adcq $0x00, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_1024_mont_loop_16 + movq 120(%rdi), %r12 + movq %r13, (%rdi) + subq 120(%rsi), %r12 + movq %r14, 8(%rdi) + sbbq %r12, %r12 + negq %r15 + notq %r12 + orq %r12, %r15 +#ifdef _WIN64 + movq %rsi, %rdx + movq %r15, %rcx +#else + movq %r15, %rcx + movq %rsi, %rdx +#endif /* _WIN64 */ + movq %rdi, %rsi + movq %rdi, %rdi + subq $0x80, %rdi +#ifndef __APPLE__ + callq sp_1024_cond_sub_16@plt +#else + callq _sp_1024_cond_sub_16 +#endif /* __APPLE__ */ + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_reduce_16,.-sp_1024_mont_reduce_16 +#endif /* __APPLE__ */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_add_16 +.type sp_1024_mont_add_16,@function +.align 16 +sp_1024_mont_add_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_add_16 +.p2align 4 +_sp_1024_mont_add_16: +#endif /* __APPLE__ */ + subq $0x80, %rsp + movq (%rsi), %rax + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + addq (%rdx), %rax + movq $0x00, %r11 + adcq 8(%rdx), %r8 + adcq 16(%rdx), %r9 + adcq 24(%rdx), %r10 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %r8 + movq 48(%rsi), %r9 + movq 56(%rsi), %r10 + adcq 32(%rdx), %rax + adcq 40(%rdx), %r8 + adcq 48(%rdx), %r9 + adcq 56(%rdx), %r10 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq %r10, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %r8 + movq 80(%rsi), %r9 + movq 88(%rsi), %r10 + adcq 64(%rdx), %rax + adcq 72(%rdx), %r8 + adcq 80(%rdx), %r9 + adcq 88(%rdx), %r10 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %r8 + movq 112(%rsi), %r9 + movq 120(%rsi), %r10 + adcq 96(%rdx), %rax + adcq 104(%rdx), %r8 + adcq 112(%rdx), %r9 + adcq 120(%rdx), %r10 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq %r9, 112(%rdi) + movq %r10, 120(%rdi) + sbbq $0x00, %r11 + subq 120(%rcx), %r10 + sbbq %r10, %r10 + notq %r10 + orq %r10, %r11 + movq (%rcx), %r9 + movq 8(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq 16(%rcx), %r9 + movq 24(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 16(%rsp) + movq %r10, 24(%rsp) + movq 32(%rcx), %r9 + movq 40(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq 48(%rcx), %r9 + movq 56(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 48(%rsp) + movq %r10, 56(%rsp) + movq 64(%rcx), %r9 + movq 72(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq 80(%rcx), %r9 + movq 88(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 80(%rsp) + movq %r10, 88(%rsp) + movq 96(%rcx), %r9 + movq 104(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 96(%rsp) + movq %r10, 104(%rsp) + movq 112(%rcx), %r9 + movq 120(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 112(%rsp) + movq %r10, 120(%rsp) + movq (%rdi), %rax + movq 8(%rdi), %r8 + subq (%rsp), %rax + sbbq 8(%rsp), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq 16(%rdi), %rax + movq 24(%rdi), %r8 + sbbq 16(%rsp), %rax + sbbq 24(%rsp), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %r8 + sbbq 32(%rsp), %rax + sbbq 40(%rsp), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq 48(%rdi), %rax + movq 56(%rdi), %r8 + sbbq 48(%rsp), %rax + sbbq 56(%rsp), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %r8 + sbbq 64(%rsp), %rax + sbbq 72(%rsp), %r8 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq 80(%rdi), %rax + movq 88(%rdi), %r8 + sbbq 80(%rsp), %rax + sbbq 88(%rsp), %r8 + movq %rax, 80(%rdi) + movq %r8, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %r8 + sbbq 96(%rsp), %rax + sbbq 104(%rsp), %r8 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq 112(%rdi), %rax + movq 120(%rdi), %r8 + sbbq 112(%rsp), %rax + sbbq 120(%rsp), %r8 + movq %rax, 112(%rdi) + movq %r8, 120(%rdi) + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_add_16,.-sp_1024_mont_add_16 +#endif /* __APPLE__ */ +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of addition. + * a Number to souble in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_dbl_16 +.type sp_1024_mont_dbl_16,@function +.align 16 +sp_1024_mont_dbl_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_dbl_16 +.p2align 4 +_sp_1024_mont_dbl_16: +#endif /* __APPLE__ */ + subq $0x80, %rsp + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + addq (%rsi), %rax + movq $0x00, %r10 + adcq 8(%rsi), %rcx + adcq 16(%rsi), %r8 + adcq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %rcx + movq 48(%rsi), %r8 + movq 56(%rsi), %r9 + adcq 32(%rsi), %rax + adcq 40(%rsi), %rcx + adcq 48(%rsi), %r8 + adcq 56(%rsi), %r9 + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %rcx + movq 80(%rsi), %r8 + movq 88(%rsi), %r9 + adcq 64(%rsi), %rax + adcq 72(%rsi), %rcx + adcq 80(%rsi), %r8 + adcq 88(%rsi), %r9 + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %rcx + movq 112(%rsi), %r8 + movq 120(%rsi), %r9 + adcq 96(%rsi), %rax + adcq 104(%rsi), %rcx + adcq 112(%rsi), %r8 + adcq 120(%rsi), %r9 + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %r10 + subq 120(%rdx), %r9 + sbbq %r9, %r9 + notq %r9 + orq %r9, %r10 + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rdi), %rax + movq 8(%rdi), %rcx + subq (%rsp), %rax + sbbq 8(%rsp), %rcx + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq 16(%rdi), %rax + movq 24(%rdi), %rcx + sbbq 16(%rsp), %rax + sbbq 24(%rsp), %rcx + movq %rax, 16(%rdi) + movq %rcx, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + sbbq 32(%rsp), %rax + sbbq 40(%rsp), %rcx + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq 48(%rdi), %rax + movq 56(%rdi), %rcx + sbbq 48(%rsp), %rax + sbbq 56(%rsp), %rcx + movq %rax, 48(%rdi) + movq %rcx, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + sbbq 64(%rsp), %rax + sbbq 72(%rsp), %rcx + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq 80(%rdi), %rax + movq 88(%rdi), %rcx + sbbq 80(%rsp), %rax + sbbq 88(%rsp), %rcx + movq %rax, 80(%rdi) + movq %rcx, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + sbbq 96(%rsp), %rax + sbbq 104(%rsp), %rcx + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq 112(%rdi), %rax + movq 120(%rdi), %rcx + sbbq 112(%rsp), %rax + sbbq 120(%rsp), %rcx + movq %rax, 112(%rdi) + movq %rcx, 120(%rdi) + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_dbl_16,.-sp_1024_mont_dbl_16 +#endif /* __APPLE__ */ +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of addition. + * a Number to souble in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_tpl_16 +.type sp_1024_mont_tpl_16,@function +.align 16 +sp_1024_mont_tpl_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_tpl_16 +.p2align 4 +_sp_1024_mont_tpl_16: +#endif /* __APPLE__ */ + subq $0x80, %rsp + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + addq (%rsi), %rax + movq $0x00, %r10 + adcq 8(%rsi), %rcx + adcq 16(%rsi), %r8 + adcq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %rcx + movq 48(%rsi), %r8 + movq 56(%rsi), %r9 + adcq 32(%rsi), %rax + adcq 40(%rsi), %rcx + adcq 48(%rsi), %r8 + adcq 56(%rsi), %r9 + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %rcx + movq 80(%rsi), %r8 + movq 88(%rsi), %r9 + adcq 64(%rsi), %rax + adcq 72(%rsi), %rcx + adcq 80(%rsi), %r8 + adcq 88(%rsi), %r9 + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %rcx + movq 112(%rsi), %r8 + movq 120(%rsi), %r9 + adcq 96(%rsi), %rax + adcq 104(%rsi), %rcx + adcq 112(%rsi), %r8 + adcq 120(%rsi), %r9 + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %r10 + subq 120(%rdx), %r9 + sbbq %r9, %r9 + notq %r9 + orq %r9, %r10 + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rdi), %rax + movq 8(%rdi), %rcx + subq (%rsp), %rax + sbbq 8(%rsp), %rcx + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq 16(%rdi), %rax + movq 24(%rdi), %rcx + sbbq 16(%rsp), %rax + sbbq 24(%rsp), %rcx + movq %rax, 16(%rdi) + movq %rcx, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + sbbq 32(%rsp), %rax + sbbq 40(%rsp), %rcx + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq 48(%rdi), %rax + movq 56(%rdi), %rcx + sbbq 48(%rsp), %rax + sbbq 56(%rsp), %rcx + movq %rax, 48(%rdi) + movq %rcx, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + sbbq 64(%rsp), %rax + sbbq 72(%rsp), %rcx + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq 80(%rdi), %rax + movq 88(%rdi), %rcx + sbbq 80(%rsp), %rax + sbbq 88(%rsp), %rcx + movq %rax, 80(%rdi) + movq %rcx, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + sbbq 96(%rsp), %rax + sbbq 104(%rsp), %rcx + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq 112(%rdi), %rax + movq 120(%rdi), %rcx + sbbq 112(%rsp), %rax + sbbq 120(%rsp), %rcx + movq %rax, 112(%rdi) + movq %rcx, 120(%rdi) + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + addq (%rsi), %rax + movq $0x00, %r10 + adcq 8(%rsi), %rcx + adcq 16(%rsi), %r8 + adcq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 + adcq 32(%rsi), %rax + adcq 40(%rsi), %rcx + adcq 48(%rsi), %r8 + adcq 56(%rsi), %r9 + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + movq 80(%rdi), %r8 + movq 88(%rdi), %r9 + adcq 64(%rsi), %rax + adcq 72(%rsi), %rcx + adcq 80(%rsi), %r8 + adcq 88(%rsi), %r9 + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + movq 112(%rdi), %r8 + movq 120(%rdi), %r9 + adcq 96(%rsi), %rax + adcq 104(%rsi), %rcx + adcq 112(%rsi), %r8 + adcq 120(%rsi), %r9 + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %r10 + subq 120(%rdx), %r9 + sbbq %r9, %r9 + notq %r9 + orq %r9, %r10 + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %r10, %r8 + andq %r10, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rdi), %rax + movq 8(%rdi), %rcx + subq (%rsp), %rax + sbbq 8(%rsp), %rcx + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq 16(%rdi), %rax + movq 24(%rdi), %rcx + sbbq 16(%rsp), %rax + sbbq 24(%rsp), %rcx + movq %rax, 16(%rdi) + movq %rcx, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + sbbq 32(%rsp), %rax + sbbq 40(%rsp), %rcx + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq 48(%rdi), %rax + movq 56(%rdi), %rcx + sbbq 48(%rsp), %rax + sbbq 56(%rsp), %rcx + movq %rax, 48(%rdi) + movq %rcx, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + sbbq 64(%rsp), %rax + sbbq 72(%rsp), %rcx + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq 80(%rdi), %rax + movq 88(%rdi), %rcx + sbbq 80(%rsp), %rax + sbbq 88(%rsp), %rcx + movq %rax, 80(%rdi) + movq %rcx, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + sbbq 96(%rsp), %rax + sbbq 104(%rsp), %rcx + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq 112(%rdi), %rax + movq 120(%rdi), %rcx + sbbq 112(%rsp), %rax + sbbq 120(%rsp), %rcx + movq %rax, 112(%rdi) + movq %rcx, 120(%rdi) + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_tpl_16,.-sp_1024_mont_tpl_16 +#endif /* __APPLE__ */ +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_sub_16 +.type sp_1024_mont_sub_16,@function +.align 16 +sp_1024_mont_sub_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_sub_16 +.p2align 4 +_sp_1024_mont_sub_16: +#endif /* __APPLE__ */ + subq $0x80, %rsp + movq (%rsi), %rax + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + subq (%rdx), %rax + movq $0x00, %r11 + sbbq 8(%rdx), %r8 + sbbq 16(%rdx), %r9 + sbbq 24(%rdx), %r10 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %r8 + movq 48(%rsi), %r9 + movq 56(%rsi), %r10 + sbbq 32(%rdx), %rax + sbbq 40(%rdx), %r8 + sbbq 48(%rdx), %r9 + sbbq 56(%rdx), %r10 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq %r10, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %r8 + movq 80(%rsi), %r9 + movq 88(%rsi), %r10 + sbbq 64(%rdx), %rax + sbbq 72(%rdx), %r8 + sbbq 80(%rdx), %r9 + sbbq 88(%rdx), %r10 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %r8 + movq 112(%rsi), %r9 + movq 120(%rsi), %r10 + sbbq 96(%rdx), %rax + sbbq 104(%rdx), %r8 + sbbq 112(%rdx), %r9 + sbbq 120(%rdx), %r10 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq %r9, 112(%rdi) + movq %r10, 120(%rdi) + sbbq $0x00, %r11 + movq (%rcx), %r9 + movq 8(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq 16(%rcx), %r9 + movq 24(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 16(%rsp) + movq %r10, 24(%rsp) + movq 32(%rcx), %r9 + movq 40(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq 48(%rcx), %r9 + movq 56(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 48(%rsp) + movq %r10, 56(%rsp) + movq 64(%rcx), %r9 + movq 72(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq 80(%rcx), %r9 + movq 88(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 80(%rsp) + movq %r10, 88(%rsp) + movq 96(%rcx), %r9 + movq 104(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 96(%rsp) + movq %r10, 104(%rsp) + movq 112(%rcx), %r9 + movq 120(%rcx), %r10 + andq %r11, %r9 + andq %r11, %r10 + movq %r9, 112(%rsp) + movq %r10, 120(%rsp) + movq (%rdi), %rax + movq 8(%rdi), %r8 + addq (%rsp), %rax + adcq 8(%rsp), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq 16(%rdi), %rax + movq 24(%rdi), %r8 + adcq 16(%rsp), %rax + adcq 24(%rsp), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %r8 + adcq 32(%rsp), %rax + adcq 40(%rsp), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq 48(%rdi), %rax + movq 56(%rdi), %r8 + adcq 48(%rsp), %rax + adcq 56(%rsp), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %r8 + adcq 64(%rsp), %rax + adcq 72(%rsp), %r8 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq 80(%rdi), %rax + movq 88(%rdi), %r8 + adcq 80(%rsp), %rax + adcq 88(%rsp), %r8 + movq %rax, 80(%rdi) + movq %r8, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %r8 + adcq 96(%rsp), %rax + adcq 104(%rsp), %r8 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq 112(%rdi), %rax + movq 120(%rdi), %r8 + adcq 112(%rsp), %rax + adcq 120(%rsp), %r8 + movq %rax, 112(%rdi) + movq %r8, 120(%rdi) + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_sub_16,.-sp_1024_mont_sub_16 +#endif /* __APPLE__ */ +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_div2_16 +.type sp_1024_div2_16,@function +.align 16 +sp_1024_div2_16: +#else +.section __TEXT,__text +.globl _sp_1024_div2_16 +.p2align 4 +_sp_1024_div2_16: +#endif /* __APPLE__ */ + subq $0x80, %rsp + movq (%rsi), %r11 + xorq %r10, %r10 + movq %r11, %rax + andq $0x01, %r11 + negq %r11 + movq (%rdx), %r8 + andq %r11, %r8 + movq %r8, (%rsp) + movq 8(%rdx), %r8 + andq %r11, %r8 + movq %r8, 8(%rsp) + movq 16(%rdx), %r8 + andq %r11, %r8 + movq %r8, 16(%rsp) + movq 24(%rdx), %r8 + andq %r11, %r8 + movq %r8, 24(%rsp) + movq 32(%rdx), %r8 + andq %r11, %r8 + movq %r8, 32(%rsp) + movq 40(%rdx), %r8 + andq %r11, %r8 + movq %r8, 40(%rsp) + movq 48(%rdx), %r8 + andq %r11, %r8 + movq %r8, 48(%rsp) + movq 56(%rdx), %r8 + andq %r11, %r8 + movq %r8, 56(%rsp) + movq 64(%rdx), %r8 + andq %r11, %r8 + movq %r8, 64(%rsp) + movq 72(%rdx), %r8 + andq %r11, %r8 + movq %r8, 72(%rsp) + movq 80(%rdx), %r8 + andq %r11, %r8 + movq %r8, 80(%rsp) + movq 88(%rdx), %r8 + andq %r11, %r8 + movq %r8, 88(%rsp) + movq 96(%rdx), %r8 + andq %r11, %r8 + movq %r8, 96(%rsp) + movq 104(%rdx), %r8 + andq %r11, %r8 + movq %r8, 104(%rsp) + movq 112(%rdx), %r8 + andq %r11, %r8 + movq %r8, 112(%rsp) + movq 120(%rdx), %r8 + andq %r11, %r8 + movq %r8, 120(%rsp) + addq %rax, (%rsp) + movq 8(%rsi), %rax + adcq %rax, 8(%rsp) + movq 16(%rsi), %rax + adcq %rax, 16(%rsp) + movq 24(%rsi), %rax + adcq %rax, 24(%rsp) + movq 32(%rsi), %rax + adcq %rax, 32(%rsp) + movq 40(%rsi), %rax + adcq %rax, 40(%rsp) + movq 48(%rsi), %rax + adcq %rax, 48(%rsp) + movq 56(%rsi), %rax + adcq %rax, 56(%rsp) + movq 64(%rsi), %rax + adcq %rax, 64(%rsp) + movq 72(%rsi), %rax + adcq %rax, 72(%rsp) + movq 80(%rsi), %rax + adcq %rax, 80(%rsp) + movq 88(%rsi), %rax + adcq %rax, 88(%rsp) + movq 96(%rsi), %rax + adcq %rax, 96(%rsp) + movq 104(%rsi), %rax + adcq %rax, 104(%rsp) + movq 112(%rsi), %rax + adcq %rax, 112(%rsp) + movq 120(%rsi), %rax + adcq %rax, 120(%rsp) + adcq $0x00, %r10 + movq (%rsp), %rax + movq 8(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, (%rdi) + movq 16(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 8(%rdi) + movq 24(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 16(%rdi) + movq 32(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 24(%rdi) + movq 40(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 32(%rdi) + movq 48(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 40(%rdi) + movq 56(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 48(%rdi) + movq 64(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 56(%rdi) + movq 72(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 64(%rdi) + movq 80(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 72(%rdi) + movq 88(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 80(%rdi) + movq 96(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 88(%rdi) + movq 104(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 96(%rdi) + movq 112(%rsp), %rax + shrdq $0x01, %rax, %rcx + movq %rcx, 104(%rdi) + movq 120(%rsp), %rcx + shrdq $0x01, %rcx, %rax + movq %rax, 112(%rdi) + shrdq $0x01, %r10, %rcx + movq %rcx, 120(%rdi) + addq $0x80, %rsp + repz retq +#ifndef __APPLE__ +.size sp_1024_div2_16,.-sp_1024_div2_16 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_sub_16 +.type sp_1024_sub_16,@function +.align 16 +sp_1024_sub_16: +#else +.section __TEXT,__text +.globl _sp_1024_sub_16 +.p2align 4 +_sp_1024_sub_16: +#endif /* __APPLE__ */ + movq (%rsi), %rcx + xorq %rax, %rax + subq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + sbbq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + sbbq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + sbbq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + sbbq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + sbbq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + sbbq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + sbbq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + sbbq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + sbbq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + sbbq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + sbbq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + sbbq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + sbbq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + sbbq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + sbbq 120(%rdx), %r8 + movq %r8, 120(%rdi) + sbbq $0x00, %rax + repz retq +#ifndef __APPLE__ +.size sp_1024_sub_16,.-sp_1024_sub_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 1024 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_reduce_avx2_16 +.type sp_1024_mont_reduce_avx2_16,@function +.align 16 +sp_1024_mont_reduce_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_reduce_avx2_16 +.p2align 4 +_sp_1024_mont_reduce_avx2_16: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp + movq %rdx, %r8 + xorq %rbp, %rbp + # i = 16 + movq $16, %r9 + movq (%rdi), %r13 + movq 8(%rdi), %r14 + movq 16(%rdi), %r15 + movq 24(%rdi), %rbx + addq $0x40, %rdi + xorq %rbp, %rbp +L_1024_mont_loop_avx2_16: + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq %r14, %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq %r15, %r14 + adcxq %rax, %r13 + adoxq %rcx, %r14 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -32(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -24(%rdi), %r11 + adcxq %rax, %rbx + adoxq %rcx, %r11 + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -24(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq -8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -16(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq (%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -8(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq 8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, (%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq 16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 8(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq 24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 16(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq 32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 24(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq 40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 32(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq 48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 40(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq 56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq 64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 56(%rdi) + adcxq %rbp, %r10 + movq %r12, %rbp + movq %r10, 64(%rdi) + adoxq %r12, %rbp + adcxq %r12, %rbp + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq %r14, %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq %r15, %r14 + adcxq %rax, %r13 + adoxq %rcx, %r14 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq %rbx, %r15 + adcxq %rax, %r14 + adoxq %rcx, %r15 + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -24(%rdi), %rbx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -16(%rdi), %r11 + adcxq %rax, %rbx + adoxq %rcx, %r11 + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -8(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -16(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq (%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -8(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq 8(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, (%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq 16(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 8(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq 24(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 16(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq 32(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 24(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq 40(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 32(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq 48(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 40(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq 56(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 48(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq 64(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 56(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq 72(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 64(%rdi) + adcxq %rbp, %r10 + movq %r12, %rbp + movq %r10, 72(%rdi) + adoxq %r12, %rbp + adcxq %r12, %rbp + # a += 2 + addq $16, %rdi + # i -= 2 + subq $2, %r9 + jnz L_1024_mont_loop_avx2_16 + subq $0x40, %rdi + subq 120(%rsi), %r10 + movq %rdi, %r8 + sbbq %r10, %r10 + negq %rbp + notq %r10 + orq %r10, %rbp + subq $0x80, %rdi + movq (%rsi), %rcx + movq %r13, %rdx + pextq %rbp, %rcx, %rcx + subq %rcx, %rdx + movq 8(%rsi), %rcx + movq %r14, %rax + pextq %rbp, %rcx, %rcx + movq %rdx, (%rdi) + sbbq %rcx, %rax + movq 16(%rsi), %rdx + movq %r15, %rcx + pextq %rbp, %rdx, %rdx + movq %rax, 8(%rdi) + sbbq %rdx, %rcx + movq 24(%rsi), %rax + movq %rbx, %rdx + pextq %rbp, %rax, %rax + movq %rcx, 16(%rdi) + sbbq %rax, %rdx + movq 32(%rsi), %rcx + movq 32(%r8), %rax + pextq %rbp, %rcx, %rcx + movq %rdx, 24(%rdi) + sbbq %rcx, %rax + movq 40(%rsi), %rdx + movq 40(%r8), %rcx + pextq %rbp, %rdx, %rdx + movq %rax, 32(%rdi) + sbbq %rdx, %rcx + movq 48(%rsi), %rax + movq 48(%r8), %rdx + pextq %rbp, %rax, %rax + movq %rcx, 40(%rdi) + sbbq %rax, %rdx + movq 56(%rsi), %rcx + movq 56(%r8), %rax + pextq %rbp, %rcx, %rcx + movq %rdx, 48(%rdi) + sbbq %rcx, %rax + movq 64(%rsi), %rdx + movq 64(%r8), %rcx + pextq %rbp, %rdx, %rdx + movq %rax, 56(%rdi) + sbbq %rdx, %rcx + movq 72(%rsi), %rax + movq 72(%r8), %rdx + pextq %rbp, %rax, %rax + movq %rcx, 64(%rdi) + sbbq %rax, %rdx + movq 80(%rsi), %rcx + movq 80(%r8), %rax + pextq %rbp, %rcx, %rcx + movq %rdx, 72(%rdi) + sbbq %rcx, %rax + movq 88(%rsi), %rdx + movq 88(%r8), %rcx + pextq %rbp, %rdx, %rdx + movq %rax, 80(%rdi) + sbbq %rdx, %rcx + movq 96(%rsi), %rax + movq 96(%r8), %rdx + pextq %rbp, %rax, %rax + movq %rcx, 88(%rdi) + sbbq %rax, %rdx + movq 104(%rsi), %rcx + movq 104(%r8), %rax + pextq %rbp, %rcx, %rcx + movq %rdx, 96(%rdi) + sbbq %rcx, %rax + movq 112(%rsi), %rdx + movq 112(%r8), %rcx + pextq %rbp, %rdx, %rdx + movq %rax, 104(%rdi) + sbbq %rdx, %rcx + movq 120(%rsi), %rax + movq 120(%r8), %rdx + pextq %rbp, %rax, %rax + movq %rcx, 112(%rdi) + sbbq %rax, %rdx + movq %rdx, 120(%rdi) + popq %rbp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_reduce_avx2_16,.-sp_1024_mont_reduce_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_add_avx2_16 +.type sp_1024_mont_add_avx2_16,@function +.align 16 +sp_1024_mont_add_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_add_avx2_16 +.p2align 4 +_sp_1024_mont_add_avx2_16: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + addq (%rdx), %rax + movq $0x00, %r11 + adcq 8(%rdx), %r8 + adcq 16(%rdx), %r9 + adcq 24(%rdx), %r10 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %r8 + movq 48(%rsi), %r9 + movq 56(%rsi), %r10 + adcq 32(%rdx), %rax + adcq 40(%rdx), %r8 + adcq 48(%rdx), %r9 + adcq 56(%rdx), %r10 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq %r10, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %r8 + movq 80(%rsi), %r9 + movq 88(%rsi), %r10 + adcq 64(%rdx), %rax + adcq 72(%rdx), %r8 + adcq 80(%rdx), %r9 + adcq 88(%rdx), %r10 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %r8 + movq 112(%rsi), %r9 + movq 120(%rsi), %r10 + adcq 96(%rdx), %rax + adcq 104(%rdx), %r8 + adcq 112(%rdx), %r9 + adcq 120(%rdx), %r10 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq %r9, 112(%rdi) + movq %r10, 120(%rdi) + sbbq $0x00, %r11 + subq 120(%rcx), %r10 + sbbq %r10, %r10 + notq %r10 + orq %r10, %r11 + movq (%rcx), %r9 + movq 8(%rcx), %r10 + movq (%rdi), %rax + movq 8(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + subq %r9, %rax + sbbq %r10, %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq 16(%rcx), %r9 + movq 24(%rcx), %r10 + movq 16(%rdi), %rax + movq 24(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movq 32(%rcx), %r9 + movq 40(%rcx), %r10 + movq 32(%rdi), %rax + movq 40(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq 48(%rcx), %r9 + movq 56(%rcx), %r10 + movq 48(%rdi), %rax + movq 56(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + movq 64(%rcx), %r9 + movq 72(%rcx), %r10 + movq 64(%rdi), %rax + movq 72(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq 80(%rcx), %r9 + movq 88(%rcx), %r10 + movq 80(%rdi), %rax + movq 88(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 80(%rdi) + movq %r8, 88(%rdi) + movq 96(%rcx), %r9 + movq 104(%rcx), %r10 + movq 96(%rdi), %rax + movq 104(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq 112(%rcx), %r9 + movq 120(%rcx), %r10 + movq 112(%rdi), %rax + movq 120(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + sbbq %r9, %rax + sbbq %r10, %r8 + movq %rax, 112(%rdi) + movq %r8, 120(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_add_avx2_16,.-sp_1024_mont_add_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of addition. + * a Number to souble in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_dbl_avx2_16 +.type sp_1024_mont_dbl_avx2_16,@function +.align 16 +sp_1024_mont_dbl_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_dbl_avx2_16 +.p2align 4 +_sp_1024_mont_dbl_avx2_16: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + addq (%rsi), %rax + movq $0x00, %r10 + adcq 8(%rsi), %rcx + adcq 16(%rsi), %r8 + adcq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %rcx + movq 48(%rsi), %r8 + movq 56(%rsi), %r9 + adcq 32(%rsi), %rax + adcq 40(%rsi), %rcx + adcq 48(%rsi), %r8 + adcq 56(%rsi), %r9 + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %rcx + movq 80(%rsi), %r8 + movq 88(%rsi), %r9 + adcq 64(%rsi), %rax + adcq 72(%rsi), %rcx + adcq 80(%rsi), %r8 + adcq 88(%rsi), %r9 + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %rcx + movq 112(%rsi), %r8 + movq 120(%rsi), %r9 + adcq 96(%rsi), %rax + adcq 104(%rsi), %rcx + adcq 112(%rsi), %r8 + adcq 120(%rsi), %r9 + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %r10 + subq 120(%rdx), %r9 + sbbq %r9, %r9 + notq %r9 + orq %r9, %r10 + movq (%rdx), %r8 + movq 8(%rdx), %r9 + movq (%rdi), %rax + movq 8(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + subq %r8, %rax + sbbq %r9, %rcx + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + movq 16(%rdi), %rax + movq 24(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 16(%rdi) + movq %rcx, 24(%rdi) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + movq 48(%rdi), %rax + movq 56(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 48(%rdi) + movq %rcx, 56(%rdi) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + movq 80(%rdi), %rax + movq 88(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 80(%rdi) + movq %rcx, 88(%rdi) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + movq 112(%rdi), %rax + movq 120(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 112(%rdi) + movq %rcx, 120(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_dbl_avx2_16,.-sp_1024_mont_dbl_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of addition. + * a Number to souble in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_tpl_avx2_16 +.type sp_1024_mont_tpl_avx2_16,@function +.align 16 +sp_1024_mont_tpl_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_tpl_avx2_16 +.p2align 4 +_sp_1024_mont_tpl_avx2_16: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + addq (%rsi), %rax + movq $0x00, %r10 + adcq 8(%rsi), %rcx + adcq 16(%rsi), %r8 + adcq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %rcx + movq 48(%rsi), %r8 + movq 56(%rsi), %r9 + adcq 32(%rsi), %rax + adcq 40(%rsi), %rcx + adcq 48(%rsi), %r8 + adcq 56(%rsi), %r9 + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %rcx + movq 80(%rsi), %r8 + movq 88(%rsi), %r9 + adcq 64(%rsi), %rax + adcq 72(%rsi), %rcx + adcq 80(%rsi), %r8 + adcq 88(%rsi), %r9 + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %rcx + movq 112(%rsi), %r8 + movq 120(%rsi), %r9 + adcq 96(%rsi), %rax + adcq 104(%rsi), %rcx + adcq 112(%rsi), %r8 + adcq 120(%rsi), %r9 + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %r10 + subq 120(%rdx), %r9 + sbbq %r9, %r9 + notq %r9 + orq %r9, %r10 + movq (%rdx), %r8 + movq 8(%rdx), %r9 + movq (%rdi), %rax + movq 8(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + subq %r8, %rax + sbbq %r9, %rcx + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + movq 16(%rdi), %rax + movq 24(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 16(%rdi) + movq %rcx, 24(%rdi) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + movq 48(%rdi), %rax + movq 56(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 48(%rdi) + movq %rcx, 56(%rdi) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + movq 80(%rdi), %rax + movq 88(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 80(%rdi) + movq %rcx, 88(%rdi) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + movq 112(%rdi), %rax + movq 120(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 112(%rdi) + movq %rcx, 120(%rdi) + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + addq (%rsi), %rax + movq $0x00, %r10 + adcq 8(%rsi), %rcx + adcq 16(%rsi), %r8 + adcq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + movq 48(%rdi), %r8 + movq 56(%rdi), %r9 + adcq 32(%rsi), %rax + adcq 40(%rsi), %rcx + adcq 48(%rsi), %r8 + adcq 56(%rsi), %r9 + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + movq 80(%rdi), %r8 + movq 88(%rdi), %r9 + adcq 64(%rsi), %rax + adcq 72(%rsi), %rcx + adcq 80(%rsi), %r8 + adcq 88(%rsi), %r9 + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + movq 112(%rdi), %r8 + movq 120(%rdi), %r9 + adcq 96(%rsi), %rax + adcq 104(%rsi), %rcx + adcq 112(%rsi), %r8 + adcq 120(%rsi), %r9 + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0x00, %r10 + subq 120(%rdx), %r9 + sbbq %r9, %r9 + notq %r9 + orq %r9, %r10 + movq (%rdx), %r8 + movq 8(%rdx), %r9 + movq (%rdi), %rax + movq 8(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + subq %r8, %rax + sbbq %r9, %rcx + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + movq 16(%rdi), %rax + movq 24(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 16(%rdi) + movq %rcx, 24(%rdi) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + movq 32(%rdi), %rax + movq 40(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 32(%rdi) + movq %rcx, 40(%rdi) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + movq 48(%rdi), %rax + movq 56(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 48(%rdi) + movq %rcx, 56(%rdi) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + movq 64(%rdi), %rax + movq 72(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 64(%rdi) + movq %rcx, 72(%rdi) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + movq 80(%rdi), %rax + movq 88(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 80(%rdi) + movq %rcx, 88(%rdi) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + movq 96(%rdi), %rax + movq 104(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 96(%rdi) + movq %rcx, 104(%rdi) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + movq 112(%rdi), %rax + movq 120(%rdi), %rcx + pextq %r10, %r8, %r8 + pextq %r10, %r9, %r9 + sbbq %r8, %rax + sbbq %r9, %rcx + movq %rax, 112(%rdi) + movq %rcx, 120(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_tpl_avx2_16,.-sp_1024_mont_tpl_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_mont_sub_avx2_16 +.type sp_1024_mont_sub_avx2_16,@function +.align 16 +sp_1024_mont_sub_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_mont_sub_avx2_16 +.p2align 4 +_sp_1024_mont_sub_avx2_16: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + subq (%rdx), %rax + movq $0x00, %r11 + sbbq 8(%rdx), %r8 + sbbq 16(%rdx), %r9 + sbbq 24(%rdx), %r10 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq 32(%rsi), %rax + movq 40(%rsi), %r8 + movq 48(%rsi), %r9 + movq 56(%rsi), %r10 + sbbq 32(%rdx), %rax + sbbq 40(%rdx), %r8 + sbbq 48(%rdx), %r9 + sbbq 56(%rdx), %r10 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq %r9, 48(%rdi) + movq %r10, 56(%rdi) + movq 64(%rsi), %rax + movq 72(%rsi), %r8 + movq 80(%rsi), %r9 + movq 88(%rsi), %r10 + sbbq 64(%rdx), %rax + sbbq 72(%rdx), %r8 + sbbq 80(%rdx), %r9 + sbbq 88(%rdx), %r10 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + movq 96(%rsi), %rax + movq 104(%rsi), %r8 + movq 112(%rsi), %r9 + movq 120(%rsi), %r10 + sbbq 96(%rdx), %rax + sbbq 104(%rdx), %r8 + sbbq 112(%rdx), %r9 + sbbq 120(%rdx), %r10 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq %r9, 112(%rdi) + movq %r10, 120(%rdi) + sbbq $0x00, %r11 + movq (%rcx), %r9 + movq 8(%rcx), %r10 + movq (%rdi), %rax + movq 8(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + addq %r9, %rax + adcq %r10, %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq 16(%rcx), %r9 + movq 24(%rcx), %r10 + movq 16(%rdi), %rax + movq 24(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movq 32(%rcx), %r9 + movq 40(%rcx), %r10 + movq 32(%rdi), %rax + movq 40(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq 48(%rcx), %r9 + movq 56(%rcx), %r10 + movq 48(%rdi), %rax + movq 56(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + movq 64(%rcx), %r9 + movq 72(%rcx), %r10 + movq 64(%rdi), %rax + movq 72(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 64(%rdi) + movq %r8, 72(%rdi) + movq 80(%rcx), %r9 + movq 88(%rcx), %r10 + movq 80(%rdi), %rax + movq 88(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 80(%rdi) + movq %r8, 88(%rdi) + movq 96(%rcx), %r9 + movq 104(%rcx), %r10 + movq 96(%rdi), %rax + movq 104(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 96(%rdi) + movq %r8, 104(%rdi) + movq 112(%rcx), %r9 + movq 120(%rcx), %r10 + movq 112(%rdi), %rax + movq 120(%rdi), %r8 + pextq %r11, %r9, %r9 + pextq %r11, %r10, %r10 + adcq %r9, %rax + adcq %r10, %r8 + movq %rax, 112(%rdi) + movq %r8, 120(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_mont_sub_avx2_16,.-sp_1024_mont_sub_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.text +.globl sp_1024_div2_avx2_16 +.type sp_1024_div2_avx2_16,@function +.align 16 +sp_1024_div2_avx2_16: +#else +.section __TEXT,__text +.globl _sp_1024_div2_avx2_16 +.p2align 4 +_sp_1024_div2_avx2_16: +#endif /* __APPLE__ */ + movq (%rsi), %r11 + xorq %r10, %r10 + movq %r11, %r8 + andq $0x01, %r11 + negq %r11 + movq (%rdx), %rax + movq 8(%rdx), %rcx + movq (%rsi), %r8 + movq 8(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + addq %rax, %r8 + adcq %rcx, %r9 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq 16(%rdx), %rax + movq 24(%rdx), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rdx), %rax + movq 40(%rdx), %rcx + movq 32(%rsi), %r8 + movq 40(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq 48(%rdx), %rax + movq 56(%rdx), %rcx + movq 48(%rsi), %r8 + movq 56(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rdx), %rax + movq 72(%rdx), %rcx + movq 64(%rsi), %r8 + movq 72(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq 80(%rdx), %rax + movq 88(%rdx), %rcx + movq 80(%rsi), %r8 + movq 88(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rdx), %rax + movq 104(%rdx), %rcx + movq 96(%rsi), %r8 + movq 104(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq 112(%rdx), %rax + movq 120(%rdx), %rcx + movq 112(%rsi), %r8 + movq 120(%rsi), %r9 + pextq %r11, %rax, %rax + pextq %r11, %rcx, %rcx + adcq %rax, %r8 + adcq %rcx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + adcq $0x00, %r10 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, (%rdi) + movq 16(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 8(%rdi) + movq 24(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 16(%rdi) + movq 32(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 24(%rdi) + movq 40(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 32(%rdi) + movq 48(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 40(%rdi) + movq 56(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 48(%rdi) + movq 64(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 56(%rdi) + movq 72(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 64(%rdi) + movq 80(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 72(%rdi) + movq 88(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 80(%rdi) + movq 96(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 88(%rdi) + movq 104(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 96(%rdi) + movq 112(%rdi), %r8 + shrdq $0x01, %r8, %r9 + movq %r9, 104(%rdi) + movq 120(%rdi), %r9 + shrdq $0x01, %r9, %r8 + movq %r8, 112(%rdi) + shrdq $0x01, %r10, %r9 + movq %r9, 120(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_1024_div2_avx2_16,.-sp_1024_div2_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Read big endian unsigned byte array into r. + * Uses the bswap instruction. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_from_bin_bswap +.type sp_1024_from_bin_bswap,@function +.align 16 +sp_1024_from_bin_bswap: +#else +.section __TEXT,__text +.globl _sp_1024_from_bin_bswap +.p2align 4 +_sp_1024_from_bin_bswap: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $0x80, %r10 + xorq %r11, %r11 + jmp L_1024_from_bin_bswap_64_end +L_1024_from_bin_bswap_64_start: + subq $0x40, %r9 + movq 56(%r9), %rax + movq 48(%r9), %r8 + bswapq %rax + bswapq %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movq 40(%r9), %rax + movq 32(%r9), %r8 + bswapq %rax + bswapq %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movq 24(%r9), %rax + movq 16(%r9), %r8 + bswapq %rax + bswapq %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movq 8(%r9), %rax + movq (%r9), %r8 + bswapq %rax + bswapq %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $0x40, %rdi + subq $0x40, %rcx +L_1024_from_bin_bswap_64_end: + cmpq $63, %rcx + jg L_1024_from_bin_bswap_64_start + jmp L_1024_from_bin_bswap_8_end +L_1024_from_bin_bswap_8_start: + subq $8, %r9 + movq (%r9), %rax + bswapq %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_1024_from_bin_bswap_8_end: + cmpq $7, %rcx + jg L_1024_from_bin_bswap_8_start + cmpq %r11, %rcx + je L_1024_from_bin_bswap_hi_end + movq %r11, %r8 + movq %r11, %rax +L_1024_from_bin_bswap_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_1024_from_bin_bswap_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_1024_from_bin_bswap_hi_end: + cmpq %r10, %rdi + je L_1024_from_bin_bswap_zero_end +L_1024_from_bin_bswap_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_1024_from_bin_bswap_zero_start +L_1024_from_bin_bswap_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_1024_from_bin_bswap,.-sp_1024_from_bin_bswap +#endif /* __APPLE__ */ +#ifndef NO_MOVBE_SUPPORT +/* Read big endian unsigned byte array into r. + * Uses the movbe instruction which is an optional instruction. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.text +.globl sp_1024_from_bin_movbe +.type sp_1024_from_bin_movbe,@function +.align 16 +sp_1024_from_bin_movbe: +#else +.section __TEXT,__text +.globl _sp_1024_from_bin_movbe +.p2align 4 +_sp_1024_from_bin_movbe: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $0x80, %r10 + xorq %r11, %r11 + jmp L_1024_from_bin_movbe_64_end +L_1024_from_bin_movbe_64_start: + subq $0x40, %r9 + movbeq 56(%r9), %rax + movbeq 48(%r9), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movbeq 40(%r9), %rax + movbeq 32(%r9), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movbeq 24(%r9), %rax + movbeq 16(%r9), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movbeq 8(%r9), %rax + movbeq (%r9), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $0x40, %rdi + subq $0x40, %rcx +L_1024_from_bin_movbe_64_end: + cmpq $63, %rcx + jg L_1024_from_bin_movbe_64_start + jmp L_1024_from_bin_movbe_8_end +L_1024_from_bin_movbe_8_start: + subq $8, %r9 + movbeq (%r9), %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_1024_from_bin_movbe_8_end: + cmpq $7, %rcx + jg L_1024_from_bin_movbe_8_start + cmpq %r11, %rcx + je L_1024_from_bin_movbe_hi_end + movq %r11, %r8 + movq %r11, %rax +L_1024_from_bin_movbe_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_1024_from_bin_movbe_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_1024_from_bin_movbe_hi_end: + cmpq %r10, %rdi + je L_1024_from_bin_movbe_zero_end +L_1024_from_bin_movbe_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_1024_from_bin_movbe_zero_start +L_1024_from_bin_movbe_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_1024_from_bin_movbe,.-sp_1024_from_bin_movbe +#endif /* __APPLE__ */ +#endif /* !NO_MOVBE_SUPPORT */ +#endif /* WOLFSSL_SP_1024 */ +#endif /* WOLFSSL_SP_X86_64_ASM */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/wolfcrypt/src/sp_x86_64_asm.asm b/wolfcrypt/src/sp_x86_64_asm.asm new file mode 100644 index 000000000..76e85c902 --- /dev/null +++ b/wolfcrypt/src/sp_x86_64_asm.asm @@ -0,0 +1,52719 @@ +; /* sp_x86_64_asm +; * +; * Copyright (C) 2006-2021 wolfSSL Inc. +; * +; * This file is part of wolfSSL. +; * +; * wolfSSL is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * wolfSSL is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License +; * along with this program; if not, write to the Free Software +; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +; */ +IF @Version LT 1200 +; AVX2 instructions not recognized by old versions of MASM +IFNDEF NO_AVX2_SUPPORT +NO_AVX2_SUPPORT = 1 +ENDIF +; MOVBE instruction not recognized by old versions of MASM +IFNDEF NO_MOVBE_SUPPORT +NO_MOVBE_SUPPORT = 1 +ENDIF +ENDIF + +IFNDEF HAVE_INTEL_AVX1 +HAVE_INTEL_AVX1 = 1 +ENDIF +IFNDEF NO_AVX2_SUPPORT +HAVE_INTEL_AVX2 = 1 +ENDIF + +IFNDEF _WIN64 +_WIN64 = 1 +ENDIF + +IFNDEF WOLFSSL_SP_NO_2048 +IFNDEF WOLFSSL_SP_NO_2048 +; /* Read big endian unsigned byte array into r. +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_2048_from_bin_bswap PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 256 + xor r13, r13 + jmp L_2048_from_bin_bswap_64_end +L_2048_from_bin_bswap_64_start: + sub r11, 64 + mov rax, QWORD PTR [r11+56] + mov r10, QWORD PTR [r11+48] + bswap rax + bswap r10 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [r11+40] + mov r10, QWORD PTR [r11+32] + bswap rax + bswap r10 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [r11+24] + mov r10, QWORD PTR [r11+16] + bswap rax + bswap r10 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [r11+8] + mov r10, QWORD PTR [r11] + bswap rax + bswap r10 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_2048_from_bin_bswap_64_end: + cmp r9, 63 + jg L_2048_from_bin_bswap_64_start + jmp L_2048_from_bin_bswap_8_end +L_2048_from_bin_bswap_8_start: + sub r11, 8 + mov rax, QWORD PTR [r11] + bswap rax + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_2048_from_bin_bswap_8_end: + cmp r9, 7 + jg L_2048_from_bin_bswap_8_start + cmp r9, r13 + je L_2048_from_bin_bswap_hi_end + mov r10, r13 + mov rax, r13 +L_2048_from_bin_bswap_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_2048_from_bin_bswap_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_2048_from_bin_bswap_hi_end: + cmp rcx, r12 + je L_2048_from_bin_bswap_zero_end +L_2048_from_bin_bswap_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_2048_from_bin_bswap_zero_start +L_2048_from_bin_bswap_zero_end: + pop r13 + pop r12 + ret +sp_2048_from_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Read big endian unsigned byte array into r. +; * Uses the movbe instruction which is an optional instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_2048_from_bin_movbe PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 256 + xor r13, r13 + jmp L_2048_from_bin_movbe_64_end +L_2048_from_bin_movbe_64_start: + sub r11, 64 + movbe rax, QWORD PTR [r11+56] + movbe r10, QWORD PTR [r11+48] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + movbe rax, QWORD PTR [r11+40] + movbe r10, QWORD PTR [r11+32] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + movbe rax, QWORD PTR [r11+24] + movbe r10, QWORD PTR [r11+16] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + movbe rax, QWORD PTR [r11+8] + movbe r10, QWORD PTR [r11] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_2048_from_bin_movbe_64_end: + cmp r9, 63 + jg L_2048_from_bin_movbe_64_start + jmp L_2048_from_bin_movbe_8_end +L_2048_from_bin_movbe_8_start: + sub r11, 8 + movbe rax, QWORD PTR [r11] + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_2048_from_bin_movbe_8_end: + cmp r9, 7 + jg L_2048_from_bin_movbe_8_start + cmp r9, r13 + je L_2048_from_bin_movbe_hi_end + mov r10, r13 + mov rax, r13 +L_2048_from_bin_movbe_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_2048_from_bin_movbe_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_2048_from_bin_movbe_hi_end: + cmp rcx, r12 + je L_2048_from_bin_movbe_zero_end +L_2048_from_bin_movbe_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_2048_from_bin_movbe_zero_start +L_2048_from_bin_movbe_zero_end: + pop r13 + pop r12 + ret +sp_2048_from_bin_movbe ENDP +_text ENDS +ENDIF +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 256 +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_2048_to_bin_bswap PROC + mov rax, QWORD PTR [rcx+248] + mov r8, QWORD PTR [rcx+240] + bswap rax + bswap r8 + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + mov rax, QWORD PTR [rcx+232] + mov r8, QWORD PTR [rcx+224] + bswap rax + bswap r8 + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + mov rax, QWORD PTR [rcx+216] + mov r8, QWORD PTR [rcx+208] + bswap rax + bswap r8 + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + mov rax, QWORD PTR [rcx+200] + mov r8, QWORD PTR [rcx+192] + bswap rax + bswap r8 + mov QWORD PTR [rdx+48], rax + mov QWORD PTR [rdx+56], r8 + mov rax, QWORD PTR [rcx+184] + mov r8, QWORD PTR [rcx+176] + bswap rax + bswap r8 + mov QWORD PTR [rdx+64], rax + mov QWORD PTR [rdx+72], r8 + mov rax, QWORD PTR [rcx+168] + mov r8, QWORD PTR [rcx+160] + bswap rax + bswap r8 + mov QWORD PTR [rdx+80], rax + mov QWORD PTR [rdx+88], r8 + mov rax, QWORD PTR [rcx+152] + mov r8, QWORD PTR [rcx+144] + bswap rax + bswap r8 + mov QWORD PTR [rdx+96], rax + mov QWORD PTR [rdx+104], r8 + mov rax, QWORD PTR [rcx+136] + mov r8, QWORD PTR [rcx+128] + bswap rax + bswap r8 + mov QWORD PTR [rdx+112], rax + mov QWORD PTR [rdx+120], r8 + mov rax, QWORD PTR [rcx+120] + mov r8, QWORD PTR [rcx+112] + bswap rax + bswap r8 + mov QWORD PTR [rdx+128], rax + mov QWORD PTR [rdx+136], r8 + mov rax, QWORD PTR [rcx+104] + mov r8, QWORD PTR [rcx+96] + bswap rax + bswap r8 + mov QWORD PTR [rdx+144], rax + mov QWORD PTR [rdx+152], r8 + mov rax, QWORD PTR [rcx+88] + mov r8, QWORD PTR [rcx+80] + bswap rax + bswap r8 + mov QWORD PTR [rdx+160], rax + mov QWORD PTR [rdx+168], r8 + mov rax, QWORD PTR [rcx+72] + mov r8, QWORD PTR [rcx+64] + bswap rax + bswap r8 + mov QWORD PTR [rdx+176], rax + mov QWORD PTR [rdx+184], r8 + mov rax, QWORD PTR [rcx+56] + mov r8, QWORD PTR [rcx+48] + bswap rax + bswap r8 + mov QWORD PTR [rdx+192], rax + mov QWORD PTR [rdx+200], r8 + mov rax, QWORD PTR [rcx+40] + mov r8, QWORD PTR [rcx+32] + bswap rax + bswap r8 + mov QWORD PTR [rdx+208], rax + mov QWORD PTR [rdx+216], r8 + mov rax, QWORD PTR [rcx+24] + mov r8, QWORD PTR [rcx+16] + bswap rax + bswap r8 + mov QWORD PTR [rdx+224], rax + mov QWORD PTR [rdx+232], r8 + mov rax, QWORD PTR [rcx+8] + mov r8, QWORD PTR [rcx] + bswap rax + bswap r8 + mov QWORD PTR [rdx+240], rax + mov QWORD PTR [rdx+248], r8 + ret +sp_2048_to_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 256 +; * Uses the movbe instruction which is optional. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_2048_to_bin_movbe PROC + movbe rax, QWORD PTR [rcx+248] + movbe r8, QWORD PTR [rcx+240] + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + movbe rax, QWORD PTR [rcx+232] + movbe r8, QWORD PTR [rcx+224] + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + movbe rax, QWORD PTR [rcx+216] + movbe r8, QWORD PTR [rcx+208] + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + movbe rax, QWORD PTR [rcx+200] + movbe r8, QWORD PTR [rcx+192] + mov QWORD PTR [rdx+48], rax + mov QWORD PTR [rdx+56], r8 + movbe rax, QWORD PTR [rcx+184] + movbe r8, QWORD PTR [rcx+176] + mov QWORD PTR [rdx+64], rax + mov QWORD PTR [rdx+72], r8 + movbe rax, QWORD PTR [rcx+168] + movbe r8, QWORD PTR [rcx+160] + mov QWORD PTR [rdx+80], rax + mov QWORD PTR [rdx+88], r8 + movbe rax, QWORD PTR [rcx+152] + movbe r8, QWORD PTR [rcx+144] + mov QWORD PTR [rdx+96], rax + mov QWORD PTR [rdx+104], r8 + movbe rax, QWORD PTR [rcx+136] + movbe r8, QWORD PTR [rcx+128] + mov QWORD PTR [rdx+112], rax + mov QWORD PTR [rdx+120], r8 + movbe rax, QWORD PTR [rcx+120] + movbe r8, QWORD PTR [rcx+112] + mov QWORD PTR [rdx+128], rax + mov QWORD PTR [rdx+136], r8 + movbe rax, QWORD PTR [rcx+104] + movbe r8, QWORD PTR [rcx+96] + mov QWORD PTR [rdx+144], rax + mov QWORD PTR [rdx+152], r8 + movbe rax, QWORD PTR [rcx+88] + movbe r8, QWORD PTR [rcx+80] + mov QWORD PTR [rdx+160], rax + mov QWORD PTR [rdx+168], r8 + movbe rax, QWORD PTR [rcx+72] + movbe r8, QWORD PTR [rcx+64] + mov QWORD PTR [rdx+176], rax + mov QWORD PTR [rdx+184], r8 + movbe rax, QWORD PTR [rcx+56] + movbe r8, QWORD PTR [rcx+48] + mov QWORD PTR [rdx+192], rax + mov QWORD PTR [rdx+200], r8 + movbe rax, QWORD PTR [rcx+40] + movbe r8, QWORD PTR [rcx+32] + mov QWORD PTR [rdx+208], rax + mov QWORD PTR [rdx+216], r8 + movbe rax, QWORD PTR [rcx+24] + movbe r8, QWORD PTR [rcx+16] + mov QWORD PTR [rdx+224], rax + mov QWORD PTR [rdx+232], r8 + movbe rax, QWORD PTR [rcx+8] + movbe r8, QWORD PTR [rcx] + mov QWORD PTR [rdx+240], rax + mov QWORD PTR [rdx+248], r8 + ret +sp_2048_to_bin_movbe ENDP +_text ENDS +ENDIF +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_16 PROC + push r12 + mov r9, rdx + sub rsp, 128 + ; A[0] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9] + xor r12, r12 + mov QWORD PTR [rsp], rax + mov r11, rdx + ; A[0] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+8], r11 + ; A[0] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+16], r12 + ; A[0] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+24], r10 + ; A[0] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+32], r11 + ; A[0] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+40], r12 + ; A[0] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+48], r10 + ; A[0] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+56], r11 + ; A[0] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+64], r12 + ; A[0] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+72], r10 + ; A[0] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+80], r11 + ; A[0] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+88], r12 + ; A[0] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+96], r10 + ; A[0] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+104], r11 + ; A[0] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+112], r12 + ; A[0] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+120], r10 + ; A[1] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+8] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+128], r11 + ; A[2] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+16] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+136], r12 + ; A[3] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+24] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+144], r10 + ; A[4] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+32] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+152], r11 + ; A[5] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+40] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+160], r12 + ; A[6] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+48] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+168], r10 + ; A[7] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+56] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+176], r11 + ; A[8] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+64] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+184], r12 + ; A[9] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+72] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+192], r10 + ; A[10] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+80] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+200], r11 + ; A[11] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+88] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+208], r12 + ; A[12] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+96] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+216], r10 + ; A[13] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+104] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+224], r11 + ; A[14] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+112] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+232], r12 + ; A[15] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+240], r10 + mov QWORD PTR [rcx+248], r11 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r10, QWORD PTR [rsp+16] + mov r11, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov r10, QWORD PTR [rsp+48] + mov r11, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rsp+64] + mov rdx, QWORD PTR [rsp+72] + mov r10, QWORD PTR [rsp+80] + mov r11, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], rdx + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rsp+96] + mov rdx, QWORD PTR [rsp+104] + mov r10, QWORD PTR [rsp+112] + mov r11, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], rdx + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + add rsp, 128 + pop r12 + ret +sp_2048_mul_16 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sqr_16 PROC + push r12 + push r13 + push r14 + mov r8, rdx + sub rsp, 128 + ; A[0] * A[0] + mov rax, QWORD PTR [r8] + mul rax + xor r11, r11 + mov QWORD PTR [rsp], rax + mov r10, rdx + ; A[0] * A[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+8], r10 + ; A[0] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[1] * A[1] + mov rax, QWORD PTR [r8+8] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rsp+16], r11 + ; A[0] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[1] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8+8] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+24], r9 + ; A[0] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[1] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+8] + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[2] * A[2] + mov rax, QWORD PTR [r8+16] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+32], r10 + ; A[0] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+40], r11 + ; A[0] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[3] + mov rax, QWORD PTR [r8+24] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+48], r9 + ; A[0] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+56], r10 + ; A[0] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[4] + mov rax, QWORD PTR [r8+32] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+64], r11 + ; A[0] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+72], r9 + ; A[0] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[5] + mov rax, QWORD PTR [r8+40] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+80], r10 + ; A[0] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+88], r11 + ; A[0] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[6] + mov rax, QWORD PTR [r8+48] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+96], r9 + ; A[0] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+104], r10 + ; A[0] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[7] + mov rax, QWORD PTR [r8+56] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+112], r11 + ; A[0] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+120], r9 + ; A[1] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[2] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[8] + mov rax, QWORD PTR [r8+64] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+128], r10 + ; A[2] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+16] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[3] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+136], r11 + ; A[3] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+24] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[4] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[9] + mov rax, QWORD PTR [r8+72] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+144], r9 + ; A[4] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+32] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[5] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+152], r10 + ; A[5] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+40] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[6] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[10] + mov rax, QWORD PTR [r8+80] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+160], r11 + ; A[6] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+48] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[7] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+168], r9 + ; A[7] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+56] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[8] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[11] * A[11] + mov rax, QWORD PTR [r8+88] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+176], r10 + ; A[8] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+64] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[9] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[11] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+88] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+184], r11 + ; A[9] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+72] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[10] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[11] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+88] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[12] * A[12] + mov rax, QWORD PTR [r8+96] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+192], r9 + ; A[10] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+80] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[11] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+88] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[12] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+96] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+200], r10 + ; A[11] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+88] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[12] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+96] + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[13] * A[13] + mov rax, QWORD PTR [r8+104] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+208], r11 + ; A[12] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+96] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[13] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+104] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+216], r9 + ; A[13] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+104] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[14] * A[14] + mov rax, QWORD PTR [r8+112] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rcx+224], r10 + ; A[14] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+112] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+232], r11 + ; A[15] * A[15] + mov rax, QWORD PTR [r8+120] + mul rax + add r9, rax + adc r10, rdx + mov QWORD PTR [rcx+240], r9 + mov QWORD PTR [rcx+248], r10 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r12, QWORD PTR [rsp+16] + mov r13, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov r12, QWORD PTR [rsp+48] + mov r13, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + mov QWORD PTR [rcx+48], r12 + mov QWORD PTR [rcx+56], r13 + mov rax, QWORD PTR [rsp+64] + mov rdx, QWORD PTR [rsp+72] + mov r12, QWORD PTR [rsp+80] + mov r13, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], rdx + mov QWORD PTR [rcx+80], r12 + mov QWORD PTR [rcx+88], r13 + mov rax, QWORD PTR [rsp+96] + mov rdx, QWORD PTR [rsp+104] + mov r12, QWORD PTR [rsp+112] + mov r13, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], rdx + mov QWORD PTR [rcx+112], r12 + mov QWORD PTR [rcx+120], r13 + add rsp, 128 + pop r14 + pop r13 + pop r12 + ret +sp_2048_sqr_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r Result of multiplication. +; * a First number to multiply. +; * b Second number to multiply. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_avx2_16 PROC + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + push rdi + mov rbp, r8 + mov r8, rcx + mov r9, rdx + sub rsp, 128 + cmp r9, r8 + mov rbx, rsp + cmovne rbx, r8 + cmp rbp, r8 + cmove rbx, rsp + add r8, 128 + xor rdi, rdi + mov rdx, QWORD PTR [r9] + ; A[0] * B[0] + mulx r11, r10, QWORD PTR [rbp] + ; A[0] * B[1] + mulx r12, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx], r10 + adcx r11, rax + ; A[0] * B[2] + mulx r13, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+8], r11 + adcx r12, rax + ; A[0] * B[3] + mulx r14, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+16], r12 + adcx r13, rax + mov QWORD PTR [rbx+24], r13 + ; A[0] * B[4] + mulx r10, rax, QWORD PTR [rbp+32] + adcx r14, rax + ; A[0] * B[5] + mulx r11, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + ; A[0] * B[6] + mulx r12, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + ; A[0] * B[7] + mulx r13, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + mov QWORD PTR [rbx+56], r12 + ; A[0] * B[8] + mulx r14, rax, QWORD PTR [rbp+64] + adcx r13, rax + ; A[0] * B[9] + mulx r10, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + ; A[0] * B[10] + mulx r11, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + ; A[0] * B[11] + mulx r12, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + mov QWORD PTR [rbx+88], r11 + ; A[0] * B[12] + mulx r13, rax, QWORD PTR [rbp+96] + adcx r12, rax + ; A[0] * B[13] + mulx r14, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + ; A[0] * B[14] + mulx r10, rax, QWORD PTR [rbp+112] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + ; A[0] * B[15] + mulx r11, rax, QWORD PTR [rbp+120] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adcx r11, rdi + mov r15, rdi + adcx r15, rdi + mov QWORD PTR [rbx+120], r10 + mov QWORD PTR [r8], r11 + mov rdx, QWORD PTR [r9+8] + mov r11, QWORD PTR [rbx+8] + mov r12, QWORD PTR [rbx+16] + mov r13, QWORD PTR [rbx+24] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + ; A[1] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[1] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+8], r11 + adcx r12, rax + adox r13, rcx + ; A[1] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+16], r12 + adcx r13, rax + adox r14, rcx + ; A[1] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+24], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+32], r14 + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + ; A[1] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[1] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + ; A[1] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[1] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+64], r13 + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + ; A[1] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r14, rax + adox r10, rcx + ; A[1] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[1] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[1] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+96], r12 + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[1] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r13, rax + adox r14, rcx + ; A[1] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[1] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[1] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [rbx+120], r10 + mov r12, rdi + adcx r11, rax + adox r12, rcx + adcx r12, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8], r11 + mov QWORD PTR [r8+8], r12 + mov rdx, QWORD PTR [r9+16] + mov r12, QWORD PTR [rbx+16] + mov r13, QWORD PTR [rbx+24] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + ; A[2] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r13, rcx + ; A[2] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+16], r12 + adcx r13, rax + adox r14, rcx + ; A[2] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+24], r13 + adcx r14, rax + adox r10, rcx + ; A[2] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+40], r10 + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + ; A[2] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[2] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[2] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[2] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+72], r14 + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + ; A[2] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[2] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[2] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[2] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+104], r13 + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[2] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r14, rax + adox r10, rcx + ; A[2] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[2] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[2] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8], r11 + mov r13, rdi + adcx r12, rax + adox r13, rcx + adcx r13, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+8], r12 + mov QWORD PTR [r8+16], r13 + mov rdx, QWORD PTR [r9+24] + mov r13, QWORD PTR [rbx+24] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + ; A[3] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r13, rax + adox r14, rcx + ; A[3] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+24], r13 + adcx r14, rax + adox r10, rcx + ; A[3] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + adox r11, rcx + ; A[3] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+48], r11 + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + ; A[3] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r13, rcx + ; A[3] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[3] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[3] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+80], r10 + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + ; A[3] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[3] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[3] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[3] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+112], r14 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[3] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r10, rax + adox r11, rcx + ; A[3] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[3] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[3] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+8], r12 + mov r14, rdi + adcx r13, rax + adox r14, rcx + adcx r14, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+16], r13 + mov QWORD PTR [r8+24], r14 + mov rdx, QWORD PTR [r9+32] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + ; A[4] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r14, rax + adox r10, rcx + ; A[4] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + adox r11, rcx + ; A[4] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + ; A[4] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+56], r12 + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + ; A[4] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r13, rax + adox r14, rcx + ; A[4] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[4] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[4] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+88], r11 + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[4] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r13, rcx + ; A[4] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[4] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[4] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+120], r10 + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[4] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r11, rax + adox r12, rcx + ; A[4] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[4] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[4] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+16], r13 + mov r10, rdi + adcx r14, rax + adox r10, rcx + adcx r10, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+24], r14 + mov QWORD PTR [r8+32], r10 + mov rdx, QWORD PTR [r9+40] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + ; A[5] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[5] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + ; A[5] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[5] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+64], r13 + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + ; A[5] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r14, rax + adox r10, rcx + ; A[5] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[5] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[5] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+96], r12 + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[5] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r13, rax + adox r14, rcx + ; A[5] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[5] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[5] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8], r11 + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + ; A[5] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r12, rax + adox r13, rcx + ; A[5] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[5] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[5] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+24], r14 + mov r11, rdi + adcx r10, rax + adox r11, rcx + adcx r11, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+32], r10 + mov QWORD PTR [r8+40], r11 + mov rdx, QWORD PTR [r9+48] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + ; A[6] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[6] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[6] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[6] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+72], r14 + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + ; A[6] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[6] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[6] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[6] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+104], r13 + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[6] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r14, rax + adox r10, rcx + ; A[6] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[6] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[6] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+8], r12 + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[6] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r13, rax + adox r14, rcx + ; A[6] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[6] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[6] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+32], r10 + mov r12, rdi + adcx r11, rax + adox r12, rcx + adcx r12, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+40], r11 + mov QWORD PTR [r8+48], r12 + mov rdx, QWORD PTR [r9+56] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + ; A[7] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r13, rcx + ; A[7] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[7] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[7] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+80], r10 + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + ; A[7] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[7] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[7] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[7] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+112], r14 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[7] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[7] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[7] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[7] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+16], r13 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + ; A[7] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r14, rax + adox r10, rcx + ; A[7] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[7] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[7] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+40], r11 + mov r13, rdi + adcx r12, rax + adox r13, rcx + adcx r13, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+48], r12 + mov QWORD PTR [r8+56], r13 + mov rdx, QWORD PTR [r9+64] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + ; A[8] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r13, rax + adox r14, rcx + ; A[8] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[8] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[8] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+88], r11 + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[8] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r13, rcx + ; A[8] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[8] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[8] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+120], r10 + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + ; A[8] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[8] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[8] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[8] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [r8+24], r14 + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + ; A[8] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r10, rax + adox r11, rcx + ; A[8] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[8] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[8] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+48], r12 + mov r14, rdi + adcx r13, rax + adox r14, rcx + adcx r14, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+56], r13 + mov QWORD PTR [r8+64], r14 + mov rdx, QWORD PTR [r9+72] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + ; A[9] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r14, rax + adox r10, rcx + ; A[9] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[9] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[9] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+96], r12 + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[9] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r13, rax + adox r14, rcx + ; A[9] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[9] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[9] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8], r11 + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[9] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r13, rcx + ; A[9] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[9] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[9] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+32], r10 + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + ; A[9] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r11, rax + adox r12, rcx + ; A[9] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[9] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[9] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+56], r13 + mov r10, rdi + adcx r14, rax + adox r10, rcx + adcx r10, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+64], r14 + mov QWORD PTR [r8+72], r10 + mov rdx, QWORD PTR [r9+80] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + ; A[10] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[10] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[10] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[10] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+104], r13 + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[10] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r14, rax + adox r10, rcx + ; A[10] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[10] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[10] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+8], r12 + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + ; A[10] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r13, rax + adox r14, rcx + ; A[10] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[10] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[10] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r11 + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[10] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r12, rax + adox r13, rcx + ; A[10] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[10] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[10] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+64], r14 + mov r11, rdi + adcx r10, rax + adox r11, rcx + adcx r11, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+72], r10 + mov QWORD PTR [r8+80], r11 + mov rdx, QWORD PTR [r9+88] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + ; A[11] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[11] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[11] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[11] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+112], r14 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[11] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[11] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[11] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[11] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+16], r13 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + ; A[11] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r14, rax + adox r10, rcx + ; A[11] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[11] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[11] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+48], r12 + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + ; A[11] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r13, rax + adox r14, rcx + ; A[11] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[11] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + ; A[11] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+72], r10 + mov r12, rdi + adcx r11, rax + adox r12, rcx + adcx r12, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+80], r11 + mov QWORD PTR [r8+88], r12 + mov rdx, QWORD PTR [r9+96] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[12] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r13, rcx + ; A[12] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[12] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[12] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+120], r10 + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + ; A[12] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[12] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[12] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[12] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [r8+24], r14 + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + ; A[12] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[12] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[12] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[12] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+56], r13 + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + mov r12, QWORD PTR [r8+88] + ; A[12] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r14, rax + adox r10, rcx + ; A[12] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + ; A[12] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+72], r10 + adcx r11, rax + adox r12, rcx + ; A[12] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+80], r11 + mov r13, rdi + adcx r12, rax + adox r13, rcx + adcx r13, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+88], r12 + mov QWORD PTR [r8+96], r13 + mov rdx, QWORD PTR [r9+104] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[13] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r13, rax + adox r14, rcx + ; A[13] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[13] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[13] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8], r11 + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[13] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r13, rcx + ; A[13] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[13] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[13] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+32], r10 + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[13] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[13] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[13] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[13] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [r8+64], r14 + mov r11, QWORD PTR [r8+80] + mov r12, QWORD PTR [r8+88] + mov r13, QWORD PTR [r8+96] + ; A[13] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r10, rax + adox r11, rcx + ; A[13] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+72], r10 + adcx r11, rax + adox r12, rcx + ; A[13] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+80], r11 + adcx r12, rax + adox r13, rcx + ; A[13] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+88], r12 + mov r14, rdi + adcx r13, rax + adox r14, rcx + adcx r14, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+96], r13 + mov QWORD PTR [r8+104], r14 + mov rdx, QWORD PTR [r9+112] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[14] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r14, rax + adox r10, rcx + ; A[14] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[14] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[14] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+8], r12 + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + ; A[14] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r13, rax + adox r14, rcx + ; A[14] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[14] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[14] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r11 + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + ; A[14] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r13, rcx + ; A[14] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[14] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[14] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+72], r10 + mov r12, QWORD PTR [r8+88] + mov r13, QWORD PTR [r8+96] + mov r14, QWORD PTR [r8+104] + ; A[14] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r11, rax + adox r12, rcx + ; A[14] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+80], r11 + adcx r12, rax + adox r13, rcx + ; A[14] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+88], r12 + adcx r13, rax + adox r14, rcx + ; A[14] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+96], r13 + mov r10, rdi + adcx r14, rax + adox r10, rcx + adcx r10, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+104], r14 + mov QWORD PTR [r8+112], r10 + mov rdx, QWORD PTR [r9+120] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[15] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[15] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[15] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[15] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+16], r13 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + ; A[15] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r14, rax + adox r10, rcx + ; A[15] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[15] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[15] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+48], r12 + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + mov r12, QWORD PTR [r8+88] + ; A[15] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r13, rax + adox r14, rcx + ; A[15] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[15] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + ; A[15] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+80], r11 + mov r13, QWORD PTR [r8+96] + mov r14, QWORD PTR [r8+104] + mov r10, QWORD PTR [r8+112] + ; A[15] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r12, rax + adox r13, rcx + ; A[15] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+88], r12 + adcx r13, rax + adox r14, rcx + ; A[15] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+96], r13 + adcx r14, rax + adox r10, rcx + ; A[15] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+104], r14 + mov r11, rdi + adcx r10, rax + adox r11, rcx + adcx r11, r15 + mov QWORD PTR [r8+112], r10 + mov QWORD PTR [r8+120], r11 + sub r8, 128 + cmp r9, r8 + je L_start_2048_mul_avx2_16 + cmp rbp, r8 + jne L_end_2048_mul_avx2_16 +L_start_2048_mul_avx2_16: + vmovdqu xmm0, OWORD PTR [rbx] + vmovups OWORD PTR [r8], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+16] + vmovups OWORD PTR [r8+16], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+32] + vmovups OWORD PTR [r8+32], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+48] + vmovups OWORD PTR [r8+48], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+64] + vmovups OWORD PTR [r8+64], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+80] + vmovups OWORD PTR [r8+80], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+96] + vmovups OWORD PTR [r8+96], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+112] + vmovups OWORD PTR [r8+112], xmm0 +L_end_2048_mul_avx2_16: + add rsp, 128 + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + ret +sp_2048_mul_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sqr_avx2_16 PROC + push rbp + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov r8, rcx + mov r9, rdx + sub rsp, 128 + cmp r9, r8 + mov rbp, rsp + cmovne rbp, r8 + add r8, 128 + xor r13, r13 + ; Diagonal 1 + xor r12, r12 + ; A[1] x A[0] + mov rdx, QWORD PTR [r9] + mulx r11, r10, QWORD PTR [r9+8] + ; A[2] x A[0] + mulx rcx, rax, QWORD PTR [r9+16] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+8], r10 + mov QWORD PTR [rbp+16], r11 + mov r10, r13 + mov r11, r13 + ; A[3] x A[0] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r12, rax + adox r10, rcx + ; A[4] x A[0] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+24], r12 + mov QWORD PTR [rbp+32], r10 + mov r12, r13 + mov r10, r13 + ; A[5] x A[0] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r11, rax + adox r12, rcx + ; A[6] x A[0] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+40], r11 + mov QWORD PTR [rbp+48], r12 + mov r11, r13 + mov r12, r13 + ; A[7] x A[0] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + ; A[8] x A[0] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+56], r10 + mov QWORD PTR [rbp+64], r11 + mov r10, r13 + mov r11, r13 + ; A[9] x A[0] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r12, rax + adox r10, rcx + ; A[10] x A[0] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+72], r12 + mov QWORD PTR [rbp+80], r10 + mov r12, r13 + mov r10, r13 + ; A[11] x A[0] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r11, rax + adox r12, rcx + ; A[12] x A[0] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+88], r11 + mov r15, r12 + mov r11, r13 + mov r12, r13 + ; A[13] x A[0] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r10, rax + adox r11, rcx + ; A[14] x A[0] + mulx rcx, rax, QWORD PTR [r9+112] + adcx r11, rax + adox r12, rcx + mov rdi, r10 + mov rsi, r11 + mov r10, r13 + ; A[15] x A[0] + mulx rcx, rax, QWORD PTR [r9+120] + adcx r12, rax + adox r10, rcx + mov rbx, r12 + ; Carry + adcx r10, r13 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8], r10 + ; Diagonal 2 + mov r10, QWORD PTR [rbp+24] + mov r11, QWORD PTR [rbp+32] + mov r12, QWORD PTR [rbp+40] + ; A[2] x A[1] + mov rdx, QWORD PTR [r9+8] + mulx rcx, rax, QWORD PTR [r9+16] + adcx r10, rax + adox r11, rcx + ; A[3] x A[1] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+24], r10 + mov QWORD PTR [rbp+32], r11 + mov r10, QWORD PTR [rbp+48] + mov r11, QWORD PTR [rbp+56] + ; A[4] x A[1] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r12, rax + adox r10, rcx + ; A[5] x A[1] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+40], r12 + mov QWORD PTR [rbp+48], r10 + mov r12, QWORD PTR [rbp+64] + mov r10, QWORD PTR [rbp+72] + ; A[6] x A[1] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r12, rcx + ; A[7] x A[1] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+56], r11 + mov QWORD PTR [rbp+64], r12 + mov r11, QWORD PTR [rbp+80] + mov r12, QWORD PTR [rbp+88] + ; A[8] x A[1] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r10, rax + adox r11, rcx + ; A[9] x A[1] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+72], r10 + mov QWORD PTR [rbp+80], r11 + ; No load %r13 - %r8 + ; No load %r14 - %r9 + ; A[10] x A[1] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r12, rax + adox r15, rcx + ; A[11] x A[1] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r12 + ; No store %r13 + ; No load %r15 - %r10 + ; No load %rbx - %r8 + ; A[12] x A[1] + mulx rcx, rax, QWORD PTR [r9+96] + adcx rdi, rax + adox rsi, rcx + ; A[13] x A[1] + mulx rcx, rax, QWORD PTR [r9+104] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r11, QWORD PTR [r8] + mov r12, r13 + ; A[14] x A[1] + mulx rcx, rax, QWORD PTR [r9+112] + adcx rbx, rax + adox r11, rcx + ; A[15] x A[1] + mulx rcx, rax, QWORD PTR [r9+120] + adcx r11, rax + adox r12, rcx + ; No store %rbx + mov QWORD PTR [r8], r11 + mov r10, r13 + ; A[15] x A[2] + mov rdx, QWORD PTR [r9+16] + mulx rcx, rax, QWORD PTR [r9+120] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+8], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+16], r10 + ; Diagonal 3 + mov r10, QWORD PTR [rbp+40] + mov r11, QWORD PTR [rbp+48] + mov r12, QWORD PTR [rbp+56] + ; A[3] x A[2] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + ; A[4] x A[2] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+40], r10 + mov QWORD PTR [rbp+48], r11 + mov r10, QWORD PTR [rbp+64] + mov r11, QWORD PTR [rbp+72] + ; A[5] x A[2] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + ; A[6] x A[2] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+56], r12 + mov QWORD PTR [rbp+64], r10 + mov r12, QWORD PTR [rbp+80] + mov r10, QWORD PTR [rbp+88] + ; A[7] x A[2] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + ; A[8] x A[2] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+72], r11 + mov QWORD PTR [rbp+80], r12 + ; No load %r13 - %r9 + ; No load %r14 - %r10 + ; A[9] x A[2] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r15, rcx + ; A[10] x A[2] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r10 + ; No store %r13 + ; No load %r15 - %r8 + ; No load %rbx - %r9 + ; A[11] x A[2] + mulx rcx, rax, QWORD PTR [r9+88] + adcx rdi, rax + adox rsi, rcx + ; A[12] x A[2] + mulx rcx, rax, QWORD PTR [r9+96] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [r8+8] + ; A[13] x A[2] + mulx rcx, rax, QWORD PTR [r9+104] + adcx rbx, rax + adox r12, rcx + ; A[14] x A[2] + mulx rcx, rax, QWORD PTR [r9+112] + adcx r12, rax + adox r10, rcx + ; No store %rbx + mov QWORD PTR [r8], r12 + mov r11, QWORD PTR [r8+16] + mov r12, r13 + ; A[14] x A[3] + mov rdx, QWORD PTR [r9+112] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + ; A[14] x A[4] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r10 + mov QWORD PTR [r8+16], r11 + mov r10, r13 + ; A[14] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+24], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+32], r10 + ; Diagonal 4 + mov r10, QWORD PTR [rbp+56] + mov r11, QWORD PTR [rbp+64] + mov r12, QWORD PTR [rbp+72] + ; A[4] x A[3] + mov rdx, QWORD PTR [r9+24] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r10, rax + adox r11, rcx + ; A[5] x A[3] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+56], r10 + mov QWORD PTR [rbp+64], r11 + mov r10, QWORD PTR [rbp+80] + mov r11, QWORD PTR [rbp+88] + ; A[6] x A[3] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r12, rax + adox r10, rcx + ; A[7] x A[3] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+72], r12 + mov QWORD PTR [rbp+80], r10 + ; No load %r13 - %r10 + ; No load %r14 - %r8 + ; A[8] x A[3] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r15, rcx + ; A[9] x A[3] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r11 + ; No store %r13 + ; No load %r15 - %r9 + ; No load %rbx - %r10 + ; A[10] x A[3] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rdi, rax + adox rsi, rcx + ; A[11] x A[3] + mulx rcx, rax, QWORD PTR [r9+88] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[12] x A[3] + mulx rcx, rax, QWORD PTR [r9+96] + adcx rbx, rax + adox r10, rcx + ; A[13] x A[3] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r10, rax + adox r11, rcx + ; No store %rbx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[13] x A[4] + mov rdx, QWORD PTR [r9+104] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + ; A[13] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, r13 + ; A[13] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + ; A[13] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+24], r10 + mov QWORD PTR [r8+32], r11 + mov r10, r13 + ; A[13] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+40], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+48], r10 + ; Diagonal 5 + mov r10, QWORD PTR [rbp+72] + mov r11, QWORD PTR [rbp+80] + mov r12, QWORD PTR [rbp+88] + ; A[5] x A[4] + mov rdx, QWORD PTR [r9+32] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + ; A[6] x A[4] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+72], r10 + mov QWORD PTR [rbp+80], r11 + ; No load %r13 - %r8 + ; No load %r14 - %r9 + ; A[7] x A[4] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r12, rax + adox r15, rcx + ; A[8] x A[4] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r12 + ; No store %r13 + ; No load %r15 - %r10 + ; No load %rbx - %r8 + ; A[9] x A[4] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rdi, rax + adox rsi, rcx + ; A[10] x A[4] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[11] x A[4] + mulx rcx, rax, QWORD PTR [r9+88] + adcx rbx, rax + adox r11, rcx + ; A[12] x A[4] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r11, rax + adox r12, rcx + ; No store %rbx + mov QWORD PTR [r8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[12] x A[5] + mov rdx, QWORD PTR [r9+96] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + ; A[12] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+8], r12 + mov QWORD PTR [r8+16], r10 + mov r12, QWORD PTR [r8+32] + mov r10, QWORD PTR [r8+40] + ; A[12] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + ; A[12] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+24], r11 + mov QWORD PTR [r8+32], r12 + mov r11, QWORD PTR [r8+48] + mov r12, r13 + ; A[12] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + ; A[12] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r10 + mov QWORD PTR [r8+48], r11 + mov r10, r13 + ; A[12] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+56], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+64], r10 + ; Diagonal 6 + mov r10, QWORD PTR [rbp+88] + ; No load %r13 - %r9 + ; No load %r14 - %r10 + ; A[6] x A[5] + mov rdx, QWORD PTR [r9+40] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r15, rcx + ; A[7] x A[5] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r10 + ; No store %r13 + ; No load %r15 - %r8 + ; No load %rbx - %r9 + ; A[8] x A[5] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rdi, rax + adox rsi, rcx + ; A[9] x A[5] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [r8+8] + ; A[10] x A[5] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rbx, rax + adox r12, rcx + ; A[11] x A[5] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r12, rax + adox r10, rcx + ; No store %rbx + mov QWORD PTR [r8], r12 + mov r11, QWORD PTR [r8+16] + mov r12, QWORD PTR [r8+24] + ; A[11] x A[6] + mov rdx, QWORD PTR [r9+88] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + ; A[11] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r10 + mov QWORD PTR [r8+16], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[11] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + ; A[11] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r12 + mov QWORD PTR [r8+32], r10 + mov r12, QWORD PTR [r8+48] + mov r10, QWORD PTR [r8+56] + ; A[11] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r12, rcx + ; A[13] x A[9] + mov rdx, QWORD PTR [r9+104] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+40], r11 + mov QWORD PTR [r8+48], r12 + mov r11, QWORD PTR [r8+64] + mov r12, r13 + ; A[13] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r10, rax + adox r11, rcx + ; A[13] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+56], r10 + mov QWORD PTR [r8+64], r11 + mov r10, r13 + ; A[13] x A[12] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+72], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+80], r10 + ; Diagonal 7 + ; No load %r14 - %r8 + ; No load %r15 - %r9 + ; No load %rbx - %r10 + ; A[7] x A[6] + mov rdx, QWORD PTR [r9+48] + mulx rcx, rax, QWORD PTR [r9+56] + adcx rdi, rax + adox rsi, rcx + ; A[8] x A[6] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[9] x A[6] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rbx, rax + adox r10, rcx + ; A[10] x A[6] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r10, rax + adox r11, rcx + ; No store %rbx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[10] x A[7] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + ; A[10] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, QWORD PTR [r8+40] + ; A[10] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + ; A[14] x A[6] + mov rdx, QWORD PTR [r9+112] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+24], r10 + mov QWORD PTR [r8+32], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[14] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r12, rax + adox r10, rcx + ; A[14] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+40], r12 + mov QWORD PTR [r8+48], r10 + mov r12, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[14] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r11, rax + adox r12, rcx + ; A[14] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+56], r11 + mov QWORD PTR [r8+64], r12 + mov r11, QWORD PTR [r8+80] + mov r12, r13 + ; A[14] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r10, rax + adox r11, rcx + ; A[14] x A[12] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+72], r10 + mov QWORD PTR [r8+80], r11 + mov r10, r13 + ; A[14] x A[13] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+88], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+96], r10 + ; Diagonal 8 + ; No load %rbx - %r8 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[8] x A[7] + mov rdx, QWORD PTR [r9+56] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rbx, rax + adox r11, rcx + ; A[9] x A[7] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r11, rax + adox r12, rcx + ; No store %rbx + mov QWORD PTR [r8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[9] x A[8] + mov rdx, QWORD PTR [r9+64] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r12, rax + adox r10, rcx + ; A[15] x A[3] + mov rdx, QWORD PTR [r9+120] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+8], r12 + mov QWORD PTR [r8+16], r10 + mov r12, QWORD PTR [r8+32] + mov r10, QWORD PTR [r8+40] + ; A[15] x A[4] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + ; A[15] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+24], r11 + mov QWORD PTR [r8+32], r12 + mov r11, QWORD PTR [r8+48] + mov r12, QWORD PTR [r8+56] + ; A[15] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + ; A[15] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r10 + mov QWORD PTR [r8+48], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + ; A[15] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + ; A[15] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+56], r12 + mov QWORD PTR [r8+64], r10 + mov r12, QWORD PTR [r8+80] + mov r10, QWORD PTR [r8+88] + ; A[15] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r12, rcx + ; A[15] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+72], r11 + mov QWORD PTR [r8+80], r12 + mov r11, QWORD PTR [r8+96] + mov r12, r13 + ; A[15] x A[12] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r10, rax + adox r11, rcx + ; A[15] x A[13] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+88], r10 + mov QWORD PTR [r8+96], r11 + mov r10, r13 + ; A[15] x A[14] + mulx rcx, rax, QWORD PTR [r9+112] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+104], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+112], r10 + mov QWORD PTR [r8+120], r14 + ; Double and Add in A[i] x A[i] + mov r11, QWORD PTR [rbp+8] + ; A[0] x A[0] + mov rdx, QWORD PTR [r9] + mulx rcx, rax, rdx + mov QWORD PTR [rbp], rax + adox r11, r11 + adcx r11, rcx + mov QWORD PTR [rbp+8], r11 + mov r10, QWORD PTR [rbp+16] + mov r11, QWORD PTR [rbp+24] + ; A[1] x A[1] + mov rdx, QWORD PTR [r9+8] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+16], r10 + mov QWORD PTR [rbp+24], r11 + mov r10, QWORD PTR [rbp+32] + mov r11, QWORD PTR [rbp+40] + ; A[2] x A[2] + mov rdx, QWORD PTR [r9+16] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+32], r10 + mov QWORD PTR [rbp+40], r11 + mov r10, QWORD PTR [rbp+48] + mov r11, QWORD PTR [rbp+56] + ; A[3] x A[3] + mov rdx, QWORD PTR [r9+24] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+48], r10 + mov QWORD PTR [rbp+56], r11 + mov r10, QWORD PTR [rbp+64] + mov r11, QWORD PTR [rbp+72] + ; A[4] x A[4] + mov rdx, QWORD PTR [r9+32] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+64], r10 + mov QWORD PTR [rbp+72], r11 + mov r10, QWORD PTR [rbp+80] + mov r11, QWORD PTR [rbp+88] + ; A[5] x A[5] + mov rdx, QWORD PTR [r9+40] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+80], r10 + mov QWORD PTR [rbp+88], r11 + ; A[6] x A[6] + mov rdx, QWORD PTR [r9+48] + mulx rcx, rax, rdx + adox r15, r15 + adox rdi, rdi + adcx r15, rax + adcx rdi, rcx + ; A[7] x A[7] + mov rdx, QWORD PTR [r9+56] + mulx rcx, rax, rdx + adox rsi, rsi + adox rbx, rbx + adcx rsi, rax + adcx rbx, rcx + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[8] x A[8] + mov rdx, QWORD PTR [r9+64] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8], r10 + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[9] x A[9] + mov rdx, QWORD PTR [r9+72] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+16], r10 + mov QWORD PTR [r8+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[10] x A[10] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+32], r10 + mov QWORD PTR [r8+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[11] x A[11] + mov rdx, QWORD PTR [r9+88] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+48], r10 + mov QWORD PTR [r8+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + ; A[12] x A[12] + mov rdx, QWORD PTR [r9+96] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+64], r10 + mov QWORD PTR [r8+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + ; A[13] x A[13] + mov rdx, QWORD PTR [r9+104] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+80], r10 + mov QWORD PTR [r8+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + ; A[14] x A[14] + mov rdx, QWORD PTR [r9+112] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+96], r10 + mov QWORD PTR [r8+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + ; A[15] x A[15] + mov rdx, QWORD PTR [r9+120] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+112], r10 + mov QWORD PTR [r8+120], r11 + mov QWORD PTR [r8+-32], r15 + mov QWORD PTR [r8+-24], rdi + mov QWORD PTR [r8+-16], rsi + mov QWORD PTR [r8+-8], rbx + sub r8, 128 + cmp r9, r8 + jne L_end_2048_sqr_avx2_16 + vmovdqu xmm0, OWORD PTR [rbp] + vmovups OWORD PTR [r8], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+16] + vmovups OWORD PTR [r8+16], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+32] + vmovups OWORD PTR [r8+32], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+48] + vmovups OWORD PTR [r8+48], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+64] + vmovups OWORD PTR [r8+64], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+80] + vmovups OWORD PTR [r8+80], xmm0 +L_end_2048_sqr_avx2_16: + add rsp, 128 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + ret +sp_2048_sqr_avx2_16 ENDP +_text ENDS +ENDIF +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_add_16 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + adc r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + adc r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + adc r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + adc r10, QWORD PTR [r8+120] + mov QWORD PTR [rcx+120], r10 + adc rax, 0 + ret +sp_2048_add_16 ENDP +_text ENDS +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sub_in_place_32 PROC + mov r8, QWORD PTR [rcx] + xor rax, rax + sub r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rcx+8] + mov QWORD PTR [rcx], r8 + sbb r9, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rcx+16] + mov QWORD PTR [rcx+8], r9 + sbb r8, QWORD PTR [rdx+16] + mov r9, QWORD PTR [rcx+24] + mov QWORD PTR [rcx+16], r8 + sbb r9, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rcx+32] + mov QWORD PTR [rcx+24], r9 + sbb r8, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rcx+40] + mov QWORD PTR [rcx+32], r8 + sbb r9, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rcx+48] + mov QWORD PTR [rcx+40], r9 + sbb r8, QWORD PTR [rdx+48] + mov r9, QWORD PTR [rcx+56] + mov QWORD PTR [rcx+48], r8 + sbb r9, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rcx+64] + mov QWORD PTR [rcx+56], r9 + sbb r8, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rcx+72] + mov QWORD PTR [rcx+64], r8 + sbb r9, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rcx+80] + mov QWORD PTR [rcx+72], r9 + sbb r8, QWORD PTR [rdx+80] + mov r9, QWORD PTR [rcx+88] + mov QWORD PTR [rcx+80], r8 + sbb r9, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rcx+96] + mov QWORD PTR [rcx+88], r9 + sbb r8, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rcx+104] + mov QWORD PTR [rcx+96], r8 + sbb r9, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rcx+112] + mov QWORD PTR [rcx+104], r9 + sbb r8, QWORD PTR [rdx+112] + mov r9, QWORD PTR [rcx+120] + mov QWORD PTR [rcx+112], r8 + sbb r9, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rcx+128] + mov QWORD PTR [rcx+120], r9 + sbb r8, QWORD PTR [rdx+128] + mov r9, QWORD PTR [rcx+136] + mov QWORD PTR [rcx+128], r8 + sbb r9, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rcx+144] + mov QWORD PTR [rcx+136], r9 + sbb r8, QWORD PTR [rdx+144] + mov r9, QWORD PTR [rcx+152] + mov QWORD PTR [rcx+144], r8 + sbb r9, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rcx+160] + mov QWORD PTR [rcx+152], r9 + sbb r8, QWORD PTR [rdx+160] + mov r9, QWORD PTR [rcx+168] + mov QWORD PTR [rcx+160], r8 + sbb r9, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rcx+176] + mov QWORD PTR [rcx+168], r9 + sbb r8, QWORD PTR [rdx+176] + mov r9, QWORD PTR [rcx+184] + mov QWORD PTR [rcx+176], r8 + sbb r9, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rcx+192] + mov QWORD PTR [rcx+184], r9 + sbb r8, QWORD PTR [rdx+192] + mov r9, QWORD PTR [rcx+200] + mov QWORD PTR [rcx+192], r8 + sbb r9, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rcx+208] + mov QWORD PTR [rcx+200], r9 + sbb r8, QWORD PTR [rdx+208] + mov r9, QWORD PTR [rcx+216] + mov QWORD PTR [rcx+208], r8 + sbb r9, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rcx+224] + mov QWORD PTR [rcx+216], r9 + sbb r8, QWORD PTR [rdx+224] + mov r9, QWORD PTR [rcx+232] + mov QWORD PTR [rcx+224], r8 + sbb r9, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rcx+240] + mov QWORD PTR [rcx+232], r9 + sbb r8, QWORD PTR [rdx+240] + mov r9, QWORD PTR [rcx+248] + mov QWORD PTR [rcx+240], r8 + sbb r9, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+248], r9 + sbb rax, 0 + ret +sp_2048_sub_in_place_32 ENDP +_text ENDS +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_add_32 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + adc r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + adc r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + adc r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + adc r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + adc r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + adc r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + adc r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + adc r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + adc r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + adc r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + adc r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + adc r10, QWORD PTR [r8+184] + mov r9, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r10 + adc r9, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r9 + adc r10, QWORD PTR [r8+200] + mov r9, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r10 + adc r9, QWORD PTR [r8+208] + mov r10, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r9 + adc r10, QWORD PTR [r8+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r10 + adc r9, QWORD PTR [r8+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r9 + adc r10, QWORD PTR [r8+232] + mov r9, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r10 + adc r9, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r9 + adc r10, QWORD PTR [r8+248] + mov QWORD PTR [rcx+248], r10 + adc rax, 0 + ret +sp_2048_add_32 ENDP +_text ENDS +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_32 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 808 + mov QWORD PTR [rsp+768], rcx + mov QWORD PTR [rsp+776], rdx + mov QWORD PTR [rsp+784], r8 + lea r12, QWORD PTR [rsp+512] + lea r14, QWORD PTR [rdx+128] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r12+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [r12+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [rdx+112] + mov QWORD PTR [r12+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r12+112], r10 + adc rax, QWORD PTR [r14+120] + mov QWORD PTR [r12+120], rax + adc r15, 0 + mov QWORD PTR [rsp+792], r15 + lea r13, QWORD PTR [rsp+640] + lea r14, QWORD PTR [r8+128] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [r8+96] + mov QWORD PTR [r13+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [r8+104] + mov QWORD PTR [r13+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [r8+112] + mov QWORD PTR [r13+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [r8+120] + mov QWORD PTR [r13+112], r10 + adc rax, QWORD PTR [r14+120] + mov QWORD PTR [r13+120], rax + adc rdi, 0 + mov QWORD PTR [rsp+800], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_2048_mul_16 + mov r8, QWORD PTR [rsp+784] + mov rdx, QWORD PTR [rsp+776] + lea rcx, QWORD PTR [rsp+256] + add r8, 128 + add rdx, 128 + call sp_2048_mul_16 + mov r8, QWORD PTR [rsp+784] + mov rdx, QWORD PTR [rsp+776] + mov rcx, QWORD PTR [rsp+768] + call sp_2048_mul_16 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+784] + mov rdx, QWORD PTR [rsp+776] + mov rcx, QWORD PTR [rsp+768] +ENDIF + mov r15, QWORD PTR [rsp+792] + mov rdi, QWORD PTR [rsp+800] + mov rsi, QWORD PTR [rsp+768] + mov r11, r15 + lea r12, QWORD PTR [rsp+512] + lea r13, QWORD PTR [rsp+640] + and r11, rdi + neg r15 + neg rdi + add rsi, 256 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12], rax + mov QWORD PTR [r13], r9 + mov rax, QWORD PTR [r12+8] + mov r9, QWORD PTR [r13+8] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+8], rax + mov QWORD PTR [r13+8], r9 + mov rax, QWORD PTR [r12+16] + mov r9, QWORD PTR [r13+16] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+16], rax + mov QWORD PTR [r13+16], r9 + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+24], rax + mov QWORD PTR [r13+24], r9 + mov rax, QWORD PTR [r12+32] + mov r9, QWORD PTR [r13+32] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+32], rax + mov QWORD PTR [r13+32], r9 + mov rax, QWORD PTR [r12+40] + mov r9, QWORD PTR [r13+40] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+40], rax + mov QWORD PTR [r13+40], r9 + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+48], rax + mov QWORD PTR [r13+48], r9 + mov rax, QWORD PTR [r12+56] + mov r9, QWORD PTR [r13+56] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+56], rax + mov QWORD PTR [r13+56], r9 + mov rax, QWORD PTR [r12+64] + mov r9, QWORD PTR [r13+64] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+64], rax + mov QWORD PTR [r13+64], r9 + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+72], rax + mov QWORD PTR [r13+72], r9 + mov rax, QWORD PTR [r12+80] + mov r9, QWORD PTR [r13+80] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+80], rax + mov QWORD PTR [r13+80], r9 + mov rax, QWORD PTR [r12+88] + mov r9, QWORD PTR [r13+88] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+88], rax + mov QWORD PTR [r13+88], r9 + mov rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [r13+96] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+96], rax + mov QWORD PTR [r13+96], r9 + mov rax, QWORD PTR [r12+104] + mov r9, QWORD PTR [r13+104] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+104], rax + mov QWORD PTR [r13+104], r9 + mov rax, QWORD PTR [r12+112] + mov r9, QWORD PTR [r13+112] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+112], rax + mov QWORD PTR [r13+112], r9 + mov rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [r13+120] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+120], rax + mov QWORD PTR [r13+120], r9 + mov rax, QWORD PTR [r12] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov QWORD PTR [rsi+120], rax + adc r11, 0 + lea r13, QWORD PTR [rsp+256] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [r13+248] + mov QWORD PTR [r12+248], r9 + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [rcx+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [rcx+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [rcx+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [rcx+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [rcx+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [rcx+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [rcx+248] + mov QWORD PTR [r12+248], r9 + sbb r11, 0 + sub rsi, 128 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r12+248] + mov QWORD PTR [rsi+248], r9 + adc r11, 0 + mov QWORD PTR [rcx+384], r11 + add rsi, 128 + ; Add + mov rax, QWORD PTR [rsi] + xor r11, r11 + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov QWORD PTR [rsi+128], r9 + adc r11, 0 + ; Add to zero + mov rax, QWORD PTR [r13+136] + adc rax, 0 + mov r9, QWORD PTR [r13+144] + mov QWORD PTR [rsi+136], rax + adc r9, 0 + mov r10, QWORD PTR [r13+152] + mov QWORD PTR [rsi+144], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+160] + mov QWORD PTR [rsi+152], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+168] + mov QWORD PTR [rsi+160], rax + adc r9, 0 + mov r10, QWORD PTR [r13+176] + mov QWORD PTR [rsi+168], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+184] + mov QWORD PTR [rsi+176], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+192] + mov QWORD PTR [rsi+184], rax + adc r9, 0 + mov r10, QWORD PTR [r13+200] + mov QWORD PTR [rsi+192], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+208] + mov QWORD PTR [rsi+200], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+216] + mov QWORD PTR [rsi+208], rax + adc r9, 0 + mov r10, QWORD PTR [r13+224] + mov QWORD PTR [rsi+216], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+232] + mov QWORD PTR [rsi+224], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+240] + mov QWORD PTR [rsi+232], rax + adc r9, 0 + mov r10, QWORD PTR [r13+248] + mov QWORD PTR [rsi+240], r9 + adc r10, 0 + mov QWORD PTR [rsi+248], r10 + add rsp, 808 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_2048_mul_32 ENDP +_text ENDS +; /* Add a to a into r. (r = a + a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_dbl_16 PROC + mov r8, QWORD PTR [rdx] + xor rax, rax + add r8, r8 + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r8 + adc r9, r9 + mov QWORD PTR [rcx+120], r9 + adc rax, 0 + ret +sp_2048_dbl_16 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sqr_32 PROC + push r12 + sub rsp, 664 + mov QWORD PTR [rsp+640], rcx + mov QWORD PTR [rsp+648], rdx + lea r10, QWORD PTR [rsp+512] + lea r11, QWORD PTR [rdx+128] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r10+88], r8 + adc rax, QWORD PTR [r11+96] + mov r8, QWORD PTR [rdx+104] + mov QWORD PTR [r10+96], rax + adc r8, QWORD PTR [r11+104] + mov rax, QWORD PTR [rdx+112] + mov QWORD PTR [r10+104], r8 + adc rax, QWORD PTR [r11+112] + mov r8, QWORD PTR [rdx+120] + mov QWORD PTR [r10+112], rax + adc r8, QWORD PTR [r11+120] + mov QWORD PTR [r10+120], r8 + adc r9, 0 + mov QWORD PTR [rsp+656], r9 + mov rdx, r10 + mov rcx, rsp + call sp_2048_sqr_16 + mov rdx, QWORD PTR [rsp+648] + lea rcx, QWORD PTR [rsp+256] + add rdx, 128 + call sp_2048_sqr_16 + mov rdx, QWORD PTR [rsp+648] + mov rcx, QWORD PTR [rsp+640] + call sp_2048_sqr_16 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+648] + mov rcx, QWORD PTR [rsp+640] +ENDIF + mov r12, QWORD PTR [rsp+656] + lea r10, QWORD PTR [rsp+512] + mov r9, r12 + neg r12 + mov rax, QWORD PTR [r10] + mov r8, QWORD PTR [r10+8] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+256], rax + mov QWORD PTR [rcx+264], r8 + mov rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r10+24] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+272], rax + mov QWORD PTR [rcx+280], r8 + mov rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r10+40] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+288], rax + mov QWORD PTR [rcx+296], r8 + mov rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r10+56] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+304], rax + mov QWORD PTR [rcx+312], r8 + mov rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r10+72] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+320], rax + mov QWORD PTR [rcx+328], r8 + mov rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r10+88] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+336], rax + mov QWORD PTR [rcx+344], r8 + mov rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r10+104] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+352], rax + mov QWORD PTR [rcx+360], r8 + mov rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r10+120] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+368], rax + mov QWORD PTR [rcx+376], r8 + mov rax, QWORD PTR [rcx+256] + add rax, rax + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, r8 + mov QWORD PTR [rcx+376], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+256] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rdx+248] + mov QWORD PTR [r10+248], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rcx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rcx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rcx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rcx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rcx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rcx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rcx+248] + mov QWORD PTR [r10+248], r8 + sbb r9, 0 + ; Add in place + mov rax, QWORD PTR [rcx+128] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [rcx+136] + mov QWORD PTR [rcx+128], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [rcx+144] + mov QWORD PTR [rcx+136], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [rcx+152] + mov QWORD PTR [rcx+144], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [rcx+160] + mov QWORD PTR [rcx+152], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [rcx+168] + mov QWORD PTR [rcx+160], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [rcx+176] + mov QWORD PTR [rcx+168], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [rcx+184] + mov QWORD PTR [rcx+176], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [rcx+192] + mov QWORD PTR [rcx+184], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [rcx+200] + mov QWORD PTR [rcx+192], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [rcx+208] + mov QWORD PTR [rcx+200], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [rcx+216] + mov QWORD PTR [rcx+208], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [rcx+224] + mov QWORD PTR [rcx+216], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [rcx+232] + mov QWORD PTR [rcx+224], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [rcx+240] + mov QWORD PTR [rcx+232], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [rcx+248] + mov QWORD PTR [rcx+240], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [rcx+256] + mov QWORD PTR [rcx+248], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, QWORD PTR [r10+184] + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, QWORD PTR [r10+200] + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, QWORD PTR [r10+216] + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, QWORD PTR [r10+232] + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, QWORD PTR [r10+248] + mov QWORD PTR [rcx+376], r8 + adc r9, 0 + mov QWORD PTR [rcx+384], r9 + ; Add in place + mov rax, QWORD PTR [rcx+256] + xor r9, r9 + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rcx+384] + mov QWORD PTR [rcx+376], r8 + adc rax, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+384], rax + adc r9, 0 + ; Add to zero + mov rax, QWORD PTR [rdx+136] + adc rax, 0 + mov r8, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+392], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+400], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+408], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+416], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+424], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+432], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+440], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+448], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+456], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+464], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+472], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+480], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+488], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+496], r8 + adc rax, 0 + mov QWORD PTR [rcx+504], rax + add rsp, 664 + pop r12 + ret +sp_2048_sqr_32 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_avx2_32 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 808 + mov QWORD PTR [rsp+768], rcx + mov QWORD PTR [rsp+776], rdx + mov QWORD PTR [rsp+784], r8 + lea r12, QWORD PTR [rsp+512] + lea r14, QWORD PTR [rdx+128] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r12+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [r12+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [rdx+112] + mov QWORD PTR [r12+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r12+112], r10 + adc rax, QWORD PTR [r14+120] + mov QWORD PTR [r12+120], rax + adc r15, 0 + mov QWORD PTR [rsp+792], r15 + lea r13, QWORD PTR [rsp+640] + lea r14, QWORD PTR [r8+128] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [r8+96] + mov QWORD PTR [r13+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [r8+104] + mov QWORD PTR [r13+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [r8+112] + mov QWORD PTR [r13+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [r8+120] + mov QWORD PTR [r13+112], r10 + adc rax, QWORD PTR [r14+120] + mov QWORD PTR [r13+120], rax + adc rdi, 0 + mov QWORD PTR [rsp+800], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_2048_mul_avx2_16 + mov r8, QWORD PTR [rsp+784] + mov rdx, QWORD PTR [rsp+776] + lea rcx, QWORD PTR [rsp+256] + add r8, 128 + add rdx, 128 + call sp_2048_mul_avx2_16 + mov r8, QWORD PTR [rsp+784] + mov rdx, QWORD PTR [rsp+776] + mov rcx, QWORD PTR [rsp+768] + call sp_2048_mul_avx2_16 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+784] + mov rdx, QWORD PTR [rsp+776] + mov rcx, QWORD PTR [rsp+768] +ENDIF + mov r15, QWORD PTR [rsp+792] + mov rdi, QWORD PTR [rsp+800] + mov rsi, QWORD PTR [rsp+768] + mov r11, r15 + lea r12, QWORD PTR [rsp+512] + lea r13, QWORD PTR [rsp+640] + and r11, rdi + neg r15 + neg rdi + add rsi, 256 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + pext rax, rax, rdi + pext r9, r9, r15 + add rax, r9 + mov r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [r13+8] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi], rax + adc r9, r10 + mov r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [r13+16] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+8], r9 + adc r10, rax + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+16], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [r13+32] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+24], rax + adc r9, r10 + mov r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [r13+40] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+32], r9 + adc r10, rax + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+40], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [r13+56] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+48], rax + adc r9, r10 + mov r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [r13+64] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+56], r9 + adc r10, rax + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+64], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [r13+80] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+72], rax + adc r9, r10 + mov r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [r13+88] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+80], r9 + adc r10, rax + mov rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [r13+96] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+88], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [r13+104] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+96], rax + adc r9, r10 + mov r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [r13+112] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+104], r9 + adc r10, rax + mov rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [r13+120] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+112], r10 + adc rax, r9 + mov QWORD PTR [rsi+120], rax + adc r11, 0 + lea r13, QWORD PTR [rsp+256] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [r13+248] + mov QWORD PTR [r12+248], r9 + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [rcx+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [rcx+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [rcx+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [rcx+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [rcx+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [rcx+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [rcx+248] + mov QWORD PTR [r12+248], r9 + sbb r11, 0 + sub rsi, 128 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r12+248] + mov QWORD PTR [rsi+248], r9 + adc r11, 0 + mov QWORD PTR [rcx+384], r11 + add rsi, 128 + ; Add + mov rax, QWORD PTR [rsi] + xor r11, r11 + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov QWORD PTR [rsi+128], r9 + adc r11, 0 + ; Add to zero + mov rax, QWORD PTR [r13+136] + adc rax, 0 + mov r9, QWORD PTR [r13+144] + mov QWORD PTR [rsi+136], rax + adc r9, 0 + mov r10, QWORD PTR [r13+152] + mov QWORD PTR [rsi+144], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+160] + mov QWORD PTR [rsi+152], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+168] + mov QWORD PTR [rsi+160], rax + adc r9, 0 + mov r10, QWORD PTR [r13+176] + mov QWORD PTR [rsi+168], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+184] + mov QWORD PTR [rsi+176], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+192] + mov QWORD PTR [rsi+184], rax + adc r9, 0 + mov r10, QWORD PTR [r13+200] + mov QWORD PTR [rsi+192], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+208] + mov QWORD PTR [rsi+200], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+216] + mov QWORD PTR [rsi+208], rax + adc r9, 0 + mov r10, QWORD PTR [r13+224] + mov QWORD PTR [rsi+216], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+232] + mov QWORD PTR [rsi+224], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+240] + mov QWORD PTR [rsi+232], rax + adc r9, 0 + mov r10, QWORD PTR [r13+248] + mov QWORD PTR [rsi+240], r9 + adc r10, 0 + mov QWORD PTR [rsi+248], r10 + add rsp, 808 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_2048_mul_avx2_32 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sqr_avx2_32 PROC + push r12 + sub rsp, 664 + mov QWORD PTR [rsp+640], rcx + mov QWORD PTR [rsp+648], rdx + lea r10, QWORD PTR [rsp+512] + lea r11, QWORD PTR [rdx+128] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r10+88], r8 + adc rax, QWORD PTR [r11+96] + mov r8, QWORD PTR [rdx+104] + mov QWORD PTR [r10+96], rax + adc r8, QWORD PTR [r11+104] + mov rax, QWORD PTR [rdx+112] + mov QWORD PTR [r10+104], r8 + adc rax, QWORD PTR [r11+112] + mov r8, QWORD PTR [rdx+120] + mov QWORD PTR [r10+112], rax + adc r8, QWORD PTR [r11+120] + mov QWORD PTR [r10+120], r8 + adc r9, 0 + mov QWORD PTR [rsp+656], r9 + mov rdx, r10 + mov rcx, rsp + call sp_2048_sqr_avx2_16 + mov rdx, QWORD PTR [rsp+648] + lea rcx, QWORD PTR [rsp+256] + add rdx, 128 + call sp_2048_sqr_avx2_16 + mov rdx, QWORD PTR [rsp+648] + mov rcx, QWORD PTR [rsp+640] + call sp_2048_sqr_avx2_16 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+648] + mov rcx, QWORD PTR [rsp+640] +ENDIF + mov r12, QWORD PTR [rsp+656] + lea r10, QWORD PTR [rsp+512] + mov r9, r12 + neg r12 + mov rax, QWORD PTR [r10] + pext rax, rax, r12 + add rax, rax + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [rcx+256], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [rcx+264], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [rcx+272], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [rcx+280], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [rcx+288], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [rcx+296], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [rcx+304], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [rcx+312], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [rcx+320], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [rcx+328], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [rcx+336], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [rcx+344], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [rcx+352], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [rcx+360], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [rcx+368], rax + pext r8, r8, r12 + adc r8, r8 + mov QWORD PTR [rcx+376], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+256] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rdx+248] + mov QWORD PTR [r10+248], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rcx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rcx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rcx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rcx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rcx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rcx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rcx+248] + mov QWORD PTR [r10+248], r8 + sbb r9, 0 + ; Add in place + mov rax, QWORD PTR [rcx+128] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [rcx+136] + mov QWORD PTR [rcx+128], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [rcx+144] + mov QWORD PTR [rcx+136], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [rcx+152] + mov QWORD PTR [rcx+144], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [rcx+160] + mov QWORD PTR [rcx+152], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [rcx+168] + mov QWORD PTR [rcx+160], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [rcx+176] + mov QWORD PTR [rcx+168], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [rcx+184] + mov QWORD PTR [rcx+176], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [rcx+192] + mov QWORD PTR [rcx+184], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [rcx+200] + mov QWORD PTR [rcx+192], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [rcx+208] + mov QWORD PTR [rcx+200], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [rcx+216] + mov QWORD PTR [rcx+208], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [rcx+224] + mov QWORD PTR [rcx+216], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [rcx+232] + mov QWORD PTR [rcx+224], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [rcx+240] + mov QWORD PTR [rcx+232], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [rcx+248] + mov QWORD PTR [rcx+240], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [rcx+256] + mov QWORD PTR [rcx+248], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, QWORD PTR [r10+184] + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, QWORD PTR [r10+200] + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, QWORD PTR [r10+216] + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, QWORD PTR [r10+232] + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, QWORD PTR [r10+248] + mov QWORD PTR [rcx+376], r8 + adc r9, 0 + mov QWORD PTR [rcx+384], r9 + ; Add in place + mov rax, QWORD PTR [rcx+256] + xor r9, r9 + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rcx+384] + mov QWORD PTR [rcx+376], r8 + adc rax, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+384], rax + adc r9, 0 + ; Add to zero + mov rax, QWORD PTR [rdx+136] + adc rax, 0 + mov r8, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+392], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+400], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+408], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+416], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+424], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+432], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+440], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+448], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+456], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+464], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+472], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+480], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+488], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+496], r8 + adc rax, 0 + mov QWORD PTR [rcx+504], rax + add rsp, 664 + pop r12 + ret +sp_2048_sqr_avx2_32 ENDP +_text ENDS +ENDIF +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sub_in_place_16 PROC + mov r8, QWORD PTR [rcx] + xor rax, rax + sub r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rcx+8] + mov QWORD PTR [rcx], r8 + sbb r9, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rcx+16] + mov QWORD PTR [rcx+8], r9 + sbb r8, QWORD PTR [rdx+16] + mov r9, QWORD PTR [rcx+24] + mov QWORD PTR [rcx+16], r8 + sbb r9, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rcx+32] + mov QWORD PTR [rcx+24], r9 + sbb r8, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rcx+40] + mov QWORD PTR [rcx+32], r8 + sbb r9, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rcx+48] + mov QWORD PTR [rcx+40], r9 + sbb r8, QWORD PTR [rdx+48] + mov r9, QWORD PTR [rcx+56] + mov QWORD PTR [rcx+48], r8 + sbb r9, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rcx+64] + mov QWORD PTR [rcx+56], r9 + sbb r8, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rcx+72] + mov QWORD PTR [rcx+64], r8 + sbb r9, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rcx+80] + mov QWORD PTR [rcx+72], r9 + sbb r8, QWORD PTR [rdx+80] + mov r9, QWORD PTR [rcx+88] + mov QWORD PTR [rcx+80], r8 + sbb r9, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rcx+96] + mov QWORD PTR [rcx+88], r9 + sbb r8, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rcx+104] + mov QWORD PTR [rcx+96], r8 + sbb r9, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rcx+112] + mov QWORD PTR [rcx+104], r9 + sbb r8, QWORD PTR [rdx+112] + mov r9, QWORD PTR [rcx+120] + mov QWORD PTR [rcx+112], r8 + sbb r9, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+120], r9 + sbb rax, 0 + ret +sp_2048_sub_in_place_16 ENDP +_text ENDS +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_d_32 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+40] + add r12, rax + mov QWORD PTR [rcx+40], r12 + adc r10, rdx + adc r11, 0 + ; A[6] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+48] + add r10, rax + mov QWORD PTR [rcx+48], r10 + adc r11, rdx + adc r12, 0 + ; A[7] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+56] + add r11, rax + mov QWORD PTR [rcx+56], r11 + adc r12, rdx + adc r10, 0 + ; A[8] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+64] + add r12, rax + mov QWORD PTR [rcx+64], r12 + adc r10, rdx + adc r11, 0 + ; A[9] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+72] + add r10, rax + mov QWORD PTR [rcx+72], r10 + adc r11, rdx + adc r12, 0 + ; A[10] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+80] + add r11, rax + mov QWORD PTR [rcx+80], r11 + adc r12, rdx + adc r10, 0 + ; A[11] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+88] + add r12, rax + mov QWORD PTR [rcx+88], r12 + adc r10, rdx + adc r11, 0 + ; A[12] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+96] + add r10, rax + mov QWORD PTR [rcx+96], r10 + adc r11, rdx + adc r12, 0 + ; A[13] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+104] + add r11, rax + mov QWORD PTR [rcx+104], r11 + adc r12, rdx + adc r10, 0 + ; A[14] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+112] + add r12, rax + mov QWORD PTR [rcx+112], r12 + adc r10, rdx + adc r11, 0 + ; A[15] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+120] + add r10, rax + mov QWORD PTR [rcx+120], r10 + adc r11, rdx + adc r12, 0 + ; A[16] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+128] + add r11, rax + mov QWORD PTR [rcx+128], r11 + adc r12, rdx + adc r10, 0 + ; A[17] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+136] + add r12, rax + mov QWORD PTR [rcx+136], r12 + adc r10, rdx + adc r11, 0 + ; A[18] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+144] + add r10, rax + mov QWORD PTR [rcx+144], r10 + adc r11, rdx + adc r12, 0 + ; A[19] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+152] + add r11, rax + mov QWORD PTR [rcx+152], r11 + adc r12, rdx + adc r10, 0 + ; A[20] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+160] + add r12, rax + mov QWORD PTR [rcx+160], r12 + adc r10, rdx + adc r11, 0 + ; A[21] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+168] + add r10, rax + mov QWORD PTR [rcx+168], r10 + adc r11, rdx + adc r12, 0 + ; A[22] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+176] + add r11, rax + mov QWORD PTR [rcx+176], r11 + adc r12, rdx + adc r10, 0 + ; A[23] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+184] + add r12, rax + mov QWORD PTR [rcx+184], r12 + adc r10, rdx + adc r11, 0 + ; A[24] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+192] + add r10, rax + mov QWORD PTR [rcx+192], r10 + adc r11, rdx + adc r12, 0 + ; A[25] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+200] + add r11, rax + mov QWORD PTR [rcx+200], r11 + adc r12, rdx + adc r10, 0 + ; A[26] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+208] + add r12, rax + mov QWORD PTR [rcx+208], r12 + adc r10, rdx + adc r11, 0 + ; A[27] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+216] + add r10, rax + mov QWORD PTR [rcx+216], r10 + adc r11, rdx + adc r12, 0 + ; A[28] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+224] + add r11, rax + mov QWORD PTR [rcx+224], r11 + adc r12, rdx + adc r10, 0 + ; A[29] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+232] + add r12, rax + mov QWORD PTR [rcx+232], r12 + adc r10, rdx + adc r11, 0 + ; A[30] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+240] + add r10, rax + mov QWORD PTR [rcx+240], r10 + adc r11, rdx + adc r12, 0 + ; A[31] * B + mov rax, r8 + mul QWORD PTR [r9+248] + add r11, rax + adc r12, rdx + mov QWORD PTR [rcx+248], r11 + mov QWORD PTR [rcx+256], r12 + pop r12 + ret +sp_2048_mul_d_32 ENDP +_text ENDS +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_2048_cond_sub_16 PROC + sub rsp, 128 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + sbb r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + sbb r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + sbb r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + sbb r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + sbb r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + sbb r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + sbb r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + sbb r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + sbb r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + sbb r11, r8 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb rax, 0 + add rsp, 128 + ret +sp_2048_cond_sub_16 ENDP +_text ENDS +; /* Reduce the number back to 2048 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_2048_mont_reduce_16 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 16 + mov r10, 16 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_2048_mont_loop_16: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc r11, 0 + ; a[i+6] += m[6] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+48] + mov r14, QWORD PTR [rcx+48] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+48], r14 + adc r12, 0 + ; a[i+7] += m[7] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+56] + mov r14, QWORD PTR [rcx+56] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+56], r14 + adc r11, 0 + ; a[i+8] += m[8] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+64] + mov r14, QWORD PTR [rcx+64] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+64], r14 + adc r12, 0 + ; a[i+9] += m[9] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+72] + mov r14, QWORD PTR [rcx+72] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+72], r14 + adc r11, 0 + ; a[i+10] += m[10] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+80] + mov r14, QWORD PTR [rcx+80] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+80], r14 + adc r12, 0 + ; a[i+11] += m[11] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+88] + mov r14, QWORD PTR [rcx+88] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+88], r14 + adc r11, 0 + ; a[i+12] += m[12] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+96] + mov r14, QWORD PTR [rcx+96] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+96], r14 + adc r12, 0 + ; a[i+13] += m[13] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+104] + mov r14, QWORD PTR [rcx+104] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+104], r14 + adc r11, 0 + ; a[i+14] += m[14] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+112] + mov r14, QWORD PTR [rcx+112] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+112], r14 + adc r12, 0 + ; a[i+15] += m[15] * mu + mov rax, r13 + mul QWORD PTR [r9+120] + mov r14, QWORD PTR [rcx+120] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+120], r14 + adc QWORD PTR [rcx+128], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_2048_mont_loop_16 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + neg rsi +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 128 + call sp_2048_cond_sub_16 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_2048_mont_reduce_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_2048_cond_sub_avx2_16 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + sbb r10, r11 + mov QWORD PTR [rcx+120], r10 + sbb rax, 0 + pop r12 + ret +sp_2048_cond_sub_avx2_16 ENDP +_text ENDS +ENDIF +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_d_16 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+40] + add r12, rax + mov QWORD PTR [rcx+40], r12 + adc r10, rdx + adc r11, 0 + ; A[6] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+48] + add r10, rax + mov QWORD PTR [rcx+48], r10 + adc r11, rdx + adc r12, 0 + ; A[7] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+56] + add r11, rax + mov QWORD PTR [rcx+56], r11 + adc r12, rdx + adc r10, 0 + ; A[8] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+64] + add r12, rax + mov QWORD PTR [rcx+64], r12 + adc r10, rdx + adc r11, 0 + ; A[9] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+72] + add r10, rax + mov QWORD PTR [rcx+72], r10 + adc r11, rdx + adc r12, 0 + ; A[10] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+80] + add r11, rax + mov QWORD PTR [rcx+80], r11 + adc r12, rdx + adc r10, 0 + ; A[11] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+88] + add r12, rax + mov QWORD PTR [rcx+88], r12 + adc r10, rdx + adc r11, 0 + ; A[12] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+96] + add r10, rax + mov QWORD PTR [rcx+96], r10 + adc r11, rdx + adc r12, 0 + ; A[13] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+104] + add r11, rax + mov QWORD PTR [rcx+104], r11 + adc r12, rdx + adc r10, 0 + ; A[14] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+112] + add r12, rax + mov QWORD PTR [rcx+112], r12 + adc r10, rdx + adc r11, 0 + ; A[15] * B + mov rax, r8 + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+120], r10 + mov QWORD PTR [rcx+128], r11 + pop r12 + ret +sp_2048_mul_d_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_d_avx2_16 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; A[6] * B + mulx r10, r9, QWORD PTR [rax+48] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; A[7] * B + mulx r10, r9, QWORD PTR [rax+56] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; A[8] * B + mulx r10, r9, QWORD PTR [rax+64] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; A[9] * B + mulx r10, r9, QWORD PTR [rax+72] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + ; A[10] * B + mulx r10, r9, QWORD PTR [rax+80] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+80], r11 + ; A[11] * B + mulx r10, r9, QWORD PTR [rax+88] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+88], r12 + ; A[12] * B + mulx r10, r9, QWORD PTR [rax+96] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+96], r11 + ; A[13] * B + mulx r10, r9, QWORD PTR [rax+104] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+104], r12 + ; A[14] * B + mulx r10, r9, QWORD PTR [rax+112] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+112], r11 + ; A[15] * B + mulx r10, r9, QWORD PTR [rax+120] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+120], r12 + mov QWORD PTR [rcx+128], r11 + pop r13 + pop r12 + ret +sp_2048_mul_d_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_2048_word_asm_16 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_2048_word_asm_16 ENDP +_text ENDS +ENDIF +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_2048_cmp_16 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+120] + mov r12, QWORD PTR [rdx+120] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+112] + mov r12, QWORD PTR [rdx+112] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+104] + mov r12, QWORD PTR [rdx+104] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+96] + mov r12, QWORD PTR [rdx+96] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+88] + mov r12, QWORD PTR [rdx+88] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+80] + mov r12, QWORD PTR [rdx+80] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+72] + mov r12, QWORD PTR [rdx+72] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+64] + mov r12, QWORD PTR [rdx+64] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+56] + mov r12, QWORD PTR [rdx+56] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+48] + mov r12, QWORD PTR [rdx+48] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_2048_cmp_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 2048 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_2048_mont_reduce_avx2_16 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r9, rcx + mov r10, rdx + xor rbp, rbp + ; i = 16 + mov r11, 16 + mov r15, QWORD PTR [r9] + mov rdi, QWORD PTR [r9+8] + mov rsi, QWORD PTR [r9+16] + mov rbx, QWORD PTR [r9+24] + add r9, 64 + xor rbp, rbp +L_2048_mont_loop_avx2_16: + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-32] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-24] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-24], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9+-8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-16], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-8], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+8], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+16], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+24], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+32], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+40], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+48], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+56], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+64], r12 + adox rbp, r14 + adcx rbp, r14 + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-24] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-16] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-8] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-16], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-8], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9+8] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+16] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+8], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+24] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+16], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+32] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+24], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+40] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+32], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+48] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+40], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+56] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+48], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+64] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+56], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+72] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+64], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+72], r12 + adox rbp, r14 + adcx rbp, r14 + ; a += 2 + add r9, 16 + ; i -= 2 + sub r11, 2 + jnz L_2048_mont_loop_avx2_16 + sub r9, 64 + neg rbp + mov r8, r9 + sub r9, 128 + mov rcx, QWORD PTR [r10] + mov rdx, r15 + pext rcx, rcx, rbp + sub rdx, rcx + mov rcx, QWORD PTR [r10+8] + mov rax, rdi + pext rcx, rcx, rbp + mov QWORD PTR [r9], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+16] + mov rcx, rsi + pext rdx, rdx, rbp + mov QWORD PTR [r9+8], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+24] + mov rdx, rbx + pext rax, rax, rbp + mov QWORD PTR [r9+16], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+32] + mov rax, QWORD PTR [r8+32] + pext rcx, rcx, rbp + mov QWORD PTR [r9+24], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+40] + mov rcx, QWORD PTR [r8+40] + pext rdx, rdx, rbp + mov QWORD PTR [r9+32], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+48] + mov rdx, QWORD PTR [r8+48] + pext rax, rax, rbp + mov QWORD PTR [r9+40], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+56] + mov rax, QWORD PTR [r8+56] + pext rcx, rcx, rbp + mov QWORD PTR [r9+48], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+64] + mov rcx, QWORD PTR [r8+64] + pext rdx, rdx, rbp + mov QWORD PTR [r9+56], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+72] + mov rdx, QWORD PTR [r8+72] + pext rax, rax, rbp + mov QWORD PTR [r9+64], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+80] + mov rax, QWORD PTR [r8+80] + pext rcx, rcx, rbp + mov QWORD PTR [r9+72], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+88] + mov rcx, QWORD PTR [r8+88] + pext rdx, rdx, rbp + mov QWORD PTR [r9+80], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+96] + mov rdx, QWORD PTR [r8+96] + pext rax, rax, rbp + mov QWORD PTR [r9+88], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+104] + mov rax, QWORD PTR [r8+104] + pext rcx, rcx, rbp + mov QWORD PTR [r9+96], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+112] + mov rcx, QWORD PTR [r8+112] + pext rdx, rdx, rbp + mov QWORD PTR [r9+104], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+120] + mov rdx, QWORD PTR [r8+120] + pext rax, rax, rbp + mov QWORD PTR [r9+112], rcx + sbb rdx, rax + mov QWORD PTR [r9+120], rdx + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_2048_mont_reduce_avx2_16 ENDP +_text ENDS +ENDIF +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_2048_cond_sub_32 PROC + sub rsp, 256 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [r8+128] + mov r11, QWORD PTR [r8+136] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+128], r10 + mov QWORD PTR [rsp+136], r11 + mov r10, QWORD PTR [r8+144] + mov r11, QWORD PTR [r8+152] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+144], r10 + mov QWORD PTR [rsp+152], r11 + mov r10, QWORD PTR [r8+160] + mov r11, QWORD PTR [r8+168] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+160], r10 + mov QWORD PTR [rsp+168], r11 + mov r10, QWORD PTR [r8+176] + mov r11, QWORD PTR [r8+184] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+176], r10 + mov QWORD PTR [rsp+184], r11 + mov r10, QWORD PTR [r8+192] + mov r11, QWORD PTR [r8+200] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+192], r10 + mov QWORD PTR [rsp+200], r11 + mov r10, QWORD PTR [r8+208] + mov r11, QWORD PTR [r8+216] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+208], r10 + mov QWORD PTR [rsp+216], r11 + mov r10, QWORD PTR [r8+224] + mov r11, QWORD PTR [r8+232] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+224], r10 + mov QWORD PTR [rsp+232], r11 + mov r10, QWORD PTR [r8+240] + mov r11, QWORD PTR [r8+248] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+240], r10 + mov QWORD PTR [rsp+248], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + sbb r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + sbb r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + sbb r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + sbb r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + sbb r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + sbb r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + sbb r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + sbb r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + sbb r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + sbb r11, r8 + mov QWORD PTR [rcx+112], r10 + mov r10, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rsp+128] + sbb r10, r8 + mov QWORD PTR [rcx+120], r11 + mov r11, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rsp+136] + sbb r11, r8 + mov QWORD PTR [rcx+128], r10 + mov r10, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rsp+144] + sbb r10, r8 + mov QWORD PTR [rcx+136], r11 + mov r11, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rsp+152] + sbb r11, r8 + mov QWORD PTR [rcx+144], r10 + mov r10, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rsp+160] + sbb r10, r8 + mov QWORD PTR [rcx+152], r11 + mov r11, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rsp+168] + sbb r11, r8 + mov QWORD PTR [rcx+160], r10 + mov r10, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rsp+176] + sbb r10, r8 + mov QWORD PTR [rcx+168], r11 + mov r11, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rsp+184] + sbb r11, r8 + mov QWORD PTR [rcx+176], r10 + mov r10, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rsp+192] + sbb r10, r8 + mov QWORD PTR [rcx+184], r11 + mov r11, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rsp+200] + sbb r11, r8 + mov QWORD PTR [rcx+192], r10 + mov r10, QWORD PTR [rdx+208] + mov r8, QWORD PTR [rsp+208] + sbb r10, r8 + mov QWORD PTR [rcx+200], r11 + mov r11, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rsp+216] + sbb r11, r8 + mov QWORD PTR [rcx+208], r10 + mov r10, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rsp+224] + sbb r10, r8 + mov QWORD PTR [rcx+216], r11 + mov r11, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rsp+232] + sbb r11, r8 + mov QWORD PTR [rcx+224], r10 + mov r10, QWORD PTR [rdx+240] + mov r8, QWORD PTR [rsp+240] + sbb r10, r8 + mov QWORD PTR [rcx+232], r11 + mov r11, QWORD PTR [rdx+248] + mov r8, QWORD PTR [rsp+248] + sbb r11, r8 + mov QWORD PTR [rcx+240], r10 + mov QWORD PTR [rcx+248], r11 + sbb rax, 0 + add rsp, 256 + ret +sp_2048_cond_sub_32 ENDP +_text ENDS +; /* Reduce the number back to 2048 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_2048_mont_reduce_32 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 32 + mov r10, 32 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_2048_mont_loop_32: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc r11, 0 + ; a[i+6] += m[6] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+48] + mov r14, QWORD PTR [rcx+48] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+48], r14 + adc r12, 0 + ; a[i+7] += m[7] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+56] + mov r14, QWORD PTR [rcx+56] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+56], r14 + adc r11, 0 + ; a[i+8] += m[8] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+64] + mov r14, QWORD PTR [rcx+64] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+64], r14 + adc r12, 0 + ; a[i+9] += m[9] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+72] + mov r14, QWORD PTR [rcx+72] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+72], r14 + adc r11, 0 + ; a[i+10] += m[10] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+80] + mov r14, QWORD PTR [rcx+80] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+80], r14 + adc r12, 0 + ; a[i+11] += m[11] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+88] + mov r14, QWORD PTR [rcx+88] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+88], r14 + adc r11, 0 + ; a[i+12] += m[12] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+96] + mov r14, QWORD PTR [rcx+96] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+96], r14 + adc r12, 0 + ; a[i+13] += m[13] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+104] + mov r14, QWORD PTR [rcx+104] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+104], r14 + adc r11, 0 + ; a[i+14] += m[14] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+112] + mov r14, QWORD PTR [rcx+112] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+112], r14 + adc r12, 0 + ; a[i+15] += m[15] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+120] + mov r14, QWORD PTR [rcx+120] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+120], r14 + adc r11, 0 + ; a[i+16] += m[16] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+128] + mov r14, QWORD PTR [rcx+128] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+128], r14 + adc r12, 0 + ; a[i+17] += m[17] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+136] + mov r14, QWORD PTR [rcx+136] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+136], r14 + adc r11, 0 + ; a[i+18] += m[18] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+144] + mov r14, QWORD PTR [rcx+144] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+144], r14 + adc r12, 0 + ; a[i+19] += m[19] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+152] + mov r14, QWORD PTR [rcx+152] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+152], r14 + adc r11, 0 + ; a[i+20] += m[20] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+160] + mov r14, QWORD PTR [rcx+160] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+160], r14 + adc r12, 0 + ; a[i+21] += m[21] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+168] + mov r14, QWORD PTR [rcx+168] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+168], r14 + adc r11, 0 + ; a[i+22] += m[22] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+176] + mov r14, QWORD PTR [rcx+176] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+176], r14 + adc r12, 0 + ; a[i+23] += m[23] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+184] + mov r14, QWORD PTR [rcx+184] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+184], r14 + adc r11, 0 + ; a[i+24] += m[24] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+192] + mov r14, QWORD PTR [rcx+192] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+192], r14 + adc r12, 0 + ; a[i+25] += m[25] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+200] + mov r14, QWORD PTR [rcx+200] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+200], r14 + adc r11, 0 + ; a[i+26] += m[26] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+208] + mov r14, QWORD PTR [rcx+208] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+208], r14 + adc r12, 0 + ; a[i+27] += m[27] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+216] + mov r14, QWORD PTR [rcx+216] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+216], r14 + adc r11, 0 + ; a[i+28] += m[28] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+224] + mov r14, QWORD PTR [rcx+224] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+224], r14 + adc r12, 0 + ; a[i+29] += m[29] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+232] + mov r14, QWORD PTR [rcx+232] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+232], r14 + adc r11, 0 + ; a[i+30] += m[30] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+240] + mov r14, QWORD PTR [rcx+240] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+240], r14 + adc r12, 0 + ; a[i+31] += m[31] * mu + mov rax, r13 + mul QWORD PTR [r9+248] + mov r14, QWORD PTR [rcx+248] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+248], r14 + adc QWORD PTR [rcx+256], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_2048_mont_loop_32 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + neg rsi +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 256 + call sp_2048_cond_sub_32 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_2048_mont_reduce_32 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_2048_cond_sub_avx2_32 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+128] + mov r11, QWORD PTR [rdx+128] + pext r12, r12, r9 + mov QWORD PTR [rcx+120], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+136] + mov r12, QWORD PTR [rdx+136] + pext r10, r10, r9 + mov QWORD PTR [rcx+128], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+144] + pext r11, r11, r9 + mov QWORD PTR [rcx+136], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+152] + mov r11, QWORD PTR [rdx+152] + pext r12, r12, r9 + mov QWORD PTR [rcx+144], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+160] + mov r12, QWORD PTR [rdx+160] + pext r10, r10, r9 + mov QWORD PTR [rcx+152], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+168] + mov r10, QWORD PTR [rdx+168] + pext r11, r11, r9 + mov QWORD PTR [rcx+160], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+176] + mov r11, QWORD PTR [rdx+176] + pext r12, r12, r9 + mov QWORD PTR [rcx+168], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+184] + mov r12, QWORD PTR [rdx+184] + pext r10, r10, r9 + mov QWORD PTR [rcx+176], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+192] + pext r11, r11, r9 + mov QWORD PTR [rcx+184], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+200] + mov r11, QWORD PTR [rdx+200] + pext r12, r12, r9 + mov QWORD PTR [rcx+192], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+208] + mov r12, QWORD PTR [rdx+208] + pext r10, r10, r9 + mov QWORD PTR [rcx+200], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+216] + mov r10, QWORD PTR [rdx+216] + pext r11, r11, r9 + mov QWORD PTR [rcx+208], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+224] + mov r11, QWORD PTR [rdx+224] + pext r12, r12, r9 + mov QWORD PTR [rcx+216], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+232] + mov r12, QWORD PTR [rdx+232] + pext r10, r10, r9 + mov QWORD PTR [rcx+224], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+240] + pext r11, r11, r9 + mov QWORD PTR [rcx+232], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+248] + mov r11, QWORD PTR [rdx+248] + pext r12, r12, r9 + mov QWORD PTR [rcx+240], r10 + sbb r11, r12 + mov QWORD PTR [rcx+248], r11 + sbb rax, 0 + pop r12 + ret +sp_2048_cond_sub_avx2_32 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_2048_mul_d_avx2_32 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; A[6] * B + mulx r10, r9, QWORD PTR [rax+48] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; A[7] * B + mulx r10, r9, QWORD PTR [rax+56] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; A[8] * B + mulx r10, r9, QWORD PTR [rax+64] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; A[9] * B + mulx r10, r9, QWORD PTR [rax+72] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + ; A[10] * B + mulx r10, r9, QWORD PTR [rax+80] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+80], r11 + ; A[11] * B + mulx r10, r9, QWORD PTR [rax+88] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+88], r12 + ; A[12] * B + mulx r10, r9, QWORD PTR [rax+96] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+96], r11 + ; A[13] * B + mulx r10, r9, QWORD PTR [rax+104] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+104], r12 + ; A[14] * B + mulx r10, r9, QWORD PTR [rax+112] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+112], r11 + ; A[15] * B + mulx r10, r9, QWORD PTR [rax+120] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+120], r12 + ; A[16] * B + mulx r10, r9, QWORD PTR [rax+128] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+128], r11 + ; A[17] * B + mulx r10, r9, QWORD PTR [rax+136] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+136], r12 + ; A[18] * B + mulx r10, r9, QWORD PTR [rax+144] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+144], r11 + ; A[19] * B + mulx r10, r9, QWORD PTR [rax+152] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+152], r12 + ; A[20] * B + mulx r10, r9, QWORD PTR [rax+160] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+160], r11 + ; A[21] * B + mulx r10, r9, QWORD PTR [rax+168] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+168], r12 + ; A[22] * B + mulx r10, r9, QWORD PTR [rax+176] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+176], r11 + ; A[23] * B + mulx r10, r9, QWORD PTR [rax+184] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+184], r12 + ; A[24] * B + mulx r10, r9, QWORD PTR [rax+192] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+192], r11 + ; A[25] * B + mulx r10, r9, QWORD PTR [rax+200] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+200], r12 + ; A[26] * B + mulx r10, r9, QWORD PTR [rax+208] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+208], r11 + ; A[27] * B + mulx r10, r9, QWORD PTR [rax+216] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+216], r12 + ; A[28] * B + mulx r10, r9, QWORD PTR [rax+224] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+224], r11 + ; A[29] * B + mulx r10, r9, QWORD PTR [rax+232] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+232], r12 + ; A[30] * B + mulx r10, r9, QWORD PTR [rax+240] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+240], r11 + ; A[31] * B + mulx r10, r9, QWORD PTR [rax+248] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+248], r12 + mov QWORD PTR [rcx+256], r11 + pop r13 + pop r12 + ret +sp_2048_mul_d_avx2_32 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_2048_word_asm_32 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_2048_word_asm_32 ENDP +_text ENDS +ENDIF +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_2048_cmp_32 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+248] + mov r12, QWORD PTR [rdx+248] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+240] + mov r12, QWORD PTR [rdx+240] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+232] + mov r12, QWORD PTR [rdx+232] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+224] + mov r12, QWORD PTR [rdx+224] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+216] + mov r12, QWORD PTR [rdx+216] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+208] + mov r12, QWORD PTR [rdx+208] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+200] + mov r12, QWORD PTR [rdx+200] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+192] + mov r12, QWORD PTR [rdx+192] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+184] + mov r12, QWORD PTR [rdx+184] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+176] + mov r12, QWORD PTR [rdx+176] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+168] + mov r12, QWORD PTR [rdx+168] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+160] + mov r12, QWORD PTR [rdx+160] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+152] + mov r12, QWORD PTR [rdx+152] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+144] + mov r12, QWORD PTR [rdx+144] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+136] + mov r12, QWORD PTR [rdx+136] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+128] + mov r12, QWORD PTR [rdx+128] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+120] + mov r12, QWORD PTR [rdx+120] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+112] + mov r12, QWORD PTR [rdx+112] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+104] + mov r12, QWORD PTR [rdx+104] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+96] + mov r12, QWORD PTR [rdx+96] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+88] + mov r12, QWORD PTR [rdx+88] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+80] + mov r12, QWORD PTR [rdx+80] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+72] + mov r12, QWORD PTR [rdx+72] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+64] + mov r12, QWORD PTR [rdx+64] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+56] + mov r12, QWORD PTR [rdx+56] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+48] + mov r12, QWORD PTR [rdx+48] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_2048_cmp_32 ENDP +_text ENDS +; /* Sub b from a into r. (r = a - b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_sub_32 PROC + mov r9, QWORD PTR [rdx] + xor rax, rax + sub r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + sbb r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + sbb r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + sbb r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + sbb r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + sbb r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + sbb r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + sbb r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + sbb r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + sbb r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + sbb r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + sbb r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + sbb r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + sbb r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + sbb r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + sbb r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + sbb r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + sbb r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + sbb r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + sbb r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + sbb r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + sbb r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + sbb r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + sbb r10, QWORD PTR [r8+184] + mov r9, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r10 + sbb r9, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r9 + sbb r10, QWORD PTR [r8+200] + mov r9, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r10 + sbb r9, QWORD PTR [r8+208] + mov r10, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r9 + sbb r10, QWORD PTR [r8+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r10 + sbb r9, QWORD PTR [r8+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r9 + sbb r10, QWORD PTR [r8+232] + mov r9, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r10 + sbb r9, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r9 + sbb r10, QWORD PTR [r8+248] + mov QWORD PTR [rcx+248], r10 + sbb rax, 0 + ret +sp_2048_sub_32 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 2048 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_2048_mont_reduce_avx2_32 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r9, rcx + mov r10, rdx + xor rbp, rbp + ; i = 32 + mov r11, 32 + mov r15, QWORD PTR [r9] + mov rdi, QWORD PTR [r9+8] + mov rsi, QWORD PTR [r9+16] + mov rbx, QWORD PTR [r9+24] + add r9, 128 + xor rbp, rbp +L_2048_mont_loop_avx2_32: + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-96] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-88] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-88], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9+-72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-80], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9+-64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-72], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+-56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-64], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+-48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-56], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+-40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-48], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+-32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-40], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+-24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-32], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+-16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-24], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+-8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-16], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-8], r13 + ; a[i+16] += m[16] * mu + mulx rcx, rax, QWORD PTR [r10+128] + mov r13, QWORD PTR [r9+8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9], r12 + ; a[i+17] += m[17] * mu + mulx rcx, rax, QWORD PTR [r10+136] + mov r12, QWORD PTR [r9+16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+8], r13 + ; a[i+18] += m[18] * mu + mulx rcx, rax, QWORD PTR [r10+144] + mov r13, QWORD PTR [r9+24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+16], r12 + ; a[i+19] += m[19] * mu + mulx rcx, rax, QWORD PTR [r10+152] + mov r12, QWORD PTR [r9+32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+24], r13 + ; a[i+20] += m[20] * mu + mulx rcx, rax, QWORD PTR [r10+160] + mov r13, QWORD PTR [r9+40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+32], r12 + ; a[i+21] += m[21] * mu + mulx rcx, rax, QWORD PTR [r10+168] + mov r12, QWORD PTR [r9+48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+40], r13 + ; a[i+22] += m[22] * mu + mulx rcx, rax, QWORD PTR [r10+176] + mov r13, QWORD PTR [r9+56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+48], r12 + ; a[i+23] += m[23] * mu + mulx rcx, rax, QWORD PTR [r10+184] + mov r12, QWORD PTR [r9+64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+56], r13 + ; a[i+24] += m[24] * mu + mulx rcx, rax, QWORD PTR [r10+192] + mov r13, QWORD PTR [r9+72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+64], r12 + ; a[i+25] += m[25] * mu + mulx rcx, rax, QWORD PTR [r10+200] + mov r12, QWORD PTR [r9+80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+72], r13 + ; a[i+26] += m[26] * mu + mulx rcx, rax, QWORD PTR [r10+208] + mov r13, QWORD PTR [r9+88] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+80], r12 + ; a[i+27] += m[27] * mu + mulx rcx, rax, QWORD PTR [r10+216] + mov r12, QWORD PTR [r9+96] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+88], r13 + ; a[i+28] += m[28] * mu + mulx rcx, rax, QWORD PTR [r10+224] + mov r13, QWORD PTR [r9+104] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+96], r12 + ; a[i+29] += m[29] * mu + mulx rcx, rax, QWORD PTR [r10+232] + mov r12, QWORD PTR [r9+112] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+104], r13 + ; a[i+30] += m[30] * mu + mulx rcx, rax, QWORD PTR [r10+240] + mov r13, QWORD PTR [r9+120] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+112], r12 + ; a[i+31] += m[31] * mu + mulx rcx, rax, QWORD PTR [r10+248] + mov r12, QWORD PTR [r9+128] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+120], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+128], r12 + adox rbp, r14 + adcx rbp, r14 + ; a += 1 + add r9, 8 + ; i -= 1 + sub r11, 1 + jnz L_2048_mont_loop_avx2_32 + sub r9, 128 + neg rbp + mov r8, r9 + sub r9, 256 + mov rcx, QWORD PTR [r10] + mov rdx, r15 + pext rcx, rcx, rbp + sub rdx, rcx + mov rcx, QWORD PTR [r10+8] + mov rax, rdi + pext rcx, rcx, rbp + mov QWORD PTR [r9], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+16] + mov rcx, rsi + pext rdx, rdx, rbp + mov QWORD PTR [r9+8], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+24] + mov rdx, rbx + pext rax, rax, rbp + mov QWORD PTR [r9+16], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+32] + mov rax, QWORD PTR [r8+32] + pext rcx, rcx, rbp + mov QWORD PTR [r9+24], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+40] + mov rcx, QWORD PTR [r8+40] + pext rdx, rdx, rbp + mov QWORD PTR [r9+32], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+48] + mov rdx, QWORD PTR [r8+48] + pext rax, rax, rbp + mov QWORD PTR [r9+40], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+56] + mov rax, QWORD PTR [r8+56] + pext rcx, rcx, rbp + mov QWORD PTR [r9+48], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+64] + mov rcx, QWORD PTR [r8+64] + pext rdx, rdx, rbp + mov QWORD PTR [r9+56], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+72] + mov rdx, QWORD PTR [r8+72] + pext rax, rax, rbp + mov QWORD PTR [r9+64], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+80] + mov rax, QWORD PTR [r8+80] + pext rcx, rcx, rbp + mov QWORD PTR [r9+72], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+88] + mov rcx, QWORD PTR [r8+88] + pext rdx, rdx, rbp + mov QWORD PTR [r9+80], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+96] + mov rdx, QWORD PTR [r8+96] + pext rax, rax, rbp + mov QWORD PTR [r9+88], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+104] + mov rax, QWORD PTR [r8+104] + pext rcx, rcx, rbp + mov QWORD PTR [r9+96], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+112] + mov rcx, QWORD PTR [r8+112] + pext rdx, rdx, rbp + mov QWORD PTR [r9+104], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+120] + mov rdx, QWORD PTR [r8+120] + pext rax, rax, rbp + mov QWORD PTR [r9+112], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+128] + mov rax, QWORD PTR [r8+128] + pext rcx, rcx, rbp + mov QWORD PTR [r9+120], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+136] + mov rcx, QWORD PTR [r8+136] + pext rdx, rdx, rbp + mov QWORD PTR [r9+128], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+144] + mov rdx, QWORD PTR [r8+144] + pext rax, rax, rbp + mov QWORD PTR [r9+136], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+152] + mov rax, QWORD PTR [r8+152] + pext rcx, rcx, rbp + mov QWORD PTR [r9+144], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+160] + mov rcx, QWORD PTR [r8+160] + pext rdx, rdx, rbp + mov QWORD PTR [r9+152], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+168] + mov rdx, QWORD PTR [r8+168] + pext rax, rax, rbp + mov QWORD PTR [r9+160], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+176] + mov rax, QWORD PTR [r8+176] + pext rcx, rcx, rbp + mov QWORD PTR [r9+168], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+184] + mov rcx, QWORD PTR [r8+184] + pext rdx, rdx, rbp + mov QWORD PTR [r9+176], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+192] + mov rdx, QWORD PTR [r8+192] + pext rax, rax, rbp + mov QWORD PTR [r9+184], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+200] + mov rax, QWORD PTR [r8+200] + pext rcx, rcx, rbp + mov QWORD PTR [r9+192], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+208] + mov rcx, QWORD PTR [r8+208] + pext rdx, rdx, rbp + mov QWORD PTR [r9+200], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+216] + mov rdx, QWORD PTR [r8+216] + pext rax, rax, rbp + mov QWORD PTR [r9+208], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+224] + mov rax, QWORD PTR [r8+224] + pext rcx, rcx, rbp + mov QWORD PTR [r9+216], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+232] + mov rcx, QWORD PTR [r8+232] + pext rdx, rdx, rbp + mov QWORD PTR [r9+224], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+240] + mov rdx, QWORD PTR [r8+240] + pext rax, rax, rbp + mov QWORD PTR [r9+232], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+248] + mov rax, QWORD PTR [r8+248] + pext rcx, rcx, rbp + mov QWORD PTR [r9+240], rdx + sbb rax, rcx + mov QWORD PTR [r9+248], rax + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_2048_mont_reduce_avx2_32 ENDP +_text ENDS +ENDIF +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_2048_cond_add_16 PROC + sub rsp, 128 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + add r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + adc r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + adc r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + adc r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + adc r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + adc r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + adc r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + adc r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + adc r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + adc r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + adc r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + adc r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + adc r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + adc r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + adc r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + adc r11, r8 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + adc rax, 0 + add rsp, 128 + ret +sp_2048_cond_add_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_2048_cond_add_avx2_16 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + add r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + adc r10, r11 + mov QWORD PTR [rcx+120], r10 + adc rax, 0 + pop r12 + ret +sp_2048_cond_add_avx2_16 ENDP +_text ENDS +ENDIF +; /* Shift number left by n bit. (r = a << n) +; * +; * r Result of left shift by n. +; * a Number to shift. +; * n Amoutnt o shift. +; */ +_text SEGMENT READONLY PARA +sp_2048_lshift_32 PROC + push r12 + push r13 + mov r9, rcx + mov rcx, r8 + mov r12, 0 + mov r13, QWORD PTR [rdx+216] + mov rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rdx+232] + mov r10, QWORD PTR [rdx+240] + mov r11, QWORD PTR [rdx+248] + shld r12, r11, cl + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+224], rax + mov QWORD PTR [r9+232], r8 + mov QWORD PTR [r9+240], r10 + mov QWORD PTR [r9+248], r11 + mov QWORD PTR [r9+256], r12 + mov r11, QWORD PTR [rdx+184] + mov rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rdx+200] + mov r10, QWORD PTR [rdx+208] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+192], rax + mov QWORD PTR [r9+200], r8 + mov QWORD PTR [r9+208], r10 + mov QWORD PTR [r9+216], r13 + mov r13, QWORD PTR [rdx+152] + mov rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rdx+168] + mov r10, QWORD PTR [rdx+176] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+160], rax + mov QWORD PTR [r9+168], r8 + mov QWORD PTR [r9+176], r10 + mov QWORD PTR [r9+184], r11 + mov r11, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rdx+136] + mov r10, QWORD PTR [rdx+144] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+128], rax + mov QWORD PTR [r9+136], r8 + mov QWORD PTR [r9+144], r10 + mov QWORD PTR [r9+152], r13 + mov r13, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+96], rax + mov QWORD PTR [r9+104], r8 + mov QWORD PTR [r9+112], r10 + mov QWORD PTR [r9+120], r11 + mov r11, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+64], rax + mov QWORD PTR [r9+72], r8 + mov QWORD PTR [r9+80], r10 + mov QWORD PTR [r9+88], r13 + mov r13, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+32], rax + mov QWORD PTR [r9+40], r8 + mov QWORD PTR [r9+48], r10 + mov QWORD PTR [r9+56], r11 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shl rax, cl + mov QWORD PTR [r9], rax + mov QWORD PTR [r9+8], r8 + mov QWORD PTR [r9+16], r10 + mov QWORD PTR [r9+24], r13 + pop r13 + pop r12 + ret +sp_2048_lshift_32 ENDP +_text ENDS +ENDIF +ENDIF +IFNDEF WOLFSSL_SP_NO_3072 +IFNDEF WOLFSSL_SP_NO_3072 +; /* Read big endian unsigned byte array into r. +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_3072_from_bin_bswap PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 384 + xor r13, r13 + jmp L_3072_from_bin_bswap_64_end +L_3072_from_bin_bswap_64_start: + sub r11, 64 + mov rax, QWORD PTR [r11+56] + mov r10, QWORD PTR [r11+48] + bswap rax + bswap r10 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [r11+40] + mov r10, QWORD PTR [r11+32] + bswap rax + bswap r10 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [r11+24] + mov r10, QWORD PTR [r11+16] + bswap rax + bswap r10 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [r11+8] + mov r10, QWORD PTR [r11] + bswap rax + bswap r10 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_3072_from_bin_bswap_64_end: + cmp r9, 63 + jg L_3072_from_bin_bswap_64_start + jmp L_3072_from_bin_bswap_8_end +L_3072_from_bin_bswap_8_start: + sub r11, 8 + mov rax, QWORD PTR [r11] + bswap rax + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_3072_from_bin_bswap_8_end: + cmp r9, 7 + jg L_3072_from_bin_bswap_8_start + cmp r9, r13 + je L_3072_from_bin_bswap_hi_end + mov r10, r13 + mov rax, r13 +L_3072_from_bin_bswap_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_3072_from_bin_bswap_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_3072_from_bin_bswap_hi_end: + cmp rcx, r12 + je L_3072_from_bin_bswap_zero_end +L_3072_from_bin_bswap_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_3072_from_bin_bswap_zero_start +L_3072_from_bin_bswap_zero_end: + pop r13 + pop r12 + ret +sp_3072_from_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Read big endian unsigned byte array into r. +; * Uses the movbe instruction which is an optional instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_3072_from_bin_movbe PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 384 + xor r13, r13 + jmp L_3072_from_bin_movbe_64_end +L_3072_from_bin_movbe_64_start: + sub r11, 64 + movbe rax, QWORD PTR [r11+56] + movbe r10, QWORD PTR [r11+48] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + movbe rax, QWORD PTR [r11+40] + movbe r10, QWORD PTR [r11+32] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + movbe rax, QWORD PTR [r11+24] + movbe r10, QWORD PTR [r11+16] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + movbe rax, QWORD PTR [r11+8] + movbe r10, QWORD PTR [r11] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_3072_from_bin_movbe_64_end: + cmp r9, 63 + jg L_3072_from_bin_movbe_64_start + jmp L_3072_from_bin_movbe_8_end +L_3072_from_bin_movbe_8_start: + sub r11, 8 + movbe rax, QWORD PTR [r11] + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_3072_from_bin_movbe_8_end: + cmp r9, 7 + jg L_3072_from_bin_movbe_8_start + cmp r9, r13 + je L_3072_from_bin_movbe_hi_end + mov r10, r13 + mov rax, r13 +L_3072_from_bin_movbe_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_3072_from_bin_movbe_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_3072_from_bin_movbe_hi_end: + cmp rcx, r12 + je L_3072_from_bin_movbe_zero_end +L_3072_from_bin_movbe_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_3072_from_bin_movbe_zero_start +L_3072_from_bin_movbe_zero_end: + pop r13 + pop r12 + ret +sp_3072_from_bin_movbe ENDP +_text ENDS +ENDIF +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 384 +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_3072_to_bin_bswap PROC + mov rax, QWORD PTR [rcx+376] + mov r8, QWORD PTR [rcx+368] + bswap rax + bswap r8 + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + mov rax, QWORD PTR [rcx+360] + mov r8, QWORD PTR [rcx+352] + bswap rax + bswap r8 + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + mov rax, QWORD PTR [rcx+344] + mov r8, QWORD PTR [rcx+336] + bswap rax + bswap r8 + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + mov rax, QWORD PTR [rcx+328] + mov r8, QWORD PTR [rcx+320] + bswap rax + bswap r8 + mov QWORD PTR [rdx+48], rax + mov QWORD PTR [rdx+56], r8 + mov rax, QWORD PTR [rcx+312] + mov r8, QWORD PTR [rcx+304] + bswap rax + bswap r8 + mov QWORD PTR [rdx+64], rax + mov QWORD PTR [rdx+72], r8 + mov rax, QWORD PTR [rcx+296] + mov r8, QWORD PTR [rcx+288] + bswap rax + bswap r8 + mov QWORD PTR [rdx+80], rax + mov QWORD PTR [rdx+88], r8 + mov rax, QWORD PTR [rcx+280] + mov r8, QWORD PTR [rcx+272] + bswap rax + bswap r8 + mov QWORD PTR [rdx+96], rax + mov QWORD PTR [rdx+104], r8 + mov rax, QWORD PTR [rcx+264] + mov r8, QWORD PTR [rcx+256] + bswap rax + bswap r8 + mov QWORD PTR [rdx+112], rax + mov QWORD PTR [rdx+120], r8 + mov rax, QWORD PTR [rcx+248] + mov r8, QWORD PTR [rcx+240] + bswap rax + bswap r8 + mov QWORD PTR [rdx+128], rax + mov QWORD PTR [rdx+136], r8 + mov rax, QWORD PTR [rcx+232] + mov r8, QWORD PTR [rcx+224] + bswap rax + bswap r8 + mov QWORD PTR [rdx+144], rax + mov QWORD PTR [rdx+152], r8 + mov rax, QWORD PTR [rcx+216] + mov r8, QWORD PTR [rcx+208] + bswap rax + bswap r8 + mov QWORD PTR [rdx+160], rax + mov QWORD PTR [rdx+168], r8 + mov rax, QWORD PTR [rcx+200] + mov r8, QWORD PTR [rcx+192] + bswap rax + bswap r8 + mov QWORD PTR [rdx+176], rax + mov QWORD PTR [rdx+184], r8 + mov rax, QWORD PTR [rcx+184] + mov r8, QWORD PTR [rcx+176] + bswap rax + bswap r8 + mov QWORD PTR [rdx+192], rax + mov QWORD PTR [rdx+200], r8 + mov rax, QWORD PTR [rcx+168] + mov r8, QWORD PTR [rcx+160] + bswap rax + bswap r8 + mov QWORD PTR [rdx+208], rax + mov QWORD PTR [rdx+216], r8 + mov rax, QWORD PTR [rcx+152] + mov r8, QWORD PTR [rcx+144] + bswap rax + bswap r8 + mov QWORD PTR [rdx+224], rax + mov QWORD PTR [rdx+232], r8 + mov rax, QWORD PTR [rcx+136] + mov r8, QWORD PTR [rcx+128] + bswap rax + bswap r8 + mov QWORD PTR [rdx+240], rax + mov QWORD PTR [rdx+248], r8 + mov rax, QWORD PTR [rcx+120] + mov r8, QWORD PTR [rcx+112] + bswap rax + bswap r8 + mov QWORD PTR [rdx+256], rax + mov QWORD PTR [rdx+264], r8 + mov rax, QWORD PTR [rcx+104] + mov r8, QWORD PTR [rcx+96] + bswap rax + bswap r8 + mov QWORD PTR [rdx+272], rax + mov QWORD PTR [rdx+280], r8 + mov rax, QWORD PTR [rcx+88] + mov r8, QWORD PTR [rcx+80] + bswap rax + bswap r8 + mov QWORD PTR [rdx+288], rax + mov QWORD PTR [rdx+296], r8 + mov rax, QWORD PTR [rcx+72] + mov r8, QWORD PTR [rcx+64] + bswap rax + bswap r8 + mov QWORD PTR [rdx+304], rax + mov QWORD PTR [rdx+312], r8 + mov rax, QWORD PTR [rcx+56] + mov r8, QWORD PTR [rcx+48] + bswap rax + bswap r8 + mov QWORD PTR [rdx+320], rax + mov QWORD PTR [rdx+328], r8 + mov rax, QWORD PTR [rcx+40] + mov r8, QWORD PTR [rcx+32] + bswap rax + bswap r8 + mov QWORD PTR [rdx+336], rax + mov QWORD PTR [rdx+344], r8 + mov rax, QWORD PTR [rcx+24] + mov r8, QWORD PTR [rcx+16] + bswap rax + bswap r8 + mov QWORD PTR [rdx+352], rax + mov QWORD PTR [rdx+360], r8 + mov rax, QWORD PTR [rcx+8] + mov r8, QWORD PTR [rcx] + bswap rax + bswap r8 + mov QWORD PTR [rdx+368], rax + mov QWORD PTR [rdx+376], r8 + ret +sp_3072_to_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 384 +; * Uses the movbe instruction which is optional. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_3072_to_bin_movbe PROC + movbe rax, QWORD PTR [rcx+376] + movbe r8, QWORD PTR [rcx+368] + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + movbe rax, QWORD PTR [rcx+360] + movbe r8, QWORD PTR [rcx+352] + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + movbe rax, QWORD PTR [rcx+344] + movbe r8, QWORD PTR [rcx+336] + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + movbe rax, QWORD PTR [rcx+328] + movbe r8, QWORD PTR [rcx+320] + mov QWORD PTR [rdx+48], rax + mov QWORD PTR [rdx+56], r8 + movbe rax, QWORD PTR [rcx+312] + movbe r8, QWORD PTR [rcx+304] + mov QWORD PTR [rdx+64], rax + mov QWORD PTR [rdx+72], r8 + movbe rax, QWORD PTR [rcx+296] + movbe r8, QWORD PTR [rcx+288] + mov QWORD PTR [rdx+80], rax + mov QWORD PTR [rdx+88], r8 + movbe rax, QWORD PTR [rcx+280] + movbe r8, QWORD PTR [rcx+272] + mov QWORD PTR [rdx+96], rax + mov QWORD PTR [rdx+104], r8 + movbe rax, QWORD PTR [rcx+264] + movbe r8, QWORD PTR [rcx+256] + mov QWORD PTR [rdx+112], rax + mov QWORD PTR [rdx+120], r8 + movbe rax, QWORD PTR [rcx+248] + movbe r8, QWORD PTR [rcx+240] + mov QWORD PTR [rdx+128], rax + mov QWORD PTR [rdx+136], r8 + movbe rax, QWORD PTR [rcx+232] + movbe r8, QWORD PTR [rcx+224] + mov QWORD PTR [rdx+144], rax + mov QWORD PTR [rdx+152], r8 + movbe rax, QWORD PTR [rcx+216] + movbe r8, QWORD PTR [rcx+208] + mov QWORD PTR [rdx+160], rax + mov QWORD PTR [rdx+168], r8 + movbe rax, QWORD PTR [rcx+200] + movbe r8, QWORD PTR [rcx+192] + mov QWORD PTR [rdx+176], rax + mov QWORD PTR [rdx+184], r8 + movbe rax, QWORD PTR [rcx+184] + movbe r8, QWORD PTR [rcx+176] + mov QWORD PTR [rdx+192], rax + mov QWORD PTR [rdx+200], r8 + movbe rax, QWORD PTR [rcx+168] + movbe r8, QWORD PTR [rcx+160] + mov QWORD PTR [rdx+208], rax + mov QWORD PTR [rdx+216], r8 + movbe rax, QWORD PTR [rcx+152] + movbe r8, QWORD PTR [rcx+144] + mov QWORD PTR [rdx+224], rax + mov QWORD PTR [rdx+232], r8 + movbe rax, QWORD PTR [rcx+136] + movbe r8, QWORD PTR [rcx+128] + mov QWORD PTR [rdx+240], rax + mov QWORD PTR [rdx+248], r8 + movbe rax, QWORD PTR [rcx+120] + movbe r8, QWORD PTR [rcx+112] + mov QWORD PTR [rdx+256], rax + mov QWORD PTR [rdx+264], r8 + movbe rax, QWORD PTR [rcx+104] + movbe r8, QWORD PTR [rcx+96] + mov QWORD PTR [rdx+272], rax + mov QWORD PTR [rdx+280], r8 + movbe rax, QWORD PTR [rcx+88] + movbe r8, QWORD PTR [rcx+80] + mov QWORD PTR [rdx+288], rax + mov QWORD PTR [rdx+296], r8 + movbe rax, QWORD PTR [rcx+72] + movbe r8, QWORD PTR [rcx+64] + mov QWORD PTR [rdx+304], rax + mov QWORD PTR [rdx+312], r8 + movbe rax, QWORD PTR [rcx+56] + movbe r8, QWORD PTR [rcx+48] + mov QWORD PTR [rdx+320], rax + mov QWORD PTR [rdx+328], r8 + movbe rax, QWORD PTR [rcx+40] + movbe r8, QWORD PTR [rcx+32] + mov QWORD PTR [rdx+336], rax + mov QWORD PTR [rdx+344], r8 + movbe rax, QWORD PTR [rcx+24] + movbe r8, QWORD PTR [rcx+16] + mov QWORD PTR [rdx+352], rax + mov QWORD PTR [rdx+360], r8 + movbe rax, QWORD PTR [rcx+8] + movbe r8, QWORD PTR [rcx] + mov QWORD PTR [rdx+368], rax + mov QWORD PTR [rdx+376], r8 + ret +sp_3072_to_bin_movbe ENDP +_text ENDS +ENDIF +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_12 PROC + push r12 + mov r9, rdx + sub rsp, 96 + ; A[0] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9] + xor r12, r12 + mov QWORD PTR [rsp], rax + mov r11, rdx + ; A[0] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+8], r11 + ; A[0] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+16], r12 + ; A[0] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+24], r10 + ; A[0] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+32], r11 + ; A[0] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+40], r12 + ; A[0] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+48], r10 + ; A[0] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+56], r11 + ; A[0] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+64], r12 + ; A[0] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+72], r10 + ; A[0] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+80], r11 + ; A[0] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+88], r12 + ; A[1] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+8] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+96], r10 + ; A[2] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+16] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+104], r11 + ; A[3] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+24] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+112], r12 + ; A[4] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+32] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+120], r10 + ; A[5] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+40] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+128], r11 + ; A[6] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+48] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+136], r12 + ; A[7] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+56] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+144], r10 + ; A[8] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+64] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+152], r11 + ; A[9] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+72] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+160], r12 + ; A[10] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+80] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+168], r10 + ; A[11] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + mov QWORD PTR [rcx+176], r11 + mov QWORD PTR [rcx+184], r12 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r10, QWORD PTR [rsp+16] + mov r11, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov r10, QWORD PTR [rsp+48] + mov r11, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rsp+64] + mov rdx, QWORD PTR [rsp+72] + mov r10, QWORD PTR [rsp+80] + mov r11, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], rdx + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + add rsp, 96 + pop r12 + ret +sp_3072_mul_12 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sqr_12 PROC + push r12 + push r13 + push r14 + mov r8, rdx + sub rsp, 96 + ; A[0] * A[0] + mov rax, QWORD PTR [r8] + mul rax + xor r11, r11 + mov QWORD PTR [rsp], rax + mov r10, rdx + ; A[0] * A[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+8], r10 + ; A[0] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[1] * A[1] + mov rax, QWORD PTR [r8+8] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rsp+16], r11 + ; A[0] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[1] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8+8] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+24], r9 + ; A[0] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[1] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+8] + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[2] * A[2] + mov rax, QWORD PTR [r8+16] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+32], r10 + ; A[0] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+40], r11 + ; A[0] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[3] + mov rax, QWORD PTR [r8+24] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+48], r9 + ; A[0] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+56], r10 + ; A[0] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[4] + mov rax, QWORD PTR [r8+32] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+64], r11 + ; A[0] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+72], r9 + ; A[0] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[5] + mov rax, QWORD PTR [r8+40] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+80], r10 + ; A[0] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+88], r11 + ; A[1] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[2] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[6] + mov rax, QWORD PTR [r8+48] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+96], r9 + ; A[2] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+16] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[3] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+104], r10 + ; A[3] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+24] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[4] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[7] + mov rax, QWORD PTR [r8+56] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+112], r11 + ; A[4] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+32] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[5] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+120], r9 + ; A[5] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+40] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[6] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[8] + mov rax, QWORD PTR [r8+64] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+128], r10 + ; A[6] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+48] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[7] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+136], r11 + ; A[7] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+56] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[8] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+64] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[9] * A[9] + mov rax, QWORD PTR [r8+72] + mul rax + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+144], r9 + ; A[8] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+64] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[9] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+72] + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rcx+152], r10 + ; A[9] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+72] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[10] * A[10] + mov rax, QWORD PTR [r8+80] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+160], r11 + ; A[10] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+80] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+168], r9 + ; A[11] * A[11] + mov rax, QWORD PTR [r8+88] + mul rax + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+176], r10 + mov QWORD PTR [rcx+184], r11 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r12, QWORD PTR [rsp+16] + mov r13, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov r12, QWORD PTR [rsp+48] + mov r13, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + mov QWORD PTR [rcx+48], r12 + mov QWORD PTR [rcx+56], r13 + mov rax, QWORD PTR [rsp+64] + mov rdx, QWORD PTR [rsp+72] + mov r12, QWORD PTR [rsp+80] + mov r13, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], rdx + mov QWORD PTR [rcx+80], r12 + mov QWORD PTR [rcx+88], r13 + add rsp, 96 + pop r14 + pop r13 + pop r12 + ret +sp_3072_sqr_12 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r Result of multiplication. +; * a First number to multiply. +; * b Second number to multiply. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_avx2_12 PROC + push rbx + push rbp + push r12 + push r13 + push r14 + mov rbp, r8 + mov r8, rcx + mov r9, rdx + sub rsp, 96 + cmp r9, r8 + mov rbx, rsp + cmovne rbx, r8 + cmp rbp, r8 + cmove rbx, rsp + add r8, 96 + xor r14, r14 + mov rdx, QWORD PTR [r9] + ; A[0] * B[0] + mulx r11, r10, QWORD PTR [rbp] + ; A[0] * B[1] + mulx r12, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx], r10 + adcx r11, rax + mov QWORD PTR [rbx+8], r11 + ; A[0] * B[2] + mulx r10, rax, QWORD PTR [rbp+16] + adcx r12, rax + ; A[0] * B[3] + mulx r11, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+16], r12 + adcx r10, rax + mov QWORD PTR [rbx+24], r10 + ; A[0] * B[4] + mulx r12, rax, QWORD PTR [rbp+32] + adcx r11, rax + ; A[0] * B[5] + mulx r10, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+32], r11 + adcx r12, rax + mov QWORD PTR [rbx+40], r12 + ; A[0] * B[6] + mulx r11, rax, QWORD PTR [rbp+48] + adcx r10, rax + ; A[0] * B[7] + mulx r12, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+48], r10 + adcx r11, rax + mov QWORD PTR [rbx+56], r11 + ; A[0] * B[8] + mulx r10, rax, QWORD PTR [rbp+64] + adcx r12, rax + ; A[0] * B[9] + mulx r11, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+64], r12 + adcx r10, rax + mov QWORD PTR [rbx+72], r10 + ; A[0] * B[10] + mulx r12, rax, QWORD PTR [rbp+80] + adcx r11, rax + ; A[0] * B[11] + mulx r10, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+80], r11 + adcx r12, rax + adcx r10, r14 + mov r13, r14 + adcx r13, r14 + mov QWORD PTR [rbx+88], r12 + mov QWORD PTR [r8], r10 + mov rdx, QWORD PTR [r9+8] + mov r11, QWORD PTR [rbx+8] + mov r12, QWORD PTR [rbx+16] + mov r10, QWORD PTR [rbx+24] + ; A[1] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[1] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+8], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+16], r12 + mov r11, QWORD PTR [rbx+32] + mov r12, QWORD PTR [rbx+40] + ; A[1] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r10, rax + adox r11, rcx + ; A[1] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+24], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+32], r11 + mov r10, QWORD PTR [rbx+48] + mov r11, QWORD PTR [rbx+56] + ; A[1] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r10, rcx + ; A[1] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+40], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+48], r10 + mov r12, QWORD PTR [rbx+64] + mov r10, QWORD PTR [rbx+72] + ; A[1] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r11, rax + adox r12, rcx + ; A[1] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+56], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+64], r12 + mov r11, QWORD PTR [rbx+80] + mov r12, QWORD PTR [rbx+88] + ; A[1] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[1] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+80], r11 + mov r10, QWORD PTR [r8] + ; A[1] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r12, rax + adox r10, rcx + ; A[1] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+88], r12 + mov r11, r14 + adcx r10, rax + adox r11, rcx + adcx r11, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8], r10 + mov QWORD PTR [r8+8], r11 + mov rdx, QWORD PTR [r9+16] + mov r12, QWORD PTR [rbx+16] + mov r10, QWORD PTR [rbx+24] + mov r11, QWORD PTR [rbx+32] + ; A[2] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r10, rcx + ; A[2] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+16], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+24], r10 + mov r12, QWORD PTR [rbx+40] + mov r10, QWORD PTR [rbx+48] + ; A[2] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r11, rax + adox r12, rcx + ; A[2] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+32], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+40], r12 + mov r11, QWORD PTR [rbx+56] + mov r12, QWORD PTR [rbx+64] + ; A[2] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[2] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+48], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+56], r11 + mov r10, QWORD PTR [rbx+72] + mov r11, QWORD PTR [rbx+80] + ; A[2] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r12, rax + adox r10, rcx + ; A[2] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+64], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+72], r10 + mov r12, QWORD PTR [rbx+88] + mov r10, QWORD PTR [r8] + ; A[2] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[2] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+80], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+88], r12 + mov r11, QWORD PTR [r8+8] + ; A[2] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r10, rax + adox r11, rcx + ; A[2] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8], r10 + mov r12, r14 + adcx r11, rax + adox r12, rcx + adcx r12, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+8], r11 + mov QWORD PTR [r8+16], r12 + mov rdx, QWORD PTR [r9+24] + mov r10, QWORD PTR [rbx+24] + mov r11, QWORD PTR [rbx+32] + mov r12, QWORD PTR [rbx+40] + ; A[3] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[3] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+24], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+32], r11 + mov r10, QWORD PTR [rbx+48] + mov r11, QWORD PTR [rbx+56] + ; A[3] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r12, rax + adox r10, rcx + ; A[3] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+40], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+48], r10 + mov r12, QWORD PTR [rbx+64] + mov r10, QWORD PTR [rbx+72] + ; A[3] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[3] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+56], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+64], r12 + mov r11, QWORD PTR [rbx+80] + mov r12, QWORD PTR [rbx+88] + ; A[3] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r10, rax + adox r11, rcx + ; A[3] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+80], r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[3] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r10, rcx + ; A[3] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+88], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + ; A[3] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r11, rax + adox r12, rcx + ; A[3] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+8], r11 + mov r10, r14 + adcx r12, rax + adox r10, rcx + adcx r10, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+16], r12 + mov QWORD PTR [r8+24], r10 + mov rdx, QWORD PTR [r9+32] + mov r11, QWORD PTR [rbx+32] + mov r12, QWORD PTR [rbx+40] + mov r10, QWORD PTR [rbx+48] + ; A[4] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[4] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+32], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+40], r12 + mov r11, QWORD PTR [rbx+56] + mov r12, QWORD PTR [rbx+64] + ; A[4] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r10, rax + adox r11, rcx + ; A[4] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+48], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+56], r11 + mov r10, QWORD PTR [rbx+72] + mov r11, QWORD PTR [rbx+80] + ; A[4] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r10, rcx + ; A[4] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+64], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+72], r10 + mov r12, QWORD PTR [rbx+88] + mov r10, QWORD PTR [r8] + ; A[4] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r11, rax + adox r12, rcx + ; A[4] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+80], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+88], r12 + mov r11, QWORD PTR [r8+8] + mov r12, QWORD PTR [r8+16] + ; A[4] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[4] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+24] + ; A[4] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r12, rax + adox r10, rcx + ; A[4] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+16], r12 + mov r11, r14 + adcx r10, rax + adox r11, rcx + adcx r11, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+24], r10 + mov QWORD PTR [r8+32], r11 + mov rdx, QWORD PTR [r9+40] + mov r12, QWORD PTR [rbx+40] + mov r10, QWORD PTR [rbx+48] + mov r11, QWORD PTR [rbx+56] + ; A[5] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r10, rcx + ; A[5] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+40], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+48], r10 + mov r12, QWORD PTR [rbx+64] + mov r10, QWORD PTR [rbx+72] + ; A[5] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r11, rax + adox r12, rcx + ; A[5] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+56], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+64], r12 + mov r11, QWORD PTR [rbx+80] + mov r12, QWORD PTR [rbx+88] + ; A[5] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[5] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+80], r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[5] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r12, rax + adox r10, rcx + ; A[5] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+88], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[5] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[5] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+8], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + ; A[5] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r10, rax + adox r11, rcx + ; A[5] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+24], r10 + mov r12, r14 + adcx r11, rax + adox r12, rcx + adcx r12, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+32], r11 + mov QWORD PTR [r8+40], r12 + mov rdx, QWORD PTR [r9+48] + mov r10, QWORD PTR [rbx+48] + mov r11, QWORD PTR [rbx+56] + mov r12, QWORD PTR [rbx+64] + ; A[6] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[6] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+48], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+56], r11 + mov r10, QWORD PTR [rbx+72] + mov r11, QWORD PTR [rbx+80] + ; A[6] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r12, rax + adox r10, rcx + ; A[6] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+64], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+72], r10 + mov r12, QWORD PTR [rbx+88] + mov r10, QWORD PTR [r8] + ; A[6] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[6] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+80], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+88], r12 + mov r11, QWORD PTR [r8+8] + mov r12, QWORD PTR [r8+16] + ; A[6] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r10, rax + adox r11, rcx + ; A[6] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+24] + mov r11, QWORD PTR [r8+32] + ; A[6] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r10, rcx + ; A[6] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+16], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r10 + mov r12, QWORD PTR [r8+40] + ; A[6] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r11, rax + adox r12, rcx + ; A[6] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+32], r11 + mov r10, r14 + adcx r12, rax + adox r10, rcx + adcx r10, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+40], r12 + mov QWORD PTR [r8+48], r10 + mov rdx, QWORD PTR [r9+56] + mov r11, QWORD PTR [rbx+56] + mov r12, QWORD PTR [rbx+64] + mov r10, QWORD PTR [rbx+72] + ; A[7] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[7] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+56], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+64], r12 + mov r11, QWORD PTR [rbx+80] + mov r12, QWORD PTR [rbx+88] + ; A[7] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r10, rax + adox r11, rcx + ; A[7] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+80], r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[7] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r10, rcx + ; A[7] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+88], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[7] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r11, rax + adox r12, rcx + ; A[7] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+8], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, QWORD PTR [r8+40] + ; A[7] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[7] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+24], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+32], r11 + mov r10, QWORD PTR [r8+48] + ; A[7] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r12, rax + adox r10, rcx + ; A[7] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+40], r12 + mov r11, r14 + adcx r10, rax + adox r11, rcx + adcx r11, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+48], r10 + mov QWORD PTR [r8+56], r11 + mov rdx, QWORD PTR [r9+64] + mov r12, QWORD PTR [rbx+64] + mov r10, QWORD PTR [rbx+72] + mov r11, QWORD PTR [rbx+80] + ; A[8] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r10, rcx + ; A[8] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+64], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+72], r10 + mov r12, QWORD PTR [rbx+88] + mov r10, QWORD PTR [r8] + ; A[8] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r11, rax + adox r12, rcx + ; A[8] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+80], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+88], r12 + mov r11, QWORD PTR [r8+8] + mov r12, QWORD PTR [r8+16] + ; A[8] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[8] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+24] + mov r11, QWORD PTR [r8+32] + ; A[8] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r12, rax + adox r10, rcx + ; A[8] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+16], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r10 + mov r12, QWORD PTR [r8+40] + mov r10, QWORD PTR [r8+48] + ; A[8] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[8] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+32], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+40], r12 + mov r11, QWORD PTR [r8+56] + ; A[8] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r10, rax + adox r11, rcx + ; A[8] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+48], r10 + mov r12, r14 + adcx r11, rax + adox r12, rcx + adcx r12, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+56], r11 + mov QWORD PTR [r8+64], r12 + mov rdx, QWORD PTR [r9+72] + mov r10, QWORD PTR [rbx+72] + mov r11, QWORD PTR [rbx+80] + mov r12, QWORD PTR [rbx+88] + ; A[9] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[9] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+80], r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[9] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r12, rax + adox r10, rcx + ; A[9] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+88], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[9] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[9] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+8], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, QWORD PTR [r8+40] + ; A[9] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r10, rax + adox r11, rcx + ; A[9] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+24], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+32], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[9] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r10, rcx + ; A[9] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+40], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+48], r10 + mov r12, QWORD PTR [r8+64] + ; A[9] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r11, rax + adox r12, rcx + ; A[9] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+56], r11 + mov r10, r14 + adcx r12, rax + adox r10, rcx + adcx r10, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+64], r12 + mov QWORD PTR [r8+72], r10 + mov rdx, QWORD PTR [r9+80] + mov r11, QWORD PTR [rbx+80] + mov r12, QWORD PTR [rbx+88] + mov r10, QWORD PTR [r8] + ; A[10] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[10] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+80], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbx+88], r12 + mov r11, QWORD PTR [r8+8] + mov r12, QWORD PTR [r8+16] + ; A[10] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r10, rax + adox r11, rcx + ; A[10] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [r8], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+24] + mov r11, QWORD PTR [r8+32] + ; A[10] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r10, rcx + ; A[10] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+16], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r10 + mov r12, QWORD PTR [r8+40] + mov r10, QWORD PTR [r8+48] + ; A[10] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r11, rax + adox r12, rcx + ; A[10] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+32], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+40], r12 + mov r11, QWORD PTR [r8+56] + mov r12, QWORD PTR [r8+64] + ; A[10] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[10] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+48], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+56], r11 + mov r10, QWORD PTR [r8+72] + ; A[10] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r12, rax + adox r10, rcx + ; A[10] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+64], r12 + mov r11, r14 + adcx r10, rax + adox r11, rcx + adcx r11, r13 + mov r13, r14 + adox r13, r14 + adcx r13, r14 + mov QWORD PTR [r8+72], r10 + mov QWORD PTR [r8+80], r11 + mov rdx, QWORD PTR [r9+88] + mov r12, QWORD PTR [rbx+88] + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[11] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r10, rcx + ; A[11] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+88], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[11] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + adcx r11, rax + adox r12, rcx + ; A[11] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [r8+8], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, QWORD PTR [r8+40] + ; A[11] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[11] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+24], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+32], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[11] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + adcx r12, rax + adox r10, rcx + ; A[11] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+40], r12 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+48], r10 + mov r12, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[11] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[11] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+56], r11 + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+64], r12 + mov r11, QWORD PTR [r8+80] + ; A[11] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + adcx r10, rax + adox r11, rcx + ; A[11] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+72], r10 + mov r12, r14 + adcx r11, rax + adox r12, rcx + adcx r12, r13 + mov QWORD PTR [r8+80], r11 + mov QWORD PTR [r8+88], r12 + sub r8, 96 + cmp r9, r8 + je L_start_3072_mul_avx2_12 + cmp rbp, r8 + jne L_end_3072_mul_avx2_12 +L_start_3072_mul_avx2_12: + vmovdqu xmm0, OWORD PTR [rbx] + vmovups OWORD PTR [r8], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+16] + vmovups OWORD PTR [r8+16], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+32] + vmovups OWORD PTR [r8+32], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+48] + vmovups OWORD PTR [r8+48], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+64] + vmovups OWORD PTR [r8+64], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+80] + vmovups OWORD PTR [r8+80], xmm0 +L_end_3072_mul_avx2_12: + add rsp, 96 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + ret +sp_3072_mul_avx2_12 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sqr_avx2_12 PROC + push rbp + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov r8, rcx + mov r9, rdx + sub rsp, 96 + cmp r9, r8 + mov rbp, rsp + cmovne rbp, r8 + add r8, 96 + xor r12, r12 + ; Diagonal 1 + ; A[1] x A[0] + mov rdx, QWORD PTR [r9] + mulx r11, r10, QWORD PTR [r9+8] + mov QWORD PTR [rbp+8], r10 + mov r10, r12 + ; A[2] x A[0] + mulx rcx, rax, QWORD PTR [r9+16] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [rbp+16], r11 + mov r11, r12 + ; A[3] x A[0] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+24], r10 + mov r10, r12 + ; A[4] x A[0] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [rbp+32], r11 + mov r11, r12 + ; A[5] x A[0] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+40], r10 + mov r10, r12 + ; A[6] x A[0] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [rbp+48], r11 + mov r11, r12 + ; A[7] x A[0] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov r14, r10 + mov r10, r12 + ; A[8] x A[0] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r10, rcx + mov r15, r11 + mov r11, r12 + ; A[9] x A[0] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov rdi, r10 + mov r10, r12 + ; A[10] x A[0] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r10, rcx + mov rsi, r11 + mov r11, r12 + ; A[11] x A[0] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r10, rax + adox r11, rcx + mov rbx, r10 + ; Carry + adcx r11, r12 + mov r13, r12 + adcx r13, r12 + adox r13, r12 + mov QWORD PTR [r8], r11 + ; Diagonal 2 + mov r11, QWORD PTR [rbp+24] + mov r10, QWORD PTR [rbp+32] + ; A[2] x A[1] + mov rdx, QWORD PTR [r9+8] + mulx rcx, rax, QWORD PTR [r9+16] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [rbp+24], r11 + mov r11, QWORD PTR [rbp+40] + ; A[3] x A[1] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+32], r10 + mov r10, QWORD PTR [rbp+48] + ; A[4] x A[1] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [rbp+40], r11 + ; No load %r12 - %r9 + ; A[5] x A[1] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r14, rcx + mov QWORD PTR [rbp+48], r10 + ; No load %r13 - %r8 + ; A[6] x A[1] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r14, rax + adox r15, rcx + ; No store %r12 + ; No load %r14 - %r9 + ; A[7] x A[1] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r15, rax + adox rdi, rcx + ; No store %r13 + ; No load %r15 - %r8 + ; A[8] x A[1] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rdi, rax + adox rsi, rcx + ; No store %r14 + ; No load %rbx - %r9 + ; A[9] x A[1] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rsi, rax + adox rbx, rcx + ; No store %r15 + mov r10, QWORD PTR [r8] + ; A[10] x A[1] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rbx, rax + adox r10, rcx + ; No store %rbx + mov r11, r12 + ; A[11] x A[1] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r10, r12 + ; A[11] x A[2] + mov rdx, QWORD PTR [r9+16] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + ; Carry + adcx r10, r13 + mov r13, r12 + adcx r13, r12 + adox r13, r12 + mov QWORD PTR [r8+16], r10 + ; Diagonal 3 + mov r10, QWORD PTR [rbp+40] + mov r11, QWORD PTR [rbp+48] + ; A[3] x A[2] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+40], r10 + ; No load %r12 - %r8 + ; A[4] x A[2] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r14, rcx + mov QWORD PTR [rbp+48], r11 + ; No load %r13 - %r9 + ; A[5] x A[2] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r14, rax + adox r15, rcx + ; No store %r12 + ; No load %r14 - %r8 + ; A[6] x A[2] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r15, rax + adox rdi, rcx + ; No store %r13 + ; No load %r15 - %r9 + ; A[7] x A[2] + mulx rcx, rax, QWORD PTR [r9+56] + adcx rdi, rax + adox rsi, rcx + ; No store %r14 + ; No load %rbx - %r8 + ; A[8] x A[2] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rsi, rax + adox rbx, rcx + ; No store %r15 + mov r11, QWORD PTR [r8] + ; A[9] x A[2] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rbx, rax + adox r11, rcx + ; No store %rbx + mov r10, QWORD PTR [r8+8] + ; A[10] x A[2] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8], r11 + mov r11, QWORD PTR [r8+16] + ; A[10] x A[3] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+8], r10 + mov r10, r12 + ; A[10] x A[4] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+16], r11 + mov r11, r12 + ; A[10] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r10 + ; Carry + adcx r11, r13 + mov r13, r12 + adcx r13, r12 + adox r13, r12 + mov QWORD PTR [r8+32], r11 + ; Diagonal 4 + ; No load %r12 - %r9 + ; No load %r13 - %r8 + ; A[4] x A[3] + mov rdx, QWORD PTR [r9+24] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r14, rax + adox r15, rcx + ; No store %r12 + ; No load %r14 - %r9 + ; A[5] x A[3] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r15, rax + adox rdi, rcx + ; No store %r13 + ; No load %r15 - %r8 + ; A[6] x A[3] + mulx rcx, rax, QWORD PTR [r9+48] + adcx rdi, rax + adox rsi, rcx + ; No store %r14 + ; No load %rbx - %r9 + ; A[7] x A[3] + mulx rcx, rax, QWORD PTR [r9+56] + adcx rsi, rax + adox rbx, rcx + ; No store %r15 + mov r10, QWORD PTR [r8] + ; A[8] x A[3] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rbx, rax + adox r10, rcx + ; No store %rbx + mov r11, QWORD PTR [r8+8] + ; A[9] x A[3] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r10, QWORD PTR [r8+16] + ; A[9] x A[4] + mov rdx, QWORD PTR [r9+72] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + mov r11, QWORD PTR [r8+24] + ; A[9] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+16], r10 + mov r10, QWORD PTR [r8+32] + ; A[9] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+24], r11 + mov r11, r12 + ; A[9] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+32], r10 + mov r10, r12 + ; A[9] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+40], r11 + ; Carry + adcx r10, r13 + mov r13, r12 + adcx r13, r12 + adox r13, r12 + mov QWORD PTR [r8+48], r10 + ; Diagonal 5 + ; No load %r14 - %r8 + ; No load %r15 - %r9 + ; A[5] x A[4] + mov rdx, QWORD PTR [r9+32] + mulx rcx, rax, QWORD PTR [r9+40] + adcx rdi, rax + adox rsi, rcx + ; No store %r14 + ; No load %rbx - %r8 + ; A[6] x A[4] + mulx rcx, rax, QWORD PTR [r9+48] + adcx rsi, rax + adox rbx, rcx + ; No store %r15 + mov r11, QWORD PTR [r8] + ; A[7] x A[4] + mulx rcx, rax, QWORD PTR [r9+56] + adcx rbx, rax + adox r11, rcx + ; No store %rbx + mov r10, QWORD PTR [r8+8] + ; A[8] x A[4] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8], r11 + mov r11, QWORD PTR [r8+16] + ; A[8] x A[5] + mov rdx, QWORD PTR [r9+64] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+8], r10 + mov r10, QWORD PTR [r8+24] + ; A[8] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+16], r11 + mov r11, QWORD PTR [r8+32] + ; A[8] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r10 + mov r10, QWORD PTR [r8+40] + ; A[10] x A[6] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+32], r11 + mov r11, QWORD PTR [r8+48] + ; A[10] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+40], r10 + mov r10, r12 + ; A[10] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+48], r11 + mov r11, r12 + ; A[10] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+56], r10 + ; Carry + adcx r11, r13 + mov r13, r12 + adcx r13, r12 + adox r13, r12 + mov QWORD PTR [r8+64], r11 + ; Diagonal 6 + ; No load %rbx - %r9 + mov r10, QWORD PTR [r8] + ; A[6] x A[5] + mov rdx, QWORD PTR [r9+40] + mulx rcx, rax, QWORD PTR [r9+48] + adcx rbx, rax + adox r10, rcx + ; No store %rbx + mov r11, QWORD PTR [r8+8] + ; A[7] x A[5] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8], r10 + mov r10, QWORD PTR [r8+16] + ; A[7] x A[6] + mov rdx, QWORD PTR [r9+48] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + mov r11, QWORD PTR [r8+24] + ; A[11] x A[3] + mov rdx, QWORD PTR [r9+88] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+16], r10 + mov r10, QWORD PTR [r8+32] + ; A[11] x A[4] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+24], r11 + mov r11, QWORD PTR [r8+40] + ; A[11] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+32], r10 + mov r10, QWORD PTR [r8+48] + ; A[11] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+40], r11 + mov r11, QWORD PTR [r8+56] + ; A[11] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+48], r10 + mov r10, QWORD PTR [r8+64] + ; A[11] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+56], r11 + mov r11, r12 + ; A[11] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+64], r10 + mov r10, r12 + ; A[11] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r10, rcx + mov QWORD PTR [r8+72], r11 + ; Carry + adcx r10, r13 + mov r13, r12 + adcx r13, r12 + adox r13, r12 + mov QWORD PTR [r8+80], r10 + mov QWORD PTR [r8+88], r13 + ; Double and Add in A[i] x A[i] + mov r11, QWORD PTR [rbp+8] + ; A[0] x A[0] + mov rdx, QWORD PTR [r9] + mulx rcx, rax, rdx + mov QWORD PTR [rbp], rax + adox r11, r11 + adcx r11, rcx + mov QWORD PTR [rbp+8], r11 + mov r10, QWORD PTR [rbp+16] + mov r11, QWORD PTR [rbp+24] + ; A[1] x A[1] + mov rdx, QWORD PTR [r9+8] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+16], r10 + mov QWORD PTR [rbp+24], r11 + mov r10, QWORD PTR [rbp+32] + mov r11, QWORD PTR [rbp+40] + ; A[2] x A[2] + mov rdx, QWORD PTR [r9+16] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+32], r10 + mov QWORD PTR [rbp+40], r11 + mov r10, QWORD PTR [rbp+48] + ; A[3] x A[3] + mov rdx, QWORD PTR [r9+24] + mulx rcx, rax, rdx + adox r10, r10 + adox r14, r14 + adcx r10, rax + adcx r14, rcx + mov QWORD PTR [rbp+48], r10 + ; A[4] x A[4] + mov rdx, QWORD PTR [r9+32] + mulx rcx, rax, rdx + adox r15, r15 + adox rdi, rdi + adcx r15, rax + adcx rdi, rcx + ; A[5] x A[5] + mov rdx, QWORD PTR [r9+40] + mulx rcx, rax, rdx + adox rsi, rsi + adox rbx, rbx + adcx rsi, rax + adcx rbx, rcx + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[6] x A[6] + mov rdx, QWORD PTR [r9+48] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8], r10 + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[7] x A[7] + mov rdx, QWORD PTR [r9+56] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+16], r10 + mov QWORD PTR [r8+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[8] x A[8] + mov rdx, QWORD PTR [r9+64] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+32], r10 + mov QWORD PTR [r8+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[9] x A[9] + mov rdx, QWORD PTR [r9+72] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+48], r10 + mov QWORD PTR [r8+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + ; A[10] x A[10] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+64], r10 + mov QWORD PTR [r8+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + ; A[11] x A[11] + mov rdx, QWORD PTR [r9+88] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+80], r10 + mov QWORD PTR [r8+88], r11 + mov QWORD PTR [r8+-40], r14 + mov QWORD PTR [r8+-32], r15 + mov QWORD PTR [r8+-24], rdi + mov QWORD PTR [r8+-16], rsi + mov QWORD PTR [r8+-8], rbx + sub r8, 96 + cmp r9, r8 + jne L_end_3072_sqr_avx2_12 + vmovdqu xmm0, OWORD PTR [rbp] + vmovups OWORD PTR [r8], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+16] + vmovups OWORD PTR [r8+16], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+32] + vmovups OWORD PTR [r8+32], xmm0 + mov rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+48], rax +L_end_3072_sqr_avx2_12: + add rsp, 96 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + ret +sp_3072_sqr_avx2_12 ENDP +_text ENDS +ENDIF +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_add_12 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov QWORD PTR [rcx+88], r10 + adc rax, 0 + ret +sp_3072_add_12 ENDP +_text ENDS +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sub_in_place_24 PROC + mov r8, QWORD PTR [rcx] + xor rax, rax + sub r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rcx+8] + mov QWORD PTR [rcx], r8 + sbb r9, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rcx+16] + mov QWORD PTR [rcx+8], r9 + sbb r8, QWORD PTR [rdx+16] + mov r9, QWORD PTR [rcx+24] + mov QWORD PTR [rcx+16], r8 + sbb r9, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rcx+32] + mov QWORD PTR [rcx+24], r9 + sbb r8, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rcx+40] + mov QWORD PTR [rcx+32], r8 + sbb r9, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rcx+48] + mov QWORD PTR [rcx+40], r9 + sbb r8, QWORD PTR [rdx+48] + mov r9, QWORD PTR [rcx+56] + mov QWORD PTR [rcx+48], r8 + sbb r9, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rcx+64] + mov QWORD PTR [rcx+56], r9 + sbb r8, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rcx+72] + mov QWORD PTR [rcx+64], r8 + sbb r9, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rcx+80] + mov QWORD PTR [rcx+72], r9 + sbb r8, QWORD PTR [rdx+80] + mov r9, QWORD PTR [rcx+88] + mov QWORD PTR [rcx+80], r8 + sbb r9, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rcx+96] + mov QWORD PTR [rcx+88], r9 + sbb r8, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rcx+104] + mov QWORD PTR [rcx+96], r8 + sbb r9, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rcx+112] + mov QWORD PTR [rcx+104], r9 + sbb r8, QWORD PTR [rdx+112] + mov r9, QWORD PTR [rcx+120] + mov QWORD PTR [rcx+112], r8 + sbb r9, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rcx+128] + mov QWORD PTR [rcx+120], r9 + sbb r8, QWORD PTR [rdx+128] + mov r9, QWORD PTR [rcx+136] + mov QWORD PTR [rcx+128], r8 + sbb r9, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rcx+144] + mov QWORD PTR [rcx+136], r9 + sbb r8, QWORD PTR [rdx+144] + mov r9, QWORD PTR [rcx+152] + mov QWORD PTR [rcx+144], r8 + sbb r9, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rcx+160] + mov QWORD PTR [rcx+152], r9 + sbb r8, QWORD PTR [rdx+160] + mov r9, QWORD PTR [rcx+168] + mov QWORD PTR [rcx+160], r8 + sbb r9, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rcx+176] + mov QWORD PTR [rcx+168], r9 + sbb r8, QWORD PTR [rdx+176] + mov r9, QWORD PTR [rcx+184] + mov QWORD PTR [rcx+176], r8 + sbb r9, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+184], r9 + sbb rax, 0 + ret +sp_3072_sub_in_place_24 ENDP +_text ENDS +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_add_24 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + adc r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + adc r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + adc r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + adc r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + adc r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + adc r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + adc r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + adc r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + adc r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + adc r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + adc r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + adc r10, QWORD PTR [r8+184] + mov QWORD PTR [rcx+184], r10 + adc rax, 0 + ret +sp_3072_add_24 ENDP +_text ENDS +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_24 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 616 + mov QWORD PTR [rsp+576], rcx + mov QWORD PTR [rsp+584], rdx + mov QWORD PTR [rsp+592], r8 + lea r12, QWORD PTR [rsp+384] + lea r14, QWORD PTR [rdx+96] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov QWORD PTR [r12+88], r10 + adc r15, 0 + mov QWORD PTR [rsp+600], r15 + lea r13, QWORD PTR [rsp+480] + lea r14, QWORD PTR [r8+96] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov QWORD PTR [r13+88], r10 + adc rdi, 0 + mov QWORD PTR [rsp+608], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_3072_mul_12 + mov r8, QWORD PTR [rsp+592] + mov rdx, QWORD PTR [rsp+584] + lea rcx, QWORD PTR [rsp+192] + add r8, 96 + add rdx, 96 + call sp_3072_mul_12 + mov r8, QWORD PTR [rsp+592] + mov rdx, QWORD PTR [rsp+584] + mov rcx, QWORD PTR [rsp+576] + call sp_3072_mul_12 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+592] + mov rdx, QWORD PTR [rsp+584] + mov rcx, QWORD PTR [rsp+576] +ENDIF + mov r15, QWORD PTR [rsp+600] + mov rdi, QWORD PTR [rsp+608] + mov rsi, QWORD PTR [rsp+576] + mov r11, r15 + lea r12, QWORD PTR [rsp+384] + lea r13, QWORD PTR [rsp+480] + and r11, rdi + neg r15 + neg rdi + add rsi, 192 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12], rax + mov QWORD PTR [r13], r9 + mov rax, QWORD PTR [r12+8] + mov r9, QWORD PTR [r13+8] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+8], rax + mov QWORD PTR [r13+8], r9 + mov rax, QWORD PTR [r12+16] + mov r9, QWORD PTR [r13+16] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+16], rax + mov QWORD PTR [r13+16], r9 + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+24], rax + mov QWORD PTR [r13+24], r9 + mov rax, QWORD PTR [r12+32] + mov r9, QWORD PTR [r13+32] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+32], rax + mov QWORD PTR [r13+32], r9 + mov rax, QWORD PTR [r12+40] + mov r9, QWORD PTR [r13+40] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+40], rax + mov QWORD PTR [r13+40], r9 + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+48], rax + mov QWORD PTR [r13+48], r9 + mov rax, QWORD PTR [r12+56] + mov r9, QWORD PTR [r13+56] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+56], rax + mov QWORD PTR [r13+56], r9 + mov rax, QWORD PTR [r12+64] + mov r9, QWORD PTR [r13+64] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+64], rax + mov QWORD PTR [r13+64], r9 + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+72], rax + mov QWORD PTR [r13+72], r9 + mov rax, QWORD PTR [r12+80] + mov r9, QWORD PTR [r13+80] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+80], rax + mov QWORD PTR [r13+80], r9 + mov rax, QWORD PTR [r12+88] + mov r9, QWORD PTR [r13+88] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+88], rax + mov QWORD PTR [r13+88], r9 + mov rax, QWORD PTR [r12] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov QWORD PTR [rsi+88], r10 + adc r11, 0 + lea r13, QWORD PTR [rsp+192] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov QWORD PTR [r12+184], r10 + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov QWORD PTR [r12+184], r10 + sbb r11, 0 + sub rsi, 96 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov QWORD PTR [rsi+184], r10 + adc r11, 0 + mov QWORD PTR [rcx+288], r11 + add rsi, 96 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov QWORD PTR [rsi+96], rax + ; Add to zero + mov rax, QWORD PTR [r13+104] + adc rax, 0 + mov r9, QWORD PTR [r13+112] + mov QWORD PTR [rsi+104], rax + adc r9, 0 + mov r10, QWORD PTR [r13+120] + mov QWORD PTR [rsi+112], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+128] + mov QWORD PTR [rsi+120], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+136] + mov QWORD PTR [rsi+128], rax + adc r9, 0 + mov r10, QWORD PTR [r13+144] + mov QWORD PTR [rsi+136], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+152] + mov QWORD PTR [rsi+144], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+160] + mov QWORD PTR [rsi+152], rax + adc r9, 0 + mov r10, QWORD PTR [r13+168] + mov QWORD PTR [rsi+160], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+176] + mov QWORD PTR [rsi+168], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+184] + mov QWORD PTR [rsi+176], rax + adc r9, 0 + mov QWORD PTR [rsi+184], r9 + add rsp, 616 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mul_24 ENDP +_text ENDS +; /* Add a to a into r. (r = a + a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_dbl_12 PROC + mov r8, QWORD PTR [rdx] + xor rax, rax + add r8, r8 + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r8 + adc r9, r9 + mov QWORD PTR [rcx+88], r9 + adc rax, 0 + ret +sp_3072_dbl_12 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sqr_24 PROC + push r12 + sub rsp, 504 + mov QWORD PTR [rsp+480], rcx + mov QWORD PTR [rsp+488], rdx + lea r10, QWORD PTR [rsp+384] + lea r11, QWORD PTR [rdx+96] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov QWORD PTR [r10+88], r8 + adc r9, 0 + mov QWORD PTR [rsp+496], r9 + mov rdx, r10 + mov rcx, rsp + call sp_3072_sqr_12 + mov rdx, QWORD PTR [rsp+488] + lea rcx, QWORD PTR [rsp+192] + add rdx, 96 + call sp_3072_sqr_12 + mov rdx, QWORD PTR [rsp+488] + mov rcx, QWORD PTR [rsp+480] + call sp_3072_sqr_12 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+488] + mov rcx, QWORD PTR [rsp+480] +ENDIF + mov r12, QWORD PTR [rsp+496] + mov r11, rcx + lea r10, QWORD PTR [rsp+384] + mov r9, r12 + neg r12 + add r11, 192 + mov rax, QWORD PTR [r10] + mov r8, QWORD PTR [r10+8] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11], rax + mov QWORD PTR [r11+8], r8 + mov rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r10+24] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+16], rax + mov QWORD PTR [r11+24], r8 + mov rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r10+40] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+32], rax + mov QWORD PTR [r11+40], r8 + mov rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r10+56] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+48], rax + mov QWORD PTR [r11+56], r8 + mov rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r10+72] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+64], rax + mov QWORD PTR [r11+72], r8 + mov rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r10+88] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+80], rax + mov QWORD PTR [r11+88], r8 + mov rax, QWORD PTR [r11] + add rax, rax + mov r8, QWORD PTR [r11+8] + mov QWORD PTR [r11], rax + adc r8, r8 + mov rax, QWORD PTR [r11+16] + mov QWORD PTR [r11+8], r8 + adc rax, rax + mov r8, QWORD PTR [r11+24] + mov QWORD PTR [r11+16], rax + adc r8, r8 + mov rax, QWORD PTR [r11+32] + mov QWORD PTR [r11+24], r8 + adc rax, rax + mov r8, QWORD PTR [r11+40] + mov QWORD PTR [r11+32], rax + adc r8, r8 + mov rax, QWORD PTR [r11+48] + mov QWORD PTR [r11+40], r8 + adc rax, rax + mov r8, QWORD PTR [r11+56] + mov QWORD PTR [r11+48], rax + adc r8, r8 + mov rax, QWORD PTR [r11+64] + mov QWORD PTR [r11+56], r8 + adc rax, rax + mov r8, QWORD PTR [r11+72] + mov QWORD PTR [r11+64], rax + adc r8, r8 + mov rax, QWORD PTR [r11+80] + mov QWORD PTR [r11+72], r8 + adc rax, rax + mov r8, QWORD PTR [r11+88] + mov QWORD PTR [r11+80], rax + adc r8, r8 + mov QWORD PTR [r11+88], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+192] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov QWORD PTR [r10+184], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov QWORD PTR [r10+184], r8 + sbb r9, 0 + sub r11, 96 + ; Add in place + mov rax, QWORD PTR [r11] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [r11+8] + mov QWORD PTR [r11], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [r11+16] + mov QWORD PTR [r11+8], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r11+24] + mov QWORD PTR [r11+16], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [r11+32] + mov QWORD PTR [r11+24], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r11+40] + mov QWORD PTR [r11+32], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [r11+48] + mov QWORD PTR [r11+40], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r11+56] + mov QWORD PTR [r11+48], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [r11+64] + mov QWORD PTR [r11+56], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r11+72] + mov QWORD PTR [r11+64], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [r11+80] + mov QWORD PTR [r11+72], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r11+88] + mov QWORD PTR [r11+80], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [r11+96] + mov QWORD PTR [r11+88], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, QWORD PTR [r10+184] + mov QWORD PTR [r11+184], r8 + adc r9, 0 + mov QWORD PTR [rcx+288], r9 + ; Add in place + mov rax, QWORD PTR [r11+96] + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r11+192] + mov QWORD PTR [r11+184], r8 + adc rax, QWORD PTR [rdx+96] + mov QWORD PTR [r11+192], rax + ; Add to zero + mov rax, QWORD PTR [rdx+104] + adc rax, 0 + mov r8, QWORD PTR [rdx+112] + mov QWORD PTR [r11+200], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r11+208], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+128] + mov QWORD PTR [r11+216], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+136] + mov QWORD PTR [r11+224], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+144] + mov QWORD PTR [r11+232], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+152] + mov QWORD PTR [r11+240], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+160] + mov QWORD PTR [r11+248], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [r11+256], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+176] + mov QWORD PTR [r11+264], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+184] + mov QWORD PTR [r11+272], r8 + adc rax, 0 + mov QWORD PTR [r11+280], rax + add rsp, 504 + pop r12 + ret +sp_3072_sqr_24 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_avx2_24 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 616 + mov QWORD PTR [rsp+576], rcx + mov QWORD PTR [rsp+584], rdx + mov QWORD PTR [rsp+592], r8 + lea r12, QWORD PTR [rsp+384] + lea r14, QWORD PTR [rdx+96] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov QWORD PTR [r12+88], r10 + adc r15, 0 + mov QWORD PTR [rsp+600], r15 + lea r13, QWORD PTR [rsp+480] + lea r14, QWORD PTR [r8+96] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov QWORD PTR [r13+88], r10 + adc rdi, 0 + mov QWORD PTR [rsp+608], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_3072_mul_avx2_12 + mov r8, QWORD PTR [rsp+592] + mov rdx, QWORD PTR [rsp+584] + lea rcx, QWORD PTR [rsp+192] + add r8, 96 + add rdx, 96 + call sp_3072_mul_avx2_12 + mov r8, QWORD PTR [rsp+592] + mov rdx, QWORD PTR [rsp+584] + mov rcx, QWORD PTR [rsp+576] + call sp_3072_mul_avx2_12 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+592] + mov rdx, QWORD PTR [rsp+584] + mov rcx, QWORD PTR [rsp+576] +ENDIF + mov r15, QWORD PTR [rsp+600] + mov rdi, QWORD PTR [rsp+608] + mov rsi, QWORD PTR [rsp+576] + mov r11, r15 + lea r12, QWORD PTR [rsp+384] + lea r13, QWORD PTR [rsp+480] + and r11, rdi + neg r15 + neg rdi + add rsi, 192 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + pext rax, rax, rdi + pext r9, r9, r15 + add rax, r9 + mov r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [r13+8] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi], rax + adc r9, r10 + mov r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [r13+16] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+8], r9 + adc r10, rax + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+16], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [r13+32] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+24], rax + adc r9, r10 + mov r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [r13+40] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+32], r9 + adc r10, rax + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+40], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [r13+56] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+48], rax + adc r9, r10 + mov r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [r13+64] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+56], r9 + adc r10, rax + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+64], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [r13+80] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+72], rax + adc r9, r10 + mov r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [r13+88] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+80], r9 + adc r10, rax + mov QWORD PTR [rsi+88], r10 + adc r11, 0 + lea r13, QWORD PTR [rsp+192] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov QWORD PTR [r12+184], r10 + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov QWORD PTR [r12+184], r10 + sbb r11, 0 + sub rsi, 96 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov QWORD PTR [rsi+184], r10 + adc r11, 0 + mov QWORD PTR [rcx+288], r11 + add rsi, 96 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov QWORD PTR [rsi+96], rax + ; Add to zero + mov rax, QWORD PTR [r13+104] + adc rax, 0 + mov r9, QWORD PTR [r13+112] + mov QWORD PTR [rsi+104], rax + adc r9, 0 + mov r10, QWORD PTR [r13+120] + mov QWORD PTR [rsi+112], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+128] + mov QWORD PTR [rsi+120], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+136] + mov QWORD PTR [rsi+128], rax + adc r9, 0 + mov r10, QWORD PTR [r13+144] + mov QWORD PTR [rsi+136], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+152] + mov QWORD PTR [rsi+144], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+160] + mov QWORD PTR [rsi+152], rax + adc r9, 0 + mov r10, QWORD PTR [r13+168] + mov QWORD PTR [rsi+160], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+176] + mov QWORD PTR [rsi+168], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+184] + mov QWORD PTR [rsi+176], rax + adc r9, 0 + mov QWORD PTR [rsi+184], r9 + add rsp, 616 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mul_avx2_24 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sqr_avx2_24 PROC + push r12 + sub rsp, 504 + mov QWORD PTR [rsp+480], rcx + mov QWORD PTR [rsp+488], rdx + lea r10, QWORD PTR [rsp+384] + lea r11, QWORD PTR [rdx+96] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov QWORD PTR [r10+88], r8 + adc r9, 0 + mov QWORD PTR [rsp+496], r9 + mov rdx, r10 + mov rcx, rsp + call sp_3072_sqr_avx2_12 + mov rdx, QWORD PTR [rsp+488] + lea rcx, QWORD PTR [rsp+192] + add rdx, 96 + call sp_3072_sqr_avx2_12 + mov rdx, QWORD PTR [rsp+488] + mov rcx, QWORD PTR [rsp+480] + call sp_3072_sqr_avx2_12 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+488] + mov rcx, QWORD PTR [rsp+480] +ENDIF + mov r12, QWORD PTR [rsp+496] + mov r11, rcx + lea r10, QWORD PTR [rsp+384] + mov r9, r12 + neg r12 + add r11, 192 + mov rax, QWORD PTR [r10] + pext rax, rax, r12 + add rax, rax + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r11], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r11+8], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r11+16], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r11+24], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r11+32], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r11+40], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r11+48], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r11+56], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r11+64], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r11+72], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r11+80], rax + pext r8, r8, r12 + adc r8, r8 + mov QWORD PTR [r11+88], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+192] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov QWORD PTR [r10+184], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov QWORD PTR [r10+184], r8 + sbb r9, 0 + sub r11, 96 + ; Add in place + mov rax, QWORD PTR [r11] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [r11+8] + mov QWORD PTR [r11], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [r11+16] + mov QWORD PTR [r11+8], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r11+24] + mov QWORD PTR [r11+16], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [r11+32] + mov QWORD PTR [r11+24], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r11+40] + mov QWORD PTR [r11+32], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [r11+48] + mov QWORD PTR [r11+40], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r11+56] + mov QWORD PTR [r11+48], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [r11+64] + mov QWORD PTR [r11+56], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r11+72] + mov QWORD PTR [r11+64], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [r11+80] + mov QWORD PTR [r11+72], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r11+88] + mov QWORD PTR [r11+80], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [r11+96] + mov QWORD PTR [r11+88], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, QWORD PTR [r10+184] + mov QWORD PTR [r11+184], r8 + adc r9, 0 + mov QWORD PTR [rcx+288], r9 + ; Add in place + mov rax, QWORD PTR [r11+96] + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r11+192] + mov QWORD PTR [r11+184], r8 + adc rax, QWORD PTR [rdx+96] + mov QWORD PTR [r11+192], rax + ; Add to zero + mov rax, QWORD PTR [rdx+104] + adc rax, 0 + mov r8, QWORD PTR [rdx+112] + mov QWORD PTR [r11+200], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r11+208], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+128] + mov QWORD PTR [r11+216], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+136] + mov QWORD PTR [r11+224], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+144] + mov QWORD PTR [r11+232], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+152] + mov QWORD PTR [r11+240], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+160] + mov QWORD PTR [r11+248], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [r11+256], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+176] + mov QWORD PTR [r11+264], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+184] + mov QWORD PTR [r11+272], r8 + adc rax, 0 + mov QWORD PTR [r11+280], rax + add rsp, 504 + pop r12 + ret +sp_3072_sqr_avx2_24 ENDP +_text ENDS +ENDIF +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sub_in_place_48 PROC + mov r8, QWORD PTR [rcx] + xor rax, rax + sub r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rcx+8] + mov QWORD PTR [rcx], r8 + sbb r9, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rcx+16] + mov QWORD PTR [rcx+8], r9 + sbb r8, QWORD PTR [rdx+16] + mov r9, QWORD PTR [rcx+24] + mov QWORD PTR [rcx+16], r8 + sbb r9, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rcx+32] + mov QWORD PTR [rcx+24], r9 + sbb r8, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rcx+40] + mov QWORD PTR [rcx+32], r8 + sbb r9, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rcx+48] + mov QWORD PTR [rcx+40], r9 + sbb r8, QWORD PTR [rdx+48] + mov r9, QWORD PTR [rcx+56] + mov QWORD PTR [rcx+48], r8 + sbb r9, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rcx+64] + mov QWORD PTR [rcx+56], r9 + sbb r8, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rcx+72] + mov QWORD PTR [rcx+64], r8 + sbb r9, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rcx+80] + mov QWORD PTR [rcx+72], r9 + sbb r8, QWORD PTR [rdx+80] + mov r9, QWORD PTR [rcx+88] + mov QWORD PTR [rcx+80], r8 + sbb r9, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rcx+96] + mov QWORD PTR [rcx+88], r9 + sbb r8, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rcx+104] + mov QWORD PTR [rcx+96], r8 + sbb r9, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rcx+112] + mov QWORD PTR [rcx+104], r9 + sbb r8, QWORD PTR [rdx+112] + mov r9, QWORD PTR [rcx+120] + mov QWORD PTR [rcx+112], r8 + sbb r9, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rcx+128] + mov QWORD PTR [rcx+120], r9 + sbb r8, QWORD PTR [rdx+128] + mov r9, QWORD PTR [rcx+136] + mov QWORD PTR [rcx+128], r8 + sbb r9, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rcx+144] + mov QWORD PTR [rcx+136], r9 + sbb r8, QWORD PTR [rdx+144] + mov r9, QWORD PTR [rcx+152] + mov QWORD PTR [rcx+144], r8 + sbb r9, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rcx+160] + mov QWORD PTR [rcx+152], r9 + sbb r8, QWORD PTR [rdx+160] + mov r9, QWORD PTR [rcx+168] + mov QWORD PTR [rcx+160], r8 + sbb r9, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rcx+176] + mov QWORD PTR [rcx+168], r9 + sbb r8, QWORD PTR [rdx+176] + mov r9, QWORD PTR [rcx+184] + mov QWORD PTR [rcx+176], r8 + sbb r9, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rcx+192] + mov QWORD PTR [rcx+184], r9 + sbb r8, QWORD PTR [rdx+192] + mov r9, QWORD PTR [rcx+200] + mov QWORD PTR [rcx+192], r8 + sbb r9, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rcx+208] + mov QWORD PTR [rcx+200], r9 + sbb r8, QWORD PTR [rdx+208] + mov r9, QWORD PTR [rcx+216] + mov QWORD PTR [rcx+208], r8 + sbb r9, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rcx+224] + mov QWORD PTR [rcx+216], r9 + sbb r8, QWORD PTR [rdx+224] + mov r9, QWORD PTR [rcx+232] + mov QWORD PTR [rcx+224], r8 + sbb r9, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rcx+240] + mov QWORD PTR [rcx+232], r9 + sbb r8, QWORD PTR [rdx+240] + mov r9, QWORD PTR [rcx+248] + mov QWORD PTR [rcx+240], r8 + sbb r9, QWORD PTR [rdx+248] + mov r8, QWORD PTR [rcx+256] + mov QWORD PTR [rcx+248], r9 + sbb r8, QWORD PTR [rdx+256] + mov r9, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], r8 + sbb r9, QWORD PTR [rdx+264] + mov r8, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r9 + sbb r8, QWORD PTR [rdx+272] + mov r9, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], r8 + sbb r9, QWORD PTR [rdx+280] + mov r8, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r9 + sbb r8, QWORD PTR [rdx+288] + mov r9, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], r8 + sbb r9, QWORD PTR [rdx+296] + mov r8, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r9 + sbb r8, QWORD PTR [rdx+304] + mov r9, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], r8 + sbb r9, QWORD PTR [rdx+312] + mov r8, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r9 + sbb r8, QWORD PTR [rdx+320] + mov r9, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], r8 + sbb r9, QWORD PTR [rdx+328] + mov r8, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r9 + sbb r8, QWORD PTR [rdx+336] + mov r9, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], r8 + sbb r9, QWORD PTR [rdx+344] + mov r8, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r9 + sbb r8, QWORD PTR [rdx+352] + mov r9, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], r8 + sbb r9, QWORD PTR [rdx+360] + mov r8, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r9 + sbb r8, QWORD PTR [rdx+368] + mov r9, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], r8 + sbb r9, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+376], r9 + sbb rax, 0 + ret +sp_3072_sub_in_place_48 ENDP +_text ENDS +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_add_48 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + adc r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + adc r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + adc r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + adc r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + adc r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + adc r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + adc r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + adc r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + adc r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + adc r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + adc r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + adc r10, QWORD PTR [r8+184] + mov r9, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r10 + adc r9, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r9 + adc r10, QWORD PTR [r8+200] + mov r9, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r10 + adc r9, QWORD PTR [r8+208] + mov r10, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r9 + adc r10, QWORD PTR [r8+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r10 + adc r9, QWORD PTR [r8+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r9 + adc r10, QWORD PTR [r8+232] + mov r9, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r10 + adc r9, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r9 + adc r10, QWORD PTR [r8+248] + mov r9, QWORD PTR [rdx+256] + mov QWORD PTR [rcx+248], r10 + adc r9, QWORD PTR [r8+256] + mov r10, QWORD PTR [rdx+264] + mov QWORD PTR [rcx+256], r9 + adc r10, QWORD PTR [r8+264] + mov r9, QWORD PTR [rdx+272] + mov QWORD PTR [rcx+264], r10 + adc r9, QWORD PTR [r8+272] + mov r10, QWORD PTR [rdx+280] + mov QWORD PTR [rcx+272], r9 + adc r10, QWORD PTR [r8+280] + mov r9, QWORD PTR [rdx+288] + mov QWORD PTR [rcx+280], r10 + adc r9, QWORD PTR [r8+288] + mov r10, QWORD PTR [rdx+296] + mov QWORD PTR [rcx+288], r9 + adc r10, QWORD PTR [r8+296] + mov r9, QWORD PTR [rdx+304] + mov QWORD PTR [rcx+296], r10 + adc r9, QWORD PTR [r8+304] + mov r10, QWORD PTR [rdx+312] + mov QWORD PTR [rcx+304], r9 + adc r10, QWORD PTR [r8+312] + mov r9, QWORD PTR [rdx+320] + mov QWORD PTR [rcx+312], r10 + adc r9, QWORD PTR [r8+320] + mov r10, QWORD PTR [rdx+328] + mov QWORD PTR [rcx+320], r9 + adc r10, QWORD PTR [r8+328] + mov r9, QWORD PTR [rdx+336] + mov QWORD PTR [rcx+328], r10 + adc r9, QWORD PTR [r8+336] + mov r10, QWORD PTR [rdx+344] + mov QWORD PTR [rcx+336], r9 + adc r10, QWORD PTR [r8+344] + mov r9, QWORD PTR [rdx+352] + mov QWORD PTR [rcx+344], r10 + adc r9, QWORD PTR [r8+352] + mov r10, QWORD PTR [rdx+360] + mov QWORD PTR [rcx+352], r9 + adc r10, QWORD PTR [r8+360] + mov r9, QWORD PTR [rdx+368] + mov QWORD PTR [rcx+360], r10 + adc r9, QWORD PTR [r8+368] + mov r10, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+368], r9 + adc r10, QWORD PTR [r8+376] + mov QWORD PTR [rcx+376], r10 + adc rax, 0 + ret +sp_3072_add_48 ENDP +_text ENDS +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_48 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 1192 + mov QWORD PTR [rsp+1152], rcx + mov QWORD PTR [rsp+1160], rdx + mov QWORD PTR [rsp+1168], r8 + lea r12, QWORD PTR [rsp+768] + lea r14, QWORD PTR [rdx+192] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r12+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [r12+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [rdx+112] + mov QWORD PTR [r12+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r12+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [r12+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [r12+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r12+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [rdx+152] + mov QWORD PTR [r12+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [rdx+160] + mov QWORD PTR [r12+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [r12+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [r12+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [r12+176], r9 + adc r10, QWORD PTR [r14+184] + mov QWORD PTR [r12+184], r10 + adc r15, 0 + mov QWORD PTR [rsp+1176], r15 + lea r13, QWORD PTR [rsp+960] + lea r14, QWORD PTR [r8+192] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [r8+96] + mov QWORD PTR [r13+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [r8+104] + mov QWORD PTR [r13+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [r8+112] + mov QWORD PTR [r13+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [r8+120] + mov QWORD PTR [r13+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [r8+128] + mov QWORD PTR [r13+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [r8+136] + mov QWORD PTR [r13+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [r8+144] + mov QWORD PTR [r13+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [r8+152] + mov QWORD PTR [r13+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [r8+160] + mov QWORD PTR [r13+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [r8+168] + mov QWORD PTR [r13+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [r8+176] + mov QWORD PTR [r13+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [r8+184] + mov QWORD PTR [r13+176], r9 + adc r10, QWORD PTR [r14+184] + mov QWORD PTR [r13+184], r10 + adc rdi, 0 + mov QWORD PTR [rsp+1184], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_3072_mul_24 + mov r8, QWORD PTR [rsp+1168] + mov rdx, QWORD PTR [rsp+1160] + lea rcx, QWORD PTR [rsp+384] + add r8, 192 + add rdx, 192 + call sp_3072_mul_24 + mov r8, QWORD PTR [rsp+1168] + mov rdx, QWORD PTR [rsp+1160] + mov rcx, QWORD PTR [rsp+1152] + call sp_3072_mul_24 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+1168] + mov rdx, QWORD PTR [rsp+1160] + mov rcx, QWORD PTR [rsp+1152] +ENDIF + mov r15, QWORD PTR [rsp+1176] + mov rdi, QWORD PTR [rsp+1184] + mov rsi, QWORD PTR [rsp+1152] + mov r11, r15 + lea r12, QWORD PTR [rsp+768] + lea r13, QWORD PTR [rsp+960] + and r11, rdi + neg r15 + neg rdi + add rsi, 384 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12], rax + mov QWORD PTR [r13], r9 + mov rax, QWORD PTR [r12+8] + mov r9, QWORD PTR [r13+8] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+8], rax + mov QWORD PTR [r13+8], r9 + mov rax, QWORD PTR [r12+16] + mov r9, QWORD PTR [r13+16] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+16], rax + mov QWORD PTR [r13+16], r9 + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+24], rax + mov QWORD PTR [r13+24], r9 + mov rax, QWORD PTR [r12+32] + mov r9, QWORD PTR [r13+32] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+32], rax + mov QWORD PTR [r13+32], r9 + mov rax, QWORD PTR [r12+40] + mov r9, QWORD PTR [r13+40] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+40], rax + mov QWORD PTR [r13+40], r9 + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+48], rax + mov QWORD PTR [r13+48], r9 + mov rax, QWORD PTR [r12+56] + mov r9, QWORD PTR [r13+56] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+56], rax + mov QWORD PTR [r13+56], r9 + mov rax, QWORD PTR [r12+64] + mov r9, QWORD PTR [r13+64] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+64], rax + mov QWORD PTR [r13+64], r9 + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+72], rax + mov QWORD PTR [r13+72], r9 + mov rax, QWORD PTR [r12+80] + mov r9, QWORD PTR [r13+80] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+80], rax + mov QWORD PTR [r13+80], r9 + mov rax, QWORD PTR [r12+88] + mov r9, QWORD PTR [r13+88] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+88], rax + mov QWORD PTR [r13+88], r9 + mov rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [r13+96] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+96], rax + mov QWORD PTR [r13+96], r9 + mov rax, QWORD PTR [r12+104] + mov r9, QWORD PTR [r13+104] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+104], rax + mov QWORD PTR [r13+104], r9 + mov rax, QWORD PTR [r12+112] + mov r9, QWORD PTR [r13+112] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+112], rax + mov QWORD PTR [r13+112], r9 + mov rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [r13+120] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+120], rax + mov QWORD PTR [r13+120], r9 + mov rax, QWORD PTR [r12+128] + mov r9, QWORD PTR [r13+128] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+128], rax + mov QWORD PTR [r13+128], r9 + mov rax, QWORD PTR [r12+136] + mov r9, QWORD PTR [r13+136] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+136], rax + mov QWORD PTR [r13+136], r9 + mov rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [r13+144] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+144], rax + mov QWORD PTR [r13+144], r9 + mov rax, QWORD PTR [r12+152] + mov r9, QWORD PTR [r13+152] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+152], rax + mov QWORD PTR [r13+152], r9 + mov rax, QWORD PTR [r12+160] + mov r9, QWORD PTR [r13+160] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+160], rax + mov QWORD PTR [r13+160], r9 + mov rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [r13+168] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+168], rax + mov QWORD PTR [r13+168], r9 + mov rax, QWORD PTR [r12+176] + mov r9, QWORD PTR [r13+176] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+176], rax + mov QWORD PTR [r13+176], r9 + mov rax, QWORD PTR [r12+184] + mov r9, QWORD PTR [r13+184] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+184], rax + mov QWORD PTR [r13+184], r9 + mov rax, QWORD PTR [r12] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r13+184] + mov QWORD PTR [rsi+184], r10 + adc r11, 0 + lea r13, QWORD PTR [rsp+384] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [r13+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [r13+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [r13+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [r13+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [r13+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [r13+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [r13+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [r13+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [r13+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [r13+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [r13+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [r13+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [r13+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [r13+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [r13+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [r13+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [r13+376] + mov QWORD PTR [r12+376], r10 + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [rcx+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [rcx+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [rcx+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [rcx+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [rcx+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [rcx+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [rcx+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [rcx+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [rcx+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [rcx+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [rcx+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [rcx+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [rcx+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [rcx+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [rcx+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [rcx+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [rcx+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [rcx+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [rcx+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [rcx+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [rcx+376] + mov QWORD PTR [r12+376], r10 + sbb r11, 0 + sub rsi, 192 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r12+248] + mov r10, QWORD PTR [rsi+256] + mov QWORD PTR [rsi+248], r9 + adc r10, QWORD PTR [r12+256] + mov rax, QWORD PTR [rsi+264] + mov QWORD PTR [rsi+256], r10 + adc rax, QWORD PTR [r12+264] + mov r9, QWORD PTR [rsi+272] + mov QWORD PTR [rsi+264], rax + adc r9, QWORD PTR [r12+272] + mov r10, QWORD PTR [rsi+280] + mov QWORD PTR [rsi+272], r9 + adc r10, QWORD PTR [r12+280] + mov rax, QWORD PTR [rsi+288] + mov QWORD PTR [rsi+280], r10 + adc rax, QWORD PTR [r12+288] + mov r9, QWORD PTR [rsi+296] + mov QWORD PTR [rsi+288], rax + adc r9, QWORD PTR [r12+296] + mov r10, QWORD PTR [rsi+304] + mov QWORD PTR [rsi+296], r9 + adc r10, QWORD PTR [r12+304] + mov rax, QWORD PTR [rsi+312] + mov QWORD PTR [rsi+304], r10 + adc rax, QWORD PTR [r12+312] + mov r9, QWORD PTR [rsi+320] + mov QWORD PTR [rsi+312], rax + adc r9, QWORD PTR [r12+320] + mov r10, QWORD PTR [rsi+328] + mov QWORD PTR [rsi+320], r9 + adc r10, QWORD PTR [r12+328] + mov rax, QWORD PTR [rsi+336] + mov QWORD PTR [rsi+328], r10 + adc rax, QWORD PTR [r12+336] + mov r9, QWORD PTR [rsi+344] + mov QWORD PTR [rsi+336], rax + adc r9, QWORD PTR [r12+344] + mov r10, QWORD PTR [rsi+352] + mov QWORD PTR [rsi+344], r9 + adc r10, QWORD PTR [r12+352] + mov rax, QWORD PTR [rsi+360] + mov QWORD PTR [rsi+352], r10 + adc rax, QWORD PTR [r12+360] + mov r9, QWORD PTR [rsi+368] + mov QWORD PTR [rsi+360], rax + adc r9, QWORD PTR [r12+368] + mov r10, QWORD PTR [rsi+376] + mov QWORD PTR [rsi+368], r9 + adc r10, QWORD PTR [r12+376] + mov QWORD PTR [rsi+376], r10 + adc r11, 0 + mov QWORD PTR [rcx+576], r11 + add rsi, 192 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r13+192] + mov QWORD PTR [rsi+192], rax + ; Add to zero + mov rax, QWORD PTR [r13+200] + adc rax, 0 + mov r9, QWORD PTR [r13+208] + mov QWORD PTR [rsi+200], rax + adc r9, 0 + mov r10, QWORD PTR [r13+216] + mov QWORD PTR [rsi+208], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+224] + mov QWORD PTR [rsi+216], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+232] + mov QWORD PTR [rsi+224], rax + adc r9, 0 + mov r10, QWORD PTR [r13+240] + mov QWORD PTR [rsi+232], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+248] + mov QWORD PTR [rsi+240], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+256] + mov QWORD PTR [rsi+248], rax + adc r9, 0 + mov r10, QWORD PTR [r13+264] + mov QWORD PTR [rsi+256], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+272] + mov QWORD PTR [rsi+264], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+280] + mov QWORD PTR [rsi+272], rax + adc r9, 0 + mov r10, QWORD PTR [r13+288] + mov QWORD PTR [rsi+280], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+296] + mov QWORD PTR [rsi+288], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+304] + mov QWORD PTR [rsi+296], rax + adc r9, 0 + mov r10, QWORD PTR [r13+312] + mov QWORD PTR [rsi+304], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+320] + mov QWORD PTR [rsi+312], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+328] + mov QWORD PTR [rsi+320], rax + adc r9, 0 + mov r10, QWORD PTR [r13+336] + mov QWORD PTR [rsi+328], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+344] + mov QWORD PTR [rsi+336], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+352] + mov QWORD PTR [rsi+344], rax + adc r9, 0 + mov r10, QWORD PTR [r13+360] + mov QWORD PTR [rsi+352], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+368] + mov QWORD PTR [rsi+360], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+376] + mov QWORD PTR [rsi+368], rax + adc r9, 0 + mov QWORD PTR [rsi+376], r9 + add rsp, 1192 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mul_48 ENDP +_text ENDS +; /* Add a to a into r. (r = a + a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_dbl_24 PROC + mov r8, QWORD PTR [rdx] + xor rax, rax + add r8, r8 + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r8 + adc r9, r9 + mov QWORD PTR [rcx+184], r9 + adc rax, 0 + ret +sp_3072_dbl_24 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sqr_48 PROC + push r12 + sub rsp, 984 + mov QWORD PTR [rsp+960], rcx + mov QWORD PTR [rsp+968], rdx + lea r10, QWORD PTR [rsp+768] + lea r11, QWORD PTR [rdx+192] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r10+88], r8 + adc rax, QWORD PTR [r11+96] + mov r8, QWORD PTR [rdx+104] + mov QWORD PTR [r10+96], rax + adc r8, QWORD PTR [r11+104] + mov rax, QWORD PTR [rdx+112] + mov QWORD PTR [r10+104], r8 + adc rax, QWORD PTR [r11+112] + mov r8, QWORD PTR [rdx+120] + mov QWORD PTR [r10+112], rax + adc r8, QWORD PTR [r11+120] + mov rax, QWORD PTR [rdx+128] + mov QWORD PTR [r10+120], r8 + adc rax, QWORD PTR [r11+128] + mov r8, QWORD PTR [rdx+136] + mov QWORD PTR [r10+128], rax + adc r8, QWORD PTR [r11+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r10+136], r8 + adc rax, QWORD PTR [r11+144] + mov r8, QWORD PTR [rdx+152] + mov QWORD PTR [r10+144], rax + adc r8, QWORD PTR [r11+152] + mov rax, QWORD PTR [rdx+160] + mov QWORD PTR [r10+152], r8 + adc rax, QWORD PTR [r11+160] + mov r8, QWORD PTR [rdx+168] + mov QWORD PTR [r10+160], rax + adc r8, QWORD PTR [r11+168] + mov rax, QWORD PTR [rdx+176] + mov QWORD PTR [r10+168], r8 + adc rax, QWORD PTR [r11+176] + mov r8, QWORD PTR [rdx+184] + mov QWORD PTR [r10+176], rax + adc r8, QWORD PTR [r11+184] + mov QWORD PTR [r10+184], r8 + adc r9, 0 + mov QWORD PTR [rsp+976], r9 + mov rdx, r10 + mov rcx, rsp + call sp_3072_sqr_24 + mov rdx, QWORD PTR [rsp+968] + lea rcx, QWORD PTR [rsp+384] + add rdx, 192 + call sp_3072_sqr_24 + mov rdx, QWORD PTR [rsp+968] + mov rcx, QWORD PTR [rsp+960] + call sp_3072_sqr_24 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+968] + mov rcx, QWORD PTR [rsp+960] +ENDIF + mov r12, QWORD PTR [rsp+976] + mov r11, rcx + lea r10, QWORD PTR [rsp+768] + mov r9, r12 + neg r12 + add r11, 384 + mov rax, QWORD PTR [r10] + mov r8, QWORD PTR [r10+8] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11], rax + mov QWORD PTR [r11+8], r8 + mov rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r10+24] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+16], rax + mov QWORD PTR [r11+24], r8 + mov rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r10+40] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+32], rax + mov QWORD PTR [r11+40], r8 + mov rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r10+56] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+48], rax + mov QWORD PTR [r11+56], r8 + mov rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r10+72] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+64], rax + mov QWORD PTR [r11+72], r8 + mov rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r10+88] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+80], rax + mov QWORD PTR [r11+88], r8 + mov rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r10+104] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+96], rax + mov QWORD PTR [r11+104], r8 + mov rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r10+120] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+112], rax + mov QWORD PTR [r11+120], r8 + mov rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [r10+136] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+128], rax + mov QWORD PTR [r11+136], r8 + mov rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [r10+152] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+144], rax + mov QWORD PTR [r11+152], r8 + mov rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [r10+168] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+160], rax + mov QWORD PTR [r11+168], r8 + mov rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [r10+184] + and rax, r12 + and r8, r12 + mov QWORD PTR [r11+176], rax + mov QWORD PTR [r11+184], r8 + mov rax, QWORD PTR [r11] + add rax, rax + mov r8, QWORD PTR [r11+8] + mov QWORD PTR [r11], rax + adc r8, r8 + mov rax, QWORD PTR [r11+16] + mov QWORD PTR [r11+8], r8 + adc rax, rax + mov r8, QWORD PTR [r11+24] + mov QWORD PTR [r11+16], rax + adc r8, r8 + mov rax, QWORD PTR [r11+32] + mov QWORD PTR [r11+24], r8 + adc rax, rax + mov r8, QWORD PTR [r11+40] + mov QWORD PTR [r11+32], rax + adc r8, r8 + mov rax, QWORD PTR [r11+48] + mov QWORD PTR [r11+40], r8 + adc rax, rax + mov r8, QWORD PTR [r11+56] + mov QWORD PTR [r11+48], rax + adc r8, r8 + mov rax, QWORD PTR [r11+64] + mov QWORD PTR [r11+56], r8 + adc rax, rax + mov r8, QWORD PTR [r11+72] + mov QWORD PTR [r11+64], rax + adc r8, r8 + mov rax, QWORD PTR [r11+80] + mov QWORD PTR [r11+72], r8 + adc rax, rax + mov r8, QWORD PTR [r11+88] + mov QWORD PTR [r11+80], rax + adc r8, r8 + mov rax, QWORD PTR [r11+96] + mov QWORD PTR [r11+88], r8 + adc rax, rax + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, r8 + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, rax + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, r8 + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, rax + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, r8 + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, rax + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, r8 + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, rax + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, r8 + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, rax + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, r8 + mov QWORD PTR [r11+184], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+384] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rdx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rdx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rdx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rdx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rdx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rdx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rdx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rdx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rdx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rdx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rdx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rdx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rdx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rdx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rdx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rdx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rdx+376] + mov QWORD PTR [r10+376], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rcx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rcx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rcx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rcx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rcx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rcx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rcx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rcx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rcx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rcx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rcx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rcx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rcx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rcx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rcx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rcx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rcx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rcx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rcx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rcx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rcx+376] + mov QWORD PTR [r10+376], r8 + sbb r9, 0 + sub r11, 192 + ; Add in place + mov rax, QWORD PTR [r11] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [r11+8] + mov QWORD PTR [r11], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [r11+16] + mov QWORD PTR [r11+8], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r11+24] + mov QWORD PTR [r11+16], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [r11+32] + mov QWORD PTR [r11+24], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r11+40] + mov QWORD PTR [r11+32], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [r11+48] + mov QWORD PTR [r11+40], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r11+56] + mov QWORD PTR [r11+48], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [r11+64] + mov QWORD PTR [r11+56], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r11+72] + mov QWORD PTR [r11+64], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [r11+80] + mov QWORD PTR [r11+72], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r11+88] + mov QWORD PTR [r11+80], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [r11+96] + mov QWORD PTR [r11+88], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, QWORD PTR [r10+184] + mov rax, QWORD PTR [r11+192] + mov QWORD PTR [r11+184], r8 + adc rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [r11+200] + mov QWORD PTR [r11+192], rax + adc r8, QWORD PTR [r10+200] + mov rax, QWORD PTR [r11+208] + mov QWORD PTR [r11+200], r8 + adc rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [r11+216] + mov QWORD PTR [r11+208], rax + adc r8, QWORD PTR [r10+216] + mov rax, QWORD PTR [r11+224] + mov QWORD PTR [r11+216], r8 + adc rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [r11+232] + mov QWORD PTR [r11+224], rax + adc r8, QWORD PTR [r10+232] + mov rax, QWORD PTR [r11+240] + mov QWORD PTR [r11+232], r8 + adc rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [r11+248] + mov QWORD PTR [r11+240], rax + adc r8, QWORD PTR [r10+248] + mov rax, QWORD PTR [r11+256] + mov QWORD PTR [r11+248], r8 + adc rax, QWORD PTR [r10+256] + mov r8, QWORD PTR [r11+264] + mov QWORD PTR [r11+256], rax + adc r8, QWORD PTR [r10+264] + mov rax, QWORD PTR [r11+272] + mov QWORD PTR [r11+264], r8 + adc rax, QWORD PTR [r10+272] + mov r8, QWORD PTR [r11+280] + mov QWORD PTR [r11+272], rax + adc r8, QWORD PTR [r10+280] + mov rax, QWORD PTR [r11+288] + mov QWORD PTR [r11+280], r8 + adc rax, QWORD PTR [r10+288] + mov r8, QWORD PTR [r11+296] + mov QWORD PTR [r11+288], rax + adc r8, QWORD PTR [r10+296] + mov rax, QWORD PTR [r11+304] + mov QWORD PTR [r11+296], r8 + adc rax, QWORD PTR [r10+304] + mov r8, QWORD PTR [r11+312] + mov QWORD PTR [r11+304], rax + adc r8, QWORD PTR [r10+312] + mov rax, QWORD PTR [r11+320] + mov QWORD PTR [r11+312], r8 + adc rax, QWORD PTR [r10+320] + mov r8, QWORD PTR [r11+328] + mov QWORD PTR [r11+320], rax + adc r8, QWORD PTR [r10+328] + mov rax, QWORD PTR [r11+336] + mov QWORD PTR [r11+328], r8 + adc rax, QWORD PTR [r10+336] + mov r8, QWORD PTR [r11+344] + mov QWORD PTR [r11+336], rax + adc r8, QWORD PTR [r10+344] + mov rax, QWORD PTR [r11+352] + mov QWORD PTR [r11+344], r8 + adc rax, QWORD PTR [r10+352] + mov r8, QWORD PTR [r11+360] + mov QWORD PTR [r11+352], rax + adc r8, QWORD PTR [r10+360] + mov rax, QWORD PTR [r11+368] + mov QWORD PTR [r11+360], r8 + adc rax, QWORD PTR [r10+368] + mov r8, QWORD PTR [r11+376] + mov QWORD PTR [r11+368], rax + adc r8, QWORD PTR [r10+376] + mov QWORD PTR [r11+376], r8 + adc r9, 0 + mov QWORD PTR [rcx+576], r9 + ; Add in place + mov rax, QWORD PTR [r11+192] + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r11+200] + mov QWORD PTR [r11+192], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r11+208] + mov QWORD PTR [r11+200], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r11+216] + mov QWORD PTR [r11+208], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r11+224] + mov QWORD PTR [r11+216], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r11+232] + mov QWORD PTR [r11+224], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r11+240] + mov QWORD PTR [r11+232], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r11+248] + mov QWORD PTR [r11+240], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r11+256] + mov QWORD PTR [r11+248], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r11+264] + mov QWORD PTR [r11+256], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r11+272] + mov QWORD PTR [r11+264], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r11+280] + mov QWORD PTR [r11+272], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r11+288] + mov QWORD PTR [r11+280], r8 + adc rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r11+296] + mov QWORD PTR [r11+288], rax + adc r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r11+304] + mov QWORD PTR [r11+296], r8 + adc rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r11+312] + mov QWORD PTR [r11+304], rax + adc r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r11+320] + mov QWORD PTR [r11+312], r8 + adc rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r11+328] + mov QWORD PTR [r11+320], rax + adc r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r11+336] + mov QWORD PTR [r11+328], r8 + adc rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r11+344] + mov QWORD PTR [r11+336], rax + adc r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r11+352] + mov QWORD PTR [r11+344], r8 + adc rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r11+360] + mov QWORD PTR [r11+352], rax + adc r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r11+368] + mov QWORD PTR [r11+360], r8 + adc rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r11+376] + mov QWORD PTR [r11+368], rax + adc r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r11+384] + mov QWORD PTR [r11+376], r8 + adc rax, QWORD PTR [rdx+192] + mov QWORD PTR [r11+384], rax + ; Add to zero + mov rax, QWORD PTR [rdx+200] + adc rax, 0 + mov r8, QWORD PTR [rdx+208] + mov QWORD PTR [r11+392], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+216] + mov QWORD PTR [r11+400], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+224] + mov QWORD PTR [r11+408], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+232] + mov QWORD PTR [r11+416], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+240] + mov QWORD PTR [r11+424], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+248] + mov QWORD PTR [r11+432], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+256] + mov QWORD PTR [r11+440], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+264] + mov QWORD PTR [r11+448], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+272] + mov QWORD PTR [r11+456], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+280] + mov QWORD PTR [r11+464], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+288] + mov QWORD PTR [r11+472], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+296] + mov QWORD PTR [r11+480], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+304] + mov QWORD PTR [r11+488], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+312] + mov QWORD PTR [r11+496], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+320] + mov QWORD PTR [r11+504], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+328] + mov QWORD PTR [r11+512], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+336] + mov QWORD PTR [r11+520], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+344] + mov QWORD PTR [r11+528], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+352] + mov QWORD PTR [r11+536], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+360] + mov QWORD PTR [r11+544], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+368] + mov QWORD PTR [r11+552], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+376] + mov QWORD PTR [r11+560], r8 + adc rax, 0 + mov QWORD PTR [r11+568], rax + add rsp, 984 + pop r12 + ret +sp_3072_sqr_48 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_avx2_48 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 1192 + mov QWORD PTR [rsp+1152], rcx + mov QWORD PTR [rsp+1160], rdx + mov QWORD PTR [rsp+1168], r8 + lea r12, QWORD PTR [rsp+768] + lea r14, QWORD PTR [rdx+192] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r12+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [r12+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [rdx+112] + mov QWORD PTR [r12+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r12+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [r12+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [r12+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r12+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [rdx+152] + mov QWORD PTR [r12+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [rdx+160] + mov QWORD PTR [r12+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [r12+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [r12+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [r12+176], r9 + adc r10, QWORD PTR [r14+184] + mov QWORD PTR [r12+184], r10 + adc r15, 0 + mov QWORD PTR [rsp+1176], r15 + lea r13, QWORD PTR [rsp+960] + lea r14, QWORD PTR [r8+192] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [r8+96] + mov QWORD PTR [r13+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [r8+104] + mov QWORD PTR [r13+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [r8+112] + mov QWORD PTR [r13+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [r8+120] + mov QWORD PTR [r13+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [r8+128] + mov QWORD PTR [r13+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [r8+136] + mov QWORD PTR [r13+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [r8+144] + mov QWORD PTR [r13+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [r8+152] + mov QWORD PTR [r13+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [r8+160] + mov QWORD PTR [r13+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [r8+168] + mov QWORD PTR [r13+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [r8+176] + mov QWORD PTR [r13+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [r8+184] + mov QWORD PTR [r13+176], r9 + adc r10, QWORD PTR [r14+184] + mov QWORD PTR [r13+184], r10 + adc rdi, 0 + mov QWORD PTR [rsp+1184], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_3072_mul_avx2_24 + mov r8, QWORD PTR [rsp+1168] + mov rdx, QWORD PTR [rsp+1160] + lea rcx, QWORD PTR [rsp+384] + add r8, 192 + add rdx, 192 + call sp_3072_mul_avx2_24 + mov r8, QWORD PTR [rsp+1168] + mov rdx, QWORD PTR [rsp+1160] + mov rcx, QWORD PTR [rsp+1152] + call sp_3072_mul_avx2_24 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+1168] + mov rdx, QWORD PTR [rsp+1160] + mov rcx, QWORD PTR [rsp+1152] +ENDIF + mov r15, QWORD PTR [rsp+1176] + mov rdi, QWORD PTR [rsp+1184] + mov rsi, QWORD PTR [rsp+1152] + mov r11, r15 + lea r12, QWORD PTR [rsp+768] + lea r13, QWORD PTR [rsp+960] + and r11, rdi + neg r15 + neg rdi + add rsi, 384 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + pext rax, rax, rdi + pext r9, r9, r15 + add rax, r9 + mov r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [r13+8] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi], rax + adc r9, r10 + mov r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [r13+16] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+8], r9 + adc r10, rax + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+16], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [r13+32] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+24], rax + adc r9, r10 + mov r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [r13+40] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+32], r9 + adc r10, rax + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+40], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [r13+56] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+48], rax + adc r9, r10 + mov r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [r13+64] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+56], r9 + adc r10, rax + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+64], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [r13+80] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+72], rax + adc r9, r10 + mov r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [r13+88] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+80], r9 + adc r10, rax + mov rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [r13+96] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+88], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [r13+104] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+96], rax + adc r9, r10 + mov r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [r13+112] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+104], r9 + adc r10, rax + mov rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [r13+120] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+112], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [r13+128] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+120], rax + adc r9, r10 + mov r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [r13+136] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+128], r9 + adc r10, rax + mov rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [r13+144] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+136], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [r13+152] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+144], rax + adc r9, r10 + mov r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [r13+160] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+152], r9 + adc r10, rax + mov rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [r13+168] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+160], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [r13+176] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+168], rax + adc r9, r10 + mov r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [r13+184] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+176], r9 + adc r10, rax + mov QWORD PTR [rsi+184], r10 + adc r11, 0 + lea r13, QWORD PTR [rsp+384] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [r13+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [r13+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [r13+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [r13+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [r13+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [r13+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [r13+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [r13+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [r13+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [r13+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [r13+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [r13+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [r13+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [r13+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [r13+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [r13+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [r13+376] + mov QWORD PTR [r12+376], r10 + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [rcx+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [rcx+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [rcx+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [rcx+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [rcx+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [rcx+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [rcx+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [rcx+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [rcx+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [rcx+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [rcx+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [rcx+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [rcx+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [rcx+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [rcx+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [rcx+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [rcx+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [rcx+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [rcx+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [rcx+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [rcx+376] + mov QWORD PTR [r12+376], r10 + sbb r11, 0 + sub rsi, 192 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r12+248] + mov r10, QWORD PTR [rsi+256] + mov QWORD PTR [rsi+248], r9 + adc r10, QWORD PTR [r12+256] + mov rax, QWORD PTR [rsi+264] + mov QWORD PTR [rsi+256], r10 + adc rax, QWORD PTR [r12+264] + mov r9, QWORD PTR [rsi+272] + mov QWORD PTR [rsi+264], rax + adc r9, QWORD PTR [r12+272] + mov r10, QWORD PTR [rsi+280] + mov QWORD PTR [rsi+272], r9 + adc r10, QWORD PTR [r12+280] + mov rax, QWORD PTR [rsi+288] + mov QWORD PTR [rsi+280], r10 + adc rax, QWORD PTR [r12+288] + mov r9, QWORD PTR [rsi+296] + mov QWORD PTR [rsi+288], rax + adc r9, QWORD PTR [r12+296] + mov r10, QWORD PTR [rsi+304] + mov QWORD PTR [rsi+296], r9 + adc r10, QWORD PTR [r12+304] + mov rax, QWORD PTR [rsi+312] + mov QWORD PTR [rsi+304], r10 + adc rax, QWORD PTR [r12+312] + mov r9, QWORD PTR [rsi+320] + mov QWORD PTR [rsi+312], rax + adc r9, QWORD PTR [r12+320] + mov r10, QWORD PTR [rsi+328] + mov QWORD PTR [rsi+320], r9 + adc r10, QWORD PTR [r12+328] + mov rax, QWORD PTR [rsi+336] + mov QWORD PTR [rsi+328], r10 + adc rax, QWORD PTR [r12+336] + mov r9, QWORD PTR [rsi+344] + mov QWORD PTR [rsi+336], rax + adc r9, QWORD PTR [r12+344] + mov r10, QWORD PTR [rsi+352] + mov QWORD PTR [rsi+344], r9 + adc r10, QWORD PTR [r12+352] + mov rax, QWORD PTR [rsi+360] + mov QWORD PTR [rsi+352], r10 + adc rax, QWORD PTR [r12+360] + mov r9, QWORD PTR [rsi+368] + mov QWORD PTR [rsi+360], rax + adc r9, QWORD PTR [r12+368] + mov r10, QWORD PTR [rsi+376] + mov QWORD PTR [rsi+368], r9 + adc r10, QWORD PTR [r12+376] + mov QWORD PTR [rsi+376], r10 + adc r11, 0 + mov QWORD PTR [rcx+576], r11 + add rsi, 192 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r13+192] + mov QWORD PTR [rsi+192], rax + ; Add to zero + mov rax, QWORD PTR [r13+200] + adc rax, 0 + mov r9, QWORD PTR [r13+208] + mov QWORD PTR [rsi+200], rax + adc r9, 0 + mov r10, QWORD PTR [r13+216] + mov QWORD PTR [rsi+208], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+224] + mov QWORD PTR [rsi+216], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+232] + mov QWORD PTR [rsi+224], rax + adc r9, 0 + mov r10, QWORD PTR [r13+240] + mov QWORD PTR [rsi+232], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+248] + mov QWORD PTR [rsi+240], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+256] + mov QWORD PTR [rsi+248], rax + adc r9, 0 + mov r10, QWORD PTR [r13+264] + mov QWORD PTR [rsi+256], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+272] + mov QWORD PTR [rsi+264], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+280] + mov QWORD PTR [rsi+272], rax + adc r9, 0 + mov r10, QWORD PTR [r13+288] + mov QWORD PTR [rsi+280], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+296] + mov QWORD PTR [rsi+288], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+304] + mov QWORD PTR [rsi+296], rax + adc r9, 0 + mov r10, QWORD PTR [r13+312] + mov QWORD PTR [rsi+304], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+320] + mov QWORD PTR [rsi+312], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+328] + mov QWORD PTR [rsi+320], rax + adc r9, 0 + mov r10, QWORD PTR [r13+336] + mov QWORD PTR [rsi+328], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+344] + mov QWORD PTR [rsi+336], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+352] + mov QWORD PTR [rsi+344], rax + adc r9, 0 + mov r10, QWORD PTR [r13+360] + mov QWORD PTR [rsi+352], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+368] + mov QWORD PTR [rsi+360], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+376] + mov QWORD PTR [rsi+368], rax + adc r9, 0 + mov QWORD PTR [rsi+376], r9 + add rsp, 1192 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mul_avx2_48 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sqr_avx2_48 PROC + push r12 + sub rsp, 984 + mov QWORD PTR [rsp+960], rcx + mov QWORD PTR [rsp+968], rdx + lea r10, QWORD PTR [rsp+768] + lea r11, QWORD PTR [rdx+192] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r10+88], r8 + adc rax, QWORD PTR [r11+96] + mov r8, QWORD PTR [rdx+104] + mov QWORD PTR [r10+96], rax + adc r8, QWORD PTR [r11+104] + mov rax, QWORD PTR [rdx+112] + mov QWORD PTR [r10+104], r8 + adc rax, QWORD PTR [r11+112] + mov r8, QWORD PTR [rdx+120] + mov QWORD PTR [r10+112], rax + adc r8, QWORD PTR [r11+120] + mov rax, QWORD PTR [rdx+128] + mov QWORD PTR [r10+120], r8 + adc rax, QWORD PTR [r11+128] + mov r8, QWORD PTR [rdx+136] + mov QWORD PTR [r10+128], rax + adc r8, QWORD PTR [r11+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r10+136], r8 + adc rax, QWORD PTR [r11+144] + mov r8, QWORD PTR [rdx+152] + mov QWORD PTR [r10+144], rax + adc r8, QWORD PTR [r11+152] + mov rax, QWORD PTR [rdx+160] + mov QWORD PTR [r10+152], r8 + adc rax, QWORD PTR [r11+160] + mov r8, QWORD PTR [rdx+168] + mov QWORD PTR [r10+160], rax + adc r8, QWORD PTR [r11+168] + mov rax, QWORD PTR [rdx+176] + mov QWORD PTR [r10+168], r8 + adc rax, QWORD PTR [r11+176] + mov r8, QWORD PTR [rdx+184] + mov QWORD PTR [r10+176], rax + adc r8, QWORD PTR [r11+184] + mov QWORD PTR [r10+184], r8 + adc r9, 0 + mov QWORD PTR [rsp+976], r9 + mov rdx, r10 + mov rcx, rsp + call sp_3072_sqr_avx2_24 + mov rdx, QWORD PTR [rsp+968] + lea rcx, QWORD PTR [rsp+384] + add rdx, 192 + call sp_3072_sqr_avx2_24 + mov rdx, QWORD PTR [rsp+968] + mov rcx, QWORD PTR [rsp+960] + call sp_3072_sqr_avx2_24 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+968] + mov rcx, QWORD PTR [rsp+960] +ENDIF + mov r12, QWORD PTR [rsp+976] + mov r11, rcx + lea r10, QWORD PTR [rsp+768] + mov r9, r12 + neg r12 + add r11, 384 + mov rax, QWORD PTR [r10] + pext rax, rax, r12 + add rax, rax + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r11], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r11+8], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r11+16], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r11+24], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r11+32], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r11+40], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r11+48], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r11+56], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r11+64], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r11+72], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r11+80], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r11+88], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r11+96], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r11+104], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r11+112], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r11+120], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r11+128], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r11+136], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r11+144], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r11+152], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r11+160], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r11+168], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r11+176], rax + pext r8, r8, r12 + adc r8, r8 + mov QWORD PTR [r11+184], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+384] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rdx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rdx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rdx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rdx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rdx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rdx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rdx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rdx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rdx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rdx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rdx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rdx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rdx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rdx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rdx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rdx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rdx+376] + mov QWORD PTR [r10+376], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rcx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rcx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rcx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rcx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rcx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rcx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rcx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rcx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rcx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rcx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rcx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rcx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rcx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rcx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rcx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rcx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rcx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rcx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rcx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rcx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rcx+376] + mov QWORD PTR [r10+376], r8 + sbb r9, 0 + sub r11, 192 + ; Add in place + mov rax, QWORD PTR [r11] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [r11+8] + mov QWORD PTR [r11], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [r11+16] + mov QWORD PTR [r11+8], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r11+24] + mov QWORD PTR [r11+16], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [r11+32] + mov QWORD PTR [r11+24], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r11+40] + mov QWORD PTR [r11+32], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [r11+48] + mov QWORD PTR [r11+40], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r11+56] + mov QWORD PTR [r11+48], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [r11+64] + mov QWORD PTR [r11+56], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r11+72] + mov QWORD PTR [r11+64], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [r11+80] + mov QWORD PTR [r11+72], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r11+88] + mov QWORD PTR [r11+80], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [r11+96] + mov QWORD PTR [r11+88], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r11+104] + mov QWORD PTR [r11+96], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [r11+112] + mov QWORD PTR [r11+104], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r11+120] + mov QWORD PTR [r11+112], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [r11+128] + mov QWORD PTR [r11+120], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [r11+136] + mov QWORD PTR [r11+128], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [r11+144] + mov QWORD PTR [r11+136], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [r11+152] + mov QWORD PTR [r11+144], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [r11+160] + mov QWORD PTR [r11+152], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [r11+168] + mov QWORD PTR [r11+160], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [r11+176] + mov QWORD PTR [r11+168], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [r11+184] + mov QWORD PTR [r11+176], rax + adc r8, QWORD PTR [r10+184] + mov rax, QWORD PTR [r11+192] + mov QWORD PTR [r11+184], r8 + adc rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [r11+200] + mov QWORD PTR [r11+192], rax + adc r8, QWORD PTR [r10+200] + mov rax, QWORD PTR [r11+208] + mov QWORD PTR [r11+200], r8 + adc rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [r11+216] + mov QWORD PTR [r11+208], rax + adc r8, QWORD PTR [r10+216] + mov rax, QWORD PTR [r11+224] + mov QWORD PTR [r11+216], r8 + adc rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [r11+232] + mov QWORD PTR [r11+224], rax + adc r8, QWORD PTR [r10+232] + mov rax, QWORD PTR [r11+240] + mov QWORD PTR [r11+232], r8 + adc rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [r11+248] + mov QWORD PTR [r11+240], rax + adc r8, QWORD PTR [r10+248] + mov rax, QWORD PTR [r11+256] + mov QWORD PTR [r11+248], r8 + adc rax, QWORD PTR [r10+256] + mov r8, QWORD PTR [r11+264] + mov QWORD PTR [r11+256], rax + adc r8, QWORD PTR [r10+264] + mov rax, QWORD PTR [r11+272] + mov QWORD PTR [r11+264], r8 + adc rax, QWORD PTR [r10+272] + mov r8, QWORD PTR [r11+280] + mov QWORD PTR [r11+272], rax + adc r8, QWORD PTR [r10+280] + mov rax, QWORD PTR [r11+288] + mov QWORD PTR [r11+280], r8 + adc rax, QWORD PTR [r10+288] + mov r8, QWORD PTR [r11+296] + mov QWORD PTR [r11+288], rax + adc r8, QWORD PTR [r10+296] + mov rax, QWORD PTR [r11+304] + mov QWORD PTR [r11+296], r8 + adc rax, QWORD PTR [r10+304] + mov r8, QWORD PTR [r11+312] + mov QWORD PTR [r11+304], rax + adc r8, QWORD PTR [r10+312] + mov rax, QWORD PTR [r11+320] + mov QWORD PTR [r11+312], r8 + adc rax, QWORD PTR [r10+320] + mov r8, QWORD PTR [r11+328] + mov QWORD PTR [r11+320], rax + adc r8, QWORD PTR [r10+328] + mov rax, QWORD PTR [r11+336] + mov QWORD PTR [r11+328], r8 + adc rax, QWORD PTR [r10+336] + mov r8, QWORD PTR [r11+344] + mov QWORD PTR [r11+336], rax + adc r8, QWORD PTR [r10+344] + mov rax, QWORD PTR [r11+352] + mov QWORD PTR [r11+344], r8 + adc rax, QWORD PTR [r10+352] + mov r8, QWORD PTR [r11+360] + mov QWORD PTR [r11+352], rax + adc r8, QWORD PTR [r10+360] + mov rax, QWORD PTR [r11+368] + mov QWORD PTR [r11+360], r8 + adc rax, QWORD PTR [r10+368] + mov r8, QWORD PTR [r11+376] + mov QWORD PTR [r11+368], rax + adc r8, QWORD PTR [r10+376] + mov QWORD PTR [r11+376], r8 + adc r9, 0 + mov QWORD PTR [rcx+576], r9 + ; Add in place + mov rax, QWORD PTR [r11+192] + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r11+200] + mov QWORD PTR [r11+192], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r11+208] + mov QWORD PTR [r11+200], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r11+216] + mov QWORD PTR [r11+208], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r11+224] + mov QWORD PTR [r11+216], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r11+232] + mov QWORD PTR [r11+224], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r11+240] + mov QWORD PTR [r11+232], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r11+248] + mov QWORD PTR [r11+240], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r11+256] + mov QWORD PTR [r11+248], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r11+264] + mov QWORD PTR [r11+256], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r11+272] + mov QWORD PTR [r11+264], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r11+280] + mov QWORD PTR [r11+272], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r11+288] + mov QWORD PTR [r11+280], r8 + adc rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r11+296] + mov QWORD PTR [r11+288], rax + adc r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r11+304] + mov QWORD PTR [r11+296], r8 + adc rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r11+312] + mov QWORD PTR [r11+304], rax + adc r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r11+320] + mov QWORD PTR [r11+312], r8 + adc rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r11+328] + mov QWORD PTR [r11+320], rax + adc r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r11+336] + mov QWORD PTR [r11+328], r8 + adc rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r11+344] + mov QWORD PTR [r11+336], rax + adc r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r11+352] + mov QWORD PTR [r11+344], r8 + adc rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r11+360] + mov QWORD PTR [r11+352], rax + adc r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r11+368] + mov QWORD PTR [r11+360], r8 + adc rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r11+376] + mov QWORD PTR [r11+368], rax + adc r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r11+384] + mov QWORD PTR [r11+376], r8 + adc rax, QWORD PTR [rdx+192] + mov QWORD PTR [r11+384], rax + ; Add to zero + mov rax, QWORD PTR [rdx+200] + adc rax, 0 + mov r8, QWORD PTR [rdx+208] + mov QWORD PTR [r11+392], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+216] + mov QWORD PTR [r11+400], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+224] + mov QWORD PTR [r11+408], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+232] + mov QWORD PTR [r11+416], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+240] + mov QWORD PTR [r11+424], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+248] + mov QWORD PTR [r11+432], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+256] + mov QWORD PTR [r11+440], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+264] + mov QWORD PTR [r11+448], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+272] + mov QWORD PTR [r11+456], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+280] + mov QWORD PTR [r11+464], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+288] + mov QWORD PTR [r11+472], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+296] + mov QWORD PTR [r11+480], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+304] + mov QWORD PTR [r11+488], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+312] + mov QWORD PTR [r11+496], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+320] + mov QWORD PTR [r11+504], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+328] + mov QWORD PTR [r11+512], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+336] + mov QWORD PTR [r11+520], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+344] + mov QWORD PTR [r11+528], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+352] + mov QWORD PTR [r11+536], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+360] + mov QWORD PTR [r11+544], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+368] + mov QWORD PTR [r11+552], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+376] + mov QWORD PTR [r11+560], r8 + adc rax, 0 + mov QWORD PTR [r11+568], rax + add rsp, 984 + pop r12 + ret +sp_3072_sqr_avx2_48 ENDP +_text ENDS +ENDIF +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_d_48 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+40] + add r12, rax + mov QWORD PTR [rcx+40], r12 + adc r10, rdx + adc r11, 0 + ; A[6] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+48] + add r10, rax + mov QWORD PTR [rcx+48], r10 + adc r11, rdx + adc r12, 0 + ; A[7] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+56] + add r11, rax + mov QWORD PTR [rcx+56], r11 + adc r12, rdx + adc r10, 0 + ; A[8] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+64] + add r12, rax + mov QWORD PTR [rcx+64], r12 + adc r10, rdx + adc r11, 0 + ; A[9] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+72] + add r10, rax + mov QWORD PTR [rcx+72], r10 + adc r11, rdx + adc r12, 0 + ; A[10] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+80] + add r11, rax + mov QWORD PTR [rcx+80], r11 + adc r12, rdx + adc r10, 0 + ; A[11] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+88] + add r12, rax + mov QWORD PTR [rcx+88], r12 + adc r10, rdx + adc r11, 0 + ; A[12] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+96] + add r10, rax + mov QWORD PTR [rcx+96], r10 + adc r11, rdx + adc r12, 0 + ; A[13] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+104] + add r11, rax + mov QWORD PTR [rcx+104], r11 + adc r12, rdx + adc r10, 0 + ; A[14] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+112] + add r12, rax + mov QWORD PTR [rcx+112], r12 + adc r10, rdx + adc r11, 0 + ; A[15] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+120] + add r10, rax + mov QWORD PTR [rcx+120], r10 + adc r11, rdx + adc r12, 0 + ; A[16] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+128] + add r11, rax + mov QWORD PTR [rcx+128], r11 + adc r12, rdx + adc r10, 0 + ; A[17] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+136] + add r12, rax + mov QWORD PTR [rcx+136], r12 + adc r10, rdx + adc r11, 0 + ; A[18] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+144] + add r10, rax + mov QWORD PTR [rcx+144], r10 + adc r11, rdx + adc r12, 0 + ; A[19] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+152] + add r11, rax + mov QWORD PTR [rcx+152], r11 + adc r12, rdx + adc r10, 0 + ; A[20] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+160] + add r12, rax + mov QWORD PTR [rcx+160], r12 + adc r10, rdx + adc r11, 0 + ; A[21] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+168] + add r10, rax + mov QWORD PTR [rcx+168], r10 + adc r11, rdx + adc r12, 0 + ; A[22] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+176] + add r11, rax + mov QWORD PTR [rcx+176], r11 + adc r12, rdx + adc r10, 0 + ; A[23] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+184] + add r12, rax + mov QWORD PTR [rcx+184], r12 + adc r10, rdx + adc r11, 0 + ; A[24] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+192] + add r10, rax + mov QWORD PTR [rcx+192], r10 + adc r11, rdx + adc r12, 0 + ; A[25] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+200] + add r11, rax + mov QWORD PTR [rcx+200], r11 + adc r12, rdx + adc r10, 0 + ; A[26] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+208] + add r12, rax + mov QWORD PTR [rcx+208], r12 + adc r10, rdx + adc r11, 0 + ; A[27] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+216] + add r10, rax + mov QWORD PTR [rcx+216], r10 + adc r11, rdx + adc r12, 0 + ; A[28] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+224] + add r11, rax + mov QWORD PTR [rcx+224], r11 + adc r12, rdx + adc r10, 0 + ; A[29] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+232] + add r12, rax + mov QWORD PTR [rcx+232], r12 + adc r10, rdx + adc r11, 0 + ; A[30] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+240] + add r10, rax + mov QWORD PTR [rcx+240], r10 + adc r11, rdx + adc r12, 0 + ; A[31] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+248] + add r11, rax + mov QWORD PTR [rcx+248], r11 + adc r12, rdx + adc r10, 0 + ; A[32] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+256] + add r12, rax + mov QWORD PTR [rcx+256], r12 + adc r10, rdx + adc r11, 0 + ; A[33] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+264] + add r10, rax + mov QWORD PTR [rcx+264], r10 + adc r11, rdx + adc r12, 0 + ; A[34] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+272] + add r11, rax + mov QWORD PTR [rcx+272], r11 + adc r12, rdx + adc r10, 0 + ; A[35] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+280] + add r12, rax + mov QWORD PTR [rcx+280], r12 + adc r10, rdx + adc r11, 0 + ; A[36] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+288] + add r10, rax + mov QWORD PTR [rcx+288], r10 + adc r11, rdx + adc r12, 0 + ; A[37] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+296] + add r11, rax + mov QWORD PTR [rcx+296], r11 + adc r12, rdx + adc r10, 0 + ; A[38] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+304] + add r12, rax + mov QWORD PTR [rcx+304], r12 + adc r10, rdx + adc r11, 0 + ; A[39] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+312] + add r10, rax + mov QWORD PTR [rcx+312], r10 + adc r11, rdx + adc r12, 0 + ; A[40] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+320] + add r11, rax + mov QWORD PTR [rcx+320], r11 + adc r12, rdx + adc r10, 0 + ; A[41] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+328] + add r12, rax + mov QWORD PTR [rcx+328], r12 + adc r10, rdx + adc r11, 0 + ; A[42] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+336] + add r10, rax + mov QWORD PTR [rcx+336], r10 + adc r11, rdx + adc r12, 0 + ; A[43] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+344] + add r11, rax + mov QWORD PTR [rcx+344], r11 + adc r12, rdx + adc r10, 0 + ; A[44] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+352] + add r12, rax + mov QWORD PTR [rcx+352], r12 + adc r10, rdx + adc r11, 0 + ; A[45] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+360] + add r10, rax + mov QWORD PTR [rcx+360], r10 + adc r11, rdx + adc r12, 0 + ; A[46] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+368] + add r11, rax + mov QWORD PTR [rcx+368], r11 + adc r12, rdx + adc r10, 0 + ; A[47] * B + mov rax, r8 + mul QWORD PTR [r9+376] + add r12, rax + adc r10, rdx + mov QWORD PTR [rcx+376], r12 + mov QWORD PTR [rcx+384], r10 + pop r12 + ret +sp_3072_mul_d_48 ENDP +_text ENDS +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_3072_cond_sub_24 PROC + sub rsp, 192 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [r8+128] + mov r11, QWORD PTR [r8+136] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+128], r10 + mov QWORD PTR [rsp+136], r11 + mov r10, QWORD PTR [r8+144] + mov r11, QWORD PTR [r8+152] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+144], r10 + mov QWORD PTR [rsp+152], r11 + mov r10, QWORD PTR [r8+160] + mov r11, QWORD PTR [r8+168] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+160], r10 + mov QWORD PTR [rsp+168], r11 + mov r10, QWORD PTR [r8+176] + mov r11, QWORD PTR [r8+184] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+176], r10 + mov QWORD PTR [rsp+184], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + sbb r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + sbb r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + sbb r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + sbb r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + sbb r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + sbb r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + sbb r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + sbb r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + sbb r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + sbb r11, r8 + mov QWORD PTR [rcx+112], r10 + mov r10, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rsp+128] + sbb r10, r8 + mov QWORD PTR [rcx+120], r11 + mov r11, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rsp+136] + sbb r11, r8 + mov QWORD PTR [rcx+128], r10 + mov r10, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rsp+144] + sbb r10, r8 + mov QWORD PTR [rcx+136], r11 + mov r11, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rsp+152] + sbb r11, r8 + mov QWORD PTR [rcx+144], r10 + mov r10, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rsp+160] + sbb r10, r8 + mov QWORD PTR [rcx+152], r11 + mov r11, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rsp+168] + sbb r11, r8 + mov QWORD PTR [rcx+160], r10 + mov r10, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rsp+176] + sbb r10, r8 + mov QWORD PTR [rcx+168], r11 + mov r11, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rsp+184] + sbb r11, r8 + mov QWORD PTR [rcx+176], r10 + mov QWORD PTR [rcx+184], r11 + sbb rax, 0 + add rsp, 192 + ret +sp_3072_cond_sub_24 ENDP +_text ENDS +; /* Reduce the number back to 3072 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_3072_mont_reduce_24 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 24 + mov r10, 24 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_3072_mont_loop_24: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc r11, 0 + ; a[i+6] += m[6] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+48] + mov r14, QWORD PTR [rcx+48] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+48], r14 + adc r12, 0 + ; a[i+7] += m[7] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+56] + mov r14, QWORD PTR [rcx+56] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+56], r14 + adc r11, 0 + ; a[i+8] += m[8] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+64] + mov r14, QWORD PTR [rcx+64] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+64], r14 + adc r12, 0 + ; a[i+9] += m[9] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+72] + mov r14, QWORD PTR [rcx+72] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+72], r14 + adc r11, 0 + ; a[i+10] += m[10] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+80] + mov r14, QWORD PTR [rcx+80] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+80], r14 + adc r12, 0 + ; a[i+11] += m[11] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+88] + mov r14, QWORD PTR [rcx+88] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+88], r14 + adc r11, 0 + ; a[i+12] += m[12] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+96] + mov r14, QWORD PTR [rcx+96] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+96], r14 + adc r12, 0 + ; a[i+13] += m[13] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+104] + mov r14, QWORD PTR [rcx+104] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+104], r14 + adc r11, 0 + ; a[i+14] += m[14] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+112] + mov r14, QWORD PTR [rcx+112] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+112], r14 + adc r12, 0 + ; a[i+15] += m[15] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+120] + mov r14, QWORD PTR [rcx+120] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+120], r14 + adc r11, 0 + ; a[i+16] += m[16] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+128] + mov r14, QWORD PTR [rcx+128] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+128], r14 + adc r12, 0 + ; a[i+17] += m[17] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+136] + mov r14, QWORD PTR [rcx+136] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+136], r14 + adc r11, 0 + ; a[i+18] += m[18] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+144] + mov r14, QWORD PTR [rcx+144] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+144], r14 + adc r12, 0 + ; a[i+19] += m[19] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+152] + mov r14, QWORD PTR [rcx+152] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+152], r14 + adc r11, 0 + ; a[i+20] += m[20] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+160] + mov r14, QWORD PTR [rcx+160] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+160], r14 + adc r12, 0 + ; a[i+21] += m[21] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+168] + mov r14, QWORD PTR [rcx+168] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+168], r14 + adc r11, 0 + ; a[i+22] += m[22] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+176] + mov r14, QWORD PTR [rcx+176] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+176], r14 + adc r12, 0 + ; a[i+23] += m[23] * mu + mov rax, r13 + mul QWORD PTR [r9+184] + mov r14, QWORD PTR [rcx+184] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+184], r14 + adc QWORD PTR [rcx+192], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_3072_mont_loop_24 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + neg rsi +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 192 + call sp_3072_cond_sub_24 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mont_reduce_24 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_3072_cond_sub_avx2_24 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+128] + mov r11, QWORD PTR [rdx+128] + pext r12, r12, r9 + mov QWORD PTR [rcx+120], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+136] + mov r12, QWORD PTR [rdx+136] + pext r10, r10, r9 + mov QWORD PTR [rcx+128], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+144] + pext r11, r11, r9 + mov QWORD PTR [rcx+136], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+152] + mov r11, QWORD PTR [rdx+152] + pext r12, r12, r9 + mov QWORD PTR [rcx+144], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+160] + mov r12, QWORD PTR [rdx+160] + pext r10, r10, r9 + mov QWORD PTR [rcx+152], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+168] + mov r10, QWORD PTR [rdx+168] + pext r11, r11, r9 + mov QWORD PTR [rcx+160], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+176] + mov r11, QWORD PTR [rdx+176] + pext r12, r12, r9 + mov QWORD PTR [rcx+168], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+184] + mov r12, QWORD PTR [rdx+184] + pext r10, r10, r9 + mov QWORD PTR [rcx+176], r11 + sbb r12, r10 + mov QWORD PTR [rcx+184], r12 + sbb rax, 0 + pop r12 + ret +sp_3072_cond_sub_avx2_24 ENDP +_text ENDS +ENDIF +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_d_24 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+40] + add r12, rax + mov QWORD PTR [rcx+40], r12 + adc r10, rdx + adc r11, 0 + ; A[6] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+48] + add r10, rax + mov QWORD PTR [rcx+48], r10 + adc r11, rdx + adc r12, 0 + ; A[7] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+56] + add r11, rax + mov QWORD PTR [rcx+56], r11 + adc r12, rdx + adc r10, 0 + ; A[8] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+64] + add r12, rax + mov QWORD PTR [rcx+64], r12 + adc r10, rdx + adc r11, 0 + ; A[9] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+72] + add r10, rax + mov QWORD PTR [rcx+72], r10 + adc r11, rdx + adc r12, 0 + ; A[10] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+80] + add r11, rax + mov QWORD PTR [rcx+80], r11 + adc r12, rdx + adc r10, 0 + ; A[11] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+88] + add r12, rax + mov QWORD PTR [rcx+88], r12 + adc r10, rdx + adc r11, 0 + ; A[12] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+96] + add r10, rax + mov QWORD PTR [rcx+96], r10 + adc r11, rdx + adc r12, 0 + ; A[13] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+104] + add r11, rax + mov QWORD PTR [rcx+104], r11 + adc r12, rdx + adc r10, 0 + ; A[14] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+112] + add r12, rax + mov QWORD PTR [rcx+112], r12 + adc r10, rdx + adc r11, 0 + ; A[15] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+120] + add r10, rax + mov QWORD PTR [rcx+120], r10 + adc r11, rdx + adc r12, 0 + ; A[16] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+128] + add r11, rax + mov QWORD PTR [rcx+128], r11 + adc r12, rdx + adc r10, 0 + ; A[17] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+136] + add r12, rax + mov QWORD PTR [rcx+136], r12 + adc r10, rdx + adc r11, 0 + ; A[18] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+144] + add r10, rax + mov QWORD PTR [rcx+144], r10 + adc r11, rdx + adc r12, 0 + ; A[19] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+152] + add r11, rax + mov QWORD PTR [rcx+152], r11 + adc r12, rdx + adc r10, 0 + ; A[20] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+160] + add r12, rax + mov QWORD PTR [rcx+160], r12 + adc r10, rdx + adc r11, 0 + ; A[21] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+168] + add r10, rax + mov QWORD PTR [rcx+168], r10 + adc r11, rdx + adc r12, 0 + ; A[22] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+176] + add r11, rax + mov QWORD PTR [rcx+176], r11 + adc r12, rdx + adc r10, 0 + ; A[23] * B + mov rax, r8 + mul QWORD PTR [r9+184] + add r12, rax + adc r10, rdx + mov QWORD PTR [rcx+184], r12 + mov QWORD PTR [rcx+192], r10 + pop r12 + ret +sp_3072_mul_d_24 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_d_avx2_24 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; A[6] * B + mulx r10, r9, QWORD PTR [rax+48] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; A[7] * B + mulx r10, r9, QWORD PTR [rax+56] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; A[8] * B + mulx r10, r9, QWORD PTR [rax+64] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; A[9] * B + mulx r10, r9, QWORD PTR [rax+72] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + ; A[10] * B + mulx r10, r9, QWORD PTR [rax+80] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+80], r11 + ; A[11] * B + mulx r10, r9, QWORD PTR [rax+88] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+88], r12 + ; A[12] * B + mulx r10, r9, QWORD PTR [rax+96] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+96], r11 + ; A[13] * B + mulx r10, r9, QWORD PTR [rax+104] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+104], r12 + ; A[14] * B + mulx r10, r9, QWORD PTR [rax+112] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+112], r11 + ; A[15] * B + mulx r10, r9, QWORD PTR [rax+120] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+120], r12 + ; A[16] * B + mulx r10, r9, QWORD PTR [rax+128] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+128], r11 + ; A[17] * B + mulx r10, r9, QWORD PTR [rax+136] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+136], r12 + ; A[18] * B + mulx r10, r9, QWORD PTR [rax+144] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+144], r11 + ; A[19] * B + mulx r10, r9, QWORD PTR [rax+152] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+152], r12 + ; A[20] * B + mulx r10, r9, QWORD PTR [rax+160] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+160], r11 + ; A[21] * B + mulx r10, r9, QWORD PTR [rax+168] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+168], r12 + ; A[22] * B + mulx r10, r9, QWORD PTR [rax+176] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+176], r11 + ; A[23] * B + mulx r10, r9, QWORD PTR [rax+184] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+184], r12 + mov QWORD PTR [rcx+192], r11 + pop r13 + pop r12 + ret +sp_3072_mul_d_avx2_24 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_3072_word_asm_24 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_3072_word_asm_24 ENDP +_text ENDS +ENDIF +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_3072_cmp_24 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+184] + mov r12, QWORD PTR [rdx+184] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+176] + mov r12, QWORD PTR [rdx+176] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+168] + mov r12, QWORD PTR [rdx+168] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+160] + mov r12, QWORD PTR [rdx+160] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+152] + mov r12, QWORD PTR [rdx+152] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+144] + mov r12, QWORD PTR [rdx+144] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+136] + mov r12, QWORD PTR [rdx+136] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+128] + mov r12, QWORD PTR [rdx+128] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+120] + mov r12, QWORD PTR [rdx+120] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+112] + mov r12, QWORD PTR [rdx+112] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+104] + mov r12, QWORD PTR [rdx+104] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+96] + mov r12, QWORD PTR [rdx+96] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+88] + mov r12, QWORD PTR [rdx+88] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+80] + mov r12, QWORD PTR [rdx+80] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+72] + mov r12, QWORD PTR [rdx+72] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+64] + mov r12, QWORD PTR [rdx+64] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+56] + mov r12, QWORD PTR [rdx+56] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+48] + mov r12, QWORD PTR [rdx+48] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_3072_cmp_24 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 3072 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_3072_mont_reduce_avx2_24 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r9, rcx + mov r10, rdx + xor rbp, rbp + ; i = 24 + mov r11, 24 + mov r15, QWORD PTR [r9] + mov rdi, QWORD PTR [r9+8] + mov rsi, QWORD PTR [r9+16] + mov rbx, QWORD PTR [r9+24] + add r9, 96 + xor rbp, rbp +L_3072_mont_loop_avx2_24: + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-64] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-56] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-56], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9+-40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-48], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9+-32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-40], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+-24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-32], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+-16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-24], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+-8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-16], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-8], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+8], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+16], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+24], r13 + ; a[i+16] += m[16] * mu + mulx rcx, rax, QWORD PTR [r10+128] + mov r13, QWORD PTR [r9+40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+32], r12 + ; a[i+17] += m[17] * mu + mulx rcx, rax, QWORD PTR [r10+136] + mov r12, QWORD PTR [r9+48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+40], r13 + ; a[i+18] += m[18] * mu + mulx rcx, rax, QWORD PTR [r10+144] + mov r13, QWORD PTR [r9+56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+48], r12 + ; a[i+19] += m[19] * mu + mulx rcx, rax, QWORD PTR [r10+152] + mov r12, QWORD PTR [r9+64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+56], r13 + ; a[i+20] += m[20] * mu + mulx rcx, rax, QWORD PTR [r10+160] + mov r13, QWORD PTR [r9+72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+64], r12 + ; a[i+21] += m[21] * mu + mulx rcx, rax, QWORD PTR [r10+168] + mov r12, QWORD PTR [r9+80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+72], r13 + ; a[i+22] += m[22] * mu + mulx rcx, rax, QWORD PTR [r10+176] + mov r13, QWORD PTR [r9+88] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+80], r12 + ; a[i+23] += m[23] * mu + mulx rcx, rax, QWORD PTR [r10+184] + mov r12, QWORD PTR [r9+96] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+88], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+96], r12 + adox rbp, r14 + adcx rbp, r14 + ; a += 1 + add r9, 8 + ; i -= 1 + sub r11, 1 + jnz L_3072_mont_loop_avx2_24 + sub r9, 96 + neg rbp + mov r8, r9 + sub r9, 192 + mov rcx, QWORD PTR [r10] + mov rdx, r15 + pext rcx, rcx, rbp + sub rdx, rcx + mov rcx, QWORD PTR [r10+8] + mov rax, rdi + pext rcx, rcx, rbp + mov QWORD PTR [r9], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+16] + mov rcx, rsi + pext rdx, rdx, rbp + mov QWORD PTR [r9+8], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+24] + mov rdx, rbx + pext rax, rax, rbp + mov QWORD PTR [r9+16], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+32] + mov rax, QWORD PTR [r8+32] + pext rcx, rcx, rbp + mov QWORD PTR [r9+24], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+40] + mov rcx, QWORD PTR [r8+40] + pext rdx, rdx, rbp + mov QWORD PTR [r9+32], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+48] + mov rdx, QWORD PTR [r8+48] + pext rax, rax, rbp + mov QWORD PTR [r9+40], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+56] + mov rax, QWORD PTR [r8+56] + pext rcx, rcx, rbp + mov QWORD PTR [r9+48], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+64] + mov rcx, QWORD PTR [r8+64] + pext rdx, rdx, rbp + mov QWORD PTR [r9+56], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+72] + mov rdx, QWORD PTR [r8+72] + pext rax, rax, rbp + mov QWORD PTR [r9+64], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+80] + mov rax, QWORD PTR [r8+80] + pext rcx, rcx, rbp + mov QWORD PTR [r9+72], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+88] + mov rcx, QWORD PTR [r8+88] + pext rdx, rdx, rbp + mov QWORD PTR [r9+80], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+96] + mov rdx, QWORD PTR [r8+96] + pext rax, rax, rbp + mov QWORD PTR [r9+88], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+104] + mov rax, QWORD PTR [r8+104] + pext rcx, rcx, rbp + mov QWORD PTR [r9+96], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+112] + mov rcx, QWORD PTR [r8+112] + pext rdx, rdx, rbp + mov QWORD PTR [r9+104], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+120] + mov rdx, QWORD PTR [r8+120] + pext rax, rax, rbp + mov QWORD PTR [r9+112], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+128] + mov rax, QWORD PTR [r8+128] + pext rcx, rcx, rbp + mov QWORD PTR [r9+120], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+136] + mov rcx, QWORD PTR [r8+136] + pext rdx, rdx, rbp + mov QWORD PTR [r9+128], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+144] + mov rdx, QWORD PTR [r8+144] + pext rax, rax, rbp + mov QWORD PTR [r9+136], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+152] + mov rax, QWORD PTR [r8+152] + pext rcx, rcx, rbp + mov QWORD PTR [r9+144], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+160] + mov rcx, QWORD PTR [r8+160] + pext rdx, rdx, rbp + mov QWORD PTR [r9+152], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+168] + mov rdx, QWORD PTR [r8+168] + pext rax, rax, rbp + mov QWORD PTR [r9+160], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+176] + mov rax, QWORD PTR [r8+176] + pext rcx, rcx, rbp + mov QWORD PTR [r9+168], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+184] + mov rcx, QWORD PTR [r8+184] + pext rdx, rdx, rbp + mov QWORD PTR [r9+176], rax + sbb rcx, rdx + mov QWORD PTR [r9+184], rcx + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mont_reduce_avx2_24 ENDP +_text ENDS +ENDIF +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_3072_cond_sub_48 PROC + sub rsp, 384 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [r8+128] + mov r11, QWORD PTR [r8+136] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+128], r10 + mov QWORD PTR [rsp+136], r11 + mov r10, QWORD PTR [r8+144] + mov r11, QWORD PTR [r8+152] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+144], r10 + mov QWORD PTR [rsp+152], r11 + mov r10, QWORD PTR [r8+160] + mov r11, QWORD PTR [r8+168] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+160], r10 + mov QWORD PTR [rsp+168], r11 + mov r10, QWORD PTR [r8+176] + mov r11, QWORD PTR [r8+184] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+176], r10 + mov QWORD PTR [rsp+184], r11 + mov r10, QWORD PTR [r8+192] + mov r11, QWORD PTR [r8+200] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+192], r10 + mov QWORD PTR [rsp+200], r11 + mov r10, QWORD PTR [r8+208] + mov r11, QWORD PTR [r8+216] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+208], r10 + mov QWORD PTR [rsp+216], r11 + mov r10, QWORD PTR [r8+224] + mov r11, QWORD PTR [r8+232] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+224], r10 + mov QWORD PTR [rsp+232], r11 + mov r10, QWORD PTR [r8+240] + mov r11, QWORD PTR [r8+248] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+240], r10 + mov QWORD PTR [rsp+248], r11 + mov r10, QWORD PTR [r8+256] + mov r11, QWORD PTR [r8+264] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+256], r10 + mov QWORD PTR [rsp+264], r11 + mov r10, QWORD PTR [r8+272] + mov r11, QWORD PTR [r8+280] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+272], r10 + mov QWORD PTR [rsp+280], r11 + mov r10, QWORD PTR [r8+288] + mov r11, QWORD PTR [r8+296] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+288], r10 + mov QWORD PTR [rsp+296], r11 + mov r10, QWORD PTR [r8+304] + mov r11, QWORD PTR [r8+312] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+304], r10 + mov QWORD PTR [rsp+312], r11 + mov r10, QWORD PTR [r8+320] + mov r11, QWORD PTR [r8+328] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+320], r10 + mov QWORD PTR [rsp+328], r11 + mov r10, QWORD PTR [r8+336] + mov r11, QWORD PTR [r8+344] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+336], r10 + mov QWORD PTR [rsp+344], r11 + mov r10, QWORD PTR [r8+352] + mov r11, QWORD PTR [r8+360] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+352], r10 + mov QWORD PTR [rsp+360], r11 + mov r10, QWORD PTR [r8+368] + mov r11, QWORD PTR [r8+376] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+368], r10 + mov QWORD PTR [rsp+376], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + sbb r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + sbb r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + sbb r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + sbb r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + sbb r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + sbb r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + sbb r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + sbb r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + sbb r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + sbb r11, r8 + mov QWORD PTR [rcx+112], r10 + mov r10, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rsp+128] + sbb r10, r8 + mov QWORD PTR [rcx+120], r11 + mov r11, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rsp+136] + sbb r11, r8 + mov QWORD PTR [rcx+128], r10 + mov r10, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rsp+144] + sbb r10, r8 + mov QWORD PTR [rcx+136], r11 + mov r11, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rsp+152] + sbb r11, r8 + mov QWORD PTR [rcx+144], r10 + mov r10, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rsp+160] + sbb r10, r8 + mov QWORD PTR [rcx+152], r11 + mov r11, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rsp+168] + sbb r11, r8 + mov QWORD PTR [rcx+160], r10 + mov r10, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rsp+176] + sbb r10, r8 + mov QWORD PTR [rcx+168], r11 + mov r11, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rsp+184] + sbb r11, r8 + mov QWORD PTR [rcx+176], r10 + mov r10, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rsp+192] + sbb r10, r8 + mov QWORD PTR [rcx+184], r11 + mov r11, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rsp+200] + sbb r11, r8 + mov QWORD PTR [rcx+192], r10 + mov r10, QWORD PTR [rdx+208] + mov r8, QWORD PTR [rsp+208] + sbb r10, r8 + mov QWORD PTR [rcx+200], r11 + mov r11, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rsp+216] + sbb r11, r8 + mov QWORD PTR [rcx+208], r10 + mov r10, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rsp+224] + sbb r10, r8 + mov QWORD PTR [rcx+216], r11 + mov r11, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rsp+232] + sbb r11, r8 + mov QWORD PTR [rcx+224], r10 + mov r10, QWORD PTR [rdx+240] + mov r8, QWORD PTR [rsp+240] + sbb r10, r8 + mov QWORD PTR [rcx+232], r11 + mov r11, QWORD PTR [rdx+248] + mov r8, QWORD PTR [rsp+248] + sbb r11, r8 + mov QWORD PTR [rcx+240], r10 + mov r10, QWORD PTR [rdx+256] + mov r8, QWORD PTR [rsp+256] + sbb r10, r8 + mov QWORD PTR [rcx+248], r11 + mov r11, QWORD PTR [rdx+264] + mov r8, QWORD PTR [rsp+264] + sbb r11, r8 + mov QWORD PTR [rcx+256], r10 + mov r10, QWORD PTR [rdx+272] + mov r8, QWORD PTR [rsp+272] + sbb r10, r8 + mov QWORD PTR [rcx+264], r11 + mov r11, QWORD PTR [rdx+280] + mov r8, QWORD PTR [rsp+280] + sbb r11, r8 + mov QWORD PTR [rcx+272], r10 + mov r10, QWORD PTR [rdx+288] + mov r8, QWORD PTR [rsp+288] + sbb r10, r8 + mov QWORD PTR [rcx+280], r11 + mov r11, QWORD PTR [rdx+296] + mov r8, QWORD PTR [rsp+296] + sbb r11, r8 + mov QWORD PTR [rcx+288], r10 + mov r10, QWORD PTR [rdx+304] + mov r8, QWORD PTR [rsp+304] + sbb r10, r8 + mov QWORD PTR [rcx+296], r11 + mov r11, QWORD PTR [rdx+312] + mov r8, QWORD PTR [rsp+312] + sbb r11, r8 + mov QWORD PTR [rcx+304], r10 + mov r10, QWORD PTR [rdx+320] + mov r8, QWORD PTR [rsp+320] + sbb r10, r8 + mov QWORD PTR [rcx+312], r11 + mov r11, QWORD PTR [rdx+328] + mov r8, QWORD PTR [rsp+328] + sbb r11, r8 + mov QWORD PTR [rcx+320], r10 + mov r10, QWORD PTR [rdx+336] + mov r8, QWORD PTR [rsp+336] + sbb r10, r8 + mov QWORD PTR [rcx+328], r11 + mov r11, QWORD PTR [rdx+344] + mov r8, QWORD PTR [rsp+344] + sbb r11, r8 + mov QWORD PTR [rcx+336], r10 + mov r10, QWORD PTR [rdx+352] + mov r8, QWORD PTR [rsp+352] + sbb r10, r8 + mov QWORD PTR [rcx+344], r11 + mov r11, QWORD PTR [rdx+360] + mov r8, QWORD PTR [rsp+360] + sbb r11, r8 + mov QWORD PTR [rcx+352], r10 + mov r10, QWORD PTR [rdx+368] + mov r8, QWORD PTR [rsp+368] + sbb r10, r8 + mov QWORD PTR [rcx+360], r11 + mov r11, QWORD PTR [rdx+376] + mov r8, QWORD PTR [rsp+376] + sbb r11, r8 + mov QWORD PTR [rcx+368], r10 + mov QWORD PTR [rcx+376], r11 + sbb rax, 0 + add rsp, 384 + ret +sp_3072_cond_sub_48 ENDP +_text ENDS +; /* Reduce the number back to 3072 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_3072_mont_reduce_48 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 48 + mov r10, 48 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_3072_mont_loop_48: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc r11, 0 + ; a[i+6] += m[6] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+48] + mov r14, QWORD PTR [rcx+48] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+48], r14 + adc r12, 0 + ; a[i+7] += m[7] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+56] + mov r14, QWORD PTR [rcx+56] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+56], r14 + adc r11, 0 + ; a[i+8] += m[8] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+64] + mov r14, QWORD PTR [rcx+64] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+64], r14 + adc r12, 0 + ; a[i+9] += m[9] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+72] + mov r14, QWORD PTR [rcx+72] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+72], r14 + adc r11, 0 + ; a[i+10] += m[10] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+80] + mov r14, QWORD PTR [rcx+80] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+80], r14 + adc r12, 0 + ; a[i+11] += m[11] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+88] + mov r14, QWORD PTR [rcx+88] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+88], r14 + adc r11, 0 + ; a[i+12] += m[12] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+96] + mov r14, QWORD PTR [rcx+96] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+96], r14 + adc r12, 0 + ; a[i+13] += m[13] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+104] + mov r14, QWORD PTR [rcx+104] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+104], r14 + adc r11, 0 + ; a[i+14] += m[14] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+112] + mov r14, QWORD PTR [rcx+112] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+112], r14 + adc r12, 0 + ; a[i+15] += m[15] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+120] + mov r14, QWORD PTR [rcx+120] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+120], r14 + adc r11, 0 + ; a[i+16] += m[16] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+128] + mov r14, QWORD PTR [rcx+128] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+128], r14 + adc r12, 0 + ; a[i+17] += m[17] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+136] + mov r14, QWORD PTR [rcx+136] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+136], r14 + adc r11, 0 + ; a[i+18] += m[18] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+144] + mov r14, QWORD PTR [rcx+144] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+144], r14 + adc r12, 0 + ; a[i+19] += m[19] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+152] + mov r14, QWORD PTR [rcx+152] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+152], r14 + adc r11, 0 + ; a[i+20] += m[20] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+160] + mov r14, QWORD PTR [rcx+160] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+160], r14 + adc r12, 0 + ; a[i+21] += m[21] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+168] + mov r14, QWORD PTR [rcx+168] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+168], r14 + adc r11, 0 + ; a[i+22] += m[22] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+176] + mov r14, QWORD PTR [rcx+176] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+176], r14 + adc r12, 0 + ; a[i+23] += m[23] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+184] + mov r14, QWORD PTR [rcx+184] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+184], r14 + adc r11, 0 + ; a[i+24] += m[24] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+192] + mov r14, QWORD PTR [rcx+192] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+192], r14 + adc r12, 0 + ; a[i+25] += m[25] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+200] + mov r14, QWORD PTR [rcx+200] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+200], r14 + adc r11, 0 + ; a[i+26] += m[26] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+208] + mov r14, QWORD PTR [rcx+208] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+208], r14 + adc r12, 0 + ; a[i+27] += m[27] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+216] + mov r14, QWORD PTR [rcx+216] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+216], r14 + adc r11, 0 + ; a[i+28] += m[28] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+224] + mov r14, QWORD PTR [rcx+224] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+224], r14 + adc r12, 0 + ; a[i+29] += m[29] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+232] + mov r14, QWORD PTR [rcx+232] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+232], r14 + adc r11, 0 + ; a[i+30] += m[30] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+240] + mov r14, QWORD PTR [rcx+240] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+240], r14 + adc r12, 0 + ; a[i+31] += m[31] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+248] + mov r14, QWORD PTR [rcx+248] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+248], r14 + adc r11, 0 + ; a[i+32] += m[32] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+256] + mov r14, QWORD PTR [rcx+256] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+256], r14 + adc r12, 0 + ; a[i+33] += m[33] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+264] + mov r14, QWORD PTR [rcx+264] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+264], r14 + adc r11, 0 + ; a[i+34] += m[34] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+272] + mov r14, QWORD PTR [rcx+272] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+272], r14 + adc r12, 0 + ; a[i+35] += m[35] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+280] + mov r14, QWORD PTR [rcx+280] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+280], r14 + adc r11, 0 + ; a[i+36] += m[36] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+288] + mov r14, QWORD PTR [rcx+288] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+288], r14 + adc r12, 0 + ; a[i+37] += m[37] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+296] + mov r14, QWORD PTR [rcx+296] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+296], r14 + adc r11, 0 + ; a[i+38] += m[38] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+304] + mov r14, QWORD PTR [rcx+304] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+304], r14 + adc r12, 0 + ; a[i+39] += m[39] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+312] + mov r14, QWORD PTR [rcx+312] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+312], r14 + adc r11, 0 + ; a[i+40] += m[40] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+320] + mov r14, QWORD PTR [rcx+320] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+320], r14 + adc r12, 0 + ; a[i+41] += m[41] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+328] + mov r14, QWORD PTR [rcx+328] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+328], r14 + adc r11, 0 + ; a[i+42] += m[42] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+336] + mov r14, QWORD PTR [rcx+336] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+336], r14 + adc r12, 0 + ; a[i+43] += m[43] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+344] + mov r14, QWORD PTR [rcx+344] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+344], r14 + adc r11, 0 + ; a[i+44] += m[44] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+352] + mov r14, QWORD PTR [rcx+352] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+352], r14 + adc r12, 0 + ; a[i+45] += m[45] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+360] + mov r14, QWORD PTR [rcx+360] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+360], r14 + adc r11, 0 + ; a[i+46] += m[46] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+368] + mov r14, QWORD PTR [rcx+368] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+368], r14 + adc r12, 0 + ; a[i+47] += m[47] * mu + mov rax, r13 + mul QWORD PTR [r9+376] + mov r14, QWORD PTR [rcx+376] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+376], r14 + adc QWORD PTR [rcx+384], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_3072_mont_loop_48 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + neg rsi +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 384 + call sp_3072_cond_sub_48 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mont_reduce_48 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_3072_cond_sub_avx2_48 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+128] + mov r11, QWORD PTR [rdx+128] + pext r12, r12, r9 + mov QWORD PTR [rcx+120], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+136] + mov r12, QWORD PTR [rdx+136] + pext r10, r10, r9 + mov QWORD PTR [rcx+128], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+144] + pext r11, r11, r9 + mov QWORD PTR [rcx+136], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+152] + mov r11, QWORD PTR [rdx+152] + pext r12, r12, r9 + mov QWORD PTR [rcx+144], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+160] + mov r12, QWORD PTR [rdx+160] + pext r10, r10, r9 + mov QWORD PTR [rcx+152], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+168] + mov r10, QWORD PTR [rdx+168] + pext r11, r11, r9 + mov QWORD PTR [rcx+160], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+176] + mov r11, QWORD PTR [rdx+176] + pext r12, r12, r9 + mov QWORD PTR [rcx+168], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+184] + mov r12, QWORD PTR [rdx+184] + pext r10, r10, r9 + mov QWORD PTR [rcx+176], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+192] + pext r11, r11, r9 + mov QWORD PTR [rcx+184], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+200] + mov r11, QWORD PTR [rdx+200] + pext r12, r12, r9 + mov QWORD PTR [rcx+192], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+208] + mov r12, QWORD PTR [rdx+208] + pext r10, r10, r9 + mov QWORD PTR [rcx+200], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+216] + mov r10, QWORD PTR [rdx+216] + pext r11, r11, r9 + mov QWORD PTR [rcx+208], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+224] + mov r11, QWORD PTR [rdx+224] + pext r12, r12, r9 + mov QWORD PTR [rcx+216], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+232] + mov r12, QWORD PTR [rdx+232] + pext r10, r10, r9 + mov QWORD PTR [rcx+224], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+240] + pext r11, r11, r9 + mov QWORD PTR [rcx+232], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+248] + mov r11, QWORD PTR [rdx+248] + pext r12, r12, r9 + mov QWORD PTR [rcx+240], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+256] + mov r12, QWORD PTR [rdx+256] + pext r10, r10, r9 + mov QWORD PTR [rcx+248], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+264] + mov r10, QWORD PTR [rdx+264] + pext r11, r11, r9 + mov QWORD PTR [rcx+256], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+272] + mov r11, QWORD PTR [rdx+272] + pext r12, r12, r9 + mov QWORD PTR [rcx+264], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+280] + mov r12, QWORD PTR [rdx+280] + pext r10, r10, r9 + mov QWORD PTR [rcx+272], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+288] + mov r10, QWORD PTR [rdx+288] + pext r11, r11, r9 + mov QWORD PTR [rcx+280], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+296] + mov r11, QWORD PTR [rdx+296] + pext r12, r12, r9 + mov QWORD PTR [rcx+288], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+304] + mov r12, QWORD PTR [rdx+304] + pext r10, r10, r9 + mov QWORD PTR [rcx+296], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+312] + mov r10, QWORD PTR [rdx+312] + pext r11, r11, r9 + mov QWORD PTR [rcx+304], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+320] + mov r11, QWORD PTR [rdx+320] + pext r12, r12, r9 + mov QWORD PTR [rcx+312], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+328] + mov r12, QWORD PTR [rdx+328] + pext r10, r10, r9 + mov QWORD PTR [rcx+320], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+336] + mov r10, QWORD PTR [rdx+336] + pext r11, r11, r9 + mov QWORD PTR [rcx+328], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+344] + mov r11, QWORD PTR [rdx+344] + pext r12, r12, r9 + mov QWORD PTR [rcx+336], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+352] + mov r12, QWORD PTR [rdx+352] + pext r10, r10, r9 + mov QWORD PTR [rcx+344], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+360] + mov r10, QWORD PTR [rdx+360] + pext r11, r11, r9 + mov QWORD PTR [rcx+352], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+368] + mov r11, QWORD PTR [rdx+368] + pext r12, r12, r9 + mov QWORD PTR [rcx+360], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+376] + mov r12, QWORD PTR [rdx+376] + pext r10, r10, r9 + mov QWORD PTR [rcx+368], r11 + sbb r12, r10 + mov QWORD PTR [rcx+376], r12 + sbb rax, 0 + pop r12 + ret +sp_3072_cond_sub_avx2_48 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_3072_mul_d_avx2_48 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; A[6] * B + mulx r10, r9, QWORD PTR [rax+48] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; A[7] * B + mulx r10, r9, QWORD PTR [rax+56] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; A[8] * B + mulx r10, r9, QWORD PTR [rax+64] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; A[9] * B + mulx r10, r9, QWORD PTR [rax+72] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + ; A[10] * B + mulx r10, r9, QWORD PTR [rax+80] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+80], r11 + ; A[11] * B + mulx r10, r9, QWORD PTR [rax+88] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+88], r12 + ; A[12] * B + mulx r10, r9, QWORD PTR [rax+96] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+96], r11 + ; A[13] * B + mulx r10, r9, QWORD PTR [rax+104] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+104], r12 + ; A[14] * B + mulx r10, r9, QWORD PTR [rax+112] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+112], r11 + ; A[15] * B + mulx r10, r9, QWORD PTR [rax+120] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+120], r12 + ; A[16] * B + mulx r10, r9, QWORD PTR [rax+128] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+128], r11 + ; A[17] * B + mulx r10, r9, QWORD PTR [rax+136] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+136], r12 + ; A[18] * B + mulx r10, r9, QWORD PTR [rax+144] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+144], r11 + ; A[19] * B + mulx r10, r9, QWORD PTR [rax+152] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+152], r12 + ; A[20] * B + mulx r10, r9, QWORD PTR [rax+160] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+160], r11 + ; A[21] * B + mulx r10, r9, QWORD PTR [rax+168] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+168], r12 + ; A[22] * B + mulx r10, r9, QWORD PTR [rax+176] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+176], r11 + ; A[23] * B + mulx r10, r9, QWORD PTR [rax+184] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+184], r12 + ; A[24] * B + mulx r10, r9, QWORD PTR [rax+192] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+192], r11 + ; A[25] * B + mulx r10, r9, QWORD PTR [rax+200] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+200], r12 + ; A[26] * B + mulx r10, r9, QWORD PTR [rax+208] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+208], r11 + ; A[27] * B + mulx r10, r9, QWORD PTR [rax+216] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+216], r12 + ; A[28] * B + mulx r10, r9, QWORD PTR [rax+224] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+224], r11 + ; A[29] * B + mulx r10, r9, QWORD PTR [rax+232] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+232], r12 + ; A[30] * B + mulx r10, r9, QWORD PTR [rax+240] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+240], r11 + ; A[31] * B + mulx r10, r9, QWORD PTR [rax+248] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+248], r12 + ; A[32] * B + mulx r10, r9, QWORD PTR [rax+256] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+256], r11 + ; A[33] * B + mulx r10, r9, QWORD PTR [rax+264] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+264], r12 + ; A[34] * B + mulx r10, r9, QWORD PTR [rax+272] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+272], r11 + ; A[35] * B + mulx r10, r9, QWORD PTR [rax+280] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+280], r12 + ; A[36] * B + mulx r10, r9, QWORD PTR [rax+288] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+288], r11 + ; A[37] * B + mulx r10, r9, QWORD PTR [rax+296] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+296], r12 + ; A[38] * B + mulx r10, r9, QWORD PTR [rax+304] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+304], r11 + ; A[39] * B + mulx r10, r9, QWORD PTR [rax+312] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+312], r12 + ; A[40] * B + mulx r10, r9, QWORD PTR [rax+320] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+320], r11 + ; A[41] * B + mulx r10, r9, QWORD PTR [rax+328] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+328], r12 + ; A[42] * B + mulx r10, r9, QWORD PTR [rax+336] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+336], r11 + ; A[43] * B + mulx r10, r9, QWORD PTR [rax+344] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+344], r12 + ; A[44] * B + mulx r10, r9, QWORD PTR [rax+352] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+352], r11 + ; A[45] * B + mulx r10, r9, QWORD PTR [rax+360] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+360], r12 + ; A[46] * B + mulx r10, r9, QWORD PTR [rax+368] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+368], r11 + ; A[47] * B + mulx r10, r9, QWORD PTR [rax+376] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+376], r12 + mov QWORD PTR [rcx+384], r11 + pop r13 + pop r12 + ret +sp_3072_mul_d_avx2_48 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_3072_word_asm_48 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_3072_word_asm_48 ENDP +_text ENDS +ENDIF +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_3072_cmp_48 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+376] + mov r12, QWORD PTR [rdx+376] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+368] + mov r12, QWORD PTR [rdx+368] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+360] + mov r12, QWORD PTR [rdx+360] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+352] + mov r12, QWORD PTR [rdx+352] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+344] + mov r12, QWORD PTR [rdx+344] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+336] + mov r12, QWORD PTR [rdx+336] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+328] + mov r12, QWORD PTR [rdx+328] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+320] + mov r12, QWORD PTR [rdx+320] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+312] + mov r12, QWORD PTR [rdx+312] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+304] + mov r12, QWORD PTR [rdx+304] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+296] + mov r12, QWORD PTR [rdx+296] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+288] + mov r12, QWORD PTR [rdx+288] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+280] + mov r12, QWORD PTR [rdx+280] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+272] + mov r12, QWORD PTR [rdx+272] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+264] + mov r12, QWORD PTR [rdx+264] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+256] + mov r12, QWORD PTR [rdx+256] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+248] + mov r12, QWORD PTR [rdx+248] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+240] + mov r12, QWORD PTR [rdx+240] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+232] + mov r12, QWORD PTR [rdx+232] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+224] + mov r12, QWORD PTR [rdx+224] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+216] + mov r12, QWORD PTR [rdx+216] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+208] + mov r12, QWORD PTR [rdx+208] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+200] + mov r12, QWORD PTR [rdx+200] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+192] + mov r12, QWORD PTR [rdx+192] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+184] + mov r12, QWORD PTR [rdx+184] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+176] + mov r12, QWORD PTR [rdx+176] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+168] + mov r12, QWORD PTR [rdx+168] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+160] + mov r12, QWORD PTR [rdx+160] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+152] + mov r12, QWORD PTR [rdx+152] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+144] + mov r12, QWORD PTR [rdx+144] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+136] + mov r12, QWORD PTR [rdx+136] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+128] + mov r12, QWORD PTR [rdx+128] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+120] + mov r12, QWORD PTR [rdx+120] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+112] + mov r12, QWORD PTR [rdx+112] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+104] + mov r12, QWORD PTR [rdx+104] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+96] + mov r12, QWORD PTR [rdx+96] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+88] + mov r12, QWORD PTR [rdx+88] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+80] + mov r12, QWORD PTR [rdx+80] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+72] + mov r12, QWORD PTR [rdx+72] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+64] + mov r12, QWORD PTR [rdx+64] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+56] + mov r12, QWORD PTR [rdx+56] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+48] + mov r12, QWORD PTR [rdx+48] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_3072_cmp_48 ENDP +_text ENDS +; /* Sub b from a into r. (r = a - b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_3072_sub_48 PROC + mov r9, QWORD PTR [rdx] + xor rax, rax + sub r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + sbb r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + sbb r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + sbb r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + sbb r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + sbb r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + sbb r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + sbb r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + sbb r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + sbb r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + sbb r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + sbb r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + sbb r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + sbb r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + sbb r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + sbb r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + sbb r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + sbb r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + sbb r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + sbb r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + sbb r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + sbb r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + sbb r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + sbb r10, QWORD PTR [r8+184] + mov r9, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r10 + sbb r9, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r9 + sbb r10, QWORD PTR [r8+200] + mov r9, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r10 + sbb r9, QWORD PTR [r8+208] + mov r10, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r9 + sbb r10, QWORD PTR [r8+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r10 + sbb r9, QWORD PTR [r8+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r9 + sbb r10, QWORD PTR [r8+232] + mov r9, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r10 + sbb r9, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r9 + sbb r10, QWORD PTR [r8+248] + mov r9, QWORD PTR [rdx+256] + mov QWORD PTR [rcx+248], r10 + sbb r9, QWORD PTR [r8+256] + mov r10, QWORD PTR [rdx+264] + mov QWORD PTR [rcx+256], r9 + sbb r10, QWORD PTR [r8+264] + mov r9, QWORD PTR [rdx+272] + mov QWORD PTR [rcx+264], r10 + sbb r9, QWORD PTR [r8+272] + mov r10, QWORD PTR [rdx+280] + mov QWORD PTR [rcx+272], r9 + sbb r10, QWORD PTR [r8+280] + mov r9, QWORD PTR [rdx+288] + mov QWORD PTR [rcx+280], r10 + sbb r9, QWORD PTR [r8+288] + mov r10, QWORD PTR [rdx+296] + mov QWORD PTR [rcx+288], r9 + sbb r10, QWORD PTR [r8+296] + mov r9, QWORD PTR [rdx+304] + mov QWORD PTR [rcx+296], r10 + sbb r9, QWORD PTR [r8+304] + mov r10, QWORD PTR [rdx+312] + mov QWORD PTR [rcx+304], r9 + sbb r10, QWORD PTR [r8+312] + mov r9, QWORD PTR [rdx+320] + mov QWORD PTR [rcx+312], r10 + sbb r9, QWORD PTR [r8+320] + mov r10, QWORD PTR [rdx+328] + mov QWORD PTR [rcx+320], r9 + sbb r10, QWORD PTR [r8+328] + mov r9, QWORD PTR [rdx+336] + mov QWORD PTR [rcx+328], r10 + sbb r9, QWORD PTR [r8+336] + mov r10, QWORD PTR [rdx+344] + mov QWORD PTR [rcx+336], r9 + sbb r10, QWORD PTR [r8+344] + mov r9, QWORD PTR [rdx+352] + mov QWORD PTR [rcx+344], r10 + sbb r9, QWORD PTR [r8+352] + mov r10, QWORD PTR [rdx+360] + mov QWORD PTR [rcx+352], r9 + sbb r10, QWORD PTR [r8+360] + mov r9, QWORD PTR [rdx+368] + mov QWORD PTR [rcx+360], r10 + sbb r9, QWORD PTR [r8+368] + mov r10, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+368], r9 + sbb r10, QWORD PTR [r8+376] + mov QWORD PTR [rcx+376], r10 + sbb rax, 0 + ret +sp_3072_sub_48 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 3072 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_3072_mont_reduce_avx2_48 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r9, rcx + mov r10, rdx + xor rbp, rbp + ; i = 48 + mov r11, 48 + mov r15, QWORD PTR [r9] + mov rdi, QWORD PTR [r9+8] + mov rsi, QWORD PTR [r9+16] + mov rbx, QWORD PTR [r9+24] + add r9, 192 + xor rbp, rbp +L_3072_mont_loop_avx2_48: + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-160] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-152] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-144] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-152], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9+-136] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-144], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9+-128] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-136], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+-120] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-128], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+-112] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-120], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+-104] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-112], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+-96] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-104], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+-88] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-96], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+-80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-88], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+-72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-80], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+-64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-72], r13 + ; a[i+16] += m[16] * mu + mulx rcx, rax, QWORD PTR [r10+128] + mov r13, QWORD PTR [r9+-56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-64], r12 + ; a[i+17] += m[17] * mu + mulx rcx, rax, QWORD PTR [r10+136] + mov r12, QWORD PTR [r9+-48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-56], r13 + ; a[i+18] += m[18] * mu + mulx rcx, rax, QWORD PTR [r10+144] + mov r13, QWORD PTR [r9+-40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-48], r12 + ; a[i+19] += m[19] * mu + mulx rcx, rax, QWORD PTR [r10+152] + mov r12, QWORD PTR [r9+-32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-40], r13 + ; a[i+20] += m[20] * mu + mulx rcx, rax, QWORD PTR [r10+160] + mov r13, QWORD PTR [r9+-24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-32], r12 + ; a[i+21] += m[21] * mu + mulx rcx, rax, QWORD PTR [r10+168] + mov r12, QWORD PTR [r9+-16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-24], r13 + ; a[i+22] += m[22] * mu + mulx rcx, rax, QWORD PTR [r10+176] + mov r13, QWORD PTR [r9+-8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-16], r12 + ; a[i+23] += m[23] * mu + mulx rcx, rax, QWORD PTR [r10+184] + mov r12, QWORD PTR [r9] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-8], r13 + ; a[i+24] += m[24] * mu + mulx rcx, rax, QWORD PTR [r10+192] + mov r13, QWORD PTR [r9+8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9], r12 + ; a[i+25] += m[25] * mu + mulx rcx, rax, QWORD PTR [r10+200] + mov r12, QWORD PTR [r9+16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+8], r13 + ; a[i+26] += m[26] * mu + mulx rcx, rax, QWORD PTR [r10+208] + mov r13, QWORD PTR [r9+24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+16], r12 + ; a[i+27] += m[27] * mu + mulx rcx, rax, QWORD PTR [r10+216] + mov r12, QWORD PTR [r9+32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+24], r13 + ; a[i+28] += m[28] * mu + mulx rcx, rax, QWORD PTR [r10+224] + mov r13, QWORD PTR [r9+40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+32], r12 + ; a[i+29] += m[29] * mu + mulx rcx, rax, QWORD PTR [r10+232] + mov r12, QWORD PTR [r9+48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+40], r13 + ; a[i+30] += m[30] * mu + mulx rcx, rax, QWORD PTR [r10+240] + mov r13, QWORD PTR [r9+56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+48], r12 + ; a[i+31] += m[31] * mu + mulx rcx, rax, QWORD PTR [r10+248] + mov r12, QWORD PTR [r9+64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+56], r13 + ; a[i+32] += m[32] * mu + mulx rcx, rax, QWORD PTR [r10+256] + mov r13, QWORD PTR [r9+72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+64], r12 + ; a[i+33] += m[33] * mu + mulx rcx, rax, QWORD PTR [r10+264] + mov r12, QWORD PTR [r9+80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+72], r13 + ; a[i+34] += m[34] * mu + mulx rcx, rax, QWORD PTR [r10+272] + mov r13, QWORD PTR [r9+88] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+80], r12 + ; a[i+35] += m[35] * mu + mulx rcx, rax, QWORD PTR [r10+280] + mov r12, QWORD PTR [r9+96] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+88], r13 + ; a[i+36] += m[36] * mu + mulx rcx, rax, QWORD PTR [r10+288] + mov r13, QWORD PTR [r9+104] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+96], r12 + ; a[i+37] += m[37] * mu + mulx rcx, rax, QWORD PTR [r10+296] + mov r12, QWORD PTR [r9+112] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+104], r13 + ; a[i+38] += m[38] * mu + mulx rcx, rax, QWORD PTR [r10+304] + mov r13, QWORD PTR [r9+120] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+112], r12 + ; a[i+39] += m[39] * mu + mulx rcx, rax, QWORD PTR [r10+312] + mov r12, QWORD PTR [r9+128] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+120], r13 + ; a[i+40] += m[40] * mu + mulx rcx, rax, QWORD PTR [r10+320] + mov r13, QWORD PTR [r9+136] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+128], r12 + ; a[i+41] += m[41] * mu + mulx rcx, rax, QWORD PTR [r10+328] + mov r12, QWORD PTR [r9+144] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+136], r13 + ; a[i+42] += m[42] * mu + mulx rcx, rax, QWORD PTR [r10+336] + mov r13, QWORD PTR [r9+152] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+144], r12 + ; a[i+43] += m[43] * mu + mulx rcx, rax, QWORD PTR [r10+344] + mov r12, QWORD PTR [r9+160] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+152], r13 + ; a[i+44] += m[44] * mu + mulx rcx, rax, QWORD PTR [r10+352] + mov r13, QWORD PTR [r9+168] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+160], r12 + ; a[i+45] += m[45] * mu + mulx rcx, rax, QWORD PTR [r10+360] + mov r12, QWORD PTR [r9+176] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+168], r13 + ; a[i+46] += m[46] * mu + mulx rcx, rax, QWORD PTR [r10+368] + mov r13, QWORD PTR [r9+184] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+176], r12 + ; a[i+47] += m[47] * mu + mulx rcx, rax, QWORD PTR [r10+376] + mov r12, QWORD PTR [r9+192] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+184], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+192], r12 + adox rbp, r14 + adcx rbp, r14 + ; a += 1 + add r9, 8 + ; i -= 1 + sub r11, 1 + jnz L_3072_mont_loop_avx2_48 + sub r9, 192 + neg rbp + mov r8, r9 + sub r9, 384 + mov rcx, QWORD PTR [r10] + mov rdx, r15 + pext rcx, rcx, rbp + sub rdx, rcx + mov rcx, QWORD PTR [r10+8] + mov rax, rdi + pext rcx, rcx, rbp + mov QWORD PTR [r9], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+16] + mov rcx, rsi + pext rdx, rdx, rbp + mov QWORD PTR [r9+8], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+24] + mov rdx, rbx + pext rax, rax, rbp + mov QWORD PTR [r9+16], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+32] + mov rax, QWORD PTR [r8+32] + pext rcx, rcx, rbp + mov QWORD PTR [r9+24], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+40] + mov rcx, QWORD PTR [r8+40] + pext rdx, rdx, rbp + mov QWORD PTR [r9+32], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+48] + mov rdx, QWORD PTR [r8+48] + pext rax, rax, rbp + mov QWORD PTR [r9+40], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+56] + mov rax, QWORD PTR [r8+56] + pext rcx, rcx, rbp + mov QWORD PTR [r9+48], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+64] + mov rcx, QWORD PTR [r8+64] + pext rdx, rdx, rbp + mov QWORD PTR [r9+56], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+72] + mov rdx, QWORD PTR [r8+72] + pext rax, rax, rbp + mov QWORD PTR [r9+64], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+80] + mov rax, QWORD PTR [r8+80] + pext rcx, rcx, rbp + mov QWORD PTR [r9+72], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+88] + mov rcx, QWORD PTR [r8+88] + pext rdx, rdx, rbp + mov QWORD PTR [r9+80], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+96] + mov rdx, QWORD PTR [r8+96] + pext rax, rax, rbp + mov QWORD PTR [r9+88], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+104] + mov rax, QWORD PTR [r8+104] + pext rcx, rcx, rbp + mov QWORD PTR [r9+96], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+112] + mov rcx, QWORD PTR [r8+112] + pext rdx, rdx, rbp + mov QWORD PTR [r9+104], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+120] + mov rdx, QWORD PTR [r8+120] + pext rax, rax, rbp + mov QWORD PTR [r9+112], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+128] + mov rax, QWORD PTR [r8+128] + pext rcx, rcx, rbp + mov QWORD PTR [r9+120], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+136] + mov rcx, QWORD PTR [r8+136] + pext rdx, rdx, rbp + mov QWORD PTR [r9+128], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+144] + mov rdx, QWORD PTR [r8+144] + pext rax, rax, rbp + mov QWORD PTR [r9+136], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+152] + mov rax, QWORD PTR [r8+152] + pext rcx, rcx, rbp + mov QWORD PTR [r9+144], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+160] + mov rcx, QWORD PTR [r8+160] + pext rdx, rdx, rbp + mov QWORD PTR [r9+152], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+168] + mov rdx, QWORD PTR [r8+168] + pext rax, rax, rbp + mov QWORD PTR [r9+160], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+176] + mov rax, QWORD PTR [r8+176] + pext rcx, rcx, rbp + mov QWORD PTR [r9+168], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+184] + mov rcx, QWORD PTR [r8+184] + pext rdx, rdx, rbp + mov QWORD PTR [r9+176], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+192] + mov rdx, QWORD PTR [r8+192] + pext rax, rax, rbp + mov QWORD PTR [r9+184], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+200] + mov rax, QWORD PTR [r8+200] + pext rcx, rcx, rbp + mov QWORD PTR [r9+192], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+208] + mov rcx, QWORD PTR [r8+208] + pext rdx, rdx, rbp + mov QWORD PTR [r9+200], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+216] + mov rdx, QWORD PTR [r8+216] + pext rax, rax, rbp + mov QWORD PTR [r9+208], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+224] + mov rax, QWORD PTR [r8+224] + pext rcx, rcx, rbp + mov QWORD PTR [r9+216], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+232] + mov rcx, QWORD PTR [r8+232] + pext rdx, rdx, rbp + mov QWORD PTR [r9+224], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+240] + mov rdx, QWORD PTR [r8+240] + pext rax, rax, rbp + mov QWORD PTR [r9+232], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+248] + mov rax, QWORD PTR [r8+248] + pext rcx, rcx, rbp + mov QWORD PTR [r9+240], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+256] + mov rcx, QWORD PTR [r8+256] + pext rdx, rdx, rbp + mov QWORD PTR [r9+248], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+264] + mov rdx, QWORD PTR [r8+264] + pext rax, rax, rbp + mov QWORD PTR [r9+256], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+272] + mov rax, QWORD PTR [r8+272] + pext rcx, rcx, rbp + mov QWORD PTR [r9+264], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+280] + mov rcx, QWORD PTR [r8+280] + pext rdx, rdx, rbp + mov QWORD PTR [r9+272], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+288] + mov rdx, QWORD PTR [r8+288] + pext rax, rax, rbp + mov QWORD PTR [r9+280], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+296] + mov rax, QWORD PTR [r8+296] + pext rcx, rcx, rbp + mov QWORD PTR [r9+288], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+304] + mov rcx, QWORD PTR [r8+304] + pext rdx, rdx, rbp + mov QWORD PTR [r9+296], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+312] + mov rdx, QWORD PTR [r8+312] + pext rax, rax, rbp + mov QWORD PTR [r9+304], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+320] + mov rax, QWORD PTR [r8+320] + pext rcx, rcx, rbp + mov QWORD PTR [r9+312], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+328] + mov rcx, QWORD PTR [r8+328] + pext rdx, rdx, rbp + mov QWORD PTR [r9+320], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+336] + mov rdx, QWORD PTR [r8+336] + pext rax, rax, rbp + mov QWORD PTR [r9+328], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+344] + mov rax, QWORD PTR [r8+344] + pext rcx, rcx, rbp + mov QWORD PTR [r9+336], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+352] + mov rcx, QWORD PTR [r8+352] + pext rdx, rdx, rbp + mov QWORD PTR [r9+344], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+360] + mov rdx, QWORD PTR [r8+360] + pext rax, rax, rbp + mov QWORD PTR [r9+352], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+368] + mov rax, QWORD PTR [r8+368] + pext rcx, rcx, rbp + mov QWORD PTR [r9+360], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+376] + mov rcx, QWORD PTR [r8+376] + pext rdx, rdx, rbp + mov QWORD PTR [r9+368], rax + sbb rcx, rdx + mov QWORD PTR [r9+376], rcx + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_3072_mont_reduce_avx2_48 ENDP +_text ENDS +ENDIF +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_3072_cond_add_24 PROC + sub rsp, 192 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [r8+128] + mov r11, QWORD PTR [r8+136] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+128], r10 + mov QWORD PTR [rsp+136], r11 + mov r10, QWORD PTR [r8+144] + mov r11, QWORD PTR [r8+152] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+144], r10 + mov QWORD PTR [rsp+152], r11 + mov r10, QWORD PTR [r8+160] + mov r11, QWORD PTR [r8+168] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+160], r10 + mov QWORD PTR [rsp+168], r11 + mov r10, QWORD PTR [r8+176] + mov r11, QWORD PTR [r8+184] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+176], r10 + mov QWORD PTR [rsp+184], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + add r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + adc r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + adc r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + adc r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + adc r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + adc r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + adc r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + adc r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + adc r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + adc r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + adc r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + adc r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + adc r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + adc r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + adc r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + adc r11, r8 + mov QWORD PTR [rcx+112], r10 + mov r10, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rsp+128] + adc r10, r8 + mov QWORD PTR [rcx+120], r11 + mov r11, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rsp+136] + adc r11, r8 + mov QWORD PTR [rcx+128], r10 + mov r10, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rsp+144] + adc r10, r8 + mov QWORD PTR [rcx+136], r11 + mov r11, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rsp+152] + adc r11, r8 + mov QWORD PTR [rcx+144], r10 + mov r10, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rsp+160] + adc r10, r8 + mov QWORD PTR [rcx+152], r11 + mov r11, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rsp+168] + adc r11, r8 + mov QWORD PTR [rcx+160], r10 + mov r10, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rsp+176] + adc r10, r8 + mov QWORD PTR [rcx+168], r11 + mov r11, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rsp+184] + adc r11, r8 + mov QWORD PTR [rcx+176], r10 + mov QWORD PTR [rcx+184], r11 + adc rax, 0 + add rsp, 192 + ret +sp_3072_cond_add_24 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_3072_cond_add_avx2_24 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + add r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+128] + mov r11, QWORD PTR [rdx+128] + pext r12, r12, r9 + mov QWORD PTR [rcx+120], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+136] + mov r12, QWORD PTR [rdx+136] + pext r10, r10, r9 + mov QWORD PTR [rcx+128], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+144] + pext r11, r11, r9 + mov QWORD PTR [rcx+136], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+152] + mov r11, QWORD PTR [rdx+152] + pext r12, r12, r9 + mov QWORD PTR [rcx+144], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+160] + mov r12, QWORD PTR [rdx+160] + pext r10, r10, r9 + mov QWORD PTR [rcx+152], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+168] + mov r10, QWORD PTR [rdx+168] + pext r11, r11, r9 + mov QWORD PTR [rcx+160], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+176] + mov r11, QWORD PTR [rdx+176] + pext r12, r12, r9 + mov QWORD PTR [rcx+168], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+184] + mov r12, QWORD PTR [rdx+184] + pext r10, r10, r9 + mov QWORD PTR [rcx+176], r11 + adc r12, r10 + mov QWORD PTR [rcx+184], r12 + adc rax, 0 + pop r12 + ret +sp_3072_cond_add_avx2_24 ENDP +_text ENDS +ENDIF +; /* Shift number left by n bit. (r = a << n) +; * +; * r Result of left shift by n. +; * a Number to shift. +; * n Amoutnt o shift. +; */ +_text SEGMENT READONLY PARA +sp_3072_lshift_48 PROC + push r12 + push r13 + mov r9, rcx + mov rcx, r8 + mov r12, 0 + mov r13, QWORD PTR [rdx+344] + mov rax, QWORD PTR [rdx+352] + mov r8, QWORD PTR [rdx+360] + mov r10, QWORD PTR [rdx+368] + mov r11, QWORD PTR [rdx+376] + shld r12, r11, cl + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+352], rax + mov QWORD PTR [r9+360], r8 + mov QWORD PTR [r9+368], r10 + mov QWORD PTR [r9+376], r11 + mov QWORD PTR [r9+384], r12 + mov r11, QWORD PTR [rdx+312] + mov rax, QWORD PTR [rdx+320] + mov r8, QWORD PTR [rdx+328] + mov r10, QWORD PTR [rdx+336] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+320], rax + mov QWORD PTR [r9+328], r8 + mov QWORD PTR [r9+336], r10 + mov QWORD PTR [r9+344], r13 + mov r13, QWORD PTR [rdx+280] + mov rax, QWORD PTR [rdx+288] + mov r8, QWORD PTR [rdx+296] + mov r10, QWORD PTR [rdx+304] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+288], rax + mov QWORD PTR [r9+296], r8 + mov QWORD PTR [r9+304], r10 + mov QWORD PTR [r9+312], r11 + mov r11, QWORD PTR [rdx+248] + mov rax, QWORD PTR [rdx+256] + mov r8, QWORD PTR [rdx+264] + mov r10, QWORD PTR [rdx+272] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+256], rax + mov QWORD PTR [r9+264], r8 + mov QWORD PTR [r9+272], r10 + mov QWORD PTR [r9+280], r13 + mov r13, QWORD PTR [rdx+216] + mov rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rdx+232] + mov r10, QWORD PTR [rdx+240] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+224], rax + mov QWORD PTR [r9+232], r8 + mov QWORD PTR [r9+240], r10 + mov QWORD PTR [r9+248], r11 + mov r11, QWORD PTR [rdx+184] + mov rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rdx+200] + mov r10, QWORD PTR [rdx+208] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+192], rax + mov QWORD PTR [r9+200], r8 + mov QWORD PTR [r9+208], r10 + mov QWORD PTR [r9+216], r13 + mov r13, QWORD PTR [rdx+152] + mov rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rdx+168] + mov r10, QWORD PTR [rdx+176] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+160], rax + mov QWORD PTR [r9+168], r8 + mov QWORD PTR [r9+176], r10 + mov QWORD PTR [r9+184], r11 + mov r11, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rdx+136] + mov r10, QWORD PTR [rdx+144] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+128], rax + mov QWORD PTR [r9+136], r8 + mov QWORD PTR [r9+144], r10 + mov QWORD PTR [r9+152], r13 + mov r13, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+96], rax + mov QWORD PTR [r9+104], r8 + mov QWORD PTR [r9+112], r10 + mov QWORD PTR [r9+120], r11 + mov r11, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+64], rax + mov QWORD PTR [r9+72], r8 + mov QWORD PTR [r9+80], r10 + mov QWORD PTR [r9+88], r13 + mov r13, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+32], rax + mov QWORD PTR [r9+40], r8 + mov QWORD PTR [r9+48], r10 + mov QWORD PTR [r9+56], r11 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shl rax, cl + mov QWORD PTR [r9], rax + mov QWORD PTR [r9+8], r8 + mov QWORD PTR [r9+16], r10 + mov QWORD PTR [r9+24], r13 + pop r13 + pop r12 + ret +sp_3072_lshift_48 ENDP +_text ENDS +ENDIF +ENDIF +IFDEF WOLFSSL_SP_4096 +IFDEF WOLFSSL_SP_4096 +; /* Read big endian unsigned byte array into r. +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_4096_from_bin_bswap PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 512 + xor r13, r13 + jmp L_4096_from_bin_bswap_64_end +L_4096_from_bin_bswap_64_start: + sub r11, 64 + mov rax, QWORD PTR [r11+56] + mov r10, QWORD PTR [r11+48] + bswap rax + bswap r10 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [r11+40] + mov r10, QWORD PTR [r11+32] + bswap rax + bswap r10 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [r11+24] + mov r10, QWORD PTR [r11+16] + bswap rax + bswap r10 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [r11+8] + mov r10, QWORD PTR [r11] + bswap rax + bswap r10 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_4096_from_bin_bswap_64_end: + cmp r9, 63 + jg L_4096_from_bin_bswap_64_start + jmp L_4096_from_bin_bswap_8_end +L_4096_from_bin_bswap_8_start: + sub r11, 8 + mov rax, QWORD PTR [r11] + bswap rax + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_4096_from_bin_bswap_8_end: + cmp r9, 7 + jg L_4096_from_bin_bswap_8_start + cmp r9, r13 + je L_4096_from_bin_bswap_hi_end + mov r10, r13 + mov rax, r13 +L_4096_from_bin_bswap_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_4096_from_bin_bswap_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_4096_from_bin_bswap_hi_end: + cmp rcx, r12 + je L_4096_from_bin_bswap_zero_end +L_4096_from_bin_bswap_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_4096_from_bin_bswap_zero_start +L_4096_from_bin_bswap_zero_end: + pop r13 + pop r12 + ret +sp_4096_from_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Read big endian unsigned byte array into r. +; * Uses the movbe instruction which is an optional instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_4096_from_bin_movbe PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 512 + xor r13, r13 + jmp L_4096_from_bin_movbe_64_end +L_4096_from_bin_movbe_64_start: + sub r11, 64 + movbe rax, QWORD PTR [r11+56] + movbe r10, QWORD PTR [r11+48] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + movbe rax, QWORD PTR [r11+40] + movbe r10, QWORD PTR [r11+32] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + movbe rax, QWORD PTR [r11+24] + movbe r10, QWORD PTR [r11+16] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + movbe rax, QWORD PTR [r11+8] + movbe r10, QWORD PTR [r11] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_4096_from_bin_movbe_64_end: + cmp r9, 63 + jg L_4096_from_bin_movbe_64_start + jmp L_4096_from_bin_movbe_8_end +L_4096_from_bin_movbe_8_start: + sub r11, 8 + movbe rax, QWORD PTR [r11] + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_4096_from_bin_movbe_8_end: + cmp r9, 7 + jg L_4096_from_bin_movbe_8_start + cmp r9, r13 + je L_4096_from_bin_movbe_hi_end + mov r10, r13 + mov rax, r13 +L_4096_from_bin_movbe_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_4096_from_bin_movbe_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_4096_from_bin_movbe_hi_end: + cmp rcx, r12 + je L_4096_from_bin_movbe_zero_end +L_4096_from_bin_movbe_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_4096_from_bin_movbe_zero_start +L_4096_from_bin_movbe_zero_end: + pop r13 + pop r12 + ret +sp_4096_from_bin_movbe ENDP +_text ENDS +ENDIF +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 512 +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_4096_to_bin_bswap PROC + mov rax, QWORD PTR [rcx+504] + mov r8, QWORD PTR [rcx+496] + bswap rax + bswap r8 + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + mov rax, QWORD PTR [rcx+488] + mov r8, QWORD PTR [rcx+480] + bswap rax + bswap r8 + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + mov rax, QWORD PTR [rcx+472] + mov r8, QWORD PTR [rcx+464] + bswap rax + bswap r8 + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + mov rax, QWORD PTR [rcx+456] + mov r8, QWORD PTR [rcx+448] + bswap rax + bswap r8 + mov QWORD PTR [rdx+48], rax + mov QWORD PTR [rdx+56], r8 + mov rax, QWORD PTR [rcx+440] + mov r8, QWORD PTR [rcx+432] + bswap rax + bswap r8 + mov QWORD PTR [rdx+64], rax + mov QWORD PTR [rdx+72], r8 + mov rax, QWORD PTR [rcx+424] + mov r8, QWORD PTR [rcx+416] + bswap rax + bswap r8 + mov QWORD PTR [rdx+80], rax + mov QWORD PTR [rdx+88], r8 + mov rax, QWORD PTR [rcx+408] + mov r8, QWORD PTR [rcx+400] + bswap rax + bswap r8 + mov QWORD PTR [rdx+96], rax + mov QWORD PTR [rdx+104], r8 + mov rax, QWORD PTR [rcx+392] + mov r8, QWORD PTR [rcx+384] + bswap rax + bswap r8 + mov QWORD PTR [rdx+112], rax + mov QWORD PTR [rdx+120], r8 + mov rax, QWORD PTR [rcx+376] + mov r8, QWORD PTR [rcx+368] + bswap rax + bswap r8 + mov QWORD PTR [rdx+128], rax + mov QWORD PTR [rdx+136], r8 + mov rax, QWORD PTR [rcx+360] + mov r8, QWORD PTR [rcx+352] + bswap rax + bswap r8 + mov QWORD PTR [rdx+144], rax + mov QWORD PTR [rdx+152], r8 + mov rax, QWORD PTR [rcx+344] + mov r8, QWORD PTR [rcx+336] + bswap rax + bswap r8 + mov QWORD PTR [rdx+160], rax + mov QWORD PTR [rdx+168], r8 + mov rax, QWORD PTR [rcx+328] + mov r8, QWORD PTR [rcx+320] + bswap rax + bswap r8 + mov QWORD PTR [rdx+176], rax + mov QWORD PTR [rdx+184], r8 + mov rax, QWORD PTR [rcx+312] + mov r8, QWORD PTR [rcx+304] + bswap rax + bswap r8 + mov QWORD PTR [rdx+192], rax + mov QWORD PTR [rdx+200], r8 + mov rax, QWORD PTR [rcx+296] + mov r8, QWORD PTR [rcx+288] + bswap rax + bswap r8 + mov QWORD PTR [rdx+208], rax + mov QWORD PTR [rdx+216], r8 + mov rax, QWORD PTR [rcx+280] + mov r8, QWORD PTR [rcx+272] + bswap rax + bswap r8 + mov QWORD PTR [rdx+224], rax + mov QWORD PTR [rdx+232], r8 + mov rax, QWORD PTR [rcx+264] + mov r8, QWORD PTR [rcx+256] + bswap rax + bswap r8 + mov QWORD PTR [rdx+240], rax + mov QWORD PTR [rdx+248], r8 + mov rax, QWORD PTR [rcx+248] + mov r8, QWORD PTR [rcx+240] + bswap rax + bswap r8 + mov QWORD PTR [rdx+256], rax + mov QWORD PTR [rdx+264], r8 + mov rax, QWORD PTR [rcx+232] + mov r8, QWORD PTR [rcx+224] + bswap rax + bswap r8 + mov QWORD PTR [rdx+272], rax + mov QWORD PTR [rdx+280], r8 + mov rax, QWORD PTR [rcx+216] + mov r8, QWORD PTR [rcx+208] + bswap rax + bswap r8 + mov QWORD PTR [rdx+288], rax + mov QWORD PTR [rdx+296], r8 + mov rax, QWORD PTR [rcx+200] + mov r8, QWORD PTR [rcx+192] + bswap rax + bswap r8 + mov QWORD PTR [rdx+304], rax + mov QWORD PTR [rdx+312], r8 + mov rax, QWORD PTR [rcx+184] + mov r8, QWORD PTR [rcx+176] + bswap rax + bswap r8 + mov QWORD PTR [rdx+320], rax + mov QWORD PTR [rdx+328], r8 + mov rax, QWORD PTR [rcx+168] + mov r8, QWORD PTR [rcx+160] + bswap rax + bswap r8 + mov QWORD PTR [rdx+336], rax + mov QWORD PTR [rdx+344], r8 + mov rax, QWORD PTR [rcx+152] + mov r8, QWORD PTR [rcx+144] + bswap rax + bswap r8 + mov QWORD PTR [rdx+352], rax + mov QWORD PTR [rdx+360], r8 + mov rax, QWORD PTR [rcx+136] + mov r8, QWORD PTR [rcx+128] + bswap rax + bswap r8 + mov QWORD PTR [rdx+368], rax + mov QWORD PTR [rdx+376], r8 + mov rax, QWORD PTR [rcx+120] + mov r8, QWORD PTR [rcx+112] + bswap rax + bswap r8 + mov QWORD PTR [rdx+384], rax + mov QWORD PTR [rdx+392], r8 + mov rax, QWORD PTR [rcx+104] + mov r8, QWORD PTR [rcx+96] + bswap rax + bswap r8 + mov QWORD PTR [rdx+400], rax + mov QWORD PTR [rdx+408], r8 + mov rax, QWORD PTR [rcx+88] + mov r8, QWORD PTR [rcx+80] + bswap rax + bswap r8 + mov QWORD PTR [rdx+416], rax + mov QWORD PTR [rdx+424], r8 + mov rax, QWORD PTR [rcx+72] + mov r8, QWORD PTR [rcx+64] + bswap rax + bswap r8 + mov QWORD PTR [rdx+432], rax + mov QWORD PTR [rdx+440], r8 + mov rax, QWORD PTR [rcx+56] + mov r8, QWORD PTR [rcx+48] + bswap rax + bswap r8 + mov QWORD PTR [rdx+448], rax + mov QWORD PTR [rdx+456], r8 + mov rax, QWORD PTR [rcx+40] + mov r8, QWORD PTR [rcx+32] + bswap rax + bswap r8 + mov QWORD PTR [rdx+464], rax + mov QWORD PTR [rdx+472], r8 + mov rax, QWORD PTR [rcx+24] + mov r8, QWORD PTR [rcx+16] + bswap rax + bswap r8 + mov QWORD PTR [rdx+480], rax + mov QWORD PTR [rdx+488], r8 + mov rax, QWORD PTR [rcx+8] + mov r8, QWORD PTR [rcx] + bswap rax + bswap r8 + mov QWORD PTR [rdx+496], rax + mov QWORD PTR [rdx+504], r8 + ret +sp_4096_to_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 512 +; * Uses the movbe instruction which is optional. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_4096_to_bin_movbe PROC + movbe rax, QWORD PTR [rcx+504] + movbe r8, QWORD PTR [rcx+496] + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + movbe rax, QWORD PTR [rcx+488] + movbe r8, QWORD PTR [rcx+480] + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + movbe rax, QWORD PTR [rcx+472] + movbe r8, QWORD PTR [rcx+464] + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + movbe rax, QWORD PTR [rcx+456] + movbe r8, QWORD PTR [rcx+448] + mov QWORD PTR [rdx+48], rax + mov QWORD PTR [rdx+56], r8 + movbe rax, QWORD PTR [rcx+440] + movbe r8, QWORD PTR [rcx+432] + mov QWORD PTR [rdx+64], rax + mov QWORD PTR [rdx+72], r8 + movbe rax, QWORD PTR [rcx+424] + movbe r8, QWORD PTR [rcx+416] + mov QWORD PTR [rdx+80], rax + mov QWORD PTR [rdx+88], r8 + movbe rax, QWORD PTR [rcx+408] + movbe r8, QWORD PTR [rcx+400] + mov QWORD PTR [rdx+96], rax + mov QWORD PTR [rdx+104], r8 + movbe rax, QWORD PTR [rcx+392] + movbe r8, QWORD PTR [rcx+384] + mov QWORD PTR [rdx+112], rax + mov QWORD PTR [rdx+120], r8 + movbe rax, QWORD PTR [rcx+376] + movbe r8, QWORD PTR [rcx+368] + mov QWORD PTR [rdx+128], rax + mov QWORD PTR [rdx+136], r8 + movbe rax, QWORD PTR [rcx+360] + movbe r8, QWORD PTR [rcx+352] + mov QWORD PTR [rdx+144], rax + mov QWORD PTR [rdx+152], r8 + movbe rax, QWORD PTR [rcx+344] + movbe r8, QWORD PTR [rcx+336] + mov QWORD PTR [rdx+160], rax + mov QWORD PTR [rdx+168], r8 + movbe rax, QWORD PTR [rcx+328] + movbe r8, QWORD PTR [rcx+320] + mov QWORD PTR [rdx+176], rax + mov QWORD PTR [rdx+184], r8 + movbe rax, QWORD PTR [rcx+312] + movbe r8, QWORD PTR [rcx+304] + mov QWORD PTR [rdx+192], rax + mov QWORD PTR [rdx+200], r8 + movbe rax, QWORD PTR [rcx+296] + movbe r8, QWORD PTR [rcx+288] + mov QWORD PTR [rdx+208], rax + mov QWORD PTR [rdx+216], r8 + movbe rax, QWORD PTR [rcx+280] + movbe r8, QWORD PTR [rcx+272] + mov QWORD PTR [rdx+224], rax + mov QWORD PTR [rdx+232], r8 + movbe rax, QWORD PTR [rcx+264] + movbe r8, QWORD PTR [rcx+256] + mov QWORD PTR [rdx+240], rax + mov QWORD PTR [rdx+248], r8 + movbe rax, QWORD PTR [rcx+248] + movbe r8, QWORD PTR [rcx+240] + mov QWORD PTR [rdx+256], rax + mov QWORD PTR [rdx+264], r8 + movbe rax, QWORD PTR [rcx+232] + movbe r8, QWORD PTR [rcx+224] + mov QWORD PTR [rdx+272], rax + mov QWORD PTR [rdx+280], r8 + movbe rax, QWORD PTR [rcx+216] + movbe r8, QWORD PTR [rcx+208] + mov QWORD PTR [rdx+288], rax + mov QWORD PTR [rdx+296], r8 + movbe rax, QWORD PTR [rcx+200] + movbe r8, QWORD PTR [rcx+192] + mov QWORD PTR [rdx+304], rax + mov QWORD PTR [rdx+312], r8 + movbe rax, QWORD PTR [rcx+184] + movbe r8, QWORD PTR [rcx+176] + mov QWORD PTR [rdx+320], rax + mov QWORD PTR [rdx+328], r8 + movbe rax, QWORD PTR [rcx+168] + movbe r8, QWORD PTR [rcx+160] + mov QWORD PTR [rdx+336], rax + mov QWORD PTR [rdx+344], r8 + movbe rax, QWORD PTR [rcx+152] + movbe r8, QWORD PTR [rcx+144] + mov QWORD PTR [rdx+352], rax + mov QWORD PTR [rdx+360], r8 + movbe rax, QWORD PTR [rcx+136] + movbe r8, QWORD PTR [rcx+128] + mov QWORD PTR [rdx+368], rax + mov QWORD PTR [rdx+376], r8 + movbe rax, QWORD PTR [rcx+120] + movbe r8, QWORD PTR [rcx+112] + mov QWORD PTR [rdx+384], rax + mov QWORD PTR [rdx+392], r8 + movbe rax, QWORD PTR [rcx+104] + movbe r8, QWORD PTR [rcx+96] + mov QWORD PTR [rdx+400], rax + mov QWORD PTR [rdx+408], r8 + movbe rax, QWORD PTR [rcx+88] + movbe r8, QWORD PTR [rcx+80] + mov QWORD PTR [rdx+416], rax + mov QWORD PTR [rdx+424], r8 + movbe rax, QWORD PTR [rcx+72] + movbe r8, QWORD PTR [rcx+64] + mov QWORD PTR [rdx+432], rax + mov QWORD PTR [rdx+440], r8 + movbe rax, QWORD PTR [rcx+56] + movbe r8, QWORD PTR [rcx+48] + mov QWORD PTR [rdx+448], rax + mov QWORD PTR [rdx+456], r8 + movbe rax, QWORD PTR [rcx+40] + movbe r8, QWORD PTR [rcx+32] + mov QWORD PTR [rdx+464], rax + mov QWORD PTR [rdx+472], r8 + movbe rax, QWORD PTR [rcx+24] + movbe r8, QWORD PTR [rcx+16] + mov QWORD PTR [rdx+480], rax + mov QWORD PTR [rdx+488], r8 + movbe rax, QWORD PTR [rcx+8] + movbe r8, QWORD PTR [rcx] + mov QWORD PTR [rdx+496], rax + mov QWORD PTR [rdx+504], r8 + ret +sp_4096_to_bin_movbe ENDP +_text ENDS +ENDIF +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_sub_in_place_64 PROC + mov r8, QWORD PTR [rcx] + xor rax, rax + sub r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rcx+8] + mov QWORD PTR [rcx], r8 + sbb r9, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rcx+16] + mov QWORD PTR [rcx+8], r9 + sbb r8, QWORD PTR [rdx+16] + mov r9, QWORD PTR [rcx+24] + mov QWORD PTR [rcx+16], r8 + sbb r9, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rcx+32] + mov QWORD PTR [rcx+24], r9 + sbb r8, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rcx+40] + mov QWORD PTR [rcx+32], r8 + sbb r9, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rcx+48] + mov QWORD PTR [rcx+40], r9 + sbb r8, QWORD PTR [rdx+48] + mov r9, QWORD PTR [rcx+56] + mov QWORD PTR [rcx+48], r8 + sbb r9, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rcx+64] + mov QWORD PTR [rcx+56], r9 + sbb r8, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rcx+72] + mov QWORD PTR [rcx+64], r8 + sbb r9, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rcx+80] + mov QWORD PTR [rcx+72], r9 + sbb r8, QWORD PTR [rdx+80] + mov r9, QWORD PTR [rcx+88] + mov QWORD PTR [rcx+80], r8 + sbb r9, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rcx+96] + mov QWORD PTR [rcx+88], r9 + sbb r8, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rcx+104] + mov QWORD PTR [rcx+96], r8 + sbb r9, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rcx+112] + mov QWORD PTR [rcx+104], r9 + sbb r8, QWORD PTR [rdx+112] + mov r9, QWORD PTR [rcx+120] + mov QWORD PTR [rcx+112], r8 + sbb r9, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rcx+128] + mov QWORD PTR [rcx+120], r9 + sbb r8, QWORD PTR [rdx+128] + mov r9, QWORD PTR [rcx+136] + mov QWORD PTR [rcx+128], r8 + sbb r9, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rcx+144] + mov QWORD PTR [rcx+136], r9 + sbb r8, QWORD PTR [rdx+144] + mov r9, QWORD PTR [rcx+152] + mov QWORD PTR [rcx+144], r8 + sbb r9, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rcx+160] + mov QWORD PTR [rcx+152], r9 + sbb r8, QWORD PTR [rdx+160] + mov r9, QWORD PTR [rcx+168] + mov QWORD PTR [rcx+160], r8 + sbb r9, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rcx+176] + mov QWORD PTR [rcx+168], r9 + sbb r8, QWORD PTR [rdx+176] + mov r9, QWORD PTR [rcx+184] + mov QWORD PTR [rcx+176], r8 + sbb r9, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rcx+192] + mov QWORD PTR [rcx+184], r9 + sbb r8, QWORD PTR [rdx+192] + mov r9, QWORD PTR [rcx+200] + mov QWORD PTR [rcx+192], r8 + sbb r9, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rcx+208] + mov QWORD PTR [rcx+200], r9 + sbb r8, QWORD PTR [rdx+208] + mov r9, QWORD PTR [rcx+216] + mov QWORD PTR [rcx+208], r8 + sbb r9, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rcx+224] + mov QWORD PTR [rcx+216], r9 + sbb r8, QWORD PTR [rdx+224] + mov r9, QWORD PTR [rcx+232] + mov QWORD PTR [rcx+224], r8 + sbb r9, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rcx+240] + mov QWORD PTR [rcx+232], r9 + sbb r8, QWORD PTR [rdx+240] + mov r9, QWORD PTR [rcx+248] + mov QWORD PTR [rcx+240], r8 + sbb r9, QWORD PTR [rdx+248] + mov r8, QWORD PTR [rcx+256] + mov QWORD PTR [rcx+248], r9 + sbb r8, QWORD PTR [rdx+256] + mov r9, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], r8 + sbb r9, QWORD PTR [rdx+264] + mov r8, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r9 + sbb r8, QWORD PTR [rdx+272] + mov r9, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], r8 + sbb r9, QWORD PTR [rdx+280] + mov r8, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r9 + sbb r8, QWORD PTR [rdx+288] + mov r9, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], r8 + sbb r9, QWORD PTR [rdx+296] + mov r8, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r9 + sbb r8, QWORD PTR [rdx+304] + mov r9, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], r8 + sbb r9, QWORD PTR [rdx+312] + mov r8, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r9 + sbb r8, QWORD PTR [rdx+320] + mov r9, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], r8 + sbb r9, QWORD PTR [rdx+328] + mov r8, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r9 + sbb r8, QWORD PTR [rdx+336] + mov r9, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], r8 + sbb r9, QWORD PTR [rdx+344] + mov r8, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r9 + sbb r8, QWORD PTR [rdx+352] + mov r9, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], r8 + sbb r9, QWORD PTR [rdx+360] + mov r8, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r9 + sbb r8, QWORD PTR [rdx+368] + mov r9, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], r8 + sbb r9, QWORD PTR [rdx+376] + mov r8, QWORD PTR [rcx+384] + mov QWORD PTR [rcx+376], r9 + sbb r8, QWORD PTR [rdx+384] + mov r9, QWORD PTR [rcx+392] + mov QWORD PTR [rcx+384], r8 + sbb r9, QWORD PTR [rdx+392] + mov r8, QWORD PTR [rcx+400] + mov QWORD PTR [rcx+392], r9 + sbb r8, QWORD PTR [rdx+400] + mov r9, QWORD PTR [rcx+408] + mov QWORD PTR [rcx+400], r8 + sbb r9, QWORD PTR [rdx+408] + mov r8, QWORD PTR [rcx+416] + mov QWORD PTR [rcx+408], r9 + sbb r8, QWORD PTR [rdx+416] + mov r9, QWORD PTR [rcx+424] + mov QWORD PTR [rcx+416], r8 + sbb r9, QWORD PTR [rdx+424] + mov r8, QWORD PTR [rcx+432] + mov QWORD PTR [rcx+424], r9 + sbb r8, QWORD PTR [rdx+432] + mov r9, QWORD PTR [rcx+440] + mov QWORD PTR [rcx+432], r8 + sbb r9, QWORD PTR [rdx+440] + mov r8, QWORD PTR [rcx+448] + mov QWORD PTR [rcx+440], r9 + sbb r8, QWORD PTR [rdx+448] + mov r9, QWORD PTR [rcx+456] + mov QWORD PTR [rcx+448], r8 + sbb r9, QWORD PTR [rdx+456] + mov r8, QWORD PTR [rcx+464] + mov QWORD PTR [rcx+456], r9 + sbb r8, QWORD PTR [rdx+464] + mov r9, QWORD PTR [rcx+472] + mov QWORD PTR [rcx+464], r8 + sbb r9, QWORD PTR [rdx+472] + mov r8, QWORD PTR [rcx+480] + mov QWORD PTR [rcx+472], r9 + sbb r8, QWORD PTR [rdx+480] + mov r9, QWORD PTR [rcx+488] + mov QWORD PTR [rcx+480], r8 + sbb r9, QWORD PTR [rdx+488] + mov r8, QWORD PTR [rcx+496] + mov QWORD PTR [rcx+488], r9 + sbb r8, QWORD PTR [rdx+496] + mov r9, QWORD PTR [rcx+504] + mov QWORD PTR [rcx+496], r8 + sbb r9, QWORD PTR [rdx+504] + mov QWORD PTR [rcx+504], r9 + sbb rax, 0 + ret +sp_4096_sub_in_place_64 ENDP +_text ENDS +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_add_64 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + adc r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + adc r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + adc r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + adc r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + adc r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + adc r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + adc r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + adc r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + adc r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + adc r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + adc r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + adc r10, QWORD PTR [r8+184] + mov r9, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r10 + adc r9, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r9 + adc r10, QWORD PTR [r8+200] + mov r9, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r10 + adc r9, QWORD PTR [r8+208] + mov r10, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r9 + adc r10, QWORD PTR [r8+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r10 + adc r9, QWORD PTR [r8+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r9 + adc r10, QWORD PTR [r8+232] + mov r9, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r10 + adc r9, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r9 + adc r10, QWORD PTR [r8+248] + mov r9, QWORD PTR [rdx+256] + mov QWORD PTR [rcx+248], r10 + adc r9, QWORD PTR [r8+256] + mov r10, QWORD PTR [rdx+264] + mov QWORD PTR [rcx+256], r9 + adc r10, QWORD PTR [r8+264] + mov r9, QWORD PTR [rdx+272] + mov QWORD PTR [rcx+264], r10 + adc r9, QWORD PTR [r8+272] + mov r10, QWORD PTR [rdx+280] + mov QWORD PTR [rcx+272], r9 + adc r10, QWORD PTR [r8+280] + mov r9, QWORD PTR [rdx+288] + mov QWORD PTR [rcx+280], r10 + adc r9, QWORD PTR [r8+288] + mov r10, QWORD PTR [rdx+296] + mov QWORD PTR [rcx+288], r9 + adc r10, QWORD PTR [r8+296] + mov r9, QWORD PTR [rdx+304] + mov QWORD PTR [rcx+296], r10 + adc r9, QWORD PTR [r8+304] + mov r10, QWORD PTR [rdx+312] + mov QWORD PTR [rcx+304], r9 + adc r10, QWORD PTR [r8+312] + mov r9, QWORD PTR [rdx+320] + mov QWORD PTR [rcx+312], r10 + adc r9, QWORD PTR [r8+320] + mov r10, QWORD PTR [rdx+328] + mov QWORD PTR [rcx+320], r9 + adc r10, QWORD PTR [r8+328] + mov r9, QWORD PTR [rdx+336] + mov QWORD PTR [rcx+328], r10 + adc r9, QWORD PTR [r8+336] + mov r10, QWORD PTR [rdx+344] + mov QWORD PTR [rcx+336], r9 + adc r10, QWORD PTR [r8+344] + mov r9, QWORD PTR [rdx+352] + mov QWORD PTR [rcx+344], r10 + adc r9, QWORD PTR [r8+352] + mov r10, QWORD PTR [rdx+360] + mov QWORD PTR [rcx+352], r9 + adc r10, QWORD PTR [r8+360] + mov r9, QWORD PTR [rdx+368] + mov QWORD PTR [rcx+360], r10 + adc r9, QWORD PTR [r8+368] + mov r10, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+368], r9 + adc r10, QWORD PTR [r8+376] + mov r9, QWORD PTR [rdx+384] + mov QWORD PTR [rcx+376], r10 + adc r9, QWORD PTR [r8+384] + mov r10, QWORD PTR [rdx+392] + mov QWORD PTR [rcx+384], r9 + adc r10, QWORD PTR [r8+392] + mov r9, QWORD PTR [rdx+400] + mov QWORD PTR [rcx+392], r10 + adc r9, QWORD PTR [r8+400] + mov r10, QWORD PTR [rdx+408] + mov QWORD PTR [rcx+400], r9 + adc r10, QWORD PTR [r8+408] + mov r9, QWORD PTR [rdx+416] + mov QWORD PTR [rcx+408], r10 + adc r9, QWORD PTR [r8+416] + mov r10, QWORD PTR [rdx+424] + mov QWORD PTR [rcx+416], r9 + adc r10, QWORD PTR [r8+424] + mov r9, QWORD PTR [rdx+432] + mov QWORD PTR [rcx+424], r10 + adc r9, QWORD PTR [r8+432] + mov r10, QWORD PTR [rdx+440] + mov QWORD PTR [rcx+432], r9 + adc r10, QWORD PTR [r8+440] + mov r9, QWORD PTR [rdx+448] + mov QWORD PTR [rcx+440], r10 + adc r9, QWORD PTR [r8+448] + mov r10, QWORD PTR [rdx+456] + mov QWORD PTR [rcx+448], r9 + adc r10, QWORD PTR [r8+456] + mov r9, QWORD PTR [rdx+464] + mov QWORD PTR [rcx+456], r10 + adc r9, QWORD PTR [r8+464] + mov r10, QWORD PTR [rdx+472] + mov QWORD PTR [rcx+464], r9 + adc r10, QWORD PTR [r8+472] + mov r9, QWORD PTR [rdx+480] + mov QWORD PTR [rcx+472], r10 + adc r9, QWORD PTR [r8+480] + mov r10, QWORD PTR [rdx+488] + mov QWORD PTR [rcx+480], r9 + adc r10, QWORD PTR [r8+488] + mov r9, QWORD PTR [rdx+496] + mov QWORD PTR [rcx+488], r10 + adc r9, QWORD PTR [r8+496] + mov r10, QWORD PTR [rdx+504] + mov QWORD PTR [rcx+496], r9 + adc r10, QWORD PTR [r8+504] + mov QWORD PTR [rcx+504], r10 + adc rax, 0 + ret +sp_4096_add_64 ENDP +_text ENDS +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_mul_64 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 1576 + mov QWORD PTR [rsp+1536], rcx + mov QWORD PTR [rsp+1544], rdx + mov QWORD PTR [rsp+1552], r8 + lea r12, QWORD PTR [rsp+1024] + lea r14, QWORD PTR [rdx+256] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r12+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [r12+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [rdx+112] + mov QWORD PTR [r12+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r12+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [r12+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [r12+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r12+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [rdx+152] + mov QWORD PTR [r12+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [rdx+160] + mov QWORD PTR [r12+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [r12+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [r12+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [r12+176], r9 + adc r10, QWORD PTR [r14+184] + mov rax, QWORD PTR [rdx+192] + mov QWORD PTR [r12+184], r10 + adc rax, QWORD PTR [r14+192] + mov r9, QWORD PTR [rdx+200] + mov QWORD PTR [r12+192], rax + adc r9, QWORD PTR [r14+200] + mov r10, QWORD PTR [rdx+208] + mov QWORD PTR [r12+200], r9 + adc r10, QWORD PTR [r14+208] + mov rax, QWORD PTR [rdx+216] + mov QWORD PTR [r12+208], r10 + adc rax, QWORD PTR [r14+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [r12+216], rax + adc r9, QWORD PTR [r14+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [r12+224], r9 + adc r10, QWORD PTR [r14+232] + mov rax, QWORD PTR [rdx+240] + mov QWORD PTR [r12+232], r10 + adc rax, QWORD PTR [r14+240] + mov r9, QWORD PTR [rdx+248] + mov QWORD PTR [r12+240], rax + adc r9, QWORD PTR [r14+248] + mov QWORD PTR [r12+248], r9 + adc r15, 0 + mov QWORD PTR [rsp+1560], r15 + lea r13, QWORD PTR [rsp+1280] + lea r14, QWORD PTR [r8+256] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [r8+96] + mov QWORD PTR [r13+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [r8+104] + mov QWORD PTR [r13+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [r8+112] + mov QWORD PTR [r13+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [r8+120] + mov QWORD PTR [r13+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [r8+128] + mov QWORD PTR [r13+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [r8+136] + mov QWORD PTR [r13+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [r8+144] + mov QWORD PTR [r13+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [r8+152] + mov QWORD PTR [r13+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [r8+160] + mov QWORD PTR [r13+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [r8+168] + mov QWORD PTR [r13+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [r8+176] + mov QWORD PTR [r13+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [r8+184] + mov QWORD PTR [r13+176], r9 + adc r10, QWORD PTR [r14+184] + mov rax, QWORD PTR [r8+192] + mov QWORD PTR [r13+184], r10 + adc rax, QWORD PTR [r14+192] + mov r9, QWORD PTR [r8+200] + mov QWORD PTR [r13+192], rax + adc r9, QWORD PTR [r14+200] + mov r10, QWORD PTR [r8+208] + mov QWORD PTR [r13+200], r9 + adc r10, QWORD PTR [r14+208] + mov rax, QWORD PTR [r8+216] + mov QWORD PTR [r13+208], r10 + adc rax, QWORD PTR [r14+216] + mov r9, QWORD PTR [r8+224] + mov QWORD PTR [r13+216], rax + adc r9, QWORD PTR [r14+224] + mov r10, QWORD PTR [r8+232] + mov QWORD PTR [r13+224], r9 + adc r10, QWORD PTR [r14+232] + mov rax, QWORD PTR [r8+240] + mov QWORD PTR [r13+232], r10 + adc rax, QWORD PTR [r14+240] + mov r9, QWORD PTR [r8+248] + mov QWORD PTR [r13+240], rax + adc r9, QWORD PTR [r14+248] + mov QWORD PTR [r13+248], r9 + adc rdi, 0 + mov QWORD PTR [rsp+1568], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_2048_mul_32 + mov r8, QWORD PTR [rsp+1552] + mov rdx, QWORD PTR [rsp+1544] + lea rcx, QWORD PTR [rsp+512] + add r8, 256 + add rdx, 256 + call sp_2048_mul_32 + mov r8, QWORD PTR [rsp+1552] + mov rdx, QWORD PTR [rsp+1544] + mov rcx, QWORD PTR [rsp+1536] + call sp_2048_mul_32 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+1552] + mov rdx, QWORD PTR [rsp+1544] + mov rcx, QWORD PTR [rsp+1536] +ENDIF + mov r15, QWORD PTR [rsp+1560] + mov rdi, QWORD PTR [rsp+1568] + mov rsi, QWORD PTR [rsp+1536] + mov r11, r15 + lea r12, QWORD PTR [rsp+1024] + lea r13, QWORD PTR [rsp+1280] + and r11, rdi + neg r15 + neg rdi + add rsi, 512 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12], rax + mov QWORD PTR [r13], r9 + mov rax, QWORD PTR [r12+8] + mov r9, QWORD PTR [r13+8] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+8], rax + mov QWORD PTR [r13+8], r9 + mov rax, QWORD PTR [r12+16] + mov r9, QWORD PTR [r13+16] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+16], rax + mov QWORD PTR [r13+16], r9 + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+24], rax + mov QWORD PTR [r13+24], r9 + mov rax, QWORD PTR [r12+32] + mov r9, QWORD PTR [r13+32] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+32], rax + mov QWORD PTR [r13+32], r9 + mov rax, QWORD PTR [r12+40] + mov r9, QWORD PTR [r13+40] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+40], rax + mov QWORD PTR [r13+40], r9 + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+48], rax + mov QWORD PTR [r13+48], r9 + mov rax, QWORD PTR [r12+56] + mov r9, QWORD PTR [r13+56] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+56], rax + mov QWORD PTR [r13+56], r9 + mov rax, QWORD PTR [r12+64] + mov r9, QWORD PTR [r13+64] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+64], rax + mov QWORD PTR [r13+64], r9 + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+72], rax + mov QWORD PTR [r13+72], r9 + mov rax, QWORD PTR [r12+80] + mov r9, QWORD PTR [r13+80] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+80], rax + mov QWORD PTR [r13+80], r9 + mov rax, QWORD PTR [r12+88] + mov r9, QWORD PTR [r13+88] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+88], rax + mov QWORD PTR [r13+88], r9 + mov rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [r13+96] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+96], rax + mov QWORD PTR [r13+96], r9 + mov rax, QWORD PTR [r12+104] + mov r9, QWORD PTR [r13+104] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+104], rax + mov QWORD PTR [r13+104], r9 + mov rax, QWORD PTR [r12+112] + mov r9, QWORD PTR [r13+112] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+112], rax + mov QWORD PTR [r13+112], r9 + mov rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [r13+120] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+120], rax + mov QWORD PTR [r13+120], r9 + mov rax, QWORD PTR [r12+128] + mov r9, QWORD PTR [r13+128] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+128], rax + mov QWORD PTR [r13+128], r9 + mov rax, QWORD PTR [r12+136] + mov r9, QWORD PTR [r13+136] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+136], rax + mov QWORD PTR [r13+136], r9 + mov rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [r13+144] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+144], rax + mov QWORD PTR [r13+144], r9 + mov rax, QWORD PTR [r12+152] + mov r9, QWORD PTR [r13+152] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+152], rax + mov QWORD PTR [r13+152], r9 + mov rax, QWORD PTR [r12+160] + mov r9, QWORD PTR [r13+160] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+160], rax + mov QWORD PTR [r13+160], r9 + mov rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [r13+168] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+168], rax + mov QWORD PTR [r13+168], r9 + mov rax, QWORD PTR [r12+176] + mov r9, QWORD PTR [r13+176] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+176], rax + mov QWORD PTR [r13+176], r9 + mov rax, QWORD PTR [r12+184] + mov r9, QWORD PTR [r13+184] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+184], rax + mov QWORD PTR [r13+184], r9 + mov rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [r13+192] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+192], rax + mov QWORD PTR [r13+192], r9 + mov rax, QWORD PTR [r12+200] + mov r9, QWORD PTR [r13+200] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+200], rax + mov QWORD PTR [r13+200], r9 + mov rax, QWORD PTR [r12+208] + mov r9, QWORD PTR [r13+208] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+208], rax + mov QWORD PTR [r13+208], r9 + mov rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [r13+216] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+216], rax + mov QWORD PTR [r13+216], r9 + mov rax, QWORD PTR [r12+224] + mov r9, QWORD PTR [r13+224] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+224], rax + mov QWORD PTR [r13+224], r9 + mov rax, QWORD PTR [r12+232] + mov r9, QWORD PTR [r13+232] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+232], rax + mov QWORD PTR [r13+232], r9 + mov rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [r13+240] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+240], rax + mov QWORD PTR [r13+240], r9 + mov rax, QWORD PTR [r12+248] + mov r9, QWORD PTR [r13+248] + and rax, rdi + and r9, r15 + mov QWORD PTR [r12+248], rax + mov QWORD PTR [r13+248], r9 + mov rax, QWORD PTR [r12] + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r13+248] + mov QWORD PTR [rsi+248], r9 + adc r11, 0 + lea r13, QWORD PTR [rsp+512] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [r13+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [r13+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [r13+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [r13+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [r13+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [r13+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [r13+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [r13+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [r13+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [r13+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [r13+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [r13+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [r13+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [r13+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [r13+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [r13+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [r13+376] + mov rax, QWORD PTR [r12+384] + mov QWORD PTR [r12+376], r10 + sbb rax, QWORD PTR [r13+384] + mov r9, QWORD PTR [r12+392] + mov QWORD PTR [r12+384], rax + sbb r9, QWORD PTR [r13+392] + mov r10, QWORD PTR [r12+400] + mov QWORD PTR [r12+392], r9 + sbb r10, QWORD PTR [r13+400] + mov rax, QWORD PTR [r12+408] + mov QWORD PTR [r12+400], r10 + sbb rax, QWORD PTR [r13+408] + mov r9, QWORD PTR [r12+416] + mov QWORD PTR [r12+408], rax + sbb r9, QWORD PTR [r13+416] + mov r10, QWORD PTR [r12+424] + mov QWORD PTR [r12+416], r9 + sbb r10, QWORD PTR [r13+424] + mov rax, QWORD PTR [r12+432] + mov QWORD PTR [r12+424], r10 + sbb rax, QWORD PTR [r13+432] + mov r9, QWORD PTR [r12+440] + mov QWORD PTR [r12+432], rax + sbb r9, QWORD PTR [r13+440] + mov r10, QWORD PTR [r12+448] + mov QWORD PTR [r12+440], r9 + sbb r10, QWORD PTR [r13+448] + mov rax, QWORD PTR [r12+456] + mov QWORD PTR [r12+448], r10 + sbb rax, QWORD PTR [r13+456] + mov r9, QWORD PTR [r12+464] + mov QWORD PTR [r12+456], rax + sbb r9, QWORD PTR [r13+464] + mov r10, QWORD PTR [r12+472] + mov QWORD PTR [r12+464], r9 + sbb r10, QWORD PTR [r13+472] + mov rax, QWORD PTR [r12+480] + mov QWORD PTR [r12+472], r10 + sbb rax, QWORD PTR [r13+480] + mov r9, QWORD PTR [r12+488] + mov QWORD PTR [r12+480], rax + sbb r9, QWORD PTR [r13+488] + mov r10, QWORD PTR [r12+496] + mov QWORD PTR [r12+488], r9 + sbb r10, QWORD PTR [r13+496] + mov rax, QWORD PTR [r12+504] + mov QWORD PTR [r12+496], r10 + sbb rax, QWORD PTR [r13+504] + mov QWORD PTR [r12+504], rax + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [rcx+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [rcx+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [rcx+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [rcx+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [rcx+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [rcx+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [rcx+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [rcx+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [rcx+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [rcx+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [rcx+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [rcx+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [rcx+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [rcx+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [rcx+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [rcx+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [rcx+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [rcx+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [rcx+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [rcx+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [rcx+376] + mov rax, QWORD PTR [r12+384] + mov QWORD PTR [r12+376], r10 + sbb rax, QWORD PTR [rcx+384] + mov r9, QWORD PTR [r12+392] + mov QWORD PTR [r12+384], rax + sbb r9, QWORD PTR [rcx+392] + mov r10, QWORD PTR [r12+400] + mov QWORD PTR [r12+392], r9 + sbb r10, QWORD PTR [rcx+400] + mov rax, QWORD PTR [r12+408] + mov QWORD PTR [r12+400], r10 + sbb rax, QWORD PTR [rcx+408] + mov r9, QWORD PTR [r12+416] + mov QWORD PTR [r12+408], rax + sbb r9, QWORD PTR [rcx+416] + mov r10, QWORD PTR [r12+424] + mov QWORD PTR [r12+416], r9 + sbb r10, QWORD PTR [rcx+424] + mov rax, QWORD PTR [r12+432] + mov QWORD PTR [r12+424], r10 + sbb rax, QWORD PTR [rcx+432] + mov r9, QWORD PTR [r12+440] + mov QWORD PTR [r12+432], rax + sbb r9, QWORD PTR [rcx+440] + mov r10, QWORD PTR [r12+448] + mov QWORD PTR [r12+440], r9 + sbb r10, QWORD PTR [rcx+448] + mov rax, QWORD PTR [r12+456] + mov QWORD PTR [r12+448], r10 + sbb rax, QWORD PTR [rcx+456] + mov r9, QWORD PTR [r12+464] + mov QWORD PTR [r12+456], rax + sbb r9, QWORD PTR [rcx+464] + mov r10, QWORD PTR [r12+472] + mov QWORD PTR [r12+464], r9 + sbb r10, QWORD PTR [rcx+472] + mov rax, QWORD PTR [r12+480] + mov QWORD PTR [r12+472], r10 + sbb rax, QWORD PTR [rcx+480] + mov r9, QWORD PTR [r12+488] + mov QWORD PTR [r12+480], rax + sbb r9, QWORD PTR [rcx+488] + mov r10, QWORD PTR [r12+496] + mov QWORD PTR [r12+488], r9 + sbb r10, QWORD PTR [rcx+496] + mov rax, QWORD PTR [r12+504] + mov QWORD PTR [r12+496], r10 + sbb rax, QWORD PTR [rcx+504] + mov QWORD PTR [r12+504], rax + sbb r11, 0 + sub rsi, 256 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r12+248] + mov r10, QWORD PTR [rsi+256] + mov QWORD PTR [rsi+248], r9 + adc r10, QWORD PTR [r12+256] + mov rax, QWORD PTR [rsi+264] + mov QWORD PTR [rsi+256], r10 + adc rax, QWORD PTR [r12+264] + mov r9, QWORD PTR [rsi+272] + mov QWORD PTR [rsi+264], rax + adc r9, QWORD PTR [r12+272] + mov r10, QWORD PTR [rsi+280] + mov QWORD PTR [rsi+272], r9 + adc r10, QWORD PTR [r12+280] + mov rax, QWORD PTR [rsi+288] + mov QWORD PTR [rsi+280], r10 + adc rax, QWORD PTR [r12+288] + mov r9, QWORD PTR [rsi+296] + mov QWORD PTR [rsi+288], rax + adc r9, QWORD PTR [r12+296] + mov r10, QWORD PTR [rsi+304] + mov QWORD PTR [rsi+296], r9 + adc r10, QWORD PTR [r12+304] + mov rax, QWORD PTR [rsi+312] + mov QWORD PTR [rsi+304], r10 + adc rax, QWORD PTR [r12+312] + mov r9, QWORD PTR [rsi+320] + mov QWORD PTR [rsi+312], rax + adc r9, QWORD PTR [r12+320] + mov r10, QWORD PTR [rsi+328] + mov QWORD PTR [rsi+320], r9 + adc r10, QWORD PTR [r12+328] + mov rax, QWORD PTR [rsi+336] + mov QWORD PTR [rsi+328], r10 + adc rax, QWORD PTR [r12+336] + mov r9, QWORD PTR [rsi+344] + mov QWORD PTR [rsi+336], rax + adc r9, QWORD PTR [r12+344] + mov r10, QWORD PTR [rsi+352] + mov QWORD PTR [rsi+344], r9 + adc r10, QWORD PTR [r12+352] + mov rax, QWORD PTR [rsi+360] + mov QWORD PTR [rsi+352], r10 + adc rax, QWORD PTR [r12+360] + mov r9, QWORD PTR [rsi+368] + mov QWORD PTR [rsi+360], rax + adc r9, QWORD PTR [r12+368] + mov r10, QWORD PTR [rsi+376] + mov QWORD PTR [rsi+368], r9 + adc r10, QWORD PTR [r12+376] + mov rax, QWORD PTR [rsi+384] + mov QWORD PTR [rsi+376], r10 + adc rax, QWORD PTR [r12+384] + mov r9, QWORD PTR [rsi+392] + mov QWORD PTR [rsi+384], rax + adc r9, QWORD PTR [r12+392] + mov r10, QWORD PTR [rsi+400] + mov QWORD PTR [rsi+392], r9 + adc r10, QWORD PTR [r12+400] + mov rax, QWORD PTR [rsi+408] + mov QWORD PTR [rsi+400], r10 + adc rax, QWORD PTR [r12+408] + mov r9, QWORD PTR [rsi+416] + mov QWORD PTR [rsi+408], rax + adc r9, QWORD PTR [r12+416] + mov r10, QWORD PTR [rsi+424] + mov QWORD PTR [rsi+416], r9 + adc r10, QWORD PTR [r12+424] + mov rax, QWORD PTR [rsi+432] + mov QWORD PTR [rsi+424], r10 + adc rax, QWORD PTR [r12+432] + mov r9, QWORD PTR [rsi+440] + mov QWORD PTR [rsi+432], rax + adc r9, QWORD PTR [r12+440] + mov r10, QWORD PTR [rsi+448] + mov QWORD PTR [rsi+440], r9 + adc r10, QWORD PTR [r12+448] + mov rax, QWORD PTR [rsi+456] + mov QWORD PTR [rsi+448], r10 + adc rax, QWORD PTR [r12+456] + mov r9, QWORD PTR [rsi+464] + mov QWORD PTR [rsi+456], rax + adc r9, QWORD PTR [r12+464] + mov r10, QWORD PTR [rsi+472] + mov QWORD PTR [rsi+464], r9 + adc r10, QWORD PTR [r12+472] + mov rax, QWORD PTR [rsi+480] + mov QWORD PTR [rsi+472], r10 + adc rax, QWORD PTR [r12+480] + mov r9, QWORD PTR [rsi+488] + mov QWORD PTR [rsi+480], rax + adc r9, QWORD PTR [r12+488] + mov r10, QWORD PTR [rsi+496] + mov QWORD PTR [rsi+488], r9 + adc r10, QWORD PTR [r12+496] + mov rax, QWORD PTR [rsi+504] + mov QWORD PTR [rsi+496], r10 + adc rax, QWORD PTR [r12+504] + mov QWORD PTR [rsi+504], rax + adc r11, 0 + mov QWORD PTR [rcx+768], r11 + add rsi, 256 + ; Add + mov rax, QWORD PTR [rsi] + xor r11, r11 + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r13+248] + mov r10, QWORD PTR [rsi+256] + mov QWORD PTR [rsi+248], r9 + adc r10, QWORD PTR [r13+256] + mov QWORD PTR [rsi+256], r10 + adc r11, 0 + ; Add to zero + mov rax, QWORD PTR [r13+264] + adc rax, 0 + mov r9, QWORD PTR [r13+272] + mov QWORD PTR [rsi+264], rax + adc r9, 0 + mov r10, QWORD PTR [r13+280] + mov QWORD PTR [rsi+272], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+288] + mov QWORD PTR [rsi+280], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+296] + mov QWORD PTR [rsi+288], rax + adc r9, 0 + mov r10, QWORD PTR [r13+304] + mov QWORD PTR [rsi+296], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+312] + mov QWORD PTR [rsi+304], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+320] + mov QWORD PTR [rsi+312], rax + adc r9, 0 + mov r10, QWORD PTR [r13+328] + mov QWORD PTR [rsi+320], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+336] + mov QWORD PTR [rsi+328], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+344] + mov QWORD PTR [rsi+336], rax + adc r9, 0 + mov r10, QWORD PTR [r13+352] + mov QWORD PTR [rsi+344], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+360] + mov QWORD PTR [rsi+352], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+368] + mov QWORD PTR [rsi+360], rax + adc r9, 0 + mov r10, QWORD PTR [r13+376] + mov QWORD PTR [rsi+368], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+384] + mov QWORD PTR [rsi+376], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+392] + mov QWORD PTR [rsi+384], rax + adc r9, 0 + mov r10, QWORD PTR [r13+400] + mov QWORD PTR [rsi+392], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+408] + mov QWORD PTR [rsi+400], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+416] + mov QWORD PTR [rsi+408], rax + adc r9, 0 + mov r10, QWORD PTR [r13+424] + mov QWORD PTR [rsi+416], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+432] + mov QWORD PTR [rsi+424], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+440] + mov QWORD PTR [rsi+432], rax + adc r9, 0 + mov r10, QWORD PTR [r13+448] + mov QWORD PTR [rsi+440], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+456] + mov QWORD PTR [rsi+448], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+464] + mov QWORD PTR [rsi+456], rax + adc r9, 0 + mov r10, QWORD PTR [r13+472] + mov QWORD PTR [rsi+464], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+480] + mov QWORD PTR [rsi+472], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+488] + mov QWORD PTR [rsi+480], rax + adc r9, 0 + mov r10, QWORD PTR [r13+496] + mov QWORD PTR [rsi+488], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+504] + mov QWORD PTR [rsi+496], r10 + adc rax, 0 + mov QWORD PTR [rsi+504], rax + add rsp, 1576 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_4096_mul_64 ENDP +_text ENDS +; /* Add a to a into r. (r = a + a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_2048_dbl_32 PROC + mov r8, QWORD PTR [rdx] + xor rax, rax + add r8, r8 + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r8 + adc r9, r9 + mov QWORD PTR [rcx+248], r9 + adc rax, 0 + ret +sp_2048_dbl_32 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_sqr_64 PROC + push r12 + sub rsp, 1304 + mov QWORD PTR [rsp+1280], rcx + mov QWORD PTR [rsp+1288], rdx + lea r10, QWORD PTR [rsp+1024] + lea r11, QWORD PTR [rdx+256] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r10+88], r8 + adc rax, QWORD PTR [r11+96] + mov r8, QWORD PTR [rdx+104] + mov QWORD PTR [r10+96], rax + adc r8, QWORD PTR [r11+104] + mov rax, QWORD PTR [rdx+112] + mov QWORD PTR [r10+104], r8 + adc rax, QWORD PTR [r11+112] + mov r8, QWORD PTR [rdx+120] + mov QWORD PTR [r10+112], rax + adc r8, QWORD PTR [r11+120] + mov rax, QWORD PTR [rdx+128] + mov QWORD PTR [r10+120], r8 + adc rax, QWORD PTR [r11+128] + mov r8, QWORD PTR [rdx+136] + mov QWORD PTR [r10+128], rax + adc r8, QWORD PTR [r11+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r10+136], r8 + adc rax, QWORD PTR [r11+144] + mov r8, QWORD PTR [rdx+152] + mov QWORD PTR [r10+144], rax + adc r8, QWORD PTR [r11+152] + mov rax, QWORD PTR [rdx+160] + mov QWORD PTR [r10+152], r8 + adc rax, QWORD PTR [r11+160] + mov r8, QWORD PTR [rdx+168] + mov QWORD PTR [r10+160], rax + adc r8, QWORD PTR [r11+168] + mov rax, QWORD PTR [rdx+176] + mov QWORD PTR [r10+168], r8 + adc rax, QWORD PTR [r11+176] + mov r8, QWORD PTR [rdx+184] + mov QWORD PTR [r10+176], rax + adc r8, QWORD PTR [r11+184] + mov rax, QWORD PTR [rdx+192] + mov QWORD PTR [r10+184], r8 + adc rax, QWORD PTR [r11+192] + mov r8, QWORD PTR [rdx+200] + mov QWORD PTR [r10+192], rax + adc r8, QWORD PTR [r11+200] + mov rax, QWORD PTR [rdx+208] + mov QWORD PTR [r10+200], r8 + adc rax, QWORD PTR [r11+208] + mov r8, QWORD PTR [rdx+216] + mov QWORD PTR [r10+208], rax + adc r8, QWORD PTR [r11+216] + mov rax, QWORD PTR [rdx+224] + mov QWORD PTR [r10+216], r8 + adc rax, QWORD PTR [r11+224] + mov r8, QWORD PTR [rdx+232] + mov QWORD PTR [r10+224], rax + adc r8, QWORD PTR [r11+232] + mov rax, QWORD PTR [rdx+240] + mov QWORD PTR [r10+232], r8 + adc rax, QWORD PTR [r11+240] + mov r8, QWORD PTR [rdx+248] + mov QWORD PTR [r10+240], rax + adc r8, QWORD PTR [r11+248] + mov QWORD PTR [r10+248], r8 + adc r9, 0 + mov QWORD PTR [rsp+1296], r9 + mov rdx, r10 + mov rcx, rsp + call sp_2048_sqr_32 + mov rdx, QWORD PTR [rsp+1288] + lea rcx, QWORD PTR [rsp+512] + add rdx, 256 + call sp_2048_sqr_32 + mov rdx, QWORD PTR [rsp+1288] + mov rcx, QWORD PTR [rsp+1280] + call sp_2048_sqr_32 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+1288] + mov rcx, QWORD PTR [rsp+1280] +ENDIF + mov r12, QWORD PTR [rsp+1296] + lea r10, QWORD PTR [rsp+1024] + mov r9, r12 + neg r12 + mov rax, QWORD PTR [r10] + mov r8, QWORD PTR [r10+8] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+512], rax + mov QWORD PTR [rcx+520], r8 + mov rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [r10+24] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+528], rax + mov QWORD PTR [rcx+536], r8 + mov rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [r10+40] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+544], rax + mov QWORD PTR [rcx+552], r8 + mov rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [r10+56] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+560], rax + mov QWORD PTR [rcx+568], r8 + mov rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [r10+72] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+576], rax + mov QWORD PTR [rcx+584], r8 + mov rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [r10+88] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+592], rax + mov QWORD PTR [rcx+600], r8 + mov rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [r10+104] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+608], rax + mov QWORD PTR [rcx+616], r8 + mov rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [r10+120] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+624], rax + mov QWORD PTR [rcx+632], r8 + mov rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [r10+136] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+640], rax + mov QWORD PTR [rcx+648], r8 + mov rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [r10+152] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+656], rax + mov QWORD PTR [rcx+664], r8 + mov rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [r10+168] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+672], rax + mov QWORD PTR [rcx+680], r8 + mov rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [r10+184] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+688], rax + mov QWORD PTR [rcx+696], r8 + mov rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [r10+200] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+704], rax + mov QWORD PTR [rcx+712], r8 + mov rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [r10+216] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+720], rax + mov QWORD PTR [rcx+728], r8 + mov rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [r10+232] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+736], rax + mov QWORD PTR [rcx+744], r8 + mov rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [r10+248] + and rax, r12 + and r8, r12 + mov QWORD PTR [rcx+752], rax + mov QWORD PTR [rcx+760], r8 + mov rax, QWORD PTR [rcx+512] + add rax, rax + mov r8, QWORD PTR [rcx+520] + mov QWORD PTR [rcx+512], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+528] + mov QWORD PTR [rcx+520], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+536] + mov QWORD PTR [rcx+528], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+544] + mov QWORD PTR [rcx+536], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+552] + mov QWORD PTR [rcx+544], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+560] + mov QWORD PTR [rcx+552], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+568] + mov QWORD PTR [rcx+560], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+576] + mov QWORD PTR [rcx+568], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+584] + mov QWORD PTR [rcx+576], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+592] + mov QWORD PTR [rcx+584], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+600] + mov QWORD PTR [rcx+592], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+608] + mov QWORD PTR [rcx+600], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+616] + mov QWORD PTR [rcx+608], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+624] + mov QWORD PTR [rcx+616], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+632] + mov QWORD PTR [rcx+624], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+640] + mov QWORD PTR [rcx+632], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+648] + mov QWORD PTR [rcx+640], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+656] + mov QWORD PTR [rcx+648], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+664] + mov QWORD PTR [rcx+656], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+672] + mov QWORD PTR [rcx+664], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+680] + mov QWORD PTR [rcx+672], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+688] + mov QWORD PTR [rcx+680], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+696] + mov QWORD PTR [rcx+688], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+704] + mov QWORD PTR [rcx+696], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+712] + mov QWORD PTR [rcx+704], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+720] + mov QWORD PTR [rcx+712], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+728] + mov QWORD PTR [rcx+720], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+736] + mov QWORD PTR [rcx+728], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+744] + mov QWORD PTR [rcx+736], rax + adc r8, r8 + mov rax, QWORD PTR [rcx+752] + mov QWORD PTR [rcx+744], r8 + adc rax, rax + mov r8, QWORD PTR [rcx+760] + mov QWORD PTR [rcx+752], rax + adc r8, r8 + mov QWORD PTR [rcx+760], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+512] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rdx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rdx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rdx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rdx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rdx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rdx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rdx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rdx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rdx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rdx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rdx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rdx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rdx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rdx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rdx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rdx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rdx+376] + mov rax, QWORD PTR [r10+384] + mov QWORD PTR [r10+376], r8 + sbb rax, QWORD PTR [rdx+384] + mov r8, QWORD PTR [r10+392] + mov QWORD PTR [r10+384], rax + sbb r8, QWORD PTR [rdx+392] + mov rax, QWORD PTR [r10+400] + mov QWORD PTR [r10+392], r8 + sbb rax, QWORD PTR [rdx+400] + mov r8, QWORD PTR [r10+408] + mov QWORD PTR [r10+400], rax + sbb r8, QWORD PTR [rdx+408] + mov rax, QWORD PTR [r10+416] + mov QWORD PTR [r10+408], r8 + sbb rax, QWORD PTR [rdx+416] + mov r8, QWORD PTR [r10+424] + mov QWORD PTR [r10+416], rax + sbb r8, QWORD PTR [rdx+424] + mov rax, QWORD PTR [r10+432] + mov QWORD PTR [r10+424], r8 + sbb rax, QWORD PTR [rdx+432] + mov r8, QWORD PTR [r10+440] + mov QWORD PTR [r10+432], rax + sbb r8, QWORD PTR [rdx+440] + mov rax, QWORD PTR [r10+448] + mov QWORD PTR [r10+440], r8 + sbb rax, QWORD PTR [rdx+448] + mov r8, QWORD PTR [r10+456] + mov QWORD PTR [r10+448], rax + sbb r8, QWORD PTR [rdx+456] + mov rax, QWORD PTR [r10+464] + mov QWORD PTR [r10+456], r8 + sbb rax, QWORD PTR [rdx+464] + mov r8, QWORD PTR [r10+472] + mov QWORD PTR [r10+464], rax + sbb r8, QWORD PTR [rdx+472] + mov rax, QWORD PTR [r10+480] + mov QWORD PTR [r10+472], r8 + sbb rax, QWORD PTR [rdx+480] + mov r8, QWORD PTR [r10+488] + mov QWORD PTR [r10+480], rax + sbb r8, QWORD PTR [rdx+488] + mov rax, QWORD PTR [r10+496] + mov QWORD PTR [r10+488], r8 + sbb rax, QWORD PTR [rdx+496] + mov r8, QWORD PTR [r10+504] + mov QWORD PTR [r10+496], rax + sbb r8, QWORD PTR [rdx+504] + mov QWORD PTR [r10+504], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rcx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rcx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rcx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rcx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rcx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rcx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rcx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rcx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rcx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rcx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rcx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rcx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rcx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rcx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rcx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rcx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rcx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rcx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rcx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rcx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rcx+376] + mov rax, QWORD PTR [r10+384] + mov QWORD PTR [r10+376], r8 + sbb rax, QWORD PTR [rcx+384] + mov r8, QWORD PTR [r10+392] + mov QWORD PTR [r10+384], rax + sbb r8, QWORD PTR [rcx+392] + mov rax, QWORD PTR [r10+400] + mov QWORD PTR [r10+392], r8 + sbb rax, QWORD PTR [rcx+400] + mov r8, QWORD PTR [r10+408] + mov QWORD PTR [r10+400], rax + sbb r8, QWORD PTR [rcx+408] + mov rax, QWORD PTR [r10+416] + mov QWORD PTR [r10+408], r8 + sbb rax, QWORD PTR [rcx+416] + mov r8, QWORD PTR [r10+424] + mov QWORD PTR [r10+416], rax + sbb r8, QWORD PTR [rcx+424] + mov rax, QWORD PTR [r10+432] + mov QWORD PTR [r10+424], r8 + sbb rax, QWORD PTR [rcx+432] + mov r8, QWORD PTR [r10+440] + mov QWORD PTR [r10+432], rax + sbb r8, QWORD PTR [rcx+440] + mov rax, QWORD PTR [r10+448] + mov QWORD PTR [r10+440], r8 + sbb rax, QWORD PTR [rcx+448] + mov r8, QWORD PTR [r10+456] + mov QWORD PTR [r10+448], rax + sbb r8, QWORD PTR [rcx+456] + mov rax, QWORD PTR [r10+464] + mov QWORD PTR [r10+456], r8 + sbb rax, QWORD PTR [rcx+464] + mov r8, QWORD PTR [r10+472] + mov QWORD PTR [r10+464], rax + sbb r8, QWORD PTR [rcx+472] + mov rax, QWORD PTR [r10+480] + mov QWORD PTR [r10+472], r8 + sbb rax, QWORD PTR [rcx+480] + mov r8, QWORD PTR [r10+488] + mov QWORD PTR [r10+480], rax + sbb r8, QWORD PTR [rcx+488] + mov rax, QWORD PTR [r10+496] + mov QWORD PTR [r10+488], r8 + sbb rax, QWORD PTR [rcx+496] + mov r8, QWORD PTR [r10+504] + mov QWORD PTR [r10+496], rax + sbb r8, QWORD PTR [rcx+504] + mov QWORD PTR [r10+504], r8 + sbb r9, 0 + ; Add in place + mov rax, QWORD PTR [rcx+256] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [rcx+384] + mov QWORD PTR [rcx+376], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [rcx+392] + mov QWORD PTR [rcx+384], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [rcx+400] + mov QWORD PTR [rcx+392], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [rcx+408] + mov QWORD PTR [rcx+400], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [rcx+416] + mov QWORD PTR [rcx+408], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [rcx+424] + mov QWORD PTR [rcx+416], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [rcx+432] + mov QWORD PTR [rcx+424], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [rcx+440] + mov QWORD PTR [rcx+432], rax + adc r8, QWORD PTR [r10+184] + mov rax, QWORD PTR [rcx+448] + mov QWORD PTR [rcx+440], r8 + adc rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [rcx+456] + mov QWORD PTR [rcx+448], rax + adc r8, QWORD PTR [r10+200] + mov rax, QWORD PTR [rcx+464] + mov QWORD PTR [rcx+456], r8 + adc rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [rcx+472] + mov QWORD PTR [rcx+464], rax + adc r8, QWORD PTR [r10+216] + mov rax, QWORD PTR [rcx+480] + mov QWORD PTR [rcx+472], r8 + adc rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [rcx+488] + mov QWORD PTR [rcx+480], rax + adc r8, QWORD PTR [r10+232] + mov rax, QWORD PTR [rcx+496] + mov QWORD PTR [rcx+488], r8 + adc rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [rcx+504] + mov QWORD PTR [rcx+496], rax + adc r8, QWORD PTR [r10+248] + mov rax, QWORD PTR [rcx+512] + mov QWORD PTR [rcx+504], r8 + adc rax, QWORD PTR [r10+256] + mov r8, QWORD PTR [rcx+520] + mov QWORD PTR [rcx+512], rax + adc r8, QWORD PTR [r10+264] + mov rax, QWORD PTR [rcx+528] + mov QWORD PTR [rcx+520], r8 + adc rax, QWORD PTR [r10+272] + mov r8, QWORD PTR [rcx+536] + mov QWORD PTR [rcx+528], rax + adc r8, QWORD PTR [r10+280] + mov rax, QWORD PTR [rcx+544] + mov QWORD PTR [rcx+536], r8 + adc rax, QWORD PTR [r10+288] + mov r8, QWORD PTR [rcx+552] + mov QWORD PTR [rcx+544], rax + adc r8, QWORD PTR [r10+296] + mov rax, QWORD PTR [rcx+560] + mov QWORD PTR [rcx+552], r8 + adc rax, QWORD PTR [r10+304] + mov r8, QWORD PTR [rcx+568] + mov QWORD PTR [rcx+560], rax + adc r8, QWORD PTR [r10+312] + mov rax, QWORD PTR [rcx+576] + mov QWORD PTR [rcx+568], r8 + adc rax, QWORD PTR [r10+320] + mov r8, QWORD PTR [rcx+584] + mov QWORD PTR [rcx+576], rax + adc r8, QWORD PTR [r10+328] + mov rax, QWORD PTR [rcx+592] + mov QWORD PTR [rcx+584], r8 + adc rax, QWORD PTR [r10+336] + mov r8, QWORD PTR [rcx+600] + mov QWORD PTR [rcx+592], rax + adc r8, QWORD PTR [r10+344] + mov rax, QWORD PTR [rcx+608] + mov QWORD PTR [rcx+600], r8 + adc rax, QWORD PTR [r10+352] + mov r8, QWORD PTR [rcx+616] + mov QWORD PTR [rcx+608], rax + adc r8, QWORD PTR [r10+360] + mov rax, QWORD PTR [rcx+624] + mov QWORD PTR [rcx+616], r8 + adc rax, QWORD PTR [r10+368] + mov r8, QWORD PTR [rcx+632] + mov QWORD PTR [rcx+624], rax + adc r8, QWORD PTR [r10+376] + mov rax, QWORD PTR [rcx+640] + mov QWORD PTR [rcx+632], r8 + adc rax, QWORD PTR [r10+384] + mov r8, QWORD PTR [rcx+648] + mov QWORD PTR [rcx+640], rax + adc r8, QWORD PTR [r10+392] + mov rax, QWORD PTR [rcx+656] + mov QWORD PTR [rcx+648], r8 + adc rax, QWORD PTR [r10+400] + mov r8, QWORD PTR [rcx+664] + mov QWORD PTR [rcx+656], rax + adc r8, QWORD PTR [r10+408] + mov rax, QWORD PTR [rcx+672] + mov QWORD PTR [rcx+664], r8 + adc rax, QWORD PTR [r10+416] + mov r8, QWORD PTR [rcx+680] + mov QWORD PTR [rcx+672], rax + adc r8, QWORD PTR [r10+424] + mov rax, QWORD PTR [rcx+688] + mov QWORD PTR [rcx+680], r8 + adc rax, QWORD PTR [r10+432] + mov r8, QWORD PTR [rcx+696] + mov QWORD PTR [rcx+688], rax + adc r8, QWORD PTR [r10+440] + mov rax, QWORD PTR [rcx+704] + mov QWORD PTR [rcx+696], r8 + adc rax, QWORD PTR [r10+448] + mov r8, QWORD PTR [rcx+712] + mov QWORD PTR [rcx+704], rax + adc r8, QWORD PTR [r10+456] + mov rax, QWORD PTR [rcx+720] + mov QWORD PTR [rcx+712], r8 + adc rax, QWORD PTR [r10+464] + mov r8, QWORD PTR [rcx+728] + mov QWORD PTR [rcx+720], rax + adc r8, QWORD PTR [r10+472] + mov rax, QWORD PTR [rcx+736] + mov QWORD PTR [rcx+728], r8 + adc rax, QWORD PTR [r10+480] + mov r8, QWORD PTR [rcx+744] + mov QWORD PTR [rcx+736], rax + adc r8, QWORD PTR [r10+488] + mov rax, QWORD PTR [rcx+752] + mov QWORD PTR [rcx+744], r8 + adc rax, QWORD PTR [r10+496] + mov r8, QWORD PTR [rcx+760] + mov QWORD PTR [rcx+752], rax + adc r8, QWORD PTR [r10+504] + mov QWORD PTR [rcx+760], r8 + adc r9, 0 + mov QWORD PTR [rcx+768], r9 + ; Add in place + mov rax, QWORD PTR [rcx+512] + xor r9, r9 + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rcx+520] + mov QWORD PTR [rcx+512], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [rcx+528] + mov QWORD PTR [rcx+520], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rcx+536] + mov QWORD PTR [rcx+528], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rcx+544] + mov QWORD PTR [rcx+536], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rcx+552] + mov QWORD PTR [rcx+544], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [rcx+560] + mov QWORD PTR [rcx+552], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rcx+568] + mov QWORD PTR [rcx+560], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rcx+576] + mov QWORD PTR [rcx+568], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rcx+584] + mov QWORD PTR [rcx+576], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [rcx+592] + mov QWORD PTR [rcx+584], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rcx+600] + mov QWORD PTR [rcx+592], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rcx+608] + mov QWORD PTR [rcx+600], r8 + adc rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rcx+616] + mov QWORD PTR [rcx+608], rax + adc r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [rcx+624] + mov QWORD PTR [rcx+616], r8 + adc rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rcx+632] + mov QWORD PTR [rcx+624], rax + adc r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rcx+640] + mov QWORD PTR [rcx+632], r8 + adc rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rcx+648] + mov QWORD PTR [rcx+640], rax + adc r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [rcx+656] + mov QWORD PTR [rcx+648], r8 + adc rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rcx+664] + mov QWORD PTR [rcx+656], rax + adc r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [rcx+672] + mov QWORD PTR [rcx+664], r8 + adc rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rcx+680] + mov QWORD PTR [rcx+672], rax + adc r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [rcx+688] + mov QWORD PTR [rcx+680], r8 + adc rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rcx+696] + mov QWORD PTR [rcx+688], rax + adc r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [rcx+704] + mov QWORD PTR [rcx+696], r8 + adc rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rcx+712] + mov QWORD PTR [rcx+704], rax + adc r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [rcx+720] + mov QWORD PTR [rcx+712], r8 + adc rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [rcx+728] + mov QWORD PTR [rcx+720], rax + adc r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [rcx+736] + mov QWORD PTR [rcx+728], r8 + adc rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rcx+744] + mov QWORD PTR [rcx+736], rax + adc r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [rcx+752] + mov QWORD PTR [rcx+744], r8 + adc rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [rcx+760] + mov QWORD PTR [rcx+752], rax + adc r8, QWORD PTR [rdx+248] + mov rax, QWORD PTR [rcx+768] + mov QWORD PTR [rcx+760], r8 + adc rax, QWORD PTR [rdx+256] + mov QWORD PTR [rcx+768], rax + adc r9, 0 + ; Add to zero + mov rax, QWORD PTR [rdx+264] + adc rax, 0 + mov r8, QWORD PTR [rdx+272] + mov QWORD PTR [rcx+776], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+280] + mov QWORD PTR [rcx+784], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+288] + mov QWORD PTR [rcx+792], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+296] + mov QWORD PTR [rcx+800], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+304] + mov QWORD PTR [rcx+808], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+312] + mov QWORD PTR [rcx+816], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+320] + mov QWORD PTR [rcx+824], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+328] + mov QWORD PTR [rcx+832], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+336] + mov QWORD PTR [rcx+840], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+344] + mov QWORD PTR [rcx+848], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+352] + mov QWORD PTR [rcx+856], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+360] + mov QWORD PTR [rcx+864], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+368] + mov QWORD PTR [rcx+872], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+880], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+384] + mov QWORD PTR [rcx+888], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+392] + mov QWORD PTR [rcx+896], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+400] + mov QWORD PTR [rcx+904], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+408] + mov QWORD PTR [rcx+912], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+416] + mov QWORD PTR [rcx+920], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+424] + mov QWORD PTR [rcx+928], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+432] + mov QWORD PTR [rcx+936], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+440] + mov QWORD PTR [rcx+944], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+448] + mov QWORD PTR [rcx+952], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+456] + mov QWORD PTR [rcx+960], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+464] + mov QWORD PTR [rcx+968], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+472] + mov QWORD PTR [rcx+976], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+480] + mov QWORD PTR [rcx+984], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+488] + mov QWORD PTR [rcx+992], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+496] + mov QWORD PTR [rcx+1000], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+504] + mov QWORD PTR [rcx+1008], r8 + adc rax, 0 + mov QWORD PTR [rcx+1016], rax + add rsp, 1304 + pop r12 + ret +sp_4096_sqr_64 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_mul_avx2_64 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 1576 + mov QWORD PTR [rsp+1536], rcx + mov QWORD PTR [rsp+1544], rdx + mov QWORD PTR [rsp+1552], r8 + lea r12, QWORD PTR [rsp+1024] + lea r14, QWORD PTR [rdx+256] + ; Add + mov rax, QWORD PTR [rdx] + xor r15, r15 + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [r12], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [rdx+16] + mov QWORD PTR [r12+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [rdx+24] + mov QWORD PTR [r12+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [r12+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [r12+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r12+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [rdx+56] + mov QWORD PTR [r12+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [rdx+64] + mov QWORD PTR [r12+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [rdx+72] + mov QWORD PTR [r12+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [r12+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [r12+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r12+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [rdx+104] + mov QWORD PTR [r12+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [rdx+112] + mov QWORD PTR [r12+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [rdx+120] + mov QWORD PTR [r12+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [r12+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [r12+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r12+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [rdx+152] + mov QWORD PTR [r12+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [rdx+160] + mov QWORD PTR [r12+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [rdx+168] + mov QWORD PTR [r12+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [r12+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [r12+176], r9 + adc r10, QWORD PTR [r14+184] + mov rax, QWORD PTR [rdx+192] + mov QWORD PTR [r12+184], r10 + adc rax, QWORD PTR [r14+192] + mov r9, QWORD PTR [rdx+200] + mov QWORD PTR [r12+192], rax + adc r9, QWORD PTR [r14+200] + mov r10, QWORD PTR [rdx+208] + mov QWORD PTR [r12+200], r9 + adc r10, QWORD PTR [r14+208] + mov rax, QWORD PTR [rdx+216] + mov QWORD PTR [r12+208], r10 + adc rax, QWORD PTR [r14+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [r12+216], rax + adc r9, QWORD PTR [r14+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [r12+224], r9 + adc r10, QWORD PTR [r14+232] + mov rax, QWORD PTR [rdx+240] + mov QWORD PTR [r12+232], r10 + adc rax, QWORD PTR [r14+240] + mov r9, QWORD PTR [rdx+248] + mov QWORD PTR [r12+240], rax + adc r9, QWORD PTR [r14+248] + mov QWORD PTR [r12+248], r9 + adc r15, 0 + mov QWORD PTR [rsp+1560], r15 + lea r13, QWORD PTR [rsp+1280] + lea r14, QWORD PTR [r8+256] + ; Add + mov rax, QWORD PTR [r8] + xor rdi, rdi + add rax, QWORD PTR [r14] + mov r9, QWORD PTR [r8+8] + mov QWORD PTR [r13], rax + adc r9, QWORD PTR [r14+8] + mov r10, QWORD PTR [r8+16] + mov QWORD PTR [r13+8], r9 + adc r10, QWORD PTR [r14+16] + mov rax, QWORD PTR [r8+24] + mov QWORD PTR [r13+16], r10 + adc rax, QWORD PTR [r14+24] + mov r9, QWORD PTR [r8+32] + mov QWORD PTR [r13+24], rax + adc r9, QWORD PTR [r14+32] + mov r10, QWORD PTR [r8+40] + mov QWORD PTR [r13+32], r9 + adc r10, QWORD PTR [r14+40] + mov rax, QWORD PTR [r8+48] + mov QWORD PTR [r13+40], r10 + adc rax, QWORD PTR [r14+48] + mov r9, QWORD PTR [r8+56] + mov QWORD PTR [r13+48], rax + adc r9, QWORD PTR [r14+56] + mov r10, QWORD PTR [r8+64] + mov QWORD PTR [r13+56], r9 + adc r10, QWORD PTR [r14+64] + mov rax, QWORD PTR [r8+72] + mov QWORD PTR [r13+64], r10 + adc rax, QWORD PTR [r14+72] + mov r9, QWORD PTR [r8+80] + mov QWORD PTR [r13+72], rax + adc r9, QWORD PTR [r14+80] + mov r10, QWORD PTR [r8+88] + mov QWORD PTR [r13+80], r9 + adc r10, QWORD PTR [r14+88] + mov rax, QWORD PTR [r8+96] + mov QWORD PTR [r13+88], r10 + adc rax, QWORD PTR [r14+96] + mov r9, QWORD PTR [r8+104] + mov QWORD PTR [r13+96], rax + adc r9, QWORD PTR [r14+104] + mov r10, QWORD PTR [r8+112] + mov QWORD PTR [r13+104], r9 + adc r10, QWORD PTR [r14+112] + mov rax, QWORD PTR [r8+120] + mov QWORD PTR [r13+112], r10 + adc rax, QWORD PTR [r14+120] + mov r9, QWORD PTR [r8+128] + mov QWORD PTR [r13+120], rax + adc r9, QWORD PTR [r14+128] + mov r10, QWORD PTR [r8+136] + mov QWORD PTR [r13+128], r9 + adc r10, QWORD PTR [r14+136] + mov rax, QWORD PTR [r8+144] + mov QWORD PTR [r13+136], r10 + adc rax, QWORD PTR [r14+144] + mov r9, QWORD PTR [r8+152] + mov QWORD PTR [r13+144], rax + adc r9, QWORD PTR [r14+152] + mov r10, QWORD PTR [r8+160] + mov QWORD PTR [r13+152], r9 + adc r10, QWORD PTR [r14+160] + mov rax, QWORD PTR [r8+168] + mov QWORD PTR [r13+160], r10 + adc rax, QWORD PTR [r14+168] + mov r9, QWORD PTR [r8+176] + mov QWORD PTR [r13+168], rax + adc r9, QWORD PTR [r14+176] + mov r10, QWORD PTR [r8+184] + mov QWORD PTR [r13+176], r9 + adc r10, QWORD PTR [r14+184] + mov rax, QWORD PTR [r8+192] + mov QWORD PTR [r13+184], r10 + adc rax, QWORD PTR [r14+192] + mov r9, QWORD PTR [r8+200] + mov QWORD PTR [r13+192], rax + adc r9, QWORD PTR [r14+200] + mov r10, QWORD PTR [r8+208] + mov QWORD PTR [r13+200], r9 + adc r10, QWORD PTR [r14+208] + mov rax, QWORD PTR [r8+216] + mov QWORD PTR [r13+208], r10 + adc rax, QWORD PTR [r14+216] + mov r9, QWORD PTR [r8+224] + mov QWORD PTR [r13+216], rax + adc r9, QWORD PTR [r14+224] + mov r10, QWORD PTR [r8+232] + mov QWORD PTR [r13+224], r9 + adc r10, QWORD PTR [r14+232] + mov rax, QWORD PTR [r8+240] + mov QWORD PTR [r13+232], r10 + adc rax, QWORD PTR [r14+240] + mov r9, QWORD PTR [r8+248] + mov QWORD PTR [r13+240], rax + adc r9, QWORD PTR [r14+248] + mov QWORD PTR [r13+248], r9 + adc rdi, 0 + mov QWORD PTR [rsp+1568], rdi + mov r8, r13 + mov rdx, r12 + mov rcx, rsp + call sp_2048_mul_avx2_32 + mov r8, QWORD PTR [rsp+1552] + mov rdx, QWORD PTR [rsp+1544] + lea rcx, QWORD PTR [rsp+512] + add r8, 256 + add rdx, 256 + call sp_2048_mul_avx2_32 + mov r8, QWORD PTR [rsp+1552] + mov rdx, QWORD PTR [rsp+1544] + mov rcx, QWORD PTR [rsp+1536] + call sp_2048_mul_avx2_32 +IFDEF _WIN64 + mov r8, QWORD PTR [rsp+1552] + mov rdx, QWORD PTR [rsp+1544] + mov rcx, QWORD PTR [rsp+1536] +ENDIF + mov r15, QWORD PTR [rsp+1560] + mov rdi, QWORD PTR [rsp+1568] + mov rsi, QWORD PTR [rsp+1536] + mov r11, r15 + lea r12, QWORD PTR [rsp+1024] + lea r13, QWORD PTR [rsp+1280] + and r11, rdi + neg r15 + neg rdi + add rsi, 512 + mov rax, QWORD PTR [r12] + mov r9, QWORD PTR [r13] + pext rax, rax, rdi + pext r9, r9, r15 + add rax, r9 + mov r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [r13+8] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi], rax + adc r9, r10 + mov r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [r13+16] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+8], r9 + adc r10, rax + mov rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [r13+24] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+16], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [r13+32] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+24], rax + adc r9, r10 + mov r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [r13+40] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+32], r9 + adc r10, rax + mov rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [r13+48] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+40], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [r13+56] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+48], rax + adc r9, r10 + mov r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [r13+64] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+56], r9 + adc r10, rax + mov rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [r13+72] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+64], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [r13+80] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+72], rax + adc r9, r10 + mov r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [r13+88] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+80], r9 + adc r10, rax + mov rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [r13+96] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+88], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [r13+104] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+96], rax + adc r9, r10 + mov r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [r13+112] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+104], r9 + adc r10, rax + mov rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [r13+120] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+112], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [r13+128] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+120], rax + adc r9, r10 + mov r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [r13+136] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+128], r9 + adc r10, rax + mov rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [r13+144] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+136], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [r13+152] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+144], rax + adc r9, r10 + mov r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [r13+160] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+152], r9 + adc r10, rax + mov rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [r13+168] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+160], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [r13+176] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+168], rax + adc r9, r10 + mov r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [r13+184] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+176], r9 + adc r10, rax + mov rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [r13+192] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+184], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [r13+200] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+192], rax + adc r9, r10 + mov r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [r13+208] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+200], r9 + adc r10, rax + mov rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [r13+216] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+208], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [r13+224] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+216], rax + adc r9, r10 + mov r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [r13+232] + pext r10, r10, rdi + pext rax, rax, r15 + mov QWORD PTR [rsi+224], r9 + adc r10, rax + mov rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [r13+240] + pext rax, rax, rdi + pext r9, r9, r15 + mov QWORD PTR [rsi+232], r10 + adc rax, r9 + mov r9, QWORD PTR [r12+248] + mov r10, QWORD PTR [r13+248] + pext r9, r9, rdi + pext r10, r10, r15 + mov QWORD PTR [rsi+240], rax + adc r9, r10 + mov QWORD PTR [rsi+248], r9 + adc r11, 0 + lea r13, QWORD PTR [rsp+512] + mov r12, rsp + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [r13] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [r13+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [r13+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [r13+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [r13+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [r13+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [r13+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [r13+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [r13+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [r13+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [r13+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [r13+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [r13+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [r13+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [r13+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [r13+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [r13+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [r13+376] + mov rax, QWORD PTR [r12+384] + mov QWORD PTR [r12+376], r10 + sbb rax, QWORD PTR [r13+384] + mov r9, QWORD PTR [r12+392] + mov QWORD PTR [r12+384], rax + sbb r9, QWORD PTR [r13+392] + mov r10, QWORD PTR [r12+400] + mov QWORD PTR [r12+392], r9 + sbb r10, QWORD PTR [r13+400] + mov rax, QWORD PTR [r12+408] + mov QWORD PTR [r12+400], r10 + sbb rax, QWORD PTR [r13+408] + mov r9, QWORD PTR [r12+416] + mov QWORD PTR [r12+408], rax + sbb r9, QWORD PTR [r13+416] + mov r10, QWORD PTR [r12+424] + mov QWORD PTR [r12+416], r9 + sbb r10, QWORD PTR [r13+424] + mov rax, QWORD PTR [r12+432] + mov QWORD PTR [r12+424], r10 + sbb rax, QWORD PTR [r13+432] + mov r9, QWORD PTR [r12+440] + mov QWORD PTR [r12+432], rax + sbb r9, QWORD PTR [r13+440] + mov r10, QWORD PTR [r12+448] + mov QWORD PTR [r12+440], r9 + sbb r10, QWORD PTR [r13+448] + mov rax, QWORD PTR [r12+456] + mov QWORD PTR [r12+448], r10 + sbb rax, QWORD PTR [r13+456] + mov r9, QWORD PTR [r12+464] + mov QWORD PTR [r12+456], rax + sbb r9, QWORD PTR [r13+464] + mov r10, QWORD PTR [r12+472] + mov QWORD PTR [r12+464], r9 + sbb r10, QWORD PTR [r13+472] + mov rax, QWORD PTR [r12+480] + mov QWORD PTR [r12+472], r10 + sbb rax, QWORD PTR [r13+480] + mov r9, QWORD PTR [r12+488] + mov QWORD PTR [r12+480], rax + sbb r9, QWORD PTR [r13+488] + mov r10, QWORD PTR [r12+496] + mov QWORD PTR [r12+488], r9 + sbb r10, QWORD PTR [r13+496] + mov rax, QWORD PTR [r12+504] + mov QWORD PTR [r12+496], r10 + sbb rax, QWORD PTR [r13+504] + mov QWORD PTR [r12+504], rax + sbb r11, 0 + mov rax, QWORD PTR [r12] + sub rax, QWORD PTR [rcx] + mov r9, QWORD PTR [r12+8] + mov QWORD PTR [r12], rax + sbb r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [r12+16] + mov QWORD PTR [r12+8], r9 + sbb r10, QWORD PTR [rcx+16] + mov rax, QWORD PTR [r12+24] + mov QWORD PTR [r12+16], r10 + sbb rax, QWORD PTR [rcx+24] + mov r9, QWORD PTR [r12+32] + mov QWORD PTR [r12+24], rax + sbb r9, QWORD PTR [rcx+32] + mov r10, QWORD PTR [r12+40] + mov QWORD PTR [r12+32], r9 + sbb r10, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r12+48] + mov QWORD PTR [r12+40], r10 + sbb rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [r12+56] + mov QWORD PTR [r12+48], rax + sbb r9, QWORD PTR [rcx+56] + mov r10, QWORD PTR [r12+64] + mov QWORD PTR [r12+56], r9 + sbb r10, QWORD PTR [rcx+64] + mov rax, QWORD PTR [r12+72] + mov QWORD PTR [r12+64], r10 + sbb rax, QWORD PTR [rcx+72] + mov r9, QWORD PTR [r12+80] + mov QWORD PTR [r12+72], rax + sbb r9, QWORD PTR [rcx+80] + mov r10, QWORD PTR [r12+88] + mov QWORD PTR [r12+80], r9 + sbb r10, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r12+96] + mov QWORD PTR [r12+88], r10 + sbb rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [r12+104] + mov QWORD PTR [r12+96], rax + sbb r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [r12+112] + mov QWORD PTR [r12+104], r9 + sbb r10, QWORD PTR [rcx+112] + mov rax, QWORD PTR [r12+120] + mov QWORD PTR [r12+112], r10 + sbb rax, QWORD PTR [rcx+120] + mov r9, QWORD PTR [r12+128] + mov QWORD PTR [r12+120], rax + sbb r9, QWORD PTR [rcx+128] + mov r10, QWORD PTR [r12+136] + mov QWORD PTR [r12+128], r9 + sbb r10, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r12+144] + mov QWORD PTR [r12+136], r10 + sbb rax, QWORD PTR [rcx+144] + mov r9, QWORD PTR [r12+152] + mov QWORD PTR [r12+144], rax + sbb r9, QWORD PTR [rcx+152] + mov r10, QWORD PTR [r12+160] + mov QWORD PTR [r12+152], r9 + sbb r10, QWORD PTR [rcx+160] + mov rax, QWORD PTR [r12+168] + mov QWORD PTR [r12+160], r10 + sbb rax, QWORD PTR [rcx+168] + mov r9, QWORD PTR [r12+176] + mov QWORD PTR [r12+168], rax + sbb r9, QWORD PTR [rcx+176] + mov r10, QWORD PTR [r12+184] + mov QWORD PTR [r12+176], r9 + sbb r10, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r12+192] + mov QWORD PTR [r12+184], r10 + sbb rax, QWORD PTR [rcx+192] + mov r9, QWORD PTR [r12+200] + mov QWORD PTR [r12+192], rax + sbb r9, QWORD PTR [rcx+200] + mov r10, QWORD PTR [r12+208] + mov QWORD PTR [r12+200], r9 + sbb r10, QWORD PTR [rcx+208] + mov rax, QWORD PTR [r12+216] + mov QWORD PTR [r12+208], r10 + sbb rax, QWORD PTR [rcx+216] + mov r9, QWORD PTR [r12+224] + mov QWORD PTR [r12+216], rax + sbb r9, QWORD PTR [rcx+224] + mov r10, QWORD PTR [r12+232] + mov QWORD PTR [r12+224], r9 + sbb r10, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r12+240] + mov QWORD PTR [r12+232], r10 + sbb rax, QWORD PTR [rcx+240] + mov r9, QWORD PTR [r12+248] + mov QWORD PTR [r12+240], rax + sbb r9, QWORD PTR [rcx+248] + mov r10, QWORD PTR [r12+256] + mov QWORD PTR [r12+248], r9 + sbb r10, QWORD PTR [rcx+256] + mov rax, QWORD PTR [r12+264] + mov QWORD PTR [r12+256], r10 + sbb rax, QWORD PTR [rcx+264] + mov r9, QWORD PTR [r12+272] + mov QWORD PTR [r12+264], rax + sbb r9, QWORD PTR [rcx+272] + mov r10, QWORD PTR [r12+280] + mov QWORD PTR [r12+272], r9 + sbb r10, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r12+288] + mov QWORD PTR [r12+280], r10 + sbb rax, QWORD PTR [rcx+288] + mov r9, QWORD PTR [r12+296] + mov QWORD PTR [r12+288], rax + sbb r9, QWORD PTR [rcx+296] + mov r10, QWORD PTR [r12+304] + mov QWORD PTR [r12+296], r9 + sbb r10, QWORD PTR [rcx+304] + mov rax, QWORD PTR [r12+312] + mov QWORD PTR [r12+304], r10 + sbb rax, QWORD PTR [rcx+312] + mov r9, QWORD PTR [r12+320] + mov QWORD PTR [r12+312], rax + sbb r9, QWORD PTR [rcx+320] + mov r10, QWORD PTR [r12+328] + mov QWORD PTR [r12+320], r9 + sbb r10, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r12+336] + mov QWORD PTR [r12+328], r10 + sbb rax, QWORD PTR [rcx+336] + mov r9, QWORD PTR [r12+344] + mov QWORD PTR [r12+336], rax + sbb r9, QWORD PTR [rcx+344] + mov r10, QWORD PTR [r12+352] + mov QWORD PTR [r12+344], r9 + sbb r10, QWORD PTR [rcx+352] + mov rax, QWORD PTR [r12+360] + mov QWORD PTR [r12+352], r10 + sbb rax, QWORD PTR [rcx+360] + mov r9, QWORD PTR [r12+368] + mov QWORD PTR [r12+360], rax + sbb r9, QWORD PTR [rcx+368] + mov r10, QWORD PTR [r12+376] + mov QWORD PTR [r12+368], r9 + sbb r10, QWORD PTR [rcx+376] + mov rax, QWORD PTR [r12+384] + mov QWORD PTR [r12+376], r10 + sbb rax, QWORD PTR [rcx+384] + mov r9, QWORD PTR [r12+392] + mov QWORD PTR [r12+384], rax + sbb r9, QWORD PTR [rcx+392] + mov r10, QWORD PTR [r12+400] + mov QWORD PTR [r12+392], r9 + sbb r10, QWORD PTR [rcx+400] + mov rax, QWORD PTR [r12+408] + mov QWORD PTR [r12+400], r10 + sbb rax, QWORD PTR [rcx+408] + mov r9, QWORD PTR [r12+416] + mov QWORD PTR [r12+408], rax + sbb r9, QWORD PTR [rcx+416] + mov r10, QWORD PTR [r12+424] + mov QWORD PTR [r12+416], r9 + sbb r10, QWORD PTR [rcx+424] + mov rax, QWORD PTR [r12+432] + mov QWORD PTR [r12+424], r10 + sbb rax, QWORD PTR [rcx+432] + mov r9, QWORD PTR [r12+440] + mov QWORD PTR [r12+432], rax + sbb r9, QWORD PTR [rcx+440] + mov r10, QWORD PTR [r12+448] + mov QWORD PTR [r12+440], r9 + sbb r10, QWORD PTR [rcx+448] + mov rax, QWORD PTR [r12+456] + mov QWORD PTR [r12+448], r10 + sbb rax, QWORD PTR [rcx+456] + mov r9, QWORD PTR [r12+464] + mov QWORD PTR [r12+456], rax + sbb r9, QWORD PTR [rcx+464] + mov r10, QWORD PTR [r12+472] + mov QWORD PTR [r12+464], r9 + sbb r10, QWORD PTR [rcx+472] + mov rax, QWORD PTR [r12+480] + mov QWORD PTR [r12+472], r10 + sbb rax, QWORD PTR [rcx+480] + mov r9, QWORD PTR [r12+488] + mov QWORD PTR [r12+480], rax + sbb r9, QWORD PTR [rcx+488] + mov r10, QWORD PTR [r12+496] + mov QWORD PTR [r12+488], r9 + sbb r10, QWORD PTR [rcx+496] + mov rax, QWORD PTR [r12+504] + mov QWORD PTR [r12+496], r10 + sbb rax, QWORD PTR [rcx+504] + mov QWORD PTR [r12+504], rax + sbb r11, 0 + sub rsi, 256 + ; Add + mov rax, QWORD PTR [rsi] + add rax, QWORD PTR [r12] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r12+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r12+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r12+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r12+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r12+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r12+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r12+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r12+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r12+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r12+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r12+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r12+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r12+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r12+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r12+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r12+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r12+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r12+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r12+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r12+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r12+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r12+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r12+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r12+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r12+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r12+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r12+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r12+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r12+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r12+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r12+248] + mov r10, QWORD PTR [rsi+256] + mov QWORD PTR [rsi+248], r9 + adc r10, QWORD PTR [r12+256] + mov rax, QWORD PTR [rsi+264] + mov QWORD PTR [rsi+256], r10 + adc rax, QWORD PTR [r12+264] + mov r9, QWORD PTR [rsi+272] + mov QWORD PTR [rsi+264], rax + adc r9, QWORD PTR [r12+272] + mov r10, QWORD PTR [rsi+280] + mov QWORD PTR [rsi+272], r9 + adc r10, QWORD PTR [r12+280] + mov rax, QWORD PTR [rsi+288] + mov QWORD PTR [rsi+280], r10 + adc rax, QWORD PTR [r12+288] + mov r9, QWORD PTR [rsi+296] + mov QWORD PTR [rsi+288], rax + adc r9, QWORD PTR [r12+296] + mov r10, QWORD PTR [rsi+304] + mov QWORD PTR [rsi+296], r9 + adc r10, QWORD PTR [r12+304] + mov rax, QWORD PTR [rsi+312] + mov QWORD PTR [rsi+304], r10 + adc rax, QWORD PTR [r12+312] + mov r9, QWORD PTR [rsi+320] + mov QWORD PTR [rsi+312], rax + adc r9, QWORD PTR [r12+320] + mov r10, QWORD PTR [rsi+328] + mov QWORD PTR [rsi+320], r9 + adc r10, QWORD PTR [r12+328] + mov rax, QWORD PTR [rsi+336] + mov QWORD PTR [rsi+328], r10 + adc rax, QWORD PTR [r12+336] + mov r9, QWORD PTR [rsi+344] + mov QWORD PTR [rsi+336], rax + adc r9, QWORD PTR [r12+344] + mov r10, QWORD PTR [rsi+352] + mov QWORD PTR [rsi+344], r9 + adc r10, QWORD PTR [r12+352] + mov rax, QWORD PTR [rsi+360] + mov QWORD PTR [rsi+352], r10 + adc rax, QWORD PTR [r12+360] + mov r9, QWORD PTR [rsi+368] + mov QWORD PTR [rsi+360], rax + adc r9, QWORD PTR [r12+368] + mov r10, QWORD PTR [rsi+376] + mov QWORD PTR [rsi+368], r9 + adc r10, QWORD PTR [r12+376] + mov rax, QWORD PTR [rsi+384] + mov QWORD PTR [rsi+376], r10 + adc rax, QWORD PTR [r12+384] + mov r9, QWORD PTR [rsi+392] + mov QWORD PTR [rsi+384], rax + adc r9, QWORD PTR [r12+392] + mov r10, QWORD PTR [rsi+400] + mov QWORD PTR [rsi+392], r9 + adc r10, QWORD PTR [r12+400] + mov rax, QWORD PTR [rsi+408] + mov QWORD PTR [rsi+400], r10 + adc rax, QWORD PTR [r12+408] + mov r9, QWORD PTR [rsi+416] + mov QWORD PTR [rsi+408], rax + adc r9, QWORD PTR [r12+416] + mov r10, QWORD PTR [rsi+424] + mov QWORD PTR [rsi+416], r9 + adc r10, QWORD PTR [r12+424] + mov rax, QWORD PTR [rsi+432] + mov QWORD PTR [rsi+424], r10 + adc rax, QWORD PTR [r12+432] + mov r9, QWORD PTR [rsi+440] + mov QWORD PTR [rsi+432], rax + adc r9, QWORD PTR [r12+440] + mov r10, QWORD PTR [rsi+448] + mov QWORD PTR [rsi+440], r9 + adc r10, QWORD PTR [r12+448] + mov rax, QWORD PTR [rsi+456] + mov QWORD PTR [rsi+448], r10 + adc rax, QWORD PTR [r12+456] + mov r9, QWORD PTR [rsi+464] + mov QWORD PTR [rsi+456], rax + adc r9, QWORD PTR [r12+464] + mov r10, QWORD PTR [rsi+472] + mov QWORD PTR [rsi+464], r9 + adc r10, QWORD PTR [r12+472] + mov rax, QWORD PTR [rsi+480] + mov QWORD PTR [rsi+472], r10 + adc rax, QWORD PTR [r12+480] + mov r9, QWORD PTR [rsi+488] + mov QWORD PTR [rsi+480], rax + adc r9, QWORD PTR [r12+488] + mov r10, QWORD PTR [rsi+496] + mov QWORD PTR [rsi+488], r9 + adc r10, QWORD PTR [r12+496] + mov rax, QWORD PTR [rsi+504] + mov QWORD PTR [rsi+496], r10 + adc rax, QWORD PTR [r12+504] + mov QWORD PTR [rsi+504], rax + adc r11, 0 + mov QWORD PTR [rcx+768], r11 + add rsi, 256 + ; Add + mov rax, QWORD PTR [rsi] + xor r11, r11 + add rax, QWORD PTR [r13] + mov r9, QWORD PTR [rsi+8] + mov QWORD PTR [rsi], rax + adc r9, QWORD PTR [r13+8] + mov r10, QWORD PTR [rsi+16] + mov QWORD PTR [rsi+8], r9 + adc r10, QWORD PTR [r13+16] + mov rax, QWORD PTR [rsi+24] + mov QWORD PTR [rsi+16], r10 + adc rax, QWORD PTR [r13+24] + mov r9, QWORD PTR [rsi+32] + mov QWORD PTR [rsi+24], rax + adc r9, QWORD PTR [r13+32] + mov r10, QWORD PTR [rsi+40] + mov QWORD PTR [rsi+32], r9 + adc r10, QWORD PTR [r13+40] + mov rax, QWORD PTR [rsi+48] + mov QWORD PTR [rsi+40], r10 + adc rax, QWORD PTR [r13+48] + mov r9, QWORD PTR [rsi+56] + mov QWORD PTR [rsi+48], rax + adc r9, QWORD PTR [r13+56] + mov r10, QWORD PTR [rsi+64] + mov QWORD PTR [rsi+56], r9 + adc r10, QWORD PTR [r13+64] + mov rax, QWORD PTR [rsi+72] + mov QWORD PTR [rsi+64], r10 + adc rax, QWORD PTR [r13+72] + mov r9, QWORD PTR [rsi+80] + mov QWORD PTR [rsi+72], rax + adc r9, QWORD PTR [r13+80] + mov r10, QWORD PTR [rsi+88] + mov QWORD PTR [rsi+80], r9 + adc r10, QWORD PTR [r13+88] + mov rax, QWORD PTR [rsi+96] + mov QWORD PTR [rsi+88], r10 + adc rax, QWORD PTR [r13+96] + mov r9, QWORD PTR [rsi+104] + mov QWORD PTR [rsi+96], rax + adc r9, QWORD PTR [r13+104] + mov r10, QWORD PTR [rsi+112] + mov QWORD PTR [rsi+104], r9 + adc r10, QWORD PTR [r13+112] + mov rax, QWORD PTR [rsi+120] + mov QWORD PTR [rsi+112], r10 + adc rax, QWORD PTR [r13+120] + mov r9, QWORD PTR [rsi+128] + mov QWORD PTR [rsi+120], rax + adc r9, QWORD PTR [r13+128] + mov r10, QWORD PTR [rsi+136] + mov QWORD PTR [rsi+128], r9 + adc r10, QWORD PTR [r13+136] + mov rax, QWORD PTR [rsi+144] + mov QWORD PTR [rsi+136], r10 + adc rax, QWORD PTR [r13+144] + mov r9, QWORD PTR [rsi+152] + mov QWORD PTR [rsi+144], rax + adc r9, QWORD PTR [r13+152] + mov r10, QWORD PTR [rsi+160] + mov QWORD PTR [rsi+152], r9 + adc r10, QWORD PTR [r13+160] + mov rax, QWORD PTR [rsi+168] + mov QWORD PTR [rsi+160], r10 + adc rax, QWORD PTR [r13+168] + mov r9, QWORD PTR [rsi+176] + mov QWORD PTR [rsi+168], rax + adc r9, QWORD PTR [r13+176] + mov r10, QWORD PTR [rsi+184] + mov QWORD PTR [rsi+176], r9 + adc r10, QWORD PTR [r13+184] + mov rax, QWORD PTR [rsi+192] + mov QWORD PTR [rsi+184], r10 + adc rax, QWORD PTR [r13+192] + mov r9, QWORD PTR [rsi+200] + mov QWORD PTR [rsi+192], rax + adc r9, QWORD PTR [r13+200] + mov r10, QWORD PTR [rsi+208] + mov QWORD PTR [rsi+200], r9 + adc r10, QWORD PTR [r13+208] + mov rax, QWORD PTR [rsi+216] + mov QWORD PTR [rsi+208], r10 + adc rax, QWORD PTR [r13+216] + mov r9, QWORD PTR [rsi+224] + mov QWORD PTR [rsi+216], rax + adc r9, QWORD PTR [r13+224] + mov r10, QWORD PTR [rsi+232] + mov QWORD PTR [rsi+224], r9 + adc r10, QWORD PTR [r13+232] + mov rax, QWORD PTR [rsi+240] + mov QWORD PTR [rsi+232], r10 + adc rax, QWORD PTR [r13+240] + mov r9, QWORD PTR [rsi+248] + mov QWORD PTR [rsi+240], rax + adc r9, QWORD PTR [r13+248] + mov r10, QWORD PTR [rsi+256] + mov QWORD PTR [rsi+248], r9 + adc r10, QWORD PTR [r13+256] + mov QWORD PTR [rsi+256], r10 + adc r11, 0 + ; Add to zero + mov rax, QWORD PTR [r13+264] + adc rax, 0 + mov r9, QWORD PTR [r13+272] + mov QWORD PTR [rsi+264], rax + adc r9, 0 + mov r10, QWORD PTR [r13+280] + mov QWORD PTR [rsi+272], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+288] + mov QWORD PTR [rsi+280], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+296] + mov QWORD PTR [rsi+288], rax + adc r9, 0 + mov r10, QWORD PTR [r13+304] + mov QWORD PTR [rsi+296], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+312] + mov QWORD PTR [rsi+304], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+320] + mov QWORD PTR [rsi+312], rax + adc r9, 0 + mov r10, QWORD PTR [r13+328] + mov QWORD PTR [rsi+320], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+336] + mov QWORD PTR [rsi+328], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+344] + mov QWORD PTR [rsi+336], rax + adc r9, 0 + mov r10, QWORD PTR [r13+352] + mov QWORD PTR [rsi+344], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+360] + mov QWORD PTR [rsi+352], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+368] + mov QWORD PTR [rsi+360], rax + adc r9, 0 + mov r10, QWORD PTR [r13+376] + mov QWORD PTR [rsi+368], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+384] + mov QWORD PTR [rsi+376], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+392] + mov QWORD PTR [rsi+384], rax + adc r9, 0 + mov r10, QWORD PTR [r13+400] + mov QWORD PTR [rsi+392], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+408] + mov QWORD PTR [rsi+400], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+416] + mov QWORD PTR [rsi+408], rax + adc r9, 0 + mov r10, QWORD PTR [r13+424] + mov QWORD PTR [rsi+416], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+432] + mov QWORD PTR [rsi+424], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+440] + mov QWORD PTR [rsi+432], rax + adc r9, 0 + mov r10, QWORD PTR [r13+448] + mov QWORD PTR [rsi+440], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+456] + mov QWORD PTR [rsi+448], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+464] + mov QWORD PTR [rsi+456], rax + adc r9, 0 + mov r10, QWORD PTR [r13+472] + mov QWORD PTR [rsi+464], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+480] + mov QWORD PTR [rsi+472], r10 + adc rax, 0 + mov r9, QWORD PTR [r13+488] + mov QWORD PTR [rsi+480], rax + adc r9, 0 + mov r10, QWORD PTR [r13+496] + mov QWORD PTR [rsi+488], r9 + adc r10, 0 + mov rax, QWORD PTR [r13+504] + mov QWORD PTR [rsi+496], r10 + adc rax, 0 + mov QWORD PTR [rsi+504], rax + add rsp, 1576 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_4096_mul_avx2_64 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_sqr_avx2_64 PROC + push r12 + sub rsp, 1304 + mov QWORD PTR [rsp+1280], rcx + mov QWORD PTR [rsp+1288], rdx + lea r10, QWORD PTR [rsp+1024] + lea r11, QWORD PTR [rdx+256] + ; Add + mov rax, QWORD PTR [rdx] + xor r9, r9 + add rax, QWORD PTR [r11] + mov r8, QWORD PTR [rdx+8] + mov QWORD PTR [r10], rax + adc r8, QWORD PTR [r11+8] + mov rax, QWORD PTR [rdx+16] + mov QWORD PTR [r10+8], r8 + adc rax, QWORD PTR [r11+16] + mov r8, QWORD PTR [rdx+24] + mov QWORD PTR [r10+16], rax + adc r8, QWORD PTR [r11+24] + mov rax, QWORD PTR [rdx+32] + mov QWORD PTR [r10+24], r8 + adc rax, QWORD PTR [r11+32] + mov r8, QWORD PTR [rdx+40] + mov QWORD PTR [r10+32], rax + adc r8, QWORD PTR [r11+40] + mov rax, QWORD PTR [rdx+48] + mov QWORD PTR [r10+40], r8 + adc rax, QWORD PTR [r11+48] + mov r8, QWORD PTR [rdx+56] + mov QWORD PTR [r10+48], rax + adc r8, QWORD PTR [r11+56] + mov rax, QWORD PTR [rdx+64] + mov QWORD PTR [r10+56], r8 + adc rax, QWORD PTR [r11+64] + mov r8, QWORD PTR [rdx+72] + mov QWORD PTR [r10+64], rax + adc r8, QWORD PTR [r11+72] + mov rax, QWORD PTR [rdx+80] + mov QWORD PTR [r10+72], r8 + adc rax, QWORD PTR [r11+80] + mov r8, QWORD PTR [rdx+88] + mov QWORD PTR [r10+80], rax + adc r8, QWORD PTR [r11+88] + mov rax, QWORD PTR [rdx+96] + mov QWORD PTR [r10+88], r8 + adc rax, QWORD PTR [r11+96] + mov r8, QWORD PTR [rdx+104] + mov QWORD PTR [r10+96], rax + adc r8, QWORD PTR [r11+104] + mov rax, QWORD PTR [rdx+112] + mov QWORD PTR [r10+104], r8 + adc rax, QWORD PTR [r11+112] + mov r8, QWORD PTR [rdx+120] + mov QWORD PTR [r10+112], rax + adc r8, QWORD PTR [r11+120] + mov rax, QWORD PTR [rdx+128] + mov QWORD PTR [r10+120], r8 + adc rax, QWORD PTR [r11+128] + mov r8, QWORD PTR [rdx+136] + mov QWORD PTR [r10+128], rax + adc r8, QWORD PTR [r11+136] + mov rax, QWORD PTR [rdx+144] + mov QWORD PTR [r10+136], r8 + adc rax, QWORD PTR [r11+144] + mov r8, QWORD PTR [rdx+152] + mov QWORD PTR [r10+144], rax + adc r8, QWORD PTR [r11+152] + mov rax, QWORD PTR [rdx+160] + mov QWORD PTR [r10+152], r8 + adc rax, QWORD PTR [r11+160] + mov r8, QWORD PTR [rdx+168] + mov QWORD PTR [r10+160], rax + adc r8, QWORD PTR [r11+168] + mov rax, QWORD PTR [rdx+176] + mov QWORD PTR [r10+168], r8 + adc rax, QWORD PTR [r11+176] + mov r8, QWORD PTR [rdx+184] + mov QWORD PTR [r10+176], rax + adc r8, QWORD PTR [r11+184] + mov rax, QWORD PTR [rdx+192] + mov QWORD PTR [r10+184], r8 + adc rax, QWORD PTR [r11+192] + mov r8, QWORD PTR [rdx+200] + mov QWORD PTR [r10+192], rax + adc r8, QWORD PTR [r11+200] + mov rax, QWORD PTR [rdx+208] + mov QWORD PTR [r10+200], r8 + adc rax, QWORD PTR [r11+208] + mov r8, QWORD PTR [rdx+216] + mov QWORD PTR [r10+208], rax + adc r8, QWORD PTR [r11+216] + mov rax, QWORD PTR [rdx+224] + mov QWORD PTR [r10+216], r8 + adc rax, QWORD PTR [r11+224] + mov r8, QWORD PTR [rdx+232] + mov QWORD PTR [r10+224], rax + adc r8, QWORD PTR [r11+232] + mov rax, QWORD PTR [rdx+240] + mov QWORD PTR [r10+232], r8 + adc rax, QWORD PTR [r11+240] + mov r8, QWORD PTR [rdx+248] + mov QWORD PTR [r10+240], rax + adc r8, QWORD PTR [r11+248] + mov QWORD PTR [r10+248], r8 + adc r9, 0 + mov QWORD PTR [rsp+1296], r9 + mov rdx, r10 + mov rcx, rsp + call sp_2048_sqr_avx2_32 + mov rdx, QWORD PTR [rsp+1288] + lea rcx, QWORD PTR [rsp+512] + add rdx, 256 + call sp_2048_sqr_avx2_32 + mov rdx, QWORD PTR [rsp+1288] + mov rcx, QWORD PTR [rsp+1280] + call sp_2048_sqr_avx2_32 +IFDEF _WIN64 + mov rdx, QWORD PTR [rsp+1288] + mov rcx, QWORD PTR [rsp+1280] +ENDIF + mov r12, QWORD PTR [rsp+1296] + lea r10, QWORD PTR [rsp+1024] + mov r9, r12 + neg r12 + mov rax, QWORD PTR [r10] + pext rax, rax, r12 + add rax, rax + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [rcx+512], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [rcx+520], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [rcx+528], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [rcx+536], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [rcx+544], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [rcx+552], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [rcx+560], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [rcx+568], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [rcx+576], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [rcx+584], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [rcx+592], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [rcx+600], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [rcx+608], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [rcx+616], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [rcx+624], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [rcx+632], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [rcx+640], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [rcx+648], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [rcx+656], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [rcx+664], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [rcx+672], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [rcx+680], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [rcx+688], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [rcx+696], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [rcx+704], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [rcx+712], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [rcx+720], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [rcx+728], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [rcx+736], rax + pext r8, r8, r12 + adc r8, r8 + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [rcx+744], r8 + pext rax, rax, r12 + adc rax, rax + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [rcx+752], rax + pext r8, r8, r12 + adc r8, r8 + mov QWORD PTR [rcx+760], r8 + adc r9, 0 + lea rdx, QWORD PTR [rsp+512] + mov r10, rsp + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rdx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rdx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rdx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rdx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rdx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rdx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rdx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rdx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rdx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rdx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rdx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rdx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rdx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rdx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rdx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rdx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rdx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rdx+376] + mov rax, QWORD PTR [r10+384] + mov QWORD PTR [r10+376], r8 + sbb rax, QWORD PTR [rdx+384] + mov r8, QWORD PTR [r10+392] + mov QWORD PTR [r10+384], rax + sbb r8, QWORD PTR [rdx+392] + mov rax, QWORD PTR [r10+400] + mov QWORD PTR [r10+392], r8 + sbb rax, QWORD PTR [rdx+400] + mov r8, QWORD PTR [r10+408] + mov QWORD PTR [r10+400], rax + sbb r8, QWORD PTR [rdx+408] + mov rax, QWORD PTR [r10+416] + mov QWORD PTR [r10+408], r8 + sbb rax, QWORD PTR [rdx+416] + mov r8, QWORD PTR [r10+424] + mov QWORD PTR [r10+416], rax + sbb r8, QWORD PTR [rdx+424] + mov rax, QWORD PTR [r10+432] + mov QWORD PTR [r10+424], r8 + sbb rax, QWORD PTR [rdx+432] + mov r8, QWORD PTR [r10+440] + mov QWORD PTR [r10+432], rax + sbb r8, QWORD PTR [rdx+440] + mov rax, QWORD PTR [r10+448] + mov QWORD PTR [r10+440], r8 + sbb rax, QWORD PTR [rdx+448] + mov r8, QWORD PTR [r10+456] + mov QWORD PTR [r10+448], rax + sbb r8, QWORD PTR [rdx+456] + mov rax, QWORD PTR [r10+464] + mov QWORD PTR [r10+456], r8 + sbb rax, QWORD PTR [rdx+464] + mov r8, QWORD PTR [r10+472] + mov QWORD PTR [r10+464], rax + sbb r8, QWORD PTR [rdx+472] + mov rax, QWORD PTR [r10+480] + mov QWORD PTR [r10+472], r8 + sbb rax, QWORD PTR [rdx+480] + mov r8, QWORD PTR [r10+488] + mov QWORD PTR [r10+480], rax + sbb r8, QWORD PTR [rdx+488] + mov rax, QWORD PTR [r10+496] + mov QWORD PTR [r10+488], r8 + sbb rax, QWORD PTR [rdx+496] + mov r8, QWORD PTR [r10+504] + mov QWORD PTR [r10+496], rax + sbb r8, QWORD PTR [rdx+504] + mov QWORD PTR [r10+504], r8 + sbb r9, 0 + mov rax, QWORD PTR [r10] + sub rax, QWORD PTR [rcx] + mov r8, QWORD PTR [r10+8] + mov QWORD PTR [r10], rax + sbb r8, QWORD PTR [rcx+8] + mov rax, QWORD PTR [r10+16] + mov QWORD PTR [r10+8], r8 + sbb rax, QWORD PTR [rcx+16] + mov r8, QWORD PTR [r10+24] + mov QWORD PTR [r10+16], rax + sbb r8, QWORD PTR [rcx+24] + mov rax, QWORD PTR [r10+32] + mov QWORD PTR [r10+24], r8 + sbb rax, QWORD PTR [rcx+32] + mov r8, QWORD PTR [r10+40] + mov QWORD PTR [r10+32], rax + sbb r8, QWORD PTR [rcx+40] + mov rax, QWORD PTR [r10+48] + mov QWORD PTR [r10+40], r8 + sbb rax, QWORD PTR [rcx+48] + mov r8, QWORD PTR [r10+56] + mov QWORD PTR [r10+48], rax + sbb r8, QWORD PTR [rcx+56] + mov rax, QWORD PTR [r10+64] + mov QWORD PTR [r10+56], r8 + sbb rax, QWORD PTR [rcx+64] + mov r8, QWORD PTR [r10+72] + mov QWORD PTR [r10+64], rax + sbb r8, QWORD PTR [rcx+72] + mov rax, QWORD PTR [r10+80] + mov QWORD PTR [r10+72], r8 + sbb rax, QWORD PTR [rcx+80] + mov r8, QWORD PTR [r10+88] + mov QWORD PTR [r10+80], rax + sbb r8, QWORD PTR [rcx+88] + mov rax, QWORD PTR [r10+96] + mov QWORD PTR [r10+88], r8 + sbb rax, QWORD PTR [rcx+96] + mov r8, QWORD PTR [r10+104] + mov QWORD PTR [r10+96], rax + sbb r8, QWORD PTR [rcx+104] + mov rax, QWORD PTR [r10+112] + mov QWORD PTR [r10+104], r8 + sbb rax, QWORD PTR [rcx+112] + mov r8, QWORD PTR [r10+120] + mov QWORD PTR [r10+112], rax + sbb r8, QWORD PTR [rcx+120] + mov rax, QWORD PTR [r10+128] + mov QWORD PTR [r10+120], r8 + sbb rax, QWORD PTR [rcx+128] + mov r8, QWORD PTR [r10+136] + mov QWORD PTR [r10+128], rax + sbb r8, QWORD PTR [rcx+136] + mov rax, QWORD PTR [r10+144] + mov QWORD PTR [r10+136], r8 + sbb rax, QWORD PTR [rcx+144] + mov r8, QWORD PTR [r10+152] + mov QWORD PTR [r10+144], rax + sbb r8, QWORD PTR [rcx+152] + mov rax, QWORD PTR [r10+160] + mov QWORD PTR [r10+152], r8 + sbb rax, QWORD PTR [rcx+160] + mov r8, QWORD PTR [r10+168] + mov QWORD PTR [r10+160], rax + sbb r8, QWORD PTR [rcx+168] + mov rax, QWORD PTR [r10+176] + mov QWORD PTR [r10+168], r8 + sbb rax, QWORD PTR [rcx+176] + mov r8, QWORD PTR [r10+184] + mov QWORD PTR [r10+176], rax + sbb r8, QWORD PTR [rcx+184] + mov rax, QWORD PTR [r10+192] + mov QWORD PTR [r10+184], r8 + sbb rax, QWORD PTR [rcx+192] + mov r8, QWORD PTR [r10+200] + mov QWORD PTR [r10+192], rax + sbb r8, QWORD PTR [rcx+200] + mov rax, QWORD PTR [r10+208] + mov QWORD PTR [r10+200], r8 + sbb rax, QWORD PTR [rcx+208] + mov r8, QWORD PTR [r10+216] + mov QWORD PTR [r10+208], rax + sbb r8, QWORD PTR [rcx+216] + mov rax, QWORD PTR [r10+224] + mov QWORD PTR [r10+216], r8 + sbb rax, QWORD PTR [rcx+224] + mov r8, QWORD PTR [r10+232] + mov QWORD PTR [r10+224], rax + sbb r8, QWORD PTR [rcx+232] + mov rax, QWORD PTR [r10+240] + mov QWORD PTR [r10+232], r8 + sbb rax, QWORD PTR [rcx+240] + mov r8, QWORD PTR [r10+248] + mov QWORD PTR [r10+240], rax + sbb r8, QWORD PTR [rcx+248] + mov rax, QWORD PTR [r10+256] + mov QWORD PTR [r10+248], r8 + sbb rax, QWORD PTR [rcx+256] + mov r8, QWORD PTR [r10+264] + mov QWORD PTR [r10+256], rax + sbb r8, QWORD PTR [rcx+264] + mov rax, QWORD PTR [r10+272] + mov QWORD PTR [r10+264], r8 + sbb rax, QWORD PTR [rcx+272] + mov r8, QWORD PTR [r10+280] + mov QWORD PTR [r10+272], rax + sbb r8, QWORD PTR [rcx+280] + mov rax, QWORD PTR [r10+288] + mov QWORD PTR [r10+280], r8 + sbb rax, QWORD PTR [rcx+288] + mov r8, QWORD PTR [r10+296] + mov QWORD PTR [r10+288], rax + sbb r8, QWORD PTR [rcx+296] + mov rax, QWORD PTR [r10+304] + mov QWORD PTR [r10+296], r8 + sbb rax, QWORD PTR [rcx+304] + mov r8, QWORD PTR [r10+312] + mov QWORD PTR [r10+304], rax + sbb r8, QWORD PTR [rcx+312] + mov rax, QWORD PTR [r10+320] + mov QWORD PTR [r10+312], r8 + sbb rax, QWORD PTR [rcx+320] + mov r8, QWORD PTR [r10+328] + mov QWORD PTR [r10+320], rax + sbb r8, QWORD PTR [rcx+328] + mov rax, QWORD PTR [r10+336] + mov QWORD PTR [r10+328], r8 + sbb rax, QWORD PTR [rcx+336] + mov r8, QWORD PTR [r10+344] + mov QWORD PTR [r10+336], rax + sbb r8, QWORD PTR [rcx+344] + mov rax, QWORD PTR [r10+352] + mov QWORD PTR [r10+344], r8 + sbb rax, QWORD PTR [rcx+352] + mov r8, QWORD PTR [r10+360] + mov QWORD PTR [r10+352], rax + sbb r8, QWORD PTR [rcx+360] + mov rax, QWORD PTR [r10+368] + mov QWORD PTR [r10+360], r8 + sbb rax, QWORD PTR [rcx+368] + mov r8, QWORD PTR [r10+376] + mov QWORD PTR [r10+368], rax + sbb r8, QWORD PTR [rcx+376] + mov rax, QWORD PTR [r10+384] + mov QWORD PTR [r10+376], r8 + sbb rax, QWORD PTR [rcx+384] + mov r8, QWORD PTR [r10+392] + mov QWORD PTR [r10+384], rax + sbb r8, QWORD PTR [rcx+392] + mov rax, QWORD PTR [r10+400] + mov QWORD PTR [r10+392], r8 + sbb rax, QWORD PTR [rcx+400] + mov r8, QWORD PTR [r10+408] + mov QWORD PTR [r10+400], rax + sbb r8, QWORD PTR [rcx+408] + mov rax, QWORD PTR [r10+416] + mov QWORD PTR [r10+408], r8 + sbb rax, QWORD PTR [rcx+416] + mov r8, QWORD PTR [r10+424] + mov QWORD PTR [r10+416], rax + sbb r8, QWORD PTR [rcx+424] + mov rax, QWORD PTR [r10+432] + mov QWORD PTR [r10+424], r8 + sbb rax, QWORD PTR [rcx+432] + mov r8, QWORD PTR [r10+440] + mov QWORD PTR [r10+432], rax + sbb r8, QWORD PTR [rcx+440] + mov rax, QWORD PTR [r10+448] + mov QWORD PTR [r10+440], r8 + sbb rax, QWORD PTR [rcx+448] + mov r8, QWORD PTR [r10+456] + mov QWORD PTR [r10+448], rax + sbb r8, QWORD PTR [rcx+456] + mov rax, QWORD PTR [r10+464] + mov QWORD PTR [r10+456], r8 + sbb rax, QWORD PTR [rcx+464] + mov r8, QWORD PTR [r10+472] + mov QWORD PTR [r10+464], rax + sbb r8, QWORD PTR [rcx+472] + mov rax, QWORD PTR [r10+480] + mov QWORD PTR [r10+472], r8 + sbb rax, QWORD PTR [rcx+480] + mov r8, QWORD PTR [r10+488] + mov QWORD PTR [r10+480], rax + sbb r8, QWORD PTR [rcx+488] + mov rax, QWORD PTR [r10+496] + mov QWORD PTR [r10+488], r8 + sbb rax, QWORD PTR [rcx+496] + mov r8, QWORD PTR [r10+504] + mov QWORD PTR [r10+496], rax + sbb r8, QWORD PTR [rcx+504] + mov QWORD PTR [r10+504], r8 + sbb r9, 0 + ; Add in place + mov rax, QWORD PTR [rcx+256] + add rax, QWORD PTR [r10] + mov r8, QWORD PTR [rcx+264] + mov QWORD PTR [rcx+256], rax + adc r8, QWORD PTR [r10+8] + mov rax, QWORD PTR [rcx+272] + mov QWORD PTR [rcx+264], r8 + adc rax, QWORD PTR [r10+16] + mov r8, QWORD PTR [rcx+280] + mov QWORD PTR [rcx+272], rax + adc r8, QWORD PTR [r10+24] + mov rax, QWORD PTR [rcx+288] + mov QWORD PTR [rcx+280], r8 + adc rax, QWORD PTR [r10+32] + mov r8, QWORD PTR [rcx+296] + mov QWORD PTR [rcx+288], rax + adc r8, QWORD PTR [r10+40] + mov rax, QWORD PTR [rcx+304] + mov QWORD PTR [rcx+296], r8 + adc rax, QWORD PTR [r10+48] + mov r8, QWORD PTR [rcx+312] + mov QWORD PTR [rcx+304], rax + adc r8, QWORD PTR [r10+56] + mov rax, QWORD PTR [rcx+320] + mov QWORD PTR [rcx+312], r8 + adc rax, QWORD PTR [r10+64] + mov r8, QWORD PTR [rcx+328] + mov QWORD PTR [rcx+320], rax + adc r8, QWORD PTR [r10+72] + mov rax, QWORD PTR [rcx+336] + mov QWORD PTR [rcx+328], r8 + adc rax, QWORD PTR [r10+80] + mov r8, QWORD PTR [rcx+344] + mov QWORD PTR [rcx+336], rax + adc r8, QWORD PTR [r10+88] + mov rax, QWORD PTR [rcx+352] + mov QWORD PTR [rcx+344], r8 + adc rax, QWORD PTR [r10+96] + mov r8, QWORD PTR [rcx+360] + mov QWORD PTR [rcx+352], rax + adc r8, QWORD PTR [r10+104] + mov rax, QWORD PTR [rcx+368] + mov QWORD PTR [rcx+360], r8 + adc rax, QWORD PTR [r10+112] + mov r8, QWORD PTR [rcx+376] + mov QWORD PTR [rcx+368], rax + adc r8, QWORD PTR [r10+120] + mov rax, QWORD PTR [rcx+384] + mov QWORD PTR [rcx+376], r8 + adc rax, QWORD PTR [r10+128] + mov r8, QWORD PTR [rcx+392] + mov QWORD PTR [rcx+384], rax + adc r8, QWORD PTR [r10+136] + mov rax, QWORD PTR [rcx+400] + mov QWORD PTR [rcx+392], r8 + adc rax, QWORD PTR [r10+144] + mov r8, QWORD PTR [rcx+408] + mov QWORD PTR [rcx+400], rax + adc r8, QWORD PTR [r10+152] + mov rax, QWORD PTR [rcx+416] + mov QWORD PTR [rcx+408], r8 + adc rax, QWORD PTR [r10+160] + mov r8, QWORD PTR [rcx+424] + mov QWORD PTR [rcx+416], rax + adc r8, QWORD PTR [r10+168] + mov rax, QWORD PTR [rcx+432] + mov QWORD PTR [rcx+424], r8 + adc rax, QWORD PTR [r10+176] + mov r8, QWORD PTR [rcx+440] + mov QWORD PTR [rcx+432], rax + adc r8, QWORD PTR [r10+184] + mov rax, QWORD PTR [rcx+448] + mov QWORD PTR [rcx+440], r8 + adc rax, QWORD PTR [r10+192] + mov r8, QWORD PTR [rcx+456] + mov QWORD PTR [rcx+448], rax + adc r8, QWORD PTR [r10+200] + mov rax, QWORD PTR [rcx+464] + mov QWORD PTR [rcx+456], r8 + adc rax, QWORD PTR [r10+208] + mov r8, QWORD PTR [rcx+472] + mov QWORD PTR [rcx+464], rax + adc r8, QWORD PTR [r10+216] + mov rax, QWORD PTR [rcx+480] + mov QWORD PTR [rcx+472], r8 + adc rax, QWORD PTR [r10+224] + mov r8, QWORD PTR [rcx+488] + mov QWORD PTR [rcx+480], rax + adc r8, QWORD PTR [r10+232] + mov rax, QWORD PTR [rcx+496] + mov QWORD PTR [rcx+488], r8 + adc rax, QWORD PTR [r10+240] + mov r8, QWORD PTR [rcx+504] + mov QWORD PTR [rcx+496], rax + adc r8, QWORD PTR [r10+248] + mov rax, QWORD PTR [rcx+512] + mov QWORD PTR [rcx+504], r8 + adc rax, QWORD PTR [r10+256] + mov r8, QWORD PTR [rcx+520] + mov QWORD PTR [rcx+512], rax + adc r8, QWORD PTR [r10+264] + mov rax, QWORD PTR [rcx+528] + mov QWORD PTR [rcx+520], r8 + adc rax, QWORD PTR [r10+272] + mov r8, QWORD PTR [rcx+536] + mov QWORD PTR [rcx+528], rax + adc r8, QWORD PTR [r10+280] + mov rax, QWORD PTR [rcx+544] + mov QWORD PTR [rcx+536], r8 + adc rax, QWORD PTR [r10+288] + mov r8, QWORD PTR [rcx+552] + mov QWORD PTR [rcx+544], rax + adc r8, QWORD PTR [r10+296] + mov rax, QWORD PTR [rcx+560] + mov QWORD PTR [rcx+552], r8 + adc rax, QWORD PTR [r10+304] + mov r8, QWORD PTR [rcx+568] + mov QWORD PTR [rcx+560], rax + adc r8, QWORD PTR [r10+312] + mov rax, QWORD PTR [rcx+576] + mov QWORD PTR [rcx+568], r8 + adc rax, QWORD PTR [r10+320] + mov r8, QWORD PTR [rcx+584] + mov QWORD PTR [rcx+576], rax + adc r8, QWORD PTR [r10+328] + mov rax, QWORD PTR [rcx+592] + mov QWORD PTR [rcx+584], r8 + adc rax, QWORD PTR [r10+336] + mov r8, QWORD PTR [rcx+600] + mov QWORD PTR [rcx+592], rax + adc r8, QWORD PTR [r10+344] + mov rax, QWORD PTR [rcx+608] + mov QWORD PTR [rcx+600], r8 + adc rax, QWORD PTR [r10+352] + mov r8, QWORD PTR [rcx+616] + mov QWORD PTR [rcx+608], rax + adc r8, QWORD PTR [r10+360] + mov rax, QWORD PTR [rcx+624] + mov QWORD PTR [rcx+616], r8 + adc rax, QWORD PTR [r10+368] + mov r8, QWORD PTR [rcx+632] + mov QWORD PTR [rcx+624], rax + adc r8, QWORD PTR [r10+376] + mov rax, QWORD PTR [rcx+640] + mov QWORD PTR [rcx+632], r8 + adc rax, QWORD PTR [r10+384] + mov r8, QWORD PTR [rcx+648] + mov QWORD PTR [rcx+640], rax + adc r8, QWORD PTR [r10+392] + mov rax, QWORD PTR [rcx+656] + mov QWORD PTR [rcx+648], r8 + adc rax, QWORD PTR [r10+400] + mov r8, QWORD PTR [rcx+664] + mov QWORD PTR [rcx+656], rax + adc r8, QWORD PTR [r10+408] + mov rax, QWORD PTR [rcx+672] + mov QWORD PTR [rcx+664], r8 + adc rax, QWORD PTR [r10+416] + mov r8, QWORD PTR [rcx+680] + mov QWORD PTR [rcx+672], rax + adc r8, QWORD PTR [r10+424] + mov rax, QWORD PTR [rcx+688] + mov QWORD PTR [rcx+680], r8 + adc rax, QWORD PTR [r10+432] + mov r8, QWORD PTR [rcx+696] + mov QWORD PTR [rcx+688], rax + adc r8, QWORD PTR [r10+440] + mov rax, QWORD PTR [rcx+704] + mov QWORD PTR [rcx+696], r8 + adc rax, QWORD PTR [r10+448] + mov r8, QWORD PTR [rcx+712] + mov QWORD PTR [rcx+704], rax + adc r8, QWORD PTR [r10+456] + mov rax, QWORD PTR [rcx+720] + mov QWORD PTR [rcx+712], r8 + adc rax, QWORD PTR [r10+464] + mov r8, QWORD PTR [rcx+728] + mov QWORD PTR [rcx+720], rax + adc r8, QWORD PTR [r10+472] + mov rax, QWORD PTR [rcx+736] + mov QWORD PTR [rcx+728], r8 + adc rax, QWORD PTR [r10+480] + mov r8, QWORD PTR [rcx+744] + mov QWORD PTR [rcx+736], rax + adc r8, QWORD PTR [r10+488] + mov rax, QWORD PTR [rcx+752] + mov QWORD PTR [rcx+744], r8 + adc rax, QWORD PTR [r10+496] + mov r8, QWORD PTR [rcx+760] + mov QWORD PTR [rcx+752], rax + adc r8, QWORD PTR [r10+504] + mov QWORD PTR [rcx+760], r8 + adc r9, 0 + mov QWORD PTR [rcx+768], r9 + ; Add in place + mov rax, QWORD PTR [rcx+512] + xor r9, r9 + add rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rcx+520] + mov QWORD PTR [rcx+512], rax + adc r8, QWORD PTR [rdx+8] + mov rax, QWORD PTR [rcx+528] + mov QWORD PTR [rcx+520], r8 + adc rax, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rcx+536] + mov QWORD PTR [rcx+528], rax + adc r8, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rcx+544] + mov QWORD PTR [rcx+536], r8 + adc rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rcx+552] + mov QWORD PTR [rcx+544], rax + adc r8, QWORD PTR [rdx+40] + mov rax, QWORD PTR [rcx+560] + mov QWORD PTR [rcx+552], r8 + adc rax, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rcx+568] + mov QWORD PTR [rcx+560], rax + adc r8, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rcx+576] + mov QWORD PTR [rcx+568], r8 + adc rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rcx+584] + mov QWORD PTR [rcx+576], rax + adc r8, QWORD PTR [rdx+72] + mov rax, QWORD PTR [rcx+592] + mov QWORD PTR [rcx+584], r8 + adc rax, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rcx+600] + mov QWORD PTR [rcx+592], rax + adc r8, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rcx+608] + mov QWORD PTR [rcx+600], r8 + adc rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rcx+616] + mov QWORD PTR [rcx+608], rax + adc r8, QWORD PTR [rdx+104] + mov rax, QWORD PTR [rcx+624] + mov QWORD PTR [rcx+616], r8 + adc rax, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rcx+632] + mov QWORD PTR [rcx+624], rax + adc r8, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rcx+640] + mov QWORD PTR [rcx+632], r8 + adc rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rcx+648] + mov QWORD PTR [rcx+640], rax + adc r8, QWORD PTR [rdx+136] + mov rax, QWORD PTR [rcx+656] + mov QWORD PTR [rcx+648], r8 + adc rax, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rcx+664] + mov QWORD PTR [rcx+656], rax + adc r8, QWORD PTR [rdx+152] + mov rax, QWORD PTR [rcx+672] + mov QWORD PTR [rcx+664], r8 + adc rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rcx+680] + mov QWORD PTR [rcx+672], rax + adc r8, QWORD PTR [rdx+168] + mov rax, QWORD PTR [rcx+688] + mov QWORD PTR [rcx+680], r8 + adc rax, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rcx+696] + mov QWORD PTR [rcx+688], rax + adc r8, QWORD PTR [rdx+184] + mov rax, QWORD PTR [rcx+704] + mov QWORD PTR [rcx+696], r8 + adc rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rcx+712] + mov QWORD PTR [rcx+704], rax + adc r8, QWORD PTR [rdx+200] + mov rax, QWORD PTR [rcx+720] + mov QWORD PTR [rcx+712], r8 + adc rax, QWORD PTR [rdx+208] + mov r8, QWORD PTR [rcx+728] + mov QWORD PTR [rcx+720], rax + adc r8, QWORD PTR [rdx+216] + mov rax, QWORD PTR [rcx+736] + mov QWORD PTR [rcx+728], r8 + adc rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rcx+744] + mov QWORD PTR [rcx+736], rax + adc r8, QWORD PTR [rdx+232] + mov rax, QWORD PTR [rcx+752] + mov QWORD PTR [rcx+744], r8 + adc rax, QWORD PTR [rdx+240] + mov r8, QWORD PTR [rcx+760] + mov QWORD PTR [rcx+752], rax + adc r8, QWORD PTR [rdx+248] + mov rax, QWORD PTR [rcx+768] + mov QWORD PTR [rcx+760], r8 + adc rax, QWORD PTR [rdx+256] + mov QWORD PTR [rcx+768], rax + adc r9, 0 + ; Add to zero + mov rax, QWORD PTR [rdx+264] + adc rax, 0 + mov r8, QWORD PTR [rdx+272] + mov QWORD PTR [rcx+776], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+280] + mov QWORD PTR [rcx+784], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+288] + mov QWORD PTR [rcx+792], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+296] + mov QWORD PTR [rcx+800], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+304] + mov QWORD PTR [rcx+808], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+312] + mov QWORD PTR [rcx+816], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+320] + mov QWORD PTR [rcx+824], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+328] + mov QWORD PTR [rcx+832], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+336] + mov QWORD PTR [rcx+840], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+344] + mov QWORD PTR [rcx+848], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+352] + mov QWORD PTR [rcx+856], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+360] + mov QWORD PTR [rcx+864], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+368] + mov QWORD PTR [rcx+872], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+880], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+384] + mov QWORD PTR [rcx+888], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+392] + mov QWORD PTR [rcx+896], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+400] + mov QWORD PTR [rcx+904], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+408] + mov QWORD PTR [rcx+912], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+416] + mov QWORD PTR [rcx+920], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+424] + mov QWORD PTR [rcx+928], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+432] + mov QWORD PTR [rcx+936], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+440] + mov QWORD PTR [rcx+944], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+448] + mov QWORD PTR [rcx+952], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+456] + mov QWORD PTR [rcx+960], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+464] + mov QWORD PTR [rcx+968], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+472] + mov QWORD PTR [rcx+976], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+480] + mov QWORD PTR [rcx+984], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+488] + mov QWORD PTR [rcx+992], r8 + adc rax, 0 + mov r8, QWORD PTR [rdx+496] + mov QWORD PTR [rcx+1000], rax + adc r8, 0 + mov rax, QWORD PTR [rdx+504] + mov QWORD PTR [rcx+1008], r8 + adc rax, 0 + mov QWORD PTR [rcx+1016], rax + add rsp, 1304 + pop r12 + ret +sp_4096_sqr_avx2_64 ENDP +_text ENDS +ENDIF +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_4096_mul_d_64 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+40] + add r12, rax + mov QWORD PTR [rcx+40], r12 + adc r10, rdx + adc r11, 0 + ; A[6] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+48] + add r10, rax + mov QWORD PTR [rcx+48], r10 + adc r11, rdx + adc r12, 0 + ; A[7] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+56] + add r11, rax + mov QWORD PTR [rcx+56], r11 + adc r12, rdx + adc r10, 0 + ; A[8] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+64] + add r12, rax + mov QWORD PTR [rcx+64], r12 + adc r10, rdx + adc r11, 0 + ; A[9] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+72] + add r10, rax + mov QWORD PTR [rcx+72], r10 + adc r11, rdx + adc r12, 0 + ; A[10] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+80] + add r11, rax + mov QWORD PTR [rcx+80], r11 + adc r12, rdx + adc r10, 0 + ; A[11] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+88] + add r12, rax + mov QWORD PTR [rcx+88], r12 + adc r10, rdx + adc r11, 0 + ; A[12] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+96] + add r10, rax + mov QWORD PTR [rcx+96], r10 + adc r11, rdx + adc r12, 0 + ; A[13] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+104] + add r11, rax + mov QWORD PTR [rcx+104], r11 + adc r12, rdx + adc r10, 0 + ; A[14] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+112] + add r12, rax + mov QWORD PTR [rcx+112], r12 + adc r10, rdx + adc r11, 0 + ; A[15] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+120] + add r10, rax + mov QWORD PTR [rcx+120], r10 + adc r11, rdx + adc r12, 0 + ; A[16] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+128] + add r11, rax + mov QWORD PTR [rcx+128], r11 + adc r12, rdx + adc r10, 0 + ; A[17] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+136] + add r12, rax + mov QWORD PTR [rcx+136], r12 + adc r10, rdx + adc r11, 0 + ; A[18] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+144] + add r10, rax + mov QWORD PTR [rcx+144], r10 + adc r11, rdx + adc r12, 0 + ; A[19] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+152] + add r11, rax + mov QWORD PTR [rcx+152], r11 + adc r12, rdx + adc r10, 0 + ; A[20] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+160] + add r12, rax + mov QWORD PTR [rcx+160], r12 + adc r10, rdx + adc r11, 0 + ; A[21] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+168] + add r10, rax + mov QWORD PTR [rcx+168], r10 + adc r11, rdx + adc r12, 0 + ; A[22] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+176] + add r11, rax + mov QWORD PTR [rcx+176], r11 + adc r12, rdx + adc r10, 0 + ; A[23] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+184] + add r12, rax + mov QWORD PTR [rcx+184], r12 + adc r10, rdx + adc r11, 0 + ; A[24] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+192] + add r10, rax + mov QWORD PTR [rcx+192], r10 + adc r11, rdx + adc r12, 0 + ; A[25] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+200] + add r11, rax + mov QWORD PTR [rcx+200], r11 + adc r12, rdx + adc r10, 0 + ; A[26] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+208] + add r12, rax + mov QWORD PTR [rcx+208], r12 + adc r10, rdx + adc r11, 0 + ; A[27] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+216] + add r10, rax + mov QWORD PTR [rcx+216], r10 + adc r11, rdx + adc r12, 0 + ; A[28] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+224] + add r11, rax + mov QWORD PTR [rcx+224], r11 + adc r12, rdx + adc r10, 0 + ; A[29] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+232] + add r12, rax + mov QWORD PTR [rcx+232], r12 + adc r10, rdx + adc r11, 0 + ; A[30] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+240] + add r10, rax + mov QWORD PTR [rcx+240], r10 + adc r11, rdx + adc r12, 0 + ; A[31] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+248] + add r11, rax + mov QWORD PTR [rcx+248], r11 + adc r12, rdx + adc r10, 0 + ; A[32] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+256] + add r12, rax + mov QWORD PTR [rcx+256], r12 + adc r10, rdx + adc r11, 0 + ; A[33] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+264] + add r10, rax + mov QWORD PTR [rcx+264], r10 + adc r11, rdx + adc r12, 0 + ; A[34] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+272] + add r11, rax + mov QWORD PTR [rcx+272], r11 + adc r12, rdx + adc r10, 0 + ; A[35] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+280] + add r12, rax + mov QWORD PTR [rcx+280], r12 + adc r10, rdx + adc r11, 0 + ; A[36] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+288] + add r10, rax + mov QWORD PTR [rcx+288], r10 + adc r11, rdx + adc r12, 0 + ; A[37] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+296] + add r11, rax + mov QWORD PTR [rcx+296], r11 + adc r12, rdx + adc r10, 0 + ; A[38] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+304] + add r12, rax + mov QWORD PTR [rcx+304], r12 + adc r10, rdx + adc r11, 0 + ; A[39] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+312] + add r10, rax + mov QWORD PTR [rcx+312], r10 + adc r11, rdx + adc r12, 0 + ; A[40] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+320] + add r11, rax + mov QWORD PTR [rcx+320], r11 + adc r12, rdx + adc r10, 0 + ; A[41] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+328] + add r12, rax + mov QWORD PTR [rcx+328], r12 + adc r10, rdx + adc r11, 0 + ; A[42] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+336] + add r10, rax + mov QWORD PTR [rcx+336], r10 + adc r11, rdx + adc r12, 0 + ; A[43] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+344] + add r11, rax + mov QWORD PTR [rcx+344], r11 + adc r12, rdx + adc r10, 0 + ; A[44] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+352] + add r12, rax + mov QWORD PTR [rcx+352], r12 + adc r10, rdx + adc r11, 0 + ; A[45] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+360] + add r10, rax + mov QWORD PTR [rcx+360], r10 + adc r11, rdx + adc r12, 0 + ; A[46] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+368] + add r11, rax + mov QWORD PTR [rcx+368], r11 + adc r12, rdx + adc r10, 0 + ; A[47] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+376] + add r12, rax + mov QWORD PTR [rcx+376], r12 + adc r10, rdx + adc r11, 0 + ; A[48] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+384] + add r10, rax + mov QWORD PTR [rcx+384], r10 + adc r11, rdx + adc r12, 0 + ; A[49] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+392] + add r11, rax + mov QWORD PTR [rcx+392], r11 + adc r12, rdx + adc r10, 0 + ; A[50] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+400] + add r12, rax + mov QWORD PTR [rcx+400], r12 + adc r10, rdx + adc r11, 0 + ; A[51] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+408] + add r10, rax + mov QWORD PTR [rcx+408], r10 + adc r11, rdx + adc r12, 0 + ; A[52] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+416] + add r11, rax + mov QWORD PTR [rcx+416], r11 + adc r12, rdx + adc r10, 0 + ; A[53] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+424] + add r12, rax + mov QWORD PTR [rcx+424], r12 + adc r10, rdx + adc r11, 0 + ; A[54] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+432] + add r10, rax + mov QWORD PTR [rcx+432], r10 + adc r11, rdx + adc r12, 0 + ; A[55] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+440] + add r11, rax + mov QWORD PTR [rcx+440], r11 + adc r12, rdx + adc r10, 0 + ; A[56] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+448] + add r12, rax + mov QWORD PTR [rcx+448], r12 + adc r10, rdx + adc r11, 0 + ; A[57] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+456] + add r10, rax + mov QWORD PTR [rcx+456], r10 + adc r11, rdx + adc r12, 0 + ; A[58] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+464] + add r11, rax + mov QWORD PTR [rcx+464], r11 + adc r12, rdx + adc r10, 0 + ; A[59] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+472] + add r12, rax + mov QWORD PTR [rcx+472], r12 + adc r10, rdx + adc r11, 0 + ; A[60] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+480] + add r10, rax + mov QWORD PTR [rcx+480], r10 + adc r11, rdx + adc r12, 0 + ; A[61] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+488] + add r11, rax + mov QWORD PTR [rcx+488], r11 + adc r12, rdx + adc r10, 0 + ; A[62] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+496] + add r12, rax + mov QWORD PTR [rcx+496], r12 + adc r10, rdx + adc r11, 0 + ; A[63] * B + mov rax, r8 + mul QWORD PTR [r9+504] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+504], r10 + mov QWORD PTR [rcx+512], r11 + pop r12 + ret +sp_4096_mul_d_64 ENDP +_text ENDS +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_4096_cond_sub_64 PROC + sub rsp, 512 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [r8+128] + mov r11, QWORD PTR [r8+136] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+128], r10 + mov QWORD PTR [rsp+136], r11 + mov r10, QWORD PTR [r8+144] + mov r11, QWORD PTR [r8+152] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+144], r10 + mov QWORD PTR [rsp+152], r11 + mov r10, QWORD PTR [r8+160] + mov r11, QWORD PTR [r8+168] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+160], r10 + mov QWORD PTR [rsp+168], r11 + mov r10, QWORD PTR [r8+176] + mov r11, QWORD PTR [r8+184] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+176], r10 + mov QWORD PTR [rsp+184], r11 + mov r10, QWORD PTR [r8+192] + mov r11, QWORD PTR [r8+200] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+192], r10 + mov QWORD PTR [rsp+200], r11 + mov r10, QWORD PTR [r8+208] + mov r11, QWORD PTR [r8+216] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+208], r10 + mov QWORD PTR [rsp+216], r11 + mov r10, QWORD PTR [r8+224] + mov r11, QWORD PTR [r8+232] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+224], r10 + mov QWORD PTR [rsp+232], r11 + mov r10, QWORD PTR [r8+240] + mov r11, QWORD PTR [r8+248] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+240], r10 + mov QWORD PTR [rsp+248], r11 + mov r10, QWORD PTR [r8+256] + mov r11, QWORD PTR [r8+264] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+256], r10 + mov QWORD PTR [rsp+264], r11 + mov r10, QWORD PTR [r8+272] + mov r11, QWORD PTR [r8+280] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+272], r10 + mov QWORD PTR [rsp+280], r11 + mov r10, QWORD PTR [r8+288] + mov r11, QWORD PTR [r8+296] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+288], r10 + mov QWORD PTR [rsp+296], r11 + mov r10, QWORD PTR [r8+304] + mov r11, QWORD PTR [r8+312] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+304], r10 + mov QWORD PTR [rsp+312], r11 + mov r10, QWORD PTR [r8+320] + mov r11, QWORD PTR [r8+328] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+320], r10 + mov QWORD PTR [rsp+328], r11 + mov r10, QWORD PTR [r8+336] + mov r11, QWORD PTR [r8+344] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+336], r10 + mov QWORD PTR [rsp+344], r11 + mov r10, QWORD PTR [r8+352] + mov r11, QWORD PTR [r8+360] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+352], r10 + mov QWORD PTR [rsp+360], r11 + mov r10, QWORD PTR [r8+368] + mov r11, QWORD PTR [r8+376] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+368], r10 + mov QWORD PTR [rsp+376], r11 + mov r10, QWORD PTR [r8+384] + mov r11, QWORD PTR [r8+392] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+384], r10 + mov QWORD PTR [rsp+392], r11 + mov r10, QWORD PTR [r8+400] + mov r11, QWORD PTR [r8+408] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+400], r10 + mov QWORD PTR [rsp+408], r11 + mov r10, QWORD PTR [r8+416] + mov r11, QWORD PTR [r8+424] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+416], r10 + mov QWORD PTR [rsp+424], r11 + mov r10, QWORD PTR [r8+432] + mov r11, QWORD PTR [r8+440] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+432], r10 + mov QWORD PTR [rsp+440], r11 + mov r10, QWORD PTR [r8+448] + mov r11, QWORD PTR [r8+456] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+448], r10 + mov QWORD PTR [rsp+456], r11 + mov r10, QWORD PTR [r8+464] + mov r11, QWORD PTR [r8+472] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+464], r10 + mov QWORD PTR [rsp+472], r11 + mov r10, QWORD PTR [r8+480] + mov r11, QWORD PTR [r8+488] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+480], r10 + mov QWORD PTR [rsp+488], r11 + mov r10, QWORD PTR [r8+496] + mov r11, QWORD PTR [r8+504] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+496], r10 + mov QWORD PTR [rsp+504], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + sbb r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + sbb r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + sbb r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + sbb r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + sbb r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + sbb r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + sbb r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + sbb r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + sbb r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + sbb r11, r8 + mov QWORD PTR [rcx+112], r10 + mov r10, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rsp+128] + sbb r10, r8 + mov QWORD PTR [rcx+120], r11 + mov r11, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rsp+136] + sbb r11, r8 + mov QWORD PTR [rcx+128], r10 + mov r10, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rsp+144] + sbb r10, r8 + mov QWORD PTR [rcx+136], r11 + mov r11, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rsp+152] + sbb r11, r8 + mov QWORD PTR [rcx+144], r10 + mov r10, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rsp+160] + sbb r10, r8 + mov QWORD PTR [rcx+152], r11 + mov r11, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rsp+168] + sbb r11, r8 + mov QWORD PTR [rcx+160], r10 + mov r10, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rsp+176] + sbb r10, r8 + mov QWORD PTR [rcx+168], r11 + mov r11, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rsp+184] + sbb r11, r8 + mov QWORD PTR [rcx+176], r10 + mov r10, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rsp+192] + sbb r10, r8 + mov QWORD PTR [rcx+184], r11 + mov r11, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rsp+200] + sbb r11, r8 + mov QWORD PTR [rcx+192], r10 + mov r10, QWORD PTR [rdx+208] + mov r8, QWORD PTR [rsp+208] + sbb r10, r8 + mov QWORD PTR [rcx+200], r11 + mov r11, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rsp+216] + sbb r11, r8 + mov QWORD PTR [rcx+208], r10 + mov r10, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rsp+224] + sbb r10, r8 + mov QWORD PTR [rcx+216], r11 + mov r11, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rsp+232] + sbb r11, r8 + mov QWORD PTR [rcx+224], r10 + mov r10, QWORD PTR [rdx+240] + mov r8, QWORD PTR [rsp+240] + sbb r10, r8 + mov QWORD PTR [rcx+232], r11 + mov r11, QWORD PTR [rdx+248] + mov r8, QWORD PTR [rsp+248] + sbb r11, r8 + mov QWORD PTR [rcx+240], r10 + mov r10, QWORD PTR [rdx+256] + mov r8, QWORD PTR [rsp+256] + sbb r10, r8 + mov QWORD PTR [rcx+248], r11 + mov r11, QWORD PTR [rdx+264] + mov r8, QWORD PTR [rsp+264] + sbb r11, r8 + mov QWORD PTR [rcx+256], r10 + mov r10, QWORD PTR [rdx+272] + mov r8, QWORD PTR [rsp+272] + sbb r10, r8 + mov QWORD PTR [rcx+264], r11 + mov r11, QWORD PTR [rdx+280] + mov r8, QWORD PTR [rsp+280] + sbb r11, r8 + mov QWORD PTR [rcx+272], r10 + mov r10, QWORD PTR [rdx+288] + mov r8, QWORD PTR [rsp+288] + sbb r10, r8 + mov QWORD PTR [rcx+280], r11 + mov r11, QWORD PTR [rdx+296] + mov r8, QWORD PTR [rsp+296] + sbb r11, r8 + mov QWORD PTR [rcx+288], r10 + mov r10, QWORD PTR [rdx+304] + mov r8, QWORD PTR [rsp+304] + sbb r10, r8 + mov QWORD PTR [rcx+296], r11 + mov r11, QWORD PTR [rdx+312] + mov r8, QWORD PTR [rsp+312] + sbb r11, r8 + mov QWORD PTR [rcx+304], r10 + mov r10, QWORD PTR [rdx+320] + mov r8, QWORD PTR [rsp+320] + sbb r10, r8 + mov QWORD PTR [rcx+312], r11 + mov r11, QWORD PTR [rdx+328] + mov r8, QWORD PTR [rsp+328] + sbb r11, r8 + mov QWORD PTR [rcx+320], r10 + mov r10, QWORD PTR [rdx+336] + mov r8, QWORD PTR [rsp+336] + sbb r10, r8 + mov QWORD PTR [rcx+328], r11 + mov r11, QWORD PTR [rdx+344] + mov r8, QWORD PTR [rsp+344] + sbb r11, r8 + mov QWORD PTR [rcx+336], r10 + mov r10, QWORD PTR [rdx+352] + mov r8, QWORD PTR [rsp+352] + sbb r10, r8 + mov QWORD PTR [rcx+344], r11 + mov r11, QWORD PTR [rdx+360] + mov r8, QWORD PTR [rsp+360] + sbb r11, r8 + mov QWORD PTR [rcx+352], r10 + mov r10, QWORD PTR [rdx+368] + mov r8, QWORD PTR [rsp+368] + sbb r10, r8 + mov QWORD PTR [rcx+360], r11 + mov r11, QWORD PTR [rdx+376] + mov r8, QWORD PTR [rsp+376] + sbb r11, r8 + mov QWORD PTR [rcx+368], r10 + mov r10, QWORD PTR [rdx+384] + mov r8, QWORD PTR [rsp+384] + sbb r10, r8 + mov QWORD PTR [rcx+376], r11 + mov r11, QWORD PTR [rdx+392] + mov r8, QWORD PTR [rsp+392] + sbb r11, r8 + mov QWORD PTR [rcx+384], r10 + mov r10, QWORD PTR [rdx+400] + mov r8, QWORD PTR [rsp+400] + sbb r10, r8 + mov QWORD PTR [rcx+392], r11 + mov r11, QWORD PTR [rdx+408] + mov r8, QWORD PTR [rsp+408] + sbb r11, r8 + mov QWORD PTR [rcx+400], r10 + mov r10, QWORD PTR [rdx+416] + mov r8, QWORD PTR [rsp+416] + sbb r10, r8 + mov QWORD PTR [rcx+408], r11 + mov r11, QWORD PTR [rdx+424] + mov r8, QWORD PTR [rsp+424] + sbb r11, r8 + mov QWORD PTR [rcx+416], r10 + mov r10, QWORD PTR [rdx+432] + mov r8, QWORD PTR [rsp+432] + sbb r10, r8 + mov QWORD PTR [rcx+424], r11 + mov r11, QWORD PTR [rdx+440] + mov r8, QWORD PTR [rsp+440] + sbb r11, r8 + mov QWORD PTR [rcx+432], r10 + mov r10, QWORD PTR [rdx+448] + mov r8, QWORD PTR [rsp+448] + sbb r10, r8 + mov QWORD PTR [rcx+440], r11 + mov r11, QWORD PTR [rdx+456] + mov r8, QWORD PTR [rsp+456] + sbb r11, r8 + mov QWORD PTR [rcx+448], r10 + mov r10, QWORD PTR [rdx+464] + mov r8, QWORD PTR [rsp+464] + sbb r10, r8 + mov QWORD PTR [rcx+456], r11 + mov r11, QWORD PTR [rdx+472] + mov r8, QWORD PTR [rsp+472] + sbb r11, r8 + mov QWORD PTR [rcx+464], r10 + mov r10, QWORD PTR [rdx+480] + mov r8, QWORD PTR [rsp+480] + sbb r10, r8 + mov QWORD PTR [rcx+472], r11 + mov r11, QWORD PTR [rdx+488] + mov r8, QWORD PTR [rsp+488] + sbb r11, r8 + mov QWORD PTR [rcx+480], r10 + mov r10, QWORD PTR [rdx+496] + mov r8, QWORD PTR [rsp+496] + sbb r10, r8 + mov QWORD PTR [rcx+488], r11 + mov r11, QWORD PTR [rdx+504] + mov r8, QWORD PTR [rsp+504] + sbb r11, r8 + mov QWORD PTR [rcx+496], r10 + mov QWORD PTR [rcx+504], r11 + sbb rax, 0 + add rsp, 512 + ret +sp_4096_cond_sub_64 ENDP +_text ENDS +; /* Reduce the number back to 4096 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_4096_mont_reduce_64 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 64 + mov r10, 64 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_4096_mont_loop_64: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc r11, 0 + ; a[i+6] += m[6] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+48] + mov r14, QWORD PTR [rcx+48] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+48], r14 + adc r12, 0 + ; a[i+7] += m[7] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+56] + mov r14, QWORD PTR [rcx+56] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+56], r14 + adc r11, 0 + ; a[i+8] += m[8] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+64] + mov r14, QWORD PTR [rcx+64] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+64], r14 + adc r12, 0 + ; a[i+9] += m[9] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+72] + mov r14, QWORD PTR [rcx+72] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+72], r14 + adc r11, 0 + ; a[i+10] += m[10] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+80] + mov r14, QWORD PTR [rcx+80] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+80], r14 + adc r12, 0 + ; a[i+11] += m[11] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+88] + mov r14, QWORD PTR [rcx+88] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+88], r14 + adc r11, 0 + ; a[i+12] += m[12] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+96] + mov r14, QWORD PTR [rcx+96] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+96], r14 + adc r12, 0 + ; a[i+13] += m[13] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+104] + mov r14, QWORD PTR [rcx+104] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+104], r14 + adc r11, 0 + ; a[i+14] += m[14] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+112] + mov r14, QWORD PTR [rcx+112] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+112], r14 + adc r12, 0 + ; a[i+15] += m[15] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+120] + mov r14, QWORD PTR [rcx+120] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+120], r14 + adc r11, 0 + ; a[i+16] += m[16] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+128] + mov r14, QWORD PTR [rcx+128] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+128], r14 + adc r12, 0 + ; a[i+17] += m[17] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+136] + mov r14, QWORD PTR [rcx+136] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+136], r14 + adc r11, 0 + ; a[i+18] += m[18] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+144] + mov r14, QWORD PTR [rcx+144] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+144], r14 + adc r12, 0 + ; a[i+19] += m[19] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+152] + mov r14, QWORD PTR [rcx+152] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+152], r14 + adc r11, 0 + ; a[i+20] += m[20] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+160] + mov r14, QWORD PTR [rcx+160] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+160], r14 + adc r12, 0 + ; a[i+21] += m[21] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+168] + mov r14, QWORD PTR [rcx+168] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+168], r14 + adc r11, 0 + ; a[i+22] += m[22] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+176] + mov r14, QWORD PTR [rcx+176] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+176], r14 + adc r12, 0 + ; a[i+23] += m[23] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+184] + mov r14, QWORD PTR [rcx+184] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+184], r14 + adc r11, 0 + ; a[i+24] += m[24] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+192] + mov r14, QWORD PTR [rcx+192] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+192], r14 + adc r12, 0 + ; a[i+25] += m[25] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+200] + mov r14, QWORD PTR [rcx+200] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+200], r14 + adc r11, 0 + ; a[i+26] += m[26] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+208] + mov r14, QWORD PTR [rcx+208] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+208], r14 + adc r12, 0 + ; a[i+27] += m[27] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+216] + mov r14, QWORD PTR [rcx+216] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+216], r14 + adc r11, 0 + ; a[i+28] += m[28] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+224] + mov r14, QWORD PTR [rcx+224] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+224], r14 + adc r12, 0 + ; a[i+29] += m[29] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+232] + mov r14, QWORD PTR [rcx+232] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+232], r14 + adc r11, 0 + ; a[i+30] += m[30] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+240] + mov r14, QWORD PTR [rcx+240] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+240], r14 + adc r12, 0 + ; a[i+31] += m[31] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+248] + mov r14, QWORD PTR [rcx+248] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+248], r14 + adc r11, 0 + ; a[i+32] += m[32] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+256] + mov r14, QWORD PTR [rcx+256] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+256], r14 + adc r12, 0 + ; a[i+33] += m[33] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+264] + mov r14, QWORD PTR [rcx+264] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+264], r14 + adc r11, 0 + ; a[i+34] += m[34] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+272] + mov r14, QWORD PTR [rcx+272] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+272], r14 + adc r12, 0 + ; a[i+35] += m[35] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+280] + mov r14, QWORD PTR [rcx+280] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+280], r14 + adc r11, 0 + ; a[i+36] += m[36] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+288] + mov r14, QWORD PTR [rcx+288] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+288], r14 + adc r12, 0 + ; a[i+37] += m[37] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+296] + mov r14, QWORD PTR [rcx+296] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+296], r14 + adc r11, 0 + ; a[i+38] += m[38] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+304] + mov r14, QWORD PTR [rcx+304] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+304], r14 + adc r12, 0 + ; a[i+39] += m[39] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+312] + mov r14, QWORD PTR [rcx+312] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+312], r14 + adc r11, 0 + ; a[i+40] += m[40] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+320] + mov r14, QWORD PTR [rcx+320] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+320], r14 + adc r12, 0 + ; a[i+41] += m[41] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+328] + mov r14, QWORD PTR [rcx+328] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+328], r14 + adc r11, 0 + ; a[i+42] += m[42] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+336] + mov r14, QWORD PTR [rcx+336] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+336], r14 + adc r12, 0 + ; a[i+43] += m[43] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+344] + mov r14, QWORD PTR [rcx+344] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+344], r14 + adc r11, 0 + ; a[i+44] += m[44] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+352] + mov r14, QWORD PTR [rcx+352] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+352], r14 + adc r12, 0 + ; a[i+45] += m[45] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+360] + mov r14, QWORD PTR [rcx+360] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+360], r14 + adc r11, 0 + ; a[i+46] += m[46] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+368] + mov r14, QWORD PTR [rcx+368] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+368], r14 + adc r12, 0 + ; a[i+47] += m[47] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+376] + mov r14, QWORD PTR [rcx+376] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+376], r14 + adc r11, 0 + ; a[i+48] += m[48] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+384] + mov r14, QWORD PTR [rcx+384] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+384], r14 + adc r12, 0 + ; a[i+49] += m[49] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+392] + mov r14, QWORD PTR [rcx+392] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+392], r14 + adc r11, 0 + ; a[i+50] += m[50] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+400] + mov r14, QWORD PTR [rcx+400] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+400], r14 + adc r12, 0 + ; a[i+51] += m[51] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+408] + mov r14, QWORD PTR [rcx+408] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+408], r14 + adc r11, 0 + ; a[i+52] += m[52] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+416] + mov r14, QWORD PTR [rcx+416] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+416], r14 + adc r12, 0 + ; a[i+53] += m[53] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+424] + mov r14, QWORD PTR [rcx+424] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+424], r14 + adc r11, 0 + ; a[i+54] += m[54] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+432] + mov r14, QWORD PTR [rcx+432] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+432], r14 + adc r12, 0 + ; a[i+55] += m[55] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+440] + mov r14, QWORD PTR [rcx+440] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+440], r14 + adc r11, 0 + ; a[i+56] += m[56] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+448] + mov r14, QWORD PTR [rcx+448] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+448], r14 + adc r12, 0 + ; a[i+57] += m[57] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+456] + mov r14, QWORD PTR [rcx+456] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+456], r14 + adc r11, 0 + ; a[i+58] += m[58] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+464] + mov r14, QWORD PTR [rcx+464] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+464], r14 + adc r12, 0 + ; a[i+59] += m[59] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+472] + mov r14, QWORD PTR [rcx+472] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+472], r14 + adc r11, 0 + ; a[i+60] += m[60] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+480] + mov r14, QWORD PTR [rcx+480] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+480], r14 + adc r12, 0 + ; a[i+61] += m[61] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+488] + mov r14, QWORD PTR [rcx+488] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+488], r14 + adc r11, 0 + ; a[i+62] += m[62] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+496] + mov r14, QWORD PTR [rcx+496] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+496], r14 + adc r12, 0 + ; a[i+63] += m[63] * mu + mov rax, r13 + mul QWORD PTR [r9+504] + mov r14, QWORD PTR [rcx+504] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+504], r14 + adc QWORD PTR [rcx+512], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_4096_mont_loop_64 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + neg rsi +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 512 + call sp_4096_cond_sub_64 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_4096_mont_reduce_64 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_4096_cond_sub_avx2_64 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+128] + mov r11, QWORD PTR [rdx+128] + pext r12, r12, r9 + mov QWORD PTR [rcx+120], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+136] + mov r12, QWORD PTR [rdx+136] + pext r10, r10, r9 + mov QWORD PTR [rcx+128], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+144] + pext r11, r11, r9 + mov QWORD PTR [rcx+136], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+152] + mov r11, QWORD PTR [rdx+152] + pext r12, r12, r9 + mov QWORD PTR [rcx+144], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+160] + mov r12, QWORD PTR [rdx+160] + pext r10, r10, r9 + mov QWORD PTR [rcx+152], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+168] + mov r10, QWORD PTR [rdx+168] + pext r11, r11, r9 + mov QWORD PTR [rcx+160], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+176] + mov r11, QWORD PTR [rdx+176] + pext r12, r12, r9 + mov QWORD PTR [rcx+168], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+184] + mov r12, QWORD PTR [rdx+184] + pext r10, r10, r9 + mov QWORD PTR [rcx+176], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+192] + pext r11, r11, r9 + mov QWORD PTR [rcx+184], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+200] + mov r11, QWORD PTR [rdx+200] + pext r12, r12, r9 + mov QWORD PTR [rcx+192], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+208] + mov r12, QWORD PTR [rdx+208] + pext r10, r10, r9 + mov QWORD PTR [rcx+200], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+216] + mov r10, QWORD PTR [rdx+216] + pext r11, r11, r9 + mov QWORD PTR [rcx+208], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+224] + mov r11, QWORD PTR [rdx+224] + pext r12, r12, r9 + mov QWORD PTR [rcx+216], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+232] + mov r12, QWORD PTR [rdx+232] + pext r10, r10, r9 + mov QWORD PTR [rcx+224], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+240] + pext r11, r11, r9 + mov QWORD PTR [rcx+232], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+248] + mov r11, QWORD PTR [rdx+248] + pext r12, r12, r9 + mov QWORD PTR [rcx+240], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+256] + mov r12, QWORD PTR [rdx+256] + pext r10, r10, r9 + mov QWORD PTR [rcx+248], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+264] + mov r10, QWORD PTR [rdx+264] + pext r11, r11, r9 + mov QWORD PTR [rcx+256], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+272] + mov r11, QWORD PTR [rdx+272] + pext r12, r12, r9 + mov QWORD PTR [rcx+264], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+280] + mov r12, QWORD PTR [rdx+280] + pext r10, r10, r9 + mov QWORD PTR [rcx+272], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+288] + mov r10, QWORD PTR [rdx+288] + pext r11, r11, r9 + mov QWORD PTR [rcx+280], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+296] + mov r11, QWORD PTR [rdx+296] + pext r12, r12, r9 + mov QWORD PTR [rcx+288], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+304] + mov r12, QWORD PTR [rdx+304] + pext r10, r10, r9 + mov QWORD PTR [rcx+296], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+312] + mov r10, QWORD PTR [rdx+312] + pext r11, r11, r9 + mov QWORD PTR [rcx+304], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+320] + mov r11, QWORD PTR [rdx+320] + pext r12, r12, r9 + mov QWORD PTR [rcx+312], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+328] + mov r12, QWORD PTR [rdx+328] + pext r10, r10, r9 + mov QWORD PTR [rcx+320], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+336] + mov r10, QWORD PTR [rdx+336] + pext r11, r11, r9 + mov QWORD PTR [rcx+328], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+344] + mov r11, QWORD PTR [rdx+344] + pext r12, r12, r9 + mov QWORD PTR [rcx+336], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+352] + mov r12, QWORD PTR [rdx+352] + pext r10, r10, r9 + mov QWORD PTR [rcx+344], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+360] + mov r10, QWORD PTR [rdx+360] + pext r11, r11, r9 + mov QWORD PTR [rcx+352], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+368] + mov r11, QWORD PTR [rdx+368] + pext r12, r12, r9 + mov QWORD PTR [rcx+360], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+376] + mov r12, QWORD PTR [rdx+376] + pext r10, r10, r9 + mov QWORD PTR [rcx+368], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+384] + mov r10, QWORD PTR [rdx+384] + pext r11, r11, r9 + mov QWORD PTR [rcx+376], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+392] + mov r11, QWORD PTR [rdx+392] + pext r12, r12, r9 + mov QWORD PTR [rcx+384], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+400] + mov r12, QWORD PTR [rdx+400] + pext r10, r10, r9 + mov QWORD PTR [rcx+392], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+408] + mov r10, QWORD PTR [rdx+408] + pext r11, r11, r9 + mov QWORD PTR [rcx+400], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+416] + mov r11, QWORD PTR [rdx+416] + pext r12, r12, r9 + mov QWORD PTR [rcx+408], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+424] + mov r12, QWORD PTR [rdx+424] + pext r10, r10, r9 + mov QWORD PTR [rcx+416], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+432] + mov r10, QWORD PTR [rdx+432] + pext r11, r11, r9 + mov QWORD PTR [rcx+424], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+440] + mov r11, QWORD PTR [rdx+440] + pext r12, r12, r9 + mov QWORD PTR [rcx+432], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+448] + mov r12, QWORD PTR [rdx+448] + pext r10, r10, r9 + mov QWORD PTR [rcx+440], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+456] + mov r10, QWORD PTR [rdx+456] + pext r11, r11, r9 + mov QWORD PTR [rcx+448], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+464] + mov r11, QWORD PTR [rdx+464] + pext r12, r12, r9 + mov QWORD PTR [rcx+456], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+472] + mov r12, QWORD PTR [rdx+472] + pext r10, r10, r9 + mov QWORD PTR [rcx+464], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+480] + mov r10, QWORD PTR [rdx+480] + pext r11, r11, r9 + mov QWORD PTR [rcx+472], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+488] + mov r11, QWORD PTR [rdx+488] + pext r12, r12, r9 + mov QWORD PTR [rcx+480], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+496] + mov r12, QWORD PTR [rdx+496] + pext r10, r10, r9 + mov QWORD PTR [rcx+488], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+504] + mov r10, QWORD PTR [rdx+504] + pext r11, r11, r9 + mov QWORD PTR [rcx+496], r12 + sbb r10, r11 + mov QWORD PTR [rcx+504], r10 + sbb rax, 0 + pop r12 + ret +sp_4096_cond_sub_avx2_64 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_4096_mul_d_avx2_64 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; A[6] * B + mulx r10, r9, QWORD PTR [rax+48] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; A[7] * B + mulx r10, r9, QWORD PTR [rax+56] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; A[8] * B + mulx r10, r9, QWORD PTR [rax+64] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; A[9] * B + mulx r10, r9, QWORD PTR [rax+72] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + ; A[10] * B + mulx r10, r9, QWORD PTR [rax+80] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+80], r11 + ; A[11] * B + mulx r10, r9, QWORD PTR [rax+88] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+88], r12 + ; A[12] * B + mulx r10, r9, QWORD PTR [rax+96] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+96], r11 + ; A[13] * B + mulx r10, r9, QWORD PTR [rax+104] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+104], r12 + ; A[14] * B + mulx r10, r9, QWORD PTR [rax+112] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+112], r11 + ; A[15] * B + mulx r10, r9, QWORD PTR [rax+120] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+120], r12 + ; A[16] * B + mulx r10, r9, QWORD PTR [rax+128] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+128], r11 + ; A[17] * B + mulx r10, r9, QWORD PTR [rax+136] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+136], r12 + ; A[18] * B + mulx r10, r9, QWORD PTR [rax+144] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+144], r11 + ; A[19] * B + mulx r10, r9, QWORD PTR [rax+152] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+152], r12 + ; A[20] * B + mulx r10, r9, QWORD PTR [rax+160] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+160], r11 + ; A[21] * B + mulx r10, r9, QWORD PTR [rax+168] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+168], r12 + ; A[22] * B + mulx r10, r9, QWORD PTR [rax+176] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+176], r11 + ; A[23] * B + mulx r10, r9, QWORD PTR [rax+184] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+184], r12 + ; A[24] * B + mulx r10, r9, QWORD PTR [rax+192] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+192], r11 + ; A[25] * B + mulx r10, r9, QWORD PTR [rax+200] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+200], r12 + ; A[26] * B + mulx r10, r9, QWORD PTR [rax+208] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+208], r11 + ; A[27] * B + mulx r10, r9, QWORD PTR [rax+216] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+216], r12 + ; A[28] * B + mulx r10, r9, QWORD PTR [rax+224] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+224], r11 + ; A[29] * B + mulx r10, r9, QWORD PTR [rax+232] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+232], r12 + ; A[30] * B + mulx r10, r9, QWORD PTR [rax+240] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+240], r11 + ; A[31] * B + mulx r10, r9, QWORD PTR [rax+248] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+248], r12 + ; A[32] * B + mulx r10, r9, QWORD PTR [rax+256] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+256], r11 + ; A[33] * B + mulx r10, r9, QWORD PTR [rax+264] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+264], r12 + ; A[34] * B + mulx r10, r9, QWORD PTR [rax+272] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+272], r11 + ; A[35] * B + mulx r10, r9, QWORD PTR [rax+280] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+280], r12 + ; A[36] * B + mulx r10, r9, QWORD PTR [rax+288] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+288], r11 + ; A[37] * B + mulx r10, r9, QWORD PTR [rax+296] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+296], r12 + ; A[38] * B + mulx r10, r9, QWORD PTR [rax+304] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+304], r11 + ; A[39] * B + mulx r10, r9, QWORD PTR [rax+312] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+312], r12 + ; A[40] * B + mulx r10, r9, QWORD PTR [rax+320] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+320], r11 + ; A[41] * B + mulx r10, r9, QWORD PTR [rax+328] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+328], r12 + ; A[42] * B + mulx r10, r9, QWORD PTR [rax+336] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+336], r11 + ; A[43] * B + mulx r10, r9, QWORD PTR [rax+344] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+344], r12 + ; A[44] * B + mulx r10, r9, QWORD PTR [rax+352] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+352], r11 + ; A[45] * B + mulx r10, r9, QWORD PTR [rax+360] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+360], r12 + ; A[46] * B + mulx r10, r9, QWORD PTR [rax+368] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+368], r11 + ; A[47] * B + mulx r10, r9, QWORD PTR [rax+376] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+376], r12 + ; A[48] * B + mulx r10, r9, QWORD PTR [rax+384] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+384], r11 + ; A[49] * B + mulx r10, r9, QWORD PTR [rax+392] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+392], r12 + ; A[50] * B + mulx r10, r9, QWORD PTR [rax+400] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+400], r11 + ; A[51] * B + mulx r10, r9, QWORD PTR [rax+408] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+408], r12 + ; A[52] * B + mulx r10, r9, QWORD PTR [rax+416] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+416], r11 + ; A[53] * B + mulx r10, r9, QWORD PTR [rax+424] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+424], r12 + ; A[54] * B + mulx r10, r9, QWORD PTR [rax+432] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+432], r11 + ; A[55] * B + mulx r10, r9, QWORD PTR [rax+440] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+440], r12 + ; A[56] * B + mulx r10, r9, QWORD PTR [rax+448] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+448], r11 + ; A[57] * B + mulx r10, r9, QWORD PTR [rax+456] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+456], r12 + ; A[58] * B + mulx r10, r9, QWORD PTR [rax+464] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+464], r11 + ; A[59] * B + mulx r10, r9, QWORD PTR [rax+472] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+472], r12 + ; A[60] * B + mulx r10, r9, QWORD PTR [rax+480] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+480], r11 + ; A[61] * B + mulx r10, r9, QWORD PTR [rax+488] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+488], r12 + ; A[62] * B + mulx r10, r9, QWORD PTR [rax+496] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+496], r11 + ; A[63] * B + mulx r10, r9, QWORD PTR [rax+504] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+504], r12 + mov QWORD PTR [rcx+512], r11 + pop r13 + pop r12 + ret +sp_4096_mul_d_avx2_64 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_4096_word_asm_64 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_4096_word_asm_64 ENDP +_text ENDS +ENDIF +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_4096_cmp_64 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+504] + mov r12, QWORD PTR [rdx+504] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+496] + mov r12, QWORD PTR [rdx+496] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+488] + mov r12, QWORD PTR [rdx+488] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+480] + mov r12, QWORD PTR [rdx+480] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+472] + mov r12, QWORD PTR [rdx+472] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+464] + mov r12, QWORD PTR [rdx+464] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+456] + mov r12, QWORD PTR [rdx+456] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+448] + mov r12, QWORD PTR [rdx+448] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+440] + mov r12, QWORD PTR [rdx+440] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+432] + mov r12, QWORD PTR [rdx+432] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+424] + mov r12, QWORD PTR [rdx+424] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+416] + mov r12, QWORD PTR [rdx+416] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+408] + mov r12, QWORD PTR [rdx+408] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+400] + mov r12, QWORD PTR [rdx+400] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+392] + mov r12, QWORD PTR [rdx+392] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+384] + mov r12, QWORD PTR [rdx+384] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+376] + mov r12, QWORD PTR [rdx+376] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+368] + mov r12, QWORD PTR [rdx+368] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+360] + mov r12, QWORD PTR [rdx+360] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+352] + mov r12, QWORD PTR [rdx+352] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+344] + mov r12, QWORD PTR [rdx+344] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+336] + mov r12, QWORD PTR [rdx+336] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+328] + mov r12, QWORD PTR [rdx+328] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+320] + mov r12, QWORD PTR [rdx+320] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+312] + mov r12, QWORD PTR [rdx+312] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+304] + mov r12, QWORD PTR [rdx+304] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+296] + mov r12, QWORD PTR [rdx+296] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+288] + mov r12, QWORD PTR [rdx+288] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+280] + mov r12, QWORD PTR [rdx+280] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+272] + mov r12, QWORD PTR [rdx+272] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+264] + mov r12, QWORD PTR [rdx+264] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+256] + mov r12, QWORD PTR [rdx+256] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+248] + mov r12, QWORD PTR [rdx+248] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+240] + mov r12, QWORD PTR [rdx+240] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+232] + mov r12, QWORD PTR [rdx+232] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+224] + mov r12, QWORD PTR [rdx+224] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+216] + mov r12, QWORD PTR [rdx+216] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+208] + mov r12, QWORD PTR [rdx+208] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+200] + mov r12, QWORD PTR [rdx+200] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+192] + mov r12, QWORD PTR [rdx+192] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+184] + mov r12, QWORD PTR [rdx+184] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+176] + mov r12, QWORD PTR [rdx+176] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+168] + mov r12, QWORD PTR [rdx+168] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+160] + mov r12, QWORD PTR [rdx+160] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+152] + mov r12, QWORD PTR [rdx+152] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+144] + mov r12, QWORD PTR [rdx+144] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+136] + mov r12, QWORD PTR [rdx+136] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+128] + mov r12, QWORD PTR [rdx+128] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+120] + mov r12, QWORD PTR [rdx+120] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+112] + mov r12, QWORD PTR [rdx+112] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+104] + mov r12, QWORD PTR [rdx+104] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+96] + mov r12, QWORD PTR [rdx+96] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+88] + mov r12, QWORD PTR [rdx+88] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+80] + mov r12, QWORD PTR [rdx+80] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+72] + mov r12, QWORD PTR [rdx+72] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+64] + mov r12, QWORD PTR [rdx+64] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+56] + mov r12, QWORD PTR [rdx+56] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+48] + mov r12, QWORD PTR [rdx+48] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_4096_cmp_64 ENDP +_text ENDS +; /* Sub b from a into r. (r = a - b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_4096_sub_64 PROC + mov r9, QWORD PTR [rdx] + xor rax, rax + sub r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + sbb r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + sbb r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + sbb r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + sbb r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + sbb r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + sbb r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + sbb r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + sbb r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + sbb r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + sbb r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + sbb r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + sbb r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + sbb r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + sbb r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + sbb r10, QWORD PTR [r8+120] + mov r9, QWORD PTR [rdx+128] + mov QWORD PTR [rcx+120], r10 + sbb r9, QWORD PTR [r8+128] + mov r10, QWORD PTR [rdx+136] + mov QWORD PTR [rcx+128], r9 + sbb r10, QWORD PTR [r8+136] + mov r9, QWORD PTR [rdx+144] + mov QWORD PTR [rcx+136], r10 + sbb r9, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+152] + mov QWORD PTR [rcx+144], r9 + sbb r10, QWORD PTR [r8+152] + mov r9, QWORD PTR [rdx+160] + mov QWORD PTR [rcx+152], r10 + sbb r9, QWORD PTR [r8+160] + mov r10, QWORD PTR [rdx+168] + mov QWORD PTR [rcx+160], r9 + sbb r10, QWORD PTR [r8+168] + mov r9, QWORD PTR [rdx+176] + mov QWORD PTR [rcx+168], r10 + sbb r9, QWORD PTR [r8+176] + mov r10, QWORD PTR [rdx+184] + mov QWORD PTR [rcx+176], r9 + sbb r10, QWORD PTR [r8+184] + mov r9, QWORD PTR [rdx+192] + mov QWORD PTR [rcx+184], r10 + sbb r9, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+200] + mov QWORD PTR [rcx+192], r9 + sbb r10, QWORD PTR [r8+200] + mov r9, QWORD PTR [rdx+208] + mov QWORD PTR [rcx+200], r10 + sbb r9, QWORD PTR [r8+208] + mov r10, QWORD PTR [rdx+216] + mov QWORD PTR [rcx+208], r9 + sbb r10, QWORD PTR [r8+216] + mov r9, QWORD PTR [rdx+224] + mov QWORD PTR [rcx+216], r10 + sbb r9, QWORD PTR [r8+224] + mov r10, QWORD PTR [rdx+232] + mov QWORD PTR [rcx+224], r9 + sbb r10, QWORD PTR [r8+232] + mov r9, QWORD PTR [rdx+240] + mov QWORD PTR [rcx+232], r10 + sbb r9, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+248] + mov QWORD PTR [rcx+240], r9 + sbb r10, QWORD PTR [r8+248] + mov r9, QWORD PTR [rdx+256] + mov QWORD PTR [rcx+248], r10 + sbb r9, QWORD PTR [r8+256] + mov r10, QWORD PTR [rdx+264] + mov QWORD PTR [rcx+256], r9 + sbb r10, QWORD PTR [r8+264] + mov r9, QWORD PTR [rdx+272] + mov QWORD PTR [rcx+264], r10 + sbb r9, QWORD PTR [r8+272] + mov r10, QWORD PTR [rdx+280] + mov QWORD PTR [rcx+272], r9 + sbb r10, QWORD PTR [r8+280] + mov r9, QWORD PTR [rdx+288] + mov QWORD PTR [rcx+280], r10 + sbb r9, QWORD PTR [r8+288] + mov r10, QWORD PTR [rdx+296] + mov QWORD PTR [rcx+288], r9 + sbb r10, QWORD PTR [r8+296] + mov r9, QWORD PTR [rdx+304] + mov QWORD PTR [rcx+296], r10 + sbb r9, QWORD PTR [r8+304] + mov r10, QWORD PTR [rdx+312] + mov QWORD PTR [rcx+304], r9 + sbb r10, QWORD PTR [r8+312] + mov r9, QWORD PTR [rdx+320] + mov QWORD PTR [rcx+312], r10 + sbb r9, QWORD PTR [r8+320] + mov r10, QWORD PTR [rdx+328] + mov QWORD PTR [rcx+320], r9 + sbb r10, QWORD PTR [r8+328] + mov r9, QWORD PTR [rdx+336] + mov QWORD PTR [rcx+328], r10 + sbb r9, QWORD PTR [r8+336] + mov r10, QWORD PTR [rdx+344] + mov QWORD PTR [rcx+336], r9 + sbb r10, QWORD PTR [r8+344] + mov r9, QWORD PTR [rdx+352] + mov QWORD PTR [rcx+344], r10 + sbb r9, QWORD PTR [r8+352] + mov r10, QWORD PTR [rdx+360] + mov QWORD PTR [rcx+352], r9 + sbb r10, QWORD PTR [r8+360] + mov r9, QWORD PTR [rdx+368] + mov QWORD PTR [rcx+360], r10 + sbb r9, QWORD PTR [r8+368] + mov r10, QWORD PTR [rdx+376] + mov QWORD PTR [rcx+368], r9 + sbb r10, QWORD PTR [r8+376] + mov r9, QWORD PTR [rdx+384] + mov QWORD PTR [rcx+376], r10 + sbb r9, QWORD PTR [r8+384] + mov r10, QWORD PTR [rdx+392] + mov QWORD PTR [rcx+384], r9 + sbb r10, QWORD PTR [r8+392] + mov r9, QWORD PTR [rdx+400] + mov QWORD PTR [rcx+392], r10 + sbb r9, QWORD PTR [r8+400] + mov r10, QWORD PTR [rdx+408] + mov QWORD PTR [rcx+400], r9 + sbb r10, QWORD PTR [r8+408] + mov r9, QWORD PTR [rdx+416] + mov QWORD PTR [rcx+408], r10 + sbb r9, QWORD PTR [r8+416] + mov r10, QWORD PTR [rdx+424] + mov QWORD PTR [rcx+416], r9 + sbb r10, QWORD PTR [r8+424] + mov r9, QWORD PTR [rdx+432] + mov QWORD PTR [rcx+424], r10 + sbb r9, QWORD PTR [r8+432] + mov r10, QWORD PTR [rdx+440] + mov QWORD PTR [rcx+432], r9 + sbb r10, QWORD PTR [r8+440] + mov r9, QWORD PTR [rdx+448] + mov QWORD PTR [rcx+440], r10 + sbb r9, QWORD PTR [r8+448] + mov r10, QWORD PTR [rdx+456] + mov QWORD PTR [rcx+448], r9 + sbb r10, QWORD PTR [r8+456] + mov r9, QWORD PTR [rdx+464] + mov QWORD PTR [rcx+456], r10 + sbb r9, QWORD PTR [r8+464] + mov r10, QWORD PTR [rdx+472] + mov QWORD PTR [rcx+464], r9 + sbb r10, QWORD PTR [r8+472] + mov r9, QWORD PTR [rdx+480] + mov QWORD PTR [rcx+472], r10 + sbb r9, QWORD PTR [r8+480] + mov r10, QWORD PTR [rdx+488] + mov QWORD PTR [rcx+480], r9 + sbb r10, QWORD PTR [r8+488] + mov r9, QWORD PTR [rdx+496] + mov QWORD PTR [rcx+488], r10 + sbb r9, QWORD PTR [r8+496] + mov r10, QWORD PTR [rdx+504] + mov QWORD PTR [rcx+496], r9 + sbb r10, QWORD PTR [r8+504] + mov QWORD PTR [rcx+504], r10 + sbb rax, 0 + ret +sp_4096_sub_64 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 4096 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_4096_mont_reduce_avx2_64 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r9, rcx + mov r10, rdx + xor rbp, rbp + ; i = 64 + mov r11, 64 + mov r15, QWORD PTR [r9] + mov rdi, QWORD PTR [r9+8] + mov rsi, QWORD PTR [r9+16] + mov rbx, QWORD PTR [r9+24] + add r9, 256 + xor rbp, rbp +L_4096_mont_loop_avx2_64: + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-224] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-216] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-208] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-216], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9+-200] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-208], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9+-192] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-200], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+-184] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-192], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+-176] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-184], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+-168] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-176], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+-160] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-168], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+-152] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-160], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+-144] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-152], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+-136] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-144], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+-128] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-136], r13 + ; a[i+16] += m[16] * mu + mulx rcx, rax, QWORD PTR [r10+128] + mov r13, QWORD PTR [r9+-120] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-128], r12 + ; a[i+17] += m[17] * mu + mulx rcx, rax, QWORD PTR [r10+136] + mov r12, QWORD PTR [r9+-112] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-120], r13 + ; a[i+18] += m[18] * mu + mulx rcx, rax, QWORD PTR [r10+144] + mov r13, QWORD PTR [r9+-104] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-112], r12 + ; a[i+19] += m[19] * mu + mulx rcx, rax, QWORD PTR [r10+152] + mov r12, QWORD PTR [r9+-96] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-104], r13 + ; a[i+20] += m[20] * mu + mulx rcx, rax, QWORD PTR [r10+160] + mov r13, QWORD PTR [r9+-88] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-96], r12 + ; a[i+21] += m[21] * mu + mulx rcx, rax, QWORD PTR [r10+168] + mov r12, QWORD PTR [r9+-80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-88], r13 + ; a[i+22] += m[22] * mu + mulx rcx, rax, QWORD PTR [r10+176] + mov r13, QWORD PTR [r9+-72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-80], r12 + ; a[i+23] += m[23] * mu + mulx rcx, rax, QWORD PTR [r10+184] + mov r12, QWORD PTR [r9+-64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-72], r13 + ; a[i+24] += m[24] * mu + mulx rcx, rax, QWORD PTR [r10+192] + mov r13, QWORD PTR [r9+-56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-64], r12 + ; a[i+25] += m[25] * mu + mulx rcx, rax, QWORD PTR [r10+200] + mov r12, QWORD PTR [r9+-48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-56], r13 + ; a[i+26] += m[26] * mu + mulx rcx, rax, QWORD PTR [r10+208] + mov r13, QWORD PTR [r9+-40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-48], r12 + ; a[i+27] += m[27] * mu + mulx rcx, rax, QWORD PTR [r10+216] + mov r12, QWORD PTR [r9+-32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-40], r13 + ; a[i+28] += m[28] * mu + mulx rcx, rax, QWORD PTR [r10+224] + mov r13, QWORD PTR [r9+-24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-32], r12 + ; a[i+29] += m[29] * mu + mulx rcx, rax, QWORD PTR [r10+232] + mov r12, QWORD PTR [r9+-16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-24], r13 + ; a[i+30] += m[30] * mu + mulx rcx, rax, QWORD PTR [r10+240] + mov r13, QWORD PTR [r9+-8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-16], r12 + ; a[i+31] += m[31] * mu + mulx rcx, rax, QWORD PTR [r10+248] + mov r12, QWORD PTR [r9] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-8], r13 + ; a[i+32] += m[32] * mu + mulx rcx, rax, QWORD PTR [r10+256] + mov r13, QWORD PTR [r9+8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9], r12 + ; a[i+33] += m[33] * mu + mulx rcx, rax, QWORD PTR [r10+264] + mov r12, QWORD PTR [r9+16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+8], r13 + ; a[i+34] += m[34] * mu + mulx rcx, rax, QWORD PTR [r10+272] + mov r13, QWORD PTR [r9+24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+16], r12 + ; a[i+35] += m[35] * mu + mulx rcx, rax, QWORD PTR [r10+280] + mov r12, QWORD PTR [r9+32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+24], r13 + ; a[i+36] += m[36] * mu + mulx rcx, rax, QWORD PTR [r10+288] + mov r13, QWORD PTR [r9+40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+32], r12 + ; a[i+37] += m[37] * mu + mulx rcx, rax, QWORD PTR [r10+296] + mov r12, QWORD PTR [r9+48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+40], r13 + ; a[i+38] += m[38] * mu + mulx rcx, rax, QWORD PTR [r10+304] + mov r13, QWORD PTR [r9+56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+48], r12 + ; a[i+39] += m[39] * mu + mulx rcx, rax, QWORD PTR [r10+312] + mov r12, QWORD PTR [r9+64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+56], r13 + ; a[i+40] += m[40] * mu + mulx rcx, rax, QWORD PTR [r10+320] + mov r13, QWORD PTR [r9+72] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+64], r12 + ; a[i+41] += m[41] * mu + mulx rcx, rax, QWORD PTR [r10+328] + mov r12, QWORD PTR [r9+80] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+72], r13 + ; a[i+42] += m[42] * mu + mulx rcx, rax, QWORD PTR [r10+336] + mov r13, QWORD PTR [r9+88] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+80], r12 + ; a[i+43] += m[43] * mu + mulx rcx, rax, QWORD PTR [r10+344] + mov r12, QWORD PTR [r9+96] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+88], r13 + ; a[i+44] += m[44] * mu + mulx rcx, rax, QWORD PTR [r10+352] + mov r13, QWORD PTR [r9+104] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+96], r12 + ; a[i+45] += m[45] * mu + mulx rcx, rax, QWORD PTR [r10+360] + mov r12, QWORD PTR [r9+112] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+104], r13 + ; a[i+46] += m[46] * mu + mulx rcx, rax, QWORD PTR [r10+368] + mov r13, QWORD PTR [r9+120] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+112], r12 + ; a[i+47] += m[47] * mu + mulx rcx, rax, QWORD PTR [r10+376] + mov r12, QWORD PTR [r9+128] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+120], r13 + ; a[i+48] += m[48] * mu + mulx rcx, rax, QWORD PTR [r10+384] + mov r13, QWORD PTR [r9+136] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+128], r12 + ; a[i+49] += m[49] * mu + mulx rcx, rax, QWORD PTR [r10+392] + mov r12, QWORD PTR [r9+144] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+136], r13 + ; a[i+50] += m[50] * mu + mulx rcx, rax, QWORD PTR [r10+400] + mov r13, QWORD PTR [r9+152] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+144], r12 + ; a[i+51] += m[51] * mu + mulx rcx, rax, QWORD PTR [r10+408] + mov r12, QWORD PTR [r9+160] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+152], r13 + ; a[i+52] += m[52] * mu + mulx rcx, rax, QWORD PTR [r10+416] + mov r13, QWORD PTR [r9+168] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+160], r12 + ; a[i+53] += m[53] * mu + mulx rcx, rax, QWORD PTR [r10+424] + mov r12, QWORD PTR [r9+176] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+168], r13 + ; a[i+54] += m[54] * mu + mulx rcx, rax, QWORD PTR [r10+432] + mov r13, QWORD PTR [r9+184] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+176], r12 + ; a[i+55] += m[55] * mu + mulx rcx, rax, QWORD PTR [r10+440] + mov r12, QWORD PTR [r9+192] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+184], r13 + ; a[i+56] += m[56] * mu + mulx rcx, rax, QWORD PTR [r10+448] + mov r13, QWORD PTR [r9+200] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+192], r12 + ; a[i+57] += m[57] * mu + mulx rcx, rax, QWORD PTR [r10+456] + mov r12, QWORD PTR [r9+208] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+200], r13 + ; a[i+58] += m[58] * mu + mulx rcx, rax, QWORD PTR [r10+464] + mov r13, QWORD PTR [r9+216] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+208], r12 + ; a[i+59] += m[59] * mu + mulx rcx, rax, QWORD PTR [r10+472] + mov r12, QWORD PTR [r9+224] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+216], r13 + ; a[i+60] += m[60] * mu + mulx rcx, rax, QWORD PTR [r10+480] + mov r13, QWORD PTR [r9+232] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+224], r12 + ; a[i+61] += m[61] * mu + mulx rcx, rax, QWORD PTR [r10+488] + mov r12, QWORD PTR [r9+240] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+232], r13 + ; a[i+62] += m[62] * mu + mulx rcx, rax, QWORD PTR [r10+496] + mov r13, QWORD PTR [r9+248] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+240], r12 + ; a[i+63] += m[63] * mu + mulx rcx, rax, QWORD PTR [r10+504] + mov r12, QWORD PTR [r9+256] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+248], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+256], r12 + adox rbp, r14 + adcx rbp, r14 + ; a += 1 + add r9, 8 + ; i -= 1 + sub r11, 1 + jnz L_4096_mont_loop_avx2_64 + sub r9, 256 + neg rbp + mov r8, r9 + sub r9, 512 + mov rcx, QWORD PTR [r10] + mov rdx, r15 + pext rcx, rcx, rbp + sub rdx, rcx + mov rcx, QWORD PTR [r10+8] + mov rax, rdi + pext rcx, rcx, rbp + mov QWORD PTR [r9], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+16] + mov rcx, rsi + pext rdx, rdx, rbp + mov QWORD PTR [r9+8], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+24] + mov rdx, rbx + pext rax, rax, rbp + mov QWORD PTR [r9+16], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+32] + mov rax, QWORD PTR [r8+32] + pext rcx, rcx, rbp + mov QWORD PTR [r9+24], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+40] + mov rcx, QWORD PTR [r8+40] + pext rdx, rdx, rbp + mov QWORD PTR [r9+32], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+48] + mov rdx, QWORD PTR [r8+48] + pext rax, rax, rbp + mov QWORD PTR [r9+40], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+56] + mov rax, QWORD PTR [r8+56] + pext rcx, rcx, rbp + mov QWORD PTR [r9+48], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+64] + mov rcx, QWORD PTR [r8+64] + pext rdx, rdx, rbp + mov QWORD PTR [r9+56], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+72] + mov rdx, QWORD PTR [r8+72] + pext rax, rax, rbp + mov QWORD PTR [r9+64], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+80] + mov rax, QWORD PTR [r8+80] + pext rcx, rcx, rbp + mov QWORD PTR [r9+72], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+88] + mov rcx, QWORD PTR [r8+88] + pext rdx, rdx, rbp + mov QWORD PTR [r9+80], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+96] + mov rdx, QWORD PTR [r8+96] + pext rax, rax, rbp + mov QWORD PTR [r9+88], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+104] + mov rax, QWORD PTR [r8+104] + pext rcx, rcx, rbp + mov QWORD PTR [r9+96], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+112] + mov rcx, QWORD PTR [r8+112] + pext rdx, rdx, rbp + mov QWORD PTR [r9+104], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+120] + mov rdx, QWORD PTR [r8+120] + pext rax, rax, rbp + mov QWORD PTR [r9+112], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+128] + mov rax, QWORD PTR [r8+128] + pext rcx, rcx, rbp + mov QWORD PTR [r9+120], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+136] + mov rcx, QWORD PTR [r8+136] + pext rdx, rdx, rbp + mov QWORD PTR [r9+128], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+144] + mov rdx, QWORD PTR [r8+144] + pext rax, rax, rbp + mov QWORD PTR [r9+136], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+152] + mov rax, QWORD PTR [r8+152] + pext rcx, rcx, rbp + mov QWORD PTR [r9+144], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+160] + mov rcx, QWORD PTR [r8+160] + pext rdx, rdx, rbp + mov QWORD PTR [r9+152], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+168] + mov rdx, QWORD PTR [r8+168] + pext rax, rax, rbp + mov QWORD PTR [r9+160], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+176] + mov rax, QWORD PTR [r8+176] + pext rcx, rcx, rbp + mov QWORD PTR [r9+168], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+184] + mov rcx, QWORD PTR [r8+184] + pext rdx, rdx, rbp + mov QWORD PTR [r9+176], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+192] + mov rdx, QWORD PTR [r8+192] + pext rax, rax, rbp + mov QWORD PTR [r9+184], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+200] + mov rax, QWORD PTR [r8+200] + pext rcx, rcx, rbp + mov QWORD PTR [r9+192], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+208] + mov rcx, QWORD PTR [r8+208] + pext rdx, rdx, rbp + mov QWORD PTR [r9+200], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+216] + mov rdx, QWORD PTR [r8+216] + pext rax, rax, rbp + mov QWORD PTR [r9+208], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+224] + mov rax, QWORD PTR [r8+224] + pext rcx, rcx, rbp + mov QWORD PTR [r9+216], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+232] + mov rcx, QWORD PTR [r8+232] + pext rdx, rdx, rbp + mov QWORD PTR [r9+224], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+240] + mov rdx, QWORD PTR [r8+240] + pext rax, rax, rbp + mov QWORD PTR [r9+232], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+248] + mov rax, QWORD PTR [r8+248] + pext rcx, rcx, rbp + mov QWORD PTR [r9+240], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+256] + mov rcx, QWORD PTR [r8+256] + pext rdx, rdx, rbp + mov QWORD PTR [r9+248], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+264] + mov rdx, QWORD PTR [r8+264] + pext rax, rax, rbp + mov QWORD PTR [r9+256], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+272] + mov rax, QWORD PTR [r8+272] + pext rcx, rcx, rbp + mov QWORD PTR [r9+264], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+280] + mov rcx, QWORD PTR [r8+280] + pext rdx, rdx, rbp + mov QWORD PTR [r9+272], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+288] + mov rdx, QWORD PTR [r8+288] + pext rax, rax, rbp + mov QWORD PTR [r9+280], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+296] + mov rax, QWORD PTR [r8+296] + pext rcx, rcx, rbp + mov QWORD PTR [r9+288], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+304] + mov rcx, QWORD PTR [r8+304] + pext rdx, rdx, rbp + mov QWORD PTR [r9+296], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+312] + mov rdx, QWORD PTR [r8+312] + pext rax, rax, rbp + mov QWORD PTR [r9+304], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+320] + mov rax, QWORD PTR [r8+320] + pext rcx, rcx, rbp + mov QWORD PTR [r9+312], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+328] + mov rcx, QWORD PTR [r8+328] + pext rdx, rdx, rbp + mov QWORD PTR [r9+320], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+336] + mov rdx, QWORD PTR [r8+336] + pext rax, rax, rbp + mov QWORD PTR [r9+328], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+344] + mov rax, QWORD PTR [r8+344] + pext rcx, rcx, rbp + mov QWORD PTR [r9+336], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+352] + mov rcx, QWORD PTR [r8+352] + pext rdx, rdx, rbp + mov QWORD PTR [r9+344], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+360] + mov rdx, QWORD PTR [r8+360] + pext rax, rax, rbp + mov QWORD PTR [r9+352], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+368] + mov rax, QWORD PTR [r8+368] + pext rcx, rcx, rbp + mov QWORD PTR [r9+360], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+376] + mov rcx, QWORD PTR [r8+376] + pext rdx, rdx, rbp + mov QWORD PTR [r9+368], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+384] + mov rdx, QWORD PTR [r8+384] + pext rax, rax, rbp + mov QWORD PTR [r9+376], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+392] + mov rax, QWORD PTR [r8+392] + pext rcx, rcx, rbp + mov QWORD PTR [r9+384], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+400] + mov rcx, QWORD PTR [r8+400] + pext rdx, rdx, rbp + mov QWORD PTR [r9+392], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+408] + mov rdx, QWORD PTR [r8+408] + pext rax, rax, rbp + mov QWORD PTR [r9+400], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+416] + mov rax, QWORD PTR [r8+416] + pext rcx, rcx, rbp + mov QWORD PTR [r9+408], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+424] + mov rcx, QWORD PTR [r8+424] + pext rdx, rdx, rbp + mov QWORD PTR [r9+416], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+432] + mov rdx, QWORD PTR [r8+432] + pext rax, rax, rbp + mov QWORD PTR [r9+424], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+440] + mov rax, QWORD PTR [r8+440] + pext rcx, rcx, rbp + mov QWORD PTR [r9+432], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+448] + mov rcx, QWORD PTR [r8+448] + pext rdx, rdx, rbp + mov QWORD PTR [r9+440], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+456] + mov rdx, QWORD PTR [r8+456] + pext rax, rax, rbp + mov QWORD PTR [r9+448], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+464] + mov rax, QWORD PTR [r8+464] + pext rcx, rcx, rbp + mov QWORD PTR [r9+456], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+472] + mov rcx, QWORD PTR [r8+472] + pext rdx, rdx, rbp + mov QWORD PTR [r9+464], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+480] + mov rdx, QWORD PTR [r8+480] + pext rax, rax, rbp + mov QWORD PTR [r9+472], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+488] + mov rax, QWORD PTR [r8+488] + pext rcx, rcx, rbp + mov QWORD PTR [r9+480], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+496] + mov rcx, QWORD PTR [r8+496] + pext rdx, rdx, rbp + mov QWORD PTR [r9+488], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+504] + mov rdx, QWORD PTR [r8+504] + pext rax, rax, rbp + mov QWORD PTR [r9+496], rcx + sbb rdx, rax + mov QWORD PTR [r9+504], rdx + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_4096_mont_reduce_avx2_64 ENDP +_text ENDS +ENDIF +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_4096_cond_add_32 PROC + sub rsp, 256 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [r8+128] + mov r11, QWORD PTR [r8+136] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+128], r10 + mov QWORD PTR [rsp+136], r11 + mov r10, QWORD PTR [r8+144] + mov r11, QWORD PTR [r8+152] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+144], r10 + mov QWORD PTR [rsp+152], r11 + mov r10, QWORD PTR [r8+160] + mov r11, QWORD PTR [r8+168] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+160], r10 + mov QWORD PTR [rsp+168], r11 + mov r10, QWORD PTR [r8+176] + mov r11, QWORD PTR [r8+184] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+176], r10 + mov QWORD PTR [rsp+184], r11 + mov r10, QWORD PTR [r8+192] + mov r11, QWORD PTR [r8+200] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+192], r10 + mov QWORD PTR [rsp+200], r11 + mov r10, QWORD PTR [r8+208] + mov r11, QWORD PTR [r8+216] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+208], r10 + mov QWORD PTR [rsp+216], r11 + mov r10, QWORD PTR [r8+224] + mov r11, QWORD PTR [r8+232] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+224], r10 + mov QWORD PTR [rsp+232], r11 + mov r10, QWORD PTR [r8+240] + mov r11, QWORD PTR [r8+248] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+240], r10 + mov QWORD PTR [rsp+248], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + add r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + adc r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + adc r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + adc r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + adc r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + adc r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + adc r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + adc r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + adc r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + adc r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + adc r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + adc r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + adc r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + adc r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + adc r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + adc r11, r8 + mov QWORD PTR [rcx+112], r10 + mov r10, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rsp+128] + adc r10, r8 + mov QWORD PTR [rcx+120], r11 + mov r11, QWORD PTR [rdx+136] + mov r8, QWORD PTR [rsp+136] + adc r11, r8 + mov QWORD PTR [rcx+128], r10 + mov r10, QWORD PTR [rdx+144] + mov r8, QWORD PTR [rsp+144] + adc r10, r8 + mov QWORD PTR [rcx+136], r11 + mov r11, QWORD PTR [rdx+152] + mov r8, QWORD PTR [rsp+152] + adc r11, r8 + mov QWORD PTR [rcx+144], r10 + mov r10, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rsp+160] + adc r10, r8 + mov QWORD PTR [rcx+152], r11 + mov r11, QWORD PTR [rdx+168] + mov r8, QWORD PTR [rsp+168] + adc r11, r8 + mov QWORD PTR [rcx+160], r10 + mov r10, QWORD PTR [rdx+176] + mov r8, QWORD PTR [rsp+176] + adc r10, r8 + mov QWORD PTR [rcx+168], r11 + mov r11, QWORD PTR [rdx+184] + mov r8, QWORD PTR [rsp+184] + adc r11, r8 + mov QWORD PTR [rcx+176], r10 + mov r10, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rsp+192] + adc r10, r8 + mov QWORD PTR [rcx+184], r11 + mov r11, QWORD PTR [rdx+200] + mov r8, QWORD PTR [rsp+200] + adc r11, r8 + mov QWORD PTR [rcx+192], r10 + mov r10, QWORD PTR [rdx+208] + mov r8, QWORD PTR [rsp+208] + adc r10, r8 + mov QWORD PTR [rcx+200], r11 + mov r11, QWORD PTR [rdx+216] + mov r8, QWORD PTR [rsp+216] + adc r11, r8 + mov QWORD PTR [rcx+208], r10 + mov r10, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rsp+224] + adc r10, r8 + mov QWORD PTR [rcx+216], r11 + mov r11, QWORD PTR [rdx+232] + mov r8, QWORD PTR [rsp+232] + adc r11, r8 + mov QWORD PTR [rcx+224], r10 + mov r10, QWORD PTR [rdx+240] + mov r8, QWORD PTR [rsp+240] + adc r10, r8 + mov QWORD PTR [rcx+232], r11 + mov r11, QWORD PTR [rdx+248] + mov r8, QWORD PTR [rsp+248] + adc r11, r8 + mov QWORD PTR [rcx+240], r10 + mov QWORD PTR [rcx+248], r11 + adc rax, 0 + add rsp, 256 + ret +sp_4096_cond_add_32 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_4096_cond_add_avx2_32 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + add r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+128] + mov r11, QWORD PTR [rdx+128] + pext r12, r12, r9 + mov QWORD PTR [rcx+120], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+136] + mov r12, QWORD PTR [rdx+136] + pext r10, r10, r9 + mov QWORD PTR [rcx+128], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+144] + mov r10, QWORD PTR [rdx+144] + pext r11, r11, r9 + mov QWORD PTR [rcx+136], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+152] + mov r11, QWORD PTR [rdx+152] + pext r12, r12, r9 + mov QWORD PTR [rcx+144], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+160] + mov r12, QWORD PTR [rdx+160] + pext r10, r10, r9 + mov QWORD PTR [rcx+152], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+168] + mov r10, QWORD PTR [rdx+168] + pext r11, r11, r9 + mov QWORD PTR [rcx+160], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+176] + mov r11, QWORD PTR [rdx+176] + pext r12, r12, r9 + mov QWORD PTR [rcx+168], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+184] + mov r12, QWORD PTR [rdx+184] + pext r10, r10, r9 + mov QWORD PTR [rcx+176], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+192] + mov r10, QWORD PTR [rdx+192] + pext r11, r11, r9 + mov QWORD PTR [rcx+184], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+200] + mov r11, QWORD PTR [rdx+200] + pext r12, r12, r9 + mov QWORD PTR [rcx+192], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+208] + mov r12, QWORD PTR [rdx+208] + pext r10, r10, r9 + mov QWORD PTR [rcx+200], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+216] + mov r10, QWORD PTR [rdx+216] + pext r11, r11, r9 + mov QWORD PTR [rcx+208], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+224] + mov r11, QWORD PTR [rdx+224] + pext r12, r12, r9 + mov QWORD PTR [rcx+216], r10 + adc r11, r12 + mov r10, QWORD PTR [r8+232] + mov r12, QWORD PTR [rdx+232] + pext r10, r10, r9 + mov QWORD PTR [rcx+224], r11 + adc r12, r10 + mov r11, QWORD PTR [r8+240] + mov r10, QWORD PTR [rdx+240] + pext r11, r11, r9 + mov QWORD PTR [rcx+232], r12 + adc r10, r11 + mov r12, QWORD PTR [r8+248] + mov r11, QWORD PTR [rdx+248] + pext r12, r12, r9 + mov QWORD PTR [rcx+240], r10 + adc r11, r12 + mov QWORD PTR [rcx+248], r11 + adc rax, 0 + pop r12 + ret +sp_4096_cond_add_avx2_32 ENDP +_text ENDS +ENDIF +; /* Shift number left by n bit. (r = a << n) +; * +; * r Result of left shift by n. +; * a Number to shift. +; * n Amoutnt o shift. +; */ +_text SEGMENT READONLY PARA +sp_4096_lshift_64 PROC + push r12 + push r13 + mov r9, rcx + mov rcx, r8 + mov r12, 0 + mov r13, QWORD PTR [rdx+472] + mov rax, QWORD PTR [rdx+480] + mov r8, QWORD PTR [rdx+488] + mov r10, QWORD PTR [rdx+496] + mov r11, QWORD PTR [rdx+504] + shld r12, r11, cl + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+480], rax + mov QWORD PTR [r9+488], r8 + mov QWORD PTR [r9+496], r10 + mov QWORD PTR [r9+504], r11 + mov QWORD PTR [r9+512], r12 + mov r11, QWORD PTR [rdx+440] + mov rax, QWORD PTR [rdx+448] + mov r8, QWORD PTR [rdx+456] + mov r10, QWORD PTR [rdx+464] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+448], rax + mov QWORD PTR [r9+456], r8 + mov QWORD PTR [r9+464], r10 + mov QWORD PTR [r9+472], r13 + mov r13, QWORD PTR [rdx+408] + mov rax, QWORD PTR [rdx+416] + mov r8, QWORD PTR [rdx+424] + mov r10, QWORD PTR [rdx+432] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+416], rax + mov QWORD PTR [r9+424], r8 + mov QWORD PTR [r9+432], r10 + mov QWORD PTR [r9+440], r11 + mov r11, QWORD PTR [rdx+376] + mov rax, QWORD PTR [rdx+384] + mov r8, QWORD PTR [rdx+392] + mov r10, QWORD PTR [rdx+400] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+384], rax + mov QWORD PTR [r9+392], r8 + mov QWORD PTR [r9+400], r10 + mov QWORD PTR [r9+408], r13 + mov r13, QWORD PTR [rdx+344] + mov rax, QWORD PTR [rdx+352] + mov r8, QWORD PTR [rdx+360] + mov r10, QWORD PTR [rdx+368] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+352], rax + mov QWORD PTR [r9+360], r8 + mov QWORD PTR [r9+368], r10 + mov QWORD PTR [r9+376], r11 + mov r11, QWORD PTR [rdx+312] + mov rax, QWORD PTR [rdx+320] + mov r8, QWORD PTR [rdx+328] + mov r10, QWORD PTR [rdx+336] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+320], rax + mov QWORD PTR [r9+328], r8 + mov QWORD PTR [r9+336], r10 + mov QWORD PTR [r9+344], r13 + mov r13, QWORD PTR [rdx+280] + mov rax, QWORD PTR [rdx+288] + mov r8, QWORD PTR [rdx+296] + mov r10, QWORD PTR [rdx+304] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+288], rax + mov QWORD PTR [r9+296], r8 + mov QWORD PTR [r9+304], r10 + mov QWORD PTR [r9+312], r11 + mov r11, QWORD PTR [rdx+248] + mov rax, QWORD PTR [rdx+256] + mov r8, QWORD PTR [rdx+264] + mov r10, QWORD PTR [rdx+272] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+256], rax + mov QWORD PTR [r9+264], r8 + mov QWORD PTR [r9+272], r10 + mov QWORD PTR [r9+280], r13 + mov r13, QWORD PTR [rdx+216] + mov rax, QWORD PTR [rdx+224] + mov r8, QWORD PTR [rdx+232] + mov r10, QWORD PTR [rdx+240] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+224], rax + mov QWORD PTR [r9+232], r8 + mov QWORD PTR [r9+240], r10 + mov QWORD PTR [r9+248], r11 + mov r11, QWORD PTR [rdx+184] + mov rax, QWORD PTR [rdx+192] + mov r8, QWORD PTR [rdx+200] + mov r10, QWORD PTR [rdx+208] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+192], rax + mov QWORD PTR [r9+200], r8 + mov QWORD PTR [r9+208], r10 + mov QWORD PTR [r9+216], r13 + mov r13, QWORD PTR [rdx+152] + mov rax, QWORD PTR [rdx+160] + mov r8, QWORD PTR [rdx+168] + mov r10, QWORD PTR [rdx+176] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+160], rax + mov QWORD PTR [r9+168], r8 + mov QWORD PTR [r9+176], r10 + mov QWORD PTR [r9+184], r11 + mov r11, QWORD PTR [rdx+120] + mov rax, QWORD PTR [rdx+128] + mov r8, QWORD PTR [rdx+136] + mov r10, QWORD PTR [rdx+144] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+128], rax + mov QWORD PTR [r9+136], r8 + mov QWORD PTR [r9+144], r10 + mov QWORD PTR [r9+152], r13 + mov r13, QWORD PTR [rdx+88] + mov rax, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+96], rax + mov QWORD PTR [r9+104], r8 + mov QWORD PTR [r9+112], r10 + mov QWORD PTR [r9+120], r11 + mov r11, QWORD PTR [rdx+56] + mov rax, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r11, cl + mov QWORD PTR [r9+64], rax + mov QWORD PTR [r9+72], r8 + mov QWORD PTR [r9+80], r10 + mov QWORD PTR [r9+88], r13 + mov r13, QWORD PTR [rdx+24] + mov rax, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + shld r11, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shld rax, r13, cl + mov QWORD PTR [r9+32], rax + mov QWORD PTR [r9+40], r8 + mov QWORD PTR [r9+48], r10 + mov QWORD PTR [r9+56], r11 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + shld r13, r10, cl + shld r10, r8, cl + shld r8, rax, cl + shl rax, cl + mov QWORD PTR [r9], rax + mov QWORD PTR [r9+8], r8 + mov QWORD PTR [r9+16], r10 + mov QWORD PTR [r9+24], r13 + pop r13 + pop r12 + ret +sp_4096_lshift_64 ENDP +_text ENDS +ENDIF +ENDIF +IFNDEF WOLFSSL_SP_NO_256 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_256_mul_4 PROC + push r12 + mov r9, rdx + sub rsp, 32 + ; A[0] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9] + xor r12, r12 + mov QWORD PTR [rsp], rax + mov r11, rdx + ; A[0] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+8], r11 + ; A[0] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+16], r12 + ; A[0] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+24], r10 + ; A[1] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+8] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+32], r11 + ; A[2] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+16] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+40], r12 + ; A[3] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r10, QWORD PTR [rsp+16] + mov r11, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + add rsp, 32 + pop r12 + ret +sp_256_mul_4 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_256_sqr_4 PROC + push r12 + push r13 + push r14 + mov r8, rdx + sub rsp, 32 + ; A[0] * A[0] + mov rax, QWORD PTR [r8] + mul rax + xor r11, r11 + mov QWORD PTR [rsp], rax + mov r10, rdx + ; A[0] * A[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+8], r10 + ; A[0] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[1] * A[1] + mov rax, QWORD PTR [r8+8] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rsp+16], r11 + ; A[0] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[1] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8+8] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+24], r9 + ; A[1] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[2] * A[2] + mov rax, QWORD PTR [r8+16] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rcx+32], r10 + ; A[2] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+16] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+40], r11 + ; A[3] * A[3] + mov rax, QWORD PTR [r8+24] + mul rax + add r9, rax + adc r10, rdx + mov QWORD PTR [rcx+48], r9 + mov QWORD PTR [rcx+56], r10 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r12, QWORD PTR [rsp+16] + mov r13, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + add rsp, 32 + pop r14 + pop r13 + pop r12 + ret +sp_256_sqr_4 ENDP +_text ENDS +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_256_add_4 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov QWORD PTR [rcx+24], r10 + adc rax, 0 + ret +sp_256_add_4 ENDP +_text ENDS +; /* Sub b from a into r. (r = a - b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_256_sub_4 PROC + push r12 + xor rax, rax + mov r9, QWORD PTR [rdx] + mov r10, QWORD PTR [rdx+8] + mov r11, QWORD PTR [rdx+16] + mov r12, QWORD PTR [rdx+24] + sub r9, QWORD PTR [r8] + sbb r10, QWORD PTR [r8+8] + sbb r11, QWORD PTR [r8+16] + sbb r12, QWORD PTR [r8+24] + mov QWORD PTR [rcx], r9 + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + sbb rax, 0 + pop r12 + ret +sp_256_sub_4 ENDP +_text ENDS +; /* Conditionally copy a into r using the mask m. +; * m is -1 to copy and 0 when not. +; * +; * r A single precision number to copy over. +; * a A single precision number to copy. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_256_cond_copy_4 PROC + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [rcx+16] + mov r11, QWORD PTR [rcx+24] + xor rax, QWORD PTR [rdx] + xor r9, QWORD PTR [rdx+8] + xor r10, QWORD PTR [rdx+16] + xor r11, QWORD PTR [rdx+24] + and rax, r8 + and r9, r8 + and r10, r8 + and r11, r8 + xor QWORD PTR [rcx], rax + xor QWORD PTR [rcx+8], r9 + xor QWORD PTR [rcx+16], r10 + xor QWORD PTR [rcx+24], r11 + ret +sp_256_cond_copy_4 ENDP +_text ENDS +; /* Multiply two Montogmery form numbers mod the modulus (prime). +; * (r = a * b mod m) +; * +; * r Result of multiplication. +; * a First number to multiply in Montogmery form. +; * b Second number to multiply in Montogmery form. +; * m Modulus (prime). +; * mp Montogmery mulitplier. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_mul_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov r10, rdx + ; A[0] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r10] + mov r11, rax + mov r12, rdx + ; A[0] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r10] + xor r13, r13 + add r12, rax + adc r13, rdx + ; A[1] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r10+8] + xor r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[0] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r10] + add r13, rax + adc r14, rdx + ; A[1] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r10+8] + xor r15, r15 + add r13, rax + adc r14, rdx + adc r15, 0 + ; A[2] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r10+16] + add r13, rax + adc r14, rdx + adc r15, 0 + ; A[0] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r10] + xor rdi, rdi + add r14, rax + adc r15, rdx + adc rdi, 0 + ; A[1] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r10+8] + add r14, rax + adc r15, rdx + adc rdi, 0 + ; A[2] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r10+16] + add r14, rax + adc r15, rdx + adc rdi, 0 + ; A[3] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r10+24] + add r14, rax + adc r15, rdx + adc rdi, 0 + ; A[1] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r10+8] + xor rsi, rsi + add r15, rax + adc rdi, rdx + adc rsi, 0 + ; A[2] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r10+16] + add r15, rax + adc rdi, rdx + adc rsi, 0 + ; A[3] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r10+24] + add r15, rax + adc rdi, rdx + adc rsi, 0 + ; A[2] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r10+16] + xor rbx, rbx + add rdi, rax + adc rsi, rdx + adc rbx, 0 + ; A[3] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r10+24] + add rdi, rax + adc rsi, rdx + adc rbx, 0 + ; A[3] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r10+24] + add rsi, rax + adc rbx, rdx + ; Start Reduction + ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + ; - a[0] << 32 << 192 + ; + (a[0] * 2) << 192 + mov rax, r11 + mov rdx, r14 + add rdx, r11 + mov r10, r12 + add rdx, r11 + mov r8, r13 + ; a[0]-a[2] << 32 + shl r11, 32 + shld r13, r10, 32 + shld r12, rax, 32 + ; - a[0] << 32 << 192 + sub rdx, r11 + ; + a[0]-a[2] << 32 << 64 + add r10, r11 + adc r8, r12 + adc rdx, r13 + ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + ; a += mu << 256 + xor r11, r11 + add r15, rax + adc rdi, r10 + adc rsi, r8 + adc rbx, rdx + sbb r11, 0 + ; a += mu << 192 + add r14, rax + adc r15, r10 + adc rdi, r8 + adc rsi, rdx + adc rbx, 0 + sbb r11, 0 + ; mu <<= 32 + mov r9, rdx + shld rdx, r8, 32 + shld r8, r10, 32 + shld r10, rax, 32 + shr r9, 32 + shl rax, 32 + ; a += (mu << 32) << 64 + add r14, r8 + adc r15, rdx + adc rdi, r9 + adc rsi, 0 + adc rbx, 0 + sbb r11, 0 + ; a -= (mu << 32) << 192 + sub r14, rax + sbb r15, r10 + sbb rdi, r8 + sbb rsi, rdx + sbb rbx, r9 + adc r11, 0 + mov rax, 4294967295 + mov r10, 18446744069414584321 + ; mask m and sub from result if overflow + ; m[0] = -1 & mask = mask + and rax, r11 + ; m[2] = 0 & mask = 0 + and r10, r11 + sub r15, r11 + sbb rdi, rax + sbb rsi, 0 + sbb rbx, r10 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + mov QWORD PTR [rcx+16], rsi + mov QWORD PTR [rcx+24], rbx + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mont_mul_4 ENDP +_text ENDS +; /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) +; * +; * r Result of squaring. +; * a Number to square in Montogmery form. +; * m Modulus (prime). +; * mp Montogmery mulitplier. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_sqr_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov r8, rdx + ; A[0] * A[1] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r8+8] + mov r11, rax + mov r12, rdx + ; A[0] * A[2] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r8+16] + xor r13, r13 + add r12, rax + adc r13, rdx + ; A[0] * A[3] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r8+24] + xor r14, r14 + add r13, rax + adc r14, rdx + ; A[1] * A[2] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8+16] + xor r15, r15 + add r13, rax + adc r14, rdx + adc r15, 0 + ; A[1] * A[3] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8+24] + add r14, rax + adc r15, rdx + ; A[2] * A[3] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8+24] + xor rdi, rdi + add r15, rax + adc rdi, rdx + ; Double + xor rsi, rsi + add r11, r11 + adc r12, r12 + adc r13, r13 + adc r14, r14 + adc r15, r15 + adc rdi, rdi + adc rsi, 0 + ; A[0] * A[0] + mov rax, QWORD PTR [r8] + mul rax + mov rax, rax + mov rdx, rdx + mov r10, rax + mov rbx, rdx + ; A[1] * A[1] + mov rax, QWORD PTR [r8+8] + mul rax + mov rax, rax + mov rdx, rdx + add r11, rbx + adc r12, rax + adc rdx, 0 + mov rbx, rdx + ; A[2] * A[2] + mov rax, QWORD PTR [r8+16] + mul rax + mov rax, rax + mov rdx, rdx + add r13, rbx + adc r14, rax + adc rdx, 0 + mov rbx, rdx + ; A[3] * A[3] + mov rax, QWORD PTR [r8+24] + mul rax + mov rax, rax + mov rdx, rdx + add r15, rbx + adc rdi, rax + adc rsi, rdx + ; Start Reduction + ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + ; - a[0] << 32 << 192 + ; + (a[0] * 2) << 192 + mov rax, r10 + mov rdx, r13 + add rdx, r10 + mov r8, r11 + add rdx, r10 + mov rbx, r12 + ; a[0]-a[2] << 32 + shl r10, 32 + shld r12, r8, 32 + shld r11, rax, 32 + ; - a[0] << 32 << 192 + sub rdx, r10 + ; + a[0]-a[2] << 32 << 64 + add r8, r10 + adc rbx, r11 + adc rdx, r12 + ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + ; a += mu << 256 + xor r10, r10 + add r14, rax + adc r15, r8 + adc rdi, rbx + adc rsi, rdx + sbb r10, 0 + ; a += mu << 192 + add r13, rax + adc r14, r8 + adc r15, rbx + adc rdi, rdx + adc rsi, 0 + sbb r10, 0 + ; mu <<= 32 + mov r9, rdx + shld rdx, rbx, 32 + shld rbx, r8, 32 + shld r8, rax, 32 + shr r9, 32 + shl rax, 32 + ; a += (mu << 32) << 64 + add r13, rbx + adc r14, rdx + adc r15, r9 + adc rdi, 0 + adc rsi, 0 + sbb r10, 0 + ; a -= (mu << 32) << 192 + sub r13, rax + sbb r14, r8 + sbb r15, rbx + sbb rdi, rdx + sbb rsi, r9 + adc r10, 0 + mov rax, 4294967295 + mov r8, 18446744069414584321 + ; mask m and sub from result if overflow + ; m[0] = -1 & mask = mask + and rax, r10 + ; m[2] = 0 & mask = 0 + and r8, r10 + sub r14, r10 + sbb r15, rax + sbb rdi, 0 + sbb rsi, r8 + mov QWORD PTR [rcx], r14 + mov QWORD PTR [rcx+8], r15 + mov QWORD PTR [rcx+16], rdi + mov QWORD PTR [rcx+24], rsi + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mont_sqr_4 ENDP +_text ENDS +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_256_cmp_4 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_256_cmp_4 ENDP +_text ENDS +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_256_cond_sub_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov rax, 0 + mov r14, QWORD PTR [r8] + mov r15, QWORD PTR [r8+8] + mov rdi, QWORD PTR [r8+16] + mov rsi, QWORD PTR [r8+24] + and r14, r9 + and r15, r9 + and rdi, r9 + and rsi, r9 + mov r10, QWORD PTR [rdx] + mov r11, QWORD PTR [rdx+8] + mov r12, QWORD PTR [rdx+16] + mov r13, QWORD PTR [rdx+24] + sub r10, r14 + sbb r11, r15 + sbb r12, rdi + sbb r13, rsi + mov QWORD PTR [rcx], r10 + mov QWORD PTR [rcx+8], r11 + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + sbb rax, 0 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_cond_sub_4 ENDP +_text ENDS +; /* Reduce the number back to 256 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_reduce_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + ; i = 0 + xor rdi, rdi + mov r10, 4 + mov r15, rcx +L_mont_loop_4: + ; mu = a[i] * mp + mov r14, QWORD PTR [r15] + imul r14, r8 + ; a[i+0] += m[0] * mu + mov rax, QWORD PTR [r9] + mov r12, QWORD PTR [r9+8] + mul r14 + mov rsi, QWORD PTR [r15] + add rsi, rax + mov r11, rdx + mov QWORD PTR [r15], rsi + adc r11, 0 + ; a[i+1] += m[1] * mu + mov rax, r12 + mul r14 + mov r12, QWORD PTR [r9+16] + mov rsi, QWORD PTR [r15+8] + add rax, r11 + mov r13, rdx + adc r13, 0 + add rsi, rax + mov QWORD PTR [r15+8], rsi + adc r13, 0 + ; a[i+2] += m[2] * mu + mov rax, r12 + mul r14 + mov r12, QWORD PTR [r9+24] + mov rsi, QWORD PTR [r15+16] + add rax, r13 + mov r11, rdx + adc r11, 0 + add rsi, rax + mov QWORD PTR [r15+16], rsi + adc r11, 0 + ; a[i+3] += m[3] * mu + mov rax, r12 + mul r14 + mov rsi, QWORD PTR [r15+24] + add rax, r11 + adc rdx, rdi + mov rdi, 0 + adc rdi, 0 + add rsi, rax + mov QWORD PTR [r15+24], rsi + adc QWORD PTR [r15+32], rdx + adc rdi, 0 + ; i += 1 + add r15, 8 + dec r10 + jnz L_mont_loop_4 + xor rax, rax + mov rdx, QWORD PTR [rcx+32] + mov r10, QWORD PTR [rcx+40] + mov rsi, QWORD PTR [rcx+48] + mov r11, QWORD PTR [rcx+56] + sub rax, rdi + mov r12, QWORD PTR [r9] + mov r13, QWORD PTR [r9+8] + mov r14, QWORD PTR [r9+16] + mov r15, QWORD PTR [r9+24] + and r12, rax + and r13, rax + and r14, rax + and r15, rax + sub rdx, r12 + sbb r10, r13 + sbb rsi, r14 + sbb r11, r15 + mov QWORD PTR [rcx], rdx + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], rsi + mov QWORD PTR [rcx+24], r11 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mont_reduce_4 ENDP +_text ENDS +; /* Add two Montgomery form numbers (r = a + b % m). +; * +; * r Result of addition. +; * a First number to add in Montogmery form. +; * b Second number to add in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_256_mont_add_4 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + mov r12, 4294967295 + mov r13, 18446744069414584321 + add rax, QWORD PTR [r8] + adc r9, QWORD PTR [r8+8] + adc r10, QWORD PTR [r8+16] + mov rdx, 0 + adc r11, QWORD PTR [r8+24] + sbb rdx, 0 + and r12, rdx + and r13, rdx + sub rax, rdx + sbb r9, r12 + sbb r10, 0 + sbb r11, r13 + adc rdx, 0 + and r12, rdx + and r13, rdx + sub rax, rdx + sbb r9, r12 + mov QWORD PTR [rcx], rax + sbb r10, 0 + mov QWORD PTR [rcx+8], r9 + sbb r11, r13 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + pop r13 + pop r12 + ret +sp_256_mont_add_4 ENDP +_text ENDS +; /* Double a Montgomery form number (r = a + a % m). +; * +; * r Result of doubling. +; * a Number to double in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_256_mont_dbl_4 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r9, QWORD PTR [rdx+16] + mov r10, QWORD PTR [rdx+24] + mov r11, 4294967295 + mov r12, 18446744069414584321 + add rax, rax + adc r8, r8 + adc r9, r9 + mov r13, 0 + adc r10, r10 + sbb r13, 0 + and r11, r13 + and r12, r13 + sub rax, r13 + sbb r8, r11 + sbb r9, 0 + sbb r10, r12 + adc r13, 0 + and r11, r13 + and r12, r13 + sub rax, r13 + sbb r8, r11 + mov QWORD PTR [rcx], rax + sbb r9, 0 + mov QWORD PTR [rcx+8], r8 + sbb r10, r12 + mov QWORD PTR [rcx+16], r9 + mov QWORD PTR [rcx+24], r10 + pop r13 + pop r12 + ret +sp_256_mont_dbl_4 ENDP +_text ENDS +; /* Triple a Montgomery form number (r = a + a + a % m). +; * +; * r Result of Tripling. +; * a Number to triple in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_256_mont_tpl_4 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r9, QWORD PTR [rdx+16] + mov r10, QWORD PTR [rdx+24] + mov r11, 4294967295 + mov r12, 18446744069414584321 + add rax, rax + adc r8, r8 + adc r9, r9 + mov r13, 0 + adc r10, r10 + sbb r13, 0 + and r11, r13 + and r12, r13 + sub rax, r13 + sbb r8, r11 + sbb r9, 0 + sbb r10, r12 + adc r13, 0 + and r11, r13 + and r12, r13 + sub rax, r13 + sbb r8, r11 + sbb r9, 0 + sbb r10, r12 + mov r11, 4294967295 + mov r12, 18446744069414584321 + add rax, QWORD PTR [rdx] + adc r8, QWORD PTR [rdx+8] + adc r9, QWORD PTR [rdx+16] + mov r13, 0 + adc r10, QWORD PTR [rdx+24] + sbb r13, 0 + and r11, r13 + and r12, r13 + sub rax, r13 + sbb r8, r11 + sbb r9, 0 + sbb r10, r12 + adc r13, 0 + and r11, r13 + and r12, r13 + sub rax, r13 + sbb r8, r11 + mov QWORD PTR [rcx], rax + sbb r9, 0 + mov QWORD PTR [rcx+8], r8 + sbb r10, r12 + mov QWORD PTR [rcx+16], r9 + mov QWORD PTR [rcx+24], r10 + pop r13 + pop r12 + ret +sp_256_mont_tpl_4 ENDP +_text ENDS +; /* Subtract two Montgomery form numbers (r = a - b % m). +; * +; * r Result of subtration. +; * a Number to subtract from in Montogmery form. +; * b Number to subtract with in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_256_mont_sub_4 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + mov r12, 4294967295 + mov r13, 18446744069414584321 + sub rax, QWORD PTR [r8] + sbb r9, QWORD PTR [r8+8] + sbb r10, QWORD PTR [r8+16] + mov rdx, 0 + sbb r11, QWORD PTR [r8+24] + sbb rdx, 0 + and r12, rdx + and r13, rdx + add rax, rdx + adc r9, r12 + adc r10, 0 + adc r11, r13 + adc rdx, 0 + and r12, rdx + and r13, rdx + add rax, rdx + adc r9, r12 + mov QWORD PTR [rcx], rax + adc r10, 0 + mov QWORD PTR [rcx+8], r9 + adc r11, r13 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + pop r13 + pop r12 + ret +sp_256_mont_sub_4 ENDP +_text ENDS +; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_256_div2_4 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r9, QWORD PTR [rdx+16] + mov r10, QWORD PTR [rdx+24] + mov r11, 4294967295 + mov r12, 18446744069414584321 + mov r13, rax + and r13, 1 + neg r13 + and r11, r13 + and r12, r13 + add rax, r13 + adc r8, r11 + adc r9, 0 + adc r10, r12 + mov r13, 0 + adc r13, 0 + shrd rax, r8, 1 + shrd r8, r9, 1 + shrd r9, r10, 1 + shrd r10, r13, 1 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r8 + mov QWORD PTR [rcx+16], r9 + mov QWORD PTR [rcx+24], r10 + pop r13 + pop r12 + ret +sp_256_div2_4 ENDP +_text ENDS +IFNDEF WC_NO_CACHE_RESISTANT +; /* Touch each possible point that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of point to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_256_get_point_33_4 PROC + mov rax, 1 + movd xmm13, r8d + add rdx, 200 + movd xmm15, eax + mov rax, 32 + pshufd xmm15, xmm15, 0 + pshufd xmm13, xmm13, 0 + pxor xmm14, xmm14 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + pxor xmm3, xmm3 + pxor xmm4, xmm4 + pxor xmm5, xmm5 + movdqa xmm14, xmm15 +L_256_get_point_33_4_start: + movdqa xmm12, xmm14 + paddd xmm14, xmm15 + pcmpeqd xmm12, xmm13 + movdqu xmm6, [rdx] + movdqu xmm7, [rdx+16] + movdqu xmm8, [rdx+64] + movdqu xmm9, [rdx+80] + movdqu xmm10, [rdx+128] + movdqu xmm11, [rdx+144] + add rdx, 200 + pand xmm6, xmm12 + pand xmm7, xmm12 + pand xmm8, xmm12 + pand xmm9, xmm12 + pand xmm10, xmm12 + pand xmm11, xmm12 + por xmm0, xmm6 + por xmm1, xmm7 + por xmm2, xmm8 + por xmm3, xmm9 + por xmm4, xmm10 + por xmm5, xmm11 + dec rax + jnz L_256_get_point_33_4_start + movdqu [rcx], xmm0 + movdqu [rcx+16], xmm1 + movdqu [rcx+64], xmm2 + movdqu [rcx+80], xmm3 + movdqu [rcx+128], xmm4 + movdqu [rcx+144], xmm5 + ret +sp_256_get_point_33_4 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Touch each possible point that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of point to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_256_get_point_33_avx2_4 PROC + mov rax, 1 + movd xmm7, r8d + add rdx, 200 + movd xmm9, eax + mov rax, 32 + vpxor ymm8, ymm8, ymm8 + vpermd ymm7, ymm8, ymm7 + vpermd ymm9, ymm8, ymm9 + vpxor ymm0, ymm0, ymm0 + vpxor ymm1, ymm1, ymm1 + vpxor ymm2, ymm2, ymm2 + vmovdqa ymm8, ymm9 +L_256_get_point_33_avx2_4_start: + vpcmpeqd ymm6, ymm8, ymm7 + vpaddd ymm8, ymm8, ymm9 + vmovupd ymm3, [rdx] + vmovupd ymm4, [rdx+64] + vmovupd ymm5, [rdx+128] + add rdx, 200 + vpand ymm3, ymm3, ymm6 + vpand ymm4, ymm4, ymm6 + vpand ymm5, ymm5, ymm6 + vpor ymm0, ymm0, ymm3 + vpor ymm1, ymm1, ymm4 + vpor ymm2, ymm2, ymm5 + dec rax + jnz L_256_get_point_33_avx2_4_start + vmovupd YMMWORD PTR [rcx], ymm0 + vmovupd YMMWORD PTR [rcx+64], ymm1 + vmovupd YMMWORD PTR [rcx+128], ymm2 + ret +sp_256_get_point_33_avx2_4 ENDP +_text ENDS +ENDIF +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Multiply two Montogmery form numbers mod the modulus (prime). +; * (r = a * b mod m) +; * +; * r Result of multiplication. +; * a First number to multiply in Montogmery form. +; * b Second number to multiply in Montogmery form. +; * m Modulus (prime). +; * mp Montogmery mulitplier. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_mul_avx2_4 PROC + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp + push rdi + push rsi + mov rbp, r8 + mov rdi, rdx + ; A[0] * B[0] + mov rdx, QWORD PTR [rbp] + mulx r9, r8, QWORD PTR [rdi] + ; A[2] * B[0] + mulx r11, r10, QWORD PTR [rdi+16] + ; A[1] * B[0] + mulx rsi, rax, QWORD PTR [rdi+8] + xor r15, r15 + adcx r9, rax + ; A[1] * B[3] + mov rdx, QWORD PTR [rbp+24] + mulx r13, r12, QWORD PTR [rdi+8] + adcx r10, rsi + ; A[0] * B[1] + mov rdx, QWORD PTR [rbp+8] + mulx rsi, rax, QWORD PTR [rdi] + adox r9, rax + ; A[2] * B[1] + mulx r14, rax, QWORD PTR [rdi+16] + adox r10, rsi + adcx r11, rax + ; A[1] * B[2] + mov rdx, QWORD PTR [rbp+16] + mulx rsi, rax, QWORD PTR [rdi+8] + adcx r12, r14 + adox r11, rax + adcx r13, r15 + adox r12, rsi + ; A[0] * B[2] + mulx rsi, rax, QWORD PTR [rdi] + adox r13, r15 + xor r14, r14 + adcx r10, rax + ; A[1] * B[1] + mov rdx, QWORD PTR [rbp+8] + mulx rax, rdx, QWORD PTR [rdi+8] + adcx r11, rsi + adox r10, rdx + ; A[3] * B[1] + mov rdx, QWORD PTR [rbp+8] + adox r11, rax + mulx rsi, rax, QWORD PTR [rdi+24] + adcx r12, rax + ; A[2] * B[2] + mov rdx, QWORD PTR [rbp+16] + mulx rax, rdx, QWORD PTR [rdi+16] + adcx r13, rsi + adox r12, rdx + ; A[3] * B[3] + mov rdx, QWORD PTR [rbp+24] + adox r13, rax + mulx rsi, rax, QWORD PTR [rdi+24] + adox r14, r15 + adcx r14, rax + ; A[0] * B[3] + mulx rax, rdx, QWORD PTR [rdi] + adcx r15, rsi + xor rsi, rsi + adcx r11, rdx + ; A[3] * B[0] + mov rdx, QWORD PTR [rdi+24] + adcx r12, rax + mulx rax, rbx, QWORD PTR [rbp] + adox r11, rbx + adox r12, rax + ; A[3] * B[2] + mulx rax, rdx, QWORD PTR [rbp+16] + adcx r13, rdx + ; A[2] * B[3] + mov rdx, QWORD PTR [rbp+24] + adcx r14, rax + mulx rdx, rax, QWORD PTR [rdi+16] + adcx r15, rsi + adox r13, rax + adox r14, rdx + adox r15, rsi + ; Start Reduction + ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + ; - a[0] << 32 << 192 + ; + (a[0] * 2) << 192 + mov rax, r8 + mov rdx, r11 + add rdx, r8 + mov rdi, r9 + add rdx, r8 + mov rbp, r10 + ; a[0]-a[2] << 32 + shl r8, 32 + shld r10, rdi, 32 + shld r9, rax, 32 + ; - a[0] << 32 << 192 + sub rdx, r8 + ; + a[0]-a[2] << 32 << 64 + add rdi, r8 + adc rbp, r9 + adc rdx, r10 + ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + ; a += mu << 256 + xor r8, r8 + add r12, rax + adc r13, rdi + adc r14, rbp + adc r15, rdx + sbb r8, 0 + ; a += mu << 192 + add r11, rax + adc r12, rdi + adc r13, rbp + adc r14, rdx + adc r15, 0 + sbb r8, 0 + ; mu <<= 32 + mov rsi, rdx + shld rdx, rbp, 32 + shld rbp, rdi, 32 + shld rdi, rax, 32 + shr rsi, 32 + shl rax, 32 + ; a += (mu << 32) << 64 + add r11, rbp + adc r12, rdx + adc r13, rsi + adc r14, 0 + adc r15, 0 + sbb r8, 0 + ; a -= (mu << 32) << 192 + sub r11, rax + sbb r12, rdi + sbb r13, rbp + sbb r14, rdx + sbb r15, rsi + adc r8, 0 + mov rax, 4294967295 + mov rdi, 18446744069414584321 + ; mask m and sub from result if overflow + ; m[0] = -1 & mask = mask + and rax, r8 + ; m[2] = 0 & mask = 0 + and rdi, r8 + sub r12, r8 + sbb r13, rax + sbb r14, 0 + sbb r15, rdi + mov QWORD PTR [rcx], r12 + mov QWORD PTR [rcx+8], r13 + mov QWORD PTR [rcx+16], r14 + mov QWORD PTR [rcx+24], r15 + pop rsi + pop rdi + pop rbp + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + ret +sp_256_mont_mul_avx2_4 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) +; * +; * r Result of squaring. +; * a Number to square in Montogmery form. +; * m Modulus (prime). +; * mp Montogmery mulitplier. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_sqr_avx2_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov rax, rdx + ; A[0] * A[1] + mov rdx, QWORD PTR [rax] + mov r15, QWORD PTR [rax+16] + mulx r10, r9, QWORD PTR [rax+8] + ; A[0] * A[3] + mulx r12, r11, QWORD PTR [rax+24] + ; A[2] * A[1] + mov rdx, r15 + mulx rbx, rsi, QWORD PTR [rax+8] + ; A[2] * A[3] + mulx r14, r13, QWORD PTR [rax+24] + xor r15, r15 + adox r11, rsi + adox r12, rbx + ; A[2] * A[0] + mulx rbx, rsi, QWORD PTR [rax] + ; A[1] * A[3] + mov rdx, QWORD PTR [rax+8] + adox r13, r15 + mulx r8, rdi, QWORD PTR [rax+24] + adcx r10, rsi + adox r14, r15 + adcx r11, rbx + adcx r12, rdi + adcx r13, r8 + adcx r14, r15 + ; Double with Carry Flag + xor r15, r15 + ; A[0] * A[0] + mov rdx, QWORD PTR [rax] + mulx rdi, r8, rdx + adcx r9, r9 + adcx r10, r10 + adox r9, rdi + ; A[1] * A[1] + mov rdx, QWORD PTR [rax+8] + mulx rbx, rsi, rdx + adcx r11, r11 + adox r10, rsi + ; A[2] * A[2] + mov rdx, QWORD PTR [rax+16] + mulx rsi, rdi, rdx + adcx r12, r12 + adox r11, rbx + adcx r13, r13 + adox r12, rdi + adcx r14, r14 + ; A[3] * A[3] + mov rdx, QWORD PTR [rax+24] + mulx rbx, rdi, rdx + adox r13, rsi + adcx r15, r15 + adox r14, rdi + adox r15, rbx + ; Start Reduction + ; mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + ; - a[0] << 32 << 192 + ; + (a[0] * 2) << 192 + mov rdi, r8 + mov rdx, r11 + add rdx, r8 + mov rax, r9 + add rdx, r8 + mov rsi, r10 + ; a[0]-a[2] << 32 + shl r8, 32 + shld r10, rax, 32 + shld r9, rdi, 32 + ; - a[0] << 32 << 192 + sub rdx, r8 + ; + a[0]-a[2] << 32 << 64 + add rax, r8 + adc rsi, r9 + adc rdx, r10 + ; a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + ; a += mu << 256 + xor r8, r8 + add r12, rdi + adc r13, rax + adc r14, rsi + adc r15, rdx + sbb r8, 0 + ; a += mu << 192 + add r11, rdi + adc r12, rax + adc r13, rsi + adc r14, rdx + adc r15, 0 + sbb r8, 0 + ; mu <<= 32 + mov rbx, rdx + shld rdx, rsi, 32 + shld rsi, rax, 32 + shld rax, rdi, 32 + shr rbx, 32 + shl rdi, 32 + ; a += (mu << 32) << 64 + add r11, rsi + adc r12, rdx + adc r13, rbx + adc r14, 0 + adc r15, 0 + sbb r8, 0 + ; a -= (mu << 32) << 192 + sub r11, rdi + sbb r12, rax + sbb r13, rsi + sbb r14, rdx + sbb r15, rbx + adc r8, 0 + mov rdi, 4294967295 + mov rax, 18446744069414584321 + ; mask m and sub from result if overflow + ; m[0] = -1 & mask = mask + and rdi, r8 + ; m[2] = 0 & mask = 0 + and rax, r8 + sub r12, r8 + sbb r13, rdi + sbb r14, 0 + sbb r15, rax + mov QWORD PTR [rcx], r12 + mov QWORD PTR [rcx+8], r13 + mov QWORD PTR [rcx+16], r14 + mov QWORD PTR [rcx+24], r15 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mont_sqr_avx2_4 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_256_cond_sub_avx2_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov rax, 0 + mov r14, QWORD PTR [r8] + mov r15, QWORD PTR [r8+8] + mov rdi, QWORD PTR [r8+16] + mov rsi, QWORD PTR [r8+24] + and r14, r9 + and r15, r9 + and rdi, r9 + and rsi, r9 + mov r10, QWORD PTR [rdx] + mov r11, QWORD PTR [rdx+8] + mov r12, QWORD PTR [rdx+16] + mov r13, QWORD PTR [rdx+24] + sub r10, r14 + sbb r11, r15 + sbb r12, rdi + sbb r13, rsi + mov QWORD PTR [rcx], r10 + mov QWORD PTR [rcx+8], r11 + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + sbb rax, 0 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_cond_sub_avx2_4 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 256 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_reduce_avx2_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov rax, rcx + mov r10, rdx + mov r11, r8 + mov r14, QWORD PTR [rax] + mov r15, QWORD PTR [rax+8] + mov rdi, QWORD PTR [rax+16] + mov rsi, QWORD PTR [rax+24] + xor r13, r13 + xor r12, r12 + ; a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp) + mov rbx, QWORD PTR [rax+32] + ; mu = a[0] * mp + mov rdx, r14 + mulx rcx, rdx, r11 + ; a[0] += m[0] * mu + mulx r9, r8, QWORD PTR [r10] + adcx r14, r8 + ; a[1] += m[1] * mu + mulx rcx, r8, QWORD PTR [r10+8] + adox r15, r9 + adcx r15, r8 + ; a[2] += m[2] * mu + mulx r9, r8, QWORD PTR [r10+16] + adox rdi, rcx + adcx rdi, r8 + ; a[3] += m[3] * mu + mulx rcx, r8, QWORD PTR [r10+24] + adox rsi, r9 + adcx rsi, r8 + ; a[4] += carry + adox rbx, rcx + adcx rbx, r12 + ; carry + adox r13, r12 + adcx r13, r12 + ; a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp) + mov r14, QWORD PTR [rax+40] + ; mu = a[1] * mp + mov rdx, r15 + mulx rcx, rdx, r11 + ; a[1] += m[0] * mu + mulx r9, r8, QWORD PTR [r10] + adcx r15, r8 + ; a[2] += m[1] * mu + mulx rcx, r8, QWORD PTR [r10+8] + adox rdi, r9 + adcx rdi, r8 + ; a[3] += m[2] * mu + mulx r9, r8, QWORD PTR [r10+16] + adox rsi, rcx + adcx rsi, r8 + ; a[4] += m[3] * mu + mulx rcx, r8, QWORD PTR [r10+24] + adox rbx, r9 + adcx rbx, r8 + ; a[5] += carry + adox r14, rcx + adcx r14, r13 + mov r13, r12 + ; carry + adox r13, r12 + adcx r13, r12 + ; a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp) + mov r15, QWORD PTR [rax+48] + ; mu = a[2] * mp + mov rdx, rdi + mulx rcx, rdx, r11 + ; a[2] += m[0] * mu + mulx r9, r8, QWORD PTR [r10] + adcx rdi, r8 + ; a[3] += m[1] * mu + mulx rcx, r8, QWORD PTR [r10+8] + adox rsi, r9 + adcx rsi, r8 + ; a[4] += m[2] * mu + mulx r9, r8, QWORD PTR [r10+16] + adox rbx, rcx + adcx rbx, r8 + ; a[5] += m[3] * mu + mulx rcx, r8, QWORD PTR [r10+24] + adox r14, r9 + adcx r14, r8 + ; a[6] += carry + adox r15, rcx + adcx r15, r13 + mov r13, r12 + ; carry + adox r13, r12 + adcx r13, r12 + ; a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp) + mov rdi, QWORD PTR [rax+56] + ; mu = a[3] * mp + mov rdx, rsi + mulx rcx, rdx, r11 + ; a[3] += m[0] * mu + mulx r9, r8, QWORD PTR [r10] + adcx rsi, r8 + ; a[4] += m[1] * mu + mulx rcx, r8, QWORD PTR [r10+8] + adox rbx, r9 + adcx rbx, r8 + ; a[5] += m[2] * mu + mulx r9, r8, QWORD PTR [r10+16] + adox r14, rcx + adcx r14, r8 + ; a[6] += m[3] * mu + mulx rcx, r8, QWORD PTR [r10+24] + adox r15, r9 + adcx r15, r8 + ; a[7] += carry + adox rdi, rcx + adcx rdi, r13 + mov r13, r12 + ; carry + adox r13, r12 + adcx r13, r12 + ; Subtract mod if carry + neg r13 + mov r8, 17562291160714782033 + mov r9, 13611842547513532036 + mov rdx, 18446744069414584320 + and r8, r13 + and r9, r13 + and rdx, r13 + sub rbx, r8 + sbb r14, r9 + sbb r15, r13 + sbb rdi, rdx + mov QWORD PTR [rax], rbx + mov QWORD PTR [rax+8], r14 + mov QWORD PTR [rax+16], r15 + mov QWORD PTR [rax+24], rdi + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mont_reduce_avx2_4 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_256_div2_avx2_4 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r9, QWORD PTR [rdx+16] + mov r10, QWORD PTR [rdx+24] + mov r11, 4294967295 + mov r12, 18446744069414584321 + mov r13, rax + and r13, 1 + neg r13 + and r11, r13 + and r12, r13 + add rax, r13 + adc r8, r11 + adc r9, 0 + adc r10, r12 + mov r13, 0 + adc r13, 0 + shrd rax, r8, 1 + shrd r8, r9, 1 + shrd r9, r10, 1 + shrd r10, r13, 1 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r8 + mov QWORD PTR [rcx+16], r9 + mov QWORD PTR [rcx+24], r10 + pop r13 + pop r12 + ret +sp_256_div2_avx2_4 ENDP +_text ENDS +ENDIF +IFNDEF WC_NO_CACHE_RESISTANT +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_256_get_entry_64_4 PROC + mov rax, 1 + movd xmm9, r8d + add rdx, 64 + movd xmm11, eax + mov rax, 63 + pshufd xmm11, xmm11, 0 + pshufd xmm9, xmm9, 0 + pxor xmm10, xmm10 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + pxor xmm3, xmm3 + movdqa xmm10, xmm11 +L_256_get_entry_64_4_start: + movdqa xmm8, xmm10 + paddd xmm10, xmm11 + pcmpeqd xmm8, xmm9 + movdqu xmm4, [rdx] + movdqu xmm5, [rdx+16] + movdqu xmm6, [rdx+32] + movdqu xmm7, [rdx+48] + add rdx, 64 + pand xmm4, xmm8 + pand xmm5, xmm8 + pand xmm6, xmm8 + pand xmm7, xmm8 + por xmm0, xmm4 + por xmm1, xmm5 + por xmm2, xmm6 + por xmm3, xmm7 + dec rax + jnz L_256_get_entry_64_4_start + movdqu [rcx], xmm0 + movdqu [rcx+16], xmm1 + movdqu [rcx+64], xmm2 + movdqu [rcx+80], xmm3 + ret +sp_256_get_entry_64_4 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_256_get_entry_64_avx2_4 PROC + mov rax, 1 + movd xmm5, r8d + add rdx, 64 + movd xmm7, eax + mov rax, 64 + vpxor ymm6, ymm6, ymm6 + vpermd ymm5, ymm6, ymm5 + vpermd ymm7, ymm6, ymm7 + vpxor ymm0, ymm0, ymm0 + vpxor ymm1, ymm1, ymm1 + vmovdqa ymm6, ymm7 +L_256_get_entry_64_avx2_4_start: + vpcmpeqd ymm4, ymm6, ymm5 + vpaddd ymm6, ymm6, ymm7 + vmovupd ymm2, [rdx] + vmovupd ymm3, [rdx+32] + add rdx, 64 + vpand ymm2, ymm2, ymm4 + vpand ymm3, ymm3, ymm4 + vpor ymm0, ymm0, ymm2 + vpor ymm1, ymm1, ymm3 + dec rax + jnz L_256_get_entry_64_avx2_4_start + vmovupd YMMWORD PTR [rcx], ymm0 + vmovupd YMMWORD PTR [rcx+64], ymm1 + ret +sp_256_get_entry_64_avx2_4 ENDP +_text ENDS +ENDIF +ENDIF +IFNDEF WC_NO_CACHE_RESISTANT +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_256_get_entry_65_4 PROC + mov rax, 1 + movd xmm9, r8d + add rdx, 64 + movd xmm11, eax + mov rax, 64 + pshufd xmm11, xmm11, 0 + pshufd xmm9, xmm9, 0 + pxor xmm10, xmm10 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + pxor xmm3, xmm3 + movdqa xmm10, xmm11 +L_256_get_entry_65_4_start: + movdqa xmm8, xmm10 + paddd xmm10, xmm11 + pcmpeqd xmm8, xmm9 + movdqu xmm4, [rdx] + movdqu xmm5, [rdx+16] + movdqu xmm6, [rdx+32] + movdqu xmm7, [rdx+48] + add rdx, 64 + pand xmm4, xmm8 + pand xmm5, xmm8 + pand xmm6, xmm8 + pand xmm7, xmm8 + por xmm0, xmm4 + por xmm1, xmm5 + por xmm2, xmm6 + por xmm3, xmm7 + dec rax + jnz L_256_get_entry_65_4_start + movdqu [rcx], xmm0 + movdqu [rcx+16], xmm1 + movdqu [rcx+64], xmm2 + movdqu [rcx+80], xmm3 + ret +sp_256_get_entry_65_4 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_256_get_entry_65_avx2_4 PROC + mov rax, 1 + movd xmm5, r8d + add rdx, 64 + movd xmm7, eax + mov rax, 65 + vpxor ymm6, ymm6, ymm6 + vpermd ymm5, ymm6, ymm5 + vpermd ymm7, ymm6, ymm7 + vpxor ymm0, ymm0, ymm0 + vpxor ymm1, ymm1, ymm1 + vmovdqa ymm6, ymm7 +L_256_get_entry_65_avx2_4_start: + vpcmpeqd ymm4, ymm6, ymm5 + vpaddd ymm6, ymm6, ymm7 + vmovupd ymm2, [rdx] + vmovupd ymm3, [rdx+32] + add rdx, 64 + vpand ymm2, ymm2, ymm4 + vpand ymm3, ymm3, ymm4 + vpor ymm0, ymm0, ymm2 + vpor ymm1, ymm1, ymm3 + dec rax + jnz L_256_get_entry_65_avx2_4_start + vmovupd YMMWORD PTR [rcx], ymm0 + vmovupd YMMWORD PTR [rcx+64], ymm1 + ret +sp_256_get_entry_65_avx2_4 ENDP +_text ENDS +ENDIF +ENDIF +; /* Add 1 to a. (a = a + 1) +; * +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_256_add_one_4 PROC + add QWORD PTR [rcx], 1 + adc QWORD PTR [rcx+8], 0 + adc QWORD PTR [rcx+16], 0 + adc QWORD PTR [rcx+24], 0 + ret +sp_256_add_one_4 ENDP +_text ENDS +; /* Read big endian unsigned byte array into r. +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_256_from_bin_bswap PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 32 + xor r13, r13 + jmp L_256_from_bin_bswap_64_end +L_256_from_bin_bswap_64_start: + sub r11, 64 + mov rax, QWORD PTR [r11+56] + mov r10, QWORD PTR [r11+48] + bswap rax + bswap r10 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [r11+40] + mov r10, QWORD PTR [r11+32] + bswap rax + bswap r10 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [r11+24] + mov r10, QWORD PTR [r11+16] + bswap rax + bswap r10 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [r11+8] + mov r10, QWORD PTR [r11] + bswap rax + bswap r10 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_256_from_bin_bswap_64_end: + cmp r9, 63 + jg L_256_from_bin_bswap_64_start + jmp L_256_from_bin_bswap_8_end +L_256_from_bin_bswap_8_start: + sub r11, 8 + mov rax, QWORD PTR [r11] + bswap rax + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_256_from_bin_bswap_8_end: + cmp r9, 7 + jg L_256_from_bin_bswap_8_start + cmp r9, r13 + je L_256_from_bin_bswap_hi_end + mov r10, r13 + mov rax, r13 +L_256_from_bin_bswap_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_256_from_bin_bswap_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_256_from_bin_bswap_hi_end: + cmp rcx, r12 + je L_256_from_bin_bswap_zero_end +L_256_from_bin_bswap_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_256_from_bin_bswap_zero_start +L_256_from_bin_bswap_zero_end: + pop r13 + pop r12 + ret +sp_256_from_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Read big endian unsigned byte array into r. +; * Uses the movbe instruction which is an optional instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_256_from_bin_movbe PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 32 + xor r13, r13 + jmp L_256_from_bin_movbe_64_end +L_256_from_bin_movbe_64_start: + sub r11, 64 + movbe rax, QWORD PTR [r11+56] + movbe r10, QWORD PTR [r11+48] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + movbe rax, QWORD PTR [r11+40] + movbe r10, QWORD PTR [r11+32] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + movbe rax, QWORD PTR [r11+24] + movbe r10, QWORD PTR [r11+16] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + movbe rax, QWORD PTR [r11+8] + movbe r10, QWORD PTR [r11] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_256_from_bin_movbe_64_end: + cmp r9, 63 + jg L_256_from_bin_movbe_64_start + jmp L_256_from_bin_movbe_8_end +L_256_from_bin_movbe_8_start: + sub r11, 8 + movbe rax, QWORD PTR [r11] + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_256_from_bin_movbe_8_end: + cmp r9, 7 + jg L_256_from_bin_movbe_8_start + cmp r9, r13 + je L_256_from_bin_movbe_hi_end + mov r10, r13 + mov rax, r13 +L_256_from_bin_movbe_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_256_from_bin_movbe_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_256_from_bin_movbe_hi_end: + cmp rcx, r12 + je L_256_from_bin_movbe_zero_end +L_256_from_bin_movbe_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_256_from_bin_movbe_zero_start +L_256_from_bin_movbe_zero_end: + pop r13 + pop r12 + ret +sp_256_from_bin_movbe ENDP +_text ENDS +ENDIF +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 32 +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_256_to_bin_bswap PROC + mov rax, QWORD PTR [rcx+24] + mov r8, QWORD PTR [rcx+16] + bswap rax + bswap r8 + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + mov rax, QWORD PTR [rcx+8] + mov r8, QWORD PTR [rcx] + bswap rax + bswap r8 + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + ret +sp_256_to_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 32 +; * Uses the movbe instruction which is optional. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_256_to_bin_movbe PROC + movbe rax, QWORD PTR [rcx+24] + movbe r8, QWORD PTR [rcx+16] + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + movbe rax, QWORD PTR [rcx+8] + movbe r8, QWORD PTR [rcx] + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + ret +sp_256_to_bin_movbe ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r Result of multiplication. +; * a First number to multiply. +; * b Second number to multiply. +; */ +_text SEGMENT READONLY PARA +sp_256_mul_avx2_4 PROC + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp + push rdi + push rsi + mov rbp, r8 + mov rdi, rdx + ; A[0] * B[0] + mov rdx, QWORD PTR [rbp] + mulx r9, r8, QWORD PTR [rdi] + ; A[2] * B[0] + mulx r11, r10, QWORD PTR [rdi+16] + ; A[1] * B[0] + mulx rsi, rax, QWORD PTR [rdi+8] + xor r15, r15 + adcx r9, rax + ; A[1] * B[3] + mov rdx, QWORD PTR [rbp+24] + mulx r13, r12, QWORD PTR [rdi+8] + adcx r10, rsi + ; A[0] * B[1] + mov rdx, QWORD PTR [rbp+8] + mulx rsi, rax, QWORD PTR [rdi] + adox r9, rax + ; A[2] * B[1] + mulx r14, rax, QWORD PTR [rdi+16] + adox r10, rsi + adcx r11, rax + ; A[1] * B[2] + mov rdx, QWORD PTR [rbp+16] + mulx rsi, rax, QWORD PTR [rdi+8] + adcx r12, r14 + adox r11, rax + adcx r13, r15 + adox r12, rsi + ; A[0] * B[2] + mulx rsi, rax, QWORD PTR [rdi] + adox r13, r15 + xor r14, r14 + adcx r10, rax + ; A[1] * B[1] + mov rdx, QWORD PTR [rbp+8] + mulx rax, rdx, QWORD PTR [rdi+8] + adcx r11, rsi + adox r10, rdx + ; A[3] * B[1] + mov rdx, QWORD PTR [rbp+8] + adox r11, rax + mulx rsi, rax, QWORD PTR [rdi+24] + adcx r12, rax + ; A[2] * B[2] + mov rdx, QWORD PTR [rbp+16] + mulx rax, rdx, QWORD PTR [rdi+16] + adcx r13, rsi + adox r12, rdx + ; A[3] * B[3] + mov rdx, QWORD PTR [rbp+24] + adox r13, rax + mulx rsi, rax, QWORD PTR [rdi+24] + adox r14, r15 + adcx r14, rax + ; A[0] * B[3] + mulx rax, rdx, QWORD PTR [rdi] + adcx r15, rsi + xor rsi, rsi + adcx r11, rdx + ; A[3] * B[0] + mov rdx, QWORD PTR [rdi+24] + adcx r12, rax + mulx rax, rbx, QWORD PTR [rbp] + adox r11, rbx + adox r12, rax + ; A[3] * B[2] + mulx rax, rdx, QWORD PTR [rbp+16] + adcx r13, rdx + ; A[2] * B[3] + mov rdx, QWORD PTR [rbp+24] + adcx r14, rax + mulx rdx, rax, QWORD PTR [rdi+16] + adcx r15, rsi + adox r13, rax + adox r14, rdx + adox r15, rsi + mov QWORD PTR [rcx], r8 + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov QWORD PTR [rcx+32], r12 + mov QWORD PTR [rcx+40], r13 + mov QWORD PTR [rcx+48], r14 + mov QWORD PTR [rcx+56], r15 + pop rsi + pop rdi + pop rbp + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + ret +sp_256_mul_avx2_4 ENDP +_text ENDS +ENDIF +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_256_sub_in_place_4 PROC + xor rax, rax + mov r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + sub QWORD PTR [rcx], r8 + sbb QWORD PTR [rcx+8], r9 + sbb QWORD PTR [rcx+16], r10 + sbb QWORD PTR [rcx+24], r11 + sbb rax, 0 + ret +sp_256_sub_in_place_4 ENDP +_text ENDS +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_256_mul_d_4 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+24], r10 + mov QWORD PTR [rcx+32], r11 + pop r12 + ret +sp_256_mul_d_4 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_256_mul_d_avx2_4 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+24], r12 + mov QWORD PTR [rcx+32], r11 + pop r13 + pop r12 + ret +sp_256_mul_d_avx2_4 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_256_word_asm_4 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_256_word_asm_4 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Multiply two Montogmery form numbers mod the modulus (prime). +; * (r = a * b mod m) +; * +; * r Result of multiplication. +; * a First number to multiply in Montogmery form. +; * b Second number to multiply in Montogmery form. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_mul_order_avx2_4 PROC + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp + push rdi + push rsi + mov rbp, r8 + mov rdi, rdx + ; A[0] * B[0] + mov rdx, QWORD PTR [rbp] + mulx r9, r8, QWORD PTR [rdi] + ; A[2] * B[0] + mulx r11, r10, QWORD PTR [rdi+16] + ; A[1] * B[0] + mulx rsi, rax, QWORD PTR [rdi+8] + xor r15, r15 + adcx r9, rax + ; A[1] * B[3] + mov rdx, QWORD PTR [rbp+24] + mulx r13, r12, QWORD PTR [rdi+8] + adcx r10, rsi + ; A[0] * B[1] + mov rdx, QWORD PTR [rbp+8] + mulx rsi, rax, QWORD PTR [rdi] + adox r9, rax + ; A[2] * B[1] + mulx r14, rax, QWORD PTR [rdi+16] + adox r10, rsi + adcx r11, rax + ; A[1] * B[2] + mov rdx, QWORD PTR [rbp+16] + mulx rsi, rax, QWORD PTR [rdi+8] + adcx r12, r14 + adox r11, rax + adcx r13, r15 + adox r12, rsi + ; A[0] * B[2] + mulx rsi, rax, QWORD PTR [rdi] + adox r13, r15 + xor r14, r14 + adcx r10, rax + ; A[1] * B[1] + mov rdx, QWORD PTR [rbp+8] + mulx rax, rdx, QWORD PTR [rdi+8] + adcx r11, rsi + adox r10, rdx + ; A[3] * B[1] + mov rdx, QWORD PTR [rbp+8] + adox r11, rax + mulx rsi, rax, QWORD PTR [rdi+24] + adcx r12, rax + ; A[2] * B[2] + mov rdx, QWORD PTR [rbp+16] + mulx rax, rdx, QWORD PTR [rdi+16] + adcx r13, rsi + adox r12, rdx + ; A[3] * B[3] + mov rdx, QWORD PTR [rbp+24] + adox r13, rax + mulx rsi, rax, QWORD PTR [rdi+24] + adox r14, r15 + adcx r14, rax + ; A[0] * B[3] + mulx rax, rdx, QWORD PTR [rdi] + adcx r15, rsi + xor rsi, rsi + adcx r11, rdx + ; A[3] * B[0] + mov rdx, QWORD PTR [rdi+24] + adcx r12, rax + mulx rax, rbx, QWORD PTR [rbp] + adox r11, rbx + adox r12, rax + ; A[3] * B[2] + mulx rax, rdx, QWORD PTR [rbp+16] + adcx r13, rdx + ; A[2] * B[3] + mov rdx, QWORD PTR [rbp+24] + adcx r14, rax + mulx rdx, rax, QWORD PTR [rdi+16] + adcx r15, rsi + adox r13, rax + adox r14, rdx + adox r15, rsi + ; Start Reduction + mov rbx, 14758798090332847183 + ; A[0] + mov rdx, rbx + imul rdx, r8 + mov rax, 17562291160714782033 + xor rbp, rbp + mulx rdi, rsi, rax + mov rax, 13611842547513532036 + adcx r8, rsi + adox r9, rdi + mulx rdi, rsi, rax + mov rax, 18446744073709551615 + adcx r9, rsi + adox r10, rdi + mulx rdi, rsi, rax + mov rax, 18446744069414584320 + adcx r10, rsi + adox r11, rdi + mulx rdi, rsi, rax + adcx r11, rsi + adox r12, rdi + adcx r12, rbp + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + ; A[1] + mov rdx, rbx + imul rdx, r9 + mov rax, 17562291160714782033 + xor rbp, rbp + mulx rdi, rsi, rax + mov rax, 13611842547513532036 + adcx r9, rsi + adox r10, rdi + mulx rdi, rsi, rax + mov rax, 18446744073709551615 + adcx r10, rsi + adox r11, rdi + mulx rdi, rsi, rax + mov rax, 18446744069414584320 + adcx r11, rsi + adox r12, rdi + mulx rdi, rsi, rax + adcx r12, rsi + adox r13, rdi + adcx r13, r8 + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + ; A[2] + mov rdx, rbx + imul rdx, r10 + mov rax, 17562291160714782033 + xor rbp, rbp + mulx rdi, rsi, rax + mov rax, 13611842547513532036 + adcx r10, rsi + adox r11, rdi + mulx rdi, rsi, rax + mov rax, 18446744073709551615 + adcx r11, rsi + adox r12, rdi + mulx rdi, rsi, rax + mov rax, 18446744069414584320 + adcx r12, rsi + adox r13, rdi + mulx rdi, rsi, rax + adcx r13, rsi + adox r14, rdi + adcx r14, r8 + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + ; A[3] + mov rdx, rbx + imul rdx, r11 + mov rax, 17562291160714782033 + xor rbp, rbp + mulx rdi, rsi, rax + mov rax, 13611842547513532036 + adcx r11, rsi + adox r12, rdi + mulx rdi, rsi, rax + mov rax, 18446744073709551615 + adcx r12, rsi + adox r13, rdi + mulx rdi, rsi, rax + mov rax, 18446744069414584320 + adcx r13, rsi + adox r14, rdi + mulx rdi, rsi, rax + adcx r14, rsi + adox r15, rdi + adcx r15, r8 + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + neg r8 + mov rax, 17562291160714782033 + mov rbx, 13611842547513532036 + and rax, r8 + mov rbp, 18446744069414584320 + and rbx, r8 + and rbp, r8 + sub r12, rax + sbb r13, rbx + mov QWORD PTR [rcx], r12 + sbb r14, r8 + mov QWORD PTR [rcx+8], r13 + sbb r15, rbp + mov QWORD PTR [rcx+16], r14 + mov QWORD PTR [rcx+24], r15 + pop rsi + pop rdi + pop rbp + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + ret +sp_256_mont_mul_order_avx2_4 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) +; * +; * r Result of squaring. +; * a Number to square in Montogmery form. +; */ +_text SEGMENT READONLY PARA +sp_256_mont_sqr_order_avx2_4 PROC + push rbp + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov rax, rdx + ; A[0] * A[1] + mov rdx, QWORD PTR [rax] + mov r15, QWORD PTR [rax+16] + mulx r10, r9, QWORD PTR [rax+8] + ; A[0] * A[3] + mulx r12, r11, QWORD PTR [rax+24] + ; A[2] * A[1] + mov rdx, r15 + mulx rbx, rsi, QWORD PTR [rax+8] + ; A[2] * A[3] + mulx r14, r13, QWORD PTR [rax+24] + xor r15, r15 + adox r11, rsi + adox r12, rbx + ; A[2] * A[0] + mulx rbx, rsi, QWORD PTR [rax] + ; A[1] * A[3] + mov rdx, QWORD PTR [rax+8] + adox r13, r15 + mulx r8, rdi, QWORD PTR [rax+24] + adcx r10, rsi + adox r14, r15 + adcx r11, rbx + adcx r12, rdi + adcx r13, r8 + adcx r14, r15 + ; Double with Carry Flag + xor r15, r15 + ; A[0] * A[0] + mov rdx, QWORD PTR [rax] + mulx rdi, r8, rdx + adcx r9, r9 + adcx r10, r10 + adox r9, rdi + ; A[1] * A[1] + mov rdx, QWORD PTR [rax+8] + mulx rbx, rsi, rdx + adcx r11, r11 + adox r10, rsi + ; A[2] * A[2] + mov rdx, QWORD PTR [rax+16] + mulx rsi, rdi, rdx + adcx r12, r12 + adox r11, rbx + adcx r13, r13 + adox r12, rdi + adcx r14, r14 + ; A[3] * A[3] + mov rdx, QWORD PTR [rax+24] + mulx rbx, rdi, rdx + adox r13, rsi + adcx r15, r15 + adox r14, rdi + adox r15, rbx + ; Start Reduction + mov rbx, 14758798090332847183 + ; A[0] + mov rdx, rbx + imul rdx, r8 + mov rdi, 17562291160714782033 + xor rbp, rbp + mulx rax, rsi, rdi + mov rdi, 13611842547513532036 + adcx r8, rsi + adox r9, rax + mulx rax, rsi, rdi + mov rdi, 18446744073709551615 + adcx r9, rsi + adox r10, rax + mulx rax, rsi, rdi + mov rdi, 18446744069414584320 + adcx r10, rsi + adox r11, rax + mulx rax, rsi, rdi + adcx r11, rsi + adox r12, rax + adcx r12, rbp + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + ; A[1] + mov rdx, rbx + imul rdx, r9 + mov rdi, 17562291160714782033 + xor rbp, rbp + mulx rax, rsi, rdi + mov rdi, 13611842547513532036 + adcx r9, rsi + adox r10, rax + mulx rax, rsi, rdi + mov rdi, 18446744073709551615 + adcx r10, rsi + adox r11, rax + mulx rax, rsi, rdi + mov rdi, 18446744069414584320 + adcx r11, rsi + adox r12, rax + mulx rax, rsi, rdi + adcx r12, rsi + adox r13, rax + adcx r13, r8 + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + ; A[2] + mov rdx, rbx + imul rdx, r10 + mov rdi, 17562291160714782033 + xor rbp, rbp + mulx rax, rsi, rdi + mov rdi, 13611842547513532036 + adcx r10, rsi + adox r11, rax + mulx rax, rsi, rdi + mov rdi, 18446744073709551615 + adcx r11, rsi + adox r12, rax + mulx rax, rsi, rdi + mov rdi, 18446744069414584320 + adcx r12, rsi + adox r13, rax + mulx rax, rsi, rdi + adcx r13, rsi + adox r14, rax + adcx r14, r8 + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + ; A[3] + mov rdx, rbx + imul rdx, r11 + mov rdi, 17562291160714782033 + xor rbp, rbp + mulx rax, rsi, rdi + mov rdi, 13611842547513532036 + adcx r11, rsi + adox r12, rax + mulx rax, rsi, rdi + mov rdi, 18446744073709551615 + adcx r12, rsi + adox r13, rax + mulx rax, rsi, rdi + mov rdi, 18446744069414584320 + adcx r13, rsi + adox r14, rax + mulx rax, rsi, rdi + adcx r14, rsi + adox r15, rax + adcx r15, r8 + mov r8, rbp + ; carry + adox r8, rbp + adcx r8, rbp + neg r8 + mov rdi, 17562291160714782033 + mov rbx, 13611842547513532036 + and rdi, r8 + mov rbp, 18446744069414584320 + and rbx, r8 + and rbp, r8 + sub r12, rdi + sbb r13, rbx + mov QWORD PTR [rcx], r12 + sbb r14, r8 + mov QWORD PTR [rcx+8], r13 + sbb r15, rbp + mov QWORD PTR [rcx+16], r14 + mov QWORD PTR [rcx+24], r15 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + ret +sp_256_mont_sqr_order_avx2_4 ENDP +_text ENDS +ENDIF +; /* Non-constant time modular inversion. +; * +; * @param [out] r Resulting number. +; * @param [in] a Number to invert. +; * @param [in] m Modulus. +; * @return MP_OKAY on success. +; */ +_text SEGMENT READONLY PARA +sp_256_mod_inv_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + sub rsp, 513 + mov r9, QWORD PTR [r8] + mov r10, QWORD PTR [r8+8] + mov r11, QWORD PTR [r8+16] + mov r12, QWORD PTR [r8+24] + mov r13, QWORD PTR [rdx] + mov r14, QWORD PTR [rdx+8] + mov r15, QWORD PTR [rdx+16] + mov rdi, QWORD PTR [rdx+24] + mov rsi, 0 + test r13b, 1 + jnz L_256_mod_inv_4_v_even_end +L_256_mod_inv_4_v_even_start: + shrd r13, r14, 1 + shrd r14, r15, 1 + shrd r15, rdi, 1 + shr rdi, 1 + mov BYTE PTR [rsp+rsi], 1 + inc rsi + test r13b, 1 + jz L_256_mod_inv_4_v_even_start +L_256_mod_inv_4_v_even_end: +L_256_mod_inv_4_uv_start: + cmp r12, rdi + jb L_256_mod_inv_4_uv_v + ja L_256_mod_inv_4_uv_u + cmp r11, r15 + jb L_256_mod_inv_4_uv_v + ja L_256_mod_inv_4_uv_u + cmp r10, r14 + jb L_256_mod_inv_4_uv_v + ja L_256_mod_inv_4_uv_u + cmp r9, r13 + jb L_256_mod_inv_4_uv_v +L_256_mod_inv_4_uv_u: + mov BYTE PTR [rsp+rsi], 2 + inc rsi + sub r9, r13 + sbb r10, r14 + sbb r11, r15 + sbb r12, rdi + shrd r9, r10, 1 + shrd r10, r11, 1 + shrd r11, r12, 1 + shr r12, 1 + test r9b, 1 + jnz L_256_mod_inv_4_usubv_even_end +L_256_mod_inv_4_usubv_even_start: + shrd r9, r10, 1 + shrd r10, r11, 1 + shrd r11, r12, 1 + shr r12, 1 + mov BYTE PTR [rsp+rsi], 0 + inc rsi + test r9b, 1 + jz L_256_mod_inv_4_usubv_even_start +L_256_mod_inv_4_usubv_even_end: + cmp r9, 1 + jne L_256_mod_inv_4_uv_start + mov rdx, r10 + or rdx, r11 + jne L_256_mod_inv_4_uv_start + or rdx, r12 + jne L_256_mod_inv_4_uv_start + mov al, 1 + jmp L_256_mod_inv_4_uv_end +L_256_mod_inv_4_uv_v: + mov BYTE PTR [rsp+rsi], 3 + inc rsi + sub r13, r9 + sbb r14, r10 + sbb r15, r11 + sbb rdi, r12 + shrd r13, r14, 1 + shrd r14, r15, 1 + shrd r15, rdi, 1 + shr rdi, 1 + test r13b, 1 + jnz L_256_mod_inv_4_vsubu_even_end +L_256_mod_inv_4_vsubu_even_start: + shrd r13, r14, 1 + shrd r14, r15, 1 + shrd r15, rdi, 1 + shr rdi, 1 + mov BYTE PTR [rsp+rsi], 1 + inc rsi + test r13b, 1 + jz L_256_mod_inv_4_vsubu_even_start +L_256_mod_inv_4_vsubu_even_end: + cmp r13, 1 + jne L_256_mod_inv_4_uv_start + mov rdx, r14 + or rdx, r15 + jne L_256_mod_inv_4_uv_start + or rdx, rdi + jne L_256_mod_inv_4_uv_start + mov al, 0 +L_256_mod_inv_4_uv_end: + mov r9, QWORD PTR [r8] + mov r10, QWORD PTR [r8+8] + mov r11, QWORD PTR [r8+16] + mov r12, QWORD PTR [r8+24] + mov r13, 1 + xor r14, r14 + xor r15, r15 + xor rdi, rdi + mov BYTE PTR [rsp+rsi], 7 + mov dl, BYTE PTR [rsp] + mov rsi, 1 + cmp dl, 1 + je L_256_mod_inv_4_op_div2_d + jl L_256_mod_inv_4_op_div2_b + cmp dl, 3 + je L_256_mod_inv_4_op_d_sub_b + jl L_256_mod_inv_4_op_b_sub_d + jmp L_256_mod_inv_4_op_end +L_256_mod_inv_4_op_b_sub_d: + sub r9, r13 + sbb r10, r14 + sbb r11, r15 + sbb r12, rdi + jnc L_256_mod_inv_4_op_div2_b + add r9, QWORD PTR [r8] + adc r10, QWORD PTR [r8+8] + adc r11, QWORD PTR [r8+16] + adc r12, QWORD PTR [r8+24] +L_256_mod_inv_4_op_div2_b: + test r9b, 1 + mov rdx, 0 + jz L_256_mod_inv_4_op_div2_b_mod + add r9, QWORD PTR [r8] + adc r10, QWORD PTR [r8+8] + adc r11, QWORD PTR [r8+16] + adc r12, QWORD PTR [r8+24] + adc rdx, 0 +L_256_mod_inv_4_op_div2_b_mod: + shrd r9, r10, 1 + shrd r10, r11, 1 + shrd r11, r12, 1 + shrd r12, rdx, 1 + mov dl, BYTE PTR [rsp+rsi] + inc rsi + cmp dl, 1 + je L_256_mod_inv_4_op_div2_d + jl L_256_mod_inv_4_op_div2_b + cmp dl, 3 + je L_256_mod_inv_4_op_d_sub_b + jl L_256_mod_inv_4_op_b_sub_d + jmp L_256_mod_inv_4_op_end +L_256_mod_inv_4_op_d_sub_b: + sub r13, r9 + sbb r14, r10 + sbb r15, r11 + sbb rdi, r12 + jnc L_256_mod_inv_4_op_div2_d + add r13, QWORD PTR [r8] + adc r14, QWORD PTR [r8+8] + adc r15, QWORD PTR [r8+16] + adc rdi, QWORD PTR [r8+24] +L_256_mod_inv_4_op_div2_d: + test r13b, 1 + mov rdx, 0 + jz L_256_mod_inv_4_op_div2_d_mod + add r13, QWORD PTR [r8] + adc r14, QWORD PTR [r8+8] + adc r15, QWORD PTR [r8+16] + adc rdi, QWORD PTR [r8+24] + adc rdx, 0 +L_256_mod_inv_4_op_div2_d_mod: + shrd r13, r14, 1 + shrd r14, r15, 1 + shrd r15, rdi, 1 + shrd rdi, rdx, 1 + mov dl, BYTE PTR [rsp+rsi] + inc rsi + cmp dl, 1 + je L_256_mod_inv_4_op_div2_d + jl L_256_mod_inv_4_op_div2_b + cmp dl, 3 + je L_256_mod_inv_4_op_d_sub_b + jl L_256_mod_inv_4_op_b_sub_d +L_256_mod_inv_4_op_end: + cmp al, 1 + jne L_256_mod_inv_4_store_d + mov QWORD PTR [rcx], r9 + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + jmp L_256_mod_inv_4_store_end +L_256_mod_inv_4_store_d: + mov QWORD PTR [rcx], r13 + mov QWORD PTR [rcx+8], r14 + mov QWORD PTR [rcx+16], r15 + mov QWORD PTR [rcx+24], rdi +L_256_mod_inv_4_store_end: + add rsp, 513 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mod_inv_4 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_order DWORD 6497617,32001851,62711546,67108863,67043328,0,0,0,41070783,45522014,67108863,1023,4194303,0,0,0 +ptr_L_sp256_mod_inv_avx2_4_order QWORD L_sp256_mod_inv_avx2_4_order +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_one QWORD 1, 0, + 0, 0 +ptr_L_sp256_mod_inv_avx2_4_one QWORD L_sp256_mod_inv_avx2_4_one +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_all_one DWORD 1,1,1,1,1,1,1,1 +ptr_L_sp256_mod_inv_avx2_4_all_one QWORD L_sp256_mod_inv_avx2_4_all_one +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_mask01111 DWORD 0,1,1,1,1,0,0,0 +ptr_L_sp256_mod_inv_avx2_4_mask01111 QWORD L_sp256_mod_inv_avx2_4_mask01111 +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_down_one_dword DWORD 1,2,3,4,5,6,7,7 +ptr_L_sp256_mod_inv_avx2_4_down_one_dword QWORD L_sp256_mod_inv_avx2_4_down_one_dword +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_neg DWORD 0,0,0,0,2147483648,0,0,0 +ptr_L_sp256_mod_inv_avx2_4_neg QWORD L_sp256_mod_inv_avx2_4_neg +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_up_one_dword DWORD 7,0,1,2,3,7,7,7 +ptr_L_sp256_mod_inv_avx2_4_up_one_dword QWORD L_sp256_mod_inv_avx2_4_up_one_dword +_DATA ENDS +_DATA SEGMENT +ALIGN 16 +L_sp256_mod_inv_avx2_4_mask26 DWORD 67108863,67108863,67108863,67108863,67108863,0,0,0 +ptr_L_sp256_mod_inv_avx2_4_mask26 QWORD L_sp256_mod_inv_avx2_4_mask26 +_DATA ENDS +; /* Non-constant time modular inversion. +; * +; * @param [out] r Resulting number. +; * @param [in] a Number to invert. +; * @param [in] m Modulus. +; * @return MP_OKAY on success. +; */ +_text SEGMENT READONLY PARA +sp_256_mod_inv_avx2_4 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov rax, QWORD PTR [r8] + mov r9, QWORD PTR [r8+8] + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + mov r12, QWORD PTR [rdx] + mov r13, QWORD PTR [rdx+8] + mov r14, QWORD PTR [rdx+16] + mov r15, QWORD PTR [rdx+24] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_order + vmovupd ymm6, [rbx] + vmovupd ymm7, [rbx+32] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_one + vmovupd ymm8, [rbx] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_mask01111 + vmovupd ymm9, [rbx] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_all_one + vmovupd ymm10, [rbx] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_down_one_dword + vmovupd ymm11, [rbx] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_neg + vmovupd ymm12, [rbx] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_up_one_dword + vmovupd ymm13, [rbx] + mov rbx, ptr_L_sp256_mod_inv_avx2_4_mask26 + vmovupd ymm14, [rbx] + vpxor xmm0, xmm0, xmm0 + vpxor xmm1, xmm1, xmm1 + vmovdqu ymm2, ymm8 + vpxor xmm3, xmm3, xmm3 + test r12b, 1 + jnz L_256_mod_inv_avx2_4_v_even_end +L_256_mod_inv_avx2_4_v_even_start: + shrd r12, r13, 1 + shrd r13, r14, 1 + shrd r14, r15, 1 + shr r15, 1 + vptest ymm2, ymm8 + jz L_256_mod_inv_avx2_4_v_even_shr1 + vpaddd ymm2, ymm2, ymm6 + vpaddd ymm3, ymm3, ymm7 +L_256_mod_inv_avx2_4_v_even_shr1: + vpand ymm4, ymm2, ymm9 + vpand ymm5, ymm3, ymm10 + vpermd ymm4, ymm11, ymm4 + vpsrad ymm2, ymm2, 1 + vpsrad ymm3, ymm3, 1 + vpslld ymm5, ymm5, 25 + vpslld xmm4, xmm4, 25 + vpaddd ymm2, ymm2, ymm5 + vpaddd ymm3, ymm3, ymm4 + test r12b, 1 + jz L_256_mod_inv_avx2_4_v_even_start +L_256_mod_inv_avx2_4_v_even_end: +L_256_mod_inv_avx2_4_uv_start: + cmp r11, r15 + jb L_256_mod_inv_avx2_4_uv_v + ja L_256_mod_inv_avx2_4_uv_u + cmp r10, r14 + jb L_256_mod_inv_avx2_4_uv_v + ja L_256_mod_inv_avx2_4_uv_u + cmp r9, r13 + jb L_256_mod_inv_avx2_4_uv_v + ja L_256_mod_inv_avx2_4_uv_u + cmp rax, r12 + jb L_256_mod_inv_avx2_4_uv_v +L_256_mod_inv_avx2_4_uv_u: + sub rax, r12 + sbb r9, r13 + vpsubd ymm0, ymm0, ymm2 + sbb r10, r14 + vpsubd ymm1, ymm1, ymm3 + sbb r11, r15 + vptest ymm1, ymm12 + jz L_256_mod_inv_avx2_4_usubv_done_neg + vpaddd ymm0, ymm0, ymm6 + vpaddd ymm1, ymm1, ymm7 +L_256_mod_inv_avx2_4_usubv_done_neg: +L_256_mod_inv_avx2_4_usubv_shr1: + shrd rax, r9, 1 + shrd r9, r10, 1 + shrd r10, r11, 1 + shr r11, 1 + vptest ymm0, ymm8 + jz L_256_mod_inv_avx2_4_usubv_sub_shr1 + vpaddd ymm0, ymm0, ymm6 + vpaddd ymm1, ymm1, ymm7 +L_256_mod_inv_avx2_4_usubv_sub_shr1: + vpand ymm4, ymm0, ymm9 + vpand ymm5, ymm1, ymm10 + vpermd ymm4, ymm11, ymm4 + vpsrad ymm0, ymm0, 1 + vpsrad ymm1, ymm1, 1 + vpslld ymm5, ymm5, 25 + vpslld xmm4, xmm4, 25 + vpaddd ymm0, ymm0, ymm5 + vpaddd ymm1, ymm1, ymm4 + test al, 1 + jz L_256_mod_inv_avx2_4_usubv_shr1 + cmp rax, 1 + jne L_256_mod_inv_avx2_4_uv_start + mov rdx, r9 + or rdx, r10 + jne L_256_mod_inv_avx2_4_uv_start + or rdx, r11 + jne L_256_mod_inv_avx2_4_uv_start + vpsrad ymm5, ymm1, 26 + vpsrad ymm4, ymm0, 26 + vpermd ymm5, ymm13, ymm5 + vpand ymm0, ymm0, ymm14 + vpand ymm1, ymm1, ymm14 + vpaddd ymm0, ymm0, ymm5 + vpaddd ymm1, ymm1, ymm4 + vpsrad ymm5, ymm1, 26 + vpsrad ymm4, ymm0, 26 + vpermd ymm5, ymm13, ymm5 + vpand ymm0, ymm0, ymm14 + vpand ymm1, ymm1, ymm14 + vpaddd ymm0, ymm0, ymm5 + vpaddd ymm1, ymm1, ymm4 + vpextrd eax, xmm0, 0 + vpextrd r10d, xmm0, 1 + vpextrd r12d, xmm0, 2 + vpextrd r14d, xmm0, 3 + vextracti128 xmm0, ymm0, 1 + vpextrd r9d, xmm1, 0 + vpextrd r11d, xmm1, 1 + vpextrd r13d, xmm1, 2 + vpextrd r15d, xmm1, 3 + vextracti128 xmm1, ymm1, 1 + vpextrd edi, xmm0, 0 + vpextrd esi, xmm1, 0 + jmp L_256_mod_inv_avx2_4_store_done +L_256_mod_inv_avx2_4_uv_v: + sub r12, rax + sbb r13, r9 + vpsubd ymm2, ymm2, ymm0 + sbb r14, r10 + vpsubd ymm3, ymm3, ymm1 + sbb r15, r11 + vptest ymm3, ymm12 + jz L_256_mod_inv_avx2_4_vsubu_done_neg + vpaddd ymm2, ymm2, ymm6 + vpaddd ymm3, ymm3, ymm7 +L_256_mod_inv_avx2_4_vsubu_done_neg: +L_256_mod_inv_avx2_4_vsubu_shr1: + shrd r12, r13, 1 + shrd r13, r14, 1 + shrd r14, r15, 1 + shr r15, 1 + vptest ymm2, ymm8 + jz L_256_mod_inv_avx2_4_vsubu_sub_shr1 + vpaddd ymm2, ymm2, ymm6 + vpaddd ymm3, ymm3, ymm7 +L_256_mod_inv_avx2_4_vsubu_sub_shr1: + vpand ymm4, ymm2, ymm9 + vpand ymm5, ymm3, ymm10 + vpermd ymm4, ymm11, ymm4 + vpsrad ymm2, ymm2, 1 + vpsrad ymm3, ymm3, 1 + vpslld ymm5, ymm5, 25 + vpslld xmm4, xmm4, 25 + vpaddd ymm2, ymm2, ymm5 + vpaddd ymm3, ymm3, ymm4 + test r12b, 1 + jz L_256_mod_inv_avx2_4_vsubu_shr1 + cmp r12, 1 + jne L_256_mod_inv_avx2_4_uv_start + mov rdx, r13 + or rdx, r14 + jne L_256_mod_inv_avx2_4_uv_start + or rdx, r15 + jne L_256_mod_inv_avx2_4_uv_start + vpsrad ymm5, ymm3, 26 + vpsrad ymm4, ymm2, 26 + vpermd ymm5, ymm13, ymm5 + vpand ymm2, ymm2, ymm14 + vpand ymm3, ymm3, ymm14 + vpaddd ymm2, ymm2, ymm5 + vpaddd ymm3, ymm3, ymm4 + vpsrad ymm5, ymm3, 26 + vpsrad ymm4, ymm2, 26 + vpermd ymm5, ymm13, ymm5 + vpand ymm2, ymm2, ymm14 + vpand ymm3, ymm3, ymm14 + vpaddd ymm2, ymm2, ymm5 + vpaddd ymm3, ymm3, ymm4 + vpextrd eax, xmm2, 0 + vpextrd r10d, xmm2, 1 + vpextrd r12d, xmm2, 2 + vpextrd r14d, xmm2, 3 + vextracti128 xmm2, ymm2, 1 + vpextrd r9d, xmm3, 0 + vpextrd r11d, xmm3, 1 + vpextrd r13d, xmm3, 2 + vpextrd r15d, xmm3, 3 + vextracti128 xmm3, ymm3, 1 + vpextrd edi, xmm2, 0 + vpextrd esi, xmm3, 0 +L_256_mod_inv_avx2_4_store_done: + movsxd rax, eax + shl r9, 26 + add rax, r9 + movsxd r10, r10d + shl r11, 26 + add r10, r11 + movsxd r12, r12d + shl r13, 26 + add r12, r13 + movsxd r14, r14d + shl r15, 26 + add r14, r15 + movsxd rdi, edi + shl rsi, 26 + add rdi, rsi + mov r9, r10 + mov r11, r12 + mov r13, r14 + shl r9, 52 + sar r10, 12 + shl r11, 40 + sar r12, 24 + shl r13, 28 + sar r14, 36 + shl rdi, 16 + add rax, r9 + adc r10, r11 + adc r12, r13 + adc r14, rdi + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r14 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_256_mod_inv_avx2_4 ENDP +_text ENDS +ENDIF +ENDIF +IFDEF WOLFSSL_SP_384 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_mul_6 PROC + push r12 + mov r9, rdx + sub rsp, 48 + ; A[0] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9] + xor r12, r12 + mov QWORD PTR [rsp], rax + mov r11, rdx + ; A[0] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+8], r11 + ; A[0] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+16], r12 + ; A[0] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+24], r10 + ; A[0] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+32], r11 + ; A[0] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+40], r12 + ; A[1] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+8] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+48], r10 + ; A[2] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+16] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+56], r11 + ; A[3] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+24] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+64], r12 + ; A[4] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+32] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+72], r10 + ; A[5] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + mov QWORD PTR [rcx+80], r11 + mov QWORD PTR [rcx+88], r12 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r10, QWORD PTR [rsp+16] + mov r11, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + add rsp, 48 + pop r12 + ret +sp_384_mul_6 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_sqr_6 PROC + push r12 + push r13 + push r14 + mov r8, rdx + sub rsp, 48 + ; A[0] * A[0] + mov rax, QWORD PTR [r8] + mul rax + xor r11, r11 + mov QWORD PTR [rsp], rax + mov r10, rdx + ; A[0] * A[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+8], r10 + ; A[0] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[1] * A[1] + mov rax, QWORD PTR [r8+8] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rsp+16], r11 + ; A[0] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[1] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8+8] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+24], r9 + ; A[0] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[1] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+8] + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[2] * A[2] + mov rax, QWORD PTR [r8+16] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+32], r10 + ; A[0] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+40], r11 + ; A[1] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+8] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[2] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+16] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[3] * A[3] + mov rax, QWORD PTR [r8+24] + mul rax + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+48], r9 + ; A[2] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+16] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[3] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+24] + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rcx+56], r10 + ; A[3] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+24] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[4] * A[4] + mov rax, QWORD PTR [r8+32] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+64], r11 + ; A[4] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+32] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+72], r9 + ; A[5] * A[5] + mov rax, QWORD PTR [r8+40] + mul rax + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r12, QWORD PTR [rsp+16] + mov r13, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + add rsp, 48 + pop r14 + pop r13 + pop r12 + ret +sp_384_sqr_6 ENDP +_text ENDS +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_add_6 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov QWORD PTR [rcx+40], r10 + adc rax, 0 + ret +sp_384_add_6 ENDP +_text ENDS +; /* Sub b from a into r. (r = a - b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_sub_6 PROC + push r12 + push r13 + push r14 + xor rax, rax + mov r9, QWORD PTR [rdx] + mov r10, QWORD PTR [rdx+8] + mov r11, QWORD PTR [rdx+16] + mov r12, QWORD PTR [rdx+24] + mov r13, QWORD PTR [rdx+32] + mov r14, QWORD PTR [rdx+40] + sub r9, QWORD PTR [r8] + sbb r10, QWORD PTR [r8+8] + sbb r11, QWORD PTR [r8+16] + sbb r12, QWORD PTR [r8+24] + sbb r13, QWORD PTR [r8+32] + sbb r14, QWORD PTR [r8+40] + mov QWORD PTR [rcx], r9 + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + mov QWORD PTR [rcx+32], r13 + mov QWORD PTR [rcx+40], r14 + sbb rax, 0 + pop r14 + pop r13 + pop r12 + ret +sp_384_sub_6 ENDP +_text ENDS +; /* Conditionally copy a into r using the mask m. +; * m is -1 to copy and 0 when not. +; * +; * r A single precision number to copy over. +; * a A single precision number to copy. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_384_cond_copy_6 PROC + push r12 + push r13 + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [rcx+16] + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rcx+32] + mov r13, QWORD PTR [rcx+40] + xor rax, QWORD PTR [rdx] + xor r9, QWORD PTR [rdx+8] + xor r10, QWORD PTR [rdx+16] + xor r11, QWORD PTR [rdx+24] + xor r12, QWORD PTR [rdx+32] + xor r13, QWORD PTR [rdx+40] + and rax, r8 + and r9, r8 + and r10, r8 + and r11, r8 + and r12, r8 + and r13, r8 + xor QWORD PTR [rcx], rax + xor QWORD PTR [rcx+8], r9 + xor QWORD PTR [rcx+16], r10 + xor QWORD PTR [rcx+24], r11 + xor QWORD PTR [rcx+32], r12 + xor QWORD PTR [rcx+40], r13 + pop r13 + pop r12 + ret +sp_384_cond_copy_6 ENDP +_text ENDS +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_384_cond_sub_6 PROC + sub rsp, 48 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov QWORD PTR [rcx+40], r11 + sbb rax, 0 + add rsp, 48 + ret +sp_384_cond_sub_6 ENDP +_text ENDS +; /* Reduce the number back to 384 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_384_mont_reduce_6 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r12, QWORD PTR [rcx] + mov r13, QWORD PTR [rcx+8] + mov r14, QWORD PTR [rcx+16] + mov r15, QWORD PTR [rcx+24] + mov rdi, QWORD PTR [rcx+32] + mov rsi, QWORD PTR [rcx+40] + xor r11, r11 + ; a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp) + mov rbx, QWORD PTR [rcx+48] + mov rbp, QWORD PTR [rcx+56] + mov rdx, r12 + mov rax, r13 + shld rax, rdx, 32 + shl rdx, 32 + add rdx, r12 + adc rax, r13 + add rax, r12 + mov r8, rdx + mov r9, rax + mov r10, rax + shld r9, r8, 32 + shl r8, 32 + shr r10, 32 + add r12, r8 + adc r13, r9 + adc r14, r10 + adc r15, 0 + adc rdi, 0 + adc rsi, 0 + adc rbx, rdx + adc rbp, rax + adc r11, 0 + add r8, rax + adc r9, rdx + adc r10, rax + mov rax, 0 + adc rax, 0 + sub r14, r9 + sbb r15, r10 + sbb rdi, rax + sbb rsi, 0 + sbb rbx, 0 + sbb rbp, 0 + sbb r11, 0 + ; a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp) + mov r12, QWORD PTR [rcx+64] + mov r13, QWORD PTR [rcx+72] + mov rdx, r14 + mov rax, r15 + shld rax, rdx, 32 + shl rdx, 32 + add rdx, r14 + adc rax, r15 + add rax, r14 + mov r8, rdx + mov r9, rax + mov r10, rax + shld r9, r8, 32 + shl r8, 32 + shr r10, 32 + add r12, r11 + adc r13, 0 + mov r11, 0 + adc r11, 0 + add r14, r8 + adc r15, r9 + adc rdi, r10 + adc rsi, 0 + adc rbx, 0 + adc rbp, 0 + adc r12, rdx + adc r13, rax + adc r11, 0 + add r8, rax + adc r9, rdx + adc r10, rax + mov rax, 0 + adc rax, 0 + sub rdi, r9 + sbb rsi, r10 + sbb rbx, rax + sbb rbp, 0 + sbb r12, 0 + sbb r13, 0 + sbb r11, 0 + ; a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp) + mov r14, QWORD PTR [rcx+80] + mov r15, QWORD PTR [rcx+88] + mov rdx, rdi + mov rax, rsi + shld rax, rdx, 32 + shl rdx, 32 + add rdx, rdi + adc rax, rsi + add rax, rdi + mov r8, rdx + mov r9, rax + mov r10, rax + shld r9, r8, 32 + shl r8, 32 + shr r10, 32 + add r14, r11 + adc r15, 0 + mov r11, 0 + adc r11, 0 + add rdi, r8 + adc rsi, r9 + adc rbx, r10 + adc rbp, 0 + adc r12, 0 + adc r13, 0 + adc r14, rdx + adc r15, rax + adc r11, 0 + add r8, rax + adc r9, rdx + adc r10, rax + mov rax, 0 + adc rax, 0 + sub rbx, r9 + sbb rbp, r10 + sbb r12, rax + sbb r13, 0 + sbb r14, 0 + sbb r15, 0 + sbb r11, 0 + ; Subtract mod if carry + neg r11 + mov r10, 18446744073709551614 + mov r8, r11 + mov r9, r11 + shr r8, 32 + shl r9, 32 + and r10, r11 + sub rbx, r8 + sbb rbp, r9 + sbb r12, r10 + sbb r13, r11 + sbb r14, r11 + sbb r15, r11 + mov QWORD PTR [rcx], rbx + mov QWORD PTR [rcx+8], rbp + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + mov QWORD PTR [rcx+32], r14 + mov QWORD PTR [rcx+40], r15 + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_384_mont_reduce_6 ENDP +_text ENDS +; /* Reduce the number back to 384 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_384_mont_reduce_order_6 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 6 + mov r10, 6 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_384_mont_loop_order_6: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc QWORD PTR [rcx+48], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_384_mont_loop_order_6 + mov QWORD PTR [rcx], r15 + mov QWORD PTR [rcx+8], rdi + neg rsi +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 48 + call sp_384_cond_sub_6 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_384_mont_reduce_order_6 ENDP +_text ENDS +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_384_cmp_6 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_384_cmp_6 ENDP +_text ENDS +; /* Add a to a into r. (r = a + a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_dbl_6 PROC + mov r8, QWORD PTR [rdx] + xor rax, rax + add r8, r8 + mov r9, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r8 + adc r9, r9 + mov r8, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r9 + adc r8, r8 + mov r9, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r8 + adc r9, r9 + mov QWORD PTR [rcx+40], r9 + adc rax, 0 + ret +sp_384_dbl_6 ENDP +_text ENDS +; /* Conditionally add a and b using the mask m. +; * m is -1 to add and 0 when not. +; * +; * r A single precision number representing conditional add result. +; * a A single precision number to add with. +; * b A single precision number to add. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_384_cond_add_6 PROC + sub rsp, 48 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + add r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + adc r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + adc r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + adc r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + adc r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + adc r11, r8 + mov QWORD PTR [rcx+32], r10 + mov QWORD PTR [rcx+40], r11 + adc rax, 0 + add rsp, 48 + ret +sp_384_cond_add_6 ENDP +_text ENDS +; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_384_div2_6 PROC + push r12 + push r13 + sub rsp, 48 + mov r13, QWORD PTR [rdx] + xor r12, r12 + mov rax, r13 + and r13, 1 + neg r13 + mov r10, QWORD PTR [r8] + and r10, r13 + mov QWORD PTR [rsp], r10 + mov r10, QWORD PTR [r8+8] + and r10, r13 + mov QWORD PTR [rsp+8], r10 + mov r10, QWORD PTR [r8+16] + and r10, r13 + mov QWORD PTR [rsp+16], r10 + mov r10, QWORD PTR [r8+24] + and r10, r13 + mov QWORD PTR [rsp+24], r10 + mov r10, QWORD PTR [r8+32] + and r10, r13 + mov QWORD PTR [rsp+32], r10 + mov r10, QWORD PTR [r8+40] + and r10, r13 + mov QWORD PTR [rsp+40], r10 + add QWORD PTR [rsp], rax + mov rax, QWORD PTR [rdx+8] + adc QWORD PTR [rsp+8], rax + mov rax, QWORD PTR [rdx+16] + adc QWORD PTR [rsp+16], rax + mov rax, QWORD PTR [rdx+24] + adc QWORD PTR [rsp+24], rax + mov rax, QWORD PTR [rdx+32] + adc QWORD PTR [rsp+32], rax + mov rax, QWORD PTR [rdx+40] + adc QWORD PTR [rsp+40], rax + adc r12, 0 + mov rax, QWORD PTR [rsp] + mov r9, QWORD PTR [rsp+8] + shrd rax, r9, 1 + mov QWORD PTR [rcx], rax + mov rax, QWORD PTR [rsp+16] + shrd r9, rax, 1 + mov QWORD PTR [rcx+8], r9 + mov r9, QWORD PTR [rsp+24] + shrd rax, r9, 1 + mov QWORD PTR [rcx+16], rax + mov rax, QWORD PTR [rsp+32] + shrd r9, rax, 1 + mov QWORD PTR [rcx+24], r9 + mov r9, QWORD PTR [rsp+40] + shrd rax, r9, 1 + mov QWORD PTR [rcx+32], rax + shrd r9, r12, 1 + mov QWORD PTR [rcx+40], r9 + add rsp, 48 + pop r13 + pop r12 + ret +sp_384_div2_6 ENDP +_text ENDS +IFNDEF WC_NO_CACHE_RESISTANT +; /* Touch each possible point that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of point to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_384_get_point_33_6 PROC + mov rax, 1 + movd xmm13, r8d + add rdx, 296 + movd xmm15, eax + mov rax, 32 + pshufd xmm15, xmm15, 0 + pshufd xmm13, xmm13, 0 + pxor xmm14, xmm14 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + pxor xmm3, xmm3 + pxor xmm4, xmm4 + pxor xmm5, xmm5 + movdqa xmm14, xmm15 +L_384_get_point_33_6_start: + movdqa xmm12, xmm14 + paddd xmm14, xmm15 + pcmpeqd xmm12, xmm13 + movdqu xmm6, [rdx] + movdqu xmm7, [rdx+16] + movdqu xmm8, [rdx+32] + movdqu xmm9, [rdx+96] + movdqu xmm10, [rdx+112] + movdqu xmm11, [rdx+128] + add rdx, 296 + pand xmm6, xmm12 + pand xmm7, xmm12 + pand xmm8, xmm12 + pand xmm9, xmm12 + pand xmm10, xmm12 + pand xmm11, xmm12 + por xmm0, xmm6 + por xmm1, xmm7 + por xmm2, xmm8 + por xmm3, xmm9 + por xmm4, xmm10 + por xmm5, xmm11 + dec rax + jnz L_384_get_point_33_6_start + movdqu [rcx], xmm0 + movdqu [rcx+16], xmm1 + movdqu [rcx+32], xmm2 + movdqu [rcx+96], xmm3 + movdqu [rcx+112], xmm4 + movdqu [rcx+128], xmm5 + mov rax, 1 + movd xmm13, r8d + sub rdx, 9472 + movd xmm15, eax + mov rax, 32 + pshufd xmm15, xmm15, 0 + pshufd xmm13, xmm13, 0 + pxor xmm14, xmm14 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + movdqa xmm14, xmm15 +L_384_get_point_33_6_start_2: + movdqa xmm12, xmm14 + paddd xmm14, xmm15 + pcmpeqd xmm12, xmm13 + movdqu xmm6, [rdx+192] + movdqu xmm7, [rdx+208] + movdqu xmm8, [rdx+224] + add rdx, 296 + pand xmm6, xmm12 + pand xmm7, xmm12 + pand xmm8, xmm12 + por xmm0, xmm6 + por xmm1, xmm7 + por xmm2, xmm8 + dec rax + jnz L_384_get_point_33_6_start_2 + movdqu [rcx+192], xmm0 + movdqu [rcx+208], xmm1 + movdqu [rcx+224], xmm2 + ret +sp_384_get_point_33_6 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Touch each possible point that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of point to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_384_get_point_33_avx2_6 PROC + mov rax, 1 + movd xmm13, r8d + add rdx, 296 + movd xmm15, eax + mov rax, 32 + vpxor ymm14, ymm14, ymm14 + vpermd ymm13, ymm14, ymm13 + vpermd ymm15, ymm14, ymm15 + vpxor ymm0, ymm0, ymm0 + vpxor xmm1, xmm1, xmm1 + vpxor ymm2, ymm2, ymm2 + vpxor xmm3, xmm3, xmm3 + vpxor ymm4, ymm4, ymm4 + vpxor xmm5, xmm5, xmm5 + vmovdqa ymm14, ymm15 +L_384_get_point_33_avx2_6_start: + vpcmpeqd ymm12, ymm14, ymm13 + vpaddd ymm14, ymm14, ymm15 + vmovupd ymm6, [rdx] + vmovdqu xmm7, OWORD PTR [rdx+32] + vmovupd ymm8, [rdx+96] + vmovdqu xmm9, OWORD PTR [rdx+128] + vmovupd ymm10, [rdx+192] + vmovdqu xmm11, OWORD PTR [rdx+224] + add rdx, 296 + vpand ymm6, ymm6, ymm12 + vpand xmm7, xmm7, xmm12 + vpand ymm8, ymm8, ymm12 + vpand xmm9, xmm9, xmm12 + vpand ymm10, ymm10, ymm12 + vpand xmm11, xmm11, xmm12 + vpor ymm0, ymm0, ymm6 + vpor xmm1, xmm1, xmm7 + vpor ymm2, ymm2, ymm8 + vpor xmm3, xmm3, xmm9 + vpor ymm4, ymm4, ymm10 + vpor xmm5, xmm5, xmm11 + dec rax + jnz L_384_get_point_33_avx2_6_start + vmovupd YMMWORD PTR [rcx], ymm0 + vmovdqu [rcx+32], xmm1 + vmovupd YMMWORD PTR [rcx+96], ymm2 + vmovdqu [rcx+128], xmm3 + vmovupd YMMWORD PTR [rcx+192], ymm4 + vmovdqu [rcx+224], xmm5 + ret +sp_384_get_point_33_avx2_6 ENDP +_text ENDS +ENDIF +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r Result of multiplication. +; * a First number to multiply. +; * b Second number to multiply. +; */ +_text SEGMENT READONLY PARA +sp_384_mul_avx2_6 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov rax, rdx + sub rsp, 40 + xor rbx, rbx + mov rdx, QWORD PTR [rax] + ; A[0] * B[0] + mulx r12, r11, QWORD PTR [r8] + ; A[0] * B[1] + mulx r13, r9, QWORD PTR [r8+8] + adcx r12, r9 + ; A[0] * B[2] + mulx r14, r9, QWORD PTR [r8+16] + adcx r13, r9 + ; A[0] * B[3] + mulx r15, r9, QWORD PTR [r8+24] + adcx r14, r9 + ; A[0] * B[4] + mulx rdi, r9, QWORD PTR [r8+32] + adcx r15, r9 + ; A[0] * B[5] + mulx rsi, r9, QWORD PTR [r8+40] + adcx rdi, r9 + adcx rsi, rbx + mov QWORD PTR [rsp], r11 + mov r11, 0 + adcx r11, rbx + xor rbx, rbx + mov rdx, QWORD PTR [rax+8] + ; A[1] * B[0] + mulx r10, r9, QWORD PTR [r8] + adcx r12, r9 + adox r13, r10 + ; A[1] * B[1] + mulx r10, r9, QWORD PTR [r8+8] + adcx r13, r9 + adox r14, r10 + ; A[1] * B[2] + mulx r10, r9, QWORD PTR [r8+16] + adcx r14, r9 + adox r15, r10 + ; A[1] * B[3] + mulx r10, r9, QWORD PTR [r8+24] + adcx r15, r9 + adox rdi, r10 + ; A[1] * B[4] + mulx r10, r9, QWORD PTR [r8+32] + adcx rdi, r9 + adox rsi, r10 + ; A[1] * B[5] + mulx r10, r9, QWORD PTR [r8+40] + adcx rsi, r9 + adox r11, r10 + adcx r11, rbx + mov QWORD PTR [rsp+8], r12 + mov r12, 0 + adcx r12, rbx + adox r12, rbx + xor rbx, rbx + mov rdx, QWORD PTR [rax+16] + ; A[2] * B[0] + mulx r10, r9, QWORD PTR [r8] + adcx r13, r9 + adox r14, r10 + ; A[2] * B[1] + mulx r10, r9, QWORD PTR [r8+8] + adcx r14, r9 + adox r15, r10 + ; A[2] * B[2] + mulx r10, r9, QWORD PTR [r8+16] + adcx r15, r9 + adox rdi, r10 + ; A[2] * B[3] + mulx r10, r9, QWORD PTR [r8+24] + adcx rdi, r9 + adox rsi, r10 + ; A[2] * B[4] + mulx r10, r9, QWORD PTR [r8+32] + adcx rsi, r9 + adox r11, r10 + ; A[2] * B[5] + mulx r10, r9, QWORD PTR [r8+40] + adcx r11, r9 + adox r12, r10 + adcx r12, rbx + mov QWORD PTR [rsp+16], r13 + mov r13, 0 + adcx r13, rbx + adox r13, rbx + xor rbx, rbx + mov rdx, QWORD PTR [rax+24] + ; A[3] * B[0] + mulx r10, r9, QWORD PTR [r8] + adcx r14, r9 + adox r15, r10 + ; A[3] * B[1] + mulx r10, r9, QWORD PTR [r8+8] + adcx r15, r9 + adox rdi, r10 + ; A[3] * B[2] + mulx r10, r9, QWORD PTR [r8+16] + adcx rdi, r9 + adox rsi, r10 + ; A[3] * B[3] + mulx r10, r9, QWORD PTR [r8+24] + adcx rsi, r9 + adox r11, r10 + ; A[3] * B[4] + mulx r10, r9, QWORD PTR [r8+32] + adcx r11, r9 + adox r12, r10 + ; A[3] * B[5] + mulx r10, r9, QWORD PTR [r8+40] + adcx r12, r9 + adox r13, r10 + adcx r13, rbx + mov QWORD PTR [rsp+24], r14 + mov r14, 0 + adcx r14, rbx + adox r14, rbx + xor rbx, rbx + mov rdx, QWORD PTR [rax+32] + ; A[4] * B[0] + mulx r10, r9, QWORD PTR [r8] + adcx r15, r9 + adox rdi, r10 + ; A[4] * B[1] + mulx r10, r9, QWORD PTR [r8+8] + adcx rdi, r9 + adox rsi, r10 + ; A[4] * B[2] + mulx r10, r9, QWORD PTR [r8+16] + adcx rsi, r9 + adox r11, r10 + ; A[4] * B[3] + mulx r10, r9, QWORD PTR [r8+24] + adcx r11, r9 + adox r12, r10 + ; A[4] * B[4] + mulx r10, r9, QWORD PTR [r8+32] + adcx r12, r9 + adox r13, r10 + ; A[4] * B[5] + mulx r10, r9, QWORD PTR [r8+40] + adcx r13, r9 + adox r14, r10 + adcx r14, rbx + mov QWORD PTR [rsp+32], r15 + mov rdx, QWORD PTR [rax+40] + ; A[5] * B[0] + mulx r10, r9, QWORD PTR [r8] + adcx rdi, r9 + adox rsi, r10 + ; A[5] * B[1] + mulx r10, r9, QWORD PTR [r8+8] + adcx rsi, r9 + adox r11, r10 + ; A[5] * B[2] + mulx r10, r9, QWORD PTR [r8+16] + adcx r11, r9 + adox r12, r10 + ; A[5] * B[3] + mulx r10, r9, QWORD PTR [r8+24] + adcx r12, r9 + adox r13, r10 + ; A[5] * B[4] + mulx r10, r9, QWORD PTR [r8+32] + adcx r13, r9 + adox r14, r10 + ; A[5] * B[5] + mulx r15, r9, QWORD PTR [r8+40] + adcx r14, r9 + adox r15, rbx + adcx r15, rbx + mov QWORD PTR [rcx+40], rdi + mov QWORD PTR [rcx+48], rsi + mov QWORD PTR [rcx+56], r11 + mov QWORD PTR [rcx+64], r12 + mov QWORD PTR [rcx+72], r13 + mov QWORD PTR [rcx+80], r14 + mov QWORD PTR [rcx+88], r15 + mov r11, QWORD PTR [rsp] + mov r12, QWORD PTR [rsp+8] + mov r13, QWORD PTR [rsp+16] + mov r14, QWORD PTR [rsp+24] + mov r15, QWORD PTR [rsp+32] + mov QWORD PTR [rcx], r11 + mov QWORD PTR [rcx+8], r12 + mov QWORD PTR [rcx+16], r13 + mov QWORD PTR [rcx+24], r14 + mov QWORD PTR [rcx+32], r15 + add rsp, 40 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_384_mul_avx2_6 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 384 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_384_mont_reduce_order_avx2_6 PROC + push r12 + push r13 + push r14 + push r15 + mov rax, rdx + xor r15, r15 + mov r14, QWORD PTR [rcx] + xor r13, r13 +L_mont_loop_order_avx2_6: + ; mu = a[i] * mp + mov rdx, r14 + mov r11, r14 + imul rdx, r8 + xor r13, r13 + ; a[i+0] += m[0] * mu + mulx r10, r9, QWORD PTR [rax] + mov r14, QWORD PTR [rcx+8] + adcx r11, r9 + adox r14, r10 + ; a[i+1] += m[1] * mu + mulx r10, r9, QWORD PTR [rax+8] + mov r11, QWORD PTR [rcx+16] + adcx r14, r9 + adox r11, r10 + ; a[i+2] += m[2] * mu + mulx r10, r9, QWORD PTR [rax+16] + mov r12, QWORD PTR [rcx+24] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; a[i+3] += m[3] * mu + mulx r10, r9, QWORD PTR [rax+24] + mov r11, QWORD PTR [rcx+32] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; a[i+4] += m[4] * mu + mulx r10, r9, QWORD PTR [rax+32] + mov r12, QWORD PTR [rcx+40] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; a[i+5] += m[5] * mu + mulx r10, r9, QWORD PTR [rax+40] + mov r11, QWORD PTR [rcx+48] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + adcx r11, r15 + mov QWORD PTR [rcx+48], r11 + mov r15, r13 + adox r15, r13 + adcx r15, r13 + ; mu = a[i] * mp + mov rdx, r14 + mov r11, r14 + imul rdx, r8 + xor r13, r13 + ; a[i+0] += m[0] * mu + mulx r10, r9, QWORD PTR [rax] + mov r14, QWORD PTR [rcx+16] + adcx r11, r9 + adox r14, r10 + ; a[i+1] += m[1] * mu + mulx r10, r9, QWORD PTR [rax+8] + mov r11, QWORD PTR [rcx+24] + adcx r14, r9 + adox r11, r10 + ; a[i+2] += m[2] * mu + mulx r10, r9, QWORD PTR [rax+16] + mov r12, QWORD PTR [rcx+32] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+24], r11 + ; a[i+3] += m[3] * mu + mulx r10, r9, QWORD PTR [rax+24] + mov r11, QWORD PTR [rcx+40] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+32], r12 + ; a[i+4] += m[4] * mu + mulx r10, r9, QWORD PTR [rax+32] + mov r12, QWORD PTR [rcx+48] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+40], r11 + ; a[i+5] += m[5] * mu + mulx r10, r9, QWORD PTR [rax+40] + mov r11, QWORD PTR [rcx+56] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+48], r12 + adcx r11, r15 + mov QWORD PTR [rcx+56], r11 + mov r15, r13 + adox r15, r13 + adcx r15, r13 + ; mu = a[i] * mp + mov rdx, r14 + mov r11, r14 + imul rdx, r8 + xor r13, r13 + ; a[i+0] += m[0] * mu + mulx r10, r9, QWORD PTR [rax] + mov r14, QWORD PTR [rcx+24] + adcx r11, r9 + adox r14, r10 + ; a[i+1] += m[1] * mu + mulx r10, r9, QWORD PTR [rax+8] + mov r11, QWORD PTR [rcx+32] + adcx r14, r9 + adox r11, r10 + ; a[i+2] += m[2] * mu + mulx r10, r9, QWORD PTR [rax+16] + mov r12, QWORD PTR [rcx+40] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; a[i+3] += m[3] * mu + mulx r10, r9, QWORD PTR [rax+24] + mov r11, QWORD PTR [rcx+48] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; a[i+4] += m[4] * mu + mulx r10, r9, QWORD PTR [rax+32] + mov r12, QWORD PTR [rcx+56] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; a[i+5] += m[5] * mu + mulx r10, r9, QWORD PTR [rax+40] + mov r11, QWORD PTR [rcx+64] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + adcx r11, r15 + mov QWORD PTR [rcx+64], r11 + mov r15, r13 + adox r15, r13 + adcx r15, r13 + ; mu = a[i] * mp + mov rdx, r14 + mov r11, r14 + imul rdx, r8 + xor r13, r13 + ; a[i+0] += m[0] * mu + mulx r10, r9, QWORD PTR [rax] + mov r14, QWORD PTR [rcx+32] + adcx r11, r9 + adox r14, r10 + ; a[i+1] += m[1] * mu + mulx r10, r9, QWORD PTR [rax+8] + mov r11, QWORD PTR [rcx+40] + adcx r14, r9 + adox r11, r10 + ; a[i+2] += m[2] * mu + mulx r10, r9, QWORD PTR [rax+16] + mov r12, QWORD PTR [rcx+48] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+40], r11 + ; a[i+3] += m[3] * mu + mulx r10, r9, QWORD PTR [rax+24] + mov r11, QWORD PTR [rcx+56] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+48], r12 + ; a[i+4] += m[4] * mu + mulx r10, r9, QWORD PTR [rax+32] + mov r12, QWORD PTR [rcx+64] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+56], r11 + ; a[i+5] += m[5] * mu + mulx r10, r9, QWORD PTR [rax+40] + mov r11, QWORD PTR [rcx+72] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+64], r12 + adcx r11, r15 + mov QWORD PTR [rcx+72], r11 + mov r15, r13 + adox r15, r13 + adcx r15, r13 + ; mu = a[i] * mp + mov rdx, r14 + mov r11, r14 + imul rdx, r8 + xor r13, r13 + ; a[i+0] += m[0] * mu + mulx r10, r9, QWORD PTR [rax] + mov r14, QWORD PTR [rcx+40] + adcx r11, r9 + adox r14, r10 + ; a[i+1] += m[1] * mu + mulx r10, r9, QWORD PTR [rax+8] + mov r11, QWORD PTR [rcx+48] + adcx r14, r9 + adox r11, r10 + ; a[i+2] += m[2] * mu + mulx r10, r9, QWORD PTR [rax+16] + mov r12, QWORD PTR [rcx+56] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; a[i+3] += m[3] * mu + mulx r10, r9, QWORD PTR [rax+24] + mov r11, QWORD PTR [rcx+64] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; a[i+4] += m[4] * mu + mulx r10, r9, QWORD PTR [rax+32] + mov r12, QWORD PTR [rcx+72] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; a[i+5] += m[5] * mu + mulx r10, r9, QWORD PTR [rax+40] + mov r11, QWORD PTR [rcx+80] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + adcx r11, r15 + mov QWORD PTR [rcx+80], r11 + mov r15, r13 + adox r15, r13 + adcx r15, r13 + ; mu = a[i] * mp + mov rdx, r14 + mov r11, r14 + imul rdx, r8 + xor r13, r13 + ; a[i+0] += m[0] * mu + mulx r10, r9, QWORD PTR [rax] + mov r14, QWORD PTR [rcx+48] + adcx r11, r9 + adox r14, r10 + ; a[i+1] += m[1] * mu + mulx r10, r9, QWORD PTR [rax+8] + mov r11, QWORD PTR [rcx+56] + adcx r14, r9 + adox r11, r10 + ; a[i+2] += m[2] * mu + mulx r10, r9, QWORD PTR [rax+16] + mov r12, QWORD PTR [rcx+64] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+56], r11 + ; a[i+3] += m[3] * mu + mulx r10, r9, QWORD PTR [rax+24] + mov r11, QWORD PTR [rcx+72] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+64], r12 + ; a[i+4] += m[4] * mu + mulx r10, r9, QWORD PTR [rax+32] + mov r12, QWORD PTR [rcx+80] + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+72], r11 + ; a[i+5] += m[5] * mu + mulx r10, r9, QWORD PTR [rax+40] + mov r11, QWORD PTR [rcx+88] + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+80], r12 + adcx r11, r15 + mov QWORD PTR [rcx+88], r11 + mov r15, r13 + adox r15, r13 + adcx r15, r13 + neg r15 + mov r8, rcx + add rcx, 48 + mov r10, QWORD PTR [rax] + mov rdx, r14 + pext r10, r10, r15 + sub rdx, r10 + mov r10, QWORD PTR [rax+8] + mov r9, QWORD PTR [rcx+8] + pext r10, r10, r15 + mov QWORD PTR [r8], rdx + sbb r9, r10 + mov rdx, QWORD PTR [rax+16] + mov r10, QWORD PTR [rcx+16] + pext rdx, rdx, r15 + mov QWORD PTR [r8+8], r9 + sbb r10, rdx + mov r9, QWORD PTR [rax+24] + mov rdx, QWORD PTR [rcx+24] + pext r9, r9, r15 + mov QWORD PTR [r8+16], r10 + sbb rdx, r9 + mov r10, QWORD PTR [rax+32] + mov r9, QWORD PTR [rcx+32] + pext r10, r10, r15 + mov QWORD PTR [r8+24], rdx + sbb r9, r10 + mov rdx, QWORD PTR [rax+40] + mov r10, QWORD PTR [rcx+40] + pext rdx, rdx, r15 + mov QWORD PTR [r8+32], r9 + sbb r10, rdx + mov QWORD PTR [r8+40], r10 + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_384_mont_reduce_order_avx2_6 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r Result of squaring. +; * a Number to square in Montogmery form. +; */ +_text SEGMENT READONLY PARA +sp_384_sqr_avx2_6 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov rax, rdx + push rcx + xor rcx, rcx + mov rdx, QWORD PTR [rax] + mov rsi, QWORD PTR [rax+8] + mov rbx, QWORD PTR [rax+16] + mov rbp, QWORD PTR [rax+24] + ; Diagonal 0 + ; A[1] * A[0] + mulx r11, r10, QWORD PTR [rax+8] + ; A[2] * A[0] + mulx r12, r8, QWORD PTR [rax+16] + adcx r11, r8 + ; A[3] * A[0] + mulx r13, r8, QWORD PTR [rax+24] + adcx r12, r8 + ; A[4] * A[0] + mulx r14, r8, QWORD PTR [rax+32] + adcx r13, r8 + ; A[5] * A[0] + mulx r15, r8, QWORD PTR [rax+40] + adcx r14, r8 + adcx r15, rcx + ; Diagonal 1 + mov rdx, rsi + ; A[2] * A[1] + mulx r9, r8, QWORD PTR [rax+16] + adcx r12, r8 + adox r13, r9 + ; A[3] * A[1] + mulx r9, r8, QWORD PTR [rax+24] + adcx r13, r8 + adox r14, r9 + ; A[4] * A[1] + mulx r9, r8, QWORD PTR [rax+32] + adcx r14, r8 + adox r15, r9 + ; A[5] * A[1] + mulx rdi, r8, QWORD PTR [rax+40] + adcx r15, r8 + adox rdi, rcx + mov rdx, rbx + ; A[5] * A[2] + mulx rsi, r8, QWORD PTR [rax+40] + adcx rdi, r8 + adox rsi, rcx + adcx rsi, rcx + adcx rbx, rcx + ; Diagonal 2 + ; A[3] * A[2] + mulx r9, r8, QWORD PTR [rax+24] + adcx r14, r8 + adox r15, r9 + ; A[4] * A[2] + mulx r9, r8, QWORD PTR [rax+32] + adcx r15, r8 + adox rdi, r9 + mov rdx, rbp + ; A[4] * A[3] + mulx r9, r8, QWORD PTR [rax+32] + adcx rdi, r8 + adox rsi, r9 + ; A[5] * A[3] + mulx rbx, r8, QWORD PTR [rax+40] + adcx rsi, r8 + adox rbx, rcx + mov rdx, QWORD PTR [rax+32] + ; A[5] * A[4] + mulx rbp, r8, QWORD PTR [rax+40] + adcx rbx, r8 + adox rbp, rcx + adcx rbp, rcx + adcx rcx, rcx + ; Doubling previous result as we add in square words results + ; A[0] * A[0] + mov rdx, QWORD PTR [rax] + mulx r9, r8, rdx + pop rdx + mov QWORD PTR [rdx], r8 + adox r10, r10 + push rdx + adcx r10, r9 + ; A[1] * A[1] + mov rdx, QWORD PTR [rax+8] + mulx r9, r8, rdx + adox r11, r11 + adcx r11, r8 + adox r12, r12 + adcx r12, r9 + ; A[2] * A[2] + mov rdx, QWORD PTR [rax+16] + mulx r9, r8, rdx + adox r13, r13 + adcx r13, r8 + adox r14, r14 + adcx r14, r9 + ; A[3] * A[3] + mov rdx, QWORD PTR [rax+24] + mulx r9, r8, rdx + adox r15, r15 + adcx r15, r8 + adox rdi, rdi + adcx rdi, r9 + ; A[4] * A[4] + mov rdx, QWORD PTR [rax+32] + mulx r9, r8, rdx + adox rsi, rsi + adcx rsi, r8 + adox rbx, rbx + adcx rbx, r9 + ; A[5] * A[5] + mov rdx, QWORD PTR [rax+40] + mulx r9, r8, rdx + adox rbp, rbp + adcx rbp, r8 + adcx r9, rcx + mov r8, 0 + adox r9, r8 + pop rcx + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + mov QWORD PTR [rcx+32], r13 + mov QWORD PTR [rcx+40], r14 + mov QWORD PTR [rcx+48], r15 + mov QWORD PTR [rcx+56], rdi + mov QWORD PTR [rcx+64], rsi + mov QWORD PTR [rcx+72], rbx + mov QWORD PTR [rcx+80], rbp + mov QWORD PTR [rcx+88], r9 + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_384_sqr_avx2_6 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_384_cond_sub_avx2_6 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov QWORD PTR [rcx+40], r12 + sbb rax, 0 + pop r12 + ret +sp_384_cond_sub_avx2_6 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_384_div2_avx2_6 PROC + push r12 + push r13 + mov r13, QWORD PTR [rdx] + xor r12, r12 + mov r10, r13 + and r13, 1 + neg r13 + mov rax, QWORD PTR [r8] + mov r9, QWORD PTR [r8+8] + mov r10, QWORD PTR [rdx] + mov r11, QWORD PTR [rdx+8] + pext rax, rax, r13 + pext r9, r9, r13 + add r10, rax + adc r11, r9 + mov QWORD PTR [rcx], r10 + mov QWORD PTR [rcx+8], r11 + mov rax, QWORD PTR [r8+16] + mov r9, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [r8+32] + mov r9, QWORD PTR [r8+40] + mov r10, QWORD PTR [rdx+32] + mov r11, QWORD PTR [rdx+40] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+32], r10 + mov QWORD PTR [rcx+40], r11 + adc r12, 0 + mov r10, QWORD PTR [rcx] + mov r11, QWORD PTR [rcx+8] + shrd r10, r11, 1 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rcx+16] + shrd r11, r10, 1 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rcx+24] + shrd r10, r11, 1 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rcx+32] + shrd r11, r10, 1 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rcx+40] + shrd r10, r11, 1 + mov QWORD PTR [rcx+32], r10 + shrd r11, r12, 1 + mov QWORD PTR [rcx+40], r11 + pop r13 + pop r12 + ret +sp_384_div2_avx2_6 ENDP +_text ENDS +ENDIF +IFNDEF WC_NO_CACHE_RESISTANT +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_384_get_entry_64_6 PROC + mov rax, 1 + movd xmm13, r8d + add rdx, 96 + movd xmm15, eax + mov rax, 63 + pshufd xmm15, xmm15, 0 + pshufd xmm13, xmm13, 0 + pxor xmm14, xmm14 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + pxor xmm3, xmm3 + pxor xmm4, xmm4 + pxor xmm5, xmm5 + movdqa xmm14, xmm15 +L_384_get_entry_64_6_start: + movdqa xmm12, xmm14 + paddd xmm14, xmm15 + pcmpeqd xmm12, xmm13 + movdqu xmm6, [rdx] + movdqu xmm7, [rdx+16] + movdqu xmm8, [rdx+32] + movdqu xmm9, [rdx+48] + movdqu xmm10, [rdx+64] + movdqu xmm11, [rdx+80] + add rdx, 96 + pand xmm6, xmm12 + pand xmm7, xmm12 + pand xmm8, xmm12 + pand xmm9, xmm12 + pand xmm10, xmm12 + pand xmm11, xmm12 + por xmm0, xmm6 + por xmm1, xmm7 + por xmm2, xmm8 + por xmm3, xmm9 + por xmm4, xmm10 + por xmm5, xmm11 + dec rax + jnz L_384_get_entry_64_6_start + movdqu [rcx], xmm0 + movdqu [rcx+16], xmm1 + movdqu [rcx+32], xmm2 + movdqu [rcx+96], xmm3 + movdqu [rcx+112], xmm4 + movdqu [rcx+128], xmm5 + ret +sp_384_get_entry_64_6 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_384_get_entry_64_avx2_6 PROC + mov rax, 1 + movd xmm9, r8d + add rdx, 96 + movd xmm11, eax + mov rax, 64 + vpxor ymm10, ymm10, ymm10 + vpermd ymm9, ymm10, ymm9 + vpermd ymm11, ymm10, ymm11 + vpxor ymm0, ymm0, ymm0 + vpxor xmm1, xmm1, xmm1 + vpxor ymm2, ymm2, ymm2 + vpxor xmm3, xmm3, xmm3 + vmovdqa ymm10, ymm11 +L_384_get_entry_64_avx2_6_start: + vpcmpeqd ymm8, ymm10, ymm9 + vpaddd ymm10, ymm10, ymm11 + vmovupd ymm4, [rdx] + vmovdqu xmm5, OWORD PTR [rdx+32] + vmovupd ymm6, [rdx+48] + vmovdqu xmm7, OWORD PTR [rdx+80] + add rdx, 96 + vpand ymm4, ymm4, ymm8 + vpand xmm5, xmm5, xmm8 + vpand ymm6, ymm6, ymm8 + vpand xmm7, xmm7, xmm8 + vpor ymm0, ymm0, ymm4 + vpor xmm1, xmm1, xmm5 + vpor ymm2, ymm2, ymm6 + vpor xmm3, xmm3, xmm7 + dec rax + jnz L_384_get_entry_64_avx2_6_start + vmovupd YMMWORD PTR [rcx], ymm0 + vmovdqu [rcx+32], xmm1 + vmovupd YMMWORD PTR [rcx+96], ymm2 + vmovdqu [rcx+128], xmm3 + ret +sp_384_get_entry_64_avx2_6 ENDP +_text ENDS +ENDIF +ENDIF +IFNDEF WC_NO_CACHE_RESISTANT +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_384_get_entry_65_6 PROC + mov rax, 1 + movd xmm13, r8d + add rdx, 96 + movd xmm15, eax + mov rax, 64 + pshufd xmm15, xmm15, 0 + pshufd xmm13, xmm13, 0 + pxor xmm14, xmm14 + pxor xmm0, xmm0 + pxor xmm1, xmm1 + pxor xmm2, xmm2 + pxor xmm3, xmm3 + pxor xmm4, xmm4 + pxor xmm5, xmm5 + movdqa xmm14, xmm15 +L_384_get_entry_65_6_start: + movdqa xmm12, xmm14 + paddd xmm14, xmm15 + pcmpeqd xmm12, xmm13 + movdqu xmm6, [rdx] + movdqu xmm7, [rdx+16] + movdqu xmm8, [rdx+32] + movdqu xmm9, [rdx+48] + movdqu xmm10, [rdx+64] + movdqu xmm11, [rdx+80] + add rdx, 96 + pand xmm6, xmm12 + pand xmm7, xmm12 + pand xmm8, xmm12 + pand xmm9, xmm12 + pand xmm10, xmm12 + pand xmm11, xmm12 + por xmm0, xmm6 + por xmm1, xmm7 + por xmm2, xmm8 + por xmm3, xmm9 + por xmm4, xmm10 + por xmm5, xmm11 + dec rax + jnz L_384_get_entry_65_6_start + movdqu [rcx], xmm0 + movdqu [rcx+16], xmm1 + movdqu [rcx+32], xmm2 + movdqu [rcx+96], xmm3 + movdqu [rcx+112], xmm4 + movdqu [rcx+128], xmm5 + ret +sp_384_get_entry_65_6 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Touch each possible entry that could be being copied. +; * +; * r Point to copy into. +; * table Table - start of the entires to access +; * idx Index of entry to retrieve. +; */ +_text SEGMENT READONLY PARA +sp_384_get_entry_65_avx2_6 PROC + mov rax, 1 + movd xmm9, r8d + add rdx, 96 + movd xmm11, eax + mov rax, 65 + vpxor ymm10, ymm10, ymm10 + vpermd ymm9, ymm10, ymm9 + vpermd ymm11, ymm10, ymm11 + vpxor ymm0, ymm0, ymm0 + vpxor xmm1, xmm1, xmm1 + vpxor ymm2, ymm2, ymm2 + vpxor xmm3, xmm3, xmm3 + vmovdqa ymm10, ymm11 +L_384_get_entry_65_avx2_6_start: + vpcmpeqd ymm8, ymm10, ymm9 + vpaddd ymm10, ymm10, ymm11 + vmovupd ymm4, [rdx] + vmovdqu xmm5, OWORD PTR [rdx+32] + vmovupd ymm6, [rdx+48] + vmovdqu xmm7, OWORD PTR [rdx+80] + add rdx, 96 + vpand ymm4, ymm4, ymm8 + vpand xmm5, xmm5, xmm8 + vpand ymm6, ymm6, ymm8 + vpand xmm7, xmm7, xmm8 + vpor ymm0, ymm0, ymm4 + vpor xmm1, xmm1, xmm5 + vpor ymm2, ymm2, ymm6 + vpor xmm3, xmm3, xmm7 + dec rax + jnz L_384_get_entry_65_avx2_6_start + vmovupd YMMWORD PTR [rcx], ymm0 + vmovdqu [rcx+32], xmm1 + vmovupd YMMWORD PTR [rcx+96], ymm2 + vmovdqu [rcx+128], xmm3 + ret +sp_384_get_entry_65_avx2_6 ENDP +_text ENDS +ENDIF +ENDIF +; /* Add 1 to a. (a = a + 1) +; * +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_add_one_6 PROC + add QWORD PTR [rcx], 1 + adc QWORD PTR [rcx+8], 0 + adc QWORD PTR [rcx+16], 0 + adc QWORD PTR [rcx+24], 0 + adc QWORD PTR [rcx+32], 0 + adc QWORD PTR [rcx+40], 0 + ret +sp_384_add_one_6 ENDP +_text ENDS +; /* Read big endian unsigned byte array into r. +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_384_from_bin_bswap PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 48 + xor r13, r13 + jmp L_384_from_bin_bswap_64_end +L_384_from_bin_bswap_64_start: + sub r11, 64 + mov rax, QWORD PTR [r11+56] + mov r10, QWORD PTR [r11+48] + bswap rax + bswap r10 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [r11+40] + mov r10, QWORD PTR [r11+32] + bswap rax + bswap r10 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [r11+24] + mov r10, QWORD PTR [r11+16] + bswap rax + bswap r10 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [r11+8] + mov r10, QWORD PTR [r11] + bswap rax + bswap r10 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_384_from_bin_bswap_64_end: + cmp r9, 63 + jg L_384_from_bin_bswap_64_start + jmp L_384_from_bin_bswap_8_end +L_384_from_bin_bswap_8_start: + sub r11, 8 + mov rax, QWORD PTR [r11] + bswap rax + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_384_from_bin_bswap_8_end: + cmp r9, 7 + jg L_384_from_bin_bswap_8_start + cmp r9, r13 + je L_384_from_bin_bswap_hi_end + mov r10, r13 + mov rax, r13 +L_384_from_bin_bswap_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_384_from_bin_bswap_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_384_from_bin_bswap_hi_end: + cmp rcx, r12 + je L_384_from_bin_bswap_zero_end +L_384_from_bin_bswap_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_384_from_bin_bswap_zero_start +L_384_from_bin_bswap_zero_end: + pop r13 + pop r12 + ret +sp_384_from_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Read big endian unsigned byte array into r. +; * Uses the movbe instruction which is an optional instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_384_from_bin_movbe PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 48 + xor r13, r13 + jmp L_384_from_bin_movbe_64_end +L_384_from_bin_movbe_64_start: + sub r11, 64 + movbe rax, QWORD PTR [r11+56] + movbe r10, QWORD PTR [r11+48] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + movbe rax, QWORD PTR [r11+40] + movbe r10, QWORD PTR [r11+32] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + movbe rax, QWORD PTR [r11+24] + movbe r10, QWORD PTR [r11+16] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + movbe rax, QWORD PTR [r11+8] + movbe r10, QWORD PTR [r11] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_384_from_bin_movbe_64_end: + cmp r9, 63 + jg L_384_from_bin_movbe_64_start + jmp L_384_from_bin_movbe_8_end +L_384_from_bin_movbe_8_start: + sub r11, 8 + movbe rax, QWORD PTR [r11] + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_384_from_bin_movbe_8_end: + cmp r9, 7 + jg L_384_from_bin_movbe_8_start + cmp r9, r13 + je L_384_from_bin_movbe_hi_end + mov r10, r13 + mov rax, r13 +L_384_from_bin_movbe_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_384_from_bin_movbe_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_384_from_bin_movbe_hi_end: + cmp rcx, r12 + je L_384_from_bin_movbe_zero_end +L_384_from_bin_movbe_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_384_from_bin_movbe_zero_start +L_384_from_bin_movbe_zero_end: + pop r13 + pop r12 + ret +sp_384_from_bin_movbe ENDP +_text ENDS +ENDIF +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 48 +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_384_to_bin_bswap PROC + mov rax, QWORD PTR [rcx+40] + mov r8, QWORD PTR [rcx+32] + bswap rax + bswap r8 + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + mov rax, QWORD PTR [rcx+24] + mov r8, QWORD PTR [rcx+16] + bswap rax + bswap r8 + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + mov rax, QWORD PTR [rcx+8] + mov r8, QWORD PTR [rcx] + bswap rax + bswap r8 + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + ret +sp_384_to_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Write r as big endian to byte array. +; * Fixed length number of bytes written: 48 +; * Uses the movbe instruction which is optional. +; * +; * r A single precision integer. +; * a Byte array. +; */ +_text SEGMENT READONLY PARA +sp_384_to_bin_movbe PROC + movbe rax, QWORD PTR [rcx+40] + movbe r8, QWORD PTR [rcx+32] + mov QWORD PTR [rdx], rax + mov QWORD PTR [rdx+8], r8 + movbe rax, QWORD PTR [rcx+24] + movbe r8, QWORD PTR [rcx+16] + mov QWORD PTR [rdx+16], rax + mov QWORD PTR [rdx+24], r8 + movbe rax, QWORD PTR [rcx+8] + movbe r8, QWORD PTR [rcx] + mov QWORD PTR [rdx+32], rax + mov QWORD PTR [rdx+40], r8 + ret +sp_384_to_bin_movbe ENDP +_text ENDS +ENDIF +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_384_sub_in_place_6 PROC + xor rax, rax + mov r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + mov r12, QWORD PTR [rdx+32] + mov r13, QWORD PTR [rdx+40] + sub QWORD PTR [rcx], r8 + sbb QWORD PTR [rcx+8], r9 + sbb QWORD PTR [rcx+16], r10 + sbb QWORD PTR [rcx+24], r11 + sbb QWORD PTR [rcx+32], r12 + sbb QWORD PTR [rcx+40], r13 + sbb rax, 0 + pop r13 + pop r12 + ret +sp_384_sub_in_place_6 ENDP +_text ENDS +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_384_mul_d_6 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + mov QWORD PTR [rcx+40], r12 + mov QWORD PTR [rcx+48], r10 + pop r12 + ret +sp_384_mul_d_6 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_384_mul_d_avx2_6 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+40], r12 + mov QWORD PTR [rcx+48], r11 + pop r13 + pop r12 + ret +sp_384_mul_d_avx2_6 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_384_word_asm_6 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_384_word_asm_6 ENDP +_text ENDS +ENDIF +; /* Shift number right by 1 bit. (r = a >> 1) +; * +; * r Result of right shift by 1. +; * a Number to shift. +; */ +_text SEGMENT READONLY PARA +sp_384_rshift1_6 PROC + push r12 + mov rax, QWORD PTR [rdx] + mov r8, QWORD PTR [rdx+8] + mov r9, QWORD PTR [rdx+16] + mov r10, QWORD PTR [rdx+24] + mov r11, QWORD PTR [rdx+32] + mov r12, QWORD PTR [rdx+40] + shrd rax, r8, 1 + shrd r8, r9, 1 + shrd r9, r10, 1 + shrd r10, r11, 1 + shrd r11, r12, 1 + shr r12, 1 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r8 + mov QWORD PTR [rcx+16], r9 + mov QWORD PTR [rcx+24], r10 + mov QWORD PTR [rcx+32], r11 + mov QWORD PTR [rcx+40], r12 + pop r12 + ret +sp_384_rshift1_6 ENDP +_text ENDS +; /* Divide the number by 2 mod the prime. (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus +; */ +_text SEGMENT READONLY PARA +sp_384_div2_mod_6 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + mov r12, QWORD PTR [rdx+32] + mov r13, QWORD PTR [rdx+40] + mov r14, QWORD PTR [r8] + mov r15, QWORD PTR [r8+8] + mov rdi, QWORD PTR [r8+16] + mov rsi, QWORD PTR [r8+24] + mov rbx, QWORD PTR [r8+32] + mov rbp, QWORD PTR [r8+40] + mov r8, rax + and r8, 1 + je L_384_mod_inv_6_div2_mod_no_add + add rax, r14 + adc r9, r15 + adc r10, rdi + adc r11, rsi + adc r12, rbx + adc r13, rbp + mov r8, 0 + adc r8, 0 +L_384_mod_inv_6_div2_mod_no_add: + shrd rax, r9, 1 + shrd r9, r10, 1 + shrd r10, r11, 1 + shrd r11, r12, 1 + shrd r12, r13, 1 + shrd r13, r8, 1 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov QWORD PTR [rcx+32], r12 + mov QWORD PTR [rcx+40], r13 + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_384_div2_mod_6 ENDP +_text ENDS +_text SEGMENT READONLY PARA +sp_384_num_bits_6 PROC + xor rax, rax + mov rdx, QWORD PTR [rcx+40] + cmp rdx, 0 + je L_384_num_bits_6_end_320 + mov rax, -1 + bsr rax, rdx + add rax, 321 + jmp L_384_num_bits_6_done +L_384_num_bits_6_end_320: + mov rdx, QWORD PTR [rcx+32] + cmp rdx, 0 + je L_384_num_bits_6_end_256 + mov rax, -1 + bsr rax, rdx + add rax, 257 + jmp L_384_num_bits_6_done +L_384_num_bits_6_end_256: + mov rdx, QWORD PTR [rcx+24] + cmp rdx, 0 + je L_384_num_bits_6_end_192 + mov rax, -1 + bsr rax, rdx + add rax, 193 + jmp L_384_num_bits_6_done +L_384_num_bits_6_end_192: + mov rdx, QWORD PTR [rcx+16] + cmp rdx, 0 + je L_384_num_bits_6_end_128 + mov rax, -1 + bsr rax, rdx + add rax, 129 + jmp L_384_num_bits_6_done +L_384_num_bits_6_end_128: + mov rdx, QWORD PTR [rcx+8] + cmp rdx, 0 + je L_384_num_bits_6_end_64 + mov rax, -1 + bsr rax, rdx + add rax, 65 + jmp L_384_num_bits_6_done +L_384_num_bits_6_end_64: + mov rdx, QWORD PTR [rcx] + cmp rdx, 0 + je L_384_num_bits_6_end_0 + mov rax, -1 + bsr rax, rdx + add rax, 1 + jmp L_384_num_bits_6_done +L_384_num_bits_6_end_0: +L_384_num_bits_6_done: + ret +sp_384_num_bits_6 ENDP +_text ENDS +ENDIF +IFDEF WOLFSSL_SP_1024 +; /* Multiply a and b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_1024_mul_16 PROC + push r12 + mov r9, rdx + sub rsp, 128 + ; A[0] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9] + xor r12, r12 + mov QWORD PTR [rsp], rax + mov r11, rdx + ; A[0] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+8], r11 + ; A[0] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+16], r12 + ; A[0] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+24], r10 + ; A[0] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+32], r11 + ; A[0] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+40], r12 + ; A[0] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+48], r10 + ; A[0] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+56], r11 + ; A[0] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+64], r12 + ; A[0] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+72], r10 + ; A[0] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+80], r11 + ; A[0] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+88], r12 + ; A[0] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+96], r10 + ; A[0] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[1] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+8] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rsp+104], r11 + ; A[0] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[1] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+8] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[2] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+16] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+112], r12 + ; A[0] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[1] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+8] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[2] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+16] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[3] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+24] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[0] + mov rax, QWORD PTR [r8] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rsp+120], r10 + ; A[1] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+8] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[2] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+16] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[3] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+24] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[4] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+32] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+128], r11 + ; A[2] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+16] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[3] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+24] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[4] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+32] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[5] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+40] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+136], r12 + ; A[3] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+24] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[4] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+32] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[5] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+40] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[6] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+48] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+144], r10 + ; A[4] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+32] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[5] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+40] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[6] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+48] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[7] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+56] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+152], r11 + ; A[5] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+40] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[6] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+48] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[7] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+56] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[8] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+64] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+160], r12 + ; A[6] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+48] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[7] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+56] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[8] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+64] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[9] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+72] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+168], r10 + ; A[7] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+56] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[8] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+64] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[9] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+72] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[10] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+80] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+176], r11 + ; A[8] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+64] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[9] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+72] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[10] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+80] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[11] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+88] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+184], r12 + ; A[9] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+72] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[10] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+80] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[11] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+88] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[12] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+96] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+192], r10 + ; A[10] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+80] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[11] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+88] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[12] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+96] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[13] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+104] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+200], r11 + ; A[11] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+88] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[12] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+96] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[13] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+104] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[14] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+112] + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+208], r12 + ; A[12] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+96] + xor r12, r12 + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[13] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+104] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[14] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+112] + add r10, rax + adc r11, rdx + adc r12, 0 + ; A[15] * B[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + adc r12, 0 + mov QWORD PTR [rcx+216], r10 + ; A[13] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+104] + xor r10, r10 + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[14] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+112] + add r11, rax + adc r12, rdx + adc r10, 0 + ; A[15] * B[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r9+120] + add r11, rax + adc r12, rdx + adc r10, 0 + mov QWORD PTR [rcx+224], r11 + ; A[14] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+112] + xor r11, r11 + add r12, rax + adc r10, rdx + adc r11, 0 + ; A[15] * B[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r9+120] + add r12, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+232], r12 + ; A[15] * B[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+240], r10 + mov QWORD PTR [rcx+248], r11 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r10, QWORD PTR [rsp+16] + mov r11, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov r10, QWORD PTR [rsp+48] + mov r11, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rsp+64] + mov rdx, QWORD PTR [rsp+72] + mov r10, QWORD PTR [rsp+80] + mov r11, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], rdx + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rsp+96] + mov rdx, QWORD PTR [rsp+104] + mov r10, QWORD PTR [rsp+112] + mov r11, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], rdx + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + add rsp, 128 + pop r12 + ret +sp_1024_mul_16 ENDP +_text ENDS +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_1024_sqr_16 PROC + push r12 + push r13 + push r14 + mov r8, rdx + sub rsp, 128 + ; A[0] * A[0] + mov rax, QWORD PTR [r8] + mul rax + xor r11, r11 + mov QWORD PTR [rsp], rax + mov r10, rdx + ; A[0] * A[1] + mov rax, QWORD PTR [r8+8] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+8], r10 + ; A[0] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[1] * A[1] + mov rax, QWORD PTR [r8+8] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rsp+16], r11 + ; A[0] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[1] * A[2] + mov rax, QWORD PTR [r8+16] + mul QWORD PTR [r8+8] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rsp+24], r9 + ; A[0] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[1] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+8] + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[2] * A[2] + mov rax, QWORD PTR [r8+16] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rsp+32], r10 + ; A[0] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[3] + mov rax, QWORD PTR [r8+24] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+40], r11 + ; A[0] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[3] + mov rax, QWORD PTR [r8+24] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+48], r9 + ; A[0] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[4] + mov rax, QWORD PTR [r8+32] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+56], r10 + ; A[0] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[4] + mov rax, QWORD PTR [r8+32] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+64], r11 + ; A[0] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[5] + mov rax, QWORD PTR [r8+40] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+72], r9 + ; A[0] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[5] + mov rax, QWORD PTR [r8+40] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+80], r10 + ; A[0] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[6] + mov rax, QWORD PTR [r8+48] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+88], r11 + ; A[0] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[6] + mov rax, QWORD PTR [r8+48] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+96], r9 + ; A[0] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[7] + mov rax, QWORD PTR [r8+56] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rsp+104], r10 + ; A[0] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[7] + mov rax, QWORD PTR [r8+56] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rsp+112], r11 + ; A[0] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[1] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+8] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[2] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[8] + mov rax, QWORD PTR [r8+64] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rsp+120], r9 + ; A[1] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+8] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[2] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+16] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[3] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[8] + mov rax, QWORD PTR [r8+64] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+128], r10 + ; A[2] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+16] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[3] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+24] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[4] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[9] + mov rax, QWORD PTR [r8+72] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+136], r11 + ; A[3] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+24] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[4] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+32] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[5] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[9] + mov rax, QWORD PTR [r8+72] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+144], r9 + ; A[4] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+32] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[5] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+40] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[6] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[10] + mov rax, QWORD PTR [r8+80] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+152], r10 + ; A[5] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+40] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[6] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+48] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[7] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[10] + mov rax, QWORD PTR [r8+80] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+160], r11 + ; A[6] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+48] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[7] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+56] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[8] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[11] + mov rax, QWORD PTR [r8+88] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+168], r9 + ; A[7] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+56] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[8] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+64] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[9] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[11] * A[11] + mov rax, QWORD PTR [r8+88] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+176], r10 + ; A[8] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+64] + xor r10, r10 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[9] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+72] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[10] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[11] * A[12] + mov rax, QWORD PTR [r8+96] + mul QWORD PTR [r8+88] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r11, r12 + adc r9, r13 + adc r10, r14 + mov QWORD PTR [rcx+184], r11 + ; A[9] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+72] + xor r11, r11 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[10] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+80] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[11] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+88] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[12] * A[12] + mov rax, QWORD PTR [r8+96] + mul rax + add r12, r12 + adc r13, r13 + adc r14, r14 + add r12, rax + adc r13, rdx + adc r14, 0 + add r9, r12 + adc r10, r13 + adc r11, r14 + mov QWORD PTR [rcx+192], r9 + ; A[10] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+80] + xor r9, r9 + xor r14, r14 + mov r12, rax + mov r13, rdx + ; A[11] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+88] + add r12, rax + adc r13, rdx + adc r14, 0 + ; A[12] * A[13] + mov rax, QWORD PTR [r8+104] + mul QWORD PTR [r8+96] + add r12, rax + adc r13, rdx + adc r14, 0 + add r12, r12 + adc r13, r13 + adc r14, r14 + add r10, r12 + adc r11, r13 + adc r9, r14 + mov QWORD PTR [rcx+200], r10 + ; A[11] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+88] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[12] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+96] + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + ; A[13] * A[13] + mov rax, QWORD PTR [r8+104] + mul rax + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+208], r11 + ; A[12] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+96] + xor r11, r11 + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + ; A[13] * A[14] + mov rax, QWORD PTR [r8+112] + mul QWORD PTR [r8+104] + add r9, rax + adc r10, rdx + adc r11, 0 + add r9, rax + adc r10, rdx + adc r11, 0 + mov QWORD PTR [rcx+216], r9 + ; A[13] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+104] + xor r9, r9 + add r10, rax + adc r11, rdx + adc r9, 0 + add r10, rax + adc r11, rdx + adc r9, 0 + ; A[14] * A[14] + mov rax, QWORD PTR [r8+112] + mul rax + add r10, rax + adc r11, rdx + adc r9, 0 + mov QWORD PTR [rcx+224], r10 + ; A[14] * A[15] + mov rax, QWORD PTR [r8+120] + mul QWORD PTR [r8+112] + xor r10, r10 + add r11, rax + adc r9, rdx + adc r10, 0 + add r11, rax + adc r9, rdx + adc r10, 0 + mov QWORD PTR [rcx+232], r11 + ; A[15] * A[15] + mov rax, QWORD PTR [r8+120] + mul rax + add r9, rax + adc r10, rdx + mov QWORD PTR [rcx+240], r9 + mov QWORD PTR [rcx+248], r10 + mov rax, QWORD PTR [rsp] + mov rdx, QWORD PTR [rsp+8] + mov r12, QWORD PTR [rsp+16] + mov r13, QWORD PTR [rsp+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], rdx + mov QWORD PTR [rcx+16], r12 + mov QWORD PTR [rcx+24], r13 + mov rax, QWORD PTR [rsp+32] + mov rdx, QWORD PTR [rsp+40] + mov r12, QWORD PTR [rsp+48] + mov r13, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], rdx + mov QWORD PTR [rcx+48], r12 + mov QWORD PTR [rcx+56], r13 + mov rax, QWORD PTR [rsp+64] + mov rdx, QWORD PTR [rsp+72] + mov r12, QWORD PTR [rsp+80] + mov r13, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], rdx + mov QWORD PTR [rcx+80], r12 + mov QWORD PTR [rcx+88], r13 + mov rax, QWORD PTR [rsp+96] + mov rdx, QWORD PTR [rsp+104] + mov r12, QWORD PTR [rsp+112] + mov r13, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], rdx + mov QWORD PTR [rcx+112], r12 + mov QWORD PTR [rcx+120], r13 + add rsp, 128 + pop r14 + pop r13 + pop r12 + ret +sp_1024_sqr_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Multiply a and b into r. (r = a * b) +; * +; * r Result of multiplication. +; * a First number to multiply. +; * b Second number to multiply. +; */ +_text SEGMENT READONLY PARA +sp_1024_mul_avx2_16 PROC + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + push rdi + mov rbp, r8 + mov r8, rcx + mov r9, rdx + sub rsp, 128 + cmp r9, r8 + mov rbx, rsp + cmovne rbx, r8 + cmp rbp, r8 + cmove rbx, rsp + add r8, 128 + xor rdi, rdi + mov rdx, QWORD PTR [r9] + ; A[0] * B[0] + mulx r11, r10, QWORD PTR [rbp] + ; A[0] * B[1] + mulx r12, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx], r10 + adcx r11, rax + ; A[0] * B[2] + mulx r13, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+8], r11 + adcx r12, rax + ; A[0] * B[3] + mulx r14, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+16], r12 + adcx r13, rax + mov QWORD PTR [rbx+24], r13 + ; A[0] * B[4] + mulx r10, rax, QWORD PTR [rbp+32] + adcx r14, rax + ; A[0] * B[5] + mulx r11, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + ; A[0] * B[6] + mulx r12, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + ; A[0] * B[7] + mulx r13, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + mov QWORD PTR [rbx+56], r12 + ; A[0] * B[8] + mulx r14, rax, QWORD PTR [rbp+64] + adcx r13, rax + ; A[0] * B[9] + mulx r10, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + ; A[0] * B[10] + mulx r11, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + ; A[0] * B[11] + mulx r12, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + mov QWORD PTR [rbx+88], r11 + ; A[0] * B[12] + mulx r13, rax, QWORD PTR [rbp+96] + adcx r12, rax + ; A[0] * B[13] + mulx r14, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + ; A[0] * B[14] + mulx r10, rax, QWORD PTR [rbp+112] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + ; A[0] * B[15] + mulx r11, rax, QWORD PTR [rbp+120] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adcx r11, rdi + mov r15, rdi + adcx r15, rdi + mov QWORD PTR [rbx+120], r10 + mov QWORD PTR [r8], r11 + mov rdx, QWORD PTR [r9+8] + mov r11, QWORD PTR [rbx+8] + mov r12, QWORD PTR [rbx+16] + mov r13, QWORD PTR [rbx+24] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + ; A[1] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[1] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+8], r11 + adcx r12, rax + adox r13, rcx + ; A[1] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+16], r12 + adcx r13, rax + adox r14, rcx + ; A[1] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+24], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+32], r14 + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + ; A[1] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[1] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + ; A[1] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[1] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+64], r13 + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + ; A[1] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r14, rax + adox r10, rcx + ; A[1] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[1] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[1] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+96], r12 + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[1] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r13, rax + adox r14, rcx + ; A[1] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[1] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[1] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [rbx+120], r10 + mov r12, rdi + adcx r11, rax + adox r12, rcx + adcx r12, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8], r11 + mov QWORD PTR [r8+8], r12 + mov rdx, QWORD PTR [r9+16] + mov r12, QWORD PTR [rbx+16] + mov r13, QWORD PTR [rbx+24] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + ; A[2] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r13, rcx + ; A[2] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+16], r12 + adcx r13, rax + adox r14, rcx + ; A[2] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+24], r13 + adcx r14, rax + adox r10, rcx + ; A[2] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+40], r10 + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + ; A[2] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[2] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[2] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[2] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+72], r14 + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + ; A[2] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[2] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[2] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[2] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+104], r13 + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[2] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r14, rax + adox r10, rcx + ; A[2] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[2] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[2] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8], r11 + mov r13, rdi + adcx r12, rax + adox r13, rcx + adcx r13, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+8], r12 + mov QWORD PTR [r8+16], r13 + mov rdx, QWORD PTR [r9+24] + mov r13, QWORD PTR [rbx+24] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + ; A[3] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r13, rax + adox r14, rcx + ; A[3] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+24], r13 + adcx r14, rax + adox r10, rcx + ; A[3] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + adox r11, rcx + ; A[3] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+48], r11 + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + ; A[3] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r13, rcx + ; A[3] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[3] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[3] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+80], r10 + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + ; A[3] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[3] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[3] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[3] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+112], r14 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[3] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r10, rax + adox r11, rcx + ; A[3] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[3] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[3] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+8], r12 + mov r14, rdi + adcx r13, rax + adox r14, rcx + adcx r14, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+16], r13 + mov QWORD PTR [r8+24], r14 + mov rdx, QWORD PTR [r9+32] + mov r14, QWORD PTR [rbx+32] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + ; A[4] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r14, rax + adox r10, rcx + ; A[4] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+32], r14 + adcx r10, rax + adox r11, rcx + ; A[4] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + ; A[4] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+56], r12 + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + ; A[4] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r13, rax + adox r14, rcx + ; A[4] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[4] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[4] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+88], r11 + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[4] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r13, rcx + ; A[4] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[4] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[4] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+120], r10 + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[4] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r11, rax + adox r12, rcx + ; A[4] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[4] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[4] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+16], r13 + mov r10, rdi + adcx r14, rax + adox r10, rcx + adcx r10, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+24], r14 + mov QWORD PTR [r8+32], r10 + mov rdx, QWORD PTR [r9+40] + mov r10, QWORD PTR [rbx+40] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + ; A[5] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[5] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+40], r10 + adcx r11, rax + adox r12, rcx + ; A[5] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[5] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+64], r13 + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + ; A[5] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r14, rax + adox r10, rcx + ; A[5] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[5] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[5] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+96], r12 + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[5] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r13, rax + adox r14, rcx + ; A[5] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[5] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[5] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8], r11 + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + ; A[5] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r12, rax + adox r13, rcx + ; A[5] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[5] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[5] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+24], r14 + mov r11, rdi + adcx r10, rax + adox r11, rcx + adcx r11, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+32], r10 + mov QWORD PTR [r8+40], r11 + mov rdx, QWORD PTR [r9+48] + mov r11, QWORD PTR [rbx+48] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + ; A[6] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[6] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+48], r11 + adcx r12, rax + adox r13, rcx + ; A[6] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[6] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+72], r14 + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + ; A[6] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[6] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[6] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[6] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+104], r13 + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[6] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r14, rax + adox r10, rcx + ; A[6] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[6] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[6] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+8], r12 + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[6] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r13, rax + adox r14, rcx + ; A[6] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[6] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[6] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+32], r10 + mov r12, rdi + adcx r11, rax + adox r12, rcx + adcx r12, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+40], r11 + mov QWORD PTR [r8+48], r12 + mov rdx, QWORD PTR [r9+56] + mov r12, QWORD PTR [rbx+56] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + ; A[7] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r13, rcx + ; A[7] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+56], r12 + adcx r13, rax + adox r14, rcx + ; A[7] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[7] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+80], r10 + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + ; A[7] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[7] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[7] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[7] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+112], r14 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[7] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[7] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[7] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[7] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+16], r13 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + ; A[7] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r14, rax + adox r10, rcx + ; A[7] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[7] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[7] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+40], r11 + mov r13, rdi + adcx r12, rax + adox r13, rcx + adcx r13, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+48], r12 + mov QWORD PTR [r8+56], r13 + mov rdx, QWORD PTR [r9+64] + mov r13, QWORD PTR [rbx+64] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + ; A[8] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r13, rax + adox r14, rcx + ; A[8] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+64], r13 + adcx r14, rax + adox r10, rcx + ; A[8] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[8] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbx+88], r11 + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[8] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r13, rcx + ; A[8] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[8] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[8] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+120], r10 + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + ; A[8] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[8] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[8] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[8] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [r8+24], r14 + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + ; A[8] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r10, rax + adox r11, rcx + ; A[8] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[8] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[8] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+48], r12 + mov r14, rdi + adcx r13, rax + adox r14, rcx + adcx r14, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+56], r13 + mov QWORD PTR [r8+64], r14 + mov rdx, QWORD PTR [r9+72] + mov r14, QWORD PTR [rbx+72] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + ; A[9] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r14, rax + adox r10, rcx + ; A[9] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+72], r14 + adcx r10, rax + adox r11, rcx + ; A[9] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[9] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [rbx+96], r12 + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[9] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r13, rax + adox r14, rcx + ; A[9] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[9] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[9] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8], r11 + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[9] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r13, rcx + ; A[9] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[9] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[9] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+32], r10 + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + ; A[9] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r11, rax + adox r12, rcx + ; A[9] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[9] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[9] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+56], r13 + mov r10, rdi + adcx r14, rax + adox r10, rcx + adcx r10, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+64], r14 + mov QWORD PTR [r8+72], r10 + mov rdx, QWORD PTR [r9+80] + mov r10, QWORD PTR [rbx+80] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + ; A[10] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[10] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+80], r10 + adcx r11, rax + adox r12, rcx + ; A[10] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[10] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [rbx+104], r13 + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[10] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r14, rax + adox r10, rcx + ; A[10] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[10] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[10] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+8], r12 + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + ; A[10] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r13, rax + adox r14, rcx + ; A[10] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[10] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[10] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r11 + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[10] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r12, rax + adox r13, rcx + ; A[10] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[10] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[10] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+64], r14 + mov r11, rdi + adcx r10, rax + adox r11, rcx + adcx r11, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+72], r10 + mov QWORD PTR [r8+80], r11 + mov rdx, QWORD PTR [r9+88] + mov r11, QWORD PTR [rbx+88] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + ; A[11] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r11, rax + adox r12, rcx + ; A[11] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+88], r11 + adcx r12, rax + adox r13, rcx + ; A[11] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[11] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [rbx+112], r14 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[11] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r10, rax + adox r11, rcx + ; A[11] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[11] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[11] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+16], r13 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + ; A[11] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r14, rax + adox r10, rcx + ; A[11] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[11] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[11] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+48], r12 + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + ; A[11] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r13, rax + adox r14, rcx + ; A[11] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[11] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + ; A[11] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+72], r10 + mov r12, rdi + adcx r11, rax + adox r12, rcx + adcx r12, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+80], r11 + mov QWORD PTR [r8+88], r12 + mov rdx, QWORD PTR [r9+96] + mov r12, QWORD PTR [rbx+96] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + ; A[12] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r12, rax + adox r13, rcx + ; A[12] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+96], r12 + adcx r13, rax + adox r14, rcx + ; A[12] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[12] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbx+120], r10 + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + ; A[12] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r11, rax + adox r12, rcx + ; A[12] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[12] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[12] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [r8+24], r14 + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + ; A[12] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r10, rax + adox r11, rcx + ; A[12] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[12] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[12] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+56], r13 + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + mov r12, QWORD PTR [r8+88] + ; A[12] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r14, rax + adox r10, rcx + ; A[12] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + ; A[12] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+72], r10 + adcx r11, rax + adox r12, rcx + ; A[12] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+80], r11 + mov r13, rdi + adcx r12, rax + adox r13, rcx + adcx r13, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+88], r12 + mov QWORD PTR [r8+96], r13 + mov rdx, QWORD PTR [r9+104] + mov r13, QWORD PTR [rbx+104] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[13] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r13, rax + adox r14, rcx + ; A[13] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+104], r13 + adcx r14, rax + adox r10, rcx + ; A[13] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[13] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8], r11 + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[13] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r12, rax + adox r13, rcx + ; A[13] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + ; A[13] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[13] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+32], r10 + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[13] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r11, rax + adox r12, rcx + ; A[13] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + ; A[13] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[13] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + mov QWORD PTR [r8+64], r14 + mov r11, QWORD PTR [r8+80] + mov r12, QWORD PTR [r8+88] + mov r13, QWORD PTR [r8+96] + ; A[13] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r10, rax + adox r11, rcx + ; A[13] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+72], r10 + adcx r11, rax + adox r12, rcx + ; A[13] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+80], r11 + adcx r12, rax + adox r13, rcx + ; A[13] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+88], r12 + mov r14, rdi + adcx r13, rax + adox r14, rcx + adcx r14, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+96], r13 + mov QWORD PTR [r8+104], r14 + mov rdx, QWORD PTR [r9+112] + mov r14, QWORD PTR [rbx+112] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + ; A[14] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r14, rax + adox r10, rcx + ; A[14] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+112], r14 + adcx r10, rax + adox r11, rcx + ; A[14] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[14] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+8], r12 + mov r14, QWORD PTR [r8+24] + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + ; A[14] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r13, rax + adox r14, rcx + ; A[14] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+16], r13 + adcx r14, rax + adox r10, rcx + ; A[14] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[14] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r11 + mov r13, QWORD PTR [r8+56] + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + ; A[14] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r12, rax + adox r13, rcx + ; A[14] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+48], r12 + adcx r13, rax + adox r14, rcx + ; A[14] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[14] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+72], r10 + mov r12, QWORD PTR [r8+88] + mov r13, QWORD PTR [r8+96] + mov r14, QWORD PTR [r8+104] + ; A[14] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r11, rax + adox r12, rcx + ; A[14] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+80], r11 + adcx r12, rax + adox r13, rcx + ; A[14] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+88], r12 + adcx r13, rax + adox r14, rcx + ; A[14] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+96], r13 + mov r10, rdi + adcx r14, rax + adox r10, rcx + adcx r10, r15 + mov r15, rdi + adox r15, rdi + adcx r15, rdi + mov QWORD PTR [r8+104], r14 + mov QWORD PTR [r8+112], r10 + mov rdx, QWORD PTR [r9+120] + mov r10, QWORD PTR [rbx+120] + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + mov r13, QWORD PTR [r8+16] + mov r14, QWORD PTR [r8+24] + ; A[15] * B[0] + mulx rcx, rax, QWORD PTR [rbp] + adcx r10, rax + adox r11, rcx + ; A[15] * B[1] + mulx rcx, rax, QWORD PTR [rbp+8] + mov QWORD PTR [rbx+120], r10 + adcx r11, rax + adox r12, rcx + ; A[15] * B[2] + mulx rcx, rax, QWORD PTR [rbp+16] + mov QWORD PTR [r8], r11 + adcx r12, rax + adox r13, rcx + ; A[15] * B[3] + mulx rcx, rax, QWORD PTR [rbp+24] + mov QWORD PTR [r8+8], r12 + adcx r13, rax + adox r14, rcx + mov QWORD PTR [r8+16], r13 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov r12, QWORD PTR [r8+48] + mov r13, QWORD PTR [r8+56] + ; A[15] * B[4] + mulx rcx, rax, QWORD PTR [rbp+32] + adcx r14, rax + adox r10, rcx + ; A[15] * B[5] + mulx rcx, rax, QWORD PTR [rbp+40] + mov QWORD PTR [r8+24], r14 + adcx r10, rax + adox r11, rcx + ; A[15] * B[6] + mulx rcx, rax, QWORD PTR [rbp+48] + mov QWORD PTR [r8+32], r10 + adcx r11, rax + adox r12, rcx + ; A[15] * B[7] + mulx rcx, rax, QWORD PTR [rbp+56] + mov QWORD PTR [r8+40], r11 + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r8+48], r12 + mov r14, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + mov r11, QWORD PTR [r8+80] + mov r12, QWORD PTR [r8+88] + ; A[15] * B[8] + mulx rcx, rax, QWORD PTR [rbp+64] + adcx r13, rax + adox r14, rcx + ; A[15] * B[9] + mulx rcx, rax, QWORD PTR [rbp+72] + mov QWORD PTR [r8+56], r13 + adcx r14, rax + adox r10, rcx + ; A[15] * B[10] + mulx rcx, rax, QWORD PTR [rbp+80] + mov QWORD PTR [r8+64], r14 + adcx r10, rax + adox r11, rcx + ; A[15] * B[11] + mulx rcx, rax, QWORD PTR [rbp+88] + mov QWORD PTR [r8+72], r10 + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+80], r11 + mov r13, QWORD PTR [r8+96] + mov r14, QWORD PTR [r8+104] + mov r10, QWORD PTR [r8+112] + ; A[15] * B[12] + mulx rcx, rax, QWORD PTR [rbp+96] + adcx r12, rax + adox r13, rcx + ; A[15] * B[13] + mulx rcx, rax, QWORD PTR [rbp+104] + mov QWORD PTR [r8+88], r12 + adcx r13, rax + adox r14, rcx + ; A[15] * B[14] + mulx rcx, rax, QWORD PTR [rbp+112] + mov QWORD PTR [r8+96], r13 + adcx r14, rax + adox r10, rcx + ; A[15] * B[15] + mulx rcx, rax, QWORD PTR [rbp+120] + mov QWORD PTR [r8+104], r14 + mov r11, rdi + adcx r10, rax + adox r11, rcx + adcx r11, r15 + mov QWORD PTR [r8+112], r10 + mov QWORD PTR [r8+120], r11 + sub r8, 128 + cmp r9, r8 + je L_start_1024_mul_avx2_16 + cmp rbp, r8 + jne L_end_1024_mul_avx2_16 +L_start_1024_mul_avx2_16: + vmovdqu xmm0, OWORD PTR [rbx] + vmovups OWORD PTR [r8], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+16] + vmovups OWORD PTR [r8+16], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+32] + vmovups OWORD PTR [r8+32], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+48] + vmovups OWORD PTR [r8+48], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+64] + vmovups OWORD PTR [r8+64], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+80] + vmovups OWORD PTR [r8+80], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+96] + vmovups OWORD PTR [r8+96], xmm0 + vmovdqu xmm0, OWORD PTR [rbx+112] + vmovups OWORD PTR [r8+112], xmm0 +L_end_1024_mul_avx2_16: + add rsp, 128 + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + ret +sp_1024_mul_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Square a and put result in r. (r = a * a) +; * +; * r A single precision integer. +; * a A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_1024_sqr_avx2_16 PROC + push rbp + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + mov r8, rcx + mov r9, rdx + sub rsp, 128 + cmp r9, r8 + mov rbp, rsp + cmovne rbp, r8 + add r8, 128 + xor r13, r13 + ; Diagonal 1 + xor r12, r12 + ; A[1] x A[0] + mov rdx, QWORD PTR [r9] + mulx r11, r10, QWORD PTR [r9+8] + ; A[2] x A[0] + mulx rcx, rax, QWORD PTR [r9+16] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+8], r10 + mov QWORD PTR [rbp+16], r11 + mov r10, r13 + mov r11, r13 + ; A[3] x A[0] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r12, rax + adox r10, rcx + ; A[4] x A[0] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+24], r12 + mov QWORD PTR [rbp+32], r10 + mov r12, r13 + mov r10, r13 + ; A[5] x A[0] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r11, rax + adox r12, rcx + ; A[6] x A[0] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+40], r11 + mov QWORD PTR [rbp+48], r12 + mov r11, r13 + mov r12, r13 + ; A[7] x A[0] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + ; A[8] x A[0] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+56], r10 + mov QWORD PTR [rbp+64], r11 + mov r10, r13 + mov r11, r13 + ; A[9] x A[0] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r12, rax + adox r10, rcx + ; A[10] x A[0] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+72], r12 + mov QWORD PTR [rbp+80], r10 + mov r12, r13 + mov r10, r13 + ; A[11] x A[0] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r11, rax + adox r12, rcx + ; A[12] x A[0] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+88], r11 + mov r15, r12 + mov r11, r13 + mov r12, r13 + ; A[13] x A[0] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r10, rax + adox r11, rcx + ; A[14] x A[0] + mulx rcx, rax, QWORD PTR [r9+112] + adcx r11, rax + adox r12, rcx + mov rdi, r10 + mov rsi, r11 + mov r10, r13 + ; A[15] x A[0] + mulx rcx, rax, QWORD PTR [r9+120] + adcx r12, rax + adox r10, rcx + mov rbx, r12 + ; Carry + adcx r10, r13 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8], r10 + ; Diagonal 2 + mov r10, QWORD PTR [rbp+24] + mov r11, QWORD PTR [rbp+32] + mov r12, QWORD PTR [rbp+40] + ; A[2] x A[1] + mov rdx, QWORD PTR [r9+8] + mulx rcx, rax, QWORD PTR [r9+16] + adcx r10, rax + adox r11, rcx + ; A[3] x A[1] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+24], r10 + mov QWORD PTR [rbp+32], r11 + mov r10, QWORD PTR [rbp+48] + mov r11, QWORD PTR [rbp+56] + ; A[4] x A[1] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r12, rax + adox r10, rcx + ; A[5] x A[1] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+40], r12 + mov QWORD PTR [rbp+48], r10 + mov r12, QWORD PTR [rbp+64] + mov r10, QWORD PTR [rbp+72] + ; A[6] x A[1] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r12, rcx + ; A[7] x A[1] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+56], r11 + mov QWORD PTR [rbp+64], r12 + mov r11, QWORD PTR [rbp+80] + mov r12, QWORD PTR [rbp+88] + ; A[8] x A[1] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r10, rax + adox r11, rcx + ; A[9] x A[1] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+72], r10 + mov QWORD PTR [rbp+80], r11 + ; No load %r13 - %r8 + ; No load %r14 - %r9 + ; A[10] x A[1] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r12, rax + adox r15, rcx + ; A[11] x A[1] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r12 + ; No store %r13 + ; No load %r15 - %r10 + ; No load %rbx - %r8 + ; A[12] x A[1] + mulx rcx, rax, QWORD PTR [r9+96] + adcx rdi, rax + adox rsi, rcx + ; A[13] x A[1] + mulx rcx, rax, QWORD PTR [r9+104] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r11, QWORD PTR [r8] + mov r12, r13 + ; A[14] x A[1] + mulx rcx, rax, QWORD PTR [r9+112] + adcx rbx, rax + adox r11, rcx + ; A[15] x A[1] + mulx rcx, rax, QWORD PTR [r9+120] + adcx r11, rax + adox r12, rcx + ; No store %rbx + mov QWORD PTR [r8], r11 + mov r10, r13 + ; A[15] x A[2] + mov rdx, QWORD PTR [r9+16] + mulx rcx, rax, QWORD PTR [r9+120] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+8], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+16], r10 + ; Diagonal 3 + mov r10, QWORD PTR [rbp+40] + mov r11, QWORD PTR [rbp+48] + mov r12, QWORD PTR [rbp+56] + ; A[3] x A[2] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + ; A[4] x A[2] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+40], r10 + mov QWORD PTR [rbp+48], r11 + mov r10, QWORD PTR [rbp+64] + mov r11, QWORD PTR [rbp+72] + ; A[5] x A[2] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + ; A[6] x A[2] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+56], r12 + mov QWORD PTR [rbp+64], r10 + mov r12, QWORD PTR [rbp+80] + mov r10, QWORD PTR [rbp+88] + ; A[7] x A[2] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + ; A[8] x A[2] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [rbp+72], r11 + mov QWORD PTR [rbp+80], r12 + ; No load %r13 - %r9 + ; No load %r14 - %r10 + ; A[9] x A[2] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r15, rcx + ; A[10] x A[2] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r10 + ; No store %r13 + ; No load %r15 - %r8 + ; No load %rbx - %r9 + ; A[11] x A[2] + mulx rcx, rax, QWORD PTR [r9+88] + adcx rdi, rax + adox rsi, rcx + ; A[12] x A[2] + mulx rcx, rax, QWORD PTR [r9+96] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [r8+8] + ; A[13] x A[2] + mulx rcx, rax, QWORD PTR [r9+104] + adcx rbx, rax + adox r12, rcx + ; A[14] x A[2] + mulx rcx, rax, QWORD PTR [r9+112] + adcx r12, rax + adox r10, rcx + ; No store %rbx + mov QWORD PTR [r8], r12 + mov r11, QWORD PTR [r8+16] + mov r12, r13 + ; A[14] x A[3] + mov rdx, QWORD PTR [r9+112] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + ; A[14] x A[4] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r10 + mov QWORD PTR [r8+16], r11 + mov r10, r13 + ; A[14] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+24], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+32], r10 + ; Diagonal 4 + mov r10, QWORD PTR [rbp+56] + mov r11, QWORD PTR [rbp+64] + mov r12, QWORD PTR [rbp+72] + ; A[4] x A[3] + mov rdx, QWORD PTR [r9+24] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r10, rax + adox r11, rcx + ; A[5] x A[3] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+56], r10 + mov QWORD PTR [rbp+64], r11 + mov r10, QWORD PTR [rbp+80] + mov r11, QWORD PTR [rbp+88] + ; A[6] x A[3] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r12, rax + adox r10, rcx + ; A[7] x A[3] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [rbp+72], r12 + mov QWORD PTR [rbp+80], r10 + ; No load %r13 - %r10 + ; No load %r14 - %r8 + ; A[8] x A[3] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r11, rax + adox r15, rcx + ; A[9] x A[3] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r11 + ; No store %r13 + ; No load %r15 - %r9 + ; No load %rbx - %r10 + ; A[10] x A[3] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rdi, rax + adox rsi, rcx + ; A[11] x A[3] + mulx rcx, rax, QWORD PTR [r9+88] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[12] x A[3] + mulx rcx, rax, QWORD PTR [r9+96] + adcx rbx, rax + adox r10, rcx + ; A[13] x A[3] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r10, rax + adox r11, rcx + ; No store %rbx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[13] x A[4] + mov rdx, QWORD PTR [r9+104] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + ; A[13] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, r13 + ; A[13] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + ; A[13] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+24], r10 + mov QWORD PTR [r8+32], r11 + mov r10, r13 + ; A[13] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+40], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+48], r10 + ; Diagonal 5 + mov r10, QWORD PTR [rbp+72] + mov r11, QWORD PTR [rbp+80] + mov r12, QWORD PTR [rbp+88] + ; A[5] x A[4] + mov rdx, QWORD PTR [r9+32] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r10, rax + adox r11, rcx + ; A[6] x A[4] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [rbp+72], r10 + mov QWORD PTR [rbp+80], r11 + ; No load %r13 - %r8 + ; No load %r14 - %r9 + ; A[7] x A[4] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r12, rax + adox r15, rcx + ; A[8] x A[4] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r12 + ; No store %r13 + ; No load %r15 - %r10 + ; No load %rbx - %r8 + ; A[9] x A[4] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rdi, rax + adox rsi, rcx + ; A[10] x A[4] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[11] x A[4] + mulx rcx, rax, QWORD PTR [r9+88] + adcx rbx, rax + adox r11, rcx + ; A[12] x A[4] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r11, rax + adox r12, rcx + ; No store %rbx + mov QWORD PTR [r8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[12] x A[5] + mov rdx, QWORD PTR [r9+96] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + ; A[12] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+8], r12 + mov QWORD PTR [r8+16], r10 + mov r12, QWORD PTR [r8+32] + mov r10, QWORD PTR [r8+40] + ; A[12] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + ; A[12] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+24], r11 + mov QWORD PTR [r8+32], r12 + mov r11, QWORD PTR [r8+48] + mov r12, r13 + ; A[12] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + ; A[12] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r10 + mov QWORD PTR [r8+48], r11 + mov r10, r13 + ; A[12] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+56], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+64], r10 + ; Diagonal 6 + mov r10, QWORD PTR [rbp+88] + ; No load %r13 - %r9 + ; No load %r14 - %r10 + ; A[6] x A[5] + mov rdx, QWORD PTR [r9+40] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r15, rcx + ; A[7] x A[5] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r15, rax + adox rdi, rcx + mov QWORD PTR [rbp+88], r10 + ; No store %r13 + ; No load %r15 - %r8 + ; No load %rbx - %r9 + ; A[8] x A[5] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rdi, rax + adox rsi, rcx + ; A[9] x A[5] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [r8+8] + ; A[10] x A[5] + mulx rcx, rax, QWORD PTR [r9+80] + adcx rbx, rax + adox r12, rcx + ; A[11] x A[5] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r12, rax + adox r10, rcx + ; No store %rbx + mov QWORD PTR [r8], r12 + mov r11, QWORD PTR [r8+16] + mov r12, QWORD PTR [r8+24] + ; A[11] x A[6] + mov rdx, QWORD PTR [r9+88] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + ; A[11] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+8], r10 + mov QWORD PTR [r8+16], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[11] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + ; A[11] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+24], r12 + mov QWORD PTR [r8+32], r10 + mov r12, QWORD PTR [r8+48] + mov r10, QWORD PTR [r8+56] + ; A[11] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r12, rcx + ; A[13] x A[9] + mov rdx, QWORD PTR [r9+104] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+40], r11 + mov QWORD PTR [r8+48], r12 + mov r11, QWORD PTR [r8+64] + mov r12, r13 + ; A[13] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r10, rax + adox r11, rcx + ; A[13] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+56], r10 + mov QWORD PTR [r8+64], r11 + mov r10, r13 + ; A[13] x A[12] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+72], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+80], r10 + ; Diagonal 7 + ; No load %r14 - %r8 + ; No load %r15 - %r9 + ; No load %rbx - %r10 + ; A[7] x A[6] + mov rdx, QWORD PTR [r9+48] + mulx rcx, rax, QWORD PTR [r9+56] + adcx rdi, rax + adox rsi, rcx + ; A[8] x A[6] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rsi, rax + adox rbx, rcx + ; No store %r14 + ; No store %r15 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[9] x A[6] + mulx rcx, rax, QWORD PTR [r9+72] + adcx rbx, rax + adox r10, rcx + ; A[10] x A[6] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r10, rax + adox r11, rcx + ; No store %rbx + mov QWORD PTR [r8], r10 + mov r12, QWORD PTR [r8+16] + mov r10, QWORD PTR [r8+24] + ; A[10] x A[7] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + ; A[10] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+8], r11 + mov QWORD PTR [r8+16], r12 + mov r11, QWORD PTR [r8+32] + mov r12, QWORD PTR [r8+40] + ; A[10] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + ; A[14] x A[6] + mov rdx, QWORD PTR [r9+112] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+24], r10 + mov QWORD PTR [r8+32], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[14] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r12, rax + adox r10, rcx + ; A[14] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+40], r12 + mov QWORD PTR [r8+48], r10 + mov r12, QWORD PTR [r8+64] + mov r10, QWORD PTR [r8+72] + ; A[14] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r11, rax + adox r12, rcx + ; A[14] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+56], r11 + mov QWORD PTR [r8+64], r12 + mov r11, QWORD PTR [r8+80] + mov r12, r13 + ; A[14] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r10, rax + adox r11, rcx + ; A[14] x A[12] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+72], r10 + mov QWORD PTR [r8+80], r11 + mov r10, r13 + ; A[14] x A[13] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+88], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+96], r10 + ; Diagonal 8 + ; No load %rbx - %r8 + mov r11, QWORD PTR [r8] + mov r12, QWORD PTR [r8+8] + ; A[8] x A[7] + mov rdx, QWORD PTR [r9+56] + mulx rcx, rax, QWORD PTR [r9+64] + adcx rbx, rax + adox r11, rcx + ; A[9] x A[7] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r11, rax + adox r12, rcx + ; No store %rbx + mov QWORD PTR [r8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[9] x A[8] + mov rdx, QWORD PTR [r9+64] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r12, rax + adox r10, rcx + ; A[15] x A[3] + mov rdx, QWORD PTR [r9+120] + mulx rcx, rax, QWORD PTR [r9+24] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+8], r12 + mov QWORD PTR [r8+16], r10 + mov r12, QWORD PTR [r8+32] + mov r10, QWORD PTR [r8+40] + ; A[15] x A[4] + mulx rcx, rax, QWORD PTR [r9+32] + adcx r11, rax + adox r12, rcx + ; A[15] x A[5] + mulx rcx, rax, QWORD PTR [r9+40] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+24], r11 + mov QWORD PTR [r8+32], r12 + mov r11, QWORD PTR [r8+48] + mov r12, QWORD PTR [r8+56] + ; A[15] x A[6] + mulx rcx, rax, QWORD PTR [r9+48] + adcx r10, rax + adox r11, rcx + ; A[15] x A[7] + mulx rcx, rax, QWORD PTR [r9+56] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+40], r10 + mov QWORD PTR [r8+48], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + ; A[15] x A[8] + mulx rcx, rax, QWORD PTR [r9+64] + adcx r12, rax + adox r10, rcx + ; A[15] x A[9] + mulx rcx, rax, QWORD PTR [r9+72] + adcx r10, rax + adox r11, rcx + mov QWORD PTR [r8+56], r12 + mov QWORD PTR [r8+64], r10 + mov r12, QWORD PTR [r8+80] + mov r10, QWORD PTR [r8+88] + ; A[15] x A[10] + mulx rcx, rax, QWORD PTR [r9+80] + adcx r11, rax + adox r12, rcx + ; A[15] x A[11] + mulx rcx, rax, QWORD PTR [r9+88] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+72], r11 + mov QWORD PTR [r8+80], r12 + mov r11, QWORD PTR [r8+96] + mov r12, r13 + ; A[15] x A[12] + mulx rcx, rax, QWORD PTR [r9+96] + adcx r10, rax + adox r11, rcx + ; A[15] x A[13] + mulx rcx, rax, QWORD PTR [r9+104] + adcx r11, rax + adox r12, rcx + mov QWORD PTR [r8+88], r10 + mov QWORD PTR [r8+96], r11 + mov r10, r13 + ; A[15] x A[14] + mulx rcx, rax, QWORD PTR [r9+112] + adcx r12, rax + adox r10, rcx + mov QWORD PTR [r8+104], r12 + ; Carry + adcx r10, r14 + mov r14, r13 + adcx r14, r13 + adox r14, r13 + mov QWORD PTR [r8+112], r10 + mov QWORD PTR [r8+120], r14 + ; Double and Add in A[i] x A[i] + mov r11, QWORD PTR [rbp+8] + ; A[0] x A[0] + mov rdx, QWORD PTR [r9] + mulx rcx, rax, rdx + mov QWORD PTR [rbp], rax + adox r11, r11 + adcx r11, rcx + mov QWORD PTR [rbp+8], r11 + mov r10, QWORD PTR [rbp+16] + mov r11, QWORD PTR [rbp+24] + ; A[1] x A[1] + mov rdx, QWORD PTR [r9+8] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+16], r10 + mov QWORD PTR [rbp+24], r11 + mov r10, QWORD PTR [rbp+32] + mov r11, QWORD PTR [rbp+40] + ; A[2] x A[2] + mov rdx, QWORD PTR [r9+16] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+32], r10 + mov QWORD PTR [rbp+40], r11 + mov r10, QWORD PTR [rbp+48] + mov r11, QWORD PTR [rbp+56] + ; A[3] x A[3] + mov rdx, QWORD PTR [r9+24] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+48], r10 + mov QWORD PTR [rbp+56], r11 + mov r10, QWORD PTR [rbp+64] + mov r11, QWORD PTR [rbp+72] + ; A[4] x A[4] + mov rdx, QWORD PTR [r9+32] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+64], r10 + mov QWORD PTR [rbp+72], r11 + mov r10, QWORD PTR [rbp+80] + mov r11, QWORD PTR [rbp+88] + ; A[5] x A[5] + mov rdx, QWORD PTR [r9+40] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [rbp+80], r10 + mov QWORD PTR [rbp+88], r11 + ; A[6] x A[6] + mov rdx, QWORD PTR [r9+48] + mulx rcx, rax, rdx + adox r15, r15 + adox rdi, rdi + adcx r15, rax + adcx rdi, rcx + ; A[7] x A[7] + mov rdx, QWORD PTR [r9+56] + mulx rcx, rax, rdx + adox rsi, rsi + adox rbx, rbx + adcx rsi, rax + adcx rbx, rcx + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + ; A[8] x A[8] + mov rdx, QWORD PTR [r9+64] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8], r10 + mov QWORD PTR [r8+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + ; A[9] x A[9] + mov rdx, QWORD PTR [r9+72] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+16], r10 + mov QWORD PTR [r8+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + ; A[10] x A[10] + mov rdx, QWORD PTR [r9+80] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+32], r10 + mov QWORD PTR [r8+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + ; A[11] x A[11] + mov rdx, QWORD PTR [r9+88] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+48], r10 + mov QWORD PTR [r8+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + ; A[12] x A[12] + mov rdx, QWORD PTR [r9+96] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+64], r10 + mov QWORD PTR [r8+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + ; A[13] x A[13] + mov rdx, QWORD PTR [r9+104] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+80], r10 + mov QWORD PTR [r8+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + ; A[14] x A[14] + mov rdx, QWORD PTR [r9+112] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+96], r10 + mov QWORD PTR [r8+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + ; A[15] x A[15] + mov rdx, QWORD PTR [r9+120] + mulx rcx, rax, rdx + adox r10, r10 + adox r11, r11 + adcx r10, rax + adcx r11, rcx + mov QWORD PTR [r8+112], r10 + mov QWORD PTR [r8+120], r11 + mov QWORD PTR [r8+-32], r15 + mov QWORD PTR [r8+-24], rdi + mov QWORD PTR [r8+-16], rsi + mov QWORD PTR [r8+-8], rbx + sub r8, 128 + cmp r9, r8 + jne L_end_1024_sqr_avx2_16 + vmovdqu xmm0, OWORD PTR [rbp] + vmovups OWORD PTR [r8], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+16] + vmovups OWORD PTR [r8+16], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+32] + vmovups OWORD PTR [r8+32], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+48] + vmovups OWORD PTR [r8+48], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+64] + vmovups OWORD PTR [r8+64], xmm0 + vmovdqu xmm0, OWORD PTR [rbp+80] + vmovups OWORD PTR [r8+80], xmm0 +L_end_1024_sqr_avx2_16: + add rsp, 128 + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + ret +sp_1024_sqr_avx2_16 ENDP +_text ENDS +ENDIF +; /* Add b to a into r. (r = a + b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_1024_add_16 PROC + ; Add + mov r9, QWORD PTR [rdx] + xor rax, rax + add r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + adc r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + adc r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + adc r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + adc r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + adc r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + adc r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + adc r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + adc r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + adc r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + adc r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + adc r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + adc r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + adc r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + adc r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + adc r10, QWORD PTR [r8+120] + mov QWORD PTR [rcx+120], r10 + adc rax, 0 + ret +sp_1024_add_16 ENDP +_text ENDS +; /* Sub b from a into a. (a -= b) +; * +; * a A single precision integer and result. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_1024_sub_in_place_16 PROC + mov r8, QWORD PTR [rcx] + xor rax, rax + sub r8, QWORD PTR [rdx] + mov r9, QWORD PTR [rcx+8] + mov QWORD PTR [rcx], r8 + sbb r9, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rcx+16] + mov QWORD PTR [rcx+8], r9 + sbb r8, QWORD PTR [rdx+16] + mov r9, QWORD PTR [rcx+24] + mov QWORD PTR [rcx+16], r8 + sbb r9, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rcx+32] + mov QWORD PTR [rcx+24], r9 + sbb r8, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rcx+40] + mov QWORD PTR [rcx+32], r8 + sbb r9, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rcx+48] + mov QWORD PTR [rcx+40], r9 + sbb r8, QWORD PTR [rdx+48] + mov r9, QWORD PTR [rcx+56] + mov QWORD PTR [rcx+48], r8 + sbb r9, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rcx+64] + mov QWORD PTR [rcx+56], r9 + sbb r8, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rcx+72] + mov QWORD PTR [rcx+64], r8 + sbb r9, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rcx+80] + mov QWORD PTR [rcx+72], r9 + sbb r8, QWORD PTR [rdx+80] + mov r9, QWORD PTR [rcx+88] + mov QWORD PTR [rcx+80], r8 + sbb r9, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rcx+96] + mov QWORD PTR [rcx+88], r9 + sbb r8, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rcx+104] + mov QWORD PTR [rcx+96], r8 + sbb r9, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rcx+112] + mov QWORD PTR [rcx+104], r9 + sbb r8, QWORD PTR [rdx+112] + mov r9, QWORD PTR [rcx+120] + mov QWORD PTR [rcx+112], r8 + sbb r9, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+120], r9 + sbb rax, 0 + ret +sp_1024_sub_in_place_16 ENDP +_text ENDS +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_1024_cond_sub_16 PROC + sub rsp, 128 + mov rax, 0 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r9 + and r11, r9 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov r10, QWORD PTR [rdx] + mov r8, QWORD PTR [rsp] + sub r10, r8 + mov r11, QWORD PTR [rdx+8] + mov r8, QWORD PTR [rsp+8] + sbb r11, r8 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rdx+16] + mov r8, QWORD PTR [rsp+16] + sbb r10, r8 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rdx+24] + mov r8, QWORD PTR [rsp+24] + sbb r11, r8 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rdx+32] + mov r8, QWORD PTR [rsp+32] + sbb r10, r8 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rdx+40] + mov r8, QWORD PTR [rsp+40] + sbb r11, r8 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rdx+48] + mov r8, QWORD PTR [rsp+48] + sbb r10, r8 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rdx+56] + mov r8, QWORD PTR [rsp+56] + sbb r11, r8 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rdx+64] + mov r8, QWORD PTR [rsp+64] + sbb r10, r8 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rdx+72] + mov r8, QWORD PTR [rsp+72] + sbb r11, r8 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rdx+80] + mov r8, QWORD PTR [rsp+80] + sbb r10, r8 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rdx+88] + mov r8, QWORD PTR [rsp+88] + sbb r11, r8 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rdx+96] + mov r8, QWORD PTR [rsp+96] + sbb r10, r8 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rdx+104] + mov r8, QWORD PTR [rsp+104] + sbb r11, r8 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rdx+112] + mov r8, QWORD PTR [rsp+112] + sbb r10, r8 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rdx+120] + mov r8, QWORD PTR [rsp+120] + sbb r11, r8 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb rax, 0 + add rsp, 128 + ret +sp_1024_cond_sub_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Conditionally subtract b from a using the mask m. +; * m is -1 to subtract and 0 when not copying. +; * +; * r A single precision number representing condition subtract result. +; * a A single precision number to subtract from. +; * b A single precision number to subtract. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_1024_cond_sub_avx2_16 PROC + push r12 + mov rax, 0 + mov r12, QWORD PTR [r8] + mov r10, QWORD PTR [rdx] + pext r12, r12, r9 + sub r10, r12 + mov r12, QWORD PTR [r8+8] + mov r11, QWORD PTR [rdx+8] + pext r12, r12, r9 + mov QWORD PTR [rcx], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+16] + mov r12, QWORD PTR [rdx+16] + pext r10, r10, r9 + mov QWORD PTR [rcx+8], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+24] + pext r11, r11, r9 + mov QWORD PTR [rcx+16], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+32] + mov r11, QWORD PTR [rdx+32] + pext r12, r12, r9 + mov QWORD PTR [rcx+24], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+40] + mov r12, QWORD PTR [rdx+40] + pext r10, r10, r9 + mov QWORD PTR [rcx+32], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+48] + pext r11, r11, r9 + mov QWORD PTR [rcx+40], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+56] + mov r11, QWORD PTR [rdx+56] + pext r12, r12, r9 + mov QWORD PTR [rcx+48], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+64] + mov r12, QWORD PTR [rdx+64] + pext r10, r10, r9 + mov QWORD PTR [rcx+56], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+72] + pext r11, r11, r9 + mov QWORD PTR [rcx+64], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+80] + mov r11, QWORD PTR [rdx+80] + pext r12, r12, r9 + mov QWORD PTR [rcx+72], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+88] + mov r12, QWORD PTR [rdx+88] + pext r10, r10, r9 + mov QWORD PTR [rcx+80], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+96] + pext r11, r11, r9 + mov QWORD PTR [rcx+88], r12 + sbb r10, r11 + mov r12, QWORD PTR [r8+104] + mov r11, QWORD PTR [rdx+104] + pext r12, r12, r9 + mov QWORD PTR [rcx+96], r10 + sbb r11, r12 + mov r10, QWORD PTR [r8+112] + mov r12, QWORD PTR [rdx+112] + pext r10, r10, r9 + mov QWORD PTR [rcx+104], r11 + sbb r12, r10 + mov r11, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+120] + pext r11, r11, r9 + mov QWORD PTR [rcx+112], r12 + sbb r10, r11 + mov QWORD PTR [rcx+120], r10 + sbb rax, 0 + pop r12 + ret +sp_1024_cond_sub_avx2_16 ENDP +_text ENDS +ENDIF +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_1024_mul_d_16 PROC + push r12 + mov r9, rdx + ; A[0] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9] + mov r10, rax + mov r11, rdx + mov QWORD PTR [rcx], r10 + ; A[1] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+8] + add r11, rax + mov QWORD PTR [rcx+8], r11 + adc r12, rdx + adc r10, 0 + ; A[2] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+16] + add r12, rax + mov QWORD PTR [rcx+16], r12 + adc r10, rdx + adc r11, 0 + ; A[3] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+24] + add r10, rax + mov QWORD PTR [rcx+24], r10 + adc r11, rdx + adc r12, 0 + ; A[4] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+32] + add r11, rax + mov QWORD PTR [rcx+32], r11 + adc r12, rdx + adc r10, 0 + ; A[5] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+40] + add r12, rax + mov QWORD PTR [rcx+40], r12 + adc r10, rdx + adc r11, 0 + ; A[6] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+48] + add r10, rax + mov QWORD PTR [rcx+48], r10 + adc r11, rdx + adc r12, 0 + ; A[7] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+56] + add r11, rax + mov QWORD PTR [rcx+56], r11 + adc r12, rdx + adc r10, 0 + ; A[8] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+64] + add r12, rax + mov QWORD PTR [rcx+64], r12 + adc r10, rdx + adc r11, 0 + ; A[9] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+72] + add r10, rax + mov QWORD PTR [rcx+72], r10 + adc r11, rdx + adc r12, 0 + ; A[10] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+80] + add r11, rax + mov QWORD PTR [rcx+80], r11 + adc r12, rdx + adc r10, 0 + ; A[11] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+88] + add r12, rax + mov QWORD PTR [rcx+88], r12 + adc r10, rdx + adc r11, 0 + ; A[12] * B + mov rax, r8 + xor r12, r12 + mul QWORD PTR [r9+96] + add r10, rax + mov QWORD PTR [rcx+96], r10 + adc r11, rdx + adc r12, 0 + ; A[13] * B + mov rax, r8 + xor r10, r10 + mul QWORD PTR [r9+104] + add r11, rax + mov QWORD PTR [rcx+104], r11 + adc r12, rdx + adc r10, 0 + ; A[14] * B + mov rax, r8 + xor r11, r11 + mul QWORD PTR [r9+112] + add r12, rax + mov QWORD PTR [rcx+112], r12 + adc r10, rdx + adc r11, 0 + ; A[15] * B + mov rax, r8 + mul QWORD PTR [r9+120] + add r10, rax + adc r11, rdx + mov QWORD PTR [rcx+120], r10 + mov QWORD PTR [rcx+128], r11 + pop r12 + ret +sp_1024_mul_d_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Mul a by digit b into r. (r = a * b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision digit. +; */ +_text SEGMENT READONLY PARA +sp_1024_mul_d_avx2_16 PROC + push r12 + push r13 + mov rax, rdx + ; A[0] * B + mov rdx, r8 + xor r13, r13 + mulx r12, r11, QWORD PTR [rax] + mov QWORD PTR [rcx], r11 + ; A[1] * B + mulx r10, r9, QWORD PTR [rax+8] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+8], r12 + ; A[2] * B + mulx r10, r9, QWORD PTR [rax+16] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+16], r11 + ; A[3] * B + mulx r10, r9, QWORD PTR [rax+24] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+24], r12 + ; A[4] * B + mulx r10, r9, QWORD PTR [rax+32] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+32], r11 + ; A[5] * B + mulx r10, r9, QWORD PTR [rax+40] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+40], r12 + ; A[6] * B + mulx r10, r9, QWORD PTR [rax+48] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+48], r11 + ; A[7] * B + mulx r10, r9, QWORD PTR [rax+56] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+56], r12 + ; A[8] * B + mulx r10, r9, QWORD PTR [rax+64] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+64], r11 + ; A[9] * B + mulx r10, r9, QWORD PTR [rax+72] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+72], r12 + ; A[10] * B + mulx r10, r9, QWORD PTR [rax+80] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+80], r11 + ; A[11] * B + mulx r10, r9, QWORD PTR [rax+88] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+88], r12 + ; A[12] * B + mulx r10, r9, QWORD PTR [rax+96] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+96], r11 + ; A[13] * B + mulx r10, r9, QWORD PTR [rax+104] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + mov QWORD PTR [rcx+104], r12 + ; A[14] * B + mulx r10, r9, QWORD PTR [rax+112] + mov r12, r13 + adcx r11, r9 + adox r12, r10 + mov QWORD PTR [rcx+112], r11 + ; A[15] * B + mulx r10, r9, QWORD PTR [rax+120] + mov r11, r13 + adcx r12, r9 + adox r11, r10 + adcx r11, r13 + mov QWORD PTR [rcx+120], r12 + mov QWORD PTR [rcx+128], r11 + pop r13 + pop r12 + ret +sp_1024_mul_d_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF _WIN64 +; /* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) +; * +; * d1 The high order half of the number to divide. +; * d0 The low order half of the number to divide. +; * div The dividend. +; * returns the result of the division. +; */ +_text SEGMENT READONLY PARA +div_1024_word_asm_16 PROC + mov r9, rdx + mov rax, r9 + mov rdx, rcx + div r8 + ret +div_1024_word_asm_16 ENDP +_text ENDS +ENDIF +; /* Compare a with b in constant time. +; * +; * a A single precision integer. +; * b A single precision integer. +; * return -ve, 0 or +ve if a is less than, equal to or greater than b +; * respectively. +; */ +_text SEGMENT READONLY PARA +sp_1024_cmp_16 PROC + push r12 + xor r9, r9 + mov r8, -1 + mov rax, -1 + mov r10, 1 + mov r11, QWORD PTR [rcx+120] + mov r12, QWORD PTR [rdx+120] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+112] + mov r12, QWORD PTR [rdx+112] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+104] + mov r12, QWORD PTR [rdx+104] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+96] + mov r12, QWORD PTR [rdx+96] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+88] + mov r12, QWORD PTR [rdx+88] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+80] + mov r12, QWORD PTR [rdx+80] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+72] + mov r12, QWORD PTR [rdx+72] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+64] + mov r12, QWORD PTR [rdx+64] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+56] + mov r12, QWORD PTR [rdx+56] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+48] + mov r12, QWORD PTR [rdx+48] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+40] + mov r12, QWORD PTR [rdx+40] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+32] + mov r12, QWORD PTR [rdx+32] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+24] + mov r12, QWORD PTR [rdx+24] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+16] + mov r12, QWORD PTR [rdx+16] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx+8] + mov r12, QWORD PTR [rdx+8] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + mov r11, QWORD PTR [rcx] + mov r12, QWORD PTR [rdx] + and r11, r8 + and r12, r8 + sub r11, r12 + cmova rax, r10 + cmovc rax, r8 + cmovnz r8, r9 + xor rax, r8 + pop r12 + ret +sp_1024_cmp_16 ENDP +_text ENDS +; /* Conditionally copy a into r using the mask m. +; * m is -1 to copy and 0 when not. +; * +; * r A single precision number to copy over. +; * a A single precision number to copy. +; * m Mask value to apply. +; */ +_text SEGMENT READONLY PARA +sp_1024_cond_copy_16 PROC + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [rcx+16] + mov r11, QWORD PTR [rcx+24] + xor rax, QWORD PTR [rdx] + xor r9, QWORD PTR [rdx+8] + xor r10, QWORD PTR [rdx+16] + xor r11, QWORD PTR [rdx+24] + and rax, r8 + and r9, r8 + and r10, r8 + and r11, r8 + xor QWORD PTR [rcx], rax + xor QWORD PTR [rcx+8], r9 + xor QWORD PTR [rcx+16], r10 + xor QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + mov r10, QWORD PTR [rcx+48] + mov r11, QWORD PTR [rcx+56] + xor rax, QWORD PTR [rdx+32] + xor r9, QWORD PTR [rdx+40] + xor r10, QWORD PTR [rdx+48] + xor r11, QWORD PTR [rdx+56] + and rax, r8 + and r9, r8 + and r10, r8 + and r11, r8 + xor QWORD PTR [rcx+32], rax + xor QWORD PTR [rcx+40], r9 + xor QWORD PTR [rcx+48], r10 + xor QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + mov r10, QWORD PTR [rcx+80] + mov r11, QWORD PTR [rcx+88] + xor rax, QWORD PTR [rdx+64] + xor r9, QWORD PTR [rdx+72] + xor r10, QWORD PTR [rdx+80] + xor r11, QWORD PTR [rdx+88] + and rax, r8 + and r9, r8 + and r10, r8 + and r11, r8 + xor QWORD PTR [rcx+64], rax + xor QWORD PTR [rcx+72], r9 + xor QWORD PTR [rcx+80], r10 + xor QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [rcx+112] + mov r11, QWORD PTR [rcx+120] + xor rax, QWORD PTR [rdx+96] + xor r9, QWORD PTR [rdx+104] + xor r10, QWORD PTR [rdx+112] + xor r11, QWORD PTR [rdx+120] + and rax, r8 + and r9, r8 + and r10, r8 + and r11, r8 + xor QWORD PTR [rcx+96], rax + xor QWORD PTR [rcx+104], r9 + xor QWORD PTR [rcx+112], r10 + xor QWORD PTR [rcx+120], r11 + ret +sp_1024_cond_copy_16 ENDP +_text ENDS +; /* Reduce the number back to 1024 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_reduce_16 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + mov r9, rdx + xor rsi, rsi + ; i = 16 + mov r10, 16 + mov r15, QWORD PTR [rcx] + mov rdi, QWORD PTR [rcx+8] +L_1024_mont_loop_16: + ; mu = a[i] * mp + mov r13, r15 + imul r13, r8 + ; a[i+0] += m[0] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9] + add r15, rax + adc r12, rdx + ; a[i+1] += m[1] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+8] + mov r15, rdi + add r15, rax + adc r11, rdx + add r15, r12 + adc r11, 0 + ; a[i+2] += m[2] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+16] + mov rdi, QWORD PTR [rcx+16] + add rdi, rax + adc r12, rdx + add rdi, r11 + adc r12, 0 + ; a[i+3] += m[3] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+24] + mov r14, QWORD PTR [rcx+24] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+24], r14 + adc r11, 0 + ; a[i+4] += m[4] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+32] + mov r14, QWORD PTR [rcx+32] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+32], r14 + adc r12, 0 + ; a[i+5] += m[5] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+40] + mov r14, QWORD PTR [rcx+40] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+40], r14 + adc r11, 0 + ; a[i+6] += m[6] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+48] + mov r14, QWORD PTR [rcx+48] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+48], r14 + adc r12, 0 + ; a[i+7] += m[7] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+56] + mov r14, QWORD PTR [rcx+56] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+56], r14 + adc r11, 0 + ; a[i+8] += m[8] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+64] + mov r14, QWORD PTR [rcx+64] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+64], r14 + adc r12, 0 + ; a[i+9] += m[9] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+72] + mov r14, QWORD PTR [rcx+72] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+72], r14 + adc r11, 0 + ; a[i+10] += m[10] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+80] + mov r14, QWORD PTR [rcx+80] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+80], r14 + adc r12, 0 + ; a[i+11] += m[11] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+88] + mov r14, QWORD PTR [rcx+88] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+88], r14 + adc r11, 0 + ; a[i+12] += m[12] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+96] + mov r14, QWORD PTR [rcx+96] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+96], r14 + adc r12, 0 + ; a[i+13] += m[13] * mu + mov rax, r13 + xor r11, r11 + mul QWORD PTR [r9+104] + mov r14, QWORD PTR [rcx+104] + add r14, rax + adc r11, rdx + add r14, r12 + mov QWORD PTR [rcx+104], r14 + adc r11, 0 + ; a[i+14] += m[14] * mu + mov rax, r13 + xor r12, r12 + mul QWORD PTR [r9+112] + mov r14, QWORD PTR [rcx+112] + add r14, rax + adc r12, rdx + add r14, r11 + mov QWORD PTR [rcx+112], r14 + adc r12, 0 + ; a[i+15] += m[15] * mu + mov rax, r13 + mul QWORD PTR [r9+120] + mov r14, QWORD PTR [rcx+120] + add r12, rax + adc rdx, rsi + mov rsi, 0 + adc rsi, 0 + add r14, r12 + mov QWORD PTR [rcx+120], r14 + adc QWORD PTR [rcx+128], rdx + adc rsi, 0 + ; i -= 1 + add rcx, 8 + dec r10 + jnz L_1024_mont_loop_16 + mov r14, QWORD PTR [rcx+120] + mov QWORD PTR [rcx], r15 + sub r14, QWORD PTR [r9+120] + mov QWORD PTR [rcx+8], rdi + sbb r14, r14 + neg rsi + not r14 + or rsi, r14 +IFDEF _WIN64 + mov r8, r9 + mov r9, rsi +ELSE + mov r9, rsi + mov r8, r9 +ENDIF + mov rdx, rcx + mov rcx, rcx + sub rcx, 128 + call sp_1024_cond_sub_16 + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_1024_mont_reduce_16 ENDP +_text ENDS +; /* Add two Montgomery form numbers (r = a + b % m). +; * +; * r Result of addition. +; * a First number to add in Montogmery form. +; * b Second number to add in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_add_16 PROC + push r12 + push r13 + sub rsp, 128 + mov rax, QWORD PTR [rdx] + mov r10, QWORD PTR [rdx+8] + mov r11, QWORD PTR [rdx+16] + mov r12, QWORD PTR [rdx+24] + add rax, QWORD PTR [r8] + mov r13, 0 + adc r10, QWORD PTR [r8+8] + adc r11, QWORD PTR [r8+16] + adc r12, QWORD PTR [r8+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + mov rax, QWORD PTR [rdx+32] + mov r10, QWORD PTR [rdx+40] + mov r11, QWORD PTR [rdx+48] + mov r12, QWORD PTR [rdx+56] + adc rax, QWORD PTR [r8+32] + adc r10, QWORD PTR [r8+40] + adc r11, QWORD PTR [r8+48] + adc r12, QWORD PTR [r8+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov QWORD PTR [rcx+48], r11 + mov QWORD PTR [rcx+56], r12 + mov rax, QWORD PTR [rdx+64] + mov r10, QWORD PTR [rdx+72] + mov r11, QWORD PTR [rdx+80] + mov r12, QWORD PTR [rdx+88] + adc rax, QWORD PTR [r8+64] + adc r10, QWORD PTR [r8+72] + adc r11, QWORD PTR [r8+80] + adc r12, QWORD PTR [r8+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov QWORD PTR [rcx+80], r11 + mov QWORD PTR [rcx+88], r12 + mov rax, QWORD PTR [rdx+96] + mov r10, QWORD PTR [rdx+104] + mov r11, QWORD PTR [rdx+112] + mov r12, QWORD PTR [rdx+120] + adc rax, QWORD PTR [r8+96] + adc r10, QWORD PTR [r8+104] + adc r11, QWORD PTR [r8+112] + adc r12, QWORD PTR [r8+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov QWORD PTR [rcx+112], r11 + mov QWORD PTR [rcx+120], r12 + sbb r13, 0 + sub r12, QWORD PTR [r9+120] + sbb r12, r12 + not r12 + or r13, r12 + mov r11, QWORD PTR [r9] + mov r12, QWORD PTR [r9+8] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp], r11 + mov QWORD PTR [rsp+8], r12 + mov r11, QWORD PTR [r9+16] + mov r12, QWORD PTR [r9+24] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+16], r11 + mov QWORD PTR [rsp+24], r12 + mov r11, QWORD PTR [r9+32] + mov r12, QWORD PTR [r9+40] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+32], r11 + mov QWORD PTR [rsp+40], r12 + mov r11, QWORD PTR [r9+48] + mov r12, QWORD PTR [r9+56] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+48], r11 + mov QWORD PTR [rsp+56], r12 + mov r11, QWORD PTR [r9+64] + mov r12, QWORD PTR [r9+72] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+64], r11 + mov QWORD PTR [rsp+72], r12 + mov r11, QWORD PTR [r9+80] + mov r12, QWORD PTR [r9+88] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+80], r11 + mov QWORD PTR [rsp+88], r12 + mov r11, QWORD PTR [r9+96] + mov r12, QWORD PTR [r9+104] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+96], r11 + mov QWORD PTR [rsp+104], r12 + mov r11, QWORD PTR [r9+112] + mov r12, QWORD PTR [r9+120] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+112], r11 + mov QWORD PTR [rsp+120], r12 + mov rax, QWORD PTR [rcx] + mov r10, QWORD PTR [rcx+8] + sub rax, QWORD PTR [rsp] + sbb r10, QWORD PTR [rsp+8] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [rcx+16] + mov r10, QWORD PTR [rcx+24] + sbb rax, QWORD PTR [rsp+16] + sbb r10, QWORD PTR [rsp+24] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [rcx+32] + mov r10, QWORD PTR [rcx+40] + sbb rax, QWORD PTR [rsp+32] + sbb r10, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [rcx+48] + mov r10, QWORD PTR [rcx+56] + sbb rax, QWORD PTR [rsp+48] + sbb r10, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + mov rax, QWORD PTR [rcx+64] + mov r10, QWORD PTR [rcx+72] + sbb rax, QWORD PTR [rsp+64] + sbb r10, QWORD PTR [rsp+72] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov rax, QWORD PTR [rcx+80] + mov r10, QWORD PTR [rcx+88] + sbb rax, QWORD PTR [rsp+80] + sbb r10, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r10 + mov rax, QWORD PTR [rcx+96] + mov r10, QWORD PTR [rcx+104] + sbb rax, QWORD PTR [rsp+96] + sbb r10, QWORD PTR [rsp+104] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov rax, QWORD PTR [rcx+112] + mov r10, QWORD PTR [rcx+120] + sbb rax, QWORD PTR [rsp+112] + sbb r10, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r10 + add rsp, 128 + pop r13 + pop r12 + ret +sp_1024_mont_add_16 ENDP +_text ENDS +; /* Double a Montgomery form number (r = a + a % m). +; * +; * r Result of addition. +; * a Number to souble in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_dbl_16 PROC + push r12 + sub rsp, 128 + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + add rax, QWORD PTR [rdx] + mov r12, 0 + adc r9, QWORD PTR [rdx+8] + adc r10, QWORD PTR [rdx+16] + adc r11, QWORD PTR [rdx+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + mov r11, QWORD PTR [rdx+56] + adc rax, QWORD PTR [rdx+32] + adc r9, QWORD PTR [rdx+40] + adc r10, QWORD PTR [rdx+48] + adc r11, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + mov r11, QWORD PTR [rdx+88] + adc rax, QWORD PTR [rdx+64] + adc r9, QWORD PTR [rdx+72] + adc r10, QWORD PTR [rdx+80] + adc r11, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + mov r11, QWORD PTR [rdx+120] + adc rax, QWORD PTR [rdx+96] + adc r9, QWORD PTR [rdx+104] + adc r10, QWORD PTR [rdx+112] + adc r11, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb r12, 0 + sub r11, QWORD PTR [r8+120] + sbb r11, r11 + not r11 + or r12, r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + sub rax, QWORD PTR [rsp] + sbb r9, QWORD PTR [rsp+8] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov rax, QWORD PTR [rcx+16] + mov r9, QWORD PTR [rcx+24] + sbb rax, QWORD PTR [rsp+16] + sbb r9, QWORD PTR [rsp+24] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r9 + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + sbb rax, QWORD PTR [rsp+32] + sbb r9, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [rcx+56] + sbb rax, QWORD PTR [rsp+48] + sbb r9, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r9 + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + sbb rax, QWORD PTR [rsp+64] + sbb r9, QWORD PTR [rsp+72] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov rax, QWORD PTR [rcx+80] + mov r9, QWORD PTR [rcx+88] + sbb rax, QWORD PTR [rsp+80] + sbb r9, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r9 + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + sbb rax, QWORD PTR [rsp+96] + sbb r9, QWORD PTR [rsp+104] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov rax, QWORD PTR [rcx+112] + mov r9, QWORD PTR [rcx+120] + sbb rax, QWORD PTR [rsp+112] + sbb r9, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r9 + add rsp, 128 + pop r12 + ret +sp_1024_mont_dbl_16 ENDP +_text ENDS +; /* Triple a Montgomery form number (r = a + a + a % m). +; * +; * r Result of addition. +; * a Number to souble in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_tpl_16 PROC + push r12 + sub rsp, 128 + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + add rax, QWORD PTR [rdx] + mov r12, 0 + adc r9, QWORD PTR [rdx+8] + adc r10, QWORD PTR [rdx+16] + adc r11, QWORD PTR [rdx+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + mov r11, QWORD PTR [rdx+56] + adc rax, QWORD PTR [rdx+32] + adc r9, QWORD PTR [rdx+40] + adc r10, QWORD PTR [rdx+48] + adc r11, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + mov r11, QWORD PTR [rdx+88] + adc rax, QWORD PTR [rdx+64] + adc r9, QWORD PTR [rdx+72] + adc r10, QWORD PTR [rdx+80] + adc r11, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + mov r11, QWORD PTR [rdx+120] + adc rax, QWORD PTR [rdx+96] + adc r9, QWORD PTR [rdx+104] + adc r10, QWORD PTR [rdx+112] + adc r11, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb r12, 0 + sub r11, QWORD PTR [r8+120] + sbb r11, r11 + not r11 + or r12, r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + sub rax, QWORD PTR [rsp] + sbb r9, QWORD PTR [rsp+8] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov rax, QWORD PTR [rcx+16] + mov r9, QWORD PTR [rcx+24] + sbb rax, QWORD PTR [rsp+16] + sbb r9, QWORD PTR [rsp+24] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r9 + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + sbb rax, QWORD PTR [rsp+32] + sbb r9, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [rcx+56] + sbb rax, QWORD PTR [rsp+48] + sbb r9, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r9 + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + sbb rax, QWORD PTR [rsp+64] + sbb r9, QWORD PTR [rsp+72] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov rax, QWORD PTR [rcx+80] + mov r9, QWORD PTR [rcx+88] + sbb rax, QWORD PTR [rsp+80] + sbb r9, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r9 + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + sbb rax, QWORD PTR [rsp+96] + sbb r9, QWORD PTR [rsp+104] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov rax, QWORD PTR [rcx+112] + mov r9, QWORD PTR [rcx+120] + sbb rax, QWORD PTR [rsp+112] + sbb r9, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r9 + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [rcx+16] + mov r11, QWORD PTR [rcx+24] + add rax, QWORD PTR [rdx] + mov r12, 0 + adc r9, QWORD PTR [rdx+8] + adc r10, QWORD PTR [rdx+16] + adc r11, QWORD PTR [rdx+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + mov r10, QWORD PTR [rcx+48] + mov r11, QWORD PTR [rcx+56] + adc rax, QWORD PTR [rdx+32] + adc r9, QWORD PTR [rdx+40] + adc r10, QWORD PTR [rdx+48] + adc r11, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + mov r10, QWORD PTR [rcx+80] + mov r11, QWORD PTR [rcx+88] + adc rax, QWORD PTR [rdx+64] + adc r9, QWORD PTR [rdx+72] + adc r10, QWORD PTR [rdx+80] + adc r11, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [rcx+112] + mov r11, QWORD PTR [rcx+120] + adc rax, QWORD PTR [rdx+96] + adc r9, QWORD PTR [rdx+104] + adc r10, QWORD PTR [rdx+112] + adc r11, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb r12, 0 + sub r11, QWORD PTR [r8+120] + sbb r11, r11 + not r11 + or r12, r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp], r10 + mov QWORD PTR [rsp+8], r11 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+16], r10 + mov QWORD PTR [rsp+24], r11 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+32], r10 + mov QWORD PTR [rsp+40], r11 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+48], r10 + mov QWORD PTR [rsp+56], r11 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+64], r10 + mov QWORD PTR [rsp+72], r11 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+80], r10 + mov QWORD PTR [rsp+88], r11 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+96], r10 + mov QWORD PTR [rsp+104], r11 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + and r10, r12 + and r11, r12 + mov QWORD PTR [rsp+112], r10 + mov QWORD PTR [rsp+120], r11 + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + sub rax, QWORD PTR [rsp] + sbb r9, QWORD PTR [rsp+8] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov rax, QWORD PTR [rcx+16] + mov r9, QWORD PTR [rcx+24] + sbb rax, QWORD PTR [rsp+16] + sbb r9, QWORD PTR [rsp+24] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r9 + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + sbb rax, QWORD PTR [rsp+32] + sbb r9, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [rcx+56] + sbb rax, QWORD PTR [rsp+48] + sbb r9, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r9 + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + sbb rax, QWORD PTR [rsp+64] + sbb r9, QWORD PTR [rsp+72] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov rax, QWORD PTR [rcx+80] + mov r9, QWORD PTR [rcx+88] + sbb rax, QWORD PTR [rsp+80] + sbb r9, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r9 + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + sbb rax, QWORD PTR [rsp+96] + sbb r9, QWORD PTR [rsp+104] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov rax, QWORD PTR [rcx+112] + mov r9, QWORD PTR [rcx+120] + sbb rax, QWORD PTR [rsp+112] + sbb r9, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r9 + add rsp, 128 + pop r12 + ret +sp_1024_mont_tpl_16 ENDP +_text ENDS +; /* Subtract two Montgomery form numbers (r = a - b % m). +; * +; * r Result of addition. +; * a First number to add in Montogmery form. +; * b Second number to add in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_sub_16 PROC + push r12 + push r13 + sub rsp, 128 + mov rax, QWORD PTR [rdx] + mov r10, QWORD PTR [rdx+8] + mov r11, QWORD PTR [rdx+16] + mov r12, QWORD PTR [rdx+24] + sub rax, QWORD PTR [r8] + mov r13, 0 + sbb r10, QWORD PTR [r8+8] + sbb r11, QWORD PTR [r8+16] + sbb r12, QWORD PTR [r8+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + mov rax, QWORD PTR [rdx+32] + mov r10, QWORD PTR [rdx+40] + mov r11, QWORD PTR [rdx+48] + mov r12, QWORD PTR [rdx+56] + sbb rax, QWORD PTR [r8+32] + sbb r10, QWORD PTR [r8+40] + sbb r11, QWORD PTR [r8+48] + sbb r12, QWORD PTR [r8+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov QWORD PTR [rcx+48], r11 + mov QWORD PTR [rcx+56], r12 + mov rax, QWORD PTR [rdx+64] + mov r10, QWORD PTR [rdx+72] + mov r11, QWORD PTR [rdx+80] + mov r12, QWORD PTR [rdx+88] + sbb rax, QWORD PTR [r8+64] + sbb r10, QWORD PTR [r8+72] + sbb r11, QWORD PTR [r8+80] + sbb r12, QWORD PTR [r8+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov QWORD PTR [rcx+80], r11 + mov QWORD PTR [rcx+88], r12 + mov rax, QWORD PTR [rdx+96] + mov r10, QWORD PTR [rdx+104] + mov r11, QWORD PTR [rdx+112] + mov r12, QWORD PTR [rdx+120] + sbb rax, QWORD PTR [r8+96] + sbb r10, QWORD PTR [r8+104] + sbb r11, QWORD PTR [r8+112] + sbb r12, QWORD PTR [r8+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov QWORD PTR [rcx+112], r11 + mov QWORD PTR [rcx+120], r12 + sbb r13, 0 + mov r11, QWORD PTR [r9] + mov r12, QWORD PTR [r9+8] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp], r11 + mov QWORD PTR [rsp+8], r12 + mov r11, QWORD PTR [r9+16] + mov r12, QWORD PTR [r9+24] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+16], r11 + mov QWORD PTR [rsp+24], r12 + mov r11, QWORD PTR [r9+32] + mov r12, QWORD PTR [r9+40] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+32], r11 + mov QWORD PTR [rsp+40], r12 + mov r11, QWORD PTR [r9+48] + mov r12, QWORD PTR [r9+56] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+48], r11 + mov QWORD PTR [rsp+56], r12 + mov r11, QWORD PTR [r9+64] + mov r12, QWORD PTR [r9+72] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+64], r11 + mov QWORD PTR [rsp+72], r12 + mov r11, QWORD PTR [r9+80] + mov r12, QWORD PTR [r9+88] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+80], r11 + mov QWORD PTR [rsp+88], r12 + mov r11, QWORD PTR [r9+96] + mov r12, QWORD PTR [r9+104] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+96], r11 + mov QWORD PTR [rsp+104], r12 + mov r11, QWORD PTR [r9+112] + mov r12, QWORD PTR [r9+120] + and r11, r13 + and r12, r13 + mov QWORD PTR [rsp+112], r11 + mov QWORD PTR [rsp+120], r12 + mov rax, QWORD PTR [rcx] + mov r10, QWORD PTR [rcx+8] + add rax, QWORD PTR [rsp] + adc r10, QWORD PTR [rsp+8] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [rcx+16] + mov r10, QWORD PTR [rcx+24] + adc rax, QWORD PTR [rsp+16] + adc r10, QWORD PTR [rsp+24] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [rcx+32] + mov r10, QWORD PTR [rcx+40] + adc rax, QWORD PTR [rsp+32] + adc r10, QWORD PTR [rsp+40] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [rcx+48] + mov r10, QWORD PTR [rcx+56] + adc rax, QWORD PTR [rsp+48] + adc r10, QWORD PTR [rsp+56] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + mov rax, QWORD PTR [rcx+64] + mov r10, QWORD PTR [rcx+72] + adc rax, QWORD PTR [rsp+64] + adc r10, QWORD PTR [rsp+72] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov rax, QWORD PTR [rcx+80] + mov r10, QWORD PTR [rcx+88] + adc rax, QWORD PTR [rsp+80] + adc r10, QWORD PTR [rsp+88] + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r10 + mov rax, QWORD PTR [rcx+96] + mov r10, QWORD PTR [rcx+104] + adc rax, QWORD PTR [rsp+96] + adc r10, QWORD PTR [rsp+104] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov rax, QWORD PTR [rcx+112] + mov r10, QWORD PTR [rcx+120] + adc rax, QWORD PTR [rsp+112] + adc r10, QWORD PTR [rsp+120] + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r10 + add rsp, 128 + pop r13 + pop r12 + ret +sp_1024_mont_sub_16 ENDP +_text ENDS +; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_div2_16 PROC + push r12 + push r13 + sub rsp, 128 + mov r13, QWORD PTR [rdx] + xor r12, r12 + mov rax, r13 + and r13, 1 + neg r13 + mov r10, QWORD PTR [r8] + and r10, r13 + mov QWORD PTR [rsp], r10 + mov r10, QWORD PTR [r8+8] + and r10, r13 + mov QWORD PTR [rsp+8], r10 + mov r10, QWORD PTR [r8+16] + and r10, r13 + mov QWORD PTR [rsp+16], r10 + mov r10, QWORD PTR [r8+24] + and r10, r13 + mov QWORD PTR [rsp+24], r10 + mov r10, QWORD PTR [r8+32] + and r10, r13 + mov QWORD PTR [rsp+32], r10 + mov r10, QWORD PTR [r8+40] + and r10, r13 + mov QWORD PTR [rsp+40], r10 + mov r10, QWORD PTR [r8+48] + and r10, r13 + mov QWORD PTR [rsp+48], r10 + mov r10, QWORD PTR [r8+56] + and r10, r13 + mov QWORD PTR [rsp+56], r10 + mov r10, QWORD PTR [r8+64] + and r10, r13 + mov QWORD PTR [rsp+64], r10 + mov r10, QWORD PTR [r8+72] + and r10, r13 + mov QWORD PTR [rsp+72], r10 + mov r10, QWORD PTR [r8+80] + and r10, r13 + mov QWORD PTR [rsp+80], r10 + mov r10, QWORD PTR [r8+88] + and r10, r13 + mov QWORD PTR [rsp+88], r10 + mov r10, QWORD PTR [r8+96] + and r10, r13 + mov QWORD PTR [rsp+96], r10 + mov r10, QWORD PTR [r8+104] + and r10, r13 + mov QWORD PTR [rsp+104], r10 + mov r10, QWORD PTR [r8+112] + and r10, r13 + mov QWORD PTR [rsp+112], r10 + mov r10, QWORD PTR [r8+120] + and r10, r13 + mov QWORD PTR [rsp+120], r10 + add QWORD PTR [rsp], rax + mov rax, QWORD PTR [rdx+8] + adc QWORD PTR [rsp+8], rax + mov rax, QWORD PTR [rdx+16] + adc QWORD PTR [rsp+16], rax + mov rax, QWORD PTR [rdx+24] + adc QWORD PTR [rsp+24], rax + mov rax, QWORD PTR [rdx+32] + adc QWORD PTR [rsp+32], rax + mov rax, QWORD PTR [rdx+40] + adc QWORD PTR [rsp+40], rax + mov rax, QWORD PTR [rdx+48] + adc QWORD PTR [rsp+48], rax + mov rax, QWORD PTR [rdx+56] + adc QWORD PTR [rsp+56], rax + mov rax, QWORD PTR [rdx+64] + adc QWORD PTR [rsp+64], rax + mov rax, QWORD PTR [rdx+72] + adc QWORD PTR [rsp+72], rax + mov rax, QWORD PTR [rdx+80] + adc QWORD PTR [rsp+80], rax + mov rax, QWORD PTR [rdx+88] + adc QWORD PTR [rsp+88], rax + mov rax, QWORD PTR [rdx+96] + adc QWORD PTR [rsp+96], rax + mov rax, QWORD PTR [rdx+104] + adc QWORD PTR [rsp+104], rax + mov rax, QWORD PTR [rdx+112] + adc QWORD PTR [rsp+112], rax + mov rax, QWORD PTR [rdx+120] + adc QWORD PTR [rsp+120], rax + adc r12, 0 + mov rax, QWORD PTR [rsp] + mov r9, QWORD PTR [rsp+8] + shrd rax, r9, 1 + mov QWORD PTR [rcx], rax + mov rax, QWORD PTR [rsp+16] + shrd r9, rax, 1 + mov QWORD PTR [rcx+8], r9 + mov r9, QWORD PTR [rsp+24] + shrd rax, r9, 1 + mov QWORD PTR [rcx+16], rax + mov rax, QWORD PTR [rsp+32] + shrd r9, rax, 1 + mov QWORD PTR [rcx+24], r9 + mov r9, QWORD PTR [rsp+40] + shrd rax, r9, 1 + mov QWORD PTR [rcx+32], rax + mov rax, QWORD PTR [rsp+48] + shrd r9, rax, 1 + mov QWORD PTR [rcx+40], r9 + mov r9, QWORD PTR [rsp+56] + shrd rax, r9, 1 + mov QWORD PTR [rcx+48], rax + mov rax, QWORD PTR [rsp+64] + shrd r9, rax, 1 + mov QWORD PTR [rcx+56], r9 + mov r9, QWORD PTR [rsp+72] + shrd rax, r9, 1 + mov QWORD PTR [rcx+64], rax + mov rax, QWORD PTR [rsp+80] + shrd r9, rax, 1 + mov QWORD PTR [rcx+72], r9 + mov r9, QWORD PTR [rsp+88] + shrd rax, r9, 1 + mov QWORD PTR [rcx+80], rax + mov rax, QWORD PTR [rsp+96] + shrd r9, rax, 1 + mov QWORD PTR [rcx+88], r9 + mov r9, QWORD PTR [rsp+104] + shrd rax, r9, 1 + mov QWORD PTR [rcx+96], rax + mov rax, QWORD PTR [rsp+112] + shrd r9, rax, 1 + mov QWORD PTR [rcx+104], r9 + mov r9, QWORD PTR [rsp+120] + shrd rax, r9, 1 + mov QWORD PTR [rcx+112], rax + shrd r9, r12, 1 + mov QWORD PTR [rcx+120], r9 + add rsp, 128 + pop r13 + pop r12 + ret +sp_1024_div2_16 ENDP +_text ENDS +; /* Sub b from a into r. (r = a - b) +; * +; * r A single precision integer. +; * a A single precision integer. +; * b A single precision integer. +; */ +_text SEGMENT READONLY PARA +sp_1024_sub_16 PROC + mov r9, QWORD PTR [rdx] + xor rax, rax + sub r9, QWORD PTR [r8] + mov r10, QWORD PTR [rdx+8] + mov QWORD PTR [rcx], r9 + sbb r10, QWORD PTR [r8+8] + mov r9, QWORD PTR [rdx+16] + mov QWORD PTR [rcx+8], r10 + sbb r9, QWORD PTR [r8+16] + mov r10, QWORD PTR [rdx+24] + mov QWORD PTR [rcx+16], r9 + sbb r10, QWORD PTR [r8+24] + mov r9, QWORD PTR [rdx+32] + mov QWORD PTR [rcx+24], r10 + sbb r9, QWORD PTR [r8+32] + mov r10, QWORD PTR [rdx+40] + mov QWORD PTR [rcx+32], r9 + sbb r10, QWORD PTR [r8+40] + mov r9, QWORD PTR [rdx+48] + mov QWORD PTR [rcx+40], r10 + sbb r9, QWORD PTR [r8+48] + mov r10, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+48], r9 + sbb r10, QWORD PTR [r8+56] + mov r9, QWORD PTR [rdx+64] + mov QWORD PTR [rcx+56], r10 + sbb r9, QWORD PTR [r8+64] + mov r10, QWORD PTR [rdx+72] + mov QWORD PTR [rcx+64], r9 + sbb r10, QWORD PTR [r8+72] + mov r9, QWORD PTR [rdx+80] + mov QWORD PTR [rcx+72], r10 + sbb r9, QWORD PTR [r8+80] + mov r10, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+80], r9 + sbb r10, QWORD PTR [r8+88] + mov r9, QWORD PTR [rdx+96] + mov QWORD PTR [rcx+88], r10 + sbb r9, QWORD PTR [r8+96] + mov r10, QWORD PTR [rdx+104] + mov QWORD PTR [rcx+96], r9 + sbb r10, QWORD PTR [r8+104] + mov r9, QWORD PTR [rdx+112] + mov QWORD PTR [rcx+104], r10 + sbb r9, QWORD PTR [r8+112] + mov r10, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+112], r9 + sbb r10, QWORD PTR [r8+120] + mov QWORD PTR [rcx+120], r10 + sbb rax, 0 + ret +sp_1024_sub_16 ENDP +_text ENDS +IFDEF HAVE_INTEL_AVX2 +; /* Reduce the number back to 1024 bits using Montgomery reduction. +; * +; * a A single precision number to reduce in place. +; * m The single precision number representing the modulus. +; * mp The digit representing the negative inverse of m mod 2^n. +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_reduce_avx2_16 PROC + push r12 + push r13 + push r14 + push r15 + push rdi + push rsi + push rbx + push rbp + mov r9, rcx + mov r10, rdx + xor rbp, rbp + ; i = 16 + mov r11, 16 + mov r15, QWORD PTR [r9] + mov rdi, QWORD PTR [r9+8] + mov rsi, QWORD PTR [r9+16] + mov rbx, QWORD PTR [r9+24] + add r9, 64 + xor rbp, rbp +L_1024_mont_loop_avx2_16: + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-32] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-24] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-24], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9+-8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-16], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-8], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+8] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+16] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+8], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+24] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+16], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+32] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+24], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+40] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+32], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+48] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+40], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+56] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+48], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+64] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+56], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+64], r12 + adox rbp, r14 + adcx rbp, r14 + ; mu = a[i] * mp + mov rdx, r15 + mov r12, r15 + imul rdx, r8 + xor r14, r14 + ; a[i+0] += m[0] * mu + mulx rcx, rax, QWORD PTR [r10] + mov r15, rdi + adcx r12, rax + adox r15, rcx + ; a[i+1] += m[1] * mu + mulx rcx, rax, QWORD PTR [r10+8] + mov rdi, rsi + adcx r15, rax + adox rdi, rcx + ; a[i+2] += m[2] * mu + mulx rcx, rax, QWORD PTR [r10+16] + mov rsi, rbx + adcx rdi, rax + adox rsi, rcx + ; a[i+3] += m[3] * mu + mulx rcx, rax, QWORD PTR [r10+24] + mov rbx, QWORD PTR [r9+-24] + adcx rsi, rax + adox rbx, rcx + ; a[i+4] += m[4] * mu + mulx rcx, rax, QWORD PTR [r10+32] + mov r13, QWORD PTR [r9+-16] + adcx rbx, rax + adox r13, rcx + ; a[i+5] += m[5] * mu + mulx rcx, rax, QWORD PTR [r10+40] + mov r12, QWORD PTR [r9+-8] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+-16], r13 + ; a[i+6] += m[6] * mu + mulx rcx, rax, QWORD PTR [r10+48] + mov r13, QWORD PTR [r9] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+-8], r12 + ; a[i+7] += m[7] * mu + mulx rcx, rax, QWORD PTR [r10+56] + mov r12, QWORD PTR [r9+8] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9], r13 + ; a[i+8] += m[8] * mu + mulx rcx, rax, QWORD PTR [r10+64] + mov r13, QWORD PTR [r9+16] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+8], r12 + ; a[i+9] += m[9] * mu + mulx rcx, rax, QWORD PTR [r10+72] + mov r12, QWORD PTR [r9+24] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+16], r13 + ; a[i+10] += m[10] * mu + mulx rcx, rax, QWORD PTR [r10+80] + mov r13, QWORD PTR [r9+32] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+24], r12 + ; a[i+11] += m[11] * mu + mulx rcx, rax, QWORD PTR [r10+88] + mov r12, QWORD PTR [r9+40] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+32], r13 + ; a[i+12] += m[12] * mu + mulx rcx, rax, QWORD PTR [r10+96] + mov r13, QWORD PTR [r9+48] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+40], r12 + ; a[i+13] += m[13] * mu + mulx rcx, rax, QWORD PTR [r10+104] + mov r12, QWORD PTR [r9+56] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+48], r13 + ; a[i+14] += m[14] * mu + mulx rcx, rax, QWORD PTR [r10+112] + mov r13, QWORD PTR [r9+64] + adcx r12, rax + adox r13, rcx + mov QWORD PTR [r9+56], r12 + ; a[i+15] += m[15] * mu + mulx rcx, rax, QWORD PTR [r10+120] + mov r12, QWORD PTR [r9+72] + adcx r13, rax + adox r12, rcx + mov QWORD PTR [r9+64], r13 + adcx r12, rbp + mov rbp, r14 + mov QWORD PTR [r9+72], r12 + adox rbp, r14 + adcx rbp, r14 + ; a += 2 + add r9, 16 + ; i -= 2 + sub r11, 2 + jnz L_1024_mont_loop_avx2_16 + sub r9, 64 + sub r12, QWORD PTR [r10+120] + mov r8, r9 + sbb r12, r12 + neg rbp + not r12 + or rbp, r12 + sub r9, 128 + mov rcx, QWORD PTR [r10] + mov rdx, r15 + pext rcx, rcx, rbp + sub rdx, rcx + mov rcx, QWORD PTR [r10+8] + mov rax, rdi + pext rcx, rcx, rbp + mov QWORD PTR [r9], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+16] + mov rcx, rsi + pext rdx, rdx, rbp + mov QWORD PTR [r9+8], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+24] + mov rdx, rbx + pext rax, rax, rbp + mov QWORD PTR [r9+16], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+32] + mov rax, QWORD PTR [r8+32] + pext rcx, rcx, rbp + mov QWORD PTR [r9+24], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+40] + mov rcx, QWORD PTR [r8+40] + pext rdx, rdx, rbp + mov QWORD PTR [r9+32], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+48] + mov rdx, QWORD PTR [r8+48] + pext rax, rax, rbp + mov QWORD PTR [r9+40], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+56] + mov rax, QWORD PTR [r8+56] + pext rcx, rcx, rbp + mov QWORD PTR [r9+48], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+64] + mov rcx, QWORD PTR [r8+64] + pext rdx, rdx, rbp + mov QWORD PTR [r9+56], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+72] + mov rdx, QWORD PTR [r8+72] + pext rax, rax, rbp + mov QWORD PTR [r9+64], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+80] + mov rax, QWORD PTR [r8+80] + pext rcx, rcx, rbp + mov QWORD PTR [r9+72], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+88] + mov rcx, QWORD PTR [r8+88] + pext rdx, rdx, rbp + mov QWORD PTR [r9+80], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+96] + mov rdx, QWORD PTR [r8+96] + pext rax, rax, rbp + mov QWORD PTR [r9+88], rcx + sbb rdx, rax + mov rcx, QWORD PTR [r10+104] + mov rax, QWORD PTR [r8+104] + pext rcx, rcx, rbp + mov QWORD PTR [r9+96], rdx + sbb rax, rcx + mov rdx, QWORD PTR [r10+112] + mov rcx, QWORD PTR [r8+112] + pext rdx, rdx, rbp + mov QWORD PTR [r9+104], rax + sbb rcx, rdx + mov rax, QWORD PTR [r10+120] + mov rdx, QWORD PTR [r8+120] + pext rax, rax, rbp + mov QWORD PTR [r9+112], rcx + sbb rdx, rax + mov QWORD PTR [r9+120], rdx + pop rbp + pop rbx + pop rsi + pop rdi + pop r15 + pop r14 + pop r13 + pop r12 + ret +sp_1024_mont_reduce_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Add two Montgomery form numbers (r = a + b % m). +; * +; * r Result of addition. +; * a First number to add in Montogmery form. +; * b Second number to add in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_add_avx2_16 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r10, QWORD PTR [rdx+8] + mov r11, QWORD PTR [rdx+16] + mov r12, QWORD PTR [rdx+24] + add rax, QWORD PTR [r8] + mov r13, 0 + adc r10, QWORD PTR [r8+8] + adc r11, QWORD PTR [r8+16] + adc r12, QWORD PTR [r8+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + mov rax, QWORD PTR [rdx+32] + mov r10, QWORD PTR [rdx+40] + mov r11, QWORD PTR [rdx+48] + mov r12, QWORD PTR [rdx+56] + adc rax, QWORD PTR [r8+32] + adc r10, QWORD PTR [r8+40] + adc r11, QWORD PTR [r8+48] + adc r12, QWORD PTR [r8+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov QWORD PTR [rcx+48], r11 + mov QWORD PTR [rcx+56], r12 + mov rax, QWORD PTR [rdx+64] + mov r10, QWORD PTR [rdx+72] + mov r11, QWORD PTR [rdx+80] + mov r12, QWORD PTR [rdx+88] + adc rax, QWORD PTR [r8+64] + adc r10, QWORD PTR [r8+72] + adc r11, QWORD PTR [r8+80] + adc r12, QWORD PTR [r8+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov QWORD PTR [rcx+80], r11 + mov QWORD PTR [rcx+88], r12 + mov rax, QWORD PTR [rdx+96] + mov r10, QWORD PTR [rdx+104] + mov r11, QWORD PTR [rdx+112] + mov r12, QWORD PTR [rdx+120] + adc rax, QWORD PTR [r8+96] + adc r10, QWORD PTR [r8+104] + adc r11, QWORD PTR [r8+112] + adc r12, QWORD PTR [r8+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov QWORD PTR [rcx+112], r11 + mov QWORD PTR [rcx+120], r12 + sbb r13, 0 + sub r12, QWORD PTR [r9+120] + sbb r12, r12 + not r12 + or r13, r12 + mov r11, QWORD PTR [r9] + mov r12, QWORD PTR [r9+8] + mov rax, QWORD PTR [rcx] + mov r10, QWORD PTR [rcx+8] + pext r11, r11, r13 + pext r12, r12, r13 + sub rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov r11, QWORD PTR [r9+16] + mov r12, QWORD PTR [r9+24] + mov rax, QWORD PTR [rcx+16] + mov r10, QWORD PTR [rcx+24] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov r11, QWORD PTR [r9+32] + mov r12, QWORD PTR [r9+40] + mov rax, QWORD PTR [rcx+32] + mov r10, QWORD PTR [rcx+40] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov r11, QWORD PTR [r9+48] + mov r12, QWORD PTR [r9+56] + mov rax, QWORD PTR [rcx+48] + mov r10, QWORD PTR [rcx+56] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + mov r11, QWORD PTR [r9+64] + mov r12, QWORD PTR [r9+72] + mov rax, QWORD PTR [rcx+64] + mov r10, QWORD PTR [rcx+72] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov r11, QWORD PTR [r9+80] + mov r12, QWORD PTR [r9+88] + mov rax, QWORD PTR [rcx+80] + mov r10, QWORD PTR [rcx+88] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r10 + mov r11, QWORD PTR [r9+96] + mov r12, QWORD PTR [r9+104] + mov rax, QWORD PTR [rcx+96] + mov r10, QWORD PTR [rcx+104] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov r11, QWORD PTR [r9+112] + mov r12, QWORD PTR [r9+120] + mov rax, QWORD PTR [rcx+112] + mov r10, QWORD PTR [rcx+120] + pext r11, r11, r13 + pext r12, r12, r13 + sbb rax, r11 + sbb r10, r12 + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r10 + pop r13 + pop r12 + ret +sp_1024_mont_add_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Double a Montgomery form number (r = a + a % m). +; * +; * r Result of addition. +; * a Number to souble in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_dbl_avx2_16 PROC + push r12 + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + add rax, QWORD PTR [rdx] + mov r12, 0 + adc r9, QWORD PTR [rdx+8] + adc r10, QWORD PTR [rdx+16] + adc r11, QWORD PTR [rdx+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + mov r11, QWORD PTR [rdx+56] + adc rax, QWORD PTR [rdx+32] + adc r9, QWORD PTR [rdx+40] + adc r10, QWORD PTR [rdx+48] + adc r11, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + mov r11, QWORD PTR [rdx+88] + adc rax, QWORD PTR [rdx+64] + adc r9, QWORD PTR [rdx+72] + adc r10, QWORD PTR [rdx+80] + adc r11, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + mov r11, QWORD PTR [rdx+120] + adc rax, QWORD PTR [rdx+96] + adc r9, QWORD PTR [rdx+104] + adc r10, QWORD PTR [rdx+112] + adc r11, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb r12, 0 + sub r11, QWORD PTR [r8+120] + sbb r11, r11 + not r11 + or r12, r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + pext r10, r10, r12 + pext r11, r11, r12 + sub rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + mov rax, QWORD PTR [rcx+16] + mov r9, QWORD PTR [rcx+24] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r9 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + mov rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [rcx+56] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r9 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + mov rax, QWORD PTR [rcx+80] + mov r9, QWORD PTR [rcx+88] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r9 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + mov rax, QWORD PTR [rcx+112] + mov r9, QWORD PTR [rcx+120] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r9 + pop r12 + ret +sp_1024_mont_dbl_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Triple a Montgomery form number (r = a + a + a % m). +; * +; * r Result of addition. +; * a Number to souble in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_tpl_avx2_16 PROC + push r12 + mov rax, QWORD PTR [rdx] + mov r9, QWORD PTR [rdx+8] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + add rax, QWORD PTR [rdx] + mov r12, 0 + adc r9, QWORD PTR [rdx+8] + adc r10, QWORD PTR [rdx+16] + adc r11, QWORD PTR [rdx+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rdx+32] + mov r9, QWORD PTR [rdx+40] + mov r10, QWORD PTR [rdx+48] + mov r11, QWORD PTR [rdx+56] + adc rax, QWORD PTR [rdx+32] + adc r9, QWORD PTR [rdx+40] + adc r10, QWORD PTR [rdx+48] + adc r11, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rdx+64] + mov r9, QWORD PTR [rdx+72] + mov r10, QWORD PTR [rdx+80] + mov r11, QWORD PTR [rdx+88] + adc rax, QWORD PTR [rdx+64] + adc r9, QWORD PTR [rdx+72] + adc r10, QWORD PTR [rdx+80] + adc r11, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rdx+96] + mov r9, QWORD PTR [rdx+104] + mov r10, QWORD PTR [rdx+112] + mov r11, QWORD PTR [rdx+120] + adc rax, QWORD PTR [rdx+96] + adc r9, QWORD PTR [rdx+104] + adc r10, QWORD PTR [rdx+112] + adc r11, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb r12, 0 + sub r11, QWORD PTR [r8+120] + sbb r11, r11 + not r11 + or r12, r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + pext r10, r10, r12 + pext r11, r11, r12 + sub rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + mov rax, QWORD PTR [rcx+16] + mov r9, QWORD PTR [rcx+24] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r9 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + mov rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [rcx+56] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r9 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + mov rax, QWORD PTR [rcx+80] + mov r9, QWORD PTR [rcx+88] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r9 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + mov rax, QWORD PTR [rcx+112] + mov r9, QWORD PTR [rcx+120] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r9 + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + mov r10, QWORD PTR [rcx+16] + mov r11, QWORD PTR [rcx+24] + add rax, QWORD PTR [rdx] + mov r12, 0 + adc r9, QWORD PTR [rdx+8] + adc r10, QWORD PTR [rdx+16] + adc r11, QWORD PTR [rdx+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + mov r10, QWORD PTR [rcx+48] + mov r11, QWORD PTR [rcx+56] + adc rax, QWORD PTR [rdx+32] + adc r9, QWORD PTR [rdx+40] + adc r10, QWORD PTR [rdx+48] + adc r11, QWORD PTR [rdx+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + mov r10, QWORD PTR [rcx+80] + mov r11, QWORD PTR [rcx+88] + adc rax, QWORD PTR [rdx+64] + adc r9, QWORD PTR [rdx+72] + adc r10, QWORD PTR [rdx+80] + adc r11, QWORD PTR [rdx+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + mov r10, QWORD PTR [rcx+112] + mov r11, QWORD PTR [rcx+120] + adc rax, QWORD PTR [rdx+96] + adc r9, QWORD PTR [rdx+104] + adc r10, QWORD PTR [rdx+112] + adc r11, QWORD PTR [rdx+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + sbb r12, 0 + sub r11, QWORD PTR [r8+120] + sbb r11, r11 + not r11 + or r12, r11 + mov r10, QWORD PTR [r8] + mov r11, QWORD PTR [r8+8] + mov rax, QWORD PTR [rcx] + mov r9, QWORD PTR [rcx+8] + pext r10, r10, r12 + pext r11, r11, r12 + sub rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r9 + mov r10, QWORD PTR [r8+16] + mov r11, QWORD PTR [r8+24] + mov rax, QWORD PTR [rcx+16] + mov r9, QWORD PTR [rcx+24] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r9 + mov r10, QWORD PTR [r8+32] + mov r11, QWORD PTR [r8+40] + mov rax, QWORD PTR [rcx+32] + mov r9, QWORD PTR [rcx+40] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r9 + mov r10, QWORD PTR [r8+48] + mov r11, QWORD PTR [r8+56] + mov rax, QWORD PTR [rcx+48] + mov r9, QWORD PTR [rcx+56] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r9 + mov r10, QWORD PTR [r8+64] + mov r11, QWORD PTR [r8+72] + mov rax, QWORD PTR [rcx+64] + mov r9, QWORD PTR [rcx+72] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r9 + mov r10, QWORD PTR [r8+80] + mov r11, QWORD PTR [r8+88] + mov rax, QWORD PTR [rcx+80] + mov r9, QWORD PTR [rcx+88] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r9 + mov r10, QWORD PTR [r8+96] + mov r11, QWORD PTR [r8+104] + mov rax, QWORD PTR [rcx+96] + mov r9, QWORD PTR [rcx+104] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r9 + mov r10, QWORD PTR [r8+112] + mov r11, QWORD PTR [r8+120] + mov rax, QWORD PTR [rcx+112] + mov r9, QWORD PTR [rcx+120] + pext r10, r10, r12 + pext r11, r11, r12 + sbb rax, r10 + sbb r9, r11 + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r9 + pop r12 + ret +sp_1024_mont_tpl_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Subtract two Montgomery form numbers (r = a - b % m). +; * +; * r Result of addition. +; * a First number to add in Montogmery form. +; * b Second number to add in Montogmery form. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_mont_sub_avx2_16 PROC + push r12 + push r13 + mov rax, QWORD PTR [rdx] + mov r10, QWORD PTR [rdx+8] + mov r11, QWORD PTR [rdx+16] + mov r12, QWORD PTR [rdx+24] + sub rax, QWORD PTR [r8] + mov r13, 0 + sbb r10, QWORD PTR [r8+8] + sbb r11, QWORD PTR [r8+16] + sbb r12, QWORD PTR [r8+24] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov QWORD PTR [rcx+16], r11 + mov QWORD PTR [rcx+24], r12 + mov rax, QWORD PTR [rdx+32] + mov r10, QWORD PTR [rdx+40] + mov r11, QWORD PTR [rdx+48] + mov r12, QWORD PTR [rdx+56] + sbb rax, QWORD PTR [r8+32] + sbb r10, QWORD PTR [r8+40] + sbb r11, QWORD PTR [r8+48] + sbb r12, QWORD PTR [r8+56] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov QWORD PTR [rcx+48], r11 + mov QWORD PTR [rcx+56], r12 + mov rax, QWORD PTR [rdx+64] + mov r10, QWORD PTR [rdx+72] + mov r11, QWORD PTR [rdx+80] + mov r12, QWORD PTR [rdx+88] + sbb rax, QWORD PTR [r8+64] + sbb r10, QWORD PTR [r8+72] + sbb r11, QWORD PTR [r8+80] + sbb r12, QWORD PTR [r8+88] + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov QWORD PTR [rcx+80], r11 + mov QWORD PTR [rcx+88], r12 + mov rax, QWORD PTR [rdx+96] + mov r10, QWORD PTR [rdx+104] + mov r11, QWORD PTR [rdx+112] + mov r12, QWORD PTR [rdx+120] + sbb rax, QWORD PTR [r8+96] + sbb r10, QWORD PTR [r8+104] + sbb r11, QWORD PTR [r8+112] + sbb r12, QWORD PTR [r8+120] + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov QWORD PTR [rcx+112], r11 + mov QWORD PTR [rcx+120], r12 + sbb r13, 0 + mov r11, QWORD PTR [r9] + mov r12, QWORD PTR [r9+8] + mov rax, QWORD PTR [rcx] + mov r10, QWORD PTR [rcx+8] + pext r11, r11, r13 + pext r12, r12, r13 + add rax, r11 + adc r10, r12 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov r11, QWORD PTR [r9+16] + mov r12, QWORD PTR [r9+24] + mov rax, QWORD PTR [rcx+16] + mov r10, QWORD PTR [rcx+24] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov r11, QWORD PTR [r9+32] + mov r12, QWORD PTR [r9+40] + mov rax, QWORD PTR [rcx+32] + mov r10, QWORD PTR [rcx+40] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov r11, QWORD PTR [r9+48] + mov r12, QWORD PTR [r9+56] + mov rax, QWORD PTR [rcx+48] + mov r10, QWORD PTR [rcx+56] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + mov r11, QWORD PTR [r9+64] + mov r12, QWORD PTR [r9+72] + mov rax, QWORD PTR [rcx+64] + mov r10, QWORD PTR [rcx+72] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+64], rax + mov QWORD PTR [rcx+72], r10 + mov r11, QWORD PTR [r9+80] + mov r12, QWORD PTR [r9+88] + mov rax, QWORD PTR [rcx+80] + mov r10, QWORD PTR [rcx+88] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+80], rax + mov QWORD PTR [rcx+88], r10 + mov r11, QWORD PTR [r9+96] + mov r12, QWORD PTR [r9+104] + mov rax, QWORD PTR [rcx+96] + mov r10, QWORD PTR [rcx+104] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+96], rax + mov QWORD PTR [rcx+104], r10 + mov r11, QWORD PTR [r9+112] + mov r12, QWORD PTR [r9+120] + mov rax, QWORD PTR [rcx+112] + mov r10, QWORD PTR [rcx+120] + pext r11, r11, r13 + pext r12, r12, r13 + adc rax, r11 + adc r10, r12 + mov QWORD PTR [rcx+112], rax + mov QWORD PTR [rcx+120], r10 + pop r13 + pop r12 + ret +sp_1024_mont_sub_avx2_16 ENDP +_text ENDS +ENDIF +IFDEF HAVE_INTEL_AVX2 +; /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) +; * +; * r Result of division by 2. +; * a Number to divide. +; * m Modulus (prime). +; */ +_text SEGMENT READONLY PARA +sp_1024_div2_avx2_16 PROC + push r12 + push r13 + mov r13, QWORD PTR [rdx] + xor r12, r12 + mov r10, r13 + and r13, 1 + neg r13 + mov rax, QWORD PTR [r8] + mov r9, QWORD PTR [r8+8] + mov r10, QWORD PTR [rdx] + mov r11, QWORD PTR [rdx+8] + pext rax, rax, r13 + pext r9, r9, r13 + add r10, rax + adc r11, r9 + mov QWORD PTR [rcx], r10 + mov QWORD PTR [rcx+8], r11 + mov rax, QWORD PTR [r8+16] + mov r9, QWORD PTR [r8+24] + mov r10, QWORD PTR [rdx+16] + mov r11, QWORD PTR [rdx+24] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+16], r10 + mov QWORD PTR [rcx+24], r11 + mov rax, QWORD PTR [r8+32] + mov r9, QWORD PTR [r8+40] + mov r10, QWORD PTR [rdx+32] + mov r11, QWORD PTR [rdx+40] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+32], r10 + mov QWORD PTR [rcx+40], r11 + mov rax, QWORD PTR [r8+48] + mov r9, QWORD PTR [r8+56] + mov r10, QWORD PTR [rdx+48] + mov r11, QWORD PTR [rdx+56] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+48], r10 + mov QWORD PTR [rcx+56], r11 + mov rax, QWORD PTR [r8+64] + mov r9, QWORD PTR [r8+72] + mov r10, QWORD PTR [rdx+64] + mov r11, QWORD PTR [rdx+72] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+64], r10 + mov QWORD PTR [rcx+72], r11 + mov rax, QWORD PTR [r8+80] + mov r9, QWORD PTR [r8+88] + mov r10, QWORD PTR [rdx+80] + mov r11, QWORD PTR [rdx+88] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+80], r10 + mov QWORD PTR [rcx+88], r11 + mov rax, QWORD PTR [r8+96] + mov r9, QWORD PTR [r8+104] + mov r10, QWORD PTR [rdx+96] + mov r11, QWORD PTR [rdx+104] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+96], r10 + mov QWORD PTR [rcx+104], r11 + mov rax, QWORD PTR [r8+112] + mov r9, QWORD PTR [r8+120] + mov r10, QWORD PTR [rdx+112] + mov r11, QWORD PTR [rdx+120] + pext rax, rax, r13 + pext r9, r9, r13 + adc r10, rax + adc r11, r9 + mov QWORD PTR [rcx+112], r10 + mov QWORD PTR [rcx+120], r11 + adc r12, 0 + mov r10, QWORD PTR [rcx] + mov r11, QWORD PTR [rcx+8] + shrd r10, r11, 1 + mov QWORD PTR [rcx], r10 + mov r10, QWORD PTR [rcx+16] + shrd r11, r10, 1 + mov QWORD PTR [rcx+8], r11 + mov r11, QWORD PTR [rcx+24] + shrd r10, r11, 1 + mov QWORD PTR [rcx+16], r10 + mov r10, QWORD PTR [rcx+32] + shrd r11, r10, 1 + mov QWORD PTR [rcx+24], r11 + mov r11, QWORD PTR [rcx+40] + shrd r10, r11, 1 + mov QWORD PTR [rcx+32], r10 + mov r10, QWORD PTR [rcx+48] + shrd r11, r10, 1 + mov QWORD PTR [rcx+40], r11 + mov r11, QWORD PTR [rcx+56] + shrd r10, r11, 1 + mov QWORD PTR [rcx+48], r10 + mov r10, QWORD PTR [rcx+64] + shrd r11, r10, 1 + mov QWORD PTR [rcx+56], r11 + mov r11, QWORD PTR [rcx+72] + shrd r10, r11, 1 + mov QWORD PTR [rcx+64], r10 + mov r10, QWORD PTR [rcx+80] + shrd r11, r10, 1 + mov QWORD PTR [rcx+72], r11 + mov r11, QWORD PTR [rcx+88] + shrd r10, r11, 1 + mov QWORD PTR [rcx+80], r10 + mov r10, QWORD PTR [rcx+96] + shrd r11, r10, 1 + mov QWORD PTR [rcx+88], r11 + mov r11, QWORD PTR [rcx+104] + shrd r10, r11, 1 + mov QWORD PTR [rcx+96], r10 + mov r10, QWORD PTR [rcx+112] + shrd r11, r10, 1 + mov QWORD PTR [rcx+104], r11 + mov r11, QWORD PTR [rcx+120] + shrd r10, r11, 1 + mov QWORD PTR [rcx+112], r10 + shrd r11, r12, 1 + mov QWORD PTR [rcx+120], r11 + pop r13 + pop r12 + ret +sp_1024_div2_avx2_16 ENDP +_text ENDS +ENDIF +; /* Read big endian unsigned byte array into r. +; * Uses the bswap instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_1024_from_bin_bswap PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 128 + xor r13, r13 + jmp L_1024_from_bin_bswap_64_end +L_1024_from_bin_bswap_64_start: + sub r11, 64 + mov rax, QWORD PTR [r11+56] + mov r10, QWORD PTR [r11+48] + bswap rax + bswap r10 + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + mov rax, QWORD PTR [r11+40] + mov r10, QWORD PTR [r11+32] + bswap rax + bswap r10 + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + mov rax, QWORD PTR [r11+24] + mov r10, QWORD PTR [r11+16] + bswap rax + bswap r10 + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + mov rax, QWORD PTR [r11+8] + mov r10, QWORD PTR [r11] + bswap rax + bswap r10 + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_1024_from_bin_bswap_64_end: + cmp r9, 63 + jg L_1024_from_bin_bswap_64_start + jmp L_1024_from_bin_bswap_8_end +L_1024_from_bin_bswap_8_start: + sub r11, 8 + mov rax, QWORD PTR [r11] + bswap rax + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_1024_from_bin_bswap_8_end: + cmp r9, 7 + jg L_1024_from_bin_bswap_8_start + cmp r9, r13 + je L_1024_from_bin_bswap_hi_end + mov r10, r13 + mov rax, r13 +L_1024_from_bin_bswap_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_1024_from_bin_bswap_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_1024_from_bin_bswap_hi_end: + cmp rcx, r12 + je L_1024_from_bin_bswap_zero_end +L_1024_from_bin_bswap_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_1024_from_bin_bswap_zero_start +L_1024_from_bin_bswap_zero_end: + pop r13 + pop r12 + ret +sp_1024_from_bin_bswap ENDP +_text ENDS +IFNDEF NO_MOVBE_SUPPORT +; /* Read big endian unsigned byte array into r. +; * Uses the movbe instruction which is an optional instruction. +; * +; * r A single precision integer. +; * size Maximum number of bytes to convert +; * a Byte array. +; * n Number of bytes in array to read. +; */ +_text SEGMENT READONLY PARA +sp_1024_from_bin_movbe PROC + push r12 + push r13 + mov r11, r8 + mov r12, rcx + add r11, r9 + add r12, 128 + xor r13, r13 + jmp L_1024_from_bin_movbe_64_end +L_1024_from_bin_movbe_64_start: + sub r11, 64 + movbe rax, QWORD PTR [r11+56] + movbe r10, QWORD PTR [r11+48] + mov QWORD PTR [rcx], rax + mov QWORD PTR [rcx+8], r10 + movbe rax, QWORD PTR [r11+40] + movbe r10, QWORD PTR [r11+32] + mov QWORD PTR [rcx+16], rax + mov QWORD PTR [rcx+24], r10 + movbe rax, QWORD PTR [r11+24] + movbe r10, QWORD PTR [r11+16] + mov QWORD PTR [rcx+32], rax + mov QWORD PTR [rcx+40], r10 + movbe rax, QWORD PTR [r11+8] + movbe r10, QWORD PTR [r11] + mov QWORD PTR [rcx+48], rax + mov QWORD PTR [rcx+56], r10 + add rcx, 64 + sub r9, 64 +L_1024_from_bin_movbe_64_end: + cmp r9, 63 + jg L_1024_from_bin_movbe_64_start + jmp L_1024_from_bin_movbe_8_end +L_1024_from_bin_movbe_8_start: + sub r11, 8 + movbe rax, QWORD PTR [r11] + mov QWORD PTR [rcx], rax + add rcx, 8 + sub r9, 8 +L_1024_from_bin_movbe_8_end: + cmp r9, 7 + jg L_1024_from_bin_movbe_8_start + cmp r9, r13 + je L_1024_from_bin_movbe_hi_end + mov r10, r13 + mov rax, r13 +L_1024_from_bin_movbe_hi_start: + mov al, BYTE PTR [r8] + shl r10, 8 + inc r8 + add r10, rax + dec r9 + jg L_1024_from_bin_movbe_hi_start + mov QWORD PTR [rcx], r10 + add rcx, 8 +L_1024_from_bin_movbe_hi_end: + cmp rcx, r12 + je L_1024_from_bin_movbe_zero_end +L_1024_from_bin_movbe_zero_start: + mov QWORD PTR [rcx], r13 + add rcx, 8 + cmp rcx, r12 + jl L_1024_from_bin_movbe_zero_start +L_1024_from_bin_movbe_zero_end: + pop r13 + pop r12 + ret +sp_1024_from_bin_movbe ENDP +_text ENDS +ENDIF +ENDIF +END diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index af047ac3c..cb3c575e2 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -1,6 +1,6 @@ /* srp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -479,7 +479,7 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) return MP_INIT_E; /* v = g ^ x % N */ - if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); + r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; if (!r) r = mp_to_unsigned_bin(&v, verifier); if (!r) *size = mp_unsigned_bin_size(&v); @@ -511,7 +511,7 @@ int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size) r = mp_init(&p); if (r != MP_OKAY) return MP_INIT_E; - if (!r) r = mp_read_unsigned_bin(&p, priv, size); + r = mp_read_unsigned_bin(&p, priv, size); if (!r) r = mp_mod(&p, &srp->N, &srp->priv); if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0; diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 8dab88207..26e39386f 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -1,6 +1,6 @@ /* tfm.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,14 +58,6 @@ #include #endif -#ifdef USE_WINDOWS_API - #pragma warning(disable:4127) - /* Disables the warning: - * 4127: conditional expression is constant - * in this file. - */ -#endif - #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) #ifdef __cplusplus extern "C" { @@ -990,7 +982,7 @@ int fp_mod(fp_int *a, fp_int *b, fp_int *c) fp_init(t); err = fp_div(a, b, NULL, t); if (err == FP_OKAY) { - if (t->sign != b->sign) { + if (!fp_iszero(t) && (t->sign != b->sign)) { err = fp_add(t, b, c); } else { fp_copy(t, c); @@ -1399,7 +1391,7 @@ top: /* b is now the inverse */ neg = a->sign; while (D->sign == FP_NEG) { - fp_add (D, b, D); + err = fp_add (D, b, D); if (err != FP_OKAY) { #ifdef WOLFSSL_SMALL_STACK XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); @@ -1468,12 +1460,15 @@ int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp) fp_sub_d(b, 2, e); /* Highest bit is always set. */ - for (i = fp_count_bits(e)-2, j = 1; i >= 0; i--, j++) { + j = 1; + for (i = fp_count_bits(e)-2; i >= 0; i--) { if (!fp_is_bit_set(e, i) || j == CT_INV_MOD_PRE_CNT) break; + j++; } fp_copy(&pre[j-1], t); - for (j = 0; i >= 0; i--) { + j = 0; + for (; i >= 0; i--) { int set = fp_is_bit_set(e, i); if ((j == CT_INV_MOD_PRE_CNT) || (!set && j > 0)) { @@ -3578,7 +3573,8 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) #error Both LITTLE_ENDIAN_ORDER and BIG_ENDIAN_ORDER defined. #endif -#if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) +#if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) && \ + (defined(FP_32BIT) || defined(FP_64BIT)) #ifdef FP_32BIT /* If we know the endianness of this architecture, and we're using 32-bit fp_digits, we can optimize this */ @@ -3586,7 +3582,6 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) unsigned char *pd = (unsigned char *)a->dp; a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit); - /* read the bytes in */ #ifdef BIG_ENDIAN_ORDER { /* Use Duff's device to unroll the loop. */ @@ -3601,6 +3596,7 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) } } #else + /* read the bytes in one at a time. */ for (c -= 1; c >= 0; c -= 1) { pd[c] = *b++; } @@ -3613,7 +3609,6 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) unsigned char *pd = (unsigned char *)a->dp; a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit); - /* read the bytes in */ #ifdef BIG_ENDIAN_ORDER { /* Use Duff's device to unroll the loop. */ @@ -3632,6 +3627,7 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) } } #else + /* read the bytes in one at a time. */ for (c -= 1; c >= 0; c -= 1) { pd[c] = *b++; } @@ -3639,7 +3635,7 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) } #endif #else - /* read the bytes in */ + /* read the bytes in one at a time - unknown number of bits in digit */ for (; c > 0; c--) { int err = fp_mul_2d (a, 8, a); if (err != FP_OKAY) { @@ -3660,10 +3656,11 @@ int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) { #if DIGIT_BIT == 64 || DIGIT_BIT == 32 - int i, j; + int i; + int j = 0; fp_digit n; - for (j=0,i=0; iused-1; ) { + for (i = 0; i < t->used-1; ) { b[x++] = (unsigned char)(t->dp[i] >> j); j += 8; i += j == DIGIT_BIT; @@ -3713,9 +3710,11 @@ int fp_to_unsigned_bin(fp_int *a, unsigned char *b) int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c) { #if DIGIT_BIT == 64 || DIGIT_BIT == 32 - int i, j, x; + int i = 0; + int j = 0; + int x; - for (x=c-1, j=0, i=0; x >= 0 && i < a->used; x--) { + for (x=c-1; x >= 0 && i < a->used; x--) { b[x] = (unsigned char)(a->dp[i] >> j); j += 8; i += j == DIGIT_BIT; @@ -3755,7 +3754,7 @@ int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c) #endif } -int fp_unsigned_bin_size(fp_int *a) +int fp_unsigned_bin_size(const fp_int *a) { int size = fp_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); @@ -3776,8 +3775,13 @@ int fp_set_int(fp_int *a, unsigned long b) { int x; - /* use direct fp_set if b is less than fp_digit max */ - if (b < FP_DIGIT_MAX) { + /* use direct fp_set if b is less than fp_digit max + * If input max value of b down shift by 1 less than full range + * fp_digit, then condition is always true. */ +#if ((ULONG_MAX >> (DIGIT_BIT-1)) > 0) + if (b < FP_DIGIT_MAX) +#endif + { fp_set (a, (fp_digit)b); return FP_OKAY; } @@ -3843,7 +3847,7 @@ int fp_set_bit (fp_int * a, fp_digit b) return MP_OKAY; } -int fp_count_bits (fp_int * a) +int fp_count_bits (const fp_int * a) { int r; fp_digit q; @@ -4271,7 +4275,11 @@ int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, mp_int * Y) return fp_exptmod_ex(G, X, digits, P, Y); } +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { return fp_exptmod_nct(G, X, P, Y); } @@ -4290,7 +4298,7 @@ int mp_cmp_d(mp_int * a, mp_digit b) } /* get the size for an unsigned equivalent */ -int mp_unsigned_bin_size (mp_int * a) +int mp_unsigned_bin_size (const mp_int * a) { return fp_unsigned_bin_size(a); } @@ -4344,7 +4352,7 @@ int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) return MP_OKAY; } -void fp_copy(fp_int *a, fp_int *b) +void fp_copy(const fp_int *a, fp_int *b) { /* if source and destination are different */ if (a != b) { @@ -4390,7 +4398,7 @@ void fp_init_copy(fp_int *a, fp_int* b) } /* fast math wrappers */ -int mp_copy(fp_int* a, fp_int* b) +int mp_copy(const fp_int* a, fp_int* b) { fp_copy(a, b); return MP_OKAY; @@ -4406,7 +4414,7 @@ int mp_iszero(mp_int* a) return fp_iszero(a); } -int mp_count_bits (mp_int* a) +int mp_count_bits (const mp_int* a) { return fp_count_bits(a); } @@ -4720,8 +4728,11 @@ int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c) static int fp_isprime_ex(fp_int *a, int t, int* result); - +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_prime_is_prime(mp_int* a, int t, int* result) +#else int mp_prime_is_prime(mp_int* a, int t, int* result) +#endif { return fp_isprime_ex(a, t, result); } @@ -4771,25 +4782,28 @@ static int fp_prime_miller_rabin_ex(fp_int * a, fp_int * b, int *result, defined(WOLFSSL_HAVE_SP_DH) #ifndef WOLFSSL_SP_NO_2048 if (fp_count_bits(a) == 1024 && fp_isodd(a)) - sp_ModExp_1024(b, r, a, y); + err = sp_ModExp_1024(b, r, a, y); else if (fp_count_bits(a) == 2048 && fp_isodd(a)) - sp_ModExp_2048(b, r, a, y); + err = sp_ModExp_2048(b, r, a, y); else #endif #ifndef WOLFSSL_SP_NO_3072 if (fp_count_bits(a) == 1536 && fp_isodd(a)) - sp_ModExp_1536(b, r, a, y); + err = sp_ModExp_1536(b, r, a, y); else if (fp_count_bits(a) == 3072 && fp_isodd(a)) - sp_ModExp_3072(b, r, a, y); + err = sp_ModExp_3072(b, r, a, y); else #endif #ifdef WOLFSSL_SP_4096 if (fp_count_bits(a) == 4096 && fp_isodd(a)) - sp_ModExp_4096(b, r, a, y); + err = sp_ModExp_4096(b, r, a, y); else #endif #endif - fp_exptmod(b, r, a, y); + err = fp_exptmod(b, r, a, y); + if (err != FP_OKAY) { + return err; + } /* if y != 1 and y != n1 do */ if (fp_cmp_d (y, 1) != FP_EQ && fp_cmp (y, n1) != FP_EQ) { @@ -4902,6 +4916,7 @@ int fp_isprime_ex(fp_int *a, int t, int* result) #endif fp_digit d; int r, res; + int err; if (t <= 0 || t > FP_PRIME_SIZE) { *result = FP_NO; @@ -4926,7 +4941,7 @@ int fp_isprime_ex(fp_int *a, int t, int* result) res = fp_mod_d(a, primes[r], &d); if (res != MP_OKAY || d == 0) { *result = FP_NO; - return FP_OKAY; + return res; } } @@ -4939,13 +4954,13 @@ int fp_isprime_ex(fp_int *a, int t, int* result) fp_init(b); for (r = 0; r < t; r++) { fp_set(b, primes[r]); - fp_prime_miller_rabin(a, b, &res); - if (res == FP_NO) { - *result = FP_NO; + err = fp_prime_miller_rabin(a, b, &res); + if ((err != FP_OKAY) || (res == FP_NO)) { + *result = res; #ifdef WOLFSSL_SMALL_STACK XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); #endif - return FP_OKAY; + return err; } } *result = FP_YES; @@ -4956,7 +4971,11 @@ int fp_isprime_ex(fp_int *a, int t, int* result) } +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +#else int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +#endif { int ret = FP_YES; fp_digit d; @@ -5019,6 +5038,7 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) b = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_BIGINT); if (b == NULL) { + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); return FP_MEM; } c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4]; @@ -5059,7 +5079,14 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) continue; } - fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r); + err = fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } if (ret == FP_NO) break; fp_zero(b); @@ -5210,6 +5237,12 @@ int fp_lcm(fp_int *a, fp_int *b, fp_int *c) fp_int *t; #endif + /* LCM of 0 and any number is undefined as 0 is not in the set of values + * being used. */ + if (fp_iszero(a) == FP_YES || fp_iszero(b) == FP_YES) { + return FP_VAL; + } + #ifdef WOLFSSL_SMALL_STACK t = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT); if (t == NULL) { @@ -5249,6 +5282,11 @@ int fp_gcd(fp_int *a, fp_int *b, fp_int *c) fp_int *u, *v, *r; #endif + /* GCD of 0 and 0 is undefined as all integers divide 0. */ + if (fp_iszero(a) == FP_YES && fp_iszero(b) == FP_YES) { + return FP_VAL; + } + /* either zero than gcd is the largest */ if (fp_iszero (a) == FP_YES && fp_iszero (b) == FP_NO) { fp_abs (b, c); @@ -5317,32 +5355,26 @@ int fp_gcd(fp_int *a, fp_int *b, fp_int *c) int fp_add_d(fp_int *a, fp_digit b, fp_int *c) { #ifndef WOLFSSL_SMALL_STACK - fp_int tmp; - int err; - fp_init(&tmp); - fp_set(&tmp, b); - err = fp_add(a, &tmp, c); - return err; + fp_int tmp[1]; #else - int i; - fp_word t = b; - int err = FP_OKAY; - - fp_copy(a, c); - for (i = 0; t != 0 && i < FP_SIZE && i < c->used; i++) { - t += c->dp[i]; - c->dp[i] = (fp_digit)t; - t >>= DIGIT_BIT; - } - if (i == c->used && i < FP_SIZE && t != 0) { - c->dp[i] = t; - c->used++; - } - if (i == FP_SIZE && t != 0) { - err = FP_VAL; - } - return err; + fp_int* tmp; #endif + int err; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) + return FP_MEM; +#endif + + fp_init(tmp); + fp_set(tmp, b); + err = fp_add(a, tmp, c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; } /* external compatibility */ @@ -5361,7 +5393,7 @@ int mp_add_d(fp_int *a, fp_digit b, fp_int *c) /* chars used in radix conversions */ static wcchar fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz+/"; + "abcdefghijklmnopqrstuvwxyz+/"; #endif #if !defined(NO_DSA) || defined(HAVE_ECC) diff --git a/wolfcrypt/src/wc_dsp.c b/wolfcrypt/src/wc_dsp.c index 594ad0489..f69a05f78 100644 --- a/wolfcrypt/src/wc_dsp.c +++ b/wolfcrypt/src/wc_dsp.c @@ -1,6 +1,6 @@ /* wc_dsp.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/wc_encrypt.c b/wolfcrypt/src/wc_encrypt.c index dbed40dad..331367b97 100644 --- a/wolfcrypt/src/wc_encrypt.c +++ b/wolfcrypt/src/wc_encrypt.c @@ -1,6 +1,6 @@ /* wc_encrypt.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -488,6 +488,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, byte unicodePasswd[MAX_UNICODE_SZ]; if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -510,6 +511,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, } #endif /* HAVE_PKCS12 */ else { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -518,6 +520,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, } if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -543,6 +546,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, ret = wc_Des_SetKey(&des, key, desIv, DES_DECRYPTION); } if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -570,6 +574,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, ret = wc_Des3Init(&des, NULL, INVALID_DEVID); if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -582,6 +587,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, ret = wc_Des3_SetKey(&des, key, desIv, DES_DECRYPTION); } if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -594,6 +600,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, ret = wc_Des3_CbcDecrypt(&des, input, input, length); } if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -648,6 +655,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, XFREE(aes, NULL, DYNAMIC_TYPE_AES); #endif if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -670,6 +678,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, ret = wc_Rc2CbcDecrypt(&rc2, input, input, length); } if (ret != 0) { + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -681,6 +690,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, #endif default: + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -688,6 +698,7 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, return ALGO_ID_E; } + ForceZero(key, MAX_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index ef4974b5e..b8b4ede04 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -1,6 +1,6 @@ /* wc_pkcs11.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -101,6 +101,14 @@ static CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY; #endif #ifdef WOLFSSL_DEBUG_PKCS11 +/* Enable logging of PKCS#11 calls and return value. */ +#define PKCS11_RV(op, rv) pkcs11_rv(op, rv) +/* Enable logging of PKCS#11 calls and value. */ +#define PKCS11_VAL(op, val) pkcs11_val(op, val) +/* Enable logging of PKCS#11 tmaplate. */ +#define PKCS11_DUMP_TEMPLATE(name, templ, cnt) \ + pkcs11_dump_template(name, templ, cnt) + /* Formats of template items - used to instruct how to log information. */ enum PKCS11_TYPE_FORMATS { PKCS11_FMT_BOOLEAN, @@ -156,10 +164,12 @@ static struct PKCS11_TYPE_STR { * * This is only for debugging purposes. Only the values needed are recognised. * + * @param [in] name PKCS #11 template name. * @param [in] templ PKCS #11 template to dump. * @param [in] cnt Count of template entries. */ -static void pkcs11_dump_template(CK_ATTRIBUTE* templ, CK_ULONG cnt) +static void pkcs11_dump_template(const char* name, CK_ATTRIBUTE* templ, + CK_ULONG cnt) { CK_ULONG i; int j; @@ -169,6 +179,8 @@ static void pkcs11_dump_template(CK_ATTRIBUTE* templ, CK_ULONG cnt) CK_KEY_TYPE keyType; CK_OBJECT_CLASS keyClass; + WOLFSSL_MSG(name); + for (i = 0; i < cnt; i++) { format = PKCS11_FMT_POINTER; @@ -340,7 +352,7 @@ static void pkcs11_dump_template(CK_ATTRIBUTE* templ, CK_ULONG cnt) /* * Log a PKCS #11 return value with the name of function called. * - * This is only for debugging purposes. Only the values needed are recognised. + * This is only for debugging purposes. Only the values needed are recognized. * * @param [in] op PKCS #11 operation that was attempted. * @param [in] rv PKCS #11 return value. @@ -381,6 +393,13 @@ static void pkcs11_val(const char* op, CK_ULONG val) WOLFSSL_MSG(line); } +#else +/* Disable logging of PKCS#11 calls and return value. */ +#define PKCS11_RV(op, ev) +/* Disable logging of PKCS#11 calls and value. */ +#define PKCS11_VAL(op, val) +/* Disable logging of PKCS#11 tmaplate. */ +#define PKCS11_DUMP_TEMPLATE(name, templ, cnt) #endif /** @@ -415,19 +434,27 @@ int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap) if (ret == 0) { dev->func = NULL; func = dlsym(dev->dlHandle, "C_GetFunctionList"); - if (func == NULL) + if (func == NULL) { + WOLFSSL_MSG(dlerror()); ret = WC_HW_E; + } } if (ret == 0) { - if (((CK_C_GetFunctionList)func)(&dev->func) != CKR_OK) + ret = ((CK_C_GetFunctionList)func)(&dev->func); + if (ret != CKR_OK) { + PKCS11_RV("CK_C_GetFunctionList", ret); ret = WC_HW_E; + } } if (ret == 0) { XMEMSET(&args, 0x00, sizeof(args)); args.flags = CKF_OS_LOCKING_OK; - if (dev->func->C_Initialize(&args) != CKR_OK) + ret = dev->func->C_Initialize(&args); + if (ret != CKR_OK) { + PKCS11_RV("C_Initialize", ret); ret = WC_INIT_E; + } } if (ret != 0) @@ -484,9 +511,7 @@ int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId, if (slotId < 0) { /* Use first available slot with a token. */ rv = dev->func->C_GetSlotList(CK_TRUE, NULL, &slotCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetSlotList", rv); -#endif + PKCS11_RV("C_GetSlotList", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -498,9 +523,7 @@ int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId, } if (ret == 0) { rv = dev->func->C_GetSlotList(CK_TRUE, slot, &slotCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetSlotList", rv); -#endif + PKCS11_RV("C_GetSlotList", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -574,18 +597,14 @@ static int Pkcs11OpenSession(Pkcs11Token* token, Pkcs11Session* session, rv = token->func->C_OpenSession(token->slotId, flags, (CK_VOID_PTR)NULL, (CK_NOTIFY)NULL, &session->handle); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_OpenSession", rv); -#endif + PKCS11_RV("C_OpenSession", rv); if (rv != CKR_OK) { ret = WC_HW_E; } if (ret == 0 && token->userPin != NULL) { rv = token->func->C_Login(session->handle, CKU_USER, token->userPin, token->userPinSz); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Login", rv); -#endif + PKCS11_RV("C_Login", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -739,16 +758,11 @@ static int Pkcs11CreateSecretKey(CK_OBJECT_HANDLE* key, Pkcs11Session* session, keyTmplCnt++; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Secret Key"); - pkcs11_dump_template(keyTemplate, keyTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Secret Key", keyTemplate, keyTmplCnt); /* Create an object containing key data for device to use. */ rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, key); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_CreateObject", rv); -#endif + PKCS11_RV("C_CreateObject", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -825,15 +839,10 @@ static int Pkcs11CreateRsaPrivateKey(CK_OBJECT_HANDLE* privateKey, keyTmplCnt++; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("RSA Private Key"); - pkcs11_dump_template(keyTemplate, keyTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("RSA Private Key", keyTemplate, keyTmplCnt); rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, privateKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_CreateObject", rv); -#endif + PKCS11_RV("C_CreateObject", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -943,15 +952,10 @@ static int Pkcs11CreateEccPublicKey(CK_OBJECT_HANDLE* publicKey, keyTemplate[4].pValue = ecPoint; keyTemplate[4].ulValueLen = len + i; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Ec Public Key"); - pkcs11_dump_template(keyTemplate, keyTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Ec Public Key", keyTemplate, keyTmplCnt); rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, publicKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_CreateObject", rv); -#endif + PKCS11_RV("C_CreateObject", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -1012,15 +1016,10 @@ static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey, keyTemplate[4].pValue = private_key->k.raw.buf; keyTemplate[4].ulValueLen = private_key->k.raw.len; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Ec Private Key"); - pkcs11_dump_template(keyTemplate, keyTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Ec Private Key", keyTemplate, keyTmplCnt); rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, privateKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_CreateObject", rv); -#endif + PKCS11_RV("C_CreateObject", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -1047,9 +1046,7 @@ static int Pkcs11MechAvail(Pkcs11Session* session, CK_MECHANISM_TYPE mech) CK_MECHANISM_INFO mechInfo; rv = session->func->C_GetMechanismInfo(session->slotId, mech, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK) { ret = NOT_COMPILED_IN; } @@ -1302,31 +1299,22 @@ static int Pkcs11FindKeyByTemplate(CK_OBJECT_HANDLE* key, WOLFSSL_MSG("PKCS#11: Find Key By Template"); -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Find Key"); - pkcs11_dump_template(keyTemplate, keyTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Find Key", keyTemplate, keyTmplCnt); rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, keyTmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_FindObjectsInit", rv); -#endif + PKCS11_RV("C_FindObjectsInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } if (ret == 0) { rv = session->func->C_FindObjects(session->handle, key, 1, count); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_FindObjects", rv); - pkcs11_val("C_FindObjects Count", *count); -#endif + PKCS11_RV("C_FindObjects", rv); + PKCS11_VAL("C_FindObjects Count", *count); if (rv != CKR_OK) { ret = WC_HW_E; } rv = session->func->C_FindObjectsFinal(session->handle); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_FindObjectsFinal", rv); -#endif + PKCS11_RV("C_FindObjectsFinal", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -1437,23 +1425,18 @@ static int Pkcs11FindRsaKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, } /** - * Exponentiate the input with the public part of the RSA key. - * Used in public encrypt and decrypt. + * Make a handle to a public RSA key. * - * @param [in] session Session object. - * @param [in] info Cryptographic operation data. - * @return WC_HW_E when a PKCS#11 library call fails. - * 0 on success. + * @param [in] session Session object. + * @param [in] rsaKey RSA key with modulus to search on. + * @param [in] sessionKey Whether to create a session key. + * @param [out] publicKey Handle to public key object. */ -static int Pkcs11RsaPublic(Pkcs11Session* session, wc_CryptoInfo* info) +static int Pkcs11RsaPublicKey(Pkcs11Session* session, RsaKey* rsaKey, + int sessionKey, CK_OBJECT_HANDLE* publicKey) { int ret = 0; CK_RV rv; - CK_MECHANISM mech; - CK_ULONG outLen; - CK_OBJECT_HANDLE publicKey = NULL_PTR; - int sessionKey = 0; - RsaKey* rsaKey = info->pk.rsa.key; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, @@ -1463,76 +1446,30 @@ static int Pkcs11RsaPublic(Pkcs11Session* session, wc_CryptoInfo* info) }; CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); - WOLFSSL_MSG("PKCS#11: RSA Public Key Operation"); + if (sessionKey) { + /* Set the modulus and public exponent data. */ + keyTemplate[3].pValue = rsaKey->n.raw.buf; + keyTemplate[3].ulValueLen = rsaKey->n.raw.len; + keyTemplate[4].pValue = rsaKey->e.raw.buf; + keyTemplate[4].ulValueLen = rsaKey->e.raw.len; - if (info->pk.rsa.outLen == NULL) { - ret = BAD_FUNC_ARG; - } - - if (ret == 0) { - if ((sessionKey = !mp_iszero(&rsaKey->e))) { - /* Set the modulus and public exponent data. */ - keyTemplate[3].pValue = rsaKey->n.raw.buf; - keyTemplate[3].ulValueLen = rsaKey->n.raw.len; - keyTemplate[4].pValue = rsaKey->e.raw.buf; - keyTemplate[4].ulValueLen = rsaKey->e.raw.len; - -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("RSA Public Key"); - pkcs11_dump_template(keyTemplate, keyTmplCnt); -#endif - /* Create an object containing public key data for device to use. */ - rv = session->func->C_CreateObject(session->handle, keyTemplate, - keyTmplCnt, &publicKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_CreateObject", rv); -#endif - if (rv != CKR_OK) { - ret = WC_HW_E; - } - } - else if (info->pk.rsa.key->labelLen > 0) { - ret = Pkcs11FindKeyByLabel(&publicKey, CKO_PUBLIC_KEY, CKK_RSA, - session, info->pk.rsa.key->label, - info->pk.rsa.key->labelLen); - } - else { - ret = Pkcs11FindKeyById(&publicKey, CKO_PUBLIC_KEY, CKK_RSA, - session, rsaKey->id, rsaKey->idLen); - } - } - - if (ret == 0) { - /* Raw RSA encrypt/decrypt operation. */ - mech.mechanism = CKM_RSA_X_509; - mech.ulParameterLen = 0; - mech.pParameter = NULL; - - rv = session->func->C_EncryptInit(session->handle, &mech, publicKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_EncryptInit", rv); -#endif + PKCS11_DUMP_TEMPLATE("RSA Public Key", keyTemplate, keyTmplCnt); + /* Create an object containing public key data for device to use. */ + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, publicKey); + PKCS11_RV("C_CreateObject", rv); if (rv != CKR_OK) { ret = WC_HW_E; } } - if (ret == 0) { - outLen = (CK_ULONG)*info->pk.rsa.outLen; - rv = session->func->C_Encrypt(session->handle, - (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, - info->pk.rsa.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Encrypt", rv); -#endif - if (rv != CKR_OK) { - ret = WC_HW_E; - } + else if (rsaKey->labelLen > 0) { + ret = Pkcs11FindKeyByLabel(publicKey, CKO_PUBLIC_KEY, CKK_RSA, + session, rsaKey->label, rsaKey->labelLen); + } + else { + ret = Pkcs11FindKeyById(publicKey, CKO_PUBLIC_KEY, CKK_RSA, + session, rsaKey->id, rsaKey->idLen); } - if (ret == 0) - *info->pk.rsa.outLen = (word32)outLen; - - if (sessionKey) - session->func->C_DestroyObject(session->handle, publicKey); return ret; } @@ -1561,22 +1498,14 @@ static int Pkcs11GetRsaPublicKey(RsaKey* key, Pkcs11Session* session, CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); CK_RV rv; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Get RSA Public Key Length"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Get RSA Public Key Length", tmpl, tmplCnt); rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, tmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("RSA Public Key Length"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("RSA Public Key Length", tmpl, tmplCnt); if (ret == 0) { modSz = (int)tmpl[0].ulValueLen; @@ -1596,22 +1525,14 @@ static int Pkcs11GetRsaPublicKey(RsaKey* key, Pkcs11Session* session, tmpl[0].pValue = mod; tmpl[1].pValue = exp; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Get RSA Public Key"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Get RSA Public Key", tmpl, tmplCnt); rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, tmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("RSA Public Key"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("RSA Public Key", tmpl, tmplCnt); } if (ret == 0) ret = wc_RsaPublicKeyDecodeRaw(mod, modSz, exp, expSz, key); @@ -1624,6 +1545,93 @@ static int Pkcs11GetRsaPublicKey(RsaKey* key, Pkcs11Session* session, return ret; } +/** + * Make a handle to a private RSA key. + * + * @param [in] session Session object. + * @param [in] rsaKey RSA key with modulus to search on. + * @param [in] sessionKey Whether to create a session key. + * @param [out] publicKey Handle to private key object. + */ +static int Pkcs11RsaPrivateKey(Pkcs11Session* session, RsaKey* rsaKey, + int sessionKey, CK_OBJECT_HANDLE* privateKey) +{ + int ret; + + if (sessionKey) { + ret = Pkcs11CreateRsaPrivateKey(privateKey, session, rsaKey, 0); + } + else if (rsaKey->labelLen > 0) { + ret = Pkcs11FindKeyByLabel(privateKey, CKO_PRIVATE_KEY, CKK_RSA, + session, rsaKey->label, rsaKey->labelLen); + } + else if (rsaKey->idLen > 0) { + ret = Pkcs11FindKeyById(privateKey, CKO_PRIVATE_KEY, CKK_RSA, session, + rsaKey->id, rsaKey->idLen); + } + else { + ret = Pkcs11FindRsaKey(privateKey, CKO_PRIVATE_KEY, session, rsaKey); + } + + if ((ret == 0) && (!sessionKey)) { + ret = Pkcs11GetRsaPublicKey(rsaKey, session, *privateKey); + } + + return ret; +} + +/** + * Exponentiate the input with the public part of the RSA key. + * Used in public encrypt and decrypt. + * + * @param [in] session Session object. + * @param [in] info Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaEncrypt(Pkcs11Session* session, wc_CryptoInfo* info, + CK_OBJECT_HANDLE key) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_ULONG outLen; + + WOLFSSL_MSG("PKCS#11: RSA Public Key Operation"); + + if (info->pk.rsa.outLen == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Raw RSA encrypt/decrypt operation. */ + mech.mechanism = CKM_RSA_X_509; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_EncryptInit(session->handle, &mech, key); + PKCS11_RV("C_EncryptInit", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Encrypt(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + PKCS11_RV("C_Encrypt", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + *info->pk.rsa.outLen = (word32)outLen; + } + + return ret; +} + /** * Exponentiate the input with the private part of the RSA key. * Used in private encrypt and decrypt. @@ -1634,15 +1642,13 @@ static int Pkcs11GetRsaPublicKey(RsaKey* key, Pkcs11Session* session, * @return WC_HW_E when a PKCS#11 library call fails. * @return 0 on success. */ -static int Pkcs11RsaPrivate(Pkcs11Session* session, wc_CryptoInfo* info, - int func) +static int Pkcs11RsaDecrypt(Pkcs11Session* session, wc_CryptoInfo* info, + CK_OBJECT_HANDLE key) { int ret = 0; CK_RV rv; CK_MECHANISM mech; CK_ULONG outLen; - CK_OBJECT_HANDLE privateKey = NULL_PTR; - int sessionKey = 0; WOLFSSL_MSG("PKCS#11: RSA Private Key Operation"); @@ -1651,28 +1657,58 @@ static int Pkcs11RsaPrivate(Pkcs11Session* session, wc_CryptoInfo* info, } if (ret == 0) { - if ((sessionKey = !mp_iszero(&info->pk.rsa.key->d))) { - ret = Pkcs11CreateRsaPrivateKey(&privateKey, session, - info->pk.rsa.key, 0); - } - else if (info->pk.rsa.key->labelLen > 0) { - ret = Pkcs11FindKeyByLabel(&privateKey, CKO_PRIVATE_KEY, CKK_RSA, - session, info->pk.rsa.key->label, - info->pk.rsa.key->labelLen); - } - else if (info->pk.rsa.key->idLen > 0) { - ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_RSA, - session, info->pk.rsa.key->id, - info->pk.rsa.key->idLen); - } - else { - ret = Pkcs11FindRsaKey(&privateKey, CKO_PRIVATE_KEY, session, - info->pk.rsa.key); + /* Raw RSA encrypt/decrypt operation. */ + mech.mechanism = CKM_RSA_X_509; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_DecryptInit(session->handle, &mech, key); + PKCS11_RV("C_DecryptInit", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; } } + if (ret == 0) { + PKCS11_VAL("C_Decrypt inLen", info->pk.rsa.inLen); + PKCS11_VAL("C_Decrypt outLen", *info->pk.rsa.outLen); + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Decrypt(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + PKCS11_RV("C_Decrypt", rv); + if (rv != CKR_OK) { + ret = WC_HW_E; + } + } + if (ret == 0) { + *info->pk.rsa.outLen = (word32)outLen; + } - if ((ret == 0) && (!sessionKey)) { - ret = Pkcs11GetRsaPublicKey(info->pk.rsa.key, session, privateKey); + return ret; +} + +/** + * Exponentiate the input with the private part of the RSA key. + * Used in private encrypt and decrypt. + * + * @param [in] session Session object. + * @param [in] info Cryptographic operation data. + * @param [in] func Function to perform - decrypt or sign. + * @return WC_HW_E when a PKCS#11 library call fails. + * @return 0 on success. + */ +static int Pkcs11RsaSign(Pkcs11Session* session, wc_CryptoInfo* info, + CK_OBJECT_HANDLE key) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_ULONG outLen; + + WOLFSSL_MSG("PKCS#11: RSA Private Key Operation"); + + if (info->pk.rsa.outLen == NULL) { + ret = BAD_FUNC_ARG; } if (ret == 0) { @@ -1681,50 +1717,20 @@ static int Pkcs11RsaPrivate(Pkcs11Session* session, wc_CryptoInfo* info, mech.ulParameterLen = 0; mech.pParameter = NULL; - if (func == CKF_DECRYPT) { - rv = session->func->C_DecryptInit(session->handle, &mech, - privateKey); - #ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptInit", rv); - #endif - } - else { - rv = session->func->C_SignInit(session->handle, &mech, privateKey); - #ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_SignInit", rv); - #endif - } + rv = session->func->C_SignInit(session->handle, &mech, key); + PKCS11_RV("C_SignInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } } if (ret == 0) { - if (func == CKF_DECRYPT) { - #ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_val("C_Decrypt inLen", info->pk.rsa.inLen); - pkcs11_val("C_Decrypt outLen", *info->pk.rsa.outLen); - #endif - outLen = (CK_ULONG)*info->pk.rsa.outLen; - rv = session->func->C_Decrypt(session->handle, - (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, - info->pk.rsa.out, &outLen); - #ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Decrypt", rv); - #endif - } - else { - #ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_val("C_Sign inLen", info->pk.rsa.inLen); - pkcs11_val("C_Sign outLen", *info->pk.rsa.outLen); - #endif - outLen = (CK_ULONG)*info->pk.rsa.outLen; - rv = session->func->C_Sign(session->handle, - (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, - info->pk.rsa.out, &outLen); - #ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Sign", rv); - #endif - } + PKCS11_VAL("C_Sign inLen", info->pk.rsa.inLen); + PKCS11_VAL("C_Sign outLen", *info->pk.rsa.outLen); + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Sign(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + PKCS11_RV("C_Sign", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -1732,8 +1738,6 @@ static int Pkcs11RsaPrivate(Pkcs11Session* session, wc_CryptoInfo* info, if (ret == 0) *info->pk.rsa.outLen = (word32)outLen; - if (sessionKey) - session->func->C_DestroyObject(session->handle, privateKey); return ret; } @@ -1751,42 +1755,73 @@ static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info) int ret = 0; CK_RV rv; CK_MECHANISM_INFO mechInfo; + int sessionKey = 0; + CK_OBJECT_HANDLE key; + RsaKey* rsaKey = info->pk.rsa.key; + int type = info->pk.rsa.type; /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_RSA_X_509, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK) { ret = NOT_COMPILED_IN; } if (ret == 0) { - if (info->pk.rsa.type == RSA_PUBLIC_ENCRYPT || - info->pk.rsa.type == RSA_PUBLIC_DECRYPT) { - if ((mechInfo.flags & CKF_ENCRYPT) == 0) - ret = NOT_COMPILED_IN; - else - ret = Pkcs11RsaPublic(session, info); + if ((type == RSA_PUBLIC_ENCRYPT) || (type == RSA_PUBLIC_DECRYPT)) { + sessionKey = !mp_iszero(&rsaKey->e); + + /* Make a handle to a public key. */ + ret = Pkcs11RsaPublicKey(session, rsaKey, sessionKey, &key); } - else if (info->pk.rsa.type == RSA_PRIVATE_ENCRYPT || - info->pk.rsa.type == RSA_PRIVATE_DECRYPT) { - if ((mechInfo.flags & CKF_DECRYPT) == 0 && - (mechInfo.flags & CKF_SIGN) == 0) { + else { + sessionKey = !mp_iszero(&rsaKey->d); + + /* Make a handle to a private key. */ + ret = Pkcs11RsaPrivateKey(session, rsaKey, sessionKey, &key); + } + + if (type == RSA_PUBLIC_ENCRYPT) { + WOLFSSL_MSG("PKCS#11: Public Encrypt"); + if ((mechInfo.flags & CKF_ENCRYPT) != 0) { + ret = Pkcs11RsaEncrypt(session, info, key); + } + else { ret = NOT_COMPILED_IN; } - else if ((info->pk.rsa.type == RSA_PRIVATE_ENCRYPT && - (mechInfo.flags & CKF_SIGN) != 0) || - (info->pk.rsa.type == RSA_PRIVATE_DECRYPT && - (mechInfo.flags & CKF_DECRYPT) == 0)) { - ret = Pkcs11RsaPrivate(session, info, CKF_SIGN); - } - else - ret = Pkcs11RsaPrivate(session, info, CKF_DECRYPT); } - else - ret = NOT_COMPILED_IN; + else if (type == RSA_PUBLIC_DECRYPT) { + WOLFSSL_MSG("PKCS#11: Public Decrypt"); + if ((mechInfo.flags & CKF_DECRYPT) != 0) { + ret = Pkcs11RsaEncrypt(session, info, key); + } + else { + ret = NOT_COMPILED_IN; + } + } + else if (type == RSA_PRIVATE_DECRYPT) { + WOLFSSL_MSG("PKCS#11: Private Decrypt"); + if ((mechInfo.flags & CKF_DECRYPT) != 0) { + ret = Pkcs11RsaDecrypt(session, info, key); + } + else { + ret = Pkcs11RsaSign(session, info, key); + } + } + else if (type == RSA_PRIVATE_ENCRYPT) { + WOLFSSL_MSG("PKCS#11: Private Encrypt"); + if ((mechInfo.flags & CKF_SIGN) != 0) { + ret = Pkcs11RsaSign(session, info, key); + } + else { + ret = Pkcs11RsaDecrypt(session, info, key); + } + } + } + + if (sessionKey) { + session->func->C_DestroyObject(session->handle, key); } return ret; @@ -1859,19 +1894,13 @@ static int Pkcs11RsaKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) mech.ulParameterLen = 0; mech.pParameter = NULL; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Public Key"); - pkcs11_dump_template(pubKeyTmpl, pubTmplCnt); - WOLFSSL_MSG("Private Key"); - pkcs11_dump_template(privKeyTmpl, privTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Public Key", pubKeyTmpl, pubTmplCnt); + PKCS11_DUMP_TEMPLATE("Private Key", privKeyTmpl, privTmplCnt); rv = session->func->C_GenerateKeyPair(session->handle, &mech, pubKeyTmpl, pubTmplCnt, privKeyTmpl, privTmplCnt, &pubKey, &privKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GenerateKeyPair", rv); -#endif + PKCS11_RV("C_GenerateKeyPair", rv); if (rv != CKR_OK) { ret = -1; } @@ -1948,32 +1977,23 @@ static int Pkcs11FindEccKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, attrCnt++; } if (ret == 0) { -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Find Ec Key"); - pkcs11_dump_template(keyTemplate, attrCnt); -#endif + PKCS11_DUMP_TEMPLATE("Find Ec Key", keyTemplate, attrCnt); rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, attrCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_FindObjectsInit", rv); -#endif + PKCS11_RV("C_FindObjectsInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } } if (ret == 0) { rv = session->func->C_FindObjects(session->handle, key, 1, &count); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_FindObjects", rv); - pkcs11_val("C_FindObjects Count", count); -#endif + PKCS11_RV("C_FindObjects", rv); + PKCS11_VAL("C_FindObjects Count", count); if (rv != CKR_OK) { ret = WC_HW_E; } rv = session->func->C_FindObjectsFinal(session->handle); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_FindObjectsFinal", rv); -#endif + PKCS11_RV("C_FindObjectsFinal", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -2012,9 +2032,7 @@ static int Pkcs11GetEccPublicKey(ecc_key* key, Pkcs11Session* session, rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, tmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -2028,22 +2046,14 @@ static int Pkcs11GetEccPublicKey(ecc_key* key, Pkcs11Session* session, if (ret == 0) { tmpl[0].pValue = point; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Get Ec Public Key"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Get Ec Public Key", tmpl, tmplCnt); rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, tmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Ec Public Key"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Ec Public Key", tmpl, tmplCnt); } /* Make sure the data is big enough for ASN.1: OCT + uncompressed point */ @@ -2150,20 +2160,14 @@ static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) mech.ulParameterLen = 0; mech.pParameter = NULL; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Ec Private"); - pkcs11_dump_template(privKeyTmpl, privTmplCnt); - WOLFSSL_MSG("Ec Public"); - pkcs11_dump_template(pubKeyTmpl, pubTmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Ec Private", privKeyTmpl, privTmplCnt); + PKCS11_DUMP_TEMPLATE("Ec Public", pubKeyTmpl, pubTmplCnt); rv = session->func->C_GenerateKeyPair(session->handle, &mech, pubKeyTmpl, pubTmplCnt, privKeyTmpl, privTmplCnt, &pubKey, &privKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GenerateKeyPair", rv); -#endif + PKCS11_RV("C_GenerateKeyPair", rv); if (rv != CKR_OK) { ret = -1; } @@ -2203,44 +2207,28 @@ static int Pkcs11ExtractSecret(Pkcs11Session* session, CK_OBJECT_HANDLE secret, CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); CK_RV rv; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Get Secret Length"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Get Secret Length", tmpl, tmplCnt); rv = session->func->C_GetAttributeValue(session->handle, secret, tmpl, tmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Secret Length"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Secret Length", tmpl, tmplCnt); if (ret == 0) { if (tmpl[0].ulValueLen > *outLen) ret = BUFFER_E; } if (ret == 0) { tmpl[0].pValue = out; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Get Secret"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Get Secret", tmpl, tmplCnt); rv = session->func->C_GetAttributeValue(session->handle, secret, tmpl, tmplCnt); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Secret"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("Secret", tmpl, tmplCnt); *outLen = (word32)tmpl[0].ulValueLen; } @@ -2330,15 +2318,10 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) mech.ulParameterLen = sizeof(params); mech.pParameter = ¶ms; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("ECDH key"); - pkcs11_dump_template(tmpl, tmplCnt); -#endif + PKCS11_DUMP_TEMPLATE("ECDH key", tmpl, tmplCnt); rv = session->func->C_DeriveKey(session->handle, &mech, privateKey, tmpl, tmplCnt, &secret); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DeriveKey", rv); -#endif + PKCS11_RV("C_DeriveKey", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -2524,22 +2507,14 @@ static int Pkcs11GetEccParams(Pkcs11Session* session, CK_OBJECT_HANDLE privKey, { CKA_EC_PARAMS, (CK_VOID_PTR)oid, sizeof(oid) } }; -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Get Ec Params"); - pkcs11_dump_template(template, 1); -#endif + PKCS11_DUMP_TEMPLATE("Get Ec Params", template, 1); rv = session->func->C_GetAttributeValue(session->handle, privKey, template, 1); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetAttributeValue", rv); -#endif + PKCS11_RV("C_GetAttributeValue", rv); if (rv != CKR_OK) { ret = WC_HW_E; } -#ifdef WOLFSSL_DEBUG_PKCS11 - WOLFSSL_MSG("Ec Params"); - pkcs11_dump_template(template, 1); -#endif + PKCS11_DUMP_TEMPLATE("Ec Params", template, 1); if (ret == 0) { /* PKCS #11 wraps the OID in ASN.1 */ curveId = wc_ecc_get_curve_id_from_oid(oid + 2, @@ -2575,15 +2550,16 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0) ret = NOT_COMPILED_IN; if (ret == 0 && info->pk.eccsign.outlen == NULL) { ret = BAD_FUNC_ARG; } + if (ret == 0 && info->pk.eccsign.out == NULL) { + ret = BAD_FUNC_ARG; + } if (ret == 0) { WOLFSSL_MSG("PKCS#11: EC Signing Operation"); @@ -2627,9 +2603,7 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = NULL; rv = session->func->C_SignInit(session->handle, &mech, privateKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_SignInit", rv); -#endif + PKCS11_RV("C_SignInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -2641,9 +2615,7 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) (CK_BYTE_PTR)info->pk.eccsign.in, info->pk.eccsign.inlen, info->pk.eccsign.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Sign", rv); -#endif + PKCS11_RV("C_Sign", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -2682,9 +2654,7 @@ static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_VERIFY) == 0) ret = NOT_COMPILED_IN; @@ -2716,9 +2686,7 @@ static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = NULL; rv = session->func->C_VerifyInit(session->handle, &mech, publicKey); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_VerifyInit", rv); -#endif + PKCS11_RV("C_VerifyInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -2730,9 +2698,7 @@ static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info) (CK_BYTE_PTR)info->pk.eccverify.hash, info->pk.eccverify.hashlen, (CK_BYTE_PTR)sig, sz * 2); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Verify", rv); -#endif + PKCS11_RV("C_Verify", rv); if (rv == CKR_SIGNATURE_INVALID) { } else if (rv != CKR_OK) @@ -2983,9 +2949,7 @@ static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0) ret = NOT_COMPILED_IN; @@ -3021,9 +2985,7 @@ static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = ¶ms; rv = session->func->C_EncryptInit(session->handle, &mech, key); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_EncryptInit", rv); -#endif + PKCS11_RV("C_EncryptInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3035,9 +2997,7 @@ static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) info->cipher.aesgcm_enc.sz, info->cipher.aesgcm_enc.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_EncryptUpdate", rv); -#endif + PKCS11_RV("C_EncryptUpdate", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3048,9 +3008,7 @@ static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) rv = session->func->C_EncryptFinal(session->handle, info->cipher.aesgcm_enc.authTag, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_EncryptFinal", rv); -#endif + PKCS11_RV("C_EncryptFinal", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3086,9 +3044,7 @@ static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0) ret = NOT_COMPILED_IN; @@ -3124,9 +3080,7 @@ static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = ¶ms; rv = session->func->C_DecryptInit(session->handle, &mech, key); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptInit", rv); -#endif + PKCS11_RV("C_DecryptInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3138,9 +3092,7 @@ static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) info->cipher.aesgcm_dec.sz, info->cipher.aesgcm_dec.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptUpdate", rv); -#endif + PKCS11_RV("C_DecryptUpdate", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3154,9 +3106,7 @@ static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) info->cipher.aesgcm_dec.authTagSz, info->cipher.aesgcm_dec.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptUpdate", rv); -#endif + PKCS11_RV("C_DecryptUpdate", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3167,9 +3117,7 @@ static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) rv = session->func->C_DecryptFinal(session->handle, info->cipher.aesgcm_dec.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptFinal", rv); -#endif + PKCS11_RV("C_DecryptFinal", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3205,9 +3153,7 @@ static int Pkcs11AesCbcEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0) ret = NOT_COMPILED_IN; @@ -3237,9 +3183,7 @@ static int Pkcs11AesCbcEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = (CK_BYTE_PTR)info->cipher.aescbc.aes->reg; rv = session->func->C_EncryptInit(session->handle, &mech, key); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_EncryptInit", rv); -#endif + PKCS11_RV("C_EncryptInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3251,9 +3195,7 @@ static int Pkcs11AesCbcEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) info->cipher.aescbc.sz, info->cipher.aescbc.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_Encrypt", rv); -#endif + PKCS11_RV("C_Encrypt", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3287,9 +3229,7 @@ static int Pkcs11AesCbcDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0) ret = NOT_COMPILED_IN; @@ -3319,9 +3259,7 @@ static int Pkcs11AesCbcDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = (CK_BYTE_PTR)info->cipher.aescbc.aes->reg; rv = session->func->C_DecryptInit(session->handle, &mech, key); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptInit", rv); -#endif + PKCS11_RV("C_DecryptInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3333,9 +3271,7 @@ static int Pkcs11AesCbcDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) info->cipher.aescbc.sz, info->cipher.aescbc.out, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_DecryptUpdate", rv); -#endif + PKCS11_RV("C_DecryptUpdate", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3378,9 +3314,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) /* Check operation is supported. */ rv = session->func->C_GetMechanismInfo(session->slotId, mechType, &mechInfo); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GetMechanismInfo", rv); -#endif + PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0) ret = NOT_COMPILED_IN; } @@ -3435,9 +3369,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) mech.pParameter = NULL; rv = session->func->C_SignInit(session->handle, &mech, key); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_SignInit", rv); -#endif + PKCS11_RV("C_SignInit", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3454,9 +3386,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) rv = session->func->C_SignUpdate(session->handle, (CK_BYTE_PTR)info->hmac.in, info->hmac.inSz); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_SignUpdate", rv); -#endif + PKCS11_RV("C_SignUpdate", rv); /* Some algorithm implementations only support C_Sign. */ if (rv == CKR_MECHANISM_INVALID) { WOLFSSL_MSG("PKCS#11: HMAC Update/Final not supported"); @@ -3475,9 +3405,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) rv = session->func->C_SignFinal(session->handle, (CK_BYTE_PTR)info->hmac.digest, &outLen); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_SignFinal", rv); -#endif + PKCS11_RV("C_SignFinal", rv); /* Some algorithm implementations only support C_Sign. */ if (rv != CKR_OK) { ret = WC_HW_E; @@ -3508,11 +3436,11 @@ static int Pkcs11RandomBlock(Pkcs11Session* session, wc_CryptoInfo* info) int ret = 0; CK_RV rv; + WOLFSSL_MSG("PKCS#11: Generate Random for Block"); + rv = session->func->C_GenerateRandom(session->handle, info->rng.out, info->rng.sz); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GenerateRandom", rv); -#endif + PKCS11_RV("C_GenerateRandom", rv); if (rv != CKR_OK) { ret = WC_HW_E; } @@ -3533,11 +3461,11 @@ static int Pkcs11RandomSeed(Pkcs11Session* session, wc_CryptoInfo* info) int ret = 0; CK_RV rv; + WOLFSSL_MSG("PKCS#11: Generate Random for Seed"); + rv = session->func->C_GenerateRandom(session->handle, info->seed.seed, info->seed.sz); -#ifdef WOLFSSL_DEBUG_PKCS11 - pkcs11_rv("C_GenerateRandom", rv); -#endif + PKCS11_RV("C_GenerateRandom", rv); if (rv != CKR_OK) { ret = WC_HW_E; } diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index cc7022e14..7e3d87a65 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -1,6 +1,6 @@ /* port.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -71,7 +71,7 @@ #endif #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ - defined(WOLFSSL_IMX6_CAAM_BLOB) + defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB) #include #endif @@ -266,7 +266,7 @@ int wolfCrypt_Init(void) #endif #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ - defined(WOLFSSL_IMX6_CAAM_BLOB) + defined(WOLFSSL_IMX6UL_CAAM) || defined(WOLFSSL_IMX6_CAAM_BLOB) if ((ret = wc_caamInit()) != 0) { return ret; } @@ -386,7 +386,11 @@ int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen, return BAD_PATH_ERROR; } - XFSEEK(f, 0, XSEEK_END); + if (XFSEEK(f, 0, XSEEK_END) != 0) { + WOLFSSL_MSG("wc_LoadFile file seek error"); + XFCLOSE(f); + return BAD_PATH_ERROR; + } fileSz = XFTELL(f); XREWIND(f); if (fileSz > 0) { @@ -415,6 +419,38 @@ int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen, #if !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) +/* File Handling Helper */ +/* returns 0 if file exists, WC_ISFILEEXIST_NOFILE if file doesn't exist */ +int wc_FileExists(const char* fname) +{ + struct ReadDirCtx ctx; + + if (fname == NULL) + return 0; + + if (XSTAT(fname, &ctx.s) != 0) { + WOLFSSL_MSG("stat on name failed"); + return BAD_PATH_ERROR; + } else +#if defined(USE_WINDOWS_API) + if (XS_ISREG(ctx.s.st_mode)) { + return 0; + } +#elif defined(WOLFSSL_ZEPHYR) + if (XS_ISREG(ctx.s.type)) { + return 0; + } +#elif defined(WOLFSSL_TELIT_M2MB) + if (XS_ISREG(ctx.s.st_mode)) { + return 0; + } +#else + if (XS_ISREG(ctx.s.st_mode)) { + return 0; + } +#endif + return WC_ISFILEEXIST_NOFILE; +} /* File Handling Helpers */ /* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */ @@ -431,7 +467,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) return BAD_FUNC_ARG; } - XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + XMEMSET(ctx, 0, sizeof(ReadDirCtx)); pathLen = (int)XSTRLEN(path); #ifdef USE_WINDOWS_API @@ -464,6 +500,37 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) return 0; } } while (FindNextFileA(ctx->hFind, &ctx->FindFileData)); + +#elif defined(INTIME_RTOS) + if (pathLen > MAX_FILENAME_SZ - 3) + return BAD_PATH_ERROR; + + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3); + XSTRNCPY(ctx->name + pathLen, "\\*", MAX_FILENAME_SZ - pathLen); + + if (!IntimeFindFirst(ctx->name, &ctx->FindFileData)) { + WOLFSSL_MSG("FindFirstFile for path verify locations failed"); + return BAD_PATH_ERROR; + } + + do { + dnameLen = (int)XSTRLEN(IntimeFilename(ctx)); + + if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { + return BAD_PATH_ERROR; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '\\'; + XSTRNCPY(ctx->name + pathLen + 1, + IntimeFilename(ctx), + MAX_FILENAME_SZ - pathLen - 1); + if (0 == wc_FileExists(ctx->name)) { + if (name) + *name = ctx->name; + return 0; + } + } while (IntimeFindNext(&ctx->FindFileData)); + #elif defined(WOLFSSL_ZEPHYR) if (fs_opendir(&ctx->dir, path) != 0) { WOLFSSL_MSG("opendir path verify locations failed"); @@ -485,11 +552,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); - if (fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -517,12 +580,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } - else if (ctx->s.st_mode & M2MB_S_IFREG) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -549,11 +607,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (S_ISREG(ctx->s.st_mode)) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -600,6 +654,26 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) return 0; } } + +#elif defined(INTIME_RTOS) + while (IntimeFindNext(&ctx->FindFileData)) { + dnameLen = (int)XSTRLEN(IntimeFilename(ctx)); + + if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { + return BAD_PATH_ERROR; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '\\'; + XSTRNCPY(ctx->name + pathLen + 1, + IntimeFilename(ctx), + MAX_FILENAME_SZ - pathLen - 1); + if (0 == wc_FileExists(ctx->name)) { + if (name) + *name = ctx->name; + return 0; + } + } + #elif defined(WOLFSSL_ZEPHYR) while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { dnameLen = (int)XSTRLEN(ctx->entry.name); @@ -615,11 +689,7 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); - if (fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -641,12 +711,7 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } - else if (ctx->s.st_mode & M2MB_S_IFREG) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -667,11 +732,7 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (S_ISREG(ctx->s.st_mode)) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -695,6 +756,10 @@ void wc_ReadDirClose(ReadDirCtx* ctx) FindClose(ctx->hFind); ctx->hFind = INVALID_HANDLE_VALUE; } + +#elif defined(INTIME_RTOS) + IntimeFindClose(&ctx->FindFileData); + #elif defined(WOLFSSL_ZEPHYR) if (ctx->dirp) { fs_closedir(ctx->dirp); @@ -1536,7 +1601,7 @@ int wolfSSL_CryptHwMutexUnLock(void) void *uITRON4_realloc(void *p, size_t sz) { ER ercd; - void *newp; + void *newp = NULL; if(p) { ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); if (ercd == E_OK) { @@ -1630,7 +1695,7 @@ int wolfSSL_CryptHwMutexUnLock(void) void *uTKernel_realloc(void *p, unsigned int sz) { ER ercd; - void *newp; + void *newp = NULL; if (p) { ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); if (ercd == E_OK) { @@ -2187,14 +2252,14 @@ time_t pic32_time(time_t* timer) time_t deos_time(time_t* timer) { const word32 systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); - word32 *systemTickPtr = systemTickPointer(); + const volatile word32 *systemTickPtr = systemTickPointer(); if (timer != NULL) *timer = *systemTickPtr/systemTickTimeInHz; #if defined(CURRENT_UNIX_TIMESTAMP) /* CURRENT_UNIX_TIMESTAMP is seconds since Jan 01 1970. (UTC) */ - return (time_t) *systemTickPtr/systemTickTimeInHz + CURRENT_UNIX_TIMESTAMP; + return (time_t) (*systemTickPtr/systemTickTimeInHz) + CURRENT_UNIX_TIMESTAMP; #else return (time_t) *systemTickPtr/systemTickTimeInHz; #endif diff --git a/wolfcrypt/src/wolfevent.c b/wolfcrypt/src/wolfevent.c index 20848cddc..8ae2717d7 100644 --- a/wolfcrypt/src/wolfevent.c +++ b/wolfcrypt/src/wolfevent.c @@ -1,6 +1,6 @@ /* wolfevent.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/wolfmath.c b/wolfcrypt/src/wolfmath.c index fd8c224b3..08d0f4642 100644 --- a/wolfcrypt/src/wolfmath.c +++ b/wolfcrypt/src/wolfmath.c @@ -1,6 +1,6 @@ /* wolfmath.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -71,7 +71,7 @@ #endif -int get_digit_count(mp_int* a) +int get_digit_count(const mp_int* a) { if (a == NULL) return 0; @@ -79,7 +79,7 @@ int get_digit_count(mp_int* a) return a->used; } -mp_digit get_digit(mp_int* a, int n) +mp_digit get_digit(const mp_int* a, int n) { if (a == NULL) return 0; @@ -142,7 +142,7 @@ int get_rand_digit(WC_RNG* rng, mp_digit* d) return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); } -#ifdef WC_RSA_BLINDING +#if defined(WC_RSA_BLINDING) || defined(WOLFCRYPT_HAVE_SAKKE) int mp_rand(mp_int* a, int digits, WC_RNG* rng) { int ret = 0; @@ -198,7 +198,7 @@ int mp_rand(mp_int* a, int digits, WC_RNG* rng) return ret; } -#endif /* WC_RSA_BLINDING */ +#endif /* WC_RSA_BLINDING || WOLFCRYPT_HAVE_SAKKE */ #endif #if defined(HAVE_ECC) || defined(WOLFSSL_EXPORT_INT) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 1d1bc566b..515c33a35 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1,6 +1,6 @@ /* test.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - #ifdef HAVE_CONFIG_H #include #endif @@ -90,7 +89,7 @@ #endif #ifdef __GNUC__ -_Pragma("GCC diagnostic ignored \"-Wunused-function\""); +_Pragma("GCC diagnostic ignored \"-Wunused-function\"") #endif #ifdef USE_FLAT_TEST_H @@ -164,6 +163,23 @@ _Pragma("GCC diagnostic ignored \"-Wunused-function\""); int dc_log_printf(char*, ...); #undef printf #define printf dc_log_printf +#elif defined(ANDROID) + #ifdef XMALLOC_USER + #include /* we're using malloc / free direct here */ + #endif + #ifndef STRING_USER + #include + #endif + #include + + #define printf(...) \ + __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__) + #define fprintf(fp, ...) \ + __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__) +#elif defined(WOLFSSL_DEOS) + #include + #undef printf + #define printf printx #else #ifdef XMALLOC_USER #include /* we're using malloc / free direct here */ @@ -238,6 +254,12 @@ _Pragma("GCC diagnostic ignored \"-Wunused-function\""); #ifdef HAVE_ED448 #include #endif +#ifdef WOLFCRYPT_HAVE_ECCSI + #include +#endif +#ifdef WOLFCRYPT_HAVE_SAKKE + #include +#endif #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) #include #endif @@ -290,7 +312,7 @@ _Pragma("GCC diagnostic ignored \"-Wunused-function\""); #include #endif -#if defined(NO_FILESYSTEM) +#if defined(NO_FILESYSTEM) || defined(WC_NO_RNG) #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) #define USE_CERT_BUFFERS_2048 @@ -310,6 +332,10 @@ _Pragma("GCC diagnostic ignored \"-Wunused-function\""); #include "libntruencrypt/ntru_crypto.h" #endif +#ifdef DEVKITPRO + #include +#endif + #ifdef WOLFSSL_STATIC_MEMORY static WOLFSSL_HEAP_HINT* HEAP_HINT; #else @@ -327,7 +353,11 @@ static void initDefaultName(void); #endif /* for async devices */ +#ifdef WOLFSSL_QNX_CAAM +static int devId = WOLFSSL_CAAM_DEVID; +#else static int devId = INVALID_DEVID; +#endif #ifdef HAVE_WNR const char* wnrConfigFile = "wnr-example.conf"; @@ -422,7 +452,8 @@ WOLFSSL_TEST_SUBROUTINE int scrypt_test(void); WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void); #endif #if defined(USE_CERT_BUFFERS_256) && !defined(WOLFSSL_ATECC508A) && \ - !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) + !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) && \ + defined(HAVE_ECC_VERIFY) && defined(HAVE_ECC_SIGN) /* skip for ATECC508/608A, cannot import private key buffers */ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void); #endif @@ -439,6 +470,12 @@ WOLFSSL_TEST_SUBROUTINE int scrypt_test(void); #ifdef HAVE_ED448 WOLFSSL_TEST_SUBROUTINE int ed448_test(void); #endif +#ifdef WOLFCRYPT_HAVE_ECCSI + WOLFSSL_TEST_SUBROUTINE int eccsi_test(void); +#endif +#ifdef WOLFCRYPT_HAVE_SAKKE + WOLFSSL_TEST_SUBROUTINE int sakke_test(void); +#endif #ifdef HAVE_BLAKE2 WOLFSSL_TEST_SUBROUTINE int blake2b_test(void); #endif @@ -849,10 +886,12 @@ initDefaultName(); test_pass("SHAKE256 test passed!\n"); #endif +#ifndef NO_HASH_WRAPPER if ( (ret = hash_test()) != 0) return err_sys("Hash test failed!\n", ret); else test_pass("Hash test passed!\n"); +#endif #ifdef WOLFSSL_RIPEMD if ( (ret = ripemd_test()) != 0) @@ -1177,7 +1216,8 @@ initDefaultName(); test_pass("ECC Enc test passed!\n"); #endif #if defined(USE_CERT_BUFFERS_256) && !defined(WOLFSSL_ATECC508A) && \ - !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) + !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) && \ + defined(HAVE_ECC_VERIFY) && defined(HAVE_ECC_SIGN) /* skip for ATECC508/608A, cannot import private key buffers */ if ( (ret = ecc_test_buffers()) != 0) return err_sys("ECC buffer test failed!\n", ret); @@ -1233,9 +1273,22 @@ initDefaultName(); #ifdef HAVE_ED448 if ( (ret = ed448_test()) != 0) - return err_sys("ED448 test failed!\n", ret); + return err_sys("ED448 test failed!\n", ret); else - test_pass("ED448 test passed!\n"); + test_pass("ED448 test passed!\n"); +#endif + +#ifdef WOLFCRYPT_HAVE_ECCSI + if ( (ret = eccsi_test()) != 0) + return err_sys("ECCSI test failed!\n", ret); + else + test_pass("ECCSI test passed!\n"); +#endif +#ifdef WOLFCRYPT_HAVE_SAKKE + if ( (ret = sakke_test()) != 0) + return err_sys("SAKKE test failed!\n", ret); + else + test_pass("SAKKE test passed!\n"); #endif #if defined(WOLFSSL_CMAC) && !defined(NO_AES) @@ -1331,7 +1384,8 @@ initDefaultName(); #endif #if defined(WOLF_CRYPTO_CB) && \ - !(defined(HAVE_INTEL_QAT_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC)) + !(defined(HAVE_INTEL_QAT_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC) || \ + defined(WOLFSSL_QNX_CAAM)) if ( (ret = cryptocb_test()) != 0) return err_sys("crypto callback test failed!\n", ret); else @@ -1413,6 +1467,26 @@ initDefaultName(); tz.tz_dsttime = 0; os_settimeofday(&utctime, &tz); #endif +#ifdef DEVKITPRO + void *framebuffer; + GXRModeObj *rmode = NULL; + + VIDEO_Init(); + WPAD_Init(); + + rmode = VIDEO_GetPreferredMode(NULL); +#pragma GCC diagnostic ignored "-Wbad-function-cast" + framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); +#pragma GCC diagnostic pop + console_init(framebuffer,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); + + VIDEO_Configure(rmode); + VIDEO_SetNextFramebuffer(framebuffer); + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + VIDEO_WaitVSync(); + if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); +#endif #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { @@ -1444,7 +1518,15 @@ initDefaultName(); if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context", -1005); #endif /* HAVE_WNR */ +#ifdef DOLPHIN_EMULATOR + /* Returning from main panics the emulator. Just hang + * and let the user force quit the emulator window. */ + printf("args.return_code: %d\n", args.return_code); + printf("Testing complete. You may close the window now\n"); + while (1); +#endif #ifndef WOLFSSL_ESPIDF + printf("Exiting main with return code: %d\n", args.return_code); return args.return_code; #endif } @@ -1602,6 +1684,7 @@ WOLFSSL_TEST_SUBROUTINE int base64_test(void) int ret; WOLFSSL_SMALL_STACK_STATIC const byte good[] = "A+Gd\0\0\0"; WOLFSSL_SMALL_STACK_STATIC const byte goodEnd[] = "A+Gd \r\n"; + WOLFSSL_SMALL_STACK_STATIC const byte good_spaces[] = " A + G d \0"; byte out[128]; word32 outLen; #ifdef WOLFSSL_BASE64_ENCODE @@ -1610,9 +1693,9 @@ WOLFSSL_TEST_SUBROUTINE int base64_test(void) byte longData[79] = { 0 }; WOLFSSL_SMALL_STACK_STATIC const byte symbols[] = "+/A="; #endif - WOLFSSL_SMALL_STACK_STATIC const byte badSmall[] = "AAA Gdj="; + WOLFSSL_SMALL_STACK_STATIC const byte badSmall[] = "AAA!Gdj="; WOLFSSL_SMALL_STACK_STATIC const byte badLarge[] = "AAA~Gdj="; - WOLFSSL_SMALL_STACK_STATIC const byte badEOL[] = "A+Gd AA"; + WOLFSSL_SMALL_STACK_STATIC const byte badEOL[] = "A+Gd!AA"; WOLFSSL_SMALL_STACK_STATIC const byte badPadding[] = "AA=A"; WOLFSSL_SMALL_STACK_STATIC const byte badChar[] = ",-.:;<=>?@[\\]^_`"; byte goodChar[] = @@ -1637,6 +1720,10 @@ WOLFSSL_TEST_SUBROUTINE int base64_test(void) return -1235; if (outLen != 64 / 4 * 3) return -1236; + outLen = sizeof(out); + ret = Base64_Decode(good_spaces, sizeof(good_spaces), out, &outLen); + if (ret != 0) + return -1201; /* Bad parameters. */ outLen = 1; @@ -3279,12 +3366,11 @@ WOLFSSL_TEST_SUBROUTINE int sha3_test(void) #ifdef WOLFSSL_SHAKE256 WOLFSSL_TEST_SUBROUTINE int shake256_test(void) { -#ifndef WOLFSSL_NO_SHAKE256 wc_Shake sha; - byte hash[114]; + byte hash[250]; - testVector a, b, c; - testVector test_sha[3]; + testVector a, b, c, d, e; + testVector test_sha[5]; int ret = 0; int times = sizeof(test_sha) / sizeof(struct testVector), i; @@ -3309,7 +3395,7 @@ WOLFSSL_TEST_SUBROUTINE int shake256_test(void) "\xbc\x0e\xab\x86\x28\x53\x34\x9e\xc7\x55\x46\xf5\x8f\xb7\xc2" "\x77\x5c\x38\x46\x2c\x50\x10\xd8\x46"; a.inLen = XSTRLEN(a.input); - a.outLen = sizeof(hash); + a.outLen = 114; b.input = "abc"; b.output = "\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11" @@ -3321,7 +3407,7 @@ WOLFSSL_TEST_SUBROUTINE int shake256_test(void) "\x28\x86\x20\x94\x4d\x78\xdb\xcd\xdb\xd9\x12\x99\x3f\x09\x13" "\xf1\x64\xfb\x2c\xe9\x51\x31\xa2\xd0"; b.inLen = XSTRLEN(b.input); - b.outLen = sizeof(hash); + b.outLen = 114; c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; c.output = "\x4d\x8c\x2d\xd2\x43\x5a\x01\x28\xee\xfb\xb8\xc3\x6f\x6f\x87" @@ -3333,11 +3419,53 @@ WOLFSSL_TEST_SUBROUTINE int shake256_test(void) "\xf2\x08\xba\xf1\x9b\xe2\x12\x33\xf3\xde\xbe\x78\xd0\x67\x60" "\xcf\xa5\x51\xee\x1e\x07\x91\x41\xd4"; c.inLen = XSTRLEN(c.input); - c.outLen = sizeof(hash); + c.outLen = 114; + + /* Taken from NIST CAVP test vectors - full rate output. */ + d.input = "\xdc\x88\x6d\xf3\xf6\x9c\x49\x51\x3d\xe3\x62\x7e\x94\x81\xdb" + "\x58\x71\xe8\xee\x88\xeb\x9f\x99\x61\x15\x41\x93\x0a\x8b\xc8" + "\x85\xe0"; + d.output = "\x00\x64\x8a\xfb\xc5\xe6\x51\x64\x9d\xb1\xfd\x82\x93\x6b\x00" + "\xdb\xbc\x12\x2f\xb4\xc8\x77\x86\x0d\x38\x5c\x49\x50\xd5\x6d" + "\xe7\xe0\x96\xd6\x13\xd7\xa3\xf2\x7e\xd8\xf2\x63\x34\xb0\xcc" + "\xc1\x40\x7b\x41\xdc\xcb\x23\xdf\xaa\x52\x98\x18\xd1\x12\x5c" + "\xd5\x34\x80\x92\x52\x43\x66\xb8\x5f\xab\xb9\x7c\x6c\xd1\xe6" + "\x06\x6f\x45\x9b\xcc\x56\x6d\xa8\x7e\xc9\xb7\xba\x36\x79\x2d" + "\x11\x8a\xc3\x9a\x4c\xce\xf6\x19\x2b\xbf\x3a\x54\xaf\x18\xe5" + "\x7b\x0c\x14\x61\x01\xf6\xae\xaa\x82\x2b\xc4\xb4\xc9\x70\x8b" + "\x09\xf0\xb3\xba\xb4\x1b\xcc\xe9\x64\xd9\x99\xd1\x10\x7b\xd7" + "\xc2"; + d.inLen = 32; + d.outLen = 136; + /* Taken from NIST CAVP test vectors - more than one output block. */ + e.input = "\x8d\x80\x01\xe2\xc0\x96\xf1\xb8\x8e\x7c\x92\x24\xa0\x86\xef" + "\xd4\x79\x7f\xbf\x74\xa8\x03\x3a\x2d\x42\x2a\x2b\x6b\x8f\x67" + "\x47\xe4"; + e.output = "\x2e\x97\x5f\x6a\x8a\x14\xf0\x70\x4d\x51\xb1\x36\x67\xd8\x19" + "\x5c\x21\x9f\x71\xe6\x34\x56\x96\xc4\x9f\xa4\xb9\xd0\x8e\x92" + "\x25\xd3\xd3\x93\x93\x42\x51\x52\xc9\x7e\x71\xdd\x24\x60\x1c" + "\x11\xab\xcf\xa0\xf1\x2f\x53\xc6\x80\xbd\x3a\xe7\x57\xb8\x13" + "\x4a\x9c\x10\xd4\x29\x61\x58\x69\x21\x7f\xdd\x58\x85\xc4\xdb" + "\x17\x49\x85\x70\x3a\x6d\x6d\xe9\x4a\x66\x7e\xac\x30\x23\x44" + "\x3a\x83\x37\xae\x1b\xc6\x01\xb7\x6d\x7d\x38\xec\x3c\x34\x46" + "\x31\x05\xf0\xd3\x94\x9d\x78\xe5\x62\xa0\x39\xe4\x46\x95\x48" + "\xb6\x09\x39\x5d\xe5\xa4\xfd\x43\xc4\x6c\xa9\xfd\x6e\xe2\x9a" + "\xda\x5e\xfc\x07\xd8\x4d\x55\x32\x49\x45\x0d\xab\x4a\x49\xc4" + "\x83\xde\xd2\x50\xc9\x33\x8f\x85\xcd\x93\x7a\xe6\x6b\xb4\x36" + "\xf3\xb4\x02\x6e\x85\x9f\xda\x1c\xa5\x71\x43\x2f\x3b\xfc\x09" + "\xe7\xc0\x3c\xa4\xd1\x83\xb7\x41\x11\x1c\xa0\x48\x3d\x0e\xda" + "\xbc\x03\xfe\xb2\x3b\x17\xee\x48\xe8\x44\xba\x24\x08\xd9\xdc" + "\xfd\x01\x39\xd2\xe8\xc7\x31\x01\x25\xae\xe8\x01\xc6\x1a\xb7" + "\x90\x0d\x1e\xfc\x47\xc0\x78\x28\x17\x66\xf3\x61\xc5\xe6\x11" + "\x13\x46\x23\x5e\x1d\xc3\x83\x25\x66\x6c"; + e.inLen = 32; + e.outLen = 250; test_sha[0] = a; test_sha[1] = b; test_sha[2] = c; + test_sha[3] = d; + test_sha[4] = e; ret = wc_InitShake256(&sha, HEAP_HINT, devId); if (ret != 0) @@ -3370,7 +3498,7 @@ WOLFSSL_TEST_SUBROUTINE int shake256_test(void) ret = wc_Shake256_Final(&sha, hash, (word32)sizeof(hash)); if (ret != 0) ERROR_OUT(-3105, exit); - if (XMEMCMP(hash, large_digest, sizeof(hash)) != 0) + if (XMEMCMP(hash, large_digest, 114) != 0) ERROR_OUT(-3106, exit); } /* END LARGE HASH TEST */ @@ -3378,13 +3506,10 @@ exit: wc_Shake256_Free(&sha); return ret; -#else - return 0; -#endif } #endif - +#ifndef NO_HASH_WRAPPER WOLFSSL_TEST_SUBROUTINE int hash_test(void) { wc_HashAlg hash; @@ -3689,6 +3814,7 @@ WOLFSSL_TEST_SUBROUTINE int hash_test(void) return 0; } +#endif /* !NO_HASH_WRAPPER */ #if !defined(NO_HMAC) && !defined(NO_MD5) WOLFSSL_TEST_SUBROUTINE int hmac_md5_test(void) @@ -4541,6 +4667,8 @@ static int rc2_ecb_test(void) h.keyLen = 33; h.effectiveKeyBits = 129; + a.iv = b.iv = c.iv = d.iv = e.iv = f.iv = g.iv = h.iv = NULL; + test_rc2[0] = a; test_rc2[1] = b; test_rc2[2] = c; @@ -4625,7 +4753,6 @@ static int rc2_cbc_test(void) /* key length = 8, effective key bits = 64 */ c.input = "\x10\x00\x00\x00\x00\x00\x00\x01" "\x10\x00\x00\x00\x00\x00\x00\x01"; - c.output = "\x30\x64\x9e\xdf\x9b\xe7\xd2\xc2"; c.output = "\xB5\x70\x14\xA2\x5F\x40\xE3\x6D" "\x81\x99\x8D\xE0\xB5\xD5\x3A\x05"; c.key = "\x30\x00\x00\x00\x00\x00\x00\x00"; @@ -6243,11 +6370,13 @@ WOLFSSL_TEST_SUBROUTINE int des_test(void) if (ret != BAD_FUNC_ARG) return -5008; - /* Test invalid hash type */ + #ifndef NO_PWDBASED + /* Test invalid hash type - only applies to wc_PBKDF1 call */ ret = wc_BufferKeyEncrypt(&info, cipher, sizeof(cipher), key, sizeof(key), WC_HASH_TYPE_NONE); if (ret == 0) return -5009; + #endif /* !NO_PWDBASED */ } #endif @@ -7621,9 +7750,11 @@ static int aes_key_size_test(void) #endif byte key16[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; +#ifndef WOLFSSL_CRYPTOCELL byte key24[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; +#endif byte key32[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, @@ -7700,7 +7831,8 @@ static int aes_key_size_test(void) if (ret != 0 || keySize != sizeof(key16)) ERROR_OUT(-5310, out); #endif - +#ifndef WOLFSSL_CRYPTOCELL +/* Cryptocell only supports AES-128 key size */ ret = wc_AesSetKey(aes, key24, sizeof(key24), iv, AES_ENCRYPTION); #ifdef WOLFSSL_AES_192 if (ret != 0) @@ -7726,7 +7858,7 @@ static int aes_key_size_test(void) if (ret != 0 || keySize != sizeof(key32)) ERROR_OUT(-5314, out); #endif - +#endif /* !WOLFSSL_CRYPTOCELL */ out: #ifdef WOLFSSL_SMALL_STACK @@ -9992,6 +10124,103 @@ WOLFSSL_TEST_SUBROUTINE int aesgcm_test(void) #endif /* WOLFSSL_AES_256 && !(WC_NO_RNG || HAVE_SELFTEST) */ #endif /* HAVE_FIPS_VERSION >= 2 */ +#if !defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT) +#ifdef WOLFSSL_AES_256 +#ifdef WOLFSSL_AESGCM_STREAM + result = wc_AesGcmEncryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1)); + if (result != 0) + ERROR_OUT(-6360, out); + result = wc_AesGcmEncryptUpdate(enc, resultC, p, sizeof(p), a, sizeof(a)); + if (result != 0) + ERROR_OUT(-6361, out); + result = wc_AesGcmEncryptFinal(enc, resultT, sizeof(resultT)); + if (result != 0) + ERROR_OUT(-6362, out); + if (XMEMCMP(resultC, c1, sizeof(c1)) != 0) + ERROR_OUT(-6363, out); + if (XMEMCMP(resultT, t1, sizeof(t1)) != 0) + ERROR_OUT(-6364, out); + +#ifdef HAVE_AES_DECRYPT + result = wc_AesGcmDecryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1)); + if (result != 0) + ERROR_OUT(-6370, out); + result = wc_AesGcmDecryptUpdate(enc, resultP, c1, sizeof(c1), a, sizeof(a)); + if (result != 0) + ERROR_OUT(-6371, out); + result = wc_AesGcmDecryptFinal(enc, t1, sizeof(t1)); + if (result != 0) + ERROR_OUT(-6372, out); + if (XMEMCMP(resultP, p, sizeof(p)) != 0) + ERROR_OUT(-6373, out); +#endif + + /* alen is the size to pass in with each update. */ + for (alen = 1; alen < AES_BLOCK_SIZE + 1; alen++) { + result = wc_AesGcmEncryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1)); + if (result != 0) + ERROR_OUT(-6380, out); + + /* plen is the offset into AAD to update with. */ + for (plen = 0; plen < (int)sizeof(a); plen += alen) { + int len = sizeof(a) - plen; + if (len > alen) len = alen; + result = wc_AesGcmEncryptUpdate(enc, NULL, NULL, 0, a + plen, len); + if (result != 0) + ERROR_OUT(-6381, out); + } + /* plen is the offset into plaintext to update with. */ + for (plen = 0; plen < (int)sizeof(p); plen += alen) { + int len = sizeof(p) - plen; + if (len > alen) len = alen; + result = wc_AesGcmEncryptUpdate(enc, resultC + plen, p + plen, len, + NULL, 0); + if (result != 0) + ERROR_OUT(-6382, out); + } + result = wc_AesGcmEncryptFinal(enc, resultT, sizeof(resultT)); + if (result != 0) + ERROR_OUT(-6383, out); + if (XMEMCMP(resultC, c1, sizeof(c1)) != 0) + ERROR_OUT(-6384, out); + if (XMEMCMP(resultT, t1, sizeof(t1)) != 0) + ERROR_OUT(-6385, out); + } + +#ifdef HAVE_AES_DECRYPT + for (alen = 1; alen < AES_BLOCK_SIZE + 1; alen++) { + result = wc_AesGcmDecryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1)); + if (result != 0) + ERROR_OUT(-6390, out); + + /* plen is the offset into AAD to update with. */ + for (plen = 0; plen < (int)sizeof(a); plen += alen) { + int len = sizeof(a) - plen; + if (len > alen) len = alen; + result = wc_AesGcmDecryptUpdate(enc, NULL, NULL, 0, a + plen, len); + if (result != 0) + ERROR_OUT(-6391, out); + } + /* plen is the offset into cipher text to update with. */ + for (plen = 0; plen < (int)sizeof(c1); plen += alen) { + int len = sizeof(c1) - plen; + if (len > alen) len = alen; + result = wc_AesGcmDecryptUpdate(enc, resultP + plen, c1 + plen, len, + NULL, 0); + if (result != 0) + ERROR_OUT(-6392, out); + } + result = wc_AesGcmDecryptFinal(enc, t1, sizeof(t1)); + if (result != 0) + ERROR_OUT(-6393, out); + if (XMEMCMP(resultP, p, sizeof(p)) != 0) + ERROR_OUT(-6394, out); + } +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AESGCM_STREAM */ +#endif /* WOLFSSL_AES_256 */ +#endif /* !WOLFSSL_AFALG_XILINX_AES && !WOLFSSL_XILINX_CRYPT */ + wc_AesFree(enc); wc_AesFree(dec); @@ -11710,6 +11939,9 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #elif defined(WOLFSSL_uTKERNEL2) #define CERT_PREFIX "/uda/" #define CERT_PATH_SEP "/" +#elif defined(_WIN32_WCE) + #define CERT_PREFIX "\\windows\\" + #define CERT_PATH_SEP "\\" #endif #ifndef CERT_PREFIX @@ -11762,6 +11994,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #if defined(WOLFSSL_DH_EXTRA) && (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) static const char* dhKeyFile = CERT_ROOT "statickeys/dh-ffdhe2048.der"; + static const char* dhKeyPubFile = CERT_ROOT "statickeys/dh-ffdhe2048-pub.der"; #endif #endif #ifndef NO_DSA @@ -11821,12 +12054,14 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) static const char* certEccRsaPemFile = CERT_WRITE_TEMP_DIR "certeccrsa.pem"; static const char* certEccRsaDerFile = CERT_WRITE_TEMP_DIR "certeccrsa.der"; #endif + #if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) static const char* eccCaKeyPemFile = CERT_WRITE_TEMP_DIR "ecc-key.pem"; static const char* eccPubKeyDerFile = CERT_WRITE_TEMP_DIR "ecc-public-key.der"; static const char* eccCaKeyTempFile = CERT_WRITE_TEMP_DIR "ecc-key.der"; - #ifdef HAVE_PKCS8 + #if defined(HAVE_PKCS8) && !defined(WC_NO_RNG) static const char* eccPkcs8KeyDerFile = CERT_WRITE_TEMP_DIR "ecc-key-pkcs8.der"; #endif + #endif /* HAVE_ECC_KEY_EXPORT */ #if defined(WOLFSSL_CERT_GEN) || \ (defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)) static const char* certEccDerFile = CERT_WRITE_TEMP_DIR "certecc.der"; @@ -13549,8 +13784,7 @@ WOLFSSL_TEST_SUBROUTINE int rsa_no_pad_test(void) #elif !defined(NO_FILESYSTEM) file = XFOPEN(clientKey, "rb"); if (!file) { - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -40); + err_sys("can't open clientKey, Please run from wolfSSL home dir", -40); ERROR_OUT(-7801, exit_rsa_nopadding); } @@ -14434,7 +14668,9 @@ static int rsa_keygen_test(WC_RNG* rng) #endif int ret; byte* der = NULL; +#ifndef WOLFSSL_CRYPTOCELL word32 idx = 0; +#endif int derSz = 0; #if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_FIPS) int keySz = 1024; @@ -14467,7 +14703,8 @@ static int rsa_keygen_test(WC_RNG* rng) #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) && \ - !defined(HAVE_SELFTEST) && !defined(HAVE_INTEL_QA) + !defined(HAVE_SELFTEST) && !defined(HAVE_INTEL_QA) \ + && !defined(WOLFSSL_NO_RSA_KEY_CHECK) ret = wc_CheckRsaKey(genKey); if (ret != 0) { ERROR_OUT(-7872, exit_rsa); @@ -14494,8 +14731,9 @@ static int rsa_keygen_test(WC_RNG* rng) if (ret != 0) { ERROR_OUT(-7875, exit_rsa); } + +#ifndef WOLFSSL_CRYPTOCELL idx = 0; -#if !defined(WOLFSSL_CRYPTOCELL) /* The private key part of the key gen pairs from cryptocell can't be exported */ ret = wc_RsaPrivateKeyDecode(der, &idx, genKey, derSz); if (ret != 0) { @@ -14549,21 +14787,12 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) RsaKey caKey[1]; #endif #endif -#if !defined(NO_ASN) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) \ - || defined(WOLFSSL_PUBLIC_MP) word32 idx = 0; -#endif -#if (!defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_PUBLIC_MP)) && \ - !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) const char inStr[] = TEST_STRING; const word32 inLen = (word32)TEST_STRING_SZ; const word32 outSz = RSA_TEST_BYTES; const word32 plainSz = RSA_TEST_BYTES; -#endif -#if (!defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ - !defined(WOLFSSL_RSA_VERIFY_ONLY)) || defined(WOLFSSL_PUBLIC_MP) - byte* res; -#endif + byte* res = NULL; #ifndef NO_SIG_WRAPPER int modLen; #endif @@ -14571,8 +14800,10 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) && \ !defined(NO_FILESYSTEM) XFILE file; +#ifdef WOLFSSL_TEST_CERT XFILE file2; #endif +#endif #ifdef WOLFSSL_TEST_CERT #ifdef WOLFSSL_SMALL_STACK DecodedCert *cert = (DecodedCert *)XMALLOC(sizeof *cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -14581,8 +14812,6 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) #endif #endif -#if (!defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_PUBLIC_MP)) && \ - !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) DECLARE_VAR(in, byte, TEST_STRING_SZ, HEAP_HINT); DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT); DECLARE_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT); @@ -14593,7 +14822,6 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) #endif XMEMCPY(in, inStr, inLen); -#endif #ifdef WOLFSSL_SMALL_STACK if (key == NULL) @@ -14728,7 +14956,8 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) goto exit_rsa; #endif -#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WC_NO_RNG) do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -14804,9 +15033,6 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) TEST_SLEEP(); #elif defined(WOLFSSL_PUBLIC_MP) - (void)outSz; - (void)inLen; - (void)res; { static byte signature_2048[] = { 0x07, 0x6f, 0xc9, 0x85, 0x73, 0x9e, 0x21, 0x79, @@ -14847,8 +15073,9 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) } #endif -#if (!defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ - !defined(WOLFSSL_RSA_VERIFY_ONLY)) || defined(WOLFSSL_PUBLIC_MP) +#if !defined(WC_NO_RNG) && !defined(WC_NO_RSA_OAEP) && \ + ((!defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_PUBLIC_MP)) idx = (word32)ret; XMEMSET(plain, 0, plainSz); do { @@ -15216,6 +15443,13 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) return ret; #endif +#if !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_ASN) && \ + !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) + (void)clientCert; +#endif + +#ifdef WOLFSSL_TEST_CERT #if defined(WOLFSSL_MDK_ARM) #define sizeof(s) XSTRLEN((char *)(s)) #endif @@ -15249,7 +15483,6 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) #undef sizeof #endif -#ifdef WOLFSSL_TEST_CERT InitDecodedCert(cert, tmp, (word32)bytes, 0); ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, 0); @@ -15259,9 +15492,7 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) } FreeDecodedCert(cert); -#else - (void)bytes; -#endif +#endif /* WOLFSSL_TEST_CERT */ #ifdef WOLFSSL_CERT_EXT @@ -15623,50 +15854,52 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void) exit_rsa: #ifdef WOLFSSL_SMALL_STACK - if (key != NULL) { wc_FreeRsaKey(key); XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } -#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) + #if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) if (keypub != NULL) { wc_FreeRsaKey(keypub); XFREE(keypub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } -#endif -#if defined(HAVE_NTRU) + #endif + #if defined(HAVE_NTRU) if (caKey != NULL) { wc_FreeRsaKey(caKey); XFREE(caKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } -#endif -#ifdef WOLFSSL_TEST_CERT + #endif + #ifdef WOLFSSL_TEST_CERT if (cert != NULL) XFREE(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); -#endif - + #endif #else - wc_FreeRsaKey(key); -#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) + #if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) wc_FreeRsaKey(keypub); -#endif -#if defined(HAVE_NTRU) + #endif + #if defined(HAVE_NTRU) wc_FreeRsaKey(caKey); -#endif - -#endif + #endif +#endif /* WOLFSSL_SMALL_STACK */ XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRng(&rng); -#if (!defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_PUBLIC_MP)) && \ - !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) FREE_VAR(in, HEAP_HINT); FREE_VAR(out, HEAP_HINT); FREE_VAR(plain, HEAP_HINT); -#endif + + (void)res; + (void)bytes; + (void)in; + (void)out; + (void)plain; + (void)inLen; + (void)outSz; + (void)plainSz; /* ret can be greater then 0 with certgen but all negative values should * be returned and treated as an error */ @@ -16045,37 +16278,43 @@ static int dh_test_check_pubvalue(void) #if defined(HAVE_FFDHE) -#ifdef HAVE_FFDHE_3072 - #define FFDHE_KEY_SIZE (3072/8) +#if defined(HAVE_FFDHE_4096) + #define MAX_DH_PRIV_SZ 39 + #define MAX_DH_KEY_SZ 512 +#elif defined(HAVE_FFDHE_3072) + #define MAX_DH_PRIV_SZ 34 + #define MAX_DH_KEY_SZ 384 #else - #define FFDHE_KEY_SIZE (2048/8) + #define MAX_DH_PRIV_SZ 29 + #define MAX_DH_KEY_SZ 256 #endif +#ifndef WC_NO_RNG static int dh_ffdhe_test(WC_RNG *rng, const DhParams* params) { int ret; word32 privSz, pubSz, privSz2, pubSz2; #ifdef WOLFSSL_SMALL_STACK - byte *priv = (byte *)XMALLOC(FFDHE_KEY_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - byte *pub = (byte *)XMALLOC(FFDHE_KEY_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - byte *priv2 = (byte *)XMALLOC(FFDHE_KEY_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - byte *pub2 = (byte *)XMALLOC(FFDHE_KEY_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - byte *agree = (byte *)XMALLOC(FFDHE_KEY_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - byte *agree2 = (byte *)XMALLOC(FFDHE_KEY_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - DhKey *key = (DhKey *)XMALLOC(sizeof *key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - DhKey *key2 = (DhKey *)XMALLOC(sizeof *key2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *priv = (byte*)XMALLOC(MAX_DH_PRIV_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *pub = (byte*)XMALLOC(MAX_DH_KEY_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *priv2 = (byte*)XMALLOC(MAX_DH_PRIV_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *pub2 = (byte*)XMALLOC(MAX_DH_KEY_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *agree = (byte*)XMALLOC(MAX_DH_KEY_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *agree2 = (byte*)XMALLOC(MAX_DH_KEY_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + DhKey *key = (DhKey*)XMALLOC(sizeof(*key), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + DhKey *key2 = (DhKey*)XMALLOC(sizeof(*key2), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #else - byte priv[FFDHE_KEY_SIZE]; - byte pub[FFDHE_KEY_SIZE]; - byte priv2[FFDHE_KEY_SIZE]; - byte pub2[FFDHE_KEY_SIZE]; - byte agree[FFDHE_KEY_SIZE]; - byte agree2[FFDHE_KEY_SIZE]; + byte priv[MAX_DH_PRIV_SZ]; + byte pub[MAX_DH_KEY_SZ]; + byte priv2[MAX_DH_PRIV_SZ]; + byte pub2[MAX_DH_KEY_SZ]; + byte agree[MAX_DH_KEY_SZ]; + byte agree2[MAX_DH_KEY_SZ]; DhKey key[1]; DhKey key2[1]; #endif - word32 agreeSz = FFDHE_KEY_SIZE; - word32 agreeSz2 = FFDHE_KEY_SIZE; + word32 agreeSz = MAX_DH_KEY_SZ; + word32 agreeSz2 = MAX_DH_KEY_SZ; #ifdef WOLFSSL_SMALL_STACK if ((priv == NULL) || @@ -16089,13 +16328,13 @@ static int dh_ffdhe_test(WC_RNG *rng, const DhParams* params) ERROR_OUT(-8050, done); #endif - pubSz = FFDHE_KEY_SIZE; - pubSz2 = FFDHE_KEY_SIZE; - privSz = FFDHE_KEY_SIZE; - privSz2 = FFDHE_KEY_SIZE; + pubSz = MAX_DH_KEY_SZ; + pubSz2 = MAX_DH_KEY_SZ; + privSz = MAX_DH_PRIV_SZ; + privSz2 = MAX_DH_PRIV_SZ; - XMEMSET(key, 0, sizeof *key); - XMEMSET(key2, 0, sizeof *key2); + XMEMSET(key, 0, sizeof(*key)); + XMEMSET(key2, 0, sizeof(*key2)); ret = wc_InitDhKey_ex(key, HEAP_HINT, devId); if (ret != 0) { @@ -16183,17 +16422,17 @@ done: #ifdef WOLFSSL_SMALL_STACK if (priv) - XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pub) - XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (priv2) - XFREE(priv2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pub2) - XFREE(pub2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (agree) - XFREE(agree, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(agree, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (agree2) - XFREE(agree2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(agree2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (key) { wc_FreeDhKey(key); XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -16209,7 +16448,7 @@ done: return ret; } - +#endif /* !WC_NO_RNG */ #endif /* HAVE_FFDHE */ WOLFSSL_TEST_SUBROUTINE int dh_test(void) @@ -16217,7 +16456,9 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) int ret; word32 bytes; word32 idx = 0, privSz, pubSz, privSz2, pubSz2; +#ifndef WC_NO_RNG WC_RNG rng; +#endif int keyInit = 0; #define DH_TEST_TMP_SIZE 1024 @@ -16226,28 +16467,34 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) #else #define DH_TEST_BUF_SIZE 512 #endif +#ifndef WC_NO_RNG word32 agreeSz = DH_TEST_BUF_SIZE; word32 agreeSz2 = DH_TEST_BUF_SIZE; +#endif #ifdef WOLFSSL_SMALL_STACK - DhKey *key = (DhKey *)XMALLOC(sizeof *key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - DhKey *key2 = (DhKey *)XMALLOC(sizeof *key2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - byte *tmp = (byte *)XMALLOC(DH_TEST_TMP_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + DhKey *key = (DhKey *)XMALLOC(sizeof *key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + DhKey *key2 = (DhKey *)XMALLOC(sizeof *key2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + byte *tmp = (byte *)XMALLOC(DH_TEST_TMP_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#else + DhKey key[1]; + DhKey key2[1]; + byte tmp[DH_TEST_TMP_SIZE]; +#endif + +#ifndef WC_NO_RNG +#ifdef WOLFSSL_SMALL_STACK byte *priv = (byte *)XMALLOC(DH_TEST_BUF_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); byte *pub = (byte *)XMALLOC(DH_TEST_BUF_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); byte *priv2 = (byte *)XMALLOC(DH_TEST_BUF_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); byte *pub2 = (byte *)XMALLOC(DH_TEST_BUF_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); byte *agree = (byte *)XMALLOC(DH_TEST_BUF_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); byte *agree2 = (byte *)XMALLOC(DH_TEST_BUF_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - - if ((tmp == NULL) || (priv == NULL) || (pub == NULL) || - (priv2 == NULL) || (pub2 == NULL) || (agree == NULL) || - (agree2 == NULL)) + if (priv == NULL || pub == NULL || priv2 == NULL || pub2 == NULL || + agree == NULL || agree2 == NULL) { ERROR_OUT(-8100, done); + } #else - DhKey key[1]; - DhKey key2[1]; - byte tmp[DH_TEST_TMP_SIZE]; byte priv[DH_TEST_BUF_SIZE]; byte pub[DH_TEST_BUF_SIZE]; byte priv2[DH_TEST_BUF_SIZE]; @@ -16255,6 +16502,13 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) byte agree[DH_TEST_BUF_SIZE]; byte agree2[DH_TEST_BUF_SIZE]; #endif +#endif /* !WC_NO_RNG */ + +#ifdef WOLFSSL_SMALL_STACK + if (key == NULL || key2 == NULL || tmp == NULL) { + ERROR_OUT(-8100, done); + } +#endif #ifdef USE_CERT_BUFFERS_1024 XMEMCPY(tmp, dh_key_der_1024, (size_t)sizeof_dh_key_der_1024); @@ -16293,7 +16547,10 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) privSz = DH_TEST_BUF_SIZE; privSz2 = DH_TEST_BUF_SIZE; +#ifndef WC_NO_RNG XMEMSET(&rng, 0, sizeof(rng)); +#endif + /* Use API for coverage. */ ret = wc_InitDhKey(key); if (ret != 0) { @@ -16334,6 +16591,7 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) } #endif +#ifndef WC_NO_RNG #ifndef HAVE_FIPS ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); #else @@ -16378,6 +16636,7 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) if (agreeSz != agreeSz2 || XMEMCMP(agree, agree2, agreeSz)) { ERROR_OUT(-8115, done); } +#endif /* !WC_NO_RNG */ #if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) if (wc_DhCheckPrivKey(NULL, NULL, 0) != BAD_FUNC_ARG) @@ -16405,82 +16664,141 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void) ERROR_OUT(-8120, done); } -#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) +#ifndef NO_ASN { + /* DH Private - Key Export / Import */ + #ifdef WOLFSSL_SMALL_STACK + byte *tmp2; + #else + byte tmp2[DH_TEST_TMP_SIZE]; + #endif XFILE file = XFOPEN(dhKeyFile, "rb"); if (!file) - ERROR_OUT(-8121, done); + ERROR_OUT(-8130, done); bytes = (word32)XFREAD(tmp, 1, DH_TEST_TMP_SIZE, file); XFCLOSE(file); - } - idx = 0; - ret = wc_DhKeyDecode(tmp, &idx, key, bytes); - if (ret != 0) { - ERROR_OUT(-8122, done); + #ifdef WOLFSSL_SMALL_STACK + tmp2 = (byte*)XMALLOC(DH_TEST_TMP_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp2 == NULL) + ERROR_OUT(-8131, done); + #endif + idx = 0; + XMEMSET(tmp2, 0, DH_TEST_TMP_SIZE); + + /* Import DH Private key as DER */ + ret = wc_DhKeyDecode(tmp, &idx, key, bytes); + if (ret == 0) { + /* Export as DER */ + idx = DH_TEST_TMP_SIZE; + ret = wc_DhPrivKeyToDer(key, tmp2, &idx); + } + + /* Verify export matches original */ + if (ret <= 0 || bytes != idx || XMEMCMP(tmp, tmp2, bytes) != 0) { + ERROR_OUT(-8132, done); + } + + + /* DH Public Key - Export / Import */ + file = XFOPEN(dhKeyPubFile, "rb"); + if (!file) + ERROR_OUT(-8133, done); + bytes = (word32)XFREAD(tmp, 1, DH_TEST_TMP_SIZE, file); + XFCLOSE(file); + + idx = 0; + XMEMSET(tmp2, 0, DH_TEST_TMP_SIZE); + + /* Import DH Public key as DER */ + ret = wc_DhKeyDecode(tmp, &idx, key, bytes); + if (ret == 0) { + /* Export as DER */ + idx = DH_TEST_TMP_SIZE; + ret = wc_DhPubKeyToDer(key, tmp2, &idx); + } + + /* Verify export matches original */ + if (ret <= 0 || bytes != idx || XMEMCMP(tmp, tmp2, bytes) != 0) { + ERROR_OUT(-8134, done); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmp2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif } #else ret = wc_DhSetKey(key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); if (ret != 0) { - ERROR_OUT(-8123, done); + ERROR_OUT(-8121, done); } -#endif - +#endif /* !NO_ASN */ privSz = DH_TEST_BUF_SIZE; pubSz = DH_TEST_BUF_SIZE; ret = wc_DhExportKeyPair(key, priv, &privSz, pub, &pubSz); if (ret != 0) { - ERROR_OUT(-8124, done); + ERROR_OUT(-8122, done); } ret = wc_DhImportKeyPair(key2, priv, privSz, pub, pubSz); if (ret != 0) { ERROR_OUT(-8125, done); } -#endif /* WOLFSSL_DH_EXTRA */ +#endif /* WOLFSSL_DH_EXTRA && !NO_FILESYSTEM && !FIPS <= 2 */ +#ifndef WC_NO_RNG ret = dh_generate_test(&rng); if (ret != 0) - ERROR_OUT(-8126, done); + ERROR_OUT(-8123, done); ret = dh_fips_generate_test(&rng); if (ret != 0) - ERROR_OUT(-8127, done); + ERROR_OUT(-8124, done); +#endif /* !WC_NO_RNG */ #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) ret = dh_test_check_pubvalue(); if (ret != 0) - ERROR_OUT(-8128, done); + ERROR_OUT(-8125, done); #endif - /* Specialized code for key gen when using FFDHE-2048 and FFDHE-3072. */ +#ifndef WC_NO_RNG + /* Specialized code for key gen when using FFDHE-2048, FFDHE-3072 and FFDHE-4096 */ #ifdef HAVE_FFDHE_2048 ret = dh_ffdhe_test(&rng, wc_Dh_ffdhe2048_Get()); if (ret != 0) - ERROR_OUT(-8129, done); + ERROR_OUT(-8126, done); #endif #ifdef HAVE_FFDHE_3072 ret = dh_ffdhe_test(&rng, wc_Dh_ffdhe3072_Get()); if (ret != 0) - ERROR_OUT(-8130, done); + ERROR_OUT(-8127, done); #endif + #ifdef HAVE_FFDHE_4096 + ret = dh_ffdhe_test(&rng, wc_Dh_ffdhe4096_Get()); + if (ret != 0) + ERROR_OUT(-8128, done); + #endif +#endif /* !WC_NO_RNG */ wc_FreeDhKey(key); keyInit = 0; #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ - !defined(WOLFSSL_OLD_PRIME_CHECK) + !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(WC_NO_RNG) /* Test Check Key */ ret = wc_DhSetCheckKey(key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g), NULL, 0, 0, &rng); if (ret != 0) - ERROR_OUT(-8131, done); + ERROR_OUT(-8129, done); keyInit = 1; /* DhSetCheckKey also initializes the key, free it */ #endif done: +#ifndef WC_NO_RNG wc_FreeRng(&rng); +#endif #ifdef WOLFSSL_SMALL_STACK if (key) { @@ -16512,6 +16830,11 @@ done: wc_FreeDhKey(key2); #endif + (void)privSz; + (void)pubSz; + (void)pubSz2; + (void)privSz2; + return ret; #undef DH_TEST_BUF_SIZE #undef DH_TEST_TMP_SIZE @@ -17796,12 +18119,14 @@ WOLFSSL_TEST_SUBROUTINE int openssl_test(void) /* test malloc / free , 10 is an arbitrary amount of memory chosen */ { byte* p; - p = (byte*)CRYPTO_malloc(10); + + p = (byte*)CRYPTO_malloc(10, "", 0); + if (p == NULL) { return -8600; } XMEMSET(p, 0, 10); - CRYPTO_free(p); + CRYPTO_free(p, "", 0); } #ifndef NO_MD5 @@ -17816,8 +18141,9 @@ WOLFSSL_TEST_SUBROUTINE int openssl_test(void) ret = EVP_DigestInit(&md_ctx, EVP_md5()); if (ret == WOLFSSL_SUCCESS) { ret = EVP_DigestUpdate(&md_ctx, a.input, (unsigned long)a.inLen); - if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + } + if (ret == WOLFSSL_SUCCESS) { + ret = EVP_DigestFinal(&md_ctx, hash, 0); } EVP_MD_CTX_cleanup(&md_ctx); if (ret != WOLFSSL_SUCCESS || @@ -20446,6 +20772,95 @@ static int ecc_test_vector(int keySize) return 0; } +#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_DETERMINISTIC_K) +static int ecc_test_deterministic_k(WC_RNG* rng) +{ + int ret; + ecc_key key; + byte sig[72]; + word32 sigSz; + unsigned char msg[] = "sample"; + unsigned char hash[32]; + const char* dIUT = + "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"; + const char* QIUTx = + "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + const char* QIUTy = + "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + const byte expSig[] = { + 0x30, 0x46, 0x02, 0x21, 0x00, 0xEF, 0xD4, 0x8B, + 0x2A, 0xAC, 0xB6, 0xA8, 0xFD, 0x11, 0x40, 0xDD, + 0x9C, 0xD4, 0x5E, 0x81, 0xD6, 0x9D, 0x2C, 0x87, + 0x7B, 0x56, 0xAA, 0xF9, 0x91, 0xC3, 0x4D, 0x0E, + 0xA8, 0x4E, 0xAF, 0x37, 0x16, 0x02, 0x21, 0x00, + 0xF7, 0xCB, 0x1C, 0x94, 0x2D, 0x65, 0x7C, 0x41, + 0xD4, 0x36, 0xC7, 0xA1, 0xB6, 0xE2, 0x9F, 0x65, + 0xF3, 0xE9, 0x00, 0xDB, 0xB9, 0xAF, 0xF4, 0x06, + 0x4D, 0xC4, 0xAB, 0x2F, 0x84, 0x3A, 0xCD, 0xA8 + }; + + ret = wc_ecc_init_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + ret = wc_ecc_import_raw(&key, QIUTx, QIUTy, dIUT, "SECP256R1"); + if (ret != 0) { + goto done; + } + + ret = wc_Hash(WC_HASH_TYPE_SHA256, msg, + (word32)XSTRLEN((const char*)msg), hash, sizeof(hash)); + if (ret != 0) { + goto done; + } + + ret = wc_ecc_set_deterministic(&key, 1); + if (ret != 0) { + goto done; + } + + sigSz = sizeof(sig); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigSz, rng, &key); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + TEST_SLEEP(); + + if (sigSz != sizeof(expSig)) { + ret = -9830; + goto done; + } + if (XMEMCMP(sig, expSig, sigSz) != 0) { + ret = -9831; + goto done; + } + + sigSz = sizeof(sig); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigSz, rng, &key); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + TEST_SLEEP(); + +done: + wc_ecc_free(&key); + return ret; +} +#endif + + #if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) static int ecc_test_sign_vectors(WC_RNG* rng) { @@ -20641,14 +21056,17 @@ static int ecc_test_make_pub(WC_RNG* rng) byte *tmp = (byte *)XMALLOC(ECC_BUFSIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #else ecc_key key[1]; -#if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) +#if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) ecc_key pub[1]; #endif byte exportBuf[ECC_BUFSIZE]; byte tmp[ECC_BUFSIZE]; #endif const byte* msg = (const byte*)"test wolfSSL ECC public gen"; - word32 x, tmpSz; +#if defined(HAVE_ECC_KEY_EXPORT) + word32 x; +#endif + word32 tmpSz; int ret = 0; ecc_point* pubPoint = NULL; #ifdef HAVE_ECC_VERIFY @@ -20759,14 +21177,16 @@ static int ecc_test_make_pub(WC_RNG* rng) #endif /* !NO_ECC256 */ /* create a new key since above test for loading key is not supported */ -#if defined(WOLFSSL_CRYPTOCELL) || defined(NO_ECC256) +#if defined(WOLFSSL_CRYPTOCELL) || defined(NO_ECC256) || \ + defined(WOLFSSL_QNX_CAAM) ret = wc_ecc_make_key(rng, ECC_KEYGEN_SIZE, key); if (ret != 0) { ERROR_OUT(-9861, done); } #endif -#ifdef HAVE_ECC_SIGN +#if defined(HAVE_ECC_SIGN) && (!defined(ECC_TIMING_RESISTANT) || \ + (defined(ECC_TIMING_RESISTANT) && !defined(WC_NO_RNG))) tmpSz = ECC_BUFSIZE; ret = 0; do { @@ -20811,7 +21231,7 @@ static int ecc_test_make_pub(WC_RNG* rng) #endif /* HAVE_ECC_SIGN */ -#if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) +#if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) /* now test private only key with creating a shared secret */ x = ECC_BUFSIZE; ret = wc_ecc_export_private_only(key, exportBuf, &x); @@ -20819,6 +21239,7 @@ static int ecc_test_make_pub(WC_RNG* rng) ERROR_OUT(-9866, done); } +#ifndef WOLFSSL_QNX_CAAM /* make private only key */ wc_ecc_free(key); wc_ecc_init_ex(key, HEAP_HINT, devId); @@ -20833,6 +21254,7 @@ static int ecc_test_make_pub(WC_RNG* rng) if (ret == 0) { ERROR_OUT(-9868, done); } +#endif /* WOLFSSL_QNX_CAAM */ /* make public key for shared secret */ wc_ecc_init_ex(pub, HEAP_HINT, devId); @@ -20867,7 +21289,7 @@ static int ecc_test_make_pub(WC_RNG* rng) ERROR_OUT(-9870, done); } TEST_SLEEP(); -#endif /* HAVE_ECC_DHE && HAVE_ECC_KEY_EXPORT */ +#endif /* HAVE_ECC_DHE && HAVE_ECC_KEY_EXPORT && !WC_NO_RNG */ ret = 0; @@ -20895,7 +21317,7 @@ done: return ret; } -#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) +#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) && !defined(WC_NO_RNG) static int ecc_test_key_decode(WC_RNG* rng, int keySize) { int ret; @@ -20976,7 +21398,7 @@ static int ecc_test_key_decode(WC_RNG* rng, int keySize) #endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ #endif /* HAVE_ECC_KEY_IMPORT */ -#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) +#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) && !defined(WC_NO_RNG) static int ecc_test_key_gen(WC_RNG* rng, int keySize) { int ret = 0; @@ -21077,7 +21499,7 @@ done: static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, int curve_id, const ecc_set_type* dp) { -#if (defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH)) && \ +#if (defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH)) && !defined(WC_NO_RNG) && \ !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) DECLARE_VAR(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT); DECLARE_VAR(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT); @@ -21087,7 +21509,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, DECLARE_VAR(exportBuf, byte, ECC_KEY_EXPORT_BUF_SIZE, HEAP_HINT); #endif word32 x = 0; -#if (defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH)) && \ +#if (defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH)) && !defined(WC_NO_RNG) && \ !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) word32 y; #endif @@ -21101,18 +21523,20 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, #endif /* HAVE_ECC_SIGN */ int ret; #ifdef WOLFSSL_SMALL_STACK - ecc_key *userA = (ecc_key *)XMALLOC(sizeof *userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER), - *userB = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER), - *pubKey = (ecc_key *)XMALLOC(sizeof *pubKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + ecc_key *userA = (ecc_key *)XMALLOC(sizeof *userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + ecc_key *userB = (ecc_key *)XMALLOC(sizeof *userB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + ecc_key *pubKey = (ecc_key *)XMALLOC(sizeof *pubKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #else - ecc_key userA[1], - userB[1], - pubKey[1]; + ecc_key userA[1]; + ecc_key userB[1]; + ecc_key pubKey[1]; #endif +#ifndef WC_NO_RNG int curveSize; +#endif #ifdef DECLARE_VAR_IS_HEAP_ALLOC -#if (defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH)) && \ +#if (defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH)) && !defined(WC_NO_RNG) && \ !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) if (sharedA == NULL || sharedB == NULL) ERROR_OUT(-9900, done); @@ -21165,6 +21589,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, } #endif +#ifndef WC_NO_RNG ret = wc_ecc_make_key_ex(rng, keySize, userA, curve_id); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userA->asyncDev, WC_ASYNC_FLAG_NONE); @@ -21282,7 +21707,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, wc_ecc_set_flags(userA, 0); wc_ecc_set_flags(userB, 0); #endif /* HAVE_ECC_CDH */ -#endif /* WOLFSSL_ATECC508A */ +#endif /* !WOLFSSL_ATECC508A && WOLFSSL_ATECC608A */ #ifdef HAVE_ECC_KEY_EXPORT x = ECC_KEY_EXPORT_BUF_SIZE; @@ -21359,15 +21784,20 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, TEST_SLEEP(); #endif /* HAVE_ECC_DHE */ #endif /* HAVE_COMP_KEY */ -#endif /* WOLFSSL_ATECC508A */ + +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A */ +#endif /* !WC_NO_RNG */ #endif /* HAVE_ECC_KEY_IMPORT */ #endif /* HAVE_ECC_KEY_EXPORT */ +#if !defined(ECC_TIMING_RESISTANT) || (defined(ECC_TIMING_RESISTANT) && !defined(WC_NO_RNG)) #ifdef HAVE_ECC_SIGN /* ECC w/out Shamir has issue with all 0 digest */ /* WC_BIGINT doesn't have 0 len well on hardware */ -#if defined(ECC_SHAMIR) && !defined(WOLFSSL_ASYNC_CRYPT) + /* Cryptocell has issues with all 0 digest */ +#if defined(ECC_SHAMIR) && !defined(WOLFSSL_ASYNC_CRYPT) && \ + !defined(WOLFSSL_CRYPTOCELL) /* test DSA sign hash with zeros */ for (i = 0; i < (int)ECC_DIGEST_SIZE; i++) { digest[i] = 0; @@ -21404,7 +21834,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, TEST_SLEEP(); } #endif /* HAVE_ECC_VERIFY */ -#endif /* ECC_SHAMIR && !WOLFSSL_ASYNC_CRYPT */ +#endif /* ECC_SHAMIR && !WOLFSSL_ASYNC_CRYPT && !WOLFSSL_CRYPTOCELL */ /* test DSA sign hash with sequence (0,1,2,3,4,...) */ for (i = 0; i < (int)ECC_DIGEST_SIZE; i++) { @@ -21443,13 +21873,16 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, } #endif /* HAVE_ECC_VERIFY */ #endif /* HAVE_ECC_SIGN */ +#endif /* !ECC_TIMING_RESISTANT || (ECC_TIMING_RESISTANT && !WC_NO_RNG) */ -#if defined(HAVE_ECC_KEY_EXPORT) && !defined(WOLFSSL_ATECC508) && \ - !defined(WOLFSSL_ATECC608A) +#if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) && \ + !defined(WOLFSSL_ATECC508) && !defined(WOLFSSL_ATECC608A) x = ECC_KEY_EXPORT_BUF_SIZE; ret = wc_ecc_export_private_only(userA, exportBuf, &x); if (ret != 0) ERROR_OUT(-9942, done); +#elif defined(HAVE_ECC_KEY_EXPORT) + (void)exportBuf; #endif /* HAVE_ECC_KEY_EXPORT */ done: @@ -21485,6 +21918,10 @@ done: FREE_VAR(digest, HEAP_HINT); #endif + (void)keySize; + (void)curve_id; + (void)rng; + return ret; } @@ -21518,7 +21955,7 @@ static int ecc_test_curve(WC_RNG* rng, int keySize) #endif #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \ - !defined(NO_ASN_CRYPT) + !defined(NO_ASN_CRYPT) && !defined(WC_NO_RNG) ret = ecc_test_key_decode(rng, keySize); if (ret < 0) { if (ret == ECC_CURVE_OID_E) { @@ -21531,7 +21968,7 @@ static int ecc_test_curve(WC_RNG* rng, int keySize) } #endif -#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) +#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) && !defined(WC_NO_RNG) ret = ecc_test_key_gen(rng, keySize); if (ret < 0) { if (ret == ECC_CURVE_OID_E) { @@ -21850,7 +22287,9 @@ static int ecc_sig_test(WC_RNG* rng, ecc_key* key) #endif #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \ - !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) + !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ + !defined(WOLFSSL_QNX_CAAM) + static int ecc_exp_imp_test(ecc_key* key) { int ret; @@ -21980,7 +22419,7 @@ done: #endif /* HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ - !defined(WOLFSSL_CRYPTOCELL) + !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_QNX_CAAM) #if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) static int ecc_mulmod_test(ecc_key* key1) { @@ -22045,7 +22484,7 @@ done: } #endif -#ifdef HAVE_ECC_DHE +#if defined(HAVE_ECC_DHE) && !defined(WC_NO_RNG) static int ecc_ssh_test(ecc_key* key, WC_RNG* rng) { int ret; @@ -22091,7 +22530,7 @@ static int ecc_ssh_test(ecc_key* key, WC_RNG* rng) TEST_SLEEP(); return 0; } -#endif /* HAVE_ECC_DHE */ +#endif /* HAVE_ECC_DHE && !WC_NO_RNG */ #endif static int ecc_def_curve_test(WC_RNG *rng) @@ -22102,6 +22541,9 @@ static int ecc_def_curve_test(WC_RNG *rng) #else ecc_key key[1]; #endif +#ifdef WC_NO_RNG + word32 idx = 0; +#endif #ifdef WOLFSSL_SMALL_STACK if (key == NULL) @@ -22122,9 +22564,16 @@ static int ecc_def_curve_test(WC_RNG *rng) goto done; } +#ifndef WC_NO_RNG ret = wc_ecc_make_key(rng, ECC_KEYGEN_SIZE, key); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); +#endif +#else + /* use test ECC key */ + ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, key, + (word32)sizeof_ecc_key_der_256); + (void)rng; #endif if (ret != 0) { ret = -10092; @@ -22138,19 +22587,20 @@ static int ecc_def_curve_test(WC_RNG *rng) goto done; #endif #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \ - !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) + !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ + !defined(WOLFSSL_QNX_CAAM) ret = ecc_exp_imp_test(key); if (ret < 0) goto done; #endif #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ - !defined(WOLFSSL_CRYPTOCELL) + !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_QNX_CAAM) #if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) ret = ecc_mulmod_test(key); if (ret < 0) goto done; #endif -#ifdef HAVE_ECC_DHE +#if defined(HAVE_ECC_DHE) && !defined(WC_NO_RNG) ret = ecc_ssh_test(key, rng); if (ret < 0) goto done; @@ -22721,16 +23171,26 @@ static int ecc_test_allocator(WC_RNG* rng) { int ret = 0; ecc_key* key; +#ifdef WC_NO_RNG + word32 idx = 0; +#endif key = wc_ecc_key_new(HEAP_HINT); if (key == NULL) { ERROR_OUT(-10150, exit); } +#ifndef WC_NO_RNG ret = wc_ecc_make_key(rng, ECC_KEYGEN_SIZE, key); if (ret != 0) { ERROR_OUT(-10151, exit); } +#else + /* use test ECC key */ + ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, key, + (word32)sizeof_ecc_key_der_256); + (void)rng; +#endif exit: wc_ecc_key_free(key); @@ -23029,7 +23489,7 @@ static int crypto_ecc_verify(const uint8_t *key, uint32_t keySz, ); count++; - /* TODO: Real-time work can be called here */ + /* This is where real-time work could be called */ } while (ret == FP_WOULDBLOCK); #ifdef DEBUG_WOLFSSL printf("ECC non-block verify: %d times\n", count); @@ -23113,7 +23573,7 @@ static int crypto_ecc_sign(const uint8_t *key, uint32_t keySz, ); count++; - /* TODO: Real-time work can be called here */ + /* This is where real-time work could be called */ } while (ret == FP_WOULDBLOCK); #ifdef DEBUG_WOLFSSL @@ -23123,8 +23583,8 @@ static int crypto_ecc_sign(const uint8_t *key, uint32_t keySz, if (ret == 0) { /* export r/s */ - mp_to_unsigned_bin(&r, sig); - mp_to_unsigned_bin(&s, sig + curveSz); + mp_to_unsigned_bin_len(&r, sig, curveSz); + mp_to_unsigned_bin_len(&s, sig + curveSz, curveSz); } mp_clear(&r); @@ -23197,6 +23657,8 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test(void) #ifndef WC_NO_RNG if (ret != 0) return -10300; +#else + (void)ret; #endif #if (defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 112 @@ -23285,6 +23747,14 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test(void) } #endif +#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_DETERMINISTIC_K) + ret = ecc_test_deterministic_k(&rng); + if (ret != 0) { + printf("ecc_test_deterministic_k failed! %d\n", ret); + goto done; + } +#endif + #if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) ret = ecc_test_sign_vectors(&rng); if (ret != 0) { @@ -23591,6 +24061,7 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) if (ret != 0) ERROR_OUT(-10423, done); +#ifndef WC_NO_RNG #ifndef HAVE_FIPS ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); #else @@ -23607,6 +24078,7 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test_buffers(void) ERROR_OUT(-10425, done); } #endif +#endif /* !WC_NO_RNG */ #if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_HKDF) { @@ -26138,7 +26610,7 @@ WOLFSSL_TEST_SUBROUTINE int ed448_test(void) WOLFSSL_SMALL_STACK_STATIC const byte* sigs[] = {sig1, sig2, sig3, sig4, sig5, sig6}; #define SIGSZ sizeof(sig1) - WOLFSSL_SMALL_STACK_STATIC const byte msg1[] = { }; + PEDANTIC_EXTENSION WOLFSSL_SMALL_STACK_STATIC const byte msg1[] = { }; WOLFSSL_SMALL_STACK_STATIC const byte msg2[] = { 0x03 }; WOLFSSL_SMALL_STACK_STATIC const byte msg3[] = { 0x64, 0xa6, 0x5f, 0x3c, 0xde, 0xdc, 0xdd, 0x66, 0x81, 0x1e, 0x29, 0x15 }; @@ -26502,6 +26974,2128 @@ WOLFSSL_TEST_SUBROUTINE int ed448_test(void) } #endif /* HAVE_ED448 */ +#ifdef WOLFCRYPT_HAVE_ECCSI +static int eccsi_api_test(WC_RNG* rng, EccsiKey* key, mp_int* ssk, + ecc_point* pvt) +{ + int ret; + byte id[1] = { 0x00 }; + int valid; + word32 sz; + byte data[256]; + byte hash[WC_MAX_DIGEST_SIZE]; + byte hashSz; + byte sig[257]; + word32 sigSz; + + ret = wc_InitEccsiKey_ex(NULL, 32, ECC_SECP256R1, HEAP_HINT, INVALID_DEVID); + if (ret != BAD_FUNC_ARG) + return -10023; + ret = wc_InitEccsiKey_ex(NULL, 32, ECC_SECP256R1, HEAP_HINT, INVALID_DEVID); + if (ret != BAD_FUNC_ARG) + return -10024; + + ret = wc_InitEccsiKey(NULL, NULL, INVALID_DEVID); + if (ret != BAD_FUNC_ARG) + return -10025; + ret = wc_InitEccsiKey(NULL, HEAP_HINT, INVALID_DEVID); + if (ret != BAD_FUNC_ARG) + return -10026; + + wc_FreeEccsiKey(NULL); + + /* Create a valid key. */ + ret = wc_InitEccsiKey(key, NULL, INVALID_DEVID); + if (ret != 0) + return -10027; + + ret = wc_MakeEccsiKey(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10028; + ret = wc_MakeEccsiKey(key, NULL); + if (ret != BAD_FUNC_ARG) + return -10029; + ret = wc_MakeEccsiKey(NULL, rng); + if (ret != BAD_FUNC_ARG) + return -10030; + + ret = wc_MakeEccsiPair(NULL, NULL, WC_HASH_TYPE_SHA256, NULL, 1, NULL, + NULL); + if (ret != BAD_FUNC_ARG) + return -10031; + ret = wc_MakeEccsiPair(key, rng, WC_HASH_TYPE_SHA256, id, 1, ssk, NULL); + if (ret != BAD_FUNC_ARG) + return -10032; + ret = wc_MakeEccsiPair(key, rng, WC_HASH_TYPE_SHA256, id, 1, NULL, pvt); + if (ret != BAD_FUNC_ARG) + return -10033; + ret = wc_MakeEccsiPair(key, rng, WC_HASH_TYPE_SHA256, NULL, 1, ssk, pvt); + if (ret != BAD_FUNC_ARG) + return -10034; + ret = wc_MakeEccsiPair(key, NULL, WC_HASH_TYPE_SHA256, id, 1, ssk, pvt); + if (ret != BAD_FUNC_ARG) + return -10035; + ret = wc_MakeEccsiPair(NULL, rng, WC_HASH_TYPE_SHA256, id, 1, ssk, pvt); + if (ret != BAD_FUNC_ARG) + return -10036; + /* No key set */ + ret = wc_MakeEccsiPair(key, rng, WC_HASH_TYPE_SHA256, id, 1, ssk, pvt); + if (ret != BAD_STATE_E) + return -10037; + + ret = wc_ValidateEccsiPair(NULL, WC_HASH_TYPE_SHA256, NULL, 1, NULL, NULL, + NULL); + if (ret != BAD_FUNC_ARG) + return -10038; + ret = wc_ValidateEccsiPair(key, WC_HASH_TYPE_SHA256, id, 1, ssk, pvt, + NULL); + if (ret != BAD_FUNC_ARG) + return -10039; + ret = wc_ValidateEccsiPair(key, WC_HASH_TYPE_SHA256, id, 1, ssk, NULL, + &valid); + if (ret != BAD_FUNC_ARG) + return -10040; + ret = wc_ValidateEccsiPair(key, WC_HASH_TYPE_SHA256, id, 1, NULL, pvt, + &valid); + if (ret != BAD_FUNC_ARG) + return -10041; + ret = wc_ValidateEccsiPair(key, WC_HASH_TYPE_SHA256, NULL, 1, ssk, pvt, + &valid); + if (ret != BAD_FUNC_ARG) + return -10042; + ret = wc_ValidateEccsiPair(NULL, WC_HASH_TYPE_SHA256, id, 1, ssk, pvt, + &valid); + if (ret != BAD_FUNC_ARG) + return -10043; + /* No key set */ + ret = wc_ValidateEccsiPair(key, WC_HASH_TYPE_SHA256, id, 1, ssk, pvt, + &valid); + if (ret != BAD_STATE_E) + return -10044; + + ret = wc_ValidateEccsiPvt(NULL, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10045; + ret = wc_ValidateEccsiPvt(key, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10046; + ret = wc_ValidateEccsiPvt(NULL, pvt, NULL); + if (ret != BAD_FUNC_ARG) + return -10047; + ret = wc_ValidateEccsiPvt(NULL, NULL, &valid); + if (ret != BAD_FUNC_ARG) + return -10048; + ret = wc_ValidateEccsiPvt(key, pvt, NULL); + if (ret != BAD_FUNC_ARG) + return -10049; + ret = wc_ValidateEccsiPvt(key, NULL, &valid); + if (ret != BAD_FUNC_ARG) + return -10050; + ret = wc_ValidateEccsiPvt(NULL, pvt, &valid); + if (ret != BAD_FUNC_ARG) + return -10051; + ret = wc_EncodeEccsiPair(NULL, NULL, NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10052; + ret = wc_EncodeEccsiPair(key, ssk, pvt, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10053; + ret = wc_EncodeEccsiPair(key, ssk, NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10054; + ret = wc_EncodeEccsiPair(key, NULL, pvt, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10055; + ret = wc_EncodeEccsiPair(NULL, ssk, pvt, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10056; + /* No key created so no curve information. */ + ret = wc_EncodeEccsiPair(key, ssk, pvt, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10057; + + ret = wc_EncodeEccsiSsk(NULL, NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10058; + ret = wc_EncodeEccsiSsk(key, ssk, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10059; + ret = wc_EncodeEccsiSsk(key, NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10060; + ret = wc_EncodeEccsiSsk(NULL, ssk, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10061; + + ret = wc_EncodeEccsiPvt(NULL, NULL, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10058; + ret = wc_EncodeEccsiPvt(key, pvt, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10059; + ret = wc_EncodeEccsiPvt(key, NULL, data, &sz, 1); + if (ret != BAD_FUNC_ARG) + return -10060; + ret = wc_EncodeEccsiPvt(NULL, pvt, data, &sz, 1); + if (ret != BAD_FUNC_ARG) + return -10061; + + ret = wc_DecodeEccsiPair(NULL, NULL, 0, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10062; + ret = wc_DecodeEccsiPair(key, data, 0, ssk, NULL); + if (ret != BAD_FUNC_ARG) + return -10063; + ret = wc_DecodeEccsiPair(key, data, 0, NULL, pvt); + if (ret != BAD_FUNC_ARG) + return -10064; + ret = wc_DecodeEccsiPair(key, NULL, 0, ssk, pvt); + if (ret != BAD_FUNC_ARG) + return -10065; + ret = wc_DecodeEccsiPair(NULL, data, 0, ssk, pvt); + if (ret != BAD_FUNC_ARG) + return -10066; + + ret = wc_DecodeEccsiSsk(NULL, NULL, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10067; + ret = wc_DecodeEccsiSsk(key, data, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10068; + ret = wc_DecodeEccsiSsk(key, NULL, 0, ssk); + if (ret != BAD_FUNC_ARG) + return -10069; + ret = wc_DecodeEccsiSsk(NULL, data, 0, ssk); + if (ret != BAD_FUNC_ARG) + return -10070; + ret = wc_DecodeEccsiPvt(NULL, NULL, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10067; + ret = wc_DecodeEccsiPvt(key, data, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10068; + ret = wc_DecodeEccsiPvt(key, NULL, 0, pvt); + if (ret != BAD_FUNC_ARG) + return -10069; + ret = wc_DecodeEccsiPvt(NULL, data, 0, pvt); + if (ret != BAD_FUNC_ARG) + return -10070; + + ret = wc_DecodeEccsiPvtFromSig(NULL, NULL, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10067; + ret = wc_DecodeEccsiPvtFromSig(key, data, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10068; + ret = wc_DecodeEccsiPvtFromSig(key, NULL, 0, pvt); + if (ret != BAD_FUNC_ARG) + return -10069; + ret = wc_DecodeEccsiPvtFromSig(NULL, data, 0, pvt); + if (ret != BAD_FUNC_ARG) + return -10070; + + ret = wc_ExportEccsiKey(NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10071; + ret = wc_ExportEccsiKey(key, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10072; + ret = wc_ExportEccsiKey(NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10073; + /* No key to export */ + ret = wc_ExportEccsiKey(key, NULL, &sz); + if (ret != BAD_STATE_E) + return -10074; + + ret = wc_ImportEccsiKey(NULL, NULL, 0); + if (ret != BAD_FUNC_ARG) + return -10075; + ret = wc_ImportEccsiKey(key, NULL, 0); + if (ret != BAD_FUNC_ARG) + return -10076; + ret = wc_ImportEccsiKey(NULL, data, 0); + if (ret != BAD_FUNC_ARG) + return -10077; + + ret = wc_ExportEccsiPrivateKey(NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10071; + ret = wc_ExportEccsiPrivateKey(key, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10072; + ret = wc_ExportEccsiPrivateKey(NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10073; + /* No key to export */ + ret = wc_ExportEccsiPrivateKey(key, NULL, &sz); + if (ret != BAD_STATE_E) + return -10074; + + ret = wc_ImportEccsiPrivateKey(NULL, NULL, 0); + if (ret != BAD_FUNC_ARG) + return -10075; + ret = wc_ImportEccsiPrivateKey(key, NULL, 0); + if (ret != BAD_FUNC_ARG) + return -10076; + ret = wc_ImportEccsiPrivateKey(NULL, data, 0); + if (ret != BAD_FUNC_ARG) + return -10077; + ret = wc_ExportEccsiPublicKey(NULL, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10078; + ret = wc_ExportEccsiPublicKey(key, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10079; + ret = wc_ExportEccsiPublicKey(NULL, data, &sz, 1); + if (ret != BAD_FUNC_ARG) + return -10080; + /* No key to export */ + ret = wc_ExportEccsiPublicKey(key, data, &sz, 1); + if (ret != BAD_STATE_E) + return -10081; + + ret = wc_ImportEccsiPublicKey(NULL, NULL, 0, 1); + if (ret != BAD_FUNC_ARG) + return -10082; + ret = wc_ImportEccsiPublicKey(key, NULL, 0, 1); + if (ret != BAD_FUNC_ARG) + return -10083; + ret = wc_ImportEccsiPublicKey(NULL, data, 0, 1); + if (ret != BAD_FUNC_ARG) + return -10084; + + ret = wc_HashEccsiId(NULL, WC_HASH_TYPE_SHA256, NULL, 1, NULL, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10085; + ret = wc_HashEccsiId(key, WC_HASH_TYPE_SHA256, id, 1, pvt, hash, NULL); + if (ret != BAD_FUNC_ARG) + return -10086; + ret = wc_HashEccsiId(key, WC_HASH_TYPE_SHA256, id, 1, pvt, NULL, &hashSz); + if (ret != BAD_FUNC_ARG) + return -10087; + ret = wc_HashEccsiId(key, WC_HASH_TYPE_SHA256, id, 1, NULL, hash, &hashSz); + if (ret != BAD_FUNC_ARG) + return -10088; + ret = wc_HashEccsiId(key, WC_HASH_TYPE_SHA256, NULL, 1, pvt, hash, + &hashSz); + if (ret != BAD_FUNC_ARG) + return -10089; + ret = wc_HashEccsiId(NULL, WC_HASH_TYPE_SHA256, id, 1, pvt, hash, &hashSz); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_HashEccsiId(key, WC_HASH_TYPE_SHA256, id, 1, pvt, hash, &hashSz); + if (ret != BAD_STATE_E) + return -10091; + + ret = wc_SetEccsiHash(NULL, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiHash(key, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiHash(NULL, hash, 1); + if (ret != BAD_FUNC_ARG) + return -10090; + + ret = wc_SetEccsiPair(NULL, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiPair(key, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiPair(NULL, ssk, NULL); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiPair(NULL, NULL, pvt); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiPair(key, ssk, NULL); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiPair(key, NULL, pvt); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SetEccsiPair(NULL, ssk, pvt); + if (ret != BAD_FUNC_ARG) + return -10090; + ret = wc_SignEccsiHash(NULL, NULL, WC_HASH_TYPE_SHA256, NULL, 0, sig, NULL); + if (ret != BAD_FUNC_ARG) + return -10092; + ret = wc_SignEccsiHash(key, rng, WC_HASH_TYPE_SHA256, data, 0, sig, NULL); + if (ret != BAD_FUNC_ARG) + return -10093; + ret = wc_SignEccsiHash(key, rng, WC_HASH_TYPE_SHA256, NULL, 0, sig, + &sigSz); + if (ret != BAD_FUNC_ARG) + return -10096; + ret = wc_SignEccsiHash(key, NULL, WC_HASH_TYPE_SHA256, data, 0, sig, + &sigSz); + if (ret != BAD_FUNC_ARG) + return -10098; + ret = wc_SignEccsiHash(NULL, rng, WC_HASH_TYPE_SHA256, data, 0, sig, + &sigSz); + if (ret != BAD_FUNC_ARG) + return -10099; + /* Key not set. */ + ret = wc_SignEccsiHash(key, rng, WC_HASH_TYPE_SHA256, data, 0, NULL, + &sigSz); + if (ret != BAD_STATE_E) + return -10100; + + ret = wc_VerifyEccsiHash(NULL, WC_HASH_TYPE_SHA256, NULL, 0, NULL, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10101; + ret = wc_VerifyEccsiHash(key, WC_HASH_TYPE_SHA256, NULL, 0, NULL, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10101; + ret = wc_VerifyEccsiHash(NULL, WC_HASH_TYPE_SHA256, data, 0, NULL, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10101; + ret = wc_VerifyEccsiHash(NULL, WC_HASH_TYPE_SHA256, NULL, 0, sig, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10101; + ret = wc_VerifyEccsiHash(NULL, WC_HASH_TYPE_SHA256, NULL, 0, NULL, 0, + &valid); + if (ret != BAD_FUNC_ARG) + return -10101; + ret = wc_VerifyEccsiHash(key, WC_HASH_TYPE_SHA256, data, 0, sig, 0, NULL); + if (ret != BAD_FUNC_ARG) + return -10102; + ret = wc_VerifyEccsiHash(key, WC_HASH_TYPE_SHA256, data, 0, NULL, 0, + &valid); + if (ret != BAD_FUNC_ARG) + return -10103; + ret = wc_VerifyEccsiHash(key, WC_HASH_TYPE_SHA256, NULL, 0, sig, 0, + &valid); + if (ret != BAD_FUNC_ARG) + return -10104; + ret = wc_VerifyEccsiHash(NULL, WC_HASH_TYPE_SHA256, data, 0, sig, 0, + &valid); + if (ret != BAD_FUNC_ARG) + return -10106; + ret = wc_VerifyEccsiHash(key, WC_HASH_TYPE_SHA256, data, 0, sig, 0, + &valid); + if (ret != BAD_STATE_E) + return -10106; + + ret = wc_SetEccsiPair(key, ssk, pvt); + if (ret != 0) + return -10107; + /* Identity hash not set. */ + ret = wc_SignEccsiHash(key, rng, WC_HASH_TYPE_SHA256, data, 0, NULL, + &sigSz); + if (ret != BAD_STATE_E) + return -10108; + + wc_FreeEccsiKey(key); + + return 0; +} + +/* RFC 6507: Appendix A */ +static int eccsi_kat_verify_test(EccsiKey* key, ecc_point* pvt) +{ + int ret; + int verified; + const byte msg[] = { 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00 }; + word32 msgSz = sizeof(msg); + byte hash[WC_SHA256_DIGEST_SIZE]; + byte hashSz = WC_SHA256_DIGEST_SIZE; + static const byte id[] = { + 0x32, 0x30, 0x31, 0x31, 0x2D, 0x30, 0x32, 0x00, + 0x74, 0x65, 0x6C, 0x3A, 0x2B, 0x34, 0x34, 0x37, + 0x37, 0x30, 0x30, 0x39, 0x30, 0x30, 0x31, 0x32, + 0x33, 0x00 + }; + word32 idSz = sizeof(id); + static const byte sig[] = { + 0x26, 0x9D, 0x4C, 0x8F, 0xDE, 0xB6, 0x6A, 0x74, + 0xE4, 0xEF, 0x8C, 0x0D, 0x5D, 0xCC, 0x59, 0x7D, + 0xDF, 0xE6, 0x02, 0x9C, 0x2A, 0xFF, 0xC4, 0x93, + 0x60, 0x08, 0xCD, 0x2C, 0xC1, 0x04, 0x5D, 0x81, + 0xE0, 0x9B, 0x52, 0x8D, 0x0E, 0xF8, 0xD6, 0xDF, + 0x1A, 0xA3, 0xEC, 0xBF, 0x80, 0x11, 0x0C, 0xFC, + 0xEC, 0x9F, 0xC6, 0x82, 0x52, 0xCE, 0xBB, 0x67, + 0x9F, 0x41, 0x34, 0x84, 0x69, 0x40, 0xCC, 0xFD, + 0x04, + 0x75, 0x8A, 0x14, 0x27, 0x79, 0xBE, 0x89, 0xE8, + 0x29, 0xE7, 0x19, 0x84, 0xCB, 0x40, 0xEF, 0x75, + 0x8C, 0xC4, 0xAD, 0x77, 0x5F, 0xC5, 0xB9, 0xA3, + 0xE1, 0xC8, 0xED, 0x52, 0xF6, 0xFA, 0x36, 0xD9, + 0xA7, 0x9D, 0x24, 0x76, 0x92, 0xF4, 0xED, 0xA3, + 0xA6, 0xBD, 0xAB, 0x77, 0xD6, 0xAA, 0x64, 0x74, + 0xA4, 0x64, 0xAE, 0x49, 0x34, 0x66, 0x3C, 0x52, + 0x65, 0xBA, 0x70, 0x18, 0xBA, 0x09, 0x1F, 0x79 + }; + word32 sigSz = sizeof(sig); + static const byte pubData[] = { + 0x50, 0xD4, 0x67, 0x0B, 0xDE, 0x75, 0x24, 0x4F, + 0x28, 0xD2, 0x83, 0x8A, 0x0D, 0x25, 0x55, 0x8A, + 0x7A, 0x72, 0x68, 0x6D, 0x45, 0x22, 0xD4, 0xC8, + 0x27, 0x3F, 0xB6, 0x44, 0x2A, 0xEB, 0xFA, 0x93, + 0xDB, 0xDD, 0x37, 0x55, 0x1A, 0xFD, 0x26, 0x3B, + 0x5D, 0xFD, 0x61, 0x7F, 0x39, 0x60, 0xC6, 0x5A, + 0x8C, 0x29, 0x88, 0x50, 0xFF, 0x99, 0xF2, 0x03, + 0x66, 0xDC, 0xE7, 0xD4, 0x36, 0x72, 0x17, 0xF4 + }; + static const byte expHash[] = { + 0x49, 0x0f, 0x3f, 0xeb, 0xbc, 0x1c, 0x90, 0x2f, + 0x62, 0x89, 0x72, 0x3d, 0x7f, 0x8c, 0xbf, 0x79, + 0xdb, 0x88, 0x93, 0x08, 0x49, 0xd1, 0x9f, 0x38, + 0xf0, 0x29, 0x5b, 0x5c, 0x27, 0x6c, 0x14, 0xd1 + }; + + ret = wc_ImportEccsiPublicKey(key, pubData, sizeof(pubData), 0); + if (ret != 0) + return -10108; + + ret = wc_DecodeEccsiPvtFromSig(key, sig, sigSz, pvt); + if (ret != 0) + return -10109; + + ret = wc_HashEccsiId(key, WC_HASH_TYPE_SHA256, id, idSz, pvt, hash, + &hashSz); + if (ret != 0) + return -10112; + if (hashSz != sizeof(expHash)) + return -10113; + if (XMEMCMP(hash, expHash, hashSz) != 0) + return -10114; + + ret = wc_SetEccsiHash(key, hash, hashSz); + if (ret != 0) + return -10112; + + ret = wc_VerifyEccsiHash(key, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10115; + if (!verified) + return -10116; + + return 0; +} +static int eccsi_enc_dec_pair_test(EccsiKey* priv, mp_int* ssk, ecc_point* pvt) +{ + int ret; + byte data[32 * 3]; + word32 sz; + mp_int decSsk; + ecc_point* decPvt = NULL; + + ret = mp_init(&decSsk); + if (ret != 0) + return -10117; + + decPvt = wc_ecc_new_point(); + if (decPvt == NULL) + return -10118; + + ret = wc_EncodeEccsiPair(priv, ssk, pvt, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10119; + if (sz != 32 * 3) + return -10120; + ret = wc_EncodeEccsiPair(priv, ssk, pvt, data, &sz); + if (ret != 0) + return -10121; + if (sz != 32* 3) + return -10122; + ret = wc_DecodeEccsiPair(priv, data, sz, &decSsk, decPvt); + if (ret != 0) + return -10123; + if (mp_cmp(ssk, &decSsk) != MP_EQ) + return -10124; + if (wc_ecc_cmp_point(pvt, decPvt) != MP_EQ) + return -10125; + + ret = wc_EncodeEccsiSsk(priv, ssk, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10119; + if (sz != 32) + return -10120; + ret = wc_EncodeEccsiSsk(priv, ssk, data, &sz); + if (ret != 0) + return -10121; + if (sz != 32) + return -10122; + ret = wc_DecodeEccsiSsk(priv, data, sz, &decSsk); + if (ret != 0) + return -10123; + if (mp_cmp(ssk, &decSsk) != MP_EQ) + return -10124; + + ret = wc_EncodeEccsiPvt(priv, pvt, NULL, &sz, 1); + if (ret != LENGTH_ONLY_E) + return -10126; + if (sz != 32 * 2) + return -10127; + ret = wc_EncodeEccsiPvt(priv, pvt, data, &sz, 1); + if (ret != 0) + return -10128; + if (sz != 32 * 2) + return -10129; + ret = wc_DecodeEccsiPvt(priv, data, sz, decPvt); + if (ret != 0) + return -10130; + if (wc_ecc_cmp_point(pvt, decPvt) != MP_EQ) + return -10131; + sz = sizeof(data); + ret = wc_EncodeEccsiPvt(priv, pvt, data, &sz, 0); + if (ret != 0) + return -10128; + if (sz != 32 * 2 + 1) + return -10129; + ret = wc_DecodeEccsiPvt(priv, data, sz, decPvt); + if (ret != 0) + return -10130; + if (wc_ecc_cmp_point(pvt, decPvt) != MP_EQ) + return -10131; + + wc_ecc_del_point(decPvt); + mp_free(&decSsk); + + return 0; +} + +static int eccsi_imp_exp_key_test(EccsiKey* priv) +{ + int ret; + byte data[32 * 3]; + byte out[32 * 3]; + word32 sz; + + ret = wc_ExportEccsiKey(priv, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10132; + if (sz != 32 * 3) + return -10133; + ret = wc_ExportEccsiKey(priv, data, &sz); + if (ret != 0) + return -10134; + ret = wc_ImportEccsiKey(priv, data, sz); + if (ret != 0) + return -10135; + ret = wc_ExportEccsiKey(priv, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10132; + if (sz != 32 * 3) + return -10143; + ret = wc_ExportEccsiKey(priv, out, &sz); + if (ret != 0) + return -10144; + if (sz != 32 * 3) + return -10145; + if (XMEMCMP(data, out, sz) != 0) + return -10146; + + ret = wc_ExportEccsiPrivateKey(priv, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10156; + if (sz != 32) + return -10157; + ret = wc_ExportEccsiPrivateKey(priv, data, &sz); + if (ret != 0) + return -10158; + ret = wc_ImportEccsiPrivateKey(priv, data, sz); + if (ret != 0) + return -10159; + ret = wc_ExportEccsiPrivateKey(priv, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10152; + if (sz != 32) + return -10163; + ret = wc_ExportEccsiPrivateKey(priv, out, &sz); + if (ret != 0) + return -10164; + if (sz != 32) + return -10165; + if (XMEMCMP(data, out, sz) != 0) + return -10166; + + return 0; +} + +static int eccsi_imp_exp_pubkey_test(EccsiKey* key1, EccsiKey* key2) +{ + int ret; + byte data[32 * 2 + 1]; + byte pubData[32 * 2 + 1]; + word32 sz; + + ret = wc_ExportEccsiPublicKey(key1, NULL, &sz, 1); + if (ret != LENGTH_ONLY_E) + return -10136; + if (sz != 32 * 2) + return -10137; + + ret = wc_ExportEccsiPublicKey(key1, data, &sz, 1); + if (ret != 0) + return -10138; + + ret = wc_ImportEccsiPublicKey(key2, data, sz, 1); + if (ret != 0) + return -10139; + sz = sizeof(pubData); + ret = wc_ExportEccsiPublicKey(key2, pubData, &sz, 1); + if (ret != 0) + return -10140; + if (sz != 32 * 2) + return -10141; + if (XMEMCMP(data, pubData, sz) != 0) + return -10142; + + sz = sizeof(pubData); + ret = wc_ExportEccsiPublicKey(key2, pubData, &sz, 0); + if (ret != 0) + return -10140; + if (sz != 32 * 2 + 1) + return -10141; + if (pubData[0] != 0x04) + return -10140; + if (XMEMCMP(pubData + 1, data, sz - 1) != 0) + return -10142; + ret = wc_ImportEccsiPublicKey(key2, pubData, sz, 0); + if (ret != 0) + return -10139; + + return 0; +} + +static int eccsi_make_key_test(EccsiKey* priv, EccsiKey* pub, WC_RNG* rng, + mp_int* ssk, ecc_point* pvt) +{ + int ret; + char mail[] = "test@wolfssl.com"; + byte* id = (byte*)mail; + word32 idSz = (word32) XSTRLEN(mail); + int valid; + + ret = wc_MakeEccsiKey(priv, rng); + if (ret != 0) + return -10143; + + ret = eccsi_imp_exp_key_test(priv); + if (ret < 0) + return ret; + + ret = eccsi_imp_exp_pubkey_test(priv, pub); + if (ret < 0) + return ret; + + ret = wc_MakeEccsiPair(priv, rng, WC_HASH_TYPE_SHA256, id, idSz, ssk, pvt); + if (ret != 0) + return -10144; + + ret = wc_ValidateEccsiPair(pub, WC_HASH_TYPE_SHA256, id, idSz, ssk, pvt, + &valid); + if (ret != 0) + return -10145; + if (!valid) + return -10146; + + ret = eccsi_enc_dec_pair_test(priv, ssk, pvt); + if (ret != 0) + return ret; + + return 0; +} + +static int eccsi_sign_verify_test(EccsiKey* priv, EccsiKey* pub, WC_RNG* rng, + mp_int* ssk, ecc_point* pvt) +{ + int ret; + byte hashPriv[WC_MAX_DIGEST_SIZE]; + byte hashPub[WC_MAX_DIGEST_SIZE]; + byte hashSz; + byte sig[144]; + word32 sigSz; + int verified, valid; + char mail[] = "test@wolfssl.com"; + byte* id = (byte*)mail; + word32 idSz = (word32) XSTRLEN(mail); + byte msg[] = { 0x00 }; + word32 msgSz = sizeof(msg); + + ret = wc_HashEccsiId(priv, WC_HASH_TYPE_SHA256, id, idSz, pvt, hashPriv, + &hashSz); + if (ret != 0) + return -10147; + if (hashSz != 32) + return -10148; + ret = wc_HashEccsiId(priv, WC_HASH_TYPE_SHA256, id, idSz, pvt, hashPub, + &hashSz); + if (ret != 0) + return -10149; + if (hashSz != 32) + return -10150; + + if (XMEMCMP(hashPriv, hashPub, hashSz) != 0) + return -10151; + + ret = wc_SetEccsiHash(priv, hashPriv, hashSz); + if (ret != 0) + return -10149; + ret = wc_SetEccsiPair(priv, ssk, pvt); + if (ret != 0) + return -10149; + + ret = wc_SignEccsiHash(priv, rng, WC_HASH_TYPE_SHA256, msg, msgSz, NULL, + &sigSz); + if (ret != LENGTH_ONLY_E) + return -10152; + if (sigSz != 129) + return -10153; + ret = wc_SignEccsiHash(priv, rng, WC_HASH_TYPE_SHA256, msg, msgSz, sig, + &sigSz); + if (ret != 0) + return -10154; + + ret = wc_SetEccsiHash(pub, hashPub, hashSz); + if (ret != 0) + return -10149; + + ret = wc_VerifyEccsiHash(pub, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10155; + if (!verified) + return -10156; + + /* Check that changing HS results in verification failure. */ + hashPub[0] ^= 0x80; + ret = wc_SetEccsiHash(pub, hashPub, hashSz); + if (ret != 0) + return -10149; + ret = wc_VerifyEccsiHash(pub, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10157; + if (verified) + return -10158; + hashPub[0] ^= 0x80; + ret = wc_SetEccsiHash(pub, hashPub, hashSz); + if (ret != 0) + return -10149; + + /* Check that changing msg results in verification failure. */ + msg[0] ^= 0x80; + ret = wc_VerifyEccsiHash(pub, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10159; + if (verified) + return -10160; + msg[0] ^= 0x80; + /* Check that changing signature results in verification failure. */ + sig[0] ^= 0x80; + ret = wc_VerifyEccsiHash(pub, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10161; + if (verified) + return -10162; + sig[0] ^= 0x80; + + /* Check that key state hasn't been invalidated. */ + ret = wc_VerifyEccsiHash(pub, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10163; + if (!verified) + return -10164; + + /* Check that verifying with the private key works. */ + ret = wc_VerifyEccsiHash(priv, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10165; + if (!verified) + return -10166; + + /* Check that the KPAK is converted from montogmery form. */ + ret = eccsi_imp_exp_key_test(priv); + if (ret != 0) + return ret; + + /* Check that KPAK can converted to Montogmery form again. */ + ret = wc_VerifyEccsiHash(priv, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10167; + if (!verified) + return -10168; + + /* Check that the KPAK is converted from montogmery form. */ + ret = wc_ValidateEccsiPair(pub, WC_HASH_TYPE_SHA256, id, idSz, ssk, pvt, + &valid); + if (ret != 0) + return -10169; + if (!valid) + return -10170; + + /* Check that KPAK can converted to Montogmery form again. */ + ret = wc_VerifyEccsiHash(priv, WC_HASH_TYPE_SHA256, msg, msgSz, sig, sigSz, + &verified); + if (ret != 0) + return -10171; + if (!verified) + return -10172; + + /* Check that the KPAK is converted from montogmery form. */ + ret = eccsi_imp_exp_pubkey_test(priv, pub); + if (ret != 0) + return ret; + + return 0; +} + +int eccsi_test(void) +{ + int ret = 0; + WC_RNG rng; + EccsiKey* priv = NULL; + EccsiKey* pub = NULL; + mp_int* ssk = NULL; + ecc_point* pvt = NULL; + + priv = (EccsiKey*)XMALLOC(sizeof(EccsiKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + ret = -10205; + } + + if (ret == 0) { + pub = (EccsiKey*)XMALLOC(sizeof(EccsiKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + ret = -10206; + } + } + + if (ret == 0) { + ssk = (mp_int*)XMALLOC(sizeof(mp_int), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssk == NULL) { + ret = -10207; + } + } + + if (ret == 0) { + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) + ret = -10200; + } + + if (ret == 0) { + pvt = wc_ecc_new_point(); + if (pvt == NULL) + ret = -10201; + } + + if (ret == 0) { + ret = mp_init(ssk); + if (ret != 0) + ret = -10202; + } + + if (ret == 0) { + ret = eccsi_api_test(&rng, priv, ssk, pvt); + } + + if (ret == 0) { + ret = wc_InitEccsiKey(pub, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + ret = -10203; + } + + if (ret == 0) { + ret = wc_InitEccsiKey(priv, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + ret = -10204; + } + + if (ret == 0) { + ret = eccsi_kat_verify_test(pub, pvt); + } + + if (ret == 0) { + ret = eccsi_make_key_test(priv, pub, &rng, ssk, pvt); + } + + if (ret == 0) { + ret = eccsi_sign_verify_test(priv, pub, &rng, ssk, pvt); + } + + wc_FreeEccsiKey(priv); + wc_FreeEccsiKey(pub); + mp_free(ssk); + wc_ecc_del_point(pvt); + + if (ret != -10200) + wc_FreeRng(&rng); + if (ssk != NULL) + XFREE(ssk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pub != NULL) + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (priv != NULL) + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* WOLFCRYPT_HAVE_ECCSI */ + +#ifdef WOLFCRYPT_HAVE_SAKKE +static int sakke_api_test(WC_RNG* rng, SakkeKey* key, ecc_point* rsk) +{ + int ret; + byte id[1] = { 0x00 }; + int valid; + byte data[256]; + word32 sz; + byte auth[257]; + word16 authSz; + byte ssv[256]; + word16 ssvSz; + word32 len; + + ret = wc_InitSakkeKey_ex(NULL, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + if (ret != BAD_FUNC_ARG) + return -10205; + ret = wc_InitSakkeKey_ex(NULL, 128, ECC_SAKKE_1, HEAP_HINT, INVALID_DEVID); + if (ret != BAD_FUNC_ARG) + return -10206; + + wc_FreeSakkeKey(NULL); + + XMEMSET(key, 0, sizeof(*key)); + wc_FreeSakkeKey(key); + + ret = wc_InitSakkeKey_ex(key, 128, ECC_SAKKE_1, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + return -10207; + + ret = wc_MakeSakkeKey(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10208; + ret = wc_MakeSakkeKey(key, NULL); + if (ret != BAD_FUNC_ARG) + return -10209; + ret = wc_MakeSakkeKey(NULL, rng); + if (ret != BAD_FUNC_ARG) + return -10210; + + ret = wc_MakeSakkePublicKey(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10211; + ret = wc_MakeSakkePublicKey(key, NULL); + if (ret != BAD_FUNC_ARG) + return -10212; + ret = wc_MakeSakkePublicKey(NULL, rsk); + if (ret != BAD_FUNC_ARG) + return -10213; + + ret = wc_MakeSakkeRsk(NULL, NULL, 1, NULL); + if (ret != BAD_FUNC_ARG) + return -10214; + ret = wc_MakeSakkeRsk(key, id, 1, NULL); + if (ret != BAD_FUNC_ARG) + return -10215; + ret = wc_MakeSakkeRsk(key, NULL, 1, rsk); + if (ret != BAD_FUNC_ARG) + return -10216; + ret = wc_MakeSakkeRsk(NULL, id, 1, rsk); + if (ret != BAD_FUNC_ARG) + return -10217; + + ret = wc_ValidateSakkeRsk(NULL, NULL, 1, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10218; + ret = wc_ValidateSakkeRsk(key, id, 1, rsk, NULL); + if (ret != BAD_FUNC_ARG) + return -10219; + ret = wc_ValidateSakkeRsk(NULL, id, 1, rsk, &valid); + if (ret != BAD_FUNC_ARG) + return -10220; + + ret = wc_ExportSakkeKey(NULL, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10221; + ret = wc_ExportSakkeKey(key, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10222; + ret = wc_ExportSakkeKey(NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10223; + + ret = wc_ImportSakkeKey(NULL, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10224; + ret = wc_ImportSakkeKey(key, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10225; + ret = wc_ImportSakkeKey(NULL, data, 1); + if (ret != BAD_FUNC_ARG) + return -10226; + + ret = wc_ExportSakkePrivateKey(NULL, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10227; + ret = wc_ExportSakkePrivateKey(key, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10228; + ret = wc_ExportSakkePrivateKey(NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10229; + + ret = wc_ImportSakkePrivateKey(NULL, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10230; + ret = wc_ImportSakkePrivateKey(key, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10231; + ret = wc_ImportSakkePrivateKey(NULL, data, 1); + if (ret != BAD_FUNC_ARG) + return -10232; + + sz = sizeof(data); + ret = wc_EncodeSakkeRsk(NULL, NULL, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10233; + ret = wc_EncodeSakkeRsk(key, rsk, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10234; + ret = wc_EncodeSakkeRsk(key, NULL, data, &sz, 1); + if (ret != BAD_FUNC_ARG) + return -10235; + ret = wc_EncodeSakkeRsk(NULL, rsk, data, &sz, 1); + if (ret != BAD_FUNC_ARG) + return -10236; + + ret = wc_DecodeSakkeRsk(NULL, NULL, sz, NULL); + if (ret != BAD_FUNC_ARG) + return -10237; + ret = wc_DecodeSakkeRsk(key, data, sz, NULL); + if (ret != BAD_FUNC_ARG) + return -10238; + ret = wc_DecodeSakkeRsk(key, NULL, sz, rsk); + if (ret != BAD_FUNC_ARG) + return -10239; + ret = wc_DecodeSakkeRsk(NULL, data, sz, rsk); + if (ret != BAD_FUNC_ARG) + return -10240; + + ret = wc_ImportSakkeRsk(NULL, NULL, sz); + if (ret != BAD_FUNC_ARG) + return -10237; + ret = wc_ImportSakkeRsk(key, NULL, sz); + if (ret != BAD_FUNC_ARG) + return -10237; + ret = wc_ImportSakkeRsk(NULL, data, sz); + if (ret != BAD_FUNC_ARG) + return -10237; + ret = wc_ImportSakkeRsk(key, data, 1); + if (ret != BUFFER_E) + return -10237; + + ret = wc_GenerateSakkeRskTable(NULL, NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10241; + ret = wc_GenerateSakkeRskTable(key, NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10242; + ret = wc_GenerateSakkeRskTable(NULL, rsk, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10243; + ret = wc_GenerateSakkeRskTable(NULL, NULL, data, &len); + if (ret != BAD_FUNC_ARG) + return -10244; + ret = wc_GenerateSakkeRskTable(key, rsk, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10245; + ret = wc_GenerateSakkeRskTable(key, NULL, data, &len); + if (ret != BAD_FUNC_ARG) + return -10246; + ret = wc_GenerateSakkeRskTable(NULL, rsk, data, &len); + if (ret != BAD_FUNC_ARG) + return -10247; + ret = wc_GenerateSakkeRskTable(key, rsk, NULL, &len); + if (ret != LENGTH_ONLY_E) + return -10248; + len--; + ret = wc_GenerateSakkeRskTable(key, rsk, data, &len); + if (ret != BUFFER_E) + return -10249; + + ret = wc_ExportSakkePublicKey(NULL, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10250; + ret = wc_ExportSakkePublicKey(key, data, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10251; + ret = wc_ExportSakkePublicKey(NULL, data, &sz, 1); + if (ret != BAD_FUNC_ARG) + return -10252; + + ret = wc_ImportSakkePublicKey(NULL, NULL, sz, 1); + if (ret != BAD_FUNC_ARG) + return -10253; + ret = wc_ImportSakkePublicKey(key, NULL, sz, 1); + if (ret != BAD_FUNC_ARG) + return -10254; + ret = wc_ImportSakkePublicKey(NULL, data, sz, 1); + if (ret != BAD_FUNC_ARG) + return -10255; + + ret = wc_GetSakkeAuthSize(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -10256; + ret = wc_GetSakkeAuthSize(key, NULL); + if (ret != BAD_FUNC_ARG) + return -10257; + ret = wc_GetSakkeAuthSize(NULL, &authSz); + if (ret != BAD_FUNC_ARG) + return -10258; + + ret = wc_MakeSakkePointI(NULL, NULL, SAKKE_ID_MAX_SIZE + 1); + if (ret != BAD_FUNC_ARG) + return -10259; + ret = wc_MakeSakkePointI(key, NULL, SAKKE_ID_MAX_SIZE + 1); + if (ret != BAD_FUNC_ARG) + return -10260; + ret = wc_MakeSakkePointI(NULL, id, 1); + if (ret != BAD_FUNC_ARG) + return -10261; + ret = wc_MakeSakkePointI(NULL, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10262; + ret = wc_MakeSakkePointI(key, id, SAKKE_ID_MAX_SIZE + 1); + if (ret != BAD_FUNC_ARG) + return -10263; + ret = wc_MakeSakkePointI(key, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10264; + ret = wc_MakeSakkePointI(NULL, id, 1); + if (ret != BAD_FUNC_ARG) + return -10265; + + ret = wc_GenerateSakkePointITable(NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10266; + ret = wc_GenerateSakkePointITable(key, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10267; + ret = wc_GenerateSakkePointITable(NULL, data, &len); + if (ret != BAD_FUNC_ARG) + return -10268; + ret = wc_GenerateSakkePointITable(key, NULL, &len); + if (ret != LENGTH_ONLY_E) + return -10269; + len--; + ret = wc_GenerateSakkePointITable(key, data, &len); + if (ret != BUFFER_E) + return -10270; + + ret = wc_SetSakkePointITable(NULL, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10271; + ret = wc_SetSakkePointITable(key, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10272; + ret = wc_SetSakkePointITable(NULL, data, 1); + if (ret != BAD_FUNC_ARG) + return -10273; + ret = wc_SetSakkePointITable(key, data, 1); + if (ret != BUFFER_E) + return -10274; + + ret = wc_ClearSakkePointITable(NULL); + if (ret != BAD_FUNC_ARG) + return -10275; + + ret = wc_GetSakkePointI(NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10276; + ret = wc_GetSakkePointI(key, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10277; + ret = wc_GetSakkePointI(NULL, data, &sz); + if (ret != BAD_FUNC_ARG) + return -10278; + sz = 1; + ret = wc_GetSakkePointI(key, data, &sz); + if (ret != BUFFER_E) + return -10279; + + sz = 256; + ret = wc_SetSakkePointI(NULL, NULL, 1, NULL, sz); + if (ret != BAD_FUNC_ARG) + return -10280; + ret = wc_SetSakkePointI(key, NULL, 1, NULL, sz); + if (ret != BAD_FUNC_ARG) + return -10281; + ret = wc_SetSakkePointI(NULL, id, 1, NULL, sz); + if (ret != BAD_FUNC_ARG) + return -10282; + ret = wc_SetSakkePointI(NULL, NULL, 1, data, sz); + if (ret != BAD_FUNC_ARG) + return -10283; + ret = wc_SetSakkePointI(key, id, 1, NULL, sz); + if (ret != BAD_FUNC_ARG) + return -10284; + ret = wc_SetSakkePointI(key, NULL, 1, data, sz); + if (ret != BAD_FUNC_ARG) + return -10285; + ret = wc_SetSakkePointI(NULL, id, 1, data, sz); + if (ret != BAD_FUNC_ARG) + return -10286; + ret = wc_SetSakkePointI(key, id, SAKKE_ID_MAX_SIZE + 1, data, sz); + if (ret != BUFFER_E) + return -10287; + ret = wc_SetSakkePointI(key, id, 1, data, sz - 1); + if (ret != BUFFER_E) + return -10288; + + ret = wc_SetSakkeIdentity(NULL, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10286; + ret = wc_SetSakkeIdentity(key, NULL, 1); + if (ret != BAD_FUNC_ARG) + return -10286; + ret = wc_SetSakkeIdentity(NULL, id, 1); + if (ret != BAD_FUNC_ARG) + return -10286; + + ssvSz = sizeof(ssv); + ret = wc_MakeSakkeEncapsulatedSSV(NULL, WC_HASH_TYPE_SHA256, NULL, ssvSz, + auth, NULL); + if (ret != BAD_FUNC_ARG) + return -10289; + ret = wc_MakeSakkeEncapsulatedSSV(key, WC_HASH_TYPE_SHA256, NULL, ssvSz, + auth, NULL); + if (ret != BAD_FUNC_ARG) + return -10290; + ret = wc_MakeSakkeEncapsulatedSSV(NULL, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, NULL); + if (ret != BAD_FUNC_ARG) + return -10291; + ret = wc_MakeSakkeEncapsulatedSSV(NULL, WC_HASH_TYPE_SHA256, NULL, ssvSz, + auth, &authSz); + if (ret != BAD_FUNC_ARG) + return -10292; + ret = wc_MakeSakkeEncapsulatedSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, NULL); + if (ret != BAD_FUNC_ARG) + return -10293; + ret = wc_MakeSakkeEncapsulatedSSV(key, WC_HASH_TYPE_SHA256, NULL, ssvSz, + auth, &authSz); + if (ret != BAD_FUNC_ARG) + return -10294; + ret = wc_MakeSakkeEncapsulatedSSV(NULL, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, &authSz); + if (ret != BAD_FUNC_ARG) + return -10295; + ret = wc_MakeSakkeEncapsulatedSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, &authSz); + if (ret != BAD_STATE_E) + return -10295; + + ret = wc_GenerateSakkeSSV(NULL, NULL, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10296; + ret = wc_GenerateSakkeSSV(key, rng, data, NULL); + if (ret != BAD_FUNC_ARG) + return -10297; + ret = wc_GenerateSakkeSSV(key, NULL, data, &ssvSz); + if (ret != BAD_FUNC_ARG) + return -10298; + ret = wc_GenerateSakkeSSV(NULL, rng, data, &ssvSz); + if (ret != BAD_FUNC_ARG) + return -10299; + + ret = wc_SetSakkeRsk(NULL, NULL, data, 1); + if (ret != BAD_FUNC_ARG) + return -10286; + ret = wc_SetSakkeRsk(key, NULL, data, 1); + if (ret != BAD_FUNC_ARG) + return -10286; + ret = wc_SetSakkeRsk(NULL, rsk, data, 1); + if (ret != BAD_FUNC_ARG) + return -10286; + + ssvSz = sizeof(ssv); + authSz = sizeof(auth); + ret = wc_DeriveSakkeSSV(NULL, WC_HASH_TYPE_SHA256, NULL, ssvSz, NULL, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, NULL, ssvSz, NULL, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(NULL, WC_HASH_TYPE_SHA256, ssv, ssvSz, NULL, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(NULL, WC_HASH_TYPE_SHA256, NULL, ssvSz, auth, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, NULL, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, NULL, ssvSz, auth, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(NULL, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != BAD_FUNC_ARG) + return -10300; + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != BAD_STATE_E) + return -10300; + + ret = wc_SetSakkeIdentity(key, id, 1); + if (ret != 0) + return -10286; + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != BAD_STATE_E) + return -10300; + ret = wc_SetSakkeIdentity(key, id, 0); + if (ret != 0) + return -10286; + + ret = wc_SetSakkeRsk(key, rsk, data, 1); + if (ret != 0) + return -10286; + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != BAD_STATE_E) + return -10300; + + wc_FreeSakkeKey(key); + + return 0; +} + +static int sakke_kat_derive_test(SakkeKey* key, ecc_point* rsk) +{ + static const byte pubData[] = { + 0x59, 0x58, 0xEF, 0x1B, 0x16, 0x79, 0xBF, 0x09, + 0x9B, 0x3A, 0x03, 0x0D, 0xF2, 0x55, 0xAA, 0x6A, + 0x23, 0xC1, 0xD8, 0xF1, 0x43, 0xD4, 0xD2, 0x3F, + 0x75, 0x3E, 0x69, 0xBD, 0x27, 0xA8, 0x32, 0xF3, + 0x8C, 0xB4, 0xAD, 0x53, 0xDD, 0xEF, 0x42, 0x60, + 0xB0, 0xFE, 0x8B, 0xB4, 0x5C, 0x4C, 0x1F, 0xF5, + 0x10, 0xEF, 0xFE, 0x30, 0x03, 0x67, 0xA3, 0x7B, + 0x61, 0xF7, 0x01, 0xD9, 0x14, 0xAE, 0xF0, 0x97, + 0x24, 0x82, 0x5F, 0xA0, 0x70, 0x7D, 0x61, 0xA6, + 0xDF, 0xF4, 0xFB, 0xD7, 0x27, 0x35, 0x66, 0xCD, + 0xDE, 0x35, 0x2A, 0x0B, 0x04, 0xB7, 0xC1, 0x6A, + 0x78, 0x30, 0x9B, 0xE6, 0x40, 0x69, 0x7D, 0xE7, + 0x47, 0x61, 0x3A, 0x5F, 0xC1, 0x95, 0xE8, 0xB9, + 0xF3, 0x28, 0x85, 0x2A, 0x57, 0x9D, 0xB8, 0xF9, + 0x9B, 0x1D, 0x00, 0x34, 0x47, 0x9E, 0xA9, 0xC5, + 0x59, 0x5F, 0x47, 0xC4, 0xB2, 0xF5, 0x4F, 0xF2, + 0x15, 0x08, 0xD3, 0x75, 0x14, 0xDC, 0xF7, 0xA8, + 0xE1, 0x43, 0xA6, 0x05, 0x8C, 0x09, 0xA6, 0xBF, + 0x2C, 0x98, 0x58, 0xCA, 0x37, 0xC2, 0x58, 0x06, + 0x5A, 0xE6, 0xBF, 0x75, 0x32, 0xBC, 0x8B, 0x5B, + 0x63, 0x38, 0x38, 0x66, 0xE0, 0x75, 0x3C, 0x5A, + 0xC0, 0xE7, 0x27, 0x09, 0xF8, 0x44, 0x5F, 0x2E, + 0x61, 0x78, 0xE0, 0x65, 0x85, 0x7E, 0x0E, 0xDA, + 0x10, 0xF6, 0x82, 0x06, 0xB6, 0x35, 0x05, 0xED, + 0x87, 0xE5, 0x34, 0xFB, 0x28, 0x31, 0xFF, 0x95, + 0x7F, 0xB7, 0xDC, 0x61, 0x9D, 0xAE, 0x61, 0x30, + 0x1E, 0xEA, 0xCC, 0x2F, 0xDA, 0x36, 0x80, 0xEA, + 0x49, 0x99, 0x25, 0x8A, 0x83, 0x3C, 0xEA, 0x8F, + 0xC6, 0x7C, 0x6D, 0x19, 0x48, 0x7F, 0xB4, 0x49, + 0x05, 0x9F, 0x26, 0xCC, 0x8A, 0xAB, 0x65, 0x5A, + 0xB5, 0x8B, 0x7C, 0xC7, 0x96, 0xE2, 0x4E, 0x9A, + 0x39, 0x40, 0x95, 0x75, 0x4F, 0x5F, 0x8B, 0xAE + }; + static const byte rskData[] = { + 0x93, 0xAF, 0x67, 0xE5, 0x00, 0x7B, 0xA6, 0xE6, + 0xA8, 0x0D, 0xA7, 0x93, 0xDA, 0x30, 0x0F, 0xA4, + 0xB5, 0x2D, 0x0A, 0x74, 0xE2, 0x5E, 0x6E, 0x7B, + 0x2B, 0x3D, 0x6E, 0xE9, 0xD1, 0x8A, 0x9B, 0x5C, + 0x50, 0x23, 0x59, 0x7B, 0xD8, 0x2D, 0x80, 0x62, + 0xD3, 0x40, 0x19, 0x56, 0x3B, 0xA1, 0xD2, 0x5C, + 0x0D, 0xC5, 0x6B, 0x7B, 0x97, 0x9D, 0x74, 0xAA, + 0x50, 0xF2, 0x9F, 0xBF, 0x11, 0xCC, 0x2C, 0x93, + 0xF5, 0xDF, 0xCA, 0x61, 0x5E, 0x60, 0x92, 0x79, + 0xF6, 0x17, 0x5C, 0xEA, 0xDB, 0x00, 0xB5, 0x8C, + 0x6B, 0xEE, 0x1E, 0x7A, 0x2A, 0x47, 0xC4, 0xF0, + 0xC4, 0x56, 0xF0, 0x52, 0x59, 0xA6, 0xFA, 0x94, + 0xA6, 0x34, 0xA4, 0x0D, 0xAE, 0x1D, 0xF5, 0x93, + 0xD4, 0xFE, 0xCF, 0x68, 0x8D, 0x5F, 0xC6, 0x78, + 0xBE, 0x7E, 0xFC, 0x6D, 0xF3, 0xD6, 0x83, 0x53, + 0x25, 0xB8, 0x3B, 0x2C, 0x6E, 0x69, 0x03, 0x6B, + 0x15, 0x5F, 0x0A, 0x27, 0x24, 0x10, 0x94, 0xB0, + 0x4B, 0xFB, 0x0B, 0xDF, 0xAC, 0x6C, 0x67, 0x0A, + 0x65, 0xC3, 0x25, 0xD3, 0x9A, 0x06, 0x9F, 0x03, + 0x65, 0x9D, 0x44, 0xCA, 0x27, 0xD3, 0xBE, 0x8D, + 0xF3, 0x11, 0x17, 0x2B, 0x55, 0x41, 0x60, 0x18, + 0x1C, 0xBE, 0x94, 0xA2, 0xA7, 0x83, 0x32, 0x0C, + 0xED, 0x59, 0x0B, 0xC4, 0x26, 0x44, 0x70, 0x2C, + 0xF3, 0x71, 0x27, 0x1E, 0x49, 0x6B, 0xF2, 0x0F, + 0x58, 0x8B, 0x78, 0xA1, 0xBC, 0x01, 0xEC, 0xBB, + 0x65, 0x59, 0x93, 0x4B, 0xDD, 0x2F, 0xB6, 0x5D, + 0x28, 0x84, 0x31, 0x8A, 0x33, 0xD1, 0xA4, 0x2A, + 0xDF, 0x5E, 0x33, 0xCC, 0x58, 0x00, 0x28, 0x0B, + 0x28, 0x35, 0x64, 0x97, 0xF8, 0x71, 0x35, 0xBA, + 0xB9, 0x61, 0x2A, 0x17, 0x26, 0x04, 0x24, 0x40, + 0x9A, 0xC1, 0x5F, 0xEE, 0x99, 0x6B, 0x74, 0x4C, + 0x33, 0x21, 0x51, 0x23, 0x5D, 0xEC, 0xB0, 0xF5 + + }; + static const byte id[] = { + 0x32, 0x30, 0x31, 0x31, 0x2D, 0x30, 0x32, 0x00, + 0x74, 0x65, 0x6C, 0x3A, 0x2B, 0x34, 0x34, 0x37, + 0x37, 0x30, 0x30, 0x39, 0x30, 0x30, 0x31, 0x32, + 0x33, 0x00 + }; + static const byte ssv[] = { + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 + }; + static const byte auth[] = { + 0x04, + 0x44, 0xE8, 0xAD, 0x44, 0xAB, 0x85, 0x92, 0xA6, + 0xA5, 0xA3, 0xDD, 0xCA, 0x5C, 0xF8, 0x96, 0xC7, + 0x18, 0x04, 0x36, 0x06, 0xA0, 0x1D, 0x65, 0x0D, + 0xEF, 0x37, 0xA0, 0x1F, 0x37, 0xC2, 0x28, 0xC3, + 0x32, 0xFC, 0x31, 0x73, 0x54, 0xE2, 0xC2, 0x74, + 0xD4, 0xDA, 0xF8, 0xAD, 0x00, 0x10, 0x54, 0xC7, + 0x6C, 0xE5, 0x79, 0x71, 0xC6, 0xF4, 0x48, 0x6D, + 0x57, 0x23, 0x04, 0x32, 0x61, 0xC5, 0x06, 0xEB, + 0xF5, 0xBE, 0x43, 0x8F, 0x53, 0xDE, 0x04, 0xF0, + 0x67, 0xC7, 0x76, 0xE0, 0xDD, 0x3B, 0x71, 0xA6, + 0x29, 0x01, 0x33, 0x28, 0x37, 0x25, 0xA5, 0x32, + 0xF2, 0x1A, 0xF1, 0x45, 0x12, 0x6D, 0xC1, 0xD7, + 0x77, 0xEC, 0xC2, 0x7B, 0xE5, 0x08, 0x35, 0xBD, + 0x28, 0x09, 0x8B, 0x8A, 0x73, 0xD9, 0xF8, 0x01, + 0xD8, 0x93, 0x79, 0x3A, 0x41, 0xFF, 0x5C, 0x49, + 0xB8, 0x7E, 0x79, 0xF2, 0xBE, 0x4D, 0x56, 0xCE, + 0x55, 0x7E, 0x13, 0x4A, 0xD8, 0x5B, 0xB1, 0xD4, + 0xB9, 0xCE, 0x4F, 0x8B, 0xE4, 0xB0, 0x8A, 0x12, + 0xBA, 0xBF, 0x55, 0xB1, 0xD6, 0xF1, 0xD7, 0xA6, + 0x38, 0x01, 0x9E, 0xA2, 0x8E, 0x15, 0xAB, 0x1C, + 0x9F, 0x76, 0x37, 0x5F, 0xDD, 0x12, 0x10, 0xD4, + 0xF4, 0x35, 0x1B, 0x9A, 0x00, 0x94, 0x86, 0xB7, + 0xF3, 0xED, 0x46, 0xC9, 0x65, 0xDE, 0xD2, 0xD8, + 0x0D, 0xAD, 0xE4, 0xF3, 0x8C, 0x67, 0x21, 0xD5, + 0x2C, 0x3A, 0xD1, 0x03, 0xA1, 0x0E, 0xBD, 0x29, + 0x59, 0x24, 0x8B, 0x4E, 0xF0, 0x06, 0x83, 0x6B, + 0xF0, 0x97, 0x44, 0x8E, 0x61, 0x07, 0xC9, 0xED, + 0xEE, 0x9F, 0xB7, 0x04, 0x82, 0x3D, 0xF1, 0x99, + 0xF8, 0x32, 0xC9, 0x05, 0xAE, 0x45, 0xF8, 0xA2, + 0x47, 0xA0, 0x72, 0xD8, 0xEF, 0x72, 0x9E, 0xAB, + 0xC5, 0xE2, 0x75, 0x74, 0xB0, 0x77, 0x39, 0xB3, + 0x4B, 0xE7, 0x4A, 0x53, 0x2F, 0x74, 0x7B, 0x86 + }; + byte encSsv[] = { + 0x89, 0xE0, 0xBC, 0x66, 0x1A, 0xA1, 0xE9, 0x16, + 0x38, 0xE6, 0xAC, 0xC8, 0x4E, 0x49, 0x65, 0x07 + }; + int ret; + int valid; + byte pubKey[sizeof(pubData) + 1]; + word32 sz = sizeof(pubKey); + byte tmpSsv[sizeof(encSsv)]; + byte* iTable = NULL; + word32 iTableLen; + byte* table = NULL; + word32 len; + + ret = wc_ImportSakkePublicKey(key, pubData, sizeof(pubData), 0); + if (ret != 0) + return -10315; + + ret = wc_DecodeSakkeRsk(key, rskData, sizeof(rskData), rsk); + if (ret != 0) + return -10316; + + ret = wc_ValidateSakkeRsk(key, id, sizeof(id), rsk, &valid); + if (ret != 0) + return -10317; + if (valid != 1) + return -10318; + + ret = wc_SetSakkeRsk(key, rsk, NULL, 0); + if (ret != 0) + return -10319; + ret = wc_SetSakkeIdentity(key, id, sizeof(id)); + if (ret != 0) + return -10319; + + XMEMCPY(tmpSsv, encSsv, sizeof(encSsv)); + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, tmpSsv, sizeof(tmpSsv), + auth, sizeof(auth)); + if (ret != 0) + return -10322; + if (XMEMCMP(tmpSsv, ssv, sizeof(ssv)) != 0) + return -10320; + + ret = wc_MakeSakkePointI(key, id, sizeof(id)); + if (ret != 0) + return -10321; + iTableLen = 0; + ret = wc_GenerateSakkePointITable(key, NULL, &iTableLen); + if (ret != LENGTH_ONLY_E) + return -10322; + if (iTableLen != 0) { + iTable = (byte*)XMALLOC(iTableLen, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (iTable == NULL) + return -10323; + ret = wc_GenerateSakkePointITable(key, iTable, &iTableLen); + if (ret != 0) + return -10324; + } + len = 0; + ret = wc_GenerateSakkeRskTable(key, rsk, NULL, &len); + if (ret != LENGTH_ONLY_E) + return -10325; + if (len > 0) { + table = (byte*)XMALLOC(len, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (table == NULL) + return -10326; + ret = wc_GenerateSakkeRskTable(key, rsk, table, &len); + if (ret != 0) + return -10327; + } + + ret = wc_SetSakkeRsk(key, rsk, table, len); + if (ret != 0) + return -10319; + + XMEMCPY(tmpSsv, encSsv, sizeof(encSsv)); + ret = wc_DeriveSakkeSSV(key, WC_HASH_TYPE_SHA256, tmpSsv, sizeof(tmpSsv), + auth, sizeof(auth)); + if (ret != 0) + return -10328; + if (XMEMCMP(tmpSsv, ssv, sizeof(ssv)) != 0) + return -10329; + + /* Don't reference table that is about to be freed. */ + ret = wc_ClearSakkePointITable(key); + if (ret != 0) + return -10330; + /* Dispose of tables */ + if (iTable != NULL) + XFREE(iTable, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (table != NULL) + XFREE(table, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + /* Make sure the key public key is exportable - convert to Montgomery form + * in Validation. + */ + ret = wc_ExportSakkePublicKey(key, pubKey, &sz, 1); + if (ret != 0) + return -10331; + if (sz != sizeof(pubData)) + return -10332; + if (XMEMCMP(pubKey, pubData, sizeof(pubData)) != 0) + return -10333; + + sz = sizeof(pubData) + 1; + ret = wc_ExportSakkePublicKey(key, pubKey, &sz, 0); + if (ret != 0) + return -10334; + if (sz != sizeof(pubData) + 1) + return -10335; + if (pubKey[0] != 0x04) + return -10336; + if (XMEMCMP(pubKey + 1, pubData, sizeof(pubData)) != 0) + return -10337; + + return 0; +} + +static int sakke_kat_encapsulate_test(SakkeKey* key) +{ + static const byte pubData[] = { + 0x59, 0x58, 0xEF, 0x1B, 0x16, 0x79, 0xBF, 0x09, + 0x9B, 0x3A, 0x03, 0x0D, 0xF2, 0x55, 0xAA, 0x6A, + 0x23, 0xC1, 0xD8, 0xF1, 0x43, 0xD4, 0xD2, 0x3F, + 0x75, 0x3E, 0x69, 0xBD, 0x27, 0xA8, 0x32, 0xF3, + 0x8C, 0xB4, 0xAD, 0x53, 0xDD, 0xEF, 0x42, 0x60, + 0xB0, 0xFE, 0x8B, 0xB4, 0x5C, 0x4C, 0x1F, 0xF5, + 0x10, 0xEF, 0xFE, 0x30, 0x03, 0x67, 0xA3, 0x7B, + 0x61, 0xF7, 0x01, 0xD9, 0x14, 0xAE, 0xF0, 0x97, + 0x24, 0x82, 0x5F, 0xA0, 0x70, 0x7D, 0x61, 0xA6, + 0xDF, 0xF4, 0xFB, 0xD7, 0x27, 0x35, 0x66, 0xCD, + 0xDE, 0x35, 0x2A, 0x0B, 0x04, 0xB7, 0xC1, 0x6A, + 0x78, 0x30, 0x9B, 0xE6, 0x40, 0x69, 0x7D, 0xE7, + 0x47, 0x61, 0x3A, 0x5F, 0xC1, 0x95, 0xE8, 0xB9, + 0xF3, 0x28, 0x85, 0x2A, 0x57, 0x9D, 0xB8, 0xF9, + 0x9B, 0x1D, 0x00, 0x34, 0x47, 0x9E, 0xA9, 0xC5, + 0x59, 0x5F, 0x47, 0xC4, 0xB2, 0xF5, 0x4F, 0xF2, + 0x15, 0x08, 0xD3, 0x75, 0x14, 0xDC, 0xF7, 0xA8, + 0xE1, 0x43, 0xA6, 0x05, 0x8C, 0x09, 0xA6, 0xBF, + 0x2C, 0x98, 0x58, 0xCA, 0x37, 0xC2, 0x58, 0x06, + 0x5A, 0xE6, 0xBF, 0x75, 0x32, 0xBC, 0x8B, 0x5B, + 0x63, 0x38, 0x38, 0x66, 0xE0, 0x75, 0x3C, 0x5A, + 0xC0, 0xE7, 0x27, 0x09, 0xF8, 0x44, 0x5F, 0x2E, + 0x61, 0x78, 0xE0, 0x65, 0x85, 0x7E, 0x0E, 0xDA, + 0x10, 0xF6, 0x82, 0x06, 0xB6, 0x35, 0x05, 0xED, + 0x87, 0xE5, 0x34, 0xFB, 0x28, 0x31, 0xFF, 0x95, + 0x7F, 0xB7, 0xDC, 0x61, 0x9D, 0xAE, 0x61, 0x30, + 0x1E, 0xEA, 0xCC, 0x2F, 0xDA, 0x36, 0x80, 0xEA, + 0x49, 0x99, 0x25, 0x8A, 0x83, 0x3C, 0xEA, 0x8F, + 0xC6, 0x7C, 0x6D, 0x19, 0x48, 0x7F, 0xB4, 0x49, + 0x05, 0x9F, 0x26, 0xCC, 0x8A, 0xAB, 0x65, 0x5A, + 0xB5, 0x8B, 0x7C, 0xC7, 0x96, 0xE2, 0x4E, 0x9A, + 0x39, 0x40, 0x95, 0x75, 0x4F, 0x5F, 0x8B, 0xAE + }; + static const byte id[] = { + 0x32, 0x30, 0x31, 0x31, 0x2D, 0x30, 0x32, 0x00, + 0x74, 0x65, 0x6C, 0x3A, 0x2B, 0x34, 0x34, 0x37, + 0x37, 0x30, 0x30, 0x39, 0x30, 0x30, 0x31, 0x32, + 0x33, 0x00 + }; + static word32 idSz = sizeof(id); + byte ssv[] = { + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 + }; + static word16 ssvSz = sizeof(ssv); + static const byte expAuth[] = { + 0x04, + 0x44, 0xE8, 0xAD, 0x44, 0xAB, 0x85, 0x92, 0xA6, + 0xA5, 0xA3, 0xDD, 0xCA, 0x5C, 0xF8, 0x96, 0xC7, + 0x18, 0x04, 0x36, 0x06, 0xA0, 0x1D, 0x65, 0x0D, + 0xEF, 0x37, 0xA0, 0x1F, 0x37, 0xC2, 0x28, 0xC3, + 0x32, 0xFC, 0x31, 0x73, 0x54, 0xE2, 0xC2, 0x74, + 0xD4, 0xDA, 0xF8, 0xAD, 0x00, 0x10, 0x54, 0xC7, + 0x6C, 0xE5, 0x79, 0x71, 0xC6, 0xF4, 0x48, 0x6D, + 0x57, 0x23, 0x04, 0x32, 0x61, 0xC5, 0x06, 0xEB, + 0xF5, 0xBE, 0x43, 0x8F, 0x53, 0xDE, 0x04, 0xF0, + 0x67, 0xC7, 0x76, 0xE0, 0xDD, 0x3B, 0x71, 0xA6, + 0x29, 0x01, 0x33, 0x28, 0x37, 0x25, 0xA5, 0x32, + 0xF2, 0x1A, 0xF1, 0x45, 0x12, 0x6D, 0xC1, 0xD7, + 0x77, 0xEC, 0xC2, 0x7B, 0xE5, 0x08, 0x35, 0xBD, + 0x28, 0x09, 0x8B, 0x8A, 0x73, 0xD9, 0xF8, 0x01, + 0xD8, 0x93, 0x79, 0x3A, 0x41, 0xFF, 0x5C, 0x49, + 0xB8, 0x7E, 0x79, 0xF2, 0xBE, 0x4D, 0x56, 0xCE, + 0x55, 0x7E, 0x13, 0x4A, 0xD8, 0x5B, 0xB1, 0xD4, + 0xB9, 0xCE, 0x4F, 0x8B, 0xE4, 0xB0, 0x8A, 0x12, + 0xBA, 0xBF, 0x55, 0xB1, 0xD6, 0xF1, 0xD7, 0xA6, + 0x38, 0x01, 0x9E, 0xA2, 0x8E, 0x15, 0xAB, 0x1C, + 0x9F, 0x76, 0x37, 0x5F, 0xDD, 0x12, 0x10, 0xD4, + 0xF4, 0x35, 0x1B, 0x9A, 0x00, 0x94, 0x86, 0xB7, + 0xF3, 0xED, 0x46, 0xC9, 0x65, 0xDE, 0xD2, 0xD8, + 0x0D, 0xAD, 0xE4, 0xF3, 0x8C, 0x67, 0x21, 0xD5, + 0x2C, 0x3A, 0xD1, 0x03, 0xA1, 0x0E, 0xBD, 0x29, + 0x59, 0x24, 0x8B, 0x4E, 0xF0, 0x06, 0x83, 0x6B, + 0xF0, 0x97, 0x44, 0x8E, 0x61, 0x07, 0xC9, 0xED, + 0xEE, 0x9F, 0xB7, 0x04, 0x82, 0x3D, 0xF1, 0x99, + 0xF8, 0x32, 0xC9, 0x05, 0xAE, 0x45, 0xF8, 0xA2, + 0x47, 0xA0, 0x72, 0xD8, 0xEF, 0x72, 0x9E, 0xAB, + 0xC5, 0xE2, 0x75, 0x74, 0xB0, 0x77, 0x39, 0xB3, + 0x4B, 0xE7, 0x4A, 0x53, 0x2F, 0x74, 0x7B, 0x86 + }; + static const byte encSsv[] = { + 0x89, 0xE0, 0xBC, 0x66, 0x1A, 0xA1, 0xE9, 0x16, + 0x38, 0xE6, 0xAC, 0xC8, 0x4E, 0x49, 0x65, 0x07 + }; + int ret; + byte auth[257]; + word16 authSz = sizeof(auth); + + ret = wc_ImportSakkePublicKey(key, pubData, sizeof(pubData), 0); + if (ret != 0) + return -10334; + + ret = wc_SetSakkeIdentity(key, id, idSz); + if (ret != 0) + return -10335; + + ret = wc_MakeSakkeEncapsulatedSSV(key, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, &authSz); + if (ret != 0) + return -10336; + if (authSz != 257) + return -10337; + + if (XMEMCMP(ssv, encSsv, ssvSz) != 0) + return -10338; + if (XMEMCMP(auth, expAuth, authSz) != 0) + return -10339; + + return 0; +} + +static int sakke_make_key_test(SakkeKey* priv, SakkeKey* pub, SakkeKey* key, + WC_RNG* rng, ecc_point* rsk) +{ + int ret; + byte data[440]; + byte pubData[257]; + word32 sz; + char mail[] = "test@wolfssl.com"; + byte* id = (byte*)mail; + word32 idSz = (word32)XSTRLEN(mail); + int valid; + ecc_point* pubKey = rsk; + + ret = wc_InitSakkeKey_ex(key, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + if (ret != 0) + return -10339; + + ret = wc_MakeSakkeKey(priv, rng); + if (ret != 0) + return -10340; + + ret = wc_ExportSakkeKey(priv, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10341; + if (sz != 384) + return -10342; + sz--; + ret = wc_ExportSakkeKey(priv, data, &sz); + if (ret == 0) + return -10343; + sz++; + ret = wc_ExportSakkeKey(priv, data, &sz); + if (ret != 0) + return -10344; + if (sz != 384) + return -10345; + + ret = wc_ImportSakkeKey(key, data, sz - 1); + if (ret == 0) + return -10346; + ret = wc_ImportSakkeKey(key, data, sz); + if (ret != 0) + return -10347; + wc_FreeSakkeKey(key); + ret = wc_InitSakkeKey_ex(key, 128, ECC_SAKKE_1, NULL, INVALID_DEVID); + if (ret != 0) + return -10348; + + ret = wc_ExportSakkePrivateKey(priv, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10349; + if (sz != 128) + return -10350; + sz--; + ret = wc_ExportSakkePrivateKey(priv, data, &sz); + if (ret == 0) + return -10351; + sz++; + ret = wc_ExportSakkePrivateKey(priv, data, &sz); + if (ret != 0) + return -10352; + if (sz != 128) + return -10353; + + ret = wc_ImportSakkePrivateKey(key, data, sz - 1); + if (ret == 0) + return -10354; + ret = wc_ImportSakkePrivateKey(key, data, sz); + if (ret != 0) + return -10355; + ret = wc_MakeSakkePublicKey(key, pubKey); + if (ret != 0) + return -10356; + + ret = wc_ExportSakkePublicKey(priv, NULL, &sz, 1); + if (ret != LENGTH_ONLY_E) + return -10357; + if (sz != 256) + return -10358; + sz--; + ret = wc_ExportSakkePublicKey(priv, data, &sz, 1); + if (ret == 0) + return -10359; + sz++; + ret = wc_ExportSakkePublicKey(priv, data, &sz, 1); + if (ret != 0) + return -10360; + if (sz != 256) + return -10361; + + ret = wc_ImportSakkePublicKey(pub, data, sz - 1, 1); + if (ret == 0) + return -10362; + ret = wc_ImportSakkePublicKey(pub, data, sz, 1); + if (ret != 0) + return -10363; + + ret = wc_ExportSakkePublicKey(pub, pubData, &sz, 1); + if (ret != 0) + return -10364; + if (sz != 256) + return -10365; + if (XMEMCMP(data, pubData, sz) != 0) + return -10366; + + ret = wc_MakeSakkeRsk(priv, id, idSz, rsk); + if (ret != 0) + return -10367; + + ret = wc_ValidateSakkeRsk(priv, id, idSz, rsk, &valid); + if (ret != 0) + return -10368; + if (valid != 1) + return -10369; + + ret = wc_ValidateSakkeRsk(pub, id, idSz, rsk, &valid); + if (ret != 0) + return -10370; + if (valid != 1) + return -10371; + + sz = sizeof(data); + ret = wc_EncodeSakkeRsk(priv, rsk, data, &sz, 1); + if (ret != 0) + return -10372; + if (sz != 256) + return -10373; + ret = wc_DecodeSakkeRsk(priv, data, sz, rsk); + if (ret != 0) + return -10374; + + sz = sizeof(pubData); + ret = wc_EncodeSakkeRsk(priv, rsk, pubData, &sz, 0); + if (ret != 0) + return -10375; + if (sz != sizeof(pubData)) + return -10376; + ret = wc_DecodeSakkeRsk(priv, pubData, sz, rsk); + if (ret != 0) + return -10377; + + wc_FreeSakkeKey(key); + + return 0; +} + +static int sakke_op_test(SakkeKey* priv, SakkeKey* pub, WC_RNG* rng, + ecc_point* rsk) +{ + int ret; + byte ssv[16]; + word16 ssvSz; + byte auth[257]; + word16 authSz; + char mail[] = "test@wolfssl.com"; + byte* id = (byte*)mail; + word32 idSz = (word32)XSTRLEN(mail); + byte pointI[256]; + word32 sz; + + ret = wc_GenerateSakkeSSV(pub, rng, NULL, &ssvSz); + if (ret != LENGTH_ONLY_E) + return -10375; + if (ssvSz != 16) + return -10376; + + ssvSz += 128; + ret = wc_GenerateSakkeSSV(pub, rng, ssv, &ssvSz); + if (ret == 0) + return -10377; + ssvSz -= 128; + ret = wc_GenerateSakkeSSV(pub, rng, ssv, &ssvSz); + if (ret != 0) + return -10378; + if (ssvSz != 16) + return -10379; + + ret = wc_GetSakkeAuthSize(pub, &authSz); + if (ret != 0) + return -10380; + + ret = wc_SetSakkeIdentity(pub, id, idSz); + if (ret != 0) + return -10380; + + ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssv, ssvSz, + NULL, &authSz); + if (ret != LENGTH_ONLY_E) + return -10381; + if (authSz != 257) + return -10382; + + authSz--; + ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, &authSz); + if (ret == 0) + return -10383; + authSz++; + ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, &authSz); + if (ret != 0) + return -10384; + if (authSz != 257) + return -10385; + + ret = wc_GetSakkePointI(pub, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return -10386; + if (sz != 256) + return -10387; + ret = wc_GetSakkePointI(pub, pointI, &sz); + if (ret != 0) + return -10388; + if (sz != 256) + return -10389; + + /* Bogus identity - make it check and regenerate I. */ + ret = wc_MakeSakkePointI(pub, ssv, ssvSz); + if (ret != 0) + return -10391; + ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssv, ssvSz, + auth, &authSz); + if (ret != 0) + return -10392; + if (authSz != 257) + return -10393; + + ret = wc_SetSakkeRsk(priv, rsk, NULL, 0); + if (ret != 0) + return -10392; + ret = wc_SetSakkeIdentity(priv, id, idSz); + if (ret != 0) + return -10392; + + authSz--; + ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret == 0) + return -10394; + authSz++; + ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != 0) + return -10395; + ssv[0] ^= 0x80; + ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != SAKKE_VERIFY_FAIL_E) + return -10396; + ssv[0] ^= 0x80; + + /* Bogus identity - make it check and regenerate I. */ + ret = wc_MakeSakkePointI(pub, ssv, idSz); + if (ret != 0) + return -10397; + ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssv, ssvSz, auth, + authSz); + if (ret != 0) + return -10398; + return 0; +} + +int sakke_test(void) +{ + int ret = 0; + WC_RNG rng; + SakkeKey* priv = NULL; + SakkeKey* pub = NULL; + SakkeKey* key = NULL; + ecc_point* rsk = NULL; + + priv = (SakkeKey*)XMALLOC(sizeof(SakkeKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + ret = -10404; + } + + if (ret == 0) { + pub = (SakkeKey*)XMALLOC(sizeof(SakkeKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + ret = -10405; + } + } + + if (ret == 0) { + key = (SakkeKey*)XMALLOC(sizeof(SakkeKey), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + ret = -10406; + } + } + + if (ret == 0) { + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) + ret = -10400; + } + + if (ret == 0) { + rsk = wc_ecc_new_point(); + if (rsk == NULL) + ret = -10401; + } + + if (ret == 0) { + ret = wc_InitSakkeKey(pub, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + ret = -10402; + } + + if (ret == 0) { + ret = wc_InitSakkeKey(priv, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + ret = -10403; + } + + if (ret == 0) { + ret = sakke_api_test(&rng, key, rsk); + } + + if (ret == 0) { + ret = sakke_kat_derive_test(pub, rsk); + } + + if (ret == 0) { + ret = sakke_kat_encapsulate_test(pub); + } + + if (ret == 0) { + ret = sakke_make_key_test(priv, pub, key, &rng, rsk); + } + + if (ret == 0) { + ret = sakke_op_test(priv, pub, &rng, rsk); + } + + wc_FreeSakkeKey(priv); + wc_FreeSakkeKey(pub); + wc_ecc_forcezero_point(rsk); + wc_ecc_del_point(rsk); + + if (ret != -10400) + wc_FreeRng(&rng); + + if (key != NULL) + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pub != NULL) + XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (priv != NULL) + XFREE(priv, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* WOLFCRYPT_HAVE_SAKKE */ + + #if defined(WOLFSSL_CMAC) && !defined(NO_AES) typedef struct CMAC_Test_Case { @@ -26680,8 +29274,16 @@ WOLFSSL_TEST_SUBROUTINE int cmac_test(void) XMEMSET(tag, 0, sizeof(tag)); tagSz = AES_BLOCK_SIZE; + +#if !defined(HAVE_FIPS) || \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 3) + if (wc_InitCmac_ex(cmac, tc->k, tc->kSz, tc->type, NULL, HEAP_HINT, devId) != 0) +#else if (wc_InitCmac(cmac, tc->k, tc->kSz, tc->type, NULL) != 0) +#endif + { ERROR_OUT(-12000, out); + } if (tc->partial) { if (wc_CmacUpdate(cmac, tc->m, tc->mSz/2 - tc->partial) != 0) @@ -27987,6 +30589,9 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); ERROR_OUT(-12192, out); + } else { + /* reset ret to 0 for success */ + ret = 0; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -28667,6 +31272,9 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); ERROR_OUT(-12232, out); + } else { + /* reset ret to 0 for success */ + ret = 0; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -31707,8 +34315,7 @@ static int mp_test_param(mp_int* a, mp_int* b, mp_int* r, WC_RNG* rng) return -12827; #endif -#if defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \ - (defined(HAVE_ECC) && defined(FP_ECC)) +#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) ret = mp_gcd(NULL, NULL, NULL); if (ret != MP_VAL) return -12828; @@ -31815,7 +34422,7 @@ static int mp_test_param(mp_int* a, mp_int* b, mp_int* r, WC_RNG* rng) return -12858; #endif -#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) +#if defined(WOLFSSL_SP_MATH_ALL) && !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) ret = mp_lcm(NULL, NULL, NULL); if (ret != MP_VAL) return -12859; @@ -32367,6 +34974,31 @@ static int mp_test_cmp(mp_int* a, mp_int* b) if (ret != MP_EQ) return -13010; +#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ + defined(WOLFSSL_SP_INT_NEGATIVE) + mp_read_radix(a, "-1", MP_RADIX_HEX); + mp_read_radix(a, "1", MP_RADIX_HEX); + ret = mp_cmp(a, b); + if (ret != MP_LT) + return -13011; + ret = mp_cmp(b, a); + if (ret != MP_GT) + return -13012; + + mp_read_radix(b, "-2", MP_RADIX_HEX); + ret = mp_cmp(a, b); + if (ret != MP_GT) + return -13013; + ret = mp_cmp(b, a); + if (ret != MP_LT) + return -13014; + + mp_read_radix(a, "-2", MP_RADIX_HEX); + ret = mp_cmp(a, b); + if (ret != MP_EQ) + return -13015; +#endif + return 0; } @@ -32644,23 +35276,20 @@ static int mp_test_prime(mp_int* a, WC_RNG* rng) } #endif -#if defined(WOLFSSL_SP_MATH_ALL) || (defined(WOLFSSL_SP_MATH) && \ - defined(WOLFSSL_HAVE_SP_DH) || (defined(HAVE_ECC) && defined(FP_ECC))) +#if defined(WOLFSSL_KEY_GEN) && (!defined(WOLFSSL_SP_MATH_ALL) || \ + !defined(NO_RSA)) static int mp_test_lcm_gcd(mp_int* a, mp_int* b, mp_int* r, mp_int* exp, WC_RNG* rng) { int ret; -#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) int i; WOLFSSL_SMALL_STACK_STATIC const int kat[][3] = { { 1, 1, 1 }, { 2, 1, 2 }, { 1, 2, 2 }, { 2, 4, 4 }, { 4, 2, 4 }, { 12, 56, 168 }, { 56, 12, 168 } }; -#endif (void)exp; -#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) mp_set(a, 0); mp_set(b, 1); ret = mp_lcm(a, a, r); @@ -32683,7 +35312,6 @@ static int mp_test_lcm_gcd(mp_int* a, mp_int* b, mp_int* r, mp_int* exp, if (mp_cmp(r, exp) != MP_EQ) return -13094; } -#endif (void)rng; #if defined(WOLFSSL_KEY_GEN) && (!defined(NO_DH) || !defined(NO_DSA)) && \ @@ -33196,7 +35824,7 @@ WOLFSSL_TEST_SUBROUTINE int mp_test(void) if (ret != 0) return -13300; -#ifdef WOLSSL_SP_MATH_ALL +#ifdef WOLFSSL_SP_MATH_ALL mp_init_copy(&p, &a); #else ret = mp_init(&p); @@ -33380,8 +36008,8 @@ WOLFSSL_TEST_SUBROUTINE int mp_test(void) if ((ret = mp_test_prime(&a, &rng)) != 0) return ret; #endif -#if defined(WOLFSSL_SP_MATH_ALL) || (defined(WOLFSSL_SP_MATH) && \ - defined(WOLFSSL_HAVE_SP_DH) || (defined(HAVE_ECC) && defined(FP_ECC))) +#if defined(WOLFSSL_KEY_GEN) && (!defined(WOLFSSL_SP_MATH_ALL) || \ + !defined(NO_RSA)) if ((ret = mp_test_lcm_gcd(&a, &b, &r1, &r2, &rng)) != 0) return ret; #endif @@ -33907,7 +36535,7 @@ WOLFSSL_TEST_SUBROUTINE int mutex_test(void) #if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) -#ifndef WOLFSSL_NO_MALLOC +#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_STATIC_MEMORY) static int malloc_cnt = 0; static int realloc_cnt = 0; static int free_cnt = 0; @@ -33950,7 +36578,7 @@ static void *my_Realloc_cb(void *ptr, size_t size) WOLFSSL_TEST_SUBROUTINE int memcb_test(void) { int ret = 0; -#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) +#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_STATIC_MEMORY) byte* b = NULL; #endif wolfSSL_Malloc_cb mc; @@ -33961,7 +36589,8 @@ WOLFSSL_TEST_SUBROUTINE int memcb_test(void) if (wolfSSL_GetAllocators(&mc, &fc, &rc) != 0) return -13800; -#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) +#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_STATIC_MEMORY) + /* test realloc */ b = (byte*)XREALLOC(b, 1024, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (b == NULL) { @@ -33971,9 +36600,9 @@ WOLFSSL_TEST_SUBROUTINE int memcb_test(void) b = NULL; /* Use API. */ - if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)(void*)&my_Malloc_cb, - (wolfSSL_Free_cb)(void*)&my_Free_cb, - (wolfSSL_Realloc_cb)(void*)&my_Realloc_cb) != 0) { + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)my_Malloc_cb, + (wolfSSL_Free_cb)my_Free_cb, + (wolfSSL_Realloc_cb)my_Realloc_cb) != 0) { ERROR_OUT(-13802, exit_memcb); } @@ -33989,7 +36618,7 @@ WOLFSSL_TEST_SUBROUTINE int memcb_test(void) ret = -13803; #endif /* !WOLFSSL_NO_MALLOC */ -#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) +#if !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_STATIC_MEMORY) exit_memcb: #endif @@ -34029,6 +36658,7 @@ WOLFSSL_TEST_SUBROUTINE int blob_test(void) XMEMSET(blob, 0, sizeof(blob)); + XMEMSET(out, 0, sizeof(out)); outSz = sizeof(blob); ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz); if (ret != 0) { @@ -34481,6 +37111,10 @@ WOLFSSL_TEST_SUBROUTINE int cryptocb_test(void) ret = pbkdf2_test(); #endif #endif +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) + if (ret == 0) + ret = cmac_test(); +#endif /* reset devId */ devId = INVALID_DEVID; diff --git a/wolfcrypt/test/test.h b/wolfcrypt/test/test.h index 7a6fc7c84..07a0c21b8 100644 --- a/wolfcrypt/test/test.h +++ b/wolfcrypt/test/test.h @@ -1,6 +1,6 @@ /* wolfcrypt/test/test.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/test/test_paths.h.in b/wolfcrypt/test/test_paths.h.in index e4428c459..7a9d3a173 100644 --- a/wolfcrypt/test/test_paths.h.in +++ b/wolfcrypt/test/test_paths.h.in @@ -1,6 +1,6 @@ /* wolfcrypt/test/test_paths.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/user-crypto/README.txt b/wolfcrypt/user-crypto/README.txt index 00b772f7b..6966a1712 100644 --- a/wolfcrypt/user-crypto/README.txt +++ b/wolfcrypt/user-crypto/README.txt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/user-crypto/include/user_rsa.h b/wolfcrypt/user-crypto/include/user_rsa.h index 59fc85d14..f22f87bc5 100644 --- a/wolfcrypt/user-crypto/include/user_rsa.h +++ b/wolfcrypt/user-crypto/include/user_rsa.h @@ -1,6 +1,6 @@ /* user_rsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/user-crypto/src/rsa.c b/wolfcrypt/user-crypto/src/rsa.c index a9f5afd8b..0ff20ff86 100644 --- a/wolfcrypt/user-crypto/src/rsa.c +++ b/wolfcrypt/user-crypto/src/rsa.c @@ -1,6 +1,6 @@ /* rsa.c * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -1644,7 +1644,7 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, { int sz, pSz, qSz; IppStatus ret; - word32 outSz = outLen; + word32 outSz; IppsMontState* pMont = NULL; IppsMontState* qMont = NULL; diff --git a/wolfssl.rc b/wolfssl.rc index cd9a6fa84..6ddc1103c 100644 Binary files a/wolfssl.rc and b/wolfssl.rc differ diff --git a/wolfssl.vcproj b/wolfssl.vcproj index ebf0007da..fd40a6b3a 100755 --- a/wolfssl.vcproj +++ b/wolfssl.vcproj @@ -359,6 +359,10 @@ RelativePath=".\wolfcrypt\src\sp_x86_64.c" >
    + + diff --git a/wolfssl.vcxproj b/wolfssl.vcxproj index d890f8cc9..a02d696da 100644 --- a/wolfssl.vcxproj +++ b/wolfssl.vcxproj @@ -295,14 +295,18 @@ + + + + @@ -357,6 +361,20 @@ $(OutDir)%(Filename).obj $(IntDir)%(Filename).obj + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + diff --git a/wolfssl/callbacks.h b/wolfssl/callbacks.h index eed27293c..a2a691687 100644 --- a/wolfssl/callbacks.h +++ b/wolfssl/callbacks.h @@ -1,6 +1,6 @@ /* callbacks.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/certs_test.h b/wolfssl/certs_test.h index 9c6fd4a76..fabf967eb 100644 --- a/wolfssl/certs_test.h +++ b/wolfssl/certs_test.h @@ -1028,6 +1028,157 @@ static const unsigned char dh_key_der_2048[] = }; static const int sizeof_dh_key_der_2048 = sizeof(dh_key_der_2048); +static const unsigned char dh_pub_key_der_2048[] = +{ + 0x30, 0x82, 0x02, 0x24, 0x30, 0x82, 0x01, 0x17, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x03, 0x01, 0x30, + 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xD3, 0xB2, + 0x99, 0x84, 0x5C, 0x0A, 0x4C, 0xE7, 0x37, 0xCC, 0xFC, 0x18, + 0x37, 0x01, 0x2F, 0x5D, 0xC1, 0x4C, 0xF4, 0x5C, 0xC9, 0x82, + 0x8D, 0xB7, 0xF3, 0xD4, 0xA9, 0x8A, 0x9D, 0x34, 0xD7, 0x76, + 0x57, 0xE5, 0xE5, 0xC3, 0xE5, 0x16, 0x85, 0xCA, 0x4D, 0xD6, + 0x5B, 0xC1, 0xF8, 0xCF, 0x89, 0x26, 0xD0, 0x38, 0x8A, 0xEE, + 0xF3, 0xCD, 0x33, 0xE5, 0x56, 0xBB, 0x90, 0x83, 0x9F, 0x97, + 0x8E, 0x71, 0xFB, 0x27, 0xE4, 0x35, 0x15, 0x45, 0x86, 0x09, + 0x71, 0xA8, 0x9A, 0xB9, 0x3E, 0x0F, 0x51, 0x8A, 0xC2, 0x75, + 0x51, 0x23, 0x12, 0xFB, 0x94, 0x31, 0x44, 0xBF, 0xCE, 0xF6, + 0xED, 0xA6, 0x3A, 0xB7, 0x92, 0xCE, 0x16, 0xA9, 0x14, 0xB3, + 0x88, 0xB7, 0x13, 0x81, 0x71, 0x83, 0x88, 0xCD, 0xB1, 0xA2, + 0x37, 0xE1, 0x59, 0x5C, 0xD0, 0xDC, 0xCA, 0x82, 0x87, 0xFA, + 0x43, 0x44, 0xDD, 0x78, 0x3F, 0xCA, 0x27, 0x7E, 0xE1, 0x6B, + 0x93, 0x19, 0x7C, 0xD9, 0xA6, 0x96, 0x47, 0x0D, 0x12, 0xC1, + 0x13, 0xD7, 0xB9, 0x0A, 0x40, 0xD9, 0x1F, 0xFF, 0xB8, 0xB4, + 0x00, 0xC8, 0xAA, 0x5E, 0xD2, 0x66, 0x4A, 0x05, 0x8E, 0x9E, + 0xF5, 0x34, 0xE7, 0xD7, 0x09, 0x7B, 0x15, 0x49, 0x1D, 0x76, + 0x31, 0xD6, 0x71, 0xEC, 0x13, 0x4E, 0x89, 0x8C, 0x09, 0x22, + 0xD8, 0xE7, 0xA3, 0xE9, 0x7D, 0x21, 0x51, 0x26, 0x6E, 0x9F, + 0x30, 0x8A, 0xBB, 0xBC, 0x74, 0xC1, 0xC3, 0x27, 0x6A, 0xCE, + 0xA3, 0x12, 0x60, 0x68, 0x01, 0xD2, 0x34, 0x07, 0x80, 0xCC, + 0x2D, 0x7F, 0x5C, 0xAE, 0xA2, 0x97, 0x40, 0xC8, 0x3C, 0xAC, + 0xDB, 0x6F, 0xFE, 0x6C, 0x6D, 0xD2, 0x06, 0x1C, 0x43, 0xA2, + 0xB2, 0x2B, 0x82, 0xB7, 0xD0, 0xAB, 0x3F, 0x2C, 0xE7, 0x9C, + 0x19, 0x16, 0xD1, 0x5E, 0x26, 0x86, 0xC7, 0x92, 0xF9, 0x16, + 0x0B, 0xFA, 0x66, 0x83, 0x02, 0x01, 0x02, 0x03, 0x82, 0x01, + 0x05, 0x00, 0x02, 0x82, 0x01, 0x00, 0x34, 0x41, 0xBF, 0xE9, + 0xF2, 0x11, 0xBF, 0x05, 0xDB, 0xB2, 0x72, 0xA8, 0x29, 0xCC, + 0xBD, 0x93, 0xEB, 0x14, 0x5D, 0x2C, 0x6B, 0x84, 0x4E, 0x96, + 0x12, 0xB3, 0x38, 0xBA, 0x8A, 0x46, 0x7C, 0x36, 0xCB, 0xE9, + 0x97, 0x70, 0xC5, 0xC3, 0x85, 0xB5, 0x51, 0xA5, 0x8B, 0x39, + 0xA8, 0xEA, 0x47, 0xD3, 0xD5, 0x11, 0xC0, 0x6D, 0xE3, 0xE3, + 0x9E, 0x00, 0x4C, 0x65, 0x41, 0x9B, 0xF6, 0xD0, 0xAC, 0x26, + 0x88, 0x01, 0xFC, 0x3C, 0x26, 0x5F, 0x67, 0xF7, 0x77, 0xD7, + 0xAC, 0xC5, 0xCA, 0xBB, 0xD8, 0x70, 0x58, 0x41, 0xF5, 0xF1, + 0x21, 0x3B, 0x15, 0xD5, 0x31, 0xF2, 0xC4, 0x8E, 0x0C, 0x38, + 0x01, 0x93, 0xD3, 0x64, 0x63, 0x57, 0xDC, 0x31, 0xE5, 0xFD, + 0x9C, 0x2B, 0xA6, 0xDE, 0x15, 0xB2, 0xC8, 0x8D, 0x65, 0x71, + 0x2E, 0xED, 0xF9, 0x1D, 0x2D, 0xA1, 0x17, 0xDD, 0xA3, 0xDA, + 0xF3, 0x10, 0x81, 0x40, 0xFA, 0x4F, 0x49, 0xB0, 0xDA, 0x16, + 0x64, 0xBE, 0x6F, 0xC5, 0x05, 0xCE, 0xC4, 0x4F, 0x67, 0x80, + 0xB3, 0x8A, 0x81, 0x17, 0xEB, 0xF9, 0x6F, 0x6D, 0x9F, 0x7F, + 0xDE, 0xEE, 0x08, 0xB8, 0xFA, 0x81, 0x68, 0x66, 0xD6, 0xC6, + 0x08, 0x50, 0xAB, 0xF0, 0x29, 0xDE, 0x6B, 0x1D, 0x50, 0x13, + 0x7F, 0x54, 0x31, 0x53, 0x89, 0x5F, 0x48, 0x72, 0x24, 0xD4, + 0xD2, 0x1D, 0x27, 0x7D, 0x74, 0xCF, 0x51, 0x17, 0xF0, 0xC5, + 0x6D, 0x3C, 0x3D, 0x6D, 0x0A, 0x8B, 0xDB, 0xEF, 0x02, 0xD8, + 0xC3, 0xCB, 0xCA, 0x21, 0xCA, 0xD6, 0x9C, 0x18, 0x9E, 0x92, + 0xBE, 0x6E, 0xE2, 0x16, 0x5E, 0x89, 0x9B, 0xAD, 0xD4, 0x04, + 0x5A, 0x24, 0x5A, 0x3F, 0x7C, 0x12, 0xAC, 0xB4, 0x71, 0x51, + 0x25, 0x58, 0x74, 0xE4, 0xB2, 0xD4, 0x45, 0xFC, 0x5F, 0xCD, + 0x81, 0x8F, 0xE7, 0x96, 0x18, 0xD9, 0xE0, 0x97, 0x08, 0x45, + 0x36, 0xC3 +}; +static const int sizeof_dh_pub_key_der_2048 = sizeof(dh_pub_key_der_2048); + +static const unsigned char dsa_pub_key_der_2048[] = +{ + 0x30, 0x82, 0x03, 0x47, 0x30, 0x82, 0x02, 0x39, 0x06, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01, 0x30, 0x82, 0x02, + 0x2C, 0x02, 0x82, 0x01, 0x01, 0x00, 0xEB, 0x7E, 0x2C, 0x97, + 0x36, 0x67, 0x0E, 0x73, 0x9A, 0xAC, 0xFD, 0xB1, 0x19, 0x03, + 0x52, 0x61, 0x25, 0x12, 0xB2, 0x37, 0x3D, 0xEA, 0xCA, 0x80, + 0x07, 0x5D, 0x2D, 0x33, 0xA2, 0x4E, 0x6B, 0xB7, 0x62, 0xF8, + 0x87, 0x4D, 0x4B, 0x20, 0xDA, 0xEA, 0x6A, 0x96, 0x13, 0xB7, + 0xB9, 0x49, 0xC0, 0x86, 0x14, 0x71, 0xCD, 0x8C, 0x60, 0x61, + 0x94, 0x71, 0x89, 0x95, 0x1A, 0x0F, 0x38, 0xCC, 0x9C, 0x1F, + 0x20, 0xE5, 0xD0, 0x65, 0x75, 0xCD, 0xFE, 0x24, 0x29, 0xE6, + 0x60, 0x97, 0x74, 0xEC, 0x4C, 0x42, 0xE8, 0xBA, 0xE9, 0xC2, + 0xF7, 0xCB, 0x9B, 0xEA, 0x55, 0xD8, 0x40, 0x50, 0x2E, 0xCF, + 0xCD, 0x41, 0x01, 0xA9, 0xE5, 0x29, 0xCA, 0xC3, 0x36, 0x58, + 0x7E, 0x2E, 0x11, 0x96, 0x87, 0xC6, 0xFA, 0xE1, 0x27, 0x53, + 0x3D, 0x60, 0x93, 0x7B, 0xAD, 0xEE, 0xE7, 0xD4, 0xDC, 0xD6, + 0x03, 0x16, 0x92, 0xD4, 0x51, 0x0C, 0xFD, 0xA9, 0x01, 0x3E, + 0x6E, 0x27, 0x67, 0x6E, 0x9F, 0x29, 0x63, 0xFD, 0x51, 0x82, + 0x79, 0x83, 0x2B, 0xCB, 0x12, 0xCD, 0x50, 0x92, 0xAC, 0x16, + 0xC9, 0xEA, 0x9E, 0x68, 0x9E, 0x4B, 0xE1, 0x63, 0xB4, 0x80, + 0xE4, 0xDF, 0x75, 0xBC, 0x27, 0xD1, 0x76, 0x03, 0x48, 0x98, + 0x1D, 0xE3, 0x29, 0x8A, 0x99, 0x59, 0xF3, 0x75, 0x5B, 0xD9, + 0xAC, 0x59, 0x11, 0x52, 0x2F, 0xE0, 0x91, 0x55, 0xB0, 0xF2, + 0x5F, 0x0A, 0xF8, 0xD2, 0x7A, 0xDD, 0x8D, 0xE9, 0x92, 0xE2, + 0xF3, 0xF7, 0x4A, 0xB1, 0x50, 0xD7, 0xFE, 0x07, 0x8D, 0x27, + 0x7D, 0x08, 0x6F, 0x08, 0x7E, 0x25, 0x19, 0x0D, 0xDE, 0x11, + 0xD1, 0x63, 0x31, 0x84, 0x18, 0x25, 0xBE, 0x7D, 0x64, 0x77, + 0xDB, 0x4A, 0x20, 0xC5, 0x51, 0x75, 0xD8, 0xB1, 0x1B, 0xDF, + 0x91, 0x7F, 0xFC, 0x74, 0xBA, 0x9D, 0xD1, 0xFA, 0x8D, 0xBD, + 0x59, 0xFD, 0x02, 0x21, 0x00, 0xFA, 0xF7, 0x62, 0x9A, 0x62, + 0x19, 0x64, 0x6D, 0xC1, 0xF3, 0xC0, 0x9B, 0xAC, 0x90, 0x28, + 0xEA, 0xA1, 0x83, 0xF9, 0xC8, 0xED, 0x31, 0xEE, 0x33, 0x1D, + 0x35, 0x22, 0x00, 0x2B, 0x12, 0x84, 0xFF, 0x02, 0x82, 0x01, + 0x00, 0x73, 0xC9, 0xED, 0x1F, 0xBC, 0xC7, 0xC4, 0xEF, 0x46, + 0x03, 0xD1, 0x72, 0xC3, 0xE5, 0x29, 0xB0, 0x9A, 0x95, 0x13, + 0x5B, 0x4E, 0x59, 0x57, 0x0F, 0x80, 0xEB, 0x74, 0x87, 0x11, + 0x1B, 0xC8, 0x11, 0xB6, 0x97, 0x4C, 0x48, 0x50, 0x3A, 0xB8, + 0x2C, 0x28, 0xF3, 0xB0, 0x9C, 0x7C, 0x3D, 0xFF, 0x8B, 0x43, + 0x43, 0x30, 0x85, 0x5F, 0x97, 0xD2, 0x68, 0x85, 0x35, 0x2E, + 0xD4, 0x61, 0xF6, 0x3E, 0x05, 0xEC, 0xCD, 0x60, 0x13, 0xE2, + 0x16, 0x02, 0x7C, 0x8B, 0x21, 0xCE, 0x36, 0x71, 0xC4, 0xED, + 0x0B, 0x47, 0x76, 0x83, 0x23, 0x2F, 0x98, 0xA4, 0x84, 0x98, + 0x9C, 0xFB, 0xD0, 0xA8, 0xD9, 0xB9, 0xE3, 0xD7, 0x32, 0xD9, + 0xB5, 0x9E, 0x82, 0x93, 0xD0, 0x55, 0x74, 0x5F, 0xDA, 0x87, + 0x91, 0x90, 0x0F, 0x85, 0x74, 0x1A, 0x32, 0x76, 0x4F, 0xCC, + 0x2A, 0x18, 0x11, 0x5B, 0xB4, 0x78, 0x93, 0xB6, 0xE5, 0xF0, + 0xC6, 0x71, 0xE8, 0xD7, 0x31, 0x19, 0x91, 0x27, 0x71, 0x5A, + 0x02, 0x1A, 0x1A, 0x3A, 0x55, 0x95, 0xFF, 0xF8, 0xED, 0xD3, + 0xE1, 0xAE, 0x8A, 0x1D, 0xFF, 0x53, 0x63, 0x79, 0x13, 0xA1, + 0xAD, 0x0A, 0x68, 0x67, 0x43, 0xB2, 0x5B, 0xD5, 0x36, 0xD4, + 0x84, 0xD0, 0xCD, 0x34, 0x82, 0x84, 0xA4, 0x89, 0xAE, 0xA1, + 0x66, 0x57, 0x89, 0x6F, 0xDC, 0x0C, 0x3B, 0x48, 0x14, 0x7C, + 0xCC, 0x63, 0x7C, 0x83, 0x93, 0x55, 0x7D, 0xB4, 0xF3, 0x34, + 0x66, 0x72, 0x85, 0xF5, 0x8D, 0xEF, 0x90, 0x1A, 0x66, 0xF8, + 0x3B, 0xC6, 0xA4, 0x59, 0xB8, 0x25, 0x4E, 0x5D, 0x84, 0xED, + 0x7C, 0x1C, 0xDD, 0x35, 0xA6, 0xBA, 0xED, 0x3B, 0xD6, 0x49, + 0xE6, 0x5A, 0xD1, 0xF8, 0xEA, 0x96, 0x75, 0x92, 0xCF, 0x05, + 0x52, 0x05, 0x3D, 0x78, 0x09, 0xCF, 0xCD, 0xE2, 0x1A, 0x99, + 0xEB, 0x5E, 0xFA, 0x27, 0x73, 0x89, 0x15, 0x03, 0x82, 0x01, + 0x06, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC2, 0x35, 0x2D, + 0xEC, 0x83, 0x83, 0x6C, 0x73, 0x13, 0x9E, 0x52, 0x7C, 0x74, + 0xC8, 0x7B, 0xEE, 0xDF, 0x39, 0xC0, 0x33, 0xCD, 0x9F, 0xB2, + 0x22, 0x64, 0x9F, 0xC5, 0xE9, 0xFF, 0xF7, 0x09, 0x47, 0x79, + 0x13, 0x96, 0x77, 0x25, 0xF3, 0x5D, 0xAA, 0x9F, 0x97, 0x67, + 0x62, 0xBC, 0x94, 0x1D, 0xAE, 0x22, 0x7E, 0x08, 0x03, 0xBD, + 0x7E, 0x34, 0x29, 0xCB, 0x62, 0xB7, 0x82, 0x1D, 0xE2, 0xFA, + 0x05, 0xC6, 0xC1, 0x68, 0xE7, 0x01, 0x27, 0x63, 0x51, 0x3E, + 0x37, 0x59, 0x42, 0x92, 0x4F, 0x99, 0x60, 0xFD, 0x63, 0x94, + 0xB7, 0xD0, 0xEE, 0xC1, 0xA0, 0xA5, 0x01, 0x74, 0x4D, 0x0E, + 0x14, 0xB2, 0xE2, 0x2C, 0xE7, 0x82, 0x0A, 0x23, 0xC7, 0x39, + 0x45, 0x40, 0xE9, 0xE9, 0x9D, 0x36, 0xE0, 0x52, 0x03, 0x99, + 0xDC, 0x87, 0x7D, 0x6A, 0x90, 0xE4, 0xDD, 0xA9, 0xC2, 0x57, + 0x90, 0xD6, 0xCA, 0xB4, 0x15, 0x80, 0xEE, 0x00, 0xCB, 0x2A, + 0xC9, 0x59, 0x4C, 0xA7, 0x7D, 0x33, 0x0A, 0x3E, 0x4A, 0x76, + 0xEA, 0x27, 0x89, 0xD8, 0x1A, 0xEA, 0x7E, 0xDB, 0x13, 0x92, + 0x93, 0x6A, 0x57, 0x9B, 0x33, 0xFD, 0xCE, 0x09, 0x0A, 0xB0, + 0x35, 0x24, 0xE4, 0x7D, 0xD8, 0x9D, 0xFF, 0x80, 0x65, 0x0F, + 0x61, 0xF7, 0xF7, 0xED, 0x8B, 0xD5, 0x8F, 0xBF, 0xB3, 0x22, + 0x20, 0x39, 0x89, 0x83, 0xB8, 0x83, 0x96, 0x32, 0x20, 0xAD, + 0xA1, 0x5D, 0x73, 0x8F, 0xE3, 0x27, 0xD9, 0x5D, 0xDB, 0x00, + 0x27, 0xF2, 0xBE, 0x89, 0x13, 0xE2, 0x97, 0x79, 0x10, 0x27, + 0x3D, 0xD8, 0x05, 0x96, 0x59, 0x6E, 0xA0, 0xC1, 0x6F, 0x99, + 0x4F, 0x28, 0xFA, 0xA6, 0x0B, 0x5C, 0x16, 0xEE, 0xB0, 0x98, + 0x8A, 0x06, 0x4A, 0xB0, 0x02, 0x2A, 0x6D, 0xCC, 0xE2, 0xC8, + 0x11, 0xF9, 0x1B, 0xF1, 0x3C, 0x68, 0xDF, 0xC2, 0xF4, 0x98, + 0x5F, 0x6C, 0xC8 +}; +static const int sizeof_dsa_pub_key_der_2048 = sizeof(dsa_pub_key_der_2048); + /* ./certs/dsa2048.der, 2048-bit */ static const unsigned char dsa_key_der_2048[] = { diff --git a/wolfssl/crl.h b/wolfssl/crl.h index 363d77cb9..308f2a8ad 100644 --- a/wolfssl/crl.h +++ b/wolfssl/crl.h @@ -1,6 +1,6 @@ /* crl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 88c47b9c6..0c3399d3e 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -1,6 +1,6 @@ /* error-ssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -170,6 +170,9 @@ enum wolfSSL_ErrorCodes { DTLS_SIZE_ERROR = -439, /* Trying to send too much data */ NO_CERT_ERROR = -440, /* TLS1.3 - no cert set error */ APP_DATA_READY = -441, /* DTLS1.2 application data ready for read */ + TOO_MUCH_EARLY_DATA = -442, /* Too much Early data */ + + SOCKET_FILTERED_E = -443, /* Session stopped by network filter */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d4f68a815..00bf17de9 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1,6 +1,6 @@ /* internal.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -59,6 +59,9 @@ #ifdef HAVE_POLY1305 #include #endif +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && defined(OPENSSL_EXTRA) + #include +#endif #ifdef HAVE_CAMELLIA #include #endif @@ -1154,7 +1157,8 @@ enum { #endif /* WOLFSSL_MULTICAST */ #ifndef WOLFSSL_MAX_MTU - #define WOLFSSL_MAX_MTU 1500 + /* 1500 - 100 bytes to account for UDP and IP headers */ + #define WOLFSSL_MAX_MTU 1400 #endif /* WOLFSSL_MAX_MTU */ @@ -1245,7 +1249,7 @@ enum Misc { /* pre RSA and all master */ #if defined(WOLFSSL_MYSQL_COMPATIBLE) || \ (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS >= 16384) -#ifndef NO_PSK +#if !defined(NO_PSK) && defined(USE_FAST_MATH) ENCRYPT_LEN = (FP_MAX_BITS / 2 / 8) + MAX_PSK_ID_LEN + 2, #else ENCRYPT_LEN = 1024, /* allow 8192 bit static buffer */ @@ -1339,9 +1343,9 @@ enum Misc { DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */ DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */ DTLS_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ - DTLS_EXPORT_OPT_SZ = 60, /* amount of bytes used from Options */ + DTLS_EXPORT_OPT_SZ = 61, /* amount of bytes used from Options */ DTLS_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ - DTLS_EXPORT_OPT_SZ_3 = 59, /* amount of bytes used from Options */ + DTLS_EXPORT_OPT_SZ_3 = 60, /* amount of bytes used from Options */ DTLS_EXPORT_KEY_SZ = 325 + (DTLS_SEQ_SZ * 2), /* max amount of bytes used from Keys */ DTLS_EXPORT_MIN_KEY_SZ = 85 + (DTLS_SEQ_SZ * 2), @@ -1349,6 +1353,9 @@ enum Misc { DTLS_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */ DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ + DTLS_MTU_ADDITIONAL_READ_BUFFER = 100, /* Additional bytes to read so that + * we can work with a peer that has + * a slightly different MTU than us. */ MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ MAX_EXPORT_STATE_BUFFER = (DTLS_EXPORT_MIN_KEY_SZ) + (3 * DTLS_EXPORT_LEN), /* max size of buffer for exporting state */ @@ -1602,11 +1609,11 @@ enum Misc { /* Check chosen encryption is available. */ #if !(defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) && \ defined(WOLFSSL_TICKET_ENC_CHACHA20_POLY1305) - #error "ChaCha20-Poly1305 not availble for default ticket encryption" + #error "ChaCha20-Poly1305 not available for default ticket encryption" #endif #if !defined(HAVE_AESGCM) && (defined(WOLFSSL_TICKET_ENC_AES128_GCM) || \ defined(WOLFSSL_TICKET_ENC_AES256_GCM)) - #error "AES-GCM not availble for default ticket encryption" + #error "AES-GCM not available for default ticket encryption" #endif #ifndef WOLFSSL_TICKET_KEY_LIFETIME @@ -1681,6 +1688,21 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); #endif #endif +struct WOLFSSL_BY_DIR_HASH { + unsigned long hash_value; + int last_suffix; +}; + +struct WOLFSSL_BY_DIR_entry { + char* dir_name; + int dir_type; + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *hashes; +}; + +struct WOLFSSL_BY_DIR { + WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *dir_entry; + wolfSSL_Mutex lock; /* dir list lock */ +}; /* wolfSSL method type */ struct WOLFSSL_METHOD { @@ -1713,7 +1735,7 @@ WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites); #ifdef WOLFSSL_TLS13 -WOLFSSL_LOCAL int FindSuite(Suites* suites, byte first, byte second); +WOLFSSL_LOCAL byte SuiteMac(byte* suite); #endif WOLFSSL_LOCAL int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32); @@ -1870,7 +1892,7 @@ WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, int haveAnon, int tls1_2, int keySz); WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16, - word16, word16, word16, word16, word16, int); + word16, word16, word16, word16, word16, word16, int); WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); @@ -1880,11 +1902,15 @@ WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, unsigned char*, unsigned int); #ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_cs_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, + const char* cipherName); typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, char*, unsigned int, unsigned char*, unsigned int, - const char**); + const char** cipherName); typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, - unsigned char*, unsigned int, const char**); + unsigned char*, unsigned int, + const char** cipherName); #endif #endif /* PSK_TYPES_DEFINED */ #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ @@ -2063,6 +2089,11 @@ struct WOLFSSL_CERT_MANAGER { #endif #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum allowed ECC key size */ +#endif +#if defined(OPENSSL_EXTRA) + WOLFSSL_X509_STORE *x509_store_p; /* a pointer back to CTX x509 store */ + /* CTX has ownership and free this */ + /* with CTX free. */ #endif wolfSSL_Mutex refMutex; /* reference count mutex */ int refCount; /* reference count */ @@ -2281,9 +2312,9 @@ WOLFSSL_LOCAL int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset); #endif -WOLFSSL_LOCAL int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, - byte msgType, int* found); -WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, +WOLFSSL_LOCAL int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input, + word16 length, byte msgType, int* found); +WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, Suites *suites); #elif defined(HAVE_SNI) \ @@ -2585,7 +2616,7 @@ typedef struct Cookie { byte data; } Cookie; -WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, +WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, const byte* data, word16 len, byte* mac, byte macSz, int resp); @@ -2596,17 +2627,23 @@ typedef struct KeyShareEntry { word16 group; /* NamedGroup */ byte* ke; /* Key exchange data */ word32 keLen; /* Key exchange data length */ - void* key; /* Private key */ - word32 keyLen; /* Private key length */ + void* key; /* Key struct */ + word32 keyLen; /* Key size (bytes) */ byte* pubKey; /* Public key */ word32 pubKeyLen; /* Public key length */ +#ifndef NO_DH + byte* privKey; /* Private key - DH only */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + int lastRet; +#endif struct KeyShareEntry* next; /* List pointer */ } KeyShareEntry; WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, KeyShareEntry **kse); WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); -WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl, int* doHelloRetry); WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl); @@ -2639,7 +2676,7 @@ WOLFSSL_LOCAL int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, word16* pSz); WOLFSSL_LOCAL int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType, word16* pSz); -WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, +WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, const byte* identity, word16 len, word32 age, byte hmac, byte cipherSuite0, byte cipherSuite, byte resumption, @@ -2834,7 +2871,12 @@ struct WOLFSSL_CTX { byte sessionCtxSz; byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ CallbackInfoState* CBIS; /* used to get info about SSL state */ + WOLFSSL_X509_VERIFY_PARAM* param; /* verification parameters*/ #endif +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + NetworkFilterCallback_t AcceptFilter; + void *AcceptFilter_arg; +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; #ifdef WOLFSSL_DTLS @@ -2865,6 +2907,7 @@ struct WOLFSSL_CTX { wc_psk_client_callback client_psk_cb; /* client callback */ wc_psk_server_callback server_psk_cb; /* server callback */ #ifdef WOLFSSL_TLS13 + wc_psk_client_cs_callback client_psk_cs_cb; /* client callback */ wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ #endif @@ -2926,15 +2969,19 @@ struct WOLFSSL_CTX { #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) SessionTicketEncCb ticketEncCb; /* enc/dec session ticket Cb */ void* ticketEncCtx; /* session encrypt context */ + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) + ticketCompatCb ticketEncWrapCb; /* callback for OpenSSL ticket key callback */ + #endif int ticketHint; /* ticket hint in seconds */ #ifndef WOLFSSL_NO_DEF_TICKET_ENC_CB TicketEncCbCtx ticketKeyCtx; #endif #endif + #endif #ifdef HAVE_SUPPORTED_CURVES byte userCurves; /* indicates user called wolfSSL_CTX_UseSupportedCurve */ #endif -#endif #ifdef ATOMIC_USER CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */ CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */ @@ -2949,31 +2996,31 @@ struct WOLFSSL_CTX { CallbackEccSign EccSignCb; /* User EccSign Callback handler */ CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */ - #ifdef HAVE_ED25519 - /* User Ed25519Sign Callback handler */ - CallbackEd25519Sign Ed25519SignCb; - /* User Ed25519Verify Callback handler */ - CallbackEd25519Verify Ed25519VerifyCb; - #endif - #ifdef HAVE_CURVE25519 - /* User X25519 KeyGen Callback Handler */ - CallbackX25519KeyGen X25519KeyGenCb; - /* User X25519 SharedSecret Callback handler */ - CallbackX25519SharedSecret X25519SharedSecretCb; - #endif - #ifdef HAVE_ED448 - /* User Ed448Sign Callback handler */ - CallbackEd448Sign Ed448SignCb; - /* User Ed448Verify Callback handler */ - CallbackEd448Verify Ed448VerifyCb; - #endif - #ifdef HAVE_CURVE448 - /* User X448 KeyGen Callback Handler */ - CallbackX448KeyGen X448KeyGenCb; - /* User X448 SharedSecret Callback handler */ - CallbackX448SharedSecret X448SharedSecretCb; - #endif #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + /* User Ed25519Sign Callback handler */ + CallbackEd25519Sign Ed25519SignCb; + /* User Ed25519Verify Callback handler */ + CallbackEd25519Verify Ed25519VerifyCb; + #endif + #ifdef HAVE_CURVE25519 + /* User X25519 KeyGen Callback Handler */ + CallbackX25519KeyGen X25519KeyGenCb; + /* User X25519 SharedSecret Callback handler */ + CallbackX25519SharedSecret X25519SharedSecretCb; + #endif + #ifdef HAVE_ED448 + /* User Ed448Sign Callback handler */ + CallbackEd448Sign Ed448SignCb; + /* User Ed448Verify Callback handler */ + CallbackEd448Verify Ed448VerifyCb; + #endif + #ifdef HAVE_CURVE448 + /* User X448 KeyGen Callback Handler */ + CallbackX448KeyGen X448KeyGenCb; + /* User X448 SharedSecret Callback handler */ + CallbackX448SharedSecret X448SharedSecretCb; + #endif #ifndef NO_DH CallbackDhAgree DhAgreeCb; /* User DH Agree Callback handler */ #endif @@ -3014,6 +3061,10 @@ void FreeSSL_Ctx(WOLFSSL_CTX*); WOLFSSL_LOCAL void SSL_CtxResourceFree(WOLFSSL_CTX*); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data); +#endif + WOLFSSL_LOCAL int DeriveTlsKeys(WOLFSSL* ssl); WOLFSSL_LOCAL @@ -3473,7 +3524,11 @@ typedef struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; wc_psk_server_callback server_psk_cb; +#ifdef OPENSSL_EXTRA + wc_psk_use_session_cb_func session_psk_cb; +#endif #ifdef WOLFSSL_TLS13 + wc_psk_client_cs_callback client_psk_cs_cb; /* client callback */ wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ #endif @@ -3534,9 +3589,7 @@ typedef struct Options { #ifdef HAVE_POLY1305 word16 oldPoly:1; /* set when to use old rfc way of poly*/ #endif -#ifdef HAVE_ANON word16 haveAnon:1; /* User wants to allow Anon suites */ -#endif #ifdef HAVE_SESSION_TICKET word16 createTicket:1; /* Server to create new Ticket */ word16 useTicket:1; /* Use Ticket not session cache */ @@ -3689,6 +3742,8 @@ typedef struct Arrays { #define STACK_TYPE_X509_NAME 9 #define STACK_TYPE_CONF_VALUE 10 #define STACK_TYPE_X509_INFO 11 +#define STACK_TYPE_BY_DIR_entry 12 +#define STACK_TYPE_BY_DIR_hash 13 struct WOLFSSL_STACK { unsigned long num; /* number of nodes in stack @@ -3714,6 +3769,8 @@ struct WOLFSSL_STACK { void* generic; char* string; WOLFSSL_GENERAL_NAME* gn; + WOLFSSL_BY_DIR_entry* dir_entry; + WOLFSSL_BY_DIR_HASH* dir_hash; } data; void* heap; /* memory heap hint */ WOLFSSL_STACK* next; @@ -4048,6 +4105,10 @@ struct WOLFSSL { #ifdef OPENSSL_EXTRA byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ #endif +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + NetworkFilterCallback_t AcceptFilter; + void *AcceptFilter_arg; +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; #ifdef WOLFSSL_STATIC_MEMORY @@ -4316,27 +4377,27 @@ struct WOLFSSL { #endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC - void* EccKeyGenCtx; /* EccKeyGen Callback Context */ - void* EccSignCtx; /* Ecc Sign Callback Context */ - void* EccVerifyCtx; /* Ecc Verify Callback Context */ - void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ - #ifdef HAVE_ED25519 - void* Ed25519SignCtx; /* ED25519 Sign Callback Context */ - void* Ed25519VerifyCtx; /* ED25519 Verify Callback Context */ - #endif - #ifdef HAVE_CURVE25519 - void* X25519KeyGenCtx; /* X25519 KeyGen Callback Context */ - void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ - #endif - #ifdef HAVE_ED448 - void* Ed448SignCtx; /* ED448 Sign Callback Context */ - void* Ed448VerifyCtx; /* ED448 Verify Callback Context */ - #endif - #ifdef HAVE_CURVE448 - void* X448KeyGenCtx; /* X448 KeyGen Callback Context */ - void* X448SharedSecretCtx; /* X448 Pms Callback Context */ - #endif + void* EccKeyGenCtx; /* EccKeyGen Callback Context */ + void* EccSignCtx; /* Ecc Sign Callback Context */ + void* EccVerifyCtx; /* Ecc Verify Callback Context */ + void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + void* Ed25519SignCtx; /* ED25519 Sign Callback Context */ + void* Ed25519VerifyCtx; /* ED25519 Verify Callback Context */ + #endif + #ifdef HAVE_CURVE25519 + void* X25519KeyGenCtx; /* X25519 KeyGen Callback Context */ + void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ + #endif + #ifdef HAVE_ED448 + void* Ed448SignCtx; /* ED448 Sign Callback Context */ + void* Ed448VerifyCtx; /* ED448 Verify Callback Context */ + #endif + #ifdef HAVE_CURVE448 + void* X448KeyGenCtx; /* X448 KeyGen Callback Context */ + void* X448SharedSecretCtx; /* X448 Pms Callback Context */ + #endif #ifndef NO_DH void* DhAgreeCtx; /* DH Pms Callback Context */ #endif /* !NO_DH */ @@ -4365,11 +4426,12 @@ struct WOLFSSL { #ifdef WOLFSSL_EARLY_DATA EarlyDataState earlyData; word32 earlyDataSz; + byte earlyDataStatus; #endif #ifdef OPENSSL_ALL long verifyCallbackResult; #endif -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if defined(OPENSSL_EXTRA) WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */ WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */ #endif @@ -4692,6 +4754,8 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void); + + WOLFSSL_LOCAL int FindSuiteMac(WOLFSSL* ssl, byte* suite); #endif WOLFSSL_LOCAL word32 LowResTimer(void); @@ -4765,17 +4829,27 @@ WOLFSSL_LOCAL int SetDsaExternal(WOLFSSL_DSA* dsa); WOLFSSL_LOCAL int SetRsaExternal(WOLFSSL_RSA* rsa); WOLFSSL_LOCAL int SetRsaInternal(WOLFSSL_RSA* rsa); #endif + +typedef enum elem_set { + ELEMENT_P = 0x01, + ELEMENT_Q = 0x02, + ELEMENT_G = 0x04, + ELEMENT_PUB = 0x08, + ELEMENT_PRV = 0x10, +} Element_Set; +WOLFSSL_LOCAL int SetDhExternal_ex(WOLFSSL_DH *dh, int elm ); WOLFSSL_LOCAL int SetDhInternal(WOLFSSL_DH* dh); WOLFSSL_LOCAL int SetDhExternal(WOLFSSL_DH *dh); -#ifndef NO_DH +#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz); WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey, const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, - byte* agree, word32* agreeSz); + byte* agree, word32* agreeSz, + const byte* prime, word32 primeSz); #endif /* !NO_DH */ #ifdef HAVE_ECC @@ -4808,6 +4882,43 @@ WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey); WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev); #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +WOLFSSL_LOCAL int LoadCertByIssuer(WOLFSSL_X509_STORE* store, + X509_NAME* issuer, int Type); +#endif +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +WOLFSSL_LOCAL WOLFSSL_BY_DIR_HASH* wolfSSL_BY_DIR_HASH_new(void); +WOLFSSL_LOCAL void wolfSSL_BY_DIR_HASH_free(WOLFSSL_BY_DIR_HASH* dir_hash); +WOLFSSL_LOCAL WOLFSSL_STACK* wolfSSL_sk_BY_DIR_HASH_new_null(void); +WOLFSSL_LOCAL int wolfSSL_sk_BY_DIR_HASH_find( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, const WOLFSSL_BY_DIR_HASH* toFind); +WOLFSSL_LOCAL int wolfSSL_sk_BY_DIR_HASH_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk); +WOLFSSL_LOCAL WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk, int i); +WOLFSSL_LOCAL WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk); +WOLFSSL_LOCAL void wolfSSL_sk_BY_DIR_HASH_pop_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, + void (*f) (WOLFSSL_BY_DIR_HASH*)); +WOLFSSL_LOCAL void wolfSSL_sk_BY_DIR_HASH_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk); +WOLFSSL_LOCAL int wolfSSL_sk_BY_DIR_HASH_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, + WOLFSSL_BY_DIR_HASH* in); +/* WOLFSSL_BY_DIR_entry stuff */ +WOLFSSL_LOCAL WOLFSSL_BY_DIR_entry* wolfSSL_BY_DIR_entry_new(void); +WOLFSSL_LOCAL void wolfSSL_BY_DIR_entry_free(WOLFSSL_BY_DIR_entry* entry); +WOLFSSL_LOCAL WOLFSSL_STACK* wolfSSL_sk_BY_DIR_entry_new_null(void); +WOLFSSL_LOCAL int wolfSSL_sk_BY_DIR_entry_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk); +WOLFSSL_LOCAL WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk, int i); +WOLFSSL_LOCAL WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk); +WOLFSSL_LOCAL void wolfSSL_sk_BY_DIR_entry_pop_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry)* sk, + void (*f) (WOLFSSL_BY_DIR_entry*)); +WOLFSSL_LOCAL void wolfSSL_sk_BY_DIR_entry_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry) *sk); +WOLFSSL_LOCAL int wolfSSL_sk_BY_DIR_entry_push(WOLF_STACK_OF(wolfSSL_BY_DIR_entry)* sk, + WOLFSSL_BY_DIR_entry* in); +#endif /* OPENSSL_ALL && !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 61068601b..acdad5120 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -1,6 +1,6 @@ /* ocsp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/aes.h b/wolfssl/openssl/aes.h index f66b57411..0899943d5 100644 --- a/wolfssl/openssl/aes.h +++ b/wolfssl/openssl/aes.h @@ -1,6 +1,6 @@ /* aes.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -59,12 +59,20 @@ WOLFSSL_API void wolfSSL_AES_ecb_encrypt WOLFSSL_API void wolfSSL_AES_cfb128_encrypt (const unsigned char *in, unsigned char* out, size_t len, AES_KEY *key, unsigned char* iv, int* num, const int enc); +WOLFSSL_API int wolfSSL_AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); +WOLFSSL_API int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); #define AES_cbc_encrypt wolfSSL_AES_cbc_encrypt #define AES_ecb_encrypt wolfSSL_AES_ecb_encrypt #define AES_cfb128_encrypt wolfSSL_AES_cfb128_encrypt #define AES_set_encrypt_key wolfSSL_AES_set_encrypt_key #define AES_set_decrypt_key wolfSSL_AES_set_decrypt_key +#define AES_wrap_key wolfSSL_AES_wrap_key +#define AES_unwrap_key wolfSSL_AES_unwrap_key #ifdef WOLFSSL_AES_DIRECT WOLFSSL_API void wolfSSL_AES_encrypt diff --git a/wolfssl/openssl/asn1.h b/wolfssl/openssl/asn1.h index 8085f0c93..3d885defe 100644 --- a/wolfssl/openssl/asn1.h +++ b/wolfssl/openssl/asn1.h @@ -1,6 +1,6 @@ /* asn1.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/asn1t.h b/wolfssl/openssl/asn1t.h index 0ee58a2d5..98c2404db 100644 --- a/wolfssl/openssl/asn1t.h +++ b/wolfssl/openssl/asn1t.h @@ -1,6 +1,6 @@ /* asn1t.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/bio.h b/wolfssl/openssl/bio.h index c5786b73a..89ce4597f 100644 --- a/wolfssl/openssl/bio.h +++ b/wolfssl/openssl/bio.h @@ -1,6 +1,6 @@ /* bio.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -68,6 +68,7 @@ #define BIO_set_fp wolfSSL_BIO_set_fp #define BIO_get_fp wolfSSL_BIO_get_fp #define BIO_seek wolfSSL_BIO_seek +#define BIO_tell wolfSSL_BIO_tell #define BIO_write_filename wolfSSL_BIO_write_filename #define BIO_set_mem_eof_return wolfSSL_BIO_set_mem_eof_return diff --git a/wolfssl/openssl/bn.h b/wolfssl/openssl/bn.h index 324ae4f5a..0bc288005 100644 --- a/wolfssl/openssl/bn.h +++ b/wolfssl/openssl/bn.h @@ -1,6 +1,6 @@ /* bn.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/buffer.h b/wolfssl/openssl/buffer.h index 5f1946dda..9ffd99e3f 100644 --- a/wolfssl/openssl/buffer.h +++ b/wolfssl/openssl/buffer.h @@ -1,6 +1,6 @@ /* buffer.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/cms.h b/wolfssl/openssl/cms.h index e86a21f0a..a782abbfd 100644 --- a/wolfssl/openssl/cms.h +++ b/wolfssl/openssl/cms.h @@ -1,6 +1,6 @@ /* cms.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/conf.h b/wolfssl/openssl/conf.h index a56983ef1..a71bc07b5 100644 --- a/wolfssl/openssl/conf.h +++ b/wolfssl/openssl/conf.h @@ -1,6 +1,6 @@ /* conf.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/crypto.h b/wolfssl/openssl/crypto.h index f4da403b8..06128fe7f 100644 --- a/wolfssl/openssl/crypto.h +++ b/wolfssl/openssl/crypto.h @@ -1,6 +1,6 @@ /* crypto.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -46,11 +46,19 @@ WOLFSSL_API unsigned long wolfSSL_OpenSSL_version_num(void); #ifdef OPENSSL_EXTRA WOLFSSL_API void wolfSSL_OPENSSL_free(void*); WOLFSSL_API void *wolfSSL_OPENSSL_malloc(size_t a); +WOLFSSL_API int wolfSSL_OPENSSL_hexchar2int(unsigned char c); +WOLFSSL_API unsigned char *wolfSSL_OPENSSL_hexstr2buf(const char *str, long *len); WOLFSSL_API int wolfSSL_OPENSSL_init_crypto(word64 opts, const OPENSSL_INIT_SETTINGS *settings); #endif -#define CRYPTO_THREADID void +typedef struct WOLFSSL_CRYPTO_THREADID { + int dummy; +}WOLFSSL_CRYPTO_THREADID; +typedef struct crypto_threadid_st CRYPTO_THREADID; + +#define crypto_threadid_st WOLFSSL_CRYPTO_THREADID +#define CRYPTO_THREADID WOLFSSL_CRYPTO_THREADID #define SSLeay_version wolfSSLeay_version #define SSLeay wolfSSLeay @@ -69,6 +77,8 @@ WOLFSSL_API int wolfSSL_OPENSSL_init_crypto(word64 opts, const OPENSSL_INIT_SETT #define OPENSSL_free wolfSSL_OPENSSL_free #define OPENSSL_malloc wolfSSL_OPENSSL_malloc +#define OPENSSL_hexchar2int wolfSSL_OPENSSL_hexchar2int +#define OPENSSL_hexstr2buf wolfSSL_OPENSSL_hexstr2buf #define OPENSSL_INIT_ENGINE_ALL_BUILTIN 0x00000001L #define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L @@ -77,6 +87,15 @@ WOLFSSL_API int wolfSSL_OPENSSL_init_crypto(word64 opts, const OPENSSL_INIT_SETT #define OPENSSL_init_crypto wolfSSL_OPENSSL_init_crypto +#ifdef WOLFSSL_OPENVPN +# define OPENSSL_assert(e) \ + if (!(e)) { \ + fprintf(stderr, "%s:%d wolfSSL internal error: assertion failed: " #e, \ + __FILE__, __LINE__); \ + raise(SIGABRT); \ + _exit(3); \ + } +#endif #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_EX_DATA) @@ -88,6 +107,8 @@ typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int i long argl, void* argp); #define CRYPTO_THREADID_set_callback wolfSSL_THREADID_set_callback #define CRYPTO_THREADID_set_numeric wolfSSL_THREADID_set_numeric +#define CRYPTO_THREADID_current wolfSSL_THREADID_current +#define CRYPTO_THREADID_hash wolfSSL_THREADID_hash #define CRYPTO_r_lock wc_LockMutex_ex #define CRYPTO_unlock wc_LockMutex_ex @@ -96,6 +117,13 @@ typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int i #define CRYPTO_THREAD_r_lock wc_LockMutex #define CRYPTO_THREAD_unlock wc_UnLockMutex +#define CRYPTO_THREAD_lock_new wc_InitAndAllocMutex +#define CRYPTO_THREAD_read_lock wc_LockMutex +#define CRYPTO_THREAD_write_lock wc_LockMutex +#define CRYPTO_THREAD_lock_free wc_FreeMutex + +#define CRYPTO_set_ex_data wolfSSL_CRYPTO_set_ex_data + #endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_EX_DATA */ #endif /* header */ diff --git a/wolfssl/openssl/des.h b/wolfssl/openssl/des.h index 14d12ec3c..d7a6ef809 100644 --- a/wolfssl/openssl/des.h +++ b/wolfssl/openssl/des.h @@ -1,6 +1,6 @@ /* des.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/dh.h b/wolfssl/openssl/dh.h index 6fb896c84..0970f366f 100644 --- a/wolfssl/openssl/dh.h +++ b/wolfssl/openssl/dh.h @@ -1,6 +1,6 @@ /* dh.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -69,7 +69,7 @@ WOLFSSL_API int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* pub, WOLFSSL_API int wolfSSL_DH_LoadDer(WOLFSSL_DH*, const unsigned char*, int sz); WOLFSSL_API int wolfSSL_DH_set0_pqg(WOLFSSL_DH*, WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*); - + #define DH_new wolfSSL_DH_new #define DH_free wolfSSL_DH_free @@ -83,6 +83,7 @@ WOLFSSL_API int wolfSSL_DH_set0_pqg(WOLFSSL_DH*, WOLFSSL_BIGNUM*, #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L #define DH_set0_pqg wolfSSL_DH_set0_pqg #endif +#define DH_get0_pqg wolfSSL_DH_get0_pqg #define DH_bits(x) (BN_num_bits(x->p)) #define DH_GENERATOR_2 2 diff --git a/wolfssl/openssl/dsa.h b/wolfssl/openssl/dsa.h index 2729c09bd..6d6f5075b 100644 --- a/wolfssl/openssl/dsa.h +++ b/wolfssl/openssl/dsa.h @@ -1,6 +1,6 @@ /* dsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 80cebb5fc..aed85c63a 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -1,6 +1,6 @@ /* ec.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -192,6 +192,7 @@ WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid); WOLFSSL_API const char* wolfSSL_EC_curve_nid2nist(int nid); +WOLFSSL_API int wolfSSL_EC_curve_nist2nid(const char* name); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void); WOLFSSL_API @@ -351,6 +352,7 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, #define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves #define EC_curve_nid2nist wolfSSL_EC_curve_nid2nist +#define EC_curve_nist2nid wolfSSL_EC_curve_nist2nid #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/openssl/ec25519.h b/wolfssl/openssl/ec25519.h index 180eb8e83..f9cf3c9fc 100644 --- a/wolfssl/openssl/ec25519.h +++ b/wolfssl/openssl/ec25519.h @@ -1,6 +1,6 @@ /* ec25519.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ec448.h b/wolfssl/openssl/ec448.h index fb3b9005d..3f0b1b7b4 100644 --- a/wolfssl/openssl/ec448.h +++ b/wolfssl/openssl/ec448.h @@ -1,6 +1,6 @@ /* ec448.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ecdh.h b/wolfssl/openssl/ecdh.h index 7d7aa09ec..039e77071 100644 --- a/wolfssl/openssl/ecdh.h +++ b/wolfssl/openssl/ecdh.h @@ -1,6 +1,6 @@ /* ecdh.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ecdsa.h b/wolfssl/openssl/ecdsa.h index 77c1a18b0..8e5c873ca 100644 --- a/wolfssl/openssl/ecdsa.h +++ b/wolfssl/openssl/ecdsa.h @@ -1,6 +1,6 @@ /* ecdsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ed25519.h b/wolfssl/openssl/ed25519.h index 579c653f6..50683d4b8 100644 --- a/wolfssl/openssl/ed25519.h +++ b/wolfssl/openssl/ed25519.h @@ -1,6 +1,6 @@ /* ed25519.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ed448.h b/wolfssl/openssl/ed448.h index b9411e92c..4ff184fbf 100644 --- a/wolfssl/openssl/ed448.h +++ b/wolfssl/openssl/ed448.h @@ -1,6 +1,6 @@ /* ed448.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/engine.h b/wolfssl/openssl/engine.h index e4a1ff193..ba147ff74 100644 --- a/wolfssl/openssl/engine.h +++ b/wolfssl/openssl/engine.h @@ -4,5 +4,7 @@ #undef HAVE_OPENSSL_ENGINE_H -#define ENGINE_load_builtin_engines() /*ENGINE_load_builtin_engines not needed*/ +/* ENGINE_load_builtin_engines not needed, as all builtin engines are already + loaded into memory and used on startup. */ +#define ENGINE_load_builtin_engines() diff --git a/wolfssl/openssl/err.h b/wolfssl/openssl/err.h index cb1acc094..6ddf2d284 100644 --- a/wolfssl/openssl/err.h +++ b/wolfssl/openssl/err.h @@ -1,6 +1,6 @@ /* err.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index aa6c61b2a..fc92977b7 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -1,6 +1,6 @@ /* evp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -85,6 +85,7 @@ typedef WOLFSSL_EVP_PKEY PKCS8_PRIV_KEY_INFO; #ifndef NO_MD5 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void); #endif +WOLFSSL_API void wolfSSL_EVP_set_pw_prompt(const char *); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void); @@ -408,6 +409,10 @@ WOLFSSL_API int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, WOLFSSL_API int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char*out, int *outl); #endif /* WOLFSSL_BASE64_DECODE */ +typedef +struct WOLFSSL_ASN1_PCTX { + int dummy; +} WOLFSSL_ASN1_PCTX; typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE; @@ -418,6 +423,8 @@ typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX; #define EVP_PKEY_OP_DECRYPT (1 << 7) #define EVP_PKEY_OP_DERIVE (1 << 8) +#define EVP_PKEY_PRINT_INDENT_MAX 128 + WOLFSSL_API void wolfSSL_EVP_init(void); WOLFSSL_API int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md); WOLFSSL_API int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md); @@ -584,7 +591,11 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY **ppkey); WOLFSSL_API int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey); +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +WOLFSSL_API void wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx); +#else WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx); +#endif WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e); WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding); WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e); @@ -624,7 +635,7 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, WOLFSSL_ENGINE *impl); WOLFSSL_API int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len); WOLFSSL_API int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, - unsigned char* sig, unsigned int sig_len, WOLFSSL_EVP_PKEY *pkey); + const unsigned char* sig, unsigned int sig_len, WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type); WOLFSSL_API int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len); @@ -705,6 +716,7 @@ typedef WOLFSSL_EVP_MD EVP_MD; typedef WOLFSSL_EVP_CIPHER EVP_CIPHER; typedef WOLFSSL_EVP_MD_CTX EVP_MD_CTX; typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; +typedef WOLFSSL_ASN1_PCTX ASN1_PCTX; #ifndef NO_MD4 #define EVP_md4 wolfSSL_EVP_md4 @@ -712,14 +724,15 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #ifndef NO_MD5 #define EVP_md5 wolfSSL_EVP_md5 #endif -#define EVP_sha1 wolfSSL_EVP_sha1 -#define EVP_mdc2 wolfSSL_EVP_mdc2 -#define EVP_dds1 wolfSSL_EVP_sha1 -#define EVP_sha224 wolfSSL_EVP_sha224 -#define EVP_sha256 wolfSSL_EVP_sha256 -#define EVP_sha384 wolfSSL_EVP_sha384 -#define EVP_sha512 wolfSSL_EVP_sha512 -#define EVP_ripemd160 wolfSSL_EVP_ripemd160 +#define EVP_sha1 wolfSSL_EVP_sha1 +#define EVP_mdc2 wolfSSL_EVP_mdc2 +#define EVP_dds1 wolfSSL_EVP_sha1 +#define EVP_sha224 wolfSSL_EVP_sha224 +#define EVP_sha256 wolfSSL_EVP_sha256 +#define EVP_sha384 wolfSSL_EVP_sha384 +#define EVP_sha512 wolfSSL_EVP_sha512 +#define EVP_ripemd160 wolfSSL_EVP_ripemd160 +#define EVP_set_pw_prompt wolfSSL_EVP_set_pw_prompt #define EVP_sha3_224 wolfSSL_EVP_sha3_224 #define EVP_sha3_256 wolfSSL_EVP_sha3_256 @@ -773,6 +786,9 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_MD_CTX_size wolfSSL_EVP_MD_CTX_size #define EVP_MD_CTX_block_size wolfSSL_EVP_MD_CTX_block_size #define EVP_MD_type wolfSSL_EVP_MD_type +#ifndef NO_WOLFSSL_STUB +#define EVP_MD_CTX_set_flags(...) +#endif #define EVP_Digest wolfSSL_EVP_Digest #define EVP_DigestInit wolfSSL_EVP_DigestInit @@ -935,6 +951,7 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG #define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED +#define EVP_PKEY_print_public wolfSSL_EVP_PKEY_print_public #define EVP_PKEY_print_private(arg1, arg2, arg3, arg4) #ifndef EVP_MAX_MD_SIZE @@ -966,7 +983,7 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_PKEY_NONE NID_undef #define EVP_PKEY_DH 28 -#define EVP_CIPHER_mode WOLFSSL_CIPHER_mode +#define EVP_CIPHER_mode WOLFSSL_EVP_CIPHER_mode /* WOLFSSL_EVP_CIPHER is just the string name of the cipher */ #define EVP_CIPHER_name(x) x #define EVP_MD_CTX_reset wolfSSL_EVP_MD_CTX_cleanup diff --git a/wolfssl/openssl/hmac.h b/wolfssl/openssl/hmac.h index d708fe1c6..8158afa9a 100644 --- a/wolfssl/openssl/hmac.h +++ b/wolfssl/openssl/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/lhash.h b/wolfssl/openssl/lhash.h index ee0fba18e..98256888a 100644 --- a/wolfssl/openssl/lhash.h +++ b/wolfssl/openssl/lhash.h @@ -1,6 +1,6 @@ /* lhash.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/md4.h b/wolfssl/openssl/md4.h index aafe9cc17..10a6d642b 100644 --- a/wolfssl/openssl/md4.h +++ b/wolfssl/openssl/md4.h @@ -1,6 +1,6 @@ /* md4.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/md5.h b/wolfssl/openssl/md5.h index 49ac1e32f..bbbd1ca2f 100644 --- a/wolfssl/openssl/md5.h +++ b/wolfssl/openssl/md5.h @@ -1,6 +1,6 @@ /* md5.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -52,13 +52,14 @@ typedef struct WOLFSSL_MD5_CTX { WOLFSSL_API int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX*); WOLFSSL_API int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX*, const void*, unsigned long); WOLFSSL_API int wolfSSL_MD5_Final(unsigned char*, WOLFSSL_MD5_CTX*); - +WOLFSSL_API int wolfSSL_MD5_Transform(WOLFSSL_MD5_CTX*, const unsigned char*); typedef WOLFSSL_MD5_CTX MD5_CTX; #define MD5_Init wolfSSL_MD5_Init #define MD5_Update wolfSSL_MD5_Update #define MD5_Final wolfSSL_MD5_Final +#define MD5_Transform wolfSSL_MD5_Transform #ifdef OPENSSL_EXTRA_BSD #define MD5Init wolfSSL_MD5_Init diff --git a/wolfssl/openssl/obj_mac.h b/wolfssl/openssl/obj_mac.h index 6d0f90047..0544d6b1a 100644 --- a/wolfssl/openssl/obj_mac.h +++ b/wolfssl/openssl/obj_mac.h @@ -1,6 +1,6 @@ /* obj_mac.h * - * Copyright (C) 2006-2017 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -42,6 +42,8 @@ #define NID_sect571k1 733 #define NID_sect571r1 734 +/* the definition is for Qt Unit test */ +#define SN_jurisdictionCountryName "jurisdictionC" #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/objects.h b/wolfssl/openssl/objects.h index cd44b6628..3f975432b 100644 --- a/wolfssl/openssl/objects.h +++ b/wolfssl/openssl/objects.h @@ -1,6 +1,6 @@ /* objects.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ocsp.h b/wolfssl/openssl/ocsp.h index e934a51de..bc70f72d9 100644 --- a/wolfssl/openssl/ocsp.h +++ b/wolfssl/openssl/ocsp.h @@ -1,6 +1,6 @@ /* ocsp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index 4b32dcc7e..1a89b5915 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -1,6 +1,6 @@ /* opensslv.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -33,9 +33,11 @@ #elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100000L +#elif defined(WOLFSSL_QT) + #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ - defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENVPN) + defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_OPENVPN) /* version number can be increased for Lighty after compatibility for ECDH is added */ #define OPENSSL_VERSION_NUMBER 0x10001040L diff --git a/wolfssl/openssl/ossl_typ.h b/wolfssl/openssl/ossl_typ.h index 5e90ffe0c..9b1142e2f 100644 --- a/wolfssl/openssl/ossl_typ.h +++ b/wolfssl/openssl/ossl_typ.h @@ -1,6 +1,6 @@ /* ossl_typ.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 31c88d619..730fd0d60 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -1,6 +1,6 @@ /* pem.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/pkcs12.h b/wolfssl/openssl/pkcs12.h index 8f4011319..1eb0f3ee9 100644 --- a/wolfssl/openssl/pkcs12.h +++ b/wolfssl/openssl/pkcs12.h @@ -1,6 +1,6 @@ /* pkcs12.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/pkcs7.h b/wolfssl/openssl/pkcs7.h index 53ab4436e..0eb8a1caf 100644 --- a/wolfssl/openssl/pkcs7.h +++ b/wolfssl/openssl/pkcs7.h @@ -1,6 +1,6 @@ /* pkcs7.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/rand.h b/wolfssl/openssl/rand.h index 4b826f8f2..11af818f6 100644 --- a/wolfssl/openssl/rand.h +++ b/wolfssl/openssl/rand.h @@ -1,6 +1,6 @@ /* rand.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,4 +24,6 @@ #include #include +typedef WOLFSSL_RAND_METHOD RAND_METHOD; + #define RAND_set_rand_method wolfSSL_RAND_set_rand_method diff --git a/wolfssl/openssl/rc4.h b/wolfssl/openssl/rc4.h index fc11e5a12..9fc3ce1da 100644 --- a/wolfssl/openssl/rc4.h +++ b/wolfssl/openssl/rc4.h @@ -1,6 +1,6 @@ /* rc4.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ripemd.h b/wolfssl/openssl/ripemd.h index 3f1d26848..f7dea2879 100644 --- a/wolfssl/openssl/ripemd.h +++ b/wolfssl/openssl/ripemd.h @@ -1,6 +1,6 @@ /* ripemd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index af11c7bc3..fcbaa6c81 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -1,6 +1,6 @@ /* rsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -107,10 +107,11 @@ WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, unsigned char* to, WOLFSSL_RSA*, int padding); WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, unsigned char* to, WOLFSSL_RSA*, int padding); -WOLFSSL_API int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, +WOLFSSL_API int wolfSSL_RSA_private_encrypt(int len, const unsigned char* in, unsigned char* out, WOLFSSL_RSA* rsa, int padding); WOLFSSL_API int wolfSSL_RSA_size(const WOLFSSL_RSA*); +WOLFSSL_API int wolfSSL_RSA_bits(const WOLFSSL_RSA*); WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m, unsigned int mLen, unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA*); @@ -151,7 +152,13 @@ WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa); WOLFSSL_API void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx); WOLFSSL_API int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data); - +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_RSA_set_ex_data_with_cleanup( + WOLFSSL_RSA *rsa, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif #define WOLFSSL_RSA_LOAD_PRIVATE 1 #define WOLFSSL_RSA_LOAD_PUBLIC 2 diff --git a/wolfssl/openssl/sha.h b/wolfssl/openssl/sha.h index e3a814717..7120ecb17 100644 --- a/wolfssl/openssl/sha.h +++ b/wolfssl/openssl/sha.h @@ -1,6 +1,6 @@ /* sha.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -52,12 +52,14 @@ typedef struct WOLFSSL_SHA_CTX { WOLFSSL_API int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX*); WOLFSSL_API int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); WOLFSSL_API int wolfSSL_SHA_Final(unsigned char*, WOLFSSL_SHA_CTX*); - +WOLFSSL_API int wolfSSL_SHA_Transform(WOLFSSL_SHA_CTX*, + const unsigned char *data); /* SHA1 points to above, shouldn't use SHA0 ever */ WOLFSSL_API int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX*); WOLFSSL_API int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); WOLFSSL_API int wolfSSL_SHA1_Final(unsigned char*, WOLFSSL_SHA_CTX*); - +WOLFSSL_API int wolfSSL_SHA1_Transform(WOLFSSL_SHA_CTX*, + const unsigned char *data); enum { SHA_DIGEST_LENGTH = 20 }; @@ -68,11 +70,20 @@ typedef WOLFSSL_SHA_CTX SHA_CTX; #define SHA_Init wolfSSL_SHA_Init #define SHA_Update wolfSSL_SHA_Update #define SHA_Final wolfSSL_SHA_Final +#define SHA_Transform wolfSSL_SHA_Transform + +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) + /* SHA is only available in non-fips mode or fips version > 2 mode + * because of SHA enum in FIPS build. */ + #define SHA wolfSSL_SHA1 +#endif #define SHA1_Init wolfSSL_SHA1_Init #define SHA1_Update wolfSSL_SHA1_Update #define SHA1_Final wolfSSL_SHA1_Final - +#define SHA1_Transform wolfSSL_SHA1_Transform #ifdef WOLFSSL_SHA224 @@ -99,6 +110,13 @@ typedef WOLFSSL_SHA224_CTX SHA224_CTX; #define SHA224_Init wolfSSL_SHA224_Init #define SHA224_Update wolfSSL_SHA224_Update #define SHA224_Final wolfSSL_SHA224_Final +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION > 2)) + /* SHA224 is only available in non-fips mode or fips version > 2 mode + * because of SHA224 enum in FIPS build. */ + #define SHA224 wolfSSL_SHA224 +#endif #endif /* WOLFSSL_SHA224 */ @@ -113,9 +131,10 @@ typedef struct WOLFSSL_SHA256_CTX { WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); WOLFSSL_API int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*, - unsigned long); + unsigned long); WOLFSSL_API int wolfSSL_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*); - +WOLFSSL_API int wolfSSL_SHA256_Transform(WOLFSSL_SHA256_CTX*, + const unsigned char *data); enum { SHA256_DIGEST_LENGTH = 32 }; @@ -126,6 +145,8 @@ typedef WOLFSSL_SHA256_CTX SHA256_CTX; #define SHA256_Init wolfSSL_SHA256_Init #define SHA256_Update wolfSSL_SHA256_Update #define SHA256_Final wolfSSL_SHA256_Final +#define SHA256_Transform wolfSSL_SHA256_Transform + #if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) /* SHA256 is only available in non-fips mode because of SHA256 enum in FIPS * build. */ @@ -171,9 +192,10 @@ typedef struct WOLFSSL_SHA512_CTX { WOLFSSL_API int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX*); WOLFSSL_API int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX*, const void*, - unsigned long); + unsigned long); WOLFSSL_API int wolfSSL_SHA512_Final(unsigned char*, WOLFSSL_SHA512_CTX*); - +WOLFSSL_API int wolfSSL_SHA512_Transform(WOLFSSL_SHA512_CTX*, + const unsigned char*); enum { SHA512_DIGEST_LENGTH = 64 }; @@ -184,6 +206,7 @@ typedef WOLFSSL_SHA512_CTX SHA512_CTX; #define SHA512_Init wolfSSL_SHA512_Init #define SHA512_Update wolfSSL_SHA512_Update #define SHA512_Final wolfSSL_SHA512_Final +#define SHA512_Transform wolfSSL_SHA512_Transform #if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) /* SHA512 is only available in non-fips mode because of SHA512 enum in FIPS * build. */ diff --git a/wolfssl/openssl/sha3.h b/wolfssl/openssl/sha3.h index 2039104d2..75bed13cf 100644 --- a/wolfssl/openssl/sha3.h +++ b/wolfssl/openssl/sha3.h @@ -1,6 +1,6 @@ /* sha3.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/srp.h b/wolfssl/openssl/srp.h index 7b5bd96b4..f6aaec2fc 100644 --- a/wolfssl/openssl/srp.h +++ b/wolfssl/openssl/srp.h @@ -1,6 +1,6 @@ /* srp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 52718b7a9..660155302 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -137,8 +137,8 @@ typedef WOLFSSL_X509_VERIFY_PARAM X509_VERIFY_PARAM; #define CONF_get1_default_config_file wolfSSL_CONF_get1_default_config_file typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; -#define CRYPTO_free(xp) XFREE(xp, NULL, DYNAMIC_TYPE_TMP_BUFFER) -#define CRYPTO_malloc(sz) XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER) +#define CRYPTO_free wolfSSL_CRYPTO_free +#define CRYPTO_malloc wolfSSL_CRYPTO_malloc #define CRYPTO_EX_new WOLFSSL_CRYPTO_EX_new #define CRYPTO_EX_dup WOLFSSL_CRYPTO_EX_dup #define CRYPTO_EX_free WOLFSSL_CRYPTO_EX_free @@ -164,6 +164,9 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define set_ex_data wolfSSL_CRYPTO_set_ex_data #define get_ex_data wolfSSL_CRYPTO_get_ex_data #define CRYPTO_memcmp wolfSSL_CRYPTO_memcmp +#define CRYPTO_get_ex_new_index wolfSSL_CRYPTO_get_ex_new_index + +#define CRYPTO_get_ex_new_index wolfSSL_CRYPTO_get_ex_new_index /* this function was used to set the default malloc, free, and realloc */ #define CRYPTO_malloc_init() 0 /* CRYPTO_malloc_init is not needed */ @@ -191,6 +194,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define i2d_PKCS8PrivateKey_bio wolfSSL_PEM_write_bio_PKCS8PrivateKey #define PKCS8_PRIV_KEY_INFO_free wolfSSL_EVP_PKEY_free #define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp +#define SSL_CTX_set_ecdh_auto wolfSSL_CTX_set_ecdh_auto #define i2d_PUBKEY wolfSSL_i2d_PUBKEY #define d2i_PUBKEY wolfSSL_d2i_PUBKEY @@ -304,7 +308,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_CTX_set_ciphersuites wolfSSL_CTX_set_cipher_list #define SSL_set_cipher_list wolfSSL_set_cipher_list /* wolfSSL does not support security levels */ -#define SSL_CTX_set_security_level(...) +#define SSL_CTX_set_security_level wolfSSL_CTX_set_security_level +#define SSL_CTX_get_security_level wolfSSL_CTX_get_security_level /* wolfSSL does not support exporting keying material */ #define SSL_export_keying_material wolfSSL_export_keying_material @@ -328,6 +333,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_SESSION_up_ref wolfSSL_SESSION_up_ref #define SSL_SESSION_dup wolfSSL_SESSION_dup #define SSL_SESSION_free wolfSSL_SESSION_free +#define SSL_SESSION_set_cipher wolfSSL_SESSION_set_cipher #define SSL_is_init_finished wolfSSL_is_init_finished #define SSL_get_version wolfSSL_get_version @@ -367,6 +373,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define DSA_dup_DH wolfSSL_DSA_dup_DH /* wolfSSL does not support DSA as the cert public key */ #define EVP_PKEY_get0_DSA wolfSSL_EVP_PKEY_get0_DSA +#define EVP_PKEY_param_check wolfSSL_EVP_PKEY_param_check +#define EVP_PKEY_CTX_free wolfSSL_EVP_PKEY_CTX_free #define DSA_bits wolfSSL_DSA_bits #define i2d_X509_bio wolfSSL_i2d_X509_bio @@ -409,6 +417,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_free wolfSSL_X509_free #define X509_load_certificate_file wolfSSL_X509_load_certificate_file #define X509_digest wolfSSL_X509_digest +#define X509_pubkey_digest wolfSSL_X509_pubkey_digest #define X509_get_ext_count wolfSSL_X509_get_ext_count #define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i #define X509V3_EXT_i2d wolfSSL_X509V3_EXT_i2d @@ -427,8 +436,10 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_REQ_get_pubkey wolfSSL_X509_get_pubkey #define X509_get_notBefore wolfSSL_X509_get_notBefore #define X509_get0_notBefore wolfSSL_X509_get_notBefore +#define X509_getm_notBefore wolfSSL_X509_get_notBefore #define X509_get_notAfter wolfSSL_X509_get_notAfter #define X509_get0_notAfter wolfSSL_X509_get_notAfter +#define X509_getm_notAfter wolfSSL_X509_get_notAfter #define X509_get_serialNumber wolfSSL_X509_get_serialNumber #define X509_get0_pubkey_bitstr wolfSSL_X509_get0_pubkey_bitstr #define X509_get_ex_new_index wolfSSL_X509_get_ex_new_index @@ -464,6 +475,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_REQ_check_private_key wolfSSL_X509_check_private_key #define X509_check_ca wolfSSL_X509_check_ca #define X509_check_host wolfSSL_X509_check_host +#define X509_check_email wolfSSL_X509_check_email #define X509_check_ip_asc wolfSSL_X509_check_ip_asc #define X509_email_free wolfSSL_X509_email_free #define X509_check_issued wolfSSL_X509_check_issued @@ -557,11 +569,18 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_V_FLAG_NO_CHECK_TIME WOLFSSL_NO_CHECK_TIME #define X509_CHECK_FLAG_NO_WILDCARDS WOLFSSL_NO_WILDCARDS +#define X509_VP_FLAG_DEFAULT WOLFSSL_VPARAM_DEFAULT +#define X509_VP_FLAG_OVERWRITE WOLFSSL_VPARAM_OVERWRITE +#define X509_VP_FLAG_RESET_FLAGS WOLFSSL_VPARAM_RESET_FLAGS +#define X509_VP_FLAG_LOCKED WOLFSSL_VPARAM_LOCKED +#define X509_VP_FLAG_ONCE WOLFSSL_VPARAM_ONCE + #define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert #define X509_STORE_CTX_set_verify_cb wolfSSL_X509_STORE_CTX_set_verify_cb #define X509_STORE_CTX_new wolfSSL_X509_STORE_CTX_new #define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free #define X509_STORE_CTX_get_chain wolfSSL_X509_STORE_CTX_get_chain +#define X509_STORE_CTX_get0_chain wolfSSL_X509_STORE_CTX_get_chain #define X509_STORE_CTX_get1_chain wolfSSL_X509_STORE_CTX_get1_chain #define X509_STORE_CTX_get0_parent_ctx wolfSSL_X509_STORE_CTX_get0_parent_ctx #define X509_STORE_CTX_get_error wolfSSL_X509_STORE_CTX_get_error @@ -594,6 +613,8 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_STORE_set_flags wolfSSL_X509_STORE_set_flags #define X509_STORE_get1_certs wolfSSL_X509_STORE_get1_certs #define X509_STORE_get_by_subject wolfSSL_X509_STORE_get_by_subject +#define X509_STORE_set_ex_data wolfSSL_X509_STORE_set_ex_data +#define X509_STORE_get_ex_data wolfSSL_X509_STORE_get_ex_data #define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer #define X509_STORE_CTX_set_time wolfSSL_X509_STORE_CTX_set_time #define X509_VERIFY_PARAM_new wolfSSL_X509_VERIFY_PARAM_new @@ -604,6 +625,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_VERIFY_PARAM_set_hostflags wolfSSL_X509_VERIFY_PARAM_set_hostflags #define X509_VERIFY_PARAM_set1_host wolfSSL_X509_VERIFY_PARAM_set1_host #define X509_VERIFY_PARAM_set1_ip_asc wolfSSL_X509_VERIFY_PARAM_set1_ip_asc +#define X509_VERIFY_PARAM_set1 wolfSSL_X509_VERIFY_PARAM_set1 #define X509_STORE_load_locations wolfSSL_X509_STORE_load_locations #define X509_LOOKUP_add_dir wolfSSL_X509_LOOKUP_add_dir @@ -621,6 +643,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_CRL_get_nextUpdate wolfSSL_X509_CRL_get_nextUpdate #define X509_CRL_verify wolfSSL_X509_CRL_verify #define X509_CRL_get_REVOKED wolfSSL_X509_CRL_get_REVOKED +#define X509_load_crl_file wolfSSL_X509_load_crl_file #define X509_get_X509_PUBKEY wolfSSL_X509_get_X509_PUBKEY #define X509_REQ_get_X509_PUBKEY wolfSSL_X509_get_X509_PUBKEY @@ -671,11 +694,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size #define BIO_f_ssl wolfSSL_BIO_f_ssl #define BIO_new_socket wolfSSL_BIO_new_socket -#ifndef NO_WOLFSSL_STUB #define BIO_new_connect wolfSSL_BIO_new_connect #define BIO_set_conn_port wolfSSL_BIO_set_conn_port #define BIO_do_connect wolfSSL_BIO_do_connect -#endif +#define BIO_do_handshake wolfSSL_BIO_do_handshake #define SSL_set_bio wolfSSL_set_bio #define BIO_set_ssl wolfSSL_BIO_set_ssl #define BIO_eof wolfSSL_BIO_eof @@ -750,7 +772,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define ASN1_STRING_free wolfSSL_ASN1_STRING_free #define ASN1_STRING_cmp wolfSSL_ASN1_STRING_cmp #define ASN1_STRING_data wolfSSL_ASN1_STRING_data -#define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data +#define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_get0_data #define ASN1_STRING_length wolfSSL_ASN1_STRING_length #define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 #define ASN1_UNIVERSALSTRING_to_string wolfSSL_ASN1_UNIVERSALSTRING_to_string @@ -797,7 +819,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define RSA_generate_key wolfSSL_RSA_generate_key #define SSL_CTX_set_tmp_rsa_callback wolfSSL_CTX_set_tmp_rsa_callback #define RSA_print wolfSSL_RSA_print -#define RSA_bits wolfSSL_RSA_size +#define RSA_bits wolfSSL_RSA_bits #define RSA_up_ref wolfSSL_RSA_up_ref #define RSA_padding_add_PKCS1_PSS wolfSSL_RSA_padding_add_PKCS1_PSS #define RSA_verify_PKCS1_PSS wolfSSL_RSA_verify_PKCS1_PSS @@ -917,8 +939,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define sk_num wolfSSL_sk_num #define sk_ASN1_OBJECT_num wolfSSL_sk_num +#define OPENSSL_sk_num wolfSSL_sk_num #define sk_value wolfSSL_sk_value #define sk_ASN1_OBJECT_value wolfSSL_sk_value +#define OPENSSL_sk_value wolfSSL_sk_value #define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio #define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp @@ -1070,6 +1094,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_min_proto_version wolfSSL_CTX_set_min_proto_version #define SSL_CTX_set_max_proto_version wolfSSL_CTX_set_max_proto_version +#define SSL_CTX_get_min_proto_version wolfSSL_CTX_get_min_proto_version #define SSL_get_tlsext_status_exts wolfSSL_get_tlsext_status_exts @@ -1080,6 +1105,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 #define SSL_CTRL_SET_TMP_DH 3 #define SSL_CTRL_SET_TMP_ECDH 4 +#define SSL_CTRL_SET_SESS_CACHE_MODE 44 #define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 @@ -1088,6 +1114,12 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 +#define SSL_CTRL_SET_GROUPS 91 +#define SSL_CTRL_GET_PEER_TMP_KEY 109 +#define SSL_CTRL_GET_SERVER_TMP_KEY SSL_CTRL_GET_PEER_TMP_KEY +#define SSL_CTRL_SET_MIN_PROTO_VERSION 123 +#define SSL_CTRL_SET_MAX_PROTO_VERSION 124 +#define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS #define SSL_CTRL_EXTRA_CHAIN_CERT 14 #define SSL_CTRL_OPTIONS 32 @@ -1117,6 +1149,22 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define DTLS1_VERSION 0xFEFF #define DTLS1_2_VERSION 0xFEFD +#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L +#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L + +#define CRYPTO_EX_INDEX_SSL 0 +#define TLS_ANY_VERSION 0x10000 +#define DTLS1_2_VERSION 0xFEFD +#define DTLS_MAX_VERSION DTLS1_2_VERSION + +#ifndef WOLFSSL_APACHE_HTTPD /* apache uses SSL_CONF_FLAG_FILE to enable conf support */ +#define SSL_CONF_FLAG_CMDLINE WOLFSSL_CONF_FLAG_CMDLINE +#define SSL_CONF_FLAG_FILE WOLFSSL_CONF_FLAG_FILE +#define SSL_CONF_FLAG_CERTIFICATE WOLFSSL_CONF_FLAG_CERTIFICATE +#define SSL_CONF_TYPE_STRING WOLFSSL_CONF_TYPE_STRING +#define SSL_CONF_TYPE_FILE WOLFSSL_CONF_TYPE_FILE +#endif + #if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(OPENSSL_EXTRA) \ || defined(OPENSSL_ALL) #include @@ -1126,6 +1174,9 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL3_AD_BAD_CERTIFICATE bad_certificate #define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE +#define SSL_AD_UNRECOGNIZED_NAME unrecognized_name +#define SSL_AD_NO_RENEGOTIATION no_renegotiation +#define SSL_AD_INTERNAL_ERROR 80 #define ASN1_STRFLGS_ESC_MSB 4 @@ -1166,6 +1217,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL3_AL_FATAL 2 #define SSL_TLSEXT_ERR_OK 0 #define SSL_TLSEXT_ERR_ALERT_FATAL alert_fatal +#define SSL_TLSEXT_ERR_ALERT_WARNING alert_warning #define SSL_TLSEXT_ERR_NOACK alert_warning #define TLSEXT_NAMETYPE_host_name WOLFSSL_SNI_HOST_NAME @@ -1220,7 +1272,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_ALL) || \ - defined(HAVE_LIGHTY) + defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) #include @@ -1253,6 +1305,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_R_HTTPS_PROXY_REQUEST PARSE_ERROR #define SSL_R_HTTP_REQUEST PARSE_ERROR #define SSL_R_UNSUPPORTED_PROTOCOL VERSION_ERROR +#define SSL_R_CERTIFICATE_VERIFY_FAILED VERIFY_CERT_ERROR #ifdef HAVE_SESSION_TICKET @@ -1265,7 +1318,6 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define OPENSSL_cleanse wolfSSL_OPENSSL_cleanse #define SSL_CTX_get_timeout wolfSSL_SSL_CTX_get_timeout #define SSL_CTX_set_tmp_ecdh wolfSSL_SSL_CTX_set_tmp_ecdh -#define SSL_CTX_set_ecdh_auto(...) #define SSL_CTX_remove_session wolfSSL_SSL_CTX_remove_session #define SSL_get_rbio wolfSSL_SSL_get_rbio #define SSL_get_wbio wolfSSL_SSL_get_wbio @@ -1305,6 +1357,8 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_srp_strength wolfSSL_CTX_set_srp_strength #define SSL_get_SSL_CTX wolfSSL_get_SSL_CTX #define SSL_get0_param wolfSSL_get0_param +#define SSL_CTX_get0_param wolfSSL_CTX_get0_param +#define SSL_CTX_set1_param wolfSSL_CTX_set1_param #define SSL_get_srp_username wolfSSL_get_srp_username #define ERR_NUM_ERRORS 16 @@ -1316,6 +1370,11 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_get_rbio wolfSSL_SSL_get_rbio #define SSL_get_wbio wolfSSL_SSL_get_wbio #define SSL_do_handshake wolfSSL_SSL_do_handshake + +#if defined(WOLFSSL_EARLY_DATA) +#define SSL_get_early_data_status wolfSSL_get_early_data_status +#endif + #endif /* OPENSSL_EXTRA */ /* cipher suites for compatibility */ @@ -1334,13 +1393,27 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define sk_X509_OBJECT_delete wolfSSL_sk_X509_OBJECT_delete #define X509_OBJECT_free wolfSSL_X509_OBJECT_free #define X509_OBJECT_get_type(x) 0 - +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +#define OpenSSL_version(x) wolfSSL_OpenSSL_version(x) +#else #define OpenSSL_version(x) wolfSSL_OpenSSL_version() +#endif #ifndef NO_WOLFSSL_STUB #define OBJ_create_objects(...) #endif +#define SSL_set_psk_use_session_callback wolfSSL_set_psk_use_session_callback +#define SSL_SESSION_is_resumable wolfSSL_SESSION_is_resumable +typedef WOLFSSL_CONF_CTX SSL_CONF_CTX; + +#define SSL_CONF_CTX_new wolfSSL_CONF_CTX_new +#define SSL_CONF_CTX_free wolfSSL_CONF_CTX_free +#define SSL_CONF_CTX_set_ssl_ctx wolfSSL_CONF_CTX_set_ssl_ctx +#define SSL_CONF_CTX_set_flags wolfSSL_CONF_CTX_set_flags +#define SSL_CONF_CTX_finish wolfSSL_CONF_CTX_finish +#define SSL_CONF_cmd wolfSSL_CONF_cmd + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/stack.h b/wolfssl/openssl/stack.h index 559a79670..8040574fe 100644 --- a/wolfssl/openssl/stack.h +++ b/wolfssl/openssl/stack.h @@ -1,6 +1,6 @@ /* stack.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/tls1.h b/wolfssl/openssl/tls1.h index b73a8b0a2..51923f693 100644 --- a/wolfssl/openssl/tls1.h +++ b/wolfssl/openssl/tls1.h @@ -1,6 +1,6 @@ /* tls1.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/txt_db.h b/wolfssl/openssl/txt_db.h index a3e0fd362..a7459589b 100644 --- a/wolfssl/openssl/txt_db.h +++ b/wolfssl/openssl/txt_db.h @@ -1,6 +1,6 @@ /* txt_db.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/x509_vfy.h b/wolfssl/openssl/x509_vfy.h index 86c995b43..bb61ba0b7 100644 --- a/wolfssl/openssl/x509_vfy.h +++ b/wolfssl/openssl/x509_vfy.h @@ -1,6 +1,6 @@ /* x509_vfy.h * - * Copyright (C) 2006-2017 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/openssl/x509v3.h b/wolfssl/openssl/x509v3.h index 75e128a4f..db471dd8d 100644 --- a/wolfssl/openssl/x509v3.h +++ b/wolfssl/openssl/x509v3.h @@ -1,6 +1,6 @@ /* x509v3.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/options.h.in b/wolfssl/options.h.in index 0a5f45c23..c67095c9c 100644 --- a/wolfssl/options.h.in +++ b/wolfssl/options.h.in @@ -1,6 +1,6 @@ /* options.h.in * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index f18415a9e..fb48498a4 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -1,6 +1,6 @@ /* sniffer.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index f2710522f..a0788f9bc 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -1,6 +1,6 @@ /* sniffer_error.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,6 +24,13 @@ #ifndef WOLFSSL_SNIFFER_ERROR_H #define WOLFSSL_SNIFFER_ERROR_H + +/* General Sniffer Error */ +#define WOLFSSL_SNIFFER_ERROR -1 + +/* Sniffer failed and is in Fatal state */ +#define WOLFSSL_SNIFFER_FATAL_ERROR -2 + /* need to have errors as #defines since .rc files can't handle enums */ /* need to start at 1 and go in order for same reason */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 0c81c9b77..d4f15652f 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -143,6 +143,10 @@ typedef struct WOLFSSL_X509_STORE_CTX WOLFSSL_X509_STORE_CTX; typedef int (*WOLFSSL_X509_STORE_CTX_verify_cb)(int, WOLFSSL_X509_STORE_CTX *); +typedef struct WOLFSSL_BY_DIR_HASH WOLFSSL_BY_DIR_HASH; +typedef struct WOLFSSL_BY_DIR_entry WOLFSSL_BY_DIR_entry; +typedef struct WOLFSSL_BY_DIR WOLFSSL_BY_DIR; + /* redeclare guard */ #define WOLFSSL_TYPES_DEFINED @@ -208,6 +212,8 @@ typedef struct WOLFSSL_AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID; typedef struct WOLFSSL_BASIC_CONSTRAINTS WOLFSSL_BASIC_CONSTRAINTS; typedef struct WOLFSSL_ACCESS_DESCRIPTION WOLFSSL_ACCESS_DESCRIPTION; +typedef struct WOLFSSL_CONF_CTX WOLFSSL_CONF_CTX; + #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) struct WOLFSSL_AUTHORITY_KEYID { @@ -276,8 +282,6 @@ struct WOLFSSL_X509V3_CTX { WOLFSSL_X509* x509; }; - - struct WOLFSSL_ASN1_OBJECT { void* heap; const unsigned char* obj; @@ -531,6 +535,8 @@ struct WOLFSSL_X509_LOOKUP_METHOD { struct WOLFSSL_X509_LOOKUP { WOLFSSL_X509_STORE *store; + int type; + WOLFSSL_BY_DIR* dirs; }; struct WOLFSSL_X509_STORE { @@ -563,8 +569,16 @@ struct WOLFSSL_X509_STORE { #define WOLFSSL_USE_CHECK_TIME 0x2 #define WOLFSSL_NO_CHECK_TIME 0x200000 #define WOLFSSL_HOST_NAME_MAX 256 + +#define WOLFSSL_VPARAM_DEFAULT 0x1 +#define WOLFSSL_VPARAM_OVERWRITE 0x2 +#define WOLFSSL_VPARAM_RESET_FLAGS 0x4 +#define WOLFSSL_VPARAM_LOCKED 0x8 +#define WOLFSSL_VPARAM_ONCE 0x10 + struct WOLFSSL_X509_VERIFY_PARAM { time_t check_time; + unsigned int inherit_flags; unsigned long flags; char hostName[WOLFSSL_HOST_NAME_MAX]; unsigned int hostFlags; @@ -631,6 +645,25 @@ struct WOLFSSL_X509_STORE_CTX { typedef char* WOLFSSL_STRING; +typedef struct WOLFSSL_RAND_METHOD { + /* seed = Data to mix into the random generator. + * len = Number of bytes to mix from seed. */ + int (*seed)(const void* seed, int len); + /* buf = Buffer to store random bytes in. + * len = Number of bytes to store in buf. */ + int (*bytes)(unsigned char* buf, int len); + void (*cleanup)(void); + /* add = Data to mix into the random generator. + * len = Number of bytes to mix from add. + * entropy = Estimate of randomness contained in seed. + * Should be between 0 and len. */ + int (*add)(const void* add, int len, double entropy); + /* buf = Buffer to store pseudorandom bytes in. + * len = Number of bytes to store in buf. */ + int (*pseudorand)(unsigned char *buf, int len); + int (*status)(void); +} WOLFSSL_RAND_METHOD; + /* Valid Alert types from page 16/17 * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c */ @@ -674,6 +707,29 @@ enum AlertLevel { alert_fatal = 2 }; +/* WS_RETURN_CODE macro + * Some OpenSSL APIs specify "0" as the return value when an error occurs. + * However, some corresponding wolfSSL APIs return negative values. Such + * functions should use this macro to fill this gap. Users who want them + * to return the same return value as OpenSSL can define + * WOLFSSL_ERR_CODE_OPENSSL. + * Give item1 a variable that contains the potentially negative + * wolfSSL-defined return value or the return value itself, and + * give item2 the openSSL-defined return value. + * Note that this macro replaces only negative return values with the + * specified value. + * Since wolfSSL 4.7.0, the following functions use this macro: + * - wolfSSL_CTX_load_verify_locations + * - wolfSSL_X509_LOOKUP_load_file + * - wolfSSL_EVP_PKEY_cmp + */ +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + #define WS_RETURN_CODE(item1,item2) \ + ((item1 < 0) ? item2 : item1) +#else + #define WS_RETURN_CODE(item1,item2) (item1) +#endif + /* Maximum master key length (SECRET_LEN) */ #define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 /* Maximum number of groups that can be set */ @@ -874,10 +930,13 @@ WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap); WOLFSSL_ABI WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); #ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff); #endif WOLFSSL_ABI WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl); +WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx); WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm); WOLFSSL_API int wolfSSL_is_server(WOLFSSL*); WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*); WOLFSSL_ABI WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int); @@ -914,6 +973,7 @@ WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_key_update_response(WOLFSSL* ssl, int* required); WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl); @@ -936,6 +996,11 @@ WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*); #ifdef WOLFSSL_EARLY_DATA + +#define WOLFSSL_EARLY_DATA_NOT_SENT 0 +#define WOLFSSL_EARLY_DATA_REJECTED 1 +#define WOLFSSL_EARLY_DATA_ACCEPTED 2 + WOLFSSL_API int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz); WOLFSSL_API int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz); @@ -943,6 +1008,7 @@ WOLFSSL_API int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz); WOLFSSL_API int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz); +WOLFSSL_API int wolfSSL_get_early_data_status(const WOLFSSL* ssl); #endif /* WOLFSSL_EARLY_DATA */ #endif /* WOLFSSL_TLS13 */ WOLFSSL_ABI WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); @@ -997,6 +1063,25 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session); typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); typedef void (CallbackInfoState)(const WOLFSSL*, int, int); +/* class index for wolfSSL_CRYPTO_get_ex_new_index */ +#define CRYPTO_EX_INDEX_SSL 0 +#define CRYPTO_EX_INDEX_SSL_CTX 1 +#define CRYPTO_EX_INDEX_SSL_SESSION 2 +#define CRYPTO_EX_INDEX_X509 3 +#define CRYPTO_EX_INDEX_X509_STORE 4 +#define CRYPTO_EX_INDEX_X509_STORE_CTX 5 +#define CRYPTO_EX_INDEX_DH 6 +#define CRYPTO_EX_INDEX_DSA 7 +#define CRYPTO_EX_INDEX_EC_KEY 8 +#define CRYPTO_EX_INDEX_RSA 9 +#define CRYPTO_EX_INDEX_ENGINE 10 +#define CRYPTO_EX_INDEX_UI 11 +#define CRYPTO_EX_INDEX_BIO 12 +#define CRYPTO_EX_INDEX_APP 13 +#define CRYPTO_EX_INDEX_UI_METHOD 14 +#define CRYPTO_EX_INDEX_DRBG 15 +#define CRYPTO_EX_INDEX__COUNT 16 + #if defined(HAVE_EX_DATA) || defined(FORTRESS) typedef int (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr, WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); @@ -1008,6 +1093,7 @@ typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr, WOLFSSL_API int wolfSSL_get_ex_new_index(long argValue, void* arg, WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b, WOLFSSL_CRYPTO_EX_free* c); + #endif WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, @@ -1077,6 +1163,29 @@ WOLFSSL_API int wolfSSL_export_keying_material(WOLFSSL *ssl, int use_context); #endif /* HAVE_KEYING_MATERIAL */ +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + +typedef enum { + WOLFSSL_NETFILTER_PASS = 0, + WOLFSSL_NETFILTER_ACCEPT = 1, + WOLFSSL_NETFILTER_REJECT = 2 +} wolfSSL_netfilter_decision_t; + +typedef int (*NetworkFilterCallback_t)( + WOLFSSL *ssl, + void *AcceptFilter_arg, + wolfSSL_netfilter_decision_t *decision); +WOLFSSL_API int wolfSSL_CTX_set_AcceptFilter( + WOLFSSL_CTX *ctx, + NetworkFilterCallback_t AcceptFilter, + void *AcceptFilter_arg); +WOLFSSL_API int wolfSSL_set_AcceptFilter( + WOLFSSL *ssl, + NetworkFilterCallback_t AcceptFilter, + void *AcceptFilter_arg); + +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + /* Nonblocking DTLS helper functions */ WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int); WOLFSSL_API int wolfSSL_dtls_get_using_nonblock(WOLFSSL*); @@ -1203,6 +1312,13 @@ WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSI WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value( WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx); WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_set_ex_data_with_cleanup( + WOLFSSL* ssl, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*); WOLFSSL_API int wolfSSL_set_rfd(WOLFSSL*, int); WOLFSSL_API int wolfSSL_set_wfd(WOLFSSL*, int); @@ -1216,6 +1332,8 @@ WOLFSSL_API int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new(void); WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); +WOLFSSL_API int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, + const WOLFSSL_CIPHER* cipher); WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL*); WOLFSSL_API const char* wolfSSL_get_version(const WOLFSSL*); @@ -1246,7 +1364,11 @@ WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void); WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void); WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void); +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(const WOLFSSL_BIO_METHOD*); +#else WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*); +#endif WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*); WOLFSSL_API void wolfSSL_BIO_vfree(WOLFSSL_BIO*); WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*); @@ -1281,6 +1403,13 @@ WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void); WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int); WOLFSSL_API void wolfSSL_BIO_clear_flags(WOLFSSL_BIO *bio, int flags); WOLFSSL_API int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_BIO_set_ex_data_with_cleanup( + WOLFSSL_BIO *bio, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif WOLFSSL_API void *wolfSSL_BIO_get_ex_data(WOLFSSL_BIO *bio, int idx); WOLFSSL_API long wolfSSL_BIO_set_nbio(WOLFSSL_BIO*, long); @@ -1324,6 +1453,8 @@ WOLFSSL_API WOLFSSL_BIO *wolfSSL_BIO_new_connect(const char *str); WOLFSSL_API long wolfSSL_BIO_set_conn_port(WOLFSSL_BIO *b, char* port); WOLFSSL_API long wolfSSL_BIO_do_connect(WOLFSSL_BIO *b); +WOLFSSL_API long wolfSSL_BIO_do_handshake(WOLFSSL_BIO *b); + WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); @@ -1336,6 +1467,7 @@ WOLFSSL_API int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); WOLFSSL_API int wolfSSL_BIO_reset(WOLFSSL_BIO *bio); WOLFSSL_API int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); +WOLFSSL_API int wolfSSL_BIO_tell(WOLFSSL_BIO* bio); WOLFSSL_API int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v); WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m); @@ -1378,6 +1510,8 @@ WOLFSSL_API void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n, unsigned char** out); +WOLFSSL_API int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, + unsigned char** out); WOLFSSL_API WOLFSSL_X509_NAME *wolfSSL_d2i_X509_NAME(WOLFSSL_X509_NAME **name, unsigned char **in, long length); #ifndef NO_RSA @@ -1455,7 +1589,11 @@ WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1); WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int dataSz); WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*); +WOLFSSL_API const unsigned char* wolfSSL_ASN1_STRING_get0_data( + const WOLFSSL_ASN1_STRING*); WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dst, + const WOLFSSL_ASN1_STRING* src); WOLFSSL_API int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*); WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long); WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*); @@ -1517,6 +1655,11 @@ WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key, unsigned char** in, long inSz); WOLFSSL_API int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der); +#if defined(OPENSSL_EXTRA) +WOLFSSL_API int wolfSSL_EVP_PKEY_print_public(WOLFSSL_BIO* out, + const WOLFSSL_EVP_PKEY* pkey, + int indent, WOLFSSL_ASN1_PCTX* pctx); +#endif /* OPENSSL_EXTRA */ WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); #ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, @@ -1543,6 +1686,12 @@ WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* p unsigned int nameSz); WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc( WOLFSSL_X509_VERIFY_PARAM *param, const char *ipasc); +WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1(WOLFSSL_X509_VERIFY_PARAM* to, + const WOLFSSL_X509_VERIFY_PARAM* from); +WOLFSSL_API int wolfSSL_X509_load_crl_file(WOLFSSL_X509_LOOKUP *ctx, + const char *file, int type); +WOLFSSL_API int wolfSSL_X509_load_cert_crl_file(WOLFSSL_X509_LOOKUP *ctx, + const char *file, int type); #endif WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*); WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( @@ -1590,6 +1739,24 @@ WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data( WOLFSSL_X509_STORE_CTX* ctx, int idx); WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx, void *data); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup( + WOLFSSL_X509_STORE_CTX* ctx, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif +WOLFSSL_API void* wolfSSL_X509_STORE_get_ex_data( + WOLFSSL_X509_STORE* store, int idx); +WOLFSSL_API int wolfSSL_X509_STORE_set_ex_data(WOLFSSL_X509_STORE* store, + int idx, void *data); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_X509_STORE_set_ex_data_with_cleanup( + WOLFSSL_X509_STORE* store, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer( @@ -2016,16 +2183,30 @@ enum { /* ssl Constants */ typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, unsigned int, unsigned char*, unsigned int); WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*, - wc_psk_client_callback); + wc_psk_client_callback); WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*, - wc_psk_client_callback); + wc_psk_client_callback); + #ifdef OPENSSL_EXTRA + typedef int (*wc_psk_use_session_cb_func)(WOLFSSL* ssl, + const WOLFSSL_EVP_MD* md, const unsigned char **id, + size_t* idlen, WOLFSSL_SESSION **sess); + WOLFSSL_API void wolfSSL_set_psk_use_session_callback(WOLFSSL* ssl, + wc_psk_use_session_cb_func cb); + #endif #ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_cs_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, const char*); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_cs_callback(WOLFSSL_CTX*, + wc_psk_client_cs_callback); + WOLFSSL_API void wolfSSL_set_psk_client_cs_callback(WOLFSSL*, + wc_psk_client_cs_callback); + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, - char*, unsigned int, unsigned char*, unsigned int, const char**); + char*, unsigned int, unsigned char*, unsigned int, const char**); WOLFSSL_API void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX*, - wc_psk_client_tls13_callback); + wc_psk_client_tls13_callback); WOLFSSL_API void wolfSSL_set_psk_client_tls13_callback(WOLFSSL*, - wc_psk_client_tls13_callback); + wc_psk_client_tls13_callback); #endif WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*); @@ -2037,16 +2218,16 @@ enum { /* ssl Constants */ typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, unsigned char*, unsigned int); WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*, - wc_psk_server_callback); + wc_psk_server_callback); WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*, - wc_psk_server_callback); + wc_psk_server_callback); #ifdef WOLFSSL_TLS13 typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, - unsigned char*, unsigned int, const char**); + unsigned char*, unsigned int, const char**); WOLFSSL_API void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX*, - wc_psk_server_tls13_callback); + wc_psk_server_tls13_callback); WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL*, - wc_psk_server_tls13_callback); + wc_psk_server_tls13_callback); #endif WOLFSSL_API void* wolfSSL_get_psk_callback_ctx(WOLFSSL*); WOLFSSL_API int wolfSSL_set_psk_callback_ctx(WOLFSSL*, void*); @@ -2055,6 +2236,11 @@ enum { /* ssl Constants */ WOLFSSL_API int wolfSSL_CTX_set_psk_callback_ctx(WOLFSSL_CTX*, void*); #define PSK_TYPES_DEFINED + +#ifdef WOLFSSL_TLS13 + WOLFSSL_API const char* wolfSSL_get_cipher_name_by_hash(WOLFSSL* ssl, + const char* hash); +#endif #endif /* NO_PSK */ @@ -2114,8 +2300,8 @@ WOLFSSL_API int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*, const unsigned char*, unsigned int); WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL*); +#ifdef OPENSSL_EXTRA WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl); #endif @@ -2148,10 +2334,17 @@ WOLFSSL_API int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *s, const char *s WOLFSSL_API int wolfSSL_sk_num(const WOLFSSL_STACK* sk); WOLFSSL_API void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i); -#if (defined(HAVE_EX_DATA) || defined(FORTRESS)) && \ - (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL)) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) || defined(WOLFSSL_WPAS_SMALL) + WOLFSSL_API void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_CRYPTO_set_ex_data_with_cleanup( + WOLFSSL_CRYPTO_EX_DATA* ex_data, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif WOLFSSL_API int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data); #endif @@ -2159,6 +2352,13 @@ WOLFSSL_API int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int /* stunnel 4.28 needs */ WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int); WOLFSSL_API int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX*, int, void*); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_CTX_set_ex_data_with_cleanup( + WOLFSSL_CTX* ctx, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif WOLFSSL_API void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX*, WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)); WOLFSSL_API void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX*, @@ -2191,7 +2391,11 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_Cleanup(void); /* which library version do we have */ WOLFSSL_API const char* wolfSSL_lib_version(void); +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +WOLFSSL_API const char* wolfSSL_OpenSSL_version(int a); +#else WOLFSSL_API const char* wolfSSL_OpenSSL_version(void); +#endif /* which library version do we have in hex */ WOLFSSL_API word32 wolfSSL_lib_version_hex(void); @@ -2253,6 +2457,8 @@ WOLFSSL_API WOLFSSL_X509* WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out); WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl, const unsigned char *in, int len); +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_bio(WOLFSSL_BIO *bp, + WOLFSSL_X509_CRL **crl); #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl); #endif @@ -2879,9 +3085,12 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_CERT_MANAGER* cm); WOLFSSL_API int wolfSSL_CertManagerDisableOCSPMustStaple( WOLFSSL_CERT_MANAGER* cm); -#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && \ + !defined(NO_FILESYSTEM) WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm); -#endif +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); +#endif /* OPENSSL_EXTRA && WOLFSSL_SIGNER_DER_CERT && !NO_FILESYSTEM */ WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options); WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int); @@ -3206,6 +3415,21 @@ WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl); #endif +#if defined(HAVE_SELFTEST) && \ + (!defined(HAVE_SELFTEST_VERSION) || (HAVE_SELFTEST_VERSION < 2)) + + /* Needed by session ticket stuff below */ + #ifndef WOLFSSL_AES_KEY_SIZE_ENUM + #define WOLFSSL_AES_KEY_SIZE_ENUM + enum SSL_Misc { + AES_IV_SIZE = 16, + AES_128_KEY_SIZE = 16, + AES_192_KEY_SIZE = 24, + AES_256_KEY_SIZE = 32 + }; + #endif +#endif + /* Session Ticket */ #ifdef HAVE_SESSION_TICKET @@ -3451,11 +3675,6 @@ WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); #endif -#ifdef WOLFSSL_WPAS_SMALL - /* WPA Supplicant requires GEN_ values */ - #include -#endif - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, int* idx); @@ -3478,6 +3697,8 @@ WOLFSSL_API void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx, WOLFSSL_API void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx); WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len); +WOLFSSL_API int wolfSSL_X509_pubkey_digest(const WOLFSSL_X509 *x509, + const WOLFSSL_EVP_MD *digest, unsigned char* buf, unsigned int* len); WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509); WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey); WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, @@ -3538,20 +3759,26 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str); WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_SECRET_CALLBACK) WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, size_t outlen); WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, size_t outSz); -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio); +/* non-standard API to determine if BIO supports "pending" */ +WOLFSSL_API int wolfSSL_BIO_supports_pending(const WOLFSSL_BIO *bio); WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); WOLFSSL_API int wolfSSL_get_server_tmp_key(const WOLFSSL*, WOLFSSL_EVP_PKEY**); WOLFSSL_API int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX*, int); WOLFSSL_API int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX*, int); +WOLFSSL_API int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); @@ -3569,7 +3796,7 @@ WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio( WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u); #endif -WOLFSSL_API int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, +WOLFSSL_API int wolfSSL_PEM_get_EVP_CIPHER_INFO(const char* header, EncryptedInfo* cipher); WOLFSSL_API int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data, long* len, @@ -3587,6 +3814,12 @@ struct WOLFSSL_ASN1_BIT_STRING { long flags; }; +struct WOLFSSL_CONF_CTX { + unsigned int flags; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; +}; + WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ @@ -3613,6 +3846,7 @@ WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA224(const unsigned char *d, size_t n, unsigned char *md); WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md); WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md); WOLFSSL_API unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, unsigned char *md); @@ -3720,7 +3954,7 @@ WOLFSSL_API int wolfSSL_FIPS_mode(void); WOLFSSL_API int wolfSSL_FIPS_mode_set(int r); -WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth); +WOLFSSL_API int wolfSSL_RAND_set_rand_method(const WOLFSSL_RAND_METHOD *methods); WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits); @@ -3808,6 +4042,13 @@ WOLFSSL_API void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int); WOLFSSL_API int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_SESSION_set_ex_data_with_cleanup( + WOLFSSL_SESSION* session, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \ @@ -3862,9 +4103,10 @@ WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE fp); WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*)); WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val); +WOLFSSL_API void wolfSSL_THREADID_current(WOLFSSL_CRYPTO_THREADID* id); +WOLFSSL_API unsigned long wolfSSL_THREADID_hash( + const WOLFSSL_CRYPTO_THREADID* id); -WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( - WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects(WOLFSSL_X509_STORE *); WOLFSSL_API WOLFSSL_X509_OBJECT* @@ -3921,6 +4163,8 @@ WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line); WOLFSSL_API void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len); WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); +WOLFSSL_API void wolfSSL_DH_get0_pqg(const WOLFSSL_DH* dh, +const WOLFSSL_BIGNUM** p, const WOLFSSL_BIGNUM** q, const WOLFSSL_BIGNUM** g); #endif #if defined(HAVE_OCSP) && !defined(NO_ASN_TIME) @@ -3936,7 +4180,8 @@ WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); #if defined(OPENSSL_ALL) \ || defined(WOLFSSL_NGINX) \ || defined(WOLFSSL_HAPROXY) \ - || defined(OPENSSL_EXTRA) + || defined(OPENSSL_EXTRA) \ + || defined(HAVE_STUNNEL) WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); #endif @@ -3954,6 +4199,13 @@ WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, void *data); +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +WOLFSSL_API int wolfSSL_X509_set_ex_data_with_cleanup( + X509 *x509, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine); +#endif #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ @@ -3974,7 +4226,11 @@ WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *, WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s); WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s); WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +WOLFSSL_API int wolfSSL_SSL_in_init(const WOLFSSL*); +#else WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL*); +#endif WOLFSSL_API int wolfSSL_SSL_in_connect_init(WOLFSSL*); #ifndef NO_SESSION_CACHE @@ -3985,9 +4241,9 @@ WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, const WOLFSSL_ASN1_INTEGER *a); #ifdef HAVE_SESSION_TICKET -WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( - WOLFSSL *ssl, unsigned char *name, unsigned char *iv, - WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +typedef int (*ticketCompatCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, ticketCompatCb); #endif #if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ @@ -4063,6 +4319,10 @@ WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, WOLFSSL_API int wolfSSL_X509_check_ip_asc(WOLFSSL_X509 *x, const char *ipasc, unsigned int flags); #endif +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_GEN) +WOLFSSL_API int wolfSSL_X509_check_email(WOLFSSL_X509 *x, const char *chk, + size_t chkLen, unsigned int flags); +#endif /* OPENSSL_EXTRA && WOLFSSL_CERT_GEN */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) @@ -4149,8 +4409,45 @@ WOLFSSL_API int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, const char* key, unsigned int keySz, int format); WOLFSSL_API int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, const char* key, unsigned int keySz, int format); + +/* returns pointer to loaded key as ASN.1/DER */ +WOLFSSL_API int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const unsigned char** key, unsigned int* keySz); +WOLFSSL_API int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const unsigned char** key, unsigned int* keySz); #endif +#if defined(OPENSSL_EXTRA) +WOLFSSL_API int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx); +WOLFSSL_API void wolfSSL_CTX_set_security_level(WOLFSSL_CTX* ctx, int level); +WOLFSSL_API int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx); + +WOLFSSL_API int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s); + +WOLFSSL_API void wolfSSL_CRYPTO_free(void *str, const char *file, int line); +WOLFSSL_API void *wolfSSL_CRYPTO_malloc(size_t num, const char *file, int line); + +WOLFSSL_API WOLFSSL_CONF_CTX* wolfSSL_CONF_CTX_new(void); +WOLFSSL_API void wolfSSL_CONF_CTX_free(WOLFSSL_CONF_CTX* cctx); +WOLFSSL_API void wolfSSL_CONF_CTX_set_ssl_ctx(WOLFSSL_CONF_CTX* cctx, WOLFSSL_CTX *ctx); +WOLFSSL_API unsigned int wolfSSL_CONF_CTX_set_flags(WOLFSSL_CONF_CTX* cctx, unsigned int flags); +WOLFSSL_API int wolfSSL_CONF_CTX_finish(WOLFSSL_CONF_CTX* cctx); + +#define WOLFSSL_CONF_FLAG_CMDLINE 0x1 +#define WOLFSSL_CONF_FLAG_FILE 0x2 +#define WOLFSSL_CONF_FLAG_CERTIFICATE 0x20 + +#define WOLFSSL_CONF_TYPE_STRING 0x1 +#define WOLFSSL_CONF_TYPE_FILE 0x2 + +WOLFSSL_API int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) +WOLFSSL_API int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + WOLFSSL_CRYPTO_EX_new* new_func, + WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func); +#endif /* HAVE_EX_DATA || FORTRESS */ +#endif /* OPENSSL_EXTRA */ #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index 5da853e60..60f310a28 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -12,10 +12,14 @@ #endif #include #include +#ifdef HAVE_ERRNO_H + #include +#endif #include #include #include #include +#include #if defined(SHOW_CERTS) && \ (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) #include /* for domain component NID value */ @@ -349,6 +353,7 @@ #define cliEd448CertFile "certs/ed448/client-ed448.pem" #define cliEd448KeyFile "certs/ed448/client-ed448-priv.pem" #define caEd448CertFile "certs/ed448/ca-ed448.pem" +#define caCertFolder "certs/" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "wnr-example.conf" @@ -382,6 +387,7 @@ #define cliEd448CertFile "./certs/ed448/client-ed448.pem" #define cliEd448KeyFile "./certs/ed448/client-ed448-priv.pem" #define caEd448CertFile "./certs/ed448/ca-ed448.pem" +#define caCertFolder "./certs/" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "./wnr-example.conf" @@ -563,7 +569,7 @@ static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) char c; char* cp; - /* Added sanity check becuase scan-build complains argv[myoptind] access + /* Added sanity check because scan-build complains argv[myoptind] access * results in a null pointer dereference. */ if (argv == NULL) { myoptarg = NULL; @@ -1295,10 +1301,9 @@ static WC_INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, static WC_INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, func_args* args, word16 port, int useAnyAddr, - int udp, int sctp, int ready_file, int do_listen) + int udp, int sctp, int ready_file, int do_listen, + SOCKADDR_IN_T *client_addr, socklen_t *client_len) { - SOCKADDR_IN_T client_addr; - socklen_t client_len = sizeof(client_addr); tcp_ready* ready = NULL; (void) ready; /* Account for case when "ready" is not used */ @@ -1355,8 +1360,8 @@ static WC_INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, } } - *clientfd = accept(*sockfd, (struct sockaddr*)&client_addr, - (ACCEPT_THIRD_T)&client_len); + *clientfd = accept(*sockfd, (struct sockaddr*)client_addr, + (ACCEPT_THIRD_T)client_len); if(WOLFSSL_SOCKET_IS_INVALID(*clientfd)) { err_sys_with_errno("tcp accept failed"); } @@ -1494,14 +1499,18 @@ static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, { int i; int b = 0x01; + int kIdLen = (int)XSTRLEN(kIdentityStr); const char* userCipher = (const char*)wolfSSL_get_psk_callback_ctx(ssl); (void)ssl; (void)key_max_len; /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ - if (XSTRNCMP(identity, kIdentityStr, XSTRLEN(kIdentityStr)) != 0) + if (XSTRNCMP(identity, kIdentityStr, kIdLen) != 0) return 0; + if (identity[kIdLen] != '\0') { + userCipher = wolfSSL_get_cipher_name_by_hash(ssl, identity + kIdLen); + } for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) @@ -1514,6 +1523,102 @@ static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, return 32; /* length of key in octets or 0 for error */ } +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) +static unsigned char local_psk[32]; +#endif +static WC_INLINE int my_psk_use_session_cb(WOLFSSL* ssl, + const WOLFSSL_EVP_MD* md, const unsigned char **id, + size_t* idlen, WOLFSSL_SESSION **sess) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + int i; + int b = 0x01; + WOLFSSL_SESSION* lsess; + char buf[256]; + const char* cipher_id = "TLS13-AES128-GCM-SHA256"; + const SSL_CIPHER* cipher = NULL; + STACK_OF(SSL_CIPHER) *supportedCiphers = NULL; + int numCiphers = 0; + (void)ssl; + (void)md; + + printf("use psk session callback \n"); + + lsess = wolfSSL_SESSION_new(); + if (lsess == NULL) { + return 0; + } + supportedCiphers = SSL_get_ciphers(ssl); + numCiphers = sk_num(supportedCiphers); + + for (i = 0; i < numCiphers; ++i) { + + if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) { + SSL_CIPHER_description(cipher, buf, sizeof(buf)); + } + + if (XMEMCMP(cipher_id, buf, XSTRLEN(cipher_id)) == 0) { + break; + } + } + + if (i != numCiphers) { + SSL_SESSION_set_cipher(lsess, cipher); + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + local_psk[i] = b; + } + + *id = local_psk; + *idlen = 32; + *sess = lsess; + + return 1; + } + else { + *id = NULL; + *idlen = 0; + *sess = NULL; + return 0; + } +#else + (void)ssl; + (void)md; + (void)id; + (void)idlen; + (void)sess; + + return 0; +#endif +} + +static WC_INLINE unsigned int my_psk_client_cs_cb(WOLFSSL* ssl, + const char* hint, char* identity, unsigned int id_max_len, + unsigned char* key, unsigned int key_max_len, const char* ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)hint; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + XSTRNCPY(identity, kIdentityStr, id_max_len); + XSTRNCAT(identity, ciphersuite + XSTRLEN(ciphersuite) - 6, id_max_len); + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + return 32; /* length of key in octets or 0 for error */ +} + #endif /* !NO_PSK */ @@ -3012,6 +3117,8 @@ static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, return ret; } +#endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 static WC_INLINE int myEd25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) @@ -3334,8 +3441,6 @@ static WC_INLINE int myX448SharedSecret(WOLFSSL* ssl, curve448_key* otherKey, } #endif /* HAVE_CURVE448 */ -#endif /* HAVE_ECC */ - #ifndef NO_DH static WC_INLINE int myDhCallback(WOLFSSL* ssl, struct DhKey* key, const unsigned char* priv, unsigned int privSz, @@ -3356,7 +3461,7 @@ static WC_INLINE int myDhCallback(WOLFSSL* ssl, struct DhKey* key, ret, privSz, pubKeySz, *outlen); return ret; -}; +} #endif /* !NO_DH */ @@ -3823,6 +3928,7 @@ static WC_INLINE void SetupPkCallbackContexts(WOLFSSL* ssl, void* myCtx) #endif /* HAVE_PK_CALLBACKS */ +#ifdef USE_WOLFSSL_IO static WC_INLINE int SimulateWantWriteIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) { static int wantWriteFlag = 1; @@ -3865,6 +3971,7 @@ static WC_INLINE int SimulateWantWriteIOSendCb(WOLFSSL *ssl, char *buf, int sz, return WOLFSSL_CBIO_ERR_WANT_WRITE; } } +#endif /* USE_WOLFSSL_IO */ #if defined(__hpux__) || defined(__MINGW32__) || defined (WOLFSSL_TIRTOS) \ || defined(_MSC_VER) @@ -4088,4 +4195,33 @@ static WC_INLINE word16 GetRandomPort(void) return port; } +#ifdef WOLFSSL_EARLY_DATA +static WC_INLINE void EarlyDataStatus(WOLFSSL* ssl) +{ + int earlyData_status; +#ifdef OPENSSL_EXTRA + earlyData_status = SSL_get_early_data_status(ssl); +#else + earlyData_status = wolfSSL_get_early_data_status(ssl); +#endif + if (earlyData_status < 0) return; + + printf("Early Data was "); + + switch(earlyData_status) { + case WOLFSSL_EARLY_DATA_NOT_SENT: + printf("not sent.\n"); + break; + case WOLFSSL_EARLY_DATA_REJECTED: + printf("rejected.\n"); + break; + case WOLFSSL_EARLY_DATA_ACCEPTED: + printf("accepted\n"); + break; + default: + printf("unknown...\n"); + } +} +#endif /* WOLFSSL_EARLY_DATA */ + #endif /* wolfSSL_TEST_H */ diff --git a/wolfssl/version.h b/wolfssl/version.h index 3f7d97692..84e6d30bf 100644 --- a/wolfssl/version.h +++ b/wolfssl/version.h @@ -1,6 +1,6 @@ /* wolfssl_version.h.in * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "4.7.0" -#define LIBWOLFSSL_VERSION_HEX 0x04007000 +#define LIBWOLFSSL_VERSION_STRING "4.7.1" +#define LIBWOLFSSL_VERSION_HEX 0x04007001 #ifdef __cplusplus } diff --git a/wolfssl/version.h.in b/wolfssl/version.h.in index 0a25a3bf6..673203f39 100644 --- a/wolfssl/version.h.in +++ b/wolfssl/version.h.in @@ -1,6 +1,6 @@ /* wolfssl_version.h.in * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 1141b0c71..21908ac3c 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -1,6 +1,6 @@ /* aes.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -250,6 +250,21 @@ struct Aes { silabs_aes_t ctx; #endif void* heap; /* memory hint to use */ +#ifdef WOLFSSL_AESGCM_STREAM +#if !defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_AESNI) + ALIGN16 byte streamData[5 * AES_BLOCK_SIZE]; +#else + byte* streamData; +#endif + word32 aSz; + word32 cSz; + byte over; + byte aOver; + byte cOver; + byte gcmKeySet:1; + byte nonceSet:1; + byte ctrSet:1; +#endif }; #ifndef WC_AES_TYPE_DEFINED @@ -361,6 +376,26 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz); +#ifdef WOLFSSL_AESGCM_STREAM +WOLFSSL_API int wc_AesGcmInit(Aes* aes, const byte* key, word32 len, + const byte* iv, word32 ivSz); + +WOLFSSL_API int wc_AesGcmEncryptInit(Aes* aes, const byte* key, word32 len, + const byte* iv, word32 ivSz); +WOLFSSL_API int wc_AesGcmEncryptInit_ex(Aes* aes, const byte* key, word32 len, + byte* ivOut, word32 ivOutSz); +WOLFSSL_API int wc_AesGcmEncryptUpdate(Aes* aes, byte* out, const byte* in, + word32 sz, const byte* authIn, word32 authInSz); +WOLFSSL_API int wc_AesGcmEncryptFinal(Aes* aes, byte* authTag, + word32 authTagSz); + +WOLFSSL_API int wc_AesGcmDecryptInit(Aes* aes, const byte* key, word32 len, + const byte* iv, word32 ivSz); +WOLFSSL_API int wc_AesGcmDecryptUpdate(Aes* aes, byte* out, const byte* in, + word32 sz, const byte* authIn, word32 authInSz); +WOLFSSL_API int wc_AesGcmDecryptFinal(Aes* aes, const byte* authTag, + word32 authTagSz); +#endif #ifndef WC_NO_RNG WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz); @@ -416,10 +451,18 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, byte* out, word32 outSz, const byte* iv); + WOLFSSL_API int wc_AesKeyWrap_ex(Aes *aes, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); WOLFSSL_API int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, byte* out, word32 outSz, const byte* iv); + WOLFSSL_API int wc_AesKeyUnWrap_ex(Aes *aes, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); #endif /* HAVE_AES_KEYWRAP */ #ifdef WOLFSSL_AES_XTS diff --git a/wolfssl/wolfcrypt/arc4.h b/wolfssl/wolfcrypt/arc4.h index bcdc9076c..2d21f5ced 100644 --- a/wolfssl/wolfcrypt/arc4.h +++ b/wolfssl/wolfcrypt/arc4.h @@ -1,6 +1,6 @@ /* arc4.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index e412c1d06..3457b435a 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1,6 +1,6 @@ /* asn.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -140,6 +140,7 @@ enum DN_Tags { /* pilot attribute types * OID values of 0.9.2342.19200300.100.1.* */ ASN_USER_ID = 0x01, /* UID */ + ASN_FAVOURITE_DRINK = 0x05, /* favouriteDrink */ ASN_DOMAIN_COMPONENT = 0x19 /* DC */ }; @@ -182,6 +183,7 @@ extern const WOLFSSL_ObjectInfo wolfssl_object_info[]; #define WOLFSSL_USER_ID "/UID=" #define WOLFSSL_DOMAIN_COMPONENT "/DC=" +#define WOLFSSL_FAVOURITE_DRINK "/favouriteDrink=" #if defined(WOLFSSL_APACHE_HTTPD) /* otherName strings */ @@ -196,6 +198,7 @@ extern const WOLFSSL_ObjectInfo wolfssl_object_info[]; #define WOLFSSL_TLS_FEATURE_SUM 92 #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* NIDs */ enum { @@ -247,6 +250,7 @@ enum NID_jurisdictionStateOrProvinceName = 0xd, NID_businessCategory = ASN_BUS_CAT, NID_domainComponent = ASN_DOMAIN_COMPONENT, + NID_favouriteDrink = 462, NID_userId = 458, NID_emailAddress = 0x30, /* emailAddress */ NID_id_on_dnsSRV = 82, /* 1.3.6.1.5.5.7.8.7 */ @@ -254,6 +258,7 @@ enum NID_X9_62_prime_field = 406 /* 1.2.840.10045.1.1 */ }; +#endif /* OPENSSL_EXTRA */ enum ECC_TYPES { @@ -305,6 +310,7 @@ enum Misc_ASN { KEYID_SIZE = WC_SHA_DIGEST_SIZE, #endif RSA_INTS = 8, /* RSA ints in private key */ + DSA_PARAM_INTS = 3, /* DSA paramater ints */ DSA_INTS = 5, /* DSA ints in private key */ MIN_DATE_SIZE = 12, MAX_DATE_SIZE = 32, @@ -330,7 +336,7 @@ enum Misc_ASN { MAX_ENCODED_DIG_ASN_SZ= 9, /* enum(bit or octet) + length(4) */ MAX_ENCODED_DIG_SZ = 64 + MAX_ENCODED_DIG_ASN_SZ, /* asn header + sha512 */ MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */ - MAX_DSA_INT_SZ = 261, /* DSA raw sz 2048 for bits + tag + len(4) */ + MAX_DSA_INT_SZ = 389, /* DSA raw sz 3072 for bits + tag + len(4) */ MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */ MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */ MAX_LENGTH_SZ = 4, /* Max length size for DER encoding */ @@ -977,6 +983,14 @@ struct DecodedCert { #endif }; +/* ASN Encoded Name field */ +typedef struct EncodedName { + int nameLen; /* actual string value length */ + int totalLen; /* total encoded length */ + int type; /* type of name */ + int used; /* are we actually using this one */ + byte encoded[CTC_NAME_SIZE * 2]; /* encoding */ +} EncodedName; #ifdef NO_SHA #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE @@ -1163,6 +1177,10 @@ WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b); WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType); WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn); +WOLFSSL_LOCAL int wc_EncodeName(EncodedName* name, const char* nameStr, + char nameType, byte type); +WOLFSSL_LOCAL int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr, + char nameType, byte type); /* ASN.1 helper functions */ #ifdef WOLFSSL_CERT_GEN WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name); @@ -1215,12 +1233,6 @@ WOLFSSL_LOCAL int GetASNTag(const byte* input, word32* idx, byte* tag, WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output); WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output); WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output); -#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_DH) \ - || defined(WOLFSSL_OPENSSH) -WOLFSSL_LOCAL int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz); -WOLFSSL_LOCAL int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz); -WOLFSSL_LOCAL int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); -#endif WOLFSSL_LOCAL int SetASNInt(int len, byte firstByte, byte* output); WOLFSSL_LOCAL word32 SetBitString(word32 len, byte unusedBits, byte* output); WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output); @@ -1262,8 +1274,8 @@ WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); #ifndef NO_CERTS -WOLFSSL_LOCAL int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, - size_t bufSz); +WOLFSSL_LOCAL int wc_EncryptedInfoParse(EncryptedInfo* info, + const char** pBuffer, size_t bufSz); WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type, DerBuffer** pDer, void* heap, EncryptedInfo* info, @@ -1280,6 +1292,7 @@ WOLFSSL_LOCAL int wc_MIME_create_header(char* name, char* body, MimeHdr** hdr); WOLFSSL_LOCAL int wc_MIME_create_parameter(char* attribute, char* value, MimeParam** param); WOLFSSL_LOCAL MimeHdr* wc_MIME_find_header_name(const char* name, MimeHdr* hdr); WOLFSSL_LOCAL MimeParam* wc_MIME_find_param_attr(const char* attribute, MimeParam* param); +WOLFSSL_LOCAL char* wc_MIME_canonicalize(const char* line); WOLFSSL_LOCAL int wc_MIME_free_hdrs(MimeHdr* head); #endif /* HAVE_SMIME */ @@ -1390,6 +1403,8 @@ struct OcspEntry byte* rawCertId; /* raw bytes of the CertID */ int rawCertIdSize; /* num bytes in raw CertID */ /* option bits - using 32-bit for alignment */ + word32 ownStatus:1; /* do we need to free the status + * response list */ word32 isDynamic:1; /* was dynamically allocated */ }; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 450f845eb..4c4479b44 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -1,6 +1,6 @@ /* asn_public.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,6 +32,7 @@ This library defines the interface APIs for X509 certificates. #define WOLF_CRYPT_ASN_PUBLIC_H #include +#include #ifdef __cplusplus extern "C" { @@ -58,6 +59,10 @@ This library defines the interface APIs for X509 certificates. typedef struct WC_RNG WC_RNG; #define WC_RNG_TYPE_DEFINED #endif +#ifndef WC_DH_TYPE_DEFINED + typedef struct DhKey DhKey; + #define WC_DH_TYPE_DEFINED +#endif enum Ecc_Sum { ECC_SECP112R1_OID = 182, @@ -509,6 +514,20 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); WOLFSSL_API int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header); #endif +#ifndef NO_DSA + /* DSA parameter DER helper functions */ + WOLFSSL_API int wc_DsaParamsDecode(const byte* input, word32* inOutIdx, + DsaKey*, word32); + WOLFSSL_API int wc_DsaKeyToParamsDer(DsaKey* key, byte* output, word32 inLen); +#endif + +#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) +WOLFSSL_LOCAL int wc_DhKeyToDer(DhKey* key, byte* output, word32* outSz, int exportPriv); +WOLFSSL_API int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz); +WOLFSSL_API int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz); +WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); +#endif + #ifdef HAVE_ECC /* private key helpers */ WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, @@ -516,6 +535,7 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen); + WOLFSSL_API int wc_EccKeyDerSize(ecc_key*, int pub); WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen); WOLFSSL_API int wc_EccKeyToPKCS8(ecc_key* key, byte* output, @@ -574,6 +594,9 @@ WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz); WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); +WOLFSSL_API int wc_EncryptPKCS8Key(byte*, word32, byte*, word32, const char*, + int, int, int, int, byte*, word32, int, WC_RNG*, void*); +WOLFSSL_API int wc_DecryptPKCS8Key(byte*, word32, const char*, int); #ifndef NO_ASN_TIME /* Time */ diff --git a/wolfssl/wolfcrypt/blake2-impl.h b/wolfssl/wolfcrypt/blake2-impl.h index cb4df286c..9806e44de 100644 --- a/wolfssl/wolfcrypt/blake2-impl.h +++ b/wolfssl/wolfcrypt/blake2-impl.h @@ -12,7 +12,7 @@ */ /* blake2-impl.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/blake2-int.h b/wolfssl/wolfcrypt/blake2-int.h index ac093d646..44f0ddf8e 100644 --- a/wolfssl/wolfcrypt/blake2-int.h +++ b/wolfssl/wolfcrypt/blake2-int.h @@ -12,7 +12,7 @@ */ /* blake2-int.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/blake2.h b/wolfssl/wolfcrypt/blake2.h index 620482dac..cdcb0661d 100644 --- a/wolfssl/wolfcrypt/blake2.h +++ b/wolfssl/wolfcrypt/blake2.h @@ -1,6 +1,6 @@ /* blake2.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/camellia.h b/wolfssl/wolfcrypt/camellia.h index 4b86e6c13..7ef0270a3 100644 --- a/wolfssl/wolfcrypt/camellia.h +++ b/wolfssl/wolfcrypt/camellia.h @@ -27,7 +27,7 @@ /* camellia.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/chacha.h b/wolfssl/wolfcrypt/chacha.h index 3e9206002..0d84c5b42 100644 --- a/wolfssl/wolfcrypt/chacha.h +++ b/wolfssl/wolfcrypt/chacha.h @@ -1,6 +1,6 @@ /* chacha.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/chacha20_poly1305.h b/wolfssl/wolfcrypt/chacha20_poly1305.h index 26289d165..44631bf9c 100644 --- a/wolfssl/wolfcrypt/chacha20_poly1305.h +++ b/wolfssl/wolfcrypt/chacha20_poly1305.h @@ -1,6 +1,6 @@ /* chacha20_poly1305.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/cmac.h b/wolfssl/wolfcrypt/cmac.h index 80f13ce97..9519af9f3 100644 --- a/wolfssl/wolfcrypt/cmac.h +++ b/wolfssl/wolfcrypt/cmac.h @@ -1,6 +1,6 @@ /* cmac.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -53,6 +53,16 @@ struct Cmac { byte k2[AES_BLOCK_SIZE]; word32 bufferSz; word32 totalSz; +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; + #ifdef WOLFSSL_QNX_CAAM + byte ctx[32]; /* hold state for save and return */ + word32 blackKey; + word32 keylen; + byte initialized; + #endif +#endif }; @@ -70,6 +80,12 @@ WOLFSSL_API int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz, int type, void* unused); + +WOLFSSL_API +int wc_InitCmac_ex(Cmac* cmac, + const byte* key, word32 keySz, + int type, void* unused, void* heap, int devId); + WOLFSSL_API int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz); diff --git a/wolfssl/wolfcrypt/coding.h b/wolfssl/wolfcrypt/coding.h index e7e2aedc1..bcc4c5b95 100644 --- a/wolfssl/wolfcrypt/coding.h +++ b/wolfssl/wolfcrypt/coding.h @@ -1,6 +1,6 @@ /* coding.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/compress.h b/wolfssl/wolfcrypt/compress.h index b3a98ac82..985f1e092 100644 --- a/wolfssl/wolfcrypt/compress.h +++ b/wolfssl/wolfcrypt/compress.h @@ -1,6 +1,6 @@ /* compress.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/cpuid.h b/wolfssl/wolfcrypt/cpuid.h index 6e009c4ac..91a725b96 100644 --- a/wolfssl/wolfcrypt/cpuid.h +++ b/wolfssl/wolfcrypt/cpuid.h @@ -1,6 +1,6 @@ /* cpuid.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,8 +32,9 @@ extern "C" { #endif -#if defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ - defined(WOLFSSL_AESNI) +#if (defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ + defined(WOLFSSL_AESNI) || defined(WOLFSSL_SP_X86_64_ASM)) && \ + !defined(WOLFSSL_NO_ASM) #define CPUID_AVX1 0x0001 #define CPUID_AVX2 0x0002 diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 5981d0f00..15c7f876e 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -1,6 +1,6 @@ /* cryptocb.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -15,7 +15,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifndef _WOLF_CRYPTO_CB_H_ @@ -58,6 +59,9 @@ #ifndef NO_DES3 #include #endif +#ifdef WOLFSSL_CMAC + #include +#endif /* Crypto Information Structure for callbacks */ @@ -216,6 +220,19 @@ typedef struct wc_CryptoInfo { word32 sz; } seed; #endif +#ifdef WOLFSSL_CMAC + struct { + Cmac* cmac; + void* ctx; + const byte* key; + const byte* in; + byte* out; + word32* outSz; + word32 keySz; + word32 inSz; + int type; + } cmac; +#endif } wc_CryptoInfo; @@ -306,6 +323,12 @@ WOLFSSL_LOCAL int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz); WOLFSSL_LOCAL int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz); #endif +#ifdef WOLFSSL_CMAC +WOLFSSL_LOCAL int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz, + const byte* in, word32 inSz, byte* out, word32* outSz, int type, + void* ctx); +#endif + #endif /* WOLF_CRYPTO_CB */ #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index 7883cb58c..8abffa2e8 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/wolfssl/wolfcrypt/curve25519.h @@ -1,6 +1,6 @@ /* curve25519.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/curve448.h b/wolfssl/wolfcrypt/curve448.h index 6a9c495e2..ba2059410 100644 --- a/wolfssl/wolfcrypt/curve448.h +++ b/wolfssl/wolfcrypt/curve448.h @@ -1,6 +1,6 @@ /* curve448.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/des3.h b/wolfssl/wolfcrypt/des3.h index 705b59e63..b87737e4f 100644 --- a/wolfssl/wolfcrypt/des3.h +++ b/wolfssl/wolfcrypt/des3.h @@ -1,6 +1,6 @@ /* des3.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index 8bc1dd3d4..1f53f31e8 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/wolfssl/wolfcrypt/dh.h @@ -1,6 +1,6 @@ /* dh.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -46,13 +46,6 @@ #include #endif -/* Optional support extended DH public / private keys */ -#if !defined(WOLFSSL_DH_EXTRA) && (defined(WOLFSSL_QT) || \ - defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) || \ - defined(WOLFSSL_STATIC_EPHEMERAL)) - #define WOLFSSL_DH_EXTRA -#endif - typedef struct DhParams { #ifdef HAVE_FFDHE_Q const byte* q; @@ -117,6 +110,8 @@ WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz, const byte* q, word32 qSz); #ifdef WOLFSSL_DH_EXTRA +WOLFSSL_API int wc_DhPublicKeyDecode(const byte* input, word32* inOutIdx, + DhKey* key, word32 inSz); WOLFSSL_API int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, const byte* pub, word32 pubSz); WOLFSSL_API int wc_DhExportKeyPair(DhKey* key, byte* priv, word32* pPrivSz, diff --git a/wolfssl/wolfcrypt/dsa.h b/wolfssl/wolfcrypt/dsa.h index acc133e5c..0bb00fbfe 100644 --- a/wolfssl/wolfcrypt/dsa.h +++ b/wolfssl/wolfcrypt/dsa.h @@ -1,6 +1,6 @@ /* dsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index f0e95ba2b..a0de8df6b 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -1,6 +1,6 @@ /* ecc.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -85,7 +85,9 @@ /* Determine max ECC bits based on enabled curves */ -#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) +#if defined(WOLFCRYPT_HAVE_SAKKE) + #define MAX_ECC_BITS 1024 +#elif defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #define MAX_ECC_BITS 521 #elif defined(HAVE_ECC512) #define MAX_ECC_BITS 512 @@ -128,10 +130,15 @@ enum { ECC_PRIVATEKEY_ONLY = 3, ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ SIG_HEADER_SZ = 7, /* ECC signature header size (30 81 87 02 42 [R] 02 42 [S]) */ - ECC_BUFSIZE = 256, /* for exported keys temp buffer */ + ECC_BUFSIZE = 257, /* for exported keys temp buffer */ ECC_MINSIZE = ECC_MIN_KEY_SZ/8, /* MIN Private Key size */ +#ifdef WOLFCRYPT_HAVE_SAKKE + ECC_MAXSIZE = 128, /* MAX Private Key size */ + ECC_MAXSIZE_GEN = 128, /* MAX Buffer size required when generating ECC keys*/ +#else ECC_MAXSIZE = 66, /* MAX Private Key size */ ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ +#endif ECC_MAX_OID_LEN = 16, ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ), @@ -212,6 +219,10 @@ typedef enum ecc_curve_id { ECC_X448, #endif +#ifdef WOLFCRYPT_HAVE_SAKKE + ECC_SAKKE_1, +#endif + #ifdef WOLFSSL_CUSTOM_CURVES ECC_CURVE_CUSTOM, #endif @@ -305,6 +316,9 @@ typedef struct ecc_set_type { #ifndef USE_FAST_MATH #error USE_FAST_MATH must be defined to use ALT_ECC_SIZE #endif +#ifdef WOLFSSL_NO_MALLOC + #error ALT_ECC_SIZE cannot be used with no malloc (WOLFSSL_NO_MALLOC) +#endif /* determine max bits required for ECC math */ #ifndef FP_MAX_BITS_ECC @@ -397,6 +411,12 @@ struct ecc_key { void* heap; /* heap hint */ ecc_point pubkey; /* public key */ mp_int k; /* private key */ + +#ifdef WOLFSSL_QNX_CAAM + word32 blackKey; /* address of key encrypted and in secure memory */ + word32 securePubKey; /* address of public key in secure memory */ + int partNum; /* partition number*/ +#endif #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) int slot; /* Key Slot Number (-1 unknown) */ byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE]; @@ -436,9 +456,13 @@ struct ecc_key { ecc_context_t ctx; #endif -#ifdef WOLFSSL_ECDSA_SET_K +#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ + defined(WOLFSSL_ECDSA_DETERMINISTIC_K) mp_int *sign_k; #endif +#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) + byte deterministic:1; +#endif #ifdef WOLFSSL_SMALL_STACK_CACHE mp_int* t1; @@ -546,7 +570,15 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, WOLFSSL_API int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, ecc_key* key, mp_int *r, mp_int *s); -#ifdef WOLFSSL_ECDSA_SET_K +#ifdef WOLFSSL_ECDSA_DETERMINISTIC_K +WOLFSSL_API +int wc_ecc_set_deterministic(ecc_key* key, byte flag); +WOLFSSL_API +int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz, + enum wc_HashType hashType, mp_int* priv, mp_int* k, mp_int* order, + void* heap); +#endif +#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) WOLFSSL_API int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key); #endif @@ -630,7 +662,9 @@ void wc_ecc_del_point(ecc_point* p); WOLFSSL_API void wc_ecc_del_point_h(ecc_point* p, void* h); WOLFSSL_API -int wc_ecc_copy_point(ecc_point* p, ecc_point *r); +void wc_ecc_forcezero_point(ecc_point* p); +WOLFSSL_API +int wc_ecc_copy_point(const ecc_point* p, ecc_point *r); WOLFSSL_API int wc_ecc_cmp_point(ecc_point* a, ecc_point *b); WOLFSSL_API @@ -640,13 +674,13 @@ int wc_ecc_point_is_on_curve(ecc_point *p, int curve_idx); #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) WOLFSSL_API -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, +int wc_ecc_mulmod(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map); WOLFSSL_LOCAL -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, +int wc_ecc_mulmod_ex(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap); WOLFSSL_LOCAL -int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, +int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap); #endif /* !WOLFSSL_ATECC508A */ @@ -722,10 +756,11 @@ int wc_ecc_export_point_der_compressed(const int curve_idx, ecc_point* point, #ifdef HAVE_ECC_KEY_IMPORT WOLFSSL_API -int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, - ecc_point* point, int shortKeySize); +int wc_ecc_import_point_der_ex(const byte* in, word32 inLen, + const int curve_idx, ecc_point* point, + int shortKeySize); WOLFSSL_API -int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, +int wc_ecc_import_point_der(const byte* in, word32 inLen, const int curve_idx, ecc_point* point); #endif /* HAVE_ECC_KEY_IMPORT */ @@ -735,7 +770,7 @@ int wc_ecc_size(ecc_key* key); WOLFSSL_API int wc_ecc_sig_size_calc(int sz); WOLFSSL_API -int wc_ecc_sig_size(ecc_key* key); +int wc_ecc_sig_size(const ecc_key* key); WOLFSSL_API int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz); diff --git a/wolfssl/wolfcrypt/eccsi.h b/wolfssl/wolfcrypt/eccsi.h new file mode 100644 index 000000000..b563514eb --- /dev/null +++ b/wolfssl/wolfcrypt/eccsi.h @@ -0,0 +1,176 @@ +/* eccsi.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/eccsi.h +*/ + + +#ifndef WOLF_CRYPT_ECCSI_H +#define WOLF_CRYPT_ECCSI_H + +#include + +#ifdef WOLFCRYPT_HAVE_ECCSI + +#include +#include +#include +#include + +#define WOLFCRYPT_ECCSI_KMS +#define WOLFCRYPT_ECCSI_CLIENT + +#define MAX_ECCSI_BYTES (256 / 8) + +/* Maximum number of loops of attempting to generate key pairs and signatures. + */ +#ifndef ECCSI_MAX_GEN_COUNT + #define ECCSI_MAX_GEN_COUNT 10 +#endif + +typedef struct EccsiKeyParams { + /** Order (q) of elliptic curve as an MP integer. */ + mp_int order; +#ifdef WOLFCRYPT_ECCSI_CLIENT + /** A parameter of elliptic curve as an MP integer. */ + mp_int a; + /** P parameter of elliptic curve as an MP integer. */ + mp_int b; + /** Prime of elliptic curve as an MP integer. */ + mp_int prime; +#endif + /** Base point for elliptic curve operations as an ECC point. */ + ecc_point* base; + + /** Bit indicates order (q) is set as an MP integer in ECCSI key. */ + byte haveOrder:1; + /** Bit indicates A is set as an MP integer in ECCSI key. */ + byte haveA:1; + /** Bit indicates B is set as an MP integer in ECCSI key. */ + byte haveB:1; + /** Bit indicates prime is set as an MP integer in ECCSI key. */ + byte havePrime:1; + /** Bit indicates base point is set as an MP integer in ECCSI key. */ + byte haveBase:1; +} EccsiKeyParams; + +/** + * ECCSI key. + */ +typedef struct EccsiKey { + /** ECC key to perform elliptic curve operations with. */ + ecc_key ecc; + /** ECC key to perform public key elliptic curve operations with. */ + ecc_key pubkey; + /** ECC parameter in forms that can be used in computation. */ + EccsiKeyParams params; +#ifdef WOLFCRYPT_ECCSI_CLIENT + /** Temporary MP integer used during operations.. */ + mp_int tmp; + /** Secret Signing Key */ + mp_int ssk; + /** Public Validation Token (PVT) */ + ecc_point* pvt; +#endif + /** Generic hash algorithm object. */ + wc_HashAlg hash; + /** Temporary buffer for use in operations. */ + byte data[(MAX_ECCSI_BYTES * 2) + 1]; +#ifdef WOLFCRYPT_ECCSI_CLIENT + /** Hash of identity - used in signing/verification. */ + byte idHash[WC_MAX_DIGEST_SIZE]; + /** Size of hash of identity in bytes. */ + byte idHashSz; +#endif + /** Heap hint for dynamic memory allocation. */ + void* heap; + /** Bit indicates KPAK (public key) is in montogmery form. */ + word16 kpakMont:1; +} EccsiKey; + +#ifdef __cplusplus + extern "C" { +#endif + +WOLFSSL_API int wc_InitEccsiKey(EccsiKey* key, void* heap, int devId); +WOLFSSL_API int wc_InitEccsiKey_ex(EccsiKey* key, int keySz, int curveId, + void* heap, int devId); +WOLFSSL_API void wc_FreeEccsiKey(EccsiKey* key); + +WOLFSSL_API int wc_MakeEccsiKey(EccsiKey* key, WC_RNG* rng); + +WOLFSSL_API int wc_MakeEccsiPair(EccsiKey* key, WC_RNG* rng, + enum wc_HashType hashType, const byte* id, word32 idSz, mp_int* ssk, + ecc_point* pvt); +WOLFSSL_API int wc_ValidateEccsiPair(EccsiKey* key, enum wc_HashType hashType, + const byte* id, word32 idSz, const mp_int* ssk, ecc_point* pvt, + int* valid); +WOLFSSL_API int wc_ValidateEccsiPvt(EccsiKey* key, const ecc_point* pvt, + int* valid); +WOLFSSL_API int wc_EncodeEccsiPair(const EccsiKey* key, mp_int* ssk, + ecc_point* pvt, byte* data, word32* sz); +WOLFSSL_API int wc_EncodeEccsiSsk(const EccsiKey* key, mp_int* ssk, byte* data, + word32* sz); +WOLFSSL_API int wc_EncodeEccsiPvt(const EccsiKey* key, ecc_point* pvt, + byte* data, word32* sz, int raw); +WOLFSSL_API int wc_DecodeEccsiPair(const EccsiKey* key, const byte* data, + word32 sz, mp_int* ssk, ecc_point* pvt); +WOLFSSL_API int wc_DecodeEccsiSsk(const EccsiKey* key, const byte* data, + word32 sz, mp_int* ssk); +WOLFSSL_API int wc_DecodeEccsiPvt(const EccsiKey* key, const byte* data, + word32 sz, ecc_point* pvt); +WOLFSSL_API int wc_DecodeEccsiPvtFromSig(const EccsiKey* key, const byte* sig, + word32 sz, ecc_point* pvt); + +WOLFSSL_API int wc_ExportEccsiKey(EccsiKey* key, byte* data, word32* sz); +WOLFSSL_API int wc_ImportEccsiKey(EccsiKey* key, const byte* data, word32 sz); + +WOLFSSL_API int wc_ExportEccsiPrivateKey(EccsiKey* key, byte* data, word32* sz); +WOLFSSL_API int wc_ImportEccsiPrivateKey(EccsiKey* key, const byte* data, + word32 sz); + +WOLFSSL_API int wc_ExportEccsiPublicKey(EccsiKey* key, byte* data, word32* sz, + int raw); +WOLFSSL_API int wc_ImportEccsiPublicKey(EccsiKey* key, const byte* data, + word32 sz, int trusted); + +WOLFSSL_API int wc_HashEccsiId(EccsiKey* key, enum wc_HashType hashType, + const byte* id, word32 idSz, ecc_point* pvt, byte* hash, byte* hashSz); +WOLFSSL_API int wc_SetEccsiHash(EccsiKey* key, const byte* hash, byte hashSz); +WOLFSSL_API int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, + const ecc_point* pvt); + +WOLFSSL_API int wc_SignEccsiHash(EccsiKey* key, WC_RNG* rng, + enum wc_HashType hashType, const byte* msg, word32 msgSz, byte* sig, + word32* sigSz); +WOLFSSL_API int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType, + const byte* msg, word32 msgSz, const byte* sig, word32 sigSz, + int* verified); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_HAVE_ECCSI */ + +#endif /* WOLF_CRYPT_ECCSI_H */ + diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index f5487ade5..2efe4eed2 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -1,6 +1,6 @@ /* ed25519.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index 4f868b53d..d45585a3f 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -1,6 +1,6 @@ /* ed448.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 2cf6fcca7..dd6ac1726 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -1,6 +1,6 @@ /* error-crypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -234,8 +234,12 @@ enum { PSS_SALTLEN_RECOVER_E=-273, /* PSS slat length not recoverable */ CHACHA_POLY_OVERFLOW =-274, /* ChaCha20Poly1305 limit overflow */ ASN_SELF_SIGNED_E = -275, /* ASN self-signed certificate error */ + SAKKE_VERIFY_FAIL_E = -276, /* SAKKE derivation verification error */ + MISSING_IV = -277, /* IV was not set */ + MISSING_KEY = -278, /* Key was not set */ + BAD_LENGTH_E = -279, /* Value of length parameter is invalid. */ - WC_LAST_E = -275, /* Update this to indicate last error */ + WC_LAST_E = -279, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ /* add new companion error id strings for any new error codes diff --git a/wolfssl/wolfcrypt/fe_448.h b/wolfssl/wolfcrypt/fe_448.h index 0bdcebdfa..6be82cdc3 100644 --- a/wolfssl/wolfcrypt/fe_448.h +++ b/wolfssl/wolfcrypt/fe_448.h @@ -1,6 +1,6 @@ /* fe448_448.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/fe_operations.h b/wolfssl/wolfcrypt/fe_operations.h index 60a1e87ae..03d3afa3a 100644 --- a/wolfssl/wolfcrypt/fe_operations.h +++ b/wolfssl/wolfcrypt/fe_operations.h @@ -1,6 +1,6 @@ /* fe_operations.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/fips_test.h b/wolfssl/wolfcrypt/fips_test.h index a78b074c4..9d139fdc4 100644 --- a/wolfssl/wolfcrypt/fips_test.h +++ b/wolfssl/wolfcrypt/fips_test.h @@ -1,6 +1,6 @@ /* fips_test.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/ge_448.h b/wolfssl/wolfcrypt/ge_448.h index c4fb2293f..befedcee1 100644 --- a/wolfssl/wolfcrypt/ge_448.h +++ b/wolfssl/wolfcrypt/ge_448.h @@ -1,6 +1,6 @@ /* ge_448.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/ge_operations.h b/wolfssl/wolfcrypt/ge_operations.h index 9632e1539..5ad78141d 100644 --- a/wolfssl/wolfcrypt/ge_operations.h +++ b/wolfssl/wolfcrypt/ge_operations.h @@ -1,6 +1,6 @@ /* ge_operations.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 73222cab9..0c6bc772f 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -1,6 +1,6 @@ /* hash.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -88,7 +88,7 @@ enum wc_HashFlags { #endif }; - +#ifndef NO_HASH_WRAPPER typedef union { #ifndef NO_MD5 wc_Md5 md5; @@ -112,6 +112,7 @@ typedef union { wc_Sha3 sha3; #endif } wc_HashAlg; +#endif /* !NO_HASH_WRAPPER */ /* Find largest possible digest size Note if this gets up to the size of 80 or over check smallstack build */ @@ -151,6 +152,8 @@ WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid); WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType); +#ifndef NO_HASH_WRAPPER + WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type); WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type); WOLFSSL_API int wc_Hash(enum wc_HashType hash_type, @@ -215,6 +218,8 @@ WOLFSSL_API int wc_Shake256Hash(const byte*, word32, byte*, word32); #endif #endif /* WOLFSSL_SHA3 */ +#endif /* !NO_HASH_WRAPPER */ + enum max_prf { #ifdef HAVE_FFDHE_8192 MAX_PRF_HALF = 516, /* Maximum half secret len */ diff --git a/wolfssl/wolfcrypt/hc128.h b/wolfssl/wolfcrypt/hc128.h index 19906be72..2b93a2407 100644 --- a/wolfssl/wolfcrypt/hc128.h +++ b/wolfssl/wolfcrypt/hc128.h @@ -1,6 +1,6 @@ /* hc128.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 806475f30..a8d12a7ab 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/idea.h b/wolfssl/wolfcrypt/idea.h index 8dbffb237..16a381789 100644 --- a/wolfssl/wolfcrypt/idea.h +++ b/wolfssl/wolfcrypt/idea.h @@ -1,6 +1,6 @@ /* idea.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 647714956..6363aaeb3 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -23,6 +23,8 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/ed448.h \ wolfssl/wolfcrypt/fe_448.h \ wolfssl/wolfcrypt/ge_448.h \ + wolfssl/wolfcrypt/eccsi.h \ + wolfssl/wolfcrypt/sakke.h \ wolfssl/wolfcrypt/error-crypt.h \ wolfssl/wolfcrypt/fips_test.h \ wolfssl/wolfcrypt/hash.h \ @@ -78,8 +80,8 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/nxp/dcp_port.h \ wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ wolfssl/wolfcrypt/port/caam/caam_driver.h \ - wolfssl/wolfcrypt/port/caam/wolfcaam.h \ - wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \ + wolfssl/wolfcrypt/port/caam/caam_error.h \ + wolfssl/wolfcrypt/port/caam/caam_qnx.h \ wolfssl/wolfcrypt/port/silabs/silabs_aes.h \ wolfssl/wolfcrypt/port/silabs/silabs_ecc.h \ wolfssl/wolfcrypt/port/silabs/silabs_hash.h \ @@ -146,3 +148,11 @@ endif if BUILD_FIPS_RAND nobase_include_HEADERS+= wolfssl/wolfcrypt/fips.h endif + +if BUILD_QNXCAAM +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/caam/wolfcaam.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h +endif diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 8f3665b60..255f55ca2 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -1,6 +1,6 @@ /* integer.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -227,7 +227,8 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); /* ---> Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) #define mp_isone(a) \ - (((((a)->used == 1)) && ((a)->dp[0] == 1u)) ? MP_YES : MP_NO) + (((((a)->used == 1)) && ((a)->dp[0] == 1u) && ((a)->sign == MP_ZPOS)) \ + ? MP_YES : MP_NO) #define mp_iseven(a) \ (((a)->used > 0 && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO) #define mp_isodd(a) \ @@ -255,9 +256,6 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define mp_prime_random(a, t, size, bbs, cb, dat) \ mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) -#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) -#define mp_raw_size(mp) mp_signed_bin_size(mp) -#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) #define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) #define mp_mag_size(mp) mp_unsigned_bin_size(mp) #define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) @@ -285,7 +283,7 @@ MP_API int mp_init (mp_int * a); MP_API void mp_clear (mp_int * a); MP_API void mp_free (mp_int * a); MP_API void mp_forcezero(mp_int * a); -MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_unsigned_bin_size(const mp_int * a); MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); @@ -296,10 +294,10 @@ MP_API int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, /* end functions needed by Rsa */ /* functions added to support above needed, removed TOOM and KARATSUBA */ -MP_API int mp_count_bits (mp_int * a); +MP_API int mp_count_bits (const mp_int * a); MP_API int mp_leading_bit (mp_int * a); MP_API int mp_init_copy (mp_int * a, mp_int * b); -MP_API int mp_copy (mp_int * a, mp_int * b); +MP_API int mp_copy (const mp_int * a, mp_int * b); MP_API int mp_grow (mp_int * a, int size); MP_API int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); MP_API void mp_zero (mp_int * a); diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index 88514b78e..092186429 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -1,6 +1,6 @@ /* logging.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/md2.h b/wolfssl/wolfcrypt/md2.h index 565385e73..8aeb4f483 100644 --- a/wolfssl/wolfcrypt/md2.h +++ b/wolfssl/wolfcrypt/md2.h @@ -1,6 +1,6 @@ /* md2.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/md4.h b/wolfssl/wolfcrypt/md4.h index 1344f8b88..cf203d97d 100644 --- a/wolfssl/wolfcrypt/md4.h +++ b/wolfssl/wolfcrypt/md4.h @@ -1,6 +1,6 @@ /* md4.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index e2ee13c32..d469147bc 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -1,6 +1,6 @@ /* md5.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -42,9 +42,12 @@ extern "C" { #endif +#if !defined(NO_OLD_MD5_NAME) + #define MD5 WC_MD5 +#endif + #ifndef NO_OLD_WC_NAMES #define Md5 wc_Md5 - #define MD5 WC_MD5 #define MD5_BLOCK_SIZE WC_MD5_BLOCK_SIZE #define MD5_DIGEST_SIZE WC_MD5_DIGEST_SIZE #define WC_MD5_PAD_SIZE WC_MD5_PAD_SIZE @@ -71,7 +74,7 @@ enum { #ifdef WOLFSSL_TI_HASH #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#elif defined(WOLFSSL_IMX6_CAAM) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM) #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" #else @@ -109,6 +112,9 @@ WOLFSSL_API int wc_InitMd5_ex(wc_Md5*, void*, int); WOLFSSL_API int wc_Md5Update(wc_Md5*, const byte*, word32); WOLFSSL_API int wc_Md5Final(wc_Md5*, byte*); WOLFSSL_API void wc_Md5Free(wc_Md5*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wc_Md5Transform(wc_Md5*, const byte*); +#endif WOLFSSL_API int wc_Md5GetHash(wc_Md5*, byte*); WOLFSSL_API int wc_Md5Copy(wc_Md5*, wc_Md5*); diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index 1d5ade9d4..362ef3969 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -1,6 +1,6 @@ /* mem_track.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index d901b2f92..42e36096b 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -1,6 +1,6 @@ /* memory.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/misc.h b/wolfssl/wolfcrypt/misc.h index 2fc4e2b11..748688fe9 100644 --- a/wolfssl/wolfcrypt/misc.h +++ b/wolfssl/wolfcrypt/misc.h @@ -1,6 +1,6 @@ /* misc.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/mpi_class.h b/wolfssl/wolfcrypt/mpi_class.h index ae2fa830c..e04acc263 100644 --- a/wolfssl/wolfcrypt/mpi_class.h +++ b/wolfssl/wolfcrypt/mpi_class.h @@ -1,6 +1,6 @@ /* mpi_class.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/mpi_superclass.h b/wolfssl/wolfcrypt/mpi_superclass.h index 186ac7505..91ebad820 100644 --- a/wolfssl/wolfcrypt/mpi_superclass.h +++ b/wolfssl/wolfcrypt/mpi_superclass.h @@ -1,6 +1,6 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/pkcs11.h b/wolfssl/wolfcrypt/pkcs11.h index bf1cb1ec9..09e2e6846 100644 --- a/wolfssl/wolfcrypt/pkcs11.h +++ b/wolfssl/wolfcrypt/pkcs11.h @@ -1,6 +1,6 @@ /* pkcs11.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/pkcs12.h b/wolfssl/wolfcrypt/pkcs12.h index 362c8bf57..fa8b331ec 100644 --- a/wolfssl/wolfcrypt/pkcs12.h +++ b/wolfssl/wolfcrypt/pkcs12.h @@ -1,6 +1,6 @@ /* pkcs12.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index e6b5fcdcd..4f24e8183 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -1,6 +1,6 @@ /* pkcs7.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/poly1305.h b/wolfssl/wolfcrypt/poly1305.h index d0bb2ff8e..a0e0b3abf 100644 --- a/wolfssl/wolfcrypt/poly1305.h +++ b/wolfssl/wolfcrypt/poly1305.h @@ -1,6 +1,6 @@ /* poly1305.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -109,18 +109,20 @@ typedef struct Poly1305 { /* does init */ WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key, - word32 kySz); + word32 kySz); WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32); WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag); /* AEAD Functions */ WOLFSSL_API int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad); -WOLFSSL_API int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz); +WOLFSSL_API int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, + word32 dataSz); #ifdef WORD64_AVAILABLE -WOLFSSL_API int wc_Poly1305_EncodeSizes64(Poly1305* ctx, word64 aadSz, word64 dataSz); +WOLFSSL_API int wc_Poly1305_EncodeSizes64(Poly1305* ctx, word64 aadSz, + word64 dataSz); #endif -WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, - byte* input, word32 sz, byte* tag, word32 tagSz); +WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, const byte* additional, + word32 addSz, const byte* input, word32 sz, byte* tag, word32 tagSz); #if defined(__aarch64__ ) && defined(WOLFSSL_ARMASM) void poly1305_blocks(Poly1305* ctx, const unsigned char *m, diff --git a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h index 526249821..e3d2cc64c 100644 --- a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h +++ b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h @@ -1,6 +1,6 @@ /* esp32-crypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -89,11 +89,13 @@ uint64_t wc_esp32elapsedTime(); /* RAW hash function APIs are not implemented with esp32 hardware acceleration*/ #define WOLFSSL_NO_HASH_RAW +#define SHA_CTX ETS_SHAContext #if ESP_IDF_VERSION_MAJOR >= 4 #include "esp32/rom/sha.h" #else #include "rom/sha.h" #endif +#undef SHA_CTX typedef enum { ESP32_SHA_INIT = 0, diff --git a/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h b/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h index 996c8c40e..7902b002d 100644 --- a/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h +++ b/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h @@ -1,6 +1,6 @@ /* renesas-tsip-crypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h b/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h index bd02913e2..5fbcb6733 100644 --- a/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h +++ b/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h @@ -1,6 +1,6 @@ /* afalg_hash.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h b/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h index d9f5b7155..27d712762 100644 --- a/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h +++ b/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h @@ -1,6 +1,6 @@ /* wc_afalg.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/arm/cryptoCell.h b/wolfssl/wolfcrypt/port/arm/cryptoCell.h index 5ca2d8c19..e434054d7 100644 --- a/wolfssl/wolfcrypt/port/arm/cryptoCell.h +++ b/wolfssl/wolfcrypt/port/arm/cryptoCell.h @@ -1,6 +1,6 @@ /* cryptoCell.h * - * Copyright (C) 2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/atmel/atmel.h b/wolfssl/wolfcrypt/port/atmel/atmel.h index b917a8022..b26637550 100644 --- a/wolfssl/wolfcrypt/port/atmel/atmel.h +++ b/wolfssl/wolfcrypt/port/atmel/atmel.h @@ -1,6 +1,6 @@ /* atmel.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -119,7 +119,7 @@ int atmel_ecc_create_pms(int slotId, const uint8_t* peerKey, uint8_t* pms); int atmel_ecc_create_key(int slotId, byte* peerKey); int atmel_ecc_sign(int slotId, const byte* message, byte* signature); int atmel_ecc_verify(const byte* message, const byte* signature, - const byte* pubkey, int* verified); + const byte* pubkey, int* pVerified); #endif /* WOLFSSL_ATECC508A */ diff --git a/wolfssl/wolfcrypt/port/caam/caam_driver.h b/wolfssl/wolfcrypt/port/caam/caam_driver.h index cac1742c0..701af3611 100644 --- a/wolfssl/wolfcrypt/port/caam/caam_driver.h +++ b/wolfssl/wolfcrypt/port/caam/caam_driver.h @@ -1,6 +1,6 @@ /* caam_driver.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -22,11 +22,25 @@ #ifndef CAAM_DRIVER_H #define CAAM_DRIVER_H -#define CAAM_BASE 0xf2100000 +#if (defined(__QNX__) || defined(__QNXNTO__)) + int InitCAAM(void); + #include "caam_qnx.h" +#endif +#if (defined(__INTEGRITY) || defined(INTEGRITY)) + #define CAAM_BASE 0xf2100000 + #define CAAM_PAGE 0xf0100000 +#endif + -#define CAAM_PAGE 0xf0100000 #define CAAM_PAGE_MAX 6 +/* max size of 64 word32's */ +#define CAAM_DESC_MAX 256 + +#ifndef CAAM_JOBRING_SIZE +#define CAAM_JOBRING_SIZE 1 +#endif + /****************************************************************************** Basic Descriptors ****************************************************************************/ @@ -50,12 +64,16 @@ #define CAAM_HEAD 0xB0800000 #define CAAM_NWB 0x00200000 + /* PROTOCOL OPERATION command */ +#define CAAM_PROT_UNIDI 0 #define CAAM_BLOB_ENCAP 0x07000000 #define CAAM_BLOB_DECAP 0x06000000 +#define CAAM_PKHA_OP 0x01000000 + #define CAAM_OPID_BLOB 0x000D0000 /* algorithms modes and types */ -#define CAAM_CLASS1 0x02000000/* i.e. AES */ +#define CAAM_CLASS1 0x02000000/* i.e. AES, PKHA */ #define CAAM_CLASS2 0x04000000/* i.e. hash algos */ #define CAAM_ENC 0x00000001 @@ -90,6 +108,38 @@ #define CAAM_HMAC_SHA384 0x00440010 #define CAAM_HMAC_SHA512 0x00450010 +/* ECDSA ECDSEL (pre defined flags for ECDSA parameters i.e. order) */ +#define CAAM_ECDSEL_SHIFT 7 +#define CAAM_ECDSA_PD 0x00400000 +#define CAAM_ECDSA_KEYGEN_PD 0x02000000 +#define CAAM_ECDSA_P192 (0x00 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P224 (0x01 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P256 (0x02 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P384 (0x03 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P521 (0x04 << CAAM_ECDSEL_SHIFT) + +#define CAAM_ECDSA_BRAINPOOL_P256 (0x0B << CAAM_ECDSEL_SHIFT) + + /* PKHA Operation ID ECDSA */ +#define CAAM_ECDSA_KEYPAIR 0x00140000 +#define CAAM_ECDSA_SIGN 0x00150000 +#define CAAM_ECDSA_VERIFY 0x00160000 +#define CAAM_ECDSA_ECDH 0x00170000 + +#define CAAM_ECDSA_MESREP_HASHED (0x10 << 7) + + /* key encryption bit */ +#define CAAM_PKHA_ECC 0x00000002 +#define CAAM_PKHA_ENC_PRI_AESCBC 0x00000004 +#define CAAM_PKHA_ENC_PRI_AESCCM (0x00000010 | CAAM_PKHA_ENC_PRI_AESCBC) +#define CAAM_PKHA_NO_TIMING_RESISTANCE 0x40000000 +#define CAAM_LOAD_BLACK_KEY 0x500000 + + /* PKHA RSA */ +#define CAAM_OPID_RSA_ENCRYPT 0x00180000 +#define CAAM_OPID_RSA_DECRYPT 0x00190000 + + #define CAAM_MD5_CTXSZ (16 + 8) #define CAAM_SHA_CTXSZ (20 + 8) #define CAAM_SHA224_CTXSZ (32 + 8) @@ -117,16 +167,18 @@ #define CAAM_PAGE_SZ 4096 /* RNG Registers */ -#define CAAM_RTMCTL CAAM_BASE + 0X0600 -#define CAAM_RTSDCTL CAAM_BASE + 0X0610 -#define CAAM_RTFRQMIN CAAM_BASE + 0X0618 -#define CAAM_RTFRQMAX CAAM_BASE + 0X061C -#define CAAM_RDSTA CAAM_BASE + 0X06C0 -#define CAAM_RTSTATUS CAAM_BASE + 0x063C +#define CAAM_RTMCTL 0X0600 +#define CAAM_RTSDCTL 0X0610 +#define CAAM_RTFRQMIN 0X0618 +#define CAAM_RTFRQMAX 0X061C +#define CAAM_RDSTA 0X06C0 +#define CAAM_RTSTATUS 0x063C +#define CAAM_RDINT0 0x06D0 /* each of the following 11 RTENT registers are an offset of 4 from RTENT0 */ -#define CAAM_RTENT0 CAAM_BASE + 0x0640 -#define CAAM_RTENT11 CAAM_BASE + 0x066C /* Max RTENT register */ +#define CAAM_RTENT0 0x0640 +#define CAAM_RTENT11 0x066C /* Max RTENT register */ +#define CAAM_RTENT_MAX 0x067C /* RNG Masks/Values */ #ifndef CAAM_ENT_DLY @@ -138,50 +190,198 @@ #define CAAM_ENTVAL 0x00000400 /* checking RTMCTL for entropy ready */ /* Input Job Ring Registers */ -#define CAAM_IRBAR0 CAAM_BASE + 0x1004 -#define CAAM_IRSR0 CAAM_BASE + 0x100C -#define CAAM_IRJAR0 CAAM_BASE + 0x101C +#define CAAM_IRBAR0 0x1004 + //0x1004 +#define CAAM_IRSR0 0x100C +#define CAAM_IRJAR0 0x101C + +#define CAAM_IRBAR2 0x3000 +#define CAAM_IRSR2 0x300C +#define CAAM_IRJAR2 0x301C +#define CAAM_IRSAR_JR2 0x3014 + + /* Output Job Ring Registers */ -#define CAAM_ORBAR0 CAAM_BASE + 0x1024 -#define CAAM_ORSR0 CAAM_BASE + 0x102C -#define CAAM_ORJAR0 CAAM_BASE + 0x103C +#define CAAM_ORBAR0 0x1024 + //0x1024 +#define CAAM_ORSR0 0x102C +#define CAAM_ORJAR0 0x103C +#define CAAM_ORBAR2 0x3024 + //0x1024 +#define CAAM_ORSR2 0x302C +#define CAAM_ORJAR2 0x303C + +#define JRCFGR_JR0_LS 0x1054 + /* Status Registers */ -#define CAAM_STATUS CAAM_BASE + 0x0FD4 -#define CAAM_VERSION_MS CAAM_BASE + 0x0FE8 -#define CAAM_VERSION_LS CAAM_BASE + 0x0FEC -#define CAMM_SUPPORT_MS CAAM_BASE + 0x0FF0 -#define CAMM_SUPPORT_LS CAAM_BASE + 0x0FF4 +#define CAAM_STATUS 0x0FD4 +#define CAAM_VERSION_MS 0x0FE8 +#define CAAM_VERSION_LS 0x0FEC +#define CAMM_SUPPORT_MS 0x0FF0 +#define CAMM_SUPPORT_LS 0x0FF4 +#define CAAM_SM_CMD 0x1BE4 +#define CAAM_SM_SMPO 0x1FBC +#define CAAM_SM_SMVID_MS 0x1FD8 +#define CAAM_SM_SMVID_LS 0x1FDC +#define CAAM_SM_STATUS 0x1BEC +#define CAAM_SM_CSP 0x00008000 +#define CAAM_SM_SMAP_LOCK 0x00002000 +#define CAAM_SM_SMAG_LOCK 0x00001000 +#define CAAM_SM_ALL_RW 0x000000FF -#define CAAM_C1DSR_LS CAAM_BASE + 0x8014 -#define CAAM_C1MR CAAM_BASE + 0x8004 +#define CAAM_C1DSR_LS 0x8014 +#define CAAM_C1MR 0x8004 /* output FIFO is 16 entries deep and each entry has a two 4 byte registers */ -#define CAAM_FIFOO_MS CAAM_BASE + 0x87F0 -#define CAAM_FIFOO_LS CAAM_BASE + 0x87F4 +#define CAAM_FIFOO_MS 0x87F0 +#define CAAM_FIFOO_LS 0x87F4 /* input FIFO is 16 entries deep with each entry having two 4 byte registers All data written to it from IP bus should be in big endian format */ -#define CAAM_FIFOI_LS CAAM_BASE + 0x87E0 +#define CAAM_FIFOI_LS 0x87E0 /* offset of 4 with range 0 .. 13 */ -#define CAAM_CTX1 CAAM_BASE + 0x8100 +#define CAAM_CTX1 0x8100 #define CAAM_CTRIV CAAM_CTX1 + 8 /* AES-CTR iv is in 2 and 3 */ #define CAAM_CBCIV CAAM_CTX1 /* AES-CBC iv is in 1 and 2 */ -/* instantiate RNG and create JDKEK, TDKEK, and TDSK key */ -static unsigned int wc_rng_start[] = { - CAAM_HEAD | 0x00000006, - CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00000004, /* Instantiate RNG handle 0 with TRNG */ - CAAM_JUMP | 0x02000001, /* wait for Class1 RNG and jump to next cmd */ - CAAM_LOAD | 0x00880004, /* Load to clear written register */ - 0x00000001, /* reset done interrupt */ - CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00001000 /* Generate secure keys */ + /* debugging registers */ +#define CAAM_DECORR 0x009C /* used to set DECO into debug mode */ +#define CAAM_DODJR 0x8E00 /* for hung operations */ +#define CAAM_DOJQCR_MS 0x8800 +#define CAAM_DOOPSTA_MS 0x8810 /* DECO operation status register */ +#define CAAM_DODAR 0x8808 /* address of current descriptor */ +#define CAAM_DODESB 0x8A00 /* 64 registers that hold the current descriptor buffer */ + + +#define JRINTR_JR0 0x104C +#define JRINTR_JR1 0x204C +#define JRINTR_JR2 0x304C + +#define CAAM_SINGLE_STEP_MODE 0x40000000 +#define CAAM_STEP 0x80000000 + +/* Port layer for CAAM driver, functions defined in caam_.c */ +unsigned int CAAM_READ(unsigned int reg); +void CAAM_WRITE(unsigned int reg, unsigned int in); +int CAAM_SET_BASEADDR(void); +void CAAM_UNSET_BASEADDR(void); +unsigned int CAAM_ADR_TO_PHYSICAL(void* in, int inSz); +void* CAAM_ADR_MAP(unsigned int in, int inSz, unsigned char copy); +void CAAM_ADR_UNMAP(void* vaddr, unsigned int out, int outSz, + unsigned char copy); +int CAAM_ADR_SYNC(void* vaddr, int sz); +CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int length); + +#ifndef WOLFSSL_CAAM_BUFFER +#define WOLFSSL_CAAM_BUFFER +typedef struct CAAM_BUFFER { + int BufferType; + CAAM_ADDRESS TheAddress; + int Length; +} CAAM_BUFFER; +#endif +unsigned int caamReadRegister(unsigned int reg); +void caamWriteRegister(unsigned int reg, unsigned int in); +int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER *buf, int sz); +int CleanupCAAM(void); + + +/* Driver API that can be called by caam_.c port layers */ +typedef struct DESCSTRUCT DESCSTRUCT; + +int caamKeyCover(DESCSTRUCT *desc, int sz, unsigned int args[4]); +int caamTRNG(unsigned char *out, int outSz); +int caamECDSA_ECDH(DESCSTRUCT *desc, int sz, unsigned int args[4]); +int caamECDSASign(DESCSTRUCT *desc, int sz, unsigned int args[4]); +int caamECDSAVerify(DESCSTRUCT *desc, CAAM_BUFFER *buf, int sz, + unsigned int args[4]); +int caamECDSAMake(DESCSTRUCT *desc, CAAM_BUFFER *buf, unsigned int args[4]); + + +int caamAesCmac(DESCSTRUCT *desc, int sz, unsigned int args[4]); +int caamBlob(DESCSTRUCT *desc); + +CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag); +int caamFreePart(unsigned int part); +int caamFindUnusuedPartition(void); + + + +void caamDescInit(DESCSTRUCT* desc, int type, unsigned int args[4], + CAAM_BUFFER* buf, int sz); + + +/* CAAM descriptor */ +#define DESC_COUNT 1 +#define MAX_BUF 20 +#define BUFFER_COUNT (MAX_BUF * DESC_COUNT) + +/* CAAM descriptors can only be 64 unsigned ints */ +#define MAX_DESC_SZ 64 + +/* 64 byte buffer for when data crosses a page boundary */ +#define ALIGN_BUF 16 + +/* MAX_CTX is 64 bytes (sha512 digest) + 8 bytes (CAAM length value) */ +#define MAX_CTX 18 + +#define MIN_READ_REG CAAM_BASE +#define MAX_READ_REG (CAAM_BASE + 0x00010000) + +struct buffer { + CAAM_ADDRESS data; + CAAM_ADDRESS dataSz; }; +struct DESCSTRUCT { +#if defined(__INTEGRITY) || defined(INTEGRITY) + struct IORequestStruct TheIORequest; +#endif + struct CAAM_DEVICE* caam; + struct buffer buf[MAX_BUF]; /* buffers holding data input address */ + unsigned int desc[MAX_DESC_SZ]; /* max size of 64 word32 */ + unsigned int aadSzBuf[4]; /* Formatted AAD size for CCM */ + unsigned int alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page + align */ + unsigned int iv[MAX_CTX]; /* AES IV and also hash state */ + unsigned int ctxBuf[MAX_CTX]; /* key */ + CAAM_ADDRESS output; /* address to output buffer */ + CAAM_ADDRESS ctxOut; /* address to update buffer holding state */ + Value alignIdx;/* index for align buffer */ + Value idx; /* index for descriptor buffer */ + Value headIdx; /* for first portion of descriptor buffer */ + Value lastIdx; /* for last portion of descriptor buffer */ + Value outputIdx; /* idx to output buffer in "buf" */ + Value inputSz; /* size of input buffer */ + Value ctxSz; /* size of CTX/Key buffer */ + Value aadSz; /* AAD size for CCM */ + Value startIdx; /* for telling header where to start */ + Value lastFifo; + Value type; + Value state; + Value DescriptorCount; + Boolean running; /* True if building/running descriptor is + in process */ +}; + +/* wolfSSL specific flags */ +#define CAAM_FIND_PART 0xFFFFFFFF +#define CAAM_GET_PART 0xFFFFFFFE +#define CAAM_FREE_PART 0xFFFFFFFD +#define CAAM_READ_PART 0xFFFFFFFC +#define CAAM_WRITE_PART 0xFFFFFFFB + + +#define MAX_ECDSA_VERIFY_ADDR 8 +#define MAX_ECDSA_SIGN_ADDR 8 +#define BLACK_KEY_MAC_SZ 16 +#define BLACK_BLOB_KEYMOD_SZ 16 +#define RED_BLOB_KEYMOD_SZ 8 #endif /* CAAM_DRIVER_H */ diff --git a/wolfssl/wolfcrypt/port/caam/caam_error.h b/wolfssl/wolfcrypt/port/caam/caam_error.h new file mode 100644 index 000000000..28cd325ac --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/caam_error.h @@ -0,0 +1,29 @@ +/* caam_error.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef CAAM_ERROR_H +#define CAAM_ERROR_H + +int caamParseError(unsigned int error); +int caamParseDECOError(unsigned int error); +int caamParseCCBError(unsigned int error); +unsigned int caamParseJRError(unsigned int error); +#endif /* CAAM_ERROR_H */ diff --git a/wolfssl/wolfcrypt/port/caam/caam_qnx.h b/wolfssl/wolfcrypt/port/caam/caam_qnx.h new file mode 100644 index 000000000..b58397e5b --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/caam_qnx.h @@ -0,0 +1,70 @@ +/* caam_qnx.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* This file is porting low level QNX interactions, such as reading register */ + +#ifndef CAAM_QNX_H +#define CAAM_QNX_H + +#define WOLFSSL_MSG(in) + +#include +#include +#include +#include +#include + +#define CAAM_MUTEX pthread_mutex_t +#define CAAM_INIT_MUTEX(x) pthread_mutex_init((x), NULL) +#define CAAM_FREE_MUTEX(x) pthread_mutex_destroy((x)) +#define CAAM_LOCK_MUTEX(x) pthread_mutex_lock((x)) +#define CAAM_UNLOCK_MUTEX(x) pthread_mutex_unlock((x)) + +#define Error int +#define Value int +#define Boolean int +#define CAAM_ADDRESS unsigned int +#define Success 1 +#define Failure 0 +#define INTERRUPT_Panic() +#define MemoryMapMayNotBeEmpty -1 +#define CAAM_WAITING -2 +#define NoActivityReady -1 +#define MemoryOperationNotPerformed -1 + +#ifndef WOLFSSL_CAAM_BUFFER +#define WOLFSSL_CAAM_BUFFER + typedef struct CAAM_BUFFER { + int BufferType; + CAAM_ADDRESS TheAddress; + int Length; + } CAAM_BUFFER; +#endif + +/* check kernel and yield to same priority threads waiting */ +#define CAAM_CPU_CHILL() sched_yield() + +/* IMX6UL */ +#define CAAM_BASE 0x02140000 +#define CAAM_PAGE 0x00100000 + +#endif /* CAAM_QNX_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/wolfssl/wolfcrypt/port/caam/wolfcaam.h index 8c39605d7..a2f40929b 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -1,6 +1,6 @@ /* wolfcaam.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,13 +23,20 @@ #define WOLF_CRYPT_CAAM_INIT_H #include - -#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) - #include +/* include for porting layer */ +#ifdef WOLFSSL_QNX_CAAM + #include +#endif + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_QNX_CAAM) + + #if defined(__INTEGRITY) || defined(INTEGRITY) #include + typedef Buffer CAAM_BUFFER; #endif WOLFSSL_LOCAL int wc_caamInit(void); @@ -39,25 +46,107 @@ WOLFSSL_LOCAL int wc_caamFreeRng(void); WOLFSSL_LOCAL word32 wc_caamReadRegister(word32 reg); WOLFSSL_LOCAL void wc_caamWriteRegister(word32 reg, word32 value); -WOLFSSL_LOCAL int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type); +WOLFSSL_LOCAL int wc_caamAddAndWait(CAAM_BUFFER* buf, int sz, word32 arg[4], + word32 type); -WOLFSSL_API int wc_caamSetResource(IODevice ioDev); +WOLFSSL_LOCAL int caamFindUnusuedPartition(void); +WOLFSSL_LOCAL CAAM_ADDRESS caamGetPartition(int part, int sz); +WOLFSSL_LOCAL int caamFreePart(int partNum); +WOLFSSL_LOCAL int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* in, int inSz); +WOLFSSL_LOCAL int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz); WOLFSSL_API int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz); WOLFSSL_API int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz); +WOLFSSL_API int wc_caamOpenBlob_ex(byte* data, word32 dataSz, byte* out, + word32* outSz, int type, byte* mod, word32 modSz); +WOLFSSL_API int wc_caamCreateBlob_ex(byte* data, word32 dataSz, byte* out, + word32* outSz, int type, byte* mod, word32 modSz); +WOLFSSL_API int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, + int flag); + /* additional size that is added by CAAM when creating a blob */ #define WC_CAAM_BLOB_SZ 48 +#define WC_CAAM_MAC_SZ 16 +#define WC_CAAM_BLOB_RED 1 +#define WC_CAAM_BLOB_BLACK 2 +#define WC_CAAM_RED_KEYMOD_SZ 8 +#define WC_CAAM_BLACK_KEYMOD_SZ 16 +#define WC_CAAM_MAX_ENTROPY 44 -#ifndef WC_CAAM_READ - #define WC_CAAM_READ(reg) wc_caamReadRegister((reg)) -#endif -#ifndef WC_CAAM_WRITE - #define WC_CAAM_WRITE(reg, x) wc_caamWriteRegister((reg), (x)) +#ifndef WOLFSSL_QNX_CAAM + WOLFSSL_API int wc_caamSetResource(IODevice ioDev); + #ifndef WC_CAAM_READ + #define WC_CAAM_READ(reg) wc_caamReadRegister((reg)) + #endif + #ifndef WC_CAAM_WRITE + #define WC_CAAM_WRITE(reg, x) wc_caamWriteRegister((reg), (x)) + #endif #endif + +#define CAAM_AESCTR 0x00100000 +#define CAAM_AESCBC 0x00100100 +#define CAAM_AESECB 0x00100200 +#define CAAM_AESCFB 0x00100300 +#define CAAM_AESOFB 0x00100400 +#define CAAM_CMAC 0x00100600 +#define CAAM_AESCCM 0x00100800 + +#define CAAM_MD5 0x00400000 +#define CAAM_SHA 0x00410000 +#define CAAM_SHA224 0x00420000 +#define CAAM_SHA256 0x00430000 +#define CAAM_SHA384 0x00440000 +#define CAAM_SHA512 0x00450000 + +#define CAAM_HMAC_MD5 0x00400010 +#define CAAM_HMAC_SHA 0x00410010 +#define CAAM_HMAC_SHA224 0x00420010 +#define CAAM_HMAC_SHA256 0x00430010 +#define CAAM_HMAC_SHA384 0x00440010 +#define CAAM_HMAC_SHA512 0x00450010 + +#define CAAM_ECDSA_KEYPAIR 0x00140000 +#define CAAM_ECDSA_SIGN 0x00150000 +#define CAAM_ECDSA_VERIFY 0x00160000 +#define CAAM_ECDSA_ECDH 0x00170000 + +#define CAAM_BLOB_ENCAP 0x07000000 +#define CAAM_BLOB_DECAP 0x06000000 +#define CAAM_FIFO_S 0x60000000 +#define CAAM_FIFO_CCM_FLAG 0x00140000 + +#define CAAM_ENC 0x00000001 +#define CAAM_DEC 0x00000000 +#define CAAM_ALG_INIT 0x00000004 +#define CAAM_ALG_INITF 0x0000000C +#define CAAM_ALG_UPDATE 0x00000000 +#define CAAM_ALG_FINAL 0x00000008 + +/* ECDSA ECDSEL (pre defined flags for ECDSA parameters i.e. order) */ +#define CAAM_ECDSEL_SHIFT 7 +#define CAAM_ECDSA_PD 0x00400000 +#define CAAM_ECDSA_KEYGEN_PD 0x02000000 +#define CAAM_ECDSA_P192 (0x00 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P224 (0x01 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P256 (0x02 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P384 (0x03 << CAAM_ECDSEL_SHIFT) +#define CAAM_ECDSA_P521 (0x04 << CAAM_ECDSEL_SHIFT) + +#define CAAM_ECDSA_BRAINPOOL_P256 (0x0B << CAAM_ECDSEL_SHIFT) + +#define CAAM_ENTROPY 0x00500001 + +/* wolfSSL specific flags */ +#define CAAM_FIND_PART 0xFFFFFFFF +#define CAAM_GET_PART 0xFFFFFFFE +#define CAAM_FREE_PART 0xFFFFFFFD +#define CAAM_READ_PART 0xFFFFFFFC +#define CAAM_WRITE_PART 0xFFFFFFFB + #endif /* WOLFSSL_IMX6_CAAM */ #endif /* WOLF_CRYPT_CAAM_INIT_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h new file mode 100644 index 000000000..d075c9816 --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h @@ -0,0 +1,36 @@ +/* wolfcaam_cmac.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#include + +#ifndef WOLFCAAM_CMAC_H +#define WOLFCAAM_CMAC_H + +#if defined(WOLFSSL_CMAC) && defined(WOLFSSL_QNX_CAAM) + +#include + +WOLFSSL_LOCAL int wc_CAAM_Cmac(Cmac* cmac, const byte* key, word32 keySz, + const byte* in, word32 inSz, byte* out, word32* outSz, int type, + void* ctx); +#endif +#endif /* WOLFCAAM_CMAC_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h new file mode 100644 index 000000000..36dbe831a --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_ecdsa.h @@ -0,0 +1,42 @@ +/* wolfcaam_ecdsa.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include + +#ifndef WOLFCAAM_ECDSA_H +#define WOLFCAAM_ECDSA_H + +#if defined(HAVE_ECC) && defined(WOLFSSL_QNX_CAAM) + +#include + +WOLFSSL_LOCAL int wc_CAAM_EccSign(const byte* in, int inlen, byte* out, + word32* outlen, WC_RNG *rng, ecc_key *key); +WOLFSSL_LOCAL int wc_CAAM_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key); +WOLFSSL_LOCAL int wc_CAAM_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen); +WOLFSSL_LOCAL int wc_CAAM_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, + int curveId); +WOLFSSL_LOCAL int wc_CAAM_EccCheckPrivKey(ecc_key* key, const byte* pubKey, + word32 pubKeySz); +#endif /* HAVE_ECC && WOLFSSL_QNX_CAAM */ +#endif /* WOLFCAAM_ECDSA_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h new file mode 100644 index 000000000..526d6c486 --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h @@ -0,0 +1,84 @@ +/* wolfcaam_qnx.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* This file is for interacting with the driver code */ +#ifndef WOLFCAAM_QNX_H +#define WOLFCAAM_QNX_H + +#include + +#ifdef WOLFSSL_QNX_CAAM +#include +#include + +#define Error int +#define Value int +#define Boolean int +#define Success 1 +#define Failure 0 +#define INTERRUPT_Panic() +#define MemoryMapMayNotBeEmpty -1 +#define CAAM_WAITING -2 +#define NoActivityReady -1 +#define MemoryOperationNotPerformed -1 + +#define CAAM_ADDRESS unsigned int +#ifndef WOLFSSL_CAAM_BUFFER +#define WOLFSSL_CAAM_BUFFER + typedef struct CAAM_BUFFER { + int BufferType; + CAAM_ADDRESS TheAddress; + int Length; + } CAAM_BUFFER; +#endif + + +/* IMX6UL */ +#define CAAM_BASE 0x02140000 +#define CAAM_PAGE 0x00100000 + +#define DataBuffer 0 +#define LastBuffer 0 +#define Success 1 + +/* unique devId for CAAM use on crypto callbacks */ +#define WOLFSSL_CAAM_DEVID 7 + +#include +#include +#include + +#define ResourceNotAvailable -3 +#define CAAM_WAITING -2 + +WOLFSSL_LOCAL int SynchronousSendRequest(int type, unsigned int args[4], + CAAM_BUFFER *buf, int sz); +WOLFSSL_LOCAL int wc_CAAMInitInterface(void); +WOLFSSL_LOCAL void wc_CAAMFreeInterface(void); + +#define CAAM_SEND_REQUEST(type, sz, arg, buf) \ + SynchronousSendRequest((type), (arg), (buf), (sz)) +#define CAAM_INIT_INTERFACE wc_CAAMInitInterface +#define CAAM_FREE_INTERFACE wc_CAAMFreeInterface +#endif + +#endif /* WOLFCAAM_QNX_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h index 9f5eaf8b5..d18a9e1f3 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h @@ -1,6 +1,6 @@ /* wolfcaam_sha.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h b/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h index f7914b8e7..6a0d76045 100644 --- a/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h +++ b/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h @@ -1,8 +1,8 @@ /* cavium_octeon_sync.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifndef _CAVIUM_OCTEON_SYNC_H_ diff --git a/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h b/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h index 964f22162..a41ace703 100644 --- a/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h +++ b/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h @@ -1,6 +1,6 @@ /* psoc6_crypto.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,38 +23,18 @@ #define _PSOC6_CRYPTO_PORT_H_ #include -#ifdef USE_FAST_MATH - #include -#elif defined WOLFSSL_SP_MATH - #include -#else - #include -#endif #include "cy_crypto_core_sha.h" #include "cy_device_headers.h" #include "psoc6_02_config.h" #include "cy_crypto_common.h" #include "cy_crypto_core.h" -#ifdef WOLFSSL_SHA512 -typedef struct wc_Sha512 { - cy_stc_crypto_sha_state_t hash_state; - cy_en_crypto_sha_mode_t sha_mode; - cy_stc_crypto_v2_sha512_buffers_t sha_buffers; -} wc_Sha512; -#define WC_SHA512_TYPE_DEFINED +#ifdef WOLFSSL_SHA512 #include #endif #ifndef NO_SHA256 - -typedef struct wc_Sha256 { - cy_stc_crypto_sha_state_t hash_state; - cy_en_crypto_sha_mode_t sha_mode; - cy_stc_crypto_v2_sha256_buffers_t sha_buffers; -} wc_Sha256; - #include #include #endif /* !def NO_SHA256 */ diff --git a/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h b/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h index c8ddbe7b9..a20aae685 100644 --- a/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h +++ b/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h @@ -1,6 +1,6 @@ /* wc_devcrypto.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/intel/quickassist_sync.h b/wolfssl/wolfcrypt/port/intel/quickassist_sync.h index 8eb9421f9..f140f618c 100644 --- a/wolfssl/wolfcrypt/port/intel/quickassist_sync.h +++ b/wolfssl/wolfcrypt/port/intel/quickassist_sync.h @@ -1,8 +1,8 @@ /* quickassist_sync.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #ifndef _INTEL_QUICKASSIST_SYNC_H_ diff --git a/wolfssl/wolfcrypt/port/nrf51.h b/wolfssl/wolfcrypt/port/nrf51.h index b18b0400a..169d9cf50 100644 --- a/wolfssl/wolfcrypt/port/nrf51.h +++ b/wolfssl/wolfcrypt/port/nrf51.h @@ -1,6 +1,6 @@ /* nrf51.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/nxp/dcp_port.h b/wolfssl/wolfcrypt/port/nxp/dcp_port.h index 8d7fcd9ea..0813b37e7 100644 --- a/wolfssl/wolfcrypt/port/nxp/dcp_port.h +++ b/wolfssl/wolfcrypt/port/nxp/dcp_port.h @@ -1,6 +1,6 @@ /* dcp_port.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -22,23 +22,22 @@ #define _DCP_PORT_H_ #include -#ifdef USE_FAST_MATH - #include -#elif defined WOLFSSL_SP_MATH - #include -#else - #include +#include "fsl_dcp.h" + +#ifndef NO_SHA256 +#include +void DCPSha256Free(wc_Sha256 *sha256); #endif -#include -#include -#include "fsl_device_registers.h" -#include "fsl_debug_console.h" -#include "fsl_dcp.h" +#ifndef NO_SHA +#include +void DCPShaFree(wc_Sha *sha); +#endif int wc_dcp_init(void); #ifndef NO_AES +#include int DCPAesInit(Aes* aes); void DCPAesFree(Aes *aes); @@ -53,25 +52,5 @@ int DCPAesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); int DCPAesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); #endif -#ifndef NO_SHA256 -typedef struct wc_Sha256_DCP { - dcp_handle_t handle; - dcp_hash_ctx_t ctx; -} wc_Sha256; -#define WC_SHA256_TYPE_DEFINED - -void DCPSha256Free(wc_Sha256 *sha256); - -#endif - -#ifndef NO_SHA -typedef struct wc_Sha_DCP { - dcp_handle_t handle; - dcp_hash_ctx_t ctx; -} wc_Sha; -#define WC_SHA_TYPE_DEFINED - -void DCPShaFree(wc_Sha *sha); -#endif #endif diff --git a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h index f73579c2a..4b85f642d 100644 --- a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h +++ b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h @@ -1,6 +1,6 @@ /* ksdk_port.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h b/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h index bb288c777..4ffd8d144 100644 --- a/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h +++ b/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h @@ -1,6 +1,6 @@ /* pic32mz-crypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/silabs/silabs_aes.h b/wolfssl/wolfcrypt/port/silabs/silabs_aes.h index 3b9d4f140..798a1ef8f 100644 --- a/wolfssl/wolfcrypt/port/silabs/silabs_aes.h +++ b/wolfssl/wolfcrypt/port/silabs/silabs_aes.h @@ -1,6 +1,6 @@ /* silabs_aes.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/silabs/silabs_ecc.h b/wolfssl/wolfcrypt/port/silabs/silabs_ecc.h index ca13ea451..a55e5f6c4 100644 --- a/wolfssl/wolfcrypt/port/silabs/silabs_ecc.h +++ b/wolfssl/wolfcrypt/port/silabs/silabs_ecc.h @@ -1,6 +1,6 @@ /* silabs_ecc.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/silabs/silabs_hash.h b/wolfssl/wolfcrypt/port/silabs/silabs_hash.h index c0e5887e5..a88da7145 100644 --- a/wolfssl/wolfcrypt/port/silabs/silabs_hash.h +++ b/wolfssl/wolfcrypt/port/silabs/silabs_hash.h @@ -1,6 +1,6 @@ /* silabs_hash.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/silabs/silabs_random.h b/wolfssl/wolfcrypt/port/silabs/silabs_random.h index 3267c4d9e..4475ceff6 100644 --- a/wolfssl/wolfcrypt/port/silabs/silabs_random.h +++ b/wolfssl/wolfcrypt/port/silabs/silabs_random.h @@ -1,6 +1,6 @@ /* silabs_random.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/st/stm32.h b/wolfssl/wolfcrypt/port/st/stm32.h index 3db84c7e9..78112328b 100644 --- a/wolfssl/wolfcrypt/port/st/stm32.h +++ b/wolfssl/wolfcrypt/port/st/stm32.h @@ -1,6 +1,6 @@ /* stm32.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/st/stsafe.h b/wolfssl/wolfcrypt/port/st/stsafe.h index 3cee4461d..cf62a475d 100644 --- a/wolfssl/wolfcrypt/port/st/stsafe.h +++ b/wolfssl/wolfcrypt/port/st/stsafe.h @@ -1,6 +1,6 @@ /* stsafe.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/ti/ti-ccm.h b/wolfssl/wolfcrypt/port/ti/ti-ccm.h index f5d71fca1..4e47fd6e5 100644 --- a/wolfssl/wolfcrypt/port/ti/ti-ccm.h +++ b/wolfssl/wolfcrypt/port/ti/ti-ccm.h @@ -1,47 +1,47 @@ -/* port/ti/ti_ccm.c - * - * Copyright (C) 2006-2020 wolfSSL Inc. - * - * This file is part of wolfSSL. - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - */ +/* port/ti/ti_ccm.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_TI_CCM_H +#define WOLF_CRYPT_TI_CCM_H + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) + +int wolfSSL_TI_CCMInit(void) ; + +#ifndef SINGLE_THREADED +void wolfSSL_TI_lockCCM(void) ; +void wolfSSL_TI_unlockCCM(void) ; +#else +#define wolfSSL_TI_lockCCM() +#define wolfSSL_TI_unlockCCM() +#endif + +#endif + +#endif - -#ifndef WOLF_CRYPT_TI_CCM_H -#define WOLF_CRYPT_TI_CCM_H - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include - -#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) - -int wolfSSL_TI_CCMInit(void) ; - -#ifndef SINGLE_THREADED -void wolfSSL_TI_lockCCM(void) ; -void wolfSSL_TI_unlockCCM(void) ; -#else -#define wolfSSL_TI_lockCCM() -#define wolfSSL_TI_unlockCCM() -#endif - -#endif - -#endif - diff --git a/wolfssl/wolfcrypt/port/ti/ti-hash.h b/wolfssl/wolfcrypt/port/ti/ti-hash.h index 1c212458c..7c5d610b0 100644 --- a/wolfssl/wolfcrypt/port/ti/ti-hash.h +++ b/wolfssl/wolfcrypt/port/ti/ti-hash.h @@ -1,6 +1,6 @@ /* port/ti/ti-hash.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h b/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h index 47b462424..edaa4fa46 100644 --- a/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h +++ b/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h @@ -1,6 +1,6 @@ /* xil-sha3.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/pwdbased.h b/wolfssl/wolfcrypt/pwdbased.h index 13860fecb..e142adb98 100644 --- a/wolfssl/wolfcrypt/pwdbased.h +++ b/wolfssl/wolfcrypt/pwdbased.h @@ -1,6 +1,6 @@ /* pwdbased.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/rabbit.h b/wolfssl/wolfcrypt/rabbit.h index 20c269398..836b73705 100644 --- a/wolfssl/wolfcrypt/rabbit.h +++ b/wolfssl/wolfcrypt/rabbit.h @@ -1,6 +1,6 @@ /* rabbit.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index f32a39c7e..066eaff49 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -1,6 +1,6 @@ /* random.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/rc2.h b/wolfssl/wolfcrypt/rc2.h index 7a8bc6998..5aa641a82 100644 --- a/wolfssl/wolfcrypt/rc2.h +++ b/wolfssl/wolfcrypt/rc2.h @@ -1,6 +1,6 @@ /* rc2.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/ripemd.h b/wolfssl/wolfcrypt/ripemd.h index 9368648de..1e4c6b3be 100644 --- a/wolfssl/wolfcrypt/ripemd.h +++ b/wolfssl/wolfcrypt/ripemd.h @@ -1,6 +1,6 @@ /* ripemd.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 769af9ecf..316435147 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -1,6 +1,6 @@ /* rsa.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -283,7 +283,7 @@ WOLFSSL_API int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, enum wc_HashType hash, int mgf, RsaKey* key); -WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); +WOLFSSL_API int wc_RsaEncryptSize(const RsaKey* key); #if !defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) diff --git a/wolfssl/wolfcrypt/sakke.h b/wolfssl/wolfcrypt/sakke.h new file mode 100644 index 000000000..79fc314e4 --- /dev/null +++ b/wolfssl/wolfcrypt/sakke.h @@ -0,0 +1,228 @@ +/* sakke.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/sakke.h +*/ + + +#ifndef WOLF_CRYPT_SAKKE_H +#define WOLF_CRYPT_SAKKE_H + +#include + +#ifdef WOLFCRYPT_HAVE_SAKKE + +#include +#include +#include +#include + +#define WOLFCRYPT_SAKKE_KMS +#define WOLFCRYPT_SAKKE_CLIENT + +#define SAKKE_ID_MAX_SIZE 128 + +/* Maximum number of loops of attempting to generate a key. */ +#ifndef SAKKE_MAX_GEN_COUNT + #define SAKKE_MAX_GEN_COUNT 10 +#endif + + +/** MP integer in projective form. */ +typedef ecc_point mp_proj; + +/** SAKKE ECC parameters in usable format. */ +typedef struct SakkeKeyParams { + /** Prime as an MP integer. */ + mp_int prime; + /** Q (order) as an MP integer. */ + mp_int q; + /** G (pairing base) as an MP integer. */ + mp_int g; + /** Temporary MP integer used during operations. */ + mp_int a; + /** Base point for elliptic curve operations as an ECC point. */ + ecc_point* base; + + /** Bit indicate prime is set as an MP integer in SAKKE key. */ + byte havePrime:1; + /** Bit indicates q (order) is set as an MP integer in SAKKE key. */ + byte haveQ:1; + /** Bit indicates g (pairing base) is set as an MP integer in SAKKE key. */ + byte haveG:1; + /** Bit indicates a is set as an MP integer in SAKKE key. */ + byte haveA:1; + /** Bit indicates base point is set as an ECC point in SAKKE key. */ + byte haveBase:1; +} SakkeKeyParams; + +/** Temporary values to use in SAKKE calculations. */ +typedef struct SakkeKeyTmp { + /** Temporary MP integer used during operations. */ + mp_int m1; + /** Temporary MP integer used during operations. */ + mp_int m2; + +#ifdef WOLFCRYPT_SAKKE_CLIENT + /** Temporary elliptic curve point for use in operations. */ + ecc_point* p1; + /** Temporary elliptic curve point for use in operations. */ + ecc_point* p2; + /** Temporary MP projective integer for use in operations. */ + mp_proj* p3; +#endif +} SakkeKeyTmp; + +#ifdef WOLFCRYPT_SAKKE_CLIENT +/** SAKKE data for the intermediate point I. */ +typedef struct SakkeKeyPointI { + /** Temporary elliptic curve point for use in operations. */ + ecc_point* i; + /** Table associated with point I. */ + byte* table; + /** Length of table */ + int tableLen; + /** Identity associated with point I. */ + byte id[SAKKE_ID_MAX_SIZE]; + /** Size of identity associated with point I. */ + word16 idSz; +} SakkeKeyPointI; + +/** SAKKE data for the Receiver Secret Key (RSK). */ +typedef struct SakkeKeyRsk { + /** RSK (Receiver Secret Key). */ + ecc_point* rsk; + /** Table associated with point I. */ + byte* table; + /** Length of table */ + int tableLen; + /** Indicates whether an RSK value has been set. */ + byte set:1; +} SakkeKeyRsk; +#endif + +/** + * SAKKE key. + */ +typedef struct SakkeKey { + /** ECC key to perform elliptic curve operations with. */ + ecc_key ecc; + + /** ECC parameter in forms that can be used in computation. */ + SakkeKeyParams params; + /** Temporaries used during calculations. */ + SakkeKeyTmp tmp; + +#ifdef WOLFCRYPT_SAKKE_CLIENT + /** Data relating to the RSK (Receiver Secret Key). */ + SakkeKeyRsk rsk; + /** Identity to perform operations with. */ + byte id[SAKKE_ID_MAX_SIZE]; + /** Size of identity in bytes. */ + word16 idSz; + + /** Data relating to the intermediate point I. */ + SakkeKeyPointI i; + + /** Generic hash algorithm object. */ + wc_HashAlg hash; + /** Temporary buffer for use in operations. */ + byte data[(MAX_ECC_BYTES * 2) + 1]; +#endif + + /** Heap hint for dynamic memory allocation. */ + void* heap; + + /** Bit indicates Z, public key, is in montgomery form. */ + byte zMont:1; + /** Bit indicate MP integers have been initialized. */ + byte mpInit:1; +} SakkeKey; + +#ifdef __cplusplus + extern "C" { +#endif + +WOLFSSL_API int wc_InitSakkeKey(SakkeKey* key, void* heap, int devId); +WOLFSSL_API int wc_InitSakkeKey_ex(SakkeKey* key, int keySize, int curveId, + void* heap, int devId); +WOLFSSL_API void wc_FreeSakkeKey(SakkeKey* key); + +WOLFSSL_API int wc_MakeSakkeKey(SakkeKey* key, WC_RNG* rng); +WOLFSSL_API int wc_MakeSakkePublicKey(SakkeKey* key, ecc_point* pub); + +WOLFSSL_API int wc_MakeSakkeRsk(SakkeKey* key, const byte* id, word16 idSz, + ecc_point* rsk); +WOLFSSL_API int wc_ValidateSakkeRsk(SakkeKey* key, const byte* id, word16 idSz, + ecc_point* rsk, int* valid); + +WOLFSSL_API int wc_ExportSakkeKey(SakkeKey* key, byte* data, word32* sz); +WOLFSSL_API int wc_ImportSakkeKey(SakkeKey* key, const byte* data, word32 sz); +WOLFSSL_API int wc_ExportSakkePrivateKey(SakkeKey* key, byte* data, word32* sz); +WOLFSSL_API int wc_ImportSakkePrivateKey(SakkeKey* key, const byte* data, + word32 sz); +WOLFSSL_API int wc_ExportSakkePublicKey(SakkeKey* key, byte* data, + word32* sz, int raw); +WOLFSSL_API int wc_ImportSakkePublicKey(SakkeKey* key, const byte* data, + word32 sz, int trusted); + +WOLFSSL_API int wc_EncodeSakkeRsk(const SakkeKey* key, ecc_point* rsk, + byte* out, word32* sz, int raw); +WOLFSSL_API int wc_DecodeSakkeRsk(const SakkeKey* key, const byte* data, + word32 sz, ecc_point* rsk); +WOLFSSL_API int wc_ImportSakkeRsk(SakkeKey* key, const byte* data, word32 sz); + +WOLFSSL_API int wc_GetSakkeAuthSize(SakkeKey* key, word16* authSz); + +WOLFSSL_API int wc_SetSakkeIdentity(SakkeKey* key, const byte* id, word16 idSz); +WOLFSSL_API int wc_MakeSakkePointI(SakkeKey* key, const byte* id, word16 idSz); +WOLFSSL_API int wc_GetSakkePointI(SakkeKey* key, byte* data, word32* sz); +WOLFSSL_API int wc_SetSakkePointI(SakkeKey* key, const byte* id, word16 idSz, + const byte* data, word32 sz); +WOLFSSL_API int wc_GenerateSakkePointITable(SakkeKey* key, byte* table, + word32* len); +WOLFSSL_API int wc_SetSakkePointITable(SakkeKey* key, byte* table, word32 len); +WOLFSSL_API int wc_ClearSakkePointITable(SakkeKey* key); + +WOLFSSL_API int wc_MakeSakkeEncapsulatedSSV(SakkeKey* key, + enum wc_HashType hashType, byte* ssv, word16 ssvSz, byte* auth, + word16* authSz); + +WOLFSSL_API int wc_GenerateSakkeRskTable(const SakkeKey* key, + const ecc_point* rsk, byte* table, word32* len); +WOLFSSL_API int wc_SetSakkeRsk(SakkeKey* key, const ecc_point* rsk, byte* table, + word32 len); + +WOLFSSL_API int wc_GenerateSakkeSSV(SakkeKey* key, WC_RNG* rng, byte* ssv, + word16* ssvSz); +WOLFSSL_API int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, + byte* ssv, word16 ssvSz, const byte* auth, + word16 authSz); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_HAVE_SAKKE */ + +#endif /* WOLF_CRYPT_SAKKE_H */ + diff --git a/wolfssl/wolfcrypt/selftest.h b/wolfssl/wolfcrypt/selftest.h index 826b90d98..0d675259d 100644 --- a/wolfssl/wolfcrypt/selftest.h +++ b/wolfssl/wolfcrypt/selftest.h @@ -1,6 +1,6 @@ /* selftest.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 6d180137e..3787cf36c 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1,6 +1,6 @@ /* settings.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -218,6 +218,11 @@ /* Uncomment next line if building for Linux Kernel Module */ /* #define WOLFSSL_LINUXKM */ +/* Uncomment next line if building for devkitPro */ +/* #define DEVKITPRO */ + +/* Uncomment next line if building for Dolphin Emulator */ +/* #define DOLPHIN_EMULATOR */ #include @@ -1178,8 +1183,11 @@ extern void uITRON4_free(void *p) ; /* the LTC PKHA hardware limit is 2048 bits (256 bytes) for integer arithmetic. the LTC_MAX_INT_BYTES defines the size of local variables that hold big integers. */ - #ifndef LTC_MAX_INT_BYTES - #define LTC_MAX_INT_BYTES (256) + /* size is multiplication of 2 big ints */ + #if !defined(NO_RSA) || !defined(NO_DH) + #define LTC_MAX_INT_BYTES (256*2) + #else + #define LTC_MAX_INT_BYTES (48*2) #endif /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined. @@ -1240,7 +1248,8 @@ extern void uITRON4_free(void *p) ; #if defined(WOLFSSL_STM32F2) || defined(WOLFSSL_STM32F4) || \ defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32F1) || \ defined(WOLFSSL_STM32L4) || defined(WOLFSSL_STM32L5) || \ - defined(WOLFSSL_STM32WB) || defined(WOLFSSL_STM32H7) + defined(WOLFSSL_STM32WB) || defined(WOLFSSL_STM32H7) || \ + defined(WOLFSSL_STM32G0) #define SIZEOF_LONG_LONG 8 #ifndef CHAR_BIT @@ -1293,6 +1302,8 @@ extern void uITRON4_free(void *p) ; #include "stm32h7xx_hal.h" #elif defined(WOLFSSL_STM32WB) #include "stm32wbxx_hal.h" + #elif defined(WOLFSSL_STM32G0) + #include "stm32g0xx_hal.h" #endif #if defined(WOLFSSL_CUBEMX_USE_LL) && defined(WOLFSSL_STM32L4) #include "stm32l4xx_ll_rng.h" @@ -1343,7 +1354,8 @@ extern void uITRON4_free(void *p) ; #endif #endif /* WOLFSSL_STM32_CUBEMX */ #endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32L4 || - WOLFSSL_STM32L5 || WOLFSSL_STM32F7 || WOLFSSL_STMWB || WOLFSSL_STM32H7 */ + WOLFSSL_STM32L5 || WOLFSSL_STM32F7 || WOLFSSL_STMWB || + WOLFSSL_STM32H7 || WOLFSSL_STM32G0 */ #ifdef WOLFSSL_DEOS #include #include @@ -1375,7 +1387,6 @@ extern void uITRON4_free(void *p) ; #define WC_RSA_BLINDING #define HAVE_ECC - #define ALT_ECC_SIZE #define TFM_ECC192 #define TFM_ECC224 #define TFM_ECC256 @@ -1652,6 +1663,10 @@ extern void uITRON4_free(void *p) ; /* large performance gain with HAVE_AES_ECB defined */ #undef HAVE_AES_ECB #define HAVE_AES_ECB + + //@TODO used for now until plugging in caam aes use with qnx + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT #endif #endif @@ -1796,7 +1811,9 @@ extern void uITRON4_free(void *p) ; /* ECC Configs */ #ifdef HAVE_ECC /* By default enable Sign, Verify, DHE, Key Import and Key Export unless explicitly disabled */ - #ifndef NO_ECC_SIGN + #if !defined(NO_ECC_SIGN) && \ + (!defined(ECC_TIMING_RESISTANT) || \ + (defined(ECC_TIMING_RESISTANT) && !defined(WC_NO_RNG))) #undef HAVE_ECC_SIGN #define HAVE_ECC_SIGN #endif @@ -1808,7 +1825,7 @@ extern void uITRON4_free(void *p) ; #undef HAVE_ECC_CHECK_KEY #define HAVE_ECC_CHECK_KEY #endif - #ifndef NO_ECC_DHE + #if !defined(NO_ECC_DHE) && !defined(WC_NO_RNG) #undef HAVE_ECC_DHE #define HAVE_ECC_DHE #endif @@ -2094,8 +2111,9 @@ extern void uITRON4_free(void *p) ; #if defined(HAVE_IO_POOL) || defined(XMALLOC_USER) || defined(NO_WOLFSSL_MEMORY) #error static memory cannot be used with HAVE_IO_POOL, XMALLOC_USER or NO_WOLFSSL_MEMORY #endif - #if !defined(USE_FAST_MATH) && !defined(NO_BIG_INT) - #error static memory requires fast math please define USE_FAST_MATH + #if !defined(WOLFSSL_SP_NO_MALLOC) && \ + !defined(USE_FAST_MATH) && !defined(NO_BIG_INT) + #error The static memory option is only supported for fast math or SP with no malloc #endif #ifdef WOLFSSL_SMALL_STACK #error static memory does not support small stack please undefine @@ -2271,9 +2289,14 @@ extern void uITRON4_free(void *p) ; #if defined(NO_OLD_WC_NAMES) || defined(OPENSSL_EXTRA) /* added to have compatibility with SHA256() */ - #if !defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) + #if !defined(NO_OLD_SHA_NAMES) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) #define NO_OLD_SHA_NAMES #endif + #if !defined(NO_OLD_MD5_NAME) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + #define NO_OLD_MD5_NAME + #endif #endif /* switch for compatibility layer functionality. Has subparts i.e. BIO/X509 @@ -2421,6 +2444,47 @@ extern void uITRON4_free(void *p) ; #define NO_STRICT_ECDSA_LEN #endif +/* Do not allow using small stack with no malloc */ +#if defined(WOLFSSL_NO_MALLOC) && \ + (defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) + #error Small stack cannot be used with no malloc (WOLFSSL_NO_MALLOC) +#endif + +/* Enable DH Extra for QT, openssl all, openssh and static ephemeral */ +/* Allows export/import of DH key and params as DER */ +#if !defined(WOLFSSL_DH_EXTRA) && \ + (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) || \ + defined(WOLFSSL_STATIC_EPHEMERAL)) + #define WOLFSSL_DH_EXTRA +#endif + +/* DH Extra is not supported on FIPS v1 or v2 (is missing DhKey .pub/.priv) */ +#if defined(WOLFSSL_DH_EXTRA) && defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || HAVE_FIPS_VERSION <= 2) + #undef WOLFSSL_DH_EXTRA +#endif + +/* Check for insecure build combination: + * secure renegotiation [enabled] + * extended master secret [disabled] + * session resumption [enabled] + */ +#if defined(HAVE_SECURE_RENEGOTIATION) && !defined(HAVE_EXTENDED_MASTER) && \ + (defined(HAVE_SESSION_TICKET) || !defined(NO_SESSION_CACHE)) + /* secure renegotiation requires extended master secret with resumption */ + #ifndef _MSC_VER + #warning Extended master secret must be enabled with secure renegotiation and session resumption + #else + #pragma message("Warning: Extended master secret must be enabled with secure renegotiation and session resumption") + #endif + + /* Note: "--enable-renegotiation-indication" ("HAVE_RENEGOTIATION_INDICATION") + * only sends the secure renegotiation extension, but is not actually supported. + * This was added because some TLS peers required it even if not used, so we call + * this "(FAKE Secure Renegotiation)" + */ +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 6203d648d..cc55fa00d 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -1,6 +1,6 @@ /* sha.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -52,6 +52,10 @@ #include "fsl_ltc.h" #endif +#ifdef WOLFSSL_IMXRT_DCP + #include "fsl_dcp.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -72,9 +76,6 @@ #ifdef WOLFSSL_ESP32WROOM32_CRYPT #include #endif -#ifdef WOLFSSL_IMXRT_DCP - #include -#endif #if defined(WOLFSSL_SILABS_SE_ACCEL) #include #endif @@ -102,13 +103,11 @@ enum { #if defined(WOLFSSL_TI_HASH) #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#elif defined(WOLFSSL_IMX6_CAAM) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM) #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" #elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" -#elif defined(WOLFSSL_PSOC6_CRYPTO) - #include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h" #else /* Sha digest */ @@ -119,6 +118,9 @@ struct wc_Sha { STM32_HASH_Context stmCtx; #elif defined(WOLFSSL_SILABS_SE_ACCEL) wc_silabs_sha_t silabsCtx; +#elif defined(WOLFSSL_IMXRT_DCP) + dcp_handle_t handle; + dcp_hash_ctx_t ctx; #else word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ @@ -169,6 +171,9 @@ WOLFSSL_API void wc_ShaFree(wc_Sha*); WOLFSSL_API int wc_ShaGetHash(wc_Sha*, byte*); WOLFSSL_API int wc_ShaCopy(wc_Sha*, wc_Sha*); +#if defined(OPENSSL_EXTRA) +WOLFSSL_API int wc_ShaTransform(wc_Sha*, const byte*); +#endif #ifdef WOLFSSL_PIC32MZ_HASH WOLFSSL_API void wc_ShaSizeSet(wc_Sha* sha, word32 len); diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 9538fed7b..87744729b 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -1,6 +1,6 @@ /* sha256.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -61,6 +61,16 @@ #include "fsl_ltc.h" #endif +#ifdef WOLFSSL_IMXRT_DCP + #include "fsl_dcp.h" +#endif + +#if defined(WOLFSSL_PSOC6_CRYPTO) +#include "cy_crypto_core_sha.h" +#include "cy_device_headers.h" +#include "cy_crypto_common.h" +#include "cy_crypto_core.h" +#endif #ifdef __cplusplus extern "C" { @@ -122,17 +132,13 @@ enum { #ifdef WOLFSSL_TI_HASH #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#elif defined(WOLFSSL_IMX6_CAAM) +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM) #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" #elif defined(WOLFSSL_AFALG_HASH) #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h" #elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" -#elif defined(WOLFSSL_PSOC6_CRYPTO) - #include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h" -#elif defined(WOLFSSL_IMXRT_DCP) - #include #else /* wc_Sha256 digest */ @@ -143,6 +149,13 @@ struct wc_Sha256 { STM32_HASH_Context stmCtx; #elif defined(WOLFSSL_SILABS_SE_ACCEL) wc_silabs_sha_t silabsCtx; +#elif defined(WOLFSSL_IMXRT_DCP) + dcp_handle_t handle; + dcp_hash_ctx_t ctx; +#elif defined(WOLFSSL_PSOC6_CRYPTO) + cy_stc_crypto_sha_state_t hash_state; + cy_en_crypto_sha_mode_t sha_mode; + cy_stc_crypto_v2_sha256_buffers_t sha_buffers; #else /* alignment on digest and buffer speeds up ARMv8 crypto operations */ ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; @@ -198,7 +211,9 @@ WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32); WOLFSSL_API int wc_Sha256FinalRaw(wc_Sha256*, byte*); WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*); WOLFSSL_API void wc_Sha256Free(wc_Sha256*); - +#if defined(OPENSSL_EXTRA) +WOLFSSL_API int wc_Sha256Transform(wc_Sha256*, const byte*); +#endif WOLFSSL_API int wc_Sha256GetHash(wc_Sha256*, byte*); WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst); @@ -216,9 +231,12 @@ WOLFSSL_API void wc_Sha256SizeSet(wc_Sha256*, word32); #if !defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +#if !defined(NO_OLD_SHA_NAMES) + #define SHA224 WC_SHA224 +#endif + #ifndef NO_OLD_WC_NAMES #define Sha224 wc_Sha224 - #define SHA224 WC_SHA224 #define SHA224_BLOCK_SIZE WC_SHA224_BLOCK_SIZE #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE #define SHA224_PAD_SIZE WC_SHA224_PAD_SIZE diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h index 7ffef7791..19347b049 100644 --- a/wolfssl/wolfcrypt/sha3.h +++ b/wolfssl/wolfcrypt/sha3.h @@ -1,6 +1,6 @@ /* sha3.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index f3e79a263..620643b3d 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -1,6 +1,6 @@ /* sha512.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -79,6 +79,12 @@ #if defined(WOLFSSL_SILABS_SE_ACCEL) #include #endif +#if defined(WOLFSSL_PSOC6_CRYPTO) + #include "cy_crypto_core_sha.h" + #include "cy_device_headers.h" + #include "cy_crypto_common.h" + #include "cy_crypto_core.h" +#endif #if defined(_MSC_VER) #define SHA512_NOINLINE __declspec(noinline) @@ -114,13 +120,16 @@ enum { }; -#ifdef WOLFSSL_IMX6_CAAM +#if defined(WOLFSSL_IMX6_CAAM) && !defined(WOLFSSL_QNX_CAAM) #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" -#elif defined (WOLFSSL_PSOC6_CRYPTO) - #include "wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h" #else /* wc_Sha512 digest */ struct wc_Sha512 { +#ifdef WOLFSSL_PSOC6_CRYPTO + cy_stc_crypto_sha_state_t hash_state; + cy_en_crypto_sha_mode_t sha_mode; + cy_stc_crypto_v2_sha512_buffers_t sha_buffers; +#else word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; word64 buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64)]; word32 buffLen; /* in bytes */ @@ -147,6 +156,7 @@ struct wc_Sha512 { #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) word32 flags; /* enum wc_HashFlags in hash.h */ #endif +#endif /* WOLFSSL_PSOC6_CRYPTO */ }; #ifndef WC_SHA512_TYPE_DEFINED @@ -180,6 +190,9 @@ WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst); WOLFSSL_API int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags); #endif +#if defined(OPENSSL_EXTRA) +WOLFSSL_API int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data); +#endif #endif /* WOLFSSL_SHA512 */ #if defined(WOLFSSL_SHA384) diff --git a/wolfssl/wolfcrypt/signature.h b/wolfssl/wolfcrypt/signature.h index afaf2ec6c..d7c4188f2 100644 --- a/wolfssl/wolfcrypt/signature.h +++ b/wolfssl/wolfcrypt/signature.h @@ -1,6 +1,6 @@ /* signature.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h index f26486b47..d6728d02e 100644 --- a/wolfssl/wolfcrypt/sp.h +++ b/wolfssl/wolfcrypt/sp.h @@ -1,6 +1,6 @@ /* sp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -27,9 +27,15 @@ #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ defined(WOLFSSL_HAVE_SP_ECC) - -#ifndef WOLFSSL_LINUXKM -#include +#ifdef _WIN32_WCE + typedef __int8 int8_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; +#elif !defined(WOLFSSL_LINUXKM) + #include #endif #include @@ -56,6 +62,10 @@ #ifdef WOLFSSL_HAVE_SP_RSA +/* non-const versions only needed for inlined ARM assembly */ +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 \ + && ( defined(WOLFSSL_SP_ARM32_ASM) || defined(WOLFSSL_SP_ARM64_ASM) ) + WOLFSSL_LOCAL int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, byte* out, word32* outLen); WOLFSSL_LOCAL int sp_RsaPrivate_2048(const byte* in, word32 inLen, @@ -74,10 +84,39 @@ WOLFSSL_LOCAL int sp_RsaPrivate_4096(const byte* in, word32 inLen, mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, byte* out, word32* outLen); +#else + +WOLFSSL_LOCAL int sp_RsaPublic_2048(const byte* in, word32 inLen, + const mp_int* em, const mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_2048(const byte* in, word32 inLen, + const mp_int* dm, const mp_int* pm, const mp_int* qm, const mp_int* dpm, + const mp_int* dqm, const mp_int* qim, const mp_int* mm, byte* out, + word32* outLen); + +WOLFSSL_LOCAL int sp_RsaPublic_3072(const byte* in, word32 inLen, + const mp_int* em, const mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_3072(const byte* in, word32 inLen, + const mp_int* dm, const mp_int* pm, const mp_int* qm, const mp_int* dpm, + const mp_int* dqm, const mp_int* qim, const mp_int* mm, byte* out, + word32* outLen); + +WOLFSSL_LOCAL int sp_RsaPublic_4096(const byte* in, word32 inLen, + const mp_int* em, const mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_4096(const byte* in, word32 inLen, + const mp_int* dm, const mp_int* pm, const mp_int* qm, const mp_int* dpm, + const mp_int* dqm, const mp_int* qim, const mp_int* mm, byte* out, + word32* outLen); + +#endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */ + #endif /* WOLFSSL_HAVE_SP_RSA */ #if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA) +/* non-const versions only needed for inlined ARM assembly */ +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 \ + && ( defined(WOLFSSL_SP_ARM32_ASM) || defined(WOLFSSL_SP_ARM64_ASM) ) + WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res); WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, @@ -89,10 +128,29 @@ WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, WOLFSSL_LOCAL int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res); +#else + +WOLFSSL_LOCAL int sp_ModExp_1024(const mp_int* base, const mp_int* exp, + const mp_int* mod, mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(const mp_int* base, const mp_int* exp, + const mp_int* mod, mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(const mp_int* base, const mp_int* exp, + const mp_int* mod, mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(const mp_int* base, const mp_int* exp, + const mp_int* mod, mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_4096(const mp_int* base, const mp_int* exp, + const mp_int* mod, mp_int* res); + +#endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */ + #endif #ifdef WOLFSSL_HAVE_SP_DH +/* non-const versions only needed for inlined ARM assembly */ +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 \ + && ( defined(WOLFSSL_SP_ARM32_ASM) || defined(WOLFSSL_SP_ARM64_ASM) ) + WOLFSSL_LOCAL int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, mp_int* mod, byte* out, word32* outLen); WOLFSSL_LOCAL int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, @@ -100,10 +158,25 @@ WOLFSSL_LOCAL int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, WOLFSSL_LOCAL int sp_DhExp_4096(mp_int* base, const byte* exp, word32 expLen, mp_int* mod, byte* out, word32* outLen); +#else + +WOLFSSL_LOCAL int sp_DhExp_2048(const mp_int* base, const byte* exp, + word32 expLen, const mp_int* mod, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_DhExp_3072(const mp_int* base, const byte* exp, + word32 expLen, const mp_int* mod, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_DhExp_4096(const mp_int* base, const byte* exp, + word32 expLen, const mp_int* mod, byte* out, word32* outLen); + +#endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */ + #endif /* WOLFSSL_HAVE_SP_DH */ #ifdef WOLFSSL_HAVE_SP_ECC +/* non-const versions only needed for inlined ARM assembly */ +#if defined(HAVE_FIPS_VERSION) && HAVE_FIPS_VERSION == 2 \ + && ( defined(WOLFSSL_SP_ARM32_ASM) || defined(WOLFSSL_SP_ARM64_ASM) ) + int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* rm, int map, void* heap); int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* rm, int map, void* heap); @@ -147,15 +220,94 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ); int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym); +#else + +int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* rm, + int map, void* heap); +int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* rm, int map, void* heap); +int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* rm, int map, + void* heap); +int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* rm, int map, void* heap); + +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap); +int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, + word32* outlen, void* heap); +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm, + int* res, void* heap); +int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY); +int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap); +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ); +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym); + +int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* rm, + int map, void* heap); +int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm, + const ecc_point* am, int inMont, ecc_point* rm, int map, void* heap); +int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* rm, int map, + void* heap); +int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* rm, int map, void* heap); + +int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap); +int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, + word32* outlen, void* heap); +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm, + int* res, void* heap); +int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY); +int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap); +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ); +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym); + +int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* rm, + int map, void* heap); +int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* rm, int map, + void* heap); +int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am, + int inMont, ecc_point* rm, int map, void* heap); +int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len, + void* heap); +int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table, + ecc_point* r, int map, void* heap); +int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res); +int sp_Pairing_1024(const ecc_point* p, const ecc_point* q, mp_int* res); +int sp_Pairing_gen_precomp_1024(const ecc_point* p, byte* table, word32* len); +int sp_Pairing_precomp_1024(const ecc_point* p, const ecc_point* q, mp_int* res, + const byte* table, word32 len); +int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY); +int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, + const mp_int* privm, void* heap); + +#endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */ + #ifdef WOLFSSL_SP_NONBLOCK -int sp_ecc_sign_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap); -int sp_ecc_verify_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, - mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); -int sp_ecc_sign_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, - mp_int* rm, mp_int* sm, mp_int* km, void* heap); -int sp_ecc_verify_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, - mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, + WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, + const mp_int* pX, const mp_int* pY, const mp_int* pZ, const mp_int* r, + const mp_int* sm, int* res, void* heap); +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, + WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, + const mp_int* pX, const mp_int* pY, const mp_int* pZ, const mp_int* r, + const mp_int* sm, int* res, void* heap); #endif /* WOLFSSL_SP_NONBLOCK */ #endif /* WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index 562603e81..8e5164d05 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -1,6 +1,6 @@ /* sp_int.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -30,6 +30,7 @@ This library provides single precision (SP) integer math functions. #ifndef WOLFSSL_LINUXKM #include #endif +#include #ifdef __cplusplus extern "C" { @@ -112,29 +113,33 @@ extern "C" { #error "Size of unsigned long not detected" #endif -#if ULLONG_MAX == 18446744073709551615UL - #define SP_ULLONG_BITS 64 +#ifdef ULLONG_MAX + #if ULLONG_MAX == 18446744073709551615ULL + #define SP_ULLONG_BITS 64 - #if SP_ULLONG_BITS > SP_ULONG_BITS - typedef unsigned long long sp_uint64; - typedef long long sp_int64; - #endif -#elif ULLONG_MAX == 4294967295UL - #define SP_ULLONG_BITS 32 + #if SP_ULLONG_BITS > SP_ULONG_BITS + typedef unsigned long long sp_uint64; + typedef long long sp_int64; + #endif + #elif ULLONG_MAX == 4294967295UL + #define SP_ULLONG_BITS 32 - #if SP_ULLONG_BITS > SP_ULONG_BITS - typedef unsigned long long sp_uint32; - typedef long long sp_int32; - #endif -#elif ULLONG_MAX == 65535 - #define SP_ULLONG_BITS 16 + #if SP_ULLONG_BITS > SP_ULONG_BITS + typedef unsigned long long sp_uint32; + typedef long long sp_int32; + #endif + #elif ULLONG_MAX == 65535 + #define SP_ULLONG_BITS 16 - #if SP_ULLONG_BITS > SP_ULONG_BITS - typedef unsigned long long sp_uint16; - typedef long long sp_int16; + #if SP_ULLONG_BITS > SP_ULONG_BITS + typedef unsigned long long sp_uint16; + typedef long long sp_int16; + #endif + #else + #error "Size of unsigned long long not detected" #endif #else - #error "Size of unsigned long long not detected" + #define SP_ULLONG_BITS 0 #endif @@ -151,15 +156,20 @@ extern "C" { #endif -/* Detemine the number of bits to use in each word. */ +/* Determine the number of bits to use in each word. */ #ifdef SP_WORD_SIZE #elif defined(WOLFSSL_DSP_BUILD) #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_X86_64) && !defined(WOLFSSL_SP_X86_64_ASM) && \ + !defined(HAVE___UINT128_T) + #define SP_WORD_SIZE 32 #elif defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_X86_64) - #if SP_ULONG_BITS == 64 + #if SP_ULONG_BITS == 64 || SP_ULLONG_BITS == 64 #define SP_WORD_SIZE 64 #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif #elif SP_ULONG_BITS == 32 #define SP_WORD_SIZE 32 #undef WOLFSSL_SP_ASM @@ -250,8 +260,10 @@ extern "C" { #elif SP_WORD_SIZE == 64 typedef sp_uint64 sp_int_digit; typedef sp_int64 sp_sint_digit; +#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) typedef sp_uint128 sp_int_word; typedef sp_int128 sp_int_sword; +#endif #define SP_MASK 0xffffffffffffffffUL #else @@ -335,6 +347,9 @@ typedef struct sp_ecc_ctx { !defined(WOLFSSL_HAVE_SP_ECC) #if !defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA) #define SP_INT_DIGITS (((6144 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #elif defined(WOLFCRYPT_HAVE_SAKKE) + #define SP_INT_DIGITS \ + (((2 * (1024 + SP_WORD_SIZE) + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) #elif defined(HAVE_ECC) #define SP_INT_DIGITS \ (((2 * ( 521 + SP_WORD_SIZE) + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) @@ -344,7 +359,10 @@ typedef struct sp_ecc_ctx { #define SP_INT_DIGITS ((( 256 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) #endif #elif !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) - #ifdef WOLFSSL_SP_MATH_ALL + #if defined(WOLFCRYPT_HAVE_SAKKE) + #define SP_INT_DIGITS \ + (((2 * (1024 + SP_WORD_SIZE) + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) + #elif defined(WOLFSSL_SP_MATH_ALL) #define SP_INT_DIGITS \ (((2 * ( 521 + SP_WORD_SIZE) + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) #elif defined(WOLFSSL_SP_384) @@ -365,7 +383,8 @@ typedef struct sp_ecc_ctx { #define SP_INT_DIGITS (((3072 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) #endif #else - #if defined(WOLFSSL_HAVE_SP_DH) + #if defined(WOLFSSL_HAVE_SP_DH) || \ + (defined(WOLFSSL_HAVE_SP_RSA) && defined(WOLFSSL_KEY_GEN)) #define SP_INT_DIGITS (((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) #else #define SP_INT_DIGITS (((2048 + SP_WORD_SIZE) / SP_WORD_SIZE) + 1) @@ -492,7 +511,7 @@ typedef struct sp_ecc_ctx { #define sp_print_digit(a, s) #define sp_print_int(a, s) -#endif +#endif /* !NO_FILESYSTEM */ /* Returns whether multi-precision number is odd * @@ -655,9 +674,9 @@ typedef struct sp_ecc_ctx { #endif /** Radix is base 10 or decimal. */ -#define MP_RADIX_DEC 10 +#define MP_RADIX_DEC 10 /** Radix is base 16 or hexadecimal. */ -#define MP_RADIX_HEX 16 +#define MP_RADIX_HEX 16 /** Result of comparison is that the first number is greater than second. */ #define MP_GT 1 @@ -666,16 +685,21 @@ typedef struct sp_ecc_ctx { /** Result of comparison is that the first number is less than second. */ #define MP_LT -1 +/* ERROR VALUES */ /** Error value on success. */ -#define MP_OKAY 0 +#define MP_OKAY 0 /** Error value when dynamic memory allocation fails. */ -#define MP_MEM -2 +#define MP_MEM -2 /** Error value when value passed is not able to be used. */ -#define MP_VAL -3 +#define MP_VAL -3 /** Error value when non-blocking operation is returning after partial * completion. */ -#define FP_WOULDBLOCK -4 +#define FP_WOULDBLOCK -4 +/* Unused error. Defined for backward compatability. */ +#define MP_NOT_INF -5 +/* Unused error. Defined for backward compatability. */ +#define MP_RANGE MP_NOT_INF /* Number of bits in each word/digit. */ #define DIGIT_BIT SP_WORD_SIZE @@ -751,7 +775,7 @@ MP_API void sp_clear(sp_int* a); MP_API void sp_forcezero(sp_int* a); MP_API int sp_init_copy (sp_int* r, sp_int* a); -MP_API int sp_copy(sp_int* a, sp_int* r); +MP_API int sp_copy(const sp_int* a, sp_int* r); MP_API int sp_exch(sp_int* a, sp_int* b); MP_API int sp_cond_swap_ct(mp_int * a, mp_int * b, int c, int m); @@ -764,7 +788,7 @@ MP_API int sp_cmp_mag(sp_int* a, sp_int* b); MP_API int sp_cmp(sp_int* a, sp_int* b); MP_API int sp_is_bit_set(sp_int* a, unsigned int b); -MP_API int sp_count_bits(sp_int* a); +MP_API int sp_count_bits(const sp_int* a); #if defined(HAVE_ECC) && defined(HAVE_COMP_KEY) MP_API int sp_cnt_lsb(sp_int* a); #endif @@ -790,8 +814,12 @@ MP_API int sp_div_2(sp_int* a, sp_int* r); MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r); MP_API int sp_sub(sp_int* a, sp_int* b, sp_int* r); -#ifdef WOLFSSL_SP_MATH_ALL +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + (!defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_CUSTOM_CURVES)) || \ + defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) MP_API int sp_addmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r); +#endif +#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) MP_API int sp_submod(sp_int* a, sp_int* b, sp_int* m, sp_int* r); #endif #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) @@ -836,7 +864,7 @@ MP_API int sp_mont_red(sp_int* a, sp_int* m, sp_int_digit mp); MP_API int sp_mont_setup(sp_int* m, sp_int_digit* rho); MP_API int sp_mont_norm(sp_int* norm, sp_int* m); -MP_API int sp_unsigned_bin_size(sp_int* a); +MP_API int sp_unsigned_bin_size(const sp_int* a); MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz); MP_API int sp_to_unsigned_bin(sp_int* a, byte* out); MP_API int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz); @@ -951,8 +979,12 @@ WOLFSSL_API word32 CheckRunTimeFastMath(void); #define mp_gcd sp_gcd #define mp_lcm sp_lcm +#ifdef WOLFSSL_DEBUG_MATH +#define mp_dump(d, a, v) sp_print(a, d) #endif +#endif /* WOLFSSL_SP_MATH || WOLFSSL_SP_MATH_ALL */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 94f198dfb..fcf1f4a84 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -1,6 +1,6 @@ /* srp.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -246,7 +246,7 @@ WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size); * * The public ephemeral value is known as: * A at the client side. A = g ^ a % N - * B at the server side. B = (k * v + (g ˆ b % N)) % N + * B at the server side. B = (k * v + (g ^ b % N)) % N * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier. * * @param[in,out] srp the Srp structure. diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 5546b57bf..cc96e3ba1 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -1,6 +1,6 @@ /* tfm.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -70,6 +70,11 @@ #define TFM_X86_64 #endif #endif +#if defined(__aarch64__) && defined(__APPLE__) + #if !defined(TFM_AARCH_64) && !defined(TFM_NO_ASM) + #define TFM_AARCH_64 + #endif +#endif #if defined(TFM_X86_64) || defined(TFM_AARCH_64) #if !defined(FP_64BIT) #define FP_64BIT @@ -422,13 +427,16 @@ MP_API void fp_free(fp_int* a); /* zero/one/even/odd/neg/word ? */ #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) #define fp_isone(a) \ - ((((a)->used == 1) && ((a)->dp[0] == 1)) ? FP_YES : FP_NO) -#define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) -#define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) -#define fp_isneg(a) (((a)->sign != 0) ? FP_YES : FP_NO) -#define fp_isword(a, w) \ - ((((a)->used == 1) && ((a)->dp[0] == w)) || ((w == 0) && ((a)->used == 0)) \ + ((((a)->used == 1) && ((a)->dp[0] == 1) && ((a)->sign == FP_ZPOS)) \ ? FP_YES : FP_NO) +#define fp_iseven(a) \ + (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) +#define fp_isodd(a) \ + (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) +#define fp_isneg(a) (((a)->sign != FP_ZPOS) ? FP_YES : FP_NO) +#define fp_isword(a, w) \ + (((((a)->used == 1) && ((a)->dp[0] == w)) || \ + ((w == 0) && ((a)->used == 0))) ? FP_YES : FP_NO) /* set to a small digit */ void fp_set(fp_int *a, fp_digit b); @@ -440,7 +448,7 @@ int fp_is_bit_set(fp_int *a, fp_digit b); int fp_set_bit (fp_int * a, fp_digit b); /* copy from a to b */ -void fp_copy(fp_int *a, fp_int *b); +void fp_copy(const fp_int *a, fp_int *b); void fp_init_copy(fp_int *a, fp_int *b); /* clamp digits */ @@ -643,19 +651,15 @@ int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y); /*int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);*/ /* radix conversions */ -int fp_count_bits(fp_int *a); +int fp_count_bits(const fp_int *a); int fp_leading_bit(fp_int *a); -int fp_unsigned_bin_size(fp_int *a); +int fp_unsigned_bin_size(const fp_int *a); int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c); int fp_to_unsigned_bin(fp_int *a, unsigned char *b); int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c); int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b); -/*int fp_signed_bin_size(fp_int *a);*/ -/*void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c);*/ -/*void fp_to_signed_bin(fp_int *a, unsigned char *b);*/ - /*int fp_read_radix(fp_int *a, char *str, int radix);*/ /*int fp_toradix(fp_int *a, char *str, int radix);*/ /*int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);*/ @@ -771,17 +775,17 @@ MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); MP_API int mp_cmp(mp_int *a, mp_int *b); MP_API int mp_cmp_d(mp_int *a, mp_digit b); -MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_unsigned_bin_size(const mp_int * a); MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); MP_API int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c); MP_API int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); -MP_API int mp_copy(fp_int* a, fp_int* b); +MP_API int mp_copy(const fp_int* a, fp_int* b); MP_API int mp_isodd(mp_int* a); MP_API int mp_iszero(mp_int* a); -MP_API int mp_count_bits(mp_int *a); +MP_API int mp_count_bits(const mp_int *a); MP_API int mp_leading_bit(mp_int *a); MP_API int mp_set_int(mp_int *a, unsigned long b); MP_API int mp_is_bit_set (mp_int * a, mp_digit b); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index ef489f9e9..827a8bd60 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1,6 +1,6 @@ /* types.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -48,8 +48,14 @@ decouple library dependencies with standard string, memory and so on. * (with minimal depencencies). */ #if defined(HAVE_EX_DATA) || defined(FORTRESS) + #ifdef HAVE_EX_DATA_CLEANUP_HOOKS + typedef void (*wolfSSL_ex_data_cleanup_routine_t)(void *data); + #endif typedef struct WOLFSSL_CRYPTO_EX_DATA { void* ex_data[MAX_EX_DATA]; + #ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_ex_data_cleanup_routine_t ex_data_cleanup_routines[MAX_EX_DATA]; + #endif } WOLFSSL_CRYPTO_EX_DATA; #endif @@ -92,12 +98,16 @@ decouple library dependencies with standard string, memory and so on. /* try to set SIZEOF_LONG or SIZEOF_LONG_LONG if user didn't */ #if defined(_MSC_VER) || defined(HAVE_LIMITS_H) - #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) + /* make sure both SIZEOF_LONG_LONG and SIZEOF_LONG are set, + * otherwise causes issues with CTC_SETTINGS */ + #if !defined(SIZEOF_LONG_LONG) || !defined(SIZEOF_LONG) #include - #if defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL) + #if !defined(SIZEOF_LONG) && defined(ULONG_MAX) && \ + (ULONG_MAX == 0xffffffffUL) #define SIZEOF_LONG 4 #endif - #if defined(ULLONG_MAX) && (ULLONG_MAX == 0xffffffffffffffffULL) + #if !defined(SIZEOF_LONG_LONG) && defined(ULLONG_MAX) && \ + (ULLONG_MAX == 0xffffffffffffffffULL) #define SIZEOF_LONG_LONG 8 #endif #endif @@ -149,7 +159,7 @@ decouple library dependencies with standard string, memory and so on. #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ defined(__mips64) || defined(__x86_64__) || defined(_M_X64)) || \ defined(__aarch64__) || defined(__sparc64__) || defined(__s390x__ ) || \ - (defined(__riscv_xlen) && (__riscv_xlen == 64)) + (defined(__riscv_xlen) && (__riscv_xlen == 64)) || defined(_M_ARM64) typedef word64 wolfssl_word; #define WC_64BIT_CPU #elif (defined(sun) || defined(__sun)) && \ @@ -211,6 +221,8 @@ decouple library dependencies with standard string, memory and so on. #else #define WC_INLINE inline #endif + #elif defined(__CCRX__) + #define WC_INLINE inline #else #define WC_INLINE #endif @@ -236,6 +248,8 @@ decouple library dependencies with standard string, memory and so on. #elif defined(__MWERKS__) && TARGET_CPU_PPC #define PPC_INTRINSICS #define FAST_ROTATE + #elif defined(__CCRX__) + #define FAST_ROTATE #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) /* GCC does peephole optimizations which should result in using rotate instructions */ @@ -556,17 +570,17 @@ decouple library dependencies with standard string, memory and so on. { va_list ap; int ret; - + if ((int)n <= 0) return -1; - + va_start(ap, format); - - ret = vsnprintf(s, n, format, ap); + + ret = XVSNPRINTF(s, n, format, ap); if (ret < 0) ret = -1; - + va_end(ap); - + return ret; } #define XSNPRINTF _xsnprintf_ @@ -597,7 +611,7 @@ decouple library dependencies with standard string, memory and so on. if ((int)bufsize <= 0) return -1; va_start(ap, format); - ret = vsnprintf(buffer, bufsize, format, ap); + ret = XVSNPRINTF(buffer, bufsize, format, ap); if (ret >= (int)bufsize) ret = -1; va_end(ap); @@ -659,6 +673,8 @@ decouple library dependencies with standard string, memory and so on. #endif #ifdef OPENSSL_ALL #define XISALNUM(c) isalnum((c)) + #define XISASCII(c) isascii((c)) + #define XISSPACE(c) isspace((c)) #endif /* needed by wolfSSL_check_domain_name() */ #define XTOLOWER(c) tolower((c)) @@ -789,8 +805,9 @@ decouple library dependencies with standard string, memory and so on. WC_ALGO_TYPE_RNG = 4, WC_ALGO_TYPE_SEED = 5, WC_ALGO_TYPE_HMAC = 6, + WC_ALGO_TYPE_CMAC = 7, - WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_HMAC + WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_CMAC }; /* hash types */ @@ -872,8 +889,9 @@ decouple library dependencies with standard string, memory and so on. WC_PK_TYPE_EC_KEYGEN = 9, WC_PK_TYPE_RSA_CHECK_PRIV_KEY = 10, WC_PK_TYPE_EC_CHECK_PRIV_KEY = 11, - - WC_PK_TYPE_MAX = WC_PK_TYPE_EC_CHECK_PRIV_KEY + WC_PK_TYPE_ED448 = 12, + WC_PK_TYPE_CURVE448 = 13, + WC_PK_TYPE_MAX = WC_PK_TYPE_CURVE448 }; @@ -990,6 +1008,14 @@ decouple library dependencies with standard string, memory and so on. #endif #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */ + #if !defined(PEDANTIC_EXTENSION) + #if defined(__GNUC__) + #define PEDANTIC_EXTENSION __extension__ + #else + #define PEDANTIC_EXTENSION + #endif + #endif /* !PEDANTIC_EXTENSION */ + #ifndef TRUE #define TRUE 1 @@ -1036,6 +1062,14 @@ decouple library dependencies with standard string, memory and so on. #define WC_MP_TO_RADIX #endif + #if defined(__GNUC__) && __GNUC__ > 5 + #define PRAGMA_GCC_IGNORE(str) _Pragma(str); + #define PRAGMA_GCC_POP _Pragma("GCC diagnostic pop"); + #else + #define PRAGMA_GCC_IGNORE(str) + #define PRAGMA_GCC_POP + #endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/visibility.h b/wolfssl/wolfcrypt/visibility.h index 8ed57fb95..46a31a444 100644 --- a/wolfssl/wolfcrypt/visibility.h +++ b/wolfssl/wolfcrypt/visibility.h @@ -1,6 +1,6 @@ /* visibility.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -43,7 +43,8 @@ */ #if defined(BUILDING_WOLFSSL) - #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) || \ + defined(_WIN32_WCE) #if defined(WOLFSSL_DLL) #define WOLFSSL_API __declspec(dllexport) #else @@ -61,7 +62,8 @@ #define WOLFSSL_LOCAL #endif /* HAVE_VISIBILITY */ #else /* BUILDING_WOLFSSL */ - #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) || \ + defined(_WIN32_WCE) #if defined(WOLFSSL_DLL) #define WOLFSSL_API __declspec(dllimport) #else diff --git a/wolfssl/wolfcrypt/wc_encrypt.h b/wolfssl/wolfcrypt/wc_encrypt.h index 93a8e7c45..56d921507 100644 --- a/wolfssl/wolfcrypt/wc_encrypt.h +++ b/wolfssl/wolfcrypt/wc_encrypt.h @@ -1,6 +1,6 @@ /* wc_encrypt.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/wc_pkcs11.h b/wolfssl/wolfcrypt/wc_pkcs11.h index 39dd5e34c..9cc4f93f8 100644 --- a/wolfssl/wolfcrypt/wc_pkcs11.h +++ b/wolfssl/wolfcrypt/wc_pkcs11.h @@ -1,6 +1,6 @@ /* wc_pkcs11.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 1ce533e8a..d4d2c17ba 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -1,6 +1,6 @@ /* wc_port.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -522,8 +522,6 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #elif defined(WOLFSSL_DEOS) #define NO_FILESYSTEM #warning "TODO - DDC-I Certifiable Fast File System for Deos is not integrated" - /* #define XFILE bfd * */ - #elif defined(MICRIUM) #include #define XFILE FS_FILE* @@ -616,6 +614,22 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XSEEK_END 0 #define XBADFILE NULL #define XFGETS(b,s,f) f_gets((b), (s), (f)) +#elif defined (_WIN32_WCE) + /* stdio, WINCE case */ + #include + #define XFILE FILE* + #define XFOPEN fopen + #define XFDOPEN fdopen + #define XFSEEK fseek + #define XFTELL ftell + #define XREWIND(F) XFSEEK(F, 0, SEEK_SET) + #define XFREAD fread + #define XFWRITE fwrite + #define XFCLOSE fclose + #define XSEEK_END SEEK_END + #define XBADFILE NULL + #define XFGETS fgets + #define XVSNPRINTF _vsnprintf #elif defined(FUSION_RTOS) #include @@ -650,7 +664,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define strncasecmp FCL_STRNCASECMP /* FUSION SPECIFIC ERROR CODE */ - #define FUSION_IO_SEND_E 63 + #define FUSION_IO_SEND_E FCL_EWOULDBLOCK #elif defined(WOLFSSL_USER_FILESYSTEM) /* To be defined in user_settings.h */ @@ -676,14 +690,42 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFGETS fgets #define XFPRINTF fprintf - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ + #if !defined(NO_WOLFSSL_DIR)\ && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + #if defined(USE_WINDOWS_API) + #include + #define XSTAT _stat + #define XS_ISREG(s) (s & _S_IFREG) + #define SEPARATOR_CHAR ';' + + #elif defined(INTIME_RTOS) + #include + #define XSTAT _stat64 + #define XS_ISREG(s) S_ISREG(s) + #define SEPARATOR_CHAR ';' + #define XWRITE write + #define XREAD read + #define XCLOSE close + + #elif defined(WOLFSSL_ZEPHYR) + #define XSTAT fs_stat + #define XS_ISREG(s) (s == FS_DIR_ENTRY_FILE) + #define SEPARATOR_CHAR ':' + #elif defined(WOLFSSL_TELIT_M2MB) + #define XSTAT m2mb_fs_stat + #define XS_ISREG(s) (s & M2MB_S_IFREG) + #define SEPARATOR_CHAR ':' + #else #include #include #include #define XWRITE write #define XREAD read #define XCLOSE close + #define XSTAT stat + #define XS_ISREG(s) S_ISREG(s) + #define SEPARATOR_CHAR ':' + #endif #endif #endif @@ -719,6 +761,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #ifdef USE_WINDOWS_API WIN32_FIND_DATAA FindFileData; HANDLE hFind; + struct XSTAT s; #elif defined(WOLFSSL_ZEPHYR) struct fs_dirent entry; struct fs_dir_t dir; @@ -729,10 +772,17 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); M2MB_DIR_T* dir; struct M2MB_DIRENT* entry; struct M2MB_STAT s; + #elif defined(INTIME_RTOS) + struct stat64 s; + struct _find64 FindFileData; + #define IntimeFindFirst(name, data) (0 == _findfirst64(name, data)) + #define IntimeFindNext(data) (0 == _findnext64(data)) + #define IntimeFindClose(data) (0 == _findclose64(data)) + #define IntimeFilename(ctx) ctx->FindFileData.f_filename #else struct dirent* entry; DIR* dir; - struct stat s; + struct XSTAT s; #endif char name[MAX_FILENAME_SZ]; } ReadDirCtx; @@ -743,6 +793,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name); WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx); #endif /* !NO_WOLFSSL_DIR */ + #define WC_ISFILEEXIST_NOFILE -1 + + WOLFSSL_API int wc_FileExists(const char* fname); #endif /* !NO_FILESYSTEM */ @@ -758,6 +811,10 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #endif /* max */ #endif /* USE_WINDOWS_API */ +#ifdef __QNXNTO__ + #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX +#endif /* TIME SECTION */ /* Time functions */ @@ -804,10 +861,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XGMTIME(c, t) rtpsys_gmtime((c)) #elif defined(WOLFSSL_DEOS) - #define XTIME(t1) deos_time((t1)) - #define WOLFSSL_GMTIME - #define USE_WOLF_TM - #define USE_WOLF_TIME_T + #include #elif defined(MICRIUM) #include @@ -859,9 +913,32 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #elif defined(_WIN32_WCE) #include + #include /* For file system */ + + time_t windows_time(time_t* timer); + + #define FindNextFileA(h, d) FindNextFile(h, (LPWIN32_FIND_DATAW) d) + #define FindFirstFileA(fn, d) FindFirstFile((LPCWSTR) fn, \ + (LPWIN32_FIND_DATAW) d) #define XTIME(t1) windows_time((t1)) #define WOLFSSL_GMTIME + /* if struct tm is not defined in WINCE SDK */ + #ifndef _TM_DEFINED + struct tm { + int tm_sec; /* seconds */ + int tm_min; /* minutes */ + int tm_hour; /* hours */ + int tm_mday; /* day of month (month specific) */ + int tm_mon; /* month */ + int tm_year; /* year */ + int tm_wday; /* day of week (out of 1-7)*/ + int tm_yday; /* day of year (out of 365) */ + int tm_isdst; /* is it daylight savings */ + }; + #define _TM_DEFINED + #endif + #elif defined(WOLFSSL_APACHE_MYNEWT) #include "os/os_time.h" #define XTIME(t1) mynewt_time((t1)) diff --git a/wolfssl/wolfcrypt/wolfevent.h b/wolfssl/wolfcrypt/wolfevent.h index 8370d5e45..639f548a1 100644 --- a/wolfssl/wolfcrypt/wolfevent.h +++ b/wolfssl/wolfcrypt/wolfevent.h @@ -1,6 +1,6 @@ /* wolfevent.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/wolfmath.h b/wolfssl/wolfcrypt/wolfmath.h index 3d9830a15..20ca975fe 100644 --- a/wolfssl/wolfcrypt/wolfmath.h +++ b/wolfssl/wolfcrypt/wolfmath.h @@ -1,6 +1,6 @@ /* wolfmath.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -55,18 +55,18 @@ This library provides big integer math functions. /* common math functions */ -MP_API int get_digit_count(mp_int* a); -MP_API mp_digit get_digit(mp_int* a, int n); +MP_API int get_digit_count(const mp_int* a); +MP_API mp_digit get_digit(const mp_int* a, int n); MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d); WOLFSSL_API int mp_cond_copy(mp_int* a, int copy, mp_int* b); WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng); -enum { - /* format type */ - WC_TYPE_HEX_STR = 1, - WC_TYPE_UNSIGNED_BIN = 2, -}; +#define WC_TYPE_HEX_STR 1 +#define WC_TYPE_UNSIGNED_BIN 2 +#if defined(WOLFSSL_QNX_CAAM) + #define WC_TYPE_BLACK_KEY 3 +#endif WOLFSSL_API int wc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz, int encType); diff --git a/wolfssl/wolfio.h b/wolfssl/wolfio.h index 77fcf83ff..aea6f8c75 100644 --- a/wolfssl/wolfio.h +++ b/wolfssl/wolfio.h @@ -1,6 +1,6 @@ /* io.h * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -248,13 +248,17 @@ #define SOCKET_ECONNREFUSED NU_CONNECTION_REFUSED #define SOCKET_ECONNABORTED NU_NOT_CONNECTED #elif defined(WOLFSSL_DEOS) - #define SOCKET_EWOULDBLOCK EAGAIN - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET EINTR - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED SOCKET_ERROR - #define SOCKET_ECONNABORTED SOCKET_ERROR + /* `sockaddr_storage` is not defined in DEOS. This workaround will + * work for IPV4, but not IPV6 + */ + #define sockaddr_storage sockaddr_in + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET EINTR + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED SOCKET_ERROR + #define SOCKET_ECONNABORTED SOCKET_ERROR #elif defined(HAVE_NETX) #define SOCKET_EWOULDBLOCK NX_NOT_CONNECTED #define SOCKET_EAGAIN NX_NOT_CONNECTED @@ -283,8 +287,7 @@ #ifdef DEVKITPRO /* from network.h */ - int net_send(int, const void*, int, unsigned int); - int net_recv(int, void*, int, unsigned int); + #include #define SEND_FUNCTION net_send #define RECV_FUNCTION net_recv #elif defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT) diff --git a/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs b/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs index 269603045..8e94c4ea5 100644 --- a/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs +++ b/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs @@ -1,6 +1,6 @@ /* wolfSSL-DTLS-PSK-Server.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + using System; diff --git a/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs b/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs index c7cdd43a7..1116ba874 100644 --- a/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs +++ b/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs @@ -1,6 +1,6 @@ /* wolfSSL-DTLS-Server.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + using System; using System.Runtime.InteropServices; diff --git a/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs b/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs index 8f0e0e27f..aaeb31a72 100644 --- a/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs +++ b/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs @@ -1,6 +1,6 @@ /* wolfSSL-Example-IOCallbacks.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + using System; diff --git a/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs b/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs index dcba3568e..dccdc4d3f 100644 --- a/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs +++ b/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs @@ -1,6 +1,6 @@ /* wolfSSL-TLS-Client.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs b/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs index e8697062a..ff6ce7316 100644 --- a/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs +++ b/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs @@ -1,6 +1,6 @@ /* wolfSSL-TLS-PSK-Server.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + using System; diff --git a/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs b/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs index 262bd74be..487f7815e 100644 --- a/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs +++ b/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs @@ -1,6 +1,6 @@ /* wolfSSL-TLS-Server.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + using System; diff --git a/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs b/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs index 2f9da4e24..a7540508a 100644 --- a/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs +++ b/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs @@ -1,6 +1,6 @@ /* wolfSSL-TLS-ServerThreaded.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. + * Copyright (C) 2006-2021 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs index 9947d9b9d..a2019cadb 100644 --- a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs @@ -1,23 +1,23 @@ /* wolfSSL.cs * - * Copyright (C) 2006-2020 wolfSSL Inc. - * - * This file is part of wolfSSL. - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - */ + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ using System; using System.Runtime.InteropServices; diff --git a/wrapper/python/wolfcrypt/setup.py b/wrapper/python/wolfcrypt/setup.py index c22149a58..b16e02366 100755 --- a/wrapper/python/wolfcrypt/setup.py +++ b/wrapper/python/wolfcrypt/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -19,6 +19,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # Python 2.7 Standard Library from __future__ import absolute_import diff --git a/wrapper/python/wolfcrypt/test/test_ciphers.py b/wrapper/python/wolfcrypt/test/test_ciphers.py index 24ccb897b..bab8820d6 100644 --- a/wrapper/python/wolfcrypt/test/test_ciphers.py +++ b/wrapper/python/wolfcrypt/test/test_ciphers.py @@ -1,6 +1,6 @@ # test_ciphers.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ import unittest from wolfcrypt.ciphers import * from wolfcrypt.utils import t2b, h2b diff --git a/wrapper/python/wolfcrypt/test/test_hashes.py b/wrapper/python/wolfcrypt/test/test_hashes.py index b9f2ccc20..e926f1b30 100644 --- a/wrapper/python/wolfcrypt/test/test_hashes.py +++ b/wrapper/python/wolfcrypt/test/test_hashes.py @@ -1,6 +1,6 @@ # test_hashes.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ import unittest from wolfcrypt.hashes import * from wolfcrypt.utils import t2b, h2b diff --git a/wrapper/python/wolfcrypt/test/test_random.py b/wrapper/python/wolfcrypt/test/test_random.py index 1425f370c..964ffb5c3 100644 --- a/wrapper/python/wolfcrypt/test/test_random.py +++ b/wrapper/python/wolfcrypt/test/test_random.py @@ -1,6 +1,6 @@ # test_random.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ import unittest from wolfcrypt.random import * diff --git a/wrapper/python/wolfcrypt/wolfcrypt/__about__.py b/wrapper/python/wolfcrypt/wolfcrypt/__about__.py index d3c58086d..d591779da 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/__about__.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/__about__.py @@ -1,6 +1,6 @@ # __about__.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ metadata = dict( __name__ = "wolfcrypt", diff --git a/wrapper/python/wolfcrypt/wolfcrypt/__init__.py b/wrapper/python/wolfcrypt/wolfcrypt/__init__.py index 31d0235ef..33f5045fc 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/__init__.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/__init__.py @@ -1,6 +1,6 @@ # __init__.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,5 +18,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ from .__about__ import * diff --git a/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py b/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py index ac03955cc..4787c07e1 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py @@ -1,6 +1,6 @@ # build_ffi.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ import os from cffi import FFI diff --git a/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py b/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py index c02cdbe33..187d44c7d 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py @@ -1,6 +1,6 @@ # ciphers.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ from wolfcrypt._ffi import ffi as _ffi from wolfcrypt._ffi import lib as _lib from wolfcrypt.utils import t2b diff --git a/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py b/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py index 26322b364..e1857c9cb 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py @@ -1,6 +1,6 @@ # exceptions.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ class WolfCryptError(Exception): diff --git a/wrapper/python/wolfcrypt/wolfcrypt/hashes.py b/wrapper/python/wolfcrypt/wolfcrypt/hashes.py index 346cb7bc0..217f0eac5 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/hashes.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/hashes.py @@ -1,6 +1,6 @@ # hashes.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ from wolfcrypt._ffi import ffi as _ffi from wolfcrypt._ffi import lib as _lib from wolfcrypt.utils import t2b, b2h diff --git a/wrapper/python/wolfcrypt/wolfcrypt/random.py b/wrapper/python/wolfcrypt/wolfcrypt/random.py index f32b9b77c..fd6148929 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/random.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/random.py @@ -1,6 +1,6 @@ # random.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ from wolfcrypt._ffi import ffi as _ffi from wolfcrypt._ffi import lib as _lib from wolfcrypt.utils import t2b diff --git a/wrapper/python/wolfcrypt/wolfcrypt/utils.py b/wrapper/python/wolfcrypt/wolfcrypt/utils.py index 537800f4c..22abab1a2 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/utils.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/utils.py @@ -1,6 +1,6 @@ # utils.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=unused-import, undefined-variable diff --git a/wrapper/python/wolfssl/Makefile b/wrapper/python/wolfssl/Makefile index 5b3f9f869..ce5f691c1 100644 --- a/wrapper/python/wolfssl/Makefile +++ b/wrapper/python/wolfssl/Makefile @@ -1,6 +1,6 @@ # Makefile # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ .PHONY : all clean clean-test clean-build clean-pyc install test check upload diff --git a/wrapper/python/wolfssl/docs/Makefile b/wrapper/python/wolfssl/docs/Makefile index 7d24fb014..2a71ed6e6 100644 --- a/wrapper/python/wolfssl/docs/Makefile +++ b/wrapper/python/wolfssl/docs/Makefile @@ -1,6 +1,6 @@ # Makefile # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ .PHONY : all clean html pdf man diff --git a/wrapper/python/wolfssl/examples/client.py b/wrapper/python/wolfssl/examples/client.py index 0ae7d57ce..68dea10d6 100755 --- a/wrapper/python/wolfssl/examples/client.py +++ b/wrapper/python/wolfssl/examples/client.py @@ -4,7 +4,7 @@ # # client.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -22,6 +22,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, invalid-name, import-error diff --git a/wrapper/python/wolfssl/examples/server.py b/wrapper/python/wolfssl/examples/server.py index a44b7e116..9e0fdf79e 100755 --- a/wrapper/python/wolfssl/examples/server.py +++ b/wrapper/python/wolfssl/examples/server.py @@ -4,7 +4,7 @@ # # server.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -22,6 +22,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, invalid-name, import-error diff --git a/wrapper/python/wolfssl/setup.py b/wrapper/python/wolfssl/setup.py index 217b59700..1eba44b63 100755 --- a/wrapper/python/wolfssl/setup.py +++ b/wrapper/python/wolfssl/setup.py @@ -3,7 +3,7 @@ # # setup.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -21,6 +21,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # Python 2.7 Standard Library diff --git a/wrapper/python/wolfssl/src/wolfssl/__about__.py b/wrapper/python/wolfssl/src/wolfssl/__about__.py index 35b983ab7..b4b69d808 100644 --- a/wrapper/python/wolfssl/src/wolfssl/__about__.py +++ b/wrapper/python/wolfssl/src/wolfssl/__about__.py @@ -2,7 +2,7 @@ # # __about__.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring diff --git a/wrapper/python/wolfssl/src/wolfssl/__init__.py b/wrapper/python/wolfssl/src/wolfssl/__init__.py index decef9595..e66d6cd73 100644 --- a/wrapper/python/wolfssl/src/wolfssl/__init__.py +++ b/wrapper/python/wolfssl/src/wolfssl/__init__.py @@ -2,7 +2,7 @@ # # __init__.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ import sys import errno diff --git a/wrapper/python/wolfssl/src/wolfssl/_memory.py b/wrapper/python/wolfssl/src/wolfssl/_memory.py index 0b6bb9f82..f3af7b8b7 100644 --- a/wrapper/python/wolfssl/src/wolfssl/_memory.py +++ b/wrapper/python/wolfssl/src/wolfssl/_memory.py @@ -2,7 +2,7 @@ # # _memory.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring diff --git a/wrapper/python/wolfssl/src/wolfssl/_methods.py b/wrapper/python/wolfssl/src/wolfssl/_methods.py index bde5eb1bf..a119939aa 100644 --- a/wrapper/python/wolfssl/src/wolfssl/_methods.py +++ b/wrapper/python/wolfssl/src/wolfssl/_methods.py @@ -2,7 +2,7 @@ # # _methods.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, invalid-name diff --git a/wrapper/python/wolfssl/src/wolfssl/build_ffi.py b/wrapper/python/wolfssl/src/wolfssl/build_ffi.py index acfe013da..eac1b2709 100644 --- a/wrapper/python/wolfssl/src/wolfssl/build_ffi.py +++ b/wrapper/python/wolfssl/src/wolfssl/build_ffi.py @@ -2,7 +2,7 @@ # # build_ffi.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, invalid-name diff --git a/wrapper/python/wolfssl/src/wolfssl/exceptions.py b/wrapper/python/wolfssl/src/wolfssl/exceptions.py index 748732254..f031e86a5 100644 --- a/wrapper/python/wolfssl/src/wolfssl/exceptions.py +++ b/wrapper/python/wolfssl/src/wolfssl/exceptions.py @@ -2,7 +2,7 @@ # # exceptions.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring diff --git a/wrapper/python/wolfssl/src/wolfssl/utils.py b/wrapper/python/wolfssl/src/wolfssl/utils.py index 721f2b96f..d7c2e9642 100644 --- a/wrapper/python/wolfssl/src/wolfssl/utils.py +++ b/wrapper/python/wolfssl/src/wolfssl/utils.py @@ -2,7 +2,7 @@ # # utils.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, unused-import, undefined-variable diff --git a/wrapper/python/wolfssl/test/conftest.py b/wrapper/python/wolfssl/test/conftest.py index d87164325..84fcb88d2 100644 --- a/wrapper/python/wolfssl/test/conftest.py +++ b/wrapper/python/wolfssl/test/conftest.py @@ -2,7 +2,7 @@ # # conftest.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, redefined-outer-name diff --git a/wrapper/python/wolfssl/test/test_client.py b/wrapper/python/wolfssl/test/test_client.py index 7ebf91fee..e67fbe691 100644 --- a/wrapper/python/wolfssl/test/test_client.py +++ b/wrapper/python/wolfssl/test/test_client.py @@ -2,7 +2,7 @@ # # test_client.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, invalid-name, import-error # pylint: disable=redefined-outer-name diff --git a/wrapper/python/wolfssl/test/test_context.py b/wrapper/python/wolfssl/test/test_context.py index 6575ed6da..0769419bd 100644 --- a/wrapper/python/wolfssl/test/test_context.py +++ b/wrapper/python/wolfssl/test/test_context.py @@ -2,7 +2,7 @@ # # test_context.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, invalid-name, import-error # pylint: disable=redefined-outer-name diff --git a/wrapper/python/wolfssl/test/test_methods.py b/wrapper/python/wolfssl/test/test_methods.py index f94038341..339b12841 100644 --- a/wrapper/python/wolfssl/test/test_methods.py +++ b/wrapper/python/wolfssl/test/test_methods.py @@ -2,7 +2,7 @@ # # test_methods.py # -# Copyright (C) 2006-2020 wolfSSL Inc. +# Copyright (C) 2006-2021 wolfSSL Inc. # # This file is part of wolfSSL. # @@ -20,6 +20,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA #/ +#/ # pylint: disable=missing-docstring, redefined-outer-name, import-error